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