From 87307ba13888ed309f4c3f3b224d4aec1752b9a8 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Sat, 23 Dec 2006 10:39:16 +0000 Subject: [PATCH] Sync with Intel's em-6.2.9 - Support more chips. - Implement suspend/resume device methods. - Correct promisc mode support. - Code and comment clean up. - Avoid reinitializing the hardware if only IP address is changed. This is implemented in a different way from Intel's: If IFF_RUNNING is set, em_init() will return immediately. So for some situation in which em_init() must run, IFF_RUNNING is cleared before calling em_init(). - Rework TX processing: In em_encap(), save the index of the packet's last TX descriptor (EOP) in the packet's first descriptor. In em_txeof(), test E1000_TXD_STAT_DD bit only for last TX descriptor (EOP) of certain packet. If it is set, then reap the TX descriptors of the packet in an inner loop. "This change is important for future chips, where DD bit is going to be set only on the EOP descriptors." -- Jack Vogel at Intel --- sys/dev/netif/em/Makefile | 7 +- sys/dev/netif/em/README | 7 +- sys/dev/netif/em/if_em.c | 1072 +++++++++++++++++--------------- sys/dev/netif/em/if_em.h | 236 ++++--- sys/dev/netif/em/if_em_hw.c | 1049 +++++++++++++++++-------------- sys/dev/netif/em/if_em_hw.h | 236 +++---- sys/dev/netif/em/if_em_osdep.h | 12 +- 7 files changed, 1371 insertions(+), 1248 deletions(-) diff --git a/sys/dev/netif/em/Makefile b/sys/dev/netif/em/Makefile index 1b17d34635..5f3f35344c 100644 --- a/sys/dev/netif/em/Makefile +++ b/sys/dev/netif/em/Makefile @@ -1,13 +1,16 @@ #$FreeBSD: src/sys/modules/em/Makefile,v 1.1.2.3 2002/06/18 21:00:56 pdeuskar Exp $ -#$DragonFly: src/sys/dev/netif/em/Makefile,v 1.6 2006/06/25 11:02:38 corecode Exp $ +#$DragonFly: src/sys/dev/netif/em/Makefile,v 1.7 2006/12/23 10:39:16 sephe Exp $ KMOD= if_em SRCS= if_em.c if_em_hw.c -SRCS+= device_if.h bus_if.h pci_if.h opt_polling.h opt_ktr.h +SRCS+= device_if.h bus_if.h pci_if.h opt_polling.h opt_inet.h opt_ktr.h .ifndef BUILDING_WITH_KERNEL opt_polling.h: echo '#define DEVICE_POLLING 1' > ${.OBJDIR}/${.TARGET} + +opt_inet.h: + echo "#define INET 1" > ${.OBJDIR}/${.TARGET} .endif .include diff --git a/sys/dev/netif/em/README b/sys/dev/netif/em/README index ea060960c1..d719bab6f2 100644 --- a/sys/dev/netif/em/README +++ b/sys/dev/netif/em/README @@ -1,8 +1,8 @@ -$DragonFly: src/sys/dev/netif/em/README,v 1.6 2006/10/24 17:09:46 swildner Exp $ +$DragonFly: src/sys/dev/netif/em/README,v 1.7 2006/12/23 10:39:16 sephe Exp $ FreeBSD* Driver for the Intel(R) PRO/1000 Family of Adapters ============================================================ -May 2, 2006 +September 25, 2006 Contents @@ -264,7 +264,8 @@ Identifying Your Adapter section. Polling ------- - NOTES: DEVICE POLLING is only valid for non-SMP kernels. + NOTES: DEVICE POLLING is only valid for non-SMP (Symmetric MultiProcessing) + kernels. The driver has to be compiled into the kernel for DEVICE POLLING to be enabled in the driver. diff --git a/sys/dev/netif/em/if_em.c b/sys/dev/netif/em/if_em.c index e95ac26e2d..3939263762 100644 --- a/sys/dev/netif/em/if_em.c +++ b/sys/dev/netif/em/if_em.c @@ -64,7 +64,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/dev/netif/em/if_em.c,v 1.52 2006/12/20 18:14:39 dillon Exp $ + * $DragonFly: src/sys/dev/netif/em/if_em.c,v 1.53 2006/12/23 10:39:16 sephe Exp $ * $FreeBSD$ */ /* @@ -94,20 +94,54 @@ */ #include "opt_polling.h" +#include "opt_inet.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef INET +#include +#include +#include +#include +#include +#include +#endif +#include #include -#include /********************************************************************* - * Set this to one to display debug statistics + * Set this to one to display debug statistics *********************************************************************/ -int em_display_debug_stats = 0; +int em_display_debug_stats = 0; /********************************************************************* * Driver version *********************************************************************/ -char em_driver_version[] = "6.1.4"; +char em_driver_version[] = "6.2.9"; /********************************************************************* @@ -131,6 +165,7 @@ static em_vendor_info_t em_vendor_info_array[] = { 0x8086, E1000_DEV_ID_82541EI, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82541ER, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_82541ER_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82541EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82541GI, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82541GI_LF, PCI_ANY_ID, PCI_ANY_ID, 0}, @@ -159,10 +194,12 @@ static em_vendor_info_t em_vendor_info_array[] = { 0x8086, E1000_DEV_ID_82546GB_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82546GB_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82546GB_PCIE, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82547EI, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_82547EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82547GI, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82571EB_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, @@ -170,6 +207,8 @@ static em_vendor_info_t em_vendor_info_array[] = { 0x8086, E1000_DEV_ID_82571EB_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82571EB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE, + PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82572EI_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82572EI_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, @@ -189,9 +228,13 @@ static em_vendor_info_t em_vendor_info_array[] = { 0x8086, E1000_DEV_ID_80003ES2LAN_SERDES_DPT, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_ICH8_IGP_M_AMT, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_ICH8_IGP_AMT, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_ICH8_IGP_C, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_ICH8_IFE, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_ICH8_IFE_GT, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_ICH8_IFE_G, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_ICH8_IGP_M, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, 0x101A, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, 0x1014, PCI_ANY_ID, PCI_ANY_ID, 0}, @@ -208,13 +251,15 @@ static const char *em_strings[] = { }; /********************************************************************* - * Function prototypes + * Function prototypes *********************************************************************/ static int em_probe(device_t); static int em_attach(device_t); static int em_detach(device_t); static int em_shutdown(device_t); static void em_intr(void *); +static int em_suspend(device_t); +static int em_resume(device_t); static void em_start(struct ifnet *); static int em_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); static void em_watchdog(struct ifnet *); @@ -223,8 +268,8 @@ static void em_stop(void *); static void em_media_status(struct ifnet *, struct ifmediareq *); static int em_media_change(struct ifnet *); static void em_identify_hardware(struct adapter *); -static int em_allocate_pci_resource(device_t); -static void em_free_pci_resource(device_t); +static int em_allocate_pci_resources(device_t); +static void em_free_pci_resources(device_t); static void em_local_timer(void *); static int em_hardware_init(struct adapter *); static void em_setup_interface(device_t, struct adapter *); @@ -237,10 +282,9 @@ static void em_disable_intr(struct adapter *); static void em_free_transmit_structures(struct adapter *); static void em_free_receive_structures(struct adapter *); static void em_update_stats_counters(struct adapter *); -static void em_clean_transmit_interrupts(struct adapter *); +static void em_txeof(struct adapter *); static int em_allocate_receive_structures(struct adapter *); -static int em_allocate_transmit_structures(struct adapter *); -static void em_process_receive_interrupts(struct adapter *, int); +static void em_rxeof(struct adapter *, int); static void em_receive_checksum(struct adapter *, struct em_rx_desc *, struct mbuf *); static void em_transmit_checksum_setup(struct adapter *, struct mbuf *, @@ -249,7 +293,7 @@ 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 void em_update_link_status(struct adapter *); static int em_get_buf(int i, struct adapter *, struct mbuf *, int how); static void em_enable_vlans(struct adapter *); static void em_disable_vlans(struct adapter *); @@ -261,13 +305,13 @@ static int em_82547_tx_fifo_reset(struct adapter *); static void em_82547_move_tail(void *); static void em_82547_move_tail_serialized(struct adapter *); static int em_dma_malloc(struct adapter *, bus_size_t, - struct em_dma_alloc *, int); + struct em_dma_alloc *); 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(uint8_t *); static int em_sysctl_stats(SYSCTL_HANDLER_ARGS); static int em_sysctl_debug_info(SYSCTL_HANDLER_ARGS); -static uint32_t em_fill_descriptors(uint64_t address, uint32_t length, +static uint32_t em_fill_descriptors(bus_addr_t address, uint32_t length, PDESC_ARRAY desc_array); static int em_sysctl_int_delay(SYSCTL_HANDLER_ARGS); static int em_sysctl_int_throttle(SYSCTL_HANDLER_ARGS); @@ -276,7 +320,7 @@ static void em_add_int_delay_sysctl(struct adapter *, const char *, struct em_int_delay_info *, int, int); /********************************************************************* - * FreeBSD Device Interface Entry Points + * FreeBSD Device Interface Entry Points *********************************************************************/ static device_method_t em_methods[] = { @@ -285,6 +329,8 @@ static device_method_t em_methods[] = { DEVMETHOD(device_attach, em_attach), DEVMETHOD(device_detach, em_detach), DEVMETHOD(device_shutdown, em_shutdown), + DEVMETHOD(device_suspend, em_suspend), + DEVMETHOD(device_resume, em_resume), {0, 0} }; @@ -364,7 +410,7 @@ em_probe(device_t dev) pci_vendor_id = pci_get_vendor(dev); if (pci_vendor_id != EM_VENDOR_ID) - return(ENXIO); + return (ENXIO); pci_device_id = pci_get_device(dev); pci_subvendor_id = pci_get_subvendor(dev); @@ -384,21 +430,21 @@ em_probe(device_t dev) "%s, Version - %s", em_strings[ent->index], em_driver_version); device_set_desc_copy(dev, adapter_name); - return(0); + return (0); } ent++; } - return(ENXIO); + return (ENXIO); } /********************************************************************* * Device initialization routine * * The attach entry point is called when the driver is being loaded. - * This routine identifies the type of hardware, allocates all resources - * and initializes the hardware. - * + * This routine identifies the type of hardware, allocates all resources + * and initializes the hardware. + * * return 0 on success, positive on failure *********************************************************************/ @@ -454,7 +500,7 @@ em_attach(device_t dev) &adapter->rx_int_delay, E1000_REG_OFFSET(&adapter->hw, RDTR), em_rx_int_delay_dflt); - em_add_int_delay_sysctl(adapter, "tx_int_delay", + em_add_int_delay_sysctl(adapter, "tx_int_delay", "transmit interrupt delay in usecs", &adapter->tx_int_delay, E1000_REG_OFFSET(&adapter->hw, TIDV), @@ -479,7 +525,7 @@ em_attach(device_t dev) /* * Validate number of transmit and receive descriptors. It * must not exceed hardware maximum, and must be multiple - * of EM_DBA_ALIGN (128) + * of EM_DBA_ALIGN. */ if (((em_txd * sizeof(struct em_tx_desc)) % EM_DBA_ALIGN) != 0 || (adapter->hw.mac_type >= em_82544 && em_txd > EM_MAX_TXD) || @@ -518,22 +564,22 @@ em_attach(device_t dev) adapter->hw.master_slave = EM_MASTER_SLAVE; #endif - /* - * Set the max frame size assuming standard ethernet - * sized frames + /* + * Set the max frame size assuming standard ethernet + * sized frames. */ adapter->hw.max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN; - adapter->hw.min_frame_size = + adapter->hw.min_frame_size = MINIMUM_ETHERNET_PACKET_SIZE + ETHER_CRC_LEN; - /* - * This controls when hardware reports transmit completion - * status. + /* + * This controls when hardware reports transmit completion + * status. */ adapter->hw.report_tx_early = 1; - error = em_allocate_pci_resource(dev); + error = em_allocate_pci_resources(dev); if (error) goto fail; @@ -544,23 +590,23 @@ em_attach(device_t dev) EM_DBA_ALIGN); /* Allocate Transmit Descriptor ring */ - if (em_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_WAITOK)) { + error = em_dma_malloc(adapter, tsize, &adapter->txdma); + if (error) { device_printf(dev, "Unable to allocate TxDescriptor memory\n"); - error = ENOMEM; goto fail; } - adapter->tx_desc_base = (struct em_tx_desc *) adapter->txdma.dma_vaddr; + adapter->tx_desc_base = (struct em_tx_desc *)adapter->txdma.dma_vaddr; rsize = roundup2(adapter->num_rx_desc * sizeof(struct em_rx_desc), EM_DBA_ALIGN); /* Allocate Receive Descriptor ring */ - if (em_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_WAITOK)) { + error = em_dma_malloc(adapter, rsize, &adapter->rxdma); + if (error) { device_printf(dev, "Unable to allocate rx_desc memory\n"); - error = ENOMEM; goto fail; } - adapter->rx_desc_base = (struct em_rx_desc *) adapter->rxdma.dma_vaddr; + adapter->rx_desc_base = (struct em_rx_desc *)adapter->rxdma.dma_vaddr; /* Initialize the hardware */ if (em_hardware_init(adapter)) { @@ -572,13 +618,13 @@ em_attach(device_t dev) /* Copy the permanent MAC address out of the EEPROM */ if (em_read_mac_addr(&adapter->hw) < 0) { device_printf(dev, - "EEPROM read error while reading mac address\n"); + "EEPROM read error while reading MAC address\n"); error = EIO; goto fail; } if (!em_is_valid_ether_addr(adapter->hw.mac_addr)) { - device_printf(dev, "Invalid mac address\n"); + device_printf(dev, "Invalid MAC address\n"); error = EIO; goto fail; } @@ -590,18 +636,7 @@ em_attach(device_t dev) em_clear_hw_cntrs(&adapter->hw); em_update_stats_counters(adapter); adapter->hw.get_link_status = 1; - em_check_for_link(&adapter->hw); - - /* Print the link status */ - if (adapter->link_active == 1) { - em_get_speed_and_duplex(&adapter->hw, &adapter->link_speed, - &adapter->link_duplex); - device_printf(dev, "Speed: %d Mbps, Duplex: %s\n", - adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? "Full" : "Half"); - } else { - device_printf(dev, "Speed: N/A, Duplex:N/A\n"); - } + em_update_link_status(adapter); /* Indicate SOL/IDER usage */ if (em_check_phy_reset_block(&adapter->hw)) { @@ -610,11 +645,11 @@ em_attach(device_t dev) } /* Identify 82544 on PCIX */ - em_get_bus_info(&adapter->hw); + em_get_bus_info(&adapter->hw); if (adapter->hw.bus_type == em_bus_type_pcix && adapter->hw.mac_type == em_82544) adapter->pcix_82544 = TRUE; - else + else adapter->pcix_82544 = FALSE; error = bus_setup_intr(dev, adapter->res_interrupt, INTR_NETSAFE, @@ -641,7 +676,7 @@ fail: * The detach entry point is called when the driver is being removed. * This routine stops the adapter and deallocates all the resources * that were allocated for driver operation. - * + * * return 0 on success, positive on failure *********************************************************************/ @@ -667,7 +702,7 @@ em_detach(device_t dev) } bus_generic_detach(dev); - em_free_pci_resource(dev); + em_free_pci_resources(dev); /* Free Transmit Descriptor ring */ if (adapter->tx_desc_base != NULL) { @@ -687,14 +722,14 @@ em_detach(device_t dev) sysctl_ctx_free(&adapter->sysctl_ctx); } - return(0); + return (0); } /********************************************************************* * * Shutdown entry point * - **********************************************************************/ + **********************************************************************/ static int em_shutdown(device_t dev) @@ -706,7 +741,38 @@ em_shutdown(device_t dev) em_stop(adapter); lwkt_serialize_exit(ifp->if_serializer); - return(0); + return (0); +} + +/* + * Suspend/resume device methods. + */ +static int +em_suspend(device_t dev) +{ + struct adapter *adapter = device_get_softc(dev); + struct ifnet *ifp = &adapter->interface_data.ac_if; + + lwkt_serialize_enter(ifp->if_serializer); + em_stop(adapter); + lwkt_serialize_exit(ifp->if_serializer); + return (0); +} + +static int +em_resume(device_t dev) +{ + struct adapter *adapter = device_get_softc(dev); + struct ifnet *ifp = &adapter->interface_data.ac_if; + + lwkt_serialize_enter(ifp->if_serializer); + ifp->if_flags &= ~IFF_RUNNING; + em_init(adapter); + if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) + em_start(ifp); + lwkt_serialize_exit(ifp->if_serializer); + + return bus_generic_resume(dev); } /********************************************************************* @@ -727,6 +793,8 @@ em_start(struct ifnet *ifp) ASSERT_SERIALIZED(ifp->if_serializer); + if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) + return; if (!adapter->link_active) return; while (!ifq_is_empty(&ifp->if_snd)) { @@ -736,7 +804,7 @@ em_start(struct ifnet *ifp) break; logif(pkt_txqueue); - if (em_encap(adapter, m_head)) { + if (em_encap(adapter, m_head)) { ifp->if_flags |= IFF_OACTIVE; break; } @@ -744,9 +812,9 @@ em_start(struct ifnet *ifp) /* Send a copy of the frame to the BPF listener */ BPF_MTAP(ifp, m_head); - - /* Set timeout in case hardware has problems transmitting */ - ifp->if_timer = EM_TX_TIMEOUT; + + /* Set timeout in case hardware has problems transmitting. */ + ifp->if_timer = EM_TX_TIMEOUT; } } @@ -809,6 +877,7 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) ifp->if_mtu = ifr->ifr_mtu; adapter->hw.max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; + ifp->if_flags &= ~IFF_RUNNING; em_init(adapter); } break; @@ -816,14 +885,18 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS " "(Set Interface Flags)"); if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_flags & IFF_RUNNING)) + if (!(ifp->if_flags & IFF_RUNNING)) { em_init(adapter); - em_disable_promisc(adapter); - em_set_promisc(adapter); + } else if ((ifp->if_flags ^ adapter->if_flags) & + IFF_PROMISC) { + em_disable_promisc(adapter); + em_set_promisc(adapter); + } } else { if (ifp->if_flags & IFF_RUNNING) em_stop(adapter); } + adapter->if_flags = ifp->if_flags; break; case SIOCADDMULTI: case SIOCDELMULTI: @@ -841,6 +914,13 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) } break; case SIOCSIFMEDIA: + /* Check SOL/IDER usage */ + if (em_check_phy_reset_block(&adapter->hw)) { + if_printf(ifp, "Media change is blocked due to " + "SOL/IDER session.\n"); + break; + } + /* FALLTHROUGH */ case SIOCGIFMEDIA: IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFMEDIA " "(Get/Set Interface Media)"); @@ -857,15 +937,17 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; reinit = 1; } - if (reinit && (ifp->if_flags & IFF_RUNNING)) + if (reinit && (ifp->if_flags & IFF_RUNNING)) { + ifp->if_flags &= ~IFF_RUNNING; em_init(adapter); + } break; default: error = ether_ioctl(ifp, command, data); break; } - return(error); + return (error); } /********************************************************************* @@ -889,13 +971,10 @@ em_watchdog(struct ifnet *ifp) return; } -#ifdef foo - if (em_check_for_link(&adapter->hw)) -#endif + if (em_check_for_link(&adapter->hw) == 0) if_printf(ifp, "watchdog timeout -- resetting\n"); ifp->if_flags &= ~IFF_RUNNING; - em_init(adapter); adapter->watchdog_timeouts++; @@ -906,7 +985,7 @@ em_watchdog(struct ifnet *ifp) * * This routine is used in two ways. It is used by the stack as * init entry point in network interface structure. It is also used - * by the driver as a hw/sw initialization routine to get to a + * by the driver as a hw/sw initialization routine to get to a * consistent state. * * return 0 on success, positive on failure @@ -919,8 +998,13 @@ em_init(void *arg) uint32_t pba; struct ifnet *ifp = &adapter->interface_data.ac_if; + ASSERT_SERIALIZED(ifp->if_serializer); + INIT_DEBUGOUT("em_init: begin"); + if (ifp->if_flags & IFF_RUNNING) + return; + em_stop(adapter); /* @@ -935,7 +1019,7 @@ em_init(void *arg) * Note: default does not leave enough room for Jumbo Frame >10k. */ switch (adapter->hw.mac_type) { - case em_82547: + case em_82547: case em_82547_rev_2: /* 82547: Total Packet Buffer is 40K */ if (adapter->hw.max_frame_size > EM_RXBUFFER_8192) pba = E1000_PBA_22K; /* 22K for Rx, 18K for Tx */ @@ -947,13 +1031,13 @@ em_init(void *arg) adapter->tx_fifo_size = (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT; break; - case em_80003es2lan: /* 80003es2lan: Total Packet Buffer is 48K */ - case em_82571: /* 82571: Total Packet Buffer is 48K */ - case em_82572: /* 82572: Total Packet Buffer is 48K */ + /* Total Packet Buffer on these is 48K */ + case em_82571: + case em_82572: + case em_80003es2lan: pba = E1000_PBA_32K; /* 32K for Rx, 16K for Tx */ break; case em_82573: /* 82573: Total Packet Buffer is 32K */ - /* Jumbo frames not supported */ pba = E1000_PBA_12K; /* 12K for Rx, 20K for Tx */ break; case em_ich8lan: @@ -979,14 +1063,23 @@ em_init(void *arg) if_printf(ifp, "Unable to initialize the hardware\n"); return; } + em_update_link_status(adapter); if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) em_enable_vlans(adapter); + /* Set hardware offload abilities */ + if (adapter->hw.mac_type >= em_82543) { + if (ifp->if_capenable & IFCAP_TXCSUM) + ifp->if_hwassist = EM_CHECKSUM_FEATURES; + else + ifp->if_hwassist = 0; + } + /* Prepare transmit descriptors and buffers */ if (em_setup_transmit_structures(adapter)) { if_printf(ifp, "Could not setup transmit structures\n"); - em_stop(adapter); + em_stop(adapter); return; } em_initialize_transmit_unit(adapter); @@ -1002,19 +1095,12 @@ em_init(void *arg) } em_initialize_receive_unit(adapter); - /* Don't loose promiscuous settings */ + /* Don't lose promiscuous settings */ em_set_promisc(adapter); ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; - if (adapter->hw.mac_type >= em_82543) { - if (ifp->if_capenable & IFCAP_TXCSUM) - ifp->if_hwassist = EM_CHECKSUM_FEATURES; - else - ifp->if_hwassist = 0; - } - callout_reset(&adapter->timer, hz, em_local_timer, adapter); em_clear_hw_cntrs(&adapter->hw); @@ -1055,15 +1141,15 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) callout_stop(&adapter->timer); adapter->hw.get_link_status = 1; em_check_for_link(&adapter->hw); - em_print_link_status(adapter); + em_update_link_status(adapter); callout_reset(&adapter->timer, hz, em_local_timer, adapter); } /* fall through */ case POLL_ONLY: if (ifp->if_flags & IFF_RUNNING) { - em_process_receive_interrupts(adapter, count); - em_clean_transmit_interrupts(adapter); + em_rxeof(adapter, count); + em_txeof(adapter); if (!ifq_is_empty(&ifp->if_snd)) em_start(ifp); @@ -1079,7 +1165,7 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) * * Interrupt Service routine * - **********************************************************************/ + *********************************************************************/ static void em_intr(void *arg) { @@ -1100,16 +1186,15 @@ em_intr(void *arg) return; } - if (reg_icr & E1000_ICR_RXO) - adapter->rx_overruns++; - - /* Link status change */ - if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { - callout_stop(&adapter->timer); - adapter->hw.get_link_status = 1; - em_check_for_link(&adapter->hw); - em_print_link_status(adapter); - callout_reset(&adapter->timer, hz, em_local_timer, adapter); + /* + * XXX: some laptops trigger several spurious interrupts on em(4) + * when in the resume cycle. The ICR register reports all-ones + * value in this case. Processing such interrupts would lead to + * a freeze. I don't know why. + */ + if (reg_icr == 0xffffffff) { + logif(intr_end); + return; } /* @@ -1118,10 +1203,22 @@ em_intr(void *arg) * packets and unnecessary piecemeal cleanups of the transmit ring. */ if (ifp->if_flags & IFF_RUNNING) { - em_process_receive_interrupts(adapter, -1); - em_clean_transmit_interrupts(adapter); + em_rxeof(adapter, -1); + em_txeof(adapter); } + /* Link status change */ + if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { + callout_stop(&adapter->timer); + adapter->hw.get_link_status = 1; + em_check_for_link(&adapter->hw); + em_update_link_status(adapter); + callout_reset(&adapter->timer, hz, em_local_timer, adapter); + } + + if (reg_icr & E1000_ICR_RXO) + adapter->rx_overruns++; + if ((ifp->if_flags & IFF_RUNNING) && !ifq_is_empty(&ifp->if_snd)) em_start(ifp); logif(intr_end); @@ -1138,7 +1235,7 @@ em_intr(void *arg) static void em_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) { - struct adapter * adapter = ifp->if_softc; + struct adapter *adapter = ifp->if_softc; u_char fiber_type = IFM_1000_SX; INIT_DEBUGOUT("em_media_status: begin"); @@ -1146,20 +1243,7 @@ em_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) ASSERT_SERIALIZED(ifp->if_serializer); em_check_for_link(&adapter->hw); - if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) { - if (adapter->link_active == 0) { - em_get_speed_and_duplex(&adapter->hw, - &adapter->link_speed, - &adapter->link_duplex); - adapter->link_active = 1; - } - } else { - if (adapter->link_active == 1) { - adapter->link_speed = 0; - adapter->link_duplex = 0; - adapter->link_active = 0; - } - } + em_update_link_status(adapter); ifmr->ifm_status = IFM_AVALID; ifmr->ifm_active = IFM_ETHER; @@ -1174,7 +1258,6 @@ em_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) if (adapter->hw.mac_type == em_82545) fiber_type = IFM_1000_LX; ifmr->ifm_active |= fiber_type | IFM_FDX; - ifmr->ifm_active |= IFM_1000_SX | IFM_FDX; } else { switch (adapter->link_speed) { case 10: @@ -1205,16 +1288,16 @@ em_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) static int em_media_change(struct ifnet *ifp) { - struct adapter * adapter = ifp->if_softc; - struct ifmedia *ifm = &adapter->media; + struct adapter *adapter = ifp->if_softc; + struct ifmedia *ifm = &adapter->media; INIT_DEBUGOUT("em_media_change: begin"); - if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) - return(EINVAL); - ASSERT_SERIALIZED(ifp->if_serializer); + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return (EINVAL); + switch (IFM_SUBTYPE(ifm->ifm_media)) { case IFM_AUTO: adapter->hw.autoneg = DO_AUTO_NEG; @@ -1232,7 +1315,7 @@ em_media_change(struct ifnet *ifp) if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) adapter->hw.forced_speed_duplex = em_100_full; else - adapter->hw.forced_speed_duplex = em_100_half; + adapter->hw.forced_speed_duplex = em_100_half; break; case IFM_10_T: adapter->hw.autoneg = FALSE; @@ -1240,7 +1323,7 @@ em_media_change(struct ifnet *ifp) if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) adapter->hw.forced_speed_duplex = em_10_full; else - adapter->hw.forced_speed_duplex = em_10_half; + adapter->hw.forced_speed_duplex = em_10_half; break; default: if_printf(ifp, "Unsupported media type\n"); @@ -1251,6 +1334,7 @@ em_media_change(struct ifnet *ifp) */ adapter->hw.phy_reset_disable = FALSE; + ifp->if_flags &= ~IFF_RUNNING; em_init(adapter); return(0); @@ -1279,19 +1363,12 @@ em_tx_cb(void *arg, bus_dma_segment_t *seg, int nsegs, bus_size_t mapsize, static int em_encap(struct adapter *adapter, struct mbuf *m_head) { - uint32_t txd_upper; - uint32_t txd_lower, txd_used = 0, txd_saved = 0; - int i, j, error; - uint64_t address; - - /* For 82544 Workaround */ - DESC_ARRAY desc_array; - uint32_t array_elements; - uint32_t counter; + uint32_t txd_upper = 0, txd_lower = 0, txd_used = 0, txd_saved = 0; + int i, j, error, last = 0; struct ifvlan *ifv = NULL; struct em_q q; - struct em_buffer *tx_buffer = NULL, *tx_buffer_map; + struct em_buffer *tx_buffer = NULL, *tx_buffer_first; bus_dmamap_t map; struct em_tx_desc *current_tx_desc = NULL; struct ifnet *ifp = &adapter->interface_data.ac_if; @@ -1301,26 +1378,33 @@ em_encap(struct adapter *adapter, struct mbuf *m_head) * available hits the threshold */ if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) { - em_clean_transmit_interrupts(adapter); + em_txeof(adapter); if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) { adapter->no_tx_desc_avail1++; - return(ENOBUFS); + return (ENOBUFS); } } + + /* + * Capture the first descriptor index, this descriptor will have + * the index of the EOP which is the only one that now gets a + * DONE bit writeback. + */ + tx_buffer_first = &adapter->tx_buffer_area[adapter->next_avail_tx_desc]; + /* * Map the packet for DMA. */ - tx_buffer_map = &adapter->tx_buffer_area[adapter->next_avail_tx_desc]; - map = tx_buffer_map->map; + map = tx_buffer_first->map; error = bus_dmamap_load_mbuf(adapter->txtag, map, m_head, em_tx_cb, &q, BUS_DMA_NOWAIT); if (error != 0) { adapter->no_tx_dma_setup++; - return(error); + return (error); } KASSERT(q.nsegs != 0, ("em_encap: empty packet")); - if (q.nsegs > adapter->num_tx_desc_avail) { + if (q.nsegs > (adapter->num_tx_desc_avail - 2)) { adapter->no_tx_desc_avail2++; error = ENOBUFS; goto fail; @@ -1329,8 +1413,6 @@ em_encap(struct adapter *adapter, struct mbuf *m_head) if (ifp->if_hwassist > 0) { em_transmit_checksum_setup(adapter, m_head, &txd_upper, &txd_lower); - } else { - txd_upper = txd_lower = 0; } /* Find out if we are in vlan mode */ @@ -1340,22 +1422,22 @@ em_encap(struct adapter *adapter, struct mbuf *m_head) ifv = m_head->m_pkthdr.rcvif->if_softc; i = adapter->next_avail_tx_desc; - if (adapter->pcix_82544) { + if (adapter->pcix_82544) txd_saved = i; - txd_used = 0; - } + + /* Set up our transmit descriptors */ for (j = 0; j < q.nsegs; j++) { /* If adapter is 82544 and on PCIX bus */ if(adapter->pcix_82544) { - array_elements = 0; - address = htole64(q.segs[j].ds_addr); + DESC_ARRAY desc_array; + uint32_t array_elements, counter; + /* * Check the Address and Length combination and * split the data accordingly */ - array_elements = em_fill_descriptors(address, - htole32(q.segs[j].ds_len), - &desc_array); + array_elements = em_fill_descriptors(q.segs[j].ds_addr, + q.segs[j].ds_len, &desc_array); for (counter = 0; counter < array_elements; counter++) { if (txd_used == adapter->num_tx_desc_avail) { adapter->next_avail_tx_desc = txd_saved; @@ -1366,15 +1448,18 @@ em_encap(struct adapter *adapter, struct mbuf *m_head) tx_buffer = &adapter->tx_buffer_area[i]; current_tx_desc = &adapter->tx_desc_base[i]; current_tx_desc->buffer_addr = htole64( - desc_array.descriptor[counter].address); + desc_array.descriptor[counter].address); current_tx_desc->lower.data = htole32( - (adapter->txd_cmd | txd_lower | - (uint16_t)desc_array.descriptor[counter].length)); - current_tx_desc->upper.data = htole32((txd_upper)); + adapter->txd_cmd | txd_lower | + (uint16_t)desc_array.descriptor[counter].length); + current_tx_desc->upper.data = htole32(txd_upper); + + last = i; if (++i == adapter->num_tx_desc) i = 0; tx_buffer->m_head = NULL; + tx_buffer->next_eop = -1; txd_used++; } } else { @@ -1386,10 +1471,12 @@ em_encap(struct adapter *adapter, struct mbuf *m_head) adapter->txd_cmd | txd_lower | q.segs[j].ds_len); current_tx_desc->upper.data = htole32(txd_upper); + last = i; if (++i == adapter->num_tx_desc) i = 0; tx_buffer->m_head = NULL; + tx_buffer->next_eop = -1; } } @@ -1408,14 +1495,22 @@ em_encap(struct adapter *adapter, struct mbuf *m_head) } tx_buffer->m_head = m_head; - tx_buffer_map->map = tx_buffer->map; + tx_buffer_first->map = tx_buffer->map; tx_buffer->map = map; bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE); /* * Last Descriptor of Packet needs End Of Packet (EOP) + * and Report Status (RS) + */ + current_tx_desc->lower.data |= + htole32(E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS); + + /* + * Keep track in the first buffer which descriptor will be + * written back. */ - current_tx_desc->lower.data |= htole32(E1000_TXD_CMD_EOP); + tx_buffer_first->next_eop = last; bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_PREWRITE); @@ -1435,7 +1530,7 @@ em_encap(struct adapter *adapter, struct mbuf *m_head) } } - return(0); + return (0); fail: bus_dmamap_unload(adapter->txtag, map); return error; @@ -1444,7 +1539,7 @@ fail: /********************************************************************* * * 82547 workaround to avoid controller hang in half-duplex environment. - * The workaround is to avoid queuing a large packet that would span + * The workaround is to avoid queuing a large packet that would span * the internal Tx FIFO ring boundary. We need to reset the FIFO pointers * in this case. We do that only when FIFO is quiescent. * @@ -1476,10 +1571,10 @@ em_82547_move_tail_serialized(struct adapter *adapter) tx_desc = &adapter->tx_desc_base[hw_tdt]; length += tx_desc->lower.flags.length; eop = tx_desc->lower.data & E1000_TXD_CMD_EOP; - if(++hw_tdt == adapter->num_tx_desc) + if (++hw_tdt == adapter->num_tx_desc) hw_tdt = 0; - if(eop) { + if (eop) { if (em_82547_fifo_workaround(adapter, length)) { adapter->tx_fifo_wrk_cnt++; callout_reset(&adapter->tx_fifo_timer, 1, @@ -1505,13 +1600,13 @@ em_82547_fifo_workaround(struct adapter *adapter, int len) if (fifo_pkt_len >= (EM_82547_PKT_THRESH + fifo_space)) { if (em_82547_tx_fifo_reset(adapter)) - return(0); + return (0); else - return(1); + return (1); } } - return(0); + return (0); } static void @@ -1530,14 +1625,10 @@ em_82547_tx_fifo_reset(struct adapter *adapter) { uint32_t tctl; - if ( (E1000_READ_REG(&adapter->hw, TDT) == - E1000_READ_REG(&adapter->hw, TDH)) && - (E1000_READ_REG(&adapter->hw, TDFT) == - E1000_READ_REG(&adapter->hw, TDFH)) && - (E1000_READ_REG(&adapter->hw, TDFTS) == - E1000_READ_REG(&adapter->hw, TDFHS)) && - (E1000_READ_REG(&adapter->hw, TDFPC) == 0)) { - + if (E1000_READ_REG(&adapter->hw, TDT) == E1000_READ_REG(&adapter->hw, TDH) && + E1000_READ_REG(&adapter->hw, TDFT) == E1000_READ_REG(&adapter->hw, TDFH) && + E1000_READ_REG(&adapter->hw, TDFTS) == E1000_READ_REG(&adapter->hw, TDFHS) && + E1000_READ_REG(&adapter->hw, TDFPC) == 0) { /* Disable TX unit */ tctl = E1000_READ_REG(&adapter->hw, TCTL); E1000_WRITE_REG(&adapter->hw, TCTL, tctl & ~E1000_TCTL_EN); @@ -1555,9 +1646,9 @@ em_82547_tx_fifo_reset(struct adapter *adapter) adapter->tx_fifo_head = 0; adapter->tx_fifo_reset_cnt++; - return(TRUE); + return (TRUE); } else { - return(FALSE); + return (FALSE); } } @@ -1681,8 +1772,8 @@ em_local_timer(void *arg) lwkt_serialize_enter(ifp->if_serializer); em_check_for_link(&adapter->hw); - em_print_link_status(adapter); - em_update_stats_counters(adapter); + em_update_link_status(adapter); + em_update_stats_counters(adapter); if (em_display_debug_stats && ifp->if_flags & IFF_RUNNING) em_print_hw_stats(adapter); em_smartspeed(adapter); @@ -1693,7 +1784,7 @@ em_local_timer(void *arg) } static void -em_print_link_status(struct adapter *adapter) +em_update_link_status(struct adapter *adapter) { if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) { if (adapter->link_active == 0) { @@ -1701,18 +1792,14 @@ em_print_link_status(struct adapter *adapter) &adapter->link_speed, &adapter->link_duplex); /* Check if we may set SPEED_MODE bit on PCI-E */ - if ((adapter->link_speed == SPEED_1000) && - ((adapter->hw.mac_type == em_82571) || - (adapter->hw.mac_type == em_82572))) { + if (adapter->link_speed == SPEED_1000 && + (adapter->hw.mac_type == em_82571 || + adapter->hw.mac_type == em_82572)) { int tarc0; -#define SPEED_MODE_BIT (1 << 21) /* On PCI-E MACs only */ - tarc0 = E1000_READ_REG(&adapter->hw, TARC0); tarc0 |= SPEED_MODE_BIT; E1000_WRITE_REG(&adapter->hw, TARC0, tarc0); - -#undef SPEED_MODE_BIT } if (bootverbose) { if_printf(&adapter->interface_data.ac_if, @@ -1723,9 +1810,16 @@ em_print_link_status(struct adapter *adapter) } adapter->link_active = 1; adapter->smartspeed = 0; +#ifdef notyet + ifp->if_baudrate = adapter->link_speed * 1000000; + if_link_state_change(ifp, LINK_STATE_UP); +#endif } } else { if (adapter->link_active == 1) { +#ifdef notyet + ifp->if_baudrate = 0; +#endif adapter->link_speed = 0; adapter->link_duplex = 0; if (bootverbose) { @@ -1733,6 +1827,9 @@ em_print_link_status(struct adapter *adapter) "Link is Down\n"); } adapter->link_active = 0; +#ifdef notyet + if_link_state_change(ifp, LINK_STATE_DOWN); +#endif } } } @@ -1740,7 +1837,7 @@ em_print_link_status(struct adapter *adapter) /********************************************************************* * * This routine disables all traffic on the adapter by issuing a - * global reset on the MAC and deallocates TX/RX buffers. + * global reset on the MAC and deallocates TX/RX buffers. * **********************************************************************/ @@ -1772,7 +1869,7 @@ em_stop(void *arg) * **********************************************************************/ static void -em_identify_hardware(struct adapter * adapter) +em_identify_hardware(struct adapter *adapter) { device_t dev = adapter->dev; @@ -1782,8 +1879,8 @@ em_identify_hardware(struct adapter * adapter) (adapter->hw.pci_cmd_word & PCIM_CMD_MEMEN))) { device_printf(dev, "Memory Access and/or Bus Master bits " "were not set!\n"); - adapter->hw.pci_cmd_word |= (PCIM_CMD_BUSMASTEREN | - PCIM_CMD_MEMEN); + adapter->hw.pci_cmd_word |= PCIM_CMD_BUSMASTEREN | + PCIM_CMD_MEMEN; pci_write_config(dev, PCIR_COMMAND, adapter->hw.pci_cmd_word, 2); } @@ -1807,15 +1904,15 @@ em_identify_hardware(struct adapter * adapter) } static int -em_allocate_pci_resource(device_t dev) +em_allocate_pci_resources(device_t dev) { struct adapter *adapter = device_get_softc(dev); int rid; - rid = EM_MMBA; + rid = PCIR_BAR(0); adapter->res_memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - if (!(adapter->res_memory)) { + if (adapter->res_memory == NULL) { device_printf(dev, "Unable to allocate bus resource: memory\n"); return ENXIO; } @@ -1826,18 +1923,24 @@ em_allocate_pci_resource(device_t dev) adapter->hw.hw_addr = (uint8_t *)&adapter->osdep.mem_bus_space_handle; if (adapter->hw.mac_type > em_82543) { - int i, val; - /* Figure our where our IO BAR is ? */ - rid = EM_MMBA; - for (i = 0; i < 5; i++) { + for (rid = PCIR_BAR(0); rid < PCIR_CIS;) { + uint32_t val; + val = pci_read_config(dev, rid, 4); - if (val & 0x00000001) { + if (EM_BAR_TYPE(val) == EM_BAR_TYPE_IO) { adapter->io_rid = rid; break; } rid += 4; + /* check for 64bit BAR */ + if (EM_BAR_MEM_TYPE(val) == EM_BAR_MEM_TYPE_64BIT) + rid += 4; } + if (rid >= PCIR_CIS) { + device_printf(dev, "Unable to locate IO BAR\n"); + return (ENXIO); + } adapter->res_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &adapter->io_rid, RF_ACTIVE); @@ -1846,16 +1949,16 @@ em_allocate_pci_resource(device_t dev) "ioport\n"); return ENXIO; } - - adapter->hw.reg_io_tag = rman_get_bustag(adapter->res_ioport); - adapter->hw.reg_io_handle = + adapter->hw.io_base = 0; + adapter->osdep.io_bus_space_tag = + rman_get_bustag(adapter->res_ioport); + adapter->osdep.io_bus_space_handle = rman_get_bushandle(adapter->res_ioport); } - /* For ICH8 we need to find the flash memory */ + /* For ICH8 we need to find the flash memory. */ if (adapter->hw.mac_type == em_ich8lan) { rid = EM_FLASH; - adapter->flash_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (adapter->flash_mem == NULL) { @@ -1872,7 +1975,7 @@ em_allocate_pci_resource(device_t dev) rid = 0x0; adapter->res_interrupt = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); - if (!(adapter->res_interrupt)) { + if (adapter->res_interrupt == NULL) { device_printf(dev, "Unable to allocate bus resource: " "interrupt\n"); return ENXIO; @@ -1884,7 +1987,7 @@ em_allocate_pci_resource(device_t dev) } static void -em_free_pci_resource(device_t dev) +em_free_pci_resources(device_t dev) { struct adapter *adapter = device_get_softc(dev); @@ -1893,7 +1996,7 @@ em_free_pci_resource(device_t dev) adapter->res_interrupt); } if (adapter->res_memory != NULL) { - bus_release_resource(dev, SYS_RES_MEMORY, EM_MMBA, + bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), adapter->res_memory); } @@ -1932,22 +2035,22 @@ em_hardware_init(struct adapter *adapter) if (em_validate_eeprom_checksum(&adapter->hw) < 0) { device_printf(adapter->dev, "The EEPROM Checksum Is Not Valid\n"); - return(EIO); + return (EIO); } if (em_read_part_num(&adapter->hw, &(adapter->part_num)) < 0) { device_printf(adapter->dev, "EEPROM read error while reading part number\n"); - return(EIO); + return (EIO); } - /* Set up smart power down as default off on newer adapters */ + /* Set up smart power down as default off on newer adapters. */ if (!em_smart_pwr_down && (adapter->hw.mac_type == em_82571 || adapter->hw.mac_type == em_82572)) { uint16_t phy_tmp = 0; - /* Speed up time to link by disabling smart power down */ + /* Speed up time to link by disabling smart power down. */ em_read_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT, &phy_tmp); phy_tmp &= ~IGP02E1000_PM_SPD; @@ -1956,8 +2059,8 @@ em_hardware_init(struct adapter *adapter) } /* - * 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. * - High water mark should allow for at least two frames to be * received after sending an XOFF. * - Low water mark works best when it is very near the high water mark. @@ -1972,44 +2075,23 @@ em_hardware_init(struct adapter *adapter) rx_buffer_size = ((E1000_READ_REG(&adapter->hw, PBA) & 0xffff) << 10); adapter->hw.fc_high_water = - rx_buffer_size - roundup2(1 * adapter->hw.max_frame_size, 1024); + rx_buffer_size - roundup2(adapter->hw.max_frame_size, 1024); adapter->hw.fc_low_water = adapter->hw.fc_high_water - 1500; if (adapter->hw.mac_type == em_80003es2lan) adapter->hw.fc_pause_time = 0xFFFF; else adapter->hw.fc_pause_time = 0x1000; adapter->hw.fc_send_xon = TRUE; - adapter->hw.fc = em_fc_full; + adapter->hw.fc = E1000_FC_FULL; if (em_init_hw(&adapter->hw) < 0) { device_printf(adapter->dev, "Hardware Initialization Failed"); - return(EIO); + return (EIO); } em_check_for_link(&adapter->hw); - /* - * At the time this code runs copper NICS fail, but fiber - * succeed, however, this causes a problem downstream, - * so for now have fiber NICs just not do this, then - * everything seems to work correctly. - */ - if ((adapter->hw.media_type != em_media_type_fiber && - adapter->hw.media_type != em_media_type_internal_serdes) && - (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) - adapter->link_active = 1; - else - adapter->link_active = 0; - if (adapter->link_active) { - em_get_speed_and_duplex(&adapter->hw, - &adapter->link_speed, - &adapter->link_duplex); - } else { - adapter->link_speed = 0; - adapter->link_duplex = 0; - } - - return(0); + return (0); } /********************************************************************* @@ -2020,7 +2102,7 @@ em_hardware_init(struct adapter *adapter) static void em_setup_interface(device_t dev, struct adapter *adapter) { - struct ifnet *ifp; + struct ifnet *ifp; u_char fiber_type = IFM_1000_SX; /* default type */ INIT_DEBUGOUT("em_setup_interface: begin"); @@ -2051,9 +2133,12 @@ em_setup_interface(device_t dev, struct adapter *adapter) * Tell the upper layer(s) we support long frames. */ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); - ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; + ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; +#if 0 + ifp->if_capenable |= IFCAP_VLAN_MTU; +#endif - /* + /* * Specify the media types supported by this adapter and register * callbacks to update media and link information */ @@ -2065,17 +2150,16 @@ em_setup_interface(device_t dev, struct adapter *adapter) fiber_type = IFM_1000_LX; ifmedia_add(&adapter->media, IFM_ETHER | fiber_type | IFM_FDX, 0, NULL); - ifmedia_add(&adapter->media, IFM_ETHER | fiber_type, - 0, NULL); + ifmedia_add(&adapter->media, IFM_ETHER | fiber_type, 0, NULL); } else { ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T, 0, NULL); - ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T | IFM_FDX, + ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL); - ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX, + ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL); - ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX | IFM_FDX, + ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL); - ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T | IFM_FDX, + ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL); } @@ -2087,13 +2171,13 @@ em_setup_interface(device_t dev, struct adapter *adapter) * * Workaround for SmartSpeed on 82541 and 82547 controllers * - **********************************************************************/ + **********************************************************************/ static void em_smartspeed(struct adapter *adapter) { uint16_t phy_tmp; - if (adapter->link_active || (adapter->hw.phy_type != em_phy_igp) || + if (adapter->link_active || (adapter->hw.phy_type != em_phy_igp) || !adapter->hw.autoneg || !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL)) return; @@ -2108,8 +2192,7 @@ em_smartspeed(struct adapter *adapter) return; em_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_tmp); if (phy_tmp & SR_1000T_MS_CONFIG_FAULT) { - em_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, - &phy_tmp); + em_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_tmp); if (phy_tmp & CR_1000T_MS_ENABLE) { phy_tmp &= ~CR_1000T_MS_ENABLE; em_write_phy_reg(&adapter->hw, @@ -2119,14 +2202,14 @@ em_smartspeed(struct adapter *adapter) !em_phy_setup_autoneg(&adapter->hw) && !em_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_tmp)) { - phy_tmp |= (MII_CR_AUTO_NEG_EN | + phy_tmp |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); em_write_phy_reg(&adapter->hw, PHY_CTRL, phy_tmp); } } } - return; + return; } else if (adapter->smartspeed == EM_SMARTSPEED_DOWNSHIFT) { /* If still no link, perhaps using 2/3 pair cable */ em_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_tmp); @@ -2150,98 +2233,76 @@ em_smartspeed(struct adapter *adapter) */ static void em_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ +{ if (error) return; - *(bus_addr_t*) arg = segs->ds_addr; + *(bus_addr_t *)arg = segs->ds_addr; } static int em_dma_malloc(struct adapter *adapter, bus_size_t size, - struct em_dma_alloc *dma, int mapflags) + struct em_dma_alloc *dma) { - int r; device_t dev = adapter->dev; + int error; - r = bus_dma_tag_create(NULL, /* parent */ - PAGE_SIZE, 0, /* alignment, bounds */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - size, /* maxsize */ - 1, /* nsegments */ - size, /* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ - &dma->dma_tag); - if (r != 0) { - device_printf(dev, "em_dma_malloc: bus_dma_tag_create failed; " - "error %u\n", r); - goto fail_0; - } - - r = bus_dmamem_alloc(dma->dma_tag, (void**) &dma->dma_vaddr, - BUS_DMA_NOWAIT, &dma->dma_map); - if (r != 0) { - device_printf(dev, "em_dma_malloc: bus_dmammem_alloc failed; " - "size %llu, error %d\n", (uintmax_t)size, r); - goto fail_2; - } - - r = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, - size, - em_dmamap_cb, - &dma->dma_paddr, - mapflags | BUS_DMA_NOWAIT); - if (r != 0) { - device_printf(dev, "em_dma_malloc: bus_dmamap_load failed; " - "error %u\n", r); - goto fail_3; - } - - dma->dma_size = size; - return(0); + error = bus_dma_tag_create(NULL, /* parent */ + EM_DBA_ALIGN, 0, /* alignment, bounds */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + size, /* maxsize */ + 1, /* nsegments */ + size, /* maxsegsize */ + 0, /* flags */ + &dma->dma_tag); + if (error) { + device_printf(dev, "%s: bus_dma_tag_create failed; error %d\n", + __func__, error); + return error; + } -fail_3: - bus_dmamap_unload(dma->dma_tag, dma->dma_map); -fail_2: - bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); + error = bus_dmamem_alloc(dma->dma_tag, (void**)&dma->dma_vaddr, + BUS_DMA_WAITOK, &dma->dma_map); + if (error) { + device_printf(dev, "%s: bus_dmammem_alloc failed; " + "size %llu, error %d\n", + __func__, (uintmax_t)size, error); + goto fail; + } + + error = bus_dmamap_load(dma->dma_tag, dma->dma_map, + dma->dma_vaddr, size, + em_dmamap_cb, &dma->dma_paddr, + BUS_DMA_WAITOK); + if (error) { + device_printf(dev, "%s: bus_dmamap_load failed; error %u\n", + __func__, error); + bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); + goto fail; + } + + return 0; +fail: bus_dma_tag_destroy(dma->dma_tag); -fail_0: - dma->dma_map = NULL; dma->dma_tag = NULL; - return(r); + return error; } static void em_dma_free(struct adapter *adapter, struct em_dma_alloc *dma) { - bus_dmamap_unload(dma->dma_tag, dma->dma_map); - bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); - bus_dma_tag_destroy(dma->dma_tag); -} - -/********************************************************************* - * - * Allocate memory for tx_buffer structures. The tx_buffer stores all - * the information needed to transmit a packet on the wire. - * - **********************************************************************/ -static int -em_allocate_transmit_structures(struct adapter * adapter) -{ - adapter->tx_buffer_area = kmalloc(sizeof(struct em_buffer) * - adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO); - if (adapter->tx_buffer_area == NULL) { - device_printf(adapter->dev, "Unable to allocate tx_buffer memory\n"); - return(ENOMEM); + if (dma->dma_tag != NULL) { + bus_dmamap_unload(dma->dma_tag, dma->dma_map); + bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); + bus_dma_tag_destroy(dma->dma_tag); + dma->dma_tag = NULL; } - - return(0); } /********************************************************************* * - * Allocate and initialize transmit structures. + * Allocate and initialize transmit structures. * **********************************************************************/ static int @@ -2255,25 +2316,26 @@ em_setup_transmit_structures(struct adapter *adapter) * Setup DMA descriptor areas. */ size = roundup2(adapter->hw.max_frame_size, MCLBYTES); - if (bus_dma_tag_create(NULL, /* parent */ + if (bus_dma_tag_create(NULL, /* parent */ 1, 0, /* alignment, bounds */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - size, /* maxsize */ - EM_MAX_SCATTER, /* nsegments */ - size, /* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + size, /* maxsize */ + EM_MAX_SCATTER, /* nsegments */ + size, /* maxsegsize */ + 0, /* flags */ &adapter->txtag)) { device_printf(adapter->dev, "Unable to allocate TX DMA tag\n"); return(ENOMEM); } - if (em_allocate_transmit_structures(adapter)) - return(ENOMEM); + adapter->tx_buffer_area = + kmalloc(sizeof(struct em_buffer) * adapter->num_tx_desc, + M_DEVBUF, M_WAITOK | M_ZERO); - bzero((void *) adapter->tx_desc_base, - (sizeof(struct em_tx_desc)) * adapter->num_tx_desc); + bzero(adapter->tx_desc_base, + sizeof(struct em_tx_desc) * adapter->num_tx_desc); tx_buffer = adapter->tx_buffer_area; for (i = 0; i < adapter->num_tx_desc; i++) { error = bus_dmamap_create(adapter->txtag, 0, &tx_buffer->map); @@ -2285,8 +2347,8 @@ em_setup_transmit_structures(struct adapter *adapter) tx_buffer++; } - adapter->next_avail_tx_desc = 0; - adapter->oldest_used_tx_desc = 0; + adapter->next_avail_tx_desc = 0; + adapter->next_tx_to_clean = 0; /* Set number of descriptors available */ adapter->num_tx_desc_avail = adapter->num_tx_desc; @@ -2297,7 +2359,7 @@ em_setup_transmit_structures(struct adapter *adapter) bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_PREWRITE); - return(0); + return (0); fail: em_free_transmit_structures(adapter); return (error); @@ -2309,9 +2371,9 @@ fail: * **********************************************************************/ static void -em_initialize_transmit_unit(struct adapter * adapter) +em_initialize_transmit_unit(struct adapter *adapter) { - uint32_t reg_tctl, reg_tarc; + uint32_t reg_tctl; uint32_t reg_tipg = 0; uint64_t bus_addr; @@ -2319,7 +2381,7 @@ em_initialize_transmit_unit(struct adapter * adapter) /* Setup the Base and Length of the Tx Descriptor Ring */ bus_addr = adapter->txdma.dma_paddr; - E1000_WRITE_REG(&adapter->hw, TDLEN, + E1000_WRITE_REG(&adapter->hw, TDLEN, adapter->num_tx_desc * sizeof(struct em_tx_desc)); E1000_WRITE_REG(&adapter->hw, TDBAH, (uint32_t)(bus_addr >> 32)); E1000_WRITE_REG(&adapter->hw, TDBAL, (uint32_t)bus_addr); @@ -2328,7 +2390,7 @@ em_initialize_transmit_unit(struct adapter * adapter) E1000_WRITE_REG(&adapter->hw, TDT, 0); E1000_WRITE_REG(&adapter->hw, TDH, 0); - HW_DEBUGOUT2("Base = %x, Length = %x\n", + HW_DEBUGOUT2("Base = %x, Length = %x\n", E1000_READ_REG(&adapter->hw, TDBAL), E1000_READ_REG(&adapter->hw, TDLEN)); @@ -2342,7 +2404,8 @@ em_initialize_transmit_unit(struct adapter * adapter) break; case em_80003es2lan: reg_tipg = DEFAULT_82543_TIPG_IPGR1; - reg_tipg |= DEFAULT_80003ES2LAN_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; + reg_tipg |= + DEFAULT_80003ES2LAN_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; break; default: if (adapter->hw.media_type == em_media_type_fiber || @@ -2356,26 +2419,9 @@ em_initialize_transmit_unit(struct adapter * adapter) E1000_WRITE_REG(&adapter->hw, TIPG, reg_tipg); E1000_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay.value); - if (adapter->hw.mac_type >= em_82540) + if (adapter->hw.mac_type >= em_82540) { E1000_WRITE_REG(&adapter->hw, TADV, adapter->tx_abs_int_delay.value); - - /* Do adapter specific tweaks before we enable the transmitter */ - if (adapter->hw.mac_type == em_82571 || adapter->hw.mac_type == em_82572) { - reg_tarc = E1000_READ_REG(&adapter->hw, TARC0); - reg_tarc |= (1 << 25); - E1000_WRITE_REG(&adapter->hw, TARC0, reg_tarc); - reg_tarc = E1000_READ_REG(&adapter->hw, TARC1); - reg_tarc |= (1 << 25); - reg_tarc &= ~(1 << 28); - E1000_WRITE_REG(&adapter->hw, TARC1, reg_tarc); - } else if (adapter->hw.mac_type == em_80003es2lan) { - reg_tarc = E1000_READ_REG(&adapter->hw, TARC0); - reg_tarc |= 1; - E1000_WRITE_REG(&adapter->hw, TARC0, reg_tarc); - reg_tarc = E1000_READ_REG(&adapter->hw, TARC1); - reg_tarc |= 1; - E1000_WRITE_REG(&adapter->hw, TARC1, reg_tarc); } /* Program the Transmit Control Register */ @@ -2388,11 +2434,11 @@ em_initialize_transmit_unit(struct adapter * adapter) else reg_tctl |= E1000_HDX_COLLISION_DISTANCE << E1000_COLD_SHIFT; - /* This write will effectively turn on the transmit unit */ + /* This write will effectively turn on the transmit unit. */ E1000_WRITE_REG(&adapter->hw, TCTL, reg_tctl); - /* Setup Transmit Descriptor Settings for this adapter */ - adapter->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_RS; + /* Setup Transmit Descriptor Base Settings */ + adapter->txd_cmd = E1000_TXD_CMD_IFCS; if (adapter->tx_int_delay.value > 0) adapter->txd_cmd |= E1000_TXD_CMD_IDE; @@ -2404,7 +2450,7 @@ em_initialize_transmit_unit(struct adapter * adapter) * **********************************************************************/ static void -em_free_transmit_structures(struct adapter * adapter) +em_free_transmit_structures(struct adapter *adapter) { struct em_buffer *tx_buffer; int i; @@ -2445,7 +2491,7 @@ em_free_transmit_structures(struct adapter * adapter) * **********************************************************************/ static void -em_transmit_checksum_setup(struct adapter * adapter, +em_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp, uint32_t *txd_upper, uint32_t *txd_lower) @@ -2494,14 +2540,14 @@ em_transmit_checksum_setup(struct adapter * adapter, TXD->lower_setup.ip_fields.ipcse = htole16(ETHER_HDR_LEN + sizeof(struct ip) - 1); - TXD->upper_setup.tcp_fields.tucss = + TXD->upper_setup.tcp_fields.tucss = ETHER_HDR_LEN + sizeof(struct ip); TXD->upper_setup.tcp_fields.tucse = htole16(0); if (adapter->active_checksum_context == OFFLOAD_TCP_IP) { TXD->upper_setup.tcp_fields.tucso = - ETHER_HDR_LEN + sizeof(struct ip) + - offsetof(struct tcphdr, th_sum); + ETHER_HDR_LEN + sizeof(struct ip) + + offsetof(struct tcphdr, th_sum); } else if (adapter->active_checksum_context == OFFLOAD_UDP_IP) { TXD->upper_setup.tcp_fields.tucso = ETHER_HDR_LEN + sizeof(struct ip) + @@ -2512,6 +2558,7 @@ em_transmit_checksum_setup(struct adapter * adapter, TXD->cmd_and_length = htole32(adapter->txd_cmd | E1000_TXD_CMD_DEXT); tx_buffer->m_head = NULL; + tx_buffer->next_eop = -1; if (++curr_txd == adapter->num_tx_desc) curr_txd = 0; @@ -2529,52 +2576,77 @@ em_transmit_checksum_setup(struct adapter * adapter, **********************************************************************/ static void -em_clean_transmit_interrupts(struct adapter *adapter) +em_txeof(struct adapter *adapter) { - int i, num_avail; + int first, last, done, num_avail; struct em_buffer *tx_buffer; - struct em_tx_desc *tx_desc; + struct em_tx_desc *tx_desc, *eop_desc; struct ifnet *ifp = &adapter->interface_data.ac_if; if (adapter->num_tx_desc_avail == adapter->num_tx_desc) return; num_avail = adapter->num_tx_desc_avail; - i = adapter->oldest_used_tx_desc; + first = adapter->next_tx_to_clean; + tx_desc = &adapter->tx_desc_base[first]; + tx_buffer = &adapter->tx_buffer_area[first]; + last = tx_buffer->next_eop; + KKASSERT(last >= 0 && last < adapter->num_tx_desc); + eop_desc = &adapter->tx_desc_base[last]; - tx_buffer = &adapter->tx_buffer_area[i]; - tx_desc = &adapter->tx_desc_base[i]; + /* + * Now caculate the terminating index for the cleanup loop below + */ + if (++last == adapter->num_tx_desc) + last = 0; + done = last; bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_POSTREAD); - while(tx_desc->upper.fields.status & E1000_TXD_STAT_DD) { - tx_desc->upper.data = 0; - num_avail++; + while (eop_desc->upper.fields.status & E1000_TXD_STAT_DD) { + while (first != done) { + tx_desc->upper.data = 0; + tx_desc->lower.data = 0; + num_avail++; - logif(pkt_txclean); + logif(pkt_txclean); - 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); + 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); - m_freem(tx_buffer->m_head); - tx_buffer->m_head = NULL; - } + m_freem(tx_buffer->m_head); + tx_buffer->m_head = NULL; + } + tx_buffer->next_eop = -1; - if (++i == adapter->num_tx_desc) - i = 0; + if (++first == adapter->num_tx_desc) + first = 0; - tx_buffer = &adapter->tx_buffer_area[i]; - tx_desc = &adapter->tx_desc_base[i]; + tx_buffer = &adapter->tx_buffer_area[first]; + tx_desc = &adapter->tx_desc_base[first]; + } + /* See if we can continue to the next packet */ + last = tx_buffer->next_eop; + if (last != -1) { + KKASSERT(last >= 0 && last < adapter->num_tx_desc); + eop_desc = &adapter->tx_desc_base[last]; + if (++last == adapter->num_tx_desc) + last = 0; + done = last; + } else { + break; + } } bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_PREWRITE); - adapter->oldest_used_tx_desc = i; + adapter->next_tx_to_clean = first; /* * If we have enough room, clear IFF_OACTIVE to tell the stack @@ -2612,7 +2684,7 @@ em_get_buf(int i, struct adapter *adapter, struct mbuf *nmp, int how) mp = m_getcl(how, MT_DATA, M_PKTHDR); if (mp == NULL) { adapter->mbuf_cluster_failed++; - return(ENOBUFS); + return (ENOBUFS); } mp->m_len = mp->m_pkthdr.len = MCLBYTES; } else { @@ -2620,6 +2692,7 @@ em_get_buf(int i, struct adapter *adapter, struct mbuf *nmp, int how) mp->m_data = mp->m_ext.ext_buf; mp->m_next = NULL; } + if (ifp->if_mtu <= ETHERMTU) m_adj(mp, ETHER_ALIGN); @@ -2634,20 +2707,20 @@ em_get_buf(int i, struct adapter *adapter, struct mbuf *nmp, int how) em_dmamap_cb, &paddr, 0); if (error) { m_free(mp); - return(error); + return (error); } rx_buffer->m_head = mp; adapter->rx_desc_base[i].buffer_addr = htole64(paddr); bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD); - return(0); + return (0); } /********************************************************************* * - * Allocate memory for rx_buffer structures. Since we use one - * rx_buffer per received packet, the maximum number of rx_buffer's - * that we'll need is equal to the number of receive descriptors + * Allocate memory for rx_buffer structures. Since we use one + * rx_buffer per received packet, the maximum number of rx_buffer's + * that we'll need is equal to the number of receive descriptors * that we've allocated. * **********************************************************************/ @@ -2668,73 +2741,68 @@ em_allocate_receive_structures(struct adapter *adapter) MCLBYTES, /* maxsize */ 1, /* nsegments */ MCLBYTES, /* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ + 0, /* flags */ &adapter->rxtag); - if (error != 0) { - device_printf(adapter->dev, "em_allocate_receive_structures: " - "bus_dma_tag_create failed; error %u\n", error); - goto fail_0; + if (error) { + device_printf(adapter->dev, "%s: bus_dma_tag_create failed; " + "error %u\n", __func__, error); + goto fail; } rx_buffer = adapter->rx_buffer_area; for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { error = bus_dmamap_create(adapter->rxtag, BUS_DMA_NOWAIT, &rx_buffer->map); - if (error != 0) { + if (error) { device_printf(adapter->dev, - "em_allocate_receive_structures: " - "bus_dmamap_create failed; error %u\n", - error); - goto fail_1; + "%s: bus_dmamap_create failed; " + "error %u\n", __func__, error); + goto fail; } } for (i = 0; i < adapter->num_rx_desc; i++) { error = em_get_buf(i, adapter, NULL, MB_WAIT); - if (error != 0) { - adapter->rx_buffer_area[i].m_head = NULL; - adapter->rx_desc_base[i].buffer_addr = 0; - return(error); - } + if (error) + goto fail; } bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, BUS_DMASYNC_PREWRITE); - return(0); - -fail_1: - bus_dma_tag_destroy(adapter->rxtag); -fail_0: - adapter->rxtag = NULL; - kfree(adapter->rx_buffer_area, M_DEVBUF); - adapter->rx_buffer_area = NULL; - return(error); + return (0); +fail: + em_free_receive_structures(adapter); + return (error); } /********************************************************************* * * Allocate and initialize receive structures. - * + * **********************************************************************/ static int em_setup_receive_structures(struct adapter *adapter) { - bzero((void *) adapter->rx_desc_base, - (sizeof(struct em_rx_desc)) * adapter->num_rx_desc); + int error; - if (em_allocate_receive_structures(adapter)) - return(ENOMEM); + bzero(adapter->rx_desc_base, + sizeof(struct em_rx_desc) * adapter->num_rx_desc); + + error = em_allocate_receive_structures(adapter); + if (error) + return (error); /* Setup our descriptor pointers */ adapter->next_rx_desc_to_check = 0; - return(0); + + return (0); } /********************************************************************* * * Enable receive unit. - * + * **********************************************************************/ static void em_initialize_receive_unit(struct adapter *adapter) @@ -2748,7 +2816,10 @@ em_initialize_receive_unit(struct adapter *adapter) ifp = &adapter->interface_data.ac_if; - /* Make sure receives are disabled while setting up the descriptor ring */ + /* + * Make sure receives are disabled while setting + * up the descriptor ring + */ E1000_WRITE_REG(&adapter->hw, RCTL, 0); /* Set the Receive Delay Timer Register */ @@ -2775,10 +2846,6 @@ em_initialize_receive_unit(struct adapter *adapter) E1000_WRITE_REG(&adapter->hw, RDBAH, (uint32_t)(bus_addr >> 32)); E1000_WRITE_REG(&adapter->hw, RDBAL, (uint32_t)bus_addr); - /* Setup the HW Rx Head and Tail Descriptor Pointers */ - E1000_WRITE_REG(&adapter->hw, RDT, adapter->num_rx_desc - 1); - E1000_WRITE_REG(&adapter->hw, RDH, 0); - /* Setup the Receive Control Register */ reg_rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | @@ -2793,13 +2860,16 @@ em_initialize_receive_unit(struct adapter *adapter) reg_rctl |= E1000_RCTL_SZ_2048; break; case EM_RXBUFFER_4096: - reg_rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | E1000_RCTL_LPE; + reg_rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | + E1000_RCTL_LPE; break; case EM_RXBUFFER_8192: - reg_rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX | E1000_RCTL_LPE; + reg_rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX | + E1000_RCTL_LPE; break; case EM_RXBUFFER_16384: - reg_rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX | E1000_RCTL_LPE; + reg_rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX | + E1000_RCTL_LPE; break; } @@ -2807,7 +2877,7 @@ em_initialize_receive_unit(struct adapter *adapter) reg_rctl |= E1000_RCTL_LPE; /* Enable 82543 Receive Checksum Offload for TCP and UDP */ - if ((adapter->hw.mac_type >= em_82543) && + if ((adapter->hw.mac_type >= em_82543) && (ifp->if_capenable & IFCAP_RXCSUM)) { reg_rxcsum = E1000_READ_REG(&adapter->hw, RXCSUM); reg_rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); @@ -2816,6 +2886,10 @@ em_initialize_receive_unit(struct adapter *adapter) /* Enable Receives */ E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl); + + /* Setup the HW Rx Head and Tail Descriptor Pointers */ + E1000_WRITE_REG(&adapter->hw, RDH, 0); + E1000_WRITE_REG(&adapter->hw, RDT, adapter->num_rx_desc - 1); } /********************************************************************* @@ -2834,13 +2908,17 @@ em_free_receive_structures(struct adapter *adapter) if (adapter->rx_buffer_area != NULL) { rx_buffer = adapter->rx_buffer_area; for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { + if (rx_buffer->m_head != NULL) { + bus_dmamap_unload(adapter->rxtag, + rx_buffer->map); + m_freem(rx_buffer->m_head); + rx_buffer->m_head = NULL; + } if (rx_buffer->map != NULL) { - bus_dmamap_unload(adapter->rxtag, rx_buffer->map); - bus_dmamap_destroy(adapter->rxtag, rx_buffer->map); + bus_dmamap_destroy(adapter->rxtag, + rx_buffer->map); + rx_buffer->map = NULL; } - if (rx_buffer->m_head != NULL) - m_freem(rx_buffer->m_head); - rx_buffer->m_head = NULL; } } if (adapter->rx_buffer_area != NULL) { @@ -2864,7 +2942,7 @@ em_free_receive_structures(struct adapter *adapter) * *********************************************************************/ static void -em_process_receive_interrupts(struct adapter *adapter, int count) +em_rxeof(struct adapter *adapter, int count) { struct ifnet *ifp; struct mbuf *mp; @@ -2883,10 +2961,10 @@ em_process_receive_interrupts(struct adapter *adapter, int count) bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, BUS_DMASYNC_POSTREAD); - if (!((current_desc->status) & E1000_RXD_STAT_DD)) + if (!(current_desc->status & E1000_RXD_STAT_DD)) return; - while ((current_desc->status & E1000_RXD_STAT_DD) && (count != 0)) { + while ((current_desc->status & E1000_RXD_STAT_DD) && count != 0) { logif(pkt_receive); mp = adapter->rx_buffer_area[i].m_head; bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map, @@ -2938,7 +3016,7 @@ em_process_receive_interrupts(struct adapter *adapter, int count) if (em_get_buf(i, adapter, NULL, MB_DONTWAIT) == ENOBUFS) { adapter->dropped_pkts++; em_get_buf(i, adapter, mp, MB_DONTWAIT); - if (adapter->fmp != NULL) + if (adapter->fmp != NULL) m_freem(adapter->fmp); adapter->fmp = NULL; adapter->lmp = NULL; @@ -2955,8 +3033,9 @@ em_process_receive_interrupts(struct adapter *adapter, int count) } else { /* Chain mbuf's together */ /* - * Adjust length of previous mbuf in chain if we - * received less than 4 bytes in the last descriptor. + * Adjust length of previous mbuf in chain if + * we received less than 4 bytes in the last + * descriptor. */ if (prev_len_adj > 0) { adapter->lmp->m_len -= prev_len_adj; @@ -2993,10 +3072,10 @@ em_process_receive_interrupts(struct adapter *adapter, int count) } skip: - /* Zero out the receive descriptors status */ + /* Zero out the receive descriptors status. */ current_desc->status = 0; - /* Advance our pointers to the next descriptor */ + /* Advance our pointers to the next descriptor. */ if (++i == adapter->num_rx_desc) { i = 0; current_desc = adapter->rx_desc_base; @@ -3019,7 +3098,7 @@ skip: /********************************************************************* * - * Verify that the hardware indicated that the checksum is valid. + * Verify that the hardware indicated that the checksum is valid. * Inform the stack about the status of checksum so that stack * doesn't spend time verifying the checksum. * @@ -3049,9 +3128,9 @@ em_receive_checksum(struct adapter *adapter, } if (rx_desc->status & E1000_RXD_STAT_TCPCS) { - /* Did it pass? */ + /* Did it pass? */ if (!(rx_desc->errors & E1000_RXD_ERR_TCPE)) { - mp->m_pkthdr.csum_flags |= + mp->m_pkthdr.csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); mp->m_pkthdr.csum_data = htons(0xffff); } @@ -3067,14 +3146,14 @@ em_enable_vlans(struct adapter *adapter) E1000_WRITE_REG(&adapter->hw, VET, ETHERTYPE_VLAN); ctrl = E1000_READ_REG(&adapter->hw, CTRL); - ctrl |= E1000_CTRL_VME; + ctrl |= E1000_CTRL_VME; E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); } static void em_disable_vlans(struct adapter *adapter) { - uint32_t ctrl; + uint32_t ctrl; ctrl = E1000_READ_REG(&adapter->hw, CTRL); ctrl &= ~E1000_CTRL_VME; @@ -3102,8 +3181,8 @@ static void em_disable_intr(struct adapter *adapter) { /* - * The first version of 82542 had an errata where when link was - * forced it would stay up even up even if the cable was disconnected. + * The first version of 82542 had an errata where when link was forced + * it would stay up even up even if the cable was disconnected. * Sequence errors were used to detect the disconnect and then the * driver would unforce the link. This code in the in the ISR. For * this to work correctly the Sequence error interrupt had to be @@ -3122,21 +3201,21 @@ em_disable_intr(struct adapter *adapter) static int em_is_valid_ether_addr(uint8_t *addr) { - char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; + static const char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; - if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) - return(FALSE); + if ((addr[0] & 1) || !bcmp(addr, zero_addr, ETHER_ADDR_LEN)) + return (FALSE); else - return(TRUE); + return (TRUE); } -void +void em_write_pci_cfg(struct em_hw *hw, uint32_t reg, uint16_t *value) { pci_write_config(((struct em_osdep *)hw->back)->dev, reg, *value, 2); } -void +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); @@ -3157,19 +3236,34 @@ em_pci_clear_mwi(struct em_hw *hw) } uint32_t -em_read_reg_io(struct em_hw *hw, uint32_t offset) +em_io_read(struct em_hw *hw, unsigned long port) { - bus_space_write_4(hw->reg_io_tag, hw->reg_io_handle, 0, offset); - return(bus_space_read_4(hw->reg_io_tag, hw->reg_io_handle, 4)); + struct em_osdep *io = hw->back; + + return bus_space_read_4(io->io_bus_space_tag, + io->io_bus_space_handle, port); } void -em_write_reg_io(struct em_hw *hw, uint32_t offset, uint32_t value) +em_io_write(struct em_hw *hw, unsigned long port, uint32_t value) +{ + struct em_osdep *io = hw->back; + + bus_space_write_4(io->io_bus_space_tag, + io->io_bus_space_handle, port, value); +} + +/* + * We may eventually really do this, but its unnecessary + * for now so we just return unsupported. + */ +int32_t +em_read_pcie_cap_reg(struct em_hw *hw, uint32_t reg, uint16_t *value) { - bus_space_write_4(hw->reg_io_tag, hw->reg_io_handle, 0, offset); - bus_space_write_4(hw->reg_io_tag, hw->reg_io_handle, 4, value); + return (0); } + /********************************************************************* * 82544 Coexistence issue workaround. * There are 2 issues. @@ -3190,7 +3284,7 @@ em_write_reg_io(struct em_hw *hw, uint32_t offset, uint32_t value) * *************************************************************************/ static uint32_t -em_fill_descriptors(uint64_t address, uint32_t length, PDESC_ARRAY desc_array) +em_fill_descriptors(bus_addr_t address, uint32_t length, PDESC_ARRAY desc_array) { /* Since issue is sensitive to length and address.*/ /* Let us first check the address...*/ @@ -3199,7 +3293,7 @@ em_fill_descriptors(uint64_t address, uint32_t length, PDESC_ARRAY desc_array) desc_array->descriptor[0].address = address; desc_array->descriptor[0].length = length; desc_array->elements = 1; - return(desc_array->elements); + return (desc_array->elements); } safe_terminator = (uint32_t)((((uint32_t)address & 0x7) + (length & 0xF)) & 0xF); /* if it does not fall between 0x1 to 0x4 and 0x9 to 0xC then return */ @@ -3209,7 +3303,7 @@ em_fill_descriptors(uint64_t address, uint32_t length, PDESC_ARRAY desc_array) desc_array->descriptor[0].address = address; desc_array->descriptor[0].length = length; desc_array->elements = 1; - return(desc_array->elements); + return (desc_array->elements); } desc_array->descriptor[0].address = address; @@ -3217,12 +3311,12 @@ em_fill_descriptors(uint64_t address, uint32_t length, PDESC_ARRAY desc_array) desc_array->descriptor[1].address = address + (length - 4); desc_array->descriptor[1].length = 4; desc_array->elements = 2; - return(desc_array->elements); + return (desc_array->elements); } /********************************************************************** * - * Update the board statistics counters. + * Update the board statistics counters. * **********************************************************************/ static void @@ -3264,7 +3358,7 @@ em_update_stats_counters(struct adapter *adapter) /* For the 64-bit byte counters the low dword must be read first. */ /* Both registers clear on the read of the high dword */ - adapter->stats.gorcl += E1000_READ_REG(&adapter->hw, GORCL); + adapter->stats.gorcl += E1000_READ_REG(&adapter->hw, GORCL); adapter->stats.gorch += E1000_READ_REG(&adapter->hw, GORCH); adapter->stats.gotcl += E1000_READ_REG(&adapter->hw, GOTCL); adapter->stats.gotch += E1000_READ_REG(&adapter->hw, GOTCH); @@ -3340,10 +3434,9 @@ em_print_debug_info(struct adapter *adapter) uint8_t *hw_addr = adapter->hw.hw_addr; device_printf(dev, "Adapter hardware address = %p \n", hw_addr); - device_printf(dev, "CTRL = 0x%x\n", - E1000_READ_REG(&adapter->hw, CTRL)); - device_printf(dev, "RCTL = 0x%x PS=(0x8402)\n", - E1000_READ_REG(&adapter->hw, RCTL)); + device_printf(dev, "CTRL = 0x%x RCTL = 0x%x\n", + E1000_READ_REG(&adapter->hw, CTRL), + E1000_READ_REG(&adapter->hw, RCTL)); device_printf(dev, "Packet buffer = Tx=%dk Rx=%dk\n", ((E1000_READ_REG(&adapter->hw, PBA) & 0xffff0000) >> 16), (E1000_READ_REG(&adapter->hw, PBA) & 0xffff)); @@ -3355,7 +3448,7 @@ em_print_debug_info(struct adapter *adapter) device_printf(dev, "rx_int_delay = %d, rx_abs_int_delay = %d\n", E1000_READ_REG(&adapter->hw, RDTR), E1000_READ_REG(&adapter->hw, RADV)); - device_printf(dev, "fifo workaround = %lld, fifo_reset = %lld\n", + device_printf(dev, "fifo workaround = %lld, fifo_reset_count = %lld\n", (long long)adapter->tx_fifo_wrk_cnt, (long long)adapter->tx_fifo_reset_cnt); device_printf(dev, "hw tdh = %d, hw tdt = %d\n", @@ -3380,8 +3473,6 @@ em_print_hw_stats(struct adapter *adapter) { device_t dev= adapter->dev; - device_printf(dev, "Adapter: %p\n", adapter); - device_printf(dev, "Excessive collisions = %lld\n", (long long)adapter->stats.ecol); device_printf(dev, "Symbol errors = %lld\n", @@ -3395,8 +3486,10 @@ em_print_hw_stats(struct adapter *adapter) (long long)adapter->stats.mpc); device_printf(dev, "Receive No Buffers = %lld\n", (long long)adapter->stats.rnbc); - device_printf(dev, "Receive length errors = %lld\n", - (long long)adapter->stats.rlec); + /* RLEC is inaccurate on some hardware, calculate our own. */ + device_printf(dev, "Receive Length errors = %lld\n", + (long long)adapter->stats.roc + + (long long)adapter->stats.ruc); device_printf(dev, "Receive errors = %lld\n", (long long)adapter->stats.rxerrc); device_printf(dev, "Crc errors = %lld\n", @@ -3435,14 +3528,14 @@ em_sysctl_debug_info(SYSCTL_HANDLER_ARGS) error = sysctl_handle_int(oidp, &result, 0, req); if (error || !req->newptr) - return(error); + return (error); if (result == 1) { adapter = (struct adapter *)arg1; em_print_debug_info(adapter); } - return(error); + return (error); } static int @@ -3456,14 +3549,14 @@ em_sysctl_stats(SYSCTL_HANDLER_ARGS) error = sysctl_handle_int(oidp, &result, 0, req); if (error || !req->newptr) - return(error); + return (error); if (result == 1) { adapter = (struct adapter *)arg1; em_print_hw_stats(adapter); } - return(error); + return (error); } static int @@ -3481,9 +3574,9 @@ em_sysctl_int_delay(SYSCTL_HANDLER_ARGS) usecs = info->value; error = sysctl_handle_int(oidp, &usecs, 0, req); if (error != 0 || req->newptr == NULL) - return(error); + return (error); if (usecs < 0 || usecs > E1000_TICKS_TO_USECS(65535)) - return(EINVAL); + return (EINVAL); info->value = usecs; ticks = E1000_USECS_TO_TICKS(usecs); @@ -3508,7 +3601,7 @@ em_sysctl_int_delay(SYSCTL_HANDLER_ARGS) } E1000_WRITE_OFFSET(&adapter->hw, info->offset, regval); lwkt_serialize_exit(adapter->interface_data.ac_if.if_serializer); - return(0); + return (0); } static void @@ -3558,4 +3651,3 @@ em_sysctl_int_throttle(SYSCTL_HANDLER_ARGS) em_int_throttle_ceil); return 0; } - diff --git a/sys/dev/netif/em/if_em.h b/sys/dev/netif/em/if_em.h index cd37d1c7d6..989e2d0dd4 100644 --- a/sys/dev/netif/em/if_em.h +++ b/sys/dev/netif/em/if_em.h @@ -32,55 +32,11 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /*$FreeBSD: src/sys/dev/em/if_em.h,v 1.1.2.13 2003/06/09 21:43:41 pdeuskar Exp $*/ -/*$DragonFly: src/sys/dev/netif/em/if_em.h,v 1.18 2006/12/22 23:26:19 swildner Exp $*/ +/*$DragonFly: src/sys/dev/netif/em/if_em.h,v 1.19 2006/12/23 10:39:16 sephe Exp $*/ #ifndef _EM_H_DEFINED_ #define _EM_H_DEFINED_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#include - /* Tunables */ /* @@ -131,7 +87,8 @@ POSSIBILITY OF SUCH DAMAGE. #define EM_TIDV 64 /* - * EM_TADV - Transmit Absolute Interrupt Delay Value (Not valid for 82542/82543/82544) + * EM_TADV - Transmit Absolute Interrupt Delay Value + * (Not valid for 82542/82543/82544) * Valid Range: 0-65535 (0=off) * Default Value: 64 * This value, in units of 1.024 microseconds, limits the delay in which a @@ -157,10 +114,10 @@ POSSIBILITY OF SUCH DAMAGE. * * CAUTION: When setting EM_RDTR to a value other than 0, adapters * may hang (stop transmitting) under certain network conditions. - * If this occurs a WATCHDOG message is logged in the system event log. - * In addition, the controller is automatically reset, restoring the - * network connection. To eliminate the potential for the hang - * ensure that EM_RDTR is set to 0. + * If this occurs a WATCHDOG message is logged in the system + * event log. In addition, the controller is automatically reset, + * restoring the network connection. To eliminate the potential + * for the hang ensure that EM_RDTR is set to 0. */ #define EM_RDTR 0 @@ -228,7 +185,6 @@ POSSIBILITY OF SUCH DAMAGE. ADVERTISE_1000_FULL) #define EM_VENDOR_ID 0x8086 -#define EM_MMBA 0x0010 /* Mem base address */ #define EM_FLASH 0x0014 /* Flash memory on ICH8 */ #define EM_JUMBO_PBA 0x00000028 @@ -236,11 +192,36 @@ POSSIBILITY OF SUCH DAMAGE. #define EM_SMARTSPEED_DOWNSHIFT 3 #define EM_SMARTSPEED_MAX 15 - #define MAX_NUM_MULTICAST_ADDRESSES 128 #define PCI_ANY_ID (~0U) -#define ETHER_ALIGN 2 -#define EM_DBA_ALIGN 128 + + +/* + * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be + * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will + * also optimize cache line size effect. H/W supports up to cache line size 128. + */ +#define EM_DBA_ALIGN 128 + +#define SPEED_MODE_BIT (1 << 21) /* On PCI-E MACs only */ + +/* PCI Config defines */ +#define EM_BAR_TYPE(v) ((v) & EM_BAR_TYPE_MASK) +#define EM_BAR_TYPE_MASK 0x00000001 +#define EM_BAR_TYPE_MMEM 0x00000000 +#define EM_BAR_TYPE_IO 0x00000001 +#define EM_BAR_MEM_TYPE(v) ((v) & EM_BAR_MEM_TYPE_MASK) +#define EM_BAR_MEM_TYPE_MASK 0x00000006 +#define EM_BAR_MEM_TYPE_32BIT 0x00000000 +#define EM_BAR_MEM_TYPE_64BIT 0x00000004 + +/* + * Community introduced backward + * compatibility issue. + */ +#if !defined(PCIR_CIS) +#define PCIR_CIS PCIR_CARDBUSCIS +#endif /* Defines for printing debug information */ #define DEBUG_INIT 0 @@ -283,6 +264,7 @@ typedef struct _em_vendor_info_t { struct em_buffer { + int next_eop; /* Index of the desc to watch */ struct mbuf *m_head; bus_dmamap_t map; /* bus_dma map for packet */ }; @@ -302,7 +284,6 @@ struct em_dma_alloc { bus_dma_tag_t dma_tag; bus_dmamap_t dma_map; bus_dma_segment_t dma_seg; - bus_size_t dma_size; int dma_nseg; }; @@ -314,126 +295,131 @@ typedef enum _XSUM_CONTEXT_T { struct adapter; struct em_int_delay_info { - struct adapter *adapter; /* Back-pointer to the adapter struct */ - int offset; /* Register offset to read/write */ - int value; /* Current value in usecs */ + struct adapter *adapter; /* Back-pointer to the adapter struct */ + int offset; /* Register offset to read/write */ + int value; /* Current value in usecs */ }; /* For 82544 PCIX Workaround */ typedef struct _ADDRESS_LENGTH_PAIR { - u_int64_t address; - u_int32_t length; + uint64_t address; + uint32_t length; } ADDRESS_LENGTH_PAIR, *PADDRESS_LENGTH_PAIR; typedef struct _DESCRIPTOR_PAIR { - ADDRESS_LENGTH_PAIR descriptor[4]; - u_int32_t elements; + ADDRESS_LENGTH_PAIR descriptor[4]; + uint32_t elements; } DESC_ARRAY, *PDESC_ARRAY; /* Our adapter structure */ struct adapter { struct arpcom interface_data; - struct em_hw hw; + struct em_hw hw; /* Operating-system-specific structures */ struct em_osdep osdep; - struct device *dev; - struct resource *res_memory; - struct resource *flash_mem; - struct resource *res_ioport; - struct resource *res_interrupt; - void *int_handler_tag; - struct ifmedia media; - struct callout timer; - struct callout tx_fifo_timer; - int io_rid; + struct device *dev; + struct resource *res_memory; + struct resource *flash_mem; + struct resource *res_ioport; + struct resource *res_interrupt; + void *int_handler_tag; + struct ifmedia media; + struct callout timer; + struct callout tx_fifo_timer; + int if_flags; + int io_rid; int em_insert_vlan_header; /* Info about the board itself */ - u_int32_t part_num; - u_int8_t link_active; - u_int16_t link_speed; - u_int16_t link_duplex; - u_int32_t smartspeed; + uint32_t part_num; + uint8_t link_active; + uint16_t link_speed; + uint16_t link_duplex; + uint32_t smartspeed; struct em_int_delay_info tx_int_delay; - struct em_int_delay_info tx_abs_int_delay; - struct em_int_delay_info rx_int_delay; - struct em_int_delay_info rx_abs_int_delay; + struct em_int_delay_info tx_abs_int_delay; + struct em_int_delay_info rx_int_delay; + struct em_int_delay_info rx_abs_int_delay; XSUM_CONTEXT_T active_checksum_context; /* - * Transmit definitions - * - * We have an array of num_tx_desc descriptors (handled - * by the controller) paired with an array of tx_buffers - * (at tx_buffer_area). - * The index of the next available descriptor is next_avail_tx_desc. - * The number of remaining tx_desc is num_tx_desc_avail. - */ + * Transmit definitions + * + * We have an array of num_tx_desc descriptors (handled + * by the controller) paired with an array of tx_buffers + * (at tx_buffer_area). + * The index of the next available descriptor is next_avail_tx_desc. + * The number of remaining tx_desc is num_tx_desc_avail. + */ struct em_dma_alloc txdma; /* bus_dma glue for tx desc */ - struct em_tx_desc *tx_desc_base; - u_int32_t next_avail_tx_desc; - u_int32_t oldest_used_tx_desc; - volatile u_int16_t num_tx_desc_avail; - u_int16_t num_tx_desc; - u_int32_t txd_cmd; - struct em_buffer *tx_buffer_area; + struct em_tx_desc *tx_desc_base; + uint32_t next_avail_tx_desc; + uint32_t next_tx_to_clean; + volatile uint16_t num_tx_desc_avail; + uint16_t num_tx_desc; + uint32_t txd_cmd; + struct em_buffer *tx_buffer_area; bus_dma_tag_t txtag; /* dma tag for tx */ /* * Receive definitions - * - * we have an array of num_rx_desc rx_desc (handled by the - * controller), and paired with an array of rx_buffers - * (at rx_buffer_area). - * The next pair to check on receive is at offset next_rx_desc_to_check - */ + * + * we have an array of num_rx_desc rx_desc (handled by the + * controller), and paired with an array of rx_buffers + * (at rx_buffer_area). + * The next pair to check on receive is at offset next_rx_desc_to_check + */ struct em_dma_alloc rxdma; /* bus_dma glue for rx desc */ - struct em_rx_desc *rx_desc_base; - u_int32_t next_rx_desc_to_check; - u_int16_t num_rx_desc; - u_int32_t rx_buffer_len; - struct em_buffer *rx_buffer_area; + struct em_rx_desc *rx_desc_base; + uint32_t next_rx_desc_to_check; + uint16_t num_rx_desc; + uint32_t rx_buffer_len; + struct em_buffer *rx_buffer_area; bus_dma_tag_t rxtag; - /* Jumbo frame */ - struct mbuf *fmp; - struct mbuf *lmp; + /* + * First/last mbuf pointers, for + * collecting multisegment RX packets. + */ + struct mbuf *fmp; + struct mbuf *lmp; - struct sysctl_ctx_list sysctl_ctx; - struct sysctl_oid *sysctl_tree; + 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; - unsigned long mbuf_cluster_failed; - unsigned long no_tx_desc_avail1; - unsigned long no_tx_desc_avail2; + unsigned long dropped_pkts; + unsigned long mbuf_alloc_failed; + unsigned long mbuf_cluster_failed; + unsigned long no_tx_desc_avail1; + unsigned long no_tx_desc_avail2; unsigned long no_tx_map_avail; unsigned long no_tx_dma_setup; unsigned long rx_overruns; unsigned long watchdog_timeouts; /* Used in for 82547 10Mb Half workaround */ - u_int32_t tx_fifo_size; - u_int32_t tx_fifo_head; - u_int32_t tx_fifo_head_addr; - u_int64_t tx_fifo_reset_cnt; - u_int64_t tx_fifo_wrk_cnt; - u_int32_t tx_head_addr; + uint32_t tx_fifo_size; + uint32_t tx_fifo_head; + uint32_t tx_fifo_head_addr; + uint64_t tx_fifo_reset_cnt; + uint64_t tx_fifo_wrk_cnt; + uint32_t tx_head_addr; #define EM_PBA_BYTES_SHIFT 0xA #define EM_TX_HEAD_ADDR_SHIFT 7 #define EM_PBA_TX_MASK 0xFFFF0000 #define EM_FIFO_HDR 0x10 + #define EM_82547_PKT_THRESH 0x3e0 /* For 82544 PCIX Workaround */ - boolean_t pcix_82544; - boolean_t in_detach; + boolean_t pcix_82544; + boolean_t in_detach; struct em_hw_stats stats; }; diff --git a/sys/dev/netif/em/if_em_hw.c b/sys/dev/netif/em/if_em_hw.c index 7054eeb3b6..72fa4a651b 100644 --- a/sys/dev/netif/em/if_em_hw.c +++ b/sys/dev/netif/em/if_em_hw.c @@ -30,12 +30,13 @@ POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ /*$FreeBSD: src/sys/dev/em/if_em_hw.c,v 1.1.2.8 2003/06/09 21:43:41 pdeuskar Exp $*/ -/*$DragonFly: src/sys/dev/netif/em/if_em_hw.c,v 1.10 2006/08/12 13:03:44 sephe Exp $*/ +/*$DragonFly: src/sys/dev/netif/em/if_em_hw.c,v 1.11 2006/12/23 10:39:16 sephe Exp $*/ /* if_em_hw.c * Shared functions for accessing and configuring the MAC */ +#define STATIC static #ifdef LM #include "if_em_hw.h" @@ -43,6 +44,62 @@ POSSIBILITY OF SUCH DAMAGE. #include #endif +static int32_t em_swfw_sync_acquire(struct em_hw *hw, uint16_t mask); +static void em_swfw_sync_release(struct em_hw *hw, uint16_t mask); +static int32_t em_read_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t *data); +static int32_t em_write_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t data); +static int32_t em_get_software_semaphore(struct em_hw *hw); +static void em_release_software_semaphore(struct em_hw *hw); + +static uint8_t em_arc_subsystem_valid(struct em_hw *hw); +static int32_t em_check_downshift(struct em_hw *hw); +static int32_t em_check_polarity(struct em_hw *hw, em_rev_polarity *polarity); +static void em_clear_vfta(struct em_hw *hw); +static int32_t em_commit_shadow_ram(struct em_hw *hw); +static int32_t em_config_dsp_after_link_change(struct em_hw *hw, boolean_t link_up); +static int32_t em_config_fc_after_link_up(struct em_hw *hw); +static int32_t em_detect_gig_phy(struct em_hw *hw); +static int32_t em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t bank); +static int32_t em_get_auto_rd_done(struct em_hw *hw); +static int32_t em_get_cable_length(struct em_hw *hw, uint16_t *min_length, uint16_t *max_length); +static int32_t em_get_hw_eeprom_semaphore(struct em_hw *hw); +static int32_t em_get_phy_cfg_done(struct em_hw *hw); +static int32_t em_get_software_flag(struct em_hw *hw); +static int32_t em_ich8_cycle_init(struct em_hw *hw); +static int32_t em_ich8_flash_cycle(struct em_hw *hw, uint32_t timeout); +static int32_t em_id_led_init(struct em_hw *hw); +static int32_t em_init_lcd_from_nvm_config_region(struct em_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size); +static int32_t em_init_lcd_from_nvm(struct em_hw *hw); +static void em_init_rx_addrs(struct em_hw *hw); +static void em_initialize_hardware_bits(struct em_hw *hw); +static boolean_t em_is_onboard_nvm_eeprom(struct em_hw *hw); +static int32_t em_kumeran_lock_loss_workaround(struct em_hw *hw); +static int32_t em_mng_enable_host_if(struct em_hw *hw); +static int32_t em_mng_host_if_write(struct em_hw *hw, uint8_t *buffer, uint16_t length, uint16_t offset, uint8_t *sum); +static int32_t em_mng_write_cmd_header(struct em_hw* hw, struct em_host_mng_command_header* hdr); +static int32_t em_mng_write_commit(struct em_hw *hw); +static int32_t em_phy_ife_get_info(struct em_hw *hw, struct em_phy_info *phy_info); +static int32_t em_phy_igp_get_info(struct em_hw *hw, struct em_phy_info *phy_info); +static int32_t em_read_eeprom_eerd(struct em_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); +static int32_t em_write_eeprom_eewr(struct em_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); +static int32_t em_poll_eerd_eewr_done(struct em_hw *hw, int eerd); +static int32_t em_phy_m88_get_info(struct em_hw *hw, struct em_phy_info *phy_info); +static void em_put_hw_eeprom_semaphore(struct em_hw *hw); +static int32_t em_read_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t *data); +static int32_t em_verify_write_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t byte); +static int32_t em_write_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t byte); +static int32_t em_read_ich8_word(struct em_hw *hw, uint32_t index, uint16_t *data); +static int32_t em_read_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size, uint16_t *data); +static int32_t em_write_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size, uint16_t data); +static int32_t em_read_eeprom_ich8(struct em_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); +static int32_t em_write_eeprom_ich8(struct em_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); +static void em_release_software_flag(struct em_hw *hw); +static int32_t em_set_d3_lplu_state(struct em_hw *hw, boolean_t active); +static int32_t em_set_d0_lplu_state(struct em_hw *hw, boolean_t active); +static int32_t em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop); +static void em_set_pci_express_master_disable(struct em_hw *hw); +static int32_t em_wait_autoneg(struct em_hw *hw); +static void em_write_reg_io(struct em_hw *hw, uint32_t offset, uint32_t value); static int32_t em_set_phy_type(struct em_hw *hw); static void em_phy_init_script(struct em_hw *hw); static int32_t em_setup_copper_link(struct em_hw *hw); @@ -106,13 +163,12 @@ uint16_t em_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] = 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121, 124}; - /****************************************************************************** * Set the phy type member in the hw struct. * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -int32_t +STATIC int32_t em_set_phy_type(struct em_hw *hw) { DEBUGFUNC("em_set_phy_type"); @@ -158,7 +214,6 @@ em_set_phy_type(struct em_hw *hw) return E1000_SUCCESS; } - /****************************************************************************** * IGP phy init script - initializes the GbE PHY * @@ -339,6 +394,8 @@ em_set_mac_type(struct em_hw *hw) case E1000_DEV_ID_82571EB_COPPER: case E1000_DEV_ID_82571EB_FIBER: case E1000_DEV_ID_82571EB_SERDES: + case E1000_DEV_ID_82571EB_QUAD_COPPER: + case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: hw->mac_type = em_82571; break; case E1000_DEV_ID_82572EI_COPPER: @@ -362,6 +419,8 @@ em_set_mac_type(struct em_hw *hw) case E1000_DEV_ID_ICH8_IGP_AMT: case E1000_DEV_ID_ICH8_IGP_C: case E1000_DEV_ID_ICH8_IFE: + case E1000_DEV_ID_ICH8_IFE_GT: + case E1000_DEV_ID_ICH8_IFE_G: case E1000_DEV_ID_ICH8_IGP_M: hw->mac_type = em_ich8lan; break; @@ -616,19 +675,12 @@ em_reset_hw(struct em_hw *hw) E1000_WRITE_FLUSH(hw); } /* fall through */ - case em_82571: - case em_82572: - case em_ich8lan: - case em_80003es2lan: + default: + /* Auto read done will delay 5ms or poll based on mac type */ ret_val = em_get_auto_rd_done(hw); if (ret_val) - /* We don't want to continue accessing MAC registers. */ return ret_val; break; - default: - /* Wait for EEPROM reload (it happens automatically) */ - msec_delay(5); - break; } /* Disable HW ARPs on ASF enabled adapters */ @@ -670,6 +722,110 @@ em_reset_hw(struct em_hw *hw) return E1000_SUCCESS; } +/****************************************************************************** + * + * Initialize a number of hardware-dependent bits + * + * hw: Struct containing variables accessed by shared code + * + *****************************************************************************/ +STATIC void +em_initialize_hardware_bits(struct em_hw *hw) +{ + if ((hw->mac_type >= em_82571) && (!hw->initialize_hw_bits_disable)) { + /* Settings common to all silicon */ + uint32_t reg_ctrl, reg_ctrl_ext; + uint32_t reg_tarc0, reg_tarc1; + uint32_t reg_tctl; + uint32_t reg_txdctl, reg_txdctl1; + + reg_tarc0 = E1000_READ_REG(hw, TARC0); + reg_tarc0 &= ~0x78000000; /* Clear bits 30, 29, 28, and 27 */ + + reg_txdctl = E1000_READ_REG(hw, TXDCTL); + reg_txdctl |= E1000_TXDCTL_COUNT_DESC; /* Set bit 22 */ + E1000_WRITE_REG(hw, TXDCTL, reg_txdctl); + + reg_txdctl1 = E1000_READ_REG(hw, TXDCTL1); + reg_txdctl1 |= E1000_TXDCTL_COUNT_DESC; /* Set bit 22 */ + E1000_WRITE_REG(hw, TXDCTL1, reg_txdctl1); + + switch (hw->mac_type) { + case em_82571: + case em_82572: + reg_tarc1 = E1000_READ_REG(hw, TARC1); + reg_tctl = E1000_READ_REG(hw, TCTL); + + /* Set the phy Tx compatible mode bits */ + reg_tarc1 &= ~0x60000000; /* Clear bits 30 and 29 */ + + reg_tarc0 |= 0x07800000; /* Set TARC0 bits 23-26 */ + reg_tarc1 |= 0x07000000; /* Set TARC1 bits 24-26 */ + + if (reg_tctl & E1000_TCTL_MULR) + reg_tarc1 &= ~0x10000000; /* Clear bit 28 if MULR is 1b */ + else + reg_tarc1 |= 0x10000000; /* Set bit 28 if MULR is 0b */ + + E1000_WRITE_REG(hw, TARC1, reg_tarc1); + break; + case em_82573: + reg_ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); + reg_ctrl = E1000_READ_REG(hw, CTRL); + + reg_ctrl_ext &= ~0x00800000; /* Clear bit 23 */ + reg_ctrl_ext |= 0x00400000; /* Set bit 22 */ + reg_ctrl &= ~0x20000000; /* Clear bit 29 */ + + E1000_WRITE_REG(hw, CTRL_EXT, reg_ctrl_ext); + E1000_WRITE_REG(hw, CTRL, reg_ctrl); + break; + case em_80003es2lan: + if ((hw->media_type == em_media_type_fiber) || + (hw->media_type == em_media_type_internal_serdes)) { + reg_tarc0 &= ~0x00100000; /* Clear bit 20 */ + } + + reg_tctl = E1000_READ_REG(hw, TCTL); + reg_tarc1 = E1000_READ_REG(hw, TARC1); + if (reg_tctl & E1000_TCTL_MULR) + reg_tarc1 &= ~0x10000000; /* Clear bit 28 if MULR is 1b */ + else + reg_tarc1 |= 0x10000000; /* Set bit 28 if MULR is 0b */ + + E1000_WRITE_REG(hw, TARC1, reg_tarc1); + break; + case em_ich8lan: + if ((hw->revision_id < 3) || + ((hw->device_id != E1000_DEV_ID_ICH8_IGP_M_AMT) && + (hw->device_id != E1000_DEV_ID_ICH8_IGP_M))) + reg_tarc0 |= 0x30000000; /* Set TARC0 bits 29 and 28 */ + reg_ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); + reg_ctrl_ext |= 0x00400000; /* Set bit 22 */ + E1000_WRITE_REG(hw, CTRL_EXT, reg_ctrl_ext); + + reg_tarc0 |= 0x0d800000; /* Set TARC0 bits 23, 24, 26, 27 */ + + reg_tarc1 = E1000_READ_REG(hw, TARC1); + reg_tctl = E1000_READ_REG(hw, TCTL); + + if (reg_tctl & E1000_TCTL_MULR) + reg_tarc1 &= ~0x10000000; /* Clear bit 28 if MULR is 1b */ + else + reg_tarc1 |= 0x10000000; /* Set bit 28 if MULR is 0b */ + + reg_tarc1 |= 0x45000000; /* Set bit 24, 26 and 30 */ + + E1000_WRITE_REG(hw, TARC1, reg_tarc1); + break; + default: + break; + } + + E1000_WRITE_REG(hw, TARC0, reg_tarc0); + } +} + /****************************************************************************** * Performs basic configuration of the adapter. * @@ -697,17 +853,16 @@ em_init_hw(struct em_hw *hw) DEBUGFUNC("em_init_hw"); - if (hw->mac_type == em_ich8lan) { - reg_data = E1000_READ_REG(hw, TARC0); - reg_data |= 0x30000000; - E1000_WRITE_REG(hw, TARC0, reg_data); - - reg_data = E1000_READ_REG(hw, STATUS); - reg_data &= ~0x80000000; - E1000_WRITE_REG(hw, STATUS, reg_data); + /* force full DMA clock frequency for 10/100 on ICH8 A0-B0 */ + if ((hw->mac_type == em_ich8lan) && + ((hw->revision_id < 3) || + ((hw->device_id != E1000_DEV_ID_ICH8_IGP_M_AMT) && + (hw->device_id != E1000_DEV_ID_ICH8_IGP_M)))) { + reg_data = E1000_READ_REG(hw, STATUS); + reg_data &= ~0x80000000; + E1000_WRITE_REG(hw, STATUS, reg_data); } - /* Initialize Identification LED */ ret_val = em_id_led_init(hw); if (ret_val) { @@ -809,17 +964,6 @@ em_init_hw(struct em_hw *hw) if (hw->mac_type > em_82544) { ctrl = E1000_READ_REG(hw, TXDCTL); ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; - switch (hw->mac_type) { - default: - break; - case em_82571: - case em_82572: - case em_82573: - case em_ich8lan: - case em_80003es2lan: - ctrl |= E1000_TXDCTL_COUNT_DESC; - break; - } E1000_WRITE_REG(hw, TXDCTL, ctrl); } @@ -857,14 +1001,11 @@ em_init_hw(struct em_hw *hw) case em_ich8lan: ctrl = E1000_READ_REG(hw, TXDCTL1); ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; - if (hw->mac_type >= em_82571) - ctrl |= E1000_TXDCTL_COUNT_DESC; E1000_WRITE_REG(hw, TXDCTL1, ctrl); break; } - if (hw->mac_type == em_82573) { uint32_t gcr = E1000_READ_REG(hw, GCR); gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX; @@ -892,6 +1033,9 @@ em_init_hw(struct em_hw *hw) E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); } + /* Must be called after em_set_media_type because media_type is used */ + em_initialize_hardware_bits(hw); + return ret_val; } @@ -968,11 +1112,11 @@ em_setup_link(struct em_hw *hw) * control setting, then the variable hw->fc will * be initialized based on a value in the EEPROM. */ - if (hw->fc == em_fc_default) { + if (hw->fc == E1000_FC_DEFAULT) { switch (hw->mac_type) { case em_ich8lan: case em_82573: - hw->fc = em_fc_full; + hw->fc = E1000_FC_FULL; break; default: ret_val = em_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, @@ -982,12 +1126,12 @@ em_setup_link(struct em_hw *hw) return -E1000_ERR_EEPROM; } if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) - hw->fc = em_fc_none; + hw->fc = E1000_FC_NONE; else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == EEPROM_WORD0F_ASM_DIR) - hw->fc = em_fc_tx_pause; + hw->fc = E1000_FC_TX_PAUSE; else - hw->fc = em_fc_full; + hw->fc = E1000_FC_FULL; break; } } @@ -997,10 +1141,10 @@ em_setup_link(struct em_hw *hw) * hub or switch with different Flow Control capabilities. */ if (hw->mac_type == em_82542_rev2_0) - hw->fc &= (~em_fc_tx_pause); + hw->fc &= (~E1000_FC_TX_PAUSE); if ((hw->mac_type < em_82543) && (hw->report_tx_early == 1)) - hw->fc &= (~em_fc_rx_pause); + hw->fc &= (~E1000_FC_RX_PAUSE); hw->original_fc = hw->fc; @@ -1052,7 +1196,7 @@ em_setup_link(struct em_hw *hw) * ability to transmit pause frames in not enabled, then these * registers will be set to 0. */ - if (!(hw->fc & em_fc_tx_pause)) { + if (!(hw->fc & E1000_FC_TX_PAUSE)) { E1000_WRITE_REG(hw, FCRTL, 0); E1000_WRITE_REG(hw, FCRTH, 0); } else { @@ -1099,11 +1243,11 @@ em_setup_fiber_serdes_link(struct em_hw *hw) if (hw->mac_type == em_82571 || hw->mac_type == em_82572) E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK); - /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be + /* On adapters with a MAC newer than 82544, SWDP 1 will be * set when the optics detect a signal. On older adapters, it will be * cleared when there is a signal. This applies to fiber media only. - * If we're on serdes media, adjust the output amplitude to value set in - * the EEPROM. + * If we're on serdes media, adjust the output amplitude to value + * set in the EEPROM. */ ctrl = E1000_READ_REG(hw, CTRL); if (hw->media_type == em_media_type_fiber) @@ -1139,11 +1283,11 @@ em_setup_fiber_serdes_link(struct em_hw *hw) * 3: Both Rx and TX flow control (symmetric) are enabled. */ switch (hw->fc) { - case em_fc_none: + case E1000_FC_NONE: /* Flow control is completely disabled by a software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); break; - case em_fc_rx_pause: + case E1000_FC_RX_PAUSE: /* RX Flow control is enabled and TX Flow control is disabled by a * software over-ride. Since there really isn't a way to advertise * that we are capable of RX Pause ONLY, we will advertise that we @@ -1152,13 +1296,13 @@ em_setup_fiber_serdes_link(struct em_hw *hw) */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; - case em_fc_tx_pause: + case E1000_FC_TX_PAUSE: /* TX Flow control is enabled, and RX Flow control is disabled, by a * software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); break; - case em_fc_full: + case E1000_FC_FULL: /* Flow control (both RX and TX) is enabled by a software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; @@ -2074,13 +2218,13 @@ em_phy_setup_autoneg(struct em_hw *hw) * in the EEPROM is used. */ switch (hw->fc) { - case em_fc_none: /* 0 */ + case E1000_FC_NONE: /* 0 */ /* Flow control (RX & TX) is completely disabled by a * software over-ride. */ mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; - case em_fc_rx_pause: /* 1 */ + case E1000_FC_RX_PAUSE: /* 1 */ /* RX Flow control is enabled, and TX Flow control is * disabled, by a software over-ride. */ @@ -2092,14 +2236,14 @@ em_phy_setup_autoneg(struct em_hw *hw) */ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; - case em_fc_tx_pause: /* 2 */ + case E1000_FC_TX_PAUSE: /* 2 */ /* TX Flow control is enabled, and RX Flow control is * disabled, by a software over-ride. */ mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; break; - case em_fc_full: /* 3 */ + case E1000_FC_FULL: /* 3 */ /* Flow control (both RX and TX) is enabled by a software * over-ride. */ @@ -2143,7 +2287,7 @@ em_phy_force_speed_duplex(struct em_hw *hw) DEBUGFUNC("em_phy_force_speed_duplex"); /* Turn off Flow control if we are forcing speed and duplex. */ - hw->fc = em_fc_none; + hw->fc = E1000_FC_NONE; DEBUGOUT1("hw->fc = %d\n", hw->fc); @@ -2223,6 +2367,7 @@ em_phy_force_speed_duplex(struct em_hw *hw) /* Need to reset the PHY or these changes will be ignored */ mii_ctrl_reg |= MII_CR_RESET; + /* Disable MDI-X support for 10/100 */ } else if (hw->phy_type == em_phy_ife) { ret_val = em_read_phy_reg(hw, IFE_PHY_MDIX_CONTROL, &phy_data); @@ -2235,6 +2380,7 @@ em_phy_force_speed_duplex(struct em_hw *hw) ret_val = em_write_phy_reg(hw, IFE_PHY_MDIX_CONTROL, phy_data); if (ret_val) return ret_val; + } else { /* Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed or duplex are forced. @@ -2497,18 +2643,18 @@ em_force_mac_fc(struct em_hw *hw) */ switch (hw->fc) { - case em_fc_none: + case E1000_FC_NONE: ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); break; - case em_fc_rx_pause: + case E1000_FC_RX_PAUSE: ctrl &= (~E1000_CTRL_TFCE); ctrl |= E1000_CTRL_RFCE; break; - case em_fc_tx_pause: + case E1000_FC_TX_PAUSE: ctrl &= (~E1000_CTRL_RFCE); ctrl |= E1000_CTRL_TFCE; break; - case em_fc_full: + case E1000_FC_FULL: ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); break; default: @@ -2535,7 +2681,7 @@ em_force_mac_fc(struct em_hw *hw) * based on the flow control negotiated by the PHY. In TBI mode, the TFCE * and RFCE bits will be automaticaly set to the negotiated flow control mode. *****************************************************************************/ -int32_t +STATIC int32_t em_config_fc_after_link_up(struct em_hw *hw) { int32_t ret_val; @@ -2637,11 +2783,11 @@ em_config_fc_after_link_up(struct em_hw *hw) * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ - if (hw->original_fc == em_fc_full) { - hw->fc = em_fc_full; + if (hw->original_fc == E1000_FC_FULL) { + hw->fc = E1000_FC_FULL; DEBUGOUT("Flow Control = FULL.\n"); } else { - hw->fc = em_fc_rx_pause; + hw->fc = E1000_FC_RX_PAUSE; DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } } @@ -2657,7 +2803,7 @@ em_config_fc_after_link_up(struct em_hw *hw) (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc = em_fc_tx_pause; + hw->fc = E1000_FC_TX_PAUSE; DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); } /* For transmitting PAUSE frames ONLY. @@ -2672,7 +2818,7 @@ em_config_fc_after_link_up(struct em_hw *hw) (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc = em_fc_rx_pause; + hw->fc = E1000_FC_RX_PAUSE; DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } /* Per the IEEE spec, at this point flow control should be @@ -2695,13 +2841,13 @@ em_config_fc_after_link_up(struct em_hw *hw) * be asked to delay transmission of packets than asking * our link partner to pause transmission of frames. */ - else if ((hw->original_fc == em_fc_none || - hw->original_fc == em_fc_tx_pause) || + else if ((hw->original_fc == E1000_FC_NONE|| + hw->original_fc == E1000_FC_TX_PAUSE) || hw->fc_strict_ieee) { - hw->fc = em_fc_none; + hw->fc = E1000_FC_NONE; DEBUGOUT("Flow Control = NONE.\n"); } else { - hw->fc = em_fc_rx_pause; + hw->fc = E1000_FC_RX_PAUSE; DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } @@ -2716,7 +2862,7 @@ em_config_fc_after_link_up(struct em_hw *hw) } if (duplex == HALF_DUPLEX) - hw->fc = em_fc_none; + hw->fc = E1000_FC_NONE; /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. @@ -3058,7 +3204,7 @@ em_get_speed_and_duplex(struct em_hw *hw, * * hw - Struct containing variables accessed by shared code ******************************************************************************/ -int32_t +STATIC int32_t em_wait_autoneg(struct em_hw *hw) { int32_t ret_val; @@ -3228,7 +3374,7 @@ em_shift_in_mdi_bits(struct em_hw *hw) return data; } -int32_t +STATIC int32_t em_swfw_sync_acquire(struct em_hw *hw, uint16_t mask) { uint32_t swfw_sync = 0; @@ -3272,7 +3418,7 @@ em_swfw_sync_acquire(struct em_hw *hw, uint16_t mask) return E1000_SUCCESS; } -void +STATIC void em_swfw_sync_release(struct em_hw *hw, uint16_t mask) { uint32_t swfw_sync; @@ -3367,9 +3513,8 @@ em_read_phy_reg(struct em_hw *hw, return ret_val; } -int32_t -em_read_phy_reg_ex(struct em_hw *hw, - uint32_t reg_addr, +STATIC int32_t +em_read_phy_reg_ex(struct em_hw *hw, uint32_t reg_addr, uint16_t *phy_data) { uint32_t i; @@ -3449,8 +3594,7 @@ em_read_phy_reg_ex(struct em_hw *hw, * data - data to write to the PHY ******************************************************************************/ int32_t -em_write_phy_reg(struct em_hw *hw, - uint32_t reg_addr, +em_write_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t phy_data) { uint32_t ret_val; @@ -3507,10 +3651,9 @@ em_write_phy_reg(struct em_hw *hw, return ret_val; } -int32_t -em_write_phy_reg_ex(struct em_hw *hw, - uint32_t reg_addr, - uint16_t phy_data) +STATIC int32_t +em_write_phy_reg_ex(struct em_hw *hw, uint32_t reg_addr, + uint16_t phy_data) { uint32_t i; uint32_t mdic = 0; @@ -3570,7 +3713,7 @@ em_write_phy_reg_ex(struct em_hw *hw, return E1000_SUCCESS; } -int32_t +STATIC int32_t em_read_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t *data) @@ -3603,7 +3746,7 @@ em_read_kmrn_reg(struct em_hw *hw, return E1000_SUCCESS; } -int32_t +STATIC int32_t em_write_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t data) @@ -3661,7 +3804,7 @@ em_phy_hw_reset(struct em_hw *hw) swfw = E1000_SWFW_PHY0_SM; } if (em_swfw_sync_acquire(hw, swfw)) { - em_release_software_semaphore(hw); + DEBUGOUT("Unable to acquire swfw sync\n"); return -E1000_ERR_SWFW_SYNC; } /* Read the device control register and assert the E1000_CTRL_PHY_RST @@ -3684,6 +3827,7 @@ em_phy_hw_reset(struct em_hw *hw) if (hw->mac_type >= em_82571) msec_delay_irq(10); + em_swfw_sync_release(hw, swfw); } else { /* Read the Extended Device Control Register, assert the PHY_RESET_DIR @@ -3742,15 +3886,14 @@ em_phy_reset(struct em_hw *hw) if (ret_val) return E1000_SUCCESS; - switch (hw->mac_type) { - case em_82541_rev_2: - case em_82571: - case em_82572: - case em_ich8lan: + switch (hw->phy_type) { + case em_phy_igp: + case em_phy_igp_2: + case em_phy_igp_3: + case em_phy_ife: ret_val = em_phy_hw_reset(hw); if (ret_val) return ret_val; - break; default: ret_val = em_read_phy_reg(hw, PHY_CTRL, &phy_data); @@ -3799,14 +3942,15 @@ em_phy_powerdown_workaround(struct em_hw *hw) E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE | E1000_PHY_CTRL_NOND0A_GBE_DISABLE); - /* Write VR power-down enable */ + /* Write VR power-down enable - bits 9:8 should be 10b */ em_read_phy_reg(hw, IGP3_VR_CTRL, &phy_data); - em_write_phy_reg(hw, IGP3_VR_CTRL, phy_data | - IGP3_VR_CTRL_MODE_SHUT); + phy_data |= (1 << 9); + phy_data &= ~(1 << 8); + em_write_phy_reg(hw, IGP3_VR_CTRL, phy_data); /* Read it back and test */ em_read_phy_reg(hw, IGP3_VR_CTRL, &phy_data); - if ((phy_data & IGP3_VR_CTRL_MODE_SHUT) || retry) + if (((phy_data & IGP3_VR_CTRL_MODE_MASK) == IGP3_VR_CTRL_MODE_SHUT) || retry) break; /* Issue PHY reset and repeat at most one more time */ @@ -3833,7 +3977,7 @@ em_phy_powerdown_workaround(struct em_hw *hw) * * hw - struct containing variables accessed by shared code ******************************************************************************/ -int32_t +STATIC int32_t em_kumeran_lock_loss_workaround(struct em_hw *hw) { int32_t ret_val; @@ -3886,7 +4030,7 @@ em_kumeran_lock_loss_workaround(struct em_hw *hw) * * hw - Struct containing variables accessed by shared code ******************************************************************************/ -int32_t +STATIC int32_t em_detect_gig_phy(struct em_hw *hw) { int32_t phy_init_status, ret_val; @@ -3895,6 +4039,9 @@ em_detect_gig_phy(struct em_hw *hw) DEBUGFUNC("em_detect_gig_phy"); + if (hw->phy_id != 0) + return E1000_SUCCESS; + /* The 82571 firmware may still be configuring the PHY. In this * case, we cannot access the PHY until the configuration is done. So * we explicitly set the PHY values. */ @@ -4006,12 +4153,13 @@ em_phy_reset_dsp(struct em_hw *hw) * hw - Struct containing variables accessed by shared code * phy_info - PHY information structure ******************************************************************************/ -int32_t +STATIC int32_t em_phy_igp_get_info(struct em_hw *hw, struct em_phy_info *phy_info) { int32_t ret_val; - uint16_t phy_data, polarity, min_length, max_length, average; + uint16_t phy_data, min_length, max_length, average; + em_rev_polarity polarity; DEBUGFUNC("em_phy_igp_get_info"); @@ -4036,8 +4184,8 @@ em_phy_igp_get_info(struct em_hw *hw, if (ret_val) return ret_val; - phy_info->mdix_mode = (phy_data & IGP01E1000_PSSR_MDIX) >> - IGP01E1000_PSSR_MDIX_SHIFT; + phy_info->mdix_mode = (em_auto_x_mode)((phy_data & IGP01E1000_PSSR_MDIX) >> + IGP01E1000_PSSR_MDIX_SHIFT); if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { @@ -4046,10 +4194,12 @@ em_phy_igp_get_info(struct em_hw *hw, if (ret_val) return ret_val; - phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> - SR_1000T_LOCAL_RX_STATUS_SHIFT; - phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) >> - SR_1000T_REMOTE_RX_STATUS_SHIFT; + phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >> + SR_1000T_LOCAL_RX_STATUS_SHIFT) ? + em_1000t_rx_status_ok : em_1000t_rx_status_not_ok; + phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >> + SR_1000T_REMOTE_RX_STATUS_SHIFT) ? + em_1000t_rx_status_ok : em_1000t_rx_status_not_ok; /* Get cable length */ ret_val = em_get_cable_length(hw, &min_length, &max_length); @@ -4080,12 +4230,13 @@ em_phy_igp_get_info(struct em_hw *hw, * hw - Struct containing variables accessed by shared code * phy_info - PHY information structure ******************************************************************************/ -int32_t +STATIC int32_t em_phy_ife_get_info(struct em_hw *hw, struct em_phy_info *phy_info) { int32_t ret_val; - uint16_t phy_data, polarity; + uint16_t phy_data; + em_rev_polarity polarity; DEBUGFUNC("em_phy_ife_get_info"); @@ -4096,8 +4247,9 @@ em_phy_ife_get_info(struct em_hw *hw, if (ret_val) return ret_val; phy_info->polarity_correction = - (phy_data & IFE_PSC_AUTO_POLARITY_DISABLE) >> - IFE_PSC_AUTO_POLARITY_DISABLE_SHIFT; + ((phy_data & IFE_PSC_AUTO_POLARITY_DISABLE) >> + IFE_PSC_AUTO_POLARITY_DISABLE_SHIFT) ? + em_polarity_reversal_disabled : em_polarity_reversal_enabled; if (phy_info->polarity_correction == em_polarity_reversal_enabled) { ret_val = em_check_polarity(hw, &polarity); @@ -4105,8 +4257,9 @@ em_phy_ife_get_info(struct em_hw *hw, return ret_val; } else { /* Polarity is forced. */ - polarity = (phy_data & IFE_PSC_FORCE_POLARITY) >> - IFE_PSC_FORCE_POLARITY_SHIFT; + polarity = ((phy_data & IFE_PSC_FORCE_POLARITY) >> + IFE_PSC_FORCE_POLARITY_SHIFT) ? + em_rev_polarity_reversed : em_rev_polarity_normal; } phy_info->cable_polarity = polarity; @@ -4114,9 +4267,9 @@ em_phy_ife_get_info(struct em_hw *hw, if (ret_val) return ret_val; - phy_info->mdix_mode = - (phy_data & (IFE_PMC_AUTO_MDIX | IFE_PMC_FORCE_MDIX)) >> - IFE_PMC_MDIX_MODE_SHIFT; + phy_info->mdix_mode = (em_auto_x_mode) + ((phy_data & (IFE_PMC_AUTO_MDIX | IFE_PMC_FORCE_MDIX)) >> + IFE_PMC_MDIX_MODE_SHIFT); return E1000_SUCCESS; } @@ -4127,12 +4280,13 @@ em_phy_ife_get_info(struct em_hw *hw, * hw - Struct containing variables accessed by shared code * phy_info - PHY information structure ******************************************************************************/ -int32_t +STATIC int32_t em_phy_m88_get_info(struct em_hw *hw, struct em_phy_info *phy_info) { int32_t ret_val; - uint16_t phy_data, polarity; + uint16_t phy_data; + em_rev_polarity polarity; DEBUGFUNC("em_phy_m88_get_info"); @@ -4145,11 +4299,14 @@ em_phy_m88_get_info(struct em_hw *hw, return ret_val; phy_info->extended_10bt_distance = - (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >> - M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT; + ((phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >> + M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT) ? + em_10bt_ext_dist_enable_lower : em_10bt_ext_dist_enable_normal; + phy_info->polarity_correction = - (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >> - M88E1000_PSCR_POLARITY_REVERSAL_SHIFT; + ((phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >> + M88E1000_PSCR_POLARITY_REVERSAL_SHIFT) ? + em_polarity_reversal_disabled : em_polarity_reversal_enabled; /* Check polarity status */ ret_val = em_check_polarity(hw, &polarity); @@ -4161,15 +4318,15 @@ em_phy_m88_get_info(struct em_hw *hw, if (ret_val) return ret_val; - phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >> - M88E1000_PSSR_MDIX_SHIFT; + phy_info->mdix_mode = (em_auto_x_mode)((phy_data & M88E1000_PSSR_MDIX) >> + M88E1000_PSSR_MDIX_SHIFT); if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { /* Cable Length Estimation and Local/Remote Receiver Information * are only valid at 1000 Mbps. */ if (hw->phy_type != em_phy_gg82563) { - phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> + phy_info->cable_length = (em_cable_length)((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> M88E1000_PSSR_CABLE_LENGTH_SHIFT); } else { ret_val = em_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE, @@ -4177,18 +4334,20 @@ em_phy_m88_get_info(struct em_hw *hw, if (ret_val) return ret_val; - phy_info->cable_length = phy_data & GG82563_DSPD_CABLE_LENGTH; + phy_info->cable_length = (em_cable_length)(phy_data & GG82563_DSPD_CABLE_LENGTH); } ret_val = em_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); if (ret_val) return ret_val; - phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> - SR_1000T_LOCAL_RX_STATUS_SHIFT; + phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >> + SR_1000T_LOCAL_RX_STATUS_SHIFT) ? + em_1000t_rx_status_ok : em_1000t_rx_status_not_ok; + phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >> + SR_1000T_REMOTE_RX_STATUS_SHIFT) ? + em_1000t_rx_status_ok : em_1000t_rx_status_not_ok; - phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) >> - SR_1000T_REMOTE_RX_STATUS_SHIFT; } return E1000_SUCCESS; @@ -4391,9 +4550,9 @@ em_init_eeprom_params(struct em_hw *hw) eeprom->use_eewr = FALSE; break; case em_ich8lan: - { + { int32_t i = 0; - uint32_t flash_size = E1000_READ_ICH8_REG(hw, ICH8_FLASH_GFPREG); + uint32_t flash_size = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_GFPREG); eeprom->type = em_eeprom_ich8; eeprom->use_eerd = FALSE; @@ -4409,16 +4568,18 @@ em_init_eeprom_params(struct em_hw *hw) } } - hw->flash_base_addr = (flash_size & ICH8_GFPREG_BASE_MASK) * - ICH8_FLASH_SECTOR_SIZE; + hw->flash_base_addr = (flash_size & ICH_GFPREG_BASE_MASK) * + ICH_FLASH_SECTOR_SIZE; + + hw->flash_bank_size = ((flash_size >> 16) & ICH_GFPREG_BASE_MASK) + 1; + hw->flash_bank_size -= (flash_size & ICH_GFPREG_BASE_MASK); + + hw->flash_bank_size *= ICH_FLASH_SECTOR_SIZE; - hw->flash_bank_size = ((flash_size >> 16) & ICH8_GFPREG_BASE_MASK) + 1; - hw->flash_bank_size -= (flash_size & ICH8_GFPREG_BASE_MASK); - hw->flash_bank_size *= ICH8_FLASH_SECTOR_SIZE; hw->flash_bank_size /= 2 * sizeof(uint16_t); break; - } + } default: break; } @@ -4750,7 +4911,7 @@ em_release_eeprom(struct em_hw *hw) * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -int32_t +STATIC int32_t em_spi_eeprom_ready(struct em_hw *hw) { uint16_t retry_count = 0; @@ -4804,44 +4965,43 @@ em_read_eeprom(struct em_hw *hw, { struct em_eeprom_info *eeprom = &hw->eeprom; uint32_t i = 0; - int32_t ret_val; DEBUGFUNC("em_read_eeprom"); + /* If eeprom is not yet detected, do so now */ + if (eeprom->word_size == 0) + em_init_eeprom_params(hw); + /* A check for invalid values: offset too large, too many words, and not * enough words. */ if ((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) || (words == 0)) { - DEBUGOUT("\"words\" parameter out of bounds\n"); + DEBUGOUT2("\"words\" parameter out of bounds. Words = %d, size = %d\n", offset, eeprom->word_size); return -E1000_ERR_EEPROM; } - /* FLASH reads without acquiring the semaphore are safe */ + /* EEPROM's that don't use EERD to read require us to bit-bang the SPI + * directly. In this case, we need to acquire the EEPROM so that + * FW or other port software does not interrupt. + */ if (em_is_onboard_nvm_eeprom(hw) == TRUE && hw->eeprom.use_eerd == FALSE) { - switch (hw->mac_type) { - case em_80003es2lan: - break; - default: - /* Prepare the EEPROM for reading */ - if (em_acquire_eeprom(hw) != E1000_SUCCESS) - return -E1000_ERR_EEPROM; - break; - } + /* Prepare the EEPROM for bit-bang reading */ + if (em_acquire_eeprom(hw) != E1000_SUCCESS) + return -E1000_ERR_EEPROM; } - if (eeprom->use_eerd == TRUE) { - ret_val = em_read_eeprom_eerd(hw, offset, words, data); - if ((em_is_onboard_nvm_eeprom(hw) == TRUE) || - (hw->mac_type != em_82573)) - em_release_eeprom(hw); - return ret_val; - } + /* Eerd register EEPROM access requires no eeprom aquire/release */ + if (eeprom->use_eerd == TRUE) + return em_read_eeprom_eerd(hw, offset, words, data); + /* ICH EEPROM access is done via the ICH flash controller */ if (eeprom->type == em_eeprom_ich8) return em_read_eeprom_ich8(hw, offset, words, data); + /* Set up the SPI or Microwire EEPROM for bit-bang reading. We have + * acquired the EEPROM at this point, so any returns should relase it */ if (eeprom->type == em_eeprom_spi) { uint16_t word_in; uint8_t read_opcode = EEPROM_READ_OPCODE_SPI; @@ -4899,7 +5059,7 @@ em_read_eeprom(struct em_hw *hw, * data - word read from the EEPROM * words - number of words to read *****************************************************************************/ -int32_t +STATIC int32_t em_read_eeprom_eerd(struct em_hw *hw, uint16_t offset, uint16_t words, @@ -4933,7 +5093,7 @@ em_read_eeprom_eerd(struct em_hw *hw, * data - word read from the EEPROM * words - number of words to read *****************************************************************************/ -int32_t +STATIC int32_t em_write_eeprom_eewr(struct em_hw *hw, uint16_t offset, uint16_t words, @@ -4974,7 +5134,7 @@ em_write_eeprom_eewr(struct em_hw *hw, * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -int32_t +STATIC int32_t em_poll_eerd_eewr_done(struct em_hw *hw, int eerd) { uint32_t attempts = 100000; @@ -5002,7 +5162,7 @@ em_poll_eerd_eewr_done(struct em_hw *hw, int eerd) * * hw - Struct containing variables accessed by shared code ****************************************************************************/ -boolean_t +STATIC boolean_t em_is_onboard_nvm_eeprom(struct em_hw *hw) { uint32_t eecd = 0; @@ -5156,6 +5316,10 @@ em_write_eeprom(struct em_hw *hw, DEBUGFUNC("em_write_eeprom"); + /* If eeprom is not yet detected, do so now */ + if (eeprom->word_size == 0) + em_init_eeprom_params(hw); + /* A check for invalid values: offset too large, too many words, and not * enough words. */ @@ -5198,7 +5362,7 @@ em_write_eeprom(struct em_hw *hw, * data - pointer to array of 8 bit words to be written to the EEPROM * *****************************************************************************/ -int32_t +STATIC int32_t em_write_eeprom_spi(struct em_hw *hw, uint16_t offset, uint16_t words, @@ -5264,7 +5428,7 @@ em_write_eeprom_spi(struct em_hw *hw, * data - pointer to array of 16 bit words to be written to the EEPROM * *****************************************************************************/ -int32_t +STATIC int32_t em_write_eeprom_microwire(struct em_hw *hw, uint16_t offset, uint16_t words, @@ -5351,7 +5515,7 @@ em_write_eeprom_microwire(struct em_hw *hw, * data - word read from the EEPROM * words - number of words to read *****************************************************************************/ -int32_t +STATIC int32_t em_commit_shadow_ram(struct em_hw *hw) { uint32_t attempts = 100000; @@ -5361,10 +5525,8 @@ em_commit_shadow_ram(struct em_hw *hw) int32_t error = E1000_SUCCESS; uint32_t old_bank_offset = 0; uint32_t new_bank_offset = 0; - uint32_t sector_retries = 0; uint8_t low_byte = 0; uint8_t high_byte = 0; - uint8_t temp_byte = 0; boolean_t sector_write_failed = FALSE; if (hw->mac_type == em_82573) { @@ -5417,90 +5579,95 @@ em_commit_shadow_ram(struct em_hw *hw) em_erase_ich8_4k_segment(hw, 0); } - do { - sector_write_failed = FALSE; - /* Loop for every byte in the shadow RAM, - * which is in units of words. */ - for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { - /* Determine whether to write the value stored - * in the other NVM bank or a modified value stored - * in the shadow RAM */ - if (hw->eeprom_shadow_ram[i].modified == TRUE) { - low_byte = (uint8_t)hw->eeprom_shadow_ram[i].eeprom_word; - em_read_ich8_byte(hw, (i << 1) + old_bank_offset, - &temp_byte); - usec_delay(100); - error = em_verify_write_ich8_byte(hw, - (i << 1) + new_bank_offset, - low_byte); - if (error != E1000_SUCCESS) - sector_write_failed = TRUE; + sector_write_failed = FALSE; + /* Loop for every byte in the shadow RAM, + * which is in units of words. */ + for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { + /* Determine whether to write the value stored + * in the other NVM bank or a modified value stored + * in the shadow RAM */ + if (hw->eeprom_shadow_ram[i].modified == TRUE) { + low_byte = (uint8_t)hw->eeprom_shadow_ram[i].eeprom_word; + usec_delay(100); + error = em_verify_write_ich8_byte(hw, + (i << 1) + new_bank_offset, low_byte); + + if (error != E1000_SUCCESS) + sector_write_failed = TRUE; + else { high_byte = (uint8_t)(hw->eeprom_shadow_ram[i].eeprom_word >> 8); - em_read_ich8_byte(hw, (i << 1) + old_bank_offset + 1, - &temp_byte); usec_delay(100); - } else { - em_read_ich8_byte(hw, (i << 1) + old_bank_offset, - &low_byte); - usec_delay(100); - error = em_verify_write_ich8_byte(hw, - (i << 1) + new_bank_offset, low_byte); - if (error != E1000_SUCCESS) - sector_write_failed = TRUE; + } + } else { + em_read_ich8_byte(hw, (i << 1) + old_bank_offset, + &low_byte); + usec_delay(100); + error = em_verify_write_ich8_byte(hw, + (i << 1) + new_bank_offset, low_byte); + + if (error != E1000_SUCCESS) + sector_write_failed = TRUE; + else { em_read_ich8_byte(hw, (i << 1) + old_bank_offset + 1, &high_byte); + usec_delay(100); } + } + /* If the write of the low byte was successful, go ahread and + * write the high byte while checking to make sure that if it + * is the signature byte, then it is handled properly */ + if (sector_write_failed == FALSE) { /* If the word is 0x13, then make sure the signature bits * (15:14) are 11b until the commit has completed. * This will allow us to write 10b which indicates the * signature is valid. We want to do this after the write * has completed so that we don't mark the segment valid * while the write is still in progress */ - if (i == E1000_ICH8_NVM_SIG_WORD) - high_byte = E1000_ICH8_NVM_SIG_MASK | high_byte; + if (i == E1000_ICH_NVM_SIG_WORD) + high_byte = E1000_ICH_NVM_SIG_MASK | high_byte; error = em_verify_write_ich8_byte(hw, - (i << 1) + new_bank_offset + 1, high_byte); + (i << 1) + new_bank_offset + 1, high_byte); if (error != E1000_SUCCESS) sector_write_failed = TRUE; - if (sector_write_failed == FALSE) { - /* Clear the now not used entry in the cache */ - hw->eeprom_shadow_ram[i].modified = FALSE; - hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF; - } + } else { + /* If the write failed then break from the loop and + * return an error */ + break; } + } - /* Don't bother writing the segment valid bits if sector - * programming failed. */ - if (sector_write_failed == FALSE) { - /* Finally validate the new segment by setting bit 15:14 - * to 10b in word 0x13 , this can be done without an - * erase as well since these bits are 11 to start with - * and we need to change bit 14 to 0b */ - em_read_ich8_byte(hw, - E1000_ICH8_NVM_SIG_WORD * 2 + 1 + new_bank_offset, - &high_byte); - high_byte &= 0xBF; + /* Don't bother writing the segment valid bits if sector + * programming failed. */ + if (sector_write_failed == FALSE) { + /* Finally validate the new segment by setting bit 15:14 + * to 10b in word 0x13 , this can be done without an + * erase as well since these bits are 11 to start with + * and we need to change bit 14 to 0b */ + em_read_ich8_byte(hw, + E1000_ICH_NVM_SIG_WORD * 2 + 1 + new_bank_offset, + &high_byte); + high_byte &= 0xBF; + error = em_verify_write_ich8_byte(hw, + E1000_ICH_NVM_SIG_WORD * 2 + 1 + new_bank_offset, high_byte); + /* And invalidate the previously valid segment by setting + * its signature word (0x13) high_byte to 0b. This can be + * done without an erase because flash erase sets all bits + * to 1's. We can write 1's to 0's without an erase */ + if (error == E1000_SUCCESS) { error = em_verify_write_ich8_byte(hw, - E1000_ICH8_NVM_SIG_WORD * 2 + 1 + new_bank_offset, - high_byte); - if (error != E1000_SUCCESS) - sector_write_failed = TRUE; + E1000_ICH_NVM_SIG_WORD * 2 + 1 + old_bank_offset, 0); + } - /* And invalidate the previously valid segment by setting - * its signature word (0x13) high_byte to 0b. This can be - * done without an erase because flash erase sets all bits - * to 1's. We can write 1's to 0's without an erase */ - error = em_verify_write_ich8_byte(hw, - E1000_ICH8_NVM_SIG_WORD * 2 + 1 + old_bank_offset, - 0); - if (error != E1000_SUCCESS) - sector_write_failed = TRUE; + /* Clear the now not used entry in the cache */ + for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { + hw->eeprom_shadow_ram[i].modified = FALSE; + hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF; } - } while (++sector_retries < 10 && sector_write_failed == TRUE); + } } return error; @@ -5590,7 +5757,7 @@ em_read_mac_addr(struct em_hw * hw) * of the receive addresss registers. Clears the multicast table. Assumes * the receiver is in reset when the routine is called. *****************************************************************************/ -void +STATIC void em_init_rx_addrs(struct em_hw *hw) { uint32_t i; @@ -5659,6 +5826,7 @@ em_mc_addr_list_update(struct em_hw *hw, num_rar_entry = E1000_RAR_ENTRIES; if (hw->mac_type == em_ich8lan) num_rar_entry = E1000_RAR_ENTRIES_ICH8LAN; + /* Reserve a spot for the Locally Administered Address to work around * an 82571 issue in which a reset on one port will reload the MAC on * the other port. */ @@ -5677,6 +5845,7 @@ em_mc_addr_list_update(struct em_hw *hw, num_mta_entry = E1000_NUM_MTA_REGISTERS; if (hw->mac_type == em_ich8lan) num_mta_entry = E1000_NUM_MTA_REGISTERS_ICH8LAN; + for (i = 0; i < num_mta_entry; i++) { E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); E1000_WRITE_FLUSH(hw); @@ -5804,6 +5973,7 @@ em_mta_set(struct em_hw *hw, hash_reg = (hash_value >> 5) & 0x7F; if (hw->mac_type == em_ich8lan) hash_reg &= 0x1F; + hash_bit = hash_value & 0x1F; mta = E1000_READ_REG_ARRAY(hw, MTA, hash_reg); @@ -5918,7 +6088,7 @@ em_write_vfta(struct em_hw *hw, * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -void +STATIC void em_clear_vfta(struct em_hw *hw) { uint32_t offset; @@ -5952,7 +6122,7 @@ em_clear_vfta(struct em_hw *hw) } } -int32_t +STATIC int32_t em_id_led_init(struct em_hw * hw) { uint32_t ledctl; @@ -5989,6 +6159,7 @@ em_id_led_init(struct em_hw * hw) else eeprom_data = ID_LED_DEFAULT; } + for (i = 0; i < 4; i++) { temp = (eeprom_data >> (i << 2)) & led_mask; switch (temp) { @@ -6364,6 +6535,7 @@ em_clear_hw_cntrs(struct em_hw *hw) temp = E1000_READ_REG(hw, ICTXQEC); temp = E1000_READ_REG(hw, ICTXQMTC); temp = E1000_READ_REG(hw, ICRXDMTC); + } /****************************************************************************** @@ -6521,6 +6693,8 @@ em_tbi_adjust_stats(struct em_hw *hw, void em_get_bus_info(struct em_hw *hw) { + int32_t ret_val; + uint16_t pci_ex_link_status; uint32_t status; switch (hw->mac_type) { @@ -6530,18 +6704,25 @@ em_get_bus_info(struct em_hw *hw) hw->bus_speed = em_bus_speed_unknown; hw->bus_width = em_bus_width_unknown; break; + case em_82571: case em_82572: case em_82573: + case em_80003es2lan: hw->bus_type = em_bus_type_pci_express; hw->bus_speed = em_bus_speed_2500; - hw->bus_width = em_bus_width_pciex_1; + ret_val = em_read_pcie_cap_reg(hw, + PCI_EX_LINK_STATUS, + &pci_ex_link_status); + if (ret_val) + hw->bus_width = em_bus_width_unknown; + else + hw->bus_width = (pci_ex_link_status & PCI_EX_LINK_WIDTH_MASK) >> + PCI_EX_LINK_WIDTH_SHIFT; break; - case em_82571: case em_ich8lan: - case em_80003es2lan: hw->bus_type = em_bus_type_pci_express; hw->bus_speed = em_bus_speed_2500; - hw->bus_width = em_bus_width_pciex_4; + hw->bus_width = em_bus_width_pciex_1; break; default: status = E1000_READ_REG(hw, STATUS); @@ -6576,6 +6757,26 @@ em_get_bus_info(struct em_hw *hw) } } +/****************************************************************************** + * 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 + *****************************************************************************/ +STATIC void +em_write_reg_io(struct em_hw *hw, + uint32_t offset, + uint32_t value) +{ + unsigned long io_addr = hw->io_base; + unsigned long io_data = hw->io_base + 4; + + em_io_write(hw, io_addr, offset); + em_io_write(hw, io_data, value); +} + /****************************************************************************** * Estimates the cable length. * @@ -6591,7 +6792,7 @@ em_get_bus_info(struct em_hw *hw) * register to the minimum and maximum range. * For IGP phy's, the function calculates the range by the AGC registers. *****************************************************************************/ -int32_t +STATIC int32_t em_get_cable_length(struct em_hw *hw, uint16_t *min_length, uint16_t *max_length) @@ -6782,9 +6983,9 @@ em_get_cable_length(struct em_hw *hw, * return 0. If the link speed is 1000 Mbps the polarity status is in the * IGP01E1000_PHY_PCS_INIT_REG. *****************************************************************************/ -int32_t +STATIC int32_t em_check_polarity(struct em_hw *hw, - uint16_t *polarity) + em_rev_polarity *polarity) { int32_t ret_val; uint16_t phy_data; @@ -6798,8 +6999,10 @@ em_check_polarity(struct em_hw *hw, &phy_data); if (ret_val) return ret_val; - *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >> - M88E1000_PSSR_REV_POLARITY_SHIFT; + *polarity = ((phy_data & M88E1000_PSSR_REV_POLARITY) >> + M88E1000_PSSR_REV_POLARITY_SHIFT) ? + em_rev_polarity_reversed : em_rev_polarity_normal; + } else if (hw->phy_type == em_phy_igp || hw->phy_type == em_phy_igp_3 || hw->phy_type == em_phy_igp_2) { @@ -6821,19 +7024,22 @@ em_check_polarity(struct em_hw *hw, return ret_val; /* Check the polarity bits */ - *polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ? 1 : 0; + *polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ? + em_rev_polarity_reversed : em_rev_polarity_normal; } else { /* For 10 Mbps, read the polarity bit in the status register. (for * 100 Mbps this bit is always 0) */ - *polarity = phy_data & IGP01E1000_PSSR_POLARITY_REVERSED; + *polarity = (phy_data & IGP01E1000_PSSR_POLARITY_REVERSED) ? + em_rev_polarity_reversed : em_rev_polarity_normal; } } else if (hw->phy_type == em_phy_ife) { ret_val = em_read_phy_reg(hw, IFE_PHY_EXTENDED_STATUS_CONTROL, &phy_data); if (ret_val) return ret_val; - *polarity = (phy_data & IFE_PESC_POLARITY_REVERSED) >> - IFE_PESC_POLARITY_REVERSED_SHIFT; + *polarity = ((phy_data & IFE_PESC_POLARITY_REVERSED) >> + IFE_PESC_POLARITY_REVERSED_SHIFT) ? + em_rev_polarity_reversed : em_rev_polarity_normal; } return E1000_SUCCESS; } @@ -6853,7 +7059,7 @@ em_check_polarity(struct em_hw *hw, * Link Health register. In IGP this bit is latched high, so the driver must * read it immediately after link is established. *****************************************************************************/ -int32_t +STATIC int32_t em_check_downshift(struct em_hw *hw) { int32_t ret_val; @@ -6899,7 +7105,7 @@ em_check_downshift(struct em_hw *hw) * ****************************************************************************/ -int32_t +STATIC int32_t em_config_dsp_after_link_change(struct em_hw *hw, boolean_t link_up) { @@ -7132,7 +7338,7 @@ em_set_phy_mode(struct em_hw *hw) * ****************************************************************************/ -int32_t +STATIC int32_t em_set_d3_lplu_state(struct em_hw *hw, boolean_t active) { @@ -7201,7 +7407,7 @@ em_set_d3_lplu_state(struct em_hw *hw, } else if (hw->smart_speed == em_smart_speed_off) { ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data); - if (ret_val) + if (ret_val) return ret_val; phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; @@ -7262,7 +7468,7 @@ em_set_d3_lplu_state(struct em_hw *hw, * ****************************************************************************/ -int32_t +STATIC int32_t em_set_d0_lplu_state(struct em_hw *hw, boolean_t active) { @@ -7311,7 +7517,7 @@ em_set_d0_lplu_state(struct em_hw *hw, } else if (hw->smart_speed == em_smart_speed_off) { ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data); - if (ret_val) + if (ret_val) return ret_val; phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; @@ -7417,7 +7623,7 @@ em_set_vco_speed(struct em_hw *hw) * * returns: - E1000_SUCCESS . ****************************************************************************/ -int32_t +STATIC int32_t em_host_if_read_cookie(struct em_hw * hw, uint8_t *buffer) { uint8_t i; @@ -7444,7 +7650,7 @@ em_host_if_read_cookie(struct em_hw * hw, uint8_t *buffer) * timeout * - E1000_SUCCESS for success. ****************************************************************************/ -int32_t +STATIC int32_t em_mng_enable_host_if(struct em_hw * hw) { uint32_t hicr; @@ -7478,7 +7684,7 @@ em_mng_enable_host_if(struct em_hw * hw) * * returns - E1000_SUCCESS for success. ****************************************************************************/ -int32_t +STATIC int32_t em_mng_host_if_write(struct em_hw * hw, uint8_t *buffer, uint16_t length, uint16_t offset, uint8_t *sum) { @@ -7546,7 +7752,7 @@ em_mng_host_if_write(struct em_hw * hw, uint8_t *buffer, * * returns - E1000_SUCCESS for success. ****************************************************************************/ -int32_t +STATIC int32_t em_mng_write_cmd_header(struct em_hw * hw, struct em_host_mng_command_header * hdr) { @@ -7586,7 +7792,7 @@ em_mng_write_cmd_header(struct em_hw * hw, * * returns - E1000_SUCCESS for success. ****************************************************************************/ -int32_t +STATIC int32_t em_mng_write_commit(struct em_hw * hw) { uint32_t hicr; @@ -7628,7 +7834,7 @@ em_check_mng_mode(struct em_hw *hw) ****************************************************************************/ int32_t em_mng_write_dhcp_info(struct em_hw * hw, uint8_t *buffer, - uint16_t length) + uint16_t length) { int32_t ret_val; struct em_host_mng_command_header hdr; @@ -7658,7 +7864,7 @@ em_mng_write_dhcp_info(struct em_hw * hw, uint8_t *buffer, * * returns - checksum of buffer contents. ****************************************************************************/ -uint8_t +STATIC uint8_t em_calculate_mng_checksum(char *buffer, uint32_t length) { uint8_t sum = 0; @@ -7841,7 +8047,7 @@ em_polarity_reversal_workaround(struct em_hw *hw) * returns: - none. * ***************************************************************************/ -void +STATIC void em_set_pci_express_master_disable(struct em_hw *hw) { uint32_t ctrl; @@ -7856,30 +8062,6 @@ em_set_pci_express_master_disable(struct em_hw *hw) E1000_WRITE_REG(hw, CTRL, ctrl); } -/*************************************************************************** - * - * Enables PCI-Express master access. - * - * hw: Struct containing variables accessed by shared code - * - * returns: - none. - * - ***************************************************************************/ -void -em_enable_pciex_master(struct em_hw *hw) -{ - uint32_t ctrl; - - DEBUGFUNC("em_enable_pciex_master"); - - if (hw->bus_type != em_bus_type_pci_express) - return; - - ctrl = E1000_READ_REG(hw, CTRL); - ctrl &= ~E1000_CTRL_GIO_MASTER_DISABLE; - E1000_WRITE_REG(hw, CTRL, ctrl); -} - /******************************************************************************* * * Disables PCI-Express master access and verifies there are no pending requests @@ -7929,7 +8111,7 @@ em_disable_pciex_master(struct em_hw *hw) * E1000_SUCCESS at any other case. * ******************************************************************************/ -int32_t +STATIC int32_t em_get_auto_rd_done(struct em_hw *hw) { int32_t timeout = AUTO_READ_DONE_TIMEOUT; @@ -7977,7 +8159,7 @@ em_get_auto_rd_done(struct em_hw *hw) * E1000_SUCCESS at any other case. * ***************************************************************************/ -int32_t +STATIC int32_t em_get_phy_cfg_done(struct em_hw *hw) { int32_t timeout = PHY_CFG_TIMEOUT; @@ -8003,7 +8185,6 @@ em_get_phy_cfg_done(struct em_hw *hw) msec_delay(1); timeout--; } - if (!timeout) { DEBUGOUT("MNG configuration cycle has not completed.\n"); return -E1000_ERR_RESET; @@ -8025,7 +8206,7 @@ em_get_phy_cfg_done(struct em_hw *hw) * E1000_SUCCESS at any other case. * ***************************************************************************/ -int32_t +STATIC int32_t em_get_hw_eeprom_semaphore(struct em_hw *hw) { int32_t timeout; @@ -8075,7 +8256,7 @@ em_get_hw_eeprom_semaphore(struct em_hw *hw) * returns: - None. * ***************************************************************************/ -void +STATIC void em_put_hw_eeprom_semaphore(struct em_hw *hw) { uint32_t swsm; @@ -8104,7 +8285,7 @@ em_put_hw_eeprom_semaphore(struct em_hw *hw) * E1000_SUCCESS at any other case. * ***************************************************************************/ -int32_t +STATIC int32_t em_get_software_semaphore(struct em_hw *hw) { int32_t timeout = hw->eeprom.word_size + 1; @@ -8112,8 +8293,9 @@ em_get_software_semaphore(struct em_hw *hw) DEBUGFUNC("em_get_software_semaphore"); - if (hw->mac_type != em_80003es2lan) + if (hw->mac_type != em_80003es2lan) { return E1000_SUCCESS; + } while (timeout) { swsm = E1000_READ_REG(hw, SWSM); @@ -8139,15 +8321,16 @@ em_get_software_semaphore(struct em_hw *hw) * hw: Struct containing variables accessed by shared code * ***************************************************************************/ -void +STATIC void em_release_software_semaphore(struct em_hw *hw) { uint32_t swsm; DEBUGFUNC("em_release_software_semaphore"); - if (hw->mac_type != em_80003es2lan) + if (hw->mac_type != em_80003es2lan) { return; + } swsm = E1000_READ_REG(hw, SWSM); /* Release the SW semaphores.*/ @@ -8181,10 +8364,10 @@ em_check_phy_reset_block(struct em_hw *hw) if (hw->mac_type > em_82547_rev_2) manc = E1000_READ_REG(hw, MANC); return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? - E1000_BLK_PHY_RESET : E1000_SUCCESS; + E1000_BLK_PHY_RESET : E1000_SUCCESS; } -uint8_t +STATIC uint8_t em_arc_subsystem_valid(struct em_hw *hw) { uint32_t fwsm; @@ -8221,7 +8404,7 @@ em_arc_subsystem_valid(struct em_hw *hw) * returns: E1000_SUCCESS * *****************************************************************************/ -int32_t +STATIC int32_t em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop) { uint32_t gcr_reg = 0; @@ -8262,7 +8445,7 @@ em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop) * hw: Struct containing variables accessed by shared code * ***************************************************************************/ -int32_t +STATIC int32_t em_get_software_flag(struct em_hw *hw) { int32_t timeout = PHY_CFG_TIMEOUT; @@ -8301,7 +8484,7 @@ em_get_software_flag(struct em_hw *hw) * hw: Struct containing variables accessed by shared code * ***************************************************************************/ -void +STATIC void em_release_software_flag(struct em_hw *hw) { uint32_t extcnf_ctrl; @@ -8317,61 +8500,6 @@ em_release_software_flag(struct em_hw *hw) return; } -/*************************************************************************** - * - * Disable dynamic power down mode in ife PHY. - * It can be used to workaround band-gap problem. - * - * hw: Struct containing variables accessed by shared code - * - ***************************************************************************/ -int32_t -em_ife_disable_dynamic_power_down(struct em_hw *hw) -{ - uint16_t phy_data; - int32_t ret_val = E1000_SUCCESS; - - DEBUGFUNC("em_ife_disable_dynamic_power_down"); - - if (hw->phy_type == em_phy_ife) { - ret_val = em_read_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN; - ret_val = em_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, phy_data); - } - - return ret_val; -} - -/*************************************************************************** - * - * Enable dynamic power down mode in ife PHY. - * It can be used to workaround band-gap problem. - * - * hw: Struct containing variables accessed by shared code - * - ***************************************************************************/ -int32_t -em_ife_enable_dynamic_power_down(struct em_hw *hw) -{ - uint16_t phy_data; - int32_t ret_val = E1000_SUCCESS; - - DEBUGFUNC("em_ife_enable_dynamic_power_down"); - - if (hw->phy_type == em_phy_ife) { - ret_val = em_read_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN; - ret_val = em_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, phy_data); - } - - return ret_val; -} /****************************************************************************** * Reads a 16 bit word or words from the EEPROM using the ICH8's flash access @@ -8382,7 +8510,7 @@ em_ife_enable_dynamic_power_down(struct em_hw *hw) * data - word read from the EEPROM * words - number of words to read *****************************************************************************/ -int32_t +STATIC int32_t em_read_eeprom_ich8(struct em_hw *hw, uint16_t offset, uint16_t words, uint16_t *data) { @@ -8438,7 +8566,7 @@ em_read_eeprom_ich8(struct em_hw *hw, uint16_t offset, uint16_t words, * words - number of words to write * data - words to write to the EEPROM *****************************************************************************/ -int32_t +STATIC int32_t em_write_eeprom_ich8(struct em_hw *hw, uint16_t offset, uint16_t words, uint16_t *data) { @@ -8485,7 +8613,7 @@ em_write_eeprom_ich8(struct em_hw *hw, uint16_t offset, uint16_t words, * * hw - The pointer to the hw structure ****************************************************************************/ -int32_t +STATIC int32_t em_ich8_cycle_init(struct em_hw *hw) { union ich8_hws_flash_status hsfsts; @@ -8494,7 +8622,7 @@ em_ich8_cycle_init(struct em_hw *hw) DEBUGFUNC("em_ich8_cycle_init"); - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); /* May be check the Flash Des Valid bit in Hw status */ if (hsfsts.hsf_status.fldesvalid == 0) { @@ -8507,7 +8635,7 @@ em_ich8_cycle_init(struct em_hw *hw) hsfsts.hsf_status.flcerr = 1; hsfsts.hsf_status.dael = 1; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval); + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); /* Either we should have a hardware SPI cycle in progress bit to check * against, in order to start a new cycle or FDONE bit should be changed @@ -8522,13 +8650,13 @@ em_ich8_cycle_init(struct em_hw *hw) /* There is no cycle running at present, so we can start a cycle */ /* Begin by setting Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval); + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); error = E1000_SUCCESS; } else { /* otherwise poll for sometime so the current cycle has a chance * to end before giving up. */ - for (i = 0; i < ICH8_FLASH_COMMAND_TIMEOUT; i++) { - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + for (i = 0; i < ICH_FLASH_COMMAND_TIMEOUT; i++) { + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcinprog == 0) { error = E1000_SUCCESS; break; @@ -8539,7 +8667,7 @@ em_ich8_cycle_init(struct em_hw *hw) /* Successful in waiting for previous cycle to timeout, * now set the Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval); + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); } else { DEBUGOUT("Flash controller busy, cannot get access"); } @@ -8552,7 +8680,7 @@ em_ich8_cycle_init(struct em_hw *hw) * * hw - The pointer to the hw structure ****************************************************************************/ -int32_t +STATIC int32_t em_ich8_flash_cycle(struct em_hw *hw, uint32_t timeout) { union ich8_hws_flash_ctrl hsflctl; @@ -8561,13 +8689,13 @@ em_ich8_flash_cycle(struct em_hw *hw, uint32_t timeout) uint32_t i = 0; /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ - hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL); + hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL); hsflctl.hsf_ctrl.flcgo = 1; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval); + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* wait till FDONE bit is set to 1 */ do { - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcdone == 1) break; usec_delay(1); @@ -8587,7 +8715,7 @@ em_ich8_flash_cycle(struct em_hw *hw, uint32_t timeout) * size - Size of data to read, 1=byte 2=word * data - Pointer to the word to store the value read. *****************************************************************************/ -int32_t +STATIC int32_t em_read_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size, uint16_t* data) { @@ -8601,10 +8729,10 @@ em_read_ich8_data(struct em_hw *hw, uint32_t index, DEBUGFUNC("em_read_ich8_data"); if (size < 1 || size > 2 || data == 0x0 || - index > ICH8_FLASH_LINEAR_ADDR_MASK) + index > ICH_FLASH_LINEAR_ADDR_MASK) return error; - flash_linear_address = (ICH8_FLASH_LINEAR_ADDR_MASK & index) + + flash_linear_address = (ICH_FLASH_LINEAR_ADDR_MASK & index) + hw->flash_base_addr; do { @@ -8614,25 +8742,25 @@ em_read_ich8_data(struct em_hw *hw, uint32_t index, if (error != E1000_SUCCESS) break; - hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL); + hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL); /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ hsflctl.hsf_ctrl.fldbcount = size - 1; - hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_READ; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval); + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* Write the last 24 bits of index into Flash Linear address field in * Flash Address */ /* TODO: TBD maybe check the index against the size of flash */ - E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address); + E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address); - error = em_ich8_flash_cycle(hw, ICH8_FLASH_COMMAND_TIMEOUT); + error = em_ich8_flash_cycle(hw, ICH_FLASH_COMMAND_TIMEOUT); /* Check if FCERR is set to 1, if set to 1, clear it and try the whole * sequence a few more times, else read in (shift in) the Flash Data0, * the order is least significant byte first msb to lsb */ if (error == E1000_SUCCESS) { - flash_data = E1000_READ_ICH8_REG(hw, ICH8_FLASH_FDATA0); + flash_data = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0); if (size == 1) { *data = (uint8_t)(flash_data & 0x000000FF); } else if (size == 2) { @@ -8642,9 +8770,9 @@ em_read_ich8_data(struct em_hw *hw, uint32_t index, } else { /* If we've gotten here, then things are probably completely hosed, * but if the error condition is detected, it won't hurt to give - * it another try...ICH8_FLASH_CYCLE_REPEAT_COUNT times. + * it another try...ICH_FLASH_CYCLE_REPEAT_COUNT times. */ - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcerr == 1) { /* Repeat for some time before giving up. */ continue; @@ -8653,7 +8781,7 @@ em_read_ich8_data(struct em_hw *hw, uint32_t index, break; } } - } while (count++ < ICH8_FLASH_CYCLE_REPEAT_COUNT); + } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); return error; } @@ -8666,7 +8794,7 @@ em_read_ich8_data(struct em_hw *hw, uint32_t index, * size - Size of data to read, 1=byte 2=word * data - The byte(s) to write to the NVM. *****************************************************************************/ -int32_t +STATIC int32_t em_write_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size, uint16_t data) { @@ -8680,10 +8808,10 @@ em_write_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size, DEBUGFUNC("em_write_ich8_data"); if (size < 1 || size > 2 || data > size * 0xff || - index > ICH8_FLASH_LINEAR_ADDR_MASK) + index > ICH_FLASH_LINEAR_ADDR_MASK) return error; - flash_linear_address = (ICH8_FLASH_LINEAR_ADDR_MASK & index) + + flash_linear_address = (ICH_FLASH_LINEAR_ADDR_MASK & index) + hw->flash_base_addr; do { @@ -8693,34 +8821,34 @@ em_write_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size, if (error != E1000_SUCCESS) break; - hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL); + hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL); /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ hsflctl.hsf_ctrl.fldbcount = size -1; - hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_WRITE; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval); + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* Write the last 24 bits of index into Flash Linear address field in * Flash Address */ - E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address); + E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address); if (size == 1) flash_data = (uint32_t)data & 0x00FF; else flash_data = (uint32_t)data; - E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FDATA0, flash_data); + E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data); /* check if FCERR is set to 1 , if set to 1, clear it and try the whole * sequence a few more times else done */ - error = em_ich8_flash_cycle(hw, ICH8_FLASH_COMMAND_TIMEOUT); + error = em_ich8_flash_cycle(hw, ICH_FLASH_COMMAND_TIMEOUT); if (error == E1000_SUCCESS) { break; } else { /* If we're here, then things are most likely completely hosed, * but if the error condition is detected, it won't hurt to give - * it another try...ICH8_FLASH_CYCLE_REPEAT_COUNT times. + * it another try...ICH_FLASH_CYCLE_REPEAT_COUNT times. */ - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcerr == 1) { /* Repeat for some time before giving up. */ continue; @@ -8729,7 +8857,7 @@ em_write_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size, break; } } - } while (count++ < ICH8_FLASH_CYCLE_REPEAT_COUNT); + } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); return error; } @@ -8741,7 +8869,7 @@ em_write_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size, * index - The index of the byte to read. * data - Pointer to a byte to store the value read. *****************************************************************************/ -int32_t +STATIC int32_t em_read_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t* data) { int32_t status = E1000_SUCCESS; @@ -8764,24 +8892,26 @@ em_read_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t* data) * index - The index of the byte to write. * byte - The byte to write to the NVM. *****************************************************************************/ -int32_t +STATIC int32_t em_verify_write_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t byte) { int32_t error = E1000_SUCCESS; - int32_t program_retries; - uint8_t temp_byte; + int32_t program_retries = 0; - em_write_ich8_byte(hw, index, byte); - usec_delay(100); + DEBUGOUT2("Byte := %2.2X Offset := %d\n", byte, index); - for (program_retries = 0; program_retries < 100; program_retries++) { - em_read_ich8_byte(hw, index, &temp_byte); - if (temp_byte == byte) - break; - usec_delay(10); - em_write_ich8_byte(hw, index, byte); - usec_delay(100); + error = em_write_ich8_byte(hw, index, byte); + + if (error != E1000_SUCCESS) { + for (program_retries = 0; program_retries < 100; program_retries++) { + DEBUGOUT2("Retrying \t Byte := %2.2X Offset := %d\n", byte, index); + error = em_write_ich8_byte(hw, index, byte); + usec_delay(100); + if (error == E1000_SUCCESS) + break; + } } + if (program_retries == 100) error = E1000_ERR_EEPROM; @@ -8795,7 +8925,7 @@ em_verify_write_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t byte) * index - The index of the byte to read. * data - The byte to write to the NVM. *****************************************************************************/ -int32_t +STATIC int32_t em_write_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t data) { int32_t status = E1000_SUCCESS; @@ -8813,7 +8943,7 @@ em_write_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t data) * index - The starting byte index of the word to read. * data - Pointer to a word to store the value read. *****************************************************************************/ -int32_t +STATIC int32_t em_read_ich8_word(struct em_hw *hw, uint32_t index, uint16_t *data) { int32_t status = E1000_SUCCESS; @@ -8821,62 +8951,53 @@ em_read_ich8_word(struct em_hw *hw, uint32_t index, uint16_t *data) return status; } -/****************************************************************************** - * Writes a word to the NVM using the ICH8 flash access registers. - * - * hw - pointer to em_hw structure - * index - The starting byte index of the word to read. - * data - The word to write to the NVM. - *****************************************************************************/ -int32_t -em_write_ich8_word(struct em_hw *hw, uint32_t index, uint16_t data) -{ - int32_t status = E1000_SUCCESS; - status = em_write_ich8_data(hw, index, 2, data); - return status; -} /****************************************************************************** - * Erases the bank specified. Each bank is a 4k block. Segments are 0 based. - * segment N is 4096 * N + flash_reg_addr. + * Erases the bank specified. Each bank may be a 4, 8 or 64k block. Banks are 0 + * based. * * hw - pointer to em_hw structure - * segment - 0 for first segment, 1 for second segment, etc. + * bank - 0 for first bank, 1 for second bank + * + * Note that this function may actually erase as much as 8 or 64 KBytes. The + * amount of NVM used in each bank is a *minimum* of 4 KBytes, but in fact the + * bank size may be 4, 8 or 64 KBytes *****************************************************************************/ int32_t -em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t segment) +em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t bank) { union ich8_hws_flash_status hsfsts; union ich8_hws_flash_ctrl hsflctl; uint32_t flash_linear_address; int32_t count = 0; int32_t error = E1000_ERR_EEPROM; - int32_t iteration, seg_size; - int32_t sector_size; + int32_t iteration; + int32_t sub_sector_size = 0; + int32_t bank_size; int32_t j = 0; int32_t error_flag = 0; - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); /* Determine HW Sector size: Read BERASE bits of Hw flash Status register */ /* 00: The Hw sector is 256 bytes, hence we need to erase 16 * consecutive sectors. The start index for the nth Hw sector can be - * calculated as = segment * 4096 + n * 256 + * calculated as bank * 4096 + n * 256 * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector. * The start index for the nth Hw sector can be calculated - * as = segment * 4096 - * 10: Error condition - * 11: The Hw sector size is much bigger than the size asked to - * erase...error condition */ + * as bank * 4096 + * 10: The HW sector is 8K bytes + * 11: The Hw sector size is 64K bytes */ if (hsfsts.hsf_status.berasesz == 0x0) { /* Hw sector size 256 */ - sector_size = seg_size = ICH8_FLASH_SEG_SIZE_256; - iteration = ICH8_FLASH_SECTOR_SIZE / ICH8_FLASH_SEG_SIZE_256; + sub_sector_size = ICH_FLASH_SEG_SIZE_256; + bank_size = ICH_FLASH_SECTOR_SIZE; + iteration = ICH_FLASH_SECTOR_SIZE / ICH_FLASH_SEG_SIZE_256; } else if (hsfsts.hsf_status.berasesz == 0x1) { - sector_size = seg_size = ICH8_FLASH_SEG_SIZE_4K; + bank_size = ICH_FLASH_SEG_SIZE_4K; iteration = 1; } else if (hsfsts.hsf_status.berasesz == 0x3) { - sector_size = seg_size = ICH8_FLASH_SEG_SIZE_64K; + bank_size = ICH_FLASH_SEG_SIZE_64K; iteration = 1; } else { return error; @@ -8894,28 +9015,27 @@ em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t segment) /* Write a value 11 (block Erase) in Flash Cycle field in Hw flash * Control */ - hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL); - hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_ERASE; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval); + hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* Write the last 24 bits of an index within the block into Flash * Linear address field in Flash Address. This probably needs to - * be calculated here based off the on-chip segment size and the - * software segment size assumed (4K) */ - /* TBD */ - flash_linear_address = segment * sector_size + j * seg_size; - flash_linear_address &= ICH8_FLASH_LINEAR_ADDR_MASK; + * be calculated here based off the on-chip erase sector size and + * the software bank size (4, 8 or 64 KBytes) */ + flash_linear_address = bank * bank_size + j * sub_sector_size; flash_linear_address += hw->flash_base_addr; + flash_linear_address &= ICH_FLASH_LINEAR_ADDR_MASK; - E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address); + E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address); - error = em_ich8_flash_cycle(hw, 1000000); + error = em_ich8_flash_cycle(hw, ICH_FLASH_ERASE_TIMEOUT); /* Check if FCERR is set to 1. If 1, clear it and try the whole * sequence a few more times else Done */ if (error == E1000_SUCCESS) { break; } else { - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcerr == 1) { /* repeat for some time before giving up */ continue; @@ -8924,7 +9044,7 @@ em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t segment) break; } } - } while ((count < ICH8_FLASH_CYCLE_REPEAT_COUNT) && !error_flag); + } while ((count < ICH_FLASH_CYCLE_REPEAT_COUNT) && !error_flag); if (error_flag == 1) break; } @@ -8933,43 +9053,8 @@ em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t segment) return error; } -/****************************************************************************** - * - * Reverse duplex setting without breaking the link. - * - * hw: Struct containing variables accessed by shared code - * - *****************************************************************************/ -int32_t -em_duplex_reversal(struct em_hw *hw) -{ - int32_t ret_val; - uint16_t phy_data; - - if (hw->phy_type != em_phy_igp_3) - return E1000_SUCCESS; - - ret_val = em_read_phy_reg(hw, PHY_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data ^= MII_CR_FULL_DUPLEX; - - ret_val = em_write_phy_reg(hw, PHY_CTRL, phy_data); - if (ret_val) - return ret_val; - - ret_val = em_read_phy_reg(hw, IGP3E1000_PHY_MISC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= IGP3_PHY_MISC_DUPLEX_MANUAL_SET; - ret_val = em_write_phy_reg(hw, IGP3E1000_PHY_MISC_CTRL, phy_data); - - return ret_val; -} -int32_t +STATIC int32_t em_init_lcd_from_nvm_config_region(struct em_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size) { @@ -9011,7 +9096,7 @@ em_init_lcd_from_nvm_config_region(struct em_hw *hw, * * hw: Struct containing variables accessed by shared code *****************************************************************************/ -int32_t +STATIC int32_t em_init_lcd_from_nvm(struct em_hw *hw) { uint32_t reg_data, cnf_base_addr, cnf_size, ret_val, loop; @@ -9061,5 +9146,3 @@ em_init_lcd_from_nvm(struct em_hw *hw) return E1000_SUCCESS; } - - diff --git a/sys/dev/netif/em/if_em_hw.h b/sys/dev/netif/em/if_em_hw.h index dcd495c1ad..b58b6ee718 100644 --- a/sys/dev/netif/em/if_em_hw.h +++ b/sys/dev/netif/em/if_em_hw.h @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ /*$FreeBSD: src/sys/dev/em/if_em_hw.h,v 1.1.2.8 2003/06/09 21:43:41 pdeuskar Exp $*/ -/*$DragonFly: src/sys/dev/netif/em/if_em_hw.h,v 1.10 2006/08/12 13:03:44 sephe Exp $*/ +/*$DragonFly: src/sys/dev/netif/em/if_em_hw.h,v 1.11 2006/12/23 10:39:16 sephe Exp $*/ /* if_em_hw.h * Structures, enums, and macros for the MAC @@ -100,15 +100,6 @@ typedef enum { em_100_full = 3 } em_speed_duplex_type; -/* Flow Control Settings */ -typedef enum { - em_fc_none = 0, - em_fc_rx_pause = 1, - em_fc_tx_pause = 2, - em_fc_full = 3, - em_fc_default = 0xFF -} em_fc_type; - struct em_shadow_ram { uint16_t eeprom_word; boolean_t modified; @@ -138,11 +129,13 @@ typedef enum { /* PCI bus widths */ typedef enum { em_bus_width_unknown = 0, + /* These PCIe values should literally match the possible return values + * from config space */ + em_bus_width_pciex_1 = 1, + em_bus_width_pciex_2 = 2, + em_bus_width_pciex_4 = 4, em_bus_width_32, em_bus_width_64, - em_bus_width_pciex_1, - em_bus_width_pciex_2, - em_bus_width_pciex_4, em_bus_width_reserved } em_bus_width; @@ -311,11 +304,13 @@ typedef enum { #define E1000_BLK_PHY_RESET 12 #define E1000_ERR_SWFW_SYNC 13 +#define E1000_BYTE_SWAP_WORD(_value) ((((_value) & 0x00ff) << 8) | \ + (((_value) & 0xff00) >> 8)) + /* Function prototypes */ /* Initialization */ int32_t em_reset_hw(struct em_hw *hw); int32_t em_init_hw(struct em_hw *hw); -int32_t em_id_led_init(struct em_hw * hw); int32_t em_set_mac_type(struct em_hw *hw); void em_set_media_type(struct em_hw *hw); @@ -323,39 +318,23 @@ void em_set_media_type(struct em_hw *hw); int32_t em_setup_link(struct em_hw *hw); int32_t em_phy_setup_autoneg(struct em_hw *hw); void em_config_collision_dist(struct em_hw *hw); -int32_t em_config_fc_after_link_up(struct em_hw *hw); int32_t em_check_for_link(struct em_hw *hw); -int32_t em_get_speed_and_duplex(struct em_hw *hw, uint16_t * speed, uint16_t * duplex); -int32_t em_wait_autoneg(struct em_hw *hw); +int32_t em_get_speed_and_duplex(struct em_hw *hw, uint16_t *speed, uint16_t *duplex); int32_t em_force_mac_fc(struct em_hw *hw); + /* PHY */ int32_t em_read_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t *phy_data); int32_t em_write_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t data); int32_t em_phy_hw_reset(struct em_hw *hw); int32_t em_phy_reset(struct em_hw *hw); -void em_phy_powerdown_workaround(struct em_hw *hw); -int32_t em_kumeran_lock_loss_workaround(struct em_hw *hw); -int32_t em_duplex_reversal(struct em_hw *hw); -int32_t em_init_lcd_from_nvm_config_region(struct em_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size); -int32_t em_init_lcd_from_nvm(struct em_hw *hw); -int32_t em_detect_gig_phy(struct em_hw *hw); int32_t em_phy_get_info(struct em_hw *hw, struct em_phy_info *phy_info); -int32_t em_phy_m88_get_info(struct em_hw *hw, struct em_phy_info *phy_info); -int32_t em_phy_igp_get_info(struct em_hw *hw, struct em_phy_info *phy_info); -int32_t em_get_cable_length(struct em_hw *hw, uint16_t *min_length, uint16_t *max_length); -int32_t em_check_polarity(struct em_hw *hw, uint16_t *polarity); -int32_t em_check_downshift(struct em_hw *hw); int32_t em_validate_mdi_setting(struct em_hw *hw); -int32_t em_read_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t *data); -int32_t em_write_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t data); + +void em_phy_powerdown_workaround(struct em_hw *hw); /* EEPROM Functions */ int32_t em_init_eeprom_params(struct em_hw *hw); -boolean_t em_is_onboard_nvm_eeprom(struct em_hw *hw); -int32_t em_read_eeprom_eerd(struct em_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); -int32_t em_write_eeprom_eewr(struct em_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); -int32_t em_poll_eerd_eewr_done(struct em_hw *hw, int eerd); /* MNG HOST IF functions */ uint32_t em_enable_mng_pass_thru(struct em_hw *hw); @@ -399,37 +378,24 @@ struct em_host_mng_dhcp_cookie{ uint8_t checksum; }; +int32_t em_read_part_num(struct em_hw *hw, uint32_t * part_num); int32_t em_mng_write_dhcp_info(struct em_hw *hw, uint8_t *buffer, uint16_t length); boolean_t em_check_mng_mode(struct em_hw *hw); boolean_t em_enable_tx_pkt_filtering(struct em_hw *hw); -int32_t em_mng_enable_host_if(struct em_hw *hw); -int32_t em_mng_host_if_write(struct em_hw *hw, uint8_t *buffer, - uint16_t length, uint16_t offset, uint8_t *sum); -int32_t em_mng_write_cmd_header(struct em_hw* hw, - struct em_host_mng_command_header* hdr); - -int32_t em_mng_write_commit(struct em_hw *hw); - int32_t em_read_eeprom(struct em_hw *hw, uint16_t reg, uint16_t words, 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 words, 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); -int32_t em_swfw_sync_acquire(struct em_hw *hw, uint16_t mask); -void em_swfw_sync_release(struct em_hw *hw, uint16_t mask); -void em_release_software_flag(struct em_hw *hw); -int32_t em_get_software_flag(struct em_hw *hw); + /* Filters (multicast, vlan, receive) */ -void em_init_rx_addrs(struct em_hw *hw); void em_mc_addr_list_update(struct em_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count); uint32_t em_hash_mc_addr(struct em_hw *hw, uint8_t * mc_addr); void em_mta_set(struct em_hw *hw, uint32_t hash_value); void em_rar_set(struct em_hw *hw, uint8_t * mc_addr, uint32_t rar_index); void em_write_vfta(struct em_hw *hw, uint32_t offset, uint32_t value); -void em_clear_vfta(struct em_hw *hw); /* LED functions */ int32_t em_setup_led(struct em_hw *hw); @@ -442,6 +408,7 @@ int32_t em_blink_led_start(struct em_hw *hw); /* Everything else */ void em_clear_hw_cntrs(struct em_hw *hw); + 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); @@ -450,53 +417,14 @@ void em_pci_set_mwi(struct em_hw *hw); void em_pci_clear_mwi(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); +int32_t em_read_pcie_cap_reg(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, unsigned long port); -uint32_t em_read_reg_io(struct em_hw *hw, uint32_t offset); void em_io_write(struct em_hw *hw, unsigned long port, uint32_t value); -void em_write_reg_io(struct em_hw *hw, uint32_t offset, uint32_t value); -int32_t em_config_dsp_after_link_change(struct em_hw *hw, boolean_t link_up); -int32_t em_set_d3_lplu_state(struct em_hw *hw, boolean_t active); -int32_t em_set_d0_lplu_state(struct em_hw *hw, boolean_t active); -void em_set_pci_express_master_disable(struct em_hw *hw); -void em_enable_pciex_master(struct em_hw *hw); int32_t em_disable_pciex_master(struct em_hw *hw); -int32_t em_get_auto_rd_done(struct em_hw *hw); -int32_t em_get_phy_cfg_done(struct em_hw *hw); -int32_t em_get_software_semaphore(struct em_hw *hw); -void em_release_software_semaphore(struct em_hw *hw); int32_t em_check_phy_reset_block(struct em_hw *hw); -int32_t em_get_hw_eeprom_semaphore(struct em_hw *hw); -void em_put_hw_eeprom_semaphore(struct em_hw *hw); -int32_t em_commit_shadow_ram(struct em_hw *hw); -uint8_t em_arc_subsystem_valid(struct em_hw *hw); -int32_t em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop); - -int32_t em_read_ich8_byte(struct em_hw *hw, uint32_t index, - uint8_t *data); -int32_t em_verify_write_ich8_byte(struct em_hw *hw, uint32_t index, - uint8_t byte); -int32_t em_write_ich8_byte(struct em_hw *hw, uint32_t index, - uint8_t byte); -int32_t em_read_ich8_word(struct em_hw *hw, uint32_t index, - uint16_t *data); -int32_t em_write_ich8_word(struct em_hw *hw, uint32_t index, - uint16_t word); -int32_t em_read_ich8_data(struct em_hw *hw, uint32_t index, - uint32_t size, uint16_t *data); -int32_t em_write_ich8_data(struct em_hw *hw, uint32_t index, - uint32_t size, uint16_t data); -int32_t em_read_eeprom_ich8(struct em_hw *hw, uint16_t offset, - uint16_t words, uint16_t *data); -int32_t em_write_eeprom_ich8(struct em_hw *hw, uint16_t offset, - uint16_t words, uint16_t *data); -int32_t em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t segment); -int32_t em_ich8_cycle_init(struct em_hw *hw); -int32_t em_ich8_flash_cycle(struct em_hw *hw, uint32_t timeout); -int32_t em_phy_ife_get_info(struct em_hw *hw, - struct em_phy_info *phy_info); -int32_t em_ife_disable_dynamic_power_down(struct em_hw *hw); -int32_t em_ife_enable_dynamic_power_down(struct em_hw *hw); + + #ifndef E1000_READ_REG_IO #define E1000_READ_REG_IO(a, reg) \ @@ -545,6 +473,7 @@ int32_t em_ife_enable_dynamic_power_down(struct em_hw *hw); #define E1000_DEV_ID_82571EB_FIBER 0x105F #define E1000_DEV_ID_82571EB_SERDES 0x1060 #define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 +#define E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE 0x10BC #define E1000_DEV_ID_82572EI_COPPER 0x107D #define E1000_DEV_ID_82572EI_FIBER 0x107E #define E1000_DEV_ID_82572EI_SERDES 0x107F @@ -562,6 +491,8 @@ int32_t em_ife_enable_dynamic_power_down(struct em_hw *hw); #define E1000_DEV_ID_ICH8_IGP_AMT 0x104A #define E1000_DEV_ID_ICH8_IGP_C 0x104B #define E1000_DEV_ID_ICH8_IFE 0x104C +#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4 +#define E1000_DEV_ID_ICH8_IFE_G 0x10C5 #define E1000_DEV_ID_ICH8_IGP_M 0x104D @@ -633,6 +564,7 @@ int32_t em_ife_enable_dynamic_power_down(struct em_hw *hw); E1000_IMS_RXSEQ | \ E1000_IMS_LSC) + /* Additional interrupts need to be handled for em_ich8lan: DSW = The FW changed the status of the DISSW bit in FWSM PHYINT = The LAN connected device generates an interrupt @@ -642,16 +574,18 @@ int32_t em_ife_enable_dynamic_power_down(struct em_hw *hw); E1000_IMS_PHYINT | \ E1000_IMS_EPRST) + /* Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. We * reserve one of these spots for our directed address, allowing us room for * E1000_RAR_ENTRIES - 1 multicast addresses. */ #define E1000_RAR_ENTRIES 15 -#define E1000_RAR_ENTRIES_ICH8LAN 7 -#define MIN_NUMBER_OF_DESCRIPTORS 8 -#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8 +#define E1000_RAR_ENTRIES_ICH8LAN 6 + +#define MIN_NUMBER_OF_DESCRIPTORS 8 +#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8 /* Receive Descriptor */ struct em_rx_desc { @@ -772,6 +706,7 @@ union em_rx_desc_packet_split { E1000_RXDEXT_STATERR_CXE | \ E1000_RXDEXT_STATERR_RXE) + /* Transmit Descriptor */ struct em_tx_desc { uint64_t buffer_addr; /* Address of the descriptor's data buffer */ @@ -1450,7 +1385,7 @@ struct em_hw { struct em_shadow_ram *eeprom_shadow_ram; uint32_t flash_bank_size; uint32_t flash_base_addr; - em_fc_type fc; + uint32_t fc; em_bus_speed bus_speed; em_bus_width bus_width; em_bus_type bus_type; @@ -1460,10 +1395,10 @@ struct em_hw { em_ffe_config ffe_config_state; uint32_t asf_firmware_present; uint32_t eeprom_semaphore_present; - bus_space_tag_t reg_io_tag; - bus_space_tag_t reg_io_handle; uint32_t swfw_sync_present; uint32_t swfwhw_semaphore_present; + + unsigned long io_base; uint32_t phy_id; uint32_t phy_revision; uint32_t phy_addr; @@ -1514,6 +1449,7 @@ struct em_hw { boolean_t tbi_compatibility_on; boolean_t laa_is_present; boolean_t phy_reset_disable; + boolean_t initialize_hw_bits_disable; boolean_t fc_send_xon; boolean_t fc_strict_ieee; boolean_t report_tx_early; @@ -1572,7 +1508,6 @@ struct em_hw { #define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ #define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ #define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to manageability engine */ - /* Device Status */ #define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ #define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ @@ -1646,8 +1581,8 @@ struct em_hw { #define E1000_HICR_FW_RESET 0xC0 #define E1000_SHADOW_RAM_WORDS 2048 -#define E1000_ICH8_NVM_SIG_WORD 0x13 -#define E1000_ICH8_NVM_SIG_MASK 0xC0 +#define E1000_ICH_NVM_SIG_WORD 0x13 +#define E1000_ICH_NVM_SIG_MASK 0xC0 /* EEPROM Read */ #define E1000_EERD_START 0x00000001 /* Start Read */ @@ -1687,16 +1622,17 @@ struct em_hw { #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 #define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000 +#define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000 #define E1000_CTRL_EXT_LINK_MODE_SERDES 0x00C00000 +#define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000 #define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000 #define E1000_CTRL_EXT_WR_WMARK_256 0x00000000 #define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 #define E1000_CTRL_EXT_WR_WMARK_384 0x02000000 #define E1000_CTRL_EXT_WR_WMARK_448 0x03000000 -#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ -#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ -#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ +#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ +#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ +#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ #define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error detection enabled */ #define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */ #define E1000_CTRL_EXT_GHOST_PAREN 0x40000000 @@ -1831,6 +1767,7 @@ struct em_hw { #define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */ #define E1000_ICR_EPRST 0x00100000 /* ME handware reset occurs */ + /* Interrupt Cause Set */ #define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ #define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ @@ -1860,6 +1797,7 @@ struct em_hw { #define E1000_ICS_PHYINT E1000_ICR_PHYINT #define E1000_ICS_EPRST E1000_ICR_EPRST + /* Interrupt Mask Set */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ #define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ @@ -1889,6 +1827,7 @@ struct em_hw { #define E1000_IMS_PHYINT E1000_ICR_PHYINT #define E1000_IMS_EPRST E1000_ICR_EPRST + /* Interrupt Mask Clear */ #define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ #define E1000_IMC_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ @@ -1918,6 +1857,7 @@ struct em_hw { #define E1000_IMC_PHYINT E1000_ICR_PHYINT #define E1000_IMC_EPRST E1000_ICR_EPRST + /* Receive Control */ #define E1000_RCTL_RST 0x00000001 /* Software reset */ #define E1000_RCTL_EN 0x00000002 /* enable */ @@ -2005,6 +1945,13 @@ struct em_hw { #define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ #define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ +/* Flow Control Settings */ +#define E1000_FC_NONE 0 +#define E1000_FC_RX_PAUSE 1 +#define E1000_FC_TX_PAUSE 2 +#define E1000_FC_FULL 3 +#define E1000_FC_DEFAULT 0xFF + /* Header split receive */ #define E1000_RFCTL_ISCSI_DIS 0x00000001 #define E1000_RFCTL_ISCSI_DWC_MASK 0x0000003E @@ -2029,9 +1976,9 @@ struct em_hw { #define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */ /* Transmit Descriptor Control */ -#define E1000_TXDCTL_PTHRESH 0x000000FF /* TXDCTL Prefetch Threshold */ -#define E1000_TXDCTL_HTHRESH 0x0000FF00 /* TXDCTL Host Threshold */ -#define E1000_TXDCTL_WTHRESH 0x00FF0000 /* TXDCTL Writeback Threshold */ +#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */ +#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */ +#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */ #define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ #define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */ #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ @@ -2292,6 +2239,11 @@ struct em_host_command_info { #define E1000_FACTPS_LAN_FUNC_SEL 0x40000000 #define E1000_FACTPS_PM_STATE_CHANGED 0x80000000 +/* PCI-Ex Config Space */ +#define PCI_EX_LINK_STATUS 0x12 +#define PCI_EX_LINK_WIDTH_MASK 0x3F0 +#define PCI_EX_LINK_WIDTH_SHIFT 4 + /* EEPROM Commands - Microwire */ #define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */ #define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */ @@ -2599,6 +2551,7 @@ struct em_host_command_info { #define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR #define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA + /* PHY 1000 MII Register/Bit Definitions */ /* PHY Registers defined by IEEE */ #define PHY_CTRL 0x00 /* Control Register */ @@ -3194,6 +3147,7 @@ struct em_host_command_info { /* I = Integrated * E = External */ +#define M88_VENDOR 0x0141 #define M88E1000_E_PHY_ID 0x01410C50 #define M88E1000_I_PHY_ID 0x01410C30 #define M88E1011_I_PHY_ID 0x01410C20 @@ -3234,6 +3188,7 @@ struct em_host_command_info { #define IGP3_VR_CTRL \ PHY_REG(776, 18) /* Voltage regulator control register */ #define IGP3_VR_CTRL_MODE_SHUT 0x0200 /* Enter powerdown, shutdown VRs */ +#define IGP3_VR_CTRL_MODE_MASK 0x0300 /* Shutdown VR Mask */ #define IGP3_CAPABILITY \ PHY_REG(776, 19) /* IGP3 Capability Register */ @@ -3318,39 +3273,40 @@ struct em_host_command_info { #define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ #define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ -#define ICH8_FLASH_COMMAND_TIMEOUT 500 /* 500 ms , should be adjusted */ -#define ICH8_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles , should be adjusted */ -#define ICH8_FLASH_SEG_SIZE_256 256 -#define ICH8_FLASH_SEG_SIZE_4K 4096 -#define ICH8_FLASH_SEG_SIZE_64K 65536 - -#define ICH8_CYCLE_READ 0x0 -#define ICH8_CYCLE_RESERVED 0x1 -#define ICH8_CYCLE_WRITE 0x2 -#define ICH8_CYCLE_ERASE 0x3 - -#define ICH8_FLASH_GFPREG 0x0000 -#define ICH8_FLASH_HSFSTS 0x0004 -#define ICH8_FLASH_HSFCTL 0x0006 -#define ICH8_FLASH_FADDR 0x0008 -#define ICH8_FLASH_FDATA0 0x0010 -#define ICH8_FLASH_FRACC 0x0050 -#define ICH8_FLASH_FREG0 0x0054 -#define ICH8_FLASH_FREG1 0x0058 -#define ICH8_FLASH_FREG2 0x005C -#define ICH8_FLASH_FREG3 0x0060 -#define ICH8_FLASH_FPR0 0x0074 -#define ICH8_FLASH_FPR1 0x0078 -#define ICH8_FLASH_SSFSTS 0x0090 -#define ICH8_FLASH_SSFCTL 0x0092 -#define ICH8_FLASH_PREOP 0x0094 -#define ICH8_FLASH_OPTYPE 0x0096 -#define ICH8_FLASH_OPMENU 0x0098 - -#define ICH8_FLASH_REG_MAPSIZE 0x00A0 -#define ICH8_FLASH_SECTOR_SIZE 4096 -#define ICH8_GFPREG_BASE_MASK 0x1FFF -#define ICH8_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF +#define ICH_FLASH_COMMAND_TIMEOUT 5000 /* 5000 uSecs - adjusted */ +#define ICH_FLASH_ERASE_TIMEOUT 3000000 /* Up to 3 seconds - worst case */ +#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles */ +#define ICH_FLASH_SEG_SIZE_256 256 +#define ICH_FLASH_SEG_SIZE_4K 4096 +#define ICH_FLASH_SEG_SIZE_64K 65536 + +#define ICH_CYCLE_READ 0x0 +#define ICH_CYCLE_RESERVED 0x1 +#define ICH_CYCLE_WRITE 0x2 +#define ICH_CYCLE_ERASE 0x3 + +#define ICH_FLASH_GFPREG 0x0000 +#define ICH_FLASH_HSFSTS 0x0004 +#define ICH_FLASH_HSFCTL 0x0006 +#define ICH_FLASH_FADDR 0x0008 +#define ICH_FLASH_FDATA0 0x0010 +#define ICH_FLASH_FRACC 0x0050 +#define ICH_FLASH_FREG0 0x0054 +#define ICH_FLASH_FREG1 0x0058 +#define ICH_FLASH_FREG2 0x005C +#define ICH_FLASH_FREG3 0x0060 +#define ICH_FLASH_FPR0 0x0074 +#define ICH_FLASH_FPR1 0x0078 +#define ICH_FLASH_SSFSTS 0x0090 +#define ICH_FLASH_SSFCTL 0x0092 +#define ICH_FLASH_PREOP 0x0094 +#define ICH_FLASH_OPTYPE 0x0096 +#define ICH_FLASH_OPMENU 0x0098 + +#define ICH_FLASH_REG_MAPSIZE 0x00A0 +#define ICH_FLASH_SECTOR_SIZE 4096 +#define ICH_GFPREG_BASE_MASK 0x1FFF +#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF /* ICH8 GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ /* Offset 04h HSFSTS */ diff --git a/sys/dev/netif/em/if_em_osdep.h b/sys/dev/netif/em/if_em_osdep.h index 531ab5c0fb..812a5b1cc4 100644 --- a/sys/dev/netif/em/if_em_osdep.h +++ b/sys/dev/netif/em/if_em_osdep.h @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /*$FreeBSD: src/sys/dev/em/if_em_osdep.h,v 1.1.2.11 2003/06/09 21:43:41 pdeuskar Exp $*/ -/*$DragonFly: src/sys/dev/netif/em/if_em_osdep.h,v 1.8 2006/12/22 23:26:19 swildner Exp $*/ +/*$DragonFly: src/sys/dev/netif/em/if_em_osdep.h,v 1.9 2006/12/23 10:39:16 sephe Exp $*/ #ifndef _FREEBSD_OS_H_ #define _FREEBSD_OS_H_ @@ -88,6 +88,8 @@ struct em_osdep { bus_space_tag_t mem_bus_space_tag; bus_space_handle_t mem_bus_space_handle; + bus_space_tag_t io_bus_space_tag; + bus_space_handle_t io_bus_space_handle; bus_space_tag_t flash_bus_space_tag; bus_space_handle_t flash_bus_space_handle; struct device *dev; @@ -149,19 +151,19 @@ struct em_osdep ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg \ + (index << 1)), value) -#define E1000_READ_ICH8_REG(hw, reg) \ +#define E1000_READ_ICH_FLASH_REG(hw, reg) \ bus_space_read_4(((struct em_osdep *)(hw)->back)->flash_bus_space_tag, \ ((struct em_osdep *)(hw)->back)->flash_bus_space_handle, reg) -#define E1000_READ_ICH8_REG16(hw, reg) \ +#define E1000_READ_ICH_FLASH_REG16(hw, reg) \ bus_space_read_2(((struct em_osdep *)(hw)->back)->flash_bus_space_tag, \ ((struct em_osdep *)(hw)->back)->flash_bus_space_handle, reg) -#define E1000_WRITE_ICH8_REG(hw, reg, value) \ +#define E1000_WRITE_ICH_FLASH_REG(hw, reg, value) \ bus_space_write_4(((struct em_osdep *)(hw)->back)->flash_bus_space_tag, \ ((struct em_osdep *)(hw)->back)->flash_bus_space_handle, reg, value) -#define E1000_WRITE_ICH8_REG16(hw, reg, value) \ +#define E1000_WRITE_ICH_FLASH_REG16(hw, reg, value) \ bus_space_write_2(((struct em_osdep *)(hw)->back)->flash_bus_space_tag, \ ((struct em_osdep *)(hw)->back)->flash_bus_space_handle, reg, value) -- 2.41.0