Annotation of sys/dev/mii/acphy.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: acphy.c,v 1.6 2006/12/27 19:11:08 kettenis Exp $ */
2: /* $NetBSD: acphy.c,v 1.13 2003/04/29 01:49:33 thorpej Exp $ */
3:
4: /*
5: * Copyright 2001 Wasabi Systems, Inc.
6: * All rights reserved.
7: *
8: * Written by Jason R. Thorpe for Wasabi Systems, Inc.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed for the NetBSD Project by
21: * Wasabi Systems, Inc.
22: * 4. The name of Wasabi Systems, Inc. may not be used to endorse
23: * or promote products derived from this software without specific prior
24: * written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
38:
39: /*
40: * Driver for the Altima AC101 PHY.
41: */
42:
43: #include <sys/param.h>
44: #include <sys/systm.h>
45: #include <sys/kernel.h>
46: #include <sys/device.h>
47: #include <sys/socket.h>
48: #include <sys/errno.h>
49:
50: #include <net/if.h>
51: #include <net/if_media.h>
52:
53: #include <dev/mii/mii.h>
54: #include <dev/mii/miivar.h>
55: #include <dev/mii/miidevs.h>
56:
57: #include <dev/mii/acphyreg.h>
58:
59: int acphymatch(struct device *, void *, void *);
60: void acphyattach(struct device *, struct device *, void *);
61:
62: struct cfattach acphy_ca = {
63: sizeof(struct mii_softc), acphymatch, acphyattach, mii_phy_detach,
64: mii_phy_activate
65: };
66:
67: struct cfdriver acphy_cd = {
68: NULL, "acphy", DV_DULL
69: };
70:
71: int acphy_service(struct mii_softc *, struct mii_data *, int);
72: void acphy_status(struct mii_softc *);
73:
74: const struct mii_phy_funcs acphy_funcs = {
75: acphy_service, acphy_status, mii_phy_reset,
76: };
77:
78: static const struct mii_phydesc acphys[] = {
79: { MII_OUI_xxALTIMA, MII_MODEL_xxALTIMA_AC101,
80: MII_STR_xxALTIMA_AC101 },
81: { MII_OUI_xxALTIMA, MII_MODEL_xxALTIMA_AC101L,
82: MII_STR_xxALTIMA_AC101L },
83: { MII_OUI_xxALTIMA, MII_MODEL_xxALTIMA_AC_UNKNOWN,
84: MII_STR_xxALTIMA_AC_UNKNOWN },
85:
86: { 0, 0,
87: NULL },
88: };
89:
90: int
91: acphymatch(struct device *parent, void *match, void *aux)
92: {
93: struct mii_attach_args *ma = aux;
94:
95: if (mii_phy_match(ma, acphys) != NULL)
96: return (10);
97:
98: return (0);
99: }
100:
101: void
102: acphyattach(struct device *parent, struct device *self, void *aux)
103: {
104: struct mii_softc *sc = (struct mii_softc *)self;
105: struct mii_attach_args *ma = aux;
106: struct mii_data *mii = ma->mii_data;
107: const struct mii_phydesc *mpd;
108:
109: mpd = mii_phy_match(ma, acphys);
110: printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
111:
112: sc->mii_inst = mii->mii_instance;
113: sc->mii_phy = ma->mii_phyno;
114: sc->mii_funcs = &acphy_funcs;
115: sc->mii_pdata = mii;
116: sc->mii_flags = ma->mii_flags;
117: sc->mii_anegticks = MII_ANEGTICKS;
118:
119: PHY_RESET(sc);
120:
121: /*
122: * XXX Check MCR_FX_SEL to set MIIF_HAVE_FIBER?
123: */
124:
125: sc->mii_capabilities =
126: PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
127:
128: #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
129: if (sc->mii_flags & MIIF_HAVEFIBER) {
130: ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, 0, sc->mii_inst),
131: MII_MEDIA_100_TX);
132: ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, sc->mii_inst),
133: MII_MEDIA_100_TX);
134: }
135: #undef ADD
136:
137: if (sc->mii_capabilities & BMSR_MEDIAMASK)
138: mii_phy_add_media(sc);
139: }
140:
141: int
142: acphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
143: {
144: struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
145: int reg;
146:
147: switch (cmd) {
148: case MII_POLLSTAT:
149: /*
150: * If we're not polling our PHY instance, just return.
151: */
152: if (IFM_INST(ife->ifm_media) != sc->mii_inst)
153: return (0);
154: break;
155:
156: case MII_MEDIACHG:
157: /*
158: * If the media indicates a different PHY instance,
159: * isolate ourselves.
160: */
161: if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
162: reg = PHY_READ(sc, MII_BMCR);
163: PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
164: return (0);
165: }
166:
167: /*
168: * If the interface is not up, don't do anything.
169: */
170: if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
171: break;
172:
173: mii_phy_setmedia(sc);
174: break;
175:
176: case MII_TICK:
177: /*
178: * If we're not currently selected, just return.
179: */
180: if (IFM_INST(ife->ifm_media) != sc->mii_inst)
181: return (0);
182:
183: if (mii_phy_tick(sc) == EJUSTRETURN)
184: return (0);
185: break;
186:
187: case MII_DOWN:
188: mii_phy_down(sc);
189: return (0);
190: }
191:
192: /* Update the media status. */
193: mii_phy_status(sc);
194:
195: /* Callback if something changed. */
196: mii_phy_update(sc, cmd);
197: return (0);
198: }
199:
200: void
201: acphy_status(struct mii_softc *sc)
202: {
203: struct mii_data *mii = sc->mii_pdata;
204: struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
205: int bmsr, bmcr, dr;
206:
207: mii->mii_media_status = IFM_AVALID;
208: mii->mii_media_active = IFM_ETHER;
209:
210: bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
211: dr = PHY_READ(sc, MII_ACPHY_DR);
212:
213: if (bmsr & BMSR_LINK)
214: mii->mii_media_status |= IFM_ACTIVE;
215:
216: bmcr = PHY_READ(sc, MII_BMCR);
217: if (bmcr & BMCR_ISO) {
218: mii->mii_media_active |= IFM_NONE;
219: mii->mii_media_status = 0;
220: return;
221: }
222:
223: if (bmcr & BMCR_LOOP)
224: mii->mii_media_active |= IFM_LOOP;
225:
226: if (bmcr & BMCR_AUTOEN) {
227: /*
228: * The media status bits are only valid if autonegotiation
229: * has completed (or it's disabled).
230: */
231: if ((bmsr & BMSR_ACOMP) == 0) {
232: /* Erg, still trying, I guess... */
233: mii->mii_media_active |= IFM_NONE;
234: return;
235: }
236:
237: if (dr & DR_SPEED)
238: mii->mii_media_active |= IFM_100_TX;
239: else
240: mii->mii_media_active |= IFM_10_T;
241:
242: if (dr & DR_DPLX)
243: mii->mii_media_active |= IFM_FDX;
244: else
245: mii->mii_media_active |= IFM_HDX;
246: } else
247: mii->mii_media_active = ife->ifm_media;
248: }
CVSweb