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