--- nono/vm/rtl8019as.cpp 2026/04/29 17:05:21 1.1.1.1 +++ nono/vm/rtl8019as.cpp 2026/04/29 17:05:25 1.1.1.2 @@ -102,7 +102,7 @@ RTL8019ASDevice::Init() // ホストからの受信コールバックを登録 scheduler->ConnectMessage(MessageID::HOSTNET_RX(n), this, - ToMessageCallback(&RTL8019ASDevice::HostRxCallback)); + ToMessageCallback(&RTL8019ASDevice::RxMessage)); return true; } @@ -207,7 +207,7 @@ RTL8019ASDevice::Decoder(uint32 addr) return addr & 0x3f; } -uint64 +busdata RTL8019ASDevice::Read8(uint32 addr) { uint32 offset = Decoder(addr); @@ -233,7 +233,7 @@ RTL8019ASDevice::Read8(uint32 addr) return data; } -uint64 +busdata RTL8019ASDevice::Read16(uint32 addr) { uint32 offset = Decoder(addr); @@ -254,7 +254,7 @@ RTL8019ASDevice::Read16(uint32 addr) return data; } -uint64 +busdata RTL8019ASDevice::Write8(uint32 addr, uint32 data) { uint32 offset = Decoder(addr); @@ -278,7 +278,7 @@ RTL8019ASDevice::Write8(uint32 addr, uin return 0; } -uint64 +busdata RTL8019ASDevice::Write16(uint32 addr, uint32 data) { uint32 offset = Decoder(addr); @@ -296,7 +296,7 @@ RTL8019ASDevice::Write16(uint32 addr, ui return 0; } -uint64 +busdata RTL8019ASDevice::Peek8(uint32 addr) { uint32 offset = Decoder(addr); @@ -406,17 +406,14 @@ RTL8019ASDevice::MonitorUpdate(Monitor * MonitorReg(screen, x + 4, y, val, rsr_bits); y++; - screen.Puts(0, y, "PAR:"); - screen.Print(x, y, "%02x", par[0]); - for (int i = 1; i < 6; i++) { - screen.Print(x - 1 + i * 3, y, ":%02x", par[i]); - } + // MAC アドレスは PAR0 が左側 (ビッグエンディアンぽい感じ)。 + screen.Print(0, y, "PAR0-5: %s", par.ToString(':').c_str()); - screen.Puts(x + 21, y, "MAR:"); - screen.Print(x + 26, y, "%02x", mar[0]); - for (int i = 1; i < 8; i++) { - screen.Print(x + 25 + i * 3, y, ":%02x", mar[i]); - } + // マルチキャストフィルタは MAR0 が右側 (リトルエンディアンぽい感じ)。 + // MAR7-0: $00000000'00000000 + uint32 marH = (mar[7] << 24) | (mar[6] << 16) | (mar[5] << 8) | mar[4]; + uint32 marL = (mar[3] << 24) | (mar[2] << 16) | (mar[1] << 8) | mar[0]; + screen.Print(x + 23, y, "MAR7-0: $%08x'%08x", marH, marL); y++; y++; @@ -1297,8 +1294,8 @@ RTL8019ASDevice::WriteMAR(int n, uint32 } else { if (__predict_false(n == 7)) { putlog(2, "MAR <- %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - mar[0], mar[1], mar[2], mar[3], - mar[4], mar[5], mar[6], mar[7]); + mar[7], mar[6], mar[5], mar[4], + mar[3], mar[2], mar[1], mar[0]); } } } @@ -2039,9 +2036,21 @@ RTL8019ASDevice::ChangeState(State newst switch (newstate) { case State::Normal: + { + uint64 filter; + filter = ((uint64)mar[0] << 0) + | ((uint64)mar[1] << 8) + | ((uint64)mar[2] << 16) + | ((uint64)mar[3] << 24) + | ((uint64)mar[4] << 32) + | ((uint64)mar[5] << 40) + | ((uint64)mar[6] << 48) + | ((uint64)mar[7] << 56); hostnet->SetMyAddr(par); + hostnet->SetMCastFilter(filter); hostnet->EnableRx(true); break; + } case State::Stop: if (tx_in_progress || rx_packet.length != 0) { @@ -2097,7 +2106,7 @@ RTL8019ASDevice::Transmit() // TXP=1 で呼ばれて、ページごとにパケットにコピーする。 // TBCR で指定された長さを全部コピーしたらホストに送信。 void -RTL8019ASDevice::TXEvent(Event& event) +RTL8019ASDevice::TXEvent(Event& ev) { // 今回処理する分 int count = std::min((uint)transmit_byte_count, 256u); @@ -2139,9 +2148,9 @@ RTL8019ASDevice::TXEvent(Event& event) scheduler->StartEvent(tx_event); } -// パケット受信通知。HostNet から呼ばれる。 +// パケット受信通知。HostNet から (EthernetDevice 経由で) 呼ばれる。 void -RTL8019ASDevice::HostRxCallback(MessageID msgid, uint32 arg) +RTL8019ASDevice::RxMessage(MessageID msgid, uint32 arg) { // 受信イベントが止まっていれば動かす。 // 受信イベントがすでに動いていれば、1パケット受信完了後に @@ -2161,7 +2170,7 @@ RTL8019ASDevice::HostRxCallback(MessageI // len != 0, remain < len : 受信パケットのコピー (2ページ目以降) // len != 0, remain == 0 : 受信パケットのコピー完了直後。 void -RTL8019ASDevice::RXEvent(Event& event) +RTL8019ASDevice::RXEvent(Event& ev) { int remain; @@ -2223,9 +2232,9 @@ RTL8019ASDevice::RXEvent(Event& event) // 初回処理 RXHead(remain); } - RXCopy(event, remain); + RXCopy(ev, remain); } else { - RXDone(event); + RXDone(ev); } return; @@ -2234,8 +2243,8 @@ RTL8019ASDevice::RXEvent(Event& event) // この場合も、ホストキューから次のパケットを引き取る作業は必要。 // XXX 間隔は適当 rx_packet.Clear(); - event.time = 1_usec; - scheduler->RestartEvent(event); + ev.time = 1_usec; + scheduler->RestartEvent(ev); } // パケット受信の初回。 @@ -2259,7 +2268,7 @@ RTL8019ASDevice::RXHead(int remain) // 1ページ埋めるかパケットをコピーし終えたら次へ。 // (初回もヘッダ書き込みに続いて呼ばれる) void -RTL8019ASDevice::RXCopy(Event& event, int remain) +RTL8019ASDevice::RXCopy(Event& ev, int remain) { // パケットをこのページにコピー。 // 今回処理する分はパケットの残りとページの残りの小さいほう。 @@ -2283,8 +2292,8 @@ RTL8019ASDevice::RXCopy(Event& event, in // 転送にかかった時間を模しておく。 // 時間は適当。10Mbps なので 1バイトあたり 1usec とする。 - event.time = count * 1_usec; - scheduler->RestartEvent(event); + ev.time = count * 1_usec; + scheduler->RestartEvent(ev); } // 受信パケットをバッファにコピーし終えた次のターンで呼ばれる。 @@ -2292,7 +2301,7 @@ RTL8019ASDevice::RXCopy(Event& event, in // ストップ待ちでなければ再び RXEvent() イベントを呼び、 // 次パケットの処理を継続する。 void -RTL8019ASDevice::RXDone(Event& event) +RTL8019ASDevice::RXDone(Event& ev) { // 前回でコピーが完了していればここで通知。 putlog(3, "RXDone Received %d bytes", rx_packet.length); @@ -2344,49 +2353,49 @@ RTL8019ASDevice::RXDone(Event& event) // (rx_packet.length == 0 で RXEvent() を呼ぶとパケット受信となる) // どのくらいか待つ? 値は適当 - event.time = 100_usec; - scheduler->RestartEvent(event); + ev.time = 100_usec; + scheduler->RestartEvent(ev); } } // 送信 LED イベント void -RTL8019ASDevice::TXLedEvent(Event& event) +RTL8019ASDevice::TXLedEvent(Event& ev) { if (tx_led == false) { // 消灯中だったら、次は 6msec 点灯 tx_led = true; - event.time = 6_msec; - scheduler->RestartEvent(event); + ev.time = 6_msec; + scheduler->RestartEvent(ev); } else { // 点灯中だったら // - 送信中なら次は 100msec 消灯 // - 送信中でなければここで終わり if (tx_in_progress) { tx_led = false; - event.time = 100_msec; - scheduler->RestartEvent(event); + ev.time = 100_msec; + scheduler->RestartEvent(ev); } } } // 受信 LED イベント void -RTL8019ASDevice::RXLedEvent(Event& event) +RTL8019ASDevice::RXLedEvent(Event& ev) { if (rx_led == false) { // 消灯中だったら、次は 6msec 点灯 rx_led = true; - event.time = 6_msec; - scheduler->RestartEvent(event); + ev.time = 6_msec; + scheduler->RestartEvent(ev); } else { // 点灯中だったら // - 受信中なら次は 100msec 消灯 // - 受信中でなければここで終わり if (rx_packet.length != 0) { rx_led = false; - event.time = 100_msec; - scheduler->RestartEvent(event); + ev.time = 100_msec; + scheduler->RestartEvent(ev); } } } @@ -2405,11 +2414,8 @@ void RTL8019ASDevice::ChangeInterrupt() { if (irq_enable) { - if ((intr_stat & intr_mask) != 0) { - interrupt->AssertINT(this); - } else { - interrupt->NegateINT(this); - } + bool irq = ((intr_stat & intr_mask) != 0); + interrupt->ChangeINT(this, irq); } else { // IRQEN が 0 だと出力がハイインピーダンスになる。 interrupt->AssertINT(this); @@ -2417,7 +2423,7 @@ RTL8019ASDevice::ChangeInterrupt() } // 割り込みアクノリッジ -int +busdata RTL8019ASDevice::InterruptAcknowledge() { return intr_vector;