1 /* $OpenBSD: gentbi.c,v 1.3 2005/03/26 04:40:09 krw Exp $ */
2 /* $NetBSD: gentbi.c,v 1.12 2004/04/11 15:40:56 thorpej Exp $ */
3
4 /*-
5 * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10 * NASA Ames Research Center.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the NetBSD
23 * Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 /*
42 * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 * This product includes software developed by Manuel Bouyer.
55 * 4. The name of the author may not be used to endorse or promote products
56 * derived from this software without specific prior written permission.
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
67 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68 */
69
70 /*
71 * Driver for generic ten-bit (1000BASE-SX) interfaces, built in to
72 * many Gigabit Ethernet chips.
73 *
74 * All we have to do here is correctly report speed and duplex.
75 */
76
77 #if 0
78 #include <sys/cdefs.h>
79 __KERNEL_RCSID(0, "$NetBSD: gentbi.c,v 1.12 2004/04/11 15:40:56 thorpej Exp $");
80 #endif
81
82 #include <sys/param.h>
83 #include <sys/systm.h>
84 #include <sys/kernel.h>
85 #include <sys/device.h>
86 #include <sys/socket.h>
87 #include <sys/errno.h>
88
89 #include <net/if.h>
90 #include <net/if_media.h>
91
92 #include <dev/mii/mii.h>
93 #include <dev/mii/miivar.h>
94 #include <dev/mii/miidevs.h>
95
96 int gentbimatch(struct device *, void *, void *);
97 void gentbiattach(struct device *, struct device *, void *);
98
99 struct cfattach gentbi_ca = {
100 sizeof(struct mii_softc), gentbimatch, gentbiattach,
101 mii_phy_detach, mii_phy_activate
102 };
103
104 struct cfdriver gentbi_cd = {
105 NULL, "gentbi", DV_DULL
106 };
107
108 int gentbi_service(struct mii_softc *, struct mii_data *, int);
109 void gentbi_status(struct mii_softc *);
110
111 const struct mii_phy_funcs gentbi_funcs = {
112 gentbi_service, gentbi_status, mii_phy_reset,
113 };
114
115 int
116 gentbimatch(struct device *parent, void *match, void *aux)
117 {
118 struct mii_attach_args *ma = aux;
119 struct mii_data *mii = ma->mii_data;
120 int bmsr, extsr;
121
122 /*
123 * We match as a generic TBI if:
124 *
125 * - There is no media in the BMSR.
126 * - EXTSR has only 1000X.
127 */
128 bmsr = (*mii->mii_readreg)(parent, ma->mii_phyno, MII_BMSR);
129 if ((bmsr & BMSR_EXTSTAT) == 0 || (bmsr & BMSR_MEDIAMASK) != 0)
130 return (0);
131
132 extsr = (*mii->mii_readreg)(parent, ma->mii_phyno, MII_EXTSR);
133 if (extsr & (EXTSR_1000TFDX|EXTSR_1000THDX))
134 return (0);
135
136 if (extsr & (EXTSR_1000XFDX|EXTSR_1000XHDX)) {
137 /*
138 * We think this is a generic TBI. Return a match
139 * priority higher than ukphy, but lower than what
140 * specific drivers will return.
141 */
142 return (2);
143 }
144
145 return (0);
146 }
147
148 void
149 gentbiattach(struct device *parent, struct device *self, void *aux)
150 {
151 struct mii_softc *sc = (struct mii_softc *)self;
152 struct mii_attach_args *ma = aux;
153 struct mii_data *mii = ma->mii_data;
154
155 printf(": Generic ten-bit interface, rev. %d\n",
156 MII_REV(ma->mii_id2));
157
158 sc->mii_inst = mii->mii_instance;
159 sc->mii_phy = ma->mii_phyno;
160 sc->mii_funcs = &gentbi_funcs;
161 sc->mii_pdata = mii;
162 sc->mii_flags = ma->mii_flags;
163 sc->mii_anegticks = MII_ANEGTICKS;
164
165 PHY_RESET(sc);
166
167 /*
168 * Mask out all media in the BMSR. We only are really interested
169 * in "auto".
170 */
171 sc->mii_capabilities =
172 PHY_READ(sc, MII_BMSR) & ma->mii_capmask & ~BMSR_MEDIAMASK;
173 if (sc->mii_capabilities & BMSR_EXTSTAT)
174 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
175
176 if ((sc->mii_capabilities & BMSR_MEDIAMASK) ||
177 (sc->mii_extcapabilities & EXTSR_MEDIAMASK))
178 mii_phy_add_media(sc);
179 }
180
181 int
182 gentbi_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
183 {
184 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
185 int reg;
186
187 switch (cmd) {
188 case MII_POLLSTAT:
189 /*
190 * If we're not polling our PHY instance, just return.
191 */
192 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
193 return (0);
194 break;
195
196 case MII_MEDIACHG:
197 /*
198 * If the media indicates a different PHY instance,
199 * isolate ourselves.
200 */
201 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
202 reg = PHY_READ(sc, MII_BMCR);
203 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
204 return (0);
205 }
206
207 /*
208 * If the interface is not up, don't do anything.
209 */
210 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
211 break;
212
213 mii_phy_setmedia(sc);
214 break;
215
216 case MII_TICK:
217 /*
218 * If we're not currently selected, just return.
219 */
220 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
221 return (0);
222
223 if (mii_phy_tick(sc) == EJUSTRETURN)
224 return (0);
225 break;
226
227 case MII_DOWN:
228 mii_phy_down(sc);
229 return (0);
230 }
231
232 /* Update the media status. */
233 mii_phy_status(sc);
234
235 /* Callback if something changed. */
236 mii_phy_update(sc, cmd);
237 return (0);
238 }
239
240 void
241 gentbi_status(struct mii_softc *sc)
242 {
243 struct mii_data *mii = sc->mii_pdata;
244 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
245 int bmsr, bmcr, anlpar;
246
247 mii->mii_media_status = IFM_AVALID;
248 mii->mii_media_active = IFM_ETHER;
249
250 bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
251
252 if (bmsr & BMSR_LINK)
253 mii->mii_media_status |= IFM_ACTIVE;
254
255 bmcr = PHY_READ(sc, MII_BMCR);
256 if (bmcr & BMCR_ISO) {
257 mii->mii_media_active |= IFM_NONE;
258 mii->mii_media_status = 0;
259 return;
260 }
261
262 if (bmcr & BMCR_LOOP)
263 mii->mii_media_active |= IFM_LOOP;
264
265 if (bmcr & BMCR_AUTOEN) {
266 /*
267 * The media status bits are only valid of autonegotiation
268 * has completed (or it's disabled).
269 */
270 if ((bmsr & BMSR_ACOMP) == 0) {
271 /* Erg, still trying, I guess... */
272 mii->mii_media_active |= IFM_NONE;
273 return;
274 }
275
276 /*
277 * The media is always 1000baseSX. Check the ANLPAR to
278 * see if we're doing full-duplex.
279 */
280 mii->mii_media_active |= IFM_1000_SX;
281
282 anlpar = PHY_READ(sc, MII_ANLPAR);
283 if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0 &&
284 (anlpar & ANLPAR_X_FD) != 0)
285 mii->mii_media_active |=
286 IFM_FDX;
287 } else
288 mii->mii_media_active = ife->ifm_media;
289 }