|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.