Added support for Intel PRO/1000 GT Desktop Adapter(Device ID 8086 107C)

Removed support for Intel 82541ER
Added fix for 82547 which corrects an issue with Jumbo frames larger than 10k.
Added fix for vlan tagged frames not being properly bridged.
Corrected TBI workaround.
Corrected incorrect LED operation issues

Submitted by:	tackerman (Tony Ackerman)
MFC after:	2 weeks
This commit is contained in:
Prafulla Deuskar 2004-09-01 23:22:41 +00:00
parent c78752b94b
commit 9821d34f43
4 changed files with 448 additions and 242 deletions

View File

@ -51,7 +51,7 @@ struct adapter *em_adapter_list = NULL;
* Driver version
*********************************************************************/
char em_driver_version[] = "1.7.25";
char em_driver_version[] = "1.7.35";
/*********************************************************************
@ -80,7 +80,6 @@ static em_vendor_info_t em_vendor_info_array[] =
{ 0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, 0x1014, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, 0x1015, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0},
@ -99,6 +98,7 @@ static em_vendor_info_t em_vendor_info_array[] =
{ 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},
{ 0x8086, 0x107C, PCI_ANY_ID, PCI_ANY_ID, 0},
/* required last entry */
{ 0, 0, 0, 0, 0}
};
@ -742,7 +742,7 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
em_init(adapter);
break;
default:
IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%x)\n", (int)command);
IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%x)", (int)command);
error = EINVAL;
}
@ -797,6 +797,7 @@ em_init_locked(struct adapter * adapter)
{
struct ifnet *ifp;
uint32_t pba;
ifp = &adapter->interface_data.ac_if;
INIT_DEBUGOUT("em_init: begin");
@ -805,6 +806,36 @@ em_init_locked(struct adapter * adapter)
em_stop(adapter);
/* 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.
*/
if(adapter->hw.mac_type < em_82547) {
/* Total FIFO is 64K */
if(adapter->rx_buffer_len > EM_RXBUFFER_8192)
pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */
else
pba = E1000_PBA_48K; /* 48K for Rx, 16K for Tx */
} else {
/* Total FIFO is 40K */
if(adapter->hw.max_frame_size > EM_RXBUFFER_8192) {
pba = E1000_PBA_22K; /* 22K for Rx, 18K for Tx */
} else {
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;
}
INIT_DEBUGOUT1("em_init: pba=%dK",pba);
E1000_WRITE_REG(&adapter->hw, PBA, pba);
/* Get the latest mac address, User can use a LAA */
bcopy(adapter->interface_data.ac_enaddr, adapter->hw.mac_addr,
ETHER_ADDR_LEN);
@ -1138,10 +1169,6 @@ em_tx_cb(void *arg, bus_dma_segment_t *seg, int nsegs, bus_size_t mapsize, int e
bcopy(seg, q->segs, nsegs * sizeof(seg[0]));
}
#define EM_FIFO_HDR 0x10
#define EM_82547_PKT_THRESH 0x3e0
#define EM_82547_TX_FIFO_SIZE 0x2800
#define EM_82547_TX_FIFO_BEGIN 0xf00
/*********************************************************************
*
* This routine maps the mbufs to tx descriptors.
@ -1356,7 +1383,7 @@ em_82547_move_tail_locked(struct adapter *adapter)
if(eop) {
if (em_82547_fifo_workaround(adapter, length)) {
adapter->tx_fifo_wrk++;
adapter->tx_fifo_wrk_cnt++;
callout_reset(&adapter->tx_fifo_timer, 1,
em_82547_move_tail, adapter);
break;
@ -1387,7 +1414,7 @@ em_82547_fifo_workaround(struct adapter *adapter, int len)
fifo_pkt_len = EM_ROUNDUP(len + EM_FIFO_HDR, EM_FIFO_HDR);
if (adapter->link_duplex == HALF_DUPLEX) {
fifo_space = EM_82547_TX_FIFO_SIZE - adapter->tx_fifo_head;
fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
if (fifo_pkt_len >= (EM_82547_PKT_THRESH + fifo_space)) {
if (em_82547_tx_fifo_reset(adapter)) {
@ -1409,8 +1436,8 @@ em_82547_update_fifo_head(struct adapter *adapter, int len)
/* tx_fifo_head is always 16 byte aligned */
adapter->tx_fifo_head += fifo_pkt_len;
if (adapter->tx_fifo_head >= EM_82547_TX_FIFO_SIZE) {
adapter->tx_fifo_head -= EM_82547_TX_FIFO_SIZE;
if (adapter->tx_fifo_head >= adapter->tx_fifo_size) {
adapter->tx_fifo_head -= adapter->tx_fifo_size;
}
return;
@ -1435,17 +1462,17 @@ em_82547_tx_fifo_reset(struct adapter *adapter)
E1000_WRITE_REG(&adapter->hw, TCTL, tctl & ~E1000_TCTL_EN);
/* Reset FIFO pointers */
E1000_WRITE_REG(&adapter->hw, TDFT, EM_82547_TX_FIFO_BEGIN);
E1000_WRITE_REG(&adapter->hw, TDFH, EM_82547_TX_FIFO_BEGIN);
E1000_WRITE_REG(&adapter->hw, TDFTS, EM_82547_TX_FIFO_BEGIN);
E1000_WRITE_REG(&adapter->hw, TDFHS, EM_82547_TX_FIFO_BEGIN);
E1000_WRITE_REG(&adapter->hw, TDFT, adapter->tx_head_addr);
E1000_WRITE_REG(&adapter->hw, TDFH, adapter->tx_head_addr);
E1000_WRITE_REG(&adapter->hw, TDFTS, adapter->tx_head_addr);
E1000_WRITE_REG(&adapter->hw, TDFHS, adapter->tx_head_addr);
/* Re-enable TX unit */
E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
E1000_WRITE_FLUSH(&adapter->hw);
adapter->tx_fifo_head = 0;
adapter->tx_fifo_reset++;
adapter->tx_fifo_reset_cnt++;
return(TRUE);
}
@ -1459,13 +1486,23 @@ em_set_promisc(struct adapter * adapter)
{
u_int32_t reg_rctl;
u_int32_t ctrl;
struct ifnet *ifp = &adapter->interface_data.ac_if;
reg_rctl = E1000_READ_REG(&adapter->hw, RCTL);
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
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
* This enables bridging of vlan tagged frames to occur
* and also allows vlan tags to be seen in tcpdump
*/
ctrl &= ~E1000_CTRL_VME;
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
} else if (ifp->if_flags & IFF_ALLMULTI) {
reg_rctl |= E1000_RCTL_MPE;
reg_rctl &= ~E1000_RCTL_UPE;
@ -1486,6 +1523,7 @@ em_disable_promisc(struct adapter * adapter)
reg_rctl &= (~E1000_RCTL_MPE);
E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
em_enable_vlans(adapter);
return;
}
@ -3169,6 +3207,10 @@ em_print_debug_info(struct adapter *adapter)
uint8_t *hw_addr = adapter->hw.hw_addr;
printf("em%d: Adapter hardware address = %p \n", unit, hw_addr);
printf("em%d:CTRL = 0x%x\n", unit,
E1000_READ_REG(&adapter->hw, CTRL));
printf("em%d:RCTL = 0x%x PS=(0x8402)\n", unit,
E1000_READ_REG(&adapter->hw, RCTL));
printf("em%d:tx_int_delay = %d, tx_abs_int_delay = %d\n", unit,
E1000_READ_REG(&adapter->hw, TIDV),
E1000_READ_REG(&adapter->hw, TADV));
@ -3183,8 +3225,8 @@ em_print_debug_info(struct adapter *adapter)
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);
(long long)adapter->tx_fifo_wrk_cnt,
(long long)adapter->tx_fifo_reset_cnt);
printf("em%d: hw tdh = %d, hw tdt = %d\n", unit,
E1000_READ_REG(&adapter->hw, TDH),
E1000_READ_REG(&adapter->hw, TDT));

View File

@ -399,8 +399,6 @@ struct adapter {
struct mbuf *fmp;
struct mbuf *lmp;
u_int16_t tx_fifo_head;
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
@ -412,8 +410,21 @@ struct adapter {
unsigned long no_tx_desc_avail2;
unsigned long no_tx_map_avail;
unsigned long no_tx_dma_setup;
u_int64_t tx_fifo_reset;
u_int64_t tx_fifo_wrk;
/* Used in for 82547 10Mb Half workaround */
#define EM_PBA_BYTES_SHIFT 0xA
#define EM_TX_HEAD_ADDR_SHIFT 7
#define EM_PBA_TX_MASK 0xFFFF0000
#define EM_FIFO_HDR 0x10
#define EM_82547_PKT_THRESH 0x3e0
u_int32_t tx_fifo_size;
u_int32_t tx_fifo_head;
u_int32_t tx_fifo_head_addr;
u_int64_t tx_fifo_reset_cnt;
u_int64_t tx_fifo_wrk_cnt;
u_int32_t tx_head_addr;
/* For 82544 PCIX Workaround */
boolean_t pcix_82544;

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,7 @@
#include <dev/em/if_em_osdep.h>
#ifndef NO_VERSION_CONTROL
#ident "@(#)$RCSfile: if_em_hw.h,v $$Revision: 1.37 $$Date: 2003/12/20 00:14:51 $"
#ident "@(#)$RCSfile: if_em_hw.h,v $$Revision: 1.41 $$Date: 2004/05/17 15:18:53 $"
#endif
/* Forward declarations of structures used by the shared code */
@ -365,6 +365,7 @@ int32_t em_set_d3_lplu_state(struct em_hw *hw, boolean_t active);
#define E1000_DEV_ID_82547GI 0x1075
#define E1000_DEV_ID_82541GI 0x1076
#define E1000_DEV_ID_82541GI_MOBILE 0x1077
#define E1000_DEV_ID_82541GI_LF 0x107C
#define E1000_DEV_ID_82546GB_COPPER 0x1079
#define E1000_DEV_ID_82546GB_FIBER 0x107A
#define E1000_DEV_ID_82546GB_SERDES 0x107B
@ -378,6 +379,9 @@ int32_t em_set_d3_lplu_state(struct em_hw *hw, boolean_t active);
#define E1000_82542_2_0_REV_ID 2
#define E1000_82542_2_1_REV_ID 3
#define E1000_REVISION_0 0
#define E1000_REVISION_1 1
#define E1000_REVISION_2 2
#define SPEED_10 10
#define SPEED_100 100
@ -772,6 +776,7 @@ struct em_ffvt_entry {
#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */
#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
#define E1000_HOST_IF 0x08800 /* Host Interface */
#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
@ -908,6 +913,7 @@ struct em_ffvt_entry {
#define E1000_82542_TDFT 0x08018
#define E1000_82542_FFMT E1000_FFMT
#define E1000_82542_FFVT E1000_FFVT
#define E1000_82542_HOST_IF E1000_HOST_IF
/* Statistics counters collected by the MAC */
struct em_hw_stats {
@ -1443,6 +1449,10 @@ struct em_hw {
#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */
#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MAC address
* filtering */
#define E1000_MANC_EN_MNG2HOST 0x00200000 /* Enable MNG packets to host
* memory */
#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */
#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */
#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */
@ -1489,6 +1499,7 @@ struct em_hw {
#define EEPROM_COMPAT 0x0003
#define EEPROM_ID_LED_SETTINGS 0x0004
#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */
#define EEPROM_PHY_CLASS_WORD 0x0007
#define EEPROM_INIT_CONTROL1_REG 0x000A
#define EEPROM_INIT_CONTROL2_REG 0x000F
#define EEPROM_INIT_CONTROL3_PORT_B 0x0014
@ -1522,6 +1533,9 @@ struct em_hw {
/* Mask bits for SERDES amplitude adjustment in Word 6 of the EEPROM */
#define EEPROM_SERDES_AMPLITUDE_MASK 0x000F
/* Mask bit for PHY class in Word 7 of the EEPROM */
#define EEPROM_PHY_CLASS_A 0x8000
/* Mask bits for fields in Word 0x0a of the EEPROM */
#define EEPROM_WORD0A_ILOS 0x0010
#define EEPROM_WORD0A_SWDPIO 0x01E0
@ -1549,7 +1563,7 @@ struct em_hw {
#define PBA_SIZE 4
/* Collision related configuration parameters */
#define E1000_COLLISION_THRESHOLD 16
#define E1000_COLLISION_THRESHOLD 15
#define E1000_CT_SHIFT 4
#define E1000_COLLISION_DISTANCE 64
#define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE
@ -2015,7 +2029,7 @@ struct em_hw {
#define IGP01E1000_PSSR_MDIX_SHIFT 0x000B /* shift right 11 */
/* IGP01E1000 Specific Port Control Register - R/W */
#define IGP01E1000_PSCR_TP_LOOPBACK 0x0001
#define IGP01E1000_PSCR_TP_LOOPBACK 0x0010
#define IGP01E1000_PSCR_CORRECT_NC_SCMBLR 0x0200
#define IGP01E1000_PSCR_TEN_CRS_SELECT 0x0400
#define IGP01E1000_PSCR_FLIP_CHIP 0x0800
@ -2025,16 +2039,18 @@ struct em_hw {
/* IGP01E1000 Specific Port Link Health Register */
#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000
#define IGP01E1000_PLHR_GIG_SCRAMBLER_ERROR 0x4000
#define IGP01E1000_PLHR_MASTER_FAULT 0x2000
#define IGP01E1000_PLHR_MASTER_RESOLUTION 0x1000
#define IGP01E1000_PLHR_GIG_REM_RCVR_NOK 0x0800 /* LH */
#define IGP01E1000_PLHR_IDLE_ERROR_CNT_OFLOW 0x0400 /* LH */
#define IGP01E1000_PLHR_DATA_ERR_1 0x0200 /* LH */
#define IGP01E1000_PLHR_DATA_ERR_0 0x0100
#define IGP01E1000_PLHR_AUTONEG_FAULT 0x0010
#define IGP01E1000_PLHR_AUTONEG_ACTIVE 0x0008
#define IGP01E1000_PLHR_VALID_CHANNEL_D 0x0004
#define IGP01E1000_PLHR_VALID_CHANNEL_C 0x0002
#define IGP01E1000_PLHR_VALID_CHANNEL_B 0x0001
#define IGP01E1000_PLHR_VALID_CHANNEL_A 0x0000
#define IGP01E1000_PLHR_AUTONEG_FAULT 0x0040
#define IGP01E1000_PLHR_AUTONEG_ACTIVE 0x0010
#define IGP01E1000_PLHR_VALID_CHANNEL_D 0x0008
#define IGP01E1000_PLHR_VALID_CHANNEL_C 0x0004
#define IGP01E1000_PLHR_VALID_CHANNEL_B 0x0002
#define IGP01E1000_PLHR_VALID_CHANNEL_A 0x0001
/* IGP01E1000 Channel Quality Register */
#define IGP01E1000_MSE_CHANNEL_D 0x000F