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