1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6
7 #include "../port/netif.h"
8
9 #include "ethermii.h"
10
11 static int
miiprobe(Mii * mii,int mask)12 miiprobe(Mii* mii, int mask)
13 {
14 MiiPhy *miiphy;
15 int bit, oui, phyno, r, rmask;
16
17 /*
18 * Probe through mii for PHYs in mask;
19 * return the mask of those found in the current probe.
20 * If the PHY has not already been probed, update
21 * the Mii information.
22 */
23 rmask = 0;
24 for(phyno = 0; phyno < NMiiPhy; phyno++){
25 bit = 1<<phyno;
26 if(!(mask & bit))
27 continue;
28 if(mii->mask & bit){
29 rmask |= bit;
30 continue;
31 }
32 if(mii->rw(mii, 0, phyno, Bmsr, 0) == -1)
33 continue;
34 r = mii->rw(mii, 0, phyno, Phyidr1, 0)<<16;
35 r |= mii->rw(mii, 0, phyno, Phyidr2, 0);
36 oui = (r>>10) & 0xffff;
37 if(oui == 0xffff || oui == 0)
38 continue;
39
40 if((miiphy = malloc(sizeof(MiiPhy))) == nil)
41 continue;
42
43 miiphy->mii = mii;
44 miiphy->phyno = phyno;
45 miiphy->phyid = r;
46 miiphy->oui = oui;
47
48 miiphy->anar = ~0;
49 miiphy->fc = ~0;
50 miiphy->mscr = ~0;
51
52 mii->phy[phyno] = miiphy;
53 if(mii->curphy == nil)
54 mii->curphy = miiphy;
55 mii->mask |= bit;
56 mii->nphy++;
57
58 rmask |= bit;
59 }
60 return rmask;
61 }
62
63 int
miimir(Mii * mii,int r)64 miimir(Mii* mii, int r)
65 {
66 if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
67 return -1;
68 return mii->rw(mii, 0, mii->curphy->phyno, r, 0);
69 }
70
71 int
miimiw(Mii * mii,int r,int data)72 miimiw(Mii* mii, int r, int data)
73 {
74 if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
75 return -1;
76 return mii->rw(mii, 1, mii->curphy->phyno, r, data);
77 }
78
79 int
miireset(Mii * mii)80 miireset(Mii* mii)
81 {
82 int bmcr, timeo;
83
84 if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
85 return -1;
86 bmcr = mii->rw(mii, 0, mii->curphy->phyno, Bmcr, 0);
87 mii->rw(mii, 1, mii->curphy->phyno, Bmcr, BmcrR|bmcr);
88 for(timeo = 0; timeo < 1000; timeo++){
89 bmcr = mii->rw(mii, 0, mii->curphy->phyno, Bmcr, 0);
90 if(!(bmcr & BmcrR))
91 break;
92 microdelay(1);
93 }
94 if(bmcr & BmcrR)
95 return -1;
96 if(bmcr & BmcrI)
97 mii->rw(mii, 1, mii->curphy->phyno, Bmcr, bmcr & ~BmcrI);
98 return 0;
99 }
100
101 int
miiane(Mii * mii,int a,int p,int e)102 miiane(Mii* mii, int a, int p, int e)
103 {
104 int anar, bmsr, mscr, r, phyno;
105
106 if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
107 return -1;
108 phyno = mii->curphy->phyno;
109
110 mii->rw(mii, 1, phyno, Bmsr, 0);
111 bmsr = mii->rw(mii, 0, phyno, Bmsr, 0);
112 if(!(bmsr & BmsrAna))
113 return -1;
114
115 if(a != ~0)
116 anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
117 else if(mii->curphy->anar != ~0)
118 anar = mii->curphy->anar;
119 else{
120 anar = mii->rw(mii, 0, phyno, Anar, 0);
121 anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
122 if(bmsr & Bmsr10THD)
123 anar |= Ana10HD;
124 if(bmsr & Bmsr10TFD)
125 anar |= Ana10FD;
126 if(bmsr & Bmsr100TXHD)
127 anar |= AnaTXHD;
128 if(bmsr & Bmsr100TXFD)
129 anar |= AnaTXFD;
130 }
131 mii->curphy->anar = anar;
132
133 if(p != ~0)
134 anar |= (AnaAP|AnaP) & p;
135 else if(mii->curphy->fc != ~0)
136 anar |= mii->curphy->fc;
137 mii->curphy->fc = (AnaAP|AnaP) & anar;
138
139 if(bmsr & BmsrEs){
140 mscr = mii->rw(mii, 0, phyno, Mscr, 0);
141 mscr &= ~(Mscr1000TFD|Mscr1000THD);
142 if(e != ~0)
143 mscr |= (Mscr1000TFD|Mscr1000THD) & e;
144 else if(mii->curphy->mscr != ~0)
145 mscr = mii->curphy->mscr;
146 else{
147 r = mii->rw(mii, 0, phyno, Esr, 0);
148 if(r & Esr1000THD)
149 mscr |= Mscr1000THD;
150 if(r & Esr1000TFD)
151 mscr |= Mscr1000TFD;
152 }
153 mii->curphy->mscr = mscr;
154 mii->rw(mii, 1, phyno, Mscr, mscr);
155 }
156 else
157 mii->curphy->mscr = 0;
158 mii->rw(mii, 1, phyno, Anar, anar);
159
160 r = mii->rw(mii, 0, phyno, Bmcr, 0);
161 if(!(r & BmcrR)){
162 r |= BmcrAne|BmcrRan;
163 mii->rw(mii, 1, phyno, Bmcr, r);
164 }
165
166 return 0;
167 }
168
169 int
miistatus(Mii * mii)170 miistatus(Mii* mii)
171 {
172 MiiPhy *phy;
173 int anlpar, bmsr, p, r, phyno;
174
175 if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
176 return -1;
177 phy = mii->curphy;
178 phyno = phy->phyno;
179
180 /*
181 * Check Auto-Negotiation is complete and link is up.
182 * (Read status twice as the Ls bit is sticky).
183 */
184 bmsr = mii->rw(mii, 0, phyno, Bmsr, 0);
185 if(!(bmsr & (BmsrAnc|BmsrAna)))
186 return -1;
187
188 bmsr = mii->rw(mii, 0, phyno, Bmsr, 0);
189 if(!(bmsr & BmsrLs)){
190 phy->link = 0;
191 return -1;
192 }
193
194 phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
195 if(phy->mscr){
196 r = mii->rw(mii, 0, phyno, Mssr, 0);
197 if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
198 phy->speed = 1000;
199 phy->fd = 1;
200 }
201 else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
202 phy->speed = 1000;
203 }
204
205 anlpar = mii->rw(mii, 0, phyno, Anlpar, 0);
206 if(phy->speed == 0){
207 r = phy->anar & anlpar;
208 if(r & AnaTXFD){
209 phy->speed = 100;
210 phy->fd = 1;
211 }
212 else if(r & AnaTXHD)
213 phy->speed = 100;
214 else if(r & Ana10FD){
215 phy->speed = 10;
216 phy->fd = 1;
217 }
218 else if(r & Ana10HD)
219 phy->speed = 10;
220 }
221 if(phy->speed == 0)
222 return -1;
223
224 if(phy->fd){
225 p = phy->fc;
226 r = anlpar & (AnaAP|AnaP);
227 if(p == AnaAP && r == (AnaAP|AnaP))
228 phy->tfc = 1;
229 else if(p == (AnaAP|AnaP) && r == AnaAP)
230 phy->rfc = 1;
231 else if((p & AnaP) && (r & AnaP))
232 phy->rfc = phy->tfc = 1;
233 }
234
235 phy->link = 1;
236
237 return 0;
238 }
239
240 char*
miidumpphy(Mii * mii,char * p,char * e)241 miidumpphy(Mii* mii, char* p, char* e)
242 {
243 int i, r;
244
245 if(mii == nil || mii->curphy == nil)
246 return p;
247
248 p = seprint(p, e, "phy: ");
249 for(i = 0; i < NMiiPhyr; i++){
250 if(i && ((i & 0x07) == 0))
251 p = seprint(p, e, "\n ");
252 r = mii->rw(mii, 0, mii->curphy->phyno, i, 0);
253 p = seprint(p, e, " %4.4ux", r);
254 }
255 p = seprint(p, e, "\n");
256
257 return p;
258 }
259
260 void
miidetach(Mii * mii)261 miidetach(Mii* mii)
262 {
263 int i;
264
265 for(i = 0; i < NMiiPhy; i++){
266 if(mii->phy[i] == nil)
267 continue;
268 free(mii);
269 mii->phy[i] = nil;
270 }
271 free(mii);
272 }
273
274 Mii*
miiattach(void * ctlr,int mask,int (* rw)(Mii *,int,int,int,int))275 miiattach(void* ctlr, int mask, int (*rw)(Mii*, int, int, int, int))
276 {
277 Mii* mii;
278
279 if((mii = malloc(sizeof(Mii))) == nil)
280 return nil;
281 mii->ctlr = ctlr;
282 mii->rw = rw;
283
284 if(miiprobe(mii, mask) == 0){
285 free(mii);
286 mii = nil;
287 }
288
289 return mii;
290 }
291