| #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 */ |