Deleted Added
full compact
mii_physubr.c (214608) mii_physubr.c (215297)
1/* $NetBSD: mii_physubr.c,v 1.5 1999/08/03 19:41:49 drochner Exp $ */
2
3/*-
4 * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,

--- 17 unchanged lines hidden (view full) ---

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.
31 */
32
33#include <sys/cdefs.h>
1/* $NetBSD: mii_physubr.c,v 1.5 1999/08/03 19:41:49 drochner Exp $ */
2
3/*-
4 * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,

--- 17 unchanged lines hidden (view full) ---

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.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/dev/mii/mii_physubr.c 214608 2010-10-31 22:59:49Z marius $");
34__FBSDID("$FreeBSD: head/sys/dev/mii/mii_physubr.c 215297 2010-11-14 13:26:10Z marius $");
35
36/*
37 * Subroutines common to all PHYs.
38 */
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>

--- 58 unchanged lines hidden (view full) ---

101void
102mii_phy_setmedia(struct mii_softc *sc)
103{
104 struct mii_data *mii = sc->mii_pdata;
105 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
106 int bmcr, anar, gtcr;
107
108 if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
35
36/*
37 * Subroutines common to all PHYs.
38 */
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>

--- 58 unchanged lines hidden (view full) ---

101void
102mii_phy_setmedia(struct mii_softc *sc)
103{
104 struct mii_data *mii = sc->mii_pdata;
105 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
106 int bmcr, anar, gtcr;
107
108 if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
109 /*
110 * Force renegotiation if MIIF_DOPAUSE or MIIF_FORCEANEG.
111 * The former is necessary as we might switch from flow-
112 * control advertisment being off to on or vice versa.
113 */
109 if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0 ||
114 if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0 ||
110 (sc->mii_flags & MIIF_FORCEANEG) != 0)
115 (sc->mii_flags & (MIIF_DOPAUSE | MIIF_FORCEANEG)) != 0)
111 (void)mii_phy_auto(sc);
112 return;
113 }
114
115 /*
116 * Table index is stored in the media entry.
117 */
118
119 KASSERT(ife->ifm_data >=0 && ife->ifm_data < MII_NMEDIA,
120 ("invalid ife->ifm_data (0x%x) in mii_phy_setmedia",
121 ife->ifm_data));
122
123 anar = mii_media_table[ife->ifm_data].mm_anar;
124 bmcr = mii_media_table[ife->ifm_data].mm_bmcr;
125 gtcr = mii_media_table[ife->ifm_data].mm_gtcr;
126
116 (void)mii_phy_auto(sc);
117 return;
118 }
119
120 /*
121 * Table index is stored in the media entry.
122 */
123
124 KASSERT(ife->ifm_data >=0 && ife->ifm_data < MII_NMEDIA,
125 ("invalid ife->ifm_data (0x%x) in mii_phy_setmedia",
126 ife->ifm_data));
127
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;
131
127 if ((mii->mii_media.ifm_media & IFM_ETH_MASTER) != 0) {
128 switch (IFM_SUBTYPE(ife->ifm_media)) {
129 case IFM_1000_T:
130 gtcr |= GTCR_MAN_MS | GTCR_ADV_MS;
131 break;
132 if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
133 gtcr |= GTCR_MAN_MS;
134 if ((ife->ifm_media & IFM_ETH_MASTER) != 0)
135 gtcr |= GTCR_ADV_MS;
136 }
132
137
133 default:
134 printf("mii_phy_setmedia: MASTER on wrong media\n");
138 if ((ife->ifm_media & IFM_GMASK) == (IFM_FDX | IFM_FLOW) ||
139 (sc->mii_flags & MIIF_FORCEPAUSE) != 0) {
140 if ((sc->mii_flags & MIIF_IS_1000X) != 0)
141 anar |= ANAR_X_PAUSE_TOWARDS;
142 else {
143 anar |= ANAR_FC;
144 /* XXX Only 1000BASE-T has PAUSE_ASYM? */
145 if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0 &&
146 (sc->mii_extcapabilities &
147 (EXTSR_1000THDX | EXTSR_1000TFDX)) != 0)
148 anar |= ANAR_X_PAUSE_ASYM;
135 }
136 }
137
138 if ((ife->ifm_media & IFM_LOOP) != 0)
139 bmcr |= BMCR_LOOP;
140
141 PHY_WRITE(sc, MII_ANAR, anar);
142 PHY_WRITE(sc, MII_BMCR, bmcr);
143 if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0)
144 PHY_WRITE(sc, MII_100T2CR, gtcr);
145}
146
147int
148mii_phy_auto(struct mii_softc *sc)
149{
149 }
150 }
151
152 if ((ife->ifm_media & IFM_LOOP) != 0)
153 bmcr |= BMCR_LOOP;
154
155 PHY_WRITE(sc, MII_ANAR, anar);
156 PHY_WRITE(sc, MII_BMCR, bmcr);
157 if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0)
158 PHY_WRITE(sc, MII_100T2CR, gtcr);
159}
160
161int
162mii_phy_auto(struct mii_softc *sc)
163{
164 struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur;
150 int anar, gtcr;
151
152 /*
153 * Check for 1000BASE-X. Autonegotiation is a bit
154 * different on such devices.
155 */
156 if ((sc->mii_flags & MIIF_IS_1000X) != 0) {
157 anar = 0;
158 if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0)
159 anar |= ANAR_X_FD;
160 if ((sc->mii_extcapabilities & EXTSR_1000XHDX) != 0)
161 anar |= ANAR_X_HD;
162
165 int anar, gtcr;
166
167 /*
168 * Check for 1000BASE-X. Autonegotiation is a bit
169 * different on such devices.
170 */
171 if ((sc->mii_flags & MIIF_IS_1000X) != 0) {
172 anar = 0;
173 if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0)
174 anar |= ANAR_X_FD;
175 if ((sc->mii_extcapabilities & EXTSR_1000XHDX) != 0)
176 anar |= ANAR_X_HD;
177
163 if ((sc->mii_flags & MIIF_DOPAUSE) != 0) {
164 /* XXX Asymmetric vs. symmetric? */
165 anar |= ANLPAR_X_PAUSE_TOWARDS;
166 }
178 if ((ife->ifm_media & IFM_FLOW) != 0 ||
179 (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
180 anar |= ANAR_X_PAUSE_TOWARDS;
167 PHY_WRITE(sc, MII_ANAR, anar);
168 } else {
169 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) |
170 ANAR_CSMA;
181 PHY_WRITE(sc, MII_ANAR, anar);
182 } else {
183 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) |
184 ANAR_CSMA;
171 if ((sc->mii_flags & MIIF_DOPAUSE) != 0)
172 anar |= ANAR_FC;
185 if ((ife->ifm_media & IFM_FLOW) != 0 ||
186 (sc->mii_flags & MIIF_FORCEPAUSE) != 0) {
187 if ((sc->mii_capabilities & BMSR_100TXFDX) != 0)
188 anar |= ANAR_FC;
189 /* XXX Only 1000BASE-T has PAUSE_ASYM? */
190 if (((sc->mii_flags & MIIF_HAVE_GTCR) != 0) &&
191 (sc->mii_extcapabilities &
192 (EXTSR_1000THDX | EXTSR_1000TFDX)) != 0)
193 anar |= ANAR_X_PAUSE_ASYM;
194 }
173 PHY_WRITE(sc, MII_ANAR, anar);
174 if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) {
175 gtcr = 0;
176 if ((sc->mii_extcapabilities & EXTSR_1000TFDX) != 0)
177 gtcr |= GTCR_ADV_1000TFDX;
178 if ((sc->mii_extcapabilities & EXTSR_1000THDX) != 0)
179 gtcr |= GTCR_ADV_1000THDX;
180 PHY_WRITE(sc, MII_100T2CR, gtcr);

--- 105 unchanged lines hidden (view full) ---

286 * attached. We expect to be set up to print a comma-separated list
287 * of media names. Does not print a newline.
288 */
289void
290mii_phy_add_media(struct mii_softc *sc)
291{
292 struct mii_data *mii = sc->mii_pdata;
293 const char *sep = "";
195 PHY_WRITE(sc, MII_ANAR, anar);
196 if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) {
197 gtcr = 0;
198 if ((sc->mii_extcapabilities & EXTSR_1000TFDX) != 0)
199 gtcr |= GTCR_ADV_1000TFDX;
200 if ((sc->mii_extcapabilities & EXTSR_1000THDX) != 0)
201 gtcr |= GTCR_ADV_1000THDX;
202 PHY_WRITE(sc, MII_100T2CR, gtcr);

--- 105 unchanged lines hidden (view full) ---

308 * attached. We expect to be set up to print a comma-separated list
309 * of media names. Does not print a newline.
310 */
311void
312mii_phy_add_media(struct mii_softc *sc)
313{
314 struct mii_data *mii = sc->mii_pdata;
315 const char *sep = "";
316 int fdx = 0;
294
295 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
296 (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) {
297 printf("no media present");
298 return;
299 }
300
301 /*

--- 27 unchanged lines hidden (view full) ---

329 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
330 MII_MEDIA_10_T);
331 PRINT("10baseT");
332 }
333 if ((sc->mii_capabilities & BMSR_10TFDX) != 0) {
334 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
335 MII_MEDIA_10_T_FDX);
336 PRINT("10baseT-FDX");
317
318 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
319 (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) {
320 printf("no media present");
321 return;
322 }
323
324 /*

--- 27 unchanged lines hidden (view full) ---

352 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
353 MII_MEDIA_10_T);
354 PRINT("10baseT");
355 }
356 if ((sc->mii_capabilities & BMSR_10TFDX) != 0) {
357 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
358 MII_MEDIA_10_T_FDX);
359 PRINT("10baseT-FDX");
360 if ((sc->mii_flags & MIIF_DOPAUSE) != 0 &&
361 (sc->mii_flags & MIIF_NOMANPAUSE) == 0) {
362 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T,
363 IFM_FDX | IFM_FLOW, sc->mii_inst),
364 MII_MEDIA_10_T_FDX);
365 PRINT("10baseT-FDX-flow");
366 }
367 fdx = 1;
337 }
338 if ((sc->mii_capabilities & BMSR_100TXHDX) != 0) {
339 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
340 MII_MEDIA_100_TX);
341 PRINT("100baseTX");
342 }
343 if ((sc->mii_capabilities & BMSR_100TXFDX) != 0) {
344 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
345 MII_MEDIA_100_TX_FDX);
346 PRINT("100baseTX-FDX");
368 }
369 if ((sc->mii_capabilities & BMSR_100TXHDX) != 0) {
370 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
371 MII_MEDIA_100_TX);
372 PRINT("100baseTX");
373 }
374 if ((sc->mii_capabilities & BMSR_100TXFDX) != 0) {
375 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
376 MII_MEDIA_100_TX_FDX);
377 PRINT("100baseTX-FDX");
378 if ((sc->mii_flags & MIIF_DOPAUSE) != 0 &&
379 (sc->mii_flags & MIIF_NOMANPAUSE) == 0) {
380 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX,
381 IFM_FDX | IFM_FLOW, sc->mii_inst),
382 MII_MEDIA_100_TX_FDX);
383 PRINT("100baseTX-FDX-flow");
384 }
385 fdx = 1;
347 }
348 if ((sc->mii_capabilities & BMSR_100T4) != 0) {
349 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst),
350 MII_MEDIA_100_T4);
351 PRINT("100baseT4");
352 }
353
354 if ((sc->mii_extcapabilities & EXTSR_MEDIAMASK) != 0) {

--- 9 unchanged lines hidden (view full) ---

364 PRINT("1000baseSX");
365 }
366 if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0) {
367 sc->mii_anegticks = MII_ANEGTICKS_GIGE;
368 sc->mii_flags |= MIIF_IS_1000X;
369 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX,
370 sc->mii_inst), MII_MEDIA_1000_X_FDX);
371 PRINT("1000baseSX-FDX");
386 }
387 if ((sc->mii_capabilities & BMSR_100T4) != 0) {
388 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst),
389 MII_MEDIA_100_T4);
390 PRINT("100baseT4");
391 }
392
393 if ((sc->mii_extcapabilities & EXTSR_MEDIAMASK) != 0) {

--- 9 unchanged lines hidden (view full) ---

403 PRINT("1000baseSX");
404 }
405 if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0) {
406 sc->mii_anegticks = MII_ANEGTICKS_GIGE;
407 sc->mii_flags |= MIIF_IS_1000X;
408 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX,
409 sc->mii_inst), MII_MEDIA_1000_X_FDX);
410 PRINT("1000baseSX-FDX");
411 if ((sc->mii_flags & MIIF_DOPAUSE) != 0 &&
412 (sc->mii_flags & MIIF_NOMANPAUSE) == 0) {
413 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX,
414 IFM_FDX | IFM_FLOW, sc->mii_inst),
415 MII_MEDIA_1000_X_FDX);
416 PRINT("1000baseSX-FDX-flow");
417 }
418 fdx = 1;
372 }
373
374 /*
375 * 1000baseT media needs to be able to manipulate
419 }
420
421 /*
422 * 1000baseT media needs to be able to manipulate
376 * master/slave mode. We set IFM_ETH_MASTER in
377 * the "don't care mask" and filter it out when
378 * the media is set.
423 * master/slave mode.
379 *
380 * All 1000baseT PHYs have a 1000baseT control register.
381 */
382 if ((sc->mii_extcapabilities & EXTSR_1000THDX) != 0) {
383 sc->mii_anegticks = MII_ANEGTICKS_GIGE;
384 sc->mii_flags |= MIIF_HAVE_GTCR;
424 *
425 * All 1000baseT PHYs have a 1000baseT control register.
426 */
427 if ((sc->mii_extcapabilities & EXTSR_1000THDX) != 0) {
428 sc->mii_anegticks = MII_ANEGTICKS_GIGE;
429 sc->mii_flags |= MIIF_HAVE_GTCR;
385 mii->mii_media.ifm_mask |= IFM_ETH_MASTER;
386 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0,
387 sc->mii_inst), MII_MEDIA_1000_T);
388 PRINT("1000baseT");
430 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0,
431 sc->mii_inst), MII_MEDIA_1000_T);
432 PRINT("1000baseT");
433 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T,
434 IFM_ETH_MASTER, sc->mii_inst), MII_MEDIA_1000_T);
435 PRINT("1000baseT-master");
389 }
390 if ((sc->mii_extcapabilities & EXTSR_1000TFDX) != 0) {
391 sc->mii_anegticks = MII_ANEGTICKS_GIGE;
392 sc->mii_flags |= MIIF_HAVE_GTCR;
436 }
437 if ((sc->mii_extcapabilities & EXTSR_1000TFDX) != 0) {
438 sc->mii_anegticks = MII_ANEGTICKS_GIGE;
439 sc->mii_flags |= MIIF_HAVE_GTCR;
393 mii->mii_media.ifm_mask |= IFM_ETH_MASTER;
394 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX,
395 sc->mii_inst), MII_MEDIA_1000_T_FDX);
396 PRINT("1000baseT-FDX");
440 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX,
441 sc->mii_inst), MII_MEDIA_1000_T_FDX);
442 PRINT("1000baseT-FDX");
443 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T,
444 IFM_FDX | IFM_ETH_MASTER, sc->mii_inst),
445 MII_MEDIA_1000_T_FDX);
446 PRINT("1000baseT-FDX-master");
447 if ((sc->mii_flags & MIIF_DOPAUSE) != 0 &&
448 (sc->mii_flags & MIIF_NOMANPAUSE) == 0) {
449 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T,
450 IFM_FDX | IFM_FLOW, sc->mii_inst),
451 MII_MEDIA_1000_T_FDX);
452 PRINT("1000baseT-FDX-flow");
453 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T,
454 IFM_FDX | IFM_FLOW | IFM_ETH_MASTER,
455 sc->mii_inst), MII_MEDIA_1000_T_FDX);
456 PRINT("1000baseT-FDX-flow-master");
457 }
458 fdx = 1;
397 }
398 }
399
400 if ((sc->mii_capabilities & BMSR_ANEG) != 0) {
459 }
460 }
461
462 if ((sc->mii_capabilities & BMSR_ANEG) != 0) {
463 /* intentionally invalid index */
401 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst),
464 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst),
402 MII_NMEDIA); /* intentionally invalid index */
465 MII_NMEDIA);
403 PRINT("auto");
466 PRINT("auto");
467 if (fdx != 0 && (sc->mii_flags & MIIF_DOPAUSE) != 0) {
468 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, IFM_FLOW,
469 sc->mii_inst), MII_NMEDIA);
470 PRINT("auto-flow");
471 }
404 }
405#undef ADD
406#undef PRINT
407}
408
409int
410mii_phy_detach(device_t dev)
411{

--- 7 unchanged lines hidden (view full) ---

419}
420
421const struct mii_phydesc *
422mii_phy_match_gen(const struct mii_attach_args *ma,
423 const struct mii_phydesc *mpd, size_t len)
424{
425
426 for (; mpd->mpd_name != NULL;
472 }
473#undef ADD
474#undef PRINT
475}
476
477int
478mii_phy_detach(device_t dev)
479{

--- 7 unchanged lines hidden (view full) ---

487}
488
489const struct mii_phydesc *
490mii_phy_match_gen(const struct mii_attach_args *ma,
491 const struct mii_phydesc *mpd, size_t len)
492{
493
494 for (; mpd->mpd_name != NULL;
427 mpd = (const struct mii_phydesc *) ((const char *) mpd + len)) {
495 mpd = (const struct mii_phydesc *)((const char *)mpd + len)) {
428 if (MII_OUI(ma->mii_id1, ma->mii_id2) == mpd->mpd_oui &&
429 MII_MODEL(ma->mii_id2) == mpd->mpd_model)
430 return (mpd);
431 }
432 return (NULL);
433}
434
435const struct mii_phydesc *

--- 9 unchanged lines hidden (view full) ---

445
446 mpd = mii_phy_match(device_get_ivars(dev), mpd);
447 if (mpd != NULL) {
448 device_set_desc(dev, mpd->mpd_name);
449 return (mrv);
450 }
451 return (ENXIO);
452}
496 if (MII_OUI(ma->mii_id1, ma->mii_id2) == mpd->mpd_oui &&
497 MII_MODEL(ma->mii_id2) == mpd->mpd_model)
498 return (mpd);
499 }
500 return (NULL);
501}
502
503const struct mii_phydesc *

--- 9 unchanged lines hidden (view full) ---

513
514 mpd = mii_phy_match(device_get_ivars(dev), mpd);
515 if (mpd != NULL) {
516 device_set_desc(dev, mpd->mpd_name);
517 return (mrv);
518 }
519 return (ENXIO);
520}
521
522/*
523 * Return the flow control status flag from MII_ANAR & MII_ANLPAR.
524 */
525u_int
526mii_phy_flowstatus(struct mii_softc *sc)
527{
528 int anar, anlpar;
529
530 if ((sc->mii_flags & MIIF_DOPAUSE) == 0)
531 return (0);
532
533 anar = PHY_READ(sc, MII_ANAR);
534 anlpar = PHY_READ(sc, MII_ANLPAR);
535
536 /*
537 * Check for 1000BASE-X. Autonegotiation is a bit
538 * different on such devices.
539 */
540 if ((sc->mii_flags & MIIF_IS_1000X) != 0) {
541 anar <<= 3;
542 anlpar <<= 3;
543 }
544
545 if ((anar & ANAR_PAUSE_SYM) != 0 && (anlpar & ANLPAR_PAUSE_SYM) != 0)
546 return (IFM_FLOW | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE);
547
548 if ((anar & ANAR_PAUSE_SYM) == 0) {
549 if ((anar & ANAR_PAUSE_ASYM) != 0 &&
550 (anlpar & ANLPAR_PAUSE_TOWARDS) != 0)
551 return (IFM_FLOW | IFM_ETH_TXPAUSE);
552 else
553 return (0);
554 }
555
556 if ((anar & ANAR_PAUSE_ASYM) == 0) {
557 if ((anlpar & ANLPAR_PAUSE_SYM) != 0)
558 return (IFM_FLOW | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE);
559 else
560 return (0);
561 }
562
563 switch ((anlpar & ANLPAR_PAUSE_TOWARDS)) {
564 case ANLPAR_PAUSE_NONE:
565 return (0);
566 case ANLPAR_PAUSE_ASYM:
567 return (IFM_FLOW | IFM_ETH_RXPAUSE);
568 default:
569 return (IFM_FLOW | IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE);
570 }
571 /* NOTREACHED */
572}