etheriwl: work towards supporting other cards than 5300, gather channel information
This commit is contained in:
parent
ab6a2eb0b6
commit
3a697585f0
3 changed files with 202 additions and 68 deletions
|
@ -222,19 +222,6 @@ enum {
|
||||||
SchedTransTblOff5000 = 0x7e0,
|
SchedTransTblOff5000 = 0x7e0,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* controller types */
|
|
||||||
enum {
|
|
||||||
Type4965 = 0,
|
|
||||||
Type5300 = 2,
|
|
||||||
Type5350 = 3,
|
|
||||||
Type5150 = 4,
|
|
||||||
Type5100 = 5,
|
|
||||||
Type1000 = 6,
|
|
||||||
Type6000 = 7,
|
|
||||||
Type6050 = 8,
|
|
||||||
Type6005 = 11,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct FWInfo FWInfo;
|
typedef struct FWInfo FWInfo;
|
||||||
typedef struct FWImage FWImage;
|
typedef struct FWImage FWImage;
|
||||||
typedef struct FWSect FWSect;
|
typedef struct FWSect FWSect;
|
||||||
|
@ -244,6 +231,8 @@ typedef struct RXQ RXQ;
|
||||||
|
|
||||||
typedef struct Ctlr Ctlr;
|
typedef struct Ctlr Ctlr;
|
||||||
|
|
||||||
|
typedef struct Ctlrtype Ctlrtype;
|
||||||
|
|
||||||
struct FWSect
|
struct FWSect
|
||||||
{
|
{
|
||||||
uchar *data;
|
uchar *data;
|
||||||
|
@ -347,6 +336,54 @@ struct Ctlr {
|
||||||
FWImage *fw;
|
FWImage *fw;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* controller types */
|
||||||
|
enum {
|
||||||
|
Type4965 = 0,
|
||||||
|
Type5300 = 2,
|
||||||
|
Type5350 = 3,
|
||||||
|
Type5150 = 4,
|
||||||
|
Type5100 = 5,
|
||||||
|
Type1000 = 6,
|
||||||
|
Type6000 = 7,
|
||||||
|
Type6050 = 8,
|
||||||
|
Type6005 = 11,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ctlrtype
|
||||||
|
{
|
||||||
|
char *fwname;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Ctlrtype ctlrtype[16] = {
|
||||||
|
[Type4965] {
|
||||||
|
.fwname = "iwn-4965",
|
||||||
|
},
|
||||||
|
[Type5300] {
|
||||||
|
.fwname = "iwn-5000",
|
||||||
|
},
|
||||||
|
[Type5350] {
|
||||||
|
.fwname = "iwn-5000",
|
||||||
|
},
|
||||||
|
[Type5150] {
|
||||||
|
.fwname = "iwn-5150",
|
||||||
|
},
|
||||||
|
[Type5100] {
|
||||||
|
.fwname = "iwn-5000",
|
||||||
|
},
|
||||||
|
[Type1000] {
|
||||||
|
.fwname = "iwn-1000",
|
||||||
|
},
|
||||||
|
[Type6000] {
|
||||||
|
.fwname = "iwn-6000",
|
||||||
|
},
|
||||||
|
[Type6050] {
|
||||||
|
.fwname = "iwn-6050",
|
||||||
|
},
|
||||||
|
[Type6005] {
|
||||||
|
.fwname = "iwn-6005",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
#define csr32r(c, r) (*((c)->nic+((r)/4)))
|
#define csr32r(c, r) (*((c)->nic+((r)/4)))
|
||||||
#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
|
#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
|
||||||
|
|
||||||
|
@ -619,23 +656,42 @@ iwlinit(Ether *edev)
|
||||||
eepromunlock(ctlr);
|
eepromunlock(ctlr);
|
||||||
goto Err;
|
goto Err;
|
||||||
}
|
}
|
||||||
if((err = eepromread(ctlr, b, 2, 0x048)) != nil){
|
if(ctlr->type != Type4965){
|
||||||
eepromunlock(ctlr);
|
if((err = eepromread(ctlr, b, 2, 0x048)) != nil){
|
||||||
goto Err;
|
eepromunlock(ctlr);
|
||||||
|
goto Err;
|
||||||
|
}
|
||||||
|
u = get16(b);
|
||||||
|
ctlr->rfcfg.type = u & 3; u >>= 2;
|
||||||
|
ctlr->rfcfg.step = u & 3; u >>= 2;
|
||||||
|
ctlr->rfcfg.dash = u & 3; u >>= 4;
|
||||||
|
ctlr->rfcfg.txantmask = u & 15; u >>= 4;
|
||||||
|
ctlr->rfcfg.rxantmask = u & 15;
|
||||||
|
if((err = eepromread(ctlr, b, 4, 0x128)) != nil){
|
||||||
|
eepromunlock(ctlr);
|
||||||
|
goto Err;
|
||||||
|
}
|
||||||
|
ctlr->eeprom.crystal = get32(b);
|
||||||
}
|
}
|
||||||
u = get16(b);
|
|
||||||
ctlr->rfcfg.type = u & 3; u >>= 2;
|
|
||||||
ctlr->rfcfg.step = u & 3; u >>= 2;
|
|
||||||
ctlr->rfcfg.dash = u & 3; u >>= 4;
|
|
||||||
ctlr->rfcfg.txantmask = u & 15; u >>= 4;
|
|
||||||
ctlr->rfcfg.rxantmask = u & 15;
|
|
||||||
if((err = eepromread(ctlr, b, 4, 0x128)) != nil){
|
|
||||||
eepromunlock(ctlr);
|
|
||||||
goto Err;
|
|
||||||
}
|
|
||||||
ctlr->eeprom.crystal = get32(b);
|
|
||||||
eepromunlock(ctlr);
|
eepromunlock(ctlr);
|
||||||
|
|
||||||
|
switch(ctlr->type){
|
||||||
|
case Type4965:
|
||||||
|
ctlr->rfcfg.txantmask = 3;
|
||||||
|
ctlr->rfcfg.rxantmask = 7;
|
||||||
|
break;
|
||||||
|
case Type5100:
|
||||||
|
ctlr->rfcfg.txantmask = 2;
|
||||||
|
ctlr->rfcfg.rxantmask = 3;
|
||||||
|
break;
|
||||||
|
case Type6000:
|
||||||
|
if(ctlr->pdev->did == 0x422c || ctlr->pdev->did == 0x4230){
|
||||||
|
ctlr->rfcfg.txantmask = 6;
|
||||||
|
ctlr->rfcfg.rxantmask = 6;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ctlr->ie = 0;
|
ctlr->ie = 0;
|
||||||
csr32w(ctlr, Isr, ~0); /* clear pending interrupts */
|
csr32w(ctlr, Isr, ~0); /* clear pending interrupts */
|
||||||
csr32w(ctlr, Imr, 0); /* no interrupts for now */
|
csr32w(ctlr, Imr, 0); /* no interrupts for now */
|
||||||
|
@ -936,6 +992,7 @@ setled(Ctlr *ctlr, int which, int on, int off)
|
||||||
static void
|
static void
|
||||||
postboot(Ctlr *ctlr)
|
postboot(Ctlr *ctlr)
|
||||||
{
|
{
|
||||||
|
uint ctxoff, ctxlen, dramaddr, txfact;
|
||||||
uchar c[8];
|
uchar c[8];
|
||||||
char *err;
|
char *err;
|
||||||
int i, q;
|
int i, q;
|
||||||
|
@ -945,33 +1002,69 @@ postboot(Ctlr *ctlr)
|
||||||
|
|
||||||
if((err = niclock(ctlr)) != nil)
|
if((err = niclock(ctlr)) != nil)
|
||||||
error(err);
|
error(err);
|
||||||
ctlr->sched.base = prphread(ctlr, SchedSramAddr);
|
|
||||||
for(i=0; i < SchedCtxLen5000/4; i++)
|
|
||||||
memwrite(ctlr, ctlr->sched.base + SchedCtxOff5000 + i*4, 0);
|
|
||||||
|
|
||||||
prphwrite(ctlr, SchedDramAddr5000, PCIWADDR(ctlr->sched.s)>>10);
|
if(ctlr->type != Type4965){
|
||||||
csr32w(ctlr, FhTxChicken, csr32r(ctlr, FhTxChicken) | 2);
|
dramaddr = SchedDramAddr5000;
|
||||||
|
ctxoff = SchedCtxOff5000;
|
||||||
/* Enable chain mode for all queues, except command queue. */
|
ctxlen = SchedCtxLen5000;
|
||||||
prphwrite(ctlr, SchedQChainSel5000, 0xfffef);
|
txfact = SchedTxFact5000;
|
||||||
prphwrite(ctlr, SchedAggrSel5000, 0);
|
} else {
|
||||||
|
dramaddr = SchedDramAddr4965;
|
||||||
for(q=0; q<nelem(ctlr->tx); q++){
|
ctxoff = SchedCtxOff4965;
|
||||||
prphwrite(ctlr, SchedQueueRdptr5000 + q*4, 0);
|
ctxlen = SchedCtxLen4965;
|
||||||
csr32w(ctlr, HbusTargWptr, q << 8);
|
txfact = SchedTxFact4965;
|
||||||
memwrite(ctlr, ctlr->sched.base + SchedCtxOff5000 + q*8, 0);
|
}
|
||||||
/* Set scheduler window size and frame limit. */
|
|
||||||
memwrite(ctlr, ctlr->sched.base + SchedCtxOff5000 + q*8 + 4, 64<<16 | 64);
|
ctlr->sched.base = prphread(ctlr, SchedSramAddr);
|
||||||
|
for(i=0; i < ctxlen/4; i++)
|
||||||
|
memwrite(ctlr, ctlr->sched.base + ctxoff + i*4, 0);
|
||||||
|
|
||||||
|
prphwrite(ctlr, dramaddr, PCIWADDR(ctlr->sched.s)>>10);
|
||||||
|
|
||||||
|
csr32w(ctlr, FhTxChicken, csr32r(ctlr, FhTxChicken) | 2);
|
||||||
|
|
||||||
|
if(ctlr->type != Type4965){
|
||||||
|
/* Enable chain mode for all queues, except command queue 4. */
|
||||||
|
prphwrite(ctlr, SchedQChainSel5000, 0xfffef);
|
||||||
|
prphwrite(ctlr, SchedAggrSel5000, 0);
|
||||||
|
|
||||||
|
for(q=0; q<nelem(ctlr->tx); q++){
|
||||||
|
prphwrite(ctlr, SchedQueueRdptr5000 + q*4, 0);
|
||||||
|
csr32w(ctlr, HbusTargWptr, q << 8);
|
||||||
|
|
||||||
|
memwrite(ctlr, ctlr->sched.base + ctxoff + q*8, 0);
|
||||||
|
/* Set scheduler window size and frame limit. */
|
||||||
|
memwrite(ctlr, ctlr->sched.base + ctxoff + q*8 + 4, 64<<16 | 64);
|
||||||
|
}
|
||||||
|
/* Enable interrupts for all our 20 queues. */
|
||||||
|
prphwrite(ctlr, SchedIntrMask5000, 0xfffff);
|
||||||
|
} else {
|
||||||
|
/* Disable chain mode for all our 16 queues. */
|
||||||
|
prphwrite(ctlr, SchedQChainSel4965, 0);
|
||||||
|
|
||||||
|
for(q=0; q<16; q++) {
|
||||||
|
prphwrite(ctlr, SchedQueueRdptr4965 + q*4, 0);
|
||||||
|
csr32w(ctlr, HbusTargWptr, q << 8);
|
||||||
|
|
||||||
|
/* Set scheduler window size. */
|
||||||
|
memwrite(ctlr, ctlr->sched.base + ctxoff + q*8, 64);
|
||||||
|
/* Set scheduler window size and frame limit. */
|
||||||
|
memwrite(ctlr, ctlr->sched.base + ctxoff + q*8 + 4, 64<<16);
|
||||||
|
}
|
||||||
|
/* Enable interrupts for all our 16 queues. */
|
||||||
|
prphwrite(ctlr, SchedIntrMask4965, 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable interrupts for all our 20 queues. */
|
|
||||||
prphwrite(ctlr, SchedIntrMask5000, 0xfffff);
|
|
||||||
/* Identify TX FIFO rings (0-7). */
|
/* Identify TX FIFO rings (0-7). */
|
||||||
prphwrite(ctlr, SchedTxFact5000, 0xff);
|
prphwrite(ctlr, txfact, 0xff);
|
||||||
|
|
||||||
/* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
|
/* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
|
||||||
for(q=0; q<7; q++){
|
for(q=0; q<7; q++){
|
||||||
static uchar qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
|
static uchar qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
|
||||||
prphwrite(ctlr, SchedQueueStatus5000 + q*4, 0x00ff0018 | qid2fifo[q]);
|
if(ctlr->type != Type4965)
|
||||||
|
prphwrite(ctlr, SchedQueueStatus5000 + q*4, 0x00ff0018 | qid2fifo[q]);
|
||||||
|
else
|
||||||
|
prphwrite(ctlr, SchedQueueStatus4965 + q*4, 0x0007fc01 | qid2fifo[q]);
|
||||||
}
|
}
|
||||||
nicunlock(ctlr);
|
nicunlock(ctlr);
|
||||||
|
|
||||||
|
@ -1029,7 +1122,7 @@ addnode(Ctlr *ctlr, uchar id, uchar *addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rxon(Ether *edev)
|
rxon(Ether *edev, Wnode *bss)
|
||||||
{
|
{
|
||||||
uchar c[Tcmdsize], *p;
|
uchar c[Tcmdsize], *p;
|
||||||
Ctlr *ctlr;
|
Ctlr *ctlr;
|
||||||
|
@ -1037,21 +1130,24 @@ rxon(Ether *edev)
|
||||||
ctlr = edev->ctlr;
|
ctlr = edev->ctlr;
|
||||||
memset(p = c, 0, sizeof(c));
|
memset(p = c, 0, sizeof(c));
|
||||||
memmove(p, edev->ea, 6); p += 8; /* myaddr */
|
memmove(p, edev->ea, 6); p += 8; /* myaddr */
|
||||||
|
memmove(p, (bss != nil) ? bss->bssid : edev->bcast, 6);
|
||||||
p += 8; /* bssid */
|
p += 8; /* bssid */
|
||||||
memmove(p, edev->ea, 6); p += 8; /* wlap */
|
memmove(p, edev->ea, 6); p += 8; /* wlap */
|
||||||
*p++ = 3; /* mode */
|
*p++ = 3; /* mode (STA) */
|
||||||
*p++ = 0; /* air (?) */
|
*p++ = 0; /* air (?) */
|
||||||
/* rxchain */
|
/* rxchain */
|
||||||
put16(p, ((ctlr->rfcfg.rxantmask & 7)<<1) | (2<<10) | (2<<12));
|
put16(p, ((ctlr->rfcfg.rxantmask & 7)<<1) | (2<<10) | (2<<12));
|
||||||
p += 2;
|
p += 2;
|
||||||
*p++ = 0xff; /* ofdm mask (not yet negotiated) */
|
*p++ = 0xff; /* ofdm mask (not yet negotiated) */
|
||||||
*p++ = 0x0f; /* cck mask (not yet negotiated) */
|
*p++ = 0x0f; /* cck mask (not yet negotiated) */
|
||||||
p += 2; /* associd (?) */
|
if(bss != nil)
|
||||||
|
put16(p, bss->aid & ~0xc000);
|
||||||
|
p += 2; /* aid */
|
||||||
put32(p, (1<<15)|(1<<30)|(1<<0)); /* flags (TSF | CTS_TO_SELF | 24GHZ) */
|
put32(p, (1<<15)|(1<<30)|(1<<0)); /* flags (TSF | CTS_TO_SELF | 24GHZ) */
|
||||||
p += 4;
|
p += 4;
|
||||||
put32(p, 4|1); /* filter (MULTICAST|PROMISC) */
|
put32(p, 8|4|1); /* filter (NODECRYPT|MULTICAST|PROMISC) */
|
||||||
p += 4;
|
p += 4;
|
||||||
*p++ = ctlr->channel; /* chan */
|
*p++ = bss != nil ? bss->channel : ctlr->channel;
|
||||||
p++; /* reserved */
|
p++; /* reserved */
|
||||||
*p++ = 0xff; /* ht single mask */
|
*p++ = 0xff; /* ht single mask */
|
||||||
*p++ = 0xff; /* ht dual mask */
|
*p++ = 0xff; /* ht dual mask */
|
||||||
|
@ -1062,6 +1158,10 @@ rxon(Ether *edev)
|
||||||
p += 2; /* reserved */
|
p += 2; /* reserved */
|
||||||
}
|
}
|
||||||
cmd(ctlr, 16, c, p - c);
|
cmd(ctlr, 16, c, p - c);
|
||||||
|
|
||||||
|
addnode(ctlr, (ctlr->type != Type4965) ? 15 : 31, edev->bcast);
|
||||||
|
if(bss != nil)
|
||||||
|
addnode(ctlr, 0, bss->bssid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ratetab {
|
static struct ratetab {
|
||||||
|
@ -1100,10 +1200,16 @@ transmit(Wifi *wifi, Wnode *, Block *b)
|
||||||
p += 4;
|
p += 4;
|
||||||
put32(p, 0);
|
put32(p, 0);
|
||||||
p += 4; /* scratch */
|
p += 4; /* scratch */
|
||||||
|
|
||||||
|
/* BUG: hardcode 11Mbit */
|
||||||
*p++ = ratetab[2].plcp; /* plcp */
|
*p++ = ratetab[2].plcp; /* plcp */
|
||||||
*p++ = ratetab[2].flags | (1<<6); /* rflags */
|
*p++ = ratetab[2].flags | (1<<6); /* rflags */
|
||||||
|
|
||||||
p += 2; /* xflags */
|
p += 2; /* xflags */
|
||||||
*p++ = 15; /* id (5000 only) */
|
|
||||||
|
/* BUG: we always use broadcast node! */
|
||||||
|
*p++ = (ctlr->type != Type4965) ? 15 : 31;
|
||||||
|
|
||||||
*p++ = 0; /* security */
|
*p++ = 0; /* security */
|
||||||
*p++ = 0; /* linkq */
|
*p++ = 0; /* linkq */
|
||||||
p++; /* reserved */
|
p++; /* reserved */
|
||||||
|
@ -1112,9 +1218,11 @@ transmit(Wifi *wifi, Wnode *, Block *b)
|
||||||
p += 2; /* reserved */
|
p += 2; /* reserved */
|
||||||
put32(p, ~0); /* lifetime */
|
put32(p, ~0); /* lifetime */
|
||||||
p += 4;
|
p += 4;
|
||||||
/* scratch ptr? not clear what this is for */
|
|
||||||
|
/* BUG: scratch ptr? not clear what this is for */
|
||||||
put32(p, PCIWADDR(ctlr->kwpage));
|
put32(p, PCIWADDR(ctlr->kwpage));
|
||||||
p += 5;
|
p += 5;
|
||||||
|
|
||||||
*p++ = 60; /* rts ntries */
|
*p++ = 60; /* rts ntries */
|
||||||
*p++ = 15; /* data ntries */
|
*p++ = 15; /* data ntries */
|
||||||
*p++ = 0; /* tid */
|
*p++ = 0; /* tid */
|
||||||
|
@ -1205,9 +1313,10 @@ iwlattach(Ether *edev)
|
||||||
ctlr->wifi = wifiattach(edev, transmit);
|
ctlr->wifi = wifiattach(edev, transmit);
|
||||||
|
|
||||||
if(ctlr->fw == nil){
|
if(ctlr->fw == nil){
|
||||||
fw = readfirmware("iwn-5000");
|
fw = readfirmware(ctlrtype[ctlr->type].fwname);
|
||||||
print("#l%d: firmware: rev %ux, build %ud, size %ux+%ux+%ux+%ux+%ux\n",
|
print("#l%d: firmware: %s, rev %ux, build %ud, size %ux+%ux+%ux+%ux+%ux\n",
|
||||||
edev->ctlrno,
|
edev->ctlrno,
|
||||||
|
ctlrtype[ctlr->type].fwname,
|
||||||
fw->rev, fw->build,
|
fw->rev, fw->build,
|
||||||
fw->main.text.size, fw->main.data.size,
|
fw->main.text.size, fw->main.data.size,
|
||||||
fw->init.text.size, fw->init.data.size,
|
fw->init.text.size, fw->init.data.size,
|
||||||
|
@ -1285,13 +1394,20 @@ iwlattach(Ether *edev)
|
||||||
|
|
||||||
if((err = niclock(ctlr)) != nil)
|
if((err = niclock(ctlr)) != nil)
|
||||||
error(err);
|
error(err);
|
||||||
|
|
||||||
prphwrite(ctlr, SchedTxFact5000, 0);
|
prphwrite(ctlr, SchedTxFact5000, 0);
|
||||||
|
|
||||||
csr32w(ctlr, FhKwAddr, PCIWADDR(ctlr->kwpage) >> 4);
|
csr32w(ctlr, FhKwAddr, PCIWADDR(ctlr->kwpage) >> 4);
|
||||||
|
|
||||||
for(q=0; q<nelem(ctlr->tx); q++)
|
for(q=0; q<nelem(ctlr->tx); q++)
|
||||||
csr32w(ctlr, FhCbbcQueue + q*4, PCIWADDR(ctlr->tx[q].d) >> 8);
|
if(q < 15 || ctlr->type != Type4965)
|
||||||
|
csr32w(ctlr, FhCbbcQueue + q*4, PCIWADDR(ctlr->tx[q].d) >> 8);
|
||||||
nicunlock(ctlr);
|
nicunlock(ctlr);
|
||||||
|
|
||||||
for(i=0; i<8; i++)
|
for(i=0; i<8; i++)
|
||||||
csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna);
|
if(i < 7 || ctlr->type != Type4965)
|
||||||
|
csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna);
|
||||||
|
|
||||||
csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
|
csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
|
||||||
csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
|
csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
|
||||||
|
|
||||||
|
@ -1315,8 +1431,7 @@ iwlattach(Ether *edev)
|
||||||
|
|
||||||
setoptions(edev);
|
setoptions(edev);
|
||||||
|
|
||||||
rxon(edev);
|
rxon(edev, nil);
|
||||||
addnode(ctlr, 15, edev->bcast);
|
|
||||||
|
|
||||||
edev->prom = 1;
|
edev->prom = 1;
|
||||||
edev->link = 1;
|
edev->link = 1;
|
||||||
|
@ -1524,6 +1639,13 @@ iwlpci(void)
|
||||||
ctlr->pdev = pdev;
|
ctlr->pdev = pdev;
|
||||||
ctlr->type = (csr32r(ctlr, Rev) >> 4) & 0xF;
|
ctlr->type = (csr32r(ctlr, Rev) >> 4) & 0xF;
|
||||||
|
|
||||||
|
if(ctlrtype[ctlr->type].fwname == nil){
|
||||||
|
print("iwl: unsupported controller type %d\n", ctlr->type);
|
||||||
|
vunmap(mem, pdev->mem[0].size);
|
||||||
|
free(ctlr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(iwlhead != nil)
|
if(iwlhead != nil)
|
||||||
iwltail->link = ctlr;
|
iwltail->link = ctlr;
|
||||||
else
|
else
|
||||||
|
|
|
@ -185,7 +185,7 @@ sendassoc(Wifi *wifi, Wnode *bss)
|
||||||
p += 1+*p;
|
p += 1+*p;
|
||||||
*p++ = 1; /* RATES */
|
*p++ = 1; /* RATES */
|
||||||
*p++ = 1;
|
*p++ = 1;
|
||||||
*p++ = 0x96;
|
*p++ = 0x96; /* BUG: hardcoded 11Mbit (802.11b) */
|
||||||
b->wp = p;
|
b->wp = p;
|
||||||
wifitx(wifi, b);
|
wifitx(wifi, b);
|
||||||
}
|
}
|
||||||
|
@ -216,6 +216,7 @@ static void
|
||||||
recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len)
|
recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len)
|
||||||
{
|
{
|
||||||
uchar *e, *x;
|
uchar *e, *x;
|
||||||
|
uchar t, m[256/8];
|
||||||
|
|
||||||
if(len < 8+2+2)
|
if(len < 8+2+2)
|
||||||
return;
|
return;
|
||||||
|
@ -226,10 +227,18 @@ recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len)
|
||||||
wn->cap = d[0] | d[1]<<8;
|
wn->cap = d[0] | d[1]<<8;
|
||||||
d += 2;
|
d += 2;
|
||||||
|
|
||||||
|
memset(m, 0, sizeof(m));
|
||||||
for(e = d + len; d+2 <= e; d = x){
|
for(e = d + len; d+2 <= e; d = x){
|
||||||
d += 2;
|
d += 2;
|
||||||
x = d + d[-1];
|
x = d + d[-1];
|
||||||
switch(d[-2]){
|
t = d[-2];
|
||||||
|
|
||||||
|
/* skip double entries */
|
||||||
|
if(m[t/8] & 1<<(t%8))
|
||||||
|
continue;
|
||||||
|
m[t/8] |= 1<<(t%8);
|
||||||
|
|
||||||
|
switch(t){
|
||||||
case 0: /* SSID */
|
case 0: /* SSID */
|
||||||
len = 0;
|
len = 0;
|
||||||
while(len < 32 && d+len < x && d[len] != 0)
|
while(len < 32 && d+len < x && d[len] != 0)
|
||||||
|
@ -245,7 +254,11 @@ recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len)
|
||||||
sendauth(wifi, wn);
|
sendauth(wifi, wn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
break;
|
||||||
|
case 3: /* DSPARAMS */
|
||||||
|
if(d != x)
|
||||||
|
wn->channel = d[0];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,8 +428,8 @@ wifistat(Wifi *wifi, void *buf, long n, ulong off)
|
||||||
for(wn=wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){
|
for(wn=wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){
|
||||||
if(wn->lastseen == 0)
|
if(wn->lastseen == 0)
|
||||||
continue;
|
continue;
|
||||||
p = seprint(p, e, "node: %E %.4x %d %ld %s\n",
|
p = seprint(p, e, "node: %E %.4x %d %ld %d %s\n",
|
||||||
wn->bssid, wn->cap, wn->ival, TK2MS(now - wn->lastseen), wn->ssid);
|
wn->bssid, wn->cap, wn->ival, TK2MS(now - wn->lastseen), wn->channel, wn->ssid);
|
||||||
}
|
}
|
||||||
n = readstr(off, buf, n, s);
|
n = readstr(off, buf, n, s);
|
||||||
free(s);
|
free(s);
|
||||||
|
|
|
@ -23,10 +23,9 @@ struct Wnode
|
||||||
char ssid[32+2];
|
char ssid[32+2];
|
||||||
int ival;
|
int ival;
|
||||||
int cap;
|
int cap;
|
||||||
|
|
||||||
long lastseen;
|
|
||||||
|
|
||||||
int aid;
|
int aid;
|
||||||
|
int channel;
|
||||||
|
long lastseen;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Wifi
|
struct Wifi
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue