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