|
|
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: #include "mystring.h"
12:
13: std::unique_ptr<DMACDevice> gDMAC;
1.1 root 14:
15: DMACDevice::DMACDevice()
16: {
17: logname = "dmac";
18: devname = "DMAC";
19: devaddr = baseaddr;
20: devlen = 0x2000;
1.1.1.2 root 21:
1.1.1.4 root 22: monitor_size = nnSize(80, 30);
1.1.1.2 root 23:
24: for (int i = 0; i < countof(dmac.chan); i++) {
25: dmac.chan[i].ch = i;
26: dmac.chan[i].parent = this;
27: }
28: dmac.chan[0].desc = "FD";
29: dmac.chan[1].desc = "HD";
30: dmac.chan[2].desc = "User";
31: dmac.chan[3].desc = "ADPCM";
32:
33: for (int i = 0; i < countof(event); i++) {
34: event[i].dev = this;
35: event[i].func = (DeviceCallback_t)&DMACDevice::Transfer;
36: event[i].SetName(string_format("DMAC #%d", i));
37: event[i].code = i;
38: }
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: // イベントをすべて停止
72: for (int i = 0; i < countof(event); i++) {
73: event[i].Stop();
74: }
75: }
76:
1.1 root 77: uint64
1.1.1.3 root 78: DMACDevice::Read(uint32 addr)
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.3 root 85: ch = addr / 0x40;
1.1.1.2 root 86: DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.3 root 87: int n = addr % 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.3 root 237: DMACDevice::Write(uint32 addr, 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.3 root 243: ch = addr / 0x40;
1.1.1.2 root 244: DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.3 root 245: int n = addr % 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.3 root 390: DMACDevice::Peek(uint32 addr)
1.1 root 391: {
392: uint8 data;
393: int ch;
394:
1.1.1.3 root 395: ch = addr / 0x40;
1.1.1.2 root 396: const DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.3 root 397: int n = addr % 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
518: DMACDevice::MonitorUpdate(TextScreen& monitor)
1.1.1.2 root 519: {
520: int x;
521: int y;
522:
523: monitor.Clear();
524:
525: y = 1;
1.1.1.3 root 526: monitor.Puts(0, y++, "CSR");
1.1.1.2 root 527: y += 2;
1.1.1.3 root 528: monitor.Puts(0, y++, "CER");
529: monitor.Puts(0, y++, "DCR:XRM");
530: monitor.Puts(0, y++, "DCR:DTYP");
531: monitor.Puts(0, y++, "DCR:DPS");
532: monitor.Puts(0, y++, "DCR:PCL");
533: monitor.Puts(0, y++, "OCR:DIR");
534: monitor.Puts(0, y++, "OCR:SIZE");
535: monitor.Puts(0, y++, "OCR:CHAIN");
536: monitor.Puts(0, y++, "OCR:REQG");
537: monitor.Puts(0, y++, "SCR:MAC");
538: monitor.Puts(0, y++, "SCR:DAC");
539: monitor.Puts(0, y++, "CCR");
1.1.1.2 root 540: y += 2;
1.1.1.3 root 541: monitor.Puts(0, y++, "MTC");
542: monitor.Puts(0, y++, "MAR");
543: monitor.Puts(0, y++, "DAR");
544: monitor.Puts(0, y++, "BTC");
545: monitor.Puts(0, y++, "BAR");
546: monitor.Puts(0, y++, "NIV");
547: monitor.Puts(0, y++, "EIV");
548: monitor.Puts(0, y++, "MFC");
549: monitor.Puts(0, y++, "CPR");
550: monitor.Puts(0, y++, "DFC");
551: monitor.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.3 root 560: monitor.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();
565: monitor.Print(x, y++, "$%02x", val);
566: static const char * const csrname[] = {
567: "COC", "BTC", "NDT", "ERR", "ACT", "---", "PCT", "PCS",
568: };
1.1.1.4 root 569: MonitorReg4(monitor, x, y++, val >> 4, &csrname[0]);
570: MonitorReg4(monitor, 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: }
580: monitor.Print(x, y, "$%02x", chan->cer);
581: if (val > 0) {
582: monitor.Print(x + 3, y, ":%s", e);
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;
595: monitor.Print(x, y++, "%d:%s", val, dcr_xrm[val]);
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;
606: monitor.Print(x, y++, "%d:%s", val, dcr_dtyp[val]);
607:
608: // DCR:DPS
609: static const char * const dcr_dps[] = {
610: //1234567890123
611: "8bit",
612: "16bit",
613: };
614: val = (chan->dcr >> 3) & 1;
615: monitor.Print(x, y++, "%d:%s", val, dcr_dps[val]);
616:
617: // DCR:PCL
618: monitor.Print(x, y++, "XXX PCL");
619:
620: // OCR:DIR
621: static const char * const ocr_dir[] = {
622: //1234567890123
623: "MemoryToDevice",
624: "DeviceToMemory",
625: };
626: val = (chan->ocr >> 7);
627: monitor.Print(x, y++, "%d:%s", val, ocr_dir[val]);
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;
638: monitor.Print(x, y++, "%d:%s", val, ocr_size[val]);
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;
649: monitor.Print(x, y++, "%d:%s", val, ocr_chain[val]);
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);
660: monitor.Print(x, y++, "%d:%s", val, ocr_reqg[val]);
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;
671: monitor.Print(x, y++, "%d:%s", val, scr_xac[val]);
672: val = chan->scr & 3;
673: monitor.Print(x, y++, "%d:%s", val, scr_xac[val]);
674:
675: // CCR
1.1.1.6 ! root 676: val = chan->ccr;
1.1.1.2 root 677: monitor.Print(x, y++, "$%02x", val);
678: static const char * const ccrnames[] = {
679: "STR", "CNT", "HLT", "SAB", "INT", "---", "---", "---",
680: };
1.1.1.4 root 681: MonitorReg4(monitor, x, y++, (val >> 4), &ccrnames[0]);
682: MonitorReg4(monitor, x, y++, (val & 0xff), &ccrnames[4]);
1.1.1.2 root 683:
684: // MTC
685: monitor.Print(x, y++, "$%04x", chan->mtc);
686: // MAR
687: // X680x0 がターゲットなので24bit超える設定は目立たせる
688: if (chan->mar > 0xffffff) {
689: monitor.Print(x, y++, TA::On, "$%08x", chan->mar);
690: } else {
691: monitor.Print(x, y++, "$%06x", chan->mar);
692: }
693: // DAR
694: if (chan->dar > 0xffffff) {
695: monitor.Print(x, y++, TA::On, "$%08x", chan->dar);
696: } else {
697: monitor.Print(x, y++, "$%06x", chan->dar);
698: }
699: // BTC
700: monitor.Print(x, y++, "$%04x", chan->btc);
701: // BAR
702: if (chan->bar > 0xffffff) {
703: monitor.Print(x, y++, TA::On, "$%08x", chan->bar);
704: } else {
705: monitor.Print(x, y++, "$%06x", chan->bar);
706: }
707:
708: // NIV
709: monitor.Print(x, y++, "$%02x", chan->niv);
710: // EIV
711: monitor.Print(x, y++, "$%02x", chan->eiv);
712:
713: // MFC
714: monitor.Print(x, y++, "$%02x", chan->mfc);
715: // CPR
716: monitor.Print(x, y++, "$%02x", chan->cpr);
717: // DFC
718: monitor.Print(x, y++, "$%02x", chan->dfc);
719: // BFC
720: monitor.Print(x, y++, "$%02x", chan->bfc);
721:
722: if (ch == 3) {
723: monitor.Print(x - 5, y++, "GCR: $%02x", dmac.gcr);
724: }
725: }
726: }
727:
728: // 4ビット分を表示する。MonitorUpdate の下請け
729: void
1.1.1.4 root 730: DMACDevice::MonitorReg4(TextScreen& monitor,
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++) {
734: bool b = reg & (1 << (3 - i));
1.1.1.3 root 735: monitor.Puts(x + i * 4, y, TA::OnOff(b), names[i]);
1.1.1.2 root 736: }
737: }
738:
739: /*static*/ const char * const
740: DMACDevice::errnames[] = {
741: //12345678901
742: "", // $00 No Error
743: "ConfigErr", // $01
744: "OperTiming", // $02
745: NULL, // $03
746: NULL, // $04
747: "AddrErrInMAR", // $05
748: "AddrErrInDAR", // $06
749: "AddrErrInBAR", // $07
750: NULL, // $08
751: "BusErrInMAR", // $09
752: "BusErrInDAR", // $0a
753: "BusErrInBAR", // $0b
754: NULL, // $0c
755: "CntErrInMTC", // $0d
756: NULL, // $0e
757: "CntErrInBTC", // $0f
758: "ExternAbort", // $10
759: "SoftAbort", // $11
760: };
761:
762: // Read と Peek とそれ以外からも呼ばれるので副作用を持たせてはいけない。
763: uint8
764: DMAC::Channel::PeekCSR() const
765: {
766: uint32 val;
767:
768: val = csr & 0xf0;
769: if (active) {
770: val |= CSR_ACT;
771: }
772: // PCT は PCL が High から Low に変わるとセット
773: if (prev_pcl == true && pcl == false) {
774: val |= CSR_PCT;
775: }
776: if (pcl) {
777: val |= CSR_PCS;
778: }
779: return val;
780: }
781:
1.1.1.6 ! root 782: // CSR への書き込み。
! 783: // CSR への書き込みによって割り込み信号線が変化するかも知れないので
! 784: // この後呼び出し側が ChangeInterrupt() を呼ぶこと。
1.1 root 785: void
1.1.1.2 root 786: DMAC::Channel::WriteCSR(uint32 data)
1.1 root 787: {
1.1.1.2 root 788: // 上位4ビットは %1 の書き込みでクリア
789: csr &= ~(data & 0xf0);
790:
791: // PCT も %1 の書き込みでクリア
792: // PCT は PCL が High → Low の時セットなので prev_pcl を下げればよい
793: if ((data & DMAC::CSR_PCT)) {
794: prev_pcl = false;
795: }
796:
797: parent->putlog(4, "#%d CSR <- $%02x (CSR = $%02x)", ch, data, PeekCSR());
798: }
799:
1.1.1.6 ! root 800: // CCR への書き込み。
! 801: // CCR への書き込みによって割り込み信号線が変化するかも知れないので
! 802: // この後呼び出し側が ChangeInterrupt() を呼ぶこと。
1.1 root 803: void
1.1.1.2 root 804: DMAC::Channel::WriteCCR(uint32 data)
1.1 root 805: {
1.1.1.2 root 806: // 割り込み許可ビットは常に反映
1.1.1.6 ! root 807: ccr &= ~DMAC::CCR_INT;
! 808: ccr |= (data & DMAC::CCR_INT);
1.1.1.2 root 809:
810: // SAB (Software Abort)
811: if ((data & DMAC::CCR_SAB)) {
812: // イベントを触るため親デバイスで処理する
813: parent->AbortTransfer(this);
814: }
815:
816: // HLT (Halt Operation)
817: if ((data & DMAC::CCR_HLT)) {
818: parent->putlog(0, "CCR HLT 未実装");
819: }
820:
821: // CNT (Continue Operation)
822: if ((data & DMAC::CCR_CNT)) {
823: parent->putlog(0, "CCR CNT 未実装");
824: }
825:
826: // STR (Start Operation)
827: if ((data & DMAC::CCR_STR)) {
828: StartTransfer();
829: }
1.1 root 830: }
831:
1.1.1.5 root 832: // 転送開始 (チャンネル側)
1.1.1.2 root 833: void
834: DMAC::Channel::StartTransfer()
835: {
836: // CSR の COC,BTC,NDT,ERR が立ってたら開始しない
837: if ((csr & 0xf0) != 0) {
838: cer = CER_CONFIG; // ?
839: csr |= CSR_ERR;
840: return;
841: }
842:
843: active = true;
844:
845: // XXX CER をどこかでクリアしないといけないようだがどこだ?
846: cer = 0;
847:
848: // 転送方法は DPS(1bit) と SIZE(2bit) で合計 8通り。
849: // (その中にさらに転送方向が2通りずつあるけど)
850: //
851: // xfertype DPS SIZE
852: // 0 8bit 8bit packed
853: // 1 8bit 16bit
854: // 2 8bit 32bit
855: // 3 8bit 8bit
856: // 4 16bit 8bit packed
857: // 5 16bit 16bit
858: // 6 16bit 32bit
859: // 7 16bit 8bit
860: xfertype = (GetDPS() << 2) | GetSIZE();
861:
862: // 転送モード
863: switch (GetREQG()) {
864: case DMAC::OCR_REQG_AUTO_LIM:
865: PANIC("REQG_AUTO_LIM 未実装");
866: break;
867:
868: case DMAC::OCR_REQG_AUTO_MAX:
869: // 自発的に転送を開始する
1.1.1.5 root 870: parent->StartTransfer(this);
1.1.1.2 root 871: break;
872:
873: case DMAC::OCR_REQG_EXTERNAL:
874: case DMAC::OCR_REQG_AUTOFIRST:
875: PANIC("未実装 REQG");
876: break;
877:
878: default:
879: __unreachable();
880: }
881: }
882:
1.1.1.5 root 883: // 転送開始 (デバイス側)
884: // (チャンネルが転送開始する際にデバイス側の private 変数(event[])が必要に
885: // なるため、プロキシしている)
886: void
887: DMACDevice::StartTransfer(DMAC::Channel *chan)
888: {
889: Transfer(event[chan->ch]);
890: }
891:
1.1.1.2 root 892: // 転送
893: // (イベントを持つのでこれはデバイスクラスのメソッド)
894: void
1.1.1.5 root 895: DMACDevice::Transfer(Event& ev)
1.1.1.2 root 896: {
1.1.1.5 root 897: int& ch = ev.code;
1.1.1.2 root 898: DMAC::Channel *chan = &dmac.chan[ch];
899: int64 rv;
900:
901: putlog(4, "#%d Transfer (MTC=$%04x)", ch, chan->mtc);
902:
903: rv = 0;
904: switch (chan->xfertype) {
905: case 0: // 8ビットポート、8ビットサイズ、パック動作
906:
907: case 1: // 8ビットポート、16ビットサイズ
908:
909: case 2: // 8ビットポート、32ビットサイズ
910: PANIC("未実装 xfer type");
911:
912: case 3: // 8ビットポート、8ビットサイズ、パックなし動作
913: if (chan->GetDIR() == DMAC::OCR_DIR_MtoD) {
914: rv = TransferM8toD8(chan);
915: } else {
916: rv = TransferD8toM8(chan);
917: }
918: break;
919:
920: case 4: // 16ビットポート、8ビットサイズ、パック動作
921: case 5: // 16ビットポート、16ビットサイズ
922: case 6: // 16ビットポート、32ビットサイズ
923: case 7: // 16ビットポート、8ビットサイズ、パックなし動作
924: PANIC("未実装 xfer type");
925: }
926:
927: // XXX バスエラーは?
928: if (rv < 0) {
929: return;
930: }
931:
932: // バスエラーでなければカウンタを更新
933: // XXX とりあえず。後で書く
934: switch (chan->GetMAC()) {
935: case DMAC::SCR_COUNT_UP:
936: chan->mar += 1;
937: break;
938: case DMAC::SCR_COUNT_DOWN:
939: chan->mar -= 1;
940: break;
941: }
942: switch (chan->GetDAC()) {
943: case DMAC::SCR_COUNT_UP:
944: chan->dar += 1;
945: break;
946: case DMAC::SCR_COUNT_DOWN:
947: chan->dar -= 1;
948: break;
949: }
950:
951: chan->mtc--;
952: if (chan->mtc == 0) {
953: // 転送完了
1.1.1.6 ! root 954: chan->csr |= DMAC::CSR_COC;
! 955: ChangeInterrupt();
1.1.1.2 root 956: } else {
957: // 次回の転送
958: // XXX とりあえず 1us で1回の転送にする
1.1.1.5 root 959: ev.time = 1_usec;
960: ev.Start();
1.1.1.2 root 961: }
962: }
963:
964: // メモリから 8ビットデバイスへ (パックなし動作)
965: int64
966: DMACDevice::TransferM8toD8(DMAC::Channel *chan)
967: {
968: uint64 data;
969: int64 rv;
970:
971: data = vm_phys_read_8(chan->mar);
972: if ((int64)data < 0)
973: return data;
974: rv = vm_phys_write_8(chan->dar, data);
975: if (rv < 0)
976: return rv;
977:
978: return 0;
979: }
980:
981: // 8ビットデバイスからメモリへ (パックなし動作)
982: int64
983: DMACDevice::TransferD8toM8(DMAC::Channel *chan)
984: {
985: uint64 data;
986: int64 rv;
987:
988: data = vm_phys_read_8(chan->dar);
989: if ((int64)data < 0)
990: return data;
991: rv = vm_phys_write_8(chan->mar, data);
992: if (rv < 0)
993: return rv;
994:
995: return 0;
996: }
997:
998: // ソフトウェアアボート
999: // (イベントを持つのでこれはデバイスクラスのメソッド)
1000: void
1001: DMACDevice::AbortTransfer(DMAC::Channel *chan)
1002: {
1003: int ch = chan->ch;
1004:
1005: putlog(2, "CCR SAB ソフトウェアアボート");
1006:
1007: // %1 を書き込むことで実際には SAB はセットされるが、ERR が立つと
1008: // SAB をクリアする動作のため、書き込んだ %1 が読めることはない。
1009: // ここでは SAB ビットのセットを省略。
1010:
1011: event[ch].Stop();
1012: chan->cer = DMAC::CER_SOFT_ABORT;
1.1.1.6 ! root 1013: // ERR ビットが立つと SAB をクリアする
! 1014: chan->csr |= DMAC::CSR_ERR;
! 1015: chan->ccr &= ~DMAC::CCR_SAB;
! 1016: ChangeInterrupt();
! 1017: }
! 1018:
! 1019: // 割り込み信号線の状態を変える。
! 1020: void
! 1021: DMACDevice::ChangeInterrupt()
! 1022: {
! 1023: bool irq = false;
! 1024:
! 1025: for (int ch = 0; ch < countof(dmac.chan); ch++) {
! 1026: DMAC::Channel *chan = &dmac.chan[ch];
! 1027:
! 1028: if ((chan->ccr & DMAC::CCR_INT) && chan->IsINTR()) {
! 1029: irq = true;
! 1030: }
! 1031: }
! 1032: gInterrupt->ChangeINT(this, irq);
! 1033: }
! 1034:
! 1035: // 割り込みアクノリッジ
! 1036: int
! 1037: DMACDevice::InterruptAcknowledge()
! 1038: {
! 1039: // XXX CPR のプライオリティは未対応、とりあえず前から順
! 1040: for (int ch = 0; ch < countof(dmac.chan); ch++) {
! 1041: DMAC::Channel *chan = &dmac.chan[ch];
! 1042:
! 1043: if (chan->active) {
! 1044: if ((chan->csr & DMAC::CSR_ERR)) {
! 1045: return chan->eiv;
! 1046: } else {
! 1047: return chan->niv;
! 1048: }
! 1049: chan->active = false;
! 1050: }
! 1051: }
! 1052: // XXX 誰もいなかったら?
! 1053: PANIC("InterruptAcknowledge no active channels?");
1.1.1.2 root 1054: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.