This source file includes following definitions.
- rlphymatch
- rlphyattach
- rlphy_service
- rlphy_status
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 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/device.h>
39 #include <sys/socket.h>
40 #include <sys/timeout.h>
41 #include <sys/errno.h>
42
43 #include <net/if.h>
44 #include <net/if_media.h>
45 #include <netinet/in.h>
46 #include <netinet/if_ether.h>
47
48 #include <dev/mii/mii.h>
49 #include <dev/mii/miivar.h>
50 #include <dev/mii/miidevs.h>
51 #include <machine/bus.h>
52 #include <dev/ic/rtl81x9reg.h>
53
54 int rlphymatch(struct device *, void *, void *);
55 void rlphyattach(struct device *, struct device *, void *);
56
57 struct cfattach rlphy_ca = {
58 sizeof(struct mii_softc), rlphymatch, rlphyattach, mii_phy_detach,
59 mii_phy_activate
60 };
61
62 struct cfdriver rlphy_cd = {
63 NULL, "rlphy", DV_DULL
64 };
65
66 int rlphy_service(struct mii_softc *, struct mii_data *, int);
67 void rlphy_status(struct mii_softc *);
68
69 const struct mii_phy_funcs rlphy_funcs = {
70 rlphy_service, rlphy_status, mii_phy_reset,
71 };
72
73 static const struct mii_phydesc rlphys[] = {
74 { MII_OUI_REALTEK, MII_MODEL_REALTEK_RTL8201L,
75 MII_STR_REALTEK_RTL8201L },
76 { MII_OUI_ICPLUS, MII_MODEL_ICPLUS_IP101,
77 MII_STR_ICPLUS_IP101 },
78
79 { 0, 0,
80 NULL },
81 };
82 int
83 rlphymatch(struct device *parent, void *match, void *aux)
84 {
85 struct mii_attach_args *ma = aux;
86 char *devname;
87
88 devname = parent->dv_cfdata->cf_driver->cd_name;
89
90 if (mii_phy_match(ma, rlphys) != NULL)
91 return (10);
92
93 if (MII_OUI(ma->mii_id1, ma->mii_id2) != 0 ||
94 MII_MODEL(ma->mii_id2) != 0)
95 return (0);
96
97 if ((strcmp(devname, "re") != 0) &&
98 (strcmp(devname, "rl") != 0))
99 return (0);
100
101
102
103
104
105 return (5);
106 }
107
108 void
109 rlphyattach(struct device *parent, struct device *self, void *aux)
110 {
111 struct mii_softc *sc = (struct mii_softc *)self;
112 struct mii_attach_args *ma = aux;
113 struct mii_data *mii = ma->mii_data;
114 const struct mii_phydesc *mpd;
115
116 mpd = mii_phy_match(ma, rlphys);
117 if (mpd != NULL) {
118 printf(": %s, rev. %d\n", mpd->mpd_name,
119 MII_REV(ma->mii_id2));
120 } else
121 printf(": RTL internal PHY\n");
122
123 sc->mii_inst = mii->mii_instance;
124 sc->mii_phy = ma->mii_phyno;
125 sc->mii_funcs = &rlphy_funcs;
126 sc->mii_pdata = mii;
127 sc->mii_flags = ma->mii_flags;
128
129 sc->mii_flags |= MIIF_NOISOLATE;
130
131 PHY_RESET(sc);
132
133 sc->mii_capabilities =
134 PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
135 if (sc->mii_capabilities & BMSR_MEDIAMASK)
136 mii_phy_add_media(sc);
137 }
138
139 int
140 rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
141 {
142 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
143
144 if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
145 return (ENXIO);
146
147
148
149
150 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
151 panic("rlphy_service: attempt to isolate phy");
152
153 switch (cmd) {
154 case MII_POLLSTAT:
155 break;
156
157 case MII_MEDIACHG:
158
159
160
161 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
162 break;
163
164 switch (IFM_SUBTYPE(ife->ifm_media)) {
165 case IFM_AUTO:
166
167
168
169 if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
170 return (0);
171 (void) mii_phy_auto(sc, 0);
172 break;
173 case IFM_100_T4:
174
175
176
177 return (EINVAL);
178 default:
179
180
181
182 PHY_WRITE(sc, MII_ANAR,
183 mii_anar(ife->ifm_media));
184 PHY_WRITE(sc, MII_BMCR, ife->ifm_data);
185 }
186 break;
187
188 case MII_TICK:
189
190
191
192 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
193 return (0);
194
195
196
197
198 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
199 break;
200
201
202
203
204
205 break;
206
207 case MII_DOWN:
208 mii_phy_down(sc);
209 return (0);
210 }
211
212
213 mii_phy_status(sc);
214
215
216 mii_phy_update(sc, cmd);
217 return (0);
218 }
219
220 void
221 rlphy_status(struct mii_softc *sc)
222 {
223 struct mii_data *mii = sc->mii_pdata;
224 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
225 int bmsr, bmcr, anlpar;
226 char *devname;
227
228 devname = sc->mii_dev.dv_parent->dv_cfdata->cf_driver->cd_name;
229
230 mii->mii_media_status = IFM_AVALID;
231 mii->mii_media_active = IFM_ETHER;
232
233 bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
234 if (bmsr & BMSR_LINK)
235 mii->mii_media_status |= IFM_ACTIVE;
236
237 bmcr = PHY_READ(sc, MII_BMCR);
238 if (bmcr & BMCR_ISO) {
239 mii->mii_media_active |= IFM_NONE;
240 mii->mii_media_status = 0;
241 return;
242 }
243
244 if (bmcr & BMCR_LOOP)
245 mii->mii_media_active |= IFM_LOOP;
246
247 if (bmcr & BMCR_AUTOEN) {
248
249
250
251
252
253 if ((bmsr & BMSR_ACOMP) == 0) {
254
255 mii->mii_media_active |= IFM_NONE;
256 return;
257 }
258
259 if ((anlpar = PHY_READ(sc, MII_ANAR) &
260 PHY_READ(sc, MII_ANLPAR))) {
261 if (anlpar & ANLPAR_T4)
262 mii->mii_media_active |= IFM_100_T4|IFM_HDX;
263 else if (anlpar & ANLPAR_TX_FD)
264 mii->mii_media_active |= IFM_100_TX|IFM_FDX;
265 else if (anlpar & ANLPAR_TX)
266 mii->mii_media_active |= IFM_100_TX|IFM_HDX;
267 else if (anlpar & ANLPAR_10_FD)
268 mii->mii_media_active |= IFM_10_T|IFM_FDX;
269 else if (anlpar & ANLPAR_10)
270 mii->mii_media_active |= IFM_10_T|IFM_HDX;
271 else
272 mii->mii_media_active |= IFM_NONE;
273 return;
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303 if (strcmp("rl", devname) == 0 ||
304 strcmp("re", devname) == 0) {
305 if (PHY_READ(sc, RL_MEDIASTAT) & RL_MEDIASTAT_SPEED10)
306 mii->mii_media_active |= IFM_10_T;
307 else
308 mii->mii_media_active |= IFM_100_TX;
309 } else {
310 if (PHY_READ(sc, 0x0019) & 0x01)
311 mii->mii_media_active |= IFM_100_TX;
312 else
313 mii->mii_media_active |= IFM_10_T;
314 }
315 mii->mii_media_active |= IFM_HDX;
316 } else
317 mii->mii_media_active = ife->ifm_media;
318 }