Module Name:    src
Committed By:   msaitoh
Date:           Wed Sep  3 14:30:04 UTC 2014

Modified Files:
        src/sys/dev/pci: if_wm.c if_wmreg.h

Log Message:
Read SFF SFP ROM and configure driver from the value.


To generate a diff of this commit:
cvs rdiff -u -r1.294 -r1.295 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.62 -r1.63 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.294 src/sys/dev/pci/if_wm.c:1.295
--- src/sys/dev/pci/if_wm.c:1.294	Mon Sep  1 16:42:27 2014
+++ src/sys/dev/pci/if_wm.c	Wed Sep  3 14:30:04 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wm.c,v 1.294 2014/09/01 16:42:27 msaitoh Exp $	*/
+/*	$NetBSD: if_wm.c,v 1.295 2014/09/03 14:30:04 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -82,7 +82,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.294 2014/09/01 16:42:27 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.295 2014/09/03 14:30:04 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -624,7 +624,8 @@ static int	wm_tbi_mediachange(struct ifn
 static void	wm_tbi_set_linkled(struct wm_softc *);
 static void	wm_tbi_check_link(struct wm_softc *);
 /* SFP related */
-static uint32_t	wm_get_sfp_media_type(struct wm_softc *);
+static int	wm_sfp_read_data_byte(struct wm_softc *, uint16_t, uint8_t *);
+static uint32_t	wm_sfp_get_media_type(struct wm_softc *);
 
 /*
  * NVM related.
@@ -2075,7 +2076,7 @@ wm_attach(device_t parent, device_t self
 				aprint_verbose_dev(sc->sc_dev, "SGMII(I2C)\n");
 				/*FALLTHROUGH*/
 			case CTRL_EXT_LINK_MODE_PCIE_SERDES:
-				sc->sc_mediatype = wm_get_sfp_media_type(sc);
+				sc->sc_mediatype = wm_sfp_get_media_type(sc);
 				if (sc->sc_mediatype == WMP_F_UNKNOWN) {
 					if (link_mode
 					    == CTRL_EXT_LINK_MODE_SGMII) {
@@ -2110,6 +2111,7 @@ wm_attach(device_t parent, device_t self
 				break;
 			case CTRL_EXT_LINK_MODE_GMII:
 			default:
+				aprint_verbose_dev(sc->sc_dev, "Copper\n");
 				sc->sc_mediatype = WMP_F_COPPER;
 				break;
 			}
@@ -7578,12 +7580,91 @@ wm_tbi_check_link(struct wm_softc *sc)
 }
 
 /* SFP related */
+
+static int
+wm_sfp_read_data_byte(struct wm_softc *sc, uint16_t offset, uint8_t *data)
+{
+	uint32_t i2ccmd;
+	int i;
+
+	i2ccmd = (offset << I2CCMD_REG_ADDR_SHIFT) | I2CCMD_OPCODE_READ;
+	CSR_WRITE(sc, WMREG_I2CCMD, i2ccmd);
+
+	/* Poll the ready bit */
+	for (i = 0; i < I2CCMD_PHY_TIMEOUT; i++) {
+		delay(50);
+		i2ccmd = CSR_READ(sc, WMREG_I2CCMD);
+		if (i2ccmd & I2CCMD_READY)
+			break;
+	}
+	if ((i2ccmd & I2CCMD_READY) == 0)
+		return -1;
+	if ((i2ccmd & I2CCMD_ERROR) != 0)
+		return -1;
+
+	*data = i2ccmd & 0x00ff;
+
+	return 0;
+}
+
 static uint32_t
-wm_get_sfp_media_type(struct wm_softc *sc)
+wm_sfp_get_media_type(struct wm_softc *sc)
 {
+	uint32_t ctrl_ext;
+	uint8_t val = 0;
+	int timeout = 3;
+	uint32_t mediatype = WMP_F_UNKNOWN;
+	int rv = -1;
 
-	/* XXX */
-	return WMP_F_SERDES;
+	ctrl_ext = CSR_READ(sc, WMREG_CTRL_EXT);
+	ctrl_ext &= ~CTRL_EXT_SWDPIN(3);
+	CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext | CTRL_EXT_I2C_ENA);
+	CSR_WRITE_FLUSH(sc);
+
+	/* Read SFP module data */
+	while (timeout) {
+		rv = wm_sfp_read_data_byte(sc, SFF_SFP_ID_OFF, &val);
+		if (rv == 0)
+			break;
+		delay(100*1000); /* XXX too big */
+		timeout--;
+	}
+	if (rv != 0)
+		goto out;
+	switch (val) {
+	case SFF_SFP_ID_SFF:
+		aprint_normal_dev(sc->sc_dev,
+		    "Module/Connector soldered to board\n");
+		break;
+	case SFF_SFP_ID_SFP:
+		aprint_normal_dev(sc->sc_dev, "SFP\n");
+		break;
+	case SFF_SFP_ID_UNKNOWN:
+		goto out;
+	default:
+		break;
+	}
+
+	rv = wm_sfp_read_data_byte(sc, SFF_SFP_ETH_FLAGS_OFF, &val);
+	if (rv != 0) {
+		goto out;
+	}
+
+	if ((val & (SFF_SFP_ETH_FLAGS_1000SX | SFF_SFP_ETH_FLAGS_1000LX)) != 0)
+		mediatype = WMP_F_SERDES;
+	else if ((val & SFF_SFP_ETH_FLAGS_1000T) != 0){
+		sc->sc_flags |= WM_F_SGMII;
+		mediatype = WMP_F_COPPER;
+	} else if ((val & SFF_SFP_ETH_FLAGS_100FX) != 0){
+		sc->sc_flags |= WM_F_SGMII;
+		mediatype = WMP_F_SERDES;
+	}
+
+out:
+	/* Restore I2C interface setting */
+	CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext);
+
+	return mediatype;
 }
 /*
  * NVM related.

Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.62 src/sys/dev/pci/if_wmreg.h:1.63
--- src/sys/dev/pci/if_wmreg.h:1.62	Mon Sep  1 16:42:27 2014
+++ src/sys/dev/pci/if_wmreg.h	Wed Sep  3 14:30:04 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmreg.h,v 1.62 2014/09/01 16:42:27 msaitoh Exp $	*/
+/*	$NetBSD: if_wmreg.h,v 1.63 2014/09/03 14:30:04 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -1035,6 +1035,20 @@ struct livengood_tcpip_ctxdesc {
 /* for PCI express Capability registers */
 #define	WM_PCIE_DCSR2_16MS	0x00000005
 
+/* SFF SFP ROM data */
+#define SFF_SFP_ID_OFF		0x00
+#define SFF_SFP_ID_UNKNOWN	0x00	/* Unknown */
+#define SFF_SFP_ID_SFF		0x02	/* Module soldered to motherboard */
+#define SFF_SFP_ID_SFP		0x03	/* SFP transceiver */
+
+#define SFF_SFP_ETH_FLAGS_OFF	0x06
+#define SFF_SFP_ETH_FLAGS_1000SX	0x01
+#define SFF_SFP_ETH_FLAGS_1000LX	0x02
+#define SFF_SFP_ETH_FLAGS_1000CX	0x04
+#define SFF_SFP_ETH_FLAGS_1000T		0x08
+#define SFF_SFP_ETH_FLAGS_100FX		0x10
+
+
 /* advanced TX descriptor for 82575 and newer */
 typedef union nq_txdesc {
 	struct {

Reply via email to