diff options
author | pdeuskar <pdeuskar@FreeBSD.org> | 2002-07-16 16:55:03 +0000 |
---|---|---|
committer | pdeuskar <pdeuskar@FreeBSD.org> | 2002-07-16 16:55:03 +0000 |
commit | 7995d306bcdcaa2681090cfcaed794f15a85c77d (patch) | |
tree | 284e4f4e8951c0bd2650ac202095af1ba0c16b3f /sys/dev/em | |
parent | 4410d83dcc36f0f5f77a472d9371eb764d2e3d62 (diff) | |
download | FreeBSD-src-7995d306bcdcaa2681090cfcaed794f15a85c77d.zip FreeBSD-src-7995d306bcdcaa2681090cfcaed794f15a85c77d.tar.gz |
- Use IO mode to reset the controller (82544 and beyond)
- Read the Mac address only once during attach.
(This fixes the failover issue observed using the bonding driver)
MFC after: 3 days
Diffstat (limited to 'sys/dev/em')
-rw-r--r-- | sys/dev/em/README | 28 | ||||
-rw-r--r-- | sys/dev/em/if_em.c | 127 | ||||
-rw-r--r-- | sys/dev/em/if_em.h | 4 | ||||
-rw-r--r-- | sys/dev/em/if_em_hw.c | 301 | ||||
-rw-r--r-- | sys/dev/em/if_em_hw.h | 34 | ||||
-rw-r--r-- | sys/dev/em/if_em_osdep.h | 38 |
6 files changed, 429 insertions, 103 deletions
diff --git a/sys/dev/em/README b/sys/dev/em/README index cb3c8b9..4603056 100644 --- a/sys/dev/em/README +++ b/sys/dev/em/README @@ -1,9 +1,8 @@ $FreeBSD$ - FreeBSD* Driver for the Intel(R) PRO/1000 Family of Adapters ============================================================ -April 3, 2002 +July 2, 2002 Contents @@ -24,14 +23,13 @@ In This Release This file describes the FreeBSD* driver, version 1.3.x, for the Intel(R) PRO/1000 Family of Adapters. This driver has been developed for use with -FreeBSD, version 4.5. +FreeBSD, version 4.6. As a new feature for this release, the driver is now +compiled by default into the FreeBSD 4.6 kernel. The driver supports Transmit/Receive Checksum Offload and Jumbo Frames on all but the 82542-based adapters. For specific adapters, refer to the Supported Adapters section below. -Support for VLANs has been added as a new feature in this driver version. - For questions related to hardware requirements, refer to the documentation supplied with your Intel PRO/1000 adapter. All hardware requirements listed apply to use with FreeBSD. @@ -146,31 +144,19 @@ NOTE: You must have kernel sources installed in order to compile the driver 7. If you want to compile the driver into the kernel, enter: - mkdir /usr/src/sys/dev/em cd em-x.x.x/src cp if_em* /usr/src/sys/dev/em - mkdir /usr/src/sys/modules/em cp Makefile /usr/src/sys/modules/em - Edit Makefile at /usr/src/sys/modules to add the em subdirectory. - - Edit your config file and add the following line, if it is not already - in the file: - - device em - - Edit your config file, and remove the 'device wx' line from the file. - - Edit the /usr/src/sys/conf/files.i386 file, and add the following lines: + Edit the /usr/src/sys/conf/files.i386 file, and add the following line: - dev/em/if_em.c optional em dev/em/if_em_hw.c optional em - Remove the following files from the /usr/src/sys/conf/files.i386 file, if + Remove the following lines from the /usr/src/sys/conf/files.i386 file, if they exist: - /dev/em/if_em_fxhw.c - /dev/em/if_em_phy.c + /dev/em/if_em_fxhw.c optional em + /dev/em/if_em_phy.c optional em Compile and install the kernel. diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c index e91abd6..f28143a 100644 --- a/sys/dev/em/if_em.c +++ b/sys/dev/em/if_em.c @@ -53,7 +53,7 @@ struct adapter *em_adapter_list = NULL; * Driver version *********************************************************************/ -char em_driver_version[] = "1.3.8"; +char em_driver_version[] = "1.3.14"; /********************************************************************* @@ -128,20 +128,20 @@ static int em_allocate_receive_structures(struct adapter *); static int em_allocate_transmit_structures(struct adapter *); static void em_process_receive_interrupts(struct adapter *); static void em_receive_checksum(struct adapter *, - struct em_rx_desc * rx_desc, - struct mbuf *); + struct em_rx_desc * rx_desc, + struct mbuf *); static void em_transmit_checksum_setup(struct adapter *, - struct mbuf *, - struct em_tx_buffer *, - u_int32_t *, - u_int32_t *); + struct mbuf *, + struct em_tx_buffer *, + u_int32_t *, + u_int32_t *); static void em_set_promisc(struct adapter *); static void em_disable_promisc(struct adapter *); static void em_set_multi(struct adapter *); static void em_print_hw_stats(struct adapter *); static void em_print_link_status(struct adapter *); static int em_get_buf(struct em_rx_buffer *, struct adapter *, - struct mbuf *); + struct mbuf *); static void em_enable_vlans(struct adapter *adapter); /********************************************************************* @@ -267,7 +267,6 @@ em_attach(device_t dev) adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT; adapter->hw.tbi_compatibility_en = TRUE; adapter->rx_buffer_len = EM_RXBUFFER_2048; - adapter->rx_checksum = EM_ENABLE_RXCSUM_OFFLOAD; adapter->hw.fc_high_water = FC_DEFAULT_HI_THRESH; adapter->hw.fc_low_water = FC_DEFAULT_LO_THRESH; @@ -339,6 +338,16 @@ em_attach(device_t dev) return(EIO); } + /* Copy the permanent MAC address out of the EEPROM */ + if (em_read_mac_addr(&adapter->hw) < 0) { + printf("em%d: EEPROM read error while reading mac address\n", + adapter->unit); + return(EIO); + } + + memcpy(adapter->interface_data.ac_enaddr, adapter->hw.mac_addr, + ETH_LENGTH_OF_ADDRESS); + /* Setup OS specific network interface */ em_setup_interface(dev, adapter); @@ -1051,7 +1060,11 @@ em_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) ifmr->ifm_active |= IFM_100_TX; break; case 1000: +#if __FreeBSD_version < 500000 + ifmr->ifm_active |= IFM_1000_TX; +#else ifmr->ifm_active |= IFM_1000_T; +#endif break; } if (adapter->link_duplex == FULL_DUPLEX) @@ -1087,7 +1100,11 @@ em_media_change(struct ifnet *ifp) adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT; break; case IFM_1000_SX: +#if __FreeBSD_version < 500000 + case IFM_1000_TX: +#else case IFM_1000_T: +#endif adapter->hw.autoneg = DO_AUTO_NEG; adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; break; @@ -1183,26 +1200,53 @@ em_identify_hardware(struct adapter * adapter) static int em_allocate_pci_resources(struct adapter * adapter) { - int resource_id = EM_MMBA; + int i, val, rid; device_t dev = adapter->dev; + rid = EM_MMBA; adapter->res_memory = bus_alloc_resource(dev, SYS_RES_MEMORY, - &resource_id, 0, ~0, 1, + &rid, 0, ~0, 1, RF_ACTIVE); if (!(adapter->res_memory)) { printf("em%d: Unable to allocate bus resource: memory\n", adapter->unit); return(ENXIO); } - adapter->osdep.bus_space_tag = + adapter->osdep.mem_bus_space_tag = rman_get_bustag(adapter->res_memory); - adapter->osdep.bus_space_handle = + adapter->osdep.mem_bus_space_handle = rman_get_bushandle(adapter->res_memory); - adapter->hw.hw_addr = (uint8_t *)&adapter->osdep.bus_space_handle; + adapter->hw.hw_addr = (uint8_t *)&adapter->osdep.mem_bus_space_handle; + - resource_id = 0x0; + if (adapter->hw.mac_type > em_82543) { + /* Figure our where our IO BAR is ? */ + rid = EM_MMBA; + for (i = 0; i < 5; i++) { + val = pci_read_config(dev, rid, 4); + if (val & 0x00000001) { + adapter->io_rid = rid; + break; + } + rid += 4; + } + + adapter->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, + &adapter->io_rid, 0, ~0, 1, + RF_ACTIVE); + if (!(adapter->res_ioport)) { + printf("em%d: Unable to allocate bus resource: ioport\n", + adapter->unit); + return(ENXIO); + } + + adapter->hw.io_base = + rman_get_start(adapter->res_ioport); + } + + rid = 0x0; adapter->res_interrupt = bus_alloc_resource(dev, SYS_RES_IRQ, - &resource_id, 0, ~0, 1, + &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); if (!(adapter->res_interrupt)) { printf("em%d: Unable to allocate bus resource: interrupt\n", @@ -1237,6 +1281,11 @@ em_free_pci_resources(struct adapter * adapter) bus_release_resource(dev, SYS_RES_MEMORY, EM_MMBA, adapter->res_memory); } + + if (adapter->res_ioport != NULL) { + bus_release_resource(dev, SYS_RES_IOPORT, adapter->io_rid, + adapter->res_ioport); + } return; } @@ -1260,16 +1309,6 @@ em_hardware_init(struct adapter * adapter) adapter->unit); return(EIO); } - /* Copy the permanent MAC address and part number out of the EEPROM */ - if (em_read_mac_addr(&adapter->hw) < 0) { - printf("em%d: EEPROM read error while reading mac address\n", - adapter->unit); - return(EIO); - } - - memcpy(adapter->interface_data.ac_enaddr, adapter->hw.mac_addr, - ETH_LENGTH_OF_ADDRESS); - if (em_read_part_num(&adapter->hw, &(adapter->part_num)) < 0) { printf("em%d: EEPROM read error while reading part number\n", @@ -1351,9 +1390,15 @@ em_setup_interface(device_t dev, struct adapter * adapter) 0, NULL); ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL); +#if __FreeBSD_version < 500000 + ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_TX | IFM_FDX, + 0, NULL); + ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_TX, 0, NULL); +#else ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL); +#endif } ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); @@ -1799,8 +1844,9 @@ em_initialize_receive_unit(struct adapter * adapter) switch (adapter->rx_buffer_len) { + default: case EM_RXBUFFER_2048: - reg_rctl |= E1000_RCTL_SZ_2048 | E1000_RCTL_LPE; + reg_rctl |= E1000_RCTL_SZ_2048; break; case EM_RXBUFFER_4096: reg_rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | E1000_RCTL_LPE; @@ -1811,10 +1857,11 @@ em_initialize_receive_unit(struct adapter * adapter) case EM_RXBUFFER_16384: reg_rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX | E1000_RCTL_LPE; break; - default: - reg_rctl |= E1000_RCTL_SZ_2048; } + if (ifp->if_mtu > ETHERMTU) + reg_rctl |= E1000_RCTL_LPE; + /* Enable 82543 Receive Checksum Offload for TCP and UDP */ if ((adapter->hw.mac_type >= em_82543) && (ifp->if_capenable & IFCAP_RXCSUM)) { @@ -2091,14 +2138,32 @@ em_disable_intr(struct adapter *adapter) return; } -void em_write_pci_cfg(struct em_hw *adapter, +void em_write_pci_cfg(struct em_hw *hw, uint32_t reg, uint16_t *value) { - pci_write_config(((struct em_osdep *)adapter->back)->dev, reg, + pci_write_config(((struct em_osdep *)hw->back)->dev, reg, *value, 2); } +void em_read_pci_cfg(struct em_hw *hw, uint32_t reg, + uint16_t *value) +{ + *value = pci_read_config(((struct em_osdep *)hw->back)->dev, + reg, 2); + return; +} + +uint32_t em_io_read(struct em_hw *hw, uint32_t port) +{ + return(inl(port)); +} + +void em_io_write(struct em_hw *hw, uint32_t port, uint32_t value) +{ + outl(port, value); + return; +} /********************************************************************** * diff --git a/sys/dev/em/if_em.h b/sys/dev/em/if_em.h index 3dc8b44..d548437 100644 --- a/sys/dev/em/if_em.h +++ b/sys/dev/em/if_em.h @@ -88,7 +88,6 @@ SUCH DAMAGE. #define AUTONEG_ADV_DEFAULT (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ ADVERTISE_100_HALF | ADVERTISE_100_FULL | \ ADVERTISE_1000_FULL) -#define EM_ENABLE_RXCSUM_OFFLOAD 1 #define EM_REPORT_TX_EARLY 2 #define EM_CHECKSUM_FEATURES (CSUM_TCP | CSUM_UDP) #define EM_MAX_INTR 3 @@ -185,10 +184,12 @@ struct adapter { struct em_osdep osdep; struct device *dev; struct resource *res_memory; + struct resource *res_ioport; struct resource *res_interrupt; void *int_handler_tag; struct ifmedia media; struct callout_handle timer_handle; + int io_rid; u_int8_t unit; /* Info about the board itself */ @@ -199,7 +200,6 @@ struct adapter { u_int32_t tx_int_delay; u_int32_t rx_int_delay; - u_int8_t rx_checksum; XSUM_CONTEXT_T active_checksum_context; /* Transmit definitions */ diff --git a/sys/dev/em/if_em_hw.c b/sys/dev/em/if_em_hw.c index 17135f1..c000bb4 100644 --- a/sys/dev/em/if_em_hw.c +++ b/sys/dev/em/if_em_hw.c @@ -109,7 +109,11 @@ em_reset_hw(struct em_hw *hw) */ DEBUGOUT("Issuing a global reset to MAC\n"); ctrl = E1000_READ_REG(hw, CTRL); - E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); + + if(hw->mac_type > em_82543) + E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); + else + E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); /* Force a reload from the EEPROM if necessary */ if(hw->mac_type < em_82540) { @@ -161,14 +165,18 @@ em_init_hw(struct em_hw *hw) uint32_t i; int32_t ret_val; uint16_t pci_cmd_word; + uint16_t pcix_cmd_word; + uint16_t pcix_stat_hi_word; + uint16_t cmd_mmrbc; + uint16_t stat_mmrbc; DEBUGFUNC("em_init_hw"); /* Initialize Identification LED */ ret_val = em_id_led_init(hw); if(ret_val < 0) { - DEBUGOUT("Error Initializing Identification LED\n"); - return ret_val; + DEBUGOUT("Error Initializing Identification LED\n"); + return ret_val; } /* Set the Media Type and exit with error if it is not valid. */ @@ -235,6 +243,21 @@ em_init_hw(struct em_hw *hw) E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR); } + /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ + if(hw->bus_type == em_bus_type_pcix) { + em_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); + em_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word); + cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >> + PCIX_COMMAND_MMRBC_SHIFT; + stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> + PCIX_STATUS_HI_MMRBC_SHIFT; + if(cmd_mmrbc > stat_mmrbc) { + pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; + pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; + em_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); + } + } + /* Call a subroutine to configure the link and setup flow control. */ ret_val = em_setup_link(hw); @@ -2337,6 +2360,47 @@ em_standby_eeprom(struct em_hw *hw) usec_delay(50); } +/****************************************************************************** + * Raises then lowers the EEPROM's clock pin + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +static void +em_clock_eeprom(struct em_hw *hw) +{ + uint32_t eecd; + + eecd = E1000_READ_REG(hw, EECD); + + /* Rising edge of clock */ + eecd |= E1000_EECD_SK; + E1000_WRITE_REG(hw, EECD, eecd); + usec_delay(50); + + /* Falling edge of clock */ + eecd &= ~E1000_EECD_SK; + E1000_WRITE_REG(hw, EECD, eecd); + usec_delay(50); +} + +/****************************************************************************** + * Terminates a command by lowering the EEPROM's chip select pin + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +static void +em_cleanup_eeprom(struct em_hw *hw) +{ + uint32_t eecd; + + eecd = E1000_READ_REG(hw, EECD); + + eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); + + E1000_WRITE_REG(hw, EECD, eecd); + + em_clock_eeprom(hw); +} /****************************************************************************** * Reads a 16 bit word from the EEPROM. @@ -2439,6 +2503,152 @@ em_validate_eeprom_checksum(struct em_hw *hw) } /****************************************************************************** + * Calculates the EEPROM checksum and writes it to the EEPROM + * + * hw - Struct containing variables accessed by shared code + * + * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA. + * Writes the difference to word offset 63 of the EEPROM. + *****************************************************************************/ +int32_t +em_update_eeprom_checksum(struct em_hw *hw) +{ + uint16_t checksum = 0; + uint16_t i, eeprom_data; + + DEBUGFUNC("em_update_eeprom_checksum"); + + for(i = 0; i < EEPROM_CHECKSUM_REG; i++) { + if(em_read_eeprom(hw, i, &eeprom_data) < 0) { + DEBUGOUT("EEPROM Read Error\n"); + return -E1000_ERR_EEPROM; + } + checksum += eeprom_data; + } + checksum = (uint16_t) EEPROM_SUM - checksum; + if(em_write_eeprom(hw, EEPROM_CHECKSUM_REG, checksum) < 0) { + DEBUGOUT("EEPROM Write Error\n"); + return -E1000_ERR_EEPROM; + } + return 0; +} + +/****************************************************************************** + * Writes a 16 bit word to a given offset in the EEPROM. + * + * hw - Struct containing variables accessed by shared code + * offset - offset within the EEPROM to be written to + * data - 16 bit word to be writen to the EEPROM + * + * If em_update_eeprom_checksum is not called after this function, the + * EEPROM will most likely contain an invalid checksum. + *****************************************************************************/ +int32_t +em_write_eeprom(struct em_hw *hw, + uint16_t offset, + uint16_t data) +{ + uint32_t eecd; + uint32_t i = 0; + int32_t status = 0; + boolean_t large_eeprom = FALSE; + + DEBUGFUNC("em_write_eeprom"); + + /* Request EEPROM Access */ + if(hw->mac_type > em_82544) { + eecd = E1000_READ_REG(hw, EECD); + if(eecd & E1000_EECD_SIZE) large_eeprom = TRUE; + eecd |= E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + eecd = E1000_READ_REG(hw, EECD); + while((!(eecd & E1000_EECD_GNT)) && (i < 100)) { + i++; + usec_delay(5); + eecd = E1000_READ_REG(hw, EECD); + } + if(!(eecd & E1000_EECD_GNT)) { + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + DEBUGOUT("Could not acquire EEPROM grant\n"); + return -E1000_ERR_EEPROM; + } + } + + /* Prepare the EEPROM for writing */ + em_setup_eeprom(hw); + + /* Send the 9-bit (or 11-bit on large EEPROM) EWEN (write enable) command + * to the EEPROM (5-bit opcode plus 4/6-bit dummy). This puts the EEPROM + * into write/erase mode. + */ + em_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE, 5); + if(large_eeprom) + em_shift_out_ee_bits(hw, 0, 6); + else + em_shift_out_ee_bits(hw, 0, 4); + + /* Prepare the EEPROM */ + em_standby_eeprom(hw); + + /* Send the Write command (3-bit opcode + addr) */ + em_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE, 3); + if(large_eeprom) + /* If we have a 256 word EEPROM, there are 8 address bits */ + em_shift_out_ee_bits(hw, offset, 8); + else + /* If we have a 64 word EEPROM, there are 6 address bits */ + em_shift_out_ee_bits(hw, offset, 6); + + /* Send the data */ + em_shift_out_ee_bits(hw, data, 16); + + /* Toggle the CS line. This in effect tells to EEPROM to actually execute + * the command in question. + */ + em_standby_eeprom(hw); + + /* Now read DO repeatedly until is high (equal to '1'). The EEEPROM will + * signal that the command has been completed by raising the DO signal. + * If DO does not go high in 10 milliseconds, then error out. + */ + for(i = 0; i < 200; i++) { + eecd = E1000_READ_REG(hw, EECD); + if(eecd & E1000_EECD_DO) break; + usec_delay(50); + } + if(i == 200) { + DEBUGOUT("EEPROM Write did not complete\n"); + status = -E1000_ERR_EEPROM; + } + + /* Recover from write */ + em_standby_eeprom(hw); + + /* Send the 9-bit (or 11-bit on large EEPROM) EWDS (write disable) command + * to the EEPROM (5-bit opcode plus 4/6-bit dummy). This takes the EEPROM + * out of write/erase mode. + */ + em_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE, 5); + if(large_eeprom) + em_shift_out_ee_bits(hw, 0, 6); + else + em_shift_out_ee_bits(hw, 0, 4); + + /* Done with writing */ + em_cleanup_eeprom(hw); + + /* Stop requesting EEPROM access */ + if(hw->mac_type > em_82544) { + eecd = E1000_READ_REG(hw, EECD); + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + } + + return status; +} + +/****************************************************************************** * Reads the adapter's part number from the EEPROM * * hw - Struct containing variables accessed by shared code @@ -2775,12 +2985,12 @@ em_id_led_init(struct em_hw * hw) const uint32_t ledctl_off = E1000_LEDCTL_MODE_LED_OFF; uint16_t eeprom_data, i, temp; const uint16_t led_mask = 0x0F; - + DEBUGFUNC("em_id_led_init"); if(hw->mac_type < em_82540) { - /* Nothing to do */ - return 0; + /* Nothing to do */ + return 0; } ledctl = E1000_READ_REG(hw, LEDCTL); @@ -2797,39 +3007,39 @@ em_id_led_init(struct em_hw * hw) for(i = 0; i < 4; i++) { temp = (eeprom_data >> (i << 2)) & led_mask; switch(temp) { - case ID_LED_ON1_DEF2: - case ID_LED_ON1_ON2: - case ID_LED_ON1_OFF2: + case ID_LED_ON1_DEF2: + case ID_LED_ON1_ON2: + case ID_LED_ON1_OFF2: hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); hw->ledctl_mode1 |= ledctl_on << (i << 3); break; - case ID_LED_OFF1_DEF2: - case ID_LED_OFF1_ON2: - case ID_LED_OFF1_OFF2: + case ID_LED_OFF1_DEF2: + case ID_LED_OFF1_ON2: + case ID_LED_OFF1_OFF2: hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); hw->ledctl_mode1 |= ledctl_off << (i << 3); break; - default: - /* Do nothing */ - break; - } - switch(temp) { - case ID_LED_DEF1_ON2: - case ID_LED_ON1_ON2: - case ID_LED_OFF1_ON2: + default: + /* Do nothing */ + break; + } + switch(temp) { + case ID_LED_DEF1_ON2: + case ID_LED_ON1_ON2: + case ID_LED_OFF1_ON2: hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); hw->ledctl_mode2 |= ledctl_on << (i << 3); break; - case ID_LED_DEF1_OFF2: - case ID_LED_ON1_OFF2: - case ID_LED_OFF1_OFF2: + case ID_LED_DEF1_OFF2: + case ID_LED_ON1_OFF2: + case ID_LED_OFF1_OFF2: hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); hw->ledctl_mode2 |= ledctl_off << (i << 3); break; - default: - /* Do nothing */ - break; - } + default: + /* Do nothing */ + break; + } } return 0; } @@ -3278,4 +3488,41 @@ em_get_bus_info(struct em_hw *hw) hw->bus_width = (status & E1000_STATUS_BUS64) ? em_bus_width_64 : em_bus_width_32; } +/****************************************************************************** + * Reads a value from one of the devices registers using port I/O (as opposed + * memory mapped I/O). Only 82544 and newer devices support port I/O. + * + * hw - Struct containing variables accessed by shared code + * offset - offset to read from + *****************************************************************************/ +uint32_t +em_read_reg_io(struct em_hw *hw, + uint32_t offset) +{ + uint32_t io_addr = hw->io_base; + uint32_t io_data = hw->io_base + 4; + + em_io_write(hw, io_addr, offset); + return em_io_read(hw, io_data); +} + +/****************************************************************************** + * Writes a value to one of the devices registers using port I/O (as opposed to + * memory mapped I/O). Only 82544 and newer devices support port I/O. + * + * hw - Struct containing variables accessed by shared code + * offset - offset to write to + * value - value to write + *****************************************************************************/ +void +em_write_reg_io(struct em_hw *hw, + uint32_t offset, + uint32_t value) +{ + uint32_t io_addr = hw->io_base; + uint32_t io_data = hw->io_base + 4; + + em_io_write(hw, io_addr, offset); + em_io_write(hw, io_data, value); +} diff --git a/sys/dev/em/if_em_hw.h b/sys/dev/em/if_em_hw.h index 2daca23..f2bf253 100644 --- a/sys/dev/em/if_em_hw.h +++ b/sys/dev/em/if_em_hw.h @@ -199,6 +199,8 @@ int32_t em_validate_mdi_setting(struct em_hw *hw); /* EEPROM Functions */ int32_t em_read_eeprom(struct em_hw *hw, uint16_t reg, uint16_t *data); int32_t em_validate_eeprom_checksum(struct em_hw *hw); +int32_t em_update_eeprom_checksum(struct em_hw *hw); +int32_t em_write_eeprom(struct em_hw *hw, uint16_t reg, uint16_t data); int32_t em_read_part_num(struct em_hw *hw, uint32_t * part_num); int32_t em_read_mac_addr(struct em_hw * hw); @@ -225,7 +227,17 @@ void em_reset_adaptive(struct em_hw *hw); void em_update_adaptive(struct em_hw *hw); void em_tbi_adjust_stats(struct em_hw *hw, struct em_hw_stats *stats, uint32_t frame_len, uint8_t * mac_addr); void em_get_bus_info(struct em_hw *hw); +void em_read_pci_cfg(struct em_hw *hw, uint32_t reg, uint16_t * value); void em_write_pci_cfg(struct em_hw *hw, uint32_t reg, uint16_t * value); +/* Port I/O is only supported on 82544 and newer */ +uint32_t em_io_read(struct em_hw *hw, uint32_t port); +uint32_t em_read_reg_io(struct em_hw *hw, uint32_t offset); +void em_io_write(struct em_hw *hw, uint32_t port, uint32_t value); +void em_write_reg_io(struct em_hw *hw, uint32_t offset, uint32_t value); +#define E1000_READ_REG_IO(a, reg) \ + em_read_reg_io((a), E1000_##reg) +#define E1000_WRITE_REG_IO(a, reg, val) \ + em_write_reg_io((a), E1000_##reg, val) /* PCI Device IDs */ #define E1000_DEV_ID_82542 0x1000 @@ -840,6 +852,7 @@ struct em_hw { em_bus_speed bus_speed; em_bus_width bus_width; em_bus_type bus_type; + uint32_t io_base; uint32_t phy_id; uint32_t phy_addr; uint32_t original_fc; @@ -1295,6 +1308,7 @@ struct em_hw { #define EEPROM_EWDS_OPCODE 0x10 /* EERPOM erast/write disable */ /* EEPROM Word Offsets */ +#define EEPROM_COMPAT 0x0003 #define EEPROM_ID_LED_SETTINGS 0x0004 #define EEPROM_INIT_CONTROL1_REG 0x000A #define EEPROM_INIT_CONTROL2_REG 0x000F @@ -1305,9 +1319,9 @@ struct em_hw { #define ID_LED_RESERVED_0000 0x0000 #define ID_LED_RESERVED_FFFF 0xFFFF #define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ - (ID_LED_OFF1_OFF2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) + (ID_LED_OFF1_OFF2 << 8) | \ + (ID_LED_DEF1_DEF2 << 4) | \ + (ID_LED_DEF1_DEF2)) #define ID_LED_DEF1_DEF2 0x1 #define ID_LED_DEF1_ON2 0x2 #define ID_LED_DEF1_OFF2 0x3 @@ -1318,6 +1332,10 @@ struct em_hw { #define ID_LED_OFF1_ON2 0x8 #define ID_LED_OFF1_OFF2 0x9 +/* Mask bits for fields in Word 0x03 of the EEPROM */ +#define EEPROM_COMPAT_SERVER 0x0400 +#define EEPROM_COMPAT_CLIENT 0x0200 + /* Mask bits for fields in Word 0x0a of the EEPROM */ #define EEPROM_WORD0A_ILOS 0x0010 #define EEPROM_WORD0A_SWDPIO 0x01E0 @@ -1403,6 +1421,16 @@ struct em_hw { #define FC_DEFAULT_LO_THRESH (0x4000) /* 16KB */ #define FC_DEFAULT_TX_TIMER (0x100) /* ~130 us */ +/* PCIX Config space */ +#define PCIX_COMMAND_REGISTER 0xE6 +#define PCIX_STATUS_REGISTER_LO 0xE8 +#define PCIX_STATUS_REGISTER_HI 0xEA + +#define PCIX_COMMAND_MMRBC_MASK 0x000C +#define PCIX_COMMAND_MMRBC_SHIFT 0x2 +#define PCIX_STATUS_HI_MMRBC_MASK 0x0060 +#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5 + /* The number of bits that we need to shift right to move the "pause" * bits from the EEPROM (bits 13:12) to the "pause" (bits 8:7) field diff --git a/sys/dev/em/if_em_osdep.h b/sys/dev/em/if_em_osdep.h index e106e04..27db87d 100644 --- a/sys/dev/em/if_em_osdep.h +++ b/sys/dev/em/if_em_osdep.h @@ -86,48 +86,48 @@ SUCH DAMAGE. struct em_osdep { - bus_space_tag_t bus_space_tag; - bus_space_handle_t bus_space_handle; - struct device *dev; + bus_space_tag_t mem_bus_space_tag; + bus_space_handle_t mem_bus_space_handle; + struct device *dev; }; #define E1000_READ_REG(a, reg) (\ ((a)->mac_type >= em_82543) ? \ - bus_space_read_4( ((struct em_osdep *)(a)->back)->bus_space_tag, \ - ((struct em_osdep *)(a)->back)->bus_space_handle, \ + bus_space_read_4( ((struct em_osdep *)(a)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(a)->back)->mem_bus_space_handle, \ E1000_##reg): \ - bus_space_read_4( ((struct em_osdep *)(a)->back)->bus_space_tag, \ - ((struct em_osdep *)(a)->back)->bus_space_handle, \ + bus_space_read_4( ((struct em_osdep *)(a)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(a)->back)->mem_bus_space_handle, \ E1000_82542_##reg)) #define E1000_WRITE_REG(a, reg, value) (\ ((a)->mac_type >= em_82543) ? \ - bus_space_write_4( ((struct em_osdep *)(a)->back)->bus_space_tag, \ - ((struct em_osdep *)(a)->back)->bus_space_handle, \ + bus_space_write_4( ((struct em_osdep *)(a)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(a)->back)->mem_bus_space_handle, \ E1000_##reg, value): \ - bus_space_write_4( ((struct em_osdep *)(a)->back)->bus_space_tag, \ - ((struct em_osdep *)(a)->back)->bus_space_handle, \ + bus_space_write_4( ((struct em_osdep *)(a)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(a)->back)->mem_bus_space_handle, \ E1000_82542_##reg, value)) #define E1000_READ_REG_ARRAY(a, reg, offset) (\ ((a)->mac_type >= em_82543) ? \ - bus_space_read_4( ((struct em_osdep *)(a)->back)->bus_space_tag, \ - ((struct em_osdep *)(a)->back)->bus_space_handle, \ + bus_space_read_4( ((struct em_osdep *)(a)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(a)->back)->mem_bus_space_handle, \ (E1000_##reg + ((offset) << 2))): \ - bus_space_read_4( ((struct em_osdep *)(a)->back)->bus_space_tag, \ - ((struct em_osdep *)(a)->back)->bus_space_handle, \ + bus_space_read_4( ((struct em_osdep *)(a)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(a)->back)->mem_bus_space_handle, \ (E1000_82542_##reg + ((offset) << 2)))) #define E1000_WRITE_REG_ARRAY(a, reg, offset, value) (\ ((a)->mac_type >= em_82543) ? \ - bus_space_write_4( ((struct em_osdep *)(a)->back)->bus_space_tag, \ - ((struct em_osdep *)(a)->back)->bus_space_handle, \ + bus_space_write_4( ((struct em_osdep *)(a)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(a)->back)->mem_bus_space_handle, \ (E1000_##reg + ((offset) << 2)), value): \ - bus_space_write_4( ((struct em_osdep *)(a)->back)->bus_space_tag, \ - ((struct em_osdep *)(a)->back)->bus_space_handle, \ + bus_space_write_4( ((struct em_osdep *)(a)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(a)->back)->mem_bus_space_handle, \ (E1000_82542_##reg + ((offset) << 2)), value)) |