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(void)
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(void *userdata)
216{
217 void (*dma_intr_handler)(void *userdata);
218 sif_completion_cb_info_arr_t *sif_otherbufcom;
219 int v4;
220 sif_completion_cb_info_arr_t *p_sif_bufcom1;
222 USE_IOP_MMIO_HWPORT();
223 USE_SIF_MMIO_HWPORT();
224
225 smi = (sifman_internals_t *)userdata;
226 dma_intr_handler = smi->dma_intr_handler;
227 if ( dma_intr_handler )
228 dma_intr_handler(smi->dma_intr_handler_userdata);
229 sif_otherbufcom = smi->sif_otherbufcom;
230 v4 = 0;
231 if ( sif_otherbufcom->count > 0 )
232 {
233 int v5;
234
235 v5 = 0;
236 do
237 {
238 ++v4;
239 sif_otherbufcom->info[v5].func(sif_otherbufcom->info[v5].userdata);
240 sif_otherbufcom = smi->sif_otherbufcom;
241 v5 = v4;
242 } while ( v4 < sif_otherbufcom->count );
243 }
244 smi->sif_otherbufcom->count = 0;
245 if ( (iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000) == 0 && smi->dmatag_index > 0 )
246 {
247 iop_mmio_hwport->dmac2.newch[2].chcr = 0;
248 iop_mmio_hwport->dmac2.newch[2].tadr = (uiptr)(smi->sif_curbuf);
249 iop_mmio_hwport->dmac2.newch[2].bcr = (iop_mmio_hwport->dmac2.newch[2].bcr & 0xFFFF0000) | 32;
250 if ( (sif_mmio_hwport->controlreg & 0x20) == 0 )
251 sif_mmio_hwport->controlreg = 32;
252 ++smi->dma_count;
253 smi->dmatag_index = 0;
254 if ( smi->sif_curbuf == smi->sif_buf1 )
255 {
256 smi->sif_curbuf = smi->sif_buf2;
257 smi->sif_curbufcom = &smi->sif_bufcom2;
258 p_sif_bufcom1 = &smi->sif_bufcom1;
259 }
260 else
261 {
262 smi->sif_curbufcom = &smi->sif_bufcom1;
263 p_sif_bufcom1 = &smi->sif_bufcom2;
264 smi->sif_curbuf = smi->sif_buf1;
265 }
266 smi->sif_otherbufcom = p_sif_bufcom1;
267 iop_mmio_hwport->dmac2.newch[2].chcr = 0x1000701;
268 }
269 return 1;
270}
271
272static int sif_dma_init(void)
273{
274 int state;
275
276 sifman_internals.sif_curbuf = sifman_internals.sif_buf1;
277 sifman_internals.sif_curbufcom = &sifman_internals.sif_bufcom1;
278 sifman_internals.dmatag_index = 0;
279 sifman_internals.sif_bufcom1.count = 0;
280 sifman_internals.sif_bufcom2.count = 0;
281 sifman_internals.sif_otherbufcom = &sifman_internals.sif_bufcom2;
282 sifman_internals.dma_intr_handler = 0;
283 sifman_internals.dma_intr_handler_userdata = 0;
284 CpuSuspendIntr(&state);
285 RegisterIntrHandler(IOP_IRQ_DMA_SIF0, 1, sifman_interrupt_handler, &sifman_internals);
286 EnableIntr(IOP_IRQ_DMA_SIF0);
287 return CpuResumeIntr(state);
288}
289
290static int sif_dma_setup_tag(SifDmaTransfer_t *a1)
291{
292 sif_info_t *v1;
293 int v2;
294 unsigned int v3;
295 unsigned int v4;
296 unsigned int v5;
297
298 v1 = &sifman_internals.sif_curbuf[sifman_internals.dmatag_index];
299 v2 = (int)a1->src & 0xFFFFFF;
300 v3 = a1->size + 3;
301 v1->data = v2;
302 v4 = v3 >> 2;
303 if ( (a1->attr & 2) != 0 )
304 v1->data = v2 | 0x40000000;
305 v1->words = v4 & 0xFFFFFF;
306 v5 = v3 >> 4;
307 if ( (v4 & 3) != 0 )
308 ++v5;
309 v1->count = v5 | 0x10000000;
310 if ( (a1->attr & 4) != 0 )
311 v1->count |= 0x80000000;
312 v1->addr = (int)a1->dest & 0x1FFFFFFF;
313 return ++sifman_internals.dmatag_index;
314}
315
316static int set_dma_inner(SifDmaTransfer_t *dmat, int count, void (*func)(void *userdata), void *data)
317{
318 u8 dmatag_index;
319 int dma_count;
320 int i;
321 int v14;
322 sif_completion_cb_info_arr_t *p_sif_bufcom1;
323 USE_IOP_MMIO_HWPORT();
324 USE_SIF_MMIO_HWPORT();
325
326 if ( 32 - sifman_internals.dmatag_index < count )
327 return 0;
328 dmatag_index = sifman_internals.dmatag_index;
329 dma_count = sifman_internals.dma_count;
330 if ( sifman_internals.dmatag_index )
331 sifman_internals.sif_curbuf[sifman_internals.dmatag_index - 1].data &= ~0x80000000;
332 for ( i = 0; i < count; ++dmat )
333 {
334 sif_dma_setup_tag(dmat);
335 ++i;
336 }
337 sifman_internals.sif_curbuf[sifman_internals.dmatag_index - 1].data |= 0x80000000;
338 if ( func )
339 {
340 sifman_internals.sif_curbufcom->info[sifman_internals.sif_curbufcom->count].func = func;
341 sifman_internals.sif_curbufcom->info[sifman_internals.sif_curbufcom->count++].userdata = data;
342 }
343 v14 = dma_count << 16;
344 if ( (iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000) == 0 )
345 {
346 v14 = dma_count << 16;
347 if ( iop_mmio_hwport->dmac2.new_unusedch.madr == 0 )
348 {
349 v14 = dma_count << 16;
350 if ( (iop_mmio_hwport->dmac2.dicr2 & 0x4000000) == 0 )
351 {
352 iop_mmio_hwport->dmac2.newch[2].chcr = 0;
353 iop_mmio_hwport->dmac2.newch[2].tadr = (uiptr)(sifman_internals.sif_curbuf);
354 if ( (sif_mmio_hwport->controlreg & 0x20) == 0 )
355 sif_mmio_hwport->controlreg = 32;
356 iop_mmio_hwport->dmac2.newch[2].bcr = (iop_mmio_hwport->dmac2.newch[2].bcr & 0xFFFF0000) | 32;
357 sifman_internals.dmatag_index = 0;
358 ++sifman_internals.dma_count;
359 if ( sifman_internals.sif_curbuf == sifman_internals.sif_buf1 )
360 {
361 sifman_internals.sif_curbuf = sifman_internals.sif_buf2;
362 sifman_internals.sif_curbufcom = &sifman_internals.sif_bufcom2;
363 p_sif_bufcom1 = &sifman_internals.sif_bufcom1;
364 }
365 else
366 {
367 sifman_internals.sif_curbuf = sifman_internals.sif_buf1;
368 sifman_internals.sif_curbufcom = &sifman_internals.sif_bufcom1;
369 p_sif_bufcom1 = &sifman_internals.sif_bufcom2;
370 }
371 sifman_internals.sif_otherbufcom = p_sif_bufcom1;
372 iop_mmio_hwport->dmac2.newch[2].chcr = 0x1000701;
373 v14 = dma_count << 16;
374 }
375 }
376 }
377 return v14 | (dmatag_index << 8) | (u8)count;
378}
379
380int sceSifSetDma(SifDmaTransfer_t *dmat, int count)
381{
382 return set_dma_inner(dmat, count, 0, 0);
383}
384
385unsigned int sceSifSetDmaIntr(SifDmaTransfer_t *dmat, int count, void (*completioncb)(void *userdata), void *userdata)
386{
387 return set_dma_inner(dmat, count, completioncb, userdata);
388}
389
390static int dma_stat_inner(unsigned int a1)
391{
392 USE_IOP_MMIO_HWPORT();
393
394 if ( (iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000) == 0 && !iop_mmio_hwport->dmac2.new_unusedch.madr )
395 {
396 if ( (iop_mmio_hwport->dmac2.dicr2 & 0x4000000) == 0 )
397 return -1;
398 }
399 if ( sifman_internals.dma_count != ((a1 >> 16) & 0xFFFF) )
400 {
401 if ( sifman_internals.dma_count == (u16)(((a1 >> 16) & 0xFFFF) + 1) )
402 return 0;
403 return -1;
404 }
405 return 1;
406}
407
408int sceSifDmaStat(int trid)
409{
410 int v2;
411 int state;
412
413 if ( QueryIntrContext() )
414 return dma_stat_inner(trid);
415 CpuSuspendIntr(&state);
416 v2 = dma_stat_inner(trid);
417 CpuResumeIntr(state);
418 return v2;
419}
420
421void sceSifSetOneDma(SifDmaTransfer_t dmat)
422{
423 int v1;
424 unsigned int v2;
425 unsigned int v3;
426 USE_IOP_MMIO_HWPORT();
427 USE_SIF_MMIO_HWPORT();
428
429 v1 = ((int)dmat.src & 0xFFFFFF) | 0x80000000;
430 v2 = ((unsigned int)dmat.size >> 2) + ((dmat.size & 3) != 0);
431 sifman_internals.one.data = v1;
432 sifman_internals.one.words = v2 & 0xFFFFFF;
433 if ( (dmat.attr & 2) != 0 )
434 sifman_internals.one.data = v1 | 0x40000000;
435 v3 = v2 >> 2;
436 if ( (v2 & 3) != 0 )
437 ++v3;
438 sifman_internals.one.count = v3 | 0x10000000;
439 if ( (dmat.attr & 4) != 0 )
440 sifman_internals.one.count |= 0x80000000;
441 sifman_internals.one.addr = (int)dmat.dest & 0xFFFFFFF;
442 if ( (sif_mmio_hwport->controlreg & 0x20) == 0 )
443 sif_mmio_hwport->controlreg = 32;
444 iop_mmio_hwport->dmac2.newch[2].chcr = 0;
445 iop_mmio_hwport->dmac2.newch[2].tadr = (uiptr)&sifman_internals.one;
446 iop_mmio_hwport->dmac2.newch[2].bcr = (iop_mmio_hwport->dmac2.newch[2].bcr & 0xFFFF0000) | 32;
447 iop_mmio_hwport->dmac2.newch[2].chcr = 0x1000701;
448}
449
450void sceSifSendSync()
451{
452 USE_IOP_MMIO_HWPORT();
453
454 while ( iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000 )
455 ;
456}
457
458int sceSifIsSending()
459{
460 USE_IOP_MMIO_HWPORT();
461
462 return iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000;
463}
464
465void sceSifDma0Transfer(void *addr, int size, int mode)
466{
467 unsigned int v4;
468 int v5;
469 USE_IOP_MMIO_HWPORT();
470 USE_SIF_MMIO_HWPORT();
471
472 (void)mode;
473
474 v4 = ((unsigned int)size >> 2) + ((size & 3) != 0);
475 if ( (sif_mmio_hwport->controlreg & 0x20) == 0 )
476 sif_mmio_hwport->controlreg = 32;
477 iop_mmio_hwport->dmac2.newch[2].chcr = 0;
478 iop_mmio_hwport->dmac2.newch[2].madr = (unsigned int)addr & 0xFFFFFF;
479 if ( (v4 & 0x1F) != 0 )
480 v5 = (v4 >> 5) + 1;
481 else
482 v5 = v4 >> 5;
483 iop_mmio_hwport->dmac2.newch[2].bcr = ((v5 & 0xFFFF) << 16) | 32;
484 iop_mmio_hwport->dmac2.newch[2].chcr = 0x1000201;
485}
486
487void sceSifDma0Sync()
488{
489 USE_IOP_MMIO_HWPORT();
490
491 while ( iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000 )
492 ;
493}
494
495int sceSifDma0Sending()
496{
497 USE_IOP_MMIO_HWPORT();
498
499 return iop_mmio_hwport->dmac2.newch[2].chcr & 0x1000000;
500}
501
502void sceSifDma1Transfer(void *addr, int size, int mode)
503{
504 unsigned int v4;
505 int v5;
506 int v6;
507 USE_IOP_MMIO_HWPORT();
508 USE_SIF_MMIO_HWPORT();
509
510 v4 = ((unsigned int)size >> 2) + ((size & 3) != 0);
511 if ( (sif_mmio_hwport->controlreg & 0x40) == 0 )
512 sif_mmio_hwport->controlreg = 64;
513 iop_mmio_hwport->dmac2.newch[3].chcr = 0;
514 iop_mmio_hwport->dmac2.newch[3].madr = (unsigned int)addr & 0xFFFFFF;
515 if ( (v4 & 0x1F) != 0 )
516 v5 = (v4 >> 5) + 1;
517 else
518 v5 = v4 >> 5;
519 iop_mmio_hwport->dmac2.newch[3].bcr = ((v5 & 0xFFFF) << 16) | 32;
520 if ( (mode & 0x10) != 0 )
521 v6 = 0x41000000;
522 else
523 v6 = 0x1000000;
524 iop_mmio_hwport->dmac2.newch[3].chcr = v6 | 0x200;
525}
526
527void sceSifDma1Sync()
528{
529 USE_IOP_MMIO_HWPORT();
530
531 while ( iop_mmio_hwport->dmac2.newch[3].chcr & 0x1000000 )
532 ;
533}
534
535int sceSifDma1Sending()
536{
537 USE_IOP_MMIO_HWPORT();
538
539 return iop_mmio_hwport->dmac2.newch[3].chcr & 0x1000000;
540}
541
542void sceSifDma2Transfer(void *addr, int size, int mode)
543{
544 unsigned int v4;
545 u16 v5;
546 int v6;
547 int v7;
548 USE_IOP_MMIO_HWPORT();
549 USE_SIF_MMIO_HWPORT();
550
551 v4 = ((unsigned int)size >> 2) + ((size & 3) != 0);
552 if ( (sif_mmio_hwport->controlreg & 0x80) == 0 )
553 sif_mmio_hwport->controlreg = 128;
554 v5 = v4;
555 iop_mmio_hwport->dmac1.oldch[2].chcr = 0;
556 iop_mmio_hwport->dmac1.oldch[2].madr = (unsigned int)addr & 0xFFFFFF;
557 if ( v4 >= 0x21 )
558 v5 = 32;
559 if ( (v4 & 0x1F) != 0 )
560 v6 = (v4 >> 5) + 1;
561 else
562 v6 = v4 >> 5;
563 iop_mmio_hwport->dmac1.oldch[2].bcr = ((v6 & 0xFFFF) << 16) | (v5 & 0xFFFF);
564 if ( (mode & 1) != 0 )
565 {
566 v7 = 0x1000201;
567 }
568 else
569 {
570 int v8;
571
572 if ( (mode & 0x10) != 0 )
573 v8 = 0x41000000;
574 else
575 v8 = 0x1000000;
576 v7 = v8 | 0x200;
577 }
578 iop_mmio_hwport->dmac1.oldch[2].chcr = v7;
579}
580
581void sceSifDma2Sync()
582{
583 USE_IOP_MMIO_HWPORT();
584
585 while ( iop_mmio_hwport->dmac1.oldch[2].chcr & 0x1000000 )
586 ;
587}
588
589int sceSifDma2Sending()
590{
591 USE_IOP_MMIO_HWPORT();
592
593 return iop_mmio_hwport->dmac1.oldch[2].chcr & 0x1000000;
594}
595
596u32 sceSifGetMSFlag()
597{
598 return get_msflag();
599}
600
601u32 sceSifSetMSFlag(u32 val)
602{
603 USE_SIF_MMIO_HWPORT();
604
605 sif_mmio_hwport->msflag = val;
606 return get_msflag();
607}
608
609u32 sceSifGetSMFlag()
610{
611 return get_smflag();
612}
613
614u32 sceSifSetSMFlag(u32 val)
615{
616 USE_SIF_MMIO_HWPORT();
617
618 sif_mmio_hwport->smflag = val;
619 return get_smflag();
620}
621
622u32 sceSifGetMainAddr()
623{
624 USE_SIF_MMIO_HWPORT();
625
626 return sif_mmio_hwport->mscom;
627}
628
629u32 sceSifGetSubAddr()
630{
631 USE_SIF_MMIO_HWPORT();
632
633 return sif_mmio_hwport->smcom;
634}
635
636u32 sceSifSetSubAddr(u32 addr)
637{
638 USE_SIF_MMIO_HWPORT();
639
640 sif_mmio_hwport->smcom = addr;
641 return sif_mmio_hwport->smcom;
642}
643
644void sceSifIntrMain()
645{
646 u32 v0;
647 USE_IOP_MMIO_HWPORT();
648
649 v0 = iop_mmio_hwport->iop_sbus_ctrl[0];
650 iop_mmio_hwport->iop_sbus_ctrl[0] = v0 | 2;
651 // cppcheck-suppress redundantAssignment
652 iop_mmio_hwport->iop_sbus_ctrl[0] = v0 & 0xFFFFFFFD;
653}
int CpuResumeIntr(int state)
Definition intrman.c:227
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 RegisterIntrHandler(int irq, int mode, int(*handler)(void *arg), void *arg)
Definition intrman.c:125
int EnableIntr(int irq)
Definition intrman.c:346
#define SIF_STAT_SIFINIT
Definition sifdma.h:46
u32 count
start sector of fragmented bd/file