1 /* $NetBSD: mii_physubr.c,v 1.49 2006/03/29 07:05:24 thorpej Exp $ */
4 * Copyright (c) 1998, 1999, 2000, 2001 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/mii_physubr.c,v 1.2.2.1 2000/12/12 19:29:14 wpaul Exp $
40 * $DragonFly: src/sys/dev/netif/mii_layer/mii_physubr.c,v 1.14 2007/03/24 05:57:49 sephe Exp $
44 * Subroutines common to all PHYs.
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/socket.h>
51 #include <sys/errno.h>
52 #include <sys/module.h>
54 #include <sys/thread2.h>
57 #include <net/if_media.h>
62 #include "miibus_if.h"
64 const struct mii_media mii_media_table
[MII_NMEDIA
] = {
65 [MII_MEDIA_NONE
] = { .mm_bmcr
= BMCR_ISO
,
69 [MII_MEDIA_10_T
] = { .mm_bmcr
= BMCR_S10
,
70 .mm_anar
= ANAR_CSMA
| ANAR_10
,
73 [MII_MEDIA_10_T_FDX
] = { .mm_bmcr
= BMCR_S10
| BMCR_FDX
,
74 .mm_anar
= ANAR_CSMA
| ANAR_10_FD
,
77 [MII_MEDIA_100_T4
] = { .mm_bmcr
= BMCR_S100
,
78 .mm_anar
= ANAR_CSMA
| ANAR_T4
,
81 [MII_MEDIA_100_TX
] = { .mm_bmcr
= BMCR_S100
,
82 .mm_anar
= ANAR_CSMA
| ANAR_TX
,
85 [MII_MEDIA_100_TX_FDX
] = { .mm_bmcr
= BMCR_S100
| BMCR_FDX
,
86 .mm_anar
= ANAR_CSMA
| ANAR_TX_FD
,
89 [MII_MEDIA_1000_X
] = { .mm_bmcr
= BMCR_S1000
,
93 [MII_MEDIA_1000_X_FDX
] = { .mm_bmcr
= BMCR_S1000
| BMCR_FDX
,
97 [MII_MEDIA_1000_T
] = { .mm_bmcr
= BMCR_S1000
,
99 .mm_gtcr
= GTCR_ADV_1000THDX
},
101 [MII_MEDIA_1000_T_FDX
] = { .mm_bmcr
= BMCR_S1000
,
102 .mm_anar
= ANAR_CSMA
,
103 .mm_gtcr
= GTCR_ADV_1000TFDX
}
107 mii_softc_init(struct mii_softc
*mii
, struct mii_attach_args
*ma
)
109 callout_init(&mii
->mii_auto_ch
);
110 mii
->mii_phy
= ma
->mii_phyno
;
111 mii
->mii_flags
|= ma
->mii_flags
;
112 mii
->mii_model
= MII_MODEL(ma
->mii_id2
);
113 mii
->mii_rev
= MII_REV(ma
->mii_id2
);
115 if (mii
->mii_reset
== NULL
)
116 mii
->mii_reset
= mii_phy_reset
;
117 if (mii
->mii_anegticks
== 0)
118 mii
->mii_anegticks
= MII_ANEGTICKS
;
122 mii_phy_auto(struct mii_softc
*sc
, int waitfor
)
126 if ((sc
->mii_flags
& MIIF_DOINGAUTO
) == 0) {
128 * Check for 1000BASE-X. Autonegotiation is a bit
129 * different on such devices.
131 if (sc
->mii_flags
& MIIF_IS_1000X
) {
134 if (sc
->mii_extcapabilities
& EXTSR_1000XFDX
)
136 if (sc
->mii_extcapabilities
& EXTSR_1000XHDX
)
139 if (sc
->mii_flags
& MIIF_DOPAUSE
) {
140 /* XXX Asymmetric vs. symmetric? */
141 anar
|= ANLPAR_X_PAUSE_TOWARDS
;
144 PHY_WRITE(sc
, MII_ANAR
, anar
);
148 anar
= BMSR_MEDIA_TO_ANAR(sc
->mii_capabilities
) |
150 if (sc
->mii_flags
& MIIF_DOPAUSE
) {
152 /* XXX Only 1000BASE-T has PAUSE_ASYM? */
153 if ((sc
->mii_flags
& MIIF_HAVE_GTCR
) &&
154 (sc
->mii_extcapabilities
&
155 (EXTSR_1000THDX
|EXTSR_1000TFDX
)))
156 anar
|= ANAR_X_PAUSE_ASYM
;
158 PHY_WRITE(sc
, MII_ANAR
, anar
);
159 if (sc
->mii_flags
& MIIF_HAVE_GTCR
) {
162 if (sc
->mii_extcapabilities
& EXTSR_1000TFDX
)
163 gtcr
|= GTCR_ADV_1000TFDX
;
164 if (sc
->mii_extcapabilities
& EXTSR_1000THDX
)
165 gtcr
|= GTCR_ADV_1000THDX
;
167 PHY_WRITE(sc
, MII_100T2CR
, gtcr
);
170 PHY_WRITE(sc
, MII_BMCR
, BMCR_AUTOEN
| BMCR_STARTNEG
);
174 /* Wait 500ms for it to complete. */
175 for (i
= 0; i
< 500; i
++) {
176 if (PHY_READ(sc
, MII_BMSR
) & BMSR_ACOMP
)
182 * Don't need to worry about clearing MIIF_DOINGAUTO.
183 * If that's set, a timeout is pending, and it will
190 * Just let it finish asynchronously. This is for the benefit of
191 * the tick handler driving autonegotiation. Don't want 500ms
192 * delays all the time while the system is running!
194 if (sc
->mii_flags
& MIIF_AUTOTSLEEP
) {
195 sc
->mii_flags
|= MIIF_DOINGAUTO
;
196 tsleep(&sc
->mii_flags
, 0, "miiaut", hz
>> 1);
197 mii_phy_auto_timeout(sc
);
198 } else if ((sc
->mii_flags
& MIIF_DOINGAUTO
) == 0) {
199 sc
->mii_flags
|= MIIF_DOINGAUTO
;
200 callout_reset(&sc
->mii_auto_ch
, hz
>> 1,
201 mii_phy_auto_timeout
, sc
);
203 return (EJUSTRETURN
);
207 mii_phy_auto_stop(struct mii_softc
*sc
)
209 if (sc
->mii_flags
& MIIF_DOINGAUTO
) {
210 sc
->mii_flags
&= ~MIIF_DOINGAUTO
;
211 callout_stop(&sc
->mii_auto_ch
);
215 /* XXX should use serializer */
217 mii_phy_auto_timeout(void *arg
)
219 struct mii_softc
*sc
= arg
;
223 sc
->mii_flags
&= ~MIIF_DOINGAUTO
;
225 /* Update the media status. */
226 sc
->mii_service(sc
, sc
->mii_pdata
, MII_POLLSTAT
);
232 mii_phy_reset(struct mii_softc
*sc
)
236 if (sc
->mii_flags
& MIIF_NOISOLATE
)
239 reg
= BMCR_RESET
| BMCR_ISO
;
240 PHY_WRITE(sc
, MII_BMCR
, reg
);
243 * It is best to allow a little time for the reset to settle
244 * in before we start polling the BMCR again. Notably, the
245 * DP83840A manual states that there should be a 500us delay
246 * between asserting software reset and attempting MII serial
247 * operations. Also, a DP83815 can get into a bad state on
248 * cable removal and reinsertion if we do not delay here.
252 /* Wait 100ms for it to complete. */
253 for (i
= 0; i
< 100; i
++) {
254 reg
= PHY_READ(sc
, MII_BMCR
);
255 if ((reg
& BMCR_RESET
) == 0)
260 if (sc
->mii_inst
!= 0 && ((sc
->mii_flags
& MIIF_NOISOLATE
) == 0))
261 PHY_WRITE(sc
, MII_BMCR
, reg
| BMCR_ISO
);
265 * Initialize generic PHY media based on BMSR, called when a PHY is
266 * attached. We expect to be set up to print a comma-separated list
267 * of media names. Does not print a newline.
270 mii_phy_add_media(struct mii_softc
*sc
)
272 struct mii_data
*mii
= sc
->mii_pdata
;
273 const char *sep
= "";
276 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
277 #define PRINT(s) kprintf("%s%s", sep, s); sep = ", "
279 if ((sc
->mii_flags
& MIIF_NOISOLATE
) == 0)
280 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_NONE
, 0, sc
->mii_inst
),
284 * There are different interpretations for the bits in
285 * HomePNA PHYs. And there is really only one media type
288 if (sc
->mii_flags
& MIIF_IS_HPNA
) {
289 if (sc
->mii_capabilities
& BMSR_10THDX
) {
290 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_HPNA_1
, 0,
298 if (sc
->mii_capabilities
& BMSR_10THDX
) {
299 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_10_T
, 0, sc
->mii_inst
),
303 if (sc
->mii_capabilities
& BMSR_10TFDX
) {
304 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_10_T
, IFM_FDX
, sc
->mii_inst
),
306 PRINT("10baseT-FDX");
309 if (sc
->mii_capabilities
& BMSR_100TXHDX
) {
310 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_100_TX
, 0, sc
->mii_inst
),
314 if (sc
->mii_capabilities
& BMSR_100TXFDX
) {
315 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_100_TX
, IFM_FDX
, sc
->mii_inst
),
316 MII_MEDIA_100_TX_FDX
);
317 PRINT("100baseTX-FDX");
320 if (sc
->mii_capabilities
& BMSR_100T4
) {
321 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_100_T4
, 0, sc
->mii_inst
),
326 if (sc
->mii_extcapabilities
& EXTSR_MEDIAMASK
) {
328 * XXX Right now only handle 1000SX and 1000TX. Need
329 * XXX to handle 1000LX and 1000CX some how.
331 * Note since it can take 5 seconds to auto-negotiate
332 * a gigabit link, we make anegticks 10 seconds for
333 * all the gigabit media types.
335 if (sc
->mii_extcapabilities
& EXTSR_1000XHDX
) {
336 sc
->mii_anegticks
= MII_ANEGTICKS_GIGE
;
337 sc
->mii_flags
|= MIIF_IS_1000X
;
338 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_SX
, 0,
339 sc
->mii_inst
), MII_MEDIA_1000_X
);
342 if (sc
->mii_extcapabilities
& EXTSR_1000XFDX
) {
343 sc
->mii_anegticks
= MII_ANEGTICKS_GIGE
;
344 sc
->mii_flags
|= MIIF_IS_1000X
;
345 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_SX
, IFM_FDX
,
346 sc
->mii_inst
), MII_MEDIA_1000_X_FDX
);
347 PRINT("1000baseSX-FDX");
352 * 1000baseT media needs to be able to manipulate
353 * master/slave mode. We set IFM_ETH_MASTER in
354 * the "don't care mask" and filter it out when
357 * All 1000baseT PHYs have a 1000baseT control register.
359 if (sc
->mii_extcapabilities
& EXTSR_1000THDX
) {
360 sc
->mii_anegticks
= MII_ANEGTICKS_GIGE
;
361 sc
->mii_flags
|= MIIF_HAVE_GTCR
;
362 mii
->mii_media
.ifm_mask
|= IFM_ETH_MASTER
;
363 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_T
, 0,
364 sc
->mii_inst
), MII_MEDIA_1000_T
);
367 if (sc
->mii_extcapabilities
& EXTSR_1000TFDX
) {
368 sc
->mii_anegticks
= MII_ANEGTICKS_GIGE
;
369 sc
->mii_flags
|= MIIF_HAVE_GTCR
;
370 mii
->mii_media
.ifm_mask
|= IFM_ETH_MASTER
;
371 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_T
, IFM_FDX
,
372 sc
->mii_inst
), MII_MEDIA_1000_T_FDX
);
373 PRINT("1000baseT-FDX");
378 if (sc
->mii_capabilities
& BMSR_ANEG
) {
379 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_AUTO
, 0, sc
->mii_inst
),
380 MII_NMEDIA
); /* intentionally invalid index */
385 if (fdx
!= 0 && (sc
->mii_flags
& MIIF_DOPAUSE
))
386 mii
->mii_media
.ifm_mask
|= IFM_ETH_FMASK
;
390 mii_phy_set_media(struct mii_softc
*sc
)
392 struct mii_data
*mii
= sc
->mii_pdata
;
393 struct ifmedia_entry
*ife
= mii
->mii_media
.ifm_cur
;
394 int bmcr
, anar
, gtcr
;
396 if (IFM_SUBTYPE(ife
->ifm_media
) == IFM_AUTO
) {
398 * Force renegotiation if MIIF_DOPAUSE.
400 * XXX This is only necessary because many NICs don't
401 * XXX advertise PAUSE capabilities at boot time. Maybe
402 * XXX we should force this only once?
404 if ((PHY_READ(sc
, MII_BMCR
) & BMCR_AUTOEN
) == 0 ||
405 (sc
->mii_flags
& (MIIF_FORCEANEG
| MIIF_DOPAUSE
)))
411 * Table index is stored in the media entry.
414 KASSERT(ife
->ifm_data
>= 0 && ife
->ifm_data
< MII_NMEDIA
,
415 ("bogus ife->ifm_data (%d)\n", ife
->ifm_data
));
417 anar
= mii_media_table
[ife
->ifm_data
].mm_anar
;
418 bmcr
= mii_media_table
[ife
->ifm_data
].mm_bmcr
;
419 gtcr
= mii_media_table
[ife
->ifm_data
].mm_gtcr
;
421 if (mii
->mii_media
.ifm_media
& IFM_ETH_MASTER
) {
422 switch (IFM_SUBTYPE(ife
->ifm_media
)) {
424 gtcr
|= GTCR_MAN_MS
|GTCR_ADV_MS
;
428 panic("mii_phy_setmedia: MASTER on wrong media");
432 if (mii
->mii_media
.ifm_media
& IFM_FLOW
) {
433 if (sc
->mii_flags
& MIIF_IS_1000X
) {
434 anar
|= ANAR_X_PAUSE_SYM
| ANAR_X_PAUSE_ASYM
;
437 /* XXX Only 1000BASE-T has PAUSE_ASYM? */
438 if ((sc
->mii_flags
& MIIF_HAVE_GTCR
) &&
439 (sc
->mii_extcapabilities
&
440 (EXTSR_1000THDX
| EXTSR_1000TFDX
)))
441 anar
|= ANAR_X_PAUSE_ASYM
;
445 if (ife
->ifm_media
& IFM_LOOP
)
448 PHY_WRITE(sc
, MII_ANAR
, anar
);
449 PHY_WRITE(sc
, MII_BMCR
, bmcr
);
450 if (sc
->mii_flags
& MIIF_HAVE_GTCR
)
451 PHY_WRITE(sc
, MII_100T2CR
, gtcr
);
455 mii_phy_tick(struct mii_softc
*sc
)
457 struct mii_data
*mii
= sc
->mii_pdata
;
458 struct ifmedia_entry
*ife
= mii
->mii_media
.ifm_cur
;
461 /* Just bail now if the interface is down. */
462 if ((mii
->mii_ifp
->if_flags
& IFF_UP
) == 0)
463 return (EJUSTRETURN
);
466 * If we're not doing autonegotiation, we don't need to do
467 * any extra work here. However, we need to check the link
468 * status so we can generate an announcement if the status
471 if (IFM_SUBTYPE(ife
->ifm_media
) != IFM_AUTO
)
474 /* Read the status register twice; BMSR_LINK is latch-low. */
475 reg
= PHY_READ(sc
, MII_BMSR
) | PHY_READ(sc
, MII_BMSR
);
476 if (reg
& BMSR_LINK
) {
484 * Only retry autonegotiation every N seconds.
486 KKASSERT(sc
->mii_anegticks
> 0);
487 if (++sc
->mii_ticks
!= sc
->mii_anegticks
)
488 return (EJUSTRETURN
);
491 sc
->mii_reset(sc
); /* Reset PHY */
493 if (mii_phy_auto(sc
, 0) == EJUSTRETURN
)
494 return (EJUSTRETURN
);
497 * Might need to generate a status message if autonegotiation
504 mii_phy_statusmsg(struct mii_softc
*sc
)
506 struct mii_data
*mii
= sc
->mii_pdata
;
507 struct ifnet
*ifp
= mii
->mii_ifp
;
508 int baudrate
, link_state
, announce
= 0;
510 if (mii
->mii_media_status
& IFM_AVALID
) {
511 if (mii
->mii_media_status
& IFM_ACTIVE
)
512 link_state
= LINK_STATE_UP
;
514 link_state
= LINK_STATE_DOWN
;
516 link_state
= LINK_STATE_UNKNOWN
;
518 baudrate
= ifmedia_baudrate(mii
->mii_media_active
);
520 if (link_state
!= ifp
->if_link_state
) {
521 ifp
->if_link_state
= link_state
;
523 * XXX Right here we'd like to notify protocols
524 * XXX that the link status has changed, so that
525 * XXX e.g. Duplicate Address Detection can restart.
530 if (baudrate
!= ifp
->if_baudrate
) {
531 ifp
->if_baudrate
= baudrate
;
539 mii_phy_update(struct mii_softc
*sc
, int cmd
)
541 struct mii_data
*mii
= sc
->mii_pdata
;
542 struct ifnet
*ifp
= mii
->mii_ifp
;
545 if (sc
->mii_media_active
!= mii
->mii_media_active
||
546 sc
->mii_media_status
!= mii
->mii_media_status
||
547 cmd
== MII_MEDIACHG
) {
548 announce
= mii_phy_statusmsg(sc
);
549 MIIBUS_STATCHG(sc
->mii_dev
);
550 sc
->mii_media_active
= mii
->mii_media_active
;
551 sc
->mii_media_status
= mii
->mii_media_status
;
555 if_link_state_change(ifp
);
562 * Return the flow control status flag from MII_ANAR & MII_ANLPAR.
565 mii_phy_flowstatus(struct mii_softc
*sc
)
569 if ((sc
->mii_flags
& MIIF_DOPAUSE
) == 0)
572 anar
= PHY_READ(sc
, MII_ANAR
);
573 anlpar
= PHY_READ(sc
, MII_ANLPAR
);
575 if ((anar
& ANAR_X_PAUSE_SYM
) & (anlpar
& ANLPAR_X_PAUSE_SYM
))
576 return (IFM_FLOW
| IFM_ETH_TXPAUSE
| IFM_ETH_RXPAUSE
);
578 if ((anar
& ANAR_X_PAUSE_SYM
) == 0) {
579 if ((anar
& ANAR_X_PAUSE_ASYM
) &&
580 ((anlpar
& ANLPAR_X_PAUSE_TOWARDS
) ==
581 ANLPAR_X_PAUSE_TOWARDS
))
582 return (IFM_FLOW
| IFM_ETH_TXPAUSE
);
587 if ((anar
& ANAR_X_PAUSE_ASYM
) == 0) {
588 if (anlpar
& ANLPAR_X_PAUSE_SYM
)
589 return (IFM_FLOW
| IFM_ETH_TXPAUSE
| IFM_ETH_RXPAUSE
);
594 switch (anlpar
& ANLPAR_X_PAUSE_TOWARDS
) {
595 case ANLPAR_X_PAUSE_NONE
:
598 case ANLPAR_X_PAUSE_ASYM
:
599 return (IFM_FLOW
| IFM_ETH_RXPAUSE
);
602 return (IFM_FLOW
| IFM_ETH_RXPAUSE
| IFM_ETH_TXPAUSE
);
607 const struct mii_phydesc
*
608 mii_phy_match(const struct mii_attach_args
*ma
, const struct mii_phydesc
*mpd
)
610 for (; mpd
->mpd_name
!= NULL
; mpd
++) {
611 if (MII_OUI(ma
->mii_id1
, ma
->mii_id2
) == mpd
->mpd_oui
&&
612 MII_MODEL(ma
->mii_id2
) == mpd
->mpd_model
)