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