mirror of
https://github.com/fail0verflow/mini.git
synced 2024-11-24 12:19:21 +01:00
Beginnings of IPC system. Totally untested.
This commit is contained in:
parent
cc5b7ea98c
commit
3a258f2ed9
209
ipc.c
209
ipc.c
@ -0,0 +1,209 @@
|
||||
#include <stdarg.h>
|
||||
#include "types.h"
|
||||
#include "irq.h"
|
||||
#include "memory.h"
|
||||
#include "utils.h"
|
||||
#include "hollywood.h"
|
||||
#include "gecko.h"
|
||||
#include "ipcstruct.h"
|
||||
#include "ipc.h"
|
||||
|
||||
#define IPC_SLOW_SIZE 128
|
||||
|
||||
volatile ipc_request slow[IPC_SLOW_SIZE];
|
||||
u16 slow_head;
|
||||
vu16 slow_tail;
|
||||
|
||||
u16 in_head;
|
||||
u16 out_tail;
|
||||
|
||||
static inline void poke_outtail(u16 num)
|
||||
{
|
||||
write16(HW_IPC_ARMMSG, num);
|
||||
}
|
||||
static inline void poke_inhead(u16 num)
|
||||
{
|
||||
write16(HW_IPC_ARMMSG+2, num);
|
||||
}
|
||||
|
||||
static inline u16 peek_intail(void)
|
||||
{
|
||||
return read16(HW_IPC_PPCMSG);
|
||||
}
|
||||
static inline u16 peek_outhead(void)
|
||||
{
|
||||
return read16(HW_IPC_PPCMSG+2);
|
||||
}
|
||||
|
||||
void ipc_post(u32 code, u32 tag, u32 num_args, ...)
|
||||
{
|
||||
int arg = 0;
|
||||
va_list ap;
|
||||
u32 cookie = irq_kill();
|
||||
|
||||
if(peek_outhead() == ((out_tail + 1)&(IPC_OUT_SIZE-1))) {
|
||||
gecko_printf("IPC: out queue full, PPC slow/dead/DoSed\n");
|
||||
while(peek_outhead() == ((out_tail + 1)&(IPC_OUT_SIZE-1)));
|
||||
}
|
||||
ipc_out[out_tail].code = code;
|
||||
ipc_out[out_tail].tag = tag;
|
||||
if(num_args) {
|
||||
va_start(ap, num_args);
|
||||
while(num_args--) {
|
||||
ipc_out[out_tail].args[arg++] = va_arg(ap, u32);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
dc_flushrange((void*)&ipc_out[out_tail], 32);
|
||||
out_tail = (out_tail+1)&(IPC_OUT_SIZE-1);
|
||||
poke_outtail(out_tail);
|
||||
write32(HW_IPC_ARMCTRL, IPC_CTRL_INT_RECV | IPC_CTRL_SEND);
|
||||
|
||||
irq_restore(cookie);
|
||||
}
|
||||
|
||||
static int process_slow(volatile ipc_request *req)
|
||||
{
|
||||
gecko_printf("IPC: process slow @ %p\n",req);
|
||||
|
||||
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]);
|
||||
|
||||
gecko_printf("IPC: unknown SLOW request %02x-%04x\n", req->device, req->req);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void process_in(void)
|
||||
{
|
||||
volatile ipc_request *req = &ipc_in[in_head];
|
||||
|
||||
gecko_printf("IPC: process in %d @ %p\n",in_head,req);
|
||||
|
||||
dc_invalidaterange((void*)req, 32);
|
||||
|
||||
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]);
|
||||
|
||||
if(req->flags & IPC_FAST) {
|
||||
switch(req->device) {
|
||||
case IPC_DEV_SYS:
|
||||
// handle fast SYS requests here
|
||||
switch(req->req) {
|
||||
case IPC_SYS_WRITE32:
|
||||
write32(req->args[0], req->args[1]);
|
||||
break;
|
||||
case IPC_SYS_WRITE16:
|
||||
write16(req->args[0], req->args[1]);
|
||||
break;
|
||||
case IPC_SYS_WRITE8:
|
||||
write8(req->args[0], req->args[1]);
|
||||
break;
|
||||
case IPC_SYS_READ32:
|
||||
ipc_post(req->code, req->tag, 1, read32(req->args[0]));
|
||||
break;
|
||||
case IPC_SYS_READ16:
|
||||
ipc_post(req->code, req->tag, 1, read16(req->args[0]));
|
||||
break;
|
||||
case IPC_SYS_READ8:
|
||||
ipc_post(req->code, req->tag, 1, read8(req->args[0]));
|
||||
break;
|
||||
case IPC_SYS_SET32:
|
||||
set32(req->args[0], req->args[1]);
|
||||
break;
|
||||
case IPC_SYS_SET16:
|
||||
set16(req->args[0], req->args[1]);
|
||||
break;
|
||||
case IPC_SYS_SET8:
|
||||
set8(req->args[0], req->args[1]);
|
||||
break;
|
||||
case IPC_SYS_CLEAR32:
|
||||
clear32(req->args[0], req->args[1]);
|
||||
break;
|
||||
case IPC_SYS_CLEAR16:
|
||||
clear16(req->args[0], req->args[1]);
|
||||
break;
|
||||
case IPC_SYS_CLEAR8:
|
||||
clear8(req->args[0], req->args[1]);
|
||||
break;
|
||||
case IPC_SYS_MASK32:
|
||||
mask32(req->args[0], req->args[1], req->args[2]);
|
||||
break;
|
||||
case IPC_SYS_MASK16:
|
||||
mask16(req->args[0], req->args[1], req->args[2]);
|
||||
break;
|
||||
case IPC_SYS_MASK8:
|
||||
mask8(req->args[0], req->args[1], req->args[2]);
|
||||
break;
|
||||
default:
|
||||
gecko_printf("IPC: unknown FAST SYS request %04x\n", req->req);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
gecko_printf("IPC: unknown FAST request %02x-%04x\n", req->device, req->req);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(slow_head == ((slow_tail + 1)&(IPC_SLOW_SIZE-1))) {
|
||||
gecko_printf("IPC: Slowqueue overrun\n");
|
||||
panic(0x33);
|
||||
}
|
||||
slow[slow_tail] = *req;
|
||||
slow_tail = (slow_tail+1)&(IPC_SLOW_SIZE-1);
|
||||
}
|
||||
}
|
||||
|
||||
void ipc_irq(void)
|
||||
{
|
||||
int donebell = 0;
|
||||
gecko_printf("IPC: irq\n");
|
||||
while(read32(HW_IPC_ARMCTRL) & IPC_CTRL_RECV) {
|
||||
write32(HW_IPC_ARMCTRL, IPC_CTRL_INT_RECV | IPC_CTRL_RECV);
|
||||
int donereq = 0;
|
||||
while(peek_intail() != in_head) {
|
||||
process_in();
|
||||
in_head = (in_head+1)&(IPC_IN_SIZE-1);
|
||||
poke_inhead(in_head);
|
||||
donereq++;
|
||||
}
|
||||
if(!donereq)
|
||||
gecko_printf("IPC bell but no reqs\n");
|
||||
donebell++;
|
||||
}
|
||||
if(!donebell)
|
||||
gecko_printf("IPC IRQ but no bell!\n");
|
||||
}
|
||||
|
||||
void ipc_initialize(void)
|
||||
{
|
||||
write32(HW_IPC_ARMMSG, 0);
|
||||
write32(HW_IPC_PPCMSG, 0);
|
||||
write32(HW_IPC_PPCCTRL, IPC_CTRL_SENT|IPC_CTRL_RECV);
|
||||
write32(HW_IPC_ARMCTRL, IPC_CTRL_SENT|IPC_CTRL_RECV);
|
||||
slow_head = 0;
|
||||
slow_tail = 0;
|
||||
in_head = 0;
|
||||
out_tail = 0;
|
||||
irq_enable(IRQ_IPC);
|
||||
write32(HW_IPC_ARMCTRL, IPC_CTRL_INT_RECV);
|
||||
}
|
||||
void ipc_shutdown(void)
|
||||
{
|
||||
irq_disable(IRQ_IPC);
|
||||
}
|
||||
|
||||
void ipc_process_slow(void)
|
||||
{
|
||||
while(1) {
|
||||
while(slow_head != slow_tail) {
|
||||
if(!process_slow(&slow[slow_head]))
|
||||
return;
|
||||
slow_head = (slow_head+1)&(IPC_SLOW_SIZE-1);
|
||||
}
|
||||
u32 cookie = irq_kill();
|
||||
if(slow_head == slow_tail)
|
||||
irq_wait();
|
||||
irq_restore(cookie);
|
||||
}
|
||||
}
|
||||
|
51
ipc.h
Normal file
51
ipc.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef __IPC_H__
|
||||
#define __IPC_H__
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define IPC_FAST 0x01
|
||||
#define IPC_SLOW 0x00
|
||||
|
||||
#define IPC_DEV_SYS 0x00
|
||||
|
||||
#define IPC_SYS_JUMP 0x0000
|
||||
#define IPC_SYS_WRITE32 0x0100
|
||||
#define IPC_SYS_WRITE16 0x0101
|
||||
#define IPC_SYS_WRITE8 0x0102
|
||||
#define IPC_SYS_READ32 0x0103
|
||||
#define IPC_SYS_READ16 0x0104
|
||||
#define IPC_SYS_READ8 0x0105
|
||||
#define IPC_SYS_SET32 0x0106
|
||||
#define IPC_SYS_SET16 0x0107
|
||||
#define IPC_SYS_SET8 0x0108
|
||||
#define IPC_SYS_CLEAR32 0x0109
|
||||
#define IPC_SYS_CLEAR16 0x010a
|
||||
#define IPC_SYS_CLEAR8 0x010b
|
||||
#define IPC_SYS_MASK32 0x010c
|
||||
#define IPC_SYS_MASK16 0x010d
|
||||
#define IPC_SYS_MASK8 0x010e
|
||||
|
||||
|
||||
#define IPC_CODE (f,d,r) (((f)<<24)|((d)<<16)|(r))
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
u8 flags;
|
||||
u8 device;
|
||||
u16 req;
|
||||
};
|
||||
u32 code;
|
||||
};
|
||||
u32 tag;
|
||||
u32 args[6];
|
||||
} ipc_request;
|
||||
|
||||
void ipc_irq(void);
|
||||
|
||||
void ipc_initialize(void);
|
||||
void ipc_shutdown(void);
|
||||
void ipc_post(u32 code, u32 tag, u32 num_args, ...);
|
||||
void ipc_process_slow(void);
|
||||
|
||||
#endif
|
@ -6,6 +6,11 @@
|
||||
|
||||
#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
|
||||
|
6
irq.c
6
irq.c
@ -2,6 +2,7 @@
|
||||
#include "hollywood.h"
|
||||
#include "gecko.h"
|
||||
#include "utils.h"
|
||||
#include "ipc.h"
|
||||
|
||||
void irq_setup_stack(void);
|
||||
|
||||
@ -60,12 +61,13 @@ void irq_handler(void)
|
||||
write32(HW_IRQFLAG, IRQF_RESET);
|
||||
}
|
||||
if(flags & IRQF_IPC) {
|
||||
gecko_printf("IRQ: IPC\n");
|
||||
//gecko_printf("IRQ: IPC\n");
|
||||
ipc_irq();
|
||||
write32(HW_IRQFLAG, IRQF_IPC);
|
||||
}
|
||||
flags &= ~IRQF_ALL;
|
||||
if(flags) {
|
||||
gecko_printf("IRQ: unknown 0x%08x\n");
|
||||
gecko_printf("IRQ: unknown 0x%08x\n", flags);
|
||||
write32(HW_IRQFLAG, flags);
|
||||
}
|
||||
}
|
||||
|
64
main.c
64
main.c
@ -11,6 +11,9 @@
|
||||
#include "panic.h"
|
||||
#include "powerpc_elf.h"
|
||||
#include "irq.h"
|
||||
#include "ipc.h"
|
||||
|
||||
void *vector;
|
||||
|
||||
typedef struct {
|
||||
u32 hdrsize;
|
||||
@ -30,7 +33,7 @@ static inline void mem1_poke(u8 *dst, u8 bv)
|
||||
{
|
||||
u32 *p = (u32*)(((u32)dst) & ~3);
|
||||
u32 val = *p;
|
||||
|
||||
|
||||
switch(((u32)dst) & 3) {
|
||||
case 0:
|
||||
val = (val & 0x00FFFFFF) | bv << 24;
|
||||
@ -45,7 +48,7 @@ static inline void mem1_poke(u8 *dst, u8 bv)
|
||||
val = (val & 0xFFFFFF00) | bv;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
*p = val;
|
||||
}
|
||||
|
||||
@ -133,7 +136,7 @@ void *patch_boot2(void *base, u64 titleID)
|
||||
boot2_patchelf(elf, titleID);
|
||||
|
||||
parhdr->argument = 0x42;
|
||||
|
||||
|
||||
gecko_printf("Vector: %p\n", (void*)(((u32)parhdr) + parhdr->hdrsize));
|
||||
|
||||
return (void*)(((u32)parhdr) + parhdr->hdrsize);
|
||||
@ -147,28 +150,28 @@ void *_main(void *base)
|
||||
gecko_init();
|
||||
gecko_puts("MiniIOS v0.1 loading\n");
|
||||
|
||||
fres = f_mount(0, &fatfs);
|
||||
|
||||
if(fres != FR_OK) {
|
||||
gecko_printf("Error %d while trying to mount SD\n", fres);
|
||||
panic2(0, PANIC_MOUNT);
|
||||
}
|
||||
|
||||
|
||||
irq_initialize();
|
||||
irq_enable(IRQ_TIMER);
|
||||
irq_enable(IRQ_NAND);
|
||||
irq_enable(IRQ_GPIO1B);
|
||||
irq_enable(IRQ_GPIO1);
|
||||
irq_enable(IRQ_RESET);
|
||||
irq_enable(IRQ_IPC);
|
||||
gecko_puts("Interrupts initialized\n");
|
||||
|
||||
gecko_puts("Trying to boot:" PPC_BOOT_FILE "\n");
|
||||
gecko_puts("Initializing IPC...\n");
|
||||
ipc_initialize();
|
||||
|
||||
write32(HW_IPC_PPCMSG, 0);
|
||||
write32(HW_IPC_ARMMSG, 0);
|
||||
write32(HW_IPC_PPCCTRL, IPC_CTRL_SENT|IPC_CTRL_RECV);
|
||||
write32(HW_IPC_ARMCTRL, IPC_CTRL_SENT|IPC_CTRL_RECV);
|
||||
gecko_puts("Mounting SD...\n");
|
||||
fres = f_mount(0, &fatfs);
|
||||
|
||||
if(fres != FR_OK) {
|
||||
gecko_printf("Error %d while trying to mount SD\n", fres);
|
||||
panic2(0, PANIC_MOUNT);
|
||||
}
|
||||
|
||||
gecko_puts("Trying to boot:" PPC_BOOT_FILE "\n");
|
||||
|
||||
res = powerpc_load_file(PPC_BOOT_FILE);
|
||||
if(res < 0) {
|
||||
@ -176,25 +179,16 @@ void *_main(void *base)
|
||||
gecko_puts("Continuing anyway\n");
|
||||
}
|
||||
|
||||
u32 tidh=0, tidl;
|
||||
|
||||
while(1) {
|
||||
if(read32(HW_IPC_ARMCTRL) & IPC_CTRL_RECV) {
|
||||
tidh = read32(HW_IPC_PPCMSG);
|
||||
write32(HW_IPC_ARMCTRL, read32(HW_IPC_ARMCTRL) | IPC_CTRL_RECV);
|
||||
}
|
||||
if(read32(HW_IPC_ARMCTRL) & IPC_CTRL_SENT) {
|
||||
tidl = read32(HW_IPC_PPCMSG);
|
||||
write32(HW_IPC_ARMCTRL, read32(HW_IPC_ARMCTRL) | IPC_CTRL_SENT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void *bootmii = patch_boot2(base, (((u64)tidh)<<32) | tidl);
|
||||
|
||||
gecko_puts("Shutting down interrupts\n");
|
||||
gecko_puts("Going into IPC mainloop...\n");
|
||||
ipc_process_slow();
|
||||
gecko_puts("IPC mainloop done!\n");
|
||||
gecko_puts("Shutting down IPC...\n");
|
||||
ipc_shutdown();
|
||||
gecko_puts("Shutting down interrupts...\n");
|
||||
irq_shutdown();
|
||||
|
||||
gecko_puts("Returning to BootMii...\n");
|
||||
return bootmii;
|
||||
|
||||
//vector = patch_boot2(base, (((u64)tidh)<<32) | tidl);
|
||||
|
||||
gecko_printf("Vectoring to %p...\n",vector);
|
||||
return vector;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user