xref: /openbsd-src/sys/dev/usb/if_axe.c (revision 43003dfe3ad45d1698bed8a37f2b0f5b14f20d4f)
1 /*	$OpenBSD: if_axe.c,v 1.93 2009/09/20 12:53:36 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 2005, 2006, 2007 Jonathan Gray <jsg@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Copyright (c) 1997, 1998, 1999, 2000-2003
21  *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the above copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *	This product includes software developed by Bill Paul.
34  * 4. Neither the name of the author nor the names of any co-contributors
35  *    may be used to endorse or promote products derived from this software
36  *    without specific prior written permission.
37  *
38  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
39  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
42  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
43  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
44  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
48  * THE POSSIBILITY OF SUCH DAMAGE.
49  */
50 
51 #include <sys/cdefs.h>
52 
53 /*
54  * ASIX Electronics AX88172 USB 2.0 ethernet driver. Used in the
55  * LinkSys USB200M and various other adapters.
56  *
57  * Manuals available from:
58  * http://www.asix.com.tw/datasheet/mac/Ax88172.PDF
59  * Note: you need the manual for the AX88170 chip (USB 1.x ethernet
60  * controller) to find the definitions for the RX control register.
61  * http://www.asix.com.tw/datasheet/mac/Ax88170.PDF
62  *
63  * Written by Bill Paul <wpaul@windriver.com>
64  * Senior Engineer
65  * Wind River Systems
66  */
67 
68 /*
69  * The AX88172 provides USB ethernet supports at 10 and 100Mbps.
70  * It uses an external PHY (reference designs use a RealTek chip),
71  * and has a 64-bit multicast hash filter. There is some information
72  * missing from the manual which one needs to know in order to make
73  * the chip function:
74  *
75  * - You must set bit 7 in the RX control register, otherwise the
76  *   chip won't receive any packets.
77  * - You must initialize all 3 IPG registers, or you won't be able
78  *   to send any packets.
79  *
80  * Note that this device appears to only support loading the station
81  * address via autload from the EEPROM (i.e. there's no way to manaully
82  * set it).
83  *
84  * (Adam Weinberger wanted me to name this driver if_gir.c.)
85  */
86 
87 /*
88  * Ported to OpenBSD 3/28/2004 by Greg Taleck <taleck@oz.net>
89  * with bits and pieces from the aue and url drivers.
90  */
91 
92 #include "bpfilter.h"
93 
94 #include <sys/param.h>
95 #include <sys/systm.h>
96 #include <sys/sockio.h>
97 #include <sys/rwlock.h>
98 #include <sys/mbuf.h>
99 #include <sys/kernel.h>
100 #include <sys/proc.h>
101 #include <sys/socket.h>
102 
103 #include <sys/device.h>
104 
105 #include <machine/bus.h>
106 
107 #include <net/if.h>
108 #include <net/if_dl.h>
109 #include <net/if_media.h>
110 
111 #if NBPFILTER > 0
112 #include <net/bpf.h>
113 #endif
114 
115 #ifdef INET
116 #include <netinet/in.h>
117 #include <netinet/in_systm.h>
118 #include <netinet/in_var.h>
119 #include <netinet/ip.h>
120 #include <netinet/if_ether.h>
121 #endif
122 
123 #include <dev/mii/mii.h>
124 #include <dev/mii/miivar.h>
125 
126 #include <dev/usb/usb.h>
127 #include <dev/usb/usbdi.h>
128 #include <dev/usb/usbdi_util.h>
129 #include <dev/usb/usbdivar.h>
130 #include <dev/usb/usbdevs.h>
131 
132 #include <dev/usb/if_axereg.h>
133 
134 #ifdef AXE_DEBUG
135 #define DPRINTF(x)	do { if (axedebug) printf x; } while (0)
136 #define DPRINTFN(n,x)	do { if (axedebug >= (n)) printf x; } while (0)
137 int	axedebug = 0;
138 #else
139 #define DPRINTF(x)
140 #define DPRINTFN(n,x)
141 #endif
142 
143 /*
144  * Various supported device vendors/products.
145  */
146 const struct axe_type axe_devs[] = {
147 	{ { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_UF200}, 0 },
148 	{ { USB_VENDOR_ACERCM, USB_PRODUCT_ACERCM_EP1427X2}, 0 },
149 	{ { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_ETHERNET }, AX772 },
150 	{ { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88172}, 0 },
151 	{ { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88772}, AX772 },
152 	{ { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88772A}, AX772 },
153 	{ { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88178}, AX178 },
154 	{ { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC210T}, 0 },
155 	{ { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D5055 }, AX178 },
156 	{ { USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USB2AR}, 0},
157 	{ { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_USB200MV2}, AX772 },
158 	{ { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB2_TX }, 0},
159 	{ { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100}, 0 },
160 	{ { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100B1 }, AX772 },
161 	{ { USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_GWUSB2E}, 0 },
162 	{ { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_ETGUS2 }, AX178 },
163 	{ { USB_VENDOR_JVC, USB_PRODUCT_JVC_MP_PRX1}, 0 },
164 	{ { USB_VENDOR_LINKSYS2, USB_PRODUCT_LINKSYS2_USB200M}, 0 },
165 	{ { USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_USB1000 }, AX178 },
166 	{ { USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LAN_GTJU2}, AX178 },
167 	{ { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAU2GT}, AX178 },
168 	{ { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAU2KTX}, 0 },
169 	{ { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA120}, 0 },
170 	{ { USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01PLUS }, AX772 },
171 	{ { USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GU1000T }, AX178 },
172 	{ { USB_VENDOR_SYSTEMTALKS, USB_PRODUCT_SYSTEMTALKS_SGCX2UL}, 0 },
173 	{ { USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_LN029}, 0 },
174 	{ { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN028 }, AX178 }
175 };
176 
177 #define axe_lookup(v, p) ((struct axe_type *)usb_lookup(axe_devs, v, p))
178 
179 int axe_match(struct device *, void *, void *);
180 void axe_attach(struct device *, struct device *, void *);
181 int axe_detach(struct device *, int);
182 int axe_activate(struct device *, enum devact);
183 
184 struct cfdriver axe_cd = {
185 	NULL, "axe", DV_IFNET
186 };
187 
188 const struct cfattach axe_ca = {
189 	sizeof(struct axe_softc),
190 	axe_match,
191 	axe_attach,
192 	axe_detach,
193 	axe_activate,
194 };
195 
196 int axe_tx_list_init(struct axe_softc *);
197 int axe_rx_list_init(struct axe_softc *);
198 struct mbuf *axe_newbuf(void);
199 int axe_encap(struct axe_softc *, struct mbuf *, int);
200 void axe_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
201 void axe_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
202 void axe_tick(void *);
203 void axe_tick_task(void *);
204 void axe_start(struct ifnet *);
205 int axe_ioctl(struct ifnet *, u_long, caddr_t);
206 void axe_init(void *);
207 void axe_stop(struct axe_softc *);
208 void axe_watchdog(struct ifnet *);
209 int axe_miibus_readreg(struct device *, int, int);
210 void axe_miibus_writereg(struct device *, int, int, int);
211 void axe_miibus_statchg(struct device *);
212 int axe_cmd(struct axe_softc *, int, int, int, void *);
213 int axe_ifmedia_upd(struct ifnet *);
214 void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
215 void axe_reset(struct axe_softc *sc);
216 
217 void axe_setmulti(struct axe_softc *);
218 void axe_lock_mii(struct axe_softc *sc);
219 void axe_unlock_mii(struct axe_softc *sc);
220 
221 void axe_ax88178_init(struct axe_softc *);
222 void axe_ax88772_init(struct axe_softc *);
223 
224 /* Get exclusive access to the MII registers */
225 void
226 axe_lock_mii(struct axe_softc *sc)
227 {
228 	sc->axe_refcnt++;
229 	rw_enter_write(&sc->axe_mii_lock);
230 }
231 
232 void
233 axe_unlock_mii(struct axe_softc *sc)
234 {
235 	rw_exit_write(&sc->axe_mii_lock);
236 	if (--sc->axe_refcnt < 0)
237 		usb_detach_wakeup(&sc->axe_dev);
238 }
239 
240 int
241 axe_cmd(struct axe_softc *sc, int cmd, int index, int val, void *buf)
242 {
243 	usb_device_request_t	req;
244 	usbd_status		err;
245 
246 	if (sc->axe_dying)
247 		return(0);
248 
249 	if (AXE_CMD_DIR(cmd))
250 		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
251 	else
252 		req.bmRequestType = UT_READ_VENDOR_DEVICE;
253 	req.bRequest = AXE_CMD_CMD(cmd);
254 	USETW(req.wValue, val);
255 	USETW(req.wIndex, index);
256 	USETW(req.wLength, AXE_CMD_LEN(cmd));
257 
258 	err = usbd_do_request(sc->axe_udev, &req, buf);
259 
260 	if (err) {
261 		DPRINTF(("axe_cmd err: cmd: %d\n", cmd));
262 		return(-1);
263 	}
264 
265 	return(0);
266 }
267 
268 int
269 axe_miibus_readreg(struct device *dev, int phy, int reg)
270 {
271 	struct axe_softc	*sc = (void *)dev;
272 	usbd_status		err;
273 	uWord			val;
274 
275 	if (sc->axe_dying) {
276 		DPRINTF(("axe: dying\n"));
277 		return(0);
278 	}
279 
280 #ifdef notdef
281 	/*
282 	 * The chip tells us the MII address of any supported
283 	 * PHYs attached to the chip, so only read from those.
284 	 */
285 
286 	DPRINTF(("axe_miibus_readreg: phy 0x%x reg 0x%x\n", phy, reg));
287 
288 	if (sc->axe_phyaddrs[0] != AXE_NOPHY && phy != sc->axe_phyaddrs[0])
289 		return (0);
290 
291 	if (sc->axe_phyaddrs[1] != AXE_NOPHY && phy != sc->axe_phyaddrs[1])
292 		return (0);
293 #endif
294 	if (sc->axe_phyaddrs[0] != 0xFF && sc->axe_phyaddrs[0] != phy)
295 		return (0);
296 
297 	USETW(val, 0);
298 
299 	axe_lock_mii(sc);
300 	axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
301 	err = axe_cmd(sc, AXE_CMD_MII_READ_REG, reg, phy, val);
302 	axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
303 	axe_unlock_mii(sc);
304 
305 	if (err) {
306 		printf("axe%d: read PHY failed\n", sc->axe_unit);
307 		return(-1);
308 	}
309 	DPRINTF(("axe_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n",
310 	    phy, reg, UGETW(val)));
311 
312 	if (UGETW(val) && UGETW(val) != 0xffff)
313 		sc->axe_phyaddrs[0] = phy;
314 
315 	return (UGETW(val));
316 }
317 
318 void
319 axe_miibus_writereg(struct device *dev, int phy, int reg, int val)
320 {
321 	struct axe_softc	*sc = (void *)dev;
322 	usbd_status		err;
323 	uWord			uval;
324 
325 	if (sc->axe_dying)
326 		return;
327 
328 	USETW(uval, val);
329 
330 	axe_lock_mii(sc);
331 	axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
332 	err = axe_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, uval);
333 	axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
334 	axe_unlock_mii(sc);
335 
336 	if (err) {
337 		printf("axe%d: write PHY failed\n", sc->axe_unit);
338 		return;
339 	}
340 }
341 
342 void
343 axe_miibus_statchg(struct device *dev)
344 {
345 	struct axe_softc	*sc = (void *)dev;
346 	struct mii_data		*mii = GET_MII(sc);
347 	int			val, err;
348 
349 	if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
350 		val = AXE_MEDIA_FULL_DUPLEX;
351 	else
352 		val = 0;
353 
354 	if (sc->axe_flags & AX178 || sc->axe_flags & AX772) {
355 		val |= (AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC);
356 
357 		switch (IFM_SUBTYPE(mii->mii_media_active)) {
358 		case IFM_1000_T:
359 			val |= AXE_178_MEDIA_GMII | AXE_178_MEDIA_ENCK;
360 			break;
361 		case IFM_100_TX:
362 			val |= AXE_178_MEDIA_100TX;
363 			break;
364 		case IFM_10_T:
365 			/* doesn't need to be handled */
366 			break;
367 		}
368 	}
369 
370 	DPRINTF(("axe_miibus_statchg: val=0x%x\n", val));
371 	err = axe_cmd(sc, AXE_CMD_WRITE_MEDIA, 0, val, NULL);
372 	if (err) {
373 		printf("%s: media change failed\n", sc->axe_dev.dv_xname);
374 		return;
375 	}
376 }
377 
378 /*
379  * Set media options.
380  */
381 int
382 axe_ifmedia_upd(struct ifnet *ifp)
383 {
384 	struct axe_softc	*sc = ifp->if_softc;
385 	struct mii_data		*mii = GET_MII(sc);
386 
387 	sc->axe_link = 0;
388 	if (mii->mii_instance) {
389 		struct mii_softc	*miisc;
390 		LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
391 			mii_phy_reset(miisc);
392 	}
393 	mii_mediachg(mii);
394 
395 	return (0);
396 }
397 
398 /*
399  * Report current media status.
400  */
401 void
402 axe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
403 {
404 	struct axe_softc	*sc = ifp->if_softc;
405 	struct mii_data		*mii = GET_MII(sc);
406 
407 	mii_pollstat(mii);
408 	ifmr->ifm_active = mii->mii_media_active;
409 	ifmr->ifm_status = mii->mii_media_status;
410 }
411 
412 void
413 axe_setmulti(struct axe_softc *sc)
414 {
415 	struct ifnet		*ifp;
416 	struct ether_multi *enm;
417 	struct ether_multistep step;
418 	u_int32_t		h = 0;
419 	uWord			urxmode;
420 	u_int16_t		rxmode;
421 	u_int8_t		hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
422 
423 	if (sc->axe_dying)
424 		return;
425 
426 	ifp = GET_IFP(sc);
427 
428 	axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, urxmode);
429 	rxmode = UGETW(urxmode);
430 
431 	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
432 allmulti:
433 		rxmode |= AXE_RXCMD_ALLMULTI;
434 		axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
435 		return;
436 	} else
437 		rxmode &= ~AXE_RXCMD_ALLMULTI;
438 
439 	/* now program new ones */
440 	ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
441 	while (enm != NULL) {
442 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
443 			   ETHER_ADDR_LEN) != 0)
444 			goto allmulti;
445 
446 		h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
447 		hashtbl[h / 8] |= 1 << (h % 8);
448 		ETHER_NEXT_MULTI(step, enm);
449 	}
450 
451 	ifp->if_flags &= ~IFF_ALLMULTI;
452 	axe_cmd(sc, AXE_CMD_WRITE_MCAST, 0, 0, (void *)&hashtbl);
453 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
454 	return;
455 }
456 
457 void
458 axe_reset(struct axe_softc *sc)
459 {
460 	if (sc->axe_dying)
461 		return;
462 	/* XXX What to reset? */
463 
464 	/* Wait a little while for the chip to get its brains in order. */
465 	DELAY(1000);
466 	return;
467 }
468 
469 void
470 axe_ax88178_init(struct axe_softc *sc)
471 {
472 	int gpio0 = 0, phymode = 0;
473 	u_int16_t eeprom;
474 
475 	axe_cmd(sc, AXE_CMD_SROM_WR_ENABLE, 0, 0, NULL);
476 	/* XXX magic */
477 	axe_cmd(sc, AXE_CMD_SROM_READ, 0, 0x0017, &eeprom);
478 	axe_cmd(sc, AXE_CMD_SROM_WR_DISABLE, 0, 0, NULL);
479 
480 	eeprom = letoh16(eeprom);
481 
482 	DPRINTF((" EEPROM is 0x%x\n", eeprom));
483 
484 	/* if EEPROM is invalid we have to use to GPIO0 */
485 	if (eeprom == 0xffff) {
486 		phymode = 0;
487 		gpio0 = 1;
488 	} else {
489 		phymode = eeprom & 7;
490 		gpio0 = (eeprom & 0x80) ? 0 : 1;
491 	}
492 
493 	DPRINTF(("use gpio0: %d, phymode %d\n", gpio0, phymode));
494 
495 	axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x008c, NULL);
496 	usbd_delay_ms(sc->axe_udev, 40);
497 	if ((eeprom >> 8) != 1) {
498 		axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL);
499 		usbd_delay_ms(sc->axe_udev, 30);
500 
501 		axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x001c, NULL);
502 		usbd_delay_ms(sc->axe_udev, 300);
503 
504 		axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL);
505 		usbd_delay_ms(sc->axe_udev, 30);
506 	} else {
507 		DPRINTF(("axe gpio phymode == 1 path\n"));
508 		axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x0004, NULL);
509 		usbd_delay_ms(sc->axe_udev, 30);
510 		axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x000c, NULL);
511 		usbd_delay_ms(sc->axe_udev, 30);
512 	}
513 
514 	/* soft reset */
515 	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL);
516 	usbd_delay_ms(sc->axe_udev, 150);
517 	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
518 	    AXE_SW_RESET_PRL | AXE_178_RESET_MAGIC, NULL);
519 	usbd_delay_ms(sc->axe_udev, 150);
520 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
521 }
522 
523 void
524 axe_ax88772_init(struct axe_softc *sc)
525 {
526 	axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x00b0, NULL);
527 	usbd_delay_ms(sc->axe_udev, 40);
528 
529 	if (sc->axe_phyaddrs[1] == AXE_INTPHY) {
530 		/* ask for the embedded PHY */
531 		axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x01, NULL);
532 		usbd_delay_ms(sc->axe_udev, 10);
533 
534 		/* power down and reset state, pin reset state */
535 		axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL);
536 		usbd_delay_ms(sc->axe_udev, 60);
537 
538 		/* power down/reset state, pin operating state */
539 		axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
540 		    AXE_SW_RESET_IPPD | AXE_SW_RESET_PRL, NULL);
541 		usbd_delay_ms(sc->axe_udev, 150);
542 
543 		/* power up, reset */
544 		axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_PRL, NULL);
545 
546 		/* power up, operating */
547 		axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
548 		    AXE_SW_RESET_IPRL | AXE_SW_RESET_PRL, NULL);
549 	} else {
550 		/* ask for external PHY */
551 		axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x00, NULL);
552 		usbd_delay_ms(sc->axe_udev, 10);
553 
554 		/* power down internal PHY */
555 		axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
556 		    AXE_SW_RESET_IPPD | AXE_SW_RESET_PRL, NULL);
557 	}
558 
559 	usbd_delay_ms(sc->axe_udev, 150);
560 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
561 }
562 
563 /*
564  * Probe for a AX88172 chip.
565  */
566 int
567 axe_match(struct device *parent, void *match, void *aux)
568 {
569 	struct usb_attach_arg *uaa = aux;
570 
571 	if (!uaa->iface)
572 		return(UMATCH_NONE);
573 
574 	return (axe_lookup(uaa->vendor, uaa->product) != NULL ?
575 		UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
576 }
577 
578 /*
579  * Attach the interface. Allocate softc structures, do ifmedia
580  * setup and ethernet/BPF attach.
581  */
582 void
583 axe_attach(struct device *parent, struct device *self, void *aux)
584 {
585 	struct axe_softc *sc = (struct axe_softc *)self;
586 	struct usb_attach_arg *uaa = aux;
587 	usbd_device_handle dev = uaa->device;
588 	usbd_status err;
589 	usb_interface_descriptor_t *id;
590 	usb_endpoint_descriptor_t *ed;
591 	struct mii_data	*mii;
592 	u_char eaddr[ETHER_ADDR_LEN];
593 	char *devname = sc->axe_dev.dv_xname;
594 	struct ifnet *ifp;
595 	int i, s;
596 
597 	sc->axe_unit = self->dv_unit; /*device_get_unit(self);*/
598 
599 	err = usbd_set_config_no(dev, AXE_CONFIG_NO, 1);
600 	if (err) {
601 		printf("%s: getting interface handle failed\n",
602 		    sc->axe_dev.dv_xname);
603 		return;
604 	}
605 
606 	sc->axe_flags = axe_lookup(uaa->vendor, uaa->product)->axe_flags;
607 
608 	usb_init_task(&sc->axe_tick_task, axe_tick_task, sc);
609 	rw_init(&sc->axe_mii_lock, "axemii");
610 	usb_init_task(&sc->axe_stop_task, (void (*)(void *))axe_stop, sc);
611 
612 	err = usbd_device2interface_handle(dev, AXE_IFACE_IDX, &sc->axe_iface);
613 	if (err) {
614 		printf("%s: getting interface handle failed\n",
615 		    sc->axe_dev.dv_xname);
616 		return;
617 	}
618 
619 	sc->axe_udev = dev;
620 	sc->axe_product = uaa->product;
621 	sc->axe_vendor = uaa->vendor;
622 
623 	id = usbd_get_interface_descriptor(sc->axe_iface);
624 
625 	/* decide on what our bufsize will be */
626 	if (sc->axe_flags & AX178 || sc->axe_flags & AX772)
627 		sc->axe_bufsz = (sc->axe_udev->speed == USB_SPEED_HIGH) ?
628 		    AXE_178_MAX_BUFSZ : AXE_178_MIN_BUFSZ;
629 	else
630 		sc->axe_bufsz = AXE_172_BUFSZ;
631 
632 	/* Find endpoints. */
633 	for (i = 0; i < id->bNumEndpoints; i++) {
634 		ed = usbd_interface2endpoint_descriptor(sc->axe_iface, i);
635 		if (!ed) {
636 			printf("%s: couldn't get ep %d\n",
637 			    sc->axe_dev.dv_xname, i);
638 			return;
639 		}
640 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
641 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
642 			sc->axe_ed[AXE_ENDPT_RX] = ed->bEndpointAddress;
643 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
644 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
645 			sc->axe_ed[AXE_ENDPT_TX] = ed->bEndpointAddress;
646 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
647 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
648 			sc->axe_ed[AXE_ENDPT_INTR] = ed->bEndpointAddress;
649 		}
650 	}
651 
652 	s = splnet();
653 
654 	printf("%s:", sc->axe_dev.dv_xname);
655 
656 	/* We need the PHYID for init dance in some cases */
657 	axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, (void *)&sc->axe_phyaddrs);
658 
659 	DPRINTF((" phyaddrs[0]: %x phyaddrs[1]: %x\n",
660 	    sc->axe_phyaddrs[0], sc->axe_phyaddrs[1]));
661 
662 	if (sc->axe_flags & AX178) {
663 		axe_ax88178_init(sc);
664 		printf(" AX88178");
665 	} else if (sc->axe_flags & AX772) {
666 		axe_ax88772_init(sc);
667 		printf(" AX88772");
668 	} else
669 		printf(" AX88172");
670 
671 	/*
672 	 * Get station address.
673 	 */
674 	if (sc->axe_flags & AX178 || sc->axe_flags & AX772)
675 		axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, &eaddr);
676 	else
677 		axe_cmd(sc, AXE_172_CMD_READ_NODEID, 0, 0, &eaddr);
678 
679 	/*
680 	 * Load IPG values
681 	 */
682 	axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, (void *)&sc->axe_ipgs);
683 
684 	/*
685 	 * Work around broken adapters that appear to lie about
686 	 * their PHY addresses.
687 	 */
688 	sc->axe_phyaddrs[0] = sc->axe_phyaddrs[1] = 0xFF;
689 
690 	/*
691 	 * An ASIX chip was detected. Inform the world.
692 	 */
693 	printf(", address %s\n", ether_sprintf(eaddr));
694 
695 	bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
696 
697 	/* Initialize interface info.*/
698 	ifp = &sc->arpcom.ac_if;
699 	ifp->if_softc = sc;
700 	strlcpy(ifp->if_xname, devname, IFNAMSIZ);
701 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
702 	ifp->if_ioctl = axe_ioctl;
703 	ifp->if_start = axe_start;
704 
705 	ifp->if_watchdog = axe_watchdog;
706 
707 /*	ifp->if_baudrate = 10000000; */
708 /*	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;*/
709 
710 	IFQ_SET_READY(&ifp->if_snd);
711 
712 	ifp->if_capabilities = IFCAP_VLAN_MTU;
713 
714 	/* Initialize MII/media info. */
715 	mii = &sc->axe_mii;
716 	mii->mii_ifp = ifp;
717 	mii->mii_readreg = axe_miibus_readreg;
718 	mii->mii_writereg = axe_miibus_writereg;
719 	mii->mii_statchg = axe_miibus_statchg;
720 	mii->mii_flags = MIIF_AUTOTSLEEP;
721 
722 	ifmedia_init(&mii->mii_media, 0, axe_ifmedia_upd, axe_ifmedia_sts);
723 	mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
724 
725 	if (LIST_FIRST(&mii->mii_phys) == NULL) {
726 		ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
727 		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
728 	} else
729 		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
730 
731 	/* Attach the interface. */
732 	if_attach(ifp);
733 	ether_ifattach(ifp);
734 
735 	timeout_set(&sc->axe_stat_ch, axe_tick, sc);
736 
737 	sc->axe_attached = 1;
738 	splx(s);
739 
740 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->axe_udev,
741 			   &sc->axe_dev);
742 }
743 
744 int
745 axe_detach(struct device *self, int flags)
746 {
747 	struct axe_softc	*sc = (struct axe_softc *)self;
748 	int			s;
749 	struct ifnet		*ifp = GET_IFP(sc);
750 
751 	DPRINTFN(2,("%s: %s: enter\n", sc->axe_dev.dv_xname, __func__));
752 
753 	/* Detached before attached finished, so just bail out. */
754 	if (!sc->axe_attached)
755 		return (0);
756 
757 	timeout_del(&sc->axe_stat_ch);
758 
759 	sc->axe_dying = 1;
760 
761 	if (sc->axe_ep[AXE_ENDPT_TX] != NULL)
762 		usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]);
763 	if (sc->axe_ep[AXE_ENDPT_RX] != NULL)
764 		usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]);
765 	if (sc->axe_ep[AXE_ENDPT_INTR] != NULL)
766 		usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
767 
768 	/*
769 	 * Remove any pending tasks.  They cannot be executing because they run
770 	 * in the same thread as detach.
771 	 */
772 	usb_rem_task(sc->axe_udev, &sc->axe_tick_task);
773 	usb_rem_task(sc->axe_udev, &sc->axe_stop_task);
774 
775 	s = splusb();
776 
777 	if (--sc->axe_refcnt >= 0) {
778 		/* Wait for processes to go away */
779 		usb_detach_wait(&sc->axe_dev);
780 	}
781 
782 	if (ifp->if_flags & IFF_RUNNING)
783 		axe_stop(sc);
784 
785 	mii_detach(&sc->axe_mii, MII_PHY_ANY, MII_OFFSET_ANY);
786 	ifmedia_delete_instance(&sc->axe_mii.mii_media, IFM_INST_ANY);
787 	ether_ifdetach(ifp);
788 	if_detach(ifp);
789 
790 #ifdef DIAGNOSTIC
791 	if (sc->axe_ep[AXE_ENDPT_TX] != NULL ||
792 	    sc->axe_ep[AXE_ENDPT_RX] != NULL ||
793 	    sc->axe_ep[AXE_ENDPT_INTR] != NULL)
794 		printf("%s: detach has active endpoints\n",
795 		    sc->axe_dev.dv_xname);
796 #endif
797 
798 	sc->axe_attached = 0;
799 
800 	if (--sc->axe_refcnt >= 0) {
801 		/* Wait for processes to go away. */
802 		usb_detach_wait(&sc->axe_dev);
803 	}
804 	splx(s);
805 
806 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->axe_udev,
807 			   &sc->axe_dev);
808 
809 	return (0);
810 }
811 
812 int
813 axe_activate(struct device *self, enum devact act)
814 {
815 	struct axe_softc *sc = (struct axe_softc *)self;
816 
817 	DPRINTFN(2,("%s: %s: enter\n", sc->axe_dev.dv_xname, __func__));
818 
819 	switch (act) {
820 	case DVACT_ACTIVATE:
821 		break;
822 
823 	case DVACT_DEACTIVATE:
824 		sc->axe_dying = 1;
825 		break;
826 	}
827 	return (0);
828 }
829 
830 struct mbuf *
831 axe_newbuf(void)
832 {
833 	struct mbuf		*m;
834 
835 	MGETHDR(m, M_DONTWAIT, MT_DATA);
836 	if (m == NULL)
837 		return (NULL);
838 
839 	MCLGET(m, M_DONTWAIT);
840 	if (!(m->m_flags & M_EXT)) {
841 		m_freem(m);
842 		return (NULL);
843 	}
844 
845 	m->m_len = m->m_pkthdr.len = MCLBYTES;
846 	m_adj(m, ETHER_ALIGN);
847 
848 	return (m);
849 }
850 
851 int
852 axe_rx_list_init(struct axe_softc *sc)
853 {
854 	struct axe_cdata *cd;
855 	struct axe_chain *c;
856 	int i;
857 
858 	DPRINTF(("%s: %s: enter\n", sc->axe_dev.dv_xname, __func__));
859 
860 	cd = &sc->axe_cdata;
861 	for (i = 0; i < AXE_RX_LIST_CNT; i++) {
862 		c = &cd->axe_rx_chain[i];
863 		c->axe_sc = sc;
864 		c->axe_idx = i;
865 		c->axe_mbuf = NULL;
866 		if (c->axe_xfer == NULL) {
867 			c->axe_xfer = usbd_alloc_xfer(sc->axe_udev);
868 			if (c->axe_xfer == NULL)
869 				return (ENOBUFS);
870 			c->axe_buf = usbd_alloc_buffer(c->axe_xfer,
871 			    sc->axe_bufsz);
872 			if (c->axe_buf == NULL) {
873 				usbd_free_xfer(c->axe_xfer);
874 				return (ENOBUFS);
875 			}
876 		}
877 	}
878 
879 	return (0);
880 }
881 
882 int
883 axe_tx_list_init(struct axe_softc *sc)
884 {
885 	struct axe_cdata *cd;
886 	struct axe_chain *c;
887 	int i;
888 
889 	DPRINTF(("%s: %s: enter\n", sc->axe_dev.dv_xname, __func__));
890 
891 	cd = &sc->axe_cdata;
892 	for (i = 0; i < AXE_TX_LIST_CNT; i++) {
893 		c = &cd->axe_tx_chain[i];
894 		c->axe_sc = sc;
895 		c->axe_idx = i;
896 		c->axe_mbuf = NULL;
897 		if (c->axe_xfer == NULL) {
898 			c->axe_xfer = usbd_alloc_xfer(sc->axe_udev);
899 			if (c->axe_xfer == NULL)
900 				return (ENOBUFS);
901 			c->axe_buf = usbd_alloc_buffer(c->axe_xfer,
902 			    sc->axe_bufsz);
903 			if (c->axe_buf == NULL) {
904 				usbd_free_xfer(c->axe_xfer);
905 				return (ENOBUFS);
906 			}
907 		}
908 	}
909 
910 	return (0);
911 }
912 
913 /*
914  * A frame has been uploaded: pass the resulting mbuf chain up to
915  * the higher level protocols.
916  */
917 void
918 axe_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
919 {
920 	struct axe_chain	*c = (struct axe_chain *)priv;
921 	struct axe_softc	*sc = c->axe_sc;
922 	struct ifnet		*ifp = GET_IFP(sc);
923 	u_char			*buf = c->axe_buf;
924 	u_int32_t		total_len;
925 	u_int16_t		pktlen = 0;
926 	struct mbuf		*m;
927 	struct axe_sframe_hdr	hdr;
928 	int			s;
929 
930 	DPRINTFN(10,("%s: %s: enter\n", sc->axe_dev.dv_xname,__func__));
931 
932 	if (sc->axe_dying)
933 		return;
934 
935 	if (!(ifp->if_flags & IFF_RUNNING))
936 		return;
937 
938 	if (status != USBD_NORMAL_COMPLETION) {
939 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
940 			return;
941 		if (usbd_ratecheck(&sc->axe_rx_notice)) {
942 			printf("%s: usb errors on rx: %s\n",
943 			    sc->axe_dev.dv_xname, usbd_errstr(status));
944 		}
945 		if (status == USBD_STALLED)
946 			usbd_clear_endpoint_stall_async(sc->axe_ep[AXE_ENDPT_RX]);
947 		goto done;
948 	}
949 
950 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
951 
952 	do {
953 		if (sc->axe_flags & AX178 || sc->axe_flags & AX772) {
954 			if (total_len < sizeof(hdr)) {
955 				ifp->if_ierrors++;
956 				goto done;
957 			}
958 
959 			buf += pktlen;
960 
961 			memcpy(&hdr, buf, sizeof(hdr));
962 			total_len -= sizeof(hdr);
963 
964 			if ((hdr.len ^ hdr.ilen) != 0xffff) {
965 				ifp->if_ierrors++;
966 				goto done;
967 			}
968 			pktlen = letoh16(hdr.len);
969 			if (pktlen > total_len) {
970 				ifp->if_ierrors++;
971 				goto done;
972 			}
973 
974 			buf += sizeof(hdr);
975 
976 			if ((pktlen % 2) != 0)
977 				pktlen++;
978 
979 			if ((total_len - pktlen) < 0)
980 				total_len = 0;
981 			else
982 				total_len -= pktlen;
983 		} else {
984 			pktlen = total_len; /* crc on the end? */
985 			total_len = 0;
986 		}
987 
988 		m = axe_newbuf();
989 		if (m == NULL) {
990 			ifp->if_ierrors++;
991 			goto done;
992 		}
993 
994 		ifp->if_ipackets++;
995 		m->m_pkthdr.rcvif = ifp;
996 		m->m_pkthdr.len = m->m_len = pktlen;
997 
998 		memcpy(mtod(m, char *), buf, pktlen);
999 
1000 		/* push the packet up */
1001 		s = splnet();
1002 #if NBPFILTER > 0
1003 		if (ifp->if_bpf)
1004 			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1005 #endif
1006 
1007 		ether_input_mbuf(ifp, m);
1008 
1009 		splx(s);
1010 
1011 	} while (total_len > 0);
1012 
1013 done:
1014 	memset(c->axe_buf, 0, sc->axe_bufsz);
1015 
1016 	/* Setup new transfer. */
1017 	usbd_setup_xfer(xfer, sc->axe_ep[AXE_ENDPT_RX],
1018 	    c, c->axe_buf, sc->axe_bufsz,
1019 	    USBD_SHORT_XFER_OK | USBD_NO_COPY,
1020 	    USBD_NO_TIMEOUT, axe_rxeof);
1021 	usbd_transfer(xfer);
1022 
1023 	DPRINTFN(10,("%s: %s: start rx\n", sc->axe_dev.dv_xname, __func__));
1024 
1025 	return;
1026 }
1027 
1028 /*
1029  * A frame was downloaded to the chip. It's safe for us to clean up
1030  * the list buffers.
1031  */
1032 
1033 void
1034 axe_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
1035 {
1036 	struct axe_softc	*sc;
1037 	struct axe_chain	*c;
1038 	struct ifnet		*ifp;
1039 	int			s;
1040 
1041 	c = priv;
1042 	sc = c->axe_sc;
1043 	ifp = &sc->arpcom.ac_if;
1044 
1045 	if (sc->axe_dying)
1046 		return;
1047 
1048 	s = splnet();
1049 
1050 	if (status != USBD_NORMAL_COMPLETION) {
1051 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1052 			splx(s);
1053 			return;
1054 		}
1055 		ifp->if_oerrors++;
1056 		printf("axe%d: usb error on tx: %s\n", sc->axe_unit,
1057 		    usbd_errstr(status));
1058 		if (status == USBD_STALLED)
1059 			usbd_clear_endpoint_stall_async(sc->axe_ep[AXE_ENDPT_TX]);
1060 		splx(s);
1061 		return;
1062 	}
1063 
1064 	ifp->if_timer = 0;
1065 	ifp->if_flags &= ~IFF_OACTIVE;
1066 
1067 	m_freem(c->axe_mbuf);
1068 	c->axe_mbuf = NULL;
1069 
1070 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1071 		axe_start(ifp);
1072 
1073 	ifp->if_opackets++;
1074 	splx(s);
1075 	return;
1076 }
1077 
1078 void
1079 axe_tick(void *xsc)
1080 {
1081 	struct axe_softc *sc = xsc;
1082 
1083 	if (sc == NULL)
1084 		return;
1085 
1086 	DPRINTFN(0xff, ("%s: %s: enter\n", sc->axe_dev.dv_xname,
1087 			__func__));
1088 
1089 	if (sc->axe_dying)
1090 		return;
1091 
1092 	/* Perform periodic stuff in process context */
1093 	usb_add_task(sc->axe_udev, &sc->axe_tick_task);
1094 
1095 }
1096 
1097 void
1098 axe_tick_task(void *xsc)
1099 {
1100 	int			s;
1101 	struct axe_softc	*sc;
1102 	struct ifnet		*ifp;
1103 	struct mii_data		*mii;
1104 
1105 	sc = xsc;
1106 
1107 	if (sc == NULL)
1108 		return;
1109 
1110 	if (sc->axe_dying)
1111 		return;
1112 
1113 	ifp = GET_IFP(sc);
1114 	mii = GET_MII(sc);
1115 	if (mii == NULL)
1116 		return;
1117 
1118 	s = splnet();
1119 
1120 	mii_tick(mii);
1121 	if (!sc->axe_link && mii->mii_media_status & IFM_ACTIVE &&
1122 	    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
1123 		DPRINTF(("%s: %s: got link\n",
1124 			 sc->axe_dev.dv_xname, __func__));
1125 		sc->axe_link++;
1126 		if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1127 			   axe_start(ifp);
1128 	}
1129 
1130 	timeout_add_sec(&sc->axe_stat_ch, 1);
1131 
1132 	splx(s);
1133 }
1134 
1135 int
1136 axe_encap(struct axe_softc *sc, struct mbuf *m, int idx)
1137 {
1138 	struct axe_chain	*c;
1139 	usbd_status		err;
1140 	struct axe_sframe_hdr	hdr;
1141 	int			length, boundary;
1142 
1143 	c = &sc->axe_cdata.axe_tx_chain[idx];
1144 
1145 	if (sc->axe_flags & AX178 || sc->axe_flags & AX772) {
1146 		boundary = (sc->axe_udev->speed == USB_SPEED_HIGH) ? 512 : 64;
1147 
1148 		hdr.len = htole16(m->m_pkthdr.len);
1149 		hdr.ilen = ~hdr.len;
1150 
1151 		memcpy(c->axe_buf, &hdr, sizeof(hdr));
1152 		length = sizeof(hdr);
1153 
1154 		m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf + length);
1155 		length += m->m_pkthdr.len;
1156 
1157 		if ((length % boundary) == 0) {
1158 			hdr.len = 0x0000;
1159 			hdr.ilen = 0xffff;
1160 			memcpy(c->axe_buf + length, &hdr, sizeof(hdr));
1161 			length += sizeof(hdr);
1162 		}
1163 
1164 	} else {
1165 		m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf);
1166 		length = m->m_pkthdr.len;
1167 	}
1168 
1169 	c->axe_mbuf = m;
1170 
1171 	usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_TX],
1172 	    c, c->axe_buf, length, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
1173 	    10000, axe_txeof);
1174 
1175 	/* Transmit */
1176 	err = usbd_transfer(c->axe_xfer);
1177 	if (err != USBD_IN_PROGRESS) {
1178 		axe_stop(sc);
1179 		return(EIO);
1180 	}
1181 
1182 	sc->axe_cdata.axe_tx_cnt++;
1183 
1184 	return(0);
1185 }
1186 
1187 void
1188 axe_start(struct ifnet *ifp)
1189 {
1190 	struct axe_softc	*sc;
1191 	struct mbuf		*m_head = NULL;
1192 
1193 	sc = ifp->if_softc;
1194 
1195 	if (!sc->axe_link)
1196 		return;
1197 
1198 	if (ifp->if_flags & IFF_OACTIVE)
1199 		return;
1200 
1201 	IFQ_POLL(&ifp->if_snd, m_head);
1202 	if (m_head == NULL)
1203 		return;
1204 
1205 	if (axe_encap(sc, m_head, 0)) {
1206 		ifp->if_flags |= IFF_OACTIVE;
1207 		return;
1208 	}
1209 	IFQ_DEQUEUE(&ifp->if_snd, m_head);
1210 
1211 	/*
1212 	 * If there's a BPF listener, bounce a copy of this frame
1213 	 * to him.
1214 	 */
1215 #if NBPFILTER > 0
1216 	if (ifp->if_bpf)
1217 		bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
1218 #endif
1219 
1220 	ifp->if_flags |= IFF_OACTIVE;
1221 
1222 	/*
1223 	 * Set a timeout in case the chip goes out to lunch.
1224 	 */
1225 	ifp->if_timer = 5;
1226 
1227 	return;
1228 }
1229 
1230 void
1231 axe_init(void *xsc)
1232 {
1233 	struct axe_softc	*sc = xsc;
1234 	struct ifnet		*ifp = &sc->arpcom.ac_if;
1235 	struct axe_chain	*c;
1236 	usbd_status		err;
1237 	int			rxmode;
1238 	int			i, s;
1239 
1240 	s = splnet();
1241 
1242 	/*
1243 	 * Cancel pending I/O and free all RX/TX buffers.
1244 	 */
1245 	axe_reset(sc);
1246 
1247 	/* set MAC address */
1248 	if (sc->axe_flags & AX178 || sc->axe_flags & AX772)
1249 		axe_cmd(sc, AXE_178_CMD_WRITE_NODEID, 0, 0,
1250 		    &sc->arpcom.ac_enaddr);
1251 
1252 	/* Enable RX logic. */
1253 
1254 	/* Init RX ring. */
1255 	if (axe_rx_list_init(sc) == ENOBUFS) {
1256 		printf("axe%d: rx list init failed\n", sc->axe_unit);
1257 		splx(s);
1258 		return;
1259 	}
1260 
1261 	/* Init TX ring. */
1262 	if (axe_tx_list_init(sc) == ENOBUFS) {
1263 		printf("axe%d: tx list init failed\n", sc->axe_unit);
1264 		splx(s);
1265 		return;
1266 	}
1267 
1268 	/* Set transmitter IPG values */
1269 	if (sc->axe_flags & AX178 || sc->axe_flags & AX772)
1270 		axe_cmd(sc, AXE_178_CMD_WRITE_IPG012, sc->axe_ipgs[2],
1271 		    (sc->axe_ipgs[1] << 8) | (sc->axe_ipgs[0]), NULL);
1272 	else {
1273 		axe_cmd(sc, AXE_172_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL);
1274 		axe_cmd(sc, AXE_172_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL);
1275 		axe_cmd(sc, AXE_172_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL);
1276 	}
1277 
1278 	/* Enable receiver, set RX mode */
1279 	rxmode = AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE;
1280 	if (sc->axe_flags & AX178 || sc->axe_flags & AX772) {
1281 		if (sc->axe_udev->speed == USB_SPEED_HIGH) {
1282 			/* largest possible USB buffer size for AX88178 */
1283 			rxmode |= AXE_178_RXCMD_MFB;
1284 		}
1285 	} else
1286 		rxmode |= AXE_172_RXCMD_UNICAST;
1287 
1288 	/* If we want promiscuous mode, set the allframes bit. */
1289 	if (ifp->if_flags & IFF_PROMISC)
1290 		rxmode |= AXE_RXCMD_PROMISC;
1291 
1292 	if (ifp->if_flags & IFF_BROADCAST)
1293 		rxmode |= AXE_RXCMD_BROADCAST;
1294 
1295 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
1296 
1297 	/* Load the multicast filter. */
1298 	axe_setmulti(sc);
1299 
1300 	/* Open RX and TX pipes. */
1301 	err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_RX],
1302 	    USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_RX]);
1303 	if (err) {
1304 		printf("axe%d: open rx pipe failed: %s\n",
1305 		    sc->axe_unit, usbd_errstr(err));
1306 		splx(s);
1307 		return;
1308 	}
1309 
1310 	err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_TX],
1311 	    USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_TX]);
1312 	if (err) {
1313 		printf("axe%d: open tx pipe failed: %s\n",
1314 		    sc->axe_unit, usbd_errstr(err));
1315 		splx(s);
1316 		return;
1317 	}
1318 
1319 	/* Start up the receive pipe. */
1320 	for (i = 0; i < AXE_RX_LIST_CNT; i++) {
1321 		c = &sc->axe_cdata.axe_rx_chain[i];
1322 		usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX],
1323 		    c, c->axe_buf, sc->axe_bufsz,
1324 		    USBD_SHORT_XFER_OK | USBD_NO_COPY,
1325 		    USBD_NO_TIMEOUT, axe_rxeof);
1326 		usbd_transfer(c->axe_xfer);
1327 	}
1328 
1329 	ifp->if_flags |= IFF_RUNNING;
1330 	ifp->if_flags &= ~IFF_OACTIVE;
1331 
1332 	splx(s);
1333 
1334 	timeout_add_sec(&sc->axe_stat_ch, 1);
1335 	return;
1336 }
1337 
1338 int
1339 axe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1340 {
1341 	struct axe_softc	*sc = ifp->if_softc;
1342 	struct ifreq		*ifr = (struct ifreq *)data;
1343 	struct ifaddr		*ifa = (struct ifaddr *)data;
1344 	struct mii_data		*mii;
1345 	uWord			rxmode;
1346 	int			s, error = 0;
1347 
1348 	s = splnet();
1349 
1350 	switch(cmd) {
1351 	case SIOCSIFADDR:
1352 		ifp->if_flags |= IFF_UP;
1353 		if (!(ifp->if_flags & IFF_RUNNING))
1354 			axe_init(sc);
1355 #ifdef INET
1356 		if (ifa->ifa_addr->sa_family == AF_INET)
1357 			arp_ifinit(&sc->arpcom, ifa);
1358 #endif
1359 		break;
1360 
1361 	case SIOCSIFFLAGS:
1362 		if (ifp->if_flags & IFF_UP) {
1363 			if (ifp->if_flags & IFF_RUNNING &&
1364 			    ifp->if_flags & IFF_PROMISC &&
1365 			    !(sc->axe_if_flags & IFF_PROMISC)) {
1366 
1367 				axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, rxmode);
1368 				axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0,
1369 				    UGETW(rxmode) | AXE_RXCMD_PROMISC, NULL);
1370 
1371 				axe_setmulti(sc);
1372 			} else if (ifp->if_flags & IFF_RUNNING &&
1373 			    !(ifp->if_flags & IFF_PROMISC) &&
1374 			    sc->axe_if_flags & IFF_PROMISC) {
1375 				axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, rxmode);
1376 				axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0,
1377 				    UGETW(rxmode) & ~AXE_RXCMD_PROMISC, NULL);
1378 				axe_setmulti(sc);
1379 			} else if (!(ifp->if_flags & IFF_RUNNING))
1380 				axe_init(sc);
1381 		} else {
1382 			if (ifp->if_flags & IFF_RUNNING)
1383 				axe_stop(sc);
1384 		}
1385 		sc->axe_if_flags = ifp->if_flags;
1386 		break;
1387 
1388 	case SIOCGIFMEDIA:
1389 	case SIOCSIFMEDIA:
1390 		mii = GET_MII(sc);
1391 		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
1392 		break;
1393 
1394 	default:
1395 		error = ether_ioctl(ifp, &sc->arpcom, cmd, data);
1396 	}
1397 
1398 	if (error == ENETRESET) {
1399 		if (ifp->if_flags & IFF_RUNNING)
1400 			axe_setmulti(sc);
1401 		error = 0;
1402 	}
1403 
1404 	splx(s);
1405 	return(error);
1406 }
1407 
1408 void
1409 axe_watchdog(struct ifnet *ifp)
1410 {
1411 	struct axe_softc	*sc;
1412 	struct axe_chain	*c;
1413 	usbd_status		stat;
1414 	int			s;
1415 
1416 	sc = ifp->if_softc;
1417 
1418 	ifp->if_oerrors++;
1419 	printf("axe%d: watchdog timeout\n", sc->axe_unit);
1420 
1421 	s = splusb();
1422 	c = &sc->axe_cdata.axe_tx_chain[0];
1423 	usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &stat);
1424 	axe_txeof(c->axe_xfer, c, stat);
1425 
1426 	if (!IFQ_IS_EMPTY(&ifp->if_snd))
1427 		axe_start(ifp);
1428 	splx(s);
1429 }
1430 
1431 /*
1432  * Stop the adapter and free any mbufs allocated to the
1433  * RX and TX lists.
1434  */
1435 void
1436 axe_stop(struct axe_softc *sc)
1437 {
1438 	usbd_status		err;
1439 	struct ifnet		*ifp;
1440 	int			i;
1441 
1442 	axe_reset(sc);
1443 
1444 	ifp = &sc->arpcom.ac_if;
1445 	ifp->if_timer = 0;
1446 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1447 
1448 	timeout_del(&sc->axe_stat_ch);
1449 
1450 	/* Stop transfers. */
1451 	if (sc->axe_ep[AXE_ENDPT_RX] != NULL) {
1452 		err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]);
1453 		if (err) {
1454 			printf("axe%d: abort rx pipe failed: %s\n",
1455 			    sc->axe_unit, usbd_errstr(err));
1456 		}
1457 		err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_RX]);
1458 		if (err) {
1459 			printf("axe%d: close rx pipe failed: %s\n",
1460 			    sc->axe_unit, usbd_errstr(err));
1461 		}
1462 		sc->axe_ep[AXE_ENDPT_RX] = NULL;
1463 	}
1464 
1465 	if (sc->axe_ep[AXE_ENDPT_TX] != NULL) {
1466 		err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]);
1467 		if (err) {
1468 			printf("axe%d: abort tx pipe failed: %s\n",
1469 			    sc->axe_unit, usbd_errstr(err));
1470 		}
1471 		err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_TX]);
1472 		if (err) {
1473 			printf("axe%d: close tx pipe failed: %s\n",
1474 			    sc->axe_unit, usbd_errstr(err));
1475 		}
1476 		sc->axe_ep[AXE_ENDPT_TX] = NULL;
1477 	}
1478 
1479 	if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) {
1480 		err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
1481 		if (err) {
1482 			printf("axe%d: abort intr pipe failed: %s\n",
1483 			    sc->axe_unit, usbd_errstr(err));
1484 		}
1485 		err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
1486 		if (err) {
1487 			printf("axe%d: close intr pipe failed: %s\n",
1488 			    sc->axe_unit, usbd_errstr(err));
1489 		}
1490 		sc->axe_ep[AXE_ENDPT_INTR] = NULL;
1491 	}
1492 
1493 	/* Free RX resources. */
1494 	for (i = 0; i < AXE_RX_LIST_CNT; i++) {
1495 		if (sc->axe_cdata.axe_rx_chain[i].axe_mbuf != NULL) {
1496 			m_freem(sc->axe_cdata.axe_rx_chain[i].axe_mbuf);
1497 			sc->axe_cdata.axe_rx_chain[i].axe_mbuf = NULL;
1498 		}
1499 		if (sc->axe_cdata.axe_rx_chain[i].axe_xfer != NULL) {
1500 			usbd_free_xfer(sc->axe_cdata.axe_rx_chain[i].axe_xfer);
1501 			sc->axe_cdata.axe_rx_chain[i].axe_xfer = NULL;
1502 		}
1503 	}
1504 
1505 	/* Free TX resources. */
1506 	for (i = 0; i < AXE_TX_LIST_CNT; i++) {
1507 		if (sc->axe_cdata.axe_tx_chain[i].axe_mbuf != NULL) {
1508 			m_freem(sc->axe_cdata.axe_tx_chain[i].axe_mbuf);
1509 			sc->axe_cdata.axe_tx_chain[i].axe_mbuf = NULL;
1510 		}
1511 		if (sc->axe_cdata.axe_tx_chain[i].axe_xfer != NULL) {
1512 			usbd_free_xfer(sc->axe_cdata.axe_tx_chain[i].axe_xfer);
1513 			sc->axe_cdata.axe_tx_chain[i].axe_xfer = NULL;
1514 		}
1515 	}
1516 
1517 	sc->axe_link = 0;
1518 }
1519 
1520