1 /* $NetBSD: nsphy.c,v 1.18 1999/07/14 23:57:36 thorpej Exp $ */
4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
39 * $FreeBSD: src/sys/dev/mii/nsphy.c,v 1.2.2.5 2001/06/08 19:58:33 semenu Exp $
40 * $DragonFly: src/sys/dev/netif/mii_layer/nsphy.c,v 1.10 2006/12/22 23:26:20 swildner Exp $
44 * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution.
54 * 3. All advertising materials mentioning features or use of this software
55 * must display the following acknowledgement:
56 * This product includes software developed by Manuel Bouyer.
57 * 4. The name of the author may not be used to endorse or promote products
58 * derived from this software without specific prior written permission.
60 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
61 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
62 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
63 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
64 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
65 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
66 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
67 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
68 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
69 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 * driver for National Semiconductor's DP83840A ethernet 10/100 PHY
74 * Data Sheet available from www.national.com
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/kernel.h>
80 #include <sys/socket.h>
81 #include <sys/errno.h>
82 #include <sys/module.h>
86 #include <net/if_media.h>
94 #include "miibus_if.h"
96 static int nsphy_probe (device_t
);
97 static int nsphy_attach (device_t
);
99 static device_method_t nsphy_methods
[] = {
100 /* device interface */
101 DEVMETHOD(device_probe
, nsphy_probe
),
102 DEVMETHOD(device_attach
, nsphy_attach
),
103 DEVMETHOD(device_detach
, ukphy_detach
),
104 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
108 static const struct mii_phydesc nsphys
[] = {
109 MII_PHYDESC(NATSEMI
, DP83840
),
113 static devclass_t nsphy_devclass
;
115 static driver_t nsphy_driver
= {
118 sizeof(struct mii_softc
)
121 DRIVER_MODULE(nsphy
, miibus
, nsphy_driver
, nsphy_devclass
, 0, 0);
123 static int nsphy_service(struct mii_softc
*, struct mii_data
*, int);
124 static void nsphy_status(struct mii_softc
*);
125 static void nsphy_reset(struct mii_softc
*);
128 nsphy_probe(device_t dev
)
130 struct mii_attach_args
*ma
= device_get_ivars(dev
);
131 const struct mii_phydesc
*mpd
;
133 mpd
= mii_phy_match(ma
, nsphys
);
135 device_set_desc(dev
, mpd
->mpd_name
);
142 nsphy_attach(device_t dev
)
144 struct mii_softc
*sc
;
145 struct mii_attach_args
*ma
;
146 struct mii_data
*mii
;
148 sc
= device_get_softc(dev
);
149 ma
= device_get_ivars(dev
);
150 mii_softc_init(sc
, ma
);
151 sc
->mii_dev
= device_get_parent(dev
);
152 mii
= device_get_softc(sc
->mii_dev
);
153 LIST_INSERT_HEAD(&mii
->mii_phys
, sc
, mii_list
);
155 sc
->mii_inst
= mii
->mii_instance
;
156 sc
->mii_service
= nsphy_service
;
157 sc
->mii_reset
= nsphy_reset
;
162 * i82557 wedges if all of its PHYs are isolated!
164 if (strcmp(device_get_name(device_get_parent(sc
->mii_dev
)),
165 "fxp") == 0 && mii
->mii_instance
== 0)
168 sc
->mii_flags
|= MIIF_NOISOLATE
;
171 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
174 /* Can't do this on the i82557! */
175 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_NONE
, 0, sc
->mii_inst
),
178 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_100_TX
, IFM_LOOP
, sc
->mii_inst
),
183 sc
->mii_capabilities
= PHY_READ(sc
, MII_BMSR
) & ma
->mii_capmask
;
184 device_printf(dev
, " ");
185 if ((sc
->mii_capabilities
& BMSR_MEDIAMASK
) == 0)
186 kprintf("no media present");
188 mii_phy_add_media(sc
);
192 MIIBUS_MEDIAINIT(sc
->mii_dev
);
197 nsphy_service(struct mii_softc
*sc
, struct mii_data
*mii
, int cmd
)
199 struct ifmedia_entry
*ife
= mii
->mii_media
.ifm_cur
;
205 * If we're not polling our PHY instance, just return.
207 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
)
213 * If the media indicates a different PHY instance,
216 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
) {
217 reg
= PHY_READ(sc
, MII_BMCR
);
218 PHY_WRITE(sc
, MII_BMCR
, reg
| BMCR_ISO
);
223 * If the interface is not up, don't do anything.
225 if ((mii
->mii_ifp
->if_flags
& IFF_UP
) == 0)
228 reg
= PHY_READ(sc
, MII_NSPHY_PCR
);
231 * Set up the PCR to use LED4 to indicate full-duplex
232 * in both 10baseT and 100baseTX modes.
237 * Make sure Carrier Intgrity Monitor function is
238 * disabled (normal for Node operation, but sometimes
244 * Make sure "force link good" is set to normal mode.
245 * It's only intended for debugging.
250 * Mystery bits which are supposedly `reserved',
251 * but we seem to need to set them when the PHY
252 * is connected to some interfaces:
254 * 0x0400 is needed for fxp
255 * (Intel EtherExpress Pro 10+/100B, 82557 chip)
256 * (nsphy with a DP83840 chip)
257 * 0x0100 may be needed for some other card
259 reg
|= PCR_CONGCTRL
| PCR_TXREADYSEL
;
261 if (strcmp(device_get_name(device_get_parent(sc
->mii_dev
)),
263 PHY_WRITE(sc
, MII_NSPHY_PCR
, reg
);
265 mii_phy_set_media(sc
);
270 * If we're not currently selected, just return.
272 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
)
275 if (mii_phy_tick(sc
) == EJUSTRETURN
)
280 /* Update the media status. */
283 /* Callback if something changed. */
284 mii_phy_update(sc
, cmd
);
289 nsphy_status(struct mii_softc
*sc
)
291 struct mii_data
*mii
= sc
->mii_pdata
;
292 int bmsr
, bmcr
, par
, anlpar
;
294 mii
->mii_media_status
= IFM_AVALID
;
295 mii
->mii_media_active
= IFM_ETHER
;
297 bmsr
= PHY_READ(sc
, MII_BMSR
) |
298 PHY_READ(sc
, MII_BMSR
);
299 if (bmsr
& BMSR_LINK
)
300 mii
->mii_media_status
|= IFM_ACTIVE
;
302 bmcr
= PHY_READ(sc
, MII_BMCR
);
303 if (bmcr
& BMCR_ISO
) {
304 mii
->mii_media_active
|= IFM_NONE
;
305 mii
->mii_media_status
= 0;
309 if (bmcr
& BMCR_LOOP
)
310 mii
->mii_media_active
|= IFM_LOOP
;
312 if (bmcr
& BMCR_AUTOEN
) {
314 * The PAR status bits are only valid of autonegotiation
315 * has completed (or it's disabled).
317 if ((bmsr
& BMSR_ACOMP
) == 0) {
318 /* Erg, still trying, I guess... */
319 mii
->mii_media_active
|= IFM_NONE
;
324 * Argh. The PAR doesn't seem to indicate duplex mode
325 * properly! Determine media based on link partner's
326 * advertised capabilities.
328 if (PHY_READ(sc
, MII_ANER
) & ANER_LPAN
) {
329 anlpar
= PHY_READ(sc
, MII_ANAR
) &
330 PHY_READ(sc
, MII_ANLPAR
);
331 if (anlpar
& ANLPAR_T4
)
332 mii
->mii_media_active
|= IFM_100_T4
;
333 else if (anlpar
& ANLPAR_TX_FD
)
334 mii
->mii_media_active
|= IFM_100_TX
|IFM_FDX
;
335 else if (anlpar
& ANLPAR_TX
)
336 mii
->mii_media_active
|= IFM_100_TX
;
337 else if (anlpar
& ANLPAR_10_FD
)
338 mii
->mii_media_active
|= IFM_10_T
|IFM_FDX
;
339 else if (anlpar
& ANLPAR_10
)
340 mii
->mii_media_active
|= IFM_10_T
;
342 mii
->mii_media_active
|= IFM_NONE
;
347 * Link partner is not capable of autonegotiation.
348 * We will never be in full-duplex mode if this is
349 * the case, so reading the PAR is OK.
351 par
= PHY_READ(sc
, MII_NSPHY_PAR
);
353 mii
->mii_media_active
|= IFM_10_T
;
355 mii
->mii_media_active
|= IFM_100_TX
;
358 mii
->mii_media_active
|= IFM_FDX
;
361 mii
->mii_media_active
|= mii
->mii_media
.ifm_cur
->ifm_media
;
365 nsphy_reset(struct mii_softc
*sc
)
370 anar
= PHY_READ(sc
, MII_ANAR
);
371 anar
|= BMSR_MEDIA_TO_ANAR(PHY_READ(sc
, MII_BMSR
));
372 PHY_WRITE(sc
, MII_ANAR
, anar
);