3f23709e |
1 | /*************************************************************************************** |
2 | * Genesis Plus |
3 | * CD data controller (LC89510 compatible) |
4 | * |
5 | * Copyright (C) 2012 Eke-Eke (Genesis Plus GX) |
6 | * |
7 | * Redistribution and use of this code or any derivative works are permitted |
8 | * provided that the following conditions are met: |
9 | * |
10 | * - Redistributions may not be sold, nor may they be used in a commercial |
11 | * product or activity. |
12 | * |
13 | * - Redistributions that are modified from the original source must include the |
14 | * complete source code, including the source code for all components used by a |
15 | * binary built from the modified sources. However, as a special exception, the |
16 | * source code distributed need not include anything that is normally distributed |
17 | * (in either source or binary form) with the major components (compiler, kernel, |
18 | * and so on) of the operating system on which the executable runs, unless that |
19 | * component itself accompanies the executable. |
20 | * |
21 | * - Redistributions must reproduce the above copyright notice, this list of |
22 | * conditions and the following disclaimer in the documentation and/or other |
23 | * materials provided with the distribution. |
24 | * |
25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
26 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
29 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
35 | * POSSIBILITY OF SUCH DAMAGE. |
36 | * |
37 | ****************************************************************************************/ |
38 | |
39 | #include "../pico_int.h" |
40 | #include "genplus_macros.h" |
41 | |
42 | /* IFSTAT register bitmasks */ |
43 | #define BIT_DTEI 0x40 |
44 | #define BIT_DECI 0x20 |
45 | #define BIT_DTBSY 0x08 |
46 | #define BIT_DTEN 0x02 |
47 | |
48 | /* IFCTRL register bitmasks */ |
49 | #define BIT_DTEIEN 0x40 |
50 | #define BIT_DECIEN 0x20 |
51 | #define BIT_DOUTEN 0x02 |
52 | |
53 | /* CTRL0 register bitmasks */ |
54 | #define BIT_DECEN 0x80 |
55 | #define BIT_E01RQ 0x20 |
56 | #define BIT_AUTORQ 0x10 |
57 | #define BIT_WRRQ 0x04 |
58 | |
59 | /* CTRL1 register bitmasks */ |
60 | #define BIT_MODRQ 0x08 |
61 | #define BIT_FORMRQ 0x04 |
62 | #define BIT_SHDREN 0x01 |
63 | |
64 | /* CTRL2 register bitmask */ |
65 | #define BIT_VALST 0x80 |
66 | |
67 | /* PicoDrive: doing DMA at once, not using callbacks */ |
68 | //#define DMA_BYTES_PER_LINE 512 |
691abdfa |
69 | #define DMA_CYCLES_PER_BYTE 4 // or 6? |
3f23709e |
70 | |
71 | enum dma_type { |
72 | word_ram_0_dma_w = 1, |
73 | word_ram_1_dma_w = 2, |
74 | word_ram_2M_dma_w = 3, |
75 | pcm_ram_dma_w = 4, |
76 | prg_ram_dma_w = 5, |
77 | }; |
78 | |
79 | /* CDC hardware */ |
80 | typedef struct |
81 | { |
82 | uint8 ifstat; |
83 | uint8 ifctrl; |
f47d0a28 |
84 | uint16 dbc; |
85 | uint16 dac; |
86 | uint16 pt; |
87 | uint16 wa; |
3f23709e |
88 | uint8 ctrl[2]; |
89 | uint8 head[2][4]; |
90 | uint8 stat[4]; |
91 | int cycles; |
92 | //void (*dma_w)(unsigned int words); |
93 | int dma_w; |
94 | uint8 ram[0x4000 + 2352]; /* 16K external RAM (with one block overhead to handle buffer overrun) */ |
dd7c8c05 |
95 | } cdc_t; |
3f23709e |
96 | |
97 | static cdc_t cdc; |
98 | |
99 | void cdc_init(void) |
100 | { |
101 | memset(&cdc, 0, sizeof(cdc_t)); |
102 | } |
103 | |
104 | void cdc_reset(void) |
105 | { |
106 | /* reset CDC register index */ |
f47d0a28 |
107 | Pico_mcd->s68k_regs[0x04+1] = 0x00; |
3f23709e |
108 | |
109 | /* reset CDC registers */ |
110 | cdc.ifstat = 0xff; |
111 | cdc.ifctrl = 0x00; |
112 | cdc.ctrl[0] = 0x00; |
113 | cdc.ctrl[1] = 0x00; |
114 | cdc.stat[0] = 0x00; |
115 | cdc.stat[1] = 0x00; |
116 | cdc.stat[2] = 0x00; |
117 | cdc.stat[3] = 0x80; |
118 | cdc.head[0][0] = 0x00; |
119 | cdc.head[0][1] = 0x00; |
120 | cdc.head[0][2] = 0x00; |
121 | cdc.head[0][3] = 0x01; |
122 | cdc.head[1][0] = 0x00; |
123 | cdc.head[1][1] = 0x00; |
124 | cdc.head[1][2] = 0x00; |
125 | cdc.head[1][3] = 0x00; |
126 | |
127 | /* reset CDC cycle counter */ |
dd7c8c05 |
128 | cdc.cycles = SekCyclesDoneS68k(); |
3f23709e |
129 | |
130 | /* DMA transfer disabled */ |
131 | cdc.dma_w = 0; |
132 | } |
133 | |
134 | int cdc_context_save(uint8 *state) |
135 | { |
136 | uint8 tmp8; |
137 | int bufferptr = 0; |
138 | |
139 | if (cdc.dma_w == pcm_ram_dma_w) |
140 | { |
141 | tmp8 = 1; |
142 | } |
143 | else if (cdc.dma_w == prg_ram_dma_w) |
144 | { |
145 | tmp8 = 2; |
146 | } |
147 | else if (cdc.dma_w == word_ram_0_dma_w) |
148 | { |
149 | tmp8 = 3; |
150 | } |
151 | else if (cdc.dma_w == word_ram_1_dma_w) |
152 | { |
153 | tmp8 = 4; |
154 | } |
155 | else if (cdc.dma_w == word_ram_2M_dma_w) |
156 | { |
157 | tmp8 = 5; |
158 | } |
159 | else |
160 | { |
161 | tmp8 = 0; |
162 | } |
163 | |
164 | save_param(&cdc, sizeof(cdc)); |
165 | save_param(&tmp8, 1); |
166 | |
167 | return bufferptr; |
168 | } |
169 | |
170 | int cdc_context_load(uint8 *state) |
171 | { |
172 | uint8 tmp8; |
173 | int bufferptr = 0; |
174 | |
175 | load_param(&cdc, sizeof(cdc)); |
176 | load_param(&tmp8, 1); |
177 | |
178 | switch (tmp8) |
179 | { |
180 | case 1: |
181 | cdc.dma_w = pcm_ram_dma_w; |
182 | break; |
183 | case 2: |
184 | cdc.dma_w = prg_ram_dma_w; |
185 | break; |
186 | case 3: |
187 | cdc.dma_w = word_ram_0_dma_w; |
188 | break; |
189 | case 4: |
190 | cdc.dma_w = word_ram_1_dma_w; |
191 | break; |
192 | case 5: |
193 | cdc.dma_w = word_ram_2M_dma_w; |
194 | break; |
195 | default: |
196 | cdc.dma_w = 0; |
197 | break; |
198 | } |
199 | |
200 | return bufferptr; |
201 | } |
202 | |
203 | int cdc_context_load_old(uint8 *state) |
204 | { |
205 | #define old_load(v, ofs) \ |
206 | memcpy(&cdc.v, state + ofs, sizeof(cdc.v)) |
207 | |
208 | memcpy(cdc.ram, state, 0x4000); |
209 | old_load(ifstat, 67892); |
210 | old_load(ifctrl, 67924); |
211 | old_load(dbc, 67896); |
212 | old_load(dac, 67900); |
213 | old_load(pt, 67908); |
214 | old_load(wa, 67912); |
215 | old_load(ctrl, 67928); |
216 | old_load(head[0], 67904); |
217 | old_load(stat, 67916); |
218 | |
219 | cdc.dma_w = 0; |
f47d0a28 |
220 | switch (Pico_mcd->s68k_regs[0x04+0] & 0x07) |
3f23709e |
221 | { |
222 | case 4: /* PCM RAM DMA */ |
223 | cdc.dma_w = pcm_ram_dma_w; |
224 | break; |
225 | case 5: /* PRG-RAM DMA */ |
226 | cdc.dma_w = prg_ram_dma_w; |
227 | break; |
228 | case 7: /* WORD-RAM DMA */ |
f47d0a28 |
229 | if (Pico_mcd->s68k_regs[0x02+1] & 0x04) |
3f23709e |
230 | { |
f47d0a28 |
231 | if (Pico_mcd->s68k_regs[0x02+1] & 0x01) |
3f23709e |
232 | cdc.dma_w = word_ram_0_dma_w; |
233 | else |
234 | cdc.dma_w = word_ram_1_dma_w; |
235 | } |
236 | else |
237 | { |
f47d0a28 |
238 | if (Pico_mcd->s68k_regs[0x02+1] & 0x02) |
3f23709e |
239 | cdc.dma_w = word_ram_2M_dma_w; |
240 | } |
241 | break; |
242 | } |
243 | |
244 | return 0x10960; // sizeof(old_cdc) |
245 | #undef old_load |
246 | } |
247 | |
dd7c8c05 |
248 | static int check_decoder_irq_pending(void) |
249 | { |
250 | /* As per mcd-verificator, DECI is active for a phase of 49:72 per sector */ |
251 | /* 12500000/75 * 49/(49+72) = ~67500, but it sometimes fails with that */ |
252 | if (CYCLES_GE(SekCyclesDoneS68k(), cdc.cycles + 67250)) |
253 | cdc.ifstat |= BIT_DECI; |
254 | |
255 | return !(cdc.ifstat & BIT_DECI) && (cdc.ifctrl & BIT_DECIEN); |
256 | } |
257 | |
178a9b68 |
258 | static void do_dma(enum dma_type type, int bytes_in) |
3f23709e |
259 | { |
178a9b68 |
260 | int dma_addr = (Pico_mcd->s68k_regs[0x0a] << 8) | Pico_mcd->s68k_regs[0x0b]; |
f47d0a28 |
261 | int src_addr = cdc.dac & 0x3ffe; |
3f23709e |
262 | int dst_addr = dma_addr; |
178a9b68 |
263 | int bytes = bytes_in; |
264 | int words = bytes_in >> 1; |
3f23709e |
265 | int dst_limit = 0; |
266 | uint8 *dst; |
267 | int len; |
268 | |
269 | elprintf(EL_CD, "dma %d %04x->%04x %x", |
178a9b68 |
270 | type, cdc.dac, dst_addr, bytes_in); |
3f23709e |
271 | |
272 | switch (type) |
273 | { |
274 | case pcm_ram_dma_w: |
275 | dst_addr = (dst_addr << 2) & 0xffc; |
178a9b68 |
276 | if (dst_addr + bytes > 0x1000) { |
3f23709e |
277 | elprintf(EL_ANOMALY, "pcm dma oflow: %x %x", dst_addr, words); |
178a9b68 |
278 | bytes = 0x1000 - dst_addr; |
3f23709e |
279 | } |
280 | dst = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank]; |
281 | dst = dst + dst_addr; |
178a9b68 |
282 | while (bytes > 0) |
3f23709e |
283 | { |
178a9b68 |
284 | if (src_addr + bytes > 0x4000) { |
3f23709e |
285 | len = 0x4000 - src_addr; |
286 | memcpy(dst, cdc.ram + src_addr, len); |
287 | dst += len; |
288 | src_addr = 0; |
178a9b68 |
289 | bytes -= len; |
3f23709e |
290 | continue; |
291 | } |
178a9b68 |
292 | memcpy(dst, cdc.ram + src_addr, bytes); |
3f23709e |
293 | break; |
294 | } |
295 | goto update_dma; |
296 | |
297 | case prg_ram_dma_w: |
298 | dst_addr <<= 3; |
178a9b68 |
299 | dst = Pico_mcd->prg_ram + dst_addr; |
3f23709e |
300 | dst_limit = 0x80000; |
301 | break; |
302 | |
303 | case word_ram_0_dma_w: |
304 | dst_addr = (dst_addr << 3) & 0x1fffe; |
178a9b68 |
305 | dst = Pico_mcd->word_ram1M[0] + dst_addr; |
3f23709e |
306 | dst_limit = 0x20000; |
307 | break; |
308 | |
309 | case word_ram_1_dma_w: |
310 | dst_addr = (dst_addr << 3) & 0x1fffe; |
178a9b68 |
311 | dst = Pico_mcd->word_ram1M[1] + dst_addr; |
3f23709e |
312 | dst_limit = 0x20000; |
313 | break; |
314 | |
315 | case word_ram_2M_dma_w: |
316 | dst_addr = (dst_addr << 3) & 0x3fffe; |
178a9b68 |
317 | dst = Pico_mcd->word_ram2M + dst_addr; |
3f23709e |
318 | dst_limit = 0x40000; |
319 | break; |
320 | |
321 | default: |
322 | elprintf(EL_ANOMALY, "invalid dma: %d", type); |
323 | goto update_dma; |
324 | } |
325 | |
326 | if (dst_addr + words * 2 > dst_limit) { |
327 | elprintf(EL_ANOMALY, "cd dma %d oflow: %x %x", type, dst_addr, words); |
328 | words = (dst_limit - dst_addr) / 2; |
329 | } |
330 | while (words > 0) |
331 | { |
332 | if (src_addr + words * 2 > 0x4000) { |
333 | len = 0x4000 - src_addr; |
334 | memcpy16bswap((void *)dst, cdc.ram + src_addr, len / 2); |
335 | dst += len; |
336 | src_addr = 0; |
337 | words -= len / 2; |
338 | continue; |
339 | } |
340 | memcpy16bswap((void *)dst, cdc.ram + src_addr, words); |
341 | break; |
342 | } |
343 | |
178a9b68 |
344 | bytes_in &= ~1; // Todo leftover byte? |
345 | |
3f23709e |
346 | update_dma: |
347 | /* update DMA addresses */ |
178a9b68 |
348 | cdc.dac += bytes_in; |
3f23709e |
349 | if (type == pcm_ram_dma_w) |
178a9b68 |
350 | dma_addr += bytes_in >> 2; |
3f23709e |
351 | else |
178a9b68 |
352 | dma_addr += bytes_in >> 3; |
3f23709e |
353 | |
354 | Pico_mcd->s68k_regs[0x0a] = dma_addr >> 8; |
355 | Pico_mcd->s68k_regs[0x0b] = dma_addr; |
356 | } |
357 | |
3f23709e |
358 | void cdc_dma_update(void) |
359 | { |
360 | /* end of DMA transfer ? */ |
f47d0a28 |
361 | //if (cdc.dbc < DMA_BYTES_PER_LINE) |
3f23709e |
362 | { |
363 | /* transfer remaining words using 16-bit DMA */ |
f47d0a28 |
364 | //cdc.dma_w((cdc.dbc + 1) >> 1); |
178a9b68 |
365 | do_dma(cdc.dma_w, cdc.dbc + 1); |
3f23709e |
366 | |
367 | /* reset data byte counter (DBCH bits 4-7 should be set to 1) */ |
691abdfa |
368 | cdc.dbc = 0xffff; |
3f23709e |
369 | |
370 | /* clear !DTEN and !DTBSY */ |
371 | cdc.ifstat |= (BIT_DTBSY | BIT_DTEN); |
372 | |
178a9b68 |
373 | /* clear DSR bit & set EDT bit (SCD register $04) */ |
374 | Pico_mcd->s68k_regs[0x04+0] = (Pico_mcd->s68k_regs[0x04+0] & 0x07) | 0x80; |
3f23709e |
375 | |
178a9b68 |
376 | if (cdc.ifstat & BIT_DTEI) { |
377 | /* pending Data Transfer End interrupt */ |
378 | cdc.ifstat &= ~BIT_DTEI; |
379 | |
380 | /* Data Transfer End interrupt enabled ? */ |
dd7c8c05 |
381 | if (!check_decoder_irq_pending() && (cdc.ifctrl & BIT_DTEIEN)) |
3f23709e |
382 | { |
178a9b68 |
383 | /* level 5 interrupt enabled ? */ |
384 | if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5) |
385 | { |
386 | /* update IRQ level */ |
387 | elprintf(EL_INTS, "cdc DTE irq 5"); |
388 | pcd_irq_s68k(5, 1); |
389 | } |
3f23709e |
390 | } |
391 | } |
392 | |
3f23709e |
393 | /* disable DMA transfer */ |
394 | cdc.dma_w = 0; |
395 | } |
396 | #if 0 |
397 | else |
398 | { |
399 | /* transfer all words using 16-bit DMA */ |
400 | cdc.dma_w(DMA_BYTES_PER_LINE >> 1); |
401 | |
402 | /* decrement data byte counter */ |
f47d0a28 |
403 | cdc.dbc -= length; |
3f23709e |
404 | } |
405 | #endif |
406 | } |
407 | |
408 | int cdc_decoder_update(uint8 header[4]) |
409 | { |
410 | /* data decoding enabled ? */ |
411 | if (cdc.ctrl[0] & BIT_DECEN) |
412 | { |
413 | /* update HEAD registers */ |
414 | memcpy(cdc.head[0], header, sizeof(cdc.head[0])); |
415 | |
416 | /* set !VALST */ |
417 | cdc.stat[3] = 0x00; |
418 | |
691abdfa |
419 | /* set CRCOK bit */ |
420 | cdc.stat[0] = BIT_DECEN; |
421 | |
3f23709e |
422 | /* pending decoder interrupt */ |
423 | cdc.ifstat &= ~BIT_DECI; |
dd7c8c05 |
424 | cdc.cycles = SekCyclesDoneS68k(); |
3f23709e |
425 | |
426 | /* decoder interrupt enabled ? */ |
dd7c8c05 |
427 | if (((cdc.ifstat & BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN)) && (cdc.ifctrl & BIT_DECIEN)) |
3f23709e |
428 | { |
429 | /* level 5 interrupt enabled ? */ |
f47d0a28 |
430 | if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5) |
3f23709e |
431 | { |
432 | /* update IRQ level */ |
433 | elprintf(EL_INTS, "cdc DEC irq 5"); |
eb36d9c7 |
434 | pcd_irq_s68k(5, 1); |
3f23709e |
435 | } |
436 | } |
437 | |
438 | /* buffer RAM write enabled ? */ |
439 | if (cdc.ctrl[0] & BIT_WRRQ) |
440 | { |
441 | uint16 offset; |
442 | |
443 | /* increment block pointer */ |
f47d0a28 |
444 | cdc.pt += 2352; |
3f23709e |
445 | |
446 | /* increment write address */ |
f47d0a28 |
447 | cdc.wa += 2352; |
3f23709e |
448 | |
449 | /* CDC buffer address */ |
f47d0a28 |
450 | offset = cdc.pt & 0x3fff; |
3f23709e |
451 | |
452 | /* write CDD block header (4 bytes) */ |
453 | memcpy(cdc.ram + offset, header, 4); |
454 | |
455 | /* write CDD block data (2048 bytes) */ |
456 | cdd_read_data(cdc.ram + 4 + offset); |
457 | |
458 | /* take care of buffer overrun */ |
459 | if (offset > (0x4000 - 2048 - 4)) |
460 | { |
461 | /* data should be written at the start of buffer */ |
462 | memcpy(cdc.ram, cdc.ram + 0x4000, offset + 2048 + 4 - 0x4000); |
463 | } |
464 | |
465 | /* read next data block */ |
466 | return 1; |
467 | } |
468 | } |
dd7c8c05 |
469 | |
3f23709e |
470 | /* keep decoding same data block if Buffer Write is disabled */ |
471 | return 0; |
472 | } |
473 | |
474 | void cdc_reg_w(unsigned char data) |
475 | { |
476 | #ifdef LOG_CDC |
f47d0a28 |
477 | elprintf(EL_STATUS, "CDC register %X write 0x%04x", Pico_mcd->s68k_regs[0x04+1] & 0x0F, data); |
3f23709e |
478 | #endif |
178a9b68 |
479 | switch (Pico_mcd->s68k_regs[0x04+1] & 0x1F) |
3f23709e |
480 | { |
178a9b68 |
481 | case 0x00: |
482 | break; |
483 | |
3f23709e |
484 | case 0x01: /* IFCTRL */ |
485 | { |
486 | /* pending interrupts ? */ |
dd7c8c05 |
487 | check_decoder_irq_pending(); |
3f23709e |
488 | if (((data & BIT_DTEIEN) && !(cdc.ifstat & BIT_DTEI)) || |
489 | ((data & BIT_DECIEN) && !(cdc.ifstat & BIT_DECI))) |
490 | { |
491 | /* level 5 interrupt enabled ? */ |
f47d0a28 |
492 | if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5) |
3f23709e |
493 | { |
494 | /* update IRQ level */ |
495 | elprintf(EL_INTS, "cdc pending irq 5"); |
eb36d9c7 |
496 | pcd_irq_s68k(5, 1); |
3f23709e |
497 | } |
498 | } |
499 | else // if (scd.pending & (1 << 5)) |
500 | { |
501 | /* clear pending level 5 interrupts */ |
eb36d9c7 |
502 | pcd_irq_s68k(5, 0); |
3f23709e |
503 | } |
504 | |
505 | /* abort any data transfer if data output is disabled */ |
506 | if (!(data & BIT_DOUTEN)) |
507 | { |
508 | /* clear !DTBSY and !DTEN */ |
509 | cdc.ifstat |= (BIT_DTBSY | BIT_DTEN); |
510 | } |
511 | |
512 | cdc.ifctrl = data; |
f47d0a28 |
513 | Pico_mcd->s68k_regs[0x04+1] = 0x02; |
3f23709e |
514 | break; |
515 | } |
516 | |
517 | case 0x02: /* DBCL */ |
f47d0a28 |
518 | cdc.dbc &= 0xff00; |
519 | cdc.dbc |= data; |
520 | Pico_mcd->s68k_regs[0x04+1] = 0x03; |
3f23709e |
521 | break; |
522 | |
523 | case 0x03: /* DBCH */ |
f47d0a28 |
524 | cdc.dbc &= 0x00ff; |
178a9b68 |
525 | cdc.dbc |= (data & 0x0f) << 8; |
f47d0a28 |
526 | Pico_mcd->s68k_regs[0x04+1] = 0x04; |
3f23709e |
527 | break; |
528 | |
529 | case 0x04: /* DACL */ |
f47d0a28 |
530 | cdc.dac &= 0xff00; |
531 | cdc.dac |= data; |
532 | Pico_mcd->s68k_regs[0x04+1] = 0x05; |
3f23709e |
533 | break; |
534 | |
535 | case 0x05: /* DACH */ |
f47d0a28 |
536 | cdc.dac &= 0x00ff; |
537 | cdc.dac |= data << 8; |
538 | Pico_mcd->s68k_regs[0x04+1] = 0x06; |
3f23709e |
539 | break; |
540 | |
541 | case 0x06: /* DTRG */ |
542 | { |
543 | /* start data transfer if data output is enabled */ |
544 | if (cdc.ifctrl & BIT_DOUTEN) |
545 | { |
546 | /* set !DTBSY */ |
547 | cdc.ifstat &= ~BIT_DTBSY; |
548 | |
549 | /* clear DBCH bits 4-7 */ |
f47d0a28 |
550 | cdc.dbc &= 0x0fff; |
3f23709e |
551 | |
552 | /* clear EDT & DSR bits (SCD register $04) */ |
f47d0a28 |
553 | Pico_mcd->s68k_regs[0x04+0] &= 0x07; |
3f23709e |
554 | |
555 | cdc.dma_w = 0; |
556 | |
557 | /* setup data transfer destination */ |
f47d0a28 |
558 | switch (Pico_mcd->s68k_regs[0x04+0] & 0x07) |
3f23709e |
559 | { |
560 | case 2: /* MAIN-CPU host read */ |
561 | case 3: /* SUB-CPU host read */ |
562 | { |
563 | /* set !DTEN */ |
564 | cdc.ifstat &= ~BIT_DTEN; |
565 | |
566 | /* set DSR bit (register $04) */ |
f47d0a28 |
567 | Pico_mcd->s68k_regs[0x04+0] |= 0x40; |
3f23709e |
568 | break; |
569 | } |
570 | |
571 | case 4: /* PCM RAM DMA */ |
572 | { |
573 | cdc.dma_w = pcm_ram_dma_w; |
574 | break; |
575 | } |
576 | |
577 | case 5: /* PRG-RAM DMA */ |
578 | { |
579 | cdc.dma_w = prg_ram_dma_w; |
580 | break; |
581 | } |
582 | |
583 | case 7: /* WORD-RAM DMA */ |
584 | { |
585 | /* check memory mode */ |
f47d0a28 |
586 | if (Pico_mcd->s68k_regs[0x02+1] & 0x04) |
3f23709e |
587 | { |
588 | /* 1M mode */ |
f47d0a28 |
589 | if (Pico_mcd->s68k_regs[0x02+1] & 0x01) |
3f23709e |
590 | { |
591 | /* Word-RAM bank 0 is assigned to SUB-CPU */ |
592 | cdc.dma_w = word_ram_0_dma_w; |
593 | } |
594 | else |
595 | { |
596 | /* Word-RAM bank 1 is assigned to SUB-CPU */ |
597 | cdc.dma_w = word_ram_1_dma_w; |
598 | } |
599 | } |
600 | else |
601 | { |
602 | /* 2M mode */ |
f47d0a28 |
603 | if (Pico_mcd->s68k_regs[0x02+1] & 0x02) |
3f23709e |
604 | { |
605 | /* only process DMA if Word-RAM is assigned to SUB-CPU */ |
606 | cdc.dma_w = word_ram_2M_dma_w; |
607 | } |
608 | } |
609 | break; |
610 | } |
611 | |
612 | default: /* invalid */ |
613 | { |
614 | elprintf(EL_ANOMALY, "invalid CDC tranfer destination (%d)", |
f47d0a28 |
615 | Pico_mcd->s68k_regs[0x04+0] & 0x07); |
3f23709e |
616 | break; |
617 | } |
618 | } |
619 | |
620 | if (cdc.dma_w) |
691abdfa |
621 | pcd_event_schedule_s68k(PCD_EVENT_DMA, cdc.dbc * DMA_CYCLES_PER_BYTE); |
3f23709e |
622 | } |
623 | |
f47d0a28 |
624 | Pico_mcd->s68k_regs[0x04+1] = 0x07; |
3f23709e |
625 | break; |
626 | } |
627 | |
628 | case 0x07: /* DTACK */ |
629 | { |
630 | /* clear pending data transfer end interrupt */ |
631 | cdc.ifstat |= BIT_DTEI; |
632 | |
633 | /* clear DBCH bits 4-7 */ |
f47d0a28 |
634 | cdc.dbc &= 0x0fff; |
3f23709e |
635 | |
3f23709e |
636 | /* no pending decoder interrupt ? */ |
dd7c8c05 |
637 | if (!check_decoder_irq_pending()) |
3f23709e |
638 | { |
639 | /* clear pending level 5 interrupt */ |
eb36d9c7 |
640 | pcd_irq_s68k(5, 0); |
3f23709e |
641 | } |
dd7c8c05 |
642 | |
f47d0a28 |
643 | Pico_mcd->s68k_regs[0x04+1] = 0x08; |
3f23709e |
644 | break; |
645 | } |
646 | |
647 | case 0x08: /* WAL */ |
f47d0a28 |
648 | cdc.wa &= 0xff00; |
649 | cdc.wa |= data; |
650 | Pico_mcd->s68k_regs[0x04+1] = 0x09; |
3f23709e |
651 | break; |
652 | |
653 | case 0x09: /* WAH */ |
f47d0a28 |
654 | cdc.wa &= 0x00ff; |
655 | cdc.wa |= data << 8; |
656 | Pico_mcd->s68k_regs[0x04+1] = 0x0a; |
3f23709e |
657 | break; |
658 | |
659 | case 0x0a: /* CTRL0 */ |
660 | { |
178a9b68 |
661 | /* reset DECI if decoder turned off */ |
dd7c8c05 |
662 | if (!(data & BIT_DECEN)) { |
178a9b68 |
663 | cdc.ifstat |= BIT_DECI; |
664 | |
dd7c8c05 |
665 | if ((cdc.ifstat & BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN)) |
666 | { |
667 | /* clear pending level 5 interrupt */ |
668 | pcd_irq_s68k(5, 0); |
669 | } |
670 | } |
671 | |
3f23709e |
672 | /* update decoding mode */ |
673 | if (data & BIT_AUTORQ) |
674 | { |
675 | /* set MODE bit according to CTRL1 register & clear FORM bit */ |
676 | cdc.stat[2] = cdc.ctrl[1] & BIT_MODRQ; |
677 | } |
dd7c8c05 |
678 | else |
3f23709e |
679 | { |
680 | /* set MODE & FORM bits according to CTRL1 register */ |
681 | cdc.stat[2] = cdc.ctrl[1] & (BIT_MODRQ | BIT_FORMRQ); |
682 | } |
683 | |
684 | cdc.ctrl[0] = data; |
f47d0a28 |
685 | Pico_mcd->s68k_regs[0x04+1] = 0x0b; |
3f23709e |
686 | break; |
687 | } |
688 | |
689 | case 0x0b: /* CTRL1 */ |
690 | { |
691 | /* update decoding mode */ |
692 | if (cdc.ctrl[0] & BIT_AUTORQ) |
693 | { |
694 | /* set MODE bit according to CTRL1 register & clear FORM bit */ |
695 | cdc.stat[2] = data & BIT_MODRQ; |
696 | } |
dd7c8c05 |
697 | else |
3f23709e |
698 | { |
699 | /* set MODE & FORM bits according to CTRL1 register */ |
700 | cdc.stat[2] = data & (BIT_MODRQ | BIT_FORMRQ); |
701 | } |
702 | |
703 | cdc.ctrl[1] = data; |
f47d0a28 |
704 | Pico_mcd->s68k_regs[0x04+1] = 0x0c; |
3f23709e |
705 | break; |
706 | } |
707 | |
708 | case 0x0c: /* PTL */ |
f47d0a28 |
709 | cdc.pt &= 0xff00; |
710 | cdc.pt |= data; |
711 | Pico_mcd->s68k_regs[0x04+1] = 0x0d; |
3f23709e |
712 | break; |
dd7c8c05 |
713 | |
3f23709e |
714 | case 0x0d: /* PTH */ |
f47d0a28 |
715 | cdc.pt &= 0x00ff; |
716 | cdc.pt |= data << 8; |
717 | Pico_mcd->s68k_regs[0x04+1] = 0x0e; |
3f23709e |
718 | break; |
719 | |
720 | case 0x0e: /* CTRL2 (unused) */ |
f47d0a28 |
721 | Pico_mcd->s68k_regs[0x04+1] = 0x0f; |
3f23709e |
722 | break; |
723 | |
724 | case 0x0f: /* RESET */ |
725 | cdc_reset(); |
726 | break; |
727 | |
728 | default: /* by default, SBOUT is not used */ |
178a9b68 |
729 | Pico_mcd->s68k_regs[0x04+1] = (Pico_mcd->s68k_regs[0x04+1] + 1) & 0x1f; |
3f23709e |
730 | break; |
731 | } |
732 | } |
733 | |
734 | unsigned char cdc_reg_r(void) |
735 | { |
02ff0254 |
736 | switch (Pico_mcd->s68k_regs[0x04+1] & 0x1F) |
3f23709e |
737 | { |
178a9b68 |
738 | case 0x00: |
739 | return 0xff; |
740 | |
3f23709e |
741 | case 0x01: /* IFSTAT */ |
f47d0a28 |
742 | Pico_mcd->s68k_regs[0x04+1] = 0x02; |
dd7c8c05 |
743 | check_decoder_irq_pending(); |
3f23709e |
744 | return cdc.ifstat; |
745 | |
746 | case 0x02: /* DBCL */ |
f47d0a28 |
747 | Pico_mcd->s68k_regs[0x04+1] = 0x03; |
748 | return cdc.dbc & 0xff; |
3f23709e |
749 | |
750 | case 0x03: /* DBCH */ |
f47d0a28 |
751 | Pico_mcd->s68k_regs[0x04+1] = 0x04; |
752 | return (cdc.dbc >> 8) & 0xff; |
3f23709e |
753 | |
754 | case 0x04: /* HEAD0 */ |
f47d0a28 |
755 | Pico_mcd->s68k_regs[0x04+1] = 0x05; |
3f23709e |
756 | return cdc.head[cdc.ctrl[1] & BIT_SHDREN][0]; |
757 | |
758 | case 0x05: /* HEAD1 */ |
f47d0a28 |
759 | Pico_mcd->s68k_regs[0x04+1] = 0x06; |
3f23709e |
760 | return cdc.head[cdc.ctrl[1] & BIT_SHDREN][1]; |
761 | |
762 | case 0x06: /* HEAD2 */ |
f47d0a28 |
763 | Pico_mcd->s68k_regs[0x04+1] = 0x07; |
3f23709e |
764 | return cdc.head[cdc.ctrl[1] & BIT_SHDREN][2]; |
765 | |
766 | case 0x07: /* HEAD3 */ |
f47d0a28 |
767 | Pico_mcd->s68k_regs[0x04+1] = 0x08; |
3f23709e |
768 | return cdc.head[cdc.ctrl[1] & BIT_SHDREN][3]; |
769 | |
770 | case 0x08: /* PTL */ |
f47d0a28 |
771 | Pico_mcd->s68k_regs[0x04+1] = 0x09; |
772 | return cdc.pt & 0xff; |
3f23709e |
773 | |
774 | case 0x09: /* PTH */ |
f47d0a28 |
775 | Pico_mcd->s68k_regs[0x04+1] = 0x0a; |
776 | return (cdc.pt >> 8) & 0xff; |
3f23709e |
777 | |
778 | case 0x0a: /* WAL */ |
f47d0a28 |
779 | Pico_mcd->s68k_regs[0x04+1] = 0x0b; |
780 | return cdc.wa & 0xff; |
3f23709e |
781 | |
782 | case 0x0b: /* WAH */ |
f47d0a28 |
783 | Pico_mcd->s68k_regs[0x04+1] = 0x0c; |
784 | return (cdc.wa >> 8) & 0xff; |
3f23709e |
785 | |
786 | case 0x0c: /* STAT0 */ |
f47d0a28 |
787 | Pico_mcd->s68k_regs[0x04+1] = 0x0d; |
3f23709e |
788 | return cdc.stat[0]; |
789 | |
790 | case 0x0d: /* STAT1 (always return 0) */ |
f47d0a28 |
791 | Pico_mcd->s68k_regs[0x04+1] = 0x0e; |
3f23709e |
792 | return 0x00; |
793 | |
794 | case 0x0e: /* STAT2 */ |
f47d0a28 |
795 | Pico_mcd->s68k_regs[0x04+1] = 0x0f; |
3f23709e |
796 | return cdc.stat[2]; |
797 | |
798 | case 0x0f: /* STAT3 */ |
799 | { |
800 | uint8 data = cdc.stat[3]; |
801 | |
802 | /* clear !VALST (note: this is not 100% correct but BIOS do not seem to care) */ |
803 | cdc.stat[3] = BIT_VALST; |
804 | |
805 | /* clear pending decoder interrupt */ |
806 | cdc.ifstat |= BIT_DECI; |
dd7c8c05 |
807 | |
3f23709e |
808 | /* no pending data transfer end interrupt */ |
dd7c8c05 |
809 | if ((cdc.ifstat & BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN)) |
3f23709e |
810 | { |
811 | /* clear pending level 5 interrupt */ |
eb36d9c7 |
812 | pcd_irq_s68k(5, 0); |
3f23709e |
813 | } |
3f23709e |
814 | |
178a9b68 |
815 | Pico_mcd->s68k_regs[0x04+1] = 0x10; |
3f23709e |
816 | return data; |
817 | } |
818 | |
819 | default: /* by default, COMIN is always empty */ |
178a9b68 |
820 | Pico_mcd->s68k_regs[0x04+1] = (Pico_mcd->s68k_regs[0x04+1] + 1) & 0x1f; |
3f23709e |
821 | return 0xff; |
822 | } |
823 | } |
824 | |
dd7c8c05 |
825 | unsigned short cdc_host_r(int sub) |
3f23709e |
826 | { |
dd7c8c05 |
827 | int dir = Pico_mcd->s68k_regs[0x04+0] & 0x07; |
828 | |
829 | /* sync sub cpu if DSR bit not there (yet?) on main cpu */ |
830 | if (!(Pico_mcd->s68k_regs[0x04+0] & 0x40)) |
831 | if (!sub) pcd_sync_s68k(SekCyclesDone()+8, 0); /* HACK, mcd-verificator */ |
832 | |
3f23709e |
833 | /* check if data is available */ |
834 | if (!(cdc.ifstat & BIT_DTEN)) |
835 | { |
836 | /* read data word from CDC RAM buffer */ |
f47d0a28 |
837 | uint8 *datap = cdc.ram + (cdc.dac & 0x3ffe); |
3f23709e |
838 | uint16 data = (datap[0] << 8) | datap[1]; |
839 | |
840 | #ifdef LOG_CDC |
f47d0a28 |
841 | error("CDC host read 0x%04x -> 0x%04x (dbc=0x%x) (%X)\n", cdc.dac, data, cdc.dbc, s68k.pc); |
3f23709e |
842 | #endif |
dd7c8c05 |
843 | |
844 | /* only the configured cpu access advances the DMA */ |
845 | if ((sub && dir != 3) || (!sub && dir != 2)) |
846 | return data; |
847 | |
3f23709e |
848 | /* increment data address counter */ |
f47d0a28 |
849 | cdc.dac += 2; |
3f23709e |
850 | |
851 | /* decrement data byte counter */ |
f47d0a28 |
852 | cdc.dbc -= 2; |
3f23709e |
853 | |
854 | /* end of transfer ? */ |
f47d0a28 |
855 | if ((int16)cdc.dbc <= 0) |
3f23709e |
856 | { |
857 | /* reset data byte counter (DBCH bits 4-7 should be set to 1) */ |
691abdfa |
858 | cdc.dbc = 0xffff; |
3f23709e |
859 | |
860 | /* clear !DTEN and !DTBSY */ |
861 | cdc.ifstat |= (BIT_DTBSY | BIT_DTEN); |
862 | |
178a9b68 |
863 | /* clear DSR bit & set EDT bit (SCD register $04) */ |
864 | Pico_mcd->s68k_regs[0x04+0] = (Pico_mcd->s68k_regs[0x04+0] & 0x07) | 0x80; |
02ff0254 |
865 | |
866 | } else if ((int16)cdc.dbc <= 2) |
867 | { |
178a9b68 |
868 | if (cdc.ifstat & BIT_DTEI) { |
869 | /* pending Data Transfer End interrupt */ |
870 | cdc.ifstat &= ~BIT_DTEI; |
3f23709e |
871 | |
178a9b68 |
872 | /* Data Transfer End interrupt enabled ? */ |
dd7c8c05 |
873 | if (!check_decoder_irq_pending() && (cdc.ifctrl & BIT_DTEIEN)) |
3f23709e |
874 | { |
178a9b68 |
875 | /* level 5 interrupt enabled ? */ |
876 | if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5) |
877 | { |
878 | /* update IRQ level */ |
879 | elprintf(EL_INTS, "cdc DTE irq 5"); |
880 | pcd_irq_s68k(5, 1); |
881 | } |
3f23709e |
882 | } |
883 | } |
178a9b68 |
884 | /* set DSR and EDT bit (SCD register $04) */ |
885 | Pico_mcd->s68k_regs[0x04+0] = (Pico_mcd->s68k_regs[0x04+0] & 0x07) | 0xc0; |
3f23709e |
886 | } |
887 | |
888 | return data; |
889 | } |
890 | |
891 | #ifdef LOG_CDC |
892 | error("error reading CDC host (data transfer disabled)\n"); |
893 | #endif |
894 | return 0xffff; |
895 | } |
896 | |
897 | // vim:shiftwidth=2:ts=2:expandtab |