ref: 239a24fd1bc5ade8f652b158835fb1bdc7f8eeb8
parent: c3a732918457130960be822c6c19c5830f226a37
author: aiju <aiju@phicode.de>
date: Sat Nov 5 06:22:21 EDT 2011
added timeouts to bcminit()
--- a/sys/src/9/pc/etherbcm.c
+++ b/sys/src/9/pc/etherbcm.c
@@ -425,7 +425,7 @@
iunlock(&ctlr->imlock);
}
-static void
+static int
bcminit(Ether *edev)
{ulong i, j;
@@ -436,7 +436,12 @@
/* initialization procedure according to the datasheet */
csr32(ctlr, MiscHostCtl) |= MaskPCIInt | ClearIntA;
csr32(ctlr, SwArbitration) |= SwArbitSet1;
- while((csr32(ctlr, SwArbitration) & SwArbitWon1) == 0);
+ for(i = 0; i < 10000 && (csr32(ctlr, SwArbitration) & SwArbitWon1) == 0; i++)
+ microdelay(100);
+ if(i == 10000){+ iprint("bcm: arbiter failed to respond\n");+ return -1;
+ }
csr32(ctlr, MemArbiterMode) |= Enable;
csr32(ctlr, MiscHostCtl) |= IndirectAccessEnable | EnablePCIStateRegister | EnableClockControlRegister;
csr32(ctlr, MemoryWindow) = 0;
@@ -452,7 +457,12 @@
csr32(ctlr, ModeControl) |= ByteWordSwap;
csr32(ctlr, MACMode) = (csr32(ctlr, MACMode) & MACPortMask) | MACPortGMII;
microdelay(40000);
- while(mem32(ctlr, 0xB50) != 0xB49A89AB);
+ for(i = 0; i < 100000 && mem32(ctlr, 0xB50) != 0xB49A89AB; i++)
+ microdelay(100);
+ if(i == 100000){+ iprint("bcm: chip failed to reset\n");+ return -1;
+ }
csr32(ctlr, TLPControl) |= (1<<25) | (1<<29);
memset(ctlr->status, 0, 20);
csr32(ctlr, DMARWControl) = (csr32(ctlr, DMARWControl) & DMAWatermarkMask) | DMAWatermarkValue;
@@ -462,10 +472,20 @@
csr32(ctlr, MBUFHighWatermark) = 0x60;
csr32(ctlr, LowWatermarkMaximum) = (csr32(ctlr, LowWatermarkMaximum) & LowWatermarkMaxMask) | LowWatermarkMaxValue;
csr32(ctlr, BufferManMode) |= Enable | Attn;
- while((csr32(ctlr, BufferManMode) & Enable) == 0);
+ for(i = 0; i < 100 && (csr32(ctlr, BufferManMode) & Enable) == 0; i++)
+ microdelay(100);
+ if(i == 100){+ iprint("bcm: buffer manager failed to start\n");+ return -1;
+ }
csr32(ctlr, FTQReset) = -1;
csr32(ctlr, FTQReset) = 0;
- while(csr32(ctlr, FTQReset));
+ for(i = 0; i < 1000 && csr32(ctlr, FTQReset) != 0; i++)
+ microdelay(100);
+ if(i == 1000){+ iprint("bcm: ftq failed to reset\n");+ return -1;
+ }
csr32(ctlr, ReceiveBDHostAddr) = 0;
csr32(ctlr, ReceiveBDHostAddr + 4) = PADDR(ctlr->recvprod);
csr32(ctlr, ReceiveBDFlags) = RecvProdRingLen << 16;
@@ -503,7 +523,12 @@
csr32(ctlr, SendInitiatorMask) = 0xFFFFFF;
csr32(ctlr, SendInitiatorConfiguration) |= SendStats;
csr32(ctlr, HostCoalescingMode) = 0;
- while(csr32(ctlr, HostCoalescingMode) != 0);
+ for(i = 0; i < 200 && csr32(ctlr, HostCoalescingMode) != 0; i++)
+ microdelay(100);
+ if(i == 200){+ iprint("bcm: host coalescing engine failed to stop\n");+ return -1;
+ }
csr32(ctlr, HostCoalescingRecvTicks) = 150;
csr32(ctlr, HostCoalescingSendTicks) = 150;
csr32(ctlr, RecvMaxCoalescedFrames) = 10;
@@ -539,7 +564,12 @@
csr32(ctlr, MIMode) = 0xC0000;
microdelay(40);
miiw(ctlr, PhyControl, 1<<15);
- while(miir(ctlr, PhyControl) & (1<<15));
+ for(i = 0; i < 1000 && miir(ctlr, PhyControl) & (1<<15); i++)
+ microdelay(100);
+ if(i == 1000){+ iprint("bcm: PHY failed to reset\n");+ return -1;
+ }
miiw(ctlr, PhyAuxControl, 2);
miir(ctlr, PhyIntStatus);
miir(ctlr, PhyIntStatus);
@@ -554,6 +584,7 @@
csr32(ctlr, ReceiveRulesConfiguration) = 1 << 3;
csr32(ctlr, MSIMode) |= Enable;
csr32(ctlr, MiscHostCtl) &= ~(MaskPCIInt | ClearIntA);
+ return 0;
}
static void
@@ -637,6 +668,7 @@
{Ctlr *ctlr;
+again:
if(bcmhead == nil)
bcmpci();
@@ -664,7 +696,10 @@
edev->arg = edev;
edev->mbps = 1000;
- bcminit(edev);
+ if(bcminit(edev) < 0){+ edev->ctlr = nil;
+ goto again;
+ }
return 0;
}
--
⑨