1 | /* $NetBSD: igphy.c,v 1.26 2016/07/07 06:55:41 msaitoh Exp $ */ |
2 | |
3 | /* |
4 | * The Intel copyright applies to the analog register setup, and the |
5 | * (currently disabled) SmartSpeed workaround code. |
6 | */ |
7 | |
8 | /******************************************************************************* |
9 | |
10 | Copyright (c) 2001-2003, Intel Corporation |
11 | All rights reserved. |
12 | |
13 | Redistribution and use in source and binary forms, with or without |
14 | modification, are permitted provided that the following conditions are met: |
15 | |
16 | 1. Redistributions of source code must retain the above copyright notice, |
17 | this list of conditions and the following disclaimer. |
18 | |
19 | 2. Redistributions in binary form must reproduce the above copyright |
20 | notice, this list of conditions and the following disclaimer in the |
21 | documentation and/or other materials provided with the distribution. |
22 | |
23 | 3. Neither the name of the Intel Corporation nor the names of its |
24 | contributors may be used to endorse or promote products derived from |
25 | this software without specific prior written permission. |
26 | |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
28 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
29 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
30 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
31 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
32 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
33 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
34 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
35 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
36 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
37 | POSSIBILITY OF SUCH DAMAGE. |
38 | |
39 | *******************************************************************************/ |
40 | |
41 | |
42 | /*- |
43 | * Copyright (c) 1998, 1999, 2000, 2003 The NetBSD Foundation, Inc. |
44 | * All rights reserved. |
45 | * |
46 | * This code is derived from software contributed to The NetBSD Foundation |
47 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, |
48 | * NASA Ames Research Center, and by Frank van der Linden. |
49 | * |
50 | * Redistribution and use in source and binary forms, with or without |
51 | * modification, are permitted provided that the following conditions |
52 | * are met: |
53 | * 1. Redistributions of source code must retain the above copyright |
54 | * notice, this list of conditions and the following disclaimer. |
55 | * 2. Redistributions in binary form must reproduce the above copyright |
56 | * notice, this list of conditions and the following disclaimer in the |
57 | * documentation and/or other materials provided with the distribution. |
58 | * |
59 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
60 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
61 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
62 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
63 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
64 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
65 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
66 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
67 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
68 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
69 | * POSSIBILITY OF SUCH DAMAGE. |
70 | */ |
71 | |
72 | #include <sys/cdefs.h> |
73 | __KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.26 2016/07/07 06:55:41 msaitoh Exp $" ); |
74 | |
75 | #ifdef _KERNEL_OPT |
76 | #include "opt_mii.h" |
77 | #endif |
78 | |
79 | #include <sys/param.h> |
80 | #include <sys/systm.h> |
81 | #include <sys/kernel.h> |
82 | #include <sys/device.h> |
83 | #include <sys/socket.h> |
84 | #include <sys/errno.h> |
85 | |
86 | #include <net/if.h> |
87 | #include <net/if_media.h> |
88 | |
89 | #include <dev/mii/mii.h> |
90 | #include <dev/mii/miivar.h> |
91 | #include <dev/mii/miidevs.h> |
92 | #include <dev/mii/igphyreg.h> |
93 | #include <dev/mii/igphyvar.h> |
94 | #include <dev/pci/if_wmvar.h> |
95 | |
96 | static void igphy_reset(struct mii_softc *); |
97 | static void igphy_load_dspcode(struct mii_softc *); |
98 | static void igphy_load_dspcode_igp3(struct mii_softc *); |
99 | static void igphy_smartspeed_workaround(struct mii_softc *sc); |
100 | |
101 | static int igphymatch(device_t, cfdata_t, void *); |
102 | static void igphyattach(device_t, device_t, void *); |
103 | |
104 | CFATTACH_DECL_NEW(igphy, sizeof(struct igphy_softc), |
105 | igphymatch, igphyattach, mii_phy_detach, mii_phy_activate); |
106 | |
107 | static int igphy_service(struct mii_softc *, struct mii_data *, int); |
108 | static void igphy_status(struct mii_softc *); |
109 | |
110 | static const struct mii_phy_funcs igphy_funcs = { |
111 | igphy_service, igphy_status, igphy_reset, |
112 | }; |
113 | |
114 | static const struct mii_phydesc igphys[] = { |
115 | { MII_OUI_yyINTEL, MII_MODEL_yyINTEL_IGP01E1000, |
116 | MII_STR_yyINTEL_IGP01E1000 }, |
117 | |
118 | { MII_OUI_yyINTEL, MII_MODEL_yyINTEL_I82566, |
119 | MII_STR_yyINTEL_I82566 }, |
120 | |
121 | {0, 0, |
122 | NULL }, |
123 | }; |
124 | |
125 | static int |
126 | igphymatch(device_t parent, cfdata_t match, void *aux) |
127 | { |
128 | struct mii_attach_args *ma = aux; |
129 | |
130 | if (mii_phy_match(ma, igphys) != NULL) |
131 | return 10; |
132 | |
133 | return 0; |
134 | } |
135 | |
136 | static void |
137 | igphyattach(device_t parent, device_t self, void *aux) |
138 | { |
139 | struct mii_softc *sc = device_private(self); |
140 | struct mii_attach_args *ma = aux; |
141 | struct mii_data *mii = ma->mii_data; |
142 | const struct mii_phydesc *mpd; |
143 | struct igphy_softc *igsc = (struct igphy_softc *) sc; |
144 | prop_dictionary_t dict; |
145 | |
146 | mpd = mii_phy_match(ma, igphys); |
147 | aprint_naive(": Media interface\n" ); |
148 | aprint_normal(": %s, rev. %d\n" , mpd->mpd_name, MII_REV(ma->mii_id2)); |
149 | |
150 | dict = device_properties(parent); |
151 | if (!prop_dictionary_get_uint32(dict, "mactype" , &igsc->sc_mactype)) |
152 | aprint_error("WARNING! Failed to get mactype\n" ); |
153 | if (!prop_dictionary_get_uint32(dict, "macflags" , &igsc->sc_macflags)) |
154 | aprint_error("WARNING! Failed to get macflags\n" ); |
155 | |
156 | sc->mii_dev = self; |
157 | sc->mii_inst = mii->mii_instance; |
158 | sc->mii_phy = ma->mii_phyno; |
159 | sc->mii_mpd_oui = MII_OUI(ma->mii_id1, ma->mii_id2); |
160 | sc->mii_mpd_model = MII_MODEL(ma->mii_id2); |
161 | sc->mii_mpd_rev = MII_REV(ma->mii_id2); |
162 | sc->mii_funcs = &igphy_funcs; |
163 | sc->mii_pdata = mii; |
164 | sc->mii_flags = ma->mii_flags; |
165 | sc->mii_anegticks = MII_ANEGTICKS_GIGE; |
166 | |
167 | PHY_RESET(sc); |
168 | |
169 | sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; |
170 | if (sc->mii_capabilities & BMSR_EXTSTAT) |
171 | sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); |
172 | aprint_normal_dev(self, "" ); |
173 | if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && |
174 | (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) |
175 | aprint_error("no media present" ); |
176 | else |
177 | mii_phy_add_media(sc); |
178 | aprint_normal("\n" ); |
179 | } |
180 | |
181 | typedef struct { |
182 | int reg; |
183 | uint16_t val; |
184 | } dspcode; |
185 | |
186 | static const dspcode igp1code[] = { |
187 | { 0x1f95, 0x0001 }, |
188 | { 0x1f71, 0xbd21 }, |
189 | { 0x1f79, 0x0018 }, |
190 | { 0x1f30, 0x1600 }, |
191 | { 0x1f31, 0x0014 }, |
192 | { 0x1f32, 0x161c }, |
193 | { 0x1f94, 0x0003 }, |
194 | { 0x1f96, 0x003f }, |
195 | { 0x2010, 0x0008 }, |
196 | { 0, 0 }, |
197 | }; |
198 | |
199 | static const dspcode igp1code_r2[] = { |
200 | { 0x1f73, 0x0099 }, |
201 | { 0, 0 }, |
202 | }; |
203 | |
204 | static const dspcode igp3code[] = { |
205 | { 0x2f5b, 0x9018}, |
206 | { 0x2f52, 0x0000}, |
207 | { 0x2fb1, 0x8b24}, |
208 | { 0x2fb2, 0xf8f0}, |
209 | { 0x2010, 0x10b0}, |
210 | { 0x2011, 0x0000}, |
211 | { 0x20dd, 0x249a}, |
212 | { 0x20de, 0x00d3}, |
213 | { 0x28b4, 0x04ce}, |
214 | { 0x2f70, 0x29e4}, |
215 | { 0x0000, 0x0140}, |
216 | { 0x1f30, 0x1606}, |
217 | { 0x1f31, 0xb814}, |
218 | { 0x1f35, 0x002a}, |
219 | { 0x1f3e, 0x0067}, |
220 | { 0x1f54, 0x0065}, |
221 | { 0x1f55, 0x002a}, |
222 | { 0x1f56, 0x002a}, |
223 | { 0x1f72, 0x3fb0}, |
224 | { 0x1f76, 0xc0ff}, |
225 | { 0x1f77, 0x1dec}, |
226 | { 0x1f78, 0xf9ef}, |
227 | { 0x1f79, 0x0210}, |
228 | { 0x1895, 0x0003}, |
229 | { 0x1796, 0x0008}, |
230 | { 0x1798, 0xd008}, |
231 | { 0x1898, 0xd918}, |
232 | { 0x187a, 0x0800}, |
233 | { 0x0019, 0x008d}, |
234 | { 0x001b, 0x2080}, |
235 | { 0x0014, 0x0045}, |
236 | { 0x0000, 0x1340}, |
237 | { 0, 0 }, |
238 | }; |
239 | |
240 | /* DSP patch for igp1 and igp2 */ |
241 | static void |
242 | igphy_load_dspcode(struct mii_softc *sc) |
243 | { |
244 | struct igphy_softc *igsc = (struct igphy_softc *) sc; |
245 | const dspcode *code; |
246 | uint16_t reg; |
247 | int i; |
248 | |
249 | /* This workaround is only for 82541 and 82547 */ |
250 | switch (igsc->sc_mactype) { |
251 | case WM_T_82541: |
252 | case WM_T_82547: |
253 | code = igp1code; |
254 | break; |
255 | case WM_T_82541_2: |
256 | case WM_T_82547_2: |
257 | code = igp1code_r2; |
258 | break; |
259 | default: |
260 | return; /* byebye */ |
261 | } |
262 | |
263 | /* Delay after phy reset to enable NVM configuration to load */ |
264 | delay(20000); |
265 | |
266 | /* |
267 | * Save off the current value of register 0x2F5B to be restored at |
268 | * the end of this routine. |
269 | */ |
270 | reg = IGPHY_READ(sc, 0x2f5b); |
271 | |
272 | /* Disabled the PHY transmitter */ |
273 | IGPHY_WRITE(sc, 0x2f5b, 0x0003); |
274 | |
275 | delay(20000); |
276 | |
277 | PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000); |
278 | PHY_WRITE(sc, 0x0000, 0x0140); |
279 | |
280 | delay(5000); |
281 | |
282 | for (i = 0; !((code[i].reg == 0) && (code[i].val == 0)); i++) |
283 | IGPHY_WRITE(sc, code[i].reg, code[i].val); |
284 | |
285 | PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000); |
286 | PHY_WRITE(sc, 0x0000, 0x3300); |
287 | |
288 | delay(20000); |
289 | |
290 | /* Now enable the transmitter */ |
291 | IGPHY_WRITE(sc, 0x2f5b, reg); |
292 | } |
293 | |
294 | static void |
295 | igphy_load_dspcode_igp3(struct mii_softc *sc) |
296 | { |
297 | const dspcode *code = igp3code; |
298 | int i; |
299 | |
300 | for (i = 0; !((code[i].reg == 0) && (code[i].val == 0)); i++) |
301 | IGPHY_WRITE(sc, code[i].reg, code[i].val); |
302 | } |
303 | |
304 | static void |
305 | igphy_reset(struct mii_softc *sc) |
306 | { |
307 | struct igphy_softc *igsc = (struct igphy_softc *) sc; |
308 | uint16_t fused, fine, coarse; |
309 | |
310 | mii_phy_reset(sc); |
311 | delay(150); |
312 | |
313 | switch (igsc->sc_mactype) { |
314 | case WM_T_82541: |
315 | case WM_T_82547: |
316 | case WM_T_82541_2: |
317 | case WM_T_82547_2: |
318 | igphy_load_dspcode(sc); |
319 | break; |
320 | case WM_T_ICH8: |
321 | case WM_T_ICH9: |
322 | if ((igsc->sc_macflags & WM_F_EEPROM_INVALID) != 0) |
323 | igphy_load_dspcode_igp3(sc); |
324 | break; |
325 | default: /* Not for ICH10, PCH and 8257[12] */ |
326 | break; |
327 | } |
328 | |
329 | if (igsc->sc_mactype == WM_T_82547) { |
330 | fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_SPARE_FUSE_STATUS); |
331 | if ((fused & ANALOG_SPARE_FUSE_ENABLED) == 0) { |
332 | fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_FUSE_STATUS); |
333 | |
334 | fine = fused & ANALOG_FUSE_FINE_MASK; |
335 | coarse = fused & ANALOG_FUSE_COARSE_MASK; |
336 | |
337 | if (coarse > ANALOG_FUSE_COARSE_THRESH) { |
338 | coarse -= ANALOG_FUSE_COARSE_10; |
339 | fine -= ANALOG_FUSE_FINE_1; |
340 | } else if (coarse == ANALOG_FUSE_COARSE_THRESH) |
341 | fine -= ANALOG_FUSE_FINE_10; |
342 | |
343 | fused = (fused & ANALOG_FUSE_POLY_MASK) | |
344 | (fine & ANALOG_FUSE_FINE_MASK) | |
345 | (coarse & ANALOG_FUSE_COARSE_MASK); |
346 | |
347 | IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_CONTROL, fused); |
348 | IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_BYPASS, |
349 | ANALOG_FUSE_ENABLE_SW_CONTROL); |
350 | } |
351 | } |
352 | PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000); |
353 | } |
354 | |
355 | |
356 | static int |
357 | igphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) |
358 | { |
359 | struct ifmedia_entry *ife = mii->mii_media.ifm_cur; |
360 | uint16_t reg; |
361 | |
362 | switch (cmd) { |
363 | case MII_POLLSTAT: |
364 | /* |
365 | * If we're not polling our PHY instance, just return. |
366 | */ |
367 | if (IFM_INST(ife->ifm_media) != sc->mii_inst) |
368 | return (0); |
369 | break; |
370 | |
371 | case MII_MEDIACHG: |
372 | /* |
373 | * If the media indicates a different PHY instance, |
374 | * isolate ourselves. |
375 | */ |
376 | if (IFM_INST(ife->ifm_media) != sc->mii_inst) { |
377 | reg = PHY_READ(sc, MII_BMCR); |
378 | PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); |
379 | return (0); |
380 | } |
381 | |
382 | /* |
383 | * If the interface is not up, don't do anything. |
384 | */ |
385 | if ((mii->mii_ifp->if_flags & IFF_UP) == 0) |
386 | break; |
387 | |
388 | reg = PHY_READ(sc, MII_IGPHY_PORT_CTRL); |
389 | if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { |
390 | reg |= PSCR_AUTO_MDIX; |
391 | reg &= ~PSCR_FORCE_MDI_MDIX; |
392 | PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg); |
393 | } else { |
394 | reg &= ~(PSCR_AUTO_MDIX | PSCR_FORCE_MDI_MDIX); |
395 | PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg); |
396 | } |
397 | |
398 | mii_phy_setmedia(sc); |
399 | break; |
400 | |
401 | case MII_TICK: |
402 | /* |
403 | * If we're not currently selected, just return. |
404 | */ |
405 | if (IFM_INST(ife->ifm_media) != sc->mii_inst) |
406 | return (0); |
407 | |
408 | igphy_smartspeed_workaround(sc); |
409 | |
410 | if (mii_phy_tick(sc) == EJUSTRETURN) |
411 | return (0); |
412 | break; |
413 | |
414 | case MII_DOWN: |
415 | mii_phy_down(sc); |
416 | return (0); |
417 | } |
418 | |
419 | /* Update the media status. */ |
420 | mii_phy_status(sc); |
421 | |
422 | /* Callback if something changed. */ |
423 | mii_phy_update(sc, cmd); |
424 | return (0); |
425 | } |
426 | |
427 | |
428 | static void |
429 | igphy_status(struct mii_softc *sc) |
430 | { |
431 | struct mii_data *mii = sc->mii_pdata; |
432 | struct ifmedia_entry *ife = mii->mii_media.ifm_cur; |
433 | uint16_t bmcr, pssr, gtsr, bmsr; |
434 | |
435 | mii->mii_media_status = IFM_AVALID; |
436 | mii->mii_media_active = IFM_ETHER; |
437 | |
438 | pssr = PHY_READ(sc, MII_IGPHY_PORT_STATUS); |
439 | |
440 | if (pssr & PSSR_LINK_UP) |
441 | mii->mii_media_status |= IFM_ACTIVE; |
442 | |
443 | bmcr = PHY_READ(sc, MII_BMCR); |
444 | if (bmcr & BMCR_ISO) { |
445 | mii->mii_media_active |= IFM_NONE; |
446 | mii->mii_media_status = 0; |
447 | return; |
448 | } |
449 | |
450 | if (bmcr & BMCR_LOOP) |
451 | mii->mii_media_active |= IFM_LOOP; |
452 | |
453 | bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); |
454 | |
455 | /* |
456 | * XXX can't check if the info is valid, no |
457 | * 'negotiation done' bit? |
458 | */ |
459 | if (bmcr & BMCR_AUTOEN) { |
460 | if ((bmsr & BMSR_ACOMP) == 0) { |
461 | mii->mii_media_active |= IFM_NONE; |
462 | return; |
463 | } |
464 | switch (pssr & PSSR_SPEED_MASK) { |
465 | case PSSR_SPEED_1000MBPS: |
466 | mii->mii_media_active |= IFM_1000_T; |
467 | gtsr = PHY_READ(sc, MII_100T2SR); |
468 | if (gtsr & GTSR_MS_RES) |
469 | mii->mii_media_active |= IFM_ETH_MASTER; |
470 | break; |
471 | |
472 | case PSSR_SPEED_100MBPS: |
473 | mii->mii_media_active |= IFM_100_TX; |
474 | break; |
475 | |
476 | case PSSR_SPEED_10MBPS: |
477 | mii->mii_media_active |= IFM_10_T; |
478 | break; |
479 | |
480 | default: |
481 | mii->mii_media_active |= IFM_NONE; |
482 | mii->mii_media_status = 0; |
483 | return; |
484 | } |
485 | |
486 | if (pssr & PSSR_FULL_DUPLEX) |
487 | mii->mii_media_active |= |
488 | IFM_FDX | mii_phy_flowstatus(sc); |
489 | else |
490 | mii->mii_media_active |= IFM_HDX; |
491 | } else |
492 | mii->mii_media_active = ife->ifm_media; |
493 | } |
494 | |
495 | static void |
496 | igphy_smartspeed_workaround(struct mii_softc *sc) |
497 | { |
498 | struct igphy_softc *igsc = (struct igphy_softc *) sc; |
499 | uint16_t reg, gtsr, gtcr; |
500 | |
501 | /* This workaround is only for 82541 and 82547 */ |
502 | switch (igsc->sc_mactype) { |
503 | case WM_T_82541: |
504 | case WM_T_82541_2: |
505 | case WM_T_82547: |
506 | case WM_T_82547_2: |
507 | break; |
508 | default: |
509 | /* byebye */ |
510 | return; |
511 | } |
512 | |
513 | if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0) |
514 | return; |
515 | |
516 | /* XXX Assume 1000TX-FDX is advertized if doing autonegotiation. */ |
517 | |
518 | reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); |
519 | if ((reg & BMSR_LINK) == 0) { |
520 | switch (igsc->sc_smartspeed) { |
521 | case 0: |
522 | gtsr = PHY_READ(sc, MII_100T2SR); |
523 | if (!(gtsr & GTSR_MAN_MS_FLT)) |
524 | break; |
525 | gtsr = PHY_READ(sc, MII_100T2SR); |
526 | if (gtsr & GTSR_MAN_MS_FLT) { |
527 | gtcr = PHY_READ(sc, MII_100T2CR); |
528 | if (gtcr & GTCR_MAN_MS) { |
529 | gtcr &= ~GTCR_MAN_MS; |
530 | PHY_WRITE(sc, MII_100T2CR, |
531 | gtcr); |
532 | } |
533 | mii_phy_auto(sc, 0); |
534 | } |
535 | break; |
536 | case IGPHY_TICK_DOWNSHIFT: |
537 | gtcr = PHY_READ(sc, MII_100T2CR); |
538 | gtcr |= GTCR_MAN_MS; |
539 | PHY_WRITE(sc, MII_100T2CR, gtcr); |
540 | mii_phy_auto(sc, 0); |
541 | break; |
542 | default: |
543 | break; |
544 | } |
545 | if (igsc->sc_smartspeed++ == IGPHY_TICK_MAX) |
546 | igsc->sc_smartspeed = 0; |
547 | } else |
548 | igsc->sc_smartspeed = 0; |
549 | } |
550 | |