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

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

unix.superglobalmegacorp.com

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