diff options
Diffstat (limited to 'qemu/roms/openbios')
32 files changed, 903 insertions, 769 deletions
diff --git a/qemu/roms/openbios/Makefile.target b/qemu/roms/openbios/Makefile.target index a7363e667..4c54105a7 100644 --- a/qemu/roms/openbios/Makefile.target +++ b/qemu/roms/openbios/Makefile.target @@ -15,7 +15,7 @@ HOSTCFLAGS+= -Wstrict-aliasing -Wwrite-strings -Wmissing-prototypes -Wnested-ext HOSTCFLAGS+= -W # Flags for dependency generation HOSTCFLAGS+= -MMD -MP -MT $@ -MF '$(*D)/$(*F).d' -HOSTINCLUDES := -I$(SRCDIR)/include -I$(SRCDIR)/kernel -I$(SRCDIR)/kernel/include -I$(ODIR)/target/include +HOSTINCLUDES := -I$(SRCDIR)/include -I$(SRCDIR)/kernel -I$(SRCDIR)/kernel/include -iquote $(ODIR)/target/include CC := $(TARGET)gcc AS := $(TARGET)as diff --git a/qemu/roms/openbios/arch/ppc/qemu/init.c b/qemu/roms/openbios/arch/ppc/qemu/init.c index 4fe8b7220..b76c5706f 100644 --- a/qemu/roms/openbios/arch/ppc/qemu/init.c +++ b/qemu/roms/openbios/arch/ppc/qemu/init.c @@ -302,6 +302,11 @@ cpu_generic_init(const struct cpudef *cpu) fword("encode-string"); push_str("state"); fword("property"); + + PUSH(0x20); + fword("encode-int"); + push_str("reservation-granule-size"); + fword("property"); } static void @@ -596,6 +601,11 @@ go(void) { ucell addr; + /* Insert copyright property for MacOS 9 and below */ + if (find_dev("/rom/macos")) { + fword("insert-copyright-property"); + } + feval("saved-program-state >sps.entry @"); addr = POP(); @@ -680,6 +690,60 @@ static void ffilll(void) } } +/* + * adler32 ( adler buf len -- checksum ) + * + * Adapted from Mark Adler's original implementation (zlib license) + * + * Both OS 9 and BootX require this word for payload validation. + */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +static void adler32(void) +{ + uint32_t len = (uint32_t)POP(); + char *buf = (char *)POP(); + uint32_t adler = (uint32_t)POP(); + + if (buf == NULL) { + RET(-1); + } + + uint32_t base = 65521; + uint32_t nmax = 5552; + + uint32_t s1 = adler & 0xffff; + uint32_t s2 = (adler >> 16) & 0xffff; + + uint32_t k; + while (len > 0) { + k = (len < nmax ? len : nmax); + len -= k; + + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) { + do { + s1 += *buf++; + s2 += s1; + } while (--k); + } + + s1 %= base; + s2 %= base; + } + + RET(s2 << 16 | s1); +} + void arch_of_init(void) { @@ -945,6 +1009,9 @@ arch_of_init(void) /* Implementation of filll word (required by BootX) */ bind_func("filll", ffilll); + + /* Implementation of adler32 word (required by OS 9, BootX) */ + bind_func("(adler32)", adler32); bind_func("platform-boot", boot); bind_func("(go)", go); diff --git a/qemu/roms/openbios/arch/ppc/qemu/methods.c b/qemu/roms/openbios/arch/ppc/qemu/methods.c index fd993daa9..930b47c4e 100644 --- a/qemu/roms/openbios/arch/ppc/qemu/methods.c +++ b/qemu/roms/openbios/arch/ppc/qemu/methods.c @@ -114,6 +114,8 @@ static void ciface_quiesce( unsigned long args[], unsigned long ret[] ) { usb_exit(); + + ob_ide_quiesce(); #if 0 unsigned long msr; /* This seems to be the correct thing to do - but I'm not sure */ @@ -164,21 +166,21 @@ DECLARE_UNNAMED_NODE( mmu, INSTALL_OPEN, 0 ); DECLARE_NODE( mmu_ciface, 0, 0, "+/openprom/client-services" ); -/* ( phys size align --- base ) */ +/* ( [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 ); + phys_addr_t phys = -1; - if( ret == -1 ) { - printk("MEM: claim failure\n"); - throw( -13 ); - return; + if (!align) { + phys = POP(); } - PUSH( ret ); + + phys = ofmem_claim_phys(phys, size, align); + + PUSH(phys); } /* ( phys size --- ) */ @@ -188,24 +190,24 @@ mem_release( void ) POP(); POP(); } -/* ( phys size align --- base ) */ +/* ( [virt] 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 ); + ucell virt = -1; - if( ret == -1 ) { - printk("MMU: CLAIM failure\n"); - throw( -13 ); - return; + if (!align) { + virt = POP(); } - PUSH( ret ); + + virt = ofmem_claim_virt(virt, size, align); + + PUSH(virt); } -/* ( phys size --- ) */ +/* ( virt size --- ) */ static void mmu_release( void ) { diff --git a/qemu/roms/openbios/arch/ppc/qemu/qemu.fs b/qemu/roms/openbios/arch/ppc/qemu/qemu.fs index 458af1bc7..3d99a34a1 100644 --- a/qemu/roms/openbios/arch/ppc/qemu/qemu.fs +++ b/qemu/roms/openbios/arch/ppc/qemu/qemu.fs @@ -93,3 +93,48 @@ variable keyboard-phandle 0 keyboard-phandle ! :noname set-defaults ; PREPOST-initializer + +\ ------------------------------------------------------------------------- +\ copyright property handling +\ ------------------------------------------------------------------------- + +: insert-copyright-property + \ As required for MacOS 9 and below + " Pbclevtug 1983-2001 Nccyr Pbzchgre, Vap. GUVF ZRFFNTR SBE PBZCNGVOVYVGL BAYL" + rot13-str encode-string " copyright" + " /" find-package if + " set-property" $find if + execute + else + 3drop drop + then + then +; + +: delete-copyright-property + \ Remove copyright property created above + active-package + " /" find-package if + active-package! + " copyright" delete-property + then + active-package! +; + +: (exit) + \ Clean up before returning to the interpreter + delete-copyright-property +; + +\ ------------------------------------------------------------------------- +\ Adler-32 wrapper +\ ------------------------------------------------------------------------- + +: adler32 ( adler buf len -- checksum ) + " (adler32)" $find if + execute + else + ." Can't find " ( adler32-name ) type cr + 3drop 0 + then +; diff --git a/qemu/roms/openbios/arch/ppc/qemu/tree.fs b/qemu/roms/openbios/arch/ppc/qemu/tree.fs index 1ed838397..5b6bbc6f7 100644 --- a/qemu/roms/openbios/arch/ppc/qemu/tree.fs +++ b/qemu/roms/openbios/arch/ppc/qemu/tree.fs @@ -42,6 +42,14 @@ new-device : close ; finish-device +new-device + " rom" device-name + h# ff800000 encode-int 0 encode-int encode+ " reg" property + 1 encode-int " #address-cells" property + h# ff800000 encode-int h# 800000 encode-int encode+ + h# ff800000 encode-int encode+ " ranges" property +finish-device + \ ------------------------------------------------------------- \ /packages \ ------------------------------------------------------------- diff --git a/qemu/roms/openbios/arch/sparc64/call-client.S b/qemu/roms/openbios/arch/sparc64/call-client.S index f365e3cb1..a8c0348e4 100644 --- a/qemu/roms/openbios/arch/sparc64/call-client.S +++ b/qemu/roms/openbios/arch/sparc64/call-client.S @@ -1,3 +1,5 @@ +#include "cpustate.h" + .globl sparc64_of_client_interface, client_tba @@ -9,151 +11,9 @@ * behaviour of OBP. */ -#define SAVE_WINDOW_STATE(type) \ - setx client_window, %g6, %g1; \ - rdpr %cwp, %g7; \ - stx %g7, [%g1]; \ - rdpr %cansave, %g7; \ - stx %g7, [%g1 + 0x8]; \ - rdpr %canrestore, %g7; \ - stx %g7, [%g1 + 0x10]; \ - rdpr %otherwin, %g7; \ - stx %g7, [%g1 + 0x18]; \ - rdpr %wstate, %g7; \ - stx %g7, [%g1 + 0x20]; \ - rdpr %cleanwin, %g7; \ - stx %g7, [%g1 + 0x28]; \ - \ - stx %o0, [%g1 + 0x30]; \ - stx %o1, [%g1 + 0x38]; \ - stx %o2, [%g1 + 0x40]; \ - stx %o3, [%g1 + 0x48]; \ - stx %o4, [%g1 + 0x50]; \ - stx %o5, [%g1 + 0x58]; \ - stx %o6, [%g1 + 0x60]; \ - stx %o7, [%g1 + 0x68]; \ - \ - rdpr %pstate, %g7; \ - stx %g7, [%g1 + 0x70]; \ - rd %y, %g7; \ - stx %g7, [%g1 + 0x78]; \ - rd %fprs, %g7; \ - stx %g7, [%g1 + 0x80]; \ - \ - /* Now iterate through all of the windows saving all l and i registers */ \ - add %g1, 0x90, %g5; \ - \ - /* Get the number of windows in %g6 */ \ - rdpr %ver, %g6; \ - and %g6, 0xf, %g6; \ - inc %g6; \ - \ -save_cpu_window_##type: \ - deccc %g6; \ - wrpr %g6, %cwp; \ - stx %l0, [%g5]; \ - stx %l1, [%g5 + 0x8]; \ - stx %l2, [%g5 + 0x10]; \ - stx %l3, [%g5 + 0x18]; \ - stx %l4, [%g5 + 0x20]; \ - stx %l5, [%g5 + 0x28]; \ - stx %l6, [%g5 + 0x30]; \ - stx %l7, [%g5 + 0x38]; \ - stx %i0, [%g5 + 0x40]; \ - stx %i1, [%g5 + 0x48]; \ - stx %i2, [%g5 + 0x50]; \ - stx %i3, [%g5 + 0x58]; \ - stx %i4, [%g5 + 0x60]; \ - stx %i5, [%g5 + 0x68]; \ - stx %i6, [%g5 + 0x70]; \ - stx %i7, [%g5 + 0x78]; \ - bne save_cpu_window_##type; \ - add %g5, 0x80, %g5; \ - \ - /* For 8 windows with 16 registers to save in the window, memory required \ - is 16*8*8 = 0x400 bytes */ \ - \ - /* Now we should be in window 0 so update the other window registers */ \ - rdpr %ver, %g6; \ - and %g6, 0xf, %g6; \ - dec %g6; \ - wrpr %g6, %cansave; \ - \ - wrpr %g0, %cleanwin; \ - wrpr %g0, %canrestore; \ - wrpr %g0, %otherwin; - - -#define RESTORE_WINDOW_STATE(type) \ - setx client_window, %g6, %g1; \ - \ - /* Get the number of windows in %g6 */ \ - rdpr %ver, %g6; \ - and %g6, 0xf, %g6; \ - inc %g6; \ - \ - /* Now iterate through all of the windows restoring all l and i registers */ \ - add %g1, 0x90, %g5; \ - \ -restore_cpu_window_##type: \ - deccc %g6; \ - wrpr %g6, %cwp; \ - ldx [%g5], %l0; \ - ldx [%g5 + 0x8], %l1; \ - ldx [%g5 + 0x10], %l2; \ - ldx [%g5 + 0x18], %l3; \ - ldx [%g5 + 0x20], %l4; \ - ldx [%g5 + 0x28], %l5; \ - ldx [%g5 + 0x30], %l6; \ - ldx [%g5 + 0x38], %l7; \ - ldx [%g5 + 0x40], %i0; \ - ldx [%g5 + 0x48], %i1; \ - ldx [%g5 + 0x50], %i2; \ - ldx [%g5 + 0x58], %i3; \ - ldx [%g5 + 0x60], %i4; \ - ldx [%g5 + 0x68], %i5; \ - ldx [%g5 + 0x70], %i6; \ - ldx [%g5 + 0x78], %i7; \ - bne restore_cpu_window_##type; \ - add %g5, 0x80, %g5; \ - \ - /* Restore the window registers to their original value */ \ - ldx [%g1], %g7; \ - wrpr %g7, %cwp; \ - ldx [%g1 + 0x8], %g7; \ - wrpr %g7, %cansave; \ - ldx [%g1 + 0x10], %g7; \ - wrpr %g7, %canrestore; \ - ldx [%g1 + 0x18], %g7; \ - wrpr %g7, %otherwin; \ - ldx [%g1 + 0x20], %g7; \ - wrpr %g7, %wstate; \ - ldx [%g1 + 0x28], %g7; \ - wrpr %g7, %cleanwin; \ - \ - ldx [%g1 + 0x30], %o0; \ - ldx [%g1 + 0x38], %o1; \ - ldx [%g1 + 0x40], %o2; \ - ldx [%g1 + 0x48], %o3; \ - ldx [%g1 + 0x50], %o4; \ - ldx [%g1 + 0x58], %o5; \ - ldx [%g1 + 0x60], %o6; \ - ldx [%g1 + 0x68], %o7; \ - \ - ldx [%g1 + 0x70], %g7; \ - wrpr %g7, %pstate; \ - ldx [%g1 + 0x78], %g7; \ - wr %g7, 0, %y; \ - ldx [%g1 + 0x80], %g7; \ - wr %g7, 0, %fprs - - .data .align 8 - .skip 16384 -openbios_stack: - client_stack: .xword 0 client_tba: @@ -176,15 +36,15 @@ client_window: sparc64_of_client_interface: /* Save globals on callers stack */ - add %sp, -56, %sp + add %sp, -248, %sp - stx %g1, [%sp + 2047 + 0] - stx %g2, [%sp + 2047 + 8] - stx %g3, [%sp + 2047 + 16] - stx %g4, [%sp + 2047 + 24] - stx %g5, [%sp + 2047 + 32] - stx %g6, [%sp + 2047 + 40] - stx %g7, [%sp + 2047 + 48] + stx %g1, [%sp + 2047 + 192] + stx %g2, [%sp + 2047 + 200] + stx %g3, [%sp + 2047 + 208] + stx %g4, [%sp + 2047 + 216] + stx %g5, [%sp + 2047 + 224] + stx %g6, [%sp + 2047 + 232] + stx %g7, [%sp + 2047 + 240] /* Save client trap table */ setx client_tba, %g6, %g7 @@ -196,22 +56,44 @@ sparc64_of_client_interface: stx %sp, [%g7] /* Save windows */ - SAVE_WINDOW_STATE(cif) - - /* Move to OpenBIOS stack */ - setx openbios_stack - 2047 - 192, %g6, %g7 + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + add %g1, -CONTEXT_STATE_SIZE, %g1 + stx %g1, [%g7] + + SAVE_CPU_WINDOW_STATE(cif) + + /* Move to OpenBIOS context stack */ + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g6 + setx CONTEXT_STACK_SIZE, %g4, %g5 + sub %g6, %g5, %g6 + stx %g6, [%g7] + + setx - 2047 - 192, %g6, %g7 + add %g1, %g7, %g7 mov %g7, %sp /* Call client inteface */ call of_client_interface ldx [%g1 + 0x30], %o0 - setx client_window, %g6, %g1 - stx %o0, [%g1 + 0x30] - /* Restore windows */ - RESTORE_WINDOW_STATE(cif) - + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + setx CONTEXT_STACK_SIZE, %g4, %g5 + add %g1, %g5, %g1 + stx %g1, [%g7] + + /* Return value */ + stx %o0, [%g1 + 0x30] + + RESTORE_CPU_WINDOW_STATE(cif) + + add %g1, CONTEXT_STATE_SIZE, %g1 + setx _fcstack_ptr, %g6, %g7 + stx %g1, [%g7] + /* Restore stack */ setx client_stack, %g6, %g7 ldx [%g7], %sp @@ -222,15 +104,15 @@ sparc64_of_client_interface: wrpr %g6, %tba /* Restore globals */ - ldx [%sp + 2047 + 0], %g1 - ldx [%sp + 2047 + 8], %g2 - ldx [%sp + 2047 + 16], %g3 - ldx [%sp + 2047 + 24], %g4 - ldx [%sp + 2047 + 32], %g5 - ldx [%sp + 2047 + 40], %g6 - ldx [%sp + 2047 + 48], %g7 - - add %sp, 56, %sp + ldx [%sp + 2047 + 192], %g1 + ldx [%sp + 2047 + 200], %g2 + ldx [%sp + 2047 + 208], %g3 + ldx [%sp + 2047 + 216], %g4 + ldx [%sp + 2047 + 224], %g5 + ldx [%sp + 2047 + 232], %g6 + ldx [%sp + 2047 + 240], %g7 + + add %sp, 248, %sp jmp %o7+8 nop diff --git a/qemu/roms/openbios/arch/sparc64/context.c b/qemu/roms/openbios/arch/sparc64/context.c index 2e7668958..98932ee9c 100644 --- a/qemu/roms/openbios/arch/sparc64/context.c +++ b/qemu/roms/openbios/arch/sparc64/context.c @@ -40,6 +40,10 @@ static uint8_t image_stack[IMAGE_STACK_SIZE]; /* Pointer to startup context (physical address) */ unsigned long __boot_ctx; +/* Pointer to Forth context stack */ +void *_fcstack_ptr = &_efcstack; + + /* * Main starter * This is the C function that runs first. diff --git a/qemu/roms/openbios/arch/sparc64/cpustate.h b/qemu/roms/openbios/arch/sparc64/cpustate.h new file mode 100644 index 000000000..0c276bfd1 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/cpustate.h @@ -0,0 +1,244 @@ +/* + * Save/restore CPU state macros + * + * Copyright (C) 2015 Mark Cave-Ayland (mark.cave-ayland@ilande.co.uk>) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +/* State size for context (see below) */ +#define CONTEXT_STATE_SIZE 0x510 + +/* Stack size for context (allocated inline of the context stack) */ +#define CONTEXT_STACK_SIZE 0x2000 + +/* + * SAVE_CPU_STATE and RESTORE_CPU_STATE are macros used to enable a context switch + * to C to occur within the MMU I/D TLB miss handlers. + * + * Because these handlers are called on a TLB miss, we cannot use flushw to store + * processor window state on the stack, as the memory areas used by each window's + * stack pointer may not be in the TLB, causing recursive TLB miss traps. + * + * For this reason, we save window state by manually rotating the window registers + * and saving their contents (along with other vital registers) into a special + * tlb_handler_stack defined above which is guaranteed to be locked in the TLB, and + * so won't cause issues with trap recursion. + * + * Once this process is complete, we remain in a TL=0, CWP=0 state (with IE=1 to allow + * window fill/spill traps if required), switch to our safe tlb_handler_stack and + * invoke the miss handler. + */ + +#define SAVE_CPU_WINDOW_STATE(type) \ + /* Save window state into context at %g1 */ \ + rdpr %cwp, %g7; \ + stx %g7, [%g1]; \ + rdpr %cansave, %g7; \ + stx %g7, [%g1 + 0x8]; \ + rdpr %canrestore, %g7; \ + stx %g7, [%g1 + 0x10]; \ + rdpr %otherwin, %g7; \ + stx %g7, [%g1 + 0x18]; \ + rdpr %wstate, %g7; \ + stx %g7, [%g1 + 0x20]; \ + rdpr %cleanwin, %g7; \ + stx %g7, [%g1 + 0x28]; \ + \ + stx %o0, [%g1 + 0x30]; \ + stx %o1, [%g1 + 0x38]; \ + stx %o2, [%g1 + 0x40]; \ + stx %o3, [%g1 + 0x48]; \ + stx %o4, [%g1 + 0x50]; \ + stx %o5, [%g1 + 0x58]; \ + stx %o6, [%g1 + 0x60]; \ + stx %o7, [%g1 + 0x68]; \ + \ + rdpr %pstate, %g7; \ + stx %g7, [%g1 + 0x70]; \ + rd %y, %g7; \ + stx %g7, [%g1 + 0x78]; \ + rd %fprs, %g7; \ + stx %g7, [%g1 + 0x80]; \ + rdpr %tl, %g7; \ + stx %g7, [%g1 + 0x88]; \ + \ + /* Now iterate through all of the windows saving all l and i registers */ \ + add %g1, 0x90, %g5; \ + \ + /* Get the number of windows in %g6 */ \ + rdpr %ver, %g6; \ + and %g6, 0xf, %g6; \ + \ + mov %g6, %g4; \ + inc %g4; \ + \ + /* Starting cwp in g7 */ \ + rdpr %cwp, %g7; \ + \ +save_cpu_window_##type: \ + wrpr %g7, %cwp; \ + stx %l0, [%g5]; \ + stx %l1, [%g5 + 0x8]; \ + stx %l2, [%g5 + 0x10]; \ + stx %l3, [%g5 + 0x18]; \ + stx %l4, [%g5 + 0x20]; \ + stx %l5, [%g5 + 0x28]; \ + stx %l6, [%g5 + 0x30]; \ + stx %l7, [%g5 + 0x38]; \ + stx %i0, [%g5 + 0x40]; \ + stx %i1, [%g5 + 0x48]; \ + stx %i2, [%g5 + 0x50]; \ + stx %i3, [%g5 + 0x58]; \ + stx %i4, [%g5 + 0x60]; \ + stx %i5, [%g5 + 0x68]; \ + stx %i6, [%g5 + 0x70]; \ + stx %i7, [%g5 + 0x78]; \ + dec %g7; \ + and %g7, %g6, %g7; \ + subcc %g4, 1, %g4; \ + bne save_cpu_window_##type; \ + add %g5, 0x80, %g5; \ + \ + /* For 8 windows with 16 registers to save in the window, memory required \ + is 16*8*8 = 0x400 bytes */ \ + \ + /* Now we should be in window 0 so update the other window registers */ \ + rdpr %ver, %g6; \ + and %g6, 0xf, %g6; \ + dec %g6; \ + wrpr %g6, %cansave; \ + \ + wrpr %g0, %cleanwin; \ + wrpr %g0, %canrestore; \ + wrpr %g0, %otherwin; \ + + +#define SAVE_CPU_TRAP_STATE(type) \ + /* Save trap state into context at %g1 */ \ + add %g1, 0x490, %g5; \ + mov 4, %g6; \ + \ +save_trap_state_##type: \ + deccc %g6; \ + wrpr %g6, %tl; \ + rdpr %tpc, %g7; \ + stx %g7, [%g5]; \ + rdpr %tnpc, %g7; \ + stx %g7, [%g5 + 0x8]; \ + rdpr %tstate, %g7; \ + stx %g7, [%g5 + 0x10]; \ + rdpr %tt, %g7; \ + stx %g7, [%g5 + 0x18]; \ + bne save_trap_state_##type; \ + add %g5, 0x20, %g5; \ + \ + /* For 4 trap levels with 4 registers, memory required is \ + 4*8*4 = 0x80 bytes */ + +/* Save all state into context at %g1 */ +#define SAVE_CPU_STATE(type) \ + SAVE_CPU_WINDOW_STATE(type); \ + SAVE_CPU_TRAP_STATE(type); + + +#define RESTORE_CPU_WINDOW_STATE(type) \ + /* Restore window state from context at %g1 */ \ + \ + /* Get the number of windows in %g6 */ \ + rdpr %ver, %g6; \ + and %g6, 0xf, %g6; \ + \ + mov %g6, %g4; \ + inc %g4; \ + \ + /* Set starting window */ \ + ldx [%g1], %g7; \ + \ + /* Now iterate through all of the windows restoring all l and i registers */ \ + add %g1, 0x90, %g5; \ + \ +restore_cpu_window_##type: \ + wrpr %g7, %cwp; \ + ldx [%g5], %l0; \ + ldx [%g5 + 0x8], %l1; \ + ldx [%g5 + 0x10], %l2; \ + ldx [%g5 + 0x18], %l3; \ + ldx [%g5 + 0x20], %l4; \ + ldx [%g5 + 0x28], %l5; \ + ldx [%g5 + 0x30], %l6; \ + ldx [%g5 + 0x38], %l7; \ + ldx [%g5 + 0x40], %i0; \ + ldx [%g5 + 0x48], %i1; \ + ldx [%g5 + 0x50], %i2; \ + ldx [%g5 + 0x58], %i3; \ + ldx [%g5 + 0x60], %i4; \ + ldx [%g5 + 0x68], %i5; \ + ldx [%g5 + 0x70], %i6; \ + ldx [%g5 + 0x78], %i7; \ + dec %g7; \ + and %g7, %g6, %g7; \ + subcc %g4, 1, %g4; \ + bne restore_cpu_window_##type; \ + add %g5, 0x80, %g5; \ + \ + /* Restore the window registers to their original value */ \ + ldx [%g1], %g7; \ + wrpr %g7, %cwp; \ + ldx [%g1 + 0x8], %g7; \ + wrpr %g7, %cansave; \ + ldx [%g1 + 0x10], %g7; \ + wrpr %g7, %canrestore; \ + ldx [%g1 + 0x18], %g7; \ + wrpr %g7, %otherwin; \ + ldx [%g1 + 0x20], %g7; \ + wrpr %g7, %wstate; \ + ldx [%g1 + 0x28], %g7; \ + wrpr %g7, %cleanwin; \ + \ + ldx [%g1 + 0x30], %o0; \ + ldx [%g1 + 0x38], %o1; \ + ldx [%g1 + 0x40], %o2; \ + ldx [%g1 + 0x48], %o3; \ + ldx [%g1 + 0x50], %o4; \ + ldx [%g1 + 0x58], %o5; \ + ldx [%g1 + 0x60], %o6; \ + ldx [%g1 + 0x68], %o7; \ + \ + ldx [%g1 + 0x70], %g7; \ + wrpr %g7, %pstate; \ + ldx [%g1 + 0x78], %g7; \ + wr %g7, 0, %y; \ + ldx [%g1 + 0x80], %g7; \ + wr %g7, 0, %fprs; \ + + +#define RESTORE_CPU_TRAP_STATE(type) \ + /* Restore trap state from context at %g1 */ \ + add %g1, 0x490, %g5; \ + mov 4, %g6; \ + \ +restore_trap_state_##type: \ + deccc %g6; \ + wrpr %g6, %tl; \ + ldx [%g5], %g7; \ + wrpr %g7, %tpc; \ + ldx [%g5 + 0x8], %g7; \ + wrpr %g7, %tnpc; \ + ldx [%g5 + 0x10], %g7; \ + wrpr %g7, %tstate; \ + ldx [%g5 + 0x18], %g7; \ + wrpr %g7, %tt; \ + bne restore_trap_state_##type; \ + add %g5, 0x20, %g5; \ + \ + ldx [%g1 + 0x88], %g7; \ + wrpr %g7, %tl + +/* Restore all state from context at %g1 */ +#define RESTORE_CPU_STATE(type) \ + RESTORE_CPU_WINDOW_STATE(type); \ + RESTORE_CPU_TRAP_STATE(type); diff --git a/qemu/roms/openbios/arch/sparc64/ldscript b/qemu/roms/openbios/arch/sparc64/ldscript index 54288e825..c5cc6a5ce 100644 --- a/qemu/roms/openbios/arch/sparc64/ldscript +++ b/qemu/roms/openbios/arch/sparc64/ldscript @@ -50,6 +50,11 @@ SECTIONS *(.bss.*) *(COMMON) + _fcstack = .; + . += 32768; + . = ALIGN(16); + _efcstack = .; + _stack = .; . += STACK_SIZE; . = ALIGN(16); diff --git a/qemu/roms/openbios/arch/sparc64/lib.c b/qemu/roms/openbios/arch/sparc64/lib.c index e9101af52..4709ca8fe 100644 --- a/qemu/roms/openbios/arch/sparc64/lib.c +++ b/qemu/roms/openbios/arch/sparc64/lib.c @@ -458,10 +458,10 @@ NODE_METHODS(mmu) = { void ob_mmu_init(const char *cpuname, uint64_t ram_size) { /* memory node */ - REGISTER_NODE_METHODS(memory, "/memory"); + REGISTER_NODE(memory); /* MMU node */ - REGISTER_NODE_METHODS(mmu, "/virtual-memory"); + REGISTER_NODE(mmu); ofmem_register(find_dev("/memory"), find_dev("/virtual-memory")); diff --git a/qemu/roms/openbios/arch/sparc64/vectors.S b/qemu/roms/openbios/arch/sparc64/vectors.S index 927c1cdc7..9d86b6bd8 100644 --- a/qemu/roms/openbios/arch/sparc64/vectors.S +++ b/qemu/roms/openbios/arch/sparc64/vectors.S @@ -24,6 +24,7 @@ */ #define __ASSEMBLY__ +#include "cpustate.h" #include "pstate.h" #include <asm/asi.h> #define ASI_BP ASI_PHYS_BYPASS_EC_E @@ -276,17 +277,8 @@ tl1_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8) .section ".data" .align 8 - .globl tlb_handler_stack_top, tlb_handler_stack_pointer, obp_ticks_pointer + .globl obp_ticks_pointer - ! Stack for the tlb MMU trap handlers -tlb_handler_stack_bottom: - .skip 8192 -tlb_handler_stack_top: - .skip 8 - - ! MMU trap handler stack pointer -tlb_handler_stack_pointer: - .xword tlb_handler_stack_top ! Pointer to current tick value obp_ticks_pointer: @@ -336,234 +328,30 @@ fill_32bit: restored retry -/* - * SAVE_CPU_STATE and RESTORE_CPU_STATE are macros used to enable a context switch - * to C to occur within the MMU I/D TLB miss handlers. - * - * Because these handlers are called on a TLB miss, we cannot use flushw to store - * processor window state on the stack, as the memory areas used by each window's - * stack pointer may not be in the TLB, causing recursive TLB miss traps. - * - * For this reason, we save window state by manually rotating the window registers - * and saving their contents (along with other vital registers) into a special - * tlb_handler_stack defined above which is guaranteed to be locked in the TLB, and - * so won't cause issues with trap recursion. - * - * Once this process is complete, we remain in a TL=0, CWP=0 state (with IE=1 to allow - * window fill/spill traps if required), switch to our safe tlb_handler_stack and - * invoke the miss handler. - */ - -#define SAVE_CPU_STATE(type) \ - /* Set up our exception stack pointer in %g1 */ \ - setx tlb_handler_stack_pointer, %g7, %g6; \ - ldx [%g6], %g1; \ - add %g1, -0x510, %g1; \ - \ - /* First save the various state registers */ \ - rdpr %cwp, %g7; \ - stx %g7, [%g1]; \ - rdpr %cansave, %g7; \ - stx %g7, [%g1 + 0x8]; \ - rdpr %canrestore, %g7; \ - stx %g7, [%g1 + 0x10]; \ - rdpr %otherwin, %g7; \ - stx %g7, [%g1 + 0x18]; \ - rdpr %wstate, %g7; \ - stx %g7, [%g1 + 0x20]; \ - rdpr %cleanwin, %g7; \ - stx %g7, [%g1 + 0x28]; \ - rdpr %pstate, %g7; \ - stx %g7, [%g1 + 0x30]; \ - \ - rd %y, %g7; \ - stx %g7, [%g1 + 0x38]; \ - rd %fprs, %g7; \ - stx %g7, [%g1 + 0x40]; \ - \ - rdpr %tl, %g7; \ - stx %g7, [%g1 + 0x48]; \ - \ - /* Trap state */ \ - add %g1, 0x50, %g5; \ - mov 4, %g6; \ - \ -save_trap_state_##type: \ - deccc %g6; \ - wrpr %g6, %tl; \ - rdpr %tpc, %g7; \ - stx %g7, [%g5]; \ - rdpr %tnpc, %g7; \ - stx %g7, [%g5 + 0x8]; \ - rdpr %tstate, %g7; \ - stx %g7, [%g5 + 0x10]; \ - rdpr %tt, %g7; \ - stx %g7, [%g5 + 0x18]; \ - bne save_trap_state_##type; \ - add %g5, 0x20, %g5; \ - \ - /* For 4 trap levels with 4 registers, memory required is - 4*8*4 = 0x80 bytes */ \ - \ - /* Save the o registers */ \ - stx %o0, [%g1 + 0xd0]; \ - stx %o1, [%g1 + 0xd8]; \ - stx %o2, [%g1 + 0xe0]; \ - stx %o3, [%g1 + 0xe8]; \ - stx %o4, [%g1 + 0xf0]; \ - stx %o5, [%g1 + 0xf8]; \ - stx %o6, [%g1 + 0x100]; \ - stx %o7, [%g1 + 0x108]; \ - \ - /* Now iterate through all of the windows saving all l and i registers */ \ - add %g1, 0x110, %g5; \ - \ - /* Get the number of windows in %g6 */ \ - rdpr %ver, %g6; \ - and %g6, 0xf, %g6; \ - inc %g6; \ - \ -save_cpu_window_##type: \ - deccc %g6; \ - wrpr %g6, %cwp; \ - stx %l0, [%g5]; \ - stx %l1, [%g5 + 0x8]; \ - stx %l2, [%g5 + 0x10]; \ - stx %l3, [%g5 + 0x18]; \ - stx %l4, [%g5 + 0x20]; \ - stx %l5, [%g5 + 0x28]; \ - stx %l6, [%g5 + 0x30]; \ - stx %l7, [%g5 + 0x38]; \ - stx %i0, [%g5 + 0x40]; \ - stx %i1, [%g5 + 0x48]; \ - stx %i2, [%g5 + 0x50]; \ - stx %i3, [%g5 + 0x58]; \ - stx %i4, [%g5 + 0x60]; \ - stx %i5, [%g5 + 0x68]; \ - stx %i6, [%g5 + 0x70]; \ - stx %i7, [%g5 + 0x78]; \ - bne save_cpu_window_##type; \ - add %g5, 0x80, %g5; \ - \ - /* For 8 windows with 16 registers to save in the window, memory required - is 16*8*8 = 0x400 bytes */ \ - \ - /* Now we should be in window 0 so update the other window registers */ \ - rdpr %ver, %g6; \ - and %g6, 0xf, %g6; \ - dec %g6; \ - wrpr %g6, %cansave; \ - \ - wrpr %g0, %cleanwin; \ - wrpr %g0, %canrestore; \ - wrpr %g0, %otherwin; \ - \ - /* Update our exception stack pointer */ \ - setx tlb_handler_stack_pointer, %g7, %g6; \ - stx %g1, [%g6]; - - -#define RESTORE_CPU_STATE(type) \ - /* Set up our exception stack pointer in %g1 */ \ - setx tlb_handler_stack_pointer, %g7, %g6; \ - ldx [%g6], %g1; \ - \ - /* Get the number of windows in %g6 */ \ - rdpr %ver, %g6; \ - and %g6, 0xf, %g6; \ - inc %g6; \ - \ - /* Now iterate through all of the windows restoring all l and i registers */ \ - add %g1, 0x110, %g5; \ - \ -restore_cpu_window_##type: \ - deccc %g6; \ - wrpr %g6, %cwp; \ - ldx [%g5], %l0; \ - ldx [%g5 + 0x8], %l1; \ - ldx [%g5 + 0x10], %l2; \ - ldx [%g5 + 0x18], %l3; \ - ldx [%g5 + 0x20], %l4; \ - ldx [%g5 + 0x28], %l5; \ - ldx [%g5 + 0x30], %l6; \ - ldx [%g5 + 0x38], %l7; \ - ldx [%g5 + 0x40], %i0; \ - ldx [%g5 + 0x48], %i1; \ - ldx [%g5 + 0x50], %i2; \ - ldx [%g5 + 0x58], %i3; \ - ldx [%g5 + 0x60], %i4; \ - ldx [%g5 + 0x68], %i5; \ - ldx [%g5 + 0x70], %i6; \ - ldx [%g5 + 0x78], %i7; \ - bne restore_cpu_window_##type; \ - add %g5, 0x80, %g5; \ - \ - /* Restore the window registers to their original value */ \ - ldx [%g1], %g7; \ - wrpr %g7, %cwp; \ - ldx [%g1 + 0x8], %g7; \ - wrpr %g7, %cansave; \ - ldx [%g1 + 0x10], %g7; \ - wrpr %g7, %canrestore; \ - ldx [%g1 + 0x18], %g7; \ - wrpr %g7, %otherwin; \ - ldx [%g1 + 0x20], %g7; \ - wrpr %g7, %wstate; \ - ldx [%g1 + 0x28], %g7; \ - wrpr %g7, %cleanwin; \ - ldx [%g1 + 0x30], %g7; \ - wrpr %g7, %pstate; \ - \ - /* Restore the o registers */ \ - ldx [%g1 + 0xd0], %o0; \ - ldx [%g1 + 0xd8], %o1; \ - ldx [%g1 + 0xe0], %o2; \ - ldx [%g1 + 0xe8], %o3; \ - ldx [%g1 + 0xf0], %o4; \ - ldx [%g1 + 0xf8], %o5; \ - ldx [%g1 + 0x100], %o6; \ - ldx [%g1 + 0x108], %o7; \ - \ - /* Restore the trap state */ \ - add %g1, 0x50, %g5; \ - mov 4, %g6; \ - \ -restore_trap_state_##type: \ - deccc %g6; \ - wrpr %g6, %tl; \ - ldx [%g5], %g7; \ - wrpr %g7, %tpc; \ - ldx [%g5 + 0x8], %g7; \ - wrpr %g7, %tnpc; \ - ldx [%g5 + 0x10], %g7; \ - wrpr %g7, %tstate; \ - ldx [%g5 + 0x18], %g7; \ - wrpr %g7, %tt; \ - bne restore_trap_state_##type; \ - add %g5, 0x20, %g5; \ - \ - ldx [%g1 + 0x38], %g7; \ - wr %g7, 0, %y; \ - ldx [%g1 + 0x40], %g7; \ - wr %g7, 0, %fprs; \ - ldx [%g1 + 0x48], %g7; \ - wrpr %g7, %tl; \ - \ - /* Restore exception stack pointer to previous value */ \ - setx tlb_handler_stack_pointer, %g7, %g6; \ - add %g1, 0x510, %g1; \ - stx %g1, [%g6]; - .globl reload_DMMU_tlb, reload_IMMU_tlb, bug reload_DMMU_tlb: - + + /* Save CPU state to stack */ + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + add %g1, -CONTEXT_STATE_SIZE, %g1 + stx %g1, [%g7] + SAVE_CPU_STATE(dtlb) - /* Switch to TLB locked stack space (note we add an additional 192 bytes required for + /* Switch to 8K TLB locked OpenBIOS stack (note we add an additional 192 bytes required for gcc to save its arguments when building with -O0) */ - add %g1, -STACK_BIAS - 192, %sp + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g6 + setx CONTEXT_STACK_SIZE, %g4, %g5 + sub %g6, %g5, %g6 + stx %g6, [%g7] + + setx - 2047 - 192, %g6, %g7 + add %g1, %g7, %g7 + mov %g7, %sp /* Enable interrupts for window spill/fill traps */ rdpr %pstate, %g7 @@ -577,18 +365,44 @@ reload_DMMU_tlb: rdpr %pstate, %g7 andn %g7, PSTATE_IE, %g7 wrpr %g7, %pstate - + + /* Restore CPU state from stack */ + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + setx CONTEXT_STACK_SIZE, %g4, %g5 + add %g1, %g5, %g1 + stx %g1, [%g7] + RESTORE_CPU_STATE(dtlb) - + + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + add %g1, CONTEXT_STATE_SIZE, %g1 + stx %g1, [%g7] + retry reload_IMMU_tlb: - + + /* Save CPU state to stack */ + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + add %g1, -CONTEXT_STATE_SIZE, %g1 + stx %g1, [%g7] + SAVE_CPU_STATE(itlb) - /* Switch to TLB locked stack space (note we add an additional 192 bytes required for + /* Switch to 8K TLB locked OpenBIOS stack (note we add an additional 192 bytes required for gcc to save its arguments when building with -O0) */ - add %g1, -STACK_BIAS - 192, %sp + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g6 + setx CONTEXT_STACK_SIZE, %g4, %g5 + sub %g6, %g5, %g6 + stx %g6, [%g7] + + setx - 2047 - 192, %g6, %g7 + add %g1, %g7, %g7 + mov %g7, %sp /* Enable interrupts for window spill/fill traps */ rdpr %pstate, %g7 @@ -602,8 +416,20 @@ reload_IMMU_tlb: rdpr %pstate, %g7 andn %g7, PSTATE_IE, %g7 wrpr %g7, %pstate - + + /* Restore CPU state from stack */ + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + setx CONTEXT_STACK_SIZE, %g4, %g5 + add %g1, %g5, %g1 + stx %g1, [%g7] + RESTORE_CPU_STATE(itlb) + + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + add %g1, CONTEXT_STATE_SIZE, %g1 + stx %g1, [%g7] retry diff --git a/qemu/roms/openbios/config/scripts/switch-arch b/qemu/roms/openbios/config/scripts/switch-arch index d5e2f7710..ab3b4ce69 100755 --- a/qemu/roms/openbios/config/scripts/switch-arch +++ b/qemu/roms/openbios/config/scripts/switch-arch @@ -17,48 +17,57 @@ if [ x"$1" = x -o "$1" = "-help" ]; then exit 0 fi -crosscflags() +is_bigendian() { - host=$1 - target=$2 - - if test "$host" = "powerpc" -o "$host" = "ppc" \ - -o "$host" = "mips" -o "$host" = "s390" \ - -o "$host" = "sparc32" -o "$host" = "sparc64" \ - -o "$host" = "m68k" -o "$host" = "armv4b"; then - hostbigendian="yes" + cpu=$1 + + if test "$cpu" = "powerpc" -o "$cpu" = "ppc" \ + -o "$cpu" = "powerpc64" -o "$cpu" = "ppc64" \ + -o "$cpu" = "mips" -o "$cpu" = "s390" \ + -o "$cpu" = "sparc32" -o "$cpu" = "sparc64" \ + -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then + echo yes else - hostbigendian="no" + echo no fi +} -# host long bits test - if test "$host" = "sparc64" -o "$host" = "ia64" \ - -o "$host" = "amd64" -o "$host" = "x86_64" \ - -o "$host" = "alpha"; then - hostlongbits="64" +longbits() +{ + cpu=$1 + if test "$cpu" = "sparc64" -o "$cpu" = "ia64" \ + -o "$cpu" = "amd64" -o "$cpu" = "x86_64" \ + -o "$cpu" = "powerpc64" -o "$cpu" = "ppc64" \ + -o "$cpu" = "alpha"; then + echo 64 else - hostlongbits="32" + echo 32 fi +} - if test "$target" = "powerpc" -o "$target" = "ppc" \ - -o "$target" = "powerpc64" -o "$target" = "ppc64" \ - -o "$target" = "mips" -o "$target" = "s390" \ - -o "$target" = "sparc32" -o "$target" = "sparc64" \ - -o "$target" = "m68k" -o "$target" = "armv4b"; then - targetbigendian="yes" - else - targetbigendian="no" - fi +basearch() +{ + arch=$1 + case $arch in + powerpc|ppc64|powerpc64) + echo ppc + ;; + *) + echo $arch + ;; + esac +} -# target long bits test - if test "$target" = "sparc64" -o "$target" = "ia64" \ - -o "$target" = "amd64" -o "$target" = "x86_64" \ - -o "$target" = "powerpc64" -o "$target" = "ppc64" \ - -o "$target" = "alpha"; then - targetlongbits="64" - else - targetlongbits="32" - fi +crosscflags() +{ + host=$1 + target=$2 + + hostbigendian=$(is_bigendian $host) + hostlongbits=$(longbits $host) + + targetbigendian=$(is_bigendian $target) + targetlongbits=$(longbits $target) if test "$targetbigendian" = "$hostbigendian"; then cflags="-USWAP_ENDIANNESS" @@ -99,23 +108,27 @@ archname() select_prefix() { - TARGETS="${1}-unknown-linux-gnu- ${1}-linux-gnu- ${1}-linux- ${1}-elf- ${1}-eabi-" + BASEARCH=$(basearch $ARCH) + for target_arch ; do + TARGETS="${target_arch}-unknown-linux-gnu- ${target_arch}-linux-gnu- ${target_arch}-linux- ${target_arch}-elf- ${target_arch}-eabi-" - if [ x"$CROSS_COMPILE" != "x" ]; then - TARGETS=$CROSS_COMPILE - fi + if [ x"$CROSS_COMPILE" != "x" ]; then + TARGETS=$CROSS_COMPILE + fi - for TARGET in $TARGETS - do - if type ${TARGET}gcc > /dev/null 2>&1 - then + for TARGET in $TARGETS + do + if type ${TARGET}gcc > /dev/null 2>&1 + then + return + fi + done + if [ "$BASEARCH" = "$(basearch $HOSTARCH)" ]; then + TARGET="" return fi done - if [ "$ARCH" = "$HOSTARCH" ]; then - return - fi - echo "ERROR: no ${1} cross-compiler found !" 1>&2 + echo "ERROR: no $* cross-compiler found !" 1>&2 exit 1 } @@ -242,7 +255,6 @@ for ARCH in $arch_list; do esac done - BASEARCH=$ARCH case $ARCH in amd64) select_prefix x86_64 @@ -251,9 +263,10 @@ for ARCH in $arch_list; do ;; ppc) - select_prefix powerpc + select_prefix powerpc powerpc64 if [ "$unix" = "no" ]; then - CFLAGS="-m32 -msoft-float -fno-builtin-bcopy -fno-builtin-log2" + # 604 cpu includes support for PReP as well as Mac + CFLAGS="-m32 -mcpu=604 -msoft-float -fno-builtin-bcopy -fno-builtin-log2" AS_FLAGS="-m32" else CFLAGS="-fno-builtin" @@ -263,13 +276,14 @@ for ARCH in $arch_list; do ppc64) select_prefix powerpc64 - CFLAGS="-Wa,-a64 -m64 -msoft-float -fno-builtin" + + # 970 cpu is used in all 64-bit Macs but disable altivec + CFLAGS="-mcpu=970 -mno-altivec -Wa,-a64 -m64 -msoft-float -fno-builtin" AS_FLAGS="-Wa,-a64" - BASEARCH=ppc ;; sparc32) - select_prefix sparc + select_prefix sparc sparc64 CFLAGS="-Wa,-xarch=v8 -Wa,-32 -m32 -mcpu=supersparc -fno-builtin" AS_FLAGS="-Wa,-xarch=v8 -Wa,-32" ;; diff --git a/qemu/roms/openbios/drivers/cuda.c b/qemu/roms/openbios/drivers/cuda.c index 9555dea49..ff5d22de2 100644 --- a/qemu/roms/openbios/drivers/cuda.c +++ b/qemu/roms/openbios/drivers/cuda.c @@ -144,8 +144,22 @@ static int cuda_adb_req (void *host, const uint8_t *snd_buf, int len, // CUDA_DPRINTF("len: %d %02x\n", len, snd_buf[0]); len = cuda_request(host, ADB_PACKET, snd_buf, len, buffer); if (len > 1 && buffer[0] == ADB_PACKET) { - pos = buffer + 2; - len -= 2; + /* We handle 2 types of ADB packet here: + Normal: <type> <status> <data> ... + Error : <type> <status> <cmd> (<data> ...) + Ideally we should use buffer[1] (status) to determine whether this + is a normal or error packet but this requires a corresponding fix + in QEMU <= 2.4. Hence we temporarily handle it this way to ease + the transition. */ + if (len > 2 && buffer[2] == snd_buf[0]) { + /* Error */ + pos = buffer + 3; + len -= 3; + } else { + /* Normal */ + pos = buffer + 2; + len -= 2; + } } else { pos = buffer + 1; len = -1; @@ -380,7 +394,8 @@ powermgt_init(char *path) ph = find_dev(buf); set_property(ph, "device_type", "power-mgt", 10); - set_property(ph, "compatible", "power-mgt", 10); + set_property(ph, "mgt-kind", "min-consumption-pwm-led", strlen("min-consumption-pwm-led") + 1); + set_property(ph, "compatible", "cuda", strlen("cuda") + 1); } cuda_t *cuda_init (const char *path, phys_addr_t base) diff --git a/qemu/roms/openbios/drivers/escc.c b/qemu/roms/openbios/drivers/escc.c index 240043be3..1990e798d 100644 --- a/qemu/roms/openbios/drivers/escc.c +++ b/qemu/roms/openbios/drivers/escc.c @@ -380,12 +380,44 @@ ob_zs_init(phys_addr_t base, uint64_t offset, int intr, int slave, int keyboard) static void escc_add_channel(const char *path, const char *node, phys_addr_t addr, - uint32_t offset) + int esnum) { char buf[64], tty[32]; phandle_t dnode, aliases; - int len; - cell props[2]; + + cell props[10]; + ucell offset; + int index; + int legacy; + + int dbdma_offsets[2][2] = { + /* ch-b */ + { 0x6, 0x7 }, + /* ch-a */ + { 0x4, 0x5 } + }; + + int reg_offsets[2][2][3] = { + { + /* ch-b */ + { 0x00, 0x10, 0x40 }, + /* ch-a */ + { 0x20, 0x30, 0x50 } + },{ + /* legacy ch-b */ + { 0x0, 0x2, 0x8 }, + /* legacy ch-a */ + { 0x4, 0x6, 0xa } + } + }; + + switch (esnum) { + case 2: index = 1; legacy = 0; break; + case 3: index = 0; legacy = 0; break; + case 4: index = 1; legacy = 1; break; + case 5: index = 0; legacy = 1; break; + default: return; + } /* add device */ @@ -411,31 +443,49 @@ escc_add_channel(const char *path, const char *node, phys_addr_t addr, set_property(dnode, "device_type", "serial", strlen("serial") + 1); - snprintf(buf, sizeof(buf), "ch-%s", node); - len = strlen(buf) + 1; - snprintf(buf + len, sizeof(buf) - len, "CHRP,es2"); - set_property(dnode, "compatible", buf, len + 9); + snprintf(buf, sizeof(buf), "chrp,es%d", esnum); + set_property(dnode, "compatible", buf, 9); - props[0] = IO_ESCC_OFFSET + offset * 0x20; - props[1] = 0x00000020; - set_property(dnode, "reg", (char *)&props, 2 * sizeof(cell)); + if (legacy) { + offset = IO_ESCC_LEGACY_OFFSET; + } else { + offset = IO_ESCC_OFFSET; + } - props[0] = addr + IO_ESCC_OFFSET + offset * 0x20; + props[0] = offset + reg_offsets[legacy][index][0]; + props[1] = 0x1; + props[2] = offset + reg_offsets[legacy][index][1]; + props[3] = 0x1; + props[4] = offset + reg_offsets[legacy][index][2]; + props[5] = 0x1; + props[6] = 0x8000 + dbdma_offsets[index][0] * 0x100; + props[7] = 0x100; + props[8] = 0x8000 + dbdma_offsets[index][1] * 0x100; + props[9] = 0x100; + set_property(dnode, "reg", (char *)&props, 10 * sizeof(cell)); + + props[0] = addr + offset + reg_offsets[legacy][index][0]; OLDWORLD(set_property(dnode, "AAPL,address", (char *)&props, 1 * sizeof(cell))); - props[0] = 0x00000010 - offset; + props[0] = 0x10 - index; OLDWORLD(set_property(dnode, "AAPL,interrupts", (char *)&props, 1 * sizeof(cell))); - props[0] = (0x24) + offset; - props[1] = 0; + props[0] = (0x24) + index; + props[1] = 0x1; + props[2] = dbdma_offsets[index][0]; + props[3] = 0x0; + props[4] = dbdma_offsets[index][1]; + props[5] = 0x0; NEWWORLD(set_property(dnode, "interrupts", - (char *)&props, 2 * sizeof(cell))); + (char *)&props, 6 * sizeof(cell))); + + set_int_property(dnode, "slot-names", 0); device_end(); - uart_init_line((unsigned char*)addr + IO_ESCC_OFFSET + offset * 0x20, + uart_init_line((unsigned char*)addr + offset + reg_offsets[legacy][index][0], CONFIG_SERIAL_SPEED); } @@ -464,13 +514,39 @@ escc_init(const char *path, phys_addr_t addr) set_property(dnode, "device_type", "escc", strlen("escc") + 1); set_property(dnode, "compatible", "escc\0CHRP,es0", 14); + set_property(dnode, "ranges", "", 0); fword("finish-device"); - escc_add_channel(buf, "a", addr, 1); - escc_add_channel(buf, "b", addr, 0); + escc_add_channel(buf, "a", addr, 2); + escc_add_channel(buf, "b", addr, 3); escc_serial_dev = (unsigned char *)addr + IO_ESCC_OFFSET + (CONFIG_SERIAL_PORT ? 0 : 0x20); + + push_str(path); + fword("find-device"); + fword("new-device"); + + push_str("escc-legacy"); + fword("device-name"); + + snprintf(buf, sizeof(buf), "%s/escc-legacy", path); + + dnode = find_dev(buf); + + set_int_property(dnode, "#address-cells", 1); + props[0] = __cpu_to_be32(IO_ESCC_LEGACY_OFFSET); + props[1] = __cpu_to_be32(IO_ESCC_LEGACY_SIZE); + set_property(dnode, "reg", (char *)&props, sizeof(props)); + set_property(dnode, "device_type", "escc-legacy", + strlen("escc-legacy") + 1); + set_property(dnode, "compatible", "chrp,es1", 9); + set_property(dnode, "ranges", "", 0); + + fword("finish-device"); + + escc_add_channel(buf, "a", addr, 4); + escc_add_channel(buf, "b", addr, 5); } #endif diff --git a/qemu/roms/openbios/drivers/escc.h b/qemu/roms/openbios/drivers/escc.h index caaf00d40..e73f267b2 100644 --- a/qemu/roms/openbios/drivers/escc.h +++ b/qemu/roms/openbios/drivers/escc.h @@ -1,6 +1,8 @@ #define IO_ESCC_SIZE 0x00001000 #define IO_ESCC_OFFSET 0x00013000 +#define IO_ESCC_LEGACY_SIZE 0x00001000 +#define IO_ESCC_LEGACY_OFFSET 0x00012000 #define ZS_REGS 8 diff --git a/qemu/roms/openbios/drivers/ide.c b/qemu/roms/openbios/drivers/ide.c index 327c64a40..1da60c895 100644 --- a/qemu/roms/openbios/drivers/ide.c +++ b/qemu/roms/openbios/drivers/ide.c @@ -73,13 +73,13 @@ static inline void ide_add_channel(struct ide_channel *chan) channels = chan; } -static struct ide_channel *ide_seek_channel(const char *name) +static struct ide_channel *ide_seek_channel(phandle_t ph) { struct ide_channel *current; current = channels; while (current) { - if (!strcmp(current->name, name)) + if (current->ph == ph) return current; current = current->next; } @@ -1247,11 +1247,10 @@ ob_ide_initialize(int *idx) static void ob_ide_open(int *idx) { - int ret=1, len; + int ret=1; phandle_t ph; struct ide_drive *drive; struct ide_channel *chan; - char *idename; int unit; fword("my-unit"); @@ -1260,9 +1259,8 @@ ob_ide_open(int *idx) fword("my-parent"); fword("ihandle>phandle"); ph=(phandle_t)POP(); - idename=get_property(ph, "name", &len); - chan = ide_seek_channel(idename); + chan = ide_seek_channel(ph); drive = &chan->drives[unit]; *(struct ide_drive **)idx = drive; @@ -1380,9 +1378,6 @@ int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0, chan = malloc(sizeof(struct ide_channel)); - snprintf(chan->name, sizeof(chan->name), - DEV_NAME, current_channel); - chan->mmio = 0; for (j = 0; j < 8; j++) @@ -1424,9 +1419,9 @@ int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0, snprintf(nodebuff, sizeof(nodebuff), "%s/" DEV_NAME, path, current_channel); - REGISTER_NAMED_NODE(ob_ide_ctrl, nodebuff); + REGISTER_NAMED_NODE_PHANDLE(ob_ide_ctrl, nodebuff, dnode); - dnode = find_dev(nodebuff); + chan->ph = dnode; #if !defined(CONFIG_PPC) && !defined(CONFIG_SPARC64) props[0]=14; props[1]=0; @@ -1468,11 +1463,9 @@ int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0, break; } IDE_DPRINTF("%s]: %s\n", media, drive->model); - snprintf(nodebuff, sizeof(nodebuff), - "%s/" DEV_NAME "/%s", path, current_channel, - media); - REGISTER_NAMED_NODE(ob_ide, nodebuff); - dnode=find_dev(nodebuff); + snprintf(nodebuff, sizeof(nodebuff), "%s/%s", + get_path_from_ph(dnode), media); + REGISTER_NAMED_NODE_PHANDLE(ob_ide, nodebuff, dnode); set_int_property(dnode, "reg", j); /* create aliases */ @@ -1488,6 +1481,28 @@ int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0, return 0; } +void ob_ide_quiesce(void) +{ + struct ide_channel *channel; + int i; + + channel = channels; + while (channel) { + for (i = 0; i < 2; i++) { + struct ide_drive *drive = &channel->drives[i]; + + if (!drive->present) + continue; + + ob_ide_select_drive(drive); + ob_ide_software_reset(drive); + ob_ide_device_type_check(drive); + } + + channel = channel->next; + } +} + #if defined(CONFIG_DRIVER_MACIO) static unsigned char macio_ide_inb(struct ide_channel *chan, unsigned int port) @@ -1527,16 +1542,13 @@ int macio_ide_init(const char *path, uint32_t addr, int nb_channels) struct ide_channel *chan; /* IDE ports on Macs are numbered from 3. - * Also see comments in macio.c:openpic_init() */ + * Also see comments in pci.c:ob_pci_host_set_interrupt_map() */ current_channel = 3; - for (i = 0; i < nb_channels; i++, current_channel++) { + for (i = 0; i < nb_channels; i++) { chan = malloc(sizeof(struct ide_channel)); - snprintf(chan->name, sizeof(chan->name), - DEV_NAME, current_channel); - chan->mmio = addr + MACIO_IDE_OFFSET + i * MACIO_IDE_SIZE; chan->obide_inb = macio_ide_inb; @@ -1574,13 +1586,19 @@ int macio_ide_init(const char *path, uint32_t addr, int nb_channels) snprintf(nodebuff, sizeof(nodebuff), "%s/" DEV_NAME, path, current_channel); - REGISTER_NAMED_NODE(ob_ide_ctrl, nodebuff); + REGISTER_NAMED_NODE_PHANDLE(ob_ide_ctrl, nodebuff, dnode); - dnode = find_dev(nodebuff); + chan->ph = dnode; set_property(dnode, "compatible", (is_oldworld() ? "heathrow-ata" : "keylargo-ata"), 13); + set_property(dnode, "model", ((current_channel == 3) ? + "ata-3" : "ata-4"), strlen("ata-*") + 1); + + set_property(dnode, "AAPL,connector", "ata", + strlen("ata") + 1); + props[0] = 0x00000526; props[1] = 0x00000085; props[2] = 0x00000025; @@ -1589,8 +1607,8 @@ int macio_ide_init(const char *path, uint32_t addr, int nb_channels) props[5] = 0x00000000; props[6] = 0x00000000; props[7] = 0x00000000; - OLDWORLD(set_property(dnode, "AAPL,pio-timing", - (char *)&props, 8*sizeof(props[0]))); + set_property(dnode, "AAPL,pio-timing", + (char *)&props, 8*sizeof(props[0])); /* The first interrupt entry is the ide interrupt, the second the dbdma interrupt */ @@ -1633,9 +1651,9 @@ int macio_ide_init(const char *path, uint32_t addr, int nb_channels) OLDWORLD(set_property(dnode, "AAPL,address", (char *)&props, 2*sizeof(props[0]))); - props[0] = 0; - OLDWORLD(set_property(dnode, "AAPL,bus-id", (char*)props, - 1 * sizeof(props[0]))); + props[0] = i; + set_property(dnode, "AAPL,bus-id", (char*)props, + 1 * sizeof(props[0])); IDE_DPRINTF(DEV_NAME": [io ports 0x%lx]\n", current_channel, chan->mmio); @@ -1663,11 +1681,9 @@ int macio_ide_init(const char *path, uint32_t addr, int nb_channels) break; } IDE_DPRINTF("%s]: %s\n", media, drive->model); - snprintf(nodebuff, sizeof(nodebuff), - "%s/" DEV_NAME "/%s", path, current_channel, - media); - REGISTER_NAMED_NODE(ob_ide, nodebuff); - dnode = find_dev(nodebuff); + snprintf(nodebuff, sizeof(nodebuff), "%s/%s", + get_path_from_ph(dnode), media); + REGISTER_NAMED_NODE_PHANDLE(ob_ide, nodebuff, dnode); set_int_property(dnode, "reg", j); /* create aliases */ diff --git a/qemu/roms/openbios/drivers/ide.h b/qemu/roms/openbios/drivers/ide.h index d6c4b9f5d..8983c8ecf 100644 --- a/qemu/roms/openbios/drivers/ide.h +++ b/qemu/roms/openbios/drivers/ide.h @@ -167,7 +167,7 @@ struct ide_drive { struct ide_channel { - char name[32]; + phandle_t ph; struct ide_channel *next; /* diff --git a/qemu/roms/openbios/drivers/obio.c b/qemu/roms/openbios/drivers/obio.c index 7c135a362..4ac063188 100644 --- a/qemu/roms/openbios/drivers/obio.c +++ b/qemu/roms/openbios/drivers/obio.c @@ -26,8 +26,6 @@ #define PROMDEV_SCREEN 0 /* output to screen */ #define PROMDEV_TTYA 1 /* in/out to ttya */ -/* DECLARE data structures for the nodes. */ -DECLARE_UNNAMED_NODE( ob_obio, INSTALL_OPEN, sizeof(int) ); void ob_new_obio_device(const char *name, const char *type) @@ -397,45 +395,6 @@ ob_smp_init(unsigned long mem_size) } static void -ob_obio_open(__attribute__((unused))int *idx) -{ - int ret=1; - RET ( -ret ); -} - -static void -ob_obio_close(__attribute__((unused))int *idx) -{ - selfword("close-deblocker"); -} - -static void -ob_obio_initialize(__attribute__((unused))int *idx) -{ - push_str("/"); - fword("find-device"); - fword("new-device"); - - push_str("obio"); - fword("device-name"); - - push_str("hierarchical"); - fword("device-type"); - - PUSH(2); - fword("encode-int"); - push_str("#address-cells"); - fword("property"); - - PUSH(1); - fword("encode-int"); - push_str("#size-cells"); - fword("property"); - - fword("finish-device"); -} - -static void ob_set_obio_ranges(uint64_t base) { push_str("/obio"); @@ -458,27 +417,6 @@ ob_set_obio_ranges(uint64_t base) fword("property"); } -static void -ob_obio_decodeunit(__attribute__((unused)) int *idx) -{ - fword("decode-unit-sbus"); -} - - -static void -ob_obio_encodeunit(__attribute__((unused)) int *idx) -{ - fword("encode-unit-sbus"); -} - -NODE_METHODS(ob_obio) = { - { NULL, ob_obio_initialize }, - { "open", ob_obio_open }, - { "close", ob_obio_close }, - { "encode-unit", ob_obio_encodeunit }, - { "decode-unit", ob_obio_decodeunit }, -}; - int ob_obio_init(uint64_t slavio_base, unsigned long fd_offset, @@ -491,10 +429,6 @@ ob_obio_init(uint64_t slavio_base, unsigned long fd_offset, // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt //printk("Initializing OBIO devices...\n"); -#if 0 // XXX - REGISTER_NAMED_NODE(ob_obio, "/obio"); - device_end(); -#endif ob_set_obio_ranges(slavio_base); // Zilog Z8530 serial ports, see http://www.zilog.com diff --git a/qemu/roms/openbios/drivers/pci.c b/qemu/roms/openbios/drivers/pci.c index 366f4a17f..5062f302f 100644 --- a/qemu/roms/openbios/drivers/pci.c +++ b/qemu/roms/openbios/drivers/pci.c @@ -144,9 +144,16 @@ static void dump_reg_property(const char* description, int nreg, u32 *reg) } #endif -static unsigned long pci_bus_addr_to_host_addr(uint32_t ba) +static unsigned long pci_bus_addr_to_host_addr(int space, uint32_t ba) { - return arch->host_pci_base + (unsigned long)ba; + if (space == IO_SPACE) { + return arch->io_base + (unsigned long)ba; + } else if (space == MEMORY_SPACE_32) { + return arch->host_pci_base + (unsigned long)ba; + } else { + /* Return unaltered to aid debugging property values */ + return (unsigned long)ba; + } } static void @@ -340,22 +347,27 @@ ob_pci_encode_unit(int *idx) ss, dev, fn, buf); } -/* ( pci-addr.lo pci-addr.hi size -- virt ) */ +/* ( pci-addr.lo pci-addr.mid pci-addr.hi size -- virt ) */ static void ob_pci_map_in(int *idx) { phys_addr_t phys; uint32_t ba; - ucell size, virt; + ucell size, virt, tmp; + int space; PCI_DPRINTF("ob_pci_bar_map_in idx=%p\n", idx); size = POP(); + tmp = POP(); POP(); ba = POP(); - phys = pci_bus_addr_to_host_addr(ba); + /* Get the space from the pci-addr.hi */ + space = ((tmp & PCI_RANGE_TYPE_MASK) >> 24); + + phys = pci_bus_addr_to_host_addr(space, ba); #if defined(CONFIG_OFMEM) ofmem_claim_phys(phys, size, 0); @@ -448,13 +460,18 @@ static void pci_host_set_ranges(const pci_config_t *config) int ncells; ncells = 0; - /* first encode PCI configuration space */ - { - ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE, + +#ifdef CONFIG_SPARC64 + /* While configuration space isn't mentioned in the IEEE-1275 PCI + bindings, it appears in the PCI host bridge ranges property in + real device trees. Hence we disable this range for all host + bridges except for SPARC, particularly as it causes Darwin/OS X + to incorrectly calculated PCI memory space ranges on PPC. */ + ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE, config->dev, 0, 0); ncells += host_encode_phys_addr(props + ncells, arch->cfg_addr); ncells += pci_encode_size(props + ncells, arch->cfg_len); - } +#endif if (arch->io_base) { ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE, @@ -585,13 +602,18 @@ static void pci_set_AAPL_address(const pci_config_t *config) { phandle_t dev = get_cur_dev(); cell props[7]; - int ncells, i; + uint32_t mask; + int ncells, i, flags, space_code; ncells = 0; for (i = 0; i < 6; i++) { if (!config->assigned[i] || !config->sizes[i]) continue; - props[ncells++] = config->assigned[i] & ~0x0000000F; + pci_decode_pci_addr(config->assigned[i], + &flags, &space_code, &mask); + + props[ncells++] = pci_bus_addr_to_host_addr(space_code, + config->assigned[i] & ~mask); } if (ncells) set_property(dev, "AAPL,address", (char *)props, @@ -752,13 +774,19 @@ int macio_keylargo_config_cb (const pci_config_t *config) int vga_config_cb (const pci_config_t *config) { unsigned long rom; - uint32_t rom_size, size; + uint32_t rom_size, size, mask; + int flags, space_code; phandle_t ph; if (config->assigned[0] != 0x00000000) { setup_video(); - rom = pci_bus_addr_to_host_addr(config->assigned[1] & ~0x0000000F); + pci_decode_pci_addr(config->assigned[1], + &flags, &space_code, &mask); + + rom = pci_bus_addr_to_host_addr(space_code, + config->assigned[1] & ~0x0000000F); + rom_size = config->sizes[1]; ph = get_cur_dev(); @@ -824,7 +852,7 @@ int ebus_config_cb(const pci_config_t *config) ncells += pci_encode_phys_addr(props + ncells, flags, space_code, config->dev, PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)), - 0); + config->assigned[i] & ~mask); props[ncells++] = config->sizes[i]; } @@ -997,7 +1025,10 @@ static void ob_pci_add_properties(phandle_t phandle, } pci_set_assigned_addresses(phandle, config, num_bars); - OLDWORLD(pci_set_AAPL_address(config)); + + if (is_apple()) { + pci_set_AAPL_address(config); + } PCI_DPRINTF("\n"); } @@ -1397,9 +1428,11 @@ static void ob_pci_set_available(phandle_t host, unsigned long mem_base, unsigne static void ob_pci_host_set_interrupt_map(phandle_t host) { - phandle_t dnode = 0; - u32 props[128]; - int i; + phandle_t dnode = 0, pci_childnode = 0; + u32 props[128], intno; + int i, ncells, len; + u32 *val, addr; + char *reg; #if defined(CONFIG_PPC) phandle_t target_node; @@ -1420,16 +1453,22 @@ static void ob_pci_host_set_interrupt_map(phandle_t host) target_node = find_dev("/pci/mac-io/escc/ch-b"); set_int_property(target_node, "interrupt-parent", dnode); + target_node = find_dev("/pci/mac-io/escc-legacy/ch-a"); + set_int_property(target_node, "interrupt-parent", dnode); + + target_node = find_dev("/pci/mac-io/escc-legacy/ch-b"); + set_int_property(target_node, "interrupt-parent", dnode); + /* QEMU only emulates 2 of the 3 ata buses currently */ /* On a new world Mac these are not numbered but named by the * ATA version they support. Thus we have: ata-3, ata-3, ata-4 * On g3beige they all called just ide. - * We take ata-3 and ata-4 which seems to work for both - * at least for clients we care about */ - target_node = find_dev("/pci/mac-io/ata-3"); + * We take 2 x ata-3 buses which seems to work for + * at least the clients we care about */ + target_node = find_dev("/pci/mac-io/ata-3@20000"); set_int_property(target_node, "interrupt-parent", dnode); - target_node = find_dev("/pci/mac-io/ata-4"); + target_node = find_dev("/pci/mac-io/ata-3@21000"); set_int_property(target_node, "interrupt-parent", dnode); target_node = find_dev("/pci/mac-io/via-cuda"); @@ -1437,69 +1476,61 @@ static void ob_pci_host_set_interrupt_map(phandle_t host) target_node = find_dev("/pci"); set_int_property(target_node, "interrupt-parent", dnode); - - /* openpic interrupt mapping */ - for (i = 0; i < (7*8); i += 7) { - props[i + PCI_INT_MAP_PCI0] = 0; - props[i + PCI_INT_MAP_PCI1] = 0; - props[i + PCI_INT_MAP_PCI2] = 0; - props[i + PCI_INT_MAP_PCI_INT] = (i / 7) + 1; // starts at PINA=1 - props[i + PCI_INT_MAP_PIC_HANDLE] = dnode; - props[i + PCI_INT_MAP_PIC_INT] = arch->irqs[i / 7]; - props[i + PCI_INT_MAP_PIC_POL] = 3; - } - set_property(host, "interrupt-map", (char *)props, 7 * 8 * sizeof(props[0])); - - props[PCI_INT_MAP_PCI0] = 0; - props[PCI_INT_MAP_PCI1] = 0; - props[PCI_INT_MAP_PCI2] = 0; - props[PCI_INT_MAP_PCI_INT] = 0x7; - - set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0])); } -#elif defined(CONFIG_SPARC64) - int ncells, len; - u32 *val, addr; - char *reg; +#else + /* PCI host bridge is the default interrupt controller */ + dnode = host; +#endif /* Set interrupt-map for PCI devices with an interrupt pin present */ ncells = 0; PUSH(host); fword("child"); - dnode = POP(); - while (dnode) { - if (get_int_property(dnode, "interrupts", &len)) { - reg = get_property(dnode, "reg", &len); - if (reg) { + pci_childnode = POP(); + while (pci_childnode) { + intno = get_int_property(pci_childnode, "interrupts", &len); + if (len && intno) { + reg = get_property(pci_childnode, "reg", &len); + if (len && reg) { val = (u32 *)reg; for (i = 0; i < (len / sizeof(u32)); i += 5) { addr = val[i]; /* Device address is in 1st 32-bit word of encoded PCI address for config space */ - if (!(addr & 0x03000000)) { + if ((addr & PCI_RANGE_TYPE_MASK) == PCI_RANGE_CONFIG) { +#if defined(CONFIG_SPARC64) ncells += pci_encode_phys_addr(props + ncells, 0, 0, addr, 0, 0); - props[ncells++] = 1; /* always interrupt pin 1 for QEMU */ - props[ncells++] = host; - props[ncells++] = SUN4U_INTERRUPT(addr, 1); + props[ncells++] = intno; + props[ncells++] = dnode; + props[ncells++] = SUN4U_INTERRUPT(addr, intno); +#elif defined(CONFIG_PPC) + ncells += pci_encode_phys_addr(props + ncells, 0, 0, addr, 0, 0); + props[ncells++] = intno; + props[ncells++] = dnode; + props[ncells++] = arch->irqs[intno - 1]; + props[ncells++] = 3; +#else + /* Keep compiler quiet */ + dnode = dnode; +#endif } } } } - PUSH(dnode); + PUSH(pci_childnode); fword("peer"); - dnode = POP(); + pci_childnode = POP(); } set_property(host, "interrupt-map", (char *)props, ncells * sizeof(props[0])); props[0] = 0x0000f800; props[1] = 0x0; props[2] = 0x0; - props[3] = 7; + props[3] = 0x7; set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0])); -#endif } int ob_pci_init(void) diff --git a/qemu/roms/openbios/drivers/pci.fs b/qemu/roms/openbios/drivers/pci.fs index 563b652a4..a7b56e1f8 100644 --- a/qemu/roms/openbios/drivers/pci.fs +++ b/qemu/roms/openbios/drivers/pci.fs @@ -12,59 +12,19 @@ rot encode-int encode+ ; -\ Get region offset for BAR reg -: pci-bar-offset@ ( bar-reg -- off.lo off.hi -1 | 0 ) - " reg" active-package get-package-property 0= if - begin - decode-phys \ ( reg prop prop-len phys.lo phys.mid phys.hi ) - ff and 5 pick = if - >r >r 3drop r> r> - -1 exit - else - 2drop - then - \ Drop the size as we don't need it - decode-int drop decode-int drop - dup 0= - until - 3drop - 0 exit - else - 0 - then - ; - -\ Get region size for BAR reg -: pci-bar-size@ ( bar-reg -- size ) - " reg" active-package get-package-property 0= if - begin - decode-phys \ ( reg prop prop-len phys.lo phys.mid phys.hi ) - ff and 5 pick = if - 2drop decode-int drop - decode-int - >r 3drop r> - exit - else - 2drop decode-int drop - decode-int drop - then - dup 0= - until - 3drop - 0 \ default size of 0 if BAR not found - then - ; - -\ Get base address for configured BAR reg -: pci-bar-base@ ( bar-reg -- addr.lo addr.hi -1 | 0 ) +\ Get PCI physical address and size for configured BAR reg +: pci-bar>pci-addr ( bar-reg -- addr.lo addr.mid addr.hi size -1 | 0 ) " assigned-addresses" active-package get-package-property 0= if begin decode-phys \ ( reg prop prop-len phys.lo phys.mid phys.hi ) - ff and 5 pick = if - >r >r 3drop r> r> + dup ff and 6 pick = if + >r >r >r rot drop + decode-int drop decode-int + -rot 2drop + r> swap r> r> rot -1 exit else - 2drop + 3drop then \ Drop the size as we don't need it decode-int drop decode-int drop @@ -77,16 +37,4 @@ then ; -\ Get PCI bus address and size for configured BAR reg -: pci-bar>pci-region ( bar-reg -- addr.lo addr.hi size ) - dup - >r pci-bar-offset@ if - swap r@ pci-bar-base@ if - swap d+ - then - swap r@ pci-bar-size@ - then - r> drop - ; - [THEN] diff --git a/qemu/roms/openbios/drivers/pci.h b/qemu/roms/openbios/drivers/pci.h index 84a2b2cf6..d5aa5f84a 100644 --- a/qemu/roms/openbios/drivers/pci.h +++ b/qemu/roms/openbios/drivers/pci.h @@ -59,6 +59,15 @@ #define PCI_MIN_GNT 0x3e /* 8 bits */ #define PCI_MAX_LAT 0x3f /* 8 bits */ +#define PCI_RANGE_RELOCATABLE 0x80000000 +#define PCI_RANGE_PREFETCHABLE 0x40000000 +#define PCI_RANGE_ALIASED 0x20000000 +#define PCI_RANGE_TYPE_MASK 0x03000000 +#define PCI_RANGE_MMIO_64BIT 0x03000000 +#define PCI_RANGE_MMIO 0x02000000 +#define PCI_RANGE_IOPORT 0x01000000 +#define PCI_RANGE_CONFIG 0x00000000 + typedef struct { u16 signature; u8 reserved[0x16]; diff --git a/qemu/roms/openbios/drivers/sbus.c b/qemu/roms/openbios/drivers/sbus.c index a9b26c0a0..4caa59aaf 100644 --- a/qemu/roms/openbios/drivers/sbus.c +++ b/qemu/roms/openbios/drivers/sbus.c @@ -369,31 +369,6 @@ sbus_probe_slot_ss600mp(unsigned int slot, uint64_t base) } } -static void -ob_sbus_open(void) -{ - int ret=1; - RET ( -ret ); -} - -static void -ob_sbus_close(void) -{ - selfword("close-deblocker"); -} - -static void -ob_sbus_initialize(void) -{ -} - - -NODE_METHODS(ob_sbus_node) = { - { NULL, ob_sbus_initialize }, - { "open", ob_sbus_open }, - { "close", ob_sbus_close }, -}; - struct sbus_offset { int slot, type; uint64_t base; diff --git a/qemu/roms/openbios/drivers/usbohci_private.h b/qemu/roms/openbios/drivers/usbohci_private.h index b3a723e21..99c964100 100644 --- a/qemu/roms/openbios/drivers/usbohci_private.h +++ b/qemu/roms/openbios/drivers/usbohci_private.h @@ -43,7 +43,7 @@ // FIXME: fake typedef enum { CMD} reg; - enum { + extern enum { NumberDownstreamPorts = 1<<0, PowerSwitchingMode = 1<<8, NoPowerSwitching = 1<<9, @@ -53,17 +53,17 @@ PowerOnToPowerGoodTime = 1<<24 } HcRhDescriptorAReg; - enum { + extern enum { NumberDownstreamPortsMask = MASK(0, 8), PowerOnToPowerGoodTimeMask = MASK(24, 8) } HcRhDescriptorAMask; - enum { + extern enum { DeviceRemovable = 1<<0, PortPowerControlMask = 1<<16 } HcRhDescriptorBReg; - enum { + extern enum { CurrentConnectStatus = 1<<0, PortEnableStatus = 1<<1, PortSuspendStatus = 1<<2, @@ -77,7 +77,7 @@ PortOverCurrentIndicatorChange = 1<<19, PortResetStatusChange = 1<<20 } HcRhPortStatusRead; - enum { + extern enum { ClearPortEnable = 1<<0, SetPortEnable = 1<<1, SetPortSuspend = 1<<2, @@ -87,7 +87,7 @@ ClearPortPower = 1<<9, } HcRhPortStatusSet; - enum { + extern enum { LocalPowerStatus = 1<<0, OverCurrentIndicator = 1<<1, DeviceRemoteWakeupEnable = 1<<15, @@ -96,18 +96,18 @@ ClearRemoteWakeupEnable = 1<<31 } HcRhStatusReg; - enum { + extern enum { FrameInterval = 1<<0, FSLargestDataPacket = 1<<16, FrameIntervalToggle = 1<<31 } HcFmIntervalOffset; - enum { + extern enum { FrameIntervalMask = MASK(0, 14), FSLargestDataPacketMask = MASK(16, 15), FrameIntervalToggleMask = MASK(31, 1) } HcFmIntervalMask; - enum { + extern enum { ControlBulkServiceRatio = 1<<0, PeriodicListEnable = 1<<2, IsochronousEnable = 1<<3, @@ -119,7 +119,7 @@ RemoteWakeupEnable = 1<<10 } HcControlReg; - enum { + extern enum { ControlBulkServiceRatioMask = MASK(0, 2), HostControllerFunctionalStateMask = MASK(6, 2) } HcControlMask; @@ -131,7 +131,7 @@ USBSuspend = 3*HostControllerFunctionalState }; - enum { + extern enum { HostControllerReset = 1<<0, ControlListFilled = 1<<1, BulkListFilled = 1<<2, @@ -139,16 +139,16 @@ SchedulingOverrunCount = 1<<16 } HcCommandStatusReg; - enum { + extern enum { SchedulingOverrunCountMask = MASK(16, 2) } HcCommandStatusMask; - enum { + extern enum { FrameRemaining = 1<<0, FrameRemainingToggle = 1<<31 } HcFmRemainingReg; - enum { + extern enum { SchedulingOverrung = 1<<0, WritebackDoneHead = 1<<1, StartofFrame = 1<<2, diff --git a/qemu/roms/openbios/drivers/vga.fs b/qemu/roms/openbios/drivers/vga.fs index ec4c6c5f1..29a043a7a 100644 --- a/qemu/roms/openbios/drivers/vga.fs +++ b/qemu/roms/openbios/drivers/vga.fs @@ -109,16 +109,17 @@ h# 1 constant VBE_DISPI_ENABLED \ PCI \ -" pci-bar>pci-region" (find-xt) value pci-bar>pci-region-xt -: pci-bar>pci-region pci-bar>pci-region-xt execute ; +" pci-bar>pci-addr" (find-xt) value pci-bar>pci-addr-xt +: pci-bar>pci-addr pci-bar>pci-addr-xt execute ; h# 10 constant cfg-bar0 \ Framebuffer BAR -1 value fb-addr : map-fb ( -- ) - cfg-bar0 pci-bar>pci-region \ ( pci-addr.lo pci-addr.hi size ) - " pci-map-in" $call-parent - to fb-addr + cfg-bar0 pci-bar>pci-addr if \ ( pci-addr.lo pci-addr.mid pci-addr.hi size ) + " pci-map-in" $call-parent + to fb-addr + then ; \ diff --git a/qemu/roms/openbios/forth/lib/string.fs b/qemu/roms/openbios/forth/lib/string.fs index eb6474917..f97db232f 100644 --- a/qemu/roms/openbios/forth/lib/string.fs +++ b/qemu/roms/openbios/forth/lib/string.fs @@ -125,3 +125,17 @@ : parse-hex ( str len -- value ) base @ hex -rot $number if 0 then swap base ! ; + + +\ ----------------------------------------------------- +\ miscellaneous functions +\ ----------------------------------------------------- + +: rot13 ( c - c ) + dup upc [char] A [char] M between if d# 13 + exit then + dup upc [char] N [char] Z between if d# 13 - then +; + +: rot13-str ( str len -- newstr len ) + strdup 2dup bounds ?do i c@ rot13 i c! loop +; diff --git a/qemu/roms/openbios/forth/system/ciface.fs b/qemu/roms/openbios/forth/system/ciface.fs index fd6c54efd..85a607627 100644 --- a/qemu/roms/openbios/forth/system/ciface.fs +++ b/qemu/roms/openbios/forth/system/ciface.fs @@ -326,6 +326,14 @@ external : exit ( -- ) ." EXIT" + + \ Execute (exit) hook if one exists + s" (exit)" $find if + execute + else + 2drop + then + outer-interpreter ; diff --git a/qemu/roms/openbios/include/arch/ppc/types.h b/qemu/roms/openbios/include/arch/ppc/types.h index 69b3db405..b2246d060 100644 --- a/qemu/roms/openbios/include/arch/ppc/types.h +++ b/qemu/roms/openbios/include/arch/ppc/types.h @@ -84,21 +84,13 @@ typedef uint32_t prom_uarg_t; /* size named types */ typedef unsigned char u8; -typedef unsigned char __u8; typedef unsigned short u16; -typedef unsigned short __u16; typedef unsigned int u32; -typedef unsigned int __u32; typedef unsigned long long u64; -typedef unsigned long long __u64; typedef signed char s8; -typedef signed char __s8; typedef short s16; -typedef short __s16; typedef int s32; -typedef int __s32; typedef long long s64; -typedef long long __s64; #endif diff --git a/qemu/roms/openbios/include/arch/sparc64/io.h b/qemu/roms/openbios/include/arch/sparc64/io.h index 2e4dfa37f..0f1a73284 100644 --- a/qemu/roms/openbios/include/arch/sparc64/io.h +++ b/qemu/roms/openbios/include/arch/sparc64/io.h @@ -9,7 +9,7 @@ extern unsigned long va_shift; // Set in entry.S // Defined in ldscript -extern char _start, _data, _stack, _estack, _end, _iomem; +extern char _start, _data, _stack, _estack, _fcstack, _efcstack, _end, _iomem; // XXX check use and merge #define phys_to_virt(phys) ((void *) ((unsigned long) (phys))) diff --git a/qemu/roms/openbios/include/drivers/drivers.h b/qemu/roms/openbios/include/drivers/drivers.h index 3b83b12d1..48f81a870 100644 --- a/qemu/roms/openbios/include/drivers/drivers.h +++ b/qemu/roms/openbios/include/drivers/drivers.h @@ -52,6 +52,7 @@ void kbd_init(uint64_t base); /* drivers/ide.c */ int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0, uint32_t io_port1, uint32_t ctl_port1); +void ob_ide_quiesce(void); int macio_ide_init(const char *path, uint32_t addr, int nb_channels); #endif #ifdef CONFIG_DRIVER_ESP diff --git a/qemu/roms/openbios/include/libopenbios/bindings.h b/qemu/roms/openbios/include/libopenbios/bindings.h index de9c77520..4ec978912 100644 --- a/qemu/roms/openbios/include/libopenbios/bindings.h +++ b/qemu/roms/openbios/include/libopenbios/bindings.h @@ -56,6 +56,7 @@ extern ihandle_t open_package( const char *argstr, phandle_t ph ); extern ihandle_t open_dev( const char *spec ); extern void close_package( ihandle_t ih ); extern void close_dev( ihandle_t ih ); +extern char *get_path_from_ph( phandle_t ph ); /* property access */ extern void set_property( phandle_t ph, const char *name, diff --git a/qemu/roms/openbios/libopenbios/bindings.c b/qemu/roms/openbios/libopenbios/bindings.c index 5323421f5..4f7a99379 100644 --- a/qemu/roms/openbios/libopenbios/bindings.c +++ b/qemu/roms/openbios/libopenbios/bindings.c @@ -366,6 +366,14 @@ find_dev( const char *path ) return ret; } +char * +get_path_from_ph( phandle_t ph ) +{ + PUSH(ph); + fword("get-package-path"); + return pop_fstr_copy(); +} + phandle_t dt_iter_begin( void ) { diff --git a/qemu/roms/openbios/libopenbios/bootinfo_load.c b/qemu/roms/openbios/libopenbios/bootinfo_load.c index fa9e36bd4..f33678185 100644 --- a/qemu/roms/openbios/libopenbios/bootinfo_load.c +++ b/qemu/roms/openbios/libopenbios/bootinfo_load.c @@ -161,6 +161,12 @@ bootinfo_init_program(void) feval("load-size"); size = POP(); + /* Some bootinfo scripts contain a binary payload after the + NULL-terminated Forth string such as OS 9. Restrict our + size to just the Forth section, otherwise we end up trying + to allocate memory for the entire binary which might fail. */ + size = strnlen(base, size); + bootscript = malloc(size); if (bootscript == NULL) { DPRINTF("Can't malloc %d bytes\n", size); |