150120Swpaul/* $NetBSD: ukphy_subr.c,v 1.2 1998/11/05 04:08:02 thorpej Exp $ */ 250120Swpaul 350120Swpaul/*- 450120Swpaul * Copyright (c) 1998 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, and by Frank van der Linden. 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$"); 35119418Sobrien 3650120Swpaul/* 3750120Swpaul * Subroutines shared by the ukphy driver and other PHY drivers. 3850120Swpaul */ 3950120Swpaul 4050120Swpaul#include <sys/param.h> 4150120Swpaul#include <sys/systm.h> 4250120Swpaul#include <sys/socket.h> 4350120Swpaul#include <sys/module.h> 4450120Swpaul#include <sys/bus.h> 4550120Swpaul 4650120Swpaul#include <net/if.h> 4750120Swpaul#include <net/if_media.h> 4850120Swpaul 4950120Swpaul#include <dev/mii/mii.h> 5050120Swpaul#include <dev/mii/miivar.h> 5150120Swpaul 5250120Swpaul#include "miibus_if.h" 5350120Swpaul 5450120Swpaul/* 5550120Swpaul * Media status subroutine. If a PHY driver does media detection simply 5650120Swpaul * by decoding the NWay autonegotiation, use this routine. 5750120Swpaul */ 5850120Swpaulvoid 5995723Sphkukphy_status(struct mii_softc *phy) 6050120Swpaul{ 6150120Swpaul struct mii_data *mii = phy->mii_pdata; 6295723Sphk struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 63158744Syongari int bmsr, bmcr, anlpar, gtcr, gtsr; 6450120Swpaul 6550120Swpaul mii->mii_media_status = IFM_AVALID; 6650120Swpaul mii->mii_media_active = IFM_ETHER; 6750120Swpaul 6850120Swpaul bmsr = PHY_READ(phy, MII_BMSR) | PHY_READ(phy, MII_BMSR); 6950120Swpaul if (bmsr & BMSR_LINK) 7050120Swpaul mii->mii_media_status |= IFM_ACTIVE; 7150120Swpaul 7250120Swpaul bmcr = PHY_READ(phy, MII_BMCR); 7350120Swpaul if (bmcr & BMCR_ISO) { 7450120Swpaul mii->mii_media_active |= IFM_NONE; 7550120Swpaul mii->mii_media_status = 0; 7650120Swpaul return; 7750120Swpaul } 7850120Swpaul 7950120Swpaul if (bmcr & BMCR_LOOP) 8050120Swpaul mii->mii_media_active |= IFM_LOOP; 8150120Swpaul 8250120Swpaul if (bmcr & BMCR_AUTOEN) { 8350120Swpaul /* 8450120Swpaul * NWay autonegotiation takes the highest-order common 8550120Swpaul * bit of the ANAR and ANLPAR (i.e. best media advertised 8650120Swpaul * both by us and our link partner). 8750120Swpaul */ 8850120Swpaul if ((bmsr & BMSR_ACOMP) == 0) { 8950120Swpaul /* Erg, still trying, I guess... */ 9050120Swpaul mii->mii_media_active |= IFM_NONE; 9150120Swpaul return; 9250120Swpaul } 9350120Swpaul 9450120Swpaul anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR); 95158744Syongari if ((phy->mii_flags & MIIF_HAVE_GTCR) != 0 && 96158744Syongari (phy->mii_extcapabilities & 97158744Syongari (EXTSR_1000THDX | EXTSR_1000TFDX)) != 0) { 98158744Syongari gtcr = PHY_READ(phy, MII_100T2CR); 99158744Syongari gtsr = PHY_READ(phy, MII_100T2SR); 100158744Syongari } else 101158744Syongari gtcr = gtsr = 0; 102158744Syongari 103158744Syongari if ((gtcr & GTCR_ADV_1000TFDX) && (gtsr & GTSR_LP_1000TFDX)) 104158744Syongari mii->mii_media_active |= IFM_1000_T|IFM_FDX; 105158744Syongari else if ((gtcr & GTCR_ADV_1000THDX) && 106158744Syongari (gtsr & GTSR_LP_1000THDX)) 107213384Smarius mii->mii_media_active |= IFM_1000_T|IFM_HDX; 108173665Syongari else if (anlpar & ANLPAR_TX_FD) 109173665Syongari mii->mii_media_active |= IFM_100_TX|IFM_FDX; 110158744Syongari else if (anlpar & ANLPAR_T4) 111213384Smarius mii->mii_media_active |= IFM_100_T4|IFM_HDX; 11250120Swpaul else if (anlpar & ANLPAR_TX) 113213384Smarius mii->mii_media_active |= IFM_100_TX|IFM_HDX; 11450120Swpaul else if (anlpar & ANLPAR_10_FD) 11550120Swpaul mii->mii_media_active |= IFM_10_T|IFM_FDX; 11650120Swpaul else if (anlpar & ANLPAR_10) 117213384Smarius mii->mii_media_active |= IFM_10_T|IFM_HDX; 11850120Swpaul else 11950120Swpaul mii->mii_media_active |= IFM_NONE; 120215297Smarius 121215297Smarius if ((mii->mii_media_active & IFM_1000_T) != 0 && 122215297Smarius (gtsr & GTSR_MS_RES) != 0) 123215297Smarius mii->mii_media_active |= IFM_ETH_MASTER; 124215297Smarius 125215297Smarius if ((mii->mii_media_active & IFM_FDX) != 0) 126215297Smarius mii->mii_media_active |= mii_phy_flowstatus(phy); 12750120Swpaul } else 12895723Sphk mii->mii_media_active = ife->ifm_media; 12950120Swpaul} 130