miniIOS IPC updates

This commit is contained in:
marcan 2009-01-25 04:04:19 +01:00 committed by bushing
parent d4cdb1f01d
commit 29caadc06b
8 changed files with 99 additions and 126 deletions

View File

@ -10,7 +10,7 @@ MAKEBIN = python ../makebin.py
TARGET = miniios.bin TARGET = miniios.bin
ELF = miniios.elf ELF = miniios.elf
OBJECTS = start.o ipcstruct.o main.o ipc.o vsprintf.o string.o gecko.o memory.o memory_asm.o \ OBJECTS = start.o main.o ipc.o vsprintf.o string.o gecko.o memory.o memory_asm.o \
utils_asm.o utils.o ff.o diskio.o sdhc.o powerpc_elf.o powerpc.o panic.o irq.o irq_asm.o \ utils_asm.o utils.o ff.o diskio.o sdhc.o powerpc_elf.o powerpc.o panic.o irq.o irq_asm.o \
exception.o exception_asm.o crypto.o nand.o nandfs.o exception.o exception_asm.o crypto.o nand.o nandfs.o

100
ipc.c
View File

@ -5,34 +5,46 @@
#include "utils.h" #include "utils.h"
#include "hollywood.h" #include "hollywood.h"
#include "gecko.h" #include "gecko.h"
#include "ipcstruct.h"
#include "ipc.h" #include "ipc.h"
#define IPC_SLOW_SIZE 128 static volatile ipc_request in_queue[IPC_IN_SIZE] ALIGNED(32) MEM2_BSS;
static volatile ipc_request out_queue[IPC_OUT_SIZE] ALIGNED(32) MEM2_BSS;
static volatile ipc_request slow_queue[IPC_SLOW_SIZE];
volatile ipc_request slow[IPC_SLOW_SIZE]; extern char __mem2_area_start[];
u16 slow_head;
vu16 slow_tail;
u16 in_head; const ipc_infohdr __ipc_info ALIGNED(32) MEM2_RODATA = {
u16 out_tail; .magic = "IPC",
.version = 1,
.mem2_boundary = __mem2_area_start,
.ipc_in = in_queue,
.ipc_in_size = IPC_IN_SIZE,
.ipc_out = out_queue,
.ipc_out_size = IPC_OUT_SIZE,
};
static u16 slow_queue_head;
static vu16 slow_queue_tail;
static u16 in_head;
static u16 out_tail;
static inline void poke_outtail(u16 num) static inline void poke_outtail(u16 num)
{ {
write16(HW_IPC_ARMMSG, num); mask32(HW_IPC_ARMMSG, 0xFFFF, num);
} }
static inline void poke_inhead(u16 num) static inline void poke_inhead(u16 num)
{ {
write16(HW_IPC_ARMMSG+2, num); mask32(HW_IPC_ARMMSG, 0xFFFF0000, num<<16);
} }
static inline u16 peek_intail(void) static inline u16 peek_intail(void)
{ {
return read16(HW_IPC_PPCMSG); return read32(HW_IPC_PPCMSG) & 0xFFF;
} }
static inline u16 peek_outhead(void) static inline u16 peek_outhead(void)
{ {
return read16(HW_IPC_PPCMSG+2); return read32(HW_IPC_PPCMSG) >> 16;
} }
void ipc_post(u32 code, u32 tag, u32 num_args, ...) void ipc_post(u32 code, u32 tag, u32 num_args, ...)
@ -42,19 +54,19 @@ void ipc_post(u32 code, u32 tag, u32 num_args, ...)
u32 cookie = irq_kill(); u32 cookie = irq_kill();
if(peek_outhead() == ((out_tail + 1)&(IPC_OUT_SIZE-1))) { if(peek_outhead() == ((out_tail + 1)&(IPC_OUT_SIZE-1))) {
gecko_printf("IPC: out queue full, PPC slow/dead/DoSed\n"); gecko_printf("IPC: out queue full, PPC slow/dead/flooded\n");
while(peek_outhead() == ((out_tail + 1)&(IPC_OUT_SIZE-1))); while(peek_outhead() == ((out_tail + 1)&(IPC_OUT_SIZE-1)));
} }
ipc_out[out_tail].code = code; out_queue[out_tail].code = code;
ipc_out[out_tail].tag = tag; out_queue[out_tail].tag = tag;
if(num_args) { if(num_args) {
va_start(ap, num_args); va_start(ap, num_args);
while(num_args--) { while(num_args--) {
ipc_out[out_tail].args[arg++] = va_arg(ap, u32); out_queue[out_tail].args[arg++] = va_arg(ap, u32);
} }
va_end(ap); va_end(ap);
} }
dc_flushrange((void*)&ipc_out[out_tail], 32); dc_flushrange((void*)&out_queue[out_tail], 32);
out_tail = (out_tail+1)&(IPC_OUT_SIZE-1); out_tail = (out_tail+1)&(IPC_OUT_SIZE-1);
poke_outtail(out_tail); poke_outtail(out_tail);
write32(HW_IPC_ARMCTRL, IPC_CTRL_INT_RECV | IPC_CTRL_SEND); write32(HW_IPC_ARMCTRL, IPC_CTRL_INT_RECV | IPC_CTRL_SEND);
@ -64,31 +76,46 @@ void ipc_post(u32 code, u32 tag, u32 num_args, ...)
static int process_slow(volatile ipc_request *req) static int process_slow(volatile ipc_request *req)
{ {
gecko_printf("IPC: process slow @ %p\n",req); //gecko_printf("IPC: process slow_queue @ %p\n",req);
gecko_printf("IPC: req %08x %08x [%08x %08x %08x %08x %08x %08x]\n", req->code, req->tag, //gecko_printf("IPC: req %08x %08x [%08x %08x %08x %08x %08x %08x]\n", req->code, req->tag,
req->args[0], req->args[1], req->args[2], req->args[3], req->args[4], req->args[5]); // req->args[0], req->args[1], req->args[2], req->args[3], req->args[4], req->args[5]);
gecko_printf("IPC: unknown SLOW request %02x-%04x\n", req->device, req->req); switch(req->device) {
case IPC_DEV_SYS:
switch(req->req) {
case IPC_SYS_PING: //PING can be both slow and fast for testing purposes
ipc_post(req->code, req->tag, 0);
break;
default:
gecko_printf("IPC: unknown SLOW SYS request %04x\n", req->req);
}
break;
default:
gecko_printf("IPC: unknown SLOW request %02x-%04x\n", req->device, req->req);
}
return 1; return 1;
} }
static void process_in(void) static void process_in(void)
{ {
volatile ipc_request *req = &ipc_in[in_head]; volatile ipc_request *req = &in_queue[in_head];
gecko_printf("IPC: process in %d @ %p\n",in_head,req); //gecko_printf("IPC: process in %d @ %p\n",in_head,req);
dc_invalidaterange((void*)req, 32); dc_invalidaterange((void*)req, 32);
gecko_printf("IPC: req %08x %08x [%08x %08x %08x %08x %08x %08x]\n", req->code, req->tag, //gecko_printf("IPC: req %08x %08x [%08x %08x %08x %08x %08x %08x]\n", req->code, req->tag,
req->args[0], req->args[1], req->args[2], req->args[3], req->args[4], req->args[5]); // req->args[0], req->args[1], req->args[2], req->args[3], req->args[4], req->args[5]);
if(req->flags & IPC_FAST) { if(req->flags & IPC_FAST) {
switch(req->device) { switch(req->device) {
case IPC_DEV_SYS: case IPC_DEV_SYS:
// handle fast SYS requests here // handle fast SYS requests here
switch(req->req) { switch(req->req) {
case IPC_SYS_PING:
ipc_post(req->code, req->tag, 0);
break;
case IPC_SYS_WRITE32: case IPC_SYS_WRITE32:
write32(req->args[0], req->args[1]); write32(req->args[0], req->args[1]);
break; break;
@ -144,34 +171,29 @@ static void process_in(void)
break; break;
} }
} else { } else {
if(slow_head == ((slow_tail + 1)&(IPC_SLOW_SIZE-1))) { if(slow_queue_head == ((slow_queue_tail + 1)&(IPC_SLOW_SIZE-1))) {
gecko_printf("IPC: Slowqueue overrun\n"); gecko_printf("IPC: Slowqueue overrun\n");
panic(0x33); panic(0x33);
} }
slow[slow_tail] = *req; slow_queue[slow_queue_tail] = *req;
slow_tail = (slow_tail+1)&(IPC_SLOW_SIZE-1); slow_queue_tail = (slow_queue_tail+1)&(IPC_SLOW_SIZE-1);
} }
} }
void ipc_irq(void) void ipc_irq(void)
{ {
int donebell = 0; int donebell = 0;
gecko_printf("IPC: irq\n");
while(read32(HW_IPC_ARMCTRL) & IPC_CTRL_RECV) { while(read32(HW_IPC_ARMCTRL) & IPC_CTRL_RECV) {
write32(HW_IPC_ARMCTRL, IPC_CTRL_INT_RECV | IPC_CTRL_RECV); write32(HW_IPC_ARMCTRL, IPC_CTRL_INT_RECV | IPC_CTRL_RECV);
int donereq = 0;
while(peek_intail() != in_head) { while(peek_intail() != in_head) {
process_in(); process_in();
in_head = (in_head+1)&(IPC_IN_SIZE-1); in_head = (in_head+1)&(IPC_IN_SIZE-1);
poke_inhead(in_head); poke_inhead(in_head);
donereq++;
} }
if(!donereq)
gecko_printf("IPC bell but no reqs\n");
donebell++; donebell++;
} }
if(!donebell) if(!donebell)
gecko_printf("IPC IRQ but no bell!\n"); gecko_printf("IPC: IRQ but no bell!\n");
} }
void ipc_initialize(void) void ipc_initialize(void)
@ -180,8 +202,8 @@ void ipc_initialize(void)
write32(HW_IPC_PPCMSG, 0); write32(HW_IPC_PPCMSG, 0);
write32(HW_IPC_PPCCTRL, IPC_CTRL_SENT|IPC_CTRL_RECV); write32(HW_IPC_PPCCTRL, IPC_CTRL_SENT|IPC_CTRL_RECV);
write32(HW_IPC_ARMCTRL, IPC_CTRL_SENT|IPC_CTRL_RECV); write32(HW_IPC_ARMCTRL, IPC_CTRL_SENT|IPC_CTRL_RECV);
slow_head = 0; slow_queue_head = 0;
slow_tail = 0; slow_queue_tail = 0;
in_head = 0; in_head = 0;
out_tail = 0; out_tail = 0;
irq_enable(IRQ_IPC); irq_enable(IRQ_IPC);
@ -195,13 +217,13 @@ void ipc_shutdown(void)
void ipc_process_slow(void) void ipc_process_slow(void)
{ {
while(1) { while(1) {
while(slow_head != slow_tail) { while(slow_queue_head != slow_queue_tail) {
if(!process_slow(&slow[slow_head])) if(!process_slow(&slow_queue[slow_queue_head]))
return; return;
slow_head = (slow_head+1)&(IPC_SLOW_SIZE-1); slow_queue_head = (slow_queue_head+1)&(IPC_SLOW_SIZE-1);
} }
u32 cookie = irq_kill(); u32 cookie = irq_kill();
if(slow_head == slow_tail) if(slow_queue_head == slow_queue_tail)
irq_wait(); irq_wait();
irq_restore(cookie); irq_restore(cookie);
} }

18
ipc.h
View File

@ -8,7 +8,8 @@
#define IPC_DEV_SYS 0x00 #define IPC_DEV_SYS 0x00
#define IPC_SYS_JUMP 0x0000 #define IPC_SYS_PING 0x0000
#define IPC_SYS_JUMP 0x0001
#define IPC_SYS_WRITE32 0x0100 #define IPC_SYS_WRITE32 0x0100
#define IPC_SYS_WRITE16 0x0101 #define IPC_SYS_WRITE16 0x0101
#define IPC_SYS_WRITE8 0x0102 #define IPC_SYS_WRITE8 0x0102
@ -25,9 +26,12 @@
#define IPC_SYS_MASK16 0x010d #define IPC_SYS_MASK16 0x010d
#define IPC_SYS_MASK8 0x010e #define IPC_SYS_MASK8 0x010e
#define IPC_CODE (f,d,r) (((f)<<24)|((d)<<16)|(r)) #define IPC_CODE (f,d,r) (((f)<<24)|((d)<<16)|(r))
#define IPC_IN_SIZE 32
#define IPC_OUT_SIZE 32
#define IPC_SLOW_SIZE 128
typedef struct { typedef struct {
union { union {
struct { struct {
@ -41,6 +45,16 @@ typedef struct {
u32 args[6]; u32 args[6];
} ipc_request; } ipc_request;
typedef const struct {
char magic[3];
char version;
void *mem2_boundary;
volatile ipc_request *ipc_in;
u32 ipc_in_size;
volatile ipc_request *ipc_out;
u32 ipc_out_size;
} ipc_infohdr;
void ipc_irq(void); void ipc_irq(void);
void ipc_initialize(void); void ipc_initialize(void);

View File

@ -1,29 +0,0 @@
#include "ipcstruct.h"
.section .rodata.ipc,"a",%progbits
.globl ipc_header
.type ipc_header, %object
.size ipc_header, 32
.align 5
ipc_header:
.ascii "IPC1"
.long 0
.long ipc_in
.long 32
.long ipc_out
.long 32
.section .bss.ipc,"aw",%nobits
.globl ipc_in
.type ipc_in, %object
.size ipc_in, 32 * IPC_IN_SIZE
.align 5
ipc_in:
.space 32 * IPC_IN_SIZE
.globl ipc_out
.type ipc_out, %object
.size ipc_out, 32 * IPC_OUT_SIZE
.align 5
ipc_out:
.space 32 * IPC_IN_SIZE

View File

@ -1,16 +0,0 @@
#ifndef __IPCSTRUCT_H__
#define __IPCSTRUCT_H__
#define IPC_IN_SIZE 32
#define IPC_OUT_SIZE 32
#ifndef _LANGUAGE_ASSEMBLY
#include "ipc.h"
extern volatile ipc_request ipc_in[IPC_IN_SIZE];
extern volatile ipc_request ipc_out[IPC_OUT_SIZE];
#endif
#endif

2
irq.c
View File

@ -31,7 +31,7 @@ void irq_handler(void)
u32 enabled = read32(HW_IRQENABLE); u32 enabled = read32(HW_IRQENABLE);
u32 flags = read32(HW_IRQFLAG); u32 flags = read32(HW_IRQFLAG);
gecko_printf("In IRQ handler: 0x%08x 0x%08x 0x%08x\n", enabled, flags, flags & enabled); //gecko_printf("In IRQ handler: 0x%08x 0x%08x 0x%08x\n", enabled, flags, flags & enabled);
flags = flags & enabled; flags = flags & enabled;

View File

@ -1,6 +1,7 @@
OUTPUT_FORMAT("elf32-bigarm") OUTPUT_FORMAT("elf32-bigarm")
OUTPUT_ARCH(arm) OUTPUT_ARCH(arm)
EXTERN(_start) EXTERN(_start)
EXTERN(__ipc_info)
ENTRY(_start) ENTRY(_start)
__stack_size = 0x800; __stack_size = 0x800;
@ -8,31 +9,26 @@ __irqstack_size = 0x100;
__excstack_size = 0x100; __excstack_size = 0x100;
MEMORY { MEMORY {
sram : ORIGIN = 0xffff0000, LENGTH = 64K sram : ORIGIN = 0xffff0000, LENGTH = 64K
sram2 : ORIGIN = 0xfffe0000, LENGTH = 32K sram2 : ORIGIN = 0xfffe0000, LENGTH = 16K
mem2 : ORIGIN = 0x13f00000, LENGTH = 1M pagetable : ORIGIN = 0xfffe4000, LENGTH = 16K
mem2 : ORIGIN = 0x13f00000, LENGTH = 1M
} }
__mem2_area_start = ORIGIN(mem2);
__mem2_area_size = LENGTH(mem2);
__mem2_area_end = ORIGIN(mem2) + LENGTH(mem2);
__page_table = ORIGIN(pagetable);
SECTIONS SECTIONS
{ {
.rodata.ipc :
{
*(.rodata.ipc)
. = ALIGN(4);
} >mem2
.bss.ipc :
{
*(.bss.ipc)
. = ALIGN(4);
} >mem2
.rodata.mem2 : .rodata.mem2 :
{ {
*(.rodata.mem2) *(.rodata.mem2)
. = ALIGN(4); . = ALIGN(4);
} >mem2 } >mem2
.data.mem2 : .data.mem2 :
{ {
*(.data.mem2) *(.data.mem2)
@ -47,6 +43,11 @@ SECTIONS
__bss2_end = . ; __bss2_end = . ;
} >mem2 } >mem2
.ipcinfo __mem2_area_end - 4 :
{
LONG(__ipc_info);
} >mem2
.init : .init :
{ {
*(.init) *(.init)
@ -73,7 +74,7 @@ SECTIONS
*(.gnu.linkonce.r*) *(.gnu.linkonce.r*)
. = ALIGN(4); . = ALIGN(4);
} >sram2 } >sram2
.data : .data :
{ {
*(.data) *(.data)
@ -81,14 +82,13 @@ SECTIONS
*(.gnu.linkonce.d*) *(.gnu.linkonce.d*)
. = ALIGN(4); . = ALIGN(4);
} >sram2 } >sram2
.bss : .bss :
{ {
__bss_start = . ; __bss_start = . ;
*(.dynbss) *(.dynbss)
*(.gnu.linkonce.b*) *(.gnu.linkonce.b*)
*(.bss*) *(.bss*)
*(.sbss*)
*(COMMON) *(COMMON)
. = ALIGN(4); . = ALIGN(4);
__bss_end = . ; __bss_end = . ;
@ -110,23 +110,5 @@ SECTIONS
__excstack_addr = .; __excstack_addr = .;
} >sram2 } >sram2
.pagetable :
{
. = ALIGN(16384);
__page_table = .;
. = . + 16384;
} >sram2
} }
PROVIDE (__page_table = __page_table);
PROVIDE (__stack_end = __stack_end);
PROVIDE (__stack_addr = __stack_addr);
PROVIDE (__irqstack_end = __irqstack_end);
PROVIDE (__irqstack_addr = __irqstack_addr);
PROVIDE (__excstack_end = __excstack_end);
PROVIDE (__excstack_addr = __excstack_addr);
PROVIDE (__bss_start = __bss_start);
PROVIDE (__bss_end = __bss_end);
PROVIDE (__bss2_start = __bss2_start);
PROVIDE (__bss2_end = __bss2_end);

View File

@ -83,7 +83,7 @@ int powerpc_load_file(const char *path)
gecko_puts("ELF load done, booting PPC...\n"); gecko_puts("ELF load done, booting PPC...\n");
powerpc_upload_stub(NULL,0); powerpc_upload_stub(NULL,0);
powerpc_reset(); powerpc_reset();
gecko_puts("PPC booted!\n\n"); gecko_puts("PPC booted!\n");
return 0; return 0;
} }