--- nono/vm/lance.cpp 2026/04/29 17:05:50 1.1.1.20 +++ nono/vm/lance.cpp 2026/04/29 17:05:59 1.1.1.21 @@ -24,10 +24,9 @@ LanceDevice::LanceDevice() SetName("Lance"); ClearAlias(); AddAlias("Lance"); - AddAlias("Ethernet"); monitor = gMonitorManager->Regist(ID_MONITOR_LANCE, this); - monitor->func = ToMonitorCallback(&LanceDevice::MonitorUpdate); + monitor->SetCallback(&LanceDevice::MonitorScreen); monitor->SetSize(80, 34); } @@ -137,7 +136,7 @@ LanceDevice::PeekPort(uint32 offset) } void -LanceDevice::MonitorUpdate(Monitor *, TextScreen& screen) +LanceDevice::MonitorScreen(Monitor *, TextScreen& screen) { /* CSR0: $1111 ERR BABL CERR MISS MERR RINT TINT IDON IADR:$123456 @@ -503,11 +502,6 @@ LanceDevice::WriteData(uint32 data) if (reg.IsSTOP()) { reg.iadr = (reg.iadr & 0xff0000) | (data & AM7990::IADR_L_MASK); putlog(2, "IDAR(L)=$%06x", reg.iadr); - -#if 0 - // IADR 設定時にパフォーマンス測定用実時間表示 - scheduler->PutlogRealtime(); -#endif } break; @@ -773,79 +767,48 @@ LanceDevice::TXCopy() uint32 src = ((tmd1 & 0x00ff) << 16) | tmd0; int32 bcnt = -(int32)(int16)tmd2; - // copycnt は bcnt のうち実際にコピーするバイト数 - int32 copycnt; - if (tx_packet.length + bcnt > tx_packet.size()) { - // コピーするとバッファが溢れてしまう計算なら、溢れないように打ち切る。 - copycnt = tx_packet.size() - tx_packet.length; - } else { - // 全部コピーできる。 - copycnt = bcnt; - } - - // 送信パケットキュー上の書き込み中バッファに追記する - uint8 *dst = &tx_packet[tx_packet.length]; - tx_packet.length += copycnt; - // ここから、SubRAM からローカルの送信バッファにコピー // XXX バーストコピー未対応 - const uint32 srcend = src + bcnt; - const uint8 *dstend = dst + copycnt; + uint32 srcend = src + bcnt; // src が奇数アドレスから始まっている(そしてコピー可能な)場合 // (バッファを奇数アドレスから始めたりする奇特な人はいないと思うが) - if (__predict_false((src & 1) != 0) && dst < dstend) { + if (__predict_false((src & 1) != 0) && src < srcend) { uint16 data = ReadMem(src & ~1); + src++; if (reg.IsBSWP() == false) { - *dst++ = data >> 8; + tx_packet.Append(data >> 8); } else { - *dst++ = data & 0xff; + tx_packet.Append(data & 0xff); } - src++; } // 残り2バイト以上コピー可能な間 (ここで src はワード境界になっている) - const uint8 *dstend_even; - dstend_even = (const uint8 *)((uintptr_t)dstend & ~(uintptr_t)1); - while (dst < dstend_even) { + for (; src + 1 < srcend; ) { uint16 data = ReadMem(src); + src += 2; if (reg.IsBSWP() == false) { - *dst++ = data & 0xff; - *dst++ = data >> 8; + tx_packet.Append(data & 0xff); + tx_packet.Append(data >> 8); } else { - *dst++ = data >> 8; - *dst++ = data & 0xff; + tx_packet.Append(data >> 8); + tx_packet.Append(data & 0xff); } - src += 2; } // src が奇数アドレスで終わっている(そしてコピー可能な)場合 - if (__predict_false(dst < dstend)) { + if (src < srcend) { uint16 data = ReadMem(src); if (reg.IsBSWP() == false) { - *dst++ = data & 0xff; + tx_packet.Append(data & 0xff); } else { - *dst++ = data >> 8; + tx_packet.Append(data >> 8); } - src += 2; - } - - // tx_packet が一杯になったら後はディスクリプタが終わるまで SubRAM から - // 読み捨てる。tx_packet の長さに上限があるのはこっち(エミュレータ)の - // 都合であって LANCE はディスクリプタが終わるまで延々読み込んでは出力を - // 続けるようだ。ここでは同じだけ読み込むところ、それにかかる時間を求める - // ところを再現する。tx_packet がイーサネットフレーム長を超過していると - // この後 SEND フェーズで BABBLE ビットを立てるところも再現する。 - // 正確には 1519バイト目の送信で立てるのだが、通常は起きない上に面倒 - // なので省略。1519バイト以上のパケットをホストに流すこともしない。 - while (src < srcend) { - ReadMem(src); - src += 2; } // メモリからの転送にかかった時間をざっくり計算 XXX まだ適当 // そのウェイト後に指定のフェーズへ。 - uint64 t = 700 * bcnt / 16; + uint64 t = nsec_to_tsec(700 * bcnt / 16); // ここが ENP なら、送信のため TXSEND フェーズへ if ((tmd1 & AM7990::TMD1_ENP)) { @@ -875,7 +838,7 @@ LanceDevice::TXSend(Event *ev) { tx_phase = TXPhase::SEND; - if (__predict_false(tx_packet.length > 1518)) { + if (__predict_false(tx_packet.Length() > 1518)) { // 本当は 1519バイト目を送ったところで BABL を立てるのだが // まず起きない上に面倒なので、ここで行う。 SetInterrupt(AM7990::CSR0_BABL); @@ -935,13 +898,13 @@ LanceDevice::ChangePhase(TXPhase new_pha scheduler->StopEvent(tx_event); return; case TXPhase::IDLE: - tx_event->func = ToEventCallback(&LanceDevice::TXIdle); + tx_event->SetCallback(&LanceDevice::TXIdle); break; case TXPhase::SEND: - tx_event->func = ToEventCallback(&LanceDevice::TXSend); + tx_event->SetCallback(&LanceDevice::TXSend); break; case TXPhase::NEXT: - tx_event->func = ToEventCallback(&LanceDevice::TXNext); + tx_event->SetCallback(&LanceDevice::TXNext); break; default: assertmsg(false, "phase %u", (uint)new_phase); @@ -1044,84 +1007,70 @@ LanceDevice::RXCopy() uint16 rmd2 = ReadMem(rmd_addr + 4); // アドレスと受信バッファのバイト数。 - uint32 bufdst = ((rmd1 & 0x00ff) << 16) | rmd0; - uint32 dst = bufdst; + uint32 dst = ((rmd1 & 0x00ff) << 16) | rmd0; // rmd2 は 2 の補数 int32 bcnt = -(int32)(int16)rmd2; - if (bcnt < rx_packet.length) { - putlog(1, "will be remain: %d < %u", bcnt, rx_packet.length); - } + // 今回のコピーバイト数。 + uint copycnt = std::min((uint)bcnt, rx_packet.GetRemain()); + uint32 dstend = dst + copycnt; - uint8 *src = &rx_packet[0]; - uint remsize = rx_packet.length; + // ローカルの受信バッファからディスクリプタバッファにコピー。 + // XXX バーストコピー未対応 - if (bcnt > remsize) { - bcnt = remsize; + // dst が奇数アドレスから始まっている場合。 + // 奇数バイトには不定データが出るらしいがここでは 0 にする + if (__predict_false((dst & 1) != 0) && dst < dstend) { + uint16 data; + if (reg.IsBSWP() == false) { + data = rx_packet.Read() << 8; + } else { + data = rx_packet.Read(); + } + WriteMem(dst & ~1, data); + dst += 1; } - // コピー後の残りサイズにしておく - remsize -= bcnt; + // 残り2バイト以上コピー可能な間 (ここで dst はワード境界になっている)。 + for (; dst + 1 < dstend; ) { + uint16 data; + if (reg.IsBSWP() == false) { + data = rx_packet.Read(); + data |= rx_packet.Read() << 8; + } else { + data = rx_packet.Read() << 8; + data |= rx_packet.Read(); + } + WriteMem(dst, data); + dst += 2; + } - // ローカルの受信バッファからディスクリプタバッファにコピー - for (; bcnt > 0; ) { - // XXX バーストコピー未対応 + // dst が奇数アドレスで終わっている場合。 + // 奇数バイトには不定データが出るらしいがここでは 0 にする + if (dst < dstend) { uint16 data; - if (bcnt >= 2 && (dst & 1) == 0) { - // 2バイト以上残っててワード境界ならワードアクセス - if (reg.IsBSWP() == false) { - data = *src++; - data |= (*src++) << 8; - } else { - data = (*src++) << 8; - data |= *src++; - } - WriteMem(dst, data); - dst += 2; - bcnt -= 2; - } else if ((dst & 1) == 0) { - // 偶数アドレスへ1バイト - // 奇数バイトには不定データが出るらしいがここでは 0 にする - if (reg.IsBSWP() == false) { - data = *src++; - } else { - data = (*src++) << 8; - } - WriteMem(dst, data); - dst += 1; - bcnt -= 1; + if (reg.IsBSWP() == false) { + data = rx_packet.Read(); } else { - // 奇数アドレスへ1バイト - // 偶数バイトには不定データが出るらしいがここでは 0 にする - if (reg.IsBSWP() == false) { - data = (*src++) << 8; - } else { - data = *src++; - } - WriteMem(dst & ~1, data); - dst += 1; - bcnt -= 1; + data = rx_packet.Read() << 8; } + WriteMem(dst, data); } // 全部書き出せたらここが ENP - if (remsize == 0) { + if (rx_packet.GetRemain() == 0) { rmd1 |= AM7990::RMD1_ENP; // ENP なら MCNT を更新 - WriteMem(rmd_addr + 6, (dst - bufdst) & 0xfff); + WriteMem(rmd_addr + 6, copycnt & 0xfff); } else { rmd1 &= ~AM7990::RMD1_ENP; - putlog(1, "copy remain %u", remsize); - - // 前詰めにコピーする - memmove(&rx_packet[0], src, remsize); - rx_packet.length = remsize; + putlog(1, "copy remain %u", rx_packet.GetRemain()); } // メモリへの転送にかかった時間をざっくり計算 XXX まだ適当 // そのウェイト後に RXNEXT フェーズへ。 - uint64 t = 700 * (dst - bufdst) / 16; + uint64 t = nsec_to_tsec(700 * copycnt / 16); ChangePhase(RXPhase::NEXT, t); } @@ -1262,10 +1211,10 @@ LanceDevice::ChangePhase(RXPhase new_pha scheduler->StopEvent(rx_event); return; case RXPhase::IDLE: - rx_event->func = ToEventCallback(&LanceDevice::RXIdle); + rx_event->SetCallback(&LanceDevice::RXIdle); break; case RXPhase::NEXT: - rx_event->func = ToEventCallback(&LanceDevice::RXNext); + rx_event->SetCallback(&LanceDevice::RXNext); break; default: assertmsg(false, "phase %u", (uint)new_phase);