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