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

1.1       root        1: //
                      2: // nono
1.1.1.3   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #include "dmac.h"
1.1.1.3   root        8: #include "bus.h"
1.1.1.6   root        9: #include "interrupt.h"
1.1.1.3   root       10: #include "mpu680x0.h"
1.1.1.2   root       11: 
                     12: std::unique_ptr<DMACDevice> gDMAC;
1.1       root       13: 
                     14: DMACDevice::DMACDevice()
                     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->csr = 0;
                     61:                chan->active = false;
                     62:                chan->pcl = false;
                     63:                chan->cpr = 0;
                     64:                chan->cer = 0;
                     65: 
                     66:                chan->niv = 0x0f;
                     67:                chan->eiv = 0x0f;
                     68:        }
                     69: 
                     70:        // イベントをすべて停止
                     71:        for (int i = 0; i < countof(event); i++) {
                     72:                event[i].Stop();
                     73:        }
                     74: }
                     75: 
1.1       root       76: uint64
1.1.1.7 ! root       77: DMACDevice::Read(uint32 offset)
1.1       root       78: {
                     79:        uint8 data;
                     80:        int ch;
                     81: 
1.1.1.5   root       82:        gMPU->AddCycle(37);     // InsideOut p.135
                     83: 
1.1.1.7 ! root       84:        ch = offset / 0x40;
1.1.1.2   root       85:        DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.7 ! root       86:        int n = offset % 0x40;
1.1       root       87:        switch (n) {
                     88:         case DMAC::CSR:
1.1.1.2   root       89:                data = chan->PeekCSR();
                     90:                putlog(4, "#%d CSR -> $%02x", ch, data);
1.1       root       91:                break;
                     92: 
                     93:         case DMAC::CER:
                     94:                data = chan->cer;
1.1.1.2   root       95:                putlog(4, "#%d CER -> $%02x", ch, data);
1.1       root       96:                break;
                     97: 
                     98:         case DMAC::DCR:
                     99:                data = chan->dcr;
1.1.1.2   root      100:                putlog(4, "#%d DCR -> $%02x", ch, data);
1.1       root      101:                break;
                    102: 
                    103:         case DMAC::OCR:
                    104:                data = chan->ocr;
1.1.1.2   root      105:                putlog(4, "#%d OCR -> $%02x", ch, data);
1.1       root      106:                break;
                    107: 
                    108:         case DMAC::SCR:
                    109:                data = chan->scr;
1.1.1.2   root      110:                putlog(4, "#%d SCR -> $%02x", ch, data);
1.1       root      111:                break;
                    112: 
                    113:         case DMAC::CCR:
1.1.1.6   root      114:                data = chan->ccr;
1.1.1.2   root      115:                putlog(4, "#%d CCR -> $%02x", ch, data);
1.1       root      116:                break;
                    117: 
                    118:         case DMAC::MTC:
                    119:                data = chan->mtc >> 8;
1.1.1.2   root      120:                putlog(4, "#%d MTC:H -> $%02x", ch, data);
1.1       root      121:                break;
                    122:         case DMAC::MTC + 1:
                    123:                data = chan->mtc & 0xff;
1.1.1.2   root      124:                putlog(4, "#%d MTC:L -> $%02x", ch, data);
1.1       root      125:                break;
                    126: 
                    127:         case DMAC::MAR:
                    128:                data = chan->mar >> 24;
1.1.1.2   root      129:                putlog(4, "#%d MAR:0 -> $%02x", ch, data);
1.1       root      130:                break;
                    131:         case DMAC::MAR + 1:
                    132:                data = (chan->mar >> 16) & 0xff;
1.1.1.2   root      133:                putlog(4, "#%d MAR:1 -> $%02x", ch, data);
1.1       root      134:                break;
                    135:         case DMAC::MAR + 2:
                    136:                data = (chan->mar >> 8) & 0xff;
1.1.1.2   root      137:                putlog(4, "#%d MAR:2 -> $%02x", ch, data);
1.1       root      138:                break;
                    139:         case DMAC::MAR + 3:
                    140:                data = chan->mar & 0xff;
1.1.1.2   root      141:                putlog(4, "#%d MAR:3 -> $%02x", ch, data);
1.1       root      142:                break;
                    143: 
                    144:         case DMAC::DAR:
                    145:                data = chan->dar >> 24;
1.1.1.2   root      146:                putlog(4, "#%d DAR:0 -> $%02x", ch, data);
1.1       root      147:                break;
                    148:         case DMAC::DAR + 1:
                    149:                data = (chan->dar >> 16) & 0xff;
1.1.1.2   root      150:                putlog(4, "#%d DAR:1 -> $%02x", ch, data);
1.1       root      151:                break;
                    152:         case DMAC::DAR + 2:
                    153:                data = (chan->dar >> 8) & 0xff;
1.1.1.2   root      154:                putlog(4, "#%d DAR:2 -> $%02x", ch, data);
1.1       root      155:                break;
                    156:         case DMAC::DAR + 3:
                    157:                data = chan->dar & 0xff;
1.1.1.2   root      158:                putlog(4, "#%d DAR:3 -> $%02x", ch, data);
1.1       root      159:                break;
                    160: 
                    161:         case DMAC::BTC:
                    162:                data = chan->btc >> 8;
1.1.1.2   root      163:                putlog(4, "#%d BTC:H -> $%02x", ch, data);
1.1       root      164:                break;
                    165:         case DMAC::BTC + 1:
                    166:                data = chan->btc & 0xff;
1.1.1.2   root      167:                putlog(4, "#%d BTC:L -> $%02x", ch, data);
1.1       root      168:                break;
                    169: 
                    170:         case DMAC::BAR:
                    171:                data = chan->bar >> 24;
1.1.1.2   root      172:                putlog(4, "#%d BAR:0 -> $%02x", ch, data);
1.1       root      173:                break;
                    174:         case DMAC::BAR + 1:
                    175:                data = (chan->bar >> 16) & 0xff;
1.1.1.2   root      176:                putlog(4, "#%d BAR:1 -> $%02x", ch, data);
1.1       root      177:                break;
                    178:         case DMAC::BAR + 2:
                    179:                data = (chan->bar >> 8) & 0xff;
1.1.1.2   root      180:                putlog(4, "#%d BAR:2 -> $%02x", ch, data);
1.1       root      181:                break;
                    182:         case DMAC::BAR + 3:
                    183:                data = chan->bar & 0xff;
1.1.1.2   root      184:                putlog(4, "#%d BAR:3 -> $%02x", ch, data);
1.1       root      185:                break;
                    186: 
                    187:         case DMAC::NIV:
                    188:                data = chan->niv;
1.1.1.2   root      189:                putlog(4, "#%d NIV -> $%02x", ch, data);
1.1       root      190:                break;
                    191: 
                    192:         case DMAC::EIV:
                    193:                data = chan->eiv;
1.1.1.2   root      194:                putlog(4, "#%d EIV -> $%02x", ch, data);
1.1       root      195:                break;
                    196: 
                    197:         case DMAC::MFC:
                    198:                data = chan->mfc;
1.1.1.2   root      199:                putlog(4, "#%d MFC -> $%02x", ch, data);
1.1       root      200:                break;
                    201: 
                    202:         case DMAC::CPR:
                    203:                data = chan->cpr;
1.1.1.2   root      204:                putlog(4, "#%d CPR -> $%02x", ch, data);
1.1       root      205:                break;
                    206: 
                    207:         case DMAC::DFC:
                    208:                data = chan->dfc;
1.1.1.2   root      209:                putlog(4, "#%d DFC -> $%02x", ch, data);
1.1       root      210:                break;
                    211: 
                    212:         case DMAC::BFC:
                    213:                data = chan->bfc;
1.1.1.2   root      214:                putlog(4, "#%d BFC -> $%02x", ch, data);
1.1       root      215:                break;
                    216: 
                    217:         case DMAC::GCR:
                    218:                if (ch == 3) {
                    219:                        data = dmac.gcr;
1.1.1.2   root      220:                        putlog(4, "GCR -> $%02x", data);
1.1       root      221:                        break;
                    222:                } else {
                    223:                        data = 0xff;
                    224:                }
                    225:                break;
                    226: 
                    227:         default:
                    228:                data = 0xff;
                    229:                break;
                    230:        }
                    231: 
                    232:        return data;
                    233: }
                    234: 
                    235: uint64
1.1.1.7 ! root      236: DMACDevice::Write(uint32 offset, uint32 data)
1.1       root      237: {
                    238:        int ch;
                    239: 
1.1.1.5   root      240:        gMPU->AddCycle(31);     // InsideOut p.135
                    241: 
1.1.1.7 ! root      242:        ch = offset / 0x40;
1.1.1.2   root      243:        DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.7 ! root      244:        int n = offset % 0x40;
1.1       root      245:        switch (n) {
                    246:         case DMAC::CSR:
1.1.1.2   root      247:                chan->WriteCSR(data);
1.1.1.6   root      248:                ChangeInterrupt();
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.1.6   root      273:                ChangeInterrupt();
1.1       root      274:                break;
                    275: 
                    276:         case DMAC::MTC:
                    277:                chan->mtc = (chan->mtc & 0x00ff) | (data << 8);
1.1.1.2   root      278:                putlog(4, "#%d MTC:H <- $%02x (MTC=$%04x)", ch, data, chan->mtc);
1.1       root      279:                break;
                    280:         case DMAC::MTC + 1:
                    281:                chan->mtc = (chan->mtc & 0xff00) | data;
1.1.1.2   root      282:                putlog(4, "#%d MTC:L <- $%02x (MTC=$%04x)", ch, data, chan->mtc);
1.1       root      283:                break;
                    284: 
                    285:         case DMAC::MAR:
                    286:                chan->mar = (chan->mar & 0x00ffffff) | (data << 24);
1.1.1.2   root      287:                putlog(4, "#%d MAR:0 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1       root      288:                break;
                    289:         case DMAC::MAR + 1:
                    290:                chan->mar = (chan->mar & 0xff00ffff) | (data << 16);
1.1.1.2   root      291:                putlog(4, "#%d MAR:1 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1       root      292:                break;
                    293:         case DMAC::MAR + 2:
                    294:                chan->mar = (chan->mar & 0xffff00ff) | (data << 8);
1.1.1.2   root      295:                putlog(4, "#%d MAR:2 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1       root      296:                break;
                    297:         case DMAC::MAR + 3:
                    298:                chan->mar = (chan->mar & 0xffffff00) | data;
1.1.1.2   root      299:                putlog(4, "#%d MAR:3 <- $%02x (MAR=$%08x)", ch, data, chan->mar);
1.1       root      300:                break;
                    301: 
                    302:         case DMAC::DAR:
                    303:                chan->dar = (chan->dar & 0x00ffffff) | (data << 24);
1.1.1.2   root      304:                putlog(4, "#%d DAR:0 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1       root      305:                break;
                    306:         case DMAC::DAR + 1:
                    307:                chan->dar = (chan->dar & 0xff00ffff) | (data << 16);
1.1.1.2   root      308:                putlog(4, "#%d DAR:1 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1       root      309:                break;
                    310:         case DMAC::DAR + 2:
                    311:                chan->dar = (chan->dar & 0xffff00ff) | (data << 8);
1.1.1.2   root      312:                putlog(4, "#%d DAR:2 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1       root      313:                break;
                    314:         case DMAC::DAR + 3:
                    315:                chan->dar = (chan->dar & 0xffffff00) | data;
1.1.1.2   root      316:                putlog(4, "#%d DAR:3 <- $%02x (DAR=$%08x)", ch, data, chan->dar);
1.1       root      317:                break;
                    318: 
                    319:         case DMAC::BTC:
                    320:                chan->btc = (chan->btc & 0x00ff) | (data << 8);
1.1.1.2   root      321:                putlog(4, "#%d BTC:H <- $%02x (BTC=$%04x)", ch, data, chan->btc);
1.1       root      322:                break;
                    323:         case DMAC::BTC + 1:
                    324:                chan->btc = (chan->btc & 0xff00) | data;
1.1.1.2   root      325:                putlog(4, "#%d BTC:L <- $%02x (BTC=$%04x)", ch, data, chan->btc);
1.1       root      326:                break;
                    327: 
                    328:         case DMAC::BAR:
                    329:                chan->bar = (chan->bar & 0x00ffffff) | (data << 24);
1.1.1.2   root      330:                putlog(4, "#%d BAR:0 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1       root      331:                break;
                    332:         case DMAC::BAR + 1:
                    333:                chan->bar = (chan->bar & 0xff00ffff) | (data << 16);
1.1.1.2   root      334:                putlog(4, "#%d BAR:1 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1       root      335:                break;
                    336:         case DMAC::BAR + 2:
                    337:                chan->bar = (chan->bar & 0xffff00ff) | (data << 8);
1.1.1.2   root      338:                putlog(4, "#%d BAR:2 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1       root      339:                break;
                    340:         case DMAC::BAR + 3:
                    341:                chan->bar = (chan->bar & 0xffffff00) | data;
1.1.1.2   root      342:                putlog(4, "#%d BAR:3 <- $%02x (BAR=$%08x)", ch, data, chan->bar);
1.1       root      343:                break;
                    344: 
                    345:         case DMAC::NIV:
1.1.1.2   root      346:                putlog(4, "#%d NIV <- $%02x", ch, data);
1.1       root      347:                chan->niv = data;
                    348:                break;
                    349: 
                    350:         case DMAC::EIV:
1.1.1.2   root      351:                putlog(4, "#%d EIV <- $%02x", ch, data);
1.1       root      352:                chan->eiv = data;
                    353:                break;
                    354: 
                    355:         case DMAC::MFC:
1.1.1.2   root      356:                putlog(4, "#%d MFC <- $%02x", ch, data);
1.1       root      357:                chan->mfc = data & 7;
                    358:                break;
                    359: 
                    360:         case DMAC::CPR:
1.1.1.2   root      361:                putlog(4, "#%d CPR <- $%02x", ch, data);
1.1       root      362:                chan->cpr = data & 3;
                    363:                break;
                    364: 
                    365:         case DMAC::DFC:
1.1.1.2   root      366:                putlog(4, "#%d DFC <- $%02x", ch, data);
1.1       root      367:                chan->dfc = data & 7;
                    368:                break;
                    369: 
                    370:         case DMAC::BFC:
1.1.1.2   root      371:                putlog(4, "#%d BFC <- $%02x", ch, data);
1.1       root      372:                chan->bfc = data & 7;
                    373:                break;
                    374: 
                    375:         case DMAC::GCR:
                    376:                if (ch == 3) {
1.1.1.2   root      377:                        putlog(4, "GCR <- $%02x", data);
1.1       root      378:                        dmac.gcr = data;
                    379:                }
                    380:                break;
                    381: 
                    382:         default:
                    383:                break;
                    384:        }
                    385:        return 0;
                    386: }
                    387: 
                    388: uint64
1.1.1.7 ! root      389: DMACDevice::Peek(uint32 offset)
1.1       root      390: {
                    391:        uint8 data;
                    392:        int ch;
                    393: 
1.1.1.7 ! root      394:        ch = offset / 0x40;
1.1.1.2   root      395:        const DMAC::Channel *chan = &dmac.chan[ch];
1.1.1.7 ! root      396:        int n = offset % 0x40;
1.1       root      397:        switch (n) {
                    398:         case DMAC::CSR:
1.1.1.2   root      399:                data = chan->PeekCSR();
1.1       root      400:                break;
                    401: 
                    402:         case DMAC::CER:
                    403:                data = chan->cer;
                    404:                break;
                    405: 
                    406:         case DMAC::DCR:
                    407:                data = chan->dcr;
                    408:                break;
                    409: 
                    410:         case DMAC::OCR:
                    411:                data = chan->ocr;
                    412:                break;
                    413: 
                    414:         case DMAC::SCR:
                    415:                data = chan->scr;
                    416:                break;
                    417: 
                    418:         case DMAC::CCR:
1.1.1.6   root      419:                data = chan->ccr;
1.1       root      420:                break;
                    421: 
                    422:         case DMAC::MTC:
                    423:                data = chan->mtc >> 8;
                    424:                break;
                    425:         case DMAC::MTC + 1:
                    426:                data = chan->mtc & 0xff;
                    427:                break;
                    428: 
                    429:         case DMAC::MAR:
                    430:                data = chan->mar >> 24;
                    431:                break;
                    432:         case DMAC::MAR + 1:
                    433:                data = (chan->mar >> 16) & 0xff;
                    434:                break;
                    435:         case DMAC::MAR + 2:
                    436:                data = (chan->mar >> 8) & 0xff;
                    437:                break;
                    438:         case DMAC::MAR + 3:
                    439:                data = chan->mar & 0xff;
                    440:                break;
                    441: 
                    442:         case DMAC::DAR:
                    443:                data = chan->dar >> 24;
                    444:                break;
                    445:         case DMAC::DAR + 1:
                    446:                data = (chan->dar >> 16) & 0xff;
                    447:                break;
                    448:         case DMAC::DAR + 2:
                    449:                data = (chan->dar >> 8) & 0xff;
                    450:                break;
                    451:         case DMAC::DAR + 3:
                    452:                data = chan->dar & 0xff;
                    453:                break;
                    454: 
                    455:         case DMAC::BTC:
                    456:                data = chan->btc >> 8;
                    457:                break;
                    458:         case DMAC::BTC + 1:
                    459:                data = chan->btc & 0xff;
                    460:                break;
                    461: 
                    462:         case DMAC::BAR:
                    463:                data = chan->bar >> 24;
                    464:                break;
                    465:         case DMAC::BAR + 1:
                    466:                data = (chan->bar >> 16) & 0xff;
                    467:                break;
                    468:         case DMAC::BAR + 2:
                    469:                data = (chan->bar >> 8) & 0xff;
                    470:                break;
                    471:         case DMAC::BAR + 3:
                    472:                data = chan->bar & 0xff;
                    473:                break;
                    474: 
                    475:         case DMAC::NIV:
                    476:                data = chan->niv;
                    477:                break;
                    478: 
                    479:         case DMAC::EIV:
                    480:                data = chan->eiv;
                    481:                break;
                    482: 
                    483:         case DMAC::MFC:
                    484:                data = chan->mfc;
                    485:                break;
                    486: 
                    487:         case DMAC::CPR:
                    488:                data = chan->cpr;
                    489:                break;
                    490: 
                    491:         case DMAC::DFC:
                    492:                data = chan->dfc;
                    493:                break;
                    494: 
                    495:         case DMAC::BFC:
                    496:                data = chan->bfc;
                    497:                break;
                    498: 
                    499:         case DMAC::GCR:
                    500:                if (ch == 3) {
                    501:                        data = dmac.gcr;
                    502:                        break;
                    503:                } else {
                    504:                        data = 0xff;
                    505:                }
                    506:                break;
                    507: 
                    508:         default:
                    509:                data = 0xff;
                    510:                break;
                    511:        }
                    512: 
                    513:        return data;
                    514: }
                    515: 
1.1.1.4   root      516: void
                    517: DMACDevice::MonitorUpdate(TextScreen& monitor)
1.1.1.2   root      518: {
                    519:        int x;
                    520:        int y;
                    521: 
                    522:        monitor.Clear();
                    523: 
                    524:        y = 1;
1.1.1.3   root      525:        monitor.Puts(0, y++, "CSR");
1.1.1.2   root      526:        y += 2;
1.1.1.3   root      527:        monitor.Puts(0, y++, "CER");
                    528:        monitor.Puts(0, y++, "DCR:XRM");
                    529:        monitor.Puts(0, y++, "DCR:DTYP");
                    530:        monitor.Puts(0, y++, "DCR:DPS");
                    531:        monitor.Puts(0, y++, "DCR:PCL");
                    532:        monitor.Puts(0, y++, "OCR:DIR");
                    533:        monitor.Puts(0, y++, "OCR:SIZE");
                    534:        monitor.Puts(0, y++, "OCR:CHAIN");
                    535:        monitor.Puts(0, y++, "OCR:REQG");
                    536:        monitor.Puts(0, y++, "SCR:MAC");
                    537:        monitor.Puts(0, y++, "SCR:DAC");
                    538:        monitor.Puts(0, y++, "CCR");
1.1.1.2   root      539:        y += 2;
1.1.1.3   root      540:        monitor.Puts(0, y++, "MTC");
                    541:        monitor.Puts(0, y++, "MAR");
                    542:        monitor.Puts(0, y++, "DAR");
                    543:        monitor.Puts(0, y++, "BTC");
                    544:        monitor.Puts(0, y++, "BAR");
                    545:        monitor.Puts(0, y++, "NIV");
                    546:        monitor.Puts(0, y++, "EIV");
                    547:        monitor.Puts(0, y++, "MFC");
                    548:        monitor.Puts(0, y++, "CPR");
                    549:        monitor.Puts(0, y++, "DFC");
                    550:        monitor.Puts(0, y++, "BFC");
1.1.1.2   root      551: 
                    552:        for (int ch = 0; ch < 4; ch++) {
                    553:                DMAC::Channel *chan = &dmac.chan[ch];
                    554:                int val;
                    555:                x = 12 + ch * 17;
                    556:                y = 0;
                    557: 
                    558:                // 地味だけど有効なチャンネルをハイライトしてみる
1.1.1.3   root      559:                monitor.Print(x, y++, (chan->active ? TA::Em : TA::Normal),
1.1.1.2   root      560:                        "#%d (%s)", chan->ch, chan->desc);
                    561: 
                    562:                // CSR
                    563:                val = chan->PeekCSR();
                    564:                monitor.Print(x, y++, "$%02x", val);
                    565:                static const char * const csrname[] = {
                    566:                        "COC", "BTC", "NDT", "ERR", "ACT", "---", "PCT", "PCS",
                    567:                };
1.1.1.4   root      568:                MonitorReg4(monitor, x, y++, val >> 4,   &csrname[0]);
                    569:                MonitorReg4(monitor, x, y++, val & 0xff, &csrname[4]);
1.1.1.2   root      570: 
                    571:                // CER
                    572:                val = chan->cer & 0x1f;
                    573:                const char *e;
                    574:                if (val <= 0x11 && errnames[val]) {
                    575:                        e = errnames[val];
                    576:                } else {
                    577:                        e = "?";
                    578:                }
                    579:                monitor.Print(x, y, "$%02x", chan->cer);
                    580:                if (val > 0) {
                    581:                        monitor.Print(x + 3, y, ":%s", e);
                    582:                }
                    583:                y++;
                    584: 
                    585:                // DCR:XRM
                    586:                static const char * const dcr_xrm[] = {
                    587:                        //1234567890123
                    588:                        "Burst",
                    589:                        "undefined",
                    590:                        "CycleW/O Hold",
                    591:                        "CycleWithHold",
                    592:                };
                    593:                val = chan->dcr >> 6;
                    594:                monitor.Print(x, y++, "%d:%s", val, dcr_xrm[val]);
                    595: 
                    596:                // DCR:DTYP
                    597:                static const char * const dcr_dtyp[] = {
                    598:                        //1234567890123
                    599:                        "68000",
                    600:                        "6800",
                    601:                        "ACK",
                    602:                        "ACK+READY",
                    603:                };
                    604:                val = (chan->dcr >> 4) & 3;
                    605:                monitor.Print(x, y++, "%d:%s", val, dcr_dtyp[val]);
                    606: 
                    607:                // DCR:DPS
                    608:                static const char * const dcr_dps[] = {
                    609:                        //1234567890123
                    610:                        "8bit",
                    611:                        "16bit",
                    612:                };
                    613:                val = (chan->dcr >> 3) & 1;
                    614:                monitor.Print(x, y++, "%d:%s", val, dcr_dps[val]);
                    615: 
                    616:                // DCR:PCL
                    617:                monitor.Print(x, y++, "XXX PCL");
                    618: 
                    619:                // OCR:DIR
                    620:                static const char * const ocr_dir[] = {
                    621:                        //1234567890123
                    622:                        "MemoryToDevice",
                    623:                        "DeviceToMemory",
                    624:                };
                    625:                val = (chan->ocr >> 7);
                    626:                monitor.Print(x, y++, "%d:%s", val, ocr_dir[val]);
                    627: 
                    628:                // OCR:SIZE
                    629:                static const char * const ocr_size[] = {
                    630:                        //1234567890123
                    631:                        "8bit",
                    632:                        "16bit",
                    633:                        "32bit",
                    634:                        "8bit Unpacked",
                    635:                };
                    636:                val = (chan->ocr >> 4) & 3;
                    637:                monitor.Print(x, y++, "%d:%s", val, ocr_size[val]);
                    638: 
                    639:                // OCR:CHAIN
                    640:                static const char * const ocr_chain[] = {
                    641:                        //1234567890123
                    642:                        "NoChain",
                    643:                        "undefined",
                    644:                        "ArrayChain",
                    645:                        "LinkArrayChain",
                    646:                };
                    647:                val = (chan->ocr >> 2) & 3;
                    648:                monitor.Print(x, y++, "%d:%s", val, ocr_chain[val]);
                    649: 
                    650:                // OCR:REQG
                    651:                static const char * const ocr_reqg[] = {
                    652:                        //1234567890123
                    653:                        "AutoReq(Limit)",
                    654:                        "AutoReq(Max)",
                    655:                        "ExternalReq",
                    656:                        "AutoThenExt",
                    657:                };
                    658:                val = (chan->ocr & 3);
                    659:                monitor.Print(x, y++, "%d:%s", val, ocr_reqg[val]);
                    660: 
                    661:                // SCR:MAC
                    662:                static const char * const scr_xac[] = {
                    663:                        //1234567890123
                    664:                        "NoCount",
                    665:                        "CountUp",
                    666:                        "CountDown",
                    667:                        "undefined",
                    668:                };
                    669:                val = (chan->scr >> 2) & 3;
                    670:                monitor.Print(x, y++, "%d:%s", val, scr_xac[val]);
                    671:                val = chan->scr & 3;
                    672:                monitor.Print(x, y++, "%d:%s", val, scr_xac[val]);
                    673: 
                    674:                // CCR
1.1.1.6   root      675:                val = chan->ccr;
1.1.1.2   root      676:                monitor.Print(x, y++, "$%02x", val);
                    677:                static const char * const ccrnames[] = {
                    678:                        "STR", "CNT", "HLT", "SAB", "INT", "---", "---", "---",
                    679:                };
1.1.1.4   root      680:                MonitorReg4(monitor, x, y++, (val >> 4),   &ccrnames[0]);
                    681:                MonitorReg4(monitor, x, y++, (val & 0xff), &ccrnames[4]);
1.1.1.2   root      682: 
                    683:                // MTC
                    684:                monitor.Print(x, y++, "$%04x", chan->mtc);
                    685:                // MAR
                    686:                // X680x0 がターゲットなので24bit超える設定は目立たせる
                    687:                if (chan->mar > 0xffffff) {
                    688:                        monitor.Print(x, y++, TA::On, "$%08x", chan->mar);
                    689:                } else {
                    690:                        monitor.Print(x, y++, "$%06x", chan->mar);
                    691:                }
                    692:                // DAR
                    693:                if (chan->dar > 0xffffff) {
                    694:                        monitor.Print(x, y++, TA::On, "$%08x", chan->dar);
                    695:                } else {
                    696:                        monitor.Print(x, y++, "$%06x", chan->dar);
                    697:                }
                    698:                // BTC
                    699:                monitor.Print(x, y++, "$%04x", chan->btc);
                    700:                // BAR
                    701:                if (chan->bar > 0xffffff) {
                    702:                        monitor.Print(x, y++, TA::On, "$%08x", chan->bar);
                    703:                } else {
                    704:                        monitor.Print(x, y++, "$%06x", chan->bar);
                    705:                }
                    706: 
                    707:                // NIV
                    708:                monitor.Print(x, y++, "$%02x", chan->niv);
                    709:                // EIV
                    710:                monitor.Print(x, y++, "$%02x", chan->eiv);
                    711: 
                    712:                // MFC
                    713:                monitor.Print(x, y++, "$%02x", chan->mfc);
                    714:                // CPR
                    715:                monitor.Print(x, y++, "$%02x", chan->cpr);
                    716:                // DFC
                    717:                monitor.Print(x, y++, "$%02x", chan->dfc);
                    718:                // BFC
                    719:                monitor.Print(x, y++, "$%02x", chan->bfc);
                    720: 
                    721:                if (ch == 3) {
                    722:                        monitor.Print(x - 5, y++, "GCR: $%02x", dmac.gcr);
                    723:                }
                    724:        }
                    725: }
                    726: 
                    727: // 4ビット分を表示する。MonitorUpdate の下請け
                    728: void
1.1.1.4   root      729: DMACDevice::MonitorReg4(TextScreen& monitor,
                    730:        int x, int y, uint32 reg, const char * const *names)
1.1.1.2   root      731: {
                    732:        for (int i = 0; i < 4; i++) {
                    733:                bool b = reg & (1 << (3 - i));
1.1.1.3   root      734:                monitor.Puts(x + i * 4, y, TA::OnOff(b), names[i]);
1.1.1.2   root      735:        }
                    736: }
                    737: 
                    738: /*static*/ const char * const
                    739: DMACDevice::errnames[] = {
                    740:        //12345678901
                    741:        "",                             // $00 No Error
                    742:        "ConfigErr",    // $01
                    743:        "OperTiming",   // $02
                    744:        NULL,                   // $03
                    745:        NULL,                   // $04
                    746:        "AddrErrInMAR", // $05
                    747:        "AddrErrInDAR", // $06
                    748:        "AddrErrInBAR", // $07
                    749:        NULL,                   // $08
                    750:        "BusErrInMAR",  // $09
                    751:        "BusErrInDAR",  // $0a
                    752:        "BusErrInBAR",  // $0b
                    753:        NULL,                   // $0c
                    754:        "CntErrInMTC",  // $0d
                    755:        NULL,                   // $0e
                    756:        "CntErrInBTC",  // $0f
                    757:        "ExternAbort",  // $10
                    758:        "SoftAbort",    // $11
                    759: };
                    760: 
                    761: // Read と Peek とそれ以外からも呼ばれるので副作用を持たせてはいけない。
                    762: uint8
                    763: DMAC::Channel::PeekCSR() const
                    764: {
                    765:        uint32 val;
                    766: 
                    767:        val = csr & 0xf0;
                    768:        if (active) {
                    769:                val |= CSR_ACT;
                    770:        }
                    771:        // PCT は PCL が High から Low に変わるとセット
                    772:        if (prev_pcl == true && pcl == false) {
                    773:                val |= CSR_PCT;
                    774:        }
                    775:        if (pcl) {
                    776:                val |= CSR_PCS;
                    777:        }
                    778:        return val;
                    779: }
                    780: 
1.1.1.6   root      781: // CSR への書き込み。
                    782: // CSR への書き込みによって割り込み信号線が変化するかも知れないので
                    783: // この後呼び出し側が ChangeInterrupt() を呼ぶこと。
1.1       root      784: void
1.1.1.2   root      785: DMAC::Channel::WriteCSR(uint32 data)
1.1       root      786: {
1.1.1.2   root      787:        // 上位4ビットは %1 の書き込みでクリア
                    788:        csr &= ~(data & 0xf0);
                    789: 
                    790:        // PCT も %1 の書き込みでクリア
                    791:        // PCT は PCL が High → Low の時セットなので prev_pcl を下げればよい
                    792:        if ((data & DMAC::CSR_PCT)) {
                    793:                prev_pcl = false;
                    794:        }
                    795: 
1.1.1.7 ! root      796:        parent->putlogf(4, lstr("#%d CSR <- $%02x (CSR = $%02x)",
        !           797:                ch, data, PeekCSR()));
1.1.1.2   root      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)) {
1.1.1.7 ! root      818:                parent->putlogf(0, lstr("CCR HLT 未実装"));
1.1.1.2   root      819:        }
                    820: 
                    821:        // CNT (Continue Operation)
                    822:        if ((data & DMAC::CCR_CNT)) {
1.1.1.7 ! root      823:                parent->putlogf(0, lstr("CCR CNT 未実装"));
1.1.1.2   root      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.