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