--- nono/vm/lance.cpp 2026/04/29 17:04:28 1.1 +++ nono/vm/lance.cpp 2026/04/29 17:04:32 1.1.1.3 @@ -4,15 +4,13 @@ // #include "lance.h" -#include "configfile.h" +#include "config.h" #include "bus.h" -#include "lunarom.h" #include "mpu.h" +#include "romimg_luna.h" #include "zram.h" #include "mystring.h" -LanceDevice *gLance; - static void *lance_run(void *); LanceDevice::LanceDevice() @@ -27,21 +25,21 @@ LanceDevice::LanceDevice() rx_event.func = (DeviceCallback_t)&LanceDevice::Callback; rx_event.code = 0; rx_event.time = 0; // 都度設定する - rx_event.name = "Lance RX"; + rx_event.SetName("Lance RX"); tx_event.dev = this; tx_event.func = (DeviceCallback_t)&LanceDevice::Callback; tx_event.code = 0; tx_event.time = 0; // 都度設定する - tx_event.name = "Lance TX"; + tx_event.SetName("Lance TX"); } LanceDevice::~LanceDevice() { - // スレッド終了を指示 - std::unique_lock lock(mtx); - request |= REQ_TERMINATE; - cv.notify_one(); + if (thread_created) { + Terminate(); + pthread_join(thread, NULL); + } } bool @@ -52,8 +50,8 @@ LanceDevice::Init() return false; } - const char *key = "ethernet.macaddr"; - const std::string config_macaddr = gConfig->ReadStr(key, "auto"); + const ConfigItem& item = gConfig->Get("ethernet-macaddr"); + const std::string& config_macaddr = item.AsString(); macaddr_t macaddr; if (config_macaddr == "rom") { // ROM に書いてあるのを使うので、ここでは何もしなくていい @@ -68,8 +66,7 @@ LanceDevice::Init() } else { // ユーザ指定 if (ParseMacAddr(macaddr, config_macaddr) == false) { - gConfig->Err(key, "%s: invalid MAC address", - config_macaddr.c_str()); + item.Err("invalid MAC address"); return false; } } @@ -78,14 +75,14 @@ LanceDevice::Init() // ROM に書き込む if (gPROM->SetMacAddr(macaddr) == false) { - putmsg(1, "Cannot set macaddr in PROM"); + warnx("LanceDevice initialization failed: unexpected PROM"); return false; } } // ワーカスレッド起動 - pthread_t th; - pthread_create(&th, NULL, lance_run, NULL); + pthread_create(&thread, NULL, lance_run, NULL); + thread_created = true; return true; } @@ -100,22 +97,15 @@ LanceDevice::ResetHard() } uint64 -LanceDevice::Read8(uint32 addr) -{ - putlog(0, "未実装バイト読み込み $%08x", addr); - return 0xff; -} - -uint64 -LanceDevice::Read16(uint32 addr) +LanceDevice::Read(uint32 addr) { uint32 data; - switch (addr - devaddr) { + switch (addr) { case 0: // RDP data = ReadData(); return data; - case 2: // RAP + case 1: // RAP { std::unique_lock lock(mtx); data = reg.rap; @@ -123,53 +113,54 @@ LanceDevice::Read16(uint32 addr) return data; } } - putlog(0, "未実装ワード読み込み $%08x", addr); - return 0xffff; + __unreachable(); } uint64 -LanceDevice::Read32(uint32 addr) +LanceDevice::Write(uint32 addr, uint32 data) { - putlog(0, "未実装ロング読み込み $%08x", addr); - return 0xffffffff; -} - -uint64 -LanceDevice::Write8(uint32 addr, uint32 data) -{ - putlog(0, "未実装バイト書き込み $%08x <- %02x", addr, data); - return 0; -} - -uint64 -LanceDevice::Write16(uint32 addr, uint32 data) -{ - switch (addr - devaddr) { + switch (addr) { case 0: // RDP WriteData(data); return 0; - case 2: // RAP + case 1: // RAP { std::unique_lock lock(mtx); reg.rap = data & 3; return 0; } } - putlog(0, "未実装ワード書き込み $%08x <- %04x", addr, data); - return 0; -} - -uint64 -LanceDevice::Write32(uint32 addr, uint32 data) -{ - putlog(0, "未実装ロング書き込み $%08x <- %08x", addr, data); - return 0; + __unreachable(); } uint64 -LanceDevice::Peek8(uint32 addr) +LanceDevice::Peek(uint32 addr) { - return 0xff; + switch (addr) { + case 0: // RDP + { + // 今読めるはずのデータ。 + // CSR[123] は STOP 中でなければ不定だがとりあえずそれは無視。 + std::unique_lock lock(mtx); + switch (reg.rap) { + case 0: + return reg.GetCSR0(); + case 1: + return reg.iadr & 0xffff; + case 2: + return reg.iadr >> 16; + case 3: + return reg.csr3; + } + break; + } + case 1: // RAP + { + std::unique_lock lock(mtx); + return reg.rap; + } + } + __unreachable(); } bool @@ -582,7 +573,7 @@ LanceDevice::ReadMem(uint32 paddr) { uint64 data; - assert((paddr & 1) == 0); + assertmsg((paddr & 1) == 0, "paddr=$%x", paddr); // XXX 3ポートRAM のエンディアンとかを調べること data = gZRAM->Read16(paddr); @@ -599,7 +590,7 @@ LanceDevice::ReadMem(uint32 paddr) uint64 LanceDevice::WriteMem(uint32 paddr, uint32 data) { - assert((paddr & 1) == 0); + assertmsg((paddr & 1) == 0, "paddr=$%x", paddr); if (!reg.IsBSWP()) { data = __builtin_bswap16(data); @@ -622,12 +613,12 @@ LanceDevice::PeekMem(uint32 paddr) if (reg.IsBSWP()) { // ビッグエンディアンアクセス - data = m68030_phys_peek_8(paddr) << 8; - data |= m68030_phys_peek_8(paddr + 1); + data = vm_phys_peek_8(paddr) << 8; + data |= vm_phys_peek_8(paddr + 1); } else { // リトルエンディアンアクセス - data = m68030_phys_peek_8(paddr); - data |= m68030_phys_peek_8(paddr + 1) << 8; + data = vm_phys_peek_8(paddr); + data |= vm_phys_peek_8(paddr + 1) << 8; } return data; } @@ -721,8 +712,8 @@ LanceDevice::ChipStop() rmd_cur = 0; // イベントを(あれば)停止。 - gScheduler->DelEvent(&rx_event); - gScheduler->DelEvent(&tx_event); + rx_event.Stop(); + tx_event.Stop(); // 受信を停止 RecvEnabled = false; @@ -754,9 +745,8 @@ void * lance_run(void *dummy) { pthread_setname_np("Lance worker"); - pthread_detach(pthread_self()); - gLance->ThreadRun(); + dynamic_cast(gEthernet.get())->ThreadRun(); return NULL; } @@ -812,10 +802,21 @@ LanceDevice::ThreadRun() dispatch(REQ_RXMISS, RXMiss); dispatch(REQ_RXRECV, RXRecv); - assert(req == 0); + assertmsg(req == 0, "req=$%x", req); } } +// スレッドの終了を指示 +void +LanceDevice::Terminate() +{ + assert(thread_created); + + std::unique_lock lock(mtx); + request |= REQ_TERMINATE; + cv.notify_one(); +} + // TXIDLE 送信アイドルフェーズ。 // ディスクリプタを所有できるかポーリングする。 // - 所有できれば PUSH フェーズへ。 @@ -850,7 +851,7 @@ LanceDevice::TXIdle() // TDMD がオフなら 1.6ms 待って再度 POLL へ。 tx_event.time = 1.6_msec; tx_event.code = REQ_TXIDLE; - gScheduler->AddEvent(&tx_event); + tx_event.Start(); } } @@ -922,7 +923,7 @@ LanceDevice::TXCopy() // メモリからの転送にかかった時間をざっくり計算 XXX まだ適当 // そのウェイト後に指定のフェーズへ。 tx_event.time = 700 * (src - bufsrc) / 16; - gScheduler->AddEvent(&tx_event); + tx_event.Start(); } // TXSEND フェーズ。パケットを送信。 @@ -1025,7 +1026,7 @@ LanceDevice::RXIdle() // 1.6ms 待って再度 RXIDLE へ。 rx_event.time = 1.6_msec; rx_event.code = REQ_RXIDLE; - gScheduler->AddEvent(&rx_event); + rx_event.Start(); } // RXRECV 先頭ディスクリプタ開始フェーズ。 @@ -1042,7 +1043,7 @@ LanceDevice::RXRecv() // パケットを受信してる時間に相当するウェイト XXX 適当 rx_event.time = 700 * rxq.size() / 16; rx_event.code = REQ_RXMISS; - gScheduler->AddEvent(&rx_event); + rx_event.Start(); } } @@ -1109,7 +1110,7 @@ LanceDevice::RXCopy() // そのウェイト後に RXNEXT フェーズへ。 rx_event.time = 700 * (dst - bufdst) / 16; rx_event.code = REQ_RXNEXT; - gScheduler->AddEvent(&rx_event); + rx_event.Start(); } // RXNEXT フェーズ。