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