Deleted Added
full compact
rgephy.c (213893) rgephy.c (215298)
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

--- 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
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
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

--- 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
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/dev/mii/rgephy.c 213893 2010-10-15 14:52:11Z marius $");
34__FBSDID("$FreeBSD: head/sys/dev/mii/rgephy.c 215298 2010-11-14 13:31:01Z marius $");
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>

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

84 rgephy_methods,
85 sizeof(struct rgephy_softc)
86};
87
88DRIVER_MODULE(rgephy, miibus, rgephy_driver, rgephy_devclass, 0, 0);
89
90static int rgephy_service(struct mii_softc *, struct mii_data *, int);
91static void rgephy_status(struct mii_softc *);
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>

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

84 rgephy_methods,
85 sizeof(struct rgephy_softc)
86};
87
88DRIVER_MODULE(rgephy, miibus, rgephy_driver, rgephy_devclass, 0, 0);
89
90static int rgephy_service(struct mii_softc *, struct mii_data *, int);
91static void rgephy_status(struct mii_softc *);
92static int rgephy_mii_phy_auto(struct mii_softc *);
92static int rgephy_mii_phy_auto(struct mii_softc *, int);
93static void rgephy_reset(struct mii_softc *);
94static void rgephy_loop(struct mii_softc *);
95static void rgephy_load_dspcode(struct mii_softc *);
96
97static const struct mii_phydesc rgephys[] = {
98 MII_PHY_DESC(xxREALTEK, RTL8169S),
99 MII_PHY_END
100};

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

108
109static int
110rgephy_attach(device_t dev)
111{
112 struct rgephy_softc *rsc;
113 struct mii_softc *sc;
114 struct mii_attach_args *ma;
115 struct mii_data *mii;
93static void rgephy_reset(struct mii_softc *);
94static void rgephy_loop(struct mii_softc *);
95static void rgephy_load_dspcode(struct mii_softc *);
96
97static const struct mii_phydesc rgephys[] = {
98 MII_PHY_DESC(xxREALTEK, RTL8169S),
99 MII_PHY_END
100};

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

108
109static int
110rgephy_attach(device_t dev)
111{
112 struct rgephy_softc *rsc;
113 struct mii_softc *sc;
114 struct mii_attach_args *ma;
115 struct mii_data *mii;
116 const char *sep = "";
117
118 rsc = device_get_softc(dev);
119 sc = &rsc->mii_sc;
120 ma = device_get_ivars(dev);
121 sc->mii_dev = device_get_parent(dev);
122 mii = ma->mii_data;
123 LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
124
125 sc->mii_flags = miibus_get_flags(dev);
126 sc->mii_inst = mii->mii_instance++;
127 sc->mii_phy = ma->mii_phyno;
128 sc->mii_service = rgephy_service;
129 sc->mii_pdata = mii;
130
131 rsc->mii_model = MII_MODEL(ma->mii_id2);
132 rsc->mii_revision = MII_REV(ma->mii_id2);
133
134#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
116
117 rsc = device_get_softc(dev);
118 sc = &rsc->mii_sc;
119 ma = device_get_ivars(dev);
120 sc->mii_dev = device_get_parent(dev);
121 mii = ma->mii_data;
122 LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
123
124 sc->mii_flags = miibus_get_flags(dev);
125 sc->mii_inst = mii->mii_instance++;
126 sc->mii_phy = ma->mii_phyno;
127 sc->mii_service = rgephy_service;
128 sc->mii_pdata = mii;
129
130 rsc->mii_model = MII_MODEL(ma->mii_id2);
131 rsc->mii_revision = MII_REV(ma->mii_id2);
132
133#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
135#define PRINT(s) printf("%s%s", sep, s); sep = ", "
136
137#if 0
138 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
139 MII_MEDIA_100_TX);
140#endif
141
134
135#if 0
136 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
137 MII_MEDIA_100_TX);
138#endif
139
142 sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
143 sc->mii_capabilities &= ~BMSR_ANEG;
140 /* RTL8169S do not report auto-sense; add manually. */
141 sc->mii_capabilities = (PHY_READ(sc, MII_BMSR) | BMSR_ANEG) &
142 ma->mii_capmask;
144 if (sc->mii_capabilities & BMSR_EXTSTAT)
145 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
143 if (sc->mii_capabilities & BMSR_EXTSTAT)
144 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
146
147 device_printf(dev, " ");
148 mii_phy_add_media(sc);
145 device_printf(dev, " ");
146 mii_phy_add_media(sc);
149 /* RTL8169S do not report auto-sense; add manually. */
150 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), MII_NMEDIA);
151 sep = ", ";
152 PRINT("auto");
153 printf("\n");
154#undef ADD
147 printf("\n");
148#undef ADD
155#undef PRINT
156
157 rgephy_reset(sc);
158 MIIBUS_MEDIAINIT(sc->mii_dev);
159 return (0);
160}
161
162static int
163rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)

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

177 * If the interface is not up, don't do anything.
178 */
179 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
180 break;
181
182 rgephy_reset(sc); /* XXX hardware bug work-around */
183
184 anar = PHY_READ(sc, RGEPHY_MII_ANAR);
149
150 rgephy_reset(sc);
151 MIIBUS_MEDIAINIT(sc->mii_dev);
152 return (0);
153}
154
155static int
156rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)

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

170 * If the interface is not up, don't do anything.
171 */
172 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
173 break;
174
175 rgephy_reset(sc); /* XXX hardware bug work-around */
176
177 anar = PHY_READ(sc, RGEPHY_MII_ANAR);
185 anar &= ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
178 anar &= ~(RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP |
179 RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
186 RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10);
187
188 switch (IFM_SUBTYPE(ife->ifm_media)) {
189 case IFM_AUTO:
190#ifdef foo
191 /*
192 * If we're already in auto mode, just return.
193 */
194 if (PHY_READ(sc, RGEPHY_MII_BMCR) & RGEPHY_BMCR_AUTOEN)
195 return (0);
196#endif
180 RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10);
181
182 switch (IFM_SUBTYPE(ife->ifm_media)) {
183 case IFM_AUTO:
184#ifdef foo
185 /*
186 * If we're already in auto mode, just return.
187 */
188 if (PHY_READ(sc, RGEPHY_MII_BMCR) & RGEPHY_BMCR_AUTOEN)
189 return (0);
190#endif
197 (void) rgephy_mii_phy_auto(sc);
191 (void)rgephy_mii_phy_auto(sc, ife->ifm_media);
198 break;
199 case IFM_1000_T:
200 speed = RGEPHY_S1000;
201 goto setit;
202 case IFM_100_TX:
203 speed = RGEPHY_S100;
204 anar |= RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX;
205 goto setit;

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

217 anar &=
218 ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_10_FD);
219 }
220
221 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) {
222 PHY_WRITE(sc, RGEPHY_MII_1000CTL, 0);
223 PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
224 PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
192 break;
193 case IFM_1000_T:
194 speed = RGEPHY_S1000;
195 goto setit;
196 case IFM_100_TX:
197 speed = RGEPHY_S100;
198 anar |= RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX;
199 goto setit;

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

211 anar &=
212 ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_10_FD);
213 }
214
215 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) {
216 PHY_WRITE(sc, RGEPHY_MII_1000CTL, 0);
217 PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
218 PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
225 RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
219 RGEPHY_BMCR_AUTOEN |
220 RGEPHY_BMCR_STARTNEG);
226 break;
227 }
228
221 break;
222 }
223
229 /*
230 * When setting the link manually, one side must
231 * be the master and the other the slave. However
232 * ifmedia doesn't give us a good way to specify
233 * this, so we fake it by using one of the LINK
234 * flags. If LINK0 is set, we program the PHY to
235 * be a master, otherwise it's a slave.
236 */
237 if ((mii->mii_ifp->if_flags & IFF_LINK0)) {
238 PHY_WRITE(sc, RGEPHY_MII_1000CTL,
239 gig|RGEPHY_1000CTL_MSE|RGEPHY_1000CTL_MSC);
240 } else {
241 PHY_WRITE(sc, RGEPHY_MII_1000CTL,
242 gig|RGEPHY_1000CTL_MSE);
243 }
224 if ((ife->ifm_media & IFM_FLOW) != 0 ||
225 (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
226 anar |= RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP;
227
228 gig |= RGEPHY_1000CTL_MSE;
229 if ((ife->ifm_media & IFM_ETH_MASTER) != 0)
230 gig |= RGEPHY_1000CTL_MSC;
231 PHY_WRITE(sc, RGEPHY_MII_1000CTL, gig);
232 PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
244 PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
245 RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
246 break;
247 case IFM_NONE:
233 PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
234 RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
235 break;
236 case IFM_NONE:
248 PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN);
237 PHY_WRITE(sc, MII_BMCR, BMCR_ISO | BMCR_PDOWN);
249 break;
238 break;
250 case IFM_100_T4:
251 default:
252 return (EINVAL);
253 }
254 break;
255
256 case MII_TICK:
257 /*
258 * Is the interface even up?

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

292 if (sc->mii_ticks++ == 0)
293 break;
294
295 /* Only retry autonegotiation every mii_anegticks seconds. */
296 if (sc->mii_ticks <= sc->mii_anegticks)
297 return (0);
298
299 sc->mii_ticks = 0;
239 default:
240 return (EINVAL);
241 }
242 break;
243
244 case MII_TICK:
245 /*
246 * Is the interface even up?

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

280 if (sc->mii_ticks++ == 0)
281 break;
282
283 /* Only retry autonegotiation every mii_anegticks seconds. */
284 if (sc->mii_ticks <= sc->mii_anegticks)
285 return (0);
286
287 sc->mii_ticks = 0;
300 rgephy_mii_phy_auto(sc);
288 rgephy_mii_phy_auto(sc, ife->ifm_media);
301 break;
302 }
303
304 /* Update the media status. */
305 rgephy_status(sc);
306
307 /*
308 * Callback if something changed. Note that we need to poke

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

390 mii->mii_media_active |= IFM_10_T;
391 else
392 mii->mii_media_active |= IFM_NONE;
393 if (bmsr & RL_GMEDIASTAT_FDX)
394 mii->mii_media_active |= IFM_FDX;
395 else
396 mii->mii_media_active |= IFM_HDX;
397 }
289 break;
290 }
291
292 /* Update the media status. */
293 rgephy_status(sc);
294
295 /*
296 * Callback if something changed. Note that we need to poke

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

378 mii->mii_media_active |= IFM_10_T;
379 else
380 mii->mii_media_active |= IFM_NONE;
381 if (bmsr & RL_GMEDIASTAT_FDX)
382 mii->mii_media_active |= IFM_FDX;
383 else
384 mii->mii_media_active |= IFM_HDX;
385 }
386
387 if ((mii->mii_media_active & IFM_FDX) != 0)
388 mii->mii_media_active |= mii_phy_flowstatus(sc);
389
390 if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) &&
391 (PHY_READ(sc, RGEPHY_MII_1000STS) & RGEPHY_1000STS_MSR) != 0)
392 mii->mii_media_active |= IFM_ETH_MASTER;
398}
399
400static int
393}
394
395static int
401rgephy_mii_phy_auto(struct mii_softc *mii)
396rgephy_mii_phy_auto(struct mii_softc *sc, int media)
402{
397{
398 int anar;
403
399
404 rgephy_loop(mii);
405 rgephy_reset(mii);
400 rgephy_loop(sc);
401 rgephy_reset(sc);
406
402
407 PHY_WRITE(mii, RGEPHY_MII_ANAR,
408 BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
403 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
404 if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
405 anar |= RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP;
406 PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
409 DELAY(1000);
407 DELAY(1000);
410 PHY_WRITE(mii, RGEPHY_MII_1000CTL,
411 RGEPHY_1000CTL_AHD|RGEPHY_1000CTL_AFD);
408 PHY_WRITE(sc, RGEPHY_MII_1000CTL,
409 RGEPHY_1000CTL_AHD | RGEPHY_1000CTL_AFD);
412 DELAY(1000);
410 DELAY(1000);
413 PHY_WRITE(mii, RGEPHY_MII_BMCR,
411 PHY_WRITE(sc, RGEPHY_MII_BMCR,
414 RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
415 DELAY(100);
416
417 return (EJUSTRETURN);
418}
419
420static void
421rgephy_loop(struct mii_softc *sc)

--- 106 unchanged lines hidden ---
412 RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
413 DELAY(100);
414
415 return (EJUSTRETURN);
416}
417
418static void
419rgephy_loop(struct mii_softc *sc)

--- 106 unchanged lines hidden ---