sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
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 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
131int 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
159void 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
186int 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
217int 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
241int 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
270int 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
299int 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
328int 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
357int 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}
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:241
int dma_channel_receive_normal(int channel, void *data, int data_size, int flags, int spr)
Definition dma.c:328
int dma_channel_wait(int channel, int timeout)
Definition dma.c:131
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:299
void dma_channel_send_packet2(packet2_t *packet2, int channel, u8 flush_cache)
Definition dma.c:159
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:217
int dma_channel_send_chain(int channel, void *data, int qwc, int flags, int spr)
Definition dma.c:186
int dma_channel_send_normal_ucab(int channel, void *data, int qwc, int flags)
Definition dma.c:270
int dma_channel_shutdown(int channel, int flags)
Definition dma.c:357
#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