|
|
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:
1.1.1.10 root 7: //
8: // DMAC (HD63450)
9: //
10:
1.1 root 11: #include "dmac.h"
1.1.1.11 root 12: #include "adpcm.h"
13: #include "fdc.h"
1.1.1.6 root 14: #include "interrupt.h"
1.1.1.12 root 15: #include "mainbus.h"
1.1.1.10 root 16: #include "mpu.h"
17: #include "scheduler.h"
18:
19: // time 時間後に呼び出すコールバックをセットする。
20: // func の書式が面倒なのを省略して書きたいため。
1.1.1.13! root 21: #define CallAfter(func_, time_, wait_) do { \
1.1.1.10 root 22: event.func = ToEventCallback(&DMACDevice::func_); \
1.1.1.13! root 23: event.time = time_ * 80_nsec + wait_; \
1.1.1.12 root 24: scheduler->StartEvent(event); \
1.1.1.10 root 25: } while (0)
1.1.1.2 root 26:
1.1.1.13! root 27: // InsideOut p.135
! 28: static const busdata read_wait = busdata::Wait(37 * 40_nsec);
! 29: static const busdata write_wait = busdata::Wait(31 * 40_nsec);
! 30:
1.1.1.10 root 31: // コンストラクタ
1.1 root 32: DMACDevice::DMACDevice()
1.1.1.12 root 33: : inherited(OBJ_DMAC)
1.1 root 34: {
1.1.1.11 root 35: for (int i = 0; i < channel.size(); i++) {
36: channel[i].ch = i;
37: }
38: channel[0].desc = "FD";
39: channel[1].desc = "HD";
40: channel[2].desc = "User";
41: channel[3].desc = "ADPCM";
42:
43: // PCL 信号線
44: // #0 はスーパーインポーズしてなければ常に Low
45: channel[0].pcl_pin = false;
46: channel[0].pcl_prev = false;
47: // #1 はプルアップされているので常に High
48: channel[1].pcl_pin = true;
49: channel[1].pcl_prev = true;
50: // #2 は外部スロット用だが未接続なので High
51: channel[2].pcl_pin = true;
52: channel[2].pcl_prev = true;
53: // #3 は未対応
1.1.1.2 root 54:
1.1.1.10 root 55: event.Regist("DMAC");
1.1.1.8 root 56:
1.1.1.10 root 57: monitor.func = ToMonitorCallback(&DMACDevice::MonitorUpdate);
1.1.1.11 root 58: monitor.SetSize(80, 34);
1.1.1.8 root 59: monitor.Regist(ID_MONITOR_DMAC);
1.1 root 60: }
61:
1.1.1.10 root 62: // デストラクタ
1.1 root 63: DMACDevice::~DMACDevice()
64: {
1.1.1.12 root 65: }
66:
67: // 初期化
68: bool
69: DMACDevice::Init()
70: {
71: if (inherited::Init() == false) {
72: return false;
73: }
74:
75: adpcm = GetADPCMDevice();
76: fdc = GetFDCDevice();
77: interrupt = GetInterruptDevice();
78: mainbus = GetMainbusDevice();
79:
80: return true;
1.1 root 81: }
82:
1.1.1.10 root 83: // リセット
1.1.1.5 root 84: void
1.1.1.10 root 85: DMACDevice::ResetHard(bool poweron)
1.1.1.5 root 86: {
1.1.1.11 root 87: putlog(2, "Reset");
1.1.1.5 root 88:
89: // Clears GCR, DCR, OCR, SCR, CCR, CSR, CPR and CER for all channels.
90: // NIV and EIV are all set to $0F (uninitialized interrupt vector).
91: // MTC, MAR, DAR, BTC, BAR, MFC, DFC and BFC are not affected.
92:
1.1.1.11 root 93: gcr = 0;
94: for (int ch = 0; ch < channel.size(); ch++) {
95: DMACChan *chan = &channel[ch];
96: chan->SetDCR(0);
97: chan->SetOCR(0);
98: chan->SetSCR(0);
99: chan->SetCCR(0);
1.1.1.5 root 100: chan->csr = 0;
101: chan->active = false;
102: chan->cpr = 0;
103: chan->cer = 0;
104:
105: chan->niv = 0x0f;
106: chan->eiv = 0x0f;
107:
1.1.1.10 root 108: chan->priority = 0;
1.1.1.5 root 109: }
1.1.1.13! root 110: ChangeInterrupt();
1.1.1.10 root 111:
112: // イベントを停止
113: event.SetName("DMAC");
1.1.1.12 root 114: scheduler->StopEvent(event);
1.1.1.5 root 115: }
116:
1.1.1.13! root 117: busdata
1.1.1.11 root 118: DMACDevice::Read8(uint32 addr)
1.1 root 119: {
1.1.1.13! root 120: busdata data;
1.1.1.5 root 121:
1.1.1.11 root 122: uint32 offset = addr & 0xff;
123: int ch = offset / 0x40;
1.1.1.7 root 124: int n = offset % 0x40;
1.1.1.11 root 125: DMACChan *chan = &channel[ch];
126:
1.1 root 127: switch (n) {
128: case DMAC::CSR:
1.1.1.11 root 129: data = chan->GetCSR();
1.1.1.13! root 130: putlog(3, "#%d CSR -> $%02x", ch, data.Data());
1.1 root 131: break;
132:
133: case DMAC::CER:
134: data = chan->cer;
1.1.1.13! root 135: putlog(3, "#%d CER -> $%02x", ch, data.Data());
1.1 root 136: break;
137:
138: case DMAC::DCR:
1.1.1.11 root 139: data = chan->GetDCR();
1.1.1.13! root 140: putlog(3, "#%d DCR -> $%02x", ch, data.Data());
1.1 root 141: break;
142:
143: case DMAC::OCR:
1.1.1.11 root 144: data = chan->GetOCR();
1.1.1.13! root 145: putlog(3, "#%d OCR -> $%02x", ch, data.Data());
1.1 root 146: break;
147:
148: case DMAC::SCR:
1.1.1.11 root 149: data = chan->GetSCR();
1.1.1.13! root 150: putlog(3, "#%d SCR -> $%02x", ch, data.Data());
1.1 root 151: break;
152:
153: case DMAC::CCR:
1.1.1.11 root 154: data = chan->GetCCR();
1.1.1.13! root 155: putlog(3, "#%d CCR -> $%02x", ch, data.Data());
1.1 root 156: break;
157:
158: case DMAC::MTC:
159: data = chan->mtc >> 8;
1.1.1.13! root 160: putlog(3, "#%d MTC:H -> $%02x", ch, data.Data());
1.1 root 161: break;
162: case DMAC::MTC + 1:
163: data = chan->mtc & 0xff;
1.1.1.13! root 164: putlog(3, "#%d MTC:L -> $%02x", ch, data.Data());
1.1 root 165: break;
166:
167: case DMAC::MAR:
168: data = chan->mar >> 24;
1.1.1.13! root 169: putlog(3, "#%d MAR:0 -> $%02x", ch, data.Data());
1.1 root 170: break;
171: case DMAC::MAR + 1:
172: data = (chan->mar >> 16) & 0xff;
1.1.1.13! root 173: putlog(3, "#%d MAR:1 -> $%02x", ch, data.Data());
1.1 root 174: break;
175: case DMAC::MAR + 2:
176: data = (chan->mar >> 8) & 0xff;
1.1.1.13! root 177: putlog(3, "#%d MAR:2 -> $%02x", ch, data.Data());
1.1 root 178: break;
179: case DMAC::MAR + 3:
180: data = chan->mar & 0xff;
1.1.1.13! root 181: putlog(3, "#%d MAR:3 -> $%02x", ch, data.Data());
1.1 root 182: break;
183:
184: case DMAC::DAR:
185: data = chan->dar >> 24;
1.1.1.13! root 186: putlog(3, "#%d DAR:0 -> $%02x", ch, data.Data());
1.1 root 187: break;
188: case DMAC::DAR + 1:
189: data = (chan->dar >> 16) & 0xff;
1.1.1.13! root 190: putlog(3, "#%d DAR:1 -> $%02x", ch, data.Data());
1.1 root 191: break;
192: case DMAC::DAR + 2:
193: data = (chan->dar >> 8) & 0xff;
1.1.1.13! root 194: putlog(3, "#%d DAR:2 -> $%02x", ch, data.Data());
1.1 root 195: break;
196: case DMAC::DAR + 3:
197: data = chan->dar & 0xff;
1.1.1.13! root 198: putlog(3, "#%d DAR:3 -> $%02x", ch, data.Data());
1.1 root 199: break;
200:
201: case DMAC::BTC:
202: data = chan->btc >> 8;
1.1.1.13! root 203: putlog(3, "#%d BTC:H -> $%02x", ch, data.Data());
1.1 root 204: break;
205: case DMAC::BTC + 1:
206: data = chan->btc & 0xff;
1.1.1.13! root 207: putlog(3, "#%d BTC:L -> $%02x", ch, data.Data());
1.1 root 208: break;
209:
210: case DMAC::BAR:
211: data = chan->bar >> 24;
1.1.1.13! root 212: putlog(3, "#%d BAR:0 -> $%02x", ch, data.Data());
1.1 root 213: break;
214: case DMAC::BAR + 1:
215: data = (chan->bar >> 16) & 0xff;
1.1.1.13! root 216: putlog(3, "#%d BAR:1 -> $%02x", ch, data.Data());
1.1 root 217: break;
218: case DMAC::BAR + 2:
219: data = (chan->bar >> 8) & 0xff;
1.1.1.13! root 220: putlog(3, "#%d BAR:2 -> $%02x", ch, data.Data());
1.1 root 221: break;
222: case DMAC::BAR + 3:
223: data = chan->bar & 0xff;
1.1.1.13! root 224: putlog(3, "#%d BAR:3 -> $%02x", ch, data.Data());
1.1 root 225: break;
226:
227: case DMAC::NIV:
228: data = chan->niv;
1.1.1.13! root 229: putlog(3, "#%d NIV -> $%02x", ch, data.Data());
1.1 root 230: break;
231:
232: case DMAC::EIV:
233: data = chan->eiv;
1.1.1.13! root 234: putlog(3, "#%d EIV -> $%02x", ch, data.Data());
1.1 root 235: break;
236:
237: case DMAC::MFC:
1.1.1.13! root 238: data = chan->mfc.GetFC();
! 239: putlog(3, "#%d MFC -> $%02x", ch, data.Data());
1.1 root 240: break;
241:
242: case DMAC::CPR:
243: data = chan->cpr;
1.1.1.13! root 244: putlog(3, "#%d CPR -> $%02x", ch, data.Data());
1.1 root 245: break;
246:
247: case DMAC::DFC:
1.1.1.13! root 248: data = chan->dfc.GetFC();
! 249: putlog(3, "#%d DFC -> $%02x", ch, data.Data());
1.1 root 250: break;
251:
252: case DMAC::BFC:
1.1.1.13! root 253: data = chan->bfc.GetFC();
! 254: putlog(3, "#%d BFC -> $%02x", ch, data.Data());
1.1 root 255: break;
256:
257: case DMAC::GCR:
258: if (ch == 3) {
1.1.1.11 root 259: data = gcr;
1.1.1.13! root 260: putlog(3, "GCR -> $%02x", data.Data());
1.1 root 261: break;
262: } else {
263: data = 0xff;
264: }
265: break;
266:
267: default:
268: data = 0xff;
269: break;
270: }
271:
1.1.1.13! root 272: data |= read_wait;
1.1 root 273: return data;
274: }
275:
1.1.1.13! root 276: busdata
1.1.1.11 root 277: DMACDevice::Read16(uint32 addr)
1.1 root 278: {
1.1.1.13! root 279: busdata data;
1.1.1.11 root 280:
281: uint32 offset = addr & 0xff;
282: int ch = offset / 0x40;
283: int n = offset % 0x40;
284: DMACChan *chan = &channel[ch];
285:
286: switch (n) {
287: case DMAC::CSR: // CSR | CER
288: data = chan->GetCSR() << 8;
289: data |= chan->cer;
1.1.1.13! root 290: putlog(3, "#%d CSR:CER -> $%04x", ch, data.Data());
1.1.1.11 root 291: break;
292:
293: case DMAC::DCR: // DCR | OCR
294: data = chan->GetDCR() << 8;
295: data |= chan->GetOCR();
1.1.1.13! root 296: putlog(3, "#%d DCR:OCR -> $%04x", ch, data.Data());
1.1.1.11 root 297: break;
298:
299: case DMAC::SCR: // SCR | CCR
300: data = chan->GetSCR() << 8;
301: data |= chan->GetCCR();
1.1.1.13! root 302: putlog(3, "#%d SCR:CCR -> $%04x", ch, data.Data());
1.1.1.11 root 303: break;
304:
305: case DMAC::MTC:
306: data = chan->mtc;
1.1.1.13! root 307: putlog(3, "#%d MTC -> $%04x", ch, data.Data());
1.1.1.11 root 308: break;
309:
310: case DMAC::MAR:
311: data = chan->mar >> 16;
1.1.1.13! root 312: putlog(3, "#%d MAR:H -> $%04x", ch, data.Data());
1.1.1.11 root 313: break;
314: case DMAC::MAR + 2:
315: data = chan->mar & 0xffff;
1.1.1.13! root 316: putlog(3, "#%d MAR:L -> $%04x", ch, data.Data());
1.1.1.11 root 317: break;
318:
319: case DMAC::DAR:
320: data = chan->dar >> 16;
1.1.1.13! root 321: putlog(3, "#%d DAR:H -> $%04x", ch, data.Data());
1.1.1.11 root 322: break;
323: case DMAC::DAR + 2:
324: data = chan->dar & 0xffff;
1.1.1.13! root 325: putlog(3, "#%d DAR:L -> $%04x", ch, data.Data());
1.1.1.11 root 326: break;
327:
328: case DMAC::BTC:
329: data = chan->btc;
1.1.1.13! root 330: putlog(3, "#%d BTC -> $%04x", ch, data.Data());
1.1.1.11 root 331: break;
332:
333: case DMAC::BAR:
334: data = chan->bar >> 16;
1.1.1.13! root 335: putlog(3, "#%d BAR:H -> $%04x", ch, data.Data());
1.1.1.11 root 336: break;
337: case DMAC::BAR + 2:
338: data = chan->bar & 0xffff;
1.1.1.13! root 339: putlog(3, "#%d BAR:L -> $%04x", ch, data.Data());
1.1.1.11 root 340: break;
341:
342: case DMAC::NIV:
343: data = chan->niv | 0xff00;
1.1.1.13! root 344: putlog(3, "#%d NIV -> $%04x", ch, data.Data());
1.1.1.11 root 345: break;
346:
347: case DMAC::EIV:
348: data = chan->eiv | 0xff00;
1.1.1.13! root 349: putlog(3, "#%d EIV -> $%04x", ch, data.Data());
1.1.1.11 root 350: break;
351:
352: case DMAC::MFC:
1.1.1.13! root 353: data = chan->mfc.GetFC() | 0xff00;
! 354: putlog(3, "#%d MFC -> $%04x", ch, data.Data());
1.1.1.11 root 355: break;
356:
357: case DMAC::CPR:
358: data = chan->cpr | 0xff00;
1.1.1.13! root 359: putlog(3, "#%d CPR -> $%04x", ch, data.Data());
1.1.1.11 root 360: break;
361:
362: case DMAC::DFC:
1.1.1.13! root 363: data = chan->dfc.GetFC() | 0xff00;
! 364: putlog(3, "#%d DFC -> $%04x", ch, data.Data());
1.1.1.11 root 365: break;
366:
367: case DMAC::BFC:
1.1.1.13! root 368: data = chan->bfc.GetFC() | 0xff00;
! 369: putlog(3, "#%d BFC -> $%04x", ch, data.Data());
1.1.1.11 root 370: break;
371:
372: case DMAC::GCR:
373: if (ch == 3) {
374: data = gcr | 0xff00;
1.1.1.13! root 375: putlog(3, "GCR -> $%04x", data.Data());
1.1.1.11 root 376: break;
377: } else {
378: data = 0xffff;
379: }
380: break;
381:
382: default:
383: data = 0xffff;
384: break;
385: }
386:
1.1.1.13! root 387: data |= read_wait;
1.1.1.11 root 388: return data;
389: }
390:
391: // STR か ACT が立っている時に書き込むとタイミングエラー
392: #define TIMING_ERR_IF_RUNNING do { \
393: if (chan->str || chan->active) { \
394: Error(chan, DMAC::CER_TIMING); \
395: break; \
396: } \
397: } while (0)
1.1 root 398:
1.1.1.11 root 399: // ログ表示版
400: #define TIMING_ERR_IF_RUNNING_log(regname) do { \
401: if (chan->str || chan->active) { \
402: putlog(2, "#%d %s <- $%02x", ch, regname, data); \
403: Error(chan, DMAC::CER_TIMING); \
404: break; \
405: } \
406: } while (0)
407:
1.1.1.13! root 408: busdata
1.1.1.11 root 409: DMACDevice::Write8(uint32 addr, uint32 data)
410: {
411: uint32 offset = addr & 0xff;
412: int ch = offset / 0x40;
1.1.1.7 root 413: int n = offset % 0x40;
1.1.1.11 root 414: DMACChan *chan = &channel[ch];
415:
1.1 root 416: switch (n) {
417: case DMAC::CSR:
1.1.1.11 root 418: WriteCSR(chan, data);
1.1 root 419: break;
420:
421: case DMAC::CER:
422: // Read only
423: break;
424:
425: case DMAC::DCR:
1.1.1.11 root 426: putlog(2, "#%d DCR <- $%02x", ch, data);
427: TIMING_ERR_IF_RUNNING;
428: chan->SetDCR(data);
1.1 root 429: break;
430:
431: case DMAC::OCR:
1.1.1.11 root 432: putlog(2, "#%d OCR <- $%02x", ch, data);
433: TIMING_ERR_IF_RUNNING;
434: chan->SetOCR(data);
1.1 root 435: break;
436:
437: case DMAC::SCR:
1.1.1.11 root 438: putlog(2, "#%d SCR <- $%02x", ch, data);
439: TIMING_ERR_IF_RUNNING;
440: chan->SetSCR(data);
1.1 root 441: break;
442:
443: case DMAC::CCR:
1.1.1.11 root 444: {
445: // %0 -> %1 に変化したビットだけを評価する。
446: uint8 up = (chan->GetCCR() ^ data) & data;
447: // バイトサイズのログを (up 込みで) 表示。
448: putlog(2, "#%d CCR <- $%02x (up=$%02x)", chan->ch, data, up);
449: // CCR を更新してから WriteCCR() で動作をする。
450: chan->SetCCR(data);
451: WriteCCR(chan, data, up);
1.1 root 452: break;
1.1.1.11 root 453: }
1.1 root 454:
455: case DMAC::MTC:
1.1.1.11 root 456: TIMING_ERR_IF_RUNNING_log("MTC:H");
1.1 root 457: chan->mtc = (chan->mtc & 0x00ff) | (data << 8);
1.1.1.11 root 458: putlog(2, "#%d MTC:H <- $%02x (MTC=$%04x)", ch, data, chan->mtc);
1.1 root 459: break;
460: case DMAC::MTC + 1:
1.1.1.11 root 461: TIMING_ERR_IF_RUNNING_log("MTC:L");
1.1 root 462: chan->mtc = (chan->mtc & 0xff00) | data;
1.1.1.11 root 463: putlog(2, "#%d MTC:L <- $%02x (MTC=$%04x)", ch, data, chan->mtc);
1.1 root 464: break;
465:
466: case DMAC::MAR:
1.1.1.11 root 467: TIMING_ERR_IF_RUNNING_log("MAR:0");
1.1 root 468: chan->mar = (chan->mar & 0x00ffffff) | (data << 24);
1.1.1.11 root 469: putlog(2, "#%d MAR:0 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1 root 470: break;
471: case DMAC::MAR + 1:
1.1.1.11 root 472: TIMING_ERR_IF_RUNNING_log("MAR:1");
1.1 root 473: chan->mar = (chan->mar & 0xff00ffff) | (data << 16);
1.1.1.11 root 474: putlog(2, "#%d MAR:1 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1 root 475: break;
476: case DMAC::MAR + 2:
1.1.1.11 root 477: TIMING_ERR_IF_RUNNING_log("MAR:2");
1.1 root 478: chan->mar = (chan->mar & 0xffff00ff) | (data << 8);
1.1.1.11 root 479: putlog(2, "#%d MAR:2 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1 root 480: break;
481: case DMAC::MAR + 3:
1.1.1.11 root 482: TIMING_ERR_IF_RUNNING_log("MAR:3");
1.1 root 483: chan->mar = (chan->mar & 0xffffff00) | data;
1.1.1.11 root 484: putlog(2, "#%d MAR:3 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1 root 485: break;
486:
487: case DMAC::DAR:
1.1.1.11 root 488: TIMING_ERR_IF_RUNNING_log("DAR:0");
1.1 root 489: chan->dar = (chan->dar & 0x00ffffff) | (data << 24);
1.1.1.11 root 490: putlog(2, "#%d DAR:0 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1 root 491: break;
492: case DMAC::DAR + 1:
1.1.1.11 root 493: TIMING_ERR_IF_RUNNING_log("DAR:1");
1.1 root 494: chan->dar = (chan->dar & 0xff00ffff) | (data << 16);
1.1.1.11 root 495: putlog(2, "#%d DAR:1 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1 root 496: break;
497: case DMAC::DAR + 2:
1.1.1.11 root 498: TIMING_ERR_IF_RUNNING_log("DAR:2");
1.1 root 499: chan->dar = (chan->dar & 0xffff00ff) | (data << 8);
1.1.1.11 root 500: putlog(2, "#%d DAR:2 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1 root 501: break;
502: case DMAC::DAR + 3:
1.1.1.11 root 503: TIMING_ERR_IF_RUNNING_log("DAR:3");
1.1 root 504: chan->dar = (chan->dar & 0xffffff00) | data;
1.1.1.11 root 505: putlog(2, "#%d DAR:3 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1 root 506: break;
507:
508: case DMAC::BTC:
509: chan->btc = (chan->btc & 0x00ff) | (data << 8);
1.1.1.11 root 510: putlog(2, "#%d BTC:H <- $%02x (BTC=$%04x)", ch, data, chan->btc);
1.1 root 511: break;
512: case DMAC::BTC + 1:
513: chan->btc = (chan->btc & 0xff00) | data;
1.1.1.11 root 514: putlog(2, "#%d BTC:L <- $%02x (BTC=$%04x)", ch, data, chan->btc);
1.1 root 515: break;
516:
517: case DMAC::BAR:
518: chan->bar = (chan->bar & 0x00ffffff) | (data << 24);
1.1.1.11 root 519: putlog(2, "#%d BAR:0 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1 root 520: break;
521: case DMAC::BAR + 1:
522: chan->bar = (chan->bar & 0xff00ffff) | (data << 16);
1.1.1.11 root 523: putlog(2, "#%d BAR:1 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1 root 524: break;
525: case DMAC::BAR + 2:
526: chan->bar = (chan->bar & 0xffff00ff) | (data << 8);
1.1.1.11 root 527: putlog(2, "#%d BAR:2 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1 root 528: break;
529: case DMAC::BAR + 3:
530: chan->bar = (chan->bar & 0xffffff00) | data;
1.1.1.11 root 531: putlog(2, "#%d BAR:3 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1 root 532: break;
533:
534: case DMAC::NIV:
1.1.1.11 root 535: putlog(2, "#%d NIV <- $%02x", ch, data);
536: chan->SetNIV(data);
1.1 root 537: break;
538:
539: case DMAC::EIV:
1.1.1.11 root 540: putlog(2, "#%d EIV <- $%02x", ch, data);
541: chan->SetEIV(data);
1.1 root 542: break;
543:
544: case DMAC::MFC:
1.1.1.11 root 545: putlog(2, "#%d MFC <- $%02x", ch, data);
546: TIMING_ERR_IF_RUNNING;
547: chan->SetMFC(data);
1.1 root 548: break;
549:
550: case DMAC::CPR:
1.1.1.11 root 551: putlog(2, "#%d CPR <- $%02x", ch, data);
552: chan->SetCPR(data);
1.1 root 553: break;
554:
555: case DMAC::DFC:
1.1.1.11 root 556: putlog(2, "#%d DFC <- $%02x", ch, data);
557: TIMING_ERR_IF_RUNNING;
558: chan->SetDFC(data);
1.1 root 559: break;
560:
561: case DMAC::BFC:
1.1.1.11 root 562: putlog(2, "#%d BFC <- $%02x", ch, data);
563: chan->SetBFC(data);
1.1 root 564: break;
565:
566: case DMAC::GCR:
567: if (ch == 3) {
1.1.1.11 root 568: WriteGCR(data);
569: }
570: break;
571:
572: default:
573: break;
574: }
1.1.1.13! root 575:
! 576: return write_wait;
1.1.1.11 root 577: }
578:
1.1.1.13! root 579: busdata
1.1.1.11 root 580: DMACDevice::Write16(uint32 addr, uint32 data)
581: {
582: uint32 offset = addr & 0xff;
583: int ch = offset / 0x40;
584: int n = offset % 0x40;
585: DMACChan *chan = &channel[ch];
586:
587: switch (n) {
588: case DMAC::CSR: // CSR | CER
589: // XXX ログがバイトサイズのまま出るがどうするか
590: WriteCSR(chan, data >> 8);
591: // CER は Read Only
592: break;
593:
594: case DMAC::DCR: // DCR | OCR
595: putlog(2, "#%d DCR:OCR <- $%04x", ch, data);
596: TIMING_ERR_IF_RUNNING;
597: chan->SetDCR(data >> 8);
598: chan->SetOCR(data & 0xff);
599: break;
600:
601: case DMAC::SCR: // SCR | CCR
602: {
603: // CCR の %0 -> %1 に変化したビットだけを取り出す。
604: uint8 up = (chan->GetCCR() ^ data) & data;
605: // ワードサイズのログを (CCR の up 込みで) 表示。
606: putlog(2, "#%d SCR:CCR <- $%04x (up=$%02x)", ch, data, up);
607: // 両方のレジスタの値を更新。
608: chan->SetSCR(data >> 8);
609: chan->SetCCR(data);
610: // ワード書き込みで STR が立っているとタイミングエラー (p.17) は
611: // ここで評価する。SCR 更新の後。
612: TIMING_ERR_IF_RUNNING;
613: // タイミングエラーでなければ CCR に基づいて動作。
614: WriteCCR(chan, data, up);
615: break;
616: }
617:
618: case DMAC::MTC:
619: putlog(2, "#%d MTC <- $%04x", ch, data);
620: TIMING_ERR_IF_RUNNING;
621: chan->mtc = data;
622: break;
623:
624: case DMAC::MAR:
625: TIMING_ERR_IF_RUNNING_log("MAR:H");
626: chan->mar = (chan->mar & 0x0000ffff) | (data << 16);
627: putlog(2, "#%d MAR:H <- $%04x (MAR=$%08x)", ch, data, chan->mar);
628: break;
629: case DMAC::MAR + 2:
630: TIMING_ERR_IF_RUNNING_log("MAR:L");
631: chan->mar = (chan->mar & 0xffff0000) | data;
632: putlog(2, "#%d MAR:L <- $%04x (MAR=$%08x)", ch, data, chan->mar);
633: break;
634:
635: case DMAC::DAR:
636: TIMING_ERR_IF_RUNNING_log("DAR:H");
637: chan->dar = (chan->dar & 0x0000ffff) | (data << 16);
638: putlog(2, "#%d DAR:H <- $%04x (DAR=$%08x)", ch, data, chan->dar);
639: break;
640: case DMAC::DAR + 2:
641: TIMING_ERR_IF_RUNNING_log("DAR:L");
642: chan->dar = (chan->dar & 0xffff0000) | data;
643: putlog(2, "#%d DAR:L <- $%04x (DAR=$%08x)", ch, data, chan->dar);
644: break;
645:
646: case DMAC::BTC:
647: putlog(2, "#%d BTC <- $%04x", ch, data);
648: TIMING_ERR_IF_RUNNING;
649: chan->btc = data;
650: break;
651:
652: case DMAC::BAR:
653: TIMING_ERR_IF_RUNNING_log("BAR:H");
654: chan->bar = (chan->bar & 0x0000ffff) | (data << 16);
655: putlog(2, "#%d BAR:H <- $%04x (BAR=$%08x)", ch, data, chan->bar);
656: break;
657: case DMAC::BAR + 2:
658: TIMING_ERR_IF_RUNNING_log("BAR:L");
659: chan->bar = (chan->bar & 0xffff0000) | data;
660: putlog(2, "#%d BAR:L <- $%04x (BAR=$%08x)", ch, data, chan->bar);
661: break;
662:
663: case DMAC::NIV:
664: putlog(2, "#%d NIV <- $%02x", ch, data);
665: chan->SetNIV(data);
666: break;
667:
668: case DMAC::EIV:
669: putlog(2, "#%d EIV <- $%02x", ch, data);
670: chan->SetEIV(data);
671: break;
672:
673: case DMAC::MFC:
674: putlog(2, "#%d MFC <- $%02x", ch, data);
675: TIMING_ERR_IF_RUNNING;
676: chan->SetMFC(data);
677: break;
678:
679: case DMAC::CPR:
680: putlog(2, "#%d CPR <- $%02x", ch, data);
681: chan->SetCPR(data);
682: break;
683:
684: case DMAC::DFC:
685: putlog(2, "#%d DFC <- $%02x", ch, data);
686: TIMING_ERR_IF_RUNNING;
687: chan->SetDFC(data);
688: break;
689:
690: case DMAC::BFC:
691: putlog(2, "#%d BFC <- $%02x", ch, data);
692: chan->SetBFC(data);
693: break;
694:
695: case DMAC::GCR - 1:
696: if (ch == 3) {
697: WriteGCR(data);
1.1 root 698: }
699: break;
700:
701: default:
702: break;
703: }
1.1.1.13! root 704:
! 705: return write_wait;
1.1 root 706: }
707:
1.1.1.13! root 708: busdata
1.1.1.11 root 709: DMACDevice::Peek8(uint32 addr)
1.1 root 710: {
711: uint8 data;
712:
1.1.1.11 root 713: uint32 offset = addr & 0xff;
714: int ch = offset / 0x40;
1.1.1.7 root 715: int n = offset % 0x40;
1.1.1.11 root 716: DMACChan *chan = &channel[ch];
717:
1.1 root 718: switch (n) {
719: case DMAC::CSR:
1.1.1.11 root 720: data = chan->GetCSR();
1.1 root 721: break;
722:
723: case DMAC::CER:
724: data = chan->cer;
725: break;
726:
727: case DMAC::DCR:
1.1.1.11 root 728: data = chan->GetDCR();
1.1 root 729: break;
730:
731: case DMAC::OCR:
1.1.1.11 root 732: data = chan->GetOCR();
1.1 root 733: break;
734:
735: case DMAC::SCR:
1.1.1.11 root 736: data = chan->GetSCR();
1.1 root 737: break;
738:
739: case DMAC::CCR:
1.1.1.11 root 740: data = chan->GetCCR();
1.1 root 741: break;
742:
743: case DMAC::MTC:
744: data = chan->mtc >> 8;
745: break;
746: case DMAC::MTC + 1:
747: data = chan->mtc & 0xff;
748: break;
749:
750: case DMAC::MAR:
751: data = chan->mar >> 24;
752: break;
753: case DMAC::MAR + 1:
754: data = (chan->mar >> 16) & 0xff;
755: break;
756: case DMAC::MAR + 2:
757: data = (chan->mar >> 8) & 0xff;
758: break;
759: case DMAC::MAR + 3:
760: data = chan->mar & 0xff;
761: break;
762:
763: case DMAC::DAR:
764: data = chan->dar >> 24;
765: break;
766: case DMAC::DAR + 1:
767: data = (chan->dar >> 16) & 0xff;
768: break;
769: case DMAC::DAR + 2:
770: data = (chan->dar >> 8) & 0xff;
771: break;
772: case DMAC::DAR + 3:
773: data = chan->dar & 0xff;
774: break;
775:
776: case DMAC::BTC:
777: data = chan->btc >> 8;
778: break;
779: case DMAC::BTC + 1:
780: data = chan->btc & 0xff;
781: break;
782:
783: case DMAC::BAR:
784: data = chan->bar >> 24;
785: break;
786: case DMAC::BAR + 1:
787: data = (chan->bar >> 16) & 0xff;
788: break;
789: case DMAC::BAR + 2:
790: data = (chan->bar >> 8) & 0xff;
791: break;
792: case DMAC::BAR + 3:
793: data = chan->bar & 0xff;
794: break;
795:
796: case DMAC::NIV:
797: data = chan->niv;
798: break;
799:
800: case DMAC::EIV:
801: data = chan->eiv;
802: break;
803:
804: case DMAC::MFC:
1.1.1.13! root 805: data = chan->mfc.GetFC();
1.1 root 806: break;
807:
808: case DMAC::CPR:
809: data = chan->cpr;
810: break;
811:
812: case DMAC::DFC:
1.1.1.13! root 813: data = chan->dfc.GetFC();
1.1 root 814: break;
815:
816: case DMAC::BFC:
1.1.1.13! root 817: data = chan->bfc.GetFC();
1.1 root 818: break;
819:
820: case DMAC::GCR:
821: if (ch == 3) {
1.1.1.11 root 822: data = gcr;
1.1 root 823: } else {
824: data = 0xff;
825: }
826: break;
827:
828: default:
829: data = 0xff;
830: break;
831: }
832:
833: return data;
834: }
835:
1.1.1.4 root 836: void
1.1.1.8 root 837: DMACDevice::MonitorUpdate(Monitor *, TextScreen& screen)
1.1.1.2 root 838: {
839: int x;
840: int y;
841:
1.1.1.8 root 842: screen.Clear();
1.1.1.2 root 843:
844: y = 1;
1.1.1.11 root 845: screen.Puts(0, y++, "BaseAddress");
846: screen.Print(0, y++, "+$%02x CSR:", DMAC::CSR);
1.1.1.2 root 847: y += 2;
1.1.1.11 root 848: screen.Print(0, y++, "+$%02x CER:", DMAC::CER);
849: screen.Print(0, y++, "+$%02x DCR:", DMAC::DCR);
850: screen.Print(5, y++, "%6s", ".XRM");
851: screen.Print(5, y++, "%6s", ".DTYP");
852: screen.Print(5, y++, "%6s", ".DPS");
853: screen.Print(5, y++, "%6s", ".PCL");
854: screen.Print(0, y++, "+$%02x OCR:", DMAC::OCR);
855: screen.Print(5, y++, "%6s", ".DIR");
856: screen.Print(5, y++, "%6s", ".SIZE");
857: screen.Print(5, y++, "%6s", ".CHAIN");
858: screen.Print(5, y++, "%6s", ".REQG");
859: screen.Print(0, y++, "+$%02x SCR:", DMAC::SCR);
860: screen.Print(5, y++, "%6s", ".MAC");
861: screen.Print(5, y++, "%6s", ".DAC");
862: screen.Print(0, y++, "+$%02x CCR:", DMAC::CCR);
1.1.1.2 root 863: y += 2;
1.1.1.11 root 864: screen.Print(0, y++, "+$%02x MTC:", DMAC::MTC);
865: screen.Print(0, y++, "+$%02x MAR:", DMAC::MAR);
866: screen.Print(0, y++, "+$%02x DAR:", DMAC::DAR);
867: screen.Print(0, y++, "+$%02x BTC:", DMAC::BTC);
868: screen.Print(0, y++, "+$%02x BAR:", DMAC::BAR);
869: screen.Print(0, y++, "+$%02x NIV:", DMAC::NIV);
870: screen.Print(0, y++, "+$%02x EIV:", DMAC::EIV);
871: screen.Print(0, y++, "+$%02x MFC:", DMAC::MFC);
872: screen.Print(0, y++, "+$%02x CPR:", DMAC::CPR);
873: screen.Print(0, y++, "+$%02x DFC:", DMAC::DFC);
874: screen.Print(0, y++, "+$%02x BFC:", DMAC::BFC);
1.1.1.2 root 875:
876: for (int ch = 0; ch < 4; ch++) {
1.1.1.11 root 877: DMACChan *chan = &channel[ch];
1.1.1.2 root 878: int val;
1.1.1.11 root 879: x = 13 + ch * 17;
1.1.1.2 root 880: y = 0;
881:
882: // 地味だけど有効なチャンネルをハイライトしてみる
1.1.1.8 root 883: screen.Print(x, y++, (chan->active ? TA::Em : TA::Normal),
1.1.1.2 root 884: "#%d (%s)", chan->ch, chan->desc);
885:
1.1.1.11 root 886: // アドレス
887: screen.Print(x, y++, "$%06x", baseaddr + ch * 0x40);
888:
1.1.1.2 root 889: // CSR
1.1.1.11 root 890: val = chan->GetCSR();
1.1.1.8 root 891: screen.Print(x, y++, "$%02x", val);
1.1.1.2 root 892: static const char * const csrname[] = {
1.1.1.11 root 893: "COC", "BTC", "NDT", "ERR", "ACT", "DIT", "PCT", "PCS",
1.1.1.2 root 894: };
1.1.1.8 root 895: MonitorReg4(screen, x, y++, val >> 4, &csrname[0]);
896: MonitorReg4(screen, x, y++, val & 0xff, &csrname[4]);
1.1.1.2 root 897:
898: // CER
1.1.1.11 root 899: val = chan->cer;
1.1.1.2 root 900: const char *e;
901: if (val <= 0x11 && errnames[val]) {
902: e = errnames[val];
903: } else {
904: e = "?";
905: }
1.1.1.8 root 906: screen.Print(x, y, "$%02x", chan->cer);
1.1.1.11 root 907: if (val != 0) {
1.1.1.8 root 908: screen.Print(x + 3, y, ":%s", e);
1.1.1.2 root 909: }
910: y++;
911:
1.1.1.11 root 912: // DCR
913: screen.Print(x, y++, "$%02x", chan->GetDCR());
914:
1.1.1.2 root 915: // DCR:XRM
916: static const char * const dcr_xrm[] = {
917: //1234567890123
918: "Burst",
919: "undefined",
920: "CycleW/O Hold",
921: "CycleWithHold",
922: };
1.1.1.11 root 923: val = chan->GetXRM();
1.1.1.8 root 924: screen.Print(x, y++, "%d:%s", val, dcr_xrm[val]);
1.1.1.2 root 925:
926: // DCR:DTYP
927: static const char * const dcr_dtyp[] = {
928: //1234567890123
929: "68000",
930: "6800",
931: "ACK",
932: "ACK+READY",
933: };
1.1.1.11 root 934: val = chan->GetDTYP();
1.1.1.8 root 935: screen.Print(x, y++, "%d:%s", val, dcr_dtyp[val]);
1.1.1.2 root 936:
937: // DCR:DPS
938: static const char * const dcr_dps[] = {
939: //1234567890123
940: "8bit",
941: "16bit",
942: };
1.1.1.11 root 943: val = chan->GetDPS();
1.1.1.8 root 944: screen.Print(x, y++, "%d:%s", val, dcr_dps[val]);
1.1.1.2 root 945:
946: // DCR:PCL
1.1.1.11 root 947: static const char * const dcr_pcl_name[] = {
948: //1234567890123
949: "Status",
950: "StatusInt",
951: "Pulse(output)",
952: "Abort",
953: };
954: val = chan->dcr_pcl;
955: screen.Print(x, y++, "%d:%s", val, dcr_pcl_name[val]);
956:
957: // OCR
958: screen.Print(x, y++, "$%02x", chan->GetOCR());
1.1.1.2 root 959:
960: // OCR:DIR
961: static const char * const ocr_dir[] = {
962: //1234567890123
963: "MemoryToDevice",
964: "DeviceToMemory",
965: };
1.1.1.11 root 966: val = chan->GetDIR();
1.1.1.8 root 967: screen.Print(x, y++, "%d:%s", val, ocr_dir[val]);
1.1.1.2 root 968:
969: // OCR:SIZE
970: static const char * const ocr_size[] = {
971: //1234567890123
1.1.1.11 root 972: "8bit (Packed)",
1.1.1.2 root 973: "16bit",
974: "32bit",
975: "8bit Unpacked",
976: };
1.1.1.11 root 977: val = chan->GetSIZE();
1.1.1.8 root 978: screen.Print(x, y++, "%d:%s", val, ocr_size[val]);
1.1.1.2 root 979:
980: // OCR:CHAIN
981: static const char * const ocr_chain[] = {
982: //1234567890123
983: "NoChain",
984: "undefined",
985: "ArrayChain",
986: "LinkArrayChain",
987: };
1.1.1.11 root 988: val = chan->GetCHAIN();
1.1.1.8 root 989: screen.Print(x, y++, "%d:%s", val, ocr_chain[val]);
1.1.1.2 root 990:
991: // OCR:REQG
992: static const char * const ocr_reqg[] = {
993: //1234567890123
994: "AutoReq(Limit)",
995: "AutoReq(Max)",
996: "ExternalReq",
997: "AutoThenExt",
998: };
1.1.1.11 root 999: val = chan->GetREQG();
1.1.1.8 root 1000: screen.Print(x, y++, "%d:%s", val, ocr_reqg[val]);
1.1.1.2 root 1001:
1.1.1.11 root 1002: // SCR
1003: screen.Print(x, y++, "$%02x", chan->GetSCR());
1004:
1005: // SCR:MAC,DAC
1.1.1.2 root 1006: static const char * const scr_xac[] = {
1007: //1234567890123
1008: "NoCount",
1009: "CountUp",
1010: "CountDown",
1011: "undefined",
1012: };
1.1.1.11 root 1013: val = chan->GetMAC();
1.1.1.8 root 1014: screen.Print(x, y++, "%d:%s", val, scr_xac[val]);
1.1.1.11 root 1015: val = chan->GetDAC();
1.1.1.8 root 1016: screen.Print(x, y++, "%d:%s", val, scr_xac[val]);
1.1.1.2 root 1017:
1018: // CCR
1.1.1.11 root 1019: val = chan->GetCCR();
1.1.1.8 root 1020: screen.Print(x, y++, "$%02x", val);
1.1.1.2 root 1021: static const char * const ccrnames[] = {
1.1.1.9 root 1022: "STR", "CNT", "HLT", "SAB", "INT", "-", "-", "-",
1.1.1.2 root 1023: };
1.1.1.8 root 1024: MonitorReg4(screen, x, y++, (val >> 4), &ccrnames[0]);
1025: MonitorReg4(screen, x, y++, (val & 0xff), &ccrnames[4]);
1.1.1.2 root 1026:
1027: // MTC
1.1.1.8 root 1028: screen.Print(x, y++, "$%04x", chan->mtc);
1.1.1.2 root 1029: // MAR
1030: // X680x0 がターゲットなので24bit超える設定は目立たせる
1031: if (chan->mar > 0xffffff) {
1.1.1.8 root 1032: screen.Print(x, y++, TA::On, "$%08x", chan->mar);
1.1.1.2 root 1033: } else {
1.1.1.8 root 1034: screen.Print(x, y++, "$%06x", chan->mar);
1.1.1.2 root 1035: }
1036: // DAR
1037: if (chan->dar > 0xffffff) {
1.1.1.8 root 1038: screen.Print(x, y++, TA::On, "$%08x", chan->dar);
1.1.1.2 root 1039: } else {
1.1.1.8 root 1040: screen.Print(x, y++, "$%06x", chan->dar);
1.1.1.2 root 1041: }
1042: // BTC
1.1.1.8 root 1043: screen.Print(x, y++, "$%04x", chan->btc);
1.1.1.2 root 1044: // BAR
1045: if (chan->bar > 0xffffff) {
1.1.1.8 root 1046: screen.Print(x, y++, TA::On, "$%08x", chan->bar);
1.1.1.2 root 1047: } else {
1.1.1.8 root 1048: screen.Print(x, y++, "$%06x", chan->bar);
1.1.1.2 root 1049: }
1050:
1051: // NIV
1.1.1.8 root 1052: screen.Print(x, y++, "$%02x", chan->niv);
1.1.1.2 root 1053: // EIV
1.1.1.8 root 1054: screen.Print(x, y++, "$%02x", chan->eiv);
1.1.1.2 root 1055:
1056: // MFC
1.1.1.13! root 1057: screen.Print(x, y++, "$%02x", chan->mfc.GetFC());
1.1.1.2 root 1058: // CPR
1.1.1.8 root 1059: screen.Print(x, y++, "$%02x", chan->cpr);
1.1.1.2 root 1060: // DFC
1.1.1.13! root 1061: screen.Print(x, y++, "$%02x", chan->dfc.GetFC());
1.1.1.2 root 1062: // BFC
1.1.1.13! root 1063: screen.Print(x, y++, "$%02x", chan->bfc.GetFC());
1.1.1.2 root 1064:
1065: if (ch == 3) {
1.1.1.11 root 1066: screen.Print(x - 10, y++, "+$3f GCR: $%02x", gcr);
1.1.1.2 root 1067: }
1068: }
1069: }
1070:
1071: // 4ビット分を表示する。MonitorUpdate の下請け
1072: void
1.1.1.8 root 1073: DMACDevice::MonitorReg4(TextScreen& screen,
1.1.1.4 root 1074: int x, int y, uint32 reg, const char * const *names)
1.1.1.2 root 1075: {
1076: for (int i = 0; i < 4; i++) {
1.1.1.9 root 1077: if (names[i][0] == '-') {
1078: screen.Puts(x + i * 4, y, TA::Disable, "---");
1079: } else {
1080: bool b = reg & (1 << (3 - i));
1081: screen.Puts(x + i * 4, y, TA::OnOff(b), names[i]);
1082: }
1.1.1.2 root 1083: }
1084: }
1085:
1086: /*static*/ const char * const
1087: DMACDevice::errnames[] = {
1088: //12345678901
1089: "", // $00 No Error
1090: "ConfigErr", // $01
1091: "OperTiming", // $02
1092: NULL, // $03
1093: NULL, // $04
1094: "AddrErrInMAR", // $05
1095: "AddrErrInDAR", // $06
1096: "AddrErrInBAR", // $07
1097: NULL, // $08
1098: "BusErrInMAR", // $09
1099: "BusErrInDAR", // $0a
1100: "BusErrInBAR", // $0b
1101: NULL, // $0c
1102: "CntErrInMTC", // $0d
1103: NULL, // $0e
1104: "CntErrInBTC", // $0f
1105: "ExternAbort", // $10
1106: "SoftAbort", // $11
1107: };
1108:
1.1.1.6 root 1109: // CSR への書き込み。
1.1 root 1110: void
1.1.1.11 root 1111: DMACDevice::WriteCSR(DMACChan *chan, uint32 data)
1.1 root 1112: {
1.1.1.11 root 1113: // 上位3ビットと DIT は %1 の書き込みでクリア
1114: chan->csr &= ~(data & 0xe4);
1115:
1116: // ERR も %1 の書き込みでクリア。
1117: // このとき CER もクリアする。
1118: if ((data & DMAC::CSR_ERR)) {
1119: chan->csr &= ~DMAC::CSR_ERR;
1120: chan->cer = 0;
1121: }
1.1.1.2 root 1122:
1.1.1.10 root 1123: // PCT も %1 の書き込みでクリア。
1.1.1.11 root 1124: // PCT は PCL が High → Low の時セットなので pcl_prev を下げればよい
1.1.1.2 root 1125: if ((data & DMAC::CSR_PCT)) {
1.1.1.11 root 1126: chan->pcl_prev = false;
1.1.1.2 root 1127: }
1128:
1.1.1.11 root 1129: putlog(2, "#%d CSR <- $%02x (CSR = $%02x)", chan->ch, data, chan->GetCSR());
1130:
1131: ChangeInterrupt();
1.1.1.2 root 1132: }
1133:
1.1.1.11 root 1134: // GCR への書き込み。
1.1 root 1135: void
1.1.1.11 root 1136: DMACDevice::WriteGCR(uint8 data)
1.1 root 1137: {
1.1.1.11 root 1138: putlog(2, "GCR <- $%02x", data);
1139: gcr = data & 0x0f;
1140: }
1141:
1142: // CCR への書き込み。これだけいろいろ変則的なので注意。
1143: // up は data のうち %0 -> %1 に変化したビット。
1144: // SetCCR() 実行済み、ログは出力済み。
1145: void
1146: DMACDevice::WriteCCR(DMACChan *chan, uint32 data, uint8 up)
1147: {
1148: // コンフィギュレーションエラーのチェック。
1149: // データシート p43 Error Conditions (a)
1150: if ((up & DMAC::CCR_STR)) {
1151: // (i) The CNT bit is set at the same time STR bit in the chaining mode.
1152: if ((up & DMAC::CCR_CNT) && chan->IsChain()) {
1153: Error(chan, DMAC::CER_CONFIG);
1154: return;
1155: }
1156:
1157: if (chan->IsSingleAddress()) {
1158: // (ii) DTYP specifies a single addressing mode, and
1159: // the device port size is not the same as the operand size.
1160: if (chan->GetDPS() == DMAC::DPS_8BIT) {
1161: if (!(chan->GetSIZE() == DMAC::SIZE_8BIT_PACK ||
1162: chan->GetSIZE() == DMAC::SIZE_8BIT_UNPK))
1163: {
1164: Error(chan, DMAC::CER_CONFIG);
1165: return;
1166: }
1167: } else {
1168: if (!(chan->GetSIZE() == DMAC::SIZE_16BIT)) {
1169: Error(chan, DMAC::CER_CONFIG);
1170: return;
1171: }
1172: }
1173: } else {
1174: // (iii) DTYP specifies a dual addressing mode, DPS is 16 bits,
1175: // SIZE is 8 bits and REQG is "10" or "11".
1176: if (chan->GetDPS() == DMAC::DPS_16BIT) {
1177: // XXX UNPK は?
1178: if (chan->GetSIZE() == DMAC::SIZE_8BIT_PACK) {
1179: if (chan->GetREQG() == DMAC::REQG_EXTERNAL ||
1180: chan->GetREQG() == DMAC::REQG_AUTOFIRST)
1181: {
1182: Error(chan, DMAC::CER_CONFIG);
1183: return;
1184: }
1185: }
1186: }
1187: }
1188:
1189: // (iv) An undefined configuration is set in the registers.
1190: if (chan->GetXRM() == 1 ||
1191: chan->GetMAC() == 3 ||
1192: chan->GetDAC() == 3 ||
1193: chan->GetCHAIN() == 1)
1194: {
1195: Error(chan, DMAC::CER_CONFIG);
1196: return;
1197: }
1198: if (chan->IsSingleAddress() == false &&
1199: chan->GetSIZE() == DMAC::SIZE_8BIT_UNPK &&
1200: chan->GetDPS() != DMAC::DPS_8BIT)
1201: {
1202: Error(chan, DMAC::CER_CONFIG);
1203: return;
1204: }
1205:
1206: // (e) Count Error
1207: // ここでは (i), (ii) のみ
1208: if (chan->IsChain() == false && chan->mtc == 0) {
1209: Error(chan, DMAC::CER_COUNT_MTC);
1210: return;
1211: }
1212: if (chan->GetCHAIN() == DMAC::CHAIN_ARRAY && chan->btc == 0) {
1213: Error(chan, DMAC::CER_COUNT_BTC);
1214: return;
1215: }
1216: }
1.1.1.2 root 1217:
1218: // SAB (Software Abort)
1.1.1.11 root 1219: if ((up & DMAC::CCR_SAB)) {
1220: AbortTransfer(chan);
1.1.1.2 root 1221: }
1222:
1223: // HLT (Halt Operation)
1.1.1.11 root 1224: if ((up & DMAC::CCR_HLT)) {
1225: putlog(0, "CCR HLT (NOT IMPLEMENTED)");
1.1.1.2 root 1226: }
1227:
1228: // CNT (Continue Operation)
1.1.1.11 root 1229: if ((up & DMAC::CCR_CNT)) {
1230: // Opeation Timing Error (i)
1231: if (chan->IsChain() && chan->active) {
1232: Error(chan, DMAC::CER_TIMING);
1233: return;
1234: }
1235: if (chan->str == false && chan->active == false) {
1236: Error(chan, DMAC::CER_TIMING);
1237: return;
1238: }
1239: putlog(0, "CCR CNT (NOT IMPLEMENTED)");
1.1.1.2 root 1240: }
1241:
1242: // STR (Start Operation)
1.1.1.11 root 1243: if ((up & DMAC::CCR_STR)) {
1244: StartTransfer(chan);
1.1.1.2 root 1245: }
1.1.1.11 root 1246:
1247: ChangeInterrupt();
1.1 root 1248: }
1249:
1.1.1.11 root 1250: // 転送開始
1.1.1.2 root 1251: void
1.1.1.11 root 1252: DMACDevice::StartTransfer(DMACChan* chan)
1.1.1.2 root 1253: {
1.1.1.11 root 1254: // Operation Timing Error (ii)
1255: // CSR の ACT,COC,BTC,NDT,ERR が立ってたら開始しない
1256: if (chan->active || (chan->csr & 0xf0) != 0) {
1257: Error(chan, DMAC::CER_TIMING);
1.1.1.2 root 1258: return;
1259: }
1260:
1.1.1.11 root 1261: // ACT を立てたら STR を下げる。
1262: chan->active = true;
1263: chan->str = false;
1.1.1.2 root 1264:
1.1.1.11 root 1265: // XXX あとで移動する
1266: switch (chan->GetMAC()) {
1267: case DMAC::SCR_COUNT_UP:
1268: chan->mac = 1;
1269: break;
1270: case DMAC::SCR_COUNT_DOWN:
1271: putlog(0, "SCR:MAC CountDown Mode (NOT SUPPORTED)");
1272: chan->mac = -1;
1273: break;
1274: default:
1275: chan->mac = 0;
1276: break;
1277: }
1278: switch (chan->GetDAC()) {
1279: case DMAC::SCR_COUNT_UP:
1280: chan->dac = 1;
1281: break;
1282: case DMAC::SCR_COUNT_DOWN:
1283: putlog(0, "SCR:DAC CountDown Mode (NOT SUPPORTED)");
1284: chan->dac = -1;
1285: break;
1286: default:
1287: chan->dac = 0;
1288: break;
1289: }
1.1.1.2 root 1290:
1.1.1.11 root 1291: chan->data.Clear();
1.1.1.2 root 1292:
1293: // 転送モード
1.1.1.12 root 1294: uint reqg = chan->GetREQG();
1295: switch (reqg) {
1.1.1.11 root 1296: case DMAC::REQG_AUTO_LIM:
1.1.1.10 root 1297: VMPANIC("REQG_AUTO_LIM 未実装");
1.1.1.2 root 1298: break;
1299:
1.1.1.11 root 1300: case DMAC::REQG_AUTO_MAX:
1.1.1.2 root 1301: // 自発的に転送を開始する
1.1.1.11 root 1302: chan->req = true;
1303: break;
1304:
1305: case DMAC::REQG_EXTERNAL:
1306: // 外部リクエスト転送。ここでは何もしなくてよい
1.1.1.2 root 1307: break;
1308:
1.1.1.11 root 1309: case DMAC::REQG_AUTOFIRST:
1.1.1.10 root 1310: VMPANIC("未実装 REQG");
1.1.1.2 root 1311: break;
1312:
1313: default:
1.1.1.12 root 1314: VMPANIC("corrupted reqg=%d", reqg);
1.1.1.2 root 1315: }
1316:
1.1.1.11 root 1317: // 転送開始ログ。全パラメータは無理なので概要だけ表示。
1318: if (loglevel >= 1) {
1319: std::string msg;
1320: if (chan->GetDIR() == DMAC::DIR_MtoD) {
1321: msg = string_format("$%06x to $%06x mtc=$%04x",
1322: chan->mar, chan->dar, chan->mtc);
1323: } else {
1324: msg = string_format("$%06x to $%06x mtc=$%04x",
1325: chan->dar, chan->mar, chan->mtc);
1326: }
1327: putlogn("#%d Start %s", chan->ch, msg.c_str());
1328: }
1329:
1.1.1.10 root 1330: if (event.IsRunning() == false) {
1.1.1.13! root 1331: CallAfter(StartCallback, 0, 0);
1.1.1.10 root 1332: }
1.1.1.5 root 1333: }
1334:
1.1.1.11 root 1335: // 今回転送するチャンネルを決定して返す。なければ NULL を返す。
1336: DMACChan *
1337: DMACDevice::SelectChannel()
1.1.1.2 root 1338: {
1.1.1.11 root 1339: DMACChan *chan;
1.1.1.10 root 1340: int ch = -1;
1341: uint8 prio = 255;
1.1.1.11 root 1342:
1343: for (int i = 0; i < channel.size(); i++) {
1344: chan = &channel[i];
1345: if (chan->active && (chan->req || chan->seq_index < chan->seq.size())) {
1.1.1.10 root 1346: uint8 p = chan->priority;
1347: if (p < prio) {
1348: prio = p;
1349: // 実効プライオリティのラウンドロビン用のところを上げておく
1350: chan->priority = (p & 0xf0) | ((p & 0x0f) >> 1);
1351: ch = i;
1352: }
1353: }
1354: }
1355: if (ch == -1) {
1356: // 転送チャンネルはもうないのでイベントは停止したままにする
1357: event.SetName("DMAC");
1.1.1.11 root 1358: return NULL;
1359: } else {
1360: chan = &channel[ch];
1361: event.SetName(string_format("DMAC #%d", chan->ch));
1362: return chan;
1363: }
1364: }
1365:
1366: // 転送開始
1367: void
1368: DMACDevice::StartCallback(Event& ev)
1369: {
1370: // チャンネルを決定
1371: auto chan = SelectChannel();
1372: if (chan == NULL) {
1.1.1.10 root 1373: return;
1374: }
1.1.1.2 root 1375:
1.1.1.10 root 1376: // 実効プライオリティを同順位の最後に回す
1.1.1.11 root 1377: chan->priority |= 0x08;
1.1.1.2 root 1378:
1.1.1.11 root 1379: chan->retry = 0;
1.1.1.10 root 1380:
1381: // XXX バスアービトレーションとか
1382:
1.1.1.11 root 1383: // 転送シーケンス決定
1384: chan->seq.clear();
1385: chan->seq_index = 0;
1386: if (chan->GetDIR() == DMAC::DIR_MtoD) {
1387: if (chan->GetDPS() == DMAC::DPS_8BIT) {
1388: if (chan->GetSIZE() == DMAC::SIZE_32BIT) {
1389: chan->seq.push_back(RD_M16);
1390: chan->seq.push_back(WR_D8);
1391: chan->seq.push_back(WR_D8);
1392: chan->seq.push_back(RD_M16);
1393: chan->seq.push_back(WR_D8);
1394: chan->seq.push_back(WR_D8);
1395: } else if (chan->GetSIZE() == DMAC::SIZE_16BIT) {
1396: chan->seq.push_back(RD_M16);
1397: chan->seq.push_back(WR_D8);
1398: chan->seq.push_back(WR_D8);
1399: } else {
1400: chan->seq.push_back(RD_M8);
1401: chan->seq.push_back(WR_D8);
1402: }
1403: } else {
1404: // DPS==16
1405: if (chan->GetSIZE() == DMAC::SIZE_32BIT) {
1406: chan->seq.push_back(RD_M16);
1407: chan->seq.push_back(WR_D16);
1408: chan->seq.push_back(RD_M16);
1409: chan->seq.push_back(WR_D16);
1410: } else if (chan->GetSIZE() == DMAC::SIZE_16BIT) {
1411: chan->seq.push_back(RD_M16);
1412: chan->seq.push_back(WR_D16);
1413: } else {
1414: chan->seq.push_back(RD_M8);
1415: chan->seq.push_back(WR_D8);
1416: }
1417: }
1418: } else { // DtoM
1419: if (chan->GetDPS() == DMAC::DPS_8BIT) {
1420: if (chan->GetSIZE() == DMAC::SIZE_32BIT) {
1421: chan->seq.push_back(RD_D8);
1422: chan->seq.push_back(RD_D8);
1423: chan->seq.push_back(WR_M16);
1424: chan->seq.push_back(RD_D8);
1425: chan->seq.push_back(RD_D8);
1426: chan->seq.push_back(WR_M16);
1427: } else if (chan->GetSIZE() == DMAC::SIZE_16BIT) {
1428: chan->seq.push_back(RD_D8);
1429: chan->seq.push_back(RD_D8);
1430: chan->seq.push_back(WR_M16);
1431: } else {
1432: chan->seq.push_back(RD_D8);
1433: chan->seq.push_back(WR_M8);
1434: }
1435: } else {
1436: // DPS==16
1437: if (chan->GetSIZE() == DMAC::SIZE_32BIT) {
1438: chan->seq.push_back(RD_D16);
1439: chan->seq.push_back(WR_M16);
1440: chan->seq.push_back(RD_D16);
1441: chan->seq.push_back(WR_M16);
1442: } else if (chan->GetSIZE() == DMAC::SIZE_16BIT) {
1443: chan->seq.push_back(RD_D16);
1444: chan->seq.push_back(WR_M16);
1445: } else {
1446: chan->seq.push_back(RD_D8);
1447: chan->seq.push_back(WR_M8);
1448: }
1449: }
1450: }
1451:
1.1.1.13! root 1452: CallAfter(TransferCallback, 1, 0);
1.1.1.11 root 1453: }
1454:
1455: // 転送処理
1456: void
1457: DMACDevice::TransferCallback(Event& ev)
1458: {
1459: // チャンネルを決定
1460: auto chan = SelectChannel();
1461: if (chan == NULL) {
1462: return;
1463: }
1464:
1465: int op = chan->seq[chan->seq_index];
1466: uint64 data;
1.1.1.13! root 1467: busdata r;
1.1.1.11 root 1468:
1469: // デバイスアクセスなら ACK#n 信号と DONE 信号のドライブ
1470: switch (op) {
1471: case RD_D8:
1472: case RD_D16:
1473: case WR_D8:
1474: case WR_D16:
1475: AssertACK(chan);
1476: break;
1477: default:
1478: break;
1479: }
1480:
1481: // パック動作が起きるケースなら op を差し替える。
1482: if (chan->GetSIZE() == DMAC::SIZE_8BIT_PACK) {
1483: if (op == RD_M8) {
1484: if (chan->mtc > 1 && chan->mar % 2 == 0 && chan->GetMAC() != 0) {
1485: if (chan->data.Length() == 0) {
1486: op = RD_M16;
1487: } else {
1488: op = NOP;
1489: }
1490: }
1491: }
1492: if (op == WR_M8) {
1493: if (chan->data.Length() >= 2) {
1494: op = WR_M16;
1495: } else {
1496: if (chan->mtc > 1 && chan->mar % 2 == 0 && chan->GetMAC() != 0){
1497: op = NOP;
1498: }
1499: }
1500: }
1501: }
1502:
1.1.1.13! root 1503: // アドレスを生成。
! 1504: busaddr addr;
1.1.1.11 root 1505: switch (op) {
1506: case RD_M8:
1507: case RD_M16:
1.1.1.13! root 1508: case WR_M8:
! 1509: case WR_M16:
! 1510: addr.Set(chan->mar, chan->mfc);
1.1.1.11 root 1511: break;
1512: case RD_D8:
1513: case RD_D16:
1.1.1.13! root 1514: case WR_D8:
! 1515: case WR_D16:
! 1516: addr.Set(chan->dar, chan->dfc);
1.1.1.11 root 1517: break;
1.1.1.13! root 1518: default:
1.1.1.11 root 1519: break;
1.1.1.13! root 1520: }
! 1521:
! 1522: // 書き込みならキューからデータを取得。
! 1523: switch (op) {
! 1524: case WR_M8:
1.1.1.11 root 1525: case WR_D8:
1526: data = chan->data.Dequeue();
1527: break;
1.1.1.13! root 1528: case WR_M16:
1.1.1.11 root 1529: case WR_D16:
1530: data = chan->data.Dequeue() << 8;
1531: data |= chan->data.Dequeue();
1532: break;
1533: default:
1.1.1.13! root 1534: data = 0;
! 1535: break;
! 1536: }
! 1537:
! 1538: // 1回分のアクセス。
! 1539:
! 1540: // ユーザ空間へのアクセスが可能かどうかここで調べる。
! 1541: // 本来は DMAC ではなくメインバスで管理すべきことだが、パフォーマンスの
! 1542: // 観点から MPU 側に FC2 カットによる可動部を増やしたくないので、
! 1543: // アクセス頻度の低い DMAC 側で肩代わりしている。
! 1544: if (__predict_false(addr.IsSuper() == false) &&
! 1545: useraccess[addr.Addr() / 0x2000] == false)
! 1546: {
! 1547: r.SetBusErr();
! 1548: } else {
! 1549: switch (op) {
! 1550: case RD_M8:
! 1551: case RD_D8:
! 1552: r = mainbus->Read8(addr);
! 1553: break;
! 1554: case RD_M16:
! 1555: case RD_D16:
! 1556: r = mainbus->Read16(addr);
! 1557: break;
! 1558: case WR_M8:
! 1559: case WR_D8:
! 1560: r = mainbus->Write8(addr, data);
! 1561: break;
! 1562: case WR_M16:
! 1563: case WR_D16:
! 1564: r = mainbus->Write16(addr, data);
! 1565: break;
! 1566: case NOP:
! 1567: r.Clear();
! 1568: break;
! 1569: default:
! 1570: VMPANIC("corrupted op=%d", op);
! 1571: }
! 1572: }
! 1573: if (__predict_false(loglevel >= 4)) {
! 1574: TransferLog(chan, op, addr, r, data);
1.1.1.11 root 1575: }
1576:
1577: // デバイスアクセスなら ACK#n 信号と DONE 信号のドライブ
1578: switch (op) {
1579: case RD_D8:
1580: case RD_D16:
1581: case WR_D8:
1582: case WR_D16:
1583: NegateACK(chan);
1584: break;
1585: default:
1586: break;
1587: }
1588:
1.1.1.13! root 1589: // バスエラー(もしくはリトライ)か。ACK を下ろした後で行う。
! 1590: if (r.IsOK() == false) {
! 1591: TransferError(chan, op, r, data);
1.1.1.11 root 1592: return;
1593: }
1594:
1595: // 読み込んだデータをキューに投入。バスエラー判定後に行う。
1596: switch (op) {
1597: case RD_M8:
1598: case RD_D8:
1.1.1.13! root 1599: chan->data.Enqueue(r.Data());
1.1.1.11 root 1600: break;
1601: case RD_M16:
1602: case RD_D16:
1.1.1.13! root 1603: chan->data.Enqueue(r.Data() >> 8);
! 1604: chan->data.Enqueue(r.Data() & 0xff);
1.1.1.11 root 1605: break;
1606: default:
1607: break;
1608: }
1609:
1610: // カウンタを更新。バスエラー判定後に行う。
1611: switch (op) {
1612: case RD_M8:
1613: case WR_M8:
1614: chan->mar += chan->mac;
1615: break;
1616: case RD_M16:
1617: case WR_M16:
1618: chan->mar += chan->mac * 2;
1619: break;
1620: case RD_D8:
1621: case WR_D8:
1622: chan->dar += chan->dac * 2;
1623: break;
1624: case RD_D16:
1625: case WR_D16:
1626: chan->dar += chan->dac * 2;
1627: break;
1628: case NOP:
1629: break;
1630: default:
1.1.1.12 root 1631: VMPANIC("corrupted op=%d", op);
1.1.1.11 root 1632: }
1633:
1634: // シーケンス完了で MTC の転送1回分
1635: if (++chan->seq_index >= chan->seq.size()) {
1636: chan->mtc -= 1;
1637:
1638: // すべての転送完了か
1639: if (__predict_false(chan->mtc == 0)) {
1640: chan->csr |= DMAC::CSR_COC;
1641: chan->active = false;
1642: ChangeInterrupt();
1643: }
1644:
1645: // XXX ディレイはあとから見直す
1.1.1.13! root 1646: CallAfter(StartCallback, 4, r.GetWait());
1.1.1.11 root 1647: } else {
1648: // XXX ディレイはあとから見直す
1.1.1.13! root 1649: CallAfter(TransferCallback, 4, r.GetWait());
1.1.1.11 root 1650: }
1.1.1.10 root 1651: }
1652:
1653: // 転送エラー
1654: void
1.1.1.13! root 1655: DMACDevice::TransferError(DMACChan *chan, int op, busdata r, uint32 data)
1.1.1.10 root 1656: {
1.1.1.13! root 1657: if (r.IsRetry()) {
1.1.1.10 root 1658: // DTACK が出ていない (SPC)。
1659: // 本当は DTACK が出たことをコールバックしてくれれば
1660: // 効率がいいのだがポーリングでもかまわんだろう。
1.1.1.11 root 1661: chan->retry++;
1662: if (chan->retry < 100) {
1.1.1.13! root 1663: // 書き込みがリトライになったら仕方ないので、今書こうとして
! 1664: // 取り出したデータをキューに戻してから再実行。うーんこの。
! 1665: switch (op) {
! 1666: case WR_M8:
! 1667: case WR_D8:
! 1668: chan->data.PushFront(data);
! 1669: break;
! 1670: case WR_M16:
! 1671: case WR_D16:
! 1672: chan->data.PushFront(data);
! 1673: chan->data.PushFront(data >> 8);
! 1674: break;
! 1675: default:
! 1676: break;
! 1677: }
! 1678:
1.1.1.10 root 1679: // 現在のイベントを再実行
1680: event.time = 1 * 80_nsec;
1.1.1.12 root 1681: scheduler->StartEvent(event);
1.1.1.10 root 1682: return;
1.1.1.13! root 1683: } else {
! 1684: // タイムアウトしたらバスエラーにフォールスルー
! 1685: putlog(3, "#%d retry exceeds", chan->ch);
1.1.1.10 root 1686: }
1687: }
1688:
1689: // バスエラー
1.1.1.11 root 1690: switch (op) {
1691: case RD_M8:
1692: case RD_M16:
1693: case WR_M8:
1694: case WR_M16:
1695: Error(chan, DMAC::CER_BUS_MAR);
1696: break;
1697: case RD_D8:
1698: case RD_D16:
1699: case WR_D8:
1700: case WR_D16:
1701: Error(chan, DMAC::CER_BUS_DAR);
1702: break;
1703: default:
1.1.1.12 root 1704: VMPANIC("corrupted op=%d", op);
1.1.1.11 root 1705: }
1706: }
1707:
1.1.1.13! root 1708: // 1転送ごとのログを出力。
! 1709: // ログを出力することが決まってから呼ばれる。
! 1710: void
! 1711: DMACDevice::TransferLog(DMACChan *chan, int op, busaddr addr,
! 1712: busdata r, uint64 data)
! 1713: {
! 1714: // Read $%06x -> $xx
! 1715: // Read $%06x -> BusErr
! 1716: // Read $%06x -> $xx (1 retried)
! 1717: // Write $%06x <- $xx
! 1718: // Write $%06x <- $xx BusErr
! 1719: // Write $%06x <- $xx (1 retried)
! 1720:
! 1721: if (op == NOP) {
! 1722: // どうする?
! 1723: return;
! 1724: }
! 1725:
! 1726: if (r.IsRetry()) {
! 1727: return;
! 1728: }
! 1729:
! 1730: const char *act;
! 1731: const char *dir;
! 1732: switch (op) {
! 1733: case RD_M8:
! 1734: case RD_D8:
! 1735: case RD_M16:
! 1736: case RD_D16:
! 1737: act = "Read ";
! 1738: dir = "->";
! 1739: break;
! 1740: case WR_M8:
! 1741: case WR_D8:
! 1742: case WR_M16:
! 1743: case WR_D16:
! 1744: act = "Write";
! 1745: dir = "<-";
! 1746: break;
! 1747: default:
! 1748: act = "";
! 1749: dir = "";
! 1750: break;
! 1751: }
! 1752:
! 1753: std::string str = string_format("#%d %s $%06x %s ",
! 1754: chan->ch, act, addr.Addr(), dir);
! 1755:
! 1756: switch (op) {
! 1757: case RD_M8:
! 1758: case RD_D8:
! 1759: if (r.IsOK()) {
! 1760: str += string_format("$%02x", r.Data());
! 1761: }
! 1762: break;
! 1763: case RD_M16:
! 1764: case RD_D16:
! 1765: if (r.IsOK()) {
! 1766: str += string_format("$%04x", r.Data());
! 1767: }
! 1768: case WR_M8:
! 1769: case WR_D8:
! 1770: str += string_format("$%02x", (uint32)data);
! 1771: break;
! 1772: case WR_M16:
! 1773: case WR_D16:
! 1774: str += string_format("$%04x", (uint32)data);
! 1775: break;
! 1776: default:
! 1777: break;
! 1778: }
! 1779:
! 1780: if (r.IsBusErr()) {
! 1781: str += " BusErr";
! 1782: }
! 1783:
! 1784: if (chan->retry != 0) {
! 1785: str += string_format(" (%d retried)", chan->retry);
! 1786: }
! 1787:
! 1788: putlogn("%s", str.c_str());
! 1789: }
! 1790:
1.1.1.11 root 1791: // エラー発生
1792: void
1793: DMACDevice::Error(DMACChan *chan, uint8 errcode)
1794: {
1795: // データシート p.43
1796: chan->cer = errcode;
1797: chan->csr |= DMAC::CSR_COC | DMAC::CSR_ERR;
1798: chan->active = false;
1799: chan->str = false;
1800: chan->cnt = false;
1.1.1.10 root 1801: ChangeInterrupt();
1.1.1.13! root 1802: CallAfter(StartCallback, 0, 0);
1.1.1.10 root 1803: }
1804:
1.1.1.11 root 1805: // ACK#n 信号線をアサート
1.1.1.10 root 1806: void
1.1.1.11 root 1807: DMACDevice::AssertACK(DMACChan *chan)
1.1.1.10 root 1808: {
1.1.1.11 root 1809: switch (chan->ch) {
1810: case 0:
1.1.1.12 root 1811: fdc->AssertDACK(chan->mtc == 1);
1.1.1.11 root 1812: break;
1813: case 1:
1.1.1.13! root 1814: case 2:
1.1.1.11 root 1815: // 接続されていない
1816: break;
1817: case 3:
1.1.1.12 root 1818: adpcm->AssertDACK(chan->mtc == 1);
1.1.1.10 root 1819: break;
1820: default:
1.1.1.13! root 1821: __unreachable();
1.1.1.10 root 1822: }
1.1.1.11 root 1823: }
1.1.1.10 root 1824:
1.1.1.11 root 1825: // ACK#n 信号線をネゲート
1826: void
1827: DMACDevice::NegateACK(DMACChan *chan)
1828: {
1829: switch (chan->ch) {
1830: case 0:
1.1.1.12 root 1831: fdc->NegateDACK();
1.1.1.11 root 1832: break;
1833: case 1:
1.1.1.13! root 1834: case 2:
1.1.1.11 root 1835: // 接続されていない
1836: break;
1837: case 3:
1.1.1.12 root 1838: adpcm->NegateDACK();
1.1.1.11 root 1839: break;
1840: default:
1.1.1.13! root 1841: __unreachable();
1.1.1.10 root 1842: }
1843: }
1.1.1.2 root 1844:
1.1.1.11 root 1845: // REQ#n 信号線アサート (外部から呼ばれる)
1.1.1.10 root 1846: void
1.1.1.11 root 1847: DMACDevice::AssertREQ(int ch)
1.1.1.10 root 1848: {
1.1.1.11 root 1849: assert(0 <= ch && ch < 4);
1.1.1.10 root 1850:
1.1.1.11 root 1851: DMACChan *chan = &channel[ch];
1852: chan->req = true;
1.1.1.2 root 1853:
1.1.1.11 root 1854: // #3(ADPCM) の REQ は PCL にも繋がっている
1855: if (ch == 3) {
1856: chan->pcl_pin = true;
1.1.1.2 root 1857: }
1858:
1.1.1.11 root 1859: if (event.IsRunning() == false) {
1.1.1.12 root 1860: scheduler->StartEvent(event);
1.1.1.2 root 1861: }
1.1.1.10 root 1862: }
1863:
1.1.1.11 root 1864: // REQ#n 信号線ネゲート (外部から呼ばれる)
1.1.1.10 root 1865: void
1.1.1.11 root 1866: DMACDevice::NegateREQ(int ch)
1.1.1.10 root 1867: {
1.1.1.11 root 1868: assert(0 <= ch && ch < 4);
1.1.1.10 root 1869:
1.1.1.11 root 1870: DMACChan *chan = &channel[ch];
1871: chan->req = false;
1.1.1.2 root 1872:
1.1.1.11 root 1873: // #3(ADPCM) の REQ は PCL にも繋がっている
1874: if (ch == 3) {
1875: chan->pcl_pin = false;
1.1.1.2 root 1876: }
1877: }
1878:
1879: // ソフトウェアアボート
1880: void
1.1.1.11 root 1881: DMACDevice::AbortTransfer(DMACChan *chan)
1.1.1.2 root 1882: {
1.1.1.11 root 1883: putlog(2, "CCR SAB Software Abort");
1.1.1.2 root 1884:
1885: // %1 を書き込むことで実際には SAB はセットされるが、ERR が立つと
1886: // SAB をクリアする動作のため、書き込んだ %1 が読めることはない。
1887: // ここでは SAB ビットのセットを省略。
1888:
1.1.1.11 root 1889: chan->str = false;
1890: chan->cnt = false;
1.1.1.10 root 1891: chan->active = false;
1.1.1.2 root 1892: chan->cer = DMAC::CER_SOFT_ABORT;
1.1.1.6 root 1893: // ERR ビットが立つと SAB をクリアする
1894: chan->csr |= DMAC::CSR_ERR;
1.1.1.11 root 1895: chan->sab = false;
1.1.1.6 root 1896: ChangeInterrupt();
1897: }
1898:
1.1.1.13! root 1899: // インデックス化されたアドレス start から end (の手前まで) のユーザ空間
! 1900: // アクセスの可否を設定する。x68kio から呼ばれる。
! 1901: // accessible true なら (MPU の FC2 ピンによらず) ユーザアクセス可能。
! 1902: // アドレスは 8KB 単位なので start=1 ならアドレスは $2000。
! 1903: void
! 1904: DMACDevice::SetUdevice(uint32 start, uint32 end, bool accessible)
! 1905: {
! 1906: for (int i = start; i < end; i++) {
! 1907: useraccess[i] = accessible;
! 1908: }
! 1909: }
! 1910:
1.1.1.6 root 1911: // 割り込み信号線の状態を変える。
1912: void
1913: DMACDevice::ChangeInterrupt()
1914: {
1915: bool irq = false;
1916:
1.1.1.11 root 1917: for (int ch = 0; ch < channel.size(); ch++) {
1918: DMACChan *chan = &channel[ch];
1.1.1.6 root 1919:
1.1.1.11 root 1920: if (chan->int_enable && chan->IsINTR()) {
1.1.1.6 root 1921: irq = true;
1922: }
1923: }
1.1.1.12 root 1924: interrupt->ChangeINT(this, irq);
1.1.1.6 root 1925: }
1926:
1927: // 割り込みアクノリッジ
1.1.1.13! root 1928: busdata
1.1.1.6 root 1929: DMACDevice::InterruptAcknowledge()
1930: {
1.1.1.11 root 1931: DMACChan *chan;
1.1.1.10 root 1932: int top = -1;
1933: uint8 prio = 255;
1934:
1935: // 割り込みを発生させているトッププライオリティのチャンネルを検索
1.1.1.11 root 1936: for (int ch = 0; ch < channel.size(); ch++) {
1937: chan = &channel[ch];
1.1.1.6 root 1938:
1.1.1.11 root 1939: if (chan->int_enable && chan->IsINTR()) {
1.1.1.10 root 1940: if (chan->priority < prio) {
1941: prio = chan->priority;
1942: top = ch;
1.1.1.6 root 1943: }
1.1.1.10 root 1944: }
1945: }
1946:
1.1.1.13! root 1947: if (__predict_true(top >= 0)) {
1.1.1.11 root 1948: chan = &channel[top];
1.1.1.10 root 1949: if ((chan->csr & DMAC::CSR_ERR)) {
1950: return chan->eiv;
1951: } else {
1952: return chan->niv;
1.1.1.6 root 1953: }
1.1.1.13! root 1954: } else {
! 1955: return busdata::BusErr;
1.1.1.6 root 1956: }
1.1.1.2 root 1957: }
1.1.1.11 root 1958:
1959: //
1960: // チャンネル
1961: //
1962:
1963: // CSR を取得する
1964: uint8
1965: DMACChan::GetCSR() const
1966: {
1967: uint32 val;
1968:
1969: val = csr & 0xf0;
1970: if (active) {
1971: val |= DMAC::CSR_ACT;
1972: }
1973: // PCT は PCL が High から Low に変わるとセット
1974: if (pcl_prev == true && pcl_pin == false) {
1975: val |= DMAC::CSR_PCT;
1976: }
1977: if (pcl_pin) {
1978: val |= DMAC::CSR_PCS;
1979: }
1980: return val;
1981: }
1982:
1983: // DCR を取得する
1984: uint8
1985: DMACChan::GetDCR() const
1986: {
1987: uint8 val;
1988:
1989: val = (xrm << 6);
1990: val |= (dtyp << 4);
1991: val |= (dps << 3);
1992: val |= dcr_pcl;
1993:
1994: return val;
1995: }
1996:
1997: // DCR を設定する
1998: void
1999: DMACChan::SetDCR(uint8 val)
2000: {
2001: xrm = (val >> 6);
2002: dtyp = (val >> 4) & 3;
2003: dps = (val >> 3) & 1;
2004: dcr_pcl = val & 3;
2005: }
2006:
2007: // OCR を取得する
2008: uint8
2009: DMACChan::GetOCR() const
2010: {
2011: uint8 val;
2012:
2013: val = (dir << 7);
2014: val |= (size << 4);
2015: val |= (chain << 2);
2016: val |= reqg;
2017:
2018: return val;
2019: }
2020:
2021: // OCR を設定する
2022: void
2023: DMACChan::SetOCR(uint8 val)
2024: {
2025: dir = (val >> 7);
2026: size = (val >> 4) & 3;
2027: chain = (val >> 2) & 3;
2028: reqg = val & 3;
2029: }
2030:
2031: // SCR を取得する
2032: uint8
2033: DMACChan::GetSCR() const
2034: {
2035: uint8 val;
2036:
2037: val = scr_mac << 2;
2038: val |= scr_dac;
2039:
2040: return val;
2041: }
2042:
2043: // SCR を設定する
2044: void
2045: DMACChan::SetSCR(uint8 val)
2046: {
2047: scr_mac = (val >> 2) & 3;
2048: scr_dac = val & 3;
2049: }
2050:
2051: // CCR を取得する
2052: uint8
2053: DMACChan::GetCCR() const
2054: {
2055: uint8 val = 0;
2056:
2057: if (str) {
2058: val |= DMAC::CCR_STR;
2059: }
2060: if (cnt) {
2061: val |= DMAC::CCR_CNT;
2062: }
2063: if (hlt) {
2064: val |= DMAC::CCR_HLT;
2065: }
2066: if (sab) {
2067: val |= DMAC::CCR_SAB;
2068: }
2069: if (int_enable) {
2070: val |= DMAC::CCR_INT;
2071: }
2072:
2073: return val;
2074: }
2075:
2076: // CCR を設定する (値を置く以上のことはしない)
2077: void
2078: DMACChan::SetCCR(uint8 val)
2079: {
2080: str = (val & DMAC::CCR_STR);
2081: cnt = (val & DMAC::CCR_CNT);
2082: hlt = (val & DMAC::CCR_HLT);
2083: sab = (val & DMAC::CCR_SAB);
2084: int_enable = (val & DMAC::CCR_INT);
2085: }
2086:
2087: // NIV を設定する
2088: void
2089: DMACChan::SetNIV(uint8 val)
2090: {
2091: niv = val;
2092: }
2093:
2094: // EIV を設定する
2095: void
2096: DMACChan::SetEIV(uint8 val)
2097: {
2098: eiv = val;
2099: }
2100:
2101: // MFC を設定する
2102: void
2103: DMACChan::SetMFC(uint8 val)
2104: {
1.1.1.13! root 2105: mfc = busaddr::FC(val & 0x07);
1.1.1.11 root 2106: }
2107:
2108: // CPR を設定する
2109: void
2110: DMACChan::SetCPR(uint8 val)
2111: {
2112: cpr = val & 0x03;
2113: // 実効プライオリティの上位4bitは cpr に等しい
2114: priority = cpr << 4;
2115: }
2116:
2117: // DFC を設定する
2118: void
2119: DMACChan::SetDFC(uint8 val)
2120: {
1.1.1.13! root 2121: dfc = busaddr::FC(val & 0x07);
1.1.1.11 root 2122: }
2123:
2124: // BFC を設定する
2125: void
2126: DMACChan::SetBFC(uint8 val)
2127: {
1.1.1.13! root 2128: bfc = busaddr::FC(val & 0x07);
1.1.1.11 root 2129: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.