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