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

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: #include "mystring.h"
                     12: 
                     13: std::unique_ptr<DMACDevice> gDMAC;
1.1       root       14: 
                     15: DMACDevice::DMACDevice()
                     16: {
                     17:        logname = "dmac";
                     18:        devname = "DMAC";
                     19:        devaddr = baseaddr;
                     20:        devlen  = 0x2000;
1.1.1.2   root       21: 
1.1.1.4   root       22:        monitor_size = nnSize(80, 30);
1.1.1.2   root       23: 
                     24:        for (int i = 0; i < countof(dmac.chan); i++) {
                     25:                dmac.chan[i].ch = i;
                     26:                dmac.chan[i].parent = this;
                     27:        }
                     28:        dmac.chan[0].desc = "FD";
                     29:        dmac.chan[1].desc = "HD";
                     30:        dmac.chan[2].desc = "User";
                     31:        dmac.chan[3].desc = "ADPCM";
                     32: 
                     33:        for (int i = 0; i < countof(event); i++) {
                     34:                event[i].dev = this;
                     35:                event[i].func = (DeviceCallback_t)&DMACDevice::Transfer;
                     36:                event[i].SetName(string_format("DMAC #%d", i));
                     37:                event[i].code = i;
                     38:        }
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:        // イベントをすべて停止
                     72:        for (int i = 0; i < countof(event); i++) {
                     73:                event[i].Stop();
                     74:        }
                     75: }
                     76: 
1.1       root       77: uint64
1.1.1.3   root       78: DMACDevice::Read(uint32 addr)
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.3   root       85:        ch = addr / 0x40;
1.1.1.2   root       86:        DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.3   root       87:        int n = addr % 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.3   root      237: DMACDevice::Write(uint32 addr, 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.3   root      243:        ch = addr / 0x40;
1.1.1.2   root      244:        DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.3   root      245:        int n = addr % 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.3   root      390: DMACDevice::Peek(uint32 addr)
1.1       root      391: {
                    392:        uint8 data;
                    393:        int ch;
                    394: 
1.1.1.3   root      395:        ch = addr / 0x40;
1.1.1.2   root      396:        const DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.3   root      397:        int n = addr % 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
                    518: DMACDevice::MonitorUpdate(TextScreen& monitor)
1.1.1.2   root      519: {
                    520:        int x;
                    521:        int y;
                    522: 
                    523:        monitor.Clear();
                    524: 
                    525:        y = 1;
1.1.1.3   root      526:        monitor.Puts(0, y++, "CSR");
1.1.1.2   root      527:        y += 2;
1.1.1.3   root      528:        monitor.Puts(0, y++, "CER");
                    529:        monitor.Puts(0, y++, "DCR:XRM");
                    530:        monitor.Puts(0, y++, "DCR:DTYP");
                    531:        monitor.Puts(0, y++, "DCR:DPS");
                    532:        monitor.Puts(0, y++, "DCR:PCL");
                    533:        monitor.Puts(0, y++, "OCR:DIR");
                    534:        monitor.Puts(0, y++, "OCR:SIZE");
                    535:        monitor.Puts(0, y++, "OCR:CHAIN");
                    536:        monitor.Puts(0, y++, "OCR:REQG");
                    537:        monitor.Puts(0, y++, "SCR:MAC");
                    538:        monitor.Puts(0, y++, "SCR:DAC");
                    539:        monitor.Puts(0, y++, "CCR");
1.1.1.2   root      540:        y += 2;
1.1.1.3   root      541:        monitor.Puts(0, y++, "MTC");
                    542:        monitor.Puts(0, y++, "MAR");
                    543:        monitor.Puts(0, y++, "DAR");
                    544:        monitor.Puts(0, y++, "BTC");
                    545:        monitor.Puts(0, y++, "BAR");
                    546:        monitor.Puts(0, y++, "NIV");
                    547:        monitor.Puts(0, y++, "EIV");
                    548:        monitor.Puts(0, y++, "MFC");
                    549:        monitor.Puts(0, y++, "CPR");
                    550:        monitor.Puts(0, y++, "DFC");
                    551:        monitor.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.3   root      560:                monitor.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();
                    565:                monitor.Print(x, y++, "$%02x", val);
                    566:                static const char * const csrname[] = {
                    567:                        "COC", "BTC", "NDT", "ERR", "ACT", "---", "PCT", "PCS",
                    568:                };
1.1.1.4   root      569:                MonitorReg4(monitor, x, y++, val >> 4,   &csrname[0]);
                    570:                MonitorReg4(monitor, 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:                }
                    580:                monitor.Print(x, y, "$%02x", chan->cer);
                    581:                if (val > 0) {
                    582:                        monitor.Print(x + 3, y, ":%s", e);
                    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;
                    595:                monitor.Print(x, y++, "%d:%s", val, dcr_xrm[val]);
                    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;
                    606:                monitor.Print(x, y++, "%d:%s", val, dcr_dtyp[val]);
                    607: 
                    608:                // DCR:DPS
                    609:                static const char * const dcr_dps[] = {
                    610:                        //1234567890123
                    611:                        "8bit",
                    612:                        "16bit",
                    613:                };
                    614:                val = (chan->dcr >> 3) & 1;
                    615:                monitor.Print(x, y++, "%d:%s", val, dcr_dps[val]);
                    616: 
                    617:                // DCR:PCL
                    618:                monitor.Print(x, y++, "XXX PCL");
                    619: 
                    620:                // OCR:DIR
                    621:                static const char * const ocr_dir[] = {
                    622:                        //1234567890123
                    623:                        "MemoryToDevice",
                    624:                        "DeviceToMemory",
                    625:                };
                    626:                val = (chan->ocr >> 7);
                    627:                monitor.Print(x, y++, "%d:%s", val, ocr_dir[val]);
                    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;
                    638:                monitor.Print(x, y++, "%d:%s", val, ocr_size[val]);
                    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;
                    649:                monitor.Print(x, y++, "%d:%s", val, ocr_chain[val]);
                    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);
                    660:                monitor.Print(x, y++, "%d:%s", val, ocr_reqg[val]);
                    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;
                    671:                monitor.Print(x, y++, "%d:%s", val, scr_xac[val]);
                    672:                val = chan->scr & 3;
                    673:                monitor.Print(x, y++, "%d:%s", val, scr_xac[val]);
                    674: 
                    675:                // CCR
1.1.1.6 ! root      676:                val = chan->ccr;
1.1.1.2   root      677:                monitor.Print(x, y++, "$%02x", val);
                    678:                static const char * const ccrnames[] = {
                    679:                        "STR", "CNT", "HLT", "SAB", "INT", "---", "---", "---",
                    680:                };
1.1.1.4   root      681:                MonitorReg4(monitor, x, y++, (val >> 4),   &ccrnames[0]);
                    682:                MonitorReg4(monitor, x, y++, (val & 0xff), &ccrnames[4]);
1.1.1.2   root      683: 
                    684:                // MTC
                    685:                monitor.Print(x, y++, "$%04x", chan->mtc);
                    686:                // MAR
                    687:                // X680x0 がターゲットなので24bit超える設定は目立たせる
                    688:                if (chan->mar > 0xffffff) {
                    689:                        monitor.Print(x, y++, TA::On, "$%08x", chan->mar);
                    690:                } else {
                    691:                        monitor.Print(x, y++, "$%06x", chan->mar);
                    692:                }
                    693:                // DAR
                    694:                if (chan->dar > 0xffffff) {
                    695:                        monitor.Print(x, y++, TA::On, "$%08x", chan->dar);
                    696:                } else {
                    697:                        monitor.Print(x, y++, "$%06x", chan->dar);
                    698:                }
                    699:                // BTC
                    700:                monitor.Print(x, y++, "$%04x", chan->btc);
                    701:                // BAR
                    702:                if (chan->bar > 0xffffff) {
                    703:                        monitor.Print(x, y++, TA::On, "$%08x", chan->bar);
                    704:                } else {
                    705:                        monitor.Print(x, y++, "$%06x", chan->bar);
                    706:                }
                    707: 
                    708:                // NIV
                    709:                monitor.Print(x, y++, "$%02x", chan->niv);
                    710:                // EIV
                    711:                monitor.Print(x, y++, "$%02x", chan->eiv);
                    712: 
                    713:                // MFC
                    714:                monitor.Print(x, y++, "$%02x", chan->mfc);
                    715:                // CPR
                    716:                monitor.Print(x, y++, "$%02x", chan->cpr);
                    717:                // DFC
                    718:                monitor.Print(x, y++, "$%02x", chan->dfc);
                    719:                // BFC
                    720:                monitor.Print(x, y++, "$%02x", chan->bfc);
                    721: 
                    722:                if (ch == 3) {
                    723:                        monitor.Print(x - 5, y++, "GCR: $%02x", dmac.gcr);
                    724:                }
                    725:        }
                    726: }
                    727: 
                    728: // 4ビット分を表示する。MonitorUpdate の下請け
                    729: void
1.1.1.4   root      730: DMACDevice::MonitorReg4(TextScreen& monitor,
                    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++) {
                    734:                bool b = reg & (1 << (3 - i));
1.1.1.3   root      735:                monitor.Puts(x + i * 4, y, TA::OnOff(b), names[i]);
1.1.1.2   root      736:        }
                    737: }
                    738: 
                    739: /*static*/ const char * const
                    740: DMACDevice::errnames[] = {
                    741:        //12345678901
                    742:        "",                             // $00 No Error
                    743:        "ConfigErr",    // $01
                    744:        "OperTiming",   // $02
                    745:        NULL,                   // $03
                    746:        NULL,                   // $04
                    747:        "AddrErrInMAR", // $05
                    748:        "AddrErrInDAR", // $06
                    749:        "AddrErrInBAR", // $07
                    750:        NULL,                   // $08
                    751:        "BusErrInMAR",  // $09
                    752:        "BusErrInDAR",  // $0a
                    753:        "BusErrInBAR",  // $0b
                    754:        NULL,                   // $0c
                    755:        "CntErrInMTC",  // $0d
                    756:        NULL,                   // $0e
                    757:        "CntErrInBTC",  // $0f
                    758:        "ExternAbort",  // $10
                    759:        "SoftAbort",    // $11
                    760: };
                    761: 
                    762: // Read と Peek とそれ以外からも呼ばれるので副作用を持たせてはいけない。
                    763: uint8
                    764: DMAC::Channel::PeekCSR() const
                    765: {
                    766:        uint32 val;
                    767: 
                    768:        val = csr & 0xf0;
                    769:        if (active) {
                    770:                val |= CSR_ACT;
                    771:        }
                    772:        // PCT は PCL が High から Low に変わるとセット
                    773:        if (prev_pcl == true && pcl == false) {
                    774:                val |= CSR_PCT;
                    775:        }
                    776:        if (pcl) {
                    777:                val |= CSR_PCS;
                    778:        }
                    779:        return val;
                    780: }
                    781: 
1.1.1.6 ! root      782: // CSR への書き込み。
        !           783: // CSR への書き込みによって割り込み信号線が変化するかも知れないので
        !           784: // この後呼び出し側が ChangeInterrupt() を呼ぶこと。
1.1       root      785: void
1.1.1.2   root      786: DMAC::Channel::WriteCSR(uint32 data)
1.1       root      787: {
1.1.1.2   root      788:        // 上位4ビットは %1 の書き込みでクリア
                    789:        csr &= ~(data & 0xf0);
                    790: 
                    791:        // PCT も %1 の書き込みでクリア
                    792:        // PCT は PCL が High → Low の時セットなので prev_pcl を下げればよい
                    793:        if ((data & DMAC::CSR_PCT)) {
                    794:                prev_pcl = false;
                    795:        }
                    796: 
                    797:        parent->putlog(4, "#%d CSR <- $%02x (CSR = $%02x)", ch, data, PeekCSR());
                    798: }
                    799: 
1.1.1.6 ! root      800: // CCR への書き込み。
        !           801: // CCR への書き込みによって割り込み信号線が変化するかも知れないので
        !           802: // この後呼び出し側が ChangeInterrupt() を呼ぶこと。
1.1       root      803: void
1.1.1.2   root      804: DMAC::Channel::WriteCCR(uint32 data)
1.1       root      805: {
1.1.1.2   root      806:        // 割り込み許可ビットは常に反映
1.1.1.6 ! root      807:        ccr &= ~DMAC::CCR_INT;
        !           808:        ccr |= (data & DMAC::CCR_INT);
1.1.1.2   root      809: 
                    810:        // SAB (Software Abort)
                    811:        if ((data & DMAC::CCR_SAB)) {
                    812:                // イベントを触るため親デバイスで処理する
                    813:                parent->AbortTransfer(this);
                    814:        }
                    815: 
                    816:        // HLT (Halt Operation)
                    817:        if ((data & DMAC::CCR_HLT)) {
                    818:                parent->putlog(0, "CCR HLT 未実装");
                    819:        }
                    820: 
                    821:        // CNT (Continue Operation)
                    822:        if ((data & DMAC::CCR_CNT)) {
                    823:                parent->putlog(0, "CCR CNT 未実装");
                    824:        }
                    825: 
                    826:        // STR (Start Operation)
                    827:        if ((data & DMAC::CCR_STR)) {
                    828:                StartTransfer();
                    829:        }
1.1       root      830: }
                    831: 
1.1.1.5   root      832: // 転送開始 (チャンネル側)
1.1.1.2   root      833: void
                    834: DMAC::Channel::StartTransfer()
                    835: {
                    836:        // CSR の COC,BTC,NDT,ERR が立ってたら開始しない
                    837:        if ((csr & 0xf0) != 0) {
                    838:                cer = CER_CONFIG;       // ?
                    839:                csr |= CSR_ERR;
                    840:                return;
                    841:        }
                    842: 
                    843:        active = true;
                    844: 
                    845:        // XXX CER をどこかでクリアしないといけないようだがどこだ?
                    846:        cer = 0;
                    847: 
                    848:        // 転送方法は DPS(1bit) と SIZE(2bit) で合計 8通り。
                    849:        // (その中にさらに転送方向が2通りずつあるけど)
                    850:        //
                    851:        // xfertype DPS   SIZE
                    852:        //     0    8bit  8bit packed
                    853:        //     1    8bit  16bit
                    854:        //     2    8bit  32bit
                    855:        //     3    8bit  8bit
                    856:        //     4    16bit 8bit packed
                    857:        //     5    16bit 16bit
                    858:        //     6    16bit 32bit
                    859:        //     7    16bit 8bit
                    860:        xfertype = (GetDPS() << 2) | GetSIZE();
                    861: 
                    862:        // 転送モード
                    863:        switch (GetREQG()) {
                    864:         case DMAC::OCR_REQG_AUTO_LIM:
                    865:                PANIC("REQG_AUTO_LIM 未実装");
                    866:                break;
                    867: 
                    868:         case DMAC::OCR_REQG_AUTO_MAX:
                    869:                // 自発的に転送を開始する
1.1.1.5   root      870:                parent->StartTransfer(this);
1.1.1.2   root      871:                break;
                    872: 
                    873:         case DMAC::OCR_REQG_EXTERNAL:
                    874:         case DMAC::OCR_REQG_AUTOFIRST:
                    875:                PANIC("未実装 REQG");
                    876:                break;
                    877: 
                    878:         default:
                    879:                __unreachable();
                    880:        }
                    881: }
                    882: 
1.1.1.5   root      883: // 転送開始 (デバイス側)
                    884: // (チャンネルが転送開始する際にデバイス側の private 変数(event[])が必要に
                    885: // なるため、プロキシしている)
                    886: void
                    887: DMACDevice::StartTransfer(DMAC::Channel *chan)
                    888: {
                    889:        Transfer(event[chan->ch]);
                    890: }
                    891: 
1.1.1.2   root      892: // 転送
                    893: // (イベントを持つのでこれはデバイスクラスのメソッド)
                    894: void
1.1.1.5   root      895: DMACDevice::Transfer(Event& ev)
1.1.1.2   root      896: {
1.1.1.5   root      897:        int& ch = ev.code;
1.1.1.2   root      898:        DMAC::Channel *chan = &dmac.chan[ch];
                    899:        int64 rv;
                    900: 
                    901:        putlog(4, "#%d Transfer (MTC=$%04x)", ch, chan->mtc);
                    902: 
                    903:        rv = 0;
                    904:        switch (chan->xfertype) {
                    905:         case 0:        // 8ビットポート、8ビットサイズ、パック動作
                    906: 
                    907:         case 1:        // 8ビットポート、16ビットサイズ
                    908: 
                    909:         case 2:        // 8ビットポート、32ビットサイズ
                    910:                PANIC("未実装 xfer type");
                    911: 
                    912:         case 3:        // 8ビットポート、8ビットサイズ、パックなし動作
                    913:                if (chan->GetDIR() == DMAC::OCR_DIR_MtoD) {
                    914:                        rv = TransferM8toD8(chan);
                    915:                } else {
                    916:                        rv = TransferD8toM8(chan);
                    917:                }
                    918:                break;
                    919: 
                    920:         case 4:        // 16ビットポート、8ビットサイズ、パック動作
                    921:         case 5:        // 16ビットポート、16ビットサイズ
                    922:         case 6:        // 16ビットポート、32ビットサイズ
                    923:         case 7:        // 16ビットポート、8ビットサイズ、パックなし動作
                    924:                PANIC("未実装 xfer type");
                    925:        }
                    926: 
                    927:        // XXX バスエラーは?
                    928:        if (rv < 0) {
                    929:                return;
                    930:        }
                    931: 
                    932:        // バスエラーでなければカウンタを更新
                    933:        // XXX とりあえず。後で書く
                    934:        switch (chan->GetMAC()) {
                    935:         case DMAC::SCR_COUNT_UP:
                    936:                chan->mar += 1;
                    937:                break;
                    938:         case DMAC::SCR_COUNT_DOWN:
                    939:                chan->mar -= 1;
                    940:                break;
                    941:        }
                    942:        switch (chan->GetDAC()) {
                    943:         case DMAC::SCR_COUNT_UP:
                    944:                chan->dar += 1;
                    945:                break;
                    946:         case DMAC::SCR_COUNT_DOWN:
                    947:                chan->dar -= 1;
                    948:                break;
                    949:        }
                    950: 
                    951:        chan->mtc--;
                    952:        if (chan->mtc == 0) {
                    953:                // 転送完了
1.1.1.6 ! root      954:                chan->csr |= DMAC::CSR_COC;
        !           955:                ChangeInterrupt();
1.1.1.2   root      956:        } else {
                    957:                // 次回の転送
                    958:                // XXX とりあえず 1us で1回の転送にする
1.1.1.5   root      959:                ev.time = 1_usec;
                    960:                ev.Start();
1.1.1.2   root      961:        }
                    962: }
                    963: 
                    964: // メモリから 8ビットデバイスへ (パックなし動作)
                    965: int64
                    966: DMACDevice::TransferM8toD8(DMAC::Channel *chan)
                    967: {
                    968:        uint64 data;
                    969:        int64 rv;
                    970: 
                    971:        data = vm_phys_read_8(chan->mar);
                    972:        if ((int64)data < 0)
                    973:                return data;
                    974:        rv = vm_phys_write_8(chan->dar, data);
                    975:        if (rv < 0)
                    976:                return rv;
                    977: 
                    978:        return 0;
                    979: }
                    980: 
                    981: // 8ビットデバイスからメモリへ (パックなし動作)
                    982: int64
                    983: DMACDevice::TransferD8toM8(DMAC::Channel *chan)
                    984: {
                    985:        uint64 data;
                    986:        int64 rv;
                    987: 
                    988:        data = vm_phys_read_8(chan->dar);
                    989:        if ((int64)data < 0)
                    990:                return data;
                    991:        rv = vm_phys_write_8(chan->mar, data);
                    992:        if (rv < 0)
                    993:                return rv;
                    994: 
                    995:        return 0;
                    996: }
                    997: 
                    998: // ソフトウェアアボート
                    999: // (イベントを持つのでこれはデバイスクラスのメソッド)
                   1000: void
                   1001: DMACDevice::AbortTransfer(DMAC::Channel *chan)
                   1002: {
                   1003:        int ch = chan->ch;
                   1004: 
                   1005:        putlog(2, "CCR SAB ソフトウェアアボート");
                   1006: 
                   1007:        // %1 を書き込むことで実際には SAB はセットされるが、ERR が立つと
                   1008:        // SAB をクリアする動作のため、書き込んだ %1 が読めることはない。
                   1009:        // ここでは SAB ビットのセットを省略。
                   1010: 
                   1011:        event[ch].Stop();
                   1012:        chan->cer = DMAC::CER_SOFT_ABORT;
1.1.1.6 ! root     1013:        // ERR ビットが立つと SAB をクリアする
        !          1014:        chan->csr |=  DMAC::CSR_ERR;
        !          1015:        chan->ccr &= ~DMAC::CCR_SAB;
        !          1016:        ChangeInterrupt();
        !          1017: }
        !          1018: 
        !          1019: // 割り込み信号線の状態を変える。
        !          1020: void
        !          1021: DMACDevice::ChangeInterrupt()
        !          1022: {
        !          1023:        bool irq = false;
        !          1024: 
        !          1025:        for (int ch = 0; ch < countof(dmac.chan); ch++) {
        !          1026:                DMAC::Channel *chan = &dmac.chan[ch];
        !          1027: 
        !          1028:                if ((chan->ccr & DMAC::CCR_INT) && chan->IsINTR()) {
        !          1029:                        irq = true;
        !          1030:                }
        !          1031:        }
        !          1032:        gInterrupt->ChangeINT(this, irq);
        !          1033: }
        !          1034: 
        !          1035: // 割り込みアクノリッジ
        !          1036: int
        !          1037: DMACDevice::InterruptAcknowledge()
        !          1038: {
        !          1039:        // XXX CPR のプライオリティは未対応、とりあえず前から順
        !          1040:        for (int ch = 0; ch < countof(dmac.chan); ch++) {
        !          1041:                DMAC::Channel *chan = &dmac.chan[ch];
        !          1042: 
        !          1043:                if (chan->active) {
        !          1044:                        if ((chan->csr & DMAC::CSR_ERR)) {
        !          1045:                                return chan->eiv;
        !          1046:                        } else {
        !          1047:                                return chan->niv;
        !          1048:                        }
        !          1049:                        chan->active = false;
        !          1050:                }
        !          1051:        }
        !          1052:        // XXX 誰もいなかったら?
        !          1053:        PANIC("InterruptAcknowledge no active channels?");
1.1.1.2   root     1054: }

unix.superglobalmegacorp.com

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