1 /* $OpenBSD: if_axe.c,v 1.93 2009/09/20 12:53:36 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2005, 2006, 2007 Jonathan Gray <jsg@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * Copyright (c) 1997, 1998, 1999, 2000-2003 21 * Bill Paul <wpaul@windriver.com>. All rights reserved. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the above copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * This product includes software developed by Bill Paul. 34 * 4. Neither the name of the author nor the names of any co-contributors 35 * may be used to endorse or promote products derived from this software 36 * without specific prior written permission. 37 * 38 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 41 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 42 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 43 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 44 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 45 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 46 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 48 * THE POSSIBILITY OF SUCH DAMAGE. 49 */ 50 51 #include <sys/cdefs.h> 52 53 /* 54 * ASIX Electronics AX88172 USB 2.0 ethernet driver. Used in the 55 * LinkSys USB200M and various other adapters. 56 * 57 * Manuals available from: 58 * http://www.asix.com.tw/datasheet/mac/Ax88172.PDF 59 * Note: you need the manual for the AX88170 chip (USB 1.x ethernet 60 * controller) to find the definitions for the RX control register. 61 * http://www.asix.com.tw/datasheet/mac/Ax88170.PDF 62 * 63 * Written by Bill Paul <wpaul@windriver.com> 64 * Senior Engineer 65 * Wind River Systems 66 */ 67 68 /* 69 * The AX88172 provides USB ethernet supports at 10 and 100Mbps. 70 * It uses an external PHY (reference designs use a RealTek chip), 71 * and has a 64-bit multicast hash filter. There is some information 72 * missing from the manual which one needs to know in order to make 73 * the chip function: 74 * 75 * - You must set bit 7 in the RX control register, otherwise the 76 * chip won't receive any packets. 77 * - You must initialize all 3 IPG registers, or you won't be able 78 * to send any packets. 79 * 80 * Note that this device appears to only support loading the station 81 * address via autload from the EEPROM (i.e. there's no way to manaully 82 * set it). 83 * 84 * (Adam Weinberger wanted me to name this driver if_gir.c.) 85 */ 86 87 /* 88 * Ported to OpenBSD 3/28/2004 by Greg Taleck <taleck@oz.net> 89 * with bits and pieces from the aue and url drivers. 90 */ 91 92 #include "bpfilter.h" 93 94 #include <sys/param.h> 95 #include <sys/systm.h> 96 #include <sys/sockio.h> 97 #include <sys/rwlock.h> 98 #include <sys/mbuf.h> 99 #include <sys/kernel.h> 100 #include <sys/proc.h> 101 #include <sys/socket.h> 102 103 #include <sys/device.h> 104 105 #include <machine/bus.h> 106 107 #include <net/if.h> 108 #include <net/if_dl.h> 109 #include <net/if_media.h> 110 111 #if NBPFILTER > 0 112 #include <net/bpf.h> 113 #endif 114 115 #ifdef INET 116 #include <netinet/in.h> 117 #include <netinet/in_systm.h> 118 #include <netinet/in_var.h> 119 #include <netinet/ip.h> 120 #include <netinet/if_ether.h> 121 #endif 122 123 #include <dev/mii/mii.h> 124 #include <dev/mii/miivar.h> 125 126 #include <dev/usb/usb.h> 127 #include <dev/usb/usbdi.h> 128 #include <dev/usb/usbdi_util.h> 129 #include <dev/usb/usbdivar.h> 130 #include <dev/usb/usbdevs.h> 131 132 #include <dev/usb/if_axereg.h> 133 134 #ifdef AXE_DEBUG 135 #define DPRINTF(x) do { if (axedebug) printf x; } while (0) 136 #define DPRINTFN(n,x) do { if (axedebug >= (n)) printf x; } while (0) 137 int axedebug = 0; 138 #else 139 #define DPRINTF(x) 140 #define DPRINTFN(n,x) 141 #endif 142 143 /* 144 * Various supported device vendors/products. 145 */ 146 const struct axe_type axe_devs[] = { 147 { { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_UF200}, 0 }, 148 { { USB_VENDOR_ACERCM, USB_PRODUCT_ACERCM_EP1427X2}, 0 }, 149 { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_ETHERNET }, AX772 }, 150 { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88172}, 0 }, 151 { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88772}, AX772 }, 152 { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88772A}, AX772 }, 153 { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88178}, AX178 }, 154 { { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC210T}, 0 }, 155 { { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D5055 }, AX178 }, 156 { { USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USB2AR}, 0}, 157 { { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_USB200MV2}, AX772 }, 158 { { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB2_TX }, 0}, 159 { { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100}, 0 }, 160 { { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100B1 }, AX772 }, 161 { { USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_GWUSB2E}, 0 }, 162 { { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_ETGUS2 }, AX178 }, 163 { { USB_VENDOR_JVC, USB_PRODUCT_JVC_MP_PRX1}, 0 }, 164 { { USB_VENDOR_LINKSYS2, USB_PRODUCT_LINKSYS2_USB200M}, 0 }, 165 { { USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_USB1000 }, AX178 }, 166 { { USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LAN_GTJU2}, AX178 }, 167 { { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAU2GT}, AX178 }, 168 { { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAU2KTX}, 0 }, 169 { { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA120}, 0 }, 170 { { USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01PLUS }, AX772 }, 171 { { USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GU1000T }, AX178 }, 172 { { USB_VENDOR_SYSTEMTALKS, USB_PRODUCT_SYSTEMTALKS_SGCX2UL}, 0 }, 173 { { USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_LN029}, 0 }, 174 { { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN028 }, AX178 } 175 }; 176 177 #define axe_lookup(v, p) ((struct axe_type *)usb_lookup(axe_devs, v, p)) 178 179 int axe_match(struct device *, void *, void *); 180 void axe_attach(struct device *, struct device *, void *); 181 int axe_detach(struct device *, int); 182 int axe_activate(struct device *, enum devact); 183 184 struct cfdriver axe_cd = { 185 NULL, "axe", DV_IFNET 186 }; 187 188 const struct cfattach axe_ca = { 189 sizeof(struct axe_softc), 190 axe_match, 191 axe_attach, 192 axe_detach, 193 axe_activate, 194 }; 195 196 int axe_tx_list_init(struct axe_softc *); 197 int axe_rx_list_init(struct axe_softc *); 198 struct mbuf *axe_newbuf(void); 199 int axe_encap(struct axe_softc *, struct mbuf *, int); 200 void axe_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); 201 void axe_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); 202 void axe_tick(void *); 203 void axe_tick_task(void *); 204 void axe_start(struct ifnet *); 205 int axe_ioctl(struct ifnet *, u_long, caddr_t); 206 void axe_init(void *); 207 void axe_stop(struct axe_softc *); 208 void axe_watchdog(struct ifnet *); 209 int axe_miibus_readreg(struct device *, int, int); 210 void axe_miibus_writereg(struct device *, int, int, int); 211 void axe_miibus_statchg(struct device *); 212 int axe_cmd(struct axe_softc *, int, int, int, void *); 213 int axe_ifmedia_upd(struct ifnet *); 214 void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *); 215 void axe_reset(struct axe_softc *sc); 216 217 void axe_setmulti(struct axe_softc *); 218 void axe_lock_mii(struct axe_softc *sc); 219 void axe_unlock_mii(struct axe_softc *sc); 220 221 void axe_ax88178_init(struct axe_softc *); 222 void axe_ax88772_init(struct axe_softc *); 223 224 /* Get exclusive access to the MII registers */ 225 void 226 axe_lock_mii(struct axe_softc *sc) 227 { 228 sc->axe_refcnt++; 229 rw_enter_write(&sc->axe_mii_lock); 230 } 231 232 void 233 axe_unlock_mii(struct axe_softc *sc) 234 { 235 rw_exit_write(&sc->axe_mii_lock); 236 if (--sc->axe_refcnt < 0) 237 usb_detach_wakeup(&sc->axe_dev); 238 } 239 240 int 241 axe_cmd(struct axe_softc *sc, int cmd, int index, int val, void *buf) 242 { 243 usb_device_request_t req; 244 usbd_status err; 245 246 if (sc->axe_dying) 247 return(0); 248 249 if (AXE_CMD_DIR(cmd)) 250 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 251 else 252 req.bmRequestType = UT_READ_VENDOR_DEVICE; 253 req.bRequest = AXE_CMD_CMD(cmd); 254 USETW(req.wValue, val); 255 USETW(req.wIndex, index); 256 USETW(req.wLength, AXE_CMD_LEN(cmd)); 257 258 err = usbd_do_request(sc->axe_udev, &req, buf); 259 260 if (err) { 261 DPRINTF(("axe_cmd err: cmd: %d\n", cmd)); 262 return(-1); 263 } 264 265 return(0); 266 } 267 268 int 269 axe_miibus_readreg(struct device *dev, int phy, int reg) 270 { 271 struct axe_softc *sc = (void *)dev; 272 usbd_status err; 273 uWord val; 274 275 if (sc->axe_dying) { 276 DPRINTF(("axe: dying\n")); 277 return(0); 278 } 279 280 #ifdef notdef 281 /* 282 * The chip tells us the MII address of any supported 283 * PHYs attached to the chip, so only read from those. 284 */ 285 286 DPRINTF(("axe_miibus_readreg: phy 0x%x reg 0x%x\n", phy, reg)); 287 288 if (sc->axe_phyaddrs[0] != AXE_NOPHY && phy != sc->axe_phyaddrs[0]) 289 return (0); 290 291 if (sc->axe_phyaddrs[1] != AXE_NOPHY && phy != sc->axe_phyaddrs[1]) 292 return (0); 293 #endif 294 if (sc->axe_phyaddrs[0] != 0xFF && sc->axe_phyaddrs[0] != phy) 295 return (0); 296 297 USETW(val, 0); 298 299 axe_lock_mii(sc); 300 axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL); 301 err = axe_cmd(sc, AXE_CMD_MII_READ_REG, reg, phy, val); 302 axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL); 303 axe_unlock_mii(sc); 304 305 if (err) { 306 printf("axe%d: read PHY failed\n", sc->axe_unit); 307 return(-1); 308 } 309 DPRINTF(("axe_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n", 310 phy, reg, UGETW(val))); 311 312 if (UGETW(val) && UGETW(val) != 0xffff) 313 sc->axe_phyaddrs[0] = phy; 314 315 return (UGETW(val)); 316 } 317 318 void 319 axe_miibus_writereg(struct device *dev, int phy, int reg, int val) 320 { 321 struct axe_softc *sc = (void *)dev; 322 usbd_status err; 323 uWord uval; 324 325 if (sc->axe_dying) 326 return; 327 328 USETW(uval, val); 329 330 axe_lock_mii(sc); 331 axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL); 332 err = axe_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, uval); 333 axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL); 334 axe_unlock_mii(sc); 335 336 if (err) { 337 printf("axe%d: write PHY failed\n", sc->axe_unit); 338 return; 339 } 340 } 341 342 void 343 axe_miibus_statchg(struct device *dev) 344 { 345 struct axe_softc *sc = (void *)dev; 346 struct mii_data *mii = GET_MII(sc); 347 int val, err; 348 349 if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) 350 val = AXE_MEDIA_FULL_DUPLEX; 351 else 352 val = 0; 353 354 if (sc->axe_flags & AX178 || sc->axe_flags & AX772) { 355 val |= (AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC); 356 357 switch (IFM_SUBTYPE(mii->mii_media_active)) { 358 case IFM_1000_T: 359 val |= AXE_178_MEDIA_GMII | AXE_178_MEDIA_ENCK; 360 break; 361 case IFM_100_TX: 362 val |= AXE_178_MEDIA_100TX; 363 break; 364 case IFM_10_T: 365 /* doesn't need to be handled */ 366 break; 367 } 368 } 369 370 DPRINTF(("axe_miibus_statchg: val=0x%x\n", val)); 371 err = axe_cmd(sc, AXE_CMD_WRITE_MEDIA, 0, val, NULL); 372 if (err) { 373 printf("%s: media change failed\n", sc->axe_dev.dv_xname); 374 return; 375 } 376 } 377 378 /* 379 * Set media options. 380 */ 381 int 382 axe_ifmedia_upd(struct ifnet *ifp) 383 { 384 struct axe_softc *sc = ifp->if_softc; 385 struct mii_data *mii = GET_MII(sc); 386 387 sc->axe_link = 0; 388 if (mii->mii_instance) { 389 struct mii_softc *miisc; 390 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 391 mii_phy_reset(miisc); 392 } 393 mii_mediachg(mii); 394 395 return (0); 396 } 397 398 /* 399 * Report current media status. 400 */ 401 void 402 axe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 403 { 404 struct axe_softc *sc = ifp->if_softc; 405 struct mii_data *mii = GET_MII(sc); 406 407 mii_pollstat(mii); 408 ifmr->ifm_active = mii->mii_media_active; 409 ifmr->ifm_status = mii->mii_media_status; 410 } 411 412 void 413 axe_setmulti(struct axe_softc *sc) 414 { 415 struct ifnet *ifp; 416 struct ether_multi *enm; 417 struct ether_multistep step; 418 u_int32_t h = 0; 419 uWord urxmode; 420 u_int16_t rxmode; 421 u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 422 423 if (sc->axe_dying) 424 return; 425 426 ifp = GET_IFP(sc); 427 428 axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, urxmode); 429 rxmode = UGETW(urxmode); 430 431 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 432 allmulti: 433 rxmode |= AXE_RXCMD_ALLMULTI; 434 axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); 435 return; 436 } else 437 rxmode &= ~AXE_RXCMD_ALLMULTI; 438 439 /* now program new ones */ 440 ETHER_FIRST_MULTI(step, &sc->arpcom, enm); 441 while (enm != NULL) { 442 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 443 ETHER_ADDR_LEN) != 0) 444 goto allmulti; 445 446 h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26; 447 hashtbl[h / 8] |= 1 << (h % 8); 448 ETHER_NEXT_MULTI(step, enm); 449 } 450 451 ifp->if_flags &= ~IFF_ALLMULTI; 452 axe_cmd(sc, AXE_CMD_WRITE_MCAST, 0, 0, (void *)&hashtbl); 453 axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); 454 return; 455 } 456 457 void 458 axe_reset(struct axe_softc *sc) 459 { 460 if (sc->axe_dying) 461 return; 462 /* XXX What to reset? */ 463 464 /* Wait a little while for the chip to get its brains in order. */ 465 DELAY(1000); 466 return; 467 } 468 469 void 470 axe_ax88178_init(struct axe_softc *sc) 471 { 472 int gpio0 = 0, phymode = 0; 473 u_int16_t eeprom; 474 475 axe_cmd(sc, AXE_CMD_SROM_WR_ENABLE, 0, 0, NULL); 476 /* XXX magic */ 477 axe_cmd(sc, AXE_CMD_SROM_READ, 0, 0x0017, &eeprom); 478 axe_cmd(sc, AXE_CMD_SROM_WR_DISABLE, 0, 0, NULL); 479 480 eeprom = letoh16(eeprom); 481 482 DPRINTF((" EEPROM is 0x%x\n", eeprom)); 483 484 /* if EEPROM is invalid we have to use to GPIO0 */ 485 if (eeprom == 0xffff) { 486 phymode = 0; 487 gpio0 = 1; 488 } else { 489 phymode = eeprom & 7; 490 gpio0 = (eeprom & 0x80) ? 0 : 1; 491 } 492 493 DPRINTF(("use gpio0: %d, phymode %d\n", gpio0, phymode)); 494 495 axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x008c, NULL); 496 usbd_delay_ms(sc->axe_udev, 40); 497 if ((eeprom >> 8) != 1) { 498 axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL); 499 usbd_delay_ms(sc->axe_udev, 30); 500 501 axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x001c, NULL); 502 usbd_delay_ms(sc->axe_udev, 300); 503 504 axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL); 505 usbd_delay_ms(sc->axe_udev, 30); 506 } else { 507 DPRINTF(("axe gpio phymode == 1 path\n")); 508 axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x0004, NULL); 509 usbd_delay_ms(sc->axe_udev, 30); 510 axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x000c, NULL); 511 usbd_delay_ms(sc->axe_udev, 30); 512 } 513 514 /* soft reset */ 515 axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL); 516 usbd_delay_ms(sc->axe_udev, 150); 517 axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 518 AXE_SW_RESET_PRL | AXE_178_RESET_MAGIC, NULL); 519 usbd_delay_ms(sc->axe_udev, 150); 520 axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); 521 } 522 523 void 524 axe_ax88772_init(struct axe_softc *sc) 525 { 526 axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x00b0, NULL); 527 usbd_delay_ms(sc->axe_udev, 40); 528 529 if (sc->axe_phyaddrs[1] == AXE_INTPHY) { 530 /* ask for the embedded PHY */ 531 axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x01, NULL); 532 usbd_delay_ms(sc->axe_udev, 10); 533 534 /* power down and reset state, pin reset state */ 535 axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL); 536 usbd_delay_ms(sc->axe_udev, 60); 537 538 /* power down/reset state, pin operating state */ 539 axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 540 AXE_SW_RESET_IPPD | AXE_SW_RESET_PRL, NULL); 541 usbd_delay_ms(sc->axe_udev, 150); 542 543 /* power up, reset */ 544 axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_PRL, NULL); 545 546 /* power up, operating */ 547 axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 548 AXE_SW_RESET_IPRL | AXE_SW_RESET_PRL, NULL); 549 } else { 550 /* ask for external PHY */ 551 axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x00, NULL); 552 usbd_delay_ms(sc->axe_udev, 10); 553 554 /* power down internal PHY */ 555 axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 556 AXE_SW_RESET_IPPD | AXE_SW_RESET_PRL, NULL); 557 } 558 559 usbd_delay_ms(sc->axe_udev, 150); 560 axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); 561 } 562 563 /* 564 * Probe for a AX88172 chip. 565 */ 566 int 567 axe_match(struct device *parent, void *match, void *aux) 568 { 569 struct usb_attach_arg *uaa = aux; 570 571 if (!uaa->iface) 572 return(UMATCH_NONE); 573 574 return (axe_lookup(uaa->vendor, uaa->product) != NULL ? 575 UMATCH_VENDOR_PRODUCT : UMATCH_NONE); 576 } 577 578 /* 579 * Attach the interface. Allocate softc structures, do ifmedia 580 * setup and ethernet/BPF attach. 581 */ 582 void 583 axe_attach(struct device *parent, struct device *self, void *aux) 584 { 585 struct axe_softc *sc = (struct axe_softc *)self; 586 struct usb_attach_arg *uaa = aux; 587 usbd_device_handle dev = uaa->device; 588 usbd_status err; 589 usb_interface_descriptor_t *id; 590 usb_endpoint_descriptor_t *ed; 591 struct mii_data *mii; 592 u_char eaddr[ETHER_ADDR_LEN]; 593 char *devname = sc->axe_dev.dv_xname; 594 struct ifnet *ifp; 595 int i, s; 596 597 sc->axe_unit = self->dv_unit; /*device_get_unit(self);*/ 598 599 err = usbd_set_config_no(dev, AXE_CONFIG_NO, 1); 600 if (err) { 601 printf("%s: getting interface handle failed\n", 602 sc->axe_dev.dv_xname); 603 return; 604 } 605 606 sc->axe_flags = axe_lookup(uaa->vendor, uaa->product)->axe_flags; 607 608 usb_init_task(&sc->axe_tick_task, axe_tick_task, sc); 609 rw_init(&sc->axe_mii_lock, "axemii"); 610 usb_init_task(&sc->axe_stop_task, (void (*)(void *))axe_stop, sc); 611 612 err = usbd_device2interface_handle(dev, AXE_IFACE_IDX, &sc->axe_iface); 613 if (err) { 614 printf("%s: getting interface handle failed\n", 615 sc->axe_dev.dv_xname); 616 return; 617 } 618 619 sc->axe_udev = dev; 620 sc->axe_product = uaa->product; 621 sc->axe_vendor = uaa->vendor; 622 623 id = usbd_get_interface_descriptor(sc->axe_iface); 624 625 /* decide on what our bufsize will be */ 626 if (sc->axe_flags & AX178 || sc->axe_flags & AX772) 627 sc->axe_bufsz = (sc->axe_udev->speed == USB_SPEED_HIGH) ? 628 AXE_178_MAX_BUFSZ : AXE_178_MIN_BUFSZ; 629 else 630 sc->axe_bufsz = AXE_172_BUFSZ; 631 632 /* Find endpoints. */ 633 for (i = 0; i < id->bNumEndpoints; i++) { 634 ed = usbd_interface2endpoint_descriptor(sc->axe_iface, i); 635 if (!ed) { 636 printf("%s: couldn't get ep %d\n", 637 sc->axe_dev.dv_xname, i); 638 return; 639 } 640 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 641 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 642 sc->axe_ed[AXE_ENDPT_RX] = ed->bEndpointAddress; 643 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 644 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 645 sc->axe_ed[AXE_ENDPT_TX] = ed->bEndpointAddress; 646 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 647 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 648 sc->axe_ed[AXE_ENDPT_INTR] = ed->bEndpointAddress; 649 } 650 } 651 652 s = splnet(); 653 654 printf("%s:", sc->axe_dev.dv_xname); 655 656 /* We need the PHYID for init dance in some cases */ 657 axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, (void *)&sc->axe_phyaddrs); 658 659 DPRINTF((" phyaddrs[0]: %x phyaddrs[1]: %x\n", 660 sc->axe_phyaddrs[0], sc->axe_phyaddrs[1])); 661 662 if (sc->axe_flags & AX178) { 663 axe_ax88178_init(sc); 664 printf(" AX88178"); 665 } else if (sc->axe_flags & AX772) { 666 axe_ax88772_init(sc); 667 printf(" AX88772"); 668 } else 669 printf(" AX88172"); 670 671 /* 672 * Get station address. 673 */ 674 if (sc->axe_flags & AX178 || sc->axe_flags & AX772) 675 axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, &eaddr); 676 else 677 axe_cmd(sc, AXE_172_CMD_READ_NODEID, 0, 0, &eaddr); 678 679 /* 680 * Load IPG values 681 */ 682 axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, (void *)&sc->axe_ipgs); 683 684 /* 685 * Work around broken adapters that appear to lie about 686 * their PHY addresses. 687 */ 688 sc->axe_phyaddrs[0] = sc->axe_phyaddrs[1] = 0xFF; 689 690 /* 691 * An ASIX chip was detected. Inform the world. 692 */ 693 printf(", address %s\n", ether_sprintf(eaddr)); 694 695 bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 696 697 /* Initialize interface info.*/ 698 ifp = &sc->arpcom.ac_if; 699 ifp->if_softc = sc; 700 strlcpy(ifp->if_xname, devname, IFNAMSIZ); 701 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 702 ifp->if_ioctl = axe_ioctl; 703 ifp->if_start = axe_start; 704 705 ifp->if_watchdog = axe_watchdog; 706 707 /* ifp->if_baudrate = 10000000; */ 708 /* ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;*/ 709 710 IFQ_SET_READY(&ifp->if_snd); 711 712 ifp->if_capabilities = IFCAP_VLAN_MTU; 713 714 /* Initialize MII/media info. */ 715 mii = &sc->axe_mii; 716 mii->mii_ifp = ifp; 717 mii->mii_readreg = axe_miibus_readreg; 718 mii->mii_writereg = axe_miibus_writereg; 719 mii->mii_statchg = axe_miibus_statchg; 720 mii->mii_flags = MIIF_AUTOTSLEEP; 721 722 ifmedia_init(&mii->mii_media, 0, axe_ifmedia_upd, axe_ifmedia_sts); 723 mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); 724 725 if (LIST_FIRST(&mii->mii_phys) == NULL) { 726 ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); 727 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); 728 } else 729 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 730 731 /* Attach the interface. */ 732 if_attach(ifp); 733 ether_ifattach(ifp); 734 735 timeout_set(&sc->axe_stat_ch, axe_tick, sc); 736 737 sc->axe_attached = 1; 738 splx(s); 739 740 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->axe_udev, 741 &sc->axe_dev); 742 } 743 744 int 745 axe_detach(struct device *self, int flags) 746 { 747 struct axe_softc *sc = (struct axe_softc *)self; 748 int s; 749 struct ifnet *ifp = GET_IFP(sc); 750 751 DPRINTFN(2,("%s: %s: enter\n", sc->axe_dev.dv_xname, __func__)); 752 753 /* Detached before attached finished, so just bail out. */ 754 if (!sc->axe_attached) 755 return (0); 756 757 timeout_del(&sc->axe_stat_ch); 758 759 sc->axe_dying = 1; 760 761 if (sc->axe_ep[AXE_ENDPT_TX] != NULL) 762 usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]); 763 if (sc->axe_ep[AXE_ENDPT_RX] != NULL) 764 usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]); 765 if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) 766 usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]); 767 768 /* 769 * Remove any pending tasks. They cannot be executing because they run 770 * in the same thread as detach. 771 */ 772 usb_rem_task(sc->axe_udev, &sc->axe_tick_task); 773 usb_rem_task(sc->axe_udev, &sc->axe_stop_task); 774 775 s = splusb(); 776 777 if (--sc->axe_refcnt >= 0) { 778 /* Wait for processes to go away */ 779 usb_detach_wait(&sc->axe_dev); 780 } 781 782 if (ifp->if_flags & IFF_RUNNING) 783 axe_stop(sc); 784 785 mii_detach(&sc->axe_mii, MII_PHY_ANY, MII_OFFSET_ANY); 786 ifmedia_delete_instance(&sc->axe_mii.mii_media, IFM_INST_ANY); 787 ether_ifdetach(ifp); 788 if_detach(ifp); 789 790 #ifdef DIAGNOSTIC 791 if (sc->axe_ep[AXE_ENDPT_TX] != NULL || 792 sc->axe_ep[AXE_ENDPT_RX] != NULL || 793 sc->axe_ep[AXE_ENDPT_INTR] != NULL) 794 printf("%s: detach has active endpoints\n", 795 sc->axe_dev.dv_xname); 796 #endif 797 798 sc->axe_attached = 0; 799 800 if (--sc->axe_refcnt >= 0) { 801 /* Wait for processes to go away. */ 802 usb_detach_wait(&sc->axe_dev); 803 } 804 splx(s); 805 806 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->axe_udev, 807 &sc->axe_dev); 808 809 return (0); 810 } 811 812 int 813 axe_activate(struct device *self, enum devact act) 814 { 815 struct axe_softc *sc = (struct axe_softc *)self; 816 817 DPRINTFN(2,("%s: %s: enter\n", sc->axe_dev.dv_xname, __func__)); 818 819 switch (act) { 820 case DVACT_ACTIVATE: 821 break; 822 823 case DVACT_DEACTIVATE: 824 sc->axe_dying = 1; 825 break; 826 } 827 return (0); 828 } 829 830 struct mbuf * 831 axe_newbuf(void) 832 { 833 struct mbuf *m; 834 835 MGETHDR(m, M_DONTWAIT, MT_DATA); 836 if (m == NULL) 837 return (NULL); 838 839 MCLGET(m, M_DONTWAIT); 840 if (!(m->m_flags & M_EXT)) { 841 m_freem(m); 842 return (NULL); 843 } 844 845 m->m_len = m->m_pkthdr.len = MCLBYTES; 846 m_adj(m, ETHER_ALIGN); 847 848 return (m); 849 } 850 851 int 852 axe_rx_list_init(struct axe_softc *sc) 853 { 854 struct axe_cdata *cd; 855 struct axe_chain *c; 856 int i; 857 858 DPRINTF(("%s: %s: enter\n", sc->axe_dev.dv_xname, __func__)); 859 860 cd = &sc->axe_cdata; 861 for (i = 0; i < AXE_RX_LIST_CNT; i++) { 862 c = &cd->axe_rx_chain[i]; 863 c->axe_sc = sc; 864 c->axe_idx = i; 865 c->axe_mbuf = NULL; 866 if (c->axe_xfer == NULL) { 867 c->axe_xfer = usbd_alloc_xfer(sc->axe_udev); 868 if (c->axe_xfer == NULL) 869 return (ENOBUFS); 870 c->axe_buf = usbd_alloc_buffer(c->axe_xfer, 871 sc->axe_bufsz); 872 if (c->axe_buf == NULL) { 873 usbd_free_xfer(c->axe_xfer); 874 return (ENOBUFS); 875 } 876 } 877 } 878 879 return (0); 880 } 881 882 int 883 axe_tx_list_init(struct axe_softc *sc) 884 { 885 struct axe_cdata *cd; 886 struct axe_chain *c; 887 int i; 888 889 DPRINTF(("%s: %s: enter\n", sc->axe_dev.dv_xname, __func__)); 890 891 cd = &sc->axe_cdata; 892 for (i = 0; i < AXE_TX_LIST_CNT; i++) { 893 c = &cd->axe_tx_chain[i]; 894 c->axe_sc = sc; 895 c->axe_idx = i; 896 c->axe_mbuf = NULL; 897 if (c->axe_xfer == NULL) { 898 c->axe_xfer = usbd_alloc_xfer(sc->axe_udev); 899 if (c->axe_xfer == NULL) 900 return (ENOBUFS); 901 c->axe_buf = usbd_alloc_buffer(c->axe_xfer, 902 sc->axe_bufsz); 903 if (c->axe_buf == NULL) { 904 usbd_free_xfer(c->axe_xfer); 905 return (ENOBUFS); 906 } 907 } 908 } 909 910 return (0); 911 } 912 913 /* 914 * A frame has been uploaded: pass the resulting mbuf chain up to 915 * the higher level protocols. 916 */ 917 void 918 axe_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 919 { 920 struct axe_chain *c = (struct axe_chain *)priv; 921 struct axe_softc *sc = c->axe_sc; 922 struct ifnet *ifp = GET_IFP(sc); 923 u_char *buf = c->axe_buf; 924 u_int32_t total_len; 925 u_int16_t pktlen = 0; 926 struct mbuf *m; 927 struct axe_sframe_hdr hdr; 928 int s; 929 930 DPRINTFN(10,("%s: %s: enter\n", sc->axe_dev.dv_xname,__func__)); 931 932 if (sc->axe_dying) 933 return; 934 935 if (!(ifp->if_flags & IFF_RUNNING)) 936 return; 937 938 if (status != USBD_NORMAL_COMPLETION) { 939 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 940 return; 941 if (usbd_ratecheck(&sc->axe_rx_notice)) { 942 printf("%s: usb errors on rx: %s\n", 943 sc->axe_dev.dv_xname, usbd_errstr(status)); 944 } 945 if (status == USBD_STALLED) 946 usbd_clear_endpoint_stall_async(sc->axe_ep[AXE_ENDPT_RX]); 947 goto done; 948 } 949 950 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 951 952 do { 953 if (sc->axe_flags & AX178 || sc->axe_flags & AX772) { 954 if (total_len < sizeof(hdr)) { 955 ifp->if_ierrors++; 956 goto done; 957 } 958 959 buf += pktlen; 960 961 memcpy(&hdr, buf, sizeof(hdr)); 962 total_len -= sizeof(hdr); 963 964 if ((hdr.len ^ hdr.ilen) != 0xffff) { 965 ifp->if_ierrors++; 966 goto done; 967 } 968 pktlen = letoh16(hdr.len); 969 if (pktlen > total_len) { 970 ifp->if_ierrors++; 971 goto done; 972 } 973 974 buf += sizeof(hdr); 975 976 if ((pktlen % 2) != 0) 977 pktlen++; 978 979 if ((total_len - pktlen) < 0) 980 total_len = 0; 981 else 982 total_len -= pktlen; 983 } else { 984 pktlen = total_len; /* crc on the end? */ 985 total_len = 0; 986 } 987 988 m = axe_newbuf(); 989 if (m == NULL) { 990 ifp->if_ierrors++; 991 goto done; 992 } 993 994 ifp->if_ipackets++; 995 m->m_pkthdr.rcvif = ifp; 996 m->m_pkthdr.len = m->m_len = pktlen; 997 998 memcpy(mtod(m, char *), buf, pktlen); 999 1000 /* push the packet up */ 1001 s = splnet(); 1002 #if NBPFILTER > 0 1003 if (ifp->if_bpf) 1004 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); 1005 #endif 1006 1007 ether_input_mbuf(ifp, m); 1008 1009 splx(s); 1010 1011 } while (total_len > 0); 1012 1013 done: 1014 memset(c->axe_buf, 0, sc->axe_bufsz); 1015 1016 /* Setup new transfer. */ 1017 usbd_setup_xfer(xfer, sc->axe_ep[AXE_ENDPT_RX], 1018 c, c->axe_buf, sc->axe_bufsz, 1019 USBD_SHORT_XFER_OK | USBD_NO_COPY, 1020 USBD_NO_TIMEOUT, axe_rxeof); 1021 usbd_transfer(xfer); 1022 1023 DPRINTFN(10,("%s: %s: start rx\n", sc->axe_dev.dv_xname, __func__)); 1024 1025 return; 1026 } 1027 1028 /* 1029 * A frame was downloaded to the chip. It's safe for us to clean up 1030 * the list buffers. 1031 */ 1032 1033 void 1034 axe_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 1035 { 1036 struct axe_softc *sc; 1037 struct axe_chain *c; 1038 struct ifnet *ifp; 1039 int s; 1040 1041 c = priv; 1042 sc = c->axe_sc; 1043 ifp = &sc->arpcom.ac_if; 1044 1045 if (sc->axe_dying) 1046 return; 1047 1048 s = splnet(); 1049 1050 if (status != USBD_NORMAL_COMPLETION) { 1051 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 1052 splx(s); 1053 return; 1054 } 1055 ifp->if_oerrors++; 1056 printf("axe%d: usb error on tx: %s\n", sc->axe_unit, 1057 usbd_errstr(status)); 1058 if (status == USBD_STALLED) 1059 usbd_clear_endpoint_stall_async(sc->axe_ep[AXE_ENDPT_TX]); 1060 splx(s); 1061 return; 1062 } 1063 1064 ifp->if_timer = 0; 1065 ifp->if_flags &= ~IFF_OACTIVE; 1066 1067 m_freem(c->axe_mbuf); 1068 c->axe_mbuf = NULL; 1069 1070 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 1071 axe_start(ifp); 1072 1073 ifp->if_opackets++; 1074 splx(s); 1075 return; 1076 } 1077 1078 void 1079 axe_tick(void *xsc) 1080 { 1081 struct axe_softc *sc = xsc; 1082 1083 if (sc == NULL) 1084 return; 1085 1086 DPRINTFN(0xff, ("%s: %s: enter\n", sc->axe_dev.dv_xname, 1087 __func__)); 1088 1089 if (sc->axe_dying) 1090 return; 1091 1092 /* Perform periodic stuff in process context */ 1093 usb_add_task(sc->axe_udev, &sc->axe_tick_task); 1094 1095 } 1096 1097 void 1098 axe_tick_task(void *xsc) 1099 { 1100 int s; 1101 struct axe_softc *sc; 1102 struct ifnet *ifp; 1103 struct mii_data *mii; 1104 1105 sc = xsc; 1106 1107 if (sc == NULL) 1108 return; 1109 1110 if (sc->axe_dying) 1111 return; 1112 1113 ifp = GET_IFP(sc); 1114 mii = GET_MII(sc); 1115 if (mii == NULL) 1116 return; 1117 1118 s = splnet(); 1119 1120 mii_tick(mii); 1121 if (!sc->axe_link && mii->mii_media_status & IFM_ACTIVE && 1122 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 1123 DPRINTF(("%s: %s: got link\n", 1124 sc->axe_dev.dv_xname, __func__)); 1125 sc->axe_link++; 1126 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 1127 axe_start(ifp); 1128 } 1129 1130 timeout_add_sec(&sc->axe_stat_ch, 1); 1131 1132 splx(s); 1133 } 1134 1135 int 1136 axe_encap(struct axe_softc *sc, struct mbuf *m, int idx) 1137 { 1138 struct axe_chain *c; 1139 usbd_status err; 1140 struct axe_sframe_hdr hdr; 1141 int length, boundary; 1142 1143 c = &sc->axe_cdata.axe_tx_chain[idx]; 1144 1145 if (sc->axe_flags & AX178 || sc->axe_flags & AX772) { 1146 boundary = (sc->axe_udev->speed == USB_SPEED_HIGH) ? 512 : 64; 1147 1148 hdr.len = htole16(m->m_pkthdr.len); 1149 hdr.ilen = ~hdr.len; 1150 1151 memcpy(c->axe_buf, &hdr, sizeof(hdr)); 1152 length = sizeof(hdr); 1153 1154 m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf + length); 1155 length += m->m_pkthdr.len; 1156 1157 if ((length % boundary) == 0) { 1158 hdr.len = 0x0000; 1159 hdr.ilen = 0xffff; 1160 memcpy(c->axe_buf + length, &hdr, sizeof(hdr)); 1161 length += sizeof(hdr); 1162 } 1163 1164 } else { 1165 m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf); 1166 length = m->m_pkthdr.len; 1167 } 1168 1169 c->axe_mbuf = m; 1170 1171 usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_TX], 1172 c, c->axe_buf, length, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 1173 10000, axe_txeof); 1174 1175 /* Transmit */ 1176 err = usbd_transfer(c->axe_xfer); 1177 if (err != USBD_IN_PROGRESS) { 1178 axe_stop(sc); 1179 return(EIO); 1180 } 1181 1182 sc->axe_cdata.axe_tx_cnt++; 1183 1184 return(0); 1185 } 1186 1187 void 1188 axe_start(struct ifnet *ifp) 1189 { 1190 struct axe_softc *sc; 1191 struct mbuf *m_head = NULL; 1192 1193 sc = ifp->if_softc; 1194 1195 if (!sc->axe_link) 1196 return; 1197 1198 if (ifp->if_flags & IFF_OACTIVE) 1199 return; 1200 1201 IFQ_POLL(&ifp->if_snd, m_head); 1202 if (m_head == NULL) 1203 return; 1204 1205 if (axe_encap(sc, m_head, 0)) { 1206 ifp->if_flags |= IFF_OACTIVE; 1207 return; 1208 } 1209 IFQ_DEQUEUE(&ifp->if_snd, m_head); 1210 1211 /* 1212 * If there's a BPF listener, bounce a copy of this frame 1213 * to him. 1214 */ 1215 #if NBPFILTER > 0 1216 if (ifp->if_bpf) 1217 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); 1218 #endif 1219 1220 ifp->if_flags |= IFF_OACTIVE; 1221 1222 /* 1223 * Set a timeout in case the chip goes out to lunch. 1224 */ 1225 ifp->if_timer = 5; 1226 1227 return; 1228 } 1229 1230 void 1231 axe_init(void *xsc) 1232 { 1233 struct axe_softc *sc = xsc; 1234 struct ifnet *ifp = &sc->arpcom.ac_if; 1235 struct axe_chain *c; 1236 usbd_status err; 1237 int rxmode; 1238 int i, s; 1239 1240 s = splnet(); 1241 1242 /* 1243 * Cancel pending I/O and free all RX/TX buffers. 1244 */ 1245 axe_reset(sc); 1246 1247 /* set MAC address */ 1248 if (sc->axe_flags & AX178 || sc->axe_flags & AX772) 1249 axe_cmd(sc, AXE_178_CMD_WRITE_NODEID, 0, 0, 1250 &sc->arpcom.ac_enaddr); 1251 1252 /* Enable RX logic. */ 1253 1254 /* Init RX ring. */ 1255 if (axe_rx_list_init(sc) == ENOBUFS) { 1256 printf("axe%d: rx list init failed\n", sc->axe_unit); 1257 splx(s); 1258 return; 1259 } 1260 1261 /* Init TX ring. */ 1262 if (axe_tx_list_init(sc) == ENOBUFS) { 1263 printf("axe%d: tx list init failed\n", sc->axe_unit); 1264 splx(s); 1265 return; 1266 } 1267 1268 /* Set transmitter IPG values */ 1269 if (sc->axe_flags & AX178 || sc->axe_flags & AX772) 1270 axe_cmd(sc, AXE_178_CMD_WRITE_IPG012, sc->axe_ipgs[2], 1271 (sc->axe_ipgs[1] << 8) | (sc->axe_ipgs[0]), NULL); 1272 else { 1273 axe_cmd(sc, AXE_172_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL); 1274 axe_cmd(sc, AXE_172_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL); 1275 axe_cmd(sc, AXE_172_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL); 1276 } 1277 1278 /* Enable receiver, set RX mode */ 1279 rxmode = AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE; 1280 if (sc->axe_flags & AX178 || sc->axe_flags & AX772) { 1281 if (sc->axe_udev->speed == USB_SPEED_HIGH) { 1282 /* largest possible USB buffer size for AX88178 */ 1283 rxmode |= AXE_178_RXCMD_MFB; 1284 } 1285 } else 1286 rxmode |= AXE_172_RXCMD_UNICAST; 1287 1288 /* If we want promiscuous mode, set the allframes bit. */ 1289 if (ifp->if_flags & IFF_PROMISC) 1290 rxmode |= AXE_RXCMD_PROMISC; 1291 1292 if (ifp->if_flags & IFF_BROADCAST) 1293 rxmode |= AXE_RXCMD_BROADCAST; 1294 1295 axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); 1296 1297 /* Load the multicast filter. */ 1298 axe_setmulti(sc); 1299 1300 /* Open RX and TX pipes. */ 1301 err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_RX], 1302 USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_RX]); 1303 if (err) { 1304 printf("axe%d: open rx pipe failed: %s\n", 1305 sc->axe_unit, usbd_errstr(err)); 1306 splx(s); 1307 return; 1308 } 1309 1310 err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_TX], 1311 USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_TX]); 1312 if (err) { 1313 printf("axe%d: open tx pipe failed: %s\n", 1314 sc->axe_unit, usbd_errstr(err)); 1315 splx(s); 1316 return; 1317 } 1318 1319 /* Start up the receive pipe. */ 1320 for (i = 0; i < AXE_RX_LIST_CNT; i++) { 1321 c = &sc->axe_cdata.axe_rx_chain[i]; 1322 usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX], 1323 c, c->axe_buf, sc->axe_bufsz, 1324 USBD_SHORT_XFER_OK | USBD_NO_COPY, 1325 USBD_NO_TIMEOUT, axe_rxeof); 1326 usbd_transfer(c->axe_xfer); 1327 } 1328 1329 ifp->if_flags |= IFF_RUNNING; 1330 ifp->if_flags &= ~IFF_OACTIVE; 1331 1332 splx(s); 1333 1334 timeout_add_sec(&sc->axe_stat_ch, 1); 1335 return; 1336 } 1337 1338 int 1339 axe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1340 { 1341 struct axe_softc *sc = ifp->if_softc; 1342 struct ifreq *ifr = (struct ifreq *)data; 1343 struct ifaddr *ifa = (struct ifaddr *)data; 1344 struct mii_data *mii; 1345 uWord rxmode; 1346 int s, error = 0; 1347 1348 s = splnet(); 1349 1350 switch(cmd) { 1351 case SIOCSIFADDR: 1352 ifp->if_flags |= IFF_UP; 1353 if (!(ifp->if_flags & IFF_RUNNING)) 1354 axe_init(sc); 1355 #ifdef INET 1356 if (ifa->ifa_addr->sa_family == AF_INET) 1357 arp_ifinit(&sc->arpcom, ifa); 1358 #endif 1359 break; 1360 1361 case SIOCSIFFLAGS: 1362 if (ifp->if_flags & IFF_UP) { 1363 if (ifp->if_flags & IFF_RUNNING && 1364 ifp->if_flags & IFF_PROMISC && 1365 !(sc->axe_if_flags & IFF_PROMISC)) { 1366 1367 axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, rxmode); 1368 axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 1369 UGETW(rxmode) | AXE_RXCMD_PROMISC, NULL); 1370 1371 axe_setmulti(sc); 1372 } else if (ifp->if_flags & IFF_RUNNING && 1373 !(ifp->if_flags & IFF_PROMISC) && 1374 sc->axe_if_flags & IFF_PROMISC) { 1375 axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, rxmode); 1376 axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 1377 UGETW(rxmode) & ~AXE_RXCMD_PROMISC, NULL); 1378 axe_setmulti(sc); 1379 } else if (!(ifp->if_flags & IFF_RUNNING)) 1380 axe_init(sc); 1381 } else { 1382 if (ifp->if_flags & IFF_RUNNING) 1383 axe_stop(sc); 1384 } 1385 sc->axe_if_flags = ifp->if_flags; 1386 break; 1387 1388 case SIOCGIFMEDIA: 1389 case SIOCSIFMEDIA: 1390 mii = GET_MII(sc); 1391 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1392 break; 1393 1394 default: 1395 error = ether_ioctl(ifp, &sc->arpcom, cmd, data); 1396 } 1397 1398 if (error == ENETRESET) { 1399 if (ifp->if_flags & IFF_RUNNING) 1400 axe_setmulti(sc); 1401 error = 0; 1402 } 1403 1404 splx(s); 1405 return(error); 1406 } 1407 1408 void 1409 axe_watchdog(struct ifnet *ifp) 1410 { 1411 struct axe_softc *sc; 1412 struct axe_chain *c; 1413 usbd_status stat; 1414 int s; 1415 1416 sc = ifp->if_softc; 1417 1418 ifp->if_oerrors++; 1419 printf("axe%d: watchdog timeout\n", sc->axe_unit); 1420 1421 s = splusb(); 1422 c = &sc->axe_cdata.axe_tx_chain[0]; 1423 usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &stat); 1424 axe_txeof(c->axe_xfer, c, stat); 1425 1426 if (!IFQ_IS_EMPTY(&ifp->if_snd)) 1427 axe_start(ifp); 1428 splx(s); 1429 } 1430 1431 /* 1432 * Stop the adapter and free any mbufs allocated to the 1433 * RX and TX lists. 1434 */ 1435 void 1436 axe_stop(struct axe_softc *sc) 1437 { 1438 usbd_status err; 1439 struct ifnet *ifp; 1440 int i; 1441 1442 axe_reset(sc); 1443 1444 ifp = &sc->arpcom.ac_if; 1445 ifp->if_timer = 0; 1446 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 1447 1448 timeout_del(&sc->axe_stat_ch); 1449 1450 /* Stop transfers. */ 1451 if (sc->axe_ep[AXE_ENDPT_RX] != NULL) { 1452 err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]); 1453 if (err) { 1454 printf("axe%d: abort rx pipe failed: %s\n", 1455 sc->axe_unit, usbd_errstr(err)); 1456 } 1457 err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_RX]); 1458 if (err) { 1459 printf("axe%d: close rx pipe failed: %s\n", 1460 sc->axe_unit, usbd_errstr(err)); 1461 } 1462 sc->axe_ep[AXE_ENDPT_RX] = NULL; 1463 } 1464 1465 if (sc->axe_ep[AXE_ENDPT_TX] != NULL) { 1466 err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]); 1467 if (err) { 1468 printf("axe%d: abort tx pipe failed: %s\n", 1469 sc->axe_unit, usbd_errstr(err)); 1470 } 1471 err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_TX]); 1472 if (err) { 1473 printf("axe%d: close tx pipe failed: %s\n", 1474 sc->axe_unit, usbd_errstr(err)); 1475 } 1476 sc->axe_ep[AXE_ENDPT_TX] = NULL; 1477 } 1478 1479 if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) { 1480 err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]); 1481 if (err) { 1482 printf("axe%d: abort intr pipe failed: %s\n", 1483 sc->axe_unit, usbd_errstr(err)); 1484 } 1485 err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_INTR]); 1486 if (err) { 1487 printf("axe%d: close intr pipe failed: %s\n", 1488 sc->axe_unit, usbd_errstr(err)); 1489 } 1490 sc->axe_ep[AXE_ENDPT_INTR] = NULL; 1491 } 1492 1493 /* Free RX resources. */ 1494 for (i = 0; i < AXE_RX_LIST_CNT; i++) { 1495 if (sc->axe_cdata.axe_rx_chain[i].axe_mbuf != NULL) { 1496 m_freem(sc->axe_cdata.axe_rx_chain[i].axe_mbuf); 1497 sc->axe_cdata.axe_rx_chain[i].axe_mbuf = NULL; 1498 } 1499 if (sc->axe_cdata.axe_rx_chain[i].axe_xfer != NULL) { 1500 usbd_free_xfer(sc->axe_cdata.axe_rx_chain[i].axe_xfer); 1501 sc->axe_cdata.axe_rx_chain[i].axe_xfer = NULL; 1502 } 1503 } 1504 1505 /* Free TX resources. */ 1506 for (i = 0; i < AXE_TX_LIST_CNT; i++) { 1507 if (sc->axe_cdata.axe_tx_chain[i].axe_mbuf != NULL) { 1508 m_freem(sc->axe_cdata.axe_tx_chain[i].axe_mbuf); 1509 sc->axe_cdata.axe_tx_chain[i].axe_mbuf = NULL; 1510 } 1511 if (sc->axe_cdata.axe_tx_chain[i].axe_xfer != NULL) { 1512 usbd_free_xfer(sc->axe_cdata.axe_tx_chain[i].axe_xfer); 1513 sc->axe_cdata.axe_tx_chain[i].axe_xfer = NULL; 1514 } 1515 } 1516 1517 sc->axe_link = 0; 1518 } 1519 1520