diff options
Diffstat (limited to 'roms/openbios/arch/ppc')
66 files changed, 10572 insertions, 0 deletions
diff --git a/roms/openbios/arch/ppc/Kconfig b/roms/openbios/arch/ppc/Kconfig new file mode 100644 index 00000000..f317c0a4 --- /dev/null +++ b/roms/openbios/arch/ppc/Kconfig @@ -0,0 +1,48 @@ +mainmenu "OpenBIOS Configuration" + +config PPC +	bool +	default y +	help +	  Building for PPC hardware. + +config BIG_ENDIAN +	bool +	default y +	help +	  PPC hardware is big endian (per default) + +choice +	prompt "Platform Type" +	default MOL + +config MOL +	bool "Mac-on-Linux" +	help +	  Build an image for Mac-on-Linux + +config MPC107 +	bool "MPC107 board (Crescendo)" +	help +	  Build for Crescendo board. + +config BRIQ +	bool "Total Impact briQ" +	help +	  Build an image for the Total Impact briQ + +config NO_ARCH +	bool "None" +	help +	  Don't build any images. + +endchoice + +menu "Build hosted UNIX Binary" +source "arch/unix/Kconfig" +endmenu + +source "kernel/Kconfig" +source "forth/Kconfig" +source "libopenbios/Kconfig" +source "drivers/Kconfig" diff --git a/roms/openbios/arch/ppc/Makefile b/roms/openbios/arch/ppc/Makefile new file mode 100644 index 00000000..e182825e --- /dev/null +++ b/roms/openbios/arch/ppc/Makefile @@ -0,0 +1,79 @@ + +include			../../config/Makefile.top + +SUBDIRS			=  +MOL			= $(CONFIG_MOL:y=mol) +BRIQ			= $(CONFIG_BRIQ:y=briq) +XTARGETS		= $(MOL) $(BRIQ) ppc mollink +DICTIONARIES		= $(MOL) $(BRIQ) + +INCLUDES		= -I../../kernel -I../../kernel/include \ +			  -I../../include/molasm -I$(ODIR)/include + +############################################################################# + +mol-OBJS		= mol/init.o mol/main.o mol/mol.o mol/console.o mol/osi-blk.o \ +			  mol/osi-scsi.o mol/pseudodisk.o mol/methods.o ofmem.o \ +			  mol/video.o mol/prom.o mol/tree.o misc.o mol/kernel.o + +briq-OBJS		= briq/init.o briq/main.o briq/briq.o briq/vfd.o \ +			  ofmem.o briq/methods.o briq/tree.o \ +			  misc.o briq/kernel.o + +ppc-OBJS		= $(KOBJS) $(MODULE_LIBS) \ +			  $(FS_LIBS) $(DRIVER_LIBS) $(LIBC_LIBS) + +all-$(CONFIG_MOL)	+= $(ODIR)/mol.image +all-$(CONFIG_BRIQ)	+= $(ODIR)/briq.image +all-$(CONFIG_MPC107)	+= $(ODIR)/mpc107.image + + +############################################################################# + +mol-SRC			= ppc.fs tree.fs mol.fs $(ARCHDICT_SRC) +briq-SRC		= ppc.fs briq/tree.fs briq/briq.fs $(ARCHDICT_SRC) + +$(ODIR)/mol/kernel.o:	$(ODIR)/include/mol-dict.h +$(ODIR)/briq/kernel.o:	$(ODIR)/include/briq-dict.h + +$(ODIR)/include/mol-dict.h: $(ODIR)/mol.dict +	test -d $(dir $@) || $(INSTALL) -d $(dir $@) +	@echo "static const char forth_dictionary[] = {" > $@ +	@cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \ +		| sed 's/0x  ,//g' >> $@ +	@echo "};" >> $@ + +$(ODIR)/include/briq-dict.h: $(ODIR)/briq.dict +	test -d $(dir $@) || $(INSTALL) -d $(dir $@) +	@echo "static const char forth_dictionary[] = {" > $@ +	@cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \ +		| sed 's/0x  ,//g' >> $@ +	@echo "};" >> $@ + +############################################################################# + +$(ODIR)/mol.image: $(ODIR)/start.o $(ODIR)/libmol.a $(ODIR)/libppc.a +	@printf "= Building %-22s : " $@ +	building= +	$(LD) -Ttext=0x01e01000 -Bstatic $^ $(LIBGCC) -o $@ +	@nm $@ | sort > $(ODIR)/mol.syms +	strip -g $@ +	@echo "ok" + +$(ODIR)/briq.image: $(ODIR)/start.o $(ODIR)/timebase.o $(ODIR)/libbriq.a $(ODIR)/libppc.a +	@printf "= Building %-22s : " $@ +	building= +	$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(LIBGCC) -o $@ +	@nm $@ | sort > $(ODIR)/briq.syms +	#strip -g $@ +	@echo "ok" + +$(ODIR)/mpc107.image: +	@echo "BUILDING mpc107.image (not yet implemented)" + +clean-local: +	$(RM) $(ODIR)/*.image $(ODIR)/*.syms $(ODIR)/include/mol-dict.h + +include			Makefile.asm +include			$(rules)/Rules.make +include			$(rules)/Rules.forth diff --git a/roms/openbios/arch/ppc/Makefile.asm b/roms/openbios/arch/ppc/Makefile.asm new file mode 100644 index 00000000..32d43376 --- /dev/null +++ b/roms/openbios/arch/ppc/Makefile.asm @@ -0,0 +1,32 @@ +# -*- makefile -*-  +# +#   Makefile.asm - assembly support +#    +#   Copyright (C) 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 + + +################################################# +# Rules for asm targets +################################################# + +ASMFLAGS	= -D__ASSEMBLY__ -I$(top_srcdir) $(ALTIVEC) +FILTERBIN	= $(top_srcdir)/scripts/asfilter +ASFILTER	= $(shell if test -x $(FILTERBIN) ; then echo $(FILTERBIN) \ +			; else echo "tr ';' '\n'" ; fi) +INVOKE_M4	= | $(M4) -s $(M4_NO_GNU) | $(ASFILTER) + +$(ODIR)/%.o: %.S +	@printf "    Compiling %-20s: " $(notdir $@) +	assembly= +	@install -d $(dir $@) +	@$(RM) $@ $@.s +	@$(CPP) $(ASMFLAGS) $(IDIRS) $< > /dev/null +	$(CPP) $(ASMFLAGS) $(IDIRS) $(DEPFLAGS) $< $(INVOKE_M4) > $@.s +	$(AS) $@.s $(AS_FLAGS) -o $@ +	@$(DEPEXTRA) +	@$(RM) $@.s +	@echo "ok" diff --git a/roms/openbios/arch/ppc/briq/briq.c b/roms/openbios/arch/ppc/briq/briq.c new file mode 100644 index 00000000..a8541c37 --- /dev/null +++ b/roms/openbios/arch/ppc/briq/briq.c @@ -0,0 +1,194 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<briq.c> + * + *   Copyright (C) 2004, Greg Watson + * + *   derived from 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 "briq/briq.h" +#include <stdarg.h> + +#define UART_BASE 0x3f8 + +unsigned long virt_offset = 0; + +void +exit( int status ) +{ +	for (;;); +} + +void +fatal_error( const char *err ) +{ +	printk("Fatal error: %s\n", err ); +	exit(0); +} + +void +panic( const char *err ) +{ +	printk("Panic: %s\n", err ); +	exit(0); + +	/* 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 ) { +			putchar( '>' ); +			putchar( '>' ); +			putchar( ' ' ); +		} +		putchar( *p ); +	} +	return i; +} + + +/************************************************************************/ +/*	TTY iface							*/ +/************************************************************************/ + +static int ttychar = -1; + +static int +tty_avail( void ) +{ +	return 1; +} + +static int +tty_putchar( int c ) +{ +	if( tty_avail() ) { +		while (!(inb(UART_BASE + 0x05) & 0x20)) +			; +		outb(c, UART_BASE); +		while (!(inb(UART_BASE + 0x05) & 0x40)) +			; +	} +	return c; +} + +int +availchar( void ) +{ +	if( !tty_avail() ) +		return 0; + +	if( ttychar < 0 ) +		ttychar = inb(UART_BASE); +	return (ttychar >= 0); +} + +int +getchar( void ) +{ +	int ch; + +	if( !tty_avail() ) +		return 0; + +	if( ttychar < 0 ) +		return inb(UART_BASE); +	ch = ttychar; +	ttychar = -1; +	return ch; +} + +int +putchar( int c ) +{ +	if (c == '\n') +		tty_putchar('\r'); +	return tty_putchar(c); +} + + +/************************************************************************/ +/*	briQ specific stuff						*/ +/************************************************************************/ + +static char nvram[2048]; + +void +dump_nvram(void) +{ +  static char hexdigit[] = "0123456789abcdef"; +  int i; +  for (i = 0; i < 16*4; i++) +    { +      printk ("%c", hexdigit[nvram[i] >> 4]); +      printk ("%c", hexdigit[nvram[i] % 16]); +      if (!((i + 1) % 16)) +        { +          printk ("\n"); +        } +      else +        { +          printk (" "); +        } +    } +} + + +int +arch_nvram_size( void ) +{ +	return sizeof(nvram); +} + +void +arch_nvram_put( char *buf ) +{ +	memcpy(nvram, buf, sizeof(nvram)); +	printk("new nvram:\n"); +	dump_nvram(); +} + +void +arch_nvram_get( char *buf ) +{ +	memcpy(buf, nvram, sizeof(nvram)); +	printk("current nvram:\n"); +	dump_nvram(); +} diff --git a/roms/openbios/arch/ppc/briq/briq.fs b/roms/openbios/arch/ppc/briq/briq.fs new file mode 100644 index 00000000..78d77970 --- /dev/null +++ b/roms/openbios/arch/ppc/briq/briq.fs @@ -0,0 +1,115 @@ +\   briq specific initialization code +\  +\   Copyright (C) 2004 Greg Watson +\  +\   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 +\  + + +\ ------------------------------------------------------------------------- +\ 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 +  " rtc" " /pci/isa/rtc" preopen +  " memory" " /memory" preopen +  " mmu" " /cpu@0" preopen +  " stdout" " /packages/terminal-emulator" preopen +  " stdin" " keyboard" 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 +; +     +: init-briq-tree ( -- ) +  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 +  " /packages/terminal-emulator" find-dev if drop +    " /packages/terminal-emulator" " input-device" $setenv +    " /packages/terminal-emulator" " 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 +  " /pci/isa/interrupt-controller" find-dev if encode-int " interrupt-controller" property then +  device-end +; diff --git a/roms/openbios/arch/ppc/briq/briq.h b/roms/openbios/arch/ppc/briq/briq.h new file mode 100644 index 00000000..33a2cafa --- /dev/null +++ b/roms/openbios/arch/ppc/briq/briq.h @@ -0,0 +1,24 @@ +/* + *   Creation Date: <2004/08/28 17:50:12 stepan> + *   Time-stamp: <2004/08/28 17:50:12 stepan> + * + *	<briq.h> + * + *   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 + * + */ + +#ifndef _H_BRIQ +#define _H_BRIQ + +/* vfd.c */ +extern int		vfd_draw_str( const char *str ); +extern void		vfd_close( void ); + +#include "kernel.h" + +#endif   /* _H_BRIQ */ diff --git a/roms/openbios/arch/ppc/briq/init.c b/roms/openbios/arch/ppc/briq/init.c new file mode 100644 index 00000000..b32e97aa --- /dev/null +++ b/roms/openbios/arch/ppc/briq/init.c @@ -0,0 +1,130 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<init.c> + * + *	Initialization for briq + * + *   Copyright (C) 2004 Greg Watson + * + *   based on mol/init.c: + * + *   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 "briq/briq.h" +#include "libopenbios/ofmem.h" +#include "openbios-version.h" + +extern void unexpected_excep( int vector ); +extern void setup_timers( void ); + +#if 0 +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; +} +#endif + +void +unexpected_excep( int vector ) +{ +	printk("briQ 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 ) +{ +#if CONFIG_RTAS +	phandle_t ph; +#endif +	int autoboot; + +	devtree_init(); +	node_methods_init(); +	modules_init(); +        setup_timers(); +#ifdef CONFIG_DRIVER_PCI +	ob_pci_init(); +#endif + +#if CONFIG_RTAS +	if( !(ph=find_dev("/rtas")) ) +		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; +		set_property( ph, "rtas-size", (char*)&size, sizeof(size) ); +	} +#endif + +#if 0 +	/* tweak boot settings */ +	autoboot = !!get_bool_res("autoboot"); +#endif +	autoboot = 0; +	if( !autoboot ) +		printk("Autobooting disabled - dropping into OpenFirmware\n"); +	setenv("auto-boot?", autoboot ? "true" : "false" ); +	setenv("boot-command", "briqboot"); + +#if 0 +	if( get_bool_res("tty-interface") == 1 ) +#endif +		fword("activate-tty-interface"); + +	/* hack */ +	device_end(); +	bind_func("briqboot", boot ); +} diff --git a/roms/openbios/arch/ppc/briq/kernel.c b/roms/openbios/arch/ppc/briq/kernel.c new file mode 100644 index 00000000..e85134d4 --- /dev/null +++ b/roms/openbios/arch/ppc/briq/kernel.c @@ -0,0 +1,16 @@ +/* + *   Creation Date: <2004/08/28 18:03:25 stepan> + *   Time-stamp: <2004/08/28 18:03:25 stepan> + * + *	<briq/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 "briq-dict.h" +#include "../kernel.c" diff --git a/roms/openbios/arch/ppc/briq/main.c b/roms/openbios/arch/ppc/briq/main.c new file mode 100644 index 00000000..fbb2a26d --- /dev/null +++ b/roms/openbios/arch/ppc/briq/main.c @@ -0,0 +1,145 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<main.c> + * + *   Copyright (C) 2004 Greg Watson + * + *   Based on MOL specific code which is + *   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 "briq/briq.h" +#include "libopenbios/ofmem.h" + +static void +transfer_control_to_elf( unsigned long entry ) +{ +	extern void call_elf( unsigned long entry ); +	printk("Starting ELF image at 0x%08lX\n", entry); +	call_elf( 0x400000 ); +	//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'\n", get_file_path(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"); + +#if 0 +		/* 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 ); +		} +#endif +		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; +} + + +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 ); +} + +/************************************************************************/ +/*	briq booting							*/ +/************************************************************************/ + +static void +briq_startup( void ) +{ +	const char *paths[] = { "hd:0,\\zImage.chrp", NULL }; +	const char *args[] = { "root=/dev/hda2 console=ttyS0,115200", 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], args[i] ); + +		update_nvram(); +		transfer_control_to_elf( entry ); +		/* won't come here */ +	} +	printk("*** Boot failure! No secondary bootloader specified ***\n"); +} + + +/************************************************************************/ +/*	entry								*/ +/************************************************************************/ + +void +boot( void ) +{ +	fword("update-chosen"); +	briq_startup(); +} diff --git a/roms/openbios/arch/ppc/briq/methods.c b/roms/openbios/arch/ppc/briq/methods.c new file mode 100644 index 00000000..649e9baf --- /dev/null +++ b/roms/openbios/arch/ppc/briq/methods.c @@ -0,0 +1,333 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<methods.c> + * + *	Misc device node methods + * + *   Copyright (C) 2004 Greg Watson + * + *   Based on MOL specific code which is + * + *   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 "briq/briq.h" +#include "libopenbios/ofmem.h" + +/************************************************************************/ +/*	RTAS (run-time abstraction services)				*/ +/************************************************************************/ + +#ifdef CONFIG_RTAS +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 }, +}; +#endif + + +/************************************************************************/ +/*	stdout								*/ +/************************************************************************/ + +DECLARE_NODE( vfd_stdout, INSTALL_OPEN, 0, "Tdisplay" ); + +/* ( addr len -- actual ) */ +static void +stdout_write( void ) +{ +	int len = POP(); +	char *addr = (char*)POP(); +	char *s = malloc( len + 1 ); + +	strncpy_nopad( s, addr, len ); +	s[len]=0; + +	printk( "%s", s ); +	//vfd_draw_str( s ); +	free( s ); + +	PUSH( len ); +} + +NODE_METHODS( vfd_stdout ) = { +	{ "write",	stdout_write	}, +}; + + +/************************************************************************/ +/*	tty								*/ +/************************************************************************/ + +DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" ); + +/* ( 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 = getchar(); +		if( ch >= 0 ) { +			*p = ch; +		} else { +			ret = 0; +		} +	} +	PUSH( ret ); +} + +/* ( addr len -- actual ) */ +static void +tty_write( void ) +{ +	int i, len = POP(); +	char *p = (char*)POP(); +	for( i=0; i<len; i++ ) +		putchar( *p++ ); +	RET( len ); +} + +NODE_METHODS( tty ) = { +	{ "read",	tty_read	}, +	{ "write",	tty_write	}, +}; + +/************************************************************************/ +/*	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"); +} + +/* ( -- ms ) */ +static void +ciface_milliseconds( unsigned long args[], unsigned long ret[] ) +{ +	extern unsigned long get_timer_freq(); +	static unsigned long mticks=0, usecs=0; +	unsigned long t; + +	asm volatile("mftb %0" : "=r" (t) : ); +	if( mticks ) +		usecs += get_timer_freq() / 1000000 * ( 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, "/cpu@0" ); +DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" ); + + +/* ( phys size align --- base ) */ +static void +mem_claim( void ) +{ +	int align = POP(); +	int size = POP(); +	int phys = POP(); +	int 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 ) +{ +	int align = POP(); +	int size = POP(); +	int phys = POP(); +	int 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 ) +{ +	int mode = POP(); +	int size = POP(); +	int virt = POP(); +	int phys = POP(); +	int 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 ) +{ +	int align = POP(); +	int size = POP(); +	int virt = POP(); +	int 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 ) +{ +#ifdef CONFIG_RTAS +	REGISTER_NODE( rtas ); +#endif +	REGISTER_NODE( vfd_stdout ); +	REGISTER_NODE( ciface ); +	REGISTER_NODE( memory ); +	REGISTER_NODE( mmu ); +	REGISTER_NODE( mmu_ciface ); +	REGISTER_NODE( tty ); +} diff --git a/roms/openbios/arch/ppc/briq/tree.c b/roms/openbios/arch/ppc/briq/tree.c new file mode 100644 index 00000000..17718388 --- /dev/null +++ b/roms/openbios/arch/ppc/briq/tree.c @@ -0,0 +1,23 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<tree.c> + * + *	device tree setup + * + *   Copyright (C) 2004 Greg Watson + * + *   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" + +void devtree_init( void ) +{ +	fword("init-briq-tree"); +} diff --git a/roms/openbios/arch/ppc/briq/tree.fs b/roms/openbios/arch/ppc/briq/tree.fs new file mode 100644 index 00000000..ae503266 --- /dev/null +++ b/roms/openbios/arch/ppc/briq/tree.fs @@ -0,0 +1,305 @@ +\   briq specific initialization code +\  +\   Copyright (C) 2004 Greg Watson +\  +\   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 +\  + +\ ------------------------------------------------------------- +\ device-tree +\ ------------------------------------------------------------- + +" /" find-device + +" chrp" device-type +" TotalImpact,BRIQ-1" model +h# 80000000 encode-int " isa-io-base" property +1 encode-int " #interrupt-cells" property +1 encode-int " #size-cells" property + +new-device +	" memory" device-name +	" memory" device-type +	0 encode-int h# 1E00000 encode-int encode+ +	h# 2000000 encode-int encode+ h# 40000000 encode-int encode+  +	  " available" property +	0 h# 40000000 reg +	external +	: open true ; +	: close ; +finish-device + +new-device +	" cpu" device-name +	" cpu" device-type +	" " encode-string " translations" property +	0 encode-phys h# 8000000 encode-int encode+ " available" property +	d# 32 encode-int " d-cache-block-size" property +	8 encode-int " d-cache-sets" property +	d# 32768 encode-int " d-cache-size" property +	d# 32 encode-int " i-cache-block-size" property +	8 encode-int " i-cache-sets" property +	d# 32768 encode-int " i-cache-size" property +	" " encode-string " cache-unified" property +	2 encode-int " i-tlb-sets" property +	d# 128 encode-int " i-tlb-size" property +	2 encode-int " d-tlb-sets" property +	d# 128 encode-int " d-tlb-size" property +	" " encode-string " tlb-split" property +	2 encode-int " tlb-sets" property +	d# 256 encode-int " tlb-size" property +	" " encode-string " performance-monitor" property +	" " encode-string " graphics" property +	4 encode-int " reservation-granule-size" property +        d# 25000000 encode-int " timebase-frequency" property +        d# 300000000 encode-int " clock-frequency" property +        d# 66000000 encode-int " bus-frequency" property +        h# 88201 encode-int " cpu-version" property +	0 encode-int " reg" property +finish-device + +" /pci" find-device +	h# 01000000 encode-int 0 encode-int encode+ 0 encode-int encode+ +	  h# 80000000 encode-int encode+ 0 encode-int encode+  +	  h# 01000000 encode-int encode+  +	h# 02000000 encode-int encode+ 0 encode-int encode+ 0 encode-int encode+  +	  h# C0000000 encode-int encode+ 0 encode-int encode+  +	  h# 08000000 encode-int encode+  +	" ranges" property +	" IBM,CPC710" model +	h# FF5F7700 encode-int " 8259-interrupt-acknowledge" property +	h# 0000F800 encode-int 0 encode-int encode+ 0 encode-int encode+  +	  7 encode-int encode+ +	  " interrupt-map-mask" property +	1 encode-int " #interrupt-cells" property +	h# 80000000 encode-int " system-dma-base" property +	d# 33333333 encode-int " clock-frequency" property +	" " encode-string " primary-bridge" property +	0 encode-int " pci-bridge-number" property +	h# FF500000 encode-int h# 100000 encode-int encode+ " reg" property +	0 encode-int 0 encode-int encode+ " bus-range" property + +new-device +  " isa" device-name +  " isa" device-type +	2 encode-int " #address-cells" property +	1 encode-int " #size-cells" property + +  external +  : open true ; +  : close ; + +finish-device + +: ?devalias ( alias-str alias-len device-str device-len -- +  \		alias-str alias-len false | true ) +  active-package >r +  " /aliases" find-device +  \ 2dup ." Checking " type +  2dup find-dev if     \ check if device exists +    drop +    2over find-dev if  \ do we already have an alias? +      \ ." alias exists" cr +      drop 2drop false +    else +      \ ." device exists" cr +      encode-string +      2swap property +      true +    then +  else +    \ ." device doesn't exist" cr +    2drop false +  then +  r> active-package! +  ; + +:noname +  " hd" +  " /pci/pci-ata/ata-1/disk@0" ?devalias not if +    " /pci/pci-ata/ata-1/disk@1" ?devalias not if +      " /pci/pci-ata/ata-2/disk@0" ?devalias not if +        " /pci/pci-ata/ata-2/disk@1" ?devalias not if +	  2drop ." No disk found." cr +	then +      then +    then +  then + +  " cdrom" +  " /pci/pci-ata/ata-1/cdrom@0" ?devalias not if +    " /pci/pci-ata/ata-1/cdrom@1" ?devalias not if +      " /pci/pci-ata/ata-2/cdrom@0" ?devalias not if +        " /pci/pci-ata/ata-2/cdrom@1" ?devalias not if +	  2drop ." No cdrom found" cr +	then +      then +    then +  then +; SYSTEM-initializer + +new-device +	" ide" device-name +	" ide" device-type +	" WINBOND,82C553" model +	h# 28 encode-int " max-latency" property +	h# 2 encode-int " min-grant" property +	h# 1 encode-int " devsel-speed" property +	h# 0 encode-int " subsystem-vendor-id" property +	h# 0 encode-int " subsystem-id" property +	h# 1018A encode-int " class-code" property +	h# 5 encode-int " revision-id" property +	h# 105 encode-int " device-id" property +	h# 10AD encode-int " vendor-id" property +	h# 1003110 encode-int 0 encode-int encode+ h# 10020 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  h# 1003114 encode-int 0 encode-int encode+ h# 10030 encode-int encode+ +	  h# 4 encode-int encode+ 0 encode-int encode+ +	  h# 1003118 encode-int 0 encode-int encode+ h# 10040 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  h# 100311C encode-int 0 encode-int encode+ h# 10034 encode-int encode+ +	  h# 4 encode-int encode+ 0 encode-int encode+ +	  h# 1003120 encode-int 0 encode-int encode+ h# 10050 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  h# 1003124 encode-int 0 encode-int encode+ h# 10060 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  " assigned-addresses" property +	h# 3100 encode-int 0 encode-int encode+ 0 encode-int encode+ +	  0 encode-int encode+ 0 encode-int encode+ +	  h# 1003110 encode-int 0 encode-int encode+ h# 0 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  h# 1003114 encode-int 0 encode-int encode+ h# 0 encode-int encode+ +	  h# 4 encode-int encode+ 0 encode-int encode+ +	  h# 1003118 encode-int 0 encode-int encode+ h# 0 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  h# 100311C encode-int 0 encode-int encode+ h# 0 encode-int encode+ +	  h# 4 encode-int encode+ 0 encode-int encode+ +	  h# 1003120 encode-int 0 encode-int encode+ h# 0 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  h# 1003124 encode-int 0 encode-int encode+ h# 0 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  " reg" property +finish-device + +new-device +	" ethernet" device-name +	" network" device-type +	" AMD,79C973" model +	h# 3800 encode-int 0 encode-int encode+ 0 encode-int encode+ +	  0 encode-int encode+ 0 encode-int encode+ +	  " reg" property +finish-device + +" /pci/isa" find-device +	0 0 " assigned-addresses" property +	0 0 " ranges" property +	0 encode-int " slot-names" property +	d# 8333333 encode-int " clock-frequency" property +	0 encode-int " eisa-slots" property +	2 encode-int " #interrupt-cells" property +	" W83C553F" encode-string " compatible" property +	" WINBOND,82C553" model +	0 encode-int " max-latency" property +	0 encode-int " min-grant" property +	1 encode-int " devsel-speed" property +	0 encode-int " subsystem-vendor-id" property +	0 encode-int " subsystem-id" property +	h# 60100 encode-int " class-code" property +	h# 10 encode-int " revision-id" property +	h# 565 encode-int " device-id" property +	h# 10AD encode-int " vendor-id" property +	h# 3000 encode-int 0 encode-int encode+ 0 encode-int encode+ +	  0 encode-int encode+ 0 encode-int encode+ " reg" property + +new-device +	" rtc" device-name +	" rtc" device-type +	" DS17285S" model +	" MC146818" encode-string +	" DS17285S" encode-string encode+ +	" pnpPNP,b00" encode-string encode+ " compatible" property +	8 encode-int 0 encode-int encode+ " interrupts" property +	h# 70 encode-int 1 encode-int encode+ +	  2 encode-int encode+ " reg" property +finish-device + +new-device +	" interrupt-controller" device-name +	" interrupt-controller" device-type +	" 8259" model +	" " encode-string " interrupt-controller" property +	2 encode-int " #interrupt-cells" property +	1 encode-int  +	2 encode-int encode+ +	3 encode-int encode+ +	6 encode-int encode+ +	  " reserved-interrupts" property +	" 8259" encode-string +	  " chrp,iic" encode-string encode+  +	  " compatible" property +	h# 20 encode-int 1 encode-int encode+ +	  2 encode-int encode+ " reg" property +finish-device + +new-device +	" serial" device-name +	" serial" device-type +	" no" encode-string " ctsrts" property +	" no" encode-string " xon" property +	" no" encode-string " parity" property +	d# 115200 encode-int " bps" property +	1 encode-int " stop-bits" property +	8 encode-int " data-bits" property +	h# 70800 encode-int " divisor" property +	h# 708000 encode-int " clock-frequency" property +	4 encode-int 0 encode-int encode+ " interrupts" property +	h# 3F8 encode-int 1 encode-int encode+ +	  8 encode-int encode+ " reg" property +finish-device + +" /pci" find-device +	" /pci/isa/interrupt-controller" find-dev if  +		encode-int " interrupt-parent" property  +	then +	h# 3800 encode-int 0 encode-int encode+  +	  0 encode-int encode+ 1 encode-int encode+ +	  " /pci/isa/interrupt-controller" find-dev if  +		encode-int encode+ +	  then +	  h# 0C encode-int encode+ 1 encode-int encode+ +	  " interrupt-map" property + +" /pci/isa" find-device +	" /pci/isa/interrupt-controller" find-dev if  +		encode-int " interrupt-parent" property  +	then + +\ ------------------------------------------------------------- +\ /packages +\ ------------------------------------------------------------- + +" /packages" find-device + +	" packages" device-name +	external +	\ allow packages to be opened with open-dev +	: open true ; +	: close ; + +\ /packages/terminal-emulator +new-device +	" terminal-emulator" device-name +	external +	: open true ; +	: close ; +	\ : write ( addr len -- actual ) +	\	dup -rot type +	\ ; +finish-device + +\ ------------------------------------------------------------- +\ The END +\ ------------------------------------------------------------- +device-end diff --git a/roms/openbios/arch/ppc/briq/vfd.c b/roms/openbios/arch/ppc/briq/vfd.c new file mode 100644 index 00000000..ffc87a07 --- /dev/null +++ b/roms/openbios/arch/ppc/briq/vfd.c @@ -0,0 +1,42 @@ +/* + *   Creation Date: <2004/08/28 17:29:43 greg> + *   Time-stamp: <2004/08/28 17:29:43 greg> + * + *	<vfd.c> + * + *	Simple text console + * + *   Copyright (C) 2004 Greg Watson + * + *   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 "briq/briq.h" + +static int vfd_is_open; + +static int +vfd_init( void ) +{ +	vfd_is_open = 1; +	return 0; +} + +void +vfd_close( void ) +{ +} + +int +vfd_draw_str( const char *str ) +{ +	if (!vfd_is_open) +		vfd_init(); + +	return 0; +} diff --git a/roms/openbios/arch/ppc/build.xml b/roms/openbios/arch/ppc/build.xml new file mode 100644 index 00000000..29f6601f --- /dev/null +++ b/roms/openbios/arch/ppc/build.xml @@ -0,0 +1,211 @@ +<?xml version="1.0"?> +<build condition="PPC"> + + <dictionary name="openbios-briq" init="openbios" target="forth" condition="BRIQ"> +  <object source="ppc.fs"/> +  <object source="briq/tree.fs"/> +  <object source="briq/briq.fs"/> +  <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/> + </dictionary> + +  <dictionary name="openbios-pearpc" init="openbios" target="forth" condition="PEARPC"> +  <object source="ppc.fs"/> +  <object source="pearpc/tree.fs"/> +  <object source="pearpc/pearpc.fs"/> +  <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/> + </dictionary> + +  <dictionary name="openbios-qemu" init="openbios" target="forth" condition="QEMU"> +  <object source="ppc.fs"/> +  <object source="qemu/tree.fs"/> +  <object source="qemu/qemu.fs"/> +  <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/> + </dictionary> + + <dictionary name="openbios-mol" init="openbios" target="forth" condition="MOL"> +  <object source="ppc.fs"/> +  <object source="mol/tree.fs"/> +  <object source="mol/mol.fs"/> +  <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/> + </dictionary> + + <!-- HACK ALERT --> + + <executable name="target/include/briq-dict.h" target="target" condition="BRIQ"> +  <rule><![CDATA[ +	$(call quiet-command,true, "  GEN   $(TARGET_DIR)$@") +	@echo "static const char forth_dictionary[] = {" > $@ +	@cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \ +					| sed 's/0x  ,//g' >> $@ +	@echo "};" >> $@]]></rule> +  <external-object source="openbios-briq.dict"/> + </executable> + + <executable name="target/arch/ppc/briq/kernel.o" target="target" condition="BRIQ"> +  <rule><![CDATA[ $(SRCDIR)/arch/ppc/briq/kernel.c $(ODIR)/target/include/static-dict.h +	$(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/briq/kernel.c, "  CC    $(TARGET_DIR)$@")]]></rule> + </executable> + + + <executable name="target/include/pearpc-dict.h" target="target" condition="PEARPC"> +  <rule><![CDATA[ +	$(call quiet-command,true, "  GEN   $(TARGET_DIR)$@") +	@echo "static const char forth_dictionary[] = {" > $@ +	@cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \ +					| sed 's/0x  ,//g' >> $@ +	@echo "};" >> $@]]></rule> +  <external-object source="openbios-pearpc.dict"/> + </executable> + + <executable name="target/arch/ppc/pearpc/kernel.o" target="target" condition="PEARPC"> +  <rule><![CDATA[ $(SRCDIR)/arch/ppc/pearpc/kernel.c $(ODIR)/target/include/pearpc-dict.h +	$(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/pearpc/kernel.c, "  CC    $(TARGET_DIR)$@")]]></rule> + </executable> + + <executable name="target/include/qemu-dict.h" target="target" condition="QEMU"> +  <rule><![CDATA[ +	$(call quiet-command,$(ODIR)/forthstrap -x -D $@ -d $< </dev/null, "  GEN   $(TARGET_DIR)$@")]]></rule> +  <external-object source="openbios-qemu.dict"/> + </executable> + + <executable name="target/arch/ppc/qemu/kernel.o" target="target" condition="QEMU"> +  <rule><![CDATA[ $(SRCDIR)/arch/ppc/qemu/kernel.c $(ODIR)/target/include/qemu-dict.h +	$(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/qemu/kernel.c, "  CC    $(TARGET_DIR)$@")]]></rule> + </executable> + + + <executable name="target/include/mol-dict.h" target="target" condition="MOL"> +  <rule><![CDATA[ +	$(call quiet-command,true, "  GEN   $(TARGET_DIR)$@") +	@echo "static const char forth_dictionary[] = {" > $@ +	@cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \ +					| sed 's/0x  ,//g' >> $@ +	@echo "};" >> $@]]></rule> +  <external-object source="openbios-mol.dict"/> + </executable> + + <executable name="target/arch/ppc/mol/kernel.o" target="target" condition="MOL"> +  <rule><![CDATA[ +	$(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/mol/kernel.c, "  CC    $(TARGET_DIR)$@")]]></rule> + </executable> + + <!-- END OF HACK ALERT --> + + <library name="briq" target="target" type="static" condition="BRIQ"> +  <object source="misc.S"/> +  <object source="ofmem.c"/> +  <object source="briq/briq.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="briq/init.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <external-object source="target/arch/ppc/briq/kernel.o"/> +  <object source="briq/main.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="briq/methods.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="briq/tree.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="briq/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/> + </library> + + <library name="pearpc" target="target" type="static" condition="PEARPC"> +  <object source="misc.S"/> +  <object source="ofmem.c"/> +  <object source="pearpc/pearpc.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="pearpc/init.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <external-object source="target/arch/ppc/pearpc/kernel.o"/> +  <object source="pearpc/main.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="pearpc/methods.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="pearpc/tree.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="pearpc/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <!-- taken from mol: generalize --> +  <object source="pearpc/console.c" flags="-I$(SRCDIR)/arch/ppc"/> + </library> + + <library name="qemu" target="target" type="static" condition="QEMU"> +  <object source="qemu/ofmem.c"/> +  <object source="qemu/qemu.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="qemu/init.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <external-object source="target/arch/ppc/qemu/kernel.o"/> +  <object source="qemu/main.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="qemu/methods.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="qemu/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="qemu/console.c" flags="-I$(SRCDIR)/arch/ppc"/> + </library> + + <library name="mol" target="target" type="static" condition="MOL"> +  <object source="misc.S"/> +  <object source="ofmem.c"/> +  <object source="mol/init.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="mol/main.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="mol/mol.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="mol/console.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="mol/osi-blk.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="mol/osi-scsi.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="mol/pseudodisk.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="mol/methods.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="mol/prom.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <object source="mol/tree.c" flags="-I$(SRCDIR)/arch/ppc"/> +  <external-object source="target/arch/ppc/mol/kernel.o"/> + </library> + + <executable name="openbios-briq.elf" target="target" condition="BRIQ"> +  <rule> +	$(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^,"  LINK  $(TARGET_DIR)$@") +	$(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-briq.syms,"  GEN   $(TARGET_DIR)$@.syms") +	$(call quiet-command,$(STRIP) $@.nostrip -o $@,"  STRIP $(TARGET_DIR)$@")</rule> +  <object source="start.S"/> +  <object source="timebase.S"/> +  <external-object source="libbriq.a"/> +  <external-object source="libbootstrap.a"/> +  <external-object source="libopenbios.a"/> +  <external-object source="libpackages.a"/> +  <external-object source="libdrivers.a"/> +  <external-object source="libfs.a"/> +  <external-object source="liblibc.a"/> + </executable> + + <executable name="openbios-pearpc.elf" target="target" condition="PEARPC"> +  <rule> +	$(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^,"  LINK  $(TARGET_DIR)$@") +	$(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-pearpc.syms,"  GEN   $(TARGET_DIR)$@.syms") +	$(call quiet-command,$(STRIP) $@.nostrip -o $@,"  STRIP $(TARGET_DIR)$@")</rule> +  <object source="start.S"/> +  <object source="timebase.S"/> +  <external-object source="libpearpc.a"/> +  <external-object source="libbootstrap.a"/> +  <external-object source="libopenbios.a"/> +  <external-object source="libpackages.a"/> +  <external-object source="libdrivers.a"/> +  <external-object source="libfs.a"/> +  <external-object source="liblibc.a"/> + </executable> + + <executable name="openbios-qemu.elf" target="target" condition="QEMU"> +  <rule> +	$(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/$(ARCH)/qemu/ldscript -o $@.nostrip --whole-archive $^,"  LINK  $(TARGET_DIR)$@") +	$(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-qemu.syms,"  GEN   $(TARGET_DIR)$@.syms") +	$(call quiet-command,$(STRIP) $@.nostrip -o $@,"  STRIP $(TARGET_DIR)$@")</rule> +  <object source="qemu/start.S"/> +  <object source="timebase.S"/> +  <external-object source="libqemu.a"/> +  <external-object source="libbootstrap.a"/> +  <external-object source="libopenbios.a"/> +  <external-object source="libpackages.a"/> +  <external-object source="libdrivers.a"/> +  <external-object source="libfs.a"/> +  <external-object source="liblibc.a"/> +  <external-object source="libgcc.a"/> + </executable> + + <executable name="openbios-mol.elf" target="target" condition="MOL"> +  <rule> +	$(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^,"  LINK  $(TARGET_DIR)$@") +	$(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-mol.syms,"  GEN   $(TARGET_DIR)$@.syms") +	$(call quiet-command,$(STRIP) $@.nostrip -o $@,"  STRIP $(TARGET_DIR)$@")</rule> +  <object source="start.S"/> +  <external-object source="libmol.a"/> +  <external-object source="libbootstrap.a"/> +  <external-object source="libopenbios.a"/> +  <external-object source="libpackages.a"/> +  <external-object source="libdrivers.a"/> +  <external-object source="libfs.a"/> +  <external-object source="liblibc.a"/> + </executable> + +</build> diff --git a/roms/openbios/arch/ppc/defconfig b/roms/openbios/arch/ppc/defconfig new file mode 100644 index 00000000..adfb181e --- /dev/null +++ b/roms/openbios/arch/ppc/defconfig @@ -0,0 +1,48 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_PPC=y +CONFIG_MOL=y +# CONFIG_MPC107 is not set +# CONFIG_NO_ARCH is not set + +# +# Build hosted UNIX Binary +# +CONFIG_HOST_UNIX=y +# CONFIG_PLUGIN_PCI is not set + +# +# Kernel Debugging +# +CONFIG_DEBUG=y +CONFIG_DEBUG_BOOT=y +# CONFIG_DEBUG_DSTACK is not set +# CONFIG_DEBUG_RSTACK is not set +# CONFIG_DEBUG_DICTIONARY is not set +# CONFIG_DEBUG_INTERNAL is not set +# CONFIG_DEBUG_INTERPRETER is not set +CONFIG_DEBUG_CONSOLE=y +CONFIG_DEBUG_CONSOLE_SERIAL=y +CONFIG_SERIAL_PORT=1 +CONFIG_SERIAL_SPEED=115200 +CONFIG_DEBUG_CONSOLE_VGA=y + +# +# Packages +# +# CONFIG_PKG_DEBLOCKER is not set +# CONFIG_PKG_DISKLABEL is not set +# CONFIG_PKG_OBP_TFTP is not set +# CONFIG_PKG_TERMINAL_EMULATOR is not set + +# +# Module Configuration +# +CONFIG_DEBLOCKER=y +CONFIG_DISK_LABEL=y +CONFIG_PART_SUPPORT=y +CONFIG_MAC_PARTS=y +CONFIG_FS=y +CONFIG_HFS=y +CONFIG_HFSP=y diff --git a/roms/openbios/arch/ppc/kernel.c b/roms/openbios/arch/ppc/kernel.c new file mode 100644 index 00000000..28f2965b --- /dev/null +++ b/roms/openbios/arch/ppc/kernel.c @@ -0,0 +1,99 @@ +/* + *   Creation Date: <2003/10/25 14:07:17 samuel> + *   Time-stamp: <2004/08/28 17:48:19 stepan> + * + *	<kernel.c> + * + *   Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + *   Copyright (C) 2003, 2004 Stefan Reinauer + * + *   Based upon unix.c (from OpenBIOS): + * + *   Copyright (C) 2003 Patrick Mauritz, 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 "config.h" +#include "dict.h" +#include "libopenbios/bindings.h" +#include "kernel/stack.h" +#include "kernel/kernel.h" +#include "libc/string.h" +#include "kernel.h" + +#define MEMORY_SIZE	(256*1024)	/* 256K ram for hosted system */ +#define DICTIONARY_SIZE	(512*1024)	/* 512K for the dictionary   */ + +static ucell 		*memory; + +/************************************************************************/ +/*	F U N C T I O N S						*/ +/************************************************************************/ + +int +forth_segv_handler( char *segv_addr ) +{ +	ucell addr = 0xdeadbeef; + +	if( PC >= (ucell) dict && PC <= (ucell) dict + dicthead ) +		addr = *(ucell *) PC; + +	printk("panic: segmentation violation at %x\n", (int)segv_addr); +	printk("dict=0x%x here=0x%x(dict+0x%x) pc=0x%x(dict+0x%x)\n", +	       (int)dict, (int)(dict + dicthead), dicthead, +	       PC, PC - (ucell) dict); +	printk("dstackcnt=%d rstackcnt=%d instruction=%x\n", +	       dstackcnt, rstackcnt, addr); + +#ifdef DEBUG_DSTACK +	printdstack(); +#endif +#ifdef DEBUG_RSTACK +	printrstack(); +#endif +	return -1; +} + +/* + * allocate memory and prepare engine for memory management. + */ + +static void +init_memory( void ) +{ +	memory = malloc(MEMORY_SIZE); +	if( !memory ) +		panic("panic: not enough memory on host system.\n"); + +	/* we push start and end of memory to the stack +	 * so that it can be used by the forth word QUIT +	 * to initialize the memory allocator +	 */ + +	PUSH( (ucell)memory ); +	PUSH( (ucell)memory + MEMORY_SIZE ); +} + +int +initialize_forth( void ) +{ +	dict = malloc(DICTIONARY_SIZE); +	load_dictionary( forth_dictionary, sizeof(forth_dictionary) ); +	forth_init(); + +	PUSH_xt( bind_noname_func(arch_of_init) ); +	fword("PREPOST-initializer"); + +	PC = (ucell)findword("initialize-of"); +	if( PC ) { +		init_memory(); +		enterforth((xt_t)PC); +		free( memory ); +	} +	free( dict ); +	return 0; +} diff --git a/roms/openbios/arch/ppc/kernel.h b/roms/openbios/arch/ppc/kernel.h new file mode 100644 index 00000000..20cda489 --- /dev/null +++ b/roms/openbios/arch/ppc/kernel.h @@ -0,0 +1,41 @@ +/* + *   Creation Date: <2004/08/28 17:50:12 stepan> + *   Time-stamp: <2004/08/28 17:50:12 stepan> + * + *	<kernel.h> + * + *   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 + * + */ + +#ifndef __KERNEL_H__ +#define __KERNEL_H__ + +/* misc.c */ +extern void		fatal_error( const char *str ); +extern void		exit( int status ); + +/* start.S */ +extern void 		flush_icache_range( char *start, char *stop ); +extern char		of_rtas_start[], of_rtas_end[]; + +/* methods.c */ +extern void		node_methods_init( void ); + +/* main.c */ +extern void 		boot( void ); + +/* init.c */ +extern void		entry( void ); +extern void 		arch_of_init( void ); +extern int		get_bool_res( const char *str ); + +/* tree.c */ +extern void		devtree_init( void ); + + +#endif   /* __KERNEL_H__ */ diff --git a/roms/openbios/arch/ppc/misc.S b/roms/openbios/arch/ppc/misc.S new file mode 100644 index 00000000..435ce0ec --- /dev/null +++ b/roms/openbios/arch/ppc/misc.S @@ -0,0 +1,74 @@ +/* + *   Creation Date: <2002/10/20 15:54:50 samuel> + *   Time-stamp: <2002/10/20 15:57:21 samuel> + * + *	<misc.S> + * + *	Low-level stuff + * + *   Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + *   Based upon misc.S from the the linux kernel with the following + *   copyrights: + * + *   Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org), + *   Cort Dougan (cort@cs.nmt.edu), Paul Mackerras + * + *   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 "asm/asmdefs.h" +#include "asm/processor.h" + + +/* + * Extended precision shifts. + * + * Updated to be valid for shift counts from 0 to 63 inclusive. + * -- Gabriel + * + * R3/R4 has 64 bit value + * R5    has shift count + * result in R3/R4 + * + *  ashrdi3: arithmetic right shift (sign propagation) + *  lshrdi3: logical right shift + *  ashldi3: left shift + */ +GLOBL(__ashrdi3): +	subfic	r6,r5,32 +	srw	r4,r4,r5	# LSW = count > 31 ? 0 : LSW >> count +	addi	r7,r5,32	# could be xori, or addi with -32 +	slw	r6,r3,r6	# t1 = count > 31 ? 0 : MSW << (32-count) +	rlwinm	r8,r7,0,32	# t3 = (count < 32) ? 32 : 0 +	sraw	r7,r3,r7	# t2 = MSW >> (count-32) +	or	r4,r4,r6	# LSW |= t1 +	slw	r7,r7,r8	# t2 = (count < 32) ? 0 : t2 +	sraw	r3,r3,r5	# MSW = MSW >> count +	or	r4,r4,r7	# LSW |= t2 +	blr + +GLOBL(__ashldi3): +	subfic	r6,r5,32 +	slw	r3,r3,r5	# MSW = count > 31 ? 0 : MSW << count +	addi	r7,r5,32	# could be xori, or addi with -32 +	srw	r6,r4,r6	# t1 = count > 31 ? 0 : LSW >> (32-count) +	slw	r7,r4,r7	# t2 = count < 32 ? 0 : LSW << (count-32) +	or	r3,r3,r6	# MSW |= t1 +	slw	r4,r4,r5	# LSW = LSW << count +	or	r3,r3,r7	# MSW |= t2 +	blr + +GLOBL(__lshrdi3): +	subfic	r6,r5,32 +	srw	r4,r4,r5	# LSW = count > 31 ? 0 : LSW >> count +	addi	r7,r5,32	# could be xori, or addi with -32 +	slw	r6,r3,r6	# t1 = count > 31 ? 0 : MSW << (32-count) +	srw	r7,r3,r7	# t2 = count < 32 ? 0 : MSW >> (count-32) +	or	r4,r4,r6	# LSW |= t1 +	srw	r3,r3,r5	# MSW = MSW >> count +	or	r4,r4,r7	# LSW |= t2 +	blr diff --git a/roms/openbios/arch/ppc/mmutypes.h b/roms/openbios/arch/ppc/mmutypes.h new file mode 100644 index 00000000..441d7f8b --- /dev/null +++ b/roms/openbios/arch/ppc/mmutypes.h @@ -0,0 +1,76 @@ +/* + *   Creation Date: <2002/01/13 13:53:14 samuel> + *   Time-stamp: <2002/01/27 19:56:11 samuel> + * + *	<mmutypes.h> + * + *	MMU definitions + * + *   Most of these declarations originate from the Linux Kernel + * + *   Copyright (C) 2002 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_MMUTYPES +#define _H_MMUTYPES + +/* Hardware Page Table Entry */ +typedef struct mPTE { +	unsigned long v:1;	/* Entry is valid */ +	unsigned long vsid:24;	/* Virtual segment identifier */ +	unsigned long h:1;	/* Hash algorithm indicator */ +	unsigned long api:6;	/* Abbreviated page index */ + +	unsigned long rpn:20;	/* Real (physical) page number */ +	unsigned long    :3;	/* Unused */ +	unsigned long r:1;	/* Referenced */ +	unsigned long c:1;	/* Changed */ +	unsigned long w:1;	/* Write-thru cache mode */ +	unsigned long i:1;	/* Cache inhibited */ +	unsigned long m:1;	/* Memory coherence */ +	unsigned long g:1;	/* Guarded */ +	unsigned long  :1;	/* Unused */ +	unsigned long pp:2;	/* Page protection */ +} mPTE_t; + + +typedef struct _mBATU {		/* Upper part of BAT (all except 601) */ +        unsigned long bepi:15;	/* Effective page index (virtual address) */ +        unsigned long :4;	/* Unused */ +        unsigned long bl:11;	/* Block size mask */ +        unsigned long vs:1;	/* Supervisor valid */ +        unsigned long vp:1;	/* User valid */ +} mBATU; + +typedef struct _mBATL {		/* Lower part of BAT (all except 601) */ +        unsigned long brpn:15;	/* Real page index (physical address) */ +        unsigned long :10;	/* Unused */ +        unsigned long w:1;	/* Write-thru cache */ +        unsigned long i:1;	/* Cache inhibit */ +        unsigned long m:1;	/* Memory coherence */ +        unsigned long g:1;	/* Guarded (MBZ in IBAT) */ +        unsigned long :1;	/* Unused */ +        unsigned long pp:2;	/* Page access protections */ +} mBATL; + +typedef struct _mBAT { +        mBATU batu;		/* Upper register */ +        mBATL batl;		/* Lower register */ +} mBAT; + +typedef struct _mSEGREG { +        unsigned long t:1;      /* Normal or I/O  type */ +        unsigned long ks:1;     /* Supervisor 'key' (normally 0) */ +        unsigned long kp:1;     /* User 'key' (normally 1) */ +        unsigned long n:1;      /* No-execute */ +        unsigned long :4;       /* Unused */ +        unsigned long vsid:24;  /* Virtual Segment Identifier */ +} mSEGREG; + + +#endif   /* _H_MMUTYPES */ diff --git a/roms/openbios/arch/ppc/mol/console.c b/roms/openbios/arch/ppc/mol/console.c new file mode 100644 index 00000000..966011e1 --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/init.c b/roms/openbios/arch/ppc/mol/init.c new file mode 100644 index 00000000..15333b4e --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/kernel.c b/roms/openbios/arch/ppc/mol/kernel.c new file mode 100644 index 00000000..1454b8a8 --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/main.c b/roms/openbios/arch/ppc/mol/main.c new file mode 100644 index 00000000..f6ed934d --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/methods.c b/roms/openbios/arch/ppc/mol/methods.c new file mode 100644 index 00000000..bfaf5150 --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/mol.c b/roms/openbios/arch/ppc/mol/mol.c new file mode 100644 index 00000000..86b3b66b --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/mol.fs b/roms/openbios/arch/ppc/mol/mol.fs new file mode 100644 index 00000000..10c99bd7 --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/mol.h b/roms/openbios/arch/ppc/mol/mol.h new file mode 100644 index 00000000..cea15a35 --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/osi-blk.c b/roms/openbios/arch/ppc/mol/osi-blk.c new file mode 100644 index 00000000..4ed1b5ab --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/osi-scsi.c b/roms/openbios/arch/ppc/mol/osi-scsi.c new file mode 100644 index 00000000..18f3dc57 --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/prom.c b/roms/openbios/arch/ppc/mol/prom.c new file mode 100644 index 00000000..0bc8bcfb --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/prom.h b/roms/openbios/arch/ppc/mol/prom.h new file mode 100644 index 00000000..54a856c2 --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/pseudodisk.c b/roms/openbios/arch/ppc/mol/pseudodisk.c new file mode 100644 index 00000000..a98e5484 --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/tree.c b/roms/openbios/arch/ppc/mol/tree.c new file mode 100644 index 00000000..b82c8c2c --- /dev/null +++ b/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/roms/openbios/arch/ppc/mol/tree.fs b/roms/openbios/arch/ppc/mol/tree.fs new file mode 100644 index 00000000..228163ff --- /dev/null +++ b/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 diff --git a/roms/openbios/arch/ppc/ofmem.c b/roms/openbios/arch/ppc/ofmem.c new file mode 100644 index 00000000..c9b066ed --- /dev/null +++ b/roms/openbios/arch/ppc/ofmem.c @@ -0,0 +1,308 @@ +/* + *   Creation Date: <1999/11/07 19:02:11 samuel> + *   Time-stamp: <2004/01/07 19:42:36 samuel> + * + *	<ofmem.c> + * + *	OF Memory manager + * + *   Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se) + *   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 + *   as published by the Free Software Foundation + * + */ + +/* TODO: Clean up MOLisms in a decent way */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "libopenbios/ofmem.h" +#include "kernel.h" +#ifdef I_WANT_MOLISMS +#include "mol/prom.h" +#include "mol/mol.h" +#endif +#include "mmutypes.h" +#include "asm/processor.h" +#ifdef I_WANT_MOLISMS +#include "osi_calls.h" +#endif + +#define BIT(n)		(1U<<(31-(n))) + +/* called from assembly */ +extern void	dsi_exception( void ); +extern void	isi_exception( void ); +extern void	setup_mmu( unsigned long code_base, unsigned long code_size, unsigned long ramsize ); + +/**************************************************************** + * Memory usage (before of_quiesce is called) + * + *			Physical + * + *	0x00000000	Exception vectors + *	0x00004000	Free space + *	0x01e00000	Open Firmware (us) + *	0x01f00000	OF allocations + *	0x01ff0000	PTE Hash + *	0x02000000-	Free space + * + * Allocations grow downwards from 0x01e00000 + * + ****************************************************************/ + +#define HASH_SIZE		(2 << 15) +#define SEGR_BASE		0x400		/* segment number range to use */ + +#define FREE_BASE_1		0x00004000 +#define OF_CODE_START		0x01e00000 +/* #define OF_MALLOC_BASE	0x01f00000 */ +extern char _end[]; +#define OF_MALLOC_BASE		_end + +#define HASH_BASE		(0x02000000 - HASH_SIZE) +#define FREE_BASE_2		0x02000000 + +#define RAMSIZE			0x02000000	/* XXXXXXXXXXXXXXXXXXX FIXME XXXXXXXXXXXXXXX */ + +static ofmem_t s_ofmem; + +#define IO_BASE			0x80000000 +#define OFMEM (&s_ofmem) + +static inline unsigned long +get_hash_base( void ) +{ +	return HASH_BASE; +} + +static inline unsigned long +get_hash_size( void ) +{ +	return HASH_SIZE; +} + +static ucell get_heap_top( void ) +{ +	return HASH_BASE; +} + +static inline size_t ALIGN_SIZE(size_t x, size_t a) +{ +    return (x + a - 1) & ~(a-1); +} + +ofmem_t* ofmem_arch_get_private(void) +{ +	return OFMEM; +} + +void* ofmem_arch_get_malloc_base(void) +{ +	return OF_MALLOC_BASE; +} + +ucell ofmem_arch_get_heap_top(void) +{ +	return get_heap_top(); +} + +ucell ofmem_arch_get_virt_top(void) +{ +	return IO_BASE; +} + +void ofmem_arch_unmap_pages(ucell virt, ucell size) +{ +	/* kill page mappings in provided range */ +} + +void ofmem_arch_map_pages(ucell phys, ucell virt, ucell size, ucell mode) +{ +	/* none yet */ +} + +/************************************************************************/ +/*	OF private allocations						*/ +/************************************************************************/ + +void * +malloc( int size ) +{ +	return ofmem_malloc(size); +} + +void +free( void *ptr ) +{ +	return ofmem_free(ptr); +} + +void * +realloc( void *ptr, size_t size ) +{ +	return ofmem_realloc(ptr, size); +} + + +/************************************************************************/ +/*	misc								*/ +/************************************************************************/ + +ucell ofmem_arch_default_translation_mode( ucell phys ) +{ +	/* XXX: Guard bit not set as it should! */ +	if( phys < IO_BASE || phys >= 0xffc00000 ) +		return 0x02;	/*0xa*/	/* wim GxPp */ +	return 0x6a;		/* WIm GxPp, I/O */ +} + + +/************************************************************************/ +/*	page fault handler						*/ +/************************************************************************/ + +static ucell +ea_to_phys( ucell ea, ucell *mode ) +{ +	ucell phys; + +	/* hardcode our translation needs */ +	if( ea >= OF_CODE_START && ea < FREE_BASE_2 ) { +		*mode = ofmem_arch_default_translation_mode( ea ); +		return ea; +	} + +	phys = ofmem_translate(ea, mode); +	if( phys == (ucell)-1 ) { +#ifdef I_WANT_MOLISMS +		if( ea != 0x80816c00 ) +			printk("ea_to_phys: no translation for %08lx, using 1-1\n", ea ); +#endif +		phys = ea; +		*mode = ofmem_arch_default_translation_mode( phys ); + +#ifdef I_WANT_MOLISMS +		forth_segv_handler( (char*)ea ); +		OSI_Debugger(1); +#endif +		/* print_virt_range(); */ +		/* print_phys_range(); */ +		/* print_trans(); */ +	} +	return phys; +} + +static void +hash_page( ucell ea, ucell phys, ucell mode ) +{ +	static int next_grab_slot=0; +	unsigned long *upte, cmp, hash1; +	int i, vsid, found; +	mPTE_t *pp; + +	vsid = (ea>>28) + SEGR_BASE; +	cmp = BIT(0) | (vsid << 7) | ((ea & 0x0fffffff) >> 22); + +	hash1 = vsid; +	hash1 ^= (ea >> 12) & 0xffff; +	hash1 &= (get_hash_size() - 1) >> 6; + +	pp = (mPTE_t*)(get_hash_base() + (hash1 << 6)); +	upte = (unsigned long*)pp; + +	/* replace old translation */ +	for( found=0, i=0; !found && i<8; i++ ) +		if( cmp == upte[i*2] ) +			found=1; + +	/* otherwise use a free slot */ +	for( i=0; !found && i<8; i++ ) +		if( !pp[i].v ) +			found=1; + +	/* out of slots, just evict one */ +	if( !found ) { +		i = next_grab_slot + 1; +		next_grab_slot = (next_grab_slot + 1) % 8; +	} +	i--; +	upte[i*2] = cmp; +	upte[i*2+1] = (phys & ~0xfff) | mode; + +	asm volatile( "tlbie %0"  :: "r"(ea) ); +} + +void +dsi_exception( void ) +{ +	unsigned long dar, dsisr; +	ucell mode; +	ucell phys; + +	asm volatile("mfdar %0" : "=r" (dar) : ); +	asm volatile("mfdsisr %0" : "=r" (dsisr) : ); + +	//printk("dsi-exception @ %08lx <%08lx>\n", dar, dsisr ); + +	phys = ea_to_phys(dar, &mode); +	hash_page( dar, phys, mode ); +} + +void +isi_exception( void ) +{ +	unsigned long nip, srr1; +	ucell mode; +	ucell phys; + +	asm volatile("mfsrr0 %0" : "=r" (nip) : ); +	asm volatile("mfsrr1 %0" : "=r" (srr1) : ); + +	//printk("isi-exception @ %08lx <%08lx>\n", nip, srr1 ); + +	phys = ea_to_phys(nip, &mode); +	hash_page( nip, phys, mode ); +} + + +/************************************************************************/ +/*	init / cleanup							*/ +/************************************************************************/ + +void +setup_mmu( unsigned long code_base, unsigned long code_size, unsigned long ramsize ) +{ +	unsigned long sdr1 = HASH_BASE | ((HASH_SIZE-1) >> 16); +	unsigned long sr_base = (0x20 << 24) | SEGR_BASE; +	unsigned long msr; +	int i; + +	asm volatile("mtsdr1 %0" :: "r" (sdr1) ); +	for( i=0; i<16; i++ ) { +		int j = i << 28; +		asm volatile("mtsrin %0,%1" :: "r" (sr_base + i), "r" (j) ); +	} +	asm volatile("mfmsr %0" : "=r" (msr) : ); +	msr |= MSR_IR | MSR_DR; +	asm volatile("mtmsr %0" :: "r" (msr) ); +} + +void +ofmem_init( void ) +{ +	ofmem_t *ofmem = OFMEM; +	/* In case we can't rely on memory being zero initialized */ +	memset(ofmem, 0, sizeof(ofmem)); + +	ofmem->ramsize = RAMSIZE; + +	ofmem_claim_phys( 0, FREE_BASE_1, 0 ); +	ofmem_claim_virt( 0, FREE_BASE_1, 0 ); +	ofmem_claim_phys( OF_CODE_START, FREE_BASE_2 - OF_CODE_START, 0 ); +	ofmem_claim_virt( OF_CODE_START, FREE_BASE_2 - OF_CODE_START, 0 ); +} diff --git a/roms/openbios/arch/ppc/osi.h b/roms/openbios/arch/ppc/osi.h new file mode 100644 index 00000000..3baae157 --- /dev/null +++ b/roms/openbios/arch/ppc/osi.h @@ -0,0 +1,170 @@ +/* + *   Creation Date: <1999/03/18 03:19:43 samuel> + *   Time-stamp: <2003/12/26 16:58:19 samuel> + * + *	<os_interface.h> + * + *	This file includes definitions for drivers + *	running in the "emulated" OS. (Mainly the 'sc' + *	mechanism of communicating) + * + *   Copyright (C) 1999, 2000, 2001, 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_OSI +#define _H_OSI + +/* Magic register values loaded into r3 and r4 before the 'sc' assembly instruction */ +#define OSI_SC_MAGIC_R3		0x113724FA +#define OSI_SC_MAGIC_R4		0x77810F9B + + +/************************************************************************/ +/*	Selectors (passed in r5)					*/ +/************************************************************************/ + +#define OSI_CALL_AVAILABLE		0 +#define OSI_DEBUGGER 			1	/* enter debugger */ +/* obsolete OSI_LOG_STR 3 */ +#define OSI_CMOUNT_DRV_VOL		4	/* conditionally mount driver volume */ +/* obsolete OSI_SCSI_xxx 5-6 */ +#define OSI_GET_GMT_TIME		7 +#define OSI_MOUSE_CNTRL			8 +#define OSI_GET_LOCALTIME		9	/* return time in secs from 01/01/04 */ + +#define OSI_ENET_OPEN			10 +#define OSI_ENET_CLOSE			11 +#define OSI_ENET_GET_ADDR		12 +#define OSI_ENET_GET_STATUS		13 +#define OSI_ENET_CONTROL		14 +#define OSI_ENET_ADD_MULTI		16 +#define OSI_ENET_DEL_MULTI		17 +#define OSI_ENET_GET_PACKET		18 +#define OSI_ENET_SEND_PACKET		19 + +#define OSI_OF_INTERFACE		20 +#define OSI_OF_TRAP			21 +#define OSI_OF_RTAS			22 + +#define OSI_SCSI_CNTRL			23 +#define OSI_SCSI_SUBMIT			24 +#define OSI_SCSI_ACK			25 + +#define OSI_GET_MOUSE			26	/* -- r3 status, r4-r8 mouse data */ +#define OSI_ACK_MOUSE_IRQ		27	/* -- int */ + +#define OSI_SET_VMODE			28	/* modeID, depth -- error */ +#define OSI_GET_VMODE_INFO		29	/* mode, depth -- r3 status, r4-r9 pb */ +#define OSI_GET_MOUSE_DPI		30	/* -- mouse_dpi */ + +#define OSI_SET_VIDEO_POWER		31 +#define OSI_GET_FB_INFO			32	/* void -- r3 status, r4-r8 video data */ + +#define OSI_SOUND_WRITE			33 +/* #define OSI_SOUND_FORMAT 34 */ +#define OSI_SOUND_SET_VOLUME		35 +#define OSI_SOUND_CNTL			36 +/* obsolete OSI_SOUND call 37 */ + +#define OSI_VIDEO_ACK_IRQ		38 +#define OSI_VIDEO_CNTRL			39 + +#define OSI_SOUND_IRQ_ACK		40 +#define OSI_SOUND_START_STOP		41 + +#define OSI_REGISTER_IRQ		42	/* reg_property[0] appl_int -- irq_cookie */ +/* obsolete OSI_IRQ 43-46 */ + +#define OSI_LOG_PUTC			47	/* char -- */ + +#define OSI_KBD_CNTRL			50 +#define OSI_GET_ADB_KEY			51	/* -- adb_keycode (keycode | keycode_id in r4) */ + +#define OSI_WRITE_NVRAM_BYTE		52	/* offs, byte -- */ +#define OSI_READ_NVRAM_BYTE		53	/* offs -- byte */ + +#define OSI_EXIT			54 + +#define OSI_KEYCODE_TO_ADB		55	/* (keycode | keycode_id) -- adb_keycode */ +#define OSI_MAP_ADB_KEY			56	/* keycode, adbcode -- */ +#define OSI_SAVE_KEYMAPPING		57	/* -- */ +#define OSI_USLEEP			58	/* usecs -- */ +#define OSI_SET_COLOR			59	/* index value -- */ + +#define OSI_PIC_MASK_IRQ		60	/* irq -- */ +#define OSI_PIC_UNMASK_IRQ		61	/* irq -- */ +#define OSI_PIC_ACK_IRQ			62	/* irq mask_flag -- */ +#define OSI_PIC_GET_ACTIVE_IRQ		63 + +#define OSI_GET_COLOR			64	/* index -- value */ + +/* 65-67 old ablk implementation */ +#define OSI_IRQTEST			65 + +#define OSI_ENET2_OPEN			68 +#define OSI_ENET2_CLOSE			69 +#define OSI_ENET2_CNTRL			70 +#define OSI_ENET2_RING_SETUP		71 +#define OSI_ENET2_KICK			72 +#define OSI_ENET2_GET_HWADDR		73 +#define OSI_ENET2_IRQ_ACK		74 + +#define OSI_PROM_IFACE			76 +#define  kPromClose		0 +#define  kPromPeer		1 +#define  kPromChild		2 +#define  kPromParent		3 +#define  kPromPackageToPath	4 +#define  kPromGetPropLen	5 +#define  kPromGetProp		6 +#define  kPromNextProp		7 +#define  kPromSetProp		8 +#define  kPromChangePHandle	9 + +#define OSI_PROM_PATH_IFACE		77 +#define  kPromCreateNode	16 +#define  kPromFindDevice	17 + +#define OSI_BOOT_HELPER			78 +#define  kBootHAscii2Unicode	32 +#define  kBootHUnicode2Ascii	33 +#define  kBootHGetStrResInd	34		/* key, buf, len -- buf */ +#define  kBootHGetRAMSize	35		/* -- ramsize */ + +#define OSI_ABLK_RING_SETUP		79 +#define OSI_ABLK_CNTRL			80 +#define OSI_ABLK_DISK_INFO		81 +#define OSI_ABLK_KICK			82 +#define OSI_ABLK_IRQ_ACK		83 +#define OSI_ABLK_SYNC_READ		84 +#define OSI_ABLK_SYNC_WRITE		85 +#define OSI_ABLK_BLESS_DISK		86 + +#define OSI_EMUACCEL			89	/* EMULATE_xxx, nip -- index */ +#define OSI_MAPIN_MREGS			90	/* mphys */ +#define OSI_NVRAM_SIZE			91 + +#define OSI_MTICKS_TO_USECS		92 +#define OSI_USECS_TO_MTICKS		93 + +/* obsolete OSI_BLK 94-95 */ + +#define OSI_PSEUDO_FS			96 +#define  kPseudoFSOpen		1 +#define  kPseudoFSClose		2 +#define  kPseudoFSGetSize	3 +#define  kPseudoFSRead		4 +#define  kPseudoFSIndex2Name	5 + +#define OSI_TTY_PUTC			97 +#define OSI_TTY_GETC			98 +#define OSI_TTY_IRQ_ACK			99 + +#define NUM_OSI_SELECTORS		100	/* remember to increase this... */ + +#endif   /* _H_OSI */ diff --git a/roms/openbios/arch/ppc/osi_calls.h b/roms/openbios/arch/ppc/osi_calls.h new file mode 100644 index 00000000..1d6b3dc5 --- /dev/null +++ b/roms/openbios/arch/ppc/osi_calls.h @@ -0,0 +1,454 @@ +/* + *   Creation Date: <2002/06/16 01:40:57 samuel> + *   Time-stamp: <2003/12/26 17:02:09 samuel> + * + *	<osi_calls.h> + * + *	OSI call inlines + * + *   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_OSI_CALLS +#define _H_OSI_CALLS + +#include "osi.h" + +/* Old gcc versions have a limit on the number of registers used. + * Newer gcc versions (gcc 3.3) require that the clobber list does + * not overlap declared registers. + */ +#if __GNUC__ == 2 || ( __GNUC__ == 3 && __GNUC_MINOR__ < 3 ) +#define SHORT_REGLIST +#endif + + +/************************************************************************/ +/*	OSI call instantiation macros					*/ +/************************************************************************/ + +#define dreg(n)			__oc_##n __asm__ (#n) +#define ir(n)			"r" (__oc_##n) +#define rr(n)			"=r" (__oc_##n) + +#define _oc_head( input_regs... )				\ +{								\ +	int _ret=0;						\ +	{							\ +		register unsigned long dreg(r3);		\ +		register unsigned long dreg(r4);		\ +		register unsigned long dreg(r5)			\ +			,##input_regs ; + +#define _oc_syscall( number, extra_ret_regs... )		\ +		__oc_r3 = OSI_SC_MAGIC_R3;			\ +		__oc_r4 = OSI_SC_MAGIC_R4;			\ +		__oc_r5 = number;				\ +		__asm__ __volatile__ (				\ +		  "sc	" : rr(r3) ,## extra_ret_regs + +#define _oc_input( regs... )					\ +		: ir(r3), ir(r4), ir(r5)			\ +		, ## regs					\ +		: "memory" ); + +/* the tail memory clobber is necessary since we violate the strict + * aliasing rules when we return structs through the registers. + */ +#define _oc_tail						\ +		asm volatile ( "" : : : "memory" );		\ +		_ret = __oc_r3;					\ +	}							\ +	return _ret;						\ +} + + +/************************************************************************/ +/*	Alternatives 							*/ +/************************************************************************/ + +#ifdef SHORT_REGLIST +#define _oc_syscall_r10w6( number, inputregs... )		\ +		__oc_r3 = OSI_SC_MAGIC_R3;			\ +		__oc_r4 = OSI_SC_MAGIC_R4;			\ +		__oc_r5 = number;				\ +		__asm__ __volatile__ (				\ +		  "sc			\n"			\ +		  "stw	4,0(10) 	\n"			\ +		  "stw	5,4(10) 	\n"			\ +		  "stw	6,8(10) 	\n"			\ +		  "stw	7,12(10) 	\n"			\ +		  "stw	8,16(10) 	\n"			\ +		  "stw	9,20(10) 	\n"			\ +		: rr(r3)					\ +		: ir(r3), ir(r4), ir(r5), ir(r10) 		\ +		  ,## inputregs 				\ +		: "memory",					\ +		   "r4", "r5", "r6", "r7", "r8", "r9" ); +#endif + + +/************************************************************************/ +/*	Common helper functions						*/ +/************************************************************************/ + +#define _osi_call0( type, name, number ) 			\ +type name( void ) 						\ +	_oc_head()						\ +	_oc_syscall( number )					\ +	_oc_input()						\ +	_oc_tail + +#define _osi_call1( type, name, number, type1, arg1 ) 		\ +type name( type1 arg1 ) 					\ +	_oc_head( dreg(r6) )					\ +	__oc_r6 = (unsigned long)arg1;				\ +	_oc_syscall( number )					\ +	_oc_input( ir(r6) )					\ +	_oc_tail + +#define _osi_call2( type, name, number, t1, a1, t2, a2 ) 	\ +type name( t1 a1, t2 a2 ) 					\ +	_oc_head( dreg(r6), dreg(r7) )				\ +	__oc_r6 = (unsigned long)a1;				\ +	__oc_r7 = (unsigned long)a2;				\ +	_oc_syscall( number )					\ +	_oc_input( ir(r6), ir(r7) )				\ +	_oc_tail + +#define _osi_call3( type, name, number, t1, a1, t2, a2, t3, a3 ) \ +type name( t1 a1, t2 a2, t3 a3 ) 				\ +	_oc_head( dreg(r6), dreg(r7), dreg(r8) )		\ +	__oc_r6 = (unsigned long)a1;				\ +	__oc_r7 = (unsigned long)a2;				\ +	__oc_r8 = (unsigned long)a3;				\ +	_oc_syscall( number )					\ +	_oc_input( ir(r6), ir(r7), ir(r8) )			\ +	_oc_tail + +#define _osi_call4( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4 ) \ +type name( t1 a1, t2 a2, t3 a3, t4 a4 ) 			\ +	_oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9) )	\ +	__oc_r6 = (unsigned long)a1;				\ +	__oc_r7 = (unsigned long)a2;				\ +	__oc_r8 = (unsigned long)a3;				\ +	__oc_r9 = (unsigned long)a4;				\ +	_oc_syscall( number )					\ +	_oc_input( ir(r6), ir(r7), ir(r8), ir(r9) )		\ +	_oc_tail + +#define _osi_call5( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5 ) \ +type name( t1 a1, t2 a2, t3 a3, t4 a4, t5 a5 ) 				\ +	_oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9), dreg(r10) )	\ +	__oc_r6 = (unsigned long)a1;					\ +	__oc_r7 = (unsigned long)a2;					\ +	__oc_r8 = (unsigned long)a3;					\ +	__oc_r9 = (unsigned long)a4;					\ +	__oc_r10 = (unsigned long)a5;					\ +	_oc_syscall( number )						\ +	_oc_input( ir(r6), ir(r7), ir(r8), ir(r9), ir(r10) )		\ +	_oc_tail + +#define _osi_call6( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6 ) \ +type name( t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6 ) 				\ +	_oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9), dreg(r10), dreg(r11) )\ +	__oc_r6 = (unsigned long)a1;					\ +	__oc_r7 = (unsigned long)a2;					\ +	__oc_r8 = (unsigned long)a3;					\ +	__oc_r9 = (unsigned long)a4;					\ +	__oc_r10 = (unsigned long)a5;					\ +	__oc_r11 = (unsigned long)a6;					\ +	_oc_syscall( number )						\ +	_oc_input( ir(r6), ir(r7), ir(r8), ir(r9), ir(r10), ir(r11) )	\ +	_oc_tail + + +/************************************************************************/ +/*	Special 							*/ +/************************************************************************/ + +/* r4 returned in retarg1 pointer */ +#define _osi_call0_w1( type, name, number, type1, retarg1 ) 	\ +type name( type1 retarg1 ) 					\ +	_oc_head()						\ +	_oc_syscall( number, rr(r4) )				\ +	_oc_input()						\ +	*retarg1 = __oc_r4;					\ +	_oc_tail + +#define _osi_call0_w2( type, name, number, type1, retarg1 ) 	\ +type name( type1 retarg1 ) 					\ +	_oc_head()						\ +	_oc_syscall( number, rr(r4), rr(r5) )			\ +	_oc_input()						\ +	((unsigned long*)retarg1)[0] = __oc_r4;			\ +	((unsigned long*)retarg1)[1] = __oc_r5;			\ +	_oc_tail + +/* r4-r8 returned in retarg1 pointer */ +#define _osi_call0_w5( type, name, number, type1, retarg1 ) 	\ +type name( type1 retarg1 ) 					\ +	_oc_head( dreg(r6), dreg(r7), dreg(r8) )		\ +	_oc_syscall( number, 					\ +		rr(r4), rr(r5), rr(r6), rr(r7), rr(r8) )	\ +	_oc_input()						\ +	((unsigned long*)retarg1)[0] = __oc_r4;			\ +	((unsigned long*)retarg1)[1] = __oc_r5;			\ +	((unsigned long*)retarg1)[2] = __oc_r6;			\ +	((unsigned long*)retarg1)[3] = __oc_r7;			\ +	((unsigned long*)retarg1)[4] = __oc_r8;			\ +	_oc_tail + +/* r4 returned in retarg pointer */ +#define _osi_call1_w1( type, name, number, t1, a1, t2, retarg ) \ +type name( t1 a1, t2 retarg ) 					\ +	_oc_head( dreg(r6) )					\ +	__oc_r6 = (unsigned long)a1;				\ +	_oc_syscall( number, rr(r4) )				\ +	_oc_input( ir(r6) )					\ +	((unsigned long*)retarg)[0] = __oc_r4;			\ +	_oc_tail + +/* r4,r5 returned in retarg1, retarg2 */ +#define _osi_call1_w1w1( type, name, number, t1, a1, t2, retarg1, t3, retarg2 ) \ +type name( t1 a1, t2 retarg1, t3 retarg2 )			\ +	_oc_head( dreg(r6) )					\ +	__oc_r6 = (unsigned long)a1;				\ +	_oc_syscall( number, rr(r4), rr(r5) )			\ +	_oc_input( ir(r6) )					\ +	((unsigned long*)retarg1)[0] = __oc_r4;			\ +	((unsigned long*)retarg2)[0] = __oc_r5;			\ +	_oc_tail + +/* r4,r5 returned in retarg1, retarg2, retarg3 */ +#define _osi_call1_w1w1w1( type, name, number, t1, a1, t2, retarg1, t3, retarg2, t4, retarg3 ) \ +type name( t1 a1, t2 retarg1, t3 retarg2, t4 retarg3 )		\ +	_oc_head( dreg(r6) )					\ +	__oc_r6 = (unsigned long)a1;				\ +	_oc_syscall( number, rr(r4), rr(r5), rr(r6) )		\ +	_oc_input( ir(r6) )					\ +	((unsigned long*)retarg1)[0] = __oc_r4;			\ +	((unsigned long*)retarg2)[0] = __oc_r5;			\ +	((unsigned long*)retarg3)[0] = __oc_r6;			\ +	_oc_tail + +/* r4,r5 returned in retarg pointer */ +#define _osi_call1_w2( type, name, number, t1, a1, t2, retarg ) \ +type name( t1 a1, t2 retarg ) 					\ +	_oc_head( dreg(r6) )					\ +	__oc_r6 = (unsigned long)a1;				\ +	_oc_syscall( number, rr(r4), rr(r5) )			\ +	_oc_input( ir(r6) )					\ +	((unsigned long*)retarg)[0] = __oc_r4;			\ +	((unsigned long*)retarg)[1] = __oc_r5;			\ +	_oc_tail + +/* r4-r7 returned in retarg pointer */ +#define _osi_call1_w4( type, name, number, t1, a1, t2, retarg ) \ +type name( t1 a1, t2 retarg )					\ +	_oc_head( dreg(r6), dreg(r7) )				\ +	__oc_r6 = (unsigned long)a1;				\ +	_oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7) )	\ +	_oc_input( ir(r6) )					\ +	((unsigned long*)retarg)[0] = __oc_r4;			\ +	((unsigned long*)retarg)[1] = __oc_r5;			\ +	((unsigned long*)retarg)[2] = __oc_r6;			\ +	((unsigned long*)retarg)[3] = __oc_r7;			\ +	_oc_tail + + +/* r4-r5 returned in retarg pointer */ +#define _osi_call2_w2( type, name, number, t1, a1, t2, a2, t3, retarg ) \ +type name( t1 a1, t2 a2, t3 retarg ) 				\ +	_oc_head( dreg(r6), dreg(r7) )				\ +	__oc_r6 = (unsigned long)a1;				\ +	__oc_r7 = (unsigned long)a2;				\ +	_oc_syscall( number, rr(r4), rr(r5) )			\ +	_oc_input( ir(r6), ir(r7) )				\ +	((unsigned long*)retarg)[0] = __oc_r4;			\ +	((unsigned long*)retarg)[1] = __oc_r5;			\ +	_oc_tail + +/* r4-r7 returned in retarg pointer */ +#define _osi_call2_w4( type, name, number, t1, a1, t2, a2, t3, retarg ) \ +type name( t1 a1, t2 a2, t3 retarg ) 				\ +	_oc_head( dreg(r6), dreg(r7) )				\ +	__oc_r6 = (unsigned long)a1;				\ +	__oc_r7 = (unsigned long)a2;				\ +	_oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7) )	\ +	_oc_input( ir(r6), ir(r7) )				\ +	((unsigned long*)retarg)[0] = __oc_r4;			\ +	((unsigned long*)retarg)[1] = __oc_r5;			\ +	((unsigned long*)retarg)[2] = __oc_r6;			\ +	((unsigned long*)retarg)[3] = __oc_r7;			\ +	_oc_tail + +#ifdef SHORT_REGLIST +/* r4-r9 returned in retarg pointer */ +#define _osi_call2_w6( type, name, number, t1, a1, t2, a2, t3, retarg ) \ +type name( t1 a1, t2 a2, t3 retarg ) 				\ +	_oc_head( dreg(r6), dreg(r7), dreg(r10) )		\ +        __oc_r6 = (unsigned long)a1;				\ +        __oc_r7 = (unsigned long)a2;				\ +	__oc_r10 = (unsigned long)retarg;			\ +	_oc_syscall_r10w6( number, ir(r6), ir(r7) )		\ +	_oc_tail + +#else /* SHORT_REGLIST */ + +/* r4-r9 returned in retarg pointer */ +#define _osi_call2_w6( type, name, number, t1, a1, t2, a2, t3, retarg ) \ +type name( t1 a1, t2 a2, t3 retarg ) 				\ +	_oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9) )	\ +	__oc_r6 = (unsigned long)a1;				\ +	__oc_r7 = (unsigned long)a2;				\ +	_oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7), rr(r8), rr(r9) )	\ +	_oc_input( ir(r6), ir(r7) )				\ +	((unsigned long*)retarg)[0] = __oc_r4;			\ +	((unsigned long*)retarg)[1] = __oc_r5;			\ +	((unsigned long*)retarg)[2] = __oc_r6;			\ +	((unsigned long*)retarg)[3] = __oc_r7;			\ +	((unsigned long*)retarg)[4] = __oc_r8;			\ +	((unsigned long*)retarg)[5] = __oc_r9;			\ +	_oc_tail + +#endif /* SHORT_REGLIST */ + + +/************************************************************************/ +/*	OSI call inlines						*/ +/************************************************************************/ + +static inline _osi_call1( int, OSI_CallAvailable, OSI_CALL_AVAILABLE, int, osi_num ); + +static inline _osi_call1( int, OSI_PutC, OSI_LOG_PUTC, int, ch ); + +static inline _osi_call1( int, OSI_Debugger, OSI_DEBUGGER, int, num ); +static inline _osi_call0( int, OSI_Exit, OSI_EXIT ); + +/* misc */ +static inline _osi_call0( unsigned long, OSI_GetLocalTime, OSI_GET_LOCALTIME ); +static inline _osi_call0( unsigned long, OSI_GetGMTTime, OSI_GET_GMT_TIME ); +static inline _osi_call1( int, OSI_USleep, OSI_USLEEP, int, usecs ); + +/* NVRAM */ +static inline _osi_call0( int, OSI_NVRamSize, OSI_NVRAM_SIZE ); +static inline _osi_call1( int, OSI_ReadNVRamByte, OSI_READ_NVRAM_BYTE, int, offs ); +static inline _osi_call2( int, OSI_WriteNVRamByte, OSI_WRITE_NVRAM_BYTE, int, offs, +			  unsigned char, ch ); + +/* keyboard stuff */ +static inline _osi_call0_w1( int, OSI_GetAdbKey2, OSI_GET_ADB_KEY, int *, raw_key ); +static inline _osi_call1( int, OSI_KbdCntrl, OSI_KBD_CNTRL, int, cmd ); + +static inline int OSI_GetAdbKey( void ) +	{ int dummy_raw_key; return OSI_GetAdbKey2( &dummy_raw_key ); } +static inline _osi_call2( int, OSI_MapAdbKey, OSI_MAP_ADB_KEY, int, keycode, int, adbkey ) +static inline _osi_call1( int, OSI_KeycodeToAdb, OSI_KEYCODE_TO_ADB, int, keycode ); +static inline _osi_call0( int, OSI_SaveKeymapping, OSI_SAVE_KEYMAPPING ); + +/* mouse support */ +struct osi_mouse; +static inline _osi_call0_w5( int, OSI_GetMouse, OSI_GET_MOUSE, struct osi_mouse *, ret ); +static inline _osi_call0( int, OSI_GetMouseDPI, OSI_GET_MOUSE_DPI ); + +/* video */ +static inline _osi_call2( int, OSI_SetVMode_, OSI_SET_VMODE, int, mode, int, depth_mode ); +struct osi_get_vmode_info; +static inline _osi_call2_w6( int, OSI_GetVModeInfo_, OSI_GET_VMODE_INFO, int, mode, int, depth_mode, +			     struct osi_get_vmode_info *, ret ); +static inline _osi_call1( int, OSI_SetVPowerState, OSI_SET_VIDEO_POWER, int, power_state ); +static inline _osi_call2( int, OSI_SetColor, OSI_SET_COLOR, int, index, int, rgb ); +static inline _osi_call0_w1( int, OSI_VideoAckIRQ, OSI_VIDEO_ACK_IRQ, int *, events ); + +static inline void OSI_RefreshPalette( void ) { OSI_SetColor(-1,0); } + +/* PIC (mac-io replacement) */ +static inline _osi_call1( int, OSI_PICMaskIRQ, OSI_PIC_MASK_IRQ, int, irq ); +static inline _osi_call1( int, OSI_PICUnmaskIRQ, OSI_PIC_UNMASK_IRQ, int, irq ); +static inline _osi_call2( int, OSI_PICAckIRQ, OSI_PIC_ACK_IRQ, int, irq, int, mask_it ); +static inline _osi_call0( int, OSI_PICGetActiveIRQ, OSI_PIC_GET_ACTIVE_IRQ ); + +/* sound */ +static inline _osi_call1( int, OSI_SoundCntl, OSI_SOUND_CNTL, int, cmd ); +static inline _osi_call2( int, OSI_SoundCntl1, OSI_SOUND_CNTL, int, cmd, int, p1 ); +static inline _osi_call3( int, OSI_SoundCntl2, OSI_SOUND_CNTL, int, cmd, int, p1, int, p2 ); +static inline _osi_call0_w2( int, OSI_SoundIRQAck, OSI_SOUND_IRQ_ACK, unsigned long *, timestamp ); +static inline _osi_call3( int, OSI_SoundWrite, OSI_SOUND_WRITE, int, physbuf, int, len, int, restart ); +static inline _osi_call3( int, OSI_SoundSetVolume, OSI_SOUND_SET_VOLUME, int, hwvol, int, speakervol, int, mute ); + +/* async block driver */ +struct ablk_disk_info; +static inline _osi_call2_w4( int, OSI_ABlkDiskInfo, OSI_ABLK_DISK_INFO, int, channel, int, unit, +			     struct ablk_disk_info *, retinfo ); +static inline _osi_call1( int, OSI_ABlkKick, OSI_ABLK_KICK, int, channel ); +static inline _osi_call1_w1w1w1( int, OSI_ABlkIRQAck, OSI_ABLK_IRQ_ACK, int, channel, int *, req_count, +			       int *, active, int *, events ); +static inline _osi_call3( int, OSI_ABlkRingSetup, OSI_ABLK_RING_SETUP, int, channel, int, mphys, int, n_el ); +static inline _osi_call2( int, OSI_ABlkCntrl, OSI_ABLK_CNTRL, int, channel, int, cmd ); +static inline _osi_call3( int, OSI_ABlkCntrl1, OSI_ABLK_CNTRL, int, channel, int, cmd, int, param ); +static inline _osi_call5( int, OSI_ABlkSyncRead, OSI_ABLK_SYNC_READ, int, channel, int, unit, +			  int, blk, unsigned long, mphys, int, size ); +static inline _osi_call5( int, OSI_ABlkSyncWrite, OSI_ABLK_SYNC_WRITE, int, channel, int, unit, +			  int, blk, unsigned long, mphys, int, size ); +static inline _osi_call2( int, OSI_ABlkBlessDisk, OSI_ABLK_BLESS_DISK, int, channel, int, unit ); + +static inline _osi_call0( int, OSI_CMountDrvVol, OSI_CMOUNT_DRV_VOL ); + +/* enet2 */ +static inline _osi_call0( int, OSI_Enet2Open, OSI_ENET2_OPEN ); +static inline _osi_call0( int, OSI_Enet2Close, OSI_ENET2_CLOSE ); +static inline _osi_call3( int, OSI_Enet2RingSetup, OSI_ENET2_RING_SETUP, int, which_ring, +			  int, ring_mphys, int, n_el ); +static inline _osi_call2( int, OSI_Enet2Cntrl1, OSI_ENET2_CNTRL, int, cmd, int, param ); +static inline _osi_call1( int, OSI_Enet2Cntrl, OSI_ENET2_CNTRL, int, cmd ); +static inline _osi_call0( int, OSI_Enet2Kick, OSI_ENET2_KICK ); + +static inline _osi_call0_w2( int, OSI_Enet2GetHWAddr__, OSI_ENET2_GET_HWADDR, unsigned long *, retbuf ); +static inline int OSI_Enet2GetHWAddr( unsigned char *addr ) { +	int ret; +	unsigned long buf[2]; + +	ret = OSI_Enet2GetHWAddr__( buf ); + +	((unsigned long*)addr)[0] = buf[0]; +	((unsigned short*)addr)[2] = (buf[1] >> 16); +	return ret; +} +static inline _osi_call2( int, OSI_Enet2IRQAck, OSI_ENET2_IRQ_ACK, int, irq_enable, int, rx_head ); + +/* PROM (device-tree) */ +static inline _osi_call2( int, OSI_PromIface, OSI_PROM_IFACE, int, what, int, ph ); +static inline _osi_call3( int, OSI_PromIface1, OSI_PROM_IFACE, int, what, int, ph, int, p1 ); +static inline _osi_call4( int, OSI_PromIface2, OSI_PROM_IFACE, int, what, int, ph, int, p1, int, p2 ); +static inline _osi_call5( int, OSI_PromIface3, OSI_PROM_IFACE, int, what, int, ph, int, p1, int, p2, int, p3 ); +static inline _osi_call2( int, OSI_PromPathIface, OSI_PROM_PATH_IFACE, int, what, const char *, p ); + +/* emulation acceleration */ +static inline _osi_call1( int, OSI_MapinMregs, OSI_MAPIN_MREGS, unsigned long, mphys ); +static inline _osi_call3( int, OSI_EmuAccel, OSI_EMUACCEL, int, emuaccel_flags, int, param, int, inst_addr ); + +/* timer frequency */ +static inline _osi_call1( int, OSI_MticksToUsecs, OSI_MTICKS_TO_USECS, unsigned long, mticks ); +static inline _osi_call1( int, OSI_UsecsToMticks, OSI_USECS_TO_MTICKS, unsigned long, usecs ); + +/* fb info */ +struct osi_fb_info; +static inline _osi_call0_w5( int, OSI_GetFBInfo, OSI_GET_FB_INFO, struct osi_fb_info *, retinfo ); + +/* SCSI */ +static inline _osi_call0( int, OSI_SCSIAck, OSI_SCSI_ACK ); +static inline _osi_call1( int, OSI_SCSISubmit, OSI_SCSI_SUBMIT, int, req_mphys ); +static inline _osi_call2( int, OSI_SCSIControl, OSI_SCSI_CNTRL, int, sel, int, param ); + +/* TTY */ +static inline _osi_call0( int, OSI_TTYGetc, OSI_TTY_GETC ); +static inline _osi_call1( int, OSI_TTYPutc, OSI_TTY_PUTC, int, ch ); +static inline _osi_call0( int, OSI_TTYIRQAck, OSI_TTY_IRQ_ACK ); + +#endif   /* _H_OSI_CALLS */ diff --git a/roms/openbios/arch/ppc/pearpc/console.c b/roms/openbios/arch/ppc/pearpc/console.c new file mode 100644 index 00000000..3869cbab --- /dev/null +++ b/roms/openbios/arch/ppc/pearpc/console.c @@ -0,0 +1,43 @@ + +/* + *      <console.c> + * + *      Simple text console + * + *   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 "libopenbios/ofmem.h" +#include "pearpc/pearpc.h" + + +typedef struct osi_fb_info { +	unsigned long   mphys; +	int             rb, w, h, depth; +} osi_fb_info_t; + + +int PearPC_GetFBInfo( osi_fb_info_t *fb ) +{ + +        fb->w=1024; +        fb->h=768; +        fb->depth=15; +        fb->rb=2048; +        fb->mphys=0x84000000; + +	return 0; +} + +#define openbios_GetFBInfo(x) PearPC_GetFBInfo(x) + +#include "../../../packages/video.c" +#include "../../../libopenbios/console_common.c" diff --git a/roms/openbios/arch/ppc/pearpc/init.c b/roms/openbios/arch/ppc/pearpc/init.c new file mode 100644 index 00000000..ca6da0a4 --- /dev/null +++ b/roms/openbios/arch/ppc/pearpc/init.c @@ -0,0 +1,136 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<init.c> + * + *	Initialization for pearpc + * + *   Copyright (C) 2004 Greg Watson + *   Copyright (C) 2005 Stefan Reinauer + * + *   based on mol/init.c: + * + *   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 "pearpc/pearpc.h" +#include "libopenbios/ofmem.h" +#include "openbios-version.h" + +extern void unexpected_excep( int vector ); +extern void ob_pci_init( void ); +extern void ob_adb_init( void ); +extern void setup_timers( void ); + +#if 0 +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; +} +#endif + +void +unexpected_excep( int vector ) +{ +	printk("openbios 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 ) +{ +#if CONFIG_RTAS +	phandle_t ph; +#endif +	int autoboot; + +	devtree_init(); +	nvram_init("/pci/mac-io/nvram"); +	openbios_init(); +	modules_init(); +        setup_timers(); +#ifdef CONFIG_DRIVER_PCI +	ob_pci_init(); +#endif +	node_methods_init(); +	init_video(); + +#if CONFIG_RTAS +	if( !(ph=find_dev("/rtas")) ) +		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; +		set_property( ph, "rtas-size", (char*)&size, sizeof(size) ); +	} +#endif + +#if 0 +	/* tweak boot settings */ +	autoboot = !!get_bool_res("autoboot"); +#endif +	autoboot = 0; +	if( !autoboot ) +		printk("Autobooting disabled - dropping into OpenFirmware\n"); +	setenv("auto-boot?", autoboot ? "true" : "false" ); +	setenv("boot-command", "pearpcboot"); + +#if 0 +	if( get_bool_res("tty-interface") == 1 ) +#endif +		fword("activate-tty-interface"); + +	/* hack */ +	device_end(); +	bind_func("pearpcboot", boot ); +} diff --git a/roms/openbios/arch/ppc/pearpc/kernel.c b/roms/openbios/arch/ppc/pearpc/kernel.c new file mode 100644 index 00000000..6408e421 --- /dev/null +++ b/roms/openbios/arch/ppc/pearpc/kernel.c @@ -0,0 +1,16 @@ +/* + *   Creation Date: <2004/08/28 18:03:25 stepan> + *   Time-stamp: <2004/08/28 18:03:25 stepan> + * + *	<pearpc/kernel.c> + * + *   Copyright (C) 2005 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 "pearpc-dict.h" +#include "../kernel.c" diff --git a/roms/openbios/arch/ppc/pearpc/main.c b/roms/openbios/arch/ppc/pearpc/main.c new file mode 100644 index 00000000..085494e5 --- /dev/null +++ b/roms/openbios/arch/ppc/pearpc/main.c @@ -0,0 +1,145 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<main.c> + * + *   Copyright (C) 2004 Greg Watson + * + *   Based on MOL specific code which is + *   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 "pearpc/pearpc.h" +#include "libopenbios/ofmem.h" + +static void +transfer_control_to_elf( unsigned long entry ) +{ +	extern void call_elf( unsigned long entry ); +	printk("Starting ELF image at 0x%08lX\n", entry); +	call_elf( 0x400000 ); +	//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'\n", get_file_path(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"); + +#if 0 +		/* 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 ); +		} +#endif +		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; +} + + +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 ); +} + +/************************************************************************/ +/*	pearpc booting							*/ +/************************************************************************/ + +static void +pearpc_startup( void ) +{ +	const char *paths[] = { "hd:0,\\zImage.chrp", NULL }; +	const char *args[] = { "root=/dev/hda2 console=ttyS0,115200", 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], args[i] ); + +		update_nvram(); +		transfer_control_to_elf( entry ); +		/* won't come here */ +	} +	printk("*** Boot failure! No secondary bootloader specified ***\n"); +} + + +/************************************************************************/ +/*	entry								*/ +/************************************************************************/ + +void +boot( void ) +{ +	fword("update-chosen"); +	pearpc_startup(); +} diff --git a/roms/openbios/arch/ppc/pearpc/methods.c b/roms/openbios/arch/ppc/pearpc/methods.c new file mode 100644 index 00000000..f505b6ce --- /dev/null +++ b/roms/openbios/arch/ppc/pearpc/methods.c @@ -0,0 +1,329 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<methods.c> + * + *	Misc device node methods + * + *   Copyright (C) 2004 Greg Watson + * + *   Based on MOL specific code which is + * + *   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 "pearpc/pearpc.h" +#include "libopenbios/ofmem.h" + +/************************************************************************/ +/*	RTAS (run-time abstraction services)				*/ +/************************************************************************/ + +#ifdef CONFIG_RTAS +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 }, +}; +#endif + + +/************************************************************************/ +/*	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 ); +	//vfd_draw_str( s ); +        console_draw_fstr(addr, len); + +	PUSH( len ); +} + +NODE_METHODS( video_stdout ) = { +	{ "write",	stdout_write	}, +}; + + +/************************************************************************/ +/*	tty								*/ +/************************************************************************/ + +DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" ); + +/* ( 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 = getchar(); +		if( ch >= 0 ) { +			*p = ch; +		} else { +			ret = 0; +		} +	} +	PUSH( ret ); +} + +/* ( addr len -- actual ) */ +static void +tty_write( void ) +{ +	int i, len = POP(); +	char *p = (char*)POP(); +	for( i=0; i<len; i++ ) +		putchar( *p++ ); +	RET( len ); +} + +NODE_METHODS( tty ) = { +	{ "read",	tty_read	}, +	{ "write",	tty_write	}, +}; + +/************************************************************************/ +/*	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"); +} + +/* ( -- ms ) */ +static void +ciface_milliseconds( unsigned long args[], unsigned long ret[] ) +{ +	extern unsigned long get_timer_freq(); +	static unsigned long mticks=0, usecs=0; +	unsigned long t; + +	asm volatile("mftb %0" : "=r" (t) : ); +	if( mticks ) +		usecs += get_timer_freq() / 1000000 * ( 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, "/cpu@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 == (ucell)-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 ) +{ +#ifdef CONFIG_RTAS +	REGISTER_NODE( rtas ); +#endif +	REGISTER_NODE( video_stdout ); +	REGISTER_NODE( ciface ); +	REGISTER_NODE( memory ); +	REGISTER_NODE( mmu ); +	REGISTER_NODE( mmu_ciface ); +	REGISTER_NODE( tty ); +} diff --git a/roms/openbios/arch/ppc/pearpc/pearpc.c b/roms/openbios/arch/ppc/pearpc/pearpc.c new file mode 100644 index 00000000..234052ce --- /dev/null +++ b/roms/openbios/arch/ppc/pearpc/pearpc.c @@ -0,0 +1,206 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<pearpc.c> + * + *   Copyright (C) 2004, Greg Watson + * + *   derived from 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 "pearpc/pearpc.h" +#include <stdarg.h> + +#define UART_BASE 0x3f8 + +// FIXME +unsigned long virt_offset = 0; + + +void +exit( int status ) +{ +	for (;;); +} + +void +fatal_error( const char *err ) +{ +	printk("Fatal error: %s\n", err ); +	exit(0); +} + +void +panic( const char *err ) +{ +	printk("Panic: %s\n", err ); +	exit(0); + +	/* 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 = vsnprintf(buf, sizeof(buf), fmt, args); +	va_end(args); + +	for( p=buf; *p; p++ ) { +		if( *p == '\n' ) +			do_indent = 0; +		if( do_indent++ == 1 ) { +			putchar( '>' ); +			putchar( '>' ); +			putchar( ' ' ); +		} +		putchar( *p ); +	} +	return i; +} + + +/************************************************************************/ +/*	TTY iface							*/ +/************************************************************************/ + +static int ttychar = -1; + +static int +tty_avail( void ) +{ +	return 1; +} + +static int +tty_putchar( int c ) +{ +	if( tty_avail() ) { +		while (!(inb(UART_BASE + 0x05) & 0x20)) +			; +		outb(c, UART_BASE); +		while (!(inb(UART_BASE + 0x05) & 0x40)) +			; +	} +	return c; +} + +int +availchar( void ) +{ +	if( !tty_avail() ) +		return 0; + +	if( ttychar < 0 ) +		ttychar = inb(UART_BASE); +	return (ttychar >= 0); +} + +int +getchar( void ) +{ +	int ch; + +	if( !tty_avail() ) +		return 0; + +	if( ttychar < 0 ) +		return inb(UART_BASE); +	ch = ttychar; +	ttychar = -1; +	return ch; +} + +int +putchar( int c ) +{ +	if (c == '\n') +		tty_putchar('\r'); +	return tty_putchar(c); +} + + +/************************************************************************/ +/*	briQ specific stuff						*/ +/************************************************************************/ + +#define IO_NVRAM_PA_START 0x80860000 +#define IO_NVRAM_PA_END 0x80880000 + +static char *nvram=(char *)IO_NVRAM_PA_START; + +void +dump_nvram(void) +{ +  static char hexdigit[] = "0123456789abcdef"; +  int i; +  for (i = 0; i < 16*4; i++) +    { +      printk ("%c", hexdigit[nvram[i<<4] >> 4]); +      printk ("%c", hexdigit[nvram[i<<4] % 16]); +      if (!((i + 1) % 16)) +        { +          printk ("\n"); +        } +      else +        { +          printk (" "); +        } +    } +} + + +int +arch_nvram_size( void ) +{ +	return (IO_NVRAM_PA_END-IO_NVRAM_PA_START)>>4; +} + +void +arch_nvram_put( char *buf ) +{ +	int i; +	for (i=0; i<(IO_NVRAM_PA_END-IO_NVRAM_PA_START)>>4; i++) +		nvram[i<<4]=buf[i]; +	// memcpy(nvram, buf, IO_NVRAM_PA_END-IO_NVRAM_PA_START); +	printk("new nvram:\n"); +	dump_nvram(); +} + +void +arch_nvram_get( char *buf ) +{ +	int i; +	for (i=0; i<(IO_NVRAM_PA_END-IO_NVRAM_PA_START)>>4; i++) +		buf[i]=nvram[i<<4]; + +	//memcpy(buf, nvram, IO_NVRAM_PA_END-IO_NVRAM_PA_START); +	printk("current nvram:\n"); +	dump_nvram(); +} diff --git a/roms/openbios/arch/ppc/pearpc/pearpc.fs b/roms/openbios/arch/ppc/pearpc/pearpc.fs new file mode 100644 index 00000000..0d018b1c --- /dev/null +++ b/roms/openbios/arch/ppc/pearpc/pearpc.fs @@ -0,0 +1,116 @@ +\   pearpc specific initialization code +\  +\   Copyright (C) 2005 Stefan Reinauer +\  +\   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 +\  + + +\ ------------------------------------------------------------------------- +\ 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 +  " rtc" " /pci/isa/rtc" preopen +  " memory" " /memory" preopen +  " mmu" " /cpu@0" preopen +  \ " stdout" " /packages/terminal-emulator" preopen +  " stdout" " /pci/pci6666,6666" preopen +  " stdin" " /pci/via-cuda/adb" 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 +; +     +: init-pearpc-tree ( -- ) +  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 +  " /packages/terminal-emulator" find-dev if drop +    " /pci/via-cuda/adb" " input-device" $setenv +    " /pci/pci6666,6666" " 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 +  " /pci/isa/interrupt-controller" find-dev if encode-int " interrupt-controller" property then +  device-end +; diff --git a/roms/openbios/arch/ppc/pearpc/pearpc.h b/roms/openbios/arch/ppc/pearpc/pearpc.h new file mode 100644 index 00000000..44497d79 --- /dev/null +++ b/roms/openbios/arch/ppc/pearpc/pearpc.h @@ -0,0 +1,26 @@ +/* + *   Creation Date: <2004/08/28 17:50:12 stepan> + *   Time-stamp: <2004/08/28 17:50:12 stepan> + * + *	<pearpc.h> + * + *   Copyright (C) 2005 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 + * + */ + +#ifndef _H_PEARPC +#define _H_PEARPC + +/* vfd.c */ +extern int		vfd_draw_str( const char *str ); +extern void		vfd_close( void ); + +extern int              console_draw_fstr(const char *str, int len); + +#include "kernel.h" + +#endif   /* _H_PEARPC */ diff --git a/roms/openbios/arch/ppc/pearpc/tree.c b/roms/openbios/arch/ppc/pearpc/tree.c new file mode 100644 index 00000000..abd1bf02 --- /dev/null +++ b/roms/openbios/arch/ppc/pearpc/tree.c @@ -0,0 +1,23 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<tree.c> + * + *	device tree setup + * + *   Copyright (C) 2004 Greg Watson + * + *   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" + +void devtree_init( void ) +{ +	fword("init-pearpc-tree"); +} diff --git a/roms/openbios/arch/ppc/pearpc/tree.fs b/roms/openbios/arch/ppc/pearpc/tree.fs new file mode 100644 index 00000000..d19b485f --- /dev/null +++ b/roms/openbios/arch/ppc/pearpc/tree.fs @@ -0,0 +1,305 @@ +\   PearPC specific initialization code +\  +\   Copyright (C) 2005 Stefan Reinauer +\  +\   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 +\  + +\ ------------------------------------------------------------- +\ device-tree +\ ------------------------------------------------------------- + +" /" find-device + +" chrp" device-type +" OpenSource,PEARPC" model +h# 80000000 encode-int " isa-io-base" property +1 encode-int " #interrupt-cells" property +1 encode-int " #size-cells" property + +new-device +	" memory" device-name +	" memory" device-type +	0 encode-int h# 1E00000 encode-int encode+ +	h# 2000000 encode-int encode+ h# 40000000 encode-int encode+  +	  " available" property +	0 h# 40000000 reg +	external +	: open true ; +	: close ; +finish-device + +new-device +	" cpu" device-name +	" cpu" device-type +	" " encode-string " translations" property +	0 encode-phys h# 8000000 encode-int encode+ " available" property +	d# 32 encode-int " d-cache-block-size" property +	8 encode-int " d-cache-sets" property +	d# 32768 encode-int " d-cache-size" property +	d# 32 encode-int " i-cache-block-size" property +	8 encode-int " i-cache-sets" property +	d# 32768 encode-int " i-cache-size" property +	" " encode-string " cache-unified" property +	2 encode-int " i-tlb-sets" property +	d# 128 encode-int " i-tlb-size" property +	2 encode-int " d-tlb-sets" property +	d# 128 encode-int " d-tlb-size" property +	" " encode-string " tlb-split" property +	2 encode-int " tlb-sets" property +	d# 256 encode-int " tlb-size" property +	" " encode-string " performance-monitor" property +	" " encode-string " graphics" property +	4 encode-int " reservation-granule-size" property +        d# 25000000 encode-int " timebase-frequency" property +        d# 300000000 encode-int " clock-frequency" property +        d# 66000000 encode-int " bus-frequency" property +        h# 88201 encode-int " cpu-version" property +	0 encode-int " reg" property +finish-device + +" /pci" find-device +	h# 01000000 encode-int 0 encode-int encode+ 0 encode-int encode+ +	  h# 80000000 encode-int encode+ 0 encode-int encode+  +	  h# 01000000 encode-int encode+  +	h# 02000000 encode-int encode+ 0 encode-int encode+ 0 encode-int encode+  +	  h# C0000000 encode-int encode+ 0 encode-int encode+  +	  h# 08000000 encode-int encode+  +	" ranges" property +	" IBM,CPC710" model +	h# FF5F7700 encode-int " 8259-interrupt-acknowledge" property +	h# 0000F800 encode-int 0 encode-int encode+ 0 encode-int encode+  +	  7 encode-int encode+ +	  " interrupt-map-mask" property +	1 encode-int " #interrupt-cells" property +	h# 80000000 encode-int " system-dma-base" property +	d# 33333333 encode-int " clock-frequency" property +	" " encode-string " primary-bridge" property +	0 encode-int " pci-bridge-number" property +	h# FEC00000 encode-int h# 100000 encode-int encode+ " reg" property +	0 encode-int 0 encode-int encode+ " bus-range" property + +new-device +  " isa" device-name +  " isa" device-type +	2 encode-int " #address-cells" property +	1 encode-int " #size-cells" property + +  external +  : open true ; +  : close ; + +finish-device + +: ?devalias ( alias-str alias-len device-str device-len -- +  \		alias-str alias-len false | true ) +  active-package >r +  " /aliases" find-device +  \ 2dup ." Checking " type +  2dup find-dev if     \ check if device exists +    drop +    2over find-dev if  \ do we already have an alias? +      \ ." alias exists" cr +      drop 2drop false +    else +      \ ." device exists" cr +      encode-string +      2swap property +      true +    then +  else +    \ ." device doesn't exist" cr +    2drop false +  then +  r> active-package! +  ; + +:noname +  " hd" +  " /pci/pci-ata/ata-1/disk@0" ?devalias not if +    " /pci/pci-ata/ata-1/disk@1" ?devalias not if +      " /pci/pci-ata/ata-2/disk@0" ?devalias not if +        " /pci/pci-ata/ata-2/disk@1" ?devalias not if +	  2drop ." No disk found." cr +	then +      then +    then +  then + +  " cdrom" +  " /pci/pci-ata/ata-1/cdrom@0" ?devalias not if +    " /pci/pci-ata/ata-1/cdrom@1" ?devalias not if +      " /pci/pci-ata/ata-2/cdrom@0" ?devalias not if +        " /pci/pci-ata/ata-2/cdrom@1" ?devalias not if +	  2drop ." No cdrom found" cr +	then +      then +    then +  then +; SYSTEM-initializer + +new-device +	" ide" device-name +	" ide" device-type +	" WINBOND,82C553" model +	h# 28 encode-int " max-latency" property +	h# 2 encode-int " min-grant" property +	h# 1 encode-int " devsel-speed" property +	h# 0 encode-int " subsystem-vendor-id" property +	h# 0 encode-int " subsystem-id" property +	h# 1018A encode-int " class-code" property +	h# 5 encode-int " revision-id" property +	h# 105 encode-int " device-id" property +	h# 10AD encode-int " vendor-id" property +	h# 1003110 encode-int 0 encode-int encode+ h# 10020 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  h# 1003114 encode-int 0 encode-int encode+ h# 10030 encode-int encode+ +	  h# 4 encode-int encode+ 0 encode-int encode+ +	  h# 1003118 encode-int 0 encode-int encode+ h# 10040 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  h# 100311C encode-int 0 encode-int encode+ h# 10034 encode-int encode+ +	  h# 4 encode-int encode+ 0 encode-int encode+ +	  h# 1003120 encode-int 0 encode-int encode+ h# 10050 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  h# 1003124 encode-int 0 encode-int encode+ h# 10060 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  " assigned-addresses" property +	h# 3100 encode-int 0 encode-int encode+ 0 encode-int encode+ +	  0 encode-int encode+ 0 encode-int encode+ +	  h# 1003110 encode-int 0 encode-int encode+ h# 0 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  h# 1003114 encode-int 0 encode-int encode+ h# 0 encode-int encode+ +	  h# 4 encode-int encode+ 0 encode-int encode+ +	  h# 1003118 encode-int 0 encode-int encode+ h# 0 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  h# 100311C encode-int 0 encode-int encode+ h# 0 encode-int encode+ +	  h# 4 encode-int encode+ 0 encode-int encode+ +	  h# 1003120 encode-int 0 encode-int encode+ h# 0 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  h# 1003124 encode-int 0 encode-int encode+ h# 0 encode-int encode+ +	  h# 10 encode-int encode+ 0 encode-int encode+ +	  " reg" property +finish-device + +new-device +	" ethernet" device-name +	" network" device-type +	" AMD,79C973" model +	h# 3800 encode-int 0 encode-int encode+ 0 encode-int encode+ +	  0 encode-int encode+ 0 encode-int encode+ +	  " reg" property +finish-device + +" /pci/isa" find-device +	0 0 " assigned-addresses" property +	0 0 " ranges" property +	0 encode-int " slot-names" property +	d# 8333333 encode-int " clock-frequency" property +	0 encode-int " eisa-slots" property +	2 encode-int " #interrupt-cells" property +	" W83C553F" encode-string " compatible" property +	" WINBOND,82C553" model +	0 encode-int " max-latency" property +	0 encode-int " min-grant" property +	1 encode-int " devsel-speed" property +	0 encode-int " subsystem-vendor-id" property +	0 encode-int " subsystem-id" property +	h# 60100 encode-int " class-code" property +	h# 10 encode-int " revision-id" property +	h# 565 encode-int " device-id" property +	h# 10AD encode-int " vendor-id" property +	h# 3000 encode-int 0 encode-int encode+ 0 encode-int encode+ +	  0 encode-int encode+ 0 encode-int encode+ " reg" property + +new-device +	" rtc" device-name +	" rtc" device-type +	" DS17285S" model +	" MC146818" encode-string +	" DS17285S" encode-string encode+ +	" pnpPNP,b00" encode-string encode+ " compatible" property +	8 encode-int 0 encode-int encode+ " interrupts" property +	h# 70 encode-int 1 encode-int encode+ +	  2 encode-int encode+ " reg" property +finish-device + +new-device +	" interrupt-controller" device-name +	" interrupt-controller" device-type +	" 8259" model +	" " encode-string " interrupt-controller" property +	2 encode-int " #interrupt-cells" property +	1 encode-int  +	2 encode-int encode+ +	3 encode-int encode+ +	6 encode-int encode+ +	  " reserved-interrupts" property +	" 8259" encode-string +	  " chrp,iic" encode-string encode+  +	  " compatible" property +	h# 20 encode-int 1 encode-int encode+ +	  2 encode-int encode+ " reg" property +finish-device + +new-device +	" serial" device-name +	" serial" device-type +	" no" encode-string " ctsrts" property +	" no" encode-string " xon" property +	" no" encode-string " parity" property +	d# 115200 encode-int " bps" property +	1 encode-int " stop-bits" property +	8 encode-int " data-bits" property +	h# 70800 encode-int " divisor" property +	h# 708000 encode-int " clock-frequency" property +	4 encode-int 0 encode-int encode+ " interrupts" property +	h# 3F8 encode-int 1 encode-int encode+ +	  8 encode-int encode+ " reg" property +finish-device + +" /pci" find-device +	" /pci/isa/interrupt-controller" find-dev if  +		encode-int " interrupt-parent" property  +	then +	h# 3800 encode-int 0 encode-int encode+  +	  0 encode-int encode+ 1 encode-int encode+ +	  " /pci/isa/interrupt-controller" find-dev if  +		encode-int encode+ +	  then +	  h# 0C encode-int encode+ 1 encode-int encode+ +	  " interrupt-map" property + +" /pci/isa" find-device +	" /pci/isa/interrupt-controller" find-dev if  +		encode-int " interrupt-parent" property  +	then + +\ ------------------------------------------------------------- +\ /packages +\ ------------------------------------------------------------- + +" /packages" find-device + +	" packages" device-name +	external +	\ allow packages to be opened with open-dev +	: open true ; +	: close ; + +\ /packages/terminal-emulator +new-device +	" terminal-emulator" device-name +	external +	: open true ; +	: close ; +	\ : write ( addr len -- actual ) +	\	dup -rot type +	\ ; +finish-device + +\ ------------------------------------------------------------- +\ The END +\ ------------------------------------------------------------- +device-end diff --git a/roms/openbios/arch/ppc/pearpc/vfd.c b/roms/openbios/arch/ppc/pearpc/vfd.c new file mode 100644 index 00000000..06485f2d --- /dev/null +++ b/roms/openbios/arch/ppc/pearpc/vfd.c @@ -0,0 +1,42 @@ +/* + *   Creation Date: <2004/08/28 17:29:43 greg> + *   Time-stamp: <2004/08/28 17:29:43 greg> + * + *	<vfd.c> + * + *	Simple text console + * + *   Copyright (C) 2004 Greg Watson + * + *   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 "pearpc/pearpc.h" + +static int vfd_is_open; + +static int +vfd_init( void ) +{ +	vfd_is_open = 1; +	return 0; +} + +void +vfd_close( void ) +{ +} + +int +vfd_draw_str( const char *str ) +{ +	if (!vfd_is_open) +		vfd_init(); + +	return 0; +} diff --git a/roms/openbios/arch/ppc/ppc.fs b/roms/openbios/arch/ppc/ppc.fs new file mode 100644 index 00000000..0414f22c --- /dev/null +++ b/roms/openbios/arch/ppc/ppc.fs @@ -0,0 +1,68 @@ +include config.fs + +\ ------------------------------------------------------------------------- +\ registers  +\ ------------------------------------------------------------------------- + +0 value %cr +0 value %ctr +0 value %lr +0 value %msr +0 value %srr0 +0 value %srr1 +0 value %pc							\ should be an alias for %srr0 + +0 value %r0 +0 value %r1 +0 value %r2 +0 value %r3 +0 value %r4 +0 value %r5 +0 value %r6 +0 value %r7 +0 value %r8 +0 value %r9 +0 value %r10 +0 value %r11 +0 value %r12 +0 value %r13 +0 value %r14 +0 value %r15 +0 value %r16 +0 value %r17 +0 value %r18 +0 value %r19 +0 value %r20 +0 value %r21 +0 value %r22 +0 value %r23 +0 value %r24 +0 value %r25 +0 value %r26 +0 value %r27 +0 value %r28 +0 value %r29 +0 value %r30 +0 value %r31 + +0 value %xer +0 value %sprg0 +0 value %sprg1 +0 value %sprg2 +0 value %sprg3 + +\ ------------------------------------------------------------------------- +\ Load VGA FCode driver blob +\ ------------------------------------------------------------------------- + +[IFDEF] CONFIG_DRIVER_VGA +  -1 value vga-driver-fcode +  " QEMU,VGA.bin" $encode-file to vga-driver-fcode +[THEN] + +\ ------------------------------------------------------------------------- +\ other +\ ------------------------------------------------------------------------- + +\ Set by BootX when booting Mac OS X +defer spin diff --git a/roms/openbios/arch/ppc/qemu/console.c b/roms/openbios/arch/ppc/qemu/console.c new file mode 100644 index 00000000..53a32152 --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/console.c @@ -0,0 +1,88 @@ +/* + *      <console.c> + * + *      Simple text console + * + *   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 "libopenbios/console.h" +#include "drivers/drivers.h" + +#ifdef CONFIG_DEBUG_CONSOLE +/* ****************************************************************** + *      common functions, implementing simple concurrent console + * ****************************************************************** */ + +static int mac_putchar(int c) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL +	escc_uart_putchar(c & 0xff); +#endif +        return c; +} + +static int mac_availchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL +	if (escc_uart_charav(CONFIG_SERIAL_PORT)) +        	return 1; +#endif +        return 0; +} + +static int mac_getchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL +	if (escc_uart_charav(CONFIG_SERIAL_PORT)) +		return (escc_uart_getchar(CONFIG_SERIAL_PORT)); +#endif +        return 0; +} + +struct _console_ops mac_console_ops = { +	.putchar = mac_putchar, +	.availchar = mac_availchar, +	.getchar = mac_getchar +}; + +static int prep_putchar(int c) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL +	uart_putchar(c & 0xff); +#endif +        return c; +} + +static int prep_availchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL +	if (uart_charav(CONFIG_SERIAL_PORT)) +		return 1; +#endif +        return 0; +} + +static int prep_getchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL +	if (uart_charav(CONFIG_SERIAL_PORT)) +		return (uart_getchar(CONFIG_SERIAL_PORT)); +#endif +        return 0; +} + +struct _console_ops prep_console_ops = { +	.putchar = prep_putchar, +	.availchar = prep_availchar, +	.getchar = prep_getchar +}; + +#endif	// CONFIG_DEBUG_CONSOLE diff --git a/roms/openbios/arch/ppc/qemu/init.c b/roms/openbios/arch/ppc/qemu/init.c new file mode 100644 index 00000000..4fe8b722 --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/init.c @@ -0,0 +1,951 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<init.c> + * + *	Initialization for qemu + * + *   Copyright (C) 2004 Greg Watson + *   Copyright (C) 2005 Stefan Reinauer + * + *   based on mol/init.c: + * + *   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 "libopenbios/console.h" +#include "drivers/pci.h" +#include "arch/common/nvram.h" +#include "drivers/drivers.h" +#include "qemu/qemu.h" +#include "libopenbios/ofmem.h" +#include "openbios-version.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" +#define NO_QEMU_PROTOS +#include "arch/common/fw_cfg.h" +#include "arch/ppc/processor.h" + +#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" + +struct cpudef { +    unsigned int iu_version; +    const char *name; +    int icache_size, dcache_size; +    int icache_sets, dcache_sets; +    int icache_block_size, dcache_block_size; +    int tlb_sets, tlb_size; +    void (*initfn)(const struct cpudef *cpu); +}; + +static uint16_t machine_id = 0; + +extern void unexpected_excep(int vector); + +void +unexpected_excep(int vector) +{ +    printk("openbios panic: Unexpected exception %x\n", vector); +    for (;;) { +    } +} + +extern void __divide_error(void); + +void +__divide_error(void) +{ +    return; +} + +enum { +    ARCH_PREP = 0, +    ARCH_MAC99, +    ARCH_HEATHROW, +    ARCH_MAC99_U3, +}; + +int is_apple(void) +{ +    return is_oldworld() || is_newworld(); +} + +int is_oldworld(void) +{ +    return machine_id == ARCH_HEATHROW; +} + +int is_newworld(void) +{ +    return (machine_id == ARCH_MAC99) || +           (machine_id == ARCH_MAC99_U3); +} + +static const pci_arch_t known_arch[] = { +    [ARCH_PREP] = { +        .name = "PREP", +        .vendor_id = PCI_VENDOR_ID_MOTOROLA, +        .device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN, +        .cfg_addr = 0x80000cf8, +        .cfg_data = 0x80000cfc, +        .cfg_base = 0x80000000, +        .cfg_len = 0x00100000, +        .host_pci_base = 0xc0000000, +        .pci_mem_base = 0x100000, /* avoid VGA at 0xa0000 */ +        .mem_len = 0x10000000, +        .io_base = 0x80000000, +        .io_len = 0x00010000, +        .rbase = 0x00000000, +        .rlen = 0x00400000, +        .irqs = { 9, 11, 9, 11 } +    }, +    [ARCH_MAC99] = { +        .name = "MAC99", +        .vendor_id = PCI_VENDOR_ID_APPLE, +        .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI, +        .cfg_addr = 0xf2800000, +        .cfg_data = 0xf2c00000, +        .cfg_base = 0xf2000000, +        .cfg_len = 0x02000000, +        .host_pci_base = 0x0, +        .pci_mem_base = 0x80000000, +        .mem_len = 0x10000000, +        .io_base = 0xf2000000, +        .io_len = 0x00800000, +        .rbase = 0x00000000, +        .rlen = 0x01000000, +        .irqs = { 0x1b, 0x1c, 0x1d, 0x1e } +    }, +    [ARCH_MAC99_U3] = { +        .name = "MAC99_U3", +        .vendor_id = PCI_VENDOR_ID_APPLE, +        .device_id = PCI_DEVICE_ID_APPLE_U3_AGP, +        .cfg_addr = 0xf0800000, +        .cfg_data = 0xf0c00000, +        .cfg_base = 0xf0000000, +        .cfg_len = 0x02000000, +        .host_pci_base = 0x0, +        .pci_mem_base = 0x80000000, +        .mem_len = 0x10000000, +        .io_base = 0xf2000000, +        .io_len = 0x00800000, +        .rbase = 0x00000000, +        .rlen = 0x01000000, +        .irqs = { 0x1b, 0x1c, 0x1d, 0x1e } +    }, +    [ARCH_HEATHROW] = { +        .name = "HEATHROW", +        .vendor_id = PCI_VENDOR_ID_MOTOROLA, +        .device_id = PCI_DEVICE_ID_MOTOROLA_MPC106, +        .cfg_addr = 0xfec00000, +        .cfg_data = 0xfee00000, +        .cfg_base = 0x80000000, +        .cfg_len = 0x7f000000, +        .host_pci_base = 0x0, +        .pci_mem_base = 0x80000000, +        .mem_len = 0x10000000, +        .io_base = 0xfe000000, +        .io_len = 0x00800000, +        .rbase = 0xfd000000, +        .rlen = 0x01000000, +        .irqs = { 21, 22, 23, 24 } +    }, +}; +unsigned long isa_io_base; + +extern struct _console_ops mac_console_ops, prep_console_ops; + +void +entry(void) +{ +    uint32_t temp = 0; +    char buf[5]; + +    arch = &known_arch[ARCH_HEATHROW]; + +    fw_cfg_init(); + +    fw_cfg_read(FW_CFG_SIGNATURE, buf, 4); +    buf[4] = '\0'; +    if (strncmp(buf, "QEMU", 4) == 0) { +        temp = fw_cfg_read_i32(FW_CFG_ID); +        if (temp == 1) { +            machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID); +            arch = &known_arch[machine_id]; +        } +    } + +    isa_io_base = arch->io_base; + +#ifdef CONFIG_DEBUG_CONSOLE +    if (is_apple()) { +        init_console(mac_console_ops); +    } else { +        init_console(prep_console_ops); +    } +#endif + +    if (temp != 1) { +        printk("Incompatible configuration device version, freezing\n"); +        for (;;) { +        } +    } + +    ofmem_init(); +    initialize_forth(); +    /* won't return */ + +    printk("of_startup returned!\n"); +    for (;;) { +    } +} + +/* -- phys.lo ... phys.hi */ +static void +push_physaddr(phys_addr_t value) +{ +    PUSH(value); +#ifdef CONFIG_PPC64 +    PUSH(value >> 32); +#endif +} + +/* From drivers/timer.c */ +extern unsigned long timer_freq; + +static void +cpu_generic_init(const struct cpudef *cpu) +{ +    push_str("/cpus"); +    fword("find-device"); + +    fword("new-device"); + +    push_str(cpu->name); +    fword("device-name"); + +    push_str("cpu"); +    fword("device-type"); + +    PUSH(mfpvr()); +    fword("encode-int"); +    push_str("cpu-version"); +    fword("property"); + +    PUSH(cpu->dcache_size); +    fword("encode-int"); +    push_str("d-cache-size"); +    fword("property"); + +    PUSH(cpu->icache_size); +    fword("encode-int"); +    push_str("i-cache-size"); +    fword("property"); + +    PUSH(cpu->dcache_sets); +    fword("encode-int"); +    push_str("d-cache-sets"); +    fword("property"); + +    PUSH(cpu->icache_sets); +    fword("encode-int"); +    push_str("i-cache-sets"); +    fword("property"); + +    PUSH(cpu->dcache_block_size); +    fword("encode-int"); +    push_str("d-cache-block-size"); +    fword("property"); + +    PUSH(cpu->icache_block_size); +    fword("encode-int"); +    push_str("i-cache-block-size"); +    fword("property"); + +    PUSH(cpu->tlb_sets); +    fword("encode-int"); +    push_str("tlb-sets"); +    fword("property"); + +    PUSH(cpu->tlb_size); +    fword("encode-int"); +    push_str("tlb-size"); +    fword("property"); + +    timer_freq = fw_cfg_read_i32(FW_CFG_PPC_TBFREQ); +    PUSH(timer_freq); +    fword("encode-int"); +    push_str("timebase-frequency"); +    fword("property"); + +    PUSH(fw_cfg_read_i32(FW_CFG_PPC_CLOCKFREQ)); +    fword("encode-int"); +    push_str("clock-frequency"); +    fword("property"); + +    PUSH(fw_cfg_read_i32(FW_CFG_PPC_BUSFREQ)); +    fword("encode-int"); +    push_str("bus-frequency"); +    fword("property"); + +    push_str("running"); +    fword("encode-string"); +    push_str("state"); +    fword("property"); +} + +static void +cpu_add_pir_property(void) +{ +    unsigned long pir; + +    asm("mfspr %0, 1023\n" +        : "=r"(pir) :); +    PUSH(pir); +    fword("encode-int"); +    push_str("reg"); +    fword("property"); +} + +static void +cpu_604_init(const struct cpudef *cpu) +{ +    cpu_generic_init(cpu); +    cpu_add_pir_property(); + +    fword("finish-device"); +} + +static void +cpu_750_init(const struct cpudef *cpu) +{ +    cpu_generic_init(cpu); + +    PUSH(0); +    fword("encode-int"); +    push_str("reg"); +    fword("property"); + +    fword("finish-device"); +} + +static void +cpu_g4_init(const struct cpudef *cpu) +{ +    cpu_generic_init(cpu); +    cpu_add_pir_property(); + +    fword("finish-device"); +} + +#ifdef CONFIG_PPC_64BITSUPPORT +/* In order to get 64 bit aware handlers that rescue all our +   GPRs from getting truncated to 32 bits, we need to patch the +   existing handlers so they jump to our 64 bit aware ones. */ +static void +ppc64_patch_handlers(void) +{ +    uint32_t *dsi = (uint32_t *)0x300UL; +    uint32_t *isi = (uint32_t *)0x400UL; + +    // Patch the first DSI handler instruction to: ba 0x2000 +    *dsi = 0x48002002; + +    // Patch the first ISI handler instruction to: ba 0x2200 +    *isi = 0x48002202; + +    // Invalidate the cache lines +    asm ("icbi 0, %0" : : "r"(dsi)); +    asm ("icbi 0, %0" : : "r"(isi)); +} +#endif + +static void +cpu_970_init(const struct cpudef *cpu) +{ +    cpu_generic_init(cpu); + +    PUSH(0); +    fword("encode-int"); +    push_str("reg"); +    fword("property"); +     +    PUSH(0); +    PUSH(0); +    fword("encode-bytes"); +    push_str("64-bit"); +    fword("property"); + +    fword("finish-device"); + +#ifdef CONFIG_PPC_64BITSUPPORT +    /* The 970 is a PPC64 CPU, so we need to activate +     * 64bit aware interrupt handlers */ + +    ppc64_patch_handlers(); +#endif + +    /* The 970 also implements the HIOR which we need to set to 0 */ + +    mtspr(S_HIOR, 0); +} + +static const struct cpudef ppc_defs[] = { +    { +        .iu_version = 0x00040000, +        .name = "PowerPC,604", +        .icache_size = 0x4000, +        .dcache_size = 0x4000, +        .icache_sets = 0x80, +        .dcache_sets = 0x80, +        .icache_block_size = 0x20, +        .dcache_block_size = 0x20, +        .tlb_sets = 0x40, +        .tlb_size = 0x80, +        .initfn = cpu_604_init, +    }, +    { // XXX find out real values +        .iu_version = 0x00090000, +        .name = "PowerPC,604e", +        .icache_size = 0x4000, +        .dcache_size = 0x4000, +        .icache_sets = 0x80, +        .dcache_sets = 0x80, +        .icache_block_size = 0x20, +        .dcache_block_size = 0x20, +        .tlb_sets = 0x40, +        .tlb_size = 0x80, +        .initfn = cpu_604_init, +    }, +    { // XXX find out real values +        .iu_version = 0x000a0000, +        .name = "PowerPC,604r", +        .icache_size = 0x4000, +        .dcache_size = 0x4000, +        .icache_sets = 0x80, +        .dcache_sets = 0x80, +        .icache_block_size = 0x20, +        .dcache_block_size = 0x20, +        .tlb_sets = 0x40, +        .tlb_size = 0x80, +        .initfn = cpu_604_init, +    }, +    { // XXX find out real values +        .iu_version = 0x80040000, +        .name = "PowerPC,MPC86xx", +        .icache_size = 0x8000, +        .dcache_size = 0x8000, +        .icache_sets = 0x80, +        .dcache_sets = 0x80, +        .icache_block_size = 0x20, +        .dcache_block_size = 0x20, +        .tlb_sets = 0x40, +        .tlb_size = 0x80, +        .initfn = cpu_750_init, +    }, +    { +        .iu_version = 0x000080000, +        .name = "PowerPC,750", +        .icache_size = 0x8000, +        .dcache_size = 0x8000, +        .icache_sets = 0x80, +        .dcache_sets = 0x80, +        .icache_block_size = 0x20, +        .dcache_block_size = 0x20, +        .tlb_sets = 0x40, +        .tlb_size = 0x80, +        .initfn = cpu_750_init, +    }, +    { // XXX find out real values +        .iu_version = 0x10080000, +        .name = "PowerPC,750", +        .icache_size = 0x8000, +        .dcache_size = 0x8000, +        .icache_sets = 0x80, +        .dcache_sets = 0x80, +        .icache_block_size = 0x20, +        .dcache_block_size = 0x20, +        .tlb_sets = 0x40, +        .tlb_size = 0x80, +        .initfn = cpu_750_init, +    }, +    { // XXX find out real values +        .iu_version = 0x70000000, +        .name = "PowerPC,750", +        .icache_size = 0x8000, +        .dcache_size = 0x8000, +        .icache_sets = 0x80, +        .dcache_sets = 0x80, +        .icache_block_size = 0x20, +        .dcache_block_size = 0x20, +        .tlb_sets = 0x40, +        .tlb_size = 0x80, +        .initfn = cpu_750_init, +    }, +    { // XXX find out real values +        .iu_version = 0x70020000, +        .name = "PowerPC,750", +        .icache_size = 0x8000, +        .dcache_size = 0x8000, +        .icache_sets = 0x80, +        .dcache_sets = 0x80, +        .icache_block_size = 0x20, +        .dcache_block_size = 0x20, +        .tlb_sets = 0x40, +        .tlb_size = 0x80, +        .initfn = cpu_750_init, +    }, +    { // XXX find out real values +        .iu_version = 0x800c0000, +        .name = "PowerPC,74xx", +        .icache_size = 0x8000, +        .dcache_size = 0x8000, +        .icache_sets = 0x80, +        .dcache_sets = 0x80, +        .icache_block_size = 0x20, +        .dcache_block_size = 0x20, +        .tlb_sets = 0x40, +        .tlb_size = 0x80, +        .initfn = cpu_750_init, +    }, +    { +        .iu_version = 0x0000c0000, +        .name = "PowerPC,G4", +        .icache_size = 0x8000, +        .dcache_size = 0x8000, +        .icache_sets = 0x80, +        .dcache_sets = 0x80, +        .icache_block_size = 0x20, +        .dcache_block_size = 0x20, +        .tlb_sets = 0x40, +        .tlb_size = 0x80, +        .initfn = cpu_g4_init, +    }, +    { +        .iu_version = 0x00390000, +        .name = "PowerPC,970", +        .icache_size = 0x10000, +        .dcache_size = 0x8000, +        .icache_sets = 0x200, +        .dcache_sets = 0x80, +        .icache_block_size = 0x80, +        .dcache_block_size = 0x80, +        .tlb_sets = 0x100, +        .tlb_size = 0x1000, +        .initfn = cpu_970_init, +    }, +    { // XXX find out real values +        .iu_version = 0x003C0000, +        .name = "PowerPC,970FX", +        .icache_size = 0x10000, +        .dcache_size = 0x8000, +        .icache_sets = 0x80, +        .dcache_sets = 0x80, +        .icache_block_size = 0x80, +        .dcache_block_size = 0x80, +        .tlb_sets = 0x100, +        .tlb_size = 0x1000, +        .initfn = cpu_970_init, +    }, +    { +        .iu_version = 0x00350000, +        .name = "PowerPC,POWER4", +        .icache_size = 0x10000, +        .dcache_size = 0x8000, +        .icache_sets = 0x100, +        .dcache_sets = 0x40, +        .icache_block_size = 0x80, +        .dcache_block_size = 0x80, +        .tlb_sets = 0x100, +        .tlb_size = 0x1000, +        .initfn = cpu_970_init, +    }, +}; + +static const struct cpudef * +id_cpu(void) +{ +    unsigned int iu_version; +    unsigned int i; + +    iu_version = mfpvr() & 0xffff0000; + +    for (i = 0; i < sizeof(ppc_defs) / sizeof(struct cpudef); i++) { +        if (iu_version == ppc_defs[i].iu_version) +            return &ppc_defs[i]; +    } +    printk("Unknown cpu (pvr %x), freezing!\n", iu_version); +    for (;;) { +    } +} + +static void go(void); + +static void +go(void) +{ +    ucell addr; + +    feval("saved-program-state >sps.entry @"); +    addr = POP(); + +    call_elf(0, 0, addr); +} + +static void kvm_of_init(void) +{ +    char hypercall[4 * 4]; +    uint32_t *hc32; + +    /* Don't expose /hypervisor when not in KVM */ +    if (!fw_cfg_read_i32(FW_CFG_PPC_IS_KVM)) +        return; + +    push_str("/"); +    fword("find-device"); + +    fword("new-device"); + +    push_str("hypervisor"); +    fword("device-name"); + +    push_str("hypervisor"); +    fword("device-type"); + +    /* compatible */ + +    push_str("linux,kvm"); +    fword("encode-string"); +    push_str("epapr,hypervisor-0.2"); +    fword("encode-string"); +    fword("encode+"); +    push_str("compatible"); +    fword("property"); + +    /* Tell the guest about the hypercall instructions */ +    fw_cfg_read(FW_CFG_PPC_KVM_HC, hypercall, 4 * 4); +    hc32 = (uint32_t*)hypercall; +    PUSH(hc32[0]); +    fword("encode-int"); +    PUSH(hc32[1]); +    fword("encode-int"); +    fword("encode+"); +    PUSH(hc32[2]); +    fword("encode-int"); +    fword("encode+"); +    PUSH(hc32[3]); +    fword("encode-int"); +    fword("encode+"); +    push_str("hcall-instructions"); +    fword("property"); + +    /* ePAPR requires us to provide a unique guest id */ +    PUSH(fw_cfg_read_i32(FW_CFG_PPC_KVM_PID)); +    fword("encode-int"); +    push_str("guest-id"); +    fword("property"); + +    /* ePAPR requires us to provide a guest name */ +    push_str("KVM guest"); +    fword("encode-string"); +    push_str("guest-name"); +    fword("property"); + +    fword("finish-device"); +} + +/* + *  filll        ( addr bytes quad -- ) + */ + +static void ffilll(void) +{ +    const u32 longval = POP(); +    u32 bytes = POP(); +    u32 *laddr = (u32 *)cell2pointer(POP()); +    u32 len; +     +    for (len = 0; len < bytes / sizeof(u32); len++) { +        *laddr++ = longval; +    }    +} + +void +arch_of_init(void) +{ +#ifdef CONFIG_RTAS +    phandle_t ph; +#endif +    uint64_t ram_size; +    const struct cpudef *cpu; +    char buf[64], qemu_uuid[16]; +    const char *stdin_path, *stdout_path, *boot_path; +    uint32_t temp = 0; +    char *boot_device; +    ofmem_t *ofmem = ofmem_arch_get_private(); + +    openbios_init(); +    modules_init(); +    setup_timers(); +#ifdef CONFIG_DRIVER_PCI +    ob_pci_init(); +#endif + +    printk("\n"); +    printk("=============================================================\n"); +    printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n", +           OPENBIOS_BUILD_DATE); + +    fw_cfg_read(FW_CFG_SIGNATURE, buf, 4); +    buf[4] = '\0'; +    printk("Configuration device id %s", buf); + +    temp = fw_cfg_read_i32(FW_CFG_ID); +    printk(" version %d machine id %d\n", temp, machine_id); + +    temp = fw_cfg_read_i32(FW_CFG_NB_CPUS); + +    printk("CPUs: %x\n", temp); + +    ram_size = ofmem->ramsize; + +    printk("Memory: %lldM\n", ram_size / 1024 / 1024); + +    fw_cfg_read(FW_CFG_UUID, qemu_uuid, 16); + +    printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], +           qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], +           qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], +           qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], +           qemu_uuid[15]); + +    /* set device tree root info */ + +    push_str("/"); +    fword("find-device"); + +    switch(machine_id) { +    case ARCH_HEATHROW:	/* OldWorld */ + +        /* model */ + +        push_str("Power Macintosh"); +        fword("model"); + +        /* compatible */ + +        push_str("AAPL,PowerMac G3"); +        fword("encode-string"); +        push_str("MacRISC"); +        fword("encode-string"); +        fword("encode+"); +        push_str("compatible"); +        fword("property"); + +        /* misc */ + +        push_str("device-tree"); +        fword("encode-string"); +        push_str("AAPL,original-name"); +        fword("property"); + +        PUSH(0); +        fword("encode-int"); +        push_str("AAPL,cpu-id"); +        fword("property"); + +        PUSH(66 * 1000 * 1000); +        fword("encode-int"); +        push_str("clock-frequency"); +        fword("property"); +        break; + +    case ARCH_MAC99: +    case ARCH_MAC99_U3: +    case ARCH_PREP: +    default: + +        /* model */ + +        push_str("PowerMac3,1"); +        fword("model"); + +        /* compatible */ + +        push_str("PowerMac3,1"); +        fword("encode-string"); +        push_str("MacRISC"); +        fword("encode-string"); +        fword("encode+"); +        push_str("MacRISC2"); +        fword("encode-string"); +        fword("encode+"); +        push_str("Power Macintosh"); +        fword("encode-string"); +        fword("encode+"); +        push_str("compatible"); +        fword("property"); + +        /* misc */ + +        push_str("bootrom"); +        fword("device-type"); + +        PUSH(100 * 1000 * 1000); +        fword("encode-int"); +        push_str("clock-frequency"); +        fword("property"); +        break; +    } + +    /* Perhaps we can store UUID here ? */ + +    push_str("0000000000000"); +    fword("encode-string"); +    push_str("system-id"); +    fword("property"); + +    /* memory info */ + +    push_str("/memory"); +    fword("find-device"); + +    /* all memory */ + +    push_physaddr(0); +    fword("encode-phys"); +    /* This needs adjusting if #size-cells gets increased. +       Alternatively use multiple (address, size) tuples. */ +    PUSH(ram_size & 0xffffffff); +    fword("encode-int"); +    fword("encode+"); +    push_str("reg"); +    fword("property"); + +    cpu = id_cpu(); +    cpu->initfn(cpu); +    printk("CPU type %s\n", cpu->name); + +    snprintf(buf, sizeof(buf), "/cpus/%s", cpu->name); +    ofmem_register(find_dev("/memory"), find_dev(buf)); +    node_methods_init(buf); + +#ifdef CONFIG_RTAS +    /* OldWorld Macs don't have an /rtas node. */ +    switch (machine_id) { +    case ARCH_MAC99: +    case ARCH_MAC99_U3: +        if (!(ph = find_dev("/rtas"))) { +            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; +            set_property(ph, "rtas-size", (char*)&size, sizeof(size)); +            set_int_property(ph, "rtas-version", is_apple() ? 0x41 : 1); +        } +        break; +    } +#endif + +    if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) { +        if (is_apple()) { +            if (CONFIG_SERIAL_PORT) { +                stdin_path = "scca"; +                stdout_path = "scca"; +            } else { +                stdin_path = "sccb"; +                stdout_path = "sccb"; +            } +        } else { +            stdin_path = "ttya"; +            stdout_path = "ttya"; +        } + +        /* Some bootloaders force the output to the screen device, so +           let's create a screen alias for the serial device too */ + +        push_str("/aliases"); +        fword("find-device"); + +        push_str(stdout_path); +        fword("pathres-resolve-aliases"); +        fword("encode-string"); +        push_str("screen"); +        fword("property"); +    } else { +        if (is_apple()) { +            stdin_path = "adb-keyboard"; +            stdout_path = "screen"; +        } else { +            stdin_path = "keyboard"; +            stdout_path = "screen"; +        } +    } + +    kvm_of_init(); + +    /* Setup nvram variables */ +    push_str("/options"); +    fword("find-device"); + +    /* Setup default boot devices (not overriding user settings) */ +    fword("boot-device"); +    boot_device = pop_fstr_copy(); +    if (boot_device && strcmp(boot_device, "disk") == 0) { +        switch (fw_cfg_read_i16(FW_CFG_BOOT_DEVICE)) { +            case 'c': +                boot_path = "hd"; +                break; +            default: +            case 'd': +                boot_path = "cd"; +                break; +        } + +        snprintf(buf, sizeof(buf), "%s:,\\\\:tbxi %s:,\\ppc\\bootinfo.txt %s:,%%BOOT", boot_path, boot_path, boot_path); +        push_str(buf); +        fword("encode-string"); +        push_str("boot-device"); +        fword("property"); +    } +    free(boot_device); + +    /* Set up other properties */ + +    push_str("/chosen"); +    fword("find-device"); + +    push_str(stdin_path); +    fword("pathres-resolve-aliases"); +    push_str("input-device"); +    fword("$setenv"); + +    push_str(stdout_path); +    fword("pathres-resolve-aliases"); +    push_str("output-device"); +    fword("$setenv"); + +#if 0 +    if(getbool("tty-interface?") == 1) +#endif +        fword("activate-tty-interface"); + +    device_end(); + +    /* Implementation of filll word (required by BootX) */ +    bind_func("filll", ffilll); +     +    bind_func("platform-boot", boot); +    bind_func("(go)", go); +} diff --git a/roms/openbios/arch/ppc/qemu/kernel.c b/roms/openbios/arch/ppc/qemu/kernel.c new file mode 100644 index 00000000..b26fba5f --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/kernel.c @@ -0,0 +1,115 @@ +/* + *   Creation Date: <2003/10/25 14:07:17 samuel> + *   Time-stamp: <2004/08/28 17:48:19 stepan> + * + *	<kernel.c> + * + *   Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + *   Copyright (C) 2003, 2004 Stefan Reinauer + * + *   Based upon unix.c (from OpenBIOS): + * + *   Copyright (C) 2003 Patrick Mauritz, 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 "config.h" +#include "dict.h" +#include "libopenbios/bindings.h" +#include "kernel/stack.h" +#include "kernel/kernel.h" +#include "libc/string.h" +#include "kernel.h" + +#define MEMORY_SIZE	(256*1024)	/* 256K ram for hosted system */ +/* 512K for the dictionary  */ +#define DICTIONARY_SIZE (512 * 1024 / sizeof(ucell)) +#ifdef __powerpc64__ +#define DICTIONARY_BASE 0xfff08000 /* this must match the value in ldscript! */ +#define DICTIONARY_SECTION __attribute__((section(".data.dict"))) +#else +#define DICTIONARY_BASE ((ucell)((char *)&forth_dictionary)) +#define DICTIONARY_SECTION +#endif + +static ucell forth_dictionary[DICTIONARY_SIZE] DICTIONARY_SECTION = { +#include "qemu-dict.h" +}; + +static ucell 		*memory; + +/************************************************************************/ +/*	F U N C T I O N S						*/ +/************************************************************************/ + +int +forth_segv_handler( char *segv_addr ) +{ +	ucell addr = 0xdeadbeef; + +	if( PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead ) +		addr = *(ucell *)cell2pointer(PC); + +	printk("panic: segmentation violation at 0x%p\n", segv_addr); +	printk("dict=0x%p here=0x%p(dict+0x%x) pc=0x%x(dict+0x%x)\n", +	       dict, (char*)dict + dicthead, dicthead, +	       PC, PC - pointer2cell(dict)); +	printk("dstackcnt=%d rstackcnt=%d instruction=%x\n", +	       dstackcnt, rstackcnt, addr); + +#ifdef DEBUG_DSTACK +	printdstack(); +#endif +#ifdef DEBUG_RSTACK +	printrstack(); +#endif +	return -1; +} + +/* + * allocate memory and prepare engine for memory management. + */ + +static void +init_memory( void ) +{ +	memory = malloc(MEMORY_SIZE); +	if( !memory ) +		panic("panic: not enough memory on host system.\n"); + +	/* we push start and end of memory to the stack +	 * so that it can be used by the forth word QUIT +	 * to initialize the memory allocator +	 */ + +	PUSH( pointer2cell(memory) ); +	PUSH( pointer2cell(memory) + MEMORY_SIZE ); +} + +int +initialize_forth( void ) +{ +        dict = (unsigned char *)forth_dictionary; +        dicthead = (ucell)FORTH_DICTIONARY_END; +        last = (ucell *)((unsigned char *)forth_dictionary + +                         FORTH_DICTIONARY_LAST); +        dictlimit = sizeof(forth_dictionary); + +	forth_init(); + +	PUSH_xt( bind_noname_func(arch_of_init) ); +	fword("PREPOST-initializer"); + +	PC = (ucell)findword("initialize-of"); +	if( PC ) { +		init_memory(); +		enterforth((xt_t)PC); +		free( memory ); +	} +	free( dict ); +	return 0; +} diff --git a/roms/openbios/arch/ppc/qemu/kernel.h b/roms/openbios/arch/ppc/qemu/kernel.h new file mode 100644 index 00000000..fe9be83d --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/kernel.h @@ -0,0 +1,42 @@ +/* + *   Creation Date: <2004/08/28 17:50:12 stepan> + *   Time-stamp: <2004/08/28 17:50:12 stepan> + * + *	<kernel.h> + * + *   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 + * + */ + +#ifndef __KERNEL_H__ +#define __KERNEL_H__ + +/* misc.c */ +extern void		fatal_error( const char *str ); +extern void		exit( int status ) __attribute__ ((noreturn)); + +/* start.S */ +extern void 		flush_icache_range( char *start, char *stop ); +extern char		of_rtas_start[], of_rtas_end[]; +extern void             call_elf( unsigned long arg1, unsigned long arg2, unsigned long elf_entry ); + +/* methods.c */ +extern void		node_methods_init( const char *cpuname ); + +/* main.c */ +extern void 		boot( void ); + +/* init.c */ +extern void		entry( void ); +extern void 		arch_of_init( void ); +extern int		get_bool_res( const char *str ); + +/* tree.c */ +extern void		devtree_init( void ); + + +#endif   /* __KERNEL_H__ */ diff --git a/roms/openbios/arch/ppc/qemu/ldscript b/roms/openbios/arch/ppc/qemu/ldscript new file mode 100644 index 00000000..8027b39d --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/ldscript @@ -0,0 +1,68 @@ +OUTPUT_FORMAT(elf32-powerpc) +OUTPUT_ARCH(powerpc:common) + +/* Initial load address + */ +BASE_ADDR = 0xfff00000; + +/* As NVRAM is at 0xfff04000, the .text needs to be after that + */ +TEXT_ADDR = 0xfff08000; + +/* Hard reset vector address + */ +HRESET_ADDR = 0xfffffffc; + +CSTACK_SIZE = 32768;	/* client stack size */ + +SECTIONS +{ +    . = BASE_ADDR; + +    _start = BASE_ADDR + 0x0100; +    .text.vectors ALIGN(4096): { +        *(.text.vectors) +    } + +    . = TEXT_ADDR; +    /* Normal sections */ +    .text ALIGN(4096): { +        *(.text) +        *(.text.*) +    } + +    .rodata ALIGN(4096): { +        _rodata = .; +	*(.rodata) +	*(.rodata.*) +        *(.note.ELFBoot) +    } +    .data ALIGN(4096): { +        _data = .; +        *(.data) +        *(.data.*) +	_edata = .; +    } + +    .bss ALIGN(4096): { +        _bss = .; +	*(.sbss) +	*(.sbss.*) +	*(.bss) +	*(.bss.*) +	*(COMMON) +	_ebss = .; +    } + +    . = HRESET_ADDR; + +    .romentry : { *(.romentry) } + +    . = ALIGN(4096); +    _end = .; + +    /* We discard .note sections other than .note.ELFBoot, +     * because some versions of GCC generates useless ones. */ + +    /DISCARD/ : { *(.comment*) *(.note.*) } +} diff --git a/roms/openbios/arch/ppc/qemu/main.c b/roms/openbios/arch/ppc/qemu/main.c new file mode 100644 index 00000000..44b16666 --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/main.c @@ -0,0 +1,85 @@ +/* + *   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/elf_load.h" +#include "arch/common/nvram.h" +#include "packages/nvram.h" +#include "libc/diskio.h" +#include "libc/vsprintf.h" +#include "kernel.h" +#include "drivers/drivers.h" +#include "libopenbios/ofmem.h" +#define NO_QEMU_PROTOS +#include "arch/common/fw_cfg.h" + +//#define DEBUG_QEMU + +#ifdef DEBUG_QEMU +#define SUBSYS_DPRINTF(subsys, fmt, args...) \ +    do { printk("%s - %s: " fmt, subsys, __func__ , ##args); } while (0) +#else +#define SUBSYS_DPRINTF(subsys, fmt, args...) \ +    do { } while (0) +#endif +#define CHRP_DPRINTF(fmt, args...) SUBSYS_DPRINTF("CHRP", fmt, ##args) +#define ELF_DPRINTF(fmt, args...) SUBSYS_DPRINTF("ELF", fmt, ##args) +#define NEWWORLD_DPRINTF(fmt, args...) SUBSYS_DPRINTF("NEWWORLD", fmt, ##args) + +static void check_preloaded_kernel(void) +{ +    unsigned long kernel_image, kernel_size; +    unsigned long initrd_image, initrd_size; +    const char * kernel_cmdline; + +    kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE); +    if (kernel_size) { +        kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR); +        kernel_cmdline = (const char *)(uintptr_t) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE); +        initrd_image = fw_cfg_read_i32(FW_CFG_INITRD_ADDR); +        initrd_size = fw_cfg_read_i32(FW_CFG_INITRD_SIZE); +        printk("[ppc] Kernel already loaded (0x%8.8lx + 0x%8.8lx) " +               "(initrd 0x%8.8lx + 0x%8.8lx)\n", +               kernel_image, kernel_size, initrd_image, initrd_size); +        if (kernel_cmdline) { +               phandle_t ph; +	       printk("[ppc] Kernel command line: %s\n", kernel_cmdline); +	       ph = find_dev("/chosen"); +               set_property(ph, "bootargs", strdup(kernel_cmdline), strlen(kernel_cmdline) + 1); +        } +        call_elf(initrd_image, initrd_size, kernel_image); +    } +} + +/************************************************************************/ +/*	entry								*/ +/************************************************************************/ + +void +boot( void ) +{ +        uint16_t boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE); + +	fword("update-chosen"); +	if (boot_device == 'm') { +	        check_preloaded_kernel(); +	} + +	if (is_apple()) { +		update_nvram(); +	} +} diff --git a/roms/openbios/arch/ppc/qemu/methods.c b/roms/openbios/arch/ppc/qemu/methods.c new file mode 100644 index 00000000..fd993daa --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/methods.c @@ -0,0 +1,327 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<methods.c> + * + *	Misc device node methods + * + *   Copyright (C) 2004 Greg Watson + * + *   Based on MOL specific code which is + * + *   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 "drivers/drivers.h" +#include "libc/string.h" +#include "qemu/qemu.h" +#include "libopenbios/ofmem.h" +#include "arch/ppc/processor.h" +#include "drivers/usb.h" + +/************************************************************************/ +/*	RTAS (run-time abstraction services)				*/ +/************************************************************************/ + +#ifdef CONFIG_RTAS +DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" ); + +/* ( physbase -- rtas_callback ) */ +static void +rtas_instantiate( void ) +{ +	ucell physbase = POP(); +	ucell s=0x1000, size = (ucell)of_rtas_end - (ucell)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 }, +}; +#endif + + +/************************************************************************/ +/*	tty								*/ +/************************************************************************/ + +DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" ); + +/* ( addr len -- actual ) */ +static void +tty_read( void ) +{ +	int ch, len = POP(); +	char *p = (char*)cell2pointer(POP()); +	int ret=0; + +	if( len > 0 ) { +		ret = 1; +		ch = getchar(); +		if( ch >= 0 ) { +			*p = ch; +		} else { +			ret = 0; +		} +	} +	PUSH( ret ); +} + +/* ( addr len -- actual ) */ +static void +tty_write( void ) +{ +	int i, len = POP(); +	char *p = (char*)cell2pointer(POP()); +	for( i=0; i<len; i++ ) +		putchar( *p++ ); +	RET( len ); +} + +NODE_METHODS( tty ) = { +	{ "read",	tty_read	}, +	{ "write",	tty_write	}, +}; + +/************************************************************************/ +/*	client interface 'quiesce'					*/ +/************************************************************************/ + +DECLARE_NODE( ciface, 0, 0, "+/openprom/client-services" ); + +/* ( -- ) */ +static void +ciface_quiesce( unsigned long args[], unsigned long ret[] ) +{ +	usb_exit(); +#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 +} + +/* ( -- ms ) */ +#define TIMER_FREQUENCY 16600000ULL + +static void +ciface_milliseconds( unsigned long args[], unsigned long ret[] ) +{ +	unsigned long tbu, tbl, temp; +	unsigned long long ticks, msecs; + +	asm volatile( +		"1:\n" +		"mftbu  %2\n" +		"mftb   %0\n" +		"mftbu  %1\n" +		"cmpw   %2,%1\n" +		"bne    1b\n" +		: "=r"(tbl), "=r"(tbu), "=r"(temp) +		: +		: "cc"); + +	ticks = (((unsigned long long)tbu) << 32) | (unsigned long long)tbl; +	msecs = (1000 * ticks) / TIMER_FREQUENCY; +	PUSH( msecs ); +} + + +NODE_METHODS( ciface ) = { +	{ "quiesce",		ciface_quiesce		}, +	{ "milliseconds",	ciface_milliseconds	}, +}; + + +/************************************************************************/ +/*	MMU/memory methods						*/ +/************************************************************************/ + +DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" ); +DECLARE_UNNAMED_NODE( mmu, INSTALL_OPEN, 0 ); +DECLARE_NODE( mmu_ciface, 0, 0, "+/openprom/client-services" ); + + +/* ( 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 ) +{ +	ucell size = POP(); +	ucell virt = POP(); +	ofmem_release(virt, size); +} + + +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( const char *cpuname ) +{ +	phandle_t chosen, ph; +#ifdef CONFIG_RTAS +	if (is_newworld()) { +		REGISTER_NODE( rtas ); +	} +#endif +	REGISTER_NODE( ciface ); +	REGISTER_NODE( memory ); +	REGISTER_NODE_METHODS( mmu, cpuname ); +	REGISTER_NODE( mmu_ciface ); +	REGISTER_NODE( tty ); + +	chosen = find_dev("/chosen"); +	if (chosen) { +		push_str(cpuname); +		fword("open-dev"); +		ph = POP(); +		set_int_property(chosen, "mmu", ph); +	} +} diff --git a/roms/openbios/arch/ppc/qemu/mmutypes.h b/roms/openbios/arch/ppc/qemu/mmutypes.h new file mode 100644 index 00000000..512c23d0 --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/mmutypes.h @@ -0,0 +1,97 @@ +/* + *   Creation Date: <2002/01/13 13:53:14 samuel> + *   Time-stamp: <2002/01/27 19:56:11 samuel> + * + *	<mmutypes.h> + * + *	MMU definitions + * + *   Most of these declarations originate from the Linux Kernel + * + *   Copyright (C) 2002 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_MMUTYPES +#define _H_MMUTYPES + +/* Hardware Page Table Entry */ +typedef struct mPTE { +	unsigned long v:1;	/* Entry is valid */ +	unsigned long vsid:24;	/* Virtual segment identifier */ +	unsigned long h:1;	/* Hash algorithm indicator */ +	unsigned long api:6;	/* Abbreviated page index */ + +	unsigned long rpn:20;	/* Real (physical) page number */ +	unsigned long    :3;	/* Unused */ +	unsigned long r:1;	/* Referenced */ +	unsigned long c:1;	/* Changed */ +	unsigned long w:1;	/* Write-thru cache mode */ +	unsigned long i:1;	/* Cache inhibited */ +	unsigned long m:1;	/* Memory coherence */ +	unsigned long g:1;	/* Guarded */ +	unsigned long  :1;	/* Unused */ +	unsigned long pp:2;	/* Page protection */ +} mPTE_t; + +typedef struct mPTE_64 { +	uint32_t avpn_low;	/* Abbreviated Virtual Page Number (unused) */ +	uint32_t avpn:25;	/* Abbreviated Virtual Page Number */ +	uint32_t sw:4;		/* Software Use */ +	uint32_t  :1;		/* Reserved */ +	uint32_t h:1;		/* Hash algorithm indicator */ +	uint32_t v:1;		/* Entry is valid */ + +	uint32_t rpn_low;	/* Real (physical) page number (unused) */ +	uint32_t rpn:20;	/* Real (physical) page number */ +	uint32_t    :2;		/* Reserved */ +	uint32_t ac:1;		/* Address Compare*/ +	uint32_t r:1;		/* Referenced */ +	uint32_t c:1;		/* Changed */ +	uint32_t w:1;		/* Write-thru cache mode */ +	uint32_t i:1;		/* Cache inhibited */ +	uint32_t m:1;		/* Memory coherence */ +	uint32_t g:1;		/* Guarded */ +	uint32_t n:1;		/* No-Execute */ +	uint32_t pp:2;		/* Page protection */ +} mPTE_64_t; + +typedef struct _mBATU {		/* Upper part of BAT (all except 601) */ +        unsigned long bepi:15;	/* Effective page index (virtual address) */ +        unsigned long :4;	/* Unused */ +        unsigned long bl:11;	/* Block size mask */ +        unsigned long vs:1;	/* Supervisor valid */ +        unsigned long vp:1;	/* User valid */ +} mBATU; + +typedef struct _mBATL {		/* Lower part of BAT (all except 601) */ +        unsigned long brpn:15;	/* Real page index (physical address) */ +        unsigned long :10;	/* Unused */ +        unsigned long w:1;	/* Write-thru cache */ +        unsigned long i:1;	/* Cache inhibit */ +        unsigned long m:1;	/* Memory coherence */ +        unsigned long g:1;	/* Guarded (MBZ in IBAT) */ +        unsigned long :1;	/* Unused */ +        unsigned long pp:2;	/* Page access protections */ +} mBATL; + +typedef struct _mBAT { +        mBATU batu;		/* Upper register */ +        mBATL batl;		/* Lower register */ +} mBAT; + +typedef struct _mSEGREG { +        unsigned long t:1;      /* Normal or I/O  type */ +        unsigned long ks:1;     /* Supervisor 'key' (normally 0) */ +        unsigned long kp:1;     /* User 'key' (normally 1) */ +        unsigned long n:1;      /* No-execute */ +        unsigned long :4;       /* Unused */ +        unsigned long vsid:24;  /* Virtual Segment Identifier */ +} mSEGREG; + + +#endif   /* _H_MMUTYPES */ diff --git a/roms/openbios/arch/ppc/qemu/ofmem.c b/roms/openbios/arch/ppc/qemu/ofmem.c new file mode 100644 index 00000000..6f346a3d --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/ofmem.c @@ -0,0 +1,563 @@ +/* + *   Creation Date: <1999/11/07 19:02:11 samuel> + *   Time-stamp: <2004/01/07 19:42:36 samuel> + * + *	<ofmem.c> + * + *	OF Memory manager + * + *   Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se) + *   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 + *   as published by the Free Software Foundation + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "libopenbios/ofmem.h" +#include "kernel.h" +#include "mmutypes.h" +#include "asm/processor.h" + +#define BIT(n)		(1U << (31 - (n))) + +#define SLB_VSID_SHIFT 12 + +/* called from assembly */ +extern void dsi_exception(void); +extern void isi_exception(void); +extern void setup_mmu(unsigned long code_base); + +/* + * From Apple's BootX source comments: + * + *  96 MB map (currently unused - 4363357 tracks re-adoption) + * 00000000 - 00003FFF  : Exception Vectors + * 00004000 - 03FFFFFF  : Kernel Image, Boot Struct and Drivers (~64 MB) + * 04000000 - 04FFFFFF  : File Load Area (16 MB)   [80 MB] + * 05000000 - 053FFFFF  : FS Cache    (4 MB)       [84 MB] + * 05400000 - 055FFFFF  : Malloc Zone (2 MB)       [86 MB] + * 05600000 - 057FFFFF  : BootX Image (2 MB)       [88 MB] + * 05800000 - 05FFFFFF  : Unused/OF   (8 MB)       [96 MB] + * + */ + +#define FREE_BASE		0x00004000UL +#define OF_CODE_START	0xfff00000UL +#define OF_CODE_SIZE    0x00100000 +#define IO_BASE			0x80000000UL + +#ifdef __powerpc64__ +#define HASH_BITS		18 +#else +#define HASH_BITS		15 +#endif +#define HASH_SIZE		(2 << HASH_BITS) +#define OFMEM_SIZE		(1 * 1024 * 1024 + 512 * 1024) + +#define	SEGR_USER		BIT(2) +#define SEGR_BASE		0x0400 + +static inline unsigned long +get_hash_base(void) +{ +    return (mfsdr1() & SDR1_HTABORG_MASK); +} + +static inline unsigned long +get_rom_base(void) +{ +    ofmem_t *ofmem = ofmem_arch_get_private(); +    return ofmem->ramsize - OF_CODE_SIZE; +} + +static unsigned long +get_ram_top(void) +{ +    return get_hash_base() - (32 + 64 + 64) * 1024 - OFMEM_SIZE; +} + +static unsigned long +get_ram_bottom(void) +{ +    return FREE_BASE; +} + +static unsigned long get_heap_top(void) +{ +    return get_hash_base() - (32 + 64 + 64) * 1024; +} + +static inline size_t ALIGN_SIZE(size_t x, size_t a) +{ +    return (x + a - 1) & ~(a - 1); +} + +ofmem_t* ofmem_arch_get_private(void) +{ +    return (ofmem_t*)cell2pointer(get_heap_top() - OFMEM_SIZE); +} + +void* ofmem_arch_get_malloc_base(void) +{ +    return (char*)ofmem_arch_get_private() + ALIGN_SIZE(sizeof(ofmem_t), 4); +} + +ucell ofmem_arch_get_heap_top(void) +{ +    return get_heap_top(); +} + +ucell ofmem_arch_get_virt_top(void) +{ +    return IO_BASE; +} + +void ofmem_arch_unmap_pages(ucell virt, ucell size) +{ +    /* kill page mappings in provided range */ +} + +void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode) +{ +    /* none yet */ +} + +ucell ofmem_arch_get_iomem_base(void) +{ +    /* Currently unused */ +    return 0; +} + +ucell ofmem_arch_get_iomem_top(void) +{ +    /* Currently unused */ +    return 0; +} + +retain_t *ofmem_arch_get_retained(void) +{ +    /* not implemented */ +    return NULL; +} + +int ofmem_arch_get_physaddr_cellsize(void) +{ +#ifdef CONFIG_PPC64 +    return 2; +#else +    return 1; +#endif +} + +int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value) +{ +    int n = 0; +#ifdef CONFIG_PPC64 +    p[n++] = value >> 32; +#endif +    p[n++] = value; +    return n; +} + +/* Return size of a single MMU package translation property entry in cells */ +int ofmem_arch_get_translation_entry_size(void) +{ +    return 3 + ofmem_arch_get_physaddr_cellsize(); +} + +/* Generate translation property entry for PPC. + * According to the platform bindings for PPC + * (http://www.openfirmware.org/1275/bindings/ppc/release/ppc-2_1.html#REF34579) + * a translation property entry has the following layout: + * + *      virtual address + *      length + *      physical address + *      mode + */ +void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t) +{ +    int i = 0; + +    transentry[i++] = t->virt; +    transentry[i++] = t->size; +    i += ofmem_arch_encode_physaddr(&transentry[i], t->phys); +    transentry[i++] = t->mode; +} + +/* Return the size of a memory available entry given the phandle in cells */ +int ofmem_arch_get_available_entry_size(phandle_t ph) +{ +    if (ph == s_phandle_memory) { +        return 1 + ofmem_arch_get_physaddr_cellsize(); +    } else { +        return 1 + 1; +    } +} + +/* Generate memory available property entry for PPC */ +void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size) +{ +    int i = 0; + +    if (ph == s_phandle_memory) { +        i += ofmem_arch_encode_physaddr(availentry, start); +    } else { +	availentry[i++] = start; +    } +     +    availentry[i] = size; +} + +/************************************************************************/ +/*	OF private allocations						*/ +/************************************************************************/ + +/* Private functions for mapping between physical/virtual addresses */ +phys_addr_t +va2pa(unsigned long va) +{ +    if (va >= OF_CODE_START && va < OF_CODE_START + OF_CODE_SIZE) { +        return (phys_addr_t)get_rom_base() - OF_CODE_START + va; +    } else { +        return (phys_addr_t)va; +    } +} + +unsigned long +pa2va(phys_addr_t pa) +{ +    if ((pa - get_rom_base() + OF_CODE_START >= OF_CODE_START) && +        (pa - get_rom_base() + OF_CODE_START < OF_CODE_START + OF_CODE_SIZE)) +        return (unsigned long)pa - get_rom_base() + OF_CODE_START; +    else +        return (unsigned long)pa; +} + +void * +malloc(int size) +{ +    return ofmem_malloc(size); +} + +void +free(void *ptr) +{ +    ofmem_free(ptr); +} + +void * +realloc(void *ptr, size_t size) +{ +    return ofmem_realloc(ptr, size); +} + + +/************************************************************************/ +/*	misc								*/ +/************************************************************************/ + +ucell ofmem_arch_default_translation_mode(phys_addr_t phys) +{ +    /* XXX: Guard bit not set as it should! */ +    if (phys < IO_BASE) +        return 0x02;	/*0xa*/	/* wim GxPp */ +    return 0x6a;		/* WIm GxPp, I/O */ +} + +ucell ofmem_arch_io_translation_mode(phys_addr_t phys) +{ +    return 0x6a;		/* WIm GxPp, I/O */ +} + +/************************************************************************/ +/*	page fault handler						*/ +/************************************************************************/ + +static phys_addr_t +ea_to_phys(unsigned long ea, ucell *mode) +{ +    phys_addr_t phys; + +    if (ea >= OF_CODE_START && ea <= 0xffffffffUL) { +        /* ROM into RAM */ +        ea -= OF_CODE_START; +        phys = get_rom_base() + ea; +        *mode = 0x02; +		return phys; +    } + +    phys = ofmem_translate(ea, mode); +    if (phys == -1) { +        phys = ea; +        *mode = ofmem_arch_default_translation_mode(phys); + +        /* print_virt_range(); */ +        /* print_phys_range(); */ +        /* print_trans(); */ +    } +    return phys; +} + +/* Converts a global variable (from .data or .bss) into a pointer that +   can be accessed from real mode */ +static void * +global_ptr_real(void *p) +{ +    return (void*)((uintptr_t)p - OF_CODE_START + get_rom_base()); +} + +/* Return the next slot to evict, in the range of [0..7] */ +static int +next_evicted_slot(void) +{ +    static int next_grab_slot; +    int *next_grab_slot_va; +    int r; + +    next_grab_slot_va = global_ptr_real(&next_grab_slot); +    r = *next_grab_slot_va; +    *next_grab_slot_va = (r + 1) % 8; + +    return r; +} + +static void +hash_page_64(unsigned long ea, phys_addr_t phys, ucell mode) +{ +    uint64_t vsid_mask, page_mask, pgidx, hash; +    uint64_t htab_mask, mask, avpn; +    unsigned long pgaddr; +    int i, found; +    unsigned int vsid, vsid_sh, sdr, sdr_sh, sdr_mask; +    mPTE_64_t *pp; + +    vsid = (ea >> 28) + SEGR_BASE; +    vsid_sh = 7; +    vsid_mask = 0x00003FFFFFFFFF80ULL; +    sdr = mfsdr1(); +    sdr_sh = 18; +    sdr_mask = 0x3FF80; +    page_mask = 0x0FFFFFFF; // XXX correct? +    pgidx = (ea & page_mask) >> PAGE_SHIFT; +    avpn = (vsid << 12) | ((pgidx >> 4) & 0x0F80);; + +    hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask; +    htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F)); +    mask = (htab_mask << sdr_sh) | sdr_mask; +    pgaddr = sdr | (hash & mask); +    pp = (mPTE_64_t *)pgaddr; + +    /* replace old translation */ +    for (found = 0, i = 0; !found && i < 8; i++) +        if (pp[i].avpn == avpn) +            found = 1; + +    /* otherwise use a free slot */ +    for (i = 0; !found && i < 8; i++) +        if (!pp[i].v) +            found = 1; + +    /* out of slots, just evict one */ +    if (!found) +        i = next_evicted_slot() + 1; +    i--; +    { +    mPTE_64_t p = { +        // .avpn_low = avpn, +        .avpn = avpn >> 7, +        .h = 0, +        .v = 1, + +        .rpn = (phys & ~0xfffUL) >> 12, +        .r = mode & (1 << 8) ? 1 : 0, +        .c = mode & (1 << 7) ? 1 : 0, +        .w = mode & (1 << 6) ? 1 : 0, +        .i = mode & (1 << 5) ? 1 : 0, +        .m = mode & (1 << 4) ? 1 : 0, +        .g = mode & (1 << 3) ? 1 : 0, +        .n = mode & (1 << 2) ? 1 : 0, +        .pp = mode & 3, +    }; +    pp[i] = p; +    } + +    asm volatile("tlbie %0" :: "r"(ea)); +} + +static void +hash_page_32(unsigned long ea, phys_addr_t phys, ucell mode) +{ +#ifndef __powerpc64__ +    unsigned long *upte, cmp, hash1; +    int i, vsid, found; +    mPTE_t *pp; + +    vsid = (ea >> 28) + SEGR_BASE; +    cmp = BIT(0) | (vsid << 7) | ((ea & 0x0fffffff) >> 22); + +    hash1 = vsid; +    hash1 ^= (ea >> 12) & 0xffff; +    hash1 &= (((mfsdr1() & 0x1ff) << 16) | 0xffff) >> 6; + +    pp = (mPTE_t*)(get_hash_base() + (hash1 << 6)); +    upte = (unsigned long*)pp; + +    /* replace old translation */ +    for (found = 0, i = 0; !found && i < 8; i++) +        if (cmp == upte[i*2]) +            found = 1; + +    /* otherwise use a free slot */ +    for (i = 0; !found && i < 8; i++) +        if (!pp[i].v) +            found = 1; + +    /* out of slots, just evict one */ +    if (!found) +        i = next_evicted_slot() + 1; +    i--; +    upte[i * 2] = cmp; +    upte[i * 2 + 1] = (phys & ~0xfff) | mode; + +    asm volatile("tlbie %0" :: "r"(ea)); +#endif +} + +static int is_ppc64(void) +{ +#ifdef __powerpc64__ +    return 1; +#elif defined(CONFIG_PPC_64BITSUPPORT) +    unsigned int pvr = mfpvr(); +    return ((pvr >= 0x330000) && (pvr < 0x70330000)); +#else +    return 0; +#endif +} + +/* XXX Remove these ugly constructs when legacy 64-bit support is dropped. */ +static void hash_page(unsigned long ea, phys_addr_t phys, ucell mode) +{ +    if (is_ppc64()) +        hash_page_64(ea, phys, mode); +    else +        hash_page_32(ea, phys, mode); +} + +void +dsi_exception(void) +{ +    unsigned long dar, dsisr; +    ucell mode; +    phys_addr_t phys; + +    asm volatile("mfdar %0" : "=r" (dar) : ); +    asm volatile("mfdsisr %0" : "=r" (dsisr) : ); + +    phys = ea_to_phys(dar, &mode); +    hash_page(dar, phys, mode); +} + +void +isi_exception(void) +{ +    unsigned long nip, srr1; +    ucell mode; +    phys_addr_t phys; + +    asm volatile("mfsrr0 %0" : "=r" (nip) : ); +    asm volatile("mfsrr1 %0" : "=r" (srr1) : ); + +    phys = ea_to_phys(nip, &mode); +    hash_page(nip, phys, mode); +} + + +/************************************************************************/ +/*	init / cleanup							*/ +/************************************************************************/ + +void +setup_mmu(unsigned long ramsize) +{ +    ofmem_t *ofmem; +#ifndef __powerpc64__ +    unsigned long sr_base; +#endif +    unsigned long hash_base; +    unsigned long hash_mask = ~0x000fffffUL; /* alignment for ppc64 */ +    int i; + +    /* SDR1: Storage Description Register 1 */ + +    hash_base = (ramsize - OF_CODE_SIZE - HASH_SIZE) & hash_mask; +    memset((void *)hash_base, 0, HASH_SIZE); +    if (is_ppc64()) +        mtsdr1(hash_base | MAX(HASH_BITS - 18, 0)); +    else +        mtsdr1(hash_base | ((HASH_SIZE - 1) >> 16)); + +#ifdef __powerpc64__ + +    /* Segment Lookaside Buffer */ + +    slbia(); /* Invalidate all SLBs except SLB 0 */ +    for (i = 0; i < 16; i++) { +        unsigned long rs = (0x400 + i) << SLB_VSID_SHIFT; +        unsigned long rb = ((unsigned long)i << 28) | (1 << 27) | i; +        slbmte(rs, rb); +    } + +#else + +    /* Segment Register */ + +    sr_base = SEGR_USER | SEGR_BASE ; +    for (i = 0; i < 16; i++) { +        int j = i << 28; +        asm volatile("mtsrin %0,%1" :: "r" (sr_base + i), "r" (j)); +    } + +#endif + +    ofmem = ofmem_arch_get_private(); +    memset(ofmem, 0, sizeof(ofmem_t)); +    ofmem->ramsize = ramsize; + +    memcpy((void *)get_rom_base(), (void *)OF_CODE_START, OF_CODE_SIZE); + +    /* Enable MMU */ + +    mtmsr(mfmsr() | MSR_IR | MSR_DR); +} + +void +ofmem_init(void) +{ +    ofmem_t *ofmem = ofmem_arch_get_private(); + +    /* Map the memory (don't map page 0 to allow catching of NULL dereferences) */ +    ofmem_claim_phys(PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0); +    ofmem_claim_virt(PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0); +    ofmem_map(PAGE_SIZE, PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0); + +    /* Mark the first page as non-free */ +    ofmem_claim_phys(0, PAGE_SIZE, 0); +    ofmem_claim_virt(0, PAGE_SIZE, 0); + +    /* Map everything at the top of physical RAM 1:1, minus the OpenBIOS ROM in RAM copy */ +    ofmem_claim_phys(get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0); +    ofmem_claim_virt(get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0); +    ofmem_map(get_ram_top(), get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0); +     +    /* Map the OpenBIOS ROM in RAM copy */ +    ofmem_claim_phys(ofmem->ramsize - OF_CODE_SIZE, OF_CODE_SIZE, 0); +    ofmem_claim_virt(OF_CODE_START, OF_CODE_SIZE, 0); +    ofmem_map(ofmem->ramsize - OF_CODE_SIZE, OF_CODE_START, OF_CODE_SIZE, 0); +} diff --git a/roms/openbios/arch/ppc/qemu/qemu.c b/roms/openbios/arch/ppc/qemu/qemu.c new file mode 100644 index 00000000..381affb7 --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/qemu.c @@ -0,0 +1,106 @@ +/* + *   Creation Date: <2004/08/28 18:38:22 greg> + *   Time-stamp: <2004/08/28 18:38:22 greg> + * + *	<qemu.c> + * + *   Copyright (C) 2004, Greg Watson + * + *   derived from 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 "libopenbios/bindings.h" +#include "drivers/drivers.h" +#include "libc/vsprintf.h" +#include "libc/string.h" +#include "libc/byteorder.h" +#include "qemu/qemu.h" +#include <stdarg.h> + +//#define DUMP_NVRAM + +unsigned long virt_offset = 0; + +void +exit( int status __attribute__ ((unused))) +{ +	for (;;); +} + +void +fatal_error( const char *err ) +{ +	printk("Fatal error: %s\n", err ); +	exit(0); +} + +void +panic( const char *err ) +{ +	printk("Panic: %s\n", err ); +	exit(0); +} + +static int do_indent; + +int +printk( const char *fmt, ... ) +{ +        char *p, buf[1024]; +	va_list args; +	int i; + +	va_start(args, fmt); +        i = vsnprintf(buf, sizeof(buf), fmt, args); +	va_end(args); + +	for( p=buf; *p; p++ ) { +		if( *p == '\n' ) +			do_indent = 0; +		if( do_indent++ == 1 ) { +			putchar( '>' ); +			putchar( '>' ); +			putchar( ' ' ); +		} +		putchar( *p ); +	} +	return i; +} + +int arch_nvram_size(void) +{ +    if (is_apple()) { +        return macio_get_nvram_size(); +    } else { +        // not implemented +    } +    return 0; +} + +void arch_nvram_put(char *buf) +{ +    if (is_apple()) { +        macio_nvram_put(buf); +    } else { +        // not implemented +    } +} + +void arch_nvram_get(char *buf) +{ +    if (is_apple()) { +        macio_nvram_get(buf); +    } else { +        // not implemented +    } +} diff --git a/roms/openbios/arch/ppc/qemu/qemu.fs b/roms/openbios/arch/ppc/qemu/qemu.fs new file mode 100644 index 00000000..458af1bc --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/qemu.fs @@ -0,0 +1,95 @@ +\   qemu specific initialization code +\ +\   Copyright (C) 2005 Stefan Reinauer +\ +\   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 +\ + + +\ ------------------------------------------------------------------------- +\ 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 +  " rtc" " rtc" preopen +  " memory" " /memory" preopen +; SYSTEM-initializer + + +\ use the tty interface if available +: activate-tty-interface +  " /packages/terminal-emulator" find-dev if drop +  then +; + +variable keyboard-phandle 0 keyboard-phandle ! + +: (find-keyboard-device) ( phandle -- ) +  recursive +  keyboard-phandle @ 0= if  \ Return first match +    >dn.child @ +    begin ?dup while +      dup dup " device_type" rot get-package-property 0= if +        drop dup cstrlen +        " keyboard" strcmp 0= if +          dup to keyboard-phandle +        then +      then +      (find-keyboard-device) +      >dn.peer @ +    repeat +  else +    drop +  then +; + +\ create the keyboard devalias  +:noname +  device-tree @ (find-keyboard-device) +  keyboard-phandle @ if +    active-package +    " /aliases" find-device +    keyboard-phandle @ get-package-path +    encode-string " keyboard" property +    active-package!   +  then +; SYSTEM-initializer + +\ ------------------------------------------------------------------------- +\ pre-booting +\ ------------------------------------------------------------------------- + +: update-chosen +  " /chosen" find-device +  stdin @ encode-int " stdin" property +  stdout @ encode-int " stdout" property +  device-end +; + +:noname +  set-defaults +; PREPOST-initializer diff --git a/roms/openbios/arch/ppc/qemu/qemu.h b/roms/openbios/arch/ppc/qemu/qemu.h new file mode 100644 index 00000000..6edf4d45 --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/qemu.h @@ -0,0 +1,24 @@ +/* + *   Creation Date: <2004/08/28 17:50:12 stepan> + *   Time-stamp: <2004/08/28 17:50:12 stepan> + * + *	<qemu.h> + * + *   Copyright (C) 2005 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 + * + */ + +#ifndef _H_QEMU +#define _H_QEMU + +/* vfd.c */ +extern int		vfd_draw_str( const char *str ); +extern void		vfd_close( void ); + +#include "kernel.h" + +#endif   /* _H_QEMU */ diff --git a/roms/openbios/arch/ppc/qemu/start.S b/roms/openbios/arch/ppc/qemu/start.S new file mode 100644 index 00000000..ae2fd53d --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/start.S @@ -0,0 +1,729 @@ +/* + *   Creation Date: <2001/06/16 21:30:18 samuel> + *   Time-stamp: <2003/04/04 16:32:06 samuel> + * + *	<init.S> + * + *	Asm glue for ELF images + * + *   Copyright (C) 2001, 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 "autoconf.h" +#include "asm/asmdefs.h" +#include "asm/processor.h" + +/************************************************************************/ +/*	Macros								*/ +/************************************************************************/ + +#define ILLEGAL_VECTOR( v )	.org __vectors + v ; vector__##v: bl trap_error ; +#define VECTOR( v, dummystr )	.org __vectors + v ; vector__##v + +#ifdef CONFIG_PPC_64BITSUPPORT + +/* We're trying to use the same code for the ppc32 and ppc64 handlers here. + * On ppc32 we only save/restore the registers, C considers volatile. + * + * On ppc64 on the other hand, we have to save/restore all registers, because + * all OF code is 32 bits, which only saves/restores the low 32 bits of the + * registers it clobbers. + */ + +#define EXCEPTION_PREAMBLE_TEMPLATE \ +	mtsprg1	r1 ;				/* scratch */ \ +	mfcr	r1 ; \ +	mtsprg2	r1 ;				/* scratch */ \ +	lis	r1, 0x8000 ;			/* r1=0x80000000 */ \ +	add.	r1,r1,r1 ;			/* r1=r1+r1 (high 32bit !0) */ \ +	beq	1f; \ +	\ +	mfmsr	r1 ;				/* unset MSR_SF */ \ +	clrldi	r1,r1,1 ; \ +	mtmsrd	r1 ; \ +1: \ +	mfsprg0	r1 ;				/* exception stack in sprg0 */ \ +.ifc ULONG_SIZE, 8 ; \ +	addi	r1,r1,-(40 * ULONG_SIZE) ;	/* push exception frame */ \ +.else ; \ +	addi	r1,r1,-(20 * ULONG_SIZE) ;	/* push exception frame */ \ +.endif ; \ + \ +	stl	r0,(0 * ULONG_SIZE)(r1) ;	/* save r0 */ \ +	mfsprg1	r0 ; \ +	stl	r0,(1 * ULONG_SIZE)(r1) ;	/* save r1 */ \ +	stl	r2,(2 * ULONG_SIZE)(r1) ;	/* save r2 */ \ +	stl	r3,(3 * ULONG_SIZE)(r1) ;	/* save r3 */ \ +	stl	r4,(4 * ULONG_SIZE)(r1) ; \ +	stl	r5,(5 * ULONG_SIZE)(r1) ; \ +	stl	r6,(6 * ULONG_SIZE)(r1) ; \ +	stl	r7,(7 * ULONG_SIZE)(r1) ; \ +	stl	r8,(8 * ULONG_SIZE)(r1) ; \ +	stl	r9,(9 * ULONG_SIZE)(r1) ; \ +	stl	r10,(10 * ULONG_SIZE)(r1) ; \ +	stl	r11,(11 * ULONG_SIZE)(r1) ; \ +	stl	r12,(12 * ULONG_SIZE)(r1) ; \ +.ifc ULONG_SIZE, 8 ; \ +	stl	r13,(17 * ULONG_SIZE)(r1) ; \ +	stl	r14,(18 * ULONG_SIZE)(r1) ; \ +	stl	r15,(19 * ULONG_SIZE)(r1) ; \ +	stl	r16,(20 * ULONG_SIZE)(r1) ; \ +	stl	r17,(21 * ULONG_SIZE)(r1) ; \ +	stl	r18,(22 * ULONG_SIZE)(r1) ; \ +	stl	r19,(23 * ULONG_SIZE)(r1) ; \ +	stl	r20,(24 * ULONG_SIZE)(r1) ; \ +	stl	r21,(25 * ULONG_SIZE)(r1) ; \ +	stl	r22,(26 * ULONG_SIZE)(r1) ; \ +	stl	r23,(27 * ULONG_SIZE)(r1) ; \ +	stl	r24,(28 * ULONG_SIZE)(r1) ; \ +	stl	r25,(29 * ULONG_SIZE)(r1) ; \ +	stl	r26,(30 * ULONG_SIZE)(r1) ; \ +	stl	r27,(31 * ULONG_SIZE)(r1) ; \ +	stl	r28,(32 * ULONG_SIZE)(r1) ; \ +	stl	r29,(33 * ULONG_SIZE)(r1) ; \ +	stl	r30,(34 * ULONG_SIZE)(r1) ; \ +	stl	r31,(35 * ULONG_SIZE)(r1) ; \ +.endif ; \ + \ +	mflr	r0 ; \ +	stl	r0,(13 * ULONG_SIZE)(r1) ; \ +	mfsprg2	r0 ; \ +	stl	r0,(14 * ULONG_SIZE)(r1) ; \ +	mfctr	r0 ; \ +	stl	r0,(15 * ULONG_SIZE)(r1) ; \ +	mfxer	r0 ; \ +	stl	r0,(16 * ULONG_SIZE)(r1) ; \ + \ +	/* 76(r1) unused */ \ +	addi	r1,r1,-16 ;	/* C ABI uses 0(r1) and 4(r1)... */ + +#define EXCEPTION_EPILOGUE_TEMPLATE \ +	addi	r1,r1,16 ;			/* pop ABI frame */ \ +\ +	ll	r0,(13 * ULONG_SIZE)(r1) ; \ +	mtlr	r0 ; \ +	ll	r0,(14 * ULONG_SIZE)(r1) ; \ +	mtcr	r0 ; \ +	ll	r0,(15 * ULONG_SIZE)(r1) ; \ +	mtctr	r0 ; \ +	ll	r0,(16 * ULONG_SIZE)(r1) ; \ +	mtxer	r0 ; \ +\ +	ll	r0,(0 * ULONG_SIZE)(r1) ; \ +	ll	r2,(2 * ULONG_SIZE)(r1) ; \ +	ll	r3,(3 * ULONG_SIZE)(r1) ; \ +	ll	r4,(4 * ULONG_SIZE)(r1) ; \ +	ll	r5,(5 * ULONG_SIZE)(r1) ; \ +	ll	r6,(6 * ULONG_SIZE)(r1) ; \ +	ll	r7,(7 * ULONG_SIZE)(r1) ; \ +	ll	r8,(8 * ULONG_SIZE)(r1) ; \ +	ll	r9,(9 * ULONG_SIZE)(r1) ; \ +	ll	r10,(10 * ULONG_SIZE)(r1) ; \ +	ll	r11,(11 * ULONG_SIZE)(r1) ; \ +	ll	r12,(12 * ULONG_SIZE)(r1) ; \ +.ifc ULONG_SIZE, 8 ; \ +	ll	r13,(17 * ULONG_SIZE)(r1) ; \ +	ll	r14,(18 * ULONG_SIZE)(r1) ; \ +	ll	r15,(19 * ULONG_SIZE)(r1) ; \ +	ll	r16,(20 * ULONG_SIZE)(r1) ; \ +	ll	r17,(21 * ULONG_SIZE)(r1) ; \ +	ll	r18,(22 * ULONG_SIZE)(r1) ; \ +	ll	r19,(23 * ULONG_SIZE)(r1) ; \ +	ll	r20,(24 * ULONG_SIZE)(r1) ; \ +	ll	r21,(25 * ULONG_SIZE)(r1) ; \ +	ll	r22,(26 * ULONG_SIZE)(r1) ; \ +	ll	r23,(27 * ULONG_SIZE)(r1) ; \ +	ll	r24,(28 * ULONG_SIZE)(r1) ; \ +	ll	r25,(29 * ULONG_SIZE)(r1) ; \ +	ll	r26,(30 * ULONG_SIZE)(r1) ; \ +	ll	r27,(31 * ULONG_SIZE)(r1) ; \ +	ll	r28,(32 * ULONG_SIZE)(r1) ; \ +	ll	r29,(33 * ULONG_SIZE)(r1) ; \ +	ll	r30,(34 * ULONG_SIZE)(r1) ; \ +	ll	r31,(35 * ULONG_SIZE)(r1) ; \ +.endif ; \ +	ll	r1,(1 * ULONG_SIZE)(r1) ;	/* restore stack at last */ \ +	rfi + +// PPC32 + +#define ULONG_SIZE		4 +#define stl			stw +#define ll			lwz + +.macro EXCEPTION_PREAMBLE +	EXCEPTION_PREAMBLE_TEMPLATE +.endm + +.macro EXCEPTION_EPILOGUE +	EXCEPTION_EPILOGUE_TEMPLATE +.endm + +#undef ULONG_SIZE +#undef stl +#undef ll + +// PPC64 + +#define ULONG_SIZE		8 +#define stl			std +#define ll			ld + +.macro EXCEPTION_PREAMBLE_64 +	EXCEPTION_PREAMBLE_TEMPLATE +.endm + +.macro EXCEPTION_EPILOGUE_64 +	EXCEPTION_EPILOGUE_TEMPLATE +.endm + +#undef ULONG_SIZE +#undef stl +#undef ll + +#define ULONG_SIZE 4 +#define STACKFRAME_MINSIZE 16 + +#else /* !CONFIG_PPC_64BITSUPPORT */ + +#ifdef __powerpc64__ + +#define ULONG_SIZE 8 +#define STACKFRAME_MINSIZE 48 +#define stl std +#define ll  ld + +#else + +#define ULONG_SIZE 4 +#define STACKFRAME_MINSIZE 16 +#define stl stw +#define ll  lwz + +#endif + +.macro EXCEPTION_PREAMBLE +    mtsprg1 r1 /* scratch */ +    mfsprg0 r1 /* exception stack in sprg0 */ +    addi    r1, r1, -(20 * ULONG_SIZE) /* push exception frame */ + +    stl     r0,  ( 0 * ULONG_SIZE)(r1) /* save r0 */ +    mfsprg1 r0 +    stl     r0,  ( 1 * ULONG_SIZE)(r1) /* save r1 */ +    stl     r2,  ( 2 * ULONG_SIZE)(r1) /* save r2 */ +    stl     r3,  ( 3 * ULONG_SIZE)(r1) /* save r3 */ +    stl     r4,  ( 4 * ULONG_SIZE)(r1) +    stl     r5,  ( 5 * ULONG_SIZE)(r1) +    stl     r6,  ( 6 * ULONG_SIZE)(r1) +    stl     r7,  ( 7 * ULONG_SIZE)(r1) +    stl     r8,  ( 8 * ULONG_SIZE)(r1) +    stl     r9,  ( 9 * ULONG_SIZE)(r1) +    stl     r10, (10 * ULONG_SIZE)(r1) +    stl     r11, (11 * ULONG_SIZE)(r1) +    stl     r12, (12 * ULONG_SIZE)(r1) + +    mflr    r0 +    stl     r0,  (13 * ULONG_SIZE)(r1) +    mfcr    r0 +    stl     r0,  (14 * ULONG_SIZE)(r1) +    mfctr   r0 +    stl     r0,  (15 * ULONG_SIZE)(r1) +    mfxer   r0 +    stl     r0,  (16 * ULONG_SIZE)(r1) + +    addi r1, r1, -STACKFRAME_MINSIZE /* C ABI saves LR and SP */ +.endm + +.macro EXCEPTION_EPILOGUE +    addi r1, r1,  STACKFRAME_MINSIZE /* pop ABI frame */ + +    ll    r0,  (13 * ULONG_SIZE)(r1) +    mtlr  r0 +    ll    r0,  (14 * ULONG_SIZE)(r1) +    mtcr  r0 +    ll    r0,  (15 * ULONG_SIZE)(r1) +    mtctr r0 +    ll    r0,  (16 * ULONG_SIZE)(r1) +    mtxer r0 + +    ll    r0,  ( 0 * ULONG_SIZE)(r1) +    ll    r2,  ( 2 * ULONG_SIZE)(r1) +    ll    r3,  ( 3 * ULONG_SIZE)(r1) +    ll    r4,  ( 4 * ULONG_SIZE)(r1) +    ll    r5,  ( 5 * ULONG_SIZE)(r1) +    ll    r6,  ( 6 * ULONG_SIZE)(r1) +    ll    r7,  ( 7 * ULONG_SIZE)(r1) +    ll    r8,  ( 8 * ULONG_SIZE)(r1) +    ll    r9,  ( 9 * ULONG_SIZE)(r1) +    ll    r10, (10 * ULONG_SIZE)(r1) +    ll    r11, (11 * ULONG_SIZE)(r1) +    ll    r12, (12 * ULONG_SIZE)(r1) + +    ll    r1,  ( 1 * ULONG_SIZE)(r1) /* restore stack at last */ +    RFI +.endm + +#endif /* !CONFIG_PPC_64BITSUPPORT */ + +/************************************************************************/ +/*	vectors								*/ +/************************************************************************/ + +        .section .text.vectors, "ax" +GLOBL(__vectors): +	nop			// NULL-jmp trap +1:	nop			// +	b	1b + +VECTOR( 0x100, "SRE" ): +        b       _entry + +trap_error: +	lis	r1, 0x8000			/* r1=0x80000000 */ +	add.	r1,r1,r1			/* r1=r1+r1 (high 32bit !0) */ +	beq	1f + +	mfmsr	r1  				/* unset MSR_SF */ +	clrldi	r1,r1,1 +	mtmsrd	r1 +1: +	mflr	r3 +	LOAD_REG_FUNC(r4, unexpected_excep) +	mtctr r4 +	bctr + +ILLEGAL_VECTOR( 0x200 ) + +VECTOR( 0x300, "DSI" ): +	b	real_dsi + +ILLEGAL_VECTOR( 0x380 ) + +VECTOR( 0x400, "ISI" ): +	b	real_isi + +ILLEGAL_VECTOR( 0x480 ) + +	ILLEGAL_VECTOR( 0x500 ) +	ILLEGAL_VECTOR( 0x600 ) +	ILLEGAL_VECTOR( 0x700 ) + +VECTOR( 0x800, "FPU" ): +	mtsprg1	r3 +	mfsrr1	r3 +	ori	r3,r3,0x2000 +	mtsrr1	r3 +	mfsprg1	r3 +	RFI + +ILLEGAL_VECTOR( 0x900 ) +ILLEGAL_VECTOR( 0xa00 ) +ILLEGAL_VECTOR( 0xb00 ) +ILLEGAL_VECTOR( 0xc00 ) +ILLEGAL_VECTOR( 0xd00 ) +ILLEGAL_VECTOR( 0xe00 ) +ILLEGAL_VECTOR( 0xf00 ) +ILLEGAL_VECTOR( 0xf20 ) +ILLEGAL_VECTOR( 0x1000 ) +ILLEGAL_VECTOR( 0x1100 ) +ILLEGAL_VECTOR( 0x1200 ) +ILLEGAL_VECTOR( 0x1300 ) +ILLEGAL_VECTOR( 0x1400 ) +ILLEGAL_VECTOR( 0x1500 ) +ILLEGAL_VECTOR( 0x1600 ) +ILLEGAL_VECTOR( 0x1700 ) + +#ifdef CONFIG_PPC_64BITSUPPORT + +VECTOR( 0x2000, "DSI_64" ): +	EXCEPTION_PREAMBLE_64 +	LOAD_REG_IMMEDIATE(r3, dsi_exception) +	mtctr	r3 +	bctrl +	EXCEPTION_EPILOGUE_64 + +VECTOR( 0x2200, "ISI_64" ): +	EXCEPTION_PREAMBLE_64 +	LOAD_REG_IMMEDIATE(r3, isi_exception) +	mtctr	r3 +	bctrl +	EXCEPTION_EPILOGUE_64 + +#endif + +real_dsi: +	EXCEPTION_PREAMBLE +	LOAD_REG_FUNC(r3, dsi_exception) +	mtctr	r3 +	bctrl +	b exception_return + +real_isi: +	EXCEPTION_PREAMBLE +	LOAD_REG_FUNC(r3, isi_exception) +	mtctr	r3 +	bctrl +	b exception_return + +exception_return: +	EXCEPTION_EPILOGUE + +GLOBL(__vectors_end): + +/************************************************************************/ +/*	entry								*/ +/************************************************************************/ + +GLOBL(_entry): + +#ifdef CONFIG_PPC_64BITSUPPORT +	li	r0,0 + +	lis	r3, 0x8000			/* r1=0x80000000 */ +	add.	r3,r3,r3			/* r1=r1+r1 (high 32bit !0) */ +	beq	no_64bit			/* only true when !MSR_SF */ + +	/* clear MSR, disable MMU, SF */ +	mtmsrd	r0 +	b	real_entry + +no_64bit: +	/* clear MSR, disable MMU */ +	mtmsr	r0 + +real_entry: +#endif + +	/* copy exception vectors */ + +	LOAD_REG_IMMEDIATE(r3, __vectors) +	li	r4,0 +	li	r5,__vectors_end - __vectors + 16 +	rlwinm	r5,r5,0,0,28 +1:	lwz	r6,0(r3) +	lwz	r7,4(r3) +	lwz	r8,8(r3) +	lwz	r9,12(r3) +	stw	r6,0(r4) +	stw	r7,4(r4) +	stw	r8,8(r4) +	stw	r9,12(r4) +	dcbst	0,r4 +	sync +	icbi	0,r4 +	sync +	addi	r5,r5,-16 +	addi	r3,r3,16 +	addi	r4,r4,16 +	cmpwi	r5,0 +	bgt	1b +	isync + +	bl compute_ramsize + +	/* Memory map: +	 * +	 * Top +-------------------------+ +	 *     |                         | +	 *     | ROM into RAM (1 MB)     | +	 *     |                         | +	 *     +-------------------------+ +	 *     |                         | +	 *     | MMU Hash Table (64 kB)  | +	 *     |                         | +	 *     +-------------------------+ +	 *     |                         | +	 *     | Exception Stack (32 kB) | +	 *     |                         | +	 *     +-------------------------+ +	 *     |                         | +	 *     | Stack (64 kB)           | +	 *     |                         | +	 *     +-------------------------+ +	 *     |                         | +	 *     | Client Stack (64 kB)    | +	 *     |                         | +	 *     +-------------------------+ +	 *     |                         | +	 *     | Malloc Zone (2 MiB)     | +	 *     |                         | +	 *     +-------------------------+ +	 *     :                         : +	 * Bottom +	 */ + +	addis	r1, r3, -16		/* ramsize - 1MB */ + +	/* setup hash table */ + +	addis	r1, r1, -1		/* - 64 kB */ +	clrrwi	r1, r1, 5*4		/* & ~0xfffff */ + +	/* setup exception stack */ + +	mtsprg0	r1 + +	/* setup stack */ + +	addi	r1, r1, -32768		/* - 32 kB */ + +	/* save memory size in stack */ + +#ifdef __powerpc64__ +	/* set up TOC pointer */ + +	LOAD_REG_IMMEDIATE(r2, setup_mmu) +	ld r2, 8(r2) +#endif + +	bl	BRANCH_LABEL(setup_mmu) +	bl	BRANCH_LABEL(entry) +1:	nop +	b	1b + + +	/* According to IEEE 1275, PPC bindings: +	 * +	 * 	MSR = FP, ME + (DR|IR) +	 *	r1 = stack (32 K + 32 bytes link area above) +	 *	r5 = client interface handler +	 *	r6 = address of client program arguments (unused) +	 *	r7 = length of client program arguments (unused) +         * +         *      Yaboot and Linux use r3 and r4 for initrd address and size +	 */ +        .data +saved_stack: +    DATA_LONG(0) +        .previous +	/* void call_elf( arg1, arg2, entry ) */ +_GLOBAL(call_elf): +	mflr	r0 +	PPC_STLU r1, -STACKFRAME_MINSIZE(r1) +	PPC_STL  r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1) +	mtlr	r5 +	LOAD_REG_IMMEDIATE(r8, saved_stack)		// save our stack pointer +	PPC_STL r1,0(r8) +	mfsdr1	r1 +	addi	r1, r1, -32768		/* - 32 KiB exception stack */ +	addis	r1, r1, -1			/* - 64 KiB stack */ +	LOAD_REG_IMMEDIATE(r5, of_client_callback)	// r5 = callback +	li	r6,0			// r6 = address of client program arguments (unused) +	li	r7,0			// r7 = length of client program arguments (unused) +	li	r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR +	MTMSRD(r0) +	blrl + +#ifdef CONFIG_PPC64 +    /* Restore SF bit */ +    LOAD_REG_IMMEDIATE(r0, MSR_SF | MSR_FP | MSR_ME | MSR_DR | MSR_IR) +    MTMSRD(r0) +#endif +	LOAD_REG_IMMEDIATE(r8, saved_stack)		// restore stack pointer +	mr	r1,r8 +	PPC_LL r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1) +	mtlr	r0 +	addi	r1, r1, STACKFRAME_MINSIZE +	// XXX: should restore r12-r31 etc.. +	// we should not really come here though +	blr + +#ifdef __powerpc64__ +#define STKOFF STACKFRAME_MINSIZE +#define SAVE_SPACE 320 +#else +#define STKOFF 8 +#define SAVE_SPACE 144 +#endif +GLOBL(of_client_callback): + +#ifdef CONFIG_PPC64 +    PPC_STLU r1, -(STACKFRAME_MINSIZE + 16)(r1) +#else +    PPC_STLU r1, -STACKFRAME_MINSIZE(r1) /* fits within alignment */ +#endif + +	/* save r4 */ + +    PPC_STL r4, STKOFF(r1) + +	/* save lr */ + +	mflr	r4 +    PPC_STL r4, PPC_LR_STKOFF(r1) + +	/* restore OF stack */ + +	LOAD_REG_IMMEDIATE(r4, saved_stack) +    PPC_LL  r4, 0(r4) + +	PPC_STLU r4,-SAVE_SPACE(r4) +	PPC_STL r1,(STKOFF)(r4)		// save caller stack +	mr	r1,r4 + +    PPC_STL r2,  (STKOFF +  1 * ULONG_SIZE)(r1) +    PPC_STL r0,  (STKOFF +  2 * ULONG_SIZE)(r1) + +	/* save ctr, cr and xer */ + +	mfctr	r2 +    PPC_STL r2,  (STKOFF +  3 * ULONG_SIZE)(r1) +	mfcr	r2 +    PPC_STL r2,  (STKOFF +  4 * ULONG_SIZE)(r1) +	mfxer	r2 +    PPC_STL r2,  (STKOFF +  5 * ULONG_SIZE)(r1) + +	/* save r5 - r31 */ + +    PPC_STL r5,  (STKOFF +  6 * ULONG_SIZE)(r1) +    PPC_STL r6,  (STKOFF +  7 * ULONG_SIZE)(r1) +    PPC_STL r7,  (STKOFF +  8 * ULONG_SIZE)(r1) +    PPC_STL r8,  (STKOFF +  9 * ULONG_SIZE)(r1) +    PPC_STL r9,  (STKOFF + 10 * ULONG_SIZE)(r1) +    PPC_STL r10, (STKOFF + 11 * ULONG_SIZE)(r1) +    PPC_STL r11, (STKOFF + 12 * ULONG_SIZE)(r1) +    PPC_STL r12, (STKOFF + 13 * ULONG_SIZE)(r1) +    PPC_STL r13, (STKOFF + 14 * ULONG_SIZE)(r1) +    PPC_STL r14, (STKOFF + 15 * ULONG_SIZE)(r1) +    PPC_STL r15, (STKOFF + 16 * ULONG_SIZE)(r1) +    PPC_STL r16, (STKOFF + 17 * ULONG_SIZE)(r1) +    PPC_STL r17, (STKOFF + 18 * ULONG_SIZE)(r1) +    PPC_STL r18, (STKOFF + 19 * ULONG_SIZE)(r1) +    PPC_STL r19, (STKOFF + 20 * ULONG_SIZE)(r1) +    PPC_STL r20, (STKOFF + 21 * ULONG_SIZE)(r1) +    PPC_STL r21, (STKOFF + 22 * ULONG_SIZE)(r1) +    PPC_STL r22, (STKOFF + 23 * ULONG_SIZE)(r1) +    PPC_STL r23, (STKOFF + 24 * ULONG_SIZE)(r1) +    PPC_STL r24, (STKOFF + 25 * ULONG_SIZE)(r1) +    PPC_STL r25, (STKOFF + 26 * ULONG_SIZE)(r1) +    PPC_STL r26, (STKOFF + 27 * ULONG_SIZE)(r1) +    PPC_STL r27, (STKOFF + 28 * ULONG_SIZE)(r1) +    PPC_STL r28, (STKOFF + 29 * ULONG_SIZE)(r1) +    PPC_STL r29, (STKOFF + 30 * ULONG_SIZE)(r1) +    PPC_STL r30, (STKOFF + 31 * ULONG_SIZE)(r1) +    PPC_STL r31, (STKOFF + 32 * ULONG_SIZE)(r1) + +#ifdef CONFIG_PPC64 +    LOAD_REG_IMMEDIATE(r2, of_client_interface) +    ld  r2, 8(r2) +#endif +    bl	BRANCH_LABEL(of_client_interface) + +	/* restore r5 - r31 */ + +    PPC_LL  r5,  (STKOFF +  6 * ULONG_SIZE)(r1) +    PPC_LL  r6,  (STKOFF +  7 * ULONG_SIZE)(r1) +    PPC_LL  r7,  (STKOFF +  8 * ULONG_SIZE)(r1) +    PPC_LL  r8,  (STKOFF +  9 * ULONG_SIZE)(r1) +    PPC_LL  r9,  (STKOFF + 10 * ULONG_SIZE)(r1) +    PPC_LL  r10, (STKOFF + 11 * ULONG_SIZE)(r1) +    PPC_LL  r11, (STKOFF + 12 * ULONG_SIZE)(r1) +    PPC_LL  r12, (STKOFF + 13 * ULONG_SIZE)(r1) +    PPC_LL  r13, (STKOFF + 14 * ULONG_SIZE)(r1) +    PPC_LL  r14, (STKOFF + 15 * ULONG_SIZE)(r1) +    PPC_LL  r15, (STKOFF + 16 * ULONG_SIZE)(r1) +    PPC_LL  r16, (STKOFF + 17 * ULONG_SIZE)(r1) +    PPC_LL  r17, (STKOFF + 18 * ULONG_SIZE)(r1) +    PPC_LL  r18, (STKOFF + 19 * ULONG_SIZE)(r1) +    PPC_LL  r19, (STKOFF + 20 * ULONG_SIZE)(r1) +    PPC_LL  r20, (STKOFF + 21 * ULONG_SIZE)(r1) +    PPC_LL  r21, (STKOFF + 22 * ULONG_SIZE)(r1) +    PPC_LL  r22, (STKOFF + 23 * ULONG_SIZE)(r1) +    PPC_LL  r23, (STKOFF + 24 * ULONG_SIZE)(r1) +    PPC_LL  r24, (STKOFF + 25 * ULONG_SIZE)(r1) +    PPC_LL  r25, (STKOFF + 26 * ULONG_SIZE)(r1) +    PPC_LL  r26, (STKOFF + 27 * ULONG_SIZE)(r1) +    PPC_LL  r27, (STKOFF + 28 * ULONG_SIZE)(r1) +    PPC_LL  r28, (STKOFF + 29 * ULONG_SIZE)(r1) +    PPC_LL  r29, (STKOFF + 30 * ULONG_SIZE)(r1) +    PPC_LL  r30, (STKOFF + 31 * ULONG_SIZE)(r1) +    PPC_LL  r31, (STKOFF + 32 * ULONG_SIZE)(r1) + +	/* restore ctr, cr and xer */ + +    PPC_LL  r2,  (STKOFF +  3 * ULONG_SIZE)(r1) +	mtctr	r2 +    PPC_LL  r2,  (STKOFF +  4 * ULONG_SIZE)(r1) +	mtcr	r2 +    PPC_LL  r2,  (STKOFF +  5 * ULONG_SIZE)(r1) +	mtxer	r2 + +	/* restore r0 and r2 */ + +    PPC_LL  r2,  (STKOFF +  1 * ULONG_SIZE)(r1) +    PPC_LL  r0,  (STKOFF +  2 * ULONG_SIZE)(r1) + +	/* restore caller stack */ + +    PPC_LL  r1,  (STKOFF)(r1) + +    PPC_LL  r4, PPC_LR_STKOFF(r1) +	mtlr	r4 +    PPC_LL  r4, STKOFF(r1) +    PPC_LL  r1, 0(r1) + +	blr + +	/* rtas glue (must be reloctable) */ +GLOBL(of_rtas_start): +	/* r3 = argument buffer, r4 = of_rtas_start */ +	/* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */ +	blr +GLOBL(of_rtas_end): + + +#define CACHE_LINE_SIZE         32 +#define LG_CACHE_LINE_SIZE      5 + +/* flush_icache_range( unsigned long start, unsigned long stop) */ +_GLOBAL(flush_icache_range): +        li      r5,CACHE_LINE_SIZE-1 +        andc    r3,r3,r5 +        subf    r4,r3,r4 +        add     r4,r4,r5 +        srwi.   r4,r4,LG_CACHE_LINE_SIZE +        beqlr +        mtctr   r4 +        mr      r6,r3 +1:      dcbst   0,r3 +        addi    r3,r3,CACHE_LINE_SIZE +        bdnz    1b +        sync                            /* wait for dcbst's to get to ram */ +        mtctr   r4 +2:      icbi    0,r6 +        addi    r6,r6,CACHE_LINE_SIZE +        bdnz    2b +        sync                            /* additional sync needed on g4 */ +        isync +        blr + +        /* Get RAM size from QEMU configuration device */ + +#define CFG_ADDR 0xf0000510 +#define FW_CFG_RAM_SIZE         0x03 + +compute_ramsize: +        LOAD_REG_IMMEDIATE(r9, CFG_ADDR) +        li      r0,FW_CFG_RAM_SIZE +        sth     r0,0(r9) +        LOAD_REG_IMMEDIATE(r9, CFG_ADDR + 2) +        lbz     r1,0(r9) +        lbz     r0,0(r9) +        slwi    r0,r0,8 +        or      r1,r1,r0 +        lbz     r0,0(r9) +        slwi    r0,r0,16 +        or      r1,r1,r0 +        lbz     r0,0(r9) +        slwi    r0,r0,24 +        or      r3,r1,r0 +        blr + +        /* Hard reset vector */ +	.section .romentry,"ax" +	bl	_entry diff --git a/roms/openbios/arch/ppc/qemu/tree.fs b/roms/openbios/arch/ppc/qemu/tree.fs new file mode 100644 index 00000000..1ed83839 --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/tree.fs @@ -0,0 +1,71 @@ +\   QEMU specific initialization code +\ +\   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.fs + +\ ------------------------------------------------------------- +\ device-tree +\ ------------------------------------------------------------- + +" /" find-device +\ Apple calls the root node device-tree +" device-tree" device-name +[IFDEF] CONFIG_PPC64 2 [ELSE] 1 [THEN] encode-int " #address-cells" property +1 encode-int " #size-cells" property +h# 05f5e100 encode-int " clock-frequency" property + +new-device +	" cpus" device-name +	1 encode-int " #address-cells" property +	0 encode-int " #size-cells" property +	external + +	: encode-unit ( unit -- str len ) +		pocket tohexstr +	; + +	: decode-unit ( str len -- unit ) +		parse-hex +	; + +finish-device + +new-device +	" memory" device-name +	" memory" device-type +	external +	: open true ; +	: close ; +finish-device + +\ ------------------------------------------------------------- +\ /packages +\ ------------------------------------------------------------- + +" /packages" find-device + +	" packages" device-name +	external +	\ allow packages to be opened with open-dev +	: open true ; +	: close ; + +\ /packages/terminal-emulator +new-device +	" terminal-emulator" device-name +	external +	: open true ; +	: close ; +	\ : write ( addr len -- actual ) +	\	dup -rot type +	\ ; +finish-device + +\ ------------------------------------------------------------- +\ The END +\ ------------------------------------------------------------- +device-end diff --git a/roms/openbios/arch/ppc/qemu/vfd.c b/roms/openbios/arch/ppc/qemu/vfd.c new file mode 100644 index 00000000..308d0e33 --- /dev/null +++ b/roms/openbios/arch/ppc/qemu/vfd.c @@ -0,0 +1,42 @@ +/* + *   Creation Date: <2004/08/28 17:29:43 greg> + *   Time-stamp: <2004/08/28 17:29:43 greg> + * + *	<vfd.c> + * + *	Simple text console + * + *   Copyright (C) 2004 Greg Watson + * + *   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 "qemu/qemu.h" + +static int vfd_is_open; + +static int +vfd_init( void ) +{ +	vfd_is_open = 1; +	return 0; +} + +void +vfd_close( void ) +{ +} + +int +vfd_draw_str( const char *str ) +{ +	if (!vfd_is_open) +		vfd_init(); + +	return 0; +} diff --git a/roms/openbios/arch/ppc/start.S b/roms/openbios/arch/ppc/start.S new file mode 100644 index 00000000..40ee0896 --- /dev/null +++ b/roms/openbios/arch/ppc/start.S @@ -0,0 +1,335 @@ +/* + *   Creation Date: <2001/06/16 21:30:18 samuel> + *   Time-stamp: <2003/04/04 16:32:06 samuel> + * + *	<init.S> + * + *	Asm glue for ELF images run inside MOL + * + *   Copyright (C) 2001, 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 "asm/asmdefs.h" +#include "asm/processor.h" +#include "osi.h" + +/************************************************************************/ +/*	Macros								*/ +/************************************************************************/ + +#define ILLEGAL_VECTOR( v )	.org __vectors + v ; bl trap_error ; +#define VECTOR( v, dummystr )	.org __vectors + v ; vector__##v + +#define EXCEPTION_PREAMBLE \ +	mtsprg1	r1 ;		/* scratch */ \ +	mfsprg0	r1 ;		/* exception stack in sprg0 */ \ +	addi	r1,r1,-80 ;	/* push exception frame */ \ + \ +	stw	r0,0(r1) ;	/* save r0 */ \ +	mfsprg1	r0 ; \ +	stw	r0,4(r1) ;	/* save r1 */ \ +	stw	r2,8(r1) ;	/* save r2 */ \ +	stw	r3,12(r1) ;	/* save r3 */ \ +	stw	r4,16(r1) ; \ +	stw	r5,20(r1) ; \ +	stw	r6,24(r1) ; \ +	stw	r7,28(r1) ; \ +	stw	r8,32(r1) ; \ +	stw	r9,36(r1) ; \ +	stw	r10,40(r1) ; \ +	stw	r11,44(r1) ; \ +	stw	r12,48(r1) ; \ + \ +	mflr	r0 ; \ +	stw	r0,52(r1) ; \ +	mfcr	r0 ; \ +	stw	r0,56(r1) ; \ +	mfctr	r0 ; \ +	stw	r0,60(r1) ; \ +	mfxer	r0 ; \ +	stw	r0,64(r1) ; \ + \ +	/* 76(r1) unused */ \ +	addi	r1,r1,-16 ;	/* call conventions uses 0(r1) and 4(r1)... */ + + +/************************************************************************/ +/*	stack space							*/ +/************************************************************************/ + +	.section .bss +	.balign 32 +	.space  32*1024		// 32 K client stack +client_stack: +	.space	128 + +	.space	64*1024		// 64 K stack +stack:	.space  64 + +	.space  32*1024		// 32 K exception stack +estack:	.space	128 + + +/************************************************************************/ +/*	entry								*/ +/************************************************************************/ + +	.text +GLOBL(_start): +	li	r0,0 +	mtmsr	r0 + +	lis	r1,HA(estack) +	addi	r1,r1,LO(estack) +	mtsprg0 r1			// setup exception stack +	lis	r1,HA(stack) +	addi	r1,r1,LO(stack) + +	// copy exception vectors +	lis	r3,HA(__vectors) +	addi	r3,r3,LO(__vectors) +	li	r4,0 +	li	r5,__vectors_end - __vectors + 16 +	rlwinm	r5,r5,0,0,28 +1:	lwz	r6,0(r3) +	lwz	r7,4(r3) +	lwz	r8,8(r3) +	lwz	r9,12(r3) +	stw	r6,0(r4) +	stw	r7,4(r4) +	stw	r8,8(r4) +	stw	r9,12(r4) +	dcbst	0,r4 +	sync +	icbi	0,r4 +	sync +	addi	r5,r5,-16 +	addi	r3,r3,16 +	addi	r4,r4,16 +	cmpwi	r5,0 +	bgt	1b +	isync + +	bl	setup_mmu +	bl	entry +1:	nop +	b	1b + + +	/* According to IEEE 1275, PPC bindings: +	 * +	 * 	MSR = FP, ME + (DR|IR) +	 *	r1 = stack (32 K + 32 bytes link area above) +	 *	r5 = clint interface handler +	 *	r6 = address of client program arguments (unused) +	 *	r7 = length of client program arguments (unsed) +	 */ +saved_stack: +	.long	0 +	/* void call_elf( entry ) */ +GLOBL(call_elf): +	mflr	r0 +	stwu	r1,-16(r1) +	stw	r0,20(r1) +	mtlr	r3 +	lis	r8,HA(saved_stack) +	addi	r8,r8,LO(saved_stack)		// save our stack pointer +	stw	r1,0(r8) +	lis	r1,HA(client_stack) +	addi	r1,r1,LO(client_stack) +	lis	r5,HA(of_client_callback) +	addi	r5,r5,LO(of_client_callback)	// r5 = callback +	li	r6,0			// r6 = address of client program arguments (unused) +	li	r7,0			// r7 = length of client program arguments (unused) +	li	r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR +	mtmsr	r0 +	blrl + +	lis	r8,HA(saved_stack) +	addi	r8,r8,LO(saved_stack)		// restore stack pointer +	mr	r1,r8 +	lwz	r0,20(r1) +	mtlr	r0 +	addi	r1,r1,16 +	// XXX: should restore r12-r31 etc.. +	// we should not really come here though +	blr + +GLOBL(of_client_callback): +	lis	r4,HA(saved_stack) +	addi	r4,r4,LO(saved_stack) +	lwz	r4,0(r4) +	stwu	r4,-32(r4) +	mflr	r5 +	stw	r5,32+4(r4) +	stw	r1,8(r4)		// save caller stack +	mr	r1,r4 +	stw	r2,12(r1) +	stw	r0,16(r1) +	mfctr	r2 +	stw	r2,20(r1) +	mfcr	r2 +	stw	r2,24(r1) +	mfxer	r2 +	stw	r2,28(r1) +	// do we need to save more registers? +	bl	of_client_interface +	lwz	r4,32+4(r1) +	mtlr	r4 +	lwz	r2,20(r1) +	mtctr	r2 +	lwz	r2,24(r1) +	mtcr	r2 +	lwz	r2,28(r1) +	mtxer	r2 +	lwz	r2,12(r1) +	lwz	r0,16(r1) +	lwz	r1,8(r1)		// restore caller stack +	blr + +	/* rtas glue (must be reloctable) */ +GLOBL(of_rtas_start): +	/* r3 = argument buffer, r4 = of_rtas_start */ +	/* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */ +	mr      r6,r3 +	lis	r3,HA(OSI_SC_MAGIC_R3) +	addi	r3,r3,LO(OSI_SC_MAGIC_R3) +	lis	r4,HA(OSI_SC_MAGIC_R4) +	addi	r4,r4,LO(OSI_SC_MAGIC_R4) +	li	r5,OSI_OF_RTAS +	sc +	blr +GLOBL(of_rtas_end): + + +	/* used in a hack to the newworld calibration */ +GLOBL(nw_dec_calibration): +	.long	0 +GLOBL(timer_calib_start): +	lis	r3,HA(nw_dec_calibration) +	addi	r3,r3,LO(nw_dec_calibration) +	lwz	r3,0(r3) +	blr +GLOBL(timer_calib_end): + + +/************************************************************************/ +/*	vectors								*/ +/************************************************************************/ + +GLOBL(__vectors): +	nop			// NULL-jmp trap +1:	nop			// +	b	1b + +exception_return: +	addi	r1,r1,16	// pop ABI frame + +	lwz	r0,52(r1) +	mtlr	r0 +	lwz	r0,56(r1) +	mtcr	r0 +	lwz	r0,60(r1) +	mtctr	r0 +	lwz	r0,64(r1) +	mtxer	r0 + +	lwz	r0,0(r1)	// restore r0 +	lwz	r2,8(r1)	// restore r2 +	lwz	r3,12(r1)	// restore r3 +	lwz	r4,16(r1) +	lwz	r5,20(r1) +	lwz	r6,24(r1) +	lwz	r7,28(r1) +	lwz	r8,32(r1) +	lwz	r9,36(r1) +	lwz	r10,40(r1) +	lwz	r11,44(r1) +	lwz	r12,48(r1) +	lwz	r1,4(r1)	// restore r1 +	rfi + +trap_error: +	mflr	r3 +	b	unexpected_excep + +ILLEGAL_VECTOR( 0x100 ) +ILLEGAL_VECTOR( 0x200 ) + +VECTOR( 0x300, "DSI" ): +	EXCEPTION_PREAMBLE +	lis	r3,HA(dsi_exception) +	addi	r3,r3,LO(dsi_exception) +	mtctr	r3 +	bctrl +	b	exception_return + +VECTOR( 0x400, "ISI" ): +	EXCEPTION_PREAMBLE +	lis	r3,HA(isi_exception) +	addi	r3,r3,LO(isi_exception) +	mtctr	r3 +	bctrl +	b	exception_return + +	ILLEGAL_VECTOR( 0x500 ) +	ILLEGAL_VECTOR( 0x600 ) +	ILLEGAL_VECTOR( 0x700 ) + +VECTOR( 0x800, "FPU" ): +	mtsprg1	r3 +	mfsrr1	r3 +	ori	r3,r3,0x2000 +	mtsrr1	r3 +	mfsprg1	r3 +	rfi + +ILLEGAL_VECTOR( 0x900 ) +ILLEGAL_VECTOR( 0xa00 ) +ILLEGAL_VECTOR( 0xb00 ) +ILLEGAL_VECTOR( 0xc00 ) +ILLEGAL_VECTOR( 0xd00 ) +ILLEGAL_VECTOR( 0xe00 ) +ILLEGAL_VECTOR( 0xf00 ) +ILLEGAL_VECTOR( 0xf20 ) +ILLEGAL_VECTOR( 0x1000 ) +ILLEGAL_VECTOR( 0x1100 ) +ILLEGAL_VECTOR( 0x1200 ) +ILLEGAL_VECTOR( 0x1300 ) +ILLEGAL_VECTOR( 0x1400 ) +ILLEGAL_VECTOR( 0x1500 ) +ILLEGAL_VECTOR( 0x1600 ) +ILLEGAL_VECTOR( 0x1700 ) + +GLOBL(__vectors_end): + + +#define CACHE_LINE_SIZE         32 +#define LG_CACHE_LINE_SIZE      5 + +/* flush_icache_range( unsigned long start, unsigned long stop) */ +GLOBL(flush_icache_range): +        li      r5,CACHE_LINE_SIZE-1 +        andc    r3,r3,r5 +        subf    r4,r3,r4 +        add     r4,r4,r5 +        srwi.   r4,r4,LG_CACHE_LINE_SIZE +        beqlr +        mtctr   r4 +        mr      r6,r3 +1:      dcbst   0,r3 +        addi    r3,r3,CACHE_LINE_SIZE +        bdnz    1b +        sync                            /* wait for dcbst's to get to ram */ +        mtctr   r4 +2:      icbi    0,r6 +        addi    r6,r6,CACHE_LINE_SIZE +        bdnz    2b +        sync                            /* additional sync needed on g4 */ +        isync +        blr diff --git a/roms/openbios/arch/ppc/timebase.S b/roms/openbios/arch/ppc/timebase.S new file mode 100644 index 00000000..19faed49 --- /dev/null +++ b/roms/openbios/arch/ppc/timebase.S @@ -0,0 +1,33 @@ +#include "asm/asmdefs.h" +#include "asm/processor.h" + +/* + * unsigned long long _get_ticks(void); + */ +_GLOBAL(_get_ticks): +1:      mftbu   r3 +        mftb    r4 +        mftbu   r5 +        cmpw    0,r3,r5 +        bne     1b +        blr + +/* + * Delay for a number of ticks + */ +_GLOBAL(_wait_ticks): +        mflr    r8              /* save link register */ +        mr      r7, r3          /* save tick count */ +        bl      BRANCH_LABEL(_get_ticks)       /* Get start time */ + +        /* Calculate end time */ +        addc    r7, r4, r7      /* Compute end time lower */ +        addze   r6, r3          /*     and end time upper */ + +1:      bl      BRANCH_LABEL(_get_ticks)       /* Get current time */ +        subfc   r4, r4, r7      /* Subtract current time from end time */ +        subfe.  r3, r3, r6 +        bge     1b              /* Loop until time expired */ + +        mtlr    r8              /* restore link register */ +        blr  | 
