ps2sdk  1.1
A collection of Open Source libraries used for developing applications on Sony's PlayStation 2® (PS2).
dma.c
Go to the documentation of this file.
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 <malloc.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  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 
130 int 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  if (timeout-- == 0)
142  {
143 
144  return -1;
145 
146  };
147 
148  }
149 
150  }
151 
152  // End function.
153  return 0;
154 
155 }
156 
157 void dma_channel_send_packet2(packet2_t *packet2, int channel, u8 flush_cache)
158 {
159  // dma_channel_send_chain does NOT flush all data that is "source chained"
160  if (packet2->mode == P2_MODE_CHAIN)
161  {
162  // "dma_channel_send_normal always flushes the data cache"
163  if (flush_cache)
164  FlushCache(0);
166  channel,
167  (void *)((u32)packet2->base & 0x0FFFFFFF),
168  0,
169  packet2->tte ? DMA_FLAG_TRANSFERTAG : 0,
170  0);
171  }
172  else
173  {
175  channel,
176  (void *)((u32)packet2->base & 0x0FFFFFFF), // make ptr normal
177  ((u32)packet2->next - (u32)packet2->base) >> 4, // length in qwords
178  0,
179  0);
180  }
181 }
182 
183 
184 int dma_channel_send_chain(int channel, void *data, int data_size, int flags, int spr)
185 {
186 
187  // clear channel status
188  *DMA_REG_STAT = DMA_SET_STAT(1 << channel,0,0,0,0,0,0);
189 
190  if (flags & DMA_FLAG_INTERRUPTSAFE)
191  {
192  iSyncDCache(data, data + (data_size<<4));
193  }
194  else
195  {
196  SyncDCache(data, data + (data_size<<4));
197  }
198 
199  // Set the size of the data, in quadwords.
200  *(vu32 *)dma_qwc[channel] = DMA_SET_QWC(0);
201 
202  // Set the address of the data.
203  *(vu32 *)dma_madr[channel] = DMA_SET_MADR(0, 0);
204 
205  // Set the address of the data tag.
206  *(vu32 *)dma_tadr[channel] = DMA_SET_TADR((u32)data, spr);
207 
208  // Start the transfer.
209  *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(1, 1, 0, flags & DMA_FLAG_TRANSFERTAG, 1, 1, 0);
210 
211  return 0;
212 
213 }
214 
215 int dma_channel_send_chain_ucab(int channel, void *data, int qwc, int flags)
216 {
217 
218  // clear channel status
219  *DMA_REG_STAT = 1 << channel;
220 
221  // Set the size of the data, in quadwords.
222  *(vu32 *)dma_qwc[channel] = DMA_SET_QWC(0);
223 
224  // Set the address of the data.
225  *(vu32 *)dma_madr[channel] = DMA_SET_MADR(0, 0);
226 
227  // Set the address of the data tag.
228  *(vu32 *)dma_tadr[channel] = DMA_SET_TADR((u32)data - 0x30000000, 0);
229 
230  // Start the transfer.
231  *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(1, 1, 0, flags & DMA_FLAG_TRANSFERTAG, 1, 1, 0);
232 
233  // End function.
234  return 0;
235 
236 }
237 
238 int dma_channel_send_normal(int channel, void *data, int qwc, int flags, int spr)
239 {
240 
241  // clear channel status
242  *DMA_REG_STAT = DMA_SET_STAT(1 << channel,0,0,0,0,0,0);
243 
244  // Not sure if this should be here.
245  if (flags & DMA_FLAG_INTERRUPTSAFE)
246  {
247  iSyncDCache(data, data + (qwc<<4));
248  }
249  else
250  {
251  SyncDCache(data, data + (qwc<<4));
252  }
253 
254  // Set the size of the data, in quadwords.
255  *(vu32 *)dma_qwc[channel] = DMA_SET_QWC(qwc);
256 
257  // Set the address of the data.
258  *(vu32 *)dma_madr[channel] = DMA_SET_MADR((u32)data, spr);
259 
260  // Start the transfer.
261  *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(1, 0, 0, flags & DMA_FLAG_TRANSFERTAG, 1, 1, 0);
262 
263  return 0;
264 
265 }
266 
267 int dma_channel_send_normal_ucab(int channel, void *data, int qwc, int flags)
268 {
269 
270  // clear channel status
271  *DMA_REG_STAT = DMA_SET_STAT(1 << channel,0,0,0,0,0,0);
272 
273  // Not sure if this should be here.
274  if (flags & DMA_FLAG_INTERRUPTSAFE)
275  {
276  iSyncDCache(data, data + (qwc<<4));
277  }
278  else
279  {
280  SyncDCache(data, data + (qwc<<4));
281  }
282 
283  // Set the size of the data, in quadwords.
284  *(vu32 *)dma_qwc[channel] = DMA_SET_QWC(qwc);
285 
286  // Set the address of the data.
287  *(vu32 *)dma_madr[channel] = DMA_SET_MADR((u32)data - 0x30000000, 0);
288 
289  // Start the transfer.
290  *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(1, 0, 0, flags & DMA_FLAG_TRANSFERTAG, 1, 1, 0);
291 
292  return 0;
293 
294 }
295 
296 int dma_channel_receive_chain(int channel, void *data, int data_size, int flags, int spr)
297 {
298 
299  // If we are not initialized...
300  if (dma_channel_initialized[channel] < 0)
301  {
302 
303  // Initialize the channel.
304  if (dma_channel_initialize(channel, NULL, flags) < 0)
305  {
306  return -1;
307  }
308 
309  }
310 
311  // Set the size of the data, in quadwords.
312  *(vu32 *)dma_qwc[channel] = DMA_SET_QWC((data_size + 15) >> 4);
313 
314  // Set the address of the data.
315  *(vu32 *)dma_madr[channel] = DMA_SET_MADR((u32)data, spr);
316 
317  // Start the transfer.
318  *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(0, 1, 0, 0, 0, 1, 0);
319 
320  // End function.
321  return 0;
322 
323 }
324 
325 int dma_channel_receive_normal(int channel, void *data, int data_size, int flags, int spr)
326 {
327 
328  // If we are not initialized...
329  if (dma_channel_initialized[channel] < 0)
330  {
331 
332  // Initialize the channel.
333  if (dma_channel_initialize(channel, NULL, flags) < 0)
334  {
335  return -1;
336  }
337 
338  }
339 
340  // Set the size of the data, in quadwords.
341  *(vu32 *)dma_qwc[channel] = DMA_SET_QWC((data_size + 15) >> 4);
342 
343  // Set the address of the data.
344  *(vu32 *)dma_madr[channel] = DMA_SET_MADR((u32)data, spr);
345 
346  // Start the transfer.
347  *(vu32 *)dma_chcr[channel] = DMA_SET_CHCR(0, 0, 0, 0, 0, 1, 0);
348 
349  // End function.
350  return 0;
351 
352 }
353 
354 int dma_channel_shutdown(int channel, int flags)
355 {
356 
357  // If we are not initialized, no need to shut down.
358  if (dma_channel_initialized[channel] < 0)
359  {
360  return 0;
361  }
362 
363  // If a handler was provided...
364  if (dma_handler_id[channel] != 0)
365  {
366 
367  // Disable the channel.
368  if (flags & DMA_FLAG_INTERRUPTSAFE)
369  {
370  iDisableDmac(channel);
371  }
372  else
373  {
374  DisableDmac(channel);
375  }
376 
377  // Remove the handler.
378  RemoveDmacHandler(channel, dma_handler_id[channel]);
379 
380  // Clear the handler id.
381  dma_handler_id[channel] = 0;
382 
383  }
384 
385  // Tell everyone we are not initialized.
386  dma_channel_initialized[channel] = 0;
387 
388  // End function.
389  return 0;
390 
391 }
static u32 dma_chcr[10]
Definition: dma.c:21
static int dma_channel_initialized[10]
Definition: dma.c:37
void dma_wait_fast(void)
Definition: dma.c:115
static int dma_handler_id[10]
Definition: dma.c:35
int dma_channel_send_normal(int channel, void *data, int qwc, int flags, int spr)
Definition: dma.c:238
int dma_channel_receive_normal(int channel, void *data, int data_size, int flags, int spr)
Definition: dma.c:325
int dma_channel_wait(int channel, int timeout)
Definition: dma.c:130
static u32 dma_asr0[10]
Definition: dma.c:29
int dma_channel_send_chain(int channel, void *data, int data_size, int flags, int spr)
Definition: dma.c:184
int dma_channel_initialize(int channel, void *handler, int flags)
Definition: dma.c:58
static u32 dma_qwc[10]
Definition: dma.c:23
int dma_channel_receive_chain(int channel, void *data, int data_size, int flags, int spr)
Definition: dma.c:296
void dma_channel_send_packet2(packet2_t *packet2, int channel, u8 flush_cache)
Definition: dma.c:157
static u32 dma_sadr[10]
Definition: dma.c:33
static u32 dma_tadr[10]
Definition: dma.c:27
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:215
int dma_channel_send_normal_ucab(int channel, void *data, int qwc, int flags)
Definition: dma.c:267
int dma_reset(void)
Definition: dma.c:40
static u32 dma_madr[10]
Definition: dma.c:25
int dma_channel_shutdown(int channel, int flags)
Definition: dma.c:354
static u32 dma_asr1[10]
Definition: dma.c:31
#define DMA_FLAG_TRANSFERTAG
Definition: dma.h:33
#define DMA_FLAG_INTERRUPTSAFE
Definition: dma.h:34
#define DMA_REG_PCR
Definition: dma_registers.h:26
#define DMA_SET_MADR(ADDR, SPR)
#define DMA_SET_CHCR(DIR, MODE, ASP, TTE, TIE, STR, TAG)
#define DMA_SET_QWC(QWC)
#define DMA_SET_STAT(CIS, SIS, MEIS, BEIS, CIM, SIM, MEIM)
Definition: dma_registers.h:79
#define DMA_REG_STAT
Definition: dma_registers.h:24
#define DMA_SET_TADR(ADDR, SPR)
@ P2_MODE_CHAIN
Definition: packet2_types.h:34
int DisableDmac(int dmac)
int iDisableDmac(int dmac)
void SyncDCache(void *start, void *end)
void ResetEE(u32 init_bitfield)
s32 AddDmacHandler(s32 channel, s32(*handler)(s32 channel), s32 next)
s32 RemoveDmacHandler(s32 channel, s32 handler_id)
void FlushCache(s32 operation)
void iSyncDCache(void *start, void *end)
int EnableDmac(int dmac)
int iEnableDmac(int dmac)
u32 data
Definition: libmouse.c:36
enum Packet2Mode mode
qword_t * base
qword_t * next
#define NULL
Definition: tamtypes.h:91
unsigned int u32
Definition: tamtypes.h:30
volatile u32 vu32
Definition: tamtypes.h:38
unsigned char u8
Definition: tamtypes.h:23