Line data Source code
1 : /* $OpenBSD: mtdphy.c,v 1.15 2015/03/14 03:38:48 jsg Exp $ */
2 :
3 : /*
4 : * Copyright (c) 1998, 1999 Jason L. Wright (jason@thought.net)
5 : * All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : *
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 : * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 : * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 : * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 : * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 : * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 : * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 : * POSSIBILITY OF SUCH DAMAGE.
27 : */
28 :
29 : /*
30 : * Driver for the Myson Technology MTD972 100BaseTX PCS/PMA.
31 : */
32 :
33 : #include <sys/param.h>
34 : #include <sys/systm.h>
35 : #include <sys/kernel.h>
36 : #include <sys/device.h>
37 : #include <sys/socket.h>
38 : #include <sys/errno.h>
39 :
40 : #include <net/if.h>
41 : #include <net/if_var.h>
42 : #include <net/if_media.h>
43 :
44 : #include <dev/mii/mii.h>
45 : #include <dev/mii/miivar.h>
46 : #include <dev/mii/miidevs.h>
47 :
48 : int mtdphymatch(struct device *, void *, void *);
49 : void mtdphyattach(struct device *, struct device *, void *);
50 :
51 : struct cfattach mtdphy_ca = {
52 : sizeof(struct mii_softc), mtdphymatch, mtdphyattach, mii_phy_detach
53 : };
54 :
55 : struct cfdriver mtdphy_cd = {
56 : NULL, "mtdphy", DV_DULL
57 : };
58 :
59 : int mtdphy_service(struct mii_softc *, struct mii_data *, int);
60 :
61 : const struct mii_phy_funcs mtdphy_funcs = {
62 : mtdphy_service, ukphy_status, mii_phy_reset,
63 : };
64 :
65 : static const struct mii_phydesc mtdphys[] = {
66 : { MII_OUI_MYSON, MII_MODEL_MYSON_MTD972,
67 : MII_STR_MYSON_MTD972 },
68 :
69 : { 0, 0,
70 : NULL },
71 : };
72 :
73 : int
74 0 : mtdphymatch(struct device *parent, void *match, void *aux)
75 : {
76 0 : struct mii_attach_args *ma = aux;
77 :
78 0 : if (mii_phy_match(ma, mtdphys) != NULL)
79 0 : return (10);
80 :
81 0 : return (0);
82 0 : }
83 :
84 : void
85 0 : mtdphyattach(struct device *parent, struct device *self, void *aux)
86 : {
87 0 : struct mii_softc *sc = (struct mii_softc *)self;
88 0 : struct mii_attach_args *ma = aux;
89 0 : struct mii_data *mii = ma->mii_data;
90 : const struct mii_phydesc *mpd;
91 :
92 0 : mpd = mii_phy_match(ma, mtdphys);
93 0 : printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
94 :
95 0 : sc->mii_inst = mii->mii_instance;
96 0 : sc->mii_phy = ma->mii_phyno;
97 0 : sc->mii_funcs = &mtdphy_funcs;
98 0 : sc->mii_pdata = mii;
99 0 : sc->mii_flags = ma->mii_flags;
100 :
101 0 : PHY_RESET(sc);
102 :
103 0 : sc->mii_capabilities =
104 0 : PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
105 0 : if (sc->mii_capabilities & BMSR_MEDIAMASK)
106 0 : mii_phy_add_media(sc);
107 0 : }
108 :
109 : int
110 0 : mtdphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
111 : {
112 0 : struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
113 : int reg;
114 :
115 0 : if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
116 0 : return (ENXIO);
117 :
118 0 : switch (cmd) {
119 : case MII_POLLSTAT:
120 : /*
121 : * If we're not polling our PHY instance, just return.
122 : */
123 0 : if (IFM_INST(ife->ifm_media) != sc->mii_inst)
124 0 : return (0);
125 : break;
126 :
127 : case MII_MEDIACHG:
128 : /*
129 : * If the interface is not up, don't do anything.
130 : */
131 0 : if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
132 0 : reg = PHY_READ(sc, MII_BMCR);
133 0 : PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
134 0 : return (0);
135 : }
136 :
137 0 : if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
138 : break;
139 :
140 0 : mii_phy_setmedia(sc);
141 0 : break;
142 :
143 : case MII_TICK:
144 : /*
145 : *If we're not currently selected, just return.
146 : */
147 0 : if (IFM_INST(ife->ifm_media) != sc->mii_inst)
148 0 : return (0);
149 :
150 0 : if (mii_phy_tick(sc) == EJUSTRETURN)
151 0 : return (0);
152 : break;
153 :
154 : case MII_DOWN:
155 0 : mii_phy_down(sc);
156 0 : return (0);
157 : }
158 :
159 : /* Update the media status. */
160 0 : mii_phy_status(sc);
161 :
162 : /* Callback if something changed. */
163 0 : mii_phy_update(sc, cmd);
164 0 : return (0);
165 0 : }
|