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