⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wavelan.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
		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, &ltv))			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, &ltv)){		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 + -