Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/waterbox/gpgx/core/cd_hw/cdc.c
2 views
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 "shared.h"
40
41
/* IFSTAT register bitmasks */
42
#define BIT_DTEI 0x40
43
#define BIT_DECI 0x20
44
#define BIT_DTBSY 0x08
45
#define BIT_DTEN 0x02
46
47
/* IFCTRL register bitmasks */
48
#define BIT_DTEIEN 0x40
49
#define BIT_DECIEN 0x20
50
#define BIT_DOUTEN 0x02
51
52
/* CTRL0 register bitmasks */
53
#define BIT_DECEN 0x80
54
#define BIT_E01RQ 0x20
55
#define BIT_AUTORQ 0x10
56
#define BIT_WRRQ 0x04
57
58
/* CTRL1 register bitmasks */
59
#define BIT_MODRQ 0x08
60
#define BIT_FORMRQ 0x04
61
#define BIT_SHDREN 0x01
62
63
/* CTRL2 register bitmask */
64
#define BIT_VALST 0x80
65
66
/* TODO: figure exact DMA transfer rate */
67
#define DMA_BYTES_PER_LINE 512
68
69
void cdc_init(void)
70
{
71
memset(&cdc, 0, sizeof(cdc_t));
72
}
73
74
void cdc_reset(void)
75
{
76
/* reset CDC register index */
77
scd.regs[0x04>>1].byte.l = 0x00;
78
79
/* reset CDC registers */
80
cdc.ifstat = 0xff;
81
cdc.ifctrl = 0x00;
82
cdc.ctrl[0] = 0x00;
83
cdc.ctrl[1] = 0x00;
84
cdc.stat[0] = 0x00;
85
cdc.stat[1] = 0x00;
86
cdc.stat[2] = 0x00;
87
cdc.stat[3] = 0x80;
88
cdc.head[0][0] = 0x00;
89
cdc.head[0][1] = 0x00;
90
cdc.head[0][2] = 0x00;
91
cdc.head[0][3] = 0x01;
92
cdc.head[1][0] = 0x00;
93
cdc.head[1][1] = 0x00;
94
cdc.head[1][2] = 0x00;
95
cdc.head[1][3] = 0x00;
96
97
/* reset CDC cycle counter */
98
cdc.cycles = 0;
99
100
/* DMA transfer disabled */
101
cdc.dma_w = 0;
102
103
/* clear any pending IRQ */
104
if (scd.pending & (1 << 5))
105
{
106
/* clear any pending interrupt level 5 */
107
scd.pending &= ~(1 << 5);
108
109
/* update IRQ level */
110
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
111
}
112
}
113
114
void cdc_dma_update(void)
115
{
116
/* maximal transfer length */
117
int length = DMA_BYTES_PER_LINE;
118
119
/* end of DMA transfer ? */
120
if (cdc.dbc.w < DMA_BYTES_PER_LINE)
121
{
122
/* transfer remaining words using 16-bit DMA */
123
cdc.dma_w((cdc.dbc.w + 1) >> 1);
124
125
/* reset data byte counter (DBCH bits 4-7 should be set to 1) */
126
cdc.dbc.w = 0xf000;
127
128
/* clear !DTEN and !DTBSY */
129
cdc.ifstat |= (BIT_DTBSY | BIT_DTEN);
130
131
/* pending Data Transfer End interrupt */
132
cdc.ifstat &= ~BIT_DTEI;
133
134
/* Data Transfer End interrupt enabled ? */
135
if (cdc.ifctrl & BIT_DTEIEN)
136
{
137
/* pending level 5 interrupt */
138
scd.pending |= (1 << 5);
139
140
/* level 5 interrupt enabled ? */
141
if (scd.regs[0x32>>1].byte.l & 0x20)
142
{
143
/* update IRQ level */
144
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
145
}
146
}
147
148
/* clear DSR bit & set EDT bit (CD register $04) */
149
scd.regs[0x04>>1].byte.h = (scd.regs[0x04>>1].byte.h & 0x07) | 0x80;
150
151
/* SUB-CPU idle on register $04 polling ? */
152
if (s68k.stopped & (1<<0x04))
153
{
154
/* sync SUB-CPU with CDC */
155
s68k.cycles = scd.cycles;
156
157
/* restart SUB-CPU */
158
s68k.stopped = 0;
159
#ifdef LOG_SCD
160
error("s68k started from %d cycles\n", s68k.cycles);
161
#endif
162
}
163
164
/* disable DMA transfer */
165
cdc.dma_w = 0;
166
}
167
else
168
{
169
/* transfer all words using 16-bit DMA */
170
cdc.dma_w(DMA_BYTES_PER_LINE >> 1);
171
172
/* decrement data byte counter */
173
cdc.dbc.w -= length;
174
}
175
}
176
177
int cdc_decoder_update(uint32 header)
178
{
179
/* data decoding enabled ? */
180
if (cdc.ctrl[0] & BIT_DECEN)
181
{
182
/* update HEAD registers */
183
*(uint32 *)(cdc.head[0]) = header;
184
185
/* set !VALST */
186
cdc.stat[3] = 0x00;
187
188
/* pending decoder interrupt */
189
cdc.ifstat &= ~BIT_DECI;
190
191
/* decoder interrupt enabled ? */
192
if (cdc.ifctrl & BIT_DECIEN)
193
{
194
/* pending level 5 interrupt */
195
scd.pending |= (1 << 5);
196
197
/* level 5 interrupt enabled ? */
198
if (scd.regs[0x32>>1].byte.l & 0x20)
199
{
200
/* update IRQ level */
201
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
202
}
203
}
204
205
/* buffer RAM write enabled ? */
206
if (cdc.ctrl[0] & BIT_WRRQ)
207
{
208
uint16 offset;
209
210
/* increment block pointer */
211
cdc.pt.w += 2352;
212
213
/* increment write address */
214
cdc.wa.w += 2352;
215
216
/* CDC buffer address */
217
offset = cdc.pt.w & 0x3fff;
218
219
/* write CDD block header (4 bytes) */
220
*(uint32 *)(cdc.ram + offset) = header;
221
222
/* write CDD block data (2048 bytes) */
223
cdd_read_data(cdc.ram + 4 + offset);
224
225
/* take care of buffer overrun */
226
if (offset > (0x4000 - 2048 - 4))
227
{
228
/* data should be written at the start of buffer */
229
memcpy(cdc.ram, cdc.ram + 0x4000, offset + 2048 + 4 - 0x4000);
230
}
231
232
/* read next data block */
233
return 1;
234
}
235
}
236
237
/* keep decoding same data block if Buffer Write is disabled */
238
return 0;
239
}
240
241
void cdc_reg_w(unsigned char data)
242
{
243
#ifdef LOG_CDC
244
error("CDC register %X write 0x%04x (%X)\n", scd.regs[0x04>>1].byte.l & 0x0F, data, s68k.pc);
245
#endif
246
switch (scd.regs[0x04>>1].byte.l & 0x0F)
247
{
248
case 0x01: /* IFCTRL */
249
{
250
/* pending interrupts ? */
251
if (((data & BIT_DTEIEN) && !(cdc.ifstat & BIT_DTEI)) ||
252
((data & BIT_DECIEN) && !(cdc.ifstat & BIT_DECI)))
253
{
254
/* pending level 5 interrupt */
255
scd.pending |= (1 << 5);
256
257
/* level 5 interrupt enabled ? */
258
if (scd.regs[0x32>>1].byte.l & 0x20)
259
{
260
/* update IRQ level */
261
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
262
}
263
}
264
else if (scd.pending & (1 << 5))
265
{
266
/* clear pending level 5 interrupts */
267
scd.pending &= ~(1 << 5);
268
269
/* update IRQ level */
270
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
271
}
272
273
/* abort any data transfer if data output is disabled */
274
if (!(data & BIT_DOUTEN))
275
{
276
/* clear !DTBSY and !DTEN */
277
cdc.ifstat |= (BIT_DTBSY | BIT_DTEN);
278
}
279
280
cdc.ifctrl = data;
281
scd.regs[0x04>>1].byte.l = 0x02;
282
break;
283
}
284
285
case 0x02: /* DBCL */
286
cdc.dbc.byte.l = data;
287
scd.regs[0x04>>1].byte.l = 0x03;
288
break;
289
290
case 0x03: /* DBCH */
291
cdc.dbc.byte.h = data;
292
scd.regs[0x04>>1].byte.l = 0x04;
293
break;
294
295
case 0x04: /* DACL */
296
cdc.dac.byte.l = data;
297
scd.regs[0x04>>1].byte.l = 0x05;
298
break;
299
300
case 0x05: /* DACH */
301
cdc.dac.byte.h = data;
302
scd.regs[0x04>>1].byte.l = 0x06;
303
break;
304
305
case 0x06: /* DTRG */
306
{
307
/* start data transfer if data output is enabled */
308
if (cdc.ifctrl & BIT_DOUTEN)
309
{
310
/* set !DTBSY */
311
cdc.ifstat &= ~BIT_DTBSY;
312
313
/* clear DBCH bits 4-7 */
314
cdc.dbc.byte.h &= 0x0f;
315
316
/* clear EDT & DSR bits (SCD register $04) */
317
scd.regs[0x04>>1].byte.h &= 0x07;
318
319
/* setup data transfer destination */
320
switch (scd.regs[0x04>>1].byte.h & 0x07)
321
{
322
case 2: /* MAIN-CPU host read */
323
case 3: /* SUB-CPU host read */
324
{
325
/* set !DTEN */
326
cdc.ifstat &= ~BIT_DTEN;
327
328
/* set DSR bit (register $04) */
329
scd.regs[0x04>>1].byte.h |= 0x40;
330
break;
331
}
332
333
case 4: /* PCM RAM DMA */
334
{
335
cdc.dma_w = pcm_ram_dma_w;
336
break;
337
}
338
339
case 5: /* PRG-RAM DMA */
340
{
341
cdc.dma_w = prg_ram_dma_w;
342
break;
343
}
344
345
case 7: /* WORD-RAM DMA */
346
{
347
/* check memory mode */
348
if (scd.regs[0x02 >> 1].byte.l & 0x04)
349
{
350
/* 1M mode */
351
if (scd.regs[0x02 >> 1].byte.l & 0x01)
352
{
353
/* Word-RAM bank 0 is assigned to SUB-CPU */
354
cdc.dma_w = word_ram_0_dma_w;
355
}
356
else
357
{
358
/* Word-RAM bank 1 is assigned to SUB-CPU */
359
cdc.dma_w = word_ram_1_dma_w;
360
}
361
}
362
else
363
{
364
/* 2M mode */
365
if (scd.regs[0x02 >> 1].byte.l & 0x02)
366
{
367
/* only process DMA if Word-RAM is assigned to SUB-CPU */
368
cdc.dma_w = word_ram_2M_dma_w;
369
}
370
}
371
break;
372
}
373
374
default: /* invalid */
375
{
376
#ifdef LOG_CDC
377
error("invalid CDC tranfer destination (%d)\n", scd.regs[0x04>>1].byte.h & 0x07);
378
#endif
379
break;
380
}
381
}
382
}
383
384
scd.regs[0x04>>1].byte.l = 0x07;
385
break;
386
}
387
388
case 0x07: /* DTACK */
389
{
390
/* clear pending data transfer end interrupt */
391
cdc.ifstat |= BIT_DTEI;
392
393
/* clear DBCH bits 4-7 */
394
cdc.dbc.byte.h &= 0x0f;
395
396
#if 0
397
/* no pending decoder interrupt ? */
398
if ((cdc.ifstat | BIT_DECI) || !(cdc.ifctrl & BIT_DECIEN))
399
{
400
/* clear pending level 5 interrupt */
401
scd.pending &= ~(1 << 5);
402
403
/* update IRQ level */
404
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
405
}
406
#endif
407
scd.regs[0x04>>1].byte.l = 0x08;
408
break;
409
}
410
411
case 0x08: /* WAL */
412
cdc.wa.byte.l = data;
413
scd.regs[0x04>>1].byte.l = 0x09;
414
break;
415
416
case 0x09: /* WAH */
417
cdc.wa.byte.h = data;
418
scd.regs[0x04>>1].byte.l = 0x0a;
419
break;
420
421
case 0x0a: /* CTRL0 */
422
{
423
/* set CRCOK bit only if decoding is enabled */
424
cdc.stat[0] = data & BIT_DECEN;
425
426
/* update decoding mode */
427
if (data & BIT_AUTORQ)
428
{
429
/* set MODE bit according to CTRL1 register & clear FORM bit */
430
cdc.stat[2] = cdc.ctrl[1] & BIT_MODRQ;
431
}
432
else
433
{
434
/* set MODE & FORM bits according to CTRL1 register */
435
cdc.stat[2] = cdc.ctrl[1] & (BIT_MODRQ | BIT_FORMRQ);
436
}
437
438
cdc.ctrl[0] = data;
439
scd.regs[0x04>>1].byte.l = 0x0b;
440
break;
441
}
442
443
case 0x0b: /* CTRL1 */
444
{
445
/* update decoding mode */
446
if (cdc.ctrl[0] & BIT_AUTORQ)
447
{
448
/* set MODE bit according to CTRL1 register & clear FORM bit */
449
cdc.stat[2] = data & BIT_MODRQ;
450
}
451
else
452
{
453
/* set MODE & FORM bits according to CTRL1 register */
454
cdc.stat[2] = data & (BIT_MODRQ | BIT_FORMRQ);
455
}
456
457
cdc.ctrl[1] = data;
458
scd.regs[0x04>>1].byte.l = 0x0c;
459
break;
460
}
461
462
case 0x0c: /* PTL */
463
cdc.pt.byte.l = data;
464
scd.regs[0x04>>1].byte.l = 0x0d;
465
break;
466
467
case 0x0d: /* PTH */
468
cdc.pt.byte.h = data;
469
scd.regs[0x04>>1].byte.l = 0x0e;
470
break;
471
472
case 0x0e: /* CTRL2 (unused) */
473
scd.regs[0x04>>1].byte.l = 0x0f;
474
break;
475
476
case 0x0f: /* RESET */
477
cdc_reset();
478
break;
479
480
default: /* by default, SBOUT is not used */
481
break;
482
}
483
}
484
485
unsigned char cdc_reg_r(void)
486
{
487
switch (scd.regs[0x04>>1].byte.l & 0x0F)
488
{
489
case 0x01: /* IFSTAT */
490
scd.regs[0x04>>1].byte.l = 0x02;
491
return cdc.ifstat;
492
493
case 0x02: /* DBCL */
494
scd.regs[0x04>>1].byte.l = 0x03;
495
return cdc.dbc.byte.l;
496
497
case 0x03: /* DBCH */
498
scd.regs[0x04>>1].byte.l = 0x04;
499
return cdc.dbc.byte.h;
500
501
case 0x04: /* HEAD0 */
502
scd.regs[0x04>>1].byte.l = 0x05;
503
return cdc.head[cdc.ctrl[1] & BIT_SHDREN][0];
504
505
case 0x05: /* HEAD1 */
506
scd.regs[0x04>>1].byte.l = 0x06;
507
return cdc.head[cdc.ctrl[1] & BIT_SHDREN][1];
508
509
case 0x06: /* HEAD2 */
510
scd.regs[0x04>>1].byte.l = 0x07;
511
return cdc.head[cdc.ctrl[1] & BIT_SHDREN][2];
512
513
case 0x07: /* HEAD3 */
514
scd.regs[0x04>>1].byte.l = 0x08;
515
return cdc.head[cdc.ctrl[1] & BIT_SHDREN][3];
516
517
case 0x08: /* PTL */
518
scd.regs[0x04>>1].byte.l = 0x09;
519
return cdc.pt.byte.l;
520
521
case 0x09: /* PTH */
522
scd.regs[0x04>>1].byte.l = 0x0a;
523
return cdc.pt.byte.h;
524
525
case 0x0a: /* WAL */
526
scd.regs[0x04>>1].byte.l = 0x0b;
527
return cdc.wa.byte.l;
528
529
case 0x0b: /* WAH */
530
scd.regs[0x04>>1].byte.l = 0x0c;
531
return cdc.wa.byte.h;
532
533
case 0x0c: /* STAT0 */
534
scd.regs[0x04>>1].byte.l = 0x0d;
535
return cdc.stat[0];
536
537
case 0x0d: /* STAT1 (always return 0) */
538
scd.regs[0x04>>1].byte.l = 0x0e;
539
return 0x00;
540
541
case 0x0e: /* STAT2 */
542
scd.regs[0x04>>1].byte.l = 0x0f;
543
return cdc.stat[2];
544
545
case 0x0f: /* STAT3 */
546
{
547
uint8 data = cdc.stat[3];
548
549
/* clear !VALST (note: this is not 100% correct but BIOS do not seem to care) */
550
cdc.stat[3] = BIT_VALST;
551
552
/* clear pending decoder interrupt */
553
cdc.ifstat |= BIT_DECI;
554
555
#if 0
556
/* no pending data transfer end interrupt */
557
if ((cdc.ifstat | BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN))
558
{
559
/* clear pending level 5 interrupt */
560
scd.pending &= ~(1 << 5);
561
562
/* update IRQ level */
563
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
564
}
565
#endif
566
567
scd.regs[0x04>>1].byte.l = 0x00;
568
return data;
569
}
570
571
default: /* by default, COMIN is always empty */
572
return 0xff;
573
}
574
}
575
576
unsigned short cdc_host_r(void)
577
{
578
/* check if data is available */
579
if (!(cdc.ifstat & BIT_DTEN))
580
{
581
/* read data word from CDC RAM buffer */
582
uint16 data = *(uint16 *)(cdc.ram + (cdc.dac.w & 0x3ffe));
583
584
#ifdef LSB_FIRST
585
/* source data is stored in big endian format */
586
data = ((data >> 8) | (data << 8)) & 0xffff;
587
#endif
588
589
#ifdef LOG_CDC
590
error("CDC host read 0x%04x -> 0x%04x (dbc=0x%x) (%X)\n", cdc.dac.w, data, cdc.dbc.w, s68k.pc);
591
#endif
592
593
/* increment data address counter */
594
cdc.dac.w += 2;
595
596
/* decrement data byte counter */
597
cdc.dbc.w -= 2;
598
599
/* end of transfer ? */
600
if ((int16)cdc.dbc.w <= 0)
601
{
602
/* reset data byte counter (DBCH bits 4-7 should be set to 1) */
603
cdc.dbc.w = 0xf000;
604
605
/* clear !DTEN and !DTBSY */
606
cdc.ifstat |= (BIT_DTBSY | BIT_DTEN);
607
608
/* pending Data Transfer End interrupt */
609
cdc.ifstat &= ~BIT_DTEI;
610
611
/* Data Transfer End interrupt enabled ? */
612
if (cdc.ifctrl & BIT_DTEIEN)
613
{
614
/* pending level 5 interrupt */
615
scd.pending |= (1 << 5);
616
617
/* level 5 interrupt enabled ? */
618
if (scd.regs[0x32>>1].byte.l & 0x20)
619
{
620
/* update IRQ level */
621
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
622
}
623
}
624
625
/* clear DSR bit & set EDT bit (SCD register $04) */
626
scd.regs[0x04>>1].byte.h = (scd.regs[0x04>>1].byte.h & 0x07) | 0x80;
627
}
628
629
return data;
630
}
631
632
#ifdef LOG_CDC
633
error("error reading CDC host (data transfer disabled)\n");
634
#endif
635
return 0xffff;
636
}
637
638