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

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

unix.superglobalmegacorp.com

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