devether: make link status prints consistent

Provide ethersetlink() function for norifying about
link status changes, which will do the printing
that includes the controller number.
This commit is contained in:
cinap_lenrek 2025-01-07 03:10:35 +00:00
parent 682e47137a
commit 5dde462f96
23 changed files with 113 additions and 112 deletions

View file

@ -1400,7 +1400,7 @@ linkdown(Ctlr *ctl)
if(edev == nil || ctl->status == Disconnected) if(edev == nil || ctl->status == Disconnected)
return; return;
ctl->status = Disconnected; ctl->status = Disconnected;
edev->link = 0; ethersetlink(edev, 0);
/* send eof to aux/wpa */ /* send eof to aux/wpa */
for(i = 0; i < edev->nfile; i++){ for(i = 0; i < edev->nfile; i++){
f = edev->f[i]; f = edev->f[i];
@ -1550,7 +1550,7 @@ bcmevent(Ctlr *ctl, uchar *p, int len)
break; break;
case 16: /* E_LINK */ case 16: /* E_LINK */
if(flags&1){ /* link up */ if(flags&1){ /* link up */
ctl->edev->link = 1; ethersetlink(ctl->edev, 1);
break; break;
} }
/* fall through */ /* fall through */
@ -1812,8 +1812,8 @@ wljoin(Ctlr *ctl, char *ssid, int chan)
ctl->status = Connecting; ctl->status = Connecting;
switch(waitjoin(ctl)){ switch(waitjoin(ctl)){
case 0: case 0:
ctl->edev->link = 1;
ctl->status = Connected; ctl->status = Connected;
ethersetlink(ctl->edev, 1);
break; break;
case 3: case 3:
ctl->status = Disconnected; ctl->status = Disconnected;

View file

@ -770,8 +770,7 @@ linkproc(void *arg)
ethersetspeed(edev, phy->speed); ethersetspeed(edev, phy->speed);
} }
edev->link = link; ethersetlink(edev, link);
// print("#l%d: link %d speed %d\n", edev->ctlrno, edev->link, edev->mbps);
} }
} }

View file

@ -111,7 +111,6 @@ ethproc(void *ved)
{ {
Ether *edev; Ether *edev;
Ctlr *c; Ctlr *c;
char *sp, *dpl;
u16int v; u16int v;
edev = ved; edev = ved;
@ -120,8 +119,7 @@ ethproc(void *ved)
mdwrite(c, MDCTRL, AUTONEG); mdwrite(c, MDCTRL, AUTONEG);
for(;;){ for(;;){
if((mdread(c, MDSTATUS) & LINK) == 0){ if((mdread(c, MDSTATUS) & LINK) == 0){
edev->link = 0; ethersetlink(edev, 0);
print("eth: no link\n");
while((mdread(c, MDSTATUS) & LINK) == 0) while((mdread(c, MDSTATUS) & LINK) == 0)
tsleep(&up->sleep, return0, nil, Linkdelay); tsleep(&up->sleep, return0, nil, Linkdelay);
} }
@ -131,26 +129,19 @@ ethproc(void *ved)
; ;
c->r[MAC_CONFIG] &= ~(1<<15); c->r[MAC_CONFIG] &= ~(1<<15);
ethersetspeed(edev, 1000); ethersetspeed(edev, 1000);
sp = "1000BASE-T";
}else if((v & 0x20) != 0){ }else if((v & 0x20) != 0){
c->r[MAC_CONFIG] = c->r[MAC_CONFIG] | (1<<15|1<<14); c->r[MAC_CONFIG] = c->r[MAC_CONFIG] | (1<<15|1<<14);
ethersetspeed(edev, 100); ethersetspeed(edev, 100);
sp = "100BASE-TX";
}else if((v & 0x10) != 0){ }else if((v & 0x10) != 0){
c->r[MAC_CONFIG] = c->r[MAC_CONFIG] & ~(1<<14) | 1<<15; c->r[MAC_CONFIG] = c->r[MAC_CONFIG] & ~(1<<14) | 1<<15;
ethersetspeed(edev, 10); ethersetspeed(edev, 10);
sp = "10BASE-T"; }
}else
sp = "???";
if((v & 0x08) != 0){ if((v & 0x08) != 0){
dpl = "full";
c->r[MAC_CONFIG] |= 1<<11; c->r[MAC_CONFIG] |= 1<<11;
}else{ }else{
dpl = "half";
c->r[MAC_CONFIG] &= ~(1<<11); c->r[MAC_CONFIG] &= ~(1<<11);
} }
edev->link = 1; ethersetlink(edev, 1);
print("eth: %s %s duplex link\n", sp, dpl);
c->r[MAC_CONFIG] |= 1<<3 | 1<<2; c->r[MAC_CONFIG] |= 1<<3 | 1<<2;
while((mdread(c, MDSTATUS) & LINK) != 0) while((mdread(c, MDSTATUS) & LINK) != 0)
tsleep(&up->sleep, return0, nil, Linkdelay); tsleep(&up->sleep, return0, nil, Linkdelay);

View file

@ -519,8 +519,7 @@ linkproc(void *arg)
wr(ctlr, ENET_RDAR, RDAR_ACTIVE); wr(ctlr, ENET_RDAR, RDAR_ACTIVE);
} }
edev->link = link; ethersetlink(edev, link);
print("#l%d: link %d speed %d\n", edev->ctlrno, edev->link, edev->mbps);
} }
} }

View file

@ -866,9 +866,9 @@ interrupt(Ureg*, void *arg)
* thus we note the link change here, and check for * thus we note the link change here, and check for
* that and autonegotiation done below. * that and autonegotiation done below.
*/ */
if(irqe & IEphystschg) { if(irqe & IEphystschg){
ether->link = (reg->ps0 & PS0linkup) != 0;
ctlr->linkchg = 1; ctlr->linkchg = 1;
ethersetlink(ether, reg->ps0 & PS0linkup);
} }
if(irqe & IEtxerrq(Qno)) if(irqe & IEtxerrq(Qno))
ether->oerrs++; ether->oerrs++;
@ -895,8 +895,8 @@ interrupt(Ureg*, void *arg)
if(ctlr->linkchg && (reg->ps1 & PS1an_done)) { if(ctlr->linkchg && (reg->ps1 & PS1an_done)) {
handled++; handled++;
ether->link = (reg->ps0 & PS0linkup) != 0;
ctlr->linkchg = 0; ctlr->linkchg = 0;
ethersetlink(ether, reg->ps0 & PS0linkup);
} }
ctlr->newintrs++; ctlr->newintrs++;

View file

@ -880,19 +880,21 @@ rtl8169link(Ether* edev)
ctlr = edev->ctlr; ctlr = edev->ctlr;
r = csr8r(ctlr, Phystatus);
/* /*
* Maybe the link changed - do we care very much? * Maybe the link changed - do we care very much?
* Could stall transmits if no link, maybe? * Could stall transmits if no link, maybe?
*/ */
edev->link = (r & Linksts) != 0; r = csr8r(ctlr, Phystatus);
if(edev->link){ if(r & Linksts){
if(r & Speed10) if(r & Speed10)
ethersetspeed(edev, 10); ethersetspeed(edev, 10);
else if(r & Speed100) else if(r & Speed100)
ethersetspeed(edev, 100); ethersetspeed(edev, 100);
else if(r & Speed1000) else if(r & Speed1000)
ethersetspeed(edev, 1000); ethersetspeed(edev, 1000);
ethersetlink(edev, 1);
} else {
ethersetlink(edev, 0);
} }
} }

View file

@ -508,7 +508,7 @@ struct Ctlr {
uvlong port; uvlong port;
Pcidev *pcidev; Pcidev *pcidev;
Ctlr *next; Ctlr *next;
int active; Ether *edev;
int type; int type;
u16int eeprom[0x40]; u16int eeprom[0x40];
@ -851,7 +851,7 @@ i82563cleanup(Ctlr *c)
c->tb[tdh] = nil; c->tb[tdh] = nil;
freeb(b); freeb(b);
}else }else
iprint("82563 tx underrun!\n"); iprint("#l%d: %s: tx underrun!\n", c->edev->ctlrno, cname(c));
c->tdba[tdh].status = 0; c->tdba[tdh].status = 0;
} }
@ -914,7 +914,7 @@ i82563replenish(Ctlr *ctlr)
for(rdt = ctlr->rdt; NEXT(rdt, ctlr->nrd) != ctlr->rdh; rdt = NEXT(rdt, ctlr->nrd)){ for(rdt = ctlr->rdt; NEXT(rdt, ctlr->nrd) != ctlr->rdh; rdt = NEXT(rdt, ctlr->nrd)){
rd = &ctlr->rdba[rdt]; rd = &ctlr->rdba[rdt];
if(ctlr->rb[rdt] != nil){ if(ctlr->rb[rdt] != nil){
iprint("82563: tx overrun\n"); iprint("#l%d: %s: tx overrun\n", ctlr->edev->ctlrno, cname(ctlr));
break; break;
} }
i++; i++;
@ -1097,7 +1097,7 @@ phyread(Ctlr *c, int phyno, int reg)
microdelay(1); microdelay(1);
} }
if((phy & (MDIe|MDIready)) != MDIready){ if((phy & (MDIe|MDIready)) != MDIready){
print("%s: phy %d wedged %.8ux\n", cname(c), phyno, phy); print("#l%d: %s: phy %d wedged %.8ux\n", c->edev->ctlrno, cname(c), phyno, phy);
return ~0; return ~0;
} }
return phy & 0xffff; return phy & 0xffff;
@ -1143,18 +1143,18 @@ static uint
phywrite(Ctlr *c, uint phyno, uint reg, ushort v) phywrite(Ctlr *c, uint phyno, uint reg, ushort v)
{ {
if(setpage(c, phyno, reg>>8, reg & 0xff) == ~0) if(setpage(c, phyno, reg>>8, reg & 0xff) == ~0)
panic("%s: bad phy reg %.4ux", cname(c), reg); panic("#l%d: %s: bad phy reg %.4ux", c->edev->ctlrno, cname(c), reg);
return phywrite0(c, phyno, reg & 0xff, v); return phywrite0(c, phyno, reg & 0xff, v);
} }
static void static void
phyerrata(Ether *e, Ctlr *c, uint phyno) phyerrata(Ctlr *c, uint phyno)
{ {
if(e->mbps == 0){ if(c->edev->mbps == 0){
if(c->phyerrata == 0){ if(c->phyerrata == 0){
c->phyerrata++; c->phyerrata++;
phywrite(c, phyno, Phyprst, Prst); /* try a port reset */ phywrite(c, phyno, Phyprst, Prst); /* try a port reset */
print("%s: phy port reset\n", cname(c)); print("#l%d: %s: phy port reset\n", c->edev->ctlrno, cname(c));
} }
}else }else
c->phyerrata = 0; c->phyerrata = 0;
@ -1174,10 +1174,11 @@ phyprobe(Ctlr *c, uint mask)
phy |= phyread(c, phyno, Phyid2) >> 10; phy |= phyread(c, phyno, Phyid2) >> 10;
if(phy == 0xFFFFF || phy == 0) if(phy == 0xFFFFF || phy == 0)
continue; continue;
print("%s: phy%d oui %#ux\n", cname(c), phyno, phy); print("#l%d: %s: phy%d oui %#ux\n", c->edev->ctlrno, cname(c),
phyno, phy);
return phyno; return phyno;
} }
print("%s: no phy\n", cname(c)); print("#l%d: %s: no phy\n", c->edev->ctlrno, cname(c));
return ~0; return ~0;
} }
@ -1221,11 +1222,13 @@ phyl79proc(void *v)
break; break;
} }
i = (phy>>8) & 3; i = (phy>>8) & 3;
e->link = i != 3 && (phy & Link) != 0; if(i != 3 && (phy & Link) != 0){
if(e->link)
ethersetspeed(e, speedtab[i]); ethersetspeed(e, speedtab[i]);
else ethersetlink(e, 1);
}else{
ethersetlink(e, 0);
i = 3; i = 3;
}
c->speeds[i]++; c->speeds[i]++;
lsleep(c, Lsc); lsleep(c, Lsc);
} }
@ -1278,14 +1281,16 @@ phylproc(void *v)
if(a) if(a)
phywrite(c, phyno, Phyctl, phyread(c, phyno, Phyctl) | Ran | Ean); phywrite(c, phyno, Phyctl, phyread(c, phyno, Phyctl) | Ran | Ean);
next: next:
e->link = (phy & Rtlink) != 0; if(phy & Rtlink){
if(e->link)
ethersetspeed(e, speedtab[i]); ethersetspeed(e, speedtab[i]);
else ethersetlink(e, 1);
}else{
ethersetlink(e, 0);
i = 3; i = 3;
}
c->speeds[i]++; c->speeds[i]++;
if(c->type == i82563) if(c->type == i82563)
phyerrata(e, c, phyno); phyerrata(c, phyno);
lsleep(c, Lsc); lsleep(c, Lsc);
} }
} }
@ -1306,13 +1311,16 @@ pcslproc(void *v)
csr32w(c, Connsw, Enrgirq); csr32w(c, Connsw, Enrgirq);
for(;;){ for(;;){
phy = csr32r(c, Pcsstat); phy = csr32r(c, Pcsstat);
e->link = phy & Linkok; if(phy & Linkok){
i = 3;
if(e->link){
i = (phy & 6) >> 1; i = (phy & 6) >> 1;
ethersetspeed(e, speedtab[i]); ethersetspeed(e, speedtab[i]);
}else if(phy & Anbad) ethersetlink(e, 1);
csr32w(c, Pcsctl, csr32r(c, Pcsctl) | Pan | Prestart); }else {
ethersetlink(e, 0);
if(phy & Anbad)
csr32w(c, Pcsctl, csr32r(c, Pcsctl) | Pan | Prestart);
i = 3;
}
c->speeds[i]++; c->speeds[i]++;
lsleep(c, Lsc | Omed); lsleep(c, Lsc | Omed);
} }
@ -1333,12 +1341,13 @@ serdeslproc(void *v)
rx = csr32r(c, Rxcw); rx = csr32r(c, Rxcw);
tx = csr32r(c, Txcw); tx = csr32r(c, Txcw);
USED(tx); USED(tx);
e->link = (rx & 1<<31) != 0; if(rx & 1<<31){ /*(csr32r(c, Status) & Lu*/
// e->link = (csr32r(c, Status) & Lu) != 0;
i = 3;
if(e->link){
i = 2; i = 2;
ethersetspeed(e, speedtab[i]); ethersetspeed(e, speedtab[i]);
ethersetlink(e, 1);
} else {
ethersetlink(e, 0);
i = 3;
} }
c->speeds[i]++; c->speeds[i]++;
lsleep(c, Lsc); lsleep(c, Lsc);
@ -1538,7 +1547,7 @@ eeread(Ctlr *ctlr, int adr)
while ((csr32r(ctlr, Eerd) & EEdone) == 0 && timeout--) while ((csr32r(ctlr, Eerd) & EEdone) == 0 && timeout--)
microdelay(5); microdelay(5);
if (timeout < 0) { if (timeout < 0) {
print("%s: eeread timeout\n", cname(ctlr)); print("#l%d: %s: eeread timeout\n", ctlr->edev->ctlrno, cname(ctlr));
return -1; return -1;
} }
return (csr32r(ctlr, Eerd) >> 16) & 0xffff; return (csr32r(ctlr, Eerd) >> 16) & 0xffff;
@ -1589,7 +1598,7 @@ done:
while((f->reg[Fsts] & Fdone) == 0 && timeout--) while((f->reg[Fsts] & Fdone) == 0 && timeout--)
microdelay(5); microdelay(5);
if(timeout < 0){ if(timeout < 0){
print("%s: fread timeout\n", cname(c)); print("#l%d: %s: fread timeout\n", c->edev->ctlrno, cname(c));
return -1; return -1;
} }
if(f->reg[Fsts] & (Fcerr|Ael)) if(f->reg[Fsts] & (Fcerr|Ael))
@ -1626,7 +1635,7 @@ done:
while((f->reg32[Fsts/2] & Fdone) == 0 && timeout--) while((f->reg32[Fsts/2] & Fdone) == 0 && timeout--)
microdelay(5); microdelay(5);
if(timeout < 0){ if(timeout < 0){
print("%s: fread timeout\n", cname(c)); print("#l%d: %s: fread timeout\n", c->edev->ctlrno, cname(c));
return -1; return -1;
} }
if(f->reg32[Fsts/2] & (Fcerr|Ael)) if(f->reg32[Fsts/2] & (Fcerr|Ael))
@ -1777,7 +1786,7 @@ i82563reset(Ctlr *ctlr)
r = eeload(ctlr); r = eeload(ctlr);
if(r != 0 && r != 0xbaba){ if(r != 0 && r != 0xbaba){
print("%s: bad eeprom checksum - %#.4ux", cname(ctlr), r); print("#l%d: %s: bad eeprom checksum - %#.4ux", ctlr->edev->ctlrno, cname(ctlr), r);
if(flag & Fbadcsum) if(flag & Fbadcsum)
print("; ignored\n"); print("; ignored\n");
else { else {
@ -2101,12 +2110,12 @@ pnp(Ether *edev, int type)
for(ctlr = i82563ctlrhead; ; ctlr = ctlr->next){ for(ctlr = i82563ctlrhead; ; ctlr = ctlr->next){
if(ctlr == nil) if(ctlr == nil)
return -1; return -1;
if(ctlr->active) if(ctlr->edev != nil)
continue; continue;
if(type != -1 && ctlr->type != type) if(type != -1 && ctlr->type != type)
continue; continue;
if(edev->port == 0 || edev->port == ctlr->port){ if(edev->port == 0 || edev->port == ctlr->port){
ctlr->active = 1; ctlr->edev = edev;
memmove(ctlr->ra, edev->ea, Eaddrlen); memmove(ctlr->ra, edev->ea, Eaddrlen);
if(setup(ctlr) == 0) if(setup(ctlr) == 0)
break; break;

View file

@ -384,11 +384,13 @@ lproc(void *v)
; ;
for (;;) { for (;;) {
r = c->reg[Links]; r = c->reg[Links];
e->link = (r & Lnkup) != 0; if(r & Lnkup){
i = 0;
if(e->link){
i = 1 + ((r & Lnkspd) != 0); i = 1 + ((r & Lnkspd) != 0);
ethersetspeed(e, speedtab[i]); ethersetspeed(e, speedtab[i]);
ethersetlink(e, 1);
} else {
ethersetlink(e, 0);
i = 0;
} }
c->speeds[i]++; c->speeds[i]++;
c->lim = 0; c->lim = 0;

View file

@ -333,15 +333,14 @@ checklink(Ether *edev)
ulong i; ulong i;
int mbps; int mbps;
mbps = 0;
ctlr = edev->ctlr; ctlr = edev->ctlr;
miir(ctlr, PhyStatus); /* dummy read necessary */ miir(ctlr, PhyStatus); /* dummy read necessary */
if(!(miir(ctlr, PhyStatus) & PhyLinkStatus)) { if(!(miir(ctlr, PhyStatus) & PhyLinkStatus)) {
edev->link = 0;
ctlr->duplex = 1; ctlr->duplex = 1;
print("bcm: no link\n"); ethersetlink(edev, 0);
goto out; goto out;
} }
edev->link = 1;
while((miir(ctlr, PhyStatus) & PhyAutoNegComplete) == 0); while((miir(ctlr, PhyStatus) & PhyAutoNegComplete) == 0);
i = miir(ctlr, PhyGbitStatus); i = miir(ctlr, PhyGbitStatus);
if(i & (Phy1000FD | Phy1000HD)) { if(i & (Phy1000FD | Phy1000HD)) {
@ -354,13 +353,12 @@ checklink(Ether *edev)
mbps = 10; mbps = 10;
ctlr->duplex = (i & Phy10FD) != 0; ctlr->duplex = (i & Phy10FD) != 0;
} else { } else {
edev->link = 0;
ctlr->duplex = 1; ctlr->duplex = 1;
print("bcm: link partner supports neither 10/100/1000 Mbps\n"); ethersetlink(edev, 0);
goto out; goto out;
} }
print("bcm: %d Mbps link, %s duplex\n", mbps, ctlr->duplex ? "full" : "half");
ethersetspeed(edev, mbps); ethersetspeed(edev, mbps);
ethersetlink(edev, 1);
out: out:
if(ctlr->duplex) csr32(ctlr, MACMode) &= ~MACHalfDuplex; if(ctlr->duplex) csr32(ctlr, MACMode) &= ~MACHalfDuplex;
else csr32(ctlr, MACMode) |= MACHalfDuplex; else csr32(ctlr, MACMode) |= MACHalfDuplex;

View file

@ -2118,6 +2118,8 @@ etherelnk3reset(Ether* ether)
intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name); intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
ether->link = ether->mbps != 0;
return 0; return 0;
} }

View file

@ -583,17 +583,12 @@ ga620event(Ether *edev, int eci, int epi)
case 1: case 1:
ethersetspeed(edev, 1000); ethersetspeed(edev, 1000);
break; break;
case 2:
print("#l%d: link down\n", edev->ctlrno);
break;
case 3: case 3:
/* it's 10 or 100 */ /* it's 10 or 100 */
ethersetspeed(edev, 100); ethersetspeed(edev, 100);
break; break;
} }
if (code != 2) ethersetlink(edev, code != 2);
print("#l%d: %dMbps link up\n",
edev->ctlrno, edev->mbps);
break; break;
case 0x07: /* event error */ case 0x07: /* event error */
default: default:

View file

@ -1242,13 +1242,8 @@ checkstats(Ether *e, Ctlr *c, Stats *s)
return; return;
i = gbit32(s->linkstat); i = gbit32(s->linkstat);
if(c->linkstat != i){ if(c->linkstat != i)
e->link = i; ethersetlink(e, c->linkstat = i);
if(c->linkstat = i)
dprint("m10g: link up\n");
else
dprint("m10g: link down\n");
}
i = gbit32(s->nrdma); i = gbit32(s->nrdma);
if(i != c->nrdma){ if(i != c->nrdma){
dprint("m10g: rdma timeout %ld\n", i); dprint("m10g: rdma timeout %ld\n", i);

View file

@ -713,9 +713,8 @@ vgbeinterrupt(Ureg *, void* arg)
print("vgbe: irq: PHY interrupt\n"); print("vgbe: irq: PHY interrupt\n");
if(status & Isr_LinkStatus){ if(status & Isr_LinkStatus){
edev->link = (riob(ctlr, PhySts0) & PhySts_Link) ? 1 : 0; ethersetlink(edev, riob(ctlr, PhySts0) & PhySts_Link);
vgbemiip(ctlr, 1); vgbemiip(ctlr, 1);
print("vgbe: irq: link status change\n");
} }
if(status & Isr_RxNoDesc) if(status & Isr_RxNoDesc)
print("vgbe: irq: ran out of Rx descriptors\n"); print("vgbe: irq: ran out of Rx descriptors\n");

View file

@ -346,11 +346,13 @@ lproc(void *v)
; ;
for (;;) { for (;;) {
r = c->reg[Links]; r = c->reg[Links];
e->link = (r & Lnkup) != 0; if(r & Lnkup){
i = 0;
if(e->link){
i = 1 + ((r & Lnkspd) != 0); i = 1 + ((r & Lnkspd) != 0);
ethersetspeed(e, speedtab[i]); ethersetspeed(e, speedtab[i]);
ethersetlink(e, 1);
} else {
ethersetlink(e, 0);
i = 0;
} }
c->speeds[i]++; c->speeds[i]++;
c->lim = 0; c->lim = 0;

View file

@ -1365,10 +1365,12 @@ link(Ether *e)
i = phyread(c, Phyint); i = phyread(c, Phyint);
s = phyread(c, Phylstat); s = phyread(c, Phylstat);
dprint("#l%d: yuk: link %.8ux %.8ux\n", e->ctlrno, i, s); dprint("#l%d: yuk: link %.8ux %.8ux\n", e->ctlrno, i, s);
e->link = (s & Plink) != 0; if(s & Plink){
if(e->link)
ethersetspeed(e, (c->feat&Ffiber)? 1000: spdtab[(s & Physpd) >> 14]); ethersetspeed(e, (c->feat&Ffiber)? 1000: spdtab[(s & Physpd) >> 14]);
dprint("#l%d: yuk: link %d spd %d\n", e->ctlrno, e->link, e->mbps); ethersetlink(e, 1);
} else {
ethersetlink(e, 0);
}
} }
static void static void

View file

@ -475,6 +475,17 @@ ethersetspeed(Ether *ether, int mbps)
return; return;
netifsetlimit(ether, etherqueuesize(ether)); netifsetlimit(ether, etherqueuesize(ether));
qsetlimit(ether->oq, ether->limit); qsetlimit(ether->oq, ether->limit);
print("#l%d: %s: speed %dMbps\n", ether->ctlrno, ether->type, mbps);
}
void
ethersetlink(Ether *ether, int link)
{
link = !!link;
if(!!ether->link == link)
return;
ether->link = link;
print("#l%d: %s: link %s\n", ether->ctlrno, ether->type, link? "up": "down");
} }
static void netconsole(int); static void netconsole(int);

View file

@ -52,6 +52,7 @@ struct Ether {
}; };
extern void ethersetspeed(Ether*, int); extern void ethersetspeed(Ether*, int);
extern void ethersetlink(Ether*, int);
extern void etheriq(Ether*, Block*); extern void etheriq(Ether*, Block*);
extern void addethercard(char*, int(*)(Ether*)); extern void addethercard(char*, int(*)(Ether*));
extern ulong ethercrc(uchar*, int); extern ulong ethercrc(uchar*, int);

View file

@ -54,6 +54,7 @@ reset(Ether* ether)
{ {
if(ether->type==nil) if(ether->type==nil)
return -1; return -1;
ether->link = 0;
ether->mbps = 1000; ether->mbps = 1000;
ether->attach = attach; ether->attach = attach;
ether->multicast = multicast; ether->multicast = multicast;

View file

@ -780,7 +780,6 @@ reset(Ether* edev)
edev->multicast = multicast; edev->multicast = multicast;
edev->promiscuous = promiscuous; edev->promiscuous = promiscuous;
pcisetbme(ctlr->pcidev); pcisetbme(ctlr->pcidev);
intrenable(edev->irq, interrupt, edev, edev->tbdf, edev->name); intrenable(edev->irq, interrupt, edev, edev->tbdf, edev->name);

View file

@ -815,9 +815,13 @@ Scan:
/* maintain access point */ /* maintain access point */
tmout = 0; tmout = 0;
while((wn = wifi->bss) != nil){ while((wn = wifi->bss) != nil){
ether->link = (wn->status == Sassoc) || (wn->status == Sblocked); if(wn->status == Sassoc || wn->status == Sblocked){
if(ether->link && (rate = wn->actrate) != nil) if((rate = wn->actrate) != nil)
ethersetspeed(ether, ((*rate & 0x7f)+3)/4); ethersetspeed(ether, ((*rate & 0x7f)+3)/4);
ethersetlink(ether, 1);
} else {
ethersetlink(ether, 0);
}
now = MACHP(0)->ticks; now = MACHP(0)->ticks;
if(wn->status != Sneedauth && TK2SEC(now - wn->lastseen) > 20 || goodbss(wifi, wn) == 0){ if(wn->status != Sneedauth && TK2SEC(now - wn->lastseen) > 20 || goodbss(wifi, wn) == 0){
wifideauth(wifi, wn); wifideauth(wifi, wn);

View file

@ -867,10 +867,11 @@ fccltimer(Ureg*, Timer *t)
return; return;
} }
if(phy->link == 0){ if(phy->link == 0){
print("link lost\n"); ethersetlink(ether, 0);
return; return;
} }
ethersetspeed(ether, phy->speed); ethersetspeed(ether, phy->speed);
ethersetlink(ether, 1);
if(phy->fd != ctlr->duplex) if(phy->fd != ctlr->duplex)
print("set duplex\n"); print("set duplex\n");

View file

@ -1280,24 +1280,22 @@ rtl8169link(Ether* edev)
ctlr = edev->ctlr; ctlr = edev->ctlr;
if(!((r = csr8r(ctlr, Phystatus)) & Linksts)){ if(!((r = csr8r(ctlr, Phystatus)) & Linksts)){
if (edev->link) { if(edev->link) {
edev->link = 0;
csr8w(ctlr, Cr, Re); csr8w(ctlr, Cr, Re);
iprint("#l%d: link down\n", edev->ctlrno); ethersetlink(edev, 0);
} }
return; return;
} }
if(edev->link == 0) {
edev->link = 1;
csr8w(ctlr, Cr, Te|Re);
iprint("#l%d: link up\n", edev->ctlrno);
}
if(r & Speed10) if(r & Speed10)
ethersetspeed(edev, 10); ethersetspeed(edev, 10);
else if(r & Speed100) else if(r & Speed100)
ethersetspeed(edev, 100); ethersetspeed(edev, 100);
else if(r & Speed1000) else if(r & Speed1000)
ethersetspeed(edev, 1000); ethersetspeed(edev, 1000);
if(edev->link == 0) {
csr8w(ctlr, Cr, Te|Re);
ethersetlink(edev, 1);
}
} }
static void static void

View file

@ -141,7 +141,6 @@ ethproc(void *ved)
{ {
Ether *edev; Ether *edev;
Ctlr *c; Ctlr *c;
char *sp, *dpl;
u16int v; u16int v;
edev = ved; edev = ved;
@ -149,40 +148,32 @@ ethproc(void *ved)
mdwrite(c, MDCTRL, AUTONEG); mdwrite(c, MDCTRL, AUTONEG);
for(;;){ for(;;){
if((mdread(c, MDSTATUS) & LINK) == 0){ if((mdread(c, MDSTATUS) & LINK) == 0){
edev->link = 0; ethersetlink(edev, 0);
print("eth: no link\n");
while((mdread(c, MDSTATUS) & LINK) == 0) while((mdread(c, MDSTATUS) & LINK) == 0)
tsleep(&up->sleep, return0, nil, Linkdelay); tsleep(&up->sleep, return0, nil, Linkdelay);
} }
v = mdread(c, MDPHYCTRL); v = mdread(c, MDPHYCTRL);
if((v & 0x40) != 0){ if((v & 0x40) != 0){
sp = "1000BASE-T";
while((mdread(c, MDGSTATUS) & RECVOK) != RECVOK) while((mdread(c, MDGSTATUS) & RECVOK) != RECVOK)
; ;
c->r[NET_CFG] |= GIGE_EN; c->r[NET_CFG] |= GIGE_EN;
slcr[GEM0_CLK_CTRL] = 1 << 20 | 8 << 8 | 1; slcr[GEM0_CLK_CTRL] = 1 << 20 | 8 << 8 | 1;
ethersetspeed(edev, 1000); ethersetspeed(edev, 1000);
}else if((v & 0x20) != 0){ }else if((v & 0x20) != 0){
sp = "100BASE-TX";
c->r[NET_CFG] = c->r[NET_CFG] & ~GIGE_EN | SPEED; c->r[NET_CFG] = c->r[NET_CFG] & ~GIGE_EN | SPEED;
slcr[GEM0_CLK_CTRL] = 5 << 20 | 8 << 8 | 1; slcr[GEM0_CLK_CTRL] = 5 << 20 | 8 << 8 | 1;
ethersetspeed(edev, 100); ethersetspeed(edev, 100);
}else if((v & 0x10) != 0){ }else if((v & 0x10) != 0){
sp = "10BASE-T";
c->r[NET_CFG] = c->r[NET_CFG] & ~(GIGE_EN | SPEED); c->r[NET_CFG] = c->r[NET_CFG] & ~(GIGE_EN | SPEED);
slcr[GEM0_CLK_CTRL] = 20 << 20 | 20 << 8 | 1; slcr[GEM0_CLK_CTRL] = 20 << 20 | 20 << 8 | 1;
ethersetspeed(edev, 10); ethersetspeed(edev, 10);
}else }
sp = "???";
if((v & 0x08) != 0){ if((v & 0x08) != 0){
dpl = "full";
c->r[NET_CFG] |= FDEN; c->r[NET_CFG] |= FDEN;
}else{ }else{
dpl = "half";
c->r[NET_CFG] &= ~FDEN; c->r[NET_CFG] &= ~FDEN;
} }
edev->link = 1; ethersetlink(edev, 1);
print("eth: %s %s duplex link\n", sp, dpl);
while((mdread(c, MDSTATUS) & LINK) != 0) while((mdread(c, MDSTATUS) & LINK) != 0)
tsleep(&up->sleep, return0, nil, Linkdelay); tsleep(&up->sleep, return0, nil, Linkdelay);
} }