PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
sifcmd.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "irx_imports.h"
12#include "sifcmd.h"
13
14extern struct irx_export_table _exp_sifcmd;
15
16#ifdef _IOP
17IRX_ID("IOP_SIF_rpc_interface", 2, 8);
18#endif
19// Based on the module from SCE SDK 3.1.0.
20
21typedef struct sif_cmd_data_
22{
23 void *pktbuf;
24 void *unused;
25 int sif_send_eebuf;
26 SifCmdSysHandlerData_t *sys_cmd_handlers;
27 int nr_sys_handlers;
28 SifCmdHandlerData_t *usr_cmd_handlers;
29 int nr_usr_handlers;
30 unsigned int *sregs_ptr;
31 int ef;
32 void (*sif_1_callback)(void *userdata);
33 void *sif_1_callback_userdata;
34 SifCmdSysHandlerData_t sys_cmd_handler_handler[32];
35 unsigned int sregs[32];
37
38typedef struct t_SifCmdChgAddrData
39{
40 SifCmdHeader_t header;
41 u32 newaddr;
43
44static sif_cmd_data_t sif_cmd_data;
45static u8 sif_iop_recvbuf[0x80];
46static u8 sif_unused[0x40];
47
48static int sif_cmd_int_handler(sif_cmd_data_t *sci);
49
50static void sif_sys_cmd_handler_set_sreg(const SifCmdSRegData_t *pkt, sif_cmd_data_t *sci)
51{
52 sci->sregs_ptr[pkt->index] = pkt->value;
53}
54
55static void sif_sys_cmd_handler_change_addr(const SifCmdChgAddrData_t *pkt, sif_cmd_data_t *sci)
56{
57 sci->sif_send_eebuf = pkt->newaddr;
58}
59
60unsigned int sceSifGetSreg(int index)
61{
62 return sif_cmd_data.sregs[index];
63}
64
65void sceSifSetSreg(int index, unsigned int value)
66{
67 sif_cmd_data.sregs[index] = value;
68}
69
70#if 0
71sif_cmd_data_t *sif_cmd_get_internal_data()
72{
73 return &sif_cmd_data;
74}
75#endif
76
77static void sif_sys_cmd_handler_init_from_ee(const SifCmdChgAddrData_t *pkt, sif_cmd_data_t *sci)
78{
79 if ( pkt->header.opt )
80 {
81 iSetEventFlag(sci->ef, 0x800u);
82 }
83 else
84 {
85 iSetEventFlag(sci->ef, 0x100u);
86 sceSifSetMSFlag(SIF_STAT_CMDINIT);
87 sci->sif_send_eebuf = pkt->newaddr;
88 }
89}
90
91int _start(int ac, char **av)
92{
93 const int *BootMode3;
94
95 (void)ac;
96 (void)av;
97
98 BootMode3 = QueryBootMode(3);
99 if ( BootMode3 )
100 {
101 int BootMode3_1;
102
103 BootMode3_1 = BootMode3[1];
104 if ( (BootMode3_1 & 1) != 0 )
105 {
106 printf(" No SIF service(sifcmd)\n");
107 return 1;
108 }
109 if ( (BootMode3_1 & 2) != 0 )
110 {
111 printf(" No SIFCMD/RPC service\n");
112 return 1;
113 }
114 }
115 if ( !sceSifCheckInit() )
116 sceSifInit();
117 if ( RegisterLibraryEntries(&_exp_sifcmd) == 0 )
118 {
119 unsigned int i;
120
121 sif_cmd_data.pktbuf = sif_iop_recvbuf;
122 sif_cmd_data.unused = sif_unused;
123 sif_cmd_data.sys_cmd_handlers = sif_cmd_data.sys_cmd_handler_handler;
124 sif_cmd_data.nr_sys_handlers =
125 sizeof(sif_cmd_data.sys_cmd_handler_handler) / sizeof(sif_cmd_data.sys_cmd_handler_handler[0]);
126 sif_cmd_data.sif_send_eebuf = 0;
127 sif_cmd_data.usr_cmd_handlers = 0;
128 sif_cmd_data.nr_usr_handlers = 0;
129 sif_cmd_data.sregs_ptr = sif_cmd_data.sregs;
130 sif_cmd_data.sif_1_callback = 0;
131 sif_cmd_data.sif_1_callback_userdata = 0;
132 for ( i = 0; i < sizeof(sif_cmd_data.sys_cmd_handler_handler) / sizeof(sif_cmd_data.sys_cmd_handler_handler[0]);
133 i += 1 )
134 {
135 sif_cmd_data.sys_cmd_handler_handler[i].handler = NULL;
136 sif_cmd_data.sys_cmd_handler_handler[i].harg = NULL;
137 }
138 for ( i = 0; i < sizeof(sif_cmd_data.sregs) / sizeof(sif_cmd_data.sregs[0]); i += 1 )
139 {
140 sif_cmd_data.sregs[i] = 0;
141 }
142 sif_cmd_data.sys_cmd_handler_handler[0].handler = (SifCmdHandler_t)sif_sys_cmd_handler_change_addr;
143 sif_cmd_data.sys_cmd_handler_handler[0].harg = &sif_cmd_data;
144 sif_cmd_data.sys_cmd_handler_handler[1].handler = (SifCmdHandler_t)sif_sys_cmd_handler_set_sreg;
145 sif_cmd_data.sys_cmd_handler_handler[1].harg = &sif_cmd_data;
146 sif_cmd_data.ef = GetSystemStatusFlag();
147 sif_cmd_data.sys_cmd_handler_handler[2].handler = (SifCmdHandler_t)sif_sys_cmd_handler_init_from_ee;
148 sif_cmd_data.sys_cmd_handler_handler[2].harg = &sif_cmd_data;
149 RegisterIntrHandler(IOP_IRQ_DMA_SIF1, 1, (int (*)(void *))sif_cmd_int_handler, &sif_cmd_data);
150 EnableIntr(0x22B);
151 sceSifSetSubAddr((u32)sif_iop_recvbuf);
152 return 0;
153 }
154 return 1;
155}
156
157int sifcmd_deinit(void)
158{
159 int old_irq;
160
161 DisableIntr(IOP_IRQ_DMA_SIF1, &old_irq);
162 ReleaseIntrHandler(IOP_IRQ_DMA_SIF1);
163#if 0
164 // FIXME: Do we really need this call?
165 sifman_2();
166#endif
167 return 0;
168}
169
170void sceSifInitCmd(void)
171{
172 sceSifSetSMFlag(SIF_STAT_CMDINIT);
173 WaitEventFlag(sif_cmd_data.ef, 0x100u, 0, 0);
174}
175
176void sceSifExitCmd(void)
177{
178 int old_irq;
179
180 DisableIntr(IOP_IRQ_DMA_SIF1, &old_irq);
181 ReleaseIntrHandler(IOP_IRQ_DMA_SIF1);
182}
183
184void sceSifSetCmdBuffer(SifCmdHandlerData_t *cmdBuffer, int size)
185{
186 sif_cmd_data.usr_cmd_handlers = cmdBuffer;
187 sif_cmd_data.nr_usr_handlers = size;
188}
189
190void sceSifSetSysCmdBuffer(SifCmdSysHandlerData_t *sysCmdBuffer, int size)
191{
192 sif_cmd_data.sys_cmd_handlers = sysCmdBuffer;
193 sif_cmd_data.nr_sys_handlers = size;
194}
195
196void sceSifAddCmdHandler(int cid, SifCmdHandler_t handler, void *harg)
197{
198 if ( cid >= 0 )
199 {
200 sif_cmd_data.usr_cmd_handlers[cid].handler = handler;
201 sif_cmd_data.usr_cmd_handlers[cid].harg = harg;
202 }
203 else
204 {
205 sif_cmd_data.sys_cmd_handlers[cid + (cid & 0x7FFFFFFF)].handler = handler;
206 sif_cmd_data.sys_cmd_handlers[cid + (cid & 0x7FFFFFFF)].harg = harg;
207 }
208}
209
210void sceSifRemoveCmdHandler(int cid)
211{
212 if ( cid >= 0 )
213 sif_cmd_data.usr_cmd_handlers[cid].handler = NULL;
214 else
215 sif_cmd_data.sys_cmd_handlers[cid + (cid & 0x7FFFFFFF)].handler = NULL;
216}
217
218static int sif_send_cmd_common(
219 int cmd,
220 char flags,
221 SifCmdHeader_t *packet,
222 int packet_size,
223 void *src_extra,
224 void *dest_extra,
225 int size_extra,
226 void (*completion_cb)(void *),
227 void *completion_cb_userdata)
228{
229 int dmatc1;
230 SifDmaTransfer_t *dmatp;
231 int dmatc2;
232 int sif_send_eebuf;
233 unsigned int dmar1;
234 SifDmaTransfer_t dmat[2];
235 int state;
236
237 if ( (unsigned int)(packet_size - 16) >= 0x61 )
238 return 0;
239 dmatc1 = 0;
240 if ( size_extra <= 0 )
241 {
242 int tmp1;
243
244 tmp1 = *(u8 *)packet;
245 packet->dest = 0;
246 *(u32 *)packet = tmp1;
247 }
248 else
249 {
250 int tmp2;
251
252 dmatc1 = 1;
253 dmat[0].dest = dest_extra;
254 dmat[0].size = size_extra;
255 dmat[0].attr = 0;
256 dmat[0].src = src_extra;
257 tmp2 = *(u8 *)packet;
258 packet->dest = dest_extra;
259 *(u32 *)packet = tmp2 | (size_extra << 8);
260 }
261 dmatp = &dmat[dmatc1];
262 dmatc2 = dmatc1 + 1;
263 *(u8 *)packet = packet_size;
264 packet->cid = cmd;
265 dmatp->src = packet;
266 sif_send_eebuf = sif_cmd_data.sif_send_eebuf;
267 dmatp->attr = 4;
268 dmatp->size = packet_size;
269 dmatp->dest = (void *)sif_send_eebuf;
270 if ( (flags & 1) != 0 )
271 {
272 if ( (flags & 8) != 0 )
273 return sceSifSetDmaIntr(dmat, dmatc2, completion_cb, completion_cb_userdata);
274 else
275 return sceSifSetDma(dmat, dmatc2);
276 }
277 else
278 {
279 unsigned int dmar2;
280
281 CpuSuspendIntr(&state);
282 if ( (flags & 8) != 0 )
283 dmar2 = sceSifSetDmaIntr(dmat, dmatc2, completion_cb, completion_cb_userdata);
284 else
285 dmar2 = sceSifSetDma(dmat, dmatc2);
286 dmar1 = dmar2;
287 CpuResumeIntr(state);
288 }
289 return dmar1;
290}
291
292unsigned int sceSifSendCmd(int cmd, void *packet, int packet_size, void *src_extra, void *dest_extra, int size_extra)
293{
294 return sif_send_cmd_common(cmd, 0, (SifCmdHeader_t *)packet, packet_size, src_extra, dest_extra, size_extra, 0, 0);
295}
296
297unsigned int sceSifSendCmdIntr(
298 int cmd,
299 void *packet,
300 int packet_size,
301 void *src_extra,
302 void *dest_extra,
303 int size_extra,
304 void (*completion_cb)(void *),
305 void *completion_cb_userdata)
306{
307 return sif_send_cmd_common(
308 cmd,
309 8,
310 (SifCmdHeader_t *)packet,
311 packet_size,
312 src_extra,
313 dest_extra,
314 size_extra,
315 (void (*)(void *))completion_cb,
316 completion_cb_userdata);
317}
318
319unsigned int isceSifSendCmd(int cmd, void *packet, int packet_size, void *src_extra, void *dest_extra, int size_extra)
320{
321 return sif_send_cmd_common(cmd, 1, (SifCmdHeader_t *)packet, packet_size, src_extra, dest_extra, size_extra, 0, 0);
322}
323
324unsigned int isceSifSendCmdIntr(
325 int cmd,
326 void *packet,
327 int packet_size,
328 void *src_extra,
329 void *dest_extra,
330 int size_extra,
331 void (*completion_cb)(void *),
332 void *completion_cb_userdata)
333{
334 return sif_send_cmd_common(
335 cmd,
336 9,
337 (SifCmdHeader_t *)packet,
338 packet_size,
339 src_extra,
340 dest_extra,
341 size_extra,
342 (void (*)(void *))completion_cb,
343 completion_cb_userdata);
344}
345
346void sceSifSetSif1CB(void (*func)(void *userdata), void *userdata)
347{
348 sif_cmd_data.sif_1_callback = func;
349 sif_cmd_data.sif_1_callback_userdata = userdata;
350}
351
352void sceSifClearSif1CB(void)
353{
354 sif_cmd_data.sif_1_callback = NULL;
355 sif_cmd_data.sif_1_callback_userdata = NULL;
356}
357
358static int sif_cmd_int_handler(sif_cmd_data_t *sci)
359{
360 void (*sif_1_callback)(void *);
361 SifCmdHeader_t *pktbuf1;
362 int size;
363 int size_calc1;
364 SifCmdHeader_t *pktbuf2;
365 int pktwords;
366 int i;
367 u32 tmp1;
368 u32 tmpbuf1[32];
369
370 sif_1_callback = sci->sif_1_callback;
371 if ( sif_1_callback )
372 sif_1_callback(sci->sif_1_callback_userdata);
373 pktbuf1 = (SifCmdHeader_t *)sci->pktbuf;
374 size = *(u8 *)sci->pktbuf;
375 if ( !*(u8 *)sci->pktbuf )
376 {
377 sceSifSetDChain();
378 return 1;
379 }
380 *(u8 *)pktbuf1 = 0;
381 size_calc1 = size + 3;
382 pktbuf2 = pktbuf1;
383 if ( size + 3 < 0 )
384 size_calc1 = size + 6;
385 pktwords = size_calc1 >> 2;
386 i = 0;
387 tmpbuf1[2] = 0;
388 if ( size_calc1 >> 2 > 0 )
389 {
390 u32 *tmpptr1;
391
392 tmpptr1 = tmpbuf1;
393 do
394 {
395 tmp1 = *(u32 *)pktbuf2;
396 pktbuf2 = (SifCmdHeader_t *)((char *)pktbuf2 + 4);
397 ++i;
398 *tmpptr1++ = tmp1;
399 } while ( i < pktwords );
400 }
401 sceSifSetDChain();
402 if ( (tmpbuf1[2] & 0x80000000) == 0 )
403 {
404 if ( (int)tmpbuf1[2] < sci->nr_usr_handlers )
405 {
406 if ( sif_cmd_data.usr_cmd_handlers[tmpbuf1[2]].handler != NULL )
407 {
408 sif_cmd_data.usr_cmd_handlers[tmpbuf1[2]].handler(tmpbuf1, sif_cmd_data.usr_cmd_handlers[tmpbuf1[2]].harg);
409 }
410 }
411 }
412 else if ( (signed int)(tmpbuf1[2] & 0x7FFFFFFF) < sci->nr_sys_handlers )
413 {
414 if ( sif_cmd_data.sys_cmd_handlers[tmpbuf1[2] + (tmpbuf1[2] & 0x7FFFFFFF)].handler != NULL )
415 {
416 sif_cmd_data.sys_cmd_handlers[tmpbuf1[2] + (tmpbuf1[2] & 0x7FFFFFFF)].handler(
417 tmpbuf1, sif_cmd_data.usr_cmd_handlers[tmpbuf1[2] + (tmpbuf1[2] & 0x7FFFFFFF)].harg);
418 }
419 }
420 return 1;
421}
int CpuResumeIntr(int state)
Definition intrman.c:227
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *), void *arg)
Definition intrman.c:125
int ReleaseIntrHandler(int irq)
Definition intrman.c:167
int DisableIntr(int irq, int *res)
Definition intrman.c:395
int CpuSuspendIntr(int *state)
Definition intrman.c:205
int EnableIntr(int irq)
Definition intrman.c:346
void * dest
Definition sifcmd.h:29
#define SIF_STAT_CMDINIT
Definition sifdma.h:48