Annotation of sys/dev/mii/lxtphy.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: lxtphy.c,v 1.15 2006/12/27 19:11:09 kettenis Exp $ */
2: /* $NetBSD: lxtphy.c,v 1.19 2000/02/02 23:34:57 thorpej Exp $ */
3:
4: /*-
5: * Copyright (c) 1998, 1999 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 Level One's LXT-970/971 ethernet 10/100 PHY
72: * datasheet from www.level1.com
73: */
74:
75: #include <sys/param.h>
76: #include <sys/systm.h>
77: #include <sys/kernel.h>
78: #include <sys/device.h>
79: #include <sys/socket.h>
80: #include <sys/errno.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/lxtphyreg.h>
90:
91: int lxtphymatch(struct device *, void *, void *);
92: void lxtphyattach(struct device *, struct device *, void *);
93:
94: struct cfattach lxtphy_ca = {
95: sizeof(struct mii_softc), lxtphymatch, lxtphyattach, mii_phy_detach,
96: mii_phy_activate
97: };
98:
99: struct cfdriver lxtphy_cd = {
100: NULL, "lxtphy", DV_DULL
101: };
102:
103: int lxtphy_service(struct mii_softc *, struct mii_data *, int);
104: void lxtphy_status(struct mii_softc *);
105: void lxtphy_reset(struct mii_softc *);
106:
107: const struct mii_phy_funcs lxtphy_funcs = {
108: lxtphy_service, lxtphy_status, lxtphy_reset,
109: };
110:
111: const struct mii_phy_funcs lxtphy971_funcs = {
112: lxtphy_service, ukphy_status, lxtphy_reset,
113: };
114:
115: static const struct mii_phydesc lxtphys[] = {
116: { MII_OUI_xxLEVEL1, MII_MODEL_xxLEVEL1_LXT970,
117: MII_STR_xxLEVEL1_LXT970 },
118: { MII_OUI_xxLEVEL1a, MII_MODEL_xxLEVEL1a_LXT971,
119: MII_STR_xxLEVEL1a_LXT971 },
120:
121: { 0, 0,
122: NULL },
123: };
124:
125: int
126: lxtphymatch(parent, match, aux)
127: struct device *parent;
128: void *match;
129: void *aux;
130: {
131: struct mii_attach_args *ma = aux;
132:
133: if (mii_phy_match(ma, lxtphys) != NULL)
134: return (10);
135:
136: return (0);
137: }
138:
139: void
140: lxtphyattach(parent, self, aux)
141: struct device *parent, *self;
142: void *aux;
143: {
144: struct mii_softc *sc = (struct mii_softc *)self;
145: struct mii_attach_args *ma = aux;
146: struct mii_data *mii = ma->mii_data;
147: const struct mii_phydesc *mpd;
148:
149: if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxLEVEL1 &&
150: MII_MODEL(ma->mii_id2) == MII_MODEL_xxLEVEL1_LXT970) {
151: sc->mii_funcs = &lxtphy_funcs;
152: }
153: if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxLEVEL1a &&
154: MII_MODEL(ma->mii_id2) == MII_MODEL_xxLEVEL1a_LXT971) {
155: sc->mii_funcs = &lxtphy971_funcs;
156: }
157:
158: mpd = mii_phy_match(ma, lxtphys);
159: printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
160:
161: sc->mii_inst = mii->mii_instance;
162: sc->mii_phy = ma->mii_phyno;
163: sc->mii_pdata = mii;
164: sc->mii_flags = ma->mii_flags;
165:
166: PHY_RESET(sc);
167:
168: sc->mii_capabilities =
169: PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
170: if (sc->mii_capabilities & BMSR_MEDIAMASK)
171: mii_phy_add_media(sc);
172: }
173:
174: int
175: lxtphy_service(sc, mii, cmd)
176: struct mii_softc *sc;
177: struct mii_data *mii;
178: int cmd;
179: {
180: struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
181: int reg;
182:
183: if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
184: return (ENXIO);
185:
186: switch (cmd) {
187: case MII_POLLSTAT:
188: /*
189: * If we're not polling our PHY instance, just return.
190: */
191: if (IFM_INST(ife->ifm_media) != sc->mii_inst)
192: return (0);
193: break;
194:
195: case MII_MEDIACHG:
196: /*
197: * If the media indicates a different PHY instance,
198: * isolate ourselves.
199: */
200: if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
201: reg = PHY_READ(sc, MII_BMCR);
202: PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
203: return (0);
204: }
205:
206: /*
207: * If the interface is not up, don't do anything.
208: */
209: if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
210: break;
211:
212: mii_phy_setmedia(sc);
213: break;
214:
215: case MII_TICK:
216: /*
217: * If we're not currently selected, just return.
218: */
219: if (IFM_INST(ife->ifm_media) != sc->mii_inst)
220: return (0);
221:
222: if (mii_phy_tick(sc) == EJUSTRETURN)
223: return (0);
224: break;
225:
226: case MII_DOWN:
227: mii_phy_down(sc);
228: return (0);
229: }
230:
231: /* Update the media status. */
232: mii_phy_status(sc);
233:
234: /* Callback if something changed. */
235: mii_phy_update(sc, cmd);
236: return (0);
237: }
238:
239: void
240: lxtphy_status(sc)
241: 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 bmcr, bmsr, csr;
246:
247: mii->mii_media_status = IFM_AVALID;
248: mii->mii_media_active = IFM_ETHER;
249:
250: /*
251: * Get link status from the CSR; we need to read the CSR
252: * for media type anyhow, and the link status in the CSR
253: * doens't latch, so fewer register reads are required.
254: */
255: csr = PHY_READ(sc, MII_LXTPHY_CSR);
256: if (csr & CSR_LINK)
257: mii->mii_media_status |= IFM_ACTIVE;
258:
259: bmcr = PHY_READ(sc, MII_BMCR);
260: if (bmcr & BMCR_ISO) {
261: mii->mii_media_active |= IFM_NONE;
262: mii->mii_media_status = 0;
263: return;
264: }
265:
266: if (bmcr & BMCR_LOOP)
267: mii->mii_media_active |= IFM_LOOP;
268:
269: if (bmcr & BMCR_AUTOEN) {
270: bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
271: if ((bmsr & BMSR_ACOMP) == 0) {
272: /* Erg, still trying, I guess... */
273: mii->mii_media_active |= IFM_NONE;
274: return;
275: }
276: if (csr & CSR_SPEED)
277: mii->mii_media_active |= IFM_100_TX;
278: else
279: mii->mii_media_active |= IFM_10_T;
280:
281: if (csr & CSR_DUPLEX)
282: mii->mii_media_active |= IFM_FDX;
283: else
284: mii->mii_media_active |= IFM_HDX;
285: } else
286: mii->mii_media_active = ife->ifm_media;
287: }
288:
289: void
290: lxtphy_reset(sc)
291: struct mii_softc *sc;
292: {
293: mii_phy_reset(sc);
294: PHY_WRITE(sc, MII_LXTPHY_IER,
295: PHY_READ(sc, MII_LXTPHY_IER) & ~IER_INTEN);
296: }
CVSweb