FreeBSD/Linux Kernel Cross Reference
sys/pc/ethermii.c
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;
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
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 if(a != ~0)
110 anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
111 else if(mii->curphy->anar != ~0)
112 anar = mii->curphy->anar;
113 else{
114 anar = mii->mir(mii, phyno, Anar);
115 anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
116 if(bmsr & Bmsr10THD)
117 anar |= Ana10HD;
118 if(bmsr & Bmsr10TFD)
119 anar |= Ana10FD;
120 if(bmsr & Bmsr100TXHD)
121 anar |= AnaTXHD;
122 if(bmsr & Bmsr100TXFD)
123 anar |= AnaTXFD;
124 }
125 mii->curphy->anar = anar;
126
127 if(p != ~0)
128 anar |= (AnaAP|AnaP) & p;
129 else if(mii->curphy->fc != ~0)
130 anar |= mii->curphy->fc;
131 mii->curphy->fc = (AnaAP|AnaP) & anar;
132
133 if(bmsr & BmsrEs){
134 mscr = mii->mir(mii, phyno, Mscr);
135 mscr &= ~(Mscr1000TFD|Mscr1000THD);
136 if(e != ~0)
137 mscr |= (Mscr1000TFD|Mscr1000THD) & e;
138 else if(mii->curphy->mscr != ~0)
139 mscr = mii->curphy->mscr;
140 else{
141 r = mii->mir(mii, phyno, Esr);
142 if(r & Esr1000THD)
143 mscr |= Mscr1000THD;
144 if(r & Esr1000TFD)
145 mscr |= Mscr1000TFD;
146 }
147 mii->curphy->mscr = mscr;
148 mii->miw(mii, phyno, Mscr, mscr);
149 }
150 mii->miw(mii, phyno, Anar, anar);
151
152 r = mii->mir(mii, phyno, Bmcr);
153 if(!(r & BmcrR)){
154 r |= BmcrAne|BmcrRan;
155 mii->miw(mii, phyno, Bmcr, r);
156 }
157
158 return 0;
159 }
160
161 int
162 miistatus(Mii* mii)
163 {
164 MiiPhy *phy;
165 int anlpar, bmsr, p, r, phyno;
166
167 if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
168 return -1;
169 phy = mii->curphy;
170 phyno = phy->phyno;
171
172 /*
173 * Check Auto-Negotiation is complete and link is up.
174 * (Read status twice as the Ls bit is sticky).
175 */
176 bmsr = mii->mir(mii, phyno, Bmsr);
177 if(!(bmsr & (BmsrAnc|BmsrAna))) {
178 // print("miistatus: auto-neg incomplete\n");
179 return -1;
180 }
181
182 bmsr = mii->mir(mii, phyno, Bmsr);
183 if(!(bmsr & BmsrLs)){
184 // print("miistatus: link down\n");
185 phy->link = 0;
186 return -1;
187 }
188
189 phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
190 if(phy->mscr){
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 // print("miistatus: phy speed 0\n");
218 return -1;
219 }
220
221 if(phy->fd){
222 p = phy->fc;
223 r = anlpar & (AnaAP|AnaP);
224 if(p == AnaAP && r == (AnaAP|AnaP))
225 phy->tfc = 1;
226 else if(p == (AnaAP|AnaP) && r == AnaAP)
227 phy->rfc = 1;
228 else if((p & AnaP) && (r & AnaP))
229 phy->rfc = phy->tfc = 1;
230 }
231
232 phy->link = 1;
233
234 return 0;
235 }
Cache object: 7ac7e83db30deec5cb8e896662c910dd
|