xref: /inferno-os/os/boot/pc/ethermii.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
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