|
|
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:
21: monitor.Init(80, 30);
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.2 root 478: bool
479: DMACDevice::MonitorUpdate()
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: };
530: MonitorReg4(x, y++, val >> 4, &csrname[0]);
531: MonitorReg4(x, y++, val & 0xff, &csrname[4]);
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: };
642: MonitorReg4(x, y++, (val >> 4), &ccrnames[0]);
643: MonitorReg4(x, y++, (val & 0xff), &ccrnames[4]);
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: return true;
689: }
690:
691: // 4ビット分を表示する。MonitorUpdate の下請け
692: void
693: DMACDevice::MonitorReg4(int x, int y, uint32 reg, const char * const *names)
694: {
695: for (int i = 0; i < 4; i++) {
696: bool b = reg & (1 << (3 - i));
1.1.1.3 ! root 697: monitor.Puts(x + i * 4, y, TA::OnOff(b), names[i]);
1.1.1.2 root 698: }
699: }
700:
701: /*static*/ const char * const
702: DMACDevice::errnames[] = {
703: //12345678901
704: "", // $00 No Error
705: "ConfigErr", // $01
706: "OperTiming", // $02
707: NULL, // $03
708: NULL, // $04
709: "AddrErrInMAR", // $05
710: "AddrErrInDAR", // $06
711: "AddrErrInBAR", // $07
712: NULL, // $08
713: "BusErrInMAR", // $09
714: "BusErrInDAR", // $0a
715: "BusErrInBAR", // $0b
716: NULL, // $0c
717: "CntErrInMTC", // $0d
718: NULL, // $0e
719: "CntErrInBTC", // $0f
720: "ExternAbort", // $10
721: "SoftAbort", // $11
722: };
723:
724: // Read と Peek とそれ以外からも呼ばれるので副作用を持たせてはいけない。
725: uint8
726: DMAC::Channel::PeekCSR() const
727: {
728: uint32 val;
729:
730: val = csr & 0xf0;
731: if (active) {
732: val |= CSR_ACT;
733: }
734: // PCT は PCL が High から Low に変わるとセット
735: if (prev_pcl == true && pcl == false) {
736: val |= CSR_PCT;
737: }
738: if (pcl) {
739: val |= CSR_PCS;
740: }
741: return val;
742: }
743:
1.1 root 744: void
1.1.1.2 root 745: DMAC::Channel::WriteCSR(uint32 data)
1.1 root 746: {
1.1.1.2 root 747: // 上位4ビットは %1 の書き込みでクリア
748: csr &= ~(data & 0xf0);
749:
750: // PCT も %1 の書き込みでクリア
751: // PCT は PCL が High → Low の時セットなので prev_pcl を下げればよい
752: if ((data & DMAC::CSR_PCT)) {
753: prev_pcl = false;
754: }
755:
756: parent->putlog(4, "#%d CSR <- $%02x (CSR = $%02x)", ch, data, PeekCSR());
757: }
758:
759: // Read と Peek から呼ばれるので副作用を持たせてはいけない。
760: uint8
761: DMAC::Channel::PeekCCR() const
762: {
763: uint32 val;
764:
765: val = ccr & 0xf0;
766: if (int_enable) {
767: val |= DMAC::CCR_INT;
768: }
769: return val;
1.1 root 770: }
771:
772: void
1.1.1.2 root 773: DMAC::Channel::WriteCCR(uint32 data)
1.1 root 774: {
1.1.1.2 root 775: // 割り込み許可ビットは常に反映
776: int_enable = (data & DMAC::CCR_INT);
777:
778: // SAB (Software Abort)
779: if ((data & DMAC::CCR_SAB)) {
780: // イベントを触るため親デバイスで処理する
781: parent->AbortTransfer(this);
782: }
783:
784: // HLT (Halt Operation)
785: if ((data & DMAC::CCR_HLT)) {
786: parent->putlog(0, "CCR HLT 未実装");
787: }
788:
789: // CNT (Continue Operation)
790: if ((data & DMAC::CCR_CNT)) {
791: parent->putlog(0, "CCR CNT 未実装");
792: }
793:
794: // STR (Start Operation)
795: if ((data & DMAC::CCR_STR)) {
796: StartTransfer();
797: }
1.1 root 798: }
799:
1.1.1.2 root 800: // 割り込み要因ビットをセットし、必要なら割り込みを上げる。
801: // PCL は割り込み条件を満たしている時だけ呼ぶこと。
802: // ここはレジスタに対する書き込みではない。
803: void
804: DMAC::Channel::SetINT(uint32 val)
805: {
806: int vector;
807:
808: csr |= val;
809:
810: // ERR ビットが立つと SAB をクリアする
811: if ((csr & CSR_ERR)) {
812: ccr &= ~CCR_SAB;
813: }
814:
815: if (int_enable) {
816: if ((csr & CSR_ERR)) {
817: vector = eiv;
818: } else {
819: vector = niv;
820: }
1.1.1.3 ! root 821: gMPU680x0->Interrupt(parent, 3, vector);
1.1.1.2 root 822: }
823: }
824:
825: // 転送開始
826: void
827: DMAC::Channel::StartTransfer()
828: {
829: // CSR の COC,BTC,NDT,ERR が立ってたら開始しない
830: if ((csr & 0xf0) != 0) {
831: cer = CER_CONFIG; // ?
832: csr |= CSR_ERR;
833: return;
834: }
835:
836: active = true;
837:
838: // XXX CER をどこかでクリアしないといけないようだがどこだ?
839: cer = 0;
840:
841: // 転送方法は DPS(1bit) と SIZE(2bit) で合計 8通り。
842: // (その中にさらに転送方向が2通りずつあるけど)
843: //
844: // xfertype DPS SIZE
845: // 0 8bit 8bit packed
846: // 1 8bit 16bit
847: // 2 8bit 32bit
848: // 3 8bit 8bit
849: // 4 16bit 8bit packed
850: // 5 16bit 16bit
851: // 6 16bit 32bit
852: // 7 16bit 8bit
853: xfertype = (GetDPS() << 2) | GetSIZE();
854:
855: // 転送モード
856: switch (GetREQG()) {
857: case DMAC::OCR_REQG_AUTO_LIM:
858: PANIC("REQG_AUTO_LIM 未実装");
859: break;
860:
861: case DMAC::OCR_REQG_AUTO_MAX:
862: // 自発的に転送を開始する
863: parent->Transfer(ch);
864: break;
865:
866: case DMAC::OCR_REQG_EXTERNAL:
867: case DMAC::OCR_REQG_AUTOFIRST:
868: PANIC("未実装 REQG");
869: break;
870:
871: default:
872: __unreachable();
873: }
874: }
875:
876: // 転送
877: // (イベントを持つのでこれはデバイスクラスのメソッド)
878: void
879: DMACDevice::Transfer(int ch)
880: {
881: DMAC::Channel *chan = &dmac.chan[ch];
882: int64 rv;
883:
884: putlog(4, "#%d Transfer (MTC=$%04x)", ch, chan->mtc);
885:
886: rv = 0;
887: switch (chan->xfertype) {
888: case 0: // 8ビットポート、8ビットサイズ、パック動作
889:
890: case 1: // 8ビットポート、16ビットサイズ
891:
892: case 2: // 8ビットポート、32ビットサイズ
893: PANIC("未実装 xfer type");
894:
895: case 3: // 8ビットポート、8ビットサイズ、パックなし動作
896: if (chan->GetDIR() == DMAC::OCR_DIR_MtoD) {
897: rv = TransferM8toD8(chan);
898: } else {
899: rv = TransferD8toM8(chan);
900: }
901: break;
902:
903: case 4: // 16ビットポート、8ビットサイズ、パック動作
904: case 5: // 16ビットポート、16ビットサイズ
905: case 6: // 16ビットポート、32ビットサイズ
906: case 7: // 16ビットポート、8ビットサイズ、パックなし動作
907: PANIC("未実装 xfer type");
908: }
909:
910: // XXX バスエラーは?
911: if (rv < 0) {
912: return;
913: }
914:
915: // バスエラーでなければカウンタを更新
916: // XXX とりあえず。後で書く
917: switch (chan->GetMAC()) {
918: case DMAC::SCR_COUNT_UP:
919: chan->mar += 1;
920: break;
921: case DMAC::SCR_COUNT_DOWN:
922: chan->mar -= 1;
923: break;
924: }
925: switch (chan->GetDAC()) {
926: case DMAC::SCR_COUNT_UP:
927: chan->dar += 1;
928: break;
929: case DMAC::SCR_COUNT_DOWN:
930: chan->dar -= 1;
931: break;
932: }
933:
934: chan->mtc--;
935: if (chan->mtc == 0) {
936: // 転送完了
937: chan->active = false;
938: chan->SetINT(DMAC::CSR_COC);
939: } else {
940: // 次回の転送
941: // XXX とりあえず 1us で1回の転送にする
942: event[ch].time = 1_usec;
943: event[ch].Start();
944: }
945: }
946:
947: // メモリから 8ビットデバイスへ (パックなし動作)
948: int64
949: DMACDevice::TransferM8toD8(DMAC::Channel *chan)
950: {
951: uint64 data;
952: int64 rv;
953:
954: data = vm_phys_read_8(chan->mar);
955: if ((int64)data < 0)
956: return data;
957: rv = vm_phys_write_8(chan->dar, data);
958: if (rv < 0)
959: return rv;
960:
961: return 0;
962: }
963:
964: // 8ビットデバイスからメモリへ (パックなし動作)
965: int64
966: DMACDevice::TransferD8toM8(DMAC::Channel *chan)
967: {
968: uint64 data;
969: int64 rv;
970:
971: data = vm_phys_read_8(chan->dar);
972: if ((int64)data < 0)
973: return data;
974: rv = vm_phys_write_8(chan->mar, data);
975: if (rv < 0)
976: return rv;
977:
978: return 0;
979: }
980:
981: // ソフトウェアアボート
982: // (イベントを持つのでこれはデバイスクラスのメソッド)
983: void
984: DMACDevice::AbortTransfer(DMAC::Channel *chan)
985: {
986: int ch = chan->ch;
987:
988: putlog(2, "CCR SAB ソフトウェアアボート");
989:
990: // %1 を書き込むことで実際には SAB はセットされるが、ERR が立つと
991: // SAB をクリアする動作のため、書き込んだ %1 が読めることはない。
992: // ここでは SAB ビットのセットを省略。
993:
994: event[ch].Stop();
995: chan->active = false;
996: chan->cer = DMAC::CER_SOFT_ABORT;
997: chan->SetINT(DMAC::CSR_ERR);
998: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.