This source file includes following definitions.
- rgephymatch
- rgephyattach
- rgephy_service
- rgephy_status
- rgephy_mii_phy_auto
- rgephy_loop
- rgephy_load_dspcode
- rgephy_reset
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/device.h>
44 #include <sys/socket.h>
45 #include <sys/timeout.h>
46 #include <sys/errno.h>
47
48 #include <net/if.h>
49 #include <net/if_media.h>
50
51 #ifdef INET
52 #include <netinet/in.h>
53 #include <netinet/if_ether.h>
54 #endif
55
56 #include <dev/pci/pcivar.h>
57
58 #include <dev/mii/mii.h>
59 #include <dev/mii/miivar.h>
60 #include <dev/mii/miidevs.h>
61
62 #include <dev/mii/rgephyreg.h>
63
64 #include <machine/bus.h>
65
66 #include <dev/ic/rtl81x9reg.h>
67
68 int rgephymatch(struct device *, void *, void *);
69 void rgephyattach(struct device *, struct device *, void *);
70
71 struct cfattach rgephy_ca = {
72 sizeof(struct mii_softc),
73 rgephymatch,
74 rgephyattach,
75 mii_phy_detach,
76 mii_phy_activate
77 };
78
79 struct cfdriver rgephy_cd = {
80 NULL, "rgephy", DV_DULL
81 };
82
83 int rgephy_service(struct mii_softc *, struct mii_data *, int);
84 void rgephy_status(struct mii_softc *);
85 int rgephy_mii_phy_auto(struct mii_softc *);
86 void rgephy_reset(struct mii_softc *);
87 void rgephy_loop(struct mii_softc *);
88 void rgephy_load_dspcode(struct mii_softc *);
89
90 const struct mii_phy_funcs rgephy_funcs = {
91 rgephy_service, rgephy_status, rgephy_reset,
92 };
93
94 static const struct mii_phydesc rgephys[] = {
95 { MII_OUI_REALTEK2, MII_MODEL_xxREALTEK_RTL8169S,
96 MII_STR_xxREALTEK_RTL8169S },
97 { MII_OUI_xxREALTEK, MII_MODEL_xxREALTEK_RTL8169S,
98 MII_STR_xxREALTEK_RTL8169S },
99
100 { 0, 0,
101 NULL },
102 };
103
104 int
105 rgephymatch(struct device *parent, void *match, void *aux)
106 {
107 struct mii_attach_args *ma = aux;
108
109 if (mii_phy_match(ma, rgephys) != NULL)
110 return (10);
111
112 return (0);
113 }
114
115 void
116 rgephyattach(struct device *parent, struct device *self, void *aux)
117 {
118 struct mii_softc *sc = (struct mii_softc *)self;
119 struct mii_attach_args *ma = aux;
120 struct mii_data *mii = ma->mii_data;
121 const struct mii_phydesc *mpd;
122
123 mpd = mii_phy_match(ma, rgephys);
124 printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
125
126 sc->mii_inst = mii->mii_instance;
127 sc->mii_phy = ma->mii_phyno;
128 sc->mii_funcs = &rgephy_funcs;
129 sc->mii_pdata = mii;
130 sc->mii_flags = ma->mii_flags;
131 sc->mii_anegticks = MII_ANEGTICKS_GIGE;
132
133 sc->mii_flags |= MIIF_NOISOLATE;
134
135 sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
136
137 if (sc->mii_capabilities & BMSR_EXTSTAT)
138 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
139 if ((sc->mii_capabilities & BMSR_MEDIAMASK) ||
140 (sc->mii_extcapabilities & EXTSR_MEDIAMASK))
141 mii_phy_add_media(sc);
142
143 PHY_RESET(sc);
144 }
145
146 int
147 rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
148 {
149 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
150 int anar, reg, speed, gig = 0;
151
152 switch (cmd) {
153 case MII_POLLSTAT:
154
155
156
157 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
158 return (0);
159 break;
160
161 case MII_MEDIACHG:
162
163
164
165
166 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
167 reg = PHY_READ(sc, MII_BMCR);
168 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
169 return (0);
170 }
171
172
173
174
175 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
176 break;
177
178 PHY_RESET(sc);
179
180 anar = PHY_READ(sc, RGEPHY_MII_ANAR);
181 anar &= ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
182 RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10);
183
184 switch (IFM_SUBTYPE(ife->ifm_media)) {
185 case IFM_AUTO:
186 (void) rgephy_mii_phy_auto(sc);
187 break;
188 case IFM_1000_T:
189 speed = RGEPHY_S1000;
190 goto setit;
191 case IFM_100_TX:
192 speed = RGEPHY_S100;
193 anar |= RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX;
194 goto setit;
195 case IFM_10_T:
196 speed = RGEPHY_S10;
197 anar |= RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10;
198 setit:
199 rgephy_loop(sc);
200 if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
201 speed |= RGEPHY_BMCR_FDX;
202 if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T)
203 gig = RGEPHY_1000CTL_AFD;
204 anar &= ~(RGEPHY_ANAR_TX | RGEPHY_ANAR_10);
205 } else {
206 if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T)
207 gig = RGEPHY_1000CTL_AHD;
208 anar &=
209 ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_10_FD);
210 }
211
212 if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T &&
213 mii->mii_media.ifm_media & IFM_ETH_MASTER)
214 gig |= RGEPHY_1000CTL_MSE|RGEPHY_1000CTL_MSC;
215
216 PHY_WRITE(sc, RGEPHY_MII_1000CTL, gig);
217 PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
218 RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
219 PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
220 break;
221 #if 0
222 case IFM_NONE:
223 PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN);
224 break;
225 #endif
226 case IFM_100_T4:
227 default:
228 return (EINVAL);
229 }
230 break;
231
232 case MII_TICK:
233
234
235
236 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
237 return (0);
238
239
240
241
242 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
243 return (0);
244
245
246
247
248 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
249 break;
250
251
252
253
254
255
256 reg = PHY_READ(sc, RL_GMEDIASTAT);
257 if (reg & RL_GMEDIASTAT_LINK)
258 break;
259
260
261
262
263 if (++sc->mii_ticks <= sc->mii_anegticks)
264 break;
265
266 sc->mii_ticks = 0;
267 rgephy_mii_phy_auto(sc);
268 return (0);
269 }
270
271
272 mii_phy_status(sc);
273
274
275
276
277
278
279 if (sc->mii_media_active != mii->mii_media_active ||
280 sc->mii_media_status != mii->mii_media_status ||
281 cmd == MII_MEDIACHG)
282 rgephy_load_dspcode(sc);
283
284
285 mii_phy_update(sc, cmd);
286
287 return (0);
288 }
289
290 void
291 rgephy_status(struct mii_softc *sc)
292 {
293 struct mii_data *mii = sc->mii_pdata;
294 int bmsr, bmcr, gtsr;
295
296 mii->mii_media_status = IFM_AVALID;
297 mii->mii_media_active = IFM_ETHER;
298
299 bmsr = PHY_READ(sc, RL_GMEDIASTAT);
300
301 if (bmsr & RL_GMEDIASTAT_LINK)
302 mii->mii_media_status |= IFM_ACTIVE;
303 bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
304
305 bmcr = PHY_READ(sc, RGEPHY_MII_BMCR);
306
307 if (bmcr & RGEPHY_BMCR_LOOP)
308 mii->mii_media_active |= IFM_LOOP;
309
310 if (bmcr & RGEPHY_BMCR_AUTOEN) {
311 if ((bmsr & RGEPHY_BMSR_ACOMP) == 0) {
312
313 mii->mii_media_active |= IFM_NONE;
314 return;
315 }
316 }
317
318 bmsr = PHY_READ(sc, RL_GMEDIASTAT);
319 if (bmsr & RL_GMEDIASTAT_1000MBPS)
320 mii->mii_media_active |= IFM_1000_T;
321 else if (bmsr & RL_GMEDIASTAT_100MBPS)
322 mii->mii_media_active |= IFM_100_TX;
323 else if (bmsr & RL_GMEDIASTAT_10MBPS)
324 mii->mii_media_active |= IFM_10_T;
325
326 if (bmsr & RL_GMEDIASTAT_FDX)
327 mii->mii_media_active |= mii_phy_flowstatus(sc) | IFM_FDX;
328 else
329 mii->mii_media_active |= IFM_HDX;
330
331 gtsr = PHY_READ(sc, RGEPHY_MII_1000STS);
332 if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) &&
333 gtsr & RGEPHY_1000STS_MSR)
334 mii->mii_media_active |= IFM_ETH_MASTER;
335 }
336
337
338 int
339 rgephy_mii_phy_auto(struct mii_softc *sc)
340 {
341 int anar;
342
343 rgephy_loop(sc);
344 PHY_RESET(sc);
345
346 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
347 if (sc->mii_flags & MIIF_DOPAUSE)
348 anar |= RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP;
349
350 PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
351 DELAY(1000);
352 PHY_WRITE(sc, RGEPHY_MII_1000CTL,
353 RGEPHY_1000CTL_AHD | RGEPHY_1000CTL_AFD);
354 DELAY(1000);
355 PHY_WRITE(sc, RGEPHY_MII_BMCR,
356 RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
357 DELAY(100);
358
359 return (EJUSTRETURN);
360 }
361
362 void
363 rgephy_loop(struct mii_softc *sc)
364 {
365 u_int32_t bmsr;
366 int i;
367
368 PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_PDOWN);
369 DELAY(1000);
370
371 for (i = 0; i < 15000; i++) {
372 bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
373 if (!(bmsr & RGEPHY_BMSR_LINK))
374 break;
375 DELAY(10);
376 }
377 }
378
379 #define PHY_SETBIT(x, y, z) \
380 PHY_WRITE(x, y, (PHY_READ(x, y) | (z)))
381 #define PHY_CLRBIT(x, y, z) \
382 PHY_WRITE(x, y, (PHY_READ(x, y) & ~(z)))
383
384
385
386
387
388
389
390
391 void
392 rgephy_load_dspcode(struct mii_softc *sc)
393 {
394 int val;
395 u_int16_t id2;
396
397 id2 = PHY_READ(sc, MII_PHYIDR2);
398 if (MII_REV(id2) > 1)
399 return;
400
401 PHY_WRITE(sc, 31, 0x0001);
402 PHY_WRITE(sc, 21, 0x1000);
403 PHY_WRITE(sc, 24, 0x65C7);
404 PHY_CLRBIT(sc, 4, 0x0800);
405 val = PHY_READ(sc, 4) & 0xFFF;
406 PHY_WRITE(sc, 4, val);
407 PHY_WRITE(sc, 3, 0x00A1);
408 PHY_WRITE(sc, 2, 0x0008);
409 PHY_WRITE(sc, 1, 0x1020);
410 PHY_WRITE(sc, 0, 0x1000);
411 PHY_SETBIT(sc, 4, 0x0800);
412 PHY_CLRBIT(sc, 4, 0x0800);
413 val = (PHY_READ(sc, 4) & 0xFFF) | 0x7000;
414 PHY_WRITE(sc, 4, val);
415 PHY_WRITE(sc, 3, 0xFF41);
416 PHY_WRITE(sc, 2, 0xDE60);
417 PHY_WRITE(sc, 1, 0x0140);
418 PHY_WRITE(sc, 0, 0x0077);
419 val = (PHY_READ(sc, 4) & 0xFFF) | 0xA000;
420 PHY_WRITE(sc, 4, val);
421 PHY_WRITE(sc, 3, 0xDF01);
422 PHY_WRITE(sc, 2, 0xDF20);
423 PHY_WRITE(sc, 1, 0xFF95);
424 PHY_WRITE(sc, 0, 0xFA00);
425 val = (PHY_READ(sc, 4) & 0xFFF) | 0xB000;
426 PHY_WRITE(sc, 4, val);
427 PHY_WRITE(sc, 3, 0xFF41);
428 PHY_WRITE(sc, 2, 0xDE20);
429 PHY_WRITE(sc, 1, 0x0140);
430 PHY_WRITE(sc, 0, 0x00BB);
431 val = (PHY_READ(sc, 4) & 0xFFF) | 0xF000;
432 PHY_WRITE(sc, 4, val);
433 PHY_WRITE(sc, 3, 0xDF01);
434 PHY_WRITE(sc, 2, 0xDF20);
435 PHY_WRITE(sc, 1, 0xFF95);
436 PHY_WRITE(sc, 0, 0xBF00);
437 PHY_SETBIT(sc, 4, 0x0800);
438 PHY_CLRBIT(sc, 4, 0x0800);
439 PHY_WRITE(sc, 31, 0x0000);
440
441 DELAY(40);
442 }
443
444 void
445 rgephy_reset(struct mii_softc *sc)
446 {
447 mii_phy_reset(sc);
448 DELAY(1000);
449 rgephy_load_dspcode(sc);
450 }