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