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