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

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.3   root       12: #include "bus.h"
1.1.1.6   root       13: #include "interrupt.h"
1.1.1.10! root       14: #include "mpu.h"
        !            15: #include "scheduler.h"
        !            16: 
        !            17: // time 時間後に呼び出すコールバックをセットする。
        !            18: // func の書式が面倒なのを省略して書きたいため。
        !            19: #define CallAfter(func_, time_)        do { \
        !            20:        event.func = ToEventCallback(&DMACDevice::func_); \
        !            21:        event.time = time_ * 80_nsec; \
        !            22:        gScheduler->StartEvent(event); \
        !            23: } while (0)
1.1.1.2   root       24: 
1.1.1.10! root       25: // グローバル参照用
        !            26: DMACDevice *gDMAC;
1.1       root       27: 
1.1.1.10! root       28: // コンストラクタ
1.1       root       29: DMACDevice::DMACDevice()
1.1.1.8   root       30:        : inherited("DMAC")
1.1       root       31: {
                     32:        devaddr = baseaddr;
                     33:        devlen  = 0x2000;
1.1.1.2   root       34: 
                     35:        for (int i = 0; i < countof(dmac.chan); i++) {
                     36:                dmac.chan[i].ch = i;
                     37:                dmac.chan[i].parent = this;
                     38:        }
                     39:        dmac.chan[0].desc = "FD";
                     40:        dmac.chan[1].desc = "HD";
                     41:        dmac.chan[2].desc = "User";
                     42:        dmac.chan[3].desc = "ADPCM";
                     43: 
1.1.1.10! root       44:        event.Regist("DMAC");
1.1.1.8   root       45: 
1.1.1.10! root       46:        monitor.func = ToMonitorCallback(&DMACDevice::MonitorUpdate);
1.1.1.8   root       47:        monitor.SetSize(80, 30);
                     48:        monitor.Regist(ID_MONITOR_DMAC);
1.1       root       49: }
                     50: 
1.1.1.10! root       51: // デストラクタ
1.1       root       52: DMACDevice::~DMACDevice()
                     53: {
1.1.1.10! root       54:        gDMAC = NULL;
1.1       root       55: }
                     56: 
1.1.1.10! root       57: // リセット
1.1.1.5   root       58: void
1.1.1.10! root       59: DMACDevice::ResetHard(bool poweron)
1.1.1.5   root       60: {
                     61:        putlog(2, "リセット");
                     62: 
                     63:        // Clears GCR, DCR, OCR, SCR, CCR, CSR, CPR and CER for all channels.
                     64:        // NIV and EIV are all set to $0F (uninitialized interrupt vector).
                     65:        // MTC, MAR, DAR, BTC, BAR, MFC, DFC and BFC are not affected.
                     66: 
                     67:        dmac.gcr = 0;
                     68:        for (int ch = 0; ch < countof(dmac.chan); ch++) {
                     69:                DMAC::Channel *chan = &dmac.chan[ch];
                     70:                chan->dcr = 0;
                     71:                chan->ocr = 0;
                     72:                chan->scr = 0;
                     73:                chan->ccr = 0;
                     74:                chan->csr = 0;
                     75:                chan->active = false;
                     76:                chan->pcl = false;
                     77:                chan->cpr = 0;
                     78:                chan->cer = 0;
                     79: 
                     80:                chan->niv = 0x0f;
                     81:                chan->eiv = 0x0f;
                     82: 
1.1.1.10! root       83:                chan->priority = 0;
1.1.1.5   root       84:        }
1.1.1.10! root       85: 
        !            86:        // イベントを停止
        !            87:        event.SetName("DMAC");
        !            88:        gScheduler->StopEvent(event);
1.1.1.5   root       89: }
                     90: 
1.1       root       91: uint64
1.1.1.7   root       92: DMACDevice::Read(uint32 offset)
1.1       root       93: {
                     94:        uint8 data;
                     95:        int ch;
                     96: 
1.1.1.5   root       97:        gMPU->AddCycle(37);     // InsideOut p.135
                     98: 
1.1.1.7   root       99:        ch = offset / 0x40;
1.1.1.2   root      100:        DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.7   root      101:        int n = offset % 0x40;
1.1       root      102:        switch (n) {
                    103:         case DMAC::CSR:
1.1.1.2   root      104:                data = chan->PeekCSR();
                    105:                putlog(4, "#%d CSR -> $%02x", ch, data);
1.1       root      106:                break;
                    107: 
                    108:         case DMAC::CER:
                    109:                data = chan->cer;
1.1.1.2   root      110:                putlog(4, "#%d CER -> $%02x", ch, data);
1.1       root      111:                break;
                    112: 
                    113:         case DMAC::DCR:
                    114:                data = chan->dcr;
1.1.1.2   root      115:                putlog(4, "#%d DCR -> $%02x", ch, data);
1.1       root      116:                break;
                    117: 
                    118:         case DMAC::OCR:
                    119:                data = chan->ocr;
1.1.1.2   root      120:                putlog(4, "#%d OCR -> $%02x", ch, data);
1.1       root      121:                break;
                    122: 
                    123:         case DMAC::SCR:
                    124:                data = chan->scr;
1.1.1.2   root      125:                putlog(4, "#%d SCR -> $%02x", ch, data);
1.1       root      126:                break;
                    127: 
                    128:         case DMAC::CCR:
1.1.1.6   root      129:                data = chan->ccr;
1.1.1.2   root      130:                putlog(4, "#%d CCR -> $%02x", ch, data);
1.1       root      131:                break;
                    132: 
                    133:         case DMAC::MTC:
                    134:                data = chan->mtc >> 8;
1.1.1.2   root      135:                putlog(4, "#%d MTC:H -> $%02x", ch, data);
1.1       root      136:                break;
                    137:         case DMAC::MTC + 1:
                    138:                data = chan->mtc & 0xff;
1.1.1.2   root      139:                putlog(4, "#%d MTC:L -> $%02x", ch, data);
1.1       root      140:                break;
                    141: 
                    142:         case DMAC::MAR:
                    143:                data = chan->mar >> 24;
1.1.1.2   root      144:                putlog(4, "#%d MAR:0 -> $%02x", ch, data);
1.1       root      145:                break;
                    146:         case DMAC::MAR + 1:
                    147:                data = (chan->mar >> 16) & 0xff;
1.1.1.2   root      148:                putlog(4, "#%d MAR:1 -> $%02x", ch, data);
1.1       root      149:                break;
                    150:         case DMAC::MAR + 2:
                    151:                data = (chan->mar >> 8) & 0xff;
1.1.1.2   root      152:                putlog(4, "#%d MAR:2 -> $%02x", ch, data);
1.1       root      153:                break;
                    154:         case DMAC::MAR + 3:
                    155:                data = chan->mar & 0xff;
1.1.1.2   root      156:                putlog(4, "#%d MAR:3 -> $%02x", ch, data);
1.1       root      157:                break;
                    158: 
                    159:         case DMAC::DAR:
                    160:                data = chan->dar >> 24;
1.1.1.2   root      161:                putlog(4, "#%d DAR:0 -> $%02x", ch, data);
1.1       root      162:                break;
                    163:         case DMAC::DAR + 1:
                    164:                data = (chan->dar >> 16) & 0xff;
1.1.1.2   root      165:                putlog(4, "#%d DAR:1 -> $%02x", ch, data);
1.1       root      166:                break;
                    167:         case DMAC::DAR + 2:
                    168:                data = (chan->dar >> 8) & 0xff;
1.1.1.2   root      169:                putlog(4, "#%d DAR:2 -> $%02x", ch, data);
1.1       root      170:                break;
                    171:         case DMAC::DAR + 3:
                    172:                data = chan->dar & 0xff;
1.1.1.2   root      173:                putlog(4, "#%d DAR:3 -> $%02x", ch, data);
1.1       root      174:                break;
                    175: 
                    176:         case DMAC::BTC:
                    177:                data = chan->btc >> 8;
1.1.1.2   root      178:                putlog(4, "#%d BTC:H -> $%02x", ch, data);
1.1       root      179:                break;
                    180:         case DMAC::BTC + 1:
                    181:                data = chan->btc & 0xff;
1.1.1.2   root      182:                putlog(4, "#%d BTC:L -> $%02x", ch, data);
1.1       root      183:                break;
                    184: 
                    185:         case DMAC::BAR:
                    186:                data = chan->bar >> 24;
1.1.1.2   root      187:                putlog(4, "#%d BAR:0 -> $%02x", ch, data);
1.1       root      188:                break;
                    189:         case DMAC::BAR + 1:
                    190:                data = (chan->bar >> 16) & 0xff;
1.1.1.2   root      191:                putlog(4, "#%d BAR:1 -> $%02x", ch, data);
1.1       root      192:                break;
                    193:         case DMAC::BAR + 2:
                    194:                data = (chan->bar >> 8) & 0xff;
1.1.1.2   root      195:                putlog(4, "#%d BAR:2 -> $%02x", ch, data);
1.1       root      196:                break;
                    197:         case DMAC::BAR + 3:
                    198:                data = chan->bar & 0xff;
1.1.1.2   root      199:                putlog(4, "#%d BAR:3 -> $%02x", ch, data);
1.1       root      200:                break;
                    201: 
                    202:         case DMAC::NIV:
                    203:                data = chan->niv;
1.1.1.2   root      204:                putlog(4, "#%d NIV -> $%02x", ch, data);
1.1       root      205:                break;
                    206: 
                    207:         case DMAC::EIV:
                    208:                data = chan->eiv;
1.1.1.2   root      209:                putlog(4, "#%d EIV -> $%02x", ch, data);
1.1       root      210:                break;
                    211: 
                    212:         case DMAC::MFC:
                    213:                data = chan->mfc;
1.1.1.2   root      214:                putlog(4, "#%d MFC -> $%02x", ch, data);
1.1       root      215:                break;
                    216: 
                    217:         case DMAC::CPR:
                    218:                data = chan->cpr;
1.1.1.2   root      219:                putlog(4, "#%d CPR -> $%02x", ch, data);
1.1       root      220:                break;
                    221: 
                    222:         case DMAC::DFC:
                    223:                data = chan->dfc;
1.1.1.2   root      224:                putlog(4, "#%d DFC -> $%02x", ch, data);
1.1       root      225:                break;
                    226: 
                    227:         case DMAC::BFC:
                    228:                data = chan->bfc;
1.1.1.2   root      229:                putlog(4, "#%d BFC -> $%02x", ch, data);
1.1       root      230:                break;
                    231: 
                    232:         case DMAC::GCR:
                    233:                if (ch == 3) {
                    234:                        data = dmac.gcr;
1.1.1.2   root      235:                        putlog(4, "GCR -> $%02x", data);
1.1       root      236:                        break;
                    237:                } else {
                    238:                        data = 0xff;
                    239:                }
                    240:                break;
                    241: 
                    242:         default:
                    243:                data = 0xff;
                    244:                break;
                    245:        }
                    246: 
                    247:        return data;
                    248: }
                    249: 
                    250: uint64
1.1.1.7   root      251: DMACDevice::Write(uint32 offset, uint32 data)
1.1       root      252: {
                    253:        int ch;
                    254: 
1.1.1.5   root      255:        gMPU->AddCycle(31);     // InsideOut p.135
                    256: 
1.1.1.7   root      257:        ch = offset / 0x40;
1.1.1.2   root      258:        DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.7   root      259:        int n = offset % 0x40;
1.1       root      260:        switch (n) {
                    261:         case DMAC::CSR:
1.1.1.2   root      262:                chan->WriteCSR(data);
1.1.1.6   root      263:                ChangeInterrupt();
1.1       root      264:                break;
                    265: 
                    266:         case DMAC::CER:
                    267:                // Read only
                    268:                break;
                    269: 
                    270:         case DMAC::DCR:
1.1.1.2   root      271:                putlog(4, "#%d DCR <- $%02x", ch, data);
1.1       root      272:                chan->dcr = data & 0xfb;
                    273:                break;
                    274: 
                    275:         case DMAC::OCR:
1.1.1.2   root      276:                putlog(4, "#%d OCR <- $%02x", ch, data);
1.1       root      277:                chan->ocr = data;
                    278:                break;
                    279: 
                    280:         case DMAC::SCR:
1.1.1.2   root      281:                putlog(4, "#%d SCR <- $%02x", ch, data);
1.1       root      282:                chan->scr = data & 0x0f;
                    283:                break;
                    284: 
                    285:         case DMAC::CCR:
1.1.1.2   root      286:                putlog(4, "#%d CCR <- $%02x", ch, data);
                    287:                chan->WriteCCR(data);
1.1.1.6   root      288:                ChangeInterrupt();
1.1       root      289:                break;
                    290: 
                    291:         case DMAC::MTC:
                    292:                chan->mtc = (chan->mtc & 0x00ff) | (data << 8);
1.1.1.2   root      293:                putlog(4, "#%d MTC:H <- $%02x (MTC=$%04x)", ch, data, chan->mtc);
1.1       root      294:                break;
                    295:         case DMAC::MTC + 1:
                    296:                chan->mtc = (chan->mtc & 0xff00) | data;
1.1.1.2   root      297:                putlog(4, "#%d MTC:L <- $%02x (MTC=$%04x)", ch, data, chan->mtc);
1.1       root      298:                break;
                    299: 
                    300:         case DMAC::MAR:
                    301:                chan->mar = (chan->mar & 0x00ffffff) | (data << 24);
1.1.1.2   root      302:                putlog(4, "#%d MAR:0 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1       root      303:                break;
                    304:         case DMAC::MAR + 1:
                    305:                chan->mar = (chan->mar & 0xff00ffff) | (data << 16);
1.1.1.2   root      306:                putlog(4, "#%d MAR:1 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1       root      307:                break;
                    308:         case DMAC::MAR + 2:
                    309:                chan->mar = (chan->mar & 0xffff00ff) | (data << 8);
1.1.1.2   root      310:                putlog(4, "#%d MAR:2 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1       root      311:                break;
                    312:         case DMAC::MAR + 3:
                    313:                chan->mar = (chan->mar & 0xffffff00) | data;
1.1.1.2   root      314:                putlog(4, "#%d MAR:3 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1       root      315:                break;
                    316: 
                    317:         case DMAC::DAR:
                    318:                chan->dar = (chan->dar & 0x00ffffff) | (data << 24);
1.1.1.2   root      319:                putlog(4, "#%d DAR:0 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1       root      320:                break;
                    321:         case DMAC::DAR + 1:
                    322:                chan->dar = (chan->dar & 0xff00ffff) | (data << 16);
1.1.1.2   root      323:                putlog(4, "#%d DAR:1 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1       root      324:                break;
                    325:         case DMAC::DAR + 2:
                    326:                chan->dar = (chan->dar & 0xffff00ff) | (data << 8);
1.1.1.2   root      327:                putlog(4, "#%d DAR:2 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1       root      328:                break;
                    329:         case DMAC::DAR + 3:
                    330:                chan->dar = (chan->dar & 0xffffff00) | data;
1.1.1.2   root      331:                putlog(4, "#%d DAR:3 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1       root      332:                break;
                    333: 
                    334:         case DMAC::BTC:
                    335:                chan->btc = (chan->btc & 0x00ff) | (data << 8);
1.1.1.2   root      336:                putlog(4, "#%d BTC:H <- $%02x (BTC=$%04x)", ch, data, chan->btc);
1.1       root      337:                break;
                    338:         case DMAC::BTC + 1:
                    339:                chan->btc = (chan->btc & 0xff00) | data;
1.1.1.2   root      340:                putlog(4, "#%d BTC:L <- $%02x (BTC=$%04x)", ch, data, chan->btc);
1.1       root      341:                break;
                    342: 
                    343:         case DMAC::BAR:
                    344:                chan->bar = (chan->bar & 0x00ffffff) | (data << 24);
1.1.1.2   root      345:                putlog(4, "#%d BAR:0 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1       root      346:                break;
                    347:         case DMAC::BAR + 1:
                    348:                chan->bar = (chan->bar & 0xff00ffff) | (data << 16);
1.1.1.2   root      349:                putlog(4, "#%d BAR:1 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1       root      350:                break;
                    351:         case DMAC::BAR + 2:
                    352:                chan->bar = (chan->bar & 0xffff00ff) | (data << 8);
1.1.1.2   root      353:                putlog(4, "#%d BAR:2 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1       root      354:                break;
                    355:         case DMAC::BAR + 3:
                    356:                chan->bar = (chan->bar & 0xffffff00) | data;
1.1.1.2   root      357:                putlog(4, "#%d BAR:3 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1       root      358:                break;
                    359: 
                    360:         case DMAC::NIV:
1.1.1.2   root      361:                putlog(4, "#%d NIV <- $%02x", ch, data);
1.1       root      362:                chan->niv = data;
                    363:                break;
                    364: 
                    365:         case DMAC::EIV:
1.1.1.2   root      366:                putlog(4, "#%d EIV <- $%02x", ch, data);
1.1       root      367:                chan->eiv = data;
                    368:                break;
                    369: 
                    370:         case DMAC::MFC:
1.1.1.2   root      371:                putlog(4, "#%d MFC <- $%02x", ch, data);
1.1       root      372:                chan->mfc = data & 7;
                    373:                break;
                    374: 
                    375:         case DMAC::CPR:
1.1.1.2   root      376:                putlog(4, "#%d CPR <- $%02x", ch, data);
1.1       root      377:                chan->cpr = data & 3;
1.1.1.10! root      378:                // 実効プライオリティの上位4bitは cpr に等しい
        !           379:                chan->priority = (chan->cpr << 4);
1.1       root      380:                break;
                    381: 
                    382:         case DMAC::DFC:
1.1.1.2   root      383:                putlog(4, "#%d DFC <- $%02x", ch, data);
1.1       root      384:                chan->dfc = data & 7;
                    385:                break;
                    386: 
                    387:         case DMAC::BFC:
1.1.1.2   root      388:                putlog(4, "#%d BFC <- $%02x", ch, data);
1.1       root      389:                chan->bfc = data & 7;
                    390:                break;
                    391: 
                    392:         case DMAC::GCR:
                    393:                if (ch == 3) {
1.1.1.2   root      394:                        putlog(4, "GCR <- $%02x", data);
1.1       root      395:                        dmac.gcr = data;
                    396:                }
                    397:                break;
                    398: 
                    399:         default:
                    400:                break;
                    401:        }
                    402:        return 0;
                    403: }
                    404: 
                    405: uint64
1.1.1.7   root      406: DMACDevice::Peek(uint32 offset)
1.1       root      407: {
                    408:        uint8 data;
                    409:        int ch;
                    410: 
1.1.1.7   root      411:        ch = offset / 0x40;
1.1.1.2   root      412:        const DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.7   root      413:        int n = offset % 0x40;
1.1       root      414:        switch (n) {
                    415:         case DMAC::CSR:
1.1.1.2   root      416:                data = chan->PeekCSR();
1.1       root      417:                break;
                    418: 
                    419:         case DMAC::CER:
                    420:                data = chan->cer;
                    421:                break;
                    422: 
                    423:         case DMAC::DCR:
                    424:                data = chan->dcr;
                    425:                break;
                    426: 
                    427:         case DMAC::OCR:
                    428:                data = chan->ocr;
                    429:                break;
                    430: 
                    431:         case DMAC::SCR:
                    432:                data = chan->scr;
                    433:                break;
                    434: 
                    435:         case DMAC::CCR:
1.1.1.6   root      436:                data = chan->ccr;
1.1       root      437:                break;
                    438: 
                    439:         case DMAC::MTC:
                    440:                data = chan->mtc >> 8;
                    441:                break;
                    442:         case DMAC::MTC + 1:
                    443:                data = chan->mtc & 0xff;
                    444:                break;
                    445: 
                    446:         case DMAC::MAR:
                    447:                data = chan->mar >> 24;
                    448:                break;
                    449:         case DMAC::MAR + 1:
                    450:                data = (chan->mar >> 16) & 0xff;
                    451:                break;
                    452:         case DMAC::MAR + 2:
                    453:                data = (chan->mar >> 8) & 0xff;
                    454:                break;
                    455:         case DMAC::MAR + 3:
                    456:                data = chan->mar & 0xff;
                    457:                break;
                    458: 
                    459:         case DMAC::DAR:
                    460:                data = chan->dar >> 24;
                    461:                break;
                    462:         case DMAC::DAR + 1:
                    463:                data = (chan->dar >> 16) & 0xff;
                    464:                break;
                    465:         case DMAC::DAR + 2:
                    466:                data = (chan->dar >> 8) & 0xff;
                    467:                break;
                    468:         case DMAC::DAR + 3:
                    469:                data = chan->dar & 0xff;
                    470:                break;
                    471: 
                    472:         case DMAC::BTC:
                    473:                data = chan->btc >> 8;
                    474:                break;
                    475:         case DMAC::BTC + 1:
                    476:                data = chan->btc & 0xff;
                    477:                break;
                    478: 
                    479:         case DMAC::BAR:
                    480:                data = chan->bar >> 24;
                    481:                break;
                    482:         case DMAC::BAR + 1:
                    483:                data = (chan->bar >> 16) & 0xff;
                    484:                break;
                    485:         case DMAC::BAR + 2:
                    486:                data = (chan->bar >> 8) & 0xff;
                    487:                break;
                    488:         case DMAC::BAR + 3:
                    489:                data = chan->bar & 0xff;
                    490:                break;
                    491: 
                    492:         case DMAC::NIV:
                    493:                data = chan->niv;
                    494:                break;
                    495: 
                    496:         case DMAC::EIV:
                    497:                data = chan->eiv;
                    498:                break;
                    499: 
                    500:         case DMAC::MFC:
                    501:                data = chan->mfc;
                    502:                break;
                    503: 
                    504:         case DMAC::CPR:
                    505:                data = chan->cpr;
                    506:                break;
                    507: 
                    508:         case DMAC::DFC:
                    509:                data = chan->dfc;
                    510:                break;
                    511: 
                    512:         case DMAC::BFC:
                    513:                data = chan->bfc;
                    514:                break;
                    515: 
                    516:         case DMAC::GCR:
                    517:                if (ch == 3) {
                    518:                        data = dmac.gcr;
                    519:                        break;
                    520:                } else {
                    521:                        data = 0xff;
                    522:                }
                    523:                break;
                    524: 
                    525:         default:
                    526:                data = 0xff;
                    527:                break;
                    528:        }
                    529: 
                    530:        return data;
                    531: }
                    532: 
1.1.1.4   root      533: void
1.1.1.8   root      534: DMACDevice::MonitorUpdate(Monitor *, TextScreen& screen)
1.1.1.2   root      535: {
                    536:        int x;
                    537:        int y;
                    538: 
1.1.1.8   root      539:        screen.Clear();
1.1.1.2   root      540: 
                    541:        y = 1;
1.1.1.8   root      542:        screen.Puts(0, y++, "CSR");
1.1.1.2   root      543:        y += 2;
1.1.1.8   root      544:        screen.Puts(0, y++, "CER");
                    545:        screen.Puts(0, y++, "DCR:XRM");
                    546:        screen.Puts(0, y++, "DCR:DTYP");
                    547:        screen.Puts(0, y++, "DCR:DPS");
                    548:        screen.Puts(0, y++, "DCR:PCL");
                    549:        screen.Puts(0, y++, "OCR:DIR");
                    550:        screen.Puts(0, y++, "OCR:SIZE");
                    551:        screen.Puts(0, y++, "OCR:CHAIN");
                    552:        screen.Puts(0, y++, "OCR:REQG");
                    553:        screen.Puts(0, y++, "SCR:MAC");
                    554:        screen.Puts(0, y++, "SCR:DAC");
                    555:        screen.Puts(0, y++, "CCR");
1.1.1.2   root      556:        y += 2;
1.1.1.8   root      557:        screen.Puts(0, y++, "MTC");
                    558:        screen.Puts(0, y++, "MAR");
                    559:        screen.Puts(0, y++, "DAR");
                    560:        screen.Puts(0, y++, "BTC");
                    561:        screen.Puts(0, y++, "BAR");
                    562:        screen.Puts(0, y++, "NIV");
                    563:        screen.Puts(0, y++, "EIV");
                    564:        screen.Puts(0, y++, "MFC");
                    565:        screen.Puts(0, y++, "CPR");
                    566:        screen.Puts(0, y++, "DFC");
                    567:        screen.Puts(0, y++, "BFC");
1.1.1.2   root      568: 
                    569:        for (int ch = 0; ch < 4; ch++) {
                    570:                DMAC::Channel *chan = &dmac.chan[ch];
                    571:                int val;
                    572:                x = 12 + ch * 17;
                    573:                y = 0;
                    574: 
                    575:                // 地味だけど有効なチャンネルをハイライトしてみる
1.1.1.8   root      576:                screen.Print(x, y++, (chan->active ? TA::Em : TA::Normal),
1.1.1.2   root      577:                        "#%d (%s)", chan->ch, chan->desc);
                    578: 
                    579:                // CSR
                    580:                val = chan->PeekCSR();
1.1.1.8   root      581:                screen.Print(x, y++, "$%02x", val);
1.1.1.2   root      582:                static const char * const csrname[] = {
1.1.1.9   root      583:                        "COC", "BTC", "NDT", "ERR", "ACT", "-", "PCT", "PCS",
1.1.1.2   root      584:                };
1.1.1.8   root      585:                MonitorReg4(screen, x, y++, val >> 4,   &csrname[0]);
                    586:                MonitorReg4(screen, x, y++, val & 0xff, &csrname[4]);
1.1.1.2   root      587: 
                    588:                // CER
                    589:                val = chan->cer & 0x1f;
                    590:                const char *e;
                    591:                if (val <= 0x11 && errnames[val]) {
                    592:                        e = errnames[val];
                    593:                } else {
                    594:                        e = "?";
                    595:                }
1.1.1.8   root      596:                screen.Print(x, y, "$%02x", chan->cer);
1.1.1.2   root      597:                if (val > 0) {
1.1.1.8   root      598:                        screen.Print(x + 3, y, ":%s", e);
1.1.1.2   root      599:                }
                    600:                y++;
                    601: 
                    602:                // DCR:XRM
                    603:                static const char * const dcr_xrm[] = {
                    604:                        //1234567890123
                    605:                        "Burst",
                    606:                        "undefined",
                    607:                        "CycleW/O Hold",
                    608:                        "CycleWithHold",
                    609:                };
                    610:                val = chan->dcr >> 6;
1.1.1.8   root      611:                screen.Print(x, y++, "%d:%s", val, dcr_xrm[val]);
1.1.1.2   root      612: 
                    613:                // DCR:DTYP
                    614:                static const char * const dcr_dtyp[] = {
                    615:                        //1234567890123
                    616:                        "68000",
                    617:                        "6800",
                    618:                        "ACK",
                    619:                        "ACK+READY",
                    620:                };
                    621:                val = (chan->dcr >> 4) & 3;
1.1.1.8   root      622:                screen.Print(x, y++, "%d:%s", val, dcr_dtyp[val]);
1.1.1.2   root      623: 
                    624:                // DCR:DPS
                    625:                static const char * const dcr_dps[] = {
                    626:                        //1234567890123
                    627:                        "8bit",
                    628:                        "16bit",
                    629:                };
                    630:                val = (chan->dcr >> 3) & 1;
1.1.1.8   root      631:                screen.Print(x, y++, "%d:%s", val, dcr_dps[val]);
1.1.1.2   root      632: 
                    633:                // DCR:PCL
1.1.1.8   root      634:                screen.Print(x, y++, "XXX PCL");
1.1.1.2   root      635: 
                    636:                // OCR:DIR
                    637:                static const char * const ocr_dir[] = {
                    638:                        //1234567890123
                    639:                        "MemoryToDevice",
                    640:                        "DeviceToMemory",
                    641:                };
                    642:                val = (chan->ocr >> 7);
1.1.1.8   root      643:                screen.Print(x, y++, "%d:%s", val, ocr_dir[val]);
1.1.1.2   root      644: 
                    645:                // OCR:SIZE
                    646:                static const char * const ocr_size[] = {
                    647:                        //1234567890123
                    648:                        "8bit",
                    649:                        "16bit",
                    650:                        "32bit",
                    651:                        "8bit Unpacked",
                    652:                };
                    653:                val = (chan->ocr >> 4) & 3;
1.1.1.8   root      654:                screen.Print(x, y++, "%d:%s", val, ocr_size[val]);
1.1.1.2   root      655: 
                    656:                // OCR:CHAIN
                    657:                static const char * const ocr_chain[] = {
                    658:                        //1234567890123
                    659:                        "NoChain",
                    660:                        "undefined",
                    661:                        "ArrayChain",
                    662:                        "LinkArrayChain",
                    663:                };
                    664:                val = (chan->ocr >> 2) & 3;
1.1.1.8   root      665:                screen.Print(x, y++, "%d:%s", val, ocr_chain[val]);
1.1.1.2   root      666: 
                    667:                // OCR:REQG
                    668:                static const char * const ocr_reqg[] = {
                    669:                        //1234567890123
                    670:                        "AutoReq(Limit)",
                    671:                        "AutoReq(Max)",
                    672:                        "ExternalReq",
                    673:                        "AutoThenExt",
                    674:                };
                    675:                val = (chan->ocr & 3);
1.1.1.8   root      676:                screen.Print(x, y++, "%d:%s", val, ocr_reqg[val]);
1.1.1.2   root      677: 
                    678:                // SCR:MAC
                    679:                static const char * const scr_xac[] = {
                    680:                        //1234567890123
                    681:                        "NoCount",
                    682:                        "CountUp",
                    683:                        "CountDown",
                    684:                        "undefined",
                    685:                };
                    686:                val = (chan->scr >> 2) & 3;
1.1.1.8   root      687:                screen.Print(x, y++, "%d:%s", val, scr_xac[val]);
1.1.1.2   root      688:                val = chan->scr & 3;
1.1.1.8   root      689:                screen.Print(x, y++, "%d:%s", val, scr_xac[val]);
1.1.1.2   root      690: 
                    691:                // CCR
1.1.1.6   root      692:                val = chan->ccr;
1.1.1.8   root      693:                screen.Print(x, y++, "$%02x", val);
1.1.1.2   root      694:                static const char * const ccrnames[] = {
1.1.1.9   root      695:                        "STR", "CNT", "HLT", "SAB", "INT", "-", "-", "-",
1.1.1.2   root      696:                };
1.1.1.8   root      697:                MonitorReg4(screen, x, y++, (val >> 4),   &ccrnames[0]);
                    698:                MonitorReg4(screen, x, y++, (val & 0xff), &ccrnames[4]);
1.1.1.2   root      699: 
                    700:                // MTC
1.1.1.8   root      701:                screen.Print(x, y++, "$%04x", chan->mtc);
1.1.1.2   root      702:                // MAR
                    703:                // X680x0 がターゲットなので24bit超える設定は目立たせる
                    704:                if (chan->mar > 0xffffff) {
1.1.1.8   root      705:                        screen.Print(x, y++, TA::On, "$%08x", chan->mar);
1.1.1.2   root      706:                } else {
1.1.1.8   root      707:                        screen.Print(x, y++, "$%06x", chan->mar);
1.1.1.2   root      708:                }
                    709:                // DAR
                    710:                if (chan->dar > 0xffffff) {
1.1.1.8   root      711:                        screen.Print(x, y++, TA::On, "$%08x", chan->dar);
1.1.1.2   root      712:                } else {
1.1.1.8   root      713:                        screen.Print(x, y++, "$%06x", chan->dar);
1.1.1.2   root      714:                }
                    715:                // BTC
1.1.1.8   root      716:                screen.Print(x, y++, "$%04x", chan->btc);
1.1.1.2   root      717:                // BAR
                    718:                if (chan->bar > 0xffffff) {
1.1.1.8   root      719:                        screen.Print(x, y++, TA::On, "$%08x", chan->bar);
1.1.1.2   root      720:                } else {
1.1.1.8   root      721:                        screen.Print(x, y++, "$%06x", chan->bar);
1.1.1.2   root      722:                }
                    723: 
                    724:                // NIV
1.1.1.8   root      725:                screen.Print(x, y++, "$%02x", chan->niv);
1.1.1.2   root      726:                // EIV
1.1.1.8   root      727:                screen.Print(x, y++, "$%02x", chan->eiv);
1.1.1.2   root      728: 
                    729:                // MFC
1.1.1.8   root      730:                screen.Print(x, y++, "$%02x", chan->mfc);
1.1.1.2   root      731:                // CPR
1.1.1.8   root      732:                screen.Print(x, y++, "$%02x", chan->cpr);
1.1.1.2   root      733:                // DFC
1.1.1.8   root      734:                screen.Print(x, y++, "$%02x", chan->dfc);
1.1.1.2   root      735:                // BFC
1.1.1.8   root      736:                screen.Print(x, y++, "$%02x", chan->bfc);
1.1.1.2   root      737: 
                    738:                if (ch == 3) {
1.1.1.8   root      739:                        screen.Print(x - 5, y++, "GCR: $%02x", dmac.gcr);
1.1.1.2   root      740:                }
                    741:        }
                    742: }
                    743: 
                    744: // 4ビット分を表示する。MonitorUpdate の下請け
                    745: void
1.1.1.8   root      746: DMACDevice::MonitorReg4(TextScreen& screen,
1.1.1.4   root      747:        int x, int y, uint32 reg, const char * const *names)
1.1.1.2   root      748: {
                    749:        for (int i = 0; i < 4; i++) {
1.1.1.9   root      750:                if (names[i][0] == '-') {
                    751:                        screen.Puts(x + i * 4, y, TA::Disable, "---");
                    752:                } else {
                    753:                        bool b = reg & (1 << (3 - i));
                    754:                        screen.Puts(x + i * 4, y, TA::OnOff(b), names[i]);
                    755:                }
1.1.1.2   root      756:        }
                    757: }
                    758: 
                    759: /*static*/ const char * const
                    760: DMACDevice::errnames[] = {
                    761:        //12345678901
                    762:        "",                             // $00 No Error
                    763:        "ConfigErr",    // $01
                    764:        "OperTiming",   // $02
                    765:        NULL,                   // $03
                    766:        NULL,                   // $04
                    767:        "AddrErrInMAR", // $05
                    768:        "AddrErrInDAR", // $06
                    769:        "AddrErrInBAR", // $07
                    770:        NULL,                   // $08
                    771:        "BusErrInMAR",  // $09
                    772:        "BusErrInDAR",  // $0a
                    773:        "BusErrInBAR",  // $0b
                    774:        NULL,                   // $0c
                    775:        "CntErrInMTC",  // $0d
                    776:        NULL,                   // $0e
                    777:        "CntErrInBTC",  // $0f
                    778:        "ExternAbort",  // $10
                    779:        "SoftAbort",    // $11
                    780: };
                    781: 
                    782: // Read と Peek とそれ以外からも呼ばれるので副作用を持たせてはいけない。
                    783: uint8
                    784: DMAC::Channel::PeekCSR() const
                    785: {
                    786:        uint32 val;
                    787: 
                    788:        val = csr & 0xf0;
                    789:        if (active) {
                    790:                val |= CSR_ACT;
                    791:        }
                    792:        // PCT は PCL が High から Low に変わるとセット
                    793:        if (prev_pcl == true && pcl == false) {
                    794:                val |= CSR_PCT;
                    795:        }
                    796:        if (pcl) {
                    797:                val |= CSR_PCS;
                    798:        }
                    799:        return val;
                    800: }
                    801: 
1.1.1.6   root      802: // CSR への書き込み。
                    803: // CSR への書き込みによって割り込み信号線が変化するかも知れないので
                    804: // この後呼び出し側が ChangeInterrupt() を呼ぶこと。
1.1       root      805: void
1.1.1.2   root      806: DMAC::Channel::WriteCSR(uint32 data)
1.1       root      807: {
1.1.1.2   root      808:        // 上位4ビットは %1 の書き込みでクリア
                    809:        csr &= ~(data & 0xf0);
                    810: 
1.1.1.10! root      811:        // PCT も %1 の書き込みでクリア。
1.1.1.2   root      812:        // PCT は PCL が High → Low の時セットなので prev_pcl を下げればよい
                    813:        if ((data & DMAC::CSR_PCT)) {
                    814:                prev_pcl = false;
                    815:        }
                    816: 
1.1.1.7   root      817:        parent->putlogf(4, lstr("#%d CSR <- $%02x (CSR = $%02x)",
                    818:                ch, data, PeekCSR()));
1.1.1.2   root      819: }
                    820: 
1.1.1.6   root      821: // CCR への書き込み。
                    822: // CCR への書き込みによって割り込み信号線が変化するかも知れないので
                    823: // この後呼び出し側が ChangeInterrupt() を呼ぶこと。
1.1       root      824: void
1.1.1.2   root      825: DMAC::Channel::WriteCCR(uint32 data)
1.1       root      826: {
1.1.1.2   root      827:        // 割り込み許可ビットは常に反映
1.1.1.6   root      828:        ccr &= ~DMAC::CCR_INT;
                    829:        ccr |= (data & DMAC::CCR_INT);
1.1.1.2   root      830: 
                    831:        // SAB (Software Abort)
                    832:        if ((data & DMAC::CCR_SAB)) {
                    833:                // イベントを触るため親デバイスで処理する
                    834:                parent->AbortTransfer(this);
                    835:        }
                    836: 
                    837:        // HLT (Halt Operation)
                    838:        if ((data & DMAC::CCR_HLT)) {
1.1.1.7   root      839:                parent->putlogf(0, lstr("CCR HLT 未実装"));
1.1.1.2   root      840:        }
                    841: 
                    842:        // CNT (Continue Operation)
                    843:        if ((data & DMAC::CCR_CNT)) {
1.1.1.7   root      844:                parent->putlogf(0, lstr("CCR CNT 未実装"));
1.1.1.2   root      845:        }
                    846: 
                    847:        // STR (Start Operation)
                    848:        if ((data & DMAC::CCR_STR)) {
                    849:                StartTransfer();
                    850:        }
1.1       root      851: }
                    852: 
1.1.1.5   root      853: // 転送開始 (チャンネル側)
1.1.1.2   root      854: void
                    855: DMAC::Channel::StartTransfer()
                    856: {
                    857:        // CSR の COC,BTC,NDT,ERR が立ってたら開始しない
                    858:        if ((csr & 0xf0) != 0) {
                    859:                cer = CER_CONFIG;       // ?
                    860:                csr |= CSR_ERR;
                    861:                return;
                    862:        }
                    863: 
                    864:        active = true;
                    865: 
                    866:        // XXX CER をどこかでクリアしないといけないようだがどこだ?
                    867:        cer = 0;
                    868: 
                    869:        // 転送方法は DPS(1bit) と SIZE(2bit) で合計 8通り。
                    870:        // (その中にさらに転送方向が2通りずつあるけど)
                    871:        //
                    872:        // xfertype DPS   SIZE
                    873:        //     0    8bit  8bit packed
                    874:        //     1    8bit  16bit
                    875:        //     2    8bit  32bit
                    876:        //     3    8bit  8bit
                    877:        //     4    16bit 8bit packed
                    878:        //     5    16bit 16bit
                    879:        //     6    16bit 32bit
                    880:        //     7    16bit 8bit
                    881:        xfertype = (GetDPS() << 2) | GetSIZE();
                    882: 
                    883:        // 転送モード
                    884:        switch (GetREQG()) {
                    885:         case DMAC::OCR_REQG_AUTO_LIM:
1.1.1.10! root      886:                VMPANIC("REQG_AUTO_LIM 未実装");
1.1.1.2   root      887:                break;
                    888: 
                    889:         case DMAC::OCR_REQG_AUTO_MAX:
                    890:                // 自発的に転送を開始する
1.1.1.10! root      891:                parent->StartTransfer();
1.1.1.2   root      892:                break;
                    893: 
                    894:         case DMAC::OCR_REQG_EXTERNAL:
                    895:         case DMAC::OCR_REQG_AUTOFIRST:
1.1.1.10! root      896:                VMPANIC("未実装 REQG");
1.1.1.2   root      897:                break;
                    898: 
                    899:         default:
                    900:                __unreachable();
                    901:        }
                    902: }
                    903: 
1.1.1.5   root      904: // 転送開始 (デバイス側)
1.1.1.10! root      905: // (チャンネルが転送開始する際にデバイス側の private 変数(event)が必要に
1.1.1.5   root      906: // なるため、プロキシしている)
                    907: void
1.1.1.10! root      908: DMACDevice::StartTransfer()
1.1.1.5   root      909: {
1.1.1.10! root      910:        if (event.IsRunning() == false) {
        !           911:                CallAfter(StartCallback, 0);
        !           912:        }
1.1.1.5   root      913: }
                    914: 
1.1.1.10! root      915: // 転送開始
1.1.1.2   root      916: void
1.1.1.10! root      917: DMACDevice::StartCallback(Event& ev)
1.1.1.2   root      918: {
1.1.1.10! root      919:        // 転送チャンネルの決定
        !           920:        int ch = -1;
        !           921:        uint8 prio = 255;
        !           922:        for (int i = 0; i < 4; i++) {
        !           923:                DMAC::Channel *chan = &dmac.chan[i];
        !           924:                if (chan->active) {
        !           925:                        uint8 p = chan->priority;
        !           926:                        if (p < prio) {
        !           927:                                prio = p;
        !           928:                                // 実効プライオリティのラウンドロビン用のところを上げておく
        !           929:                                chan->priority = (p & 0xf0) | ((p & 0x0f) >> 1);
        !           930:                                ch = i;
        !           931:                        }
        !           932:                }
        !           933:        }
        !           934:        if (ch == -1) {
        !           935:                // 転送チャンネルはもうないのでイベントは停止したままにする
        !           936:                event.SetName("DMAC");
        !           937:                return;
        !           938:        }
        !           939:        xfer_chan = &dmac.chan[ch];
1.1.1.2   root      940: 
1.1.1.10! root      941:        // 実効プライオリティを同順位の最後に回す
        !           942:        xfer_chan->priority |= 0x08;
1.1.1.2   root      943: 
1.1.1.10! root      944:        if (xfer_chan->GetDIR() == DMAC::OCR_DIR_MtoD) {
        !           945:                xfer_src = xfer_chan->mar;
        !           946:                xfer_dst = xfer_chan->dar;
        !           947:        } else {
        !           948:                xfer_src = xfer_chan->dar;
        !           949:                xfer_dst = xfer_chan->mar;
        !           950:        }
        !           951: 
        !           952:        // XXX バスアービトレーションとか
        !           953: 
        !           954:        xfer_retry = 0;
        !           955:        event.SetName(string_format("DMAC #%d", ch));
        !           956:        CallAfter(ReadCallback, 1);
        !           957: }
        !           958: 
        !           959: // 転送エラー
        !           960: void
        !           961: DMACDevice::Error(uint64 r)
        !           962: {
        !           963:        if ((int64)r == -2) {
        !           964:                // DTACK が出ていない (SPC)。
        !           965:                // 本当は DTACK が出たことをコールバックしてくれれば
        !           966:                // 効率がいいのだがポーリングでもかまわんだろう。
        !           967:                xfer_retry++;
        !           968:                putlog(4, "xfer_retry=%d", xfer_retry);
        !           969:                if (xfer_retry < 100) {
        !           970:                        // 現在のイベントを再実行
        !           971:                        event.time = 1 * 80_nsec;
        !           972:                        gScheduler->StartEvent(event);
        !           973:                        return;
        !           974:                }
        !           975:                // タイムアウトしたらバスエラーにフォールスルー
        !           976:        }
        !           977: 
        !           978:        // バスエラー
        !           979:        xfer_chan->csr |= DMAC::CSR_ERR;
        !           980:        xfer_chan->active = false;
        !           981:        ChangeInterrupt();
        !           982:        CallAfter(StartCallback, 0);
        !           983: }
        !           984: 
        !           985: // 転送(読み込み)
        !           986: void
        !           987: DMACDevice::ReadCallback(Event& ev)
        !           988: {
        !           989:        uint64 r;
        !           990: 
        !           991:        // シングルアドレスモードはサポートしていない
1.1.1.2   root      992: 
1.1.1.10! root      993:        switch (xfer_chan->xfertype) {
        !           994:         case 0:        // 8ビットポート、8ビットサイズ、パック動作
1.1.1.2   root      995:         case 1:        // 8ビットポート、16ビットサイズ
1.1.1.10! root      996:         case 2:        // 8ビットポート、32ビットサイズ
        !           997:                VMPANIC("未実装 xfer type");
        !           998: 
        !           999:         case 3:        // 8ビットポート、8ビットサイズ、パックなし動作
        !          1000:                r = vm_phys_read_8(xfer_src);
        !          1001:                break;
        !          1002: 
        !          1003:         case 4:        // 16ビットポート、8ビットサイズ、パック動作
        !          1004:         case 5:        // 16ビットポート、16ビットサイズ
        !          1005:         case 6:        // 16ビットポート、32ビットサイズ
        !          1006:         case 7:        // 16ビットポート、8ビットサイズ、パックなし動作
        !          1007:         default:
        !          1008:                VMPANIC("未実装 xfer type");
        !          1009:        }
        !          1010: 
        !          1011:        if ((int64)r < 0) {
        !          1012:                Error(r);
        !          1013:                return;
        !          1014:        }
        !          1015:        xfer_retry = 0;
        !          1016:        xfer_data = r;
        !          1017: 
        !          1018:        CallAfter(WriteCallback, 4);
        !          1019: }
1.1.1.2   root     1020: 
1.1.1.10! root     1021: // 転送(書き込み)
        !          1022: void
        !          1023: DMACDevice::WriteCallback(Event& ev)
        !          1024: {
        !          1025:        uint64 r;
        !          1026:        putlog(4, "WRITE xfer_data=$%02x", xfer_data);
        !          1027: 
        !          1028:        switch (xfer_chan->xfertype) {
        !          1029:         case 0:        // 8ビットポート、8ビットサイズ、パック動作
        !          1030:         case 1:        // 8ビットポート、16ビットサイズ
1.1.1.2   root     1031:         case 2:        // 8ビットポート、32ビットサイズ
1.1.1.10! root     1032:                VMPANIC("未実装 xfer type");
1.1.1.2   root     1033: 
                   1034:         case 3:        // 8ビットポート、8ビットサイズ、パックなし動作
1.1.1.10! root     1035:                r = vm_phys_write_8(xfer_dst, xfer_data);
1.1.1.2   root     1036:                break;
                   1037: 
                   1038:         case 4:        // 16ビットポート、8ビットサイズ、パック動作
                   1039:         case 5:        // 16ビットポート、16ビットサイズ
                   1040:         case 6:        // 16ビットポート、32ビットサイズ
                   1041:         case 7:        // 16ビットポート、8ビットサイズ、パックなし動作
1.1.1.10! root     1042:         default:
        !          1043:                VMPANIC("未実装 xfer type");
1.1.1.2   root     1044:        }
                   1045: 
1.1.1.10! root     1046:        if ((int64)r < 0) {
        !          1047:                Error(r);
1.1.1.2   root     1048:                return;
                   1049:        }
                   1050: 
1.1.1.10! root     1051:        CallAfter(DoneCallback, 5);
        !          1052: }
        !          1053: 
        !          1054: // 1回の転送完了
        !          1055: void
        !          1056: DMACDevice::DoneCallback(Event& ev)
        !          1057: {
        !          1058:        putlog(4, "DONE");
        !          1059: 
1.1.1.2   root     1060:        // バスエラーでなければカウンタを更新
                   1061:        // XXX とりあえず。後で書く
1.1.1.10! root     1062:        switch (xfer_chan->GetMAC()) {
1.1.1.2   root     1063:         case DMAC::SCR_COUNT_UP:
1.1.1.10! root     1064:                xfer_chan->mar += 1;
1.1.1.2   root     1065:                break;
                   1066:         case DMAC::SCR_COUNT_DOWN:
1.1.1.10! root     1067:                xfer_chan->mar -= 1;
1.1.1.2   root     1068:                break;
                   1069:        }
1.1.1.10! root     1070:        switch (xfer_chan->GetDAC()) {
1.1.1.2   root     1071:         case DMAC::SCR_COUNT_UP:
1.1.1.10! root     1072:                xfer_chan->dar += 1;
1.1.1.2   root     1073:                break;
                   1074:         case DMAC::SCR_COUNT_DOWN:
1.1.1.10! root     1075:                xfer_chan->dar -= 1;
1.1.1.2   root     1076:                break;
                   1077:        }
                   1078: 
1.1.1.10! root     1079:        xfer_chan->mtc--;
        !          1080:        if (xfer_chan->mtc == 0) {
1.1.1.2   root     1081:                // 転送完了
1.1.1.10! root     1082:                xfer_chan->csr |= DMAC::CSR_COC;
        !          1083:                xfer_chan->active = false;
1.1.1.6   root     1084:                ChangeInterrupt();
1.1.1.2   root     1085:        }
                   1086: 
1.1.1.10! root     1087:        CallAfter(StartCallback, 1);
1.1.1.2   root     1088: }
                   1089: 
                   1090: // ソフトウェアアボート
                   1091: // (イベントを持つのでこれはデバイスクラスのメソッド)
                   1092: void
                   1093: DMACDevice::AbortTransfer(DMAC::Channel *chan)
                   1094: {
                   1095:        putlog(2, "CCR SAB ソフトウェアアボート");
                   1096: 
                   1097:        // %1 を書き込むことで実際には SAB はセットされるが、ERR が立つと
                   1098:        // SAB をクリアする動作のため、書き込んだ %1 が読めることはない。
                   1099:        // ここでは SAB ビットのセットを省略。
                   1100: 
1.1.1.10! root     1101:        chan->active = false;
1.1.1.2   root     1102:        chan->cer = DMAC::CER_SOFT_ABORT;
1.1.1.6   root     1103:        // ERR ビットが立つと SAB をクリアする
                   1104:        chan->csr |=  DMAC::CSR_ERR;
                   1105:        chan->ccr &= ~DMAC::CCR_SAB;
                   1106:        ChangeInterrupt();
                   1107: }
                   1108: 
                   1109: // 割り込み信号線の状態を変える。
                   1110: void
                   1111: DMACDevice::ChangeInterrupt()
                   1112: {
                   1113:        bool irq = false;
                   1114: 
                   1115:        for (int ch = 0; ch < countof(dmac.chan); ch++) {
                   1116:                DMAC::Channel *chan = &dmac.chan[ch];
                   1117: 
                   1118:                if ((chan->ccr & DMAC::CCR_INT) && chan->IsINTR()) {
                   1119:                        irq = true;
                   1120:                }
                   1121:        }
                   1122:        gInterrupt->ChangeINT(this, irq);
                   1123: }
                   1124: 
                   1125: // 割り込みアクノリッジ
                   1126: int
                   1127: DMACDevice::InterruptAcknowledge()
                   1128: {
1.1.1.10! root     1129:        DMAC::Channel *chan;
        !          1130:        int top = -1;
        !          1131:        uint8 prio = 255;
        !          1132: 
        !          1133:        // 割り込みを発生させているトッププライオリティのチャンネルを検索
1.1.1.6   root     1134:        for (int ch = 0; ch < countof(dmac.chan); ch++) {
1.1.1.10! root     1135:                chan = &dmac.chan[ch];
1.1.1.6   root     1136: 
1.1.1.10! root     1137:                if ((chan->ccr & DMAC::CCR_INT) && chan->IsINTR()) {
        !          1138:                        if (chan->priority < prio) {
        !          1139:                                prio = chan->priority;
        !          1140:                                top = ch;
1.1.1.6   root     1141:                        }
1.1.1.10! root     1142:                }
        !          1143:        }
        !          1144: 
        !          1145:        if (top >= 0) {
        !          1146:                chan = &dmac.chan[top];
        !          1147:                if ((chan->csr & DMAC::CSR_ERR)) {
        !          1148:                        return chan->eiv;
        !          1149:                } else {
        !          1150:                        return chan->niv;
1.1.1.6   root     1151:                }
                   1152:        }
                   1153:        // XXX 誰もいなかったら?
1.1.1.10! root     1154:        VMPANIC("InterruptAcknowledge no active channels?");
1.1.1.2   root     1155: }

unix.superglobalmegacorp.com

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