PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
dma.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 "accore_internal.h"
12
13static struct dma_softc Dmac;
14
15static int dma_cancel(struct dma_softc *dmac, acDmaT dma, int intr, int result)
16{
17 int d_state;
18 acQueueT q_next;
19 acQueueT q_prev;
20 acSpl state;
21
22 (void)dmac;
23 CpuSuspendIntr(&state);
24 d_state = dma->d_state;
25 if ( d_state )
26 {
27 if ( (unsigned int)d_state <= 3u )
28 {
29 if ( d_state == 3 )
30 {
31 dmac_disable(8u);
32 }
33 q_next = dma->d_chain.q_next;
34 q_prev = dma->d_chain.q_prev;
35 q_prev->q_next = q_next;
36 q_next->q_prev = q_prev;
37 }
38 else
39 {
40 d_state = -13;
41 }
42 }
43 else
44 {
45 d_state = -13;
46 }
47 CpuResumeIntr(state);
48 if ( d_state >= 0 )
49 {
50 acDmaOpsT ops;
51
52 ops = dma->d_ops;
53 dma->d_state = 0;
54 ops->do_error(dma, intr, (acDmaState)d_state, result);
55 }
56 return d_state;
57}
58
59static int dma_xfer(acDmaT dma, void *ioptr, void *buf, int count)
60{
61 int slice;
62 int ret;
63 int slice_v2;
64 int ret_v3;
65 int state;
66
67 slice = dma->d_slice;
68 if ( count >= 4 << slice )
69 {
70 ret = count >> (slice + 2);
71 slice_v2 = 1 << slice;
72 }
73 else
74 {
75 ret = count >> 2;
76 slice_v2 = 1;
77 }
78 CpuSuspendIntr(&state);
79 if ( dma == (acDmaT)Dmac.requestq.q_next && dma->d_state == 2 )
80 {
81 if ( ret > 0 )
82 {
83 int attr;
84 unsigned int v12;
85 int v13;
86 int v14;
87
88 attr = dma->d_attr;
89 v12 = GetAcIoDelayReg() & 0x80FFDFFF;
90 v13 = 0x62000000;
91 if ( ioptr == (void *)0xB6000000 )
92 v13 = 0x24000000;
93 SetAcIoDelayReg(v12 | v13);
94 dmac_ch_set_dpcr(8u, (unsigned int)attr >> 5);
95 dmac_enable(8u);
96 v14 = dmac_request(8u, buf, slice_v2, ret, attr & 1);
97 if ( v14 == 1 )
98 {
99 *((volatile acUint32 *)0x1F801410) = ((unsigned int)ioptr & 0x3FFFFFF) | 0x14000000;
100 Dmac.status = 2;
101 dma->d_state = 3;
102 dmac_transfer(8u);
103 ret_v3 = 1;
104 }
105 else
106 {
107 Dmac.status = 1;
108 ret_v3 = -5;
109 }
110 }
111 else
112 {
113 ret_v3 = -22;
114 }
115 }
116 else
117 {
118 ret_v3 = -13;
119 }
120 CpuResumeIntr(state);
121 return ret_v3;
122}
123
124static int dma_request(struct dma_softc *dmac, acDmaT dma, int intr)
125{
126 acDmaState d_state;
127 acDmaOpsT ops;
128 int ret;
129 acSpl state;
130
131 CpuSuspendIntr(&state);
132 if ( dma )
133 {
134 d_state = dma->d_state;
135 }
136 else
137 {
138 acDmaT q_next;
139
140 q_next = (acDmaT)dmac->requestq.q_next;
141 d_state = AC_DMA_STATE_READY;
142 if ( dmac == (struct dma_softc *)q_next )
143 {
144 d_state = AC_DMA_STATE_FREE;
145 }
146 else
147 {
148 dma = (acDmaT)dmac->requestq.q_next;
149 q_next->d_state = 2;
150 }
151 }
152 ret = 0;
153 if ( dma )
154 {
155 int flg;
156 flg = 0;
157 ops = dma->d_ops;
158 if ( d_state == AC_DMA_STATE_QUEUE )
159 {
160 flg = 1;
161 }
162 else
163 {
164 if ( d_state )
165 {
166 if ( d_state != AC_DMA_STATE_READY )
167 {
168 ret = -13;
169 if ( d_state == AC_DMA_STATE_XFER )
170 {
171 ret = 0;
172 flg = 1;
173 }
174 }
175 }
176 else
177 {
178 acQueueT v10;
179 acDmaT state_v5;
180 unsigned int v12;
181
182 v10 = dmac->requestq.q_next;
183 state_v5 = (acDmaT)dmac->requestq.q_prev;
184 dma->d_chain.q_next = &dmac->requestq;
185 v12 = (unsigned int)dmac ^ (unsigned int)v10;
186 ret = v12 == 0;
187 flg = v12 != 0;
188 dma->d_chain.q_prev = (acQueueT)state_v5;
189 state_v5->d_chain.q_next = &dma->d_chain;
190 dmac->requestq.q_prev = &dma->d_chain;
191 }
192 if ( ret < 0 )
193 {
194 flg = 0;
195 }
196 }
197 if ( !flg )
198 {
199 ret = -13;
200 if ( dma == (acDmaT)dmac->requestq.q_next )
201 {
202 if ( !ops->do_xfer )
203 {
204 ret = -14;
205 }
206 else
207 {
208 dma->d_state = 2;
209 CpuResumeIntr(state);
210 ret = ops->do_xfer(dma, intr, dma_xfer);
211 CpuSuspendIntr(&state);
212 if ( dma->d_state == 3 )
213 {
214 ret = 0;
215 }
216 }
217 }
218 flg = 1;
219 }
220 if ( ret < 0 )
221 {
222 flg = 0;
223 }
224 if ( flg )
225 {
226 acUint8 v13;
227
228 v13 = dma->d_state + ret;
229 ret = dma->d_state;
230 dma->d_state = v13;
231 }
232 }
233 CpuResumeIntr(state);
234 if ( ret < 0 )
235 {
236 dma_cancel(dmac, dma, intr, ret);
237 }
238 return ret;
239}
240
241int acDmaRequest(acDmaT dma)
242{
243 int ret;
244
245 ret = dma_request(&Dmac, dma, 0);
246 if ( ret < 0 )
247 {
248 while ( dma_request(&Dmac, 0, 0) < 0 )
249 ;
250 }
251 return ret;
252}
253
254int acDmaRequestI(acDmaT dma)
255{
256 int ret;
257
258 ret = dma_request(&Dmac, dma, 1);
259 if ( ret < 0 )
260 {
261 while ( dma_request(&Dmac, 0, 1) < 0 )
262 ;
263 }
264 return ret;
265}
266
267int acDmaCancel(acDmaT dma, int result)
268{
269 int ret;
270
271 ret = dma_cancel(&Dmac, dma, 0, result);
272 if ( ret >= 0 )
273 {
274 while ( dma_request(&Dmac, 0, 0) < 0 )
275 ;
276 }
277 return ret;
278}
279
280int acDmaCancelI(acDmaT dma, int result)
281{
282 int ret;
283
284 ret = dma_cancel(&Dmac, dma, 1, result);
285 if ( ret >= 0 )
286 {
287 while ( dma_request(&Dmac, 0, 1) < 0 )
288 ;
289 }
290 return ret;
291}
292
293static int dma_intr(void *arg)
294{
295 acDmaData *q_next;
296 acQueueData *v3;
297 acQueueT q_prev;
298 struct dma_softc *argt;
299
300 argt = (struct dma_softc *)arg;
301 if ( argt )
302 {
303 dmac_disable(8u);
304 q_next = (acDmaData *)argt->requestq.q_next;
305 if ( argt != (struct dma_softc *)q_next )
306 {
307 acDmaOpsT ops;
308 acDmaState state;
309
310 v3 = q_next->d_chain.q_next;
311 q_prev = q_next->d_chain.q_prev;
312 ops = q_next->d_ops;
313 state = q_next->d_state;
314 q_prev->q_next = v3;
315 v3->q_prev = q_prev;
316 q_next->d_state = 0;
317 if ( state == AC_DMA_STATE_XFER )
318 ops->do_done(q_next);
319 else
320 ops->do_error(q_next, 1, state, -13);
321 }
322 while ( dma_request(&Dmac, 0, 1) < 0 )
323 ;
324 }
325 return 1;
326}
327
328acDmaT acDmaSetup(acDmaData *dma, acDmaOpsData *ops, int priority, int slice, int output)
329{
330 if ( dma )
331 {
332 acUint32 x;
333 unsigned int v6;
334
335 dma->d_ops = ops;
336 dma->d_attr = (32 * priority) | (output != 0);
337 x = slice / 4;
338 v6 = 0;
339 if ( x > 1 )
340 {
341 v6 = 1;
342 while ( ((unsigned int)1 << v6) < x )
343 {
344 v6 = v6 + 1;
345 }
346 v6 = v6 - 1;
347 }
348 dma->d_slice = v6;
349 dma->d_state = 0;
350 }
351 return dma;
352}
353
354int acDmaModuleStart(int argc, char **argv)
355{
356 int ret;
357 char *msg;
358
359 (void)argc;
360 (void)argv;
361 if ( Dmac.status )
362 {
363 return -16;
364 }
365 Dmac.requestq.q_prev = (acQueueT)&Dmac;
366 Dmac.requestq.q_next = (acQueueT)&Dmac;
367 ret = RegisterIntrHandler(41, 1, dma_intr, &Dmac);
368 if ( !ret || ret == -104 )
369 {
370 ret = EnableIntr(41);
371 if ( !ret )
372 {
373 dmac_disable(8u);
374 Dmac.status = 1;
375 return 0;
376 }
378 msg = "dma_intr_enable";
379 }
380 else
381 {
382 msg = "dma_intr_register";
383 }
384 printf("accore:dma_init:%s: error %d\n", msg, ret);
385 return -6;
386}
387
388int acDmaModuleStop()
389{
390 int dummy;
391
392 if ( Dmac.status )
393 {
394 DisableIntr(41, &dummy);
396 Dmac.status = 0;
397 }
398 return 0;
399}
400
401int acDmaModuleRestart(int argc, char **argv)
402{
403 (void)argc;
404 (void)argv;
405 return -88;
406}
407
408int acDmaModuleStatus()
409{
410 return Dmac.status;
411}
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 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
u32 count
start sector of fragmented bd/file