PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
sifman.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "irx_imports.h"
12#include "sifman.h"
13
14#include "iop_mmio_hwport.h"
15#include "sif_mmio_hwport.h"
16
17extern struct irx_export_table _exp_sifman;
18
19#ifdef _IOP
20IRX_ID("IOP_SIF_manager", 2, 5);
21#endif
22// Based on the module from SCE SDK 3.1.0.
23
24typedef struct sif_info_
25{
26 int data;
27 int words;
28 int count;
29 int addr;
31
33{
34 void (*func)(void *userdata);
35 void *userdata;
37
43
44typedef struct sifman_internals_
45{
46 u16 dma_count;
47 // cppcheck-suppress unusedStructMember
48 char unused02[2];
49 int dmatag_index;
50 sif_info_t *sif_curbuf;
51 sif_info_t sif_buf1[32];
52 sif_info_t sif_buf2[32];
53 sif_completion_cb_info_arr_t *sif_otherbufcom;
54 sif_completion_cb_info_arr_t *sif_curbufcom;
57 void (*dma_intr_handler)(void *userdata);
58 void *dma_intr_handler_userdata;
59 // cppcheck-suppress unusedStructMember
60 char field_624[4];
61 sif_info_t one;
62 // cppcheck-suppress unusedStructMember
63 char field_638[8];
65
66static sifman_internals_t sifman_internals;
67static u32 sif_dma2_inited = 0;
68static u32 sif_inited = 0;
69
70#define PRID $15
71
72#define _mfc0(reg) \
73 ({ \
74 u32 val; \
75 __asm__ volatile("mfc0 %0, " #reg : "=r"(val)); \
76 val; \
77 })
78
79#define mfc0(reg) _mfc0(reg)
80
81int _start(int ac, char **av)
82{
83 s32 prid;
84 USE_IOP_MMIO_HWPORT();
85 USE_SIF_MMIO_HWPORT();
86
87 (void)ac;
88 (void)av;
89
90 prid = mfc0(PRID);
91 if ( prid >= 16 )
92 {
93 if ( (iop_mmio_hwport->iop_sbus_ctrl[0] & 8) == 0 )
94 {
95 if ( sif_mmio_hwport->unk60 == 0x1D000060 )
96 return RegisterLibraryEntries(&_exp_sifman) != 0;
97 if ( (sif_mmio_hwport->unk60 & 0xFFFFF000) == 0 )
98 return RegisterLibraryEntries(&_exp_sifman) != 0;
99 }
100 }
101 return 1;
102}
103
104static u32 get_msflag()
105{
106 u32 result;
107 USE_SIF_MMIO_HWPORT();
108
109 for ( result = sif_mmio_hwport->msflag; result != sif_mmio_hwport->msflag; result = sif_mmio_hwport->msflag )
110 ;
111 return result;
112}
113
114static u32 get_smflag()
115{
116 u32 result;
117 USE_SIF_MMIO_HWPORT();
118
119 for ( result = sif_mmio_hwport->smflag; result != sif_mmio_hwport->smflag; result = sif_mmio_hwport->smflag )
120 ;
121 return result;
122}
123
124void sceSifDma2Init()
125{
126 USE_IOP_MMIO_HWPORT();
127
128 if ( !sif_dma2_inited )
129 {
130 iop_mmio_hwport->dmac1.oldch[2].chcr = 0;
131 iop_mmio_hwport->dmac1.dpcr1 |= 0x800;
132 sif_dma2_inited = 1;
133 }
134}
135
136static int sif_dma_init(void);
137
138void sceSifInit()
139{
140 u32 msflag;
141 int state;
142 USE_IOP_MMIO_HWPORT();
143 USE_SIF_MMIO_HWPORT();
144
145 if ( !sif_inited )
146 {
147 iop_mmio_hwport->dmac2.dpcr2 |= 0x8800;
148 iop_mmio_hwport->dmac2.newch[2].chcr = 0;
149 iop_mmio_hwport->dmac2.newch[3].chcr = 0;
150 sceSifDma2Init();
151 if ( (iop_mmio_hwport->iop_sbus_ctrl[0] & 0x10) != 0 )
152 {
153 iop_mmio_hwport->iop_sbus_ctrl[0] |= 0x10;
154 }
155 iop_mmio_hwport->iop_sbus_ctrl[0] |= 1;
156 sif_dma_init();
157 do
158 {
159 CpuSuspendIntr(&state);
160 msflag = get_msflag();
161 CpuResumeIntr(state);
162 } while ( (msflag & SIF_STAT_SIFINIT) == 0 );
163 sceSifSetDChain();
164 sceSifSetSubAddr(0);
165 sif_mmio_hwport->smflag = SIF_STAT_SIFINIT;
166 sif_inited = 1;
167 }
168}
169
170int sifman_deinit()
171{
172 int old_irq;
173 USE_IOP_MMIO_HWPORT();
174
175 DisableIntr(IOP_IRQ_DMA_SIF0, &old_irq);
176 ReleaseIntrHandler(IOP_IRQ_DMA_SIF0);
177 iop_mmio_hwport->dmac2.newch[2].chcr = 0;
178 iop_mmio_hwport->dmac2.newch[3].chcr = 0;
179 if ( iop_mmio_hwport->iop_sbus_ctrl[0] & 0x10 )
180 {
181 iop_mmio_hwport->iop_sbus_ctrl[0] |= 0x10;
182 }
183 return 0;
184}
185
186int sceSifCheckInit()
187{
188 return sif_inited;
189}
190
191void sceSifSetDChain()
192{
193 USE_IOP_MMIO_HWPORT();
194 USE_SIF_MMIO_HWPORT();
195
196 if ( (sif_mmio_hwport->controlreg & 0x40) == 0 )
197 sif_mmio_hwport->controlreg = 64;
198 iop_mmio_hwport->dmac2.newch[3].chcr = 0;
199 iop_mmio_hwport->dmac2.newch[3].bcr = (iop_mmio_hwport->dmac2.newch[3].bcr & 0xFFFF0000) | 32;
200 iop_mmio_hwport->dmac2.newch[3].chcr = 0x41000300;
201}
202
203void sceSifSetDmaIntrHandler(void (*handler)(void *userdata), void *arg)
204{
205 sifman_internals.dma_intr_handler = handler;
206 sifman_internals.dma_intr_handler_userdata = arg;
207}
208
209void sceSifResetDmaIntrHandler()
210{
211 sifman_internals.dma_intr_handler = NULL;
212 sifman_internals.dma_intr_handler_userdata = NULL;
213}
214
215static int sifman_interrupt_handler(sifman_internals_t *smi)
216{
217 void (*dma_intr_handler)(void *);
218 sif_completion_cb_info_arr_t *sif_otherbufcom;
219 int v4;
220 sif_completion_cb_info_arr_t *p_sif_bufcom1;
221 USE_IOP_MMIO_HWPORT();
222 USE_SIF_MMIO_HWPORT();
223
224 dma_intr_handler = smi->dma_intr_handler;
225 if ( dma_intr_handler )
226 dma_intr_handler(smi->dma_intr_handler_userdata);
227 sif_otherbufcom = smi->sif_otherbufcom;
228 v4 = 0;
229 if ( sif_otherbufcom->count > 0 )
230 {
231 int v5;
232
233 v5 = 0;
234 do
235 {
236 ++v4;
237 sif_otherbufcom->info[v5].func(sif_otherbufcom->info[v5].userdata);
238 sif_otherbufcom = smi->sif_otherbufcom;
239 v5 = v4;
240 } while ( v4 < sif_otherbufcom->count );
241 }
242 smi->sif_otherbufcom->count = 0;
243 if ( (iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000) == 0 && smi->dmatag_index > 0 )
244 {
245 iop_mmio_hwport->dmac2.newch[2].chcr = 0;
246 iop_mmio_hwport->dmac2.newch[2].tadr = (uiptr)(smi->sif_curbuf);
247 iop_mmio_hwport->dmac2.newch[2].bcr = (iop_mmio_hwport->dmac2.newch[2].bcr & 0xFFFF0000) | 32;
248 if ( (sif_mmio_hwport->controlreg & 0x20) == 0 )
249 sif_mmio_hwport->controlreg = 32;
250 ++smi->dma_count;
251 smi->dmatag_index = 0;
252 if ( smi->sif_curbuf == smi->sif_buf1 )
253 {
254 smi->sif_curbuf = smi->sif_buf2;
255 smi->sif_curbufcom = &smi->sif_bufcom2;
256 p_sif_bufcom1 = &smi->sif_bufcom1;
257 }
258 else
259 {
260 smi->sif_curbufcom = &smi->sif_bufcom1;
261 p_sif_bufcom1 = &smi->sif_bufcom2;
262 smi->sif_curbuf = smi->sif_buf1;
263 }
264 smi->sif_otherbufcom = p_sif_bufcom1;
265 iop_mmio_hwport->dmac2.newch[2].chcr = 0x1000701;
266 }
267 return 1;
268}
269
270static int sif_dma_init(void)
271{
272 int state;
273
274 sifman_internals.sif_curbuf = sifman_internals.sif_buf1;
275 sifman_internals.sif_curbufcom = &sifman_internals.sif_bufcom1;
276 sifman_internals.dmatag_index = 0;
277 sifman_internals.sif_bufcom1.count = 0;
278 sifman_internals.sif_bufcom2.count = 0;
279 sifman_internals.sif_otherbufcom = &sifman_internals.sif_bufcom2;
280 sifman_internals.dma_intr_handler = 0;
281 sifman_internals.dma_intr_handler_userdata = 0;
282 CpuSuspendIntr(&state);
283 RegisterIntrHandler(IOP_IRQ_DMA_SIF0, 1, (int (*)(void *))sifman_interrupt_handler, &sifman_internals);
284 EnableIntr(IOP_IRQ_DMA_SIF0);
285 return CpuResumeIntr(state);
286}
287
288static int sif_dma_setup_tag(SifDmaTransfer_t *a1)
289{
290 sif_info_t *v1;
291 int v2;
292 unsigned int v3;
293 unsigned int v4;
294 unsigned int v5;
295
296 v1 = &sifman_internals.sif_curbuf[sifman_internals.dmatag_index];
297 v2 = (int)a1->src & 0xFFFFFF;
298 v3 = a1->size + 3;
299 v1->data = v2;
300 v4 = v3 >> 2;
301 if ( (a1->attr & 2) != 0 )
302 v1->data = v2 | 0x40000000;
303 v1->words = v4 & 0xFFFFFF;
304 v5 = v3 >> 4;
305 if ( (v4 & 3) != 0 )
306 ++v5;
307 v1->count = v5 | 0x10000000;
308 if ( (a1->attr & 4) != 0 )
309 v1->count |= 0x80000000;
310 v1->addr = (int)a1->dest & 0x1FFFFFFF;
311 return ++sifman_internals.dmatag_index;
312}
313
314static int set_dma_inner(SifDmaTransfer_t *dmat, int count, void (*func)(), void *data)
315{
316 u8 dmatag_index;
317 int dma_count;
318 int i;
319 int v14;
320 sif_completion_cb_info_arr_t *p_sif_bufcom1;
321 USE_IOP_MMIO_HWPORT();
322 USE_SIF_MMIO_HWPORT();
323
324 if ( 32 - sifman_internals.dmatag_index < count )
325 return 0;
326 dmatag_index = sifman_internals.dmatag_index;
327 dma_count = sifman_internals.dma_count;
328 if ( sifman_internals.dmatag_index )
329 sifman_internals.sif_curbuf[sifman_internals.dmatag_index - 1].data &= ~0x80000000;
330 for ( i = 0; i < count; ++dmat )
331 {
332 sif_dma_setup_tag(dmat);
333 ++i;
334 }
335 sifman_internals.sif_curbuf[sifman_internals.dmatag_index - 1].data |= 0x80000000;
336 if ( func )
337 {
338 sifman_internals.sif_curbufcom->info[sifman_internals.sif_curbufcom->count].func = func;
339 sifman_internals.sif_curbufcom->info[sifman_internals.sif_curbufcom->count++].userdata = data;
340 }
341 v14 = dma_count << 16;
342 if ( (iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000) == 0 )
343 {
344 v14 = dma_count << 16;
345 if ( iop_mmio_hwport->dmac2.new_unusedch.madr == 0 )
346 {
347 v14 = dma_count << 16;
348 if ( (iop_mmio_hwport->dmac2.dicr2 & 0x4000000) == 0 )
349 {
350 iop_mmio_hwport->dmac2.newch[2].chcr = 0;
351 iop_mmio_hwport->dmac2.newch[2].tadr = (uiptr)(sifman_internals.sif_curbuf);
352 if ( (sif_mmio_hwport->controlreg & 0x20) == 0 )
353 sif_mmio_hwport->controlreg = 32;
354 iop_mmio_hwport->dmac2.newch[2].bcr = (iop_mmio_hwport->dmac2.newch[2].bcr & 0xFFFF0000) | 32;
355 sifman_internals.dmatag_index = 0;
356 ++sifman_internals.dma_count;
357 if ( sifman_internals.sif_curbuf == sifman_internals.sif_buf1 )
358 {
359 sifman_internals.sif_curbuf = sifman_internals.sif_buf2;
360 sifman_internals.sif_curbufcom = &sifman_internals.sif_bufcom2;
361 p_sif_bufcom1 = &sifman_internals.sif_bufcom1;
362 }
363 else
364 {
365 sifman_internals.sif_curbuf = sifman_internals.sif_buf1;
366 sifman_internals.sif_curbufcom = &sifman_internals.sif_bufcom1;
367 p_sif_bufcom1 = &sifman_internals.sif_bufcom2;
368 }
369 sifman_internals.sif_otherbufcom = p_sif_bufcom1;
370 iop_mmio_hwport->dmac2.newch[2].chcr = 0x1000701;
371 v14 = dma_count << 16;
372 }
373 }
374 }
375 return v14 | (dmatag_index << 8) | (u8)count;
376}
377
378int sceSifSetDma(SifDmaTransfer_t *dmat, int count)
379{
380 return set_dma_inner(dmat, count, 0, 0);
381}
382
383unsigned int sceSifSetDmaIntr(SifDmaTransfer_t *dmat, int len, void (*func)(), void *data)
384{
385 return set_dma_inner(dmat, len, func, data);
386}
387
388static int dma_stat_inner(unsigned int a1)
389{
390 USE_IOP_MMIO_HWPORT();
391
392 if ( (iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000) == 0 && !iop_mmio_hwport->dmac2.new_unusedch.madr )
393 {
394 if ( (iop_mmio_hwport->dmac2.dicr2 & 0x4000000) == 0 )
395 return -1;
396 }
397 if ( sifman_internals.dma_count != ((a1 >> 16) & 0xFFFF) )
398 {
399 if ( sifman_internals.dma_count == (u16)(((a1 >> 16) & 0xFFFF) + 1) )
400 return 0;
401 return -1;
402 }
403 return 1;
404}
405
406int sceSifDmaStat(int trid)
407{
408 int v2;
409 int state;
410
411 if ( QueryIntrContext() )
412 return dma_stat_inner(trid);
413 CpuSuspendIntr(&state);
414 v2 = dma_stat_inner(trid);
415 CpuResumeIntr(state);
416 return v2;
417}
418
419void sceSifSetOneDma(SifDmaTransfer_t dmat)
420{
421 int v1;
422 unsigned int v2;
423 unsigned int v3;
424 USE_IOP_MMIO_HWPORT();
425 USE_SIF_MMIO_HWPORT();
426
427 v1 = ((int)dmat.src & 0xFFFFFF) | 0x80000000;
428 v2 = ((unsigned int)dmat.size >> 2) + ((dmat.size & 3) != 0);
429 sifman_internals.one.data = v1;
430 sifman_internals.one.words = v2 & 0xFFFFFF;
431 if ( (dmat.attr & 2) != 0 )
432 sifman_internals.one.data = v1 | 0x40000000;
433 v3 = v2 >> 2;
434 if ( (v2 & 3) != 0 )
435 ++v3;
436 sifman_internals.one.count = v3 | 0x10000000;
437 if ( (dmat.attr & 4) != 0 )
438 sifman_internals.one.count |= 0x80000000;
439 sifman_internals.one.addr = (int)dmat.dest & 0xFFFFFFF;
440 if ( (sif_mmio_hwport->controlreg & 0x20) == 0 )
441 sif_mmio_hwport->controlreg = 32;
442 iop_mmio_hwport->dmac2.newch[2].chcr = 0;
443 iop_mmio_hwport->dmac2.newch[2].tadr = (uiptr)&sifman_internals.one;
444 iop_mmio_hwport->dmac2.newch[2].bcr = (iop_mmio_hwport->dmac2.newch[2].bcr & 0xFFFF0000) | 32;
445 iop_mmio_hwport->dmac2.newch[2].chcr = 0x1000701;
446}
447
448void sceSifSendSync()
449{
450 USE_IOP_MMIO_HWPORT();
451
452 while ( iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000 )
453 ;
454}
455
456int sceSifIsSending()
457{
458 USE_IOP_MMIO_HWPORT();
459
460 return iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000;
461}
462
463void sceSifDma0Transfer(void *addr, int size, int mode)
464{
465 unsigned int v4;
466 int v5;
467 USE_IOP_MMIO_HWPORT();
468 USE_SIF_MMIO_HWPORT();
469
470 (void)mode;
471
472 v4 = ((unsigned int)size >> 2) + ((size & 3) != 0);
473 if ( (sif_mmio_hwport->controlreg & 0x20) == 0 )
474 sif_mmio_hwport->controlreg = 32;
475 iop_mmio_hwport->dmac2.newch[2].chcr = 0;
476 iop_mmio_hwport->dmac2.newch[2].madr = (unsigned int)addr & 0xFFFFFF;
477 if ( (v4 & 0x1F) != 0 )
478 v5 = (v4 >> 5) + 1;
479 else
480 v5 = v4 >> 5;
481 iop_mmio_hwport->dmac2.newch[2].bcr = ((v5 & 0xFFFF) << 16) | 32;
482 iop_mmio_hwport->dmac2.newch[2].chcr = 0x1000201;
483}
484
485void sceSifDma0Sync()
486{
487 USE_IOP_MMIO_HWPORT();
488
489 while ( iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000 )
490 ;
491}
492
493int sceSifDma0Sending()
494{
495 USE_IOP_MMIO_HWPORT();
496
497 return iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000;
498}
499
500void sceSifDma1Transfer(void *addr, int size, int mode)
501{
502 unsigned int v4;
503 int v5;
504 int v6;
505 USE_IOP_MMIO_HWPORT();
506 USE_SIF_MMIO_HWPORT();
507
508 v4 = ((unsigned int)size >> 2) + ((size & 3) != 0);
509 if ( (sif_mmio_hwport->controlreg & 0x40) == 0 )
510 sif_mmio_hwport->controlreg = 64;
511 iop_mmio_hwport->dmac2.newch[3].chcr = 0;
512 iop_mmio_hwport->dmac2.newch[3].madr = (unsigned int)addr & 0xFFFFFF;
513 if ( (v4 & 0x1F) != 0 )
514 v5 = (v4 >> 5) + 1;
515 else
516 v5 = v4 >> 5;
517 iop_mmio_hwport->dmac2.newch[3].bcr = ((v5 & 0xFFFF) << 16) | 32;
518 if ( (mode & 0x10) != 0 )
519 v6 = 0x41000000;
520 else
521 v6 = 0x1000000;
522 iop_mmio_hwport->dmac2.newch[3].chcr = v6 | 0x200;
523}
524
525void sceSifDma1Sync()
526{
527 USE_IOP_MMIO_HWPORT();
528
529 while ( iop_mmio_hwport->dmac2.newch[3].chcr & 0x1000000 )
530 ;
531}
532
533int sceSifDma1Sending()
534{
535 USE_IOP_MMIO_HWPORT();
536
537 return iop_mmio_hwport->dmac2.newch[3].chcr & 0x1000000;
538}
539
540void sceSifDma2Transfer(void *addr, int size, int mode)
541{
542 unsigned int v4;
543 u16 v5;
544 int v6;
545 int v7;
546 USE_IOP_MMIO_HWPORT();
547 USE_SIF_MMIO_HWPORT();
548
549 v4 = ((unsigned int)size >> 2) + ((size & 3) != 0);
550 if ( (sif_mmio_hwport->controlreg & 0x80) == 0 )
551 sif_mmio_hwport->controlreg = 128;
552 v5 = v4;
553 iop_mmio_hwport->dmac1.oldch[2].chcr = 0;
554 iop_mmio_hwport->dmac1.oldch[2].madr = (unsigned int)addr & 0xFFFFFF;
555 if ( v4 >= 0x21 )
556 v5 = 32;
557 if ( (v4 & 0x1F) != 0 )
558 v6 = (v4 >> 5) + 1;
559 else
560 v6 = v4 >> 5;
561 iop_mmio_hwport->dmac1.oldch[2].bcr = ((v6 & 0xFFFF) << 16) | (v5 & 0xFFFF);
562 if ( (mode & 1) != 0 )
563 {
564 v7 = 0x1000201;
565 }
566 else
567 {
568 int v8;
569
570 if ( (mode & 0x10) != 0 )
571 v8 = 0x41000000;
572 else
573 v8 = 0x1000000;
574 v7 = v8 | 0x200;
575 }
576 iop_mmio_hwport->dmac1.oldch[2].chcr = v7;
577}
578
579void sceSifDma2Sync()
580{
581 USE_IOP_MMIO_HWPORT();
582
583 while ( iop_mmio_hwport->dmac1.oldch[2].chcr & 0x1000000 )
584 ;
585}
586
587int sceSifDma2Sending()
588{
589 USE_IOP_MMIO_HWPORT();
590
591 return iop_mmio_hwport->dmac1.oldch[2].chcr & 0x1000000;
592}
593
594u32 sceSifGetMSFlag()
595{
596 return get_msflag();
597}
598
599u32 sceSifSetMSFlag(u32 val)
600{
601 USE_SIF_MMIO_HWPORT();
602
603 sif_mmio_hwport->msflag = val;
604 return get_msflag();
605}
606
607u32 sceSifGetSMFlag()
608{
609 return get_smflag();
610}
611
612u32 sceSifSetSMFlag(u32 val)
613{
614 USE_SIF_MMIO_HWPORT();
615
616 sif_mmio_hwport->smflag = val;
617 return get_smflag();
618}
619
620u32 sceSifGetMainAddr()
621{
622 USE_SIF_MMIO_HWPORT();
623
624 return sif_mmio_hwport->mscom;
625}
626
627u32 sceSifGetSubAddr()
628{
629 USE_SIF_MMIO_HWPORT();
630
631 return sif_mmio_hwport->smcom;
632}
633
634u32 sceSifSetSubAddr(u32 addr)
635{
636 USE_SIF_MMIO_HWPORT();
637
638 sif_mmio_hwport->smcom = addr;
639 return sif_mmio_hwport->smcom;
640}
641
642void sceSifIntrMain()
643{
644 u32 v0;
645 USE_IOP_MMIO_HWPORT();
646
647 v0 = iop_mmio_hwport->iop_sbus_ctrl[0];
648 iop_mmio_hwport->iop_sbus_ctrl[0] = v0 | 2;
649 // cppcheck-suppress redundantAssignment
650 iop_mmio_hwport->iop_sbus_ctrl[0] = v0 & 0xFFFFFFFD;
651}
int CpuResumeIntr(int state)
Definition intrman.c:227
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *), void *arg)
Definition intrman.c:125
int ReleaseIntrHandler(int irq)
Definition intrman.c:167
int QueryIntrContext(void)
int DisableIntr(int irq, int *res)
Definition intrman.c:395
int CpuSuspendIntr(int *state)
Definition intrman.c:205
int EnableIntr(int irq)
Definition intrman.c:346
#define SIF_STAT_SIFINIT
Definition sifdma.h:46
u32 count
start sector of fragmented bd/file