mii.c (215711) | mii.c (221407) |
---|---|
1/* $NetBSD: mii.c,v 1.12 1999/08/03 19:41:49 drochner Exp $ */ 2 3/*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, --- 17 unchanged lines hidden (view full) --- 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 THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> | 1/* $NetBSD: mii.c,v 1.12 1999/08/03 19:41:49 drochner Exp $ */ 2 3/*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, --- 17 unchanged lines hidden (view full) --- 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 THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> |
34__FBSDID("$FreeBSD: head/sys/dev/mii/mii.c 215711 2010-11-22 20:57:44Z marius $"); | 34__FBSDID("$FreeBSD: head/sys/dev/mii/mii.c 221407 2011-05-03 19:51:29Z marius $"); |
35 36/* 37 * MII bus layer, glues MII-capable network interface drivers to sharable 38 * PHY drivers. This exports an interface compatible with BSD/OS 3.0's, 39 * plus some NetBSD extensions. 40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/socket.h> 45#include <sys/malloc.h> 46#include <sys/module.h> | 35 36/* 37 * MII bus layer, glues MII-capable network interface drivers to sharable 38 * PHY drivers. This exports an interface compatible with BSD/OS 3.0's, 39 * plus some NetBSD extensions. 40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/socket.h> 45#include <sys/malloc.h> 46#include <sys/module.h> |
47#include <sys/bus.h> | 47#include |
48 49#include <net/if.h> 50#include <net/if_media.h> 51#include <net/route.h> 52 53#include <dev/mii/mii.h> 54#include <dev/mii/miivar.h> 55 --- 8 unchanged lines hidden (view full) --- 64 size_t buflen); 65static int miibus_child_pnpinfo_str(device_t bus, device_t child, char *buf, 66 size_t buflen); 67static int miibus_readreg(device_t, int, int); 68static int miibus_writereg(device_t, int, int, int); 69static void miibus_statchg(device_t); 70static void miibus_linkchg(device_t); 71static void miibus_mediainit(device_t); | 48 49#include <net/if.h> 50#include <net/if_media.h> 51#include <net/route.h> 52 53#include <dev/mii/mii.h> 54#include <dev/mii/miivar.h> 55 --- 8 unchanged lines hidden (view full) --- 64 size_t buflen); 65static int miibus_child_pnpinfo_str(device_t bus, device_t child, char *buf, 66 size_t buflen); 67static int miibus_readreg(device_t, int, int); 68static int miibus_writereg(device_t, int, int, int); 69static void miibus_statchg(device_t); 70static void miibus_linkchg(device_t); 71static void miibus_mediainit(device_t); |
72static unsigned char mii_bitreverse(unsigned char x); |
|
72 73static device_method_t miibus_methods[] = { 74 /* device interface */ 75 DEVMETHOD(device_probe, miibus_probe), 76 DEVMETHOD(device_attach, miibus_attach), 77 DEVMETHOD(device_detach, miibus_detach), 78 DEVMETHOD(device_shutdown, bus_generic_shutdown), 79 80 /* bus interface */ 81 DEVMETHOD(bus_print_child, miibus_print_child), 82 DEVMETHOD(bus_read_ivar, miibus_read_ivar), 83 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 84 DEVMETHOD(bus_child_pnpinfo_str, miibus_child_pnpinfo_str), 85 DEVMETHOD(bus_child_location_str, miibus_child_location_str), 86 87 /* MII interface */ 88 DEVMETHOD(miibus_readreg, miibus_readreg), 89 DEVMETHOD(miibus_writereg, miibus_writereg), | 73 74static device_method_t miibus_methods[] = { 75 /* device interface */ 76 DEVMETHOD(device_probe, miibus_probe), 77 DEVMETHOD(device_attach, miibus_attach), 78 DEVMETHOD(device_detach, miibus_detach), 79 DEVMETHOD(device_shutdown, bus_generic_shutdown), 80 81 /* bus interface */ 82 DEVMETHOD(bus_print_child, miibus_print_child), 83 DEVMETHOD(bus_read_ivar, miibus_read_ivar), 84 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 85 DEVMETHOD(bus_child_pnpinfo_str, miibus_child_pnpinfo_str), 86 DEVMETHOD(bus_child_location_str, miibus_child_location_str), 87 88 /* MII interface */ 89 DEVMETHOD(miibus_readreg, miibus_readreg), 90 DEVMETHOD(miibus_writereg, miibus_writereg), |
90 DEVMETHOD(miibus_statchg, miibus_statchg), 91 DEVMETHOD(miibus_linkchg, miibus_linkchg), 92 DEVMETHOD(miibus_mediainit, miibus_mediainit), | 91 DEVMETHOD(miibus_statchg, miibus_statchg), 92 DEVMETHOD(miibus_linkchg, miibus_linkchg), 93 DEVMETHOD(miibus_mediainit, miibus_mediainit), |
93 94 { 0, 0 } 95}; 96 97devclass_t miibus_devclass; 98 99driver_t miibus_driver = { 100 "miibus", --- 159 unchanged lines hidden (view full) --- 260 struct mii_data *mii; 261 device_t parent; 262 int link_state; 263 264 parent = device_get_parent(dev); 265 MIIBUS_LINKCHG(parent); 266 267 mii = device_get_softc(dev); | 94 95 { 0, 0 } 96}; 97 98devclass_t miibus_devclass; 99 100driver_t miibus_driver = { 101 "miibus", --- 159 unchanged lines hidden (view full) --- 261 struct mii_data *mii; 262 device_t parent; 263 int link_state; 264 265 parent = device_get_parent(dev); 266 MIIBUS_LINKCHG(parent); 267 268 mii = device_get_softc(dev); |
268 | 269 |
269 if (mii->mii_media_status & IFM_AVALID) { 270 if (mii->mii_media_status & IFM_ACTIVE) 271 link_state = LINK_STATE_UP; 272 else 273 link_state = LINK_STATE_DOWN; 274 } else 275 link_state = LINK_STATE_UNKNOWN; 276 if_link_state_change(mii->mii_ifp, link_state); --- 79 unchanged lines hidden (view full) --- 356 return (EINVAL); 357 } 358 /* 359 * Assignment of the attach arguments mii_data for the first 360 * pass is done in miibus_attach(), i.e. once the miibus softc 361 * has been allocated. 362 */ 363 ma.mii_data = device_get_softc(*miibus); | 270 if (mii->mii_media_status & IFM_AVALID) { 271 if (mii->mii_media_status & IFM_ACTIVE) 272 link_state = LINK_STATE_UP; 273 else 274 link_state = LINK_STATE_DOWN; 275 } else 276 link_state = LINK_STATE_UNKNOWN; 277 if_link_state_change(mii->mii_ifp, link_state); --- 79 unchanged lines hidden (view full) --- 357 return (EINVAL); 358 } 359 /* 360 * Assignment of the attach arguments mii_data for the first 361 * pass is done in miibus_attach(), i.e. once the miibus softc 362 * has been allocated. 363 */ 364 ma.mii_data = device_get_softc(*miibus); |
364 } | 365 } |
365 366 ma.mii_capmask = capmask; 367 368 phy = NULL; 369 offset = 0; 370 for (ma.mii_phyno = phymin; ma.mii_phyno <= phymax; ma.mii_phyno++) { 371 /* 372 * Make sure we haven't already configured a PHY at this --- 14 unchanged lines hidden (view full) --- 387 } 388 free(children, M_TEMP); 389 } 390 391 /* 392 * Check to see if there is a PHY at this address. Note, 393 * many braindead PHYs report 0/0 in their ID registers, 394 * so we test for media in the BMSR. | 366 367 ma.mii_capmask = capmask; 368 369 phy = NULL; 370 offset = 0; 371 for (ma.mii_phyno = phymin; ma.mii_phyno <= phymax; ma.mii_phyno++) { 372 /* 373 * Make sure we haven't already configured a PHY at this --- 14 unchanged lines hidden (view full) --- 388 } 389 free(children, M_TEMP); 390 } 391 392 /* 393 * Check to see if there is a PHY at this address. Note, 394 * many braindead PHYs report 0/0 in their ID registers, 395 * so we test for media in the BMSR. |
395 */ | 396 */ |
396 bmsr = MIIBUS_READREG(dev, ma.mii_phyno, MII_BMSR); 397 if (bmsr == 0 || bmsr == 0xffff || 398 (bmsr & (BMSR_EXTSTAT | BMSR_MEDIAMASK)) == 0) { 399 /* Assume no PHY at this address. */ 400 continue; 401 } 402 403 /* 404 * There is a PHY at this address. If we were given an 405 * `offset' locator, skip this PHY if it doesn't match. 406 */ 407 if (offloc != MII_OFFSET_ANY && offloc != offset) 408 goto skip; 409 410 /* 411 * Extract the IDs. Braindead PHYs will be handled by 412 * the `ukphy' driver, as we have no ID information to 413 * match on. | 397 bmsr = MIIBUS_READREG(dev, ma.mii_phyno, MII_BMSR); 398 if (bmsr == 0 || bmsr == 0xffff || 399 (bmsr & (BMSR_EXTSTAT | BMSR_MEDIAMASK)) == 0) { 400 /* Assume no PHY at this address. */ 401 continue; 402 } 403 404 /* 405 * There is a PHY at this address. If we were given an 406 * `offset' locator, skip this PHY if it doesn't match. 407 */ 408 if (offloc != MII_OFFSET_ANY && offloc != offset) 409 goto skip; 410 411 /* 412 * Extract the IDs. Braindead PHYs will be handled by 413 * the `ukphy' driver, as we have no ID information to 414 * match on. |
414 */ | 415 */ |
415 ma.mii_id1 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR1); 416 ma.mii_id2 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR2); 417 | 416 ma.mii_id1 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR1); 417 ma.mii_id2 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR2); 418 |
419 ma.mii_offset = offset; |
|
418 args = malloc(sizeof(struct mii_attach_args), M_DEVBUF, 419 M_NOWAIT); 420 if (args == NULL) 421 goto skip; 422 bcopy((char *)&ma, (char *)args, sizeof(ma)); 423 phy = device_add_child(*miibus, NULL, -1); 424 if (phy == NULL) { 425 free(args, M_DEVBUF); --- 55 unchanged lines hidden (view full) --- 481 "can't handle non-zero PHY instance %d\n", 482 __func__, child->mii_inst); 483 continue; 484 } 485 PHY_WRITE(child, MII_BMCR, PHY_READ(child, MII_BMCR) | 486 BMCR_ISO); 487 continue; 488 } | 420 args = malloc(sizeof(struct mii_attach_args), M_DEVBUF, 421 M_NOWAIT); 422 if (args == NULL) 423 goto skip; 424 bcopy((char *)&ma, (char *)args, sizeof(ma)); 425 phy = device_add_child(*miibus, NULL, -1); 426 if (phy == NULL) { 427 free(args, M_DEVBUF); --- 55 unchanged lines hidden (view full) --- 483 "can't handle non-zero PHY instance %d\n", 484 __func__, child->mii_inst); 485 continue; 486 } 487 PHY_WRITE(child, MII_BMCR, PHY_READ(child, MII_BMCR) | 488 BMCR_ISO); 489 continue; 490 } |
489 rv = (*child->mii_service)(child, mii, MII_MEDIACHG); | 491 rv = PHY_SERVICE(child, mii, MII_MEDIACHG); |
490 if (rv) 491 return (rv); 492 } 493 return (0); 494} 495 496/* 497 * Call the PHY tick routines, used during autonegotiation. --- 6 unchanged lines hidden (view full) --- 504 505 LIST_FOREACH(child, &mii->mii_phys, mii_list) { 506 /* 507 * If this PHY instance isn't currently selected, just skip 508 * it. 509 */ 510 if (IFM_INST(ife->ifm_media) != child->mii_inst) 511 continue; | 492 if (rv) 493 return (rv); 494 } 495 return (0); 496} 497 498/* 499 * Call the PHY tick routines, used during autonegotiation. --- 6 unchanged lines hidden (view full) --- 506 507 LIST_FOREACH(child, &mii->mii_phys, mii_list) { 508 /* 509 * If this PHY instance isn't currently selected, just skip 510 * it. 511 */ 512 if (IFM_INST(ife->ifm_media) != child->mii_inst) 513 continue; |
512 (void)(*child->mii_service)(child, mii, MII_TICK); | 514 (void)PHY_SERVICE(child, mii, MII_TICK); |
513 } 514} 515 516/* 517 * Get media status from PHYs. 518 */ 519void 520mii_pollstat(struct mii_data *mii) --- 5 unchanged lines hidden (view full) --- 526 mii->mii_media_active = IFM_NONE; 527 528 LIST_FOREACH(child, &mii->mii_phys, mii_list) { 529 /* 530 * If we're not polling this PHY instance, just skip it. 531 */ 532 if (IFM_INST(ife->ifm_media) != child->mii_inst) 533 continue; | 515 } 516} 517 518/* 519 * Get media status from PHYs. 520 */ 521void 522mii_pollstat(struct mii_data *mii) --- 5 unchanged lines hidden (view full) --- 528 mii->mii_media_active = IFM_NONE; 529 530 LIST_FOREACH(child, &mii->mii_phys, mii_list) { 531 /* 532 * If we're not polling this PHY instance, just skip it. 533 */ 534 if (IFM_INST(ife->ifm_media) != child->mii_inst) 535 continue; |
534 (void)(*child->mii_service)(child, mii, MII_POLLSTAT); | 536 (void)PHY_SERVICE(child, mii, MII_POLLSTAT); |
535 } 536} 537 538/* 539 * Inform the PHYs that the interface is down. 540 */ 541void 542mii_down(struct mii_data *mii) 543{ 544 struct mii_softc *child; 545 546 LIST_FOREACH(child, &mii->mii_phys, mii_list) 547 mii_phy_down(child); 548} | 537 } 538} 539 540/* 541 * Inform the PHYs that the interface is down. 542 */ 543void 544mii_down(struct mii_data *mii) 545{ 546 struct mii_softc *child; 547 548 LIST_FOREACH(child, &mii->mii_phys, mii_list) 549 mii_phy_down(child); 550} |
551 552static unsigned char 553mii_bitreverse(unsigned char x) 554{ 555 static unsigned char nibbletab[16] = { 556 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 557 }; 558 559 return ((nibbletab[x & 15] << 4) | nibbletab[x >> 4]); 560} 561 562u_int 563mii_oui(u_int id1, u_int id2) 564{ 565 u_int h; 566 567 h = (id1 << 6) | (id2 >> 10); 568 569 return ((mii_bitreverse(h >> 16) << 16) | 570 (mii_bitreverse((h >> 8) & 0xff) << 8) | 571 mii_bitreverse(h & 0xff)); 572} |
|