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