Annotation of sys/dev/usb/if_kue.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_kue.c,v 1.55 2007/06/14 10:11:15 mbalmer Exp $ */
2: /* $NetBSD: if_kue.c,v 1.50 2002/07/16 22:00:31 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_kue.c,v 1.14 2000/01/14 01:36:15 wpaul Exp $
35: */
36:
37: /*
38: * Kawasaki LSI KL5KUSB101B USB to ethernet adapter driver.
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 KLSI USB to ethernet adapter chip contains an USB serial interface,
47: * ethernet MAC and embedded microcontroller (called the QT Engine).
48: * The chip must have firmware loaded into it before it will operate.
49: * Packets are passed between the chip and host via bulk transfers.
50: * There is an interrupt endpoint mentioned in the software spec, however
51: * it's currently unused. This device is 10Mbps half-duplex only, hence
52: * there is no media selection logic. The MAC supports a 128 entry
53: * multicast filter, though the exact size of the filter can depend
54: * on the firmware. Curiously, while the software spec describes various
55: * ethernet statistics counters, my sample adapter and firmware combination
56: * claims not to support any statistics counters at all.
57: *
58: * Note that once we load the firmware in the device, we have to be
59: * careful not to load it again: if you restart your computer but
60: * leave the adapter attached to the USB controller, it may remain
61: * powered on and retain its firmware. In this case, we don't need
62: * to load the firmware a second time.
63: *
64: * Special thanks to Rob Furr for providing an ADS Technologies
65: * adapter for development and testing. No monkeys were harmed during
66: * the development of this driver.
67: */
68:
69: /*
70: * Ported to NetBSD and somewhat rewritten by Lennart Augustsson.
71: */
72:
73: #include "bpfilter.h"
74:
75: #include <sys/param.h>
76: #include <sys/systm.h>
77: #include <sys/sockio.h>
78: #include <sys/mbuf.h>
79: #include <sys/malloc.h>
80: #include <sys/kernel.h>
81: #include <sys/socket.h>
82: #include <sys/device.h>
83: #include <sys/proc.h>
84:
85: #include <net/if.h>
86: #include <net/if_dl.h>
87:
88: #if NBPFILTER > 0
89: #include <net/bpf.h>
90: #endif
91:
92: #ifdef INET
93: #include <netinet/in.h>
94: #include <netinet/in_systm.h>
95: #include <netinet/in_var.h>
96: #include <netinet/ip.h>
97: #include <netinet/if_ether.h>
98: #endif
99:
100: #include <dev/usb/usb.h>
101: #include <dev/usb/usbdi.h>
102: #include <dev/usb/usbdi_util.h>
103: #include <dev/usb/usbdevs.h>
104:
105: #include <dev/usb/if_kuereg.h>
106: #include <dev/usb/if_kuevar.h>
107:
108: #ifdef KUE_DEBUG
109: #define DPRINTF(x) do { if (kuedebug) printf x; } while (0)
110: #define DPRINTFN(n,x) do { if (kuedebug >= (n)) printf x; } while (0)
111: int kuedebug = 0;
112: #else
113: #define DPRINTF(x)
114: #define DPRINTFN(n,x)
115: #endif
116:
117: /*
118: * Various supported device vendors/products.
119: */
120: const struct usb_devno kue_devs[] = {
121: { USB_VENDOR_3COM, USB_PRODUCT_3COM_3C19250 },
122: { USB_VENDOR_3COM, USB_PRODUCT_3COM_3C460 },
123: { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_URE450 },
124: { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BT },
125: { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BTX },
126: { USB_VENDOR_AOX, USB_PRODUCT_AOX_USB101 },
127: { USB_VENDOR_ASANTE, USB_PRODUCT_ASANTE_EA },
128: { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC10T },
129: { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_DSB650C },
130: { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_ETHER_USB_T },
131: { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650C },
132: { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_E45 },
133: { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_XX1 },
134: { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_XX2 },
135: { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETT },
136: { USB_VENDOR_JATON, USB_PRODUCT_JATON_EDA },
137: { USB_VENDOR_KINGSTON, USB_PRODUCT_KINGSTON_XX1 },
138: { USB_VENDOR_KLSI, USB_PRODUCT_KLSI_DUH3E10BT },
139: { USB_VENDOR_KLSI, USB_PRODUCT_KLSI_DUH3E10BTN },
140: { USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10T },
141: { USB_VENDOR_MOBILITY, USB_PRODUCT_MOBILITY_EA },
142: { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101 },
143: { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101X },
144: { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET },
145: { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET2 },
146: { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET3 },
147: { USB_VENDOR_PORTGEAR, USB_PRODUCT_PORTGEAR_EA8 },
148: { USB_VENDOR_PORTGEAR, USB_PRODUCT_PORTGEAR_EA9 },
149: { USB_VENDOR_PORTSMITH, USB_PRODUCT_PORTSMITH_EEA },
150: { USB_VENDOR_SHARK, USB_PRODUCT_SHARK_PA },
151: { USB_VENDOR_SILICOM, USB_PRODUCT_SILICOM_U2E },
152: { USB_VENDOR_SILICOM, USB_PRODUCT_SILICOM_GPE },
153: { USB_VENDOR_SMC, USB_PRODUCT_SMC_2102USB },
154: };
155: #define kue_lookup(v, p) (usb_lookup(kue_devs, v, p))
156:
157: int kue_match(struct device *, void *, void *);
158: void kue_attach(struct device *, struct device *, void *);
159: int kue_detach(struct device *, int);
160: int kue_activate(struct device *, enum devact);
161:
162: struct cfdriver kue_cd = {
163: NULL, "kue", DV_IFNET
164: };
165:
166: const struct cfattach kue_ca = {
167: sizeof(struct kue_softc),
168: kue_match,
169: kue_attach,
170: kue_detach,
171: kue_activate,
172: };
173:
174: int kue_tx_list_init(struct kue_softc *);
175: int kue_rx_list_init(struct kue_softc *);
176: int kue_newbuf(struct kue_softc *, struct kue_chain *,struct mbuf *);
177: int kue_send(struct kue_softc *, struct mbuf *, int);
178: int kue_open_pipes(struct kue_softc *);
179: void kue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
180: void kue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
181: void kue_start(struct ifnet *);
182: int kue_ioctl(struct ifnet *, u_long, caddr_t);
183: void kue_init(void *);
184: void kue_stop(struct kue_softc *);
185: void kue_watchdog(struct ifnet *);
186:
187: void kue_setmulti(struct kue_softc *);
188: void kue_reset(struct kue_softc *);
189:
190: usbd_status kue_ctl(struct kue_softc *, int, u_int8_t,
191: u_int16_t, void *, u_int32_t);
192: usbd_status kue_setword(struct kue_softc *, u_int8_t, u_int16_t);
193: int kue_load_fw(struct kue_softc *);
194: void kue_attachhook(void *);
195:
196: usbd_status
197: kue_setword(struct kue_softc *sc, u_int8_t breq, u_int16_t word)
198: {
199: usb_device_request_t req;
200:
201: DPRINTFN(10,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
202:
203: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
204: req.bRequest = breq;
205: USETW(req.wValue, word);
206: USETW(req.wIndex, 0);
207: USETW(req.wLength, 0);
208:
209: return (usbd_do_request(sc->kue_udev, &req, NULL));
210: }
211:
212: usbd_status
213: kue_ctl(struct kue_softc *sc, int rw, u_int8_t breq, u_int16_t val,
214: void *data, u_int32_t len)
215: {
216: usb_device_request_t req;
217:
218: DPRINTFN(10,("%s: %s: enter, len=%d\n", sc->kue_dev.dv_xname,
219: __func__, len));
220:
221: if (rw == KUE_CTL_WRITE)
222: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
223: else
224: req.bmRequestType = UT_READ_VENDOR_DEVICE;
225:
226: req.bRequest = breq;
227: USETW(req.wValue, val);
228: USETW(req.wIndex, 0);
229: USETW(req.wLength, len);
230:
231: return (usbd_do_request(sc->kue_udev, &req, data));
232: }
233:
234: int
235: kue_load_fw(struct kue_softc *sc)
236: {
237: usb_device_descriptor_t dd;
238: usbd_status err;
239: struct kue_firmware *fw;
240: u_char *buf;
241: size_t buflen;
242:
243: DPRINTFN(1,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__));
244:
245: /*
246: * First, check if we even need to load the firmware.
247: * If the device was still attached when the system was
248: * rebooted, it may already have firmware loaded in it.
249: * If this is the case, we don't need to do it again.
250: * And in fact, if we try to load it again, we'll hang,
251: * so we have to avoid this condition if we don't want
252: * to look stupid.
253: *
254: * We can test this quickly by checking the bcdRevision
255: * code. The NIC will return a different revision code if
256: * it's probed while the firmware is still loaded and
257: * running.
258: */
259: if (usbd_get_device_desc(sc->kue_udev, &dd))
260: return (EIO);
261: if (UGETW(dd.bcdDevice) >= KUE_WARM_REV) {
262: printf("%s: warm boot, no firmware download\n",
263: sc->kue_dev.dv_xname);
264: return (0);
265: }
266:
267: err = loadfirmware("kue", &buf, &buflen);
268: if (err) {
269: printf("%s: failed loadfirmware of file %s: errno %d\n",
270: sc->kue_dev.dv_xname, "kue", err);
271: return (err);
272: }
273: fw = (struct kue_firmware *)buf;
274:
275: printf("%s: cold boot, downloading firmware\n",
276: sc->kue_dev.dv_xname);
277:
278: /* Load code segment */
279: DPRINTFN(1,("%s: kue_load_fw: download code_seg\n",
280: sc->kue_dev.dv_xname));
281: err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
282: 0, (void *)&fw->data[0], ntohl(fw->codeseglen));
283: if (err) {
284: printf("%s: failed to load code segment: %s\n",
285: sc->kue_dev.dv_xname, usbd_errstr(err));
286: free(buf, M_DEVBUF);
287: return (EIO);
288: }
289:
290: /* Load fixup segment */
291: DPRINTFN(1,("%s: kue_load_fw: download fix_seg\n",
292: sc->kue_dev.dv_xname));
293: err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
294: 0, (void *)&fw->data[ntohl(fw->codeseglen)], ntohl(fw->fixseglen));
295: if (err) {
296: printf("%s: failed to load fixup segment: %s\n",
297: sc->kue_dev.dv_xname, usbd_errstr(err));
298: free(buf, M_DEVBUF);
299: return (EIO);
300: }
301:
302: /* Send trigger command. */
303: DPRINTFN(1,("%s: kue_load_fw: download trig_seg\n",
304: sc->kue_dev.dv_xname));
305: err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
306: 0, (void *)&fw->data[ntohl(fw->codeseglen) + ntohl(fw->fixseglen)],
307: ntohl(fw->trigseglen));
308: if (err) {
309: printf("%s: failed to load trigger segment: %s\n",
310: sc->kue_dev.dv_xname, usbd_errstr(err));
311: free(buf, M_DEVBUF);
312: return (EIO);
313: }
314: free(buf, M_DEVBUF);
315:
316: usbd_delay_ms(sc->kue_udev, 10);
317:
318: /*
319: * Reload device descriptor.
320: * Why? The chip without the firmware loaded returns
321: * one revision code. The chip with the firmware
322: * loaded and running returns a *different* revision
323: * code. This confuses the quirk mechanism, which is
324: * dependent on the revision data.
325: */
326: (void)usbd_reload_device_desc(sc->kue_udev);
327:
328: DPRINTFN(1,("%s: %s: done\n", sc->kue_dev.dv_xname, __func__));
329:
330: /* Reset the adapter. */
331: kue_reset(sc);
332:
333: return (0);
334: }
335:
336: void
337: kue_setmulti(struct kue_softc *sc)
338: {
339: struct ifnet *ifp = GET_IFP(sc);
340: struct ether_multi *enm;
341: struct ether_multistep step;
342: int i;
343:
344: DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__));
345:
346: if (ifp->if_flags & IFF_PROMISC) {
347: allmulti:
348: ifp->if_flags |= IFF_ALLMULTI;
349: sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI;
350: sc->kue_rxfilt &= ~KUE_RXFILT_MULTICAST;
351: kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt);
352: return;
353: }
354:
355: sc->kue_rxfilt &= ~KUE_RXFILT_ALLMULTI;
356:
357: i = 0;
358: ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
359: while (enm != NULL) {
360: if (i == KUE_MCFILTCNT(sc) ||
361: memcmp(enm->enm_addrlo, enm->enm_addrhi,
362: ETHER_ADDR_LEN) != 0)
363: goto allmulti;
364:
365: memcpy(KUE_MCFILT(sc, i), enm->enm_addrlo, ETHER_ADDR_LEN);
366: ETHER_NEXT_MULTI(step, enm);
367: i++;
368: }
369:
370: ifp->if_flags &= ~IFF_ALLMULTI;
371:
372: sc->kue_rxfilt |= KUE_RXFILT_MULTICAST;
373: kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SET_MCAST_FILTERS,
374: i, sc->kue_mcfilters, i * ETHER_ADDR_LEN);
375:
376: kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt);
377: }
378:
379: /*
380: * Issue a SET_CONFIGURATION command to reset the MAC. This should be
381: * done after the firmware is loaded into the adapter in order to
382: * bring it into proper operation.
383: */
384: void
385: kue_reset(struct kue_softc *sc)
386: {
387: DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__));
388:
389: if (usbd_set_config_no(sc->kue_udev, KUE_CONFIG_NO, 1) ||
390: usbd_device2interface_handle(sc->kue_udev, KUE_IFACE_IDX,
391: &sc->kue_iface))
392: printf("%s: reset failed\n", sc->kue_dev.dv_xname);
393:
394: /* Wait a little while for the chip to get its brains in order. */
395: usbd_delay_ms(sc->kue_udev, 10);
396: }
397:
398: /*
399: * Probe for a KLSI chip.
400: */
401: int
402: kue_match(struct device *parent, void *match, void *aux)
403: {
404: struct usb_attach_arg *uaa = aux;
405:
406: DPRINTFN(25,("kue_match: enter\n"));
407:
408: if (uaa->iface != NULL)
409: return (UMATCH_NONE);
410:
411: return (kue_lookup(uaa->vendor, uaa->product) != NULL ?
412: UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
413: }
414:
415: void
416: kue_attachhook(void *xsc)
417: {
418: struct kue_softc *sc = xsc;
419: int s;
420: struct ifnet *ifp;
421: usbd_device_handle dev = sc->kue_udev;
422: usbd_interface_handle iface;
423: usbd_status err;
424: usb_interface_descriptor_t *id;
425: usb_endpoint_descriptor_t *ed;
426: int i;
427:
428: /* Load the firmware into the NIC. */
429: if (kue_load_fw(sc)) {
430: printf("%s: loading firmware failed\n",
431: sc->kue_dev.dv_xname);
432: return;
433: }
434:
435: err = usbd_device2interface_handle(dev, KUE_IFACE_IDX, &iface);
436: if (err) {
437: printf("%s: getting interface handle failed\n",
438: sc->kue_dev.dv_xname);
439: return;
440: }
441:
442: sc->kue_iface = iface;
443: id = usbd_get_interface_descriptor(iface);
444:
445: /* Find endpoints. */
446: for (i = 0; i < id->bNumEndpoints; i++) {
447: ed = usbd_interface2endpoint_descriptor(iface, i);
448: if (ed == NULL) {
449: printf("%s: couldn't get ep %d\n",
450: sc->kue_dev.dv_xname, i);
451: return;
452: }
453: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
454: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
455: sc->kue_ed[KUE_ENDPT_RX] = ed->bEndpointAddress;
456: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
457: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
458: sc->kue_ed[KUE_ENDPT_TX] = ed->bEndpointAddress;
459: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
460: UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
461: sc->kue_ed[KUE_ENDPT_INTR] = ed->bEndpointAddress;
462: }
463: }
464:
465: if (sc->kue_ed[KUE_ENDPT_RX] == 0 || sc->kue_ed[KUE_ENDPT_TX] == 0) {
466: printf("%s: missing endpoint\n", sc->kue_dev.dv_xname);
467: return;
468: }
469:
470: /* Read ethernet descriptor */
471: err = kue_ctl(sc, KUE_CTL_READ, KUE_CMD_GET_ETHER_DESCRIPTOR,
472: 0, &sc->kue_desc, sizeof(sc->kue_desc));
473: if (err) {
474: printf("%s: could not read Ethernet descriptor\n",
475: sc->kue_dev.dv_xname);
476: return;
477: }
478:
479: sc->kue_mcfilters = malloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN,
480: M_USBDEV, M_NOWAIT);
481: if (sc->kue_mcfilters == NULL) {
482: printf("%s: no memory for multicast filter buffer\n",
483: sc->kue_dev.dv_xname);
484: return;
485: }
486:
487: s = splnet();
488:
489: /*
490: * A KLSI chip was detected. Inform the world.
491: */
492: printf("%s: address %s\n", sc->kue_dev.dv_xname,
493: ether_sprintf(sc->kue_desc.kue_macaddr));
494:
495: bcopy(sc->kue_desc.kue_macaddr,
496: (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
497:
498: /* Initialize interface info.*/
499: ifp = GET_IFP(sc);
500: ifp->if_softc = sc;
501: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
502: ifp->if_ioctl = kue_ioctl;
503: ifp->if_start = kue_start;
504: ifp->if_watchdog = kue_watchdog;
505: strlcpy(ifp->if_xname, sc->kue_dev.dv_xname, IFNAMSIZ);
506:
507: IFQ_SET_READY(&ifp->if_snd);
508:
509: /* Attach the interface. */
510: if_attach(ifp);
511: ether_ifattach(ifp);
512:
513: sc->kue_attached = 1;
514: splx(s);
515:
516: }
517:
518: /*
519: * Attach the interface. Allocate softc structures, do
520: * setup and ethernet/BPF attach.
521: */
522: void
523: kue_attach(struct device *parent, struct device *self, void *aux)
524: {
525: struct kue_softc *sc = (struct kue_softc *)self;
526: struct usb_attach_arg *uaa = aux;
527: char *devinfop;
528: usbd_device_handle dev = uaa->device;
529: usbd_status err;
530:
531: DPRINTFN(5,(" : kue_attach: sc=%p, dev=%p", sc, dev));
532:
533: devinfop = usbd_devinfo_alloc(dev, 0);
534: printf("\n%s: %s\n", sc->kue_dev.dv_xname, devinfop);
535: usbd_devinfo_free(devinfop);
536:
537: err = usbd_set_config_no(dev, KUE_CONFIG_NO, 1);
538: if (err) {
539: printf("%s: setting config no failed\n",
540: sc->kue_dev.dv_xname);
541: return;
542: }
543:
544: sc->kue_udev = dev;
545: sc->kue_product = uaa->product;
546: sc->kue_vendor = uaa->vendor;
547:
548: if (rootvp == NULL)
549: mountroothook_establish(kue_attachhook, sc);
550: else
551: kue_attachhook(sc);
552:
553: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->kue_udev,
554: &sc->kue_dev);
555: }
556:
557: int
558: kue_detach(struct device *self, int flags)
559: {
560: struct kue_softc *sc = (struct kue_softc *)self;
561: struct ifnet *ifp = GET_IFP(sc);
562: int s;
563:
564: s = splusb(); /* XXX why? */
565:
566: if (sc->kue_mcfilters != NULL) {
567: free(sc->kue_mcfilters, M_USBDEV);
568: sc->kue_mcfilters = NULL;
569: }
570:
571: if (!sc->kue_attached) {
572: /* Detached before attached finished, so just bail out. */
573: splx(s);
574: return (0);
575: }
576:
577: if (ifp->if_flags & IFF_RUNNING)
578: kue_stop(sc);
579:
580: ether_ifdetach(ifp);
581:
582: if_detach(ifp);
583:
584: #ifdef DIAGNOSTIC
585: if (sc->kue_ep[KUE_ENDPT_TX] != NULL ||
586: sc->kue_ep[KUE_ENDPT_RX] != NULL ||
587: sc->kue_ep[KUE_ENDPT_INTR] != NULL)
588: printf("%s: detach has active endpoints\n",
589: sc->kue_dev.dv_xname);
590: #endif
591:
592: sc->kue_attached = 0;
593: splx(s);
594:
595: return (0);
596: }
597:
598: int
599: kue_activate(struct device *self, enum devact act)
600: {
601: struct kue_softc *sc = (struct kue_softc *)self;
602:
603: DPRINTFN(2,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__));
604:
605: switch (act) {
606: case DVACT_ACTIVATE:
607: break;
608:
609: case DVACT_DEACTIVATE:
610: sc->kue_dying = 1;
611: break;
612: }
613: return (0);
614: }
615:
616: /*
617: * Initialize an RX descriptor and attach an MBUF cluster.
618: */
619: int
620: kue_newbuf(struct kue_softc *sc, struct kue_chain *c, struct mbuf *m)
621: {
622: struct mbuf *m_new = NULL;
623:
624: DPRINTFN(10,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
625:
626: if (m == NULL) {
627: MGETHDR(m_new, M_DONTWAIT, MT_DATA);
628: if (m_new == NULL) {
629: printf("%s: no memory for rx list "
630: "-- packet dropped!\n", sc->kue_dev.dv_xname);
631: return (ENOBUFS);
632: }
633:
634: MCLGET(m_new, M_DONTWAIT);
635: if (!(m_new->m_flags & M_EXT)) {
636: printf("%s: no memory for rx list "
637: "-- packet dropped!\n", sc->kue_dev.dv_xname);
638: m_freem(m_new);
639: return (ENOBUFS);
640: }
641: m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
642: } else {
643: m_new = m;
644: m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
645: m_new->m_data = m_new->m_ext.ext_buf;
646: }
647:
648: c->kue_mbuf = m_new;
649:
650: return (0);
651: }
652:
653: int
654: kue_rx_list_init(struct kue_softc *sc)
655: {
656: struct kue_cdata *cd;
657: struct kue_chain *c;
658: int i;
659:
660: DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__));
661:
662: cd = &sc->kue_cdata;
663: for (i = 0; i < KUE_RX_LIST_CNT; i++) {
664: c = &cd->kue_rx_chain[i];
665: c->kue_sc = sc;
666: c->kue_idx = i;
667: if (kue_newbuf(sc, c, NULL) == ENOBUFS)
668: return (ENOBUFS);
669: if (c->kue_xfer == NULL) {
670: c->kue_xfer = usbd_alloc_xfer(sc->kue_udev);
671: if (c->kue_xfer == NULL)
672: return (ENOBUFS);
673: c->kue_buf = usbd_alloc_buffer(c->kue_xfer, KUE_BUFSZ);
674: if (c->kue_buf == NULL)
675: return (ENOBUFS); /* XXX free xfer */
676: }
677: }
678:
679: return (0);
680: }
681:
682: int
683: kue_tx_list_init(struct kue_softc *sc)
684: {
685: struct kue_cdata *cd;
686: struct kue_chain *c;
687: int i;
688:
689: DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__));
690:
691: cd = &sc->kue_cdata;
692: for (i = 0; i < KUE_TX_LIST_CNT; i++) {
693: c = &cd->kue_tx_chain[i];
694: c->kue_sc = sc;
695: c->kue_idx = i;
696: c->kue_mbuf = NULL;
697: if (c->kue_xfer == NULL) {
698: c->kue_xfer = usbd_alloc_xfer(sc->kue_udev);
699: if (c->kue_xfer == NULL)
700: return (ENOBUFS);
701: c->kue_buf = usbd_alloc_buffer(c->kue_xfer, KUE_BUFSZ);
702: if (c->kue_buf == NULL)
703: return (ENOBUFS);
704: }
705: }
706:
707: return (0);
708: }
709:
710: /*
711: * A frame has been uploaded: pass the resulting mbuf chain up to
712: * the higher level protocols.
713: */
714: void
715: kue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
716: {
717: struct kue_chain *c = priv;
718: struct kue_softc *sc = c->kue_sc;
719: struct ifnet *ifp = GET_IFP(sc);
720: struct mbuf *m;
721: int total_len = 0;
722: int s;
723:
724: DPRINTFN(10,("%s: %s: enter status=%d\n", sc->kue_dev.dv_xname,
725: __func__, status));
726:
727: if (sc->kue_dying)
728: return;
729:
730: if (!(ifp->if_flags & IFF_RUNNING))
731: return;
732:
733: if (status != USBD_NORMAL_COMPLETION) {
734: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
735: return;
736: sc->kue_rx_errs++;
737: if (usbd_ratecheck(&sc->kue_rx_notice)) {
738: printf("%s: %u usb errors on rx: %s\n",
739: sc->kue_dev.dv_xname, sc->kue_rx_errs,
740: usbd_errstr(status));
741: sc->kue_rx_errs = 0;
742: }
743: if (status == USBD_STALLED)
744: usbd_clear_endpoint_stall_async(sc->kue_ep[KUE_ENDPT_RX]);
745: goto done;
746: }
747:
748: usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
749:
750: DPRINTFN(10,("%s: %s: total_len=%d len=%d\n", sc->kue_dev.dv_xname,
751: __func__, total_len,
752: UGETW(mtod(c->kue_mbuf, u_int8_t *))));
753:
754: if (total_len <= 1)
755: goto done;
756:
757: m = c->kue_mbuf;
758: /* copy data to mbuf */
759: memcpy(mtod(m, char *), c->kue_buf, total_len);
760:
761: /* No errors; receive the packet. */
762: total_len = UGETW(mtod(m, u_int8_t *));
763: m_adj(m, sizeof(u_int16_t));
764:
765: if (total_len < sizeof(struct ether_header)) {
766: ifp->if_ierrors++;
767: goto done;
768: }
769:
770: ifp->if_ipackets++;
771: m->m_pkthdr.len = m->m_len = total_len;
772:
773: m->m_pkthdr.rcvif = ifp;
774:
775: s = splnet();
776:
777: /* XXX ugly */
778: if (kue_newbuf(sc, c, NULL) == ENOBUFS) {
779: ifp->if_ierrors++;
780: goto done1;
781: }
782:
783: #if NBPFILTER > 0
784: /*
785: * Handle BPF listeners. Let the BPF user see the packet, but
786: * don't pass it up to the ether_input() layer unless it's
787: * a broadcast packet, multicast packet, matches our ethernet
788: * address or the interface is in promiscuous mode.
789: */
790: if (ifp->if_bpf)
791: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
792: #endif
793:
794: DPRINTFN(10,("%s: %s: deliver %d\n", sc->kue_dev.dv_xname,
795: __func__, m->m_len));
796: ether_input_mbuf(ifp, m);
797: done1:
798: splx(s);
799:
800: done:
801:
802: /* Setup new transfer. */
803: usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX],
804: c, c->kue_buf, KUE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
805: USBD_NO_TIMEOUT, kue_rxeof);
806: usbd_transfer(c->kue_xfer);
807:
808: DPRINTFN(10,("%s: %s: start rx\n", sc->kue_dev.dv_xname,
809: __func__));
810: }
811:
812: /*
813: * A frame was downloaded to the chip. It's safe for us to clean up
814: * the list buffers.
815: */
816:
817: void
818: kue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
819: {
820: struct kue_chain *c = priv;
821: struct kue_softc *sc = c->kue_sc;
822: struct ifnet *ifp = GET_IFP(sc);
823: int s;
824:
825: if (sc->kue_dying)
826: return;
827:
828: s = splnet();
829:
830: DPRINTFN(10,("%s: %s: enter status=%d\n", sc->kue_dev.dv_xname,
831: __func__, status));
832:
833: ifp->if_timer = 0;
834: ifp->if_flags &= ~IFF_OACTIVE;
835:
836: if (status != USBD_NORMAL_COMPLETION) {
837: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
838: splx(s);
839: return;
840: }
841: ifp->if_oerrors++;
842: printf("%s: usb error on tx: %s\n", sc->kue_dev.dv_xname,
843: usbd_errstr(status));
844: if (status == USBD_STALLED)
845: usbd_clear_endpoint_stall_async(sc->kue_ep[KUE_ENDPT_TX]);
846: splx(s);
847: return;
848: }
849:
850: ifp->if_opackets++;
851:
852: m_freem(c->kue_mbuf);
853: c->kue_mbuf = NULL;
854:
855: if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
856: kue_start(ifp);
857:
858: splx(s);
859: }
860:
861: int
862: kue_send(struct kue_softc *sc, struct mbuf *m, int idx)
863: {
864: int total_len;
865: struct kue_chain *c;
866: usbd_status err;
867:
868: DPRINTFN(10,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
869:
870: c = &sc->kue_cdata.kue_tx_chain[idx];
871:
872: /*
873: * Copy the mbuf data into a contiguous buffer, leaving two
874: * bytes at the beginning to hold the frame length.
875: */
876: m_copydata(m, 0, m->m_pkthdr.len, c->kue_buf + 2);
877: c->kue_mbuf = m;
878:
879: total_len = m->m_pkthdr.len + 2;
880: /* XXX what's this? */
881: total_len += 64 - (total_len % 64);
882:
883: /* Frame length is specified in the first 2 bytes of the buffer. */
884: c->kue_buf[0] = (u_int8_t)m->m_pkthdr.len;
885: c->kue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8);
886:
887: usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_TX],
888: c, c->kue_buf, total_len, USBD_NO_COPY, USBD_DEFAULT_TIMEOUT,
889: kue_txeof);
890:
891: /* Transmit */
892: err = usbd_transfer(c->kue_xfer);
893: if (err != USBD_IN_PROGRESS) {
894: printf("%s: kue_send error=%s\n", sc->kue_dev.dv_xname,
895: usbd_errstr(err));
896: kue_stop(sc);
897: return (EIO);
898: }
899:
900: sc->kue_cdata.kue_tx_cnt++;
901:
902: return (0);
903: }
904:
905: void
906: kue_start(struct ifnet *ifp)
907: {
908: struct kue_softc *sc = ifp->if_softc;
909: struct mbuf *m_head = NULL;
910:
911: DPRINTFN(10,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
912:
913: if (sc->kue_dying)
914: return;
915:
916: if (ifp->if_flags & IFF_OACTIVE)
917: return;
918:
919: IFQ_POLL(&ifp->if_snd, m_head);
920: if (m_head == NULL)
921: return;
922:
923: if (kue_send(sc, m_head, 0)) {
924: ifp->if_flags |= IFF_OACTIVE;
925: return;
926: }
927:
928: IFQ_DEQUEUE(&ifp->if_snd, m_head);
929:
930: #if NBPFILTER > 0
931: /*
932: * If there's a BPF listener, bounce a copy of this frame
933: * to him.
934: */
935: if (ifp->if_bpf)
936: bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
937: #endif
938:
939: ifp->if_flags |= IFF_OACTIVE;
940:
941: /*
942: * Set a timeout in case the chip goes out to lunch.
943: */
944: ifp->if_timer = 6;
945: }
946:
947: void
948: kue_init(void *xsc)
949: {
950: struct kue_softc *sc = xsc;
951: struct ifnet *ifp = GET_IFP(sc);
952: int s;
953: u_char *eaddr;
954:
955: DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
956:
957: if (ifp->if_flags & IFF_RUNNING)
958: return;
959:
960: s = splnet();
961:
962: eaddr = sc->arpcom.ac_enaddr;
963: /* Set MAC address */
964: kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SET_MAC, 0, eaddr, ETHER_ADDR_LEN);
965:
966: sc->kue_rxfilt = KUE_RXFILT_UNICAST | KUE_RXFILT_BROADCAST;
967:
968: /* If we want promiscuous mode, set the allframes bit. */
969: if (ifp->if_flags & IFF_PROMISC)
970: sc->kue_rxfilt |= KUE_RXFILT_PROMISC;
971:
972: kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt);
973:
974: /* I'm not sure how to tune these. */
975: #if 0
976: /*
977: * Leave this one alone for now; setting it
978: * wrong causes lockups on some machines/controllers.
979: */
980: kue_setword(sc, KUE_CMD_SET_SOFS, 1);
981: #endif
982: kue_setword(sc, KUE_CMD_SET_URB_SIZE, 64);
983:
984: /* Init TX ring. */
985: if (kue_tx_list_init(sc) == ENOBUFS) {
986: printf("%s: tx list init failed\n", sc->kue_dev.dv_xname);
987: splx(s);
988: return;
989: }
990:
991: /* Init RX ring. */
992: if (kue_rx_list_init(sc) == ENOBUFS) {
993: printf("%s: rx list init failed\n", sc->kue_dev.dv_xname);
994: splx(s);
995: return;
996: }
997:
998: /* Load the multicast filter. */
999: kue_setmulti(sc);
1000:
1001: if (sc->kue_ep[KUE_ENDPT_RX] == NULL) {
1002: if (kue_open_pipes(sc)) {
1003: splx(s);
1004: return;
1005: }
1006: }
1007:
1008: ifp->if_flags |= IFF_RUNNING;
1009: ifp->if_flags &= ~IFF_OACTIVE;
1010:
1011: splx(s);
1012: }
1013:
1014: int
1015: kue_open_pipes(struct kue_softc *sc)
1016: {
1017: usbd_status err;
1018: struct kue_chain *c;
1019: int i;
1020:
1021: DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
1022:
1023: /* Open RX and TX pipes. */
1024: err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_RX],
1025: USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_RX]);
1026: if (err) {
1027: printf("%s: open rx pipe failed: %s\n",
1028: sc->kue_dev.dv_xname, usbd_errstr(err));
1029: return (EIO);
1030: }
1031:
1032: err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_TX],
1033: USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_TX]);
1034: if (err) {
1035: printf("%s: open tx pipe failed: %s\n",
1036: sc->kue_dev.dv_xname, usbd_errstr(err));
1037: return (EIO);
1038: }
1039:
1040: /* Start up the receive pipe. */
1041: for (i = 0; i < KUE_RX_LIST_CNT; i++) {
1042: c = &sc->kue_cdata.kue_rx_chain[i];
1043: usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX],
1044: c, c->kue_buf, KUE_BUFSZ,
1045: USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
1046: kue_rxeof);
1047: DPRINTFN(5,("%s: %s: start read\n", sc->kue_dev.dv_xname,
1048: __func__));
1049: usbd_transfer(c->kue_xfer);
1050: }
1051:
1052: return (0);
1053: }
1054:
1055: int
1056: kue_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1057: {
1058: struct kue_softc *sc = ifp->if_softc;
1059: struct ifaddr *ifa = (struct ifaddr *)data;
1060: struct ifreq *ifr = (struct ifreq *)data;
1061: int s, error = 0;
1062:
1063: DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
1064:
1065: if (sc->kue_dying)
1066: return (EIO);
1067:
1068: #ifdef DIAGNOSTIC
1069: if (!curproc) {
1070: printf("%s: no proc!!\n", sc->kue_dev.dv_xname);
1071: return EIO;
1072: }
1073: #endif
1074:
1075: s = splnet();
1076:
1077: switch(command) {
1078: case SIOCSIFADDR:
1079: ifp->if_flags |= IFF_UP;
1080: kue_init(sc);
1081:
1082: switch (ifa->ifa_addr->sa_family) {
1083: #ifdef INET
1084: case AF_INET:
1085: arp_ifinit(&sc->arpcom, ifa);
1086: break;
1087: #endif /* INET */
1088: }
1089: break;
1090:
1091: case SIOCSIFMTU:
1092: if (ifr->ifr_mtu > ETHERMTU)
1093: error = EINVAL;
1094: else
1095: ifp->if_mtu = ifr->ifr_mtu;
1096: break;
1097:
1098: case SIOCSIFFLAGS:
1099: if (ifp->if_flags & IFF_UP) {
1100: if (ifp->if_flags & IFF_RUNNING &&
1101: ifp->if_flags & IFF_PROMISC &&
1102: !(sc->kue_if_flags & IFF_PROMISC)) {
1103: sc->kue_rxfilt |= KUE_RXFILT_PROMISC;
1104: kue_setword(sc, KUE_CMD_SET_PKT_FILTER,
1105: sc->kue_rxfilt);
1106: } else if (ifp->if_flags & IFF_RUNNING &&
1107: !(ifp->if_flags & IFF_PROMISC) &&
1108: sc->kue_if_flags & IFF_PROMISC) {
1109: sc->kue_rxfilt &= ~KUE_RXFILT_PROMISC;
1110: kue_setword(sc, KUE_CMD_SET_PKT_FILTER,
1111: sc->kue_rxfilt);
1112: } else if (!(ifp->if_flags & IFF_RUNNING))
1113: kue_init(sc);
1114: } else {
1115: if (ifp->if_flags & IFF_RUNNING)
1116: kue_stop(sc);
1117: }
1118: sc->kue_if_flags = ifp->if_flags;
1119: error = 0;
1120: break;
1121: case SIOCADDMULTI:
1122: case SIOCDELMULTI:
1123: error = (command == SIOCADDMULTI) ?
1124: ether_addmulti(ifr, &sc->arpcom) :
1125: ether_delmulti(ifr, &sc->arpcom);
1126:
1127: if (error == ENETRESET) {
1128: /*
1129: * Multicast list has changed; set the hardware
1130: * filter accordingly.
1131: */
1132: if (ifp->if_flags & IFF_RUNNING)
1133: kue_setmulti(sc);
1134: error = 0;
1135: }
1136: break;
1137: default:
1138: error = EINVAL;
1139: break;
1140: }
1141:
1142: splx(s);
1143:
1144: return (error);
1145: }
1146:
1147: void
1148: kue_watchdog(struct ifnet *ifp)
1149: {
1150: struct kue_softc *sc = ifp->if_softc;
1151: struct kue_chain *c;
1152: usbd_status stat;
1153: int s;
1154:
1155: DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
1156:
1157: if (sc->kue_dying)
1158: return;
1159:
1160: ifp->if_oerrors++;
1161: printf("%s: watchdog timeout\n", sc->kue_dev.dv_xname);
1162:
1163: s = splusb();
1164: c = &sc->kue_cdata.kue_tx_chain[0];
1165: usbd_get_xfer_status(c->kue_xfer, NULL, NULL, NULL, &stat);
1166: kue_txeof(c->kue_xfer, c, stat);
1167:
1168: if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1169: kue_start(ifp);
1170: splx(s);
1171: }
1172:
1173: /*
1174: * Stop the adapter and free any mbufs allocated to the
1175: * RX and TX lists.
1176: */
1177: void
1178: kue_stop(struct kue_softc *sc)
1179: {
1180: usbd_status err;
1181: struct ifnet *ifp;
1182: int i;
1183:
1184: DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
1185:
1186: ifp = GET_IFP(sc);
1187: ifp->if_timer = 0;
1188: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1189:
1190: /* Stop transfers. */
1191: if (sc->kue_ep[KUE_ENDPT_RX] != NULL) {
1192: err = usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_RX]);
1193: if (err) {
1194: printf("%s: abort rx pipe failed: %s\n",
1195: sc->kue_dev.dv_xname, usbd_errstr(err));
1196: }
1197: err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_RX]);
1198: if (err) {
1199: printf("%s: close rx pipe failed: %s\n",
1200: sc->kue_dev.dv_xname, usbd_errstr(err));
1201: }
1202: sc->kue_ep[KUE_ENDPT_RX] = NULL;
1203: }
1204:
1205: if (sc->kue_ep[KUE_ENDPT_TX] != NULL) {
1206: err = usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_TX]);
1207: if (err) {
1208: printf("%s: abort tx pipe failed: %s\n",
1209: sc->kue_dev.dv_xname, usbd_errstr(err));
1210: }
1211: err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_TX]);
1212: if (err) {
1213: printf("%s: close tx pipe failed: %s\n",
1214: sc->kue_dev.dv_xname, usbd_errstr(err));
1215: }
1216: sc->kue_ep[KUE_ENDPT_TX] = NULL;
1217: }
1218:
1219: if (sc->kue_ep[KUE_ENDPT_INTR] != NULL) {
1220: err = usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_INTR]);
1221: if (err) {
1222: printf("%s: abort intr pipe failed: %s\n",
1223: sc->kue_dev.dv_xname, usbd_errstr(err));
1224: }
1225: err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_INTR]);
1226: if (err) {
1227: printf("%s: close intr pipe failed: %s\n",
1228: sc->kue_dev.dv_xname, usbd_errstr(err));
1229: }
1230: sc->kue_ep[KUE_ENDPT_INTR] = NULL;
1231: }
1232:
1233: /* Free RX resources. */
1234: for (i = 0; i < KUE_RX_LIST_CNT; i++) {
1235: if (sc->kue_cdata.kue_rx_chain[i].kue_mbuf != NULL) {
1236: m_freem(sc->kue_cdata.kue_rx_chain[i].kue_mbuf);
1237: sc->kue_cdata.kue_rx_chain[i].kue_mbuf = NULL;
1238: }
1239: if (sc->kue_cdata.kue_rx_chain[i].kue_xfer != NULL) {
1240: usbd_free_xfer(sc->kue_cdata.kue_rx_chain[i].kue_xfer);
1241: sc->kue_cdata.kue_rx_chain[i].kue_xfer = NULL;
1242: }
1243: }
1244:
1245: /* Free TX resources. */
1246: for (i = 0; i < KUE_TX_LIST_CNT; i++) {
1247: if (sc->kue_cdata.kue_tx_chain[i].kue_mbuf != NULL) {
1248: m_freem(sc->kue_cdata.kue_tx_chain[i].kue_mbuf);
1249: sc->kue_cdata.kue_tx_chain[i].kue_mbuf = NULL;
1250: }
1251: if (sc->kue_cdata.kue_tx_chain[i].kue_xfer != NULL) {
1252: usbd_free_xfer(sc->kue_cdata.kue_tx_chain[i].kue_xfer);
1253: sc->kue_cdata.kue_tx_chain[i].kue_xfer = NULL;
1254: }
1255: }
1256: }
CVSweb