PS2SDK
PS2 Homebrew Libraries
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"
14 IRX_ID(MODNAME, 1, 1);
15 
16 static char buf_zero[0xC00];
17 
18 static void _spu2_config_initialize(void);
19 static void _spu2_config_initialize_typically(void);
20 static void start_inner2(void);
21 static int do_spu_intr(void *userdata);
22 static void SpuStart(void);
23 static void spu_init_(void);
24 static int do_dma_finish(void *userdata);
25 static void do_dma_stop(int which_core);
26 static int do_dma_get_status(int which_core);
27 static void do_dma_start(void *addr, int size, int which_core);
28 static void do_spu_wait(void);
29 
30 int _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();
47  CpuEnableIntr();
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 
67 static 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 
77 static 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 
85 static void _spu2_config_initialize(void)
86 {
87  spu2_config_iop_();
88  spu2_config_SPDIF_();
89 }
90 
91 static 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 
135 static void start_inner2(void)
136 {
137  spu_init_();
138  // Unofficial: Remove setting of never read variables
139  SpuStart();
140 }
141 
142 static int do_spu_intr(void *userdata)
143 {
144  (void)userdata;
145  // Unofficial: Always return 0 (callback never set!)
146  return 0;
147 }
148 
149 static int intr_flag_spu12[2] = {0, 1};
150 
151 static void SpuStart(void)
152 {
153  CpuDisableIntr();
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]);
158  CpuEnableIntr();
159  ReleaseIntrHandler(IOP_IRQ_SPU);
160  RegisterIntrHandler(IOP_IRQ_SPU, 1, do_spu_intr, 0);
161 }
162 
163 static 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 
217 static 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 
231 static void do_dma_stop(int which_core)
232 {
233  *(vu16 *)((which_core << 10) + 0xBF90019A) &= 0xFFCFu;
234  *(vu16 *)((which_core << 10) + 0xBF9001B0) = 0;
235 }
236 
237 static 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 
245 static 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 
258 static 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 }
CpuDisableIntr
int CpuDisableIntr()
Definition: intrman.c:228
RegisterIntrHandler
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *arg), void *arg)
Definition: intrman.c:115
ReleaseIntrHandler
int ReleaseIntrHandler(int irq)
Definition: intrman.c:157
CpuEnableIntr
int CpuEnableIntr()
Definition: intrman.c:240
DisableIntr
int DisableIntr(int irq, int *res)
Definition: intrman.c:385
EnableIntr
int EnableIntr(int irq)
Definition: intrman.c:336