--- nono/vm/fuserom.cpp 2026/04/29 17:04:32 1.1 +++ nono/vm/fuserom.cpp 2026/04/29 17:05:14 1.1.1.6 @@ -1,35 +1,98 @@ // // nono -// Copyright (C) 2020 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // +// +// FuseROM +// + +// FuseROM は 128 バイト分のデータを保持できる 4bit ROM みたいなものっぽい。 +// 読み出しは1バイトが上位下位ニブルに分割して読める。そして LUNA88K バス +// なのでそれが 1ワード(1ロングワード) 境界ごとに配置される。 +// +// 例えば "01" という2バイトはゲストからは次のような 16バイトとして読める。 +// +// +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f +// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +// | 3f| ff| ff| ff| 0f| ff| ff| ff| 3f| ff| ff| ff| 1f| ff| ff| ff| +// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +// $3 $0 $3 $1 +// +// ここでは src[128] に元データを8ビット(バイト)単位で、つまり上の例の +// "01" のように人間が読める形式で用意しておき、アクセス時に都度ニブルに +// 変換して (さらに BusIO_BFFF<> 経由して) 返すことにする。 +// どうせ大したアクセス量でもないので、細かいことは気にしない。 + #include "fuserom.h" +#include "ethernet.h" +#include "mainapp.h" + +// グローバル参照用 +FuseROMDevice *gFuseROM; +// コンストラクタ FuseROMDevice::FuseROMDevice() - : inherited() + : inherited("FuseROM") { - logname = "fuserom"; - - mem = new uint8[sizeof(src) * 8]; - mask = (sizeof(src) * 8) - 1; } +// デストラクタ FuseROMDevice::~FuseROMDevice() { - delete[] mem; + gFuseROM = NULL; } bool FuseROMDevice::Init() { - // バイトデータ - memcpy(src, "MNAME=LUNA88K", 13 + 1); + uint8 checksum = 0; + + memset(src, 0, sizeof(src)); // XXX 未調査 + + // src に元データを用意する。 + if (gMainApp.GetVMType() == VMType::LUNA88K) { + // LUNA88K なら先頭が MAC アドレス + macaddr_t macaddr = gEthernet->GetMacAddr(); + strcpy((char *)src, "ENADDR="); + strcpy((char *)src + 7, macaddr.ToString().c_str()); + } else { + // LUNA88K2 なら先頭が機種名 (MAC アドレスは NVRAM にある) のようだ。 + } - // 1ロングワードに1ニブルずつ置いてある - uint32 *d = (uint32 *)mem; - for (int i = 0; i < sizeof(src); i++) { - *d++ = htobe32((src[i] << 24) | 0x0fffffff); - *d++ = htobe32((src[i] << 28) | 0x0fffffff); + // 最終バイトはチェックバイト (Mach の kernel/luna88k/autoconf.c より) + for (int i = 0; i < sizeof(src) - 1; i++) { + checksum ^= src[i]; } + src[sizeof(src) - 1] = checksum; + return true; } + +uint64 +FuseROMDevice::Read(uint32 offset) +{ + return Peek(offset); +} + +uint64 +FuseROMDevice::Write(uint32 offset, uint32 data) +{ + return 0; +} + +// Read() からも呼ばれる +uint64 +FuseROMDevice::Peek(uint32 offset) +{ + uint8 data; + if ((offset & 1) == 0) { + // 上位ニブル + data = src[offset / 2]; + } else { + // 下位ニブル + data = (src[offset / 2] & 0x0f) << 4; + } + return data | 0x0f; +}