diff options
Diffstat (limited to 'qemu/roms/openbios/arch/ppc/mol')
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/console.c | 30 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/init.c | 119 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/kernel.c | 16 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/main.c | 370 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/methods.c | 470 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/mol.c | 165 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/mol.fs | 107 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/mol.h | 44 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/osi-blk.c | 119 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/osi-scsi.c | 271 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/prom.c | 175 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/prom.h | 47 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/pseudodisk.c | 178 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/tree.c | 165 | ||||
-rw-r--r-- | qemu/roms/openbios/arch/ppc/mol/tree.fs | 103 |
15 files changed, 2379 insertions, 0 deletions
diff --git a/qemu/roms/openbios/arch/ppc/mol/console.c b/qemu/roms/openbios/arch/ppc/mol/console.c new file mode 100644 index 000000000..966011e19 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/console.c @@ -0,0 +1,30 @@ +/* + * Creation Date: <2002/10/29 18:59:05 samuel> + * Time-stamp: <2003/12/28 22:51:11 samuel> + * + * <console.c> + * + * Simple text console + * + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/diskio.h" +#include "osi_calls.h" +#include "libopenbios/ofmem.h" +#include "mol/mol.h" +#include "boothelper_sh.h" +#include "video_sh.h" + +#define openbios_GetFBInfo(x) OSI_GetFBInfo(x) + +#include "../../../packages/video.c" +#include "../../../libopenbios/console_common.c" diff --git a/qemu/roms/openbios/arch/ppc/mol/init.c b/qemu/roms/openbios/arch/ppc/mol/init.c new file mode 100644 index 000000000..15333b4e1 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/init.c @@ -0,0 +1,119 @@ +/* + * Creation Date: <1999/11/16 00:49:26 samuel> + * Time-stamp: <2004/04/12 16:26:50 samuel> + * + * <init.c> + * + * Initialization + * + * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh + # (samuel@ibrium.se, dary@lindesign.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation + * + */ + +#include "config.h" +#include "libopenbios/openbios.h" +#include "libopenbios/bindings.h" +#include "arch/common/nvram.h" +#include "mol/mol.h" +#include "libopenbios/ofmem.h" +#include "mol/prom.h" +#include "openbios-version.h" +#include "osi_calls.h" +#include "boothelper_sh.h" + +extern void unexpected_excep( int vector ); + +int +get_bool_res( const char *res ) +{ + char buf[8], *p; + + p = BootHGetStrRes( res, buf, sizeof(buf) ); + if( !p ) + return -1; + if( !strcasecmp(p,"true") || !strcasecmp(p,"yes") || !strcasecmp(p,"1") ) + return 1; + return 0; +} + +void +unexpected_excep( int vector ) +{ + printk("MOL panic: Unexpected exception %x\n", vector ); + for( ;; ) + ; +} + +unsigned long isa_io_base; + +void +entry( void ) +{ + isa_io_base = 0x80000000; + + printk("\n"); + printk("=============================================================\n"); + printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n", + OPENBIOS_BUILD_DATE); + + ofmem_init(); + initialize_forth(); + /* won't return */ + + printk("of_startup returned!\n"); + for( ;; ) + ; +} + +static void +setenv( char *env, char *value ) +{ + push_str( value ); + push_str( env ); + fword("$setenv"); +} + +void +arch_of_init( void ) +{ + mol_phandle_t ph; + int autoboot; + + devtree_init(); + node_methods_init(); + nvram_init("/pci/mac-io/nvram"); + openbios_init(); + modules_init(); + pseudodisk_init(); + osiblk_init(); + osiscsi_init(); + init_video(); + + if( (ph=prom_find_device("/rtas")) == -1 ) + printk("Warning: No /rtas node\n"); + else { + unsigned long size = 0x1000; + while( size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start ) + size *= 2; + prom_set_prop( ph, "rtas-size", (char*)&size, sizeof(size) ); + } + + /* tweak boot settings */ + autoboot = !!get_bool_res("autoboot"); + if( !autoboot ) + printk("Autobooting disabled - dropping into OpenFirmware\n"); + setenv("auto-boot?", autoboot ? "true" : "false" ); + setenv("boot-command", "molboot"); + + if( get_bool_res("tty-interface") == 1 ) + fword("activate-tty-interface"); + + /* hack */ + device_end(); + bind_func("molboot", boot ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/kernel.c b/qemu/roms/openbios/arch/ppc/mol/kernel.c new file mode 100644 index 000000000..1454b8a85 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/kernel.c @@ -0,0 +1,16 @@ +/* + * Creation Date: <2004/08/28 18:03:25 stepan> + * Time-stamp: <2004/08/28 18:03:25 stepan> + * + * <mol/kernel.c> + * + * Copyright (C) 2004 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "mol-dict.h" +#include "../kernel.c" diff --git a/qemu/roms/openbios/arch/ppc/mol/main.c b/qemu/roms/openbios/arch/ppc/mol/main.c new file mode 100644 index 000000000..f6ed934d0 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/main.c @@ -0,0 +1,370 @@ +/* + * Creation Date: <2002/10/02 22:24:24 samuel> + * Time-stamp: <2004/03/27 01:57:55 samuel> + * + * <main.c> + * + * + * + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation + * + */ + + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/elfload.h" +#include "arch/common/nvram.h" +#include "libc/diskio.h" +#include "libc/vsprintf.h" +#include "mol/mol.h" +#include "libopenbios/ofmem.h" +#include "osi_calls.h" +#include "ablk_sh.h" +#include "boothelper_sh.h" + + +static void patch_newworld_rom( char *start, size_t size ); +static void newworld_timer_hack( char *start, size_t size ); + +static void +transfer_control_to_elf( unsigned long entry ) +{ + extern void call_elf( unsigned long entry ); + printk("Starting ELF boot loader\n"); + call_elf( entry ); + + fatal_error("call_elf returned unexpectedly\n"); +} + +static int +load_elf_rom( unsigned long *entry, int fd ) +{ + int i, lszz_offs, elf_offs; + char buf[128], *addr; + Elf_ehdr ehdr; + Elf_phdr *phdr; + size_t s; + + printk("Loading '%s' from '%s'\n", get_file_path(fd), + get_volume_name(fd) ); + + /* the ELF-image (usually) starts at offset 0x4000 */ + if( (elf_offs=find_elf(fd)) < 0 ) { + printk("----> %s is not an ELF image\n", buf ); + exit(1); + } + if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) ) + fatal_error("elf_readhdrs failed\n"); + + *entry = ehdr.e_entry; + + /* load segments. Compressed ROM-image assumed to be located immediately + * after the last segment */ + lszz_offs = elf_offs; + for( i=0; i<ehdr.e_phnum; i++ ) { + /* p_memsz, p_flags */ + s = MIN( phdr[i].p_filesz, phdr[i].p_memsz ); + seek_io( fd, elf_offs + phdr[i].p_offset ); + + /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n", + phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset, + phdr[i].p_vaddr ); */ + + if( phdr[i].p_vaddr != phdr[i].p_paddr ) + printk("WARNING: ELF segment virtual addr != physical addr\n"); + lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz ); + if( !s ) + continue; + if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 ) + fatal_error("Claim failed!\n"); + + addr = (char*)phdr[i].p_vaddr; + if( read_io(fd, addr, s) != s ) + fatal_error("read failed\n"); + + /* patch CODE segment */ + if( *entry >= phdr[i].p_vaddr && *entry < phdr[i].p_vaddr + s ) { + patch_newworld_rom( (char*)phdr[i].p_vaddr, s ); + newworld_timer_hack( (char*)phdr[i].p_vaddr, s ); + } + flush_icache_range( addr, addr+s ); + + /* printk("ELF ROM-section loaded at %08lX (size %08lX)\n", + (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/ + } + free( phdr ); + return lszz_offs; +} + + +/************************************************************************/ +/* newworld ROM loading */ +/************************************************************************/ + +#define ROM_BASE 0x1100000 /* where we decide to put things */ + +/* fix bug present in the 2.4 and the 3.0 Apple ROM */ +static void +patch_newworld_rom( char *start, size_t size ) +{ + int s; + unsigned long mark[] = { 0x7c7d1b78, /* mr r29,r3 */ + 0x7c9c2378, /* mr r28,r4 */ + 0x7cc33378, /* mr r3,r6 */ + 0x7c864214, /* add r4,r6,r8 <------ BUG -- */ + 0x80b10000, /* lwz r5,0(r17) */ + 0x38a500e8 }; /* addi r5,r5,232 */ + + /* Correcting add r4,r6,r8 ----> addi r4,r6,8 */ + for( s=0; s<size-sizeof(mark); s+=4 ) + if( memcmp( start+s, mark, sizeof(mark)) == 0 ) { + printk("FIXING ROM BUG @ %X!\n", s+12); + ((unsigned long*)(start+s))[3] = 0x38860008; /* addi r4,r6,8 */ + } +} + +/* This hack is only needed on machines with a timebase slower than 12.5 MHz + * (50 MHz bus frequency). Typically only old, accelerated machines fall + * into this category. The cause of the problem is an overflow in Apple's + * calibration routine. + */ +static void +newworld_timer_hack( char *start, size_t size ) +{ + int s; + unsigned long mark[] = { 0x7d0000a6, 0x5507045e, 0x7ce00124, 0x4c00012c, + 0x38e00000, 0x3c80000f, 0x6084ffff, 0x98830c00, + 0x7c0006ac, 0x98830a00, 0x7c0006ac, 0x7c9603a6, + 0x4c00012c, 0x7cb602a6, 0x2c050000, 0x4181fff8, + 0x7c0004ac, 0x88830a00, 0x7c0006ac, 0x88a30800, + 0x7c0006ac, 0x88c30a00, 0x7c0006ac, 0x7c043040, + 0x40a2ffe4, 0x5085442e, 0x7ca500d0, 0x54a5043e, + 0x7c053840, 0x7ca72b78, 0x4082ff9c, 0x7ca32b78, + 0x7d000124, 0x4c00012c, 0x4e800020 + }; + + /* return #via ticks corresponding to 0xfffff DEC ticks (VIA frequency == 47/60 MHz) */ + for( s=0; s < size-sizeof(mark); s+=4 ) { + if( !memcmp( start+s, mark, sizeof(mark)) ) { + extern char timer_calib_start[], timer_calib_end[]; + extern unsigned long nw_dec_calibration; + int hz = OSI_UsecsToMticks(1000); + nw_dec_calibration = OSI_MticksToUsecs(0xfffff*47)/60; + memcpy( start + s, timer_calib_start, timer_calib_end - timer_calib_start ); + + printk("Timer calibration fix: %d.%02d MHz [%ld]\n", + hz/1000, (hz/10)%100, nw_dec_calibration ); + break; + } + } +} + +static unsigned long +load_newworld_rom( int fd ) +{ + int lszz_offs, lszz_size; + unsigned long entry, data[2]; + phandle_t ph; + + lszz_offs = load_elf_rom( &entry, fd ); + seek_io( fd, -1 ); + lszz_size = tell(fd) - lszz_offs; + seek_io( fd, lszz_offs ); + + /* printk("Compressed ROM image: offset %08X, size %08X loaded at %08x\n", + lszz_offs, lszz_size, ROM_BASE ); */ + + if( ofmem_claim(ROM_BASE, lszz_size, 0) == -1 ) + fatal_error("Claim failure (lszz)!\n"); + + read_io( fd, (char*)ROM_BASE, lszz_size ); + + /* Fix the /rom/macos/AAPL,toolbox-image,lzss property (phys, size) */ +#if 0 + if( (ph=prom_create_node("/rom/macos/")) == -1 ) + fatal_error("Failed creating /rom/macos/"); +#else + ph = find_dev("/rom/macos"); +#endif + data[0] = ROM_BASE; + data[1] = lszz_size; + set_property( ph, "AAPL,toolbox-image,lzss", (char*)data, sizeof(data) ); + + /* The 7.8 rom (MacOS 9.2) uses AAPL,toolbox-parcels instead of + * AAPL,toolbox-image,lzss. It probably doesn't hurt to have it + * always present (we don't have an easy way to determine ROM version...) + */ + set_property( ph, "AAPL,toolbox-parcels", (char*)data, sizeof(data) ); + return entry; +} + +static int +search_nwrom( int fd, int fast ) +{ + char *s, buf[128]; + int found = 0; + + if( fast ) { + int ind; + found = !reopen( fd, "\\\\:tbxi" ); + for( ind=0; !found && (s=BootHGetStrResInd("macos_rompath", buf, sizeof(buf), ind++, 0)) ; ) + found = !reopen( fd, s ); + for( ind=0; !found && (s=BootHGetStrResInd("macos_rompath_", buf, sizeof(buf), ind++, 0)) ; ) + found = !reopen( fd, s ); + } else { + printk("Searching %s for a 'Mac OS ROM' file\n", get_volume_name(fd) ); + if( !(found=reopen_nwrom(fd)) ) { + printk(" \n**** HINT ***************************************************\n"); + printk("* The booting can be speeded up by adding the line\n"); + printk("* macos_rompath: '%s'\n", get_file_path(fd) ); + printk("* to the /etc/mol/molrc.macos (recommended).\n"); + printk("*************************************************************\n \n"); + } + } + return found; +} + +static void +encode_bootpath( const char *spec, const char *args ) +{ + phandle_t chosen_ph = find_dev("/chosen"); + set_property( chosen_ph, "bootpath", spec, strlen(spec)+1 ); + set_property( chosen_ph, "bootargs", args, strlen(args)+1 ); +} + +static char * +newworld_load( const char *node_path, const char *spec, int do_search ) +{ + char *p, *entry, buf[80]; + int fd, len; + + if( (fd=open_io(spec)) == -1 ) + return NULL; + + if( !search_nwrom(fd, do_search) ) { + close_io(fd); + return NULL; + } + printk("Boot Disk: %s [%s]\n", spec, get_fstype(fd) ); + + entry = (char*)load_newworld_rom( fd ); + +#if 1 + PUSH_ih( get_ih_from_fd(fd) ); + fword("get-instance-path"); + len = POP(); + p = (char*)POP(); + buf[0] = 0; + if( len < sizeof(buf) ) { + memcpy( buf, p, len ); + buf[len] =0; + } + strcat( buf, "/x@:" ); + printk("boot_path: %s\n", buf ); + encode_bootpath( buf, "" ); +#endif + close_io( fd ); + return entry; +} + +static void +newworld_startup( void ) +{ + int i, j, bootunit, type, fd; + ablk_disk_info_t info; + char *entry = NULL; + char spec[80]; + phandle_t ph; + + char path[]="/pci/pci-bridge/mol-blk"; + if( !(ph=find_dev(path)) ) + fatal_error("MOLBlockDriver node not found\n"); + + /* user-specified newworld ROMs take precedence */ + if( (fd=open_io("pseudo:,nwrom")) >= 0 ) { + entry = (char*)load_newworld_rom( fd ); + close_io( fd ); + } + + /* determine boot volume */ + for( bootunit=-1, type=0; bootunit==-1 && type<3 ; type++ ) { + for( i=0; !OSI_ABlkDiskInfo(0, i, &info) ; i++ ) { + if( type<=1 && !(info.flags & ABLK_BOOT_HINT) ) + continue; + if( type>1 && (info.flags & ABLK_BOOT_HINT) ) + continue; + + for( j=0; !entry && j<32; j++ ) { + snprintf( spec, sizeof(spec), "%s/disk@%x:%d", + path, i, j ); + entry = newworld_load( path, spec, (!type || type==2) ); + } + if( entry ) { + bootunit = i; + break; + } + } + } + + if( entry ) { + OSI_ABlkBlessDisk( 0 /*channel*/, bootunit ); + + update_nvram(); + transfer_control_to_elf( (unsigned long)entry ); + /* won't come here */ + return; + } + + printk("\n--- No bootable disk was found! -----------------------------\n"); + printk("If this is an oldworld machine, try booting from the MacOS\n"); + printk("install CD and install MacOS from within MOL.\n"); + printk("-------------------------------------------------------------\n"); + exit(1); +} + + +/************************************************************************/ +/* yaboot booting */ +/************************************************************************/ + +static void +yaboot_startup( void ) +{ + const char *paths[] = { "pseudo:,ofclient", "pseudo:,yaboot", NULL }; + unsigned long entry; + int i, fd; + + for( i=0; paths[i]; i++ ) { + if( (fd=open_io(paths[i])) == -1 ) + continue; + (void) load_elf_rom( &entry, fd ); + close_io( fd ); + encode_bootpath( paths[i], "" ); + + update_nvram(); + transfer_control_to_elf( entry ); + /* won't come here */ + } + printk("*** Boot failure! No secondary bootloader specified ***\n"); + exit(1); +} + + +/************************************************************************/ +/* entry */ +/************************************************************************/ + +void +boot( void ) +{ + fword("update-chosen"); + if( find_dev("/mol-platform") ) + yaboot_startup(); + else + newworld_startup(); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/methods.c b/qemu/roms/openbios/arch/ppc/mol/methods.c new file mode 100644 index 000000000..bfaf51506 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/methods.c @@ -0,0 +1,470 @@ +/* + * Creation Date: <2003/10/18 13:24:29 samuel> + * Time-stamp: <2004/03/27 02:00:30 samuel> + * + * <methods.c> + * + * Misc device node methods + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "mol/mol.h" +#include "libopenbios/ofmem.h" +#include "mol/prom.h" +#include "osi_calls.h" +#include "kbd_sh.h" + +/************************************************************************/ +/* Power Management */ +/************************************************************************/ + +DECLARE_NODE( powermgt, INSTALL_OPEN, 0, "/pci/pci-bridge/mac-io/power-mgt" ); + +/* ( -- ) */ +static void +set_hybernot_flag( void ) +{ +} + +NODE_METHODS( powermgt ) = { + { "set-hybernot-flag", set_hybernot_flag }, +}; + + +/************************************************************************/ +/* RTAS (run-time abstraction services) */ +/************************************************************************/ + +DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" ); + +/* ( physbase -- rtas_callback ) */ +static void +rtas_instantiate( void ) +{ + int physbase = POP(); + int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start; + unsigned long virt; + + while( s < size ) + s += 0x1000; + virt = ofmem_claim_virt( 0, s, 0x1000 ); + ofmem_map( physbase, virt, s, -1 ); + memcpy( (char*)virt, of_rtas_start, size ); + + printk("RTAS instantiated at %08x\n", physbase ); + flush_icache_range( (char*)virt, (char*)virt + size ); + + PUSH( physbase ); +} + +NODE_METHODS( rtas ) = { + { "instantiate", rtas_instantiate }, + { "instantiate-rtas", rtas_instantiate }, +}; + + + +/************************************************************************/ +/* stdout */ +/************************************************************************/ + +DECLARE_NODE( video_stdout, INSTALL_OPEN, 0, "Tdisplay" ); + +/* ( addr len -- actual ) */ +static void +stdout_write( void ) +{ + int len = POP(); + char *addr = (char*)POP(); + + /* printk( "%s", s ); */ + console_draw_fstr(addr, len); + + PUSH( len ); +} + +NODE_METHODS( video_stdout ) = { + { "write", stdout_write }, +}; + + +/************************************************************************/ +/* tty */ +/************************************************************************/ + +DECLARE_NODE( tty, INSTALL_OPEN, 0, "+/mol/mol-tty" ); + +/* ( addr len -- actual ) */ +static void +tty_read( void ) +{ + int ch, len = POP(); + char *p = (char*)POP(); + int ret=0; + + if( len > 0 ) { + ret = 1; + ch = OSI_TTYGetc(); + if( ch >= 0 ) { + *p = ch; + } else { + ret = 0; + OSI_USleep(1); + } + } + PUSH( ret ); +} + +/* ( addr len -- actual ) */ +static void +tty_write( void ) +{ + int i, len = POP(); + char *p = (char*)POP(); + for( i=0; i<len; i++ ) + OSI_TTYPutc( *p++ ); + RET( len ); +} + +NODE_METHODS( tty ) = { + { "read", tty_read }, + { "write", tty_write }, +}; + + +/************************************************************************/ +/* keyboard */ +/************************************************************************/ + +typedef struct { + int cntrl; + int shift; + int meta; + int alt; + int save_key; + char keytable[32]; +} kbd_state_t; + +static const unsigned char adb_ascii_table[128] = + /* 0x00 */ "asdfhgzxcv`bqwer" + /* 0x10 */ "yt123465=97-80]o" + /* 0x20 */ "u[ip\nlj'k;\\,/nm." + /* 0x30 */ "\t <\b \e " + /* 0x40 */ " . * + / - " + /* 0x50 */ " =01234567 89 " + /* 0x60 */ " " + /* 0x70 */ " "; + +static const unsigned char adb_shift_table[128] = + /* 0x00 */ "ASDFHGZXCV~BQWER" + /* 0x10 */ "YT!@#$^%+(&_*)}O" + /* 0x20 */ "U{IP\nLJ\"K:|<?NM>" + /* 0x30 */ "\t <\b \e " + /* 0x40 */ " . * + / - " + /* 0x50 */ " =01234567 89 " + /* 0x60 */ " " + /* 0x70 */ " "; + +DECLARE_NODE( kbd, INSTALL_OPEN, sizeof(kbd_state_t), + "/psuedo-hid/keyboard", + "/mol/mol-keyboard", + "/mol/keyboard" +); + +/* ( -- keymap ) (?) */ +/* should return a pointer to an array with 32 bytes (256 bits) */ +static void +kbd_get_key_map( kbd_state_t *ks ) +{ + /* printk("met_kbd_get_key_map\n"); */ + + /* keytable[5] = 0x40; */ + PUSH( (int)ks->keytable ); +} + +/* ( buf len --- actlen ) */ +static void +kbd_read( kbd_state_t *ks ) +{ + int ret=0, len = POP(); + char *p = (char*)POP(); + int key; + + if( !p || !len ) { + PUSH( -1 ); + return; + } + + if( ks->save_key ) { + *p = ks->save_key; + ks->save_key = 0; + RET( 1 ); + } + OSI_USleep(1); /* be nice */ + + for( ; (key=OSI_GetAdbKey()) >= 0 ; ) { + int code = (key & 0x7f); + int down = !(key & 0x80); + + if( code == 0x36 /* ctrl */ ) { + ks->cntrl = down; + continue; + } + if( code == 0x38 /* shift */ || code == 0x7b) { + ks->shift = down; + continue; + } + if( code == 0x37 /* command */ ) { + ks->meta = down; + continue; + } + if( code == 0x3a /* alt */ ) { + ks->alt = down; + continue; + } + if( !down ) + continue; + + ret = 1; + if( ks->shift ) + key = adb_shift_table[ key & 0x7f ]; + else + key = adb_ascii_table[ key & 0x7f ]; + + if( ks->meta ) { + ks->save_key = key; + key = 27; + } else if( ks->cntrl ) { + key = key - 'a' + 1; + } + *p = key; + if( !*p ) + *p = 'x'; + break; + } + PUSH( ret ); +} + +NODE_METHODS( kbd ) = { + { "read", kbd_read }, + { "get-key-map", kbd_get_key_map }, +}; + + +/************************************************************************/ +/* client interface 'quiesce' */ +/************************************************************************/ + +DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" ); + +/* ( -- ) */ +static void +ciface_quiesce( unsigned long args[], unsigned long ret[] ) +{ +#if 0 + unsigned long msr; + /* This seems to be the correct thing to do - but I'm not sure */ + asm volatile("mfmsr %0" : "=r" (msr) : ); + msr &= ~(MSR_IR | MSR_DR); + asm volatile("mtmsr %0" :: "r" (msr) ); +#endif + printk("=============================================================\n\n"); + prom_close(); + + OSI_KbdCntrl( kKbdCntrlSuspend ); +} + +/* ( -- ms ) */ +static void +ciface_milliseconds( unsigned long args[], unsigned long ret[] ) +{ + static unsigned long mticks=0, usecs=0; + unsigned long t; + + asm volatile("mftb %0" : "=r" (t) : ); + if( mticks ) + usecs += OSI_MticksToUsecs( t-mticks ); + mticks = t; + + PUSH( usecs/1000 ); +} + + +NODE_METHODS( ciface ) = { + { "quiesce", ciface_quiesce }, + { "milliseconds", ciface_milliseconds }, +}; + + +/************************************************************************/ +/* MMU/memory methods */ +/************************************************************************/ + +DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" ); +DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpus/@0" ); +DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" ); + + +/* ( phys size align --- base ) */ +static void +mem_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell phys = POP(); + ucell ret = ofmem_claim_phys( phys, size, align ); + + if( ret == -1 ) { + printk("MEM: claim failure\n"); + throw( -13 ); + return; + } + PUSH( ret ); +} + +/* ( phys size --- ) */ +static void +mem_release( void ) +{ + POP(); POP(); +} + +/* ( phys size align --- base ) */ +static void +mmu_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell phys = POP(); + ucell ret = ofmem_claim_virt( phys, size, align ); + + if( ret == -1 ) { + printk("MMU: CLAIM failure\n"); + throw( -13 ); + return; + } + PUSH( ret ); +} + +/* ( phys size --- ) */ +static void +mmu_release( void ) +{ + POP(); POP(); +} + +/* ( phys virt size mode -- [ret???] ) */ +static void +mmu_map( void ) +{ + ucell mode = POP(); + ucell size = POP(); + ucell virt = POP(); + ucell phys = POP(); + ucell ret; + + /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */ + ret = ofmem_map( phys, virt, size, mode ); + + if( ret ) { + printk("MMU: map failure\n"); + throw( -13 ); + return; + } +} + +/* ( virt size -- ) */ +static void +mmu_unmap( void ) +{ + POP(); POP(); +} + +/* ( virt -- false | phys mode true ) */ +static void +mmu_translate( void ) +{ + ucell mode; + ucell virt = POP(); + ucell phys = ofmem_translate( virt, &mode ); + + if( phys == -1 ) { + PUSH( 0 ); + } else { + PUSH( phys ); + PUSH( mode ); + PUSH( -1 ); + } +} + +/* ( virt size align -- baseaddr|-1 ) */ +static void +ciface_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell virt = POP(); + ucell ret = ofmem_claim( virt, size, align ); + + /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */ + PUSH( ret ); +} + +/* ( virt size -- ) */ +static void +ciface_release( void ) +{ + POP(); + POP(); +} + + +NODE_METHODS( memory ) = { + { "claim", mem_claim }, + { "release", mem_release }, +}; + +NODE_METHODS( mmu ) = { + { "claim", mmu_claim }, + { "release", mmu_release }, + { "map", mmu_map }, + { "unmap", mmu_unmap }, + { "translate", mmu_translate }, +}; + +NODE_METHODS( mmu_ciface ) = { + { "cif-claim", ciface_claim }, + { "cif-release", ciface_release }, +}; + + +/************************************************************************/ +/* init */ +/************************************************************************/ + +void +node_methods_init( void ) +{ + REGISTER_NODE( rtas ); + REGISTER_NODE( powermgt ); + REGISTER_NODE( kbd ); + REGISTER_NODE( video_stdout ); + REGISTER_NODE( ciface ); + REGISTER_NODE( memory ); + REGISTER_NODE( mmu ); + REGISTER_NODE( mmu_ciface ); + + if( OSI_CallAvailable(OSI_TTY_GETC) ) + REGISTER_NODE( tty ); + + OSI_KbdCntrl( kKbdCntrlActivate ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/mol.c b/qemu/roms/openbios/arch/ppc/mol/mol.c new file mode 100644 index 000000000..86b3b66bf --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/mol.c @@ -0,0 +1,165 @@ +/* + * Creation Date: <2003/12/19 18:46:21 samuel> + * Time-stamp: <2004/04/12 16:27:12 samuel> + * + * <mol.c> + * + * + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "arch/common/nvram.h" +#include "libc/vsprintf.h" +#include "libc/string.h" +#include "mol/mol.h" +#include "osi_calls.h" +#include <stdarg.h> + +void +exit( int status ) +{ + OSI_Exit(); +} + +void +fatal_error( const char *err ) +{ + printk("Fatal error: %s\n", err ); + OSI_Exit(); +} + +void +panic( const char *err ) +{ + printk("Panic: %s\n", err ); + OSI_Exit(); + + /* won't come here... this keeps the gcc happy */ + for( ;; ) + ; +} + + +/************************************************************************/ +/* print using OSI interface */ +/************************************************************************/ + +static int do_indent; + +int +printk( const char *fmt, ... ) +{ + char *p, buf[1024]; + va_list args; + int i; + + va_start(args, fmt); + i = vnsprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + for( p=buf; *p; p++ ) { + if( *p == '\n' ) + do_indent = 0; + if( do_indent++ == 1 ) { + OSI_PutC( '>' ); + OSI_PutC( '>' ); + OSI_PutC( ' ' ); + } + OSI_PutC( *p ); + } + return i; +} + + +/************************************************************************/ +/* TTY iface */ +/************************************************************************/ + +static int ttychar = -1; + +static int +tty_avail( void ) +{ + return OSI_CallAvailable( OSI_TTY_GETC ); +} + +int +availchar( void ) +{ + if( !tty_avail() ) + return 0; + + if( ttychar < 0 ) + ttychar = OSI_TTYGetc(); + if( ttychar < 0 ) + OSI_USleep(1); + return (ttychar >= 0); +} + +int +getchar( void ) +{ + int ch; + + if( !tty_avail() ) + return 0; + + if( ttychar < 0 ) + return OSI_TTYGetc(); + ch = ttychar; + ttychar = -1; + return ch; +} + +int +putchar( int c ) +{ + printk("%c", c ); + + if( tty_avail() ) + OSI_TTYPutc( c ); + return c; +} + + +/************************************************************************/ +/* MOL specific stuff */ +/************************************************************************/ + +int +arch_nvram_size( void ) +{ + return OSI_NVRamSize(); +} + +void +arch_nvram_put( char *buf ) +{ + int i, size = arch_nvram_size(); + + for( i=0; i<size; i++ ) + OSI_WriteNVRamByte( i, buf[i] ); +} + +void +arch_nvram_get( char *buf ) +{ + int i, size = arch_nvram_size(); + + /* support for zapping the nvram */ + if( get_bool_res("zap_nvram") == 1 ) { + memset( buf, 0, size ); + return; + } + + for( i=0; i<size; i++ ) + buf[i] = OSI_ReadNVRamByte( i ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/mol.fs b/qemu/roms/openbios/arch/ppc/mol/mol.fs new file mode 100644 index 000000000..10c99bd79 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/mol.fs @@ -0,0 +1,107 @@ + + +\ ------------------------------------------------------------------------- +\ initialization +\ ------------------------------------------------------------------------- + +: make-openable ( path ) + find-dev if + begin ?dup while + \ install trivial open and close methods + dup active-package! is-open + parent + repeat + then +; + +: preopen ( chosen-str node-path ) + 2dup make-openable + + " /chosen" find-device + open-dev ?dup if + encode-int 2swap property + else + 2drop + then +; + +\ preopen device nodes (and store the ihandles under /chosen) +:noname + " memory" " /memory" preopen + " mmu" " /cpus/@0" preopen + " stdout" " /packages/mol-stdout" preopen + " stdin" " keyboard" preopen + " nvram" " /pci/pci-bridge/mac-io/nvram" preopen + " nvram" " /mol/nvram" preopen + +; SYSTEM-initializer + + +\ ------------------------------------------------------------------------- +\ device tree fixing +\ ------------------------------------------------------------------------- + +\ add decode-address methods +: (make-decodable) ( phandle -- ) + + dup " #address-cells" rot get-package-property 0= if + decode-int nip nip + over " decode-unit" rot find-method if 2drop else + ( save phandle ncells ) + + over active-package! + case + 1 of ['] parse-hex " decode-unit" is-xt-func endof + 3 of + " bus-range" active-package get-package-property 0= if + decode-int nip nip + ['] encode-unit-pci " encode-unit" is-xt-func + " decode-unit" is-func-begin + ['] (lit) , , + ['] decode-unit-pci-bus , + is-func-end + then + endof + endcase + then + then + drop +; + +: tree-fixes ( -- ) + active-package + + iterate-tree-begin + begin ?dup while + + dup (make-decodable) + + iterate-tree + repeat + + active-package! +; + +\ use the tty interface if available +: activate-tty-interface + " /mol/mol-tty" find-dev if drop + " /mol/mol-tty" " input-device" $setenv + " /mol/mol-tty" " output-device" $setenv + then +; + +:noname + " keyboard" input +; CONSOLE-IN-initializer + + +\ ------------------------------------------------------------------------- +\ pre-booting +\ ------------------------------------------------------------------------- + +: update-chosen + " /chosen" find-device + stdin @ encode-int " stdin" property + stdout @ encode-int " stdout" property + device-end +; diff --git a/qemu/roms/openbios/arch/ppc/mol/mol.h b/qemu/roms/openbios/arch/ppc/mol/mol.h new file mode 100644 index 000000000..cea15a350 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/mol.h @@ -0,0 +1,44 @@ +/* + * Creation Date: <2003/12/20 00:20:12 samuel> + * Time-stamp: <2004/03/27 01:52:50 samuel> + * + * <mol.h> + * + * + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_MOL +#define _H_MOL + +/* video.c */ +extern void init_video( void ); +extern int video_get_res( int *w, int *h ); +extern void draw_pixel( int x, int y, int colind ); +extern void set_color( int index, unsigned long color ); + +/* console.c */ +extern int console_draw_fstr(const char *str, int len); +extern void console_close( void ); + +/* pseudodisk.c */ +extern void pseudodisk_init( void ); + +/* osi-blk.c */ +extern void osiblk_init( void ); + +/* osi-scsi.c */ +extern void osiscsi_init( void ); + +/* pseudofs.c */ +extern void pseudofs_init( void ); + +#include "../kernel.h" + +#endif /* _H_MOL */ diff --git a/qemu/roms/openbios/arch/ppc/mol/osi-blk.c b/qemu/roms/openbios/arch/ppc/mol/osi-blk.c new file mode 100644 index 000000000..4ed1b5ab3 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/osi-blk.c @@ -0,0 +1,119 @@ +/* + * Creation Date: <2003/12/07 19:08:33 samuel> + * Time-stamp: <2004/01/07 19:38:36 samuel> + * + * <osi-blk.c> + * + * OSI-block interface + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "mol/mol.h" +#include "osi_calls.h" + +typedef struct { + int unit; + int channel; +} osiblk_data_t; + + +DECLARE_NODE( osiblk, INSTALL_OPEN, sizeof(osiblk_data_t), + "/pci/pci-bridge/mol-blk/disk", "/mol/mol-blk" ); + + +static void +osiblk_open( osiblk_data_t *pb ) +{ + phandle_t ph; + + fword("my-unit"); + pb->unit = POP(); + pb->channel = 0; /* FIXME */ + + selfword("open-deblocker"); + + /* interpose disk-label */ + ph = find_dev("/packages/disk-label"); + fword("my-args"); + PUSH_ph( ph ); + fword("interpose"); + + /* printk("osi-blk: open %d\n", pb->unit ); */ + PUSH( -1 ); +} + +static void +osiblk_close( osiblk_data_t *pb ) +{ + selfword("close-deblocker"); +} + + +/* ( buf blk nblks -- actual ) */ +static void +osiblk_read_blocks( osiblk_data_t *pb ) +{ + int i, n = POP(); + int blk = POP(); + char *dest = (char*)POP(); + + /* printk("osiblk_read_blocks %x block=%d n=%d\n", (int)dest, blk, n ); */ + + for( i=0; i<n; ) { + char buf[4096]; + int m = MIN( n-i, sizeof(buf)/512 ); + + if( OSI_ABlkSyncRead(pb->channel, pb->unit, blk+i, (int)buf, m*512) < 0 ) { + printk("SyncRead: error\n"); + RET(0); + } + memcpy( dest, buf, m * 512 ); + i += m; + dest += m * 512; + } + PUSH( n ); +} + +/* ( -- bs ) */ +static void +osiblk_block_size( osiblk_data_t *pb ) +{ + PUSH( 512 ); +} + +/* ( -- maxbytes ) */ +static void +osiblk_max_transfer( osiblk_data_t *pb ) +{ + PUSH( 1024*1024 ); +} + +static void +osiblk_initialize( osiblk_data_t *pb ) +{ + fword("is-deblocker"); +} + + +NODE_METHODS( osiblk ) = { + { NULL, osiblk_initialize }, + { "open", osiblk_open }, + { "close", osiblk_close }, + { "read-blocks", osiblk_read_blocks }, + { "block-size", osiblk_block_size }, + { "max-transfer", osiblk_max_transfer }, +}; + +void +osiblk_init( void ) +{ + REGISTER_NODE( osiblk ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/osi-scsi.c b/qemu/roms/openbios/arch/ppc/mol/osi-scsi.c new file mode 100644 index 000000000..18f3dc577 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/osi-scsi.c @@ -0,0 +1,271 @@ +/* + * Creation Date: <2003/12/11 21:23:54 samuel> + * Time-stamp: <2004/01/07 19:38:45 samuel> + * + * <osi-scsi.c> + * + * SCSI device node + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "mol/mol.h" +#include "scsi_sh.h" +#include "osi_calls.h" + +#define MAX_TARGETS 32 + +typedef struct { + int probed; + int valid; /* a useable device found */ + + int is_cd; + int blocksize; +} target_info_t; + +static target_info_t scsi_devs[ MAX_TARGETS ]; + +typedef struct { + int target; + target_info_t *info; +} instance_data_t; + + +DECLARE_NODE( scsi, INSTALL_OPEN, sizeof(instance_data_t), + "/pci/pci-bridge/mol-scsi/sd", "/mol/mol-scsi/sd" ); + + +static int +scsi_cmd_( instance_data_t *sd, const char *cmd, int cmdlen, char *dest, + int len, int prelen, int postlen ) +{ + char prebuf[4096], postbuf[4096]; + scsi_req_t r[2]; /* the [2] is a hack to get space for the sg-list */ + char sb[32]; + + /* memset( dest, 0, len ); */ + + if( (unsigned int)prelen > sizeof(prebuf) || (unsigned int)postlen > sizeof(postbuf) ) { + printk("bad pre/post len %d %d\n", prelen, postlen ); + return 1; + } + + memset( r, 0, sizeof(r[0]) ); + r->lun = 0; + r->target = sd->target; + r->is_write = 0; + memcpy( r->cdb, cmd, cmdlen ); + r->client_addr = (int)&r; + r->cdb_len = cmdlen; + r->sense[0].base = (int)&sb; + r->sense[0].size = sizeof(sb); + r->size = prelen + len + postlen; + r->n_sg = 3; + r->sglist.n_el = 3; + r->sglist.vec[0].base = (int)prebuf; + r->sglist.vec[0].size = prelen; + r->sglist.vec[1].base = (int)dest; + r->sglist.vec[1].size = len; + r->sglist.vec[2].base = (int)postbuf; + r->sglist.vec[2].size = postlen; + + if( OSI_SCSISubmit((int)&r) ) { + printk("OSI_SCSISubmit: error!\n"); + return 1; + } + while( !OSI_SCSIAck() ) + OSI_USleep( 10 ); + + if( r->adapter_status ) + return -1; + if( r->scsi_status ) + return ((sb[2] & 0xf) << 16) | (sb[12] << 8) | sb[13]; + return 0; +} + +static int +scsi_cmd( instance_data_t *sd, const char *cmd, int cmdlen ) +{ + return scsi_cmd_( sd, cmd, cmdlen, NULL, 0, 0, 0 ); +} + +/* ( buf blk nblks -- actual ) */ +static void +scsi_read_blocks( instance_data_t *sd ) +{ + int nblks = POP(); + int blk = POP(); + char *dest = (char*)POP(); + unsigned char cmd[10]; + int len = nblks * sd->info->blocksize; + + memset( dest, 0, len ); + + /* printk("READ: blk: %d length %d\n", blk, len ); */ + memset( cmd, 0, sizeof(cmd) ); + cmd[0] = 0x28; /* READ_10 */ + cmd[2] = blk >> 24; + cmd[3] = blk >> 16; + cmd[4] = blk >> 8; + cmd[5] = blk; + cmd[7] = nblks >> 8; + cmd[8] = nblks; + + if( scsi_cmd_(sd, cmd, 10, dest, len, 0, 0) ) { + printk("read: scsi_cmd failed\n"); + RET( -1 ); + } + PUSH( nblks ); +} + +static int +inquiry( instance_data_t *sd ) +{ + char inquiry_cmd[6] = { 0x12, 0, 0, 0, 32, 0 }; + char start_stop_unit_cmd[6] = { 0x1b, 0, 0, 0, 1, 0 }; + char test_unit_ready_cmd[6] = { 0x00, 0, 0, 0, 0, 0 }; + char prev_allow_medium_removal[6] = { 0x1e, 0, 0, 0, 1, 0 }; + char set_cd_speed_cmd[12] = { 0xbb, 0, 0xff, 0xff, 0xff, 0xff, + 0, 0, 0, 0, 0, 0 }; + target_info_t *info = &scsi_devs[sd->target]; + char ret[32]; + int i, sense; + + if( sd->target >= MAX_TARGETS ) + return -1; + sd->info = info; + + if( info->probed ) + return info->valid ? 0:-1; + info->probed = 1; + + if( (sense=scsi_cmd_(sd, inquiry_cmd, 6, ret, 2, 0, 0)) ) { + if( sense < 0 ) + return -1; + printk("INQUIRY failed\n"); + return -1; + } + + /* medium present? */ + if( (scsi_cmd(sd, test_unit_ready_cmd, 6) >> 8) == 0x23a ) { + printk("no media\n"); + return -1; + } + + info->is_cd = 0; + info->blocksize = 512; + + if( ret[0] == 5 /* CD/DVD */ ) { + info->blocksize = 2048; + info->is_cd = 1; + + scsi_cmd( sd, prev_allow_medium_removal, 6 ); + scsi_cmd( sd, set_cd_speed_cmd, 12 ); + scsi_cmd( sd, start_stop_unit_cmd, 6 ); + + } else if( ret[0] == 0 /* DISK */ ) { + scsi_cmd( sd, test_unit_ready_cmd, 6 ); + scsi_cmd( sd, start_stop_unit_cmd, 6 ); + } else { + /* don't boot from this device (could be a scanner :-)) */ + return -1; + } + + /* wait for spin-up (or whatever) to complete */ + for( i=0; ; i++ ) { + if( i > 300 ) { + printk("SCSI timeout (sense %x)\n", sense ); + return -1; + } + sense = scsi_cmd( sd, test_unit_ready_cmd, 6 ); + if( (sense & 0xf0000) == 0x20000 ) { + OSI_USleep( 10000 ); + continue; + } + break; + } + + info->valid = 1; + return 0; +} + +/* ( -- success? ) */ +static void +scsi_open( instance_data_t *sd ) +{ + static int once = 0; + phandle_t ph; + + fword("my-unit"); + sd->target = POP(); + + if( !once ) { + once++; + OSI_SCSIControl( SCSI_CTRL_INIT, 0 ); + } + + /* obtiain device information */ + if( inquiry(sd) ) + RET(0); + + selfword("open-deblocker"); + + /* interpose disk-label */ + ph = find_dev("/packages/disk-label"); + fword("my-args"); + PUSH_ph( ph ); + fword("interpose"); + + PUSH( -1 ); +} + +/* ( -- ) */ +static void +scsi_close( instance_data_t *pb ) +{ + selfword("close-deblocker"); +} + + +/* ( -- bs ) */ +static void +scsi_block_size( instance_data_t *sd ) +{ + PUSH( sd->info->blocksize ); +} + +/* ( -- maxbytes ) */ +static void +scsi_max_transfer( instance_data_t *sd ) +{ + PUSH( 1024*1024 ); +} + +static void +scsi_initialize( instance_data_t *sd ) +{ + fword("is-deblocker"); +} + + +NODE_METHODS( scsi ) = { + { NULL, scsi_initialize }, + { "open", scsi_open }, + { "close", scsi_close }, + { "read-blocks", scsi_read_blocks }, + { "block-size", scsi_block_size }, + { "max-transfer", scsi_max_transfer }, +}; + +void +osiscsi_init( void ) +{ + REGISTER_NODE( scsi ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/prom.c b/qemu/roms/openbios/arch/ppc/mol/prom.c new file mode 100644 index 000000000..0bc8bcfbc --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/prom.c @@ -0,0 +1,175 @@ +/* + * Creation Date: <2002/10/03 20:55:02 samuel> + * Time-stamp: <2002/10/29 13:00:23 samuel> + * + * <prom.c> + * + * oftree interface + * + * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation + * + */ + +#include "config.h" +#include "osi_calls.h" +#include "mol/prom.h" + +/* OSI_PromClose (free linux side device tree) */ +int +prom_close( void ) +{ + return OSI_PromIface( kPromClose, 0 ); +} + +/* ret: 0 no more peers, -1 if error */ +mol_phandle_t +prom_peer( mol_phandle_t phandle ) +{ + return OSI_PromIface( kPromPeer, phandle ); +} + +/* ret: 0 no child, -1 if error */ +mol_phandle_t +prom_child( mol_phandle_t phandle ) +{ + return OSI_PromIface( kPromChild, phandle ); +} + +/* ret: 0 if root node, -1 if error */ +mol_phandle_t +prom_parent( mol_phandle_t phandle ) +{ + return OSI_PromIface( kPromParent, phandle ); +} + +/* ret: -1 error */ +int +prom_package_to_path( mol_phandle_t phandle, char *buf, long buflen ) +{ + return OSI_PromIface2( kPromPackageToPath, phandle, (int)buf, buflen ); +} + +/* ret: -1 error */ +int +prom_get_prop_len( mol_phandle_t phandle, const char *name ) +{ + return OSI_PromIface1( kPromGetPropLen, phandle, (int)name ); +} + +/* ret: prop len or -1 if error */ +int +prom_get_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen ) +{ + return OSI_PromIface3( kPromGetProp, phandle, (int)name, (int)buf, buflen ); +} + +/* ret: prop len or -1 if error */ +int +prom_get_prop_by_path( const char *path, const char *name, char *buf, long buflen ) +{ + mol_phandle_t ph = prom_find_device(path); + return (ph != -1)? prom_get_prop( ph, name, buf, buflen) : -1; +} + +/* ret: -1 error, 0 last prop, 1 otherwise */ +int +prom_next_prop( mol_phandle_t phandle, const char *prev, char *buf ) +{ + return OSI_PromIface2( kPromNextProp, phandle, (int)prev, (int)buf ); +} + +/* ret: -1 if error */ +int +prom_set_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen ) +{ + return OSI_PromIface3( kPromSetProp, phandle, (int)name, (int)buf, buflen ); +} + +/* ret: -1 if error */ +mol_phandle_t +prom_create_node( const char *path ) +{ + return OSI_PromPathIface( kPromCreateNode, path ); +} + +/* ret: -1 if not found */ +mol_phandle_t +prom_find_device( const char *path ) +{ + mol_phandle_t ph; + char buf2[256], ch, *p; + + if( !path ) + return -1; + + if( (ph=OSI_PromPathIface( kPromFindDevice, path )) != -1 ) + return ph; + else if( path[0] == '/' ) + return -1; + + /* might be an alias */ + if( !(p=strpbrk(path, "@:/")) ) + p = (char*)path + strlen(path); + + ch = *p; + *p = 0; + if( (ph=prom_get_prop(prom_find_device("/aliases"), path, buf2, sizeof(buf2))) == -1 ) + return -1; + *p = ch; + strncat( buf2, p, sizeof(buf2) ); + + if( buf2[0] != '/' ) { + printk("Error: aliases must be absolute!\n"); + return -1; + } + ph = OSI_PromPathIface( kPromFindDevice, buf2 ); + return ph; +} + + + +/************************************************************************/ +/* search the tree for nodes with matching device_type */ +/************************************************************************/ + +static mol_phandle_t +prom_find_device_type_( mol_phandle_t ph, const char *type, int *icount, int index ) +{ + char buf[64]; + int ph2; + + if( ph == -1 || !ph ) + return -1; + if( prom_get_prop( ph, "device_type", buf, sizeof(buf)) > 0 ) + if( !strcmp(buf, type) ) + if( (*icount)++ == index ) + return ph; + if( (ph2=prom_find_device_type_( prom_peer(ph), type, icount, index )) != -1 ) + return ph2; + if( (ph2=prom_find_device_type_( prom_child(ph), type, icount, index )) != -1 ) + return ph2; + return -1; +} + +mol_phandle_t +prom_find_device_type( const char *type, int index ) +{ + int count = 0; + return prom_find_device_type_( prom_peer(0), type, &count, index ); +} + + +/************************************************************************/ +/* device tree tweaking */ +/************************************************************************/ + +/* -1 if error */ +int +prom_change_phandle( mol_phandle_t old_ph, mol_phandle_t new_ph ) +{ + return OSI_PromIface1( kPromChangePHandle, old_ph, (int)new_ph ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/prom.h b/qemu/roms/openbios/arch/ppc/mol/prom.h new file mode 100644 index 000000000..54a856c27 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/prom.h @@ -0,0 +1,47 @@ +/* + * Creation Date: <2002/10/03 21:07:27 samuel> + * Time-stamp: <2003/10/22 22:45:26 samuel> + * + * <prom.h> + * + * device tree interface + * + * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation + * + */ + +#ifndef _H_PROM +#define _H_PROM + +/* Note 1: MOL uses -1 as the invalid phandle while OpenFirmware uses 0 as the + * invalid phandle (it is also the root node). + * + * Note 2: phandles might be negative. For instance, phandles originating from + * a real Open Firmware tree might look like 0xff123000 (a ROM address)... + */ + +typedef enum { kGetRootPhandle=0 } mol_phandle_t; /* must promote to int */ + +extern int prom_close( void ); + +extern mol_phandle_t prom_peer( mol_phandle_t phandle ); +extern mol_phandle_t prom_child( mol_phandle_t phandle ); +extern mol_phandle_t prom_parent( mol_phandle_t phandle ); +extern int prom_package_to_path( mol_phandle_t phandle, char *buf, long buflen ); +extern int prom_get_prop_len( mol_phandle_t phandle, const char *name ); +extern int prom_get_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen ); +extern int prom_get_prop_by_path( const char *path, const char *name, char *buf, long buflen ); +extern int prom_next_prop( mol_phandle_t phandle, const char *prev, char *buf ); +extern int prom_set_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen ); +extern mol_phandle_t prom_create_node( const char *path ); +extern mol_phandle_t prom_find_device( const char *path ); + +extern mol_phandle_t prom_find_device_type( const char *type, int index ); + +extern int prom_change_phandle( mol_phandle_t old_ph, mol_phandle_t new_ph ); + +#endif /* _H_PROM */ diff --git a/qemu/roms/openbios/arch/ppc/mol/pseudodisk.c b/qemu/roms/openbios/arch/ppc/mol/pseudodisk.c new file mode 100644 index 000000000..a98e54845 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/pseudodisk.c @@ -0,0 +1,178 @@ +/* + * Creation Date: <2003/11/26 16:55:47 samuel> + * Time-stamp: <2004/01/07 19:41:54 samuel> + * + * <pseudodisk.c> + * + * pseudodisk (contains files exported from linux) + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "osi_calls.h" +#include "libc/string.h" +#include "libopenbios/ofmem.h" +#include "mol/prom.h" +#include "mol/mol.h" +#include "osi_calls.h" +#include "pseudofs_sh.h" + +typedef struct { + int seekpos; + int fd; + char *myargs; + char *name; + int size; +} pdisk_data_t; + + +DECLARE_NODE( pdisk, INSTALL_OPEN, sizeof(pdisk_data_t), "/mol/pseudo-disk/disk" ); + +static void +pdisk_open( pdisk_data_t *pb ) +{ + char *ep, *name = NULL; + int part; + + pb->myargs = my_args_copy(); + /* printk("pdisk-open: %s\n", pb->myargs ); */ + + part = strtol( pb->myargs, &ep, 10 ); + if( *ep ) { + if( (name=strchr(pb->myargs, ',')) ) { + *name = 0; + name++; + } else { + name = pb->myargs; + } + } + if( part ) + goto err; + + if( !name || !strlen(name) ) + pb->fd = -1; + else { + if( (pb->fd=PseudoFSOpen(name)) < 0 ) + goto err; + pb->size = PseudoFSGetSize( pb->fd ); + } + pb->name = name; + RET( -1 ); + err: + free( pb->myargs ); + RET(0); +} + +/* ( addr len -- actual ) */ +static void +pdisk_read( pdisk_data_t *pb ) +{ + int len = POP(); + char *dest = (char*)POP(); + int cnt; + + if( pb->fd < 0 ) { + memset( dest, 0, len ); + PUSH(len); + return; + } + /* dest is not "mol-DMA" safe (might have a nontrivial mapping) */ + for( cnt=0; cnt<len; ) { + char buf[2048]; + int n = MIN( len-cnt, sizeof(buf) ); + + n = PseudoFSRead( pb->fd, pb->seekpos, buf, n ); + if( n <= 0 ) + break; + + memcpy( dest+cnt, buf, n ); + cnt += n; + pb->seekpos += n; + } + PUSH( cnt ); +} + +/* ( addr len -- actual ) */ +static void +pdisk_write( pdisk_data_t *pb ) +{ + POP(); POP(); PUSH(-1); + printk("pdisk write\n"); +} + +/* ( pos.lo pos.hi -- status ) */ +static void +pdisk_seek( pdisk_data_t *pb ) +{ + int pos_lo; + POP(); + pos_lo = POP(); + + if( pb->fd >= 0 ) { + if( pos_lo == -1 ) + pos_lo = pb->size; + } + + pb->seekpos = pos_lo; + + PUSH(0); /* ??? */ +} + +/* ( -- pos.d ) */ +static void +pdisk_tell( pdisk_data_t *pb ) +{ + DPUSH( pb->seekpos ); +} + +/* ( -- cstr ) */ +static void +pdisk_get_path( pdisk_data_t *pb ) +{ + PUSH( (int)pb->name ); +} + +/* ( -- cstr ) */ +static void +pdisk_get_fstype( pdisk_data_t *pb ) +{ + PUSH( (int)"PSEUDO" ); +} + +/* ( -- cstr ) */ +static void +pdisk_volume_name( pdisk_data_t *pb ) +{ + PUSH( (int)"Virtual Volume" ); +} + +static void +pdisk_block_size( pdisk_data_t *pb ) +{ + PUSH(1); +} + +NODE_METHODS( pdisk ) = { + { "open", pdisk_open }, + { "read", pdisk_read }, + { "write", pdisk_write }, + { "seek", pdisk_seek }, + { "tell", pdisk_tell }, + { "block-size", pdisk_block_size }, + { "get-path", pdisk_get_path }, + { "get-fstype", pdisk_get_fstype }, + { "volume-name", pdisk_volume_name }, +}; + +void +pseudodisk_init( void ) +{ + REGISTER_NODE( pdisk ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/tree.c b/qemu/roms/openbios/arch/ppc/mol/tree.c new file mode 100644 index 000000000..b82c8c2c8 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/tree.c @@ -0,0 +1,165 @@ +/* + * Creation Date: <2003/11/18 14:55:05 samuel> + * Time-stamp: <2004/03/27 02:03:55 samuel> + * + * <tree.c> + * + * device tree setup + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "mol/mol.h" +#include "mol/prom.h" + + +/************************************************************************/ +/* copy device tree */ +/************************************************************************/ + +static void +copy_node( mol_phandle_t molph ) +{ + char name[40], path[80]; + int exists; + phandle_t ph; + + if( !molph ) + return; + + prom_package_to_path( molph, path, sizeof(path) ); + + /* don't copy /options node */ + if( !strcmp("/options", path) ) { + copy_node( prom_peer(molph) ); + return; + } + + exists = 1; + if( !(ph=find_dev(path)) ) { + exists = 0; + fword("new-device"); + ph = get_cur_dev(); + } + activate_dev( ph ); + + name[0] = 0; + while( prom_next_prop(molph, name, name) > 0 ) { + int len = prom_get_prop_len( molph, name ); + char *p; +#if 0 + if( len > 0x1000 ) { + printk("prop to large (%d)\n", len ); + continue; + } +#endif + /* don't copy /chosen/{stdin,stdout} (XXX: ugly hack...) */ + if( !strcmp("/chosen", path) ) + if( !strcmp("stdio", name) || !strcmp("stdout", name) ) + continue; + + p = malloc( len ); + prom_get_prop( molph, name, p, len ); + set_property( ph, name, p, len ); + free( p ); + } + + set_int_property( ph, "MOL,phandle", molph ); + copy_node( prom_child(molph) ); + + if( !exists ) + fword("finish-device"); + else + activate_device(".."); + + copy_node( prom_peer(molph) ); +} + + + +/************************************************************************/ +/* device tree cloning and tweaking */ +/************************************************************************/ + +static phandle_t +translate_molph( mol_phandle_t molph ) +{ + static mol_phandle_t cached_molph; + static phandle_t cached_ph; + phandle_t ph=0; + + if( cached_molph == molph ) + return cached_ph; + + while( (ph=dt_iterate(ph)) ) + if( get_int_property(ph, "MOL,phandle", NULL) == molph ) + break; + cached_molph = molph; + cached_ph = ph; + + if( !ph ) + printk("failed to translate molph\n"); + return ph; +} + +static void +fix_phandles( void ) +{ + static char *pnames[] = { "interrupt-parent", "interrupt-controller", NULL } ; + int len, *map; + phandle_t ph=0; + char **pp; + + while( (ph=dt_iterate(ph)) ) { + for( pp=pnames; *pp; pp++ ) { + phandle_t *p = (phandle_t*)get_property( ph, *pp, &len ); + if( len == 4 ) + *p = translate_molph( *(int*)p ); + } + + /* need to fix interrupt map properties too */ + if( (map=(int*)get_property(ph, "interrupt-map", &len)) ) { + int i, acells = get_int_property(ph, "#address-cells", NULL); + int icells = get_int_property(ph, "#interrupt-cells", NULL); + + len /= sizeof(int); + for( i=0; i<len; i++ ) { + phandle_t ch_ph; + int ch_acells, ch_icells; + + i += acells + icells; + if( !(ch_ph=translate_molph(map[i])) ) + break; + map[i] = (int)ch_ph; + ch_acells = get_int_property(ch_ph, "#address-cells", NULL); + ch_icells = get_int_property(ch_ph, "#interrupt-cells", NULL); + i += ch_acells + icells; + } + if( i != len ) + printk("interrupt map fixing failure\n"); + } + } + /* delete MOL,phandle properties */ + for( ph=0; (ph=dt_iterate(ph)) ; ) { + push_str("MOL,phandle"); + PUSH_ph(ph); + fword("(delete-property)"); + } + fword("device-end"); +} + +void +devtree_init( void ) +{ + activate_device("/"); + copy_node( prom_peer(0) ); + fix_phandles(); + fword("tree-fixes"); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/tree.fs b/qemu/roms/openbios/arch/ppc/mol/tree.fs new file mode 100644 index 000000000..228163ffc --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/tree.fs @@ -0,0 +1,103 @@ + +: int-property ( val name -- ) + rot encode-int 2swap property +; + + +\ ------------------------------------------------------------- +\ device-tree +\ ------------------------------------------------------------- + +" /" find-device + + " device-tree" device-name + " bootrom" device-type + +\ ------------------------------------------------------------- +\ /memory +\ ------------------------------------------------------------- + +new-device + " memory" device-name + \ 12230 encode-int " reg" property + external + : open true ; + : close ; + \ claim ( phys size align -- base ) + \ release ( phys size -- ) +finish-device + +\ ------------------------------------------------------------- +\ /mol/ +\ ------------------------------------------------------------- + +new-device + " mol" device-name + 1 " #address-cells" int-property + 0 " #size-cells" int-property + + external + : open true ; + : close ; + +new-device + " test" device-name + + external + : open + ." /mol/test opened" cr + " argument-str" " ipose" find-package drop interpose + true + ; +finish-device +finish-device + +\ ------------------------------------------------------------- +\ /cpus/ +\ ------------------------------------------------------------- + +new-device + " cpus" device-name + 1 " #address-cells" int-property + 0 " #size-cells" int-property + + external + : open true ; + : close ; + : decode-unit parse-hex ; + +finish-device + +\ ------------------------------------------------------------- +\ /packages +\ ------------------------------------------------------------- + +" /packages" find-device + + " packages" device-name + external + \ allow packages to be opened with open-dev + : open true ; + : close ; + +\ /packages/mol-stdout +new-device + " mol-stdout" device-name + external + : open true ; + : close ; + : write ( addr len -- actual ) + dup -rot type + ; +finish-device + +\ XXXXXXXXXXXXXXXXXXXXXXX TESTING +" /" find-device +new-device + " test" device-name +finish-device + +\ ------------------------------------------------------------- +\ The END +\ ------------------------------------------------------------- +device-end |