]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/teg2/ethermii.c
devarch: restrict i/o port access to 64K, disallow msr 32-bit wrap arround (thanks...
[plan9front.git] / sys / src / 9 / teg2 / 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 #include "../port/etherif.h"
10
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 }