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