Annotation of nono/vm/dmac.cpp, revision 1.1.1.13

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.