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