xref: /openbsd-src/sys/dev/usb/if_cue.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /*	$OpenBSD: if_cue.c,v 1.75 2016/04/13 11:03:37 mpi 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 #include "bpfilter.h"
60 
61 #include <sys/param.h>
62 #include <sys/systm.h>
63 #include <sys/sockio.h>
64 #include <sys/mbuf.h>
65 #include <sys/kernel.h>
66 #include <sys/socket.h>
67 #include <sys/timeout.h>
68 #include <sys/device.h>
69 
70 #include <net/if.h>
71 
72 #if NBPFILTER > 0
73 #include <net/bpf.h>
74 #endif
75 
76 #include <netinet/in.h>
77 #include <netinet/if_ether.h>
78 
79 #include <dev/usb/usb.h>
80 #include <dev/usb/usbdi.h>
81 #include <dev/usb/usbdi_util.h>
82 #include <dev/usb/usbdevs.h>
83 
84 #include <dev/usb/if_cuereg.h>
85 
86 #ifdef CUE_DEBUG
87 #define DPRINTF(x)	do { if (cuedebug) printf x; } while (0)
88 #define DPRINTFN(n,x)	do { if (cuedebug >= (n)) printf x; } while (0)
89 int	cuedebug = 0;
90 #else
91 #define DPRINTF(x)
92 #define DPRINTFN(n,x)
93 #endif
94 
95 /*
96  * Various supported device vendors/products.
97  */
98 struct usb_devno cue_devs[] = {
99 	{ USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE },
100 	{ USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE2 },
101 	{ USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTLINK },
102 	/* Belkin F5U111 adapter covered by NETMATE entry */
103 };
104 
105 int cue_match(struct device *, void *, void *);
106 void cue_attach(struct device *, struct device *, void *);
107 int cue_detach(struct device *, int);
108 
109 struct cfdriver cue_cd = {
110 	NULL, "cue", DV_IFNET
111 };
112 
113 const struct cfattach cue_ca = {
114 	sizeof(struct cue_softc), cue_match, cue_attach, cue_detach
115 };
116 
117 int cue_open_pipes(struct cue_softc *);
118 int cue_tx_list_init(struct cue_softc *);
119 int cue_rx_list_init(struct cue_softc *);
120 int cue_newbuf(struct cue_softc *, struct cue_chain *, struct mbuf *);
121 int cue_send(struct cue_softc *, struct mbuf *, int);
122 void cue_rxeof(struct usbd_xfer *, void *, usbd_status);
123 void cue_txeof(struct usbd_xfer *, void *, usbd_status);
124 void cue_tick(void *);
125 void cue_tick_task(void *);
126 void cue_start(struct ifnet *);
127 int cue_ioctl(struct ifnet *, u_long, caddr_t);
128 void cue_init(void *);
129 void cue_stop(struct cue_softc *);
130 void cue_watchdog(struct ifnet *);
131 
132 void cue_setmulti(struct cue_softc *);
133 void cue_reset(struct cue_softc *);
134 
135 int cue_csr_read_1(struct cue_softc *, int);
136 int cue_csr_write_1(struct cue_softc *, int, int);
137 int cue_csr_read_2(struct cue_softc *, int);
138 #if 0
139 int cue_csr_write_2(struct cue_softc *, int, int);
140 #endif
141 int cue_mem(struct cue_softc *, int, int, void *, int);
142 int cue_getmac(struct cue_softc *, void *);
143 
144 #define CUE_SETBIT(sc, reg, x)				\
145 	cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) | (x))
146 
147 #define CUE_CLRBIT(sc, reg, x)				\
148 	cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) & ~(x))
149 
150 int
151 cue_csr_read_1(struct cue_softc *sc, int reg)
152 {
153 	usb_device_request_t	req;
154 	usbd_status		err;
155 	u_int8_t		val = 0;
156 
157 	if (usbd_is_dying(sc->cue_udev))
158 		return (0);
159 
160 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
161 	req.bRequest = CUE_CMD_READREG;
162 	USETW(req.wValue, 0);
163 	USETW(req.wIndex, reg);
164 	USETW(req.wLength, 1);
165 
166 	err = usbd_do_request(sc->cue_udev, &req, &val);
167 
168 	if (err) {
169 		DPRINTF(("%s: cue_csr_read_1: reg=0x%x err=%s\n",
170 			 sc->cue_dev.dv_xname, reg, usbd_errstr(err)));
171 		return (0);
172 	}
173 
174 	DPRINTFN(10,("%s: cue_csr_read_1 reg=0x%x val=0x%x\n",
175 		     sc->cue_dev.dv_xname, reg, val));
176 
177 	return (val);
178 }
179 
180 int
181 cue_csr_read_2(struct cue_softc *sc, int reg)
182 {
183 	usb_device_request_t	req;
184 	usbd_status		err;
185 	uWord			val;
186 
187 	if (usbd_is_dying(sc->cue_udev))
188 		return (0);
189 
190 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
191 	req.bRequest = CUE_CMD_READREG;
192 	USETW(req.wValue, 0);
193 	USETW(req.wIndex, reg);
194 	USETW(req.wLength, 2);
195 
196 	err = usbd_do_request(sc->cue_udev, &req, &val);
197 
198 	DPRINTFN(10,("%s: cue_csr_read_2 reg=0x%x val=0x%x\n",
199 		     sc->cue_dev.dv_xname, reg, UGETW(val)));
200 
201 	if (err) {
202 		DPRINTF(("%s: cue_csr_read_2: reg=0x%x err=%s\n",
203 			 sc->cue_dev.dv_xname, reg, usbd_errstr(err)));
204 		return (0);
205 	}
206 
207 	return (UGETW(val));
208 }
209 
210 int
211 cue_csr_write_1(struct cue_softc *sc, int reg, int val)
212 {
213 	usb_device_request_t	req;
214 	usbd_status		err;
215 
216 	if (usbd_is_dying(sc->cue_udev))
217 		return (0);
218 
219 	DPRINTFN(10,("%s: cue_csr_write_1 reg=0x%x val=0x%x\n",
220 		     sc->cue_dev.dv_xname, reg, val));
221 
222 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
223 	req.bRequest = CUE_CMD_WRITEREG;
224 	USETW(req.wValue, val);
225 	USETW(req.wIndex, reg);
226 	USETW(req.wLength, 0);
227 
228 	err = usbd_do_request(sc->cue_udev, &req, NULL);
229 
230 	if (err) {
231 		DPRINTF(("%s: cue_csr_write_1: reg=0x%x err=%s\n",
232 			 sc->cue_dev.dv_xname, reg, usbd_errstr(err)));
233 		return (-1);
234 	}
235 
236 	DPRINTFN(20,("%s: cue_csr_write_1, after reg=0x%x val=0x%x\n",
237 		     sc->cue_dev.dv_xname, reg, cue_csr_read_1(sc, reg)));
238 
239 	return (0);
240 }
241 
242 #if 0
243 int
244 cue_csr_write_2(struct cue_softc *sc, int reg, int aval)
245 {
246 	usb_device_request_t	req;
247 	usbd_status		err;
248 	uWord			val;
249 	int			s;
250 
251 	if (usbd_is_dying(sc->cue_udev))
252 		return (0);
253 
254 	DPRINTFN(10,("%s: cue_csr_write_2 reg=0x%x val=0x%x\n",
255 		     sc->cue_dev.dv_xname, reg, aval));
256 
257 	USETW(val, aval);
258 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
259 	req.bRequest = CUE_CMD_WRITEREG;
260 	USETW(req.wValue, val);
261 	USETW(req.wIndex, reg);
262 	USETW(req.wLength, 0);
263 
264 	err = usbd_do_request(sc->cue_udev, &req, NULL);
265 
266 	if (err) {
267 		DPRINTF(("%s: cue_csr_write_2: reg=0x%x err=%s\n",
268 			 sc->cue_dev.dv_xname, reg, usbd_errstr(err)));
269 		return (-1);
270 	}
271 
272 	return (0);
273 }
274 #endif
275 
276 int
277 cue_mem(struct cue_softc *sc, int cmd, int addr, void *buf, int len)
278 {
279 	usb_device_request_t	req;
280 	usbd_status		err;
281 
282 	DPRINTFN(10,("%s: cue_mem cmd=0x%x addr=0x%x len=%d\n",
283 		     sc->cue_dev.dv_xname, cmd, addr, len));
284 
285 	if (cmd == CUE_CMD_READSRAM)
286 		req.bmRequestType = UT_READ_VENDOR_DEVICE;
287 	else
288 		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
289 	req.bRequest = cmd;
290 	USETW(req.wValue, 0);
291 	USETW(req.wIndex, addr);
292 	USETW(req.wLength, len);
293 
294 	err = usbd_do_request(sc->cue_udev, &req, buf);
295 
296 	if (err) {
297 		DPRINTF(("%s: cue_csr_mem: addr=0x%x err=%s\n",
298 			 sc->cue_dev.dv_xname, addr, usbd_errstr(err)));
299 		return (-1);
300 	}
301 
302 	return (0);
303 }
304 
305 int
306 cue_getmac(struct cue_softc *sc, void *buf)
307 {
308 	usb_device_request_t	req;
309 	usbd_status		err;
310 
311 	DPRINTFN(10,("%s: cue_getmac\n", sc->cue_dev.dv_xname));
312 
313 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
314 	req.bRequest = CUE_CMD_GET_MACADDR;
315 	USETW(req.wValue, 0);
316 	USETW(req.wIndex, 0);
317 	USETW(req.wLength, ETHER_ADDR_LEN);
318 
319 	err = usbd_do_request(sc->cue_udev, &req, buf);
320 
321 	if (err) {
322 		printf("%s: read MAC address failed\n",
323 		       sc->cue_dev.dv_xname);
324 		return (-1);
325 	}
326 
327 	return (0);
328 }
329 
330 #define CUE_BITS	9
331 
332 void
333 cue_setmulti(struct cue_softc *sc)
334 {
335 	struct arpcom		*ac = &sc->arpcom;
336 	struct ifnet		*ifp;
337 	struct ether_multi	*enm;
338 	struct ether_multistep	step;
339 	u_int32_t		h, i;
340 
341 	ifp = GET_IFP(sc);
342 
343 	DPRINTFN(2,("%s: cue_setmulti if_flags=0x%x\n",
344 		    sc->cue_dev.dv_xname, ifp->if_flags));
345 
346 	if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
347 		ifp->if_flags |= IFF_ALLMULTI;
348 		for (i = 0; i < CUE_MCAST_TABLE_LEN; i++)
349 			sc->cue_mctab[i] = 0xFF;
350 		cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
351 		    &sc->cue_mctab, CUE_MCAST_TABLE_LEN);
352 		return;
353 	}
354 
355 	/* first, zot all the existing hash bits */
356 	for (i = 0; i < CUE_MCAST_TABLE_LEN; i++)
357 		sc->cue_mctab[i] = 0;
358 
359 	/* now program new ones */
360 	ETHER_FIRST_MULTI(step, ac, enm);
361 	while (enm != NULL) {
362 		h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) &
363 		    ((1 << CUE_BITS) - 1);
364 		sc->cue_mctab[h >> 3] |= 1 << (h & 0x7);
365 		ETHER_NEXT_MULTI(step, enm);
366 	}
367 
368 	ifp->if_flags &= ~IFF_ALLMULTI;
369 
370 	/*
371 	 * Also include the broadcast address in the filter
372 	 * so we can receive broadcast frames.
373 	 */
374 	if (ifp->if_flags & IFF_BROADCAST) {
375 		h = ether_crc32_le(etherbroadcastaddr, ETHER_ADDR_LEN) &
376 		    ((1 << CUE_BITS) - 1);
377 		sc->cue_mctab[h >> 3] |= 1 << (h & 0x7);
378 	}
379 
380 	cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
381 	    &sc->cue_mctab, CUE_MCAST_TABLE_LEN);
382 }
383 
384 void
385 cue_reset(struct cue_softc *sc)
386 {
387 	usb_device_request_t	req;
388 	usbd_status		err;
389 
390 	DPRINTFN(2,("%s: cue_reset\n", sc->cue_dev.dv_xname));
391 
392 	if (usbd_is_dying(sc->cue_udev))
393 		return;
394 
395 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
396 	req.bRequest = CUE_CMD_RESET;
397 	USETW(req.wValue, 0);
398 	USETW(req.wIndex, 0);
399 	USETW(req.wLength, 0);
400 
401 	err = usbd_do_request(sc->cue_udev, &req, NULL);
402 
403 	if (err)
404 		printf("%s: reset failed\n", sc->cue_dev.dv_xname);
405 
406 	/* Wait a little while for the chip to get its brains in order. */
407 	usbd_delay_ms(sc->cue_udev, 1);
408 }
409 
410 /*
411  * Probe for a CATC chip.
412  */
413 int
414 cue_match(struct device *parent, void *match, void *aux)
415 {
416 	struct usb_attach_arg	*uaa = aux;
417 
418 	if (uaa->iface != NULL)
419 		return (UMATCH_NONE);
420 
421 	return (usb_lookup(cue_devs, uaa->vendor, uaa->product) != NULL ?
422 	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
423 }
424 
425 /*
426  * Attach the interface. Allocate softc structures, do ifmedia
427  * setup and ethernet/BPF attach.
428  */
429 void
430 cue_attach(struct device *parent, struct device *self, void *aux)
431 {
432 	struct cue_softc	*sc = (struct cue_softc *)self;
433 	struct usb_attach_arg	*uaa = aux;
434 	int			s;
435 	u_char			eaddr[ETHER_ADDR_LEN];
436 	struct usbd_device	*dev = uaa->device;
437 	struct usbd_interface	*iface;
438 	usbd_status		err;
439 	struct ifnet		*ifp;
440 	usb_interface_descriptor_t	*id;
441 	usb_endpoint_descriptor_t	*ed;
442 	int			i;
443 
444 	DPRINTFN(5,(" : cue_attach: sc=%p, dev=%p", sc, dev));
445 
446 	sc->cue_udev = dev;
447 
448 	err = usbd_set_config_no(dev, CUE_CONFIG_NO, 1);
449 	if (err) {
450 		printf("%s: setting config no failed\n",
451 		    sc->cue_dev.dv_xname);
452 		return;
453 	}
454 
455 	sc->cue_product = uaa->product;
456 	sc->cue_vendor = uaa->vendor;
457 
458 	usb_init_task(&sc->cue_tick_task, cue_tick_task, sc,
459 	    USB_TASK_TYPE_GENERIC);
460 	usb_init_task(&sc->cue_stop_task, (void (*)(void *))cue_stop, sc,
461 	    USB_TASK_TYPE_GENERIC);
462 
463 	err = usbd_device2interface_handle(dev, CUE_IFACE_IDX, &iface);
464 	if (err) {
465 		printf("%s: getting interface handle failed\n",
466 		    sc->cue_dev.dv_xname);
467 		return;
468 	}
469 
470 	sc->cue_iface = iface;
471 	id = usbd_get_interface_descriptor(iface);
472 
473 	/* Find endpoints. */
474 	for (i = 0; i < id->bNumEndpoints; i++) {
475 		ed = usbd_interface2endpoint_descriptor(iface, i);
476 		if (ed == NULL) {
477 			printf("%s: couldn't get ep %d\n",
478 			    sc->cue_dev.dv_xname, i);
479 			return;
480 		}
481 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
482 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
483 			sc->cue_ed[CUE_ENDPT_RX] = ed->bEndpointAddress;
484 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
485 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
486 			sc->cue_ed[CUE_ENDPT_TX] = ed->bEndpointAddress;
487 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
488 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
489 			sc->cue_ed[CUE_ENDPT_INTR] = ed->bEndpointAddress;
490 		}
491 	}
492 
493 #if 0
494 	/* Reset the adapter. */
495 	cue_reset(sc);
496 #endif
497 	/*
498 	 * Get station address.
499 	 */
500 	cue_getmac(sc, &eaddr);
501 
502 	s = splnet();
503 
504 	/*
505 	 * A CATC chip was detected. Inform the world.
506 	 */
507 	printf("%s: address %s\n", sc->cue_dev.dv_xname,
508 	    ether_sprintf(eaddr));
509 
510 	bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
511 
512 	/* Initialize interface info.*/
513 	ifp = GET_IFP(sc);
514 	ifp->if_softc = sc;
515 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
516 	ifp->if_ioctl = cue_ioctl;
517 	ifp->if_start = cue_start;
518 	ifp->if_watchdog = cue_watchdog;
519 	strlcpy(ifp->if_xname, sc->cue_dev.dv_xname, IFNAMSIZ);
520 
521 	/* Attach the interface. */
522 	if_attach(ifp);
523 	ether_ifattach(ifp);
524 
525 	timeout_set(&sc->cue_stat_ch, cue_tick, sc);
526 
527 	splx(s);
528 }
529 
530 int
531 cue_detach(struct device *self, int flags)
532 {
533 	struct cue_softc	*sc = (struct cue_softc *)self;
534 	struct ifnet		*ifp = GET_IFP(sc);
535 	int			s;
536 
537 	DPRINTFN(2,("%s: %s: enter\n", sc->cue_dev.dv_xname, __func__));
538 
539 	if (timeout_initialized(&sc->cue_stat_ch))
540 		timeout_del(&sc->cue_stat_ch);
541 
542 	/*
543 	 * Remove any pending task.  It cannot be executing because it run
544 	 * in the same thread as detach.
545 	 */
546 	usb_rem_task(sc->cue_udev, &sc->cue_tick_task);
547 	usb_rem_task(sc->cue_udev, &sc->cue_stop_task);
548 
549 	s = splusb();
550 
551 	if (ifp->if_flags & IFF_RUNNING)
552 		cue_stop(sc);
553 
554 	if (ifp->if_softc != NULL) {
555 		ether_ifdetach(ifp);
556 		if_detach(ifp);
557 	}
558 
559 #ifdef DIAGNOSTIC
560 	if (sc->cue_ep[CUE_ENDPT_TX] != NULL ||
561 	    sc->cue_ep[CUE_ENDPT_RX] != NULL ||
562 	    sc->cue_ep[CUE_ENDPT_INTR] != NULL)
563 		printf("%s: detach has active endpoints\n",
564 		       sc->cue_dev.dv_xname);
565 #endif
566 
567 	splx(s);
568 
569 	return (0);
570 }
571 
572 /*
573  * Initialize an RX descriptor and attach an MBUF cluster.
574  */
575 int
576 cue_newbuf(struct cue_softc *sc, struct cue_chain *c, struct mbuf *m)
577 {
578 	struct mbuf		*m_new = NULL;
579 
580 	if (m == NULL) {
581 		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
582 		if (m_new == NULL) {
583 			printf("%s: no memory for rx list "
584 			    "-- packet dropped!\n", sc->cue_dev.dv_xname);
585 			return (ENOBUFS);
586 		}
587 
588 		MCLGET(m_new, M_DONTWAIT);
589 		if (!(m_new->m_flags & M_EXT)) {
590 			printf("%s: no memory for rx list "
591 			    "-- packet dropped!\n", sc->cue_dev.dv_xname);
592 			m_freem(m_new);
593 			return (ENOBUFS);
594 		}
595 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
596 	} else {
597 		m_new = m;
598 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
599 		m_new->m_data = m_new->m_ext.ext_buf;
600 	}
601 
602 	m_adj(m_new, ETHER_ALIGN);
603 	c->cue_mbuf = m_new;
604 
605 	return (0);
606 }
607 
608 int
609 cue_rx_list_init(struct cue_softc *sc)
610 {
611 	struct cue_cdata	*cd;
612 	struct cue_chain	*c;
613 	int			i;
614 
615 	cd = &sc->cue_cdata;
616 	for (i = 0; i < CUE_RX_LIST_CNT; i++) {
617 		c = &cd->cue_rx_chain[i];
618 		c->cue_sc = sc;
619 		c->cue_idx = i;
620 		if (cue_newbuf(sc, c, NULL) == ENOBUFS)
621 			return (ENOBUFS);
622 		if (c->cue_xfer == NULL) {
623 			c->cue_xfer = usbd_alloc_xfer(sc->cue_udev);
624 			if (c->cue_xfer == NULL)
625 				return (ENOBUFS);
626 			c->cue_buf = usbd_alloc_buffer(c->cue_xfer, CUE_BUFSZ);
627 			if (c->cue_buf == NULL) {
628 				usbd_free_xfer(c->cue_xfer);
629 				return (ENOBUFS);
630 			}
631 		}
632 	}
633 
634 	return (0);
635 }
636 
637 int
638 cue_tx_list_init(struct cue_softc *sc)
639 {
640 	struct cue_cdata	*cd;
641 	struct cue_chain	*c;
642 	int			i;
643 
644 	cd = &sc->cue_cdata;
645 	for (i = 0; i < CUE_TX_LIST_CNT; i++) {
646 		c = &cd->cue_tx_chain[i];
647 		c->cue_sc = sc;
648 		c->cue_idx = i;
649 		c->cue_mbuf = NULL;
650 		if (c->cue_xfer == NULL) {
651 			c->cue_xfer = usbd_alloc_xfer(sc->cue_udev);
652 			if (c->cue_xfer == NULL)
653 				return (ENOBUFS);
654 			c->cue_buf = usbd_alloc_buffer(c->cue_xfer, CUE_BUFSZ);
655 			if (c->cue_buf == NULL) {
656 				usbd_free_xfer(c->cue_xfer);
657 				return (ENOBUFS);
658 			}
659 		}
660 	}
661 
662 	return (0);
663 }
664 
665 /*
666  * A frame has been uploaded: pass the resulting mbuf chain up to
667  * the higher level protocols.
668  */
669 void
670 cue_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
671 {
672 	struct cue_chain	*c = priv;
673 	struct cue_softc	*sc = c->cue_sc;
674 	struct ifnet		*ifp = GET_IFP(sc);
675 	struct mbuf_list	ml = MBUF_LIST_INITIALIZER();
676 	struct mbuf		*m;
677 	int			total_len = 0;
678 	u_int16_t		len;
679 	int			s;
680 
681 	DPRINTFN(10,("%s: %s: enter status=%d\n", sc->cue_dev.dv_xname,
682 		     __func__, status));
683 
684 	if (usbd_is_dying(sc->cue_udev))
685 		return;
686 
687 	if (!(ifp->if_flags & IFF_RUNNING))
688 		return;
689 
690 	if (status != USBD_NORMAL_COMPLETION) {
691 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
692 			return;
693 		sc->cue_rx_errs++;
694 		if (usbd_ratecheck(&sc->cue_rx_notice)) {
695 			printf("%s: %u usb errors on rx: %s\n",
696 			    sc->cue_dev.dv_xname, sc->cue_rx_errs,
697 			    usbd_errstr(status));
698 			sc->cue_rx_errs = 0;
699 		}
700 		if (status == USBD_STALLED)
701 			usbd_clear_endpoint_stall_async(sc->cue_ep[CUE_ENDPT_RX]);
702 		goto done;
703 	}
704 
705 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
706 
707 	memcpy(mtod(c->cue_mbuf, char *), c->cue_buf, total_len);
708 
709 	m = c->cue_mbuf;
710 	len = UGETW(mtod(m, u_int8_t *));
711 
712 	/* No errors; receive the packet. */
713 	total_len = len;
714 
715 	if (len < sizeof(struct ether_header)) {
716 		ifp->if_ierrors++;
717 		goto done;
718 	}
719 
720 	m_adj(m, sizeof(u_int16_t));
721 	m->m_pkthdr.len = m->m_len = total_len;
722 	ml_enqueue(&ml, m);
723 
724 	if (cue_newbuf(sc, c, NULL) == ENOBUFS) {
725 		ifp->if_ierrors++;
726 		goto done;
727 	}
728 
729 	s = splnet();
730 	if_input(ifp, &ml);
731 	splx(s);
732 
733 done:
734 	/* Setup new transfer. */
735 	usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_RX],
736 	    c, c->cue_buf, CUE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
737 	    USBD_NO_TIMEOUT, cue_rxeof);
738 	usbd_transfer(c->cue_xfer);
739 
740 	DPRINTFN(10,("%s: %s: start rx\n", sc->cue_dev.dv_xname,
741 		    __func__));
742 }
743 
744 /*
745  * A frame was downloaded to the chip. It's safe for us to clean up
746  * the list buffers.
747  */
748 void
749 cue_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
750 {
751 	struct cue_chain	*c = priv;
752 	struct cue_softc	*sc = c->cue_sc;
753 	struct ifnet		*ifp = GET_IFP(sc);
754 	int			s;
755 
756 	if (usbd_is_dying(sc->cue_udev))
757 		return;
758 
759 	s = splnet();
760 
761 	DPRINTFN(10,("%s: %s: enter status=%d\n", sc->cue_dev.dv_xname,
762 		    __func__, status));
763 
764 	ifp->if_timer = 0;
765 	ifq_clr_oactive(&ifp->if_snd);
766 
767 	if (status != USBD_NORMAL_COMPLETION) {
768 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
769 			splx(s);
770 			return;
771 		}
772 		ifp->if_oerrors++;
773 		printf("%s: usb error on tx: %s\n", sc->cue_dev.dv_xname,
774 		    usbd_errstr(status));
775 		if (status == USBD_STALLED)
776 			usbd_clear_endpoint_stall_async(sc->cue_ep[CUE_ENDPT_TX]);
777 		splx(s);
778 		return;
779 	}
780 
781 	ifp->if_opackets++;
782 
783 	m_freem(c->cue_mbuf);
784 	c->cue_mbuf = NULL;
785 
786 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
787 		cue_start(ifp);
788 
789 	splx(s);
790 }
791 
792 void
793 cue_tick(void *xsc)
794 {
795 	struct cue_softc	*sc = xsc;
796 
797 	if (sc == NULL)
798 		return;
799 
800 	if (usbd_is_dying(sc->cue_udev))
801 		return;
802 
803 	DPRINTFN(2,("%s: %s: enter\n", sc->cue_dev.dv_xname, __func__));
804 
805 	/* Perform statistics update in process context. */
806 	usb_add_task(sc->cue_udev, &sc->cue_tick_task);
807 }
808 
809 void
810 cue_tick_task(void *xsc)
811 {
812 	struct cue_softc	*sc = xsc;
813 	struct ifnet		*ifp;
814 
815 	if (usbd_is_dying(sc->cue_udev))
816 		return;
817 
818 	DPRINTFN(2,("%s: %s: enter\n", sc->cue_dev.dv_xname, __func__));
819 
820 	ifp = GET_IFP(sc);
821 
822 	ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_SINGLECOLL);
823 	ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_MULTICOLL);
824 	ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_EXCESSCOLL);
825 
826 	if (cue_csr_read_2(sc, CUE_RX_FRAMEERR))
827 		ifp->if_ierrors++;
828 }
829 
830 int
831 cue_send(struct cue_softc *sc, struct mbuf *m, int idx)
832 {
833 	int			total_len;
834 	struct cue_chain	*c;
835 	usbd_status		err;
836 
837 	c = &sc->cue_cdata.cue_tx_chain[idx];
838 
839 	/*
840 	 * Copy the mbuf data into a contiguous buffer, leaving two
841 	 * bytes at the beginning to hold the frame length.
842 	 */
843 	m_copydata(m, 0, m->m_pkthdr.len, c->cue_buf + 2);
844 	c->cue_mbuf = m;
845 
846 	total_len = m->m_pkthdr.len + 2;
847 
848 	DPRINTFN(10,("%s: %s: total_len=%d\n",
849 		     sc->cue_dev.dv_xname, __func__, total_len));
850 
851 	/* The first two bytes are the frame length */
852 	c->cue_buf[0] = (u_int8_t)m->m_pkthdr.len;
853 	c->cue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8);
854 
855 	/* XXX 10000 */
856 	usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_TX],
857 	    c, c->cue_buf, total_len, USBD_NO_COPY, 10000, cue_txeof);
858 
859 	/* Transmit */
860 	err = usbd_transfer(c->cue_xfer);
861 	if (err != USBD_IN_PROGRESS) {
862 		printf("%s: cue_send error=%s\n", sc->cue_dev.dv_xname,
863 		       usbd_errstr(err));
864 		/* Stop the interface from process context. */
865 		usb_add_task(sc->cue_udev, &sc->cue_stop_task);
866 		return (EIO);
867 	}
868 
869 	sc->cue_cdata.cue_tx_cnt++;
870 
871 	return (0);
872 }
873 
874 void
875 cue_start(struct ifnet *ifp)
876 {
877 	struct cue_softc	*sc = ifp->if_softc;
878 	struct mbuf		*m_head = NULL;
879 
880 	if (usbd_is_dying(sc->cue_udev))
881 		return;
882 
883 	DPRINTFN(10,("%s: %s: enter\n", sc->cue_dev.dv_xname,__func__));
884 
885 	if (ifq_is_oactive(&ifp->if_snd))
886 		return;
887 
888 	m_head = ifq_deq_begin(&ifp->if_snd);
889 	if (m_head == NULL)
890 		return;
891 
892 	if (cue_send(sc, m_head, 0)) {
893 		ifq_deq_rollback(&ifp->if_snd, m_head);
894 		ifq_set_oactive(&ifp->if_snd);
895 		return;
896 	}
897 
898 	ifq_deq_commit(&ifp->if_snd, m_head);
899 
900 #if NBPFILTER > 0
901 	/*
902 	 * If there's a BPF listener, bounce a copy of this frame
903 	 * to him.
904 	 */
905 	if (ifp->if_bpf)
906 		bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
907 #endif
908 
909 	ifq_set_oactive(&ifp->if_snd);
910 
911 	/*
912 	 * Set a timeout in case the chip goes out to lunch.
913 	 */
914 	ifp->if_timer = 5;
915 }
916 
917 void
918 cue_init(void *xsc)
919 {
920 	struct cue_softc	*sc = xsc;
921 	struct ifnet		*ifp = GET_IFP(sc);
922 	int			i, s, ctl;
923 	u_char			*eaddr;
924 
925 	if (usbd_is_dying(sc->cue_udev))
926 		return;
927 
928 	DPRINTFN(10,("%s: %s: enter\n", sc->cue_dev.dv_xname,__func__));
929 
930 	if (ifp->if_flags & IFF_RUNNING)
931 		return;
932 
933 	s = splnet();
934 
935 	/*
936 	 * Cancel pending I/O and free all RX/TX buffers.
937 	 */
938 #if 1
939 	cue_reset(sc);
940 #endif
941 
942 	/* Set advanced operation modes. */
943 	cue_csr_write_1(sc, CUE_ADVANCED_OPMODES,
944 	    CUE_AOP_EMBED_RXLEN | 0x03); /* 1 wait state */
945 
946 	eaddr = sc->arpcom.ac_enaddr;
947 	/* Set MAC address */
948 	for (i = 0; i < ETHER_ADDR_LEN; i++)
949 		cue_csr_write_1(sc, CUE_PAR0 - i, eaddr[i]);
950 
951 	/* Enable RX logic. */
952 	ctl = CUE_ETHCTL_RX_ON | CUE_ETHCTL_MCAST_ON;
953 	if (ifp->if_flags & IFF_PROMISC)
954 		ctl |= CUE_ETHCTL_PROMISC;
955 	cue_csr_write_1(sc, CUE_ETHCTL, ctl);
956 
957 	/* Init TX ring. */
958 	if (cue_tx_list_init(sc) == ENOBUFS) {
959 		printf("%s: tx list init failed\n", sc->cue_dev.dv_xname);
960 		splx(s);
961 		return;
962 	}
963 
964 	/* Init RX ring. */
965 	if (cue_rx_list_init(sc) == ENOBUFS) {
966 		printf("%s: rx list init failed\n", sc->cue_dev.dv_xname);
967 		splx(s);
968 		return;
969 	}
970 
971 	/* Load the multicast filter. */
972 	cue_setmulti(sc);
973 
974 	/*
975 	 * Set the number of RX and TX buffers that we want
976 	 * to reserve inside the ASIC.
977 	 */
978 	cue_csr_write_1(sc, CUE_RX_BUFPKTS, CUE_RX_FRAMES);
979 	cue_csr_write_1(sc, CUE_TX_BUFPKTS, CUE_TX_FRAMES);
980 
981 	/* Set advanced operation modes. */
982 	cue_csr_write_1(sc, CUE_ADVANCED_OPMODES,
983 	    CUE_AOP_EMBED_RXLEN | 0x01); /* 1 wait state */
984 
985 	/* Program the LED operation. */
986 	cue_csr_write_1(sc, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK);
987 
988 	if (sc->cue_ep[CUE_ENDPT_RX] == NULL) {
989 		if (cue_open_pipes(sc)) {
990 			splx(s);
991 			return;
992 		}
993 	}
994 
995 	ifp->if_flags |= IFF_RUNNING;
996 	ifq_clr_oactive(&ifp->if_snd);
997 
998 	splx(s);
999 
1000 	timeout_add_sec(&sc->cue_stat_ch, 1);
1001 }
1002 
1003 int
1004 cue_open_pipes(struct cue_softc *sc)
1005 {
1006 	struct cue_chain	*c;
1007 	usbd_status		err;
1008 	int			i;
1009 
1010 	/* Open RX and TX pipes. */
1011 	err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_RX],
1012 	    USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_RX]);
1013 	if (err) {
1014 		printf("%s: open rx pipe failed: %s\n",
1015 		    sc->cue_dev.dv_xname, usbd_errstr(err));
1016 		return (EIO);
1017 	}
1018 	err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_TX],
1019 	    USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_TX]);
1020 	if (err) {
1021 		printf("%s: open tx pipe failed: %s\n",
1022 		    sc->cue_dev.dv_xname, usbd_errstr(err));
1023 		return (EIO);
1024 	}
1025 
1026 	/* Start up the receive pipe. */
1027 	for (i = 0; i < CUE_RX_LIST_CNT; i++) {
1028 		c = &sc->cue_cdata.cue_rx_chain[i];
1029 		usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_RX],
1030 		    c, c->cue_buf, CUE_BUFSZ,
1031 		    USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
1032 		    cue_rxeof);
1033 		usbd_transfer(c->cue_xfer);
1034 	}
1035 
1036 	return (0);
1037 }
1038 
1039 int
1040 cue_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1041 {
1042 	struct cue_softc	*sc = ifp->if_softc;
1043 	int			s, error = 0;
1044 
1045 	if (usbd_is_dying(sc->cue_udev))
1046 		return (EIO);
1047 
1048 	s = splnet();
1049 
1050 	switch(command) {
1051 	case SIOCSIFADDR:
1052 		ifp->if_flags |= IFF_UP;
1053 		cue_init(sc);
1054 		break;
1055 
1056 	case SIOCSIFFLAGS:
1057 		if (ifp->if_flags & IFF_UP) {
1058 			if (ifp->if_flags & IFF_RUNNING &&
1059 			    ifp->if_flags & IFF_PROMISC &&
1060 			    !(sc->cue_if_flags & IFF_PROMISC)) {
1061 				CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
1062 				cue_setmulti(sc);
1063 			} else if (ifp->if_flags & IFF_RUNNING &&
1064 			    !(ifp->if_flags & IFF_PROMISC) &&
1065 			    sc->cue_if_flags & IFF_PROMISC) {
1066 				CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
1067 				cue_setmulti(sc);
1068 			} else if (!(ifp->if_flags & IFF_RUNNING))
1069 				cue_init(sc);
1070 		} else {
1071 			if (ifp->if_flags & IFF_RUNNING)
1072 				cue_stop(sc);
1073 		}
1074 		sc->cue_if_flags = ifp->if_flags;
1075 		error = 0;
1076 		break;
1077 
1078 	default:
1079 		error = ether_ioctl(ifp, &sc->arpcom, command, data);
1080 	}
1081 
1082 	if (error == ENETRESET) {
1083 		if (ifp->if_flags & IFF_RUNNING)
1084 			cue_setmulti(sc);
1085 		error = 0;
1086 	}
1087 
1088 	splx(s);
1089 	return (error);
1090 }
1091 
1092 void
1093 cue_watchdog(struct ifnet *ifp)
1094 {
1095 	struct cue_softc	*sc = ifp->if_softc;
1096 	struct cue_chain	*c;
1097 	usbd_status		stat;
1098 	int			s;
1099 
1100 	DPRINTFN(5,("%s: %s: enter\n", sc->cue_dev.dv_xname,__func__));
1101 
1102 	if (usbd_is_dying(sc->cue_udev))
1103 		return;
1104 
1105 	ifp->if_oerrors++;
1106 	printf("%s: watchdog timeout\n", sc->cue_dev.dv_xname);
1107 
1108 	s = splusb();
1109 	c = &sc->cue_cdata.cue_tx_chain[0];
1110 	usbd_get_xfer_status(c->cue_xfer, NULL, NULL, NULL, &stat);
1111 	cue_txeof(c->cue_xfer, c, stat);
1112 
1113 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1114 		cue_start(ifp);
1115 	splx(s);
1116 }
1117 
1118 /*
1119  * Stop the adapter and free any mbufs allocated to the
1120  * RX and TX lists.
1121  */
1122 void
1123 cue_stop(struct cue_softc *sc)
1124 {
1125 	usbd_status		err;
1126 	struct ifnet		*ifp;
1127 	int			i;
1128 
1129 	DPRINTFN(10,("%s: %s: enter\n", sc->cue_dev.dv_xname,__func__));
1130 
1131 	ifp = GET_IFP(sc);
1132 	ifp->if_timer = 0;
1133 	ifp->if_flags &= ~IFF_RUNNING;
1134 	ifq_clr_oactive(&ifp->if_snd);
1135 
1136 	cue_csr_write_1(sc, CUE_ETHCTL, 0);
1137 	cue_reset(sc);
1138 	timeout_del(&sc->cue_stat_ch);
1139 
1140 	/* Stop transfers. */
1141 	if (sc->cue_ep[CUE_ENDPT_RX] != NULL) {
1142 		usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_RX]);
1143 		err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_RX]);
1144 		if (err) {
1145 			printf("%s: close rx pipe failed: %s\n",
1146 			sc->cue_dev.dv_xname, usbd_errstr(err));
1147 		}
1148 		sc->cue_ep[CUE_ENDPT_RX] = NULL;
1149 	}
1150 
1151 	if (sc->cue_ep[CUE_ENDPT_TX] != NULL) {
1152 		usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_TX]);
1153 		err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_TX]);
1154 		if (err) {
1155 			printf("%s: close tx pipe failed: %s\n",
1156 			    sc->cue_dev.dv_xname, usbd_errstr(err));
1157 		}
1158 		sc->cue_ep[CUE_ENDPT_TX] = NULL;
1159 	}
1160 
1161 	if (sc->cue_ep[CUE_ENDPT_INTR] != NULL) {
1162 		usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_INTR]);
1163 		err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_INTR]);
1164 		if (err) {
1165 			printf("%s: close intr pipe failed: %s\n",
1166 			    sc->cue_dev.dv_xname, usbd_errstr(err));
1167 		}
1168 		sc->cue_ep[CUE_ENDPT_INTR] = NULL;
1169 	}
1170 
1171 	/* Free RX resources. */
1172 	for (i = 0; i < CUE_RX_LIST_CNT; i++) {
1173 		if (sc->cue_cdata.cue_rx_chain[i].cue_mbuf != NULL) {
1174 			m_freem(sc->cue_cdata.cue_rx_chain[i].cue_mbuf);
1175 			sc->cue_cdata.cue_rx_chain[i].cue_mbuf = NULL;
1176 		}
1177 		if (sc->cue_cdata.cue_rx_chain[i].cue_xfer != NULL) {
1178 			usbd_free_xfer(sc->cue_cdata.cue_rx_chain[i].cue_xfer);
1179 			sc->cue_cdata.cue_rx_chain[i].cue_xfer = NULL;
1180 		}
1181 	}
1182 
1183 	/* Free TX resources. */
1184 	for (i = 0; i < CUE_TX_LIST_CNT; i++) {
1185 		if (sc->cue_cdata.cue_tx_chain[i].cue_mbuf != NULL) {
1186 			m_freem(sc->cue_cdata.cue_tx_chain[i].cue_mbuf);
1187 			sc->cue_cdata.cue_tx_chain[i].cue_mbuf = NULL;
1188 		}
1189 		if (sc->cue_cdata.cue_tx_chain[i].cue_xfer != NULL) {
1190 			usbd_free_xfer(sc->cue_cdata.cue_tx_chain[i].cue_xfer);
1191 			sc->cue_cdata.cue_tx_chain[i].cue_xfer = NULL;
1192 		}
1193 	}
1194 }
1195