|
|
nono 1.7.0
//
// nono
// Copyright (C) 2023 nono project
// Licensed under nono-license.txt
//
//
// Nereid イーサネット (RTL8019AS)
//
#pragma once
#include "ethernet.h"
#include "hostnet.h"
#include "message.h"
class InterruptDevice;
struct RTL8019
{
// レジスタアドレスは $0-$f までの16個 x Page 0-3 の4ページなので、
// ここでのレジスタ番号は全部リニアに並べて表現する。
// Page0 はほとんどが Read/Write でレジスタが異なるが、
// それについてはここでは区別せず、Read/Write のコード中で使い分ける。
// Page0 R(/W)
static const uint32 CR = 0x00; // RW: Command Register
static const uint32 CLDA0 = 0x01; // R-: Current Local DMA Address Regs
static const uint32 CLDA1 = 0x02; // R-: Current Local DMA Address Regs
static const uint32 BNRY = 0x03; // RW: Boundary Register
static const uint32 TSR = 0x04; // R-: Transmit Status Register
static const uint32 NCR = 0x05; // R-: Number of Collisions Register
static const uint32 FIFO = 0x06; // R-: First In First Out Register
static const uint32 ISR = 0x07; // RW: Interrupt Status Register
static const uint32 CRDA0 = 0x08; // R-: Current Remote DMA Address Regs
static const uint32 CRDA1 = 0x09; // R-: Current Remote DMA Address Regs
static const uint32 ID0 = 0x0a; // R-: 8019ID0
static const uint32 ID1 = 0x0b; // R-: 8019ID1
static const uint32 RSR = 0x0c; // R-: Receive Configuration Register
static const uint32 CNTR0 = 0x0d; // R-: Frame Align.Error Tally Counter
static const uint32 CNTR1 = 0x0e; // R-: CRC Error Tally Counter Reg.
static const uint32 CNTR2 = 0x0f; // R-: Missed Pakcet Tally Counter Reg.
// Page0 W
static const uint32 PSTART = 0x01; // -W: Page Start Register
static const uint32 PSTOP = 0x02; // -W: Page Stop Register
static const uint32 TPSR = 0x04; // -W: Transmit Page Start Register
static const uint32 TBCR0 = 0x05; // -W: Transmit Byte Counter Registers
static const uint32 TBCR1 = 0x06; // -W: Transmit Byte Counter Registers
static const uint32 RSAR0 = 0x08; // -W: Remote Start Address Regs
static const uint32 RSAR1 = 0x09; // -W: Remote Start Address Regs
static const uint32 RBCR0 = 0x0a; // -W: Remote Byte Count Registers
static const uint32 RBCR1 = 0x0b; // -W: Remote Byte Count Registers
static const uint32 RCR = 0x0c; // -W: Receive Configuration Register
static const uint32 TCR = 0x0d; // -W: Transmit Configuration Register
static const uint32 DCR = 0x0e; // -W: Data Configuration Register
static const uint32 IMR = 0x0f; // -W: Interrupt Mask Register
// Page 1 R/W
static const uint32 CR_1 = 0x10;
static const uint32 PAR0 = 0x11; // RW: Physical Address Registers
static const uint32 PAR1 = 0x12; // RW: Physical Address Registers
static const uint32 PAR2 = 0x13; // RW: Physical Address Registers
static const uint32 PAR3 = 0x14; // RW: Physical Address Registers
static const uint32 PAR4 = 0x15; // RW: Physical Address Registers
static const uint32 PAR5 = 0x16; // RW: Physical Address Registers
static const uint32 CURR = 0x17; // RW: Current Page Register
static const uint32 MAR0 = 0x18; // RW: Multicast Address Registers
static const uint32 MAR1 = 0x19; // RW: Multicast Address Registers
static const uint32 MAR2 = 0x1a; // RW: Multicast Address Registers
static const uint32 MAR3 = 0x1b; // RW: Multicast Address Registers
static const uint32 MAR4 = 0x1c; // RW: Multicast Address Registers
static const uint32 MAR5 = 0x1d; // RW: Multicast Address Registers
static const uint32 MAR6 = 0x1e; // RW: Multicast Address Registers
static const uint32 MAR7 = 0x1f; // RW: Multicast Address Registers
// Page2 R
static const uint32 CR_2 = 0x20;
static const uint32 PSTART_2= 0x21;
static const uint32 PSTOP_2 = 0x22;
static const uint32 TPSR_2 = 0x24;
static const uint32 RCR_2 = 0x2c;
static const uint32 TCR_2 = 0x2d;
static const uint32 DCR_2 = 0x2e;
static const uint32 IMR_2 = 0x2f;
// Page3 R/W
static const uint32 CR_3 = 0x30;
static const uint32 CR9346 = 0x31; // RW: 9346 Command Register
static const uint32 BPAGE = 0x32; // RW: BROM Page Register
static const uint32 CONFIG0 = 0x33; // R-: RTL8019AS Config. Register 0
static const uint32 CONFIG1 = 0x34; // RW: RTL8019AS Config. Register 1
static const uint32 CONFIG2 = 0x35; // RW: RTL8019AS Config. Register 2
static const uint32 CONFIG3 = 0x36; // RW: RTL8019AS Config. Register 3
static const uint32 TEST = 0x37; // -W:
static const uint32 CSNSAV = 0x38; // R-: CSN Save Register (For PnP)
static const uint32 HLTCLK = 0x39; // -W: Halt Clock Register
static const uint32 INTR = 0x3b; // R-: Interrupt Register
static const uint32 FMWP = 0x3c; // -W: Flush Memory Write Protect Reg.
static const uint32 CONFIG4 = 0x3d; // R-: RTL8019AS Config. Register 4
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// CR | PS | RD | TXP | STA | STP |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 CR_RD_READ = 0x08;
static const uint32 CR_RD_WRITE = 0x10;
static const uint32 CR_RD_SEND = 0x18;
static const uint32 CR_TXP = 0x04;
static const uint32 CR_STA = 0x02;
static const uint32 CR_STP = 0x01;
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// TSR | OWC | CDH | 0 | CRS | ABT | COL | 1 | PTX |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 TSR_OWC = 0x80; // Out of Window Collision
static const uint32 TSR_CDH = 0x40; // CD Heartbeat
static const uint32 TSR_CRS = 0x10; // Carrier Sense lost bit
static const uint32 TSR_ABT = 0x08; // Abort TX due to excessive coll.
static const uint32 TSR_COL = 0x04; // TX collied with other station
static const uint32 TSR_PTX = 0x01; // TX completes with no errors
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// ISR | RST | RDC | CNT | OVW | TXE | RXE | PTX | PRX |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 ISR_RST = 0x80; // Enter reset state
static const uint32 ISR_RDC = 0x40; // Remote DMA operation completed
static const uint32 ISR_CNT = 0x20; //
static const uint32 ISR_OVW = 0x10; // RX buffer overflow
static const uint32 ISR_TXE = 0x08; // TX Error
static const uint32 ISR_RXE = 0x04; // RX Error
static const uint32 ISR_PTX = 0x02; // Packet transmitted with no errors
static const uint32 ISR_PRX = 0x01; // Packet received with no errors
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// RSR | DFR | DIS | PHY | MPA | 0 | FAE | CRC | PRX |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 RSR_DFR = 0x80; // Deffering
static const uint32 RSR_DIS = 0x40; // Receiver Disabled
static const uint32 RSR_PHY = 0x20; // Recv'd packet is multi/broadcast
static const uint32 RSR_MPA = 0x10; // Missed Packet
static const uint32 RSR_FAE = 0x04; // Frame Alignment Error
static const uint32 RSR_CRC = 0x02; // CRC Error
static const uint32 RSR_PRX = 0x01; // Packet received with no errors
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// RCR | 1 | 1 | MON | PRO | AM | AB | AR | SEP |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 RCR_MON = 0x20; // Monitor mode
static const uint32 RCR_PRO = 0x10; // Promisc.
static const uint32 RCR_AM = 0x08; // Accept multicast dest address
static const uint32 RCR_AB = 0x04; // Accept broadcast dest address
static const uint32 RCR_AR = 0x02; // Accept <64bytes
static const uint32 RCR_SEP = 0x01; // Accept packet with recv errors
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// TCR | 1 | 1 | 1 |OFST | ATD | LB | CRC |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 TCR_OFST = 0x10; // Collision Offset Enable
static const uint32 TCR_ATD = 0x08; // Auto Transmit Disable
static const uint32 TCR_LB_MASK = 0x06; // Loopback mode
static const uint32 TCR_CRC = 0x01; // Don't append CRC
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// DCR | 1 | FT | ARM | LS | LAS | BOS | WTS |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 DCR_FT_MASK = 0x60; // FIFO threshold
static const uint32 DCR_ARM = 0x10; // Auto initialize Remote
static const uint32 DCR_LS = 0x08; // Loopback Select
static const uint32 DCR_LAS = 0x04; // (32bit DMA not supported by NIC)
static const uint32 DCR_BOS = 0x02; // Byte Order Select (Not Impl?)
static const uint32 DCR_WTS = 0x01; // Word Transfer Select
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// 9346CR | EEM | not used |EECS |EESK |EEDI |EEDO |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 CR9346_EEM_MASK = 0xc0; // RTL8019AS operating mode
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// CONFIG0 | VERID | AUI |PNPJP| JP | BNC | 0 | 0 |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 CONFIG0_VERID_MASK = 0xc0;
static const uint32 CONFIG0_AUI = 0x20;
static const uint32 CONFIG0_PNPJP = 0x10;
static const uint32 CONFIG0_JP = 0x08;
static const uint32 CONFIG0_BNC = 0x04;
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// CONFIG1 |IRQEN| IRQS | IOS |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 CONFIG1_IRQEN = 0x80;
static const uint32 CONFIG1_IRQS_MASK = 0x70;
static const uint32 CONFIG1_IOS_MASK = 0x0f;
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// CONFIG2 | PL |BSELB| BS |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 CONFIG2_PL_MASK = 0xc0;
static const uint32 CONFIG2_BSELB = 0x20;
static const uint32 CONFIG2_BS = 0x1f;
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// CONFIG3 | PNP |FUDUP|LEDS1|LEDS0| 0 |SLEEP|PWRDN|ACTB |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 CONFIG3_PNP = 0x80;
static const uint32 CONFIG3_FUDUP = 0x40;
static const uint32 CONFIG3_LEDS1 = 0x20;
static const uint32 CONFIG3_LEDS0 = 0x10;
static const uint32 CONFIG3_SLEEP = 0x04;
static const uint32 CONFIG3_PWRDN = 0x02;
static const uint32 CONFIG3_ACTB = 0x01;
// 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// CONFIG4 | - | - | - | - | - | - | - |IOMS |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static const uint32 CONFIG4_IOMS = 0x01;
// メディアタイプ (CONFIG2)
enum {
MediaType_10BaseT_Auto = 0,
MediaType_10BaseT = 1,
MediaType_10Base5 = 2,
MediaType_10Base2 = 3,
};
};
class RTL8019ASDevice : public EthernetDevice, public IHWAddrFilter
{
using inherited = EthernetDevice;
// 動作状態 (数値比較も行うことに注意)
enum class State {
Normal = 0, // 送受信可能
Stop = 1, // STP
StopInProgress = 2, // STP へ移行中 (処理中の送受信のみ継続)
};
// DMA 状態?
enum class DMAMode {
NotAllowed = 0,
RemoteRead = 1,
RemoteWrite = 2,
SendPacket = 3,
Complete = 4,
};
public:
RTL8019ASDevice(uint n_, int vector_);
~RTL8019ASDevice() override;
bool Init() override;
void ResetHard(bool poweron) override;
busdata Read(busaddr addr) override;
busdata Write(busaddr addr, uint32 data) override;
busdata Peek1(uint32 addr) override;
busdata InterruptAcknowledge();
int HWAddrFilter(const MacAddr& dstaddr) const override;
private:
static inline uint32 Decoder(uint32 addr);
uint32 ReadReg(uint32 rn);
uint32 ReadDMA8(uint32 a0);
uint32 ReadDMA16();
void WriteReg(uint32 rn, uint32 data);
void WriteCR(uint32 data);
void WritePSTART(uint32 data);
void WritePSTOP(uint32 data);
void WriteBNRY(uint32 data);
void WriteTPSR(uint32 data);
void WriteTBCR0(uint32 data);
void WriteTBCR1(uint32 data);
void WriteISR(uint32 data);
void WriteRSAR0(uint32 data);
void WriteRSAR1(uint32 data);
void WriteRBCR0(uint32 data);
void WriteRBCR1(uint32 data);
void WriteRCR(uint32 data);
void WriteTCR(uint32 data);
void WriteDCR(uint32 data);
void WriteIMR(uint32 data);
void WritePAR(uint n, uint32 data);
void WriteCURR(uint32 data);
void WriteMAR(uint n, uint32 data);
void Write9346CR(uint32 data);
void WriteCONFIG0(uint32 data);
void WriteCONFIG1(uint32 data);
void WriteCONFIG2(uint32 data);
void WriteCONFIG3(uint32 data);
void WriteDMA8(uint32 data);
void WriteDMA16(uint32 data);
uint32 PeekReg(uint32 rn) const;
uint32 PeekCR() const;
uint32 PeekCLDA() const;
uint32 PeekBNRY() const;
uint32 PeekTSR() const;
uint32 PeekNCR() const;
uint32 PeekFIFO() const;
uint32 PeekISR() const;
uint32 PeekCRDA() const;
uint32 Peek8019ID0() const;
uint32 Peek8019ID1() const;
uint32 PeekRSR() const;
uint32 PeekCNTR(int n) const;
uint32 PeekPAR(int n) const;
uint32 PeekCURR() const;
uint32 PeekMAR(int n) const;
uint32 PeekPSTART() const;
uint32 PeekPSTOP() const;
uint32 PeekTPSR() const;
uint32 PeekRCR() const;
uint32 PeekTCR() const;
uint32 PeekDCR() const;
uint32 PeekIMR() const;
uint32 Peek9346CR() const;
uint32 PeekBPAGE() const;
uint32 PeekCONFIG0() const;
uint32 PeekCONFIG1() const;
uint32 PeekCONFIG2() const;
uint32 PeekCONFIG3() const;
uint32 PeekCONFIG4() const;
uint32 PeekCSNSAV() const;
uint32 PeekReg39() const;
uint32 PeekINTR() const;
uint32 PeekDMA(uint32 a0) const;
DECLARE_MONITOR_SCREEN(MonitorScreen);
void MonitorReg(TextScreen&, int, int, uint32, const char * const *names);
void Reset();
void ChangeInterrupt();
// DMA 処理の下請け
void ReadDMAlog(uint32 addr, uint32 data, int width);
void PostDMA();
// 内蔵空間アクセス
inline uint32 ReadPROM(uint32 addr) const;
inline uint32 ReadRAM(uint32 addr) const;
inline void WriteRAM(uint32 addr, uint32 data);
// 状態
bool IsStopOrInProgress() const;
void ChangeState(State newstate);
// 送信
void Transmit();
void TXEvent(Event *);
// 受信
void RxMessage(MessageID msgid, uint32 arg);
void RXEvent(Event *);
void RXHead();
void RXCopy(Event *, uint remain);
void RXDone(Event *);
void TXLedEvent(Event *);
void RXLedEvent(Event *);
void IncCounter(int n);
// レジスタ名を返す
static std::string RegNameR(int rn);
static std::string RegNameW(int rn);
static const char *GetDMAName(uint32);
// 動作状態
// ハードウェアリセット(解除?)後、STA が発行されるまではリセット状態。
// STP が発行されたら、仕掛りの送受信を終えたところでリセット状態に入る。
// リセット状態に入ると ISR:RST が立つ。
// このリセット状態をここでは Stop 状態と呼ぶ。
State state {};
// 送信処理中なら true
// (受信処理中の方は rx_packet.length != 0 で判定する)
bool tx_in_progress {};
// CR: ページ番号 (をあらかじめオフセットしたもの)
uint32 pagesel {};
// CR_RD: DMA 状態?
DMAMode dmamode {};
bool cr_sta {};
// 割り込みフラグ (bit7 は 0 にすること)
uint32 intr_stat {};
// 割り込みマスク (bit7 は 0 にすること)
uint32 intr_mask {};
// 割り込みベクタ (NereidBoardDevice から渡される)
uint32 intr_vector {};
uint32 tsr {};
uint32 rsr {}; // DIS 以外のビットを保持
// RCR: モニタモード
bool monitor_mode {};
bool promisc_mode {};
bool accept_mcast {};
bool accept_bcast {};
bool accept_short {};
bool accept_error {};
// TCR
uint32 tcr {};
// DCR
bool word_transfer {};
uint32 dcr {}; // それ以外のビット
// 折り返しを計算しなくて済むように uint16 にしておく。
// またレジスタイメージがバイト単位かページ単位かに関わらず、
// すべてバイト単位で統一。
uint16 remote_addr {}; // RSAR/CRDA: 現在のアクセス位置
uint16 remote_count {}; // RBCR: 残り転送バイト数
uint16 remote_start_addr {}; // DMA 開始時の位置 (ログ用)
uint16 remote_start_count {}; // DMA 開始時の残り転送バイト数 (ログ用)
uint16 transmit_page_start_addr {}; // TPSR
uint16 transmit_byte_count {}; // TBCR
uint16 pstart_addr {}; // PSTART
uint16 pstop_addr {}; // PSTOP
uint16 boundary_addr {}; // BNRY
uint16 current_page_addr {}; // CURR: 受信開始位置
uint16 local_addr {}; // CLDA: 書き込み位置
uint16 next_page_addr {}; // 次パケットの受信開始位置
MacAddr par {};
uint64 mar {};
std::array<uint8, 3> error_counter {};
// 9346CR
bool config_write_enable {};
// CONFIG
uint32 verid {};
bool irq_enable {};
uint32 mediatype {};
bool brom_force_disable {};
uint32 config3 {};
// バッファ (16KB 固定)
std::array<uint8, 16384> buffer {};
// PROM (実質 16 バイト)
std::array<uint8, 16> prom {};
NetPacket tx_packet {};
NetPacket rx_packet {};
// LED (true で点灯)
bool tx_led {};
bool rx_led {};
Monitor *monitor {};
Event *tx_event {};
Event *rx_event {};
Event *txled_event {};
Event *rxled_event {};
InterruptDevice *interrupt {};
static const char * const regnames[];
};
inline RTL8019ASDevice *GetRTL8019ASDevice(int n) {
return Object::GetObject<RTL8019ASDevice>(OBJ_ETHERNET(n));
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.