1 /*	$OpenBSD: if_cue.c,v 1.26 2005/07/02 22:21:12 brad Exp $ */
2 /*	$NetBSD: if_cue.c,v 1.40 2002/07/11 21:14:26 augustss Exp $	*/
3 /*
4  * Copyright (c) 1997, 1998, 1999, 2000
5  *	Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by Bill Paul.
18  * 4. Neither the name of the author nor the names of any co-contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  * THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * $FreeBSD: src/sys/dev/usb/if_cue.c,v 1.4 2000/01/16 22:45:06 wpaul Exp $
35  */
36 
37 /*
38  * CATC USB-EL1210A USB to ethernet driver. Used in the CATC Netmate
39  * adapters and others.
40  *
41  * Written by Bill Paul <wpaul@ee.columbia.edu>
42  * Electrical Engineering Department
43  * Columbia University, New York City
44  */
45 
46 /*
47  * The CATC USB-EL1210A provides USB ethernet support at 10Mbps. The
48  * RX filter uses a 512-bit multicast hash table, single perfect entry
49  * for the station address, and promiscuous mode. Unlike the ADMtek
50  * and KLSI chips, the CATC ASIC supports read and write combining
51  * mode where multiple packets can be transferred using a single bulk
52  * transaction, which helps performance a great deal.
53  */
54 
55 /*
56  * Ported to NetBSD and somewhat rewritten by Lennart Augustsson.
57  */
58 
59 #if defined(__NetBSD__)
60 #include "opt_inet.h"
61 #include "opt_ns.h"
62 #include "bpfilter.h"
63 #include "rnd.h"
64 #elif defined(__OpenBSD__)
65 #include "bpfilter.h"
66 #endif /* defined(__OpenBSD__) */
67 
68 #include <sys/param.h>
69 #include <sys/systm.h>
70 #if !defined(__OpenBSD__)
71 #include <sys/callout.h>
72 #endif
73 #include <sys/sockio.h>
74 #include <sys/mbuf.h>
75 #include <sys/malloc.h>
76 #include <sys/kernel.h>
77 #include <sys/socket.h>
78 
79 #include <sys/device.h>
80 #if NRND > 0
81 #include <sys/rnd.h>
82 #endif
83 
84 #include <net/if.h>
85 #if defined(__NetBSD__)
86 #include <net/if_arp.h>
87 #endif
88 #include <net/if_dl.h>
89 
90 #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
91 
92 #if NBPFILTER > 0
93 #include <net/bpf.h>
94 #endif
95 
96 #if defined(__NetBSD__)
97 #include <net/if_ether.h>
98 #ifdef INET
99 #include <netinet/in.h>
100 #include <netinet/if_inarp.h>
101 #endif
102 #endif /* defined(__NetBSD__) */
103 
104 #if defined(__OpenBSD__)
105 #ifdef INET
106 #include <netinet/in.h>
107 #include <netinet/in_systm.h>
108 #include <netinet/in_var.h>
109 #include <netinet/ip.h>
110 #include <netinet/if_ether.h>
111 #endif
112 #endif /* defined(__OpenBSD__) */
113 
114 #include <dev/usb/usb.h>
115 #include <dev/usb/usbdi.h>
116 #include <dev/usb/usbdi_util.h>
117 #include <dev/usb/usbdevs.h>
118 
119 #include <dev/usb/if_cuereg.h>
120 
121 #ifdef CUE_DEBUG
122 #define DPRINTF(x)	do { if (cuedebug) logprintf x; } while (0)
123 #define DPRINTFN(n,x)	do { if (cuedebug >= (n)) logprintf x; } while (0)
124 int	cuedebug = 0;
125 #else
126 #define DPRINTF(x)
127 #define DPRINTFN(n,x)
128 #endif
129 
130 /*
131  * Various supported device vendors/products.
132  */
133 Static struct usb_devno cue_devs[] = {
134 	{ USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE },
135 	{ USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE2 },
136 	{ USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTLINK },
137 	/* Belkin F5U111 adapter covered by NETMATE entry */
138 };
139 #define cue_lookup(v, p) (usb_lookup(cue_devs, v, p))
140 
141 USB_DECLARE_DRIVER_CLASS(cue, DV_IFNET);
142 
143 Static int cue_open_pipes(struct cue_softc *);
144 Static int cue_tx_list_init(struct cue_softc *);
145 Static int cue_rx_list_init(struct cue_softc *);
146 Static int cue_newbuf(struct cue_softc *, struct cue_chain *, struct mbuf *);
147 Static int cue_send(struct cue_softc *, struct mbuf *, int);
148 Static void cue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
149 Static void cue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
150 Static void cue_tick(void *);
151 Static void cue_tick_task(void *);
152 Static void cue_start(struct ifnet *);
153 Static int cue_ioctl(struct ifnet *, u_long, caddr_t);
154 Static void cue_init(void *);
155 Static void cue_stop(struct cue_softc *);
156 Static void cue_watchdog(struct ifnet *);
157 
158 Static void cue_setmulti(struct cue_softc *);
159 Static void cue_reset(struct cue_softc *);
160 
161 Static int cue_csr_read_1(struct cue_softc *, int);
162 Static int cue_csr_write_1(struct cue_softc *, int, int);
163 Static int cue_csr_read_2(struct cue_softc *, int);
164 #if 0
165 Static int cue_csr_write_2(struct cue_softc *, int, int);
166 #endif
167 Static int cue_mem(struct cue_softc *, int, int, void *, int);
168 Static int cue_getmac(struct cue_softc *, void *);
169 
170 #define CUE_SETBIT(sc, reg, x)				\
171 	cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) | (x))
172 
173 #define CUE_CLRBIT(sc, reg, x)				\
174 	cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) & ~(x))
175 
176 Static int
cue_csr_read_1(struct cue_softc * sc,int reg)177 cue_csr_read_1(struct cue_softc *sc, int reg)
178 {
179 	usb_device_request_t	req;
180 	usbd_status		err;
181 	u_int8_t		val = 0;
182 
183 	if (sc->cue_dying)
184 		return (0);
185 
186 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
187 	req.bRequest = CUE_CMD_READREG;
188 	USETW(req.wValue, 0);
189 	USETW(req.wIndex, reg);
190 	USETW(req.wLength, 1);
191 
192 	err = usbd_do_request(sc->cue_udev, &req, &val);
193 
194 	if (err) {
195 		DPRINTF(("%s: cue_csr_read_1: reg=0x%x err=%s\n",
196 			 USBDEVNAME(sc->cue_dev), reg, usbd_errstr(err)));
197 		return (0);
198 	}
199 
200 	DPRINTFN(10,("%s: cue_csr_read_1 reg=0x%x val=0x%x\n",
201 		     USBDEVNAME(sc->cue_dev), reg, val));
202 
203 	return (val);
204 }
205 
206 Static int
cue_csr_read_2(struct cue_softc * sc,int reg)207 cue_csr_read_2(struct cue_softc *sc, int reg)
208 {
209 	usb_device_request_t	req;
210 	usbd_status		err;
211 	uWord			val;
212 
213 	if (sc->cue_dying)
214 		return (0);
215 
216 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
217 	req.bRequest = CUE_CMD_READREG;
218 	USETW(req.wValue, 0);
219 	USETW(req.wIndex, reg);
220 	USETW(req.wLength, 2);
221 
222 	err = usbd_do_request(sc->cue_udev, &req, &val);
223 
224 	DPRINTFN(10,("%s: cue_csr_read_2 reg=0x%x val=0x%x\n",
225 		     USBDEVNAME(sc->cue_dev), reg, UGETW(val)));
226 
227 	if (err) {
228 		DPRINTF(("%s: cue_csr_read_2: reg=0x%x err=%s\n",
229 			 USBDEVNAME(sc->cue_dev), reg, usbd_errstr(err)));
230 		return (0);
231 	}
232 
233 	return (UGETW(val));
234 }
235 
236 Static int
cue_csr_write_1(struct cue_softc * sc,int reg,int val)237 cue_csr_write_1(struct cue_softc *sc, int reg, int val)
238 {
239 	usb_device_request_t	req;
240 	usbd_status		err;
241 
242 	if (sc->cue_dying)
243 		return (0);
244 
245 	DPRINTFN(10,("%s: cue_csr_write_1 reg=0x%x val=0x%x\n",
246 		     USBDEVNAME(sc->cue_dev), reg, val));
247 
248 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
249 	req.bRequest = CUE_CMD_WRITEREG;
250 	USETW(req.wValue, val);
251 	USETW(req.wIndex, reg);
252 	USETW(req.wLength, 0);
253 
254 	err = usbd_do_request(sc->cue_udev, &req, NULL);
255 
256 	if (err) {
257 		DPRINTF(("%s: cue_csr_write_1: reg=0x%x err=%s\n",
258 			 USBDEVNAME(sc->cue_dev), reg, usbd_errstr(err)));
259 		return (-1);
260 	}
261 
262 	DPRINTFN(20,("%s: cue_csr_write_1, after reg=0x%x val=0x%x\n",
263 		     USBDEVNAME(sc->cue_dev), reg, cue_csr_read_1(sc, reg)));
264 
265 	return (0);
266 }
267 
268 #if 0
269 Static int
270 cue_csr_write_2(struct cue_softc *sc, int reg, int aval)
271 {
272 	usb_device_request_t	req;
273 	usbd_status		err;
274 	uWord			val;
275 	int			s;
276 
277 	if (sc->cue_dying)
278 		return (0);
279 
280 	DPRINTFN(10,("%s: cue_csr_write_2 reg=0x%x val=0x%x\n",
281 		     USBDEVNAME(sc->cue_dev), reg, aval));
282 
283 	USETW(val, aval);
284 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
285 	req.bRequest = CUE_CMD_WRITEREG;
286 	USETW(req.wValue, val);
287 	USETW(req.wIndex, reg);
288 	USETW(req.wLength, 0);
289 
290 	err = usbd_do_request(sc->cue_udev, &req, NULL);
291 
292 	if (err) {
293 		DPRINTF(("%s: cue_csr_write_2: reg=0x%x err=%s\n",
294 			 USBDEVNAME(sc->cue_dev), reg, usbd_errstr(err)));
295 		return (-1);
296 	}
297 
298 	return (0);
299 }
300 #endif
301 
302 Static int
cue_mem(struct cue_softc * sc,int cmd,int addr,void * buf,int len)303 cue_mem(struct cue_softc *sc, int cmd, int addr, void *buf, int len)
304 {
305 	usb_device_request_t	req;
306 	usbd_status		err;
307 
308 	DPRINTFN(10,("%s: cue_mem cmd=0x%x addr=0x%x len=%d\n",
309 		     USBDEVNAME(sc->cue_dev), cmd, addr, len));
310 
311 	if (cmd == CUE_CMD_READSRAM)
312 		req.bmRequestType = UT_READ_VENDOR_DEVICE;
313 	else
314 		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
315 	req.bRequest = cmd;
316 	USETW(req.wValue, 0);
317 	USETW(req.wIndex, addr);
318 	USETW(req.wLength, len);
319 
320 	err = usbd_do_request(sc->cue_udev, &req, buf);
321 
322 	if (err) {
323 		DPRINTF(("%s: cue_csr_mem: addr=0x%x err=%s\n",
324 			 USBDEVNAME(sc->cue_dev), addr, usbd_errstr(err)));
325 		return (-1);
326 	}
327 
328 	return (0);
329 }
330 
331 Static int
cue_getmac(struct cue_softc * sc,void * buf)332 cue_getmac(struct cue_softc *sc, void *buf)
333 {
334 	usb_device_request_t	req;
335 	usbd_status		err;
336 
337 	DPRINTFN(10,("%s: cue_getmac\n", USBDEVNAME(sc->cue_dev)));
338 
339 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
340 	req.bRequest = CUE_CMD_GET_MACADDR;
341 	USETW(req.wValue, 0);
342 	USETW(req.wIndex, 0);
343 	USETW(req.wLength, ETHER_ADDR_LEN);
344 
345 	err = usbd_do_request(sc->cue_udev, &req, buf);
346 
347 	if (err) {
348 		printf("%s: read MAC address failed\n",
349 		       USBDEVNAME(sc->cue_dev));
350 		return (-1);
351 	}
352 
353 	return (0);
354 }
355 
356 #define CUE_BITS	9
357 
358 Static void
cue_setmulti(struct cue_softc * sc)359 cue_setmulti(struct cue_softc *sc)
360 {
361 	struct ifnet		*ifp;
362 	struct ether_multi	*enm;
363 	struct ether_multistep	step;
364 	u_int32_t		h, i;
365 
366 	ifp = GET_IFP(sc);
367 
368 	DPRINTFN(2,("%s: cue_setmulti if_flags=0x%x\n",
369 		    USBDEVNAME(sc->cue_dev), ifp->if_flags));
370 
371 	if (ifp->if_flags & IFF_PROMISC) {
372 allmulti:
373 		ifp->if_flags |= IFF_ALLMULTI;
374 		for (i = 0; i < CUE_MCAST_TABLE_LEN; i++)
375 			sc->cue_mctab[i] = 0xFF;
376 		cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
377 		    &sc->cue_mctab, CUE_MCAST_TABLE_LEN);
378 		return;
379 	}
380 
381 	/* first, zot all the existing hash bits */
382 	for (i = 0; i < CUE_MCAST_TABLE_LEN; i++)
383 		sc->cue_mctab[i] = 0;
384 
385 	/* now program new ones */
386 #if defined(__NetBSD__)
387 	ETHER_FIRST_MULTI(step, &sc->cue_ec, enm);
388 #else
389 	ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
390 #endif
391 	while (enm != NULL) {
392 		if (memcmp(enm->enm_addrlo,
393 		    enm->enm_addrhi, ETHER_ADDR_LEN) != 0)
394 			goto allmulti;
395 
396 		h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) &
397 		    ((1 << CUE_BITS) - 1);
398 		sc->cue_mctab[h >> 3] |= 1 << (h & 0x7);
399 		ETHER_NEXT_MULTI(step, enm);
400 	}
401 
402 	ifp->if_flags &= ~IFF_ALLMULTI;
403 
404 	/*
405 	 * Also include the broadcast address in the filter
406 	 * so we can receive broadcast frames.
407 	 */
408 	if (ifp->if_flags & IFF_BROADCAST) {
409 		h = ether_crc32_le(etherbroadcastaddr, ETHER_ADDR_LEN) &
410 		    ((1 << CUE_BITS) - 1);
411 		sc->cue_mctab[h >> 3] |= 1 << (h & 0x7);
412 	}
413 
414 	cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
415 	    &sc->cue_mctab, CUE_MCAST_TABLE_LEN);
416 }
417 
418 Static void
cue_reset(struct cue_softc * sc)419 cue_reset(struct cue_softc *sc)
420 {
421 	usb_device_request_t	req;
422 	usbd_status		err;
423 
424 	DPRINTFN(2,("%s: cue_reset\n", USBDEVNAME(sc->cue_dev)));
425 
426 	if (sc->cue_dying)
427 		return;
428 
429 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
430 	req.bRequest = CUE_CMD_RESET;
431 	USETW(req.wValue, 0);
432 	USETW(req.wIndex, 0);
433 	USETW(req.wLength, 0);
434 
435 	err = usbd_do_request(sc->cue_udev, &req, NULL);
436 
437 	if (err)
438 		printf("%s: reset failed\n", USBDEVNAME(sc->cue_dev));
439 
440 	/* Wait a little while for the chip to get its brains in order. */
441 	usbd_delay_ms(sc->cue_udev, 1);
442 }
443 
444 /*
445  * Probe for a CATC chip.
446  */
USB_MATCH(cue)447 USB_MATCH(cue)
448 {
449 	USB_MATCH_START(cue, uaa);
450 
451 	if (uaa->iface != NULL)
452 		return (UMATCH_NONE);
453 
454 	return (cue_lookup(uaa->vendor, uaa->product) != NULL ?
455 		UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
456 }
457 
458 /*
459  * Attach the interface. Allocate softc structures, do ifmedia
460  * setup and ethernet/BPF attach.
461  */
USB_ATTACH(cue)462 USB_ATTACH(cue)
463 {
464 	USB_ATTACH_START(cue, sc, uaa);
465 	char			devinfo[1024];
466 	int			s;
467 	u_char			eaddr[ETHER_ADDR_LEN];
468 	usbd_device_handle	dev = uaa->device;
469 	usbd_interface_handle	iface;
470 	usbd_status		err;
471 	struct ifnet		*ifp;
472 	usb_interface_descriptor_t	*id;
473 	usb_endpoint_descriptor_t	*ed;
474 	int			i;
475 
476 	DPRINTFN(5,(" : cue_attach: sc=%p, dev=%p", sc, dev));
477 
478 	usbd_devinfo(dev, 0, devinfo, sizeof devinfo);
479 	USB_ATTACH_SETUP;
480 	printf("%s: %s\n", USBDEVNAME(sc->cue_dev), devinfo);
481 
482 	err = usbd_set_config_no(dev, CUE_CONFIG_NO, 1);
483 	if (err) {
484 		printf("%s: setting config no failed\n",
485 		    USBDEVNAME(sc->cue_dev));
486 		USB_ATTACH_ERROR_RETURN;
487 	}
488 
489 	sc->cue_udev = dev;
490 	sc->cue_product = uaa->product;
491 	sc->cue_vendor = uaa->vendor;
492 
493 	usb_init_task(&sc->cue_tick_task, cue_tick_task, sc);
494 	usb_init_task(&sc->cue_stop_task, (void (*)(void *))cue_stop, sc);
495 
496 	err = usbd_device2interface_handle(dev, CUE_IFACE_IDX, &iface);
497 	if (err) {
498 		printf("%s: getting interface handle failed\n",
499 		    USBDEVNAME(sc->cue_dev));
500 		USB_ATTACH_ERROR_RETURN;
501 	}
502 
503 	sc->cue_iface = iface;
504 	id = usbd_get_interface_descriptor(iface);
505 
506 	/* Find endpoints. */
507 	for (i = 0; i < id->bNumEndpoints; i++) {
508 		ed = usbd_interface2endpoint_descriptor(iface, i);
509 		if (ed == NULL) {
510 			printf("%s: couldn't get ep %d\n",
511 			    USBDEVNAME(sc->cue_dev), i);
512 			USB_ATTACH_ERROR_RETURN;
513 		}
514 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
515 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
516 			sc->cue_ed[CUE_ENDPT_RX] = ed->bEndpointAddress;
517 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
518 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
519 			sc->cue_ed[CUE_ENDPT_TX] = ed->bEndpointAddress;
520 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
521 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
522 			sc->cue_ed[CUE_ENDPT_INTR] = ed->bEndpointAddress;
523 		}
524 	}
525 
526 #if 0
527 	/* Reset the adapter. */
528 	cue_reset(sc);
529 #endif
530 	/*
531 	 * Get station address.
532 	 */
533 	cue_getmac(sc, &eaddr);
534 
535 	s = splnet();
536 
537 	/*
538 	 * A CATC chip was detected. Inform the world.
539 	 */
540 	printf("%s: address %s\n", USBDEVNAME(sc->cue_dev),
541 	    ether_sprintf(eaddr));
542 
543 #if defined(__OpenBSD__)
544 	bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
545 #endif
546 
547 	/* Initialize interface info.*/
548 	ifp = GET_IFP(sc);
549 	ifp->if_softc = sc;
550 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
551 	ifp->if_ioctl = cue_ioctl;
552 	ifp->if_start = cue_start;
553 	ifp->if_watchdog = cue_watchdog;
554 	strlcpy(ifp->if_xname, USBDEVNAME(sc->cue_dev), IFNAMSIZ);
555 
556 	IFQ_SET_READY(&ifp->if_snd);
557 
558 	/* Attach the interface. */
559 	if_attach(ifp);
560 	Ether_ifattach(ifp, eaddr);
561 #if NRND > 0
562 	rnd_attach_source(&sc->rnd_source, USBDEVNAME(sc->cue_dev),
563 	    RND_TYPE_NET, 0);
564 #endif
565 
566 	usb_callout_init(sc->cue_stat_ch);
567 
568 	sc->cue_attached = 1;
569 	splx(s);
570 
571 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cue_udev,
572 	    USBDEV(sc->cue_dev));
573 
574 	USB_ATTACH_SUCCESS_RETURN;
575 }
576 
USB_DETACH(cue)577 USB_DETACH(cue)
578 {
579 	USB_DETACH_START(cue, sc);
580 	struct ifnet		*ifp = GET_IFP(sc);
581 	int			s;
582 
583 	DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->cue_dev), __func__));
584 
585 	usb_uncallout(sc->cue_stat_ch, cue_tick, sc);
586 	/*
587 	 * Remove any pending task.  It cannot be executing because it run
588 	 * in the same thread as detach.
589 	 */
590 	usb_rem_task(sc->cue_udev, &sc->cue_tick_task);
591 	usb_rem_task(sc->cue_udev, &sc->cue_stop_task);
592 
593 	if (!sc->cue_attached) {
594 		/* Detached before attached finished, so just bail out. */
595 		return (0);
596 	}
597 
598 	s = splusb();
599 
600 	if (ifp->if_flags & IFF_RUNNING)
601 		cue_stop(sc);
602 
603 #if defined(__NetBSD__)
604 #if NRND > 0
605 	rnd_detach_source(&sc->rnd_source);
606 #endif
607 #endif /* __NetBSD__ */
608 	ether_ifdetach(ifp);
609 
610 	if_detach(ifp);
611 
612 #ifdef DIAGNOSTIC
613 	if (sc->cue_ep[CUE_ENDPT_TX] != NULL ||
614 	    sc->cue_ep[CUE_ENDPT_RX] != NULL ||
615 	    sc->cue_ep[CUE_ENDPT_INTR] != NULL)
616 		printf("%s: detach has active endpoints\n",
617 		       USBDEVNAME(sc->cue_dev));
618 #endif
619 
620 	sc->cue_attached = 0;
621 	splx(s);
622 
623 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->cue_udev,
624 	    USBDEV(sc->cue_dev));
625 
626 	return (0);
627 }
628 
629 int
cue_activate(device_ptr_t self,enum devact act)630 cue_activate(device_ptr_t self, enum devact act)
631 {
632 	struct cue_softc *sc = (struct cue_softc *)self;
633 
634 	DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->cue_dev), __func__));
635 
636 	switch (act) {
637 	case DVACT_ACTIVATE:
638 		return (EOPNOTSUPP);
639 		break;
640 
641 	case DVACT_DEACTIVATE:
642 		/* Deactivate the interface. */
643 		if_deactivate(&sc->cue_ec.ec_if);
644 		sc->cue_dying = 1;
645 		break;
646 	}
647 	return (0);
648 }
649 
650 /*
651  * Initialize an RX descriptor and attach an MBUF cluster.
652  */
653 Static int
cue_newbuf(struct cue_softc * sc,struct cue_chain * c,struct mbuf * m)654 cue_newbuf(struct cue_softc *sc, struct cue_chain *c, struct mbuf *m)
655 {
656 	struct mbuf		*m_new = NULL;
657 
658 	if (m == NULL) {
659 		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
660 		if (m_new == NULL) {
661 			printf("%s: no memory for rx list "
662 			    "-- packet dropped!\n", USBDEVNAME(sc->cue_dev));
663 			return (ENOBUFS);
664 		}
665 
666 		MCLGET(m_new, M_DONTWAIT);
667 		if (!(m_new->m_flags & M_EXT)) {
668 			printf("%s: no memory for rx list "
669 			    "-- packet dropped!\n", USBDEVNAME(sc->cue_dev));
670 			m_freem(m_new);
671 			return (ENOBUFS);
672 		}
673 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
674 	} else {
675 		m_new = m;
676 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
677 		m_new->m_data = m_new->m_ext.ext_buf;
678 	}
679 
680 	m_adj(m_new, ETHER_ALIGN);
681 	c->cue_mbuf = m_new;
682 
683 	return (0);
684 }
685 
686 Static int
cue_rx_list_init(struct cue_softc * sc)687 cue_rx_list_init(struct cue_softc *sc)
688 {
689 	struct cue_cdata	*cd;
690 	struct cue_chain	*c;
691 	int			i;
692 
693 	cd = &sc->cue_cdata;
694 	for (i = 0; i < CUE_RX_LIST_CNT; i++) {
695 		c = &cd->cue_rx_chain[i];
696 		c->cue_sc = sc;
697 		c->cue_idx = i;
698 		if (cue_newbuf(sc, c, NULL) == ENOBUFS)
699 			return (ENOBUFS);
700 		if (c->cue_xfer == NULL) {
701 			c->cue_xfer = usbd_alloc_xfer(sc->cue_udev);
702 			if (c->cue_xfer == NULL)
703 				return (ENOBUFS);
704 			c->cue_buf = usbd_alloc_buffer(c->cue_xfer, CUE_BUFSZ);
705 			if (c->cue_buf == NULL) {
706 				usbd_free_xfer(c->cue_xfer);
707 				return (ENOBUFS);
708 			}
709 		}
710 	}
711 
712 	return (0);
713 }
714 
715 Static int
cue_tx_list_init(struct cue_softc * sc)716 cue_tx_list_init(struct cue_softc *sc)
717 {
718 	struct cue_cdata	*cd;
719 	struct cue_chain	*c;
720 	int			i;
721 
722 	cd = &sc->cue_cdata;
723 	for (i = 0; i < CUE_TX_LIST_CNT; i++) {
724 		c = &cd->cue_tx_chain[i];
725 		c->cue_sc = sc;
726 		c->cue_idx = i;
727 		c->cue_mbuf = NULL;
728 		if (c->cue_xfer == NULL) {
729 			c->cue_xfer = usbd_alloc_xfer(sc->cue_udev);
730 			if (c->cue_xfer == NULL)
731 				return (ENOBUFS);
732 			c->cue_buf = usbd_alloc_buffer(c->cue_xfer, CUE_BUFSZ);
733 			if (c->cue_buf == NULL) {
734 				usbd_free_xfer(c->cue_xfer);
735 				return (ENOBUFS);
736 			}
737 		}
738 	}
739 
740 	return (0);
741 }
742 
743 /*
744  * A frame has been uploaded: pass the resulting mbuf chain up to
745  * the higher level protocols.
746  */
747 Static void
cue_rxeof(usbd_xfer_handle xfer,usbd_private_handle priv,usbd_status status)748 cue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
749 {
750 	struct cue_chain	*c = priv;
751 	struct cue_softc	*sc = c->cue_sc;
752 	struct ifnet		*ifp = GET_IFP(sc);
753 	struct mbuf		*m;
754 	int			total_len = 0;
755 	u_int16_t		len;
756 	int			s;
757 
758 	DPRINTFN(10,("%s: %s: enter status=%d\n", USBDEVNAME(sc->cue_dev),
759 		     __func__, status));
760 
761 	if (sc->cue_dying)
762 		return;
763 
764 	if (!(ifp->if_flags & IFF_RUNNING))
765 		return;
766 
767 	if (status != USBD_NORMAL_COMPLETION) {
768 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
769 			return;
770 		sc->cue_rx_errs++;
771 		if (usbd_ratecheck(&sc->cue_rx_notice)) {
772 			printf("%s: %u usb errors on rx: %s\n",
773 			    USBDEVNAME(sc->cue_dev), sc->cue_rx_errs,
774 			    usbd_errstr(status));
775 			sc->cue_rx_errs = 0;
776 		}
777 		if (status == USBD_STALLED)
778 			usbd_clear_endpoint_stall(sc->cue_ep[CUE_ENDPT_RX]);
779 		goto done;
780 	}
781 
782 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
783 
784 	memcpy(mtod(c->cue_mbuf, char *), c->cue_buf, total_len);
785 
786 	m = c->cue_mbuf;
787 	len = UGETW(mtod(m, u_int8_t *));
788 
789 	/* No errors; receive the packet. */
790 	total_len = len;
791 
792 	if (len < sizeof(struct ether_header)) {
793 		ifp->if_ierrors++;
794 		goto done;
795 	}
796 
797 	ifp->if_ipackets++;
798 	m_adj(m, sizeof(u_int16_t));
799 	m->m_pkthdr.len = m->m_len = total_len;
800 
801 	m->m_pkthdr.rcvif = ifp;
802 
803 	s = splnet();
804 
805 	/* XXX ugly */
806 	if (cue_newbuf(sc, c, NULL) == ENOBUFS) {
807 		ifp->if_ierrors++;
808 		goto done1;
809 	}
810 
811 #if NBPFILTER > 0
812 	/*
813 	 * Handle BPF listeners. Let the BPF user see the packet, but
814 	 * don't pass it up to the ether_input() layer unless it's
815 	 * a broadcast packet, multicast packet, matches our ethernet
816 	 * address or the interface is in promiscuous mode.
817 	 */
818 	if (ifp->if_bpf)
819 		BPF_MTAP(ifp, m);
820 #endif
821 
822 	DPRINTFN(10,("%s: %s: deliver %d\n", USBDEVNAME(sc->cue_dev),
823 		    __func__, m->m_len));
824 	IF_INPUT(ifp, m);
825  done1:
826 	splx(s);
827 
828 done:
829 	/* Setup new transfer. */
830 	usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_RX],
831 	    c, c->cue_buf, CUE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
832 	    USBD_NO_TIMEOUT, cue_rxeof);
833 	usbd_transfer(c->cue_xfer);
834 
835 	DPRINTFN(10,("%s: %s: start rx\n", USBDEVNAME(sc->cue_dev),
836 		    __func__));
837 }
838 
839 /*
840  * A frame was downloaded to the chip. It's safe for us to clean up
841  * the list buffers.
842  */
843 Static void
cue_txeof(usbd_xfer_handle xfer,usbd_private_handle priv,usbd_status status)844 cue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
845 {
846 	struct cue_chain	*c = priv;
847 	struct cue_softc	*sc = c->cue_sc;
848 	struct ifnet		*ifp = GET_IFP(sc);
849 	int			s;
850 
851 	if (sc->cue_dying)
852 		return;
853 
854 	s = splnet();
855 
856 	DPRINTFN(10,("%s: %s: enter status=%d\n", USBDEVNAME(sc->cue_dev),
857 		    __func__, status));
858 
859 	ifp->if_timer = 0;
860 	ifp->if_flags &= ~IFF_OACTIVE;
861 
862 	if (status != USBD_NORMAL_COMPLETION) {
863 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
864 			splx(s);
865 			return;
866 		}
867 		ifp->if_oerrors++;
868 		printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cue_dev),
869 		    usbd_errstr(status));
870 		if (status == USBD_STALLED)
871 			usbd_clear_endpoint_stall(sc->cue_ep[CUE_ENDPT_TX]);
872 		splx(s);
873 		return;
874 	}
875 
876 	ifp->if_opackets++;
877 
878 	m_freem(c->cue_mbuf);
879 	c->cue_mbuf = NULL;
880 
881 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
882 		cue_start(ifp);
883 
884 	splx(s);
885 }
886 
887 Static void
cue_tick(void * xsc)888 cue_tick(void *xsc)
889 {
890 	struct cue_softc	*sc = xsc;
891 
892 	if (sc == NULL)
893 		return;
894 
895 	if (sc->cue_dying)
896 		return;
897 
898 	DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->cue_dev), __func__));
899 
900 	/* Perform statistics update in process context. */
901 	usb_add_task(sc->cue_udev, &sc->cue_tick_task);
902 }
903 
904 Static void
cue_tick_task(void * xsc)905 cue_tick_task(void *xsc)
906 {
907 	struct cue_softc	*sc = xsc;
908 	struct ifnet		*ifp;
909 
910 	if (sc->cue_dying)
911 		return;
912 
913 	DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->cue_dev), __func__));
914 
915 	ifp = GET_IFP(sc);
916 
917 	ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_SINGLECOLL);
918 	ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_MULTICOLL);
919 	ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_EXCESSCOLL);
920 
921 	if (cue_csr_read_2(sc, CUE_RX_FRAMEERR))
922 		ifp->if_ierrors++;
923 }
924 
925 Static int
cue_send(struct cue_softc * sc,struct mbuf * m,int idx)926 cue_send(struct cue_softc *sc, struct mbuf *m, int idx)
927 {
928 	int			total_len;
929 	struct cue_chain	*c;
930 	usbd_status		err;
931 
932 	c = &sc->cue_cdata.cue_tx_chain[idx];
933 
934 	/*
935 	 * Copy the mbuf data into a contiguous buffer, leaving two
936 	 * bytes at the beginning to hold the frame length.
937 	 */
938 	m_copydata(m, 0, m->m_pkthdr.len, c->cue_buf + 2);
939 	c->cue_mbuf = m;
940 
941 	total_len = m->m_pkthdr.len + 2;
942 
943 	DPRINTFN(10,("%s: %s: total_len=%d\n",
944 		     USBDEVNAME(sc->cue_dev), __func__, total_len));
945 
946 	/* The first two bytes are the frame length */
947 	c->cue_buf[0] = (u_int8_t)m->m_pkthdr.len;
948 	c->cue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8);
949 
950 	/* XXX 10000 */
951 	usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_TX],
952 	    c, c->cue_buf, total_len, USBD_NO_COPY, 10000, cue_txeof);
953 
954 	/* Transmit */
955 	err = usbd_transfer(c->cue_xfer);
956 	if (err != USBD_IN_PROGRESS) {
957 		printf("%s: cue_send error=%s\n", USBDEVNAME(sc->cue_dev),
958 		       usbd_errstr(err));
959 		/* Stop the interface from process context. */
960 		usb_add_task(sc->cue_udev, &sc->cue_stop_task);
961 		return (EIO);
962 	}
963 
964 	sc->cue_cdata.cue_tx_cnt++;
965 
966 	return (0);
967 }
968 
969 Static void
cue_start(struct ifnet * ifp)970 cue_start(struct ifnet *ifp)
971 {
972 	struct cue_softc	*sc = ifp->if_softc;
973 	struct mbuf		*m_head = NULL;
974 
975 	if (sc->cue_dying)
976 		return;
977 
978 	DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->cue_dev),__func__));
979 
980 	if (ifp->if_flags & IFF_OACTIVE)
981 		return;
982 
983 	IFQ_POLL(&ifp->if_snd, m_head);
984 	if (m_head == NULL)
985 		return;
986 
987 	if (cue_send(sc, m_head, 0)) {
988 		ifp->if_flags |= IFF_OACTIVE;
989 		return;
990 	}
991 
992 	IFQ_DEQUEUE(&ifp->if_snd, m_head);
993 
994 #if NBPFILTER > 0
995 	/*
996 	 * If there's a BPF listener, bounce a copy of this frame
997 	 * to him.
998 	 */
999 	if (ifp->if_bpf)
1000 		BPF_MTAP(ifp, m_head);
1001 #endif
1002 
1003 	ifp->if_flags |= IFF_OACTIVE;
1004 
1005 	/*
1006 	 * Set a timeout in case the chip goes out to lunch.
1007 	 */
1008 	ifp->if_timer = 5;
1009 }
1010 
1011 Static void
cue_init(void * xsc)1012 cue_init(void *xsc)
1013 {
1014 	struct cue_softc	*sc = xsc;
1015 	struct ifnet		*ifp = GET_IFP(sc);
1016 	int			i, s, ctl;
1017 	u_char			*eaddr;
1018 
1019 	if (sc->cue_dying)
1020 		return;
1021 
1022 	DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->cue_dev),__func__));
1023 
1024 	if (ifp->if_flags & IFF_RUNNING)
1025 		return;
1026 
1027 	s = splnet();
1028 
1029 	/*
1030 	 * Cancel pending I/O and free all RX/TX buffers.
1031 	 */
1032 #if 1
1033 	cue_reset(sc);
1034 #endif
1035 
1036 	/* Set advanced operation modes. */
1037 	cue_csr_write_1(sc, CUE_ADVANCED_OPMODES,
1038 	    CUE_AOP_EMBED_RXLEN | 0x03); /* 1 wait state */
1039 
1040 #if defined(__OpenBSD__)
1041 	eaddr = sc->arpcom.ac_enaddr;
1042 #elif defined(__NetBSD__)
1043 	eaddr = LLADDR(ifp->if_sadl);
1044 #endif
1045 	/* Set MAC address */
1046 	for (i = 0; i < ETHER_ADDR_LEN; i++)
1047 		cue_csr_write_1(sc, CUE_PAR0 - i, eaddr[i]);
1048 
1049 	/* Enable RX logic. */
1050 	ctl = CUE_ETHCTL_RX_ON | CUE_ETHCTL_MCAST_ON;
1051 	if (ifp->if_flags & IFF_PROMISC)
1052 		ctl |= CUE_ETHCTL_PROMISC;
1053 	cue_csr_write_1(sc, CUE_ETHCTL, ctl);
1054 
1055 	/* Init TX ring. */
1056 	if (cue_tx_list_init(sc) == ENOBUFS) {
1057 		printf("%s: tx list init failed\n", USBDEVNAME(sc->cue_dev));
1058 		splx(s);
1059 		return;
1060 	}
1061 
1062 	/* Init RX ring. */
1063 	if (cue_rx_list_init(sc) == ENOBUFS) {
1064 		printf("%s: rx list init failed\n", USBDEVNAME(sc->cue_dev));
1065 		splx(s);
1066 		return;
1067 	}
1068 
1069 	/* Load the multicast filter. */
1070 	cue_setmulti(sc);
1071 
1072 	/*
1073 	 * Set the number of RX and TX buffers that we want
1074 	 * to reserve inside the ASIC.
1075 	 */
1076 	cue_csr_write_1(sc, CUE_RX_BUFPKTS, CUE_RX_FRAMES);
1077 	cue_csr_write_1(sc, CUE_TX_BUFPKTS, CUE_TX_FRAMES);
1078 
1079 	/* Set advanced operation modes. */
1080 	cue_csr_write_1(sc, CUE_ADVANCED_OPMODES,
1081 	    CUE_AOP_EMBED_RXLEN | 0x01); /* 1 wait state */
1082 
1083 	/* Program the LED operation. */
1084 	cue_csr_write_1(sc, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK);
1085 
1086 	if (sc->cue_ep[CUE_ENDPT_RX] == NULL) {
1087 		if (cue_open_pipes(sc)) {
1088 			splx(s);
1089 			return;
1090 		}
1091 	}
1092 
1093 	ifp->if_flags |= IFF_RUNNING;
1094 	ifp->if_flags &= ~IFF_OACTIVE;
1095 
1096 	splx(s);
1097 
1098 	usb_callout(sc->cue_stat_ch, hz, cue_tick, sc);
1099 }
1100 
1101 Static int
cue_open_pipes(struct cue_softc * sc)1102 cue_open_pipes(struct cue_softc *sc)
1103 {
1104 	struct cue_chain	*c;
1105 	usbd_status		err;
1106 	int			i;
1107 
1108 	/* Open RX and TX pipes. */
1109 	err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_RX],
1110 	    USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_RX]);
1111 	if (err) {
1112 		printf("%s: open rx pipe failed: %s\n",
1113 		    USBDEVNAME(sc->cue_dev), usbd_errstr(err));
1114 		return (EIO);
1115 	}
1116 	err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_TX],
1117 	    USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_TX]);
1118 	if (err) {
1119 		printf("%s: open tx pipe failed: %s\n",
1120 		    USBDEVNAME(sc->cue_dev), usbd_errstr(err));
1121 		return (EIO);
1122 	}
1123 
1124 	/* Start up the receive pipe. */
1125 	for (i = 0; i < CUE_RX_LIST_CNT; i++) {
1126 		c = &sc->cue_cdata.cue_rx_chain[i];
1127 		usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_RX],
1128 		    c, c->cue_buf, CUE_BUFSZ,
1129 		    USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
1130 		    cue_rxeof);
1131 		usbd_transfer(c->cue_xfer);
1132 	}
1133 
1134 	return (0);
1135 }
1136 
1137 Static int
cue_ioctl(struct ifnet * ifp,u_long command,caddr_t data)1138 cue_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1139 {
1140 	struct cue_softc	*sc = ifp->if_softc;
1141 	struct ifaddr 		*ifa = (struct ifaddr *)data;
1142 	struct ifreq		*ifr = (struct ifreq *)data;
1143 	int			s, error = 0;
1144 
1145 	if (sc->cue_dying)
1146 		return (EIO);
1147 
1148 	s = splnet();
1149 
1150 	switch(command) {
1151 	case SIOCSIFADDR:
1152 		ifp->if_flags |= IFF_UP;
1153 		cue_init(sc);
1154 
1155 		switch (ifa->ifa_addr->sa_family) {
1156 #ifdef INET
1157 		case AF_INET:
1158 #if defined(__NetBSD__)
1159 			arp_ifinit(ifp, ifa);
1160 #else
1161 			arp_ifinit(&sc->arpcom, ifa);
1162 #endif
1163 			break;
1164 #endif /* INET */
1165 		}
1166 		break;
1167 
1168 	case SIOCSIFMTU:
1169 		if (ifr->ifr_mtu > ETHERMTU)
1170 			error = EINVAL;
1171 		else
1172 			ifp->if_mtu = ifr->ifr_mtu;
1173 		break;
1174 
1175 	case SIOCSIFFLAGS:
1176 		if (ifp->if_flags & IFF_UP) {
1177 			if (ifp->if_flags & IFF_RUNNING &&
1178 			    ifp->if_flags & IFF_PROMISC &&
1179 			    !(sc->cue_if_flags & IFF_PROMISC)) {
1180 				CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
1181 				cue_setmulti(sc);
1182 			} else if (ifp->if_flags & IFF_RUNNING &&
1183 			    !(ifp->if_flags & IFF_PROMISC) &&
1184 			    sc->cue_if_flags & IFF_PROMISC) {
1185 				CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
1186 				cue_setmulti(sc);
1187 			} else if (!(ifp->if_flags & IFF_RUNNING))
1188 				cue_init(sc);
1189 		} else {
1190 			if (ifp->if_flags & IFF_RUNNING)
1191 				cue_stop(sc);
1192 		}
1193 		sc->cue_if_flags = ifp->if_flags;
1194 		error = 0;
1195 		break;
1196 	case SIOCADDMULTI:
1197 	case SIOCDELMULTI:
1198 		error = (command == SIOCADDMULTI) ?
1199 		    ether_addmulti(ifr, &sc->arpcom) :
1200 		    ether_delmulti(ifr, &sc->arpcom);
1201 
1202 		if (error == ENETRESET) {
1203 			/*
1204 			 * Multicast list has changed; set the hardware
1205 			 * filter accordingly.
1206 			 */
1207 			if (ifp->if_flags & IFF_RUNNING)
1208 				cue_setmulti(sc);
1209 			error = 0;
1210 		}
1211 		break;
1212 	default:
1213 		error = EINVAL;
1214 		break;
1215 	}
1216 
1217 	splx(s);
1218 
1219 	return (error);
1220 }
1221 
1222 Static void
cue_watchdog(struct ifnet * ifp)1223 cue_watchdog(struct ifnet *ifp)
1224 {
1225 	struct cue_softc	*sc = ifp->if_softc;
1226 	struct cue_chain	*c;
1227 	usbd_status		stat;
1228 	int			s;
1229 
1230 	DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->cue_dev),__func__));
1231 
1232 	if (sc->cue_dying)
1233 		return;
1234 
1235 	ifp->if_oerrors++;
1236 	printf("%s: watchdog timeout\n", USBDEVNAME(sc->cue_dev));
1237 
1238 	s = splusb();
1239 	c = &sc->cue_cdata.cue_tx_chain[0];
1240 	usbd_get_xfer_status(c->cue_xfer, NULL, NULL, NULL, &stat);
1241 	cue_txeof(c->cue_xfer, c, stat);
1242 
1243 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1244 		cue_start(ifp);
1245 	splx(s);
1246 }
1247 
1248 /*
1249  * Stop the adapter and free any mbufs allocated to the
1250  * RX and TX lists.
1251  */
1252 Static void
cue_stop(struct cue_softc * sc)1253 cue_stop(struct cue_softc *sc)
1254 {
1255 	usbd_status		err;
1256 	struct ifnet		*ifp;
1257 	int			i;
1258 
1259 	DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->cue_dev),__func__));
1260 
1261 	ifp = GET_IFP(sc);
1262 	ifp->if_timer = 0;
1263 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1264 
1265 	cue_csr_write_1(sc, CUE_ETHCTL, 0);
1266 	cue_reset(sc);
1267 	usb_uncallout(sc->cue_stat_ch, cue_tick, sc);
1268 
1269 	/* Stop transfers. */
1270 	if (sc->cue_ep[CUE_ENDPT_RX] != NULL) {
1271 		err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_RX]);
1272 		if (err) {
1273 			printf("%s: abort rx pipe failed: %s\n",
1274 			USBDEVNAME(sc->cue_dev), usbd_errstr(err));
1275 		}
1276 		err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_RX]);
1277 		if (err) {
1278 			printf("%s: close rx pipe failed: %s\n",
1279 			USBDEVNAME(sc->cue_dev), usbd_errstr(err));
1280 		}
1281 		sc->cue_ep[CUE_ENDPT_RX] = NULL;
1282 	}
1283 
1284 	if (sc->cue_ep[CUE_ENDPT_TX] != NULL) {
1285 		err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_TX]);
1286 		if (err) {
1287 			printf("%s: abort tx pipe failed: %s\n",
1288 			USBDEVNAME(sc->cue_dev), usbd_errstr(err));
1289 		}
1290 		err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_TX]);
1291 		if (err) {
1292 			printf("%s: close tx pipe failed: %s\n",
1293 			    USBDEVNAME(sc->cue_dev), usbd_errstr(err));
1294 		}
1295 		sc->cue_ep[CUE_ENDPT_TX] = NULL;
1296 	}
1297 
1298 	if (sc->cue_ep[CUE_ENDPT_INTR] != NULL) {
1299 		err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_INTR]);
1300 		if (err) {
1301 			printf("%s: abort intr pipe failed: %s\n",
1302 			USBDEVNAME(sc->cue_dev), usbd_errstr(err));
1303 		}
1304 		err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_INTR]);
1305 		if (err) {
1306 			printf("%s: close intr pipe failed: %s\n",
1307 			    USBDEVNAME(sc->cue_dev), usbd_errstr(err));
1308 		}
1309 		sc->cue_ep[CUE_ENDPT_INTR] = NULL;
1310 	}
1311 
1312 	/* Free RX resources. */
1313 	for (i = 0; i < CUE_RX_LIST_CNT; i++) {
1314 		if (sc->cue_cdata.cue_rx_chain[i].cue_mbuf != NULL) {
1315 			m_freem(sc->cue_cdata.cue_rx_chain[i].cue_mbuf);
1316 			sc->cue_cdata.cue_rx_chain[i].cue_mbuf = NULL;
1317 		}
1318 		if (sc->cue_cdata.cue_rx_chain[i].cue_xfer != NULL) {
1319 			usbd_free_xfer(sc->cue_cdata.cue_rx_chain[i].cue_xfer);
1320 			sc->cue_cdata.cue_rx_chain[i].cue_xfer = NULL;
1321 		}
1322 	}
1323 
1324 	/* Free TX resources. */
1325 	for (i = 0; i < CUE_TX_LIST_CNT; i++) {
1326 		if (sc->cue_cdata.cue_tx_chain[i].cue_mbuf != NULL) {
1327 			m_freem(sc->cue_cdata.cue_tx_chain[i].cue_mbuf);
1328 			sc->cue_cdata.cue_tx_chain[i].cue_mbuf = NULL;
1329 		}
1330 		if (sc->cue_cdata.cue_tx_chain[i].cue_xfer != NULL) {
1331 			usbd_free_xfer(sc->cue_cdata.cue_tx_chain[i].cue_xfer);
1332 			sc->cue_cdata.cue_tx_chain[i].cue_xfer = NULL;
1333 		}
1334 	}
1335 }
1336