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