void w_power(Ether* ether, int on) { Ctlr *ctlr; ctlr = (Ctlr*) ether->ctlr; ilock(ctlr); iprint("w_power %d\n", on); if(on){ if((ctlr->state & Power) == 0){ if (wavelanreset(ether, ctlr) < 0){ iprint("w_power: reset failed\n"); iunlock(ctlr); w_detach(ether); free(ctlr); return; } if(ctlr->state & Attached) w_enable(ether); ctlr->state |= Power; } }else{ if(ctlr->state & Power){ if(ctlr->state & Attached) w_intdis(ctlr); ctlr->state &= ~Power; } } iunlock(ctlr); }
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_attach(Ether* ether) { Ctlr* ctlr; char name[64]; int rc; if(ether->ctlr == 0) return; snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno); ctlr = (Ctlr*) ether->ctlr; if((ctlr->state & Attached) == 0){ ilock(ctlr); rc = w_enable(ether); iunlock(ctlr); if(rc == 0){ ctlr->state |= Attached; kproc(name, w_timer, ether); } else print("#l%d: enable failed\n",ether->ctlrno); } }
long w_ctl(Ether* ether, void* buf, long n) { Ctlr *ctlr; if((ctlr = ether->ctlr) == nil) error(Enonexist); if((ctlr->state & Attached) == 0) error(Eshutdown); ilock(ctlr); if(w_option(ctlr, buf, n)){ iunlock(ctlr); error(Ebadctl); } if(ctlr->txbusy) w_txdone(ctlr, WTxErrEv); w_enable(ether); w_txstart(ether); iunlock(ctlr); return n; }