1 /* $NetBSD: mii_physubr.c,v 1.5 1999/08/03 19:41:49 drochner 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.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD: src/sys/dev/mii/mii_physubr.c,v 1.22.2.2 2006/07/29 08:30:12 oleg Exp $");
37 * Subroutines common to all PHYs.
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/socket.h>
44 #include <sys/errno.h>
45 #include <sys/module.h>
49 #include <net/if_media.h>
51 #include <dev/mii/mii.h>
52 #include <dev/mii/miivar.h>
54 #include "miibus_if.h"
57 * Media to register setting conversion table. Order matters.
59 static const struct mii_media mii_media_table
[MII_NMEDIA
] = {
61 { BMCR_ISO
, ANAR_CSMA
,
65 { BMCR_S10
, ANAR_CSMA
|ANAR_10
,
69 { BMCR_S10
|BMCR_FDX
, ANAR_CSMA
|ANAR_10_FD
,
73 { BMCR_S100
, ANAR_CSMA
|ANAR_T4
,
77 { BMCR_S100
, ANAR_CSMA
|ANAR_TX
,
81 { BMCR_S100
|BMCR_FDX
, ANAR_CSMA
|ANAR_TX_FD
,
85 { BMCR_S1000
, ANAR_CSMA
,
89 { BMCR_S1000
|BMCR_FDX
, ANAR_CSMA
,
93 { BMCR_S1000
, ANAR_CSMA
,
97 { BMCR_S1000
, ANAR_CSMA
,
102 mii_phy_setmedia(struct mii_softc
*sc
)
104 struct mii_data
*mii
= sc
->mii_pdata
;
105 struct ifmedia_entry
*ife
= mii
->mii_media
.ifm_cur
;
106 int bmcr
, anar
, gtcr
;
108 if (IFM_SUBTYPE(ife
->ifm_media
) == IFM_AUTO
) {
110 * Force renegotiation if MIIF_DOPAUSE or MIIF_FORCEANEG.
111 * The former is necessary as we might switch from flow-
112 * control advertisement being off to on or vice versa.
114 if ((PHY_READ(sc
, MII_BMCR
) & BMCR_AUTOEN
) == 0 ||
115 (sc
->mii_flags
& (MIIF_DOPAUSE
| MIIF_FORCEANEG
)) != 0)
116 (void)mii_phy_auto(sc
);
121 * Table index is stored in the media entry.
124 KASSERT(ife
->ifm_data
>=0 && ife
->ifm_data
< MII_NMEDIA
,
125 ("invalid ife->ifm_data (0x%x) in mii_phy_setmedia",
128 anar
= mii_media_table
[ife
->ifm_data
].mm_anar
;
129 bmcr
= mii_media_table
[ife
->ifm_data
].mm_bmcr
;
130 gtcr
= mii_media_table
[ife
->ifm_data
].mm_gtcr
;
132 if (IFM_SUBTYPE(ife
->ifm_media
) == IFM_1000_T
) {
134 if ((ife
->ifm_media
& IFM_ETH_MASTER
) != 0)
138 if ((ife
->ifm_media
& IFM_FDX
) != 0 &&
139 ((ife
->ifm_media
& IFM_FLOW
) != 0 ||
140 (sc
->mii_flags
& MIIF_FORCEPAUSE
) != 0)) {
141 if ((sc
->mii_flags
& MIIF_IS_1000X
) != 0)
142 anar
|= ANAR_X_PAUSE_TOWARDS
;
145 /* XXX Only 1000BASE-T has PAUSE_ASYM? */
146 if ((sc
->mii_flags
& MIIF_HAVE_GTCR
) != 0 &&
147 (sc
->mii_extcapabilities
&
148 (EXTSR_1000THDX
| EXTSR_1000TFDX
)) != 0)
149 anar
|= ANAR_X_PAUSE_ASYM
;
153 PHY_WRITE(sc
, MII_ANAR
, anar
);
154 PHY_WRITE(sc
, MII_BMCR
, bmcr
);
155 if ((sc
->mii_flags
& MIIF_HAVE_GTCR
) != 0)
156 PHY_WRITE(sc
, MII_100T2CR
, gtcr
);
160 mii_phy_auto(struct mii_softc
*sc
)
162 struct ifmedia_entry
*ife
= sc
->mii_pdata
->mii_media
.ifm_cur
;
166 * Check for 1000BASE-X. Autonegotiation is a bit
167 * different on such devices.
169 if ((sc
->mii_flags
& MIIF_IS_1000X
) != 0) {
171 if ((sc
->mii_extcapabilities
& EXTSR_1000XFDX
) != 0)
173 if ((sc
->mii_extcapabilities
& EXTSR_1000XHDX
) != 0)
176 if ((ife
->ifm_media
& IFM_FLOW
) != 0 ||
177 (sc
->mii_flags
& MIIF_FORCEPAUSE
) != 0)
178 anar
|= ANAR_X_PAUSE_TOWARDS
;
179 PHY_WRITE(sc
, MII_ANAR
, anar
);
181 anar
= BMSR_MEDIA_TO_ANAR(sc
->mii_capabilities
) |
183 if ((ife
->ifm_media
& IFM_FLOW
) != 0 ||
184 (sc
->mii_flags
& MIIF_FORCEPAUSE
) != 0) {
185 if ((sc
->mii_capabilities
&
186 (BMSR_10TFDX
| BMSR_100TXFDX
)) != 0)
188 /* XXX Only 1000BASE-T has PAUSE_ASYM? */
189 if (((sc
->mii_flags
& MIIF_HAVE_GTCR
) != 0) &&
190 (sc
->mii_extcapabilities
&
191 (EXTSR_1000THDX
| EXTSR_1000TFDX
)) != 0)
192 anar
|= ANAR_X_PAUSE_ASYM
;
194 PHY_WRITE(sc
, MII_ANAR
, anar
);
195 if ((sc
->mii_flags
& MIIF_HAVE_GTCR
) != 0) {
197 if ((sc
->mii_extcapabilities
& EXTSR_1000TFDX
) != 0)
198 gtcr
|= GTCR_ADV_1000TFDX
;
199 if ((sc
->mii_extcapabilities
& EXTSR_1000THDX
) != 0)
200 gtcr
|= GTCR_ADV_1000THDX
;
201 PHY_WRITE(sc
, MII_100T2CR
, gtcr
);
204 PHY_WRITE(sc
, MII_BMCR
, BMCR_AUTOEN
| BMCR_STARTNEG
);
205 return (EJUSTRETURN
);
209 mii_phy_tick(struct mii_softc
*sc
)
211 struct ifmedia_entry
*ife
= sc
->mii_pdata
->mii_media
.ifm_cur
;
212 struct ifnet
*ifp
= sc
->mii_pdata
->mii_ifp
;
215 /* Just bail now if the interface is down. */
216 if ((ifp
->if_flags
& IFF_UP
) == 0)
217 return (EJUSTRETURN
);
220 * If we're not doing autonegotiation, we don't need to do
221 * any extra work here. However, we need to check the link
222 * status so we can generate an announcement if the status
225 if (IFM_SUBTYPE(ife
->ifm_media
) != IFM_AUTO
) {
226 sc
->mii_ticks
= 0; /* reset autonegotiation timer. */
230 /* Read the status register twice; BMSR_LINK is latch-low. */
231 reg
= PHY_READ(sc
, MII_BMSR
) | PHY_READ(sc
, MII_BMSR
);
232 if ((reg
& BMSR_LINK
) != 0) {
233 sc
->mii_ticks
= 0; /* reset autonegotiation timer. */
238 /* Announce link loss right after it happens */
239 if (sc
->mii_ticks
++ == 0)
242 /* XXX: use default value if phy driver did not set mii_anegticks */
243 if (sc
->mii_anegticks
== 0)
244 sc
->mii_anegticks
= MII_ANEGTICKS_GIGE
;
246 /* Only retry autonegotiation every mii_anegticks ticks. */
247 if (sc
->mii_ticks
<= sc
->mii_anegticks
)
248 return (EJUSTRETURN
);
257 mii_phy_reset(struct mii_softc
*sc
)
259 struct ifmedia_entry
*ife
= sc
->mii_pdata
->mii_media
.ifm_cur
;
262 if ((sc
->mii_flags
& MIIF_NOISOLATE
) != 0)
265 reg
= BMCR_RESET
| BMCR_ISO
;
266 PHY_WRITE(sc
, MII_BMCR
, reg
);
268 /* Wait 100ms for it to complete. */
269 for (i
= 0; i
< 100; i
++) {
270 reg
= PHY_READ(sc
, MII_BMCR
);
271 if ((reg
& BMCR_RESET
) == 0)
276 /* NB: a PHY may default to being powered down and/or isolated. */
277 reg
&= ~(BMCR_PDOWN
| BMCR_ISO
);
278 if ((sc
->mii_flags
& MIIF_NOISOLATE
) == 0 &&
279 ((ife
== NULL
&& sc
->mii_inst
!= 0) ||
280 (ife
!= NULL
&& IFM_INST(ife
->ifm_media
) != sc
->mii_inst
)))
282 if (PHY_READ(sc
, MII_BMCR
) != reg
)
283 PHY_WRITE(sc
, MII_BMCR
, reg
);
287 mii_phy_down(struct mii_softc
*sc
)
293 mii_phy_update(struct mii_softc
*sc
, int cmd
)
295 struct mii_data
*mii
= sc
->mii_pdata
;
297 if (sc
->mii_media_active
!= mii
->mii_media_active
||
298 cmd
== MII_MEDIACHG
) {
299 MIIBUS_STATCHG(sc
->mii_dev
);
300 sc
->mii_media_active
= mii
->mii_media_active
;
302 if (sc
->mii_media_status
!= mii
->mii_media_status
) {
303 MIIBUS_LINKCHG(sc
->mii_dev
);
304 sc
->mii_media_status
= mii
->mii_media_status
;
309 * Given an ifmedia word, return the corresponding ANAR value.
316 switch (media
& (IFM_TMASK
|IFM_NMASK
|IFM_FDX
)) {
317 case IFM_ETHER
|IFM_10_T
:
318 rv
= ANAR_10
|ANAR_CSMA
;
320 case IFM_ETHER
|IFM_10_T
|IFM_FDX
:
321 rv
= ANAR_10_FD
|ANAR_CSMA
;
323 case IFM_ETHER
|IFM_100_TX
:
324 rv
= ANAR_TX
|ANAR_CSMA
;
326 case IFM_ETHER
|IFM_100_TX
|IFM_FDX
:
327 rv
= ANAR_TX_FD
|ANAR_CSMA
;
329 case IFM_ETHER
|IFM_100_T4
:
330 rv
= ANAR_T4
|ANAR_CSMA
;
341 * Given a BMCR value, return the corresponding ifmedia word.
344 mii_media_from_bmcr(int bmcr
)
348 if (bmcr
& BMCR_S100
)
359 * Initialize generic PHY media based on BMSR, called when a PHY is
360 * attached. We expect to be set up to print a comma-separated list
361 * of media names. Does not print a newline.
364 mii_phy_add_media(struct mii_softc
*sc
)
366 struct mii_data
*mii
= sc
->mii_pdata
;
367 const char *sep
= "";
371 * Set the autonegotiation timer for 10/100 media. Gigabit media is
374 sc
->mii_anegticks
= MII_ANEGTICKS
;
376 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
377 #define PRINT(s) printf("%s%s", sep, s); sep = ", "
379 if ((sc
->mii_flags
& MIIF_NOISOLATE
) == 0) {
380 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_NONE
, 0, sc
->mii_inst
),
386 * There are different interpretations for the bits in
387 * HomePNA PHYs. And there is really only one media type
390 if ((sc
->mii_flags
& MIIF_IS_HPNA
) != 0) {
391 if ((sc
->mii_capabilities
& BMSR_10THDX
) != 0) {
392 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_HPNA_1
, 0,
393 sc
->mii_inst
), MII_MEDIA_10_T
);
399 if ((sc
->mii_capabilities
& BMSR_10THDX
) != 0) {
400 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_10_T
, 0, sc
->mii_inst
),
404 if ((sc
->mii_capabilities
& BMSR_10TFDX
) != 0) {
405 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_10_T
, IFM_FDX
, sc
->mii_inst
),
407 PRINT("10baseT-FDX");
408 if ((sc
->mii_flags
& MIIF_DOPAUSE
) != 0 &&
409 (sc
->mii_flags
& MIIF_NOMANPAUSE
) == 0) {
410 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_10_T
,
411 IFM_FDX
| IFM_FLOW
, sc
->mii_inst
),
413 PRINT("10baseT-FDX-flow");
417 if ((sc
->mii_capabilities
& BMSR_100TXHDX
) != 0) {
418 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_100_TX
, 0, sc
->mii_inst
),
422 if ((sc
->mii_capabilities
& BMSR_100TXFDX
) != 0) {
423 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_100_TX
, IFM_FDX
, sc
->mii_inst
),
424 MII_MEDIA_100_TX_FDX
);
425 PRINT("100baseTX-FDX");
426 if ((sc
->mii_flags
& MIIF_DOPAUSE
) != 0 &&
427 (sc
->mii_flags
& MIIF_NOMANPAUSE
) == 0) {
428 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_100_TX
,
429 IFM_FDX
| IFM_FLOW
, sc
->mii_inst
),
430 MII_MEDIA_100_TX_FDX
);
431 PRINT("100baseTX-FDX-flow");
435 if ((sc
->mii_capabilities
& BMSR_100T4
) != 0) {
436 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_100_T4
, 0, sc
->mii_inst
),
441 if ((sc
->mii_extcapabilities
& EXTSR_MEDIAMASK
) != 0) {
443 * XXX Right now only handle 1000SX and 1000TX. Need
444 * XXX to handle 1000LX and 1000CX somehow.
446 if ((sc
->mii_extcapabilities
& EXTSR_1000XHDX
) != 0) {
447 sc
->mii_anegticks
= MII_ANEGTICKS_GIGE
;
448 sc
->mii_flags
|= MIIF_IS_1000X
;
449 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_SX
, 0,
450 sc
->mii_inst
), MII_MEDIA_1000_X
);
453 if ((sc
->mii_extcapabilities
& EXTSR_1000XFDX
) != 0) {
454 sc
->mii_anegticks
= MII_ANEGTICKS_GIGE
;
455 sc
->mii_flags
|= MIIF_IS_1000X
;
456 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_SX
, IFM_FDX
,
457 sc
->mii_inst
), MII_MEDIA_1000_X_FDX
);
458 PRINT("1000baseSX-FDX");
459 if ((sc
->mii_flags
& MIIF_DOPAUSE
) != 0 &&
460 (sc
->mii_flags
& MIIF_NOMANPAUSE
) == 0) {
461 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_SX
,
462 IFM_FDX
| IFM_FLOW
, sc
->mii_inst
),
463 MII_MEDIA_1000_X_FDX
);
464 PRINT("1000baseSX-FDX-flow");
470 * 1000baseT media needs to be able to manipulate
473 * All 1000baseT PHYs have a 1000baseT control register.
475 if ((sc
->mii_extcapabilities
& EXTSR_1000THDX
) != 0) {
476 sc
->mii_anegticks
= MII_ANEGTICKS_GIGE
;
477 sc
->mii_flags
|= MIIF_HAVE_GTCR
;
478 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_T
, 0,
479 sc
->mii_inst
), MII_MEDIA_1000_T
);
481 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_T
,
482 IFM_ETH_MASTER
, sc
->mii_inst
), MII_MEDIA_1000_T
);
483 PRINT("1000baseT-master");
485 if ((sc
->mii_extcapabilities
& EXTSR_1000TFDX
) != 0) {
486 sc
->mii_anegticks
= MII_ANEGTICKS_GIGE
;
487 sc
->mii_flags
|= MIIF_HAVE_GTCR
;
488 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_T
, IFM_FDX
,
489 sc
->mii_inst
), MII_MEDIA_1000_T_FDX
);
490 PRINT("1000baseT-FDX");
491 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_T
,
492 IFM_FDX
| IFM_ETH_MASTER
, sc
->mii_inst
),
493 MII_MEDIA_1000_T_FDX
);
494 PRINT("1000baseT-FDX-master");
495 if ((sc
->mii_flags
& MIIF_DOPAUSE
) != 0 &&
496 (sc
->mii_flags
& MIIF_NOMANPAUSE
) == 0) {
497 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_T
,
498 IFM_FDX
| IFM_FLOW
, sc
->mii_inst
),
499 MII_MEDIA_1000_T_FDX
);
500 PRINT("1000baseT-FDX-flow");
501 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_T
,
502 IFM_FDX
| IFM_FLOW
| IFM_ETH_MASTER
,
503 sc
->mii_inst
), MII_MEDIA_1000_T_FDX
);
504 PRINT("1000baseT-FDX-flow-master");
510 if ((sc
->mii_capabilities
& BMSR_ANEG
) != 0) {
511 /* intentionally invalid index */
512 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_AUTO
, 0, sc
->mii_inst
),
515 if (fdx
!= 0 && (sc
->mii_flags
& MIIF_DOPAUSE
) != 0) {
516 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_AUTO
, IFM_FLOW
,
517 sc
->mii_inst
), MII_NMEDIA
);
526 mii_phy_detach(device_t dev
)
528 struct mii_softc
*sc
;
530 sc
= device_get_softc(dev
);
533 LIST_REMOVE(sc
, mii_list
);
537 const struct mii_phydesc
*
538 mii_phy_match_gen(const struct mii_attach_args
*ma
,
539 const struct mii_phydesc
*mpd
, size_t len
)
542 for (; mpd
->mpd_name
!= NULL
;
543 mpd
= (const struct mii_phydesc
*)((const char *)mpd
+ len
)) {
544 if (MII_OUI(ma
->mii_id1
, ma
->mii_id2
) == mpd
->mpd_oui
&&
545 MII_MODEL(ma
->mii_id2
) == mpd
->mpd_model
)
551 const struct mii_phydesc
*
552 mii_phy_match(const struct mii_attach_args
*ma
, const struct mii_phydesc
*mpd
)
555 return (mii_phy_match_gen(ma
, mpd
, sizeof(struct mii_phydesc
)));
559 mii_phy_dev_probe(device_t dev
, const struct mii_phydesc
*mpd
, int mrv
)
562 mpd
= mii_phy_match(device_get_ivars(dev
), mpd
);
564 device_set_desc(dev
, mpd
->mpd_name
);
571 mii_phy_dev_attach(device_t dev
, u_int flags
, const struct mii_phy_funcs
*mpf
,
574 struct mii_softc
*sc
;
575 struct mii_attach_args
*ma
;
576 struct mii_data
*mii
;
578 sc
= device_get_softc(dev
);
579 ma
= device_get_ivars(dev
);
580 sc
->mii_dev
= device_get_parent(dev
);
582 LIST_INSERT_HEAD(&mii
->mii_phys
, sc
, mii_list
);
584 sc
->mii_flags
= flags
| miibus_get_flags(dev
);
585 sc
->mii_mpd_oui
= MII_OUI(ma
->mii_id1
, ma
->mii_id2
);
586 sc
->mii_mpd_model
= MII_MODEL(ma
->mii_id2
);
587 sc
->mii_mpd_rev
= MII_REV(ma
->mii_id2
);
588 sc
->mii_capmask
= ma
->mii_capmask
;
589 sc
->mii_inst
= mii
->mii_instance
++;
590 sc
->mii_phy
= ma
->mii_phyno
;
591 sc
->mii_offset
= ma
->mii_offset
;
596 device_printf(dev
, "OUI 0x%06x, model 0x%04x, rev. %d\n",
597 sc
->mii_mpd_oui
, sc
->mii_mpd_model
, sc
->mii_mpd_rev
);
604 sc
->mii_capabilities
= PHY_READ(sc
, MII_BMSR
) & sc
->mii_capmask
;
605 if (sc
->mii_capabilities
& BMSR_EXTSTAT
)
606 sc
->mii_extcapabilities
= PHY_READ(sc
, MII_EXTSR
);
607 device_printf(dev
, " ");
608 mii_phy_add_media(sc
);
611 MIIBUS_MEDIAINIT(sc
->mii_dev
);
615 * Return the flow control status flag from MII_ANAR & MII_ANLPAR.
618 mii_phy_flowstatus(struct mii_softc
*sc
)
622 if ((sc
->mii_flags
& MIIF_DOPAUSE
) == 0)
625 anar
= PHY_READ(sc
, MII_ANAR
);
626 anlpar
= PHY_READ(sc
, MII_ANLPAR
);
629 * Check for 1000BASE-X. Autonegotiation is a bit
630 * different on such devices.
632 if ((sc
->mii_flags
& MIIF_IS_1000X
) != 0) {
637 if ((anar
& ANAR_PAUSE_SYM
) != 0 && (anlpar
& ANLPAR_PAUSE_SYM
) != 0)
638 return (IFM_FLOW
| IFM_ETH_TXPAUSE
| IFM_ETH_RXPAUSE
);
640 if ((anar
& ANAR_PAUSE_SYM
) == 0) {
641 if ((anar
& ANAR_PAUSE_ASYM
) != 0 &&
642 (anlpar
& ANLPAR_PAUSE_TOWARDS
) != 0)
643 return (IFM_FLOW
| IFM_ETH_TXPAUSE
);
648 if ((anar
& ANAR_PAUSE_ASYM
) == 0) {
649 if ((anlpar
& ANLPAR_PAUSE_SYM
) != 0)
650 return (IFM_FLOW
| IFM_ETH_TXPAUSE
| IFM_ETH_RXPAUSE
);
655 switch ((anlpar
& ANLPAR_PAUSE_TOWARDS
)) {
656 case ANLPAR_PAUSE_NONE
:
658 case ANLPAR_PAUSE_ASYM
:
659 return (IFM_FLOW
| IFM_ETH_RXPAUSE
);
661 return (IFM_FLOW
| IFM_ETH_RXPAUSE
| IFM_ETH_TXPAUSE
);