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