diff options
| author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-02-12 14:28:22 +0100 |
|---|---|---|
| committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-02-12 14:28:22 +0100 |
| commit | 78fc90ec86481dac7d9528a446fa4624631e5a26 (patch) | |
| tree | c7765ef9fe81a3e7ab0f76b483efa279793ad672 | |
| parent | 8d271549cdc06d7c1cbc8496261be118e90f5e24 (diff) | |
| download | plan9front-78fc90ec86481dac7d9528a446fa4624631e5a26.tar.xz | |
etheriwl: support for WiFi Link 4965
| -rw-r--r-- | sys/src/9/pc/etheriwl.c | 160 |
1 files changed, 74 insertions, 86 deletions
diff --git a/sys/src/9/pc/etheriwl.c b/sys/src/9/pc/etheriwl.c index 9fff050bc..9e2b68860 100644 --- a/sys/src/9/pc/etheriwl.c +++ b/sys/src/9/pc/etheriwl.c @@ -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,9 @@ enum { enum { SchedCtxOff4965 = 0x380, SchedCtxLen4965 = 416, - SchedTransTblOff4965 = 0x500, SchedCtxOff5000 = 0x600, SchedCtxLen5000 = 512, - SchedTransTblOff5000 = 0x7e0, }; enum { @@ -253,8 +252,6 @@ typedef struct RXQ RXQ; typedef struct Ctlr Ctlr; -typedef struct Ctlrtype Ctlrtype; - struct FWSect { uchar *data; @@ -378,39 +375,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))) @@ -754,7 +728,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; @@ -776,7 +750,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; @@ -942,6 +916,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; } @@ -966,6 +941,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) @@ -1019,7 +1000,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"; @@ -1120,17 +1100,18 @@ flushq(Ctlr *ctlr, uint qid) static void -cmd(Ctlr *ctlr, uint code, uchar *data, int size) +flushcmd(Ctlr *ctlr) { - qcmd(ctlr, 4, code, data, size, nil); + flushq(ctlr, 4); } static void -flushcmd(Ctlr *ctlr) +cmd(Ctlr *ctlr, uint code, uchar *data, int size) { - flushq(ctlr, 4); + qcmd(ctlr, 4, code, data, size, nil); } + static void setled(Ctlr *ctlr, int which, int on, int off) { @@ -1173,8 +1154,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); @@ -1185,7 +1166,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); @@ -1217,25 +1198,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); } @@ -1266,15 +1248,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); } @@ -1344,6 +1326,7 @@ rxon(Ether *edev, Wnode *bss) p += 2; /* reserved */ } cmd(ctlr, 16, c, p - c); + if(ctlr->bcastnodeid == -1){ ctlr->bcastnodeid = (ctlr->type != Type4965) ? 15 : 31; addnode(ctlr, ctlr->bcastnodeid, edev->bcast); @@ -1617,10 +1600,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, @@ -1699,18 +1682,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); @@ -1820,9 +1805,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; @@ -1906,6 +1892,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; @@ -1940,7 +1928,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); |
