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