📄 wavelan.c
字号:
return 0; } return -1;}/* set scanning interval */static voidw_scanbs(void *a, uint secs){ Ether *ether = a; Ctlr* ctlr = (Ctlr*) ether->ctlr; ctlr->scanticks = secs*(1000/MSperTick);}static voidw_intr(Ether *ether){ int rc, txid; Ctlr* ctlr = (Ctlr*) ether->ctlr; if((ctlr->state & Power) == 0) return; if((ctlr->state & Attached) == 0){ csr_ack(ctlr, 0xffff); csr_outs(ctlr, WR_IntEna, 0); return; } rc = csr_ins(ctlr, WR_EvSts); csr_ack(ctlr, ~WEvs); // Not interested in them if(rc & WRXEv){ w_rxdone(ether); csr_ack(ctlr, WRXEv); } if(rc & WTXEv){ w_txdone(ctlr, rc); csr_ack(ctlr, WTXEv); } if(rc & WAllocEv){ ctlr->nalloc++; txid = csr_ins(ctlr, WR_Alloc); csr_ack(ctlr, WAllocEv); if(txid == ctlr->txdid){ if((rc & WTXEv) == 0) w_txdone(ctlr, rc); } } if(rc & WInfoEv){ ctlr->ninfo++; w_info(ether, ctlr); csr_ack(ctlr, WInfoEv); } if(rc & WTxErrEv){ w_txdone(ctlr, rc); csr_ack(ctlr, WTxErrEv); } if(rc & WIDropEv){ ctlr->nidrop++; csr_ack(ctlr, WIDropEv); } w_txstart(ether);}// Watcher to ensure that the card still works properly and// to request WStats updates once a minute.// BUG: it runs much more often, see the comment below.static voidw_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);}voidw_multicast(void*, uchar*, int){ // BUG: to be added.}voidw_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); }}voidw_detach(Ether* ether){ Ctlr* ctlr; char name[64]; if(ether->ctlr == nil) return; snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno); ctlr = (Ctlr*) ether->ctlr; if(ctlr->state & Attached){ ilock(ctlr); w_intdis(ctlr); if(ctlr->timerproc){ if(!postnote(ctlr->timerproc, 1, "kill", NExit)) print("timerproc note not posted\n"); print("w_detach, killing 0x%p\n", ctlr->timerproc); } ctlr->state &= ~Attached; iunlock(ctlr); } ether->ctlr = nil;}voidw_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);}#define PRINTSTAT(fmt,val) l += snprint(p+l, READSTR-l, (fmt), (val))#define PRINTSTR(fmt) l += snprint(p+l, READSTR-l, (fmt))longw_ifstat(Ether* ether, void* a, long n, ulong offset){ Ctlr *ctlr = (Ctlr*) ether->ctlr; char *k, *p; int i, l, txid; ether->oerrs = ctlr->ntxerr; ether->crcs = ctlr->nrxfcserr; ether->frames = 0; ether->buffs = ctlr->nrxdropnobuf; ether->overflows = 0; // // Offset must be zero or there's a possibility the // new data won't match the previous read. // if(n == 0 || offset != 0) return 0; p = malloc(READSTR); l = 0; PRINTSTAT("Signal: %d\n", ctlr->signal-149); PRINTSTAT("Noise: %d\n", ctlr->noise-149); PRINTSTAT("SNR: %ud\n", ctlr->signal-ctlr->noise); PRINTSTAT("Interrupts: %lud\n", ctlr->nints); PRINTSTAT("Double Interrupts: %lud\n", ctlr->ndoubleint); PRINTSTAT("TxPackets: %lud\n", ctlr->ntx); PRINTSTAT("RxPackets: %lud\n", ctlr->nrx); PRINTSTAT("TxErrors: %lud\n", ctlr->ntxerr); PRINTSTAT("RxErrors: %lud\n", ctlr->nrxerr); PRINTSTAT("TxRequests: %lud\n", ctlr->ntxrq); PRINTSTAT("AllocEvs: %lud\n", ctlr->nalloc); PRINTSTAT("InfoEvs: %lud\n", ctlr->ninfo); PRINTSTAT("InfoDrop: %lud\n", ctlr->nidrop); PRINTSTAT("WatchDogs: %lud\n", ctlr->nwatchdogs); PRINTSTAT("Ticks: %ud\n", ctlr->ticks); PRINTSTAT("TickIntr: %ud\n", ctlr->tickintr); k = ((ctlr->state & Attached) ? "attached" : "not attached"); PRINTSTAT("Card %s", k); k = ((ctlr->state & Power) ? "on" : "off"); PRINTSTAT(", power %s", k); k = ((ctlr->txbusy)? ", txbusy" : ""); PRINTSTAT("%s\n", k); if(ctlr->hascrypt){ PRINTSTR("Keys: "); for (i = 0; i < WNKeys; i++){ if(ctlr->keys.keys[i].len == 0) PRINTSTR("none "); else if(SEEKEYS == 0) PRINTSTR("set "); else PRINTSTAT("%s ", ctlr->keys.keys[i].dat); } PRINTSTR("\n"); } // real card stats ilock(ctlr); PRINTSTR("\nCard stats: \n"); PRINTSTAT("Status: %ux\n", csr_ins(ctlr, WR_Sts)); PRINTSTAT("Event status: %ux\n", csr_ins(ctlr, WR_EvSts)); i = ltv_ins(ctlr, WTyp_Ptype); PRINTSTAT("Port type: %d\n", i); PRINTSTAT("Transmit rate: %d\n", ltv_ins(ctlr, WTyp_TxRate)); PRINTSTAT("Current Transmit rate: %d\n", ltv_ins(ctlr, WTyp_CurTxRate)); PRINTSTAT("Channel: %d\n", ltv_ins(ctlr, WTyp_Chan)); PRINTSTAT("AP density: %d\n", ltv_ins(ctlr, WTyp_ApDens)); PRINTSTAT("Promiscuous mode: %d\n", ltv_ins(ctlr, WTyp_Prom)); if(i == WPTypeAdHoc) PRINTSTAT("SSID name: %s\n", ltv_inname(ctlr, WTyp_NetName)); else { Wltv ltv; PRINTSTAT("Current name: %s\n", ltv_inname(ctlr, WTyp_CurName)); ltv.type = WTyp_BaseID; ltv.len = 4; if(w_inltv(ctlr, <v)) print("#l%d: unable to read base station mac addr\n", ether->ctlrno); l += snprint(p+l, READSTR-l, "Base station: %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", ltv.addr[0], ltv.addr[1], ltv.addr[2], ltv.addr[3], ltv.addr[4], ltv.addr[5]); } PRINTSTAT("Net name: %s\n", ltv_inname(ctlr, WTyp_WantName)); PRINTSTAT("Node name: %s\n", ltv_inname(ctlr, WTyp_NodeName)); if(ltv_ins(ctlr, WTyp_HasCrypt) == 0) PRINTSTR("WEP: not supported\n"); else { if(ltv_ins(ctlr, WTyp_Crypt) == 0) PRINTSTR("WEP: disabled\n"); else{ PRINTSTR("WEP: enabled\n"); k = ((ctlr->xclear)? "excluded": "included"); PRINTSTAT("Clear packets: %s\n", k); txid = ltv_ins(ctlr, WTyp_TxKey); PRINTSTAT("Transmit key id: %d\n", txid); } } iunlock(ctlr); PRINTSTAT("ntxuframes: %lud\n", ctlr->ntxuframes); PRINTSTAT("ntxmframes: %lud\n", ctlr->ntxmframes); PRINTSTAT("ntxfrags: %lud\n", ctlr->ntxfrags); PRINTSTAT("ntxubytes: %lud\n", ctlr->ntxubytes); PRINTSTAT("ntxmbytes: %lud\n", ctlr->ntxmbytes); PRINTSTAT("ntxdeferred: %lud\n", ctlr->ntxdeferred); PRINTSTAT("ntxsretries: %lud\n", ctlr->ntxsretries); PRINTSTAT("ntxmultiretries: %lud\n", ctlr->ntxmultiretries); PRINTSTAT("ntxretrylimit: %lud\n", ctlr->ntxretrylimit); PRINTSTAT("ntxdiscards: %lud\n", ctlr->ntxdiscards); PRINTSTAT("nrxuframes: %lud\n", ctlr->nrxuframes); PRINTSTAT("nrxmframes: %lud\n", ctlr->nrxmframes); PRINTSTAT("nrxfrags: %lud\n", ctlr->nrxfrags); PRINTSTAT("nrxubytes: %lud\n", ctlr->nrxubytes); PRINTSTAT("nrxmbytes: %lud\n", ctlr->nrxmbytes); PRINTSTAT("nrxfcserr: %lud\n", ctlr->nrxfcserr); PRINTSTAT("nrxdropnobuf: %lud\n", ctlr->nrxdropnobuf); PRINTSTAT("nrxdropnosa: %lud\n", ctlr->nrxdropnosa); PRINTSTAT("nrxcantdecrypt: %lud\n", ctlr->nrxcantdecrypt); PRINTSTAT("nrxmsgfrag: %lud\n", ctlr->nrxmsgfrag); PRINTSTAT("nrxmsgbadfrag: %lud\n", ctlr->nrxmsgbadfrag); USED(l); n = readstr(offset, a, n, p); free(p); return n;}#undef PRINTSTR#undef PRINTSTATintw_option(Ctlr* ctlr, char* buf, long n){ char *p; int i, r; WKey *key; Cmdbuf *cb; r = 0; cb = parsecmd(buf, n); if(cb->nf < 2) r = -1; else if(cistrcmp(cb->f[0], "essid") == 0){ if(cistrcmp(cb->f[1],"default") == 0) p = ""; else p = cb->f[1]; if(ctlr->ptype == WPTypeAdHoc){ memset(ctlr->netname, 0, sizeof(ctlr->netname)); strncpy(ctlr->netname, p, WNameLen); } else{ memset(ctlr->wantname, 0, sizeof(ctlr->wantname)); strncpy(ctlr->wantname, p, WNameLen); } } else if(cistrcmp(cb->f[0], "station") == 0){ memset(ctlr->nodename, 0, sizeof(ctlr->nodename)); strncpy(ctlr->nodename, cb->f[1], WNameLen); } else if(cistrcmp(cb->f[0], "channel") == 0){ if((i = atoi(cb->f[1])) >= 1 && i <= 16) ctlr->chan = i; else r = -1; } else if(cistrcmp(cb->f[0], "mode") == 0){ if(cistrcmp(cb->f[1], "managed") == 0) ctlr->ptype = WPTypeManaged; else if(cistrcmp(cb->f[1], "wds") == 0) ctlr->ptype = WPTypeWDS; else if(cistrcmp(cb->f[1], "adhoc") == 0) ctlr->ptype = WPTypeAdHoc; else if((i = atoi(cb->f[1])) >= 1 && i <= 3) ctlr->ptype = i; else r = -1; } else if(cistrcmp(cb->f[0], "ibss") == 0){ if(cistrcmp(cb->f[1], "on") == 0) ctlr->createibss = 1; else ctlr->createibss = 0; } else if(cistrcmp(cb->f[0], "crypt") == 0){ if(cistrcmp(cb->f[1], "off") == 0) ctlr->crypt = 0; else if(cistrcmp(cb->f[1], "on") == 0 && ctlr->hascrypt) ctlr->crypt = 1; else r = -1; } else if(cistrcmp(cb->f[0], "clear") == 0){ if(cistrcmp(cb->f[1], "on") == 0) ctlr->xclear = 0; else if(cistrcmp(cb->f[1], "off") == 0 && ctlr->hascrypt) ctlr->xclear = 1; else r = -1; } else if(cistrncmp(cb->f[0], "key", 3) == 0){ if((i = atoi(cb->f[0]+3)) >= 1 && i <= WNKeys){ ctlr->txkey = i-1; key = &ctlr->keys.keys[ctlr->txkey]; key->len = strlen(cb->f[1]); if(key->len > WKeyLen) key->len = WKeyLen; memset(key->dat, 0, sizeof(key->dat)); memmove(key->dat, cb->f[1], key->len); } else r = -1; } else if(cistrcmp(cb->f[0], "txkey") == 0){ if((i = atoi(cb->f[1])) >= 1 && i <= WNKeys) ctlr->txkey = i-1; else r = -1; } else if(cistrcmp(cb->f[0], "pm") == 0){ if(cistrcmp(cb->f[1], "off") == 0) ctlr->pmena = 0; else if(cistrcmp(cb->f[1], "on") == 0){ ctlr->pmena = 1; if(cb->nf == 3){ i = atoi(cb->f[2]); // check range here? what are the units? ctlr->pmwait = i; } } else r = -1; } else r = -2; free(cb); return r;}longw_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;}voidw_transmit(Ether* ether){ Ctlr* ctlr = ether->ctlr; if(ctlr == 0) return; ilock(ctlr); ctlr->ntxrq++; w_txstart(ether); iunlock(ctlr);}voidw_promiscuous(void* arg, int on){ Ether* ether = (Ether*)arg; Ctlr* ctlr = ether->ctlr; if(ctlr == nil) error("card not found"); if((ctlr->state & Attached) == 0) error("card not attached"); ilock(ctlr); ltv_outs(ctlr, WTyp_Prom, (on?1:0)); iunlock(ctlr);}voidw_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);}intwavelanreset(Ether* ether, Ctlr *ctlr){ Wltv ltv; iprint("wavelanreset, iob 0x%ux\n", ctlr->iob); w_intdis(ctlr); if(w_cmd(ctlr,WCmdIni,0)){ iprint("#l%d: init failed\n", ether->ctlrno); return -1; } w_intdis(ctlr); ltv_outs(ctlr, WTyp_Tick, 8); ctlr->chan = 0; ctlr->ptype = WDfltPType; ctlr->txkey = 0; ctlr->createibss = 0; ctlr->keys.len = sizeof(WKey)*WNKeys/2 + 1; ctlr->keys.type = WTyp_Keys; if(ctlr->hascrypt = ltv_ins(ctlr, WTyp_HasCrypt)) ctlr->crypt = 1; *ctlr->netname = *ctlr->wantname = 0; strcpy(ctlr->nodename, "Plan 9 STA"); ctlr->netname[WNameLen-1] = 0; ctlr->wantname[WNameLen-1] = 0; ctlr->nodename[WNameLen-1] =0; ltv.type = WTyp_Mac; ltv.len = 4; if(w_inltv(ctlr, <v)){ iprint("#l%d: unable to read mac addr\n", ether->ctlrno); return -1; } memmove(ether->ea, ltv.addr, Eaddrlen); if(ctlr->chan == 0) ctlr->chan = ltv_ins(ctlr, WTyp_Chan); ctlr->apdensity = WDfltApDens; ctlr->rtsthres = WDfltRtsThres; ctlr->txrate = WDfltTxRate; ctlr->maxlen = WMaxLen; ctlr->pmena = 0; ctlr->pmwait = 100; ctlr->signal = 1; ctlr->noise = 1; ctlr->state |= Power; // free old Ctlr struct if resetting after suspend if(ether->ctlr && ether->ctlr != ctlr) free(ether->ctlr); // link to ether ether->ctlr = ctlr; ether->mbps = 10; ether->attach = w_attach; ether->detach = w_detach; ether->interrupt = w_interrupt; ether->transmit = w_transmit; ether->ifstat = w_ifstat; ether->ctl = w_ctl; ether->power = w_power; ether->promiscuous = w_promiscuous; ether->multicast = w_multicast; ether->scanbs = w_scanbs; ether->arg = ether; DEBUG("#l%d: irq %lud port %lx type %s", ether->ctlrno, ether->intnum, ether->ports[0].port, ether->type); DEBUG(" %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux\n", ether->ea[0], ether->ea[1], ether->ea[2], ether->ea[3], ether->ea[4], ether->ea[5]); return 0;}char* wavenames[] = { "WaveLAN/IEEE", "TrueMobile 1150", "Instant Wireless ; Network PC CARD", "Instant Wireless Network PC Card", "Avaya Wireless PC Card", "AirLancer MC-11", nil,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -