--- nono/vm/rtl8019as.cpp 2026/04/29 17:05:33 1.1.1.4 +++ nono/vm/rtl8019as.cpp 2026/04/29 17:05:38 1.1.1.5 @@ -68,24 +68,17 @@ RTL8019ASDevice::~RTL8019ASDevice() bool RTL8019ASDevice::Init() { - if (inherited::Init() == false) { - return false; - } - uint n = GetId() - OBJ_ETHERNET0; // MAC アドレスを取得 - macaddr_t macaddr; + MacAddr macaddr; if (inherited::GetConfigMacAddr(n, &macaddr, false) == false) { // エラーメッセージ表示済み return false; } // PROM 領域 (実質16バイト) を作成 memset(&prom[0], 0xff, prom.size()); - uint8 *d = &prom[0]; - for (auto m : macaddr) { - *d++ = m; - } + macaddr.ExportTo(&prom[0]); prom[0xe] = 'W'; prom[0xf] = 'W'; @@ -406,9 +399,8 @@ RTL8019ASDevice::MonitorUpdate(Monitor * // マルチキャストフィルタは 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); + screen.Print(x + 23, y, "MAR7-0: $%08x'%08x", + (uint32)(mar >> 32), (uint32)mar); y++; y++; @@ -1200,9 +1192,6 @@ RTL8019ASDevice::WriteRCR(uint32 data) accept_bcast = (data & RTL8019::RCR_AB); accept_short = (data & RTL8019::RCR_AR); accept_error = (data & RTL8019::RCR_SEP); - - // プロミスキャスの設定はここで行う? - hostnet->SetPromisc(promisc_mode); } // TCR レジスタ書き込み @@ -1283,15 +1272,14 @@ RTL8019ASDevice::WriteCURR(uint32 data) void RTL8019ASDevice::WriteMAR(uint n, uint32 data) { - mar[n] = data; + mar &= ~(0xffULL << (n * 8)); + mar |= (uint64)data << (n * 8); if (__predict_false(loglevel >= 3)) { putlogn("MAR%u <- $%02x", n, data); } else { if (__predict_false(n == 7)) { - putlog(2, "MAR <- %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - mar[7], mar[6], mar[5], mar[4], - mar[3], mar[2], mar[1], mar[0]); + putlog(2, "MAR <- $%08x'%08x", (uint32)(mar >> 32), (uint32)mar); } } } @@ -1787,7 +1775,7 @@ RTL8019ASDevice::PeekCURR() const uint32 RTL8019ASDevice::PeekMAR(int n) const { - return mar[n]; + return (mar >> (n * 8)) & 0xff; } uint32 @@ -2032,21 +2020,8 @@ 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) { @@ -2304,6 +2279,9 @@ RTL8019ASDevice::RXDone(Event& ev) // 受信ヘッダに書き込む前に RSR を更新 rsr |= RTL8019::RSR_PRX; + if ((rx_packet[0] & 0x01)) { + rsr |= RTL8019::RSR_PHY; + } // 念のためエラービットをクリア (DP83901A.pdf) rsr &= ~(RTL8019::RSR_MPA | RTL8019::RSR_FAE | @@ -2354,6 +2332,68 @@ RTL8019ASDevice::RXDone(Event& ev) } } +// この宛先アドレスを受信するかどうか。 +// これは HostNet スレッドで呼ばれる。 +int +RTL8019ASDevice::HWAddrFilter(const MacAddr& dstaddr) const +{ + // RTL8019AS.pdf では詳細不明だが、 + // DP83901A.pdf には、完全なプロミスキャスにするには AB, AM, PRO 全部 + // 立ててさらにマルチキャストハッシュを全部 1 にしろ、と注釈があるので、 + // - PRO は自分宛て以外のユニキャストを受け取るかどうか、 + // - AM は、ハッシュで accept になったマルチキャストを受け取るか + // マルチキャストを一切受け取らないか、 + // - AB はブロードキャストを受け取るかどうか、 + // の独立したビットのようだ。 + + if (dstaddr.IsUnicast()) { + if (promisc_mode == false) { + if (dstaddr != par) { + return HPF_DROP_UNICAST; + } + } + } else { + if (dstaddr.IsBroadcast()) { + if (accept_bcast == false) { + // XXX 選択肢がまだない + return HPF_DROP_MULTICAST; + } + } else { + if (accept_mcast == false) { + return HPF_DROP_MULTICAST; + } + + // マルチキャスト + // + // RTL8019AS のマルチキャストフィルタ(ハッシュ) は宛先 MAC + // アドレスの CRC (32ビット) のうち上位6ビットを pos として、 + // MAR の下から pos ビット目が立っていれば受理する、というもの。 + // + // 31 30 29 28 27 26 25 24 0 + // +---+---+---+---+---+---+---+---+-- --+ + // CRC32(dstaddr) = | p5| p4| p3| p2| p1| p0| X X | .. | + // +---+---+---+---+---+---+---+---+-- --+ + // + // +---+---+---+---+---+---+ + // pos = | p5| p4| p3| p2| p1| p0| + // +---+---+---+---+---+---+ + + uint32 crc = EthernetDevice::CRC32(dstaddr); + uint pos = crc >> 26; + bool mcast_pass = (mar & (1ULL << pos)); + putmsg(2, "mcast %02x:%02x:%02x:%02x:%02x:%02x pos=%u %s", + dstaddr[0], dstaddr[1], dstaddr[2], + dstaddr[3], dstaddr[4], dstaddr[5], + pos, (mcast_pass ? "pass" : "drop")); + if (mcast_pass == false) { + return HPF_DROP_MULTICAST; + } + } + } + + return HPF_PASS; +} + // 送信 LED イベント void RTL8019ASDevice::TXLedEvent(Event& ev)