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

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

unix.superglobalmegacorp.com

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