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 "../ppc/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;
85
86 if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
87 return -1;
88 bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
89 bmcr |= BmcrR;
90 mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
91 microdelay(1);
92
93 return 0;
94 }
95
96 int
miiane(Mii * mii,int a,int p,int e)97 miiane(Mii* mii, int a, int p, int e)
98 {
99 int anar, bmsr, mscr, r, phyno;
100
101 if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
102 return -1;
103 phyno = mii->curphy->phyno;
104
105 bmsr = mii->mir(mii, phyno, Bmsr);
106 if(!(bmsr & BmsrAna))
107 return -1;
108
109 anar = mii->mir(mii, phyno, Anar);
110 anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
111
112 if(a != ~0)
113 anar |= (AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
114 else if(mii->curphy->anar != ~0)
115 anar = mii->curphy->anar;
116 else{
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 mii->miw(mii, phyno, Anar, anar);
135
136 mscr = 0;
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->miw(mii, phyno, Mscr, mscr);
152 }
153 mii->curphy->mscr = mscr;
154
155 r = mii->mir(mii, phyno, Bmcr);
156 if(!(r & BmcrR)){
157 r |= BmcrAne|BmcrRan;
158 mii->miw(mii, phyno, Bmcr, r);
159 }
160
161 return 0;
162 }
163
164 int
miistatus(Mii * mii)165 miistatus(Mii* mii)
166 {
167 MiiPhy *phy;
168 int anlpar, bmsr, p, r, phyno;
169
170 if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
171 return -1;
172 phy = mii->curphy;
173 phyno = phy->phyno;
174
175 /*
176 * Check Auto-Negotiation is complete and link is up.
177 * (Read status twice as the Ls bit is sticky).
178 */
179 phy->bmsr = bmsr = mii->mir(mii, phyno, Bmsr);
180 if(!(bmsr & (BmsrAnc|BmsrAna)))
181 return -1;
182
183 phy->bmsr = bmsr = mii->mir(mii, phyno, Bmsr);
184 if(!(bmsr & BmsrLs)){
185 phy->link = 0;
186 return 0;
187 }
188
189 phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
190 if(phy->mscr & (Mscr1000TFD|Mscr1000THD)){
191 r = mii->mir(mii, phyno, Mssr);
192 if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
193 phy->speed = 1000;
194 phy->fd = 1;
195 }
196 else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
197 phy->speed = 1000;
198 }
199
200 anlpar = mii->mir(mii, phyno, Anlpar);
201 if(phy->speed == 0){
202 r = phy->anar & anlpar;
203 if(r & AnaTXFD){
204 phy->speed = 100;
205 phy->fd = 1;
206 }
207 else if(r & AnaTXHD)
208 phy->speed = 100;
209 else if(r & Ana10FD){
210 phy->speed = 10;
211 phy->fd = 1;
212 }
213 else if(r & Ana10HD)
214 phy->speed = 10;
215 }
216 if(phy->speed == 0)
217 return -1;
218
219 if(phy->fd){
220 p = phy->fc;
221 r = anlpar & (AnaAP|AnaP);
222 if(p == AnaAP && r == (AnaAP|AnaP))
223 phy->tfc = 1;
224 else if(p == (AnaAP|AnaP) && r == AnaAP)
225 phy->rfc = 1;
226 else if((p & AnaP) && (r & AnaP))
227 phy->rfc = phy->tfc = 1;
228 }
229
230 phy->link = 1;
231
232 return 0;
233 }
234