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

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

unix.superglobalmegacorp.com

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