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