david/ipxe
Archived
1
0
This repository has been archived on 2020-12-06. You can view files and clone it, but cannot push or open issues or pull requests.
ipxe/src/drivers/net/intel.h
Michael Brown ead70bf920 [intel] Apply PBS/PBA errata workaround only to ICH8 PCI device IDs
ICH8 devices have an errata which requires us to reconfigure the
packet buffer size (PBS) register, and correspondingly adjust the
packet buffer allocation (PBA) register.  The "Intel I/O Controller
Hub ICH8/9/10 and 82566/82567/82562V Software Developer's Manual"
notes for the PBS register that:

  10.4.20   Packet Buffer Size - PBS (01008h; R/W)

  Note: The default setting of this register is 20 KB and is
        incorrect. This register must be programmed to 16 KB.

  Initial value: 0014h
                 0018h (ICH9/ICH10)

It is unclear from this comment precisely which devices require the
workaround to be applied.  We currently attempt to err on the side of
caution: if we detect an initial value of either 0x14 or 0x18 then the
workaround will be applied.  If the workaround is applied
unnecessarily, then the effect should be just that we use less than
the full amount of the available packet buffer memory.

Unfortunately this approach does not play nicely with other device
drivers.  For example, the Linux e1000e driver will rewrite PBA while
assuming that PBS still contains the default value, which can result
in inconsistent values between the two registers, and a corresponding
inability to transmit or receive packets.  Even more unfortunately,
the contents of PBS and PBA are not reset by anything less than a
power cycle, meaning that this error condition will survive a hardware
reset.

The Linux driver (written and maintained by Intel) applies the PBS/PBA
errata workaround only for devices in the ICH8 family, identified via
the PCI device ID.  Adopt a similar approach, using the PCI_ROM()
driver data field to indicate when the workaround is required.

Reported-by: Donald Bindner <dbindner@truman.edu>
Debugged-by: Donald Bindner <dbindner@truman.edu>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2014-08-21 00:40:22 +01:00

268 lines
7.3 KiB
C

#ifndef _INTEL_H
#define _INTEL_H
/** @file
*
* Intel 10/100/1000 network card driver
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
#include <stdint.h>
#include <ipxe/if_ether.h>
#include <ipxe/nvs.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;
/** Reserved */
uint8_t reserved_a;
/** Command */
uint8_t command;
/** Status */
uint8_t status;
/** Errors */
uint8_t errors;
/** Reserved */
uint16_t reserved_b;
} __attribute__ (( packed ));
/** Packet descriptor command bits */
enum intel_descriptor_command {
/** Report status */
INTEL_DESC_CMD_RS = 0x08,
/** Insert frame checksum (CRC) */
INTEL_DESC_CMD_IFCS = 0x02,
/** End of packet */
INTEL_DESC_CMD_EOP = 0x01,
};
/** Packet descriptor status bits */
enum intel_descriptor_status {
/** Descriptor done */
INTEL_DESC_STATUS_DD = 0x01,
};
/** 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_LSC 0x00000004UL /**< Link status change */
#define INTEL_IRQ_RXT0 0x00000080UL /**< Receive timer */
#define INTEL_IRQ_RXO 0x00000400UL /**< Receive overrun */
/** 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 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 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 */
/** Receive Address Low */
#define INTEL_RAL0 0x05400UL
/** Receive Address High */
#define INTEL_RAH0 0x05404UL
#define INTEL_RAH0_AV 0x80000000UL /**< Address valid */
/** 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;
/** Producer index */
unsigned int prod;
/** Consumer index */
unsigned int cons;
/** Register block */
unsigned int reg;
/** Length (in bytes) */
size_t len;
};
/**
* Initialise descriptor ring
*
* @v ring Descriptor ring
* @v count Number of descriptors
* @v reg Descriptor register block
*/
static inline __attribute__ (( always_inline)) void
intel_init_ring ( struct intel_ring *ring, unsigned int count,
unsigned int reg ) {
ring->len = ( count * sizeof ( ring->desc[0] ) );
ring->reg = reg;
}
/** An Intel network card */
struct intel_nic {
/** Registers */
void *regs;
/** Port number (for multi-port devices) */
unsigned int port;
/** Flags */
unsigned int flags;
/** EEPROM */
struct nvs_device eeprom;
/** EEPROM done flag */
uint32_t eerd_done;
/** EEPROM address shift */
unsigned int eerd_addr_shift;
/** 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,
};
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 */