--- nono/vm/lance.cpp 2026/04/29 17:05:10 1.1.1.11 +++ nono/vm/lance.cpp 2026/04/29 17:05:24 1.1.1.15 @@ -10,20 +10,20 @@ #include "lance.h" #include "bitops.h" -#include "bus.h" -#include "config.h" #include "interrupt.h" +#include "mainbus.h" #include "scheduler.h" -#include "zram.h" +#include "subram.h" // コンストラクタ LanceDevice::LanceDevice() - : inherited("Lance") + : inherited(OBJ_ETHERNET(0)) { + SetName("Lance"); + ClearAlias(); + AddAlias("Lance"); AddAlias("Ethernet"); - devaddr = 0xf1000000; - // func, time は都度設定する rx_event.Regist("Lance RX"); tx_event.Regist("Lance TX"); @@ -38,35 +38,20 @@ LanceDevice::~LanceDevice() { } +// 初期化 bool LanceDevice::Init() { - // ホストからの受信コールバックを登録 - gScheduler->ConnectMessage(MessageID::HOSTNET_RX, this, - ToMessageCallback(&LanceDevice::HostRxCallback)); + if (inherited::Init() == false) { + return false; + } - const ConfigItem& item = gConfig->Find("ethernet-macaddr"); - const std::string& config_macaddr = item.AsString(); - if (config_macaddr == "rom") { - // ROM に書いてあるのを使うので、ここでは何もしなくていい - } else { - if (config_macaddr == "auto") { - // 自動生成 - // すでに記録されていれば使う。なければ生成して記録したい - if (0) { - } else { - macaddr.Generate(); - } - } else { - // ユーザ指定 - if (macaddr.FromString(config_macaddr) == false) { - item.Err("invalid MAC address"); - return false; - } - } + interrupt = GetInterruptDevice(); + subram = GetSubRAMDevice(); - putmsg(1, "macaddr=%s", macaddr.ToString(':').c_str()); - } + // ホストからの受信コールバックを登録 + scheduler->ConnectMessage(MessageID::HOSTNET_RX(0), this, + ToMessageCallback(&LanceDevice::RxMessage)); return true; } @@ -79,40 +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: - __unreachable(); + VMPANIC("corrupted offset=%d", offset); + 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: - __unreachable(); + VMPANIC("corrupted offset=%d", offset); + break; } + + // XXX wait? + return 0; } -uint64 +busdata LanceDevice::Peek(uint32 offset) { switch (offset) { @@ -129,14 +123,15 @@ LanceDevice::Peek(uint32 offset) case 3: return reg.csr3; default: - __unreachable(); + break; } break; case 1: // RAP return reg.rap; default: - __unreachable(); + break; } + return 0xff; } void @@ -147,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 @@ -206,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], @@ -396,7 +390,7 @@ LanceDevice::ReadData() putlog(2, "CSR%d -> $%04x", reg.rap, data); } else { data = 0xcccc & AM7990::CSR1_MASK; - putlog(2, "CSR%d -> $%04x (不定読み出し)", reg.rap, data); + putlog(2, "CSR%d -> $%04x (indefinate read)", reg.rap, data); } break; case 2: @@ -405,7 +399,7 @@ LanceDevice::ReadData() putlog(2, "CSR%d -> $%04x", reg.rap, data); } else { data = 0xcccc & AM7990::CSR2_MASK; - putlog(2, "CSR%d -> $%04x (不定読み出し)", reg.rap, data); + putlog(2, "CSR%d -> $%04x (indefinate read)", reg.rap, data); } break; case 3: @@ -415,11 +409,13 @@ LanceDevice::ReadData() putlog(2, "CSR%d -> $%04x<%s>", reg.rap, data, name.c_str()); } else { data = 0xcccc & AM7990::CSR3_MASK; - putlog(2, "CSR%d -> $%04x (不定読み出し)", reg.rap, data); + putlog(2, "CSR%d -> $%04x (indefinate read)", reg.rap, data); } break; default: - __unreachable(); + VMPANIC("corrupted reg.rap=%d", reg.rap); + data = 0xffff; + break; } return data; } @@ -506,7 +502,7 @@ LanceDevice::WriteData(uint32 data) #if 0 // IADR 設定時にパフォーマンス測定用実時間表示 - gScheduler->PutlogRealtime(); + scheduler->PutlogRealtime(); #endif } break; @@ -530,20 +526,20 @@ LanceDevice::WriteData(uint32 data) break; default: - __unreachable(); + VMPANIC("corrupted reg.rap=%d", reg.rap); } } // メモリアクセスについて。 // LANCE(AM7990) から見たメモリは、メインメモリではなく 3ポートSRAM -// (ここでは ZRAM デバイス)。 -// LANCE のメモリバスは 16bit で、DAL15..8 が ZRAM の偶数アドレス、 -// DAL7..0 が ZRAM の奇数アドレスに接続されている。 +// (ここでは SubRAM デバイス)。 +// LANCE のメモリバスは 16bit で、DAL15..8 が SubRAM の偶数アドレス、 +// DAL7..0 が SubRAM の奇数アドレスに接続されている。 // -// LANCE | DAL15..DAL8 | DAL7..DAL0 -// ------+-------------+------------ -// ZRAM | +0 byte | +1 byte -// | +2 byte | +3 byte +// LANCE | DAL15..DAL8 | DAL7..DAL0 +// -------+-------------+------------ +// SubRAM | +0 byte | +1 byte +// | +2 byte | +3 byte // // メモリアクセスは常にこの構成で、CSR3.BSWP はこの1ワードを SILO(FIFO) に // 書き込む/から読み出す順序を入れ替えるもの。 @@ -557,7 +553,7 @@ LanceDevice::ReadMem(uint32 paddr) assertmsg((paddr & 1) == 0, "paddr=$%x", paddr); // XXX 所要クロックを考察すること - data = gZRAM->Read16(paddr); + data = subram->Read16(paddr); return data; } @@ -568,7 +564,7 @@ LanceDevice::WriteMem(uint32 paddr, uint assertmsg((paddr & 1) == 0, "paddr=$%x", paddr); // XXX 所要クロックを考察すること - gZRAM->Write16(paddr, data); + subram->Write16(paddr, data); return 0; } @@ -578,18 +574,13 @@ LanceDevice::PeekMem(uint32 paddr) { uint64 data; - // XXX なんでここ gZRAM->Peek() じゃないんだっけ? - - paddr &= 0x1ffff; - paddr += 0x71000000; // XXX 定数にしたほうがいい + data = subram->Peek8(paddr) << 8; + data |= subram->Peek8(paddr + 1); - data = vm_phys_peek_8(paddr) << 8; - data |= vm_phys_peek_8(paddr + 1); return data; } // INIT ビットによるチップ初期化。 -// ロック状態で呼ばれる。 void LanceDevice::ChipInit() { @@ -627,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 本当はいろいろ時間がかかりそうなはずだが @@ -637,11 +640,10 @@ LanceDevice::ChipInit() } // STRT ビットによるスタート。 -// ロック状態で呼ばれる。 void LanceDevice::ChipStart() { - putlog(1, "スタート"); + putlog(1, "Start"); // STRT を書き込むと STOP はクリア reg.csr0 |= AM7990::CSR0_STRT; @@ -676,14 +678,14 @@ LanceDevice::ChipStart() // STOP ビットによるチップリセット。 // ハードリセットもここに来る。 -// ロック状態で呼ばれる。 void LanceDevice::ChipStop() { - putlog(1, "リセット"); + putlog(1, "Reset"); // STOPセットで CSR0 は STOP セット、他は全クリア reg.csr0 = AM7990::CSR0_STOP; + ChangeInterrupt(); // CSR1, 2 は不定 // CSR3 はクリア reg.csr3 = 0; @@ -716,11 +718,8 @@ LanceDevice::SetInterrupt(uint32 bit) void LanceDevice::ChangeInterrupt() { - if (reg.IsINTR() && (reg.csr0 & AM7990::CSR0_INEA)) { - gInterrupt->AssertINT(this); - } else { - gInterrupt->NegateINT(this); - } + bool irq = (reg.IsINTR() && (reg.csr0 & AM7990::CSR0_INEA)); + interrupt->ChangeINT(this, irq); } // TXIDLE 送信アイドルフェーズ。 @@ -729,7 +728,7 @@ LanceDevice::ChangeInterrupt() // - 所有できない場合、TDMD オンなら即、 // オフなら 1.6ms 待ってから再び TXIDLE へ。 void -LanceDevice::TXIdle(Event& event) +LanceDevice::TXIdle(Event& ev) { tx_phase = TXPhase::IDLE; @@ -794,7 +793,7 @@ LanceDevice::TXCopy() uint8 *dst = &tx_packet[tx_packet.length]; tx_packet.length += copycnt; - // ここから、ZRAM からローカルの送信バッファにコピー + // ここから、SubRAM からローカルの送信バッファにコピー // XXX バーストコピー未対応 const uint32 srcend = src + bcnt; const uint8 *dstend = dst + copycnt; @@ -837,7 +836,7 @@ LanceDevice::TXCopy() src += 2; } - // tx_packet が一杯になったら後はディスクリプタが終わるまで ZRAM から + // tx_packet が一杯になったら後はディスクリプタが終わるまで SubRAM から // 読み捨てる。tx_packet の長さに上限があるのはこっち(エミュレータ)の // 都合であって LANCE はディスクリプタが終わるまで延々読み込んでは出力を // 続けるようだ。ここでは同じだけ読み込むところ、それにかかる時間を求める @@ -878,7 +877,7 @@ LanceDevice::TXCopy() // ただし ENP でなければアンダーフローによるパケット送信なのでフラグ処理。 // その後 TXNEXT フェーズへ。 void -LanceDevice::TXSend(Event& event) +LanceDevice::TXSend(Event& ev) { tx_phase = TXPhase::SEND; @@ -915,7 +914,7 @@ LanceDevice::TXSend(Event& event) // TXNEXT フェーズ。次のディスクリプタを指して TXIDLE へ。 void -LanceDevice::TXNext(Event& event) +LanceDevice::TXNext(Event& ev) { tx_phase = TXPhase::NEXT; @@ -939,7 +938,7 @@ LanceDevice::ChangePhase(TXPhase new_pha tx_event.time = time; switch (new_phase) { case TXPhase::STOP: - gScheduler->StopEvent(tx_event); + scheduler->StopEvent(tx_event); return; case TXPhase::IDLE: tx_event.func = ToEventCallback(&LanceDevice::TXIdle); @@ -953,7 +952,7 @@ LanceDevice::ChangePhase(TXPhase new_pha default: assertmsg(false, "phase %d", (int)new_phase); } - gScheduler->RestartEvent(tx_event); + scheduler->RestartEvent(tx_event); } // 受信フェーズ遷移図 @@ -962,7 +961,7 @@ LanceDevice::ChangePhase(TXPhase new_pha // | RXSTOP |<- - - (CSR0.STOP 書き込み / リセット) // +--------+ // : -// : +‥‥‥+ <‥‥ HostRxCallback (パケット受信) +// : +‥‥‥+ <‥‥ RxMessage (パケット受信) // v v : // +-------------+ : // +‥‥‥>| RXIDLE |‥‥+ Idle @@ -980,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 に戻ったところで処理される。 @@ -994,7 +993,7 @@ LanceDevice::HostRxCallback(MessageID ms // RXIDLE 受信アイドルフェーズ。 // (最初の)ディスクリプタを所有できるかポーリングする。 void -LanceDevice::RXIdle(Event& event) +LanceDevice::RXIdle(Event& ev) { rx_phase = RXPhase::IDLE; @@ -1138,7 +1137,7 @@ LanceDevice::RXCopy() // - 次のディスクリプタが所有できれば引き続き書き出すため RXCOPY へ。 // - 次のディスクリプタが所有できなければエラーにして RXIDLE へ。 void -LanceDevice::RXNext(Event& event) +LanceDevice::RXNext(Event& ev) { rx_phase = RXPhase::NEXT; @@ -1218,7 +1217,7 @@ LanceDevice::ChangePhase(RXPhase new_pha rx_event.time = time; switch (new_phase) { case RXPhase::STOP: - gScheduler->StopEvent(rx_event); + scheduler->StopEvent(rx_event); return; case RXPhase::IDLE: rx_event.func = ToEventCallback(&LanceDevice::RXIdle); @@ -1229,7 +1228,7 @@ LanceDevice::ChangePhase(RXPhase new_pha default: assertmsg(false, "phase %d", (int)new_phase); } - gScheduler->RestartEvent(rx_event); + scheduler->RestartEvent(rx_event); }