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