diff options
author | pdeuskar <pdeuskar@FreeBSD.org> | 2003-06-05 17:51:38 +0000 |
---|---|---|
committer | pdeuskar <pdeuskar@FreeBSD.org> | 2003-06-05 17:51:38 +0000 |
commit | 0dd10e1a2aabd02a8e64f2ff6820e0a31c608f19 (patch) | |
tree | 74f4ec3fcb51301c1a7510094d844c34276a6a8a /sys | |
parent | 2fac90898b99531fbc2de36e62926a5c7605ea1b (diff) | |
download | FreeBSD-src-0dd10e1a2aabd02a8e64f2ff6820e0a31c608f19.zip FreeBSD-src-0dd10e1a2aabd02a8e64f2ff6820e0a31c608f19.tar.gz |
Add support for Quad port adapter
Add sysctl's to display statistics/debug_info
Set WAIT_FOR_AUTONEG_DEFAULT to zero by default
Increment packet in/out statistics inline instead of every two seconds.
MFC after: 3 days
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/em/README | 6 | ||||
-rw-r--r-- | sys/dev/em/if_em.c | 360 | ||||
-rw-r--r-- | sys/dev/em/if_em.h | 15 | ||||
-rw-r--r-- | sys/dev/em/if_em_hw.c | 473 | ||||
-rw-r--r-- | sys/dev/em/if_em_hw.h | 8 |
5 files changed, 488 insertions, 374 deletions
diff --git a/sys/dev/em/README b/sys/dev/em/README index dd47ac5..2f0556e 100644 --- a/sys/dev/em/README +++ b/sys/dev/em/README @@ -2,7 +2,7 @@ $FreeBSD$ FreeBSD* Driver for the Intel(R) PRO/1000 Family of Adapters ============================================================ -February 5, 2003 +April 13, 2003 Contents @@ -65,6 +65,8 @@ release: 82546 PRO/1000 MF Dual Port Server Adapter A91620-xxx + 82546EB PRO/1000 MT Quad Port Server Adapter C11227-xxx + To verify your Intel adapter is supported, find the board ID number on the @@ -126,7 +128,7 @@ name of the driver tar file. cp if_em* /usr/src/sys/dev/em - cp Makefile /usr/src/sys/modules/em + cp Makefile.kernel /usr/src/sys/modules/em/Makefile Edit the /usr/src/sys/conf/files.i386 file, and add the following lines: diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c index f5cbf56..ce1c55a 100644 --- a/sys/dev/em/if_em.c +++ b/sys/dev/em/if_em.c @@ -51,7 +51,7 @@ struct adapter *em_adapter_list = NULL; * Driver version *********************************************************************/ -char em_driver_version[] = "1.5.31"; +char em_driver_version[] = "1.6.6"; /********************************************************************* @@ -87,6 +87,7 @@ static em_vendor_info_t em_vendor_info_array[] = { 0x8086, 0x1018, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, 0x101A, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0}, /* required last entry */ { 0, 0, 0, 0, 0} @@ -158,6 +159,10 @@ static void em_82547_move_tail(void *arg); static int em_dma_malloc(struct adapter *, bus_size_t, struct em_dma_alloc *, int); static void em_dma_free(struct adapter *, struct em_dma_alloc *); +static void em_print_debug_info(struct adapter *); +static int em_is_valid_ether_addr(u_int8_t *); +static int em_sysctl_stats(SYSCTL_HANDLER_ARGS); +static int em_sysctl_debug_info(SYSCTL_HANDLER_ARGS); /********************************************************************* * FreeBSD Device Interface Entry Points @@ -249,6 +254,7 @@ em_attach(device_t dev) struct adapter * adapter; int s; int tsize, rsize; + int error = 0; INIT_DEBUGOUT("em_attach: begin"); s = splimp(); @@ -269,6 +275,31 @@ em_attach(device_t dev) adapter->next = em_adapter_list; em_adapter_list = adapter; + /* SYSCTL stuff */ + sysctl_ctx_init(&adapter->sysctl_ctx); + adapter->sysctl_tree = SYSCTL_ADD_NODE(&adapter->sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_hw), + OID_AUTO, + device_get_nameunit(dev), + CTLFLAG_RD, + 0, ""); + if (adapter->sysctl_tree == NULL) { + error = EIO; + goto err_sysctl; + } + + SYSCTL_ADD_PROC(&adapter->sysctl_ctx, + SYSCTL_CHILDREN(adapter->sysctl_tree), + OID_AUTO, "debug_info", CTLTYPE_INT|CTLFLAG_RW, + (void *)adapter, 0, + em_sysctl_debug_info, "I", "Debug Information"); + + SYSCTL_ADD_PROC(&adapter->sysctl_ctx, + SYSCTL_CHILDREN(adapter->sysctl_tree), + OID_AUTO, "stats", CTLTYPE_INT|CTLFLAG_RW, + (void *)adapter, 0, + em_sysctl_stats, "I", "Statistics"); + callout_handle_init(&adapter->timer_handle); callout_handle_init(&adapter->tx_fifo_timer_handle); @@ -288,9 +319,10 @@ em_attach(device_t dev) adapter->hw.tbi_compatibility_en = TRUE; adapter->rx_buffer_len = EM_RXBUFFER_2048; - /* These parameters control the automatic generation(Tx) and - * response(Rx) to Ethernet PAUSE frames. - */ + /* + * These parameters control the automatic generation(Tx) and + * response(Rx) to Ethernet PAUSE frames. + */ adapter->hw.fc_high_water = FC_DEFAULT_HI_THRESH; adapter->hw.fc_low_water = FC_DEFAULT_LO_THRESH; adapter->hw.fc_pause_time = FC_DEFAULT_TX_TIMER; @@ -319,9 +351,8 @@ em_attach(device_t dev) if (em_allocate_pci_resources(adapter)) { printf("em%d: Allocation of PCI resources failed\n", adapter->unit); - em_free_pci_resources(adapter); - splx(s); - return(ENXIO); + error = ENXIO; + goto err_pci; } @@ -335,9 +366,8 @@ em_attach(device_t dev) if (em_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) { printf("em%d: Unable to allocate tx_desc memory\n", adapter->unit); - em_free_pci_resources(adapter); - splx(s); - return(ENOMEM); + error = ENOMEM; + goto err_tx_desc; } adapter->tx_desc_base = (struct em_tx_desc *) adapter->txdma.dma_vaddr; @@ -348,10 +378,8 @@ em_attach(device_t dev) if (em_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) { printf("em%d: Unable to allocate rx_desc memory\n", adapter->unit); - em_free_pci_resources(adapter); - em_dma_free(adapter, &adapter->txdma); - splx(s); - return(ENOMEM); + error = ENOMEM; + goto err_rx_desc; } adapter->rx_desc_base = (struct em_rx_desc *) adapter->rxdma.dma_vaddr; @@ -359,24 +387,24 @@ em_attach(device_t dev) if (em_hardware_init(adapter)) { printf("em%d: Unable to initialize the hardware\n", adapter->unit); - em_free_pci_resources(adapter); - em_dma_free(adapter, &adapter->txdma); - em_dma_free(adapter, &adapter->rxdma); - splx(s); - return(EIO); + error = EIO; + goto err_hw_init; } /* 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); - em_free_pci_resources(adapter); - em_dma_free(adapter, &adapter->txdma); - em_dma_free(adapter, &adapter->rxdma); - splx(s); - return(EIO); + error = EIO; + goto err_mac_addr; } + if (!em_is_valid_ether_addr(adapter->hw.mac_addr)) { + printf("em%d: Invalid mac address\n", adapter->unit); + error = EIO; + goto err_mac_addr; + } + bcopy(adapter->hw.mac_addr, adapter->interface_data.ac_enaddr, ETHER_ADDR_LEN); @@ -403,6 +431,20 @@ em_attach(device_t dev) INIT_DEBUGOUT("em_attach: end"); splx(s); return(0); + +err_mac_addr: +err_hw_init: + em_dma_free(adapter, &adapter->rxdma); +err_rx_desc: + em_dma_free(adapter, &adapter->txdma); +err_tx_desc: +err_pci: + em_free_pci_resources(adapter); + sysctl_ctx_free(&adapter->sysctl_ctx); +err_sysctl: + splx(s); + return(error); + } /********************************************************************* @@ -579,9 +621,13 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) if (ifp->if_flags & IFF_RUNNING) { em_disable_intr(adapter); em_set_multi(adapter); - if (adapter->hw.mac_type == em_82542_rev2_0) + if (adapter->hw.mac_type == em_82542_rev2_0) { em_initialize_receive_unit(adapter); - em_enable_intr(adapter); + } +#ifdef DEVICE_POLLING + if (!(ifp->if_ipending & IFF_POLLING)) +#endif + em_enable_intr(adapter); } break; case SIOCSIFMEDIA: @@ -787,31 +833,30 @@ em_intr(void *arg) } #endif /* DEVICE_POLLING */ + reg_icr = E1000_READ_REG(&adapter->hw, ICR); + if (!reg_icr) { + return; + } - em_disable_intr(adapter); - while (loop_cnt > 0 && - (reg_icr = E1000_READ_REG(&adapter->hw, ICR)) != 0) { - - /* Link status change */ - if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { - untimeout(em_local_timer, adapter, - adapter->timer_handle); - adapter->hw.get_link_status = 1; - em_check_for_link(&adapter->hw); - em_print_link_status(adapter); - adapter->timer_handle = - timeout(em_local_timer, adapter, 2*hz); - } + /* Link status change */ + if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { + untimeout(em_local_timer, adapter, + adapter->timer_handle); + adapter->hw.get_link_status = 1; + em_check_for_link(&adapter->hw); + em_print_link_status(adapter); + adapter->timer_handle = + timeout(em_local_timer, adapter, 2*hz); + } + while (loop_cnt > 0) { if (ifp->if_flags & IFF_RUNNING) { em_process_receive_interrupts(adapter, -1); em_clean_transmit_interrupts(adapter); } loop_cnt--; } - - em_enable_intr(adapter); - + if (ifp->if_flags & IFF_RUNNING && ifp->if_snd.ifq_head != NULL) em_start(ifp); @@ -1915,32 +1960,23 @@ em_initialize_transmit_unit(struct adapter * adapter) E1000_READ_REG(&adapter->hw, TDBAL), E1000_READ_REG(&adapter->hw, TDLEN)); - /* Set the default values for the Tx Inter Packet Gap timer */ switch (adapter->hw.mac_type) { - case em_82543: - case em_82544: - case em_82540: - case em_82545: - case em_82546: - case em_82541: - case em_82547: - if (adapter->hw.media_type == em_media_type_fiber) - reg_tipg = DEFAULT_82543_TIPG_IPGT_FIBER; - else - reg_tipg = DEFAULT_82543_TIPG_IPGT_COPPER; - reg_tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; - reg_tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; - break; case em_82542_rev2_0: - case em_82542_rev2_1: - reg_tipg = DEFAULT_82542_TIPG_IPGT; - reg_tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; - reg_tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; - break; - default: - printf("em%d: Invalid mac type detected\n", adapter->unit); - } + case em_82542_rev2_1: + reg_tipg = DEFAULT_82542_TIPG_IPGT; + reg_tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; + reg_tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; + break; + default: + if (adapter->hw.media_type == em_media_type_fiber) + reg_tipg = DEFAULT_82543_TIPG_IPGT_FIBER; + else + reg_tipg = DEFAULT_82543_TIPG_IPGT_COPPER; + reg_tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; + reg_tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; + } + E1000_WRITE_REG(&adapter->hw, TIPG, reg_tipg); E1000_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay); if(adapter->hw.mac_type >= em_82540) @@ -2100,6 +2136,7 @@ em_clean_transmit_interrupts(struct adapter * adapter) int i, num_avail; struct em_buffer *tx_buffer; struct em_tx_desc *tx_desc; + struct ifnet *ifp = &adapter->interface_data.ac_if; if (adapter->num_tx_desc_avail == adapter->num_tx_desc) return; @@ -2120,7 +2157,7 @@ em_clean_transmit_interrupts(struct adapter * adapter) num_avail++; if (tx_buffer->m_head) { - + ifp->if_opackets++; bus_dmamap_sync(adapter->txtag, tx_buffer->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(adapter->txtag, tx_buffer->map); @@ -2128,7 +2165,6 @@ em_clean_transmit_interrupts(struct adapter * adapter) m_freem(tx_buffer->m_head); tx_buffer->m_head = NULL; - } if (++i == adapter->num_tx_desc) @@ -2146,9 +2182,7 @@ em_clean_transmit_interrupts(struct adapter * adapter) * If there are no pending descriptors, clear the timeout. Otherwise, * if some descriptors have been freed, restart the timeout. */ - if (num_avail > EM_TX_CLEANUP_THRESHOLD) { - struct ifnet *ifp = &adapter->interface_data.ac_if; - + if (num_avail > EM_TX_CLEANUP_THRESHOLD) { ifp->if_flags &= ~IFF_OACTIVE; if (num_avail == adapter->num_tx_desc) ifp->if_timer = 0; @@ -2535,6 +2569,7 @@ em_process_receive_interrupts(struct adapter * adapter, int count) if (eop) { adapter->fmp->m_pkthdr.rcvif = ifp; + ifp->if_ipackets++; #if __FreeBSD_version < 500000 eh = mtod(adapter->fmp, struct ether_header *); @@ -2664,6 +2699,18 @@ em_disable_intr(struct adapter *adapter) return; } +static int +em_is_valid_ether_addr(u_int8_t *addr) +{ + char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; + + if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) { + return (FALSE); + } + + return(TRUE); +} + void em_write_pci_cfg(struct em_hw *hw, uint32_t reg, @@ -2798,8 +2845,6 @@ em_update_stats_counters(struct adapter *adapter) ifp = &adapter->interface_data.ac_if; /* Fill out the OS statistics structure */ - ifp->if_ipackets = adapter->stats.gprc; - ifp->if_opackets = adapter->stats.gptc; ifp->if_ibytes = adapter->stats.gorcl; ifp->if_obytes = adapter->stats.gotcl; ifp->if_imcasts = adapter->stats.mprc; @@ -2828,68 +2873,123 @@ em_update_stats_counters(struct adapter *adapter) * **********************************************************************/ static void -em_print_hw_stats(struct adapter *adapter) +em_print_debug_info(struct adapter *adapter) { - int unit = adapter->unit; + int unit = adapter->unit; #ifdef DBG_STATS - printf("em%d: Packets not Avail = %ld\n", unit, - adapter->no_pkts_avail); - printf("em%d: CleanTxInterrupts = %ld\n", unit, - adapter->clean_tx_interrupts); + printf("em%d: Packets not Avail = %ld\n", unit, + adapter->no_pkts_avail); + printf("em%d: CleanTxInterrupts = %ld\n", unit, + adapter->clean_tx_interrupts); #endif + printf("em%d: fifo workaround = %lld, fifo_reset = %lld\n", unit, + (long long)adapter->tx_fifo_wrk, + (long long)adapter->tx_fifo_reset); + printf("em%d: hw tdh = %d, hw tdt = %d\n", unit, + E1000_READ_REG(&adapter->hw, TDH), + E1000_READ_REG(&adapter->hw, TDT)); + printf("em%d: Num Tx descriptors avail = %d\n", unit, + adapter->num_tx_desc_avail); + printf("em%d: Tx Descriptors not avail1 = %ld\n", unit, + adapter->no_tx_desc_avail1); + printf("em%d: Tx Descriptors not avail2 = %ld\n", unit, + adapter->no_tx_desc_avail2); + printf("em%d: Std mbuf failed = %ld\n", unit, + adapter->mbuf_alloc_failed); + printf("em%d: Std mbuf cluster failed = %ld\n", unit, + adapter->mbuf_cluster_failed); + printf("em%d: Driver dropped packets = %ld\n", unit, + adapter->dropped_pkts); - printf("em%d: fifo workaround = %lld, fifo_reset = %lld\n", unit, - (long long)adapter->tx_fifo_wrk, - (long long)adapter->tx_fifo_reset); - printf("em%d: hw tdh = %d, hw tdt = %d\n", unit, - E1000_READ_REG(&adapter->hw, TDH), - E1000_READ_REG(&adapter->hw, TDT)); - printf("em%d: Excessive collisions = %lld\n", unit, - (long long)adapter->stats.ecol); - printf("em%d: Tx Descriptors not avail1 = %ld\n", unit, - adapter->no_tx_desc_avail1); - printf("em%d: Tx Descriptors not avail2 = %ld\n", unit, - adapter->no_tx_desc_avail2); - - printf("em%d: Symbol errors = %lld\n", unit, - (long long)adapter->stats.symerrs); - printf("em%d: Sequence errors = %lld\n", unit, - (long long)adapter->stats.sec); - printf("em%d: Defer count = %lld\n", unit, - (long long)adapter->stats.dc); - - printf("em%d: Missed Packets = %lld\n", unit, - (long long)adapter->stats.mpc); - printf("em%d: Receive No Buffers = %lld\n", unit, - (long long)adapter->stats.rnbc); - printf("em%d: Receive length errors = %lld\n", unit, - (long long)adapter->stats.rlec); - printf("em%d: Receive errors = %lld\n", unit, - (long long)adapter->stats.rxerrc); - printf("em%d: Crc errors = %lld\n", unit, - (long long)adapter->stats.crcerrs); - printf("em%d: Alignment errors = %lld\n", unit, - (long long)adapter->stats.algnerrc); - printf("em%d: Carrier extension errors = %lld\n", unit, - (long long)adapter->stats.cexterr); - printf("em%d: Driver dropped packets = %ld\n", unit, - adapter->dropped_pkts); - - printf("em%d: XON Rcvd = %lld\n", unit, - (long long)adapter->stats.xonrxc); - printf("em%d: XON Xmtd = %lld\n", unit, - (long long)adapter->stats.xontxc); - printf("em%d: XOFF Rcvd = %lld\n", unit, - (long long)adapter->stats.xoffrxc); - printf("em%d: XOFF Xmtd = %lld\n", unit, - (long long)adapter->stats.xofftxc); - - printf("em%d: Good Packets Rcvd = %lld\n", unit, - (long long)adapter->stats.gprc); - printf("em%d: Good Packets Xmtd = %lld\n", unit, - (long long)adapter->stats.gptc); + return; +} - return; +static void +em_print_hw_stats(struct adapter *adapter) +{ + int unit = adapter->unit; + + printf("em%d: Excessive collisions = %lld\n", unit, + (long long)adapter->stats.ecol); + printf("em%d: Symbol errors = %lld\n", unit, + (long long)adapter->stats.symerrs); + printf("em%d: Sequence errors = %lld\n", unit, + (long long)adapter->stats.sec); + printf("em%d: Defer count = %lld\n", unit, + (long long)adapter->stats.dc); + + printf("em%d: Missed Packets = %lld\n", unit, + (long long)adapter->stats.mpc); + printf("em%d: Receive No Buffers = %lld\n", unit, + (long long)adapter->stats.rnbc); + printf("em%d: Receive length errors = %lld\n", unit, + (long long)adapter->stats.rlec); + printf("em%d: Receive errors = %lld\n", unit, + (long long)adapter->stats.rxerrc); + printf("em%d: Crc errors = %lld\n", unit, + (long long)adapter->stats.crcerrs); + printf("em%d: Alignment errors = %lld\n", unit, + (long long)adapter->stats.algnerrc); + printf("em%d: Carrier extension errors = %lld\n", unit, + (long long)adapter->stats.cexterr); + + printf("em%d: XON Rcvd = %lld\n", unit, + (long long)adapter->stats.xonrxc); + printf("em%d: XON Xmtd = %lld\n", unit, + (long long)adapter->stats.xontxc); + printf("em%d: XOFF Rcvd = %lld\n", unit, + (long long)adapter->stats.xoffrxc); + printf("em%d: XOFF Xmtd = %lld\n", unit, + (long long)adapter->stats.xofftxc); + + printf("em%d: Good Packets Rcvd = %lld\n", unit, + (long long)adapter->stats.gprc); + printf("em%d: Good Packets Xmtd = %lld\n", unit, + (long long)adapter->stats.gptc); + + return; } +static int +em_sysctl_debug_info(SYSCTL_HANDLER_ARGS) +{ + int error; + int result; + struct adapter *adapter; + + result = -1; + error = sysctl_handle_int(oidp, &result, 0, req); + + if (error || !req->newptr) + return (error); + + if (result == 1) { + adapter = (struct adapter *)arg1; + em_print_debug_info(adapter); + } + + return error; +} + + +static int +em_sysctl_stats(SYSCTL_HANDLER_ARGS) +{ + int error; + int result; + struct adapter *adapter; + + result = -1; + error = sysctl_handle_int(oidp, &result, 0, req); + + if (error || !req->newptr) + return (error); + + if (result == 1) { + adapter = (struct adapter *)arg1; + em_print_hw_stats(adapter); + } + + return error; +} diff --git a/sys/dev/em/if_em.h b/sys/dev/em/if_em.h index 9cf1379..57a6195 100644 --- a/sys/dev/em/if_em.h +++ b/sys/dev/em/if_em.h @@ -72,6 +72,8 @@ POSSIBILITY OF SUCH DAMAGE. #include <pci/pcivar.h> #include <pci/pcireg.h> #include <sys/endian.h> +#include <sys/proc.h> +#include <sys/sysctl.h> #include "opt_bdg.h" #include <dev/em/if_em_hw.h> @@ -81,7 +83,7 @@ POSSIBILITY OF SUCH DAMAGE. /* * TxDescriptors * Valid Range: 80-256 for 82542 and 82543-based adapters - * 80-4096 for 82540, 82544, 82545, and 82546-based adapters + * 80-4096 for others * Default Value: 256 * This value is the number of transmit descriptors allocated by the driver. * Increasing this value allows the driver to queue more transmits. Each @@ -92,7 +94,7 @@ POSSIBILITY OF SUCH DAMAGE. /* * RxDescriptors * Valid Range: 80-256 for 82542 and 82543-based adapters - * 80-4096 for 82540, 82544, 82545, and 82546-based adapters + * 80-4096 for others * Default Value: 256 * This value is the number of receive descriptors allocated by the driver. * Increasing this value allows the driver to buffer more incoming packets. @@ -115,7 +117,7 @@ POSSIBILITY OF SUCH DAMAGE. #define EM_TIDV 64 /* - * TxAbsIntDelay (82540, 82545, and 82546-based adapters only) + * TxAbsIntDelay (Not valid for 82542 and 82543) * Valid Range: 0-65535 (0=off) * Default Value: 64 * This value, in units of 1.024 microseconds, limits the delay in which a @@ -149,7 +151,7 @@ POSSIBILITY OF SUCH DAMAGE. #define EM_RDTR 0 /* - * RxAbsIntDelay (82540, 82545, and 82546-based adapters only) + * RxAbsIntDelay (Not valid for 82542 and 82543) * Valid Range: 0-65535 (0=off) * Default Value: 64 * This value, in units of 1.024 microseconds, limits the delay in which a @@ -198,7 +200,7 @@ POSSIBILITY OF SUCH DAMAGE. * 1 - Wait for autonegotiation to complete * 0 - Don't wait for autonegotiation to complete */ -#define WAIT_FOR_AUTO_NEG_DEFAULT 1 +#define WAIT_FOR_AUTO_NEG_DEFAULT 0 /* Tunables -- End */ @@ -371,6 +373,9 @@ struct adapter { u_int16_t tx_fifo_head; + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *sysctl_tree; + /* Misc stats maintained by the driver */ unsigned long dropped_pkts; unsigned long mbuf_alloc_failed; diff --git a/sys/dev/em/if_em_hw.c b/sys/dev/em/if_em_hw.c index 6803fd8..0336bc6 100644 --- a/sys/dev/em/if_em_hw.c +++ b/sys/dev/em/if_em_hw.c @@ -35,7 +35,7 @@ /* if_em_hw.c * Shared functions for accessing and configuring the MAC */ - + #include <dev/em/if_em_hw.h> static int32_t em_set_phy_type(struct em_hw *hw); @@ -191,6 +191,7 @@ em_set_mac_type(struct em_hw *hw) break; case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_FIBER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: hw->mac_type = em_82546; break; case E1000_DEV_ID_82541EI: @@ -260,14 +261,24 @@ em_reset_hw(struct em_hw *hw) /* Must reset the PHY before resetting the MAC */ if((hw->mac_type == em_82541) || (hw->mac_type == em_82547)) { - E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST)); + E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST)); msec_delay(5); } - if((hw->mac_type > em_82543) && (hw->mac_type != em_82547)) - E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); - else - E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); + switch(hw->mac_type) { + case em_82544: + case em_82540: + case em_82545: + case em_82546: + case em_82541: + /* These controllers can't ack the 64-bit write when issuing the + * reset, so use IO-mapping as a workaround to issue the reset */ + E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); + break; + default: + E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); + break; + } /* Force a reload from the EEPROM if necessary */ if(hw->mac_type < em_82540) { @@ -294,9 +305,7 @@ em_reset_hw(struct em_hw *hw) /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= IGP_ACTIVITY_LED_ENABLE; - if(hw->mac_type == em_82547) - led_ctrl |= IGP_LED3_MODE; + led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); E1000_WRITE_REG(hw, LEDCTL, led_ctrl); } @@ -694,7 +703,8 @@ em_setup_fiber_link(struct em_hw *hw) static int32_t em_setup_copper_link(struct em_hw *hw) { - uint32_t ctrl, led_ctrl; + uint32_t ctrl; + uint32_t led_ctrl; int32_t ret_val; uint16_t i; uint16_t phy_data; @@ -724,143 +734,145 @@ em_setup_copper_link(struct em_hw *hw) } DEBUGOUT1("Phy ID = %x \n", hw->phy_id); -if (hw->phy_type == em_phy_igp) { + if (hw->phy_type == em_phy_igp) { - ret_val = em_phy_reset(hw); - if(ret_val < 0) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; - } + ret_val = em_phy_reset(hw); + if(ret_val < 0) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } - /* Wait 10ms for MAC to configure PHY from eeprom settings */ - msec_delay(15); + /* Wait 10ms for MAC to configure PHY from eeprom settings */ + msec_delay(15); - if(em_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if(em_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + + /* Configure activity LED after PHY reset */ + led_ctrl = E1000_READ_REG(hw, LEDCTL); + led_ctrl &= IGP_ACTIVITY_LED_MASK; + led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); + E1000_WRITE_REG(hw, LEDCTL, led_ctrl); - /* Configure activity LED after PHY reset */ - led_ctrl = E1000_READ_REG(hw, LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= IGP_ACTIVITY_LED_ENABLE; - if(hw->mac_type == em_82547) - led_ctrl |= IGP_LED3_MODE; - E1000_WRITE_REG(hw, LEDCTL, led_ctrl); - - if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - if(em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data) < 0) { + if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { + /* Disable SmartSpeed */ + if(em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; + if(em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + /* Set auto Master/Slave resolution process */ + if(em_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + phy_data &= ~CR_1000T_MS_ENABLE; + if(em_write_phy_reg(hw, PHY_1000T_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + } + + if(em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; } - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - if(em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data) < 0) { + + /* Force MDI for IGP PHY */ + phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | + IGP01E1000_PSCR_FORCE_MDI_MDIX); + + hw->mdix = 1; + + if(em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { DEBUGOUT("PHY Write Error\n"); return -E1000_ERR_PHY; } - /* Set auto Master/Slave resolution process */ - if(em_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data) < 0) { + + } else { + /* Enable CRS on TX. This must be set for half-duplex operation. */ + if(em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; } - phy_data &= ~CR_1000T_MS_ENABLE; - if(em_write_phy_reg(hw, PHY_1000T_CTRL, phy_data) < 0) { + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + + /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode + * 2 - MDI-X mode + * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) + */ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + + switch (hw->mdix) { + case 1: + phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; + break; + case 2: + phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; + break; + case 3: + phy_data |= M88E1000_PSCR_AUTO_X_1000T; + break; + case 0: + default: + phy_data |= M88E1000_PSCR_AUTO_X_MODE; + break; + } + + /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled + */ + phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; + if(hw->disable_polarity_correction == 1) + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; + if(em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { DEBUGOUT("PHY Write Error\n"); return -E1000_ERR_PHY; } - } - - if(em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - - /* Force MDI for IGP PHY */ - phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | IGP01E1000_PSCR_FORCE_MDI_MDIX); - - hw->mdix = 1; - if(em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - -} else { - /* Enable CRS on TX. This must be set for half-duplex operation. */ - if(em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - - switch (hw->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } - - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if(hw->disable_polarity_correction == 1) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - if(em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - - /* Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - if(em_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_EPSCR_TX_CLK_25; - - if (hw->phy_revision < M88E1011_I_REV_4) { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - if(em_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); + /* Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ + if(em_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; } - } + phy_data |= M88E1000_EPSCR_TX_CLK_25; + + if (hw->phy_revision < M88E1011_I_REV_4) { + /* Configure Master and Slave downshift values */ + phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); + phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); + if(em_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + } - /* SW Reset the PHY so all changes take effect */ - ret_val = em_phy_reset(hw); - if(ret_val < 0) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; + /* SW Reset the PHY so all changes take effect */ + ret_val = em_phy_reset(hw); + if(ret_val < 0) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } } -} /* Options: * autoneg = 1 (default) @@ -1199,41 +1211,41 @@ em_phy_force_speed_duplex(struct em_hw *hw) /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); -if (hw->phy_type == em_phy_m88) { - if(em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if (hw->phy_type == em_phy_m88) { + if(em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } - /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed are duplex are forced. - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - if(em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data); + /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI + * forced whenever speed are duplex are forced. + */ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + if(em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data); - /* Need to reset the PHY or these changes will be ignored */ - mii_ctrl_reg |= MII_CR_RESET; -} else { - /* Clear Auto-Crossover to force MDI manually. IGP requires MDI - * forced whenever speed or duplex are forced. - */ - if(em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + /* Need to reset the PHY or these changes will be ignored */ + mii_ctrl_reg |= MII_CR_RESET; + } else { + /* Clear Auto-Crossover to force MDI manually. IGP requires MDI + * forced whenever speed or duplex are forced. + */ + if(em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; + phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; + phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - if(em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; + if(em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } } -} /* Write back the modified PHY MII control register. */ if(em_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg) < 0) { @@ -1297,34 +1309,34 @@ if (hw->phy_type == em_phy_m88) { } } -if (hw->phy_type == em_phy_m88) { - /* Because we reset the PHY above, we need to re-force TX_CLK in the - * Extended PHY Specific Control Register to 25MHz clock. This value - * defaults back to a 2.5MHz clock when the PHY is reset. - */ - if(em_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_EPSCR_TX_CLK_25; - if(em_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if (hw->phy_type == em_phy_m88) { + /* Because we reset the PHY above, we need to re-force TX_CLK in the + * Extended PHY Specific Control Register to 25MHz clock. This value + * defaults back to a 2.5MHz clock when the PHY is reset. + */ + if(em_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + phy_data |= M88E1000_EPSCR_TX_CLK_25; + if(em_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } - /* In addition, because of the s/w reset above, we need to enable CRS on - * TX. This must be set for both full and half duplex operation. - */ - if(em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - if(em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; + /* In addition, because of the s/w reset above, we need to enable CRS on + * TX. This must be set for both full and half duplex operation. + */ + if(em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + if(em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } } -} return 0; } @@ -1379,43 +1391,43 @@ em_config_mac_to_phy(struct em_hw *hw) /* Set up duplex in the Device Control and Transmit Control * registers depending on negotiated values. */ -if (hw->phy_type == em_phy_igp) { - if(em_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD; - else ctrl &= ~E1000_CTRL_FD; + if (hw->phy_type == em_phy_igp) { + if(em_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD; + else ctrl &= ~E1000_CTRL_FD; - em_config_collision_dist(hw); + em_config_collision_dist(hw); - /* Set up speed in the Device Control register depending on - * negotiated values. - */ - if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) - ctrl |= E1000_CTRL_SPD_1000; - else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_100MBPS) - ctrl |= E1000_CTRL_SPD_100; -} else { - if(em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD; - else ctrl &= ~E1000_CTRL_FD; + /* Set up speed in the Device Control register depending on + * negotiated values. + */ + if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_1000MBPS) + ctrl |= E1000_CTRL_SPD_1000; + else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_100MBPS) + ctrl |= E1000_CTRL_SPD_100; + } else { + if(em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD; + else ctrl &= ~E1000_CTRL_FD; - em_config_collision_dist(hw); + em_config_collision_dist(hw); - /* Set up speed in the Device Control register depending on - * negotiated values. - */ - if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) - ctrl |= E1000_CTRL_SPD_1000; - else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) - ctrl |= E1000_CTRL_SPD_100; -} + /* Set up speed in the Device Control register depending on + * negotiated values. + */ + if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) + ctrl |= E1000_CTRL_SPD_1000; + else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) + ctrl |= E1000_CTRL_SPD_100; + } /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); return 0; @@ -2254,7 +2266,8 @@ em_write_phy_reg(struct em_hw *hw, void em_phy_hw_reset(struct em_hw *hw) { - uint32_t ctrl, ctrl_ext, led_ctrl; + uint32_t ctrl, ctrl_ext; + uint32_t led_ctrl; DEBUGFUNC("em_phy_hw_reset"); @@ -2295,9 +2308,7 @@ em_phy_hw_reset(struct em_hw *hw) /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= IGP_ACTIVITY_LED_ENABLE; - if(hw->mac_type == em_82547) - led_ctrl |= IGP_LED3_MODE; + led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); E1000_WRITE_REG(hw, LEDCTL, led_ctrl); } } @@ -2352,10 +2363,6 @@ em_detect_gig_phy(struct em_hw *hw) return -E1000_ERR_PHY; } hw->phy_id = (uint32_t) (phy_id_high << 16); -#ifdef MPW3 - /* Tabor/Mpw - changed from 2 to 20 since it did not read the low word in - * the mpw, might be fixed in A0 */ -#endif usec_delay(20); if(em_read_phy_reg(hw, PHY_ID2, &phy_id_low) < 0) { DEBUGOUT("PHY Read Error\n"); @@ -2364,22 +2371,12 @@ em_detect_gig_phy(struct em_hw *hw) hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK); hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK; -#ifdef MPW3 /* Tabor MPW3 workaround, expect to be removed in Tabor A0 */ - /* workaround for MPW - IGP PHYID is incorrect! */ - if(hw->phy_id == 0x02A80400) - hw->phy_id = 0x02A80380; - -#endif switch(hw->mac_type) { case em_82543: if(hw->phy_id == M88E1000_E_PHY_ID) match = TRUE; break; case em_82544: if(hw->phy_id == M88E1000_I_PHY_ID) match = TRUE; -#ifdef MPW3 /* MPW3 only, expected to be removed in Tabor A0 */ - /* MPW driver only - IGP should work with Cordova */ - if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE; -#endif break; case em_82540: case em_82545: @@ -3817,6 +3814,7 @@ em_setup_led(struct em_hw *hw) case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EP: case E1000_DEV_ID_82547EI: @@ -3858,6 +3856,7 @@ em_cleanup_led(struct em_hw *hw) case E1000_DEV_ID_82545EM_FIBER: case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_FIBER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EP: case E1000_DEV_ID_82547EI: @@ -3912,6 +3911,7 @@ em_led_on(struct em_hw *hw) case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EP: case E1000_DEV_ID_82547EI: @@ -3965,6 +3965,7 @@ em_led_off(struct em_hw *hw) case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EP: case E1000_DEV_ID_82547EI: @@ -4222,7 +4223,11 @@ em_get_bus_info(struct em_hw *hw) status = E1000_READ_REG(hw, STATUS); hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? em_bus_type_pcix : em_bus_type_pci; - if(hw->bus_type == em_bus_type_pci) { + + if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) { + hw->bus_speed = (hw->bus_type == em_bus_type_pci) ? + em_bus_speed_66 : em_bus_speed_120; + } else if(hw->bus_type == em_bus_type_pci) { hw->bus_speed = (status & E1000_STATUS_PCI66) ? em_bus_speed_66 : em_bus_speed_33; } else { diff --git a/sys/dev/em/if_em_hw.h b/sys/dev/em/if_em_hw.h index fe50c9a..7258599 100644 --- a/sys/dev/em/if_em_hw.h +++ b/sys/dev/em/if_em_hw.h @@ -104,6 +104,7 @@ typedef enum { em_bus_speed_33, em_bus_speed_66, em_bus_speed_100, + em_bus_speed_120, em_bus_speed_133, em_bus_speed_reserved } em_bus_speed; @@ -319,10 +320,11 @@ void em_write_reg_io(struct em_hw *hw, uint32_t offset, uint32_t value); #define E1000_DEV_ID_82545EM_FIBER 0x1011 #define E1000_DEV_ID_82546EB_COPPER 0x1010 #define E1000_DEV_ID_82546EB_FIBER 0x1012 +#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D #define E1000_DEV_ID_82541EI 0x1013 #define E1000_DEV_ID_82541EP 0x1018 #define E1000_DEV_ID_82547EI 0x1019 -#define NUM_DEV_IDS 19 +#define NUM_DEV_IDS 20 #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 @@ -606,7 +608,7 @@ struct em_ffvt_entry { #define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ #define E1000_EERD 0x00014 /* EEPROM Read - RW */ #define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ -#define E1000_FLA 0x0001C /* Flash Access Register - RW */ +#define E1000_FLA 0x0001C /* Flash Access - RW */ #define E1000_MDIC 0x00020 /* MDI Control - RW */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ @@ -735,6 +737,7 @@ struct em_ffvt_entry { * the registers function in the same manner. */ #define E1000_82542_CTRL E1000_CTRL +#define E1000_82542_CTRL_DUP E1000_CTRL_DUP #define E1000_82542_STATUS E1000_STATUS #define E1000_82542_EECD E1000_EECD #define E1000_82542_EERD E1000_EERD @@ -1490,7 +1493,6 @@ struct em_hw { #define E1000_COLLISION_DISTANCE 64 #define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE #define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE -#define E1000_GB_HDX_COLLISION_DISTANCE 512 #define E1000_COLD_SHIFT 12 /* The number of Transmit and Receive Descriptors must be a multiple of 8 */ |