Annotation of src/sys/dev/usb/if_upl.c, Revision 1.20
1.20 ! itojun 1: /* $NetBSD: if_upl.c,v 1.19 2002/07/11 21:14:26 augustss Exp $ */
1.1 augustss 2: /*
3: * Copyright (c) 2000 The NetBSD Foundation, Inc.
4: * All rights reserved.
5: *
6: * This code is derived from software contributed to The NetBSD Foundation
1.3 augustss 7: * by Lennart Augustsson (lennart@augustsson.net) at
1.1 augustss 8: * Carlstedt Research & Technology.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
38:
39: /*
40: * Prolific PL2301/PL2302 driver
41: */
1.16 lukem 42:
43: #include <sys/cdefs.h>
1.20 ! itojun 44: __KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1.19 2002/07/11 21:14:26 augustss Exp $");
1.1 augustss 45:
46: #include "opt_inet.h"
47: #include "opt_ns.h"
48: #include "bpfilter.h"
49: #include "rnd.h"
50:
51: #include <sys/param.h>
52: #include <sys/systm.h>
53: #include <sys/callout.h>
54: #include <sys/sockio.h>
55: #include <sys/mbuf.h>
56: #include <sys/malloc.h>
57: #include <sys/kernel.h>
58: #include <sys/socket.h>
59:
60: #include <sys/device.h>
61: #if NRND > 0
62: #include <sys/rnd.h>
63: #endif
64:
65: #include <net/if.h>
66: #include <net/if_types.h>
67: #include <net/if_dl.h>
68: #include <net/netisr.h>
69:
70: #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
71:
72: #if NBPFILTER > 0
73: #include <net/bpf.h>
74: #endif
75:
76: #ifdef INET
1.19 augustss 77: #include <netinet/in.h>
78: #include <netinet/in_var.h>
1.1 augustss 79: #include <netinet/if_inarp.h>
1.8 itojun 80: #else
81: #error upl without INET?
1.1 augustss 82: #endif
83:
84: #ifdef NS
85: #include <netns/ns.h>
86: #include <netns/ns_if.h>
87: #endif
88:
89: #include <dev/usb/usb.h>
90: #include <dev/usb/usbdi.h>
91: #include <dev/usb/usbdi_util.h>
92: #include <dev/usb/usbdevs.h>
93:
94: /*
95: * 7 6 5 4 3 2 1 0
1.6 augustss 96: * tx rx 1 0
1.1 augustss 97: * 1110 0000 rxdata
98: * 1010 0000 idle
99: * 0010 0000 tx over
100: * 0110 tx over + rxd
101: */
102:
103: #define UPL_RXDATA 0x40
104: #define UPL_TXOK 0x80
105:
106: #define UPL_INTR_PKTLEN 1
107:
108: #define UPL_CONFIG_NO 1
109: #define UPL_IFACE_IDX 0
110:
111: /***/
112:
113: #define UPL_INTR_INTERVAL 20
114:
115: #define UPL_BUFSZ 1024
116:
117: #define UPL_RX_FRAMES 1
118: #define UPL_TX_FRAMES 1
119:
120: #define UPL_RX_LIST_CNT 1
121: #define UPL_TX_LIST_CNT 1
122:
123: #define UPL_ENDPT_RX 0x0
124: #define UPL_ENDPT_TX 0x1
125: #define UPL_ENDPT_INTR 0x2
126: #define UPL_ENDPT_MAX 0x3
127:
128: struct upl_type {
129: u_int16_t upl_vid;
130: u_int16_t upl_did;
131: };
132:
133: struct upl_softc;
134:
135: struct upl_chain {
136: struct upl_softc *upl_sc;
137: usbd_xfer_handle upl_xfer;
138: char *upl_buf;
139: struct mbuf *upl_mbuf;
140: int upl_idx;
141: };
142:
143: struct upl_cdata {
144: struct upl_chain upl_tx_chain[UPL_TX_LIST_CNT];
145: struct upl_chain upl_rx_chain[UPL_RX_LIST_CNT];
146: int upl_tx_prod;
147: int upl_tx_cons;
148: int upl_tx_cnt;
149: int upl_rx_prod;
150: };
151:
152: struct upl_softc {
153: USBBASEDEVICE sc_dev;
154:
155: struct ifnet sc_if;
156: #if NRND > 0
157: rndsource_element_t sc_rnd_source;
158: #endif
159:
160: usb_callout_t sc_stat_ch;
161:
162: usbd_device_handle sc_udev;
163: usbd_interface_handle sc_iface;
164: u_int16_t sc_vendor;
165: u_int16_t sc_product;
166: int sc_ed[UPL_ENDPT_MAX];
167: usbd_pipe_handle sc_ep[UPL_ENDPT_MAX];
168: struct upl_cdata sc_cdata;
169:
170: uByte sc_ibuf;
171:
172: char sc_dying;
173: char sc_attached;
174: u_int sc_rx_errs;
175: struct timeval sc_rx_notice;
176: u_int sc_intr_errs;
177: };
178:
179: #ifdef UPL_DEBUG
180: #define DPRINTF(x) if (upldebug) logprintf x
181: #define DPRINTFN(n,x) if (upldebug >= (n)) logprintf x
182: int upldebug = 0;
183: #else
184: #define DPRINTF(x)
185: #define DPRINTFN(n,x)
186: #endif
187:
188: /*
189: * Various supported device vendors/products.
190: */
191: Static struct upl_type sc_devs[] = {
192: { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301 },
193: { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302 },
194: { 0, 0 }
195: };
196:
197: USB_DECLARE_DRIVER(upl);
198:
1.4 augustss 199: Static int upl_openpipes(struct upl_softc *);
200: Static int upl_tx_list_init(struct upl_softc *);
201: Static int upl_rx_list_init(struct upl_softc *);
202: Static int upl_newbuf(struct upl_softc *, struct upl_chain *, struct mbuf *);
203: Static int upl_send(struct upl_softc *, struct mbuf *, int);
204: Static void upl_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
205: Static void upl_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
206: Static void upl_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
207: Static void upl_start(struct ifnet *);
208: Static int upl_ioctl(struct ifnet *, u_long, caddr_t);
209: Static void upl_init(void *);
210: Static void upl_stop(struct upl_softc *);
211: Static void upl_watchdog(struct ifnet *);
212:
213: Static int upl_output(struct ifnet *, struct mbuf *, struct sockaddr *,
214: struct rtentry *);
215: Static void upl_input(struct ifnet *, struct mbuf *);
1.1 augustss 216:
217: /*
218: * Probe for a Prolific chip.
219: */
220: USB_MATCH(upl)
221: {
222: USB_MATCH_START(upl, uaa);
223: struct upl_type *t;
224:
225: if (uaa->iface != NULL)
226: return (UMATCH_NONE);
227:
228: for (t = sc_devs; t->upl_vid != 0; t++)
229: if (uaa->vendor == t->upl_vid && uaa->product == t->upl_did)
230: return (UMATCH_VENDOR_PRODUCT);
231:
232: return (UMATCH_NONE);
233: }
234:
235: USB_ATTACH(upl)
236: {
237: USB_ATTACH_START(upl, sc, uaa);
238: char devinfo[1024];
239: int s;
240: usbd_device_handle dev = uaa->device;
241: usbd_interface_handle iface;
242: usbd_status err;
243: struct ifnet *ifp;
244: usb_interface_descriptor_t *id;
245: usb_endpoint_descriptor_t *ed;
246: int i;
247:
248: DPRINTFN(5,(" : upl_attach: sc=%p, dev=%p", sc, dev));
249:
1.20 ! itojun 250: usbd_devinfo(dev, 0, devinfo, sizeof(devinfo));
1.1 augustss 251: USB_ATTACH_SETUP;
252: printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
253:
1.9 augustss 254: err = usbd_set_config_no(dev, UPL_CONFIG_NO, 1);
1.1 augustss 255: if (err) {
256: printf("%s: setting config no failed\n",
257: USBDEVNAME(sc->sc_dev));
258: USB_ATTACH_ERROR_RETURN;
259: }
260:
261: sc->sc_udev = dev;
262: sc->sc_product = uaa->product;
263: sc->sc_vendor = uaa->vendor;
264:
265: err = usbd_device2interface_handle(dev, UPL_IFACE_IDX, &iface);
266: if (err) {
267: printf("%s: getting interface handle failed\n",
268: USBDEVNAME(sc->sc_dev));
269: USB_ATTACH_ERROR_RETURN;
270: }
271:
272: sc->sc_iface = iface;
273: id = usbd_get_interface_descriptor(iface);
274:
275: /* Find endpoints. */
276: for (i = 0; i < id->bNumEndpoints; i++) {
277: ed = usbd_interface2endpoint_descriptor(iface, i);
278: if (ed == NULL) {
279: printf("%s: couldn't get ep %d\n",
280: USBDEVNAME(sc->sc_dev), i);
281: USB_ATTACH_ERROR_RETURN;
282: }
283: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
284: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
285: sc->sc_ed[UPL_ENDPT_RX] = ed->bEndpointAddress;
286: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
287: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
288: sc->sc_ed[UPL_ENDPT_TX] = ed->bEndpointAddress;
289: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
290: UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
291: sc->sc_ed[UPL_ENDPT_INTR] = ed->bEndpointAddress;
292: }
293: }
294:
295: if (sc->sc_ed[UPL_ENDPT_RX] == 0 || sc->sc_ed[UPL_ENDPT_TX] == 0 ||
296: sc->sc_ed[UPL_ENDPT_INTR] == 0) {
297: printf("%s: missing endpoint\n", USBDEVNAME(sc->sc_dev));
298: USB_ATTACH_ERROR_RETURN;
299: }
300:
1.14 thorpej 301: s = splnet();
1.1 augustss 302:
303: /* Initialize interface info.*/
304: ifp = &sc->sc_if;
305: ifp->if_softc = sc;
306: ifp->if_mtu = UPL_BUFSZ;
307: ifp->if_flags = IFF_POINTOPOINT | IFF_NOARP | IFF_SIMPLEX;
308: ifp->if_ioctl = upl_ioctl;
309: ifp->if_start = upl_start;
310: ifp->if_watchdog = upl_watchdog;
311: strncpy(ifp->if_xname, USBDEVNAME(sc->sc_dev), IFNAMSIZ);
312:
313: ifp->if_type = IFT_OTHER;
314: ifp->if_addrlen = 0;
315: ifp->if_hdrlen = 0;
316: ifp->if_output = upl_output;
317: ifp->if_input = upl_input;
318: ifp->if_baudrate = 12000000;
1.12 augustss 319: ifp->if_dlt = DLT_RAW;
1.17 itojun 320: IFQ_SET_READY(&ifp->if_snd);
1.1 augustss 321:
322: /* Attach the interface. */
323: if_attach(ifp);
1.12 augustss 324: if_alloc_sadl(ifp);
1.1 augustss 325:
326: #if NBPFILTER > 0
1.12 augustss 327: bpfattach(ifp, DLT_RAW, 0);
1.1 augustss 328: #endif
329: #if NRND > 0
330: rnd_attach_source(&sc->sc_rnd_source, USBDEVNAME(sc->sc_dev),
331: RND_TYPE_NET, 0);
332: #endif
333:
334: sc->sc_attached = 1;
335: splx(s);
336:
337: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
338: USBDEV(sc->sc_dev));
339:
340: USB_ATTACH_SUCCESS_RETURN;
341: }
342:
343: USB_DETACH(upl)
344: {
345: USB_DETACH_START(upl, sc);
346: struct ifnet *ifp = &sc->sc_if;
347: int s;
348:
1.18 augustss 349: DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
1.1 augustss 350:
351: s = splusb();
352:
353: if (!sc->sc_attached) {
354: /* Detached before attached finished, so just bail out. */
355: splx(s);
356: return (0);
357: }
358:
359: if (ifp->if_flags & IFF_RUNNING)
360: upl_stop(sc);
361:
362: #if NRND > 0
363: rnd_detach_source(&sc->sc_rnd_source);
364: #endif
365: #if NBPFILTER > 0
366: bpfdetach(ifp);
367: #endif
368:
369: if_detach(ifp);
370:
371: #ifdef DIAGNOSTIC
372: if (sc->sc_ep[UPL_ENDPT_TX] != NULL ||
373: sc->sc_ep[UPL_ENDPT_RX] != NULL ||
374: sc->sc_ep[UPL_ENDPT_INTR] != NULL)
375: printf("%s: detach has active endpoints\n",
376: USBDEVNAME(sc->sc_dev));
377: #endif
378:
379: sc->sc_attached = 0;
380: splx(s);
381:
382: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
383: USBDEV(sc->sc_dev));
384:
385: return (0);
386: }
387:
388: int
1.4 augustss 389: upl_activate(device_ptr_t self, enum devact act)
1.1 augustss 390: {
391: struct upl_softc *sc = (struct upl_softc *)self;
392:
1.18 augustss 393: DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
1.1 augustss 394:
395: switch (act) {
396: case DVACT_ACTIVATE:
397: return (EOPNOTSUPP);
398: break;
399:
400: case DVACT_DEACTIVATE:
401: /* Deactivate the interface. */
402: if_deactivate(&sc->sc_if);
403: sc->sc_dying = 1;
404: break;
405: }
406: return (0);
407: }
408:
409: /*
410: * Initialize an RX descriptor and attach an MBUF cluster.
411: */
412: Static int
1.4 augustss 413: upl_newbuf(struct upl_softc *sc, struct upl_chain *c, struct mbuf *m)
1.1 augustss 414: {
415: struct mbuf *m_new = NULL;
416:
1.18 augustss 417: DPRINTFN(8,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
1.1 augustss 418:
419: if (m == NULL) {
420: MGETHDR(m_new, M_DONTWAIT, MT_DATA);
421: if (m_new == NULL) {
422: printf("%s: no memory for rx list "
423: "-- packet dropped!\n", USBDEVNAME(sc->sc_dev));
424: return (ENOBUFS);
425: }
426:
427: MCLGET(m_new, M_DONTWAIT);
428: if (!(m_new->m_flags & M_EXT)) {
429: printf("%s: no memory for rx list "
430: "-- packet dropped!\n", USBDEVNAME(sc->sc_dev));
431: m_freem(m_new);
432: return (ENOBUFS);
433: }
434: m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
435: } else {
436: m_new = m;
437: m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
438: m_new->m_data = m_new->m_ext.ext_buf;
439: }
440:
441: c->upl_mbuf = m_new;
442:
443: return (0);
444: }
445:
446: Static int
1.4 augustss 447: upl_rx_list_init(struct upl_softc *sc)
1.1 augustss 448: {
449: struct upl_cdata *cd;
450: struct upl_chain *c;
451: int i;
452:
1.18 augustss 453: DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
1.1 augustss 454:
455: cd = &sc->sc_cdata;
456: for (i = 0; i < UPL_RX_LIST_CNT; i++) {
457: c = &cd->upl_rx_chain[i];
458: c->upl_sc = sc;
459: c->upl_idx = i;
460: if (upl_newbuf(sc, c, NULL) == ENOBUFS)
461: return (ENOBUFS);
462: if (c->upl_xfer == NULL) {
463: c->upl_xfer = usbd_alloc_xfer(sc->sc_udev);
464: if (c->upl_xfer == NULL)
465: return (ENOBUFS);
466: c->upl_buf = usbd_alloc_buffer(c->upl_xfer, UPL_BUFSZ);
467: if (c->upl_buf == NULL) {
468: usbd_free_xfer(c->upl_xfer);
469: return (ENOBUFS);
470: }
471: }
472: }
473:
474: return (0);
475: }
476:
477: Static int
1.4 augustss 478: upl_tx_list_init(struct upl_softc *sc)
1.1 augustss 479: {
480: struct upl_cdata *cd;
481: struct upl_chain *c;
482: int i;
483:
1.18 augustss 484: DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
1.1 augustss 485:
486: cd = &sc->sc_cdata;
487: for (i = 0; i < UPL_TX_LIST_CNT; i++) {
488: c = &cd->upl_tx_chain[i];
489: c->upl_sc = sc;
490: c->upl_idx = i;
491: c->upl_mbuf = NULL;
492: if (c->upl_xfer == NULL) {
493: c->upl_xfer = usbd_alloc_xfer(sc->sc_udev);
494: if (c->upl_xfer == NULL)
495: return (ENOBUFS);
496: c->upl_buf = usbd_alloc_buffer(c->upl_xfer, UPL_BUFSZ);
497: if (c->upl_buf == NULL) {
498: usbd_free_xfer(c->upl_xfer);
499: return (ENOBUFS);
500: }
501: }
502: }
503:
504: return (0);
505: }
506:
507: /*
508: * A frame has been uploaded: pass the resulting mbuf chain up to
509: * the higher level protocols.
510: */
511: Static void
1.4 augustss 512: upl_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
1.1 augustss 513: {
514: struct upl_chain *c = priv;
515: struct upl_softc *sc = c->upl_sc;
516: struct ifnet *ifp = &sc->sc_if;
517: struct mbuf *m;
518: int total_len = 0;
519: int s;
520:
521: if (sc->sc_dying)
522: return;
523:
524: if (!(ifp->if_flags & IFF_RUNNING))
525: return;
526:
527: if (status != USBD_NORMAL_COMPLETION) {
528: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
529: return;
530: sc->sc_rx_errs++;
531: if (usbd_ratecheck(&sc->sc_rx_notice)) {
532: printf("%s: %u usb errors on rx: %s\n",
533: USBDEVNAME(sc->sc_dev), sc->sc_rx_errs,
534: usbd_errstr(status));
535: sc->sc_rx_errs = 0;
536: }
537: if (status == USBD_STALLED)
538: usbd_clear_endpoint_stall(sc->sc_ep[UPL_ENDPT_RX]);
539: goto done;
540: }
541:
542: usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
543:
544: DPRINTFN(9,("%s: %s: enter status=%d length=%d\n",
1.18 augustss 545: USBDEVNAME(sc->sc_dev), __func__, status, total_len));
1.1 augustss 546:
547: m = c->upl_mbuf;
548: memcpy(mtod(c->upl_mbuf, char *), c->upl_buf, total_len);
549:
550: ifp->if_ipackets++;
551: m->m_pkthdr.len = m->m_len = total_len;
552:
553: m->m_pkthdr.rcvif = ifp;
554:
1.14 thorpej 555: s = splnet();
1.1 augustss 556:
557: /* XXX ugly */
558: if (upl_newbuf(sc, c, NULL) == ENOBUFS) {
559: ifp->if_ierrors++;
560: goto done1;
561: }
562:
563: #if NBPFILTER > 0
564: /*
565: * Handle BPF listeners. Let the BPF user see the packet, but
566: * don't pass it up to the ether_input() layer unless it's
567: * a broadcast packet, multicast packet, matches our ethernet
568: * address or the interface is in promiscuous mode.
569: */
570: if (ifp->if_bpf) {
571: BPF_MTAP(ifp, m);
572: }
573: #endif
574:
575: DPRINTFN(10,("%s: %s: deliver %d\n", USBDEVNAME(sc->sc_dev),
1.18 augustss 576: __func__, m->m_len));
1.1 augustss 577:
578: IF_INPUT(ifp, m);
579:
580: done1:
581: splx(s);
582:
583: done:
584: #if 1
585: /* Setup new transfer. */
586: usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX],
587: c, c->upl_buf, UPL_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
588: USBD_NO_TIMEOUT, upl_rxeof);
589: usbd_transfer(c->upl_xfer);
590:
591: DPRINTFN(10,("%s: %s: start rx\n", USBDEVNAME(sc->sc_dev),
1.18 augustss 592: __func__));
1.1 augustss 593: #endif
594: }
595:
596: /*
597: * A frame was downloaded to the chip. It's safe for us to clean up
598: * the list buffers.
599: */
600: Static void
1.4 augustss 601: upl_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
1.1 augustss 602: {
603: struct upl_chain *c = priv;
604: struct upl_softc *sc = c->upl_sc;
605: struct ifnet *ifp = &sc->sc_if;
606: int s;
607:
608: if (sc->sc_dying)
609: return;
610:
1.14 thorpej 611: s = splnet();
1.1 augustss 612:
613: DPRINTFN(10,("%s: %s: enter status=%d\n", USBDEVNAME(sc->sc_dev),
1.18 augustss 614: __func__, status));
1.1 augustss 615:
616: ifp->if_timer = 0;
617: ifp->if_flags &= ~IFF_OACTIVE;
618:
619: if (status != USBD_NORMAL_COMPLETION) {
620: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
621: splx(s);
622: return;
623: }
624: ifp->if_oerrors++;
625: printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->sc_dev),
626: usbd_errstr(status));
627: if (status == USBD_STALLED)
628: usbd_clear_endpoint_stall(sc->sc_ep[UPL_ENDPT_TX]);
629: splx(s);
630: return;
631: }
632:
633: ifp->if_opackets++;
634:
635: m_freem(c->upl_mbuf);
636: c->upl_mbuf = NULL;
637:
1.17 itojun 638: if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1.1 augustss 639: upl_start(ifp);
640:
641: splx(s);
642: }
643:
644: Static int
1.4 augustss 645: upl_send(struct upl_softc *sc, struct mbuf *m, int idx)
1.1 augustss 646: {
647: int total_len;
648: struct upl_chain *c;
649: usbd_status err;
650:
651: c = &sc->sc_cdata.upl_tx_chain[idx];
652:
653: /*
654: * Copy the mbuf data into a contiguous buffer, leaving two
655: * bytes at the beginning to hold the frame length.
656: */
657: m_copydata(m, 0, m->m_pkthdr.len, c->upl_buf);
658: c->upl_mbuf = m;
659:
660: total_len = m->m_pkthdr.len;
661:
662: DPRINTFN(10,("%s: %s: total_len=%d\n",
1.18 augustss 663: USBDEVNAME(sc->sc_dev), __func__, total_len));
1.1 augustss 664:
665: usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_TX],
666: c, c->upl_buf, total_len, USBD_NO_COPY, USBD_DEFAULT_TIMEOUT,
667: upl_txeof);
668:
669: /* Transmit */
670: err = usbd_transfer(c->upl_xfer);
671: if (err != USBD_IN_PROGRESS) {
672: printf("%s: upl_send error=%s\n", USBDEVNAME(sc->sc_dev),
673: usbd_errstr(err));
674: upl_stop(sc);
675: return (EIO);
676: }
677:
678: sc->sc_cdata.upl_tx_cnt++;
679:
680: return (0);
681: }
682:
683: Static void
1.4 augustss 684: upl_start(struct ifnet *ifp)
1.1 augustss 685: {
686: struct upl_softc *sc = ifp->if_softc;
687: struct mbuf *m_head = NULL;
688:
689: if (sc->sc_dying)
690: return;
691:
1.18 augustss 692: DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
1.1 augustss 693:
694: if (ifp->if_flags & IFF_OACTIVE)
695: return;
696:
1.17 itojun 697: IFQ_POLL(&ifp->if_snd, m_head);
1.1 augustss 698: if (m_head == NULL)
699: return;
700:
701: if (upl_send(sc, m_head, 0)) {
702: ifp->if_flags |= IFF_OACTIVE;
703: return;
704: }
705:
1.17 itojun 706: IFQ_DEQUEUE(&ifp->if_snd, m_head);
707:
1.1 augustss 708: #if NBPFILTER > 0
709: /*
710: * If there's a BPF listener, bounce a copy of this frame
711: * to him.
712: */
713: if (ifp->if_bpf)
714: BPF_MTAP(ifp, m_head);
715: #endif
716:
717: ifp->if_flags |= IFF_OACTIVE;
718:
719: /*
720: * Set a timeout in case the chip goes out to lunch.
721: */
722: ifp->if_timer = 5;
723: }
724:
725: Static void
1.4 augustss 726: upl_init(void *xsc)
1.1 augustss 727: {
728: struct upl_softc *sc = xsc;
729: struct ifnet *ifp = &sc->sc_if;
730: int s;
731:
732: if (sc->sc_dying)
733: return;
734:
1.18 augustss 735: DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
1.1 augustss 736:
737: if (ifp->if_flags & IFF_RUNNING)
738: return;
739:
1.14 thorpej 740: s = splnet();
1.1 augustss 741:
742: /* Init TX ring. */
743: if (upl_tx_list_init(sc) == ENOBUFS) {
744: printf("%s: tx list init failed\n", USBDEVNAME(sc->sc_dev));
745: splx(s);
746: return;
747: }
748:
749: /* Init RX ring. */
750: if (upl_rx_list_init(sc) == ENOBUFS) {
751: printf("%s: rx list init failed\n", USBDEVNAME(sc->sc_dev));
752: splx(s);
753: return;
754: }
755:
756: if (sc->sc_ep[UPL_ENDPT_RX] == NULL) {
757: if (upl_openpipes(sc)) {
758: splx(s);
759: return;
760: }
761: }
762:
763: ifp->if_flags |= IFF_RUNNING;
764: ifp->if_flags &= ~IFF_OACTIVE;
765:
766: splx(s);
767: }
768:
769: Static int
1.4 augustss 770: upl_openpipes(struct upl_softc *sc)
1.1 augustss 771: {
772: struct upl_chain *c;
773: usbd_status err;
774: int i;
775:
776: /* Open RX and TX pipes. */
777: err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_RX],
778: USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_RX]);
779: if (err) {
780: printf("%s: open rx pipe failed: %s\n",
781: USBDEVNAME(sc->sc_dev), usbd_errstr(err));
782: return (EIO);
783: }
784: err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_TX],
785: USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_TX]);
786: if (err) {
787: printf("%s: open tx pipe failed: %s\n",
788: USBDEVNAME(sc->sc_dev), usbd_errstr(err));
789: return (EIO);
790: }
791: err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ed[UPL_ENDPT_INTR],
792: USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_INTR], sc,
1.19 augustss 793: &sc->sc_ibuf, UPL_INTR_PKTLEN, upl_intr,
1.1 augustss 794: UPL_INTR_INTERVAL);
795: if (err) {
796: printf("%s: open intr pipe failed: %s\n",
797: USBDEVNAME(sc->sc_dev), usbd_errstr(err));
798: return (EIO);
799: }
800:
801:
802: #if 1
803: /* Start up the receive pipe. */
804: for (i = 0; i < UPL_RX_LIST_CNT; i++) {
805: c = &sc->sc_cdata.upl_rx_chain[i];
806: usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX],
807: c, c->upl_buf, UPL_BUFSZ,
808: USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
809: upl_rxeof);
810: usbd_transfer(c->upl_xfer);
811: }
812: #endif
813:
814: return (0);
815: }
816:
817: Static void
1.4 augustss 818: upl_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
1.1 augustss 819: {
820: struct upl_softc *sc = priv;
821: struct ifnet *ifp = &sc->sc_if;
822: uByte stat;
823:
1.18 augustss 824: DPRINTFN(15,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
1.1 augustss 825:
826: if (sc->sc_dying)
827: return;
828:
829: if (!(ifp->if_flags & IFF_RUNNING))
830: return;
831:
832: if (status != USBD_NORMAL_COMPLETION) {
833: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
834: return;
835: }
836: sc->sc_intr_errs++;
837: if (usbd_ratecheck(&sc->sc_rx_notice)) {
838: printf("%s: %u usb errors on intr: %s\n",
839: USBDEVNAME(sc->sc_dev), sc->sc_rx_errs,
840: usbd_errstr(status));
841: sc->sc_intr_errs = 0;
842: }
843: if (status == USBD_STALLED)
844: usbd_clear_endpoint_stall(sc->sc_ep[UPL_ENDPT_RX]);
845: return;
846: }
847:
848: stat = sc->sc_ibuf;
849:
850: if (stat == 0)
851: return;
852:
853: DPRINTFN(10,("%s: %s: stat=0x%02x\n", USBDEVNAME(sc->sc_dev),
1.18 augustss 854: __func__, stat));
1.1 augustss 855:
856: }
857:
858: Static int
1.4 augustss 859: upl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1.1 augustss 860: {
861: struct upl_softc *sc = ifp->if_softc;
862: struct ifaddr *ifa = (struct ifaddr *)data;
863: struct ifreq *ifr = (struct ifreq *)data;
864: int s, error = 0;
865:
866: if (sc->sc_dying)
867: return (EIO);
868:
869: DPRINTFN(5,("%s: %s: cmd=0x%08lx\n",
1.18 augustss 870: USBDEVNAME(sc->sc_dev), __func__, command));
1.1 augustss 871:
1.14 thorpej 872: s = splnet();
1.1 augustss 873:
874: switch(command) {
875: case SIOCSIFADDR:
876: ifp->if_flags |= IFF_UP;
877: upl_init(sc);
878:
879: switch (ifa->ifa_addr->sa_family) {
880: #ifdef INET
881: case AF_INET:
882: break;
883: #endif /* INET */
884: #ifdef NS
885: case AF_NS:
886: {
887: struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
888:
889: if (ns_nullhost(*ina))
890: ina->x_host = *(union ns_host *)
891: LLADDR(ifp->if_sadl);
892: else
893: memcpy(LLADDR(ifp->if_sadl),
894: ina->x_host.c_host,
895: ifp->if_addrlen);
896: break;
897: }
898: #endif /* NS */
899: }
900: break;
901:
902: case SIOCSIFMTU:
903: if (ifr->ifr_mtu > UPL_BUFSZ)
904: error = EINVAL;
905: else
906: ifp->if_mtu = ifr->ifr_mtu;
907: break;
908:
909: case SIOCSIFFLAGS:
910: if (ifp->if_flags & IFF_UP) {
911: if (!(ifp->if_flags & IFF_RUNNING))
912: upl_init(sc);
913: } else {
914: if (ifp->if_flags & IFF_RUNNING)
915: upl_stop(sc);
916: }
917: error = 0;
918: break;
919: default:
920: error = EINVAL;
921: break;
922: }
923:
924: splx(s);
925:
926: return (error);
927: }
928:
929: Static void
1.4 augustss 930: upl_watchdog(struct ifnet *ifp)
1.1 augustss 931: {
932: struct upl_softc *sc = ifp->if_softc;
933:
1.18 augustss 934: DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
1.1 augustss 935:
936: if (sc->sc_dying)
937: return;
938:
939: ifp->if_oerrors++;
940: printf("%s: watchdog timeout\n", USBDEVNAME(sc->sc_dev));
941:
942: upl_stop(sc);
943: upl_init(sc);
944:
1.17 itojun 945: if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1.1 augustss 946: upl_start(ifp);
947: }
948:
949: /*
950: * Stop the adapter and free any mbufs allocated to the
951: * RX and TX lists.
952: */
953: Static void
1.4 augustss 954: upl_stop(struct upl_softc *sc)
1.1 augustss 955: {
956: usbd_status err;
957: struct ifnet *ifp;
958: int i;
959:
1.18 augustss 960: DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
1.1 augustss 961:
962: ifp = &sc->sc_if;
963: ifp->if_timer = 0;
964:
965: /* Stop transfers. */
966: if (sc->sc_ep[UPL_ENDPT_RX] != NULL) {
967: err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_RX]);
968: if (err) {
969: printf("%s: abort rx pipe failed: %s\n",
970: USBDEVNAME(sc->sc_dev), usbd_errstr(err));
971: }
972: err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_RX]);
973: if (err) {
974: printf("%s: close rx pipe failed: %s\n",
975: USBDEVNAME(sc->sc_dev), usbd_errstr(err));
976: }
977: sc->sc_ep[UPL_ENDPT_RX] = NULL;
978: }
979:
980: if (sc->sc_ep[UPL_ENDPT_TX] != NULL) {
981: err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_TX]);
982: if (err) {
983: printf("%s: abort tx pipe failed: %s\n",
984: USBDEVNAME(sc->sc_dev), usbd_errstr(err));
985: }
986: err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_TX]);
987: if (err) {
988: printf("%s: close tx pipe failed: %s\n",
989: USBDEVNAME(sc->sc_dev), usbd_errstr(err));
990: }
991: sc->sc_ep[UPL_ENDPT_TX] = NULL;
992: }
993:
994: if (sc->sc_ep[UPL_ENDPT_INTR] != NULL) {
995: err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_INTR]);
996: if (err) {
997: printf("%s: abort intr pipe failed: %s\n",
998: USBDEVNAME(sc->sc_dev), usbd_errstr(err));
999: }
1000: err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_INTR]);
1001: if (err) {
1002: printf("%s: close intr pipe failed: %s\n",
1003: USBDEVNAME(sc->sc_dev), usbd_errstr(err));
1004: }
1005: sc->sc_ep[UPL_ENDPT_INTR] = NULL;
1006: }
1007:
1008: /* Free RX resources. */
1009: for (i = 0; i < UPL_RX_LIST_CNT; i++) {
1010: if (sc->sc_cdata.upl_rx_chain[i].upl_mbuf != NULL) {
1011: m_freem(sc->sc_cdata.upl_rx_chain[i].upl_mbuf);
1012: sc->sc_cdata.upl_rx_chain[i].upl_mbuf = NULL;
1013: }
1014: if (sc->sc_cdata.upl_rx_chain[i].upl_xfer != NULL) {
1015: usbd_free_xfer(sc->sc_cdata.upl_rx_chain[i].upl_xfer);
1016: sc->sc_cdata.upl_rx_chain[i].upl_xfer = NULL;
1017: }
1018: }
1019:
1020: /* Free TX resources. */
1021: for (i = 0; i < UPL_TX_LIST_CNT; i++) {
1022: if (sc->sc_cdata.upl_tx_chain[i].upl_mbuf != NULL) {
1023: m_freem(sc->sc_cdata.upl_tx_chain[i].upl_mbuf);
1024: sc->sc_cdata.upl_tx_chain[i].upl_mbuf = NULL;
1025: }
1026: if (sc->sc_cdata.upl_tx_chain[i].upl_xfer != NULL) {
1027: usbd_free_xfer(sc->sc_cdata.upl_tx_chain[i].upl_xfer);
1028: sc->sc_cdata.upl_tx_chain[i].upl_xfer = NULL;
1029: }
1030: }
1031:
1032: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1033: }
1034:
1035: Static int
1.4 augustss 1036: upl_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
1037: struct rtentry *rt0)
1.1 augustss 1038: {
1.17 itojun 1039: int s, len, error;
1040: ALTQ_DECL(struct altq_pktattr pktattr;)
1.1 augustss 1041:
1042: DPRINTFN(10,("%s: %s: enter\n",
1043: USBDEVNAME(((struct upl_softc *)ifp->if_softc)->sc_dev),
1.18 augustss 1044: __func__));
1.1 augustss 1045:
1.17 itojun 1046: /*
1047: * if the queueing discipline needs packet classification,
1048: * do it now.
1049: */
1050: IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
1051:
1052: len = m->m_pkthdr.len;
1.14 thorpej 1053: s = splnet();
1.1 augustss 1054: /*
1055: * Queue message on interface, and start output if interface
1056: * not yet active.
1057: */
1.17 itojun 1058: IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
1059: if (error) {
1060: /* mbuf is already freed */
1.1 augustss 1061: splx(s);
1.17 itojun 1062: return (error);
1.1 augustss 1063: }
1.17 itojun 1064: ifp->if_obytes += len;
1.1 augustss 1065: if ((ifp->if_flags & IFF_OACTIVE) == 0)
1066: (*ifp->if_start)(ifp);
1067: splx(s);
1068:
1069: return (0);
1070: }
1071:
1072: Static void
1.4 augustss 1073: upl_input(struct ifnet *ifp, struct mbuf *m)
1.1 augustss 1074: {
1075: struct ifqueue *inq;
1076: int s;
1077:
1078: /* XXX Assume all traffic is IP */
1079:
1080: schednetisr(NETISR_IP);
1081: inq = &ipintrq;
1082:
1.14 thorpej 1083: s = splnet();
1.1 augustss 1084: if (IF_QFULL(inq)) {
1085: IF_DROP(inq);
1086: splx(s);
1.7 augustss 1087: #if 0
1088: if (sc->sc_flags & SC_DEBUG)
1089: printf("%s: input queue full\n", ifp->if_xname);
1090: #endif
1.1 augustss 1091: ifp->if_iqdrops++;
1092: return;
1093: }
1094: IF_ENQUEUE(inq, m);
1095: splx(s);
1096: ifp->if_ipackets++;
1097: ifp->if_ibytes += m->m_len;
1098: }
CVSweb <webmaster@jp.NetBSD.org>