blob: 29cf3a7d82460cc319b62aeb1bf3d9624df7e4fc [file] [log] [blame]
#ifndef _INTEL_H
#define _INTEL_H
/** @file
*
* Intel 10/100/1000 network card driver
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/if_ether.h>
#include <ipxe/nvs.h>
#include <ipxe/dma.h>
/** Intel BAR size */
#define INTEL_BAR_SIZE ( 128 * 1024 )
/** A packet descriptor */
struct intel_descriptor {
/** Buffer address */
uint64_t address;
/** Length */
uint16_t length;
/** Flags */
uint8_t flags;
/** Command */
uint8_t command;
/** Status */
uint32_t status;
} __attribute__ (( packed ));
/** Descriptor type */
#define INTEL_DESC_FL_DTYP( dtyp ) ( (dtyp) << 4 )
#define INTEL_DESC_FL_DTYP_DATA INTEL_DESC_FL_DTYP ( 0x03 )
/** Descriptor extension */
#define INTEL_DESC_CMD_DEXT 0x20
/** Report status */
#define INTEL_DESC_CMD_RS 0x08
/** Insert frame checksum (CRC) */
#define INTEL_DESC_CMD_IFCS 0x02
/** End of packet */
#define INTEL_DESC_CMD_EOP 0x01
/** Descriptor done */
#define INTEL_DESC_STATUS_DD 0x00000001UL
/** Receive error */
#define INTEL_DESC_STATUS_RXE 0x00000100UL
/** Payload length */
#define INTEL_DESC_STATUS_PAYLEN( len ) ( (len) << 14 )
/** Device Control Register */
#define INTEL_CTRL 0x00000UL
#define INTEL_CTRL_LRST 0x00000008UL /**< Link reset */
#define INTEL_CTRL_ASDE 0x00000020UL /**< Auto-speed detection */
#define INTEL_CTRL_SLU 0x00000040UL /**< Set link up */
#define INTEL_CTRL_FRCSPD 0x00000800UL /**< Force speed */
#define INTEL_CTRL_FRCDPLX 0x00001000UL /**< Force duplex */
#define INTEL_CTRL_RST 0x04000000UL /**< Device reset */
#define INTEL_CTRL_PHY_RST 0x80000000UL /**< PHY reset */
/** Time to delay for device reset, in milliseconds */
#define INTEL_RESET_DELAY_MS 20
/** Device Status Register */
#define INTEL_STATUS 0x00008UL
#define INTEL_STATUS_LU 0x00000002UL /**< Link up */
/** EEPROM Read Register */
#define INTEL_EERD 0x00014UL
#define INTEL_EERD_START 0x00000001UL /**< Start read */
#define INTEL_EERD_DONE_SMALL 0x00000010UL /**< Read done (small EERD) */
#define INTEL_EERD_DONE_LARGE 0x00000002UL /**< Read done (large EERD) */
#define INTEL_EERD_ADDR_SHIFT_SMALL 8 /**< Address shift (small) */
#define INTEL_EERD_ADDR_SHIFT_LARGE 2 /**< Address shift (large) */
#define INTEL_EERD_DATA(value) ( (value) >> 16 ) /**< Read data */
/** Maximum time to wait for EEPROM read, in milliseconds */
#define INTEL_EEPROM_MAX_WAIT_MS 100
/** EEPROM word length */
#define INTEL_EEPROM_WORD_LEN_LOG2 1
/** Minimum EEPROM size, in words */
#define INTEL_EEPROM_MIN_SIZE_WORDS 64
/** Offset of MAC address within EEPROM */
#define INTEL_EEPROM_MAC 0x00
/** Interrupt Cause Read Register */
#define INTEL_ICR 0x000c0UL
#define INTEL_IRQ_TXDW 0x00000001UL /**< Transmit descriptor done */
#define INTEL_IRQ_TXQE 0x00000002UL /**< Transmit queue empty */
#define INTEL_IRQ_LSC 0x00000004UL /**< Link status change */
#define INTEL_IRQ_RXDMT0 0x00000010UL /**< Receive queue low */
#define INTEL_IRQ_RXO 0x00000040UL /**< Receive overrun */
#define INTEL_IRQ_RXT0 0x00000080UL /**< Receive timer */
/** Interrupt Mask Set/Read Register */
#define INTEL_IMS 0x000d0UL
/** Interrupt Mask Clear Register */
#define INTEL_IMC 0x000d8UL
/** Receive Control Register */
#define INTEL_RCTL 0x00100UL
#define INTEL_RCTL_EN 0x00000002UL /**< Receive enable */
#define INTEL_RCTL_UPE 0x00000008UL /**< Unicast promiscuous mode */
#define INTEL_RCTL_MPE 0x00000010UL /**< Multicast promiscuous */
#define INTEL_RCTL_BAM 0x00008000UL /**< Broadcast accept mode */
#define INTEL_RCTL_BSIZE_BSEX(bsex,bsize) \
( ( (bsize) << 16 ) | ( (bsex) << 25 ) ) /**< Buffer size */
#define INTEL_RCTL_BSIZE_2048 INTEL_RCTL_BSIZE_BSEX ( 0, 0 )
#define INTEL_RCTL_BSIZE_BSEX_MASK INTEL_RCTL_BSIZE_BSEX ( 1, 3 )
#define INTEL_RCTL_SECRC 0x04000000UL /**< Strip CRC */
/** Transmit Control Register */
#define INTEL_TCTL 0x00400UL
#define INTEL_TCTL_EN 0x00000002UL /**< Transmit enable */
#define INTEL_TCTL_PSP 0x00000008UL /**< Pad short packets */
#define INTEL_TCTL_CT(x) ( (x) << 4 ) /**< Collision threshold */
#define INTEL_TCTL_CT_DEFAULT INTEL_TCTL_CT ( 0x0f )
#define INTEL_TCTL_CT_MASK INTEL_TCTL_CT ( 0xff )
#define INTEL_TCTL_COLD(x) ( (x) << 12 ) /**< Collision distance */
#define INTEL_TCTL_COLD_DEFAULT INTEL_TCTL_COLD ( 0x040 )
#define INTEL_TCTL_COLD_MASK INTEL_TCTL_COLD ( 0x3ff )
/** Packet Buffer Allocation */
#define INTEL_PBA 0x01000UL
/** Packet Buffer Size */
#define INTEL_PBS 0x01008UL
/** Receive packet buffer size */
#define INTEL_RXPBS 0x02404UL
#define INTEL_RXPBS_I210 0x000000a2UL /**< I210 power-up default */
/** Receive Descriptor register block */
#define INTEL_RD 0x02800UL
/** Number of receive descriptors
*
* Minimum value is 8, since the descriptor ring length must be a
* multiple of 128.
*/
#define INTEL_NUM_RX_DESC 16
/** Receive descriptor ring fill level */
#define INTEL_RX_FILL 8
/** Receive buffer length */
#define INTEL_RX_MAX_LEN 2048
/** Transmit packet buffer size */
#define INTEL_TXPBS 0x03404UL
#define INTEL_TXPBS_I210 0x04000014UL /**< I210 power-up default */
/** Transmit Descriptor register block */
#define INTEL_TD 0x03800UL
/** Number of transmit descriptors
*
* Descriptor ring length must be a multiple of 16. ICH8/9/10
* requires a minimum of 16 TX descriptors.
*/
#define INTEL_NUM_TX_DESC 16
/** Transmit descriptor ring maximum fill level */
#define INTEL_TX_FILL ( INTEL_NUM_TX_DESC - 1 )
/** Receive/Transmit Descriptor Base Address Low (offset) */
#define INTEL_xDBAL 0x00
/** Receive/Transmit Descriptor Base Address High (offset) */
#define INTEL_xDBAH 0x04
/** Receive/Transmit Descriptor Length (offset) */
#define INTEL_xDLEN 0x08
/** Receive/Transmit Descriptor Head (offset) */
#define INTEL_xDH 0x10
/** Receive/Transmit Descriptor Tail (offset) */
#define INTEL_xDT 0x18
/** Receive/Transmit Descriptor Control (offset) */
#define INTEL_xDCTL 0x28
#define INTEL_xDCTL_ENABLE 0x02000000UL /**< Queue enable */
/** Maximum time to wait for queue disable, in milliseconds */
#define INTEL_DISABLE_MAX_WAIT_MS 100
/** Receive Address Low */
#define INTEL_RAL0 0x05400UL
/** Receive Address High */
#define INTEL_RAH0 0x05404UL
#define INTEL_RAH0_AV 0x80000000UL /**< Address valid */
/** Future Extended NVM register 11 */
#define INTEL_FEXTNVM11 0x05bbcUL
#define INTEL_FEXTNVM11_WTF 0x00002000UL /**< Don't ask */
/** Receive address */
union intel_receive_address {
struct {
uint32_t low;
uint32_t high;
} __attribute__ (( packed )) reg;
uint8_t raw[ETH_ALEN];
};
/** An Intel descriptor ring */
struct intel_ring {
/** Descriptors */
struct intel_descriptor *desc;
/** Descriptor ring DMA mapping */
struct dma_mapping map;
/** Producer index */
unsigned int prod;
/** Consumer index */
unsigned int cons;
/** Register block */
unsigned int reg;
/** Length (in bytes) */
size_t len;
/** Populate descriptor
*
* @v desc Descriptor
* @v addr Data buffer address
* @v len Length of data
*/
void ( * describe ) ( struct intel_descriptor *desc, physaddr_t addr,
size_t len );
};
/**
* Initialise descriptor ring
*
* @v ring Descriptor ring
* @v count Number of descriptors
* @v reg Descriptor register block
* @v describe Method to populate descriptor
*/
static inline __attribute__ (( always_inline)) void
intel_init_ring ( struct intel_ring *ring, unsigned int count, unsigned int reg,
void ( * describe ) ( struct intel_descriptor *desc,
physaddr_t addr, size_t len ) ) {
ring->len = ( count * sizeof ( ring->desc[0] ) );
ring->reg = reg;
ring->describe = describe;
}
/** An Intel virtual function mailbox */
struct intel_mailbox {
/** Mailbox control register */
unsigned int ctrl;
/** Mailbox memory base */
unsigned int mem;
};
/**
* Initialise mailbox
*
* @v mbox Mailbox
* @v ctrl Mailbox control register
* @v mem Mailbox memory register base
*/
static inline __attribute__ (( always_inline )) void
intel_init_mbox ( struct intel_mailbox *mbox, unsigned int ctrl,
unsigned int mem ) {
mbox->ctrl = ctrl;
mbox->mem = mem;
}
/** An Intel network card */
struct intel_nic {
/** Registers */
void *regs;
/** DMA device */
struct dma_device *dma;
/** Port number (for multi-port devices) */
unsigned int port;
/** Flags */
unsigned int flags;
/** Forced interrupts */
unsigned int force_icr;
/** EEPROM */
struct nvs_device eeprom;
/** EEPROM done flag */
uint32_t eerd_done;
/** EEPROM address shift */
unsigned int eerd_addr_shift;
/** Mailbox */
struct intel_mailbox mbox;
/** Transmit descriptor ring */
struct intel_ring tx;
/** Receive descriptor ring */
struct intel_ring rx;
/** Receive I/O buffers */
struct io_buffer *rx_iobuf[INTEL_NUM_RX_DESC];
};
/** Driver flags */
enum intel_flags {
/** PBS/PBA errata workaround required */
INTEL_PBS_ERRATA = 0x0001,
/** VMware missing interrupt workaround required */
INTEL_VMWARE = 0x0002,
/** PHY reset is broken */
INTEL_NO_PHY_RST = 0x0004,
/** ASDE is broken */
INTEL_NO_ASDE = 0x0008,
/** Reset may cause a complete device hang */
INTEL_RST_HANG = 0x0010,
/** PBSIZE registers must be explicitly reset */
INTEL_PBSIZE_RST = 0x0020,
};
/** The i219 has a seriously broken reset mechanism */
#define INTEL_I219 ( INTEL_NO_PHY_RST | INTEL_RST_HANG )
/**
* Dump diagnostic information
*
* @v intel Intel device
*/
static inline void intel_diag ( struct intel_nic *intel ) {
DBGC ( intel, "INTEL %p TX %04x(%02x)/%04x(%02x) "
"RX %04x(%02x)/%04x(%02x)\n", intel,
( intel->tx.cons & 0xffff ),
readl ( intel->regs + intel->tx.reg + INTEL_xDH ),
( intel->tx.prod & 0xffff ),
readl ( intel->regs + intel->tx.reg + INTEL_xDT ),
( intel->rx.cons & 0xffff ),
readl ( intel->regs + intel->rx.reg + INTEL_xDH ),
( intel->rx.prod & 0xffff ),
readl ( intel->regs + intel->rx.reg + INTEL_xDT ) );
}
extern void intel_describe_tx ( struct intel_descriptor *tx,
physaddr_t addr, size_t len );
extern void intel_describe_tx_adv ( struct intel_descriptor *tx,
physaddr_t addr, size_t len );
extern void intel_describe_rx ( struct intel_descriptor *rx,
physaddr_t addr, size_t len );
extern void intel_reset_ring ( struct intel_nic *intel, unsigned int reg );
extern int intel_create_ring ( struct intel_nic *intel,
struct intel_ring *ring );
extern void intel_destroy_ring ( struct intel_nic *intel,
struct intel_ring *ring );
extern void intel_refill_rx ( struct intel_nic *intel );
extern void intel_empty_rx ( struct intel_nic *intel );
extern int intel_transmit ( struct net_device *netdev,
struct io_buffer *iobuf );
extern void intel_poll_tx ( struct net_device *netdev );
extern void intel_poll_rx ( struct net_device *netdev );
#endif /* _INTEL_H */