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