2 * Intel WiFi Link driver.
4 * Written without any documentation but Damien Bergaminis
5 * OpenBSD iwn(4) and iwm(4) driver sources. Requires intel
6 * firmware to be present in /lib/firmware/iwn-* on attach.
10 #include "../port/lib.h"
15 #include "../port/pci.h"
16 #include "../port/error.h"
17 #include "../port/netif.h"
18 #include "../port/etherif.h"
19 #include "../port/wifi.h"
22 MaxQueue = 24*1024, /* total buffer is 2*MaxQueue: 48k at 22Mbit ≅ 20ms */
26 Ntxqmax = MaxQueue/1500,
40 FWPagesize = 1<<FWPageshift,
42 FWBlockpages = 1<<FWBlockshift,
43 FWBlocksize = 1<<(FWBlockshift + FWPageshift),
48 Cfg = 0x000, /* config register */
50 CfgMacDashMask = 3<<CfgMacDashShift,
52 CfgMacStepMask = 3<<CfgMacStepShift,
58 CfgPhyTypeMask = 3<<CfgPhyTypeShift,
60 CfgPhyDashMask = 3<<CfgPhyDashShift,
62 CfgPhyStepMask = 3<<CfgPhyStepShift,
71 Isr = 0x008, /* interrupt status */
72 Imr = 0x00c, /* interrupt mask */
85 Ierr = Iswerr | Ihwerr,
86 Idefmask = Ierr | Ifhtx | Ifhrx | Ialive | Iwakeup | Iswrx | Ictreached | Irftoggled,
88 FhIsr = 0x010, /* second interrupt status */
92 Rev = 0x028, /* hardware revision */
94 EepromIo = 0x02c, /* EEPROM i/o register */
99 RelativeAccess = 1<<17,
101 EccUncorrStts = 1<<21,
103 Gpc = 0x024, /* gp cntrl */
105 MacClockReady = 1<<0,
117 GpDrvRadioIqInvert = 1<<7,
125 UcodeGp1RfKill = 1<<1,
126 UcodeGp1CmdBlocked = 1<<2,
127 UcodeGp1CtempStopRf = 1<<3,
129 ShadowRegCtrl = 0x0a8,
132 MboxSetOsAlive = 1<<5,
141 Dbglinkpwrmgmt = 0x250,
153 HbusTargWptr = 0x460,
155 UcodeLoadStatus = 0x1af0,
159 * Flow-Handler registers.
162 FhTfbdCtrl0 = 0x1900, // +q*8
163 FhTfbdCtrl1 = 0x1904, // +q*8
167 FhSramAddr = 0x19a4, // +q*4
169 FhCbbcQueue0 = 0x19d0, // +q*4
170 FhCbbcQueue16 = 0x1bf0, // +q*4
171 FhCbbcQueue20 = 0x1b20, // +q*4
173 FhStatusWptr = 0x1bc0,
177 FhRxConfigEna = 1<<31,
178 FhRxConfigRbSize8K = 1<<16,
179 FhRxConfigSingleFrame = 1<<15,
180 FhRxConfigIrqDstHost = 1<<12,
181 FhRxConfigIgnRxfEmpty = 1<<2,
183 FhRxConfigNrbdShift = 20,
184 FhRxConfigRbTimeoutShift= 4,
188 FhRxQ0Wptr = 0x1c80, // +q*4 (9000 mqrx)
190 FhTxConfig = 0x1d00, // +q*32
191 FhTxConfigDmaCreditEna = 1<<3,
192 FhTxConfigDmaEna = 1<<31,
193 FhTxConfigCirqHostEndTfd= 1<<20,
195 FhTxBufStatus = 0x1d08, // +q*32
196 FhTxBufStatusTbNumShift = 20,
197 FhTxBufStatusTbIdxShift = 12,
198 FhTxBufStatusTfbdValid = 3,
200 FhTxChicken = 0x1e98,
207 * NIC internal memory offsets.
210 ApmgClkCtrl = 0x3000,
217 EarlyPwroffDis = 1<<22,
223 ApmgDigitalSvr = 0x3058,
224 ApmgAnalogSvr = 0x306c,
227 BsmWrMemSrc = 0x3404,
228 BsmWrMemDst = 0x3408,
229 BsmWrDwCount = 0x340c,
230 BsmDramTextAddr = 0x3490,
231 BsmDramTextSize = 0x3494,
232 BsmDramDataAddr = 0x3498,
233 BsmDramDataSize = 0x349c,
234 BsmSramBase = 0x3800,
237 ReleaseCpuReset = 0x300c,
238 CpuResetBit = 0x1000000,
240 LmpmChick = 0xa01ff8,
243 SbCpu1Status = 0xa01e30,
244 SbCpu2Status = 0xa01e34,
245 UregChick = 0xa05c00,
246 UregChickMsiEnable = 1<<24,
248 FhUcodeLoadStatus=0xa05c40,
252 * RX ring for mqrx 9000
255 RfhQ0FreeBase = 0xa08000, // +q*8
256 RfhQ0FreeWptr = 0xa08080, // +q*4
257 RfhQ0FreeRptr = 0xa080c0, // +q*4
259 RfhQ0UsedBase = 0xa08100, // +q*8
260 RfhQ0UsedWptr = 0xa08180, // +q*4
262 RfhQ0SttsBase = 0xa08200, // +q*8
264 RfhGenCfg = 0xa09800,
265 RfhGenServiceDmaSnoop = 1<<0,
266 RfhGenRfhDmaSnoop = 1<<1,
267 RfhGenRbChunkSize64 = 0<<4,
268 RfhGenRbChunkSize128 = 1<<4,
270 RfhGenStatus = 0xa09808,
271 RfhGenStatusDmaIdle = 1<<31,
273 RfhRxqActive = 0xa0980c,
275 RfhDmaCfg = 0xa09820,
276 RfhDma1KSizeShift = 16,
277 RfhDmaNrbdShift = 20,
278 RfhDmaMinRbSizeShift = 24,
279 RfhDmaDropTooLarge = 1<<26,
280 RfhDmaEnable = 1<<31,
284 * TX scheduler registers.
287 SchedBase = 0xa02c00,
288 SchedSramAddr = SchedBase,
290 SchedDramAddr4965 = SchedBase+0x010,
291 SchedTxFact4965 = SchedBase+0x01c,
292 SchedQueueRdptr4965 = SchedBase+0x064, // +q*4
293 SchedQChainSel4965 = SchedBase+0x0d0,
294 SchedIntrMask4965 = SchedBase+0x0e4,
295 SchedQueueStatus4965 = SchedBase+0x104, // +q*4
297 SchedDramAddr = SchedBase+0x008,
298 SchedTxFact = SchedBase+0x010,
299 SchedQueueWrptr = SchedBase+0x018, // +q*4
300 SchedQueueRdptr = SchedBase+0x068, // +q*4
301 SchedQChainSel = SchedBase+0x0e8,
302 SchedIntrMask = SchedBase+0x108,
304 SchedQueueStatus = SchedBase+0x10c, // +q*4
306 SchedGpCtrl = SchedBase+0x1a8,
307 Enable31Queues = 1<<0,
308 AutoActiveMode = 1<<18,
310 SchedChainExtEn = SchedBase+0x244,
311 SchedAggrSel = SchedBase+0x248,
312 SchedEnCtrl = SchedBase+0x254,
314 SchedQueueRdptr20 = SchedBase+0x2b4, // +q*4
315 SchedQueueStatus20 = SchedBase+0x334, // +q*4
319 SchedCtxOff4965 = 0x380,
320 SchedCtxLen4965 = 416,
322 SchedCtxOff = 0x600, // +q*8
324 SchedSttsOff = 0x6A0, // +q*16
326 SchedTransTblOff = 0x7E0, // +q*2
330 FilterPromisc = 1<<0,
332 FilterMulticast = 1<<2,
333 FilterNoDecrypt = 1<<3,
334 FilterNoDecryptMcast = 1<<4,
344 RFlagShPreamble = 1<<5,
345 RFlagNoDiversity = 1<<7,
346 RFlagAntennaA = 1<<8,
347 RFlagAntennaB = 1<<9,
349 RFlagCTSToSelf = 1<<30,
353 TFlagNeedProtection = 1<<0,
359 TFlagFullTxOp = 1<<7,
361 TFlagAutoSeq = 1<<13,
362 TFlagMoreFrag = 1<<14,
363 TFlagInsertTs = 1<<16,
364 TFlagNeedPadding = 1<<20,
373 typedef struct FWInfo FWInfo;
374 typedef struct FWImage FWImage;
375 typedef struct FWSect FWSect;
376 typedef struct FWBlock FWBlock;
377 typedef struct FWMem FWMem;
379 typedef struct TXQ TXQ;
380 typedef struct RXQ RXQ;
382 typedef struct Station Station;
384 typedef struct Ctlr Ctlr;
524 /* assigned sta ids in hardware sta table or -1 if unassigned */
535 /* current receiver settings */
536 uchar bssid[Eaddrlen];
621 /* controller types */
631 Type6005 = 11, /* also Centrino Advanced-N 6030, 6235 */
638 static struct ratetab {
645 { 11, 55, RFlagCCK },
646 { 22, 110, RFlagCCK },
659 static uchar iwlrates[] = {
677 static char *fwname[32] = {
678 [Type4965] "iwn-4965",
679 [Type5300] "iwn-5000",
680 [Type5350] "iwn-5000",
681 [Type5150] "iwn-5150",
682 [Type5100] "iwn-5000",
683 [Type1000] "iwn-1000",
684 [Type6000] "iwn-6000",
685 [Type6050] "iwn-6050",
686 [Type6005] "iwn-6005", /* see in iwlattach() below */
687 [Type2030] "iwn-2030",
688 [Type2000] "iwn-2000",
691 static char *qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block);
692 static char *flushq(Ctlr *ctlr, uint qid);
693 static char *cmd(Ctlr *ctlr, uint code, uchar *data, int size);
695 #define csr32r(c, r) (*((c)->nic+((r)/4)))
696 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
700 return *((u16int*)p);
704 return *((u32int*)p);
707 put32(uchar *p, uint v){
711 put64(uchar *p, uvlong v)
716 put16(uchar *p, uint v){
725 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq);
726 for(i=0; i<1000; i++){
727 if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna)
731 return "niclock: timeout";
735 nicunlock(Ctlr *ctlr)
737 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq);
741 prphread(Ctlr *ctlr, uint off)
744 csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off);
746 return csr32r(ctlr, PrphRdata);
749 prphwrite(Ctlr *ctlr, uint off, u32int data)
752 csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off);
754 csr32w(ctlr, PrphWdata, data);
758 prphwrite64(Ctlr *ctlr, uint off, u64int data)
760 prphwrite(ctlr, off, data & 0xFFFFFFFF);
761 prphwrite(ctlr, off+4, data >> 32);
765 memread(Ctlr *ctlr, uint off)
767 csr32w(ctlr, MemRaddr, off);
769 return csr32r(ctlr, MemRdata);
772 memwrite(Ctlr *ctlr, uint off, u32int data)
774 csr32w(ctlr, MemWaddr, off);
776 csr32w(ctlr, MemWdata, data);
780 setfwinfo(Ctlr *ctlr, uchar *d, int len)
786 case 2+2 + 1+1+2+1+1 + 1+1 + 1+1 + 2 + 4+4+4+4+4+4 + 4:
787 case 2+2 + 1+1+2+1+1 + 1+1 + 1+1 + 2 + 4+4+4+4+4+4 + 4 + 4+4 + 1+1 + 2 + 4+4:
788 i->status = get16(d); d += 2;
789 i->flags = get16(d); d += 2;
802 i->tstamp = get32(d); d += 4;
803 i->errptr = get32(d); d += 4;
804 i->logptr = get32(d); d += 4;
805 i->regptr = get32(d); d += 4;
806 d += 4; // dbgm_config_ptr
807 d += 4; // alive counter ptr
809 i->scdptr = get32(d); d += 4;
811 if(len < 1+1+2+1+1+1+1+1+1+2+4+4+4+4+4 + 4+4+4+1+1+2+4+4)
817 i->umac.minor = *d++;
818 i->umac.major = *d++;
821 i->umac.errptr = get32(d); d += 4;
822 i->umac.logptr = get32(d); d += 4;
824 i->valid = (i->status == 0xcafe);
827 case 2+2 + 4+4 + 1+1 + 1+1 + 4+4+4+4+4+4 + 4 + 4+4 + 4+4+4+4:
828 i->status = get16(d); d += 2;
829 i->flags = get16(d); d += 2;
840 i->tstamp = get32(d); d += 4;
841 i->errptr = get32(d); d += 4;
842 i->logptr = get32(d); d += 4;
843 i->regptr = get32(d); d += 4;
844 d += 4; // dbgm_config_ptr
845 d += 4; // alive counter ptr
847 i->scdptr = get32(d);
853 i->umac.minor = get32(d); d += 4;
854 i->umac.major = get32(d); d += 4;
855 i->umac.errptr = get32(d); d += 4;
856 i->umac.logptr = get32(d); d += 4;
858 i->valid = (i->status == 0xcafe);
870 i->logptr = get32(d); d += 4;
871 i->errptr = get32(d); d += 4;
872 i->tstamp = get32(d); d += 4;
879 printfwinfo(Ctlr *ctlr)
881 FWInfo *i = &ctlr->fwinfo;
883 print("fwinfo: status=%.4ux flags=%.4ux\n",
884 i->status, i->flags);
886 print("fwinfo: ver %ud.%ud type %ud.%ud\n",
887 i->major, i->minor, i->type, i->subtype);
888 print("fwinfo: scdptr=%.8ux\n", i->scdptr);
889 print("fwinfo: regptr=%.8ux\n", i->regptr);
890 print("fwinfo: logptr=%.8ux\n", i->logptr);
891 print("fwinfo: errptr=%.8ux\n", i->errptr);
893 print("fwinfo: ts=%.8ux\n", i->tstamp);
895 print("fwinfo: umac ver %ud.%ud\n", i->umac.major, i->umac.minor);
896 print("fwinfo: umac errptr %.8ux\n", i->umac.errptr);
897 print("fwinfo: umac logptr %.8ux\n", i->umac.logptr);
906 print("lastcmd: %ud (0x%ux)\n", ctlr->tx[4].lastcmd, ctlr->tx[4].lastcmd);
908 if(!ctlr->fwinfo.valid || ctlr->fwinfo.errptr == 0){
909 print("no error pointer\n");
912 for(i=0; i<nelem(dump); i++)
913 dump[i] = memread(ctlr, ctlr->fwinfo.errptr + i*4);
915 if(ctlr->family >= 7000){
916 print( "error:\tid %ux, trm_hw_status %.8ux %.8ux,\n"
917 "\tbranchlink2 %.8ux, interruptlink %.8ux %.8ux,\n"
918 "\terrordata %.8ux %.8ux %.8ux\n",
919 dump[1], dump[2], dump[3],
920 dump[4], dump[5], dump[6],
921 dump[7], dump[8], dump[9]);
923 print( "error:\tid %ux, pc %ux,\n"
924 "\tbranchlink %.8ux %.8ux, interruptlink %.8ux %.8ux,\n"
925 "\terrordata %.8ux %.8ux, srcline %ud, tsf %ux, time %ux\n",
927 dump[4], dump[3], dump[6], dump[5],
928 dump[7], dump[8], dump[9], dump[10], dump[11]);
933 eepromlock(Ctlr *ctlr)
937 for(i=0; i<100; i++){
938 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | EepromLocked);
939 for(j=0; j<100; j++){
940 if(csr32r(ctlr, Cfg) & EepromLocked)
945 return "eepromlock: timeout";
948 eepromunlock(Ctlr *ctlr)
950 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) & ~EepromLocked);
953 eepromread(Ctlr *ctlr, void *data, int count, uint off)
960 off += ctlr->eeprom.off;
961 for(; count > 0; count -= 2, off++){
962 csr32w(ctlr, EepromIo, off << 2);
964 w = csr32r(ctlr, EepromIo);
970 return "eepromread: timeout";
971 if(ctlr->eeprom.otp){
972 s = csr32r(ctlr, OtpromGp);
973 if(s & EccUncorrStts)
974 return "eepromread: otprom ecc error";
976 csr32w(ctlr, OtpromGp, s);
990 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
992 if(csr32r(ctlr, Cfg) & NicReady)
996 if(ctlr->family >= 7000){
997 csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31));
1001 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | Prepare);
1002 for(i=0; i<15000; i++){
1003 if((csr32r(ctlr, Cfg) & PrepareDone) == 0)
1008 return "handover: timeout";
1010 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
1012 if(csr32r(ctlr, Cfg) & NicReady)
1016 return "handover: timeout";
1018 if(ctlr->family >= 7000)
1019 csr32w(ctlr, MboxSet, csr32r(ctlr, MboxSet) | MboxSetOsAlive);
1024 clockwait(Ctlr *ctlr)
1028 /* Set "initialization complete" bit. */
1029 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone);
1030 for(i=0; i<2500; i++){
1031 if(csr32r(ctlr, Gpc) & MacClockReady)
1035 return "clockwait: timeout";
1045 if(ctlr->family >= 7000){
1046 /* Reset entire device */
1047 csr32w(ctlr, Reset, (1<<7));
1051 if(ctlr->family < 8000){
1052 /* Disable L0s exit timer (NMI bug workaround). */
1053 csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | DisL0Stimer);
1056 /* Don't wait for ICH L0s (ICH bug workaround). */
1057 csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | L1AnoL0Srx);
1059 /* Set FH wait threshold to max (HW bug under stress workaround). */
1060 csr32w(ctlr, Dbghpetmem, csr32r(ctlr, Dbghpetmem) | 0xffff0000);
1062 /* Enable HAP INTA to move adapter from L1a to L0s. */
1063 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | HapwakeL1A);
1065 capoff = pcicap(ctlr->pdev, PciCapPCIe);
1067 /* Workaround for HW instability in PCIe L0->L0s->L1 transition. */
1068 if(pcicfgr16(ctlr->pdev, capoff + 0x10) & 0x2) /* LCSR -> L1 Entry enabled. */
1069 csr32w(ctlr, Gio, csr32r(ctlr, Gio) | EnaL0S);
1071 csr32w(ctlr, Gio, csr32r(ctlr, Gio) & ~EnaL0S);
1074 if(ctlr->family < 7000){
1075 if(ctlr->type != Type4965 && ctlr->type <= Type1000)
1076 csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | 0x00880300);
1079 /* Wait for clock stabilization before accessing prph. */
1080 if((err = clockwait(ctlr)) != nil)
1084 /* Newer cards default to MSIX? */
1085 if((err = niclock(ctlr)) != nil)
1087 prphwrite(ctlr, UregChick, UregChickMsiEnable);
1091 if(ctlr->family < 8000){
1092 if((err = niclock(ctlr)) != nil)
1095 /* Enable DMA and BSM (Bootstrap State Machine). */
1096 if(ctlr->type == Type4965)
1097 prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt);
1099 prphwrite(ctlr, ApmgClkEna, DmaClkRqt);
1102 /* Disable L1-Active. */
1103 prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11));
1114 poweroff(Ctlr *ctlr)
1118 csr32w(ctlr, Reset, 1);
1120 /* Disable interrupts */
1122 csr32w(ctlr, Imr, 0);
1123 csr32w(ctlr, Isr, ~0);
1124 csr32w(ctlr, FhIsr, ~0);
1126 /* Stop scheduler */
1127 if(ctlr->family >= 7000 || ctlr->type != Type4965)
1128 prphwrite(ctlr, SchedTxFact, 0);
1130 prphwrite(ctlr, SchedTxFact4965, 0);
1133 if(niclock(ctlr) == nil){
1134 for(i = 0; i < ctlr->ndma; i++){
1135 csr32w(ctlr, FhTxConfig + i*32, 0);
1136 for(j = 0; j < 200; j++){
1137 if(csr32r(ctlr, FhTxStatus) & (0x10000<<i))
1146 if(niclock(ctlr) == nil){
1148 prphwrite(ctlr, RfhDmaCfg, 0);
1149 for(j = 0; j < 200; j++){
1150 if(prphread(ctlr, RfhGenStatus) & RfhGenStatusDmaIdle)
1155 csr32w(ctlr, FhRxConfig, 0);
1156 for(j = 0; j < 200; j++){
1157 if(csr32r(ctlr, FhRxStatus) & 0x1000000)
1165 if(ctlr->family <= 7000){
1167 if(niclock(ctlr) == nil){
1168 prphwrite(ctlr, ApmgClkDis, DmaClkRqt);
1174 if(ctlr->family >= 7000){
1175 csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31));
1176 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | Prepare|EnablePme);
1178 csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) & ~(1<<31));
1182 /* Stop busmaster DMA activity. */
1183 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | (1<<9));
1184 for(j = 0; j < 100; j++){
1185 if(csr32r(ctlr, Reset) & (1<<8))
1190 /* Reset the entire device. */
1191 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | (1<<7));
1194 /* Clear "initialization complete" bit. */
1195 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~InitDone);
1208 ctlr->eeprom.otp = 0;
1209 ctlr->eeprom.off = 0;
1210 if(ctlr->type < Type1000 || (csr32r(ctlr, OtpromGp) & DevSelOtp) == 0)
1213 /* Wait for clock stabilization before accessing prph. */
1214 if((err = clockwait(ctlr)) != nil)
1217 if((err = niclock(ctlr)) != nil)
1219 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | ResetReq);
1221 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) & ~ResetReq);
1224 /* Set auto clock gate disable bit for HW with OTP shadow RAM. */
1225 if(ctlr->type != Type1000)
1226 csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31));
1228 csr32w(ctlr, EepromGp, csr32r(ctlr, EepromGp) & ~0x00000180);
1230 /* Clear ECC status. */
1231 csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) | (EccCorrStts | EccUncorrStts));
1233 ctlr->eeprom.otp = 1;
1234 if(ctlr->type != Type1000)
1237 /* Switch to absolute addressing mode. */
1238 csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) & ~RelativeAccess);
1241 * Find the block before last block (contains the EEPROM image)
1242 * for HW without OTP shadow RAM.
1246 if((err = eepromread(ctlr, buf, 2, last)) != nil)
1253 if(i == 0 || i >= 3)
1254 return "rominit: missing eeprom image";
1256 ctlr->eeprom.off = prev+1;
1261 iwlinit(Ether *edev)
1266 uint u, caloff, regoff;
1270 /* Clear device-specific "PCI retry timeout" register (41h). */
1271 if(pcicfgr8(ctlr->pdev, 0x41) != 0)
1272 pcicfgw8(ctlr->pdev, 0x41, 0);
1274 /* Clear interrupt disable bit. Hardware bug workaround. */
1275 if(ctlr->pdev->pcr & 0x400){
1276 ctlr->pdev->pcr &= ~0x400;
1277 pcicfgw16(ctlr->pdev, PciPCR, ctlr->pdev->pcr);
1280 ctlr->type = csr32r(ctlr, Rev);
1281 if(ctlr->family >= 8000){
1282 ctlr->type &= 0xFFFF;
1284 ctlr->step = ctlr->type & 15, ctlr->type >>= 4;
1286 ctlr->type &= 0x1FF;
1287 ctlr->dash = ctlr->type & 3, ctlr->type >>= 2;
1288 ctlr->step = ctlr->type & 3, ctlr->type >>= 2;
1289 if(fwname[ctlr->type] == nil){
1290 print("iwl: unsupported controller type %d\n", ctlr->type);
1295 if((err = handover(ctlr)) != nil)
1298 /* >= 7000 family needs firmware loaded to access NVM */
1299 if(ctlr->family >= 7000)
1302 if((err = poweron(ctlr)) != nil)
1305 if((csr32r(ctlr, EepromGp) & 0x7) == 0){
1306 err = "bad rom signature";
1309 if((err = eepromlock(ctlr)) != nil)
1311 if((err = rominit(ctlr)) != nil)
1313 if((err = eepromread(ctlr, edev->ea, sizeof(edev->ea), 0x15)) != nil){
1317 if((err = eepromread(ctlr, b, 2, 0x048)) != nil){
1323 ctlr->rfcfg.type = u & 3; u >>= 2;
1324 ctlr->rfcfg.step = u & 3; u >>= 2;
1325 ctlr->rfcfg.dash = u & 3; u >>= 4;
1326 ctlr->rfcfg.txantmask = u & 15; u >>= 4;
1327 ctlr->rfcfg.rxantmask = u & 15;
1328 if((err = eepromread(ctlr, b, 2, 0x66)) != nil)
1331 if((err = eepromread(ctlr, b, 4, regoff+1)) != nil)
1333 strncpy(ctlr->eeprom.regdom, (char*)b, 4);
1334 ctlr->eeprom.regdom[4] = 0;
1335 if((err = eepromread(ctlr, b, 2, 0x67)) != nil)
1338 if((err = eepromread(ctlr, b, 4, caloff)) != nil)
1340 ctlr->eeprom.version = b[0];
1341 ctlr->eeprom.type = b[1];
1342 ctlr->eeprom.volt = get16(b+2);
1344 ctlr->eeprom.temp = 0;
1345 ctlr->eeprom.rawtemp = 0;
1346 if(ctlr->type == Type2030 || ctlr->type == Type2000){
1347 if((err = eepromread(ctlr, b, 2, caloff + 0x12a)) != nil)
1349 ctlr->eeprom.temp = get16(b);
1350 if((err = eepromread(ctlr, b, 2, caloff + 0x12b)) != nil)
1352 ctlr->eeprom.rawtemp = get16(b);
1355 if(ctlr->type != Type4965 && ctlr->type != Type5150){
1356 if((err = eepromread(ctlr, b, 4, caloff + 0x128)) != nil)
1358 ctlr->eeprom.crystal = get32(b);
1364 ctlr->rfcfg.txantmask = 3;
1365 ctlr->rfcfg.rxantmask = 7;
1368 ctlr->rfcfg.txantmask = 2;
1369 ctlr->rfcfg.rxantmask = 3;
1372 if(ctlr->pdev->did == 0x422c || ctlr->pdev->did == 0x4230){
1373 ctlr->rfcfg.txantmask = 6;
1374 ctlr->rfcfg.rxantmask = 6;
1381 print("iwlinit: %s\n", err);
1387 crackfw(FWImage *i, uchar *data, uint size, int alt)
1393 memset(i, 0, sizeof(*i));
1396 return "firmware image too short";
1400 i->rev = get32(p); p += 4;
1404 if(size < (4+64+4+4+8))
1406 if(memcmp(p, "IWL\n", 4) != 0)
1407 return "bad firmware signature";
1409 strncpy(i->descr, (char*)p, 64);
1412 i->rev = get32(p); p += 4;
1413 i->build = get32(p); p += 4;
1414 altmask = get32(p); p += 4;
1415 altmask |= (uvlong)get32(p) << 32; p += 4;
1416 while(alt > 0 && (altmask & (1ULL<<alt)) == 0)
1418 for(;p < e; p += (l + 3) & ~3){
1422 t = get32(p), p += 4;
1423 l = get32(p), p += 4;
1427 if((t >> 16) != 0 && (t >> 16) != alt)
1433 if(i->main.nsect < 1)
1435 s->addr = 0x00000000;
1439 if(i->main.nsect < 2)
1441 s->addr = 0x00800000;
1445 if(i->init.nsect < 1)
1447 s->addr = 0x00000000;
1451 if(i->init.nsect < 2)
1453 s->addr = 0x00800000;
1457 s->addr = 0x00000000;
1460 if(i->main.nsect >= nelem(i->main.sect))
1461 return "too many main sections";
1462 s = &i->main.sect[i->main.nsect++];
1465 if(i->init.nsect >= nelem(i->init.sect))
1466 return "too many init sections";
1467 s = &i->init.sect[i->init.nsect++];
1482 i->main.defcalib.flowmask = get32(p+4);
1483 i->main.defcalib.eventmask = get32(p+8);
1486 i->init.defcalib.flowmask = get32(p+4);
1487 i->init.defcalib.eventmask = get32(p+8);
1494 i->physku = get32(p);
1500 if(t >= nelem(i->api))
1502 i->api[t] = get32(p+4);
1508 if(t >= nelem(i->capa))
1510 i->capa[t] = get32(p+4);
1515 i->pagedmemsize = get32(p) & -FWPagesize;
1520 if(((i->rev>>8) & 0xFF) < 2)
1521 return "need firmware api >= 2";
1522 if(((i->rev>>8) & 0xFF) >= 3){
1523 i->build = get32(p); p += 4;
1528 i->main.text.size = get32(p); p += 4;
1529 i->main.data.size = get32(p); p += 4;
1530 i->init.text.size = get32(p); p += 4;
1531 i->init.data.size = get32(p); p += 4;
1532 i->boot.text.size = get32(p); p += 4;
1534 i->main.text.data = p; p += i->main.text.size;
1535 i->main.data.data = p; p += i->main.data.size;
1536 i->init.text.data = p; p += i->init.text.size;
1537 i->init.data.data = p; p += i->init.data.size;
1538 i->boot.text.data = p; p += i->boot.text.size;
1544 i->main.text.addr = 0x00000000;
1545 i->main.data.addr = 0x00800000;
1546 i->init.text.addr = 0x00000000;
1547 i->init.data.addr = 0x00800000;
1553 readfirmware(char *name)
1555 uchar dirbuf[sizeof(Dir)+100], *data;
1556 char buf[128], *err;
1565 snprint(buf, sizeof buf, "/boot/%s", name);
1566 c = namec(buf, Aopen, OREAD, 0);
1569 snprint(buf, sizeof buf, "/lib/firmware/%s", name);
1570 c = namec(buf, Aopen, OREAD, 0);
1576 n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf);
1578 error("can't stat firmware");
1579 convM2D(dirbuf, n, &d, nil);
1580 fw = smalloc(sizeof(*fw) + 16 + d.length);
1581 data = (uchar*)(fw+1);
1587 while(r < d.length){
1588 n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r);
1593 if((err = crackfw(fw, data, r, 1)) != nil)
1606 return (ctlr->wait.m & ctlr->wait.w) != 0;
1610 irqwait(Ctlr *ctlr, u32int mask, int timeout)
1615 r = ctlr->wait.m & mask;
1617 ctlr->wait.w = mask;
1620 tsleep(&ctlr->wait, gotirq, ctlr, timeout);
1625 r = ctlr->wait.m & mask;
1633 rbplant(Ctlr *ctlr, uint i)
1639 b = iallocb(Rbufsize*2);
1642 b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, Rbufsize);
1643 memset(b->rp, 0, Rdscsize);
1648 put64(ctlr->rx.p + (i<<3), PCIWADDR(b->rp));
1650 put32(ctlr->rx.p + (i<<2), PCIWADDR(b->rp) >> 8);
1662 if(ctlr->fw->pagedmemsize > 0){
1663 ctlr->fwmem.npage = ctlr->fw->pagedmemsize >> FWPageshift;
1664 ctlr->fwmem.nblock = ctlr->fwmem.npage >> FWBlockshift;
1665 if(ctlr->fwmem.nblock >= nelem(ctlr->fwmem.block)-1)
1666 return "paged memory size too big";
1667 for(i = 0; i < ctlr->fwmem.nblock; i++)
1668 ctlr->fwmem.block[i].size = FWBlocksize;
1669 ctlr->fwmem.block[i].size = (ctlr->fwmem.npage % FWBlockpages) << FWPageshift;
1670 if(ctlr->fwmem.block[i].size != 0)
1671 ctlr->fwmem.nblock++;
1672 for(i = 0; i < ctlr->fwmem.nblock; i++){
1673 if(ctlr->fwmem.block[i].p == nil){
1674 ctlr->fwmem.block[i].p = mallocalign(ctlr->fwmem.block[i].size, FWPagesize, 0, 0);
1675 if(ctlr->fwmem.block[i].p == nil)
1676 return "no memory for firmware block";
1679 if(ctlr->fwmem.css == nil){
1680 if((ctlr->fwmem.css = mallocalign(FWPagesize, FWPagesize, 0, 0)) == nil)
1681 return "no memory for firmware css page";
1688 rx->u = mallocalign(4 * Nrx, 4096, 0, 0);
1690 rx->p = mallocalign(8 * Nrx, 4096, 0, 0);
1691 if(rx->u == nil || rx->p == nil)
1692 return "no memory for rx rings";
1693 memset(rx->u, 0, 4 * Nrx);
1694 memset(rx->p, 0, 8 * Nrx);
1698 rx->p = mallocalign(4 * Nrx, 256, 0, 0);
1700 return "no memory for rx rings";
1701 memset(rx->p, 0, 4 * Nrx);
1704 rx->s = mallocalign(Rstatsize, 4096, 0, 0);
1706 rx->b = malloc(sizeof(Block*) * Nrx);
1707 if(rx->b == nil || rx->s == nil)
1708 return "no memory for rx ring";
1709 memset(rx->s, 0, Rstatsize);
1710 for(i=0; i<Nrx; i++){
1711 if(rx->b[i] != nil){
1715 if(rbplant(ctlr, i) < 0)
1716 return "no memory for rx descriptors";
1722 if(ctlr->family >= 7000) {
1725 if(ctlr->type == Type4965) {
1731 if(ctlr->sched.s == nil)
1732 ctlr->sched.s = mallocalign((256+64)*2 * ctlr->ntxq, 4096, 0, 0);
1733 if(ctlr->sched.s == nil)
1734 return "no memory for sched buffer";
1735 memset(ctlr->sched.s, 0, (256+64)*2 * ctlr->ntxq);
1737 for(q=0; q < nelem(ctlr->tx); q++){
1740 tx->b = malloc(sizeof(Block*) * Ntx);
1742 tx->d = mallocalign(Tdscsize * Ntx, 4096, 0, 0);
1744 tx->c = mallocalign(Tcmdsize * Ntx, 4096, 0, 0);
1745 if(tx->b == nil || tx->d == nil || tx->c == nil)
1746 return "no memory for tx ring";
1747 memset(tx->d, 0, Tdscsize * Ntx);
1748 memset(tx->c, 0, Tcmdsize * Ntx);
1749 for(i=0; i<Ntx; i++){
1750 if(tx->b[i] != nil){
1751 freeblist(tx->b[i]);
1760 if(ctlr->kwpage == nil)
1761 ctlr->kwpage = mallocalign(4096, 4096, 0, 0);
1762 if(ctlr->kwpage == nil)
1763 return "no memory for kwpage";
1764 memset(ctlr->kwpage, 0, 4096);
1777 if((err = initmem(ctlr)) != nil)
1779 if((err = poweron(ctlr)) != nil)
1782 if(ctlr->family <= 7000){
1783 if((err = niclock(ctlr)) != nil)
1785 prphwrite(ctlr, ApmgPs, (prphread(ctlr, ApmgPs) & ~PwrSrcMask) | PwrSrcVMain);
1789 if(ctlr->family >= 7000){
1792 u = csr32r(ctlr, Cfg);
1794 u &= ~(RadioSi|MacSi|CfgMacDashMask|CfgMacStepMask|CfgPhyTypeMask|CfgPhyStepMask|CfgPhyDashMask);
1796 u |= (ctlr->step << CfgMacStepShift) & CfgMacStepMask;
1797 u |= (ctlr->dash << CfgMacDashShift) & CfgMacDashMask;
1799 u |= ctlr->rfcfg.type << CfgPhyTypeShift;
1800 u |= ctlr->rfcfg.step << CfgPhyStepShift;
1801 u |= ctlr->rfcfg.dash << CfgPhyDashShift;
1803 csr32w(ctlr, Cfg, u);
1806 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | RadioSi | MacSi);
1809 if(ctlr->family < 8000){
1810 if((err = niclock(ctlr)) != nil)
1812 if(ctlr->family == 7000 || ctlr->type != Type4965)
1813 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | EarlyPwroffDis);
1816 if(ctlr->family < 7000){
1817 if((err = niclock(ctlr)) != nil)
1819 if(ctlr->type == Type1000){
1821 * Select first Switching Voltage Regulator (1.32V) to
1822 * solve a stability issue related to noisy DC2DC line
1823 * in the silicon of 1000 Series.
1825 prphwrite(ctlr, ApmgDigitalSvr,
1826 (prphread(ctlr, ApmgDigitalSvr) & ~(0xf<<5)) | (3<<5));
1828 if((ctlr->type == Type6005 || ctlr->type == Type6050) && ctlr->eeprom.version == 6)
1829 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvCalV6);
1830 if(ctlr->type == Type6005)
1831 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrv1X2);
1832 if(ctlr->type == Type2030 || ctlr->type == Type2000)
1833 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvRadioIqInvert);
1837 if((err = niclock(ctlr)) != nil)
1842 prphwrite(ctlr, RfhDmaCfg, 0);
1843 /* Disable RX used and free queue operation. */
1844 prphwrite(ctlr, RfhRxqActive, 0);
1846 prphwrite64(ctlr, RfhQ0SttsBase, PCIWADDR(ctlr->rx.s));
1847 prphwrite64(ctlr, RfhQ0FreeBase, PCIWADDR(ctlr->rx.p));
1848 prphwrite64(ctlr, RfhQ0UsedBase, PCIWADDR(ctlr->rx.u));
1850 prphwrite(ctlr, RfhQ0FreeWptr, 0);
1851 prphwrite(ctlr, RfhQ0FreeRptr, 0);
1852 prphwrite(ctlr, RfhQ0UsedWptr, 0);
1855 prphwrite(ctlr, RfhDmaCfg,
1857 RfhDmaDropTooLarge |
1858 ((Rbufsize/1024) << RfhDma1KSizeShift) |
1859 (3 << RfhDmaMinRbSizeShift) |
1860 (Nrxlog << RfhDmaNrbdShift));
1862 /* Enable RX DMA snooping. */
1863 prphwrite(ctlr, RfhGenCfg,
1864 RfhGenServiceDmaSnoop |
1866 RfhGenRbChunkSize128);
1869 prphwrite(ctlr, RfhRxqActive, (1 << 16) | 1);
1872 csr32w(ctlr, FhRxQ0Wptr, (Nrx-1) & ~7);
1875 csr32w(ctlr, FhRxConfig, 0);
1876 csr32w(ctlr, FhRxWptr, 0);
1877 csr32w(ctlr, FhRxBase, PCIWADDR(ctlr->rx.p) >> 8);
1878 csr32w(ctlr, FhStatusWptr, PCIWADDR(ctlr->rx.s) >> 4);
1879 csr32w(ctlr, FhRxConfig,
1881 FhRxConfigIgnRxfEmpty |
1882 FhRxConfigIrqDstHost |
1883 FhRxConfigSingleFrame |
1884 (Nrxlog << FhRxConfigNrbdShift));
1886 csr32w(ctlr, FhRxWptr, (Nrx-1) & ~7);
1889 for(i = 0; i < ctlr->ndma; i++)
1890 csr32w(ctlr, FhTxConfig + i*32, 0);
1892 if(ctlr->family >= 7000 || ctlr->type != Type4965)
1893 prphwrite(ctlr, SchedTxFact, 0);
1895 prphwrite(ctlr, SchedTxFact4965, 0);
1897 if(ctlr->family >= 7000){
1898 prphwrite(ctlr, SchedEnCtrl, 0);
1899 prphwrite(ctlr, SchedGpCtrl, prphread(ctlr, SchedGpCtrl)
1900 | Enable31Queues*(ctlr->ntxq == 31)
1902 for(q = 0; q < ctlr->ntxq; q++)
1903 prphwrite(ctlr, (q<20? SchedQueueStatus: SchedQueueStatus20) + q*4, 1 << 19);
1906 csr32w(ctlr, FhKwAddr, PCIWADDR(ctlr->kwpage) >> 4);
1907 for(q = 0; q < ctlr->ntxq; q++){
1908 i = q < nelem(ctlr->tx) ? q : nelem(ctlr->tx)-1;
1910 csr32w(ctlr, FhCbbcQueue0 + q*4, PCIWADDR(ctlr->tx[i].d) >> 8);
1912 csr32w(ctlr, FhCbbcQueue16 + (q-16)*4, PCIWADDR(ctlr->tx[i].d) >> 8);
1914 csr32w(ctlr, FhCbbcQueue20 + (q-20)*4, PCIWADDR(ctlr->tx[i].d) >> 8);
1917 if(ctlr->family >= 7000 || ctlr->type >= Type6000)
1918 csr32w(ctlr, ShadowRegCtrl, csr32r(ctlr, ShadowRegCtrl) | 0x800fffff);
1922 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
1923 csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
1931 ctlr->bcast.id = -1;
1938 ctlr->te.active = 0;
1941 if(ctlr->family >= 9000)
1942 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | 0x4000000);
1944 ctlr->ie = Idefmask;
1945 csr32w(ctlr, Imr, ctlr->ie);
1946 csr32w(ctlr, Isr, ~0);
1948 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
1949 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
1950 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
1956 sendmccupdate(Ctlr *ctlr, char *mcc)
1958 uchar c[2+1+1+4+5*4], *p;
1960 memset(p = c, 0, sizeof(c));
1964 *p++ = 0; // reserved
1969 return cmd(ctlr, 200, c, p - c);
1973 sendbtcoexadv(Ctlr *ctlr)
1975 static u32int btcoex3wire[12] = {
1976 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
1977 0xcc00ff28, 0x0000aaaa, 0xcc00aaaa, 0x0000aaaa,
1978 0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,
1981 uchar c[Tcmdsize], *p;
1986 memset(c, 0, sizeof(c));
1989 if(ctlr->family >= 7000){
1994 } else if(ctlr->type == Type2030){
1995 *p++ = 145; /* flags */
1996 p++; /* lead time */
1997 *p++ = 5; /* max kill */
1998 *p++ = 1; /* bt3 t7 timer */
1999 put32(p, 0xffff0000); /* kill ack */
2001 put32(p, 0xffff0000); /* kill cts */
2003 *p++ = 2; /* sample time */
2004 *p++ = 0xc; /* bt3 t2 timer */
2005 p += 2; /* bt4 reaction */
2006 for (i = 0; i < nelem(btcoex3wire); i++){
2007 put32(p, btcoex3wire[i]);
2010 p += 2; /* bt4 decision */
2011 put16(p, 0xff); /* valid */
2013 put32(p, 0xf0); /* prio boost */
2016 p++; /* tx prio boost */
2017 p += 2; /* rx prio boost */
2019 if((err = cmd(ctlr, 155, c, p-c)) != nil)
2022 if(ctlr->family >= 7000)
2025 /* set BT priority */
2026 memset(c, 0, sizeof(c));
2029 *p++ = 0x6; /* init1 */
2030 *p++ = 0x7; /* init2 */
2031 *p++ = 0x2; /* periodic low1 */
2032 *p++ = 0x3; /* periodic low2 */
2033 *p++ = 0x4; /* periodic high1 */
2034 *p++ = 0x5; /* periodic high2 */
2035 *p++ = 0x6; /* dtim */
2036 *p++ = 0x8; /* scan52 */
2037 *p++ = 0xa; /* scan24 */
2038 p += 7; /* reserved */
2039 if((err = cmd(ctlr, 204, c, p-c)) != nil)
2042 /* force BT state machine change */
2043 memset(c, 0, sizeof(c));
2046 *p++ = 1; /* open */
2047 *p++ = 1; /* type */
2048 p += 2; /* reserved */
2049 if((err = cmd(ctlr, 205, c, p-c)) != nil)
2052 c[0] = 0; /* open */
2053 return cmd(ctlr, 205, c, p-c);
2057 sendpagingcmd(Ctlr *ctlr)
2059 uchar c[3*4 + 4 + 32*4], *p;
2063 put32(p, (3<<8) | (ctlr->fwmem.npage % FWBlockpages));
2065 put32(p, FWPageshift + FWBlockshift);
2067 put32(p, ctlr->fwmem.nblock);
2070 put32(p, PCIWADDR(ctlr->fwmem.css) >> FWPageshift);
2073 for(i = 0; i < ctlr->fwmem.nblock; i++){
2074 put32(p, PCIWADDR(ctlr->fwmem.block[i].p) >> FWPageshift);
2083 return cmd(ctlr, 79 | (1<<8), c, p-c);
2087 enablepaging(Ctlr *ctlr)
2093 if(ctlr->fwmem.css == nil)
2097 /* clear everything */
2098 memset(ctlr->fwmem.css, 0, FWPagesize);
2099 for(i = 0; i < ctlr->fwmem.nblock; i++)
2100 memset(ctlr->fwmem.block[i].p, 0, ctlr->fwmem.block[i].size);
2103 if(ctlr->calib.done == 0){
2104 sect = ctlr->fw->init.sect;
2105 nsect = ctlr->fw->init.nsect;
2107 sect = ctlr->fw->main.sect;
2108 nsect = ctlr->fw->main.nsect;
2111 /* first CSS segment */
2112 for(i = 0; i < nsect; i++) {
2113 if(sect[i].addr == 0xAAAABBBB){
2120 return "firmware misses CSS+paging sections";
2122 if(sect[i].size > FWPagesize)
2123 return "CSS section too big";
2124 if(sect[i+1].size > (ctlr->fwmem.npage << FWPageshift))
2125 return "paged section too big";
2127 memmove(ctlr->fwmem.css, sect[i].data, sect[i].size);
2129 for(j = 0, o = 0; o < sect[i+1].size; o += n, j++){
2130 n = sect[i+1].size - o;
2131 if(n > ctlr->fwmem.block[j].size)
2132 n = ctlr->fwmem.block[j].size;
2133 memmove(ctlr->fwmem.block[j].p, sect[i+1].data + o, n);
2136 return sendpagingcmd(ctlr);
2140 readnvmsect1(Ctlr *ctlr, int type, void *data, int len, int off)
2142 uchar c[2+2+2+2], *p;
2146 *p++ = 0; // read op
2157 ctlr->nvm.type = -1;
2160 ctlr->nvm.buf = data;
2161 ctlr->nvm.len = len;
2163 if((err = cmd(ctlr, 136, c, p - c)) != nil){
2164 ctlr->nvm.buf = nil;
2166 print("readnvmsect: %s\n", err);
2170 if(ctlr->nvm.ret < len)
2171 len = ctlr->nvm.ret;
2173 if(ctlr->nvm.sts != 0 || ctlr->nvm.off != off || (ctlr->nvm.type & 0xFF) != type)
2180 readnvmsect(Ctlr *ctlr, int type, void *data, int len, int off)
2184 for(o = 0; o < len; o += n){
2188 if((n = readnvmsect1(ctlr, type, (char*)data + o, r, o+off)) < 0)
2199 readnvmconfig(Ctlr *ctlr)
2201 uchar *ea = ctlr->edev->ea;
2206 if(readnvmsect(ctlr, 1, buf, 8, 0) != 8)
2207 return "can't read nvm version";
2209 ctlr->nvm.version = get16(buf);
2210 if (ctlr->family == 7000) {
2213 ctlr->rfcfg.type = (u >> 4) & 3;
2214 ctlr->rfcfg.step = (u >> 2) & 3;
2215 ctlr->rfcfg.dash = (u >> 0) & 3;
2216 ctlr->rfcfg.pnum = (u >> 6) & 3;
2218 ctlr->rfcfg.txantmask = (u >> 8) & 15;
2219 ctlr->rfcfg.rxantmask = (u >> 12) & 15;
2222 if(readnvmsect(ctlr, 12, buf, 8, 0) != 8)
2223 return "can't read nvm phy config";
2227 ctlr->rfcfg.type = (u >> 12) & 0xFFF;
2228 ctlr->rfcfg.step = (u >> 8) & 15;
2229 ctlr->rfcfg.dash = (u >> 4) & 15;
2230 ctlr->rfcfg.pnum = (u >> 6) & 3;
2232 ctlr->rfcfg.txantmask = (u >> 24) & 15;
2233 ctlr->rfcfg.rxantmask = (u >> 28) & 15;
2235 if(ctlr->family >= 8000){
2236 if(readnvmsect(ctlr, 11, ea, Eaddrlen, 0x01<<1) != Eaddrlen){
2239 if((err = niclock(ctlr)) != nil)
2241 a0 = prphread(ctlr, 0xa03080);
2242 a1 = prphread(ctlr, 0xa03084);
2253 readnvmsect(ctlr, 0, ea, Eaddrlen, 0x15<<1);
2255 memmove(ctlr->edev->addr, ea, Eaddrlen);
2261 sendtxantconfig(Ctlr *ctlr, uint val)
2266 return cmd(ctlr, 152, c, 4);
2270 sendphyconfig(Ctlr *ctlr, u32int physku, u32int flowmask, u32int eventmask)
2275 put32(c+4, flowmask);
2276 put32(c+8, eventmask);
2277 return cmd(ctlr, 106, c, 3*4);
2281 delstation(Ctlr *ctlr, Station *sta)
2289 memset(p = c, 0, sizeof(c));
2292 if((err = cmd(ctlr, 25, c, 4)) != nil)
2301 StaTypeGeneralPurpose,
2308 setstation(Ctlr *ctlr, int id, int type, uchar addr[6], Station *sta)
2310 uchar c[Tcmdsize], *p;
2313 memset(p = c, 0, sizeof(c));
2315 *p++ = 0; /* control (1 = update) */
2317 if(ctlr->family >= 7000){
2320 put32(p, ctlr->macid);
2323 p += 2; /* reserved */
2326 memmove(p, addr, 6);
2329 *p++ = id; /* sta id */
2331 if(ctlr->family >= 7000){
2332 *p++ = 1 << 1; /* modify mask */
2333 p += 2; /* reserved */
2335 put32(p, 0<<26 | 0<<28);
2336 p += 4; /* station_flags */
2338 put32(p, 3<<26 | 3<<28);
2339 p += 4; /* station_flags_mask */
2341 p++; /* add_immediate_ba_tid */
2342 p++; /* remove_immediate_ba_tid */
2343 p += 2; /* add_immediate_ba_ssn */
2344 p += 2; /* sleep_tx_count */
2345 p++; /* sleep state flags */
2347 *p++ = (ctlr->fw->api[0] & (1<<30)) != 0 ? type : 0; /* station_type */
2349 p += 2; /* assoc id */
2351 p += 2; /* beamform flags */
2354 p += 4; /* tfd_queue_mask */
2357 p += 2; /* rx_ba_window */
2358 p++; /* sp_length */
2359 p++; /* uapsd_acs */
2363 p += 2; /* kflags */
2366 p += 5*2; /* ttak */
2370 if(ctlr->type != Type4965){
2375 p += 4; /* htflags */
2377 p += 2; /* disable tid */
2378 p += 2; /* reserved */
2379 p++; /* add ba tid */
2380 p++; /* del ba tid */
2381 p += 2; /* add ba ssn */
2382 p += 4; /* reserved */
2385 if((err = cmd(ctlr, 24, c, p - c)) != nil)
2392 setphycontext(Ctlr *ctlr, int amr)
2394 uchar c[Tcmdsize], *p;
2398 phyid = ctlr->phyid;
2400 if(amr == CmdRemove)
2404 } else if(amr == CmdAdd)
2407 memset(p = c, 0, sizeof(c));
2408 put32(p, phyid); // id and color
2412 put32(p, 0); // apply time 0 = immediate
2414 put32(p, 0); // tx param color ????
2417 *p++ = (ctlr->rxflags & RFlag24Ghz) != 0;
2418 *p++ = ctlr->channel; // channel number
2419 *p++ = 0; // channel width (20MHz<<val)
2420 *p++ = 0; // pos1 below
2422 put32(p, ctlr->rfcfg.txantmask);
2424 put32(p, ctlr->rfcfg.rxantmask<<1 | (1<<10) | (1<<12));
2426 put32(p, 0); // acquisition_data ????
2428 put32(p, 0); // dsp_cfg_flags
2431 if((err = cmd(ctlr, 8, c, p - c)) != nil)
2434 if(amr == CmdRemove)
2436 ctlr->phyid = phyid;
2441 reciprocal(u32int v)
2443 return v != 0 ? 0xFFFFFFFFU / v : 0;
2447 setmaccontext(Ether *edev, Ctlr *ctlr, int amr, Wnode *bss)
2449 uchar c[4+4 + 4+4 + 8+8 + 4+4+4+4+4+4+4 + 5*8 + 12*4], *p;
2453 macid = ctlr->macid;
2455 if(amr == CmdRemove)
2459 } else if(amr == CmdAdd)
2462 memset(p = c, 0, sizeof(c));
2468 put32(p, 5); // mac type 5 = bss
2471 put32(p, 0); // tsf id ???
2474 memmove(p, edev->ea, 6);
2477 memmove(p, ctlr->bssid, 6);
2480 put32(p, bss == nil? 0xF : (bss->validrates & 0xF));
2482 put32(p, bss == nil? 0xFF : (bss->validrates >> 4));
2485 put32(p, 0); // protection flags
2488 put32(p, ctlr->rxflags & RFlagShPreamble);
2490 put32(p, ctlr->rxflags & RFlagShSlot);
2492 put32(p, ctlr->rxfilter);
2495 put32(p, 0); // qos flags
2498 for(i = 0; i < 4; i++){
2499 put16(p, 0x07); // cw_min
2501 put16(p, 0x0f); // cw_max
2504 *p++ = (1<<i); // fifos_mask
2505 put16(p, 102*32); // edca_txop
2511 int dtimoff = bss->ival * (int)bss->dtimcount * 1024;
2514 put32(p, bss->aid != 0);
2517 /* dtim time (system time) */
2518 put32(p, bss->rs + dtimoff);
2522 put64(p, bss->ts + dtimoff);
2525 /* beacon interval */
2526 put32(p, bss->ival);
2528 put32(p, reciprocal(bss->ival));
2532 put32(p, bss->ival * bss->dtimperiod);
2534 put32(p, reciprocal(bss->ival * bss->dtimperiod));
2537 /* listen interval */
2542 put32(p, bss->aid & 0x3fff);
2545 /* assoc beacon arrive time */
2551 if((err = cmd(ctlr, 40, c, sizeof(c))) != nil)
2554 if(amr == CmdRemove)
2556 ctlr->macid = macid;
2562 setbindingcontext(Ctlr *ctlr, int amr)
2564 uchar c[Tcmdsize], *p;
2569 bindid = ctlr->bindid;
2571 if(amr == CmdRemove)
2575 } else if(amr == CmdAdd)
2579 return "setbindingcontext: no phyid";
2581 return "setbindingcontext: no macid";
2590 if(amr != CmdRemove){
2591 put32(p, ctlr->macid);
2599 put32(p, ctlr->phyid);
2602 if((err = cmd(ctlr, 43, c, p - c)) != nil)
2605 if(amr == CmdRemove)
2607 ctlr->bindid = bindid;
2612 timeeventdone(void *arg)
2615 return ctlr->te.id == -1 || ctlr->te.active != 0;
2619 settimeevent(Ctlr *ctlr, int amr, int ival)
2621 int duration, delay, timeid;
2627 timeid = ctlr->te.id;
2637 timeid = ctlr->te.id;
2651 memset(p = c, 0, sizeof(c));
2652 put32(p, ctlr->macid);
2659 put32(p, 0); // apply time
2663 put32(p, 0); // depends on
2665 put32(p, 1); // interval
2670 *p++ = 0; // max frags
2671 put16(p, 1<<0 | 1<<1 | 1<<11); // policy
2674 ctlr->te.active = 0;
2675 if((err = cmd(ctlr, 41, c, p - c)) != nil)
2678 if(amr == CmdRemove){
2679 ctlr->te.active = 0;
2683 tsleep(&ctlr->te, timeeventdone, ctlr, 100);
2684 return ctlr->te.active? nil: "timeevent did not start";
2689 setbindingquotas(Ctlr *ctlr, int bindid)
2691 uchar c[4*(3*4)], *p;
2715 return cmd(ctlr, 44, c, p - c);
2719 setmcastfilter(Ctlr *ctlr)
2728 *p++ = 1; // filter own
2729 *p++ = 0; // port id
2731 *p++ = 1; // pass all
2733 memmove(p, ctlr->bssid, 6);
2739 if((err = qcmd(ctlr, 4, 208, nil, 0, b)) != nil){
2743 return flushq(ctlr, 4);
2747 setmacpowermode(Ctlr *ctlr)
2749 uchar c[4 + 2+2 + 4+4+4+4 + 1+1 + 2+2 + 1+1+1+1 + 1+1+1+1 + 1+1], *p;
2752 put32(p, ctlr->macid);
2755 put16(p, 0); // flags
2757 put16(p, 5); // keep alive seconds
2760 put32(p, 0); // rx data timeout
2762 put32(p, 0); // tx data timeout
2764 put32(p, 0); // rx data timeout uapsd
2766 put32(p, 0); // tx data timeout uapsd
2769 *p++ = 0; // lprx rssi threshold
2770 *p++ = 0; // skip dtim periods
2772 put16(p, 0); // snooze interval
2774 put16(p, 0); // snooze window
2777 *p++ = 0; // snooze step
2778 *p++ = 0; // qndp tid
2779 *p++ = 0; // uapsd ac flags
2780 *p++ = 0; // uapsd max sp
2782 *p++ = 0; // heavy tx thld packets
2783 *p++ = 0; // heavy rx thld packets
2785 *p++ = 0; // heavy tx thld percentage
2786 *p++ = 0; // heavy rx thld percentage
2788 *p++ = 0; // limited ps threshold
2789 *p++ = 0; // reserved
2791 return cmd(ctlr, 169, c, p - c);
2795 disablebeaconfilter(Ctlr *ctlr)
2799 memset(c, 0, sizeof(c));
2800 return cmd(ctlr, 210, c, 11*4);
2804 updatedevicepower(Ctlr *ctlr)
2808 memset(c, 0, sizeof(c));
2809 put16(c, 0<<13 | 1<<0); // cont active off, pm enable
2811 return cmd(ctlr, 119, c, 4);
2815 postboot7000(Ctlr *ctlr)
2819 if(ctlr->calib.done == 0){
2820 if((err = readnvmconfig(ctlr)) != nil)
2824 if((err = sendtxantconfig(ctlr, ctlr->rfcfg.txantmask)) != nil)
2827 if(ctlr->calib.done == 0){
2828 if((err = sendphyconfig(ctlr,
2830 ctlr->fw->init.defcalib.flowmask,
2831 ctlr->fw->init.defcalib.eventmask)) != nil)
2834 /* wait to collect calibration records */
2835 if(irqwait(ctlr, Ierr, 2000))
2836 return "calibration failed";
2838 if(ctlr->calib.done == 0){
2839 print("iwl: no calibration results\n");
2840 ctlr->calib.done = 1;
2846 for(i = 0; i < nelem(ctlr->calib.cmd); i++){
2847 if((b = ctlr->calib.cmd[i]) == nil)
2849 b = copyblock(b, BLEN(b));
2850 if((qcmd(ctlr, 4, 108, nil, 0, b)) != nil){
2854 if((err = flushq(ctlr, 4)) != nil)
2858 if((err = sendphyconfig(ctlr,
2860 ctlr->fw->main.defcalib.flowmask,
2861 ctlr->fw->main.defcalib.eventmask)) != nil)
2864 if((err = sendbtcoexadv(ctlr)) != nil)
2867 if((err = updatedevicepower(ctlr)) != nil){
2868 print("can't update device power: %s\n", err);
2871 if((err = sendmccupdate(ctlr, "ZZ")) != nil){
2872 print("can't disable beacon filter: %s\n", err);
2875 if((err = disablebeaconfilter(ctlr)) != nil){
2876 print("can't disable beacon filter: %s\n", err);
2885 postboot6000(Ctlr *ctlr)
2890 /* disable wimax coexistance */
2891 memset(c, 0, sizeof(c));
2892 if((err = cmd(ctlr, 90, c, 4+4*16)) != nil)
2895 /* 6235 times out if we calibrate the crystal immediately */
2896 tsleep(&up->sleep, return0, nil, 10);
2897 if(ctlr->type != Type5150){
2898 /* calibrate crystal */
2899 memset(c, 0, sizeof(c));
2900 c[0] = 15; /* code */
2901 c[1] = 0; /* group */
2902 c[2] = 1; /* ngroup */
2903 c[3] = 1; /* isvalid */
2904 c[4] = ctlr->eeprom.crystal;
2905 c[5] = ctlr->eeprom.crystal>>16;
2906 /* for some reason 8086:4238 needs a second try */
2907 if(cmd(ctlr, 176, c, 8) != nil && (err = cmd(ctlr, 176, c, 8)) != nil)
2911 if(ctlr->calib.done == 0){
2912 /* query calibration (init firmware) */
2913 memset(c, 0, sizeof(c));
2914 put32(c + 0*(5*4) + 0, 0xffffffff);
2915 put32(c + 0*(5*4) + 4, 0xffffffff);
2916 put32(c + 0*(5*4) + 8, 0xffffffff);
2917 put32(c + 2*(5*4) + 0, 0xffffffff);
2918 if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil)
2921 /* wait to collect calibration records */
2922 if(irqwait(ctlr, Ierr, 2000))
2923 return "calibration failed";
2925 if(ctlr->calib.done == 0){
2926 print("iwl: no calibration results\n");
2927 ctlr->calib.done = 1;
2930 static uchar cmds[] = {8, 9, 11, 17, 16};
2933 /* send calibration records (runtime firmware) */
2934 for(q=0; q<nelem(cmds); q++){
2939 if(i == 8 && ctlr->type != Type5150 && ctlr->type != Type2030 &&
2940 ctlr->type != Type2000)
2942 if(i == 17 && (ctlr->type >= Type6000 || ctlr->type == Type5150) &&
2943 ctlr->type != Type2030 && ctlr->type != Type2000)
2946 if((b = ctlr->calib.cmd[i]) == nil)
2948 b = copyblock(b, BLEN(b));
2949 if((err = qcmd(ctlr, 4, 176, nil, 0, b)) != nil){
2953 if((err = flushq(ctlr, 4)) != nil)
2957 /* temperature sensor offset */
2958 switch (ctlr->type){
2960 memset(c, 0, sizeof(c));
2966 if((err = cmd(ctlr, 176, c, 4+2+2)) != nil)
2972 memset(c, 0, sizeof(c));
2977 if(ctlr->eeprom.rawtemp != 0){
2978 put16(c + 4, ctlr->eeprom.temp);
2979 put16(c + 6, ctlr->eeprom.rawtemp);
2984 put16(c + 8, ctlr->eeprom.volt);
2985 if((err = cmd(ctlr, 176, c, 4+2+2+2+2)) != nil)
2990 if(ctlr->type == Type6005 || ctlr->type == Type6050){
2991 /* runtime DC calibration */
2992 memset(c, 0, sizeof(c));
2993 put32(c + 0*(5*4) + 0, 0xffffffff);
2994 put32(c + 0*(5*4) + 4, 1<<1);
2995 if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil)
2999 if((err = sendtxantconfig(ctlr, ctlr->rfcfg.txantmask & 7)) != nil)
3002 if(ctlr->type == Type2030){
3003 if((err = sendbtcoexadv(ctlr)) != nil)
3011 initqueue(Ctlr *ctlr, int qid, int fifo, int chainmode, int window)
3013 csr32w(ctlr, HbusTargWptr, (qid << 8) | 0);
3015 if(ctlr->family >= 7000 || ctlr->type != Type4965){
3016 if(ctlr->family >= 7000)
3017 prphwrite(ctlr, SchedQueueStatus + qid*4, 1 << 19);
3020 prphwrite(ctlr, SchedQChainSel, prphread(ctlr, SchedQChainSel) | (1<<qid));
3022 prphwrite(ctlr, SchedQChainSel, prphread(ctlr, SchedQChainSel) & ~(1<<qid));
3024 prphwrite(ctlr, SchedAggrSel, prphread(ctlr, SchedAggrSel) & ~(1<<qid));
3026 prphwrite(ctlr, SchedQueueRdptr + qid*4, 0);
3028 /* Set scheduler window size and frame limit. */
3029 memwrite(ctlr, ctlr->sched.base + SchedCtxOff + qid*8, 0);
3030 memwrite(ctlr, ctlr->sched.base + SchedCtxOff + qid*8 + 4, window<<16 | window);
3032 if(ctlr->family >= 7000){
3033 prphwrite(ctlr, SchedQueueStatus + qid*4, 0x017f0018 | fifo);
3035 prphwrite(ctlr, SchedQueueStatus + qid*4, 0x00ff0018 | fifo);
3039 prphwrite(ctlr, SchedQChainSel4965, prphread(ctlr, SchedQChainSel4965) | (1<<qid));
3041 prphwrite(ctlr, SchedQChainSel4965, prphread(ctlr, SchedQChainSel4965) & ~(1<<qid));
3043 prphwrite(ctlr, SchedQueueRdptr4965 + qid*4, 0);
3045 /* Set scheduler window size and frame limit. */
3046 memwrite(ctlr, ctlr->sched.base + SchedCtxOff4965 + qid*8, window);
3047 memwrite(ctlr, ctlr->sched.base + SchedCtxOff4965 + qid*8 + 4, window<<16);
3049 prphwrite(ctlr, SchedQueueStatus4965 + qid*4, 0x0007fc01 | fifo<<1);
3054 postboot(Ctlr *ctlr)
3056 uint ctxoff, ctxlen, dramaddr;
3060 if((err = niclock(ctlr)) != nil)
3063 if(ctlr->family >= 7000 || ctlr->type != Type4965){
3064 dramaddr = SchedDramAddr;
3065 ctxoff = SchedCtxOff;
3066 ctxlen = (SchedTransTblOff + 2*ctlr->ntxq) - ctxoff;
3068 dramaddr = SchedDramAddr4965;
3069 ctxoff = SchedCtxOff4965;
3070 ctxlen = SchedCtxLen4965;
3073 ctlr->sched.base = prphread(ctlr, SchedSramAddr);
3074 for(i=0; i < ctxlen; i += 4)
3075 memwrite(ctlr, ctlr->sched.base + ctxoff + i, 0);
3077 prphwrite(ctlr, dramaddr, PCIWADDR(ctlr->sched.s)>>10);
3079 if(ctlr->family >= 7000) {
3080 prphwrite(ctlr, SchedEnCtrl, 0);
3081 prphwrite(ctlr, SchedChainExtEn, 0);
3084 for(i = 0; i < nelem(ctlr->tx); i++){
3085 if(i == 4 && ctlr->family < 7000 && ctlr->type == Type4965)
3088 static char qid2fifo[] = {
3089 3, 2, 1, 0, 7, 5, 6,
3093 initqueue(ctlr, i, f, i != 4 && ctlr->type != Type4965, 64);
3096 /* Enable interrupts for all queues. */
3097 if(ctlr->family >= 7000){
3098 prphwrite(ctlr, SchedEnCtrl, 1 << 4);
3099 } else if(ctlr->type != Type4965) {
3100 prphwrite(ctlr, SchedIntrMask, (1<<ctlr->ntxq)-1);
3102 prphwrite(ctlr, SchedIntrMask4965, (1<<ctlr->ntxq)-1);
3105 /* Identify TX FIFO rings (0-7). */
3106 if(ctlr->family >= 7000 || ctlr->type != Type4965){
3107 prphwrite(ctlr, SchedTxFact, 0xff);
3109 prphwrite(ctlr, SchedTxFact4965, 0xff);
3112 /* Enable DMA channels */
3113 for(i = 0; i < ctlr->ndma; i++)
3114 csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna);
3116 /* Auto Retry Enable */
3117 csr32w(ctlr, FhTxChicken, csr32r(ctlr, FhTxChicken) | 2);
3121 if((err = enablepaging(ctlr)) != nil){
3122 ctlr->calib.done = 0;
3126 if(ctlr->family >= 7000)
3127 return postboot7000(ctlr);
3128 else if(ctlr->type != Type4965)
3129 return postboot6000(ctlr);
3135 loadfirmware1(Ctlr *ctlr, u32int dst, uchar *data, int size)
3137 enum { Maxchunk = 0x20000 };
3141 while(size > Maxchunk){
3142 if((err = loadfirmware1(ctlr, dst, data, Maxchunk)) != nil)
3149 dma = mallocalign(size, 16, 0, 0);
3151 return "no memory for dma";
3152 memmove(dma, data, size);
3155 if((err = niclock(ctlr)) != nil){
3160 if(ctlr->family >= 7000 && dst >= 0x40000 && dst < 0x57fff)
3161 prphwrite(ctlr, LmpmChick, prphread(ctlr, LmpmChick) | ExtAddr);
3163 prphwrite(ctlr, LmpmChick, prphread(ctlr, LmpmChick) & ~ExtAddr);
3165 csr32w(ctlr, FhTxConfig + 9*32, 0);
3166 csr32w(ctlr, FhSramAddr + 9*4, dst);
3167 csr32w(ctlr, FhTfbdCtrl0 + 9*8, PCIWADDR(dma));
3168 csr32w(ctlr, FhTfbdCtrl1 + 9*8, size);
3169 csr32w(ctlr, FhTxBufStatus + 9*32,
3170 (1<<FhTxBufStatusTbNumShift) |
3171 (1<<FhTxBufStatusTbIdxShift) |
3172 FhTxBufStatusTfbdValid);
3173 csr32w(ctlr, FhTxConfig + 9*32, FhTxConfigDmaEna | FhTxConfigCirqHostEndTfd);
3177 if(irqwait(ctlr, Ifhtx|Ierr, 5000) != Ifhtx)
3178 err = "dma error / timeout";
3180 if(niclock(ctlr) == nil){
3181 prphwrite(ctlr, LmpmChick, prphread(ctlr, LmpmChick) & ~ExtAddr);
3191 setloadstatus(Ctlr *ctlr, u32int val)
3195 if((err = niclock(ctlr)) != nil)
3197 csr32w(ctlr, UcodeLoadStatus, val);
3203 loadsections(Ctlr *ctlr, FWSect *sect, int nsect)
3208 if(ctlr->family >= 8000){
3209 if((err = niclock(ctlr)) != nil)
3211 prphwrite(ctlr, ReleaseCpuReset, CpuResetBit);
3216 for(i = 0; i < nsect; i++){
3217 if(sect[i].addr == 0xAAAABBBB)
3219 if(sect[i].addr == 0xFFFFCCCC)
3222 if(sect[i].data == nil || sect[i].size == 0)
3223 return "bad load section";
3224 if((err = loadfirmware1(ctlr, sect[i].addr, sect[i].data, sect[i].size)) != nil)
3228 if(ctlr->family >= 8000
3229 && (err = setloadstatus(ctlr, (1ULL << num)-1)) != nil)
3236 ucodestart(Ctlr *ctlr)
3238 memset(&ctlr->fwinfo, 0, sizeof(ctlr->fwinfo));
3239 if(ctlr->family >= 8000)
3240 return setloadstatus(ctlr, -1);
3241 csr32w(ctlr, Reset, 0);
3255 if(fw->boot.text.size == 0){
3256 if(ctlr->calib.done == 0){
3257 if((err = loadsections(ctlr, fw->init.sect, fw->init.nsect)) != nil)
3259 if((err = ucodestart(ctlr)) != nil)
3262 tsleep(&up->sleep, return0, 0, 100);
3264 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive|| !ctlr->fwinfo.valid){
3265 return "init firmware boot failed";
3267 if((err = postboot(ctlr)) != nil)
3269 if((err = reset(ctlr)) != nil)
3273 if((err = loadsections(ctlr, fw->main.sect, fw->main.nsect)) != nil)
3275 if((err= ucodestart(ctlr)) != nil)
3278 tsleep(&up->sleep, return0, 0, 100);
3280 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive || !ctlr->fwinfo.valid)
3281 return "main firmware boot failed";
3283 return postboot(ctlr);
3286 if(ctlr->family >= 7000)
3287 return "wrong firmware image";
3289 size = ROUND(fw->init.data.size, 16) + ROUND(fw->init.text.size, 16);
3290 dma = mallocalign(size, 16, 0, 0);
3292 return "no memory for dma";
3294 if((err = niclock(ctlr)) != nil){
3300 memmove(p, fw->init.data.data, fw->init.data.size);
3302 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
3303 prphwrite(ctlr, BsmDramDataSize, fw->init.data.size);
3304 p += ROUND(fw->init.data.size, 16);
3305 memmove(p, fw->init.text.data, fw->init.text.size);
3307 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
3308 prphwrite(ctlr, BsmDramTextSize, fw->init.text.size);
3311 if((err = niclock(ctlr)) != nil){
3316 p = fw->boot.text.data;
3317 n = fw->boot.text.size/4;
3318 for(i=0; i<n; i++, p += 4)
3319 prphwrite(ctlr, BsmSramBase+i*4, get32(p));
3321 prphwrite(ctlr, BsmWrMemSrc, 0);
3322 prphwrite(ctlr, BsmWrMemDst, 0);
3323 prphwrite(ctlr, BsmWrDwCount, n);
3325 prphwrite(ctlr, BsmWrCtrl, 1<<31);
3327 for(i=0; i<1000; i++){
3328 if((prphread(ctlr, BsmWrCtrl) & (1<<31)) == 0)
3335 return "bootcode timeout";
3338 prphwrite(ctlr, BsmWrCtrl, 1<<30);
3341 csr32w(ctlr, Reset, 0);
3342 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
3344 return "boot firmware boot failed";
3348 size = ROUND(fw->main.data.size, 16) + ROUND(fw->main.text.size, 16);
3349 dma = mallocalign(size, 16, 0, 0);
3351 return "no memory for dma";
3352 if((err = niclock(ctlr)) != nil){
3357 memmove(p, fw->main.data.data, fw->main.data.size);
3359 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
3360 prphwrite(ctlr, BsmDramDataSize, fw->main.data.size);
3361 p += ROUND(fw->main.data.size, 16);
3362 memmove(p, fw->main.text.data, fw->main.text.size);
3364 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
3365 prphwrite(ctlr, BsmDramTextSize, fw->main.text.size | (1<<31));
3368 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
3370 return "main firmware boot failed";
3373 return postboot(ctlr);
3380 return q->n < Ntxqmax;
3384 qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
3391 assert(qid < ctlr->ntxq);
3393 if((code & 0xFF00) != 0)
3398 if(hdrlen+size > Tcmdsize)
3399 bcmd = allocb(hdrlen + size);
3405 while(q->n >= Ntxqmax && !ctlr->broken){
3409 tsleep(q, txqready, q, 5);
3417 return "qcmd: broken";
3424 bcmd->next = q->b[q->i];
3428 bcmd->wp = c + hdrlen + size;
3430 c = q->c + q->i * Tcmdsize;
3436 c[1] = code>>8; /* group id */
3444 c[1] = 0; /* flags */
3449 memmove(c+hdrlen, data, size);
3452 /* build descriptor */
3453 d = q->d + q->i * Tdscsize;
3457 *d++ = 1 + (block != nil); /* nsegs */
3458 put32(d, PCIWADDR(c)); d += 4;
3459 put16(d, size << 4); d += 2;
3462 put32(d, PCIWADDR(block->rp)); d += 4;
3463 put16(d, size << 4); d += 2;
3469 q->i = (q->i+1) % Ntx;
3470 csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i);
3485 flushq(Ctlr *ctlr, uint qid)
3492 for(i = 0; i < 200 && !ctlr->broken; i++){
3498 tsleep(q, txqempty, q, 10);
3504 return "flushq: broken";
3506 return "flushq: timeout";
3510 cmd(Ctlr *ctlr, uint code, uchar *data, int size)
3514 if(0) print("cmd %ud\n", code);
3516 if((err = qcmd(ctlr, 4, code, data, size, nil)) != nil
3517 || (err = flushq(ctlr, 4)) != nil){
3518 print("#l%d: cmd %ud: %s\n", ctlr->edev->ctlrno, code, err);
3525 setled(Ctlr *ctlr, int which, int on, int off)
3529 if(ctlr->family >= 7000)
3532 csr32w(ctlr, Led, csr32r(ctlr, Led) & ~LedBsmCtrl);
3538 cmd(ctlr, 72, c, sizeof(c));
3542 rxoff7000(Ether *edev, Ctlr *ctlr)
3547 for(i = 0; i < nelem(ctlr->tx); i++)
3549 settimeevent(ctlr, CmdRemove, 0);
3551 if((err = setbindingquotas(ctlr, -1)) != nil){
3552 print("can't disable quotas: %s\n", err);
3555 if((err = delstation(ctlr, &ctlr->bss)) != nil){
3556 print("can't remove bss station: %s\n", err);
3559 if((err = delstation(ctlr, &ctlr->bcast)) != nil){
3560 print("can't remove bcast station: %s\n", err);
3563 if((err = setbindingcontext(ctlr, CmdRemove)) != nil){
3564 print("removing bindingcontext: %s\n", err);
3567 if((err = setmaccontext(edev, ctlr, CmdRemove, nil)) != nil){
3568 print("removing maccontext: %s\n", err);
3571 if((err = setphycontext(ctlr, CmdRemove)) != nil){
3572 print("setphycontext: %s\n", err);
3579 rxon7000(Ether *edev, Ctlr *ctlr)
3583 if((err = setphycontext(ctlr, CmdAdd)) != nil){
3584 print("setphycontext: %s\n", err);
3587 if((err = setmaccontext(edev, ctlr, CmdAdd, nil)) != nil){
3588 print("setmaccontext: %s\n", err);
3591 if((err = setbindingcontext(ctlr, CmdAdd)) != nil){
3592 print("removing bindingcontext: %s\n", err);
3595 if((err = setmcastfilter(ctlr)) != nil){
3596 print("can't set mcast filter: %s\n", err);
3599 if((err = setmacpowermode(ctlr)) != nil){
3600 print("can't set mac power: %s\n", err);
3603 if((err = setbindingquotas(ctlr, ctlr->aid != 0 ? ctlr->bindid : -1)) != nil){
3604 print("can't set binding quotas: %s\n", err);
3611 rxon6000(Ether *edev, Ctlr *ctlr)
3613 uchar c[Tcmdsize], *p;
3616 memset(p = c, 0, sizeof(c));
3617 memmove(p, edev->ea, 6); p += 8; /* myaddr */
3618 memmove(p, ctlr->bssid, 6); p += 8; /* bssid */
3619 memmove(p, edev->ea, 6); p += 8; /* wlap */
3620 *p++ = 3; /* mode (STA) */
3621 *p++ = 0; /* air (?) */
3623 put16(p, ((ctlr->rfcfg.rxantmask & 7)<<1) | (2<<10) | (2<<12));
3625 *p++ = 0xff; /* ofdm mask (not yet negotiated) */
3626 *p++ = 0x0f; /* cck mask (not yet negotiated) */
3627 put16(p, ctlr->aid & 0x3fff);
3629 put32(p, ctlr->rxflags);
3631 put32(p, ctlr->rxfilter);
3633 *p++ = ctlr->channel;
3635 *p++ = 0xff; /* ht single mask */
3636 *p++ = 0xff; /* ht dual mask */
3637 if(ctlr->type != Type4965){
3638 *p++ = 0xff; /* ht triple mask */
3640 put16(p, 0); p += 2; /* acquisition */
3641 p += 2; /* reserved */
3643 if((err = cmd(ctlr, 16, c, p - c)) != nil){
3644 print("rxon6000: %s\n", err);
3651 rxon(Ether *edev, Wnode *bss)
3653 Ctlr *ctlr = edev->ctlr;
3656 if(ctlr->family >= 7000)
3657 if((err = rxoff7000(edev, ctlr)) != nil)
3660 ctlr->rxfilter = FilterNoDecrypt | FilterMulticast | FilterBeacon;
3661 if(ctlr->family >= 7000)
3662 ctlr->rxfilter |= FilterNoDecryptMcast;
3664 ctlr->rxfilter |= FilterPromisc;
3666 ctlr->rxflags = RFlagTSF | RFlagCTSToSelf | RFlag24Ghz | RFlagAuto;
3668 ctlr->aid = bss->aid;
3669 ctlr->channel = bss->channel;
3670 memmove(ctlr->bssid, bss->bssid, sizeof(ctlr->bssid));
3671 if(bss->cap & (1<<5))
3672 ctlr->rxflags |= RFlagShPreamble;
3673 if(bss->cap & (1<<10))
3674 ctlr->rxflags |= RFlagShSlot;
3676 ctlr->rxfilter |= FilterBSS;
3677 ctlr->rxfilter &= ~FilterBeacon;
3680 ctlr->bcast.id = -1;
3684 memmove(ctlr->bssid, edev->bcast, sizeof(ctlr->bssid));
3685 ctlr->bcast.id = -1;
3690 setled(ctlr, 2, 0, 1); /* on when associated */
3691 else if(memcmp(ctlr->bssid, edev->bcast, sizeof(ctlr->bssid)) != 0)
3692 setled(ctlr, 2, 10, 10); /* slow blink when connecting */
3694 setled(ctlr, 2, 5, 5); /* fast blink when scanning */
3696 if(ctlr->wifi->debug)
3697 print("#l%d: rxon: bssid %E, aid %x, channel %d, rxfilter %ux, rxflags %ux\n",
3698 edev->ctlrno, ctlr->bssid, ctlr->aid, ctlr->channel, ctlr->rxfilter, ctlr->rxflags);
3700 if(ctlr->family >= 7000)
3701 err = rxon7000(edev, ctlr);
3703 err = rxon6000(edev, ctlr);
3707 if(ctlr->bcast.id == -1){
3708 if((err = setstation(ctlr,
3709 (ctlr->type != Type4965)? 15: 31,
3710 StaTypeGeneralPurpose,
3712 &ctlr->bcast)) != nil)
3715 if(ctlr->bss.id == -1 && bss != nil && ctlr->aid != 0){
3716 if((err = setstation(ctlr,
3720 &ctlr->bss)) != nil)
3723 if(ctlr->family >= 7000)
3724 if((err = setmaccontext(edev, ctlr, CmdModify, bss)) != nil)
3732 transmit(Wifi *wifi, Wnode *wn, Block *b)
3734 int flags, rate, ant;
3735 uchar c[Tcmdsize], *p;
3746 if(ctlr->attached == 0 || ctlr->broken){
3753 if((wn->channel != ctlr->channel)
3754 || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0))){
3755 if(rxon(edev, wn) != nil)
3760 * unless authenticated, the firmware will hop
3761 * channels unless we force it onto a channel using
3764 if(ctlr->aid == 0 && ctlr->family >= 7000)
3765 if(settimeevent(ctlr, CmdAdd, wn->ival) != nil)
3769 /* association note has no data to transmit */
3776 w = (Wifipkt*)b->rp;
3777 if((w->a1[0] & 1) == 0){
3778 flags |= TFlagNeedACK;
3781 flags |= TFlagNeedRTS;
3783 if((w->fc[0] & 0x0c) == 0x08 && ctlr->bss.id != -1){
3788 if(flags & (TFlagNeedRTS|TFlagNeedCTS)){
3789 if(ctlr->family >= 7000 || ctlr->type != Type4965){
3790 flags &= ~(TFlagNeedRTS|TFlagNeedCTS);
3791 flags |= TFlagNeedProtection;
3793 flags |= TFlagFullTxOp;
3800 if(p >= wifi->rates)
3801 rate = p - wifi->rates;
3805 /* select first available antenna */
3806 ant = ctlr->rfcfg.txantmask & 7;
3808 ant = ((ant - 1) & ant) ^ ant;
3810 memset(p = c, 0, sizeof(c));
3817 p += 4; /* scratch */
3819 *p++ = ratetab[rate].plcp;
3820 *p++ = ratetab[rate].flags | (ant<<6);
3822 p += 2; /* xflags */
3823 *p++ = sta->id; /* station id */
3824 *p++ = 0; /* security */
3825 *p++ = 0; /* linkq */
3829 p += 2; /* reserved */
3830 put32(p, ~0); /* lifetime */
3833 /* BUG: scratch ptr? not clear what this is for */
3834 put32(p, PCIWADDR(ctlr->kwpage));
3837 *p++ = 60; /* rts ntries */
3838 *p++ = 15; /* data ntries */
3840 put16(p, 0); /* timeout */
3845 if((err = qcmd(ctlr, 0, 28, c, p - c, b)) != nil){
3846 print("#l%d: transmit %s\n", edev->ctlrno, err);
3852 iwlctl(Ether *edev, void *buf, long n)
3857 if(n >= 5 && memcmp(buf, "reset", 5) == 0){
3862 return wifictl(ctlr->wifi, buf, n);
3867 iwlifstat(Ether *edev, void *buf, long n, ulong off)
3873 return wifistat(ctlr->wifi, buf, n, off);
3878 setoptions(Ether *edev)
3884 for(i = 0; i < edev->nopt; i++)
3885 wificfg(ctlr->wifi, edev->opt[i]);
3889 iwlpromiscuous(void *arg, int on)
3898 rxon(edev, ctlr->wifi->bss);
3903 iwlmulticast(void *, uchar*, int)
3908 iwlrecover(void *arg)
3918 tsleep(&up->sleep, return0, 0, 4000);
3922 if(ctlr->broken == 0)
3928 if((csr32r(ctlr, Gpc) & RfKill) == 0)
3931 if(reset(ctlr) != nil)
3933 if(boot(ctlr) != nil)
3936 rxon(edev, ctlr->wifi->bss);
3944 iwlattach(Ether *edev)
3953 print("#l%d: %s\n", edev->ctlrno, up->errstr);
3959 if(ctlr->attached == 0){
3960 if((csr32r(ctlr, Gpc) & RfKill) == 0)
3961 error("wifi disabled by switch");
3963 if(ctlr->fw == nil){
3968 fn = fwname[ctlr->type];
3969 if(ctlr->type == Type6005){
3970 switch(ctlr->pdev->did){
3971 case 0x0082: /* Centrino Advanced-N 6205 */
3972 case 0x0085: /* Centrino Advanced-N 6205 */
3974 default: /* Centrino Advanced-N 6030, 6235 */
3979 fw = readfirmware(fn);
3980 print("#l%d: firmware: %s, rev %ux, build %ud, size [%d] %ux+%ux + [%d] %ux+%ux + %ux\n",
3983 fw->main.nsect, fw->main.text.size, fw->main.data.size,
3984 fw->init.nsect, fw->init.text.size, fw->init.data.size,
3985 fw->boot.text.size);
3989 if(ctlr->family >= 7000){
3990 u32int u = ctlr->fw->physku;
3992 ctlr->rfcfg.type = u & 3; u >>= 2;
3993 ctlr->rfcfg.step = u & 3; u >>= 2;
3994 ctlr->rfcfg.dash = u & 3; u >>= 12;
3996 ctlr->rfcfg.txantmask = u & 15; u >>= 4;
3997 ctlr->rfcfg.rxantmask = u & 15;
4000 if((err = reset(ctlr)) != nil)
4002 if((err = boot(ctlr)) != nil)
4005 if(ctlr->wifi == nil){
4006 qsetlimit(edev->oq, MaxQueue);
4008 ctlr->wifi = wifiattach(edev, transmit);
4009 /* tested with 2230, it has transmit issues using higher bit rates */
4010 if(ctlr->family >= 7000 || ctlr->type != Type2030)
4011 ctlr->wifi->rates = iwlrates;
4018 kproc("iwlrecover", iwlrecover, edev);
4025 updatesystime(Ctlr *ctlr, u32int ts)
4027 u32int dt = ts - (u32int)ctlr->systime;
4028 ctlr->systime += dt;
4041 if(ctlr->broken || rx->s == nil || rx->b == nil)
4044 for(hw = get16(rx->s) % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){
4045 int type, flags, idx, qid, len;
4052 len = get32(d); d += 4;
4061 if((qid & 0x80) == 0 && qid < ctlr->ntxq){
4062 tx = &ctlr->tx[qid];
4069 if(len >= 0) switch(type){
4070 case 1: /* microcontroller ready */
4071 setfwinfo(ctlr, d, len);
4073 case 24: /* add node done */
4077 case 28: /* tx done */
4078 if(ctlr->family >= 7000){
4079 if(len <= 36 || d[36] == 1 || d[36] == 2)
4081 } else if(ctlr->type == Type4965){
4082 if(len <= 20 || d[20] == 1 || d[20] == 2)
4085 if(len <= 32 || d[32] == 1 || d[32] == 2)
4088 if(ctlr->wifi != nil)
4089 wifitxfail(ctlr->wifi, bb);
4096 if(ctlr->te.id == -1)
4097 ctlr->te.id = get32(d+8);
4102 if(ctlr->te.id == -1 || get32(d+8) != ctlr->te.id)
4104 switch(get32(d+16)){
4106 ctlr->te.active = 1;
4110 ctlr->te.active = 0;
4115 case 102: /* calibration result (Type5000 only) */
4116 if(ctlr->family >= 7000)
4122 if(idx < 0 || idx >= nelem(ctlr->calib.cmd))
4124 if(rbplant(ctlr, rx->i) < 0)
4126 if(ctlr->calib.cmd[idx] != nil)
4127 freeb(ctlr->calib.cmd[idx]);
4130 ctlr->calib.cmd[idx] = b;
4132 case 4: /* init complete (>= 7000 family) */
4133 if(ctlr->family < 7000)
4136 case 103: /* calibration done (Type5000 only) */
4137 ctlr->calib.done = 1;
4139 case 107: /* calibration result (>= 7000 family) */
4140 if(ctlr->family < 7000)
4151 idx = &ctlr->calib.cfg - &ctlr->calib.cmd[0];
4154 idx = &ctlr->calib.nch - &ctlr->calib.cmd[0];
4159 idx = &ctlr->calib.papd[get16(d+4) % nelem(ctlr->calib.papd)] - &ctlr->calib.cmd[0];
4164 idx = &ctlr->calib.txp[get16(d+4) % nelem(ctlr->calib.txp)] - &ctlr->calib.cmd[0];
4169 case 130: /* start scan */
4170 case 132: /* stop scan */
4172 case 136: /* NVM access (>= 7000 family) */
4173 if(ctlr->family < 7000)
4178 if(ctlr->nvm.len < len)
4179 len = ctlr->nvm.len;
4180 ctlr->nvm.off = get16(d + 0);
4181 ctlr->nvm.ret = get16(d + 2);
4182 ctlr->nvm.type= get16(d + 4);
4183 ctlr->nvm.sts = get16(d + 6);
4185 if(ctlr->nvm.ret < len)
4186 len = ctlr->nvm.ret;
4187 if(ctlr->nvm.buf != nil && len > 0)
4188 memmove(ctlr->nvm.buf, d, len);
4189 ctlr->nvm.buf = nil;
4192 case 156: /* rx statistics */
4193 case 157: /* beacon statistics */
4194 case 161: /* state changed */
4195 case 162: /* beacon missed */
4196 case 177: /* mduart load notification */
4198 case 192: /* rx phy */
4200 updatesystime(ctlr, get32(d+4));
4202 case 195: /* rx done */
4208 case 193: /* mpdu rx done */
4213 if(d + 48 + len > b->lim)
4215 updatesystime(ctlr, get32(d+36));
4216 if((d[12] & 3) != 3)
4221 if(d + len + 4 > b->lim)
4223 if((d[len] & 3) != 3)
4226 if(ctlr->wifi == nil)
4228 if(rbplant(ctlr, rx->i) < 0)
4233 put64(d - 8, ctlr->systime);
4234 b->flag |= Btimestamp;
4236 wifiiq(ctlr->wifi, b);
4238 case 197: /* rx compressed ba */
4242 if(tx != nil && tx->n > 0){
4249 csr32w(ctlr, FhRxQ0Wptr, ((hw+Nrx-1) % Nrx) & ~7);
4251 csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7);
4255 iwlinterrupt(Ureg*, void *arg)
4264 csr32w(ctlr, Imr, 0);
4265 isr = csr32r(ctlr, Isr);
4266 fhisr = csr32r(ctlr, FhIsr);
4267 if(isr == 0xffffffff || (isr & 0xfffffff0) == 0xa5a5a5a0){
4271 if(isr == 0 && fhisr == 0)
4273 csr32w(ctlr, Isr, isr);
4274 csr32w(ctlr, FhIsr, fhisr);
4276 if((isr & (Iswrx | Ifhrx | Irxperiodic | Ialive)) || (fhisr & Ifhrx))
4280 print("#l%d: fatal firmware error\n", edev->ctlrno);
4283 ctlr->wait.m |= isr;
4284 if(ctlr->wait.m & ctlr->wait.w)
4285 wakeup(&ctlr->wait);
4287 csr32w(ctlr, Imr, ctlr->ie);
4292 iwlshutdown(Ether *edev)
4300 pcidisable(ctlr->pdev);
4303 static Ctlr *iwlhead, *iwltail;
4313 while(pdev = pcimatch(pdev, 0, 0)) {
4317 if(pdev->ccrb != 2 || pdev->ccru != 0x80)
4319 if(pdev->vid != 0x8086)
4321 if(pdev->mem[0].bar & 1)
4327 case 0x0084: /* WiFi Link 1000 */
4328 case 0x4229: /* WiFi Link 4965 */
4329 case 0x4230: /* WiFi Link 4965 */
4330 case 0x4232: /* Wifi Link 5100 */
4331 case 0x4235: /* Intel Corporation Ultimate N WiFi Link 5300 */
4332 case 0x4236: /* WiFi Link 5300 AGN */
4333 case 0x4237: /* Wifi Link 5100 AGN */
4334 case 0x4239: /* Centrino Advanced-N 6200 */
4335 case 0x423d: /* Wifi Link 5150 */
4336 case 0x423b: /* PRO/Wireless 5350 AGN */
4337 case 0x0082: /* Centrino Advanced-N 6205 */
4338 case 0x0085: /* Centrino Advanced-N 6205 */
4339 case 0x422b: /* Centrino Ultimate-N 6300 variant 1 */
4340 case 0x4238: /* Centrino Ultimate-N 6300 variant 2 */
4341 case 0x08ae: /* Centrino Wireless-N 100 */
4342 case 0x0083: /* Centrino Wireless-N 1000 */
4343 case 0x008a: /* Centrino Wireless-N 1030 */
4344 case 0x0891: /* Centrino Wireless-N 2200 */
4345 case 0x0887: /* Centrino Wireless-N 2230 */
4346 case 0x0888: /* Centrino Wireless-N 2230 */
4347 case 0x0090: /* Centrino Advanced-N 6030 */
4348 case 0x0091: /* Centrino Advanced-N 6030 */
4349 case 0x088e: /* Centrino Advanced-N 6235 */
4350 case 0x088f: /* Centrino Advanced-N 6235 */
4354 case 0x24f3: /* Wireless AC 8260 */
4356 fwname = "iwm-8000C-34";
4358 case 0x24fd: /* Wireless AC 8265 */
4360 fwname = "iwm-8265-34";
4362 case 0x2526: /* Wireless AC 9260 */
4364 fwname = "iwm-9260-34";
4368 ctlr = malloc(sizeof(Ctlr));
4370 print("iwl: unable to alloc Ctlr\n");
4373 ctlr->port = pdev->mem[0].bar & ~0xF;
4374 mem = vmap(ctlr->port, pdev->mem[0].size);
4376 print("iwl: can't map %llux\n", ctlr->port);
4382 ctlr->fwname = fwname;
4383 ctlr->family = family;
4384 ctlr->mqrx = family >= 9000;
4387 iwltail->link = ctlr;
4402 for(ctlr = iwlhead; ctlr != nil; ctlr = ctlr->link){
4403 if(ctlr->edev != nil)
4405 if(edev->port == 0 || edev->port == ctlr->port){
4415 edev->port = ctlr->port;
4416 edev->irq = ctlr->pdev->intl;
4417 edev->tbdf = ctlr->pdev->tbdf;
4419 edev->attach = iwlattach;
4420 edev->ifstat = iwlifstat;
4422 edev->shutdown = iwlshutdown;
4423 edev->promiscuous = iwlpromiscuous;
4424 edev->multicast = iwlmulticast;
4427 pcienable(ctlr->pdev);
4428 if(iwlinit(edev) < 0){
4429 pcidisable(ctlr->pdev);
4430 ctlr->edev = (void*)-1;
4435 pcisetbme(ctlr->pdev);
4436 intrenable(edev->irq, iwlinterrupt, edev, edev->tbdf, edev->name);
4444 addethercard("iwl", iwlpnp);