diff --git a/common/include/iop_mmio_hwport.h b/common/include/iop_mmio_hwport.h new file mode 100644 index 00000000000..c0c653b469e --- /dev/null +++ b/common/include/iop_mmio_hwport.h @@ -0,0 +1,312 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +/** + * @file + * Definitions for memory-mapped I/O for IOP. + */ + +#ifndef __IOP_MMIO_HWPORT__ +#define __IOP_MMIO_HWPORT__ + +typedef struct dmac_channel_ +{ + vu32 madr; + vu32 bcr; + vu32 chcr; + vu32 tadr; +} dmac_channel_t; + +typedef struct dmac1_mmio_hwport_ +{ + dmac_channel_t oldch[7]; + vu32 dpcr1; + vu32 dicr1; +} dmac1_mmio_hwport_t; + +typedef struct dmac2_mmio_hwport_ +{ + dmac_channel_t newch[6]; + dmac_channel_t new_unusedch; + vu32 dpcr2; + vu32 dicr2; + vu32 dmacen; + vu32 dmacinten; +} dmac2_mmio_hwport_t; + +typedef struct dmac_channel3_ +{ + vu32 madr; + vu32 dlen; + vu32 slice; + vu32 chcr; + vu32 rtar; + vu32 DmarReadStart; + vu32 DmarReadEnd; +} dmac_channel3_t; + +typedef struct dmac3_mmio_hwport_ +{ + dmac_channel3_t dmac_channel3_0; + u8 unused_1c[0x4]; + dmac_channel3_t dmac_channel3_1; + u8 unused_3c[0x4]; + dmac_channel3_t dmac_channel3_2; + vu32 DmarWriteStart; + vu32 DmarWriteEnd; + u8 unused_64[0x1C]; +} dmac3_mmio_hwport_t; + +typedef struct ssbus1_mmio_hwport_ +{ + vu32 ind_0_address; + vu32 ind_8_address; + vu32 ind_0_delay; + vu32 ind_1_delay; + vu32 ind_2_delay; + vu32 ind_4_delay; + vu32 ind_5_delay; + vu32 ind_8_delay; + vu32 common_delay; +} ssbus1_mmio_hwport_t; + +typedef struct ssbus2_mmio_hwport_ +{ + vu32 ind_1_address; + vu32 ind_4_address; + vu32 ind_5_address; + vu32 ind_9_address; + vu32 ind_B_address; + vu32 ind_9_delay; + vu32 ind_A_delay; + vu32 ind_B_delay; + vu32 ind_C_delay; +} ssbus2_mmio_hwport_t; + +typedef struct sio0_1_mmio_hwport_ +{ + vu32 data; + vu32 stat; + vu16 mode; + vu16 ctrl; + vu16 misc; + vu16 baud; +} sio0_1_mmio_hwport_t; + +typedef struct sio2_mmio_hwport_ +{ + vu8 send3_buf[0x40]; + vu8 send1_2_buf[0x20]; + vu32 out_fifo; /* PCSX2 says in */ + vu32 in_fifo; /* PCSX2 says out */ + vu32 ctrl; + vu32 recv1; + vu32 recv2; + vu32 recv3; + vu32 unk_78; + vu32 unk_7c; + vu32 stat; + u8 unused[0x7c]; +} sio2_mmio_hwport_t; + +typedef struct usb_mmio_hwport_ +{ + vu32 HcRevision; + vu32 HcControl; + vu32 HcCommandStatus; + vu32 HcInterruptStatus; + vu32 HcInterruptEnable; + vu32 HcInterruptDisable; + vu32 HcHCCA; + vu32 HcPeriodCurrentEd; + vu32 HcControlHeadEd; + vu32 HcControlCurrentEd; + vu32 HcBulkHeadEd; + vu32 HcBulkCurrentEd; + vu32 HcDoneHead; + vu32 HcFmInterval; + vu32 HcFmRemaining; + vu32 HcFmNumber; + vu32 HcPeriodicStart; + vu32 HcLsThreshold; + vu32 HcRhDescriptorA; + vu32 HcRhDescriptorB; + vu32 HcRhStatus; + vu32 HcRhPortStatus[2]; /* PCSX2 says 15 or 11 */ + u8 unused[0xa4]; +} usb_mmio_hwport_t; + +typedef struct ieee1394_mmio_hwport_ +{ + vu32 NodeID; + vu32 CycleTime; + + vu32 ctrl0; + vu32 ctrl1; + vu32 ctrl2; + + vu32 PHYAccess; + + vu32 UnknownRegister18; + vu32 UnknownRegister1C; + + vu32 intr0; + vu32 intr0Mask; + + vu32 intr1; + vu32 intr1Mask; + + vu32 intr2; + vu32 intr2Mask; + + vu32 dmar; + vu32 ack_status; + vu32 ubufTransmitNext; + vu32 ubufTransmitLast; + vu32 ubufTransmitClear; + vu32 ubufReceiveClear; + vu32 ubufReceive; + vu32 ubufReceiveLevel; + + vu32 unmapped1[0x06]; + + vu32 UnknownRegister70; + vu32 UnknownRegister74; + vu32 UnknownRegister78; + vu32 UnknownRegister7C; + + vu32 PHT_ctrl_ST_R0; + vu32 PHT_split_TO_R0; + vu32 PHT_ReqResHdr0_R0; + vu32 PHT_ReqResHdr1_R0; + vu32 PHT_ReqResHdr2_R0; + + vu32 STRxNIDSel0_R0; + vu32 STRxNIDSel1_R0; + + vu32 STRxHDR_R0; + vu32 STTxHDR_R0; + + vu32 DTransCTRL0; + vu32 CIPHdrTx0_R0; + vu32 CIPHdrTx1_R0; + + vu32 padding4; + vu32 STTxTimeStampOffs_R0; + + vu32 dmaCtrlSR0; + vu32 dmaTransTRSH0; + vu32 dbufFIFO_lvlR0; + vu32 dbufTxDataR0; + vu32 dbufRxDataR0; + + vu32 dbufWatermarksR0; + vu32 dbufFIFOSzR0; + + vu32 unmapped2[0x0B]; + + vu32 PHT_ctrl_ST_R1; + vu32 PHT_split_TO_R1; + vu32 PHT_ReqResHdr0_R1; + vu32 PHT_ReqResHdr1_R1; + vu32 PHT_ReqResHdr2_R1; + + vu32 STRxNIDSel0_R1; + vu32 STRxNIDSel1_R1; + + vu32 STRxHDR_R1; + vu32 STTxHDR_R1; + + vu32 DTransCTRL1; + vu32 CIPHdrTx0_R1; + vu32 CIPHdrTx1_R1; + + vu32 padding5; + vu32 STTxTimeStampOffs_R1; + + vu32 dmaCtrlSR1; + vu32 dmaTransTRSH1; + vu32 dbufFIFO_lvlR1; + vu32 dbufTxDataR1; + vu32 dbufRxDataR1; + + vu32 dbufWatermarksR1; + vu32 dbufFIFOSzR1; +} ieee1394_mmio_hwport_t; + +typedef struct iop_counter_mmio_hwport_ +{ + vu32 count; + vu32 mode; + vu32 target; + vu32 unused_c; +} iop_counter_mmio_hwport_t; + +typedef struct iop_mmio_hwport_ /* base -> 0xBF800000 */ +{ + u8 scratchpad_cache0[0x400]; + u8 scratchpad_cache1[0x400]; + u8 unv_0800[0x800]; + ssbus1_mmio_hwport_t ssbus1; /* 0x1000 */ + u8 unv_1024[0x1c]; + sio0_1_mmio_hwport_t sio0; + sio0_1_mmio_hwport_t sio1; + vu32 iop_ram_size; + u8 unv_1064[0xC]; + vu32 istat; + vu32 imask; + vu32 iop_sbus_info; + vu32 unk_107c; + dmac1_mmio_hwport_t dmac1; /* 0x1080 */ + u8 unv_10f8[0x8]; + iop_counter_mmio_hwport_t counter1[3]; /* 0x1100 */ + u8 unv_1130[0x2d0]; + ssbus2_mmio_hwport_t ssbus2; /* 0x1400 */ + u8 unv_1424[0x2c]; + vu32 iop_sbus_ctrl[2]; /* 0x1450 */ + u8 unk_1458[0x8]; + u8 dev9c[0x20]; + iop_counter_mmio_hwport_t counter2[3]; /* 0x1480 */ + u8 unk_14b0[0x10]; + vu32 rtc_holdmode; + u8 unk_14c4[0x3c]; + dmac2_mmio_hwport_t dmac2; /* 0x1500 */ + dmac3_mmio_hwport_t dmac3; /* 0x1580 */ + usb_mmio_hwport_t usb; /* 0x1600 */ + u8 unk_1700[0x100]; + vu32 ps1_cdrom; + u8 unk_1804[0xc]; + vu32 ps1_gpu1; + vu32 ps1_gpu2; + u8 unk_1818[0x8]; + vu32 ps1_mdec1; + vu32 ps1_mdec2; + u8 unk_1828[0x8]; + u8 unk_1830[0xd0]; + u8 deckard_i2c[0x20]; /* 0x1900 */ + u8 unv_1920[0x2e0]; + u8 spu_core0[0x400]; /* 0x1C00 */ + u8 exp2_r2[0x2000]; /* 0x2000 */ + u8 unk_4000[0x4000]; + u8 sio2_internal[0x200]; /* 0x8000 */ + sio2_mmio_hwport_t sio2; /* 0x8200 */ + u8 unk_8300[0x100]; + ieee1394_mmio_hwport_t ieee1394; /* 0x8400 */ +} iop_mmio_hwport_t; + +#if !defined(USE_IOP_MMIO_HWPORT) && defined(_IOP) +// cppcheck-suppress-macro constVariablePointer +#define USE_IOP_MMIO_HWPORT() iop_mmio_hwport_t *const iop_mmio_hwport = (iop_mmio_hwport_t *)0xBF800000 +#endif +#if !defined(USE_IOP_MMIO_HWPORT) +#define USE_IOP_MMIO_HWPORT() +#endif + +#endif /* __IOP_MMIO_HWPORT__ */ diff --git a/common/include/sif_mmio_hwport.h b/common/include/sif_mmio_hwport.h new file mode 100644 index 00000000000..008e25969b3 --- /dev/null +++ b/common/include/sif_mmio_hwport.h @@ -0,0 +1,49 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +/** + * @file + * Definitions for memory-mapped I/O for SIF. + */ + +#ifndef __SIF_MMIO_HWPORT__ +#define __SIF_MMIO_HWPORT__ + +typedef struct sif_mmio_hwport_ /* base -> 0xBD000000 */ +{ + vu32 mscom; + u32 unused04[3]; + vu32 smcom; + u32 unused14[3]; + vu32 msflag; + u32 unused24[3]; + vu32 smflag; + u32 unused34[3]; + vu32 controlreg; + u32 unused44[7]; + vu32 unk60; + u32 unused64[3]; +} sif_mmio_hwport_t; + +#if !defined(USE_SIF_MMIO_HWPORT) && defined(_EE) +// cppcheck-suppress-macro constVariablePointer +#define USE_SIF_MMIO_HWPORT() \ + sif_mmio_hwport_t *const sif_mmio_hwport = (sif_mmio_hwport_t *)0xB000F200 +#endif +#if !defined(USE_SIF_MMIO_HWPORT) && defined(_IOP) +// cppcheck-suppress-macro constVariablePointer +#define USE_SIF_MMIO_HWPORT() \ + sif_mmio_hwport_t *const sif_mmio_hwport = (sif_mmio_hwport_t *)0xBD000000 +#endif +#if !defined(USE_SIF_MMIO_HWPORT) +#define USE_SIF_MMIO_HWPORT() +#endif + +#endif /* __SIF_MMIO_HWPORT__ */ diff --git a/iop/kernel/include/sifcmd.h b/iop/kernel/include/sifcmd.h index b848fe08c11..c4ee6dcb1be 100644 --- a/iop/kernel/include/sifcmd.h +++ b/iop/kernel/include/sifcmd.h @@ -40,13 +40,14 @@ typedef struct t_SifCmdHeader { /* System functions */ #define SIF_CMD_ID_SYSTEM 0x80000000 -#define SIF_CMD_SET_SREG (SIF_CMD_ID_SYSTEM | 1) -#define SIF_CMD_INIT_CMD (SIF_CMD_ID_SYSTEM | 2) -#define SIF_CMD_RESET_CMD (SIF_CMD_ID_SYSTEM | 3) -#define SIF_CMD_RPC_END (SIF_CMD_ID_SYSTEM | 8) -#define SIF_CMD_RPC_BIND (SIF_CMD_ID_SYSTEM | 9) -#define SIF_CMD_RPC_CALL (SIF_CMD_ID_SYSTEM | 10) -#define SIF_CMD_RPC_RDATA (SIF_CMD_ID_SYSTEM | 12) +#define SIF_CMD_CHANGE_SADDR (SIF_CMD_ID_SYSTEM | 0) +#define SIF_CMD_SET_SREG (SIF_CMD_ID_SYSTEM | 1) +#define SIF_CMD_INIT_CMD (SIF_CMD_ID_SYSTEM | 2) +#define SIF_CMD_RESET_CMD (SIF_CMD_ID_SYSTEM | 3) +#define SIF_CMD_RPC_END (SIF_CMD_ID_SYSTEM | 8) +#define SIF_CMD_RPC_BIND (SIF_CMD_ID_SYSTEM | 9) +#define SIF_CMD_RPC_CALL (SIF_CMD_ID_SYSTEM | 10) +#define SIF_CMD_RPC_RDATA (SIF_CMD_ID_SYSTEM | 12) //System SREG #define SIF_SREG_RPCINIT 0 @@ -76,7 +77,7 @@ typedef struct t_SifCmdSysHandlerData void sceSifInitCmd(void); void sceSifExitCmd(void); -void sceSifGetSreg(int index); +unsigned int sceSifGetSreg(int index); void sceSifSetSreg(int index, unsigned int value); void sceSifSetCmdBuffer(SifCmdHandlerData_t *cmdBuffer, int size); void sceSifSetSysCmdBuffer(SifCmdSysHandlerData_t *sysCmdBuffer, int size); @@ -93,6 +94,66 @@ void sceSifAddCmdHandler(int cid, SifCmdHandler_t handler, void *harg); typedef void * (*SifRpcFunc_t)(int fno, void *buffer, int length); typedef void (*SifRpcEndFunc_t)(void *end_param); +typedef struct t_SifRpcPktHeader +{ + struct t_SifCmdHeader sifcmd; + int rec_id; + void *pkt_addr; + int rpc_id; +} SifRpcPktHeader_t; + +typedef struct t_SifRpcRendPkt +{ + struct t_SifCmdHeader sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + + struct t_SifRpcClientData *client; /* 7 */ + u32 cid; /* 8 */ + struct t_SifRpcServerData *server; /* 9 */ + void *buff, /* 10 */ + *cbuff; /* 11 */ +} SifRpcRendPkt_t; + +typedef struct t_SifRpcOtherDataPkt +{ + struct t_SifCmdHeader sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + + struct t_SifRpcReceiveData *receive; /* 07 */ + void *src; /* 08 */ + void *dest; /* 09 */ + int size; /* 10 */ +} SifRpcOtherDataPkt_t; + +typedef struct t_SifRpcBindPkt +{ + struct t_SifCmdHeader sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + struct t_SifRpcClientData *client; /* 07 */ + int sid; /* 08 */ +} SifRpcBindPkt_t; + +typedef struct t_SifRpcCallPkt +{ + struct t_SifCmdHeader sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + struct t_SifRpcClientData *client; /* 07 */ + int rpc_number; /* 08 */ + int send_size; /* 09 */ + void *receive; /* 10 */ + int recv_size; /* 11 */ + int rmode; /* 12 */ + struct t_SifRpcServerData *server; /* 13 */ +} SifRpcCallPkt_t; + typedef struct t_SifRpcServerData { int sid; @@ -177,7 +238,7 @@ int sceSifGetOtherData(SifRpcReceiveData_t *rd, void *src, void *dest, int size, SifRpcServerData_t *sceSifRemoveRpc(SifRpcServerData_t *sd, SifRpcDataQueue_t *qd); SifRpcDataQueue_t *sceSifRemoveRpcQueue(SifRpcDataQueue_t *qd); -void sceSifSetSif1CB(void *func, int param); +void sceSifSetSif1CB(void (*func)(void *userdata), void *userdata); void sceSifClearSif1CB(void); unsigned int sceSifSendCmdIntr(int cmd, void *packet, int packet_size, void *src_extra, void *dest_extra, int size_extra, void (*completioncb)(void *userdata), void *userdata); diff --git a/iop/system/Makefile b/iop/system/Makefile index 43dd1adae0f..3bf92b5557a 100644 --- a/iop/system/Makefile +++ b/iop/system/Makefile @@ -11,9 +11,6 @@ SUBDIRS = \ dmacman \ eesync \ eesync-nano \ - threadman \ - timrman \ - timrmanp \ ioman \ iomanx \ iopmgr \ @@ -28,6 +25,9 @@ SUBDIRS = \ rpadman \ rsio2man \ sbusintr \ + sifcmd \ + sifinit \ + sifman \ siftoo \ sio2log \ sio2man \ @@ -37,6 +37,9 @@ SUBDIRS = \ sysclib \ sysclib-full \ sysclib-nano \ + threadman \ + timrman \ + timrmanp \ udnl \ udnl-t300 diff --git a/iop/system/sifcmd/Makefile b/iop/system/sifcmd/Makefile new file mode 100644 index 00000000000..4d3ac992241 --- /dev/null +++ b/iop/system/sifcmd/Makefile @@ -0,0 +1,16 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +IOP_BIN ?= sifcmd.irx + +IOP_OBJS = sifcmd.o sifrpc.o exports.o imports.o + +include $(PS2SDKSRC)/Defs.make +include $(PS2SDKSRC)/iop/Rules.bin.make +include $(PS2SDKSRC)/iop/Rules.make +include $(PS2SDKSRC)/iop/Rules.release diff --git a/iop/system/sifcmd/README.md b/iop/system/sifcmd/README.md new file mode 100644 index 00000000000..d21dd300861 --- /dev/null +++ b/iop/system/sifcmd/README.md @@ -0,0 +1,17 @@ +# SIF CMD + +This module provides functions to handle CoMmanDs and Remote Procedure Calls through Subsystem InterFace. + +## Configurations + +There are multiple configurations of this library, allowing the choice of +balancing between size, speed, and features. + +* `sifcmd` -> The recommended version. + +## How to use this module in your program + +In order to use this module in your program, you must integrate the module into +an IOPRP image, then load the image with `UDNL`.\ +Using `LoadModule` or `LoadModuleBuffer` directly will not work, because the +module is already loaded at IOP boot. diff --git a/iop/system/sifcmd/src/exports.tab b/iop/system/sifcmd/src/exports.tab new file mode 100644 index 00000000000..84c2be3a4e7 --- /dev/null +++ b/iop/system/sifcmd/src/exports.tab @@ -0,0 +1,37 @@ + +DECLARE_EXPORT_TABLE(sifcmd, 1, 1) +DECLARE_EXPORT(_start) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(sifcmd_deinit) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(sceSifInitCmd) +DECLARE_EXPORT(sceSifExitCmd) +DECLARE_EXPORT(sceSifGetSreg) +DECLARE_EXPORT(sceSifSetSreg) +DECLARE_EXPORT(sceSifSetCmdBuffer) +DECLARE_EXPORT(sceSifSetSysCmdBuffer) +DECLARE_EXPORT(sceSifAddCmdHandler) +DECLARE_EXPORT(sceSifRemoveCmdHandler) +DECLARE_EXPORT(sceSifSendCmd) +DECLARE_EXPORT(isceSifSendCmd) +DECLARE_EXPORT(sceSifInitRpc) +DECLARE_EXPORT(sceSifBindRpc) +DECLARE_EXPORT(sceSifCallRpc) +DECLARE_EXPORT(sceSifRegisterRpc) +DECLARE_EXPORT(sceSifCheckStatRpc) +DECLARE_EXPORT(sceSifSetRpcQueue) +DECLARE_EXPORT(sceSifGetNextRequest) +DECLARE_EXPORT(sceSifExecRequest) +DECLARE_EXPORT(sceSifRpcLoop) +DECLARE_EXPORT(sceSifGetOtherData) +DECLARE_EXPORT(sceSifRemoveRpc) +DECLARE_EXPORT(sceSifRemoveRpcQueue) +DECLARE_EXPORT(sceSifSetSif1CB) +DECLARE_EXPORT(sceSifClearSif1CB) +DECLARE_EXPORT(sceSifSendCmdIntr) +DECLARE_EXPORT(isceSifSendCmdIntr) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(_retonly) +END_EXPORT_TABLE + +void _retonly() {} diff --git a/iop/system/sifcmd/src/imports.lst b/iop/system/sifcmd/src/imports.lst new file mode 100644 index 00000000000..f1600f315af --- /dev/null +++ b/iop/system/sifcmd/src/imports.lst @@ -0,0 +1,44 @@ + +loadcore_IMPORTS_start +I_RegisterLibraryEntries +I_QueryBootMode +loadcore_IMPORTS_end + +intrman_IMPORTS_start +I_RegisterIntrHandler +I_ReleaseIntrHandler +I_EnableIntr +I_DisableIntr +I_CpuSuspendIntr +I_CpuResumeIntr +intrman_IMPORTS_end + +stdio_IMPORTS_start +I_printf +stdio_IMPORTS_end + +sifman_IMPORTS_start +/* 0x00401bc0 2 */ +I_sceSifInit +I_sceSifSetDChain +I_sceSifSetDma +I_sceSifSetMSFlag +I_sceSifSetSMFlag +I_sceSifSetSubAddr +I_sceSifCheckInit +I_sceSifSetDmaIntr +sifman_IMPORTS_end + +thbase_IMPORTS_start +I_SleepThread +I_iWakeupThread +I_iSetAlarm +I_GetSystemStatusFlag +thbase_IMPORTS_end + +thevent_IMPORTS_start +I_CreateEventFlag +I_iSetEventFlag +I_ClearEventFlag +I_WaitEventFlag +thevent_IMPORTS_end diff --git a/iop/system/sifcmd/src/irx_imports.h b/iop/system/sifcmd/src/irx_imports.h new file mode 100644 index 00000000000..58a0b36d937 --- /dev/null +++ b/iop/system/sifcmd/src/irx_imports.h @@ -0,0 +1,27 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# Defines all IRX imports. +*/ + +#ifndef IOP_IRX_IMPORTS_H +#define IOP_IRX_IMPORTS_H + +#include + +/* Please keep these in alphabetical order! */ + +#include +#include +#include +#include +#include +#include + +#endif /* IOP_IRX_IMPORTS_H */ diff --git a/iop/system/sifcmd/src/sifcmd.c b/iop/system/sifcmd/src/sifcmd.c new file mode 100644 index 00000000000..313c46c0843 --- /dev/null +++ b/iop/system/sifcmd/src/sifcmd.c @@ -0,0 +1,421 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#include "irx_imports.h" +#include "sifcmd.h" + +extern struct irx_export_table _exp_sifcmd; + +#ifdef _IOP +IRX_ID("IOP_SIF_rpc_interface", 2, 8); +#endif +// Based on the module from SCE SDK 3.1.0. + +typedef struct sif_cmd_data_ +{ + void *pktbuf; + void *unused; + int sif_send_eebuf; + SifCmdSysHandlerData_t *sys_cmd_handlers; + int nr_sys_handlers; + SifCmdHandlerData_t *usr_cmd_handlers; + int nr_usr_handlers; + unsigned int *sregs_ptr; + int ef; + void (*sif_1_callback)(void *userdata); + void *sif_1_callback_userdata; + SifCmdSysHandlerData_t sys_cmd_handler_handler[32]; + unsigned int sregs[32]; +} sif_cmd_data_t; + +typedef struct t_SifCmdChgAddrData +{ + SifCmdHeader_t header; + u32 newaddr; +} SifCmdChgAddrData_t; + +static sif_cmd_data_t sif_cmd_data; +static u8 sif_iop_recvbuf[0x80]; +static u8 sif_unused[0x40]; + +static int sif_cmd_int_handler(sif_cmd_data_t *sci); + +static void sif_sys_cmd_handler_set_sreg(const SifCmdSRegData_t *pkt, sif_cmd_data_t *sci) +{ + sci->sregs_ptr[pkt->index] = pkt->value; +} + +static void sif_sys_cmd_handler_change_addr(const SifCmdChgAddrData_t *pkt, sif_cmd_data_t *sci) +{ + sci->sif_send_eebuf = pkt->newaddr; +} + +unsigned int sceSifGetSreg(int index) +{ + return sif_cmd_data.sregs[index]; +} + +void sceSifSetSreg(int index, unsigned int value) +{ + sif_cmd_data.sregs[index] = value; +} + +#if 0 +sif_cmd_data_t *sif_cmd_get_internal_data() +{ + return &sif_cmd_data; +} +#endif + +static void sif_sys_cmd_handler_init_from_ee(const SifCmdChgAddrData_t *pkt, sif_cmd_data_t *sci) +{ + if ( pkt->header.opt ) + { + iSetEventFlag(sci->ef, 0x800u); + } + else + { + iSetEventFlag(sci->ef, 0x100u); + sceSifSetMSFlag(SIF_STAT_CMDINIT); + sci->sif_send_eebuf = pkt->newaddr; + } +} + +int _start(int ac, char **av) +{ + const int *BootMode3; + + (void)ac; + (void)av; + + BootMode3 = QueryBootMode(3); + if ( BootMode3 ) + { + int BootMode3_1; + + BootMode3_1 = BootMode3[1]; + if ( (BootMode3_1 & 1) != 0 ) + { + printf(" No SIF service(sifcmd)\n"); + return 1; + } + if ( (BootMode3_1 & 2) != 0 ) + { + printf(" No SIFCMD/RPC service\n"); + return 1; + } + } + if ( !sceSifCheckInit() ) + sceSifInit(); + if ( RegisterLibraryEntries(&_exp_sifcmd) == 0 ) + { + unsigned int i; + + sif_cmd_data.pktbuf = sif_iop_recvbuf; + sif_cmd_data.unused = sif_unused; + sif_cmd_data.sys_cmd_handlers = sif_cmd_data.sys_cmd_handler_handler; + sif_cmd_data.nr_sys_handlers = + sizeof(sif_cmd_data.sys_cmd_handler_handler) / sizeof(sif_cmd_data.sys_cmd_handler_handler[0]); + sif_cmd_data.sif_send_eebuf = 0; + sif_cmd_data.usr_cmd_handlers = 0; + sif_cmd_data.nr_usr_handlers = 0; + sif_cmd_data.sregs_ptr = sif_cmd_data.sregs; + sif_cmd_data.sif_1_callback = 0; + sif_cmd_data.sif_1_callback_userdata = 0; + for ( i = 0; i < sizeof(sif_cmd_data.sys_cmd_handler_handler) / sizeof(sif_cmd_data.sys_cmd_handler_handler[0]); + i += 1 ) + { + sif_cmd_data.sys_cmd_handler_handler[i].handler = NULL; + sif_cmd_data.sys_cmd_handler_handler[i].harg = NULL; + } + for ( i = 0; i < sizeof(sif_cmd_data.sregs) / sizeof(sif_cmd_data.sregs[0]); i += 1 ) + { + sif_cmd_data.sregs[i] = 0; + } + sif_cmd_data.sys_cmd_handler_handler[0].handler = (SifCmdHandler_t)sif_sys_cmd_handler_change_addr; + sif_cmd_data.sys_cmd_handler_handler[0].harg = &sif_cmd_data; + sif_cmd_data.sys_cmd_handler_handler[1].handler = (SifCmdHandler_t)sif_sys_cmd_handler_set_sreg; + sif_cmd_data.sys_cmd_handler_handler[1].harg = &sif_cmd_data; + sif_cmd_data.ef = GetSystemStatusFlag(); + sif_cmd_data.sys_cmd_handler_handler[2].handler = (SifCmdHandler_t)sif_sys_cmd_handler_init_from_ee; + sif_cmd_data.sys_cmd_handler_handler[2].harg = &sif_cmd_data; + RegisterIntrHandler(IOP_IRQ_DMA_SIF1, 1, (int (*)(void *))sif_cmd_int_handler, &sif_cmd_data); + EnableIntr(0x22B); + sceSifSetSubAddr((u32)sif_iop_recvbuf); + return 0; + } + return 1; +} + +int sifcmd_deinit(void) +{ + int old_irq; + + DisableIntr(IOP_IRQ_DMA_SIF1, &old_irq); + ReleaseIntrHandler(IOP_IRQ_DMA_SIF1); +#if 0 + // FIXME: Do we really need this call? + sifman_2(); +#endif + return 0; +} + +void sceSifInitCmd(void) +{ + sceSifSetSMFlag(SIF_STAT_CMDINIT); + WaitEventFlag(sif_cmd_data.ef, 0x100u, 0, 0); +} + +void sceSifExitCmd(void) +{ + int old_irq; + + DisableIntr(IOP_IRQ_DMA_SIF1, &old_irq); + ReleaseIntrHandler(IOP_IRQ_DMA_SIF1); +} + +void sceSifSetCmdBuffer(SifCmdHandlerData_t *cmdBuffer, int size) +{ + sif_cmd_data.usr_cmd_handlers = cmdBuffer; + sif_cmd_data.nr_usr_handlers = size; +} + +void sceSifSetSysCmdBuffer(SifCmdSysHandlerData_t *sysCmdBuffer, int size) +{ + sif_cmd_data.sys_cmd_handlers = sysCmdBuffer; + sif_cmd_data.nr_sys_handlers = size; +} + +void sceSifAddCmdHandler(int cid, SifCmdHandler_t handler, void *harg) +{ + if ( cid >= 0 ) + { + sif_cmd_data.usr_cmd_handlers[cid].handler = handler; + sif_cmd_data.usr_cmd_handlers[cid].harg = harg; + } + else + { + sif_cmd_data.sys_cmd_handlers[cid + (cid & 0x7FFFFFFF)].handler = handler; + sif_cmd_data.sys_cmd_handlers[cid + (cid & 0x7FFFFFFF)].harg = harg; + } +} + +void sceSifRemoveCmdHandler(int cid) +{ + if ( cid >= 0 ) + sif_cmd_data.usr_cmd_handlers[cid].handler = NULL; + else + sif_cmd_data.sys_cmd_handlers[cid + (cid & 0x7FFFFFFF)].handler = NULL; +} + +static int sif_send_cmd_common( + int cmd, + char flags, + SifCmdHeader_t *packet, + int packet_size, + void *src_extra, + void *dest_extra, + int size_extra, + void (*completion_cb)(void *), + void *completion_cb_userdata) +{ + int dmatc1; + SifDmaTransfer_t *dmatp; + int dmatc2; + int sif_send_eebuf; + unsigned int dmar1; + SifDmaTransfer_t dmat[2]; + int state; + + if ( (unsigned int)(packet_size - 16) >= 0x61 ) + return 0; + dmatc1 = 0; + if ( size_extra <= 0 ) + { + int tmp1; + + tmp1 = *(u8 *)packet; + packet->dest = 0; + *(u32 *)packet = tmp1; + } + else + { + int tmp2; + + dmatc1 = 1; + dmat[0].dest = dest_extra; + dmat[0].size = size_extra; + dmat[0].attr = 0; + dmat[0].src = src_extra; + tmp2 = *(u8 *)packet; + packet->dest = dest_extra; + *(u32 *)packet = tmp2 | (size_extra << 8); + } + dmatp = &dmat[dmatc1]; + dmatc2 = dmatc1 + 1; + *(u8 *)packet = packet_size; + packet->cid = cmd; + dmatp->src = packet; + sif_send_eebuf = sif_cmd_data.sif_send_eebuf; + dmatp->attr = 4; + dmatp->size = packet_size; + dmatp->dest = (void *)sif_send_eebuf; + if ( (flags & 1) != 0 ) + { + if ( (flags & 8) != 0 ) + return sceSifSetDmaIntr(dmat, dmatc2, completion_cb, completion_cb_userdata); + else + return sceSifSetDma(dmat, dmatc2); + } + else + { + unsigned int dmar2; + + CpuSuspendIntr(&state); + if ( (flags & 8) != 0 ) + dmar2 = sceSifSetDmaIntr(dmat, dmatc2, completion_cb, completion_cb_userdata); + else + dmar2 = sceSifSetDma(dmat, dmatc2); + dmar1 = dmar2; + CpuResumeIntr(state); + } + return dmar1; +} + +unsigned int sceSifSendCmd(int cmd, void *packet, int packet_size, void *src_extra, void *dest_extra, int size_extra) +{ + return sif_send_cmd_common(cmd, 0, (SifCmdHeader_t *)packet, packet_size, src_extra, dest_extra, size_extra, 0, 0); +} + +unsigned int sceSifSendCmdIntr( + int cmd, + void *packet, + int packet_size, + void *src_extra, + void *dest_extra, + int size_extra, + void (*completion_cb)(void *), + void *completion_cb_userdata) +{ + return sif_send_cmd_common( + cmd, + 8, + (SifCmdHeader_t *)packet, + packet_size, + src_extra, + dest_extra, + size_extra, + (void (*)(void *))completion_cb, + completion_cb_userdata); +} + +unsigned int isceSifSendCmd(int cmd, void *packet, int packet_size, void *src_extra, void *dest_extra, int size_extra) +{ + return sif_send_cmd_common(cmd, 1, (SifCmdHeader_t *)packet, packet_size, src_extra, dest_extra, size_extra, 0, 0); +} + +unsigned int isceSifSendCmdIntr( + int cmd, + void *packet, + int packet_size, + void *src_extra, + void *dest_extra, + int size_extra, + void (*completion_cb)(void *), + void *completion_cb_userdata) +{ + return sif_send_cmd_common( + cmd, + 9, + (SifCmdHeader_t *)packet, + packet_size, + src_extra, + dest_extra, + size_extra, + (void (*)(void *))completion_cb, + completion_cb_userdata); +} + +void sceSifSetSif1CB(void (*func)(void *userdata), void *userdata) +{ + sif_cmd_data.sif_1_callback = func; + sif_cmd_data.sif_1_callback_userdata = userdata; +} + +void sceSifClearSif1CB(void) +{ + sif_cmd_data.sif_1_callback = NULL; + sif_cmd_data.sif_1_callback_userdata = NULL; +} + +static int sif_cmd_int_handler(sif_cmd_data_t *sci) +{ + void (*sif_1_callback)(void *); + SifCmdHeader_t *pktbuf1; + int size; + int size_calc1; + SifCmdHeader_t *pktbuf2; + int pktwords; + int i; + u32 tmp1; + u32 tmpbuf1[32]; + + sif_1_callback = sci->sif_1_callback; + if ( sif_1_callback ) + sif_1_callback(sci->sif_1_callback_userdata); + pktbuf1 = (SifCmdHeader_t *)sci->pktbuf; + size = *(u8 *)sci->pktbuf; + if ( !*(u8 *)sci->pktbuf ) + { + sceSifSetDChain(); + return 1; + } + *(u8 *)pktbuf1 = 0; + size_calc1 = size + 3; + pktbuf2 = pktbuf1; + if ( size + 3 < 0 ) + size_calc1 = size + 6; + pktwords = size_calc1 >> 2; + i = 0; + tmpbuf1[2] = 0; + if ( size_calc1 >> 2 > 0 ) + { + u32 *tmpptr1; + + tmpptr1 = tmpbuf1; + do + { + tmp1 = *(u32 *)pktbuf2; + pktbuf2 = (SifCmdHeader_t *)((char *)pktbuf2 + 4); + ++i; + *tmpptr1++ = tmp1; + } while ( i < pktwords ); + } + sceSifSetDChain(); + if ( (tmpbuf1[2] & 0x80000000) == 0 ) + { + if ( (int)tmpbuf1[2] < sci->nr_usr_handlers ) + { + if ( sif_cmd_data.usr_cmd_handlers[tmpbuf1[2]].handler != NULL ) + { + sif_cmd_data.usr_cmd_handlers[tmpbuf1[2]].handler(tmpbuf1, sif_cmd_data.usr_cmd_handlers[tmpbuf1[2]].harg); + } + } + } + else if ( (signed int)(tmpbuf1[2] & 0x7FFFFFFF) < sci->nr_sys_handlers ) + { + if ( sif_cmd_data.sys_cmd_handlers[tmpbuf1[2] + (tmpbuf1[2] & 0x7FFFFFFF)].handler != NULL ) + { + sif_cmd_data.sys_cmd_handlers[tmpbuf1[2] + (tmpbuf1[2] & 0x7FFFFFFF)].handler( + tmpbuf1, sif_cmd_data.usr_cmd_handlers[tmpbuf1[2] + (tmpbuf1[2] & 0x7FFFFFFF)].harg); + } + } + return 1; +} diff --git a/iop/system/sifcmd/src/sifrpc.c b/iop/system/sifcmd/src/sifrpc.c new file mode 100644 index 00000000000..b2cba0abc45 --- /dev/null +++ b/iop/system/sifcmd/src/sifrpc.c @@ -0,0 +1,771 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#include "irx_imports.h" +#include "sifcmd.h" + +typedef struct sif_rpc_data_ +{ + int pid; + void *pkt_table; + int pkt_table_len; + int unused1; + int unused2; + u8 *rdata_table; + int rdata_table_len; + u8 *client_table; + int client_table_len; + int rdata_table_idx; + SifRpcDataQueue_t *active_queue; + int sif_rpc_sema_ef; + int used_sema_bitfield; +} sif_rpc_data_t; + +static sif_rpc_data_t sif_rpc_data; +static u32 init = 0; +static u8 pkt_table[0x800]; +static u8 rdata_table[0x800]; +static u8 client_data[0x800]; + +static void sif_cmd_handler_end(SifRpcRendPkt_t *data, sif_rpc_data_t *harg); +static void sif_cmd_handler_bind(SifRpcBindPkt_t *data, sif_rpc_data_t *harg); +static void sif_cmd_handler_call(SifRpcCallPkt_t *data, sif_rpc_data_t *harg); +static void sif_cmd_handler_rdata(SifRpcOtherDataPkt_t *data, sif_rpc_data_t *harg); + +void sceSifInitRpc(int mode) +{ + int SystemStatusFlag; + iop_event_t efp; + int state; + + (void)mode; + + sceSifInitCmd(); + CpuSuspendIntr(&state); + if ( init ) + { + CpuResumeIntr(state); + } + else + { + sif_rpc_data.rdata_table = (u8 *)rdata_table; + init = 1; + sif_rpc_data.pkt_table = pkt_table; + sif_rpc_data.pkt_table_len = 32; + sif_rpc_data.unused1 = 0; + sif_rpc_data.unused2 = 0; + sif_rpc_data.rdata_table_len = 32; + sif_rpc_data.client_table = (u8 *)client_data; + sif_rpc_data.client_table_len = 32; + sif_rpc_data.rdata_table_idx = 0; + sif_rpc_data.pid = 1; + sceSifAddCmdHandler(SIF_CMD_RPC_END, (SifCmdHandler_t)sif_cmd_handler_end, &sif_rpc_data); + sceSifAddCmdHandler(SIF_CMD_RPC_BIND, (SifCmdHandler_t)sif_cmd_handler_bind, &sif_rpc_data); + sceSifAddCmdHandler(SIF_CMD_RPC_CALL, (SifCmdHandler_t)sif_cmd_handler_call, &sif_rpc_data); + sceSifAddCmdHandler(SIF_CMD_RPC_RDATA, (SifCmdHandler_t)sif_cmd_handler_rdata, &sif_rpc_data); + efp.attr = EA_MULTI; + efp.bits = 0; + sif_rpc_data.sif_rpc_sema_ef = CreateEventFlag(&efp); + sif_rpc_data.used_sema_bitfield = 0; + CpuResumeIntr(state); + pkt_table[4] = 0; + pkt_table[5] = 1; + sceSifSendCmd(SIF_CMD_SET_SREG, pkt_table, 24, 0, 0, 0); + } + SystemStatusFlag = GetSystemStatusFlag(); + WaitEventFlag(SystemStatusFlag, 0x800u, 0, 0); +} + +static int sif_rpc_get_sema(sif_rpc_data_t *rpc_data) +{ + int i; + int state; + + CpuSuspendIntr(&state); + for ( i = 0; i < 32; ++i ) + { + int used_sema_bitfield; + + used_sema_bitfield = rpc_data->used_sema_bitfield; + if ( (used_sema_bitfield & ((u32)1 << i)) == 0 ) + { + rpc_data->used_sema_bitfield = used_sema_bitfield | (1 << i); + CpuResumeIntr(state); + return i; + } + } + CpuResumeIntr(state); + return -1; +} + +static int sif_rpc_free_sema(sif_rpc_data_t *rpc_data, char sema_id) +{ + int state; + + CpuSuspendIntr(&state); + rpc_data->used_sema_bitfield &= ~(1 << sema_id); + return CpuResumeIntr(state); +} + +static SifRpcPktHeader_t *sif_rpc_packet_get(sif_rpc_data_t *rpc_data) +{ + SifRpcPktHeader_t *pkt_table_0; + int i; + int state; + + CpuSuspendIntr(&state); + pkt_table_0 = (SifRpcPktHeader_t *)rpc_data->pkt_table; + i = 0; + if ( rpc_data->pkt_table_len <= 0 ) + { + CpuResumeIntr(state); + return 0; + } + else + { + void **p_pkt_addr; + int pid; + int pid_1_tmp; + + p_pkt_addr = &pkt_table_0->pkt_addr; + while ( ((unsigned int)*(p_pkt_addr - 1) & 2) != 0 ) + { + ++i; + p_pkt_addr += 16; + pkt_table_0 = (SifRpcPktHeader_t *)((char *)pkt_table_0 + 64); + if ( i >= rpc_data->pkt_table_len ) + { + CpuResumeIntr(state); + return 0; + } + } + *(p_pkt_addr - 1) = (void *)((i << 16) | 6); + pid = rpc_data->pid; + pid_1_tmp = rpc_data->pid + 1; + rpc_data->pid = pid_1_tmp; + if ( pid_1_tmp == 1 ) + { + pid_1_tmp = 1; + rpc_data->pid = pid + 2; + } + p_pkt_addr[1] = (void *)pid_1_tmp; + *p_pkt_addr = pkt_table_0; + CpuResumeIntr(state); + return pkt_table_0; + } +} + +static void sif_rpc_packet_free(SifRpcRendPkt_t *pkt) +{ + pkt->rpc_id = 0; + pkt->rec_id &= 0xFFFFFFFD; +} + +static void *sif_rpc_get_fpacket(sif_rpc_data_t *rpc_data) +{ + int rdata_table_idx; + int rdata_table_len; + int index_calc; + + rdata_table_idx = rpc_data->rdata_table_idx; + rdata_table_len = rpc_data->rdata_table_len; + index_calc = rdata_table_idx % rdata_table_len; + if ( rdata_table_len == -1 && (u32)rdata_table_idx == 0x80000000 ) + __asm__("break\n"); + rpc_data->rdata_table_idx = index_calc + 1; + return &rpc_data->rdata_table[64 * index_calc]; +} + +static void *sif_rpc_get_fpacket2(sif_rpc_data_t *rpc_data, int rid) +{ + if ( rid >= 0 && rid < rpc_data->client_table_len ) + return &rpc_data->client_table[64 * rid]; + else + return sif_rpc_get_fpacket(rpc_data); +} + +static void sif_cmd_handler_end(SifRpcRendPkt_t *data, sif_rpc_data_t *harg) +{ + u32 cid; + SifRpcClientData_t *client1; + SifRpcEndFunc_t end_function; + SifRpcClientData_t *client2; + SifRpcClientData_t *client3; + int sema_id; + + cid = data->cid; + if ( cid == SIF_CMD_RPC_CALL ) + { + client1 = data->client; + end_function = client1->end_function; + if ( end_function ) + end_function(client1->end_param); + } + else if ( cid == SIF_CMD_RPC_BIND ) + { + client2 = data->client; + client2->server = data->server; + client2->buff = data->buff; + } + client3 = data->client; + sema_id = client3->hdr.sema_id; + if ( sema_id >= 0 ) + iSetEventFlag(harg->sif_rpc_sema_ef, 1 << sema_id); + sif_rpc_packet_free((SifRpcRendPkt_t *)client3->hdr.pkt_addr); + client3->hdr.pkt_addr = 0; +} + +static unsigned int sif_cmd_handler_rdata_alarm_retry(SifRpcRendPkt_t *a1) +{ + if ( isceSifSendCmd(SIF_CMD_RPC_END, a1, 64, a1->server, a1->buff, (int)a1->cbuff) != 0 ) + return 0; + return 0xF000; +} + +static void sif_cmd_handler_rdata(SifRpcOtherDataPkt_t *data, sif_rpc_data_t *harg) +{ + unsigned int rec_id; + SifRpcRendPkt_t *fpacket2; + SifRpcClientData_t *receive; + iop_sys_clock_t clk; + + rec_id = data->rec_id; + if ( (rec_id & 4) != 0 ) + fpacket2 = (SifRpcRendPkt_t *)sif_rpc_get_fpacket2(harg, (rec_id >> 16) & 0xFFFF); + else + fpacket2 = (SifRpcRendPkt_t *)sif_rpc_get_fpacket(harg); + fpacket2->pkt_addr = data->pkt_addr; + receive = (SifRpcClientData_t *)data->receive; + fpacket2->cid = SIF_CMD_RPC_RDATA; + fpacket2->client = receive; + fpacket2->server = (SifRpcServerData_t *)data->src; + fpacket2->buff = data->dest; + fpacket2->cbuff = (void *)data->size; + if ( !isceSifSendCmd(SIF_CMD_RPC_END, fpacket2, 64, data->src, data->dest, data->size) ) + { + clk.hi = 0; + clk.lo = 0xF000; + iSetAlarm(&clk, (unsigned int (*)(void *))sif_cmd_handler_rdata_alarm_retry, fpacket2); + } +} + +int sceSifGetOtherData(SifRpcReceiveData_t *rd, void *src, void *dest, int size, int mode) +{ + SifRpcOtherDataPkt_t *other; + + other = (SifRpcOtherDataPkt_t *)sif_rpc_packet_get(&sif_rpc_data); + if ( other ) + { + rd->hdr.pkt_addr = other; + rd->hdr.rpc_id = other->rpc_id; + other->pkt_addr = other; + other->receive = rd; + other->src = src; + other->dest = dest; + other->size = size; + if ( (mode & SIF_RPC_M_NOWAIT) != 0 ) + { + rd->hdr.sema_id = -1; + if ( sceSifSendCmd(SIF_CMD_RPC_RDATA, other, 64, 0, 0, 0) == 0 ) + { + sif_rpc_packet_free((SifRpcRendPkt_t *)other); + return -2; + } + return 0; + } + else + { + int sema; + + sema = sif_rpc_get_sema(&sif_rpc_data); + rd->hdr.sema_id = sema; + if ( sema >= 0 ) + { + if ( sceSifSendCmd(SIF_CMD_RPC_RDATA, other, 64, 0, 0, 0) ) + { + WaitEventFlag(sif_rpc_data.sif_rpc_sema_ef, 1 << rd->hdr.sema_id, 0, 0); + ClearEventFlag(sif_rpc_data.sif_rpc_sema_ef, ~(1 << rd->hdr.sema_id)); + sif_rpc_free_sema(&sif_rpc_data, rd->hdr.sema_id); + return 0; + } + else + { + sif_rpc_packet_free((SifRpcRendPkt_t *)other); + sif_rpc_free_sema(&sif_rpc_data, rd->hdr.sema_id); + return -2; + } + } + else + { + sif_rpc_packet_free((SifRpcRendPkt_t *)other); + return -4; + } + } + } + return -1; +} + +static SifRpcServerData_t *sif_search_svdata(int sid, const sif_rpc_data_t *rpc_data) +{ + const SifRpcDataQueue_t *queue; + SifRpcServerData_t *server; + + queue = rpc_data->active_queue; + while ( queue ) + { + server = queue->link; + while ( server ) + { + if ( server->sid == sid ) + return server; + server = server->link; + } + queue = queue->next; + } + + return NULL; +} + +static unsigned int sif_cmd_handler_bind_alarm_retry(void *a1) +{ + if ( isceSifSendCmd(SIF_CMD_RPC_END, a1, 64, 0, 0, 0) != 0 ) + return 0; + return 0xF000; +} + +static void sif_cmd_handler_bind(SifRpcBindPkt_t *data, sif_rpc_data_t *harg) +{ + SifRpcRendPkt_t *fpacket; + SifRpcClientData_t *client; + SifRpcServerData_t *server; + iop_sys_clock_t clk; + + fpacket = (SifRpcRendPkt_t *)sif_rpc_get_fpacket(harg); + fpacket->pkt_addr = data->pkt_addr; + client = data->client; + fpacket->cid = SIF_CMD_RPC_BIND; + fpacket->client = client; + server = sif_search_svdata(data->sid, harg); + if ( server ) + { + fpacket->server = server; + fpacket->buff = server->buff; + } + else + { + fpacket->server = 0; + fpacket->buff = 0; + } + if ( !isceSifSendCmd(SIF_CMD_RPC_END, fpacket, 64, 0, 0, 0) ) + { + clk.hi = 0; + clk.lo = 0xF000; + iSetAlarm(&clk, (unsigned int (*)(void *))sif_cmd_handler_bind_alarm_retry, fpacket); + } +} + +int sceSifBindRpc(SifRpcClientData_t *client, int rpc_number, int mode) +{ + SifRpcBindPkt_t *bind; + + client->command = 0; + client->server = 0; + bind = (SifRpcBindPkt_t *)sif_rpc_packet_get(&sif_rpc_data); + if ( bind ) + { + client->hdr.pkt_addr = bind; + client->hdr.rpc_id = bind->rpc_id; + bind->pkt_addr = bind; + bind->client = client; + bind->sid = rpc_number; + if ( (mode & SIF_RPC_M_NOWAIT) != 0 ) + { + client->hdr.sema_id = -1; + if ( sceSifSendCmd(SIF_CMD_RPC_BIND, bind, 64, 0, 0, 0) == 0 ) + { + sif_rpc_packet_free((SifRpcRendPkt_t *)bind); + return -2; + } + return 0; + } + else + { + int sema; + + sema = sif_rpc_get_sema(&sif_rpc_data); + client->hdr.sema_id = sema; + if ( sema >= 0 ) + { + if ( sceSifSendCmd(SIF_CMD_RPC_BIND, bind, 64, 0, 0, 0) ) + { + WaitEventFlag(sif_rpc_data.sif_rpc_sema_ef, 1 << client->hdr.sema_id, 0, 0); + ClearEventFlag(sif_rpc_data.sif_rpc_sema_ef, ~(1 << client->hdr.sema_id)); + sif_rpc_free_sema(&sif_rpc_data, client->hdr.sema_id); + return 0; + } + else + { + sif_rpc_packet_free((SifRpcRendPkt_t *)bind); + sif_rpc_free_sema(&sif_rpc_data, client->hdr.sema_id); + return -2; + } + } + else + { + sif_rpc_packet_free((SifRpcRendPkt_t *)bind); + return -4; + } + } + } + return -1; +} + +static void sif_cmd_handler_call(SifRpcCallPkt_t *data, sif_rpc_data_t *harg) +{ + SifRpcServerData_t *server; + SifRpcDataQueue_t *base; + + (void)harg; + + server = data->server; + base = server->base; + if ( base->start ) + base->end->next = server; + else + base->start = server; + base->end = server; + server->pkt_addr = data->pkt_addr; + server->client = data->client; + server->rpc_number = data->rpc_number; + server->size = data->send_size; + server->receive = data->receive; + server->rsize = data->recv_size; + server->rmode = data->rmode; + server->rid = data->rec_id; + if ( base->thread_id >= 0 && !base->active ) + iWakeupThread(base->thread_id); +} + +int sceSifCallRpc( + SifRpcClientData_t *client, + int rpc_number, + int mode, + void *send, + int ssize, + void *receive, + int rsize, + SifRpcEndFunc_t end_function, + void *end_param) +{ + SifRpcCallPkt_t *call; + + call = (SifRpcCallPkt_t *)sif_rpc_packet_get(&sif_rpc_data); + if ( call ) + { + int rpc_id; + + client->hdr.pkt_addr = call; + rpc_id = call->rpc_id; + client->end_function = end_function; + client->end_param = end_param; + client->hdr.rpc_id = rpc_id; + call->pkt_addr = call; + call->client = client; + call->rpc_number = rpc_number; + call->send_size = ssize; + call->receive = receive; + call->recv_size = rsize; + call->server = client->server; + if ( (mode & SIF_RPC_M_NOWAIT) != 0 ) + { + void *dest_extra; + + if ( end_function ) + call->rmode = 1; + else + call->rmode = 0; + dest_extra = client->buff; + client->hdr.sema_id = -1; + if ( sceSifSendCmd(SIF_CMD_RPC_CALL, call, 64, send, dest_extra, ssize) == 0 ) + { + sif_rpc_packet_free((SifRpcRendPkt_t *)call); + return -2; + } + return 0; + } + else + { + int sema; + + call->rmode = 1; + sema = sif_rpc_get_sema(&sif_rpc_data); + client->hdr.sema_id = sema; + if ( sema >= 0 ) + { + if ( sceSifSendCmd(SIF_CMD_RPC_CALL, call, 64, send, client->buff, ssize) ) + { + WaitEventFlag(sif_rpc_data.sif_rpc_sema_ef, 1 << client->hdr.sema_id, 0, 0); + ClearEventFlag(sif_rpc_data.sif_rpc_sema_ef, ~(1 << client->hdr.sema_id)); + sif_rpc_free_sema(&sif_rpc_data, client->hdr.sema_id); + return 0; + } + else + { + sif_rpc_packet_free((SifRpcRendPkt_t *)call); + sif_rpc_free_sema(&sif_rpc_data, client->hdr.sema_id); + return -2; + } + } + else + { + sif_rpc_packet_free((SifRpcRendPkt_t *)call); + return -4; + } + } + } + return -1; +} + +int sceSifCheckStatRpc(SifRpcClientData_t *cd) +{ + const SifRpcPktHeader_t *pkt_addr; + + pkt_addr = (SifRpcPktHeader_t *)cd->hdr.pkt_addr; + return cd->hdr.pkt_addr && (int)(cd->hdr.rpc_id) == pkt_addr->rpc_id && (pkt_addr->rec_id & 2) != 0; +} + +SifRpcDataQueue_t *sceSifSetRpcQueue(SifRpcDataQueue_t *q, int thread_id) +{ + SifRpcDataQueue_t *queue; + int state; + + CpuSuspendIntr(&state); + q->thread_id = thread_id; + q->active = 0; + q->link = 0; + q->start = 0; + q->end = 0; + q->next = 0; + if ( sif_rpc_data.active_queue ) + { + for ( queue = sif_rpc_data.active_queue; queue->next; queue = queue->next ) + ; + queue->next = q; + } + else + { + sif_rpc_data.active_queue = q; + } + return (SifRpcDataQueue_t *)CpuResumeIntr(state); +} + +void sceSifRegisterRpc( + SifRpcServerData_t *sd, int sid, SifRpcFunc_t func, void *buf, SifRpcFunc_t cfunc, void *cbuf, SifRpcDataQueue_t *qd) +{ + SifRpcServerData_t *server; + int state; + + CpuSuspendIntr(&state); + sd->sid = sid; + sd->func = func; + sd->buff = buf; + sd->next = 0; + sd->link = 0; + sd->cfunc = cfunc; + sd->cbuff = cbuf; + sd->base = qd; + server = qd->link; + if ( server ) + { + for ( ; server->link; server = server->link ) + ; + server->link = sd; + } + else + { + qd->link = sd; + } + CpuResumeIntr(state); +} + +SifRpcServerData_t *sceSifRemoveRpc(SifRpcServerData_t *sd, SifRpcDataQueue_t *qd) +{ + SifRpcServerData_t *server1; + const SifRpcServerData_t *server2; + int state; + + CpuSuspendIntr(&state); + server1 = qd->link; + if ( server1 == sd ) + { + qd->link = server1->link; + } + else if ( server1 ) + { + while ( 1 ) + { + server2 = server1->link; + if ( server2 == sd ) + { + server1->link = server2->link; + break; + } + server1 = server1->link; + if ( !server2 ) + { + break; + } + } + } + CpuResumeIntr(state); + return server1; +} + +SifRpcDataQueue_t *sceSifRemoveRpcQueue(SifRpcDataQueue_t *qd) +{ + SifRpcDataQueue_t *queue1; + const SifRpcDataQueue_t *queue2; + int state; + + CpuSuspendIntr(&state); + queue1 = sif_rpc_data.active_queue; + if ( sif_rpc_data.active_queue == qd ) + { + sif_rpc_data.active_queue = sif_rpc_data.active_queue->next; + } + else if ( sif_rpc_data.active_queue ) + { + while ( 1 ) + { + queue2 = queue1->next; + if ( queue2 == qd ) + { + queue1->next = queue2->next; + break; + } + queue1 = queue1->next; + if ( !queue2 ) + break; + } + } + CpuResumeIntr(state); + return queue1; +} + +SifRpcServerData_t *sceSifGetNextRequest(SifRpcDataQueue_t *qd) +{ + SifRpcServerData_t *server; + int state; + + CpuSuspendIntr(&state); + server = qd->start; + if ( server ) + { + qd->active = 1; + qd->start = server->next; + } + else + { + qd->active = 0; + } + CpuResumeIntr(state); + return server; +} + +void sceSifExecRequest(SifRpcServerData_t *srv) +{ + int size_extra; + void *rec; + unsigned int rid; + SifRpcRendPkt_t *fpacket2; + SifRpcRendPkt_t *rend; + SifRpcClientData_t *client; + int exsz; + void *receive; + void *pkt_addr; + SifDmaTransfer_t dmat2[2]; + int state[2]; + + size_extra = 0; + rec = (void *)srv->func(srv->rpc_number, srv->buff, srv->size); + if ( rec ) + size_extra = srv->rsize; + CpuSuspendIntr(state); + rid = srv->rid; + if ( (rid & 4) != 0 ) + fpacket2 = (SifRpcRendPkt_t *)sif_rpc_get_fpacket2(&sif_rpc_data, (rid >> 16) & 0xFFFF); + else + fpacket2 = (SifRpcRendPkt_t *)sif_rpc_get_fpacket(&sif_rpc_data); + rend = fpacket2; + CpuResumeIntr(state[0]); + client = srv->client; + rend->cid = SIF_CMD_RPC_CALL; + rend->client = client; + exsz = 0; + if ( srv->rmode ) + { + while ( !sceSifSendCmd(SIF_CMD_RPC_END, rend, 64, rec, srv->receive, size_extra) ) + ; + } + else + { + int exsz1; + int exsz2; + SifDmaTransfer_t *dmat1; + + rend->rpc_id = 0; + rend->rec_id = 0; + if ( size_extra > 0 ) + { + exsz = 1; + dmat2[0].src = rec; + receive = srv->receive; + dmat2[0].size = size_extra; + dmat2[0].attr = 0; + dmat2[0].dest = receive; + } + exsz1 = exsz; + exsz2 = exsz + 1; + dmat1 = &dmat2[exsz1]; + dmat1->src = rend; + pkt_addr = srv->pkt_addr; + dmat1->size = 64; + dmat1->attr = 0; + dmat1->dest = pkt_addr; + while ( 1 ) + { + int dmar; + int busywait; + + CpuSuspendIntr(state); + dmar = sceSifSetDma(dmat2, exsz2); + CpuResumeIntr(state[0]); + if ( dmar ) + break; + busywait = 0xFFFE; + while ( busywait-- != -1 ) + ; + } + } +} + +void sceSifRpcLoop(SifRpcDataQueue_t *qd) +{ + while ( 1 ) + { + SifRpcServerData_t *server; + + server = sceSifGetNextRequest(qd); + if ( server ) + sceSifExecRequest(server); + else + SleepThread(); + } +} diff --git a/iop/system/sifinit/Makefile b/iop/system/sifinit/Makefile new file mode 100644 index 00000000000..1969619e372 --- /dev/null +++ b/iop/system/sifinit/Makefile @@ -0,0 +1,16 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +IOP_BIN ?= sifinit.irx + +IOP_OBJS = sifinit.o imports.o + +include $(PS2SDKSRC)/Defs.make +include $(PS2SDKSRC)/iop/Rules.bin.make +include $(PS2SDKSRC)/iop/Rules.make +include $(PS2SDKSRC)/iop/Rules.release diff --git a/iop/system/sifinit/README.md b/iop/system/sifinit/README.md new file mode 100644 index 00000000000..203818cf913 --- /dev/null +++ b/iop/system/sifinit/README.md @@ -0,0 +1,17 @@ +# SIF Initialization + +This module initializes SIF. + +## Configurations + +There are multiple configurations of this library, allowing the choice of +balancing between size, speed, and features. + +* `sifinit` -> The recommended version. + +## How to use this module in your program + +In order to use this module in your program, you must integrate the module into +an IOPRP image, then load the image with `UDNL`.\ +Using `LoadModule` or `LoadModuleBuffer` directly will not work, because the +module is already loaded at IOP boot. diff --git a/iop/system/sifinit/src/imports.lst b/iop/system/sifinit/src/imports.lst new file mode 100644 index 00000000000..d8b53206748 --- /dev/null +++ b/iop/system/sifinit/src/imports.lst @@ -0,0 +1,12 @@ + +loadcore_IMPORTS_start +I_QueryBootMode +loadcore_IMPORTS_end + +stdio_IMPORTS_start +I_printf +stdio_IMPORTS_end + +sifman_IMPORTS_start +I_sceSifInit +sifman_IMPORTS_end diff --git a/iop/system/sifinit/src/irx_imports.h b/iop/system/sifinit/src/irx_imports.h new file mode 100644 index 00000000000..446920c596d --- /dev/null +++ b/iop/system/sifinit/src/irx_imports.h @@ -0,0 +1,24 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# Defines all IRX imports. +*/ + +#ifndef IOP_IRX_IMPORTS_H +#define IOP_IRX_IMPORTS_H + +#include + +/* Please keep these in alphabetical order! */ + +#include +#include +#include + +#endif /* IOP_IRX_IMPORTS_H */ diff --git a/iop/system/sifinit/src/sifinit.c b/iop/system/sifinit/src/sifinit.c new file mode 100644 index 00000000000..7a808110002 --- /dev/null +++ b/iop/system/sifinit/src/sifinit.c @@ -0,0 +1,47 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#include "irx_imports.h" + +#ifdef _IOP +IRX_ID("SifInit", 1, 1); +#endif +// Based on the module from SCE SDK 1.3.4. + +int _start(int ac, char **av) +{ + const int *BootMode3; + + (void)ac; + (void)av; + + BootMode3 = QueryBootMode(3); + if ( BootMode3 && (BootMode3[1] & 1) != 0 ) + { + printf(" Skip SIF init\n"); + return 1; + } + else + { + const int *BootMode1; + + BootMode1 = QueryBootMode(1); + if ( BootMode1 && *(const u16 *)BootMode1 == 1 ) + { + printf(" Skip SIF init (it is DECI1)\n"); + return 1; + } + else + { + sceSifInit(); + return 1; + } + } +} diff --git a/iop/system/sifman/Makefile b/iop/system/sifman/Makefile new file mode 100644 index 00000000000..edf97b28174 --- /dev/null +++ b/iop/system/sifman/Makefile @@ -0,0 +1,16 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +IOP_BIN ?= sifman.irx + +IOP_OBJS = sifman.o exports.o imports.o + +include $(PS2SDKSRC)/Defs.make +include $(PS2SDKSRC)/iop/Rules.bin.make +include $(PS2SDKSRC)/iop/Rules.make +include $(PS2SDKSRC)/iop/Rules.release diff --git a/iop/system/sifman/README.md b/iop/system/sifman/README.md new file mode 100644 index 00000000000..63188f2cd03 --- /dev/null +++ b/iop/system/sifman/README.md @@ -0,0 +1,17 @@ +# SIF Manager + +This module provides functions to manage the Subsystem InterFace (SIF). + +## Configurations + +There are multiple configurations of this library, allowing the choice of +balancing between size, speed, and features. + +* `sifman` -> The recommended version. + +## How to use this module in your program + +In order to use this module in your program, you must integrate the module into +an IOPRP image, then load the image with `UDNL`.\ +Using `LoadModule` or `LoadModuleBuffer` directly will not work, because the +module is already loaded at IOP boot. diff --git a/iop/system/sifman/src/exports.tab b/iop/system/sifman/src/exports.tab new file mode 100644 index 00000000000..abd6f867c0b --- /dev/null +++ b/iop/system/sifman/src/exports.tab @@ -0,0 +1,41 @@ + +DECLARE_EXPORT_TABLE(sifman, 1, 1) +DECLARE_EXPORT(_start) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(sifman_deinit) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(sceSifDma2Init) +DECLARE_EXPORT(sceSifInit) +DECLARE_EXPORT(sceSifSetDChain) +DECLARE_EXPORT(sceSifSetDma) +DECLARE_EXPORT(sceSifDmaStat) +DECLARE_EXPORT(sceSifSetOneDma) +DECLARE_EXPORT(sceSifSendSync) +DECLARE_EXPORT(sceSifIsSending) +DECLARE_EXPORT(sceSifDma0Transfer) +DECLARE_EXPORT(sceSifDma0Sync) +DECLARE_EXPORT(sceSifDma0Sending) +DECLARE_EXPORT(sceSifDma1Transfer) +DECLARE_EXPORT(sceSifDma1Sync) +DECLARE_EXPORT(sceSifDma1Sending) +DECLARE_EXPORT(sceSifDma2Transfer) +DECLARE_EXPORT(sceSifDma2Sync) +DECLARE_EXPORT(sceSifDma2Sending) +DECLARE_EXPORT(sceSifGetMSFlag) +DECLARE_EXPORT(sceSifSetMSFlag) +DECLARE_EXPORT(sceSifGetSMFlag) +DECLARE_EXPORT(sceSifSetSMFlag) +DECLARE_EXPORT(sceSifGetMainAddr) +DECLARE_EXPORT(sceSifGetSubAddr) +DECLARE_EXPORT(sceSifSetSubAddr) +DECLARE_EXPORT(sceSifIntrMain) +DECLARE_EXPORT(sceSifCheckInit) +DECLARE_EXPORT(sceSifSetDmaIntrHandler) +DECLARE_EXPORT(sceSifResetDmaIntrHandler) +DECLARE_EXPORT(sceSifSetDmaIntr) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(_retonly) +END_EXPORT_TABLE + +void _retonly() {} diff --git a/iop/system/sifman/src/imports.lst b/iop/system/sifman/src/imports.lst new file mode 100644 index 00000000000..82cf1881846 --- /dev/null +++ b/iop/system/sifman/src/imports.lst @@ -0,0 +1,14 @@ + +loadcore_IMPORTS_start +I_RegisterLibraryEntries +loadcore_IMPORTS_end + +intrman_IMPORTS_start +I_RegisterIntrHandler +I_ReleaseIntrHandler +I_EnableIntr +I_DisableIntr +I_CpuSuspendIntr +I_CpuResumeIntr +I_QueryIntrContext +intrman_IMPORTS_end diff --git a/iop/system/sifman/src/irx_imports.h b/iop/system/sifman/src/irx_imports.h new file mode 100644 index 00000000000..d5c0fba6bda --- /dev/null +++ b/iop/system/sifman/src/irx_imports.h @@ -0,0 +1,23 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# Defines all IRX imports. +*/ + +#ifndef IOP_IRX_IMPORTS_H +#define IOP_IRX_IMPORTS_H + +#include + +/* Please keep these in alphabetical order! */ + +#include +#include + +#endif /* IOP_IRX_IMPORTS_H */ diff --git a/iop/system/sifman/src/sifman.c b/iop/system/sifman/src/sifman.c new file mode 100644 index 00000000000..6690ebd3172 --- /dev/null +++ b/iop/system/sifman/src/sifman.c @@ -0,0 +1,651 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#include "irx_imports.h" +#include "sifman.h" + +#include "iop_mmio_hwport.h" +#include "sif_mmio_hwport.h" + +extern struct irx_export_table _exp_sifman; + +#ifdef _IOP +IRX_ID("IOP_SIF_manager", 2, 5); +#endif +// Based on the module from SCE SDK 3.1.0. + +typedef struct sif_info_ +{ + int data; + int words; + int count; + int addr; +} sif_info_t; + +typedef struct sif_completion_cb_info_ +{ + void (*func)(void *userdata); + void *userdata; +} sif_completion_cb_info_t; + +typedef struct sif_completion_cb_info_arr_ +{ + sif_completion_cb_info_t info[32]; + int count; +} sif_completion_cb_info_arr_t; + +typedef struct sifman_internals_ +{ + u16 dma_count; + // cppcheck-suppress unusedStructMember + char unused02[2]; + int dmatag_index; + sif_info_t *sif_curbuf; + sif_info_t sif_buf1[32]; + sif_info_t sif_buf2[32]; + sif_completion_cb_info_arr_t *sif_otherbufcom; + sif_completion_cb_info_arr_t *sif_curbufcom; + sif_completion_cb_info_arr_t sif_bufcom1; + sif_completion_cb_info_arr_t sif_bufcom2; + void (*dma_intr_handler)(void *userdata); + void *dma_intr_handler_userdata; + // cppcheck-suppress unusedStructMember + char field_624[4]; + sif_info_t one; + // cppcheck-suppress unusedStructMember + char field_638[8]; +} sifman_internals_t; + +static sifman_internals_t sifman_internals; +static u32 sif_dma2_inited = 0; +static u32 sif_inited = 0; + +#define PRID $15 + +#define _mfc0(reg) \ + ({ \ + u32 val; \ + __asm__ volatile("mfc0 %0, " #reg : "=r"(val)); \ + val; \ + }) + +#define mfc0(reg) _mfc0(reg) + +int _start(int ac, char **av) +{ + s32 prid; + USE_IOP_MMIO_HWPORT(); + USE_SIF_MMIO_HWPORT(); + + (void)ac; + (void)av; + + prid = mfc0(PRID); + if ( prid >= 16 ) + { + if ( (iop_mmio_hwport->iop_sbus_ctrl[0] & 8) == 0 ) + { + if ( sif_mmio_hwport->unk60 == 0x1D000060 ) + return RegisterLibraryEntries(&_exp_sifman) != 0; + if ( (sif_mmio_hwport->unk60 & 0xFFFFF000) == 0 ) + return RegisterLibraryEntries(&_exp_sifman) != 0; + } + } + return 1; +} + +static u32 get_msflag() +{ + u32 result; + USE_SIF_MMIO_HWPORT(); + + for ( result = sif_mmio_hwport->msflag; result != sif_mmio_hwport->msflag; result = sif_mmio_hwport->msflag ) + ; + return result; +} + +static u32 get_smflag() +{ + u32 result; + USE_SIF_MMIO_HWPORT(); + + for ( result = sif_mmio_hwport->smflag; result != sif_mmio_hwport->smflag; result = sif_mmio_hwport->smflag ) + ; + return result; +} + +void sceSifDma2Init() +{ + USE_IOP_MMIO_HWPORT(); + + if ( !sif_dma2_inited ) + { + iop_mmio_hwport->dmac1.oldch[2].chcr = 0; + iop_mmio_hwport->dmac1.dpcr1 |= 0x800; + sif_dma2_inited = 1; + } +} + +static int sif_dma_init(void); + +void sceSifInit() +{ + u32 msflag; + int state; + USE_IOP_MMIO_HWPORT(); + USE_SIF_MMIO_HWPORT(); + + if ( !sif_inited ) + { + iop_mmio_hwport->dmac2.dpcr2 |= 0x8800; + iop_mmio_hwport->dmac2.newch[2].chcr = 0; + iop_mmio_hwport->dmac2.newch[3].chcr = 0; + sceSifDma2Init(); + if ( (iop_mmio_hwport->iop_sbus_ctrl[0] & 0x10) != 0 ) + { + iop_mmio_hwport->iop_sbus_ctrl[0] |= 0x10; + } + iop_mmio_hwport->iop_sbus_ctrl[0] |= 1; + sif_dma_init(); + do + { + CpuSuspendIntr(&state); + msflag = get_msflag(); + CpuResumeIntr(state); + } while ( (msflag & SIF_STAT_SIFINIT) == 0 ); + sceSifSetDChain(); + sceSifSetSubAddr(0); + sif_mmio_hwport->smflag = SIF_STAT_SIFINIT; + sif_inited = 1; + } +} + +int sifman_deinit() +{ + int old_irq; + USE_IOP_MMIO_HWPORT(); + + DisableIntr(IOP_IRQ_DMA_SIF0, &old_irq); + ReleaseIntrHandler(IOP_IRQ_DMA_SIF0); + iop_mmio_hwport->dmac2.newch[2].chcr = 0; + iop_mmio_hwport->dmac2.newch[3].chcr = 0; + if ( iop_mmio_hwport->iop_sbus_ctrl[0] & 0x10 ) + { + iop_mmio_hwport->iop_sbus_ctrl[0] |= 0x10; + } + return 0; +} + +int sceSifCheckInit() +{ + return sif_inited; +} + +void sceSifSetDChain() +{ + USE_IOP_MMIO_HWPORT(); + USE_SIF_MMIO_HWPORT(); + + if ( (sif_mmio_hwport->controlreg & 0x40) == 0 ) + sif_mmio_hwport->controlreg = 64; + iop_mmio_hwport->dmac2.newch[3].chcr = 0; + iop_mmio_hwport->dmac2.newch[3].bcr = (iop_mmio_hwport->dmac2.newch[3].bcr & 0xFFFF0000) | 32; + iop_mmio_hwport->dmac2.newch[3].chcr = 0x41000300; +} + +void sceSifSetDmaIntrHandler(void (*handler)(void *userdata), void *arg) +{ + sifman_internals.dma_intr_handler = handler; + sifman_internals.dma_intr_handler_userdata = arg; +} + +void sceSifResetDmaIntrHandler() +{ + sifman_internals.dma_intr_handler = NULL; + sifman_internals.dma_intr_handler_userdata = NULL; +} + +static int sifman_interrupt_handler(sifman_internals_t *smi) +{ + void (*dma_intr_handler)(void *); + sif_completion_cb_info_arr_t *sif_otherbufcom; + int v4; + sif_completion_cb_info_arr_t *p_sif_bufcom1; + USE_IOP_MMIO_HWPORT(); + USE_SIF_MMIO_HWPORT(); + + dma_intr_handler = smi->dma_intr_handler; + if ( dma_intr_handler ) + dma_intr_handler(smi->dma_intr_handler_userdata); + sif_otherbufcom = smi->sif_otherbufcom; + v4 = 0; + if ( sif_otherbufcom->count > 0 ) + { + int v5; + + v5 = 0; + do + { + ++v4; + sif_otherbufcom->info[v5].func(sif_otherbufcom->info[v5].userdata); + sif_otherbufcom = smi->sif_otherbufcom; + v5 = v4; + } while ( v4 < sif_otherbufcom->count ); + } + smi->sif_otherbufcom->count = 0; + if ( (iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000) == 0 && smi->dmatag_index > 0 ) + { + iop_mmio_hwport->dmac2.newch[2].chcr = 0; + iop_mmio_hwport->dmac2.newch[2].tadr = (uiptr)(smi->sif_curbuf); + iop_mmio_hwport->dmac2.newch[2].bcr = (iop_mmio_hwport->dmac2.newch[2].bcr & 0xFFFF0000) | 32; + if ( (sif_mmio_hwport->controlreg & 0x20) == 0 ) + sif_mmio_hwport->controlreg = 32; + ++smi->dma_count; + smi->dmatag_index = 0; + if ( smi->sif_curbuf == smi->sif_buf1 ) + { + smi->sif_curbuf = smi->sif_buf2; + smi->sif_curbufcom = &smi->sif_bufcom2; + p_sif_bufcom1 = &smi->sif_bufcom1; + } + else + { + smi->sif_curbufcom = &smi->sif_bufcom1; + p_sif_bufcom1 = &smi->sif_bufcom2; + smi->sif_curbuf = smi->sif_buf1; + } + smi->sif_otherbufcom = p_sif_bufcom1; + iop_mmio_hwport->dmac2.newch[2].chcr = 0x1000701; + } + return 1; +} + +static int sif_dma_init(void) +{ + int state; + + sifman_internals.sif_curbuf = sifman_internals.sif_buf1; + sifman_internals.sif_curbufcom = &sifman_internals.sif_bufcom1; + sifman_internals.dmatag_index = 0; + sifman_internals.sif_bufcom1.count = 0; + sifman_internals.sif_bufcom2.count = 0; + sifman_internals.sif_otherbufcom = &sifman_internals.sif_bufcom2; + sifman_internals.dma_intr_handler = 0; + sifman_internals.dma_intr_handler_userdata = 0; + CpuSuspendIntr(&state); + RegisterIntrHandler(IOP_IRQ_DMA_SIF0, 1, (int (*)(void *))sifman_interrupt_handler, &sifman_internals); + EnableIntr(IOP_IRQ_DMA_SIF0); + return CpuResumeIntr(state); +} + +static int sif_dma_setup_tag(SifDmaTransfer_t *a1) +{ + sif_info_t *v1; + int v2; + unsigned int v3; + unsigned int v4; + unsigned int v5; + + v1 = &sifman_internals.sif_curbuf[sifman_internals.dmatag_index]; + v2 = (int)a1->src & 0xFFFFFF; + v3 = a1->size + 3; + v1->data = v2; + v4 = v3 >> 2; + if ( (a1->attr & 2) != 0 ) + v1->data = v2 | 0x40000000; + v1->words = v4 & 0xFFFFFF; + v5 = v3 >> 4; + if ( (v4 & 3) != 0 ) + ++v5; + v1->count = v5 | 0x10000000; + if ( (a1->attr & 4) != 0 ) + v1->count |= 0x80000000; + v1->addr = (int)a1->dest & 0x1FFFFFFF; + return ++sifman_internals.dmatag_index; +} + +static int set_dma_inner(SifDmaTransfer_t *dmat, int count, void (*func)(), void *data) +{ + u8 dmatag_index; + int dma_count; + int i; + int v14; + sif_completion_cb_info_arr_t *p_sif_bufcom1; + USE_IOP_MMIO_HWPORT(); + USE_SIF_MMIO_HWPORT(); + + if ( 32 - sifman_internals.dmatag_index < count ) + return 0; + dmatag_index = sifman_internals.dmatag_index; + dma_count = sifman_internals.dma_count; + if ( sifman_internals.dmatag_index ) + sifman_internals.sif_curbuf[sifman_internals.dmatag_index - 1].data &= ~0x80000000; + for ( i = 0; i < count; ++dmat ) + { + sif_dma_setup_tag(dmat); + ++i; + } + sifman_internals.sif_curbuf[sifman_internals.dmatag_index - 1].data |= 0x80000000; + if ( func ) + { + sifman_internals.sif_curbufcom->info[sifman_internals.sif_curbufcom->count].func = func; + sifman_internals.sif_curbufcom->info[sifman_internals.sif_curbufcom->count++].userdata = data; + } + v14 = dma_count << 16; + if ( (iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000) == 0 ) + { + v14 = dma_count << 16; + if ( iop_mmio_hwport->dmac2.new_unusedch.madr == 0 ) + { + v14 = dma_count << 16; + if ( (iop_mmio_hwport->dmac2.dicr2 & 0x4000000) == 0 ) + { + iop_mmio_hwport->dmac2.newch[2].chcr = 0; + iop_mmio_hwport->dmac2.newch[2].tadr = (uiptr)(sifman_internals.sif_curbuf); + if ( (sif_mmio_hwport->controlreg & 0x20) == 0 ) + sif_mmio_hwport->controlreg = 32; + iop_mmio_hwport->dmac2.newch[2].bcr = (iop_mmio_hwport->dmac2.newch[2].bcr & 0xFFFF0000) | 32; + sifman_internals.dmatag_index = 0; + ++sifman_internals.dma_count; + if ( sifman_internals.sif_curbuf == sifman_internals.sif_buf1 ) + { + sifman_internals.sif_curbuf = sifman_internals.sif_buf2; + sifman_internals.sif_curbufcom = &sifman_internals.sif_bufcom2; + p_sif_bufcom1 = &sifman_internals.sif_bufcom1; + } + else + { + sifman_internals.sif_curbuf = sifman_internals.sif_buf1; + sifman_internals.sif_curbufcom = &sifman_internals.sif_bufcom1; + p_sif_bufcom1 = &sifman_internals.sif_bufcom2; + } + sifman_internals.sif_otherbufcom = p_sif_bufcom1; + iop_mmio_hwport->dmac2.newch[2].chcr = 0x1000701; + v14 = dma_count << 16; + } + } + } + return v14 | (dmatag_index << 8) | (u8)count; +} + +int sceSifSetDma(SifDmaTransfer_t *dmat, int count) +{ + return set_dma_inner(dmat, count, 0, 0); +} + +unsigned int sceSifSetDmaIntr(SifDmaTransfer_t *dmat, int len, void (*func)(), void *data) +{ + return set_dma_inner(dmat, len, func, data); +} + +static int dma_stat_inner(unsigned int a1) +{ + USE_IOP_MMIO_HWPORT(); + + if ( (iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000) == 0 && !iop_mmio_hwport->dmac2.new_unusedch.madr ) + { + if ( (iop_mmio_hwport->dmac2.dicr2 & 0x4000000) == 0 ) + return -1; + } + if ( sifman_internals.dma_count != ((a1 >> 16) & 0xFFFF) ) + { + if ( sifman_internals.dma_count == (u16)(((a1 >> 16) & 0xFFFF) + 1) ) + return 0; + return -1; + } + return 1; +} + +int sceSifDmaStat(int trid) +{ + int v2; + int state; + + if ( QueryIntrContext() ) + return dma_stat_inner(trid); + CpuSuspendIntr(&state); + v2 = dma_stat_inner(trid); + CpuResumeIntr(state); + return v2; +} + +void sceSifSetOneDma(SifDmaTransfer_t dmat) +{ + int v1; + unsigned int v2; + unsigned int v3; + USE_IOP_MMIO_HWPORT(); + USE_SIF_MMIO_HWPORT(); + + v1 = ((int)dmat.src & 0xFFFFFF) | 0x80000000; + v2 = ((unsigned int)dmat.size >> 2) + ((dmat.size & 3) != 0); + sifman_internals.one.data = v1; + sifman_internals.one.words = v2 & 0xFFFFFF; + if ( (dmat.attr & 2) != 0 ) + sifman_internals.one.data = v1 | 0x40000000; + v3 = v2 >> 2; + if ( (v2 & 3) != 0 ) + ++v3; + sifman_internals.one.count = v3 | 0x10000000; + if ( (dmat.attr & 4) != 0 ) + sifman_internals.one.count |= 0x80000000; + sifman_internals.one.addr = (int)dmat.dest & 0xFFFFFFF; + if ( (sif_mmio_hwport->controlreg & 0x20) == 0 ) + sif_mmio_hwport->controlreg = 32; + iop_mmio_hwport->dmac2.newch[2].chcr = 0; + iop_mmio_hwport->dmac2.newch[2].tadr = (uiptr)&sifman_internals.one; + iop_mmio_hwport->dmac2.newch[2].bcr = (iop_mmio_hwport->dmac2.newch[2].bcr & 0xFFFF0000) | 32; + iop_mmio_hwport->dmac2.newch[2].chcr = 0x1000701; +} + +void sceSifSendSync() +{ + USE_IOP_MMIO_HWPORT(); + + while ( iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000 ) + ; +} + +int sceSifIsSending() +{ + USE_IOP_MMIO_HWPORT(); + + return iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000; +} + +void sceSifDma0Transfer(void *addr, int size, int mode) +{ + unsigned int v4; + int v5; + USE_IOP_MMIO_HWPORT(); + USE_SIF_MMIO_HWPORT(); + + (void)mode; + + v4 = ((unsigned int)size >> 2) + ((size & 3) != 0); + if ( (sif_mmio_hwport->controlreg & 0x20) == 0 ) + sif_mmio_hwport->controlreg = 32; + iop_mmio_hwport->dmac2.newch[2].chcr = 0; + iop_mmio_hwport->dmac2.newch[2].madr = (unsigned int)addr & 0xFFFFFF; + if ( (v4 & 0x1F) != 0 ) + v5 = (v4 >> 5) + 1; + else + v5 = v4 >> 5; + iop_mmio_hwport->dmac2.newch[2].bcr = ((v5 & 0xFFFF) << 16) | 32; + iop_mmio_hwport->dmac2.newch[2].chcr = 0x1000201; +} + +void sceSifDma0Sync() +{ + USE_IOP_MMIO_HWPORT(); + + while ( iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000 ) + ; +} + +int sceSifDma0Sending() +{ + USE_IOP_MMIO_HWPORT(); + + return iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000; +} + +void sceSifDma1Transfer(void *addr, int size, int mode) +{ + unsigned int v4; + int v5; + int v6; + USE_IOP_MMIO_HWPORT(); + USE_SIF_MMIO_HWPORT(); + + v4 = ((unsigned int)size >> 2) + ((size & 3) != 0); + if ( (sif_mmio_hwport->controlreg & 0x40) == 0 ) + sif_mmio_hwport->controlreg = 64; + iop_mmio_hwport->dmac2.newch[3].chcr = 0; + iop_mmio_hwport->dmac2.newch[3].madr = (unsigned int)addr & 0xFFFFFF; + if ( (v4 & 0x1F) != 0 ) + v5 = (v4 >> 5) + 1; + else + v5 = v4 >> 5; + iop_mmio_hwport->dmac2.newch[3].bcr = ((v5 & 0xFFFF) << 16) | 32; + if ( (mode & 0x10) != 0 ) + v6 = 0x41000000; + else + v6 = 0x1000000; + iop_mmio_hwport->dmac2.newch[3].chcr = v6 | 0x200; +} + +void sceSifDma1Sync() +{ + USE_IOP_MMIO_HWPORT(); + + while ( iop_mmio_hwport->dmac2.newch[3].chcr & 0x1000000 ) + ; +} + +int sceSifDma1Sending() +{ + USE_IOP_MMIO_HWPORT(); + + return iop_mmio_hwport->dmac2.newch[3].chcr & 0x1000000; +} + +void sceSifDma2Transfer(void *addr, int size, int mode) +{ + unsigned int v4; + u16 v5; + int v6; + int v7; + USE_IOP_MMIO_HWPORT(); + USE_SIF_MMIO_HWPORT(); + + v4 = ((unsigned int)size >> 2) + ((size & 3) != 0); + if ( (sif_mmio_hwport->controlreg & 0x80) == 0 ) + sif_mmio_hwport->controlreg = 128; + v5 = v4; + iop_mmio_hwport->dmac1.oldch[2].chcr = 0; + iop_mmio_hwport->dmac1.oldch[2].madr = (unsigned int)addr & 0xFFFFFF; + if ( v4 >= 0x21 ) + v5 = 32; + if ( (v4 & 0x1F) != 0 ) + v6 = (v4 >> 5) + 1; + else + v6 = v4 >> 5; + iop_mmio_hwport->dmac1.oldch[2].bcr = ((v6 & 0xFFFF) << 16) | (v5 & 0xFFFF); + if ( (mode & 1) != 0 ) + { + v7 = 0x1000201; + } + else + { + int v8; + + if ( (mode & 0x10) != 0 ) + v8 = 0x41000000; + else + v8 = 0x1000000; + v7 = v8 | 0x200; + } + iop_mmio_hwport->dmac1.oldch[2].chcr = v7; +} + +void sceSifDma2Sync() +{ + USE_IOP_MMIO_HWPORT(); + + while ( iop_mmio_hwport->dmac1.oldch[2].chcr & 0x1000000 ) + ; +} + +int sceSifDma2Sending() +{ + USE_IOP_MMIO_HWPORT(); + + return iop_mmio_hwport->dmac1.oldch[2].chcr & 0x1000000; +} + +u32 sceSifGetMSFlag() +{ + return get_msflag(); +} + +u32 sceSifSetMSFlag(u32 val) +{ + USE_SIF_MMIO_HWPORT(); + + sif_mmio_hwport->msflag = val; + return get_msflag(); +} + +u32 sceSifGetSMFlag() +{ + return get_smflag(); +} + +u32 sceSifSetSMFlag(u32 val) +{ + USE_SIF_MMIO_HWPORT(); + + sif_mmio_hwport->smflag = val; + return get_smflag(); +} + +u32 sceSifGetMainAddr() +{ + USE_SIF_MMIO_HWPORT(); + + return sif_mmio_hwport->mscom; +} + +u32 sceSifGetSubAddr() +{ + USE_SIF_MMIO_HWPORT(); + + return sif_mmio_hwport->smcom; +} + +u32 sceSifSetSubAddr(u32 addr) +{ + USE_SIF_MMIO_HWPORT(); + + sif_mmio_hwport->smcom = addr; + return sif_mmio_hwport->smcom; +} + +void sceSifIntrMain() +{ + u32 v0; + USE_IOP_MMIO_HWPORT(); + + v0 = iop_mmio_hwport->iop_sbus_ctrl[0]; + iop_mmio_hwport->iop_sbus_ctrl[0] = v0 | 2; + // cppcheck-suppress redundantAssignment + iop_mmio_hwport->iop_sbus_ctrl[0] = v0 & 0xFFFFFFFD; +}