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