7ddeb06da41069b4a9ed922761dde396f9fe93aa
[dragonfly.git] / sys / bus / u4b / net / if_cue.c
1 /*-
2  * Copyright (c) 1997, 1998, 1999, 2000
3  *      Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Bill Paul.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
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@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 #include <sys/stdint.h>
55 #include <sys/stddef.h>
56 #include <sys/param.h>
57 #include <sys/queue.h>
58 #include <sys/types.h>
59 #include <sys/systm.h>
60 #include <sys/kernel.h>
61 #include <sys/bus.h>
62 #include <sys/module.h>
63 #include <sys/lock.h>
64 #include <sys/mutex.h>
65 #include <sys/condvar.h>
66 #include <sys/sysctl.h>
67 #include <sys/sx.h>
68 #include <sys/unistd.h>
69 #include <sys/callout.h>
70 #include <sys/malloc.h>
71 #include <sys/priv.h>
72
73 #include <dev/usb/usb.h>
74 #include <dev/usb/usbdi.h>
75 #include <dev/usb/usbdi_util.h>
76 #include "usbdevs.h"
77
78 #define USB_DEBUG_VAR cue_debug
79 #include <dev/usb/usb_debug.h>
80 #include <dev/usb/usb_process.h>
81
82 #include <dev/usb/net/usb_ethernet.h>
83 #include <dev/usb/net/if_cuereg.h>
84
85 /*
86  * Various supported device vendors/products.
87  */
88
89 /* Belkin F5U111 adapter covered by NETMATE entry */
90
91 static const STRUCT_USB_HOST_ID cue_devs[] = {
92 #define CUE_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
93         CUE_DEV(CATC, NETMATE),
94         CUE_DEV(CATC, NETMATE2),
95         CUE_DEV(SMARTBRIDGES, SMARTLINK),
96 #undef CUE_DEV
97 };
98
99 /* prototypes */
100
101 static device_probe_t cue_probe;
102 static device_attach_t cue_attach;
103 static device_detach_t cue_detach;
104
105 static usb_callback_t cue_bulk_read_callback;
106 static usb_callback_t cue_bulk_write_callback;
107
108 static uether_fn_t cue_attach_post;
109 static uether_fn_t cue_init;
110 static uether_fn_t cue_stop;
111 static uether_fn_t cue_start;
112 static uether_fn_t cue_tick;
113 static uether_fn_t cue_setmulti;
114 static uether_fn_t cue_setpromisc;
115
116 static uint8_t  cue_csr_read_1(struct cue_softc *, uint16_t);
117 static uint16_t cue_csr_read_2(struct cue_softc *, uint8_t);
118 static int      cue_csr_write_1(struct cue_softc *, uint16_t, uint16_t);
119 static int      cue_mem(struct cue_softc *, uint8_t, uint16_t, void *, int);
120 static int      cue_getmac(struct cue_softc *, void *);
121 static uint32_t cue_mchash(const uint8_t *);
122 static void     cue_reset(struct cue_softc *);
123
124 #ifdef USB_DEBUG
125 static int cue_debug = 0;
126
127 static SYSCTL_NODE(_hw_usb, OID_AUTO, cue, CTLFLAG_RW, 0, "USB cue");
128 SYSCTL_INT(_hw_usb_cue, OID_AUTO, debug, CTLFLAG_RW, &cue_debug, 0,
129     "Debug level");
130 #endif
131
132 static const struct usb_config cue_config[CUE_N_TRANSFER] = {
133
134         [CUE_BULK_DT_WR] = {
135                 .type = UE_BULK,
136                 .endpoint = UE_ADDR_ANY,
137                 .direction = UE_DIR_OUT,
138                 .bufsize = (MCLBYTES + 2),
139                 .flags = {.pipe_bof = 1,},
140                 .callback = cue_bulk_write_callback,
141                 .timeout = 10000,       /* 10 seconds */
142         },
143
144         [CUE_BULK_DT_RD] = {
145                 .type = UE_BULK,
146                 .endpoint = UE_ADDR_ANY,
147                 .direction = UE_DIR_IN,
148                 .bufsize = (MCLBYTES + 2),
149                 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
150                 .callback = cue_bulk_read_callback,
151         },
152 };
153
154 static device_method_t cue_methods[] = {
155         /* Device interface */
156         DEVMETHOD(device_probe, cue_probe),
157         DEVMETHOD(device_attach, cue_attach),
158         DEVMETHOD(device_detach, cue_detach),
159
160         DEVMETHOD_END
161 };
162
163 static driver_t cue_driver = {
164         .name = "cue",
165         .methods = cue_methods,
166         .size = sizeof(struct cue_softc),
167 };
168
169 static devclass_t cue_devclass;
170
171 DRIVER_MODULE(cue, uhub, cue_driver, cue_devclass, NULL, NULL);
172 MODULE_DEPEND(cue, uether, 1, 1, 1);
173 MODULE_DEPEND(cue, usb, 1, 1, 1);
174 MODULE_DEPEND(cue, ether, 1, 1, 1);
175 MODULE_VERSION(cue, 1);
176
177 static const struct usb_ether_methods cue_ue_methods = {
178         .ue_attach_post = cue_attach_post,
179         .ue_start = cue_start,
180         .ue_init = cue_init,
181         .ue_stop = cue_stop,
182         .ue_tick = cue_tick,
183         .ue_setmulti = cue_setmulti,
184         .ue_setpromisc = cue_setpromisc,
185 };
186
187 #define CUE_SETBIT(sc, reg, x)                          \
188         cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) | (x))
189
190 #define CUE_CLRBIT(sc, reg, x)                          \
191         cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) & ~(x))
192
193 static uint8_t
194 cue_csr_read_1(struct cue_softc *sc, uint16_t reg)
195 {
196         struct usb_device_request req;
197         uint8_t val;
198
199         req.bmRequestType = UT_READ_VENDOR_DEVICE;
200         req.bRequest = CUE_CMD_READREG;
201         USETW(req.wValue, 0);
202         USETW(req.wIndex, reg);
203         USETW(req.wLength, 1);
204
205         if (uether_do_request(&sc->sc_ue, &req, &val, 1000)) {
206                 /* ignore any errors */
207         }
208         return (val);
209 }
210
211 static uint16_t
212 cue_csr_read_2(struct cue_softc *sc, uint8_t reg)
213 {
214         struct usb_device_request req;
215         uint16_t val;
216
217         req.bmRequestType = UT_READ_VENDOR_DEVICE;
218         req.bRequest = CUE_CMD_READREG;
219         USETW(req.wValue, 0);
220         USETW(req.wIndex, reg);
221         USETW(req.wLength, 2);
222
223         (void)uether_do_request(&sc->sc_ue, &req, &val, 1000);
224         return (le16toh(val));
225 }
226
227 static int
228 cue_csr_write_1(struct cue_softc *sc, uint16_t reg, uint16_t val)
229 {
230         struct usb_device_request req;
231
232         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
233         req.bRequest = CUE_CMD_WRITEREG;
234         USETW(req.wValue, val);
235         USETW(req.wIndex, reg);
236         USETW(req.wLength, 0);
237
238         return (uether_do_request(&sc->sc_ue, &req, NULL, 1000));
239 }
240
241 static int
242 cue_mem(struct cue_softc *sc, uint8_t cmd, uint16_t addr, void *buf, int len)
243 {
244         struct usb_device_request req;
245
246         if (cmd == CUE_CMD_READSRAM)
247                 req.bmRequestType = UT_READ_VENDOR_DEVICE;
248         else
249                 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
250         req.bRequest = cmd;
251         USETW(req.wValue, 0);
252         USETW(req.wIndex, addr);
253         USETW(req.wLength, len);
254
255         return (uether_do_request(&sc->sc_ue, &req, buf, 1000));
256 }
257
258 static int
259 cue_getmac(struct cue_softc *sc, void *buf)
260 {
261         struct usb_device_request req;
262
263         req.bmRequestType = UT_READ_VENDOR_DEVICE;
264         req.bRequest = CUE_CMD_GET_MACADDR;
265         USETW(req.wValue, 0);
266         USETW(req.wIndex, 0);
267         USETW(req.wLength, ETHER_ADDR_LEN);
268
269         return (uether_do_request(&sc->sc_ue, &req, buf, 1000));
270 }
271
272 #define CUE_BITS 9
273
274 static uint32_t
275 cue_mchash(const uint8_t *addr)
276 {
277         uint32_t crc;
278
279         /* Compute CRC for the address value. */
280         crc = ether_crc32_le(addr, ETHER_ADDR_LEN);
281
282         return (crc & ((1 << CUE_BITS) - 1));
283 }
284
285 static void
286 cue_setpromisc(struct usb_ether *ue)
287 {
288         struct cue_softc *sc = uether_getsc(ue);
289         struct ifnet *ifp = uether_getifp(ue);
290
291         CUE_LOCK_ASSERT(sc, MA_OWNED);
292
293         /* if we want promiscuous mode, set the allframes bit */
294         if (ifp->if_flags & IFF_PROMISC)
295                 CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
296         else
297                 CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
298
299         /* write multicast hash-bits */
300         cue_setmulti(ue);
301 }
302
303 static void
304 cue_setmulti(struct usb_ether *ue)
305 {
306         struct cue_softc *sc = uether_getsc(ue);
307         struct ifnet *ifp = uether_getifp(ue);
308         struct ifmultiaddr *ifma;
309         uint32_t h = 0, i;
310         uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
311
312         CUE_LOCK_ASSERT(sc, MA_OWNED);
313
314         if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
315                 for (i = 0; i < 8; i++)
316                         hashtbl[i] = 0xff;
317                 cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
318                     &hashtbl, 8);
319                 return;
320         }
321
322         /* now program new ones */
323         if_maddr_rlock(ifp);
324         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
325         {
326                 if (ifma->ifma_addr->sa_family != AF_LINK)
327                         continue;
328                 h = cue_mchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
329                 hashtbl[h >> 3] |= 1 << (h & 0x7);
330         }
331         if_maddr_runlock(ifp);
332
333         /*
334          * Also include the broadcast address in the filter
335          * so we can receive broadcast frames.
336          */
337         if (ifp->if_flags & IFF_BROADCAST) {
338                 h = cue_mchash(ifp->if_broadcastaddr);
339                 hashtbl[h >> 3] |= 1 << (h & 0x7);
340         }
341
342         cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR, &hashtbl, 8);
343 }
344
345 static void
346 cue_reset(struct cue_softc *sc)
347 {
348         struct usb_device_request req;
349
350         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
351         req.bRequest = CUE_CMD_RESET;
352         USETW(req.wValue, 0);
353         USETW(req.wIndex, 0);
354         USETW(req.wLength, 0);
355
356         if (uether_do_request(&sc->sc_ue, &req, NULL, 1000)) {
357                 /* ignore any errors */
358         }
359
360         /*
361          * wait a little while for the chip to get its brains in order:
362          */
363         uether_pause(&sc->sc_ue, hz / 100);
364 }
365
366 static void
367 cue_attach_post(struct usb_ether *ue)
368 {
369         struct cue_softc *sc = uether_getsc(ue);
370
371         cue_getmac(sc, ue->ue_eaddr);
372 }
373
374 static int
375 cue_probe(device_t dev)
376 {
377         struct usb_attach_arg *uaa = device_get_ivars(dev);
378
379         if (uaa->usb_mode != USB_MODE_HOST)
380                 return (ENXIO);
381         if (uaa->info.bConfigIndex != CUE_CONFIG_IDX)
382                 return (ENXIO);
383         if (uaa->info.bIfaceIndex != CUE_IFACE_IDX)
384                 return (ENXIO);
385
386         return (usbd_lookup_id_by_uaa(cue_devs, sizeof(cue_devs), uaa));
387 }
388
389 /*
390  * Attach the interface. Allocate softc structures, do ifmedia
391  * setup and ethernet/BPF attach.
392  */
393 static int
394 cue_attach(device_t dev)
395 {
396         struct usb_attach_arg *uaa = device_get_ivars(dev);
397         struct cue_softc *sc = device_get_softc(dev);
398         struct usb_ether *ue = &sc->sc_ue;
399         uint8_t iface_index;
400         int error;
401
402         device_set_usb_desc(dev);
403         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
404
405         iface_index = CUE_IFACE_IDX;
406         error = usbd_transfer_setup(uaa->device, &iface_index,
407             sc->sc_xfer, cue_config, CUE_N_TRANSFER, sc, &sc->sc_mtx);
408         if (error) {
409                 device_printf(dev, "allocating USB transfers failed\n");
410                 goto detach;
411         }
412
413         ue->ue_sc = sc;
414         ue->ue_dev = dev;
415         ue->ue_udev = uaa->device;
416         ue->ue_mtx = &sc->sc_mtx;
417         ue->ue_methods = &cue_ue_methods;
418
419         error = uether_ifattach(ue);
420         if (error) {
421                 device_printf(dev, "could not attach interface\n");
422                 goto detach;
423         }
424         return (0);                     /* success */
425
426 detach:
427         cue_detach(dev);
428         return (ENXIO);                 /* failure */
429 }
430
431 static int
432 cue_detach(device_t dev)
433 {
434         struct cue_softc *sc = device_get_softc(dev);
435         struct usb_ether *ue = &sc->sc_ue;
436
437         usbd_transfer_unsetup(sc->sc_xfer, CUE_N_TRANSFER);
438         uether_ifdetach(ue);
439         mtx_destroy(&sc->sc_mtx);
440
441         return (0);
442 }
443
444 static void
445 cue_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
446 {
447         struct cue_softc *sc = usbd_xfer_softc(xfer);
448         struct usb_ether *ue = &sc->sc_ue;
449         struct ifnet *ifp = uether_getifp(ue);
450         struct usb_page_cache *pc;
451         uint8_t buf[2];
452         int len;
453         int actlen;
454
455         usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
456
457         switch (USB_GET_STATE(xfer)) {
458         case USB_ST_TRANSFERRED:
459
460                 if (actlen <= (2 + sizeof(struct ether_header))) {
461                         ifp->if_ierrors++;
462                         goto tr_setup;
463                 }
464                 pc = usbd_xfer_get_frame(xfer, 0);
465                 usbd_copy_out(pc, 0, buf, 2);
466                 actlen -= 2;
467                 len = buf[0] | (buf[1] << 8);
468                 len = min(actlen, len);
469
470                 uether_rxbuf(ue, pc, 2, len);
471                 /* FALLTHROUGH */
472         case USB_ST_SETUP:
473 tr_setup:
474                 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
475                 usbd_transfer_submit(xfer);
476                 uether_rxflush(ue);
477                 return;
478
479         default:                        /* Error */
480                 DPRINTF("bulk read error, %s\n",
481                     usbd_errstr(error));
482
483                 if (error != USB_ERR_CANCELLED) {
484                         /* try to clear stall first */
485                         usbd_xfer_set_stall(xfer);
486                         goto tr_setup;
487                 }
488                 return;
489
490         }
491 }
492
493 static void
494 cue_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
495 {
496         struct cue_softc *sc = usbd_xfer_softc(xfer);
497         struct ifnet *ifp = uether_getifp(&sc->sc_ue);
498         struct usb_page_cache *pc;
499         struct mbuf *m;
500         uint8_t buf[2];
501
502         switch (USB_GET_STATE(xfer)) {
503         case USB_ST_TRANSFERRED:
504                 DPRINTFN(11, "transfer complete\n");
505                 ifp->if_opackets++;
506
507                 /* FALLTHROUGH */
508         case USB_ST_SETUP:
509 tr_setup:
510                 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
511
512                 if (m == NULL)
513                         return;
514                 if (m->m_pkthdr.len > MCLBYTES)
515                         m->m_pkthdr.len = MCLBYTES;
516                 usbd_xfer_set_frame_len(xfer, 0, (m->m_pkthdr.len + 2));
517
518                 /* the first two bytes are the frame length */
519
520                 buf[0] = (uint8_t)(m->m_pkthdr.len);
521                 buf[1] = (uint8_t)(m->m_pkthdr.len >> 8);
522
523                 pc = usbd_xfer_get_frame(xfer, 0);
524                 usbd_copy_in(pc, 0, buf, 2);
525                 usbd_m_copy_in(pc, 2, m, 0, m->m_pkthdr.len);
526
527                 /*
528                  * If there's a BPF listener, bounce a copy of this frame
529                  * to him.
530                  */
531                 BPF_MTAP(ifp, m);
532
533                 m_freem(m);
534
535                 usbd_transfer_submit(xfer);
536
537                 return;
538
539         default:                        /* Error */
540                 DPRINTFN(11, "transfer error, %s\n",
541                     usbd_errstr(error));
542
543                 ifp->if_oerrors++;
544
545                 if (error != USB_ERR_CANCELLED) {
546                         /* try to clear stall first */
547                         usbd_xfer_set_stall(xfer);
548                         goto tr_setup;
549                 }
550                 return;
551         }
552 }
553
554 static void
555 cue_tick(struct usb_ether *ue)
556 {
557         struct cue_softc *sc = uether_getsc(ue);
558         struct ifnet *ifp = uether_getifp(ue);
559
560         CUE_LOCK_ASSERT(sc, MA_OWNED);
561
562         ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_SINGLECOLL);
563         ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_MULTICOLL);
564         ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_EXCESSCOLL);
565
566         if (cue_csr_read_2(sc, CUE_RX_FRAMEERR))
567                 ifp->if_ierrors++;
568 }
569
570 static void
571 cue_start(struct usb_ether *ue)
572 {
573         struct cue_softc *sc = uether_getsc(ue);
574
575         /*
576          * start the USB transfers, if not already started:
577          */
578         usbd_transfer_start(sc->sc_xfer[CUE_BULK_DT_RD]);
579         usbd_transfer_start(sc->sc_xfer[CUE_BULK_DT_WR]);
580 }
581
582 static void
583 cue_init(struct usb_ether *ue)
584 {
585         struct cue_softc *sc = uether_getsc(ue);
586         struct ifnet *ifp = uether_getifp(ue);
587         int i;
588
589         CUE_LOCK_ASSERT(sc, MA_OWNED);
590
591         /*
592          * Cancel pending I/O and free all RX/TX buffers.
593          */
594         cue_stop(ue);
595 #if 0
596         cue_reset(sc);
597 #endif
598         /* Set MAC address */
599         for (i = 0; i < ETHER_ADDR_LEN; i++)
600                 cue_csr_write_1(sc, CUE_PAR0 - i, IF_LLADDR(ifp)[i]);
601
602         /* Enable RX logic. */
603         cue_csr_write_1(sc, CUE_ETHCTL, CUE_ETHCTL_RX_ON | CUE_ETHCTL_MCAST_ON);
604
605         /* Load the multicast filter */
606         cue_setpromisc(ue);
607
608         /*
609          * Set the number of RX and TX buffers that we want
610          * to reserve inside the ASIC.
611          */
612         cue_csr_write_1(sc, CUE_RX_BUFPKTS, CUE_RX_FRAMES);
613         cue_csr_write_1(sc, CUE_TX_BUFPKTS, CUE_TX_FRAMES);
614
615         /* Set advanced operation modes. */
616         cue_csr_write_1(sc, CUE_ADVANCED_OPMODES,
617             CUE_AOP_EMBED_RXLEN | 0x01);/* 1 wait state */
618
619         /* Program the LED operation. */
620         cue_csr_write_1(sc, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK);
621
622         usbd_xfer_set_stall(sc->sc_xfer[CUE_BULK_DT_WR]);
623
624         ifp->if_drv_flags |= IFF_DRV_RUNNING;
625         cue_start(ue);
626 }
627
628 /*
629  * Stop the adapter and free any mbufs allocated to the
630  * RX and TX lists.
631  */
632 static void
633 cue_stop(struct usb_ether *ue)
634 {
635         struct cue_softc *sc = uether_getsc(ue);
636         struct ifnet *ifp = uether_getifp(ue);
637
638         CUE_LOCK_ASSERT(sc, MA_OWNED);
639
640         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
641
642         /*
643          * stop all the transfers, if not already stopped:
644          */
645         usbd_transfer_stop(sc->sc_xfer[CUE_BULK_DT_WR]);
646         usbd_transfer_stop(sc->sc_xfer[CUE_BULK_DT_RD]);
647
648         cue_csr_write_1(sc, CUE_ETHCTL, 0);
649         cue_reset(sc);
650 }