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