bigmac: support more registers.

This commit is contained in:
Maxim Poliakovski 2023-09-22 00:09:17 +02:00
parent 9db3076a48
commit 5f48a3ab5b
2 changed files with 152 additions and 1 deletions

View File

@ -30,6 +30,13 @@ BigMac::BigMac(uint8_t id) {
supports_types(HWCompType::MMIO_DEV | HWCompType::ETHER_MAC); supports_types(HWCompType::MMIO_DEV | HWCompType::ETHER_MAC);
this->chip_id = id; this->chip_id = id;
this->chip_reset();
}
void BigMac::chip_reset() {
this->event_mask = 0xFFFFU; // disable HW events causing on-chip interrupts
this->stat = 0;
this->phy_reset(); this->phy_reset();
this->mii_reset(); this->mii_reset();
this->srom_reset(); this->srom_reset();
@ -37,12 +44,38 @@ BigMac::BigMac(uint8_t id) {
uint16_t BigMac::read(uint16_t reg_offset) { uint16_t BigMac::read(uint16_t reg_offset) {
switch (reg_offset) { switch (reg_offset) {
case BigMacReg::XIFC:
return this->tx_if_ctrl;
case BigMacReg::CHIP_ID: case BigMacReg::CHIP_ID:
return this->chip_id; return this->chip_id;
case BigMacReg::MIF_CSR: case BigMacReg::MIF_CSR:
return (this->mif_csr_old & ~Mif_Data_In) | (this->mii_in_bit << 3); return (this->mif_csr_old & ~Mif_Data_In) | (this->mii_in_bit << 3);
case BigMacReg::GLOB_STAT: {
uint16_t old_stat = this->stat;
this->stat = 0; // clear-on-read
return old_stat;
}
case BigMacReg::EVENT_MASK:
return this->event_mask;
case BigMacReg::SROM_CSR: case BigMacReg::SROM_CSR:
return (this->srom_csr_old & ~Srom_Data_In) | (this->srom_in_bit << 2); return (this->srom_csr_old & ~Srom_Data_In) | (this->srom_in_bit << 2);
case BigMacReg::TX_SW_RST:
return this->tx_reset;
case BigMacReg::TX_CONFIG:
return this->tx_config;
case BigMacReg::PEAK_ATT: {
uint8_t old_val = this->peak_attempts;
this->peak_attempts = 0; // clear-on-read
return old_val;
}
case BigMacReg::NC_CNT:
return this->norm_coll_cnt;
case BigMacReg::EX_CNT:
return this->excs_coll_cnt;
case BigMacReg::LT_CNT:
return this->late_coll_cnt;
case BigMacReg::RX_CONFIG:
return this->rx_config;
default: default:
LOG_F(WARNING, "%s: unimplemented register at 0x%X", this->name.c_str(), LOG_F(WARNING, "%s: unimplemented register at 0x%X", this->name.c_str(),
reg_offset); reg_offset);
@ -53,6 +86,20 @@ uint16_t BigMac::read(uint16_t reg_offset) {
void BigMac::write(uint16_t reg_offset, uint16_t value) { void BigMac::write(uint16_t reg_offset, uint16_t value) {
switch (reg_offset) { switch (reg_offset) {
case BigMacReg::XIFC:
this->tx_if_ctrl = value;
break;
case BigMacReg::TX_FIFO_CSR:
this->tx_fifo_enable = !!(value & 1);
this->tx_fifo_size = (((value >> 1) & 0xFF) + 1) << 7;
break;
case BigMacReg::TX_FIFO_TH:
this->tx_fifo_tresh = value;
break;
case BigMacReg::RX_FIFO_CSR:
this->rx_fifo_enable = !!(value & 1);
this->rx_fifo_size = (((value >> 1) & 0xFF) + 1) << 7;
break;
case BigMacReg::MIF_CSR: case BigMacReg::MIF_CSR:
if (value & Mif_Data_Out_En) { if (value & Mif_Data_Out_En) {
// send bits one by one on each low-to-high transition of Mif_Clock // send bits one by one on each low-to-high transition of Mif_Clock
@ -64,6 +111,9 @@ void BigMac::write(uint16_t reg_offset, uint16_t value) {
} }
this->mif_csr_old = value; this->mif_csr_old = value;
break; break;
case BigMacReg::EVENT_MASK:
this->event_mask = value;
break;
case BigMacReg::SROM_CSR: case BigMacReg::SROM_CSR:
if (value & Srom_Chip_Select) { if (value & Srom_Chip_Select) {
// exchange data on each low-to-high transition of Srom_Clock // exchange data on each low-to-high transition of Srom_Clock
@ -80,11 +130,58 @@ void BigMac::write(uint16_t reg_offset, uint16_t value) {
this->tx_reset = 0; // acknowledge SW reset this->tx_reset = 0; // acknowledge SW reset
} }
break; break;
case BigMacReg::TX_CONFIG:
this->tx_config = value;
break;
case BigMacReg::NC_CNT:
this->norm_coll_cnt = value;
break;
case BigMacReg::NT_CNT:
this->net_coll_cnt = value;
break;
case BigMacReg::EX_CNT:
this->excs_coll_cnt = value;
break;
case BigMacReg::LT_CNT:
this->late_coll_cnt = value;
break;
case BigMacReg::RNG_SEED:
this->rng_seed = value;
break;
case BigMacReg::RX_SW_RST: case BigMacReg::RX_SW_RST:
if (!value) { if (!value) {
LOG_F(INFO, "%s: receiver soft reset asserted", this->name.c_str()); LOG_F(INFO, "%s: receiver soft reset asserted", this->name.c_str());
} }
break; break;
case BigMacReg::RX_CONFIG:
this->rx_config = value;
break;
case BigMacReg::MAC_ADDR_0:
case BigMacReg::MAC_ADDR_1:
case BigMacReg::MAC_ADDR_2:
this->mac_addr_flt[8 - ((reg_offset >> 4) & 0xF)] = value;
break;
case BigMacReg::RX_FRM_CNT:
this->rcv_frame_cnt = value;
break;
case BigMacReg::RX_LE_CNT:
this->len_err_cnt = value;
break;
case BigMacReg::RX_AE_CNT:
this->align_err_cnt = value;
break;
case BigMacReg::RX_FE_CNT:
this->fcs_err_cnt = value;
break;
case BigMacReg::RX_CVE_CNT:
this->cv_err_cnt = value;
break;
case BigMacReg::HASH_TAB_0:
case BigMacReg::HASH_TAB_1:
case BigMacReg::HASH_TAB_2:
case BigMacReg::HASH_TAB_3:
this->hash_table[(reg_offset >> 4) & 3] = value;
break;
default: default:
LOG_F(WARNING, "%s: unimplemented register at 0x%X is written with 0x%X", LOG_F(WARNING, "%s: unimplemented register at 0x%X is written with 0x%X",
this->name.c_str(), reg_offset, value); this->name.c_str(), reg_offset, value);

View File

@ -37,11 +37,37 @@ enum EthernetCellId : uint8_t {
/* BigMac HW registers. */ /* BigMac HW registers. */
enum BigMacReg : uint16_t { enum BigMacReg : uint16_t {
XIFC = 0x000, // transceiver interface control
TX_FIFO_CSR = 0x100,
TX_FIFO_TH = 0x110,
RX_FIFO_CSR = 0x120,
CHIP_ID = 0x170, CHIP_ID = 0x170,
MIF_CSR = 0x180, MIF_CSR = 0x180,
GLOB_STAT = 0x200, // Apple: kSTAT, Sun: Global Status Register
EVENT_MASK = 0x210, // ambiguously called INT_DISABLE in the Apple source
SROM_CSR = 0x190, SROM_CSR = 0x190,
TX_SW_RST = 0x420, TX_SW_RST = 0x420,
TX_CONFIG = 0x430,
PEAK_ATT = 0x4E0, // Apple: kPAREG, Sun: PeakAttempts Register
NC_CNT = 0x500, // Normal Collision Counter
NT_CNT = 0x510, // Apple: Network Collision Counter
EX_CNT = 0x520, // Excessive Collision Counter
LT_CNT = 0x530, // Late Collision Counter
RNG_SEED = 0x540,
RX_SW_RST = 0x620, RX_SW_RST = 0x620,
RX_CONFIG = 0x630,
MAC_ADDR_2 = 0x660,
MAC_ADDR_1 = 0x670,
MAC_ADDR_0 = 0x680,
RX_FRM_CNT = 0x690, // Receive Frame Counter
RX_LE_CNT = 0x6A0, // Length Error Counter
RX_AE_CNT = 0x6B0, // Alignment Error Counter
RX_FE_CNT = 0x6C0, // FCS Error Counter
RX_CVE_CNT = 0x6E0, // Code Violation Error Counter
HASH_TAB_3 = 0x700,
HASH_TAB_2 = 0x710,
HASH_TAB_1 = 0x720,
HASH_TAB_0 = 0x730,
}; };
/* MIF_CSR bit definitions. */ /* MIF_CSR bit definitions. */
@ -107,6 +133,9 @@ public:
uint16_t read(uint16_t reg_offset); uint16_t read(uint16_t reg_offset);
void write(uint16_t reg_offset, uint16_t value); void write(uint16_t reg_offset, uint16_t value);
protected:
void chip_reset();
// MII methods // MII methods
bool mii_rcv_value(uint16_t& var, uint8_t num_bits, uint8_t next_bit); bool mii_rcv_value(uint16_t& var, uint8_t num_bits, uint8_t next_bit);
void mii_rcv_bit(); void mii_rcv_bit();
@ -127,7 +156,32 @@ private:
uint8_t chip_id; // BigMac Chip ID uint8_t chip_id; // BigMac Chip ID
// BigMac state // BigMac state
uint16_t tx_reset = 0; uint16_t tx_reset = 0; // self-clearing one-bit register
uint16_t tx_if_ctrl = 0;
uint16_t rng_seed;
uint16_t norm_coll_cnt = 0;
uint16_t net_coll_cnt = 0;
uint16_t excs_coll_cnt = 0;
uint16_t late_coll_cnt = 0;
uint16_t rcv_frame_cnt = 0;
uint8_t len_err_cnt = 0;
uint8_t align_err_cnt = 0;
uint8_t fcs_err_cnt = 0;
uint8_t cv_err_cnt = 0;
uint8_t peak_attempts = 0;
uint8_t tx_fifo_tresh = 0;
bool tx_fifo_enable = false;
bool rx_fifo_enable = false;
uint16_t tx_fifo_size = 0;
uint16_t rx_fifo_size = 0;
uint16_t hash_table[4] = {};
uint16_t mac_addr_flt[3] = {};
uint16_t tx_config = 0;
uint16_t rx_config = 0;
// Interrupt state
uint16_t event_mask = 0xFFFFU; // inverted mask: 0 - enabled, 1 - disabled
uint16_t stat = 0;
// MII state // MII state
uint8_t mif_csr_old = 0; uint8_t mif_csr_old = 0;