if_cue.c revision 188412
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: head/sys/dev/usb2/ethernet/if_cue2.c 188412 2009-02-09 22:02:38Z thompsa $");
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 <dev/usb2/include/usb2_devid.h>
55#include <dev/usb2/include/usb2_standard.h>
56#include <dev/usb2/include/usb2_mfunc.h>
57#include <dev/usb2/include/usb2_error.h>
58
59#define	USB_DEBUG_VAR cue_debug
60
61#include <dev/usb2/core/usb2_core.h>
62#include <dev/usb2/core/usb2_lookup.h>
63#include <dev/usb2/core/usb2_process.h>
64#include <dev/usb2/core/usb2_debug.h>
65#include <dev/usb2/core/usb2_request.h>
66#include <dev/usb2/core/usb2_busdma.h>
67#include <dev/usb2/core/usb2_util.h>
68
69#include <dev/usb2/ethernet/usb2_ethernet.h>
70#include <dev/usb2/ethernet/if_cuereg.h>
71
72/*
73 * Various supported device vendors/products.
74 */
75
76/* Belkin F5U111 adapter covered by NETMATE entry */
77
78static const struct usb2_device_id cue_devs[] = {
79	{USB_VPI(USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE, 0)},
80	{USB_VPI(USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE2, 0)},
81	{USB_VPI(USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTLINK, 0)},
82};
83
84/* prototypes */
85
86static device_probe_t cue_probe;
87static device_attach_t cue_attach;
88static device_detach_t cue_detach;
89static device_shutdown_t cue_shutdown;
90
91static usb2_callback_t cue_bulk_read_callback;
92static usb2_callback_t cue_bulk_write_callback;
93
94static usb2_ether_fn_t cue_attach_post;
95static usb2_ether_fn_t cue_init;
96static usb2_ether_fn_t cue_stop;
97static usb2_ether_fn_t cue_start;
98static usb2_ether_fn_t cue_tick;
99static usb2_ether_fn_t cue_setmulti;
100static usb2_ether_fn_t cue_setpromisc;
101
102static uint8_t	cue_csr_read_1(struct cue_softc *, uint16_t);
103static uint16_t	cue_csr_read_2(struct cue_softc *, uint8_t);
104static int	cue_csr_write_1(struct cue_softc *, uint16_t, uint16_t);
105static int	cue_mem(struct cue_softc *, uint8_t, uint16_t, void *, int);
106static int	cue_getmac(struct cue_softc *, void *);
107static uint32_t	cue_mchash(const uint8_t *);
108static void	cue_reset(struct cue_softc *);
109
110#if USB_DEBUG
111static int cue_debug = 0;
112
113SYSCTL_NODE(_hw_usb2, OID_AUTO, cue, CTLFLAG_RW, 0, "USB cue");
114SYSCTL_INT(_hw_usb2_cue, OID_AUTO, debug, CTLFLAG_RW, &cue_debug, 0,
115    "Debug level");
116#endif
117
118static const struct usb2_config cue_config[CUE_N_TRANSFER] = {
119
120	[CUE_BULK_DT_WR] = {
121		.type = UE_BULK,
122		.endpoint = UE_ADDR_ANY,
123		.direction = UE_DIR_OUT,
124		.mh.bufsize = (MCLBYTES + 2),
125		.mh.flags = {.pipe_bof = 1,},
126		.mh.callback = cue_bulk_write_callback,
127		.mh.timeout = 10000,	/* 10 seconds */
128	},
129
130	[CUE_BULK_DT_RD] = {
131		.type = UE_BULK,
132		.endpoint = UE_ADDR_ANY,
133		.direction = UE_DIR_IN,
134		.mh.bufsize = (MCLBYTES + 2),
135		.mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
136		.mh.callback = cue_bulk_read_callback,
137	},
138};
139
140static device_method_t cue_methods[] = {
141	/* Device interface */
142	DEVMETHOD(device_probe, cue_probe),
143	DEVMETHOD(device_attach, cue_attach),
144	DEVMETHOD(device_detach, cue_detach),
145	DEVMETHOD(device_shutdown, cue_shutdown),
146
147	{0, 0}
148};
149
150static driver_t cue_driver = {
151	.name = "cue",
152	.methods = cue_methods,
153	.size = sizeof(struct cue_softc),
154};
155
156static devclass_t cue_devclass;
157
158DRIVER_MODULE(cue, ushub, cue_driver, cue_devclass, NULL, 0);
159MODULE_DEPEND(cue, usb2_ethernet, 1, 1, 1);
160MODULE_DEPEND(cue, usb2_core, 1, 1, 1);
161MODULE_DEPEND(cue, ether, 1, 1, 1);
162
163static const struct usb2_ether_methods cue_ue_methods = {
164	.ue_attach_post = cue_attach_post,
165	.ue_start = cue_start,
166	.ue_init = cue_init,
167	.ue_stop = cue_stop,
168	.ue_tick = cue_tick,
169	.ue_setmulti = cue_setmulti,
170	.ue_setpromisc = cue_setpromisc,
171};
172
173#define	CUE_SETBIT(sc, reg, x)				\
174	cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) | (x))
175
176#define	CUE_CLRBIT(sc, reg, x)				\
177	cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) & ~(x))
178
179static uint8_t
180cue_csr_read_1(struct cue_softc *sc, uint16_t reg)
181{
182	struct usb2_device_request req;
183	uint8_t val;
184
185	req.bmRequestType = UT_READ_VENDOR_DEVICE;
186	req.bRequest = CUE_CMD_READREG;
187	USETW(req.wValue, 0);
188	USETW(req.wIndex, reg);
189	USETW(req.wLength, 1);
190
191	if (usb2_ether_do_request(&sc->sc_ue, &req, &val, 1000)) {
192		/* ignore any errors */
193	}
194	return (val);
195}
196
197static uint16_t
198cue_csr_read_2(struct cue_softc *sc, uint8_t reg)
199{
200	struct usb2_device_request req;
201	uint16_t val;
202
203	req.bmRequestType = UT_READ_VENDOR_DEVICE;
204	req.bRequest = CUE_CMD_READREG;
205	USETW(req.wValue, 0);
206	USETW(req.wIndex, reg);
207	USETW(req.wLength, 2);
208
209	(void)usb2_ether_do_request(&sc->sc_ue, &req, &val, 1000);
210	return (le16toh(val));
211}
212
213static int
214cue_csr_write_1(struct cue_softc *sc, uint16_t reg, uint16_t val)
215{
216	struct usb2_device_request req;
217
218	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
219	req.bRequest = CUE_CMD_WRITEREG;
220	USETW(req.wValue, val);
221	USETW(req.wIndex, reg);
222	USETW(req.wLength, 0);
223
224	return (usb2_ether_do_request(&sc->sc_ue, &req, NULL, 1000));
225}
226
227static int
228cue_mem(struct cue_softc *sc, uint8_t cmd, uint16_t addr, void *buf, int len)
229{
230	struct usb2_device_request req;
231
232	if (cmd == CUE_CMD_READSRAM)
233		req.bmRequestType = UT_READ_VENDOR_DEVICE;
234	else
235		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
236	req.bRequest = cmd;
237	USETW(req.wValue, 0);
238	USETW(req.wIndex, addr);
239	USETW(req.wLength, len);
240
241	return (usb2_ether_do_request(&sc->sc_ue, &req, buf, 1000));
242}
243
244static int
245cue_getmac(struct cue_softc *sc, void *buf)
246{
247	struct usb2_device_request req;
248
249	req.bmRequestType = UT_READ_VENDOR_DEVICE;
250	req.bRequest = CUE_CMD_GET_MACADDR;
251	USETW(req.wValue, 0);
252	USETW(req.wIndex, 0);
253	USETW(req.wLength, ETHER_ADDR_LEN);
254
255	return (usb2_ether_do_request(&sc->sc_ue, &req, buf, 1000));
256}
257
258#define	CUE_BITS 9
259
260static uint32_t
261cue_mchash(const uint8_t *addr)
262{
263	uint32_t crc;
264
265	/* Compute CRC for the address value. */
266	crc = ether_crc32_le(addr, ETHER_ADDR_LEN);
267
268	return (crc & ((1 << CUE_BITS) - 1));
269}
270
271static void
272cue_setpromisc(struct usb2_ether *ue)
273{
274	struct cue_softc *sc = usb2_ether_getsc(ue);
275	struct ifnet *ifp = usb2_ether_getifp(ue);
276
277	CUE_LOCK_ASSERT(sc, MA_OWNED);
278
279	/* if we want promiscuous mode, set the allframes bit */
280	if (ifp->if_flags & IFF_PROMISC)
281		CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
282	else
283		CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
284
285	/* write multicast hash-bits */
286	cue_setmulti(ue);
287}
288
289static void
290cue_setmulti(struct usb2_ether *ue)
291{
292	struct cue_softc *sc = usb2_ether_getsc(ue);
293	struct ifnet *ifp = usb2_ether_getifp(ue);
294	struct ifmultiaddr *ifma;
295	uint32_t h = 0, i;
296	uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
297
298	CUE_LOCK_ASSERT(sc, MA_OWNED);
299
300	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
301		for (i = 0; i < 8; i++)
302			hashtbl[i] = 0xff;
303		cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
304		    &hashtbl, 8);
305		return;
306	}
307
308	/* now program new ones */
309	IF_ADDR_LOCK(ifp);
310	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
311	{
312		if (ifma->ifma_addr->sa_family != AF_LINK)
313			continue;
314		h = cue_mchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
315		hashtbl[h >> 3] |= 1 << (h & 0x7);
316	}
317	IF_ADDR_UNLOCK(ifp);
318
319	/*
320	 * Also include the broadcast address in the filter
321	 * so we can receive broadcast frames.
322 	 */
323	if (ifp->if_flags & IFF_BROADCAST) {
324		h = cue_mchash(ifp->if_broadcastaddr);
325		hashtbl[h >> 3] |= 1 << (h & 0x7);
326	}
327
328	cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR, &hashtbl, 8);
329}
330
331static void
332cue_reset(struct cue_softc *sc)
333{
334	struct usb2_device_request req;
335
336	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
337	req.bRequest = CUE_CMD_RESET;
338	USETW(req.wValue, 0);
339	USETW(req.wIndex, 0);
340	USETW(req.wLength, 0);
341
342	if (usb2_ether_do_request(&sc->sc_ue, &req, NULL, 1000)) {
343		/* ignore any errors */
344	}
345
346	/*
347	 * wait a little while for the chip to get its brains in order:
348	 */
349	usb2_ether_pause(&sc->sc_ue, hz / 100);
350}
351
352static void
353cue_attach_post(struct usb2_ether *ue)
354{
355	struct cue_softc *sc = usb2_ether_getsc(ue);
356
357	cue_getmac(sc, ue->ue_eaddr);
358}
359
360static int
361cue_probe(device_t dev)
362{
363	struct usb2_attach_arg *uaa = device_get_ivars(dev);
364
365	if (uaa->usb2_mode != USB_MODE_HOST)
366		return (ENXIO);
367	if (uaa->info.bConfigIndex != CUE_CONFIG_IDX)
368		return (ENXIO);
369	if (uaa->info.bIfaceIndex != CUE_IFACE_IDX)
370		return (ENXIO);
371
372	return (usb2_lookup_id_by_uaa(cue_devs, sizeof(cue_devs), uaa));
373}
374
375/*
376 * Attach the interface. Allocate softc structures, do ifmedia
377 * setup and ethernet/BPF attach.
378 */
379static int
380cue_attach(device_t dev)
381{
382	struct usb2_attach_arg *uaa = device_get_ivars(dev);
383	struct cue_softc *sc = device_get_softc(dev);
384	struct usb2_ether *ue = &sc->sc_ue;
385	uint8_t iface_index;
386	int error;
387
388	device_set_usb2_desc(dev);
389	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
390
391	iface_index = CUE_IFACE_IDX;
392	error = usb2_transfer_setup(uaa->device, &iface_index,
393	    sc->sc_xfer, cue_config, CUE_N_TRANSFER, sc, &sc->sc_mtx);
394	if (error) {
395		device_printf(dev, "allocating USB transfers failed!\n");
396		goto detach;
397	}
398
399	ue->ue_sc = sc;
400	ue->ue_dev = dev;
401	ue->ue_udev = uaa->device;
402	ue->ue_mtx = &sc->sc_mtx;
403	ue->ue_methods = &cue_ue_methods;
404
405	error = usb2_ether_ifattach(ue);
406	if (error) {
407		device_printf(dev, "could not attach interface\n");
408		goto detach;
409	}
410	return (0);			/* success */
411
412detach:
413	cue_detach(dev);
414	return (ENXIO);			/* failure */
415}
416
417static int
418cue_detach(device_t dev)
419{
420	struct cue_softc *sc = device_get_softc(dev);
421	struct usb2_ether *ue = &sc->sc_ue;
422
423	usb2_transfer_unsetup(sc->sc_xfer, CUE_N_TRANSFER);
424	usb2_ether_ifdetach(ue);
425	mtx_destroy(&sc->sc_mtx);
426
427	return (0);
428}
429
430static void
431cue_bulk_read_callback(struct usb2_xfer *xfer)
432{
433	struct cue_softc *sc = xfer->priv_sc;
434	struct usb2_ether *ue = &sc->sc_ue;
435	struct ifnet *ifp = usb2_ether_getifp(ue);
436	uint8_t buf[2];
437	int len;
438
439	switch (USB_GET_STATE(xfer)) {
440	case USB_ST_TRANSFERRED:
441
442		if (xfer->actlen <= (2 + sizeof(struct ether_header))) {
443			ifp->if_ierrors++;
444			goto tr_setup;
445		}
446		usb2_copy_out(xfer->frbuffers, 0, buf, 2);
447		xfer->actlen -= 2;
448		len = buf[0] | (buf[1] << 8);
449		len = min(xfer->actlen, len);
450
451		usb2_ether_rxbuf(ue, xfer->frbuffers, 2, len);
452		/* FALLTHROUGH */
453	case USB_ST_SETUP:
454tr_setup:
455		xfer->frlengths[0] = xfer->max_data_length;
456		usb2_start_hardware(xfer);
457		usb2_ether_rxflush(ue);
458		return;
459
460	default:			/* Error */
461		DPRINTF("bulk read error, %s\n",
462		    usb2_errstr(xfer->error));
463
464		if (xfer->error != USB_ERR_CANCELLED) {
465			/* try to clear stall first */
466			xfer->flags.stall_pipe = 1;
467			goto tr_setup;
468		}
469		return;
470
471	}
472}
473
474static void
475cue_bulk_write_callback(struct usb2_xfer *xfer)
476{
477	struct cue_softc *sc = xfer->priv_sc;
478	struct ifnet *ifp = usb2_ether_getifp(&sc->sc_ue);
479	struct mbuf *m;
480	uint8_t buf[2];
481
482	switch (USB_GET_STATE(xfer)) {
483	case USB_ST_TRANSFERRED:
484		DPRINTFN(11, "transfer complete\n");
485		ifp->if_opackets++;
486
487		/* FALLTHROUGH */
488	case USB_ST_SETUP:
489tr_setup:
490		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
491
492		if (m == NULL)
493			return;
494		if (m->m_pkthdr.len > MCLBYTES)
495			m->m_pkthdr.len = MCLBYTES;
496		xfer->frlengths[0] = (m->m_pkthdr.len + 2);
497
498		/* the first two bytes are the frame length */
499
500		buf[0] = (uint8_t)(m->m_pkthdr.len);
501		buf[1] = (uint8_t)(m->m_pkthdr.len >> 8);
502
503		usb2_copy_in(xfer->frbuffers, 0, buf, 2);
504
505		usb2_m_copy_in(xfer->frbuffers, 2,
506		    m, 0, m->m_pkthdr.len);
507
508		/*
509		 * If there's a BPF listener, bounce a copy of this frame
510		 * to him.
511		 */
512		BPF_MTAP(ifp, m);
513
514		m_freem(m);
515
516		usb2_start_hardware(xfer);
517
518		return;
519
520	default:			/* Error */
521		DPRINTFN(11, "transfer error, %s\n",
522		    usb2_errstr(xfer->error));
523
524		ifp->if_oerrors++;
525
526		if (xfer->error != USB_ERR_CANCELLED) {
527			/* try to clear stall first */
528			xfer->flags.stall_pipe = 1;
529			goto tr_setup;
530		}
531		return;
532	}
533}
534
535static void
536cue_tick(struct usb2_ether *ue)
537{
538	struct cue_softc *sc = usb2_ether_getsc(ue);
539	struct ifnet *ifp = usb2_ether_getifp(ue);
540
541	CUE_LOCK_ASSERT(sc, MA_OWNED);
542
543	ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_SINGLECOLL);
544	ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_MULTICOLL);
545	ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_EXCESSCOLL);
546
547	if (cue_csr_read_2(sc, CUE_RX_FRAMEERR))
548		ifp->if_ierrors++;
549}
550
551static void
552cue_start(struct usb2_ether *ue)
553{
554	struct cue_softc *sc = usb2_ether_getsc(ue);
555
556	/*
557	 * start the USB transfers, if not already started:
558	 */
559	usb2_transfer_start(sc->sc_xfer[CUE_BULK_DT_RD]);
560	usb2_transfer_start(sc->sc_xfer[CUE_BULK_DT_WR]);
561}
562
563static void
564cue_init(struct usb2_ether *ue)
565{
566	struct cue_softc *sc = usb2_ether_getsc(ue);
567	struct ifnet *ifp = usb2_ether_getifp(ue);
568	int i;
569
570	CUE_LOCK_ASSERT(sc, MA_OWNED);
571
572	/*
573	 * Cancel pending I/O and free all RX/TX buffers.
574	 */
575	cue_stop(ue);
576#if 0
577	cue_reset(sc);
578#endif
579	/* Set MAC address */
580	for (i = 0; i < ETHER_ADDR_LEN; i++)
581		cue_csr_write_1(sc, CUE_PAR0 - i, IF_LLADDR(ifp)[i]);
582
583	/* Enable RX logic. */
584	cue_csr_write_1(sc, CUE_ETHCTL, CUE_ETHCTL_RX_ON | CUE_ETHCTL_MCAST_ON);
585
586	/* Load the multicast filter */
587	cue_setpromisc(ue);
588
589	/*
590	 * Set the number of RX and TX buffers that we want
591	 * to reserve inside the ASIC.
592	 */
593	cue_csr_write_1(sc, CUE_RX_BUFPKTS, CUE_RX_FRAMES);
594	cue_csr_write_1(sc, CUE_TX_BUFPKTS, CUE_TX_FRAMES);
595
596	/* Set advanced operation modes. */
597	cue_csr_write_1(sc, CUE_ADVANCED_OPMODES,
598	    CUE_AOP_EMBED_RXLEN | 0x01);/* 1 wait state */
599
600	/* Program the LED operation. */
601	cue_csr_write_1(sc, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK);
602
603	usb2_transfer_set_stall(sc->sc_xfer[CUE_BULK_DT_WR]);
604
605	ifp->if_drv_flags |= IFF_DRV_RUNNING;
606	cue_start(ue);
607}
608
609/*
610 * Stop the adapter and free any mbufs allocated to the
611 * RX and TX lists.
612 */
613static void
614cue_stop(struct usb2_ether *ue)
615{
616	struct cue_softc *sc = usb2_ether_getsc(ue);
617	struct ifnet *ifp = usb2_ether_getifp(ue);
618
619	CUE_LOCK_ASSERT(sc, MA_OWNED);
620
621	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
622
623	/*
624	 * stop all the transfers, if not already stopped:
625	 */
626	usb2_transfer_stop(sc->sc_xfer[CUE_BULK_DT_WR]);
627	usb2_transfer_stop(sc->sc_xfer[CUE_BULK_DT_RD]);
628
629	cue_csr_write_1(sc, CUE_ETHCTL, 0);
630	cue_reset(sc);
631}
632
633/*
634 * Stop all chip I/O so that the kernel's probe routines don't
635 * get confused by errant DMAs when rebooting.
636 */
637static int
638cue_shutdown(device_t dev)
639{
640	struct cue_softc *sc = device_get_softc(dev);
641
642	usb2_ether_ifshutdown(&sc->sc_ue);
643
644	return (0);
645}
646