|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
1.1.1.6 root 7: //
1.1 root 8: // LUNA-I の ROM エミュレーション
1.1.1.4 root 9: //
1.1.1.6 root 10:
1.1.1.4 root 11: // IODevice
1.1.1.10 root 12: // |
13: // +- ROMDevice (LoadROM()、ウェイト、マスク等を持つ)
14: // | +- PROMDevice (LUNA* の PROM)
15: // | +- IPLROM1Device (X680x0 の IPLROM 後半)
16: // | +- IPLROM2Device (X680x0 の IPLROM 前半)
17: // | +- CGROMDevice (X680x0 の CGROM)
18: // | |
19: // | +- ROMEmuDevice
20: // | |
21: // | +- LunaPROMEmuDevice (LUNA PROM エミュレーションの共通部分)
22: // | | |
23: // | | | +--------------------+
24: // | | +-| Luna1PROMEmuDevice | (LUNA-I の PROM エミュレーション)
25: // | | | +--------------------+
26: // | | |
27: // | | +- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション)
28: // | +- NewsROMEmuDevice (NEWS の ROM エミュレーション)
29: // | +- ROM30EmuDevice (X68030 の ROM30 エミュレーション)
30: // | +- Virt68kROMEmuDevice (virt-m68k の IPLROM 相当の何か)
31: // |
32: // +- PROM0Device (LUNA* のブートページ切り替え用プロキシ)
33: // +- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ)
1.1 root 34:
1.1.1.6 root 35: // ROM マップ
36: //
37: // 先頭の "*" は仕様または実機と揃える必要があるアドレスを示す。
38: // そうでないものはこっちが適当に割り振っているアドレスで、変更可。
39: //
40: // *4100'0000.L リセットベクタ(SP)
41: // *4100'0004.L リセットベクタ(PC)
42: // *4100'000c.L メモリサイズ格納先アドレス (実 ROM は RAM をさしている)
43: // 4100'0010.L メモリサイズ
44: // *4100'00b8.L プレーンマスク格納先アドレス (実 ROM は RAM をさしている)
45: // 4100'00bc.L プレーンマスク
1.1.1.13 root 46: // *4100'00d4.L 'x' コマンドの引数バッファアドレス
1.1.1.6 root 47: //
48: // 4100'0400 リセットハンドラ
1.1.1.13 root 49: // 4100'0500 Lv5 (Sysclk) 割り込みハンドラ
1.1.1.6 root 50: // 4100'0600 Lv6 (SIO) 割り込みハンドラ
51: // 4100'0700 Lv7 (NMI) 割り込みハンドラ
52: // 4100'0800 デフォルトハンドラ
1.1.1.13 root 53: // 4100'0900 サブルーチン
54: // 4100'1000.B[64] 'x' コマンドの引数バッファ(ダミー)
1.1.1.6 root 55: //
56: // *4101'ffd8〜 "ENADDR",0,0
57: // *4101'ffe0〜 MACアドレス(文字列形式、英大文字、区切りなし)
58: // 0123456789ab c
59: // "0011223344AA",0
60:
1.1 root 61: #include "romemu_luna1.h"
1.1.1.7 root 62: #include "bt45x.h"
1.1 root 63: #include "ethernet.h"
1.1.1.10 root 64: #include "iodevstream.h"
1.1 root 65: #include "mainapp.h"
1.1.1.7 root 66: #include "mainram.h"
1.1 root 67: #include "memorystream.h"
68: #include "mk48t02.h"
69: #include "mpu680x0.h"
1.1.1.9 root 70: #include "sysclk.h"
1.1 root 71:
72: // コンストラクタ
73: Luna1PROMEmuDevice::Luna1PROMEmuDevice()
74: {
1.1.1.9 root 75: machine_name = "LUNA-I";
1.1 root 76: }
77:
78: // デストラクタ
79: Luna1PROMEmuDevice::~Luna1PROMEmuDevice()
80: {
81: }
82:
1.1.1.7 root 83: // 初期化
1.1 root 84: bool
85: Luna1PROMEmuDevice::Init()
86: {
87: if (inherited::Init() == false) {
88: return false;
89: }
90:
1.1.1.12 root 91: // LUNA-I の ROM の特定アドレスを読み出す人がいるので、
92: // サイズは実 ROM と同じにしておく必要がある。
93: if (AllocROM(128 * 1024, 0) == false) {
94: return false;
95: }
96:
1.1.1.9 root 97: SysClkDevice *sysclk = GetSysClkDevice();
98:
1.1.1.10 root 99: MemoryStreamBE roms(imagebuf.get());
100: roms.Write4(0x00002000); // +00: リセットベクタ SP
101: roms.Write4(0x41000400); // +04: リセットベクタ PC
102: roms.Write4(0); // +08
103: roms.Write4(0x41000010); // +0c: メモリサイズ格納先
1.1.1.6 root 104: // +10: 値は ROM_Init() でセット
1.1.1.10 root 105: roms.SetOffset(0xb8);
106: roms.Write4(0x410000bc); // +b8: プレーンマスク格納先
1.1.1.6 root 107: // +bc: 値は ROM_Init() でセット
1.1.1.13 root 108: roms.SetOffset(0xd4);
109: roms.Write4(0x41001000); // +d4: 'x' コマンドの引数(実際はRAM)
1.1 root 110:
111: // リセット時に実行する命令
1.1.1.10 root 112: roms.SetOffset(0x400);
113: roms.Write2(0x13c0); // move.b d0,#0x41000000 ; RAMに切り替え
114: roms.Write4(0x41000000);
115: roms.Write2(0x2039); // move.l (ROMIO_INIT),d0
116: roms.Write4(ROMIO_INIT);
117: roms.Write2(0x2039); // move.l (ROMIO_LOAD),d0
118: roms.Write4(ROMIO_LOAD);
119: roms.Write2(0x72ff); // moveq.l #0xffffffff,d1
120: roms.Write2(0x6004); // bra _entry
1.1 root 121: //_prompt:
1.1.1.10 root 122: uint32 _prompt = roms.GetOffset();
123: roms.Write4(0x4e722500); // stop #0x2500 ; キー入力を待つ
1.1.1.9 root 124: //_entry:
1.1.1.10 root 125: roms.Write2(0x2039); // move.l (ROMIO_ENTRY),d0
126: roms.Write4(ROMIO_ENTRY); // ; エントリポイント取得
127: roms.Write2(0xb081); // cmp.l d1,d0
128: roms.Write2(0x67f2); // beq _prompt ; 起動先なければループ
1.1 root 129: //_go:
1.1.1.10 root 130: roms.Write2(0x2040); // move.l d0,a0 ; ジャンプ先を a0 にセット
131: roms.Write2(0x2039); // move.l (ROMIO_CLOSE),d0
132: roms.Write4(ROMIO_CLOSE); // ; 後始末
133: roms.Write2(0x4ed0); // jmp (a0) ; ジャンプ
1.1 root 134:
1.1.1.9 root 135: // Lv5 (Sysclk) 割り込みハンドラ。
1.1.1.10 root 136: roms.SetOffset(0x500);
137: roms.Write2(0x13c0); // move.b d0,#0x63000000 ; ACK
138: roms.Write4(0x63000000);
139: roms.Write2(0x52b9); // addq.l #1,(ROMIO_CLKCNT)
140: roms.Write4(ROMIO_CLKCNT);
141: roms.Write2(0x4e73); // rte
1.1.1.9 root 142:
1.1.1.14! root 143: // Lv6 (SIO) 割り込みハンドラ。
! 144: // この中でコマンドなどを処理する。
1.1.1.10 root 145: roms.SetOffset(0x600);
1.1.1.14! root 146: roms.Write2(0x4ab9); // tst.l (ROMIO_SIOINTR)
! 147: roms.Write4(ROMIO_SIOINTR); // ; キー入力処理
1.1.1.10 root 148: roms.Write2(0x4e73); // rte
1.1 root 149:
1.1.1.6 root 150: // NMI のハンドラ
1.1.1.10 root 151: roms.SetOffset(0x700);
152: roms.Write4(0x46fc2700); // move.w #0x2700,sr
153: roms.Write2(0x91c8); // suba.l a0,a0
154: roms.Write4(0x4e7b8801); // movec a0,vbr
155: roms.Write2(0x2e50); // movea.l (a0),sp
156: roms.Write2(0x4ef9); // jmp _prompt
157: roms.Write4(0x41000000 + _prompt);
1.1.1.6 root 158:
159: // デフォルトのハンドラ
1.1.1.10 root 160: roms.SetOffset(0x800);
161: roms.Write2(0x4e73); // rte
1.1.1.6 root 162:
1.1.1.9 root 163: // サブルーチン
1.1.1.10 root 164: roms.SetOffset(0x900); //_ap1:
165: roms.Write2(0x2039); // move.l (ROMIO_AP1),d0
166: roms.Write4(ROMIO_AP1); //
167: uint freq = sysclk->GetFreq();
168: roms.Write2(0x7200 + freq * 3);
169: // moveq.l #(CLK_FREQ*3),d1
1.1.1.9 root 170: //@@:
1.1.1.10 root 171: roms.Write4(0x4e722400); // stop #0x2400 ; クロック入力を待つ
172: roms.Write2(0x2039); // move.l (ROMIO_CLKCNT),d0
173: roms.Write4(ROMIO_CLKCNT);
174: roms.Write2(0xb001); // cmp.b d1,d0
175: roms.Write2(0x66f2); // bne @b
176: roms.Write2(0x2039); // move.l (ROMIO_AP2),d0
177: roms.Write4(ROMIO_AP2); //
178: roms.Write2(0x4e75); // rts
1.1.1.9 root 179:
1.1 root 180: // MAC アドレス
1.1.1.11 root 181: MacAddr macaddr;
1.1.1.8 root 182: if (EthernetDevice::GetConfigMacAddr(0, &macaddr, false) == false) {
1.1.1.7 root 183: // エラーメッセージは表示済み
184: return false;
185: }
186: putmsg(1, "macaddr=%s", macaddr.ToString(':').c_str());
1.1.1.4 root 187: strcpy((char *)&imagebuf[0x1ffd8], "ENADDR");
1.1.1.6 root 188: memcpy(&imagebuf[0x1ffe0], macaddr.ToString().c_str(), 12);
1.1 root 189:
190: return true;
191: }
192:
1.1.1.9 root 193: // ROM 起動時の初期化 (機種依存部分) を行う。
194: void
195: Luna1PROMEmuDevice::ROM_InitMD()
1.1 root 196: {
1.1.1.10 root 197: IODeviceStream rams(mainram);
198: MemoryStreamBE roms(imagebuf.get());
1.1.1.7 root 199:
1.1.1.6 root 200: // +0010: メモリサイズ
1.1.1.10 root 201: roms.SetOffset(0x10);
1.1.1.12 root 202: roms.Write4((uint32)mainram->GetSize());
1.1 root 203:
1.1.1.7 root 204: // プレーン数(1,4,8)をプレーンマスク(0x01, 0x0f, 0xff)に
205: int nplane = bt45x->GetPlaneCount();
1.1.1.13 root 206: int planemask = (1U << nplane) - 1;
1.1.1.6 root 207: // プレーンマスク。実際は RAM に書き込まれるがとりあえず
1.1.1.10 root 208: roms.SetOffset(0xbc);
209: roms.Write4(planemask);
1.1 root 210:
1.1.1.6 root 211: // RAM にベクタを書き込む
1.1.1.10 root 212: roms.SetOffset(0);
1.1.1.12 root 213: rams.SetAddr(0);
1.1.1.10 root 214: rams.Write4(roms.Read4()); // ROM のリセットベクタをコピー
215: rams.Write4(roms.Read4());
216: for (uint i = 2; i < 256; i++) { // デフォルトベクタで埋める
217: rams.Write4(0x41000800);
218: }
219: rams.Write4(0x74, 0x41000500); // +74: Lv5 割り込み
220: rams.Write4(0x78, 0x41000600); // +78: Lv6 割り込み
221: rams.Write4(0x7c, 0x41000700); // +7c: Lv7 割り込み = RESET
1.1.1.6 root 222:
1.1 root 223: prompt_idx = 0;
224: prompt = default_prompt;
225:
1.1.1.10 root 226: uint32 ap = (nvram->PeekPort(0x7fd) << 8) | nvram->PeekPort(0x7fe);
1.1.1.9 root 227: if (__predict_false(0||(ap & 0x3f1f) == 0x0104)) {
228: auto mpu680x0 = GetMPU680x0Device(mpu);
229: m68kreg& reg = mpu680x0->reg;
230: reg.A[7] -= 4;
1.1.1.10 root 231: rams.Write4(reg.A[7], reg.pc);
1.1.1.9 root 232: reg.pc = 0x41000900;
1.1 root 233: }
234: }
235:
236: // ROM 処理のクローズ。
237: // 次段プログラムにジャンプするための処理も含む。
238: void
239: Luna1PROMEmuDevice::ROM_Close()
240: {
241: inherited::ROM_Close();
242:
243: // NetBSD のブートローダがカーネルを読み込む時にはいくつかレジスタ
244: // 渡しのパラメータがあるので、ここで用意する。本当はターゲットが
245: // NetBSD カーネルの時に限定すべきのような気もするけど、とりあえず。
246: // ROM がブートローダを読み込む時にはそのような取り決め事は一切ない
247: // ので、ブートローダを読む時にも同じ値が入ってしまうが気にしない
248: // ことにする。
249: // 必要なパラメータは
250: // %d6 に bootdev、NetBSD/luna68k の場合は
251: // bootdev = $MACUPP00
252: // ||||++-- パーティション番号
253: // |||+---- SCSI ID (XXX ただしここでは 6 決め打ち)
254: // ||+----- unit (spc0 なら 0 のやつのはず)
255: // |+------ アダプタ (spc = 0、lance = 1)
256: // +------- magic ($a)
257: //
258: // %d7 に howto (0 でよい)
259: // (と %a0 にジャンプ先を入れるがこれは Init() が書き出した ROM
260: // アセンブラコード側で行っている)
1.1.1.9 root 261: m68kreg& reg = GetMPU680x0Device(mpu)->reg;
1.1.1.7 root 262: reg.D[6] = 0xa0060000;
263: reg.D[7] = 0;
1.1.1.9 root 264: }
1.1.1.6 root 265:
1.1.1.9 root 266: // ファイルをロードする。
267: // -X が指定されていればそのホストファイル。
268: // そうでなければゲストファイル。この場合引数 fname があれば
269: // NVRAM で指定されたデバイスから読み込む際のファイル名とする。
270: // 空なら NVRAM で指定されたファイル名。
271: // ロードできればエントリポイントを返す。
272: // ロードできなければ errmsg にメッセージをセットし -1 を返す。
273: uint32
274: Luna1PROMEmuDevice::LoadFile(const std::string& fname)
275: {
276: uint32 entry = -1;
277:
278: if (gMainApp.exec_file) {
279: // -X が指定されてたらホストプログラムを読み込む。
280: entry = LoadHostFile();
281: } else {
282: // NVRAM で指定されるゲストプログラムを読み込む。
283: std::string ctlr = nvram->PeekString(0x0030);
284: if (ctlr == "dk") { // harddisk
285: bootinfo_t bootinfo;
286: GetNVRAM(bootinfo);
287: // 引数で指定されたらファイル名だけ上書き
288: if (fname.empty() == false) {
289: bootinfo.dkfile = fname;
290: }
291: entry = LoadGuestFile(bootinfo);
292:
293: } else if (ctlr == "et" || // netboot
294: ctlr == "sd" || // cassette tape
295: ctlr == "fl" ) // floppy
296: {
297: errmsg = ctlr + " boot not supported.";
298: } else {
299: // 起きないはず
300: errmsg = ctlr + ": Invalid boot controller name.";
301: }
302: }
303:
304: return entry;
1.1 root 305: }
306:
307: // 入力コマンド処理 (入力行が揃ったところで呼ばれる)。
308: void
309: Luna1PROMEmuDevice::Command()
310: {
311: std::vector<char> buf(inputbuf.length() + 1);
312: std::vector<std::string> arg;
313:
314: // 1ワードごとに分解
1.1.1.10 root 315: strlcpy(buf.data(), inputbuf.c_str(), buf.size());
1.1 root 316: char *p = &buf[0];
1.1.1.2 root 317: for (char *ap; (ap = strsep(&p, " ")) != NULL; ) {
318: if (*ap != '\0') {
319: arg.push_back(std::string(ap));
1.1 root 320: }
321: }
322: if (loglevel >= 1) {
323: for (int i = 0; i < arg.size(); i++) {
1.1.1.10 root 324: putmsgn("arg[%u]=|%s|", i, arg[i].c_str());
1.1 root 325: }
326: }
327:
328: // "k" コマンド中ならここで先に処理する
329: if (prompt_idx != 0) {
330: CommandK(arg);
331: return;
332: }
333:
334: // 空行
335: if (arg.size() == 0) {
336: return;
337: }
338:
339: // 1ワード目がコマンド
340: if (arg[0] == "h") {
341: // ヘルプメッセージ
1.1.1.6 root 342: Print("Commands\n");
343: Print(
1.1 root 344: " g [<filename>] : load program\n"
345: " h : show this message\n"
346: " k : show/set boot constants\n"
347: " x : execute loaded program\n"
348: );
349: return;
350: }
351: if (arg[0] == "g") {
352: CommandG(arg);
353: return;
354: }
355: if (arg[0] == "k") {
356: CommandK(arg);
357: return;
358: }
359: if (arg[0] == "x") {
360: CommandX();
361: return;
362: }
363:
1.1.1.6 root 364: Print("** Unknown command: %s\n", arg[0].c_str());
1.1 root 365: }
366:
367: // "g" コマンド
1.1.1.9 root 368: // g なら NVRAM の情報 (もしくは -X オプション) に従ってプログラムをロード。
1.1 root 369: // g <fname> なら NVRAM の fname だけ指定の名前を使ってロード。NVRAM には
370: // 書き込まない。
371: void
372: Luna1PROMEmuDevice::CommandG(const std::vector<std::string>& arg)
373: {
1.1.1.9 root 374: std::string fname {};
1.1 root 375:
1.1.1.9 root 376: switch (arg.size()) {
377: case 1:
378: break;
379: case 2:
380: fname = arg[1];
381: break;
382: default:
383: Print("** Invalid argument.\n");
384: return;
1.1 root 385: }
386:
1.1.1.9 root 387: entrypoint = LoadFile(fname);
388: if (entrypoint == -1) {
389: Print("** %s\n", errmsg.c_str());
390: } else {
391: Print("%s. Entry point = $%08x\n",
392: (gMainApp.exec_file ? "Host program loaded" : "Loaded"),
393: entrypoint);
1.1 root 394: }
395: }
396:
397: // k コマンドのパラメータ表
398: struct kinfo {
399: uint32 offset; // NVRAM 上のオフセット
400: const char * const name; // 表示名
401: int next; // 次インデックス
402: };
403: static const struct kinfo kinfo[] = {
404: { 0 }, // 0 は通常プロンプトを指すのでここでは使わない
405: { 0x0030, "controller", 0 }, // [1] BOOT (next は動的判定する)
406: { 0x0090, "drive unit", 3 }, // [2] DKUNIT
407: { 0x00b0, "partition ", 4 }, // [3] DKPART
408: { 0x00d0, "filename ", 0 }, // [4] FLNAME
409: { 0x0050, "hostname ", 6 }, // [5] HOST
410: { 0x0070, "servername", 7 }, // [6] SERVER
411: { 0x0190, "filename ", 8 }, // [7] ETBOOT
412: { 0x01b0, "", 0 }, // [8] ETFILE (ETBOOT と1行で処理する)
413: };
414:
415: // "k" コマンド
416: void
417: Luna1PROMEmuDevice::CommandK(const std::vector<std::string>& arg)
418: {
419: uint32 offset;
420: const char *name;
421: int next;
422:
423: // 入力を処理
424: if (prompt_idx == 0) {
425: // ここは1行目表示前なので前行の入力はない。
426: next = 1;
427: } else {
428: std::string val;
429: bool rv;
430:
431: // 入力があれば更新
432: if (arg.size() != 0) {
433: rv = CommandKInput(arg[0]);
434: } else {
435: // [7] の時に入力があれば CommandKInput() の中で更新されるが、
436: // 入力がなければそこを通らないので、こっちでやらないといけない。
437: // うーん。
438: if (prompt_idx == 7) {
439: prompt_idx = kinfo[prompt_idx].next;
440: }
441: rv = true;
442: }
443:
444: // これ以降は更新後の prompt_idx を使う
445:
446: // 入力エラーがあった時はこの行を再入力するため
447: next = prompt_idx;
448:
449: if (rv == true) {
450: // 入力があっても空でも次インデックスへ。
451: if (prompt_idx == 1) {
452: // BOOT なら現在値によって次のインデックスが変わる
453: // "dk" なら [2]、"et" なら [5]。他は未対応
454: offset = kinfo[prompt_idx].offset;
455: val = nvram->PeekString(offset);
456: if (val == "dk") {
457: next = 2;
458: } else if (val == "et") {
459: next = 5;
460: } else {
461: // 起きることはないはず
1.1.1.6 root 462: Print("** Inconsistent boot parameter: %s\n",
1.1 root 463: val.c_str());
464: }
465: } else {
466: // それ以外はテーブルにかかれている通り
467: next = kinfo[prompt_idx].next;
468: }
469: }
470: }
471:
472: // この行のプロンプト文字列を作成
473: prompt_idx = next;
474: if (prompt_idx == 0) {
475: // 最終行なら元に戻す
476: prompt = default_prompt;
477: } else {
478: // 次のプロンプトに変更
479: name = kinfo[prompt_idx].name;
480: offset = kinfo[prompt_idx].offset;
481: std::string val = nvram->PeekString(offset);
482:
483: // [7] ETBOOT だけ1行で ETBOOT:ETFILE 形式
484: if (prompt_idx == 7) {
485: next = kinfo[prompt_idx].next; // ETFILE
486: offset = kinfo[next].offset;
487: val += ":";
488: val += nvram->PeekString(offset);
489: }
490:
491: prompt = string_format("%s: %s ?", name, val.c_str());
492: }
493: }
494:
495: // k コマンドの入力値を処理する部分。
496: // 成功すれば true を返す。
497: // 失敗すれば false を返す。
498: // 実機 ROM は入力値にエラーがあると黙って再入力を促す。
499: // エラーメッセージくらい表示してもいいかもだがとりあえず真似しておく。
500: bool
501: Luna1PROMEmuDevice::CommandKInput(const std::string& val)
502: {
503: int offset;
504: bool rv = true;
505:
506: offset = kinfo[prompt_idx].offset;
507:
508: switch (prompt_idx) {
509: case 1: // BOOT
510: // 正常な入力値は "dk", "et", "sd", "fl" のみ。
511: if (val != "dk" && val != "et" && val != "sd" && val != "fl") {
512: return false;
513: }
514: rv = nvram->WriteString(offset, val);
515: if (rv == false) {
516: return false;
517: }
518: break;
519:
520: case 7: // ETBOOT
521: {
522: // こいつだけ ETBOOT:ETFILE 形式で2つのパラメータを同時に処理する
523:
524: // ':' で前後に分ける
525: int sep = val.find(':');
526: if (sep == std::string::npos) {
527: return false;
528: }
529: std::string etboot = val.substr(0, sep);
530: std::string etfile = val.substr(sep + 1, val.size() - sep + 1);
531: if (etboot.empty() || etfile.empty()) {
532: return false;
533: }
534:
535: // ETBOOT
536: rv = nvram->WriteString(offset, etboot);
537: if (rv == false) {
538: return false;
539: }
540:
541: // 次へ
542: prompt_idx = kinfo[prompt_idx].next;
543:
544: // ETFILE
545: offset = kinfo[prompt_idx].offset;
546: rv = nvram->WriteString(offset, etfile);
547: if (rv == false) {
548: return false;
549: }
550: break;
551: }
552:
553: default:
554: rv = nvram->WriteString(offset, val);
555: if (rv == false) {
556: return false;
557: }
558: break;
559: }
560:
561: WriteNVRAMCsum();
562: return rv;
563: }
564:
565: // "x" コマンド
566: // 読み込まれていたらフラグを立てるだけ。
567: void
568: Luna1PROMEmuDevice::CommandX()
569: {
1.1.1.9 root 570: if (entrypoint == -1) {
1.1.1.6 root 571: Print("** Program is not loaded.\n");
1.1.1.9 root 572: return;
1.1 root 573: }
1.1.1.9 root 574: execute = true;
1.1 root 575: }
576:
577: // NVRAM を初期化する
578: bool
579: Luna1PROMEmuDevice::InitNVRAM()
580: {
1.1.1.3 root 581: nvram->ClearAll();
582:
1.1 root 583: // 初期値どうしたもんか
584: nvram->WriteString(0x0004, "<nv>");
585: nvram->WriteString(0x0020, "BOOT");
586: nvram->WriteString(0x0030, "dk");
587: nvram->WriteString(0x0040, "HOST");
588: nvram->WriteString(0x0050, "nono"); // 偽札的なアレ
589: nvram->WriteString(0x0060, "SERVER");
590: nvram->WriteString(0x0070, "servername");
591: nvram->WriteString(0x0080, "DKUNIT");
592: nvram->WriteString(0x0090, "0");
593: nvram->WriteString(0x00a0, "DKPART");
594: nvram->WriteString(0x00b0, "c");
595: nvram->WriteString(0x00c0, "DKFILE");
596: nvram->WriteString(0x00d0, "vmunix");
597: nvram->WriteString(0x00e0, "FLUNIT");
598: nvram->WriteString(0x00f0, "2");
599: nvram->WriteString(0x0100, "FLFILE");
600: nvram->WriteString(0x0110, "vmunix");
601: nvram->WriteString(0x0120, "STUNIT");
602: nvram->WriteString(0x0130, "0");
603: nvram->WriteString(0x0140, "STFLNO");
604: nvram->WriteString(0x0150, "1");
605: nvram->WriteString(0x0160, "STFILE");
606: nvram->WriteString(0x0170, "vmunix");
607: nvram->WriteString(0x0180, "ETBOOT");
608: nvram->WriteString(0x0190, "server");
609: nvram->WriteString(0x01a0, "ETFILE");
610: nvram->WriteString(0x01b0, "/vmunix");
611: nvram->WriteString(0x0560, "ENADDR");
612: nvram->WriteString(0x0570, ""); // どうするか
613:
614: // チェックサム再計算
615: WriteNVRAMCsum();
616:
617: return true;
618: }
619:
620: // NVRAM のブート設定を bootinfo に取得する。
621: void
622: Luna1PROMEmuDevice::GetNVRAM(bootinfo_t& bootinfo)
623: {
624: // 起動先情報を NVRAM (mk48t02) に問い合わせる
625: // DKUNIT が装置番号(今はまだ SCSI ID=6 固定)。
626: // DKPART が 'a'..'h' でパーティション。
627: // DKFILE が読み込む次段プログラム (NetBSD では通常 /boot のこと)。
1.1.1.10 root 628: bootinfo.dkunit = nvram->PeekPort(0x0090) - '0';
629: bootinfo.dkpart = nvram->PeekPort(0x00b0) - 'a';
1.1 root 630: bootinfo.dkfile = nvram->PeekString(0x00d0);
1.1.1.10 root 631: putmsg(1, "%s DKUNIT=%u", __func__, bootinfo.dkunit);
1.1 root 632: putmsg(1, "%s DKPART=%c", __func__, bootinfo.dkpart + 'a');
633: putmsg(1, "%s DKFILE=|%s|", __func__, bootinfo.dkfile.c_str());
634: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.