mii_physubr.c revision 214265
150120Swpaul/*	$NetBSD: mii_physubr.c,v 1.5 1999/08/03 19:41:49 drochner Exp $	*/
250120Swpaul
350120Swpaul/*-
495718Sphk * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
550120Swpaul * All rights reserved.
650120Swpaul *
750120Swpaul * This code is derived from software contributed to The NetBSD Foundation
850120Swpaul * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
950120Swpaul * NASA Ames Research Center.
1050120Swpaul *
1150120Swpaul * Redistribution and use in source and binary forms, with or without
1250120Swpaul * modification, are permitted provided that the following conditions
1350120Swpaul * are met:
1450120Swpaul * 1. Redistributions of source code must retain the above copyright
1550120Swpaul *    notice, this list of conditions and the following disclaimer.
1650120Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1750120Swpaul *    notice, this list of conditions and the following disclaimer in the
1850120Swpaul *    documentation and/or other materials provided with the distribution.
1950120Swpaul *
2050120Swpaul * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2150120Swpaul * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2250120Swpaul * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2350120Swpaul * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2450120Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2550120Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2650120Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2750120Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2850120Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2950120Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3050120Swpaul * POSSIBILITY OF SUCH DAMAGE.
3150120Swpaul */
3250120Swpaul
33119418Sobrien#include <sys/cdefs.h>
34119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/mii/mii_physubr.c 214265 2010-10-24 12:59:43Z marius $");
35119418Sobrien
3650120Swpaul/*
3750120Swpaul * Subroutines common to all PHYs.
3850120Swpaul */
3950120Swpaul
4050120Swpaul#include <sys/param.h>
4150120Swpaul#include <sys/systm.h>
4250120Swpaul#include <sys/kernel.h>
4350120Swpaul#include <sys/socket.h>
4450120Swpaul#include <sys/errno.h>
4550120Swpaul#include <sys/module.h>
4650120Swpaul#include <sys/bus.h>
4750120Swpaul
4850120Swpaul#include <net/if.h>
4950120Swpaul#include <net/if_media.h>
5050120Swpaul
5150120Swpaul#include <dev/mii/mii.h>
5250120Swpaul#include <dev/mii/miivar.h>
5350120Swpaul
5450120Swpaul#include "miibus_if.h"
5550120Swpaul
5695707Sphk/*
5795707Sphk * Media to register setting conversion table.  Order matters.
5895707Sphk */
59214265Smariusstatic const struct mii_media mii_media_table[MII_NMEDIA] = {
6095707Sphk	/* None */
6195707Sphk	{ BMCR_ISO,		ANAR_CSMA,
6295707Sphk	  0, },
6395707Sphk
6495707Sphk	/* 10baseT */
6595707Sphk	{ BMCR_S10,		ANAR_CSMA|ANAR_10,
6695707Sphk	  0, },
6795707Sphk
6895707Sphk	/* 10baseT-FDX */
6995707Sphk	{ BMCR_S10|BMCR_FDX,	ANAR_CSMA|ANAR_10_FD,
7095707Sphk	  0, },
7195707Sphk
7295707Sphk	/* 100baseT4 */
7395707Sphk	{ BMCR_S100,		ANAR_CSMA|ANAR_T4,
7495707Sphk	  0, },
7595707Sphk
7695707Sphk	/* 100baseTX */
7795707Sphk	{ BMCR_S100,		ANAR_CSMA|ANAR_TX,
7895707Sphk	  0, },
7995707Sphk
8095707Sphk	/* 100baseTX-FDX */
8195707Sphk	{ BMCR_S100|BMCR_FDX,	ANAR_CSMA|ANAR_TX_FD,
8295707Sphk	  0, },
8395707Sphk
8495707Sphk	/* 1000baseX */
8595707Sphk	{ BMCR_S1000,		ANAR_CSMA,
8695707Sphk	  0, },
8795707Sphk
8895707Sphk	/* 1000baseX-FDX */
8995707Sphk	{ BMCR_S1000|BMCR_FDX,	ANAR_CSMA,
9095707Sphk	  0, },
9195707Sphk
9295707Sphk	/* 1000baseT */
9395707Sphk	{ BMCR_S1000,		ANAR_CSMA,
9495707Sphk	  GTCR_ADV_1000THDX },
9595707Sphk
9695707Sphk	/* 1000baseT-FDX */
9795707Sphk	{ BMCR_S1000,		ANAR_CSMA,
9895707Sphk	  GTCR_ADV_1000TFDX },
9995707Sphk};
10095707Sphk
10195707Sphkvoid
10295707Sphkmii_phy_setmedia(struct mii_softc *sc)
10395707Sphk{
10495707Sphk	struct mii_data *mii = sc->mii_pdata;
10595707Sphk	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
10695707Sphk	int bmcr, anar, gtcr;
10795707Sphk
10895707Sphk	if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
109164702Smarius		if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0 ||
110164702Smarius		    (sc->mii_flags & MIIF_FORCEANEG))
11196026Sphk			(void) mii_phy_auto(sc);
11295707Sphk		return;
11395707Sphk	}
11495707Sphk
11595707Sphk	/*
11695707Sphk	 * Table index is stored in the media entry.
11795707Sphk	 */
11895707Sphk
11995718Sphk	KASSERT(ife->ifm_data >=0 && ife->ifm_data < MII_NMEDIA,
12095718Sphk	    ("invalid ife->ifm_data (0x%x) in mii_phy_setmedia",
12195718Sphk	    ife->ifm_data));
12295707Sphk
12395707Sphk	anar = mii_media_table[ife->ifm_data].mm_anar;
12495707Sphk	bmcr = mii_media_table[ife->ifm_data].mm_bmcr;
12595707Sphk	gtcr = mii_media_table[ife->ifm_data].mm_gtcr;
12695707Sphk
12795707Sphk	if (mii->mii_media.ifm_media & IFM_ETH_MASTER) {
12895707Sphk		switch (IFM_SUBTYPE(ife->ifm_media)) {
12995707Sphk		case IFM_1000_T:
13095707Sphk			gtcr |= GTCR_MAN_MS|GTCR_ADV_MS;
13195707Sphk			break;
13295707Sphk
13395707Sphk		default:
13495707Sphk			panic("mii_phy_setmedia: MASTER on wrong media");
13595707Sphk		}
13695707Sphk	}
13795707Sphk
13895707Sphk	if (ife->ifm_media & IFM_LOOP)
13995707Sphk		bmcr |= BMCR_LOOP;
14095707Sphk
14195707Sphk	PHY_WRITE(sc, MII_ANAR, anar);
14295707Sphk	PHY_WRITE(sc, MII_BMCR, bmcr);
14395707Sphk	if (sc->mii_flags & MIIF_HAVE_GTCR)
14495707Sphk		PHY_WRITE(sc, MII_100T2CR, gtcr);
14595707Sphk}
14695707Sphk
14750120Swpaulint
14896026Sphkmii_phy_auto(struct mii_softc *sc)
14950120Swpaul{
15050120Swpaul
15196026Sphk	/*
15296026Sphk	 * Check for 1000BASE-X.  Autonegotiation is a bit
15396026Sphk	 * different on such devices.
15496026Sphk	 */
15596026Sphk	if (sc->mii_flags & MIIF_IS_1000X) {
15696026Sphk		uint16_t anar = 0;
15795718Sphk
15896026Sphk		if (sc->mii_extcapabilities & EXTSR_1000XFDX)
15996026Sphk			anar |= ANAR_X_FD;
16096026Sphk		if (sc->mii_extcapabilities & EXTSR_1000XHDX)
16196026Sphk			anar |= ANAR_X_HD;
16295718Sphk
16396026Sphk		if (sc->mii_flags & MIIF_DOPAUSE) {
16496026Sphk			/* XXX Asymmetric vs. symmetric? */
16596026Sphk			anar |= ANLPAR_X_PAUSE_TOWARDS;
16696026Sphk		}
16795718Sphk
16896026Sphk		PHY_WRITE(sc, MII_ANAR, anar);
16996026Sphk	} else {
17096026Sphk		uint16_t anar;
17195718Sphk
17296026Sphk		anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) |
17396026Sphk		    ANAR_CSMA;
17496026Sphk		if (sc->mii_flags & MIIF_DOPAUSE)
17596026Sphk			anar |= ANAR_FC;
17696026Sphk		PHY_WRITE(sc, MII_ANAR, anar);
17796026Sphk		if (sc->mii_flags & MIIF_HAVE_GTCR) {
17896026Sphk			uint16_t gtcr = 0;
17995718Sphk
18096026Sphk			if (sc->mii_extcapabilities & EXTSR_1000TFDX)
18196026Sphk				gtcr |= GTCR_ADV_1000TFDX;
18296026Sphk			if (sc->mii_extcapabilities & EXTSR_1000THDX)
18396026Sphk				gtcr |= GTCR_ADV_1000THDX;
18495718Sphk
18596026Sphk			PHY_WRITE(sc, MII_100T2CR, gtcr);
18695718Sphk		}
18750120Swpaul	}
18896026Sphk	PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
18950120Swpaul	return (EJUSTRETURN);
19050120Swpaul}
19150120Swpaul
19284140Sjlemonint
19395718Sphkmii_phy_tick(struct mii_softc *sc)
19484140Sjlemon{
19584140Sjlemon	struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur;
19684140Sjlemon	struct ifnet *ifp = sc->mii_pdata->mii_ifp;
19784140Sjlemon	int reg;
19884140Sjlemon
19995718Sphk	/* Just bail now if the interface is down. */
20084140Sjlemon	if ((ifp->if_flags & IFF_UP) == 0)
20184140Sjlemon		return (EJUSTRETURN);
20284140Sjlemon
20384140Sjlemon	/*
20484140Sjlemon	 * If we're not doing autonegotiation, we don't need to do
20584140Sjlemon	 * any extra work here.  However, we need to check the link
20684140Sjlemon	 * status so we can generate an announcement if the status
20784140Sjlemon	 * changes.
20884140Sjlemon	 */
209160082Soleg	if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
210160082Soleg		sc->mii_ticks = 0;	/* reset autonegotiation timer. */
21184140Sjlemon		return (0);
212160082Soleg	}
21384140Sjlemon
21495718Sphk	/* Read the status register twice; BMSR_LINK is latch-low. */
21584140Sjlemon	reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
21695718Sphk	if (reg & BMSR_LINK) {
217158649Soleg		sc->mii_ticks = 0;	/* reset autonegotiation timer. */
218158649Soleg		/* See above. */
21984140Sjlemon		return (0);
22095718Sphk	}
22184140Sjlemon
222158649Soleg	/* Announce link loss right after it happens */
223158649Soleg	if (sc->mii_ticks++ == 0)
224128870Sandre		return (0);
225158649Soleg
226158649Soleg	/* XXX: use default value if phy driver did not set mii_anegticks */
227158649Soleg	if (sc->mii_anegticks == 0)
228158649Soleg		sc->mii_anegticks = MII_ANEGTICKS_GIGE;
229158649Soleg
230158649Soleg	/* Only retry autonegotiation every mii_anegticks ticks. */
231158649Soleg	if (sc->mii_ticks <= sc->mii_anegticks)
23284140Sjlemon		return (EJUSTRETURN);
23384140Sjlemon
23484140Sjlemon	sc->mii_ticks = 0;
23584140Sjlemon	mii_phy_reset(sc);
23696026Sphk	mii_phy_auto(sc);
23784140Sjlemon	return (0);
23884140Sjlemon}
23984140Sjlemon
24050120Swpaulvoid
24195718Sphkmii_phy_reset(struct mii_softc *sc)
24250120Swpaul{
243164702Smarius	struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur;
24450120Swpaul	int reg, i;
24550120Swpaul
24695718Sphk	if (sc->mii_flags & MIIF_NOISOLATE)
24750120Swpaul		reg = BMCR_RESET;
24850120Swpaul	else
24950120Swpaul		reg = BMCR_RESET | BMCR_ISO;
25095718Sphk	PHY_WRITE(sc, MII_BMCR, reg);
25150120Swpaul
25250120Swpaul	/* Wait 100ms for it to complete. */
25350120Swpaul	for (i = 0; i < 100; i++) {
254164702Smarius		reg = PHY_READ(sc, MII_BMCR);
25550120Swpaul		if ((reg & BMCR_RESET) == 0)
25650120Swpaul			break;
25750120Swpaul		DELAY(1000);
25850120Swpaul	}
25950120Swpaul
260164702Smarius	if ((sc->mii_flags & MIIF_NOISOLATE) == 0) {
261164702Smarius		if ((ife == NULL && sc->mii_inst != 0) ||
262164702Smarius		    (ife != NULL && IFM_INST(ife->ifm_media) != sc->mii_inst))
263164702Smarius			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
264164702Smarius	}
26550120Swpaul}
26650120Swpaul
26784140Sjlemonvoid
26895722Sphkmii_phy_down(struct mii_softc *sc)
26984140Sjlemon{
27095722Sphk
27195722Sphk}
27295722Sphk
27395722Sphkvoid
27495722Sphkmii_phy_update(struct mii_softc *sc, int cmd)
27595722Sphk{
27684140Sjlemon	struct mii_data *mii = sc->mii_pdata;
27784140Sjlemon
27895722Sphk	if (sc->mii_media_active != mii->mii_media_active ||
27995722Sphk	    cmd == MII_MEDIACHG) {
28084140Sjlemon		MIIBUS_STATCHG(sc->mii_dev);
28195705Sphk		sc->mii_media_active = mii->mii_media_active;
28284140Sjlemon	}
28395705Sphk	if (sc->mii_media_status != mii->mii_media_status) {
28484140Sjlemon		MIIBUS_LINKCHG(sc->mii_dev);
28595705Sphk		sc->mii_media_status = mii->mii_media_status;
28684140Sjlemon	}
28784140Sjlemon}
28884140Sjlemon
28950120Swpaul/*
29050120Swpaul * Initialize generic PHY media based on BMSR, called when a PHY is
29150120Swpaul * attached.  We expect to be set up to print a comma-separated list
29250120Swpaul * of media names.  Does not print a newline.
29350120Swpaul */
29450120Swpaulvoid
29595718Sphkmii_phy_add_media(struct mii_softc *sc)
29695718Sphk{
29795718Sphk	struct mii_data *mii = sc->mii_pdata;
29895718Sphk	const char *sep = "";
29995718Sphk
300164703Smarius	if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
301164703Smarius	    (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) {
302164703Smarius		printf("no media present");
303164703Smarius		return;
304164703Smarius	}
305164703Smarius
306158649Soleg	/* Set aneg timer for 10/100 media. Gigabit media handled below. */
307158649Soleg	sc->mii_anegticks = MII_ANEGTICKS;
308158649Soleg
30995718Sphk#define	ADD(m, c)	ifmedia_add(&mii->mii_media, (m), (c), NULL)
31095718Sphk#define	PRINT(s)	printf("%s%s", sep, s); sep = ", "
31195718Sphk
31295718Sphk	if ((sc->mii_flags & MIIF_NOISOLATE) == 0)
31395718Sphk		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
31495718Sphk		    MII_MEDIA_NONE);
31595718Sphk
31695718Sphk	/*
31795718Sphk	 * There are different interpretations for the bits in
31895718Sphk	 * HomePNA PHYs.  And there is really only one media type
31995718Sphk	 * that is supported.
32095718Sphk	 */
32195718Sphk	if (sc->mii_flags & MIIF_IS_HPNA) {
32295718Sphk		if (sc->mii_capabilities & BMSR_10THDX) {
32395718Sphk			ADD(IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0,
32495718Sphk					 sc->mii_inst),
32595718Sphk			    MII_MEDIA_10_T);
32695718Sphk			PRINT("HomePNA1");
32795718Sphk		}
32895718Sphk		return;
32995718Sphk	}
33095718Sphk
33195718Sphk	if (sc->mii_capabilities & BMSR_10THDX) {
33295718Sphk		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
33395718Sphk		    MII_MEDIA_10_T);
33495718Sphk		PRINT("10baseT");
33595718Sphk	}
33695718Sphk	if (sc->mii_capabilities & BMSR_10TFDX) {
33795718Sphk		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
33895718Sphk		    MII_MEDIA_10_T_FDX);
33995718Sphk		PRINT("10baseT-FDX");
34095718Sphk	}
34195718Sphk	if (sc->mii_capabilities & BMSR_100TXHDX) {
34295718Sphk		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
34395718Sphk		    MII_MEDIA_100_TX);
34495718Sphk		PRINT("100baseTX");
34595718Sphk	}
34695718Sphk	if (sc->mii_capabilities & BMSR_100TXFDX) {
34795718Sphk		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
34895718Sphk		    MII_MEDIA_100_TX_FDX);
34995718Sphk		PRINT("100baseTX-FDX");
35095718Sphk	}
35195718Sphk	if (sc->mii_capabilities & BMSR_100T4) {
35295718Sphk		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst),
35395718Sphk		    MII_MEDIA_100_T4);
35495718Sphk		PRINT("100baseT4");
35595718Sphk	}
35695718Sphk
35795718Sphk	if (sc->mii_extcapabilities & EXTSR_MEDIAMASK) {
35895718Sphk		/*
35995718Sphk		 * XXX Right now only handle 1000SX and 1000TX.  Need
36095718Sphk		 * XXX to handle 1000LX and 1000CX some how.
36195718Sphk		 */
36295718Sphk		if (sc->mii_extcapabilities & EXTSR_1000XHDX) {
363158649Soleg			sc->mii_anegticks = MII_ANEGTICKS_GIGE;
36495718Sphk			sc->mii_flags |= MIIF_IS_1000X;
36595718Sphk			ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0,
36695718Sphk			    sc->mii_inst), MII_MEDIA_1000_X);
36795718Sphk			PRINT("1000baseSX");
36895718Sphk		}
36995718Sphk		if (sc->mii_extcapabilities & EXTSR_1000XFDX) {
370158649Soleg			sc->mii_anegticks = MII_ANEGTICKS_GIGE;
37195718Sphk			sc->mii_flags |= MIIF_IS_1000X;
37295718Sphk			ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX,
37395718Sphk			    sc->mii_inst), MII_MEDIA_1000_X_FDX);
37495718Sphk			PRINT("1000baseSX-FDX");
37595718Sphk		}
37695718Sphk
37795718Sphk		/*
37895718Sphk		 * 1000baseT media needs to be able to manipulate
37995718Sphk		 * master/slave mode.  We set IFM_ETH_MASTER in
38095718Sphk		 * the "don't care mask" and filter it out when
38195718Sphk		 * the media is set.
38295718Sphk		 *
38395718Sphk		 * All 1000baseT PHYs have a 1000baseT control register.
38495718Sphk		 */
38595718Sphk		if (sc->mii_extcapabilities & EXTSR_1000THDX) {
386158649Soleg			sc->mii_anegticks = MII_ANEGTICKS_GIGE;
38795718Sphk			sc->mii_flags |= MIIF_HAVE_GTCR;
38895718Sphk			mii->mii_media.ifm_mask |= IFM_ETH_MASTER;
38995718Sphk			ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0,
39095718Sphk			    sc->mii_inst), MII_MEDIA_1000_T);
39195718Sphk			PRINT("1000baseT");
39295718Sphk		}
39395718Sphk		if (sc->mii_extcapabilities & EXTSR_1000TFDX) {
394158649Soleg			sc->mii_anegticks = MII_ANEGTICKS_GIGE;
39595718Sphk			sc->mii_flags |= MIIF_HAVE_GTCR;
39695718Sphk			mii->mii_media.ifm_mask |= IFM_ETH_MASTER;
39795718Sphk			ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX,
39895718Sphk			    sc->mii_inst), MII_MEDIA_1000_T_FDX);
39995718Sphk			PRINT("1000baseT-FDX");
40095718Sphk		}
40195718Sphk	}
40295718Sphk
40395718Sphk	if (sc->mii_capabilities & BMSR_ANEG) {
40495718Sphk		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst),
40595718Sphk		    MII_NMEDIA);	/* intentionally invalid index */
40695718Sphk		PRINT("auto");
40795718Sphk	}
40895718Sphk#undef ADD
40995718Sphk#undef PRINT
41095718Sphk}
41195718Sphk
41295722Sphkint
41395722Sphkmii_phy_detach(device_t dev)
41495722Sphk{
41595722Sphk	struct mii_softc *sc;
41695722Sphk
41795722Sphk	sc = device_get_softc(dev);
41895722Sphk	mii_phy_down(sc);
41995722Sphk	sc->mii_dev = NULL;
42095722Sphk	LIST_REMOVE(sc, mii_list);
42195722Sphk
42295722Sphk	return(0);
42395722Sphk}
42495724Sphk
42595724Sphkconst struct mii_phydesc *
426150756Simpmii_phy_match_gen(const struct mii_attach_args *ma,
427150756Simp  const struct mii_phydesc *mpd, size_t len)
42895724Sphk{
42995724Sphk
430150756Simp	for (; mpd->mpd_name != NULL;
431150756Simp	     mpd = (const struct mii_phydesc *) ((const char *) mpd + len)) {
43295724Sphk		if (MII_OUI(ma->mii_id1, ma->mii_id2) == mpd->mpd_oui &&
43395724Sphk		    MII_MODEL(ma->mii_id2) == mpd->mpd_model)
43495724Sphk			return (mpd);
43595724Sphk	}
43695724Sphk	return (NULL);
43795724Sphk}
438150756Simp
439150756Simpconst struct mii_phydesc *
440150756Simpmii_phy_match(const struct mii_attach_args *ma, const struct mii_phydesc *mpd)
441150756Simp{
442164702Smarius
443150756Simp	return (mii_phy_match_gen(ma, mpd, sizeof(struct mii_phydesc)));
444150756Simp}
445164827Smarius
446164827Smariusint
447164827Smariusmii_phy_dev_probe(device_t dev, const struct mii_phydesc *mpd, int mrv)
448164827Smarius{
449164827Smarius
450164827Smarius	mpd = mii_phy_match(device_get_ivars(dev), mpd);
451164827Smarius	if (mpd != NULL) {
452164827Smarius		device_set_desc(dev, mpd->mpd_name);
453164827Smarius		return (mrv);
454164827Smarius	}
455164827Smarius
456164827Smarius	return (ENXIO);
457164827Smarius}
458