--- nono/vm/lance.cpp 2026/04/29 17:05:20 1.1.1.14 +++ nono/vm/lance.cpp 2026/04/29 17:05:24 1.1.1.15 @@ -51,7 +51,7 @@ LanceDevice::Init() // ホストからの受信コールバックを登録 scheduler->ConnectMessage(MessageID::HOSTNET_RX(0), this, - ToMessageCallback(&LanceDevice::HostRxCallback)); + ToMessageCallback(&LanceDevice::RxMessage)); return true; } @@ -64,42 +64,49 @@ LanceDevice::ResetHard(bool poweron) ChipStop(); } -uint64 +busdata LanceDevice::Read(uint32 offset) { - uint32 data; + busdata data; switch (offset) { case 0: // RDP data = ReadData(); - return data; + break; case 1: // RAP data = reg.rap; putlog(2, "RAP -> %d", reg.rap); - return data; + break; default: VMPANIC("corrupted offset=%d", offset); - return 0xff; + data = 0xffff; + break; } + + // XXX wait? + return data; } -uint64 +busdata LanceDevice::Write(uint32 offset, uint32 data) { switch (offset) { case 0: // RDP WriteData(data); - return 0; + break; case 1: // RAP reg.rap = data & 3; - return 0; + break; default: VMPANIC("corrupted offset=%d", offset); - return 0; + break; } + + // XXX wait? + return 0; } -uint64 +busdata LanceDevice::Peek(uint32 offset) { switch (offset) { @@ -135,8 +142,8 @@ CSR0: $1111 ERR BABL CERR MISS MERR RIN CSR3:$0004 BSWP ACON BCON MODE: $0000 PROM INTL DRTY COLL DTCR LOOP DTX DRX -PADR: 00:11:22:33:44:55 RDRP: $12345678 (RDRA=$123456 entries=32) -LADRF:$12345678_12345678 TDRP: +PADR: 00:11:22:33:44:55 RDRP: $12345678 (RDRA=$123456 entries=32) +LADRF:$fedcba98'76543210 TDRP: Current 00 OWN ERR OFLO CRC BUFF STP ENP BCNT=$123 MCNT=$123 buf=$123456 01234567890123456789012345678901234567890 00 @@ -194,8 +201,7 @@ LADRF:$12345678_12345678 TDRP: initblock[1] & 0xff, initblock[1] >> 8, initblock[2] & 0xff, initblock[2] >> 8, initblock[3] & 0xff, initblock[3] >> 8); - // XXX LADRF のバイト順未検証 - screen.Print(0, y + 1, "LADRF:$%04x%04x_%04x%04x", + screen.Print(0, y + 1, "LADRF:$%04x%04x'%04x%04x", initblock[7], initblock[6], initblock[5], @@ -408,7 +414,7 @@ LanceDevice::ReadData() break; default: VMPANIC("corrupted reg.rap=%d", reg.rap); - data = 0xff; + data = 0xffff; break; } return data; @@ -612,8 +618,20 @@ LanceDevice::ChipInit() padr[4] = initblock[3] & 0xff; padr[5] = initblock[3] >> 8; + // LADRF は以下のように格納されていて、そのまま LADRF(63:00) に対応する。 + // IADR+$08 LADRF(15:00) + // IADR+$0a LADRF(31:16) + // IADR+$0c LADRF(47:32) + // IADR+$0e LADRF(63:48) + uint64 filter; + filter = ((uint64)initblock[4] << 0) + | ((uint64)initblock[5] << 16) + | ((uint64)initblock[6] << 32) + | ((uint64)initblock[7] << 48); + // ホストデバイスに設定 hostnet->SetMyAddr(padr); + hostnet->SetMCastFilter(filter); hostnet->SetPromisc((initblock[0] & AM7990::IBMODE_PROM)); // XXX 本当はいろいろ時間がかかりそうなはずだが @@ -667,6 +685,7 @@ LanceDevice::ChipStop() // STOPセットで CSR0 は STOP セット、他は全クリア reg.csr0 = AM7990::CSR0_STOP; + ChangeInterrupt(); // CSR1, 2 は不定 // CSR3 はクリア reg.csr3 = 0; @@ -699,11 +718,8 @@ LanceDevice::SetInterrupt(uint32 bit) void LanceDevice::ChangeInterrupt() { - if (reg.IsINTR() && (reg.csr0 & AM7990::CSR0_INEA)) { - interrupt->AssertINT(this); - } else { - interrupt->NegateINT(this); - } + bool irq = (reg.IsINTR() && (reg.csr0 & AM7990::CSR0_INEA)); + interrupt->ChangeINT(this, irq); } // TXIDLE 送信アイドルフェーズ。 @@ -712,7 +728,7 @@ LanceDevice::ChangeInterrupt() // - 所有できない場合、TDMD オンなら即、 // オフなら 1.6ms 待ってから再び TXIDLE へ。 void -LanceDevice::TXIdle(Event& event) +LanceDevice::TXIdle(Event& ev) { tx_phase = TXPhase::IDLE; @@ -861,7 +877,7 @@ LanceDevice::TXCopy() // ただし ENP でなければアンダーフローによるパケット送信なのでフラグ処理。 // その後 TXNEXT フェーズへ。 void -LanceDevice::TXSend(Event& event) +LanceDevice::TXSend(Event& ev) { tx_phase = TXPhase::SEND; @@ -898,7 +914,7 @@ LanceDevice::TXSend(Event& event) // TXNEXT フェーズ。次のディスクリプタを指して TXIDLE へ。 void -LanceDevice::TXNext(Event& event) +LanceDevice::TXNext(Event& ev) { tx_phase = TXPhase::NEXT; @@ -945,7 +961,7 @@ LanceDevice::ChangePhase(TXPhase new_pha // | RXSTOP |<- - - (CSR0.STOP 書き込み / リセット) // +--------+ // : -// : +‥‥‥+ <‥‥ HostRxCallback (パケット受信) +// : +‥‥‥+ <‥‥ RxMessage (パケット受信) // v v : // +-------------+ : // +‥‥‥>| RXIDLE |‥‥+ Idle @@ -963,9 +979,9 @@ LanceDevice::ChangePhase(TXPhase new_pha // | RXCOPY | 関数呼び出し ----> // +-----------+ イベントによる遷移 ‥‥> -// パケット受信通知。HostNet から呼ばれる。 +// パケット受信通知。HostNet から (EthernetDevice 経由で) 呼ばれる。 void -LanceDevice::HostRxCallback(MessageID msgid, uint32 arg) +LanceDevice::RxMessage(MessageID msgid, uint32 arg) { // RXIDLE ポーリングのウェイト中ならすぐに始める。 // そうでないときは RXIDLE に戻ったところで処理される。 @@ -977,7 +993,7 @@ LanceDevice::HostRxCallback(MessageID ms // RXIDLE 受信アイドルフェーズ。 // (最初の)ディスクリプタを所有できるかポーリングする。 void -LanceDevice::RXIdle(Event& event) +LanceDevice::RXIdle(Event& ev) { rx_phase = RXPhase::IDLE; @@ -1121,7 +1137,7 @@ LanceDevice::RXCopy() // - 次のディスクリプタが所有できれば引き続き書き出すため RXCOPY へ。 // - 次のディスクリプタが所有できなければエラーにして RXIDLE へ。 void -LanceDevice::RXNext(Event& event) +LanceDevice::RXNext(Event& ev) { rx_phase = RXPhase::NEXT;