summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_em.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/if_em.c')
-rw-r--r--sys/dev/pci/if_em.c161
1 files changed, 113 insertions, 48 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index 4e68e57c30b..936272dfdc6 100644
--- a/sys/dev/pci/if_em.c
+++ b/sys/dev/pci/if_em.c
@@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
-/* $OpenBSD: if_em.c,v 1.133 2006/06/28 02:46:54 brad Exp $ */
+/* $OpenBSD: if_em.c,v 1.134 2006/07/03 20:55:55 brad Exp $ */
/* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */
#include <dev/pci/if_em.h>
@@ -45,7 +45,7 @@ int em_display_debug_stats = 0;
* Driver version
*********************************************************************/
-char em_driver_version[] = "5.1.5";
+char em_driver_version[] = "6.0.5";
/*********************************************************************
* PCI Device ID Table
@@ -53,6 +53,8 @@ char em_driver_version[] = "5.1.5";
const struct pci_matchid em_devices[] = {
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80003ES2LAN_CPR_DPT },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80003ES2LAN_SDS_DPT },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80003ES2LAN_CPR_SPT },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80003ES2LAN_SDS_SPT },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EM },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EM_LOM },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EP },
@@ -106,7 +108,12 @@ const struct pci_matchid em_devices[] = {
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573L },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573L_PL_1 },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573L_PL_2 },
- { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573V_PM }
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573V_PM },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IGP_M_AMT },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IGP_AMT },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IGP_C },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IFE },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IGP_M }
};
/*********************************************************************
@@ -182,6 +189,8 @@ struct cfdriver em_cd = {
0, "em", DV_IFNET
};
+static int em_smart_pwr_down = FALSE;
+
/*********************************************************************
* Device identification routine
*
@@ -290,6 +299,10 @@ em_attach(struct device *parent, struct device *self, void *aux)
case em_80003es2lan: /* Limit Jumbo Frame size */
sc->hw.max_frame_size = 9234;
break;
+ case em_ich8lan:
+ /* ICH8 does not support jumbo frames */
+ sc->hw.max_frame_size = ETHER_MAX_LEN;
+ break;
default:
sc->hw.max_frame_size =
MAX_JUMBO_FRAME_SIZE;
@@ -300,10 +313,10 @@ em_attach(struct device *parent, struct device *self, void *aux)
if (sc->hw.mac_type >= em_82544)
tsize = EM_ROUNDUP(sc->num_tx_desc * sizeof(struct em_tx_desc),
- EM_MAX_TXD_82544 * sizeof(struct em_tx_desc));
+ EM_MAX_TXD * sizeof(struct em_tx_desc));
else
tsize = EM_ROUNDUP(sc->num_tx_desc * sizeof(struct em_tx_desc),
- EM_MAX_TXD * sizeof(struct em_tx_desc));
+ EM_MAX_TXD_82543 * sizeof(struct em_tx_desc));
tsize = EM_ROUNDUP(tsize, PAGE_SIZE);
/* Allocate Transmit Descriptor ring */
@@ -602,9 +615,9 @@ em_init(void *arg)
if (ifp->if_flags & IFF_UP) {
if (sc->hw.mac_type >= em_82544)
- sc->num_tx_desc = EM_MAX_TXD_82544;
- else
sc->num_tx_desc = EM_MAX_TXD;
+ else
+ sc->num_tx_desc = EM_MAX_TXD_82543;
sc->num_rx_desc = EM_MAX_RXD;
} else {
sc->num_tx_desc = EM_MIN_TXD;
@@ -615,6 +628,12 @@ em_init(void *arg)
/* Packet Buffer Allocation (PBA)
* Writing PBA sets the receive portion of the buffer
* the remainder is used for the transmit buffer.
+ *
+ * Devices before the 82547 had a Packet Buffer of 64K.
+ * Default allocation: PBA=48K for Rx, leaving 16K for Tx.
+ * After the 82547 the buffer was reduced to 40K.
+ * Default allocation: PBA=30K for Rx, leaving 10K for Tx.
+ * Note: default does not leave enough room for Jumbo Frame >10k.
*/
switch (sc->hw.mac_type) {
case em_82547:
@@ -636,6 +655,9 @@ em_init(void *arg)
/* Jumbo frames not supported */
pba = E1000_PBA_12K; /* 12K for Rx, 20K for Tx */
break;
+ case em_ich8lan:
+ pba = E1000_PBA_8K;
+ break;
default:
/* Devices before 82547 had a Packet Buffer of 64K. */
if (sc->hw.max_frame_size > EM_RXBUFFER_8192)
@@ -1246,6 +1268,8 @@ em_local_timer(void *arg)
splx(s);
}
+#define SPEED_MODE_BIT (1<<21) /* On PCI-E MACs only */
+
void
em_update_link_status(struct em_softc *sc)
{
@@ -1256,6 +1280,15 @@ em_update_link_status(struct em_softc *sc)
em_get_speed_and_duplex(&sc->hw,
&sc->link_speed,
&sc->link_duplex);
+ /* Check if we may set SPEED_MODE bit on PCI-E */
+ if ((sc->link_speed == SPEED_1000) &&
+ ((sc->hw.mac_type == em_82571) ||
+ (sc->hw.mac_type == em_82572))) {
+ int tarc0;
+ tarc0 = E1000_READ_REG(&sc->hw, TARC0);
+ tarc0 |= SPEED_MODE_BIT;
+ E1000_WRITE_REG(&sc->hw, TARC0, tarc0);
+ }
sc->link_active = 1;
sc->smartspeed = 0;
ifp->if_baudrate = sc->link_speed * 1000000;
@@ -1371,18 +1404,33 @@ em_allocate_pci_resources(struct em_softc *sc)
PCI_MAPREG_MEM_TYPE_64BIT)
rid += 4; /* skip high bits, too */
}
+
if (pci_mapreg_map(pa, rid, PCI_MAPREG_TYPE_IO, 0,
- &sc->osdep.em_iobtag,
- &sc->osdep.em_iobhandle,
- &sc->osdep.em_iobase,
- &sc->osdep.em_iosize, 0)) {
+ &sc->osdep.io_bus_space_tag, &sc->osdep.io_bus_space_handle,
+ &sc->osdep.em_iobase, &sc->osdep.em_iosize, 0)) {
printf(": can't find io space\n");
return (ENXIO);
}
- sc->hw.io_base = 0;
+ sc->hw.io_base = sc->osdep.em_iobase;
}
+ /* for ICH8 we need to find the flash memory */
+ if (sc->hw.mac_type == em_ich8lan) {
+ val = pci_conf_read(pa->pa_pc, pa->pa_tag, EM_FLASH);
+ if (PCI_MAPREG_TYPE(val) != PCI_MAPREG_TYPE_MEM) {
+ printf(": flash isn't memory");
+ return (ENXIO);
+ }
+
+ if (pci_mapreg_map(pa, EM_FLASH, PCI_MAPREG_MEM_TYPE(val), 0,
+ &sc->osdep.flash_bus_space_tag, &sc->osdep.flash_bus_space_handle,
+ &sc->osdep.em_flashbase, &sc->osdep.em_flashsize, 0)) {
+ printf(": can't find mem space\n");
+ return (ENXIO);
+ }
+ }
+
if (pci_intr_map(pa, &ih)) {
printf(": couldn't map interrupt\n");
return (ENXIO);
@@ -1411,16 +1459,21 @@ em_free_pci_resources(struct em_softc *sc)
struct pci_attach_args *pa = &sc->osdep.em_pa;
pci_chipset_tag_t pc = pa->pa_pc;
- if(sc->sc_intrhand)
+ if (sc->sc_intrhand)
pci_intr_disestablish(pc, sc->sc_intrhand);
sc->sc_intrhand = 0;
- if(sc->osdep.em_iobase)
- bus_space_unmap(sc->osdep.em_iobtag, sc->osdep.em_iobhandle,
+ if (sc->osdep.em_flashbase)
+ bus_space_unmap(sc->osdep.flash_bus_space_tag, sc->osdep.flash_bus_space_handle,
+ sc->osdep.em_flashsize);
+ sc->osdep.em_flashbase = 0;
+
+ if (sc->osdep.em_iobase)
+ bus_space_unmap(sc->osdep.io_bus_space_tag, sc->osdep.io_bus_space_handle,
sc->osdep.em_iosize);
sc->osdep.em_iobase = 0;
- if(sc->osdep.em_membase)
+ if (sc->osdep.em_membase)
bus_space_unmap(sc->osdep.mem_bus_space_tag, sc->osdep.mem_bus_space_handle,
sc->osdep.em_memsize);
sc->osdep.em_membase = 0;
@@ -1459,6 +1512,17 @@ em_hardware_init(struct em_softc *sc)
return (EIO);
}
+ /* Set up smart power down as default off on newer adapters */
+ if (!em_smart_pwr_down &&
+ (sc->hw.mac_type == em_82571 ||
+ sc->hw.mac_type == em_82572)) {
+ uint16_t phy_tmp = 0;
+ /* speed up time to link by disabling smart power down */
+ em_read_phy_reg(&sc->hw, IGP02E1000_PHY_POWER_MGMT, &phy_tmp);
+ phy_tmp &= ~IGP02E1000_PM_SPD;
+ em_write_phy_reg(&sc->hw, IGP02E1000_PHY_POWER_MGMT, phy_tmp);
+ }
+
/*
* These parameters control the automatic generation (Tx) and
* response (Rx) to Ethernet PAUSE frames.
@@ -1750,22 +1814,22 @@ em_setup_transmit_structures(struct em_softc *sc)
void
em_initialize_transmit_unit(struct em_softc *sc)
{
- u_int32_t reg_tctl, tarc;
+ u_int32_t reg_tctl, reg_tarc;
u_int32_t reg_tipg = 0;
u_int64_t bus_addr;
INIT_DEBUGOUT("em_initialize_transmit_unit: begin");
/* Setup the Base and Length of the Tx Descriptor Ring */
bus_addr = sc->txdma.dma_map->dm_segs[0].ds_addr;
- E1000_WRITE_REG(&sc->hw, TDBAL, (u_int32_t)bus_addr);
- E1000_WRITE_REG(&sc->hw, TDBAH, (u_int32_t)(bus_addr >> 32));
E1000_WRITE_REG(&sc->hw, TDLEN,
sc->num_tx_desc *
sizeof(struct em_tx_desc));
+ E1000_WRITE_REG(&sc->hw, TDBAH, (u_int32_t)(bus_addr >> 32));
+ E1000_WRITE_REG(&sc->hw, TDBAL, (u_int32_t)bus_addr);
/* Setup the HW Tx Head and Tail descriptor pointers */
- E1000_WRITE_REG(&sc->hw, TDH, 0);
E1000_WRITE_REG(&sc->hw, TDT, 0);
+ E1000_WRITE_REG(&sc->hw, TDH, 0);
HW_DEBUGOUT2("Base = %x, Length = %x\n",
E1000_READ_REG(&sc->hw, TDBAL),
@@ -1797,6 +1861,26 @@ em_initialize_transmit_unit(struct em_softc *sc)
if(sc->hw.mac_type >= em_82540)
E1000_WRITE_REG(&sc->hw, TADV, sc->tx_abs_int_delay);
+ /* Do adapter specific tweaks before we enable the transmitter */
+ if (sc->hw.mac_type == em_82571 || sc->hw.mac_type == em_82572) {
+ reg_tarc = E1000_READ_REG(&sc->hw, TARC0);
+ reg_tarc |= (1 << 25);
+ E1000_WRITE_REG(&sc->hw, TARC0, reg_tarc);
+ reg_tarc = E1000_READ_REG(&sc->hw, TARC1);
+ reg_tarc |= (1 << 25);
+ reg_tarc &= ~(1 << 28);
+ E1000_WRITE_REG(&sc->hw, TARC1, reg_tarc);
+ } else if (sc->hw.mac_type == em_80003es2lan) {
+ reg_tarc = E1000_READ_REG(&sc->hw, TARC0);
+ reg_tarc |= 1;
+ if (sc->hw.media_type == em_media_type_internal_serdes)
+ reg_tarc |= (1 << 20);
+ E1000_WRITE_REG(&sc->hw, TARC0, reg_tarc);
+ reg_tarc = E1000_READ_REG(&sc->hw, TARC1);
+ reg_tarc |= 1;
+ E1000_WRITE_REG(&sc->hw, TARC1, reg_tarc);
+ }
+
/* Program the Transmit Control Register */
reg_tctl = E1000_TCTL_PSP | E1000_TCTL_EN |
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
@@ -1806,30 +1890,9 @@ em_initialize_transmit_unit(struct em_softc *sc)
reg_tctl |= E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT;
else
reg_tctl |= E1000_HDX_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+ /* This write will effectively turn on the transmit unit */
E1000_WRITE_REG(&sc->hw, TCTL, reg_tctl);
- if (sc->hw.mac_type == em_82571 || sc->hw.mac_type == em_82572) {
- tarc = E1000_READ_REG(&sc->hw, TARC0);
- tarc |= ((1 << 25) | (1 << 21));
- E1000_WRITE_REG(&sc->hw, TARC0, tarc);
- tarc = E1000_READ_REG(&sc->hw, TARC1);
- tarc |= (1 << 25);
- if (reg_tctl & E1000_TCTL_MULR)
- tarc &= ~(1 << 28);
- else
- tarc |= (1 << 28);
- E1000_WRITE_REG(&sc->hw, TARC1, tarc);
- } else if (sc->hw.mac_type == em_80003es2lan) {
- tarc = E1000_READ_REG(&sc->hw, TARC0);
- tarc |= 1;
- if (sc->hw.media_type == em_media_type_internal_serdes)
- tarc |= (1 << 20);
- E1000_WRITE_REG(&sc->hw, TARC0, tarc);
- tarc = E1000_READ_REG(&sc->hw, TARC1);
- tarc |= 1;
- E1000_WRITE_REG(&sc->hw, TARC1, tarc);
- }
-
/* Setup Transmit Descriptor Settings for this adapter */
sc->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_RS;
@@ -2186,14 +2249,14 @@ em_initialize_receive_unit(struct em_softc *sc)
/* Setup the Base and Length of the Rx Descriptor Ring */
bus_addr = sc->rxdma.dma_map->dm_segs[0].ds_addr;
- E1000_WRITE_REG(&sc->hw, RDBAL, (u_int32_t)bus_addr);
- E1000_WRITE_REG(&sc->hw, RDBAH, (u_int32_t)(bus_addr >> 32));
E1000_WRITE_REG(&sc->hw, RDLEN, sc->num_rx_desc *
sizeof(struct em_rx_desc));
+ E1000_WRITE_REG(&sc->hw, RDBAH, (u_int32_t)(bus_addr >> 32));
+ E1000_WRITE_REG(&sc->hw, RDBAL, (u_int32_t)bus_addr);
/* Setup the HW Rx Head and Tail Descriptor Pointers */
- E1000_WRITE_REG(&sc->hw, RDH, 0);
E1000_WRITE_REG(&sc->hw, RDT, sc->num_rx_desc - 1);
+ E1000_WRITE_REG(&sc->hw, RDH, 0);
/* Setup the Receive Control Register */
reg_rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
@@ -2735,7 +2798,7 @@ em_update_stats_counters(struct em_softc *sc)
sc->stats.rxerrc +
sc->stats.crcerrs +
sc->stats.algnerrc +
- sc->stats.rlec + sc->stats.rnbc +
+ sc->stats.ruc + sc->stats.roc +
sc->stats.mpc + sc->stats.cexterr +
sc->rx_overruns;
@@ -2769,8 +2832,10 @@ em_print_hw_stats(struct em_softc *sc)
(long long)sc->stats.mpc);
printf("%s: Receive No Buffers = %lld\n", unit,
(long long)sc->stats.rnbc);
- printf("%s: Receive length errors = %lld\n", unit,
- (long long)sc->stats.rlec);
+ /* RLEC is inaccurate on some hardware, calculate our own */
+ printf("%s: Receive Length Errors = %lld\n", unit,
+ ((long long)sc->stats.roc +
+ (long long)sc->stats.ruc));
printf("%s: Receive errors = %lld\n", unit,
(long long)sc->stats.rxerrc);
printf("%s: Crc errors = %lld\n", unit,