Home | History | Annotate | Line # | Download | only in mii
igphy.c revision 1.4
      1  1.4  thorpej /*	$NetBSD: igphy.c,v 1.4 2004/08/23 06:16:06 thorpej Exp $	*/
      2  1.1     fvdl 
      3  1.1     fvdl /*
      4  1.1     fvdl  * The Intel copyright applies to the analog register setup, and the
      5  1.1     fvdl  * (currently disabled) SmartSpeed workaround code.
      6  1.1     fvdl  */
      7  1.1     fvdl 
      8  1.1     fvdl /*******************************************************************************
      9  1.1     fvdl 
     10  1.1     fvdl   Copyright (c) 2001-2003, Intel Corporation
     11  1.1     fvdl   All rights reserved.
     12  1.1     fvdl 
     13  1.1     fvdl   Redistribution and use in source and binary forms, with or without
     14  1.1     fvdl   modification, are permitted provided that the following conditions are met:
     15  1.1     fvdl 
     16  1.1     fvdl    1. Redistributions of source code must retain the above copyright notice,
     17  1.1     fvdl       this list of conditions and the following disclaimer.
     18  1.1     fvdl 
     19  1.1     fvdl    2. Redistributions in binary form must reproduce the above copyright
     20  1.1     fvdl       notice, this list of conditions and the following disclaimer in the
     21  1.1     fvdl       documentation and/or other materials provided with the distribution.
     22  1.1     fvdl 
     23  1.1     fvdl    3. Neither the name of the Intel Corporation nor the names of its
     24  1.1     fvdl       contributors may be used to endorse or promote products derived from
     25  1.1     fvdl       this software without specific prior written permission.
     26  1.1     fvdl 
     27  1.1     fvdl   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     28  1.1     fvdl   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     29  1.1     fvdl   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     30  1.1     fvdl   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     31  1.1     fvdl   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  1.1     fvdl   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  1.1     fvdl   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  1.1     fvdl   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  1.1     fvdl   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  1.1     fvdl   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  1.1     fvdl   POSSIBILITY OF SUCH DAMAGE.
     38  1.1     fvdl 
     39  1.1     fvdl *******************************************************************************/
     40  1.1     fvdl 
     41  1.1     fvdl 
     42  1.1     fvdl /*-
     43  1.1     fvdl  * Copyright (c) 1998, 1999, 2000, 2003 The NetBSD Foundation, Inc.
     44  1.1     fvdl  * All rights reserved.
     45  1.1     fvdl  *
     46  1.1     fvdl  * This code is derived from software contributed to The NetBSD Foundation
     47  1.1     fvdl  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
     48  1.1     fvdl  * NASA Ames Research Center, and by Frank van der Linden.
     49  1.1     fvdl  *
     50  1.1     fvdl  * Redistribution and use in source and binary forms, with or without
     51  1.1     fvdl  * modification, are permitted provided that the following conditions
     52  1.1     fvdl  * are met:
     53  1.1     fvdl  * 1. Redistributions of source code must retain the above copyright
     54  1.1     fvdl  *    notice, this list of conditions and the following disclaimer.
     55  1.1     fvdl  * 2. Redistributions in binary form must reproduce the above copyright
     56  1.1     fvdl  *    notice, this list of conditions and the following disclaimer in the
     57  1.1     fvdl  *    documentation and/or other materials provided with the distribution.
     58  1.1     fvdl  * 3. All advertising materials mentioning features or use of this software
     59  1.1     fvdl  *    must display the following acknowledgement:
     60  1.1     fvdl  *	This product includes software developed by the NetBSD
     61  1.1     fvdl  *	Foundation, Inc. and its contributors.
     62  1.1     fvdl  * 4. Neither the name of The NetBSD Foundation nor the names of its
     63  1.1     fvdl  *    contributors may be used to endorse or promote products derived
     64  1.1     fvdl  *    from this software without specific prior written permission.
     65  1.1     fvdl  *
     66  1.1     fvdl  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     67  1.1     fvdl  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     68  1.1     fvdl  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     69  1.1     fvdl  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     70  1.1     fvdl  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     71  1.1     fvdl  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     72  1.1     fvdl  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     73  1.1     fvdl  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     74  1.1     fvdl  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     75  1.1     fvdl  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     76  1.1     fvdl  * POSSIBILITY OF SUCH DAMAGE.
     77  1.1     fvdl  */
     78  1.1     fvdl 
     79  1.1     fvdl #include <sys/cdefs.h>
     80  1.4  thorpej __KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.4 2004/08/23 06:16:06 thorpej Exp $");
     81  1.1     fvdl 
     82  1.1     fvdl #include "opt_mii.h"
     83  1.1     fvdl 
     84  1.1     fvdl #include <sys/param.h>
     85  1.1     fvdl #include <sys/systm.h>
     86  1.1     fvdl #include <sys/kernel.h>
     87  1.1     fvdl #include <sys/device.h>
     88  1.1     fvdl #include <sys/socket.h>
     89  1.1     fvdl #include <sys/errno.h>
     90  1.1     fvdl 
     91  1.1     fvdl #include <net/if.h>
     92  1.1     fvdl #include <net/if_media.h>
     93  1.1     fvdl 
     94  1.1     fvdl #include <dev/mii/mii.h>
     95  1.1     fvdl #include <dev/mii/miivar.h>
     96  1.1     fvdl #include <dev/mii/miidevs.h>
     97  1.1     fvdl 
     98  1.1     fvdl #include <dev/mii/igphyreg.h>
     99  1.1     fvdl 
    100  1.1     fvdl static void igphy_reset(struct mii_softc *);
    101  1.1     fvdl static void igphy_load_dspcode(struct mii_softc *);
    102  1.1     fvdl #if 0
    103  1.1     fvdl static void igphy_smartspeed_workaround(struct mii_softc *sc);
    104  1.1     fvdl #endif
    105  1.1     fvdl 
    106  1.4  thorpej static int	igphymatch(struct device *, struct cfdata *, void *);
    107  1.4  thorpej static void	igphyattach(struct device *, struct device *, void *);
    108  1.1     fvdl 
    109  1.1     fvdl CFATTACH_DECL(igphy, sizeof(struct mii_softc),
    110  1.1     fvdl     igphymatch, igphyattach, mii_phy_detach, mii_phy_activate);
    111  1.1     fvdl 
    112  1.4  thorpej static int	igphy_service(struct mii_softc *, struct mii_data *, int);
    113  1.4  thorpej static void	igphy_status(struct mii_softc *);
    114  1.1     fvdl 
    115  1.4  thorpej static const struct mii_phy_funcs igphy_funcs = {
    116  1.1     fvdl 	igphy_service, igphy_status, igphy_reset,
    117  1.1     fvdl };
    118  1.1     fvdl 
    119  1.4  thorpej static const struct mii_phydesc igphys[] = {
    120  1.1     fvdl 	{ MII_OUI_yyINTEL,		MII_MODEL_yyINTEL_IGP01E1000,
    121  1.1     fvdl 	  MII_STR_yyINTEL_IGP01E1000 },
    122  1.1     fvdl 
    123  1.1     fvdl 	{0,				0,
    124  1.1     fvdl 	 NULL },
    125  1.1     fvdl };
    126  1.1     fvdl 
    127  1.4  thorpej static int
    128  1.1     fvdl igphymatch(struct device *parent, struct cfdata *match, void *aux)
    129  1.1     fvdl {
    130  1.1     fvdl 	struct mii_attach_args *ma = aux;
    131  1.1     fvdl 
    132  1.1     fvdl 	if (mii_phy_match(ma, igphys) != NULL)
    133  1.1     fvdl 		return 10;
    134  1.1     fvdl 
    135  1.1     fvdl 	return 0;
    136  1.1     fvdl }
    137  1.1     fvdl 
    138  1.4  thorpej static void
    139  1.1     fvdl igphyattach(struct device *parent, struct device *self, void *aux)
    140  1.1     fvdl {
    141  1.1     fvdl 	struct mii_softc *sc = (struct mii_softc *)self;
    142  1.1     fvdl 	struct mii_attach_args *ma = aux;
    143  1.1     fvdl 	struct mii_data *mii = ma->mii_data;
    144  1.1     fvdl 	const struct mii_phydesc *mpd;
    145  1.1     fvdl 
    146  1.1     fvdl 	mpd = mii_phy_match(ma, igphys);
    147  1.1     fvdl 	aprint_naive(": Media interface\n");
    148  1.1     fvdl 	aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
    149  1.1     fvdl 
    150  1.1     fvdl 	sc->mii_inst = mii->mii_instance;
    151  1.1     fvdl 	sc->mii_phy = ma->mii_phyno;
    152  1.1     fvdl 	sc->mii_funcs = &igphy_funcs;
    153  1.1     fvdl 	sc->mii_pdata = mii;
    154  1.1     fvdl 	sc->mii_flags = ma->mii_flags;
    155  1.1     fvdl 	sc->mii_anegticks = 10;
    156  1.1     fvdl 
    157  1.1     fvdl 	PHY_RESET(sc);
    158  1.1     fvdl 
    159  1.1     fvdl 	sc->mii_capabilities =
    160  1.1     fvdl 	    PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
    161  1.1     fvdl 	if (sc->mii_capabilities & BMSR_EXTSTAT)
    162  1.1     fvdl 		sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
    163  1.1     fvdl 	aprint_normal("%s: ", sc->mii_dev.dv_xname);
    164  1.1     fvdl 	if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
    165  1.1     fvdl 	    (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
    166  1.1     fvdl 		aprint_error("no media present");
    167  1.1     fvdl 	else
    168  1.1     fvdl 		mii_phy_add_media(sc);
    169  1.1     fvdl 	aprint_normal("\n");
    170  1.1     fvdl }
    171  1.1     fvdl 
    172  1.1     fvdl static void
    173  1.1     fvdl igphy_load_dspcode(struct mii_softc *sc)
    174  1.1     fvdl {
    175  1.1     fvdl 	static const struct {
    176  1.1     fvdl 		int reg;
    177  1.1     fvdl 		uint16_t val;
    178  1.1     fvdl 	} dspcode[] = {
    179  1.1     fvdl 		{ 0x1f95, 0x0001 },
    180  1.1     fvdl 		{ 0x1f71, 0xbd21 },
    181  1.1     fvdl 		{ 0x1f79, 0x0018 },
    182  1.1     fvdl 		{ 0x1f30, 0x1600 },
    183  1.1     fvdl 		{ 0x1f31, 0x0014 },
    184  1.1     fvdl 		{ 0x1f32, 0x161c },
    185  1.1     fvdl 		{ 0x1f94, 0x0003 },
    186  1.1     fvdl 		{ 0x1f96, 0x003f },
    187  1.1     fvdl 		{ 0x2010, 0x0008 },
    188  1.1     fvdl 		{ 0, 0 },
    189  1.1     fvdl 	};
    190  1.1     fvdl 	int i;
    191  1.1     fvdl 
    192  1.1     fvdl 	delay(10);
    193  1.1     fvdl 
    194  1.1     fvdl 	PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
    195  1.1     fvdl 	PHY_WRITE(sc, 0x0000, 0x0140);
    196  1.1     fvdl 
    197  1.1     fvdl 	delay(5);
    198  1.1     fvdl 
    199  1.1     fvdl 	for (i = 0; dspcode[i].reg != 0; i++)
    200  1.1     fvdl 		IGPHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
    201  1.1     fvdl 
    202  1.1     fvdl 	PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000);
    203  1.1     fvdl 	PHY_WRITE(sc, 0x0000, 0x3300);
    204  1.1     fvdl }
    205  1.1     fvdl 
    206  1.1     fvdl static void
    207  1.1     fvdl igphy_reset(struct mii_softc *sc)
    208  1.1     fvdl {
    209  1.1     fvdl 	uint16_t fused, fine, coarse;
    210  1.1     fvdl 
    211  1.1     fvdl 	mii_phy_reset(sc);
    212  1.1     fvdl 	igphy_load_dspcode(sc);
    213  1.1     fvdl 
    214  1.1     fvdl 	fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_SPARE_FUSE_STATUS);
    215  1.1     fvdl 	if ((fused & ANALOG_SPARE_FUSE_ENABLED) == 0) {
    216  1.1     fvdl 		fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_FUSE_STATUS);
    217  1.1     fvdl 
    218  1.1     fvdl 		fine = fused & ANALOG_FUSE_FINE_MASK;
    219  1.1     fvdl 		coarse = fused & ANALOG_FUSE_COARSE_MASK;
    220  1.1     fvdl 
    221  1.1     fvdl 		if (coarse > ANALOG_FUSE_COARSE_THRESH) {
    222  1.1     fvdl 			coarse -= ANALOG_FUSE_COARSE_10;
    223  1.1     fvdl 			fine -= ANALOG_FUSE_FINE_1;
    224  1.1     fvdl 		} else if (coarse == ANALOG_FUSE_COARSE_THRESH)
    225  1.1     fvdl 			fine -= ANALOG_FUSE_FINE_10;
    226  1.1     fvdl 
    227  1.1     fvdl 		fused = (fused & ANALOG_FUSE_POLY_MASK) |
    228  1.1     fvdl 			(fine & ANALOG_FUSE_FINE_MASK) |
    229  1.1     fvdl 			(coarse & ANALOG_FUSE_COARSE_MASK);
    230  1.1     fvdl 
    231  1.1     fvdl 		IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_CONTROL, fused);
    232  1.1     fvdl 		IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_BYPASS,
    233  1.1     fvdl 		    ANALOG_FUSE_ENABLE_SW_CONTROL);
    234  1.1     fvdl 	}
    235  1.1     fvdl 	PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000);
    236  1.1     fvdl }
    237  1.1     fvdl 
    238  1.1     fvdl 
    239  1.4  thorpej static int
    240  1.1     fvdl igphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
    241  1.1     fvdl {
    242  1.1     fvdl 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
    243  1.1     fvdl 	uint16_t reg;
    244  1.1     fvdl 
    245  1.1     fvdl 	switch (cmd) {
    246  1.1     fvdl 	case MII_POLLSTAT:
    247  1.1     fvdl 		/*
    248  1.1     fvdl 		 * If we're not polling our PHY instance, just return.
    249  1.1     fvdl 		 */
    250  1.1     fvdl 		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
    251  1.1     fvdl 			return (0);
    252  1.1     fvdl 		break;
    253  1.1     fvdl 
    254  1.1     fvdl 	case MII_MEDIACHG:
    255  1.1     fvdl 		/*
    256  1.1     fvdl 		 * If the media indicates a different PHY instance,
    257  1.1     fvdl 		 * isolate ourselves.
    258  1.1     fvdl 		 */
    259  1.1     fvdl 		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
    260  1.1     fvdl 			reg = PHY_READ(sc, MII_BMCR);
    261  1.1     fvdl 			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
    262  1.1     fvdl 			return (0);
    263  1.1     fvdl 		}
    264  1.1     fvdl 
    265  1.1     fvdl 		/*
    266  1.1     fvdl 		 * If the interface is not up, don't do anything.
    267  1.1     fvdl 		 */
    268  1.1     fvdl 		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
    269  1.1     fvdl 			break;
    270  1.1     fvdl 
    271  1.1     fvdl 		mii_phy_setmedia(sc);
    272  1.1     fvdl 		break;
    273  1.1     fvdl 
    274  1.1     fvdl 	case MII_TICK:
    275  1.1     fvdl 		/*
    276  1.1     fvdl 		 * If we're not currently selected, just return.
    277  1.1     fvdl 		 */
    278  1.1     fvdl 		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
    279  1.1     fvdl 			return (0);
    280  1.1     fvdl 
    281  1.1     fvdl #if 0
    282  1.1     fvdl 		igphy_smartspeed_workaround(sc);
    283  1.1     fvdl #endif
    284  1.1     fvdl 
    285  1.1     fvdl 		if (mii_phy_tick(sc) == EJUSTRETURN)
    286  1.1     fvdl 			return (0);
    287  1.1     fvdl 		break;
    288  1.1     fvdl 
    289  1.1     fvdl 	case MII_DOWN:
    290  1.1     fvdl 		mii_phy_down(sc);
    291  1.1     fvdl 		return (0);
    292  1.1     fvdl 	}
    293  1.1     fvdl 
    294  1.1     fvdl 	/* Update the media status. */
    295  1.1     fvdl 	mii_phy_status(sc);
    296  1.1     fvdl 
    297  1.1     fvdl 	/* Callback if something changed. */
    298  1.1     fvdl 	mii_phy_update(sc, cmd);
    299  1.1     fvdl 	return (0);
    300  1.1     fvdl }
    301  1.1     fvdl 
    302  1.1     fvdl 
    303  1.4  thorpej static void
    304  1.1     fvdl igphy_status(struct mii_softc *sc)
    305  1.1     fvdl {
    306  1.1     fvdl 	struct mii_data *mii = sc->mii_pdata;
    307  1.1     fvdl 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
    308  1.1     fvdl 	uint16_t bmcr, pssr, gtsr, bmsr;
    309  1.1     fvdl 
    310  1.1     fvdl 	mii->mii_media_status = IFM_AVALID;
    311  1.1     fvdl 	mii->mii_media_active = IFM_ETHER;
    312  1.1     fvdl 
    313  1.1     fvdl 	pssr = PHY_READ(sc, MII_IGPHY_PORT_STATUS);
    314  1.1     fvdl 
    315  1.1     fvdl 	if (pssr & PSSR_LINK_UP)
    316  1.1     fvdl 		mii->mii_media_status |= IFM_ACTIVE;
    317  1.1     fvdl 
    318  1.1     fvdl 	bmcr = PHY_READ(sc, MII_BMCR);
    319  1.1     fvdl 	if (bmcr & BMCR_ISO) {
    320  1.1     fvdl 		mii->mii_media_active |= IFM_NONE;
    321  1.1     fvdl 		mii->mii_media_status = 0;
    322  1.1     fvdl 		return;
    323  1.1     fvdl 	}
    324  1.1     fvdl 
    325  1.1     fvdl 	if (bmcr & BMCR_LOOP)
    326  1.1     fvdl 		mii->mii_media_active |= IFM_LOOP;
    327  1.1     fvdl 
    328  1.1     fvdl 	bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
    329  1.1     fvdl 
    330  1.1     fvdl 	/*
    331  1.1     fvdl 	 * XXX can't check if the info is valid, no
    332  1.1     fvdl 	 * 'negotiation done' bit?
    333  1.1     fvdl 	 */
    334  1.1     fvdl 	if (bmcr & BMCR_AUTOEN) {
    335  1.1     fvdl 		if ((bmsr & BMSR_ACOMP) == 0) {
    336  1.1     fvdl 			mii->mii_media_active |= IFM_NONE;
    337  1.1     fvdl 			return;
    338  1.1     fvdl 		}
    339  1.1     fvdl 		switch (pssr & PSSR_SPEED_MASK) {
    340  1.1     fvdl 		case PSSR_SPEED_1000MBPS:
    341  1.1     fvdl 			mii->mii_media_active |= IFM_1000_T;
    342  1.1     fvdl 			gtsr = PHY_READ(sc, MII_100T2SR);
    343  1.1     fvdl 			if (gtsr & GTSR_MS_RES)
    344  1.1     fvdl 				mii->mii_media_active |= IFM_ETH_MASTER;
    345  1.1     fvdl 			break;
    346  1.1     fvdl 
    347  1.1     fvdl 		case PSSR_SPEED_100MBPS:
    348  1.1     fvdl 			mii->mii_media_active |= IFM_100_TX;
    349  1.1     fvdl 			break;
    350  1.1     fvdl 
    351  1.1     fvdl 		case PSSR_SPEED_10MBPS:
    352  1.1     fvdl 			mii->mii_media_active |= IFM_10_T;
    353  1.1     fvdl 			break;
    354  1.1     fvdl 
    355  1.1     fvdl 		default:
    356  1.1     fvdl 			mii->mii_media_active |= IFM_NONE;
    357  1.1     fvdl 			mii->mii_media_status = 0;
    358  1.1     fvdl 			return;
    359  1.1     fvdl 		}
    360  1.1     fvdl 
    361  1.1     fvdl 		if (pssr & PSSR_FULL_DUPLEX)
    362  1.2  thorpej 			mii->mii_media_active |=
    363  1.3  thorpej 			    IFM_FDX | mii_phy_flowstatus(sc);
    364  1.1     fvdl 	} else
    365  1.1     fvdl 		mii->mii_media_active = ife->ifm_media;
    366  1.1     fvdl }
    367  1.1     fvdl 
    368  1.1     fvdl #if 0
    369  1.1     fvdl static void
    370  1.1     fvdl igphy_smartspeed_workaround(struct mii_softc *sc)
    371  1.1     fvdl {
    372  1.1     fvdl 	uint16_t reg, gtsr, gctr;
    373  1.1     fvdl 
    374  1.1     fvdl 	reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
    375  1.1     fvdl 	if (!(reg & BMSR_LINK)) {
    376  1.1     fvdl 		switch (sc->mii_ticks) {
    377  1.1     fvdl 		case 0:
    378  1.1     fvdl 			gtsr = PHY_READ(sc, MII_100T2SR);
    379  1.1     fvdl 			if (!(gtsr & GTSR_MAN_MS_FLT))
    380  1.1     fvdl 				break;
    381  1.1     fvdl 			gtsr = PHY_READ(sc, MII_100T2SR);
    382  1.1     fvdl 			if (gtsr & GTSR_MAN_MS_FLT) {
    383  1.1     fvdl 				gtcr = PHY_READ(sc, MII_100T2CR);
    384  1.1     fvdl 				if (gtcr & GTCR_MAN_MS) {
    385  1.1     fvdl 					gtcr &= ~GTCR_MAN_MS;
    386  1.1     fvdl 					PHY_WRITE(sc, MII_100T2CR,
    387  1.1     fvdl 					    gtcr);
    388  1.1     fvdl 				}
    389  1.1     fvdl 				mii_phy_auto(sc, 0);
    390  1.1     fvdl 				sc->mii_ticks++;
    391  1.1     fvdl 			}
    392  1.1     fvdl 			break;
    393  1.1     fvdl 		case IGPHY_TICK_DOWNSHIFT:
    394  1.1     fvdl 			gtcr = PHY_READ(sc, MII_100T2CR);
    395  1.1     fvdl 			gtcr |= GTCR_MAN_MS;
    396  1.1     fvdl 			PHY_WRITE(sc, MII_100T2CR, gtcr);
    397  1.1     fvdl 			mii_phy_auto(sc, 0);
    398  1.1     fvdl 			break;
    399  1.1     fvdl 		default:
    400  1.1     fvdl 			break;
    401  1.1     fvdl 		}
    402  1.1     fvdl 	}
    403  1.1     fvdl }
    404  1.1     fvdl #endif
    405