## diffname pc/wavelan.c 1999/0623
## diff -e /dev/null /n/emeliedump/1999/0623/sys/src/brazil/pc/wavelan.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
extern Dev rootdevtab;
extern Dev consdevtab;
extern Dev envdevtab;
extern Dev pipedevtab;
extern Dev procdevtab;
extern Dev mntdevtab;
extern Dev srvdevtab;
extern Dev dupdevtab;
extern Dev rtcdevtab;
extern Dev ssldevtab;
extern Dev mntstatsdevtab;
extern Dev etherdevtab;
extern Dev ipdevtab;
extern Dev drawdevtab;
extern Dev mousedevtab;
extern Dev vgadevtab;
extern Dev scsidevtab;
extern Dev cddevtab;
extern Dev sddevtab;
extern Dev atadevtab;
extern Dev floppydevtab;
extern Dev audiodevtab;
extern Dev i82365devtab;
extern Dev lptdevtab;
extern Dev ns16552devtab;
extern Dev lmldevtab;
Dev* devtab[]={
&rootdevtab,
&consdevtab,
&envdevtab,
&pipedevtab,
&procdevtab,
&mntdevtab,
&srvdevtab,
&dupdevtab,
&rtcdevtab,
&ssldevtab,
&mntstatsdevtab,
ðerdevtab,
&ipdevtab,
&drawdevtab,
&mousedevtab,
&vgadevtab,
&scsidevtab,
&cddevtab,
&sddevtab,
&atadevtab,
&floppydevtab,
&audiodevtab,
&i82365devtab,
&lptdevtab,
&ns16552devtab,
&lmldevtab,
nil,
};
extern void ether2000link(void);
extern void ether2114xlink(void);
extern void ether589link(void);
extern void ether79c970link(void);
extern void ether8003link(void);
extern void ether82557link(void);
extern void etherelnk3link(void);
extern void etherwavelanlink(void);
extern void ethermediumlink(void);
void links(void){
ether2000link();
ether2114xlink();
ether589link();
ether79c970link();
ether8003link();
ether82557link();
etherelnk3link();
etherwavelanlink();
ethermediumlink();
}
extern PCArch archgeneric;
extern PCArch archmp;
PCArch* knownarch[] = {
&archgeneric,
&archmp,
nil,
};
extern SCSIdev scsibuslogicdev;
SCSIdev* scsidev[] = {
&scsibuslogicdev,
nil,
};
#define Image IMAGE
#include <draw.h>
#include <memdraw.h>
#include <cursor.h>
#include "screen.h"
extern VGAdev vgaark2000pvdev;
extern VGAdev vgaclgd542xdev;
extern VGAdev vgact65545dev;
extern VGAdev vgamach64xxdev;
extern VGAdev vgamga2164wdev;
extern VGAdev vgas3dev;
VGAdev* vgadev[] = {
&vgaark2000pvdev,
&vgaclgd542xdev,
&vgact65545dev,
&vgamach64xxdev,
&vgamga2164wdev,
&vgas3dev,
nil,
};
extern VGAcur vgaark2000pvcur;
extern VGAcur vgabt485cur;
extern VGAcur vgaclgd542xcur;
extern VGAcur vgact65545cur;
extern VGAcur vgamach64xxcur;
extern VGAcur vgamga2164wcur;
extern VGAcur vgargb524cur;
extern VGAcur vgas3cur;
extern VGAcur vgatvp3020cur;
extern VGAcur vgatvp3026cur;
VGAcur* vgacur[] = {
&vgaark2000pvcur,
&vgabt485cur,
&vgaclgd542xcur,
&vgact65545cur,
&vgamach64xxcur,
&vgamga2164wcur,
&vgargb524cur,
&vgas3cur,
&vgatvp3020cur,
&vgatvp3026cur,
nil,
};
#include "../ip/ip.h"
extern void ilinit(Fs*);
extern void tcpinit(Fs*);
extern void udpinit(Fs*);
extern void rudpinit(Fs*);
extern void ipifcinit(Fs*);
extern void icmpinit(Fs*);
extern void greinit(Fs*);
extern void ipmuxinit(Fs*);
void (*ipprotoinit[])(Fs*) = {
ilinit,
tcpinit,
udpinit,
rudpinit,
ipifcinit,
icmpinit,
greinit,
ipmuxinit,
nil,
};
int cpuserver = 0;
char* conffile = "wavelan";
ulong kerndate = KERNDATE;
.
## diffname pc/wavelan.c 2002/0606
## diff -e /n/emeliedump/1999/0623/sys/src/brazil/pc/wavelan.c /n/emeliedump/2002/0606/sys/src/9/pc/wavelan.c
166,168d
145,162c
if(ctlr->mmb){
rp = dat;
wp = &ctlr->mmb[reg];
while(ndat-- > 0)
*wp = *rp++;
}else
outss(ctlr->iob+reg, dat, ndat);
}
// w_... routines do not ilock the Ctlr and should
// be called locked.
void
w_intdis(Ctlr* ctlr)
{
csr_outs(ctlr, WR_IntEna, 0);
csr_ack(ctlr, 0xffff);
}
static void
w_intena(Ctlr* ctlr)
{
csr_outs(ctlr, WR_IntEna, WEvs);
}
int
w_cmd(Ctlr *ctlr, ushort cmd, ushort arg)
{
int i, rc;
for(i=0; i<WTmOut; i++)
if((csr_ins(ctlr, WR_Cmd)&WCmdBusy) == 0)
break;
if(i==WTmOut){
print("#l%d: issuing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_Cmd));
return -1;
}
csr_outs(ctlr, WR_Parm0, arg);
csr_outs(ctlr, WR_Cmd, cmd);
for(i=0; i<WTmOut; i++)
if(csr_ins(ctlr, WR_EvSts)&WCmdEv)
break;
if(i==WTmOut){
/*
* WCmdIni can take a really long time.
*/
enum { IniTmOut = 2000 };
for(i=0; i<IniTmOut; i++){
if(csr_ins(ctlr, WR_EvSts)&WCmdEv)
break;
microdelay(100);
}
if(i < IniTmOut)
if(0) print("#l%d: long cmd %.4ux %d\n", ctlr->ctlrno, cmd, i);
if(i == IniTmOut){
print("#l%d: execing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_EvSts));
return -1;
}
}
rc = csr_ins(ctlr, WR_Sts);
csr_ack(ctlr, WCmdEv);
if((rc&WCmdMsk) != (cmd&WCmdMsk)){
print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc);
return -1;
}
if(rc&WResSts){
/*
* Don't print; this happens on every WCmdAccWr for some reason.
*/
if(0) print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc);
return -1;
}
return 0;
}
static int
w_seek(Ctlr* ctlr, ushort id, ushort offset, int chan)
{
int i, rc;
static ushort sel[] = { WR_Sel0, WR_Sel1 };
static ushort off[] = { WR_Off0, WR_Off1 };
if (chan != 0 && chan != 1)
panic("wavelan: bad chan\n");
csr_outs(ctlr, sel[chan], id);
csr_outs(ctlr, off[chan], offset);
for (i=0; i<WTmOut; i++){
rc = csr_ins(ctlr, off[chan]);
if ((rc & (WBusyOff|WErrOff)) == 0)
return 0;
}
return -1;
}
int
w_inltv(Ctlr* ctlr, Wltv* ltv)
{
int len;
ushort code;
if (w_cmd(ctlr, WCmdAccRd, ltv->type)){
DEBUG("wavelan: access read failed\n");
return -1;
}
if (w_seek(ctlr,ltv->type,0,1)){
DEBUG("wavelan: seek failed\n");
return -1;
}
len = csr_ins(ctlr, WR_Data1);
if (len > ltv->len)
return -1;
ltv->len = len;
if ((code=csr_ins(ctlr, WR_Data1)) != ltv->type){
USED(code);
DEBUG("wavelan: type %x != code %x\n",ltv->type,code);
return -1;
}
if(ltv->len > 0)
csr_inss(ctlr, WR_Data1, <v->val, ltv->len-1);
return 0;
}
static void
w_outltv(Ctlr* ctlr, Wltv* ltv)
{
if(w_seek(ctlr,ltv->type, 0, 1))
return;
csr_outss(ctlr, WR_Data1, ltv, ltv->len+1);
w_cmd(ctlr, WCmdAccWr, ltv->type);
}
void
ltv_outs(Ctlr* ctlr, int type, ushort val)
{
Wltv ltv;
ltv.len = 2;
ltv.type = type;
ltv.val = val;
w_outltv(ctlr, <v);
}
int
ltv_ins(Ctlr* ctlr, int type)
{
Wltv ltv;
ltv.len = 2;
ltv.type = type;
ltv.val = 0;
if(w_inltv(ctlr, <v))
return -1;
return ltv.val;
}
static void
ltv_outstr(Ctlr* ctlr, int type, char* val)
{
Wltv ltv;
int len;
len = strlen(val);
if(len > sizeof(ltv.s))
len = sizeof(ltv.s);
memset(<v, 0, sizeof(ltv));
ltv.len = (sizeof(ltv.type)+sizeof(ltv.slen)+sizeof(ltv.s))/2;
ltv.type = type;
// This should be ltv.slen = len; according to Axel Belinfante
ltv.slen = len;
strncpy(ltv.s, val, len);
w_outltv(ctlr, <v);
}
static char Unkname[] = "who knows";
static char Nilname[] = "card does not tell";
static char*
ltv_inname(Ctlr* ctlr, int type)
{
static Wltv ltv;
int len;
memset(<v,0,sizeof(ltv));
ltv.len = WNameLen/2+2;
ltv.type = type;
if (w_inltv(ctlr, <v))
return Unkname;
len = ltv.slen;
if(len == 0 || ltv.s[0] == 0)
return Nilname;
if(len >= sizeof ltv.s)
len = sizeof ltv.s - 1;
ltv.s[len] = '\0';
return ltv.s;
}
static int
w_read(Ctlr* ctlr, int type, int off, void* buf, ulong len)
{
if (w_seek(ctlr, type, off, 1)){
DEBUG("wavelan: w_read: seek failed");
return 0;
}
csr_inss(ctlr, WR_Data1, buf, len/2);
return len;
}
static int
w_write(Ctlr* ctlr, int type, int off, void* buf, ulong len)
{
int tries;
for (tries=0; tries < WTmOut; tries++){
if (w_seek(ctlr, type, off, 0)){
DEBUG("wavelan: w_write: seek failed\n");
return 0;
}
csr_outss(ctlr, WR_Data0, buf, len/2);
csr_outs(ctlr, WR_Data0, 0xdead);
csr_outs(ctlr, WR_Data0, 0xbeef);
if (w_seek(ctlr, type, off + len, 0)){
DEBUG("wavelan: write seek failed\n");
return 0;
}
if (csr_ins(ctlr, WR_Data0) == 0xdead)
if (csr_ins(ctlr, WR_Data0) == 0xbeef)
return len;
DEBUG("wavelan: Hermes bug byte.\n");
return 0;
}
DEBUG("wavelan: tx timeout\n");
return 0;
}
static int
w_alloc(Ctlr* ctlr, int len)
{
int rc;
int i,j;
if (w_cmd(ctlr, WCmdMalloc, len)==0)
for (i = 0; i<WTmOut; i++)
if (csr_ins(ctlr, WR_EvSts) & WAllocEv){
csr_ack(ctlr, WAllocEv);
rc=csr_ins(ctlr, WR_Alloc);
if (w_seek(ctlr, rc, 0, 0))
return -1;
len = len/2;
for (j=0; j<len; j++)
csr_outs(ctlr, WR_Data0, 0);
return rc;
}
return -1;
}
static int
w_enable(Ether* ether)
{
Wltv ltv;
Ctlr* ctlr = (Ctlr*) ether->ctlr;
if (!ctlr)
return -1;
w_intdis(ctlr);
w_cmd(ctlr, WCmdDis, 0);
w_intdis(ctlr);
if(w_cmd(ctlr, WCmdIni, 0))
return -1;
w_intdis(ctlr);
ltv_outs(ctlr, WTyp_Tick, 8);
ltv_outs(ctlr, WTyp_MaxLen, ctlr->maxlen);
ltv_outs(ctlr, WTyp_Ptype, ctlr->ptype);
ltv_outs(ctlr, WTyp_CreateIBSS, ctlr->createibss);
ltv_outs(ctlr, WTyp_RtsThres, ctlr->rtsthres);
ltv_outs(ctlr, WTyp_TxRate, ctlr->txrate);
ltv_outs(ctlr, WTyp_ApDens, ctlr->apdensity);
ltv_outs(ctlr, WTyp_PMWait, ctlr->pmwait);
ltv_outs(ctlr, WTyp_PM, ctlr->pmena);
if (*ctlr->netname)
ltv_outstr(ctlr, WTyp_NetName, ctlr->netname);
if (*ctlr->wantname)
ltv_outstr(ctlr, WTyp_WantName, ctlr->wantname);
ltv_outs(ctlr, WTyp_Chan, ctlr->chan);
if (*ctlr->nodename)
ltv_outstr(ctlr, WTyp_NodeName, ctlr->nodename);
ltv.len = 4;
ltv.type = WTyp_Mac;
memmove(ltv.addr, ether->ea, Eaddrlen);
w_outltv(ctlr, <v);
ltv_outs(ctlr, WTyp_Prom, (ether->prom?1:0));
if (ctlr->hascrypt){
ltv_outs(ctlr, WTyp_Crypt, ctlr->crypt);
ltv_outs(ctlr, WTyp_TxKey, ctlr->txkey);
w_outltv(ctlr, &ctlr->keys);
ltv_outs(ctlr, WTyp_XClear, ctlr->xclear);
}
// BUG: set multicast addresses
if (w_cmd(ctlr, WCmdEna, 0)){
DEBUG("wavelan: Enable failed");
return -1;
}
ctlr->txdid = w_alloc(ctlr, 1518 + sizeof(WFrame) + 8);
ctlr->txmid = w_alloc(ctlr, 1518 + sizeof(WFrame) + 8);
if (ctlr->txdid == -1 || ctlr->txmid == -1)
DEBUG("wavelan: alloc failed");
ctlr->txbusy = 0;
w_intena(ctlr);
return 0;
}
static void
w_rxdone(Ether* ether)
{
Ctlr* ctlr = (Ctlr*) ether->ctlr;
int len, sp;
WFrame f;
Block* bp=0;
Etherpkt* ep;
sp = csr_ins(ctlr, WR_RXId);
len = w_read(ctlr, sp, 0, &f, sizeof(f));
if (len == 0){
DEBUG("wavelan: read frame error\n");
goto rxerror;
}
if (f.sts&WF_Err){
goto rxerror;
}
switch(f.sts){
case WF_1042:
case WF_Tunnel:
case WF_WMP:
len = f.dlen + WSnapHdrLen;
bp = iallocb(ETHERHDRSIZE + len + 2);
if (!bp)
goto rxerror;
ep = (Etherpkt*) bp->wp;
memmove(ep->d, f.addr1, Eaddrlen);
memmove(ep->s, f.addr2, Eaddrlen);
memmove(ep->type,&f.type,2);
bp->wp += ETHERHDRSIZE;
if (w_read(ctlr, sp, WF_802_11_Off, bp->wp, len+2) == 0){
DEBUG("wavelan: read 802.11 error\n");
goto rxerror;
}
bp->wp = bp->rp+(ETHERHDRSIZE+f.dlen);
break;
default:
len = ETHERHDRSIZE + f.dlen + 2;
bp = iallocb(len);
if (!bp)
goto rxerror;
if (w_read(ctlr, sp, WF_802_3_Off, bp->wp, len) == 0){
DEBUG("wavelan: read 800.3 error\n");
goto rxerror;
}
bp->wp += len;
}
ctlr->nrx++;
etheriq(ether,bp,1);
ctlr->signal = ((ctlr->signal*15)+((f.qinfo>>8) & 0xFF))/16;
ctlr->noise = ((ctlr->noise*15)+(f.qinfo & 0xFF))/16;
return;
rxerror:
freeb(bp);
ctlr->nrxerr++;
}
static void
w_txstart(Ether* ether)
{
Etherpkt *pkt;
Ctlr *ctlr;
Block *bp;
int len, off;
if((ctlr = ether->ctlr) == nil || ctlr->attached == 0 || ctlr->txbusy)
return;
if((bp = qget(ether->oq)) == nil)
return;
pkt = (Etherpkt*)bp->rp;
//
// If the packet header type field is > 1500 it is an IP or
// ARP datagram, otherwise it is an 802.3 packet. See RFC1042.
//
memset(&ctlr->txf, 0, sizeof(ctlr->txf));
if(((pkt->type[0]<<8)|pkt->type[1]) > 1500){
ctlr->txf.framectl = WF_Data;
memmove(ctlr->txf.addr1, pkt->d, Eaddrlen);
memmove(ctlr->txf.addr2, pkt->s, Eaddrlen);
memmove(ctlr->txf.dstaddr, pkt->d, Eaddrlen);
memmove(ctlr->txf.srcaddr, pkt->s, Eaddrlen);
memmove(&ctlr->txf.type, pkt->type, 2);
bp->rp += ETHERHDRSIZE;
len = BLEN(bp);
off = WF_802_11_Off;
ctlr->txf.dlen = len+ETHERHDRSIZE-WSnapHdrLen;
hnputs((uchar*)&ctlr->txf.dat[0], WSnap0);
hnputs((uchar*)&ctlr->txf.dat[1], WSnap1);
hnputs((uchar*)&ctlr->txf.len, len+ETHERHDRSIZE-WSnapHdrLen);
}
else{
len = BLEN(bp);
off = WF_802_3_Off;
ctlr->txf.dlen = len;
}
w_write(ctlr, ctlr->txdid, 0, &ctlr->txf, sizeof(ctlr->txf));
w_write(ctlr, ctlr->txdid, off, bp->rp, len+2);
if(w_cmd(ctlr, WCmdReclaim|WCmdTx, ctlr->txdid)){
DEBUG("wavelan: transmit failed\n");
ctlr->ntxerr++;
}
else{
ctlr->txbusy = 1;
ctlr->txtmout = 2;
}
freeb(bp);
}
static void
w_txdone(Ctlr* ctlr, int sts)
{
ctlr->txbusy = 0;
ctlr->txtmout = 0;
if (sts & WTxErrEv)
ctlr->ntxerr++;
else
ctlr->ntx++;
}
static int
w_stats(Ctlr* ctlr)
{
int i, rc, sp;
Wltv ltv;
ulong* p = (ulong*)&ctlr->WStats;
ulong* pend = (ulong*)&ctlr->end;
sp = csr_ins(ctlr, WR_InfoId);
ltv.len = ltv.type = 0;
w_read(ctlr, sp, 0, <v, 4);
if (ltv.type == WTyp_Stats){
ltv.len--;
for (i = 0; i < ltv.len && p < pend; i++){
rc = csr_ins(ctlr, WR_Data1);
if (rc > 0xf000)
rc = ~rc & 0xffff;
p[i] += rc;
}
return 0;
}
return -1;
}
static void
w_intr(Ether *ether)
{
int rc, txid;
Ctlr* ctlr = (Ctlr*) ether->ctlr;
if (ctlr->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_stats(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 void
w_timer(void* arg)
{
Ether* ether = (Ether*) arg;
Ctlr* ctlr = (Ctlr*)ether->ctlr;
for(;;){
tsleep(&ctlr->timer, return0, 0, 50);
ctlr = (Ctlr*)ether->ctlr;
if (ctlr == 0)
break;
if (ctlr->attached == 0)
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, WCmdAskStats, WTyp_Stats);
}
iunlock(ctlr);
}
pexit("terminated",0);
}
void
w_multicast(void*, uchar*, int)
{
// BUG: to be added.
}
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->attached == 0){
ilock(ctlr);
rc = w_enable(ether);
iunlock(ctlr);
if(rc == 0){
ctlr->attached = 1;
kproc(name, w_timer, ether);
} else
print("#l%d: enable failed\n",ether->ctlrno);
}
}
#define PRINTSTAT(fmt,val) l += snprint(p+l, READSTR-l, (fmt), (val))
#define PRINTSTR(fmt) l += snprint(p+l, READSTR-l, (fmt))
long
w_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->attached) ? "attached" : "not attached");
PRINTSTAT("Card %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 == 3)
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 PRINTSTAT
int
w_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 == 3){
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;
}
long
w_ctl(Ether* ether, void* buf, long n)
{
Ctlr *ctlr;
if((ctlr = ether->ctlr) == nil)
error(Enonexist);
if(ctlr->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;
}
void
w_transmit(Ether* ether)
{
Ctlr* ctlr = ether->ctlr;
if (ctlr == 0)
return;
ilock(ctlr);
ctlr->ntxrq++;
w_txstart(ether);
iunlock(ctlr);
}
void
w_promiscuous(void* arg, int on)
{
Ether* ether = (Ether*)arg;
Ctlr* ctlr = ether->ctlr;
if (ctlr == nil)
error("card not found");
if (ctlr->attached == 0)
error("card not attached");
ilock(ctlr);
ltv_outs(ctlr, WTyp_Prom, (on?1:0));
iunlock(ctlr);
}
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);
}
int
wavelanreset(Ether* ether, Ctlr *ctlr)
{
Wltv ltv;
w_intdis(ctlr);
if (w_cmd(ctlr,WCmdIni,0)){
print("#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)){
print("#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;
// link to ether
ether->ctlr = ctlr;
ether->mbps = 10;
ether->attach = w_attach;
ether->interrupt = w_interrupt;
ether->transmit = w_transmit;
ether->ifstat = w_ifstat;
ether->ctl = w_ctl;
ether->promiscuous = w_promiscuous;
ether->multicast = w_multicast;
ether->arg = ether;
// DEBUG("#l%d: irq %ld port %lx type %s",
// ether->ctlrno, ether->irq, ether->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",
.
121,143c
static void
csr_outss(Ctlr *ctlr, int reg, void *dat, int ndat)
{
ushort *rp, *wp;
.
100,119c
if(ctlr->mmb){
rp = &ctlr->mmb[reg];
wp = dat;
while(ndat-- > 0)
*wp++ = *rp;
}else
inss(ctlr->iob+reg, dat, ndat);
}
.
94,98c
static void
csr_inss(Ctlr *ctlr, int reg, void *dat, int ndat)
{
ushort *rp, *wp;
.
86,92c
static void
csr_ack(Ctlr *ctlr, int ev)
{
csr_outs(ctlr, WR_EvAck, ev);
}
.
65,83c
ushort
csr_ins(Ctlr *ctlr, int reg)
{
if(ctlr->mmb)
return ctlr->mmb[reg];
else
return ins(ctlr->iob+reg);
.
9,63c
/*
* When we're using a PCI device and memory-mapped I/O,
* the registers are spaced out as though each takes 32 bits,
* even though they are only 16-bit registers. Thus,
* ctlr->mmb[reg] is the right way to access register reg,
* even though a priori you'd expect to use ctlr->mmb[reg/2].
*/
void
csr_outs(Ctlr *ctlr, int reg, ushort arg)
{
if(ctlr->mmb)
ctlr->mmb[reg] = arg;
else
outs(ctlr->iob+reg, arg);
}
.
7a
#include "../port/netif.h"
#include "etherif.h"
#include "wavelan.h"
.
0a
/*
Lucent Wavelan IEEE 802.11 pcmcia.
There is almost no documentation for the card.
the driver is done using both the FreeBSD, Linux and
original Plan 9 drivers as `documentation'.
Has been used with the card plugged in during all up time.
no cards removals/insertions yet.
For known BUGS see the comments below. Besides,
the driver keeps interrupts disabled for just too
long. When it gets robust, locks should be revisited.
BUGS: check endian, alignment and mem/io issues;
multicast;
receive watchdog interrupts.
TODO: automatic power management;
improve locking.
*/
.
## diffname pc/wavelan.c 2002/0615
## diff -e /n/emeliedump/2002/0606/sys/src/9/pc/wavelan.c /n/emeliedump/2002/0615/sys/src/9/pc/wavelan.c
1051a
ether->detach = w_detach;
.
690a
void
w_detach(Ether* ether)
{
Ctlr* ctlr;
char name[64];
if (ether->ctlr == 0)
return;
snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno);
ctlr = (Ctlr*) ether->ctlr;
if (ctlr->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->attached = 0;
iunlock(ctlr);
}
}
.
658c
poperror();
pexit("terminated", 0);
.
611a
if (waserror()){
print("timerporc dying\n");
pexit("aaargh!", 0);
}
ctlr->timerproc = up;
.
## diffname pc/wavelan.c 2002/0616
## diff -e /n/emeliedump/2002/0615/sys/src/9/pc/wavelan.c /n/emeliedump/2002/0616/sys/src/9/pc/wavelan.c
1077a
// free old Ctlr struct if resetting after suspend
if (ether->ctlr)
free(ether->ctlr);
.
## diffname pc/wavelan.c 2002/0618
## diff -e /n/emeliedump/2002/0616/sys/src/9/pc/wavelan.c /n/emeliedump/2002/0618/sys/src/9/pc/wavelan.c
1090a
ether->power = w_power;
.
1009c
if ((ctlr->state & Attached) == 0)
.
970c
if((ctlr->state & Attached) == 0)
.
764a
k = ((ctlr->state & Power) ? "on" : "off");
PRINTSTAT("PCardower %s", k);
.
763c
k = ((ctlr->state & Attached) ? "attached" : "not attached");
.
720a
void
w_power(Ether* ether, int on)
{
Ctlr *ctlr;
ctlr = (Ctlr*) ether->ctlr;
ilock(ctlr);
if (on){
if ((ctlr->state & Power) == 0){
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);
}
.
716c
ctlr->state &= ~Attached;
.
708c
if (ctlr->state & Attached){
.
690c
ctlr->state |= Attached;
.
685c
if ((ctlr->state & Attached) == 0){
.
663d
622c
if ((ctlr->state & Attached) == 0)
.
612,615d
561c
if ((ctlr->state & Power) == 0)
return;
if ((ctlr->state & Attached) == 0){
.
474c
if((ctlr = ether->ctlr) == nil || (ctlr->state & (Attached|Power)) == 0 || ctlr->txbusy)
.
## diffname pc/wavelan.c 2002/0619
## diff -e /n/emeliedump/2002/0618/sys/src/9/pc/wavelan.c /n/emeliedump/2002/0619/sys/src/9/pc/wavelan.c
1102c
if(ether->ctlr)
.
1099a
ctlr->state |= Power;
.
1090c
if(ctlr->chan == 0)
.
1083c
if(w_inltv(ctlr, <v)){
.
1059c
if(w_cmd(ctlr,WCmdIni,0)){
.
1045c
if(ctlr == 0)
.
1032c
if((ctlr->state & Attached) == 0)
.
1030c
if(ctlr == nil)
.
1015c
if(ctlr == 0)
.
951c
if(key->len > WKeyLen)
.
889c
if(cistrcmp(cb->f[1],"default") == 0)
.
834c
if(ltv_ins(ctlr, WTyp_Crypt) == 0)
.
831c
if(ltv_ins(ctlr, WTyp_HasCrypt) == 0)
.
824c
if(w_inltv(ctlr, <v))
.
796c
else if(SEEKEYS == 0)
.
794c
if(ctlr->keys.keys[i].len == 0)
.
791c
if(ctlr->hascrypt){
.
733,734c
if(ctlr->state & Power){
if(ctlr->state & Attached)
.
726,728c
if(on){
if((ctlr->state & Power) == 0){
if(ctlr->state & Attached)
.
709,710c
if(ctlr->timerproc){
if(!postnote(ctlr->timerproc, 1, "kill", NExit))
.
706c
if(ctlr->state & Attached){
.
701c
if(ether->ctlr == 0)
.
683c
if((ctlr->state & Attached) == 0){
.
678c
if(ether->ctlr == 0)
.
656,657c
if((ctlr->ticks % 120) == 0)
if(ctlr->txbusy == 0)
.
651c
if(w_enable(ether)){
.
647,648c
if((ctlr->ticks % 10) == 0) {
if(ctlr->txtmout && --ctlr->txtmout == 0){
.
642c
if(csr_ins(ctlr, WR_EvSts)&WEvs){
.
621c
if((ctlr->state & Attached) == 0)
.
619c
if(ctlr == 0)
.
598c
if(rc & WIDropEv){
.
594c
if(rc & WTxErrEv){
.
589c
if(rc & WInfoEv){
.
584,585c
if(txid == ctlr->txdid){
if((rc & WTXEv) == 0)
.
580c
if(rc & WAllocEv){
.
576c
if(rc & WTXEv){
.
572c
if(rc & WRXEv){
.
564c
if((ctlr->state & Attached) == 0){
.
561c
if((ctlr->state & Power) == 0)
.
546c
if(rc > 0xf000)
.
542c
if(ltv.type == WTyp_Stats){
.
525c
if(sts & WTxErrEv)
.
448c
if(w_read(ctlr, sp, WF_802_3_Off, bp->wp, len) == 0){
.
446c
if(!bp)
.
437c
if(w_read(ctlr, sp, WF_802_11_Off, bp->wp, len+2) == 0){
.
430c
if(!bp)
.
421c
if(f.sts&WF_Err){
.
417c
if(len == 0){
.
399c
if(ctlr->txdid == -1 || ctlr->txmid == -1)
.
393c
if(w_cmd(ctlr, WCmdEna, 0)){
.
384c
if(ctlr->hascrypt){
.
375c
if(*ctlr->nodename)
.
372c
if(*ctlr->wantname)
.
370c
if(*ctlr->netname)
.
351c
if(!ctlr)
.
335c
if(w_seek(ctlr, rc, 0, 0))
.
332c
if(csr_ins(ctlr, WR_EvSts) & WAllocEv){
.
330c
if(w_cmd(ctlr, WCmdMalloc, len)==0)
.
314,315c
if(csr_ins(ctlr, WR_Data0) == 0xdead)
if(csr_ins(ctlr, WR_Data0) == 0xbeef)
.
310c
if(w_seek(ctlr, type, off + len, 0)){
.
301c
if(w_seek(ctlr, type, off, 0)){
.
286c
if(w_seek(ctlr, type, off, 1)){
.
272c
if(w_inltv(ctlr, <v))
.
196c
if((code=csr_ins(ctlr, WR_Data1)) != ltv->type){
.
193c
if(len > ltv->len)
.
188c
if(w_seek(ctlr,ltv->type,0,1)){
.
184c
if(w_cmd(ctlr, WCmdAccRd, ltv->type)){
.
172c
if((rc & (WBusyOff|WErrOff)) == 0)
.
166c
if(chan != 0 && chan != 1)
.
## diffname pc/wavelan.c 2002/0626
## diff -e /n/emeliedump/2002/0619/sys/src/9/pc/wavelan.c /n/emeliedump/2002/0626/sys/src/9/pc/wavelan.c
1120,1124c
DEBUG("#l%d: intnum %ld port %lx type %s",
ether->ctlrno, ether->intnum, ether->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]);
.
1103c
if(ether->ctlr && ether->ctlr != ctlr)
.
1084c
iprint("#l%d: unable to read mac addr\n",
.
1060c
iprint("#l%d: init failed\n", ether->ctlrno);
.
1057a
iprint("wavelanreset, iob 0x%ux\n", ctlr->iob);
.
727a
if (wavelanreset(ether, ctlr) < 0){
iprint("w_power: reset failed\n");
iunlock(ctlr);
w_detach(ether);
free(ctlr);
return;
}
.
725a
iprint("w_power %d\n", on);
.
716a
ether->ctlr = nil;
.
701c
if(ether->ctlr == nil)
.
621c
if((ctlr->state & (Attached|Power)) != (Attached|Power))
.
474c
if((ctlr = ether->ctlr) == nil || (ctlr->state & (Attached|Power)) != (Attached|Power) || ctlr->txbusy)
.
## diffname pc/wavelan.c 2002/0703
## diff -e /n/emeliedump/2002/0626/sys/src/9/pc/wavelan.c /n/emeliedump/2002/0703/sys/src/9/pc/wavelan.c
1130,1131c
DEBUG("#l%d: irq %ld port %lx type %s",
ether->ctlrno, ether->irq, ether->port, ether->type);
.
## diffname pc/wavelan.c 2002/0919
## diff -e /n/emeliedump/2002/0703/sys/src/9/pc/wavelan.c /n/emeliedump/2002/0919/sys/src/9/pc/wavelan.c
1142a
"Avaya Wireless PC Card",
"AirLancer MC-11",
.
## diffname pc/wavelan.c 2002/1015
## diff -e /n/emeliedump/2002/0919/sys/src/9/pc/wavelan.c /n/emeliedump/2002/1015/sys/src/9/pc/wavelan.c
1147d
1142a
"Instant Wireless Network PC Card",
.
## diffname pc/wavelan.c 2002/1231
## diff -e /n/emeliedump/2002/1015/sys/src/9/pc/wavelan.c /n/emeliedump/2002/1231/sys/src/9/pc/wavelan.c
796c
PRINTSTAT(", power %s", k);
.
## diffname pc/wavelan.c 2003/0116
## diff -e /n/emeliedump/2002/1231/sys/src/9/pc/wavelan.c /n/emeliedump/2003/0116/sys/src/9/pc/wavelan.c
902c
if(ctlr->ptype == WPTypeAdHoc){
.
895c
if(cistrcmp(cb->f[0], "scan") == 0){
w_cmd(ctlr, WCmdEnquire, WTyp_Scan);
}
else if(cb->nf < 2)
.
852a
if(ctlr->nwscan){
for(i = 0; i < ctlr->nwscan; i++)
PRINTSTAT("ws: %4.4ux\n", ctlr->wscan[i]);
ctlr->nwscan = 0;
}
.
826c
if(i == WPTypeAdHoc)
.
774c
p = malloc(2*READSTR);
.
658c
w_cmd(ctlr, WCmdEnquire, WTyp_Stats);
.
591c
w_info(ctlr);
.
551a
print("got type %d\n", ltv.len);
.
550a
case WTyp_Scan:
print("calling w_scan %d\n", ltv.len);
w_scan(ctlr, ltv.len);
return 0;
.
542,549c
ltv.len--;
switch(ltv.type){
case WTyp_Stats:
w_stats(ctlr, ltv.len);
.
538a
for (i = 0; i < len && p < pend; i++){
rc = csr_ins(ctlr, WR_Data1);
if(rc > 0xf000)
rc = ~rc & 0xffff;
p[i] += rc;
}
}
static void
w_scan(Ctlr* ctlr, int len)
{
int i;
for (i = 0; i < len && i < nelem(ctlr->wscan); i++)
ctlr->wscan[i] = csr_ins(ctlr, WR_Data1);
ctlr->nwscan = i;
}
static int
w_info(Ctlr* ctlr)
{
int sp;
Wltv ltv;
.
534,535c
int i, rc;
.
531,532c
static void
w_stats(Ctlr* ctlr, int len)
.
## diffname pc/wavelan.c 2003/0117
## diff -e /n/emeliedump/2003/0116/sys/src/9/pc/wavelan.c /n/emeliedump/2003/0117/sys/src/9/pc/wavelan.c
1115c
ctlr->crypt = 0;
.
924,927c
if(cb->nf < 2)
.
666,669c
// if(csr_ins(ctlr, WR_EvSts)&WEvs){
// ctlr->tickintr++;
// w_intr(ether);
// }
.
595a
print("intr %ux\n", rc);
.
575c
print("got type %d\n", ltv.type);
.
384c
if(ctlr->hascrypt && ctlr->crypt){
.
## diffname pc/wavelan.c 2003/0118
## diff -e /n/emeliedump/2003/0117/sys/src/9/pc/wavelan.c /n/emeliedump/2003/0118/sys/src/9/pc/wavelan.c
1157a
ether->scanbs = w_scanbs;
.
1113c
ctlr->crypt = 1;
.
878,882d
799c
p = malloc(READSTR);
.
683a
if(ctlr->scanticks > 0)
if((ctlr->ticks % ctlr->scanticks) == 0)
if(ctlr->txbusy == 0)
w_cmd(ctlr, WCmdEnquire, WTyp_Scan);
.
667,670c
if(csr_ins(ctlr, WR_EvSts)&WEvs){
ctlr->tickintr++;
w_intr(ether);
}
.
642c
tsleep(&ctlr->timer, return0, 0, MSperTick);
.
616c
w_info(ether, ctlr);
.
596d
579a
w_scanbs(void *a, uint secs)
{
Ether *ether = a;
Ctlr* ctlr = (Ctlr*) ether->ctlr;
ctlr->scanticks = secs*(1000/MSperTick);
}
static void
.
578a
/* set scanning interval */
.
575d
571,572c
w_scaninfo(ether, ctlr, ltv.len);
.
557c
w_info(Ether *ether, Ctlr* ctlr)
.
551,553c
for (i = 0; i < len ; i++)
ctlr->scanbuf[i] = csr_ins(ctlr, WR_Data1);
len *= 2;
i = ether->scan;
ep = ðer->f[Ntypes];
for(fp = ether->f; fp < ep && i > 0; fp++){
f = *fp;
if(f == nil || f->scan == 0)
continue;
bp = iallocb(2048);
if(bp == nil)
break;
for(j = 0; j < len/(2*25); j++){
wsp = (WScan*)(&ctlr->scanbuf[j*25]);
if(wsp->ssid_len > 32)
wsp->ssid_len = 32;
bp->wp += snprint((char*)bp->wp, 2048,
"ssid=%.*s;bssid=%E;signal=%d;noise=%d;chan=%d%s\n",
wsp->ssid_len, wsp->ssid, wsp->bssid, wsp->signal,
wsp->noise, wsp->chan, (wsp->capinfo&(1<<4))?";wep":"");
}
qpass(f->in, bp);
i--;
}
.
549c
int i, j;
Netfile **ep, *f, **fp;
Block *bp;
WScan *wsp;
.
547c
w_scaninfo(Ether* ether, Ctlr *ctlr, int len)
.
545a
/* send the base station scan info to any readers */
.
530a
/* save the stats info in the ctlr struct */
.
30a
enum
{
MSperTick= 50, /* ms between ticks of kproc */
};
.
## diffname pc/wavelan.c 2003/0301
## diff -e /n/emeliedump/2003/0118/sys/src/9/pc/wavelan.c /n/emeliedump/2003/0301/sys/src/9/pc/wavelan.c
1200c
DEBUG("#l%d: irq %d port %lx type %s",
.
## diffname pc/wavelan.c 2003/0302
## diff -e /n/emeliedump/2003/0301/sys/src/9/pc/wavelan.c /n/emeliedump/2003/0302/sys/src/9/pc/wavelan.c
586a
free(scanbuf);
.
579c
bp->wp = (uchar*)seprint((char*)bp->wp, (char*)bp->lim,
.
575,576c
for(j = 0; j < len; j++){
wsp = (WScan*)(&scanbuf[j*25]);
.
572c
bp = iallocb(100*len);
.
564c
len /= 25;
.
562c
scanbuf[i] = csr_ins(ctlr, WR_Data1);
.
560a
scanbuf = malloc(len*2);
if(scanbuf == nil)
return;
.
559a
ushort *scanbuf;
.
## diffname pc/wavelan.c 2003/0304
## diff -e /n/emeliedump/2003/0302/sys/src/9/pc/wavelan.c /n/emeliedump/2003/0304/sys/src/9/pc/wavelan.c
591a
out:
.
569a
if(len == 0)
goto out;
.
568a
/* calculate number of samples */
.
## diffname pc/wavelan.c 2003/0407
## diff -e /n/emeliedump/2003/0304/sys/src/9/pc/wavelan.c /n/emeliedump/2003/0407/sys/src/9/pc/wavelan.c
693c
tsleep(&up->sleep, return0, 0, MSperTick);
.
|