Thu Aug 6 04:58:48 2009 UTC ()
Later generation 82566 IGP PHYs have problems with media changes to 100Mb and
10Mb; it appears that the SmartSpeed workaround and dspcode in this PHY are
aimed at earlier generation IGPs.  Remove reference to 82566s, allowing
them to fall through to choose other PHYs.


(kml)
diff -r1.17 -r1.18 src/sys/dev/mii/igphy.c

cvs diff -r1.17 -r1.18 src/sys/dev/mii/igphy.c (switch to unified diff)

--- src/sys/dev/mii/igphy.c 2008/11/17 03:04:27 1.17
+++ src/sys/dev/mii/igphy.c 2009/08/06 04:58:48 1.18
@@ -1,418 +1,415 @@ @@ -1,418 +1,415 @@
1/* $NetBSD: igphy.c,v 1.17 2008/11/17 03:04:27 dyoung Exp $ */ 1/* $NetBSD: igphy.c,v 1.18 2009/08/06 04:58:48 kml Exp $ */
2 2
3/* 3/*
4 * The Intel copyright applies to the analog register setup, and the 4 * The Intel copyright applies to the analog register setup, and the
5 * (currently disabled) SmartSpeed workaround code. 5 * (currently disabled) SmartSpeed workaround code.
6 */ 6 */
7 7
8/******************************************************************************* 8/*******************************************************************************
9 9
10 Copyright (c) 2001-2003, Intel Corporation 10 Copyright (c) 2001-2003, Intel Corporation
11 All rights reserved. 11 All rights reserved.
12 12
13 Redistribution and use in source and binary forms, with or without 13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions are met: 14 modification, are permitted provided that the following conditions are met:
15 15
16 1. Redistributions of source code must retain the above copyright notice, 16 1. Redistributions of source code must retain the above copyright notice,
17 this list of conditions and the following disclaimer. 17 this list of conditions and the following disclaimer.
18 18
19 2. Redistributions in binary form must reproduce the above copyright 19 2. Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in the 20 notice, this list of conditions and the following disclaimer in the
21 documentation and/or other materials provided with the distribution. 21 documentation and/or other materials provided with the distribution.
22 22
23 3. Neither the name of the Intel Corporation nor the names of its 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 24 contributors may be used to endorse or promote products derived from
25 this software without specific prior written permission. 25 this software without specific prior written permission.
26 26
27 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 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 28 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 30 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 34 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 36 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 POSSIBILITY OF SUCH DAMAGE. 37 POSSIBILITY OF SUCH DAMAGE.
38 38
39*******************************************************************************/ 39*******************************************************************************/
40 40
41 41
42/*- 42/*-
43 * Copyright (c) 1998, 1999, 2000, 2003 The NetBSD Foundation, Inc. 43 * Copyright (c) 1998, 1999, 2000, 2003 The NetBSD Foundation, Inc.
44 * All rights reserved. 44 * All rights reserved.
45 * 45 *
46 * This code is derived from software contributed to The NetBSD Foundation 46 * This code is derived from software contributed to The NetBSD Foundation
47 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 47 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
48 * NASA Ames Research Center, and by Frank van der Linden. 48 * NASA Ames Research Center, and by Frank van der Linden.
49 * 49 *
50 * Redistribution and use in source and binary forms, with or without 50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions 51 * modification, are permitted provided that the following conditions
52 * are met: 52 * are met:
53 * 1. Redistributions of source code must retain the above copyright 53 * 1. Redistributions of source code must retain the above copyright
54 * notice, this list of conditions and the following disclaimer. 54 * notice, this list of conditions and the following disclaimer.
55 * 2. Redistributions in binary form must reproduce the above copyright 55 * 2. Redistributions in binary form must reproduce the above copyright
56 * notice, this list of conditions and the following disclaimer in the 56 * notice, this list of conditions and the following disclaimer in the
57 * documentation and/or other materials provided with the distribution. 57 * documentation and/or other materials provided with the distribution.
58 * 58 *
59 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 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 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 61 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
62 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 62 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
63 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 63 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
64 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 64 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
65 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 66 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
67 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 68 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
69 * POSSIBILITY OF SUCH DAMAGE. 69 * POSSIBILITY OF SUCH DAMAGE.
70 */ 70 */
71 71
72#include <sys/cdefs.h> 72#include <sys/cdefs.h>
73__KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.17 2008/11/17 03:04:27 dyoung Exp $"); 73__KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.18 2009/08/06 04:58:48 kml Exp $");
74 74
75#include "opt_mii.h" 75#include "opt_mii.h"
76 76
77#include <sys/param.h> 77#include <sys/param.h>
78#include <sys/systm.h> 78#include <sys/systm.h>
79#include <sys/kernel.h> 79#include <sys/kernel.h>
80#include <sys/device.h> 80#include <sys/device.h>
81#include <sys/socket.h> 81#include <sys/socket.h>
82#include <sys/errno.h> 82#include <sys/errno.h>
83 83
84#include <net/if.h> 84#include <net/if.h>
85#include <net/if_media.h> 85#include <net/if_media.h>
86 86
87#include <dev/mii/mii.h> 87#include <dev/mii/mii.h>
88#include <dev/mii/miivar.h> 88#include <dev/mii/miivar.h>
89#include <dev/mii/miidevs.h> 89#include <dev/mii/miidevs.h>
90 90
91#include <dev/mii/igphyreg.h> 91#include <dev/mii/igphyreg.h>
92 92
93struct igphy_softc { 93struct igphy_softc {
94 struct mii_softc sc_mii; 94 struct mii_softc sc_mii;
95 int sc_smartspeed; 95 int sc_smartspeed;
96}; 96};
97 97
98static void igphy_reset(struct mii_softc *); 98static void igphy_reset(struct mii_softc *);
99static void igphy_load_dspcode(struct mii_softc *); 99static void igphy_load_dspcode(struct mii_softc *);
100static void igphy_smartspeed_workaround(struct mii_softc *sc); 100static void igphy_smartspeed_workaround(struct mii_softc *sc);
101 101
102static int igphymatch(device_t, cfdata_t, void *); 102static int igphymatch(device_t, cfdata_t, void *);
103static void igphyattach(device_t, device_t, void *); 103static void igphyattach(device_t, device_t, void *);
104 104
105CFATTACH_DECL_NEW(igphy, sizeof(struct igphy_softc), 105CFATTACH_DECL_NEW(igphy, sizeof(struct igphy_softc),
106 igphymatch, igphyattach, mii_phy_detach, mii_phy_activate); 106 igphymatch, igphyattach, mii_phy_detach, mii_phy_activate);
107 107
108static int igphy_service(struct mii_softc *, struct mii_data *, int); 108static int igphy_service(struct mii_softc *, struct mii_data *, int);
109static void igphy_status(struct mii_softc *); 109static void igphy_status(struct mii_softc *);
110 110
111static const struct mii_phy_funcs igphy_funcs = { 111static const struct mii_phy_funcs igphy_funcs = {
112 igphy_service, igphy_status, igphy_reset, 112 igphy_service, igphy_status, igphy_reset,
113}; 113};
114 114
115static const struct mii_phydesc igphys[] = { 115static const struct mii_phydesc igphys[] = {
116 { MII_OUI_yyINTEL, MII_MODEL_yyINTEL_IGP01E1000, 116 { MII_OUI_yyINTEL, MII_MODEL_yyINTEL_IGP01E1000,
117 MII_STR_yyINTEL_IGP01E1000 }, 117 MII_STR_yyINTEL_IGP01E1000 },
118 118
119 { MII_OUI_yyINTEL, MII_MODEL_yyINTEL_I82566, 
120 MII_STR_yyINTEL_I82566 }, 
121 
122 {0, 0, 119 {0, 0,
123 NULL }, 120 NULL },
124}; 121};
125 122
126static int 123static int
127igphymatch(device_t parent, cfdata_t match, void *aux) 124igphymatch(device_t parent, cfdata_t match, void *aux)
128{ 125{
129 struct mii_attach_args *ma = aux; 126 struct mii_attach_args *ma = aux;
130 127
131 if (mii_phy_match(ma, igphys) != NULL) 128 if (mii_phy_match(ma, igphys) != NULL)
132 return 10; 129 return 10;
133 130
134 return 0; 131 return 0;
135} 132}
136 133
137static void 134static void
138igphyattach(device_t parent, device_t self, void *aux) 135igphyattach(device_t parent, device_t self, void *aux)
139{ 136{
140 struct mii_softc *sc = device_private(self); 137 struct mii_softc *sc = device_private(self);
141 struct mii_attach_args *ma = aux; 138 struct mii_attach_args *ma = aux;
142 struct mii_data *mii = ma->mii_data; 139 struct mii_data *mii = ma->mii_data;
143 const struct mii_phydesc *mpd; 140 const struct mii_phydesc *mpd;
144 141
145 mpd = mii_phy_match(ma, igphys); 142 mpd = mii_phy_match(ma, igphys);
146 aprint_naive(": Media interface\n"); 143 aprint_naive(": Media interface\n");
147 aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2)); 144 aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
148 145
149 sc->mii_dev = self; 146 sc->mii_dev = self;
150 sc->mii_inst = mii->mii_instance; 147 sc->mii_inst = mii->mii_instance;
151 sc->mii_phy = ma->mii_phyno; 148 sc->mii_phy = ma->mii_phyno;
152 sc->mii_funcs = &igphy_funcs; 149 sc->mii_funcs = &igphy_funcs;
153 sc->mii_pdata = mii; 150 sc->mii_pdata = mii;
154 sc->mii_flags = ma->mii_flags; 151 sc->mii_flags = ma->mii_flags;
155 sc->mii_anegticks = MII_ANEGTICKS_GIGE; 152 sc->mii_anegticks = MII_ANEGTICKS_GIGE;
156 153
157 PHY_RESET(sc); 154 PHY_RESET(sc);
158 155
159 sc->mii_capabilities = 156 sc->mii_capabilities =
160 PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 157 PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
161 if (sc->mii_capabilities & BMSR_EXTSTAT) 158 if (sc->mii_capabilities & BMSR_EXTSTAT)
162 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); 159 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
163 aprint_normal_dev(self, ""); 160 aprint_normal_dev(self, "");
164 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && 161 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
165 (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) 162 (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
166 aprint_error("no media present"); 163 aprint_error("no media present");
167 else 164 else
168 mii_phy_add_media(sc); 165 mii_phy_add_media(sc);
169 aprint_normal("\n"); 166 aprint_normal("\n");
170} 167}
171 168
172static void 169static void
173igphy_load_dspcode(struct mii_softc *sc) 170igphy_load_dspcode(struct mii_softc *sc)
174{ 171{
175 static const struct { 172 static const struct {
176 int reg; 173 int reg;
177 uint16_t val; 174 uint16_t val;
178 } dspcode[] = { 175 } dspcode[] = {
179 { 0x1f95, 0x0001 }, 176 { 0x1f95, 0x0001 },
180 { 0x1f71, 0xbd21 }, 177 { 0x1f71, 0xbd21 },
181 { 0x1f79, 0x0018 }, 178 { 0x1f79, 0x0018 },
182 { 0x1f30, 0x1600 }, 179 { 0x1f30, 0x1600 },
183 { 0x1f31, 0x0014 }, 180 { 0x1f31, 0x0014 },
184 { 0x1f32, 0x161c }, 181 { 0x1f32, 0x161c },
185 { 0x1f94, 0x0003 }, 182 { 0x1f94, 0x0003 },
186 { 0x1f96, 0x003f }, 183 { 0x1f96, 0x003f },
187 { 0x2010, 0x0008 }, 184 { 0x2010, 0x0008 },
188 { 0, 0 }, 185 { 0, 0 },
189 }; 186 };
190 int i; 187 int i;
191 188
192 delay(10); 189 delay(10);
193 190
194 PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000); 191 PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
195 PHY_WRITE(sc, 0x0000, 0x0140); 192 PHY_WRITE(sc, 0x0000, 0x0140);
196 193
197 delay(5); 194 delay(5);
198 195
199 for (i = 0; dspcode[i].reg != 0; i++) 196 for (i = 0; dspcode[i].reg != 0; i++)
200 IGPHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 197 IGPHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
201 198
202 PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000); 199 PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000);
203 PHY_WRITE(sc, 0x0000, 0x3300); 200 PHY_WRITE(sc, 0x0000, 0x3300);
204} 201}
205 202
206static void 203static void
207igphy_reset(struct mii_softc *sc) 204igphy_reset(struct mii_softc *sc)
208{ 205{
209 uint16_t fused, fine, coarse; 206 uint16_t fused, fine, coarse;
210 207
211 mii_phy_reset(sc); 208 mii_phy_reset(sc);
212 igphy_load_dspcode(sc); 209 igphy_load_dspcode(sc);
213 210
214 fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_SPARE_FUSE_STATUS); 211 fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_SPARE_FUSE_STATUS);
215 if ((fused & ANALOG_SPARE_FUSE_ENABLED) == 0) { 212 if ((fused & ANALOG_SPARE_FUSE_ENABLED) == 0) {
216 fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_FUSE_STATUS); 213 fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_FUSE_STATUS);
217 214
218 fine = fused & ANALOG_FUSE_FINE_MASK; 215 fine = fused & ANALOG_FUSE_FINE_MASK;
219 coarse = fused & ANALOG_FUSE_COARSE_MASK; 216 coarse = fused & ANALOG_FUSE_COARSE_MASK;
220 217
221 if (coarse > ANALOG_FUSE_COARSE_THRESH) { 218 if (coarse > ANALOG_FUSE_COARSE_THRESH) {
222 coarse -= ANALOG_FUSE_COARSE_10; 219 coarse -= ANALOG_FUSE_COARSE_10;
223 fine -= ANALOG_FUSE_FINE_1; 220 fine -= ANALOG_FUSE_FINE_1;
224 } else if (coarse == ANALOG_FUSE_COARSE_THRESH) 221 } else if (coarse == ANALOG_FUSE_COARSE_THRESH)
225 fine -= ANALOG_FUSE_FINE_10; 222 fine -= ANALOG_FUSE_FINE_10;
226 223
227 fused = (fused & ANALOG_FUSE_POLY_MASK) | 224 fused = (fused & ANALOG_FUSE_POLY_MASK) |
228 (fine & ANALOG_FUSE_FINE_MASK) | 225 (fine & ANALOG_FUSE_FINE_MASK) |
229 (coarse & ANALOG_FUSE_COARSE_MASK); 226 (coarse & ANALOG_FUSE_COARSE_MASK);
230 227
231 IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_CONTROL, fused); 228 IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_CONTROL, fused);
232 IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_BYPASS, 229 IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_BYPASS,
233 ANALOG_FUSE_ENABLE_SW_CONTROL); 230 ANALOG_FUSE_ENABLE_SW_CONTROL);
234 } 231 }
235 PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000); 232 PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000);
236} 233}
237 234
238 235
239static int 236static int
240igphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 237igphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
241{ 238{
242 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 239 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
243 uint16_t reg; 240 uint16_t reg;
244 241
245 switch (cmd) { 242 switch (cmd) {
246 case MII_POLLSTAT: 243 case MII_POLLSTAT:
247 /* 244 /*
248 * If we're not polling our PHY instance, just return. 245 * If we're not polling our PHY instance, just return.
249 */ 246 */
250 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 247 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
251 return (0); 248 return (0);
252 break; 249 break;
253 250
254 case MII_MEDIACHG: 251 case MII_MEDIACHG:
255 /* 252 /*
256 * If the media indicates a different PHY instance, 253 * If the media indicates a different PHY instance,
257 * isolate ourselves. 254 * isolate ourselves.
258 */ 255 */
259 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 256 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
260 reg = PHY_READ(sc, MII_BMCR); 257 reg = PHY_READ(sc, MII_BMCR);
261 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 258 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
262 return (0); 259 return (0);
263 } 260 }
264 261
265 /* 262 /*
266 * If the interface is not up, don't do anything. 263 * If the interface is not up, don't do anything.
267 */ 264 */
268 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 265 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
269 break; 266 break;
270 267
271 reg = PHY_READ(sc, MII_IGPHY_PORT_CTRL); 268 reg = PHY_READ(sc, MII_IGPHY_PORT_CTRL);
272 if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { 269 if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
273 reg |= PSCR_AUTO_MDIX; 270 reg |= PSCR_AUTO_MDIX;
274 reg &= ~PSCR_FORCE_MDI_MDIX; 271 reg &= ~PSCR_FORCE_MDI_MDIX;
275 PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg); 272 PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg);
276 } else { 273 } else {
277 reg &= ~(PSCR_AUTO_MDIX | PSCR_FORCE_MDI_MDIX); 274 reg &= ~(PSCR_AUTO_MDIX | PSCR_FORCE_MDI_MDIX);
278 PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg); 275 PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg);
279 } 276 }
280 277
281 mii_phy_setmedia(sc); 278 mii_phy_setmedia(sc);
282 break; 279 break;
283 280
284 case MII_TICK: 281 case MII_TICK:
285 /* 282 /*
286 * If we're not currently selected, just return. 283 * If we're not currently selected, just return.
287 */ 284 */
288 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 285 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
289 return (0); 286 return (0);
290 287
291 igphy_smartspeed_workaround(sc); 288 igphy_smartspeed_workaround(sc);
292 289
293 if (mii_phy_tick(sc) == EJUSTRETURN) 290 if (mii_phy_tick(sc) == EJUSTRETURN)
294 return (0); 291 return (0);
295 break; 292 break;
296 293
297 case MII_DOWN: 294 case MII_DOWN:
298 mii_phy_down(sc); 295 mii_phy_down(sc);
299 return (0); 296 return (0);
300 } 297 }
301 298
302 /* Update the media status. */ 299 /* Update the media status. */
303 mii_phy_status(sc); 300 mii_phy_status(sc);
304 301
305 /* Callback if something changed. */ 302 /* Callback if something changed. */
306 mii_phy_update(sc, cmd); 303 mii_phy_update(sc, cmd);
307 return (0); 304 return (0);
308} 305}
309 306
310 307
311static void 308static void
312igphy_status(struct mii_softc *sc) 309igphy_status(struct mii_softc *sc)
313{ 310{
314 struct mii_data *mii = sc->mii_pdata; 311 struct mii_data *mii = sc->mii_pdata;
315 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 312 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
316 uint16_t bmcr, pssr, gtsr, bmsr; 313 uint16_t bmcr, pssr, gtsr, bmsr;
317 314
318 mii->mii_media_status = IFM_AVALID; 315 mii->mii_media_status = IFM_AVALID;
319 mii->mii_media_active = IFM_ETHER; 316 mii->mii_media_active = IFM_ETHER;
320 317
321 pssr = PHY_READ(sc, MII_IGPHY_PORT_STATUS); 318 pssr = PHY_READ(sc, MII_IGPHY_PORT_STATUS);
322 319
323 if (pssr & PSSR_LINK_UP) 320 if (pssr & PSSR_LINK_UP)
324 mii->mii_media_status |= IFM_ACTIVE; 321 mii->mii_media_status |= IFM_ACTIVE;
325 322
326 bmcr = PHY_READ(sc, MII_BMCR); 323 bmcr = PHY_READ(sc, MII_BMCR);
327 if (bmcr & BMCR_ISO) { 324 if (bmcr & BMCR_ISO) {
328 mii->mii_media_active |= IFM_NONE; 325 mii->mii_media_active |= IFM_NONE;
329 mii->mii_media_status = 0; 326 mii->mii_media_status = 0;
330 return; 327 return;
331 } 328 }
332 329
333 if (bmcr & BMCR_LOOP) 330 if (bmcr & BMCR_LOOP)
334 mii->mii_media_active |= IFM_LOOP; 331 mii->mii_media_active |= IFM_LOOP;
335 332
336 bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 333 bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
337 334
338 /* 335 /*
339 * XXX can't check if the info is valid, no 336 * XXX can't check if the info is valid, no
340 * 'negotiation done' bit? 337 * 'negotiation done' bit?
341 */ 338 */
342 if (bmcr & BMCR_AUTOEN) { 339 if (bmcr & BMCR_AUTOEN) {
343 if ((bmsr & BMSR_ACOMP) == 0) { 340 if ((bmsr & BMSR_ACOMP) == 0) {
344 mii->mii_media_active |= IFM_NONE; 341 mii->mii_media_active |= IFM_NONE;
345 return; 342 return;
346 } 343 }
347 switch (pssr & PSSR_SPEED_MASK) { 344 switch (pssr & PSSR_SPEED_MASK) {
348 case PSSR_SPEED_1000MBPS: 345 case PSSR_SPEED_1000MBPS:
349 mii->mii_media_active |= IFM_1000_T; 346 mii->mii_media_active |= IFM_1000_T;
350 gtsr = PHY_READ(sc, MII_100T2SR); 347 gtsr = PHY_READ(sc, MII_100T2SR);
351 if (gtsr & GTSR_MS_RES) 348 if (gtsr & GTSR_MS_RES)
352 mii->mii_media_active |= IFM_ETH_MASTER; 349 mii->mii_media_active |= IFM_ETH_MASTER;
353 break; 350 break;
354 351
355 case PSSR_SPEED_100MBPS: 352 case PSSR_SPEED_100MBPS:
356 mii->mii_media_active |= IFM_100_TX; 353 mii->mii_media_active |= IFM_100_TX;
357 break; 354 break;
358 355
359 case PSSR_SPEED_10MBPS: 356 case PSSR_SPEED_10MBPS:
360 mii->mii_media_active |= IFM_10_T; 357 mii->mii_media_active |= IFM_10_T;
361 break; 358 break;
362 359
363 default: 360 default:
364 mii->mii_media_active |= IFM_NONE; 361 mii->mii_media_active |= IFM_NONE;
365 mii->mii_media_status = 0; 362 mii->mii_media_status = 0;
366 return; 363 return;
367 } 364 }
368 365
369 if (pssr & PSSR_FULL_DUPLEX) 366 if (pssr & PSSR_FULL_DUPLEX)
370 mii->mii_media_active |= 367 mii->mii_media_active |=
371 IFM_FDX | mii_phy_flowstatus(sc); 368 IFM_FDX | mii_phy_flowstatus(sc);
372 } else 369 } else
373 mii->mii_media_active = ife->ifm_media; 370 mii->mii_media_active = ife->ifm_media;
374} 371}
375 372
376static void 373static void
377igphy_smartspeed_workaround(struct mii_softc *sc) 374igphy_smartspeed_workaround(struct mii_softc *sc)
378{ 375{
379 struct igphy_softc *igsc = (struct igphy_softc *) sc; 376 struct igphy_softc *igsc = (struct igphy_softc *) sc;
380 uint16_t reg, gtsr, gtcr; 377 uint16_t reg, gtsr, gtcr;
381 378
382 if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0) 379 if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0)
383 return; 380 return;
384 381
385 /* XXX Assume 1000TX-FDX is advertized if doing autonegotiation. */ 382 /* XXX Assume 1000TX-FDX is advertized if doing autonegotiation. */
386 383
387 reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 384 reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
388 if ((reg & BMSR_LINK) == 0) { 385 if ((reg & BMSR_LINK) == 0) {
389 switch (igsc->sc_smartspeed) { 386 switch (igsc->sc_smartspeed) {
390 case 0: 387 case 0:
391 gtsr = PHY_READ(sc, MII_100T2SR); 388 gtsr = PHY_READ(sc, MII_100T2SR);
392 if (!(gtsr & GTSR_MAN_MS_FLT)) 389 if (!(gtsr & GTSR_MAN_MS_FLT))
393 break; 390 break;
394 gtsr = PHY_READ(sc, MII_100T2SR); 391 gtsr = PHY_READ(sc, MII_100T2SR);
395 if (gtsr & GTSR_MAN_MS_FLT) { 392 if (gtsr & GTSR_MAN_MS_FLT) {
396 gtcr = PHY_READ(sc, MII_100T2CR); 393 gtcr = PHY_READ(sc, MII_100T2CR);
397 if (gtcr & GTCR_MAN_MS) { 394 if (gtcr & GTCR_MAN_MS) {
398 gtcr &= ~GTCR_MAN_MS; 395 gtcr &= ~GTCR_MAN_MS;
399 PHY_WRITE(sc, MII_100T2CR, 396 PHY_WRITE(sc, MII_100T2CR,
400 gtcr); 397 gtcr);
401 } 398 }
402 mii_phy_auto(sc, 0); 399 mii_phy_auto(sc, 0);
403 } 400 }
404 break; 401 break;
405 case IGPHY_TICK_DOWNSHIFT: 402 case IGPHY_TICK_DOWNSHIFT:
406 gtcr = PHY_READ(sc, MII_100T2CR); 403 gtcr = PHY_READ(sc, MII_100T2CR);
407 gtcr |= GTCR_MAN_MS; 404 gtcr |= GTCR_MAN_MS;
408 PHY_WRITE(sc, MII_100T2CR, gtcr); 405 PHY_WRITE(sc, MII_100T2CR, gtcr);
409 mii_phy_auto(sc, 0); 406 mii_phy_auto(sc, 0);
410 break; 407 break;
411 default: 408 default:
412 break; 409 break;
413 } 410 }
414 if (igsc->sc_smartspeed++ == IGPHY_TICK_MAX) 411 if (igsc->sc_smartspeed++ == IGPHY_TICK_MAX)
415 igsc->sc_smartspeed = 0; 412 igsc->sc_smartspeed = 0;
416 } else 413 } else
417 igsc->sc_smartspeed = 0; 414 igsc->sc_smartspeed = 0;
418} 415}