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