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