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

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

unix.superglobalmegacorp.com

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