PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
spu2.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2004, 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# Based on freesd source
11*/
12
13#ifndef LIBSD
14
15#include "types.h"
16#include <stdarg.h>
17#include "spu2regs.h"
18#include "freesd.h"
19#include "thbase.h"
20#include "intrman.h"
21#include "loadcore.h"
22
23// block
24u32 BlockTransBuff[2];
25u32 BlockTransAddr[2];
26u32 BlockTransSize[2];
27
28// voice
29#ifndef ISJPCM
30u32 VoiceTransStatus[2];
31volatile u16 VoiceTransComplete[2];
32u32 VoiceTransIoMode[2];
33#endif
34// Global
35
36sceSdTransIntrHandler TransIntrHandlers[2];
37SdIntrCallback TransIntrCallbacks[2];
38#ifndef ISJPCM
39u16 SpdifSettings;
40void *Spu2IntrData;
41sceSdSpu2IntrHandler Spu2IntrHandler;
42SdIntrCallback Spu2IrqCallback;
43#endif
44IntrData TransIntrData[2];
45
46#ifndef ISJPCM
47volatile u16 *ParamRegList[] =
48 {
49 SD_VP_VOLL(0, 0), SD_VP_VOLR(0, 0), SD_VP_PITCH(0, 0), SD_VP_ADSR1(0, 0),
50 SD_VP_ADSR2(0, 0), SD_VP_ENVX(0, 0), SD_VP_VOLXL(0, 0), SD_VP_VOLXR(0, 0),
51 SD_P_MMIX(0), SD_P_MVOLL(0), SD_P_MVOLR(0), SD_P_EVOLL(0),
52 SD_P_EVOLR(0), SD_P_AVOLL(0), SD_P_AVOLR(0), SD_P_BVOLL(0),
53 SD_P_BVOLR(0), SD_P_MVOLXL(0), SD_P_MVOLXR(0), SD_S_PMON_HI(0),
54 SD_S_NON_HI(0), SD_A_KON_HI(0), SD_A_KON_HI(0), SD_S_ENDX_HI(0),
55 SD_S_VMIXL_HI(0), SD_S_VMIXEL_HI(0), SD_S_VMIXR_HI(0), SD_S_VMIXER_HI(0),
56 SD_A_ESA_HI(0), SD_A_EEA_HI(0), SD_A_TSA_HI(0), SD_CORE_IRQA(0),
57 SD_VA_SSA_HI(0, 0), SD_VA_LSAX(0, 0), SD_VA_NAX(0, 0), SD_CORE_ATTR(0),
58 SD_A_TSA_HI(0), SD_A_STD(0),
59 // 1AE & 1B0 are both related to core attr & dma somehow
60 U16_REGISTER(0x1AE), U16_REGISTER(0x1B0),
61 (u16 *)0xBF900334
62
63};
64#endif
65
66int TransInterrupt(void *data)
67{
68 IntrData *intr = (IntrData *)data;
69 s32 dir;
70 s32 core;
71
72 dir = ((intr->mode & 0x200) < 1);
73 core = intr->mode & 0xFF;
74
75 // Voice Transfer
76 if ((intr->mode & 0x100) == 0) {
77#ifndef ISJPCM
78 // SD_C_STATX(core)
79 // If done elsewise, it doesn't work, havn't figured out why yet.
80 volatile u16 *statx = U16_REGISTER(0x344 + (core * 1024));
81
82 while ((*statx & 0x80) == 0)
83 ;
84
85 *SD_CORE_ATTR(core) &= ~SD_CORE_DMA;
86
87 while ((*SD_CORE_ATTR(core) & 0x30) != 0)
88 ;
89
90 if (TransIntrHandlers[core])
91 goto intr_handler;
92 if (TransIntrCallbacks[core])
93 goto SdIntrCallback;
94
95 VoiceTransComplete[core] = 1;
96#endif
97 } else { // Block Transfer
98 if (intr->mode & (SD_TRANS_LOOP << 8)) {
99 // Switch buffers
100 BlockTransBuff[core] = 1 - BlockTransBuff[core];
101 // Setup DMA & send
102 *SD_DMA_ADDR(core) = (BlockTransSize[core] * BlockTransBuff[core]) + BlockTransAddr[core];
103 *SD_DMA_SIZE(core) = (BlockTransSize[core] / 64) + ((BlockTransSize[core] & 63) > 0);
104 *SD_DMA_CHCR(core) = SD_DMA_START | SD_DMA_CS | dir;
105 } else {
106#ifndef ISJPCM
107 *SD_CORE_ATTR(core) &= ~SD_CORE_DMA;
108 *SD_P_MMIX(core) &= 0xFF3F;
109 *U16_REGISTER(0x1B0 + (core * 1024)) = 0;
110#endif
111 }
112
113 if (TransIntrHandlers[core]) {
114#ifndef ISJPCM
116#endif
117 TransIntrHandlers[core](core, intr->data);
118 } else {
119 if (TransIntrCallbacks[core]) {
120#ifndef ISJPCM
121 SdIntrCallback:
122#endif
123 TransIntrCallbacks[core](0);
124 }
125 }
126 }
127
128 if (dir == SD_DMA_DIR_SPU2IOP)
129 FlushDcache();
130
131 return 1;
132}
133
134#ifndef ISJPCM
135int Spu2Interrupt(void *data)
136
137{
138 (void)data;
139
140 if (Spu2IntrHandler != NULL) {
141 volatile u16 *reg1 = U16_REGISTER(0x7C2);
142
143 Spu2IntrHandler((*reg1 & 0xC) >> 2, Spu2IntrData);
144 } else {
145 if (Spu2IrqCallback)
146 Spu2IrqCallback(0);
147 }
148
149 return 1;
150}
151#endif
152
153void nopdelay()
154{
155 s32 i;
156
157 for (i = 0; i < 0x10000; i++)
158 asm volatile("nop\nnop\nnop\nnop\nnop");
159}
160
161void InitSpu2()
162{
163
164 *U32_REGISTER(0x1404) = 0xBF900000;
165 *U32_REGISTER(0x140C) = 0xBF900800;
166 *U32_REGISTER(0x10F0) |= 0x80000;
167 *U32_REGISTER(0x1570) |= 8;
168 *U32_REGISTER(0x1014) = 0x200B31E1;
169 *U32_REGISTER(0x1414) = 0x200B31E1;
170}
171
172
173void RegisterInterrupts()
174{
175 s32 ret;
176
177 DisableIntr(0x24, (int *)&ret);
178 DisableIntr(0x28, (int *)&ret);
179#ifndef ISJPCM
180 DisableIntr(0x9, (int *)&ret);
181#endif
182
183 ReleaseIntrHandler(0x24);
184 ReleaseIntrHandler(0x28);
185
186 RegisterIntrHandler(0x24, 1, TransInterrupt, &TransIntrData[0]);
187 RegisterIntrHandler(0x28, 1, TransInterrupt, &TransIntrData[1]);
188
189#ifndef ISJPCM
190 VoiceTransComplete[0] = 0;
191 VoiceTransComplete[1] = 0;
192
194 RegisterIntrHandler(0x9, 1, Spu2Interrupt, &Spu2IntrData);
195#endif
196}
197
198void ResetAll()
199{
200 u32 core;
201 volatile u16 *statx;
202
203 *SD_C_SPDIF_OUT = 0;
204 nopdelay();
205 *SD_C_SPDIF_OUT = 0x8000;
206 nopdelay();
207
208 *U32_REGISTER(0x10F0) |= 0xB0000;
209
210 for (core = 0; core < 2; core++) {
211#ifndef ISJPCM
212 VoiceTransIoMode[core] = 0;
213#endif
214 *U16_REGISTER(0x1B0) = 0;
215 *SD_CORE_ATTR(core) = 0;
216 nopdelay();
217 *SD_CORE_ATTR(core) = SD_SPU2_ON;
218
219 *SD_P_MVOLL(core) = 0;
220 *SD_P_MVOLR(core) = 0;
221
222 statx = U16_REGISTER(0x344 + (core * 1024));
223
224 while (*statx & 0x7FF)
225 ;
226
227 *SD_A_KOFF_HI(core) = 0xFFFF;
228 *SD_A_KOFF_LO(core) = 0xFFFF; // Should probably only be 0xFF
229 }
230
231 *SD_S_PMON_HI(1) = 0;
232 *SD_S_PMON_LO(1) = 0;
233 *SD_S_NON_HI(1) = 0;
234 *SD_S_NON_LO(1) = 0;
235}
236
237
238u16 VoiceDataInit[16] = {0x707, 0x707, 0x707, 0x707, 0x707, 0x707, 0x707, 0x707,
239 0, 0, 0, 0, 0, 0, 0, 0};
240
241void InitVoices()
242{
243 s32 voice, i;
244 volatile u16 *statx;
245
246 // Set Start Address of data to transfer.
247 *SD_A_TSA_HI(0) = 0;
248 *SD_A_TSA_LO(0) = 0x5000 >> 1;
249
250 // Fill with data.
251 // First 16 bytes are reserved.
252 for (i = 0; i < 16; i++)
253 *SD_A_STD(0) = VoiceDataInit[i];
254
255 // Set Transfer mode to IO
256 *SD_CORE_ATTR(0) = (*SD_CORE_ATTR(0) & ~SD_CORE_DMA) | SD_DMA_IO;
257
258 statx = U16_REGISTER(0x344);
259
260 // Wait for transfer to complete;
261 while (*statx & SD_IO_IN_PROCESS)
262 ;
263
264 // Reset DMA settings
265 *SD_CORE_ATTR(0) &= ~SD_CORE_DMA;
266
267 // Init voices
268 for (voice = 0; voice < 24; voice++) {
269#ifndef ISJPCM
270 *SD_VP_VOLL(0, voice) = 0;
271 *SD_VP_VOLR(0, voice) = 0;
272 *SD_VP_PITCH(0, voice) = 0x3FFF;
273 *SD_VP_ADSR1(0, voice) = 0;
274 *SD_VP_ADSR2(0, voice) = 0;
275#endif
276
277 *SD_VP_VOLL(1, voice) = 0;
278 *SD_VP_VOLR(1, voice) = 0;
279 *SD_VP_PITCH(1, voice) = 0x3FFF;
280 *SD_VP_ADSR1(1, voice) = 0;
281 *SD_VP_ADSR2(1, voice) = 0;
282
283#ifndef ISJPCM
284 // Top address of waveform data
285 *SD_VA_SSA_HI(0, voice) = 0;
286 *SD_VA_SSA_LO(0, voice) = 0x5000 >> 1;
287#endif
288 *SD_VA_SSA_HI(1, voice) = 0;
289 *SD_VA_SSA_LO(1, voice) = 0x5000 >> 1;
290 }
291
292// Set all voices to ON
293#ifndef ISJPCM
294 *SD_A_KON_HI(0) = 0xFFFF;
295 *SD_A_KON_LO(0) = 0xFF;
296#endif
297 *SD_A_KON_HI(1) = 0xFFFF;
298 *SD_A_KON_LO(1) = 0xFF;
299
300 // There is no guarantee that voices will be turn on at once.
301 // So we wait to make sure.
302 nopdelay();
303
304// Set all voices to OFF
305#ifndef ISJPCM
306 *SD_A_KOFF_HI(0) = 0xFFFF;
307 *SD_A_KOFF_LO(0) = 0xFF;
308#endif
309 *SD_A_KOFF_HI(1) = 0xFFFF;
310 *SD_A_KOFF_LO(1) = 0xFF;
311
312 // There is no guarantee that voices will be turn off at once.
313 // So we wait to make sure.
314 nopdelay();
315
316#ifndef ISJPCM
317 *SD_S_ENDX_HI(0) = 0;
318 *SD_S_ENDX_LO(0) = 0;
319#endif
320}
321
322// Core / Volume Registers
323void InitCoreVolume(s32 flag)
324{
325 *SD_C_SPDIF_OUT = 0xC032;
326
327 if (flag) {
328 *SD_CORE_ATTR(0) = SD_SPU2_ON | SD_ENABLE_EFFECTS | SD_MUTE;
329 *SD_CORE_ATTR(1) = SD_SPU2_ON | SD_ENABLE_EFFECTS | SD_MUTE | SD_ENABLE_EX_INPUT;
330 } else {
331 *SD_CORE_ATTR(0) = SD_SPU2_ON | SD_MUTE;
332 *SD_CORE_ATTR(1) = SD_SPU2_ON | SD_MUTE | SD_ENABLE_EX_INPUT;
333 }
334
335// HIgh is voices 0-15, LOw is 16-23, representing voices 0..23 (24)
336#ifndef ISJPCM
337 *SD_S_VMIXL_HI(0) = 0xFFFF;
338 *SD_S_VMIXL_LO(0) = 0xFF;
339 *SD_S_VMIXR_HI(0) = 0xFFFF;
340 *SD_S_VMIXR_LO(0) = 0xFF;
341 *SD_S_VMIXEL_HI(0) = 0xFFFF;
342 *SD_S_VMIXEL_LO(0) = 0xFF;
343 *SD_S_VMIXER_HI(0) = 0xFFFF;
344 *SD_S_VMIXER_LO(0) = 0xFF;
345#endif
346
347 *SD_S_VMIXL_HI(1) = 0xFFFF;
348 *SD_S_VMIXL_LO(1) = 0xFF;
349 *SD_S_VMIXR_HI(1) = 0xFFFF;
350 *SD_S_VMIXR_LO(1) = 0xFF;
351 *SD_S_VMIXEL_HI(1) = 0xFFFF;
352 *SD_S_VMIXEL_LO(1) = 0xFF;
353 *SD_S_VMIXER_HI(1) = 0xFFFF;
354 *SD_S_VMIXER_LO(1) = 0xFF;
355
356
357 *SD_P_MMIX(0) = 0xFF0;
358 *SD_P_MMIX(1) = 0xFFC;
359
360 if (flag == 0) {
361#ifndef ISJPCM
362 *SD_P_MVOLL(0) = 0;
363 *SD_P_MVOLR(0) = 0;
364#endif
365
366 *SD_P_MVOLL(1) = 0;
367 *SD_P_MVOLR(1) = 0;
368
369#ifndef ISJPCM
370 *SD_P_EVOLL(0) = 0;
371#endif
372 *SD_P_EVOLL(1) = 0;
373
374#ifndef ISJPCM
375 *SD_P_EVOLR(0) = 0;
376#endif
377 *SD_P_EVOLR(1) = 0;
378
379// Effect End Address, Upper part
380#ifndef ISJPCM
381 *SD_A_EEA_HI(0) = 0xE;
382#endif
383 *SD_A_EEA_HI(1) = 0xF;
384 }
385#ifndef ISJPCM
386 *SD_P_AVOLL(0) = 0;
387 *SD_P_AVOLR(0) = 0;
388#endif
389 // Core 1 External Input Volume.
390 // The external Input is Core 0's output.
391 *SD_P_AVOLL(1) = 0x7FFF;
392 *SD_P_AVOLR(1) = 0x7FFF;
393
394#ifndef ISJPCM
395 *SD_P_BVOLL(0) = 0;
396 *SD_P_BVOLR(0) = 0;
397#endif
398 *SD_P_BVOLL(1) = 0;
399 *SD_P_BVOLR(1) = 0;
400}
401
402void InitSpdif()
403{
404 *SD_C_SPDIF_MODE = 0x900;
405 *SD_C_SPDIF_MEDIA = 0x200;
406 *U16_REGISTER(0x7CA) = 8;
407}
408
409int sceSdInit(int flag)
410{
411 flag &= 1;
412
413 InitSpu2();
414 InitSpdif();
415
416 if (flag == 0)
417 ResetAll();
418 RegisterInterrupts();
419
420 InitVoices();
421 InitCoreVolume(flag);
422
423 EnableIntr(0x24);
424 EnableIntr(0x28);
425#ifndef ISJPCM
426 EnableIntr(9);
427#endif
428
429 return 0;
430}
431
432#ifndef ISJPCM
433void SetSpdifMode(u16 val)
434{
435 u16 out, mode;
436
437 out = *SD_C_SPDIF_OUT;
438 mode = *SD_C_SPDIF_MODE;
439
440 switch (val & 0xF) {
441 case 0:
442 mode &= 0xFFFD;
443 out = (val & 0xFEF7) | 0x20;
444 break;
445 case 1:
446 mode |= 2;
447 out = (out & 0xFFD7) | 0x100;
448 break;
449 case 2:
450 out &= 0xFED7;
451 break;
452 case 0xF:
453 out = (out & 0xFEDF) | 8;
454 break;
455 default:
456 return;
457 }
458
459 if (val & 0x80)
460 mode |= 0x8000;
461 else
462 mode &= 0x7FFF;
463
464 switch (val & 0xF00) {
465 case 0x800:
466 *SD_C_SPDIF_MEDIA = 0x200;
467 mode |= 0x1800;
468 break;
469 case 0x400:
470 *SD_C_SPDIF_MEDIA = 0;
471 mode &= 0xE7FF;
472 break;
473 default:
474 *SD_C_SPDIF_MEDIA = 0x200;
475 mode = (mode & 0xE7FF) | 0x800;
476 break;
477 }
478
479 *SD_C_SPDIF_OUT = out;
480 *SD_C_SPDIF_MODE = mode;
481
482 SpdifSettings = val;
483}
484#endif
485
486
487// Enable/disable bits in SD_CORE_ATTR
488u8 CoreAttrShifts[4] = {7, 6, 14, 8};
489
490void sceSdSetCoreAttr(u16 entry, u16 val)
491{
492 u16 core_attr = *SD_CORE_ATTR(entry & 1);
493
494 switch (entry & ~1) {
495 case SD_CORE_NOISE_CLK: // 0x8
496 *SD_CORE_ATTR(entry & 1) = (core_attr - 0x3F01) | ((val & 0x3F) << 8);
497 break;
498
499#ifndef ISJPCM
500 case SD_CORE_SPDIF_MODE: // 0xA
501 SetSpdifMode(val); // sub1
502 break;
503#endif
504 default: {
505 u32 core = entry & 1;
506 entry = (entry >> 1) - 1;
507 core_attr &= ~(1 << CoreAttrShifts[entry]);
508 core_attr |= (val & 1) << CoreAttrShifts[entry];
509 *SD_CORE_ATTR(core) = core_attr;
510 } break;
511 }
512}
513
514void sceSdSetParam(u16 reg, u16 val)
515{
516#ifndef ISJPCM
517 u32 offs;
518 u32 voice;
519 u32 reg_index;
520 u32 core;
521 volatile u16 *reg_p;
522
523
524 core = reg & 1;
525
526 // Determine the channel offset
527 if (reg & 0x80)
528 offs = (40 * core) >> 1;
529 else
530 offs = (1024 * core) >> 1;
531
532 reg_index = (reg >> 8) & 0xFF;
533 voice = (reg & 0x3E) << 2;
534 reg_p = ParamRegList[reg_index] + offs + voice;
535
536 *reg_p = val;
537#else
538 u32 core;
539
540
541 core = reg & 1;
542 reg &= ~1;
543
544 switch (reg) {
545 case SD_PARAM_MVOLL:
546 *SD_P_MVOLL(core) = val;
547 break;
548
549 case SD_PARAM_MVOLR:
550 *SD_P_MVOLR(core) = val;
551 break;
552
553 case SD_PARAM_BVOLL:
554 *SD_P_BVOLL(core) = val;
555 break;
556
557 case SD_PARAM_BVOLR:
558 *SD_P_BVOLR(core) = val;
559 break;
560 }
561#endif
562}
563
564SdIntrCallback sceSdSetTransCallback(s32 core, SdIntrCallback cb)
565{
566 SdIntrCallback old_cb;
567
568 old_cb = TransIntrCallbacks[core & 1];
569 TransIntrCallbacks[core & 1] = cb;
570
571 return old_cb;
572}
573
574// DMA
575
576u32 DmaStop(u32 core)
577{
578 u32 retval;
579
580 core &= 1;
581
582 if (*U16_REGISTER(0x1B0 + (core * 1024)) == 0)
583 retval = 0;
584 else
585 retval = *SD_DMA_ADDR(core);
586
587 *SD_DMA_CHCR(core) &= ~SD_DMA_START;
588 *U16_REGISTER(0x1B0 + (core * 1024)) = 0;
589
590 retval = (BlockTransBuff[core] << 24) | (retval & 0xFFFFFF);
591
592 return retval;
593}
594
595void SetDmaWrite(s32 chan)
596{
597 volatile u32 *reg = U32_REGISTER(0x1014 + (chan << 10));
598 *reg = (*reg & 0xF0FFFFFF) | 0x20000000;
599}
600
601void SetDmaRead(s32 chan)
602{
603 volatile u32 *reg = U32_REGISTER(0x1014 + (chan << 10));
604 *reg = (*reg & 0xF0FFFFFF) | 0x22000000;
605}
606
607// Block Transfer
608#ifndef ISJPCM
609s32 BlockTransWriteFrom(u8 *iopaddr, u32 size, s32 chan, u16 mode, u8 *startaddr)
610{
611 s32 core = chan & 1;
612 s32 offset;
613
614 BlockTransBuff[core] = 0;
615 BlockTransSize[core] = size;
616 BlockTransAddr[core] = (u32)iopaddr;
617
618 if (startaddr == 0)
619 startaddr = iopaddr;
620
621 offset = startaddr - iopaddr;
622
623 if ((u32)offset > size) {
624 if (mode & SD_TRANS_LOOP) {
625 offset -= size;
626 BlockTransBuff[core] = 1;
627 } else {
628 return -1;
629 }
630 }
631
632 if (offset & 1023)
633 offset += 1024;
634
635 iopaddr += (BlockTransSize[core] * BlockTransBuff[core]) + offset;
636
637 if (*SD_CORE_ATTR(core) & SD_DMA_IN_PROCESS)
638 return -1;
639 if (*SD_DMA_CHCR(core) & SD_DMA_START)
640 return -1;
641
642 // 0x26B8
643 *SD_CORE_ATTR(core) &= 0xFFCF;
644
645 *SD_A_TSA_HI(core) = 0;
646 *SD_A_TSA_LO(core) = 0;
647
648 *U16_REGISTER(0x1B0 + (core * 1024)) = 1 << core;
649
650 SetDmaWrite(core);
651
652 *SD_DMA_ADDR(core) = (u32)iopaddr;
653 *SD_DMA_MODE(core) = 0x10;
654 *SD_DMA_SIZE(core) = (size / 64) + ((size & 63) > 0);
655 *SD_DMA_CHCR(core) = SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_IOP2SPU;
656
657 return 0;
658}
659#endif
660
661s32 BlockTransWrite(u8 *iopaddr, u32 size, s32 chan)
662{
663 s32 core = chan & 1;
664
665 BlockTransBuff[core] = 0;
666 BlockTransSize[core] = size;
667 BlockTransAddr[core] = (u32)iopaddr;
668
669 if (*SD_CORE_ATTR(core) & SD_DMA_IN_PROCESS)
670 return -1;
671 if (*SD_DMA_CHCR(core) & SD_DMA_START)
672 return -1;
673
674 // 0x26B8
675 *SD_CORE_ATTR(core) &= 0xFFCF;
676
677 *SD_A_TSA_HI(core) = 0;
678 *SD_A_TSA_LO(core) = 0;
679
680 *U16_REGISTER(0x1B0 + (core * 1024)) = 1 << core;
681
682 SetDmaWrite(core);
683
684 *SD_DMA_ADDR(core) = (u32)iopaddr;
685 *SD_DMA_MODE(core) = 0x10;
686 *SD_DMA_SIZE(core) = (size / 64) + ((size & 63) > 0);
687 *SD_DMA_CHCR(core) = SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_IOP2SPU;
688
689 return 0;
690}
691
692
693#ifndef ISJPCM
694s32 BlockTransRead(u8 *iopaddr, u32 size, s32 chan, s16 mode)
695{
696 u32 i;
697
698 s32 core = chan & 1;
699
700 BlockTransBuff[core] = 0;
701 BlockTransSize[core] = size;
702 BlockTransAddr[core] = (u32)iopaddr;
703
704 if (*SD_CORE_ATTR(core) & SD_DMA_IN_PROCESS)
705 return -1;
706 if (*SD_DMA_CHCR(core) & SD_DMA_START)
707 return -1;
708
709 *SD_CORE_ATTR(core) &= 0xFFCF;
710
711 *SD_A_TSA_HI(core) = 0;
712 *SD_A_TSA_LO(core) = ((mode & 0xF00) << 1) + 0x400;
713
714 *U16_REGISTER(0x1AE + (core * 1024)) = (mode & 0xF000) >> 11;
715
716 i = 0x4937;
717
718 while (i--)
719 ;
720
721 *U16_REGISTER(0x1B0 + (core * 1024)) = 4;
722
723 SetDmaRead(core);
724
725 *SD_DMA_ADDR(core) = (u32)iopaddr;
726 *SD_DMA_MODE(core) = 0x10;
727 *SD_DMA_SIZE(core) = (size / 64) + ((size & 63) > 0);
728 *SD_DMA_CHCR(core) = SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_SPU2IOP;
729
730
731 return 0;
732}
733#endif
734
735
736int sceSdBlockTrans(s16 chan, u16 mode, u8 *iopaddr, u32 size, ...)
737{
738#ifndef ISJPCM
739 int transfer_dir = mode & 3;
740#endif
741 int core = chan & 1;
742 int _size = size;
743
744#ifndef ISJPCM
745 switch (transfer_dir) {
746 case SD_TRANS_WRITE: {
747 TransIntrData[core].mode = 0x100 | core;
748
749 if (mode & SD_TRANS_LOOP) {
750 TransIntrData[core].mode |= SD_TRANS_LOOP << 8;
751 _size /= 2;
752 }
753
754 if (BlockTransWrite(iopaddr, _size, core) >= 0)
755 return 0;
756
757 } break;
758
759
760 case SD_TRANS_READ: {
761 TransIntrData[core].mode = 0x300 | core;
762
763 if (mode & SD_TRANS_LOOP) {
764 TransIntrData[core].mode |= SD_TRANS_LOOP << 8;
765 _size /= 2;
766 }
767
768 if (BlockTransRead(iopaddr, _size, chan, mode) >= 0)
769 return 0;
770
771 } break;
772
773 case SD_TRANS_STOP: {
774 return DmaStop(core);
775
776 } break;
777
778 case SD_TRANS_WRITE_FROM: {
779 va_list alist;
780 u8 *startaddr;
781
782 va_start(alist, size);
783 startaddr = va_arg(alist, u8 *);
784 va_end(alist);
785
786 TransIntrData[core].mode = 0x100 | core;
787
788 if (mode & SD_TRANS_LOOP) {
789 TransIntrData[core].mode |= SD_TRANS_LOOP << 8;
790 _size /= 2;
791 }
792
793 if (BlockTransWriteFrom(iopaddr, _size, core, mode, startaddr) >= 0)
794 return 0;
795
796
797 } break;
798 }
799#else
800 TransIntrData[core].mode = 0x100 | core;
801 TransIntrData[core].mode |= SD_TRANS_LOOP << 8;
802 _size /= 2;
803
804 if (BlockTransWrite(iopaddr, _size, core) >= 0)
805 return 0;
806#endif
807
808 return -1;
809}
810
811u32 sceSdBlockTransStatus(s16 chan, s16 flag)
812{
813 u32 retval;
814
815 (void)flag;
816
817 chan &= 1;
818
819 if (*U16_REGISTER(0x1B0 + (chan * 1024)) == 0)
820 retval = 0;
821 else
822 retval = *SD_DMA_ADDR(chan);
823
824 retval = (BlockTransBuff[chan] << 24) | (retval & 0xFFFFFF);
825
826 return retval;
827}
828
829#endif
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *), void *arg)
Definition intrman.c:125
int ReleaseIntrHandler(int irq)
Definition intrman.c:167
int DisableIntr(int irq, int *res)
Definition intrman.c:395
int EnableIntr(int irq)
Definition intrman.c:346