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

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

unix.superglobalmegacorp.com

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