xref: /netbsd-src/sys/dev/usb/if_cue.c (revision ba65fde2d7fefa7d39838fa5fa855e62bd606b5e)
1 /*	$NetBSD: if_cue.c,v 1.67 2013/01/22 14:03:19 jmcneill Exp $	*/
2 /*
3  * Copyright (c) 1997, 1998, 1999, 2000
4  *	Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *	This product includes software developed by Bill Paul.
17  * 4. Neither the name of the author nor the names of any co-contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31  * THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * $FreeBSD: src/sys/dev/usb/if_cue.c,v 1.4 2000/01/16 22:45:06 wpaul Exp $
34  */
35 
36 /*
37  * CATC USB-EL1210A USB to ethernet driver. Used in the CATC Netmate
38  * adapters and others.
39  *
40  * Written by Bill Paul <wpaul@ee.columbia.edu>
41  * Electrical Engineering Department
42  * Columbia University, New York City
43  */
44 
45 /*
46  * The CATC USB-EL1210A provides USB ethernet support at 10Mbps. The
47  * RX filter uses a 512-bit multicast hash table, single perfect entry
48  * for the station address, and promiscuous mode. Unlike the ADMtek
49  * and KLSI chips, the CATC ASIC supports read and write combining
50  * mode where multiple packets can be transfered using a single bulk
51  * transaction, which helps performance a great deal.
52  */
53 
54 /*
55  * Ported to NetBSD and somewhat rewritten by Lennart Augustsson.
56  */
57 
58 #include <sys/cdefs.h>
59 __KERNEL_RCSID(0, "$NetBSD: if_cue.c,v 1.67 2013/01/22 14:03:19 jmcneill Exp $");
60 
61 #ifdef _KERNEL_OPT
62 #include "opt_inet.h"
63 #endif
64 
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/callout.h>
68 #include <sys/sockio.h>
69 #include <sys/mbuf.h>
70 #include <sys/malloc.h>
71 #include <sys/kernel.h>
72 #include <sys/socket.h>
73 #include <sys/bus.h>
74 #include <sys/device.h>
75 #include <sys/rnd.h>
76 
77 #include <net/if.h>
78 #include <net/if_arp.h>
79 #include <net/if_dl.h>
80 #include <net/bpf.h>
81 #include <net/if_ether.h>
82 
83 #ifdef INET
84 #include <netinet/in.h>
85 #include <netinet/if_inarp.h>
86 #endif
87 
88 #include <dev/usb/usb.h>
89 #include <dev/usb/usbdi.h>
90 #include <dev/usb/usbdi_util.h>
91 #include <dev/usb/usbdivar.h>
92 #include <dev/usb/usbdevs.h>
93 
94 #include <dev/usb/if_cuereg.h>
95 
96 #ifdef CUE_DEBUG
97 #define DPRINTF(x)	if (cuedebug) printf x
98 #define DPRINTFN(n,x)	if (cuedebug >= (n)) printf x
99 int	cuedebug = 0;
100 #else
101 #define DPRINTF(x)
102 #define DPRINTFN(n,x)
103 #endif
104 
105 /*
106  * Various supported device vendors/products.
107  */
108 Static struct usb_devno cue_devs[] = {
109 	{ USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE },
110 	{ USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE2 },
111 	{ USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTLINK },
112 	/* Belkin F5U111 adapter covered by NETMATE entry */
113 };
114 #define cue_lookup(v, p) (usb_lookup(cue_devs, v, p))
115 
116 int cue_match(device_t, cfdata_t, void *);
117 void cue_attach(device_t, device_t, void *);
118 int cue_detach(device_t, int);
119 int cue_activate(device_t, enum devact);
120 extern struct cfdriver cue_cd;
121 CFATTACH_DECL_NEW(cue, sizeof(struct cue_softc), cue_match, cue_attach,
122     cue_detach, cue_activate);
123 
124 Static int cue_open_pipes(struct cue_softc *);
125 Static int cue_tx_list_init(struct cue_softc *);
126 Static int cue_rx_list_init(struct cue_softc *);
127 Static int cue_newbuf(struct cue_softc *, struct cue_chain *, struct mbuf *);
128 Static int cue_send(struct cue_softc *, struct mbuf *, int);
129 Static void cue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
130 Static void cue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
131 Static void cue_tick(void *);
132 Static void cue_tick_task(void *);
133 Static void cue_start(struct ifnet *);
134 Static int cue_ioctl(struct ifnet *, u_long, void *);
135 Static void cue_init(void *);
136 Static void cue_stop(struct cue_softc *);
137 Static void cue_watchdog(struct ifnet *);
138 
139 Static void cue_setmulti(struct cue_softc *);
140 Static u_int32_t cue_crc(const char *);
141 Static void cue_reset(struct cue_softc *);
142 
143 Static int cue_csr_read_1(struct cue_softc *, int);
144 Static int cue_csr_write_1(struct cue_softc *, int, int);
145 Static int cue_csr_read_2(struct cue_softc *, int);
146 #if 0
147 Static int cue_csr_write_2(struct cue_softc *, int, int);
148 #endif
149 Static int cue_mem(struct cue_softc *, int, int, void *, int);
150 Static int cue_getmac(struct cue_softc *, void *);
151 
152 #define CUE_SETBIT(sc, reg, x)				\
153 	cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) | (x))
154 
155 #define CUE_CLRBIT(sc, reg, x)				\
156 	cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) & ~(x))
157 
158 Static int
159 cue_csr_read_1(struct cue_softc	*sc, int reg)
160 {
161 	usb_device_request_t	req;
162 	usbd_status		err;
163 	u_int8_t		val = 0;
164 
165 	if (sc->cue_dying)
166 		return (0);
167 
168 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
169 	req.bRequest = CUE_CMD_READREG;
170 	USETW(req.wValue, 0);
171 	USETW(req.wIndex, reg);
172 	USETW(req.wLength, 1);
173 
174 	err = usbd_do_request(sc->cue_udev, &req, &val);
175 
176 	if (err) {
177 		DPRINTF(("%s: cue_csr_read_1: reg=0x%x err=%s\n",
178 		    device_xname(sc->cue_dev), reg, usbd_errstr(err)));
179 		return (0);
180 	}
181 
182 	DPRINTFN(10,("%s: cue_csr_read_1 reg=0x%x val=0x%x\n",
183 	    device_xname(sc->cue_dev), reg, val));
184 
185 	return (val);
186 }
187 
188 Static int
189 cue_csr_read_2(struct cue_softc	*sc, int reg)
190 {
191 	usb_device_request_t	req;
192 	usbd_status		err;
193 	uWord			val;
194 
195 	if (sc->cue_dying)
196 		return (0);
197 
198 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
199 	req.bRequest = CUE_CMD_READREG;
200 	USETW(req.wValue, 0);
201 	USETW(req.wIndex, reg);
202 	USETW(req.wLength, 2);
203 
204 	err = usbd_do_request(sc->cue_udev, &req, &val);
205 
206 	DPRINTFN(10,("%s: cue_csr_read_2 reg=0x%x val=0x%x\n",
207 	    device_xname(sc->cue_dev), reg, UGETW(val)));
208 
209 	if (err) {
210 		DPRINTF(("%s: cue_csr_read_2: reg=0x%x err=%s\n",
211 		    device_xname(sc->cue_dev), reg, usbd_errstr(err)));
212 		return (0);
213 	}
214 
215 	return (UGETW(val));
216 }
217 
218 Static int
219 cue_csr_write_1(struct cue_softc *sc, int reg, int val)
220 {
221 	usb_device_request_t	req;
222 	usbd_status		err;
223 
224 	if (sc->cue_dying)
225 		return (0);
226 
227 	DPRINTFN(10,("%s: cue_csr_write_1 reg=0x%x val=0x%x\n",
228 	    device_xname(sc->cue_dev), reg, val));
229 
230 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
231 	req.bRequest = CUE_CMD_WRITEREG;
232 	USETW(req.wValue, val);
233 	USETW(req.wIndex, reg);
234 	USETW(req.wLength, 0);
235 
236 	err = usbd_do_request(sc->cue_udev, &req, NULL);
237 
238 	if (err) {
239 		DPRINTF(("%s: cue_csr_write_1: reg=0x%x err=%s\n",
240 		    device_xname(sc->cue_dev), reg, usbd_errstr(err)));
241 		return (-1);
242 	}
243 
244 	DPRINTFN(20,("%s: cue_csr_write_1, after reg=0x%x val=0x%x\n",
245 	    device_xname(sc->cue_dev), reg, cue_csr_read_1(sc, reg)));
246 
247 	return (0);
248 }
249 
250 #if 0
251 Static int
252 cue_csr_write_2(struct cue_softc *sc, int reg, int aval)
253 {
254 	usb_device_request_t	req;
255 	usbd_status		err;
256 	uWord			val;
257 	int			s;
258 
259 	if (sc->cue_dying)
260 		return (0);
261 
262 	DPRINTFN(10,("%s: cue_csr_write_2 reg=0x%x val=0x%x\n",
263 	    device_xname(sc->cue_dev), reg, aval));
264 
265 	USETW(val, aval);
266 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
267 	req.bRequest = CUE_CMD_WRITEREG;
268 	USETW(req.wValue, val);
269 	USETW(req.wIndex, reg);
270 	USETW(req.wLength, 0);
271 
272 	err = usbd_do_request(sc->cue_udev, &req, NULL);
273 
274 	if (err) {
275 		DPRINTF(("%s: cue_csr_write_2: reg=0x%x err=%s\n",
276 		    device_xname(sc->cue_dev), reg, usbd_errstr(err)));
277 		return (-1);
278 	}
279 
280 	return (0);
281 }
282 #endif
283 
284 Static int
285 cue_mem(struct cue_softc *sc, int cmd, int addr, void *buf, int len)
286 {
287 	usb_device_request_t	req;
288 	usbd_status		err;
289 
290 	DPRINTFN(10,("%s: cue_mem cmd=0x%x addr=0x%x len=%d\n",
291 	    device_xname(sc->cue_dev), cmd, addr, len));
292 
293 	if (cmd == CUE_CMD_READSRAM)
294 		req.bmRequestType = UT_READ_VENDOR_DEVICE;
295 	else
296 		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
297 	req.bRequest = cmd;
298 	USETW(req.wValue, 0);
299 	USETW(req.wIndex, addr);
300 	USETW(req.wLength, len);
301 
302 	err = usbd_do_request(sc->cue_udev, &req, buf);
303 
304 	if (err) {
305 		DPRINTF(("%s: cue_csr_mem: addr=0x%x err=%s\n",
306 		    device_xname(sc->cue_dev), addr, usbd_errstr(err)));
307 		return (-1);
308 	}
309 
310 	return (0);
311 }
312 
313 Static int
314 cue_getmac(struct cue_softc *sc, void *buf)
315 {
316 	usb_device_request_t	req;
317 	usbd_status		err;
318 
319 	DPRINTFN(10,("%s: cue_getmac\n", device_xname(sc->cue_dev)));
320 
321 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
322 	req.bRequest = CUE_CMD_GET_MACADDR;
323 	USETW(req.wValue, 0);
324 	USETW(req.wIndex, 0);
325 	USETW(req.wLength, ETHER_ADDR_LEN);
326 
327 	err = usbd_do_request(sc->cue_udev, &req, buf);
328 
329 	if (err) {
330 		printf("%s: read MAC address failed\n",
331 		    device_xname(sc->cue_dev));
332 		return (-1);
333 	}
334 
335 	return (0);
336 }
337 
338 #define CUE_POLY	0xEDB88320
339 #define CUE_BITS	9
340 
341 Static u_int32_t
342 cue_crc(const char *addr)
343 {
344 	u_int32_t		idx, bit, data, crc;
345 
346 	/* Compute CRC for the address value. */
347 	crc = 0xFFFFFFFF; /* initial value */
348 
349 	for (idx = 0; idx < 6; idx++) {
350 		for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1)
351 			crc = (crc >> 1) ^ (((crc ^ data) & 1) ? CUE_POLY : 0);
352 	}
353 
354 	return (crc & ((1 << CUE_BITS) - 1));
355 }
356 
357 Static void
358 cue_setmulti(struct cue_softc *sc)
359 {
360 	struct ifnet		*ifp;
361 	struct ether_multi	*enm;
362 	struct ether_multistep	step;
363 	u_int32_t		h, i;
364 
365 	ifp = GET_IFP(sc);
366 
367 	DPRINTFN(2,("%s: cue_setmulti if_flags=0x%x\n",
368 	    device_xname(sc->cue_dev), ifp->if_flags));
369 
370 	if (ifp->if_flags & IFF_PROMISC) {
371 allmulti:
372 		ifp->if_flags |= IFF_ALLMULTI;
373 		for (i = 0; i < CUE_MCAST_TABLE_LEN; i++)
374 			sc->cue_mctab[i] = 0xFF;
375 		cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
376 		    &sc->cue_mctab, CUE_MCAST_TABLE_LEN);
377 		return;
378 	}
379 
380 	/* first, zot all the existing hash bits */
381 	for (i = 0; i < CUE_MCAST_TABLE_LEN; i++)
382 		sc->cue_mctab[i] = 0;
383 
384 	/* now program new ones */
385 	ETHER_FIRST_MULTI(step, &sc->cue_ec, enm);
386 	while (enm != NULL) {
387 		if (memcmp(enm->enm_addrlo,
388 		    enm->enm_addrhi, ETHER_ADDR_LEN) != 0)
389 			goto allmulti;
390 
391 		h = cue_crc(enm->enm_addrlo);
392 		sc->cue_mctab[h >> 3] |= 1 << (h & 0x7);
393 		ETHER_NEXT_MULTI(step, enm);
394 	}
395 
396 	ifp->if_flags &= ~IFF_ALLMULTI;
397 
398 	/*
399 	 * Also include the broadcast address in the filter
400 	 * so we can receive broadcast frames.
401 	 */
402 	if (ifp->if_flags & IFF_BROADCAST) {
403 		h = cue_crc(etherbroadcastaddr);
404 		sc->cue_mctab[h >> 3] |= 1 << (h & 0x7);
405 	}
406 
407 	cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
408 	    &sc->cue_mctab, CUE_MCAST_TABLE_LEN);
409 }
410 
411 Static void
412 cue_reset(struct cue_softc *sc)
413 {
414 	usb_device_request_t	req;
415 	usbd_status		err;
416 
417 	DPRINTFN(2,("%s: cue_reset\n", device_xname(sc->cue_dev)));
418 
419 	if (sc->cue_dying)
420 		return;
421 
422 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
423 	req.bRequest = CUE_CMD_RESET;
424 	USETW(req.wValue, 0);
425 	USETW(req.wIndex, 0);
426 	USETW(req.wLength, 0);
427 
428 	err = usbd_do_request(sc->cue_udev, &req, NULL);
429 
430 	if (err)
431 		printf("%s: reset failed\n", device_xname(sc->cue_dev));
432 
433 	/* Wait a little while for the chip to get its brains in order. */
434 	usbd_delay_ms(sc->cue_udev, 1);
435 }
436 
437 /*
438  * Probe for a CATC chip.
439  */
440 int
441 cue_match(device_t parent, cfdata_t match, void *aux)
442 {
443 	struct usb_attach_arg *uaa = aux;
444 
445 	return (cue_lookup(uaa->vendor, uaa->product) != NULL ?
446 		UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
447 }
448 
449 /*
450  * Attach the interface. Allocate softc structures, do ifmedia
451  * setup and ethernet/BPF attach.
452  */
453 void
454 cue_attach(device_t parent, device_t self, void *aux)
455 {
456 	struct cue_softc *sc = device_private(self);
457 	struct usb_attach_arg *uaa = aux;
458 	char			*devinfop;
459 	int			s;
460 	u_char			eaddr[ETHER_ADDR_LEN];
461 	usbd_device_handle	dev = uaa->device;
462 	usbd_interface_handle	iface;
463 	usbd_status		err;
464 	struct ifnet		*ifp;
465 	usb_interface_descriptor_t	*id;
466 	usb_endpoint_descriptor_t	*ed;
467 	int			i;
468 
469 	DPRINTFN(5,(" : cue_attach: sc=%p, dev=%p", sc, dev));
470 
471 	sc->cue_dev = self;
472 
473 	aprint_naive("\n");
474 	aprint_normal("\n");
475 
476 	devinfop = usbd_devinfo_alloc(dev, 0);
477 	aprint_normal_dev(self, "%s\n", devinfop);
478 	usbd_devinfo_free(devinfop);
479 
480 	err = usbd_set_config_no(dev, CUE_CONFIG_NO, 1);
481 	if (err) {
482 		aprint_error_dev(self, "failed to set configuration"
483 		    ", err=%s\n", usbd_errstr(err));
484 		return;
485 	}
486 
487 	sc->cue_udev = dev;
488 	sc->cue_product = uaa->product;
489 	sc->cue_vendor = uaa->vendor;
490 
491 	usb_init_task(&sc->cue_tick_task, cue_tick_task, sc, 0);
492 	usb_init_task(&sc->cue_stop_task, (void (*)(void *))cue_stop, sc, 0);
493 
494 	err = usbd_device2interface_handle(dev, CUE_IFACE_IDX, &iface);
495 	if (err) {
496 		aprint_error_dev(self, "getting interface handle failed\n");
497 		return;
498 	}
499 
500 	sc->cue_iface = iface;
501 	id = usbd_get_interface_descriptor(iface);
502 
503 	/* Find endpoints. */
504 	for (i = 0; i < id->bNumEndpoints; i++) {
505 		ed = usbd_interface2endpoint_descriptor(iface, i);
506 		if (ed == NULL) {
507 			aprint_error_dev(self, "couldn't get ep %d\n", i);
508 			return;
509 		}
510 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
511 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
512 			sc->cue_ed[CUE_ENDPT_RX] = ed->bEndpointAddress;
513 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
514 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
515 			sc->cue_ed[CUE_ENDPT_TX] = ed->bEndpointAddress;
516 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
517 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
518 			sc->cue_ed[CUE_ENDPT_INTR] = ed->bEndpointAddress;
519 		}
520 	}
521 
522 #if 0
523 	/* Reset the adapter. */
524 	cue_reset(sc);
525 #endif
526 	/*
527 	 * Get station address.
528 	 */
529 	cue_getmac(sc, &eaddr);
530 
531 	s = splnet();
532 
533 	/*
534 	 * A CATC chip was detected. Inform the world.
535 	 */
536 	aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(eaddr));
537 
538 	/* Initialize interface info.*/
539 	ifp = GET_IFP(sc);
540 	ifp->if_softc = sc;
541 	ifp->if_mtu = ETHERMTU;
542 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
543 	ifp->if_ioctl = cue_ioctl;
544 	ifp->if_start = cue_start;
545 	ifp->if_watchdog = cue_watchdog;
546 	strncpy(ifp->if_xname, device_xname(sc->cue_dev), IFNAMSIZ);
547 
548 	IFQ_SET_READY(&ifp->if_snd);
549 
550 	/* Attach the interface. */
551 	if_attach(ifp);
552 	ether_ifattach(ifp, eaddr);
553 	rnd_attach_source(&sc->rnd_source, device_xname(sc->cue_dev),
554 	    RND_TYPE_NET, 0);
555 
556 	callout_init(&(sc->cue_stat_ch), 0);
557 
558 	sc->cue_attached = 1;
559 	splx(s);
560 
561 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cue_udev, sc->cue_dev);
562 
563 	return;
564 }
565 
566 int
567 cue_detach(device_t self, int flags)
568 {
569 	struct cue_softc *sc = device_private(self);
570 	struct ifnet		*ifp = GET_IFP(sc);
571 	int			s;
572 
573 	DPRINTFN(2,("%s: %s: enter\n", device_xname(sc->cue_dev), __func__));
574 
575 	callout_stop(&sc->cue_stat_ch);
576 	/*
577 	 * Remove any pending task.  It cannot be executing because it run
578 	 * in the same thread as detach.
579 	 */
580 	usb_rem_task(sc->cue_udev, &sc->cue_tick_task);
581 	usb_rem_task(sc->cue_udev, &sc->cue_stop_task);
582 
583 	if (!sc->cue_attached) {
584 		/* Detached before attached finished, so just bail out. */
585 		return (0);
586 	}
587 
588 	s = splusb();
589 
590 	if (ifp->if_flags & IFF_RUNNING)
591 		cue_stop(sc);
592 
593 	rnd_detach_source(&sc->rnd_source);
594 	ether_ifdetach(ifp);
595 
596 	if_detach(ifp);
597 
598 #ifdef DIAGNOSTIC
599 	if (sc->cue_ep[CUE_ENDPT_TX] != NULL ||
600 	    sc->cue_ep[CUE_ENDPT_RX] != NULL ||
601 	    sc->cue_ep[CUE_ENDPT_INTR] != NULL)
602 		aprint_debug_dev(self, "detach has active endpoints\n");
603 #endif
604 
605 	sc->cue_attached = 0;
606 	splx(s);
607 
608 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->cue_udev, sc->cue_dev);
609 
610 	return (0);
611 }
612 
613 int
614 cue_activate(device_t self, enum devact act)
615 {
616 	struct cue_softc *sc = device_private(self);
617 
618 	DPRINTFN(2,("%s: %s: enter\n", device_xname(sc->cue_dev), __func__));
619 
620 	switch (act) {
621 	case DVACT_DEACTIVATE:
622 		/* Deactivate the interface. */
623 		if_deactivate(&sc->cue_ec.ec_if);
624 		sc->cue_dying = 1;
625 		return 0;
626 	default:
627 		return EOPNOTSUPP;
628 	}
629 }
630 
631 /*
632  * Initialize an RX descriptor and attach an MBUF cluster.
633  */
634 Static int
635 cue_newbuf(struct cue_softc *sc, struct cue_chain *c, struct mbuf *m)
636 {
637 	struct mbuf		*m_new = NULL;
638 
639 	if (m == NULL) {
640 		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
641 		if (m_new == NULL) {
642 			printf("%s: no memory for rx list "
643 			    "-- packet dropped!\n", device_xname(sc->cue_dev));
644 			return (ENOBUFS);
645 		}
646 
647 		MCLGET(m_new, M_DONTWAIT);
648 		if (!(m_new->m_flags & M_EXT)) {
649 			printf("%s: no memory for rx list "
650 			    "-- packet dropped!\n", device_xname(sc->cue_dev));
651 			m_freem(m_new);
652 			return (ENOBUFS);
653 		}
654 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
655 	} else {
656 		m_new = m;
657 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
658 		m_new->m_data = m_new->m_ext.ext_buf;
659 	}
660 
661 	m_adj(m_new, ETHER_ALIGN);
662 	c->cue_mbuf = m_new;
663 
664 	return (0);
665 }
666 
667 Static int
668 cue_rx_list_init(struct cue_softc *sc)
669 {
670 	struct cue_cdata	*cd;
671 	struct cue_chain	*c;
672 	int			i;
673 
674 	cd = &sc->cue_cdata;
675 	for (i = 0; i < CUE_RX_LIST_CNT; i++) {
676 		c = &cd->cue_rx_chain[i];
677 		c->cue_sc = sc;
678 		c->cue_idx = i;
679 		if (cue_newbuf(sc, c, NULL) == ENOBUFS)
680 			return (ENOBUFS);
681 		if (c->cue_xfer == NULL) {
682 			c->cue_xfer = usbd_alloc_xfer(sc->cue_udev);
683 			if (c->cue_xfer == NULL)
684 				return (ENOBUFS);
685 			c->cue_buf = usbd_alloc_buffer(c->cue_xfer, CUE_BUFSZ);
686 			if (c->cue_buf == NULL) {
687 				usbd_free_xfer(c->cue_xfer);
688 				return (ENOBUFS);
689 			}
690 		}
691 	}
692 
693 	return (0);
694 }
695 
696 Static int
697 cue_tx_list_init(struct cue_softc *sc)
698 {
699 	struct cue_cdata	*cd;
700 	struct cue_chain	*c;
701 	int			i;
702 
703 	cd = &sc->cue_cdata;
704 	for (i = 0; i < CUE_TX_LIST_CNT; i++) {
705 		c = &cd->cue_tx_chain[i];
706 		c->cue_sc = sc;
707 		c->cue_idx = i;
708 		c->cue_mbuf = NULL;
709 		if (c->cue_xfer == NULL) {
710 			c->cue_xfer = usbd_alloc_xfer(sc->cue_udev);
711 			if (c->cue_xfer == NULL)
712 				return (ENOBUFS);
713 			c->cue_buf = usbd_alloc_buffer(c->cue_xfer, CUE_BUFSZ);
714 			if (c->cue_buf == NULL) {
715 				usbd_free_xfer(c->cue_xfer);
716 				return (ENOBUFS);
717 			}
718 		}
719 	}
720 
721 	return (0);
722 }
723 
724 /*
725  * A frame has been uploaded: pass the resulting mbuf chain up to
726  * the higher level protocols.
727  */
728 Static void
729 cue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
730 {
731 	struct cue_chain	*c = priv;
732 	struct cue_softc	*sc = c->cue_sc;
733 	struct ifnet		*ifp = GET_IFP(sc);
734 	struct mbuf		*m;
735 	int			total_len = 0;
736 	u_int16_t		len;
737 	int			s;
738 
739 	DPRINTFN(10,("%s: %s: enter status=%d\n", device_xname(sc->cue_dev),
740 		     __func__, status));
741 
742 	if (sc->cue_dying)
743 		return;
744 
745 	if (!(ifp->if_flags & IFF_RUNNING))
746 		return;
747 
748 	if (status != USBD_NORMAL_COMPLETION) {
749 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
750 			return;
751 		sc->cue_rx_errs++;
752 		if (usbd_ratecheck(&sc->cue_rx_notice)) {
753 			printf("%s: %u usb errors on rx: %s\n",
754 			    device_xname(sc->cue_dev), sc->cue_rx_errs,
755 			    usbd_errstr(status));
756 			sc->cue_rx_errs = 0;
757 		}
758 		if (status == USBD_STALLED)
759 			usbd_clear_endpoint_stall_async(sc->cue_ep[CUE_ENDPT_RX]);
760 		goto done;
761 	}
762 
763 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
764 
765 	memcpy(mtod(c->cue_mbuf, char *), c->cue_buf, total_len);
766 
767 	m = c->cue_mbuf;
768 	len = UGETW(mtod(m, u_int8_t *));
769 
770 	/* No errors; receive the packet. */
771 	total_len = len;
772 
773 	if (len < sizeof(struct ether_header)) {
774 		ifp->if_ierrors++;
775 		goto done;
776 	}
777 
778 	ifp->if_ipackets++;
779 	m_adj(m, sizeof(u_int16_t));
780 	m->m_pkthdr.len = m->m_len = total_len;
781 
782 	m->m_pkthdr.rcvif = ifp;
783 
784 	s = splnet();
785 
786 	/* XXX ugly */
787 	if (cue_newbuf(sc, c, NULL) == ENOBUFS) {
788 		ifp->if_ierrors++;
789 		goto done1;
790 	}
791 
792 	/*
793 	 * Handle BPF listeners. Let the BPF user see the packet, but
794 	 * don't pass it up to the ether_input() layer unless it's
795 	 * a broadcast packet, multicast packet, matches our ethernet
796 	 * address or the interface is in promiscuous mode.
797 	 */
798 	bpf_mtap(ifp, m);
799 
800 	DPRINTFN(10,("%s: %s: deliver %d\n", device_xname(sc->cue_dev),
801 		    __func__, m->m_len));
802 	(*(ifp)->if_input)((ifp), (m));
803  done1:
804 	splx(s);
805 
806 done:
807 	/* Setup new transfer. */
808 	usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_RX],
809 	    c, c->cue_buf, CUE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
810 	    USBD_NO_TIMEOUT, cue_rxeof);
811 	usbd_transfer(c->cue_xfer);
812 
813 	DPRINTFN(10,("%s: %s: start rx\n", device_xname(sc->cue_dev),
814 		    __func__));
815 }
816 
817 /*
818  * A frame was downloaded to the chip. It's safe for us to clean up
819  * the list buffers.
820  */
821 Static void
822 cue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
823     usbd_status status)
824 {
825 	struct cue_chain	*c = priv;
826 	struct cue_softc	*sc = c->cue_sc;
827 	struct ifnet		*ifp = GET_IFP(sc);
828 	int			s;
829 
830 	if (sc->cue_dying)
831 		return;
832 
833 	s = splnet();
834 
835 	DPRINTFN(10,("%s: %s: enter status=%d\n", device_xname(sc->cue_dev),
836 		    __func__, status));
837 
838 	ifp->if_timer = 0;
839 	ifp->if_flags &= ~IFF_OACTIVE;
840 
841 	if (status != USBD_NORMAL_COMPLETION) {
842 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
843 			splx(s);
844 			return;
845 		}
846 		ifp->if_oerrors++;
847 		printf("%s: usb error on tx: %s\n", device_xname(sc->cue_dev),
848 		    usbd_errstr(status));
849 		if (status == USBD_STALLED)
850 			usbd_clear_endpoint_stall_async(sc->cue_ep[CUE_ENDPT_TX]);
851 		splx(s);
852 		return;
853 	}
854 
855 	ifp->if_opackets++;
856 
857 	m_freem(c->cue_mbuf);
858 	c->cue_mbuf = NULL;
859 
860 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
861 		cue_start(ifp);
862 
863 	splx(s);
864 }
865 
866 Static void
867 cue_tick(void *xsc)
868 {
869 	struct cue_softc	*sc = xsc;
870 
871 	if (sc == NULL)
872 		return;
873 
874 	if (sc->cue_dying)
875 		return;
876 
877 	DPRINTFN(2,("%s: %s: enter\n", device_xname(sc->cue_dev), __func__));
878 
879 	/* Perform statistics update in process context. */
880 	usb_add_task(sc->cue_udev, &sc->cue_tick_task, USB_TASKQ_DRIVER);
881 }
882 
883 Static void
884 cue_tick_task(void *xsc)
885 {
886 	struct cue_softc	*sc = xsc;
887 	struct ifnet		*ifp;
888 
889 	if (sc->cue_dying)
890 		return;
891 
892 	DPRINTFN(2,("%s: %s: enter\n", device_xname(sc->cue_dev), __func__));
893 
894 	ifp = GET_IFP(sc);
895 
896 	ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_SINGLECOLL);
897 	ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_MULTICOLL);
898 	ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_EXCESSCOLL);
899 
900 	if (cue_csr_read_2(sc, CUE_RX_FRAMEERR))
901 		ifp->if_ierrors++;
902 }
903 
904 Static int
905 cue_send(struct cue_softc *sc, struct mbuf *m, int idx)
906 {
907 	int			total_len;
908 	struct cue_chain	*c;
909 	usbd_status		err;
910 
911 	c = &sc->cue_cdata.cue_tx_chain[idx];
912 
913 	/*
914 	 * Copy the mbuf data into a contiguous buffer, leaving two
915 	 * bytes at the beginning to hold the frame length.
916 	 */
917 	m_copydata(m, 0, m->m_pkthdr.len, c->cue_buf + 2);
918 	c->cue_mbuf = m;
919 
920 	total_len = m->m_pkthdr.len + 2;
921 
922 	DPRINTFN(10,("%s: %s: total_len=%d\n",
923 		     device_xname(sc->cue_dev), __func__, total_len));
924 
925 	/* The first two bytes are the frame length */
926 	c->cue_buf[0] = (u_int8_t)m->m_pkthdr.len;
927 	c->cue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8);
928 
929 	/* XXX 10000 */
930 	usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_TX],
931 	    c, c->cue_buf, total_len, USBD_NO_COPY, 10000, cue_txeof);
932 
933 	/* Transmit */
934 	err = usbd_transfer(c->cue_xfer);
935 	if (err != USBD_IN_PROGRESS) {
936 		printf("%s: cue_send error=%s\n", device_xname(sc->cue_dev),
937 		       usbd_errstr(err));
938 		/* Stop the interface from process context. */
939 		usb_add_task(sc->cue_udev, &sc->cue_stop_task,
940 		    USB_TASKQ_DRIVER);
941 		return (EIO);
942 	}
943 
944 	sc->cue_cdata.cue_tx_cnt++;
945 
946 	return (0);
947 }
948 
949 Static void
950 cue_start(struct ifnet *ifp)
951 {
952 	struct cue_softc	*sc = ifp->if_softc;
953 	struct mbuf		*m_head = NULL;
954 
955 	if (sc->cue_dying)
956 		return;
957 
958 	DPRINTFN(10,("%s: %s: enter\n", device_xname(sc->cue_dev),__func__));
959 
960 	if (ifp->if_flags & IFF_OACTIVE)
961 		return;
962 
963 	IFQ_POLL(&ifp->if_snd, m_head);
964 	if (m_head == NULL)
965 		return;
966 
967 	if (cue_send(sc, m_head, 0)) {
968 		ifp->if_flags |= IFF_OACTIVE;
969 		return;
970 	}
971 
972 	IFQ_DEQUEUE(&ifp->if_snd, m_head);
973 
974 	/*
975 	 * If there's a BPF listener, bounce a copy of this frame
976 	 * to him.
977 	 */
978 	bpf_mtap(ifp, m_head);
979 
980 	ifp->if_flags |= IFF_OACTIVE;
981 
982 	/*
983 	 * Set a timeout in case the chip goes out to lunch.
984 	 */
985 	ifp->if_timer = 5;
986 }
987 
988 Static void
989 cue_init(void *xsc)
990 {
991 	struct cue_softc	*sc = xsc;
992 	struct ifnet		*ifp = GET_IFP(sc);
993 	int			i, s, ctl;
994 	const u_char		*eaddr;
995 
996 	if (sc->cue_dying)
997 		return;
998 
999 	DPRINTFN(10,("%s: %s: enter\n", device_xname(sc->cue_dev),__func__));
1000 
1001 	if (ifp->if_flags & IFF_RUNNING)
1002 		return;
1003 
1004 	s = splnet();
1005 
1006 	/*
1007 	 * Cancel pending I/O and free all RX/TX buffers.
1008 	 */
1009 #if 1
1010 	cue_reset(sc);
1011 #endif
1012 
1013 	/* Set advanced operation modes. */
1014 	cue_csr_write_1(sc, CUE_ADVANCED_OPMODES,
1015 	    CUE_AOP_EMBED_RXLEN | 0x03); /* 1 wait state */
1016 
1017 	eaddr = CLLADDR(ifp->if_sadl);
1018 	/* Set MAC address */
1019 	for (i = 0; i < ETHER_ADDR_LEN; i++)
1020 		cue_csr_write_1(sc, CUE_PAR0 - i, eaddr[i]);
1021 
1022 	/* Enable RX logic. */
1023 	ctl = CUE_ETHCTL_RX_ON | CUE_ETHCTL_MCAST_ON;
1024 	if (ifp->if_flags & IFF_PROMISC)
1025 		ctl |= CUE_ETHCTL_PROMISC;
1026 	cue_csr_write_1(sc, CUE_ETHCTL, ctl);
1027 
1028 	/* Init TX ring. */
1029 	if (cue_tx_list_init(sc) == ENOBUFS) {
1030 		printf("%s: tx list init failed\n", device_xname(sc->cue_dev));
1031 		splx(s);
1032 		return;
1033 	}
1034 
1035 	/* Init RX ring. */
1036 	if (cue_rx_list_init(sc) == ENOBUFS) {
1037 		printf("%s: rx list init failed\n", device_xname(sc->cue_dev));
1038 		splx(s);
1039 		return;
1040 	}
1041 
1042 	/* Load the multicast filter. */
1043 	cue_setmulti(sc);
1044 
1045 	/*
1046 	 * Set the number of RX and TX buffers that we want
1047 	 * to reserve inside the ASIC.
1048 	 */
1049 	cue_csr_write_1(sc, CUE_RX_BUFPKTS, CUE_RX_FRAMES);
1050 	cue_csr_write_1(sc, CUE_TX_BUFPKTS, CUE_TX_FRAMES);
1051 
1052 	/* Set advanced operation modes. */
1053 	cue_csr_write_1(sc, CUE_ADVANCED_OPMODES,
1054 	    CUE_AOP_EMBED_RXLEN | 0x01); /* 1 wait state */
1055 
1056 	/* Program the LED operation. */
1057 	cue_csr_write_1(sc, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK);
1058 
1059 	if (sc->cue_ep[CUE_ENDPT_RX] == NULL) {
1060 		if (cue_open_pipes(sc)) {
1061 			splx(s);
1062 			return;
1063 		}
1064 	}
1065 
1066 	ifp->if_flags |= IFF_RUNNING;
1067 	ifp->if_flags &= ~IFF_OACTIVE;
1068 
1069 	splx(s);
1070 
1071 	callout_reset(&(sc->cue_stat_ch), (hz), (cue_tick), (sc));
1072 }
1073 
1074 Static int
1075 cue_open_pipes(struct cue_softc	*sc)
1076 {
1077 	struct cue_chain	*c;
1078 	usbd_status		err;
1079 	int			i;
1080 
1081 	/* Open RX and TX pipes. */
1082 	err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_RX],
1083 	    USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_RX]);
1084 	if (err) {
1085 		printf("%s: open rx pipe failed: %s\n",
1086 		    device_xname(sc->cue_dev), usbd_errstr(err));
1087 		return (EIO);
1088 	}
1089 	err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_TX],
1090 	    USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_TX]);
1091 	if (err) {
1092 		printf("%s: open tx pipe failed: %s\n",
1093 		    device_xname(sc->cue_dev), usbd_errstr(err));
1094 		return (EIO);
1095 	}
1096 
1097 	/* Start up the receive pipe. */
1098 	for (i = 0; i < CUE_RX_LIST_CNT; i++) {
1099 		c = &sc->cue_cdata.cue_rx_chain[i];
1100 		usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_RX],
1101 		    c, c->cue_buf, CUE_BUFSZ,
1102 		    USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
1103 		    cue_rxeof);
1104 		usbd_transfer(c->cue_xfer);
1105 	}
1106 
1107 	return (0);
1108 }
1109 
1110 Static int
1111 cue_ioctl(struct ifnet *ifp, u_long command, void *data)
1112 {
1113 	struct cue_softc	*sc = ifp->if_softc;
1114 	struct ifaddr 		*ifa = (struct ifaddr *)data;
1115 	struct ifreq		*ifr = (struct ifreq *)data;
1116 	int			s, error = 0;
1117 
1118 	if (sc->cue_dying)
1119 		return (EIO);
1120 
1121 	s = splnet();
1122 
1123 	switch(command) {
1124 	case SIOCINITIFADDR:
1125 		ifp->if_flags |= IFF_UP;
1126 		cue_init(sc);
1127 
1128 		switch (ifa->ifa_addr->sa_family) {
1129 #ifdef INET
1130 		case AF_INET:
1131 			arp_ifinit(ifp, ifa);
1132 			break;
1133 #endif /* INET */
1134 		}
1135 		break;
1136 
1137 	case SIOCSIFMTU:
1138 		if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU)
1139 			error = EINVAL;
1140 		else if ((error = ifioctl_common(ifp, command, data)) == ENETRESET)
1141 			error = 0;
1142 		break;
1143 
1144 	case SIOCSIFFLAGS:
1145 		if ((error = ifioctl_common(ifp, command, data)) != 0)
1146 			break;
1147 		if (ifp->if_flags & IFF_UP) {
1148 			if (ifp->if_flags & IFF_RUNNING &&
1149 			    ifp->if_flags & IFF_PROMISC &&
1150 			    !(sc->cue_if_flags & IFF_PROMISC)) {
1151 				CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
1152 				cue_setmulti(sc);
1153 			} else if (ifp->if_flags & IFF_RUNNING &&
1154 			    !(ifp->if_flags & IFF_PROMISC) &&
1155 			    sc->cue_if_flags & IFF_PROMISC) {
1156 				CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
1157 				cue_setmulti(sc);
1158 			} else if (!(ifp->if_flags & IFF_RUNNING))
1159 				cue_init(sc);
1160 		} else {
1161 			if (ifp->if_flags & IFF_RUNNING)
1162 				cue_stop(sc);
1163 		}
1164 		sc->cue_if_flags = ifp->if_flags;
1165 		error = 0;
1166 		break;
1167 	case SIOCADDMULTI:
1168 	case SIOCDELMULTI:
1169 		cue_setmulti(sc);
1170 		error = 0;
1171 		break;
1172 	default:
1173 		error = ether_ioctl(ifp, command, data);
1174 		break;
1175 	}
1176 
1177 	splx(s);
1178 
1179 	return (error);
1180 }
1181 
1182 Static void
1183 cue_watchdog(struct ifnet *ifp)
1184 {
1185 	struct cue_softc	*sc = ifp->if_softc;
1186 	struct cue_chain	*c;
1187 	usbd_status		stat;
1188 	int			s;
1189 
1190 	DPRINTFN(5,("%s: %s: enter\n", device_xname(sc->cue_dev), __func__));
1191 
1192 	if (sc->cue_dying)
1193 		return;
1194 
1195 	ifp->if_oerrors++;
1196 	printf("%s: watchdog timeout\n", device_xname(sc->cue_dev));
1197 
1198 	s = splusb();
1199 	c = &sc->cue_cdata.cue_tx_chain[0];
1200 	usbd_get_xfer_status(c->cue_xfer, NULL, NULL, NULL, &stat);
1201 	cue_txeof(c->cue_xfer, c, stat);
1202 
1203 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1204 		cue_start(ifp);
1205 	splx(s);
1206 }
1207 
1208 /*
1209  * Stop the adapter and free any mbufs allocated to the
1210  * RX and TX lists.
1211  */
1212 Static void
1213 cue_stop(struct cue_softc *sc)
1214 {
1215 	usbd_status		err;
1216 	struct ifnet		*ifp;
1217 	int			i;
1218 
1219 	DPRINTFN(10,("%s: %s: enter\n", device_xname(sc->cue_dev),__func__));
1220 
1221 	ifp = GET_IFP(sc);
1222 	ifp->if_timer = 0;
1223 
1224 	cue_csr_write_1(sc, CUE_ETHCTL, 0);
1225 	cue_reset(sc);
1226 	callout_stop(&sc->cue_stat_ch);
1227 
1228 	/* Stop transfers. */
1229 	if (sc->cue_ep[CUE_ENDPT_RX] != NULL) {
1230 		err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_RX]);
1231 		if (err) {
1232 			printf("%s: abort rx pipe failed: %s\n",
1233 			    device_xname(sc->cue_dev), usbd_errstr(err));
1234 		}
1235 		err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_RX]);
1236 		if (err) {
1237 			printf("%s: close rx pipe failed: %s\n",
1238 			    device_xname(sc->cue_dev), usbd_errstr(err));
1239 		}
1240 		sc->cue_ep[CUE_ENDPT_RX] = NULL;
1241 	}
1242 
1243 	if (sc->cue_ep[CUE_ENDPT_TX] != NULL) {
1244 		err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_TX]);
1245 		if (err) {
1246 			printf("%s: abort tx pipe failed: %s\n",
1247 			    device_xname(sc->cue_dev), usbd_errstr(err));
1248 		}
1249 		err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_TX]);
1250 		if (err) {
1251 			printf("%s: close tx pipe failed: %s\n",
1252 			    device_xname(sc->cue_dev), usbd_errstr(err));
1253 		}
1254 		sc->cue_ep[CUE_ENDPT_TX] = NULL;
1255 	}
1256 
1257 	if (sc->cue_ep[CUE_ENDPT_INTR] != NULL) {
1258 		err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_INTR]);
1259 		if (err) {
1260 			printf("%s: abort intr pipe failed: %s\n",
1261 			    device_xname(sc->cue_dev), usbd_errstr(err));
1262 		}
1263 		err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_INTR]);
1264 		if (err) {
1265 			printf("%s: close intr pipe failed: %s\n",
1266 			    device_xname(sc->cue_dev), usbd_errstr(err));
1267 		}
1268 		sc->cue_ep[CUE_ENDPT_INTR] = NULL;
1269 	}
1270 
1271 	/* Free RX resources. */
1272 	for (i = 0; i < CUE_RX_LIST_CNT; i++) {
1273 		if (sc->cue_cdata.cue_rx_chain[i].cue_mbuf != NULL) {
1274 			m_freem(sc->cue_cdata.cue_rx_chain[i].cue_mbuf);
1275 			sc->cue_cdata.cue_rx_chain[i].cue_mbuf = NULL;
1276 		}
1277 		if (sc->cue_cdata.cue_rx_chain[i].cue_xfer != NULL) {
1278 			usbd_free_xfer(sc->cue_cdata.cue_rx_chain[i].cue_xfer);
1279 			sc->cue_cdata.cue_rx_chain[i].cue_xfer = NULL;
1280 		}
1281 	}
1282 
1283 	/* Free TX resources. */
1284 	for (i = 0; i < CUE_TX_LIST_CNT; i++) {
1285 		if (sc->cue_cdata.cue_tx_chain[i].cue_mbuf != NULL) {
1286 			m_freem(sc->cue_cdata.cue_tx_chain[i].cue_mbuf);
1287 			sc->cue_cdata.cue_tx_chain[i].cue_mbuf = NULL;
1288 		}
1289 		if (sc->cue_cdata.cue_tx_chain[i].cue_xfer != NULL) {
1290 			usbd_free_xfer(sc->cue_cdata.cue_tx_chain[i].cue_xfer);
1291 			sc->cue_cdata.cue_tx_chain[i].cue_xfer = NULL;
1292 		}
1293 	}
1294 
1295 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1296 }
1297