2011-03-30 12:46:40 +00:00
|
|
|
#include "u.h"
|
|
|
|
#include "../port/lib.h"
|
|
|
|
#include "mem.h"
|
|
|
|
#include "dat.h"
|
|
|
|
#include "fns.h"
|
|
|
|
#include "io.h"
|
|
|
|
#include "../port/error.h"
|
|
|
|
#include "../port/netif.h"
|
2018-02-11 17:08:03 +00:00
|
|
|
#include "../port/etherif.h"
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
#include "ethermii.h"
|
|
|
|
|
|
|
|
int
|
|
|
|
mii(Mii* mii, int mask)
|
|
|
|
{
|
|
|
|
MiiPhy *miiphy;
|
2019-07-25 07:11:53 +00:00
|
|
|
int bit, oui, phyno, rmask;
|
|
|
|
u32int id;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Probe through mii for PHYs in mask;
|
|
|
|
* return the mask of those found in the current probe.
|
|
|
|
* If the PHY has not already been probed, update
|
|
|
|
* the Mii information.
|
|
|
|
*/
|
|
|
|
rmask = 0;
|
|
|
|
for(phyno = 0; phyno < NMiiPhy; phyno++){
|
|
|
|
bit = 1<<phyno;
|
|
|
|
if(!(mask & bit))
|
|
|
|
continue;
|
|
|
|
if(mii->mask & bit){
|
|
|
|
rmask |= bit;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(mii->mir(mii, phyno, Bmsr) == -1)
|
|
|
|
continue;
|
2019-07-25 07:11:53 +00:00
|
|
|
id = mii->mir(mii, phyno, Phyidr1) << 16;
|
|
|
|
id |= mii->mir(mii, phyno, Phyidr2);
|
|
|
|
oui = (id & 0x3FFFFC00)>>10;
|
2011-03-30 12:46:40 +00:00
|
|
|
if(oui == 0xFFFFF || oui == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if((miiphy = malloc(sizeof(MiiPhy))) == nil)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
miiphy->mii = mii;
|
2019-07-25 07:11:53 +00:00
|
|
|
miiphy->id = id;
|
2011-03-30 12:46:40 +00:00
|
|
|
miiphy->oui = oui;
|
|
|
|
miiphy->phyno = phyno;
|
|
|
|
|
|
|
|
miiphy->anar = ~0;
|
|
|
|
miiphy->fc = ~0;
|
|
|
|
miiphy->mscr = ~0;
|
|
|
|
|
|
|
|
mii->phy[phyno] = miiphy;
|
|
|
|
if(mii->curphy == nil)
|
|
|
|
mii->curphy = miiphy;
|
|
|
|
mii->mask |= bit;
|
|
|
|
mii->nphy++;
|
|
|
|
|
|
|
|
rmask |= bit;
|
|
|
|
}
|
|
|
|
return rmask;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
miimir(Mii* mii, int r)
|
|
|
|
{
|
|
|
|
if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
|
|
|
|
return -1;
|
|
|
|
return mii->mir(mii, mii->curphy->phyno, r);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
miimiw(Mii* mii, int r, int data)
|
|
|
|
{
|
|
|
|
if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
|
|
|
|
return -1;
|
|
|
|
return mii->miw(mii, mii->curphy->phyno, r, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
miireset(Mii* mii)
|
|
|
|
{
|
|
|
|
int bmcr;
|
|
|
|
|
|
|
|
if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
|
|
|
|
return -1;
|
|
|
|
bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
|
|
|
|
bmcr |= BmcrR;
|
|
|
|
mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
|
|
|
|
microdelay(1);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
miiane(Mii* mii, int a, int p, int e)
|
|
|
|
{
|
|
|
|
int anar, bmsr, mscr, r, phyno;
|
|
|
|
|
|
|
|
if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
|
|
|
|
return -1;
|
|
|
|
phyno = mii->curphy->phyno;
|
|
|
|
|
|
|
|
bmsr = mii->mir(mii, phyno, Bmsr);
|
|
|
|
if(!(bmsr & BmsrAna))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if(a != ~0)
|
|
|
|
anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
|
|
|
|
else if(mii->curphy->anar != ~0)
|
|
|
|
anar = mii->curphy->anar;
|
|
|
|
else{
|
|
|
|
anar = mii->mir(mii, phyno, Anar);
|
|
|
|
anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
|
|
|
|
if(bmsr & Bmsr10THD)
|
|
|
|
anar |= Ana10HD;
|
|
|
|
if(bmsr & Bmsr10TFD)
|
|
|
|
anar |= Ana10FD;
|
|
|
|
if(bmsr & Bmsr100TXHD)
|
|
|
|
anar |= AnaTXHD;
|
|
|
|
if(bmsr & Bmsr100TXFD)
|
|
|
|
anar |= AnaTXFD;
|
|
|
|
}
|
|
|
|
mii->curphy->anar = anar;
|
|
|
|
|
|
|
|
if(p != ~0)
|
|
|
|
anar |= (AnaAP|AnaP) & p;
|
|
|
|
else if(mii->curphy->fc != ~0)
|
|
|
|
anar |= mii->curphy->fc;
|
|
|
|
mii->curphy->fc = (AnaAP|AnaP) & anar;
|
|
|
|
|
|
|
|
if(bmsr & BmsrEs){
|
|
|
|
mscr = mii->mir(mii, phyno, Mscr);
|
|
|
|
mscr &= ~(Mscr1000TFD|Mscr1000THD);
|
|
|
|
if(e != ~0)
|
|
|
|
mscr |= (Mscr1000TFD|Mscr1000THD) & e;
|
|
|
|
else if(mii->curphy->mscr != ~0)
|
|
|
|
mscr = mii->curphy->mscr;
|
|
|
|
else{
|
|
|
|
r = mii->mir(mii, phyno, Esr);
|
|
|
|
if(r & Esr1000THD)
|
|
|
|
mscr |= Mscr1000THD;
|
|
|
|
if(r & Esr1000TFD)
|
|
|
|
mscr |= Mscr1000TFD;
|
|
|
|
}
|
|
|
|
mii->curphy->mscr = mscr;
|
|
|
|
mii->miw(mii, phyno, Mscr, mscr);
|
|
|
|
}
|
|
|
|
mii->miw(mii, phyno, Anar, anar);
|
|
|
|
|
|
|
|
r = mii->mir(mii, phyno, Bmcr);
|
|
|
|
if(!(r & BmcrR)){
|
|
|
|
r |= BmcrAne|BmcrRan;
|
|
|
|
mii->miw(mii, phyno, Bmcr, r);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
miistatus(Mii* mii)
|
|
|
|
{
|
|
|
|
MiiPhy *phy;
|
|
|
|
int anlpar, bmsr, p, r, phyno;
|
|
|
|
|
|
|
|
if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
|
|
|
|
return -1;
|
|
|
|
phy = mii->curphy;
|
|
|
|
phyno = phy->phyno;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check Auto-Negotiation is complete and link is up.
|
|
|
|
* (Read status twice as the Ls bit is sticky).
|
|
|
|
*/
|
|
|
|
bmsr = mii->mir(mii, phyno, Bmsr);
|
|
|
|
if(!(bmsr & (BmsrAnc|BmsrAna))) {
|
|
|
|
// print("miistatus: auto-neg incomplete\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bmsr = mii->mir(mii, phyno, Bmsr);
|
|
|
|
if(!(bmsr & BmsrLs)){
|
|
|
|
// print("miistatus: link down\n");
|
|
|
|
phy->link = 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
|
|
|
|
if(phy->mscr){
|
|
|
|
r = mii->mir(mii, phyno, Mssr);
|
|
|
|
if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
|
|
|
|
phy->speed = 1000;
|
|
|
|
phy->fd = 1;
|
|
|
|
}
|
|
|
|
else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
|
|
|
|
phy->speed = 1000;
|
|
|
|
}
|
|
|
|
|
|
|
|
anlpar = mii->mir(mii, phyno, Anlpar);
|
|
|
|
if(phy->speed == 0){
|
|
|
|
r = phy->anar & anlpar;
|
|
|
|
if(r & AnaTXFD){
|
|
|
|
phy->speed = 100;
|
|
|
|
phy->fd = 1;
|
|
|
|
}
|
|
|
|
else if(r & AnaTXHD)
|
|
|
|
phy->speed = 100;
|
|
|
|
else if(r & Ana10FD){
|
|
|
|
phy->speed = 10;
|
|
|
|
phy->fd = 1;
|
|
|
|
}
|
|
|
|
else if(r & Ana10HD)
|
|
|
|
phy->speed = 10;
|
|
|
|
}
|
|
|
|
if(phy->speed == 0) {
|
|
|
|
// print("miistatus: phy speed 0\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(phy->fd){
|
|
|
|
p = phy->fc;
|
|
|
|
r = anlpar & (AnaAP|AnaP);
|
|
|
|
if(p == AnaAP && r == (AnaAP|AnaP))
|
|
|
|
phy->tfc = 1;
|
|
|
|
else if(p == (AnaAP|AnaP) && r == AnaAP)
|
|
|
|
phy->rfc = 1;
|
|
|
|
else if((p & AnaP) && (r & AnaP))
|
|
|
|
phy->rfc = phy->tfc = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
phy->link = 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2019-07-25 07:11:53 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
miimmdr(Mii* mii, int a, int r)
|
|
|
|
{
|
|
|
|
a &= 0x1F;
|
|
|
|
if(miimiw(mii, Mmdctrl, a) == -1)
|
|
|
|
return -1;
|
|
|
|
if(miimiw(mii, Mmddata, r) == -1)
|
|
|
|
return -1;
|
|
|
|
if(miimiw(mii, Mmdctrl, a | 0x4000) == -1)
|
|
|
|
return -1;
|
|
|
|
return miimir(mii, Mmddata);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
miimmdw(Mii* mii, int a, int r, int data)
|
|
|
|
{
|
|
|
|
a &= 0x1F;
|
|
|
|
if(miimiw(mii, Mmdctrl, a) == -1)
|
|
|
|
return -1;
|
|
|
|
if(miimiw(mii, Mmddata, r) == -1)
|
|
|
|
return -1;
|
|
|
|
if(miimiw(mii, Mmdctrl, a | 0x4000) == -1)
|
|
|
|
return -1;
|
|
|
|
return miimiw(mii, Mmddata, data);
|
|
|
|
}
|