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