if_upl.c revision 1.27.4.4 1 /* $NetBSD: if_upl.c,v 1.27.4.4 2007/06/18 13:43:21 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.4 2007/06/18 13:43:21 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 #if 1
480 /* Setup new transfer. */
481 (void)usbd_map_buffer_mbuf(c->ue_xfer, c->ue_mbuf);
482 usbd_setup_xfer(c->ue_xfer, sc->sc_ep[UPL_ENDPT_RX],
483 c, NULL /* XXX buf */, UPL_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
484 USBD_NO_TIMEOUT, upl_rxeof);
485 usbd_transfer(c->ue_xfer);
486
487 DPRINTFN(10,("%s: %s: start rx\n", USBDEVNAME(sc->sc_dev),
488 __func__));
489 #endif
490 }
491
492 /*
493 * A frame was downloaded to the chip. It's safe for us to clean up
494 * the list buffers.
495 */
496 Static void
497 upl_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
498 usbd_status status)
499 {
500 struct ue_chain *c = priv;
501 struct upl_softc *sc = (void *)c->ue_dev;
502 struct ifnet *ifp = &sc->sc_if;
503 int s;
504
505 if (sc->sc_dying)
506 return;
507
508 s = splnet();
509
510 DPRINTFN(10,("%s: %s: enter status=%d\n", USBDEVNAME(sc->sc_dev),
511 __func__, status));
512
513 ifp->if_timer = 0;
514 ifp->if_flags &= ~IFF_OACTIVE;
515
516 usbd_unmap_buffer(xfer);
517
518 if (status != USBD_NORMAL_COMPLETION) {
519 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
520 splx(s);
521 return;
522 }
523 ifp->if_oerrors++;
524 printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->sc_dev),
525 usbd_errstr(status));
526 if (status == USBD_STALLED)
527 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_TX]);
528 splx(s);
529 return;
530 }
531
532 ifp->if_opackets++;
533
534 m_freem(c->ue_mbuf);
535 c->ue_mbuf = NULL;
536
537 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
538 upl_start(ifp);
539
540 splx(s);
541 }
542
543 Static int
544 upl_send(struct upl_softc *sc, struct mbuf *m, int idx)
545 {
546 int total_len;
547 struct ue_chain *c;
548 usbd_status err;
549 int ret;
550
551 c = &sc->sc_cdata.upl_tx_chain[idx];
552
553 ret = usb_ether_map_tx_buffer_mbuf(c, m);
554 if (ret)
555 return (ret);
556
557 total_len = m->m_pkthdr.len;
558
559 DPRINTFN(10,("%s: %s: total_len=%d\n",
560 USBDEVNAME(sc->sc_dev), __func__, total_len));
561
562 usbd_setup_xfer(c->ue_xfer, sc->sc_ep[UPL_ENDPT_TX],
563 c, NULL /* XXX buf */, total_len, USBD_NO_COPY, USBD_DEFAULT_TIMEOUT,
564 upl_txeof);
565
566 /* Transmit */
567 err = usbd_transfer(c->ue_xfer);
568 if (err != USBD_IN_PROGRESS) {
569 printf("%s: upl_send error=%s\n", USBDEVNAME(sc->sc_dev),
570 usbd_errstr(err));
571 upl_stop(&sc->sc_if, 0);
572 return (EIO);
573 }
574
575 sc->sc_cdata.upl_tx_cnt++;
576
577 return (0);
578 }
579
580 Static void
581 upl_start(struct ifnet *ifp)
582 {
583 struct upl_softc *sc = ifp->if_softc;
584 struct mbuf *m_head = NULL;
585
586 if (sc->sc_dying)
587 return;
588
589 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
590
591 if (ifp->if_flags & IFF_OACTIVE)
592 return;
593
594 IFQ_POLL(&ifp->if_snd, m_head);
595 if (m_head == NULL)
596 return;
597
598 if (upl_send(sc, m_head, 0)) {
599 ifp->if_flags |= IFF_OACTIVE;
600 return;
601 }
602
603 IFQ_DEQUEUE(&ifp->if_snd, m_head);
604
605 #if NBPFILTER > 0
606 /*
607 * If there's a BPF listener, bounce a copy of this frame
608 * to him.
609 */
610 if (ifp->if_bpf)
611 BPF_MTAP(ifp, m_head);
612 #endif
613
614 ifp->if_flags |= IFF_OACTIVE;
615
616 /*
617 * Set a timeout in case the chip goes out to lunch.
618 */
619 ifp->if_timer = 5;
620 }
621
622 Static int
623 upl_init(struct ifnet *ifp)
624 {
625 struct upl_softc *sc = ifp->if_softc;
626 int s;
627 struct ue_chain *c;
628 int i;
629
630 if (sc->sc_dying)
631 return (EIO);
632
633 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
634
635 if (ifp->if_flags & IFF_RUNNING)
636 return (EIO);
637
638 s = splnet();
639
640 if (sc->sc_ep[UPL_ENDPT_RX] == NULL) {
641 if (upl_openpipes(sc)) {
642 splx(s);
643 return (EIO);
644 }
645 }
646
647 /* Init TX ring. */
648 if ((i = usb_ether_tx_list_init(USBDEV(sc->sc_dev),
649 sc->sc_cdata.upl_tx_chain, UPL_TX_LIST_CNT,
650 sc->sc_udev, sc->sc_ep[UPL_ENDPT_TX], NULL))) {
651 printf("%s: tx list init failed\n", USBDEVNAME(sc->sc_dev));
652 splx(s);
653 return (i);
654 }
655
656 /* Init RX ring. */
657 if ((i = usb_ether_rx_list_init(USBDEV(sc->sc_dev),
658 sc->sc_cdata.upl_rx_chain, UPL_RX_LIST_CNT,
659 sc->sc_udev, sc->sc_ep[UPL_ENDPT_RX]))) {
660 printf("%s: rx list init failed\n", USBDEVNAME(sc->sc_dev));
661 splx(s);
662 return (i);
663 }
664
665 /* Start up the receive pipe. */
666 for (i = 0; i < UPL_RX_LIST_CNT; i++) {
667 c = &sc->sc_cdata.upl_rx_chain[i];
668 (void)usbd_map_buffer_mbuf(c->ue_xfer, c->ue_mbuf);
669 usbd_setup_xfer(c->ue_xfer, sc->sc_ep[UPL_ENDPT_RX],
670 c, NULL /* XXX buf */, UPL_BUFSZ,
671 USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
672 upl_rxeof);
673 usbd_transfer(c->ue_xfer);
674 }
675
676 ifp->if_flags |= IFF_RUNNING;
677 ifp->if_flags &= ~IFF_OACTIVE;
678
679 splx(s);
680 return (0);
681 }
682
683 Static int
684 upl_openpipes(struct upl_softc *sc)
685 {
686 usbd_status err;
687
688 /* Open RX and TX pipes. */
689 err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_RX],
690 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_RX]);
691 if (err) {
692 printf("%s: open rx pipe failed: %s\n",
693 USBDEVNAME(sc->sc_dev), usbd_errstr(err));
694 return (EIO);
695 }
696 err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_TX],
697 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_TX]);
698 if (err) {
699 printf("%s: open tx pipe failed: %s\n",
700 USBDEVNAME(sc->sc_dev), usbd_errstr(err));
701 return (EIO);
702 }
703 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ed[UPL_ENDPT_INTR],
704 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_INTR], sc,
705 &sc->sc_ibuf, UPL_INTR_PKTLEN, upl_intr,
706 UPL_INTR_INTERVAL);
707 if (err) {
708 printf("%s: open intr pipe failed: %s\n",
709 USBDEVNAME(sc->sc_dev), usbd_errstr(err));
710 return (EIO);
711 }
712
713 return (0);
714 }
715
716 Static void
717 upl_intr(usbd_xfer_handle xfer, usbd_private_handle priv,
718 usbd_status status)
719 {
720 struct upl_softc *sc = priv;
721 struct ifnet *ifp = &sc->sc_if;
722 uByte stat;
723
724 DPRINTFN(15,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
725
726 if (sc->sc_dying)
727 return;
728
729 if (!(ifp->if_flags & IFF_RUNNING))
730 return;
731
732 if (status != USBD_NORMAL_COMPLETION) {
733 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
734 return;
735 }
736 sc->sc_intr_errs++;
737 if (usbd_ratecheck(&sc->sc_rx_notice)) {
738 printf("%s: %u usb errors on intr: %s\n",
739 USBDEVNAME(sc->sc_dev), sc->sc_rx_errs,
740 usbd_errstr(status));
741 sc->sc_intr_errs = 0;
742 }
743 if (status == USBD_STALLED)
744 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]);
745 return;
746 }
747
748 stat = sc->sc_ibuf;
749
750 if (stat == 0)
751 return;
752
753 DPRINTFN(10,("%s: %s: stat=0x%02x\n", USBDEVNAME(sc->sc_dev),
754 __func__, stat));
755
756 }
757
758 Static int
759 upl_ioctl(struct ifnet *ifp, u_long command, usb_ioctlarg_t data)
760 {
761 struct upl_softc *sc = ifp->if_softc;
762 #if 0
763 struct ifaddr *ifa = (struct ifaddr *)data;
764 struct ifreq *ifr = (struct ifreq *)data;
765 #endif
766 int s, error = 0;
767
768 if (sc->sc_dying)
769 return (EIO);
770
771 DPRINTFN(5,("%s: %s: cmd=0x%08lx\n",
772 USBDEVNAME(sc->sc_dev), __func__, command));
773
774 s = splnet();
775
776 switch(command) {
777 #if 0
778 case SIOCSIFADDR:
779 ifp->if_flags |= IFF_UP;
780 upl_init(ifp);
781
782 switch (ifa->ifa_addr->sa_family) {
783 #ifdef INET
784 case AF_INET:
785 break;
786 #endif /* INET */
787 }
788 break;
789
790 case SIOCSIFMTU:
791 if (ifr->ifr_mtu > UPL_BUFSZ)
792 error = EINVAL;
793 else
794 ifp->if_mtu = ifr->ifr_mtu;
795 break;
796
797 case SIOCSIFFLAGS:
798 if (ifp->if_flags & IFF_UP) {
799 if (!(ifp->if_flags & IFF_RUNNING))
800 upl_init(ifp);
801 } else {
802 if (ifp->if_flags & IFF_RUNNING)
803 upl_stop(ifp, 1);
804 }
805 error = 0;
806 break;
807 #endif
808 default:
809 error = ether_ioctl(ifp, command, data);
810 if (error == ENETRESET) {
811 /*
812 * Multicast list has changed; set the hardware
813 * filter accordingly.
814 */
815 #if 0 /* XXX not yet */
816 if (ifp->if_flags & IFF_RUNNING)
817 upl_setmulti(sc);
818 #endif
819 error = 0;
820 }
821 break;
822 }
823
824 splx(s);
825
826 return (error);
827 }
828
829 Static void
830 upl_watchdog(struct ifnet *ifp)
831 {
832 struct upl_softc *sc = ifp->if_softc;
833
834 DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
835
836 if (sc->sc_dying)
837 return;
838
839 ifp->if_oerrors++;
840 printf("%s: watchdog timeout\n", USBDEVNAME(sc->sc_dev));
841
842 upl_stop(ifp, 1);
843 upl_init(ifp);
844
845 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
846 upl_start(ifp);
847 }
848
849 /*
850 * Stop the adapter and free any mbufs allocated to the
851 * RX and TX lists.
852 */
853 Static void
854 upl_stop(struct ifnet *ifp, int disable)
855 {
856 struct upl_softc *sc = ifp->if_softc;
857 usbd_status err;
858
859 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
860
861 ifp = &sc->sc_if;
862 ifp->if_timer = 0;
863
864 /* Stop transfers. */
865 if (sc->sc_ep[UPL_ENDPT_RX] != NULL) {
866 err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_RX]);
867 if (err) {
868 printf("%s: abort rx pipe failed: %s\n",
869 USBDEVNAME(sc->sc_dev), usbd_errstr(err));
870 }
871 }
872
873 if (sc->sc_ep[UPL_ENDPT_TX] != NULL) {
874 err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_TX]);
875 if (err) {
876 printf("%s: abort tx pipe failed: %s\n",
877 USBDEVNAME(sc->sc_dev), usbd_errstr(err));
878 }
879 }
880
881 if (sc->sc_ep[UPL_ENDPT_INTR] != NULL) {
882 err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_INTR]);
883 if (err) {
884 printf("%s: abort intr pipe failed: %s\n",
885 USBDEVNAME(sc->sc_dev), usbd_errstr(err));
886 }
887 }
888
889 /* Free RX/TX list resources. */
890 usb_ether_rx_list_free(sc->sc_cdata.upl_rx_chain, UPL_RX_LIST_CNT);
891 usb_ether_tx_list_free(sc->sc_cdata.upl_tx_chain, UPL_TX_LIST_CNT);
892
893 /* Close pipes. */
894 if (sc->sc_ep[UPL_ENDPT_RX] != NULL) {
895 err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_RX]);
896 if (err) {
897 printf("%s: close rx pipe failed: %s\n",
898 USBDEVNAME(sc->sc_dev), usbd_errstr(err));
899 }
900 sc->sc_ep[UPL_ENDPT_RX] = NULL;
901 }
902
903 if (sc->sc_ep[UPL_ENDPT_TX] != NULL) {
904 err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_TX]);
905 if (err) {
906 printf("%s: close tx pipe failed: %s\n",
907 USBDEVNAME(sc->sc_dev), usbd_errstr(err));
908 }
909 sc->sc_ep[UPL_ENDPT_TX] = NULL;
910 }
911
912 if (sc->sc_ep[UPL_ENDPT_INTR] != NULL) {
913 err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_INTR]);
914 if (err) {
915 printf("%s: close intr pipe failed: %s\n",
916 USBDEVNAME(sc->sc_dev), usbd_errstr(err));
917 }
918 sc->sc_ep[UPL_ENDPT_INTR] = NULL;
919 }
920
921 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
922 }
923
924 Static int
925 upl_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
926 struct rtentry *rt0)
927 {
928 int s, len, error;
929 ALTQ_DECL(struct altq_pktattr pktattr;)
930
931 DPRINTFN(10,("%s: %s: enter\n",
932 USBDEVNAME(((struct upl_softc *)ifp->if_softc)->sc_dev),
933 __func__));
934
935 /*
936 * if the queueing discipline needs packet classification,
937 * do it now.
938 */
939 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
940
941 len = m->m_pkthdr.len;
942 s = splnet();
943 /*
944 * Queue message on interface, and start output if interface
945 * not yet active.
946 */
947 IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
948 if (error) {
949 /* mbuf is already freed */
950 splx(s);
951 return (error);
952 }
953 ifp->if_obytes += len;
954 if ((ifp->if_flags & IFF_OACTIVE) == 0)
955 (*ifp->if_start)(ifp);
956 splx(s);
957
958 return (0);
959 }
960
961 Static void
962 upl_input(struct ifnet *ifp, struct mbuf *m)
963 {
964 #ifdef INET
965 struct ifqueue *inq;
966 int s;
967
968 /* XXX Assume all traffic is IP */
969
970 schednetisr(NETISR_IP);
971 inq = &ipintrq;
972
973 s = splnet();
974 if (IF_QFULL(inq)) {
975 IF_DROP(inq);
976 splx(s);
977 #if 0
978 if (sc->sc_flags & SC_DEBUG)
979 printf("%s: input queue full\n", ifp->if_xname);
980 #endif
981 ifp->if_iqdrops++;
982 return;
983 }
984 IF_ENQUEUE(inq, m);
985 splx(s);
986 #endif
987 ifp->if_ipackets++;
988 ifp->if_ibytes += m->m_len;
989 }
990