PS2SDK
PS2 Homebrew Libraries
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 
14 extern struct irx_export_table _exp_sifcmd;
15 
16 #ifdef _IOP
17 IRX_ID("IOP_SIF_rpc_interface", 2, 8);
18 #endif
19 // Based on the module from SCE SDK 3.1.0.
20 
21 typedef 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];
36 } __attribute__((aligned(16))) sif_cmd_data_t;
37 
38 typedef struct t_SifCmdChgAddrData
39 {
40  SifCmdHeader_t header;
41  u32 newaddr;
42 } SifCmdChgAddrData_t;
43 
44 static sif_cmd_data_t sif_cmd_data;
45 static u8 sif_iop_recvbuf[0x80] __attribute__((aligned(16)));
46 static u8 sif_unused[0x40] __attribute__((aligned(16)));
47 
48 static int sif_cmd_int_handler(void *userdata);
49 
50 static 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 
55 static 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 
60 unsigned int sceSifGetSreg(int sreg)
61 {
62  return sif_cmd_data.sregs[sreg];
63 }
64 
65 void sceSifSetSreg(int sreg, unsigned int value)
66 {
67  sif_cmd_data.sregs[sreg] = value;
68 }
69 
70 #if 0
71 sif_cmd_data_t *sif_cmd_get_internal_data()
72 {
73  return &sif_cmd_data;
74 }
75 #endif
76 
77 static 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 
91 int _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, 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 
157 int 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 
170 void sceSifInitCmd(void)
171 {
172  sceSifSetSMFlag(SIF_STAT_CMDINIT);
173  WaitEventFlag(sif_cmd_data.ef, 0x100u, 0, 0);
174 }
175 
176 void sceSifExitCmd(void)
177 {
178  int old_irq;
179 
180  DisableIntr(IOP_IRQ_DMA_SIF1, &old_irq);
181  ReleaseIntrHandler(IOP_IRQ_DMA_SIF1);
182 }
183 
184 void sceSifSetCmdBuffer(SifCmdHandlerData_t *db, int size)
185 {
186  sif_cmd_data.usr_cmd_handlers = db;
187  sif_cmd_data.nr_usr_handlers = size;
188 }
189 
190 void sceSifSetSysCmdBuffer(SifCmdSysHandlerData_t *db, int size)
191 {
192  sif_cmd_data.sys_cmd_handlers = db;
193  sif_cmd_data.nr_sys_handlers = size;
194 }
195 
196 void 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 
210 void 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 
218 static int sif_send_cmd_common(
219  int cid,
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 *userdata),
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 = cid;
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 
292 unsigned int sceSifSendCmd(int cid, void *packet, int packet_size, void *src_extra, void *dest_extra, int size_extra)
293 {
294  return sif_send_cmd_common(cid, 0, (SifCmdHeader_t *)packet, packet_size, src_extra, dest_extra, size_extra, 0, 0);
295 }
296 
297 unsigned int sceSifSendCmdIntr(
298  int cid,
299  void *packet,
300  int packet_size,
301  void *src_extra,
302  void *dest_extra,
303  int size_extra,
304  void (*completion_cb)(void *userdata),
305  void *completion_cb_userdata)
306 {
307  return sif_send_cmd_common(
308  cid,
309  8,
310  (SifCmdHeader_t *)packet,
311  packet_size,
312  src_extra,
313  dest_extra,
314  size_extra,
315  completion_cb,
316  completion_cb_userdata);
317 }
318 
319 unsigned int isceSifSendCmd(int cid, void *packet, int packet_size, void *src_extra, void *dest_extra, int size_extra)
320 {
321  return sif_send_cmd_common(cid, 1, (SifCmdHeader_t *)packet, packet_size, src_extra, dest_extra, size_extra, 0, 0);
322 }
323 
324 unsigned int isceSifSendCmdIntr(
325  int cid,
326  void *packet,
327  int packet_size,
328  void *src_extra,
329  void *dest_extra,
330  int size_extra,
331  void (*completion_cb)(void *userdata),
332  void *completion_cb_userdata)
333 {
334  return sif_send_cmd_common(
335  cid,
336  9,
337  (SifCmdHeader_t *)packet,
338  packet_size,
339  src_extra,
340  dest_extra,
341  size_extra,
342  completion_cb,
343  completion_cb_userdata);
344 }
345 
346 void 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 
352 void sceSifClearSif1CB(void)
353 {
354  sif_cmd_data.sif_1_callback = NULL;
355  sif_cmd_data.sif_1_callback_userdata = NULL;
356 }
357 
358 static int sif_cmd_int_handler(void *userdata)
359 {
360  void (*sif_1_callback)(void *userdata);
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  sif_cmd_data_t *sci;
370 
371  sci = (sif_cmd_data_t *)userdata;
372  sif_1_callback = sci->sif_1_callback;
373  if ( sif_1_callback )
374  sif_1_callback(sci->sif_1_callback_userdata);
375  pktbuf1 = (SifCmdHeader_t *)sci->pktbuf;
376  size = *(u8 *)sci->pktbuf;
377  if ( !*(u8 *)sci->pktbuf )
378  {
379  sceSifSetDChain();
380  return 1;
381  }
382  *(u8 *)pktbuf1 = 0;
383  size_calc1 = size + 3;
384  pktbuf2 = pktbuf1;
385  if ( size + 3 < 0 )
386  size_calc1 = size + 6;
387  pktwords = size_calc1 >> 2;
388  i = 0;
389  tmpbuf1[2] = 0;
390  if ( size_calc1 >> 2 > 0 )
391  {
392  u32 *tmpptr1;
393 
394  tmpptr1 = tmpbuf1;
395  do
396  {
397  tmp1 = *(u32 *)pktbuf2;
398  pktbuf2 = (SifCmdHeader_t *)((char *)pktbuf2 + 4);
399  ++i;
400  *tmpptr1++ = tmp1;
401  } while ( i < pktwords );
402  }
403  sceSifSetDChain();
404  if ( (tmpbuf1[2] & 0x80000000) == 0 )
405  {
406  if ( (int)tmpbuf1[2] < sci->nr_usr_handlers )
407  {
408  if ( sif_cmd_data.usr_cmd_handlers[tmpbuf1[2]].handler != NULL )
409  {
410  sif_cmd_data.usr_cmd_handlers[tmpbuf1[2]].handler(tmpbuf1, sif_cmd_data.usr_cmd_handlers[tmpbuf1[2]].harg);
411  }
412  }
413  }
414  else if ( (signed int)(tmpbuf1[2] & 0x7FFFFFFF) < sci->nr_sys_handlers )
415  {
416  if ( sif_cmd_data.sys_cmd_handlers[tmpbuf1[2] + (tmpbuf1[2] & 0x7FFFFFFF)].handler != NULL )
417  {
418  sif_cmd_data.sys_cmd_handlers[tmpbuf1[2] + (tmpbuf1[2] & 0x7FFFFFFF)].handler(
419  tmpbuf1, sif_cmd_data.usr_cmd_handlers[tmpbuf1[2] + (tmpbuf1[2] & 0x7FFFFFFF)].harg);
420  }
421  }
422  return 1;
423 }
SIF_STAT_CMDINIT
#define SIF_STAT_CMDINIT
Definition: sifdma.h:48
RegisterIntrHandler
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *arg), void *arg)
Definition: intrman.c:115
ReleaseIntrHandler
int ReleaseIntrHandler(int irq)
Definition: intrman.c:157
t_SifCmdHeader::cid
int cid
Definition: sifcmd-common.h:31
t_SifCmdHandlerData
Definition: sifcmd-common.h:66
sif_cmd_data_
Definition: sifcmd.c:21
DisableIntr
int DisableIntr(int irq, int *res)
Definition: intrman.c:385
t_SifCmdHeader::dest
void * dest
Definition: sifcmd-common.h:29
CpuSuspendIntr
int CpuSuspendIntr(int *state)
Definition: intrman.c:195
t_SifCmdSysHandlerData
Definition: sifcmd-common.h:72
t_SifCmdHeader
Definition: sifcmd-common.h:22
EnableIntr
int EnableIntr(int irq)
Definition: intrman.c:336
t_SifCmdSRegData
Definition: sifcmd-common.h:54
irx_export_table
Definition: irx.h:90
t_SifDmaTransfer
Definition: sifdma.h:52
CpuResumeIntr
int CpuResumeIntr(int state)
Definition: intrman.c:217
__attribute__
Definition: gif_registers.h:38