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"
17 #include "../port/etherif.h"
18 #include "../port/wifi.h"
21 MaxQueue = 24*1024, /* total buffer is 2*MaxQueue: 48k at 22Mbit ≅ 20ms */
25 Ntxqmax = MaxQueue/1500,
41 Cfg = 0x000, /* config register */
50 Isr = 0x008, /* interrupt status */
51 Imr = 0x00c, /* interrupt mask */
64 Ierr = Iswerr | Ihwerr,
65 Idefmask = Ierr | Ifhtx | Ifhrx | Ialive | Iwakeup | Iswrx | Ictreached | Irftoggled,
67 FhIsr = 0x010, /* second interrupt status */
71 Rev = 0x028, /* hardware revision */
73 EepromIo = 0x02c, /* EEPROM i/o register */
78 RelativeAccess = 1<<17,
80 EccUncorrStts = 1<<21,
82 Gpc = 0x024, /* gp cntrl */
96 GpDrvRadioIqInvert = 1<<7,
104 UcodeGp1RfKill = 1<<1,
105 UcodeGp1CmdBlocked = 1<<2,
106 UcodeGp1CtempStopRf = 1<<3,
108 ShadowRegCtrl = 0x0a8,
117 Dbglinkpwrmgmt = 0x250,
129 HbusTargWptr = 0x460,
133 * Flow-Handler registers.
136 FhTfbdCtrl0 = 0x1900, // +q*8
137 FhTfbdCtrl1 = 0x1904, // +q*8
141 FhSramAddr = 0x19a4, // +q*4
142 FhCbbcQueue = 0x19d0, // +q*4
143 FhStatusWptr = 0x1bc0,
147 FhRxConfigEna = 1<<31,
148 FhRxConfigRbSize8K = 1<<16,
149 FhRxConfigSingleFrame = 1<<15,
150 FhRxConfigIrqDstHost = 1<<12,
151 FhRxConfigIgnRxfEmpty = 1<<2,
153 FhRxConfigNrbdShift = 20,
154 FhRxConfigRbTimeoutShift= 4,
158 FhTxConfig = 0x1d00, // +q*32
159 FhTxConfigDmaCreditEna = 1<<3,
160 FhTxConfigDmaEna = 1<<31,
161 FhTxConfigCirqHostEndTfd= 1<<20,
163 FhTxBufStatus = 0x1d08, // +q*32
164 FhTxBufStatusTbNumShift = 20,
165 FhTxBufStatusTbIdxShift = 12,
166 FhTxBufStatusTfbdValid = 3,
168 FhTxChicken = 0x1e98,
173 * NIC internal memory offsets.
176 ApmgClkCtrl = 0x3000,
183 EarlyPwroffDis = 1<<22,
189 ApmgDigitalSvr = 0x3058,
190 ApmgAnalogSvr = 0x306c,
193 BsmWrMemSrc = 0x3404,
194 BsmWrMemDst = 0x3408,
195 BsmWrDwCount = 0x340c,
196 BsmDramTextAddr = 0x3490,
197 BsmDramTextSize = 0x3494,
198 BsmDramDataAddr = 0x3498,
199 BsmDramDataSize = 0x349c,
200 BsmSramBase = 0x3800,
204 * TX scheduler registers.
207 SchedBase = 0xa02c00,
208 SchedSramAddr = SchedBase,
210 SchedDramAddr4965 = SchedBase+0x010,
211 SchedTxFact4965 = SchedBase+0x01c,
212 SchedQueueRdptr4965 = SchedBase+0x064, // +q*4
213 SchedQChainSel4965 = SchedBase+0x0d0,
214 SchedIntrMask4965 = SchedBase+0x0e4,
215 SchedQueueStatus4965 = SchedBase+0x104, // +q*4
217 SchedDramAddr5000 = SchedBase+0x008,
218 SchedTxFact5000 = SchedBase+0x010,
219 SchedQueueRdptr5000 = SchedBase+0x068, // +q*4
220 SchedQChainSel5000 = SchedBase+0x0e8,
221 SchedIntrMask5000 = SchedBase+0x108,
222 SchedQueueStatus5000 = SchedBase+0x10c, // +q*4
223 SchedAggrSel5000 = SchedBase+0x248,
227 SchedCtxOff4965 = 0x380,
228 SchedCtxLen4965 = 416,
230 SchedCtxOff5000 = 0x600,
231 SchedCtxLen5000 = 512,
235 FilterPromisc = 1<<0,
237 FilterMulticast = 1<<2,
238 FilterNoDecrypt = 1<<3,
248 RFlagShPreamble = 1<<5,
249 RFlagNoDiversity = 1<<7,
250 RFlagAntennaA = 1<<8,
251 RFlagAntennaB = 1<<9,
253 RFlagCTSToSelf = 1<<30,
256 typedef struct FWInfo FWInfo;
257 typedef struct FWImage FWImage;
258 typedef struct FWSect FWSect;
260 typedef struct TXQ TXQ;
261 typedef struct RXQ RXQ;
263 typedef struct Ctlr Ctlr;
339 /* assigned node ids in hardware node table or -1 if unassigned */
343 /* current receiver settings */
344 uchar bssid[Eaddrlen];
395 /* controller types */
405 Type6005 = 11, /* also Centrino Advanced-N 6030, 6235 */
410 static char *fwname[32] = {
411 [Type4965] "iwn-4965",
412 [Type5300] "iwn-5000",
413 [Type5350] "iwn-5000",
414 [Type5150] "iwn-5150",
415 [Type5100] "iwn-5000",
416 [Type1000] "iwn-1000",
417 [Type6000] "iwn-6000",
418 [Type6050] "iwn-6050",
419 [Type6005] "iwn-6005", /* see in iwlattach() below */
420 [Type2030] "iwn-2030",
421 [Type2000] "iwn-2000",
424 static char *qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block);
425 static char *flushq(Ctlr *ctlr, uint qid);
426 static char *cmd(Ctlr *ctlr, uint code, uchar *data, int size);
428 #define csr32r(c, r) (*((c)->nic+((r)/4)))
429 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
433 return *((u16int*)p);
437 return *((u32int*)p);
440 put32(uchar *p, uint v){
444 put16(uchar *p, uint v){
453 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq);
454 for(i=0; i<1000; i++){
455 if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna)
459 return "niclock: timeout";
463 nicunlock(Ctlr *ctlr)
465 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq);
469 prphread(Ctlr *ctlr, uint off)
471 csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off);
473 return csr32r(ctlr, PrphRdata);
476 prphwrite(Ctlr *ctlr, uint off, u32int data)
478 csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off);
480 csr32w(ctlr, PrphWdata, data);
484 memread(Ctlr *ctlr, uint off)
486 csr32w(ctlr, MemRaddr, off);
488 return csr32r(ctlr, MemRdata);
491 memwrite(Ctlr *ctlr, uint off, u32int data)
493 csr32w(ctlr, MemWaddr, off);
495 csr32w(ctlr, MemWdata, data);
499 setfwinfo(Ctlr *ctlr, uchar *d, int len)
512 i->logptr = get32(d); d += 4;
513 i->errptr = get32(d); d += 4;
514 i->tstamp = get32(d); d += 4;
524 print("lastcmd: %ud (0x%ux)\n", ctlr->tx[4].lastcmd, ctlr->tx[4].lastcmd);
525 if(ctlr->fwinfo.errptr == 0){
526 print("no error pointer\n");
529 for(i=0; i<nelem(dump); i++)
530 dump[i] = memread(ctlr, ctlr->fwinfo.errptr + i*4);
531 print( "error:\tid %ux, pc %ux,\n"
532 "\tbranchlink %.8ux %.8ux, interruptlink %.8ux %.8ux,\n"
533 "\terrordata %.8ux %.8ux, srcline %ud, tsf %ux, time %ux\n",
535 dump[4], dump[3], dump[6], dump[5],
536 dump[7], dump[8], dump[9], dump[10], dump[11]);
540 eepromlock(Ctlr *ctlr)
544 for(i=0; i<100; i++){
545 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | EepromLocked);
546 for(j=0; j<100; j++){
547 if(csr32r(ctlr, Cfg) & EepromLocked)
552 return "eepromlock: timeout";
555 eepromunlock(Ctlr *ctlr)
557 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) & ~EepromLocked);
560 eepromread(Ctlr *ctlr, void *data, int count, uint off)
567 off += ctlr->eeprom.off;
568 for(; count > 0; count -= 2, off++){
569 csr32w(ctlr, EepromIo, off << 2);
571 w = csr32r(ctlr, EepromIo);
577 return "eepromread: timeout";
578 if(ctlr->eeprom.otp){
579 s = csr32r(ctlr, OtpromGp);
580 if(s & EccUncorrStts)
581 return "eepromread: otprom ecc error";
583 csr32w(ctlr, OtpromGp, s);
597 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
599 if(csr32r(ctlr, Cfg) & NicReady)
603 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | Prepare);
604 for(i=0; i<15000; i++){
605 if((csr32r(ctlr, Cfg) & PrepareDone) == 0)
610 return "handover: timeout";
611 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
613 if(csr32r(ctlr, Cfg) & NicReady)
617 return "handover: timeout";
621 clockwait(Ctlr *ctlr)
625 /* Set "initialization complete" bit. */
626 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone);
627 for(i=0; i<2500; i++){
628 if(csr32r(ctlr, Gpc) & MacClockReady)
632 return "clockwait: timeout";
641 /* Disable L0s exit timer (NMI bug workaround). */
642 csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | DisL0Stimer);
644 /* Don't wait for ICH L0s (ICH bug workaround). */
645 csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | L1AnoL0Srx);
647 /* Set FH wait threshold to max (HW bug under stress workaround). */
648 csr32w(ctlr, Dbghpetmem, csr32r(ctlr, Dbghpetmem) | 0xffff0000);
650 /* Enable HAP INTA to move adapter from L1a to L0s. */
651 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | HapwakeL1A);
653 capoff = pcicap(ctlr->pdev, PciCapPCIe);
655 /* Workaround for HW instability in PCIe L0->L0s->L1 transition. */
656 if(pcicfgr16(ctlr->pdev, capoff + 0x10) & 0x2) /* LCSR -> L1 Entry enabled. */
657 csr32w(ctlr, Gio, csr32r(ctlr, Gio) | EnaL0S);
659 csr32w(ctlr, Gio, csr32r(ctlr, Gio) & ~EnaL0S);
662 if(ctlr->type != Type4965 && ctlr->type <= Type1000)
663 csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | 0x00880300);
665 /* Wait for clock stabilization before accessing prph. */
666 if((err = clockwait(ctlr)) != nil)
669 if((err = niclock(ctlr)) != nil)
672 /* Enable DMA and BSM (Bootstrap State Machine). */
673 if(ctlr->type == Type4965)
674 prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt);
676 prphwrite(ctlr, ApmgClkEna, DmaClkRqt);
679 /* Disable L1-Active. */
680 prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11));
694 csr32w(ctlr, Reset, 1);
696 /* Disable interrupts */
698 csr32w(ctlr, Imr, 0);
699 csr32w(ctlr, Isr, ~0);
700 csr32w(ctlr, FhIsr, ~0);
703 if(ctlr->type != Type4965)
704 prphwrite(ctlr, SchedTxFact5000, 0);
706 prphwrite(ctlr, SchedTxFact4965, 0);
709 if(niclock(ctlr) == nil){
710 for(i = (ctlr->type != Type4965) ? 7 : 6; i >= 0; i--){
711 csr32w(ctlr, FhTxConfig + i*32, 0);
712 for(j = 0; j < 200; j++){
713 if(csr32r(ctlr, FhTxStatus) & (0x10000<<i))
722 if(niclock(ctlr) == nil){
723 csr32w(ctlr, FhRxConfig, 0);
724 for(j = 0; j < 200; j++){
725 if(csr32r(ctlr, FhRxStatus) & 0x1000000)
733 if(niclock(ctlr) == nil){
734 prphwrite(ctlr, ApmgClkDis, DmaClkRqt);
739 /* Stop busmaster DMA activity. */
740 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | (1<<9));
741 for(j = 0; j < 100; j++){
742 if(csr32r(ctlr, Reset) & (1<<8))
747 /* Reset the entire device. */
748 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | (1<<7));
751 /* Clear "initialization complete" bit. */
752 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~InitDone);
765 ctlr->eeprom.otp = 0;
766 ctlr->eeprom.off = 0;
767 if(ctlr->type < Type1000 || (csr32r(ctlr, OtpromGp) & DevSelOtp) == 0)
770 /* Wait for clock stabilization before accessing prph. */
771 if((err = clockwait(ctlr)) != nil)
774 if((err = niclock(ctlr)) != nil)
776 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | ResetReq);
778 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) & ~ResetReq);
781 /* Set auto clock gate disable bit for HW with OTP shadow RAM. */
782 if(ctlr->type != Type1000)
783 csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31));
785 csr32w(ctlr, EepromGp, csr32r(ctlr, EepromGp) & ~0x00000180);
787 /* Clear ECC status. */
788 csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) | (EccCorrStts | EccUncorrStts));
790 ctlr->eeprom.otp = 1;
791 if(ctlr->type != Type1000)
794 /* Switch to absolute addressing mode. */
795 csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) & ~RelativeAccess);
798 * Find the block before last block (contains the EEPROM image)
799 * for HW without OTP shadow RAM.
803 if((err = eepromread(ctlr, buf, 2, last)) != nil)
811 return "rominit: missing eeprom image";
813 ctlr->eeprom.off = prev+1;
823 uint u, caloff, regoff;
827 /* Clear device-specific "PCI retry timeout" register (41h). */
828 if(pcicfgr8(ctlr->pdev, 0x41) != 0)
829 pcicfgw8(ctlr->pdev, 0x41, 0);
831 /* Clear interrupt disable bit. Hardware bug workaround. */
832 if(ctlr->pdev->pcr & 0x400){
833 ctlr->pdev->pcr &= ~0x400;
834 pcicfgw16(ctlr->pdev, PciPCR, ctlr->pdev->pcr);
837 ctlr->type = (csr32r(ctlr, Rev) >> 4) & 0x1F;
838 if(fwname[ctlr->type] == nil){
839 print("iwl: unsupported controller type %d\n", ctlr->type);
843 if((err = handover(ctlr)) != nil)
845 if((err = poweron(ctlr)) != nil)
847 if((csr32r(ctlr, EepromGp) & 0x7) == 0){
848 err = "bad rom signature";
851 if((err = eepromlock(ctlr)) != nil)
853 if((err = rominit(ctlr)) != nil)
855 if((err = eepromread(ctlr, edev->ea, sizeof(edev->ea), 0x15)) != nil){
859 if((err = eepromread(ctlr, b, 2, 0x048)) != nil){
865 ctlr->rfcfg.type = u & 3; u >>= 2;
866 ctlr->rfcfg.step = u & 3; u >>= 2;
867 ctlr->rfcfg.dash = u & 3; u >>= 4;
868 ctlr->rfcfg.txantmask = u & 15; u >>= 4;
869 ctlr->rfcfg.rxantmask = u & 15;
870 if((err = eepromread(ctlr, b, 2, 0x66)) != nil)
873 if((err = eepromread(ctlr, b, 4, regoff+1)) != nil)
875 strncpy(ctlr->eeprom.regdom, (char*)b, 4);
876 ctlr->eeprom.regdom[4] = 0;
877 if((err = eepromread(ctlr, b, 2, 0x67)) != nil)
880 if((err = eepromread(ctlr, b, 4, caloff)) != nil)
882 ctlr->eeprom.version = b[0];
883 ctlr->eeprom.type = b[1];
884 ctlr->eeprom.volt = get16(b+2);
886 ctlr->eeprom.temp = 0;
887 ctlr->eeprom.rawtemp = 0;
888 if(ctlr->type == Type2030 || ctlr->type == Type2000){
889 if((err = eepromread(ctlr, b, 2, caloff + 0x12a)) != nil)
891 ctlr->eeprom.temp = get16(b);
892 if((err = eepromread(ctlr, b, 2, caloff + 0x12b)) != nil)
894 ctlr->eeprom.rawtemp = get16(b);
897 if(ctlr->type != Type4965 && ctlr->type != Type5150){
898 if((err = eepromread(ctlr, b, 4, caloff + 0x128)) != nil)
900 ctlr->eeprom.crystal = get32(b);
906 ctlr->rfcfg.txantmask = 3;
907 ctlr->rfcfg.rxantmask = 7;
910 ctlr->rfcfg.txantmask = 2;
911 ctlr->rfcfg.rxantmask = 3;
914 if(ctlr->pdev->did == 0x422c || ctlr->pdev->did == 0x4230){
915 ctlr->rfcfg.txantmask = 6;
916 ctlr->rfcfg.rxantmask = 6;
923 print("iwlinit: %s\n", err);
929 crackfw(FWImage *i, uchar *data, uint size, int alt)
934 memset(i, 0, sizeof(*i));
937 return "firmware image too short";
941 i->rev = get32(p); p += 4;
945 if(size < (4+64+4+4+8))
947 if(memcmp(p, "IWL\n", 4) != 0)
948 return "bad firmware signature";
950 strncpy(i->descr, (char*)p, 64);
953 i->rev = get32(p); p += 4;
954 i->build = get32(p); p += 4;
955 altmask = get32(p); p += 4;
956 altmask |= (uvlong)get32(p) << 32; p += 4;
957 while(alt > 0 && (altmask & (1ULL<<alt)) == 0)
965 case 1: s = &i->main.text; break;
966 case 2: s = &i->main.data; break;
967 case 3: s = &i->init.text; break;
968 case 4: s = &i->init.data; break;
969 case 5: s = &i->boot.text; break;
973 if(get16(p) != 0 && get16(p) != alt)
976 s->size = get32(p); p += 4;
978 if((p + s->size) > e)
980 p += (s->size + 3) & ~3;
983 if(((i->rev>>8) & 0xFF) < 2)
984 return "need firmware api >= 2";
985 if(((i->rev>>8) & 0xFF) >= 3){
986 i->build = get32(p); p += 4;
990 i->main.text.size = get32(p); p += 4;
991 i->main.data.size = get32(p); p += 4;
992 i->init.text.size = get32(p); p += 4;
993 i->init.data.size = get32(p); p += 4;
994 i->boot.text.size = get32(p); p += 4;
995 i->main.text.data = p; p += i->main.text.size;
996 i->main.data.data = p; p += i->main.data.size;
997 i->init.text.data = p; p += i->init.text.size;
998 i->init.data.data = p; p += i->init.data.size;
999 i->boot.text.data = p; p += i->boot.text.size;
1007 readfirmware(char *name)
1009 uchar dirbuf[sizeof(Dir)+100], *data;
1010 char buf[128], *err;
1019 snprint(buf, sizeof buf, "/boot/%s", name);
1020 c = namec(buf, Aopen, OREAD, 0);
1023 snprint(buf, sizeof buf, "/lib/firmware/%s", name);
1024 c = namec(buf, Aopen, OREAD, 0);
1030 n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf);
1032 error("can't stat firmware");
1033 convM2D(dirbuf, n, &d, nil);
1034 fw = smalloc(sizeof(*fw) + 16 + d.length);
1035 data = (uchar*)(fw+1);
1041 while(r < d.length){
1042 n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r);
1047 if((err = crackfw(fw, data, r, 1)) != nil)
1060 return (ctlr->wait.m & ctlr->wait.w) != 0;
1064 irqwait(Ctlr *ctlr, u32int mask, int timeout)
1069 r = ctlr->wait.m & mask;
1071 ctlr->wait.w = mask;
1074 tsleep(&ctlr->wait, gotirq, ctlr, timeout);
1079 r = ctlr->wait.m & mask;
1087 rbplant(Ctlr *ctlr, int i)
1091 b = iallocb(Rbufsize + 256);
1094 b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, 256);
1095 memset(b->rp, 0, Rdscsize);
1097 ctlr->rx.p[i] = PCIWADDR(b->rp) >> 8;
1102 initring(Ctlr *ctlr)
1110 rx->b = malloc(sizeof(Block*) * Nrx);
1112 rx->p = mallocalign(sizeof(u32int) * Nrx, 256, 0, 0);
1114 rx->s = mallocalign(Rstatsize, 16, 0, 0);
1115 if(rx->b == nil || rx->p == nil || rx->s == nil)
1116 return "no memory for rx ring";
1117 memset(ctlr->rx.s, 0, Rstatsize);
1118 for(i=0; i<Nrx; i++){
1120 if(rx->b[i] != nil){
1124 if(rbplant(ctlr, i) < 0)
1125 return "no memory for rx descriptors";
1129 if(ctlr->sched.s == nil)
1130 ctlr->sched.s = mallocalign(512 * nelem(ctlr->tx) * 2, 1024, 0, 0);
1131 if(ctlr->sched.s == nil)
1132 return "no memory for sched buffer";
1133 memset(ctlr->sched.s, 0, 512 * nelem(ctlr->tx));
1135 for(q=0; q<nelem(ctlr->tx); q++){
1138 tx->b = malloc(sizeof(Block*) * Ntx);
1140 tx->d = mallocalign(Tdscsize * Ntx, 256, 0, 0);
1142 tx->c = mallocalign(Tcmdsize * Ntx, 4, 0, 0);
1143 if(tx->b == nil || tx->d == nil || tx->c == nil)
1144 return "no memory for tx ring";
1145 memset(tx->d, 0, Tdscsize * Ntx);
1146 memset(tx->c, 0, Tcmdsize * Ntx);
1147 for(i=0; i<Ntx; i++){
1148 if(tx->b[i] != nil){
1158 if(ctlr->kwpage == nil)
1159 ctlr->kwpage = mallocalign(4096, 4096, 0, 0);
1160 if(ctlr->kwpage == nil)
1161 return "no memory for kwpage";
1162 memset(ctlr->kwpage, 0, 4096);
1175 if((err = initring(ctlr)) != nil)
1177 if((err = poweron(ctlr)) != nil)
1180 if((err = niclock(ctlr)) != nil)
1182 prphwrite(ctlr, ApmgPs, (prphread(ctlr, ApmgPs) & ~PwrSrcMask) | PwrSrcVMain);
1185 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | RadioSi | MacSi);
1187 if((err = niclock(ctlr)) != nil)
1189 if(ctlr->type != Type4965)
1190 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | EarlyPwroffDis);
1191 if(ctlr->type == Type1000){
1193 * Select first Switching Voltage Regulator (1.32V) to
1194 * solve a stability issue related to noisy DC2DC line
1195 * in the silicon of 1000 Series.
1197 prphwrite(ctlr, ApmgDigitalSvr,
1198 (prphread(ctlr, ApmgDigitalSvr) & ~(0xf<<5)) | (3<<5));
1202 if((err = niclock(ctlr)) != nil)
1204 if((ctlr->type == Type6005 || ctlr->type == Type6050) && ctlr->eeprom.version == 6)
1205 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvCalV6);
1206 if(ctlr->type == Type6005)
1207 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrv1X2);
1208 if(ctlr->type == Type2030 || ctlr->type == Type2000)
1209 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvRadioIqInvert);
1212 if((err = niclock(ctlr)) != nil)
1214 csr32w(ctlr, FhRxConfig, 0);
1215 csr32w(ctlr, FhRxWptr, 0);
1216 csr32w(ctlr, FhRxBase, PCIWADDR(ctlr->rx.p) >> 8);
1217 csr32w(ctlr, FhStatusWptr, PCIWADDR(ctlr->rx.s) >> 4);
1218 csr32w(ctlr, FhRxConfig,
1220 FhRxConfigIgnRxfEmpty |
1221 FhRxConfigIrqDstHost |
1222 FhRxConfigSingleFrame |
1223 (Nrxlog << FhRxConfigNrbdShift));
1224 csr32w(ctlr, FhRxWptr, (Nrx-1) & ~7);
1227 if((err = niclock(ctlr)) != nil)
1229 if(ctlr->type != Type4965)
1230 prphwrite(ctlr, SchedTxFact5000, 0);
1232 prphwrite(ctlr, SchedTxFact4965, 0);
1233 csr32w(ctlr, FhKwAddr, PCIWADDR(ctlr->kwpage) >> 4);
1234 for(q = (ctlr->type != Type4965) ? 19 : 15; q >= 0; q--)
1235 csr32w(ctlr, FhCbbcQueue + q*4, PCIWADDR(ctlr->tx[q].d) >> 8);
1238 for(i = (ctlr->type != Type4965) ? 7 : 6; i >= 0; i--)
1239 csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna);
1241 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
1242 csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
1248 ctlr->ie = Idefmask;
1249 csr32w(ctlr, Imr, ctlr->ie);
1250 csr32w(ctlr, Isr, ~0);
1252 if(ctlr->type >= Type6000)
1253 csr32w(ctlr, ShadowRegCtrl, csr32r(ctlr, ShadowRegCtrl) | 0x800fffff);
1259 sendbtcoexadv(Ctlr *ctlr)
1261 static u32int btcoex3wire[12] = {
1262 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
1263 0xcc00ff28, 0x0000aaaa, 0xcc00aaaa, 0x0000aaaa,
1264 0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,
1267 uchar c[Tcmdsize], *p;
1272 memset(c, 0, sizeof(c));
1275 if(ctlr->type == Type2030){
1276 *p++ = 145; /* flags */
1277 p++; /* lead time */
1278 *p++ = 5; /* max kill */
1279 *p++ = 1; /* bt3 t7 timer */
1280 put32(p, 0xffff0000); /* kill ack */
1282 put32(p, 0xffff0000); /* kill cts */
1284 *p++ = 2; /* sample time */
1285 *p++ = 0xc; /* bt3 t2 timer */
1286 p += 2; /* bt4 reaction */
1287 for (i = 0; i < nelem(btcoex3wire); i++){
1288 put32(p, btcoex3wire[i]);
1291 p += 2; /* bt4 decision */
1292 put16(p, 0xff); /* valid */
1294 put32(p, 0xf0); /* prio boost */
1297 p++; /* tx prio boost */
1298 p += 2; /* rx prio boost */
1300 if((err = cmd(ctlr, 155, c, p-c)) != nil)
1303 /* set BT priority */
1304 memset(c, 0, sizeof(c));
1307 *p++ = 0x6; /* init1 */
1308 *p++ = 0x7; /* init2 */
1309 *p++ = 0x2; /* periodic low1 */
1310 *p++ = 0x3; /* periodic low2 */
1311 *p++ = 0x4; /* periodic high1 */
1312 *p++ = 0x5; /* periodic high2 */
1313 *p++ = 0x6; /* dtim */
1314 *p++ = 0x8; /* scan52 */
1315 *p++ = 0xa; /* scan24 */
1316 p += 7; /* reserved */
1317 if((err = cmd(ctlr, 204, c, p-c)) != nil)
1320 /* force BT state machine change */
1321 memset(c, 0, sizeof(c));
1324 *p++ = 1; /* open */
1325 *p++ = 1; /* type */
1326 p += 2; /* reserved */
1327 if((err = cmd(ctlr, 205, c, p-c)) != nil)
1330 c[0] = 0; /* open */
1331 return cmd(ctlr, 205, c, p-c);
1335 postboot(Ctlr *ctlr)
1337 uint ctxoff, ctxlen, dramaddr;
1341 if((err = niclock(ctlr)) != nil)
1344 if(ctlr->type != Type4965){
1345 dramaddr = SchedDramAddr5000;
1346 ctxoff = SchedCtxOff5000;
1347 ctxlen = SchedCtxLen5000;
1349 dramaddr = SchedDramAddr4965;
1350 ctxoff = SchedCtxOff4965;
1351 ctxlen = SchedCtxLen4965;
1354 ctlr->sched.base = prphread(ctlr, SchedSramAddr);
1355 for(i=0; i < ctxlen; i += 4)
1356 memwrite(ctlr, ctlr->sched.base + ctxoff + i, 0);
1358 prphwrite(ctlr, dramaddr, PCIWADDR(ctlr->sched.s)>>10);
1360 csr32w(ctlr, FhTxChicken, csr32r(ctlr, FhTxChicken) | 2);
1362 if(ctlr->type != Type4965){
1363 /* Enable chain mode for all queues, except command queue 4. */
1364 prphwrite(ctlr, SchedQChainSel5000, 0xfffef);
1365 prphwrite(ctlr, SchedAggrSel5000, 0);
1367 for(q=0; q<20; q++){
1368 prphwrite(ctlr, SchedQueueRdptr5000 + q*4, 0);
1369 csr32w(ctlr, HbusTargWptr, q << 8);
1371 memwrite(ctlr, ctlr->sched.base + ctxoff + q*8, 0);
1372 /* Set scheduler window size and frame limit. */
1373 memwrite(ctlr, ctlr->sched.base + ctxoff + q*8 + 4, 64<<16 | 64);
1375 /* Enable interrupts for all our 20 queues. */
1376 prphwrite(ctlr, SchedIntrMask5000, 0xfffff);
1378 /* Identify TX FIFO rings (0-7). */
1379 prphwrite(ctlr, SchedTxFact5000, 0xff);
1381 /* Disable chain mode for all our 16 queues. */
1382 prphwrite(ctlr, SchedQChainSel4965, 0);
1384 for(q=0; q<16; q++) {
1385 prphwrite(ctlr, SchedQueueRdptr4965 + q*4, 0);
1386 csr32w(ctlr, HbusTargWptr, q << 8);
1388 /* Set scheduler window size. */
1389 memwrite(ctlr, ctlr->sched.base + ctxoff + q*8, 64);
1390 /* Set scheduler window size and frame limit. */
1391 memwrite(ctlr, ctlr->sched.base + ctxoff + q*8 + 4, 64<<16);
1393 /* Enable interrupts for all our 16 queues. */
1394 prphwrite(ctlr, SchedIntrMask4965, 0xffff);
1396 /* Identify TX FIFO rings (0-7). */
1397 prphwrite(ctlr, SchedTxFact4965, 0xff);
1400 /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
1402 if(ctlr->type != Type4965){
1403 static uchar qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
1404 prphwrite(ctlr, SchedQueueStatus5000 + q*4, 0x00ff0018 | qid2fifo[q]);
1406 static uchar qid2fifo[] = { 3, 2, 1, 0, 4, 5, 6 };
1407 prphwrite(ctlr, SchedQueueStatus4965 + q*4, 0x0007fc01 | qid2fifo[q]<<1);
1412 if(ctlr->type != Type4965){
1415 /* disable wimax coexistance */
1416 memset(c, 0, sizeof(c));
1417 if((err = cmd(ctlr, 90, c, 4+4*16)) != nil)
1420 if(ctlr->type != Type5150){
1421 /* calibrate crystal */
1422 memset(c, 0, sizeof(c));
1423 c[0] = 15; /* code */
1424 c[1] = 0; /* group */
1425 c[2] = 1; /* ngroup */
1426 c[3] = 1; /* isvalid */
1427 c[4] = ctlr->eeprom.crystal;
1428 c[5] = ctlr->eeprom.crystal>>16;
1429 /* for some reason 8086:4238 needs a second try */
1430 if(cmd(ctlr, 176, c, 8) != nil && (err = cmd(ctlr, 176, c, 8)) != nil)
1434 if(ctlr->calib.done == 0){
1435 /* query calibration (init firmware) */
1436 memset(c, 0, sizeof(c));
1437 put32(c + 0*(5*4) + 0, 0xffffffff);
1438 put32(c + 0*(5*4) + 4, 0xffffffff);
1439 put32(c + 0*(5*4) + 8, 0xffffffff);
1440 put32(c + 2*(5*4) + 0, 0xffffffff);
1441 if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil)
1444 /* wait to collect calibration records */
1445 if(irqwait(ctlr, Ierr, 2000))
1446 return "calibration failed";
1448 if(ctlr->calib.done == 0){
1449 print("iwl: no calibration results\n");
1450 ctlr->calib.done = 1;
1453 static uchar cmds[] = {8, 9, 11, 17, 16};
1455 /* send calibration records (runtime firmware) */
1456 for(q=0; q<nelem(cmds); q++){
1460 if(i == 8 && ctlr->type != Type5150 && ctlr->type != Type2030 &&
1461 ctlr->type != Type2000)
1463 if(i == 17 && (ctlr->type >= Type6000 || ctlr->type == Type5150) &&
1464 ctlr->type != Type2030 && ctlr->type != Type2000)
1467 if((b = ctlr->calib.cmd[i]) == nil)
1469 b = copyblock(b, BLEN(b));
1470 if((err = qcmd(ctlr, 4, 176, nil, 0, b)) != nil){
1474 if((err = flushq(ctlr, 4)) != nil)
1478 /* temperature sensor offset */
1479 switch (ctlr->type){
1481 memset(c, 0, sizeof(c));
1487 if((err = cmd(ctlr, 176, c, 4+2+2)) != nil)
1493 memset(c, 0, sizeof(c));
1498 if(ctlr->eeprom.rawtemp != 0){
1499 put16(c + 4, ctlr->eeprom.temp);
1500 put16(c + 6, ctlr->eeprom.rawtemp);
1505 put16(c + 8, ctlr->eeprom.volt);
1506 if((err = cmd(ctlr, 176, c, 4+2+2+2+2)) != nil)
1511 if(ctlr->type == Type6005 || ctlr->type == Type6050){
1512 /* runtime DC calibration */
1513 memset(c, 0, sizeof(c));
1514 put32(c + 0*(5*4) + 0, 0xffffffff);
1515 put32(c + 0*(5*4) + 4, 1<<1);
1516 if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil)
1520 /* set tx antenna config */
1521 put32(c, ctlr->rfcfg.txantmask & 7);
1522 if((err = cmd(ctlr, 152, c, 4)) != nil)
1525 if(ctlr->type == Type2030){
1526 if((err = sendbtcoexadv(ctlr)) != nil)
1536 loadfirmware1(Ctlr *ctlr, u32int dst, uchar *data, int size)
1541 dma = mallocalign(size, 16, 0, 0);
1543 return "no memory for dma";
1544 memmove(dma, data, size);
1546 if((err = niclock(ctlr)) != 0){
1550 csr32w(ctlr, FhTxConfig + 9*32, 0);
1551 csr32w(ctlr, FhSramAddr + 9*4, dst);
1552 csr32w(ctlr, FhTfbdCtrl0 + 9*8, PCIWADDR(dma));
1553 csr32w(ctlr, FhTfbdCtrl1 + 9*8, size);
1554 csr32w(ctlr, FhTxBufStatus + 9*32,
1555 (1<<FhTxBufStatusTbNumShift) |
1556 (1<<FhTxBufStatusTbIdxShift) |
1557 FhTxBufStatusTfbdValid);
1558 csr32w(ctlr, FhTxConfig + 9*32, FhTxConfigDmaEna | FhTxConfigCirqHostEndTfd);
1560 if(irqwait(ctlr, Ifhtx|Ierr, 5000) != Ifhtx){
1562 return "dma error / timeout";
1578 if(fw->boot.text.size == 0){
1579 if(ctlr->calib.done == 0){
1580 if((err = loadfirmware1(ctlr, 0x00000000, fw->init.text.data, fw->init.text.size)) != nil)
1582 if((err = loadfirmware1(ctlr, 0x00800000, fw->init.data.data, fw->init.data.size)) != nil)
1584 csr32w(ctlr, Reset, 0);
1585 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive)
1586 return "init firmware boot failed";
1587 if((err = postboot(ctlr)) != nil)
1589 if((err = reset(ctlr)) != nil)
1592 if((err = loadfirmware1(ctlr, 0x00000000, fw->main.text.data, fw->main.text.size)) != nil)
1594 if((err = loadfirmware1(ctlr, 0x00800000, fw->main.data.data, fw->main.data.size)) != nil)
1596 csr32w(ctlr, Reset, 0);
1597 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive)
1598 return "main firmware boot failed";
1599 return postboot(ctlr);
1602 size = ROUND(fw->init.data.size, 16) + ROUND(fw->init.text.size, 16);
1603 dma = mallocalign(size, 16, 0, 0);
1605 return "no memory for dma";
1607 if((err = niclock(ctlr)) != nil){
1613 memmove(p, fw->init.data.data, fw->init.data.size);
1615 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
1616 prphwrite(ctlr, BsmDramDataSize, fw->init.data.size);
1617 p += ROUND(fw->init.data.size, 16);
1618 memmove(p, fw->init.text.data, fw->init.text.size);
1620 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
1621 prphwrite(ctlr, BsmDramTextSize, fw->init.text.size);
1624 if((err = niclock(ctlr)) != nil){
1629 p = fw->boot.text.data;
1630 n = fw->boot.text.size/4;
1631 for(i=0; i<n; i++, p += 4)
1632 prphwrite(ctlr, BsmSramBase+i*4, get32(p));
1634 prphwrite(ctlr, BsmWrMemSrc, 0);
1635 prphwrite(ctlr, BsmWrMemDst, 0);
1636 prphwrite(ctlr, BsmWrDwCount, n);
1638 prphwrite(ctlr, BsmWrCtrl, 1<<31);
1640 for(i=0; i<1000; i++){
1641 if((prphread(ctlr, BsmWrCtrl) & (1<<31)) == 0)
1648 return "bootcode timeout";
1651 prphwrite(ctlr, BsmWrCtrl, 1<<30);
1654 csr32w(ctlr, Reset, 0);
1655 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
1657 return "init firmware boot failed";
1661 size = ROUND(fw->main.data.size, 16) + ROUND(fw->main.text.size, 16);
1662 dma = mallocalign(size, 16, 0, 0);
1664 return "no memory for dma";
1665 if((err = niclock(ctlr)) != nil){
1670 memmove(p, fw->main.data.data, fw->main.data.size);
1672 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
1673 prphwrite(ctlr, BsmDramDataSize, fw->main.data.size);
1674 p += ROUND(fw->main.data.size, 16);
1675 memmove(p, fw->main.text.data, fw->main.text.size);
1677 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
1678 prphwrite(ctlr, BsmDramTextSize, fw->main.text.size | (1<<31));
1681 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
1683 return "main firmware boot failed";
1686 return postboot(ctlr);
1693 return q->n < Ntxqmax;
1697 qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
1702 assert(qid < nelem(ctlr->tx));
1703 assert(size <= Tcmdsize-4);
1707 while(q->n >= Ntxqmax && !ctlr->broken){
1711 tsleep(q, txqready, q, 5);
1719 return "qcmd: broken";
1725 c = q->c + q->i * Tcmdsize;
1726 d = q->d + q->i * Tdscsize;
1730 c[1] = 0; /* flags */
1735 memmove(c+4, data, size);
1739 /* build descriptor */
1743 *d++ = 1 + (block != nil); /* nsegs */
1744 put32(d, PCIWADDR(c)); d += 4;
1745 put16(d, size << 4); d += 2;
1748 put32(d, PCIWADDR(block->rp)); d += 4;
1749 put16(d, size << 4);
1754 q->i = (q->i+1) % Ntx;
1755 csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i);
1770 flushq(Ctlr *ctlr, uint qid)
1777 for(i = 0; i < 200 && !ctlr->broken; i++){
1783 tsleep(q, txqempty, q, 10);
1789 return "flushq: broken";
1790 return "flushq: timeout";
1794 cmd(Ctlr *ctlr, uint code, uchar *data, int size)
1798 if(0) print("cmd %ud\n", code);
1799 if((err = qcmd(ctlr, 4, code, data, size, nil)) != nil)
1801 return flushq(ctlr, 4);
1805 setled(Ctlr *ctlr, int which, int on, int off)
1809 csr32w(ctlr, Led, csr32r(ctlr, Led) & ~LedBsmCtrl);
1811 memset(c, 0, sizeof(c));
1816 cmd(ctlr, 72, c, sizeof(c));
1820 addnode(Ctlr *ctlr, uchar id, uchar *addr)
1822 uchar c[Tcmdsize], *p;
1824 memset(p = c, 0, sizeof(c));
1825 *p++ = 0; /* control (1 = update) */
1826 p += 3; /* reserved */
1827 memmove(p, addr, 6);
1829 p += 2; /* reserved */
1830 *p++ = id; /* node id */
1832 p += 2; /* reserved */
1833 p += 2; /* kflags */
1836 p += 5*2; /* ttak */
1840 if(ctlr->type != Type4965){
1845 p += 4; /* htflags */
1847 p += 2; /* disable tid */
1848 p += 2; /* reserved */
1849 p++; /* add ba tid */
1850 p++; /* del ba tid */
1851 p += 2; /* add ba ssn */
1852 p += 4; /* reserved */
1853 cmd(ctlr, 24, c, p - c);
1857 rxon(Ether *edev, Wnode *bss)
1859 uchar c[Tcmdsize], *p;
1865 filter = FilterNoDecrypt | FilterMulticast | FilterBeacon;
1867 filter |= FilterPromisc;
1869 ctlr->channel = bss->channel;
1872 flags = RFlagTSF | RFlagCTSToSelf | RFlag24Ghz | RFlagAuto;
1874 if(bss->cap & (1<<5))
1875 flags |= RFlagShPreamble;
1876 if(bss->cap & (1<<10))
1877 flags |= RFlagShSlot;
1878 ctlr->channel = bss->channel;
1879 memmove(ctlr->bssid, bss->bssid, Eaddrlen);
1880 ctlr->aid = bss->aid;
1882 filter |= FilterBSS;
1883 filter &= ~FilterBeacon;
1884 ctlr->bssnodeid = -1;
1886 ctlr->bcastnodeid = -1;
1888 memmove(ctlr->bssid, edev->bcast, Eaddrlen);
1890 ctlr->bcastnodeid = -1;
1891 ctlr->bssnodeid = -1;
1895 setled(ctlr, 2, 0, 1); /* on when associated */
1896 else if(memcmp(ctlr->bssid, edev->bcast, Eaddrlen) != 0)
1897 setled(ctlr, 2, 10, 10); /* slow blink when connecting */
1899 setled(ctlr, 2, 5, 5); /* fast blink when scanning */
1901 if(ctlr->wifi->debug)
1902 print("#l%d: rxon: bssid %E, aid %x, channel %d, filter %x, flags %x\n",
1903 edev->ctlrno, ctlr->bssid, ctlr->aid, ctlr->channel, filter, flags);
1905 memset(p = c, 0, sizeof(c));
1906 memmove(p, edev->ea, 6); p += 8; /* myaddr */
1907 memmove(p, ctlr->bssid, 6); p += 8; /* bssid */
1908 memmove(p, edev->ea, 6); p += 8; /* wlap */
1909 *p++ = 3; /* mode (STA) */
1910 *p++ = 0; /* air (?) */
1912 put16(p, ((ctlr->rfcfg.rxantmask & 7)<<1) | (2<<10) | (2<<12));
1914 *p++ = 0xff; /* ofdm mask (not yet negotiated) */
1915 *p++ = 0x0f; /* cck mask (not yet negotiated) */
1916 put16(p, ctlr->aid & 0x3fff);
1922 *p++ = ctlr->channel;
1924 *p++ = 0xff; /* ht single mask */
1925 *p++ = 0xff; /* ht dual mask */
1926 if(ctlr->type != Type4965){
1927 *p++ = 0xff; /* ht triple mask */
1929 put16(p, 0); p += 2; /* acquisition */
1930 p += 2; /* reserved */
1932 if((err = cmd(ctlr, 16, c, p - c)) != nil){
1933 print("rxon: %s\n", err);
1937 if(ctlr->bcastnodeid == -1){
1938 ctlr->bcastnodeid = (ctlr->type != Type4965) ? 15 : 31;
1939 addnode(ctlr, ctlr->bcastnodeid, edev->bcast);
1941 if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){
1942 ctlr->bssnodeid = 0;
1943 addnode(ctlr, ctlr->bssnodeid, bss->bssid);
1947 static struct ratetab {
1952 { 2, 10, RFlagCCK },
1953 { 4, 20, RFlagCCK },
1954 { 11, 55, RFlagCCK },
1955 { 22, 110, RFlagCCK },
1968 static uchar iwlrates[] = {
1988 TFlagNeedProtection = 1<<0,
1989 TFlagNeedRTS = 1<<1,
1990 TFlagNeedCTS = 1<<2,
1991 TFlagNeedACK = 1<<3,
1994 TFlagFullTxOp = 1<<7,
1996 TFlagAutoSeq = 1<<13,
1997 TFlagMoreFrag = 1<<14,
1998 TFlagInsertTs = 1<<16,
1999 TFlagNeedPadding = 1<<20,
2003 transmit(Wifi *wifi, Wnode *wn, Block *b)
2005 int flags, nodeid, rate, ant;
2006 uchar c[Tcmdsize], *p;
2016 if(ctlr->attached == 0 || ctlr->broken){
2022 if((wn->channel != ctlr->channel)
2023 || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0)))
2027 /* association note has no data to transmit */
2033 nodeid = ctlr->bcastnodeid;
2035 w = (Wifipkt*)b->rp;
2036 if((w->a1[0] & 1) == 0){
2037 flags |= TFlagNeedACK;
2040 flags |= TFlagNeedRTS;
2042 if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){
2043 nodeid = ctlr->bssnodeid;
2047 if(flags & (TFlagNeedRTS|TFlagNeedCTS)){
2048 if(ctlr->type != Type4965){
2049 flags &= ~(TFlagNeedRTS|TFlagNeedCTS);
2050 flags |= TFlagNeedProtection;
2052 flags |= TFlagFullTxOp;
2055 if(p >= wifi->rates)
2056 rate = p - wifi->rates;
2061 /* select first available antenna */
2062 ant = ctlr->rfcfg.txantmask & 7;
2064 ant = ((ant - 1) & ant) ^ ant;
2066 memset(p = c, 0, sizeof(c));
2073 p += 4; /* scratch */
2075 *p++ = ratetab[rate].plcp;
2076 *p++ = ratetab[rate].flags | (ant<<6);
2078 p += 2; /* xflags */
2080 *p++ = 0; /* security */
2081 *p++ = 0; /* linkq */
2085 p += 2; /* reserved */
2086 put32(p, ~0); /* lifetime */
2089 /* BUG: scratch ptr? not clear what this is for */
2090 put32(p, PCIWADDR(ctlr->kwpage));
2093 *p++ = 60; /* rts ntries */
2094 *p++ = 15; /* data ntries */
2096 put16(p, 0); /* timeout */
2099 if((err = qcmd(ctlr, 0, 28, c, p - c, b)) != nil){
2100 print("transmit: %s\n", err);
2106 iwlctl(Ether *edev, void *buf, long n)
2111 if(n >= 5 && memcmp(buf, "reset", 5) == 0){
2116 return wifictl(ctlr->wifi, buf, n);
2121 iwlifstat(Ether *edev, void *buf, long n, ulong off)
2127 return wifistat(ctlr->wifi, buf, n, off);
2132 setoptions(Ether *edev)
2138 for(i = 0; i < edev->nopt; i++)
2139 wificfg(ctlr->wifi, edev->opt[i]);
2143 iwlpromiscuous(void *arg, int on)
2152 rxon(edev, ctlr->wifi->bss);
2157 iwlmulticast(void *, uchar*, int)
2162 iwlrecover(void *arg)
2172 tsleep(&up->sleep, return0, 0, 4000);
2176 if(ctlr->broken == 0)
2182 if((csr32r(ctlr, Gpc) & RfKill) == 0)
2185 if(reset(ctlr) != nil)
2187 if(boot(ctlr) != nil)
2190 ctlr->bcastnodeid = -1;
2191 ctlr->bssnodeid = -1;
2193 rxon(edev, ctlr->wifi->bss);
2201 iwlattach(Ether *edev)
2210 print("#l%d: %s\n", edev->ctlrno, up->errstr);
2216 if(ctlr->attached == 0){
2217 if((csr32r(ctlr, Gpc) & RfKill) == 0)
2218 error("wifi disabled by switch");
2220 if(ctlr->wifi == nil){
2221 qsetlimit(edev->oq, MaxQueue);
2223 ctlr->wifi = wifiattach(edev, transmit);
2224 /* tested with 2230, it has transmit issues using higher bit rates */
2225 if(ctlr->type != Type2030)
2226 ctlr->wifi->rates = iwlrates;
2229 if(ctlr->fw == nil){
2230 char *fn = fwname[ctlr->type];
2231 if(ctlr->type == Type6005){
2232 switch(ctlr->pdev->did){
2233 case 0x0082: /* Centrino Advanced-N 6205 */
2234 case 0x0085: /* Centrino Advanced-N 6205 */
2236 default: /* Centrino Advanced-N 6030, 6235 */
2240 fw = readfirmware(fn);
2241 print("#l%d: firmware: %s, rev %ux, build %ud, size %ux+%ux+%ux+%ux+%ux\n",
2244 fw->main.text.size, fw->main.data.size,
2245 fw->init.text.size, fw->init.data.size,
2246 fw->boot.text.size);
2250 if((err = reset(ctlr)) != nil)
2252 if((err = boot(ctlr)) != nil)
2255 ctlr->bcastnodeid = -1;
2256 ctlr->bssnodeid = -1;
2264 kproc("iwlrecover", iwlrecover, edev);
2280 if(ctlr->broken || rx->s == nil || rx->b == nil)
2284 for(hw = get16(rx->s) % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){
2285 uchar type, flags, idx, qid;
2293 len = get32(d); d += 4;
2304 if((qid & 0x80) == 0 && qid < nelem(ctlr->tx)){
2305 tx = &ctlr->tx[qid];
2316 if(len < 4 || type == 0)
2321 case 1: /* microcontroller ready */
2322 setfwinfo(ctlr, d, len);
2324 case 24: /* add node done */
2326 case 28: /* tx done */
2327 if(ctlr->type == Type4965){
2328 if(len <= 20 || d[20] == 1 || d[20] == 2)
2331 if(len <= 32 || d[32] == 1 || d[32] == 2)
2334 wifitxfail(ctlr->wifi, bb);
2336 case 102: /* calibration result (Type5000 only) */
2340 if(idx >= nelem(ctlr->calib.cmd))
2342 if(rbplant(ctlr, rx->i) < 0)
2344 if(ctlr->calib.cmd[idx] != nil)
2345 freeb(ctlr->calib.cmd[idx]);
2348 ctlr->calib.cmd[idx] = b;
2350 case 103: /* calibration done (Type5000 only) */
2351 ctlr->calib.done = 1;
2353 case 130: /* start scan */
2355 case 132: /* stop scan */
2357 case 156: /* rx statistics */
2359 case 157: /* beacon statistics */
2361 case 161: /* state changed */
2363 case 162: /* beacon missed */
2365 case 192: /* rx phy */
2367 case 195: /* rx done */
2372 case 193: /* mpdu rx done */
2375 len = get16(d); d += 4;
2376 if(d + len + 4 > b->lim)
2378 if((get32(d + len) & 3) != 3)
2380 if(ctlr->wifi == nil)
2382 if(rbplant(ctlr, rx->i) < 0)
2386 wifiiq(ctlr->wifi, b);
2388 case 197: /* rx compressed ba */
2392 csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7);
2398 iwlinterrupt(Ureg*, void *arg)
2407 csr32w(ctlr, Imr, 0);
2408 isr = csr32r(ctlr, Isr);
2409 fhisr = csr32r(ctlr, FhIsr);
2410 if(isr == 0xffffffff || (isr & 0xfffffff0) == 0xa5a5a5a0){
2414 if(isr == 0 && fhisr == 0)
2416 csr32w(ctlr, Isr, isr);
2417 csr32w(ctlr, FhIsr, fhisr);
2418 if((isr & (Iswrx | Ifhrx | Irxperiodic)) || (fhisr & Ifhrx))
2422 print("#l%d: fatal firmware error\n", edev->ctlrno);
2425 ctlr->wait.m |= isr;
2426 if(ctlr->wait.m & ctlr->wait.w)
2427 wakeup(&ctlr->wait);
2429 csr32w(ctlr, Imr, ctlr->ie);
2434 iwlshutdown(Ether *edev)
2444 static Ctlr *iwlhead, *iwltail;
2452 while(pdev = pcimatch(pdev, 0, 0)) {
2456 if(pdev->ccrb != 2 || pdev->ccru != 0x80)
2458 if(pdev->vid != 0x8086)
2464 case 0x0084: /* WiFi Link 1000 */
2465 case 0x4229: /* WiFi Link 4965 */
2466 case 0x4230: /* WiFi Link 4965 */
2467 case 0x4232: /* Wifi Link 5100 */
2468 case 0x4235: /* Intel Corporation Ultimate N WiFi Link 5300 */
2469 case 0x4236: /* WiFi Link 5300 AGN */
2470 case 0x4237: /* Wifi Link 5100 AGN */
2471 case 0x4239: /* Centrino Advanced-N 6200 */
2472 case 0x423d: /* Wifi Link 5150 */
2473 case 0x423b: /* PRO/Wireless 5350 AGN */
2474 case 0x0082: /* Centrino Advanced-N 6205 */
2475 case 0x0085: /* Centrino Advanced-N 6205 */
2476 case 0x422b: /* Centrino Ultimate-N 6300 variant 1 */
2477 case 0x4238: /* Centrino Ultimate-N 6300 variant 2 */
2478 case 0x08ae: /* Centrino Wireless-N 100 */
2479 case 0x0083: /* Centrino Wireless-N 1000 */
2480 case 0x0891: /* Centrino Wireless-N 2200 */
2481 case 0x0887: /* Centrino Wireless-N 2230 */
2482 case 0x0888: /* Centrino Wireless-N 2230 */
2483 case 0x0090: /* Centrino Advanced-N 6030 */
2484 case 0x0091: /* Centrino Advanced-N 6030 */
2485 case 0x088e: /* Centrino Advanced-N 6235 */
2486 case 0x088f: /* Centrino Advanced-N 6235 */
2490 ctlr = malloc(sizeof(Ctlr));
2492 print("iwl: unable to alloc Ctlr\n");
2495 ctlr->port = pdev->mem[0].bar & ~0x0F;
2496 mem = vmap(pdev->mem[0].bar & ~0x0F, pdev->mem[0].size);
2498 print("iwl: can't map %8.8luX\n", pdev->mem[0].bar);
2506 iwltail->link = ctlr;
2521 for(ctlr = iwlhead; ctlr != nil; ctlr = ctlr->link){
2524 if(edev->port == 0 || edev->port == ctlr->port){
2534 edev->port = ctlr->port;
2535 edev->irq = ctlr->pdev->intl;
2536 edev->tbdf = ctlr->pdev->tbdf;
2538 edev->attach = iwlattach;
2539 edev->ifstat = iwlifstat;
2541 edev->shutdown = iwlshutdown;
2542 edev->promiscuous = iwlpromiscuous;
2543 edev->multicast = iwlmulticast;
2546 pcienable(ctlr->pdev);
2547 if(iwlinit(edev) < 0){
2548 pcidisable(ctlr->pdev);
2553 pcisetbme(ctlr->pdev);
2554 intrenable(edev->irq, iwlinterrupt, edev, edev->tbdf, edev->name);
2562 addethercard("iwl", iwlpnp);