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