1 1.109 riastrad /* $NetBSD: if_cue.c,v 1.109 2024/06/29 12:11:12 riastradh Exp $ */ 2 1.85 mrg 3 1.1 augustss /* 4 1.1 augustss * Copyright (c) 1997, 1998, 1999, 2000 5 1.1 augustss * Bill Paul <wpaul (at) ee.columbia.edu>. All rights reserved. 6 1.1 augustss * 7 1.1 augustss * Redistribution and use in source and binary forms, with or without 8 1.1 augustss * modification, are permitted provided that the following conditions 9 1.1 augustss * are met: 10 1.1 augustss * 1. Redistributions of source code must retain the above copyright 11 1.1 augustss * notice, this list of conditions and the following disclaimer. 12 1.1 augustss * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 augustss * notice, this list of conditions and the following disclaimer in the 14 1.1 augustss * documentation and/or other materials provided with the distribution. 15 1.1 augustss * 3. All advertising materials mentioning features or use of this software 16 1.1 augustss * must display the following acknowledgement: 17 1.1 augustss * This product includes software developed by Bill Paul. 18 1.1 augustss * 4. Neither the name of the author nor the names of any co-contributors 19 1.1 augustss * may be used to endorse or promote products derived from this software 20 1.1 augustss * without specific prior written permission. 21 1.1 augustss * 22 1.1 augustss * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 23 1.1 augustss * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 augustss * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 augustss * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 26 1.1 augustss * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 1.1 augustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 1.1 augustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 1.1 augustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 1.1 augustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 1.1 augustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 1.1 augustss * THE POSSIBILITY OF SUCH DAMAGE. 33 1.1 augustss * 34 1.1 augustss * $FreeBSD: src/sys/dev/usb/if_cue.c,v 1.4 2000/01/16 22:45:06 wpaul Exp $ 35 1.1 augustss */ 36 1.1 augustss 37 1.1 augustss /* 38 1.15 augustss * CATC USB-EL1210A USB to ethernet driver. Used in the CATC Netmate 39 1.1 augustss * adapters and others. 40 1.1 augustss * 41 1.1 augustss * Written by Bill Paul <wpaul (at) ee.columbia.edu> 42 1.1 augustss * Electrical Engineering Department 43 1.1 augustss * Columbia University, New York City 44 1.1 augustss */ 45 1.1 augustss 46 1.1 augustss /* 47 1.15 augustss * The CATC USB-EL1210A provides USB ethernet support at 10Mbps. The 48 1.1 augustss * RX filter uses a 512-bit multicast hash table, single perfect entry 49 1.1 augustss * for the station address, and promiscuous mode. Unlike the ADMtek 50 1.1 augustss * and KLSI chips, the CATC ASIC supports read and write combining 51 1.87 msaitoh * mode where multiple packets can be transferred using a single bulk 52 1.1 augustss * transaction, which helps performance a great deal. 53 1.1 augustss */ 54 1.1 augustss 55 1.1 augustss /* 56 1.1 augustss * Ported to NetBSD and somewhat rewritten by Lennart Augustsson. 57 1.1 augustss */ 58 1.36 lukem 59 1.36 lukem #include <sys/cdefs.h> 60 1.109 riastrad __KERNEL_RCSID(0, "$NetBSD: if_cue.c,v 1.109 2024/06/29 12:11:12 riastradh Exp $"); 61 1.1 augustss 62 1.65 christos #ifdef _KERNEL_OPT 63 1.1 augustss #include "opt_inet.h" 64 1.74 skrll #include "opt_usb.h" 65 1.65 christos #endif 66 1.1 augustss 67 1.1 augustss #include <sys/param.h> 68 1.85 mrg 69 1.85 mrg #include <dev/usb/usbnet.h> 70 1.85 mrg #include <dev/usb/if_cuereg.h> 71 1.1 augustss 72 1.1 augustss #ifdef INET 73 1.40 augustss #include <netinet/in.h> 74 1.1 augustss #include <netinet/if_inarp.h> 75 1.1 augustss #endif 76 1.1 augustss 77 1.1 augustss #ifdef CUE_DEBUG 78 1.60 dyoung #define DPRINTF(x) if (cuedebug) printf x 79 1.82 msaitoh #define DPRINTFN(n, x) if (cuedebug >= (n)) printf x 80 1.1 augustss int cuedebug = 0; 81 1.1 augustss #else 82 1.1 augustss #define DPRINTF(x) 83 1.82 msaitoh #define DPRINTFN(n, x) 84 1.1 augustss #endif 85 1.1 augustss 86 1.85 mrg #define CUE_BUFSZ 1536 87 1.85 mrg #define CUE_MIN_FRAMELEN 60 88 1.85 mrg #define CUE_RX_FRAMES 1 89 1.85 mrg #define CUE_TX_FRAMES 1 90 1.85 mrg 91 1.85 mrg #define CUE_CONFIG_NO 1 92 1.85 mrg #define CUE_IFACE_IDX 0 93 1.85 mrg 94 1.85 mrg #define CUE_RX_LIST_CNT 1 95 1.85 mrg #define CUE_TX_LIST_CNT 1 96 1.85 mrg 97 1.85 mrg struct cue_type { 98 1.85 mrg uint16_t cue_vid; 99 1.85 mrg uint16_t cue_did; 100 1.85 mrg }; 101 1.85 mrg 102 1.85 mrg struct cue_softc; 103 1.85 mrg 104 1.85 mrg struct cue_chain { 105 1.85 mrg struct cue_softc *cue_sc; 106 1.85 mrg struct usbd_xfer *cue_xfer; 107 1.85 mrg char *cue_buf; 108 1.85 mrg struct mbuf *cue_mbuf; 109 1.85 mrg int cue_idx; 110 1.85 mrg }; 111 1.85 mrg 112 1.85 mrg struct cue_cdata { 113 1.85 mrg struct cue_chain cue_tx_chain[CUE_TX_LIST_CNT]; 114 1.85 mrg struct cue_chain cue_rx_chain[CUE_RX_LIST_CNT]; 115 1.85 mrg int cue_tx_prod; 116 1.85 mrg int cue_tx_cnt; 117 1.85 mrg }; 118 1.85 mrg 119 1.85 mrg struct cue_softc { 120 1.85 mrg struct usbnet cue_un; 121 1.85 mrg uint8_t cue_mctab[CUE_MCAST_TABLE_LEN]; 122 1.85 mrg }; 123 1.85 mrg 124 1.1 augustss /* 125 1.1 augustss * Various supported device vendors/products. 126 1.1 augustss */ 127 1.88 maxv static const struct usb_devno cue_devs[] = { 128 1.1 augustss { USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE }, 129 1.1 augustss { USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE2 }, 130 1.22 augustss { USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTLINK }, 131 1.15 augustss /* Belkin F5U111 adapter covered by NETMATE entry */ 132 1.1 augustss }; 133 1.38 augustss #define cue_lookup(v, p) (usb_lookup(cue_devs, v, p)) 134 1.1 augustss 135 1.88 maxv static int cue_match(device_t, cfdata_t, void *); 136 1.88 maxv static void cue_attach(device_t, device_t, void *); 137 1.81 mrg 138 1.60 dyoung CFATTACH_DECL_NEW(cue, sizeof(struct cue_softc), cue_match, cue_attach, 139 1.85 mrg usbnet_detach, usbnet_activate); 140 1.1 augustss 141 1.91 thorpej static unsigned cue_uno_tx_prepare(struct usbnet *, struct mbuf *, 142 1.91 thorpej struct usbnet_chain *); 143 1.91 thorpej static void cue_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); 144 1.94 riastrad static void cue_uno_mcast(struct ifnet *); 145 1.91 thorpej static void cue_uno_stop(struct ifnet *, int); 146 1.91 thorpej static int cue_uno_init(struct ifnet *); 147 1.91 thorpej static void cue_uno_tick(struct usbnet *); 148 1.85 mrg 149 1.88 maxv static const struct usbnet_ops cue_ops = { 150 1.91 thorpej .uno_stop = cue_uno_stop, 151 1.94 riastrad .uno_mcast = cue_uno_mcast, 152 1.91 thorpej .uno_tx_prepare = cue_uno_tx_prepare, 153 1.91 thorpej .uno_rx_loop = cue_uno_rx_loop, 154 1.91 thorpej .uno_init = cue_uno_init, 155 1.91 thorpej .uno_tick = cue_uno_tick, 156 1.85 mrg }; 157 1.1 augustss 158 1.85 mrg #ifdef CUE_DEBUG 159 1.85 mrg static int 160 1.85 mrg cue_csr_read_1(struct usbnet *un, int reg) 161 1.1 augustss { 162 1.1 augustss usb_device_request_t req; 163 1.1 augustss usbd_status err; 164 1.72 skrll uint8_t val = 0; 165 1.1 augustss 166 1.85 mrg if (usbnet_isdying(un)) 167 1.72 skrll return 0; 168 1.1 augustss 169 1.1 augustss req.bmRequestType = UT_READ_VENDOR_DEVICE; 170 1.1 augustss req.bRequest = CUE_CMD_READREG; 171 1.1 augustss USETW(req.wValue, 0); 172 1.1 augustss USETW(req.wIndex, reg); 173 1.1 augustss USETW(req.wLength, 1); 174 1.1 augustss 175 1.85 mrg err = usbd_do_request(un->un_udev, &req, &val); 176 1.1 augustss 177 1.15 augustss if (err) { 178 1.90 christos DPRINTF(("%s: cue_csr_read_1: reg=%#x err=%s\n", 179 1.85 mrg device_xname(un->un_dev), reg, usbd_errstr(err))); 180 1.72 skrll return 0; 181 1.15 augustss } 182 1.15 augustss 183 1.90 christos DPRINTFN(10,("%s: cue_csr_read_1 reg=%#x val=%#x\n", 184 1.85 mrg device_xname(un->un_dev), reg, val)); 185 1.1 augustss 186 1.72 skrll return val; 187 1.1 augustss } 188 1.85 mrg #endif 189 1.1 augustss 190 1.85 mrg static int 191 1.85 mrg cue_csr_read_2(struct usbnet *un, int reg) 192 1.1 augustss { 193 1.1 augustss usb_device_request_t req; 194 1.1 augustss usbd_status err; 195 1.15 augustss uWord val; 196 1.1 augustss 197 1.85 mrg if (usbnet_isdying(un)) 198 1.72 skrll return 0; 199 1.1 augustss 200 1.1 augustss req.bmRequestType = UT_READ_VENDOR_DEVICE; 201 1.1 augustss req.bRequest = CUE_CMD_READREG; 202 1.1 augustss USETW(req.wValue, 0); 203 1.1 augustss USETW(req.wIndex, reg); 204 1.1 augustss USETW(req.wLength, 2); 205 1.1 augustss 206 1.85 mrg err = usbd_do_request(un->un_udev, &req, &val); 207 1.1 augustss 208 1.90 christos DPRINTFN(10,("%s: cue_csr_read_2 reg=%#x val=%#x\n", 209 1.85 mrg device_xname(un->un_dev), reg, UGETW(val))); 210 1.1 augustss 211 1.15 augustss if (err) { 212 1.90 christos DPRINTF(("%s: cue_csr_read_2: reg=%#x err=%s\n", 213 1.85 mrg device_xname(un->un_dev), reg, usbd_errstr(err))); 214 1.72 skrll return 0; 215 1.15 augustss } 216 1.1 augustss 217 1.72 skrll return UGETW(val); 218 1.1 augustss } 219 1.1 augustss 220 1.85 mrg static int 221 1.85 mrg cue_csr_write_1(struct usbnet *un, int reg, int val) 222 1.1 augustss { 223 1.1 augustss usb_device_request_t req; 224 1.1 augustss usbd_status err; 225 1.1 augustss 226 1.85 mrg if (usbnet_isdying(un)) 227 1.72 skrll return 0; 228 1.15 augustss 229 1.90 christos DPRINTFN(10,("%s: cue_csr_write_1 reg=%#x val=%#x\n", 230 1.85 mrg device_xname(un->un_dev), reg, val)); 231 1.1 augustss 232 1.1 augustss req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 233 1.1 augustss req.bRequest = CUE_CMD_WRITEREG; 234 1.1 augustss USETW(req.wValue, val); 235 1.1 augustss USETW(req.wIndex, reg); 236 1.1 augustss USETW(req.wLength, 0); 237 1.1 augustss 238 1.85 mrg err = usbd_do_request(un->un_udev, &req, NULL); 239 1.1 augustss 240 1.15 augustss if (err) { 241 1.90 christos DPRINTF(("%s: cue_csr_write_1: reg=%#x err=%s\n", 242 1.85 mrg device_xname(un->un_dev), reg, usbd_errstr(err))); 243 1.72 skrll return -1; 244 1.15 augustss } 245 1.15 augustss 246 1.90 christos DPRINTFN(20,("%s: cue_csr_write_1, after reg=%#x val=%#x\n", 247 1.85 mrg device_xname(un->un_dev), reg, cue_csr_read_1(un, reg))); 248 1.1 augustss 249 1.72 skrll return 0; 250 1.1 augustss } 251 1.1 augustss 252 1.23 augustss #if 0 253 1.85 mrg static int 254 1.85 mrg cue_csr_write_2(struct usbnet *un, int reg, int aval) 255 1.1 augustss { 256 1.1 augustss usb_device_request_t req; 257 1.1 augustss usbd_status err; 258 1.15 augustss uWord val; 259 1.1 augustss int s; 260 1.1 augustss 261 1.85 mrg if (usbnet_isdying(un)) 262 1.72 skrll return 0; 263 1.15 augustss 264 1.90 christos DPRINTFN(10,("%s: cue_csr_write_2 reg=%#x val=%#x\n", 265 1.85 mrg device_xname(un->un_dev), reg, aval)); 266 1.1 augustss 267 1.15 augustss USETW(val, aval); 268 1.1 augustss req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 269 1.1 augustss req.bRequest = CUE_CMD_WRITEREG; 270 1.1 augustss USETW(req.wValue, val); 271 1.1 augustss USETW(req.wIndex, reg); 272 1.1 augustss USETW(req.wLength, 0); 273 1.1 augustss 274 1.85 mrg err = usbd_do_request(un->un_udev, &req, NULL); 275 1.1 augustss 276 1.15 augustss if (err) { 277 1.90 christos DPRINTF(("%s: cue_csr_write_2: reg=%#x err=%s\n", 278 1.85 mrg device_xname(un->un_dev), reg, usbd_errstr(err))); 279 1.72 skrll return -1; 280 1.15 augustss } 281 1.1 augustss 282 1.72 skrll return 0; 283 1.1 augustss } 284 1.1 augustss #endif 285 1.1 augustss 286 1.85 mrg static int 287 1.85 mrg cue_mem(struct usbnet *un, int cmd, int addr, void *buf, int len) 288 1.1 augustss { 289 1.1 augustss usb_device_request_t req; 290 1.1 augustss usbd_status err; 291 1.1 augustss 292 1.90 christos DPRINTFN(10,("%s: cue_mem cmd=%#x addr=%#x len=%d\n", 293 1.85 mrg device_xname(un->un_dev), cmd, addr, len)); 294 1.1 augustss 295 1.1 augustss if (cmd == CUE_CMD_READSRAM) 296 1.1 augustss req.bmRequestType = UT_READ_VENDOR_DEVICE; 297 1.1 augustss else 298 1.1 augustss req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 299 1.1 augustss req.bRequest = cmd; 300 1.1 augustss USETW(req.wValue, 0); 301 1.1 augustss USETW(req.wIndex, addr); 302 1.1 augustss USETW(req.wLength, len); 303 1.1 augustss 304 1.85 mrg err = usbd_do_request(un->un_udev, &req, buf); 305 1.1 augustss 306 1.15 augustss if (err) { 307 1.90 christos DPRINTF(("%s: cue_csr_mem: addr=%#x err=%s\n", 308 1.85 mrg device_xname(un->un_dev), addr, usbd_errstr(err))); 309 1.72 skrll return -1; 310 1.15 augustss } 311 1.1 augustss 312 1.72 skrll return 0; 313 1.1 augustss } 314 1.1 augustss 315 1.85 mrg static int 316 1.85 mrg cue_getmac(struct usbnet *un) 317 1.1 augustss { 318 1.1 augustss usb_device_request_t req; 319 1.1 augustss usbd_status err; 320 1.1 augustss 321 1.85 mrg DPRINTFN(10,("%s: cue_getmac\n", device_xname(un->un_dev))); 322 1.1 augustss 323 1.1 augustss req.bmRequestType = UT_READ_VENDOR_DEVICE; 324 1.1 augustss req.bRequest = CUE_CMD_GET_MACADDR; 325 1.1 augustss USETW(req.wValue, 0); 326 1.1 augustss USETW(req.wIndex, 0); 327 1.1 augustss USETW(req.wLength, ETHER_ADDR_LEN); 328 1.1 augustss 329 1.85 mrg err = usbd_do_request(un->un_udev, &req, un->un_eaddr); 330 1.1 augustss 331 1.1 augustss if (err) { 332 1.60 dyoung printf("%s: read MAC address failed\n", 333 1.85 mrg device_xname(un->un_dev)); 334 1.72 skrll return -1; 335 1.1 augustss } 336 1.1 augustss 337 1.72 skrll return 0; 338 1.1 augustss } 339 1.1 augustss 340 1.1 augustss #define CUE_POLY 0xEDB88320 341 1.1 augustss #define CUE_BITS 9 342 1.1 augustss 343 1.85 mrg static uint32_t 344 1.42 yamt cue_crc(const char *addr) 345 1.1 augustss { 346 1.72 skrll uint32_t idx, bit, data, crc; 347 1.1 augustss 348 1.1 augustss /* Compute CRC for the address value. */ 349 1.1 augustss crc = 0xFFFFFFFF; /* initial value */ 350 1.1 augustss 351 1.1 augustss for (idx = 0; idx < 6; idx++) { 352 1.1 augustss for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) 353 1.1 augustss crc = (crc >> 1) ^ (((crc ^ data) & 1) ? CUE_POLY : 0); 354 1.1 augustss } 355 1.1 augustss 356 1.72 skrll return crc & ((1 << CUE_BITS) - 1); 357 1.1 augustss } 358 1.1 augustss 359 1.85 mrg static void 360 1.99 riastrad cue_uno_mcast(struct ifnet *ifp) 361 1.1 augustss { 362 1.99 riastrad struct usbnet *un = ifp->if_softc; 363 1.85 mrg struct cue_softc *sc = usbnet_softc(un); 364 1.85 mrg struct ethercom *ec = usbnet_ec(un); 365 1.15 augustss struct ether_multi *enm; 366 1.15 augustss struct ether_multistep step; 367 1.72 skrll uint32_t h, i; 368 1.1 augustss 369 1.107 riastrad DPRINTFN(2,("%s: cue_setiff promisc=%d\n", 370 1.107 riastrad device_xname(un->un_dev), usbnet_ispromisc(un))); 371 1.15 augustss 372 1.107 riastrad if (usbnet_ispromisc(un)) { 373 1.100 riastrad ETHER_LOCK(ec); 374 1.33 enami allmulti: 375 1.100 riastrad ec->ec_flags |= ETHER_F_ALLMULTI; 376 1.100 riastrad ETHER_UNLOCK(ec); 377 1.1 augustss for (i = 0; i < CUE_MCAST_TABLE_LEN; i++) 378 1.1 augustss sc->cue_mctab[i] = 0xFF; 379 1.85 mrg cue_mem(un, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR, 380 1.15 augustss &sc->cue_mctab, CUE_MCAST_TABLE_LEN); 381 1.1 augustss return; 382 1.1 augustss } 383 1.1 augustss 384 1.1 augustss /* first, zot all the existing hash bits */ 385 1.1 augustss for (i = 0; i < CUE_MCAST_TABLE_LEN; i++) 386 1.1 augustss sc->cue_mctab[i] = 0; 387 1.1 augustss 388 1.1 augustss /* now program new ones */ 389 1.84 msaitoh ETHER_LOCK(ec); 390 1.84 msaitoh ETHER_FIRST_MULTI(step, ec, enm); 391 1.15 augustss while (enm != NULL) { 392 1.15 augustss if (memcmp(enm->enm_addrlo, 393 1.84 msaitoh enm->enm_addrhi, ETHER_ADDR_LEN) != 0) { 394 1.33 enami goto allmulti; 395 1.84 msaitoh } 396 1.33 enami 397 1.15 augustss h = cue_crc(enm->enm_addrlo); 398 1.40 augustss sc->cue_mctab[h >> 3] |= 1 << (h & 0x7); 399 1.15 augustss ETHER_NEXT_MULTI(step, enm); 400 1.15 augustss } 401 1.100 riastrad ec->ec_flags &= ~ETHER_F_ALLMULTI; 402 1.84 msaitoh ETHER_UNLOCK(ec); 403 1.33 enami 404 1.1 augustss /* 405 1.1 augustss * Also include the broadcast address in the filter 406 1.1 augustss * so we can receive broadcast frames. 407 1.1 augustss */ 408 1.108 riastrad h = cue_crc(etherbroadcastaddr); 409 1.108 riastrad sc->cue_mctab[h >> 3] |= 1 << (h & 0x7); 410 1.1 augustss 411 1.85 mrg cue_mem(un, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR, 412 1.1 augustss &sc->cue_mctab, CUE_MCAST_TABLE_LEN); 413 1.1 augustss } 414 1.1 augustss 415 1.85 mrg static void 416 1.85 mrg cue_reset(struct usbnet *un) 417 1.1 augustss { 418 1.1 augustss usb_device_request_t req; 419 1.1 augustss usbd_status err; 420 1.1 augustss 421 1.85 mrg DPRINTFN(2,("%s: cue_reset\n", device_xname(un->un_dev))); 422 1.15 augustss 423 1.85 mrg if (usbnet_isdying(un)) 424 1.15 augustss return; 425 1.1 augustss 426 1.1 augustss req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 427 1.1 augustss req.bRequest = CUE_CMD_RESET; 428 1.1 augustss USETW(req.wValue, 0); 429 1.1 augustss USETW(req.wIndex, 0); 430 1.1 augustss USETW(req.wLength, 0); 431 1.15 augustss 432 1.85 mrg err = usbd_do_request(un->un_udev, &req, NULL); 433 1.1 augustss 434 1.1 augustss if (err) 435 1.85 mrg printf("%s: reset failed\n", device_xname(un->un_dev)); 436 1.1 augustss 437 1.1 augustss /* Wait a little while for the chip to get its brains in order. */ 438 1.85 mrg usbd_delay_ms(un->un_udev, 1); 439 1.1 augustss } 440 1.1 augustss 441 1.1 augustss /* 442 1.1 augustss * Probe for a CATC chip. 443 1.1 augustss */ 444 1.88 maxv static int 445 1.60 dyoung cue_match(device_t parent, cfdata_t match, void *aux) 446 1.1 augustss { 447 1.60 dyoung struct usb_attach_arg *uaa = aux; 448 1.1 augustss 449 1.72 skrll return cue_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ? 450 1.72 skrll UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 451 1.1 augustss } 452 1.1 augustss 453 1.1 augustss /* 454 1.1 augustss * Attach the interface. Allocate softc structures, do ifmedia 455 1.1 augustss * setup and ethernet/BPF attach. 456 1.1 augustss */ 457 1.88 maxv static void 458 1.60 dyoung cue_attach(device_t parent, device_t self, void *aux) 459 1.1 augustss { 460 1.60 dyoung struct cue_softc *sc = device_private(self); 461 1.85 mrg struct usbnet * const un = &sc->cue_un; 462 1.60 dyoung struct usb_attach_arg *uaa = aux; 463 1.43 augustss char *devinfop; 464 1.72 skrll struct usbd_device * dev = uaa->uaa_device; 465 1.1 augustss usbd_status err; 466 1.1 augustss usb_interface_descriptor_t *id; 467 1.1 augustss usb_endpoint_descriptor_t *ed; 468 1.1 augustss int i; 469 1.1 augustss 470 1.85 mrg KASSERT((void *)sc == un); 471 1.85 mrg 472 1.1 augustss DPRINTFN(5,(" : cue_attach: sc=%p, dev=%p", sc, dev)); 473 1.1 augustss 474 1.55 plunky aprint_naive("\n"); 475 1.55 plunky aprint_normal("\n"); 476 1.43 augustss devinfop = usbd_devinfo_alloc(dev, 0); 477 1.53 cube aprint_normal_dev(self, "%s\n", devinfop); 478 1.43 augustss usbd_devinfo_free(devinfop); 479 1.1 augustss 480 1.25 augustss err = usbd_set_config_no(dev, CUE_CONFIG_NO, 1); 481 1.1 augustss if (err) { 482 1.64 skrll aprint_error_dev(self, "failed to set configuration" 483 1.64 skrll ", err=%s\n", usbd_errstr(err)); 484 1.60 dyoung return; 485 1.1 augustss } 486 1.1 augustss 487 1.85 mrg un->un_dev = self; 488 1.85 mrg un->un_udev = dev; 489 1.85 mrg un->un_sc = sc; 490 1.85 mrg un->un_ops = &cue_ops; 491 1.85 mrg un->un_rx_xfer_flags = USBD_SHORT_XFER_OK; 492 1.85 mrg un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER; 493 1.85 mrg un->un_rx_list_cnt = CUE_RX_LIST_CNT; 494 1.85 mrg un->un_tx_list_cnt = CUE_TX_LIST_CNT; 495 1.85 mrg un->un_rx_bufsz = CUE_BUFSZ; 496 1.85 mrg un->un_tx_bufsz = CUE_BUFSZ; 497 1.1 augustss 498 1.85 mrg err = usbd_device2interface_handle(dev, CUE_IFACE_IDX, &un->un_iface); 499 1.1 augustss if (err) { 500 1.53 cube aprint_error_dev(self, "getting interface handle failed\n"); 501 1.60 dyoung return; 502 1.1 augustss } 503 1.1 augustss 504 1.85 mrg id = usbd_get_interface_descriptor(un->un_iface); 505 1.1 augustss 506 1.1 augustss /* Find endpoints. */ 507 1.1 augustss for (i = 0; i < id->bNumEndpoints; i++) { 508 1.85 mrg ed = usbd_interface2endpoint_descriptor(un->un_iface, i); 509 1.1 augustss if (ed == NULL) { 510 1.53 cube aprint_error_dev(self, "couldn't get ep %d\n", i); 511 1.60 dyoung return; 512 1.1 augustss } 513 1.1 augustss if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 514 1.11 augustss UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 515 1.85 mrg un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress; 516 1.1 augustss } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 517 1.11 augustss UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 518 1.85 mrg un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress; 519 1.1 augustss } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 520 1.11 augustss UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 521 1.85 mrg un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress; 522 1.1 augustss } 523 1.1 augustss } 524 1.1 augustss 525 1.85 mrg /* First level attach. */ 526 1.106 riastrad usbnet_attach(un); 527 1.85 mrg 528 1.15 augustss #if 0 529 1.1 augustss /* Reset the adapter. */ 530 1.85 mrg cue_reset(un); 531 1.1 augustss #endif 532 1.1 augustss /* 533 1.1 augustss * Get station address. 534 1.1 augustss */ 535 1.85 mrg cue_getmac(un); 536 1.1 augustss 537 1.86 mrg usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 538 1.86 mrg 0, NULL); 539 1.1 augustss } 540 1.1 augustss 541 1.85 mrg static void 542 1.91 thorpej cue_uno_tick(struct usbnet *un) 543 1.1 augustss { 544 1.85 mrg struct ifnet *ifp = usbnet_ifp(un); 545 1.1 augustss 546 1.89 thorpej net_stat_ref_t nsr = IF_STAT_GETREF(ifp); 547 1.85 mrg if (cue_csr_read_2(un, CUE_RX_FRAMEERR)) 548 1.109 riastrad if_statinc_ref(ifp, nsr, if_ierrors); 549 1.1 augustss 550 1.109 riastrad if_statadd_ref(ifp, nsr, if_collisions, 551 1.89 thorpej cue_csr_read_2(un, CUE_TX_SINGLECOLL)); 552 1.109 riastrad if_statadd_ref(ifp, nsr, if_collisions, 553 1.89 thorpej cue_csr_read_2(un, CUE_TX_MULTICOLL)); 554 1.109 riastrad if_statadd_ref(ifp, nsr, if_collisions, 555 1.89 thorpej cue_csr_read_2(un, CUE_TX_EXCESSCOLL)); 556 1.89 thorpej IF_STAT_PUTREF(ifp); 557 1.1 augustss } 558 1.1 augustss 559 1.85 mrg static void 560 1.91 thorpej cue_uno_rx_loop(struct usbnet *un, struct usbnet_chain *c, uint32_t total_len) 561 1.1 augustss { 562 1.85 mrg struct ifnet *ifp = usbnet_ifp(un); 563 1.85 mrg uint8_t *buf = c->unc_buf; 564 1.72 skrll uint16_t len; 565 1.1 augustss 566 1.85 mrg DPRINTFN(5,("%s: %s: total_len=%d len=%d\n", 567 1.85 mrg device_xname(un->un_dev), __func__, 568 1.85 mrg total_len, le16dec(buf))); 569 1.85 mrg 570 1.85 mrg len = UGETW(buf); 571 1.85 mrg if (total_len < 2 || 572 1.85 mrg len > total_len - 2 || 573 1.85 mrg len < sizeof(struct ether_header)) { 574 1.89 thorpej if_statinc(ifp, if_ierrors); 575 1.1 augustss return; 576 1.1 augustss } 577 1.1 augustss 578 1.1 augustss /* No errors; receive the packet. */ 579 1.85 mrg usbnet_enqueue(un, buf + 2, len, 0, 0, 0); 580 1.1 augustss } 581 1.1 augustss 582 1.85 mrg static unsigned 583 1.91 thorpej cue_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) 584 1.1 augustss { 585 1.85 mrg unsigned total_len; 586 1.4 augustss 587 1.85 mrg DPRINTFN(5,("%s: %s: mbuf len=%d\n", 588 1.85 mrg device_xname(un->un_dev), __func__, 589 1.85 mrg m->m_pkthdr.len)); 590 1.1 augustss 591 1.85 mrg if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz - 2) 592 1.85 mrg return 0; 593 1.1 augustss 594 1.1 augustss /* 595 1.1 augustss * Copy the mbuf data into a contiguous buffer, leaving two 596 1.1 augustss * bytes at the beginning to hold the frame length. 597 1.1 augustss */ 598 1.85 mrg m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf + 2); 599 1.1 augustss 600 1.1 augustss total_len = m->m_pkthdr.len + 2; 601 1.1 augustss 602 1.1 augustss /* The first two bytes are the frame length */ 603 1.85 mrg c->unc_buf[0] = (uint8_t)m->m_pkthdr.len; 604 1.85 mrg c->unc_buf[1] = (uint8_t)(m->m_pkthdr.len >> 8); 605 1.1 augustss 606 1.85 mrg return total_len; 607 1.1 augustss } 608 1.1 augustss 609 1.85 mrg static int 610 1.97 riastrad cue_uno_init(struct ifnet *ifp) 611 1.1 augustss { 612 1.85 mrg struct usbnet * const un = ifp->if_softc; 613 1.85 mrg int i, ctl; 614 1.51 dyoung const u_char *eaddr; 615 1.1 augustss 616 1.85 mrg DPRINTFN(10,("%s: %s: enter\n", device_xname(un->un_dev),__func__)); 617 1.4 augustss 618 1.85 mrg /* Cancel pending I/O */ 619 1.104 riastrad cue_uno_stop(ifp, 1); 620 1.1 augustss 621 1.85 mrg /* Reset the interface. */ 622 1.15 augustss #if 1 623 1.85 mrg cue_reset(un); 624 1.1 augustss #endif 625 1.1 augustss 626 1.15 augustss /* Set advanced operation modes. */ 627 1.85 mrg cue_csr_write_1(un, CUE_ADVANCED_OPMODES, 628 1.15 augustss CUE_AOP_EMBED_RXLEN | 0x03); /* 1 wait state */ 629 1.15 augustss 630 1.51 dyoung eaddr = CLLADDR(ifp->if_sadl); 631 1.1 augustss /* Set MAC address */ 632 1.1 augustss for (i = 0; i < ETHER_ADDR_LEN; i++) 633 1.85 mrg cue_csr_write_1(un, CUE_PAR0 - i, eaddr[i]); 634 1.1 augustss 635 1.1 augustss /* Enable RX logic. */ 636 1.15 augustss ctl = CUE_ETHCTL_RX_ON | CUE_ETHCTL_MCAST_ON; 637 1.107 riastrad if (usbnet_ispromisc(un)) 638 1.15 augustss ctl |= CUE_ETHCTL_PROMISC; 639 1.85 mrg cue_csr_write_1(un, CUE_ETHCTL, ctl); 640 1.1 augustss 641 1.1 augustss /* 642 1.1 augustss * Set the number of RX and TX buffers that we want 643 1.1 augustss * to reserve inside the ASIC. 644 1.1 augustss */ 645 1.85 mrg cue_csr_write_1(un, CUE_RX_BUFPKTS, CUE_RX_FRAMES); 646 1.85 mrg cue_csr_write_1(un, CUE_TX_BUFPKTS, CUE_TX_FRAMES); 647 1.1 augustss 648 1.1 augustss /* Set advanced operation modes. */ 649 1.85 mrg cue_csr_write_1(un, CUE_ADVANCED_OPMODES, 650 1.15 augustss CUE_AOP_EMBED_RXLEN | 0x01); /* 1 wait state */ 651 1.1 augustss 652 1.1 augustss /* Program the LED operation. */ 653 1.85 mrg cue_csr_write_1(un, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK); 654 1.1 augustss 655 1.105 riastrad return 0; 656 1.15 augustss } 657 1.15 augustss 658 1.85 mrg /* Stop and reset the adapter. */ 659 1.85 mrg static void 660 1.91 thorpej cue_uno_stop(struct ifnet *ifp, int disable) 661 1.1 augustss { 662 1.85 mrg struct usbnet * const un = ifp->if_softc; 663 1.4 augustss 664 1.85 mrg DPRINTFN(10,("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 665 1.1 augustss 666 1.85 mrg cue_csr_write_1(un, CUE_ETHCTL, 0); 667 1.85 mrg cue_reset(un); 668 1.1 augustss } 669 1.1 augustss 670 1.85 mrg #ifdef _MODULE 671 1.85 mrg #include "ioconf.c" 672 1.85 mrg #endif 673 1.72 skrll 674 1.85 mrg USBNET_MODULE(cue) 675