[realtek] Support RTL8139 cards within generic Realtek driver

RTL8139C+ cards use essentially the same datapath as RTL8169, which is
zerocopy and 64-bit capable.  Older RTL8139 cards use a single receive
ring buffer rather than a descriptor ring, but still share substantial
amounts of functionality with RTL8169.

Include support for RTL8139 cards within the generic Realtek driver,
since there is no way to differentiate between RTL8139 and RTL8139C+
cards based on the PCI IDs alone.

Many thanks to all the people who worked on the rtl8139 driver over
the years.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2012-04-28 15:47:46 +01:00
parent e01cf6fb3a
commit f8bb40b002
3 changed files with 400 additions and 649 deletions

View File

@@ -49,6 +49,22 @@ enum realtek_descriptor_flags {
/** 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
@@ -58,43 +74,75 @@ enum realtek_descriptor_flags {
/** 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 */
/** 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
/** Transmit Priority Polling Register (byte) */
#define RTL_TPPOLL 0x38
/** 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 0x20 /**< Packet underrun / link change */
#define RTL_IRQ_TER 0x08 /**< Transmit error */
#define RTL_IRQ_TOK 0x04 /**< Transmit OK */
#define RTL_IRQ_RER 0x02 /**< Receive error */
#define RTL_IRQ_ROK 0x01 /**< Receive OK */
#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
/** Receive (Rx) Configuration Register (dword) */
#define RTL_RCR 0x44
#define RTL_RCR_9356SEL 0x40 /**< EEPROM is a 93C56 */
#define RTL_RCR_AB 0x08 /**< Accept broadcast packets */
#define RTL_RCR_AM 0x04 /**< Accept multicast packets */
#define RTL_RCR_APM 0x02 /**< Accept physical match packets */
#define RTL_RCR_AAP 0x01 /**< Accept all packets */
#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_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
@@ -118,7 +166,11 @@ enum realtek_descriptor_flags {
#define RTL_CONFIG1 0x52
#define RTL_CONFIG1_VPD 0x02 /**< Vital Product Data enabled */
/** PHY Access Register (dword) */
/** Media Status Register (byte, 8139 only) */
#define RTL_MSR 0x58
#define RTL_MSR_LINKB 0x04 /**< Inverse of link status */
/** PHY Access Register (dword, 8169 only) */
#define RTL_PHYAR 0x60
#define RTL_PHYAR_FLAG 0x80000000UL /**< Read/write flag */
@@ -131,17 +183,22 @@ enum realtek_descriptor_flags {
/** Maximum time to wait for PHY access, in microseconds */
#define RTL_MII_MAX_WAIT_US 500
/** PHY (GMII, MII, or TBI) Status Register (byte) */
/** PHY (GMII, MII, or TBI) Status Register (byte, 8169 only) */
#define RTL_PHYSTATUS 0x6c
#define RTL_PHYSTATUS_LINKSTS 0x02 /**< Link ok */
/** 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 0x10 /**< PCI Dual Address Cycle Enable */
#define RTL_CPCR_MULRW 0x08 /**< PCI Multiple Read/Write Enable */
#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
@@ -194,12 +251,23 @@ struct realtek_nic {
/** MII interface */
struct mii_interface 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) */
void *rx_buffer;
/** Offset within receive buffer (legacy mode) */
unsigned int rx_offset;
};
#endif /* _REALTEK_H */