Annotation of nono/vm/prom.cpp, revision 1.1.1.12

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
1.1.1.10  root        7: //
1.1.1.12! root        8: // PROM (LUNA-I, LUNA-88K 共通)
1.1.1.8   root        9: //
1.1.1.10  root       10: 
1.1.1.8   root       11: // IODevice
                     12: //    |
                     13: //    +-- ROMDevice (LoadROM()、ウェイト、マスク等を持つ)
                     14: //    |     |
                     15: //    |     |  +------------+
                     16: //    |     +--| PROMDevice |  (LUNA* の PROM)
                     17: //    |     |  +------------+
                     18: //    |     |
                     19: //    |     +-- IPLROM1Device (X680x0 の IPLROM 後半)
                     20: //    |     +-- IPLROM2Device (X680x0 の IPLROM 前半)
                     21: //    |     +-- CGROMDevice   (X680x0 の CGROM)
                     22: //    |     +-- LunaPROMEmuDevice   (LUNA PROM エミュレーションの共通部分)
                     23: //    |           |
1.1.1.12! root       24: //    |           +-- Luna1PROMEmuDevice   (LUNA-I の PROM エミュレーション)
        !            25: //    |           +-- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション)
1.1.1.8   root       26: //    |
                     27: //    |   +-------------+
                     28: //    +-- | PROM0Device | (LUNA* のブートページ切り替え用プロキシ)
                     29: //    |   +-------------+
                     30: //    |
                     31: //    +-- IPLROM0Device   (X680x0 のブートページ切り替え用プロキシ)
1.1       root       32: 
                     33: #include "prom.h"
                     34: #include "config.h"
1.1.1.8   root       35: #include "ethernet.h"
1.1       root       36: #include "mainapp.h"
1.1.1.11  root       37: #include "vm.h"
1.1       root       38: 
1.1.1.8   root       39: //
                     40: // PROM0
                     41: //
                     42: // PROM0 は PROM のブートページ担当。
                     43: // これ自身はメモリ領域を持たず PROM へのプロキシとして動作する。
                     44: //
                     45: // リセット後最初の ROM 領域への書き込みアクセスでブートページを RAM に
                     46: // 切り替える。
                     47: // LUNA のブートページのアドレス範囲は不明なので、とりあえず devtable の
                     48: // 1区画である 16MB ($0000'0000..$00ff'ffff) とする。実害はない。
                     49: 
                     50: // コンストラクタ
                     51: PROM0Device::PROM0Device()
1.1.1.12! root       52:        : inherited(OBJ_PROM_BOOT)
1.1.1.8   root       53: {
1.1.1.12! root       54:        // 通常ここからログを出すことはない
1.1.1.8   root       55:        ClearAlias();
                     56: }
                     57: 
                     58: // デストラクタ
                     59: PROM0Device::~PROM0Device()
                     60: {
                     61: }
                     62: 
1.1.1.12! root       63: // 初期化
1.1.1.8   root       64: bool
                     65: PROM0Device::Init()
                     66: {
1.1.1.12! root       67:        if (inherited::Init() == false) {
        !            68:                return false;
        !            69:        }
        !            70: 
        !            71:        prom = GetPROMDevice();
        !            72: 
1.1.1.8   root       73:        return true;
                     74: }
                     75: 
1.1.1.10  root       76: // リセット
1.1.1.8   root       77: void
1.1.1.10  root       78: PROM0Device::ResetHard(bool poweron)
1.1.1.8   root       79: {
                     80:        gVM->SwitchBootPageToROM(this);
                     81: }
                     82: 
                     83: // アドレスデコーダ
                     84: /*static*/ inline uint32
                     85: PROM0Device::Decoder(uint32 addr)
                     86: {
                     87:        // ここはブートページか ROM かの比較だけで十分 (それ以外はここに来ない)
                     88:        if (addr < 0x0100'0000) {
                     89:                addr += 0x4100'0000;
                     90:        }
                     91:        return addr;
                     92: }
                     93: 
                     94: uint64
                     95: PROM0Device::Read8(uint32 addr)
                     96: {
                     97:        addr = Decoder(addr);
                     98:        return prom->Read8(addr);
                     99: }
                    100: 
                    101: uint64
                    102: PROM0Device::Read16(uint32 addr)
                    103: {
                    104:        addr = Decoder(addr);
                    105:        return prom->Read16(addr);
                    106: }
                    107: 
                    108: uint64
                    109: PROM0Device::Read32(uint32 addr)
                    110: {
                    111:        addr = Decoder(addr);
                    112:        return prom->Read32(addr);
                    113: }
                    114: 
                    115: // LUNA では PROM へのライトアクセスでブートページを RAM に切り替えている。
                    116: // - LUNA-I では最初に $41000000.B への書き込みがあるが、
                    117: //   それ以降も $41000000.L への書き込みが(複数回)あるようだ。
1.1.1.12! root      118: // - LUNA-88K では $4100000c.L への書き込みがある。
1.1.1.8   root      119: //
                    120: // よってアドレスを定めず PROM 全域への書き込みで最初の1回だけ発動する
                    121: // ようにしておく。サイズも今の所ワード(16bit)アクセスは確認してないけど
                    122: // 統一的に対処しておく。
                    123: uint64
                    124: PROM0Device::Write()
                    125: {
                    126:        gVM->SwitchBootPageToRAM(this);
                    127: 
                    128:        // バスエラーは起きない
                    129:        return 0;
                    130: }
                    131: 
                    132: uint64
                    133: PROM0Device::Write8(uint32 addr, uint32 data)
                    134: {
                    135:        return Write();
                    136: }
                    137: 
                    138: uint64
                    139: PROM0Device::Write16(uint32 addr, uint32 data)
                    140: {
                    141:        return Write();
                    142: }
                    143: 
                    144: uint64
                    145: PROM0Device::Write32(uint32 addr, uint32 data)
                    146: {
                    147:        return Write();
                    148: }
                    149: 
                    150: uint64
                    151: PROM0Device::Peek8(uint32 addr)
                    152: {
                    153:        addr = Decoder(addr);
                    154:        return prom->Peek8(addr);
                    155: }
                    156: 
                    157: 
                    158: //
                    159: // PROM
                    160: //
                    161: 
1.1       root      162: // コンストラクタ
                    163: PROMDevice::PROMDevice()
1.1.1.12! root      164:        : inherited(OBJ_PROM)
1.1       root      165: {
1.1.1.8   root      166:        // LUNA では ROM への書き込みは何も起きない
                    167:        write_op = 0;
1.1       root      168: }
                    169: 
                    170: // デストラクタ
                    171: PROMDevice::~PROMDevice()
                    172: {
                    173: }
                    174: 
1.1.1.12! root      175: // 初期化
1.1       root      176: bool
                    177: PROMDevice::Init()
                    178: {
1.1.1.12! root      179:        if (inherited::Init() == false) {
        !           180:                return false;
        !           181:        }
        !           182: 
1.1.1.11  root      183:        VMType vmtype = gMainApp.GetVMType();
1.1       root      184: 
                    185:        switch (vmtype) {
1.1.1.11  root      186:         case VMType::LUNA1:
1.1.1.12! root      187:                if (gMainApp.msxdos_mode) {
        !           188:                        return true;
        !           189:                } else {
        !           190:                        return InitLuna1();
        !           191:                }
1.1       root      192: 
1.1.1.11  root      193:         case VMType::LUNA88K:
1.1       root      194:                return InitLuna88k();
                    195: 
                    196:         default:
1.1.1.11  root      197:                PANIC("unknown vmtype %d", (int)vmtype);
1.1       root      198:        }
                    199: }
                    200: 
                    201: // LUNA-I の場合
                    202: bool
1.1.1.6   root      203: PROMDevice::InitLuna1()
1.1       root      204: {
1.1.1.12! root      205:        uint devlen = 128 * 1024;
1.1       root      206:        mask = devlen - 1;
                    207: 
                    208:        // ファイル名が存在してる時しかここに来ない
                    209:        const ConfigItem& item = gConfig->Find("prom-image");
                    210:        if (LoadROM(item.AsString().c_str(), devlen) == false) {
                    211:                return false;
                    212:        }
                    213: 
1.1.1.8   root      214:        // XXX アクセスウェイトは未調査。とりあえず RAM と同程度にしておく
                    215:        wait = 1;
                    216: 
1.1.1.2   root      217:        // ROM バージョンを確認。確認されてるのは
                    218:        // V4.02 (Wed Oct 12 17:07:11 1988)
                    219:        // V4.22 (Thu Jul 27 11:45:42 1989)
                    220:        // V4.25
                    221:        //
                    222:        // とりあえず V4.22 は +$00d390 からにタイムスタンプ文字列があるので
                    223:        // それで判別してみる。
                    224:        //00d390 54 68 75 20 4a 75 6c 20 32 37 20 31 31 3a 34 35 |Thu Jul 27 11:45|
                    225:        //00d3a0 3a 34 32 20 31 39 38 39 00 00 00 00 4e 56 fd f8 |:42 1989....NV..|
                    226: 
                    227:        if (strcmp((const char *)&mem[0xd390], "Thu Jul 27 11:45:42 1989") == 0) {
1.1.1.12! root      228:                romver = 422;
        !           229:        }
        !           230: 
        !           231:        if (romver == 0) {
        !           232:                putmsg(0, "Unknown PROM version");
        !           233:        } else {
        !           234:                putmsg(1, "v%d.%02d detected", romver / 100, romver % 100);
        !           235:        }
        !           236: 
        !           237:        if (romver == 422) {
        !           238:                // V4.22。他の ROM は何も分からないので何もしない。
1.1.1.2   root      239: 
                    240:                // MAC アドレスは ROM に書き込まれているので、ここで上書き
                    241:                if (strcmp((const char *)&mem[0x1ffd8], "ENADDR") != 0) {
                    242:                        warnx("ENADDR not found; unknown ROM V4.22 variants?");
                    243:                        return false;
                    244:                }
                    245: 
                    246:                // MAC アドレスは12桁の16進数文字列として書き込まれている。例えば
                    247:                // 前半の 00:00:0A 部分は 30 30 30 30 30 41 "00000A" という感じ。
1.1.1.12! root      248:                macaddr_t macaddr {};
        !           249:                if (EthernetDevice::GetConfigMacAddr(&macaddr, true) == false) {
        !           250:                        // エラーメッセージは表示済み
        !           251:                        return false;
        !           252:                }
        !           253: 
        !           254:                const char *msg;
        !           255:                if (macaddr.Empty()) {
        !           256:                        // "rom" なら元イメージのままにする。
        !           257:                        msg = "ROM";
        !           258:                } else {
        !           259:                        // 指定されたら上書き。
        !           260:                        memcpy(&imagebuf[0x1ffe0], macaddr.ToString().c_str(), 12);
        !           261:                        msg = "config";
        !           262:                }
        !           263:                putmsg(1, "macaddr=%c%c:%c%c:%c%c:%c%c:%c%c:%c%c (from %s)",
        !           264:                        std::tolower(imagebuf[0x1ffe0]),
        !           265:                        std::tolower(imagebuf[0x1ffe1]),
        !           266:                        std::tolower(imagebuf[0x1ffe2]),
        !           267:                        std::tolower(imagebuf[0x1ffe3]),
        !           268:                        std::tolower(imagebuf[0x1ffe4]),
        !           269:                        std::tolower(imagebuf[0x1ffe5]),
        !           270:                        std::tolower(imagebuf[0x1ffe6]),
        !           271:                        std::tolower(imagebuf[0x1ffe7]),
        !           272:                        std::tolower(imagebuf[0x1ffe8]),
        !           273:                        std::tolower(imagebuf[0x1ffe9]),
        !           274:                        std::tolower(imagebuf[0x1ffea]),
        !           275:                        std::tolower(imagebuf[0x1ffeb]),
        !           276:                        msg);
1.1.1.2   root      277: 
                    278:                // SCSI デバッグビット
                    279:                bool scsi_debug_bit = gConfig->Find(".prom-scsi-debug").AsInt();
1.1.1.11  root      280:                imagebuf[0x4100981d - 0x41000000] = (scsi_debug_bit) ? 0x01 : 0;
1.1       root      281:        }
                    282: 
                    283:        return true;
                    284: }
                    285: 
1.1.1.12! root      286: // LUNA-88K の場合
1.1       root      287: bool
                    288: PROMDevice::InitLuna88k()
                    289: {
1.1.1.12! root      290:        uint devlen = 256 * 1024;
1.1       root      291:        mask = devlen - 1;
                    292: 
                    293:        // ファイル名が存在してる時しかここに来ない
                    294:        const ConfigItem& item = gConfig->Find("prom-image");
                    295:        if (LoadROM(item.AsString().c_str(), devlen) == false) {
                    296:                return false;
                    297:        }
                    298: 
1.1.1.8   root      299:        // XXX アクセスウェイトは未調査。とりあえず RAM と同程度にしておく
                    300:        wait = 3;
                    301: 
1.1.1.12! root      302:        // ROM バージョンを照合。どこかに日付が埋まってるっぽい。
        !           303:        //
        !           304:        // 1.20:
        !           305:        //02c190 00 00 04 b0 28 0d 2f e1 28 0d 2f e1 54 68 75 20 |....(./.(./.Thu |
        !           306:        //02c1a0 41 70 72 20 31 38 20 31 34 3a 33 34 3a 32 35 20 |Apr 18 14:34:25 |
        !           307:        //02c1b0 31 39 39 31 00 00 00 00 41 02 c1 9c 00 00 00 00 |1991....A.......|
        !           308:        //
        !           309:        // 1.31:
        !           310:        //03c940 00 00 05 1e 2a 0f 28 78 2a 0f 28 78 54 75 65 20 |....*.(x*.(xTue |
        !           311:        //03c950 4d 61 79 20 31 32 20 31 31 3a 30 37 3a 35 32 20 |May 12 11:07:52 |
        !           312:        //03c960 31 39 39 32 00 00 00 00 41 03 c9 4c 00 00 00 00 |1992....A..L....|
        !           313:        //
        !           314:        // 1.37:
        !           315:        //03cf30 00 00 05 5a 2b 5a 4a 7d 2b 5a 4a 7d 4d 6f 6e 20 |...Z+ZJ}+ZJ}Mon |
        !           316:        //03cf40 4a 61 6e 20 31 38 20 31 35 3a 31 33 3a 31 37 20 |Jan 18 15:13:17 |
        !           317:        //03cf50 31 39 39 33 00 00 00 00 41 03 cf 3c 00 00 00 00 |1993....A..<....|
        !           318: 
        !           319:        if (strcmp((const char *)&mem[0x2c19c], "Thu Apr 18 14:34:25 1991") == 0) {
        !           320:                romver = 120;
        !           321:        } else
        !           322:        if (strcmp((const char *)&mem[0x3c94c], "Tue May 12 11:07:52 1992") == 0) {
        !           323:                romver = 131;
        !           324:        } else
        !           325:        if (strcmp((const char *)&mem[0x3cf3c], "Mon Jan 18 15:13:17 1993") == 0) {
        !           326:                romver = 137;
        !           327:        }
        !           328: 
        !           329:        if (romver == 0) {
        !           330:                putmsg(0, "Unknown PROM version");
        !           331:        } else {
        !           332:                putmsg(1, "v%d.%02d detected", romver / 100, romver % 100);
        !           333:        }
        !           334: 
1.1       root      335:        return true;
                    336: }

unix.superglobalmegacorp.com

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