Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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