1 /*- 2 * Copyright (c) 2000 3 * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Bill Paul. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 /* 37 * Driver for the Broadcom BCR5400 1000baseTX PHY. Speed is always 38 * 1000mbps; all we need to negotiate here is full or half duplex. 39 */ 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/module.h> 45 #include <sys/socket.h> 46 #include <sys/bus.h> 47 48 49 #include <net/if.h> 50 #include <net/ethernet.h> 51 #include <net/if_media.h> 52 53 #include <dev/mii/mii.h> 54 #include <dev/mii/miivar.h> 55 #include "miidevs.h" 56 57 #include <dev/mii/brgphyreg.h> 58 #include <net/if_arp.h> 59 #include <machine/bus.h> 60 #include <dev/bge/if_bgereg.h> 61 #include <dev/bce/if_bcereg.h> 62 63 #include <dev/pci/pcireg.h> 64 #include <dev/pci/pcivar.h> 65 66 #include "miibus_if.h" 67 68 static int brgphy_probe(device_t); 69 static int brgphy_attach(device_t); 70 71 static device_method_t brgphy_methods[] = { 72 /* device interface */ 73 DEVMETHOD(device_probe, brgphy_probe), 74 DEVMETHOD(device_attach, brgphy_attach), 75 DEVMETHOD(device_detach, mii_phy_detach), 76 DEVMETHOD(device_shutdown, bus_generic_shutdown), 77 { 0, 0 } 78 }; 79 80 static devclass_t brgphy_devclass; 81 82 static driver_t brgphy_driver = { 83 "brgphy", 84 brgphy_methods, 85 sizeof(struct mii_softc) 86 }; 87 88 DRIVER_MODULE(brgphy, miibus, brgphy_driver, brgphy_devclass, 0, 0); 89 90 static int brgphy_service(struct mii_softc *, struct mii_data *, int); 91 static void brgphy_status(struct mii_softc *); 92 static int brgphy_mii_phy_auto(struct mii_softc *); 93 static void brgphy_reset(struct mii_softc *); 94 static void brgphy_loop(struct mii_softc *); 95 static void bcm5401_load_dspcode(struct mii_softc *); 96 static void bcm5411_load_dspcode(struct mii_softc *); 97 static void bcm5703_load_dspcode(struct mii_softc *); 98 static void bcm5750_load_dspcode(struct mii_softc *); 99 static int brgphy_mii_model; 100 101 static const struct mii_phydesc brgphys[] = { 102 MII_PHY_DESC(xxBROADCOM, BCM5400), 103 MII_PHY_DESC(xxBROADCOM, BCM5401), 104 MII_PHY_DESC(xxBROADCOM, BCM5411), 105 MII_PHY_DESC(xxBROADCOM, BCM5701), 106 MII_PHY_DESC(xxBROADCOM, BCM5703), 107 MII_PHY_DESC(xxBROADCOM, BCM5704), 108 MII_PHY_DESC(xxBROADCOM, BCM5705), 109 MII_PHY_DESC(xxBROADCOM, BCM5750), 110 MII_PHY_DESC(xxBROADCOM, BCM5714), 111 MII_PHY_DESC(xxBROADCOM, BCM5780), 112 MII_PHY_DESC(xxBROADCOM, BCM5706C), 113 MII_PHY_DESC(xxBROADCOM, BCM5708C), 114 MII_PHY_END 115 }; 116 117 static int 118 brgphy_probe(device_t dev) 119 { 120 struct mii_attach_args *ma; 121 const struct mii_phydesc *mpd; 122 123 ma = device_get_ivars(dev); 124 mpd = mii_phy_match(ma, brgphys); 125 if (mpd != NULL) { 126 device_set_desc(dev, mpd->mpd_name); 127 return (BUS_PROBE_DEFAULT); 128 } 129 130 return (ENXIO); 131 } 132 133 static int 134 brgphy_attach(device_t dev) 135 { 136 struct mii_softc *sc; 137 struct mii_attach_args *ma; 138 struct mii_data *mii; 139 const char *sep = ""; 140 struct bge_softc *bge_sc = NULL; 141 struct bce_softc *bce_sc = NULL; 142 int fast_ether_only = FALSE; 143 144 sc = device_get_softc(dev); 145 ma = device_get_ivars(dev); 146 sc->mii_dev = device_get_parent(dev); 147 mii = device_get_softc(sc->mii_dev); 148 LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); 149 150 sc->mii_inst = mii->mii_instance; 151 sc->mii_phy = ma->mii_phyno; 152 sc->mii_service = brgphy_service; 153 sc->mii_pdata = mii; 154 155 sc->mii_flags |= MIIF_NOISOLATE; 156 mii->mii_instance++; 157 158 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 159 #define PRINT(s) printf("%s%s", sep, s); sep = ", " 160 161 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), 162 BMCR_ISO); 163 #if 0 164 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), 165 BMCR_LOOP|BMCR_S100); 166 #endif 167 168 brgphy_mii_model = MII_MODEL(ma->mii_id2); 169 brgphy_reset(sc); 170 171 172 sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 173 sc->mii_capabilities &= ~BMSR_ANEG; 174 device_printf(dev, " "); 175 mii_add_media(sc); 176 177 /* Find the driver associated with this PHY. */ 178 if (strcmp(mii->mii_ifp->if_dname, "bge") == 0) { 179 bge_sc = mii->mii_ifp->if_softc; 180 } else if (strcmp(mii->mii_ifp->if_dname, "bce") == 0) { 181 bce_sc = mii->mii_ifp->if_softc; 182 } 183 184 /* The 590x chips are 10/100 only. */ 185 if (strcmp(mii->mii_ifp->if_dname, "bge") == 0 && 186 pci_get_vendor(bge_sc->bge_dev) == BCOM_VENDORID && 187 (pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901 || 188 pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901A2)) 189 fast_ether_only = TRUE; 190 191 if (fast_ether_only == FALSE) { 192 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, 193 sc->mii_inst), BRGPHY_BMCR_FDX); 194 PRINT(", 1000baseTX"); 195 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 196 IFM_FDX, sc->mii_inst), 0); 197 PRINT("1000baseTX-FDX"); 198 } 199 200 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0); 201 PRINT("auto"); 202 203 printf("\n"); 204 #undef ADD 205 #undef PRINT 206 207 MIIBUS_MEDIAINIT(sc->mii_dev); 208 return(0); 209 } 210 211 static int 212 brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 213 { 214 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 215 int reg, speed, gig; 216 217 switch (cmd) { 218 case MII_POLLSTAT: 219 /* 220 * If we're not polling our PHY instance, just return. 221 */ 222 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 223 return (0); 224 break; 225 226 case MII_MEDIACHG: 227 /* 228 * If the media indicates a different PHY instance, 229 * isolate ourselves. 230 */ 231 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 232 reg = PHY_READ(sc, MII_BMCR); 233 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 234 return (0); 235 } 236 237 /* 238 * If the interface is not up, don't do anything. 239 */ 240 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 241 break; 242 243 brgphy_reset(sc); /* XXX hardware bug work-around */ 244 245 switch (IFM_SUBTYPE(ife->ifm_media)) { 246 case IFM_AUTO: 247 #ifdef foo 248 /* 249 * If we're already in auto mode, just return. 250 */ 251 if (PHY_READ(sc, BRGPHY_MII_BMCR) & BRGPHY_BMCR_AUTOEN) 252 return (0); 253 #endif 254 (void) brgphy_mii_phy_auto(sc); 255 break; 256 case IFM_1000_T: 257 speed = BRGPHY_S1000; 258 goto setit; 259 case IFM_100_TX: 260 speed = BRGPHY_S100; 261 goto setit; 262 case IFM_10_T: 263 speed = BRGPHY_S10; 264 setit: 265 brgphy_loop(sc); 266 if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) { 267 speed |= BRGPHY_BMCR_FDX; 268 gig = BRGPHY_1000CTL_AFD; 269 } else { 270 gig = BRGPHY_1000CTL_AHD; 271 } 272 273 PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0); 274 PHY_WRITE(sc, BRGPHY_MII_BMCR, speed); 275 PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE); 276 277 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) 278 break; 279 280 PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig); 281 PHY_WRITE(sc, BRGPHY_MII_BMCR, 282 speed|BRGPHY_BMCR_AUTOEN|BRGPHY_BMCR_STARTNEG); 283 284 if (brgphy_mii_model != MII_MODEL_xxBROADCOM_BCM5701) 285 break; 286 287 /* 288 * When settning the link manually, one side must 289 * be the master and the other the slave. However 290 * ifmedia doesn't give us a good way to specify 291 * this, so we fake it by using one of the LINK 292 * flags. If LINK0 is set, we program the PHY to 293 * be a master, otherwise it's a slave. 294 */ 295 if ((mii->mii_ifp->if_flags & IFF_LINK0)) { 296 PHY_WRITE(sc, BRGPHY_MII_1000CTL, 297 gig|BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC); 298 } else { 299 PHY_WRITE(sc, BRGPHY_MII_1000CTL, 300 gig|BRGPHY_1000CTL_MSE); 301 } 302 break; 303 #ifdef foo 304 case IFM_NONE: 305 PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN); 306 break; 307 #endif 308 case IFM_100_T4: 309 default: 310 return (EINVAL); 311 } 312 break; 313 314 case MII_TICK: 315 /* 316 * If we're not currently selected, just return. 317 */ 318 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 319 return (0); 320 321 /* 322 * Is the interface even up? 323 */ 324 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 325 return (0); 326 327 /* 328 * Only used for autonegotiation. 329 */ 330 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) 331 break; 332 333 /* 334 * Check to see if we have link. If we do, we don't 335 * need to restart the autonegotiation process. Read 336 * the BMSR twice in case it's latched. 337 */ 338 reg = PHY_READ(sc, BRGPHY_MII_AUXSTS); 339 if (reg & BRGPHY_AUXSTS_LINK) 340 break; 341 342 /* 343 * Only retry autonegotiation every 5 seconds. 344 */ 345 if (++sc->mii_ticks <= 5) 346 break; 347 348 sc->mii_ticks = 0; 349 brgphy_mii_phy_auto(sc); 350 break; 351 } 352 353 /* Update the media status. */ 354 brgphy_status(sc); 355 356 /* 357 * Callback if something changed. Note that we need to poke 358 * the DSP on the Broadcom PHYs if the media changes. 359 * 360 */ 361 if (sc->mii_media_active != mii->mii_media_active || 362 sc->mii_media_status != mii->mii_media_status || 363 cmd == MII_MEDIACHG) { 364 switch (brgphy_mii_model) { 365 case MII_MODEL_xxBROADCOM_BCM5400: 366 case MII_MODEL_xxBROADCOM_BCM5401: 367 bcm5401_load_dspcode(sc); 368 break; 369 case MII_MODEL_xxBROADCOM_BCM5411: 370 bcm5411_load_dspcode(sc); 371 break; 372 } 373 } 374 mii_phy_update(sc, cmd); 375 return (0); 376 } 377 378 static void 379 brgphy_status(struct mii_softc *sc) 380 { 381 struct mii_data *mii = sc->mii_pdata; 382 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 383 int bmsr, bmcr; 384 385 mii->mii_media_status = IFM_AVALID; 386 mii->mii_media_active = IFM_ETHER; 387 388 bmsr = PHY_READ(sc, BRGPHY_MII_BMSR); 389 if (PHY_READ(sc, BRGPHY_MII_AUXSTS) & BRGPHY_AUXSTS_LINK) 390 mii->mii_media_status |= IFM_ACTIVE; 391 392 bmcr = PHY_READ(sc, BRGPHY_MII_BMCR); 393 394 if (bmcr & BRGPHY_BMCR_LOOP) 395 mii->mii_media_active |= IFM_LOOP; 396 397 if (bmcr & BRGPHY_BMCR_AUTOEN) { 398 if ((bmsr & BRGPHY_BMSR_ACOMP) == 0) { 399 /* Erg, still trying, I guess... */ 400 mii->mii_media_active |= IFM_NONE; 401 return; 402 } 403 404 switch (PHY_READ(sc, BRGPHY_MII_AUXSTS) & 405 BRGPHY_AUXSTS_AN_RES) { 406 case BRGPHY_RES_1000FD: 407 mii->mii_media_active |= IFM_1000_T | IFM_FDX; 408 break; 409 case BRGPHY_RES_1000HD: 410 mii->mii_media_active |= IFM_1000_T | IFM_HDX; 411 break; 412 case BRGPHY_RES_100FD: 413 mii->mii_media_active |= IFM_100_TX | IFM_FDX; 414 break; 415 case BRGPHY_RES_100T4: 416 mii->mii_media_active |= IFM_100_T4; 417 break; 418 case BRGPHY_RES_100HD: 419 mii->mii_media_active |= IFM_100_TX | IFM_HDX; 420 break; 421 case BRGPHY_RES_10FD: 422 mii->mii_media_active |= IFM_10_T | IFM_FDX; 423 break; 424 case BRGPHY_RES_10HD: 425 mii->mii_media_active |= IFM_10_T | IFM_HDX; 426 break; 427 default: 428 mii->mii_media_active |= IFM_NONE; 429 break; 430 } 431 return; 432 } 433 434 mii->mii_media_active = ife->ifm_media; 435 436 return; 437 } 438 439 440 static int 441 brgphy_mii_phy_auto(struct mii_softc *mii) 442 { 443 int ktcr = 0; 444 445 brgphy_loop(mii); 446 brgphy_reset(mii); 447 ktcr = BRGPHY_1000CTL_AFD|BRGPHY_1000CTL_AHD; 448 if (brgphy_mii_model == MII_MODEL_xxBROADCOM_BCM5701) 449 ktcr |= BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC; 450 PHY_WRITE(mii, BRGPHY_MII_1000CTL, ktcr); 451 ktcr = PHY_READ(mii, BRGPHY_MII_1000CTL); 452 DELAY(1000); 453 PHY_WRITE(mii, BRGPHY_MII_ANAR, 454 BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA); 455 DELAY(1000); 456 PHY_WRITE(mii, BRGPHY_MII_BMCR, 457 BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG); 458 PHY_WRITE(mii, BRGPHY_MII_IMR, 0xFF00); 459 return (EJUSTRETURN); 460 } 461 462 static void 463 brgphy_loop(struct mii_softc *sc) 464 { 465 u_int32_t bmsr; 466 int i; 467 468 PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_LOOP); 469 for (i = 0; i < 15000; i++) { 470 bmsr = PHY_READ(sc, BRGPHY_MII_BMSR); 471 if (!(bmsr & BRGPHY_BMSR_LINK)) { 472 #if 0 473 device_printf(sc->mii_dev, "looped %d\n", i); 474 #endif 475 break; 476 } 477 DELAY(10); 478 } 479 } 480 481 /* Turn off tap power management on 5401. */ 482 static void 483 bcm5401_load_dspcode(struct mii_softc *sc) 484 { 485 static const struct { 486 int reg; 487 uint16_t val; 488 } dspcode[] = { 489 { BRGPHY_MII_AUXCTL, 0x0c20 }, 490 { BRGPHY_MII_DSP_ADDR_REG, 0x0012 }, 491 { BRGPHY_MII_DSP_RW_PORT, 0x1804 }, 492 { BRGPHY_MII_DSP_ADDR_REG, 0x0013 }, 493 { BRGPHY_MII_DSP_RW_PORT, 0x1204 }, 494 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 495 { BRGPHY_MII_DSP_RW_PORT, 0x0132 }, 496 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 497 { BRGPHY_MII_DSP_RW_PORT, 0x0232 }, 498 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 499 { BRGPHY_MII_DSP_RW_PORT, 0x0a20 }, 500 { 0, 0 }, 501 }; 502 int i; 503 504 for (i = 0; dspcode[i].reg != 0; i++) 505 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 506 DELAY(40); 507 } 508 509 static void 510 bcm5411_load_dspcode(struct mii_softc *sc) 511 { 512 static const struct { 513 int reg; 514 uint16_t val; 515 } dspcode[] = { 516 { 0x1c, 0x8c23 }, 517 { 0x1c, 0x8ca3 }, 518 { 0x1c, 0x8c23 }, 519 { 0, 0 }, 520 }; 521 int i; 522 523 for (i = 0; dspcode[i].reg != 0; i++) 524 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 525 } 526 527 static void 528 bcm5703_load_dspcode(struct mii_softc *sc) 529 { 530 static const struct { 531 int reg; 532 uint16_t val; 533 } dspcode[] = { 534 { BRGPHY_MII_AUXCTL, 0x0c00 }, 535 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 536 { BRGPHY_MII_DSP_RW_PORT, 0x2aaa }, 537 { 0, 0 }, 538 }; 539 int i; 540 541 for (i = 0; dspcode[i].reg != 0; i++) 542 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 543 } 544 545 static void 546 bcm5704_load_dspcode(struct mii_softc *sc) 547 { 548 static const struct { 549 int reg; 550 u_int16_t val; 551 } dspcode[] = { 552 { 0x1c, 0x8d68 }, 553 { 0x1c, 0x8d68 }, 554 { 0, 0 }, 555 }; 556 int i; 557 558 for (i = 0; dspcode[i].reg != 0; i++) 559 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 560 } 561 562 static void 563 bcm5750_load_dspcode(struct mii_softc *sc) 564 { 565 static const struct { 566 int reg; 567 u_int16_t val; 568 } dspcode[] = { 569 { 0x18, 0x0c00 }, 570 { 0x17, 0x000a }, 571 { 0x15, 0x310b }, 572 { 0x17, 0x201f }, 573 { 0x15, 0x9506 }, 574 { 0x17, 0x401f }, 575 { 0x15, 0x14e2 }, 576 { 0x18, 0x0400 }, 577 { 0, 0 }, 578 }; 579 int i; 580 581 for (i = 0; dspcode[i].reg != 0; i++) 582 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 583 } 584 585 static void 586 brgphy_reset(struct mii_softc *sc) 587 { 588 u_int32_t val; 589 struct ifnet *ifp; 590 struct bge_softc *bge_sc = NULL; 591 struct bce_softc *bce_sc = NULL; 592 593 mii_phy_reset(sc); 594 595 switch (brgphy_mii_model) { 596 case MII_MODEL_xxBROADCOM_BCM5400: 597 case MII_MODEL_xxBROADCOM_BCM5401: 598 bcm5401_load_dspcode(sc); 599 break; 600 case MII_MODEL_xxBROADCOM_BCM5411: 601 bcm5411_load_dspcode(sc); 602 break; 603 case MII_MODEL_xxBROADCOM_BCM5703: 604 bcm5703_load_dspcode(sc); 605 break; 606 case MII_MODEL_xxBROADCOM_BCM5704: 607 bcm5704_load_dspcode(sc); 608 break; 609 case MII_MODEL_xxBROADCOM_BCM5750: 610 case MII_MODEL_xxBROADCOM_BCM5714: 611 case MII_MODEL_xxBROADCOM_BCM5780: 612 case MII_MODEL_xxBROADCOM_BCM5706C: 613 case MII_MODEL_xxBROADCOM_BCM5708C: 614 bcm5750_load_dspcode(sc); 615 break; 616 } 617 618 ifp = sc->mii_pdata->mii_ifp; 619 620 /* Find the driver associated with this PHY. */ 621 if (strcmp(ifp->if_dname, "bge") == 0) { 622 bge_sc = ifp->if_softc; 623 } else if (strcmp(ifp->if_dname, "bce") == 0) { 624 bce_sc = ifp->if_softc; 625 } 626 627 /* Handle any NetXtreme/bge workarounds. */ 628 if (bge_sc) { 629 /* 630 * Don't enable Ethernet@WireSpeed for the 5700 or the 631 * 5705 A1 and A2 chips. Make sure we only do this test 632 * on "bge" NICs, since other drivers may use this same 633 * PHY subdriver. 634 */ 635 if (bge_sc->bge_asicrev == BGE_ASICREV_BCM5700 || 636 bge_sc->bge_chipid == BGE_CHIPID_BCM5705_A1 || 637 bge_sc->bge_chipid == BGE_CHIPID_BCM5705_A2) 638 return; 639 640 /* Enable Ethernet@WireSpeed. */ 641 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007); 642 val = PHY_READ(sc, BRGPHY_MII_AUXCTL); 643 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4)); 644 645 /* Enable Link LED on Dell boxes */ 646 if (bge_sc->bge_no_3_led) { 647 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, 648 PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) 649 & ~BRGPHY_PHY_EXTCTL_3_LED); 650 } 651 } else if (bce_sc) { 652 653 /* Set or clear jumbo frame settings in the PHY. */ 654 if (ifp->if_mtu > ETHER_MAX_LEN) { 655 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7); 656 val = PHY_READ(sc, BRGPHY_MII_AUXCTL); 657 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 658 val | BRGPHY_AUXCTL_LONG_PKT); 659 660 val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL); 661 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, 662 val | BRGPHY_PHY_EXTCTL_HIGH_LA); 663 } else { 664 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7); 665 val = PHY_READ(sc, BRGPHY_MII_AUXCTL); 666 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 667 val & ~(BRGPHY_AUXCTL_LONG_PKT | 0x7)); 668 669 val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL); 670 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, 671 val & ~BRGPHY_PHY_EXTCTL_HIGH_LA); 672 } 673 674 /* Enable Ethernet@Wirespeed */ 675 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007); 676 val = PHY_READ(sc, BRGPHY_MII_AUXCTL); 677 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, (val | (1 << 15) | (1 << 4))); 678 } 679 } 680