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 some code to support 82580[ER]. Tested on my...



details:   https://anonhg.NetBSD.org/src/rev/8e4f1984545d
branches:  trunk
changeset: 755849:8e4f1984545d
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Fri Jun 25 04:03:14 2010 +0000

description:
Add some code to support 82580[ER]. Tested on my own I340-T4.

 - Fix CTRL_EXT_SWDPIN() and CTRL_EXT_SWDPIO() macros. The bit order of the
   SW definable pin is not 6543 but 3654!!!

 - Rewrite the code to read MAC address from eeprom.

 - Add some code to support 82580.

TODO:
 - ukphy -> somephy

diffstat:

 sys/dev/pci/if_wm.c    |  183 +++++++++++++++++++++++++++++++++++++++++-------
 sys/dev/pci/if_wmreg.h |   23 +++++-
 2 files changed, 175 insertions(+), 31 deletions(-)

diffs (truncated from 356 to 300 lines):

diff -r 412a83fd11da -r 8e4f1984545d sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Fri Jun 25 03:47:57 2010 +0000
+++ b/sys/dev/pci/if_wm.c       Fri Jun 25 04:03:14 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.207 2010/05/25 01:17:55 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.208 2010/06/25 04:03:14 msaitoh Exp $      */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.207 2010/05/25 01:17:55 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.208 2010/06/25 04:03:14 msaitoh Exp $");
 
 #include "rnd.h"
 
@@ -510,6 +510,7 @@
 static int     wm_read_eeprom(struct wm_softc *, int, int, u_int16_t *);
 static int     wm_read_eeprom_eerd(struct wm_softc *, int, int, u_int16_t *);
 static int     wm_validate_eeprom_checksum(struct wm_softc *);
+static int     wm_read_mac_addr(struct wm_softc *, uint8_t *);
 static void    wm_tick(void *);
 
 static void    wm_set_filter(struct wm_softc *);
@@ -1098,7 +1099,7 @@
        prop_data_t ea;
        prop_number_t pn;
        uint8_t enaddr[ETHER_ADDR_LEN];
-       uint16_t myea[ETHER_ADDR_LEN / 2], cfg1, cfg2, swdpin, io3;
+       uint16_t cfg1, cfg2, swdpin, io3;
        pcireg_t preg, memtype;
        uint16_t eeprom_data, apme_mask;
        uint32_t reg;
@@ -1246,7 +1247,8 @@
         */
        if ((sc->sc_type == WM_T_82546) || (sc->sc_type == WM_T_82546_3)
            || (sc->sc_type ==  WM_T_82571) || (sc->sc_type == WM_T_80003)
-           || (sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576))
+           || (sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)
+           || (sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER))
                sc->sc_funcid = (CSR_READ(sc, WMREG_STATUS)
                    >> STATUS_FUNCID_SHIFT) & STATUS_FUNCID_MASK;
        else
@@ -1605,29 +1607,10 @@
                KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN);
                memcpy(enaddr, prop_data_data_nocopy(ea), ETHER_ADDR_LEN);
        } else {
-               if (wm_read_eeprom(sc, EEPROM_OFF_MACADDR,
-                   sizeof(myea) / sizeof(myea[0]), myea)) {
+               if (wm_read_mac_addr(sc, enaddr) != 0)
                        aprint_error_dev(sc->sc_dev,
                            "unable to read Ethernet address\n");
-                       return;
-               }
-               enaddr[0] = myea[0] & 0xff;
-               enaddr[1] = myea[0] >> 8;
-               enaddr[2] = myea[1] & 0xff;
-               enaddr[3] = myea[1] >> 8;
-               enaddr[4] = myea[2] & 0xff;
-               enaddr[5] = myea[2] >> 8;
-       }
-
-       /*
-        * Toggle the LSB of the MAC address on the second port
-        * of the dual port controller.
-        */
-       if ((sc->sc_type == WM_T_82546) || (sc->sc_type == WM_T_82546_3)
-           || (sc->sc_type ==  WM_T_82571) || (sc->sc_type == WM_T_80003)
-           || (sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)) {
-               if (sc->sc_funcid == 1)
-                       enaddr[5] ^= 1;
+               return;
        }
 
        aprint_normal_dev(sc->sc_dev, "Ethernet address %s\n",
@@ -3595,6 +3578,8 @@
        case WM_T_82574:
        case WM_T_82575:
        case WM_T_82576:
+       case WM_T_82580:
+       case WM_T_82580ER:
        case WM_T_82583:
        default:
                /* Everything else can safely use the documented method. */
@@ -3653,6 +3638,8 @@
                break;
        case WM_T_82575:
        case WM_T_82576:
+       case WM_T_82580:
+       case WM_T_82580ER:
        case WM_T_80003:
        case WM_T_ICH8:
        case WM_T_ICH9:
@@ -3671,13 +3658,19 @@
        switch (sc->sc_type) {
        case WM_T_82575:
        case WM_T_82576:
+#if 0 /* XXX */
        case WM_T_82580:
+       case WM_T_82580ER:
+#endif
        case WM_T_ICH8:
        case WM_T_ICH9:
                if ((CSR_READ(sc, WMREG_EECD) & EECD_EE_PRES) == 0) {
                        /* Not found */
                        sc->sc_flags |= WM_F_EEPROM_INVALID;
-                       if (sc->sc_type == WM_T_82575) /* 82575 only */
+                       if ((sc->sc_type == WM_T_82575)
+                           || (sc->sc_type == WM_T_82576)
+                           || (sc->sc_type == WM_T_82580)
+                           || (sc->sc_type == WM_T_82580ER))
                                wm_reset_init_script_82575(sc);
                }
                break;
@@ -3685,6 +3678,11 @@
                break;
        }
 
+       if ((sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)) {
+               /* clear global device reset status bit */
+               CSR_WRITE(sc, WMREG_STATUS, STATUS_DEV_RST_SET);
+       }
+
        /* Clear any pending interrupt events. */
        CSR_WRITE(sc, WMREG_IMC, 0xffffffffU);
        reg = CSR_READ(sc, WMREG_ICR);
@@ -4224,6 +4222,8 @@
        case WM_T_82583:
        case WM_T_82575:
        case WM_T_82576:
+       case WM_T_82580:
+       case WM_T_82580ER:
        case WM_T_80003:
        case WM_T_ICH8:
        case WM_T_ICH9:
@@ -4309,6 +4309,7 @@
        case WM_T_82575:
        case WM_T_82576:
        case WM_T_82580:
+       case WM_T_82580ER:
                mask = EEMNGCTL_CFGDONE_0 << sc->sc_funcid;
                for (i = 0; i < WM_PHY_CFG_TIMEOUT; i++) {
                        if (CSR_READ(sc, WMREG_EEMNGCTL) & mask)
@@ -4692,6 +4693,101 @@
        return done;
 }
 
+static int
+wm_read_mac_addr(struct wm_softc *sc, uint8_t *enaddr)
+{
+       uint16_t myea[ETHER_ADDR_LEN / 2];
+       uint16_t offset;
+       int do_invert = 0;
+
+       if (sc->sc_funcid == 0)
+               offset = EEPROM_OFF_MACADDR;
+       else {
+               switch (sc->sc_type) {
+               case WM_T_82580:
+               case WM_T_82580ER:
+                       switch (sc->sc_funcid) {
+                       case 1:
+                               offset = EEPROM_OFF_LAN1;
+                               break;
+                       case 2:
+                               offset = EEPROM_OFF_LAN2;
+                               break;
+                       case 3:
+                               offset = EEPROM_OFF_LAN3;
+                               break;
+                       default:
+                               goto bad;
+                               /* NOTREACHED */
+                               break;
+                       }
+                       break;
+               case WM_T_82571:
+               case WM_T_82575:
+               case WM_T_82576:
+               case WM_T_80003:
+                       if (wm_read_eeprom(sc, EEPROM_ALT_MAC_ADDR_PTR, 1,
+                               &offset) != 0) {
+                               goto bad;
+                       }
+
+                       /* no pointer */
+                       if (offset == 0xffff) {
+                               /* reset the offset to LAN0 */
+                               offset = EEPROM_OFF_MACADDR;
+                               do_invert = 1;
+                               goto do_read;
+                       }
+
+                       switch (sc->sc_funcid) {
+                       case 1:
+                               offset += EEPROM_OFF_MACADDR_LAN1;
+                               break;
+                       case 2:
+                               offset += EEPROM_OFF_MACADDR_LAN2;
+                               break;
+                       case 3:
+                               offset += EEPROM_OFF_MACADDR_LAN3;
+                               break;
+                       default:
+                               goto bad;
+                               /* NOTREACHED */
+                               break;
+                       }
+                       break;
+               default:
+                       do_invert = 1;
+                       break;
+               }
+       }
+ do_read:
+       if (wm_read_eeprom(sc, offset, sizeof(myea) / sizeof(myea[0]),
+               myea) != 0) {
+               goto bad;
+       }
+
+       enaddr[0] = myea[0] & 0xff;
+       enaddr[1] = myea[0] >> 8;
+       enaddr[2] = myea[1] & 0xff;
+       enaddr[3] = myea[1] >> 8;
+       enaddr[4] = myea[2] & 0xff;
+       enaddr[5] = myea[2] >> 8;
+
+       /*
+        * Toggle the LSB of the MAC address on the second port
+        * of some dual port cards.
+        */
+       if (do_invert != 0)
+               enaddr[5] ^= 1;
+
+       return 0;
+
+ bad:
+       aprint_error_dev(sc->sc_dev, "unable to read Ethernet address\n");
+
+       return -1;
+}
+
 /*
  * wm_add_rxbuf:
  *
@@ -5494,8 +5590,35 @@
        ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, wm_gmii_mediachange,
            wm_gmii_mediastatus);
 
-       mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
-           MII_OFFSET_ANY, MIIF_DOPAUSE);
+       if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)
+           || (sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)) {
+               if ((sc->sc_flags & WM_F_SGMII) == 0) {
+                       /* Attach only one port */
+                       mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, 1,
+                           MII_OFFSET_ANY, MIIF_DOPAUSE);
+               } else {
+                       int i;
+                       uint32_t ctrl_ext;
+
+                       /* Power on sgmii phy if it is disabled */
+                       ctrl_ext = CSR_READ(sc, WMREG_CTRL_EXT);
+                       CSR_WRITE(sc, WMREG_CTRL_EXT,
+                           ctrl_ext &~ CTRL_EXT_SWDPIN(3));
+                       CSR_WRITE_FLUSH(sc);
+                       delay(300*1000); /* XXX too long */
+
+                       /* from 1 to 8 */
+                       for (i = 1; i < 8; i++)
+                               mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff,
+                                   i, MII_OFFSET_ANY, MIIF_DOPAUSE);
+
+                       /* restore previous sfp cage power state */
+                       CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext);
+               }
+       } else {
+               mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
+                   MII_OFFSET_ANY, MIIF_DOPAUSE);
+       }
 
        if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
                /* if failed, retry with *_bm_* */
@@ -7290,6 +7413,10 @@
        case WM_T_82574:
        case WM_T_82575:
        case WM_T_82576:
+#if 0 /* XXX */
+       case WM_T_82580:
+       case WM_T_82580ER:
+#endif
                if ((CSR_READ(sc, WMREG_FWSM) & FWSM_MODE_MASK) != 0)
                        sc->sc_flags |= WM_F_ARC_SUBSYS_VALID;
                sc->sc_flags |= WM_F_ASF_FIRMWARE_PRES;
diff -r 412a83fd11da -r 8e4f1984545d sys/dev/pci/if_wmreg.h
--- a/sys/dev/pci/if_wmreg.h    Fri Jun 25 03:47:57 2010 +0000
+++ b/sys/dev/pci/if_wmreg.h    Fri Jun 25 04:03:14 2010 +0000
@@ -1,4 +1,4 @@



Home | Main Index | Thread Index | Old Index