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