This source file includes following definitions.
- eephymatch
- eephyattach
- eephy_reset
- eephy_service
- eephy_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
36
37
38
39
40
41
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/device.h>
47 #include <sys/socket.h>
48 #include <sys/proc.h>
49
50 #include <net/if.h>
51 #include <net/if_media.h>
52
53 #include <dev/mii/mii.h>
54 #include <dev/mii/miivar.h>
55 #include <dev/mii/miidevs.h>
56
57 #include <dev/mii/eephyreg.h>
58
59 int eephy_service(struct mii_softc *, struct mii_data *, int);
60 void eephy_status(struct mii_softc *);
61 int eephymatch(struct device *, void *, void *);
62 void eephyattach(struct device *, struct device *, void *);
63
64 struct cfattach eephy_ca = {
65 sizeof (struct mii_softc), eephymatch, eephyattach,
66 mii_phy_detach, mii_phy_activate
67 };
68
69 struct cfdriver eephy_cd = {
70 NULL, "eephy", DV_DULL
71 };
72
73 int eephy_mii_phy_auto(struct mii_softc *);
74 void eephy_reset(struct mii_softc *);
75
76 const struct mii_phy_funcs eephy_funcs = {
77 eephy_service, eephy_status, eephy_reset,
78 };
79
80 static const struct mii_phydesc eephys[] = {
81 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000_1,
82 MII_STR_MARVELL_E1000_1 },
83 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000_2,
84 MII_STR_MARVELL_E1000_2 },
85 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000_3,
86 MII_STR_MARVELL_E1000_3 },
87 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000_4,
88 MII_STR_MARVELL_E1000_4 },
89 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000S,
90 MII_STR_MARVELL_E1000S },
91 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1011,
92 MII_STR_MARVELL_E1011 },
93 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1111,
94 MII_STR_MARVELL_E1111 },
95 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1112,
96 MII_STR_MARVELL_E1112 },
97 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1116,
98 MII_STR_MARVELL_E1116 },
99 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1118,
100 MII_STR_MARVELL_E1118 },
101 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1149,
102 MII_STR_MARVELL_E1149 },
103 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E3082,
104 MII_STR_MARVELL_E3082 },
105 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1000_5,
106 MII_STR_xxMARVELL_E1000_5 },
107 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1000_6,
108 MII_STR_xxMARVELL_E1000_6 },
109 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1000_7,
110 MII_STR_xxMARVELL_E1000_7 },
111 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1111,
112 MII_STR_xxMARVELL_E1111 },
113
114 { 0, 0,
115 NULL },
116 };
117
118 int
119 eephymatch(struct device *parent, void *match, void *aux)
120 {
121 struct mii_attach_args *ma = aux;
122
123 if (mii_phy_match(ma, eephys) != NULL)
124 return (10);
125
126 return (0);
127 }
128
129 void
130 eephyattach(struct device *parent, struct device *self, void *aux)
131 {
132 struct mii_softc *sc = (struct mii_softc *)self;
133 struct mii_attach_args *ma = aux;
134 struct mii_data *mii = ma->mii_data;
135 const struct mii_phydesc *mpd;
136 int reg, page;
137
138 mpd = mii_phy_match(ma, eephys);
139 printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
140
141 sc->mii_inst = mii->mii_instance;
142 sc->mii_phy = ma->mii_phyno;
143 sc->mii_funcs = &eephy_funcs;
144 sc->mii_model = MII_MODEL(ma->mii_id2);
145 sc->mii_pdata = mii;
146 sc->mii_flags = ma->mii_flags;
147
148
149 sc->mii_flags |= MIIF_NOLOOP;
150
151
152 if (sc->mii_model == MII_MODEL_MARVELL_E1112 &&
153 sc->mii_flags & MIIF_HAVEFIBER) {
154 page = PHY_READ(sc, E1000_EADR);
155 PHY_WRITE(sc, E1000_EADR, 2);
156 reg = PHY_READ(sc, E1000_SCR);
157 reg &= ~E1000_SCR_MODE_MASK;
158 reg |= E1000_SCR_MODE_1000BX;
159 PHY_WRITE(sc, E1000_SCR, reg);
160 PHY_WRITE(sc, E1000_EADR, page);
161
162 PHY_RESET(sc);
163 }
164
165 sc->mii_capabilities = PHY_READ(sc, E1000_SR) & ma->mii_capmask;
166 if (sc->mii_capabilities & BMSR_EXTSTAT)
167 sc->mii_extcapabilities = PHY_READ(sc, E1000_ESR);
168
169 mii_phy_add_media(sc);
170
171
172
173
174
175 reg = PHY_READ(sc, E1000_SCR);
176
177
178 reg |= E1000_SCR_ASSERT_CRS_ON_TX;
179
180
181 switch (sc->mii_model) {
182 case MII_MODEL_MARVELL_E3082:
183
184 reg |= (E1000_SCR_AUTO_X_MODE >> 1);
185 break;
186 default:
187
188 if (sc->mii_flags & MIIF_IS_1000X)
189 reg &= ~E1000_SCR_AUTO_X_MODE;
190 else
191 reg |= E1000_SCR_AUTO_X_MODE;
192 }
193
194
195 switch(sc->mii_model) {
196 case MII_MODEL_MARVELL_E1011:
197 case MII_MODEL_MARVELL_E1111:
198 case MII_MODEL_MARVELL_E1112:
199
200 reg &= ~E1000_SCR_EN_DETECT_MASK;
201 break;
202 }
203
204 PHY_WRITE(sc, E1000_SCR, reg);
205
206
207 reg = PHY_READ(sc, E1000_ESCR);
208 reg |= E1000_ESCR_TX_CLK_25;
209 PHY_WRITE(sc, E1000_ESCR, reg);
210
211
212
213
214
215
216 reg = PHY_READ(sc, E1000_CR);
217 reg &= ~E1000_CR_AUTO_NEG_ENABLE;
218 PHY_WRITE(sc, E1000_CR, reg | E1000_CR_RESET);
219 }
220
221 void
222 eephy_reset(struct mii_softc *sc)
223 {
224 int reg, i;
225
226 reg = PHY_READ(sc, E1000_CR);
227 reg |= E1000_CR_RESET;
228 PHY_WRITE(sc, E1000_CR, reg);
229
230 for (i = 0; i < 500; i++) {
231 DELAY(1);
232 reg = PHY_READ(sc, E1000_CR);
233 if (!(reg & E1000_CR_RESET))
234 break;
235 }
236 }
237
238 int
239 eephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
240 {
241 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
242 int bmcr;
243
244 if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
245 return (ENXIO);
246
247 switch (cmd) {
248 case MII_POLLSTAT:
249
250
251
252 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
253 return (0);
254 break;
255
256 case MII_MEDIACHG:
257
258
259
260
261 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
262 bmcr = PHY_READ(sc, E1000_CR);
263 PHY_WRITE(sc, E1000_CR, bmcr | E1000_CR_ISOLATE);
264 return (0);
265 }
266
267
268
269
270 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
271 break;
272
273 mii_phy_setmedia(sc);
274
275
276
277
278
279 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
280 bmcr = PHY_READ(sc, E1000_CR);
281 PHY_WRITE(sc, E1000_CR, bmcr | E1000_CR_RESET);
282 }
283 break;
284
285 case MII_TICK:
286
287
288
289 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
290 return (0);
291
292 if (mii_phy_tick(sc) == EJUSTRETURN)
293 return (0);
294 break;
295
296 case MII_DOWN:
297 mii_phy_down(sc);
298 return (0);
299 }
300
301
302 mii_phy_status(sc);
303
304
305 mii_phy_update(sc, cmd);
306 return (0);
307 }
308
309 void
310 eephy_status(struct mii_softc *sc)
311 {
312 struct mii_data *mii = sc->mii_pdata;
313 int bmcr, gsr, ssr;
314
315 mii->mii_media_status = IFM_AVALID;
316 mii->mii_media_active = IFM_ETHER;
317
318 bmcr = PHY_READ(sc, E1000_CR);
319 ssr = PHY_READ(sc, E1000_SSR);
320
321 if (ssr & E1000_SSR_LINK)
322 mii->mii_media_status |= IFM_ACTIVE;
323
324 if (bmcr & E1000_CR_LOOPBACK)
325 mii->mii_media_active |= IFM_LOOP;
326
327 if (!(ssr & E1000_SSR_SPD_DPLX_RESOLVED)) {
328
329 mii->mii_media_active |= IFM_NONE;
330 return;
331 }
332
333 if (sc->mii_flags & MIIF_IS_1000X) {
334 mii->mii_media_active |= IFM_1000_SX;
335 } else {
336 if (ssr & E1000_SSR_1000MBS)
337 mii->mii_media_active |= IFM_1000_T;
338 else if (ssr & E1000_SSR_100MBS)
339 mii->mii_media_active |= IFM_100_TX;
340 else
341 mii->mii_media_active |= IFM_10_T;
342 }
343
344 if (ssr & E1000_SSR_DUPLEX)
345 mii->mii_media_active |= mii_phy_flowstatus(sc) | IFM_FDX;
346 else
347 mii->mii_media_active |= IFM_HDX;
348
349 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
350 gsr = PHY_READ(sc, E1000_1GSR) | PHY_READ(sc, E1000_1GSR);
351 if (gsr & E1000_1GSR_MS_CONFIG_RES)
352 mii->mii_media_active |= IFM_ETH_MASTER;
353 }
354 }