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);
70unsigned int INTR_DVRRDY_TO_HANDLER(void *a1);
71void INTR_CMD_ACK_HANDLER(int a1, void *a2);
72unsigned int INTR_CMD_ACK_TO_HANDLER(void *arg);
73void INTR_CMD_COMP_HANDLER(int a1, void *a2);
74unsigned int INTR_CMD_COMP_TO_HANDLER(void *arg);
75void INTR_DMAACK_HANDLER(int a1, void *a2);
76unsigned int INTR_DMAACK_TO_HANDLER(void *arg);
77void INTR_DMAEND_HANDLER(int a1, void *a2);
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 intrnr, void *arg);
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, 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
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 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 }
278LABEL_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 }
292LABEL_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 }
329LABEL_44:
330 ClearItrSidTbl(v14);
331 UnblockAPI();
332 return v11;
333}
334
335int 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
351int 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
402void 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
412void 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
423int 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
439int DvrdrvCancelWaitDmaEnd(u16 command)
440{
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
457int DvrdrvWaitDmaEnd(struct_itr_sema *itrsema, u16 command)
458{
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
499int 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;
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
521int DvrdrvCancelWaitCmdComp(u16 command)
522{
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
542int DvrdrvWaitCmdComp(struct_itr_sema *itrsema, u16 command, u16 *status_4220, u16 *comp_status, u32 *status_4228)
543{
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
587s32 DvrdrvBlockPhase()
588{
589 return WaitSema(phase_sema_id);
590}
591
592s32 DvrdrvUnblockPhase()
593{
594 return SignalSema(phase_sema_id);
595}
596
597int 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
609int 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
623int 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
643int 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
663int 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
691int 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
717void 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
728unsigned 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
738void INTR_CMD_ACK_HANDLER(int a1, void *a2)
739{
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
779unsigned int INTR_CMD_ACK_TO_HANDLER(void *arg)
780{
781 unsigned int v1;
782 s32 v3;
783 iop_sys_clock_t clock;
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
796void INTR_CMD_COMP_HANDLER(int a1, void *a2)
797{
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
837unsigned int INTR_CMD_COMP_TO_HANDLER(void *arg)
838{
839 unsigned int v1;
840 s32 v3;
841 iop_sys_clock_t clock;
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
854void INTR_DMAACK_HANDLER(int a1, void *a2)
855{
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
876unsigned int INTR_DMAACK_TO_HANDLER(void *arg)
877{
878 unsigned int v1;
879 iop_sys_clock_t clock;
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
891void INTR_DMAEND_HANDLER(int a1, void *a2)
892{
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
913int BlockAPI()
914{
915 WaitSema(api_sema_id);
916 return 0;
917}
918
919int UnblockAPI()
920{
921 SignalSema(api_sema_id);
922 return 0;
923}
924
925struct_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
946struct_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
964int 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
978struct_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
1002int 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
1025int 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
1056int 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
1099int 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();
1180LABEL_17:
1181 ReleaseItrSema(v3);
1182 return v6;
1183}
1184
1185int 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();
1257LABEL_14:
1258 ReleaseItrSema(v3);
1259 return v5;
1260}
1261
1262int 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;
1365LABEL_16:
1366 DvrdrvCancelWaitCmdComp(v9);
1367 DvrdrvUnblockPhase();
1368LABEL_21:
1369 ReleaseItrSema(v3);
1370 return v5;
1371}
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
u16 newflags
Definition loadcore.h:36