Annotation of src/sys/dev/usb/if_kue.c, Revision 1.102
1.102 ! thorpej 1: /* $NetBSD: if_kue.c,v 1.101 2020/01/07 06:42:26 maxv Exp $ */
1.77 mrg 2:
1.1 augustss 3: /*
4: * Copyright (c) 1997, 1998, 1999, 2000
5: * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Bill Paul.
18: * 4. Neither the name of the author nor the names of any co-contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32: * THE POSSIBILITY OF SUCH DAMAGE.
33: *
34: * $FreeBSD: src/sys/dev/usb/if_kue.c,v 1.14 2000/01/14 01:36:15 wpaul Exp $
35: */
36:
37: /*
38: * Kawasaki LSI KL5KUSB101B USB to ethernet adapter driver.
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 KLSI USB to ethernet adapter chip contains an USB serial interface,
47: * ethernet MAC and embedded microcontroller (called the QT Engine).
48: * The chip must have firmware loaded into it before it will operate.
49: * Packets are passed between the chip and host via bulk transfers.
50: * There is an interrupt endpoint mentioned in the software spec, however
51: * it's currently unused. This device is 10Mbps half-duplex only, hence
52: * there is no media selection logic. The MAC supports a 128 entry
53: * multicast filter, though the exact size of the filter can depend
54: * on the firmware. Curiously, while the software spec describes various
55: * ethernet statistics counters, my sample adapter and firmware combination
56: * claims not to support any statistics counters at all.
57: *
58: * Note that once we load the firmware in the device, we have to be
59: * careful not to load it again: if you restart your computer but
60: * leave the adapter attached to the USB controller, it may remain
61: * powered on and retain its firmware. In this case, we don't need
62: * to load the firmware a second time.
63: *
64: * Special thanks to Rob Furr for providing an ADS Technologies
65: * adapter for development and testing. No monkeys were harmed during
66: * the development of this driver.
67: */
68:
69: /*
70: * Ported to NetBSD and somewhat rewritten by Lennart Augustsson.
71: */
1.44 lukem 72:
73: #include <sys/cdefs.h>
1.102 ! thorpej 74: __KERNEL_RCSID(0, "$NetBSD: if_kue.c,v 1.101 2020/01/07 06:42:26 maxv Exp $");
1.1 augustss 75:
1.79 christos 76: #ifdef _KERNEL_OPT
1.1 augustss 77: #include "opt_inet.h"
1.87 skrll 78: #include "opt_usb.h"
1.79 christos 79: #endif
1.1 augustss 80:
81: #include <sys/param.h>
1.84 skrll 82: #include <sys/kmem.h>
1.98 mrg 83:
84: #include <dev/usb/usbnet.h>
1.1 augustss 85:
86: #ifdef INET
1.49 augustss 87: #include <netinet/in.h>
1.1 augustss 88: #include <netinet/if_inarp.h>
89: #endif
90:
91: #include <dev/usb/if_kuereg.h>
92: #include <dev/usb/kue_fw.h>
93:
94: #ifdef KUE_DEBUG
1.74 dyoung 95: #define DPRINTF(x) if (kuedebug) printf x
1.94 msaitoh 96: #define DPRINTFN(n, x) if (kuedebug >= (n)) printf x
1.1 augustss 97: int kuedebug = 0;
98: #else
99: #define DPRINTF(x)
1.94 msaitoh 100: #define DPRINTFN(n, x)
1.1 augustss 101: #endif
102:
1.98 mrg 103: struct kue_type {
104: uint16_t kue_vid;
105: uint16_t kue_did;
106: };
107:
108: struct kue_softc {
109: struct usbnet kue_un;
110:
111: struct kue_ether_desc kue_desc;
112: uint16_t kue_rxfilt;
113: uint8_t *kue_mcfilters;
114: };
115:
116: #define KUE_MCFILT(x, y) \
117: (uint8_t *)&(sc->kue_mcfilters[y * ETHER_ADDR_LEN])
118:
119: #define KUE_BUFSZ 1536
120: #define KUE_MIN_FRAMELEN 60
121:
122: #define KUE_RX_LIST_CNT 1
123: #define KUE_TX_LIST_CNT 1
124:
1.1 augustss 125: /*
126: * Various supported device vendors/products.
127: */
1.72 tsutsui 128: static const struct usb_devno kue_devs[] = {
1.42 augustss 129: { USB_VENDOR_3COM, USB_PRODUCT_3COM_3C19250 },
130: { USB_VENDOR_3COM, USB_PRODUCT_3COM_3C460 },
131: { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_URE450 },
132: { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BT },
1.43 augustss 133: { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BTX },
1.99 mrg 134: { USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_KL5KUSB101 },
135: { USB_VENDOR_ALLIEDTELESYN, USB_PRODUCT_ALLIEDTELESYN_AT_USB10 },
1.1 augustss 136: { USB_VENDOR_AOX, USB_PRODUCT_AOX_USB101 },
1.43 augustss 137: { USB_VENDOR_ASANTE, USB_PRODUCT_ASANTE_EA },
1.1 augustss 138: { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC10T },
1.43 augustss 139: { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_DSB650C },
1.42 augustss 140: { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_ETHER_USB_T },
141: { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650C },
142: { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_E45 },
1.43 augustss 143: { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_XX1 },
144: { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_XX2 },
1.42 augustss 145: { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETT },
1.43 augustss 146: { USB_VENDOR_JATON, USB_PRODUCT_JATON_EDA },
147: { USB_VENDOR_KINGSTON, USB_PRODUCT_KINGSTON_XX1 },
1.42 augustss 148: { USB_VENDOR_KLSI, USB_PRODUCT_KLSI_DUH3E10BT },
1.43 augustss 149: { USB_VENDOR_KLSI, USB_PRODUCT_KLSI_DUH3E10BTN },
1.42 augustss 150: { USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10T },
1.43 augustss 151: { USB_VENDOR_MOBILITY, USB_PRODUCT_MOBILITY_EA },
1.1 augustss 152: { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101 },
1.43 augustss 153: { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101X },
1.1 augustss 154: { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET },
155: { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET2 },
1.40 augustss 156: { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET3 },
1.43 augustss 157: { USB_VENDOR_PORTGEAR, USB_PRODUCT_PORTGEAR_EA8 },
158: { USB_VENDOR_PORTGEAR, USB_PRODUCT_PORTGEAR_EA9 },
159: { USB_VENDOR_PORTSMITH, USB_PRODUCT_PORTSMITH_EEA },
160: { USB_VENDOR_SHARK, USB_PRODUCT_SHARK_PA },
1.52 augustss 161: { USB_VENDOR_SILICOM, USB_PRODUCT_SILICOM_U2E },
1.99 mrg 162: { USB_VENDOR_SILICOM, USB_PRODUCT_SILICOM_GPE },
1.1 augustss 163: { USB_VENDOR_SMC, USB_PRODUCT_SMC_2102USB },
164: };
1.46 augustss 165: #define kue_lookup(v, p) (usb_lookup(kue_devs, v, p))
1.1 augustss 166:
1.101 maxv 167: static int kue_match(device_t, cfdata_t, void *);
168: static void kue_attach(device_t, device_t, void *);
169: static int kue_detach(device_t, int);
1.93 mrg 170:
1.74 dyoung 171: CFATTACH_DECL_NEW(kue, sizeof(struct kue_softc), kue_match, kue_attach,
1.98 mrg 172: kue_detach, usbnet_activate);
1.1 augustss 173:
1.98 mrg 174: static void kue_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t);
175: static unsigned kue_tx_prepare(struct usbnet *, struct mbuf *,
176: struct usbnet_chain *);
177: static int kue_ioctl_cb(struct ifnet *, u_long, void *);
178: static int kue_init(struct ifnet *);
179:
1.101 maxv 180: static const struct usbnet_ops kue_ops = {
1.98 mrg 181: .uno_ioctl = kue_ioctl_cb,
182: .uno_tx_prepare = kue_tx_prepare,
183: .uno_rx_loop = kue_rx_loop,
184: .uno_init = kue_init,
185: };
1.29 augustss 186:
1.98 mrg 187: static void kue_setiff(struct usbnet *);
188: static void kue_reset(struct usbnet *);
1.29 augustss 189:
1.98 mrg 190: static usbd_status kue_ctl(struct usbnet *, int, uint8_t,
1.71 tsutsui 191: uint16_t, void *, uint32_t);
1.98 mrg 192: static int kue_load_fw(struct usbnet *);
1.1 augustss 193:
1.72 tsutsui 194: static usbd_status
1.98 mrg 195: kue_setword(struct usbnet *un, uint8_t breq, uint16_t word)
1.1 augustss 196: {
197: usb_device_request_t req;
198:
1.98 mrg 199: DPRINTFN(10,("%s: %s: enter\n", device_xname(un->un_dev),__func__));
1.1 augustss 200:
201: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
202: req.bRequest = breq;
203: USETW(req.wValue, word);
204: USETW(req.wIndex, 0);
205: USETW(req.wLength, 0);
206:
1.98 mrg 207: return usbd_do_request(un->un_udev, &req, NULL);
1.1 augustss 208: }
209:
1.72 tsutsui 210: static usbd_status
1.98 mrg 211: kue_ctl(struct usbnet *un, int rw, uint8_t breq, uint16_t val,
1.71 tsutsui 212: void *data, uint32_t len)
1.1 augustss 213: {
214: usb_device_request_t req;
215:
1.98 mrg 216: DPRINTFN(10,("%s: %s: enter, len=%d\n", device_xname(un->un_dev),
1.48 augustss 217: __func__, len));
1.1 augustss 218:
219: if (rw == KUE_CTL_WRITE)
220: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
221: else
222: req.bmRequestType = UT_READ_VENDOR_DEVICE;
223:
224: req.bRequest = breq;
225: USETW(req.wValue, val);
226: USETW(req.wIndex, 0);
227: USETW(req.wLength, len);
228:
1.98 mrg 229: return usbd_do_request(un->un_udev, &req, data);
1.1 augustss 230: }
231:
1.72 tsutsui 232: static int
1.98 mrg 233: kue_load_fw(struct usbnet *un)
1.1 augustss 234: {
1.36 augustss 235: usb_device_descriptor_t dd;
1.1 augustss 236: usbd_status err;
237:
1.98 mrg 238: DPRINTFN(1,("%s: %s: enter\n", device_xname(un->un_dev), __func__));
1.1 augustss 239:
240: /*
241: * First, check if we even need to load the firmware.
242: * If the device was still attached when the system was
243: * rebooted, it may already have firmware loaded in it.
244: * If this is the case, we don't need to do it again.
245: * And in fact, if we try to load it again, we'll hang,
246: * so we have to avoid this condition if we don't want
247: * to look stupid.
248: *
1.65 dyoung 249: * We can test this quickly by checking the bcdRevision
250: * code. The NIC will return a different revision code if
251: * it's probed while the firmware is still loaded and
252: * running.
253: */
1.98 mrg 254: if (usbd_get_device_desc(un->un_udev, &dd))
1.84 skrll 255: return EIO;
1.65 dyoung 256: if (UGETW(dd.bcdDevice) == KUE_WARM_REV) {
1.1 augustss 257: printf("%s: warm boot, no firmware download\n",
1.98 mrg 258: device_xname(un->un_dev));
1.84 skrll 259: return 0;
1.1 augustss 260: }
261:
262: printf("%s: cold boot, downloading firmware\n",
1.98 mrg 263: device_xname(un->un_dev));
1.1 augustss 264:
265: /* Load code segment */
1.49 augustss 266: DPRINTFN(1,("%s: kue_load_fw: download code_seg\n",
1.98 mrg 267: device_xname(un->un_dev)));
1.54 christos 268: /*XXXUNCONST*/
1.98 mrg 269: err = kue_ctl(un, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
1.54 christos 270: 0, __UNCONST(kue_code_seg), sizeof(kue_code_seg));
1.1 augustss 271: if (err) {
272: printf("%s: failed to load code segment: %s\n",
1.98 mrg 273: device_xname(un->un_dev), usbd_errstr(err));
1.84 skrll 274: return EIO;
1.1 augustss 275: }
276:
277: /* Load fixup segment */
1.49 augustss 278: DPRINTFN(1,("%s: kue_load_fw: download fix_seg\n",
1.98 mrg 279: device_xname(un->un_dev)));
1.54 christos 280: /*XXXUNCONST*/
1.98 mrg 281: err = kue_ctl(un, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
1.54 christos 282: 0, __UNCONST(kue_fix_seg), sizeof(kue_fix_seg));
1.1 augustss 283: if (err) {
284: printf("%s: failed to load fixup segment: %s\n",
1.98 mrg 285: device_xname(un->un_dev), usbd_errstr(err));
1.84 skrll 286: return EIO;
1.1 augustss 287: }
288:
289: /* Send trigger command. */
1.49 augustss 290: DPRINTFN(1,("%s: kue_load_fw: download trig_seg\n",
1.98 mrg 291: device_xname(un->un_dev)));
1.54 christos 292: /*XXXUNCONST*/
1.98 mrg 293: err = kue_ctl(un, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
1.54 christos 294: 0, __UNCONST(kue_trig_seg), sizeof(kue_trig_seg));
1.1 augustss 295: if (err) {
296: printf("%s: failed to load trigger segment: %s\n",
1.98 mrg 297: device_xname(un->un_dev), usbd_errstr(err));
1.84 skrll 298: return EIO;
1.1 augustss 299: }
300:
1.98 mrg 301: usbd_delay_ms(un->un_udev, 10);
1.1 augustss 302:
303: /*
304: * Reload device descriptor.
305: * Why? The chip without the firmware loaded returns
306: * one revision code. The chip with the firmware
307: * loaded and running returns a *different* revision
308: * code. This confuses the quirk mechanism, which is
309: * dependent on the revision data.
310: */
1.98 mrg 311: (void)usbd_reload_device_desc(un->un_udev);
1.1 augustss 312:
1.98 mrg 313: DPRINTFN(1,("%s: %s: done\n", device_xname(un->un_dev), __func__));
1.1 augustss 314:
315: /* Reset the adapter. */
1.98 mrg 316: kue_reset(un);
1.1 augustss 317:
1.84 skrll 318: return 0;
1.1 augustss 319: }
320:
1.72 tsutsui 321: static void
1.98 mrg 322: kue_setiff(struct usbnet *un)
1.1 augustss 323: {
1.98 mrg 324: struct ethercom * ec = usbnet_ec(un);
325: struct kue_softc * sc = usbnet_softc(un);
326: struct ifnet * const ifp = usbnet_ifp(un);
1.1 augustss 327: struct ether_multi *enm;
328: struct ether_multistep step;
329: int i;
330:
1.98 mrg 331: DPRINTFN(5,("%s: %s: enter\n", device_xname(un->un_dev), __func__));
332:
333: /* If we want promiscuous mode, set the allframes bit. */
334: if (ifp->if_flags & IFF_PROMISC)
335: sc->kue_rxfilt |= KUE_RXFILT_PROMISC;
336: else
337: sc->kue_rxfilt &= ~KUE_RXFILT_PROMISC;
1.1 augustss 338:
1.38 enami 339: if (ifp->if_flags & IFF_PROMISC) {
340: allmulti:
341: ifp->if_flags |= IFF_ALLMULTI;
1.98 mrg 342: sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI|KUE_RXFILT_PROMISC;
1.1 augustss 343: sc->kue_rxfilt &= ~KUE_RXFILT_MULTICAST;
1.98 mrg 344: kue_setword(un, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt);
1.1 augustss 345: return;
346: }
347:
1.98 mrg 348: sc->kue_rxfilt &= ~(KUE_RXFILT_ALLMULTI|KUE_RXFILT_PROMISC);
1.1 augustss 349:
350: i = 0;
1.96 msaitoh 351: ETHER_LOCK(ec);
352: ETHER_FIRST_MULTI(step, ec, enm);
1.1 augustss 353: while (enm != NULL) {
1.38 enami 354: if (i == KUE_MCFILTCNT(sc) ||
355: memcmp(enm->enm_addrlo, enm->enm_addrhi,
1.96 msaitoh 356: ETHER_ADDR_LEN) != 0) {
357: ETHER_UNLOCK(ec);
1.38 enami 358: goto allmulti;
1.96 msaitoh 359: }
1.38 enami 360:
1.1 augustss 361: memcpy(KUE_MCFILT(sc, i), enm->enm_addrlo, ETHER_ADDR_LEN);
362: ETHER_NEXT_MULTI(step, enm);
363: i++;
364: }
1.96 msaitoh 365: ETHER_UNLOCK(ec);
1.1 augustss 366:
1.38 enami 367: ifp->if_flags &= ~IFF_ALLMULTI;
368:
369: sc->kue_rxfilt |= KUE_RXFILT_MULTICAST;
1.98 mrg 370: kue_ctl(un, KUE_CTL_WRITE, KUE_CMD_SET_MCAST_FILTERS,
1.38 enami 371: i, sc->kue_mcfilters, i * ETHER_ADDR_LEN);
1.1 augustss 372:
1.98 mrg 373: kue_setword(un, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt);
1.1 augustss 374: }
375:
376: /*
377: * Issue a SET_CONFIGURATION command to reset the MAC. This should be
378: * done after the firmware is loaded into the adapter in order to
379: * bring it into proper operation.
380: */
1.72 tsutsui 381: static void
1.98 mrg 382: kue_reset(struct usbnet *un)
1.1 augustss 383: {
1.98 mrg 384: DPRINTFN(5,("%s: %s: enter\n", device_xname(un->un_dev), __func__));
1.1 augustss 385:
1.98 mrg 386: if (usbd_set_config_no(un->un_udev, KUE_CONFIG_NO, 1) ||
387: usbd_device2interface_handle(un->un_udev, KUE_IFACE_IDX,
388: &un->un_iface))
389: printf("%s: reset failed\n", device_xname(un->un_dev));
1.1 augustss 390:
391: /* Wait a little while for the chip to get its brains in order. */
1.98 mrg 392: usbd_delay_ms(un->un_udev, 10);
1.1 augustss 393: }
394:
395: /*
396: * Probe for a KLSI chip.
397: */
1.101 maxv 398: static int
1.74 dyoung 399: kue_match(device_t parent, cfdata_t match, void *aux)
1.1 augustss 400: {
1.74 dyoung 401: struct usb_attach_arg *uaa = aux;
1.1 augustss 402:
403: DPRINTFN(25,("kue_match: enter\n"));
404:
1.84 skrll 405: return kue_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ?
406: UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
1.1 augustss 407: }
408:
409: /*
410: * Attach the interface. Allocate softc structures, do
411: * setup and ethernet/BPF attach.
412: */
1.101 maxv 413: static void
1.74 dyoung 414: kue_attach(device_t parent, device_t self, void *aux)
1.1 augustss 415: {
1.74 dyoung 416: struct kue_softc *sc = device_private(self);
1.98 mrg 417: struct usbnet * const un = &sc->kue_un;
1.74 dyoung 418: struct usb_attach_arg *uaa = aux;
1.53 augustss 419: char *devinfop;
1.84 skrll 420: struct usbd_device * dev = uaa->uaa_device;
1.1 augustss 421: usbd_status err;
422: usb_interface_descriptor_t *id;
423: usb_endpoint_descriptor_t *ed;
424: int i;
425:
1.98 mrg 426: KASSERT((void *)sc == un);
427:
1.1 augustss 428: DPRINTFN(5,(" : kue_attach: sc=%p, dev=%p", sc, dev));
429:
1.66 plunky 430: aprint_naive("\n");
431: aprint_normal("\n");
1.53 augustss 432: devinfop = usbd_devinfo_alloc(dev, 0);
1.63 cube 433: aprint_normal_dev(self, "%s\n", devinfop);
1.53 augustss 434: usbd_devinfo_free(devinfop);
1.1 augustss 435:
1.98 mrg 436: un->un_dev = self;
437: un->un_udev = dev;
438: un->un_sc = sc;
439: un->un_ops = &kue_ops;
440: un->un_rx_xfer_flags = USBD_SHORT_XFER_OK;
441: un->un_tx_xfer_flags = 0;
442: un->un_rx_list_cnt = KUE_RX_LIST_CNT;
443: un->un_tx_list_cnt = KUE_TX_LIST_CNT;
444: un->un_rx_bufsz = KUE_BUFSZ;
445: un->un_tx_bufsz = KUE_BUFSZ;
446:
1.31 augustss 447: err = usbd_set_config_no(dev, KUE_CONFIG_NO, 1);
1.1 augustss 448: if (err) {
1.78 skrll 449: aprint_error_dev(self, "failed to set configuration"
450: ", err=%s\n", usbd_errstr(err));
1.74 dyoung 451: return;
1.1 augustss 452: }
453:
454: /* Load the firmware into the NIC. */
1.98 mrg 455: if (kue_load_fw(un)) {
1.63 cube 456: aprint_error_dev(self, "loading firmware failed\n");
1.74 dyoung 457: return;
1.1 augustss 458: }
459:
1.98 mrg 460: err = usbd_device2interface_handle(dev, KUE_IFACE_IDX, &un->un_iface);
1.1 augustss 461: if (err) {
1.63 cube 462: aprint_error_dev(self, "getting interface handle failed\n");
1.74 dyoung 463: return;
1.1 augustss 464: }
465:
1.98 mrg 466: id = usbd_get_interface_descriptor(un->un_iface);
1.1 augustss 467:
468: /* Find endpoints. */
469: for (i = 0; i < id->bNumEndpoints; i++) {
1.98 mrg 470: ed = usbd_interface2endpoint_descriptor(un->un_iface, i);
1.1 augustss 471: if (ed == NULL) {
1.63 cube 472: aprint_error_dev(self, "couldn't get ep %d\n", i);
1.74 dyoung 473: return;
1.1 augustss 474: }
475: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
1.12 augustss 476: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1.98 mrg 477: un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress;
1.1 augustss 478: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
1.12 augustss 479: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1.98 mrg 480: un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress;
1.1 augustss 481: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
1.12 augustss 482: UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
1.98 mrg 483: /*
484: * The interrupt endpoint is currently unused by the
485: * KLSI part.
486: */
487: un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress;
1.1 augustss 488: }
489: }
490:
1.98 mrg 491: if (un->un_ed[USBNET_ENDPT_RX] == 0 ||
492: un->un_ed[USBNET_ENDPT_TX] == 0) {
1.63 cube 493: aprint_error_dev(self, "missing endpoint\n");
1.74 dyoung 494: return;
1.1 augustss 495: }
496:
1.98 mrg 497: /* First level attach, so kue_ctl() works. */
498: usbnet_attach(un, "kuedet");
499:
1.1 augustss 500: /* Read ethernet descriptor */
1.98 mrg 501: err = kue_ctl(un, KUE_CTL_READ, KUE_CMD_GET_ETHER_DESCRIPTOR,
1.18 augustss 502: 0, &sc->kue_desc, sizeof(sc->kue_desc));
1.1 augustss 503: if (err) {
1.63 cube 504: aprint_error_dev(self, "could not read Ethernet descriptor\n");
1.74 dyoung 505: return;
1.1 augustss 506: }
1.98 mrg 507: memcpy(un->un_eaddr, sc->kue_desc.kue_macaddr, sizeof un->un_eaddr);
1.1 augustss 508:
1.84 skrll 509: sc->kue_mcfilters = kmem_alloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN,
510: KM_SLEEP);
1.1 augustss 511:
1.100 mrg 512: usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST,
513: 0, NULL);
1.1 augustss 514: }
515:
1.101 maxv 516: static int
1.74 dyoung 517: kue_detach(device_t self, int flags)
1.1 augustss 518: {
1.74 dyoung 519: struct kue_softc *sc = device_private(self);
1.1 augustss 520:
1.8 augustss 521: if (sc->kue_mcfilters != NULL) {
1.84 skrll 522: kmem_free(sc->kue_mcfilters,
523: KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN);
1.8 augustss 524: sc->kue_mcfilters = NULL;
525: }
526:
1.98 mrg 527: return usbnet_detach(self, flags);
1.1 augustss 528: }
529:
530: /*
531: * A frame has been uploaded: pass the resulting mbuf chain up to
532: * the higher level protocols.
533: */
1.72 tsutsui 534: static void
1.98 mrg 535: kue_rx_loop(struct usbnet *un, struct usbnet_chain *c, uint32_t total_len)
1.1 augustss 536: {
1.98 mrg 537: struct ifnet *ifp = usbnet_ifp(un);
538: uint8_t *buf = c->unc_buf;
539: unsigned pktlen;
1.1 augustss 540:
1.98 mrg 541: if (total_len <= 1)
1.1 augustss 542: return;
543:
1.98 mrg 544: DPRINTFN(10,("%s: %s: total_len=%d len=%d\n",
545: device_xname(un->un_dev), __func__,
546: total_len, le16dec(buf)));
547:
548: pktlen = le16dec(buf);
549: if (pktlen > total_len - ETHER_ALIGN)
550: pktlen = total_len - ETHER_ALIGN;
1.73 tsutsui 551:
552: if (pktlen < ETHER_MIN_LEN - ETHER_CRC_LEN ||
553: pktlen > MCLBYTES - ETHER_ALIGN) {
1.102 ! thorpej 554: if_statinc(ifp, if_ierrors);
1.98 mrg 555: return;
1.73 tsutsui 556: }
557:
1.98 mrg 558: DPRINTFN(10,("%s: %s: deliver %d\n", device_xname(un->un_dev),
559: __func__, pktlen));
560: usbnet_enqueue(un, buf + 2, pktlen, 0, 0, 0);
1.1 augustss 561: }
562:
1.98 mrg 563: static unsigned
564: kue_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c)
1.1 augustss 565: {
1.98 mrg 566: unsigned total_len, pkt_len;
1.1 augustss 567:
1.98 mrg 568: pkt_len = m->m_pkthdr.len + 2;
569: total_len = roundup2(pkt_len, 64);
1.6 augustss 570:
1.98 mrg 571: if ((unsigned)total_len > un->un_tx_bufsz) {
572: DPRINTFN(10,("%s: %s: too big pktlen %u total %u\n",
573: device_xname(un->un_dev), __func__, pkt_len, total_len));
574: return 0;
1.1 augustss 575: }
576:
1.73 tsutsui 577: /* Frame length is specified in the first 2 bytes of the buffer. */
1.98 mrg 578: le16enc(c->unc_buf, (uint16_t)m->m_pkthdr.len);
1.73 tsutsui 579:
1.1 augustss 580: /*
1.98 mrg 581: * Copy the mbuf data into a contiguous buffer after the frame length,
582: * possibly zeroing the rest of the buffer.
1.1 augustss 583: */
1.98 mrg 584: m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf + 2);
585: if (total_len - pkt_len > 0)
586: memset(c->unc_buf + pkt_len, 0, total_len - pkt_len);
1.1 augustss 587:
1.98 mrg 588: DPRINTFN(10,("%s: %s: enter pktlen %u total %u\n",
589: device_xname(un->un_dev), __func__, pkt_len, total_len));
1.1 augustss 590:
1.98 mrg 591: return total_len;
1.1 augustss 592: }
593:
1.98 mrg 594: static int
595: kue_init_locked(struct ifnet *ifp)
1.1 augustss 596: {
1.98 mrg 597: struct usbnet * const un = ifp->if_softc;
598: struct kue_softc *sc = usbnet_softc(un);
1.71 tsutsui 599: uint8_t eaddr[ETHER_ADDR_LEN];
1.1 augustss 600:
1.98 mrg 601: DPRINTFN(5,("%s: %s: enter\n", device_xname(un->un_dev),__func__));
1.1 augustss 602:
1.98 mrg 603: if (usbnet_isdying(un))
604: return EIO;
1.1 augustss 605:
1.98 mrg 606: /* Cancel pending I/O */
607: usbnet_stop(un, ifp, 1);
1.1 augustss 608:
1.61 dyoung 609: memcpy(eaddr, CLLADDR(ifp->if_sadl), sizeof(eaddr));
1.1 augustss 610: /* Set MAC address */
1.98 mrg 611: kue_ctl(un, KUE_CTL_WRITE, KUE_CMD_SET_MAC, 0, eaddr, ETHER_ADDR_LEN);
1.1 augustss 612:
613: sc->kue_rxfilt = KUE_RXFILT_UNICAST | KUE_RXFILT_BROADCAST;
614:
615: /* I'm not sure how to tune these. */
616: #if 0
617: /*
618: * Leave this one alone for now; setting it
619: * wrong causes lockups on some machines/controllers.
620: */
1.98 mrg 621: kue_setword(un, KUE_CMD_SET_SOFS, 1);
1.1 augustss 622: #endif
1.98 mrg 623: kue_setword(un, KUE_CMD_SET_URB_SIZE, 64);
1.1 augustss 624:
1.84 skrll 625: /* Load the multicast filter. */
1.98 mrg 626: kue_setiff(un);
1.84 skrll 627:
1.98 mrg 628: return usbnet_init_rx_tx(un);
1.1 augustss 629: }
630:
1.72 tsutsui 631: static int
1.98 mrg 632: kue_init(struct ifnet *ifp)
1.1 augustss 633: {
1.98 mrg 634: struct usbnet * const un = ifp->if_softc;
635: int rv;
1.1 augustss 636:
1.98 mrg 637: usbnet_lock(un);
638: rv = kue_init_locked(ifp);
639: usbnet_unlock(un);
1.1 augustss 640:
1.98 mrg 641: return rv;
1.1 augustss 642: }
643:
1.72 tsutsui 644: static int
1.98 mrg 645: kue_ioctl_cb(struct ifnet *ifp, u_long cmd, void *data)
1.1 augustss 646: {
1.98 mrg 647: struct usbnet * const un = ifp->if_softc;
1.1 augustss 648:
1.98 mrg 649: switch (cmd) {
1.1 augustss 650: case SIOCADDMULTI:
651: case SIOCDELMULTI:
1.98 mrg 652: //kue_init(ifp);
653: kue_setiff(un);
1.1 augustss 654: break;
655: default:
656: break;
657: }
658:
1.98 mrg 659: return 0;
1.1 augustss 660: }
661:
1.98 mrg 662: #ifdef _MODULE
663: #include "ioconf.c"
664: #endif
1.1 augustss 665:
1.98 mrg 666: USBNET_MODULE(kue)
CVSweb <webmaster@jp.NetBSD.org>