PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
dma.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# (c) 2005 Naomi Peori <naomi@peori.ca>
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include <tamtypes.h>
12
13#include <dma.h>
14#include <kernel.h>
15#include <stdlib.h>
16#include <string.h>
17
18#include <dma_registers.h>
19
20// Channel Control
21static u32 dma_chcr[10] = { 0x10008000, 0x10009000, 0x1000A000, 0x1000B000, 0x1000B400, 0x1000C000, 0x1000C400, 0x1000C800, 0x1000D000, 0x1000D400 };
22// Quadword Count
23static u32 dma_qwc[10] = { 0x10008020, 0x10009020, 0x1000A020, 0x1000B020, 0x1000B420, 0x1000C020, 0x1000C420, 0x1000C820, 0x1000D020, 0x1000D420 };
24// Memory Address
25static u32 dma_madr[10] = { 0x10008010, 0x10009010, 0x1000A010, 0x1000B010, 0x1000B410, 0x1000C010, 0x1000C410, 0x1000C810, 0x1000D010, 0x1000D410 };
26// Tag Address
27static u32 dma_tadr[10] = { 0x10008030, 0x10009030, 0x1000A030, 0x1000B030, 0x1000B430, 0x1000C030, 0x1000C430, 0x1000C830, 0x1000D030, 0x1000D430 };
28// Tag Address Save 0
29static u32 dma_asr0[10] = { 0x10008040, 0x10009040, 0x1000A040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
30// Tag Address Save 1
31static u32 dma_asr1[10] = { 0x10008050, 0x10009050, 0x1000A050, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
32// SPR Transfer Address
33static u32 dma_sadr[10] = { 0x10008080, 0x10009080, 0x1000A080, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1000D080, 0x1000D480 };
34
35static int dma_handler_id[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
36
37static int dma_channel_initialized[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
38
39
40int dma_reset(void)
41{
42
43 int i;
44
45 for(i = 0; i < 10; i++)
46 {
47
49
50 }
51
52 ResetEE(0x01);
53
54 return 0;
55
56}
57
58int dma_channel_initialize(int channel, void *handler, int flags)
59{
60
61 // Shut down the channel before making changes.
62 if (dma_channel_shutdown(channel, flags) < 0)
63 {
64 return -1;
65 }
66
67 // Clear any saved dmatags
68 if (dma_asr0[channel])
69 {
70 *(vu32 *)dma_asr0[channel] = 0;
71 *(vu32 *)dma_asr1[channel] = 0;
72 }
73
74 // Clear saved spr address
75 if (dma_sadr[channel])
76 {
77 *(vu32 *)dma_sadr[channel] = 0;
78 }
79
80 // If a handler is provided...
81 if (handler != NULL)
82 {
83
84 // Add the handler, storing the handler id.
85 dma_handler_id[channel] = AddDmacHandler(channel, handler, 0);
86
87 // Enable the channel interrupt.
88 if (flags & DMA_FLAG_INTERRUPTSAFE)
89 {
90 iEnableDmac(channel);
91 }
92 else
93 {
94 EnableDmac(channel);
95 }
96
97 }
98
99 // Tell everyone we are initialized.
100 dma_channel_initialized[channel] = 1;
101
102 // End function.
103 return 0;
104
105}
106
107// allows for cpcond0 checking
108void dma_channel_fast_waits(int channel)
109{
110
111 *DMA_REG_PCR |= 1 << channel;
112
113}
114
116{
117
118 asm volatile (
119 "sync.l; sync.p;" \
120 "0:" \
121 "bc0t 0f; nop;" \
122 "bc0t 0f; nop;" \
123 "bc0t 0f; nop;" \
124 "bc0f 0b; nop;" \
125 "0:"
126 );
127
128}
129
130int dma_channel_wait(int channel, int timeout)
131{
132
133 // While the channel is not ready...
134 while (*((vu32 *)dma_chcr[channel]) & 0x00000100)
135 {
136
137 // Decrement the timeout counter, exiting if it expires.
138 if (timeout > 0)
139 {
140
141 timeout -= 1;
142 if (timeout == 0)
143 {
144
145 return -1;
146
147 };
148
149 }
150
151 }
152
153 // End function.
154 return 0;
155
156}
157
158void dma_channel_send_packet2(packet2_t *packet2, int channel, u8 flush_cache)
159{
160 // dma_channel_send_chain does NOT flush all data that is "source chained"
161 if (packet2->mode == P2_MODE_CHAIN)
162 {
163 // "dma_channel_send_normal always flushes the data cache"
164 if (flush_cache)
165 FlushCache(0);
167 channel,
168 (void *)((u32)packet2->base & 0x0FFFFFFF),
169 0,
170 packet2->tte ? DMA_FLAG_TRANSFERTAG : 0,
171 0);
172 }
173 else
174 {
176 channel,
177 (void *)((u32)packet2->base & 0x0FFFFFFF), // make ptr normal
178 ((u32)packet2->next - (u32)packet2->base) >> 4, // length in qwords
179 0,
180 0);
181 }
182}
183
184
185int dma_channel_send_chain(int channel, void *data, int data_size, int flags, int spr)
186{
187
188 // clear channel status
189 *DMA_REG_STAT = DMA_SET_STAT(1 << channel,0,0,0,0,0,0);
190
191 if (flags & DMA_FLAG_INTERRUPTSAFE)
192 {
193 iSyncDCache(data, (void *)((u8 *)data + (data_size<<4)));
194 }
195 else
196 {
197 SyncDCache(data, (void *)((u8 *)data + (data_size<<4)));
198 }
199
200 // Set the size of the data, in quadwords.
201 *(vu32 *)dma_qwc[channel] = DMA_SET_QWC(0);
202
203 // Set the address of the data.
204 *(vu32 *)dma_madr[channel] = DMA_SET_MADR(0, 0);
205
206 // Set the address of the data tag.
207 *(vu32 *)dma_tadr[channel] = DMA_SET_TADR((u32)data, spr);
208
209 // Start the transfer.
210 *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(1, 1, 0, flags & DMA_FLAG_TRANSFERTAG, 1, 1, 0);
211
212 return 0;
213
214}
215
216int dma_channel_send_chain_ucab(int channel, void *data, int qwc, int flags)
217{
218 (void)qwc;
219
220 // clear channel status
221 *DMA_REG_STAT = 1 << channel;
222
223 // Set the size of the data, in quadwords.
224 *(vu32 *)dma_qwc[channel] = DMA_SET_QWC(0);
225
226 // Set the address of the data.
227 *(vu32 *)dma_madr[channel] = DMA_SET_MADR(0, 0);
228
229 // Set the address of the data tag.
230 *(vu32 *)dma_tadr[channel] = DMA_SET_TADR((u32)data - 0x30000000, 0);
231
232 // Start the transfer.
233 *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(1, 1, 0, flags & DMA_FLAG_TRANSFERTAG, 1, 1, 0);
234
235 // End function.
236 return 0;
237
238}
239
240int dma_channel_send_normal(int channel, void *data, int qwc, int flags, int spr)
241{
242
243 // clear channel status
244 *DMA_REG_STAT = DMA_SET_STAT(1 << channel,0,0,0,0,0,0);
245
246 // Not sure if this should be here.
247 if (flags & DMA_FLAG_INTERRUPTSAFE)
248 {
249 iSyncDCache(data, (void *)((u8 *)data + (qwc<<4)));
250 }
251 else
252 {
253 SyncDCache(data, (void *)((u8 *)data + (qwc<<4)));
254 }
255
256 // Set the size of the data, in quadwords.
257 *(vu32 *)dma_qwc[channel] = DMA_SET_QWC(qwc);
258
259 // Set the address of the data.
260 *(vu32 *)dma_madr[channel] = DMA_SET_MADR((u32)data, spr);
261
262 // Start the transfer.
263 *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(1, 0, 0, flags & DMA_FLAG_TRANSFERTAG, 1, 1, 0);
264
265 return 0;
266
267}
268
269int dma_channel_send_normal_ucab(int channel, void *data, int qwc, int flags)
270{
271
272 // clear channel status
273 *DMA_REG_STAT = DMA_SET_STAT(1 << channel,0,0,0,0,0,0);
274
275 // Not sure if this should be here.
276 if (flags & DMA_FLAG_INTERRUPTSAFE)
277 {
278 iSyncDCache(data, (void *)((u8 *)data + (qwc<<4)));
279 }
280 else
281 {
282 SyncDCache(data, (void *)((u8 *)data + (qwc<<4)));
283 }
284
285 // Set the size of the data, in quadwords.
286 *(vu32 *)dma_qwc[channel] = DMA_SET_QWC(qwc);
287
288 // Set the address of the data.
289 *(vu32 *)dma_madr[channel] = DMA_SET_MADR((u32)data - 0x30000000, 0);
290
291 // Start the transfer.
292 *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(1, 0, 0, flags & DMA_FLAG_TRANSFERTAG, 1, 1, 0);
293
294 return 0;
295
296}
297
298int dma_channel_receive_chain(int channel, void *data, int data_size, int flags, int spr)
299{
300
301 // If we are not initialized...
302 if (dma_channel_initialized[channel] < 0)
303 {
304
305 // Initialize the channel.
306 if (dma_channel_initialize(channel, NULL, flags) < 0)
307 {
308 return -1;
309 }
310
311 }
312
313 // Set the size of the data, in quadwords.
314 *(vu32 *)dma_qwc[channel] = DMA_SET_QWC((data_size + 15) >> 4);
315
316 // Set the address of the data.
317 *(vu32 *)dma_madr[channel] = DMA_SET_MADR((u32)data, spr);
318
319 // Start the transfer.
320 *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(0, 1, 0, 0, 0, 1, 0);
321
322 // End function.
323 return 0;
324
325}
326
327int dma_channel_receive_normal(int channel, void *data, int data_size, int flags, int spr)
328{
329
330 // If we are not initialized...
331 if (dma_channel_initialized[channel] < 0)
332 {
333
334 // Initialize the channel.
335 if (dma_channel_initialize(channel, NULL, flags) < 0)
336 {
337 return -1;
338 }
339
340 }
341
342 // Set the size of the data, in quadwords.
343 *(vu32 *)dma_qwc[channel] = DMA_SET_QWC((data_size + 15) >> 4);
344
345 // Set the address of the data.
346 *(vu32 *)dma_madr[channel] = DMA_SET_MADR((u32)data, spr);
347
348 // Start the transfer.
349 *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(0, 0, 0, 0, 0, 1, 0);
350
351 // End function.
352 return 0;
353
354}
355
356int dma_channel_shutdown(int channel, int flags)
357{
358
359 // If we are not initialized, no need to shut down.
360 if (dma_channel_initialized[channel] < 0)
361 {
362 return 0;
363 }
364
365 // If a handler was provided...
366 if (dma_handler_id[channel] != 0)
367 {
368
369 // Disable the channel.
370 if (flags & DMA_FLAG_INTERRUPTSAFE)
371 {
372 iDisableDmac(channel);
373 }
374 else
375 {
376 DisableDmac(channel);
377 }
378
379 // Remove the handler.
380 RemoveDmacHandler(channel, dma_handler_id[channel]);
381
382 // Clear the handler id.
383 dma_handler_id[channel] = 0;
384
385 }
386
387 // Tell everyone we are not initialized.
388 dma_channel_initialized[channel] = 0;
389
390 // End function.
391 return 0;
392
393}
void dma_wait_fast(void)
Definition dma.c:115
int dma_channel_send_normal(int channel, void *data, int qwc, int flags, int spr)
Definition dma.c:240
int dma_channel_receive_normal(int channel, void *data, int data_size, int flags, int spr)
Definition dma.c:327
int dma_channel_wait(int channel, int timeout)
Definition dma.c:130
int dma_channel_initialize(int channel, void *handler, int flags)
Definition dma.c:58
int dma_channel_receive_chain(int channel, void *data, int data_size, int flags, int spr)
Definition dma.c:298
void dma_channel_send_packet2(packet2_t *packet2, int channel, u8 flush_cache)
Definition dma.c:158
void dma_channel_fast_waits(int channel)
Definition dma.c:108
int dma_channel_send_chain_ucab(int channel, void *data, int qwc, int flags)
Definition dma.c:216
int dma_channel_send_chain(int channel, void *data, int qwc, int flags, int spr)
Definition dma.c:185
int dma_channel_send_normal_ucab(int channel, void *data, int qwc, int flags)
Definition dma.c:269
int dma_channel_shutdown(int channel, int flags)
Definition dma.c:356
#define DMA_REG_PCR
#define DMA_SET_CHCR(DIR, MODE, ASP, TTE, TIE, STR, TAG)
#define DMA_REG_STAT
enum Packet2Mode mode
qword_t * next