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