xref: /dragonfly/sys/dev/netif/mii_layer/ukphy.c (revision bff82488b6f45c2f067e4c552e649b1d3e07cd7c)
1 /*        $NetBSD: ukphy.c,v 1.27 2006/03/29 07:05:24 thorpej Exp $   */
2 
3 /*-
4  * Copyright (c) 1998, 1999, 2000 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, and by Frank van der Linden.
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  * $FreeBSD: src/sys/dev/mii/ukphy.c,v 1.2.2.2 2002/11/08 21:53:49 semenu Exp $
40  */
41 
42 /*
43  * Copyright (c) 1997 Manuel Bouyer.  All rights reserved.
44  *
45  * Redistribution and use in source and binary forms, with or without
46  * modification, are permitted provided that the following conditions
47  * are met:
48  * 1. Redistributions of source code must retain the above copyright
49  *    notice, this list of conditions and the following disclaimer.
50  * 2. Redistributions in binary form must reproduce the above copyright
51  *    notice, this list of conditions and the following disclaimer in the
52  *    documentation and/or other materials provided with the distribution.
53  * 3. All advertising materials mentioning features or use of this software
54  *    must display the following acknowledgement:
55  *        This product includes software developed by Manuel Bouyer.
56  * 4. The name of the author may not be used to endorse or promote products
57  *    derived from this software without specific prior written permission.
58  *
59  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
60  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
61  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
63  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
64  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
65  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
66  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
67  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
68  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69  */
70 
71 /*
72  * driver for generic unknown PHYs
73  */
74 
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/kernel.h>
78 #include <sys/socket.h>
79 #include <sys/errno.h>
80 #include <sys/module.h>
81 #include <sys/bus.h>
82 
83 #include <net/if.h>
84 #include <net/if_var.h>
85 #include <net/if_media.h>
86 
87 #include <machine/clock.h>
88 
89 #include "mii.h"
90 #include "miivar.h"
91 
92 #include "miibus_if.h"
93 
94 static int          ukphy_service(struct mii_softc *, struct mii_data *, int);
95 static int          ukphy_probe(device_t);
96 
97 static device_method_t ukphy_methods[] = {
98           /* device interface */
99           DEVMETHOD(device_probe,                 ukphy_probe),
100           DEVMETHOD(device_attach,      ukphy_attach),
101           DEVMETHOD(device_detach,      ukphy_detach),
102           DEVMETHOD(device_shutdown,    bus_generic_shutdown),
103           DEVMETHOD_END
104 };
105 
106 static devclass_t ukphy_devclass;
107 
108 static driver_t ukphy_driver = {
109           "ukphy",
110           ukphy_methods,
111           sizeof(struct mii_softc)
112 };
113 
114 DRIVER_MODULE(ukphy, miibus, ukphy_driver, ukphy_devclass, NULL, NULL);
115 
116 static int
ukphy_probe(device_t dev)117 ukphy_probe(device_t dev)
118 {
119 
120           /*
121            * We know something is here, so always match at a low priority.
122            */
123           device_set_desc(dev, "Generic IEEE 802.3u media interface");
124           return (-100);
125 }
126 
127 int
ukphy_attach(device_t dev)128 ukphy_attach(device_t dev)
129 {
130           struct mii_softc *sc;
131           struct mii_attach_args *ma;
132           struct mii_data *mii;
133 
134           sc = device_get_softc(dev);
135           ma = device_get_ivars(dev);
136 
137           mii_softc_init(sc, ma);
138           sc->mii_dev = device_get_parent(dev);
139           mii = device_get_softc(sc->mii_dev);
140           LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
141 
142           if (bootverbose) {
143                     device_printf(dev, "OUI 0x%06x, model 0x%04x, rev. %d\n",
144                         MII_OUI(ma->mii_id1, ma->mii_id2),
145                         MII_MODEL(ma->mii_id2), MII_REV(ma->mii_id2));
146           }
147 
148           sc->mii_inst = mii->mii_instance;
149           sc->mii_service = ukphy_service;
150           sc->mii_pdata = mii;
151 
152           mii->mii_instance++;
153 
154           /*
155            * Don't do loopback on unknown PHYs.  It might confuse some of them.
156            */
157           sc->mii_flags |= MIIF_NOLOOP;
158 
159           mii_phy_reset(sc);
160 
161           sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
162           if (sc->mii_capabilities & BMSR_EXTSTAT)
163                     sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
164 
165           device_printf(dev, " ");
166           if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
167               (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
168                     kprintf("no media present");
169           else
170                     mii_phy_add_media(sc);
171           kprintf("\n");
172 
173           MIIBUS_MEDIAINIT(sc->mii_dev);
174           return(0);
175 }
176 
177 int
ukphy_detach(device_t dev)178 ukphy_detach(device_t dev)
179 {
180           struct mii_softc *sc;
181 
182           sc = device_get_softc(dev);
183           sc->mii_dev = NULL;
184           LIST_REMOVE(sc, mii_list);
185 
186           return(0);
187 }
188 
189 static int
ukphy_service(struct mii_softc * sc,struct mii_data * mii,int cmd)190 ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
191 {
192           struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
193           int reg;
194 
195           switch (cmd) {
196           case MII_POLLSTAT:
197                     /*
198                      * If we're not polling our PHY instance, just return.
199                      */
200                     if (IFM_INST(ife->ifm_media) != sc->mii_inst)
201                               return (0);
202                     break;
203 
204           case MII_MEDIACHG:
205                     /*
206                      * If the media indicates a different PHY instance,
207                      * isolate ourselves.
208                      */
209                     if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
210                               reg = PHY_READ(sc, MII_BMCR);
211                               PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
212                               return (0);
213                     }
214 
215                     /*
216                      * If the interface is not up, don't do anything.
217                      */
218                     if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
219                               break;
220 
221                     mii_phy_set_media(sc);
222                     break;
223 
224           case MII_TICK:
225                     /*
226                      * If we're not currently selected, just return.
227                      */
228                     if (IFM_INST(ife->ifm_media) != sc->mii_inst)
229                               return (0);
230 
231                     if (mii_phy_tick(sc) == EJUSTRETURN)
232                               return (0);
233                     break;
234           }
235 
236           /* Update the media status. */
237           ukphy_status(sc);
238 
239           /* Callback if something changed. */
240           mii_phy_update(sc, cmd);
241           return (0);
242 }
243