static int tx_tail;
static int rx_tail, rx_last;
-static struct pci_device_id supported[] = {
+static struct pci_device_id e1000_supported[] = {
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82542},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_FIBER},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_COPPER},
* If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
* valid.
*****************************************************************************/
-static int
-e1000_validate_eeprom_checksum(struct eth_device *nic)
+static int e1000_validate_eeprom_checksum(struct e1000_hw *hw)
{
- struct e1000_hw *hw = nic->priv;
- uint16_t checksum = 0;
- uint16_t i, eeprom_data;
+ uint16_t i, checksum, checksum_reg, *buf;
DEBUGFUNC();
- for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
- if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
- DEBUGOUT("EEPROM Read Error\n");
- return -E1000_ERR_EEPROM;
- }
- checksum += eeprom_data;
+ /* Allocate a temporary buffer */
+ buf = malloc(sizeof(buf[0]) * (EEPROM_CHECKSUM_REG + 1));
+ if (!buf) {
+ E1000_ERR(hw->nic, "Unable to allocate EEPROM buffer!\n");
+ return -E1000_ERR_EEPROM;
}
- if (checksum == (uint16_t) EEPROM_SUM) {
- return 0;
- } else {
- DEBUGOUT("EEPROM Checksum Invalid\n");
+ /* Read the EEPROM */
+ if (e1000_read_eeprom(hw, 0, EEPROM_CHECKSUM_REG + 1, buf) < 0) {
+ E1000_ERR(hw->nic, "Unable to read EEPROM!\n");
return -E1000_ERR_EEPROM;
}
+
+ /* Compute the checksum */
+ for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
+ checksum += buf[i];
+ checksum = ((uint16_t)EEPROM_SUM) - checksum;
+ checksum_reg = buf[i];
+
+ /* Verify it! */
+ if (checksum == checksum_reg)
+ return 0;
+
+ /* Hrm, verification failed, print an error */
+ E1000_ERR(hw->nic, "EEPROM checksum is incorrect!\n");
+ E1000_ERR(hw->nic, " ...register was 0x%04hx, calculated 0x%04hx\n",
+ checksum_reg, checksum);
+
+ return -E1000_ERR_EEPROM;
}
/*****************************************************************************
return E1000_SUCCESS;
}
+static boolean_t e1000_is_second_port(struct e1000_hw *hw)
+{
+ switch (hw->mac_type) {
+ case e1000_80003es2lan:
+ case e1000_82546:
+ case e1000_82571:
+ if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+ return TRUE;
+ /* Fallthrough */
+ default:
+ return FALSE;
+ }
+}
+
/******************************************************************************
* Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
* second function of dual function devices
nic->enetaddr[i] = eeprom_data & 0xff;
nic->enetaddr[i + 1] = (eeprom_data >> 8) & 0xff;
}
- if ((hw->mac_type == e1000_82546) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
- /* Invert the last bit if this is the second device */
- nic->enetaddr[5] += 1;
- }
+
+ /* Invert the last bit if this is the second device */
+ if (e1000_is_second_port(hw))
+ nic->enetaddr[5] ^= 1;
+
#ifdef CONFIG_E1000_FALLBACK_MAC
if ( *(u32*)(nic->enetaddr) == 0 || *(u32*)(nic->enetaddr) == ~0 ) {
unsigned char fb_mac[NODE_ADDRESS_SIZE] = CONFIG_E1000_FALLBACK_MAC;
static int32_t
e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data)
{
+ uint16_t swfw = E1000_SWFW_PHY0_SM;
uint32_t reg_val;
- uint16_t swfw;
DEBUGFUNC();
- if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ if (e1000_is_second_port(hw))
swfw = E1000_SWFW_PHY1_SM;
- } else {
- swfw = E1000_SWFW_PHY0_SM;
- }
+
if (e1000_swfw_sync_acquire(hw, swfw))
return -E1000_ERR_SWFW_SYNC;
static int32_t
e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data)
{
+ uint16_t swfw = E1000_SWFW_PHY0_SM;
uint32_t reg_val;
- uint16_t swfw;
DEBUGFUNC();
- if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ if (e1000_is_second_port(hw))
swfw = E1000_SWFW_PHY1_SM;
- } else {
- swfw = E1000_SWFW_PHY0_SM;
- }
+
if (e1000_swfw_sync_acquire(hw, swfw))
return -E1000_ERR_SWFW_SYNC;
default:
mdelay(10);
break;
+
case e1000_80003es2lan:
/* Separate *_CFG_DONE_* bit for each port */
- if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+ if (e1000_is_second_port(hw))
cfg_mask = E1000_EEPROM_CFG_DONE_PORT_1;
- /* Fall Through */
+ /* Fall Through */
+
case e1000_82571:
case e1000_82572:
while (timeout) {
int32_t
e1000_phy_hw_reset(struct e1000_hw *hw)
{
+ uint16_t swfw = E1000_SWFW_PHY0_SM;
uint32_t ctrl, ctrl_ext;
uint32_t led_ctrl;
int32_t ret_val;
- uint16_t swfw;
DEBUGFUNC();
DEBUGOUT("Resetting Phy...\n");
if (hw->mac_type > e1000_82543) {
- if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ if (e1000_is_second_port(hw))
swfw = E1000_SWFW_PHY1_SM;
- } else {
- swfw = E1000_SWFW_PHY0_SM;
- }
+
if (e1000_swfw_sync_acquire(hw, swfw)) {
DEBUGOUT("Unable to acquire swfw sync\n");
return -E1000_ERR_SWFW_SYNC;
}
+
/* Read the device control register and assert the E1000_CTRL_PHY_RST
* bit. Then, take it out of reset.
*/
**/
static int
-e1000_sw_init(struct eth_device *nic, int cardnum)
+e1000_sw_init(struct eth_device *nic)
{
struct e1000_hw *hw = (typeof(hw)) nic->priv;
int result;
/* identify the MAC */
result = e1000_set_mac_type(hw);
if (result) {
- E1000_ERR("Unknown MAC Type\n");
+ E1000_ERR(hw->nic, "Unknown MAC Type\n");
return result;
}
break;
}
- /* lan a vs. lan b settings */
- if (hw->mac_type == e1000_82546)
- /*this also works w/ multiple 82546 cards */
- /*but not if they're intermingled /w other e1000s */
- hw->lan_loc = (cardnum % 2) ? e1000_lan_b : e1000_lan_a;
- else
- hw->lan_loc = e1000_lan_a;
-
/* flow control settings */
hw->fc_high_water = E1000_FC_HIGH_THRESH;
hw->fc_low_water = E1000_FC_LOW_THRESH;
if (ret_val < 0) {
if ((ret_val == -E1000_ERR_NOLINK) ||
(ret_val == -E1000_ERR_TIMEOUT)) {
- E1000_ERR("Valid Link not detected\n");
+ E1000_ERR(hw->nic, "Valid Link not detected\n");
} else {
- E1000_ERR("Hardware Initialization Failed\n");
+ E1000_ERR(hw->nic, "Hardware Initialization Failed\n");
}
return 0;
}
int
e1000_initialize(bd_t * bis)
{
+ unsigned int i;
pci_dev_t devno;
- int card_number = 0;
- struct eth_device *nic = NULL;
- struct e1000_hw *hw = NULL;
- u32 iobase;
- int idx = 0;
- u32 PciCommandWord;
DEBUGFUNC();
- while (1) { /* Find PCI device(s) */
- if ((devno = pci_find_devices(supported, idx++)) < 0) {
- break;
- }
-
- pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase);
- iobase &= ~0xf; /* Mask the bits that say "this is an io addr" */
- DEBUGOUT("e1000#%d: iobase 0x%08x\n", card_number, iobase);
-
- pci_write_config_dword(devno, PCI_COMMAND,
- PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
- /* Check if I/O accesses and Bus Mastering are enabled. */
- pci_read_config_dword(devno, PCI_COMMAND, &PciCommandWord);
- if (!(PciCommandWord & PCI_COMMAND_MEMORY)) {
- printf("Error: Can not enable MEM access.\n");
- continue;
- } else if (!(PciCommandWord & PCI_COMMAND_MASTER)) {
- printf("Error: Can not enable Bus Mastering.\n");
- continue;
- }
-
- nic = (struct eth_device *) malloc(sizeof (*nic));
- if (!nic) {
- printf("Error: e1000 - Can not alloc memory\n");
- return 0;
- }
+ /* Find and probe all the matching PCI devices */
+ for (i = 0; (devno = pci_find_devices(e1000_supported, i)) >= 0; i++) {
+ u32 val;
- hw = (struct e1000_hw *) malloc(sizeof (*hw));
- if (!hw) {
+ /*
+ * These will never get freed due to errors, this allows us to
+ * perform SPI EEPROM programming from U-boot, for example.
+ */
+ struct eth_device *nic = malloc(sizeof(*nic));
+ struct e1000_hw *hw = malloc(sizeof(*hw));
+ if (!nic || !hw) {
+ printf("e1000#%u: Out of Memory!\n", i);
free(nic);
- printf("Error: e1000 - Can not alloc memory\n");
- return 0;
+ free(hw);
+ continue;
}
+ /* Make sure all of the fields are initially zeroed */
memset(nic, 0, sizeof(*nic));
memset(hw, 0, sizeof(*hw));
+ /* Assign the passed-in values */
+ hw->cardnum = i;
hw->pdev = devno;
+ hw->nic = nic;
nic->priv = hw;
- sprintf(nic->name, "e1000#%d", card_number);
+ /* Generate a card name */
+ sprintf(nic->name, "e1000#%u", hw->cardnum);
+
+ /* Print a debug message with the IO base address */
+ pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &val);
+ E1000_DBG(nic, "iobase 0x%08x\n", val & 0xfffffff0);
+
+ /* Try to enable I/O accesses and bus-mastering */
+ val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+ pci_write_config_dword(devno, PCI_COMMAND, val);
+
+ /* Make sure it worked */
+ pci_read_config_dword(devno, PCI_COMMAND, &val);
+ if (!(val & PCI_COMMAND_MEMORY)) {
+ E1000_ERR(nic, "Can't enable I/O memory\n");
+ continue;
+ }
+ if (!(val & PCI_COMMAND_MASTER)) {
+ E1000_ERR(nic, "Can't enable bus-mastering\n");
+ continue;
+ }
/* Are these variables needed? */
hw->fc = e1000_fc_default;
hw->autoneg_failed = 0;
hw->autoneg = 1;
hw->get_link_status = TRUE;
- hw->hw_addr =
- pci_map_bar(devno, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+ hw->hw_addr = pci_map_bar(devno, PCI_BASE_ADDRESS_0,
+ PCI_REGION_MEM);
hw->mac_type = e1000_undefined;
/* MAC and Phy settings */
- if (e1000_sw_init(nic, card_number) < 0) {
- free(hw);
- free(nic);
- return 0;
+ if (e1000_sw_init(nic) < 0) {
+ E1000_ERR(nic, "Software init failed\n");
+ continue;
}
if (e1000_check_phy_reset_block(hw))
- printf("phy reset block error \n");
+ E1000_ERR(nic, "PHY Reset is blocked!\n");
+
+ /* Basic init was OK, reset the hardware */
e1000_reset_hw(hw);
+
+ /* Validate the EEPROM and get chipset information */
#if !(defined(CONFIG_AP1000) || defined(CONFIG_MVBC_1G))
if (e1000_init_eeprom_params(hw)) {
- printf("The EEPROM Checksum Is Not Valid\n");
- free(hw);
- free(nic);
- return 0;
- }
- if (e1000_validate_eeprom_checksum(nic) < 0) {
- printf("The EEPROM Checksum Is Not Valid\n");
- free(hw);
- free(nic);
- return 0;
+ E1000_ERR(nic, "EEPROM is invalid!\n");
+ continue;
}
+ if (e1000_validate_eeprom_checksum(hw))
+ continue;
#endif
e1000_read_mac_addr(nic);
-
- /* get the bus type information */
e1000_get_bus_type(hw);
- printf("e1000: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ printf("e1000: %02x:%02x:%02x:%02x:%02x:%02x\n ",
nic->enetaddr[0], nic->enetaddr[1], nic->enetaddr[2],
nic->enetaddr[3], nic->enetaddr[4], nic->enetaddr[5]);
+ /* Set up the function pointers and register the device */
nic->init = e1000_init;
nic->recv = e1000_poll;
nic->send = e1000_transmit;
nic->halt = e1000_disable;
-
eth_register(nic);
-
- card_number++;
}
- return card_number;
+
+ return i;
}