This commit is contained in:
ppatience0 2013-02-13 07:37:26 -05:00
commit 6d7bb96b22
13 changed files with 412 additions and 151 deletions

View file

@ -71,3 +71,5 @@ Ouch
Please don't.
Test?
sure
NOT LGTM sorry
i lost the ability to use rio a few years ago when they moved wireless configuration into the gnome window manager, making it impossible to have rio and a network connection at the same time.

View file

@ -114,3 +114,6 @@ did anyone at iwp9 give an update about osprey? anyone ask when it'll be availab
just run linux -- aiju
I'm fairly new to plan9, and am having trouble ssh'ing to my mac.
Subject: [golang-dev] not reading code
Is Trolling Ever Okay?
I've downloaded the nix bits from http://code.google.com/p/nix-os/ and compiled it under 9vx on OSX, but I'm having some trouble getting the resultant kernel to boot.
Subject: [nix] servers down

View file

@ -4799,3 +4799,15 @@ I don't want Javascript promises
--- you can reply above this line ---
MIT OpenCourseware >> Electrical Engineering and Computer Science >> Introduction to Electrical Engineering and Computer Science I >> Python Tutorial
(#plan9) semka → May be I should ask at #cat-v :)
Monument To Steve Jobs Goes Up In St. Petersburg
But without moving the directory specifics out of user space code like it was V7 and earlier, it would have been hard to create something as clean as VFS.
(#cat-v) aiju → what's weird is that uriel loved gay colours
rcirc on GNU Emacs 24.2.1
Decade Old KDE Bug Fixed
Fix the value of TWO
Fedora 18 Installer: Counterintuitive and Confusing?
when all you understand is trivial bullshit, trivial bullshit is what's important
hjfs: ending
If its done right this is not wrong. -- 20h
Just today I found out that the Chrome JS editor can hot-swap your code.
A programming language, even with its libraries, is not enough, nor is it always the right place to solve all the problems of the network.

View file

@ -45,7 +45,7 @@ int mpfmt(Fmt*);
char* mptoa(mpint*, int, char*, int);
mpint* letomp(uchar*, uint, mpint*); /* byte array, little-endian */
int mptole(mpint*, uchar*, uint, uchar**);
mpint* betomp(uchar*, uint, mpint*); /* byte array, little-endian */
mpint* betomp(uchar*, uint, mpint*); /* byte array, big-endian */
int mptobe(mpint*, uchar*, uint, uchar**);
uint mptoui(mpint*); /* unsigned int */
mpint* uitomp(uint, mpint*);

View file

@ -107,6 +107,7 @@ mkdir -p cron
mkdir -p dist/plan9front
mkdir -p fd
mkdir -p lib/audio
mkdir -p lib/firmware
mkdir -p lib/ndb
mkdir -p lib/tftpd
mkdir -p mail/box

View file

@ -381,6 +381,29 @@ programming interface.
Currently the only tested cards are those based on the
Intersil Prism 2.5 chipset.
.
.TP
.B iwl
Intel Wireless WiFi Link mini PCI-Express adapters require
firmware from
.B http://firmware.openbsd.org/firmware/iwn-firmware*.tgz
to be present on attach in
.B /lib/firmware
or
.B /boot.
To select the access point, the
.B essid=
parameter can be specified at boot or set during runtime
like:
.EX
echo essid left-armpit >/net/ether1/clone
.EE
Scan results appear in the
.B ifstats
file and can be read out like:
.EX
cat /net/ether1/ifstats
.EE
Ad-hoc mode or encryption is currently not supported.
.SS DISKS, TAPES
(S)ATA controllers are autodetected.
.SS \fL*nodma=\fP

View file

@ -19,7 +19,6 @@
#include "wifi.h"
enum {
Ntxlog = 8,
Ntx = 1<<Ntxlog,
Nrxlog = 8,
@ -197,16 +196,18 @@ enum {
enum {
SchedBase = 0xa02c00,
SchedSramAddr = SchedBase,
SchedDramAddr5000 = SchedBase+0x008,
SchedDramAddr4965 = SchedBase+0x010,
SchedTxFact5000 = SchedBase+0x010,
SchedTxFact4965 = SchedBase+0x01c,
SchedQueueRdptr4965 = SchedBase+0x064, // +q*4
SchedQueueRdptr5000 = SchedBase+0x068, // +q*4
SchedQChainSel4965 = SchedBase+0x0d0,
SchedIntrMask4965 = SchedBase+0x0e4,
SchedQChainSel5000 = SchedBase+0x0e8,
SchedQueueStatus4965 = SchedBase+0x104, // +q*4
SchedDramAddr5000 = SchedBase+0x008,
SchedTxFact5000 = SchedBase+0x010,
SchedQueueRdptr5000 = SchedBase+0x068, // +q*4
SchedQChainSel5000 = SchedBase+0x0e8,
SchedIntrMask5000 = SchedBase+0x108,
SchedQueueStatus5000 = SchedBase+0x10c, // +q*4
SchedAggrSel5000 = SchedBase+0x248,
@ -215,11 +216,31 @@ enum {
enum {
SchedCtxOff4965 = 0x380,
SchedCtxLen4965 = 416,
SchedTransTblOff4965 = 0x500,
SchedCtxOff5000 = 0x600,
SchedCtxLen5000 = 512,
SchedTransTblOff5000 = 0x7e0,
};
enum {
FilterPromisc = 1<<0,
FilterCtl = 1<<1,
FilterMulticast = 1<<2,
FilterNoDecrypt = 1<<3,
FilterBSS = 1<<5,
FilterBeacon = 1<<6,
};
enum {
RFlag24Ghz = 1<<0,
RFlagCCK = 1<<1,
RFlagAuto = 1<<2,
RFlagShSlot = 1<<4,
RFlagShPreamble = 1<<5,
RFlagNoDiversity = 1<<7,
RFlagAntennaA = 1<<8,
RFlagAntennaB = 1<<9,
RFlagTSF = 1<<15,
RFlagCTSToSelf = 1<<30,
};
typedef struct FWInfo FWInfo;
@ -231,8 +252,6 @@ typedef struct RXQ RXQ;
typedef struct Ctlr Ctlr;
typedef struct Ctlrtype Ctlrtype;
struct FWSect
{
uchar *data;
@ -303,7 +322,15 @@ struct Ctlr {
u32int *nic;
uchar *kwpage;
/* assigned node ids in hardware node table or -1 if unassigned */
int bcastnodeid;
int bssnodeid;
/* current receiver settings */
uchar bssid[Eaddrlen];
int channel;
int prom;
int aid;
RXQ rx;
TXQ tx[20];
@ -349,39 +376,16 @@ enum {
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",
},
static char *fwname[16] = {
[Type4965] "iwn-4965",
[Type5300] "iwn-5000",
[Type5350] "iwn-5000",
[Type5150] "iwn-5150",
[Type5100] "iwn-5000",
[Type1000] "iwn-1000",
[Type6000] "iwn-6000",
[Type6050] "iwn-6050",
[Type6005] "iwn-6005",
};
#define csr32r(c, r) (*((c)->nic+((r)/4)))
@ -725,7 +729,7 @@ Tooshort:
return "bad firmware signature";
p += 4;
strncpy(i->descr, (char*)p, 64);
i->descr[sizeof(i->descr)-1] = 0;
i->descr[64] = 0;
p += 64;
i->rev = get32(p); p += 4;
i->build = get32(p); p += 4;
@ -747,7 +751,7 @@ Tooshort:
default:s = &dummy;
}
p += 2;
if(get16(p) != alt)
if(get16(p) != 0 && get16(p) != alt)
s = &dummy;
p += 2;
s->size = get32(p); p += 4;
@ -913,6 +917,7 @@ bootfirmware(Ctlr *ctlr)
return err;
if((err = loadfirmware1(ctlr, 0x00800000, fw->main.data.data, fw->main.data.size)) != nil)
return err;
csr32w(ctlr, Reset, 0);
goto bootmain;
}
@ -937,6 +942,12 @@ bootfirmware(Ctlr *ctlr)
prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
prphwrite(ctlr, BsmDramTextSize, fw->init.text.size);
nicunlock(ctlr);
if((err = niclock(ctlr)) != nil){
free(dma);
return err;
}
p = fw->boot.text.data;
n = fw->boot.text.size/4;
for(i=0; i<n; i++, p += 4)
@ -990,7 +1001,6 @@ bootfirmware(Ctlr *ctlr)
nicunlock(ctlr);
bootmain:
csr32w(ctlr, Reset, 0);
if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
free(dma);
return "main firmware boot failed";
@ -1019,12 +1029,11 @@ qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
q = &ctlr->tx[qid];
while(q->n >= Ntx){
iunlock(ctlr);
eqlock(q);
if(waserror()){
qunlock(q);
nexterror();
qlock(q);
if(!waserror()){
tsleep(q, txqready, q, 10);
poperror();
}
tsleep(q, txqready, q, 10);
qunlock(q);
ilock(ctlr);
}
@ -1067,12 +1076,43 @@ qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
iunlock(ctlr);
}
static int
txqempty(void *arg)
{
TXQ *q = arg;
return q->n == 0;
}
static void
flushq(Ctlr *ctlr, uint qid)
{
TXQ *q;
q = &ctlr->tx[qid];
while(q->n > 0){
qlock(q);
if(!waserror()){
tsleep(q, txqempty, q, 10);
poperror();
}
qunlock(q);
}
}
static void
flushcmd(Ctlr *ctlr)
{
flushq(ctlr, 4);
}
static void
cmd(Ctlr *ctlr, uint code, uchar *data, int size)
{
qcmd(ctlr, 4, code, data, size, nil);
}
static void
setled(Ctlr *ctlr, int which, int on, int off)
{
@ -1099,9 +1139,6 @@ postboot(Ctlr *ctlr)
char *err;
int i, q;
/* main led turn on! (verify that firmware processes commands) */
setled(ctlr, 2, 0, 1);
if((err = niclock(ctlr)) != nil)
error(err);
@ -1118,8 +1155,8 @@ postboot(Ctlr *ctlr)
}
ctlr->sched.base = prphread(ctlr, SchedSramAddr);
for(i=0; i < ctxlen/4; i++)
memwrite(ctlr, ctlr->sched.base + ctxoff + i*4, 0);
for(i=0; i < ctxlen; i += 4)
memwrite(ctlr, ctlr->sched.base + ctxoff + i, 0);
prphwrite(ctlr, dramaddr, PCIWADDR(ctlr->sched.s)>>10);
@ -1130,7 +1167,7 @@ postboot(Ctlr *ctlr)
prphwrite(ctlr, SchedQChainSel5000, 0xfffef);
prphwrite(ctlr, SchedAggrSel5000, 0);
for(q=0; q<nelem(ctlr->tx); q++){
for(q=0; q<20; q++){
prphwrite(ctlr, SchedQueueRdptr5000 + q*4, 0);
csr32w(ctlr, HbusTargWptr, q << 8);
@ -1162,25 +1199,26 @@ postboot(Ctlr *ctlr)
/* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
for(q=0; q<7; q++){
static uchar qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
if(ctlr->type != Type4965)
if(ctlr->type != Type4965){
static uchar qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
prphwrite(ctlr, SchedQueueStatus5000 + q*4, 0x00ff0018 | qid2fifo[q]);
else
prphwrite(ctlr, SchedQueueStatus4965 + q*4, 0x0007fc01 | qid2fifo[q]);
} else {
static uchar qid2fifo[] = { 3, 2, 1, 0, 4, 5, 6 };
prphwrite(ctlr, SchedQueueStatus4965 + q*4, 0x0007fc01 | qid2fifo[q]<<1);
}
}
nicunlock(ctlr);
if(ctlr->type != Type5150){
memset(c, 0, sizeof(c));
c[0] = 15; /* code */
c[1] = 0; /* grup */
c[2] = 1; /* ngroup */
c[3] = 1; /* isvalid */
put16(c+4, ctlr->eeprom.crystal);
cmd(ctlr, 176, c, 8);
}
if(ctlr->type != Type4965){
if(ctlr->type != Type5150){
memset(c, 0, sizeof(c));
c[0] = 15; /* code */
c[1] = 0; /* grup */
c[2] = 1; /* ngroup */
c[3] = 1; /* isvalid */
put16(c+4, ctlr->eeprom.crystal);
cmd(ctlr, 176, c, 8);
}
put32(c, ctlr->rfcfg.txantmask & 7);
cmd(ctlr, 152, c, 4);
}
@ -1211,15 +1249,15 @@ addnode(Ctlr *ctlr, uchar id, uchar *addr)
p += 8; /* tcs */
p += 8; /* rxmic */
p += 8; /* txmic */
p += 4; /* htflags */
p += 4; /* mask */
p += 2; /* disable tid */
p += 2; /* reserved */
p++; /* add ba tid */
p++; /* del ba tid */
p += 2; /* add ba ssn */
p += 4; /* reserved */
}
p += 4; /* htflags */
p += 4; /* mask */
p += 2; /* disable tid */
p += 2; /* reserved */
p++; /* add ba tid */
p++; /* del ba tid */
p += 2; /* add ba ssn */
p += 4; /* reserved */
cmd(ctlr, 24, c, p - c);
}
@ -1227,13 +1265,39 @@ void
rxon(Ether *edev, Wnode *bss)
{
uchar c[Tcmdsize], *p;
int filter, flags;
Ctlr *ctlr;
ctlr = edev->ctlr;
filter = FilterMulticast | FilterBeacon;
if(ctlr->prom){
filter |= FilterPromisc;
bss = nil;
}
if(bss != nil){
ctlr->channel = bss->channel;
memmove(ctlr->bssid, bss->bssid, Eaddrlen);
ctlr->aid = bss->aid;
if(ctlr->aid != 0){
filter |= FilterBSS;
filter &= ~FilterBeacon;
ctlr->bssnodeid = -1;
} else
ctlr->bcastnodeid = -1;
} else {
memmove(ctlr->bssid, edev->bcast, Eaddrlen);
ctlr->aid = 0;
ctlr->bcastnodeid = -1;
ctlr->bssnodeid = -1;
}
flags = RFlagTSF | RFlagCTSToSelf | RFlag24Ghz | RFlagAuto;
if(0) print("rxon: bssid %E, aid %x, channel %d, filter %x, flags %x\n",
ctlr->bssid, ctlr->aid, ctlr->channel, filter, flags);
memset(p = c, 0, sizeof(c));
memmove(p, edev->ea, 6); p += 8; /* myaddr */
memmove(p, (bss != nil) ? bss->bssid : edev->bcast, 6);
p += 8; /* bssid */
memmove(p, ctlr->bssid, 6); p += 8; /* bssid */
memmove(p, edev->ea, 6); p += 8; /* wlap */
*p++ = 3; /* mode (STA) */
*p++ = 0; /* air (?) */
@ -1242,14 +1306,13 @@ rxon(Ether *edev, Wnode *bss)
p += 2;
*p++ = 0xff; /* ofdm mask (not yet negotiated) */
*p++ = 0x0f; /* cck mask (not yet negotiated) */
if(bss != nil)
put16(p, bss->aid & ~0xc000);
put16(p, ctlr->aid & 0x3fff);
p += 2; /* aid */
put32(p, (1<<15)|(1<<30)|(1<<0)); /* flags (TSF | CTS_TO_SELF | 24GHZ) */
put32(p, flags);
p += 4;
put32(p, 8|4|1); /* filter (NODECRYPT|MULTICAST|PROMISC) */
put32(p, filter);
p += 4;
*p++ = bss != nil ? bss->channel : ctlr->channel;
*p++ = ctlr->channel;
p++; /* reserved */
*p++ = 0xff; /* ht single mask */
*p++ = 0xff; /* ht dual mask */
@ -1261,9 +1324,15 @@ rxon(Ether *edev, Wnode *bss)
}
cmd(ctlr, 16, c, p - c);
addnode(ctlr, (ctlr->type != Type4965) ? 15 : 31, edev->bcast);
if(bss != nil)
addnode(ctlr, 0, bss->bssid);
if(ctlr->bcastnodeid == -1){
ctlr->bcastnodeid = (ctlr->type != Type4965) ? 15 : 31;
addnode(ctlr, ctlr->bcastnodeid, edev->bcast);
}
if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){
ctlr->bssnodeid = 0;
addnode(ctlr, ctlr->bssnodeid, bss->bssid);
}
flushcmd(ctlr);
}
static struct ratetab {
@ -1271,10 +1340,10 @@ static struct ratetab {
uchar plcp;
uchar flags;
} ratetab[] = {
{ 2, 10, 1<<1 },
{ 4, 20, 1<<1 },
{ 11, 55, 1<<1 },
{ 22, 110, 1<<1 },
{ 2, 10, RFlagCCK },
{ 4, 20, RFlagCCK },
{ 11, 55, RFlagCCK },
{ 22, 110, RFlagCCK },
{ 12, 0xd, 0 },
{ 18, 0xf, 0 },
{ 24, 0x5, 0 },
@ -1286,32 +1355,80 @@ static struct ratetab {
{ 120, 0x3, 0 }
};
enum {
TFlagNeedProtection = 1<<0,
TFlagNeedRTS = 1<<1,
TFlagNeedCTS = 1<<2,
TFlagNeedACK = 1<<3,
TFlagLinkq = 1<<4,
TFlagImmBa = 1<<6,
TFlagFullTxOp = 1<<7,
TFlagBtDis = 1<<12,
TFlagAutoSeq = 1<<13,
TFlagMoreFrag = 1<<14,
TFlagInsertTs = 1<<16,
TFlagNeedPadding = 1<<20,
};
static void
transmit(Wifi *wifi, Wnode *, Block *b)
transmit(Wifi *wifi, Wnode *wn, Block *b)
{
uchar c[Tcmdsize], *p;
Ether *edev;
Ctlr *ctlr;
Wifipkt *w;
int flags, nodeid, rate;
ctlr = wifi->ether->ctlr;
w = (Wifipkt*)b->rp;
edev = wifi->ether;
ctlr = edev->ctlr;
qlock(ctlr);
if(ctlr->prom == 0)
if(wn->aid != ctlr->aid
|| wn->channel != ctlr->channel
|| memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0)
rxon(edev, wn);
rate = 0;
flags = 0;
nodeid = ctlr->bcastnodeid;
if((w->a1[0] & 1) == 0){
flags |= TFlagNeedACK;
if(BLEN(b) > 512-4)
flags |= TFlagNeedRTS;
if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){
nodeid = ctlr->bssnodeid;
rate = 2; /* BUG: hardcode 11Mbit */
}
if(flags & (TFlagNeedRTS|TFlagNeedCTS)){
if(ctlr->type != Type4965){
flags &= ~(TFlagNeedRTS|TFlagNeedCTS);
flags |= TFlagNeedProtection;
} else
flags |= TFlagFullTxOp;
}
}
qunlock(ctlr);
memset(p = c, 0, sizeof(c));
put16(p, BLEN(b));
p += 2;
p += 2; /* lnext */
put32(p, 0); /* flags */
put32(p, flags);
p += 4;
put32(p, 0);
p += 4; /* scratch */
/* BUG: hardcode 11Mbit */
*p++ = ratetab[2].plcp; /* plcp */
*p++ = ratetab[2].flags | (1<<6); /* rflags */
*p++ = ratetab[rate].plcp;
*p++ = ratetab[rate].flags | (1<<6);
p += 2; /* xflags */
/* BUG: we always use broadcast node! */
*p++ = (ctlr->type != Type4965) ? 15 : 31;
*p++ = nodeid;
*p++ = 0; /* security */
*p++ = 0; /* linkq */
p++; /* reserved */
@ -1379,11 +1496,7 @@ setoptions(Ether *edev)
int i;
ctlr = edev->ctlr;
ctlr->channel = 3;
for(i = 0; i < edev->nopt; i++){
if(strncmp(edev->opt[i], "channel=", 8) == 0)
ctlr->channel = atoi(edev->opt[i]+8);
else
if(strncmp(edev->opt[i], "essid=", 6) == 0){
snprint(buf, sizeof(buf), "essid %s", edev->opt[i]+6);
if(!waserror()){
@ -1394,9 +1507,75 @@ setoptions(Ether *edev)
}
}
static void
iwlpromiscuous(void *arg, int on)
{
Ether *edev;
Ctlr *ctlr;
edev = arg;
ctlr = edev->ctlr;
qlock(ctlr);
ctlr->prom = on;
rxon(edev, ctlr->wifi->bss);
qunlock(ctlr);
}
static void
iwlproc(void *arg)
{
Ether *edev;
Ctlr *ctlr;
Wifi *wifi;
Wnode *bss;
edev = arg;
ctlr = edev->ctlr;
wifi = ctlr->wifi;
for(;;){
/* hop channels for catching beacons */
setled(ctlr, 2, 5, 5);
while(wifi->bss == nil){
qlock(ctlr);
if(wifi->bss != nil){
qunlock(ctlr);
break;
}
ctlr->channel = 1 + ctlr->channel % 11;
ctlr->aid = 0;
rxon(edev, nil);
qunlock(ctlr);
tsleep(&up->sleep, return0, 0, 1000);
}
/* wait for association */
setled(ctlr, 2, 10, 10);
while((bss = wifi->bss) != nil){
if(bss->aid != 0)
break;
tsleep(&up->sleep, return0, 0, 1000);
}
if(bss == nil)
continue;
/* wait for disassociation */
edev->link = 1;
setled(ctlr, 2, 0, 1);
while((bss = wifi->bss) != nil){
if(bss->aid == 0)
break;
tsleep(&up->sleep, return0, 0, 1000);
}
edev->link = 0;
}
}
static void
iwlattach(Ether *edev)
{
char name[32];
FWImage *fw;
Ctlr *ctlr;
char *err;
@ -1420,10 +1599,10 @@ iwlattach(Ether *edev)
ctlr->wifi = wifiattach(edev, transmit);
if(ctlr->fw == nil){
fw = readfirmware(ctlrtype[ctlr->type].fwname);
fw = readfirmware(fwname[ctlr->type]);
print("#l%d: firmware: %s, rev %ux, build %ud, size %ux+%ux+%ux+%ux+%ux\n",
edev->ctlrno,
ctlrtype[ctlr->type].fwname,
fwname[ctlr->type],
fw->rev, fw->build,
fw->main.text.size, fw->main.data.size,
fw->init.text.size, fw->init.data.size,
@ -1502,18 +1681,20 @@ iwlattach(Ether *edev)
if((err = niclock(ctlr)) != nil)
error(err);
prphwrite(ctlr, SchedTxFact5000, 0);
if(ctlr->type != Type4965)
prphwrite(ctlr, SchedTxFact5000, 0);
else
prphwrite(ctlr, SchedTxFact4965, 0);
csr32w(ctlr, FhKwAddr, PCIWADDR(ctlr->kwpage) >> 4);
for(q=0; q<nelem(ctlr->tx); q++)
if(q < 15 || ctlr->type != Type4965)
csr32w(ctlr, FhCbbcQueue + q*4, PCIWADDR(ctlr->tx[q].d) >> 8);
for(q = (ctlr->type != Type4965) ? 19 : 15; q >= 0; q--)
csr32w(ctlr, FhCbbcQueue + q*4, PCIWADDR(ctlr->tx[q].d) >> 8);
nicunlock(ctlr);
for(i=0; i<8; i++)
if(i < 7 || ctlr->type != Type4965)
csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna);
for(i = (ctlr->type != Type4965) ? 7 : 6; i >= 0; i--)
csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna);
csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
@ -1528,12 +1709,16 @@ iwlattach(Ether *edev)
bootfirmware(ctlr);
postboot(ctlr);
ctlr->bcastnodeid = -1;
ctlr->bssnodeid = -1;
ctlr->channel = 1;
ctlr->aid = 0;
setoptions(edev);
rxon(edev, nil);
snprint(name, sizeof(name), "#l%diwl", edev->ctlrno);
kproc(name, iwlproc, edev);
edev->prom = 1;
edev->link = 1;
ctlr->attached = 1;
}
qunlock(ctlr);
@ -1619,9 +1804,10 @@ receive(Ctlr *ctlr)
case 192: /* rx phy */
break;
case 195: /* rx done */
if(d + 60 > b->lim)
if(d + 2 > b->lim)
break;
d += 60;
d += d[1];
d += 56;
case 193: /* mpdu rx done */
if(d + 4 > b->lim)
break;
@ -1705,6 +1891,8 @@ iwlpci(void)
switch(pdev->did){
default:
continue;
case 0x4229: /* WiFi Link 4965 */
case 0x4230: /* WiFi Link 4965 */
case 0x4236: /* WiFi Link 5300 AGN */
case 0x4237: /* Wifi Link 5100 AGN */
break;
@ -1739,7 +1927,7 @@ iwlpci(void)
ctlr->pdev = pdev;
ctlr->type = (csr32r(ctlr, Rev) >> 4) & 0xF;
if(ctlrtype[ctlr->type].fwname == nil){
if(fwname[ctlr->type] == nil){
print("iwl: unsupported controller type %d\n", ctlr->type);
vunmap(mem, pdev->mem[0].size);
free(ctlr);
@ -1783,7 +1971,7 @@ again:
edev->attach = iwlattach;
edev->ifstat = iwlifstat;
edev->ctl = iwlctl;
edev->promiscuous = nil;
edev->promiscuous = iwlpromiscuous;
edev->multicast = nil;
edev->mbps = 10;

View file

@ -121,6 +121,7 @@ trap.$O: /sys/include/tos.h
uartaxp.$O: uartaxp.i
etherm10g.$O: etherm10g2k.i etherm10g4k.i
etheriwl.$O: wifi.h
wifi.$O: wifi.h
init.h:D: ../port/initcode.c init9.c
$CC ../port/initcode.c

View file

@ -681,6 +681,7 @@ static Bridge southbridges[] = {
{ 0x8086, 0x3b06, pIIxget, pIIxset }, /* Intel 82801? ibex peak */
{ 0x8086, 0x3b14, pIIxget, pIIxset }, /* Intel 82801? 3420 */
{ 0x8086, 0x1c49, pIIxget, pIIxset }, /* Intel 82hm65 cougar point pch */
{ 0x8086, 0x1c4f, pIIxget, pIIxset }, /* Intel 82qm67 cougar point pch */
{ 0x8086, 0x1c52, pIIxget, pIIxset }, /* Intel 82q65 cougar point pch */
{ 0x8086, 0x1c54, pIIxget, pIIxset }, /* Intel 82q67 cougar point pch */
{ 0x1106, 0x0586, viaget, viaset }, /* Viatech 82C586 */

View file

@ -63,9 +63,13 @@ wifiiq(Wifi *wifi, Block *b)
default:
goto drop;
}
if(BLEN(b) < SNAPHDRSIZE || b->rp[0] != 0xAA || b->rp[1] != 0xAA || b->rp[2] != 0x03)
if(BLEN(b) < SNAPHDRSIZE)
break;
memmove(&s, b->rp, SNAPHDRSIZE);
if(s.dsap != 0xAA || s.ssap != 0xAA || s.control != 3)
break;
if(s.orgcode[0] != 0 || s.orgcode[1] != 0 || s.orgcode[2] != 0)
break;
b->rp += SNAPHDRSIZE-ETHERHDRSIZE;
e = (Etherpkt*)b->rp;
switch(w.fc[1] & 0x03){
@ -93,12 +97,12 @@ drop:
}
static void
wifitx(Wifi *wifi, Block *b)
wifitx(Wifi *wifi, Wnode *wn, Block *b)
{
Wifipkt *w;
uint seq;
seq = wifi->txseq++;
seq = incref(&wifi->txseq);
seq <<= 4;
w = (Wifipkt*)b->rp;
@ -107,7 +111,7 @@ wifitx(Wifi *wifi, Block *b)
w->seq[0] = seq;
w->seq[1] = seq>>8;
(*wifi->transmit)(wifi, wifi->bss, b);
(*wifi->transmit)(wifi, wn, b);
}
@ -118,17 +122,32 @@ nodelookup(Wifi *wifi, uchar *bssid, int new)
if(memcmp(bssid, wifi->ether->bcast, Eaddrlen) == 0)
return nil;
for(wn = nn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){
if((wn = wifi->bss) != nil){
if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){
wn->lastseen = MACHP(0)->ticks;
return wn;
}
if(wn != wifi->bss && wn->lastseen < nn->lastseen)
}
if((nn = wifi->node) == wn)
nn++;
for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){
if(wn == wifi->bss)
continue;
if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){
wn->lastseen = MACHP(0)->ticks;
return wn;
}
if(wn->lastseen < nn->lastseen)
nn = wn;
}
if(!new)
return nil;
memmove(nn->bssid, bssid, Eaddrlen);
nn->ssid[0] = 0;
nn->ival = 0;
nn->cap = 0;
nn->aid = 0;
nn->channel = 0;
nn->lastseen = MACHP(0)->ticks;
return nn;
}
@ -156,7 +175,7 @@ sendauth(Wifi *wifi, Wnode *bss)
*p++ = 0; /* status */
*p++ = 0;
b->wp = p;
wifitx(wifi, b);
wifitx(wifi, bss, b);
}
static void
@ -190,7 +209,7 @@ sendassoc(Wifi *wifi, Wnode *bss)
*p++ = 0x8b;
*p++ = 0x96;
b->wp = p;
wifitx(wifi, b);
wifitx(wifi, bss, b);
}
static void
@ -210,13 +229,14 @@ recvassoc(Wifi *wifi, Wnode *wn, uchar *d, int len)
wifi->status = Sassoc;
break;
default:
wn->aid = 0;
wifi->status = Sunassoc;
return;
}
}
static void
recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len)
recvbeacon(Wifi *, Wnode *wn, uchar *d, int len)
{
uchar *e, *x;
uchar t, m[256/8];
@ -251,11 +271,6 @@ recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len)
if(len != strlen(wn->ssid) || strncmp(wn->ssid, (char*)d, len) != 0){
strncpy(wn->ssid, (char*)d, len);
wn->ssid[len] = 0;
if(wifi->bss == nil && strcmp(wifi->essid, wn->ssid) == 0){
wifi->bss = wn;
wifi->status = Sconn;
sendauth(wifi, wn);
}
}
break;
case 3: /* DSPARAMS */
@ -289,8 +304,15 @@ wifiproc(void *arg)
continue;
b->rp += WIFIHDRSIZE;
recvbeacon(wifi, wn, b->rp, BLEN(b));
if(wifi->bss == nil && wifi->essid[0] != 0 && strcmp(wifi->essid, wn->ssid) == 0){
wifi->bss = wn;
wifi->status = Sconn;
sendauth(wifi, wn);
}
continue;
}
if(memcmp(w->a1, wifi->ether->ea, Eaddrlen))
continue;
if((wn = nodelookup(wifi, w->a3, 0)) == nil)
continue;
if(wn != wifi->bss)
@ -306,7 +328,9 @@ wifiproc(void *arg)
sendassoc(wifi, wn);
break;
case 0xc0: /* deauth */
wn->aid = 0;
wifi->status = Sunauth;
sendauth(wifi, wn);
break;
}
}
@ -318,9 +342,11 @@ wifietheroq(Wifi *wifi, Block *b)
{
Etherpkt e;
Wifipkt *w;
Wnode *bss;
SNAP *s;
if(BLEN(b) < ETHERHDRSIZE){
bss = wifi->bss;
if(bss == nil || BLEN(b) < ETHERHDRSIZE){
freeb(b);
return;
}
@ -332,7 +358,7 @@ wifietheroq(Wifi *wifi, Block *b)
w = (Wifipkt*)b->rp;
w->fc[0] = 0x08; /* data */
w->fc[1] = 0x01; /* STA->AP */
memmove(w->a1, wifi->bss ? wifi->bss->bssid : wifi->ether->bcast, Eaddrlen);
memmove(w->a1, bss->bssid, Eaddrlen);
memmove(w->a2, e.s, Eaddrlen);
memmove(w->a3, e.d, Eaddrlen);
@ -344,7 +370,7 @@ wifietheroq(Wifi *wifi, Block *b)
s->orgcode[2] = 0;
memmove(s->type, e.type, 2);
wifitx(wifi, b);
wifitx(wifi, bss, b);
}
static void
@ -364,6 +390,7 @@ wifoproc(void *arg)
Wifi*
wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*))
{
char name[32];
Wifi *wifi;
wifi = malloc(sizeof(Wifi));
@ -372,8 +399,10 @@ wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*))
wifi->transmit = transmit;
wifi->status = Snone;
kproc("wifi", wifiproc, wifi);
kproc("wifo", wifoproc, wifi);
snprint(name, sizeof(name), "#l%dwifi", ether->ctlrno);
kproc(name, wifiproc, wifi);
snprint(name, sizeof(name), "#l%dwifo", ether->ctlrno);
kproc(name, wifoproc, wifi);
return wifi;
}
@ -392,13 +421,13 @@ wifictl(Wifi *wifi, void *buf, long n)
cb = parsecmd(buf, n);
if(cb->f[0] && strcmp(cb->f[0], "essid") == 0){
if(cb->f[1] == nil){
/* TODO senddeauth(wifi); */
wifi->essid[0] = 0;
wifi->bss = nil;
wifi->status = Snone;
} else {
strncpy(wifi->essid, cb->f[1], 32);
wifi->essid[32] = 0;
for(wn=wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++)
for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++)
if(strcmp(wifi->essid, wn->ssid) == 0){
wifi->bss = wn;
wifi->status = Sconn;
@ -425,10 +454,11 @@ wifistat(Wifi *wifi, void *buf, long n, ulong off)
p = seprint(p, e, "status: %s\n", wifi->status);
p = seprint(p, e, "essid: %s\n", wifi->essid);
p = seprint(p, e, "bssid: %E\n", wifi->bss ? wifi->bss->bssid : zeros);
wn = wifi->bss;
p = seprint(p, e, "bssid: %E\n", wn != nil ? wn->bssid : zeros);
now = MACHP(0)->ticks;
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)
continue;
p = seprint(p, e, "node: %E %.4x %d %ld %d %s\n",

View file

@ -34,13 +34,13 @@ struct Wifi
Queue *iq;
char *status;
Ref txseq;
void (*transmit)(Wifi*, Wnode*, Block*);
Wnode node[16];
char essid[32+2];
Wnode *bss;
uint txseq;
char essid[32+2];
Wnode node[32];
};
Wifi *wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*));

View file

@ -812,7 +812,7 @@ dwrite(Req *req)
}
switch(lun->phase){
case Pcmd:
if(count != 6 && count != 10){
if(count != 6 && count != 10 && count != 12 && count != 16){
respond(req, "bad command length");
break;
}

View file

@ -79,7 +79,7 @@ struct Umsc
/* partitions */
Part part[Maxparts];
uchar rawcmd[10];
uchar rawcmd[16];
uchar phase;
char *inq;
Ums *ums;