Remove some duplicate FreeBSD CVS IDs, move some IDs to better places.
[dragonfly.git] / sys / dev / netif / mii_layer / brgphy.c
1 /*
2  * Copyright (c) 2000
3  *      Bill Paul <wpaul@ee.columbia.edu>.  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  * $FreeBSD: src/sys/dev/mii/brgphy.c,v 1.1.2.7 2003/05/11 18:00:55 ps Exp $
33  * $DragonFly: src/sys/dev/netif/mii_layer/brgphy.c,v 1.7 2005/02/21 18:40:36 joerg Exp $
34  */
35
36 /*
37  * Driver for the Broadcom BCR5400 1000baseTX PHY. Speed is always
38  * 1000mbps; all we need to negotiate here is full or half duplex.
39  */
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/socket.h>
45 #include <sys/bus.h>
46
47 #include <machine/bus.h>
48 #include <machine/clock.h>
49
50 #include <net/if.h>
51 #include <net/if_media.h>
52 #include <net/if_arp.h>
53
54 #include "mii.h"
55 #include "miivar.h"
56 #include "miidevs.h"
57
58 #include "brgphyreg.h"
59 #include <dev/netif/bge/if_bgereg.h>
60
61 #include "miibus_if.h"
62
63 static int brgphy_probe(device_t);
64 static int brgphy_attach(device_t);
65 static int brgphy_detach(device_t);
66
67 static device_method_t brgphy_methods[] = {
68         /* device interface */
69         DEVMETHOD(device_probe,         brgphy_probe),
70         DEVMETHOD(device_attach,        brgphy_attach),
71         DEVMETHOD(device_detach,        brgphy_detach),
72         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
73         { 0, 0 }
74 };
75
76 static devclass_t brgphy_devclass;
77
78 static driver_t brgphy_driver = {
79         "brgphy",
80         brgphy_methods,
81         sizeof(struct mii_softc)
82 };
83
84 DRIVER_MODULE(brgphy, miibus, brgphy_driver, brgphy_devclass, 0, 0);
85
86 static int      brgphy_service(struct mii_softc *, struct mii_data *, int);
87 static void     brgphy_status(struct mii_softc *);
88 static int      brgphy_mii_phy_auto(struct mii_softc *);
89 static void     brgphy_reset(struct mii_softc *);
90 static void     brgphy_loop(struct mii_softc *);
91 static void     bcm5401_load_dspcode(struct mii_softc *);
92 static void     bcm5411_load_dspcode(struct mii_softc *);
93 static void     bcm5703_load_dspcode(struct mii_softc *);
94 static int      brgphy_mii_model;
95
96 static int brgphy_probe(dev)
97         device_t                dev;
98 {
99         struct mii_attach_args *ma;
100
101         ma = device_get_ivars(dev);
102
103         if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
104             MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5400) {
105                 device_set_desc(dev, MII_STR_xxBROADCOM_BCM5400);
106                 return(0);
107         }
108
109         if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
110             MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5401) {
111                 device_set_desc(dev, MII_STR_xxBROADCOM_BCM5401);
112                 return(0);
113         }
114
115         if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
116             MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5411) {
117                 device_set_desc(dev, MII_STR_xxBROADCOM_BCM5411);
118                 return(0);
119         }
120
121         if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
122             MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5701) {
123                 device_set_desc(dev, MII_STR_xxBROADCOM_BCM5701);
124                 return(0);
125         }
126
127         if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
128             MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5703) {
129                 device_set_desc(dev, MII_STR_xxBROADCOM_BCM5703);
130                 return(0);
131         }
132
133         if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
134             MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5704) {
135                 device_set_desc(dev, MII_STR_xxBROADCOM_BCM5704);
136                 return(0);
137         }
138
139         if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
140             MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5705) {
141                 device_set_desc(dev, MII_STR_xxBROADCOM_BCM5705);
142                 return(0);
143         }
144
145         return(ENXIO);
146 }
147
148 static int
149 brgphy_attach(dev)
150         device_t                dev;
151 {
152         struct mii_softc *sc;
153         struct mii_attach_args *ma;
154         struct mii_data *mii;
155         const char *sep = "";
156
157         sc = device_get_softc(dev);
158         ma = device_get_ivars(dev);
159         mii_softc_init(sc);
160         sc->mii_dev = device_get_parent(dev);
161         mii = device_get_softc(sc->mii_dev);
162         LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
163
164         sc->mii_inst = mii->mii_instance;
165         sc->mii_phy = ma->mii_phyno;
166         sc->mii_service = brgphy_service;
167         sc->mii_pdata = mii;
168
169         sc->mii_flags |= MIIF_NOISOLATE;
170         mii->mii_instance++;
171
172 #define ADD(m, c)       ifmedia_add(&mii->mii_media, (m), (c), NULL)
173 #define PRINT(s)        printf("%s%s", sep, s); sep = ", "
174
175         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
176             BMCR_ISO);
177 #if 0
178         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
179             BMCR_LOOP|BMCR_S100);
180 #endif
181
182         brgphy_mii_model = MII_MODEL(ma->mii_id2);
183         brgphy_reset(sc);
184
185         sc->mii_capabilities =
186             PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
187         device_printf(dev, " ");
188         if (sc->mii_capabilities & BMSR_MEDIAMASK)
189                 mii_add_media(mii, (sc->mii_capabilities & ~BMSR_ANEG),
190                     sc->mii_inst);
191         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst),
192             BRGPHY_BMCR_FDX);
193         PRINT(", 1000baseTX");
194         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst), 0);
195         PRINT("1000baseTX-FDX");
196         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
197         PRINT("auto");
198
199         printf("\n");
200 #undef ADD
201 #undef PRINT
202
203         MIIBUS_MEDIAINIT(sc->mii_dev);
204         return(0);
205 }
206
207 static int
208 brgphy_detach(dev)
209         device_t                dev;
210 {
211         struct mii_softc *sc;
212         struct mii_data *mii;
213
214         sc = device_get_softc(dev);
215         mii = device_get_softc(device_get_parent(dev));
216         sc->mii_dev = NULL;
217         LIST_REMOVE(sc, mii_list);
218
219         return(0);
220 }
221
222 static int
223 brgphy_service(sc, mii, cmd)
224         struct mii_softc *sc;
225         struct mii_data *mii;
226         int cmd;
227 {
228         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
229         int reg, speed, gig;
230
231         switch (cmd) {
232         case MII_POLLSTAT:
233                 /*
234                  * If we're not polling our PHY instance, just return.
235                  */
236                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
237                         return (0);
238                 break;
239
240         case MII_MEDIACHG:
241                 /*
242                  * If the media indicates a different PHY instance,
243                  * isolate ourselves.
244                  */
245                 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
246                         reg = PHY_READ(sc, MII_BMCR);
247                         PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
248                         return (0);
249                 }
250
251                 /*
252                  * If the interface is not up, don't do anything.
253                  */
254                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
255                         break;
256
257                 brgphy_reset(sc);       /* XXX hardware bug work-around */
258
259                 switch (IFM_SUBTYPE(ife->ifm_media)) {
260                 case IFM_AUTO:
261 #ifdef foo
262                         /*
263                          * If we're already in auto mode, just return.
264                          */
265                         if (PHY_READ(sc, BRGPHY_MII_BMCR) & BRGPHY_BMCR_AUTOEN)
266                                 return (0);
267 #endif
268                         (void) brgphy_mii_phy_auto(sc);
269                         break;
270                 case IFM_1000_T:
271                         speed = BRGPHY_S1000;
272                         goto setit;
273                 case IFM_100_TX:
274                         speed = BRGPHY_S100;
275                         goto setit;
276                 case IFM_10_T:
277                         speed = BRGPHY_S10;
278 setit:
279                         brgphy_loop(sc);
280                         if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
281                                 speed |= BRGPHY_BMCR_FDX;
282                                 gig = BRGPHY_1000CTL_AFD;
283                         } else {
284                                 gig = BRGPHY_1000CTL_AHD;
285                         }
286
287                         PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0);
288                         PHY_WRITE(sc, BRGPHY_MII_BMCR, speed);
289                         PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE);
290
291                         if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
292                                 break;
293
294                         PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig);
295                         PHY_WRITE(sc, BRGPHY_MII_BMCR,
296                             speed|BRGPHY_BMCR_AUTOEN|BRGPHY_BMCR_STARTNEG);
297
298                         if (brgphy_mii_model != MII_MODEL_xxBROADCOM_BCM5701)
299                                 break;
300
301                         /*
302                          * When settning the link manually, one side must
303                          * be the master and the other the slave. However
304                          * ifmedia doesn't give us a good way to specify
305                          * this, so we fake it by using one of the LINK
306                          * flags. If LINK0 is set, we program the PHY to
307                          * be a master, otherwise it's a slave.
308                          */
309                         if ((mii->mii_ifp->if_flags & IFF_LINK0)) {
310                                 PHY_WRITE(sc, BRGPHY_MII_1000CTL,
311                                     gig|BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC);
312                         } else {
313                                 PHY_WRITE(sc, BRGPHY_MII_1000CTL,
314                                     gig|BRGPHY_1000CTL_MSE);
315                         }
316                         break;
317 #ifdef foo
318                 case IFM_NONE:
319                         PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN);
320                         break;
321 #endif
322                 case IFM_100_T4:
323                 default:
324                         return (EINVAL);
325                 }
326                 break;
327
328         case MII_TICK:
329                 /*
330                  * If we're not currently selected, just return.
331                  */
332                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
333                         return (0);
334
335                 /*
336                  * Only used for autonegotiation.
337                  */
338                 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
339                         return (0);
340
341                 /*
342                  * Is the interface even up?
343                  */
344                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
345                         return (0);
346
347                 /*
348                  * Check to see if we have link.  If we do, we don't
349                  * need to restart the autonegotiation process.  Read
350                  * the BMSR twice in case it's latched.
351                  */
352                 reg = PHY_READ(sc, BRGPHY_MII_AUXSTS);
353                 if (reg & BRGPHY_AUXSTS_LINK)
354                         break;
355
356                 /*
357                  * Only retry autonegotiation every 5 seconds.
358                  */
359                 if (++sc->mii_ticks != 5)
360                         return (0);
361                 
362                 sc->mii_ticks = 0;
363                 brgphy_mii_phy_auto(sc);
364                 return (0);
365         }
366
367         /* Update the media status. */
368         brgphy_status(sc);
369
370         /*
371          * Callback if something changed. Note that we need to poke
372          * the DSP on the Broadcom PHYs if the media changes.
373          */
374         if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
375                 MIIBUS_STATCHG(sc->mii_dev);
376                 sc->mii_active = mii->mii_media_active;
377                 switch (brgphy_mii_model) {
378                 case MII_MODEL_xxBROADCOM_BCM5401:
379                         bcm5401_load_dspcode(sc);
380                         break;
381                 case MII_MODEL_xxBROADCOM_BCM5411:
382                         bcm5411_load_dspcode(sc);
383                         break;
384                 }
385         }
386         return (0);
387 }
388
389 void
390 brgphy_status(sc)
391         struct mii_softc *sc;
392 {
393         struct mii_data *mii = sc->mii_pdata;
394         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
395         int bmsr, bmcr;
396
397         mii->mii_media_status = IFM_AVALID;
398         mii->mii_media_active = IFM_ETHER;
399
400         bmsr = PHY_READ(sc, BRGPHY_MII_BMSR);
401         if (PHY_READ(sc, BRGPHY_MII_AUXSTS) & BRGPHY_AUXSTS_LINK)
402                 mii->mii_media_status |= IFM_ACTIVE;
403
404         bmcr = PHY_READ(sc, BRGPHY_MII_BMCR);
405
406         if (bmcr & BRGPHY_BMCR_LOOP)
407                 mii->mii_media_active |= IFM_LOOP;
408
409         if (bmcr & BRGPHY_BMCR_AUTOEN) {
410                 if ((bmsr & BRGPHY_BMSR_ACOMP) == 0) {
411                         /* Erg, still trying, I guess... */
412                         mii->mii_media_active |= IFM_NONE;
413                         return;
414                 }
415
416                 switch (PHY_READ(sc, BRGPHY_MII_AUXSTS) &
417                     BRGPHY_AUXSTS_AN_RES) {
418                 case BRGPHY_RES_1000FD:
419                         mii->mii_media_active |= IFM_1000_T | IFM_FDX;
420                         break;
421                 case BRGPHY_RES_1000HD:
422                         mii->mii_media_active |= IFM_1000_T | IFM_HDX;
423                         break;
424                 case BRGPHY_RES_100FD:
425                         mii->mii_media_active |= IFM_100_TX | IFM_FDX;
426                         break;
427                 case BRGPHY_RES_100T4:
428                         mii->mii_media_active |= IFM_100_T4;
429                         break;
430                 case BRGPHY_RES_100HD:
431                         mii->mii_media_active |= IFM_100_TX | IFM_HDX;
432                         break;
433                 case BRGPHY_RES_10FD:
434                         mii->mii_media_active |= IFM_10_T | IFM_FDX;
435                         break;
436                 case BRGPHY_RES_10HD:
437                         mii->mii_media_active |= IFM_10_T | IFM_HDX;
438                         break;
439                 default:
440                         mii->mii_media_active |= IFM_NONE;
441                         break;
442                 }
443                 return;
444         }
445
446         mii->mii_media_active = ife->ifm_media;
447
448         return;
449 }
450
451
452 static int
453 brgphy_mii_phy_auto(mii)
454         struct mii_softc *mii;
455 {
456         int ktcr = 0;
457
458         brgphy_loop(mii);
459         brgphy_reset(mii);
460         ktcr = BRGPHY_1000CTL_AFD|BRGPHY_1000CTL_AHD;
461         if (brgphy_mii_model == MII_MODEL_xxBROADCOM_BCM5701)
462                 ktcr |= BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC;
463         PHY_WRITE(mii, BRGPHY_MII_1000CTL, ktcr);
464         ktcr = PHY_READ(mii, BRGPHY_MII_1000CTL);
465         DELAY(1000);
466         PHY_WRITE(mii, BRGPHY_MII_ANAR,
467             BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
468         DELAY(1000);
469         PHY_WRITE(mii, BRGPHY_MII_BMCR,
470             BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG);
471         PHY_WRITE(mii, BRGPHY_MII_IMR, 0xFF00);
472         return (EJUSTRETURN);
473 }
474
475 static void
476 brgphy_loop(struct mii_softc *sc)
477 {
478         u_int32_t bmsr;
479         int i;
480
481         PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_LOOP);
482         for (i = 0; i < 15000; i++) {
483                 bmsr = PHY_READ(sc, BRGPHY_MII_BMSR);
484                 if (!(bmsr & BRGPHY_BMSR_LINK)) {
485 #if 0
486                         device_printf(sc->mii_dev, "looped %d\n", i);
487 #endif
488                         break;
489                 }
490                 DELAY(10);
491         }
492 }
493
494 /* Turn off tap power management on 5401. */
495 static void
496 bcm5401_load_dspcode(struct mii_softc *sc)
497 {
498         static const struct {
499                 int             reg;
500                 uint16_t        val;
501         } dspcode[] = {
502                 { BRGPHY_MII_AUXCTL,            0x0c20 },
503                 { BRGPHY_MII_DSP_ADDR_REG,      0x0012 },
504                 { BRGPHY_MII_DSP_RW_PORT,       0x1804 },
505                 { BRGPHY_MII_DSP_ADDR_REG,      0x0013 },
506                 { BRGPHY_MII_DSP_RW_PORT,       0x1204 },
507                 { BRGPHY_MII_DSP_ADDR_REG,      0x8006 },
508                 { BRGPHY_MII_DSP_RW_PORT,       0x0132 },
509                 { BRGPHY_MII_DSP_ADDR_REG,      0x8006 },
510                 { BRGPHY_MII_DSP_RW_PORT,       0x0232 },
511                 { BRGPHY_MII_DSP_ADDR_REG,      0x201f },
512                 { BRGPHY_MII_DSP_RW_PORT,       0x0a20 },
513                 { 0,                            0 },
514         };
515         int i;
516
517         for (i = 0; dspcode[i].reg != 0; i++)
518                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
519         DELAY(40);
520 }
521
522 static void
523 bcm5411_load_dspcode(struct mii_softc *sc)
524 {
525         static const struct {
526                 int             reg;
527                 uint16_t        val;
528         } dspcode[] = {
529                 { 0x1c,                         0x8c23 },
530                 { 0x1c,                         0x8ca3 },
531                 { 0x1c,                         0x8c23 },
532                 { 0,                            0 },
533         };
534         int i;
535
536         for (i = 0; dspcode[i].reg != 0; i++)
537                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
538 }
539
540 static void
541 bcm5703_load_dspcode(struct mii_softc *sc)
542 {
543         static const struct {
544                 int             reg;
545                 uint16_t        val;
546         } dspcode[] = {
547                 { BRGPHY_MII_AUXCTL,            0x0c00 },
548                 { BRGPHY_MII_DSP_ADDR_REG,      0x201f },
549                 { BRGPHY_MII_DSP_RW_PORT,       0x2aaa },
550                 { 0,                            0 },
551         };
552         int i;
553
554         for (i = 0; dspcode[i].reg != 0; i++)
555                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
556 }
557
558 static void
559 bcm5704_load_dspcode(struct mii_softc *sc)
560 {
561         static const struct {
562                 int             reg;
563                 u_int16_t       val;
564         } dspcode[] = {
565                 { 0x1c,                         0x8d68 },
566                 { 0x1c,                         0x8d68 },
567                 { 0,                            0 },
568         };
569         int i;
570
571         for (i = 0; dspcode[i].reg != 0; i++)
572                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
573 }
574
575 static void
576 brgphy_reset(struct mii_softc *sc)
577 {
578         u_int32_t       val;
579         struct ifnet    *ifp;
580         struct bge_softc        *bge_sc;
581
582         mii_phy_reset(sc);
583
584         switch (brgphy_mii_model) {
585         case MII_MODEL_xxBROADCOM_BCM5401:
586                 bcm5401_load_dspcode(sc);
587                 break;
588         case MII_MODEL_xxBROADCOM_BCM5411:
589                 bcm5411_load_dspcode(sc);
590                 break;
591         case MII_MODEL_xxBROADCOM_BCM5703:
592                 bcm5703_load_dspcode(sc);
593                 break;
594         case MII_MODEL_xxBROADCOM_BCM5704:
595                 bcm5704_load_dspcode(sc);
596                 break;
597         }
598
599         ifp = sc->mii_pdata->mii_ifp;
600         bge_sc = ifp->if_softc;
601
602         /*
603          * Don't enable Ethernet@WireSpeed for the 5700 or the
604          * 5705 A1 and A2 chips. Make sure we only do this test
605          * on "bge" NICs, since other drivers may use this same
606          * PHY subdriver.
607          */
608         if (strcmp(ifp->if_dname, "bge") == 0 &&
609             (bge_sc->bge_asicrev == BGE_ASICREV_BCM5700 ||
610             bge_sc->bge_chipid == BGE_CHIPID_BCM5705_A1 ||
611             bge_sc->bge_chipid == BGE_CHIPID_BCM5705_A2))
612                 return;
613
614         /* Enable Ethernet@WireSpeed. */
615         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007);
616         val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
617         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4));
618
619         /* Enable Link LED on Dell boxes */
620         if (bge_sc->bge_no_3_led) {
621                 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, 
622                     PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL)
623                     & ~BRGPHY_PHY_EXTCTL_3_LED);
624         }
625 }