1 #include "Iop_SifMan.h"
2 #include "Iop_Sysmem.h"
3 #include "../MIPSAssembler.h"
4 #include "../Log.h"
5
6 #define LOG_NAME ("iop_sifman")
7
8 #define FUNCTION_SIFINIT "SifInit"
9 #define FUNCTION_SIFSETDMA "SifSetDma"
10 #define FUNCTION_SIFDMASTAT "SifDmaStat"
11 #define FUNCTION_SIFCHECKINIT "SifCheckInit"
12 #define FUNCTION_SIFSETDMACALLBACK "SifSetDmaCallback"
13
14 using namespace Iop;
15
CSifMan()16 CSifMan::CSifMan()
17 : m_sifSetDmaCallbackHandlerPtr(0)
18 {
19 }
20
GetId() const21 std::string CSifMan::GetId() const
22 {
23 return "sifman";
24 }
25
GetFunctionName(unsigned int functionId) const26 std::string CSifMan::GetFunctionName(unsigned int functionId) const
27 {
28 switch(functionId)
29 {
30 case 5:
31 return FUNCTION_SIFINIT;
32 break;
33 case 7:
34 return FUNCTION_SIFSETDMA;
35 break;
36 case 8:
37 return FUNCTION_SIFDMASTAT;
38 break;
39 case 29:
40 return FUNCTION_SIFCHECKINIT;
41 break;
42 case 32:
43 return FUNCTION_SIFSETDMACALLBACK;
44 break;
45 }
46 return "unknown";
47 }
48
Invoke(CMIPS & context,unsigned int functionId)49 void CSifMan::Invoke(CMIPS& context, unsigned int functionId)
50 {
51 switch(functionId)
52 {
53 case 7:
54 context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(SifSetDma(
55 context.m_State.nGPR[CMIPS::A0].nV0,
56 context.m_State.nGPR[CMIPS::A1].nV0));
57 break;
58 case 8:
59 context.m_State.nGPR[CMIPS::V0].nV0 = SifDmaStat(context.m_State.nGPR[CMIPS::A0].nV0);
60 break;
61 case 29:
62 context.m_State.nGPR[CMIPS::V0].nV0 = SifCheckInit();
63 break;
64 case 32:
65 context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(SifSetDmaCallback(
66 context,
67 context.m_State.nGPR[CMIPS::A0].nV0,
68 context.m_State.nGPR[CMIPS::A1].nV0,
69 context.m_State.nGPR[CMIPS::A2].nV0,
70 context.m_State.nGPR[CMIPS::A3].nV0));
71 break;
72 default:
73 CLog::GetInstance().Warn(LOG_NAME, "%08X: Unknown function (%d) called.\r\n", context.m_State.nPC, functionId);
74 break;
75 }
76 }
77
GenerateHandlers(uint8 * ram,CSysmem & sysMem)78 void CSifMan::GenerateHandlers(uint8* ram, CSysmem& sysMem)
79 {
80 const uint32 handlerAllocSize = 64;
81
82 assert(m_sifSetDmaCallbackHandlerPtr == 0);
83 m_sifSetDmaCallbackHandlerPtr = sysMem.AllocateMemory(handlerAllocSize, 0, 0);
84
85 CMIPSAssembler assembler(reinterpret_cast<uint32*>(ram + m_sifSetDmaCallbackHandlerPtr));
86
87 assembler.ADDIU(CMIPS::SP, CMIPS::SP, 0xFFF0);
88 assembler.SW(CMIPS::RA, 0x00, CMIPS::SP);
89 assembler.SW(CMIPS::S0, 0x04, CMIPS::SP);
90
91 assembler.ADDU(CMIPS::S0, CMIPS::V0, CMIPS::R0);
92 assembler.JALR(CMIPS::A1);
93 assembler.NOP();
94
95 assembler.ADDU(CMIPS::V0, CMIPS::S0, CMIPS::R0);
96
97 assembler.LW(CMIPS::S0, 0x04, CMIPS::SP);
98 assembler.LW(CMIPS::RA, 0x00, CMIPS::SP);
99 assembler.JR(CMIPS::RA);
100 assembler.ADDIU(CMIPS::SP, CMIPS::SP, 0x0010);
101
102 assert((assembler.GetProgramSize() * 4) <= handlerAllocSize);
103 }
104
SifSetDma(uint32 structAddr,uint32 count)105 uint32 CSifMan::SifSetDma(uint32 structAddr, uint32 count)
106 {
107 CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFSETDMA "(structAddr = 0x%08X, count = %d);\r\n",
108 structAddr, count);
109 return count;
110 }
111
SifDmaStat(uint32 transferId)112 uint32 CSifMan::SifDmaStat(uint32 transferId)
113 {
114 CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFDMASTAT "(transferId = %X);\r\n",
115 transferId);
116 return -1;
117 }
118
SifCheckInit()119 uint32 CSifMan::SifCheckInit()
120 {
121 CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFCHECKINIT "();\r\n");
122 // Since we don't handle the init call, always return true for check init.
123 return 1;
124 }
125
SifSetDmaCallback(CMIPS & context,uint32 structAddr,uint32 count,uint32 callbackPtr,uint32 callbackParam)126 uint32 CSifMan::SifSetDmaCallback(CMIPS& context, uint32 structAddr, uint32 count, uint32 callbackPtr, uint32 callbackParam)
127 {
128 CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFSETDMACALLBACK "(structAddr = 0x%08X, count = %d, callbackPtr = 0x%08X, callbackParam = 0x%08X);\r\n",
129 structAddr, count, callbackPtr, callbackParam);
130
131 //Modify context so we can execute the callback function
132 context.m_State.nPC = m_sifSetDmaCallbackHandlerPtr;
133 context.m_State.nGPR[CMIPS::A0].nV0 = callbackParam;
134 context.m_State.nGPR[CMIPS::A1].nV0 = callbackPtr;
135
136 return SifSetDma(structAddr, count);
137 }
138