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