Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-6]: src/sys/dev/pci Pull up revision 1.17 (requested by thorpej...
details: https://anonhg.NetBSD.org/src/rev/1ccf4a3cb368
branches: netbsd-1-6
changeset: 529299:1ccf4a3cb368
user: tron <tron%NetBSD.org@localhost>
date: Fri Nov 08 08:50:24 2002 +0000
description:
Pull up revision 1.17 (requested by thorpej in ticket #650):
Add support for the new i82540, i82545, and i82546 Gig-E chips. The
i82546 chip has 2 Gig-E interfaces in a single chip.
The main difference is these chips have a special handshaking protocol
for accessing the EEPROM (due to the shared nature on the i82546).
diffstat:
sys/dev/pci/if_wm.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 93 insertions(+), 9 deletions(-)
diffs (175 lines):
diff -r a0233b89fe6b -r 1ccf4a3cb368 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c Fri Nov 08 00:13:09 2002 +0000
+++ b/sys/dev/pci/if_wm.c Fri Nov 08 08:50:24 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.9.4.7 2002/11/07 20:05:02 tron Exp $ */
+/* $NetBSD: if_wm.c,v 1.9.4.8 2002/11/08 08:50:24 tron Exp $ */
/*
* Copyright (c) 2001, 2002 Wasabi Systems, Inc.
@@ -296,6 +296,7 @@
/* sc_flags */
#define WM_F_HAS_MII 0x01 /* has MII */
+#define WM_F_EEPROM_HANDSHAKE 0x02 /* requires EEPROM handshake */
#ifdef WM_EVENT_COUNTERS
#define WM_EVCNT_INCR(ev) (ev)->ev_count++
@@ -467,6 +468,30 @@
"Intel i82544GC (LOM) 1000BASE-T Ethernet",
WM_T_82544, WMP_F_1000T },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EM,
+ "Intel i82540EM 1000BASE-T Ethernet",
+ WM_T_82540, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82545EM_COPPER,
+ "Intel i82545EM 1000BASE-T Ethernet",
+ WM_T_82545, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546EB_COPPER,
+ "Intel i82546EB 1000BASE-T Ethernet",
+ WM_T_82546, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82545EM_FIBER,
+ "Intel i82545EM 1000BASE-X Ethernet",
+ WM_T_82545, WMP_F_1000X },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546EB_FIBER,
+ "Intel i82546EB 1000BASE-X Ethernet",
+ WM_T_82546, WMP_F_1000X },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EM_LOM,
+ "Intel i82540EM (LOM) 1000BASE-T Ethernet",
+ WM_T_82540, WMP_F_1000T },
+
{ 0, 0,
NULL,
0, 0 },
@@ -565,6 +590,12 @@
}
/*
+ * Some chips require a handshake to access the EEPROM.
+ */
+ if (sc->sc_type >= WM_T_82540)
+ sc->sc_flags |= WM_F_EEPROM_HANDSHAKE;
+
+ /*
* Map the device.
*/
memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, WM_PCI_MMBA);
@@ -711,6 +742,15 @@
enaddr[4] = myea[2] & 0xff;
enaddr[5] = myea[2] >> 8;
+ /*
+ * Toggle the LSB of the MAC address on the second port
+ * of the i82546.
+ */
+ if (sc->sc_type == WM_T_82546) {
+ if ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1)
+ enaddr[5] ^= 1;
+ }
+
printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
ether_sprintf(enaddr));
@@ -2130,18 +2170,53 @@
wm_read_eeprom(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
{
uint32_t reg;
- int i, x;
+ int i, x, addrbits = 6;
for (i = 0; i < wordcnt; i++) {
- /* Send CHIP SELECT for one clock tick. */
- CSR_WRITE(sc, WMREG_EECD, EECD_CS);
+ if (sc->sc_flags & WM_F_EEPROM_HANDSHAKE) {
+ reg = CSR_READ(sc, WMREG_EECD);
+
+ /* Get number of address bits. */
+ if (reg & EECD_EE_SIZE)
+ addrbits = 8;
+
+ /* Request EEPROM access. */
+ reg |= EECD_EE_REQ;
+ CSR_WRITE(sc, WMREG_EECD, reg);
+
+ /* ..and wait for it to be granted. */
+ for (x = 0; x < 100; x++) {
+ reg = CSR_READ(sc, WMREG_EECD);
+ if (reg & EECD_EE_GNT)
+ break;
+ delay(5);
+ }
+ if ((reg & EECD_EE_GNT) == 0) {
+ printf("%s: could not acquire EEPROM GNT\n",
+ sc->sc_dev.dv_xname);
+ *data = 0xffff;
+ reg &= ~EECD_EE_REQ;
+ CSR_WRITE(sc, WMREG_EECD, reg);
+ continue;
+ }
+ } else
+ reg = 0;
+
+ /* Clear SK and DI. */
+ reg &= ~(EECD_SK | EECD_DI);
+ CSR_WRITE(sc, WMREG_EECD, reg);
+
+ /* Set CHIP SELECT. */
+ reg |= EECD_CS;
+ CSR_WRITE(sc, WMREG_EECD, reg);
delay(2);
/* Shift in the READ command. */
for (x = 3; x > 0; x--) {
- reg = EECD_CS;
if (UWIRE_OPC_READ & (1 << (x - 1)))
reg |= EECD_DI;
+ else
+ reg &= ~EECD_DI;
CSR_WRITE(sc, WMREG_EECD, reg);
delay(2);
CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
@@ -2151,10 +2226,11 @@
}
/* Shift in address. */
- for (x = 6; x > 0; x--) {
- reg = EECD_CS;
+ for (x = addrbits; x > 0; x--) {
if ((word + i) & (1 << (x - 1)))
reg |= EECD_DI;
+ else
+ reg &= ~EECD_DI;
CSR_WRITE(sc, WMREG_EECD, reg);
delay(2);
CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
@@ -2164,7 +2240,7 @@
}
/* Shift out the data. */
- reg = EECD_CS;
+ reg &= ~EECD_DI;
data[i] = 0;
for (x = 16; x > 0; x--) {
CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
@@ -2176,7 +2252,15 @@
}
/* Clear CHIP SELECT. */
- CSR_WRITE(sc, WMREG_EECD, 0);
+ reg &= ~EECD_CS;
+ CSR_WRITE(sc, WMREG_EECD, reg);
+ delay(2);
+
+ if (sc->sc_flags & WM_F_EEPROM_HANDSHAKE) {
+ /* Release the EEPROM. */
+ reg &= ~EECD_EE_REQ;
+ CSR_WRITE(sc, WMREG_EECD, reg);
+ }
}
}
Home |
Main Index |
Thread Index |
Old Index