diff --git a/include/hardware/pxi.h b/include/hardware/pxi.h index e13338d..6938d7b 100644 --- a/include/hardware/pxi.h +++ b/include/hardware/pxi.h @@ -18,45 +18,54 @@ * along with this program. If not, see . */ -#include "mem_map.h" #include "types.h" +#include "mem_map.h" #ifdef ARM9 -#define PXI_REGS_BASE (IO_MEM_ARM9_ONLY + 0x8000) +#define PXI_REGS_BASE (IO_MEM_ARM9_ONLY + 0x8000) #elif ARM11 -#define PXI_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x63000) +#define PXI_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x63000) #endif -#define REG_PXI_DATA_RECEIVED *((vu8 *)(PXI_REGS_BASE + 0x00)) -#define REG_PXI_DATA_SENT *((vu8 *)(PXI_REGS_BASE + 0x01)) -#define REG_PXI_SYNC *((vu32*)(PXI_REGS_BASE + 0x00)) -#define REG_PXI_CNT *((vu16*)(PXI_REGS_BASE + 0x04)) -#define REG_PXI_SEND *((vu32*)(PXI_REGS_BASE + 0x08)) -#define REG_PXI_RECV *((vu32*)(PXI_REGS_BASE + 0x0C)) +#define REG_PXI_SYNC_RECVD *((const vu8*)(PXI_REGS_BASE + 0x00)) +#define REG_PXI_SYNC_SENT *((vu8 *)(PXI_REGS_BASE + 0x01)) +#define REG_PXI_SYNC_IRQ *((vu8 *)(PXI_REGS_BASE + 0x03)) +#define REG_PXI_SYNC *((vu32*)(PXI_REGS_BASE + 0x00)) +#define REG_PXI_CNT *((vu16*)(PXI_REGS_BASE + 0x04)) +#define REG_PXI_SFIFO *((vu32*)(PXI_REGS_BASE + 0x08)) +#define REG_PXI_RFIFO *((const vu32*)(PXI_REGS_BASE + 0x0C)) -// Defines for PX_SYNC regs -#define PXI_DATA_RECEIVED (REG_PXI_SYNC & 0xFFu) -#define PXI_DATA_SENT(sent) ((REG_PXI_SYNC & ~(0xFFu<<8)) | (sent)<<8) +// REG_PXI_SYNC +#define PXI_SYNC_RECVD (REG_PXI_SYNC & 0xFFu) +#define PXI_SYNC_SENT(sent) ((REG_PXI_SYNC & ~(0xFFu<<8)) | (sent)<<8) #ifdef ARM9 -#define PXI_TRIGGER_SYNC_IRQ (1u<<29) +#define PXI_SYNC_IRQ (1u<<29) #elif ARM11 -#define PXI_TRIGGER_SYNC_IRQ (1u<<30) +#define PXI_SYNC_IRQ (1u<<30) #endif -#define PXI_IRQ_ENABLE (1u<<31) +#define PXI_SYNC_IRQ_ENABLE (1u<<31) -// Defines for PXI_CNT regs -#define PXI_SEND_FIFO_EMPTY (1u<<0) -#define PXI_SEND_FIFO_FULL (1u<<1) -#define PXI_SEND_FIFO_EMPTY_IRQ (1u<<2) -#define PXI_FLUSH_SEND_FIFO (1u<<3) -#define PXI_RECV_FIFO_EMPTY (1u<<8) -#define PXI_RECV_FIFO_FULL (1u<<9) -#define PXI_RECV_FIFO_NOT_EMPTY_IRQ (1u<<10) -#define PXI_EMPTY_FULL_ERROR (1u<<14) -#define PXI_ENABLE_SEND_RECV_FIFO (1u<<15) +// REG_PXI_SYNC_IRQ +#ifdef ARM9 +#define PXI_SYNC_IRQ_IRQ (1u<<5) +#elif ARM11 +#define PXI_SYNC_IRQ_IRQ (1u<<6) +#endif +#define PXI_SYNC_IRQ_IRQ_ENABLE (1u<<7) + +// REG_PXI_CNT +#define PXI_CNT_SFIFO_EMPTY (1u<<0) +#define PXI_CNT_SFIFO_FULL (1u<<1) +#define PXI_CNT_SFIFO_EMPTY_IRQ_ENABLE (1u<<2) +#define PXI_CNT_FLUSH_SFIFO (1u<<3) +#define PXI_CNT_RFIFO_EMPTY (1u<<8) +#define PXI_CNT_RFIFO_FULL (1u<<9) +#define PXI_CNT_RFIFO_NOT_EMPTY_IRQ_ENABLE (1u<<10) +#define PXI_CNT_FIFO_ERROR (1u<<14) // Also used for aknowledge +#define PXI_CNT_ENABLE_SRFIFO (1u<<15) void PXI_init(void); -u32 PXI_sendCmd(u32 cmd, const u32 *const buf, u32 words); +u32 PXI_sendCmd(u32 cmd, const u32 *buf, u32 words); diff --git a/source/arm11/firm.c b/source/arm11/firm.c index 65fd174..8896e8d 100644 --- a/source/arm11/firm.c +++ b/source/arm11/firm.c @@ -30,23 +30,17 @@ { *((vu32*)A11_FALLBACK_ENTRY) = 0; - REG_PXI_SYNC = 0; // Disable all IRQs // Tell ARM9 we are ready - REG_PXI_SEND = 0xA8E4u; + REG_PXI_SFIFO = 0xA8E4u; // Wait for entry address - while(REG_PXI_CNT & PXI_RECV_FIFO_EMPTY); - u32 entry = REG_PXI_RECV; + while(REG_PXI_CNT & PXI_CNT_RFIFO_EMPTY); + u32 entry = REG_PXI_RFIFO; // Tell ARM9 we got the entry - REG_PXI_SEND = 0x94C6u; - REG_PXI_CNT = 0; // Disable PXI + REG_PXI_SFIFO = 0x94C6u; - if(!entry) - { - while(!*((vu32*)A11_FALLBACK_ENTRY)); - entry = *((vu32*)A11_FALLBACK_ENTRY); - } + if(!entry) while(!(entry = *((vu32*)A11_FALLBACK_ENTRY))); ((void (*)(void))entry)(); } diff --git a/source/arm9/firm.c b/source/arm9/firm.c index c6c647e..8e59d4f 100644 --- a/source/arm9/firm.c +++ b/source/arm9/firm.c @@ -127,12 +127,11 @@ u32 entry11 = firm_hdr->entrypointarm11; - REG_PXI_SYNC = 0; // Disable all IRQs while(1) { // Wait for the ARM11 to be ready before copying sections - while(REG_PXI_CNT & PXI_RECV_FIFO_EMPTY); - if(REG_PXI_RECV == 0xA8E4u) break; + while(REG_PXI_CNT & PXI_CNT_RFIFO_EMPTY); + if(REG_PXI_RFIFO == 0xA8E4u) break; } for(u32 i = 0; i < 4; i++) @@ -170,17 +169,15 @@ REG_NDMA2_CNT & NDMA_ENABLE || REG_NDMA3_CNT & NDMA_ENABLE); // Tell ARM11 its entrypoint - REG_PXI_SEND = entry11; + REG_PXI_SFIFO = entry11; while(1) { // Wait for the ARM111 to confirm it received the entrypoint - while(REG_PXI_CNT & PXI_RECV_FIFO_EMPTY); - if(REG_PXI_RECV == 0x94C6u) break; + while(REG_PXI_CNT & PXI_CNT_RFIFO_EMPTY); + if(REG_PXI_RFIFO == 0x94C6u) break; } - REG_PXI_CNT = 0; // Disable PXI - // go for it! entry9(argc, argv, 0x3BEEFu); } diff --git a/source/hardware/pxi.c b/source/hardware/pxi.c index cc607ca..0b49f49 100644 --- a/source/hardware/pxi.c +++ b/source/hardware/pxi.c @@ -33,19 +33,41 @@ static void pxiIrqHandler(UNUSED u32 id); +static inline void pxiSendWord(u32 word) +{ + while(REG_PXI_CNT & PXI_CNT_SFIFO_FULL); + REG_PXI_SFIFO = word; +} + +static inline u32 pxiRecvWord(void) +{ + while(REG_PXI_CNT & PXI_CNT_RFIFO_EMPTY); + return REG_PXI_RFIFO; +} + +static inline bool pxiFifoError(void) +{ + return (REG_PXI_CNT & PXI_CNT_FIFO_ERROR) != 0; +} + +static inline void pxiSyncRequest(void) +{ + REG_PXI_SYNC_IRQ |= PXI_SYNC_IRQ_IRQ; +} + void PXI_init(void) { - REG_PXI_SYNC = PXI_IRQ_ENABLE; - REG_PXI_CNT = PXI_ENABLE_SEND_RECV_FIFO | PXI_EMPTY_FULL_ERROR | PXI_FLUSH_SEND_FIFO; + REG_PXI_SYNC = PXI_SYNC_IRQ_ENABLE; + REG_PXI_CNT = PXI_CNT_ENABLE_SRFIFO | PXI_CNT_FIFO_ERROR | PXI_CNT_FLUSH_SFIFO; #ifdef ARM9 - REG_PXI_DATA_SENT = 9; - while(REG_PXI_DATA_RECEIVED != 11); + REG_PXI_SYNC_SENT = 9; + while(REG_PXI_SYNC_RECVD != 11); IRQ_registerHandler(IRQ_PXI_SYNC, pxiIrqHandler); #elif ARM11 - while(REG_PXI_DATA_RECEIVED != 9); - REG_PXI_DATA_SENT = 11; + while(REG_PXI_SYNC_RECVD != 9); + REG_PXI_SYNC_SENT = 11; IRQ_registerHandler(IRQ_PXI_SYNC, 13, 0, true, pxiIrqHandler); #endif @@ -53,24 +75,21 @@ static void pxiIrqHandler(UNUSED u32 id) { - const u32 cmdCode = REG_PXI_RECV; + const u32 cmdCode = pxiRecvWord(); const u32 inBufs = IPC_CMD_IN_BUFS_MASK(cmdCode); const u32 outBufs = IPC_CMD_OUT_BUFS_MASK(cmdCode); const u32 params = IPC_CMD_PARAMS_MASK(cmdCode); - const u32 cmdBufSize = (inBufs * 2) + (outBufs * 2) + params; - if(cmdBufSize > IPC_MAX_PARAMS || cmdBufSize != REG_PXI_DATA_RECEIVED) - { - panic(); - } + const u32 words = (inBufs * 2) + (outBufs * 2) + params; + if(words > IPC_MAX_PARAMS) panic(); u32 buf[IPC_MAX_PARAMS]; - for(u32 i = 0; i < cmdBufSize; i++) buf[i] = REG_PXI_RECV; - if(REG_PXI_CNT & PXI_EMPTY_FULL_ERROR) panic(); + for(u32 i = 0; i < words; i++) buf[i] = pxiRecvWord(); + if(pxiFifoError()) panic(); - REG_PXI_SEND = IPC_handleCmd(IPC_CMD_ID_MASK(cmdCode), inBufs, outBufs, buf); + pxiSendWord(IPC_handleCmd(IPC_CMD_ID_MASK(cmdCode), inBufs, outBufs, buf)); } -u32 PXI_sendCmd(u32 cmd, const u32 *const buf, u32 words) +u32 PXI_sendCmd(u32 cmd, const u32 *buf, u32 words) { fb_assert(words <= IPC_MAX_PARAMS); @@ -88,15 +107,13 @@ if(outBuf->ptr && outBuf->size) invalidateDCacheRange(outBuf->ptr, outBuf->size); } - while(REG_PXI_CNT & PXI_SEND_FIFO_FULL); - REG_PXI_SEND = cmd; - for(u32 i = 0; i < words; i++) REG_PXI_SEND = buf[i]; - if(REG_PXI_CNT & PXI_EMPTY_FULL_ERROR) panic(); + pxiSendWord(cmd); + pxiSyncRequest(); - REG_PXI_SYNC = PXI_DATA_SENT(words) | PXI_TRIGGER_SYNC_IRQ; + while(words--) pxiSendWord(*buf++); + if(pxiFifoError()) panic(); - while(REG_PXI_CNT & PXI_RECV_FIFO_EMPTY); - const u32 res = REG_PXI_RECV; + const u32 res = pxiRecvWord(); #ifdef ARM11 // The CPU may do speculative prefetches of data after the first invalidation