xref: /openbsd/sys/dev/usb/if_mos.c (revision 404b540a)
1 /*	$OpenBSD: if_mos.c,v 1.7 2009/10/13 19:33:17 pirofti Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Johann Christian Rode <jcrode@gmx.net>
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) 2005, 2006, 2007 Jonathan Gray <jsg@openbsd.org>
21  *
22  * Permission to use, copy, modify, and distribute this software for any
23  * purpose with or without fee is hereby granted, provided that the above
24  * copyright notice and this permission notice appear in all copies.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
27  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
28  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
29  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
30  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
31  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
32  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33  */
34 
35 /*
36  * Copyright (c) 1997, 1998, 1999, 2000-2003
37  *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions
41  * are met:
42  * 1. Redistributions of source code must retain the above copyright
43  *    notice, this list of conditions and the following disclaimer.
44  * 2. Redistributions in binary form must reproduce the above copyright
45  *    notice, this list of conditions and the following disclaimer in the
46  *    documentation and/or other materials provided with the distribution.
47  * 3. All advertising materials mentioning features or use of this software
48  *    must display the following acknowledgement:
49  *	This product includes software developed by Bill Paul.
50  * 4. Neither the name of the author nor the names of any co-contributors
51  *    may be used to endorse or promote products derived from this software
52  *    without specific prior written permission.
53  *
54  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
55  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
58  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
64  * THE POSSIBILITY OF SUCH DAMAGE.
65  */
66 
67 #include <sys/cdefs.h>
68 
69 /*
70  * Moschip MCS7730/MCS7830 USB to Ethernet controller
71  * The datasheet is available at the following URL:
72  * http://www.moschip.com/data/products/MCS7830/Data%20Sheet_7830.pdf
73  */
74 
75 #include "bpfilter.h"
76 
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/sockio.h>
80 #include <sys/rwlock.h>
81 #include <sys/mbuf.h>
82 #include <sys/kernel.h>
83 #include <sys/proc.h>
84 #include <sys/socket.h>
85 
86 #include <sys/device.h>
87 
88 #include <machine/bus.h>
89 
90 #include <net/if.h>
91 #include <net/if_dl.h>
92 #include <net/if_media.h>
93 
94 #if NBPFILTER > 0
95 #include <net/bpf.h>
96 #endif
97 
98 #ifdef INET
99 #include <netinet/in.h>
100 #include <netinet/in_systm.h>
101 #include <netinet/in_var.h>
102 #include <netinet/ip.h>
103 #include <netinet/if_ether.h>
104 #endif
105 
106 #include <dev/mii/mii.h>
107 #include <dev/mii/miivar.h>
108 
109 #include <dev/usb/usb.h>
110 #include <dev/usb/usbdi.h>
111 #include <dev/usb/usbdi_util.h>
112 #include <dev/usb/usbdivar.h>
113 #include <dev/usb/usbdevs.h>
114 
115 #include <dev/usb/if_mosreg.h>
116 
117 #ifdef MOS_DEBUG
118 #define DPRINTF(x)      do { if (mosdebug) printf x; } while (0)
119 #define DPRINTFN(n,x)   do { if (mosdebug >= (n)) printf x; } while (0)
120 int     mosdebug = 0;
121 #else
122 #define DPRINTF(x)
123 #define DPRINTFN(n,x)
124 #endif
125 
126 /*
127  * Various supported device vendors/products.
128  */
129 const struct mos_type mos_devs[] = {
130 	{ { USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7730 }, MCS7730 },
131 	{ { USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7830 }, MCS7830 },
132 	{ { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN030 }, MCS7830 },
133 };
134 #define mos_lookup(v, p) ((struct mos_type *)usb_lookup(mos_devs, v, p))
135 
136 int mos_match(struct device *, void *, void *);
137 void mos_attach(struct device *, struct device *, void *);
138 int mos_detach(struct device *, int);
139 int mos_activate(struct device *, int);
140 
141 struct cfdriver mos_cd = {
142 	NULL, "mos", DV_IFNET
143 };
144 
145 const struct cfattach mos_ca = {
146 	sizeof(struct mos_softc),
147 	mos_match,
148 	mos_attach,
149 	mos_detach,
150 	mos_activate,
151 };
152 
153 int mos_tx_list_init(struct mos_softc *);
154 int mos_rx_list_init(struct mos_softc *);
155 struct mbuf *mos_newbuf(void);
156 int mos_encap(struct mos_softc *, struct mbuf *, int);
157 void mos_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
158 void mos_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
159 void mos_tick(void *);
160 void mos_tick_task(void *);
161 void mos_start(struct ifnet *);
162 int mos_ioctl(struct ifnet *, u_long, caddr_t);
163 void mos_init(void *);
164 void mos_chip_init(struct mos_softc *);
165 void mos_stop(struct mos_softc *);
166 void mos_watchdog(struct ifnet *);
167 int mos_miibus_readreg(struct device *, int, int);
168 void mos_miibus_writereg(struct device *, int, int, int);
169 void mos_miibus_statchg(struct device *);
170 int mos_ifmedia_upd(struct ifnet *);
171 void mos_ifmedia_sts(struct ifnet *, struct ifmediareq *);
172 void mos_reset(struct mos_softc *sc);
173 
174 int mos_reg_read_1(struct mos_softc *, int);
175 int mos_reg_read_2(struct mos_softc *, int);
176 int mos_reg_write_1(struct mos_softc *, int, int);
177 int mos_reg_write_2(struct mos_softc *, int, int);
178 int mos_readmac(struct mos_softc *, u_char *);
179 int mos_writemac(struct mos_softc *, u_char *);
180 int mos_write_mcast(struct mos_softc *, u_char *);
181 
182 void mos_setmulti(struct mos_softc *);
183 void mos_lock_mii(struct mos_softc *);
184 void mos_unlock_mii(struct mos_softc *);
185 
186 /*
187  * Get exclusive access to the MII registers
188  */
189 void
190 mos_lock_mii(struct mos_softc *sc)
191 {
192 	sc->mos_refcnt++;
193 	rw_enter_write(&sc->mos_mii_lock);
194 }
195 
196 void
197 mos_unlock_mii(struct mos_softc *sc)
198 {
199 	rw_exit_write(&sc->mos_mii_lock);
200 	if (--sc->mos_refcnt < 0)
201 		usb_detach_wakeup(&sc->mos_dev);
202 }
203 
204 int
205 mos_reg_read_1(struct mos_softc *sc, int reg)
206 {
207 	usb_device_request_t	req;
208 	usbd_status		err;
209 	uByte			val = 0;
210 
211 	if (sc->mos_dying)
212 		return (0);
213 
214 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
215 	req.bRequest = MOS_UR_READREG;
216 	USETW(req.wValue, 0);
217 	USETW(req.wIndex, reg);
218 	USETW(req.wLength, 1);
219 
220 	err = usbd_do_request(sc->mos_udev, &req, &val);
221 
222 	if (err) {
223 		DPRINTF(("mos_reg_read_1 error, reg: %d\n", reg));
224 		return (-1);
225 	}
226 
227 	return (val);
228 }
229 
230 int
231 mos_reg_read_2(struct mos_softc *sc, int reg)
232 {
233 	usb_device_request_t	req;
234 	usbd_status		err;
235 	uWord			val;
236 
237 	USETW(val,0);
238 
239 	if (sc->mos_dying)
240 		return(0);
241 
242 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
243 	req.bRequest = MOS_UR_READREG;
244 	USETW(req.wValue, 0);
245 	USETW(req.wIndex, reg);
246 	USETW(req.wLength, 2);
247 
248 	err = usbd_do_request(sc->mos_udev, &req, &val);
249 
250 	if (err) {
251 		DPRINTF(("mos_reg_read_2 error, reg: %d\n", reg));
252 		return (-1);
253 	}
254 
255 	return(UGETW(val));
256 }
257 
258 int
259 mos_reg_write_1(struct mos_softc *sc, int reg, int aval)
260 {
261 	usb_device_request_t	req;
262 	usbd_status		err;
263 	uByte			val;
264 
265 	val = aval;
266 
267 	if (sc->mos_dying)
268 		return(0);
269 
270 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
271 	req.bRequest = MOS_UR_WRITEREG;
272 	USETW(req.wValue, 0);
273 	USETW(req.wIndex, reg);
274 	USETW(req.wLength, 1);
275 
276 	err = usbd_do_request(sc->mos_udev, &req, &val);
277 
278 	if (err) {
279 		DPRINTF(("mos_reg_write_1 error, reg: %d\n", reg));
280 		return (-1);
281 	}
282 
283 	return(0);
284 }
285 
286 int
287 mos_reg_write_2(struct mos_softc *sc, int reg, int aval)
288 {
289 	usb_device_request_t	req;
290 	usbd_status		err;
291 	uWord			val;
292 
293 	USETW(val, aval);
294 
295 	if (sc->mos_dying)
296 		return (0);
297 
298 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
299 	req.bRequest = MOS_UR_WRITEREG;
300 	USETW(req.wValue, 0);
301 	USETW(req.wIndex, reg);
302 	USETW(req.wLength, 2);
303 
304 	err = usbd_do_request(sc->mos_udev, &req, &val);
305 
306 	if (err) {
307 		DPRINTF(("mos_reg_write_2 error, reg: %d\n", reg));
308 		return (-1);
309 	}
310 
311 	return (0);
312 }
313 
314 int
315 mos_readmac(struct mos_softc *sc, u_char *mac)
316 {
317 	usb_device_request_t	req;
318 	usbd_status		err;
319 
320 	if (sc->mos_dying)
321 		return(0);
322 
323 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
324 	req.bRequest = MOS_UR_READREG;
325 	USETW(req.wValue, 0);
326 	USETW(req.wIndex, MOS_MAC);
327 	USETW(req.wLength, ETHER_ADDR_LEN);
328 
329 	err = usbd_do_request(sc->mos_udev, &req, mac);
330 
331 	if (err) {
332 		DPRINTF(("mos_readmac error"));
333 		return (-1);
334 	}
335 
336 	return (0);
337 }
338 
339 int
340 mos_writemac(struct mos_softc *sc, u_char *mac)
341 {
342 	usb_device_request_t	req;
343 	usbd_status		err;
344 
345 	if (sc->mos_dying)
346 		return(0);
347 
348 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
349 	req.bRequest = MOS_UR_WRITEREG;
350 	USETW(req.wValue, 0);
351 	USETW(req.wIndex, MOS_MAC);
352 	USETW(req.wLength, ETHER_ADDR_LEN);
353 
354 	err = usbd_do_request(sc->mos_udev, &req, mac);
355 
356 	if (err) {
357 		DPRINTF(("mos_writemac error"));
358 		return (-1);
359 	}
360 
361 	return (0);
362 }
363 
364 int
365 mos_write_mcast(struct mos_softc *sc, u_char *hashtbl)
366 {
367 	usb_device_request_t	req;
368 	usbd_status		err;
369 
370 	if (sc->mos_dying)
371 		return(0);
372 
373 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
374 	req.bRequest = MOS_UR_WRITEREG;
375 	USETW(req.wValue, 0);
376 	USETW(req.wIndex, MOS_MCAST_TABLE);
377 	USETW(req.wLength, 8);
378 
379 	err = usbd_do_request(sc->mos_udev, &req, hashtbl);
380 
381 	if (err) {
382 		DPRINTF(("mos_reg_mcast error\n"));
383 		return(-1);
384 	}
385 
386 	return(0);
387 }
388 
389 int
390 mos_miibus_readreg(struct device *dev, int phy, int reg)
391 {
392 	struct mos_softc	*sc = (void *)dev;
393 	uWord			val;
394 	int			i,res;
395 
396 	if (sc->mos_dying) {
397 		DPRINTF(("mos: dying\n"));
398 		return (0);
399 	}
400 
401 	USETW(val, 0);
402 
403 	mos_lock_mii(sc);
404 
405 	mos_reg_write_2(sc, MOS_PHY_DATA, 0);
406 	mos_reg_write_1(sc, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) |
407 	    MOS_PHYCTL_READ);
408 	mos_reg_write_1(sc, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) |
409 	    MOS_PHYSTS_PENDING);
410 
411 	for (i = 0; i < MOS_TIMEOUT; i++) {
412 		if (mos_reg_read_1(sc, MOS_PHY_STS) & MOS_PHYSTS_READY)
413 			break;
414 	}
415 	if (i == MOS_TIMEOUT) {
416 		printf("%s: MII read timeout\n", sc->mos_dev.dv_xname);
417 	}
418 
419 	res = mos_reg_read_2(sc, MOS_PHY_DATA);
420 
421 	mos_unlock_mii(sc);
422 
423 	return (res);
424 }
425 
426 void
427 mos_miibus_writereg(struct device *dev, int phy, int reg, int val)
428 {
429 	struct mos_softc	*sc = (void *)dev;
430 	int			i;
431 
432 	if (sc->mos_dying)
433 		return;
434 
435 	mos_lock_mii(sc);
436 
437 	mos_reg_write_2(sc, MOS_PHY_DATA, val);
438 	mos_reg_write_1(sc, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) |
439 	    MOS_PHYCTL_WRITE);
440 	mos_reg_write_1(sc, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) |
441 	    MOS_PHYSTS_PENDING);
442 
443 	for (i = 0; i < MOS_TIMEOUT; i++) {
444 		if (mos_reg_read_1(sc, MOS_PHY_STS) & MOS_PHYSTS_READY)
445 			break;
446 	}
447 	if (i == MOS_TIMEOUT) {
448 		printf("%s: MII write timeout\n", sc->mos_dev.dv_xname);
449 	}
450 
451 	mos_unlock_mii(sc);
452 
453 	return;
454 }
455 
456 void
457 mos_miibus_statchg(struct device *dev)
458 {
459 	struct mos_softc	*sc = (void *)dev;
460 	struct mii_data		*mii = GET_MII(sc);
461 	int			val, err;
462 
463 	mos_lock_mii(sc);
464 
465 	/* disable RX, TX prior to changing FDX, SPEEDSEL */
466 	val = mos_reg_read_1(sc, MOS_CTL);
467 	val &= ~(MOS_CTL_TX_ENB | MOS_CTL_RX_ENB);
468 	mos_reg_write_1(sc, MOS_CTL, val);
469 
470 	/* reset register which counts dropped frames */
471 	mos_reg_write_1(sc, MOS_FRAME_DROP_CNT, 0);
472 
473 	if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
474 		val |= MOS_CTL_FDX_ENB;
475 	else
476 		val &= ~(MOS_CTL_FDX_ENB);
477 
478 	switch (IFM_SUBTYPE(mii->mii_media_active)) {
479 		case IFM_100_TX:
480 			val |=  MOS_CTL_SPEEDSEL;
481 			break;
482 		case IFM_10_T:
483 			val &= ~(MOS_CTL_SPEEDSEL);
484 			break;
485 	}
486 
487 	/* re-enable TX, RX */
488 	val |= (MOS_CTL_TX_ENB | MOS_CTL_RX_ENB);
489 	err = mos_reg_write_1(sc, MOS_CTL, val);
490 	mos_unlock_mii(sc);
491 
492 	if (err) {
493 		printf("%s: media change failed\n", sc->mos_dev.dv_xname);
494 		return;
495 	}
496 }
497 
498 /*
499  * Set media options.
500  */
501 int
502 mos_ifmedia_upd(struct ifnet *ifp)
503 {
504 	struct mos_softc	*sc = ifp->if_softc;
505 	struct mii_data		*mii = GET_MII(sc);
506 
507 	sc->mos_link = 0;
508 	if (mii->mii_instance) {
509 		struct mii_softc	*miisc;
510 		LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
511 			mii_phy_reset(miisc);
512 	}
513 	mii_mediachg(mii);
514 
515 	return (0);
516 }
517 
518 /*
519  * Report current media status.
520  */
521 void
522 mos_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
523 {
524 	struct mos_softc	*sc = ifp->if_softc;
525 	struct mii_data		*mii = GET_MII(sc);
526 
527 	mii_pollstat(mii);
528 	ifmr->ifm_active = mii->mii_media_active;
529 	ifmr->ifm_status = mii->mii_media_status;
530 }
531 
532 void
533 mos_setmulti(struct mos_softc *sc)
534 {
535 	struct ifnet		*ifp;
536 	struct ether_multi	*enm;
537 	struct ether_multistep	step;
538 	u_int32_t		h = 0;
539 	u_int8_t		rxmode;
540 	u_int8_t		hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
541 
542 	if (sc->mos_dying)
543 		return;
544 
545 	ifp = GET_IFP(sc);
546 
547 	rxmode = mos_reg_read_1(sc, MOS_CTL);
548 
549 	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
550 allmulti:
551 		rxmode |= MOS_CTL_ALLMULTI;
552 		mos_reg_write_1(sc, MOS_CTL, rxmode);
553 		return;
554 	} else
555 		rxmode &= ~MOS_CTL_ALLMULTI;
556 
557 	/* now program new ones */
558 	ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
559 	while (enm != NULL) {
560 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
561 		   ETHER_ADDR_LEN) != 0)
562 			goto allmulti;
563 
564 		h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
565 		hashtbl[h / 8] |= 1 << (h % 8);
566 		ETHER_NEXT_MULTI(step, enm);
567 	}
568 
569 	ifp->if_flags &= ~IFF_ALLMULTI;
570 	mos_write_mcast(sc, (void *)&hashtbl);
571 	mos_reg_write_1(sc, MOS_CTL, rxmode);
572 	return;
573 }
574 
575 void
576 mos_reset(struct mos_softc *sc)
577 {
578 	u_int8_t ctl;
579 	if (sc->mos_dying)
580 		return;
581 
582 	ctl = mos_reg_read_1(sc, MOS_CTL);
583 	ctl &= ~(MOS_CTL_RX_PROMISC | MOS_CTL_ALLMULTI | MOS_CTL_TX_ENB |
584 	    MOS_CTL_RX_ENB);
585 	/* Disable RX, TX, promiscuous and allmulticast mode */
586 	mos_reg_write_1(sc, MOS_CTL, ctl);
587 
588 	/* Reset frame drop counter register to zero */
589 	mos_reg_write_1(sc, MOS_FRAME_DROP_CNT, 0);
590 
591 	/* Wait a little while for the chip to get its brains in order. */
592 	DELAY(1000);
593 	return;
594 }
595 
596 void
597 mos_chip_init(struct mos_softc *sc)
598 {
599 	int	i;
600 
601 	/*
602 	 * Rev.C devices have a pause threshold register which needs to be set
603 	 * at startup.
604 	 */
605 	if (mos_reg_read_1(sc, MOS_PAUSE_TRHD) != -1) {
606 		for (i=0;i<MOS_PAUSE_REWRITES;i++)
607 			mos_reg_write_1(sc, MOS_PAUSE_TRHD, 0);
608 	}
609 
610 	sc->mos_phyaddrs[0] = 1; sc->mos_phyaddrs[1] = 0xFF;
611 }
612 
613 /*
614  * Probe for a MCS7x30 chip.
615  */
616 int
617 mos_match(struct device *parent, void *match, void *aux)
618 {
619 	struct usb_attach_arg *uaa = aux;
620 
621 	if (!uaa->iface)
622 		return(UMATCH_NONE);
623 
624 	return (mos_lookup(uaa->vendor, uaa->product) != NULL ?
625 	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
626 }
627 
628 /*
629  * Attach the interface. Allocate softc structures, do ifmedia
630  * setup and ethernet/BPF attach.
631  */
632 void
633 mos_attach(struct device *parent, struct device *self, void *aux)
634 {
635 	struct mos_softc	*sc = (struct mos_softc *)self;
636 	struct usb_attach_arg	*uaa = aux;
637 	struct ifnet		*ifp;
638 	usbd_device_handle	dev = uaa->device;
639 	usbd_status		err;
640 	usb_interface_descriptor_t 	*id;
641 	usb_endpoint_descriptor_t 	*ed;
642 	struct mii_data 	*mii;
643 	u_char			eaddr[ETHER_ADDR_LEN];
644 	int			i,s;
645 
646 	sc->mos_unit = self->dv_unit;
647 
648 	err = usbd_set_config_no(dev, MOS_CONFIG_NO, 1);
649 	if (err) {
650 		printf("%s: getting interface handle failed\n",
651 		    sc->mos_dev.dv_xname);
652 		return;
653 	}
654 
655 	usb_init_task(&sc->mos_tick_task, mos_tick_task, sc);
656 	rw_init(&sc->mos_mii_lock, "mosmii");
657 	usb_init_task(&sc->mos_stop_task, (void (*)(void *))mos_stop, sc);
658 
659 	err = usbd_device2interface_handle(dev, MOS_IFACE_IDX, &sc->mos_iface);
660 	if (err) {
661 		printf("%s: getting interface handle failed\n",
662 		    sc->mos_dev.dv_xname);
663 		return;
664 	}
665 
666 	sc->mos_udev = dev;
667 	sc->mos_flags = mos_lookup(uaa->vendor, uaa->product)->mos_flags;
668 
669 	id = usbd_get_interface_descriptor(sc->mos_iface);
670 
671 	sc->mos_bufsz = MOS_BUFSZ;
672 
673 	/* Find endpoints. */
674 	for (i = 0; i < id->bNumEndpoints; i++) {
675 		ed = usbd_interface2endpoint_descriptor(sc->mos_iface, i);
676 		if (!ed) {
677 			printf("%s: couldn't get ep %d\n",
678 			    sc->mos_dev.dv_xname, i);
679 			return;
680 		}
681 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
682 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
683 			sc->mos_ed[MOS_ENDPT_RX] = ed->bEndpointAddress;
684 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
685 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
686 			sc->mos_ed[MOS_ENDPT_TX] = ed->bEndpointAddress;
687 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
688 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
689 			sc->mos_ed[MOS_ENDPT_INTR] = ed->bEndpointAddress;
690 		}
691 	}
692 
693 	s = splnet();
694 
695 	printf("%s:", sc->mos_dev.dv_xname);
696 
697 	if (sc->mos_flags & MCS7730) {
698 		printf(" MCS7730");
699 	} else if (sc->mos_flags & MCS7830) {
700 		printf(" MCS7830");
701 	}
702 
703 	mos_chip_init(sc);
704 
705 	/*
706 	 * Read MAC address, inform the world.
707 	 */
708 	err = mos_readmac(sc, (void*)&eaddr);
709 	if (err) {
710 		printf("%s: couldn't get MAC address\n",
711 		    sc->mos_dev.dv_xname);
712 		return;
713 	}
714 	bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
715 	printf(", address %s\n", ether_sprintf(eaddr));
716 
717 	/* Initialize interface info.*/
718 	ifp = GET_IFP(sc);
719 	ifp->if_softc = sc;
720 	ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST;
721 	ifp->if_ioctl = mos_ioctl;
722 	ifp->if_start = mos_start;
723 	ifp->if_watchdog = mos_watchdog;
724 	strlcpy(ifp->if_xname, sc->mos_dev.dv_xname, IFNAMSIZ);
725 
726 	IFQ_SET_READY(&ifp->if_snd);
727 
728 	ifp->if_capabilities = IFCAP_VLAN_MTU;
729 
730 	/* Initialize MII/media info. */
731 	mii = GET_MII(sc);
732 	mii->mii_ifp = ifp;
733 	mii->mii_readreg = mos_miibus_readreg;
734 	mii->mii_writereg = mos_miibus_writereg;
735 	mii->mii_statchg = mos_miibus_statchg;
736 	mii->mii_flags = MIIF_AUTOTSLEEP;
737 
738 	ifmedia_init(&mii->mii_media, 0, mos_ifmedia_upd, mos_ifmedia_sts);
739 	mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
740 
741 	if (LIST_FIRST(&mii->mii_phys) == NULL) {
742 		ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
743 		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
744 	} else
745 		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
746 
747 	/* Attach the interface. */
748 	if_attach(ifp);
749 	ether_ifattach(ifp);
750 
751 	timeout_set(&sc->mos_stat_ch, mos_tick, sc);
752 
753 	sc->mos_attached = 1;
754 	splx(s);
755 
756 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->mos_udev,
757 			   &sc->mos_dev);
758 }
759 
760 int
761 mos_detach(struct device *self, int flags)
762 {
763 	struct mos_softc	*sc = (struct mos_softc *)self;
764 	struct ifnet		*ifp = GET_IFP(sc);
765 	int			s;
766 
767 	DPRINTFN(2,("%s: %s: enter\n", sc->mos_dev.dv_xname, __func__));
768 
769 	if (!sc->mos_attached)
770 		return (0);
771 
772 	timeout_del(&sc->mos_stat_ch);
773 
774 	sc->mos_dying = 1;
775 
776 	if (sc->mos_ep[MOS_ENDPT_TX] != NULL)
777 		usbd_abort_pipe(sc->mos_ep[MOS_ENDPT_TX]);
778 	if (sc->mos_ep[MOS_ENDPT_RX] != NULL)
779 		usbd_abort_pipe(sc->mos_ep[MOS_ENDPT_RX]);
780 	if (sc->mos_ep[MOS_ENDPT_INTR] != NULL)
781 		usbd_abort_pipe(sc->mos_ep[MOS_ENDPT_INTR]);
782 
783 	/*
784 	 * Remove any pending tasks.  They cannot be executing because they run
785 	 * in the same thread as detach.
786 	 */
787 	usb_rem_task(sc->mos_udev, &sc->mos_tick_task);
788 	usb_rem_task(sc->mos_udev, &sc->mos_stop_task);
789 	s = splusb();
790 
791 	if (--sc->mos_refcnt >= 0) {
792 		/* Wait for processes to go away */
793 		usb_detach_wait(&sc->mos_dev);
794 	}
795 
796 	if (ifp->if_flags & IFF_RUNNING)
797 		mos_stop(sc);
798 
799 	mii_detach(&sc->mos_mii, MII_PHY_ANY, MII_OFFSET_ANY);
800 	ifmedia_delete_instance(&sc->mos_mii.mii_media, IFM_INST_ANY);
801 	ether_ifdetach(ifp);
802 	if_detach(ifp);
803 
804 #ifdef DIAGNOSTIC
805 	if (sc->mos_ep[MOS_ENDPT_TX] != NULL ||
806 	    sc->mos_ep[MOS_ENDPT_RX] != NULL ||
807 	    sc->mos_ep[MOS_ENDPT_INTR] != NULL)
808 		printf("%s: detach has active endpoints\n",
809 		    sc->mos_dev.dv_xname);
810 #endif
811 
812 	sc->mos_attached = 0;
813 
814 	if (--sc->mos_refcnt >= 0) {
815 		/* Wait for processes to go away. */
816 		usb_detach_wait(&sc->mos_dev);
817 	}
818 	splx(s);
819 
820 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->mos_udev,
821 			   &sc->mos_dev);
822 
823 	return (0);
824 }
825 
826 
827 int
828 mos_activate(struct device *self, int act)
829 {
830 	struct mos_softc *sc = (struct mos_softc *)self;
831 
832 	DPRINTFN(2,("%s: %s: enter\n", sc->mos_dev.dv_xname, __func__));
833 
834 	switch (act) {
835 	case DVACT_ACTIVATE:
836 		break;
837 
838 	case DVACT_DEACTIVATE:
839 		sc->mos_dying = 1;
840 		break;
841 	}
842 	return (0);
843 }
844 
845 struct mbuf *
846 mos_newbuf(void)
847 {
848 	struct mbuf		*m;
849 
850 	MGETHDR(m, M_DONTWAIT, MT_DATA);
851 	if (m == NULL)
852 		return (NULL);
853 
854 	MCLGET(m, M_DONTWAIT);
855 	if (!(m->m_flags & M_EXT)) {
856 		m_freem(m);
857 		return (NULL);
858 	}
859 
860 	m->m_len = m->m_pkthdr.len = MCLBYTES;
861 	m_adj(m, ETHER_ALIGN);
862 
863 	return (m);
864 }
865 
866 int
867 mos_rx_list_init(struct mos_softc *sc)
868 {
869 	struct mos_cdata	*cd;
870 	struct mos_chain	*c;
871 	int 			i;
872 
873 	DPRINTF(("%s: %s: enter\n", sc->mos_dev.dv_xname, __func__));
874 
875 	cd = &sc->mos_cdata;
876 	for (i = 0; i < MOS_RX_LIST_CNT; i++) {
877 		c = &cd->mos_rx_chain[i];
878 		c->mos_sc = sc;
879 		c->mos_idx = i;
880 		c->mos_mbuf = NULL;
881 		if (c->mos_xfer == NULL) {
882 			c->mos_xfer = usbd_alloc_xfer(sc->mos_udev);
883 			if (c->mos_xfer == NULL)
884 				return (ENOBUFS);
885 			c->mos_buf = usbd_alloc_buffer(c->mos_xfer,
886 			    sc->mos_bufsz);
887 			if (c->mos_buf == NULL) {
888 				usbd_free_xfer(c->mos_xfer);
889 				return (ENOBUFS);
890 			}
891 		}
892 	}
893 
894 	return (0);
895 }
896 
897 int
898 mos_tx_list_init(struct mos_softc *sc)
899 {
900 	struct mos_cdata	*cd;
901 	struct mos_chain	*c;
902 	int			i;
903 
904 	DPRINTF(("%s: %s: enter\n", sc->mos_dev.dv_xname, __func__));
905 
906 	cd = &sc->mos_cdata;
907 	for (i = 0; i < MOS_TX_LIST_CNT; i++) {
908 		c = &cd->mos_tx_chain[i];
909 		c->mos_sc = sc;
910 		c->mos_idx = i;
911 		c->mos_mbuf = NULL;
912 		if (c->mos_xfer == NULL) {
913 			c->mos_xfer = usbd_alloc_xfer(sc->mos_udev);
914 			if (c->mos_xfer == NULL)
915 				return (ENOBUFS);
916 			c->mos_buf = usbd_alloc_buffer(c->mos_xfer,
917 			    sc->mos_bufsz);
918 			if (c->mos_buf == NULL) {
919 				usbd_free_xfer(c->mos_xfer);
920 				return (ENOBUFS);
921 			}
922 		}
923 	}
924 
925 	return (0);
926 }
927 
928 /*
929  * A frame has been uploaded: pass the resulting mbuf chain up to
930  * the higher level protocols.
931  */
932 void
933 mos_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
934 {
935 	struct mos_chain	*c = (struct mos_chain *)priv;
936 	struct mos_softc	*sc = c->mos_sc;
937 	struct ifnet		*ifp = GET_IFP(sc);
938 	u_char			*buf = c->mos_buf;
939 	u_int8_t		rxstat;
940 	u_int32_t		total_len;
941 	u_int16_t		pktlen = 0;
942 	struct mbuf		*m;
943 	int			s;
944 
945 	DPRINTFN(10,("%s: %s: enter\n", sc->mos_dev.dv_xname,__func__));
946 
947 	if (sc->mos_dying)
948 		return;
949 
950 	if (!(ifp->if_flags & IFF_RUNNING))
951 		return;
952 
953 	if (status != USBD_NORMAL_COMPLETION) {
954 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
955 			return;
956 		if (usbd_ratecheck(&sc->mos_rx_notice)) {
957 			printf("%s: usb errors on rx: %s\n",
958 			    sc->mos_dev.dv_xname, usbd_errstr(status));
959 		}
960 		if (status == USBD_STALLED)
961 			usbd_clear_endpoint_stall_async(sc->mos_ep[MOS_ENDPT_RX]);
962 		goto done;
963 	}
964 
965 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
966 
967 	if (total_len <= 1)
968 		goto done;
969 
970 	/* evaluate status byte at the end */
971 	pktlen = total_len - 1;
972 	rxstat = buf[pktlen] & MOS_RXSTS_MASK;
973 
974 	if (rxstat != MOS_RXSTS_VALID) {
975 		DPRINTF(("%s: erroneous frame received: ",
976 		    sc->mos_dev.dv_xname));
977 		if (rxstat & MOS_RXSTS_SHORT_FRAME)
978 			DPRINTF(("frame size less than 64 bytes\n"));
979 		if (rxstat & MOS_RXSTS_LARGE_FRAME)
980 			DPRINTF(("frame size larger than 1532 bytes\n"));
981 		if (rxstat & MOS_RXSTS_CRC_ERROR)
982 			DPRINTF(("CRC error\n"));
983 		if (rxstat & MOS_RXSTS_ALIGN_ERROR)
984 			DPRINTF(("alignment error\n"));
985 		ifp->if_ierrors++;
986 		goto done;
987 	}
988 
989 	if ( pktlen < sizeof(struct ether_header) ) {
990 		ifp->if_ierrors++;
991 		goto done;
992 	}
993 
994 	m = mos_newbuf();
995 	if (m == NULL) {
996 		ifp->if_ierrors++;
997 		goto done;
998 	}
999 
1000 	ifp->if_ipackets++;
1001 	m->m_pkthdr.rcvif = ifp;
1002 	m->m_pkthdr.len = m->m_len = pktlen;
1003 
1004 	memcpy(mtod(m, char *), buf, pktlen);
1005 
1006 	/* push the packet up */
1007 	s = splnet();
1008 #if NBPFILTER > 0
1009 	if (ifp->if_bpf)
1010 		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1011 #endif
1012 
1013 	ether_input_mbuf(ifp, m);
1014 
1015 	splx(s);
1016 
1017 done:
1018 	memset(c->mos_buf, 0, sc->mos_bufsz);
1019 
1020 	/* Setup new transfer. */
1021 	usbd_setup_xfer(xfer, sc->mos_ep[MOS_ENDPT_RX],
1022 	    c, c->mos_buf, sc->mos_bufsz,
1023 	    USBD_SHORT_XFER_OK | USBD_NO_COPY,
1024 	    USBD_NO_TIMEOUT, mos_rxeof);
1025 	usbd_transfer(xfer);
1026 
1027 	DPRINTFN(10,("%s: %s: start rx\n", sc->mos_dev.dv_xname, __func__));
1028 
1029 	return;
1030 }
1031 
1032 /*
1033  * A frame was downloaded to the chip. It's safe for us to clean up
1034  * the list buffers.
1035  */
1036 
1037 void
1038 mos_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
1039 {
1040 	struct mos_softc	*sc;
1041 	struct mos_chain	*c;
1042 	struct ifnet		*ifp;
1043 	int			s;
1044 
1045 	c = priv;
1046 	sc = c->mos_sc;
1047 	ifp = &sc->arpcom.ac_if;
1048 
1049 	if (sc->mos_dying)
1050 		return;
1051 
1052 	s = splnet();
1053 
1054 	if (status != USBD_NORMAL_COMPLETION) {
1055 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1056 			splx(s);
1057 			return;
1058 		}
1059 		ifp->if_oerrors++;
1060 		printf("%s: usb error on tx: %s\n", sc->mos_dev.dv_xname,
1061 		    usbd_errstr(status));
1062 		if (status == USBD_STALLED)
1063 			usbd_clear_endpoint_stall_async(sc->mos_ep[MOS_ENDPT_TX]);
1064 		splx(s);
1065 		return;
1066 	}
1067 
1068 	ifp->if_timer = 0;
1069 	ifp->if_flags &= ~IFF_OACTIVE;
1070 
1071 	m_freem(c->mos_mbuf);
1072 	c->mos_mbuf = NULL;
1073 
1074 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1075 		mos_start(ifp);
1076 
1077 	ifp->if_opackets++;
1078 	splx(s);
1079 	return;
1080 }
1081 
1082 void
1083 mos_tick(void *xsc)
1084 {
1085 	struct mos_softc *sc = xsc;
1086 
1087 	if (sc == NULL)
1088 		return;
1089 
1090 	DPRINTFN(0xff, ("%s: %s: enter\n", sc->mos_dev.dv_xname,
1091 			__func__));
1092 
1093 	if (sc->mos_dying)
1094 		return;
1095 
1096 	/* Perform periodic stuff in process context */
1097 	usb_add_task(sc->mos_udev, &sc->mos_tick_task);
1098 
1099 }
1100 
1101 void
1102 mos_tick_task(void *xsc)
1103 {
1104 	int			s;
1105 	struct mos_softc	*sc;
1106 	struct ifnet		*ifp;
1107 	struct mii_data		*mii;
1108 
1109 	sc = xsc;
1110 
1111 	if (sc == NULL)
1112 		return;
1113 
1114 	if (sc->mos_dying)
1115 		return;
1116 
1117 	ifp = GET_IFP(sc);
1118 	mii = GET_MII(sc);
1119 	if (mii == NULL)
1120 		return;
1121 
1122 	s = splnet();
1123 
1124 	mii_tick(mii);
1125 	if (!sc->mos_link && mii->mii_media_status & IFM_ACTIVE &&
1126 	    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
1127 		DPRINTF(("%s: %s: got link\n",
1128 			 sc->mos_dev.dv_xname, __func__));
1129 		sc->mos_link++;
1130 		if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1131 			mos_start(ifp);
1132 	}
1133 
1134 	timeout_add_sec(&sc->mos_stat_ch, 1);
1135 
1136 	splx(s);
1137 }
1138 
1139 int
1140 mos_encap(struct mos_softc *sc, struct mbuf *m, int idx)
1141 {
1142 	struct mos_chain	*c;
1143 	usbd_status		err;
1144 	int			length;
1145 
1146 	c = &sc->mos_cdata.mos_tx_chain[idx];
1147 
1148 	m_copydata(m, 0, m->m_pkthdr.len, c->mos_buf);
1149 	length = m->m_pkthdr.len;
1150 
1151 	c->mos_mbuf = m;
1152 
1153 	usbd_setup_xfer(c->mos_xfer, sc->mos_ep[MOS_ENDPT_TX],
1154 	    c, c->mos_buf, length, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
1155 	    10000, mos_txeof);
1156 
1157 	/* Transmit */
1158 	err = usbd_transfer(c->mos_xfer);
1159 	if (err != USBD_IN_PROGRESS) {
1160 		mos_stop(sc);
1161 		return(EIO);
1162 	}
1163 
1164 	sc->mos_cdata.mos_tx_cnt++;
1165 
1166 	return(0);
1167 }
1168 
1169 void
1170 mos_start(struct ifnet *ifp)
1171 {
1172 	struct mos_softc	*sc;
1173 	struct mbuf		*m_head = NULL;
1174 
1175 	sc = ifp->if_softc;
1176 
1177 	if (!sc->mos_link)
1178 		return;
1179 
1180 	if (ifp->if_flags & IFF_OACTIVE)
1181 		return;
1182 
1183 	IFQ_POLL(&ifp->if_snd, m_head);
1184 	if (m_head == NULL)
1185 		return;
1186 
1187 	if (mos_encap(sc, m_head, 0)) {
1188 		ifp->if_flags |= IFF_OACTIVE;
1189 		return;
1190 	}
1191 	IFQ_DEQUEUE(&ifp->if_snd, m_head);
1192 
1193 	/*
1194 	 * If there's a BPF listener, bounce a copy of this frame
1195 	 * to him.
1196 	 */
1197 #if NBPFILTER > 0
1198 	if (ifp->if_bpf)
1199 		bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
1200 #endif
1201 
1202 	ifp->if_flags |= IFF_OACTIVE;
1203 
1204 	/*
1205 	 * Set a timeout in case the chip goes out to lunch.
1206 	 */
1207 	ifp->if_timer = 5;
1208 
1209 	return;
1210 }
1211 
1212 void
1213 mos_init(void *xsc)
1214 {
1215 	struct mos_softc	*sc = xsc;
1216 	struct ifnet		*ifp = &sc->arpcom.ac_if;
1217 	struct mos_chain	*c;
1218 	usbd_status		err;
1219 	u_int8_t		rxmode;
1220 	int			i, s;
1221 
1222 	s = splnet();
1223 
1224 	/*
1225 	 * Cancel pending I/O and free all RX/TX buffers.
1226 	 */
1227 	mos_reset(sc);
1228 
1229 	/*
1230 	 * Write MAC address
1231 	 */
1232 	mos_writemac(sc, sc->arpcom.ac_enaddr);
1233 
1234 	/* Init RX ring. */
1235 	if (mos_rx_list_init(sc) == ENOBUFS) {
1236 		printf("%s: rx list init failed\n", sc->mos_dev.dv_xname);
1237 		splx(s);
1238 		return;
1239 	}
1240 
1241 	/* Init TX ring. */
1242 	if (mos_tx_list_init(sc) == ENOBUFS) {
1243 		printf("%s: tx list init failed\n", sc->mos_dev.dv_xname);
1244 		splx(s);
1245 		return;
1246 	}
1247 
1248 	/* Read and set transmitter IPG values */
1249 	sc->mos_ipgs[0] = mos_reg_read_1(sc, MOS_IPG0);
1250 	sc->mos_ipgs[1] = mos_reg_read_1(sc, MOS_IPG1);
1251 	mos_reg_write_1(sc, MOS_IPG0, sc->mos_ipgs[0]);
1252 	mos_reg_write_1(sc, MOS_IPG1, sc->mos_ipgs[1]);
1253 
1254 	/* Enable receiver and transmitter, bridge controls speed/duplex mode */
1255 	rxmode = mos_reg_read_1(sc, MOS_CTL);
1256 	rxmode |= MOS_CTL_RX_ENB | MOS_CTL_TX_ENB | MOS_CTL_BS_ENB;
1257 	rxmode &= ~(MOS_CTL_SLEEP);
1258 
1259 	/* If we want promiscuous mode, set the allframes bit. */
1260 	if (ifp->if_flags & IFF_PROMISC)
1261 		rxmode |= MOS_CTL_RX_PROMISC;
1262 
1263 	/* XXX: broadcast mode? */
1264 
1265 	mos_reg_write_1(sc, MOS_CTL, rxmode);
1266 
1267 	/* Load the multicast filter. */
1268 	mos_setmulti(sc);
1269 
1270 	mii_mediachg(GET_MII(sc));
1271 
1272 	/* Open RX and TX pipes. */
1273 	err = usbd_open_pipe(sc->mos_iface, sc->mos_ed[MOS_ENDPT_RX],
1274 	    USBD_EXCLUSIVE_USE, &sc->mos_ep[MOS_ENDPT_RX]);
1275 	if (err) {
1276 		printf("%s: open rx pipe failed: %s\n",
1277 		    sc->mos_dev.dv_xname, usbd_errstr(err));
1278 		splx(s);
1279 		return;
1280 	}
1281 
1282 	err = usbd_open_pipe(sc->mos_iface, sc->mos_ed[MOS_ENDPT_TX],
1283 	    USBD_EXCLUSIVE_USE, &sc->mos_ep[MOS_ENDPT_TX]);
1284 	if (err) {
1285 		printf("%s: open tx pipe failed: %s\n",
1286 		    sc->mos_dev.dv_xname, usbd_errstr(err));
1287 		splx(s);
1288 		return;
1289 	}
1290 
1291 	/* Start up the receive pipe. */
1292 	for (i = 0; i < MOS_RX_LIST_CNT; i++) {
1293 		c = &sc->mos_cdata.mos_rx_chain[i];
1294 		usbd_setup_xfer(c->mos_xfer, sc->mos_ep[MOS_ENDPT_RX],
1295 		    c, c->mos_buf, sc->mos_bufsz,
1296 		    USBD_SHORT_XFER_OK | USBD_NO_COPY,
1297 		    USBD_NO_TIMEOUT, mos_rxeof);
1298 		usbd_transfer(c->mos_xfer);
1299 	}
1300 
1301 	ifp->if_flags |= IFF_RUNNING;
1302 	ifp->if_flags &= ~IFF_OACTIVE;
1303 
1304 	splx(s);
1305 
1306 	timeout_add_sec(&sc->mos_stat_ch, 1);
1307 	return;
1308 }
1309 
1310 int
1311 mos_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1312 {
1313 	struct mos_softc	*sc = ifp->if_softc;
1314 	struct ifreq		*ifr = (struct ifreq *)data;
1315 	struct ifaddr		*ifa = (struct ifaddr *)data;
1316 	struct mii_data		*mii;
1317 	u_int8_t		rxmode;
1318 	int			s, error = 0;
1319 
1320 	s = splnet();
1321 
1322 	switch(cmd) {
1323 	case SIOCSIFADDR:
1324 		ifp->if_flags |= IFF_UP;
1325 		if (!(ifp->if_flags & IFF_RUNNING))
1326 			mos_init(sc);
1327 #ifdef INET
1328 		if (ifa->ifa_addr->sa_family == AF_INET)
1329 			arp_ifinit(&sc->arpcom, ifa);
1330 #endif
1331 		break;
1332 
1333 	case SIOCSIFMTU:
1334 		if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
1335 			error = EINVAL;
1336 		else if (ifp->if_mtu != ifr->ifr_mtu)
1337 			ifp->if_mtu = ifr->ifr_mtu;
1338 		break;
1339 
1340 	case SIOCSIFFLAGS:
1341 		if (ifp->if_flags & IFF_UP) {
1342 			if (ifp->if_flags & IFF_RUNNING &&
1343 			    ifp->if_flags & IFF_PROMISC &&
1344 			    !(sc->mos_if_flags & IFF_PROMISC)) {
1345 				rxmode = mos_reg_read_1(sc, MOS_CTL);
1346 				rxmode |= MOS_CTL_RX_PROMISC;
1347 				mos_reg_write_1(sc, MOS_CTL, rxmode);
1348 				mos_setmulti(sc);
1349 			} else if (ifp->if_flags & IFF_RUNNING &&
1350 			    !(ifp->if_flags & IFF_PROMISC) &&
1351 			    !(sc->mos_if_flags & IFF_PROMISC)) {
1352 				rxmode = mos_reg_read_1(sc, MOS_CTL);
1353 				rxmode |= MOS_CTL_RX_PROMISC;
1354 				mos_reg_write_1(sc, MOS_CTL, rxmode);
1355 				mos_setmulti(sc);
1356 			} else if (!(ifp->if_flags & IFF_RUNNING))
1357 				mos_init(sc);
1358 		} else {
1359 			if (ifp->if_flags & IFF_RUNNING)
1360 				mos_stop(sc);
1361 		}
1362 		sc->mos_if_flags = ifp->if_flags;
1363 		break;
1364 	case SIOCADDMULTI:
1365 	case SIOCDELMULTI:
1366 		error = (cmd == SIOCADDMULTI) ?
1367 		    ether_addmulti(ifr, &sc->arpcom) :
1368 		    ether_delmulti(ifr, &sc->arpcom);
1369 
1370 		if (error == ENETRESET) {
1371 			/*
1372 			 * Multicast list has changed; set the hardware
1373 			 * filter accordingly.
1374 			 */
1375 			if (ifp->if_flags & IFF_RUNNING)
1376 				mos_setmulti(sc);
1377 			error = 0;
1378 		}
1379 		break;
1380 	case SIOCGIFMEDIA:
1381 	case SIOCSIFMEDIA:
1382 		mii = GET_MII(sc);
1383 		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
1384 		break;
1385 
1386 	default:
1387 		error = ether_ioctl(ifp, &sc->arpcom, cmd, data);
1388 	}
1389 
1390 	splx(s);
1391 	return(error);
1392 }
1393 
1394 void
1395 mos_watchdog(struct ifnet *ifp)
1396 {
1397 	struct mos_softc	*sc;
1398 	struct mos_chain	*c;
1399 	usbd_status		stat;
1400 	int			s;
1401 
1402 	sc = ifp->if_softc;
1403 
1404 	ifp->if_oerrors++;
1405 	printf("%s: watchdog timeout\n", sc->mos_dev.dv_xname);
1406 
1407 	s = splusb();
1408 	c = &sc->mos_cdata.mos_tx_chain[0];
1409 	usbd_get_xfer_status(c->mos_xfer, NULL, NULL, NULL, &stat);
1410 	mos_txeof(c->mos_xfer, c, stat);
1411 
1412 	if (!IFQ_IS_EMPTY(&ifp->if_snd))
1413 		mos_start(ifp);
1414 	splx(s);
1415 }
1416 
1417 
1418 /*
1419  * Stop the adapter and free any mbufs allocated to the
1420  * RX and TX lists.
1421  */
1422 void
1423 mos_stop(struct mos_softc *sc)
1424 {
1425 	usbd_status		err;
1426 	struct ifnet		*ifp;
1427 	int			i;
1428 
1429 	mos_reset(sc);
1430 
1431 	ifp = &sc->arpcom.ac_if;
1432 	ifp->if_timer = 0;
1433 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1434 
1435 	timeout_del(&sc->mos_stat_ch);
1436 
1437 	/* Stop transfers. */
1438 	if (sc->mos_ep[MOS_ENDPT_RX] != NULL) {
1439 		err = usbd_abort_pipe(sc->mos_ep[MOS_ENDPT_RX]);
1440 		if (err) {
1441 			printf("%s: abort rx pipe failed: %s\n",
1442 			    sc->mos_dev.dv_xname, usbd_errstr(err));
1443 		}
1444 		err = usbd_close_pipe(sc->mos_ep[MOS_ENDPT_RX]);
1445 		if (err) {
1446 			printf("%s: close rx pipe failed: %s\n",
1447 			    sc->mos_dev.dv_xname, usbd_errstr(err));
1448 		}
1449 		sc->mos_ep[MOS_ENDPT_RX] = NULL;
1450 	}
1451 
1452 	if (sc->mos_ep[MOS_ENDPT_TX] != NULL) {
1453 		err = usbd_abort_pipe(sc->mos_ep[MOS_ENDPT_TX]);
1454 		if (err) {
1455 			printf("%s: abort tx pipe failed: %s\n",
1456 			    sc->mos_dev.dv_xname, usbd_errstr(err));
1457 		}
1458 		err = usbd_close_pipe(sc->mos_ep[MOS_ENDPT_TX]);
1459 		if (err) {
1460 			printf("%s: close tx pipe failed: %s\n",
1461 			    sc->mos_dev.dv_xname, usbd_errstr(err));
1462 		}
1463 		sc->mos_ep[MOS_ENDPT_TX] = NULL;
1464 	}
1465 
1466 	if (sc->mos_ep[MOS_ENDPT_INTR] != NULL) {
1467 		err = usbd_abort_pipe(sc->mos_ep[MOS_ENDPT_INTR]);
1468 		if (err) {
1469 			printf("%s: abort intr pipe failed: %s\n",
1470 			    sc->mos_dev.dv_xname, usbd_errstr(err));
1471 		}
1472 		err = usbd_close_pipe(sc->mos_ep[MOS_ENDPT_INTR]);
1473 		if (err) {
1474 			printf("%s: close intr pipe failed: %s\n",
1475 			    sc->mos_dev.dv_xname, usbd_errstr(err));
1476 		}
1477 		sc->mos_ep[MOS_ENDPT_INTR] = NULL;
1478 	}
1479 
1480 	/* Free RX resources. */
1481 	for (i = 0; i < MOS_RX_LIST_CNT; i++) {
1482 		if (sc->mos_cdata.mos_rx_chain[i].mos_mbuf != NULL) {
1483 			m_freem(sc->mos_cdata.mos_rx_chain[i].mos_mbuf);
1484 			sc->mos_cdata.mos_rx_chain[i].mos_mbuf = NULL;
1485 		}
1486 		if (sc->mos_cdata.mos_rx_chain[i].mos_xfer != NULL) {
1487 			usbd_free_xfer(sc->mos_cdata.mos_rx_chain[i].mos_xfer);
1488 			sc->mos_cdata.mos_rx_chain[i].mos_xfer = NULL;
1489 		}
1490 	}
1491 
1492 	/* Free TX resources. */
1493 	for (i = 0; i < MOS_TX_LIST_CNT; i++) {
1494 		if (sc->mos_cdata.mos_tx_chain[i].mos_mbuf != NULL) {
1495 			m_freem(sc->mos_cdata.mos_tx_chain[i].mos_mbuf);
1496 			sc->mos_cdata.mos_tx_chain[i].mos_mbuf = NULL;
1497 		}
1498 		if (sc->mos_cdata.mos_tx_chain[i].mos_xfer != NULL) {
1499 			usbd_free_xfer(sc->mos_cdata.mos_tx_chain[i].mos_xfer);
1500 			sc->mos_cdata.mos_tx_chain[i].mos_xfer = NULL;
1501 		}
1502 	}
1503 
1504 	sc->mos_link = 0;
1505 }
1506 
1507