--- nono/vm/lance.h 2026/04/29 17:04:39 1.1.1.4 +++ nono/vm/lance.h 2026/04/29 17:05:38 1.1.1.15 @@ -4,14 +4,23 @@ // Licensed under nono-license.txt // +// +// Lance (AM7990) +// + #pragma once #include "ethernet.h" -#include "scheduler.h" +#include "event.h" +#include "hostnet.h" +#include "message.h" + +class InterruptDevice; +class SubRAMDevice; struct AM7990 { - int rap; // レジスタアドレス (0..3) + uint rap; // レジスタアドレス (0..3) // CSR0 static const uint16 CSR0_ERR = 0x8000; @@ -135,60 +144,55 @@ struct AM7990 bool IsBSWP() const { return (csr3 & CSR3_BSWP); } }; -class LanceDevice - : public EthernetDevice +class LanceDevice : public EthernetDevice, public IHWAddrFilter { using inherited = EthernetDevice; - public: - static const uint32 REQ_TXIDLE = 0x00000001; // ポーリングフェーズ - static const uint32 REQ_TXCOPY = 0x00000002; // バッファ読込フェーズ - static const uint32 REQ_TXSEND = 0x00000004; // 送信フェーズ - static const uint32 REQ_TXNEXT = 0x00000008; // TMD 更新フェーズ - static const uint32 REQ_RXIDLE = 0x00000010; // ポーリングフェーズ - static const uint32 REQ_RXCOPY = 0x00000020; // バッファ書込フェーズ - static const uint32 REQ_RXNEXT = 0x00000040; // RMD 更新フェーズ - static const uint32 REQ_RXMISS = 0x00000080; // 受信 MISS - static const uint32 REQ_RXRECV = 0x00000100; // 受信イベント - static const uint32 REQ_TERMINATE = 0x80000000; // スレッド終了指示 + + // 受信フェーズ + enum class RXPhase { + STOP = 0, // (動作していない) + IDLE, // ポーリング + COPY, // バッファ書き込み + NEXT, // RMD 更新 + MISS, // 受信ミス + }; + // 送信フェーズ + enum class TXPhase { + STOP = 0, // (動作していない) + IDLE, // ポーリング + COPY, // バッファ読み込み + SEND, // 送信 + NEXT, // TMD 更新 + }; public: LanceDevice(); ~LanceDevice() override; bool Init() override; - void ResetHard() override; + void ResetHard(bool poweron) override; - void MonitorUpdate(TextScreen&) override; + int HWAddrFilter(const MacAddr& dstaddr) const override; - // ワーカスレッド (エントリポイントから呼ばれる) - void ThreadRun(); - - // パケットを受信した (ホストネットワークスレッドから呼ばれる) - bool RecvPacket(qvector& buf) override; - - protected: // BusIO インタフェース + // (内蔵 ROM からのアクセス用に特別に public にしてある) + busdata WritePort(uint32 offset, uint32 data); + protected: static const uint32 NPORT = 2; - uint64 Read(uint32 addr); - uint64 Write(uint32 addr, uint32 data); - uint64 Peek(uint32 addr); + busdata ReadPort(uint32 offset); + busdata PeekPort(uint32 offset); private: - pthread_t thread; - bool thread_created = false; // スレッドが作成されたら true - - // スレッドの終了を指示 - void Terminate(); - + DECLARE_MONITOR_CALLBACK(MonitorUpdate); void MonitorReg(TextScreen&, int x, int y, uint32 data, const char * const * names); uint32 ReadData(); void WriteData(uint32 data); // メモリアクセス - uint64 ReadMem(uint32 paddr); - uint64 WriteMem(uint32 paddr, uint32 data); - uint64 PeekMem(uint32 paddr); + uint32 ReadMem(uint32 paddr); + void WriteMem(uint32 paddr, uint32 data); + uint32 PeekMem(uint32 paddr) const; void ChipInit(); void ChipStart(); @@ -196,19 +200,25 @@ class LanceDevice // 割り込み要因をセットし、許可されていれば割り込みを上げる void SetInterrupt(uint32 bit); - // 許可されていれば割り込みを上げる - void Interrupt(); + // 割り込み信号線の状態を変える + void ChangeInterrupt(); - void TXIdle(); + void TXIdle(Event&); void TXCopy(); - void TXSend(); - void TXNext(); - void RXIdle(); + void TXSend(Event&); + void TXNext(Event&); + + void RXIdle(Event&); void RXCopy(); - void RXNext(); - void RXRecv(); + void RXNext(Event&); void RXMiss(); - void Callback(int arg); + + // フェーズ遷移 + void ChangePhase(TXPhase new_phase, uint64 time = 100_nsec); + void ChangePhase(RXPhase new_phase, uint64 time = 100_nsec); + + // パケット受信通知 (HostNet から EthernetDevice 経由で呼ばれる) + void RxMessage(MessageID, uint32); const std::string BitToString(const char * const name[], uint16 bits); const std::string CSR0ToString(uint16 bits); @@ -225,25 +235,42 @@ class LanceDevice // Initialization Block uint16 initblock[12] {}; - uint32 rmd_base = 0; // 受信ディスクリプタの(ZRAM での)開始アドレス - int rmd_num = 0; // 受信ディスクリプタ数 - int rmd_cur = 0; // RMD 内の現在の注目インデックス - uint32 tmd_base = 0; // 送信ディスクリプタの(ZRAM での)開始アドレス - int tmd_num = 0; // 送信ディスクリプタ数 - int tmd_cur = 0; // TMD 内の現在の注目インデックス - - uint16 rmd1 = 0; // 現在の RMD1 - uint32 rmd1_ahead = 0; // 次の RMD1 先読み (負なら先読みしてない状態) - qvector rxq {}; // 受信バッファ - - uint16 tmd1 = 0; // 現在の TMD1 - uint32 tmd1_ahead = 0; // 次の TMD1 先読み (負なら先読みしてない状態) - std::vector txq {}; // 送信バッファ + MacAddr padr {}; + uint64 ladrf {}; + bool promisc {}; + + uint32 rmd_base {}; // 受信ディスクリプタの(SubRAMでの)開始アドレス + uint rmd_num {}; // 受信ディスクリプタ数 + uint rmd_cur {}; // RMD 内の現在の注目インデックス + uint32 tmd_base {}; // 送信ディスクリプタの(SubRAMでの)開始アドレス + uint tmd_num {}; // 送信ディスクリプタ数 + uint tmd_cur {}; // TMD 内の現在の注目インデックス + + uint16 rmd1 {}; // 現在の RMD1 + uint32 rmd1_ahead {}; // 次の RMD1 先読み (負なら先読みしてない状態) - // 待ち時間用イベント - Event rx_event {}; - Event tx_event {}; + uint16 tmd1 {}; // 現在の TMD1 + uint32 tmd1_ahead {}; // 次の TMD1 先読み (負なら先読みしてない状態) + + NetPacket rx_packet {}; // 受信バッファ + NetPacket tx_packet {}; // 送信バッファ + + RXPhase rx_phase {}; // 受信フェーズ + TXPhase tx_phase {}; // 送信フェーズ // 前回の TMD 状態文字列 (デバッグ表示用) std::string last_tmdstr {}; + + InterruptDevice *interrupt {}; + SubRAMDevice *subram {}; + + // 待ち時間用イベント + Event rx_event { this }; + Event tx_event { this }; + + Monitor *monitor {}; }; + +static inline LanceDevice *GetLanceDevice() { + return Object::GetObject(OBJ_ETHERNET(0)); +}