| #ifndef _REALTEK_H |
| #define _REALTEK_H |
| |
| /** @file |
| * |
| * Realtek 10/100/1000 network card driver |
| * |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); |
| |
| #include <ipxe/spi.h> |
| #include <ipxe/spi_bit.h> |
| #include <ipxe/nvo.h> |
| #include <ipxe/if_ether.h> |
| |
| /** PCI memory BAR size */ |
| #define RTL_BAR_SIZE 0x100 |
| |
| /** A packet descriptor */ |
| struct realtek_descriptor { |
| /** Buffer size */ |
| uint16_t length; |
| /** Flags */ |
| uint16_t flags; |
| /** Reserved */ |
| uint32_t reserved; |
| /** Buffer address */ |
| uint64_t address; |
| } __attribute__ (( packed )); |
| |
| /** Descriptor buffer size mask */ |
| #define RTL_DESC_SIZE_MASK 0x3fff |
| |
| /** Packet descriptor flags */ |
| enum realtek_descriptor_flags { |
| /** Descriptor is owned by NIC */ |
| RTL_DESC_OWN = 0x8000, |
| /** End of descriptor ring */ |
| RTL_DESC_EOR = 0x4000, |
| /** First segment descriptor */ |
| RTL_DESC_FS = 0x2000, |
| /** Last segment descriptor */ |
| RTL_DESC_LS = 0x1000, |
| /** Receive error summary */ |
| RTL_DESC_RES = 0x0020, |
| }; |
| |
| /** Descriptor ring alignment */ |
| #define RTL_RING_ALIGN 256 |
| |
| /** A legacy mode receive packet header */ |
| struct realtek_legacy_header { |
| /** Status */ |
| uint16_t status; |
| /** Length */ |
| uint16_t length; |
| /** Packet data */ |
| uint8_t data[0]; |
| } __attribute__ (( packed )); |
| |
| /** Legacy mode status bits */ |
| enum realtek_legacy_status { |
| /** Received OK */ |
| RTL_STAT_ROK = 0x0001, |
| }; |
| |
| /** ID Register 0 (6 bytes) */ |
| #define RTL_IDR0 0x00 |
| |
| /** Multicast Register 0 (dword) */ |
| #define RTL_MAR0 0x08 |
| |
| /** Multicast Register 4 (dword) */ |
| #define RTL_MAR4 0x0c |
| |
| /** Transmit Status of Descriptor N (dword, 8139 only) */ |
| #define RTL_TSD(n) ( 0x10 + 4 * (n) ) |
| #define RTL_TSD_ERTXTH(x) ( (x) << 16 ) /**< Early TX threshold */ |
| #define RTL_TSD_ERTXTH_DEFAULT RTL_TSD_ERTXTH ( 256 / 32 ) |
| #define RTL_TSD_OWN 0x00002000UL /**< Ownership */ |
| |
| /** Transmit Start Address of Descriptor N (dword, 8139 only) */ |
| #define RTL_TSAD(n) ( 0x20 + 4 * (n) ) |
| |
| /** Transmit Normal Priority Descriptors (qword) */ |
| #define RTL_TNPDS 0x20 |
| |
| /** Number of transmit descriptors |
| * |
| * This is a hardware limit when using legacy mode. |
| */ |
| #define RTL_NUM_TX_DESC 4 |
| |
| /** Receive Buffer Start Address (dword, 8139 only) */ |
| #define RTL_RBSTART 0x30 |
| |
| /** Receive buffer length */ |
| #define RTL_RXBUF_LEN 8192 |
| |
| /** Receive buffer padding */ |
| #define RTL_RXBUF_PAD 2038 /* Allow space for WRAP */ |
| |
| /** Receive buffer alignment */ |
| #define RTL_RXBUF_ALIGN 16 |
| |
| /** Command Register (byte) */ |
| #define RTL_CR 0x37 |
| #define RTL_CR_RST 0x10 /**< Reset */ |
| #define RTL_CR_RE 0x08 /**< Receiver Enable */ |
| #define RTL_CR_TE 0x04 /**< Transmit Enable */ |
| #define RTL_CR_BUFE 0x01 /**< Receive buffer empty */ |
| |
| /** Maximum time to wait for a reset, in milliseconds */ |
| #define RTL_RESET_MAX_WAIT_MS 100 |
| |
| /** Current Address of Packet Read (word, 8139 only) */ |
| #define RTL_CAPR 0x38 |
| |
| /** Transmit Priority Polling Register (byte, 8169 only) */ |
| #define RTL_TPPOLL_8169 0x38 |
| #define RTL_TPPOLL_NPQ 0x40 /**< Normal Priority Queue Polling */ |
| |
| /** Interrupt Mask Register (word) */ |
| #define RTL_IMR 0x3c |
| #define RTL_IRQ_PUN_LINKCHG 0x0020 /**< Packet underrun / link change */ |
| #define RTL_IRQ_TER 0x0008 /**< Transmit error */ |
| #define RTL_IRQ_TOK 0x0004 /**< Transmit OK */ |
| #define RTL_IRQ_RER 0x0002 /**< Receive error */ |
| #define RTL_IRQ_ROK 0x0001 /**< Receive OK */ |
| |
| /** Interrupt Status Register (word) */ |
| #define RTL_ISR 0x3e |
| |
| /** Transmit (Tx) Configuration Register (dword) */ |
| #define RTL_TCR 0x40 |
| #define RTL_TCR_MXDMA(x) ( (x) << 8 ) /**< Max DMA burst size */ |
| #define RTL_TCR_MXDMA_MASK RTL_TCR_MXDMA ( 0x7 ) |
| #define RTL_TCR_MXDMA_DEFAULT RTL_TCR_MXDMA ( 0x7 /* Unlimited */ ) |
| |
| /** Receive (Rx) Configuration Register (dword) */ |
| #define RTL_RCR 0x44 |
| #define RTL_RCR_STOP_WORKING 0x01000000UL /**< Here be dragons */ |
| #define RTL_RCR_RXFTH(x) ( (x) << 13 ) /**< Receive FIFO threshold */ |
| #define RTL_RCR_RXFTH_MASK RTL_RCR_RXFTH ( 0x7 ) |
| #define RTL_RCR_RXFTH_DEFAULT RTL_RCR_RXFTH ( 0x7 /* Whole packet */ ) |
| #define RTL_RCR_RBLEN(x) ( (x) << 11 ) /**< Receive buffer length */ |
| #define RTL_RCR_RBLEN_MASK RTL_RCR_RBLEN ( 0x3 ) |
| #define RTL_RCR_RBLEN_DEFAULT RTL_RCR_RBLEN ( 0 /* 8kB */ ) |
| #define RTL_RCR_MXDMA(x) ( (x) << 8 ) /**< Max DMA burst size */ |
| #define RTL_RCR_MXDMA_MASK RTL_RCR_MXDMA ( 0x7 ) |
| #define RTL_RCR_MXDMA_DEFAULT RTL_RCR_MXDMA ( 0x7 /* Unlimited */ ) |
| #define RTL_RCR_WRAP 0x00000080UL /**< Overrun receive buffer */ |
| #define RTL_RCR_9356SEL 0x00000040UL /**< EEPROM is a 93C56 */ |
| #define RTL_RCR_AB 0x00000008UL /**< Accept broadcast packets */ |
| #define RTL_RCR_AM 0x00000004UL /**< Accept multicast packets */ |
| #define RTL_RCR_APM 0x00000002UL /**< Accept physical match */ |
| #define RTL_RCR_AAP 0x00000001UL /**< Accept all packets */ |
| |
| /** 93C46 (93C56) Command Register (byte) */ |
| #define RTL_9346CR 0x50 |
| #define RTL_9346CR_EEM(x) ( (x) << 6 ) /**< Mode select */ |
| #define RTL_9346CR_EEM_EEPROM RTL_9346CR_EEM ( 0x2 ) /**< EEPROM mode */ |
| #define RTL_9346CR_EEM_NORMAL RTL_9346CR_EEM ( 0x0 ) /**< Normal mode */ |
| #define RTL_9346CR_EECS 0x08 /**< Chip select */ |
| #define RTL_9346CR_EESK 0x04 /**< Clock */ |
| #define RTL_9346CR_EEDI 0x02 /**< Data in */ |
| #define RTL_9346CR_EEDO 0x01 /**< Data out */ |
| |
| /** Word offset of ID code word within EEPROM */ |
| #define RTL_EEPROM_ID ( 0x00 / 2 ) |
| |
| /** EEPROM code word magic value */ |
| #define RTL_EEPROM_ID_MAGIC 0x8129 |
| |
| /** Word offset of MAC address within EEPROM */ |
| #define RTL_EEPROM_MAC ( 0x0e / 2 ) |
| |
| /** Word offset of VPD / non-volatile options within EEPROM */ |
| #define RTL_EEPROM_VPD ( 0x40 / 2 ) |
| |
| /** Length of VPD / non-volatile options within EEPROM */ |
| #define RTL_EEPROM_VPD_LEN 0x40 |
| |
| /** Configuration Register 1 (byte) */ |
| #define RTL_CONFIG1 0x52 |
| #define RTL_CONFIG1_VPD 0x02 /**< Vital Product Data enabled */ |
| |
| /** Media Status Register (byte, 8139 only) */ |
| #define RTL_MSR 0x58 |
| #define RTL_MSR_TXFCE 0x80 /**< TX flow control enabled */ |
| #define RTL_MSR_RXFCE 0x40 /**< RX flow control enabled */ |
| #define RTL_MSR_AUX_STATUS 0x10 /**< Aux power present */ |
| #define RTL_MSR_SPEED_10 0x08 /**< 10Mbps */ |
| #define RTL_MSR_LINKB 0x04 /**< Inverse of link status */ |
| #define RTL_MSR_TXPF 0x02 /**< TX pause flag */ |
| #define RTL_MSR_RXPF 0x01 /**< RX pause flag */ |
| |
| /** PHY Access Register (dword, 8169 only) */ |
| #define RTL_PHYAR 0x60 |
| #define RTL_PHYAR_FLAG 0x80000000UL /**< Read/write flag */ |
| |
| /** Construct PHY Access Register value */ |
| #define RTL_PHYAR_VALUE( flag, reg, data ) ( (flag) | ( (reg) << 16 ) | (data) ) |
| |
| /** Extract PHY Access Register data */ |
| #define RTL_PHYAR_DATA( value ) ( (value) & 0xffff ) |
| |
| /** Maximum time to wait for PHY access, in microseconds */ |
| #define RTL_MII_MAX_WAIT_US 500 |
| |
| /** PHY (GMII, MII, or TBI) Status Register (byte, 8169 only) */ |
| #define RTL_PHYSTATUS 0x6c |
| #define RTL_PHYSTATUS_ENTBI 0x80 /**< TBI / GMII mode */ |
| #define RTL_PHYSTATUS_TXFLOW 0x40 /**< TX flow control enabled */ |
| #define RTL_PHYSTATUS_RXFLOW 0x20 /**< RX flow control enabled */ |
| #define RTL_PHYSTATUS_1000MF 0x10 /**< 1000Mbps full-duplex */ |
| #define RTL_PHYSTATUS_100M 0x08 /**< 100Mbps */ |
| #define RTL_PHYSTATUS_10M 0x04 /**< 10Mbps */ |
| #define RTL_PHYSTATUS_LINKSTS 0x02 /**< Link ok */ |
| #define RTL_PHYSTATUS_FULLDUP 0x01 /**< Full duplex */ |
| |
| /** Transmit Priority Polling Register (byte, 8139C+ only) */ |
| #define RTL_TPPOLL_8139CP 0xd9 |
| |
| /** RX Packet Maximum Size Register (word) */ |
| #define RTL_RMS 0xda |
| |
| /** C+ Command Register (word) */ |
| #define RTL_CPCR 0xe0 |
| #define RTL_CPCR_DAC 0x0010 /**< PCI Dual Address Cycle Enable */ |
| #define RTL_CPCR_MULRW 0x0008 /**< PCI Multiple Read/Write Enable */ |
| #define RTL_CPCR_CPRX 0x0002 /**< C+ receive enable */ |
| #define RTL_CPCR_CPTX 0x0001 /**< C+ transmit enable */ |
| |
| /** Receive Descriptor Start Address Register (qword) */ |
| #define RTL_RDSAR 0xe4 |
| |
| /** Number of receive descriptors */ |
| #define RTL_NUM_RX_DESC 4 |
| |
| /** Receive buffer length */ |
| #define RTL_RX_MAX_LEN \ |
| ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ + 4 /* extra space */ ) |
| |
| /** A Realtek descriptor ring */ |
| struct realtek_ring { |
| /** Descriptors */ |
| struct realtek_descriptor *desc; |
| /** Descriptor ring DMA mapping */ |
| struct dma_mapping map; |
| /** Producer index */ |
| unsigned int prod; |
| /** Consumer index */ |
| unsigned int cons; |
| |
| /** Descriptor start address register */ |
| unsigned int reg; |
| /** Length (in bytes) */ |
| size_t len; |
| }; |
| |
| /** |
| * Initialise descriptor ring |
| * |
| * @v ring Descriptor ring |
| * @v count Number of descriptors |
| * @v reg Descriptor start address register |
| */ |
| static inline __attribute__ (( always_inline)) void |
| realtek_init_ring ( struct realtek_ring *ring, unsigned int count, |
| unsigned int reg ) { |
| ring->len = ( count * sizeof ( ring->desc[0] ) ); |
| ring->reg = reg; |
| } |
| |
| /** Receive buffer (legacy mode *) */ |
| struct realtek_rx_buffer { |
| /** Buffer */ |
| void *data; |
| /** Buffer DMA mapping */ |
| struct dma_mapping map; |
| /** Offset within buffer */ |
| unsigned int offset; |
| }; |
| |
| /** A Realtek network card */ |
| struct realtek_nic { |
| /** Registers */ |
| void *regs; |
| /** DMA device */ |
| struct dma_device *dma; |
| /** SPI bit-bashing interface */ |
| struct spi_bit_basher spibit; |
| /** EEPROM */ |
| struct spi_device eeprom; |
| /** Non-volatile options */ |
| struct nvo_block nvo; |
| /** MII interface */ |
| struct mii_interface mdio; |
| /** MII device */ |
| struct mii_device mii; |
| |
| /** Legacy datapath mode */ |
| int legacy; |
| /** PHYAR and PHYSTATUS registers are present */ |
| int have_phy_regs; |
| /** TPPoll register offset */ |
| unsigned int tppoll; |
| |
| /** Transmit descriptor ring */ |
| struct realtek_ring tx; |
| /** Receive descriptor ring */ |
| struct realtek_ring rx; |
| /** Receive I/O buffers */ |
| struct io_buffer *rx_iobuf[RTL_NUM_RX_DESC]; |
| /** Receive buffer (legacy mode) */ |
| struct realtek_rx_buffer rxbuf; |
| }; |
| |
| #endif /* _REALTEK_H */ |