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