Deleted Added
full compact
nsphy.c (95667) nsphy.c (95722)
1/* $NetBSD: nsphy.c,v 1.18 1999/07/14 23:57:36 thorpej Exp $ */
2
3/*-
4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE 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 * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by Manuel Bouyer.
54 * 4. The name of the author may not be used to endorse or promote products
55 * derived from this software without specific prior written permission.
56 *
57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
58 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
59 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
61 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
62 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
63 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
64 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
65 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
66 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67 */
68
69/*
70 * driver for National Semiconductor's DP83840A ethernet 10/100 PHY
71 * Data Sheet available from www.national.com
72 */
73
74#include <sys/param.h>
75#include <sys/systm.h>
76#include <sys/kernel.h>
77#include <sys/socket.h>
78#include <sys/errno.h>
79#include <sys/module.h>
80#include <sys/bus.h>
81
82#include <net/if.h>
83#include <net/if_media.h>
84
85#include <dev/mii/mii.h>
86#include <dev/mii/miivar.h>
87#include <dev/mii/miidevs.h>
88
89#include <dev/mii/nsphyreg.h>
90
91#include "miibus_if.h"
92
93#if !defined(lint)
94static const char rcsid[] =
1/* $NetBSD: nsphy.c,v 1.18 1999/07/14 23:57:36 thorpej Exp $ */
2
3/*-
4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE 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 * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by Manuel Bouyer.
54 * 4. The name of the author may not be used to endorse or promote products
55 * derived from this software without specific prior written permission.
56 *
57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
58 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
59 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
61 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
62 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
63 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
64 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
65 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
66 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67 */
68
69/*
70 * driver for National Semiconductor's DP83840A ethernet 10/100 PHY
71 * Data Sheet available from www.national.com
72 */
73
74#include <sys/param.h>
75#include <sys/systm.h>
76#include <sys/kernel.h>
77#include <sys/socket.h>
78#include <sys/errno.h>
79#include <sys/module.h>
80#include <sys/bus.h>
81
82#include <net/if.h>
83#include <net/if_media.h>
84
85#include <dev/mii/mii.h>
86#include <dev/mii/miivar.h>
87#include <dev/mii/miidevs.h>
88
89#include <dev/mii/nsphyreg.h>
90
91#include "miibus_if.h"
92
93#if !defined(lint)
94static const char rcsid[] =
95 "$FreeBSD: head/sys/dev/mii/nsphy.c 95667 2002-04-28 19:25:07Z phk $";
95 "$FreeBSD: head/sys/dev/mii/nsphy.c 95722 2002-04-29 13:07:38Z phk $";
96#endif
97
98static int nsphy_probe (device_t);
99static int nsphy_attach (device_t);
96#endif
97
98static int nsphy_probe (device_t);
99static int nsphy_attach (device_t);
100static int nsphy_detach (device_t);
101
102static device_method_t nsphy_methods[] = {
103 /* device interface */
104 DEVMETHOD(device_probe, nsphy_probe),
105 DEVMETHOD(device_attach, nsphy_attach),
100
101static device_method_t nsphy_methods[] = {
102 /* device interface */
103 DEVMETHOD(device_probe, nsphy_probe),
104 DEVMETHOD(device_attach, nsphy_attach),
106 DEVMETHOD(device_detach, nsphy_detach),
105 DEVMETHOD(device_detach, mii_phy_detach),
107 DEVMETHOD(device_shutdown, bus_generic_shutdown),
108 { 0, 0 }
109};
110
111static devclass_t nsphy_devclass;
112
113static driver_t nsphy_driver = {
114 "nsphy",
115 nsphy_methods,
116 sizeof(struct mii_softc)
117};
118
119DRIVER_MODULE(nsphy, miibus, nsphy_driver, nsphy_devclass, 0, 0);
120
121static int nsphy_service(struct mii_softc *, struct mii_data *, int);
122static void nsphy_status(struct mii_softc *);
123
124static int nsphy_probe(dev)
125 device_t dev;
126{
127 struct mii_attach_args *ma;
128
129 ma = device_get_ivars(dev);
130
131 if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_NATSEMI &&
132 MII_MODEL(ma->mii_id2) == MII_MODEL_NATSEMI_DP83840) {
133 device_set_desc(dev, MII_STR_NATSEMI_DP83840);
134 } else
135 return (ENXIO);
136
137 return (0);
138}
139
140static int nsphy_attach(dev)
141 device_t dev;
142{
143 struct mii_softc *sc;
144 struct mii_attach_args *ma;
145 struct mii_data *mii;
146
147 sc = device_get_softc(dev);
148 ma = device_get_ivars(dev);
149 sc->mii_dev = device_get_parent(dev);
150 mii = device_get_softc(sc->mii_dev);
151 LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
152
153 sc->mii_inst = mii->mii_instance;
154 sc->mii_phy = ma->mii_phyno;
155 sc->mii_service = nsphy_service;
156 sc->mii_pdata = mii;
157
158#ifdef foo
159 /*
160 * i82557 wedges if all of its PHYs are isolated!
161 */
162 if (strcmp(device_get_name(device_get_parent(sc->mii_dev)),
163 "fxp") == 0 && mii->mii_instance == 0)
164#endif
165
166 sc->mii_flags |= MIIF_NOISOLATE;
167 mii->mii_instance++;
168
169#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
170
171#if 0
172 /* Can't do this on the i82557! */
173 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
174 BMCR_ISO);
175#endif
176 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
177 BMCR_LOOP|BMCR_S100);
178
179 mii_phy_reset(sc);
180
181 sc->mii_capabilities =
182 PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
183 device_printf(dev, " ");
184 mii_add_media(sc);
185 printf("\n");
186#undef ADD
187
188 MIIBUS_MEDIAINIT(sc->mii_dev);
189 return(0);
190}
191
106 DEVMETHOD(device_shutdown, bus_generic_shutdown),
107 { 0, 0 }
108};
109
110static devclass_t nsphy_devclass;
111
112static driver_t nsphy_driver = {
113 "nsphy",
114 nsphy_methods,
115 sizeof(struct mii_softc)
116};
117
118DRIVER_MODULE(nsphy, miibus, nsphy_driver, nsphy_devclass, 0, 0);
119
120static int nsphy_service(struct mii_softc *, struct mii_data *, int);
121static void nsphy_status(struct mii_softc *);
122
123static int nsphy_probe(dev)
124 device_t dev;
125{
126 struct mii_attach_args *ma;
127
128 ma = device_get_ivars(dev);
129
130 if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_NATSEMI &&
131 MII_MODEL(ma->mii_id2) == MII_MODEL_NATSEMI_DP83840) {
132 device_set_desc(dev, MII_STR_NATSEMI_DP83840);
133 } else
134 return (ENXIO);
135
136 return (0);
137}
138
139static int nsphy_attach(dev)
140 device_t dev;
141{
142 struct mii_softc *sc;
143 struct mii_attach_args *ma;
144 struct mii_data *mii;
145
146 sc = device_get_softc(dev);
147 ma = device_get_ivars(dev);
148 sc->mii_dev = device_get_parent(dev);
149 mii = device_get_softc(sc->mii_dev);
150 LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
151
152 sc->mii_inst = mii->mii_instance;
153 sc->mii_phy = ma->mii_phyno;
154 sc->mii_service = nsphy_service;
155 sc->mii_pdata = mii;
156
157#ifdef foo
158 /*
159 * i82557 wedges if all of its PHYs are isolated!
160 */
161 if (strcmp(device_get_name(device_get_parent(sc->mii_dev)),
162 "fxp") == 0 && mii->mii_instance == 0)
163#endif
164
165 sc->mii_flags |= MIIF_NOISOLATE;
166 mii->mii_instance++;
167
168#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
169
170#if 0
171 /* Can't do this on the i82557! */
172 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
173 BMCR_ISO);
174#endif
175 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
176 BMCR_LOOP|BMCR_S100);
177
178 mii_phy_reset(sc);
179
180 sc->mii_capabilities =
181 PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
182 device_printf(dev, " ");
183 mii_add_media(sc);
184 printf("\n");
185#undef ADD
186
187 MIIBUS_MEDIAINIT(sc->mii_dev);
188 return(0);
189}
190
192static int nsphy_detach(dev)
193 device_t dev;
194{
195 struct mii_softc *sc;
196 struct mii_data *mii;
197
198 sc = device_get_softc(dev);
199 mii = device_get_softc(device_get_parent(dev));
200 mii_phy_auto_stop(sc);
201 sc->mii_dev = NULL;
202 LIST_REMOVE(sc, mii_list);
203
204 return(0);
205}
206
207static int
208nsphy_service(sc, mii, cmd)
209 struct mii_softc *sc;
210 struct mii_data *mii;
211 int cmd;
212{
213 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
214 int reg;
215
216 switch (cmd) {
217 case MII_POLLSTAT:
218 /*
219 * If we're not polling our PHY instance, just return.
220 */
221 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
222 return (0);
223 break;
224
225 case MII_MEDIACHG:
226 /*
227 * If the media indicates a different PHY instance,
228 * isolate ourselves.
229 */
230 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
231 reg = PHY_READ(sc, MII_BMCR);
232 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
233 return (0);
234 }
235
236 /*
237 * If the interface is not up, don't do anything.
238 */
239 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
240 break;
241
242 reg = PHY_READ(sc, MII_NSPHY_PCR);
243
244 /*
245 * Set up the PCR to use LED4 to indicate full-duplex
246 * in both 10baseT and 100baseTX modes.
247 */
248 reg |= PCR_LED4MODE;
249
250 /*
251 * Make sure Carrier Intgrity Monitor function is
252 * disabled (normal for Node operation, but sometimes
253 * it's not set?!)
254 */
255 reg |= PCR_CIMDIS;
256
257 /*
258 * Make sure "force link good" is set to normal mode.
259 * It's only intended for debugging.
260 */
261 reg |= PCR_FLINK100;
262
263 /*
264 * Mystery bits which are supposedly `reserved',
265 * but we seem to need to set them when the PHY
266 * is connected to some interfaces:
267 *
268 * 0x0400 is needed for fxp
269 * (Intel EtherExpress Pro 10+/100B, 82557 chip)
270 * (nsphy with a DP83840 chip)
271 * 0x0100 may be needed for some other card
272 */
273 reg |= 0x0100 | 0x0400;
274
275 if (strcmp(device_get_name(device_get_parent(sc->mii_dev)),
276 "fxp") == 0)
277 PHY_WRITE(sc, MII_NSPHY_PCR, reg);
278
279 switch (IFM_SUBTYPE(ife->ifm_media)) {
280 case IFM_AUTO:
281 /*
282 * If we're already in auto mode, just return.
283 */
284 if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
285 return (0);
286 (void) mii_phy_auto(sc, 1);
287 break;
288 case IFM_100_T4:
289 /*
290 * XXX Not supported as a manual setting right now.
291 */
292 return (EINVAL);
293 default:
294 /*
295 * BMCR data is stored in the ifmedia entry.
296 */
297 PHY_WRITE(sc, MII_ANAR,
298 mii_anar(ife->ifm_media));
299 PHY_WRITE(sc, MII_BMCR, ife->ifm_data);
300 }
301 break;
302
303 case MII_TICK:
304 /*
305 * If we're not currently selected, just return.
306 */
307 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
308 return (0);
309 if (mii_phy_tick(sc) == EJUSTRETURN)
310 return (0);
311 break;
312 }
313
314 /* Update the media status. */
315 nsphy_status(sc);
316
317 /* Callback if something changed. */
318 mii_phy_update(sc, cmd);
319 return (0);
320}
321
322static void
323nsphy_status(sc)
324 struct mii_softc *sc;
325{
326 struct mii_data *mii = sc->mii_pdata;
327 int bmsr, bmcr, par, anlpar;
328
329 mii->mii_media_status = IFM_AVALID;
330 mii->mii_media_active = IFM_ETHER;
331
332 bmsr = PHY_READ(sc, MII_BMSR) |
333 PHY_READ(sc, MII_BMSR);
334 if (bmsr & BMSR_LINK)
335 mii->mii_media_status |= IFM_ACTIVE;
336
337 bmcr = PHY_READ(sc, MII_BMCR);
338 if (bmcr & BMCR_ISO) {
339 mii->mii_media_active |= IFM_NONE;
340 mii->mii_media_status = 0;
341 return;
342 }
343
344 if (bmcr & BMCR_LOOP)
345 mii->mii_media_active |= IFM_LOOP;
346
347 if (bmcr & BMCR_AUTOEN) {
348 /*
349 * The PAR status bits are only valid of autonegotiation
350 * has completed (or it's disabled).
351 */
352 if ((bmsr & BMSR_ACOMP) == 0) {
353 /* Erg, still trying, I guess... */
354 mii->mii_media_active |= IFM_NONE;
355 return;
356 }
357
358 /*
359 * Argh. The PAR doesn't seem to indicate duplex mode
360 * properly! Determine media based on link partner's
361 * advertised capabilities.
362 */
363 if (PHY_READ(sc, MII_ANER) & ANER_LPAN) {
364 anlpar = PHY_READ(sc, MII_ANAR) &
365 PHY_READ(sc, MII_ANLPAR);
366 if (anlpar & ANLPAR_T4)
367 mii->mii_media_active |= IFM_100_T4;
368 else if (anlpar & ANLPAR_TX_FD)
369 mii->mii_media_active |= IFM_100_TX|IFM_FDX;
370 else if (anlpar & ANLPAR_TX)
371 mii->mii_media_active |= IFM_100_TX;
372 else if (anlpar & ANLPAR_10_FD)
373 mii->mii_media_active |= IFM_10_T|IFM_FDX;
374 else if (anlpar & ANLPAR_10)
375 mii->mii_media_active |= IFM_10_T;
376 else
377 mii->mii_media_active |= IFM_NONE;
378 return;
379 }
380
381 /*
382 * Link partner is not capable of autonegotiation.
383 * We will never be in full-duplex mode if this is
384 * the case, so reading the PAR is OK.
385 */
386 par = PHY_READ(sc, MII_NSPHY_PAR);
387 if (par & PAR_10)
388 mii->mii_media_active |= IFM_10_T;
389 else
390 mii->mii_media_active |= IFM_100_TX;
391#if 0
392 if (par & PAR_FDX)
393 mii->mii_media_active |= IFM_FDX;
394#endif
395 } else
396 mii->mii_media_active |= mii_media_from_bmcr(bmcr);
397}
191static int
192nsphy_service(sc, mii, cmd)
193 struct mii_softc *sc;
194 struct mii_data *mii;
195 int cmd;
196{
197 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
198 int reg;
199
200 switch (cmd) {
201 case MII_POLLSTAT:
202 /*
203 * If we're not polling our PHY instance, just return.
204 */
205 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
206 return (0);
207 break;
208
209 case MII_MEDIACHG:
210 /*
211 * If the media indicates a different PHY instance,
212 * isolate ourselves.
213 */
214 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
215 reg = PHY_READ(sc, MII_BMCR);
216 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
217 return (0);
218 }
219
220 /*
221 * If the interface is not up, don't do anything.
222 */
223 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
224 break;
225
226 reg = PHY_READ(sc, MII_NSPHY_PCR);
227
228 /*
229 * Set up the PCR to use LED4 to indicate full-duplex
230 * in both 10baseT and 100baseTX modes.
231 */
232 reg |= PCR_LED4MODE;
233
234 /*
235 * Make sure Carrier Intgrity Monitor function is
236 * disabled (normal for Node operation, but sometimes
237 * it's not set?!)
238 */
239 reg |= PCR_CIMDIS;
240
241 /*
242 * Make sure "force link good" is set to normal mode.
243 * It's only intended for debugging.
244 */
245 reg |= PCR_FLINK100;
246
247 /*
248 * Mystery bits which are supposedly `reserved',
249 * but we seem to need to set them when the PHY
250 * is connected to some interfaces:
251 *
252 * 0x0400 is needed for fxp
253 * (Intel EtherExpress Pro 10+/100B, 82557 chip)
254 * (nsphy with a DP83840 chip)
255 * 0x0100 may be needed for some other card
256 */
257 reg |= 0x0100 | 0x0400;
258
259 if (strcmp(device_get_name(device_get_parent(sc->mii_dev)),
260 "fxp") == 0)
261 PHY_WRITE(sc, MII_NSPHY_PCR, reg);
262
263 switch (IFM_SUBTYPE(ife->ifm_media)) {
264 case IFM_AUTO:
265 /*
266 * If we're already in auto mode, just return.
267 */
268 if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
269 return (0);
270 (void) mii_phy_auto(sc, 1);
271 break;
272 case IFM_100_T4:
273 /*
274 * XXX Not supported as a manual setting right now.
275 */
276 return (EINVAL);
277 default:
278 /*
279 * BMCR data is stored in the ifmedia entry.
280 */
281 PHY_WRITE(sc, MII_ANAR,
282 mii_anar(ife->ifm_media));
283 PHY_WRITE(sc, MII_BMCR, ife->ifm_data);
284 }
285 break;
286
287 case MII_TICK:
288 /*
289 * If we're not currently selected, just return.
290 */
291 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
292 return (0);
293 if (mii_phy_tick(sc) == EJUSTRETURN)
294 return (0);
295 break;
296 }
297
298 /* Update the media status. */
299 nsphy_status(sc);
300
301 /* Callback if something changed. */
302 mii_phy_update(sc, cmd);
303 return (0);
304}
305
306static void
307nsphy_status(sc)
308 struct mii_softc *sc;
309{
310 struct mii_data *mii = sc->mii_pdata;
311 int bmsr, bmcr, par, anlpar;
312
313 mii->mii_media_status = IFM_AVALID;
314 mii->mii_media_active = IFM_ETHER;
315
316 bmsr = PHY_READ(sc, MII_BMSR) |
317 PHY_READ(sc, MII_BMSR);
318 if (bmsr & BMSR_LINK)
319 mii->mii_media_status |= IFM_ACTIVE;
320
321 bmcr = PHY_READ(sc, MII_BMCR);
322 if (bmcr & BMCR_ISO) {
323 mii->mii_media_active |= IFM_NONE;
324 mii->mii_media_status = 0;
325 return;
326 }
327
328 if (bmcr & BMCR_LOOP)
329 mii->mii_media_active |= IFM_LOOP;
330
331 if (bmcr & BMCR_AUTOEN) {
332 /*
333 * The PAR status bits are only valid of autonegotiation
334 * has completed (or it's disabled).
335 */
336 if ((bmsr & BMSR_ACOMP) == 0) {
337 /* Erg, still trying, I guess... */
338 mii->mii_media_active |= IFM_NONE;
339 return;
340 }
341
342 /*
343 * Argh. The PAR doesn't seem to indicate duplex mode
344 * properly! Determine media based on link partner's
345 * advertised capabilities.
346 */
347 if (PHY_READ(sc, MII_ANER) & ANER_LPAN) {
348 anlpar = PHY_READ(sc, MII_ANAR) &
349 PHY_READ(sc, MII_ANLPAR);
350 if (anlpar & ANLPAR_T4)
351 mii->mii_media_active |= IFM_100_T4;
352 else if (anlpar & ANLPAR_TX_FD)
353 mii->mii_media_active |= IFM_100_TX|IFM_FDX;
354 else if (anlpar & ANLPAR_TX)
355 mii->mii_media_active |= IFM_100_TX;
356 else if (anlpar & ANLPAR_10_FD)
357 mii->mii_media_active |= IFM_10_T|IFM_FDX;
358 else if (anlpar & ANLPAR_10)
359 mii->mii_media_active |= IFM_10_T;
360 else
361 mii->mii_media_active |= IFM_NONE;
362 return;
363 }
364
365 /*
366 * Link partner is not capable of autonegotiation.
367 * We will never be in full-duplex mode if this is
368 * the case, so reading the PAR is OK.
369 */
370 par = PHY_READ(sc, MII_NSPHY_PAR);
371 if (par & PAR_10)
372 mii->mii_media_active |= IFM_10_T;
373 else
374 mii->mii_media_active |= IFM_100_TX;
375#if 0
376 if (par & PAR_FDX)
377 mii->mii_media_active |= IFM_FDX;
378#endif
379 } else
380 mii->mii_media_active |= mii_media_from_bmcr(bmcr);
381}