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