Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Add support for the new i82540, i82545, and i825...



details:   https://anonhg.NetBSD.org/src/rev/1fb67ffdd940
branches:  trunk
changeset: 534999:1fb67ffdd940
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Thu Aug 08 00:12:08 2002 +0000

description:
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 ++++++++++++++++++++++++++++++++++++++++++++----
 sys/dev/pci/if_wmreg.h |    9 +++-
 2 files changed, 101 insertions(+), 10 deletions(-)

diffs (205 lines):

diff -r 0c38eb0760a0 -r 1fb67ffdd940 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Thu Aug 08 00:11:52 2002 +0000
+++ b/sys/dev/pci/if_wm.c       Thu Aug 08 00:12:08 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.16 2002/08/07 04:53:18 simonb Exp $        */
+/*     $NetBSD: if_wm.c,v 1.17 2002/08/08 00:12:08 thorpej Exp $       */
 
 /*
  * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
@@ -303,6 +303,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++
@@ -474,6 +475,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 },
@@ -572,6 +597,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);
@@ -718,6 +749,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));
 
@@ -2136,18 +2176,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);
@@ -2157,10 +2232,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);
@@ -2170,7 +2246,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);
@@ -2182,7 +2258,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);
+               }
        }
 }
 
diff -r 0c38eb0760a0 -r 1fb67ffdd940 sys/dev/pci/if_wmreg.h
--- a/sys/dev/pci/if_wmreg.h    Thu Aug 08 00:11:52 2002 +0000
+++ b/sys/dev/pci/if_wmreg.h    Thu Aug 08 00:12:08 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wmreg.h,v 1.2 2002/07/14 00:56:22 thorpej Exp $     */
+/*     $NetBSD: if_wmreg.h,v 1.3 2002/08/08 00:12:08 thorpej Exp $     */
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -201,6 +201,8 @@
 #define        STATUS_LU       (1U << 1)       /* link up */
 #define        STATUS_TCKOK    (1U << 2)       /* Tx clock running */
 #define        STATUS_RBCOK    (1U << 3)       /* Rx clock running */
+#define        STATUS_FUNCID_SHIFT 2           /* 82546 function ID */
+#define        STATUS_FUNCID_MASK  3           /* ... */
 #define        STATUS_TXOFF    (1U << 4)       /* Tx paused */
 #define        STATUS_TBIMODE  (1U << 5)       /* fiber mode (Livengood) */
 #define        STATUS_SPEED(x) ((x) << 6)      /* speed indication */
@@ -225,6 +227,11 @@
 #define        EECD_FWE(x)     ((x) << 4)      /* flash write enable control */
 #define        EECD_FWE_DISABLED EECD_FWE(1)
 #define        EECD_FWE_ENABLED  EECD_FWE(2)
+#define        EECD_EE_REQ     (1U << 6)       /* (shared) EEPROM request */
+#define        EECD_EE_GNT     (1U << 7)       /* (shared) EEPROM grant */
+#define        EECD_EE_PRES    (1U << 8)       /* EEPROM present */
+#define        EECD_EE_SIZE    (1U << 9)       /* EEPROM size
+                                          (0 = 64 word, 1 = 256 word) */
 
 #define        UWIRE_OPC_ERASE 0x04            /* MicroWire "erase" opcode */
 #define        UWIRE_OPC_WRITE 0x05            /* MicroWire "write" opcode */



Home | Main Index | Thread Index | Old Index