summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2003-09-11 06:56:46 +0000
committerwpaul <wpaul@FreeBSD.org>2003-09-11 06:56:46 +0000
commitd4a3ccea7c9aa74a42d1df6d9a635c2b8054eaf5 (patch)
tree1f97f1d0d087d2e14ccbbed21f5e267a05ff56b1
parent5d369f4c62f70ea67230f7be1aa4b7a62be2586b (diff)
downloadFreeBSD-src-d4a3ccea7c9aa74a42d1df6d9a635c2b8054eaf5.zip
FreeBSD-src-d4a3ccea7c9aa74a42d1df6d9a635c2b8054eaf5.tar.gz
- For the 8169 chips, read the station address by forcing an EEPROM
autoload and then copying the contends of the station address registers. For some reason, reading the EEPROM on the 8169S doesn't work right. This gets around the problem, and allows us to read the station address correctly on the 8169S. - Insert a delay after initiating packet transmition in re_diag() to allow lots of time for the frame to echo back to the host, and wait for both the 'RX complete' and 'timeout expired' bits in the ISR register to be set. - Deal more intelligently with the fact that the frame length field in the RX descriptor is a different width on the 8139C+ than it is on the 8169/8169S/8110S - For the 8169, you have to set bit 17 in the TX config register to enter digital loopback mode, but for the 8139C+, you have to set both bits 17 and 18. Take this into account so that re_diag() works properly for both types of chips.
-rw-r--r--sys/dev/re/if_re.c86
-rw-r--r--sys/pci/if_rlreg.h10
2 files changed, 65 insertions, 31 deletions
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c
index af763eb..6e21d67 100644
--- a/sys/dev/re/if_re.c
+++ b/sys/dev/re/if_re.c
@@ -740,14 +740,17 @@ re_diag(sc)
/* Queue the packet, start transmission */
IF_HANDOFF(&ifp->if_snd, m0, ifp);
+ CSR_WRITE_2(sc, RL_ISR, 0xFFFF);
re_start(ifp);
m0 = NULL;
/* Wait for it to propagate through the chip */
+ DELAY(100000);
for (i = 0; i < RL_TIMEOUT; i++) {
status = CSR_READ_2(sc, RL_ISR);
- if (status & RL_ISR_RX_OK)
+ if ((status & (RL_ISR_TIMEOUT_EXPIRED|RL_ISR_RX_OK)) ==
+ (RL_ISR_TIMEOUT_EXPIRED|RL_ISR_RX_OK))
break;
DELAY(10);
}
@@ -1155,22 +1158,56 @@ re_attach(dev)
/* Reset the adapter. */
re_reset(sc);
- CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_PROGRAM);
- sc->rl_eecmd_read = RL_EECMD_READ_6BIT;
- re_read_eeprom(sc, (caddr_t)&re_did, 0, 1, 0);
- if (re_did != 0x8129)
- sc->rl_eecmd_read = RL_EECMD_READ_8BIT;
- /*
- * Get station address from the EEPROM.
- */
- re_read_eeprom(sc, (caddr_t)as, RL_EE_EADDR, 3, 0);
- for (i = 0; i < 3; i++) {
- eaddr[(i * 2) + 0] = as[i] & 0xff;
- eaddr[(i * 2) + 1] = as[i] >> 8;
+ hw_rev = re_hwrevs;
+ hwrev = CSR_READ_4(sc, RL_TXCFG) & RL_TXCFG_HWREV;
+ while (hw_rev->rl_desc != NULL) {
+ if (hw_rev->rl_rev == hwrev) {
+ sc->rl_type = hw_rev->rl_type;
+ break;
+ }
+ hw_rev++;
}
- CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
+ if (sc->rl_type == RL_8169) {
+
+ /* Set RX length mask */
+
+ sc->rl_rxlenmask = RL_RDESC_STAT_GFRAGLEN;
+
+ /* Force station address autoload from the EEPROM */
+
+ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_AUTOLOAD);
+ for (i = 0; i < RL_TIMEOUT; i++) {
+ if (!(CSR_READ_1(sc, RL_EECMD) & RL_EEMODE_AUTOLOAD))
+ break;
+ DELAY(100);
+ }
+ if (i == RL_TIMEOUT)
+ printf ("re%d: eeprom autoload timed out\n", unit);
+
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ eaddr[i] = CSR_READ_1(sc, RL_IDR0 + i);
+ } else {
+
+ /* Set RX length mask */
+
+ sc->rl_rxlenmask = RL_RDESC_STAT_FRAGLEN;
+
+ sc->rl_eecmd_read = RL_EECMD_READ_6BIT;
+ re_read_eeprom(sc, (caddr_t)&re_did, 0, 1, 0);
+ if (re_did != 0x8129)
+ sc->rl_eecmd_read = RL_EECMD_READ_8BIT;
+
+ /*
+ * Get station address from the EEPROM.
+ */
+ re_read_eeprom(sc, (caddr_t)as, RL_EE_EADDR, 3, 0);
+ for (i = 0; i < 3; i++) {
+ eaddr[(i * 2) + 0] = as[i] & 0xff;
+ eaddr[(i * 2) + 1] = as[i] >> 8;
+ }
+ }
/*
* A RealTek chip was detected. Inform the world.
@@ -1180,16 +1217,6 @@ re_attach(dev)
sc->rl_unit = unit;
bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
- hw_rev = re_hwrevs;
- hwrev = CSR_READ_4(sc, RL_TXCFG) & RL_TXCFG_HWREV;
- while (hw_rev->rl_desc != NULL) {
- if (hw_rev->rl_rev == hwrev) {
- sc->rl_type = hw_rev->rl_type;
- break;
- }
- hw_rev++;
- }
-
/*
* Allocate the parent bus DMA tag appropriate for PCI.
*/
@@ -2071,9 +2098,14 @@ re_init(xsc)
/*
* Set the initial TX and RX configuration.
*/
- if (sc->rl_testmode)
- CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG|RL_LOOPTEST_ON);
- else
+ if (sc->rl_testmode) {
+ if (sc->rl_type == RL_8169)
+ CSR_WRITE_4(sc, RL_TXCFG,
+ RL_TXCFG_CONFIG|RL_LOOPTEST_ON);
+ else
+ CSR_WRITE_4(sc, RL_TXCFG,
+ RL_TXCFG_CONFIG|RL_LOOPTEST_ON_CPLUS);
+ } else
CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG);
CSR_WRITE_4(sc, RL_RXCFG, RL_RXCFG_CONFIG);
diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h
index 32edf6f..2f2d710 100644
--- a/sys/pci/if_rlreg.h
+++ b/sys/pci/if_rlreg.h
@@ -142,6 +142,7 @@
#define RL_LOOPTEST_OFF 0x00000000
#define RL_LOOPTEST_ON 0x00020000
+#define RL_LOOPTEST_ON_CPLUS 0x00060000
#define RL_HWREV_8169 0x00000000
#define RL_HWREV_8169S 0x04000000
@@ -530,7 +531,7 @@ struct rl_desc {
#define RL_RDESC_CMD_EOR 0x40000000
#define RL_RDESC_CMD_OWN 0x80000000
-#define RL_RDESC_CMD_BUFLEN 0x00003FFF
+#define RL_RDESC_CMD_BUFLEN 0x00001FFF
#define RL_RDESC_STAT_OWN 0x80000000
#define RL_RDESC_STAT_EOR 0x40000000
@@ -550,7 +551,8 @@ struct rl_desc {
#define RL_RDESC_STAT_IPSUMBAD 0x00008000 /* IP header checksum bad */
#define RL_RDESC_STAT_UDPSUMBAD 0x00004000 /* UDP checksum bad */
#define RL_RDESC_STAT_TCPSUMBAD 0x00002000 /* TCP checksum bad */
-#define RL_RDESC_STAT_FRAGLEN 0x00003FFF /* RX'ed frame/frag len */
+#define RL_RDESC_STAT_FRAGLEN 0x00001FFF /* RX'ed frame/frag len */
+#define RL_RDESC_STAT_GFRAGLEN 0x00003FFF /* RX'ed frame/frag len */
#define RL_RDESC_VLANCTL_TAG 0x00010000 /* VLAN tag available
(rl_vlandata valid)*/
@@ -595,8 +597,7 @@ struct rl_stats {
#define RL_IFQ_MAXLEN 512
#define RL_DESC_INC(x) (x = (x + 1) % RL_TX_DESC_CNT)
#define RL_OWN(x) (le32toh((x)->rl_cmdstat) & RL_RDESC_STAT_OWN)
-#define RL_RXBYTES(x) (le32toh((x)->rl_cmdstat) & \
- RL_RDESC_STAT_FRAGLEN)
+#define RL_RXBYTES(x) (le32toh((x)->rl_cmdstat) & sc->rl_rxlenmask)
#define RL_PKTSZ(x) ((x)/* >> 3*/)
#define RL_ADDR_LO(y) ((u_int64_t) (y) & 0xFFFFFFFF)
@@ -669,6 +670,7 @@ struct rl_softc {
struct mbuf *rl_head;
struct mbuf *rl_tail;
u_int32_t rl_hwrev;
+ u_int32_t rl_rxlenmask;
int rl_testmode;
int suspended; /* 0 = normal 1 = suspended */
#ifdef DEVICE_POLLING
OpenPOWER on IntegriCloud