123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "../port/netif.h"
- #include "ethermii.h"
- static int
- miiprobe(Mii* mii, int mask)
- {
- MiiPhy *miiphy;
- int bit, oui, phyno, r, rmask;
- /*
- * 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->rw(mii, 0, phyno, Bmsr, 0) == -1)
- continue;
- r = mii->rw(mii, 0, phyno, Phyidr1, 0)<<16;
- r |= mii->rw(mii, 0, phyno, Phyidr2, 0);
- oui = (r>>10) & 0xffff;
- if(oui == 0xffff || oui == 0)
- continue;
- if((miiphy = malloc(sizeof(MiiPhy))) == nil)
- continue;
- miiphy->mii = mii;
- miiphy->phyno = phyno;
- miiphy->phyid = r;
- miiphy->oui = oui;
- 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->rw(mii, 0, mii->curphy->phyno, r, 0);
- }
- int
- miimiw(Mii* mii, int r, int data)
- {
- if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
- return -1;
- return mii->rw(mii, 1, mii->curphy->phyno, r, data);
- }
- int
- miireset(Mii* mii)
- {
- int bmcr, timeo;
- if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
- return -1;
- bmcr = mii->rw(mii, 0, mii->curphy->phyno, Bmcr, 0);
- mii->rw(mii, 1, mii->curphy->phyno, Bmcr, BmcrR|bmcr);
- for(timeo = 0; timeo < 1000; timeo++){
- bmcr = mii->rw(mii, 0, mii->curphy->phyno, Bmcr, 0);
- if(!(bmcr & BmcrR))
- break;
- microdelay(1);
- }
- if(bmcr & BmcrR)
- return -1;
- if(bmcr & BmcrI)
- mii->rw(mii, 1, mii->curphy->phyno, Bmcr, bmcr & ~BmcrI);
- 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;
- mii->rw(mii, 1, phyno, Bmsr, 0);
- bmsr = mii->rw(mii, 0, phyno, Bmsr, 0);
- 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->rw(mii, 0, phyno, Anar, 0);
- 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->rw(mii, 0, phyno, Mscr, 0);
- mscr &= ~(Mscr1000TFD|Mscr1000THD);
- if(e != ~0)
- mscr |= (Mscr1000TFD|Mscr1000THD) & e;
- else if(mii->curphy->mscr != ~0)
- mscr = mii->curphy->mscr;
- else{
- r = mii->rw(mii, 0, phyno, Esr, 0);
- if(r & Esr1000THD)
- mscr |= Mscr1000THD;
- if(r & Esr1000TFD)
- mscr |= Mscr1000TFD;
- }
- mii->curphy->mscr = mscr;
- mii->rw(mii, 1, phyno, Mscr, mscr);
- }
- else
- mii->curphy->mscr = 0;
- mii->rw(mii, 1, phyno, Anar, anar);
- r = mii->rw(mii, 0, phyno, Bmcr, 0);
- if(!(r & BmcrR)){
- r |= BmcrAne|BmcrRan;
- mii->rw(mii, 1, 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->rw(mii, 0, phyno, Bmsr, 0);
- if(!(bmsr & (BmsrAnc|BmsrAna)))
- return -1;
- bmsr = mii->rw(mii, 0, phyno, Bmsr, 0);
- if(!(bmsr & BmsrLs)){
- phy->link = 0;
- return -1;
- }
- phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
- if(phy->mscr){
- r = mii->rw(mii, 0, phyno, Mssr, 0);
- if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
- phy->speed = 1000;
- phy->fd = 1;
- }
- else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
- phy->speed = 1000;
- }
- anlpar = mii->rw(mii, 0, phyno, Anlpar, 0);
- 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)
- 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;
- }
- char*
- miidumpphy(Mii* mii, char* p, char* e)
- {
- int i, r;
- if(mii == nil || mii->curphy == nil)
- return p;
- p = seprint(p, e, "phy: ");
- for(i = 0; i < NMiiPhyr; i++){
- if(i && ((i & 0x07) == 0))
- p = seprint(p, e, "\n ");
- r = mii->rw(mii, 0, mii->curphy->phyno, i, 0);
- p = seprint(p, e, " %4.4ux", r);
- }
- p = seprint(p, e, "\n");
- return p;
- }
- void
- miidetach(Mii* mii)
- {
- int i;
- for(i = 0; i < NMiiPhy; i++){
- if(mii->phy[i] == nil)
- continue;
- free(mii);
- mii->phy[i] = nil;
- }
- free(mii);
- }
- Mii*
- miiattach(void* ctlr, int mask, int (*rw)(Mii*, int, int, int, int))
- {
- Mii* mii;
- if((mii = malloc(sizeof(Mii))) == nil)
- return nil;
- mii->ctlr = ctlr;
- mii->rw = rw;
- if(miiprobe(mii, mask) == 0){
- free(mii);
- mii = nil;
- }
- return mii;
- }
|