Module Name: src
Committed By: msaitoh
Date: Fri Jun 25 04:03:14 UTC 2010
Modified Files:
src/sys/dev/pci: if_wm.c if_wmreg.h
Log Message:
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
To generate a diff of this commit:
cvs rdiff -u -r1.207 -r1.208 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.41 -r1.42 src/sys/dev/pci/if_wmreg.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.207 src/sys/dev/pci/if_wm.c:1.208
--- src/sys/dev/pci/if_wm.c:1.207 Tue May 25 01:17:55 2010
+++ src/sys/dev/pci/if_wm.c Fri Jun 25 04:03:14 2010
@@ -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;
Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.41 src/sys/dev/pci/if_wmreg.h:1.42
--- src/sys/dev/pci/if_wmreg.h:1.41 Fri Jun 25 03:47:57 2010
+++ src/sys/dev/pci/if_wmreg.h Fri Jun 25 04:03:14 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmreg.h,v 1.41 2010/06/25 03:47:57 msaitoh Exp $ */
+/* $NetBSD: if_wmreg.h,v 1.42 2010/06/25 04:03:14 msaitoh Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -232,6 +232,7 @@
#define STATUS_PCIXSPD_100_133 STATUS_PCIXSPD(2)
#define STATUS_PCIXSPD_MASK STATUS_PCIXSPD(3)
#define STATUS_GIO_M_ENA (1U << 19) /* GIO master enable */
+#define STATUS_DEV_RST_SET (1U << 20) /* Device Reset Set */
#define WMREG_EECD 0x0010 /* EEPROM Control Register */
#define EECD_SK (1U << 0) /* clock */
@@ -280,6 +281,7 @@
#define EEPROM_OFF_K1_CONFIG 0x1b /* NVM K1 Config */
#define EEPROM_OFF_SWDPIN 0x20 /* SWD Pins (Cordova) */
#define EEPROM_OFF_CFG3_PORTA 0x24 /* config word 3 */
+#define EEPROM_ALT_MAC_ADDR_PTR 0x37 /* to the alternative MAC addresses */
#define EEPROM_CFG1_LVDID (1U << 0)
#define EEPROM_CFG1_LSSID (1U << 1)
@@ -323,6 +325,18 @@
#define EEPROM_CFG3_APME (1U << 10)
+#define EEPROM_OFF_MACADDR_LAN1 3 /* macaddr offset from PTR (port 1) */
+#define EEPROM_OFF_MACADDR_LAN2 6 /* macaddr offset from PTR (port 2) */
+#define EEPROM_OFF_MACADDR_LAN3 9 /* macaddr offset from PTR (port 3) */
+
+/*
+ * EEPROM Partitioning. See Table 6-1, "EEPROM Top Level Partitioning"
+ * in 82580's datasheet.
+ */
+#define EEPROM_OFF_LAN1 0x0080 /* Offset for LAN1 (82580)*/
+#define EEPROM_OFF_LAN2 0x00c0 /* Offset for LAN1 (82580)*/
+#define EEPROM_OFF_LAN3 0x0100 /* Offset for LAN1 (82580)*/
+
#define WMREG_EERD 0x0014 /* EEPROM read */
#define EERD_DONE 0x02 /* done bit */
#define EERD_START 0x01 /* First bit for telling part to start operation */
@@ -333,10 +347,13 @@
#define CTRL_EXT_GPI_EN(x) (1U << (x)) /* gpin interrupt enable */
#define CTRL_EXT_SWDPINS_SHIFT 4
#define CTRL_EXT_SWDPINS_MASK 0x0d
-#define CTRL_EXT_SWDPIN(x) (1U << (CTRL_EXT_SWDPINS_SHIFT + (x) - 4))
+/* The bit order of the SW Definable pin is not 6543 but 3654! */
+#define CTRL_EXT_SWDPIN(x) (1U << (CTRL_EXT_SWDPINS_SHIFT \
+ + ((x) == 3 ? 3 : ((x) - 4))))
#define CTRL_EXT_SWDPIO_SHIFT 8
#define CTRL_EXT_SWDPIO_MASK 0x0d
-#define CTRL_EXT_SWDPIO(x) (1U << (CTRL_EXT_SWDPIO_SHIFT + (x) - 4))
+#define CTRL_EXT_SWDPIO(x) (1U << (CTRL_EXT_SWDPIO_SHIFT \
+ + ((x) == 3 ? 3 : ((x) - 4))))
#define CTRL_EXT_ASDCHK (1U << 12) /* ASD check */
#define CTRL_EXT_EE_RST (1U << 13) /* EEPROM reset */
#define CTRL_EXT_IPS (1U << 14) /* invert power state bit 0 */