Deleted Added
full compact
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}