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
mii(Mii * mii,int mask)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
miimir(Mii * mii,int r)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
miimiw(Mii * mii,int r,int data)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
miireset(Mii * mii)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
miiane(Mii * mii,int a,int p,int e)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
miistatus(Mii * mii)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 }
240