PERFORCE change 114016 for review

Sam Leffler sam at FreeBSD.org
Sun Feb 4 22:59:53 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=114016

Change 114016 by sam at sam_ebb on 2007/02/04 22:59:50

	checkpoint AX772 support; needs a bit more work

Affected files ...

.. //depot/projects/wifi/sys/dev/usb/if_axe.c#12 edit
.. //depot/projects/wifi/sys/dev/usb/if_axereg.h#7 edit
.. //depot/projects/wifi/sys/dev/usb/usbdevs#20 edit

Differences ...

==== //depot/projects/wifi/sys/dev/usb/if_axe.c#12 (text+ko) ====

@@ -111,14 +111,17 @@
  * Various supported device vendors/products.
  */
 static struct axe_type axe_devs[] = {
-	{ USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88172 },
-	{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100 },
-	{ USB_VENDOR_JVC, USB_PRODUCT_JVC_MP_PRX1 },
-	{ USB_VENDOR_LINKSYS2, USB_PRODUCT_LINKSYS2_USB200M },
-	{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAU2KTX },
-	{ USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA120 },
-	{ USB_VENDOR_SYSTEMTALKS, USB_PRODUCT_SYSTEMTALKS_SGCX2UL },
-	{ USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_LN029 },
+	{ AX172, USB_VENDOR_ASIX,	USB_PRODUCT_ASIX_AX88172 },
+	{ AX172, USB_VENDOR_DLINK,	USB_PRODUCT_DLINK_DUBE100 },
+	{ AX172, USB_VENDOR_JVC,	USB_PRODUCT_JVC_MP_PRX1 },
+	{ AX172, USB_VENDOR_LINKSYS2,	USB_PRODUCT_LINKSYS2_USB200M },
+	{ AX172, USB_VENDOR_MELCO,	USB_PRODUCT_MELCO_LUAU2KTX },
+	{ AX172, USB_VENDOR_NETGEAR,	USB_PRODUCT_NETGEAR_FA120 },
+	{ AX172, USB_VENDOR_SYSTEMTALKS,USB_PRODUCT_SYSTEMTALKS_SGCX2UL },
+	{ AX172, USB_VENDOR_SITECOM,	USB_PRODUCT_SITECOM_LN029 },
+
+	{ AX772, USB_VENDOR_ASIX,	USB_PRODUCT_ASIX_AX88772 },
+	{ AX772, USB_VENDOR_LINKSYS4,	USB_PRODUCT_LINKSYS4_USB200MV2 },
 	{ 0, 0 }
 };
 
@@ -146,6 +149,8 @@
 static void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
 
 static void axe_setmulti(struct axe_softc *);
+static void axe_ax88178_init(struct axe_softc *);
+static void axe_ax88772_init(struct axe_softc *);
 
 static device_method_t axe_methods[] = {
 	/* Device interface */
@@ -276,13 +281,36 @@
 static void
 axe_miibus_statchg(device_t dev)
 {
-#ifdef notdef
 	struct axe_softc	*sc = USBGETSOFTC(dev);
 	struct mii_data		*mii = GET_MII(sc);
-#endif
-	/* doesn't seem to be necessary */
+	int			val, err;
+
+	if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
+		val = AXE_MEDIA_FULL_DUPLEX;
+	else
+		val = 0;
+
+	if ((sc->axe_flags & AX178) || (sc->axe_flags & AX772)) {
+		val |= (AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC);
+
+		switch (IFM_SUBTYPE(mii->mii_media_active)) {
+		case IFM_1000_T:
+			val |= AXE_178_MEDIA_GMII | AXE_178_MEDIA_ENCK;
+			break;
+		case IFM_100_TX:
+			val |= AXE_178_MEDIA_100TX;
+			break;
+		case IFM_10_T:
+			/* doesn't need to be handled */
+			break;
+		}
+	}
 
-	return;
+	err = axe_cmd(sc, AXE_CMD_WRITE_MEDIA, 0, val, NULL);
+	if (err) {
+		printf("axe%d: media change failed\n", sc->axe_unit);
+		return;
+	}
 }
 
 /*
@@ -317,8 +345,6 @@
         mii_pollstat(mii);
         ifmr->ifm_active = mii->mii_media_active;
         ifmr->ifm_status = mii->mii_media_status;
-
-        return;
 }
 
 static void
@@ -344,12 +370,7 @@
 		rxmode &= ~AXE_RXCMD_ALLMULTI;
 
 	IF_ADDR_LOCK(ifp);
-#if __FreeBSD_version >= 500000
-	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
-#else
-	LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
-#endif
-	{
+	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
 		h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
@@ -361,8 +382,80 @@
 	axe_cmd(sc, AXE_CMD_WRITE_MCAST, 0, 0, (void *)&hashtbl);
 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
 	AXE_UNLOCK(sc);
+}
+
+static void
+axe_ax88178_init(struct axe_softc *sc)
+{
+	int gpio0 = 0, phymode = 0;
+	u_int16_t eeprom;
 
-	return;
+	axe_cmd(sc, AXE_CMD_SROM_WR_ENABLE, 0, 0, NULL);
+	/* XXX magic */
+	axe_cmd(sc, AXE_CMD_SROM_READ, 0, 0x0017, &eeprom);
+	axe_cmd(sc, AXE_CMD_SROM_WR_DISABLE, 0, 0, NULL);
+
+	/* if EEPROM is invalid we have to use to GPIO0 */
+	if (eeprom == 0xffff) {
+		phymode = 0;
+		gpio0 = 1;
+	} else {
+		phymode = eeprom & 7;
+		gpio0 = (eeprom & 0x80) ? 0 : 1;
+	}
+
+	axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x008c, NULL);
+	usbd_delay_ms(sc->axe_udev, 40);
+	if ((eeprom >> 8) != 1) {
+		axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL);
+		usbd_delay_ms(sc->axe_udev, 30);
+
+		axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x001c, NULL);
+		usbd_delay_ms(sc->axe_udev, 300);
+
+		axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL);
+		usbd_delay_ms(sc->axe_udev, 30);
+	} else {
+		axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x0004, NULL);
+		usbd_delay_ms(sc->axe_udev, 30);
+		axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x000c, NULL);
+		usbd_delay_ms(sc->axe_udev, 30);
+	}
+
+	/* soft reset */
+	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 0, NULL);
+	usbd_delay_ms(sc->axe_udev, 150);
+	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
+	    AXE_178_RESET_PRL | AXE_178_RESET_MAGIC, NULL);
+	usbd_delay_ms(sc->axe_udev, 150);
+	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
+}
+
+static void
+axe_ax88772_init(struct axe_softc *sc)
+{
+	axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x00b0, NULL);
+	usbd_delay_ms(sc->axe_udev, 40);
+
+	/* ask for embedded PHY */
+	axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x01, NULL);
+	usbd_delay_ms(sc->axe_udev, 10);
+
+	/* power down and reset state, pin reset state */
+	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 0x00, NULL);
+	usbd_delay_ms(sc->axe_udev, 60);
+
+	/* power down/reset state, pin operating state */
+	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 0x48, NULL);
+	usbd_delay_ms(sc->axe_udev, 150);
+
+	/* power up, reset */
+	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 0x08, NULL);
+
+	/* power up, operating */
+	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 0x28, NULL);
+
+	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
 }
 
 static void
@@ -383,27 +476,26 @@
 	return;
 }
 
+static int
+axe_devflags(int vendor, int product)
+{
+	struct axe_type *t;
+
+	for (t = axe_devs; t->axe_vid != 0; t++)
+		if (t->axe_vid == vendor && t->axe_did == product)
+			return t->axe_flags;
+	return 0;
+}
+
 /*
  * Probe for a AX88172 chip.
  */
 USB_MATCH(axe)
 {
 	USB_MATCH_START(axe, uaa);
-	struct axe_type			*t;
 
-	if (!uaa->iface)
-		return(UMATCH_NONE);
-
-	t = axe_devs;
-	while(t->axe_vid) {
-		if (uaa->vendor == t->axe_vid &&
-		    uaa->product == t->axe_did) {
-			return(UMATCH_VENDOR_PRODUCT);
-		}
-		t++;
-	}
-
-	return(UMATCH_NONE);
+	return (!uaa->iface || axe_devflags(uaa->vendor, uaa->product) == 0 ?
+		UMATCH_NONE : UMATCH_VENDOR_PRODUCT);
 }
 
 /*
@@ -424,6 +516,7 @@
 	sc->axe_udev = uaa->device;
 	sc->axe_dev = self;
 	sc->axe_unit = device_get_unit(self);
+	sc->axe_flags = axe_devflags(uaa->vendor, uaa->product);
 
 	if (usbd_set_config_no(sc->axe_udev, AXE_CONFIG_NO, 1)) {
 		printf("axe%d: getting interface handle failed\n",
@@ -444,7 +537,9 @@
 
 	usbd_devinfo(uaa->device, 0, devinfo);
 	device_set_desc_copy(self, devinfo);
-	printf("%s: %s\n", device_get_nameunit(self), devinfo);
+	printf("%s: %s%s\n", device_get_nameunit(self), devinfo,
+		sc->axe_flags & AX178 ? ", AX88178" :
+		sc->axe_flags & AX772 ? ", AX88772" : "");
 
 	/* Find endpoints. */
 	for (i = 0; i < id->bNumEndpoints; i++) {
@@ -466,18 +561,24 @@
 		}
 	}
 
-#if __FreeBSD_version >= 500000
 	mtx_init(&sc->axe_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK,
 	    MTX_DEF | MTX_RECURSE);
-#endif
 	sx_init(&sc->axe_sleeplock, device_get_nameunit(self));
 	AXE_SLEEPLOCK(sc);
 	AXE_LOCK(sc);
 
+	if (sc->axe_flags & AX178)
+		axe_ax88178_init(sc);
+	else if (sc->axe_flags & AX772)
+		axe_ax88772_init(sc);
+
 	/*
 	 * Get station address.
 	 */
-	axe_cmd(sc, AXE_CMD_READ_NODEID, 0, 0, &eaddr);
+	if (sc->axe_flags & (AX178|AX772))
+		axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, &eaddr);
+	else
+		axe_cmd(sc, AXE_CMD_READ_NODEID, 0, 0, &eaddr);
 
 	/*
 	 * Load IPG values and PHY indexes.
@@ -497,9 +598,7 @@
 		AXE_UNLOCK(sc);
 		AXE_SLEEPUNLOCK(sc);
 		sx_destroy(&sc->axe_sleeplock);
-#if __FreeBSD_version >= 500000
 		mtx_destroy(&sc->axe_mtx);
-#endif
 		USB_ATTACH_ERROR_RETURN;
 	}
 	ifp->if_softc = sc;
@@ -523,9 +622,7 @@
 		AXE_UNLOCK(sc);
 		AXE_SLEEPUNLOCK(sc);
 		sx_destroy(&sc->axe_sleeplock);
-#if __FreeBSD_version >= 500000
 		mtx_destroy(&sc->axe_mtx);
-#endif
 		USB_ATTACH_ERROR_RETURN;
 	}
 
@@ -533,11 +630,7 @@
 	 * Call MI attach routine.
 	 */
 
-#if __FreeBSD_version >= 500000
 	ether_ifattach(ifp, eaddr);
-#else
-	ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
-#endif
 	callout_handle_init(&sc->axe_stat_ch);
 	usb_register_netisr();
 
@@ -563,12 +656,8 @@
 	untimeout(axe_tick, sc, sc->axe_stat_ch);
 	usb_rem_task(sc->axe_udev, &sc->axe_tick_task);
 
-#if __FreeBSD_version >= 500000
 	ether_ifdetach(ifp);
 	if_free(ifp);
-#else
-	ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
-#endif
 
 	if (sc->axe_ep[AXE_ENDPT_TX] != NULL)
 		usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]);
@@ -579,9 +668,7 @@
 
 	AXE_UNLOCK(sc);
 	sx_destroy(&sc->axe_sleeplock);
-#if __FreeBSD_version >= 500000
 	mtx_destroy(&sc->axe_mtx);
-#endif
 
 	return(0);
 }
@@ -915,12 +1002,24 @@
 	}
 
 	/* Set transmitter IPG values */
-	axe_cmd(sc, AXE_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL);
-	axe_cmd(sc, AXE_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL);
-	axe_cmd(sc, AXE_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL);
+	if (sc->axe_flags & (AX178|AX772)) {
+		axe_cmd(sc, AXE_178_CMD_WRITE_IPG012, sc->axe_ipgs[2],
+		    (sc->axe_ipgs[1]<<8) | sc->axe_ipgs[0], NULL);
+	} else {
+		axe_cmd(sc, AXE_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL);
+		axe_cmd(sc, AXE_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL);
+		axe_cmd(sc, AXE_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL);
+	}
 
 	/* Enable receiver, set RX mode */
-	rxmode = AXE_RXCMD_UNICAST|AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE;
+	rxmode = AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE;
+	if (sc->axe_flags & (AX178|AX772)) {
+#ifdef notyet
+		if (sc->axe_udev->speed == USB_SPEED_HIGH)
+			rxmode |= AXE_178_RXCMD_MFB;
+#endif
+	} else
+		rxmode |= AXE_RXCMD_UNICAST;
 
 	/* If we want promiscuous mode, set the allframes bit. */
 	if (ifp->if_flags & IFF_PROMISC)

==== //depot/projects/wifi/sys/dev/usb/if_axereg.h#7 (text+ko) ====

@@ -82,7 +82,32 @@
 #define AXE_CMD_WRITE_MONITOR_MODE		0x011D
 #define AXE_CMD_READ_GPIO			0x101E
 #define AXE_CMD_WRITE_GPIO			0x011F
+#define AXE_CMD_SW_RESET_REG			0x0120
+#define AXE_CMD_SW_PHY_STATUS			0x0021
+#define AXE_CMD_SW_PHY_SELECT			0x0122
 
+#define AXE_172_CMD_WRITE_RX_SRAM		0x0103
+#define AXE_172_CMD_WRITE_TX_SRAM		0x0104
+#define AXE_172_CMD_WRITE_IPG0			0x0112
+#define AXE_172_CMD_WRITE_IPG1			0x0113
+#define AXE_172_CMD_WRITE_IPG2			0x0114
+#define AXE_172_CMD_READ_NODEID			0x6017
+#define AXE_172_CMD_WRITE_NODEID		0x6118
+#define AXE_172_CMD_READ_MEDIA			0x101A
+
+#define AXE_178_CMD_WRITE_IPG012		0x0112
+#define AXE_178_CMD_READ_NODEID			0x6013
+#define AXE_178_CMD_WRITE_NODEID		0x6014
+#define AXE_178_CMD_READ_MEDIA			0x201A
+
+#define AXE_178_RESET_RR			0x01
+#define AXE_178_RESET_RT			0x02
+#define AXE_178_RESET_PRTE			0x04
+#define AXE_178_RESET_PRL			0x08
+#define AXE_178_RESET_BZ			0x10
+/* AX88178 documentation says to always write this bit... */
+#define AXE_178_RESET_MAGIC			0x40
+
 #define AXE_RXCMD_PROMISC			0x0001
 #define AXE_RXCMD_ALLMULTI			0x0002
 #define AXE_RXCMD_UNICAST			0x0004
@@ -90,6 +115,22 @@
 #define AXE_RXCMD_MULTICAST			0x0010
 #define AXE_RXCMD_ENABLE			0x0080
 
+#define AXE_178_MEDIA_GMII			0x0001
+#define AXE_MEDIA_FULL_DUPLEX			0x0002
+#define AXE_172_MEDIA_TX_ABORT_ALLOW		0x0004
+/* AX88178 documentation says to always write 1 to reserved bit... */
+#define AXE_178_MEDIA_MAGIC			0x0004
+#define AXE_178_MEDIA_ENCK			0x0008
+#define AXE_172_MEDIA_FLOW_CONTROL_EN		0x0010
+#define AXE_178_MEDIA_RXFLOW_CONTROL_EN		0x0010
+#define AXE_178_MEDIA_TXFLOW_CONTROL_EN		0x0020
+#define AXE_178_MEDIA_JUMBO_EN			0x0040
+#define AXE_178_MEDIA_LTPF_ONLY			0x0080
+#define AXE_178_MEDIA_RX_EN			0x0100
+#define AXE_178_MEDIA_100TX			0x0200
+#define AXE_178_MEDIA_SBP			0x0800
+#define AXE_178_MEDIA_SUPERMAC			0x1000
+
 #define AXE_NOPHY				0xE0
 
 #define AXE_TIMEOUT		1000
@@ -113,6 +154,10 @@
 #define AXE_ENDPT_MAX		0x3
 
 struct axe_type {
+	int			axe_flags;
+#define	AX172	0x0001		/* AX88172 */
+#define	AX178	0x0002		/* AX88178 */
+#define	AX772	0x0004		/* AX88772 */
 	u_int16_t		axe_vid;
 	u_int16_t		axe_did;
 };
@@ -120,13 +165,6 @@
 #define AXE_INC(x, y)		(x) = (x + 1) % y
 
 struct axe_softc {
-#if defined(__FreeBSD__)
-#define GET_MII(sc) (device_get_softc((sc)->axe_miibus))
-#elif defined(__NetBSD__)
-#define GET_MII(sc) (&(sc)->axe_mii)
-#elif defined(__OpenBSD__)
-#define GET_MII(sc) (&(sc)->axe_mii)
-#endif
 	struct ifnet		*axe_ifp;
 	device_t		axe_miibus;
 	device_t		axe_dev;
@@ -136,11 +174,10 @@
 	usbd_pipe_handle	axe_ep[AXE_ENDPT_MAX];
 	int			axe_unit;
 	int			axe_if_flags;
+	int			axe_flags;
 	struct ue_cdata		axe_cdata;
 	struct callout_handle	axe_stat_ch;
-#if __FreeBSD_version >= 500000
 	struct mtx		axe_mtx;
-#endif
 	struct sx		axe_sleeplock;
 	char			axe_dying;
 	int			axe_link;
@@ -151,6 +188,8 @@
 	struct usb_task		axe_tick_task;
 };
 
+#define GET_MII(sc) device_get_softc((sc)->axe_miibus)
+
 #if 0
 #define	AXE_LOCK(_sc)		mtx_lock(&(_sc)->axe_mtx)
 #define	AXE_UNLOCK(_sc)		mtx_unlock(&(_sc)->axe_mtx)

==== //depot/projects/wifi/sys/dev/usb/usbdevs#20 (text+ko) ====

@@ -696,6 +696,7 @@
 
 /* ASIX Electronics products */
 product ASIX AX88172		0x1720  10/100 ethernet
+product ASIX AX88772		0x7720	AX88772
 
 /* ASUS products */
 product ASUS WL167G		0x1707	WL-167g wireless adapter
@@ -1226,6 +1227,7 @@
 product LINKSYS4 WUSB54G	0x000d	WUSB54G wireless adapter
 product LINKSYS4 WUSB54GP	0x0011	WUSB54GP wireless adapter
 product LINKSYS4 HU200TS	0x001a	HU200TS wireless adapter
+product LINKSYS4 USB200MV2	0x0018	USB 2.0 10/100 ethernet
 
 /* Logitech products */
 product LOGITECH M2452		0x0203	M2452 keyboard


More information about the p4-projects mailing list