summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjfv <jfv@FreeBSD.org>2006-10-28 00:47:55 +0000
committerjfv <jfv@FreeBSD.org>2006-10-28 00:47:55 +0000
commit8ca206e26c2343bd1ddbcb0313abb6e7eadf1682 (patch)
tree7ecb50e57013161b3b97e18931d51a083ef45636
parentf3dd13700bb000a0c99cb0996d1f6c9df117b656 (diff)
downloadFreeBSD-src-8ca206e26c2343bd1ddbcb0313abb6e7eadf1682.zip
FreeBSD-src-8ca206e26c2343bd1ddbcb0313abb6e7eadf1682.tar.gz
This is the merge of the Intel 6.2.9 driver. It provides all new shared code,
new device support, and it is hoped a more stable driver for 6.2. RELEASE. This checkin was discussed and approved today by RE, scottl, jhb, and pdeuskar
-rw-r--r--sys/dev/em/if_em.c1531
-rw-r--r--sys/dev/em/if_em.h170
-rw-r--r--sys/dev/em/if_em_hw.c1109
-rw-r--r--sys/dev/em/if_em_hw.h304
-rw-r--r--sys/dev/em/if_em_osdep.h98
5 files changed, 1504 insertions, 1708 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c
index bfabd62..030d9a5 100644
--- a/sys/dev/em/if_em.c
+++ b/sys/dev/em/if_em.c
@@ -69,11 +69,11 @@ POSSIBILITY OF SUCH DAMAGE.
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
-#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <machine/in_cksum.h>
+
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/em/if_em_hw.h>
@@ -87,8 +87,7 @@ int em_display_debug_stats = 0;
/*********************************************************************
* Driver version
*********************************************************************/
-
-char em_driver_version[] = "Version - 6.1.4 - TSO";
+char em_driver_version[] = "Version - 6.2.9";
/*********************************************************************
@@ -118,8 +117,6 @@ static em_vendor_info_t em_vendor_info_array[] =
{ 0x8086, E1000_DEV_ID_82541GI_LF, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82541GI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82542, PCI_ANY_ID, PCI_ANY_ID, 0},
-
{ 0x8086, E1000_DEV_ID_82543GC_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82543GC_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
@@ -154,6 +151,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},
@@ -171,9 +170,13 @@ static em_vendor_info_t em_vendor_info_array[] =
PCI_ANY_ID, PCI_ANY_ID, 0},
{ 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},
/* required last entry */
{ 0, 0, 0, 0, 0}
@@ -207,13 +210,11 @@ 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_resources(struct adapter *);
-static int em_allocate_intr(struct adapter *);
-static void em_free_intr(struct adapter *);
static void em_free_pci_resources(struct adapter *);
static void em_local_timer(void *);
static int em_hardware_init(struct adapter *);
static void em_setup_interface(device_t, struct adapter *);
-static int em_setup_transmit_structures(struct adapter *);
+static void em_setup_transmit_structures(struct adapter *);
static void em_initialize_transmit_unit(struct adapter *);
static int em_setup_receive_structures(struct adapter *);
static void em_initialize_receive_unit(struct adapter *);
@@ -233,14 +234,16 @@ static void em_receive_checksum(struct adapter *, struct em_rx_desc *,
struct mbuf *);
static void em_transmit_checksum_setup(struct adapter *, struct mbuf *,
uint32_t *, uint32_t *);
-static boolean_t em_tso_setup(struct adapter *, struct mbuf *,
- uint32_t *, uint32_t *);
+#ifdef EM_TSO
+static boolean_t em_tso_setup(struct adapter *, struct mbuf *, u_int32_t *,
+ uint32_t *);
+#endif
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_update_link_status(struct adapter *);
-static int em_get_buf(struct adapter *, int);
+static int em_get_buf(int i, struct adapter *, struct mbuf *);
static void em_enable_vlans(struct adapter *);
static void em_disable_vlans(struct adapter *);
static int em_encap(struct adapter *, struct mbuf **);
@@ -262,20 +265,10 @@ static uint32_t em_fill_descriptors (bus_addr_t address, uint32_t length,
static int em_sysctl_int_delay(SYSCTL_HANDLER_ARGS);
static void em_add_int_delay_sysctl(struct adapter *, const char *,
const char *, struct em_int_delay_info *, int, int);
+static void em_intr(void *);
-/*
- * Fast interrupt handler and legacy ithread/polling modes are
- * mutually exclusive.
- */
#ifdef DEVICE_POLLING
static poll_handler_t em_poll;
-static void em_intr(void *);
-#else
-static void em_intr_fast(void *);
-static void em_add_int_process_limit(struct adapter *, const char *,
- const char *, int *, int);
-static void em_handle_rxtx(void *context, int pending);
-static void em_handle_link(void *context, int pending);
#endif
/*********************************************************************
@@ -308,7 +301,7 @@ MODULE_DEPEND(em, ether, 1, 1, 1);
#define E1000_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000)
#define E1000_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024)
-#define M_TSO_LEN 66
+#define M_TSO_LEN 66 /* mbuf with just hdr and TSO pkthdr */
static int em_tx_int_delay_dflt = E1000_TICKS_TO_USECS(EM_TIDV);
static int em_rx_int_delay_dflt = E1000_TICKS_TO_USECS(EM_RDTR);
@@ -325,10 +318,6 @@ TUNABLE_INT("hw.em.rx_abs_int_delay", &em_rx_abs_int_delay_dflt);
TUNABLE_INT("hw.em.rxd", &em_rxd);
TUNABLE_INT("hw.em.txd", &em_txd);
TUNABLE_INT("hw.em.smart_pwr_down", &em_smart_pwr_down);
-#ifndef DEVICE_POLLING
-static int em_rx_process_limit = 100;
-TUNABLE_INT("hw.em.rx_process_limit", &em_rx_process_limit);
-#endif
/*********************************************************************
* Device identification routine
@@ -441,13 +430,6 @@ em_attach(device_t dev)
em_tx_abs_int_delay_dflt);
}
-#ifndef DEVICE_POLLING
- /* Sysctls for limiting the amount of work done in the taskqueue */
- em_add_int_process_limit(adapter, "rx_processing_limit",
- "max number of rx packets to process", &adapter->rx_process_limit,
- em_rx_process_limit);
-#endif
-
/*
* Validate number of transmit and receive descriptors. It
* must not exceed hardware maximum, and must be multiple
@@ -490,9 +472,11 @@ em_attach(device_t dev)
* Set the max frame size assuming standard ethernet
* sized frames.
*/
- adapter->hw.max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN;
+ adapter->hw.max_frame_size =
+ ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN;
- adapter->hw.min_frame_size = MINIMUM_ETHERNET_PACKET_SIZE + ETHER_CRC_LEN;
+ adapter->hw.min_frame_size =
+ MINIMUM_ETHERNET_PACKET_SIZE + ETHER_CRC_LEN;
/*
* This controls when hardware reports transmit completion
@@ -551,11 +535,23 @@ em_attach(device_t dev)
goto err_hw_init;
}
+ /* Allocate transmit descriptors and buffers */
+ if (em_allocate_transmit_structures(adapter)) {
+ device_printf(dev, "Could not setup transmit structures\n");
+ error = ENOMEM;
+ goto err_tx_struct;
+ }
+
+ /* Allocate receive descriptors and buffers */
+ if (em_allocate_receive_structures(adapter)) {
+ device_printf(dev, "Could not setup receive structures\n");
+ error = ENOMEM;
+ goto err_rx_struct;
+ }
+
/* Setup OS specific network interface */
em_setup_interface(dev, adapter);
- em_allocate_intr(adapter);
-
/* Initialize statistics */
em_clear_hw_cntrs(&adapter->hw);
em_update_stats_counters(adapter);
@@ -569,7 +565,8 @@ em_attach(device_t dev)
/* Identify 82544 on PCIX */
em_get_bus_info(&adapter->hw);
- if(adapter->hw.bus_type == em_bus_type_pcix && adapter->hw.mac_type == em_82544)
+ if (adapter->hw.bus_type == em_bus_type_pcix &&
+ adapter->hw.mac_type == em_82544)
adapter->pcix_82544 = TRUE;
else
adapter->pcix_82544 = FALSE;
@@ -578,13 +575,15 @@ em_attach(device_t dev)
return (0);
+err_rx_struct:
+ em_free_transmit_structures(adapter);
err_hw_init:
+err_tx_struct:
em_dma_free(adapter, &adapter->rxdma);
err_rx_desc:
em_dma_free(adapter, &adapter->txdma);
err_tx_desc:
err_pci:
- em_free_intr(adapter);
em_free_pci_resources(adapter);
EM_LOCK_DESTROY(adapter);
@@ -614,7 +613,6 @@ em_detach(device_t dev)
ether_poll_deregister(ifp);
#endif
- em_free_intr(adapter);
EM_LOCK(adapter);
adapter->in_detach = 1;
em_stop(adapter);
@@ -626,6 +624,9 @@ em_detach(device_t dev)
bus_generic_detach(dev);
if_free(ifp);
+ em_free_transmit_structures(adapter);
+ em_free_receive_structures(adapter);
+
/* Free Transmit Descriptor ring */
if (adapter->tx_desc_base) {
em_dma_free(adapter, &adapter->txdma);
@@ -806,8 +807,8 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
* 82573 only supports jumbo frames
* if ASPM is disabled.
*/
- em_read_eeprom(&adapter->hw, EEPROM_INIT_3GIO_3, 1,
- &eeprom_data);
+ em_read_eeprom(&adapter->hw,
+ EEPROM_INIT_3GIO_3, 1, &eeprom_data);
if (eeprom_data & EEPROM_WORD1A_ASPM_MASK) {
max_frame_size = ETHER_MAX_LEN;
break;
@@ -834,13 +835,14 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
ifp->if_mtu = ifr->ifr_mtu;
adapter->hw.max_frame_size =
- ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
+ ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
em_init_locked(adapter);
EM_UNLOCK(adapter);
break;
}
case SIOCSIFFLAGS:
- IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface Flags)");
+ IOCTL_DEBUGOUT("ioctl rcv'd:\
+ SIOCSIFFLAGS (Set Interface Flags)");
EM_LOCK(adapter);
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
@@ -877,8 +879,15 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
break;
case SIOCSIFMEDIA:
+ /* Check SOL/IDER usage */
+ if (em_check_phy_reset_block(&adapter->hw)) {
+ device_printf(adapter->dev, "Media change is"
+ "blocked due to SOL/IDER session.\n");
+ break;
+ }
case SIOCGIFMEDIA:
- IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFMEDIA (Get/Set Interface Media)");
+ IOCTL_DEBUGOUT("ioctl rcv'd: \
+ SIOCxIFMEDIA (Get/Set Interface Media)");
error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);
break;
case SIOCSIFCAP:
@@ -912,17 +921,12 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
ifp->if_capenable ^= IFCAP_HWCSUM;
reinit = 1;
}
- if (mask & IFCAP_TSO4) {
- ifp->if_capenable ^= IFCAP_TSO4;
- reinit = 1;
- }
if (mask & IFCAP_VLAN_HWTAGGING) {
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
reinit = 1;
}
if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING))
em_init(adapter);
- VLAN_CAPABILITIES(ifp);
break;
}
default:
@@ -955,18 +959,6 @@ em_watchdog(struct ifnet *ifp)
return;
}
- /*
- * Reclaim first as there is a possibility of losing Tx completion
- * interrupts. Possible cause of missing Tx completion interrupts
- * comes from Tx interrupt moderation mechanism(delayed interrupts)
- * or chipset bug.
- */
- em_txeof(adapter);
- if (adapter->num_tx_desc_avail == adapter->num_tx_desc) {
- EM_UNLOCK(adapter);
- return;
- }
-
if (em_check_for_link(&adapter->hw) == 0)
device_printf(adapter->dev, "watchdog timeout -- resetting\n");
@@ -1021,15 +1013,16 @@ em_init_locked(struct adapter *adapter)
pba = E1000_PBA_30K; /* 30K for Rx, 10K for Tx */
adapter->tx_fifo_head = 0;
adapter->tx_head_addr = pba << EM_TX_HEAD_ADDR_SHIFT;
- adapter->tx_fifo_size = (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT;
+ 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:
@@ -1047,7 +1040,8 @@ em_init_locked(struct adapter *adapter)
E1000_WRITE_REG(&adapter->hw, PBA, pba);
/* Get the latest mac address, User can use a LAA */
- bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac_addr, ETHER_ADDR_LEN);
+ bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac_addr,
+ ETHER_ADDR_LEN);
/* Initialize the hardware */
if (em_hardware_init(adapter)) {
@@ -1059,24 +1053,19 @@ em_init_locked(struct adapter *adapter)
if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
em_enable_vlans(adapter);
+ /* Set hardware offload abilities */
ifp->if_hwassist = 0;
if (adapter->hw.mac_type >= em_82543) {
if (ifp->if_capenable & IFCAP_TXCSUM)
- ifp->if_hwassist = EM_CHECKSUM_FEATURES;
- /*
- * em_setup_transmit_structures() will behave differently
- * based on the state of TSO.
- */
+ ifp->if_hwassist |= EM_CHECKSUM_FEATURES;
+#ifdef EM_TSO
if (ifp->if_capenable & IFCAP_TSO)
ifp->if_hwassist |= EM_TCPSEG_FEATURES;
+#endif
}
/* Prepare transmit descriptors and buffers */
- if (em_setup_transmit_structures(adapter)) {
- device_printf(dev, "Could not setup transmit structures\n");
- em_stop(adapter);
- return;
- }
+ em_setup_transmit_structures(adapter);
em_initialize_transmit_unit(adapter);
/* Setup Multicast table */
@@ -1098,6 +1087,7 @@ em_init_locked(struct adapter *adapter)
callout_reset(&adapter->timer, hz, em_local_timer, adapter);
em_clear_hw_cntrs(&adapter->hw);
+
#ifdef DEVICE_POLLING
/*
* Only enable interrupts if we are not polling, make sure
@@ -1125,11 +1115,6 @@ em_init(void *arg)
#ifdef DEVICE_POLLING
-/*********************************************************************
- *
- * Legacy polling routine
- *
- *********************************************************************/
static void
em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
@@ -1149,7 +1134,8 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
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);
+ callout_reset(&adapter->timer, hz,
+ em_local_timer, adapter);
}
}
em_rxeof(adapter, count);
@@ -1159,10 +1145,11 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
em_start_locked(ifp);
EM_UNLOCK(adapter);
}
+#endif /* DEVICE_POLLING */
/*********************************************************************
*
- * Legacy Interrupt Service routine
+ * Interrupt Service routine
*
*********************************************************************/
static void
@@ -1176,10 +1163,12 @@ em_intr(void *arg)
ifp = adapter->ifp;
+#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING) {
EM_UNLOCK(adapter);
return;
}
+#endif /* DEVICE_POLLING */
for (;;) {
reg_icr = E1000_READ_REG(&adapter->hw, ICR);
@@ -1209,7 +1198,8 @@ em_intr(void *arg)
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);
+ callout_reset(&adapter->timer, hz,
+ em_local_timer, adapter);
}
if (reg_icr & E1000_ICR_RXO)
@@ -1223,103 +1213,6 @@ em_intr(void *arg)
EM_UNLOCK(adapter);
}
-#else /* if not DEVICE_POLLING, then fast interrupt routines only */
-
-static void
-em_handle_link(void *context, int pending)
-{
- struct adapter *adapter = context;
- struct ifnet *ifp;
-
- ifp = adapter->ifp;
-
- EM_LOCK(adapter);
-
- 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);
- EM_UNLOCK(adapter);
-}
-
-static void
-em_handle_rxtx(void *context, int pending)
-{
- struct adapter *adapter = context;
- struct ifnet *ifp;
-
- NET_LOCK_GIANT();
- ifp = adapter->ifp;
-
- /*
- * TODO:
- * It should be possible to run the tx clean loop without the lock.
- */
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if (em_rxeof(adapter, adapter->rx_process_limit) != 0)
- taskqueue_enqueue(adapter->tq, &adapter->rxtx_task);
- EM_LOCK(adapter);
- em_txeof(adapter);
-
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- em_start_locked(ifp);
- EM_UNLOCK(adapter);
- }
-
- em_enable_intr(adapter);
- NET_UNLOCK_GIANT();
-}
-
-/*********************************************************************
- *
- * Fast Interrupt Service routine
- *
- *********************************************************************/
-static void
-em_intr_fast(void *arg)
-{
- struct adapter *adapter = arg;
- struct ifnet *ifp;
- uint32_t reg_icr;
-
- ifp = adapter->ifp;
-
- reg_icr = E1000_READ_REG(&adapter->hw, ICR);
-
- /* Hot eject? */
- if (reg_icr == 0xffffffff)
- return;
-
- /* Definitely not our interrupt. */
- if (reg_icr == 0x0)
- return;
-
- /*
- * Starting with the 82571 chip, bit 31 should be used to
- * determine whether the interrupt belongs to us.
- */
- if (adapter->hw.mac_type >= em_82571 &&
- (reg_icr & E1000_ICR_INT_ASSERTED) == 0)
- return;
-
- /*
- * Mask interrupts until the taskqueue is finished running. This is
- * cheap, just assume that it is needed. This also works around the
- * MSI message reordering errata on certain systems.
- */
- em_disable_intr(adapter);
- taskqueue_enqueue(adapter->tq, &adapter->rxtx_task);
-
- /* Link status change */
- if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))
- taskqueue_enqueue(taskqueue_fast, &adapter->link_task);
-
- if (reg_icr & E1000_ICR_RXO)
- adapter->rx_overruns++;
-}
-#endif /* ! DEVICE_POLLING */
-
/*********************************************************************
*
* Media Ioctl callback
@@ -1332,6 +1225,7 @@ static void
em_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct adapter *adapter = ifp->if_softc;
+ u_char fiber_type = IFM_1000_SX;
INIT_DEBUGOUT("em_media_status: begin");
@@ -1352,9 +1246,8 @@ em_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
if ((adapter->hw.media_type == em_media_type_fiber) ||
(adapter->hw.media_type == em_media_type_internal_serdes)) {
if (adapter->hw.mac_type == em_82545)
- ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
- else
- ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
+ fiber_type = IFM_1000_LX;
+ ifmr->ifm_active |= fiber_type | IFM_FDX;
} else {
switch (adapter->link_speed) {
case 10:
@@ -1449,43 +1342,54 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
struct ifnet *ifp = adapter->ifp;
bus_dma_segment_t segs[EM_MAX_SCATTER];
bus_dmamap_t map;
- struct em_buffer *tx_buffer, *tx_buffer_last;
+ struct em_buffer *tx_buffer, *tx_buffer_mapped;
struct em_tx_desc *current_tx_desc;
struct mbuf *m_head;
+ struct m_tag *mtag;
uint32_t txd_upper, txd_lower, txd_used, txd_saved;
- int nsegs, i, j;
+ int nsegs, i, j, first, last = 0;
int error, do_tso, tso_desc = 0;
m_head = *m_headp;
current_tx_desc = NULL;
txd_upper = txd_lower = txd_used = txd_saved = 0;
+#ifdef EM_TSO
do_tso = ((m_head->m_pkthdr.csum_flags & CSUM_TSO) != 0);
+#else
+ do_tso = 0;
+#endif
- /*
- * Force a cleanup if number of TX descriptors
- * available hits the threshold.
- */
+ /*
+ * Force a cleanup if number of TX descriptors
+ * available hits the threshold
+ */
if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) {
em_txeof(adapter);
if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) {
adapter->no_tx_desc_avail1++;
- return (ENOBUFS);
+ return(ENOBUFS);
}
- }
+ }
/*
- * When operating in promiscuous mode, hardware stripping of the
- * VLAN tag on receive is disabled. This should not prevent us
- * from doing hardware insertion of the VLAN tag here as that
- * is controlled by the dma descriptor flags and not the receive
- * tag strip setting. Unfortunatly this hardware switches the
- * VLAN encapsulation type from 802.1q to ISL when stripping om
- * receive is disabled. This means we have to add the vlan
- * encapsulation here in the driver, since it will have come down
- * from the VLAN layer with a tag instead of a VLAN header.
+ * 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.
*/
- if ((m_head->m_flags & M_VLANTAG) && adapter->em_insert_vlan_header) {
+ first = adapter->next_avail_tx_desc;
+
+ /* Find out if we are in vlan mode */
+ mtag = VLAN_OUTPUT_TAG(ifp, m_head);
+
+ /*
+ * When operating in promiscuous mode, hardware encapsulation for
+ * packets is disabled. This means we have to add the vlan
+ * encapsulation in the driver, since it will have come down from the
+ * VLAN layer with a tag instead of a VLAN header.
+ */
+ if (mtag != NULL && adapter->em_insert_vlan_header) {
struct ether_vlan_header *evl;
struct ether_header eh;
@@ -1509,57 +1413,46 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
bcopy(&eh, evl, sizeof(*evl));
evl->evl_proto = evl->evl_encap_proto;
evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
- evl->evl_tag = htons(m_head->m_pkthdr.ether_vtag);
+ evl->evl_tag = htons(VLAN_TAG_VALUE(mtag));
+ m_tag_delete(m_head, mtag);
+ mtag = NULL;
*m_headp = m_head;
}
/*
- * TSO workaround:
- * If an mbuf contains only the IP and TCP header we have
- * to pull 4 bytes of data into it.
+ * TSO workaround:
+ * If an mbuf is only header we need
+ * to pull 4 bytes of data into it.
*/
if (do_tso && (m_head->m_len <= M_TSO_LEN)) {
m_head = m_pullup(m_head, M_TSO_LEN + 4);
*m_headp = m_head;
- if (m_head == NULL) {
+ if (m_head == NULL)
return (ENOBUFS);
- }
}
- /*
- * Map the packet for DMA.
- */
- tx_buffer = &adapter->tx_buffer_area[adapter->next_avail_tx_desc];
- tx_buffer_last = tx_buffer;
+ /*
+ * Map the packet for DMA.
+ */
+ tx_buffer = &adapter->tx_buffer_area[first];
+ tx_buffer_mapped = tx_buffer;
map = tx_buffer->map;
-
- error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, *m_headp, segs,
- &nsegs, BUS_DMA_NOWAIT);
-
- /*
- * There are two types of errors we can (try) to handle:
- * - EFBIG means the mbuf chain was too long and bus_dma ran
- * out of segments. Defragment the mbuf chain and try again.
- * - ENOMEM means bus_dma could not obtain enough bounce buffers
- * at this point in time. Defer sending and try again later.
- * All other errors, in particular EINVAL, are fatal and prevent the
- * mbuf chain from ever going through. Drop it and report error.
- */
+ error = bus_dmamap_load_mbuf_sg(adapter->txtag, tx_buffer->map,
+ *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
if (error == EFBIG) {
struct mbuf *m;
m = m_defrag(*m_headp, M_DONTWAIT);
if (m == NULL) {
- /* Assume m_defrag(9) used only m_get(9). */
adapter->mbuf_alloc_failed++;
m_freem(*m_headp);
*m_headp = NULL;
return (ENOBUFS);
}
*m_headp = m;
-
- error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, *m_headp,
- segs, &nsegs, BUS_DMA_NOWAIT);
+ /* Try it again */
+ error = bus_dmamap_load_mbuf_sg(adapter->txtag, tx_buffer->map,
+ *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
if (error == ENOMEM) {
adapter->no_tx_dma_setup++;
@@ -1592,36 +1485,36 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
adapter->tx_tso = FALSE;
}
- if (nsegs > adapter->num_tx_desc_avail - 2) {
- adapter->no_tx_desc_avail2++;
- bus_dmamap_unload(adapter->txtag, map);
- return (ENOBUFS);
- }
- m_head = *m_headp;
+ if (nsegs > (adapter->num_tx_desc_avail - 2)) {
+ adapter->no_tx_desc_avail2++;
+ error = ENOBUFS;
+ goto encap_fail;
+ }
/* Do hardware assists */
- if (ifp->if_hwassist) {
- if (do_tso &&
- em_tso_setup(adapter, m_head, &txd_upper, &txd_lower)) {
+ if (ifp->if_hwassist > 0) {
+#ifdef EM_TSO
+ if (em_tso_setup(adapter, m_head, &txd_upper, &txd_lower)) {
/* we need to make a final sentinel transmit desc */
tso_desc = TRUE;
} else
+#endif
em_transmit_checksum_setup(adapter, m_head,
&txd_upper, &txd_lower);
}
i = adapter->next_avail_tx_desc;
- if (adapter->pcix_82544)
+ if (adapter->pcix_82544)
txd_saved = i;
+ /* Set up our transmit descriptors */
for (j = 0; j < nsegs; j++) {
bus_size_t seg_len;
bus_addr_t seg_addr;
- /* If adapter is 82544 and on PCIX bus. */
+ /* If adapter is 82544 and on PCIX bus */
if(adapter->pcix_82544) {
DESC_ARRAY desc_array;
uint32_t array_elements, counter;
-
/*
* Check the Address and Length combination and
* split the data accordingly
@@ -1632,23 +1525,25 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
if (txd_used == adapter->num_tx_desc_avail) {
adapter->next_avail_tx_desc = txd_saved;
adapter->no_tx_desc_avail2++;
- bus_dmamap_unload(adapter->txtag, map);
- return (ENOBUFS);
+ error = ENOBUFS;
+ goto encap_fail;
}
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;
-
+ i = 0;
tx_buffer->m_head = NULL;
+ tx_buffer->next_eop = -1;
txd_used++;
- }
+ }
} else {
tx_buffer = &adapter->tx_buffer_area[i];
current_tx_desc = &adapter->tx_desc_base[i];
@@ -1668,7 +1563,7 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
htole32(txd_upper);
if (++i == adapter->num_tx_desc)
i = 0;
- /* Now make the sentinel */
+ /* Now make the sentinel */
++txd_used; /* using an extra txd */
current_tx_desc = &adapter->tx_desc_base[i];
tx_buffer = &adapter->tx_buffer_area[i];
@@ -1678,6 +1573,7 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
adapter->txd_cmd | txd_lower | 4);
current_tx_desc->upper.data =
htole32(txd_upper);
+ last = i;
if (++i == adapter->num_tx_desc)
i = 0;
} else {
@@ -1686,10 +1582,12 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
adapter->txd_cmd | txd_lower | seg_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;
}
}
@@ -1702,24 +1600,33 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
adapter->num_tx_desc_avail -= txd_used;
}
- if (m_head->m_flags & M_VLANTAG) {
+ if (mtag != NULL) {
/* Set the vlan id. */
current_tx_desc->upper.fields.special =
- htole16(m_head->m_pkthdr.ether_vtag);
-
- /* Tell hardware to add tag. */
- current_tx_desc->lower.data |= htole32(E1000_TXD_CMD_VLE);
- }
-
- tx_buffer->m_head = m_head;
- tx_buffer_last->map = tx_buffer->map;
+ htole16(VLAN_TAG_VALUE(mtag));
+ /* Tell hardware to add tag */
+ current_tx_desc->lower.data |=
+ htole32(E1000_TXD_CMD_VLE);
+ }
+
+ tx_buffer->m_head = m_head;
+ tx_buffer_mapped->map = tx_buffer->map;
tx_buffer->map = map;
- bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE);
-
+ 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);
/*
- * Last Descriptor of Packet needs End Of Packet (EOP).
+ * Keep track in the first buffer which
+ * descriptor will be written back
*/
- current_tx_desc->lower.data |= htole32(E1000_TXD_CMD_EOP);
+ tx_buffer = &adapter->tx_buffer_area[first];
+ tx_buffer->next_eop = last;
/*
* Advance the Transmit Descriptor Tail (Tdt), this tells the E1000
@@ -1727,17 +1634,21 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
*/
bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
if (adapter->hw.mac_type == em_82547 &&
adapter->link_duplex == HALF_DUPLEX)
em_82547_move_tail_locked(adapter);
else {
E1000_WRITE_REG(&adapter->hw, TDT, i);
if (adapter->hw.mac_type == em_82547)
- em_82547_update_fifo_head(adapter, m_head->m_pkthdr.len);
+ em_82547_update_fifo_head(adapter,
+ m_head->m_pkthdr.len);
}
return (0);
+
+encap_fail:
+ bus_dmamap_unload(adapter->txtag, tx_buffer->map);
+ return (error);
}
/*********************************************************************
@@ -1766,7 +1677,7 @@ em_82547_move_tail_locked(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) {
@@ -1829,14 +1740,16 @@ em_82547_update_fifo_head(struct adapter *adapter, int len)
static int
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))&&
+ 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);
@@ -1872,12 +1785,9 @@ em_set_promisc(struct adapter *adapter)
if (ifp->if_flags & IFF_PROMISC) {
reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
- /*
- * Disable VLAN stripping in promiscous mode.
+ /* Disable VLAN stripping in promiscous mode
* This enables bridging of vlan tagged frames to occur
- * and also allows vlan tags to be seen in tcpdump.
- * XXX: This is a bit bogus as tcpdump may be used
- * w/o promisc mode as well.
+ * and also allows vlan tags to be seen in tcpdump
*/
if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
em_disable_vlans(adapter);
@@ -2003,8 +1913,8 @@ em_update_link_status(struct adapter *adapter)
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);
+ em_get_speed_and_duplex(&adapter->hw,
+ &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) ||
@@ -2055,18 +1965,16 @@ em_stop(void *arg)
INIT_DEBUGOUT("em_stop: begin");
em_disable_intr(adapter);
- em_reset_hw(&adapter->hw);
callout_stop(&adapter->timer);
callout_stop(&adapter->tx_fifo_timer);
- em_free_transmit_structures(adapter);
- em_free_receive_structures(adapter);
/* Tell the stack that the interface is no longer active */
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ em_reset_hw(&adapter->hw);
}
-/********************************************************************
+/*********************************************************************
*
* Determine hardware revision.
*
@@ -2077,23 +1985,33 @@ em_identify_hardware(struct adapter *adapter)
device_t dev = adapter->dev;
/* Make sure our PCI config space has the necessary stuff set */
- pci_enable_busmaster(dev);
- pci_enable_io(dev, SYS_RES_MEMORY);
adapter->hw.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2);
+ if ((adapter->hw.pci_cmd_word & PCIM_CMD_BUSMASTEREN) == 0 &&
+ (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);
+ pci_write_config(dev, PCIR_COMMAND,
+ adapter->hw.pci_cmd_word, 2);
+ }
/* Save off the information about this board */
adapter->hw.vendor_id = pci_get_vendor(dev);
adapter->hw.device_id = pci_get_device(dev);
- adapter->hw.revision_id = pci_get_revid(dev);
- adapter->hw.subsystem_vendor_id = pci_get_subvendor(dev);
- adapter->hw.subsystem_id = pci_get_subdevice(dev);
+ adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1);
+ adapter->hw.subsystem_vendor_id =
+ pci_read_config(dev, PCIR_SUBVEND_0, 2);
+ adapter->hw.subsystem_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
/* Identify the MAC */
if (em_set_mac_type(&adapter->hw))
device_printf(dev, "Unknown MAC Type\n");
- if(adapter->hw.mac_type == em_82541 || adapter->hw.mac_type == em_82541_rev_2 ||
- adapter->hw.mac_type == em_82547 || adapter->hw.mac_type == em_82547_rev_2)
+ if (adapter->hw.mac_type == em_82541 ||
+ adapter->hw.mac_type == em_82541_rev_2 ||
+ adapter->hw.mac_type == em_82547 ||
+ adapter->hw.mac_type == em_82547_rev_2)
adapter->hw.phy_init_script = TRUE;
}
@@ -2111,36 +2029,38 @@ em_allocate_pci_resources(struct adapter *adapter)
return (ENXIO);
}
adapter->osdep.mem_bus_space_tag =
- rman_get_bustag(adapter->res_memory);
- adapter->osdep.mem_bus_space_handle = rman_get_bushandle(adapter->res_memory);
+ rman_get_bustag(adapter->res_memory);
+ adapter->osdep.mem_bus_space_handle =
+ rman_get_bushandle(adapter->res_memory);
adapter->hw.hw_addr = (uint8_t *)&adapter->osdep.mem_bus_space_handle;
if (adapter->hw.mac_type > em_82543) {
/* Figure our where our IO BAR is ? */
for (rid = PCIR_BAR(0); rid < PCIR_CIS;) {
val = pci_read_config(dev, rid, 4);
- if (E1000_BAR_TYPE(val) == E1000_BAR_TYPE_IO) {
+ if (EM_BAR_TYPE(val) == EM_BAR_TYPE_IO) {
adapter->io_rid = rid;
break;
}
rid += 4;
/* check for 64bit BAR */
- if (E1000_BAR_MEM_TYPE(val) == E1000_BAR_MEM_TYPE_64BIT)
+ 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);
+ adapter->res_ioport = bus_alloc_resource_any(dev,
+ SYS_RES_IOPORT, &adapter->io_rid, RF_ACTIVE);
if (adapter->res_ioport == NULL) {
device_printf(dev, "Unable to allocate bus resource: "
"ioport\n");
return (ENXIO);
}
adapter->hw.io_base = 0;
- adapter->osdep.io_bus_space_tag = rman_get_bustag(adapter->res_ioport);
+ adapter->osdep.io_bus_space_tag =
+ rman_get_bustag(adapter->res_ioport);
adapter->osdep.io_bus_space_handle =
rman_get_bushandle(adapter->res_ioport);
}
@@ -2148,106 +2068,58 @@ em_allocate_pci_resources(struct adapter *adapter)
/* 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);
- adapter->osdep.flash_bus_space_tag = rman_get_bustag(adapter->flash_mem);
+ adapter->flash_mem = bus_alloc_resource_any(dev,
+ SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ adapter->osdep.flash_bus_space_tag =
+ rman_get_bustag(adapter->flash_mem);
adapter->osdep.flash_bus_space_handle =
rman_get_bushandle(adapter->flash_mem);
}
rid = 0x0;
- adapter->res_interrupt = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
+ adapter->res_interrupt = bus_alloc_resource_any(dev,
+ SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
if (adapter->res_interrupt == NULL) {
device_printf(dev, "Unable to allocate bus resource: "
"interrupt\n");
return (ENXIO);
}
+ if (bus_setup_intr(dev, adapter->res_interrupt,
+ INTR_TYPE_NET | INTR_MPSAFE,
+ (void (*)(void *)) em_intr, adapter,
+ &adapter->int_handler_tag)) {
+ device_printf(dev, "Error registering interrupt handler!\n");
+ return(ENXIO);
+ }
adapter->hw.back = &adapter->osdep;
return (0);
}
-int
-em_allocate_intr(struct adapter *adapter)
-{
- device_t dev = adapter->dev;
- int error;
-
- /* Manually turn off all interrupts */
- E1000_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
-
-#ifdef DEVICE_POLLING
- if (adapter->int_handler_tag == NULL && (error = bus_setup_intr(dev,
- adapter->res_interrupt, INTR_TYPE_NET | INTR_MPSAFE, em_intr, adapter,
- &adapter->int_handler_tag)) != 0) {
- device_printf(dev, "Failed to register interrupt handler");
- return (error);
- }
-#else
- /*
- * Try allocating a fast interrupt and the associated deferred
- * processing contexts.
- */
- TASK_INIT(&adapter->rxtx_task, 0, em_handle_rxtx, adapter);
- TASK_INIT(&adapter->link_task, 0, em_handle_link, adapter);
- adapter->tq = taskqueue_create_fast("em_taskq", M_NOWAIT,
- taskqueue_thread_enqueue, &adapter->tq);
- taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq",
- device_get_nameunit(adapter->dev));
- if ((error = bus_setup_intr(dev, adapter->res_interrupt,
- INTR_TYPE_NET | INTR_FAST, em_intr_fast, adapter,
- &adapter->int_handler_tag)) != 0) {
- device_printf(dev, "Failed to register fast interrupt "
- "handler: %d\n", error);
- taskqueue_free(adapter->tq);
- adapter->tq = NULL;
- return (error);
- }
-#endif
-
- em_enable_intr(adapter);
- return (0);
-}
-
-static void
-em_free_intr(struct adapter *adapter)
-{
- device_t dev = adapter->dev;
-
- if (adapter->int_handler_tag != NULL) {
- bus_teardown_intr(dev, adapter->res_interrupt, adapter->int_handler_tag);
- adapter->int_handler_tag = NULL;
- }
- if (adapter->tq != NULL) {
- taskqueue_drain(adapter->tq, &adapter->rxtx_task);
- taskqueue_drain(taskqueue_fast, &adapter->link_task);
- taskqueue_free(adapter->tq);
- adapter->tq = NULL;
- }
-}
-
static void
em_free_pci_resources(struct adapter *adapter)
{
device_t dev = adapter->dev;
- if (adapter->res_interrupt != NULL)
- bus_release_resource(dev, SYS_RES_IRQ, 0, adapter->res_interrupt);
+ if (adapter->res_interrupt != NULL) {
+ bus_teardown_intr(dev, adapter->res_interrupt,
+ adapter->int_handler_tag);
+ bus_release_resource(dev, SYS_RES_IRQ,
+ 0, adapter->res_interrupt);
+ }
if (adapter->res_memory != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0),
- adapter->res_memory);
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ PCIR_BAR(0), adapter->res_memory);
if (adapter->flash_mem != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY, EM_FLASH,
- adapter->flash_mem);
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ EM_FLASH, adapter->flash_mem);
if (adapter->res_ioport != NULL)
- bus_release_resource(dev, SYS_RES_IOPORT, adapter->io_rid,
- adapter->res_ioport);
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ adapter->io_rid, adapter->res_ioport);
}
/*********************************************************************
@@ -2278,20 +2150,22 @@ em_hardware_init(struct adapter *adapter)
}
if (em_read_part_num(&adapter->hw, &(adapter->part_num)) < 0) {
- device_printf(dev, "EEPROM read error while reading part "
- "number\n");
+ device_printf(dev, "EEPROM read error "
+ "reading part number\n");
return (EIO);
}
/* 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)) {
+ 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. */
- em_read_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT, &phy_tmp);
+ em_read_phy_reg(&adapter->hw,
+ IGP02E1000_PHY_POWER_MGMT, &phy_tmp);
phy_tmp &= ~IGP02E1000_PM_SPD;
- em_write_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT, phy_tmp);
+ em_write_phy_reg(&adapter->hw,
+ IGP02E1000_PHY_POWER_MGMT, phy_tmp);
}
/*
@@ -2318,7 +2192,7 @@ em_hardware_init(struct adapter *adapter)
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(dev, "Hardware Initialization Failed");
@@ -2339,6 +2213,8 @@ static void
em_setup_interface(device_t dev, struct adapter *adapter)
{
struct ifnet *ifp;
+ u_char fiber_type = IFM_1000_SX; /* default type */
+
INIT_DEBUGOUT("em_setup_interface: begin");
ifp = adapter->ifp = if_alloc(IFT_ETHER);
@@ -2361,16 +2237,18 @@ em_setup_interface(device_t dev, struct adapter *adapter)
ifp->if_capabilities = ifp->if_capenable = 0;
if (adapter->hw.mac_type >= em_82543) {
- ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
- ifp->if_capenable |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
+ ifp->if_capabilities |= IFCAP_HWCSUM;
+ ifp->if_capenable |= IFCAP_HWCSUM;
}
+#ifdef EM_TSO
/* Enable TSO if available */
if ((adapter->hw.mac_type > em_82544) &&
- (adapter->hw.mac_type != em_82547)) {
- ifp->if_capabilities |= IFCAP_TSO4;
- ifp->if_capenable |= IFCAP_TSO4;
+ (adapter->hw.mac_type != em_82547)) {
+ ifp->if_capabilities |= IFCAP_TSO;
+ ifp->if_capenable |= IFCAP_TSO;
}
+#endif
/*
* Tell the upper layer(s) we support long frames.
@@ -2387,16 +2265,14 @@ em_setup_interface(device_t dev, struct adapter *adapter)
* Specify the media types supported by this adapter and register
* callbacks to update media and link information
*/
- ifmedia_init(&adapter->media, IFM_IMASK, em_media_change,
- em_media_status);
+ ifmedia_init(&adapter->media, IFM_IMASK,
+ em_media_change, em_media_status);
if ((adapter->hw.media_type == em_media_type_fiber) ||
(adapter->hw.media_type == em_media_type_internal_serdes)) {
- u_char fiber_type = IFM_1000_SX; /* default type; */
-
if (adapter->hw.mac_type == em_82545)
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 | IFM_FDX,
+ 0, NULL);
ifmedia_add(&adapter->media, IFM_ETHER | fiber_type, 0, NULL);
} else {
ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T, 0, NULL);
@@ -2490,12 +2366,12 @@ em_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
}
static int
-em_dma_malloc(struct adapter *adapter, bus_size_t size, struct em_dma_alloc *dma,
- int mapflags)
+em_dma_malloc(struct adapter *adapter, bus_size_t size,
+ struct em_dma_alloc *dma, int mapflags)
{
int error;
- error = bus_dma_tag_create(bus_get_dma_tag(adapter->dev), /* parent */
+ error = bus_dma_tag_create(NULL, /* parent */
EM_DBA_ALIGN, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
@@ -2508,7 +2384,8 @@ em_dma_malloc(struct adapter *adapter, bus_size_t size, struct em_dma_alloc *dma
NULL, /* lockarg */
&dma->dma_tag);
if (error) {
- device_printf(adapter->dev, "%s: bus_dma_tag_create failed: %d\n",
+ device_printf(adapter->dev,
+ "%s: bus_dma_tag_create failed: %d\n",
__func__, error);
goto fail_0;
}
@@ -2516,7 +2393,8 @@ em_dma_malloc(struct adapter *adapter, bus_size_t size, struct em_dma_alloc *dma
error = bus_dmamem_alloc(dma->dma_tag, (void**) &dma->dma_vaddr,
BUS_DMA_NOWAIT, &dma->dma_map);
if (error) {
- device_printf(adapter->dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n",
+ device_printf(adapter->dev,
+ "%s: bus_dmamem_alloc(%ju) failed: %d\n",
__func__, (uintmax_t)size, error);
goto fail_2;
}
@@ -2525,7 +2403,8 @@ em_dma_malloc(struct adapter *adapter, bus_size_t size, struct em_dma_alloc *dma
error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
size, em_dmamap_cb, &dma->dma_paddr, mapflags | BUS_DMA_NOWAIT);
if (error || dma->dma_paddr == 0) {
- device_printf(adapter->dev, "%s: bus_dmamap_load failed: %d\n",
+ device_printf(adapter->dev,
+ "%s: bus_dmamap_load failed: %d\n",
__func__, error);
goto fail_3;
}
@@ -2570,44 +2449,21 @@ em_dma_free(struct adapter *adapter, struct em_dma_alloc *dma)
static int
em_allocate_transmit_structures(struct adapter *adapter)
{
- adapter->tx_buffer_area = malloc(sizeof(struct em_buffer) *
- adapter->num_tx_desc, M_DEVBUF, M_NOWAIT);
- if (adapter->tx_buffer_area == NULL) {
- device_printf(adapter->dev, "Unable to allocate tx_buffer memory\n");
- return (ENOMEM);
- }
-
- bzero(adapter->tx_buffer_area, sizeof(struct em_buffer) * adapter->num_tx_desc);
-
- return (0);
-}
-
-/*********************************************************************
- *
- * Allocate and initialize transmit structures.
- *
- **********************************************************************/
-static int
-em_setup_transmit_structures(struct adapter *adapter)
-{
- struct ifnet *ifp = adapter->ifp;
device_t dev = adapter->dev;
struct em_buffer *tx_buffer;
bus_size_t size, segsize;
int error, i;
+#ifdef EM_TSO
+ size = EM_TSO_SIZE;
+ segsize = PAGE_SIZE;
+#else
+ segsize = size = roundup2(adapter->hw.max_frame_size, MCLBYTES);
+#endif
/*
* Setup DMA descriptor areas.
*/
- segsize = size = roundup2(adapter->hw.max_frame_size, MCLBYTES);
-
- /* Overrides for TSO - want large sizes */
- if (ifp->if_hwassist & EM_TCPSEG_FEATURES) {
- size = EM_TSO_SIZE;
- segsize = PAGE_SIZE;
- }
-
- if ((error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
+ if ((error = bus_dma_tag_create(NULL, /* parent */
1, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
@@ -2623,10 +2479,14 @@ em_setup_transmit_structures(struct adapter *adapter)
goto fail;
}
- if ((error = em_allocate_transmit_structures(adapter)) != 0)
+ adapter->tx_buffer_area = malloc(sizeof(struct em_buffer) *
+ adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (adapter->tx_buffer_area == NULL) {
+ device_printf(dev, "Unable to allocate tx_buffer memory\n");
+ error = ENOMEM;
goto fail;
+ }
- 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);
@@ -2637,8 +2497,41 @@ em_setup_transmit_structures(struct adapter *adapter)
tx_buffer++;
}
+ return (0);
+
+fail:
+ em_free_transmit_structures(adapter);
+ return (error);
+}
+
+/*********************************************************************
+ *
+ * Initialize transmit structures.
+ *
+ **********************************************************************/
+static void
+em_setup_transmit_structures(struct adapter *adapter)
+{
+ struct em_buffer *tx_buffer;
+ int i;
+
+ bzero(adapter->tx_desc_base,
+ (sizeof(struct em_tx_desc)) * adapter->num_tx_desc);
+
adapter->next_avail_tx_desc = 0;
- adapter->oldest_used_tx_desc = 0;
+ adapter->next_tx_to_clean = 0;
+
+ /* Free any existing tx buffers. */
+ tx_buffer = adapter->tx_buffer_area;
+ for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) {
+ if (tx_buffer->m_head != NULL) {
+ 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;
+ }
+ }
/* Set number of descriptors available */
adapter->num_tx_desc_avail = adapter->num_tx_desc;
@@ -2647,12 +2540,6 @@ em_setup_transmit_structures(struct adapter *adapter)
adapter->active_checksum_context = OFFLOAD_NONE;
bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
- return (0);
-
-fail:
- em_free_transmit_structures(adapter);
- return (error);
}
/*********************************************************************
@@ -2663,8 +2550,7 @@ fail:
static void
em_initialize_transmit_unit(struct adapter *adapter)
{
- uint32_t reg_tctl, reg_tarc;
- uint32_t reg_tipg = 0;
+ uint32_t reg_tctl, reg_tipg = 0;
uint64_t bus_addr;
INIT_DEBUGOUT("em_initialize_transmit_unit: begin");
@@ -2679,8 +2565,8 @@ 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", E1000_READ_REG(&adapter->hw, TDBAL),
+ HW_DEBUGOUT2("Base = %x, Length = %x\n",
+ E1000_READ_REG(&adapter->hw, TDBAL),
E1000_READ_REG(&adapter->hw, TDLEN));
/* Set the default values for the Tx Inter Packet Gap timer */
@@ -2709,25 +2595,8 @@ 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)
- 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);
- }
+ E1000_WRITE_REG(&adapter->hw, TADV,
+ adapter->tx_abs_int_delay.value);
/* Program the Transmit Control Register */
reg_tctl = E1000_TCTL_PSP | E1000_TCTL_EN |
@@ -2742,8 +2611,8 @@ em_initialize_transmit_unit(struct adapter *adapter)
/* 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;
@@ -2805,127 +2674,69 @@ em_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp,
{
struct em_context_desc *TXD;
struct em_buffer *tx_buffer;
- struct ether_vlan_header *eh;
- struct ip *ip;
- struct ip6_hdr *ip6;
- struct tcp_hdr *th;
- int curr_txd, ehdrlen, hdr_len, ip_hlen;
- uint32_t cmd = 0;
- uint16_t etype;
- uint8_t ipproto;
-
- /* Setup checksum offload context. */
- curr_txd = adapter->next_avail_tx_desc;
- tx_buffer = &adapter->tx_buffer_area[curr_txd];
- TXD = (struct em_context_desc *) &adapter->tx_desc_base[curr_txd];
+ int curr_txd;
- *txd_lower = E1000_TXD_CMD_DEXT | /* Extended descr type */
- E1000_TXD_DTYP_D; /* Data descr */
+ if (mp->m_pkthdr.csum_flags) {
- /*
- * Determine where frame payload starts.
- * Jump over vlan headers if already present,
- * helpful for QinQ too.
- */
- eh = mtod(mp, struct ether_vlan_header *);
- if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
- etype = ntohs(eh->evl_proto);
- ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
+ if (mp->m_pkthdr.csum_flags & CSUM_TCP) {
+ *txd_upper = E1000_TXD_POPTS_TXSM << 8;
+ *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
+ if (adapter->active_checksum_context == OFFLOAD_TCP_IP)
+ return;
+ else
+ adapter->active_checksum_context =
+ OFFLOAD_TCP_IP;
+ } else if (mp->m_pkthdr.csum_flags & CSUM_UDP) {
+ *txd_upper = E1000_TXD_POPTS_TXSM << 8;
+ *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
+ if (adapter->active_checksum_context == OFFLOAD_UDP_IP)
+ return;
+ else
+ adapter->active_checksum_context =
+ OFFLOAD_UDP_IP;
+ } else {
+ *txd_upper = 0;
+ *txd_lower = 0;
+ return;
+ }
} else {
- etype = ntohs(eh->evl_encap_proto);
- ehdrlen = ETHER_HDR_LEN;
+ *txd_upper = 0;
+ *txd_lower = 0;
+ return;
}
- /*
- * We only support TCP/UDP for IPv4 and IPv6 for the moment.
- * TODO: Support SCTP too when it hits the tree.
+ /* If we reach this point, the checksum offload context
+ * needs to be reset.
*/
- switch (etype) {
- case ETHERTYPE_IP:
- ip = (struct ip *)(mp->m_data + ehdrlen);
- ip_hlen = ip->ip_hl << 2;
-
- /* Setup of IP header checksum. */
- if (mp->m_pkthdr.csum_flags & CSUM_IP) {
- /*
- * Start offset for header checksum calculation.
- * End offset for header checksum calculation.
- * Offset of place to put the checksum.
- */
- TXD->lower_setup.ip_fields.ipcss = ehdrlen;
- TXD->lower_setup.ip_fields.ipcse =
- htole16(ehdrlen + ip_hlen);
- TXD->lower_setup.ip_fields.ipcso =
- ehdrlen + offsetof(struct ip, ip_sum);
- cmd |= E1000_TXD_CMD_IP;
- *txd_upper |= E1000_TXD_POPTS_IXSM << 8;
- }
-
- if (mp->m_len < ehdrlen + ip_hlen)
- return; /* failure */
-
- hdr_len = ehdrlen + ip_hlen;
- ipproto = ip->ip_p;
-
- break;
- case ETHERTYPE_IPV6:
- ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
- ip_hlen = sizeof(struct ip6_hdr); /* XXX: No header stacking. */
-
- if (mp->m_len < ehdrlen + ip_hlen)
- return; /* failure */
-
- /* IPv6 doesn't have a header checksum. */
+ curr_txd = adapter->next_avail_tx_desc;
+ tx_buffer = &adapter->tx_buffer_area[curr_txd];
+ TXD = (struct em_context_desc *) &adapter->tx_desc_base[curr_txd];
- hdr_len = ehdrlen + ip_hlen;
- ipproto = ip6->ip6_nxt;
+ TXD->lower_setup.ip_fields.ipcss = ETHER_HDR_LEN;
+ TXD->lower_setup.ip_fields.ipcso =
+ ETHER_HDR_LEN + offsetof(struct ip, ip_sum);
+ TXD->lower_setup.ip_fields.ipcse =
+ htole16(ETHER_HDR_LEN + sizeof(struct ip) - 1);
- break;
- default:
- *txd_upper = 0;
- *txd_lower = 0;
- return;
- }
+ TXD->upper_setup.tcp_fields.tucss =
+ ETHER_HDR_LEN + sizeof(struct ip);
+ TXD->upper_setup.tcp_fields.tucse = htole16(0);
- switch (ipproto) {
- case IPPROTO_TCP:
- if (mp->m_pkthdr.csum_flags & CSUM_TCP) {
- /*
- * Start offset for payload checksum calculation.
- * End offset for payload checksum calculation.
- * Offset of place to put the checksum.
- */
- th = (struct tcp_hdr *)(mp->m_data + hdr_len);
- TXD->upper_setup.tcp_fields.tucss = hdr_len;
- TXD->upper_setup.tcp_fields.tucse = htole16(0);
- TXD->upper_setup.tcp_fields.tucso =
- hdr_len + offsetof(struct tcphdr, th_sum);
- cmd |= E1000_TXD_CMD_TCP;
- *txd_upper |= E1000_TXD_POPTS_TXSM << 8;
- }
- break;
- case IPPROTO_UDP:
- if (mp->m_pkthdr.csum_flags & CSUM_UDP) {
- /*
- * Start offset for header checksum calculation.
- * End offset for header checksum calculation.
- * Offset of place to put the checksum.
- */
- TXD->upper_setup.tcp_fields.tucss = hdr_len;
- TXD->upper_setup.tcp_fields.tucse = htole16(0);
- TXD->upper_setup.tcp_fields.tucso =
- hdr_len + offsetof(struct udphdr, uh_sum);
- *txd_upper |= E1000_TXD_POPTS_TXSM << 8;
- }
- break;
- default:
- break;
+ 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);
+ } else if (adapter->active_checksum_context == OFFLOAD_UDP_IP) {
+ TXD->upper_setup.tcp_fields.tucso =
+ ETHER_HDR_LEN + sizeof(struct ip) +
+ offsetof(struct udphdr, uh_sum);
}
TXD->tcp_seg_setup.data = htole32(0);
- TXD->cmd_and_length =
- htole32(adapter->txd_cmd | E1000_TXD_CMD_DEXT | cmd);
+ 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;
@@ -2934,153 +2745,76 @@ em_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp,
adapter->next_avail_tx_desc = curr_txd;
}
+#ifdef EM_TSO
/**********************************************************************
*
* Setup work for hardware segmentation offload (TSO)
*
**********************************************************************/
static boolean_t
-em_tso_setup(struct adapter *adapter, struct mbuf *mp, uint32_t *txd_upper,
- uint32_t *txd_lower)
+em_tso_setup(struct adapter *adapter,
+ struct mbuf *mp,
+ u_int32_t *txd_upper,
+ u_int32_t *txd_lower)
{
struct em_context_desc *TXD;
struct em_buffer *tx_buffer;
- struct ether_vlan_header *eh;
struct ip *ip;
- struct ip6_hdr *ip6;
struct tcphdr *th;
- int curr_txd, ehdrlen, hdr_len, ip_hlen, isip6;
- uint16_t etype;
-
- /*
- * XXX: This is not really correct as the stack would not have
- * set up all checksums.
- * XXX: Return FALSE is not sufficient as we may have to return
- * in true failure cases as well. Should do -1 (failure), 0 (no)
- * and 1 (success).
- */
- if (mp->m_pkthdr.len <= E1000_TX_BUFFER_SIZE)
- return FALSE; /* 0 */
+ int curr_txd, hdr_len, ip_hlen, tcp_hlen;
- /*
- * This function could/should be extended to support IP/IPv6
- * fragmentation as well. But as they say, one step at a time.
- */
-
- /*
- * Determine where frame payload starts.
- * Jump over vlan headers if already present,
- * helpful for QinQ too.
- */
- eh = mtod(mp, struct ether_vlan_header *);
- if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
- etype = ntohs(eh->evl_proto);
- ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
- } else {
- etype = ntohs(eh->evl_encap_proto);
- ehdrlen = ETHER_HDR_LEN;
- }
-
- /* Ensure we have at least the IP+TCP header in the first mbuf. */
- if (mp->m_len < ehdrlen + sizeof(struct ip) + sizeof(struct tcphdr))
- return FALSE; /* -1 */
-
- /*
- * We only support TCP for IPv4 and IPv6 (notyet) for the moment.
- * TODO: Support SCTP too when it hits the tree.
- */
- switch (etype) {
- case ETHERTYPE_IP:
- isip6 = 0;
- ip = (struct ip *)(mp->m_data + ehdrlen);
- if (ip->ip_p != IPPROTO_TCP)
- return FALSE; /* 0 */
- ip->ip_len = 0;
- ip->ip_sum = 0;
- ip_hlen = ip->ip_hl << 2;
- if (mp->m_len < ehdrlen + ip_hlen + sizeof(struct tcphdr))
- return FALSE; /* -1 */
- th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
-#if 1
- th->th_sum = in_pseudo(ip->ip_src.s_addr,
- ip->ip_dst.s_addr, htons(IPPROTO_TCP));
-#else
- th->th_sum = mp->m_pkthdr.csum_data;
-#endif
- break;
- case ETHERTYPE_IPV6:
- isip6 = 1;
- return FALSE; /* Not supported yet. */
- ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
- if (ip6->ip6_nxt != IPPROTO_TCP)
- return FALSE; /* 0 */
- ip6->ip6_plen = 0;
- ip_hlen = sizeof(struct ip6_hdr); /* XXX: no header stacking. */
- if (mp->m_len < ehdrlen + ip_hlen + sizeof(struct tcphdr))
- return FALSE; /* -1 */
- th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
-#if 0
- th->th_sum = in6_pseudo(ip6->ip6_src, ip->ip6_dst,
- htons(IPPROTO_TCP)); /* XXX: function notyet. */
-#else
- th->th_sum = mp->m_pkthdr.csum_data;
-#endif
- break;
- default:
+ if (((mp->m_pkthdr.csum_flags & CSUM_TSO) == 0) ||
+ (mp->m_pkthdr.len <= E1000_TX_BUFFER_SIZE)) {
return FALSE;
}
- hdr_len = ehdrlen + ip_hlen + (th->th_off << 2);
- *txd_lower = (E1000_TXD_CMD_DEXT | /* Extended descr type */
- E1000_TXD_DTYP_D | /* Data descr type */
- E1000_TXD_CMD_TSE); /* Do TSE on this packet */
+ *txd_lower = (E1000_TXD_CMD_DEXT |
+ E1000_TXD_DTYP_D |
+ E1000_TXD_CMD_TSE);
- /* IP and/or TCP header checksum calculation and insertion. */
- *txd_upper = ((isip6 ? 0 : E1000_TXD_POPTS_IXSM) |
+ *txd_upper = (E1000_TXD_POPTS_IXSM |
E1000_TXD_POPTS_TXSM) << 8;
curr_txd = adapter->next_avail_tx_desc;
tx_buffer = &adapter->tx_buffer_area[curr_txd];
TXD = (struct em_context_desc *) &adapter->tx_desc_base[curr_txd];
- /* IPv6 doesn't have a header checksum. */
- if (!isip6) {
- /*
- * Start offset for header checksum calculation.
- * End offset for header checksum calculation.
- * Offset of place put the checksum.
- */
- TXD->lower_setup.ip_fields.ipcss = ehdrlen;
- TXD->lower_setup.ip_fields.ipcse =
- htole16(ehdrlen + ip_hlen - 1);
- TXD->lower_setup.ip_fields.ipcso =
- ehdrlen + offsetof(struct ip, ip_sum);
- }
- /*
- * Start offset for payload checksum calculation.
- * End offset for payload checksum calculation.
- * Offset of place to put the checksum.
- */
- TXD->upper_setup.tcp_fields.tucss =
- ehdrlen + ip_hlen;
+ mp->m_data += sizeof(struct ether_header);
+ ip = mtod(mp, struct ip *);
+ ip->ip_len = 0;
+ ip->ip_sum = 0;
+ ip_hlen = ip->ip_hl << 2 ;
+ th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
+ tcp_hlen = th->th_off << 2;
+
+ hdr_len = ETHER_HDR_LEN + ip_hlen + tcp_hlen;
+ th->th_sum = in_pseudo(ip->ip_src.s_addr,
+ ip->ip_dst.s_addr,
+ htons(IPPROTO_TCP));
+
+ mp->m_data -= sizeof(struct ether_header);
+ TXD->lower_setup.ip_fields.ipcss = ETHER_HDR_LEN;
+ TXD->lower_setup.ip_fields.ipcso =
+ ETHER_HDR_LEN + offsetof(struct ip, ip_sum);
+ TXD->lower_setup.ip_fields.ipcse =
+ htole16(ETHER_HDR_LEN + ip_hlen - 1);
+
+ TXD->upper_setup.tcp_fields.tucss =
+ ETHER_HDR_LEN + ip_hlen;
TXD->upper_setup.tcp_fields.tucse = 0;
- TXD->upper_setup.tcp_fields.tucso =
- ehdrlen + ip_hlen + offsetof(struct tcphdr, th_sum);
- /*
- * Payload size per packet w/o any headers.
- * Length of all headers up to payload.
- */
+ TXD->upper_setup.tcp_fields.tucso =
+ ETHER_HDR_LEN + ip_hlen +
+ offsetof(struct tcphdr, th_sum);
TXD->tcp_seg_setup.fields.mss = htole16(mp->m_pkthdr.tso_segsz);
TXD->tcp_seg_setup.fields.hdr_len = hdr_len;
-
TXD->cmd_and_length = htole32(adapter->txd_cmd |
- E1000_TXD_CMD_DEXT | /* Extended descr */
- E1000_TXD_CMD_TSE | /* TSE context */
- (isip6 ? 0 : E1000_TXD_CMD_IP) | /* Do IP csum */
- E1000_TXD_CMD_TCP | /* Do TCP checksum */
- (mp->m_pkthdr.len - (hdr_len))); /* Total len */
+ E1000_TXD_CMD_DEXT |
+ E1000_TXD_CMD_TSE |
+ E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP |
+ (mp->m_pkthdr.len - (hdr_len)));
tx_buffer->m_head = NULL;
+ tx_buffer->next_eop = -1;
if (++curr_txd == adapter->num_tx_desc)
curr_txd = 0;
@@ -3091,6 +2825,7 @@ em_tso_setup(struct adapter *adapter, struct mbuf *mp, uint32_t *txd_upper,
return TRUE;
}
+#endif /* EM_TSO */
/**********************************************************************
*
@@ -3102,64 +2837,89 @@ em_tso_setup(struct adapter *adapter, struct mbuf *mp, uint32_t *txd_upper,
static void
em_txeof(struct adapter *adapter)
{
- int i, num_avail;
- struct em_buffer *tx_buffer;
- struct em_tx_desc *tx_desc;
+ int first, last, done, num_avail;
+ struct em_buffer *tx_buffer;
+ struct em_tx_desc *tx_desc, *eop_desc;
struct ifnet *ifp = adapter->ifp;
EM_LOCK_ASSERT(adapter);
- if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
- return;
-
- num_avail = adapter->num_tx_desc_avail;
- i = adapter->oldest_used_tx_desc;
+ if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
+ return;
- tx_buffer = &adapter->tx_buffer_area[i];
- tx_desc = &adapter->tx_desc_base[i];
+ num_avail = adapter->num_tx_desc_avail;
+ 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;
+ eop_desc = &adapter->tx_desc_base[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) {
+ /*
+ * 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 (eop_desc->upper.fields.status & E1000_TXD_STAT_DD) {
+ /* We clean the range of the packet */
+ while (first != done) {
+ tx_desc->upper.data = 0;
+ tx_desc->lower.data = 0;
+ num_avail++;
+
+ if (tx_buffer->m_head) {
+ ifp->if_opackets++;
+ bus_dmamap_sync(adapter->txtag,
+ tx_buffer->map,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(adapter->txtag,
+ tx_buffer->map);
- tx_desc->upper.data = 0;
- num_avail++;
+ m_freem(tx_buffer->m_head);
+ tx_buffer->m_head = NULL;
+ }
+ tx_buffer->next_eop = -1;
- 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 (++first == adapter->num_tx_desc)
+ first = 0;
- m_freem(tx_buffer->m_head);
- tx_buffer->m_head = NULL;
+ tx_buffer = &adapter->tx_buffer_area[first];
+ tx_desc = &adapter->tx_desc_base[first];
}
-
- if (++i == adapter->num_tx_desc)
- i = 0;
-
- tx_buffer = &adapter->tx_buffer_area[i];
- tx_desc = &adapter->tx_desc_base[i];
- }
- bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
- adapter->oldest_used_tx_desc = i;
-
- /*
- * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack
- * that it is OK to send packets.
- * If there are no pending descriptors, clear the timeout. Otherwise,
- * if some descriptors have been freed, restart the timeout.
- */
- if (num_avail > EM_TX_CLEANUP_THRESHOLD) {
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- if (num_avail == adapter->num_tx_desc)
- ifp->if_timer = 0;
- else if (num_avail != adapter->num_tx_desc_avail)
- ifp->if_timer = EM_TX_TIMEOUT;
- }
- adapter->num_tx_desc_avail = num_avail;
+ /* See if we can continue to the next packet */
+ last = tx_buffer->next_eop;
+ if (last != -1) {
+ eop_desc = &adapter->tx_desc_base[last];
+ /* Get new done point */
+ 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_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ adapter->next_tx_to_clean = first;
+
+ /*
+ * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack
+ * that it is OK to send packets.
+ * If there are no pending descriptors, clear the timeout. Otherwise,
+ * if some descriptors have been freed, restart the timeout.
+ */
+ if (num_avail > EM_TX_CLEANUP_THRESHOLD) {
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ if (num_avail == adapter->num_tx_desc)
+ ifp->if_timer = 0;
+ else if (num_avail != adapter->num_tx_desc_avail)
+ ifp->if_timer = EM_TX_TIMEOUT;
+ }
+ adapter->num_tx_desc_avail = num_avail;
+ return;
}
/*********************************************************************
@@ -3168,47 +2928,46 @@ em_txeof(struct adapter *adapter)
*
**********************************************************************/
static int
-em_get_buf(struct adapter *adapter, int i)
+em_get_buf(int i, struct adapter *adapter, struct mbuf *mp)
{
- struct mbuf *m;
+ struct ifnet *ifp = adapter->ifp;
bus_dma_segment_t segs[1];
- bus_dmamap_t map;
struct em_buffer *rx_buffer;
int error, nsegs;
- m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
- if (m == NULL) {
- adapter->mbuf_cluster_failed++;
- return (ENOBUFS);
+ if (mp == NULL) {
+ mp = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (mp == NULL) {
+ adapter->mbuf_cluster_failed++;
+ return (ENOBUFS);
+ }
+ mp->m_len = mp->m_pkthdr.len = MCLBYTES;
+ } else {
+ mp->m_len = mp->m_pkthdr.len = MCLBYTES;
+ mp->m_data = mp->m_ext.ext_buf;
+ mp->m_next = NULL;
}
- m->m_len = m->m_pkthdr.len = MCLBYTES;
- if (adapter->hw.max_frame_size <= (MCLBYTES - ETHER_ALIGN))
- m_adj(m, ETHER_ALIGN);
+
+ if (ifp->if_mtu <= ETHERMTU)
+ m_adj(mp, ETHER_ALIGN);
+
+ rx_buffer = &adapter->rx_buffer_area[i];
/*
* Using memory from the mbuf cluster pool, invoke the
* bus_dma machinery to arrange the memory mapping.
*/
- error = bus_dmamap_load_mbuf_sg(adapter->rxtag, adapter->rx_sparemap,
- m, segs, &nsegs, BUS_DMA_NOWAIT);
+ error = bus_dmamap_load_mbuf_sg(adapter->rxtag, rx_buffer->map,
+ mp, segs, &nsegs, 0);
if (error != 0) {
- m_free(m);
+ m_free(mp);
return (error);
}
/* If nsegs is wrong then the stack is corrupt. */
KASSERT(nsegs == 1, ("Too many segments returned!"));
-
- rx_buffer = &adapter->rx_buffer_area[i];
- if (rx_buffer->m_head != NULL)
- bus_dmamap_unload(adapter->rxtag, rx_buffer->map);
-
- map = rx_buffer->map;
- rx_buffer->map = adapter->rx_sparemap;
- adapter->rx_sparemap = map;
- bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD);
- rx_buffer->m_head = m;
-
+ rx_buffer->m_head = mp;
adapter->rx_desc_base[i].buffer_addr = htole64(segs[0].ds_addr);
+ bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD);
return (0);
}
@@ -3228,16 +2987,17 @@ em_allocate_receive_structures(struct adapter *adapter)
struct em_buffer *rx_buffer;
int i, error;
- adapter->rx_buffer_area = malloc(sizeof(struct em_buffer) * adapter->num_rx_desc,
- M_DEVBUF, M_NOWAIT);
+ adapter->rx_buffer_area = malloc(sizeof(struct em_buffer) *
+ adapter->num_rx_desc, M_DEVBUF, M_NOWAIT);
if (adapter->rx_buffer_area == NULL) {
device_printf(dev, "Unable to allocate rx_buffer memory\n");
return (ENOMEM);
}
- bzero(adapter->rx_buffer_area, sizeof(struct em_buffer) * adapter->num_rx_desc);
+ bzero(adapter->rx_buffer_area,
+ sizeof(struct em_buffer) * adapter->num_rx_desc);
- error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
+ error = bus_dma_tag_create(NULL, /* parent */
1, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
@@ -3255,13 +3015,6 @@ em_allocate_receive_structures(struct adapter *adapter)
goto fail;
}
- error = bus_dmamap_create(adapter->rxtag, BUS_DMA_NOWAIT,
- &adapter->rx_sparemap);
- if (error) {
- device_printf(dev, "%s: bus_dmamap_create failed: %d\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,
@@ -3273,14 +3026,6 @@ em_allocate_receive_structures(struct adapter *adapter)
}
}
- for (i = 0; i < adapter->num_rx_desc; i++) {
- error = em_get_buf(adapter, i);
- if (error)
- goto fail;
- }
- bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
return (0);
fail:
@@ -3296,15 +3041,35 @@ fail:
static int
em_setup_receive_structures(struct adapter *adapter)
{
- int error;
+ struct em_buffer *rx_buffer;
+ int i, error;
- bzero(adapter->rx_desc_base, (sizeof(struct em_rx_desc)) * adapter->num_rx_desc);
+ bzero(adapter->rx_desc_base,
+ (sizeof(struct em_rx_desc)) * adapter->num_rx_desc);
- if ((error = em_allocate_receive_structures(adapter)) != 0)
- return (error);
+ /* Free current RX buffers. */
+ 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_sync(adapter->rxtag, rx_buffer->map,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(adapter->rxtag, rx_buffer->map);
+ m_freem(rx_buffer->m_head);
+ rx_buffer->m_head = NULL;
+ }
+ }
+
+ /* Allocate new ones. */
+ for (i = 0; i < adapter->num_rx_desc; i++) {
+ error = em_get_buf(i, adapter, NULL);
+ if (error)
+ return (error);
+ }
/* Setup our descriptor pointers */
adapter->next_rx_desc_to_check = 0;
+ bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
return (0);
}
@@ -3330,12 +3095,9 @@ em_initialize_receive_unit(struct adapter *adapter)
*/
E1000_WRITE_REG(&adapter->hw, RCTL, 0);
- /* Set the Receive Delay Timer Register */
- E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay.value | E1000_RDT_FPDB);
-
if(adapter->hw.mac_type >= em_82540) {
- E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay.value);
-
+ E1000_WRITE_REG(&adapter->hw, RADV,
+ adapter->rx_abs_int_delay.value);
/*
* Set the interrupt throttling rate. Value is calculated
* as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns)
@@ -3352,10 +3114,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 |
@@ -3371,13 +3129,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;
}
@@ -3394,6 +3155,14 @@ 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);
+
+ return;
}
/*********************************************************************
@@ -3409,10 +3178,6 @@ em_free_receive_structures(struct adapter *adapter)
INIT_DEBUGOUT("free_receive_structures: begin");
- if (adapter->rx_sparemap) {
- bus_dmamap_destroy(adapter->rxtag, adapter->rx_sparemap);
- adapter->rx_sparemap = NULL;
- }
if (adapter->rx_buffer_area != NULL) {
rx_buffer = adapter->rx_buffer_area;
for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) {
@@ -3526,9 +3291,14 @@ em_rxeof(struct adapter *adapter, int count)
}
if (accept_frame) {
- if (em_get_buf(adapter, i) != 0) {
- ifp->if_iqdrops++;
- goto discard;
+ if (em_get_buf(i, adapter, NULL) == ENOBUFS) {
+ adapter->dropped_pkts++;
+ em_get_buf(i, adapter, mp);
+ if (adapter->fmp != NULL)
+ m_freem(adapter->fmp);
+ adapter->fmp = NULL;
+ adapter->lmp = NULL;
+ break;
}
/* Assign correct length to the current fragment */
@@ -3567,12 +3337,10 @@ em_rxeof(struct adapter *adapter, int count)
em_fixup_rx(adapter) != 0)
goto skip;
#endif
- if (status & E1000_RXD_STAT_VP) {
- adapter->fmp->m_pkthdr.ether_vtag =
+ if (status & E1000_RXD_STAT_VP)
+ VLAN_INPUT_TAG_NEW(ifp, adapter->fmp,
(le16toh(current_desc->special) &
- E1000_RXD_SPC_VLAN_MASK);
- adapter->fmp->m_flags |= M_VLANTAG;
- }
+ E1000_RXD_SPC_VLAN_MASK));
#ifndef __NO_STRICT_ALIGNMENT
skip:
#endif
@@ -3581,21 +3349,12 @@ skip:
adapter->lmp = NULL;
}
} else {
- ifp->if_ierrors++;
-discard:
- /* Reuse loaded DMA map and just update mbuf chain */
- mp = adapter->rx_buffer_area[i].m_head;
- mp->m_len = mp->m_pkthdr.len = MCLBYTES;
- mp->m_data = mp->m_ext.ext_buf;
- mp->m_next = NULL;
- if (adapter->hw.max_frame_size <= (MCLBYTES - ETHER_ALIGN))
- m_adj(mp, ETHER_ALIGN);
- if (adapter->fmp != NULL) {
+ adapter->dropped_pkts++;
+ em_get_buf(i, adapter, mp);
+ if (adapter->fmp != NULL)
m_freem(adapter->fmp);
- adapter->fmp = NULL;
- adapter->lmp = NULL;
- }
- m = NULL;
+ adapter->fmp = NULL;
+ adapter->lmp = NULL;
}
/* Zero out the receive descriptors status. */
@@ -3608,13 +3367,9 @@ discard:
i = 0;
if (m != NULL) {
adapter->next_rx_desc_to_check = i;
-#ifdef DEVICE_POLLING
EM_UNLOCK(adapter);
(*ifp->if_input)(ifp, m);
EM_LOCK(adapter);
-#else
- (*ifp->if_input)(ifp, m);
-#endif
i = adapter->next_rx_desc_to_check;
}
current_desc = &adapter->rx_desc_base[i];
@@ -3668,12 +3423,10 @@ em_fixup_rx(struct adapter *adapter)
n->m_next = m;
adapter->fmp = n;
} else {
- adapter->ifp->if_iqdrops++;
- adapter->mbuf_alloc_failed++;
+ adapter->dropped_pkts++;
m_freem(adapter->fmp);
adapter->fmp = NULL;
- adapter->lmp = NULL;
- error = ENOBUFS;
+ error = ENOMEM;
}
}
@@ -3689,8 +3442,8 @@ em_fixup_rx(struct adapter *adapter)
*
*********************************************************************/
static void
-em_receive_checksum(struct adapter *adapter, struct em_rx_desc *rx_desc,
- struct mbuf *mp)
+em_receive_checksum(struct adapter *adapter,
+ struct em_rx_desc *rx_desc, struct mbuf *mp)
{
/* 82543 or newer only */
if ((adapter->hw.mac_type < em_82543) ||
@@ -3767,8 +3520,7 @@ em_disable_intr(struct adapter *adapter)
E1000_WRITE_REG(&adapter->hw, IMC,
(0xffffffff & ~E1000_IMC_RXSEQ));
else
- E1000_WRITE_REG(&adapter->hw, IMC,
- 0xffffffff);
+ E1000_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
}
static int
@@ -3809,6 +3561,37 @@ em_pci_clear_mwi(struct em_hw *hw)
(hw->pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE), 2);
}
+uint32_t
+em_io_read(struct em_hw *hw, unsigned long port)
+{
+ struct em_osdep *io = hw->back;
+ uint32_t ret;
+
+ ret = bus_space_read_4(io->io_bus_space_tag,
+ io->io_bus_space_handle, port);
+ return (ret);
+}
+
+void
+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);
+ return;
+}
+
+/*
+ * 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)
+{
+ return (0);
+}
+
/*********************************************************************
* 82544 Coexistence issue workaround.
* There are 2 issues.
@@ -3824,9 +3607,10 @@ em_pci_clear_mwi(struct em_hw *hw)
*
*
* WORKAROUND:
-* Make sure we do not have ending address as 1,2,3,4(Hang) or 9,a,b,c (DAC)
+* Make sure we do not have ending address
+* as 1,2,3,4(Hang) or 9,a,b,c (DAC)
*
-*** *********************************************************************/
+*************************************************************************/
static uint32_t
em_fill_descriptors (bus_addr_t address, uint32_t length,
PDESC_ARRAY desc_array)
@@ -3840,7 +3624,8 @@ em_fill_descriptors (bus_addr_t address, uint32_t length,
desc_array->elements = 1;
return (desc_array->elements);
}
- safe_terminator = (uint32_t)((((uint32_t)address & 0x7) + (length & 0xF)) & 0xF);
+ 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 */
if (safe_terminator == 0 ||
(safe_terminator > 4 &&
@@ -3933,25 +3718,32 @@ em_update_stats_counters(struct adapter *adapter)
adapter->stats.bptc += E1000_READ_REG(&adapter->hw, BPTC);
if (adapter->hw.mac_type >= em_82543) {
- adapter->stats.algnerrc += E1000_READ_REG(&adapter->hw, ALGNERRC);
- adapter->stats.rxerrc += E1000_READ_REG(&adapter->hw, RXERRC);
- adapter->stats.tncrs += E1000_READ_REG(&adapter->hw, TNCRS);
- adapter->stats.cexterr += E1000_READ_REG(&adapter->hw, CEXTERR);
- adapter->stats.tsctc += E1000_READ_REG(&adapter->hw, TSCTC);
- adapter->stats.tsctfc += E1000_READ_REG(&adapter->hw, TSCTFC);
+ adapter->stats.algnerrc +=
+ E1000_READ_REG(&adapter->hw, ALGNERRC);
+ adapter->stats.rxerrc +=
+ E1000_READ_REG(&adapter->hw, RXERRC);
+ adapter->stats.tncrs +=
+ E1000_READ_REG(&adapter->hw, TNCRS);
+ adapter->stats.cexterr +=
+ E1000_READ_REG(&adapter->hw, CEXTERR);
+ adapter->stats.tsctc +=
+ E1000_READ_REG(&adapter->hw, TSCTC);
+ adapter->stats.tsctfc +=
+ E1000_READ_REG(&adapter->hw, TSCTFC);
}
ifp = adapter->ifp;
ifp->if_collisions = adapter->stats.colc;
/* Rx Errors */
- ifp->if_ierrors = adapter->stats.rxerrc + adapter->stats.crcerrs +
- adapter->stats.algnerrc + adapter->stats.ruc + adapter->stats.roc +
+ ifp->if_ierrors = adapter->dropped_pkts + adapter->stats.rxerrc +
+ adapter->stats.crcerrs + adapter->stats.algnerrc +
+ adapter->stats.ruc + adapter->stats.roc +
adapter->stats.mpc + adapter->stats.cexterr;
/* Tx Errors */
- ifp->if_oerrors = adapter->stats.ecol + adapter->stats.latecol +
- adapter->watchdog_events;
+ ifp->if_oerrors = adapter->stats.ecol +
+ adapter->stats.latecol + adapter->watchdog_events;
}
@@ -4000,6 +3792,8 @@ em_print_debug_info(struct adapter *adapter)
adapter->mbuf_alloc_failed);
device_printf(dev, "Std mbuf cluster failed = %ld\n",
adapter->mbuf_cluster_failed);
+ device_printf(dev, "Driver dropped packets = %ld\n",
+ adapter->dropped_pkts);
}
static void
@@ -4009,13 +3803,16 @@ em_print_hw_stats(struct adapter *adapter)
device_printf(dev, "Excessive collisions = %lld\n",
(long long)adapter->stats.ecol);
+#if (DEBUG_HW > 0) /* Dont output these errors normally */
device_printf(dev, "Symbol errors = %lld\n",
(long long)adapter->stats.symerrs);
+#endif
device_printf(dev, "Sequence errors = %lld\n",
(long long)adapter->stats.sec);
- device_printf(dev, "Defer count = %lld\n", (long long)adapter->stats.dc);
-
- device_printf(dev, "Missed Packets = %lld\n", (long long)adapter->stats.mpc);
+ device_printf(dev, "Defer count = %lld\n",
+ (long long)adapter->stats.dc);
+ device_printf(dev, "Missed Packets = %lld\n",
+ (long long)adapter->stats.mpc);
device_printf(dev, "Receive No Buffers = %lld\n",
(long long)adapter->stats.rnbc);
/* RLEC is inaccurate on some hardware, calculate our own. */
@@ -4023,27 +3820,33 @@ em_print_hw_stats(struct adapter *adapter)
((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", (long long)adapter->stats.crcerrs);
+ device_printf(dev, "Crc errors = %lld\n",
+ (long long)adapter->stats.crcerrs);
device_printf(dev, "Alignment errors = %lld\n",
(long long)adapter->stats.algnerrc);
device_printf(dev, "Carrier extension errors = %lld\n",
(long long)adapter->stats.cexterr);
device_printf(dev, "RX overruns = %ld\n", adapter->rx_overruns);
- device_printf(dev, "watchdog timeouts = %ld\n", adapter->watchdog_events);
-
- device_printf(dev, "XON Rcvd = %lld\n", (long long)adapter->stats.xonrxc);
- device_printf(dev, "XON Xmtd = %lld\n", (long long)adapter->stats.xontxc);
- device_printf(dev, "XOFF Rcvd = %lld\n", (long long)adapter->stats.xoffrxc);
- device_printf(dev, "XOFF Xmtd = %lld\n", (long long)adapter->stats.xofftxc);
-
+ device_printf(dev, "watchdog timeouts = %ld\n",
+ adapter->watchdog_events);
+ device_printf(dev, "XON Rcvd = %lld\n",
+ (long long)adapter->stats.xonrxc);
+ device_printf(dev, "XON Xmtd = %lld\n",
+ (long long)adapter->stats.xontxc);
+ device_printf(dev, "XOFF Rcvd = %lld\n",
+ (long long)adapter->stats.xoffrxc);
+ device_printf(dev, "XOFF Xmtd = %lld\n",
+ (long long)adapter->stats.xofftxc);
device_printf(dev, "Good Packets Rcvd = %lld\n",
(long long)adapter->stats.gprc);
device_printf(dev, "Good Packets Xmtd = %lld\n",
(long long)adapter->stats.gptc);
+#ifdef EM_TSO
device_printf(dev, "TSO Contexts Xmtd = %lld\n",
(long long)adapter->stats.tsctc);
device_printf(dev, "TSO Contexts Failed = %lld\n",
(long long)adapter->stats.tsctfc);
+#endif
}
static int
@@ -4148,15 +3951,3 @@ em_add_int_delay_sysctl(struct adapter *adapter, const char *name,
OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW,
info, 0, em_sysctl_int_delay, "I", description);
}
-
-#ifndef DEVICE_POLLING
-static void
-em_add_int_process_limit(struct adapter *adapter, const char *name,
- const char *description, int *limit, int value)
-{
- *limit = value;
- SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
- OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
-}
-#endif
diff --git a/sys/dev/em/if_em.h b/sys/dev/em/if_em.h
index 99a7ba8..b88c585 100644
--- a/sys/dev/em/if_em.h
+++ b/sys/dev/em/if_em.h
@@ -30,7 +30,6 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
-
/*$FreeBSD$*/
#ifndef _EM_H_DEFINED_
@@ -86,7 +85,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
@@ -112,10 +112,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
@@ -137,10 +137,12 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#define EM_CHECKSUM_FEATURES (CSUM_TCP | CSUM_UDP)
+#ifdef EM_TSO
/*
* Inform the stack about transmit segmentation offload capabilities.
*/
-#define EM_TCPSEG_FEATURES CSUM_TSO
+#define EM_TCPSEG_FEATURES CSUM_TSO
+#endif
/*
* This parameter controls the duration of transmit watchdog timer.
@@ -169,9 +171,10 @@ POSSIBILITY OF SUCH DAMAGE.
#define WAIT_FOR_AUTO_NEG_DEFAULT 0
/*
- * EM_MASTER_SLAVE is only defined to enable a workaround for a known compatibility issue
- * with 82541/82547 devices and some switches. See the "Known Limitations" section of
- * the README file for a complete description and a list of affected switches.
+ * EM_MASTER_SLAVE is only defined to enable a workaround for a known
+ * compatibility issue with 82541/82547 devices and some switches.
+ * See the "Known Limitations" section of the README file for a complete
+ * description and a list of affected switches.
*
* 0 = Hardware default
* 1 = Master mode
@@ -182,12 +185,12 @@ POSSIBILITY OF SUCH DAMAGE.
/* Tunables -- End */
-#define AUTONEG_ADV_DEFAULT (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
- ADVERTISE_100_HALF | ADVERTISE_100_FULL | \
- ADVERTISE_1000_FULL)
+#define AUTONEG_ADV_DEFAULT (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
+ ADVERTISE_100_HALF | ADVERTISE_100_FULL | \
+ ADVERTISE_1000_FULL)
#define EM_VENDOR_ID 0x8086
-#define EM_FLASH 0x0014 /* Flash memory on ICH8 */
+#define EM_FLASH 0x0014 /* Flash memory on ICH8 */
#define EM_JUMBO_PBA 0x00000028
#define EM_DEFAULT_PBA 0x00000030
@@ -207,6 +210,22 @@ POSSIBILITY OF SUCH DAMAGE.
#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
+/*
+ * Backward compatibility hack
+ */
+#if !defined(PCIR_CIS)
+#define PCIR_CIS PCIR_CARDBUSCIS
+#endif
+
/* Defines for printing debug information */
#define DEBUG_INIT 0
#define DEBUG_IOCTL 0
@@ -229,37 +248,71 @@ POSSIBILITY OF SUCH DAMAGE.
#define EM_RXBUFFER_8192 8192
#define EM_RXBUFFER_16384 16384
-#define EM_MAX_SCATTER 64
-#define EM_TSO_SIZE 65535
+#define EM_MAX_SCATTER 64
+#define EM_TSO_SIZE 65535 /* maxsize of a dma transfer */
-typedef enum _XSUM_CONTEXT_T {
- OFFLOAD_NONE,
- OFFLOAD_TCP_IP,
- OFFLOAD_UDP_IP
-} XSUM_CONTEXT_T;
+/* ******************************************************************************
+ * vendor_info_array
+ *
+ * This array contains the list of Subvendor/Subdevice IDs on which the driver
+ * should load.
+ *
+ * ******************************************************************************/
+typedef struct _em_vendor_info_t {
+ unsigned int vendor_id;
+ unsigned int device_id;
+ unsigned int subvendor_id;
+ unsigned int subdevice_id;
+ unsigned int index;
+} em_vendor_info_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 em_buffer {
+ int next_eop; /* Index of the desc to watch */
+ struct mbuf *m_head;
+ bus_dmamap_t map; /* bus_dma map for packet */
};
/*
* Bus dma allocation structure used by
- * em_dma_malloc() and em_dma_free().
+ * em_dma_malloc and em_dma_free.
*/
struct em_dma_alloc {
- bus_addr_t dma_paddr;
- caddr_t dma_vaddr;
- bus_dma_tag_t dma_tag;
- bus_dmamap_t dma_map;
- bus_dma_segment_t dma_seg;
- int dma_nseg;
+ bus_addr_t dma_paddr;
+ caddr_t dma_vaddr;
+ bus_dma_tag_t dma_tag;
+ bus_dmamap_t dma_map;
+ bus_dma_segment_t dma_seg;
+ int dma_nseg;
};
-/* Driver softc. */
+typedef enum _XSUM_CONTEXT_T {
+ OFFLOAD_NONE,
+ OFFLOAD_TCP_IP,
+ OFFLOAD_UDP_IP
+} XSUM_CONTEXT_T;
+
+struct adapter adapter; /* XXX: ugly forward declaration */
+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 */
+};
+
+/* For 82544 PCIX Workaround */
+typedef struct _ADDRESS_LENGTH_PAIR
+{
+ uint64_t address;
+ uint32_t length;
+} ADDRESS_LENGTH_PAIR, *PADDRESS_LENGTH_PAIR;
+
+typedef struct _DESCRIPTOR_PAIR
+{
+ ADDRESS_LENGTH_PAIR descriptor[4];
+ uint32_t elements;
+} DESC_ARRAY, *PDESC_ARRAY;
+
+/* Our adapter structure */
struct adapter {
struct ifnet *ifp;
struct em_hw hw;
@@ -279,10 +332,6 @@ struct adapter {
int if_flags;
struct mtx mtx;
int em_insert_vlan_header;
- struct task link_task;
- struct task rxtx_task;
- struct taskqueue *tq; /* private task queue */
-
/* Info about the board itself */
uint32_t part_num;
uint8_t link_active;
@@ -308,13 +357,13 @@ struct adapter {
struct em_dma_alloc txdma; /* bus_dma glue for tx desc */
struct em_tx_desc *tx_desc_base;
uint32_t next_avail_tx_desc;
- uint32_t oldest_used_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 */
- uint32_t tx_tso; /* last tx was tso */
+ uint32_t tx_tso; /* last tx was tso */
/*
* Receive definitions
@@ -332,13 +381,16 @@ struct adapter {
int rx_process_limit;
struct em_buffer *rx_buffer_area;
bus_dma_tag_t rxtag;
- bus_dmamap_t rx_sparemap;
- /* First/last mbuf pointers, for collecting multisegment RX packets. */
+ /*
+ * First/last mbuf pointers, for
+ * collecting multisegment RX packets.
+ */
struct mbuf *fmp;
struct mbuf *lmp;
/* 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;
@@ -370,40 +422,6 @@ struct adapter {
struct em_hw_stats stats;
};
-/* ******************************************************************************
- * vendor_info_array
- *
- * This array contains the list of Subvendor/Subdevice IDs on which the driver
- * should load.
- *
- * ******************************************************************************/
-typedef struct _em_vendor_info_t {
- unsigned int vendor_id;
- unsigned int device_id;
- unsigned int subvendor_id;
- unsigned int subdevice_id;
- unsigned int index;
-} em_vendor_info_t;
-
-
-struct em_buffer {
- struct mbuf *m_head;
- bus_dmamap_t map; /* bus_dma map for packet */
-};
-
-/* For 82544 PCIX Workaround */
-typedef struct _ADDRESS_LENGTH_PAIR
-{
- u_int64_t address;
- u_int32_t length;
-} ADDRESS_LENGTH_PAIR, *PADDRESS_LENGTH_PAIR;
-
-typedef struct _DESCRIPTOR_PAIR
-{
- ADDRESS_LENGTH_PAIR descriptor[4];
- u_int32_t elements;
-} DESC_ARRAY, *PDESC_ARRAY;
-
#define EM_LOCK_INIT(_sc, _name) \
mtx_init(&(_sc)->mtx, _name, MTX_NETWORK_LOCK, MTX_DEF)
#define EM_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx)
diff --git a/sys/dev/em/if_em_hw.c b/sys/dev/em/if_em_hw.c
index 58716c5..4a69caa 100644
--- a/sys/dev/em/if_em_hw.c
+++ b/sys/dev/em/if_em_hw.c
@@ -1,48 +1,102 @@
/*******************************************************************************
-Copyright (c) 2001-2005, Intel Corporation
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (c) 2001-2005, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
*******************************************************************************/
+/*$FreeBSD$*/
/* if_em_hw.c
* Shared functions for accessing and configuring the MAC
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+#define STATIC static
-#ifdef LM
-#include "if_em_hw.h"
-#else
#include <dev/em/if_em_hw.h>
-#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 +160,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 +211,6 @@ em_set_phy_type(struct em_hw *hw)
return E1000_SUCCESS;
}
-
/******************************************************************************
* IGP phy init script - initializes the GbE PHY
*
@@ -340,6 +392,7 @@ em_set_mac_type(struct em_hw *hw)
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:
@@ -363,6 +416,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;
@@ -552,9 +607,7 @@ em_reset_hw(struct em_hw *hw)
case em_82544:
case em_82540:
case em_82545:
-#ifndef __arm__
case em_82546:
-#endif
case em_82541:
case em_82541_rev_2:
/* These controllers can't ack the 64-bit write when issuing the
@@ -619,19 +672,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 */
@@ -674,6 +720,110 @@ em_reset_hw(struct em_hw *hw)
}
/******************************************************************************
+ *
+ * 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.
*
* hw - Struct containing variables accessed by shared code
@@ -700,14 +850,14 @@ 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 */
@@ -720,6 +870,9 @@ em_init_hw(struct em_hw *hw)
/* Set the media type and TBI compatibility */
em_set_media_type(hw);
+ /* Must be called after em_set_media_type because media_type is used */
+ em_initialize_hardware_bits(hw);
+
/* Disabling VLAN filtering. */
DEBUGOUT("Initializing the IEEE VLAN\n");
/* VET hardcoded to standard value and VFTA removed in ICH8 LAN */
@@ -811,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);
}
@@ -859,8 +1001,6 @@ 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;
}
@@ -969,11 +1109,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,
@@ -983,12 +1123,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;
}
}
@@ -998,10 +1138,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;
@@ -1053,7 +1193,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 {
@@ -1100,11 +1240,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)
@@ -1140,11 +1280,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
@@ -1153,13 +1293,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;
@@ -2075,13 +2215,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.
*/
@@ -2093,14 +2233,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.
*/
@@ -2144,7 +2284,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);
@@ -2224,6 +2364,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);
@@ -2236,6 +2377,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.
@@ -2498,18 +2640,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:
@@ -2536,7 +2678,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;
@@ -2638,11 +2780,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");
}
}
@@ -2658,7 +2800,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.
@@ -2673,7 +2815,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
@@ -2696,13 +2838,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");
}
@@ -2717,7 +2859,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.
@@ -3059,7 +3201,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;
@@ -3229,7 +3371,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;
@@ -3273,7 +3415,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;
@@ -3368,9 +3510,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;
@@ -3450,8 +3591,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;
@@ -3508,10 +3648,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;
@@ -3571,7 +3710,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)
@@ -3604,7 +3743,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)
@@ -3662,7 +3801,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
@@ -3685,6 +3824,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
@@ -3743,15 +3883,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);
@@ -3800,14 +3939,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 */
@@ -3834,7 +3974,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;
@@ -3887,7 +4027,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;
@@ -3896,6 +4036,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. */
@@ -4007,12 +4150,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");
@@ -4037,8 +4181,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) {
@@ -4047,10 +4191,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);
@@ -4081,12 +4227,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");
@@ -4097,8 +4244,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);
@@ -4106,8 +4254,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;
@@ -4115,9 +4264,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;
}
@@ -4128,12 +4277,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");
@@ -4146,11 +4296,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);
@@ -4162,15 +4315,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,
@@ -4178,18 +4331,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;
@@ -4392,9 +4547,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;
@@ -4410,16 +4565,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;
}
@@ -4751,7 +4908,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;
@@ -4805,44 +4962,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;
@@ -4900,7 +5056,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,
@@ -4934,7 +5090,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,
@@ -4975,7 +5131,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;
@@ -5003,7 +5159,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;
@@ -5157,6 +5313,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.
*/
@@ -5199,7 +5359,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,
@@ -5265,7 +5425,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,
@@ -5352,7 +5512,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;
@@ -5362,10 +5522,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) {
@@ -5418,90 +5576,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;
@@ -5591,7 +5754,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;
@@ -5660,6 +5823,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. */
@@ -5678,6 +5842,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);
@@ -5805,6 +5970,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);
@@ -5919,7 +6085,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;
@@ -5953,7 +6119,7 @@ em_clear_vfta(struct em_hw *hw)
}
}
-int32_t
+STATIC int32_t
em_id_led_init(struct em_hw * hw)
{
uint32_t ledctl;
@@ -5990,6 +6156,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) {
@@ -6365,6 +6532,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);
+
}
/******************************************************************************
@@ -6522,6 +6690,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) {
@@ -6531,18 +6701,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,23 +6753,6 @@ em_get_bus_info(struct em_hw *hw)
break;
}
}
-/******************************************************************************
- * Reads a value from one of the devices registers using port I/O (as opposed
- * memory mapped I/O). Only 82544 and newer devices support port I/O.
- *
- * hw - Struct containing variables accessed by shared code
- * offset - offset to read from
- *****************************************************************************/
-uint32_t
-em_read_reg_io(struct em_hw *hw,
- uint32_t offset)
-{
- unsigned long io_addr = hw->io_base;
- unsigned long io_data = hw->io_base + 4;
-
- em_io_write(hw, io_addr, offset);
- return em_io_read(hw, io_data);
-}
/******************************************************************************
* Writes a value to one of the devices registers using port I/O (as opposed to
@@ -6602,7 +6762,7 @@ em_read_reg_io(struct em_hw *hw,
* offset - offset to write to
* value - value to write
*****************************************************************************/
-void
+STATIC void
em_write_reg_io(struct em_hw *hw,
uint32_t offset,
uint32_t value)
@@ -6614,7 +6774,6 @@ em_write_reg_io(struct em_hw *hw,
em_io_write(hw, io_data, value);
}
-
/******************************************************************************
* Estimates the cable length.
*
@@ -6630,7 +6789,7 @@ em_write_reg_io(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)
@@ -6821,9 +6980,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;
@@ -6837,8 +6996,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) {
@@ -6860,19 +7021,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;
}
@@ -6892,7 +7056,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;
@@ -6938,7 +7102,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)
{
@@ -7171,7 +7335,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)
{
@@ -7240,7 +7404,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;
@@ -7301,7 +7465,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)
{
@@ -7350,7 +7514,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;
@@ -7456,7 +7620,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;
@@ -7483,7 +7647,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;
@@ -7517,7 +7681,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)
{
@@ -7585,7 +7749,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)
{
@@ -7625,7 +7789,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;
@@ -7667,7 +7831,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;
@@ -7697,7 +7861,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;
@@ -7880,7 +8044,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;
@@ -7895,30 +8059,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
@@ -7968,7 +8108,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;
@@ -8016,7 +8156,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;
@@ -8042,7 +8182,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;
@@ -8064,7 +8203,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;
@@ -8114,7 +8253,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;
@@ -8143,7 +8282,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;
@@ -8151,8 +8290,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);
@@ -8178,15 +8318,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.*/
@@ -8220,10 +8361,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;
@@ -8260,7 +8401,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;
@@ -8301,7 +8442,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;
@@ -8340,7 +8481,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;
@@ -8356,61 +8497,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
@@ -8421,7 +8507,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)
{
@@ -8477,7 +8563,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)
{
@@ -8524,7 +8610,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;
@@ -8533,7 +8619,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) {
@@ -8546,7 +8632,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
@@ -8561,13 +8647,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;
@@ -8578,7 +8664,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");
}
@@ -8591,7 +8677,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;
@@ -8600,13 +8686,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);
@@ -8626,7 +8712,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)
{
@@ -8640,10 +8726,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 {
@@ -8653,25 +8739,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) {
@@ -8681,9 +8767,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;
@@ -8692,7 +8778,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;
}
@@ -8705,7 +8791,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)
{
@@ -8719,10 +8805,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 {
@@ -8732,34 +8818,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;
@@ -8768,7 +8854,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;
}
@@ -8780,7 +8866,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;
@@ -8803,24 +8889,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;
@@ -8834,7 +8922,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;
@@ -8852,7 +8940,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;
@@ -8860,62 +8948,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;
@@ -8933,28 +9012,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;
@@ -8963,7 +9041,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;
}
@@ -8972,43 +9050,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)
{
@@ -9050,7 +9093,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;
diff --git a/sys/dev/em/if_em_hw.h b/sys/dev/em/if_em_hw.h
index 7c0a74f..7971536 100644
--- a/sys/dev/em/if_em_hw.h
+++ b/sys/dev/em/if_em_hw.h
@@ -1,35 +1,38 @@
/*******************************************************************************
-Copyright (c) 2001-2005, Intel Corporation
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (c) 2001-2005, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
*******************************************************************************/
-/* $FreeBSD$ */
+/*$FreeBSD$*/
+
/* if_em_hw.h
* Structures, enums, and macros for the MAC
*/
@@ -37,11 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef _EM_HW_H_
#define _EM_HW_H_
-#ifdef LM
-#include "if_em_osdep.h"
-#else
#include <dev/em/if_em_osdep.h>
-#endif
/* Forward declarations of structures used by the shared code */
@@ -98,15 +97,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;
@@ -136,11 +126,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;
@@ -309,11 +301,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);
@@ -321,39 +315,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);
@@ -397,37 +375,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);
@@ -440,6 +405,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);
@@ -448,60 +414,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_read_reg_io(struct em_hw *hw, uint32_t offset);
-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);
+uint32_t em_io_read(struct em_hw *hw, unsigned long port);
+void em_io_write(struct em_hw *hw, unsigned long port, uint32_t value);
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);
-
-#define E1000_BAR_TYPE(v) ((v) & E1000_BAR_TYPE_MASK)
-#define E1000_BAR_TYPE_MASK 0x00000001
-#define E1000_BAR_TYPE_MEM 0x00000000
-#define E1000_BAR_TYPE_IO 0x00000001
-#define E1000_BAR_MEM_TYPE(v) ((v) & E1000_BAR_MEM_TYPE_MASK)
-#define E1000_BAR_MEM_TYPE_MASK 0x00000006
-#define E1000_BAR_MEM_TYPE_32BIT 0x00000000
-#define E1000_BAR_MEM_TYPE_64BIT 0x00000004
+
+
#ifndef E1000_READ_REG_IO
#define E1000_READ_REG_IO(a, reg) \
@@ -550,6 +470,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
@@ -567,6 +488,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
@@ -636,9 +559,9 @@ int32_t em_ife_enable_dynamic_power_down(struct em_hw *hw);
E1000_IMS_TXDW | \
E1000_IMS_RXDMT0 | \
E1000_IMS_RXSEQ | \
- E1000_IMS_RXO | \
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
@@ -648,16 +571,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 {
@@ -778,6 +703,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 */
@@ -1456,7 +1382,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;
@@ -1468,6 +1394,7 @@ struct em_hw {
uint32_t eeprom_semaphore_present;
uint32_t swfw_sync_present;
uint32_t swfwhw_semaphore_present;
+
unsigned long io_base;
uint32_t phy_id;
uint32_t phy_revision;
@@ -1519,6 +1446,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;
@@ -1577,7 +1505,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 */
@@ -1651,8 +1578,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 */
@@ -1692,16 +1619,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
@@ -1836,6 +1764,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 */
@@ -1865,6 +1794,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 */
@@ -1894,6 +1824,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 */
@@ -1923,6 +1854,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 */
@@ -2010,6 +1942,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
@@ -2297,6 +2236,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 */
@@ -2604,6 +2548,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 */
@@ -3199,6 +3144,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
@@ -3239,6 +3185,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 */
@@ -3323,39 +3270,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 */
@@ -3426,3 +3374,5 @@ union ich8_hws_flash_regacc {
#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds*/
#endif /* _EM_HW_H_ */
+
+
diff --git a/sys/dev/em/if_em_osdep.h b/sys/dev/em/if_em_osdep.h
index fa175e9..51d44aa 100644
--- a/sys/dev/em/if_em_osdep.h
+++ b/sys/dev/em/if_em_osdep.h
@@ -37,19 +37,27 @@ POSSIBILITY OF SUCH DAMAGE.
#define _FREEBSD_OS_H_
#include <sys/types.h>
+#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/bus.h>
#include <sys/mbuf.h>
-#include <sys/malloc.h>
+#include <sys/protosw.h>
#include <sys/socket.h>
-
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
-
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/clock.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
+
+#define ASSERT(x) if(!(x)) panic("EM: x")
+
+/* The happy-fun DELAY macro is defined in /usr/src/sys/i386/include/clock.h */
#define usec_delay(x) DELAY(x)
#define msec_delay(x) DELAY(1000*(x))
/* TODO: Should we be paranoid about delaying in interrupt context? */
@@ -57,7 +65,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define MSGOUT(S, A, B) printf(S "\n", A, B)
#define DEBUGFUNC(F) DEBUGOUT(F);
-#ifdef DBG
+#if DBG
#define DEBUGOUT(S) printf(S "\n")
#define DEBUGOUT1(S,A) printf(S "\n",A)
#define DEBUGOUT2(S,A,B) printf(S "\n",A,B)
@@ -84,94 +92,80 @@ struct em_osdep
bus_space_handle_t io_bus_space_handle;
bus_space_tag_t flash_bus_space_tag;
bus_space_handle_t flash_bus_space_handle;
- device_t dev;
+ struct device *dev;
};
-#define E1000_WRITE_FLUSH(hw) E1000_READ_REG(hw, STATUS)
+#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS)
/* Read from an absolute offset in the adapter's memory space */
#define E1000_READ_OFFSET(hw, offset) \
- bus_space_read_4( ((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \
+ bus_space_read_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \
((struct em_osdep *)(hw)->back)->mem_bus_space_handle, offset)
/* Write to an absolute offset in the adapter's memory space */
#define E1000_WRITE_OFFSET(hw, offset, value) \
- bus_space_write_4( ((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \
+ bus_space_write_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \
((struct em_osdep *)(hw)->back)->mem_bus_space_handle, offset, value)
/* Convert a register name to its offset in the adapter's memory space */
#define E1000_REG_OFFSET(hw, reg) \
((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg)
-/*
- * Register READ/WRITE macros.
- *
- * XXXGL: Due to define's namespace mangling in recent version of
- * if_em_hw.*, we prepend "_" to the register name in all macros,
- * to prevent reg from being substituted, and then, in E1000_REG_OFFSET()
- * we prepend either "E1000" or "E1000_82542".
- *
- * P.S. The problematic defines are E1000_PHY_CTRL and PHY_CTRL.
- *
- * P.P.S. Intel has removed E1000_REG_OFFSET() and copy-pasted it to all
- * macros.
- */
-#define _E1000_REG_OFFSET(hw, reg) \
- ((hw)->mac_type >= em_82543 ? E1000##reg : E1000_82542##reg)
+/* Register READ/WRITE macros */
#define E1000_READ_REG(hw, reg) \
- E1000_READ_OFFSET(hw, _E1000_REG_OFFSET(hw, _##reg))
+ bus_space_read_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \
+ ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \
+ ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg))
#define E1000_WRITE_REG(hw, reg, value) \
- E1000_WRITE_OFFSET(hw, _E1000_REG_OFFSET(hw, _##reg), value)
+ bus_space_write_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \
+ ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \
+ ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg), \
+ value)
#define E1000_READ_REG_ARRAY(hw, reg, index) \
- E1000_READ_OFFSET(hw, _E1000_REG_OFFSET(hw, _##reg) + ((index) << 2))
-
-#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
+ bus_space_read_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \
+ ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \
+ ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg) \
+ + ((index) << 2))
#define E1000_WRITE_REG_ARRAY(hw, reg, index, value) \
- E1000_WRITE_OFFSET(hw, _E1000_REG_OFFSET(hw, _##reg) + ((index) << 2), value)
+ bus_space_write_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \
+ ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \
+ ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg) \
+ + ((index) << 2), value)
+
+#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
+#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
#define E1000_WRITE_REG_ARRAY_BYTE(hw, reg, index, value) \
bus_space_write_1( ((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \
- ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \
- _E1000_REG_OFFSET(hw, _##reg) + (index), \
- value)
+ ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \
+ ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg \
+ + index), value)
#define E1000_WRITE_REG_ARRAY_WORD(hw, reg, index, value) \
bus_space_write_2( ((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \
- ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \
- _E1000_REG_OFFSET(hw, _##reg) + (index), \
- value)
-
-#define E1000_WRITE_REG_ARRAY_DWORD(hw, reg, index, value) \
- E1000_WRITE_OFFSET(hw, _E1000_REG_OFFSET(hw, _##reg) + ((index) << 2), value)
+ ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \
+ ((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)
-
-#define em_io_read(hw, port) \
- bus_space_read_4(((struct em_osdep *)(hw)->back)->io_bus_space_tag, \
- ((struct em_osdep *)(hw)->back)->io_bus_space_handle, (port))
-
-#define em_io_write(hw, port, value) \
- bus_space_write_4(((struct em_osdep *)(hw)->back)->io_bus_space_tag, \
- ((struct em_osdep *)(hw)->back)->io_bus_space_handle, (port), \
- (value))
#endif /* _FREEBSD_OS_H_ */
OpenPOWER on IntegriCloud