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