1 // license:BSD-3-Clause
2 // copyright-holders:Ville Linde
3 /* SHARC DMA operations */
4
5 #define DMA_PMODE_NO_PACKING 0
6 #define DMA_PMODE_16_32 1
7 #define DMA_PMODE_16_48 2
8 #define DMA_PMODE_32_48 3
9 #define DMA_PMODE_8_48 4
10
schedule_chained_dma_op(int channel,uint32_t dma_chain_ptr,int chained_direction)11 void adsp21062_device::schedule_chained_dma_op(int channel, uint32_t dma_chain_ptr, int chained_direction)
12 {
13 uint32_t op_ptr = 0x20000 + dma_chain_ptr;
14
15 uint32_t int_index = dm_read32(op_ptr - 0);
16 uint32_t int_modifier = dm_read32(op_ptr - 1);
17 uint32_t int_count = dm_read32(op_ptr - 2);
18 uint32_t chain_ptr = dm_read32(op_ptr - 3);
19 //uint32_t gen_purpose = dm_read32(op_ptr - 4);
20 uint32_t ext_index = dm_read32(op_ptr - 5);
21 uint32_t ext_modifier = dm_read32(op_ptr - 6);
22 uint32_t ext_count = dm_read32(op_ptr - 7);
23
24 if (m_core->dma_op[channel].active)
25 {
26 fatalerror("schedule_chained_dma_op: DMA operation already scheduled at %08X!\n", m_core->pc);
27 }
28
29 if (chained_direction) // Transmit to external
30 {
31 m_core->dma_op[channel].dst = ext_index;
32 m_core->dma_op[channel].dst_modifier = ext_modifier;
33 m_core->dma_op[channel].dst_count = ext_count;
34 m_core->dma_op[channel].src = int_index;
35 m_core->dma_op[channel].src_modifier = int_modifier;
36 m_core->dma_op[channel].src_count = int_count;
37 }
38 else // Receive from external
39 {
40 m_core->dma_op[channel].src = ext_index;
41 m_core->dma_op[channel].src_modifier = ext_modifier;
42 m_core->dma_op[channel].src_count = ext_count;
43 m_core->dma_op[channel].dst = int_index;
44 m_core->dma_op[channel].dst_modifier = int_modifier;
45 m_core->dma_op[channel].dst_count = int_count;
46 }
47
48 m_core->dma_op[channel].pmode = 0;
49 m_core->dma_op[channel].chain_ptr = chain_ptr;
50 m_core->dma_op[channel].chained_direction = chained_direction;
51
52 m_core->dma_op[channel].active = true;
53
54 int cycles = m_core->dma_op[channel].src_count / 4;
55 m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel);
56
57 // enable busy flag
58 m_core->dma_status |= (1 << channel);
59 }
60
schedule_dma_op(int channel,uint32_t src,uint32_t dst,int src_modifier,int dst_modifier,int src_count,int dst_count,int pmode)61 void adsp21062_device::schedule_dma_op(int channel, uint32_t src, uint32_t dst, int src_modifier, int dst_modifier, int src_count, int dst_count, int pmode)
62 {
63 if (m_core->dma_op[channel].active)
64 {
65 fatalerror("schedule_dma_op: DMA operation already scheduled at %08X!\n", m_core->pc);
66 }
67
68 m_core->dma_op[channel].src = src;
69 m_core->dma_op[channel].dst = dst;
70 m_core->dma_op[channel].src_modifier = src_modifier;
71 m_core->dma_op[channel].dst_modifier = dst_modifier;
72 m_core->dma_op[channel].src_count = src_count;
73 m_core->dma_op[channel].dst_count = dst_count;
74 m_core->dma_op[channel].pmode = pmode;
75 m_core->dma_op[channel].chain_ptr = 0;
76
77 m_core->dma_op[channel].active = true;
78
79 int cycles = src_count / 4;
80 m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel);
81
82 // enable busy flag
83 m_core->dma_status |= (1 << channel);
84 }
85
dma_op(int channel)86 void adsp21062_device::dma_op(int channel)
87 {
88 int i;
89 uint32_t src = m_core->dma_op[channel].src;
90 uint32_t dst = m_core->dma_op[channel].dst;
91 int src_modifier = m_core->dma_op[channel].src_modifier;
92 int dst_modifier = m_core->dma_op[channel].dst_modifier;
93 int src_count = m_core->dma_op[channel].src_count;
94 //int dst_count = m_core->dma_op[channel].dst_count;
95 int pmode = m_core->dma_op[channel].pmode;
96
97 //printf("dma_op: %08X, %08X, %08X, %08X, %08X, %d\n", src, dst, src_modifier, dst_modifier, src_count, pmode);
98
99 switch (pmode)
100 {
101 case DMA_PMODE_NO_PACKING:
102 {
103 for (i=0; i < src_count; i++)
104 {
105 uint32_t data = dm_read32(src);
106 dm_write32(dst, data);
107 src += src_modifier;
108 dst += dst_modifier;
109 }
110 break;
111 }
112 case DMA_PMODE_16_32:
113 {
114 int length = src_count/2;
115 for (i=0; i < length; i++)
116 {
117 uint32_t data = ((dm_read32(src+0) & 0xffff) << 16) | (dm_read32(src+1) & 0xffff);
118
119 dm_write32(dst, data);
120 src += src_modifier * 2;
121 dst += dst_modifier;
122 }
123 break;
124 }
125 case DMA_PMODE_8_48:
126 {
127 int length = src_count/6;
128 for (i=0; i < length; i++)
129 {
130 uint64_t data = ((uint64_t)(dm_read32(src+0) & 0xff) << 0) |
131 ((uint64_t)(dm_read32(src+1) & 0xff) << 8) |
132 ((uint64_t)(dm_read32(src+2) & 0xff) << 16) |
133 ((uint64_t)(dm_read32(src+3) & 0xff) << 24) |
134 ((uint64_t)(dm_read32(src+4) & 0xff) << 32) |
135 ((uint64_t)(dm_read32(src+5) & 0xff) << 40);
136
137 pm_write48(dst, data);
138 src += src_modifier * 6;
139 dst += dst_modifier;
140 }
141 break;
142 }
143 default:
144 {
145 fatalerror("SHARC: dma_op: unimplemented packing mode %d\n", pmode);
146 }
147 }
148
149 if (channel == 6)
150 {
151 m_core->irptl |= (1 << (channel+10));
152
153 /* DMA interrupt */
154 if (m_core->imask & (1 << (channel+10)))
155 {
156 m_core->irq_pending |= 1 << (channel+10);
157 }
158 }
159
160 // clear busy flag
161 m_core->dma_status &= ~(1 << channel);
162
163 m_core->dma_op[channel].active = false;
164 }
165
sharc_dma_exec(int channel)166 void adsp21062_device::sharc_dma_exec(int channel)
167 {
168 uint32_t src, dst;
169 uint32_t src_count, dst_count;
170 uint32_t src_modifier, dst_modifier;
171 int chen, tran, dtype, pmode, /*mswf, master,*/ ishake, intio/*, ext, flsh*/;
172
173 chen = (m_core->dma[channel].control >> 1) & 0x1;
174 tran = (m_core->dma[channel].control >> 2) & 0x1;
175 dtype = (m_core->dma[channel].control >> 5) & 0x1;
176 pmode = (m_core->dma[channel].control >> 6) & 0x3;
177 //mswf = (m_core->dma[channel].control >> 8) & 0x1;
178 //master = (m_core->dma[channel].control >> 9) & 0x1;
179 ishake = (m_core->dma[channel].control >> 10) & 0x1;
180 intio = (m_core->dma[channel].control >> 11) & 0x1;
181 //ext = (m_core->dma[channel].control >> 12) & 0x1;
182 //flsh = (m_core->dma[channel].control >> 13) & 0x1;
183
184 if (ishake)
185 fatalerror("SHARC: dma_exec: handshake not supported\n");
186 if (intio)
187 fatalerror("SHARC: dma_exec: single-word interrupt enable not supported\n");
188
189
190 if (chen) // Chained DMA
191 {
192 uint32_t dma_chain_ptr = m_core->dma[channel].chain_ptr & 0x1ffff;
193
194 schedule_chained_dma_op(channel, dma_chain_ptr, tran);
195 }
196 else
197 {
198 if (tran) // Transmit to external
199 {
200 dst = m_core->dma[channel].ext_index;
201 dst_modifier = m_core->dma[channel].ext_modifier;
202 dst_count = m_core->dma[channel].ext_count;
203 src = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000;
204 src_modifier = m_core->dma[channel].int_modifier;
205 src_count = m_core->dma[channel].int_count;
206 }
207 else // Receive from external
208 {
209 src = m_core->dma[channel].ext_index;
210 src_modifier = m_core->dma[channel].ext_modifier;
211 src_count = m_core->dma[channel].ext_count;
212 dst = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000;
213 dst_modifier = m_core->dma[channel].int_modifier;
214 dst_count = m_core->dma[channel].int_count;
215 }
216
217 if (dtype)
218 //if (src_count != dst_count)
219 {
220 pmode = DMA_PMODE_8_48;
221 }
222
223 schedule_dma_op(channel, src, dst, src_modifier, dst_modifier, src_count, dst_count, pmode);
224 }
225 }
226
TIMER_CALLBACK_MEMBER(adsp21062_device::sharc_dma_callback)227 TIMER_CALLBACK_MEMBER(adsp21062_device::sharc_dma_callback)
228 {
229 int channel = param;
230
231 m_core->dma_op[channel].timer->adjust(attotime::never, 0);
232
233 m_core->irptl |= (1 << (channel+10));
234
235 // DMA interrupt
236 if (m_core->imask & (1 << (channel+10)))
237 {
238 m_core->irq_pending |= 1 << (channel+10);
239 }
240
241 dma_op(channel);
242 if (m_core->dma_op[channel].chain_ptr != 0)
243 {
244 schedule_chained_dma_op(channel, m_core->dma_op[channel].chain_ptr, m_core->dma_op[channel].chained_direction);
245 }
246 }
247