xref: /openbsd-src/sys/dev/usb/if_upl.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /*	$OpenBSD: if_upl.c,v 1.71 2016/04/13 11:03:37 mpi Exp $ */
2 /*	$NetBSD: if_upl.c,v 1.19 2002/07/11 21:14:26 augustss Exp $	*/
3 /*
4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Lennart Augustsson (lennart@augustsson.net) at
9  * Carlstedt Research & Technology.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Prolific PL2301/PL2302 driver
35  */
36 
37 #include "bpfilter.h"
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/timeout.h>
42 #include <sys/sockio.h>
43 #include <sys/mbuf.h>
44 #include <sys/kernel.h>
45 #include <sys/socket.h>
46 
47 #include <sys/device.h>
48 
49 #include <net/if.h>
50 #include <net/if_types.h>
51 
52 #if NBPFILTER > 0
53 #include <net/bpf.h>
54 #endif
55 
56 #include <netinet/in.h>
57 #include <netinet/if_ether.h>
58 
59 #include <dev/usb/usb.h>
60 #include <dev/usb/usbdi.h>
61 #include <dev/usb/usbdi_util.h>
62 #include <dev/usb/usbdevs.h>
63 
64 /*
65  * 7  6  5  4  3  2  1  0
66  * tx rx 1  0
67  * 1110 0000 rxdata
68  * 1010 0000 idle
69  * 0010 0000 tx over
70  * 0110      tx over + rxd
71  */
72 
73 #define UPL_RXDATA		0x40
74 #define UPL_TXOK		0x80
75 
76 #define UPL_INTR_PKTLEN		1
77 
78 #define UPL_CONFIG_NO		1
79 #define UPL_IFACE_IDX		0
80 
81 /***/
82 
83 #define UPL_INTR_INTERVAL	20
84 
85 #define UPL_BUFSZ		1024
86 
87 #define UPL_RX_FRAMES		1
88 #define UPL_TX_FRAMES		1
89 
90 #define UPL_RX_LIST_CNT		1
91 #define UPL_TX_LIST_CNT		1
92 
93 #define UPL_ENDPT_RX		0x0
94 #define UPL_ENDPT_TX		0x1
95 #define UPL_ENDPT_INTR		0x2
96 #define UPL_ENDPT_MAX		0x3
97 
98 struct upl_softc;
99 
100 struct upl_chain {
101 	struct upl_softc	*upl_sc;
102 	struct usbd_xfer	*upl_xfer;
103 	char			*upl_buf;
104 	struct mbuf		*upl_mbuf;
105 	int			upl_idx;
106 };
107 
108 struct upl_cdata {
109 	struct upl_chain	upl_tx_chain[UPL_TX_LIST_CNT];
110 	struct upl_chain	upl_rx_chain[UPL_RX_LIST_CNT];
111 	int			upl_tx_prod;
112 	int			upl_tx_cons;
113 	int			upl_tx_cnt;
114 	int			upl_rx_prod;
115 };
116 
117 struct upl_softc {
118 	struct device		sc_dev;
119 
120 	struct ifnet		sc_if;
121 	struct timeout		sc_stat_ch;
122 
123 	struct usbd_device	*sc_udev;
124 	struct usbd_interface	*sc_iface;
125 	int			sc_ed[UPL_ENDPT_MAX];
126 	struct usbd_pipe	*sc_ep[UPL_ENDPT_MAX];
127 	struct upl_cdata	sc_cdata;
128 
129 	uByte			sc_ibuf;
130 
131 	u_int			sc_rx_errs;
132 	struct timeval		sc_rx_notice;
133 	u_int			sc_intr_errs;
134 };
135 
136 #ifdef UPL_DEBUG
137 #define DPRINTF(x)	do { if (upldebug) printf x; } while (0)
138 #define DPRINTFN(n,x)	do { if (upldebug >= (n)) printf x; } while (0)
139 int	upldebug = 0;
140 #else
141 #define DPRINTF(x)
142 #define DPRINTFN(n,x)
143 #endif
144 
145 /*
146  * Various supported device vendors/products.
147  */
148 struct usb_devno upl_devs[] = {
149 	{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301 },
150 	{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302 }
151 };
152 
153 int upl_match(struct device *, void *, void *);
154 void upl_attach(struct device *, struct device *, void *);
155 int upl_detach(struct device *, int);
156 
157 struct cfdriver upl_cd = {
158 	NULL, "upl", DV_IFNET
159 };
160 
161 const struct cfattach upl_ca = {
162 	sizeof(struct upl_softc), upl_match, upl_attach, upl_detach
163 };
164 
165 int upl_openpipes(struct upl_softc *);
166 int upl_tx_list_init(struct upl_softc *);
167 int upl_rx_list_init(struct upl_softc *);
168 int upl_newbuf(struct upl_softc *, struct upl_chain *, struct mbuf *);
169 int upl_send(struct upl_softc *, struct mbuf *, int);
170 void upl_intr(struct usbd_xfer *, void *, usbd_status);
171 void upl_rxeof(struct usbd_xfer *, void *, usbd_status);
172 void upl_txeof(struct usbd_xfer *, void *, usbd_status);
173 void upl_start(struct ifnet *);
174 int upl_ioctl(struct ifnet *, u_long, caddr_t);
175 void upl_init(void *);
176 void upl_stop(struct upl_softc *);
177 void upl_watchdog(struct ifnet *);
178 
179 int upl_output(struct ifnet *, struct mbuf *, struct sockaddr *,
180 		      struct rtentry *);
181 
182 /*
183  * Probe for a Prolific chip.
184  */
185 int
186 upl_match(struct device *parent, void *match, void *aux)
187 {
188 	struct usb_attach_arg		*uaa = aux;
189 
190 	if (uaa->iface != NULL)
191 		return (UMATCH_NONE);
192 
193 	return (usb_lookup(upl_devs, uaa->vendor, uaa->product) != NULL ?
194 	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
195 }
196 
197 void
198 upl_attach(struct device *parent, struct device *self, void *aux)
199 {
200 	struct upl_softc	*sc = (struct upl_softc *)self;
201 	struct usb_attach_arg	*uaa = aux;
202 	int			s;
203 	struct usbd_device	*dev = uaa->device;
204 	struct usbd_interface	*iface;
205 	usbd_status		err;
206 	struct ifnet		*ifp;
207 	usb_interface_descriptor_t	*id;
208 	usb_endpoint_descriptor_t	*ed;
209 	int			i;
210 
211 	DPRINTFN(5,(" : upl_attach: sc=%p, dev=%p", sc, dev));
212 
213 	err = usbd_set_config_no(dev, UPL_CONFIG_NO, 1);
214 	if (err) {
215 		printf("%s: setting config no failed\n",
216 		    sc->sc_dev.dv_xname);
217 		return;
218 	}
219 
220 	sc->sc_udev = dev;
221 
222 	err = usbd_device2interface_handle(dev, UPL_IFACE_IDX, &iface);
223 	if (err) {
224 		printf("%s: getting interface handle failed\n",
225 		    sc->sc_dev.dv_xname);
226 		return;
227 	}
228 
229 	sc->sc_iface = iface;
230 	id = usbd_get_interface_descriptor(iface);
231 
232 	/* Find endpoints. */
233 	for (i = 0; i < id->bNumEndpoints; i++) {
234 		ed = usbd_interface2endpoint_descriptor(iface, i);
235 		if (ed == NULL) {
236 			printf("%s: couldn't get ep %d\n",
237 			    sc->sc_dev.dv_xname, i);
238 			return;
239 		}
240 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
241 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
242 			sc->sc_ed[UPL_ENDPT_RX] = ed->bEndpointAddress;
243 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
244 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
245 			sc->sc_ed[UPL_ENDPT_TX] = ed->bEndpointAddress;
246 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
247 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
248 			sc->sc_ed[UPL_ENDPT_INTR] = ed->bEndpointAddress;
249 		}
250 	}
251 
252 	if (sc->sc_ed[UPL_ENDPT_RX] == 0 || sc->sc_ed[UPL_ENDPT_TX] == 0 ||
253 	    sc->sc_ed[UPL_ENDPT_INTR] == 0) {
254 		printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
255 		return;
256 	}
257 
258 	s = splnet();
259 
260 	/* Initialize interface info.*/
261 	ifp = &sc->sc_if;
262 	ifp->if_softc = sc;
263 	ifp->if_mtu = UPL_BUFSZ;
264 	ifp->if_hardmtu = UPL_BUFSZ;
265 	ifp->if_flags = IFF_POINTOPOINT | IFF_NOARP | IFF_SIMPLEX;
266 	ifp->if_ioctl = upl_ioctl;
267 	ifp->if_start = upl_start;
268 	ifp->if_watchdog = upl_watchdog;
269 	strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
270 
271 	ifp->if_type = IFT_OTHER;
272 	ifp->if_addrlen = 0;
273 	ifp->if_hdrlen = 0;
274 	ifp->if_output = upl_output;
275 	ifp->if_baudrate = IF_Mbps(12);
276 
277 	/* Attach the interface. */
278 	if_attach(ifp);
279 	if_alloc_sadl(ifp);
280 
281 	splx(s);
282 }
283 
284 int
285 upl_detach(struct device *self, int flags)
286 {
287 	struct upl_softc	*sc = (struct upl_softc *)self;
288 	struct ifnet		*ifp = &sc->sc_if;
289 	int			s;
290 
291 	DPRINTFN(2,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
292 
293 	s = splusb();
294 
295 	if (ifp->if_flags & IFF_RUNNING)
296 		upl_stop(sc);
297 
298 	if (ifp->if_softc != NULL)
299 		if_detach(ifp);
300 
301 #ifdef DIAGNOSTIC
302 	if (sc->sc_ep[UPL_ENDPT_TX] != NULL ||
303 	    sc->sc_ep[UPL_ENDPT_RX] != NULL ||
304 	    sc->sc_ep[UPL_ENDPT_INTR] != NULL)
305 		printf("%s: detach has active endpoints\n",
306 		       sc->sc_dev.dv_xname);
307 #endif
308 
309 	splx(s);
310 
311 	return (0);
312 }
313 
314 /*
315  * Initialize an RX descriptor and attach an MBUF cluster.
316  */
317 int
318 upl_newbuf(struct upl_softc *sc, struct upl_chain *c, struct mbuf *m)
319 {
320 	struct mbuf		*m_new = NULL;
321 
322 	DPRINTFN(8,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
323 
324 	if (m == NULL) {
325 		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
326 		if (m_new == NULL) {
327 			printf("%s: no memory for rx list "
328 			    "-- packet dropped!\n", sc->sc_dev.dv_xname);
329 			return (ENOBUFS);
330 		}
331 
332 		MCLGET(m_new, M_DONTWAIT);
333 		if (!(m_new->m_flags & M_EXT)) {
334 			printf("%s: no memory for rx list "
335 			    "-- packet dropped!\n", sc->sc_dev.dv_xname);
336 			m_freem(m_new);
337 			return (ENOBUFS);
338 		}
339 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
340 	} else {
341 		m_new = m;
342 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
343 		m_new->m_data = m_new->m_ext.ext_buf;
344 	}
345 
346 	c->upl_mbuf = m_new;
347 
348 	return (0);
349 }
350 
351 int
352 upl_rx_list_init(struct upl_softc *sc)
353 {
354 	struct upl_cdata	*cd;
355 	struct upl_chain	*c;
356 	int			i;
357 
358 	DPRINTFN(5,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
359 
360 	cd = &sc->sc_cdata;
361 	for (i = 0; i < UPL_RX_LIST_CNT; i++) {
362 		c = &cd->upl_rx_chain[i];
363 		c->upl_sc = sc;
364 		c->upl_idx = i;
365 		if (upl_newbuf(sc, c, NULL) == ENOBUFS)
366 			return (ENOBUFS);
367 		if (c->upl_xfer == NULL) {
368 			c->upl_xfer = usbd_alloc_xfer(sc->sc_udev);
369 			if (c->upl_xfer == NULL)
370 				return (ENOBUFS);
371 			c->upl_buf = usbd_alloc_buffer(c->upl_xfer, UPL_BUFSZ);
372 			if (c->upl_buf == NULL) {
373 				usbd_free_xfer(c->upl_xfer);
374 				return (ENOBUFS);
375 			}
376 		}
377 	}
378 
379 	return (0);
380 }
381 
382 int
383 upl_tx_list_init(struct upl_softc *sc)
384 {
385 	struct upl_cdata	*cd;
386 	struct upl_chain	*c;
387 	int			i;
388 
389 	DPRINTFN(5,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
390 
391 	cd = &sc->sc_cdata;
392 	for (i = 0; i < UPL_TX_LIST_CNT; i++) {
393 		c = &cd->upl_tx_chain[i];
394 		c->upl_sc = sc;
395 		c->upl_idx = i;
396 		c->upl_mbuf = NULL;
397 		if (c->upl_xfer == NULL) {
398 			c->upl_xfer = usbd_alloc_xfer(sc->sc_udev);
399 			if (c->upl_xfer == NULL)
400 				return (ENOBUFS);
401 			c->upl_buf = usbd_alloc_buffer(c->upl_xfer, UPL_BUFSZ);
402 			if (c->upl_buf == NULL) {
403 				usbd_free_xfer(c->upl_xfer);
404 				return (ENOBUFS);
405 			}
406 		}
407 	}
408 
409 	return (0);
410 }
411 
412 /*
413  * A frame has been uploaded: pass the resulting mbuf chain up to
414  * the higher level protocols.
415  */
416 void
417 upl_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
418 {
419 	struct upl_chain	*c = priv;
420 	struct upl_softc	*sc = c->upl_sc;
421 	struct ifnet		*ifp = &sc->sc_if;
422 	struct mbuf_list	ml = MBUF_LIST_INITIALIZER();
423 	struct mbuf		*m;
424 	int			total_len = 0;
425 	int			s;
426 
427 	if (usbd_is_dying(sc->sc_udev))
428 		return;
429 
430 	if (!(ifp->if_flags & IFF_RUNNING))
431 		return;
432 
433 	if (status != USBD_NORMAL_COMPLETION) {
434 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
435 			return;
436 		sc->sc_rx_errs++;
437 		if (usbd_ratecheck(&sc->sc_rx_notice)) {
438 			printf("%s: %u usb errors on rx: %s\n",
439 			    sc->sc_dev.dv_xname, sc->sc_rx_errs,
440 			    usbd_errstr(status));
441 			sc->sc_rx_errs = 0;
442 		}
443 		if (status == USBD_STALLED)
444 			usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]);
445 		goto done;
446 	}
447 
448 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
449 
450 	DPRINTFN(9,("%s: %s: enter status=%d length=%d\n",
451 		    sc->sc_dev.dv_xname, __func__, status, total_len));
452 
453 	m = c->upl_mbuf;
454 	memcpy(mtod(c->upl_mbuf, char *), c->upl_buf, total_len);
455 
456 	m->m_pkthdr.len = m->m_len = total_len;
457 	ml_enqueue(&ml, m);
458 
459 	if (upl_newbuf(sc, c, NULL) == ENOBUFS) {
460 		ifp->if_ierrors++;
461 		goto done;
462 	}
463 
464 	s = splnet();
465 	if_input(ifp, &ml);
466 	splx(s);
467  done:
468 #if 1
469 	/* Setup new transfer. */
470 	usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX],
471 	    c, c->upl_buf, UPL_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
472 	    USBD_NO_TIMEOUT, upl_rxeof);
473 	usbd_transfer(c->upl_xfer);
474 
475 	DPRINTFN(10,("%s: %s: start rx\n", sc->sc_dev.dv_xname,
476 		    __func__));
477 #endif
478 }
479 
480 /*
481  * A frame was downloaded to the chip. It's safe for us to clean up
482  * the list buffers.
483  */
484 void
485 upl_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
486 {
487 	struct upl_chain	*c = priv;
488 	struct upl_softc	*sc = c->upl_sc;
489 	struct ifnet		*ifp = &sc->sc_if;
490 	int			s;
491 
492 	if (usbd_is_dying(sc->sc_udev))
493 		return;
494 
495 	s = splnet();
496 
497 	DPRINTFN(10,("%s: %s: enter status=%d\n", sc->sc_dev.dv_xname,
498 		    __func__, status));
499 
500 	ifp->if_timer = 0;
501 	ifq_clr_oactive(&ifp->if_snd);
502 
503 	if (status != USBD_NORMAL_COMPLETION) {
504 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
505 			splx(s);
506 			return;
507 		}
508 		ifp->if_oerrors++;
509 		printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname,
510 		    usbd_errstr(status));
511 		if (status == USBD_STALLED)
512 			usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_TX]);
513 		splx(s);
514 		return;
515 	}
516 
517 	ifp->if_opackets++;
518 
519 	m_freem(c->upl_mbuf);
520 	c->upl_mbuf = NULL;
521 
522 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
523 		upl_start(ifp);
524 
525 	splx(s);
526 }
527 
528 int
529 upl_send(struct upl_softc *sc, struct mbuf *m, int idx)
530 {
531 	int			total_len;
532 	struct upl_chain	*c;
533 	usbd_status		err;
534 
535 	c = &sc->sc_cdata.upl_tx_chain[idx];
536 
537 	/*
538 	 * Copy the mbuf data into a contiguous buffer, leaving two
539 	 * bytes at the beginning to hold the frame length.
540 	 */
541 	m_copydata(m, 0, m->m_pkthdr.len, c->upl_buf);
542 	c->upl_mbuf = m;
543 
544 	total_len = m->m_pkthdr.len;
545 
546 	DPRINTFN(10,("%s: %s: total_len=%d\n",
547 		     sc->sc_dev.dv_xname, __func__, total_len));
548 
549 	usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_TX],
550 	    c, c->upl_buf, total_len, USBD_NO_COPY, USBD_DEFAULT_TIMEOUT,
551 	    upl_txeof);
552 
553 	/* Transmit */
554 	err = usbd_transfer(c->upl_xfer);
555 	if (err != USBD_IN_PROGRESS) {
556 		printf("%s: upl_send error=%s\n", sc->sc_dev.dv_xname,
557 		       usbd_errstr(err));
558 		upl_stop(sc);
559 		return (EIO);
560 	}
561 
562 	sc->sc_cdata.upl_tx_cnt++;
563 
564 	return (0);
565 }
566 
567 void
568 upl_start(struct ifnet *ifp)
569 {
570 	struct upl_softc	*sc = ifp->if_softc;
571 	struct mbuf		*m_head = NULL;
572 
573 	if (usbd_is_dying(sc->sc_udev))
574 		return;
575 
576 	DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
577 
578 	if (ifq_is_oactive(&ifp->if_snd))
579 		return;
580 
581 	m_head = ifq_deq_begin(&ifp->if_snd);
582 	if (m_head == NULL)
583 		return;
584 
585 	if (upl_send(sc, m_head, 0)) {
586 		ifq_deq_rollback(&ifp->if_snd, m_head);
587 		ifq_set_oactive(&ifp->if_snd);
588 		return;
589 	}
590 
591 	ifq_deq_commit(&ifp->if_snd, m_head);
592 
593 #if NBPFILTER > 0
594 	/*
595 	 * If there's a BPF listener, bounce a copy of this frame
596 	 * to him.
597 	 */
598 	if (ifp->if_bpf)
599 		bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
600 #endif
601 
602 	ifq_set_oactive(&ifp->if_snd);
603 
604 	/*
605 	 * Set a timeout in case the chip goes out to lunch.
606 	 */
607 	ifp->if_timer = 5;
608 }
609 
610 void
611 upl_init(void *xsc)
612 {
613 	struct upl_softc	*sc = xsc;
614 	struct ifnet		*ifp = &sc->sc_if;
615 	int			s;
616 
617 	if (usbd_is_dying(sc->sc_udev))
618 		return;
619 
620 	DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
621 
622 	s = splnet();
623 
624 	/* Init TX ring. */
625 	if (upl_tx_list_init(sc) == ENOBUFS) {
626 		printf("%s: tx list init failed\n", sc->sc_dev.dv_xname);
627 		splx(s);
628 		return;
629 	}
630 
631 	/* Init RX ring. */
632 	if (upl_rx_list_init(sc) == ENOBUFS) {
633 		printf("%s: rx list init failed\n", sc->sc_dev.dv_xname);
634 		splx(s);
635 		return;
636 	}
637 
638 	if (sc->sc_ep[UPL_ENDPT_RX] == NULL) {
639 		if (upl_openpipes(sc)) {
640 			splx(s);
641 			return;
642 		}
643 	}
644 
645 	ifp->if_flags |= IFF_RUNNING;
646 	ifq_clr_oactive(&ifp->if_snd);
647 
648 	splx(s);
649 }
650 
651 int
652 upl_openpipes(struct upl_softc *sc)
653 {
654 	struct upl_chain	*c;
655 	usbd_status		err;
656 	int			i;
657 
658 	/* Open RX and TX pipes. */
659 	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_RX],
660 	    USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_RX]);
661 	if (err) {
662 		printf("%s: open rx pipe failed: %s\n",
663 		    sc->sc_dev.dv_xname, usbd_errstr(err));
664 		return (EIO);
665 	}
666 	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_TX],
667 	    USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_TX]);
668 	if (err) {
669 		printf("%s: open tx pipe failed: %s\n",
670 		    sc->sc_dev.dv_xname, usbd_errstr(err));
671 		return (EIO);
672 	}
673 	err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ed[UPL_ENDPT_INTR],
674 	    USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_INTR], sc,
675 	    &sc->sc_ibuf, UPL_INTR_PKTLEN, upl_intr,
676 	    UPL_INTR_INTERVAL);
677 	if (err) {
678 		printf("%s: open intr pipe failed: %s\n",
679 		    sc->sc_dev.dv_xname, usbd_errstr(err));
680 		return (EIO);
681 	}
682 
683 
684 #if 1
685 	/* Start up the receive pipe. */
686 	for (i = 0; i < UPL_RX_LIST_CNT; i++) {
687 		c = &sc->sc_cdata.upl_rx_chain[i];
688 		usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX],
689 		    c, c->upl_buf, UPL_BUFSZ,
690 		    USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
691 		    upl_rxeof);
692 		usbd_transfer(c->upl_xfer);
693 	}
694 #endif
695 
696 	return (0);
697 }
698 
699 void
700 upl_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
701 {
702 	struct upl_softc	*sc = priv;
703 	struct ifnet		*ifp = &sc->sc_if;
704 	uByte			stat;
705 
706 	DPRINTFN(15,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
707 
708 	if (usbd_is_dying(sc->sc_udev))
709 		return;
710 
711 	if (!(ifp->if_flags & IFF_RUNNING))
712 		return;
713 
714 	if (status != USBD_NORMAL_COMPLETION) {
715 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
716 			return;
717 		}
718 		sc->sc_intr_errs++;
719 		if (usbd_ratecheck(&sc->sc_rx_notice)) {
720 			printf("%s: %u usb errors on intr: %s\n",
721 			    sc->sc_dev.dv_xname, sc->sc_rx_errs,
722 			    usbd_errstr(status));
723 			sc->sc_intr_errs = 0;
724 		}
725 		if (status == USBD_STALLED)
726 			usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]);
727 		return;
728 	}
729 
730 	stat = sc->sc_ibuf;
731 
732 	if (stat == 0)
733 		return;
734 
735 	DPRINTFN(10,("%s: %s: stat=0x%02x\n", sc->sc_dev.dv_xname,
736 		     __func__, stat));
737 
738 }
739 
740 int
741 upl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
742 {
743 	struct upl_softc	*sc = ifp->if_softc;
744 	struct ifreq		*ifr = (struct ifreq *)data;
745 	int			s, error = 0;
746 
747 	if (usbd_is_dying(sc->sc_udev))
748 		return (EIO);
749 
750 	DPRINTFN(5,("%s: %s: cmd=0x%08lx\n",
751 		    sc->sc_dev.dv_xname, __func__, command));
752 
753 	s = splnet();
754 
755 	switch(command) {
756 	case SIOCSIFADDR:
757 		ifp->if_flags |= IFF_UP;
758 		if (!(ifp->if_flags & IFF_RUNNING))
759 			upl_init(sc);
760 		break;
761 
762 	case SIOCSIFFLAGS:
763 		if (ifp->if_flags & IFF_UP) {
764 			if (ifp->if_flags & IFF_RUNNING)
765 				error = ENETRESET;
766 			else
767 				upl_init(sc);
768 		} else {
769 			if (ifp->if_flags & IFF_RUNNING)
770 				upl_stop(sc);
771 		}
772 		break;
773 
774 	case SIOCSIFMTU:
775 		if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
776 			error = EINVAL;
777 		else
778 			ifp->if_mtu = ifr->ifr_mtu;
779 		break;
780 
781 	default:
782 		error = ENOTTY;
783 	}
784 
785 	if (error == ENETRESET)
786 		error = 0;
787 
788 	splx(s);
789 	return (error);
790 }
791 
792 void
793 upl_watchdog(struct ifnet *ifp)
794 {
795 	struct upl_softc	*sc = ifp->if_softc;
796 
797 	DPRINTFN(5,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
798 
799 	if (usbd_is_dying(sc->sc_udev))
800 		return;
801 
802 	ifp->if_oerrors++;
803 	printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
804 
805 	upl_stop(sc);
806 	upl_init(sc);
807 
808 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
809 		upl_start(ifp);
810 }
811 
812 /*
813  * Stop the adapter and free any mbufs allocated to the
814  * RX and TX lists.
815  */
816 void
817 upl_stop(struct upl_softc *sc)
818 {
819 	usbd_status		err;
820 	struct ifnet		*ifp;
821 	int			i;
822 
823 	DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
824 
825 	ifp = &sc->sc_if;
826 	ifp->if_timer = 0;
827 	ifp->if_flags &= ~IFF_RUNNING;
828 	ifq_clr_oactive(&ifp->if_snd);
829 
830 	/* Stop transfers. */
831 	if (sc->sc_ep[UPL_ENDPT_RX] != NULL) {
832 		usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_RX]);
833 		err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_RX]);
834 		if (err) {
835 			printf("%s: close rx pipe failed: %s\n",
836 			sc->sc_dev.dv_xname, usbd_errstr(err));
837 		}
838 		sc->sc_ep[UPL_ENDPT_RX] = NULL;
839 	}
840 
841 	if (sc->sc_ep[UPL_ENDPT_TX] != NULL) {
842 		usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_TX]);
843 		err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_TX]);
844 		if (err) {
845 			printf("%s: close tx pipe failed: %s\n",
846 			    sc->sc_dev.dv_xname, usbd_errstr(err));
847 		}
848 		sc->sc_ep[UPL_ENDPT_TX] = NULL;
849 	}
850 
851 	if (sc->sc_ep[UPL_ENDPT_INTR] != NULL) {
852 		usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_INTR]);
853 		err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_INTR]);
854 		if (err) {
855 			printf("%s: close intr pipe failed: %s\n",
856 			    sc->sc_dev.dv_xname, usbd_errstr(err));
857 		}
858 		sc->sc_ep[UPL_ENDPT_INTR] = NULL;
859 	}
860 
861 	/* Free RX resources. */
862 	for (i = 0; i < UPL_RX_LIST_CNT; i++) {
863 		if (sc->sc_cdata.upl_rx_chain[i].upl_mbuf != NULL) {
864 			m_freem(sc->sc_cdata.upl_rx_chain[i].upl_mbuf);
865 			sc->sc_cdata.upl_rx_chain[i].upl_mbuf = NULL;
866 		}
867 		if (sc->sc_cdata.upl_rx_chain[i].upl_xfer != NULL) {
868 			usbd_free_xfer(sc->sc_cdata.upl_rx_chain[i].upl_xfer);
869 			sc->sc_cdata.upl_rx_chain[i].upl_xfer = NULL;
870 		}
871 	}
872 
873 	/* Free TX resources. */
874 	for (i = 0; i < UPL_TX_LIST_CNT; i++) {
875 		if (sc->sc_cdata.upl_tx_chain[i].upl_mbuf != NULL) {
876 			m_freem(sc->sc_cdata.upl_tx_chain[i].upl_mbuf);
877 			sc->sc_cdata.upl_tx_chain[i].upl_mbuf = NULL;
878 		}
879 		if (sc->sc_cdata.upl_tx_chain[i].upl_xfer != NULL) {
880 			usbd_free_xfer(sc->sc_cdata.upl_tx_chain[i].upl_xfer);
881 			sc->sc_cdata.upl_tx_chain[i].upl_xfer = NULL;
882 		}
883 	}
884 }
885 
886 int
887 upl_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
888 	   struct rtentry *rt0)
889 {
890 	return (if_enqueue(ifp, m));
891 }
892