150120Swpaul/*	$NetBSD: exphy.c,v 1.16 1999/04/23 04:24:32 thorpej Exp $	*/
250120Swpaul
350120Swpaul/*-
450120Swpaul * Copyright (c) 1998, 1999 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
33139749Simp/*-
3450120Swpaul * Copyright (c) 1997 Manuel Bouyer.  All rights reserved.
3550120Swpaul *
3650120Swpaul * Redistribution and use in source and binary forms, with or without
3750120Swpaul * modification, are permitted provided that the following conditions
3850120Swpaul * are met:
3950120Swpaul * 1. Redistributions of source code must retain the above copyright
4050120Swpaul *    notice, this list of conditions and the following disclaimer.
4150120Swpaul * 2. Redistributions in binary form must reproduce the above copyright
4250120Swpaul *    notice, this list of conditions and the following disclaimer in the
4350120Swpaul *    documentation and/or other materials provided with the distribution.
4450120Swpaul *
4550120Swpaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
4650120Swpaul * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
4750120Swpaul * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4850120Swpaul * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
4950120Swpaul * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
5050120Swpaul * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5150120Swpaul * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5250120Swpaul * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5350120Swpaul * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5450120Swpaul * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5550120Swpaul */
5650120Swpaul
57129844Smarius#include <sys/cdefs.h>
58129844Smarius__FBSDID("$FreeBSD$");
59129844Smarius
6050120Swpaul/*
6150120Swpaul * driver for 3Com internal PHYs
6250120Swpaul */
6350120Swpaul
6450120Swpaul#include <sys/param.h>
6550120Swpaul#include <sys/systm.h>
6650120Swpaul#include <sys/kernel.h>
6750120Swpaul#include <sys/socket.h>
6850120Swpaul#include <sys/module.h>
6950120Swpaul#include <sys/bus.h>
7050120Swpaul
7150120Swpaul#include <net/if.h>
7250120Swpaul#include <net/if_media.h>
7350120Swpaul
7450120Swpaul#include <dev/mii/mii.h>
7550120Swpaul#include <dev/mii/miivar.h>
76109514Sobrien#include "miidevs.h"
7750120Swpaul
7850120Swpaul#include "miibus_if.h"
7950120Swpaul
80226154Smariusstatic int xlphy_probe(device_t);
81226154Smariusstatic int xlphy_attach(device_t);
8250120Swpaul
83226154Smariusstatic device_method_t xlphy_methods[] = {
8450120Swpaul	/* device interface */
85226154Smarius	DEVMETHOD(device_probe,		xlphy_probe),
86226154Smarius	DEVMETHOD(device_attach,	xlphy_attach),
8795722Sphk	DEVMETHOD(device_detach,	mii_phy_detach),
8850120Swpaul	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
89229093Shselasky	DEVMETHOD_END
9050120Swpaul};
9150120Swpaul
92226154Smariusstatic devclass_t xlphy_devclass;
9350120Swpaul
94226154Smariusstatic driver_t xlphy_driver = {
9550120Swpaul	"xlphy",
96226154Smarius	xlphy_methods,
9750120Swpaul	sizeof(struct mii_softc)
9850120Swpaul};
9950120Swpaul
100226154SmariusDRIVER_MODULE(xlphy, miibus, xlphy_driver, xlphy_devclass, 0, 0);
10150120Swpaul
102226154Smariusstatic int	xlphy_service(struct mii_softc *, struct mii_data *, int);
103226154Smariusstatic void	xlphy_reset(struct mii_softc *);
10450120Swpaul
105165988Smarius/*
106165988Smarius * Some 3Com internal PHYs report zero for OUI and model, others use
107165988Smarius * actual values.
108165988Smarius * Note that the 3Com internal PHYs having OUI 0x105a and model 0 are
109165988Smarius * handled fine by ukphy(4); they can be isolated and don't require
110165988Smarius * special treatment after reset.
111165988Smarius */
112226154Smariusstatic const struct mii_phydesc xlphys[] = {
113165988Smarius	{ 0, 0, "3Com internal media interface" },
114221407Smarius	MII_PHY_DESC(xxBROADCOM, 3C905C),
115165988Smarius	MII_PHY_END
116165988Smarius};
117221407Smarius
118226154Smariusstatic const struct mii_phy_funcs xlphy_funcs = {
119226154Smarius	xlphy_service,
120221407Smarius	ukphy_status,
121226154Smarius	xlphy_reset
122221407Smarius};
123221407Smarius
124105135Salfredstatic int
125226154Smariusxlphy_probe(device_t dev)
12650120Swpaul{
12750120Swpaul
128165988Smarius	if (strcmp(device_get_name(device_get_parent(device_get_parent(dev))),
129165988Smarius	    "xl") == 0)
130226154Smarius		return (mii_phy_dev_probe(dev, xlphys, BUS_PROBE_DEFAULT));
131165988Smarius	return (ENXIO);
13250120Swpaul}
13350120Swpaul
134105135Salfredstatic int
135226154Smariusxlphy_attach(device_t dev)
13650120Swpaul{
13750120Swpaul
138213364Smarius	/*
139213364Smarius	 * The 3Com PHY can never be isolated.
140213364Smarius	 */
141221407Smarius	mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE,
142226154Smarius	    &xlphy_funcs, 1);
143165988Smarius	return (0);
14450120Swpaul}
14550120Swpaul
14684145Sjlemonstatic int
147226154Smariusxlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
14850120Swpaul{
14950120Swpaul
15050120Swpaul	switch (cmd) {
15150120Swpaul	case MII_POLLSTAT:
15250120Swpaul		break;
15350120Swpaul
15450120Swpaul	case MII_MEDIACHG:
15550120Swpaul		/*
15650120Swpaul		 * If the interface is not up, don't do anything.
15750120Swpaul		 */
15850120Swpaul		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
15950120Swpaul			break;
16050120Swpaul
16195723Sphk		mii_phy_setmedia(sc);
16250120Swpaul		break;
16350120Swpaul
16450120Swpaul	case MII_TICK:
16550120Swpaul		/*
16684145Sjlemon		 * Is the interface even up?
16750120Swpaul		 */
16884145Sjlemon		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
16950120Swpaul			return (0);
17050120Swpaul
17150120Swpaul		/*
17250120Swpaul		 * The 3Com PHY's autonegotiation doesn't need to be
17350120Swpaul		 * kicked; it continues in the background.
17450120Swpaul		 */
17550120Swpaul		break;
17650120Swpaul	}
17750120Swpaul
17850120Swpaul	/* Update the media status. */
179221407Smarius	PHY_STATUS(sc);
18050120Swpaul
18150120Swpaul	/* Callback if something changed. */
18284145Sjlemon	mii_phy_update(sc, cmd);
18350120Swpaul	return (0);
18450120Swpaul}
18550120Swpaul
18684145Sjlemonstatic void
187226154Smariusxlphy_reset(struct mii_softc *sc)
18850120Swpaul{
18950120Swpaul
19050120Swpaul	mii_phy_reset(sc);
19150120Swpaul
19250120Swpaul	/*
19350120Swpaul	 * XXX 3Com PHY doesn't set the BMCR properly after
19450120Swpaul	 * XXX reset, which breaks autonegotiation.
19550120Swpaul	 */
19650120Swpaul	PHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_AUTOEN|BMCR_FDX);
19750120Swpaul}
198