|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2020 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: // PROM (LUNA-I, LUNA88K 共通) ! 8: ! 9: // IODevice ! 10: // | ! 11: // +----------------------------------------+ ! 12: // | | ! 13: // v v ! 14: // ROMDevice Luna*PROMEmuDeivce ! 15: // | (ROM エミュレーションはここ) ! 16: // +---------+---------------+ ! 17: // v v ! 18: // PROMDevice CGROMDevice など ! 19: // (LUNA* の実ROM共通) (X68k の各種ROM) ! 20: ! 21: #include "prom.h" ! 22: #include "config.h" ! 23: #include "mainapp.h" ! 24: #include "scheduler.h" ! 25: ! 26: // コンストラクタ ! 27: PROMDevice::PROMDevice() ! 28: { ! 29: logname = "prom"; ! 30: devname = "PROM"; ! 31: devaddr = 0x41000000; ! 32: } ! 33: ! 34: // デストラクタ ! 35: PROMDevice::~PROMDevice() ! 36: { ! 37: } ! 38: ! 39: bool ! 40: PROMDevice::Init() ! 41: { ! 42: vmtype_t vmtype = gMainApp.GetVMType(); ! 43: ! 44: switch (vmtype) { ! 45: case VMTYPE_LUNA1: ! 46: return InitLuna(); ! 47: ! 48: case VMTYPE_LUNA88K: ! 49: return InitLuna88k(); ! 50: ! 51: default: ! 52: PANIC("unknown vmtype %d", vmtype); ! 53: } ! 54: } ! 55: ! 56: // LUNA-I の場合 ! 57: bool ! 58: PROMDevice::InitLuna() ! 59: { ! 60: devlen = 128 * 1024; ! 61: mask = devlen - 1; ! 62: ! 63: // ファイル名が存在してる時しかここに来ない ! 64: const ConfigItem& item = gConfig->Find("prom-image"); ! 65: if (LoadROM(item.AsString().c_str(), devlen) == false) { ! 66: return false; ! 67: } ! 68: ! 69: // MAC アドレスは ROM に書き込まれているので、ここで上書き ! 70: if (strcmp((const char *)&mem[0x1ffd8], "ENADDR") != 0) { ! 71: warnx("ENADDR not found; unknown ROM variants?"); ! 72: return false; ! 73: } ! 74: // MAC アドレスは12桁の16進数文字列として書き込まれている。例えば ! 75: // 前半の 00:00:0A 部分は 30 30 30 30 30 41 "00000A" という感じ。 ! 76: const macaddr_t macaddr = gEthernet->GetMacAddr(); ! 77: memcpy(&mem[0x1ffe0], macaddr.to_string().c_str(), 12); ! 78: ! 79: // SCSI デバッグビット ! 80: // XXX ROM を確認してから適用したほうがいい ! 81: bool scsi_debug_bit = gConfig->Find(".prom-scsi-debug").AsInt(); ! 82: mem[0x4100981d - 0x41000000] = (scsi_debug_bit) ? 0x01 : 0; ! 83: ! 84: return true; ! 85: } ! 86: ! 87: // LUNA88K の場合 ! 88: bool ! 89: PROMDevice::InitLuna88k() ! 90: { ! 91: devlen = 256 * 1024; ! 92: mask = devlen - 1; ! 93: ! 94: // ファイル名が存在してる時しかここに来ない ! 95: const ConfigItem& item = gConfig->Find("prom-image"); ! 96: if (LoadROM(item.AsString().c_str(), devlen) == false) { ! 97: return false; ! 98: } ! 99: ! 100: return true; ! 101: } ! 102: ! 103: bool ! 104: PROMDevice::PowerOn() ! 105: { ! 106: // パフォーマンス測定に電源オン時の実時刻を記憶。 ! 107: // Write8() 参照。 ! 108: start_time = ::GetRealTime(); ! 109: return true; ! 110: } ! 111: ! 112: uint64 ! 113: PROMDevice::Read8(uint32 addr) ! 114: { ! 115: // パフォーマンス測定のためのバックドア。 ! 116: // 0x42000004 番地をバイト読み込みを行うと VM 電源オン時から現在までの ! 117: // 実時間をホスト (ログ) に出力する。NetBSD のマルチユーザブートが ! 118: // あらかた終わってログインプロンプトが出る少し前に実行される ! 119: // /etc/rc.local に ! 120: // dd if=/dev/mem skip=1107296260 bs=1 count=1 ! 121: // と書いておくことでここまでにかかる時間を表示できる。ただしこの値は ! 122: // ホスト性能に依存するため、同一環境下での相対的な比較のみが可能。 ! 123: // 実機ではこの動作では PROM のミラーが読めるだけなので副作用はないはず。 ! 124: // PROM は仕様では 0x4100_0000 から 128KB なので、ここでは通常アクセス ! 125: // するはずのない 0x4200_0004 からの1バイトの読み込みをバックドアに使う。 ! 126: // 0x4100_0000..0x41ff_ffff への書き込みは 0番地付近を ROM から RAM に ! 127: // 切り替えるらしいが実際に PROM がアクセスするのは 0x4100_0000.[BL] ! 128: // のみなので、ここではそれを避けて 0x4200_0004.B を使う。 ! 129: // 書き込みをバックドアにしたかったが dd で書き込めなさそうだったので ! 130: // 読み込みを使う。ちゃんと調べてない。 ! 131: if (addr == 0x42000004) { ! 132: uint64 end, result; ! 133: uint64 vt; ! 134: ! 135: // 電源オン時からここまでの時間を表示するだけでリセット等はしない。 ! 136: end = ::GetRealTime(); ! 137: vt = gScheduler->GetVirtTime(); ! 138: result = end - start_time; ! 139: putlog(0, "電源オンから %d.%03d 秒経過 %3.3f%%", ! 140: (int)(result / (1000 * 1000 * 1000)), ! 141: (int)((result / (1000 * 1000)) % 1000), ! 142: (double)vt / result * 100); ! 143: } ! 144: ! 145: // それ以外は通常動作 ! 146: return inherited::Read8(addr); ! 147: } ! 148: ! 149: uint64 ! 150: PROMDevice::Write8(uint32 addr, uint32 data) ! 151: { ! 152: // LUNA では PROM への書き込みで 0番地付近を RAM に切り替えている。 ! 153: // nono では 0番地付近を ROM に見せること自体をしていないので、 ! 154: // ここでは何もしなくてよく、単に無視する。 ! 155: // LUNA-I だと最初に $41000000.B への書き込みがあるが、それ以降も ! 156: // $41000000.L への書き込みがあるようなので Write32() でも対処している。 ! 157: ! 158: if (addr == 0x41000000) { ! 159: return 0; ! 160: } ! 161: return inherited::Write8(addr, data); ! 162: } ! 163: ! 164: uint64 ! 165: PROMDevice::Write32(uint32 addr, uint32 data) ! 166: { ! 167: // PROM への書き込みで 0番地付近を RAM に切り替えている。 ! 168: // すぐ上の Write8() のコメントも参照。 ! 169: // LUNA88K では $4100000c.L への書き込みが最初にある。 ! 170: // LUNA-I でも $41000000.L への書き込みがあるので、ここでは両方無視する。 ! 171: if (addr < 0x41000010) { ! 172: return 0; ! 173: } ! 174: return inherited::Write32(addr, data); ! 175: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.