aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/em/if_em.c
diff options
context:
space:
mode:
authorPrafulla Deuskar <pdeuskar@FreeBSD.org>2003-08-27 21:52:37 +0000
committerPrafulla Deuskar <pdeuskar@FreeBSD.org>2003-08-27 21:52:37 +0000
commit3a47a99d78722cf543c0e90caf157f8b22d9db12 (patch)
treece908ffb0bfff042753843ad1101e8dac4bc56f9 /sys/dev/em/if_em.c
parent5e1847b4d167c586e715c6cbcbcf88a0aa7b65f2 (diff)
Notes
Diffstat (limited to 'sys/dev/em/if_em.c')
-rw-r--r--sys/dev/em/if_em.c187
1 files changed, 168 insertions, 19 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c
index dd895894f9fd..984f7574a4d7 100644
--- a/sys/dev/em/if_em.c
+++ b/sys/dev/em/if_em.c
@@ -51,7 +51,7 @@ struct adapter *em_adapter_list = NULL;
* Driver version
*********************************************************************/
-char em_driver_version[] = "1.6.6";
+char em_driver_version[] = "1.7.16";
/*********************************************************************
@@ -89,6 +89,16 @@ static em_vendor_info_t em_vendor_info_array[] =
{ 0x8086, 0x101A, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, 0x1026, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, 0x1027, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, 0x1028, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, 0x1075, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, 0x1076, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, 0x1077, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, 0x1078, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, 0x1079, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, 0x107A, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, 0x107B, PCI_ANY_ID, PCI_ANY_ID, 0},
/* required last entry */
{ 0, 0, 0, 0, 0}
};
@@ -163,6 +173,9 @@ static void em_print_debug_info(struct adapter *);
static int em_is_valid_ether_addr(u_int8_t *);
static int em_sysctl_stats(SYSCTL_HANDLER_ARGS);
static int em_sysctl_debug_info(SYSCTL_HANDLER_ARGS);
+static u_int32_t em_fill_descriptors (u_int64_t address,
+ u_int32_t length,
+ PDESC_ARRAY desc_array);
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 *,
@@ -367,7 +380,13 @@ em_attach(device_t dev)
adapter->hw.fc = em_fc_full;
adapter->hw.phy_init_script = 1;
+ adapter->hw.phy_reset_disable = FALSE;
+#ifndef EM_MASTER_SLAVE
+ adapter->hw.master_slave = em_ms_hw_default;
+#else
+ adapter->hw.master_slave = EM_MASTER_SLAVE;
+#endif
/*
* Set the max frame size assuming standard ethernet
* sized frames
@@ -465,6 +484,15 @@ em_attach(device_t dev)
} else
printf("em%d: Speed:N/A Duplex:N/A\n", adapter->unit);
+ /* 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) {
+ adapter->pcix_82544 = TRUE;
+ }
+ else {
+ adapter->pcix_82544 = FALSE;
+ }
INIT_DEBUGOUT("em_attach: end");
splx(s);
return(0);
@@ -525,6 +553,9 @@ em_detach(device_t dev)
adapter->rx_desc_base = NULL;
}
+ /* Free the sysctl tree */
+ sysctl_ctx_free(&adapter->sysctl_ctx);
+
/* Remove from the adapter list */
if (em_adapter_list == adapter)
em_adapter_list = adapter->next;
@@ -641,8 +672,11 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
case SIOCSIFFLAGS:
IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface Flags)");
if (ifp->if_flags & IFF_UP) {
- if (!(ifp->if_flags & IFF_RUNNING))
+ if (!(ifp->if_flags & IFF_RUNNING)) {
+ bcopy(IF_LLADDR(ifp), adapter->hw.mac_addr,
+ ETHER_ADDR_LEN);
em_init(adapter);
+ }
em_disable_promisc(adapter);
em_set_promisc(adapter);
@@ -685,7 +719,7 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
break;
default:
- IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%d)\n", (int)command);
+ IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%x)\n", (int)command);
error = EINVAL;
}
@@ -1052,9 +1086,15 @@ static int
em_encap(struct adapter *adapter, struct mbuf *m_head)
{
u_int32_t txd_upper;
- u_int32_t txd_lower;
+ u_int32_t txd_lower, txd_used = 0, txd_saved = 0;
int i, j, error;
-
+ u_int64_t address;
+
+ /* For 82544 Workaround */
+ DESC_ARRAY desc_array;
+ u_int32_t array_elements;
+ u_int32_t counter;
+
#if __FreeBSD_version < 500000
struct ifvlan *ifv = NULL;
#else
@@ -1118,23 +1158,66 @@ em_encap(struct adapter *adapter, struct mbuf *m_head)
#endif
i = adapter->next_avail_tx_desc;
+ if (adapter->pcix_82544) {
+ txd_saved = i;
+ txd_used = 0;
+ }
for (j = 0; j < q.nsegs; j++) {
- tx_buffer = &adapter->tx_buffer_area[i];
- current_tx_desc = &adapter->tx_desc_base[i];
+ /* If adapter is 82544 and on PCIX bus */
+ if(adapter->pcix_82544) {
+ array_elements = 0;
+ address = htole64(q.segs[j].ds_addr);
+ /*
+ * Check the Address and Length combination and
+ * split the data accordingly
+ */
+ array_elements = em_fill_descriptors(address,
+ htole32(q.segs[j].ds_len),
+ &desc_array);
+ for (counter = 0; counter < array_elements; counter++) {
+ if (txd_used == adapter->num_tx_desc_avail) {
+ adapter->next_avail_tx_desc = txd_saved;
+ adapter->no_tx_desc_avail2++;
+ bus_dmamap_destroy(adapter->txtag, q.map);
+ return (ENOBUFS);
+ }
+ 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);
+ current_tx_desc->lower.data = htole32(
+ (adapter->txd_cmd | txd_lower |
+ (u_int16_t)desc_array.descriptor[counter].length));
+ current_tx_desc->upper.data = htole32((txd_upper));
+ if (++i == adapter->num_tx_desc)
+ i = 0;
- current_tx_desc->buffer_addr = htole64(q.segs[j].ds_addr);
- current_tx_desc->lower.data = htole32(
- adapter->txd_cmd | txd_lower | q.segs[j].ds_len);
- current_tx_desc->upper.data = htole32(txd_upper);
+ tx_buffer->m_head = NULL;
+ txd_used++;
+ }
+ } else {
+ tx_buffer = &adapter->tx_buffer_area[i];
+ current_tx_desc = &adapter->tx_desc_base[i];
- if (++i == adapter->num_tx_desc)
- i = 0;
+ current_tx_desc->buffer_addr = htole64(q.segs[j].ds_addr);
+ current_tx_desc->lower.data = htole32(
+ adapter->txd_cmd | txd_lower | q.segs[j].ds_len);
+ current_tx_desc->upper.data = htole32(txd_upper);
+
+ if (++i == adapter->num_tx_desc)
+ i = 0;
- tx_buffer->m_head = NULL;
+ tx_buffer->m_head = NULL;
+ }
}
- adapter->num_tx_desc_avail -= q.nsegs;
- adapter->next_avail_tx_desc = i;
+ adapter->next_avail_tx_desc = i;
+ if (adapter->pcix_82544) {
+ adapter->num_tx_desc_avail -= txd_used;
+ }
+ else {
+ adapter->num_tx_desc_avail -= q.nsegs;
+ }
#if __FreeBSD_version < 500000
if (ifv != NULL) {
@@ -1474,7 +1557,7 @@ em_stop(void *arg)
struct adapter * adapter = arg;
ifp = &adapter->interface_data.ac_if;
- INIT_DEBUGOUT("em_stop: begin\n");
+ INIT_DEBUGOUT("em_stop: begin");
em_disable_intr(adapter);
em_reset_hw(&adapter->hw);
untimeout(em_local_timer, adapter, adapter->timer_handle);
@@ -1522,6 +1605,12 @@ em_identify_hardware(struct adapter * adapter)
/* Identify the MAC */
if (em_set_mac_type(&adapter->hw))
printf("em%d: Unknown MAC Type\n", adapter->unit);
+
+ 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;
return;
}
@@ -1629,6 +1718,7 @@ em_free_pci_resources(struct adapter * adapter)
static int
em_hardware_init(struct adapter * adapter)
{
+ INIT_DEBUGOUT("em_hardware_init: begin");
/* Issue a global reset */
em_reset_hw(&adapter->hw);
@@ -1984,6 +2074,7 @@ em_initialize_transmit_unit(struct adapter * adapter)
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 = adapter->txdma.dma_paddr;
E1000_WRITE_REG(&adapter->hw, TDBAL, (u_int32_t)bus_addr);
@@ -2399,6 +2490,7 @@ em_initialize_receive_unit(struct adapter * adapter)
struct ifnet *ifp;
u_int64_t bus_addr;
+ INIT_DEBUGOUT("em_initialize_receive_unit: begin");
ifp = &adapter->interface_data.ac_if;
/* Make sure receives are disabled while setting up the descriptor ring */
@@ -2469,6 +2561,7 @@ em_initialize_receive_unit(struct adapter * adapter)
/* Enable Receives */
E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
+ em_set_promisc(adapter);
return;
}
@@ -2805,6 +2898,59 @@ em_io_write(struct em_hw *hw, uint32_t port, uint32_t value)
return;
}
+/*********************************************************************
+* 82544 Coexistence issue workaround.
+* There are 2 issues.
+* 1. Transmit Hang issue.
+* To detect this issue, following equation can be used...
+* SIZE[3:0] + ADDR[2:0] = SUM[3:0].
+* If SUM[3:0] is in between 1 to 4, we will have this issue.
+*
+* 2. DAC issue.
+* To detect this issue, following equation can be used...
+* SIZE[3:0] + ADDR[2:0] = SUM[3:0].
+* If SUM[3:0] is in between 9 to c, we will have this issue.
+*
+*
+* WORKAROUND:
+* Make sure we do not have ending address as 1,2,3,4(Hang) or 9,a,b,c (DAC)
+*
+*** *********************************************************************/
+static u_int32_t
+em_fill_descriptors (u_int64_t address,
+ u_int32_t length,
+ PDESC_ARRAY desc_array)
+{
+ /* Since issue is sensitive to length and address.*/
+ /* Let us first check the address...*/
+ u_int32_t safe_terminator;
+ if (length <= 4) {
+ desc_array->descriptor[0].address = address;
+ desc_array->descriptor[0].length = length;
+ desc_array->elements = 1;
+ return desc_array->elements;
+ }
+ safe_terminator = (u_int32_t)((((u_int32_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 &&
+ safe_terminator < 9) ||
+ (safe_terminator > 0xC &&
+ safe_terminator <= 0xF)) {
+ desc_array->descriptor[0].address = address;
+ desc_array->descriptor[0].length = length;
+ desc_array->elements = 1;
+ return desc_array->elements;
+ }
+
+ desc_array->descriptor[0].address = address;
+ desc_array->descriptor[0].length = length - 4;
+ desc_array->descriptor[1].address = address + (length - 4);
+ desc_array->descriptor[1].length = 4;
+ desc_array->elements = 2;
+ return desc_array->elements;
+}
+
/**********************************************************************
*
* Update the board statistics counters.
@@ -2815,8 +2961,12 @@ em_update_stats_counters(struct adapter *adapter)
{
struct ifnet *ifp;
+ if(adapter->hw.media_type == em_media_type_copper ||
+ (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
+ adapter->stats.symerrs += E1000_READ_REG(&adapter->hw, SYMERRS);
+ adapter->stats.sec += E1000_READ_REG(&adapter->hw, SEC);
+ }
adapter->stats.crcerrs += E1000_READ_REG(&adapter->hw, CRCERRS);
- adapter->stats.symerrs += E1000_READ_REG(&adapter->hw, SYMERRS);
adapter->stats.mpc += E1000_READ_REG(&adapter->hw, MPC);
adapter->stats.scc += E1000_READ_REG(&adapter->hw, SCC);
adapter->stats.ecol += E1000_READ_REG(&adapter->hw, ECOL);
@@ -2825,7 +2975,6 @@ em_update_stats_counters(struct adapter *adapter)
adapter->stats.latecol += E1000_READ_REG(&adapter->hw, LATECOL);
adapter->stats.colc += E1000_READ_REG(&adapter->hw, COLC);
adapter->stats.dc += E1000_READ_REG(&adapter->hw, DC);
- adapter->stats.sec += E1000_READ_REG(&adapter->hw, SEC);
adapter->stats.rlec += E1000_READ_REG(&adapter->hw, RLEC);
adapter->stats.xonrxc += E1000_READ_REG(&adapter->hw, XONRXC);
adapter->stats.xontxc += E1000_READ_REG(&adapter->hw, XONTXC);