PS2SDK
PS2 Homebrew Libraries
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
21 static u32 dma_chcr[10] = { 0x10008000, 0x10009000, 0x1000A000, 0x1000B000, 0x1000B400, 0x1000C000, 0x1000C400, 0x1000C800, 0x1000D000, 0x1000D400 };
22 // Quadword Count
23 static u32 dma_qwc[10] = { 0x10008020, 0x10009020, 0x1000A020, 0x1000B020, 0x1000B420, 0x1000C020, 0x1000C420, 0x1000C820, 0x1000D020, 0x1000D420 };
24 // Memory Address
25 static u32 dma_madr[10] = { 0x10008010, 0x10009010, 0x1000A010, 0x1000B010, 0x1000B410, 0x1000C010, 0x1000C410, 0x1000C810, 0x1000D010, 0x1000D410 };
26 // Tag Address
27 static u32 dma_tadr[10] = { 0x10008030, 0x10009030, 0x1000A030, 0x1000B030, 0x1000B430, 0x1000C030, 0x1000C430, 0x1000C830, 0x1000D030, 0x1000D430 };
28 // Tag Address Save 0
29 static u32 dma_asr0[10] = { 0x10008040, 0x10009040, 0x1000A040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
30 // Tag Address Save 1
31 static u32 dma_asr1[10] = { 0x10008050, 0x10009050, 0x1000A050, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
32 // SPR Transfer Address
33 static u32 dma_sadr[10] = { 0x10008080, 0x10009080, 0x1000A080, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1000D080, 0x1000D480 };
34 
35 static int dma_handler_id[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
36 
37 static int dma_channel_initialized[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
38 
39 
40 int 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 
58 int 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
108 void dma_channel_fast_waits(int channel)
109 {
110 
111  *DMA_REG_PCR |= 1 << channel;
112 
113 }
114 
115 void dma_wait_fast(void)
116 {
117 
118  EE_SYNCL();
119  EE_SYNCP();
120  __asm__ __volatile__ (
121  "0:" \
122  "bc0t 0f; nop;" \
123  "bc0t 0f; nop;" \
124  "bc0t 0f; nop;" \
125  "bc0f 0b; nop;" \
126  "0:"
127  );
128 
129 }
130 
131 int dma_channel_wait(int channel, int timeout)
132 {
133 
134  // While the channel is not ready...
135  while (*((vu32 *)dma_chcr[channel]) & 0x00000100)
136  {
137 
138  // Decrement the timeout counter, exiting if it expires.
139  if (timeout > 0)
140  {
141 
142  timeout -= 1;
143  if (timeout == 0)
144  {
145 
146  return -1;
147 
148  };
149 
150  }
151 
152  }
153 
154  // End function.
155  return 0;
156 
157 }
158 
159 void dma_channel_send_packet2(packet2_t *packet2, int channel, u8 flush_cache)
160 {
161  // dma_channel_send_chain does NOT flush all data that is "source chained"
162  if (packet2->mode == P2_MODE_CHAIN)
163  {
164  // "dma_channel_send_normal always flushes the data cache"
165  if (flush_cache)
166  FlushCache(0);
168  channel,
169  (void *)((u32)packet2->base & 0x0FFFFFFF),
170  0,
171  packet2->tte ? DMA_FLAG_TRANSFERTAG : 0,
172  0);
173  }
174  else
175  {
177  channel,
178  (void *)((u32)packet2->base & 0x0FFFFFFF), // make ptr normal
179  ((u32)packet2->next - (u32)packet2->base) >> 4, // length in qwords
180  0,
181  0);
182  }
183 }
184 
185 
186 int dma_channel_send_chain(int channel, void *data, int data_size, int flags, int spr)
187 {
188 
189  // clear channel status
190  *DMA_REG_STAT = DMA_SET_STAT(1 << channel,0,0,0,0,0,0);
191 
192  if (flags & DMA_FLAG_INTERRUPTSAFE)
193  {
194  iSyncDCache(data, (void *)((u8 *)data + (data_size<<4)));
195  }
196  else
197  {
198  SyncDCache(data, (void *)((u8 *)data + (data_size<<4)));
199  }
200 
201  // Set the size of the data, in quadwords.
202  *(vu32 *)dma_qwc[channel] = DMA_SET_QWC(0);
203 
204  // Set the address of the data.
205  *(vu32 *)dma_madr[channel] = DMA_SET_MADR(0, 0);
206 
207  // Set the address of the data tag.
208  *(vu32 *)dma_tadr[channel] = DMA_SET_TADR((u32)data, spr);
209 
210  // Start the transfer.
211  *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(1, 1, 0, flags & DMA_FLAG_TRANSFERTAG, 1, 1, 0);
212 
213  return 0;
214 
215 }
216 
217 int dma_channel_send_chain_ucab(int channel, void *data, int qwc, int flags)
218 {
219  (void)qwc;
220 
221  // clear channel status
222  *DMA_REG_STAT = 1 << channel;
223 
224  // Set the size of the data, in quadwords.
225  *(vu32 *)dma_qwc[channel] = DMA_SET_QWC(0);
226 
227  // Set the address of the data.
228  *(vu32 *)dma_madr[channel] = DMA_SET_MADR(0, 0);
229 
230  // Set the address of the data tag.
231  *(vu32 *)dma_tadr[channel] = DMA_SET_TADR((u32)data - 0x30000000, 0);
232 
233  // Start the transfer.
234  *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(1, 1, 0, flags & DMA_FLAG_TRANSFERTAG, 1, 1, 0);
235 
236  // End function.
237  return 0;
238 
239 }
240 
241 int dma_channel_send_normal(int channel, void *data, int qwc, int flags, int spr)
242 {
243 
244  // clear channel status
245  *DMA_REG_STAT = DMA_SET_STAT(1 << channel,0,0,0,0,0,0);
246 
247  // Not sure if this should be here.
248  if (flags & DMA_FLAG_INTERRUPTSAFE)
249  {
250  iSyncDCache(data, (void *)((u8 *)data + (qwc<<4)));
251  }
252  else
253  {
254  SyncDCache(data, (void *)((u8 *)data + (qwc<<4)));
255  }
256 
257  // Set the size of the data, in quadwords.
258  *(vu32 *)dma_qwc[channel] = DMA_SET_QWC(qwc);
259 
260  // Set the address of the data.
261  *(vu32 *)dma_madr[channel] = DMA_SET_MADR((u32)data, spr);
262 
263  // Start the transfer.
264  *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(1, 0, 0, flags & DMA_FLAG_TRANSFERTAG, 1, 1, 0);
265 
266  return 0;
267 
268 }
269 
270 int dma_channel_send_normal_ucab(int channel, void *data, int qwc, int flags)
271 {
272 
273  // clear channel status
274  *DMA_REG_STAT = DMA_SET_STAT(1 << channel,0,0,0,0,0,0);
275 
276  // Not sure if this should be here.
277  if (flags & DMA_FLAG_INTERRUPTSAFE)
278  {
279  iSyncDCache(data, (void *)((u8 *)data + (qwc<<4)));
280  }
281  else
282  {
283  SyncDCache(data, (void *)((u8 *)data + (qwc<<4)));
284  }
285 
286  // Set the size of the data, in quadwords.
287  *(vu32 *)dma_qwc[channel] = DMA_SET_QWC(qwc);
288 
289  // Set the address of the data.
290  *(vu32 *)dma_madr[channel] = DMA_SET_MADR((u32)data - 0x30000000, 0);
291 
292  // Start the transfer.
293  *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(1, 0, 0, flags & DMA_FLAG_TRANSFERTAG, 1, 1, 0);
294 
295  return 0;
296 
297 }
298 
299 int dma_channel_receive_chain(int channel, void *data, int data_size, int flags, int spr)
300 {
301 
302  // If we are not initialized...
303  if (dma_channel_initialized[channel] < 0)
304  {
305 
306  // Initialize the channel.
307  if (dma_channel_initialize(channel, NULL, flags) < 0)
308  {
309  return -1;
310  }
311 
312  }
313 
314  // Set the size of the data, in quadwords.
315  *(vu32 *)dma_qwc[channel] = DMA_SET_QWC((data_size + 15) >> 4);
316 
317  // Set the address of the data.
318  *(vu32 *)dma_madr[channel] = DMA_SET_MADR((u32)data, spr);
319 
320  // Start the transfer.
321  *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(0, 1, 0, 0, 0, 1, 0);
322 
323  // End function.
324  return 0;
325 
326 }
327 
328 int dma_channel_receive_normal(int channel, void *data, int data_size, int flags, int spr)
329 {
330 
331  // If we are not initialized...
332  if (dma_channel_initialized[channel] < 0)
333  {
334 
335  // Initialize the channel.
336  if (dma_channel_initialize(channel, NULL, flags) < 0)
337  {
338  return -1;
339  }
340 
341  }
342 
343  // Set the size of the data, in quadwords.
344  *(vu32 *)dma_qwc[channel] = DMA_SET_QWC((data_size + 15) >> 4);
345 
346  // Set the address of the data.
347  *(vu32 *)dma_madr[channel] = DMA_SET_MADR((u32)data, spr);
348 
349  // Start the transfer.
350  *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(0, 0, 0, 0, 0, 1, 0);
351 
352  // End function.
353  return 0;
354 
355 }
356 
357 int dma_channel_shutdown(int channel, int flags)
358 {
359 
360  // If we are not initialized, no need to shut down.
361  if (dma_channel_initialized[channel] < 0)
362  {
363  return 0;
364  }
365 
366  // If a handler was provided...
367  if (dma_handler_id[channel] != 0)
368  {
369 
370  // Disable the channel.
371  if (flags & DMA_FLAG_INTERRUPTSAFE)
372  {
373  iDisableDmac(channel);
374  }
375  else
376  {
377  DisableDmac(channel);
378  }
379 
380  // Remove the handler.
381  RemoveDmacHandler(channel, dma_handler_id[channel]);
382 
383  // Clear the handler id.
384  dma_handler_id[channel] = 0;
385 
386  }
387 
388  // Tell everyone we are not initialized.
389  dma_channel_initialized[channel] = 0;
390 
391  // End function.
392  return 0;
393 
394 }
kernel.h
packet2_t::mode
enum Packet2Mode mode
Definition: packet2_types.h:307
dma_channel_shutdown
int dma_channel_shutdown(int channel, int flags)
Definition: dma.c:357
packet2_t::tte
u8 tte
Definition: packet2_types.h:315
dma_channel_send_normal
int dma_channel_send_normal(int channel, void *data, int qwc, int flags, int spr)
Definition: dma.c:241
dma_channel_send_chain
int dma_channel_send_chain(int channel, void *data, int qwc, int flags, int spr)
Definition: dma.c:186
dma_channel_fast_waits
void dma_channel_fast_waits(int channel)
Definition: dma.c:108
DMA_REG_STAT
#define DMA_REG_STAT
Definition: dma_registers.h:24
dma_channel_send_packet2
void dma_channel_send_packet2(packet2_t *packet2, int channel, u8 flush_cache)
Definition: dma.c:159
dma_channel_send_chain_ucab
int dma_channel_send_chain_ucab(int channel, void *data, int qwc, int flags)
Definition: dma.c:217
packet2_t
Definition: packet2_types.h:300
dma_channel_receive_normal
int dma_channel_receive_normal(int channel, void *data, int data_size, int flags, int spr)
Definition: dma.c:328
DMA_SET_CHCR
#define DMA_SET_CHCR(DIR, MODE, ASP, TTE, TIE, STR, TAG)
Definition: dma_registers.h:103
packet2_t::next
qword_t * next
Definition: packet2_types.h:319
dma_wait_fast
void dma_wait_fast(void)
Definition: dma.c:115
tamtypes.h
dma_registers.h
DMA_REG_PCR
#define DMA_REG_PCR
Definition: dma_registers.h:26
dma_channel_wait
int dma_channel_wait(int channel, int timeout)
Definition: dma.c:131
stdlib.h
dma_channel_receive_chain
int dma_channel_receive_chain(int channel, void *data, int data_size, int flags, int spr)
Definition: dma.c:299
dma_channel_send_normal_ucab
int dma_channel_send_normal_ucab(int channel, void *data, int qwc, int flags)
Definition: dma.c:270
dma_channel_initialize
int dma_channel_initialize(int channel, void *handler, int flags)
Definition: dma.c:58
dma.h