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