|
|
nono 0.0.3
//
// nono
// Copyright (C) 2019 [email protected]
//
#include "romimg_luna.h"
#include "config.h"
#include "scheduler.h"
std::unique_ptr<PROMDevice> gPROM;
//
// PROM
//
PROMDevice::PROMDevice()
{
logname = "prom";
devname = "PROM";
devaddr = 0x41000000;
devlen = 128 * 1024;
mask = devlen - 1;
}
PROMDevice::~PROMDevice()
{
}
bool
PROMDevice::Init()
{
if (LoadROM("PROM.DAT", 128 * 1024) == false) {
return false;
}
// SCSI デバッグビット
// XXX ROM を確認してから適用したほうがいい
bool scsi_debug_bit = gConfig->Get(".prom-scsi-debug").AsInt();
mem[0x4100981d - 0x41000000] = (scsi_debug_bit) ? 0x01 : 0;
return true;
}
bool
PROMDevice::PowerOn()
{
// パフォーマンス測定に電源オン時の実時刻を記憶。
// Write8() 参照。
start_time = ::GetRealTime();
return true;
}
// ROM に指定された MAC アドレスを設定する
bool
PROMDevice::SetMacAddr(const macaddr_t& macaddr)
{
std::string buf;
// 念のため確認する?
if (strcmp((const char *)&mem[0x1ffd8], "ENADDR") != 0) {
return false;
}
// MAC アドレスは12桁の16進数文字列として書き込まれている。例えば
// 前半の 00:00:0A 部分は 30 30 30 30 30 41 "00000A" という感じ。
for (const auto& v : macaddr) {
// 英字は大文字
buf += string_format("%02X", v);
}
for (int i = 0; i < buf.length(); i++) {
mem[0x1ffe0 + i] = buf[i];
}
return true;
}
uint64
PROMDevice::Read8(uint32 addr)
{
// パフォーマンス測定のためのバックドア。
// 0x42000004 番地をバイト読み込みを行うと VM 電源オン時から現在までの
// 実時間をホスト (ログ) に出力する。NetBSD のマルチユーザブートが
// あらかた終わってログインプロンプトが出る少し前に実行される
// /etc/rc.local に
// dd if=/dev/mem skip=1107296260 bs=1 count=1
// と書いておくことでここまでにかかる時間を表示できる。ただしこの値は
// ホスト性能に依存するため、同一環境下での相対的な比較のみが可能。
// 実機ではこの動作では PROM のミラーが読めるだけなので副作用はないはず。
// PROM は仕様では 0x4100_0000 から 128KB なので、ここでは通常アクセス
// するはずのない 0x4200_0004 からの1バイトの読み込みをバックドアに使う。
// 0x4100_0000..0x41ff_ffff への書き込みは 0番地付近を ROM から RAM に
// 切り替えるらしいが実際に PROM がアクセスするのは 0x4100_0000.[BL]
// のみなので、ここではそれを避けて 0x4200_0004.B を使う。
// 書き込みをバックドアにしたかったが dd で書き込めなさそうだったので
// 読み込みを使う。ちゃんと調べてない。
if (addr == 0x42000004) {
uint64 end, result;
uint64 vt;
// 電源オン時からここまでの時間を表示するだけでリセット等はしない。
end = ::GetRealTime();
vt = gScheduler->GetVirtTime();
result = end - start_time;
putlog(0, "電源オンから %d.%03d 秒経過 %3.3f%%",
(int)(result / (1000 * 1000 * 1000)),
(int)((result / (1000 * 1000)) % 1000),
(double)vt / result * 100);
}
// それ以外は通常動作
return inherited::Read8(addr);
}
uint64
PROMDevice::Write8(uint32 addr, uint32 data)
{
// LUNA では PROM への書き込みで 0番地付近を RAM に切り替えている。
// ここではその動作は必要ないので、単に無視する。
// XXX アドレスチェック一応しておく?
if (addr == 0x41000000) {
return 0;
}
return inherited::Write8(addr, data);
}
uint64
PROMDevice::Write32(uint32 addr, uint32 data)
{
// LUNA では PROM への書き込みで 0番地付近を RAM に切り替えている。
// ここではその動作は必要ないので、単に無視する。
// XXX アドレスチェック一応しておく?
if (addr == 0x41000000) {
return 0;
}
return inherited::Write32(addr, data);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.