Annotation of nono/hd64180/hd647180io.cpp, revision 1.1.1.4

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2022 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // HD647180 I/O アクセス
                      9: //
                     10: 
                     11: #include "mpu64180.h"
                     12: #include "hd647180.h"
1.1.1.3   root       13: #include "hd647180asci.h"
1.1       root       14: #include "pio.h"
                     15: #include "scheduler.h"
1.1.1.2   root       16: #include "ssg.h"
1.1       root       17: #include "xpbus.h"
                     18: 
                     19: //#define ENABLE_SERIAL_LOG
                     20: 
                     21: uint32
                     22: MPU64180Device::ReadIO(uint32 addr)
                     23: {
                     24:        CYCLE(iowait);
                     25: 
                     26:        // 内蔵 I/O
                     27:        if (io_address <= addr && addr < io_address + 0x80) {
                     28:                return ReadInternalIO(addr - io_address);
                     29:        }
                     30: 
                     31:        return ReadExternalIO(addr);
                     32: }
                     33: 
                     34: uint32
                     35: MPU64180Device::ReadInternalIO(uint32 offset)
                     36: {
                     37:        uint32 data = -1;
                     38: 
                     39:        switch (offset) {
                     40:         case 0x00:                                     // IO_CNTLA0
1.1.1.3   root       41:                data = asci->ReadCNTLA(0);
                     42:                break;
1.1       root       43:         case 0x01:                                     // IO_CNTLA1
1.1.1.3   root       44:                data = asci->ReadCNTLA(1);
                     45:                break;
1.1       root       46:         case 0x02:                                     // IO_CNTLB0
1.1.1.3   root       47:                data = asci->ReadCNTLB(0);
                     48:                break;
1.1       root       49:         case 0x03:                                     // IO_CNTLB1
1.1.1.3   root       50:                data = asci->ReadCNTLB(1);
1.1       root       51:                break;
                     52:         case 0x04:                                     // IO_STAT0
1.1.1.3   root       53:                data = asci->ReadSTAT(0);
                     54:                break;
1.1       root       55:         case 0x05:                                     // IO_STAT1
1.1.1.3   root       56:                data = asci->ReadSTAT(1);
                     57:                break;
1.1       root       58:         case 0x06:                                     // IO_TDR0
1.1.1.3   root       59:                data = asci->ReadTDR(0);
                     60:                break;
1.1       root       61:         case 0x07:                                     // IO_TDR1
1.1.1.3   root       62:                data = asci->ReadTDR(1);
                     63:                break;
                     64:         case 0x08:                                     // IO_RDR0
                     65:                data = asci->ReadRDR(0);
                     66:                break;
                     67:         case 0x09:                                     // IO_RDR1
                     68:                data = asci->ReadRDR(1);
                     69:                break;
                     70: 
1.1       root       71:         case 0x0a:                                     // IO_CNTR
                     72:         case 0x0b:                                     // IO_TRDR
                     73:                break;
                     74: 
                     75:         case 0x0c:                                     // IO_TMDR0L
                     76:                data = ReadTMDRL(0);
                     77:                break;
                     78:         case 0x0d:                                     // IO_TMDR0H
                     79:                data = ReadTMDRH(0);
                     80:                break;
                     81:         case 0x0e:                                     // IO_RLDR0L
                     82:                data = PeekRLDRL(0);
                     83:                break;
                     84:         case 0x0f:                                     // IO_RLDR0H
                     85:                data = PeekRLDRH(0);
                     86:                break;
                     87:         case 0x10:                                     // IO_TCR
                     88:                data = ReadTCR();
                     89:                break;
                     90:         case 0x14:                                     // IO_TMDR1L
                     91:                data = ReadTMDRL(1);
                     92:                break;
                     93:         case 0x15:                                     // IO_TMDR1H
                     94:                data = ReadTMDRH(1);
                     95:                break;
                     96:         case 0x16:                                     // IO_RLDR1L
                     97:                data = PeekRLDRH(0);
                     98:                break;
                     99:         case 0x17:                                     // IO_RLDR1H
                    100:                data = PeekRLDRH(1);
                    101:                break;
                    102:         case 0x18:                                     // IO_FRC
                    103:                data = PeekFRC();
                    104:                break;
                    105: 
                    106:         case 0x20:                                     // IO_SAR0L
                    107:         case 0x21:                                     // IO_SAR0H
                    108:         case 0x22:                                     // IO_SAR0B
                    109:         case 0x23:                                     // IO_DAR0L
                    110:         case 0x24:                                     // IO_DAR0H
                    111:         case 0x25:                                     // IO_DAR0B
                    112:         case 0x26:                                     // IO_BCR0L
                    113:         case 0x27:                                     // IO_BCR0H
                    114:         case 0x28:                                     // IO_MAR1L
                    115:         case 0x29:                                     // IO_MAR1H
                    116:         case 0x2a:                                     // IO_MAR1B
                    117:         case 0x2b:                                     // IO_IAR1L
                    118:         case 0x2c:                                     // IO_IAR1H
                    119:         case 0x2e:                                     // IO_BCR1L
                    120:         case 0x2f:                                     // IO_BCR1H
                    121:         case 0x30:                                     // IO_DSTAT
                    122:         case 0x31:                                     // IO_DMODE
                    123:                break;
                    124:         case 0x32:                                     // IO_DCNTL
                    125:                data = PeekDCNTL();
                    126:                break;
                    127: 
                    128:         case 0x33:                                     // IO_IL
                    129:                data = PeekIL();
                    130:                break;
                    131:         case 0x34:                                     // IO_ITC
                    132:                data = PeekITC();
                    133:                break;
                    134:         case 0x36:                                     // IO_RCR
                    135:                data = PeekRCR();
                    136:                break;
                    137: 
                    138:         case 0x38:                                     // IO_CBR
                    139:                data = PeekCBR();
                    140:                break;
                    141: 
                    142:         case 0x39:                                     // IO_BBR
                    143:                data = PeekBBR();
                    144:                break;
                    145: 
                    146:         case 0x3a:                                     // IO_CBAR
                    147:                data = PeekCBAR();
                    148:                break;
                    149: 
                    150:         case 0x3e:                                     // IO_OMCR
                    151:                break;
                    152:         case 0x3f:                                     // IO_ICR
                    153:                data = PeekICR();
                    154:                break;
                    155: 
                    156:         case 0x40:                                     // IO_T2FRCL
                    157:         case 0x41:                                     // IO_T2FRCH
                    158:         case 0x42:                                     // IO_T2OCR1L
                    159:         case 0x43:                                     // IO_T2OCR1H
                    160:         case 0x44:                                     // IO_T2OCR2L
                    161:         case 0x45:                                     // IO_T2OCR2H
                    162:         case 0x46:                                     // IO_T2ICRL
                    163:         case 0x47:                                     // IO_T2ICRH
                    164:         case 0x48:                                     // IO_T2CSR1
                    165:         case 0x49:                                     // IO_T2CSR2
                    166:                break;
                    167: 
                    168:         case 0x50:                                     // IO_CCSR
                    169:                break;
                    170:         case 0x51:                                     // IO_RMCR
                    171:                data = PeekRMCR();
                    172:                break;
                    173: 
                    174:         case 0x53:                                     // IO_DERA
                    175:                break;
                    176:         case 0x60:                                     // IO_IODRA
                    177:                data = 0xff;
                    178: #if defined(ENABLE_SERIAL_LOG)
                    179:                putlog(0, "%s -> $%02x (NOT IMPLEMENTED)",
                    180:                        IOName(offset).c_str(), data);
                    181: #endif
                    182:                return data;
                    183:         case 0x61:                                     // IO_IODRB
                    184:         case 0x62:                                     // IO_IODRC
                    185:         case 0x63:                                     // IO_IODRD
                    186:         case 0x64:                                     // IO_IODRE
                    187:         case 0x65:                                     // IO_IODRF
                    188:         case 0x66:                                     // IO_IDRG
                    189:         case 0x70:                                     // IO_DDRA
                    190:         case 0x71:                                     // IO_DDRB
                    191:         case 0x72:                                     // IO_DDRC
                    192:         case 0x73:                                     // IO_DDRD
                    193:         case 0x74:                                     // IO_DDRE
                    194:         case 0x75:                                     // IO_DDRF
                    195:                break;
                    196: 
                    197:         default:
                    198:                break;
                    199:        }
                    200: 
                    201:        // 表示して値を返す部分はだいたいほぼ共通なので。
                    202:        if ((int32)data < 0) {
                    203:                // data が (32bitで) 負なら未実装ポート。
                    204:                data = 0xff;
                    205:                putlog(0, "ReadInternalIO %s -> $%02x (NOT IMPLEMENTED)",
                    206:                        IOName(offset).c_str(), data);
                    207:        } else {
                    208:                putlog(2, "%s -> $%02x", IOName(offset).c_str(), data);
                    209:        }
                    210:        return data;
                    211: }
                    212: 
                    213: uint32
                    214: MPU64180Device::ReadExternalIO(uint32 addr)
                    215: {
                    216:        uint32 data = -1;
                    217: 
                    218:        // LUNA の外部 I/O はアドレスの上位バイト不問
                    219:        switch (addr & 0xff) {
                    220:         case 0x82:                                     // SSG
                    221:         case 0x83:                                     // SSG
1.1.1.2   root      222:                if (ssg) {
                    223:                        data = ssg->Read1(addr);
                    224:                } else {
                    225:                        data = 0xff;    // ?
                    226:                }
1.1       root      227:                break;
                    228: 
                    229:         case 0x90:                                     // INT0 ネゲート
                    230:                // 読み込みでも (というかアクセスがあっただけで) ネゲート。
                    231:                putlog(1, "%s Negate INT0", IOName(addr).c_str());
                    232:                NegateINT0();
                    233:                // 実際何が読めるかは不明だが。
                    234:                return 0xff;
                    235: 
                    236:         case 0xa0:                                     // レベル5 割り込み要求
                    237:         case 0xb0:                                     // レベル1 割り込み要求
                    238:                // 読み込みでも割り込み上げそうだがとりあえず未実装へ回しておく。
                    239:                break;
                    240: 
                    241:         default:
                    242:                break;
                    243:        }
                    244: 
                    245:        // 表示して値を返す部分はだいたいほぼ共通なので。
                    246:        if ((int32)data < 0) {
                    247:                // data が (32bitで) 負なら未実装ポート。
                    248:                data = 0xff;
                    249:                putlog(0, "ReadExternalIO %s -> $%02x (NOT IMPLEMENTED)",
                    250:                        IOName(addr).c_str(), data);
                    251:        } else {
                    252:                putlog(2, "%s -> $%02x", IOName(addr).c_str(), data);
                    253:        }
                    254:        return data;
                    255: }
                    256: 
                    257: uint32
                    258: MPU64180Device::ReadTMDRL(int ch)
                    259: {
                    260:        auto& t = timer[ch];
                    261: 
                    262:        // TDR 読み出しで割り込みフラグクリアの実績を解除
                    263:        t.tif &= ~0x02;
                    264:        ChangeTimerInterrupt();
                    265: 
                    266:        // L の読み出しで count を tmp にラッチ
                    267:        t.tmpcount = t.count;
                    268: 
                    269:        // でラッチした L を読み出す
                    270:        return t.tmpcount & 0xff;
                    271: }
                    272: 
                    273: uint32
                    274: MPU64180Device::ReadTMDRH(int ch)
                    275: {
                    276:        auto& t = timer[ch];
                    277: 
                    278:        // TDR 読み出しで割り込みフラグクリアの実績を解除
                    279:        t.tif &= ~0x02;
                    280:        ChangeTimerInterrupt();
                    281: 
                    282:        // L 読み出し時にラッチしたやつを読み出す。
                    283:        return t.tmpcount >> 8;
                    284: }
                    285: 
                    286: uint32
                    287: MPU64180Device::ReadTCR()
                    288: {
                    289:        // TCR 読み出しで割り込みフラグクリアの実績を解除
                    290:        timer[0].tif &= ~0x01;
                    291:        timer[1].tif &= ~0x01;
                    292:        ChangeTimerInterrupt();
                    293: 
                    294:        return PeekTCR();
                    295: }
                    296: 
                    297: uint32
                    298: MPU64180Device::WriteIO(uint32 addr, uint32 data)
                    299: {
                    300:        CYCLE(iowait);
                    301: 
                    302:        // 内蔵 I/O
                    303:        if (io_address <= addr && addr < io_address + 0x80) {
                    304:                return WriteInternalIO(addr - io_address, data);
                    305:        }
                    306: 
                    307:        return WriteExternalIO(addr, data);
                    308: }
                    309: 
                    310: uint32
                    311: MPU64180Device::WriteInternalIO(uint32 offset, uint32 data)
                    312: {
                    313:        switch (offset) {
                    314:         case 0x00:                                     // IO_CNTLA0
1.1.1.3   root      315:                return asci->WriteCNTLA(0, data);
1.1       root      316:         case 0x01:                                     // IO_CNTLA1
1.1.1.3   root      317:                return asci->WriteCNTLA(1, data);
1.1       root      318:         case 0x02:                                     // IO_CNTLB0
1.1.1.3   root      319:                return asci->WriteCNTLB(0, data);
1.1       root      320:         case 0x03:                                     // IO_CNTLB1
1.1.1.3   root      321:                return asci->WriteCNTLB(1, data);
1.1       root      322:         case 0x04:                                     // IO_STAT0
1.1.1.3   root      323:                return asci->WriteSTAT(0, data);
1.1       root      324:         case 0x05:                                     // IO_STAT1
1.1.1.3   root      325:                return asci->WriteSTAT(1, data);
1.1       root      326:         case 0x06:                                     // IO_TDR0
1.1.1.3   root      327:                return asci->WriteTDR(0, data);
1.1       root      328:         case 0x07:                                     // IO_TDR1
1.1.1.3   root      329:                return asci->WriteTDR(1, data);
                    330:         case 0x08:                                     // IO_RDR0
                    331:                return asci->WriteRDR(0, data);
                    332:         case 0x09:                                     // IO_RDR1
                    333:                return asci->WriteRDR(1, data);
                    334: 
1.1       root      335:         case 0x0a:                                     // IO_CNTR
                    336:         case 0x0b:                                     // IO_TRDR
                    337:                break;
                    338: 
                    339:         case 0x0c:                                     // IO_TMDR0L
                    340:                return WriteTMDRL(0, data);
                    341:         case 0x0d:                                     // IO_TMDR0H
                    342:                return WriteTMDRH(0, data);
                    343:         case 0x0e:                                     // IO_RLDR0L
                    344:                return WriteRLDRL(0, data);
                    345:         case 0x0f:                                     // IO_RLDR0H
                    346:                return WriteRLDRH(0, data);
                    347:         case 0x10:                                     // IO_TCR
                    348:                return WriteTCR(data);
                    349:         case 0x14:                                     // IO_TMDR1L
                    350:                return WriteTMDRL(1, data);
                    351:         case 0x15:                                     // IO_TMDR1H
                    352:                return WriteTMDRH(1, data);
                    353:         case 0x16:                                     // IO_RLDR1L
                    354:                return WriteRLDRL(1, data);
                    355:         case 0x17:                                     // IO_RLDR1H
                    356:                return WriteRLDRH(1, data);
                    357:         case 0x18:                                     // IO_FRC
                    358:                // 書き込みは出来るけど、してはいけないっぽい。
                    359:                // たぶん現在値が変わるだけだと思うけど未対応。
                    360:                break;
                    361: 
                    362:         case 0x20:                                     // IO_SAR0L
                    363:         case 0x21:                                     // IO_SAR0H
                    364:         case 0x22:                                     // IO_SAR0B
                    365:         case 0x23:                                     // IO_DAR0L
                    366:         case 0x24:                                     // IO_DAR0H
                    367:         case 0x25:                                     // IO_DAR0B
                    368:         case 0x26:                                     // IO_BCR0L
                    369:         case 0x27:                                     // IO_BCR0H
                    370:         case 0x28:                                     // IO_MAR1L
                    371:         case 0x29:                                     // IO_MAR1H
                    372:         case 0x2a:                                     // IO_MAR1B
                    373:         case 0x2b:                                     // IO_IAR1L
                    374:         case 0x2c:                                     // IO_IAR1H
                    375:         case 0x2e:                                     // IO_BCR1L
                    376:         case 0x2f:                                     // IO_BCR1H
                    377:         case 0x30:                                     // IO_DSTAT
                    378:         case 0x31:                                     // IO_DMODE
                    379:                break;
                    380:         case 0x32:                                     // IO_DCNTL
                    381:                return WriteDCNTL(data);
                    382: 
                    383:         case 0x33:                                     // IO_IL
                    384:                return WriteIL(data);
                    385:         case 0x34:                                     // IO_ITC
                    386:                return WriteITC(data);
                    387:         case 0x36:                                     // IO_RCR
                    388:                return WriteRCR(data);
                    389: 
                    390:         case 0x38:                                     // IO_CBR
                    391:                return WriteCBR(data);
                    392:         case 0x39:                                     // IO_BBR
                    393:                return WriteBBR(data);
                    394:         case 0x3a:                                     // IO_CBAR
                    395:                return WriteCBAR(data);
                    396: 
                    397:         case 0x3e:                                     // IO_OMCR
                    398:                break;
                    399:         case 0x3f:                                     // IO_ICR
                    400:                return WriteICR(data);
                    401: 
                    402:         case 0x40:                                     // IO_T2FRCL
                    403:         case 0x41:                                     // IO_T2FRCH
                    404:         case 0x42:                                     // IO_T2OCR1L
                    405:         case 0x43:                                     // IO_T2OCR1H
                    406:         case 0x44:                                     // IO_T2OCR2L
                    407:         case 0x45:                                     // IO_T2OCR2H
                    408:         case 0x46:                                     // IO_T2ICRL
                    409:         case 0x47:                                     // IO_T2ICRH
                    410:         case 0x48:                                     // IO_T2CSR1
                    411:         case 0x49:                                     // IO_T2CSR2
                    412:                break;
                    413: 
                    414:         case 0x50:                                     // IO_CCSR
                    415:                break;
                    416:         case 0x51:                                     // IO_RMCR
                    417:                return WriteRMCR(data);
                    418: 
                    419:         case 0x53:                                     // IO_DERA
                    420:         case 0x60:                                     // IO_IODRA
                    421:         case 0x61:                                     // IO_IODRB
                    422:         case 0x62:                                     // IO_IODRC
                    423:         case 0x63:                                     // IO_IODRD
                    424:         case 0x64:                                     // IO_IODRE
                    425:         case 0x65:                                     // IO_IODRF
                    426:         case 0x66:                                     // IO_IDRG
                    427:         case 0x70:                                     // IO_DDRA
                    428:         case 0x71:                                     // IO_DDRB
                    429:         case 0x72:                                     // IO_DDRC
                    430:         case 0x73:                                     // IO_DDRD
                    431:         case 0x74:                                     // IO_DDRE
                    432:         case 0x75:                                     // IO_DDRF
                    433:                break;
                    434: 
                    435:         default:
                    436:                break;
                    437:        }
                    438: 
                    439:        putlog(0, "WriteInternalIO %s <- $%02x (NOT IMPLEMENTED)",
                    440:                IOName(offset).c_str(), data);
                    441:        return 0;
                    442: }
                    443: 
                    444: uint32
                    445: MPU64180Device::WriteExternalIO(uint32 addr, uint32 data)
                    446: {
                    447:        // LUNA の外部 I/O はアドレスの上位バイト不問
                    448:        switch (addr & 0xff) {
                    449:         case 0x82:                                     // SSG
                    450:         case 0x83:                                     // SSG
1.1.1.2   root      451:                if (ssg) {
                    452:                        ssg->Write1(addr, data);
                    453:                }
1.1       root      454:                return 0;
                    455: 
                    456:         case 0x90:                                     // INT0 ネゲート
                    457:                putlog(1, "%s Negate INT0", IOName(addr).c_str());
                    458:                NegateINT0();
                    459:                return 0;
                    460: 
                    461:         case 0xa0:                                     // レベル5 割り込み要求
                    462:                putlog(1, "%s Interrupt High", IOName(addr).c_str());
                    463:                pio0->InterruptXPHigh();
                    464:                return 0;
                    465: 
                    466:         case 0xb0:                                     // レベル1 割り込み要求
                    467:                putlog(1, "%s Interrupt Low", IOName(addr).c_str());
                    468:                pio0->InterruptXPLow();
                    469:                return 0;
                    470: 
                    471:         default:
                    472:                break;
                    473:        }
                    474: 
                    475:        putlog(0, "WriteExternalIO %s <- $%02x (NOT IMPLEMENTED)",
                    476:                IOName(addr).c_str(), data);
                    477:        return 0;
                    478: }
                    479: 
                    480: uint32
                    481: MPU64180Device::WriteTMDRL(int ch, uint32 data)
                    482: {
                    483:        auto& t = timer[ch];
                    484:        if (t.running) {
                    485:                // タイマー動作中の更新は inhibited と書いてあるけど、実際どうなる?
                    486:                putlog(0, "Writing %s <- $%02x while timer is running! (ignored)",
                    487:                        IOName(HD647180::IO_TMDRL(ch)).c_str(), data);
                    488:        } else {
                    489:                t.count = (t.count & 0xff00) | data;
1.1.1.2   root      490:                putlog(1, "%s <- $%02x (TMDR%u = $%04x)",
1.1       root      491:                        IOName(HD647180::IO_TMDRL(ch)).c_str(), data, ch, t.count);
                    492:        }
                    493:        return 0;
                    494: }
                    495: 
                    496: uint32
                    497: MPU64180Device::WriteTMDRH(int ch, uint32 data)
                    498: {
                    499:        auto& t = timer[ch];
                    500:        if (t.running) {
                    501:                // タイマー動作中の更新は inhibited と書いてあるけど、実際どうなる?
                    502:                putlog(0, "Writing %s <- $%02x while timer is running! (ignored)",
                    503:                        IOName(HD647180::IO_TMDRH(ch)).c_str(), data);
                    504:        } else {
                    505:                t.count = (data << 8) | (t.count & 0x00ff);
1.1.1.2   root      506:                putlog(1, "%s <- $%02x (TMDR%u = $%04x)",
1.1       root      507:                        IOName(HD647180::IO_TMDRH(ch)).c_str(), data, ch, t.count);
                    508:        }
                    509:        return 0;
                    510: }
                    511: 
                    512: uint32
                    513: MPU64180Device::WriteRLDRL(int ch, uint32 data)
                    514: {
                    515:        // 動作中にも変更可能
                    516:        auto& t = timer[ch];
                    517:        t.reload = (t.reload & 0xff00) | data;
1.1.1.2   root      518:        putlog(1, "%s <- $%02x (RLDR%u = $%04x)",
1.1       root      519:                IOName(HD647180::IO_RLDRL(ch)).c_str(), data, ch, t.reload);
                    520:        return 0;
                    521: }
                    522: 
                    523: uint32
                    524: MPU64180Device::WriteRLDRH(int ch, uint32 data)
                    525: {
                    526:        // 動作中にも変更可能
                    527:        auto& t = timer[ch];
                    528:        t.reload = (data << 8) | (t.reload & 0x00ff);
1.1.1.2   root      529:        putlog(1, "%s <- $%02x (RLDR%u = $%04x)",
1.1       root      530:                IOName(HD647180::IO_RLDRH(ch)).c_str(), data, ch, t.reload);
                    531:        return 0;
                    532: }
                    533: 
                    534: uint32
                    535: MPU64180Device::WriteTCR(uint32 data)
                    536: {
                    537:        std::array<bool, 2> new_tde;
                    538:        std::string msg;
                    539: 
                    540:        timer[1].intr_enable = (data & 0x20);
                    541:        timer[0].intr_enable = (data & 0x10);
                    542:        // intr_enable を変更したので ChangeTimerInterrupt() を呼ぶのは
                    543:        // 最後に行っている。
                    544: 
                    545:        timer_toc = (data >> 2) & 3;
                    546: 
                    547:        new_tde[1] = (data & 0x02);
                    548:        new_tde[0] = (data & 0x01);
1.1.1.2   root      549:        msg = string_format("TIE1=%u TIE0=%u TOC=$%x",
1.1       root      550:                (timer[1].intr_enable ? 1 : 0),
                    551:                (timer[0].intr_enable ? 1 : 0),
                    552:                timer_toc);
                    553: 
                    554:        for (int ch = 0; ch < timer.size(); ch++) {
                    555:                auto& t = timer[ch];
                    556:                if (t.running == false && new_tde[ch] == true) {
                    557:                        // カウントダウン開始
                    558:                        t.count = t.reload;
                    559:                        t.running = true;
                    560:                        MakeActiveTimer();
1.1.1.2   root      561:                        msg += string_format(" Timer%u=Start", ch);
1.1       root      562:                        EnableTimer();
                    563:                } else if (t.running == true && new_tde[ch] == false) {
                    564:                        // カウントダウン停止
                    565: 
                    566:                        // ここではタイマーの状態を停止にするだけでよい。
                    567:                        // タイマーイベントの中で running が落ちてたら停止してくれる。
                    568:                        t.running = false;
                    569:                        MakeActiveTimer();
1.1.1.2   root      570:                        msg += string_format(" Timer%u=Stop", ch);
1.1       root      571:                } else {
                    572:                        // 変化なし
                    573:                }
                    574:        }
                    575: 
                    576:        putlog(1, "%s <- $%02x: %s",
                    577:                IOName(HD647180::IO_TCR).c_str(), data, msg.c_str());
                    578: 
                    579:        // ログの順序的に書き込みログの後で変更する
                    580:        ChangeTimerInterrupt();
                    581: 
                    582:        return 0;
                    583: }
                    584: 
                    585: uint32
                    586: MPU64180Device::WriteDCNTL(uint32 data)
                    587: {
                    588:        // メモリウェイト 0,1,2,3
                    589:        memwait = (data >> 6) & 3;
                    590: 
                    591:        // I/O ウェイトは 0,2,3,4
                    592:        iowait = (data >> 4) & 3;
                    593:        if (iowait != 0)
                    594:                iowait++;
                    595: 
                    596:        // 下位4ビット分は未実装
                    597:        dcntl = data & 0x0f;
                    598:        return 0;
                    599: }
                    600: 
                    601: uint32
                    602: MPU64180Device::WriteIL(uint32 data)
                    603: {
                    604:        // 書き込み時にマスクする
                    605:        intvec_low = data & 0xe0;
                    606:        return 0;
                    607: }
                    608: 
                    609: uint32
                    610: MPU64180Device::WriteITC(uint32 data)
                    611: {
                    612:        itc_trap = (data & 0x80);
                    613:        // UFO は ReadOnly
                    614:        itc_ite2 = (data & 0x04);
                    615:        itc_ite1 = (data & 0x02);
                    616:        itc_ite0 = (data & 0x01);
                    617: 
                    618:        // XXX 割り込み変わったら何かする?
                    619: 
                    620:        return 0;
                    621: }
                    622: 
                    623: uint32
                    624: MPU64180Device::WriteRCR(uint32 data)
                    625: {
                    626:        // 未実装
                    627:        rcr = data | 0x3c;
                    628: 
                    629:        if ((rcr & 0x80)) {
                    630:                // Refresh Enable は未実装。無効にするなら表示不要。
                    631:                putlog(0, "%s <- $%02x: Refresh Enable (NOT IMPLEMENTED)",
                    632:                        IOName(HD647180::IO_RCR).c_str(), data);
                    633:        } else {
                    634:                // ログレベル 1 なら全部表示
                    635:                putlog(1, "%s <- $%02x (NOT IMPLEMENTED)",
                    636:                        IOName(HD647180::IO_RCR).c_str(), data);
                    637:        }
                    638:        return 0;
                    639: }
                    640: 
                    641: uint32
                    642: MPU64180Device::WriteCBR(uint32 data)
                    643: {
                    644:        int lv;
                    645:        uint32 new_base = data << 12;
                    646:        if (commbase != new_base) {
                    647:                lv = 1;
                    648:                commbase = new_base;
                    649:        } else {
                    650:                lv = 2;
                    651:        }
                    652:        putlog(lv, "%s <- $%02x: Common Base Addr=$%05x",
                    653:                IOName(HD647180::IO_CBR).c_str(), data, commbase);
                    654:        return 0;
                    655: }
                    656: 
                    657: uint32
                    658: MPU64180Device::WriteBBR(uint32 data)
                    659: {
                    660:        int lv;
                    661:        uint32 new_base = data << 12;
                    662:        if (bankbase != new_base) {
                    663:                lv = 1;
                    664:                bankbase = new_base;
                    665:        } else {
                    666:                lv = 2;
                    667:        }
                    668:        putlog(lv, "%s <- $%02x: Bank Base Addr=$%05x",
                    669:                IOName(HD647180::IO_BBR).c_str(), data, bankbase);
                    670:        return 0;
                    671: }
                    672: 
                    673: uint32
                    674: MPU64180Device::WriteCBAR(uint32 data)
                    675: {
                    676:        int lv;
                    677:        uint32 new_comm = (data & 0xf0) << 8;
                    678:        uint32 new_bank = (data & 0x0f) << 12;
                    679:        if (commarea != new_comm || bankarea != new_bank) {
                    680:                lv = 1;
                    681:                commarea = new_comm;
                    682:                bankarea = new_bank;
                    683:        } else {
                    684:                lv = 2;
                    685:        }
                    686:        putlog(lv, "%s <- $%02x: CommArea=$%04x BankArea=$%04x",
                    687:                IOName(HD647180::IO_CBAR).c_str(), data, commarea, bankarea);
                    688:        return 0;
                    689: }
                    690: 
                    691: uint32
                    692: MPU64180Device::WriteICR(uint32 data)
                    693: {
                    694:        io_address = data & 0x80;
                    695:        putlog(1, "%s <- $%02x: I/O Address=$%02x",
                    696:                IOName(HD647180::IO_ICR).c_str(), data, io_address);
                    697: 
                    698:        // IOSTP は未実装
                    699:        if ((data & 0x20) != 0) {
                    700:                putlog(0, "%s IOSTP (NOT IMPLEMENTED)");
                    701:        }
                    702:        return 0;
                    703: }
                    704: 
                    705: uint32
                    706: MPU64180Device::WriteRMCR(uint32 data)
                    707: {
                    708:        xpbus->SetRMCR(data);
                    709:        putlog(1, "%s <- $%02x: RAM address=$%05x",
                    710:                IOName(HD647180::IO_RMCR).c_str(), data, xpbus->GetXPRAMAddr());
                    711:        return 0;
                    712: }
                    713: 
                    714: uint32
                    715: MPU64180Device::PeekIO(uint32 addr)
                    716: {
                    717:        // 内蔵 I/O
                    718:        if (io_address <= addr && addr < io_address + 0x80) {
                    719:                return PeekInternalIO(addr - io_address);
                    720:        }
                    721: 
                    722:        return PeekExternalIO(addr);
                    723: }
                    724: 
                    725: uint32
                    726: MPU64180Device::PeekInternalIO(uint32 offset)
                    727: {
                    728:        switch (offset) {
                    729:         case 0x00:                                     // IO_CNTLA0
1.1.1.3   root      730:                return asci->PeekCNTLA(0);
1.1       root      731:         case 0x01:                                     // IO_CNTLA1
1.1.1.3   root      732:                return asci->PeekCNTLA(1);
1.1       root      733:         case 0x02:                                     // IO_CNTLB0
1.1.1.3   root      734:                return asci->PeekCNTLB(0);
1.1       root      735:         case 0x03:                                     // IO_CNTLB1
1.1.1.3   root      736:                return asci->PeekCNTLB(1);
1.1       root      737:         case 0x04:                                     // IO_STAT0
1.1.1.3   root      738:                return asci->PeekSTAT(0);
1.1       root      739:         case 0x05:                                     // IO_STAT1
1.1.1.3   root      740:                return asci->PeekSTAT(1);
1.1       root      741:         case 0x06:                                     // IO_TDR0
1.1.1.3   root      742:                return asci->PeekTDR(0);
1.1       root      743:         case 0x07:                                     // IO_TDR1
1.1.1.3   root      744:                return asci->PeekTDR(1);
                    745:         case 0x08:                                     // IO_RDR0
                    746:                return asci->PeekRDR(0);
                    747:         case 0x09:                                     // IO_RDR1
                    748:                return asci->PeekRDR(1);
                    749: 
1.1       root      750:         case 0x0a:                                     // IO_CNTR
                    751:         case 0x0b:                                     // IO_TRDR
                    752:                break;
                    753: 
                    754:         case 0x0c:                                     // IO_TMDR0L
                    755:                return PeekTMDRL(0);
                    756:         case 0x0d:                                     // IO_TMDR0H
                    757:                return PeekTMDRH(0);
                    758:         case 0x0e:                                     // IO_RLDR0L
                    759:                return PeekRLDRL(0);
                    760:         case 0x0f:                                     // IO_RLDR0H
                    761:                return PeekRLDRH(0);
                    762:         case 0x10:                                     // IO_TCR
                    763:                return PeekTCR();
                    764:         case 0x14:                                     // IO_TMDR1L
                    765:                return PeekTMDRL(1);
                    766:         case 0x15:                                     // IO_TMDR1H
                    767:                return PeekTMDRH(1);
                    768:         case 0x16:                                     // IO_RLDR1L
                    769:                return PeekRLDRL(1);
                    770:         case 0x17:                                     // IO_RLDR1H
                    771:                return PeekRLDRH(1);
                    772:         case 0x18:                                     // IO_FRC
                    773:                return PeekFRC();
                    774: 
                    775:         case 0x20:                                     // IO_SAR0L
                    776:         case 0x21:                                     // IO_SAR0H
                    777:         case 0x22:                                     // IO_SAR0B
                    778:         case 0x23:                                     // IO_DAR0L
                    779:         case 0x24:                                     // IO_DAR0H
                    780:         case 0x25:                                     // IO_DAR0B
                    781:         case 0x26:                                     // IO_BCR0L
                    782:         case 0x27:                                     // IO_BCR0H
                    783:         case 0x28:                                     // IO_MAR1L
                    784:         case 0x29:                                     // IO_MAR1H
                    785:         case 0x2a:                                     // IO_MAR1B
                    786:         case 0x2b:                                     // IO_IAR1L
                    787:         case 0x2c:                                     // IO_IAR1H
                    788:         case 0x2e:                                     // IO_BCR1L
                    789:         case 0x2f:                                     // IO_BCR1H
                    790:         case 0x30:                                     // IO_DSTAT
                    791:         case 0x31:                                     // IO_DMODE
                    792:                break;
                    793:         case 0x32:                                     // IO_DCNTL
                    794:                return PeekDCNTL();
                    795: 
                    796:         case 0x33:                                     // IO_IL
                    797:                return PeekIL();
                    798:         case 0x34:                                     // IO_ITC
                    799:                return PeekITC();
                    800:         case 0x36:                                     // IO_RCR
                    801:                return PeekRCR();
                    802: 
                    803:         case 0x38:                                     // IO_CBR
                    804:                return PeekCBR();
                    805:         case 0x39:                                     // IO_BBR
                    806:                return PeekBBR();
                    807:         case 0x3a:                                     // IO_CBAR
                    808:                return PeekCBAR();
                    809: 
                    810:         case 0x3e:                                     // IO_OMCR
                    811:                break;
                    812:         case 0x3f:                                     // IO_ICR
                    813:                return PeekICR();
                    814: 
                    815:         case 0x40:                                     // IO_T2FRCL
                    816:         case 0x41:                                     // IO_T2FRCH
                    817:         case 0x42:                                     // IO_T2OCR1L
                    818:         case 0x43:                                     // IO_T2OCR1H
                    819:         case 0x44:                                     // IO_T2OCR2L
                    820:         case 0x45:                                     // IO_T2OCR2H
                    821:         case 0x46:                                     // IO_T2ICRL
                    822:         case 0x47:                                     // IO_T2ICRH
                    823:         case 0x48:                                     // IO_T2CSR1
                    824:         case 0x49:                                     // IO_T2CSR2
                    825:                break;
                    826: 
                    827:         case 0x50:                                     // IO_CCSR
                    828:                break;
                    829:         case 0x51:                                     // IO_RMCR
                    830:                return xpbus->GetRMCR();
                    831: 
                    832:         case 0x53:                                     // IO_DERA
                    833:         case 0x60:                                     // IO_IODRA
                    834:         case 0x61:                                     // IO_IODRB
                    835:         case 0x62:                                     // IO_IODRC
                    836:         case 0x63:                                     // IO_IODRD
                    837:         case 0x64:                                     // IO_IODRE
                    838:         case 0x65:                                     // IO_IODRF
                    839:         case 0x66:                                     // IO_IDRG
                    840:         case 0x70:                                     // IO_DDRA
                    841:         case 0x71:                                     // IO_DDRB
                    842:         case 0x72:                                     // IO_DDRC
                    843:         case 0x73:                                     // IO_DDRD
                    844:         case 0x74:                                     // IO_DDRE
                    845:         case 0x75:                                     // IO_DDRF
                    846:                break;
                    847: 
                    848:         default:
                    849:                break;
                    850:        }
                    851:        return 0xff;
                    852: }
                    853: 
                    854: uint32
                    855: MPU64180Device::PeekExternalIO(uint32 addr)
                    856: {
                    857:        // LUNA の外部 I/O はアドレスの上位バイト不問
                    858:        switch (addr & 0xff) {
                    859:         case 0x82:                                     // SSG
                    860:         case 0x83:                                     // SSG
1.1.1.2   root      861:                if (ssg) {
                    862:                        return ssg->Peek1(addr);
                    863:                }
1.1       root      864:                break;
                    865: 
                    866:         case 0x90:                                     // INT0 ネゲート
                    867:                break;
                    868: 
                    869:         case 0xa0:                                     // レベル5 割り込み要求
                    870:         case 0xb0:                                     // レベル1 割り込み要求
                    871:                break;
                    872: 
                    873:         default:
                    874:                break;
                    875:        }
                    876:        return 0xff;
                    877: }
                    878: 
                    879: uint32
                    880: MPU64180Device::PeekTMDRL(int ch) const
                    881: {
                    882:        return timer[ch].count & 0xff;
                    883: }
                    884: 
                    885: uint32
                    886: MPU64180Device::PeekTMDRH(int ch) const
                    887: {
                    888:        return timer[ch].count >> 8;
                    889: }
                    890: 
                    891: uint32
                    892: MPU64180Device::PeekRLDRL(int ch) const
                    893: {
                    894:        return timer[ch].reload & 0xff;
                    895: }
                    896: 
                    897: uint32
                    898: MPU64180Device::PeekRLDRH(int ch) const
                    899: {
                    900:        return timer[ch].reload >> 8;
                    901: }
                    902: 
                    903: uint32
                    904: MPU64180Device::PeekTCR() const
                    905: {
                    906:        uint32 data = (timer_toc << 2);
                    907: 
                    908:        if (timer[1].tif != 0)
                    909:                data |= 0x80;
                    910:        if (timer[0].tif != 0)
                    911:                data |= 0x40;
                    912:        if (timer[1].intr_enable)
                    913:                data |= 0x20;
                    914:        if (timer[0].intr_enable)
                    915:                data |= 0x10;
                    916:        if (timer[1].running)
                    917:                data |= 0x02;
                    918:        if (timer[0].running)
                    919:                data |= 0x01;
                    920: 
                    921:        return data;
                    922: }
                    923: 
                    924: uint32
                    925: MPU64180Device::PeekFRC() const
                    926: {
                    927:        if (opmode == OpMode::Reset) {
                    928:                return 0xff;
                    929:        } else {
                    930:                // Free Running Counter はリセット時に 0FFH で、
                    931:                // そこから 10φ ごとに1ずつ減っていく。
                    932:                // そのため、リセット時の時刻を覚えておき、経過時間から計算する。
                    933:                uint64 time = scheduler->GetVirtTime() - timer_epoch;
1.1.1.4 ! root      934:                return 0xff - (uint8)(time / (clock_tsec * 10));
1.1       root      935:        }
                    936: }
                    937: 
                    938: uint32
                    939: MPU64180Device::PeekDCNTL() const
                    940: {
                    941:        uint32 data;
                    942: 
                    943:        data = (memwait << 6);
                    944:        if (iowait != 0) {
                    945:                data |= (iowait - 1) << 4;
                    946:        }
                    947:        data |= dcntl;
                    948: 
                    949:        return data;
                    950: }
                    951: 
                    952: uint32
                    953: MPU64180Device::PeekIL() const
                    954: {
                    955:        return intvec_low;
                    956: }
                    957: 
                    958: uint32
                    959: MPU64180Device::PeekITC() const
                    960: {
                    961:        uint32 data = 0x38;
                    962:        if (itc_trap)
                    963:                data |= 0x80;
                    964:        if (itc_ufo)
                    965:                data |= 0x40;
                    966:        if (itc_ite2)
                    967:                data |= 0x04;
                    968:        if (itc_ite1)
                    969:                data |= 0x02;
                    970:        if (itc_ite0)
                    971:                data |= 0x01;
                    972:        return data;
                    973: }
                    974: 
                    975: uint32
                    976: MPU64180Device::PeekRCR() const
                    977: {
                    978:        return rcr;
                    979: }
                    980: 
                    981: uint32
                    982: MPU64180Device::PeekCBR() const
                    983: {
                    984:        return (commbase >> 12) & 0xff;
                    985: }
                    986: 
                    987: uint32
                    988: MPU64180Device::PeekBBR() const
                    989: {
                    990:        return (bankbase >> 12) & 0xff;
                    991: }
                    992: 
                    993: uint32
                    994: MPU64180Device::PeekCBAR() const
                    995: {
                    996:        uint32 data;
                    997: 
                    998:        data  = (commarea >>  8) & 0xf0;
                    999:        data |= (bankarea >> 12) & 0x0f;
                   1000: 
                   1001:        return data;
                   1002: }
                   1003: 
                   1004: uint32
                   1005: MPU64180Device::PeekICR() const
                   1006: {
                   1007:        // IOSTP は未実装
                   1008:        return io_address | 0x5f;
                   1009: }
                   1010: 
                   1011: uint32
                   1012: MPU64180Device::PeekRMCR() const
                   1013: {
                   1014:        return xpbus->GetRMCR();
                   1015: }
                   1016: 
                   1017: // アドレス (とあれば名前) を返す。
                   1018: /*static*/ std::string
                   1019: MPU64180Device::IOName(uint32 addr)
                   1020: {
                   1021:        std::string buf;
                   1022: 
                   1023:        if (addr < 0x100) {
                   1024:                buf = string_format("%02XH", addr);
                   1025:        } else {
                   1026:                buf = string_format("%04XH", addr);
                   1027:        }
                   1028: 
                   1029:        if (addr < ionames.size() && ionames[addr] != NULL) {
                   1030:                buf += '(';
                   1031:                buf += ionames[addr];
                   1032:                buf += ')';
                   1033:        }
                   1034:        return buf;
                   1035: }
                   1036: 
                   1037: /*static*/ std::vector<const char *>
                   1038: MPU64180Device::ionames = {
                   1039:        "CNTLA0",       // 00
                   1040:        "CNTLA1",       // 01
                   1041:        "CNTLB0",       // 02
                   1042:        "CNTLB1",       // 03
                   1043:        "STAT0",        // 04
                   1044:        "STAT1",        // 05
                   1045:        "TDR0",         // 06
                   1046:        "TDR1",         // 07
1.1.1.3   root     1047:        "RDR0",         // 08
                   1048:        "RDR1",         // 09
1.1       root     1049:        "CNTR",         // 0a
                   1050:        "TRDR",         // 0b
                   1051:        "TMDR0L",       // 0c
                   1052:        "TMDR0H",       // 0d
                   1053:        "RLDR0L",       // 0e
                   1054:        "RLDR0H",       // 0f
                   1055: 
                   1056:        "TCR",          // 10
                   1057:        NULL,           // 11
                   1058:        NULL,           // 12
                   1059:        NULL,           // 13
                   1060:        "TMDR1L",       // 14
                   1061:        "TMDR1H",       // 15
                   1062:        "RLDR1L",       // 16
                   1063:        "RLDR1H",       // 17
                   1064:        "FRFC",         // 18
                   1065:        NULL,           // 19
                   1066:        NULL,           // 1a
                   1067:        NULL,           // 1b
                   1068:        NULL,           // 1c
                   1069:        NULL,           // 1d
                   1070:        NULL,           // 1e
                   1071:        NULL,           // 1f
                   1072: 
                   1073:        "SAR0L",        // 20
                   1074:        "SAR0H",        // 21
                   1075:        "SAR0B",        // 22
                   1076:        "DAR0L",        // 23
                   1077:        "DAR0H",        // 24
                   1078:        "DAR0B",        // 25
                   1079:        "BCR0L",        // 26
                   1080:        "BCR0H",        // 27
                   1081:        "MAR1L",        // 28
                   1082:        "MAR1H",        // 29
                   1083:        "MAR1B",        // 2a
                   1084:        "IAR1L",        // 2b
                   1085:        "IAR1H",        // 2c
                   1086:        NULL,           // 2d
                   1087:        "BCR1L",        // 2e
                   1088:        "BCR1H",        // 2f
                   1089: 
                   1090:        "DSTAT",        // 30
                   1091:        "DMODE",        // 31
                   1092:        "DCNTL",        // 32
                   1093:        "IL",           // 33
                   1094:        "ITC",          // 34
                   1095:        NULL,           // 35
                   1096:        "RCR",          // 36
                   1097:        NULL,           // 37
                   1098:        "CBR",          // 38
                   1099:        "BBR",          // 39
                   1100:        "CBAR",         // 3a
                   1101:        NULL,           // 3b
                   1102:        NULL,           // 3c
                   1103:        NULL,           // 3d
                   1104:        "OMCR",         // 3e
                   1105:        "ICR",          // 3f
                   1106: 
                   1107:        "T2FRCL",       // 40
                   1108:        "T2FRCH",       // 41
                   1109:        "T2OCR1L",      // 42
                   1110:        "T2OCR1H",      // 43
                   1111:        "T2OCR2L",      // 44
                   1112:        "T2OCR2H",      // 45
                   1113:        "T2ICRL",       // 46
                   1114:        "T2ICRH",       // 47
                   1115:        "T2CSR1",       // 48
                   1116:        "T2CSR2",       // 49
                   1117:        NULL,           // 4a
                   1118:        NULL,           // 4b
                   1119:        NULL,           // 4c
                   1120:        NULL,           // 4d
                   1121:        NULL,           // 4e
                   1122:        NULL,           // 4f
                   1123: 
                   1124:        "CCSR",         // 50
                   1125:        "RMCR",         // 51
                   1126:        NULL,           // 52
                   1127:        "DERA",         // 53
                   1128:        NULL,           // 54
                   1129:        NULL,           // 55
                   1130:        NULL,           // 56
                   1131:        NULL,           // 57
                   1132:        NULL,           // 58
                   1133:        NULL,           // 59
                   1134:        NULL,           // 5a
                   1135:        NULL,           // 5b
                   1136:        NULL,           // 5c
                   1137:        NULL,           // 5d
                   1138:        NULL,           // 5e
                   1139:        NULL,           // 5f
                   1140: 
                   1141:        "IODRA",        // 60
                   1142:        "IODRB",        // 61
                   1143:        "IODRC",        // 62
                   1144:        "IODRD",        // 63
                   1145:        "IODRE",        // 64
                   1146:        "IODRF",        // 65
                   1147:        "IDRG",         // 66
                   1148:        NULL,           // 67
                   1149:        NULL,           // 68
                   1150:        NULL,           // 69
                   1151:        NULL,           // 6a
                   1152:        NULL,           // 6b
                   1153:        NULL,           // 6c
                   1154:        NULL,           // 6d
                   1155:        NULL,           // 6e
                   1156:        NULL,           // 6f
                   1157: 
                   1158:        "DDRA",         // 70
                   1159:        "DDRB",         // 71
                   1160:        "DDRC",         // 72
                   1161:        "DDRD",         // 73
                   1162:        "DDRE",         // 74
                   1163:        "DDRF",         // 75
                   1164: };

unix.superglobalmegacorp.com

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