PS2SDK
PS2 Homebrew Libraries
dvrdrv.c
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2021-2021, 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.h"
12 #include "tamtypes.h"
13 #include "stdbool.h"
14 #include "dev9.h"
15 #include "sysmem.h"
16 #include "intrman.h"
17 #include "loadcore.h"
18 #include "stdio.h"
19 #include "thbase.h"
20 #include "thsemap.h"
21 #include "speedregs.h"
22 
23 #include "pvrdrv.h"
24 
25 // Based off of DESR / PSX DVR system software version 1.31.
26 #define MODNAME "DVR_Basic_driver"
27 IRX_ID(MODNAME, 1, 1);
28 
29 typedef struct struct_itr_sid_tbl_
30 {
31  u16 command;
32  u8 gap2[2];
33  int sema;
34  u16 error;
35  u8 timed_out;
36  u8 byteB;
38 
39 typedef struct __attribute__((aligned(4))) struct_itr_sema_
40 {
41  int sema;
42  u8 used;
43 } struct_itr_sema;
44 
45 typedef struct struct_dvrdrv_
46 {
47  int mainthread_id;
48  u16 dvr_ready;
50 
51 int module_start(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi);
52 int module_stop(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi);
53 int DvrdrvInit();
54 int DvrdrvSendCmdAck(struct_itr_sema *itrsema, u16 command, u16 *input_word, s32 input_word_count, u16 *status_4220, u16 *ack_status, u32 *status_4228);
55 int DvrdrvSetDmaDirection(u32 arg);
56 int DvrdrvTransferDma(u8 *output_buffer, int a2);
57 void DvrPreDmaHandler(int bcr, int dir);
58 void DvrPostDmaHandler(int bcr, int dir);
59 int DvrdrvPrepareWaitDmaEnd(struct_itr_sema *itrsema, u16 command);
60 int DvrdrvCancelWaitDmaEnd(u16 command);
61 int DvrdrvWaitDmaEnd(struct_itr_sema *itrsema, u16 command);
62 int DvrdrvPrepareWaitCmdComp(struct_itr_sema *itrsema, u16 command, u32 timeout);
63 int DvrdrvCancelWaitCmdComp(u16 command);
64 int DvrdrvWaitCmdComp(struct_itr_sema *itrsema, u16 command, u16 *status_4220, u16 *comp_status, u32 *status_4228);
65 s32 DvrdrvBlockPhase();
66 s32 DvrdrvUnblockPhase();
67 int DvrdrvEnd();
68 int DVR_INTR_HANDLER(int flag);
69 void INTR_DVRRDY_HANDLER(int a1, void *a2v);
70 unsigned int INTR_DVRRDY_TO_HANDLER(void *a1);
71 void INTR_CMD_ACK_HANDLER(int a1, void *a2);
72 unsigned int INTR_CMD_ACK_TO_HANDLER(void *arg);
73 void INTR_CMD_COMP_HANDLER(int a1, void *a2);
74 unsigned int INTR_CMD_COMP_TO_HANDLER(void *arg);
75 void INTR_DMAACK_HANDLER(int a1, void *a2);
76 unsigned int INTR_DMAACK_TO_HANDLER(void *arg);
77 void INTR_DMAEND_HANDLER(int a1, void *a2);
78 int BlockAPI();
79 int UnblockAPI();
80 struct_itr_sid_tbl *SetItrSidTbl(int itrsid_index, u16 command, int sema);
81 struct_itr_sid_tbl *GetItrSidTbl(int itrsid_index, u16 command);
82 int ClearItrSidTbl(struct_itr_sid_tbl *a1);
83 struct_itr_sema *AllocItrSema();
84 int ReleaseItrSema(const struct_itr_sema *itrsema);
85 
86 extern struct irx_export_table _exp_pvrdrv;
87 struct_dvrdrv DVRDRV;
88 s32 api_sema_id;
89 s32 phase_sema_id;
90 void (*intrhandler_callbacks[32])(int intrnr, void *arg);
91 int intrhandler_intrnum[32];
92 void *intrhandler_callbacksarg[32];
93 struct_itr_sid_tbl itrsid_table[3][32];
94 struct_itr_sema itr_sema_table[32];
95 
96 int _start(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
97 {
98  if (argc >= 0)
99  return module_start(argc, argv, startaddr, mi);
100  else
101  return module_stop(argc, argv, startaddr, mi);
102 }
103 
104 int module_start(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
105 {
106  (void)argc;
107  (void)argv;
108  (void)startaddr;
109  if (DvrdrvInit() != -1) {
110  if (RegisterLibraryEntries(&_exp_pvrdrv) == 0) {
111 #if 0
112  return MODULE_REMOVABLE_END;
113 #else
114  if (mi && ((mi->newflags & 2) != 0))
115  mi->newflags |= 0x10;
116  return MODULE_RESIDENT_END;
117 #endif
118  }
119  }
120  return MODULE_NO_RESIDENT_END;
121 }
122 
123 int module_stop(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
124 {
125  (void)argc;
126  (void)argv;
127  (void)startaddr;
128  (void)mi;
129 
130  ReleaseLibraryEntries(&_exp_pvrdrv);
131  if (DvrdrvEnd() != 0)
132  return MODULE_REMOVABLE_END;
133  return MODULE_NO_RESIDENT_END;
134 }
135 
136 int DvrdrvInit()
137 {
138  int v0;
139  int v1;
140  iop_sema_t v12;
141  iop_sema_t v13;
142 
143  DVRDRV.mainthread_id = -1;
144  v12.attr = 0;
145  v12.initial = 1;
146  v12.max = 1;
147  v12.option = 0;
148  v0 = CreateSema(&v12);
149  if (v0 < 0)
150  return -1;
151  api_sema_id = v0;
152  v13.attr = 0;
153  v13.initial = 1;
154  v13.max = 1;
155  v13.option = 0;
156  v1 = CreateSema(&v13);
157  if (v1 < 0)
158  return -1;
159  phase_sema_id = v1;
160  v13.attr = 0;
161  v13.initial = 0;
162  v13.max = 1;
163  v13.option = 0;
164  for (int i = 0; i < 32; i += 1) {
165  itr_sema_table[i].sema = CreateSema(&v13);
166  itr_sema_table[i].used = 0;
167  }
168  for (int i = 0; i < 32; i += 1) {
169  intrhandler_callbacks[i] = 0;
170  intrhandler_intrnum[i] = 0;
171  }
172  for (int i = 0; i < 3; i += 1) {
173  for (int j = 0; j < 32; j += 1) {
174  ClearItrSidTbl(&itrsid_table[i][j]);
175  }
176  }
177  SpdRegisterIntrHandler(9, DVR_INTR_HANDLER);
178  DvrdrvRegisterIntrHandler(1, &DVRDRV, INTR_DVRRDY_HANDLER);
179  DvrdrvRegisterIntrHandler(2, &DVRDRV, INTR_CMD_ACK_HANDLER);
180  DvrdrvRegisterIntrHandler(4, &DVRDRV, INTR_CMD_COMP_HANDLER);
181  DvrdrvRegisterIntrHandler(8, &DVRDRV, INTR_DMAACK_HANDLER);
182  DvrdrvRegisterIntrHandler(16, &DVRDRV, INTR_DMAEND_HANDLER);
183  DvrdrvEnableIntr(0x1Fu);
184  dev9RegisterPreDmaCb(2, DvrPreDmaHandler);
185  dev9RegisterPostDmaCb(2, DvrPostDmaHandler);
186  return 0;
187 }
188 
189 int DvrdrvResetSystem()
190 {
191  s32 v0;
192  bool v1;
193  int v2;
194  iop_sys_clock_t v4;
195  USE_SPD_REGS;
196 
197  BlockAPI();
198  SPD_REG8(0x4008) &= 0xFEu;
199  DelayThread(100000);
200  SPD_REG8(0x4008) |= 1u;
201  DVRDRV.mainthread_id = GetThreadId();
202  USec2SysClock(0x1C9C380u, &v4);
203  SetAlarm(&v4, INTR_DVRRDY_TO_HANDLER, &DVRDRV);
204  v0 = SleepThread();
205  CancelAlarm(INTR_DVRRDY_TO_HANDLER, &DVRDRV);
206  v1 = v0 != 0;
207  v2 = -2;
208  if (!v1) {
209  v2 = -1;
210  if ((DVRDRV.dvr_ready & 1) != 0)
211  v2 = 0;
212  DVRDRV.dvr_ready = 0;
213  }
214  DvrdrvDisableIntr(1);
215  UnblockAPI();
216  return v2;
217 }
218 
219 int DvrdrvSendCmdAck(struct_itr_sema *itrsema, u16 command, u16 *input_word, s32 input_word_count, u16 *status_4220, u16 *ack_status, u32 *status_4228)
220 {
221  int v11;
222  int v12;
223  struct_itr_sid_tbl *v14;
224  s32 v15;
225  u16 *v16;
226  s16 v17;
227  int v18;
228  int v20;
229  int v21;
230  s16 v23;
231  unsigned int v24;
232  int v25;
233  s32 i;
234  iop_sys_clock_t v28;
235  USE_SPD_REGS;
236 
237  v11 = -1;
238  v12 = 0;
239  do {
240  if ((SPD_REG16(0x4230) & 2) != 0)
241  break;
242  DelayThread(1000);
243  ++v12;
244  } while (v12 < 100);
245  if (v12 == 100) {
246  printf("DvrdrvSendCmdAck -> Command is running... (Time out)\n");
247  return -2;
248  }
249  BlockAPI();
250  v14 = SetItrSidTbl(0, command, itrsema->sema);
251  if (!v14) {
252  v11 = -1;
253  printf("DvrdrvSendCmdAck() -> SetItrSidTbl Error\n");
254  goto LABEL_44;
255  }
256  SPD_REG16(0x4218) |= 0x80u;
257  while ((SPD_REG16(0x4218) & 0x80) != 0)
258  ;
259  v15 = 0;
260  if (input_word_count > 0) {
261  v16 = input_word;
262  do {
263  v17 = *v16++;
264  ++v15;
265  SPD_REG16(0x4214) = v17;
266  } while (v15 < input_word_count);
267  }
268  USec2SysClock(0x1C9C380u, &v28);
269  v18 = (u16)(command & 0xF00) >> 8;
270  if (v18 == 1) {
271  SetAlarm(&v28, INTR_CMD_ACK_TO_HANDLER, v14);
272  goto LABEL_19;
273  }
274  if (v18 && (u16)(command & 0xF00) >> 8 < 4u) {
275  SetAlarm(&v28, INTR_DMAACK_TO_HANDLER, v14);
276  goto LABEL_19;
277  }
278 LABEL_19:
279  v20 = itrsema->sema;
280  SPD_REG16(0x4210) = command;
281  WaitSema(v20);
282  v21 = (u16)(command & 0xF00) >> 8;
283  if (v21 == 1) {
284  CancelAlarm(INTR_CMD_ACK_TO_HANDLER, v14);
285  } else {
286  if (!v21 || (u16)(command & 0xF00) >> 8 >= 4u) {
287  printf("DvrdrvSendCmdAck() -> Error!\n");
288  goto LABEL_26;
289  }
290  CancelAlarm(INTR_DMAACK_TO_HANDLER, v14);
291  }
292 LABEL_26:
293  if (!v14->timed_out || v14->error) {
294  v23 = v14->error;
295  v24 = command & 0xF00;
296  if ((v23 & 0x8000) == 0) {
297  if (v24 >> 8 == 1) {
298  v11 = 0;
299  if ((v23 & 2) == 0) {
300  v11 = -1;
301  printf("DvrdrvSendCmdAck -> Interrupt Flag Error!,%04X\n", (u16)v14->error);
302  goto LABEL_44;
303  }
304  } else if (v24 >> 8) {
305  if (v24 >> 8 < 4) {
306  v11 = 0;
307  if ((v14->error & 8) == 0) {
308  v11 = -1;
309  goto LABEL_44;
310  }
311  }
312  }
313  v25 = 64;
314  if ((SPD_REG16(0x4228) & 1) == 0)
315  v25 = (u8)(SPD_REG16(0x4228) & 0xFC) >> 2;
316  *status_4228 = v25;
317  for (i = 0; (u32)i < *status_4228; ++ack_status) {
318  ++i;
319  *ack_status = SPD_REG16(0x4224);
320  }
321  *status_4220 = SPD_REG16(0x4220);
322  goto LABEL_44;
323  }
324  v11 = -3;
325  } else {
326  v11 = -2;
327  printf("DvrdrvSendCmdAck() -> TO!\n");
328  }
329 LABEL_44:
330  ClearItrSidTbl(v14);
331  UnblockAPI();
332  return v11;
333 }
334 
335 int DvrdrvSetDmaDirection(u32 arg)
336 {
337  USE_SPD_REGS;
338  if (arg < 2 && (SPD_REG16(0x4100) & 2) != 0) {
339  while ((SPD_REG16(0x4100) & 2) != 0)
340  ;
341  }
342  if ((SPD_REG8(0x4004) & 7) == arg)
343  return 0;
344  SPD_REG8(0x4004) = arg | (SPD_REG8(0x4004) & 0xF8);
345  SPD_REG16(0x4100) |= 1u;
346  while ((SPD_REG16(0x4100) & 1) != 0)
347  ;
348  return 0;
349 }
350 
351 int DvrdrvTransferDma(u8 *output_buffer, int a2)
352 {
353  int v4;
354  int result;
355  int v6;
356  int v7;
357  u32 *v8;
358  USE_SPD_REGS;
359 
360  v4 = 0;
361  if (((u32)output_buffer & 3) != 0)
362  return -1;
363  BlockAPI();
364  v6 = a2 / 128;
365  v7 = a2 % 128;
366  SPD_REG16(0x4108) = a2 / 128;
367  SPD_REG16(0x410C) = 32;
368  v8 = (u32 *)&output_buffer[128 * (u16)(a2 / 128)];
369  switch (SPD_REG8(0x4004) & 7) {
370  case 0:
371  case 2:
372  case 7:
373  v4 = 0;
374  goto LABEL_7;
375  case 1:
376  case 3:
377  v4 = 1;
378  goto LABEL_7;
379  case 4:
380  case 5:
381  case 6:
382  UnblockAPI();
383  return -1;
384  default:
385  LABEL_7:
386  SpdDmaTransfer(2, output_buffer, (v6 << 16) | 0x20, v4);
387  if (v7 > 0) {
388  do {
389  v7 -= 4;
390  SPD_REG16(0x4120) = ((*((u32 *)v8)) & 0x0000FFFF);
391  SPD_REG16(0x4122) = ((*((u32 *)v8)) & 0xFFFF0000) >> 16;
392  v8 += 1;
393  } while (v7 > 0);
394  }
395  UnblockAPI();
396  result = 0;
397  break;
398  }
399  return result;
400 }
401 
402 void DvrPreDmaHandler(int bcr, int dir)
403 {
404  USE_SPD_REGS;
405 
406  (void)bcr;
407  (void)dir;
408 
409  SPD_REG16(0x4100) |= 2u;
410 }
411 
412 void DvrPostDmaHandler(int bcr, int dir)
413 {
414  USE_SPD_REGS;
415 
416  (void)bcr;
417  (void)dir;
418 
419  while ((SPD_REG16(0x4100) & 2) != 0)
420  ;
421 }
422 
423 int DvrdrvPrepareWaitDmaEnd(struct_itr_sema *itrsema, u16 command)
424 {
425  int v4;
426 
427  BlockAPI();
428  if (itrsema) {
429  v4 = 0;
430  SetItrSidTbl(1, command, itrsema->sema);
431  } else {
432  v4 = -1;
433  printf("DvrdrvPrepareWaitDmaEnd : itrsema==NULL\n");
434  }
435  UnblockAPI();
436  return v4;
437 }
438 
439 int DvrdrvCancelWaitDmaEnd(u16 command)
440 {
441  struct_itr_sid_tbl *v2;
442  int v3;
443 
444  BlockAPI();
445  v2 = GetItrSidTbl(1, command);
446  if (v2) {
447  ClearItrSidTbl(v2);
448  v3 = 0;
449  } else {
450  v3 = -1;
451  printf("DvrdrvCancelWaitDmaEnd -> Cannot found Sid!!\n");
452  }
453  UnblockAPI();
454  return v3;
455 }
456 
457 int DvrdrvWaitDmaEnd(struct_itr_sema *itrsema, u16 command)
458 {
459  struct_itr_sid_tbl *v3;
460  s16 v4;
461  int v5;
462  u8 v6;
463  char v10;
464  USE_SPD_REGS;
465 
466  WaitSema(itrsema->sema);
467  v3 = GetItrSidTbl(1, command);
468  v4 = v3->error;
469  v5 = -3;
470  if ((v4 & 0x8000) == 0) {
471  if ((v4 & 0x10) != 0) {
472  int v7;
473 
474  v5 = 0;
475  if ((SPD_REG16(0x4228) & 1) != 0)
476  v6 = 64;
477  else
478  v6 = (u8)(SPD_REG16(0x4228) & 0xFC) >> 2;
479  v7 = 0;
480  if (v6) {
481  char *v8;
482 
483  v8 = &v10;
484  do {
485  ++v7;
486  *(u16 *)v8 = SPD_REG16(0x4224);
487  v8 += 2;
488  } while (v7 < v6);
489  }
490  } else {
491  v5 = -1;
492  printf("DvrdrvWaitDmaEnd -> Interrupt Flag Error!,%04X\n", (u16)v3->error);
493  }
494  }
495  ClearItrSidTbl(v3);
496  return v5;
497 }
498 
499 int DvrdrvPrepareWaitCmdComp(struct_itr_sema *itrsema, u16 command, u32 timeout)
500 {
501  int v6;
502  iop_sys_clock_t v10;
503 
504  BlockAPI();
505  if (itrsema) {
506  int v7;
507  struct_itr_sid_tbl *v8;
508  v7 = itrsema->sema;
509  v6 = 0;
510  v8 = SetItrSidTbl(2, command, v7);
511  USec2SysClock(timeout, &v10);
512  SetAlarm(&v10, INTR_CMD_COMP_TO_HANDLER, v8);
513  } else {
514  v6 = -1;
515  printf("DvrdrvPrepareWaitCmdComp : itrsema==NULL\n");
516  }
517  UnblockAPI();
518  return v6;
519 }
520 
521 int DvrdrvCancelWaitCmdComp(u16 command)
522 {
523  struct_itr_sid_tbl *v2;
524  struct_itr_sid_tbl *v3;
525  int v4;
526 
527  BlockAPI();
528  v2 = GetItrSidTbl(2, command);
529  v3 = v2;
530  if (v2) {
531  CancelAlarm(INTR_CMD_COMP_TO_HANDLER, v2);
532  ClearItrSidTbl(v3);
533  v4 = 0;
534  } else {
535  v4 = -1;
536  printf("DvrdrvCancelWaitCmdComp -> Cannot found Sid!!\n");
537  }
538  UnblockAPI();
539  return v4;
540 }
541 
542 int DvrdrvWaitCmdComp(struct_itr_sema *itrsema, u16 command, u16 *status_4220, u16 *comp_status, u32 *status_4228)
543 {
544  struct_itr_sid_tbl *v8;
545  int v9;
546  s32 v12;
547  USE_SPD_REGS;
548 
549  WaitSema(itrsema->sema);
550  v8 = GetItrSidTbl(2, command);
551  CancelAlarm(INTR_CMD_COMP_TO_HANDLER, v8);
552  v9 = -2;
553  if (!v8->timed_out) {
554  s16 v10;
555  v10 = v8->error;
556  v9 = -3;
557  if ((v10 & 0x8000) == 0) {
558  if ((v10 & 4) != 0) {
559  int v11;
560  v9 = 0;
561  if ((SPD_REG16(0x4228) & 1) != 0)
562  v11 = 64;
563  else
564  v11 = (u8)(SPD_REG16(0x4228) & 0xFC) >> 2;
565  *status_4228 = v11;
566  v12 = 0;
567  if (*status_4228 > 0) {
568  u16 *v13;
569 
570  v13 = comp_status;
571  do {
572  ++v12;
573  *v13++ = SPD_REG16(0x4224);
574  } while ((u32)v12 < *status_4228);
575  }
576  *status_4220 = SPD_REG16(0x4220);
577  } else {
578  v9 = -1;
579  printf("DvrdrvWaitCmdComp -> Interrupt Flag Error!,%04X\n", (u16)v8->error);
580  }
581  }
582  }
583  ClearItrSidTbl(v8);
584  return v9;
585 }
586 
587 s32 DvrdrvBlockPhase()
588 {
589  return WaitSema(phase_sema_id);
590 }
591 
592 s32 DvrdrvUnblockPhase()
593 {
594  return SignalSema(phase_sema_id);
595 }
596 
597 int DvrdrvEnableIntr(u16 a1)
598 {
599  int state;
600  USE_SPD_REGS;
601 
602  CpuSuspendIntr(&state);
603  SPD_REG16(0x4208) |= a1;
604  SpdIntrEnable(0x200);
605  CpuResumeIntr(state);
606  return 0;
607 }
608 
609 int DvrdrvDisableIntr(s16 a1)
610 {
611  int state;
612  USE_SPD_REGS;
613 
614  CpuSuspendIntr(&state);
615  SPD_REG16(0x4208) &= ~a1;
616  SPD_REG16(0x4204) = a1;
617  if (!SPD_REG16(0x4208))
618  SpdIntrDisable(0x200);
619  CpuResumeIntr(state);
620  return 0;
621 }
622 
623 int DvrdrvRegisterIntrHandler(int a1, void *arg, void (*a3)(int intrnr, void *arg))
624 {
625  int i;
626 
627  BlockAPI();
628  for (i = 0; i < 32; i += 1)
629  {
630  if (intrhandler_callbacks[i] == NULL)
631  {
632  intrhandler_callbacks[i] = a3;
633  intrhandler_intrnum[i] = a1;
634  intrhandler_callbacksarg[i] = arg;
635  UnblockAPI();
636  return 0;
637  }
638  }
639  UnblockAPI();
640  return -1;
641 }
642 
643 int DvrdrvUnregisterIntrHandler(void (*a1)(int intrnr, void *arg))
644 {
645  int i;
646 
647  BlockAPI();
648  for (i = 0; i < 32; i += 1)
649  {
650  if (intrhandler_callbacks[i] == a1)
651  {
652  intrhandler_callbacks[i] = NULL;
653  intrhandler_intrnum[i] = 0;
654  intrhandler_callbacksarg[i] = 0;
655  UnblockAPI();
656  return 0;
657  }
658  }
659  UnblockAPI();
660  return -1;
661 }
662 
663 int DvrdrvEnd()
664 {
665  int result;
666 
667  result = -1;
668  if (api_sema_id < 0)
669  return result;
670  result = -1;
671  if (phase_sema_id < 0)
672  return result;
673  DvrdrvDisableIntr(0x801F);
674  DvrdrvUnregisterIntrHandler((void *)INTR_DVRRDY_HANDLER);
675  DvrdrvUnregisterIntrHandler((void *)INTR_CMD_ACK_HANDLER);
676  DvrdrvUnregisterIntrHandler((void *)INTR_CMD_COMP_HANDLER);
677  DvrdrvUnregisterIntrHandler((void *)INTR_DMAACK_HANDLER);
678  DvrdrvUnregisterIntrHandler((void *)INTR_DMAEND_HANDLER);
679  DeleteSema(api_sema_id);
680  DeleteSema(phase_sema_id);
681  api_sema_id = -1;
682  phase_sema_id = -1;
683 #if 0
684  for (int i = 0; i < 32; i += 1) {
685  DeleteSema(itr_sema_table[i].sema);
686  }
687 #endif
688  return 0;
689 }
690 
691 int DVR_INTR_HANDLER(int flag)
692 {
693  int i;
694  s16 v1;
695  int v4;
696  USE_SPD_REGS;
697 
698  (void)flag;
699 
700  v1 = 0;
701  v4 = SPD_REG16(0x4200);
702  for (i = 0; i < 32; i += 1)
703  {
704  if ((intrhandler_intrnum[i] & v4) != 0)
705  {
706  if (intrhandler_callbacks[i])
707  {
708  intrhandler_callbacks[i](v4, intrhandler_callbacksarg[i]);
709  v1 |= intrhandler_intrnum[i];
710  }
711  }
712  }
713  SPD_REG16(0x4204) = v1;
714  return 1;
715 }
716 
717 void INTR_DVRRDY_HANDLER(int a1, void *a2v)
718 {
719  struct_dvrdrv *a2 = (struct_dvrdrv *)a2v;
720 
721  (void)a1;
722 
723  a2->dvr_ready |= 1u;
724  if (a2->mainthread_id >= 0)
725  iWakeupThread(a2->mainthread_id);
726 }
727 
728 unsigned int INTR_DVRRDY_TO_HANDLER(void *a1)
729 {
730  s32 v1;
731 
732  v1 = *(s32 *)a1;
733  if (v1 >= 0)
734  iReleaseWaitThread(v1);
735  return 0;
736 }
737 
738 void INTR_CMD_ACK_HANDLER(int a1, void *a2)
739 {
740  struct_itr_sid_tbl *v2;
741  s32 v6;
742  char v7;
743  USE_SPD_REGS;
744 
745  (void)a1;
746  (void)a2;
747 
748  v2 = GetItrSidTbl(0, SPD_REG16(0x4220));
749  if (v2) {
750  v6 = v2->sema;
751  v2->error |= 2u;
752  if (v6 < 0)
753  Kprintf("Illegal Sema ID : %d\n", v6);
754  else
755  iSignalSema(v6);
756  } else {
757  int v3;
758  int v4;
759 
760  Kprintf("ACK:GetItrSidTbl(%04Xh) error\n", SPD_REG16(0x4220));
761  Kprintf("Clear \"Reply FIFO\"\n");
762  v3 = 64;
763  if ((SPD_REG16(0x4228) & 1) == 0)
764  v3 = (u8)(SPD_REG16(0x4228) & 0xFC) >> 2;
765  v4 = 0;
766  if (v3) {
767  char *v5;
768 
769  v5 = &v7;
770  do {
771  ++v4;
772  *(u16 *)v5 = SPD_REG16(0x4224);
773  v5 += 2;
774  } while (v4 < v3);
775  }
776  }
777 }
778 
779 unsigned int INTR_CMD_ACK_TO_HANDLER(void *arg)
780 {
781  unsigned int v1;
782  s32 v3;
783  iop_sys_clock_t clock;
784  struct_itr_sid_tbl *a1;
785 
786  a1 = (struct_itr_sid_tbl *)arg;
787  GetSystemTime(&clock);
788  v1 = clock.lo;
789  Kprintf("CMDACK_TO:[%u]\n", v1);
790  v3 = a1->sema;
791  a1->timed_out = 1;
792  iSignalSema(v3);
793  return 0;
794 }
795 
796 void INTR_CMD_COMP_HANDLER(int a1, void *a2)
797 {
798  struct_itr_sid_tbl *v2;
799  s32 v6;
800  char v7;
801  USE_SPD_REGS;
802 
803  (void)a1;
804  (void)a2;
805 
806  v2 = GetItrSidTbl(2, SPD_REG16(0x4220));
807  if (v2) {
808  v6 = v2->sema;
809  v2->error |= 4u;
810  if (v6 < 0)
811  Kprintf("Illegal thread ID : %d\n", v6);
812  else
813  iSignalSema(v6);
814  } else {
815  int v3;
816  int v4;
817 
818  Kprintf("COMP:GetItrSidTbl(%04Xh) error\n", SPD_REG16(0x4220));
819  Kprintf("Clear \"Reply FIFO\"\n");
820  v3 = 64;
821  if ((SPD_REG16(0x4228) & 1) == 0)
822  v3 = (u8)(SPD_REG16(0x4228) & 0xFC) >> 2;
823  v4 = 0;
824  if (v3) {
825  char *v5;
826 
827  v5 = &v7;
828  do {
829  ++v4;
830  *(u16 *)v5 = SPD_REG16(0x4224);
831  v5 += 2;
832  } while (v4 < v3);
833  }
834  }
835 }
836 
837 unsigned int INTR_CMD_COMP_TO_HANDLER(void *arg)
838 {
839  unsigned int v1;
840  s32 v3;
841  iop_sys_clock_t clock;
842  struct_itr_sid_tbl *a1;
843 
844  a1 = (struct_itr_sid_tbl *)arg;
845  GetSystemTime(&clock);
846  v1 = clock.lo;
847  Kprintf("COMP TO:[%u]\n", v1);
848  v3 = a1->sema;
849  a1->timed_out = 1;
850  iSignalSema(v3);
851  return 0;
852 }
853 
854 void INTR_DMAACK_HANDLER(int a1, void *a2)
855 {
856  struct_itr_sid_tbl *v2;
857  s32 v3;
858  USE_SPD_REGS;
859 
860  (void)a1;
861  (void)a2;
862 
863  v2 = GetItrSidTbl(0, SPD_REG16(0x4220));
864  if (v2) {
865  v3 = v2->sema;
866  v2->error |= 8u;
867  if (v3 < 0)
868  Kprintf("Illegal thread ID : %d\n", v3);
869  else
870  iSignalSema(v3);
871  } else {
872  Kprintf("GetItrSidTbl(%04Xh) error\n", SPD_REG16(0x4220));
873  }
874 }
875 
876 unsigned int INTR_DMAACK_TO_HANDLER(void *arg)
877 {
878  unsigned int v1;
879  iop_sys_clock_t clock;
880  struct_itr_sid_tbl *a1;
881 
882  a1 = (struct_itr_sid_tbl *)arg;
883  GetSystemTime(&clock);
884  v1 = clock.lo;
885  Kprintf("DMAACK_TO:[%u]\n", v1);
886  GetItrSidTbl(0, a1->command)->timed_out = 1;
887  iSignalSema(a1->sema);
888  return 0;
889 }
890 
891 void INTR_DMAEND_HANDLER(int a1, void *a2)
892 {
893  struct_itr_sid_tbl *v2;
894  s32 v3;
895  USE_SPD_REGS;
896 
897  (void)a1;
898  (void)a2;
899 
900  v2 = GetItrSidTbl(1, SPD_REG16(0x4220));
901  if (v2) {
902  v3 = v2->sema;
903  v2->error |= 0x10u;
904  if (v3 < 0)
905  Kprintf("Illegal thread ID : %d\n", v3);
906  else
907  iSignalSema(v3);
908  } else {
909  Kprintf("GetItrSidTbl(%04Xh) error\n", SPD_REG16(0x4220));
910  }
911 }
912 
913 int BlockAPI()
914 {
915  WaitSema(api_sema_id);
916  return 0;
917 }
918 
919 int UnblockAPI()
920 {
921  SignalSema(api_sema_id);
922  return 0;
923 }
924 
925 struct_itr_sid_tbl *SetItrSidTbl(int itrsid_index, u16 command, int sema)
926 {
927  int state;
928  int i = 0;
929 
930  CpuSuspendIntr(&state);
931  for (i = 0; i < 32; i += 1) {
932  if (itrsid_table[itrsid_index][i].sema == -1 || itrsid_table[itrsid_index][i].command == command) {
933  itrsid_table[itrsid_index][i].command = command;
934  itrsid_table[itrsid_index][i].sema = sema;
935  itrsid_table[itrsid_index][i].error = 0;
936  break;
937  }
938  }
939  CpuResumeIntr(state);
940  if (i != 32)
941  return &itrsid_table[itrsid_index][i];
942  Kprintf("SetItrSidTbl : Error!\n");
943  return 0;
944 }
945 
946 struct_itr_sid_tbl *GetItrSidTbl(int itrsid_index, u16 command)
947 {
948  int state;
949  int i = 0;
950 
951  CpuSuspendIntr(&state);
952  for (i = 0; i < 32; i += 1) {
953  if (itrsid_table[itrsid_index][i].command == command) {
954  break;
955  }
956  }
957  CpuResumeIntr(state);
958  if (i != 32)
959  return &itrsid_table[itrsid_index][i];
960  Kprintf("GetItrSidTbl : Error!\n");
961  return 0;
962 }
963 
964 int ClearItrSidTbl(struct_itr_sid_tbl *a1)
965 {
966  int v2;
967  int state;
968 
969  CpuSuspendIntr(&state);
970  a1->timed_out = 0;
971  v2 = state;
972  a1->command = 0;
973  a1->sema = -1;
974  a1->error = 0;
975  return CpuResumeIntr(v2);
976 }
977 
978 struct_itr_sema *AllocItrSema()
979 {
980  int i;
981  struct_itr_sema *result;
982  int state;
983 
984  result = 0;
985  CpuSuspendIntr(&state);
986  for (i = 0; i < 32; i += 1)
987  {
988  if (!itr_sema_table[i].used)
989  {
990  itr_sema_table[i].used = 1;
991  result = &itr_sema_table[i];
992  break;
993  }
994  }
995  CpuResumeIntr(state);
996  if (result)
997  return result;
998  printf("AllocItrSema : empty\n");
999  return 0;
1000 }
1001 
1002 int ReleaseItrSema(const struct_itr_sema *itrsema)
1003 {
1004  int i;
1005  int result;
1006  int state;
1007 
1008  CpuSuspendIntr(&state);
1009  for (i = 0; i < 32; i += 1)
1010  {
1011  if (&itr_sema_table[i] == itrsema)
1012  {
1013  itr_sema_table[i].used = 0;
1014  break;
1015  }
1016  }
1017  CpuResumeIntr(state);
1018  result = 0;
1019  if (i != 32)
1020  return result;
1021  printf("ReleaseItrSema : full\n");
1022  return -1;
1023 }
1024 
1025 int DvrdrvExecCmdAck(drvdrv_exec_cmd_ack *a1)
1026 {
1027  struct_itr_sema *v2;
1028  u16 v3;
1029  int result;
1030 
1031  v2 = AllocItrSema();
1032  if (v2) {
1033  int v4;
1034 
1035  DvrdrvBlockPhase();
1036  v3 = a1->command;
1037  a1->phase = 1;
1038  v4 = DvrdrvSendCmdAck(
1039  v2,
1040  v3,
1041  a1->input_word,
1042  a1->input_word_count,
1043  &a1->status_4220_ack,
1044  &a1->ack_status_ack,
1045  &a1->status_4228_ack);
1046  DvrdrvUnblockPhase();
1047  ReleaseItrSema(v2);
1048  result = v4;
1049  } else {
1050  printf("DvrdrvExecCmdAck : Cannot alloc sema\n");
1051  result = -1;
1052  }
1053  return result;
1054 }
1055 
1056 int DvrdrvExecCmdAckComp(drvdrv_exec_cmd_ack *a1)
1057 {
1058  struct_itr_sema *v2;
1059  struct_itr_sema *v3;
1060  int result;
1061  u16 v5;
1062  u16 v7;
1063 
1064  v2 = AllocItrSema();
1065  v3 = v2;
1066  if (v2) {
1067  int v6;
1068 
1069  DvrdrvPrepareWaitCmdComp(v2, a1->command, a1->timeout);
1070  DvrdrvBlockPhase();
1071  v5 = a1->command;
1072  a1->phase = 1;
1073  v6 = DvrdrvSendCmdAck(
1074  v3,
1075  v5,
1076  a1->input_word,
1077  a1->input_word_count,
1078  &a1->status_4220_ack,
1079  &a1->ack_status_ack,
1080  &a1->status_4228_ack);
1081  if (v6) {
1082  DvrdrvCancelWaitCmdComp(a1->command);
1083  DvrdrvUnblockPhase();
1084  } else {
1085  DvrdrvUnblockPhase();
1086  v7 = a1->command;
1087  a1->phase = 4;
1088  v6 = DvrdrvWaitCmdComp(v3, v7, &a1->status_4220_comp, &a1->comp_status, &a1->status_4228_comp);
1089  }
1090  ReleaseItrSema(v3);
1091  result = v6;
1092  } else {
1093  printf("DvrdrvExecCmdAck : Cannot alloc sema\n");
1094  result = -1;
1095  }
1096  return result;
1097 }
1098 
1099 int DvrdrvExecCmdAckDmaSendComp(drvdrv_exec_cmd_ack *a1)
1100 {
1101  struct_itr_sema *v2;
1102  struct_itr_sema *v3;
1103  int v5;
1104  int v6;
1105  u16 v7;
1106  int v8;
1107  s16 v9;
1108  struct_itr_sema *v10;
1109  u16 v11;
1110  u16 v12;
1111  u16 v13[65];
1112  s32 input_word_count;
1113  u16 v15;
1114  u16 ack_status[65];
1115  u32 v17[37];
1116  int v18;
1117 
1118  v2 = AllocItrSema();
1119  v3 = v2;
1120  if (!v2) {
1121  printf("DvrdrvExecCmdAck : Cannot alloc sema\n");
1122  return -1;
1123  }
1124  DvrdrvPrepareWaitCmdComp(v2, a1->command, a1->timeout);
1125  a1->phase = 1;
1126  DvrdrvBlockPhase();
1127  v5 = DvrdrvSendCmdAck(
1128  v3,
1129  a1->command,
1130  a1->input_word,
1131  a1->input_word_count,
1132  &a1->status_4220_ack,
1133  &a1->ack_status_ack,
1134  &a1->status_4228_ack);
1135  v6 = v5;
1136  if (v5) {
1137  printf("Phase1 error -> %d\n", v5);
1138  v7 = a1->command;
1139  } else {
1140  DvrdrvUnblockPhase();
1141  a1->phase = 2;
1142  DvrdrvBlockPhase();
1143  DvrdrvSetDmaDirection(1u);
1144  v8 = a1->input_buffer_length;
1145  if ((v8 & 0x7F) != 0)
1146  v18 = (v8 / 128 + 1) << 7;
1147  else
1148  v18 = a1->input_buffer_length;
1149  v9 = a1->command;
1150  input_word_count = 2;
1151  v12 = (v9 & 0xF0FF) | 0x200;
1152  v13[0] = (v18 & 0xFFFF0000) >> 16;
1153  v13[1] = v18;
1154  v10 = AllocItrSema();
1155  DvrdrvPrepareWaitDmaEnd(v10, v12);
1156  v6 = DvrdrvSendCmdAck(v3, v12, v13, input_word_count, &v15, ack_status, v17);
1157  if (v6) {
1158  v7 = a1->command;
1159  } else {
1160  v6 = -1;
1161  if (!ack_status[0]) {
1162  if (v18 <= 0) {
1163  DvrdrvCancelWaitDmaEnd(v12);
1164  } else {
1165  DvrdrvTransferDma(a1->input_buffer, v18);
1166  DvrdrvWaitDmaEnd(v10, v12);
1167  }
1168  ReleaseItrSema(v10);
1169  DvrdrvUnblockPhase();
1170  v11 = a1->command;
1171  a1->phase = 4;
1172  v6 = DvrdrvWaitCmdComp(v3, v11, &a1->status_4220_comp, &a1->comp_status, &a1->status_4228_comp);
1173  goto LABEL_17;
1174  }
1175  v7 = a1->command;
1176  }
1177  }
1178  DvrdrvCancelWaitCmdComp(v7);
1179  DvrdrvUnblockPhase();
1180 LABEL_17:
1181  ReleaseItrSema(v3);
1182  return v6;
1183 }
1184 
1185 int DvrdrvExecCmdAckDmaRecvComp(drvdrv_exec_cmd_ack *a1)
1186 {
1187  struct_itr_sema *v2;
1188  struct_itr_sema *v3;
1189  int v5;
1190  u16 v6;
1191  s16 v7;
1192  struct_itr_sema *v8;
1193  int v9;
1194  u16 v10;
1195  u16 v11;
1196  u16 v12[65];
1197  s32 input_word_count;
1198  u16 v14;
1199  u16 ack_status[65];
1200  u32 v16[41];
1201 
1202  v2 = AllocItrSema();
1203  v3 = v2;
1204  if (!v2) {
1205  printf("DvrdrvExecCmdAck : Cannot alloc sema\n");
1206  return -1;
1207  }
1208  DvrdrvPrepareWaitCmdComp(v2, a1->command, a1->timeout);
1209  a1->phase = 1;
1210  DvrdrvBlockPhase();
1211  v5 = DvrdrvSendCmdAck(
1212  v3,
1213  a1->command,
1214  a1->input_word,
1215  a1->input_word_count,
1216  &a1->status_4220_ack,
1217  &a1->ack_status_ack,
1218  &a1->status_4228_ack);
1219  if (v5) {
1220  v6 = a1->command;
1221  } else {
1222  DvrdrvUnblockPhase();
1223  a1->phase = 3;
1224  DvrdrvBlockPhase();
1225  DvrdrvSetDmaDirection(0);
1226  v7 = a1->command;
1227  input_word_count = 0;
1228  v11 = (v7 & 0xF0FF) | 0x300;
1229  v8 = AllocItrSema();
1230  DvrdrvPrepareWaitDmaEnd(v8, v11);
1231  v5 = DvrdrvSendCmdAck(v3, v11, v12, input_word_count, &v14, ack_status, v16);
1232  if (v5) {
1233  v6 = a1->command;
1234  } else {
1235  v5 = -1;
1236  if (!ack_status[0]) {
1237  v9 = (ack_status[1] << 16) + ack_status[2];
1238  a1->ack_status_ack2 = v9;
1239  if (v9 <= 0) {
1240  DvrdrvCancelWaitDmaEnd(v11);
1241  } else {
1242  DvrdrvTransferDma((u8 *)a1->output_buffer, v9);
1243  DvrdrvWaitDmaEnd(v8, v11);
1244  }
1245  ReleaseItrSema(v8);
1246  DvrdrvUnblockPhase();
1247  v10 = a1->command;
1248  a1->phase = 4;
1249  v5 = DvrdrvWaitCmdComp(v3, v10, &a1->status_4220_comp, &a1->comp_status, &a1->status_4228_comp);
1250  goto LABEL_14;
1251  }
1252  v6 = a1->command;
1253  }
1254  }
1255  DvrdrvCancelWaitCmdComp(v6);
1256  DvrdrvUnblockPhase();
1257 LABEL_14:
1258  ReleaseItrSema(v3);
1259  return v5;
1260 }
1261 
1262 int DvrdrvExecCmdAckDma2Comp(drvdrv_exec_cmd_ack *a1)
1263 {
1264  struct_itr_sema *v2;
1265  struct_itr_sema *v3;
1266  int v5;
1267  int v6;
1268  s16 v7;
1269  struct_itr_sema *v8;
1270  u16 v9;
1271  s16 v10;
1272  struct_itr_sema *v11;
1273  int v12;
1274  u16 v13;
1275  u16 v14;
1276  u16 v15[65];
1277  s32 input_word_count;
1278  u16 v17;
1279  u16 ack_status[65];
1280  u32 v19[37];
1281  int v20;
1282  u16 v21;
1283  u16 v22[65];
1284  s32 v23;
1285  u16 v24;
1286  u16 v25[65];
1287  u32 v26[41];
1288 
1289  v2 = AllocItrSema();
1290  v3 = v2;
1291  if (!v2) {
1292  printf("DvrdrvExecCmdAck : Cannot alloc sema\n");
1293  return -1;
1294  }
1295  DvrdrvPrepareWaitCmdComp(v2, a1->command, a1->timeout);
1296  a1->phase = 1;
1297  DvrdrvBlockPhase();
1298  v5 = DvrdrvSendCmdAck(
1299  v3,
1300  a1->command,
1301  a1->input_word,
1302  a1->input_word_count,
1303  &a1->status_4220_ack,
1304  &a1->ack_status_ack,
1305  &a1->status_4228_ack);
1306  if (v5)
1307  goto LABEL_15;
1308  DvrdrvUnblockPhase();
1309  a1->phase = 2;
1310  DvrdrvBlockPhase();
1311  DvrdrvSetDmaDirection(1u);
1312  v6 = a1->input_buffer_length;
1313  v20 = (v6 & 0x7F) != 0 ? (u32)((v6 / 128 + 1) << 7) : a1->input_buffer_length;
1314  v7 = a1->command;
1315  input_word_count = 2;
1316  v14 = (v7 & 0xF0FF) | 0x200;
1317  v15[0] = (v20 & 0xFFFF0000) >> 16;
1318  v15[1] = v20;
1319  v8 = AllocItrSema();
1320  DvrdrvPrepareWaitDmaEnd(v8, v14);
1321  v5 = DvrdrvSendCmdAck(v3, v14, v15, input_word_count, &v17, ack_status, v19);
1322  if (v5) {
1323  LABEL_15:
1324  v9 = a1->command;
1325  goto LABEL_16;
1326  }
1327  v5 = -1;
1328  if (!ack_status[0]) {
1329  if (v20 <= 0) {
1330  DvrdrvCancelWaitDmaEnd(v14);
1331  } else {
1332  DvrdrvTransferDma(a1->input_buffer, v20);
1333  DvrdrvWaitDmaEnd(v8, v14);
1334  }
1335  ReleaseItrSema(v8);
1336  DvrdrvUnblockPhase();
1337  a1->phase = 3;
1338  DvrdrvBlockPhase();
1339  DvrdrvSetDmaDirection(0);
1340  v10 = a1->command;
1341  v23 = 0;
1342  v21 = (v10 & 0xF0FF) | 0x300;
1343  v11 = AllocItrSema();
1344  DvrdrvPrepareWaitDmaEnd(v11, v21);
1345  v5 = DvrdrvSendCmdAck(v3, v21, v22, v23, &v24, v25, v26);
1346  if (!v5 && !v25[0]) {
1347  v12 = (v25[1] << 16) + v25[2];
1348  a1->ack_status_ack2 = v12;
1349  if (v12 <= 0) {
1350  DvrdrvCancelWaitDmaEnd(v21);
1351  } else {
1352  DvrdrvTransferDma((u8 *)a1->output_buffer, v12);
1353  DvrdrvWaitDmaEnd(v11, v21);
1354  }
1355  ReleaseItrSema(v11);
1356  DvrdrvUnblockPhase();
1357  v13 = a1->command;
1358  a1->phase = 4;
1359  v5 = DvrdrvWaitCmdComp(v3, v13, &a1->status_4220_comp, &a1->comp_status, &a1->status_4228_comp);
1360  goto LABEL_21;
1361  }
1362  goto LABEL_15;
1363  }
1364  v9 = a1->command;
1365 LABEL_16:
1366  DvrdrvCancelWaitCmdComp(v9);
1367  DvrdrvUnblockPhase();
1368 LABEL_21:
1369  ReleaseItrSema(v3);
1370  return v5;
1371 }
_ModuleInfo::newflags
u16 newflags
Definition: loadcore.h:36
speedregs.h
thbase.h
iop_sema_t
Definition: thsemap.h:38
struct_dvrdrv_
Definition: dvrdrv.c:45
CpuSuspendIntr
int CpuSuspendIntr(int *state)
Definition: intrman.c:195
loadcore.h
irx.h
pvrdrv.h
thsemap.h
irx_export_table
Definition: irx.h:90
tamtypes.h
stdio.h
CpuResumeIntr
int CpuResumeIntr(int state)
Definition: intrman.c:217
sysmem.h
__attribute__
Definition: gif_registers.h:38
dev9.h
struct_itr_sid_tbl_
Definition: dvrdrv.c:29
intrman.h
_ModuleInfo
Definition: loadcore.h:31
_iop_sys_clock
Definition: thbase.h:87