2 * Intel WiFi Link driver.
4 * Written without any documentation but Damien Bergaminis
5 * OpenBSD iwn(4) driver sources. Requires intel firmware
6 * to be present in /lib/firmware/iwn-* on attach.
10 #include "../port/lib.h"
15 #include "../port/error.h"
16 #include "../port/netif.h"
38 Cfg = 0x000, /* config register */
47 Isr = 0x008, /* interrupt status */
48 Imr = 0x00c, /* interrupt mask */
61 Ierr = Iswerr | Ihwerr,
62 Idefmask = Ierr | Ifhtx | Ifhrx | Ialive | Iwakeup | Iswrx | Ictreached | Irftoggled,
64 FhIsr = 0x010, /* second interrupt status */
68 Rev = 0x028, /* hardware revision */
70 EepromIo = 0x02c, /* EEPROM i/o register */
75 RelativeAccess = 1<<17,
77 EccUncorrStts = 1<<21,
79 Gpc = 0x024, /* gp cntrl */
100 UcodeGp1RfKill = 1<<1,
101 UcodeGp1CmdBlocked = 1<<2,
102 UcodeGp1CtempStopRf = 1<<3,
104 ShadowRegCtrl = 0x0a8,
113 Dbglinkpwrmgmt = 0x250,
125 HbusTargWptr = 0x460,
129 * Flow-Handler registers.
132 FhTfbdCtrl0 = 0x1900, // +q*8
133 FhTfbdCtrl1 = 0x1904, // +q*8
137 FhSramAddr = 0x19a4, // +q*4
138 FhCbbcQueue = 0x19d0, // +q*4
139 FhStatusWptr = 0x1bc0,
143 FhRxConfigEna = 1<<31,
144 FhRxConfigRbSize8K = 1<<16,
145 FhRxConfigSingleFrame = 1<<15,
146 FhRxConfigIrqDstHost = 1<<12,
147 FhRxConfigIgnRxfEmpty = 1<<2,
149 FhRxConfigNrbdShift = 20,
150 FhRxConfigRbTimeoutShift= 4,
154 FhTxConfig = 0x1d00, // +q*32
155 FhTxConfigDmaCreditEna = 1<<3,
156 FhTxConfigDmaEna = 1<<31,
157 FhTxConfigCirqHostEndTfd= 1<<20,
159 FhTxBufStatus = 0x1d08, // +q*32
160 FhTxBufStatusTbNumShift = 20,
161 FhTxBufStatusTbIdxShift = 12,
162 FhTxBufStatusTfbdValid = 3,
164 FhTxChicken = 0x1e98,
169 * NIC internal memory offsets.
172 ApmgClkCtrl = 0x3000,
179 EarlyPwroffDis = 1<<22,
185 ApmgDigitalSvr = 0x3058,
186 ApmgAnalogSvr = 0x306c,
189 BsmWrMemSrc = 0x3404,
190 BsmWrMemDst = 0x3408,
191 BsmWrDwCount = 0x340c,
192 BsmDramTextAddr = 0x3490,
193 BsmDramTextSize = 0x3494,
194 BsmDramDataAddr = 0x3498,
195 BsmDramDataSize = 0x349c,
196 BsmSramBase = 0x3800,
200 * TX scheduler registers.
203 SchedBase = 0xa02c00,
204 SchedSramAddr = SchedBase,
206 SchedDramAddr4965 = SchedBase+0x010,
207 SchedTxFact4965 = SchedBase+0x01c,
208 SchedQueueRdptr4965 = SchedBase+0x064, // +q*4
209 SchedQChainSel4965 = SchedBase+0x0d0,
210 SchedIntrMask4965 = SchedBase+0x0e4,
211 SchedQueueStatus4965 = SchedBase+0x104, // +q*4
213 SchedDramAddr5000 = SchedBase+0x008,
214 SchedTxFact5000 = SchedBase+0x010,
215 SchedQueueRdptr5000 = SchedBase+0x068, // +q*4
216 SchedQChainSel5000 = SchedBase+0x0e8,
217 SchedIntrMask5000 = SchedBase+0x108,
218 SchedQueueStatus5000 = SchedBase+0x10c, // +q*4
219 SchedAggrSel5000 = SchedBase+0x248,
223 SchedCtxOff4965 = 0x380,
224 SchedCtxLen4965 = 416,
226 SchedCtxOff5000 = 0x600,
227 SchedCtxLen5000 = 512,
231 FilterPromisc = 1<<0,
233 FilterMulticast = 1<<2,
234 FilterNoDecrypt = 1<<3,
244 RFlagShPreamble = 1<<5,
245 RFlagNoDiversity = 1<<7,
246 RFlagAntennaA = 1<<8,
247 RFlagAntennaB = 1<<9,
249 RFlagCTSToSelf = 1<<30,
252 typedef struct FWInfo FWInfo;
253 typedef struct FWImage FWImage;
254 typedef struct FWSect FWSect;
256 typedef struct TXQ TXQ;
257 typedef struct RXQ RXQ;
259 typedef struct Ctlr Ctlr;
335 /* assigned node ids in hardware node table or -1 if unassigned */
339 /* current receiver settings */
340 uchar bssid[Eaddrlen];
389 /* controller types */
402 static char *fwname[16] = {
403 [Type4965] "iwn-4965",
404 [Type5300] "iwn-5000",
405 [Type5350] "iwn-5000",
406 [Type5150] "iwn-5150",
407 [Type5100] "iwn-5000",
408 [Type1000] "iwn-1000",
409 [Type6000] "iwn-6000",
410 [Type6050] "iwn-6050",
411 [Type6005] "iwn-6005",
414 static char *qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block);
415 static char *flushq(Ctlr *ctlr, uint qid);
416 static char *cmd(Ctlr *ctlr, uint code, uchar *data, int size);
418 #define csr32r(c, r) (*((c)->nic+((r)/4)))
419 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
423 return *((u16int*)p);
427 return *((u32int*)p);
430 put32(uchar *p, uint v){
434 put16(uchar *p, uint v){
443 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq);
444 for(i=0; i<1000; i++){
445 if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna)
449 return "niclock: timeout";
453 nicunlock(Ctlr *ctlr)
455 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq);
459 prphread(Ctlr *ctlr, uint off)
461 csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off);
463 return csr32r(ctlr, PrphRdata);
466 prphwrite(Ctlr *ctlr, uint off, u32int data)
468 csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off);
470 csr32w(ctlr, PrphWdata, data);
474 memread(Ctlr *ctlr, uint off)
476 csr32w(ctlr, MemRaddr, off);
478 return csr32r(ctlr, MemRdata);
481 memwrite(Ctlr *ctlr, uint off, u32int data)
483 csr32w(ctlr, MemWaddr, off);
485 csr32w(ctlr, MemWdata, data);
489 setfwinfo(Ctlr *ctlr, uchar *d, int len)
502 i->logptr = get32(d); d += 4;
503 i->errptr = get32(d); d += 4;
504 i->tstamp = get32(d); d += 4;
514 print("lastcmd: %ud (0x%ux)\n", ctlr->tx[4].lastcmd, ctlr->tx[4].lastcmd);
515 if(ctlr->fwinfo.errptr == 0){
516 print("no error pointer\n");
519 for(i=0; i<nelem(dump); i++)
520 dump[i] = memread(ctlr, ctlr->fwinfo.errptr + i*4);
521 print( "error:\tid %ux, pc %ux,\n"
522 "\tbranchlink %.8ux %.8ux, interruptlink %.8ux %.8ux,\n"
523 "\terrordata %.8ux %.8ux, srcline %ud, tsf %ux, time %ux\n",
525 dump[4], dump[3], dump[6], dump[5],
526 dump[7], dump[8], dump[9], dump[10], dump[11]);
530 eepromlock(Ctlr *ctlr)
534 for(i=0; i<100; i++){
535 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | EepromLocked);
536 for(j=0; j<100; j++){
537 if(csr32r(ctlr, Cfg) & EepromLocked)
542 return "eepromlock: timeout";
545 eepromunlock(Ctlr *ctlr)
547 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) & ~EepromLocked);
550 eepromread(Ctlr *ctlr, void *data, int count, uint off)
557 off += ctlr->eeprom.off;
558 for(; count > 0; count -= 2, off++){
559 csr32w(ctlr, EepromIo, off << 2);
561 w = csr32r(ctlr, EepromIo);
567 return "eepromread: timeout";
568 if(ctlr->eeprom.otp){
569 s = csr32r(ctlr, OtpromGp);
570 if(s & EccUncorrStts)
571 return "eepromread: otprom ecc error";
573 csr32w(ctlr, OtpromGp, s);
587 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
589 if(csr32r(ctlr, Cfg) & NicReady)
593 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | Prepare);
594 for(i=0; i<15000; i++){
595 if((csr32r(ctlr, Cfg) & PrepareDone) == 0)
600 return "handover: timeout";
601 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
603 if(csr32r(ctlr, Cfg) & NicReady)
607 return "handover: timeout";
611 clockwait(Ctlr *ctlr)
615 /* Set "initialization complete" bit. */
616 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone);
617 for(i=0; i<2500; i++){
618 if(csr32r(ctlr, Gpc) & MacClockReady)
622 return "clockwait: timeout";
631 /* Disable L0s exit timer (NMI bug workaround). */
632 csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | DisL0Stimer);
634 /* Don't wait for ICH L0s (ICH bug workaround). */
635 csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | L1AnoL0Srx);
637 /* Set FH wait threshold to max (HW bug under stress workaround). */
638 csr32w(ctlr, Dbghpetmem, csr32r(ctlr, Dbghpetmem) | 0xffff0000);
640 /* Enable HAP INTA to move adapter from L1a to L0s. */
641 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | HapwakeL1A);
643 capoff = pcicap(ctlr->pdev, PciCapPCIe);
645 /* Workaround for HW instability in PCIe L0->L0s->L1 transition. */
646 if(pcicfgr16(ctlr->pdev, capoff + 0x10) & 0x2) /* LCSR -> L1 Entry enabled. */
647 csr32w(ctlr, Gio, csr32r(ctlr, Gio) | EnaL0S);
649 csr32w(ctlr, Gio, csr32r(ctlr, Gio) & ~EnaL0S);
652 if(ctlr->type != Type4965 && ctlr->type <= Type1000)
653 csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | 0x00880300);
655 /* Wait for clock stabilization before accessing prph. */
656 if((err = clockwait(ctlr)) != nil)
659 if((err = niclock(ctlr)) != nil)
662 /* Enable DMA and BSM (Bootstrap State Machine). */
663 if(ctlr->type == Type4965)
664 prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt);
666 prphwrite(ctlr, ApmgClkEna, DmaClkRqt);
669 /* Disable L1-Active. */
670 prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11));
684 csr32w(ctlr, Reset, 1);
686 /* Disable interrupts */
688 csr32w(ctlr, Imr, 0);
689 csr32w(ctlr, Isr, ~0);
690 csr32w(ctlr, FhIsr, ~0);
693 if(ctlr->type != Type4965)
694 prphwrite(ctlr, SchedTxFact5000, 0);
696 prphwrite(ctlr, SchedTxFact4965, 0);
699 if(niclock(ctlr) == nil){
700 for(i = (ctlr->type != Type4965) ? 7 : 6; i >= 0; i--){
701 csr32w(ctlr, FhTxConfig + i*32, 0);
702 for(j = 0; j < 200; j++){
703 if(csr32r(ctlr, FhTxStatus) & (0x10000<<i))
712 if(niclock(ctlr) == nil){
713 csr32w(ctlr, FhRxConfig, 0);
714 for(j = 0; j < 200; j++){
715 if(csr32r(ctlr, FhRxStatus) & 0x1000000)
723 if(niclock(ctlr) == nil){
724 prphwrite(ctlr, ApmgClkDis, DmaClkRqt);
729 /* Stop busmaster DMA activity. */
730 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | (1<<9));
731 for(j = 0; j < 100; j++){
732 if(csr32r(ctlr, Reset) & (1<<8))
737 /* Reset the entire device. */
738 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | (1<<7));
741 /* Clear "initialization complete" bit. */
742 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~InitDone);
755 ctlr->eeprom.otp = 0;
756 ctlr->eeprom.off = 0;
757 if(ctlr->type < Type1000 || (csr32r(ctlr, OtpromGp) & DevSelOtp) == 0)
760 /* Wait for clock stabilization before accessing prph. */
761 if((err = clockwait(ctlr)) != nil)
764 if((err = niclock(ctlr)) != nil)
766 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | ResetReq);
768 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) & ~ResetReq);
771 /* Set auto clock gate disable bit for HW with OTP shadow RAM. */
772 if(ctlr->type != Type1000)
773 csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31));
775 csr32w(ctlr, EepromGp, csr32r(ctlr, EepromGp) & ~0x00000180);
777 /* Clear ECC status. */
778 csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) | (EccCorrStts | EccUncorrStts));
780 ctlr->eeprom.otp = 1;
781 if(ctlr->type != Type1000)
784 /* Switch to absolute addressing mode. */
785 csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) & ~RelativeAccess);
788 * Find the block before last block (contains the EEPROM image)
789 * for HW without OTP shadow RAM.
793 if((err = eepromread(ctlr, buf, 2, last)) != nil)
801 return "rominit: missing eeprom image";
803 ctlr->eeprom.off = prev+1;
813 uint u, caloff, regoff;
816 if((err = handover(ctlr)) != nil)
818 if((err = poweron(ctlr)) != nil)
820 if((csr32r(ctlr, EepromGp) & 0x7) == 0){
821 err = "bad rom signature";
824 if((err = eepromlock(ctlr)) != nil)
826 if((err = rominit(ctlr)) != nil)
828 if((err = eepromread(ctlr, edev->ea, sizeof(edev->ea), 0x15)) != nil){
832 if((err = eepromread(ctlr, b, 2, 0x048)) != nil){
838 ctlr->rfcfg.type = u & 3; u >>= 2;
839 ctlr->rfcfg.step = u & 3; u >>= 2;
840 ctlr->rfcfg.dash = u & 3; u >>= 4;
841 ctlr->rfcfg.txantmask = u & 15; u >>= 4;
842 ctlr->rfcfg.rxantmask = u & 15;
843 if((err = eepromread(ctlr, b, 2, 0x66)) != nil)
846 if((err = eepromread(ctlr, b, 4, regoff+1)) != nil)
848 strncpy(ctlr->eeprom.regdom, (char*)b, 4);
849 ctlr->eeprom.regdom[4] = 0;
850 if((err = eepromread(ctlr, b, 2, 0x67)) != nil)
853 if((err = eepromread(ctlr, b, 4, caloff)) != nil)
855 ctlr->eeprom.version = b[0];
856 ctlr->eeprom.type = b[1];
857 ctlr->eeprom.volt = get16(b+2);
858 if(ctlr->type != Type4965 && ctlr->type != Type5150){
859 if((err = eepromread(ctlr, b, 4, caloff + 0x128)) != nil)
861 ctlr->eeprom.crystal = get32(b);
867 ctlr->rfcfg.txantmask = 3;
868 ctlr->rfcfg.rxantmask = 7;
871 ctlr->rfcfg.txantmask = 2;
872 ctlr->rfcfg.rxantmask = 3;
875 if(ctlr->pdev->did == 0x422c || ctlr->pdev->did == 0x4230){
876 ctlr->rfcfg.txantmask = 6;
877 ctlr->rfcfg.rxantmask = 6;
884 print("iwlinit: %s\n", err);
890 crackfw(FWImage *i, uchar *data, uint size, int alt)
895 memset(i, 0, sizeof(*i));
898 return "firmware image too short";
902 i->rev = get32(p); p += 4;
906 if(size < (4+64+4+4+8))
908 if(memcmp(p, "IWL\n", 4) != 0)
909 return "bad firmware signature";
911 strncpy(i->descr, (char*)p, 64);
914 i->rev = get32(p); p += 4;
915 i->build = get32(p); p += 4;
916 altmask = get32(p); p += 4;
917 altmask |= (uvlong)get32(p) << 32; p += 4;
918 while(alt > 0 && (altmask & (1ULL<<alt)) == 0)
926 case 1: s = &i->main.text; break;
927 case 2: s = &i->main.data; break;
928 case 3: s = &i->init.text; break;
929 case 4: s = &i->init.data; break;
930 case 5: s = &i->boot.text; break;
934 if(get16(p) != 0 && get16(p) != alt)
937 s->size = get32(p); p += 4;
939 if((p + s->size) > e)
941 p += (s->size + 3) & ~3;
944 if(((i->rev>>8) & 0xFF) < 2)
945 return "need firmware api >= 2";
946 if(((i->rev>>8) & 0xFF) >= 3){
947 i->build = get32(p); p += 4;
951 i->main.text.size = get32(p); p += 4;
952 i->main.data.size = get32(p); p += 4;
953 i->init.text.size = get32(p); p += 4;
954 i->init.data.size = get32(p); p += 4;
955 i->boot.text.size = get32(p); p += 4;
956 i->main.text.data = p; p += i->main.text.size;
957 i->main.data.data = p; p += i->main.data.size;
958 i->init.text.data = p; p += i->init.text.size;
959 i->init.data.data = p; p += i->init.data.size;
960 i->boot.text.data = p; p += i->boot.text.size;
968 readfirmware(char *name)
970 uchar dirbuf[sizeof(Dir)+100], *data;
980 snprint(buf, sizeof buf, "/boot/%s", name);
981 c = namec(buf, Aopen, OREAD, 0);
984 snprint(buf, sizeof buf, "/lib/firmware/%s", name);
985 c = namec(buf, Aopen, OREAD, 0);
991 n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf);
993 error("can't stat firmware");
994 convM2D(dirbuf, n, &d, nil);
995 fw = smalloc(sizeof(*fw) + 16 + d.length);
996 data = (uchar*)(fw+1);
1002 while(r < d.length){
1003 n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r);
1008 if((err = crackfw(fw, data, r, 1)) != nil)
1021 return (ctlr->wait.m & ctlr->wait.w) != 0;
1025 irqwait(Ctlr *ctlr, u32int mask, int timeout)
1030 r = ctlr->wait.m & mask;
1032 ctlr->wait.w = mask;
1035 tsleep(&ctlr->wait, gotirq, ctlr, timeout);
1040 r = ctlr->wait.m & mask;
1048 rbplant(Ctlr *ctlr, int i)
1052 b = iallocb(Rbufsize + 256);
1055 b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, 256);
1056 memset(b->rp, 0, Rdscsize);
1058 ctlr->rx.p[i] = PCIWADDR(b->rp) >> 8;
1063 initring(Ctlr *ctlr)
1071 rx->b = malloc(sizeof(Block*) * Nrx);
1073 rx->p = mallocalign(sizeof(u32int) * Nrx, 256, 0, 0);
1075 rx->s = mallocalign(Rstatsize, 16, 0, 0);
1076 if(rx->b == nil || rx->p == nil || rx->s == nil)
1077 return "no memory for rx ring";
1078 memset(ctlr->rx.s, 0, Rstatsize);
1079 for(i=0; i<Nrx; i++){
1081 if(rx->b[i] != nil){
1085 if(rbplant(ctlr, i) < 0)
1086 return "no memory for rx descriptors";
1090 if(ctlr->sched.s == nil)
1091 ctlr->sched.s = mallocalign(512 * nelem(ctlr->tx) * 2, 1024, 0, 0);
1092 if(ctlr->sched.s == nil)
1093 return "no memory for sched buffer";
1094 memset(ctlr->sched.s, 0, 512 * nelem(ctlr->tx));
1096 for(q=0; q<nelem(ctlr->tx); q++){
1099 tx->b = malloc(sizeof(Block*) * Ntx);
1101 tx->d = mallocalign(Tdscsize * Ntx, 256, 0, 0);
1103 tx->c = mallocalign(Tcmdsize * Ntx, 4, 0, 0);
1104 if(tx->b == nil || tx->d == nil || tx->c == nil)
1105 return "no memory for tx ring";
1106 memset(tx->d, 0, Tdscsize * Ntx);
1107 memset(tx->c, 0, Tcmdsize * Ntx);
1108 for(i=0; i<Ntx; i++){
1109 if(tx->b[i] != nil){
1119 if(ctlr->kwpage == nil)
1120 ctlr->kwpage = mallocalign(4096, 4096, 0, 0);
1121 if(ctlr->kwpage == nil)
1122 return "no memory for kwpage";
1123 memset(ctlr->kwpage, 0, 4096);
1136 if((err = initring(ctlr)) != nil)
1138 if((err = poweron(ctlr)) != nil)
1141 if((err = niclock(ctlr)) != nil)
1143 prphwrite(ctlr, ApmgPs, (prphread(ctlr, ApmgPs) & ~PwrSrcMask) | PwrSrcVMain);
1146 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | RadioSi | MacSi);
1148 if((err = niclock(ctlr)) != nil)
1150 if(ctlr->type != Type4965)
1151 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | EarlyPwroffDis);
1152 if(ctlr->type == Type1000){
1154 * Select first Switching Voltage Regulator (1.32V) to
1155 * solve a stability issue related to noisy DC2DC line
1156 * in the silicon of 1000 Series.
1158 prphwrite(ctlr, ApmgDigitalSvr,
1159 (prphread(ctlr, ApmgDigitalSvr) & ~(0xf<<5)) | (3<<5));
1163 if((err = niclock(ctlr)) != nil)
1165 if((ctlr->type == Type6005 || ctlr->type == Type6050) && ctlr->eeprom.version == 6)
1166 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvCalV6);
1167 if(ctlr->type == Type6005)
1168 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrv1X2);
1171 if((err = niclock(ctlr)) != nil)
1173 csr32w(ctlr, FhRxConfig, 0);
1174 csr32w(ctlr, FhRxWptr, 0);
1175 csr32w(ctlr, FhRxBase, PCIWADDR(ctlr->rx.p) >> 8);
1176 csr32w(ctlr, FhStatusWptr, PCIWADDR(ctlr->rx.s) >> 4);
1177 csr32w(ctlr, FhRxConfig,
1179 FhRxConfigIgnRxfEmpty |
1180 FhRxConfigIrqDstHost |
1181 FhRxConfigSingleFrame |
1182 (Nrxlog << FhRxConfigNrbdShift));
1183 csr32w(ctlr, FhRxWptr, (Nrx-1) & ~7);
1186 if((err = niclock(ctlr)) != nil)
1188 if(ctlr->type != Type4965)
1189 prphwrite(ctlr, SchedTxFact5000, 0);
1191 prphwrite(ctlr, SchedTxFact4965, 0);
1192 csr32w(ctlr, FhKwAddr, PCIWADDR(ctlr->kwpage) >> 4);
1193 for(q = (ctlr->type != Type4965) ? 19 : 15; q >= 0; q--)
1194 csr32w(ctlr, FhCbbcQueue + q*4, PCIWADDR(ctlr->tx[q].d) >> 8);
1197 for(i = (ctlr->type != Type4965) ? 7 : 6; i >= 0; i--)
1198 csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna);
1200 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
1201 csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
1207 ctlr->ie = Idefmask;
1208 csr32w(ctlr, Imr, ctlr->ie);
1209 csr32w(ctlr, Isr, ~0);
1211 if(ctlr->type >= Type6000)
1212 csr32w(ctlr, ShadowRegCtrl, csr32r(ctlr, ShadowRegCtrl) | 0x800fffff);
1218 postboot(Ctlr *ctlr)
1220 uint ctxoff, ctxlen, dramaddr;
1224 if((err = niclock(ctlr)) != nil)
1227 if(ctlr->type != Type4965){
1228 dramaddr = SchedDramAddr5000;
1229 ctxoff = SchedCtxOff5000;
1230 ctxlen = SchedCtxLen5000;
1232 dramaddr = SchedDramAddr4965;
1233 ctxoff = SchedCtxOff4965;
1234 ctxlen = SchedCtxLen4965;
1237 ctlr->sched.base = prphread(ctlr, SchedSramAddr);
1238 for(i=0; i < ctxlen; i += 4)
1239 memwrite(ctlr, ctlr->sched.base + ctxoff + i, 0);
1241 prphwrite(ctlr, dramaddr, PCIWADDR(ctlr->sched.s)>>10);
1243 csr32w(ctlr, FhTxChicken, csr32r(ctlr, FhTxChicken) | 2);
1245 if(ctlr->type != Type4965){
1246 /* Enable chain mode for all queues, except command queue 4. */
1247 prphwrite(ctlr, SchedQChainSel5000, 0xfffef);
1248 prphwrite(ctlr, SchedAggrSel5000, 0);
1250 for(q=0; q<20; q++){
1251 prphwrite(ctlr, SchedQueueRdptr5000 + q*4, 0);
1252 csr32w(ctlr, HbusTargWptr, q << 8);
1254 memwrite(ctlr, ctlr->sched.base + ctxoff + q*8, 0);
1255 /* Set scheduler window size and frame limit. */
1256 memwrite(ctlr, ctlr->sched.base + ctxoff + q*8 + 4, 64<<16 | 64);
1258 /* Enable interrupts for all our 20 queues. */
1259 prphwrite(ctlr, SchedIntrMask5000, 0xfffff);
1261 /* Identify TX FIFO rings (0-7). */
1262 prphwrite(ctlr, SchedTxFact5000, 0xff);
1264 /* Disable chain mode for all our 16 queues. */
1265 prphwrite(ctlr, SchedQChainSel4965, 0);
1267 for(q=0; q<16; q++) {
1268 prphwrite(ctlr, SchedQueueRdptr4965 + q*4, 0);
1269 csr32w(ctlr, HbusTargWptr, q << 8);
1271 /* Set scheduler window size. */
1272 memwrite(ctlr, ctlr->sched.base + ctxoff + q*8, 64);
1273 /* Set scheduler window size and frame limit. */
1274 memwrite(ctlr, ctlr->sched.base + ctxoff + q*8 + 4, 64<<16);
1276 /* Enable interrupts for all our 16 queues. */
1277 prphwrite(ctlr, SchedIntrMask4965, 0xffff);
1279 /* Identify TX FIFO rings (0-7). */
1280 prphwrite(ctlr, SchedTxFact4965, 0xff);
1283 /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
1285 if(ctlr->type != Type4965){
1286 static uchar qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
1287 prphwrite(ctlr, SchedQueueStatus5000 + q*4, 0x00ff0018 | qid2fifo[q]);
1289 static uchar qid2fifo[] = { 3, 2, 1, 0, 4, 5, 6 };
1290 prphwrite(ctlr, SchedQueueStatus4965 + q*4, 0x0007fc01 | qid2fifo[q]<<1);
1295 if(ctlr->type != Type4965){
1298 /* disable wimax coexistance */
1299 memset(c, 0, sizeof(c));
1300 if((err = cmd(ctlr, 90, c, 4+4*16)) != nil)
1303 if(ctlr->type != Type5150){
1304 /* calibrate crystal */
1305 memset(c, 0, sizeof(c));
1306 c[0] = 15; /* code */
1307 c[1] = 0; /* group */
1308 c[2] = 1; /* ngroup */
1309 c[3] = 1; /* isvalid */
1310 c[4] = ctlr->eeprom.crystal;
1311 c[5] = ctlr->eeprom.crystal>>16;
1312 /* for some reason 8086:4238 needs a second try */
1313 if(cmd(ctlr, 176, c, 8) != nil && (err = cmd(ctlr, 176, c, 8)) != nil)
1317 if(ctlr->calib.done == 0){
1318 /* query calibration (init firmware) */
1319 memset(c, 0, sizeof(c));
1320 put32(c + 0*(5*4) + 0, 0xffffffff);
1321 put32(c + 0*(5*4) + 4, 0xffffffff);
1322 put32(c + 0*(5*4) + 8, 0xffffffff);
1323 put32(c + 2*(5*4) + 0, 0xffffffff);
1324 if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil)
1327 /* wait to collect calibration records */
1328 if(irqwait(ctlr, Ierr, 2000))
1329 return "calibration failed";
1331 if(ctlr->calib.done == 0){
1332 print("iwl: no calibration results\n");
1333 ctlr->calib.done = 1;
1336 static uchar cmds[] = {8, 9, 11, 17, 16};
1338 /* send calibration records (runtime firmware) */
1339 for(q=0; q<nelem(cmds); q++){
1343 if(i == 8 && ctlr->type != Type5150)
1345 if(i == 17 && (ctlr->type >= Type6000 || ctlr->type == Type5150))
1347 if((b = ctlr->calib.cmd[i]) == nil)
1349 b->ref++; /* dont free on command completion */
1350 if((err = qcmd(ctlr, 4, 176, nil, 0, b)) != nil){
1354 if((err = flushq(ctlr, 4)) != nil)
1358 if(ctlr->type == Type6005){
1359 /* temperature sensor offset */
1360 memset(c, 0, sizeof(c));
1366 if((err = cmd(ctlr, 176, c, 4+2+2)) != nil)
1370 if(ctlr->type == Type6005 || ctlr->type == Type6050){
1371 /* runtime DC calibration */
1372 memset(c, 0, sizeof(c));
1373 put32(c + 0*(5*4) + 0, 0xffffffff);
1374 put32(c + 0*(5*4) + 4, 1<<1);
1375 if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil)
1379 /* set tx antenna config */
1380 put32(c, ctlr->rfcfg.txantmask & 7);
1381 if((err = cmd(ctlr, 152, c, 4)) != nil)
1390 loadfirmware1(Ctlr *ctlr, u32int dst, uchar *data, int size)
1395 dma = mallocalign(size, 16, 0, 0);
1397 return "no memory for dma";
1398 memmove(dma, data, size);
1400 if((err = niclock(ctlr)) != 0){
1404 csr32w(ctlr, FhTxConfig + 9*32, 0);
1405 csr32w(ctlr, FhSramAddr + 9*4, dst);
1406 csr32w(ctlr, FhTfbdCtrl0 + 9*8, PCIWADDR(dma));
1407 csr32w(ctlr, FhTfbdCtrl1 + 9*8, size);
1408 csr32w(ctlr, FhTxBufStatus + 9*32,
1409 (1<<FhTxBufStatusTbNumShift) |
1410 (1<<FhTxBufStatusTbIdxShift) |
1411 FhTxBufStatusTfbdValid);
1412 csr32w(ctlr, FhTxConfig + 9*32, FhTxConfigDmaEna | FhTxConfigCirqHostEndTfd);
1414 if(irqwait(ctlr, Ifhtx|Ierr, 5000) != Ifhtx){
1416 return "dma error / timeout";
1432 if(fw->boot.text.size == 0){
1433 if(ctlr->calib.done == 0){
1434 if((err = loadfirmware1(ctlr, 0x00000000, fw->init.text.data, fw->init.text.size)) != nil)
1436 if((err = loadfirmware1(ctlr, 0x00800000, fw->init.data.data, fw->init.data.size)) != nil)
1438 csr32w(ctlr, Reset, 0);
1439 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive)
1440 return "init firmware boot failed";
1441 if((err = postboot(ctlr)) != nil)
1443 if((err = reset(ctlr)) != nil)
1446 if((err = loadfirmware1(ctlr, 0x00000000, fw->main.text.data, fw->main.text.size)) != nil)
1448 if((err = loadfirmware1(ctlr, 0x00800000, fw->main.data.data, fw->main.data.size)) != nil)
1450 csr32w(ctlr, Reset, 0);
1451 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive)
1452 return "main firmware boot failed";
1453 return postboot(ctlr);
1456 size = ROUND(fw->init.data.size, 16) + ROUND(fw->init.text.size, 16);
1457 dma = mallocalign(size, 16, 0, 0);
1459 return "no memory for dma";
1461 if((err = niclock(ctlr)) != nil){
1467 memmove(p, fw->init.data.data, fw->init.data.size);
1469 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
1470 prphwrite(ctlr, BsmDramDataSize, fw->init.data.size);
1471 p += ROUND(fw->init.data.size, 16);
1472 memmove(p, fw->init.text.data, fw->init.text.size);
1474 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
1475 prphwrite(ctlr, BsmDramTextSize, fw->init.text.size);
1478 if((err = niclock(ctlr)) != nil){
1483 p = fw->boot.text.data;
1484 n = fw->boot.text.size/4;
1485 for(i=0; i<n; i++, p += 4)
1486 prphwrite(ctlr, BsmSramBase+i*4, get32(p));
1488 prphwrite(ctlr, BsmWrMemSrc, 0);
1489 prphwrite(ctlr, BsmWrMemDst, 0);
1490 prphwrite(ctlr, BsmWrDwCount, n);
1492 prphwrite(ctlr, BsmWrCtrl, 1<<31);
1494 for(i=0; i<1000; i++){
1495 if((prphread(ctlr, BsmWrCtrl) & (1<<31)) == 0)
1502 return "bootcode timeout";
1505 prphwrite(ctlr, BsmWrCtrl, 1<<30);
1508 csr32w(ctlr, Reset, 0);
1509 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
1511 return "init firmware boot failed";
1515 size = ROUND(fw->main.data.size, 16) + ROUND(fw->main.text.size, 16);
1516 dma = mallocalign(size, 16, 0, 0);
1518 return "no memory for dma";
1519 if((err = niclock(ctlr)) != nil){
1524 memmove(p, fw->main.data.data, fw->main.data.size);
1526 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
1527 prphwrite(ctlr, BsmDramDataSize, fw->main.data.size);
1528 p += ROUND(fw->main.data.size, 16);
1529 memmove(p, fw->main.text.data, fw->main.text.size);
1531 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
1532 prphwrite(ctlr, BsmDramTextSize, fw->main.text.size | (1<<31));
1535 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
1537 return "main firmware boot failed";
1540 return postboot(ctlr);
1551 qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
1556 assert(qid < nelem(ctlr->tx));
1557 assert(size <= Tcmdsize-4);
1561 while(q->n >= Ntx && !ctlr->broken){
1565 tsleep(q, txqready, q, 10);
1573 return "qcmd: broken";
1579 c = q->c + q->i * Tcmdsize;
1580 d = q->d + q->i * Tdscsize;
1584 c[1] = 0; /* flags */
1589 memmove(c+4, data, size);
1593 /* build descriptor */
1597 *d++ = 1 + (block != nil); /* nsegs */
1598 put32(d, PCIWADDR(c)); d += 4;
1599 put16(d, size << 4); d += 2;
1602 put32(d, PCIWADDR(block->rp)); d += 4;
1603 put16(d, size << 4);
1608 q->i = (q->i+1) % Ntx;
1609 csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i);
1624 flushq(Ctlr *ctlr, uint qid)
1631 for(i = 0; i < 200 && !ctlr->broken; i++){
1637 tsleep(q, txqempty, q, 10);
1643 return "flushq: broken";
1644 return "flushq: timeout";
1648 cmd(Ctlr *ctlr, uint code, uchar *data, int size)
1652 if(0) print("cmd %ud\n", code);
1653 if((err = qcmd(ctlr, 4, code, data, size, nil)) != nil)
1655 return flushq(ctlr, 4);
1659 setled(Ctlr *ctlr, int which, int on, int off)
1663 csr32w(ctlr, Led, csr32r(ctlr, Led) & ~LedBsmCtrl);
1665 memset(c, 0, sizeof(c));
1670 cmd(ctlr, 72, c, sizeof(c));
1674 addnode(Ctlr *ctlr, uchar id, uchar *addr)
1676 uchar c[Tcmdsize], *p;
1678 memset(p = c, 0, sizeof(c));
1679 *p++ = 0; /* control (1 = update) */
1680 p += 3; /* reserved */
1681 memmove(p, addr, 6);
1683 p += 2; /* reserved */
1684 *p++ = id; /* node id */
1686 p += 2; /* reserved */
1687 p += 2; /* kflags */
1690 p += 5*2; /* ttak */
1694 if(ctlr->type != Type4965){
1699 p += 4; /* htflags */
1701 p += 2; /* disable tid */
1702 p += 2; /* reserved */
1703 p++; /* add ba tid */
1704 p++; /* del ba tid */
1705 p += 2; /* add ba ssn */
1706 p += 4; /* reserved */
1707 cmd(ctlr, 24, c, p - c);
1711 rxon(Ether *edev, Wnode *bss)
1713 uchar c[Tcmdsize], *p;
1719 filter = FilterNoDecrypt | FilterMulticast | FilterBeacon;
1721 filter |= FilterPromisc;
1723 ctlr->channel = bss->channel;
1727 ctlr->channel = bss->channel;
1728 memmove(ctlr->bssid, bss->bssid, Eaddrlen);
1729 ctlr->aid = bss->aid;
1731 filter |= FilterBSS;
1732 filter &= ~FilterBeacon;
1733 ctlr->bssnodeid = -1;
1735 ctlr->bcastnodeid = -1;
1737 memmove(ctlr->bssid, edev->bcast, Eaddrlen);
1739 ctlr->bcastnodeid = -1;
1740 ctlr->bssnodeid = -1;
1742 flags = RFlagTSF | RFlagCTSToSelf | RFlag24Ghz | RFlagAuto;
1745 setled(ctlr, 2, 0, 1); /* on when associated */
1746 else if(memcmp(ctlr->bssid, edev->bcast, Eaddrlen) != 0)
1747 setled(ctlr, 2, 10, 10); /* slow blink when connecting */
1749 setled(ctlr, 2, 5, 5); /* fast blink when scanning */
1751 if(ctlr->wifi->debug)
1752 print("#l%d: rxon: bssid %E, aid %x, channel %d, filter %x, flags %x\n",
1753 edev->ctlrno, ctlr->bssid, ctlr->aid, ctlr->channel, filter, flags);
1755 memset(p = c, 0, sizeof(c));
1756 memmove(p, edev->ea, 6); p += 8; /* myaddr */
1757 memmove(p, ctlr->bssid, 6); p += 8; /* bssid */
1758 memmove(p, edev->ea, 6); p += 8; /* wlap */
1759 *p++ = 3; /* mode (STA) */
1760 *p++ = 0; /* air (?) */
1762 put16(p, ((ctlr->rfcfg.rxantmask & 7)<<1) | (2<<10) | (2<<12));
1764 *p++ = 0xff; /* ofdm mask (not yet negotiated) */
1765 *p++ = 0x0f; /* cck mask (not yet negotiated) */
1766 put16(p, ctlr->aid & 0x3fff);
1772 *p++ = ctlr->channel;
1774 *p++ = 0xff; /* ht single mask */
1775 *p++ = 0xff; /* ht dual mask */
1776 if(ctlr->type != Type4965){
1777 *p++ = 0xff; /* ht triple mask */
1779 put16(p, 0); p += 2; /* acquisition */
1780 p += 2; /* reserved */
1782 if((err = cmd(ctlr, 16, c, p - c)) != nil){
1783 print("rxon: %s\n", err);
1787 if(ctlr->bcastnodeid == -1){
1788 ctlr->bcastnodeid = (ctlr->type != Type4965) ? 15 : 31;
1789 addnode(ctlr, ctlr->bcastnodeid, edev->bcast);
1791 if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){
1792 ctlr->bssnodeid = 0;
1793 addnode(ctlr, ctlr->bssnodeid, bss->bssid);
1797 static struct ratetab {
1802 { 2, 10, RFlagCCK },
1803 { 4, 20, RFlagCCK },
1804 { 11, 55, RFlagCCK },
1805 { 22, 110, RFlagCCK },
1817 static uchar iwlrates[] = {
1836 TFlagNeedProtection = 1<<0,
1837 TFlagNeedRTS = 1<<1,
1838 TFlagNeedCTS = 1<<2,
1839 TFlagNeedACK = 1<<3,
1842 TFlagFullTxOp = 1<<7,
1844 TFlagAutoSeq = 1<<13,
1845 TFlagMoreFrag = 1<<14,
1846 TFlagInsertTs = 1<<16,
1847 TFlagNeedPadding = 1<<20,
1851 transmit(Wifi *wifi, Wnode *wn, Block *b)
1853 int flags, nodeid, rate, ant;
1854 uchar c[Tcmdsize], *p;
1864 if(ctlr->attached == 0 || ctlr->broken){
1870 if((wn->channel != ctlr->channel)
1871 || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0)))
1875 /* association note has no data to transmit */
1881 nodeid = ctlr->bcastnodeid;
1883 w = (Wifipkt*)b->rp;
1884 if((w->a1[0] & 1) == 0){
1885 flags |= TFlagNeedACK;
1888 flags |= TFlagNeedRTS;
1890 if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){
1891 nodeid = ctlr->bssnodeid;
1895 if(flags & (TFlagNeedRTS|TFlagNeedCTS)){
1896 if(ctlr->type != Type4965){
1897 flags &= ~(TFlagNeedRTS|TFlagNeedCTS);
1898 flags |= TFlagNeedProtection;
1900 flags |= TFlagFullTxOp;
1906 if(p >= iwlrates && p < &iwlrates[nelem(ratetab)])
1907 rate = p - iwlrates;
1909 /* select first available antenna */
1910 ant = ctlr->rfcfg.txantmask & 7;
1912 ant = ((ant - 1) & ant) ^ ant;
1914 memset(p = c, 0, sizeof(c));
1921 p += 4; /* scratch */
1923 *p++ = ratetab[rate].plcp;
1924 *p++ = ratetab[rate].flags | (ant<<6);
1926 p += 2; /* xflags */
1928 *p++ = 0; /* security */
1929 *p++ = 0; /* linkq */
1933 p += 2; /* reserved */
1934 put32(p, ~0); /* lifetime */
1937 /* BUG: scratch ptr? not clear what this is for */
1938 put32(p, PCIWADDR(ctlr->kwpage));
1941 *p++ = 60; /* rts ntries */
1942 *p++ = 15; /* data ntries */
1944 put16(p, 0); /* timeout */
1947 if((err = qcmd(ctlr, 0, 28, c, p - c, b)) != nil){
1948 print("transmit: %s\n", err);
1954 iwlctl(Ether *edev, void *buf, long n)
1960 return wifictl(ctlr->wifi, buf, n);
1965 iwlifstat(Ether *edev, void *buf, long n, ulong off)
1971 return wifistat(ctlr->wifi, buf, n, off);
1976 setoptions(Ether *edev)
1983 for(i = 0; i < edev->nopt; i++){
1984 snprint(buf, sizeof(buf), "%s", edev->opt[i]);
1985 p = strchr(buf, '=');
1988 if(strcmp(buf, "debug") == 0
1989 || strcmp(buf, "essid") == 0
1990 || strcmp(buf, "bssid") == 0){
1994 wifictl(ctlr->wifi, buf, strlen(buf));
2002 iwlpromiscuous(void *arg, int on)
2011 rxon(edev, ctlr->wifi->bss);
2016 iwlrecover(void *arg)
2026 tsleep(&up->sleep, return0, 0, 4000);
2030 if(ctlr->broken == 0)
2036 if((csr32r(ctlr, Gpc) & RfKill) == 0)
2039 if(reset(ctlr) != nil)
2041 if(boot(ctlr) != nil)
2044 ctlr->bcastnodeid = -1;
2045 ctlr->bssnodeid = -1;
2047 rxon(edev, ctlr->wifi->bss);
2055 iwlattach(Ether *edev)
2064 print("#l%d: %s\n", edev->ctlrno, up->errstr);
2070 if(ctlr->attached == 0){
2071 if((csr32r(ctlr, Gpc) & RfKill) == 0)
2072 error("wifi disabled by switch");
2074 if(ctlr->wifi == nil){
2075 ctlr->wifi = wifiattach(edev, transmit);
2076 ctlr->wifi->rates = iwlrates;
2079 if(ctlr->fw == nil){
2080 fw = readfirmware(fwname[ctlr->type]);
2081 print("#l%d: firmware: %s, rev %ux, build %ud, size %ux+%ux+%ux+%ux+%ux\n",
2085 fw->main.text.size, fw->main.data.size,
2086 fw->init.text.size, fw->init.data.size,
2087 fw->boot.text.size);
2091 if((err = reset(ctlr)) != nil)
2093 if((err = boot(ctlr)) != nil)
2096 ctlr->bcastnodeid = -1;
2097 ctlr->bssnodeid = -1;
2105 kproc("iwlrecover", iwlrecover, edev);
2121 if(ctlr->broken || rx->s == nil || rx->b == nil)
2123 for(hw = get16(rx->s) % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){
2124 uchar type, flags, idx, qid;
2132 len = get32(d); d += 4;
2139 if((qid & 0x80) == 0 && qid < nelem(ctlr->tx)){
2140 tx = &ctlr->tx[qid];
2147 /* paranoia: clear tx descriptors */
2148 dd = tx->d + idx*Tdscsize;
2149 cc = tx->c + idx*Tcmdsize;
2150 memset(dd, 0, Tdscsize);
2151 memset(cc, 0, Tcmdsize);
2159 if(len < 4 || type == 0)
2164 case 1: /* microcontroller ready */
2165 setfwinfo(ctlr, d, len);
2167 case 24: /* add node done */
2169 case 28: /* tx done */
2171 case 102: /* calibration result (Type5000 only) */
2175 if(idx >= nelem(ctlr->calib.cmd))
2177 if(rbplant(ctlr, rx->i) < 0)
2179 if(ctlr->calib.cmd[idx] != nil)
2180 freeb(ctlr->calib.cmd[idx]);
2183 ctlr->calib.cmd[idx] = b;
2185 case 103: /* calibration done (Type5000 only) */
2186 ctlr->calib.done = 1;
2188 case 130: /* start scan */
2190 case 132: /* stop scan */
2192 case 156: /* rx statistics */
2194 case 157: /* beacon statistics */
2196 case 161: /* state changed */
2198 case 162: /* beacon missed */
2200 case 192: /* rx phy */
2202 case 195: /* rx done */
2207 case 193: /* mpdu rx done */
2210 len = get16(d); d += 4;
2211 if(d + len + 4 > b->lim)
2213 if((get32(d + len) & 3) != 3)
2215 if(ctlr->wifi == nil)
2217 if(rbplant(ctlr, rx->i) < 0)
2221 wifiiq(ctlr->wifi, b);
2223 case 197: /* rx compressed ba */
2226 /* paranoia: clear the descriptor */
2227 memset(b->rp, 0, Rdscsize);
2229 csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7);
2233 iwlinterrupt(Ureg*, void *arg)
2242 csr32w(ctlr, Imr, 0);
2243 isr = csr32r(ctlr, Isr);
2244 fhisr = csr32r(ctlr, FhIsr);
2245 if(isr == 0xffffffff || (isr & 0xfffffff0) == 0xa5a5a5a0){
2249 if(isr == 0 && fhisr == 0)
2251 csr32w(ctlr, Isr, isr);
2252 csr32w(ctlr, FhIsr, fhisr);
2253 if((isr & (Iswrx | Ifhrx | Irxperiodic)) || (fhisr & Ifhrx))
2257 print("#l%d: fatal firmware error\n", edev->ctlrno);
2260 ctlr->wait.m |= isr;
2261 if(ctlr->wait.m & ctlr->wait.w)
2262 wakeup(&ctlr->wait);
2264 csr32w(ctlr, Imr, ctlr->ie);
2269 iwlshutdown(Ether *edev)
2279 static Ctlr *iwlhead, *iwltail;
2287 while(pdev = pcimatch(pdev, 0, 0)) {
2291 if(pdev->ccrb != 2 || pdev->ccru != 0x80)
2293 if(pdev->vid != 0x8086)
2299 case 0x0084: /* WiFi Link 1000 */
2300 case 0x4229: /* WiFi Link 4965 */
2301 case 0x4230: /* WiFi Link 4965 */
2302 case 0x4232: /* Wifi Link 5100 */
2303 case 0x4236: /* WiFi Link 5300 AGN */
2304 case 0x4237: /* Wifi Link 5100 AGN */
2305 case 0x423d: /* Wifi Link 5150 */
2306 case 0x0085: /* Centrino Advanced-N 6205 */
2307 case 0x422b: /* Centrino Ultimate-N 6300 variant 1 */
2308 case 0x4238: /* Centrino Ultimate-N 6300 variant 2 */
2309 case 0x08ae: /* Centrino Wireless-N 100 */
2313 /* Clear device-specific "PCI retry timeout" register (41h). */
2314 if(pcicfgr8(pdev, 0x41) != 0)
2315 pcicfgw8(pdev, 0x41, 0);
2317 /* Clear interrupt disable bit. Hardware bug workaround. */
2318 if(pdev->pcr & 0x400){
2319 pdev->pcr &= ~0x400;
2320 pcicfgw16(pdev, PciPCR, pdev->pcr);
2326 ctlr = malloc(sizeof(Ctlr));
2328 print("iwl: unable to alloc Ctlr\n");
2331 ctlr->port = pdev->mem[0].bar & ~0x0F;
2332 mem = vmap(pdev->mem[0].bar & ~0x0F, pdev->mem[0].size);
2334 print("iwl: can't map %8.8luX\n", pdev->mem[0].bar);
2340 ctlr->type = (csr32r(ctlr, Rev) >> 4) & 0xF;
2342 if(fwname[ctlr->type] == nil){
2343 print("iwl: unsupported controller type %d\n", ctlr->type);
2344 vunmap(mem, pdev->mem[0].size);
2350 iwltail->link = ctlr;
2365 for(ctlr = iwlhead; ctlr != nil; ctlr = ctlr->link){
2368 if(edev->port == 0 || edev->port == ctlr->port){
2378 edev->port = ctlr->port;
2379 edev->irq = ctlr->pdev->intl;
2380 edev->tbdf = ctlr->pdev->tbdf;
2382 edev->interrupt = iwlinterrupt;
2383 edev->attach = iwlattach;
2384 edev->ifstat = iwlifstat;
2386 edev->shutdown = iwlshutdown;
2387 edev->promiscuous = iwlpromiscuous;
2388 edev->multicast = nil;
2391 if(iwlinit(edev) < 0){
2402 addethercard("iwl", iwlpnp);