]> git.sur5r.net Git - u-boot/blobdiff - drivers/net/e1000.c
e1000: Rewrite EEPROM checksum error to give more information
[u-boot] / drivers / net / e1000.c
index 01bdf814fd8605d8fbcdf27fa6c8a2a453eb82de..39057d231683bb737257dec26dd61a00447dbf79 100644 (file)
@@ -66,7 +66,7 @@ static struct e1000_rx_desc *rx_base;
 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},
@@ -876,29 +876,41 @@ e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset,
  * 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;
 }
 
 /*****************************************************************************
@@ -1099,6 +1111,20 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
        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
@@ -1125,11 +1151,11 @@ e1000_read_mac_addr(struct eth_device *nic)
                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;
@@ -2535,16 +2561,13 @@ e1000_check_mng_mode(struct e1000_hw *hw)
 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;
 
@@ -2559,16 +2582,13 @@ e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data)
 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;
 
@@ -4266,11 +4286,13 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
        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) {
@@ -4299,10 +4321,10 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
 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();
 
@@ -4315,16 +4337,14 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
        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.
                 */
@@ -4753,7 +4773,7 @@ e1000_set_media_type(struct e1000_hw *hw)
  **/
 
 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;
@@ -4771,7 +4791,7 @@ e1000_sw_init(struct eth_device *nic, int cardnum)
        /* 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;
        }
 
@@ -4786,14 +4806,6 @@ e1000_sw_init(struct eth_device *nic, int cardnum)
                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;
@@ -5111,9 +5123,9 @@ e1000_init(struct eth_device *nic, bd_t * bis)
        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;
        }
@@ -5162,57 +5174,59 @@ You should omit the last argument struct pci_device * for a non-PCI NIC
 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;
@@ -5220,50 +5234,44 @@ e1000_initialize(bd_t * bis)
                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;
 }