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