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