--- nono/vm/goldfish_tty.cpp 2026/04/29 17:05:29 1.1.1.2 +++ nono/vm/goldfish_tty.cpp 2026/04/29 17:06:00 1.1.1.6 @@ -40,8 +40,8 @@ #include "goldfish_pic.h" #include "hostcom.h" #include "mainbus.h" -#include "mpu.h" #include "scheduler.h" +#include "syncer.h" // コンストラクタ GFTTYDevice::GFTTYDevice() @@ -53,7 +53,7 @@ GFTTYDevice::GFTTYDevice() GFTTYDevice::~GFTTYDevice() { if ((bool)hostcom) { - hostcom->SetRxCallback(NULL); + hostcom->ResetRxCallback(); } } @@ -61,11 +61,14 @@ bool GFTTYDevice::Create() { // 対応するホストドライバを作成 - hostcom.reset(new HostCOMDevice(this, "HostCOM")); + try { + hostcom.reset(new HostCOMDevice(this, 0, "GoldfishTTY")); + } catch (...) { } if ((bool)hostcom == false) { + warnx("Failed to initialize HostCOMDevice at %s", __method__); return false; } - hostcom->SetRxCallback(ToDeviceCallback(&GFTTYDevice::HostRxCallback)); + hostcom->SetRxCallback(ToDeviceCallback(&GFTTYDevice::HostRxCallback), 0); return true; } @@ -75,24 +78,21 @@ GFTTYDevice::SetLogLevel(int loglevel_) { inherited::SetLogLevel(loglevel_); - assert((bool)hostcom); - hostcom->SetLogLevel(loglevel_); + if ((bool)hostcom) { + hostcom->SetLogLevel(loglevel_); + } } // 初期化 bool GFTTYDevice::Init() { - if (inherited::Init() == false) { - return false; - } - mainbus = GetMainbusDevice(); gfpic = GetGFPICDevice(1); gfpic->RegistIRQ(32, "GFTTY", this); - scheduler->ConnectMessage(MessageID::HOSTCOM_RX, this, + scheduler->ConnectMessage(MessageID::HOSTCOM0_RX, this, ToMessageCallback(&GFTTYDevice::RxMessage)); return true; } @@ -101,6 +101,7 @@ GFTTYDevice::Init() void GFTTYDevice::ResetHard(bool poweron) { + sesame_idx = 0; rxq.clear(); intr_enable = false; ChangeInterrupt(); @@ -123,7 +124,7 @@ GFTTYDevice::ReadPort(uint32 offset) break; default: - putlog(1, "Read $%08x.L", mpu->GetPaddr()); + putlog(1, "Read $%08x.L", mainbus->GetPaddr()); data.SetBusErr(); break; } @@ -140,7 +141,7 @@ GFTTYDevice::WritePort(uint32 offset, ui switch (offset) { case PUT_CHAR: putlog(2, "PUT_CHAR <- $%02x", data); - hostcom->Tx(data); + Tx(data); break; case COMMAND: @@ -158,7 +159,7 @@ GFTTYDevice::WritePort(uint32 offset, ui break; default: - putlog(1, "Write $%08x.L", mpu->GetPaddr()); + putlog(1, "Write $%08x.L", mainbus->GetPaddr()); r.SetBusErr(); break; } @@ -215,7 +216,7 @@ GFTTYDevice::Command(uint32 cmd) putlog(1, "WRITE_BUFFER: BusError at $%08x", addr); break; } - hostcom->Tx(data); + Tx(data); } break; } @@ -245,6 +246,40 @@ GFTTYDevice::Command(uint32 cmd) } } +// 1バイト送信。 +void +GFTTYDevice::Tx(uint32 data) +{ + // --perf によるパフォーマンス測定用のギミック。 + // GFTTY に特定の文字列を書き込むと、 + // VM 電源オン時から現在までの実時間をログに出力する。NetBSD の + // マルチユーザブートがあらかた終わってログインプロンプトが出る手前の + // /etc/rc.local に + // + // printf '\e[?68008h\e[?68008l' + // + // と書いておくことで、ここまでにかかる時間を表示できる。 + // この値はホスト性能に依存するため、同一環境下での相対比較のみ可能。 + // + // このエスケープシーケンスは DEC/xterm 拡張の設定と解除を続けて行う + // もので、68008 は空いてそうな適当な値。知らない番号の拡張機能については + // おそらく黙って何もしないだけだと思うので、どの端末エミュレータを通過 + // しても副作用は少ないと思われる。 + static const char sesame[] = "\x1b[?68008h\x1b[?68008l"; + if (__predict_false(data == sesame[sesame_idx])) { + sesame_idx++; + if (__predict_false(sesame_idx >= strlen(sesame))) { + GetSyncer()->PutlogRealtime(); + sesame_idx = 0; + } + } else { + sesame_idx = 0; + } + + // 1バイト送信。 + hostcom->Tx(data); +} + void GFTTYDevice::ChangeInterrupt() { @@ -255,9 +290,9 @@ GFTTYDevice::ChangeInterrupt() // ホストスレッドからの受信通知 // (HostCOM スレッドで呼ばれる) void -GFTTYDevice::HostRxCallback() +GFTTYDevice::HostRxCallback(uint32 dummy) { - scheduler->SendMessage(MessageID::HOSTCOM_RX); + scheduler->SendMessage(MessageID::HOSTCOM0_RX); } // ホストシリアルからの1バイト(以上)受信メッセージ