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