1*74a4d8c2SCharles.Forsyth #include "u.h"
2*74a4d8c2SCharles.Forsyth #include "lib.h"
3*74a4d8c2SCharles.Forsyth #include "mem.h"
4*74a4d8c2SCharles.Forsyth #include "dat.h"
5*74a4d8c2SCharles.Forsyth #include "fns.h"
6*74a4d8c2SCharles.Forsyth #include "io.h"
7*74a4d8c2SCharles.Forsyth
8*74a4d8c2SCharles.Forsyth #include "etherif.h"
9*74a4d8c2SCharles.Forsyth #include "ethermii.h"
10*74a4d8c2SCharles.Forsyth
11*74a4d8c2SCharles.Forsyth int
mii(Mii * mii,int mask)12*74a4d8c2SCharles.Forsyth mii(Mii* mii, int mask)
13*74a4d8c2SCharles.Forsyth {
14*74a4d8c2SCharles.Forsyth MiiPhy *miiphy;
15*74a4d8c2SCharles.Forsyth int bit, phyno, r, rmask;
16*74a4d8c2SCharles.Forsyth
17*74a4d8c2SCharles.Forsyth /*
18*74a4d8c2SCharles.Forsyth * Probe through mii for PHYs in mask;
19*74a4d8c2SCharles.Forsyth * return the mask of those found in the current probe.
20*74a4d8c2SCharles.Forsyth * If the PHY has not already been probed, update
21*74a4d8c2SCharles.Forsyth * the Mii information.
22*74a4d8c2SCharles.Forsyth */
23*74a4d8c2SCharles.Forsyth rmask = 0;
24*74a4d8c2SCharles.Forsyth for(phyno = 0; phyno < NMiiPhy; phyno++){
25*74a4d8c2SCharles.Forsyth bit = 1<<phyno;
26*74a4d8c2SCharles.Forsyth if(!(mask & bit))
27*74a4d8c2SCharles.Forsyth continue;
28*74a4d8c2SCharles.Forsyth if(mii->mask & bit){
29*74a4d8c2SCharles.Forsyth rmask |= bit;
30*74a4d8c2SCharles.Forsyth continue;
31*74a4d8c2SCharles.Forsyth }
32*74a4d8c2SCharles.Forsyth if(mii->mir(mii, phyno, Bmsr) == -1)
33*74a4d8c2SCharles.Forsyth continue;
34*74a4d8c2SCharles.Forsyth if((miiphy = malloc(sizeof(MiiPhy))) == nil)
35*74a4d8c2SCharles.Forsyth continue;
36*74a4d8c2SCharles.Forsyth
37*74a4d8c2SCharles.Forsyth miiphy->mii = mii;
38*74a4d8c2SCharles.Forsyth r = mii->mir(mii, phyno, Phyidr1);
39*74a4d8c2SCharles.Forsyth miiphy->oui = (r & 0x3FFF)<<6;
40*74a4d8c2SCharles.Forsyth r = mii->mir(mii, phyno, Phyidr2);
41*74a4d8c2SCharles.Forsyth miiphy->oui |= r>>10;
42*74a4d8c2SCharles.Forsyth miiphy->phyno = phyno;
43*74a4d8c2SCharles.Forsyth
44*74a4d8c2SCharles.Forsyth miiphy->anar = ~0;
45*74a4d8c2SCharles.Forsyth miiphy->fc = ~0;
46*74a4d8c2SCharles.Forsyth miiphy->mscr = ~0;
47*74a4d8c2SCharles.Forsyth
48*74a4d8c2SCharles.Forsyth mii->phy[phyno] = miiphy;
49*74a4d8c2SCharles.Forsyth if(mii->curphy == nil)
50*74a4d8c2SCharles.Forsyth mii->curphy = miiphy;
51*74a4d8c2SCharles.Forsyth mii->mask |= bit;
52*74a4d8c2SCharles.Forsyth mii->nphy++;
53*74a4d8c2SCharles.Forsyth
54*74a4d8c2SCharles.Forsyth rmask |= bit;
55*74a4d8c2SCharles.Forsyth }
56*74a4d8c2SCharles.Forsyth return rmask;
57*74a4d8c2SCharles.Forsyth }
58*74a4d8c2SCharles.Forsyth
59*74a4d8c2SCharles.Forsyth int
miimir(Mii * mii,int r)60*74a4d8c2SCharles.Forsyth miimir(Mii* mii, int r)
61*74a4d8c2SCharles.Forsyth {
62*74a4d8c2SCharles.Forsyth if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
63*74a4d8c2SCharles.Forsyth return -1;
64*74a4d8c2SCharles.Forsyth return mii->mir(mii, mii->curphy->phyno, r);
65*74a4d8c2SCharles.Forsyth }
66*74a4d8c2SCharles.Forsyth
67*74a4d8c2SCharles.Forsyth int
miimiw(Mii * mii,int r,int data)68*74a4d8c2SCharles.Forsyth miimiw(Mii* mii, int r, int data)
69*74a4d8c2SCharles.Forsyth {
70*74a4d8c2SCharles.Forsyth if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
71*74a4d8c2SCharles.Forsyth return -1;
72*74a4d8c2SCharles.Forsyth return mii->miw(mii, mii->curphy->phyno, r, data);
73*74a4d8c2SCharles.Forsyth }
74*74a4d8c2SCharles.Forsyth
75*74a4d8c2SCharles.Forsyth int
miireset(Mii * mii)76*74a4d8c2SCharles.Forsyth miireset(Mii* mii)
77*74a4d8c2SCharles.Forsyth {
78*74a4d8c2SCharles.Forsyth int bmcr;
79*74a4d8c2SCharles.Forsyth
80*74a4d8c2SCharles.Forsyth if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
81*74a4d8c2SCharles.Forsyth return -1;
82*74a4d8c2SCharles.Forsyth bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
83*74a4d8c2SCharles.Forsyth bmcr |= BmcrR;
84*74a4d8c2SCharles.Forsyth mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
85*74a4d8c2SCharles.Forsyth microdelay(1);
86*74a4d8c2SCharles.Forsyth
87*74a4d8c2SCharles.Forsyth return 0;
88*74a4d8c2SCharles.Forsyth }
89*74a4d8c2SCharles.Forsyth
90*74a4d8c2SCharles.Forsyth int
miiane(Mii * mii,int a,int p,int e)91*74a4d8c2SCharles.Forsyth miiane(Mii* mii, int a, int p, int e)
92*74a4d8c2SCharles.Forsyth {
93*74a4d8c2SCharles.Forsyth int anar, bmsr, mscr, r, phyno;
94*74a4d8c2SCharles.Forsyth
95*74a4d8c2SCharles.Forsyth if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
96*74a4d8c2SCharles.Forsyth return -1;
97*74a4d8c2SCharles.Forsyth phyno = mii->curphy->phyno;
98*74a4d8c2SCharles.Forsyth
99*74a4d8c2SCharles.Forsyth bmsr = mii->mir(mii, phyno, Bmsr);
100*74a4d8c2SCharles.Forsyth if(!(bmsr & BmsrAna))
101*74a4d8c2SCharles.Forsyth return -1;
102*74a4d8c2SCharles.Forsyth
103*74a4d8c2SCharles.Forsyth if(a != ~0)
104*74a4d8c2SCharles.Forsyth anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
105*74a4d8c2SCharles.Forsyth else if(mii->curphy->anar != ~0)
106*74a4d8c2SCharles.Forsyth anar = mii->curphy->anar;
107*74a4d8c2SCharles.Forsyth else{
108*74a4d8c2SCharles.Forsyth anar = mii->mir(mii, phyno, Anar);
109*74a4d8c2SCharles.Forsyth anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
110*74a4d8c2SCharles.Forsyth if(bmsr & Bmsr10THD)
111*74a4d8c2SCharles.Forsyth anar |= Ana10HD;
112*74a4d8c2SCharles.Forsyth if(bmsr & Bmsr10TFD)
113*74a4d8c2SCharles.Forsyth anar |= Ana10FD;
114*74a4d8c2SCharles.Forsyth if(bmsr & Bmsr100TXHD)
115*74a4d8c2SCharles.Forsyth anar |= AnaTXHD;
116*74a4d8c2SCharles.Forsyth if(bmsr & Bmsr100TXFD)
117*74a4d8c2SCharles.Forsyth anar |= AnaTXFD;
118*74a4d8c2SCharles.Forsyth }
119*74a4d8c2SCharles.Forsyth mii->curphy->anar = anar;
120*74a4d8c2SCharles.Forsyth
121*74a4d8c2SCharles.Forsyth if(p != ~0)
122*74a4d8c2SCharles.Forsyth anar |= (AnaAP|AnaP) & p;
123*74a4d8c2SCharles.Forsyth else if(mii->curphy->fc != ~0)
124*74a4d8c2SCharles.Forsyth anar |= mii->curphy->fc;
125*74a4d8c2SCharles.Forsyth mii->curphy->fc = (AnaAP|AnaP) & anar;
126*74a4d8c2SCharles.Forsyth
127*74a4d8c2SCharles.Forsyth if(bmsr & BmsrEs){
128*74a4d8c2SCharles.Forsyth mscr = mii->mir(mii, phyno, Mscr);
129*74a4d8c2SCharles.Forsyth mscr &= ~(Mscr1000TFD|Mscr1000THD);
130*74a4d8c2SCharles.Forsyth if(e != ~0)
131*74a4d8c2SCharles.Forsyth mscr |= (Mscr1000TFD|Mscr1000THD) & e;
132*74a4d8c2SCharles.Forsyth else if(mii->curphy->mscr != ~0)
133*74a4d8c2SCharles.Forsyth mscr = mii->curphy->mscr;
134*74a4d8c2SCharles.Forsyth else{
135*74a4d8c2SCharles.Forsyth r = mii->mir(mii, phyno, Esr);
136*74a4d8c2SCharles.Forsyth if(r & Esr1000THD)
137*74a4d8c2SCharles.Forsyth mscr |= Mscr1000THD;
138*74a4d8c2SCharles.Forsyth if(r & Esr1000TFD)
139*74a4d8c2SCharles.Forsyth mscr |= Mscr1000TFD;
140*74a4d8c2SCharles.Forsyth }
141*74a4d8c2SCharles.Forsyth mii->curphy->mscr = mscr;
142*74a4d8c2SCharles.Forsyth mii->miw(mii, phyno, Mscr, mscr);
143*74a4d8c2SCharles.Forsyth }
144*74a4d8c2SCharles.Forsyth mii->miw(mii, phyno, Anar, anar);
145*74a4d8c2SCharles.Forsyth
146*74a4d8c2SCharles.Forsyth r = mii->mir(mii, phyno, Bmcr);
147*74a4d8c2SCharles.Forsyth if(!(r & BmcrR)){
148*74a4d8c2SCharles.Forsyth r |= BmcrAne|BmcrRan;
149*74a4d8c2SCharles.Forsyth mii->miw(mii, phyno, Bmcr, r);
150*74a4d8c2SCharles.Forsyth }
151*74a4d8c2SCharles.Forsyth
152*74a4d8c2SCharles.Forsyth return 0;
153*74a4d8c2SCharles.Forsyth }
154*74a4d8c2SCharles.Forsyth
155*74a4d8c2SCharles.Forsyth int
miistatus(Mii * mii)156*74a4d8c2SCharles.Forsyth miistatus(Mii* mii)
157*74a4d8c2SCharles.Forsyth {
158*74a4d8c2SCharles.Forsyth MiiPhy *phy;
159*74a4d8c2SCharles.Forsyth int anlpar, bmsr, p, r, phyno;
160*74a4d8c2SCharles.Forsyth
161*74a4d8c2SCharles.Forsyth if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
162*74a4d8c2SCharles.Forsyth return -1;
163*74a4d8c2SCharles.Forsyth phy = mii->curphy;
164*74a4d8c2SCharles.Forsyth phyno = phy->phyno;
165*74a4d8c2SCharles.Forsyth
166*74a4d8c2SCharles.Forsyth /*
167*74a4d8c2SCharles.Forsyth * Check Auto-Negotiation is complete and link is up.
168*74a4d8c2SCharles.Forsyth * (Read status twice as the Ls bit is sticky).
169*74a4d8c2SCharles.Forsyth */
170*74a4d8c2SCharles.Forsyth bmsr = mii->mir(mii, phyno, Bmsr);
171*74a4d8c2SCharles.Forsyth if(!(bmsr & (BmsrAnc|BmsrAna)))
172*74a4d8c2SCharles.Forsyth return -1;
173*74a4d8c2SCharles.Forsyth
174*74a4d8c2SCharles.Forsyth bmsr = mii->mir(mii, phyno, Bmsr);
175*74a4d8c2SCharles.Forsyth if(!(bmsr & BmsrLs)){
176*74a4d8c2SCharles.Forsyth phy->link = 0;
177*74a4d8c2SCharles.Forsyth return -1;
178*74a4d8c2SCharles.Forsyth }
179*74a4d8c2SCharles.Forsyth
180*74a4d8c2SCharles.Forsyth phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
181*74a4d8c2SCharles.Forsyth if(phy->mscr){
182*74a4d8c2SCharles.Forsyth r = mii->mir(mii, phyno, Mssr);
183*74a4d8c2SCharles.Forsyth if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
184*74a4d8c2SCharles.Forsyth phy->speed = 1000;
185*74a4d8c2SCharles.Forsyth phy->fd = 1;
186*74a4d8c2SCharles.Forsyth }
187*74a4d8c2SCharles.Forsyth else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
188*74a4d8c2SCharles.Forsyth phy->speed = 1000;
189*74a4d8c2SCharles.Forsyth }
190*74a4d8c2SCharles.Forsyth
191*74a4d8c2SCharles.Forsyth anlpar = mii->mir(mii, phyno, Anlpar);
192*74a4d8c2SCharles.Forsyth if(phy->speed == 0){
193*74a4d8c2SCharles.Forsyth r = phy->anar & anlpar;
194*74a4d8c2SCharles.Forsyth if(r & AnaTXFD){
195*74a4d8c2SCharles.Forsyth phy->speed = 100;
196*74a4d8c2SCharles.Forsyth phy->fd = 1;
197*74a4d8c2SCharles.Forsyth }
198*74a4d8c2SCharles.Forsyth else if(r & AnaTXHD)
199*74a4d8c2SCharles.Forsyth phy->speed = 100;
200*74a4d8c2SCharles.Forsyth else if(r & Ana10FD){
201*74a4d8c2SCharles.Forsyth phy->speed = 10;
202*74a4d8c2SCharles.Forsyth phy->fd = 1;
203*74a4d8c2SCharles.Forsyth }
204*74a4d8c2SCharles.Forsyth else if(r & Ana10HD)
205*74a4d8c2SCharles.Forsyth phy->speed = 10;
206*74a4d8c2SCharles.Forsyth }
207*74a4d8c2SCharles.Forsyth if(phy->speed == 0)
208*74a4d8c2SCharles.Forsyth return -1;
209*74a4d8c2SCharles.Forsyth
210*74a4d8c2SCharles.Forsyth if(phy->fd){
211*74a4d8c2SCharles.Forsyth p = phy->fc;
212*74a4d8c2SCharles.Forsyth r = anlpar & (AnaAP|AnaP);
213*74a4d8c2SCharles.Forsyth if(p == AnaAP && r == (AnaAP|AnaP))
214*74a4d8c2SCharles.Forsyth phy->tfc = 1;
215*74a4d8c2SCharles.Forsyth else if(p == (AnaAP|AnaP) && r == AnaAP)
216*74a4d8c2SCharles.Forsyth phy->rfc = 1;
217*74a4d8c2SCharles.Forsyth else if((p & AnaP) && (r & AnaP))
218*74a4d8c2SCharles.Forsyth phy->rfc = phy->tfc = 1;
219*74a4d8c2SCharles.Forsyth }
220*74a4d8c2SCharles.Forsyth
221*74a4d8c2SCharles.Forsyth phy->link = 1;
222*74a4d8c2SCharles.Forsyth
223*74a4d8c2SCharles.Forsyth return 0;
224*74a4d8c2SCharles.Forsyth }
225