diff --git a/gecko.c b/gecko.c index 40b7509..3ffce78 100644 --- a/gecko.c +++ b/gecko.c @@ -320,14 +320,13 @@ void gecko_timer(void) { // done receiving, handle the command switch (_gecko_cmd) { case 0x43524150: - if (powerpc_boot_mem((u8 *) 0x10100000, _gecko_receive_len)) - gecko_printf("MINI/GECKO: the received binary is not a valid " - "PPC ELF. Broadway is dead now.\n"); + ipc_enqueue_slow(IPC_DEV_PPC, IPC_PPC_BOOT, 3, + 1, (u32) 0x10100000, _gecko_receive_len); break; case 0x5a4f4d47: // skip headerlen, which is stored at u32[0] - ipc_queue_slow_jump(((u32 *) 0x0)[0]); + ipc_enqueue_slow(IPC_DEV_SYS, IPC_SYS_JUMP, 1, ((u32 *) 0x0)[0]); break; } diff --git a/ipc.c b/ipc.c index 3681590..bac11ae 100644 --- a/ipc.c +++ b/ipc.c @@ -185,13 +185,28 @@ static u32 process_slow(volatile ipc_request *req) return 0; } -void ipc_add_slow(volatile ipc_request *req) +void ipc_enqueue_slow(u8 device, u16 req, u32 num_args, ...) { + int arg = 0; + va_list ap; + if(slow_queue_head == ((slow_queue_tail + 1)&(IPC_SLOW_SIZE-1))) { gecko_printf("IPC: Slowqueue overrun\n"); panic2(0, PANIC_IPCOVF); } - slow_queue[slow_queue_tail] = *req; + + slow_queue[slow_queue_tail].flags = IPC_SLOW; + slow_queue[slow_queue_tail].device = device; + slow_queue[slow_queue_tail].req = req; + slow_queue[slow_queue_tail].tag = 0; + + if(num_args) { + va_start(ap, num_args); + while(num_args--) + slow_queue[slow_queue_tail].args[arg++] = va_arg(ap, u32); + va_end(ap); + } + slow_queue_tail = (slow_queue_tail+1)&(IPC_SLOW_SIZE-1); } @@ -269,7 +284,13 @@ static void process_in(void) break; } } else { - ipc_add_slow(req); + if(slow_queue_head == ((slow_queue_tail + 1)&(IPC_SLOW_SIZE-1))) { + gecko_printf("IPC: Slowqueue overrun\n"); + panic2(0, PANIC_IPCOVF); + } + + slow_queue[slow_queue_tail] = *req; + slow_queue_tail = (slow_queue_tail+1)&(IPC_SLOW_SIZE-1); } } @@ -289,26 +310,6 @@ void ipc_irq(void) gecko_printf("IPC: IRQ but no bell!\n"); } -void ipc_queue_slow_jump(u32 addr) -{ - volatile ipc_request *req = &in_queue[in_head]; - - if(slow_queue_head == ((slow_queue_tail + 1)&(IPC_SLOW_SIZE-1))) { - gecko_printf("IPC: Slowqueue overrun\n"); - panic2(0, PANIC_IPCOVF); - } - - req->flags = IPC_SLOW; - req->device = IPC_DEV_SYS; - req->req = IPC_SYS_JUMP; - - req->tag = 0; - req->args[0] = addr; - - slow_queue[slow_queue_tail] = *req; - slow_queue_tail = (slow_queue_tail+1)&(IPC_SLOW_SIZE-1); -} - void ipc_initialize(void) { write32(HW_IPC_ARMMSG, 0); diff --git a/ipc.h b/ipc.h index a2d6423..a8a06ba 100644 --- a/ipc.h +++ b/ipc.h @@ -108,8 +108,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define IPC_PPC_BOOT 0x0000 -//#define IPC_USER0_OHAI 0x8000 <- your code goez here - #define IPC_CODE (f,d,r) (((f)<<24)|((d)<<16)|(r)) #define IPC_IN_SIZE 32 @@ -140,7 +138,6 @@ typedef const struct { } ipc_infohdr; void ipc_irq(void); -void ipc_queue_slow_jump(u32 addr); // only call this from irq context void ipc_initialize(void); void ipc_shutdown(void); @@ -148,9 +145,8 @@ void ipc_post(u32 code, u32 tag, u32 num_args, ...); void ipc_flush(void); u32 ipc_process_slow(void); -// add an entry to the slow queue from the arm -// (you probably want to use this in irq context) -void ipc_add_slow(volatile ipc_request *req); +// Enqueues a request in the slow in_queue, use this in IRQ context only. +void ipc_enqueue_slow(u8 device, u16 req, u32 num_args, ...); #endif diff --git a/mini.ld b/mini.ld index 402d1e1..8aac94e 100644 --- a/mini.ld +++ b/mini.ld @@ -24,7 +24,7 @@ EXTERN(__ipc_info) ENTRY(_start) __stack_size = 0x800; -__irqstack_size = 0x400; /* blame the bsd's sdhc_intr function */ +__irqstack_size = 0x100; __excstack_size = 0x100; MEMORY { diff --git a/powerpc.c b/powerpc.c index 32d03d7..b7ead86 100644 --- a/powerpc.c +++ b/powerpc.c @@ -81,10 +81,16 @@ void powerpc_ipc(volatile ipc_request *req) { switch (req->req) { case IPC_PPC_BOOT: - dc_invalidaterange((void *) req->args[0], (u32) req->args[1]); - int res = powerpc_boot_mem((u8 *) req->args[0], (u32) req->args[1]); - if (res) - ipc_post(req->code, req->tag, 1, res); + if (req->args[0]) { + // Enqueued from ARM side, do not invalidate mem nor ipc_post + powerpc_boot_mem((u8 *) req->args[1], req->args[2]); + } else { + dc_invalidaterange((void *) req->args[1], req->args[2]); + int res = powerpc_boot_mem((u8 *) req->args[1], req->args[2]); + if (res) + ipc_post(req->code, req->tag, 1, res); + } + break; default: gecko_printf("IPC: unknown SLOW PPC request %04X\n", req->req); diff --git a/sdhc.c b/sdhc.c index 327c80c..cb031e4 100644 --- a/sdhc.c +++ b/sdhc.c @@ -1057,16 +1057,10 @@ sdhc_intr(void *arg) * Wake up the sdmmc event thread to scan for cards. */ if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)) { - // this pushed a request to the slow queue so that we - // don't block other IRQs. - // this is also static because we are in IRQ context - // here and want to save stack space - static ipc_request req; - memset(&req, 0, sizeof(req)); - req.device = IPC_DEV_SDHC; - req.req = IPC_SDHC_DISCOVER; - req.args[0] = (u32)hp->sdmmc; - ipc_add_slow(&req); + // this pushed a request to the slow queue so that we + // don't block other IRQs. + ipc_enqueue_slow(IPC_DEV_SDHC, IPC_SDHC_DISCOVER, 1, + (u32) hp->sdmmc); } /*