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