PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
ram.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 "acram_internal.h"
12
13static int ram_dma_xfer(acDmaT dma, int intr, acDmaOp op);
14static void ram_dma_done(acDmaT dma);
15static void ram_dma_error(acDmaT dma, int intr, acDmaState state, int result);
16
17static acUint32 Ram_limits[] = {0x2000000, 0x4000000, 0x4000000};
18static const acDmaOpsData ops_22 = {&ram_dma_xfer, &ram_dma_done, &ram_dma_error};
19static struct ram_softc Ramc;
20
21static int ram_dma_xfer(acDmaT dma, int intr, acDmaOp op)
22{
23 int i;
24 int v5;
25 int bank;
26 int size;
27 acRamAddr output;
28 acRamAddr addr;
29 acRamAddr v10;
30 int v11;
31 acRamReg ramreg;
32 void *buf;
33 void *ioaddr;
34 int v16;
35 struct ram_softc *dmatmp;
36
37 (void)intr;
38 dmatmp = (struct ram_softc *)dma;
39 i = 0;
40 v5 = 0;
41 while ( 1 )
42 {
43 bank = i;
44 if ( dmatmp->addr < Ram_limits[v5] )
45 break;
46 v5 = ++i;
47 if ( (unsigned int)i >= 3 )
48 {
49 bank = -14;
50 break;
51 }
52 }
53 size = dmatmp->size;
54 output = dmatmp->addr & 1;
55 addr = dmatmp->addr - output;
56 if ( bank < 0 )
57 return -34;
58 v10 = Ram_limits[bank];
59 if ( addr + size >= v10 )
60 size = v10 - addr;
61 v11 = bank << 21;
62 if ( size <= 0 )
63 return -34;
64 ramreg = (acRamReg)(v11 + 0xB4000000);
65 dmatmp->result = size;
66 buf = dmatmp->buf;
67 *(acUint16 *)((size & 0x7FC) + v11 + 0xB4000000 + 0x20000) = size >> 11;
68 ioaddr = (void *)(v11 + 0xB4000000 + 0x100000);
69 if ( bank > 0 )
70 addr -= Ram_limits[bank - 1];
71 if ( output )
72 v16 = 0x70000;
73 else
74 v16 = 0x60000;
75 *(acRamReg)((char *)ramreg + (addr & 0x7FC) + v16) = addr >> 11;
76 return op(dma, ioaddr, buf, size);
77}
78
79static void ram_dma_done(acDmaT dma)
80{
81 int thid;
82 struct ram_softc *dmatmp;
83
84 dmatmp = (struct ram_softc *)dma;
85 thid = dmatmp->thid;
86 dmatmp->size = 0;
87 if ( thid )
88 iWakeupThread(thid);
89}
90
91static void ram_dma_error(acDmaT dma, int intr, acDmaState state, int result)
92{
93 int thid;
94 struct ram_softc *dmatmp;
95
96 dmatmp = (struct ram_softc *)dma;
97 thid = dmatmp->thid;
98 dmatmp->result = result;
99 dmatmp->size = 0;
100 if ( thid )
101 {
102 if ( intr )
103 iWakeupThread(thid);
104 else
105 WakeupThread(thid);
106 }
107 Kprintf("acram:dma_error: state=%d ret=%d\n", state, result);
108}
109
110static int ram_dma_request(struct ram_softc *ramc, acRamT ram)
111{
112 int count;
113 acRamAddr r_addr;
114 int ret;
115 acUint8 *r_buf;
116 int output;
117 acUint8 *buf;
118
119 count = ram->r_count;
120 r_addr = ram->r_addr;
121 ret = 0;
122 ramc->addr = r_addr;
123 r_buf = (acUint8 *)ram->r_buf;
124 output = r_addr & 1;
125 ramc->size = count;
126 ramc->result = 0;
127 for ( ramc->buf = r_buf; count > 0; ramc->buf = &buf[ret] )
128 {
129 acDmaT dma;
130 acRamAddr addr;
131
132 dma = acDmaSetup(&ramc->dma, (acDmaOpsData *)&ops_22, 7, 64, output);
133 CancelWakeupThread(0);
134 ret = acDmaRequest(dma);
135 if ( ret < 0 )
136 break;
137 while ( ramc->size )
138 SleepThread();
139 ret = ramc->result;
140 count -= ret;
141 if ( ret < 0 )
142 break;
143 addr = ramc->addr;
144 buf = ramc->buf;
145 ramc->size = count;
146 ramc->addr = addr + ret;
147 }
148 return ret;
149}
150
151static void ram_thread(void *arg)
152{
153 acQueueHeadData *qh;
154 int thid;
155 acRamT ram;
156 int ret;
157 acQueueT q_next;
158 acQueueT q_prev;
159 acRamDone r_done;
160 acSpl state;
161 struct ram_softc *argt;
162
163 argt = (struct ram_softc *)arg;
164 qh = &argt->requestq;
165 thid = GetThreadId();
166 argt->thid = thid;
167 while ( 1 )
168 {
169 CpuSuspendIntr(&state);
170 ram = 0;
171 if ( qh != qh->q_next )
172 ram = (acRamT)qh->q_next;
173 CpuResumeIntr(state);
174 if ( ram )
175 {
176 ret = ram_dma_request(argt, ram);
177 CpuSuspendIntr(&state);
178 q_next = ram->r_chain.q_next;
179 q_prev = ram->r_chain.q_prev;
180 q_prev->q_next = q_next;
181 q_next->q_prev = q_prev;
182 CpuResumeIntr(state);
183 r_done = ram->r_done;
184 if ( r_done )
185 r_done(ram, ram->r_arg, ret);
186 }
187 else
188 {
189 SleepThread();
190 }
191 if ( thid != argt->thid )
192 ExitThread();
193 }
194}
195
196acRamT acRamSetup(acRamData *ram, acRamDone done, void *arg, int tmout)
197{
198 if ( ram )
199 {
200 ram->r_tmout = tmout;
201 ram->r_done = done;
202 ram->r_arg = arg;
203 }
204 return ram;
205}
206
207static int ram_request(acRamT ram, acRamAddr addr, void *buf, int count, int (*wakeup)(int thid), int out)
208{
209 int thid;
210 acQueueT out_v8;
211 acSpl state;
212
213 if ( !Ramc.thid )
214 return -6;
215 if ( !ram )
216 return -22;
217 if ( !buf )
218 return -22;
219 if ( (addr & 3) != 0 )
220 {
221 return -14;
222 }
223 if ( ((uiptr)buf & 3) != 0 )
224 {
225 return -14;
226 }
227 if ( count < 3 )
228 {
229 return 0;
230 }
231 ram->r_buf = buf;
232 ram->r_count = count;
233 ram->r_addr = addr | out;
234 CpuSuspendIntr(&state);
235 thid = Ramc.thid;
236 if ( Ramc.thid )
237 {
238 if ( Ramc.requestq.q_next != &Ramc.requestq )
239 wakeup = 0;
240 out_v8 = Ramc.requestq.q_prev;
241 ram->r_chain.q_next = &Ramc.requestq;
242 ram->r_chain.q_prev = out_v8;
243 out_v8->q_next = &ram->r_chain;
244 Ramc.requestq.q_prev = &ram->r_chain;
245 }
246 else
247 {
248 wakeup = 0;
249 }
250 CpuResumeIntr(state);
251 if ( !thid )
252 return -6;
253 if ( wakeup )
254 {
255 wakeup(thid);
256 return 1;
257 }
258 return 0;
259}
260
261int acRamRead(acRamT ram, acRamAddr addr, void *buf, int count)
262{
263 return ram_request(ram, addr, buf, count, WakeupThread, 0);
264}
265
266int acRamReadI(acRamT ram, acRamAddr addr, void *buf, int count)
267{
268 return ram_request(ram, addr, buf, count, iWakeupThread, 0);
269}
270
271int acRamWrite(acRamT ram, acRamAddr addr, void *buf, int count)
272{
273 return ram_request(ram, addr, buf, count, WakeupThread, 1);
274}
275
276int acRamWriteI(acRamT ram, acRamAddr addr, void *buf, int count)
277{
278 return ram_request(ram, addr, buf, count, iWakeupThread, 1);
279}
280
281static int ram_thread_init(struct ram_softc *ramc, int prio)
282{
283 int th;
284 iop_thread_t param;
285
286 param.attr = 0x2000000;
287 param.thread = ram_thread;
288 param.priority = prio;
289 param.stacksize = 0x800;
290 param.option = 0;
291 th = CreateThread(&param);
292 if ( th > 0 )
293 StartThread(th, ramc);
294 return th;
295}
296
297static unsigned int ram_refresh(void *arg)
298{
299 const struct ram_softc *argt;
300
301 argt = (struct ram_softc *)arg;
302 return argt->refresh;
303}
304
305int acRamModuleStart(int argc, char **argv)
306{
307 int index;
308 int prio;
309 char **v8;
310 char *opt;
311 int v10;
312 const char *opt_v7;
313 int value;
314 int retry;
315 int ret;
316 char *msg;
317 iop_sys_clock_t v16;
318 char *next;
319
320 if ( acRamModuleStatus() != 0 )
321 {
322 return -16;
323 }
324 index = 1;
325 prio = 82;
326 v8 = argv + 1;
327 while ( index < argc )
328 {
329 opt = *v8;
330 if ( **v8 == '-' )
331 {
332 v10 = opt[1];
333 opt_v7 = opt + 2;
334 if ( v10 == 'p' )
335 {
336 value = strtol(opt_v7, &next, 0);
337 if ( next != opt_v7 )
338 prio = value;
339 }
340 }
341 ++index;
342 ++v8;
343 }
344 retry = 0xFFFFF;
345 *((volatile acUint16 *)0xB2416012) = 0;
346 Ramc.requestq.q_prev = &Ramc.requestq;
347 Ramc.requestq.q_next = &Ramc.requestq;
348 Ramc.addr = 0;
349 Ramc.buf = 0;
350 Ramc.size = 0;
351 Ramc.result = 0;
352 Ramc.thid = 0;
353 Ramc.refresh = 0;
354 while ( retry >= 0 )
355 {
356 if ( (*((volatile acUint16 *)0xB241C000) & 0x1000) == 0 )
357 {
358 break;
359 }
360 --retry;
361 }
362 *((volatile acUint16 *)0xB4640000) = 0;
363 ChangeThreadPriority(0, 123);
364 USec2SysClock(0x411Bu, &v16);
365 Ramc.refresh = v16.lo;
366 ret = SetAlarm(&v16, ram_refresh, &Ramc);
367 if ( ret )
368 {
369 msg = "ram refresh";
370 }
371 else
372 {
373 ret = ram_thread_init(&Ramc, prio);
374 if ( ret <= 0 )
375 {
376 CancelAlarm(ram_refresh, &Ramc);
377 msg = "thread";
378 }
379 else
380 {
381 Ramc.thid = ret;
382 return 0;
383 }
384 }
385 printf("acram:module: %s: error %d\n", msg, ret);
386 return -6;
387}
388
389int acRamModuleStop()
390{
391 int thid;
392 int ret_v3;
393
394 if ( !acRamModuleStatus() )
395 return 0;
396 thid = Ramc.thid;
397 *((volatile acUint16 *)0xB2416010) = 0;
398 if ( Ramc.thid > 0 )
399 {
400 int i;
401
402 Ramc.thid = 0;
403 WakeupThread(thid);
404 for ( i = 1000;; i = 1000000 )
405 {
406 int ret;
407
408 DelayThread(i);
409 ret = DeleteThread(thid);
410 if ( !ret )
411 break;
412 printf("acram:term_thread: DELETE ret=%d\n", ret);
413 }
414 }
415 ret_v3 = CancelAlarm(ram_refresh, &Ramc);
416 if ( ret_v3 != 0 )
417 return -6;
418 return 0;
419}
420
421int acRamModuleRestart(int argc, char **argv)
422{
423 (void)argc;
424 (void)argv;
425
426 return -88;
427}
428
429int acRamModuleStatus()
430{
431 int ret;
432 int state;
433
434 CpuSuspendIntr(&state);
435 if ( Ramc.thid )
436 {
437 ret = 2;
438 if ( Ramc.requestq.q_next == &Ramc.requestq )
439 ret = 1;
440 }
441 else
442 {
443 ret = 0;
444 }
445 CpuResumeIntr(state);
446 return ret;
447}
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
Definition acram.h:23
u32 count
start sector of fragmented bd/file