]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/mii/rgephy.c
vmx: use C99 bool, not boolean_t
[FreeBSD/FreeBSD.git] / sys / dev / mii / rgephy.c
1 /*-
2  * SPDX-License-Identifier: BSD-4-Clause
3  *
4  * Copyright (c) 2003
5  *      Bill Paul <wpaul@windriver.com>.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Bill Paul.
18  * 4. Neither the name of the author nor the names of any co-contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  * THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 /*
39  * Driver for the RealTek 8169S/8110S/8211B/8211C internal 10/100/1000 PHY.
40  */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/module.h>
46 #include <sys/socket.h>
47 #include <sys/taskqueue.h>
48 #include <sys/bus.h>
49
50 #include <net/if.h>
51 #include <net/if_var.h>
52 #include <net/if_arp.h>
53 #include <net/if_media.h>
54
55 #include <dev/mii/mii.h>
56 #include <dev/mii/miivar.h>
57 #include "miidevs.h"
58
59 #include <dev/mii/rgephyreg.h>
60
61 #include "miibus_if.h"
62
63 #include <machine/bus.h>
64 #include <dev/rl/if_rlreg.h>
65
66 static int rgephy_probe(device_t);
67 static int rgephy_attach(device_t);
68
69 static device_method_t rgephy_methods[] = {
70         /* device interface */
71         DEVMETHOD(device_probe,         rgephy_probe),
72         DEVMETHOD(device_attach,        rgephy_attach),
73         DEVMETHOD(device_detach,        mii_phy_detach),
74         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
75         DEVMETHOD_END
76 };
77
78 static devclass_t rgephy_devclass;
79
80 static driver_t rgephy_driver = {
81         "rgephy",
82         rgephy_methods,
83         sizeof(struct mii_softc)
84 };
85
86 DRIVER_MODULE(rgephy, miibus, rgephy_driver, rgephy_devclass, 0, 0);
87
88 static int      rgephy_service(struct mii_softc *, struct mii_data *, int);
89 static void     rgephy_status(struct mii_softc *);
90 static int      rgephy_mii_phy_auto(struct mii_softc *, int);
91 static void     rgephy_reset(struct mii_softc *);
92 static int      rgephy_linkup(struct mii_softc *);
93 static void     rgephy_loop(struct mii_softc *);
94 static void     rgephy_load_dspcode(struct mii_softc *);
95 static void     rgephy_disable_eee(struct mii_softc *);
96
97 static const struct mii_phydesc rgephys[] = {
98         MII_PHY_DESC(REALTEK, RTL8169S),
99         MII_PHY_DESC(REALTEK, RTL8251),
100         MII_PHY_END
101 };
102
103 static const struct mii_phy_funcs rgephy_funcs = {
104         rgephy_service,
105         rgephy_status,
106         rgephy_reset
107 };
108
109 static int
110 rgephy_probe(device_t dev)
111 {
112
113         return (mii_phy_dev_probe(dev, rgephys, BUS_PROBE_DEFAULT));
114 }
115
116 static int
117 rgephy_attach(device_t dev)
118 {
119         struct mii_softc *sc;
120         u_int flags;
121
122         sc = device_get_softc(dev);
123         flags = 0;
124         if (mii_dev_mac_match(dev, "re"))
125                 flags |= MIIF_PHYPRIV0;
126         else if (mii_dev_mac_match(dev, "ure"))
127                 flags |= MIIF_PHYPRIV1;
128         mii_phy_dev_attach(dev, flags, &rgephy_funcs, 0);
129
130         /* RTL8169S do not report auto-sense; add manually. */
131         sc->mii_capabilities = (PHY_READ(sc, MII_BMSR) | BMSR_ANEG) &
132             sc->mii_capmask;
133         if (sc->mii_capabilities & BMSR_EXTSTAT)
134                 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
135         device_printf(dev, " ");
136         mii_phy_add_media(sc);
137         printf("\n");
138         /*
139          * Allow IFM_FLAG0 to be set indicating that auto-negotiation with
140          * manual configuration, which is used to work around issues with
141          * certain setups by default, should not be triggered as it may in
142          * turn cause harm in some edge cases.
143          */
144         sc->mii_pdata->mii_media.ifm_mask |= IFM_FLAG0;
145
146         PHY_RESET(sc);
147
148         MIIBUS_MEDIAINIT(sc->mii_dev);
149         return (0);
150 }
151
152 static int
153 rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
154 {
155         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
156         int speed, gig, anar;
157
158         switch (cmd) {
159         case MII_POLLSTAT:
160                 break;
161
162         case MII_MEDIACHG:
163                 PHY_RESET(sc);  /* XXX hardware bug work-around */
164
165                 anar = PHY_READ(sc, RGEPHY_MII_ANAR);
166                 anar &= ~(RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP |
167                     RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
168                     RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10);
169
170                 switch (IFM_SUBTYPE(ife->ifm_media)) {
171                 case IFM_AUTO:
172 #ifdef foo
173                         /*
174                          * If we're already in auto mode, just return.
175                          */
176                         if (PHY_READ(sc, RGEPHY_MII_BMCR) & RGEPHY_BMCR_AUTOEN)
177                                 return (0);
178 #endif
179                         (void)rgephy_mii_phy_auto(sc, ife->ifm_media);
180                         break;
181                 case IFM_1000_T:
182                         speed = RGEPHY_S1000;
183                         goto setit;
184                 case IFM_100_TX:
185                         speed = RGEPHY_S100;
186                         anar |= RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX;
187                         goto setit;
188                 case IFM_10_T:
189                         speed = RGEPHY_S10;
190                         anar |= RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10;
191 setit:
192                         if ((ife->ifm_media & IFM_FLOW) != 0 &&
193                             (mii->mii_media.ifm_media & IFM_FLAG0) != 0)
194                                 return (EINVAL);
195
196                         if ((ife->ifm_media & IFM_FDX) != 0) {
197                                 speed |= RGEPHY_BMCR_FDX;
198                                 gig = RGEPHY_1000CTL_AFD;
199                                 anar &= ~(RGEPHY_ANAR_TX | RGEPHY_ANAR_10);
200                                 if ((ife->ifm_media & IFM_FLOW) != 0 ||
201                                     (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
202                                         anar |=
203                                             RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP;
204                         } else {
205                                 gig = RGEPHY_1000CTL_AHD;
206                                 anar &=
207                                     ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_10_FD);
208                         }
209                         if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
210                                 gig |= RGEPHY_1000CTL_MSE;
211                                 if ((ife->ifm_media & IFM_ETH_MASTER) != 0)
212                                     gig |= RGEPHY_1000CTL_MSC;
213                         } else {
214                                 gig = 0;
215                                 anar &= ~RGEPHY_ANAR_ASP;
216                         }
217                         if ((mii->mii_media.ifm_media & IFM_FLAG0) == 0)
218                                 speed |=
219                                     RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG;
220                         rgephy_loop(sc);
221                         PHY_WRITE(sc, RGEPHY_MII_1000CTL, gig);
222                         PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
223                         PHY_WRITE(sc, RGEPHY_MII_BMCR, speed);
224                         break;
225                 case IFM_NONE:
226                         PHY_WRITE(sc, MII_BMCR, BMCR_ISO | BMCR_PDOWN);
227                         break;
228                 default:
229                         return (EINVAL);
230                 }
231                 break;
232
233         case MII_TICK:
234                 /*
235                  * Only used for autonegotiation.
236                  */
237                 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
238                         sc->mii_ticks = 0;
239                         break;
240                 }
241
242                 /*
243                  * Check to see if we have link.  If we do, we don't
244                  * need to restart the autonegotiation process.
245                  */
246                 if (rgephy_linkup(sc) != 0) {
247                         sc->mii_ticks = 0;
248                         break;
249                 }
250
251                 /* Announce link loss right after it happens. */
252                 if (sc->mii_ticks++ == 0)
253                         break;
254
255                 /* Only retry autonegotiation every mii_anegticks seconds. */
256                 if (sc->mii_ticks <= sc->mii_anegticks)
257                         return (0);
258
259                 sc->mii_ticks = 0;
260                 rgephy_mii_phy_auto(sc, ife->ifm_media);
261                 break;
262         }
263
264         /* Update the media status. */
265         PHY_STATUS(sc);
266
267         /*
268          * Callback if something changed. Note that we need to poke
269          * the DSP on the RealTek PHYs if the media changes.
270          *
271          */
272         if (sc->mii_media_active != mii->mii_media_active ||
273             sc->mii_media_status != mii->mii_media_status ||
274             cmd == MII_MEDIACHG) {
275                 rgephy_load_dspcode(sc);
276         }
277         mii_phy_update(sc, cmd);
278         return (0);
279 }
280
281 static int
282 rgephy_linkup(struct mii_softc *sc)
283 {
284         int linkup;
285         uint16_t reg;
286
287         linkup = 0;
288         if ((sc->mii_flags & MIIF_PHYPRIV0) == 0 &&
289             sc->mii_mpd_rev >= RGEPHY_8211B) {
290                 if (sc->mii_mpd_rev == RGEPHY_8211F) {
291                         reg = PHY_READ(sc, RGEPHY_F_MII_SSR);
292                         if (reg & RGEPHY_F_SSR_LINK)
293                                 linkup++;
294                 } else {
295                         reg = PHY_READ(sc, RGEPHY_MII_SSR);
296                         if (reg & RGEPHY_SSR_LINK)
297                                 linkup++;
298                 }
299         } else {
300                 if (sc->mii_flags & MIIF_PHYPRIV1)
301                         reg = PHY_READ(sc, URE_GMEDIASTAT);
302                 else
303                         reg = PHY_READ(sc, RL_GMEDIASTAT);
304                 if (reg & RL_GMEDIASTAT_LINK)
305                         linkup++;
306         }
307
308         return (linkup);
309 }
310
311 static void
312 rgephy_status(struct mii_softc *sc)
313 {
314         struct mii_data *mii = sc->mii_pdata;
315         int bmsr, bmcr;
316         uint16_t ssr;
317
318         mii->mii_media_status = IFM_AVALID;
319         mii->mii_media_active = IFM_ETHER;
320
321         if (rgephy_linkup(sc) != 0)
322                 mii->mii_media_status |= IFM_ACTIVE;
323
324         bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
325         bmcr = PHY_READ(sc, RGEPHY_MII_BMCR);
326         if (bmcr & RGEPHY_BMCR_ISO) {
327                 mii->mii_media_active |= IFM_NONE;
328                 mii->mii_media_status = 0;
329                 return;
330         }
331
332         if (bmcr & RGEPHY_BMCR_LOOP)
333                 mii->mii_media_active |= IFM_LOOP;
334
335         if (bmcr & RGEPHY_BMCR_AUTOEN) {
336                 if ((bmsr & RGEPHY_BMSR_ACOMP) == 0) {
337                         /* Erg, still trying, I guess... */
338                         mii->mii_media_active |= IFM_NONE;
339                         return;
340                 }
341         }
342
343         if ((sc->mii_flags & MIIF_PHYPRIV0) == 0 &&
344             sc->mii_mpd_rev >= RGEPHY_8211B) {
345                 if (sc->mii_mpd_rev == RGEPHY_8211F) {
346                         ssr = PHY_READ(sc, RGEPHY_F_MII_SSR);
347                         switch (ssr & RGEPHY_F_SSR_SPD_MASK) {
348                         case RGEPHY_F_SSR_S1000:
349                                 mii->mii_media_active |= IFM_1000_T;
350                                 break;
351                         case RGEPHY_F_SSR_S100:
352                                 mii->mii_media_active |= IFM_100_TX;
353                                 break;
354                         case RGEPHY_F_SSR_S10:
355                                 mii->mii_media_active |= IFM_10_T;
356                                 break;
357                         default:
358                                 mii->mii_media_active |= IFM_NONE;
359                                 break;
360                         }
361                         if (ssr & RGEPHY_F_SSR_FDX)
362                                 mii->mii_media_active |= IFM_FDX;
363                         else
364                                 mii->mii_media_active |= IFM_HDX;
365
366                 } else {
367                         ssr = PHY_READ(sc, RGEPHY_MII_SSR);
368                         switch (ssr & RGEPHY_SSR_SPD_MASK) {
369                         case RGEPHY_SSR_S1000:
370                                 mii->mii_media_active |= IFM_1000_T;
371                                 break;
372                         case RGEPHY_SSR_S100:
373                                 mii->mii_media_active |= IFM_100_TX;
374                                 break;
375                         case RGEPHY_SSR_S10:
376                                 mii->mii_media_active |= IFM_10_T;
377                                 break;
378                         default:
379                                 mii->mii_media_active |= IFM_NONE;
380                                 break;
381                         }
382                         if (ssr & RGEPHY_SSR_FDX)
383                                 mii->mii_media_active |= IFM_FDX;
384                         else
385                                 mii->mii_media_active |= IFM_HDX;
386                 }
387         } else {
388                 if (sc->mii_flags & MIIF_PHYPRIV1)
389                         bmsr = PHY_READ(sc, URE_GMEDIASTAT);
390                 else
391                         bmsr = PHY_READ(sc, RL_GMEDIASTAT);
392                 if (bmsr & RL_GMEDIASTAT_1000MBPS)
393                         mii->mii_media_active |= IFM_1000_T;
394                 else if (bmsr & RL_GMEDIASTAT_100MBPS)
395                         mii->mii_media_active |= IFM_100_TX;
396                 else if (bmsr & RL_GMEDIASTAT_10MBPS)
397                         mii->mii_media_active |= IFM_10_T;
398                 else
399                         mii->mii_media_active |= IFM_NONE;
400                 if (bmsr & RL_GMEDIASTAT_FDX)
401                         mii->mii_media_active |= IFM_FDX;
402                 else
403                         mii->mii_media_active |= IFM_HDX;
404         }
405
406         if ((mii->mii_media_active & IFM_FDX) != 0)
407                 mii->mii_media_active |= mii_phy_flowstatus(sc);
408
409         if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) &&
410             (PHY_READ(sc, RGEPHY_MII_1000STS) & RGEPHY_1000STS_MSR) != 0)
411                 mii->mii_media_active |= IFM_ETH_MASTER;
412 }
413
414 static int
415 rgephy_mii_phy_auto(struct mii_softc *sc, int media)
416 {
417         int anar;
418
419         rgephy_loop(sc);
420         PHY_RESET(sc);
421
422         anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
423         if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
424                 anar |= RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP;
425         PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
426         DELAY(1000);
427         PHY_WRITE(sc, RGEPHY_MII_1000CTL,
428             RGEPHY_1000CTL_AHD | RGEPHY_1000CTL_AFD);
429         DELAY(1000);
430         PHY_WRITE(sc, RGEPHY_MII_BMCR,
431             RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
432         DELAY(100);
433
434         return (EJUSTRETURN);
435 }
436
437 static void
438 rgephy_loop(struct mii_softc *sc)
439 {
440         int i;
441
442         if (sc->mii_mpd_model != MII_MODEL_REALTEK_RTL8251 &&
443             sc->mii_mpd_rev < RGEPHY_8211B) {
444                 PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_PDOWN);
445                 DELAY(1000);
446         }
447
448         for (i = 0; i < 15000; i++) {
449                 if (!(PHY_READ(sc, RGEPHY_MII_BMSR) & RGEPHY_BMSR_LINK)) {
450 #if 0
451                         device_printf(sc->mii_dev, "looped %d\n", i);
452 #endif
453                         break;
454                 }
455                 DELAY(10);
456         }
457 }
458
459 #define PHY_SETBIT(x, y, z) \
460         PHY_WRITE(x, y, (PHY_READ(x, y) | (z)))
461 #define PHY_CLRBIT(x, y, z) \
462         PHY_WRITE(x, y, (PHY_READ(x, y) & ~(z)))
463
464 /*
465  * Initialize RealTek PHY per the datasheet. The DSP in the PHYs of
466  * existing revisions of the 8169S/8110S chips need to be tuned in
467  * order to reliably negotiate a 1000Mbps link. This is only needed
468  * for rev 0 and rev 1 of the PHY. Later versions work without
469  * any fixups.
470  */
471 static void
472 rgephy_load_dspcode(struct mii_softc *sc)
473 {
474         int val;
475
476         if (sc->mii_mpd_model == MII_MODEL_REALTEK_RTL8251 ||
477             sc->mii_mpd_rev >= RGEPHY_8211B)
478                 return;
479
480         PHY_WRITE(sc, 31, 0x0001);
481         PHY_WRITE(sc, 21, 0x1000);
482         PHY_WRITE(sc, 24, 0x65C7);
483         PHY_CLRBIT(sc, 4, 0x0800);
484         val = PHY_READ(sc, 4) & 0xFFF;
485         PHY_WRITE(sc, 4, val);
486         PHY_WRITE(sc, 3, 0x00A1);
487         PHY_WRITE(sc, 2, 0x0008);
488         PHY_WRITE(sc, 1, 0x1020);
489         PHY_WRITE(sc, 0, 0x1000);
490         PHY_SETBIT(sc, 4, 0x0800);
491         PHY_CLRBIT(sc, 4, 0x0800);
492         val = (PHY_READ(sc, 4) & 0xFFF) | 0x7000;
493         PHY_WRITE(sc, 4, val);
494         PHY_WRITE(sc, 3, 0xFF41);
495         PHY_WRITE(sc, 2, 0xDE60);
496         PHY_WRITE(sc, 1, 0x0140);
497         PHY_WRITE(sc, 0, 0x0077);
498         val = (PHY_READ(sc, 4) & 0xFFF) | 0xA000;
499         PHY_WRITE(sc, 4, val);
500         PHY_WRITE(sc, 3, 0xDF01);
501         PHY_WRITE(sc, 2, 0xDF20);
502         PHY_WRITE(sc, 1, 0xFF95);
503         PHY_WRITE(sc, 0, 0xFA00);
504         val = (PHY_READ(sc, 4) & 0xFFF) | 0xB000;
505         PHY_WRITE(sc, 4, val);
506         PHY_WRITE(sc, 3, 0xFF41);
507         PHY_WRITE(sc, 2, 0xDE20);
508         PHY_WRITE(sc, 1, 0x0140);
509         PHY_WRITE(sc, 0, 0x00BB);
510         val = (PHY_READ(sc, 4) & 0xFFF) | 0xF000;
511         PHY_WRITE(sc, 4, val);
512         PHY_WRITE(sc, 3, 0xDF01);
513         PHY_WRITE(sc, 2, 0xDF20);
514         PHY_WRITE(sc, 1, 0xFF95);
515         PHY_WRITE(sc, 0, 0xBF00);
516         PHY_SETBIT(sc, 4, 0x0800);
517         PHY_CLRBIT(sc, 4, 0x0800);
518         PHY_WRITE(sc, 31, 0x0000);
519
520         DELAY(40);
521 }
522
523 static void
524 rgephy_reset(struct mii_softc *sc)
525 {
526         uint16_t pcr, ssr;
527
528         switch (sc->mii_mpd_rev) {
529         case RGEPHY_8211F:
530                 pcr = PHY_READ(sc, RGEPHY_F_MII_PCR1);
531                 pcr &= ~(RGEPHY_F_PCR1_MDI_MM | RGEPHY_F_PCR1_ALDPS_EN);
532                 PHY_WRITE(sc, RGEPHY_F_MII_PCR1, pcr);
533                 rgephy_disable_eee(sc);
534                 break;
535         case RGEPHY_8211C:
536                 if ((sc->mii_flags & MIIF_PHYPRIV0) == 0) {
537                         /* RTL8211C(L) */
538                         ssr = PHY_READ(sc, RGEPHY_MII_SSR);
539                         if ((ssr & RGEPHY_SSR_ALDPS) != 0) {
540                                 ssr &= ~RGEPHY_SSR_ALDPS;
541                                 PHY_WRITE(sc, RGEPHY_MII_SSR, ssr);
542                         }
543                 }
544                 /* FALLTHROUGH */
545         default:
546                 if (sc->mii_mpd_rev >= RGEPHY_8211B) {
547                         pcr = PHY_READ(sc, RGEPHY_MII_PCR);
548                         if ((pcr & RGEPHY_PCR_MDIX_AUTO) == 0) {
549                                 pcr &= ~RGEPHY_PCR_MDI_MASK;
550                                 pcr |= RGEPHY_PCR_MDIX_AUTO;
551                                 PHY_WRITE(sc, RGEPHY_MII_PCR, pcr);
552                         }
553                 }
554                 break;
555         }
556
557         mii_phy_reset(sc);
558         DELAY(1000);
559         rgephy_load_dspcode(sc);
560 }
561
562 static void
563 rgephy_disable_eee(struct mii_softc *sc)
564 {
565         uint16_t anar;
566
567         PHY_WRITE(sc, RGEPHY_F_EPAGSR, 0x0000);
568         PHY_WRITE(sc, MII_MMDACR, MMDACR_FN_ADDRESS |
569             (MMDACR_DADDRMASK & RGEPHY_F_MMD_DEV_7));
570         PHY_WRITE(sc, MII_MMDAADR, RGEPHY_F_MMD_EEEAR);
571         PHY_WRITE(sc, MII_MMDACR, MMDACR_FN_DATANPI |
572             (MMDACR_DADDRMASK & RGEPHY_F_MMD_DEV_7));
573         PHY_WRITE(sc, MII_MMDAADR, 0x0000);
574         PHY_WRITE(sc, MII_MMDACR, 0x0000);
575         /*
576          * XXX
577          * Restart auto-negotiation to take changes effect.
578          * This may result in link establishment.
579          */
580         anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
581         PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
582         PHY_WRITE(sc, RGEPHY_MII_1000CTL, RGEPHY_1000CTL_AHD |
583             RGEPHY_1000CTL_AFD);
584         PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_RESET |
585             RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
586 }