PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
clearspu.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
13#define MODNAME "clearspu"
14IRX_ID(MODNAME, 1, 1);
15
16static char buf_zero[0xC00];
17
18static void _spu2_config_initialize(void);
19static void _spu2_config_initialize_typically(void);
20static void start_inner2(void);
21static int do_spu_intr(void *userdata);
22static void SpuStart(void);
23static void spu_init_(void);
24static int do_dma_finish(void *userdata);
25static void do_dma_stop(int which_core);
26static int do_dma_get_status(int which_core);
27static void do_dma_start(void *addr, int size, int which_core);
28static void do_spu_wait(void);
29
30int _start(int argc, char *argv[])
31{
32 int i;
33 int dummyarg[2];
34
35 (void)argc;
36 (void)argv;
37
38 ReleaseIntrHandler(IOP_IRQ_DMA_SPU2);
39 ReleaseIntrHandler(IOP_IRQ_DMA_SPU);
40 ReleaseIntrHandler(IOP_IRQ_SPU);
41 DisableIntr(IOP_IRQ_DMA_SPU2, dummyarg);
42 DisableIntr(IOP_IRQ_DMA_SPU, dummyarg);
43 DisableIntr(IOP_IRQ_SPU, dummyarg);
44 _spu2_config_initialize();
45 start_inner2();
46 _spu2_config_initialize_typically();
48 EnableIntr(IOP_IRQ_DMA_SPU);
49 EnableIntr(IOP_IRQ_DMA_SPU2);
50 EnableIntr(IOP_IRQ_SPU);
51 memset(buf_zero, 0, sizeof(buf_zero));
52 for ( i = 0; i < 2; i += 1 )
53 {
54 // Unofficial: Apply fixed argument, remove unused branches
55 do_dma_start(buf_zero, sizeof(buf_zero), i);
56 }
57 while ( do_dma_get_status(0) && do_dma_get_status(1) )
58 ;
59 ReleaseIntrHandler(IOP_IRQ_DMA_SPU2);
60 ReleaseIntrHandler(IOP_IRQ_DMA_SPU);
61 ReleaseIntrHandler(IOP_IRQ_SPU);
62 printf("clearspu: completed\n");
63 // Unofficial: Return non-resident
64 return MODULE_NO_RESIDENT_END;
65}
66
67static void spu2_config_iop_(void)
68{
69 *((vu32 *)0xBF801404) = 0xBF900000;
70 *((vu32 *)0xBF80140C) = 0xBF900800;
71 *((vu32 *)0xBF8010F0) |= 0x80000u;
72 *((vu32 *)0xBF801570) |= 8u;
73 *((vu32 *)0xBF801014) = 0x200B31E1;
74 *((vu32 *)0xBF801414) = 0x200B31E1;
75}
76
77static void spu2_config_SPDIF_(void)
78{
79 // Unofficial: Remove unused branch and contents
80 *((vu16 *)0xBF9007C6) = 2304;
81 *((vu16 *)0xBF9007C8) = 512;
82 *((vu16 *)0xBF9007CA) = 8;
83}
84
85static void _spu2_config_initialize(void)
86{
87 spu2_config_iop_();
88 spu2_config_SPDIF_();
89}
90
91static void _spu2_config_initialize_typically(void)
92{
93 // Unofficial: Remove unused branch and contents
94 *((vu16 *)0xBF9007C0) = -16334;
95 *((vu16 *)0xBF90019A) = -16384;
96 *((vu16 *)0xBF90059A) = -16383;
97 *((vu16 *)0xBF900188) = -1;
98 *((vu16 *)0xBF90018A) = 255;
99 *((vu16 *)0xBF900190) = -1;
100 *((vu16 *)0xBF900192) = 255;
101 *((vu16 *)0xBF90018C) = -1;
102 *((vu16 *)0xBF90018E) = 255;
103 *((vu16 *)0xBF900194) = -1;
104 *((vu16 *)0xBF900196) = 255;
105 *((vu16 *)0xBF900588) = -1;
106 *((vu16 *)0xBF90058A) = 255;
107 *((vu16 *)0xBF900590) = -1;
108 *((vu16 *)0xBF900592) = 255;
109 *((vu16 *)0xBF90058C) = -1;
110 *((vu16 *)0xBF90058E) = 255;
111 *((vu16 *)0xBF900594) = -1;
112 *((vu16 *)0xBF900596) = 255;
113 *((vu16 *)0xBF900198) = 4080;
114 *((vu16 *)0xBF900598) = 4092;
115 *((vu16 *)0xBF900760) = 0;
116 *((vu16 *)0xBF900762) = 0;
117 *((vu16 *)0xBF900788) = 0;
118 *((vu16 *)0xBF90078A) = 0;
119 *((vu16 *)0xBF900764) = 0;
120 *((vu16 *)0xBF900766) = 0;
121 *((vu16 *)0xBF90078C) = 0;
122 *((vu16 *)0xBF90078E) = 0;
123 *((vu16 *)0xBF90033C) = 14;
124 *((vu16 *)0xBF90073C) = 15;
125 *((vu16 *)0xBF900768) = 0;
126 *((vu16 *)0xBF90076A) = 0;
127 *((vu16 *)0xBF900790) = 0x7FFF;
128 *((vu16 *)0xBF900792) = 0x7FFF;
129 *((vu16 *)0xBF90076C) = 0;
130 *((vu16 *)0xBF90076E) = 0;
131 *((vu16 *)0xBF900794) = 0;
132 *((vu16 *)0xBF900796) = 0;
133}
134
135static void start_inner2(void)
136{
137 spu_init_();
138 // Unofficial: Remove setting of never read variables
139 SpuStart();
140}
141
142static int do_spu_intr(void *userdata)
143{
144 (void)userdata;
145 // Unofficial: Always return 0 (callback never set!)
146 return 0;
147}
148
149static int intr_flag_spu12[2] = {0, 1};
150
151static void SpuStart(void)
152{
154 ReleaseIntrHandler(IOP_IRQ_DMA_SPU);
155 ReleaseIntrHandler(IOP_IRQ_DMA_SPU2);
156 RegisterIntrHandler(IOP_IRQ_DMA_SPU, 1, do_dma_finish, &intr_flag_spu12[0]);
157 RegisterIntrHandler(IOP_IRQ_DMA_SPU2, 1, do_dma_finish, &intr_flag_spu12[1]);
159 ReleaseIntrHandler(IOP_IRQ_SPU);
160 RegisterIntrHandler(IOP_IRQ_SPU, 1, do_spu_intr, 0);
161}
162
163static void spu_init_(void)
164{
165 vu16 *v0;
166 vu16 *spu_RXX_;
167 vu32 *spu_sys_pcr_;
168 int i;
169
170 // Unofficial: Make variables local
171 spu_RXX_ = (vu16 *)0xBF900000;
172 spu_sys_pcr_ = (vu32 *)0xBF8010F0;
173 *spu_sys_pcr_ |= 0xB0000u;
174 v0 = &spu_RXX_[0];
175 v0[944] = 0;
176 v0[945] = 0;
177 v0[1456] = 0;
178 v0[1457] = 0;
179 do_dma_stop(0);
180 do_dma_stop(1);
181 for ( i = 0; i < 2; i += 1 )
182 {
183 vu16 *v3;
184 vu16 *v4;
185 unsigned int v5;
186 vu16 *v6;
187
188 // Unofficial: Remove setting of never read variables
189 spu_RXX_[512 * i + 205] = 0;
190 do_spu_wait();
191 do_spu_wait();
192 do_spu_wait();
193 spu_RXX_[512 * i + 205] = 0x8000;
194 do_spu_wait();
195 do_spu_wait();
196 do_spu_wait();
197 v3 = &spu_RXX_[20 * i];
198 v4 = &spu_RXX_[512 * i];
199 v3[944] = 0;
200 v3[945] = 0;
201 v5 = 1;
202 while ( (v4[418] & 0x7FF) != 0 )
203 {
204 if ( v5 >= 0xF01 )
205 {
206 printf("SPU:T/O [%s]\n", "wait (reset)");
207 break;
208 }
209 ++v5;
210 }
211 v6 = &spu_RXX_[512 * i];
212 v6[210] = -1;
213 v6[211] = -1;
214 }
215}
216
217static int do_dma_finish(void *userdata)
218{
219 int which_core;
220
221 which_core = (*(u32 *)userdata) & 0xFF;
222 // Unofficial: Remove never used branch
223 *(vu16 *)((which_core << 10) + 0xBF90019A) &= 0xFFCFu;
224 *(vu16 *)((which_core << 10) + 0xBF900198) &= 0xFF3Fu;
225 *(vu16 *)((which_core << 10) + 0xBF9001B0) = 0;
226 // Unofficial: Remove calling of callback that is never set
227 FlushDcache();
228 return 1;
229}
230
231static void do_dma_stop(int which_core)
232{
233 *(vu16 *)((which_core << 10) + 0xBF90019A) &= 0xFFCFu;
234 *(vu16 *)((which_core << 10) + 0xBF9001B0) = 0;
235}
236
237static int do_dma_get_status(int which_core)
238{
239 // Unofficial: Apply fixed variables
240 if ( *(vu16 *)((which_core << 10) + 0xBF9001B0) )
241 return (*(vu32 *)(1088 * which_core + 0xBF8010C0)) & 0xFFFFFF;
242 return 0;
243}
244
245static void do_dma_start(void *addr, int size, int which_core)
246{
247 // Unofficial: Apply fixed variables
248 *(vu16 *)((which_core << 10) + 0xBF90019A) &= 0xFFCFu;
249 *(vu16 *)((which_core << 10) + 0xBF9001A8) = 0;
250 *(vu16 *)((which_core << 10) + 0xBF9001AA) = 0;
251 *(vu16 *)((which_core << 10) + 0xBF9001B0) = 1 << which_core;
252 *(vu32 *)(1088 * which_core + 0xBF8010C0) = (uiptr)addr;
253 *(vu16 *)(1088 * which_core + 0xBF8010C4) = 16;
254 *(vu16 *)(1088 * which_core + 0xBF8010C6) = size / 64 + (size % 64 > 0);
255 *(vu32 *)(1088 * which_core + 0xBF8010C8) = 16777729;
256}
257
258static void do_spu_wait(void)
259{
260 int i;
261 int v1;
262
263 v1 = 13;
264 for ( i = 0; i < 80; ++i )
265 {
266 __asm__ __volatile__("" : "+g"(v1) : :);
267 v1 *= 13;
268 }
269}
int CpuEnableIntr()
Definition intrman.c:250
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *), void *arg)
Definition intrman.c:125
int ReleaseIntrHandler(int irq)
Definition intrman.c:167
int CpuDisableIntr()
Definition intrman.c:238
int DisableIntr(int irq, int *res)
Definition intrman.c:395
int EnableIntr(int irq)
Definition intrman.c:346