|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #include "dmac.h"
1.1.1.3 root 8: #include "bus.h"
9: #include "mpu680x0.h"
1.1.1.2 root 10: #include "mystring.h"
11:
12: std::unique_ptr<DMACDevice> gDMAC;
1.1 root 13:
14: DMACDevice::DMACDevice()
15: {
16: logname = "dmac";
17: devname = "DMAC";
18: devaddr = baseaddr;
19: devlen = 0x2000;
1.1.1.2 root 20:
1.1.1.4 root 21: monitor_size = nnSize(80, 30);
1.1.1.2 root 22:
23: for (int i = 0; i < countof(dmac.chan); i++) {
24: dmac.chan[i].ch = i;
25: dmac.chan[i].parent = this;
26: }
27: dmac.chan[0].desc = "FD";
28: dmac.chan[1].desc = "HD";
29: dmac.chan[2].desc = "User";
30: dmac.chan[3].desc = "ADPCM";
31:
32: for (int i = 0; i < countof(event); i++) {
33: event[i].dev = this;
34: event[i].func = (DeviceCallback_t)&DMACDevice::Transfer;
35: event[i].SetName(string_format("DMAC #%d", i));
36: event[i].code = i;
37: }
1.1 root 38: }
39:
40: DMACDevice::~DMACDevice()
41: {
42: }
43:
1.1.1.5 ! root 44: void
! 45: DMACDevice::ResetHard()
! 46: {
! 47: putlog(2, "リセット");
! 48:
! 49: // Clears GCR, DCR, OCR, SCR, CCR, CSR, CPR and CER for all channels.
! 50: // NIV and EIV are all set to $0F (uninitialized interrupt vector).
! 51: // MTC, MAR, DAR, BTC, BAR, MFC, DFC and BFC are not affected.
! 52:
! 53: dmac.gcr = 0;
! 54: for (int ch = 0; ch < countof(dmac.chan); ch++) {
! 55: DMAC::Channel *chan = &dmac.chan[ch];
! 56: chan->dcr = 0;
! 57: chan->ocr = 0;
! 58: chan->scr = 0;
! 59: chan->ccr = 0;
! 60: chan->int_enable = false;
! 61: chan->csr = 0;
! 62: chan->active = false;
! 63: chan->pcl = false;
! 64: chan->cpr = 0;
! 65: chan->cer = 0;
! 66:
! 67: chan->niv = 0x0f;
! 68: chan->eiv = 0x0f;
! 69: }
! 70:
! 71: // イベントをすべて停止
! 72: for (int i = 0; i < countof(event); i++) {
! 73: event[i].Stop();
! 74: }
! 75: }
! 76:
1.1 root 77: uint64
1.1.1.3 root 78: DMACDevice::Read(uint32 addr)
1.1 root 79: {
80: uint8 data;
81: int ch;
82:
1.1.1.5 ! root 83: gMPU->AddCycle(37); // InsideOut p.135
! 84:
1.1.1.3 root 85: ch = addr / 0x40;
1.1.1.2 root 86: DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.3 root 87: int n = addr % 0x40;
1.1 root 88: switch (n) {
89: case DMAC::CSR:
1.1.1.2 root 90: data = chan->PeekCSR();
91: putlog(4, "#%d CSR -> $%02x", ch, data);
1.1 root 92: break;
93:
94: case DMAC::CER:
95: data = chan->cer;
1.1.1.2 root 96: putlog(4, "#%d CER -> $%02x", ch, data);
1.1 root 97: break;
98:
99: case DMAC::DCR:
100: data = chan->dcr;
1.1.1.2 root 101: putlog(4, "#%d DCR -> $%02x", ch, data);
1.1 root 102: break;
103:
104: case DMAC::OCR:
105: data = chan->ocr;
1.1.1.2 root 106: putlog(4, "#%d OCR -> $%02x", ch, data);
1.1 root 107: break;
108:
109: case DMAC::SCR:
110: data = chan->scr;
1.1.1.2 root 111: putlog(4, "#%d SCR -> $%02x", ch, data);
1.1 root 112: break;
113:
114: case DMAC::CCR:
1.1.1.2 root 115: data = chan->PeekCCR();
116: putlog(4, "#%d CCR -> $%02x", ch, data);
1.1 root 117: break;
118:
119: case DMAC::MTC:
120: data = chan->mtc >> 8;
1.1.1.2 root 121: putlog(4, "#%d MTC:H -> $%02x", ch, data);
1.1 root 122: break;
123: case DMAC::MTC + 1:
124: data = chan->mtc & 0xff;
1.1.1.2 root 125: putlog(4, "#%d MTC:L -> $%02x", ch, data);
1.1 root 126: break;
127:
128: case DMAC::MAR:
129: data = chan->mar >> 24;
1.1.1.2 root 130: putlog(4, "#%d MAR:0 -> $%02x", ch, data);
1.1 root 131: break;
132: case DMAC::MAR + 1:
133: data = (chan->mar >> 16) & 0xff;
1.1.1.2 root 134: putlog(4, "#%d MAR:1 -> $%02x", ch, data);
1.1 root 135: break;
136: case DMAC::MAR + 2:
137: data = (chan->mar >> 8) & 0xff;
1.1.1.2 root 138: putlog(4, "#%d MAR:2 -> $%02x", ch, data);
1.1 root 139: break;
140: case DMAC::MAR + 3:
141: data = chan->mar & 0xff;
1.1.1.2 root 142: putlog(4, "#%d MAR:3 -> $%02x", ch, data);
1.1 root 143: break;
144:
145: case DMAC::DAR:
146: data = chan->dar >> 24;
1.1.1.2 root 147: putlog(4, "#%d DAR:0 -> $%02x", ch, data);
1.1 root 148: break;
149: case DMAC::DAR + 1:
150: data = (chan->dar >> 16) & 0xff;
1.1.1.2 root 151: putlog(4, "#%d DAR:1 -> $%02x", ch, data);
1.1 root 152: break;
153: case DMAC::DAR + 2:
154: data = (chan->dar >> 8) & 0xff;
1.1.1.2 root 155: putlog(4, "#%d DAR:2 -> $%02x", ch, data);
1.1 root 156: break;
157: case DMAC::DAR + 3:
158: data = chan->dar & 0xff;
1.1.1.2 root 159: putlog(4, "#%d DAR:3 -> $%02x", ch, data);
1.1 root 160: break;
161:
162: case DMAC::BTC:
163: data = chan->btc >> 8;
1.1.1.2 root 164: putlog(4, "#%d BTC:H -> $%02x", ch, data);
1.1 root 165: break;
166: case DMAC::BTC + 1:
167: data = chan->btc & 0xff;
1.1.1.2 root 168: putlog(4, "#%d BTC:L -> $%02x", ch, data);
1.1 root 169: break;
170:
171: case DMAC::BAR:
172: data = chan->bar >> 24;
1.1.1.2 root 173: putlog(4, "#%d BAR:0 -> $%02x", ch, data);
1.1 root 174: break;
175: case DMAC::BAR + 1:
176: data = (chan->bar >> 16) & 0xff;
1.1.1.2 root 177: putlog(4, "#%d BAR:1 -> $%02x", ch, data);
1.1 root 178: break;
179: case DMAC::BAR + 2:
180: data = (chan->bar >> 8) & 0xff;
1.1.1.2 root 181: putlog(4, "#%d BAR:2 -> $%02x", ch, data);
1.1 root 182: break;
183: case DMAC::BAR + 3:
184: data = chan->bar & 0xff;
1.1.1.2 root 185: putlog(4, "#%d BAR:3 -> $%02x", ch, data);
1.1 root 186: break;
187:
188: case DMAC::NIV:
189: data = chan->niv;
1.1.1.2 root 190: putlog(4, "#%d NIV -> $%02x", ch, data);
1.1 root 191: break;
192:
193: case DMAC::EIV:
194: data = chan->eiv;
1.1.1.2 root 195: putlog(4, "#%d EIV -> $%02x", ch, data);
1.1 root 196: break;
197:
198: case DMAC::MFC:
199: data = chan->mfc;
1.1.1.2 root 200: putlog(4, "#%d MFC -> $%02x", ch, data);
1.1 root 201: break;
202:
203: case DMAC::CPR:
204: data = chan->cpr;
1.1.1.2 root 205: putlog(4, "#%d CPR -> $%02x", ch, data);
1.1 root 206: break;
207:
208: case DMAC::DFC:
209: data = chan->dfc;
1.1.1.2 root 210: putlog(4, "#%d DFC -> $%02x", ch, data);
1.1 root 211: break;
212:
213: case DMAC::BFC:
214: data = chan->bfc;
1.1.1.2 root 215: putlog(4, "#%d BFC -> $%02x", ch, data);
1.1 root 216: break;
217:
218: case DMAC::GCR:
219: if (ch == 3) {
220: data = dmac.gcr;
1.1.1.2 root 221: putlog(4, "GCR -> $%02x", data);
1.1 root 222: break;
223: } else {
224: data = 0xff;
225: }
226: break;
227:
228: default:
229: data = 0xff;
230: break;
231: }
232:
233: return data;
234: }
235:
236: uint64
1.1.1.3 root 237: DMACDevice::Write(uint32 addr, uint32 data)
1.1 root 238: {
239: int ch;
240:
1.1.1.5 ! root 241: gMPU->AddCycle(31); // InsideOut p.135
! 242:
1.1.1.3 root 243: ch = addr / 0x40;
1.1.1.2 root 244: DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.3 root 245: int n = addr % 0x40;
1.1 root 246: switch (n) {
247: case DMAC::CSR:
1.1.1.2 root 248: chan->WriteCSR(data);
1.1 root 249: break;
250:
251: case DMAC::CER:
252: // Read only
253: break;
254:
255: case DMAC::DCR:
1.1.1.2 root 256: putlog(4, "#%d DCR <- $%02x", ch, data);
1.1 root 257: chan->dcr = data & 0xfb;
258: break;
259:
260: case DMAC::OCR:
1.1.1.2 root 261: putlog(4, "#%d OCR <- $%02x", ch, data);
1.1 root 262: chan->ocr = data;
263: break;
264:
265: case DMAC::SCR:
1.1.1.2 root 266: putlog(4, "#%d SCR <- $%02x", ch, data);
1.1 root 267: chan->scr = data & 0x0f;
268: break;
269:
270: case DMAC::CCR:
1.1.1.2 root 271: putlog(4, "#%d CCR <- $%02x", ch, data);
272: chan->WriteCCR(data);
1.1 root 273: break;
274:
275: case DMAC::MTC:
276: chan->mtc = (chan->mtc & 0x00ff) | (data << 8);
1.1.1.2 root 277: putlog(4, "#%d MTC:H <- $%02x (MTC=$%04x)", ch, data, chan->mtc);
1.1 root 278: break;
279: case DMAC::MTC + 1:
280: chan->mtc = (chan->mtc & 0xff00) | data;
1.1.1.2 root 281: putlog(4, "#%d MTC:L <- $%02x (MTC=$%04x)", ch, data, chan->mtc);
1.1 root 282: break;
283:
284: case DMAC::MAR:
285: chan->mar = (chan->mar & 0x00ffffff) | (data << 24);
1.1.1.2 root 286: putlog(4, "#%d MAR:0 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1 root 287: break;
288: case DMAC::MAR + 1:
289: chan->mar = (chan->mar & 0xff00ffff) | (data << 16);
1.1.1.2 root 290: putlog(4, "#%d MAR:1 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1 root 291: break;
292: case DMAC::MAR + 2:
293: chan->mar = (chan->mar & 0xffff00ff) | (data << 8);
1.1.1.2 root 294: putlog(4, "#%d MAR:2 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1 root 295: break;
296: case DMAC::MAR + 3:
297: chan->mar = (chan->mar & 0xffffff00) | data;
1.1.1.2 root 298: putlog(4, "#%d MAR:3 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1 root 299: break;
300:
301: case DMAC::DAR:
302: chan->dar = (chan->dar & 0x00ffffff) | (data << 24);
1.1.1.2 root 303: putlog(4, "#%d DAR:0 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1 root 304: break;
305: case DMAC::DAR + 1:
306: chan->dar = (chan->dar & 0xff00ffff) | (data << 16);
1.1.1.2 root 307: putlog(4, "#%d DAR:1 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1 root 308: break;
309: case DMAC::DAR + 2:
310: chan->dar = (chan->dar & 0xffff00ff) | (data << 8);
1.1.1.2 root 311: putlog(4, "#%d DAR:2 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1 root 312: break;
313: case DMAC::DAR + 3:
314: chan->dar = (chan->dar & 0xffffff00) | data;
1.1.1.2 root 315: putlog(4, "#%d DAR:3 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1 root 316: break;
317:
318: case DMAC::BTC:
319: chan->btc = (chan->btc & 0x00ff) | (data << 8);
1.1.1.2 root 320: putlog(4, "#%d BTC:H <- $%02x (BTC=$%04x)", ch, data, chan->btc);
1.1 root 321: break;
322: case DMAC::BTC + 1:
323: chan->btc = (chan->btc & 0xff00) | data;
1.1.1.2 root 324: putlog(4, "#%d BTC:L <- $%02x (BTC=$%04x)", ch, data, chan->btc);
1.1 root 325: break;
326:
327: case DMAC::BAR:
328: chan->bar = (chan->bar & 0x00ffffff) | (data << 24);
1.1.1.2 root 329: putlog(4, "#%d BAR:0 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1 root 330: break;
331: case DMAC::BAR + 1:
332: chan->bar = (chan->bar & 0xff00ffff) | (data << 16);
1.1.1.2 root 333: putlog(4, "#%d BAR:1 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1 root 334: break;
335: case DMAC::BAR + 2:
336: chan->bar = (chan->bar & 0xffff00ff) | (data << 8);
1.1.1.2 root 337: putlog(4, "#%d BAR:2 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1 root 338: break;
339: case DMAC::BAR + 3:
340: chan->bar = (chan->bar & 0xffffff00) | data;
1.1.1.2 root 341: putlog(4, "#%d BAR:3 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1 root 342: break;
343:
344: case DMAC::NIV:
1.1.1.2 root 345: putlog(4, "#%d NIV <- $%02x", ch, data);
1.1 root 346: chan->niv = data;
347: break;
348:
349: case DMAC::EIV:
1.1.1.2 root 350: putlog(4, "#%d EIV <- $%02x", ch, data);
1.1 root 351: chan->eiv = data;
352: break;
353:
354: case DMAC::MFC:
1.1.1.2 root 355: putlog(4, "#%d MFC <- $%02x", ch, data);
1.1 root 356: chan->mfc = data & 7;
357: break;
358:
359: case DMAC::CPR:
1.1.1.2 root 360: putlog(4, "#%d CPR <- $%02x", ch, data);
1.1 root 361: chan->cpr = data & 3;
362: break;
363:
364: case DMAC::DFC:
1.1.1.2 root 365: putlog(4, "#%d DFC <- $%02x", ch, data);
1.1 root 366: chan->dfc = data & 7;
367: break;
368:
369: case DMAC::BFC:
1.1.1.2 root 370: putlog(4, "#%d BFC <- $%02x", ch, data);
1.1 root 371: chan->bfc = data & 7;
372: break;
373:
374: case DMAC::GCR:
375: if (ch == 3) {
1.1.1.2 root 376: putlog(4, "GCR <- $%02x", data);
1.1 root 377: dmac.gcr = data;
378: }
379: break;
380:
381: default:
382: break;
383: }
384: return 0;
385: }
386:
387: uint64
1.1.1.3 root 388: DMACDevice::Peek(uint32 addr)
1.1 root 389: {
390: uint8 data;
391: int ch;
392:
1.1.1.3 root 393: ch = addr / 0x40;
1.1.1.2 root 394: const DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.3 root 395: int n = addr % 0x40;
1.1 root 396: switch (n) {
397: case DMAC::CSR:
1.1.1.2 root 398: data = chan->PeekCSR();
1.1 root 399: break;
400:
401: case DMAC::CER:
402: data = chan->cer;
403: break;
404:
405: case DMAC::DCR:
406: data = chan->dcr;
407: break;
408:
409: case DMAC::OCR:
410: data = chan->ocr;
411: break;
412:
413: case DMAC::SCR:
414: data = chan->scr;
415: break;
416:
417: case DMAC::CCR:
1.1.1.2 root 418: data = chan->PeekCCR();
1.1 root 419: break;
420:
421: case DMAC::MTC:
422: data = chan->mtc >> 8;
423: break;
424: case DMAC::MTC + 1:
425: data = chan->mtc & 0xff;
426: break;
427:
428: case DMAC::MAR:
429: data = chan->mar >> 24;
430: break;
431: case DMAC::MAR + 1:
432: data = (chan->mar >> 16) & 0xff;
433: break;
434: case DMAC::MAR + 2:
435: data = (chan->mar >> 8) & 0xff;
436: break;
437: case DMAC::MAR + 3:
438: data = chan->mar & 0xff;
439: break;
440:
441: case DMAC::DAR:
442: data = chan->dar >> 24;
443: break;
444: case DMAC::DAR + 1:
445: data = (chan->dar >> 16) & 0xff;
446: break;
447: case DMAC::DAR + 2:
448: data = (chan->dar >> 8) & 0xff;
449: break;
450: case DMAC::DAR + 3:
451: data = chan->dar & 0xff;
452: break;
453:
454: case DMAC::BTC:
455: data = chan->btc >> 8;
456: break;
457: case DMAC::BTC + 1:
458: data = chan->btc & 0xff;
459: break;
460:
461: case DMAC::BAR:
462: data = chan->bar >> 24;
463: break;
464: case DMAC::BAR + 1:
465: data = (chan->bar >> 16) & 0xff;
466: break;
467: case DMAC::BAR + 2:
468: data = (chan->bar >> 8) & 0xff;
469: break;
470: case DMAC::BAR + 3:
471: data = chan->bar & 0xff;
472: break;
473:
474: case DMAC::NIV:
475: data = chan->niv;
476: break;
477:
478: case DMAC::EIV:
479: data = chan->eiv;
480: break;
481:
482: case DMAC::MFC:
483: data = chan->mfc;
484: break;
485:
486: case DMAC::CPR:
487: data = chan->cpr;
488: break;
489:
490: case DMAC::DFC:
491: data = chan->dfc;
492: break;
493:
494: case DMAC::BFC:
495: data = chan->bfc;
496: break;
497:
498: case DMAC::GCR:
499: if (ch == 3) {
500: data = dmac.gcr;
501: break;
502: } else {
503: data = 0xff;
504: }
505: break;
506:
507: default:
508: data = 0xff;
509: break;
510: }
511:
512: return data;
513: }
514:
1.1.1.4 root 515: void
516: DMACDevice::MonitorUpdate(TextScreen& monitor)
1.1.1.2 root 517: {
518: int x;
519: int y;
520:
521: monitor.Clear();
522:
523: y = 1;
1.1.1.3 root 524: monitor.Puts(0, y++, "CSR");
1.1.1.2 root 525: y += 2;
1.1.1.3 root 526: monitor.Puts(0, y++, "CER");
527: monitor.Puts(0, y++, "DCR:XRM");
528: monitor.Puts(0, y++, "DCR:DTYP");
529: monitor.Puts(0, y++, "DCR:DPS");
530: monitor.Puts(0, y++, "DCR:PCL");
531: monitor.Puts(0, y++, "OCR:DIR");
532: monitor.Puts(0, y++, "OCR:SIZE");
533: monitor.Puts(0, y++, "OCR:CHAIN");
534: monitor.Puts(0, y++, "OCR:REQG");
535: monitor.Puts(0, y++, "SCR:MAC");
536: monitor.Puts(0, y++, "SCR:DAC");
537: monitor.Puts(0, y++, "CCR");
1.1.1.2 root 538: y += 2;
1.1.1.3 root 539: monitor.Puts(0, y++, "MTC");
540: monitor.Puts(0, y++, "MAR");
541: monitor.Puts(0, y++, "DAR");
542: monitor.Puts(0, y++, "BTC");
543: monitor.Puts(0, y++, "BAR");
544: monitor.Puts(0, y++, "NIV");
545: monitor.Puts(0, y++, "EIV");
546: monitor.Puts(0, y++, "MFC");
547: monitor.Puts(0, y++, "CPR");
548: monitor.Puts(0, y++, "DFC");
549: monitor.Puts(0, y++, "BFC");
1.1.1.2 root 550:
551: for (int ch = 0; ch < 4; ch++) {
552: DMAC::Channel *chan = &dmac.chan[ch];
553: int val;
554: x = 12 + ch * 17;
555: y = 0;
556:
557: // 地味だけど有効なチャンネルをハイライトしてみる
1.1.1.3 root 558: monitor.Print(x, y++, (chan->active ? TA::Em : TA::Normal),
1.1.1.2 root 559: "#%d (%s)", chan->ch, chan->desc);
560:
561: // CSR
562: val = chan->PeekCSR();
563: monitor.Print(x, y++, "$%02x", val);
564: static const char * const csrname[] = {
565: "COC", "BTC", "NDT", "ERR", "ACT", "---", "PCT", "PCS",
566: };
1.1.1.4 root 567: MonitorReg4(monitor, x, y++, val >> 4, &csrname[0]);
568: MonitorReg4(monitor, x, y++, val & 0xff, &csrname[4]);
1.1.1.2 root 569:
570: // CER
571: val = chan->cer & 0x1f;
572: const char *e;
573: if (val <= 0x11 && errnames[val]) {
574: e = errnames[val];
575: } else {
576: e = "?";
577: }
578: monitor.Print(x, y, "$%02x", chan->cer);
579: if (val > 0) {
580: monitor.Print(x + 3, y, ":%s", e);
581: }
582: y++;
583:
584: // DCR:XRM
585: static const char * const dcr_xrm[] = {
586: //1234567890123
587: "Burst",
588: "undefined",
589: "CycleW/O Hold",
590: "CycleWithHold",
591: };
592: val = chan->dcr >> 6;
593: monitor.Print(x, y++, "%d:%s", val, dcr_xrm[val]);
594:
595: // DCR:DTYP
596: static const char * const dcr_dtyp[] = {
597: //1234567890123
598: "68000",
599: "6800",
600: "ACK",
601: "ACK+READY",
602: };
603: val = (chan->dcr >> 4) & 3;
604: monitor.Print(x, y++, "%d:%s", val, dcr_dtyp[val]);
605:
606: // DCR:DPS
607: static const char * const dcr_dps[] = {
608: //1234567890123
609: "8bit",
610: "16bit",
611: };
612: val = (chan->dcr >> 3) & 1;
613: monitor.Print(x, y++, "%d:%s", val, dcr_dps[val]);
614:
615: // DCR:PCL
616: monitor.Print(x, y++, "XXX PCL");
617:
618: // OCR:DIR
619: static const char * const ocr_dir[] = {
620: //1234567890123
621: "MemoryToDevice",
622: "DeviceToMemory",
623: };
624: val = (chan->ocr >> 7);
625: monitor.Print(x, y++, "%d:%s", val, ocr_dir[val]);
626:
627: // OCR:SIZE
628: static const char * const ocr_size[] = {
629: //1234567890123
630: "8bit",
631: "16bit",
632: "32bit",
633: "8bit Unpacked",
634: };
635: val = (chan->ocr >> 4) & 3;
636: monitor.Print(x, y++, "%d:%s", val, ocr_size[val]);
637:
638: // OCR:CHAIN
639: static const char * const ocr_chain[] = {
640: //1234567890123
641: "NoChain",
642: "undefined",
643: "ArrayChain",
644: "LinkArrayChain",
645: };
646: val = (chan->ocr >> 2) & 3;
647: monitor.Print(x, y++, "%d:%s", val, ocr_chain[val]);
648:
649: // OCR:REQG
650: static const char * const ocr_reqg[] = {
651: //1234567890123
652: "AutoReq(Limit)",
653: "AutoReq(Max)",
654: "ExternalReq",
655: "AutoThenExt",
656: };
657: val = (chan->ocr & 3);
658: monitor.Print(x, y++, "%d:%s", val, ocr_reqg[val]);
659:
660: // SCR:MAC
661: static const char * const scr_xac[] = {
662: //1234567890123
663: "NoCount",
664: "CountUp",
665: "CountDown",
666: "undefined",
667: };
668: val = (chan->scr >> 2) & 3;
669: monitor.Print(x, y++, "%d:%s", val, scr_xac[val]);
670: val = chan->scr & 3;
671: monitor.Print(x, y++, "%d:%s", val, scr_xac[val]);
672:
673: // CCR
674: val = chan->PeekCCR();
675: monitor.Print(x, y++, "$%02x", val);
676: static const char * const ccrnames[] = {
677: "STR", "CNT", "HLT", "SAB", "INT", "---", "---", "---",
678: };
1.1.1.4 root 679: MonitorReg4(monitor, x, y++, (val >> 4), &ccrnames[0]);
680: MonitorReg4(monitor, x, y++, (val & 0xff), &ccrnames[4]);
1.1.1.2 root 681:
682: // MTC
683: monitor.Print(x, y++, "$%04x", chan->mtc);
684: // MAR
685: // X680x0 がターゲットなので24bit超える設定は目立たせる
686: if (chan->mar > 0xffffff) {
687: monitor.Print(x, y++, TA::On, "$%08x", chan->mar);
688: } else {
689: monitor.Print(x, y++, "$%06x", chan->mar);
690: }
691: // DAR
692: if (chan->dar > 0xffffff) {
693: monitor.Print(x, y++, TA::On, "$%08x", chan->dar);
694: } else {
695: monitor.Print(x, y++, "$%06x", chan->dar);
696: }
697: // BTC
698: monitor.Print(x, y++, "$%04x", chan->btc);
699: // BAR
700: if (chan->bar > 0xffffff) {
701: monitor.Print(x, y++, TA::On, "$%08x", chan->bar);
702: } else {
703: monitor.Print(x, y++, "$%06x", chan->bar);
704: }
705:
706: // NIV
707: monitor.Print(x, y++, "$%02x", chan->niv);
708: // EIV
709: monitor.Print(x, y++, "$%02x", chan->eiv);
710:
711: // MFC
712: monitor.Print(x, y++, "$%02x", chan->mfc);
713: // CPR
714: monitor.Print(x, y++, "$%02x", chan->cpr);
715: // DFC
716: monitor.Print(x, y++, "$%02x", chan->dfc);
717: // BFC
718: monitor.Print(x, y++, "$%02x", chan->bfc);
719:
720: if (ch == 3) {
721: monitor.Print(x - 5, y++, "GCR: $%02x", dmac.gcr);
722: }
723: }
724: }
725:
726: // 4ビット分を表示する。MonitorUpdate の下請け
727: void
1.1.1.4 root 728: DMACDevice::MonitorReg4(TextScreen& monitor,
729: int x, int y, uint32 reg, const char * const *names)
1.1.1.2 root 730: {
731: for (int i = 0; i < 4; i++) {
732: bool b = reg & (1 << (3 - i));
1.1.1.3 root 733: monitor.Puts(x + i * 4, y, TA::OnOff(b), names[i]);
1.1.1.2 root 734: }
735: }
736:
737: /*static*/ const char * const
738: DMACDevice::errnames[] = {
739: //12345678901
740: "", // $00 No Error
741: "ConfigErr", // $01
742: "OperTiming", // $02
743: NULL, // $03
744: NULL, // $04
745: "AddrErrInMAR", // $05
746: "AddrErrInDAR", // $06
747: "AddrErrInBAR", // $07
748: NULL, // $08
749: "BusErrInMAR", // $09
750: "BusErrInDAR", // $0a
751: "BusErrInBAR", // $0b
752: NULL, // $0c
753: "CntErrInMTC", // $0d
754: NULL, // $0e
755: "CntErrInBTC", // $0f
756: "ExternAbort", // $10
757: "SoftAbort", // $11
758: };
759:
760: // Read と Peek とそれ以外からも呼ばれるので副作用を持たせてはいけない。
761: uint8
762: DMAC::Channel::PeekCSR() const
763: {
764: uint32 val;
765:
766: val = csr & 0xf0;
767: if (active) {
768: val |= CSR_ACT;
769: }
770: // PCT は PCL が High から Low に変わるとセット
771: if (prev_pcl == true && pcl == false) {
772: val |= CSR_PCT;
773: }
774: if (pcl) {
775: val |= CSR_PCS;
776: }
777: return val;
778: }
779:
1.1 root 780: void
1.1.1.2 root 781: DMAC::Channel::WriteCSR(uint32 data)
1.1 root 782: {
1.1.1.2 root 783: // 上位4ビットは %1 の書き込みでクリア
784: csr &= ~(data & 0xf0);
785:
786: // PCT も %1 の書き込みでクリア
787: // PCT は PCL が High → Low の時セットなので prev_pcl を下げればよい
788: if ((data & DMAC::CSR_PCT)) {
789: prev_pcl = false;
790: }
791:
792: parent->putlog(4, "#%d CSR <- $%02x (CSR = $%02x)", ch, data, PeekCSR());
793: }
794:
795: // Read と Peek から呼ばれるので副作用を持たせてはいけない。
796: uint8
797: DMAC::Channel::PeekCCR() const
798: {
799: uint32 val;
800:
801: val = ccr & 0xf0;
802: if (int_enable) {
803: val |= DMAC::CCR_INT;
804: }
805: return val;
1.1 root 806: }
807:
808: void
1.1.1.2 root 809: DMAC::Channel::WriteCCR(uint32 data)
1.1 root 810: {
1.1.1.2 root 811: // 割り込み許可ビットは常に反映
812: int_enable = (data & DMAC::CCR_INT);
813:
814: // SAB (Software Abort)
815: if ((data & DMAC::CCR_SAB)) {
816: // イベントを触るため親デバイスで処理する
817: parent->AbortTransfer(this);
818: }
819:
820: // HLT (Halt Operation)
821: if ((data & DMAC::CCR_HLT)) {
822: parent->putlog(0, "CCR HLT 未実装");
823: }
824:
825: // CNT (Continue Operation)
826: if ((data & DMAC::CCR_CNT)) {
827: parent->putlog(0, "CCR CNT 未実装");
828: }
829:
830: // STR (Start Operation)
831: if ((data & DMAC::CCR_STR)) {
832: StartTransfer();
833: }
1.1 root 834: }
835:
1.1.1.2 root 836: // 割り込み要因ビットをセットし、必要なら割り込みを上げる。
837: // PCL は割り込み条件を満たしている時だけ呼ぶこと。
838: // ここはレジスタに対する書き込みではない。
839: void
840: DMAC::Channel::SetINT(uint32 val)
841: {
842: int vector;
843:
844: csr |= val;
845:
846: // ERR ビットが立つと SAB をクリアする
847: if ((csr & CSR_ERR)) {
848: ccr &= ~CCR_SAB;
849: }
850:
851: if (int_enable) {
852: if ((csr & CSR_ERR)) {
853: vector = eiv;
854: } else {
855: vector = niv;
856: }
1.1.1.3 root 857: gMPU680x0->Interrupt(parent, 3, vector);
1.1.1.2 root 858: }
859: }
860:
1.1.1.5 ! root 861: // 転送開始 (チャンネル側)
1.1.1.2 root 862: void
863: DMAC::Channel::StartTransfer()
864: {
865: // CSR の COC,BTC,NDT,ERR が立ってたら開始しない
866: if ((csr & 0xf0) != 0) {
867: cer = CER_CONFIG; // ?
868: csr |= CSR_ERR;
869: return;
870: }
871:
872: active = true;
873:
874: // XXX CER をどこかでクリアしないといけないようだがどこだ?
875: cer = 0;
876:
877: // 転送方法は DPS(1bit) と SIZE(2bit) で合計 8通り。
878: // (その中にさらに転送方向が2通りずつあるけど)
879: //
880: // xfertype DPS SIZE
881: // 0 8bit 8bit packed
882: // 1 8bit 16bit
883: // 2 8bit 32bit
884: // 3 8bit 8bit
885: // 4 16bit 8bit packed
886: // 5 16bit 16bit
887: // 6 16bit 32bit
888: // 7 16bit 8bit
889: xfertype = (GetDPS() << 2) | GetSIZE();
890:
891: // 転送モード
892: switch (GetREQG()) {
893: case DMAC::OCR_REQG_AUTO_LIM:
894: PANIC("REQG_AUTO_LIM 未実装");
895: break;
896:
897: case DMAC::OCR_REQG_AUTO_MAX:
898: // 自発的に転送を開始する
1.1.1.5 ! root 899: parent->StartTransfer(this);
1.1.1.2 root 900: break;
901:
902: case DMAC::OCR_REQG_EXTERNAL:
903: case DMAC::OCR_REQG_AUTOFIRST:
904: PANIC("未実装 REQG");
905: break;
906:
907: default:
908: __unreachable();
909: }
910: }
911:
1.1.1.5 ! root 912: // 転送開始 (デバイス側)
! 913: // (チャンネルが転送開始する際にデバイス側の private 変数(event[])が必要に
! 914: // なるため、プロキシしている)
! 915: void
! 916: DMACDevice::StartTransfer(DMAC::Channel *chan)
! 917: {
! 918: Transfer(event[chan->ch]);
! 919: }
! 920:
1.1.1.2 root 921: // 転送
922: // (イベントを持つのでこれはデバイスクラスのメソッド)
923: void
1.1.1.5 ! root 924: DMACDevice::Transfer(Event& ev)
1.1.1.2 root 925: {
1.1.1.5 ! root 926: int& ch = ev.code;
1.1.1.2 root 927: DMAC::Channel *chan = &dmac.chan[ch];
928: int64 rv;
929:
930: putlog(4, "#%d Transfer (MTC=$%04x)", ch, chan->mtc);
931:
932: rv = 0;
933: switch (chan->xfertype) {
934: case 0: // 8ビットポート、8ビットサイズ、パック動作
935:
936: case 1: // 8ビットポート、16ビットサイズ
937:
938: case 2: // 8ビットポート、32ビットサイズ
939: PANIC("未実装 xfer type");
940:
941: case 3: // 8ビットポート、8ビットサイズ、パックなし動作
942: if (chan->GetDIR() == DMAC::OCR_DIR_MtoD) {
943: rv = TransferM8toD8(chan);
944: } else {
945: rv = TransferD8toM8(chan);
946: }
947: break;
948:
949: case 4: // 16ビットポート、8ビットサイズ、パック動作
950: case 5: // 16ビットポート、16ビットサイズ
951: case 6: // 16ビットポート、32ビットサイズ
952: case 7: // 16ビットポート、8ビットサイズ、パックなし動作
953: PANIC("未実装 xfer type");
954: }
955:
956: // XXX バスエラーは?
957: if (rv < 0) {
958: return;
959: }
960:
961: // バスエラーでなければカウンタを更新
962: // XXX とりあえず。後で書く
963: switch (chan->GetMAC()) {
964: case DMAC::SCR_COUNT_UP:
965: chan->mar += 1;
966: break;
967: case DMAC::SCR_COUNT_DOWN:
968: chan->mar -= 1;
969: break;
970: }
971: switch (chan->GetDAC()) {
972: case DMAC::SCR_COUNT_UP:
973: chan->dar += 1;
974: break;
975: case DMAC::SCR_COUNT_DOWN:
976: chan->dar -= 1;
977: break;
978: }
979:
980: chan->mtc--;
981: if (chan->mtc == 0) {
982: // 転送完了
983: chan->active = false;
984: chan->SetINT(DMAC::CSR_COC);
985: } else {
986: // 次回の転送
987: // XXX とりあえず 1us で1回の転送にする
1.1.1.5 ! root 988: ev.time = 1_usec;
! 989: ev.Start();
1.1.1.2 root 990: }
991: }
992:
993: // メモリから 8ビットデバイスへ (パックなし動作)
994: int64
995: DMACDevice::TransferM8toD8(DMAC::Channel *chan)
996: {
997: uint64 data;
998: int64 rv;
999:
1000: data = vm_phys_read_8(chan->mar);
1001: if ((int64)data < 0)
1002: return data;
1003: rv = vm_phys_write_8(chan->dar, data);
1004: if (rv < 0)
1005: return rv;
1006:
1007: return 0;
1008: }
1009:
1010: // 8ビットデバイスからメモリへ (パックなし動作)
1011: int64
1012: DMACDevice::TransferD8toM8(DMAC::Channel *chan)
1013: {
1014: uint64 data;
1015: int64 rv;
1016:
1017: data = vm_phys_read_8(chan->dar);
1018: if ((int64)data < 0)
1019: return data;
1020: rv = vm_phys_write_8(chan->mar, data);
1021: if (rv < 0)
1022: return rv;
1023:
1024: return 0;
1025: }
1026:
1027: // ソフトウェアアボート
1028: // (イベントを持つのでこれはデバイスクラスのメソッド)
1029: void
1030: DMACDevice::AbortTransfer(DMAC::Channel *chan)
1031: {
1032: int ch = chan->ch;
1033:
1034: putlog(2, "CCR SAB ソフトウェアアボート");
1035:
1036: // %1 を書き込むことで実際には SAB はセットされるが、ERR が立つと
1037: // SAB をクリアする動作のため、書き込んだ %1 が読めることはない。
1038: // ここでは SAB ビットのセットを省略。
1039:
1040: event[ch].Stop();
1041: chan->active = false;
1042: chan->cer = DMAC::CER_SOFT_ABORT;
1043: chan->SetINT(DMAC::CSR_ERR);
1044: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.