static void w_timer(void* arg) { Ether* ether = (Ether*) arg; Ctlr* ctlr = (Ctlr*)ether->ctlr; ctlr->timerproc = up; for(;;) { tsleep(&up->sleep, return0, 0, MSperTick); ctlr = (Ctlr*)ether->ctlr; if(ctlr == 0) break; if((ctlr->state & (Attached|Power)) != (Attached|Power)) continue; ctlr->ticks++; ilock(ctlr); // Seems that the card gets frames BUT does // not send the interrupt; this is a problem because // I suspect it runs out of receive buffers and // stops receiving until a transmit watchdog // reenables the card. // The problem is serious because it leads to // poor rtts. // This can be seen clearly by commenting out // the next if and doing a ping: it will stop // receiving (although the icmp replies are being // issued from the remote) after a few seconds. // Of course this `bug' could be because I'm reading // the card frames in the wrong way; due to the // lack of documentation I cannot know. if(csr_ins(ctlr, WR_EvSts)&WEvs) { ctlr->tickintr++; w_intr(ether); } if((ctlr->ticks % 10) == 0) { if(ctlr->txtmout && --ctlr->txtmout == 0) { ctlr->nwatchdogs++; w_txdone(ctlr, WTxErrEv); if(w_enable(ether)) { DEBUG("wavelan: wdog enable failed\n"); } w_txstart(ether); } if((ctlr->ticks % 120) == 0) if(ctlr->txbusy == 0) w_cmd(ctlr, WCmdEnquire, WTyp_Stats); if(ctlr->scanticks > 0) if((ctlr->ticks % ctlr->scanticks) == 0) if(ctlr->txbusy == 0) w_cmd(ctlr, WCmdEnquire, WTyp_Scan); } iunlock(ctlr); } pexit("terminated", 0); }
void w_interrupt(Ureg* ,void* arg) { Ether* ether = (Ether*) arg; Ctlr* ctlr = (Ctlr*) ether->ctlr; if(ctlr == 0) return; ilock(ctlr); ctlr->nints++; w_intr(ether); iunlock(ctlr); }