|
|
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 root 8: // PROM (LUNA-I, LUNA88K 共通)
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: // | |
24: // | +-- Luna1PROMEmuDevice (LUNA1 の PROM エミュレーション)
25: // | +-- Luna88kPROMEmuDevice (LUNA88K の PROM エミュレーション)
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.10 root 39: // グローバル参照用
40: PROM0Device *gPROM0;
1.1.1.11! root 41: PROMDevice *gPROM;
1.1.1.8 root 42:
43: //
44: // PROM0
45: //
46: // PROM0 は PROM のブートページ担当。
47: // これ自身はメモリ領域を持たず PROM へのプロキシとして動作する。
48: //
49: // リセット後最初の ROM 領域への書き込みアクセスでブートページを RAM に
50: // 切り替える。
51: // LUNA のブートページのアドレス範囲は不明なので、とりあえず devtable の
52: // 1区画である 16MB ($0000'0000..$00ff'ffff) とする。実害はない。
53:
54: // コンストラクタ
55: PROM0Device::PROM0Device()
1.1.1.10 root 56: : inherited("PROM(BOOT)")
1.1.1.8 root 57: {
58: ClearAlias();
1.1.1.10 root 59: AddAlias("PROMBOOT");
1.1.1.8 root 60: }
61:
62: // デストラクタ
63: PROM0Device::~PROM0Device()
64: {
1.1.1.10 root 65: gPROM0 = NULL;
1.1.1.8 root 66: }
67:
68: bool
69: PROM0Device::Init()
70: {
1.1.1.10 root 71: prom = gPROM;
1.1.1.8 root 72: return true;
73: }
74:
1.1.1.10 root 75: // リセット
1.1.1.8 root 76: void
1.1.1.10 root 77: PROM0Device::ResetHard(bool poweron)
1.1.1.8 root 78: {
79: gVM->SwitchBootPageToROM(this);
80: }
81:
82: // アドレスデコーダ
83: /*static*/ inline uint32
84: PROM0Device::Decoder(uint32 addr)
85: {
86: // ここはブートページか ROM かの比較だけで十分 (それ以外はここに来ない)
87: if (addr < 0x0100'0000) {
88: addr += 0x4100'0000;
89: }
90: return addr;
91: }
92:
93: uint64
94: PROM0Device::Read8(uint32 addr)
95: {
96: addr = Decoder(addr);
97: return prom->Read8(addr);
98: }
99:
100: uint64
101: PROM0Device::Read16(uint32 addr)
102: {
103: addr = Decoder(addr);
104: return prom->Read16(addr);
105: }
106:
107: uint64
108: PROM0Device::Read32(uint32 addr)
109: {
110: addr = Decoder(addr);
111: return prom->Read32(addr);
112: }
113:
114: // LUNA では PROM へのライトアクセスでブートページを RAM に切り替えている。
115: // - LUNA-I では最初に $41000000.B への書き込みがあるが、
116: // それ以降も $41000000.L への書き込みが(複数回)あるようだ。
117: // - LUNA88K では $4100000c.L への書き込みがある。
118: //
119: // よってアドレスを定めず PROM 全域への書き込みで最初の1回だけ発動する
120: // ようにしておく。サイズも今の所ワード(16bit)アクセスは確認してないけど
121: // 統一的に対処しておく。
122: uint64
123: PROM0Device::Write()
124: {
125: gVM->SwitchBootPageToRAM(this);
126:
127: // バスエラーは起きない
128: return 0;
129: }
130:
131: uint64
132: PROM0Device::Write8(uint32 addr, uint32 data)
133: {
134: return Write();
135: }
136:
137: uint64
138: PROM0Device::Write16(uint32 addr, uint32 data)
139: {
140: return Write();
141: }
142:
143: uint64
144: PROM0Device::Write32(uint32 addr, uint32 data)
145: {
146: return Write();
147: }
148:
149: uint64
150: PROM0Device::Peek8(uint32 addr)
151: {
152: addr = Decoder(addr);
153: return prom->Peek8(addr);
154: }
155:
156:
157: //
158: // PROM
159: //
160:
1.1 root 161: // コンストラクタ
162: PROMDevice::PROMDevice()
1.1.1.7 root 163: : inherited("PROM")
1.1 root 164: {
165: devaddr = 0x41000000;
1.1.1.8 root 166:
167: // LUNA では ROM への書き込みは何も起きない
168: write_op = 0;
1.1 root 169: }
170:
171: // デストラクタ
172: PROMDevice::~PROMDevice()
173: {
1.1.1.10 root 174: gPROM = NULL;
1.1 root 175: }
176:
177: bool
178: PROMDevice::Init()
179: {
1.1.1.11! root 180: VMType vmtype = gMainApp.GetVMType();
1.1 root 181:
182: switch (vmtype) {
1.1.1.11! root 183: case VMType::LUNA1:
1.1.1.6 root 184: return InitLuna1();
1.1 root 185:
1.1.1.11! root 186: case VMType::LUNA88K:
1.1 root 187: return InitLuna88k();
188:
189: default:
1.1.1.11! root 190: PANIC("unknown vmtype %d", (int)vmtype);
1.1 root 191: }
192: }
193:
194: // LUNA-I の場合
195: bool
1.1.1.6 root 196: PROMDevice::InitLuna1()
1.1 root 197: {
198: devlen = 128 * 1024;
199: mask = devlen - 1;
200:
201: // ファイル名が存在してる時しかここに来ない
202: const ConfigItem& item = gConfig->Find("prom-image");
203: if (LoadROM(item.AsString().c_str(), devlen) == false) {
204: return false;
205: }
206:
1.1.1.8 root 207: // XXX アクセスウェイトは未調査。とりあえず RAM と同程度にしておく
208: wait = 1;
209:
1.1.1.2 root 210: // ROM バージョンを確認。確認されてるのは
211: // V4.02 (Wed Oct 12 17:07:11 1988)
212: // V4.22 (Thu Jul 27 11:45:42 1989)
213: // V4.25
214: //
215: // とりあえず V4.22 は +$00d390 からにタイムスタンプ文字列があるので
216: // それで判別してみる。
217: //00d390 54 68 75 20 4a 75 6c 20 32 37 20 31 31 3a 34 35 |Thu Jul 27 11:45|
218: //00d3a0 3a 34 32 20 31 39 38 39 00 00 00 00 4e 56 fd f8 |:42 1989....NV..|
219:
220: if (strcmp((const char *)&mem[0xd390], "Thu Jul 27 11:45:42 1989") == 0) {
221: // V4.22
1.1.1.10 root 222: putmsg(1, "V4.22 detected");
1.1.1.2 root 223:
224: // MAC アドレスは ROM に書き込まれているので、ここで上書き
225: if (strcmp((const char *)&mem[0x1ffd8], "ENADDR") != 0) {
226: warnx("ENADDR not found; unknown ROM V4.22 variants?");
227: return false;
228: }
229:
230: // MAC アドレスは12桁の16進数文字列として書き込まれている。例えば
231: // 前半の 00:00:0A 部分は 30 30 30 30 30 41 "00000A" という感じ。
232: const macaddr_t macaddr = gEthernet->GetMacAddr();
1.1.1.11! root 233: memcpy(&imagebuf[0x1ffe0], macaddr.ToString().c_str(), 12);
1.1.1.2 root 234:
235: // SCSI デバッグビット
236: bool scsi_debug_bit = gConfig->Find(".prom-scsi-debug").AsInt();
1.1.1.11! root 237: imagebuf[0x4100981d - 0x41000000] = (scsi_debug_bit) ? 0x01 : 0;
1.1.1.2 root 238: } else {
239: // 他の ROM は何も分からないので何もしない。
1.1.1.10 root 240: putmsg(0, "Unknown PROM Version");
1.1 root 241: }
242:
243: return true;
244: }
245:
246: // LUNA88K の場合
247: bool
248: PROMDevice::InitLuna88k()
249: {
250: devlen = 256 * 1024;
251: mask = devlen - 1;
252:
253: // ファイル名が存在してる時しかここに来ない
254: const ConfigItem& item = gConfig->Find("prom-image");
255: if (LoadROM(item.AsString().c_str(), devlen) == false) {
256: return false;
257: }
258:
1.1.1.8 root 259: // XXX アクセスウェイトは未調査。とりあえず RAM と同程度にしておく
260: wait = 3;
261:
1.1 root 262: return true;
263: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.