--- nono/vm/fuserom.cpp 2026/04/29 17:04:32 1.1.1.1 +++ nono/vm/fuserom.cpp 2026/04/29 17:05:28 1.1.1.10 @@ -1,35 +1,124 @@ // // nono -// Copyright (C) 2020 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // +// +// FuseROM (82S129) +// + +// FuseROM は 128 バイト分のデータを保持できる 4bit ROM みたいなものっぽい。 +// 読み出しは1バイトが上位下位ニブルに分割して読める。そして LUNA-88K バス +// なのでそれが 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<> 経由して) 返すことにする。 +// どうせ大したアクセス量でもないので、細かいことは気にしない。 +// +// デバイスに繋がっている4ビット以外の 28ビットのところは実際には +// $f'ffffff ではなく $4'00c001 であることが多いが時々数ビット異なる。 +// その時のアクセスのパターンから決まる直近の残像のようなものに見える。 +// この辺をどこまで再現するかは疑問。 + #include "fuserom.h" +#include "ethernet.h" +#include "mainapp.h" +// コンストラクタ FuseROMDevice::FuseROMDevice() - : inherited() + : inherited(OBJ_FUSEROM) { - logname = "fuserom"; - - mem = new uint8[sizeof(src) * 8]; - mask = (sizeof(src) * 8) - 1; } +// デストラクタ FuseROMDevice::~FuseROMDevice() { - delete[] mem; } +// 初期化 bool FuseROMDevice::Init() { - // バイトデータ - memcpy(src, "MNAME=LUNA88K", 13 + 1); + if (inherited::Init() == false) { + return false; + } + + uint8 checksum = 0; + + // XXX 初期値は未調査 - // 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); + // src に元データを用意する。 + if (gMainApp.IsLUNA88K()) { + // LUNA-88K なら先頭が MAC アドレス + macaddr_t macaddr; + if (EthernetDevice::GetConfigMacAddr(0, &macaddr, false) == false) { + // エラーメッセージは表示済み + return false; + } + putmsg(1, "macaddr=%s", macaddr.ToString(':').c_str()); + strlcpy((char *)&src[0], "ENADDR=", src.size()); + strlcpy((char *)&src[7], macaddr.ToString().c_str(), src.size() - 7); + } else { + // LUNA-88K2 なら先頭が機種名 (MAC アドレスは NVRAM にある) のようだ。 } + + // 最終バイトはチェックバイト (Mach の kernel/luna88k/autoconf.c より) + for (int i = 0; i < src.size() - 1; i++) { + checksum ^= src[i]; + } + src[src.size() - 1] = checksum; + return true; } + +busdata +FuseROMDevice::ReadPort(uint32 offset) +{ + busdata data = GetByte(offset); + data |= BusData::Size1; + return data; +} + +busdata +FuseROMDevice::WritePort(uint32 offset, uint32 data) +{ + return BusData::Size1; +} + +// ReadPort() からも呼ばれる +busdata +FuseROMDevice::PeekPort(uint32 offset) +{ + return GetByte(offset); +} + +bool +FuseROMDevice::PokePort(uint32 offset, uint32 data) +{ + return false; +} + +// offset の位置の値を返す +uint8 +FuseROMDevice::GetByte(uint32 offset) const +{ + uint8 data; + if ((offset & 1) == 0) { + // 上位ニブル + data = src[offset / 2]; + } else { + // 下位ニブル + data = (src[offset / 2] & 0x0f) << 4; + } + return data | 0x0f; +}