--- nono/vm/lance.cpp 2026/04/29 17:04:28 1.1.1.1 +++ nono/vm/lance.cpp 2026/04/29 17:04:42 1.1.1.6 @@ -1,17 +1,16 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // #include "lance.h" -#include "configfile.h" #include "bus.h" -#include "lunarom.h" +#include "config.h" #include "mpu.h" -#include "zram.h" #include "mystring.h" - -LanceDevice *gLance; +#include "mythread.h" +#include "zram.h" static void *lance_run(void *); @@ -21,27 +20,27 @@ LanceDevice::LanceDevice() devname = "Lance"; devaddr = 0xf1000000; - monitor.Init(80, 34); + monitor_size = nnSize(80, 34); rx_event.dev = this; 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,9 +51,8 @@ LanceDevice::Init() return false; } - const char *key = "ethernet.macaddr"; - const std::string config_macaddr = gConfig->ReadStr(key, "auto"); - macaddr_t macaddr; + const ConfigItem& item = gConfig->Find("ethernet-macaddr"); + const std::string& config_macaddr = item.AsString(); if (config_macaddr == "rom") { // ROM に書いてあるのを使うので、ここでは何もしなくていい } else { @@ -68,24 +66,17 @@ 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; } } - putmsg(1, "macaddr=%s", macaddr.to_string().c_str()); - - // ROM に書き込む - if (gPROM->SetMacAddr(macaddr) == false) { - putmsg(1, "Cannot set macaddr in PROM"); - return false; - } + putmsg(1, "macaddr=%s", macaddr.to_string(':').c_str()); } // ワーカスレッド起動 - pthread_t th; - pthread_create(&th, NULL, lance_run, NULL); + pthread_create(&thread, NULL, lance_run, NULL); + thread_created = true; return true; } @@ -100,22 +91,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,57 +107,58 @@ 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 -LanceDevice::MonitorUpdate() +void +LanceDevice::MonitorUpdate(TextScreen& monitor) { /* CSR0: $1111 ERR BABL CERR MISS MERR RINT TINT IDON IADR:$123456 @@ -193,9 +178,7 @@ LADRF:$12345678_12345678 TDRP: // name を表示。(var & bit) ならオン(反転)表示。 // bitpos は 0..15 で [0] が MSB にあたる。 #define MonitorBit(var, bit, name) do { \ - monitor.Print(x, y, \ - (((var) & (bit)) ? TA::On : TA::Off), \ - "%s", name); \ + monitor.Puts(x, y, TA::OnOff((var) & (bit)), name); \ x += strlen(name) + 1; \ } while (0) @@ -211,8 +194,8 @@ LADRF:$12345678_12345678 TDRP: // CSR uint16 csr0 = reg.GetCSR0(); monitor.Print(0, y, "CSR0:$%04x", csr0); - MonitorReg(11, y, csr0 >> 8, csr0names); - MonitorReg(11, y + 1, csr0, csr0names + 8); + MonitorReg(monitor, 11, y, csr0 >> 8, csr0names); + MonitorReg(monitor, 11, y + 1, csr0, csr0names + 8); monitor.Print(54, y++, "IADR:$%06x", reg.iadr); monitor.Print(54, y, "CSR3:$%04x", reg.csr3); @@ -223,7 +206,7 @@ LADRF:$12345678_12345678 TDRP: MonitorBit(reg.csr3, AM7990::CSR3_BCON, csr3names[15]); y++; - monitor.Print(0, y, ""); + monitor.Puts(0, y, ""); y++; // MODE は bit15 と bit6-0 の8ビットだけ使われてるので // 途中を省略して 8ビットとして表示する @@ -264,7 +247,7 @@ LADRF:$12345678_12345678 TDRP: y++; // RMD - monitor.Print(0, y, ""); + monitor.Puts(0, y, ""); uint16 rmd[4]; uint32 rmd_addr; @@ -334,7 +317,7 @@ LADRF:$12345678_12345678 TDRP: y += 17; // TMD - monitor.Print(0, y, ""); + monitor.Puts(0, y, ""); uint16 tmd[4]; uint32 tmd_addr; @@ -397,19 +380,17 @@ LADRF:$12345678_12345678 TDRP: } } } - - return true; } // レジスタをビットごとに表示する。 // data は下位8ビットのみ使用し、上位は無視する。 void -LanceDevice::MonitorReg(int x, int y, uint32 data, const char * const *names) +LanceDevice::MonitorReg(TextScreen& monitor, + int x, int y, uint32 data, const char * const *names) { for (int i = 0; i < 8; i++) { bool b = data & (1 << (7 - i)); - uint attr = b ? TA::On : TA::Off; - monitor.Print(x + i * 5, y, attr, "%s", names[i]); + monitor.Puts(x + i * 5, y, TA::OnOff(b), names[i]); } } @@ -582,7 +563,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 +580,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 +603,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 +702,8 @@ LanceDevice::ChipStop() rmd_cur = 0; // イベントを(あれば)停止。 - gScheduler->DelEvent(&rx_event); - gScheduler->DelEvent(&tx_event); + rx_event.Stop(); + tx_event.Stop(); // 受信を停止 RecvEnabled = false; @@ -743,7 +724,7 @@ LanceDevice::Interrupt() { if ((reg.csr0 & AM7990::CSR0_INEA)) { putlog(2, "割り込み"); - gMPU->Interrupt(3); + gMPU->Interrupt(this, 3); } else { putlog(2, "割り込みはマスクされている"); } @@ -753,10 +734,9 @@ LanceDevice::Interrupt() void * lance_run(void *dummy) { - pthread_setname_np("Lance worker"); - pthread_detach(pthread_self()); + PTHREAD_SETNAME("Lance worker"); - gLance->ThreadRun(); + dynamic_cast(gEthernet.get())->ThreadRun(); return NULL; } @@ -795,11 +775,12 @@ LanceDevice::ThreadRun() } } -#define dispatch(flag, func) \ +#define dispatch(flag, func) do { \ if ((req & (flag))) { \ req &= ~(flag); \ (func)(); \ - } + } \ +} while (0) dispatch(REQ_TXIDLE, TXIdle); dispatch(REQ_TXCOPY, TXCopy); @@ -812,10 +793,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 +842,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 +914,7 @@ LanceDevice::TXCopy() // メモリからの転送にかかった時間をざっくり計算 XXX まだ適当 // そのウェイト後に指定のフェーズへ。 tx_event.time = 700 * (src - bufsrc) / 16; - gScheduler->AddEvent(&tx_event); + tx_event.Start(); } // TXSEND フェーズ。パケットを送信。 @@ -1025,7 +1017,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 +1034,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 +1101,7 @@ LanceDevice::RXCopy() // そのウェイト後に RXNEXT フェーズへ。 rx_event.time = 700 * (dst - bufdst) / 16; rx_event.code = REQ_RXNEXT; - gScheduler->AddEvent(&rx_event); + rx_event.Start(); } // RXNEXT フェーズ。 @@ -1179,12 +1171,12 @@ LanceDevice::RXMiss() // イベントハンドラ void -LanceDevice::Callback(int arg) +LanceDevice::Callback(Event& ev) { std::unique_lock lock(mtx); // ワーカスレッドにフェーズ遷移を伝えるだけ - request |= arg; + request |= ev.code; cv.notify_one(); }