rlfnb d4dd6511b9 replace tickdelay with micro_delay to be quantum-agnostic
Change-Id: Ie449d797389a178372035d797c84b02d636788cd
2017-06-01 19:48:56 +02:00

919 lines
22 KiB
C

/* A device driver for Intel Pro/1000 Gigabit Ethernet Controllers. */
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <machine/pci.h>
#include <sys/mman.h>
#include "assert.h"
#include "e1000.h"
#include "e1000_hw.h"
#include "e1000_reg.h"
#include "e1000_pci.h"
static int e1000_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks);
static void e1000_stop(void);
static void e1000_set_mode(unsigned int, const netdriver_addr_t *,
unsigned int);
static void e1000_set_hwaddr(const netdriver_addr_t *);
static int e1000_send(struct netdriver_data *data, size_t size);
static ssize_t e1000_recv(struct netdriver_data *data, size_t max);
static unsigned int e1000_get_link(uint32_t *);
static void e1000_intr(unsigned int mask);
static void e1000_tick(void);
static int e1000_probe(e1000_t *e, int skip);
static void e1000_init_hw(e1000_t *e, netdriver_addr_t *addr);
static uint32_t e1000_reg_read(e1000_t *e, uint32_t reg);
static void e1000_reg_write(e1000_t *e, uint32_t reg, uint32_t value);
static void e1000_reg_set(e1000_t *e, uint32_t reg, uint32_t value);
static void e1000_reg_unset(e1000_t *e, uint32_t reg, uint32_t value);
static u16_t eeprom_eerd(e1000_t *e, int reg);
static u16_t eeprom_ich(e1000_t *e, int reg);
static int eeprom_ich_init(e1000_t *e);
static int eeprom_ich_cycle(e1000_t *e, u32_t timeout);
static int e1000_instance;
static e1000_t e1000_state;
static const struct netdriver e1000_table = {
.ndr_name = "em",
.ndr_init = e1000_init,
.ndr_stop = e1000_stop,
.ndr_set_mode = e1000_set_mode,
.ndr_set_hwaddr = e1000_set_hwaddr,
.ndr_recv = e1000_recv,
.ndr_send = e1000_send,
.ndr_get_link = e1000_get_link,
.ndr_intr = e1000_intr,
.ndr_tick = e1000_tick
};
/*
* The e1000 driver.
*/
int
main(int argc, char * argv[])
{
env_setargs(argc, argv);
/* Let the netdriver library take control. */
netdriver_task(&e1000_table);
return 0;
}
/*
* Initialize the e1000 driver and device.
*/
static int
e1000_init(unsigned int instance, netdriver_addr_t * addr, uint32_t * caps,
unsigned int * ticks)
{
e1000_t *e;
int r;
e1000_instance = instance;
/* Clear state. */
memset(&e1000_state, 0, sizeof(e1000_state));
e = &e1000_state;
/* Perform calibration. */
if ((r = tsc_calibrate()) != OK)
panic("tsc_calibrate failed: %d", r);
/* See if we can find a matching device. */
if (!e1000_probe(e, instance))
return ENXIO;
/* Initialize the hardware, and return its ethernet address. */
e1000_init_hw(e, addr);
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST | NDEV_CAP_HWADDR;
*ticks = sys_hz() / 10; /* update statistics 10x/sec */
return OK;
}
/*
* Map flash memory. This step is optional.
*/
static void
e1000_map_flash(e1000_t * e, int devind, int did)
{
u32_t flash_addr, gfpreg, sector_base_addr;
size_t flash_size;
/* The flash memory is pointed to by BAR2. It may not be present. */
if ((flash_addr = pci_attr_r32(devind, PCI_BAR_2)) == 0)
return;
/* The default flash size. */
flash_size = 0x10000;
switch (did) {
case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82545EM:
case E1000_DEV_ID_82540EP:
case E1000_DEV_ID_82540EP_LP:
return; /* don't even try */
/* 82566/82567/82562V series support mapping 4kB of flash memory. */
case E1000_DEV_ID_ICH10_D_BM_LM:
case E1000_DEV_ID_ICH10_R_BM_LF:
flash_size = 0x1000;
break;
}
e->flash = vm_map_phys(SELF, (void *)flash_addr, flash_size);
if (e->flash == MAP_FAILED)
panic("e1000: couldn't map in flash");
/* sector_base_addr is a "sector"-aligned address (4096 bytes). */
gfpreg = E1000_READ_FLASH_REG(e, ICH_FLASH_GFPREG);
sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
/* flash_base_addr is byte-aligned. */
e->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
}
/*
* Find a matching device. Return TRUE on success.
*/
static int
e1000_probe(e1000_t * e, int skip)
{
int r, devind, ioflag;
u16_t vid, did, cr;
u32_t status;
u32_t base, size;
const char *dname;
E1000_DEBUG(3, ("%s: probe()\n", netdriver_name()));
/* Initialize communication to the PCI driver. */
pci_init();
/* Attempt to iterate the PCI bus. Start at the beginning. */
if ((r = pci_first_dev(&devind, &vid, &did)) == 0)
return FALSE;
/* Loop devices on the PCI bus. */
while (skip--) {
E1000_DEBUG(3, ("%s: probe() devind %d vid 0x%x did 0x%x\n",
netdriver_name(), devind, vid, did));
if (!(r = pci_next_dev(&devind, &vid, &did)))
return FALSE;
}
/* We found a matching card. Set card-specific properties. */
e->eeprom_read = eeprom_eerd;
switch (did) {
case E1000_DEV_ID_ICH10_D_BM_LM:
case E1000_DEV_ID_ICH10_R_BM_LF:
e->eeprom_read = eeprom_ich;
break;
case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82545EM:
case E1000_DEV_ID_82540EP_LP:
e->eeprom_done_bit = (1 << 4);
e->eeprom_addr_off = 8;
break;
default:
e->eeprom_done_bit = (1 << 1);
e->eeprom_addr_off = 2;
break;
}
/* Inform the user about the new card. */
if (!(dname = pci_dev_name(vid, did)))
dname = "Intel Pro/1000 Gigabit Ethernet Card";
E1000_DEBUG(1, ("%s: %s (%04x/%04x) at %s\n",
netdriver_name(), dname, vid, did, pci_slot_name(devind)));
/* Reserve PCI resources found. */
pci_reserve(devind);
/* Read PCI configuration. */
e->irq = pci_attr_r8(devind, PCI_ILR);
if ((r = pci_get_bar(devind, PCI_BAR, &base, &size, &ioflag)) != OK)
panic("failed to get PCI BAR: %d", r);
if (ioflag)
panic("PCI BAR is not for memory");
if ((e->regs = vm_map_phys(SELF, (void *)base, size)) == MAP_FAILED)
panic("failed to map hardware registers from PCI");
/* Enable DMA bus mastering if necessary. */
cr = pci_attr_r16(devind, PCI_CR);
if (!(cr & PCI_CR_MAST_EN))
pci_attr_w16(devind, PCI_CR, cr | PCI_CR_MAST_EN);
/* Optionally map flash memory. */
e1000_map_flash(e, devind, did);
/* Output debug information. */
status = e1000_reg_read(e, E1000_REG_STATUS);
E1000_DEBUG(3, ("%s: MEM at %p, IRQ %d\n", netdriver_name(),
e->regs, e->irq));
E1000_DEBUG(3, ("%s: link %s, %s duplex\n", netdriver_name(),
status & 3 ? "up" : "down", status & 1 ? "full" : "half"));
return TRUE;
}
/*
* Reset the card.
*/
static void
e1000_reset_hw(e1000_t * e)
{
/* Assert a Device Reset signal. */
e1000_reg_set(e, E1000_REG_CTRL, E1000_REG_CTRL_RST);
/* Wait one microsecond. */
micro_delay(16000);
}
/*
* Initialize and return the card's ethernet address.
*/
static void
e1000_init_addr(e1000_t * e, netdriver_addr_t * addr)
{
static char eakey[] = E1000_ENVVAR "#_EA";
static char eafmt[] = "x:x:x:x:x:x";
u16_t word;
int i;
long v;
/* Do we have a user defined ethernet address? */
eakey[sizeof(E1000_ENVVAR)-1] = '0' + e1000_instance;
for (i = 0; i < 6; i++) {
if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
break;
else
addr->na_addr[i] = v;
}
/* If that fails, read Ethernet Address from EEPROM. */
if (i != 6) {
for (i = 0; i < 3; i++) {
word = e->eeprom_read(e, i);
addr->na_addr[i * 2] = (word & 0x00ff);
addr->na_addr[i * 2 + 1] = (word & 0xff00) >> 8;
}
}
/* Set Receive Address. */
e1000_set_hwaddr(addr);
E1000_DEBUG(3, ("%s: Ethernet Address %x:%x:%x:%x:%x:%x\n",
netdriver_name(),
addr->na_addr[0], addr->na_addr[1], addr->na_addr[2],
addr->na_addr[3], addr->na_addr[4], addr->na_addr[5]));
}
/*
* Initialize receive and transmit buffers.
*/
static void
e1000_init_buf(e1000_t * e)
{
phys_bytes rx_desc_p, rx_buff_p;
phys_bytes tx_desc_p, tx_buff_p;
int i;
/* Number of descriptors. */
e->rx_desc_count = E1000_RXDESC_NR;
e->tx_desc_count = E1000_TXDESC_NR;
/* Allocate receive descriptors. */
if ((e->rx_desc = alloc_contig(sizeof(e1000_rx_desc_t) *
e->rx_desc_count, AC_ALIGN4K, &rx_desc_p)) == NULL)
panic("failed to allocate RX descriptors");
memset(e->rx_desc, 0, sizeof(e1000_rx_desc_t) * e->rx_desc_count);
/* Allocate receive buffers. */
e->rx_buffer_size = E1000_RXDESC_NR * E1000_IOBUF_SIZE;
if ((e->rx_buffer = alloc_contig(e->rx_buffer_size, AC_ALIGN4K,
&rx_buff_p)) == NULL)
panic("failed to allocate RX buffers");
/* Set up receive descriptors. */
for (i = 0; i < E1000_RXDESC_NR; i++)
e->rx_desc[i].buffer = rx_buff_p + i * E1000_IOBUF_SIZE;
/* Allocate transmit descriptors. */
if ((e->tx_desc = alloc_contig(sizeof(e1000_tx_desc_t) *
e->tx_desc_count, AC_ALIGN4K, &tx_desc_p)) == NULL)
panic("failed to allocate TX descriptors");
memset(e->tx_desc, 0, sizeof(e1000_tx_desc_t) * e->tx_desc_count);
/* Allocate transmit buffers. */
e->tx_buffer_size = E1000_TXDESC_NR * E1000_IOBUF_SIZE;
if ((e->tx_buffer = alloc_contig(e->tx_buffer_size, AC_ALIGN4K,
&tx_buff_p)) == NULL)
panic("failed to allocate TX buffers");
/* Set up transmit descriptors. */
for (i = 0; i < E1000_TXDESC_NR; i++)
e->tx_desc[i].buffer = tx_buff_p + i * E1000_IOBUF_SIZE;
/* Set up the receive ring registers. */
e1000_reg_write(e, E1000_REG_RDBAL, rx_desc_p);
e1000_reg_write(e, E1000_REG_RDBAH, 0);
e1000_reg_write(e, E1000_REG_RDLEN,
e->rx_desc_count * sizeof(e1000_rx_desc_t));
e1000_reg_write(e, E1000_REG_RDH, 0);
e1000_reg_write(e, E1000_REG_RDT, e->rx_desc_count - 1);
e1000_reg_unset(e, E1000_REG_RCTL, E1000_REG_RCTL_BSIZE);
e1000_reg_set(e, E1000_REG_RCTL, E1000_REG_RCTL_EN);
/* Set up the transmit ring registers. */
e1000_reg_write(e, E1000_REG_TDBAL, tx_desc_p);
e1000_reg_write(e, E1000_REG_TDBAH, 0);
e1000_reg_write(e, E1000_REG_TDLEN,
e->tx_desc_count * sizeof(e1000_tx_desc_t));
e1000_reg_write(e, E1000_REG_TDH, 0);
e1000_reg_write(e, E1000_REG_TDT, 0);
e1000_reg_set(e, E1000_REG_TCTL,
E1000_REG_TCTL_EN | E1000_REG_TCTL_PSP);
}
/*
* Initialize the hardware. Return the ethernet address.
*/
static void
e1000_init_hw(e1000_t * e, netdriver_addr_t * addr)
{
int r, i;
e->irq_hook = e->irq;
/*
* Set the interrupt handler and policy. Do not automatically
* reenable interrupts. Return the IRQ line number on interrupts.
*/
if ((r = sys_irqsetpolicy(e->irq, 0, &e->irq_hook)) != OK)
panic("sys_irqsetpolicy failed: %d", r);
if ((r = sys_irqenable(&e->irq_hook)) != OK)
panic("sys_irqenable failed: %d", r);
/* Reset hardware. */
e1000_reset_hw(e);
/*
* Initialize appropriately, according to section 14.3 General
* Configuration of Intel's Gigabit Ethernet Controllers Software
* Developer's Manual.
*/
e1000_reg_set(e, E1000_REG_CTRL,
E1000_REG_CTRL_ASDE | E1000_REG_CTRL_SLU);
e1000_reg_unset(e, E1000_REG_CTRL, E1000_REG_CTRL_LRST);
e1000_reg_unset(e, E1000_REG_CTRL, E1000_REG_CTRL_PHY_RST);
e1000_reg_unset(e, E1000_REG_CTRL, E1000_REG_CTRL_ILOS);
e1000_reg_write(e, E1000_REG_FCAL, 0);
e1000_reg_write(e, E1000_REG_FCAH, 0);
e1000_reg_write(e, E1000_REG_FCT, 0);
e1000_reg_write(e, E1000_REG_FCTTV, 0);
e1000_reg_unset(e, E1000_REG_CTRL, E1000_REG_CTRL_VME);
/* Clear Multicast Table Array (MTA). */
for (i = 0; i < 128; i++)
e1000_reg_write(e, E1000_REG_MTA + i * 4, 0);
/* Initialize statistics registers. */
for (i = 0; i < 64; i++)
e1000_reg_write(e, E1000_REG_CRCERRS + i * 4, 0);
/* Acquire MAC address and set up RX/TX buffers. */
e1000_init_addr(e, addr);
e1000_init_buf(e);
/* Enable interrupts. */
e1000_reg_set(e, E1000_REG_IMS, E1000_REG_IMS_LSC | E1000_REG_IMS_RXO |
E1000_REG_IMS_RXT | E1000_REG_IMS_TXQE | E1000_REG_IMS_TXDW);
}
/*
* Set receive mode.
*/
static void
e1000_set_mode(unsigned int mode, const netdriver_addr_t * mcast_list __unused,
unsigned int mcast_count __unused)
{
e1000_t *e;
uint32_t rctl;
e = &e1000_state;
rctl = e1000_reg_read(e, E1000_REG_RCTL);
rctl &= ~(E1000_REG_RCTL_BAM | E1000_REG_RCTL_MPE |
E1000_REG_RCTL_UPE);
/* TODO: support for NDEV_MODE_DOWN and multicast lists */
if (mode & NDEV_MODE_BCAST)
rctl |= E1000_REG_RCTL_BAM;
if (mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
rctl |= E1000_REG_RCTL_MPE;
if (mode & NDEV_MODE_PROMISC)
rctl |= E1000_REG_RCTL_BAM | E1000_REG_RCTL_MPE |
E1000_REG_RCTL_UPE;
e1000_reg_write(e, E1000_REG_RCTL, rctl);
}
/*
* Set hardware address.
*/
static void
e1000_set_hwaddr(const netdriver_addr_t * hwaddr)
{
e1000_t *e;
e = &e1000_state;
e1000_reg_write(e, E1000_REG_RAL,
*(const u32_t *)(&hwaddr->na_addr[0]));
e1000_reg_write(e, E1000_REG_RAH,
*(const u16_t *)(&hwaddr->na_addr[4]));
e1000_reg_set(e, E1000_REG_RAH, E1000_REG_RAH_AV);
}
/*
* Try to send a packet.
*/
static int
e1000_send(struct netdriver_data * data, size_t size)
{
e1000_t *e;
e1000_tx_desc_t *desc;
unsigned int head, tail, next;
char *ptr;
e = &e1000_state;
if (size > E1000_IOBUF_SIZE)
panic("packet too large to send");
/*
* The queue tail must not advance to the point that it is equal to the
* queue head, since this condition indicates that the queue is empty.
*/
head = e1000_reg_read(e, E1000_REG_TDH);
tail = e1000_reg_read(e, E1000_REG_TDT);
next = (tail + 1) % e->tx_desc_count;
if (next == head)
return SUSPEND;
/* The descriptor to use is the one pointed to by the current tail. */
desc = &e->tx_desc[tail];
/* Copy the packet from the caller. */
ptr = e->tx_buffer + tail * E1000_IOBUF_SIZE;
netdriver_copyin(data, 0, ptr, size);
/* Mark this descriptor ready. */
desc->status = 0;
desc->length = size;
desc->command = E1000_TX_CMD_EOP | E1000_TX_CMD_FCS | E1000_TX_CMD_RS;
/* Increment tail. Start transmission. */
e1000_reg_write(e, E1000_REG_TDT, next);
return OK;
}
/*
* Try to receive a packet.
*/
static ssize_t
e1000_recv(struct netdriver_data * data, size_t max)
{
e1000_t *e;
e1000_rx_desc_t *desc;
unsigned int head, tail, cur;
char *ptr;
size_t size;
e = &e1000_state;
/* If the queue head and tail are equal, the queue is empty. */
head = e1000_reg_read(e, E1000_REG_RDH);
tail = e1000_reg_read(e, E1000_REG_RDT);
E1000_DEBUG(4, ("%s: head=%u, tail=%u\n",
netdriver_name(), head, tail));
if (head == tail)
return SUSPEND;
/* Has a packet been received? */
cur = (tail + 1) % e->rx_desc_count;
desc = &e->rx_desc[cur];
if (!(desc->status & E1000_RX_STATUS_DONE))
return SUSPEND;
/*
* HACK: we expect all packets to fit in a single receive buffer.
* Eventually, some sort of support to deal with packets spanning
* multiple receive descriptors should be added. For now, we panic,
* so that we can continue after the restart; this is already an
* improvement over freezing (the old behavior of this driver).
*/
size = desc->length;
if (!(desc->status & E1000_RX_STATUS_EOP))
panic("received packet too large");
/* Copy the packet to the caller. */
ptr = e->rx_buffer + cur * E1000_IOBUF_SIZE;
if (size > max)
size = max;
netdriver_copyout(data, 0, ptr, size);
/* Reset the descriptor. */
desc->status = 0;
/* Increment tail. */
e1000_reg_write(e, E1000_REG_RDT, cur);
/* Return the size of the received packet. */
return size;
}
/*
* Return the link and media status.
*/
static unsigned int
e1000_get_link(uint32_t * media)
{
uint32_t status, type;
status = e1000_reg_read(&e1000_state, E1000_REG_STATUS);
if (!(status & E1000_REG_STATUS_LU))
return NDEV_LINK_DOWN;
if (status & E1000_REG_STATUS_FD)
type = IFM_ETHER | IFM_FDX;
else
type = IFM_ETHER | IFM_HDX;
switch (status & E1000_REG_STATUS_SPEED) {
case E1000_REG_STATUS_SPEED_10:
type |= IFM_10_T;
break;
case E1000_REG_STATUS_SPEED_100:
type |= IFM_100_TX;
break;
case E1000_REG_STATUS_SPEED_1000_A:
case E1000_REG_STATUS_SPEED_1000_B:
type |= IFM_1000_T;
break;
}
*media = type;
return NDEV_LINK_UP;
}
/*
* Handle an interrupt.
*/
static void
e1000_intr(unsigned int __unused mask)
{
e1000_t *e;
u32_t cause;
E1000_DEBUG(3, ("e1000: interrupt\n"));
e = &e1000_state;
/* Reenable interrupts. */
if (sys_irqenable(&e->irq_hook) != OK)
panic("failed to re-enable IRQ");
/* Read the Interrupt Cause Read register. */
if ((cause = e1000_reg_read(e, E1000_REG_ICR)) != 0) {
if (cause & E1000_REG_ICR_LSC)
netdriver_link();
if (cause & (E1000_REG_ICR_RXO | E1000_REG_ICR_RXT))
netdriver_recv();
if (cause & (E1000_REG_ICR_TXQE | E1000_REG_ICR_TXDW))
netdriver_send();
}
}
/*
* Do regular processing.
*/
static void
e1000_tick(void)
{
e1000_t *e;
e = &e1000_state;
/* Update statistics. */
netdriver_stat_ierror(e1000_reg_read(e, E1000_REG_RXERRC));
netdriver_stat_ierror(e1000_reg_read(e, E1000_REG_CRCERRS));
netdriver_stat_ierror(e1000_reg_read(e, E1000_REG_MPC));
netdriver_stat_coll(e1000_reg_read(e, E1000_REG_COLC));
}
/*
* Stop the card.
*/
static void
e1000_stop(void)
{
e1000_t *e;
e = &e1000_state;
E1000_DEBUG(3, ("%s: stop()\n", netdriver_name()));
e1000_reset_hw(e);
}
/*
* Read from a register.
*/
static uint32_t
e1000_reg_read(e1000_t * e, uint32_t reg)
{
uint32_t value;
/* Assume a sane register. */
assert(reg < 0x1ffff);
/* Read from memory mapped register. */
value = *(volatile uint32_t *)(e->regs + reg);
/* Return the result. */
return value;
}
/*
* Write to a register.
*/
static void
e1000_reg_write(e1000_t * e, uint32_t reg, uint32_t value)
{
/* Assume a sane register. */
assert(reg < 0x1ffff);
/* Write to memory mapped register. */
*(volatile u32_t *)(e->regs + reg) = value;
}
/*
* Set bits in a register.
*/
static void
e1000_reg_set(e1000_t * e, uint32_t reg, uint32_t value)
{
uint32_t data;
/* First read the current value. */
data = e1000_reg_read(e, reg);
/* Set bits, and write back. */
e1000_reg_write(e, reg, data | value);
}
/*
* Clear bits in a register.
*/
static void
e1000_reg_unset(e1000_t * e, uint32_t reg, uint32_t value)
{
uint32_t data;
/* First read the current value. */
data = e1000_reg_read(e, reg);
/* Unset bits, and write back. */
e1000_reg_write(e, reg, data & ~value);
}
/*
* Read from EEPROM.
*/
static u16_t
eeprom_eerd(e1000_t * e, int reg)
{
u32_t data;
/* Request EEPROM read. */
e1000_reg_write(e, E1000_REG_EERD,
(reg << e->eeprom_addr_off) | (E1000_REG_EERD_START));
/* Wait until ready. */
while (!((data = (e1000_reg_read(e, E1000_REG_EERD))) &
e->eeprom_done_bit));
return data >> 16;
}
/*
* Initialize ICH8 flash.
*/
static int
eeprom_ich_init(e1000_t * e)
{
union ich8_hws_flash_status hsfsts;
int ret_val = -1;
int i = 0;
hsfsts.regval = E1000_READ_FLASH_REG16(e, ICH_FLASH_HSFSTS);
/* Check if the flash descriptor is valid */
if (hsfsts.hsf_status.fldesvalid == 0) {
E1000_DEBUG(3, ("Flash descriptor invalid. "
"SW Sequencing must be used."));
return ret_val;
}
/* Clear FCERR and DAEL in hw status by writing 1 */
hsfsts.hsf_status.flcerr = 1;
hsfsts.hsf_status.dael = 1;
E1000_WRITE_FLASH_REG16(e, ICH_FLASH_HSFSTS, hsfsts.regval);
/*
* Either we should have a hardware SPI cycle in progress bit to check
* against, in order to start a new cycle or FDONE bit should be
* changed in the hardware so that it is 1 after hardware reset, which
* can then be used as an indication whether a cycle is in progress or
* has been completed.
*/
if (hsfsts.hsf_status.flcinprog == 0) {
/*
* There is no cycle running at present, so we can start a
* cycle. Begin by setting Flash Cycle Done.
*/
hsfsts.hsf_status.flcdone = 1;
E1000_WRITE_FLASH_REG16(e, ICH_FLASH_HSFSTS, hsfsts.regval);
ret_val = 0;
} else {
/*
* Otherwise poll for sometime so the current cycle has a
* chance to end before giving up.
*/
for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) {
hsfsts.regval = E1000_READ_FLASH_REG16(e,
ICH_FLASH_HSFSTS);
if (hsfsts.hsf_status.flcinprog == 0) {
ret_val = 0;
break;
}
micro_delay(16000);
}
if (ret_val == 0) {
/*
* Successful in waiting for previous cycle to timeout,
* now set the Flash Cycle Done.
*/
hsfsts.hsf_status.flcdone = 1;
E1000_WRITE_FLASH_REG16(e, ICH_FLASH_HSFSTS,
hsfsts.regval);
} else {
E1000_DEBUG(3,
("Flash controller busy, cannot get access"));
}
}
return ret_val;
}
/*
* Start ICH8 flash cycle.
*/
static int
eeprom_ich_cycle(e1000_t * e, u32_t timeout)
{
union ich8_hws_flash_ctrl hsflctl;
union ich8_hws_flash_status hsfsts;
int ret_val = -1;
u32_t i = 0;
E1000_DEBUG(3, ("e1000_flash_cycle_ich8lan"));
/* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
hsflctl.regval = E1000_READ_FLASH_REG16(e, ICH_FLASH_HSFCTL);
hsflctl.hsf_ctrl.flcgo = 1;
E1000_WRITE_FLASH_REG16(e, ICH_FLASH_HSFCTL, hsflctl.regval);
/* Wait till the FDONE bit is set to 1 */
do {
hsfsts.regval = E1000_READ_FLASH_REG16(e, ICH_FLASH_HSFSTS);
if (hsfsts.hsf_status.flcdone == 1)
break;
micro_delay(16000);
} while (i++ < timeout);
if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0)
ret_val = 0;
return ret_val;
}
/*
* Read from ICH8 flash.
*/
static u16_t
eeprom_ich(e1000_t * e, int reg)
{
union ich8_hws_flash_status hsfsts;
union ich8_hws_flash_ctrl hsflctl;
u32_t flash_linear_addr;
u32_t flash_data = 0;
int ret_val = -1;
u8_t count = 0;
u16_t data = 0;
E1000_DEBUG(3, ("e1000_read_flash_data_ich8lan"));
if (reg > ICH_FLASH_LINEAR_ADDR_MASK)
return data;
reg *= sizeof(u16_t);
flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & reg) +
e->flash_base_addr;
do {
micro_delay(16000);
/* Steps */
ret_val = eeprom_ich_init(e);
if (ret_val != 0)
break;
hsflctl.regval = E1000_READ_FLASH_REG16(e, ICH_FLASH_HSFCTL);
/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
hsflctl.hsf_ctrl.fldbcount = 1;
hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
E1000_WRITE_FLASH_REG16(e, ICH_FLASH_HSFCTL, hsflctl.regval);
E1000_WRITE_FLASH_REG(e, ICH_FLASH_FADDR, flash_linear_addr);
ret_val = eeprom_ich_cycle(e, ICH_FLASH_READ_COMMAND_TIMEOUT);
/*
* Check if FCERR is set to 1, if set to 1, clear it and try
* the whole sequence a few more times, else read in (shift in)
* the Flash Data0, the order is least significant byte first
* msb to lsb.
*/
if (ret_val == 0) {
flash_data = E1000_READ_FLASH_REG(e, ICH_FLASH_FDATA0);
data = (u16_t)(flash_data & 0x0000FFFF);
break;
} else {
/*
* If we've gotten here, then things are probably
* completely hosed, but if the error condition is
* detected, it won't hurt to give it another try...
* ICH_FLASH_CYCLE_REPEAT_COUNT times.
*/
hsfsts.regval = E1000_READ_FLASH_REG16(e,
ICH_FLASH_HSFSTS);
if (hsfsts.hsf_status.flcerr == 1) {
/* Repeat for some time before giving up. */
continue;
} else if (hsfsts.hsf_status.flcdone == 0) {
E1000_DEBUG(3, ("Timeout error - flash cycle "
"did not complete."));
break;
}
}
} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
return data;
}