2 * Intel WiFi Link driver.
4 * Written without any documentation but Damien Bergamini's
5 * iwn(4) and Stefan Sperling's iwm(4) OpenBSD driver sources.
6 * Requires Intel firmware to be present in /lib/firmware/iw[nm]-*
11 #include "../port/lib.h"
16 #include "../port/pci.h"
17 #include "../port/error.h"
18 #include "../port/netif.h"
19 #include "../port/etherif.h"
20 #include "../port/wifi.h"
23 MaxQueue = 24*1024, /* total buffer is 2*MaxQueue: 48k at 22Mbit ≅ 20ms */
27 Ntxqmax = MaxQueue/1500,
41 FWPagesize = 1<<FWPageshift,
43 FWBlockpages = 1<<FWBlockshift,
44 FWBlocksize = 1<<(FWBlockshift + FWPageshift),
49 Cfg = 0x000, /* config register */
51 CfgMacDashMask = 3<<CfgMacDashShift,
53 CfgMacStepMask = 3<<CfgMacStepShift,
59 CfgPhyTypeMask = 3<<CfgPhyTypeShift,
61 CfgPhyDashMask = 3<<CfgPhyDashShift,
63 CfgPhyStepMask = 3<<CfgPhyStepShift,
72 Isr = 0x008, /* interrupt status */
73 Imr = 0x00c, /* interrupt mask */
86 Ierr = Iswerr | Ihwerr,
87 Idefmask = Ierr | Ifhtx | Ifhrx | Ialive | Iwakeup | Iswrx | Ictreached | Irftoggled,
89 FhIsr = 0x010, /* second interrupt status */
93 Rev = 0x028, /* hardware revision */
95 EepromIo = 0x02c, /* EEPROM i/o register */
100 RelativeAccess = 1<<17,
102 EccUncorrStts = 1<<21,
104 Gpc = 0x024, /* gp cntrl */
106 MacClockReady = 1<<0,
118 GpDrvRadioIqInvert = 1<<7,
126 UcodeGp1RfKill = 1<<1,
127 UcodeGp1CmdBlocked = 1<<2,
128 UcodeGp1CtempStopRf = 1<<3,
130 ShadowRegCtrl = 0x0a8,
133 MboxSetOsAlive = 1<<5,
142 Dbglinkpwrmgmt = 0x250,
154 HbusTargWptr = 0x460,
156 UcodeLoadStatus = 0x1af0,
160 * Flow-Handler registers.
163 FhTfbdCtrl0 = 0x1900, // +q*8
164 FhTfbdCtrl1 = 0x1904, // +q*8
168 FhSramAddr = 0x19a4, // +q*4
170 FhCbbcQueue0 = 0x19d0, // +q*4
171 FhCbbcQueue16 = 0x1bf0, // +q*4
172 FhCbbcQueue20 = 0x1b20, // +q*4
174 FhStatusWptr = 0x1bc0,
178 FhRxConfigEna = 1<<31,
179 FhRxConfigRbSize8K = 1<<16,
180 FhRxConfigSingleFrame = 1<<15,
181 FhRxConfigIrqDstHost = 1<<12,
182 FhRxConfigIgnRxfEmpty = 1<<2,
184 FhRxConfigNrbdShift = 20,
185 FhRxConfigRbTimeoutShift= 4,
189 FhRxQ0Wptr = 0x1c80, // +q*4 (9000 mqrx)
191 FhTxConfig = 0x1d00, // +q*32
192 FhTxConfigDmaCreditEna = 1<<3,
193 FhTxConfigDmaEna = 1<<31,
194 FhTxConfigCirqHostEndTfd= 1<<20,
196 FhTxBufStatus = 0x1d08, // +q*32
197 FhTxBufStatusTbNumShift = 20,
198 FhTxBufStatusTbIdxShift = 12,
199 FhTxBufStatusTfbdValid = 3,
201 FhTxChicken = 0x1e98,
208 * NIC internal memory offsets.
211 ApmgClkCtrl = 0x3000,
218 EarlyPwroffDis = 1<<22,
224 ApmgDigitalSvr = 0x3058,
225 ApmgAnalogSvr = 0x306c,
228 BsmWrMemSrc = 0x3404,
229 BsmWrMemDst = 0x3408,
230 BsmWrDwCount = 0x340c,
231 BsmDramTextAddr = 0x3490,
232 BsmDramTextSize = 0x3494,
233 BsmDramDataAddr = 0x3498,
234 BsmDramDataSize = 0x349c,
235 BsmSramBase = 0x3800,
238 ReleaseCpuReset = 0x300c,
239 CpuResetBit = 0x1000000,
241 LmpmChick = 0xa01ff8,
244 SbCpu1Status = 0xa01e30,
245 SbCpu2Status = 0xa01e34,
248 UregChick = 0xa05c00,
249 UregChickMsiEnable = 1<<24,
251 FhUcodeLoadStatus=0xa05c40,
255 * RX ring for mqrx 9000
258 RfhQ0FreeBase = 0xa08000, // +q*8
259 RfhQ0FreeWptr = 0xa08080, // +q*4
260 RfhQ0FreeRptr = 0xa080c0, // +q*4
262 RfhQ0UsedBase = 0xa08100, // +q*8
263 RfhQ0UsedWptr = 0xa08180, // +q*4
265 RfhQ0SttsBase = 0xa08200, // +q*8
267 RfhGenCfg = 0xa09800,
268 RfhGenServiceDmaSnoop = 1<<0,
269 RfhGenRfhDmaSnoop = 1<<1,
270 RfhGenRbChunkSize64 = 0<<4,
271 RfhGenRbChunkSize128 = 1<<4,
273 RfhGenStatus = 0xa09808,
274 RfhGenStatusDmaIdle = 1<<31,
276 RfhRxqActive = 0xa0980c,
278 RfhDmaCfg = 0xa09820,
279 RfhDma1KSizeShift = 16,
280 RfhDmaNrbdShift = 20,
281 RfhDmaMinRbSizeShift = 24,
282 RfhDmaDropTooLarge = 1<<26,
283 RfhDmaEnable = 1<<31,
287 * TX scheduler registers.
290 SchedBase = 0xa02c00,
291 SchedSramAddr = SchedBase,
293 SchedDramAddr4965 = SchedBase+0x010,
294 SchedTxFact4965 = SchedBase+0x01c,
295 SchedQueueRdptr4965 = SchedBase+0x064, // +q*4
296 SchedQChainSel4965 = SchedBase+0x0d0,
297 SchedIntrMask4965 = SchedBase+0x0e4,
298 SchedQueueStatus4965 = SchedBase+0x104, // +q*4
300 SchedDramAddr = SchedBase+0x008,
301 SchedTxFact = SchedBase+0x010,
302 SchedQueueWrptr = SchedBase+0x018, // +q*4
303 SchedQueueRdptr = SchedBase+0x068, // +q*4
304 SchedQChainSel = SchedBase+0x0e8,
305 SchedIntrMask = SchedBase+0x108,
307 SchedQueueStatus = SchedBase+0x10c, // +q*4
309 SchedGpCtrl = SchedBase+0x1a8,
310 Enable31Queues = 1<<0,
311 AutoActiveMode = 1<<18,
313 SchedChainExtEn = SchedBase+0x244,
314 SchedAggrSel = SchedBase+0x248,
315 SchedEnCtrl = SchedBase+0x254,
317 SchedQueueRdptr20 = SchedBase+0x2b4, // +q*4
318 SchedQueueStatus20 = SchedBase+0x334, // +q*4
322 SchedCtxOff4965 = 0x380,
323 SchedCtxLen4965 = 416,
325 SchedCtxOff = 0x600, // +q*8
327 SchedSttsOff = 0x6A0, // +q*16
329 SchedTransTblOff = 0x7E0, // +q*2
333 FilterPromisc = 1<<0,
335 FilterMulticast = 1<<2,
336 FilterNoDecrypt = 1<<3,
337 FilterNoDecryptMcast = 1<<4,
347 RFlagShPreamble = 1<<5,
348 RFlagNoDiversity = 1<<7,
349 RFlagAntennaA = 1<<8,
350 RFlagAntennaB = 1<<9,
352 RFlagCTSToSelf = 1<<30,
356 TFlagNeedProtection = 1<<0,
362 TFlagFullTxOp = 1<<7,
364 TFlagAutoSeq = 1<<13,
365 TFlagMoreFrag = 1<<14,
366 TFlagInsertTs = 1<<16,
367 TFlagNeedPadding = 1<<20,
376 typedef struct FWInfo FWInfo;
377 typedef struct FWImage FWImage;
378 typedef struct FWSect FWSect;
379 typedef struct FWBlock FWBlock;
380 typedef struct FWMem FWMem;
382 typedef struct TXQ TXQ;
383 typedef struct RXQ RXQ;
385 typedef struct Station Station;
387 typedef struct Ctlr Ctlr;
527 /* assigned sta ids in hardware sta table or -1 if unassigned */
538 /* current receiver settings */
539 uchar bssid[Eaddrlen];
624 /* controller types */
634 Type6005 = 11, /* also Centrino Advanced-N 6030, 6235 */
642 static struct ratetab {
649 { 11, 55, RFlagCCK },
650 { 22, 110, RFlagCCK },
663 static uchar iwlrates[] = {
681 static char *fwname[32] = {
682 [Type4965] "iwn-4965",
683 [Type5300] "iwn-5000",
684 [Type5350] "iwn-5000",
685 [Type5150] "iwn-5150",
686 [Type5100] "iwn-5000",
687 [Type1000] "iwn-1000",
688 [Type6000] "iwn-6000",
689 [Type6050] "iwn-6050",
690 [Type6005] "iwn-6005", /* see in iwlattach() below */
691 [Type2030] "iwn-2030",
692 [Type2000] "iwn-2000",
693 [Type7260] "iwm-7260-17",
696 static char *qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block);
697 static char *flushq(Ctlr *ctlr, uint qid);
698 static char *cmd(Ctlr *ctlr, uint code, uchar *data, int size);
700 #define csr32r(c, r) (*((c)->nic+((r)/4)))
701 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
705 return *((u16int*)p);
709 return *((u32int*)p);
712 put32(uchar *p, uint v){
716 put64(uchar *p, uvlong v)
721 put16(uchar *p, uint v){
730 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq);
731 for(i=0; i<1000; i++){
732 if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna)
736 return "niclock: timeout";
740 nicunlock(Ctlr *ctlr)
742 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq);
746 prphread(Ctlr *ctlr, uint off)
749 csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off);
751 return csr32r(ctlr, PrphRdata);
754 prphwrite(Ctlr *ctlr, uint off, u32int data)
757 csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off);
759 csr32w(ctlr, PrphWdata, data);
763 prphwrite64(Ctlr *ctlr, uint off, u64int data)
765 prphwrite(ctlr, off, data & 0xFFFFFFFF);
766 prphwrite(ctlr, off+4, data >> 32);
770 memread(Ctlr *ctlr, uint off)
772 csr32w(ctlr, MemRaddr, off);
774 return csr32r(ctlr, MemRdata);
777 memwrite(Ctlr *ctlr, uint off, u32int data)
779 csr32w(ctlr, MemWaddr, off);
781 csr32w(ctlr, MemWdata, data);
785 setfwinfo(Ctlr *ctlr, uchar *d, int len)
791 case 2+2 + 1+1+2+1+1 + 1+1 + 1+1 + 2 + 4+4+4+4+4+4 + 4:
792 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:
793 i->status = get16(d); d += 2;
794 i->flags = get16(d); d += 2;
807 i->tstamp = get32(d); d += 4;
808 i->errptr = get32(d); d += 4;
809 i->logptr = get32(d); d += 4;
810 i->regptr = get32(d); d += 4;
811 d += 4; // dbgm_config_ptr
812 d += 4; // alive counter ptr
814 i->scdptr = get32(d); d += 4;
816 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)
822 i->umac.minor = *d++;
823 i->umac.major = *d++;
826 i->umac.errptr = get32(d); d += 4;
827 i->umac.logptr = get32(d); d += 4;
829 i->valid = (i->status == 0xcafe);
832 case 2+2 + 4+4 + 1+1 + 1+1 + 4+4+4+4+4+4 + 4 + 4+4 + 4+4+4+4:
833 i->status = get16(d); d += 2;
834 i->flags = get16(d); d += 2;
845 i->tstamp = get32(d); d += 4;
846 i->errptr = get32(d); d += 4;
847 i->logptr = get32(d); d += 4;
848 i->regptr = get32(d); d += 4;
849 d += 4; // dbgm_config_ptr
850 d += 4; // alive counter ptr
852 i->scdptr = get32(d);
858 i->umac.minor = get32(d); d += 4;
859 i->umac.major = get32(d); d += 4;
860 i->umac.errptr = get32(d); d += 4;
861 i->umac.logptr = get32(d); d += 4;
863 i->valid = (i->status == 0xcafe);
875 i->logptr = get32(d); d += 4;
876 i->errptr = get32(d); d += 4;
877 i->tstamp = get32(d); d += 4;
884 printfwinfo(Ctlr *ctlr)
886 FWInfo *i = &ctlr->fwinfo;
888 print("fwinfo: status=%.4ux flags=%.4ux\n",
889 i->status, i->flags);
891 print("fwinfo: ver %ud.%ud type %ud.%ud\n",
892 i->major, i->minor, i->type, i->subtype);
893 print("fwinfo: scdptr=%.8ux\n", i->scdptr);
894 print("fwinfo: regptr=%.8ux\n", i->regptr);
895 print("fwinfo: logptr=%.8ux\n", i->logptr);
896 print("fwinfo: errptr=%.8ux\n", i->errptr);
898 print("fwinfo: ts=%.8ux\n", i->tstamp);
900 print("fwinfo: umac ver %ud.%ud\n", i->umac.major, i->umac.minor);
901 print("fwinfo: umac errptr %.8ux\n", i->umac.errptr);
902 print("fwinfo: umac logptr %.8ux\n", i->umac.logptr);
911 print("lastcmd: %ud (0x%ux)\n", ctlr->tx[4].lastcmd, ctlr->tx[4].lastcmd);
913 if(!ctlr->fwinfo.valid || ctlr->fwinfo.errptr == 0){
914 print("no error pointer\n");
917 for(i=0; i<nelem(dump); i++)
918 dump[i] = memread(ctlr, ctlr->fwinfo.errptr + i*4);
920 if(ctlr->family >= 7000){
921 print( "error:\tid %ux, trm_hw_status %.8ux %.8ux,\n"
922 "\tbranchlink2 %.8ux, interruptlink %.8ux %.8ux,\n"
923 "\terrordata %.8ux %.8ux %.8ux\n",
924 dump[1], dump[2], dump[3],
925 dump[4], dump[5], dump[6],
926 dump[7], dump[8], dump[9]);
928 print( "error:\tid %ux, pc %ux,\n"
929 "\tbranchlink %.8ux %.8ux, interruptlink %.8ux %.8ux,\n"
930 "\terrordata %.8ux %.8ux, srcline %ud, tsf %ux, time %ux\n",
932 dump[4], dump[3], dump[6], dump[5],
933 dump[7], dump[8], dump[9], dump[10], dump[11]);
938 eepromlock(Ctlr *ctlr)
942 for(i=0; i<100; i++){
943 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | EepromLocked);
944 for(j=0; j<100; j++){
945 if(csr32r(ctlr, Cfg) & EepromLocked)
950 return "eepromlock: timeout";
953 eepromunlock(Ctlr *ctlr)
955 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) & ~EepromLocked);
958 eepromread(Ctlr *ctlr, void *data, int count, uint off)
965 off += ctlr->eeprom.off;
966 for(; count > 0; count -= 2, off++){
967 csr32w(ctlr, EepromIo, off << 2);
969 w = csr32r(ctlr, EepromIo);
975 return "eepromread: timeout";
976 if(ctlr->eeprom.otp){
977 s = csr32r(ctlr, OtpromGp);
978 if(s & EccUncorrStts)
979 return "eepromread: otprom ecc error";
981 csr32w(ctlr, OtpromGp, s);
995 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
997 if(csr32r(ctlr, Cfg) & NicReady)
1001 if(ctlr->family >= 7000){
1002 csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31));
1006 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | Prepare);
1007 for(i=0; i<15000; i++){
1008 if((csr32r(ctlr, Cfg) & PrepareDone) == 0)
1013 return "handover: timeout";
1015 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
1017 if(csr32r(ctlr, Cfg) & NicReady)
1021 return "handover: timeout";
1023 if(ctlr->family >= 7000)
1024 csr32w(ctlr, MboxSet, csr32r(ctlr, MboxSet) | MboxSetOsAlive);
1029 clockwait(Ctlr *ctlr)
1033 /* Set "initialization complete" bit. */
1034 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone);
1035 for(i=0; i<2500; i++){
1036 if(csr32r(ctlr, Gpc) & MacClockReady)
1040 return "clockwait: timeout";
1050 if(ctlr->family >= 7000){
1051 /* Reset entire device */
1052 csr32w(ctlr, Reset, (1<<7));
1056 if(ctlr->family < 8000){
1057 /* Disable L0s exit timer (NMI bug workaround). */
1058 csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | DisL0Stimer);
1061 /* Don't wait for ICH L0s (ICH bug workaround). */
1062 csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | L1AnoL0Srx);
1064 /* Set FH wait threshold to max (HW bug under stress workaround). */
1065 csr32w(ctlr, Dbghpetmem, csr32r(ctlr, Dbghpetmem) | 0xffff0000);
1067 /* Enable HAP INTA to move adapter from L1a to L0s. */
1068 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | HapwakeL1A);
1070 capoff = pcicap(ctlr->pdev, PciCapPCIe);
1072 /* Workaround for HW instability in PCIe L0->L0s->L1 transition. */
1073 if(pcicfgr16(ctlr->pdev, capoff + 0x10) & 0x2) /* LCSR -> L1 Entry enabled. */
1074 csr32w(ctlr, Gio, csr32r(ctlr, Gio) | EnaL0S);
1076 csr32w(ctlr, Gio, csr32r(ctlr, Gio) & ~EnaL0S);
1079 if(ctlr->family < 7000){
1080 if(ctlr->type != Type4965 && ctlr->type <= Type1000)
1081 csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | 0x00880300);
1084 /* Wait for clock stabilization before accessing prph. */
1085 if((err = clockwait(ctlr)) != nil)
1089 /* Newer cards default to MSIX? */
1090 if((err = niclock(ctlr)) != nil)
1092 prphwrite(ctlr, UregChick, UregChickMsiEnable);
1096 /* Enable the oscillator to count wake up time for L1 exit. (weird W/A) */
1097 if(ctlr->type == Type7260){
1098 if((err = niclock(ctlr)) != nil)
1101 prphread(ctlr, OscClk);
1102 prphread(ctlr, OscClk);
1105 prphwrite(ctlr, OscClk, prphread(ctlr, OscClk) | OscClkCtrl);
1107 prphread(ctlr, OscClk);
1108 prphread(ctlr, OscClk);
1113 if(ctlr->family < 8000){
1114 if((err = niclock(ctlr)) != nil)
1117 /* Enable DMA and BSM (Bootstrap State Machine). */
1118 if(ctlr->type == Type4965)
1119 prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt);
1121 prphwrite(ctlr, ApmgClkEna, DmaClkRqt);
1124 /* Disable L1-Active. */
1125 prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11));
1136 poweroff(Ctlr *ctlr)
1140 csr32w(ctlr, Reset, 1);
1142 /* Disable interrupts */
1144 csr32w(ctlr, Imr, 0);
1145 csr32w(ctlr, Isr, ~0);
1146 csr32w(ctlr, FhIsr, ~0);
1148 /* Stop scheduler */
1149 if(ctlr->family >= 7000 || ctlr->type != Type4965)
1150 prphwrite(ctlr, SchedTxFact, 0);
1152 prphwrite(ctlr, SchedTxFact4965, 0);
1155 if(niclock(ctlr) == nil){
1156 for(i = 0; i < ctlr->ndma; i++){
1157 csr32w(ctlr, FhTxConfig + i*32, 0);
1158 for(j = 0; j < 200; j++){
1159 if(csr32r(ctlr, FhTxStatus) & (0x10000<<i))
1168 if(niclock(ctlr) == nil){
1170 prphwrite(ctlr, RfhDmaCfg, 0);
1171 for(j = 0; j < 200; j++){
1172 if(prphread(ctlr, RfhGenStatus) & RfhGenStatusDmaIdle)
1177 csr32w(ctlr, FhRxConfig, 0);
1178 for(j = 0; j < 200; j++){
1179 if(csr32r(ctlr, FhRxStatus) & 0x1000000)
1187 if(ctlr->family <= 7000){
1189 if(niclock(ctlr) == nil){
1190 prphwrite(ctlr, ApmgClkDis, DmaClkRqt);
1196 if(ctlr->family >= 7000){
1197 csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31));
1198 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | Prepare|EnablePme);
1200 csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) & ~(1<<31));
1204 /* Stop busmaster DMA activity. */
1205 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | (1<<9));
1206 for(j = 0; j < 100; j++){
1207 if(csr32r(ctlr, Reset) & (1<<8))
1212 /* Reset the entire device. */
1213 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | (1<<7));
1216 /* Clear "initialization complete" bit. */
1217 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~InitDone);
1230 ctlr->eeprom.otp = 0;
1231 ctlr->eeprom.off = 0;
1232 if(ctlr->type < Type1000 || (csr32r(ctlr, OtpromGp) & DevSelOtp) == 0)
1235 /* Wait for clock stabilization before accessing prph. */
1236 if((err = clockwait(ctlr)) != nil)
1239 if((err = niclock(ctlr)) != nil)
1241 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | ResetReq);
1243 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) & ~ResetReq);
1246 /* Set auto clock gate disable bit for HW with OTP shadow RAM. */
1247 if(ctlr->type != Type1000)
1248 csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31));
1250 csr32w(ctlr, EepromGp, csr32r(ctlr, EepromGp) & ~0x00000180);
1252 /* Clear ECC status. */
1253 csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) | (EccCorrStts | EccUncorrStts));
1255 ctlr->eeprom.otp = 1;
1256 if(ctlr->type != Type1000)
1259 /* Switch to absolute addressing mode. */
1260 csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) & ~RelativeAccess);
1263 * Find the block before last block (contains the EEPROM image)
1264 * for HW without OTP shadow RAM.
1268 if((err = eepromread(ctlr, buf, 2, last)) != nil)
1275 if(i == 0 || i >= 3)
1276 return "rominit: missing eeprom image";
1278 ctlr->eeprom.off = prev+1;
1283 iwlinit(Ether *edev)
1288 uint u, caloff, regoff;
1292 /* Clear device-specific "PCI retry timeout" register (41h). */
1293 if(pcicfgr8(ctlr->pdev, 0x41) != 0)
1294 pcicfgw8(ctlr->pdev, 0x41, 0);
1296 /* Clear interrupt disable bit. Hardware bug workaround. */
1297 if(ctlr->pdev->pcr & 0x400){
1298 ctlr->pdev->pcr &= ~0x400;
1299 pcicfgw16(ctlr->pdev, PciPCR, ctlr->pdev->pcr);
1302 ctlr->type = csr32r(ctlr, Rev);
1303 if(ctlr->family >= 8000){
1304 ctlr->type &= 0xFFFF;
1306 ctlr->step = ctlr->type & 15, ctlr->type >>= 4;
1308 ctlr->type &= 0x1FF;
1309 ctlr->dash = ctlr->type & 3, ctlr->type >>= 2;
1310 ctlr->step = ctlr->type & 3, ctlr->type >>= 2;
1311 if(fwname[ctlr->type] == nil){
1312 print("iwl: unsupported controller type %d\n", ctlr->type);
1317 if((err = handover(ctlr)) != nil)
1320 /* >= 7000 family needs firmware loaded to access NVM */
1321 if(ctlr->family >= 7000)
1324 if((err = poweron(ctlr)) != nil)
1327 if((csr32r(ctlr, EepromGp) & 0x7) == 0){
1328 err = "bad rom signature";
1331 if((err = eepromlock(ctlr)) != nil)
1333 if((err = rominit(ctlr)) != nil)
1335 if((err = eepromread(ctlr, edev->ea, sizeof(edev->ea), 0x15)) != nil){
1339 if((err = eepromread(ctlr, b, 2, 0x048)) != nil){
1345 ctlr->rfcfg.type = u & 3; u >>= 2;
1346 ctlr->rfcfg.step = u & 3; u >>= 2;
1347 ctlr->rfcfg.dash = u & 3; u >>= 4;
1348 ctlr->rfcfg.txantmask = u & 15; u >>= 4;
1349 ctlr->rfcfg.rxantmask = u & 15;
1350 if((err = eepromread(ctlr, b, 2, 0x66)) != nil)
1353 if((err = eepromread(ctlr, b, 4, regoff+1)) != nil)
1355 strncpy(ctlr->eeprom.regdom, (char*)b, 4);
1356 ctlr->eeprom.regdom[4] = 0;
1357 if((err = eepromread(ctlr, b, 2, 0x67)) != nil)
1360 if((err = eepromread(ctlr, b, 4, caloff)) != nil)
1362 ctlr->eeprom.version = b[0];
1363 ctlr->eeprom.type = b[1];
1364 ctlr->eeprom.volt = get16(b+2);
1366 ctlr->eeprom.temp = 0;
1367 ctlr->eeprom.rawtemp = 0;
1368 if(ctlr->type == Type2030 || ctlr->type == Type2000){
1369 if((err = eepromread(ctlr, b, 2, caloff + 0x12a)) != nil)
1371 ctlr->eeprom.temp = get16(b);
1372 if((err = eepromread(ctlr, b, 2, caloff + 0x12b)) != nil)
1374 ctlr->eeprom.rawtemp = get16(b);
1377 if(ctlr->type != Type4965 && ctlr->type != Type5150){
1378 if((err = eepromread(ctlr, b, 4, caloff + 0x128)) != nil)
1380 ctlr->eeprom.crystal = get32(b);
1386 ctlr->rfcfg.txantmask = 3;
1387 ctlr->rfcfg.rxantmask = 7;
1390 ctlr->rfcfg.txantmask = 2;
1391 ctlr->rfcfg.rxantmask = 3;
1394 if(ctlr->pdev->did == 0x422c || ctlr->pdev->did == 0x4230){
1395 ctlr->rfcfg.txantmask = 6;
1396 ctlr->rfcfg.rxantmask = 6;
1403 print("iwlinit: %s\n", err);
1409 crackfw(FWImage *i, uchar *data, uint size, int alt)
1415 memset(i, 0, sizeof(*i));
1418 return "firmware image too short";
1422 i->rev = get32(p); p += 4;
1426 if(size < (4+64+4+4+8))
1428 if(memcmp(p, "IWL\n", 4) != 0)
1429 return "bad firmware signature";
1431 strncpy(i->descr, (char*)p, 64);
1434 i->rev = get32(p); p += 4;
1435 i->build = get32(p); p += 4;
1436 altmask = get32(p); p += 4;
1437 altmask |= (uvlong)get32(p) << 32; p += 4;
1438 while(alt > 0 && (altmask & (1ULL<<alt)) == 0)
1440 for(;p < e; p += (l + 3) & ~3){
1444 t = get32(p), p += 4;
1445 l = get32(p), p += 4;
1449 if((t >> 16) != 0 && (t >> 16) != alt)
1455 if(i->main.nsect < 1)
1457 s->addr = 0x00000000;
1461 if(i->main.nsect < 2)
1463 s->addr = 0x00800000;
1467 if(i->init.nsect < 1)
1469 s->addr = 0x00000000;
1473 if(i->init.nsect < 2)
1475 s->addr = 0x00800000;
1479 s->addr = 0x00000000;
1482 if(i->main.nsect >= nelem(i->main.sect))
1483 return "too many main sections";
1484 s = &i->main.sect[i->main.nsect++];
1487 if(i->init.nsect >= nelem(i->init.sect))
1488 return "too many init sections";
1489 s = &i->init.sect[i->init.nsect++];
1504 i->main.defcalib.flowmask = get32(p+4);
1505 i->main.defcalib.eventmask = get32(p+8);
1508 i->init.defcalib.flowmask = get32(p+4);
1509 i->init.defcalib.eventmask = get32(p+8);
1516 i->physku = get32(p);
1522 if(t >= nelem(i->api))
1524 i->api[t] = get32(p+4);
1530 if(t >= nelem(i->capa))
1532 i->capa[t] = get32(p+4);
1537 i->pagedmemsize = get32(p) & -FWPagesize;
1542 if(((i->rev>>8) & 0xFF) < 2)
1543 return "need firmware api >= 2";
1544 if(((i->rev>>8) & 0xFF) >= 3){
1545 i->build = get32(p); p += 4;
1550 i->main.text.size = get32(p); p += 4;
1551 i->main.data.size = get32(p); p += 4;
1552 i->init.text.size = get32(p); p += 4;
1553 i->init.data.size = get32(p); p += 4;
1554 i->boot.text.size = get32(p); p += 4;
1556 i->main.text.data = p; p += i->main.text.size;
1557 i->main.data.data = p; p += i->main.data.size;
1558 i->init.text.data = p; p += i->init.text.size;
1559 i->init.data.data = p; p += i->init.data.size;
1560 i->boot.text.data = p; p += i->boot.text.size;
1566 i->main.text.addr = 0x00000000;
1567 i->main.data.addr = 0x00800000;
1568 i->init.text.addr = 0x00000000;
1569 i->init.data.addr = 0x00800000;
1575 readfirmware(char *name)
1577 uchar dirbuf[sizeof(Dir)+100], *data;
1578 char buf[128], *err;
1587 snprint(buf, sizeof buf, "/boot/%s", name);
1588 c = namec(buf, Aopen, OREAD, 0);
1591 snprint(buf, sizeof buf, "/lib/firmware/%s", name);
1592 c = namec(buf, Aopen, OREAD, 0);
1598 n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf);
1600 error("can't stat firmware");
1601 convM2D(dirbuf, n, &d, nil);
1602 fw = smalloc(sizeof(*fw) + 16 + d.length);
1603 data = (uchar*)(fw+1);
1609 while(r < d.length){
1610 n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r);
1615 if((err = crackfw(fw, data, r, 1)) != nil)
1628 return (ctlr->wait.m & ctlr->wait.w) != 0;
1632 irqwait(Ctlr *ctlr, u32int mask, int timeout)
1637 r = ctlr->wait.m & mask;
1639 ctlr->wait.w = mask;
1642 tsleep(&ctlr->wait, gotirq, ctlr, timeout);
1647 r = ctlr->wait.m & mask;
1655 rbplant(Ctlr *ctlr, uint i)
1661 b = iallocb(Rbufsize*2);
1664 b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, Rbufsize);
1665 memset(b->rp, 0, Rdscsize);
1670 put64(ctlr->rx.p + (i<<3), PCIWADDR(b->rp));
1672 put32(ctlr->rx.p + (i<<2), PCIWADDR(b->rp) >> 8);
1684 if(ctlr->fw->pagedmemsize > 0){
1685 ctlr->fwmem.npage = ctlr->fw->pagedmemsize >> FWPageshift;
1686 ctlr->fwmem.nblock = ctlr->fwmem.npage >> FWBlockshift;
1687 if(ctlr->fwmem.nblock >= nelem(ctlr->fwmem.block)-1)
1688 return "paged memory size too big";
1689 for(i = 0; i < ctlr->fwmem.nblock; i++)
1690 ctlr->fwmem.block[i].size = FWBlocksize;
1691 ctlr->fwmem.block[i].size = (ctlr->fwmem.npage % FWBlockpages) << FWPageshift;
1692 if(ctlr->fwmem.block[i].size != 0)
1693 ctlr->fwmem.nblock++;
1694 for(i = 0; i < ctlr->fwmem.nblock; i++){
1695 if(ctlr->fwmem.block[i].p == nil){
1696 ctlr->fwmem.block[i].p = mallocalign(ctlr->fwmem.block[i].size, FWPagesize, 0, 0);
1697 if(ctlr->fwmem.block[i].p == nil)
1698 return "no memory for firmware block";
1701 if(ctlr->fwmem.css == nil){
1702 if((ctlr->fwmem.css = mallocalign(FWPagesize, FWPagesize, 0, 0)) == nil)
1703 return "no memory for firmware css page";
1710 rx->u = mallocalign(4 * Nrx, 4096, 0, 0);
1712 rx->p = mallocalign(8 * Nrx, 4096, 0, 0);
1713 if(rx->u == nil || rx->p == nil)
1714 return "no memory for rx rings";
1715 memset(rx->u, 0, 4 * Nrx);
1716 memset(rx->p, 0, 8 * Nrx);
1720 rx->p = mallocalign(4 * Nrx, 256, 0, 0);
1722 return "no memory for rx rings";
1723 memset(rx->p, 0, 4 * Nrx);
1726 rx->s = mallocalign(Rstatsize, 4096, 0, 0);
1728 rx->b = malloc(sizeof(Block*) * Nrx);
1729 if(rx->b == nil || rx->s == nil)
1730 return "no memory for rx ring";
1731 memset(rx->s, 0, Rstatsize);
1732 for(i=0; i<Nrx; i++){
1733 if(rx->b[i] != nil){
1737 if(rbplant(ctlr, i) < 0)
1738 return "no memory for rx descriptors";
1744 if(ctlr->family >= 7000) {
1747 if(ctlr->type == Type4965) {
1753 if(ctlr->sched.s == nil)
1754 ctlr->sched.s = mallocalign((256+64)*2 * ctlr->ntxq, 4096, 0, 0);
1755 if(ctlr->sched.s == nil)
1756 return "no memory for sched buffer";
1757 memset(ctlr->sched.s, 0, (256+64)*2 * ctlr->ntxq);
1759 for(q=0; q < nelem(ctlr->tx); q++){
1762 tx->b = malloc(sizeof(Block*) * Ntx);
1764 tx->d = mallocalign(Tdscsize * Ntx, 4096, 0, 0);
1766 tx->c = mallocalign(Tcmdsize * Ntx, 4096, 0, 0);
1767 if(tx->b == nil || tx->d == nil || tx->c == nil)
1768 return "no memory for tx ring";
1769 memset(tx->d, 0, Tdscsize * Ntx);
1770 memset(tx->c, 0, Tcmdsize * Ntx);
1771 for(i=0; i<Ntx; i++){
1772 if(tx->b[i] != nil){
1773 freeblist(tx->b[i]);
1782 if(ctlr->kwpage == nil)
1783 ctlr->kwpage = mallocalign(4096, 4096, 0, 0);
1784 if(ctlr->kwpage == nil)
1785 return "no memory for kwpage";
1786 memset(ctlr->kwpage, 0, 4096);
1799 if((err = initmem(ctlr)) != nil)
1801 if((err = poweron(ctlr)) != nil)
1804 if(ctlr->family <= 7000){
1805 if((err = niclock(ctlr)) != nil)
1807 prphwrite(ctlr, ApmgPs, (prphread(ctlr, ApmgPs) & ~PwrSrcMask) | PwrSrcVMain);
1811 if(ctlr->family >= 7000){
1814 u = csr32r(ctlr, Cfg);
1816 u &= ~(RadioSi|MacSi|CfgMacDashMask|CfgMacStepMask|CfgPhyTypeMask|CfgPhyStepMask|CfgPhyDashMask);
1818 u |= (ctlr->step << CfgMacStepShift) & CfgMacStepMask;
1819 u |= (ctlr->dash << CfgMacDashShift) & CfgMacDashMask;
1821 u |= ctlr->rfcfg.type << CfgPhyTypeShift;
1822 u |= ctlr->rfcfg.step << CfgPhyStepShift;
1823 u |= ctlr->rfcfg.dash << CfgPhyDashShift;
1825 csr32w(ctlr, Cfg, u);
1828 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | RadioSi | MacSi);
1831 if(ctlr->family < 8000){
1832 if((err = niclock(ctlr)) != nil)
1834 if(ctlr->family == 7000 || ctlr->type != Type4965)
1835 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | EarlyPwroffDis);
1838 if(ctlr->family < 7000){
1839 if((err = niclock(ctlr)) != nil)
1841 if(ctlr->type == Type1000){
1843 * Select first Switching Voltage Regulator (1.32V) to
1844 * solve a stability issue related to noisy DC2DC line
1845 * in the silicon of 1000 Series.
1847 prphwrite(ctlr, ApmgDigitalSvr,
1848 (prphread(ctlr, ApmgDigitalSvr) & ~(0xf<<5)) | (3<<5));
1850 if((ctlr->type == Type6005 || ctlr->type == Type6050) && ctlr->eeprom.version == 6)
1851 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvCalV6);
1852 if(ctlr->type == Type6005)
1853 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrv1X2);
1854 if(ctlr->type == Type2030 || ctlr->type == Type2000)
1855 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvRadioIqInvert);
1859 if((err = niclock(ctlr)) != nil)
1864 prphwrite(ctlr, RfhDmaCfg, 0);
1865 /* Disable RX used and free queue operation. */
1866 prphwrite(ctlr, RfhRxqActive, 0);
1868 prphwrite64(ctlr, RfhQ0SttsBase, PCIWADDR(ctlr->rx.s));
1869 prphwrite64(ctlr, RfhQ0FreeBase, PCIWADDR(ctlr->rx.p));
1870 prphwrite64(ctlr, RfhQ0UsedBase, PCIWADDR(ctlr->rx.u));
1872 prphwrite(ctlr, RfhQ0FreeWptr, 0);
1873 prphwrite(ctlr, RfhQ0FreeRptr, 0);
1874 prphwrite(ctlr, RfhQ0UsedWptr, 0);
1877 prphwrite(ctlr, RfhDmaCfg,
1879 RfhDmaDropTooLarge |
1880 ((Rbufsize/1024) << RfhDma1KSizeShift) |
1881 (3 << RfhDmaMinRbSizeShift) |
1882 (Nrxlog << RfhDmaNrbdShift));
1884 /* Enable RX DMA snooping. */
1885 prphwrite(ctlr, RfhGenCfg,
1886 RfhGenServiceDmaSnoop |
1888 RfhGenRbChunkSize128);
1891 prphwrite(ctlr, RfhRxqActive, (1 << 16) | 1);
1894 csr32w(ctlr, FhRxQ0Wptr, (Nrx-1) & ~7);
1897 csr32w(ctlr, FhRxConfig, 0);
1898 csr32w(ctlr, FhRxWptr, 0);
1899 csr32w(ctlr, FhRxBase, PCIWADDR(ctlr->rx.p) >> 8);
1900 csr32w(ctlr, FhStatusWptr, PCIWADDR(ctlr->rx.s) >> 4);
1901 csr32w(ctlr, FhRxConfig,
1903 FhRxConfigIgnRxfEmpty |
1904 FhRxConfigIrqDstHost |
1905 FhRxConfigSingleFrame |
1906 (Nrxlog << FhRxConfigNrbdShift));
1908 csr32w(ctlr, FhRxWptr, (Nrx-1) & ~7);
1911 for(i = 0; i < ctlr->ndma; i++)
1912 csr32w(ctlr, FhTxConfig + i*32, 0);
1914 if(ctlr->family >= 7000 || ctlr->type != Type4965)
1915 prphwrite(ctlr, SchedTxFact, 0);
1917 prphwrite(ctlr, SchedTxFact4965, 0);
1919 if(ctlr->family >= 7000){
1920 prphwrite(ctlr, SchedEnCtrl, 0);
1921 prphwrite(ctlr, SchedGpCtrl, prphread(ctlr, SchedGpCtrl)
1922 | Enable31Queues*(ctlr->ntxq == 31)
1924 for(q = 0; q < ctlr->ntxq; q++)
1925 prphwrite(ctlr, (q<20? SchedQueueStatus: SchedQueueStatus20) + q*4, 1 << 19);
1928 csr32w(ctlr, FhKwAddr, PCIWADDR(ctlr->kwpage) >> 4);
1929 for(q = 0; q < ctlr->ntxq; q++){
1930 i = q < nelem(ctlr->tx) ? q : nelem(ctlr->tx)-1;
1932 csr32w(ctlr, FhCbbcQueue0 + q*4, PCIWADDR(ctlr->tx[i].d) >> 8);
1934 csr32w(ctlr, FhCbbcQueue16 + (q-16)*4, PCIWADDR(ctlr->tx[i].d) >> 8);
1936 csr32w(ctlr, FhCbbcQueue20 + (q-20)*4, PCIWADDR(ctlr->tx[i].d) >> 8);
1939 if(ctlr->family >= 7000 || ctlr->type >= Type6000)
1940 csr32w(ctlr, ShadowRegCtrl, csr32r(ctlr, ShadowRegCtrl) | 0x800fffff);
1944 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
1945 csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
1953 ctlr->bcast.id = -1;
1960 ctlr->te.active = 0;
1963 if(ctlr->family >= 9000)
1964 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | 0x4000000);
1966 ctlr->ie = Idefmask;
1967 csr32w(ctlr, Imr, ctlr->ie);
1968 csr32w(ctlr, Isr, ~0);
1970 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
1971 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
1972 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
1978 sendmccupdate(Ctlr *ctlr, char *mcc)
1980 uchar c[2+1+1+4+5*4], *p;
1982 memset(p = c, 0, sizeof(c));
1986 *p++ = 0; // reserved
1991 return cmd(ctlr, 200, c, p - c);
1995 sendbtcoexadv(Ctlr *ctlr)
1997 static u32int btcoex3wire[12] = {
1998 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
1999 0xcc00ff28, 0x0000aaaa, 0xcc00aaaa, 0x0000aaaa,
2000 0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,
2003 uchar c[Tcmdsize], *p;
2008 memset(c, 0, sizeof(c));
2011 if(ctlr->family >= 7000){
2016 } else if(ctlr->type == Type2030){
2017 *p++ = 145; /* flags */
2018 p++; /* lead time */
2019 *p++ = 5; /* max kill */
2020 *p++ = 1; /* bt3 t7 timer */
2021 put32(p, 0xffff0000); /* kill ack */
2023 put32(p, 0xffff0000); /* kill cts */
2025 *p++ = 2; /* sample time */
2026 *p++ = 0xc; /* bt3 t2 timer */
2027 p += 2; /* bt4 reaction */
2028 for (i = 0; i < nelem(btcoex3wire); i++){
2029 put32(p, btcoex3wire[i]);
2032 p += 2; /* bt4 decision */
2033 put16(p, 0xff); /* valid */
2035 put32(p, 0xf0); /* prio boost */
2038 p++; /* tx prio boost */
2039 p += 2; /* rx prio boost */
2041 if((err = cmd(ctlr, 155, c, p-c)) != nil)
2044 if(ctlr->family >= 7000)
2047 /* set BT priority */
2048 memset(c, 0, sizeof(c));
2051 *p++ = 0x6; /* init1 */
2052 *p++ = 0x7; /* init2 */
2053 *p++ = 0x2; /* periodic low1 */
2054 *p++ = 0x3; /* periodic low2 */
2055 *p++ = 0x4; /* periodic high1 */
2056 *p++ = 0x5; /* periodic high2 */
2057 *p++ = 0x6; /* dtim */
2058 *p++ = 0x8; /* scan52 */
2059 *p++ = 0xa; /* scan24 */
2060 p += 7; /* reserved */
2061 if((err = cmd(ctlr, 204, c, p-c)) != nil)
2064 /* force BT state machine change */
2065 memset(c, 0, sizeof(c));
2068 *p++ = 1; /* open */
2069 *p++ = 1; /* type */
2070 p += 2; /* reserved */
2071 if((err = cmd(ctlr, 205, c, p-c)) != nil)
2074 c[0] = 0; /* open */
2075 return cmd(ctlr, 205, c, p-c);
2079 sendpagingcmd(Ctlr *ctlr)
2081 uchar c[3*4 + 4 + 32*4], *p;
2085 put32(p, (3<<8) | (ctlr->fwmem.npage % FWBlockpages));
2087 put32(p, FWPageshift + FWBlockshift);
2089 put32(p, ctlr->fwmem.nblock);
2092 put32(p, PCIWADDR(ctlr->fwmem.css) >> FWPageshift);
2095 for(i = 0; i < ctlr->fwmem.nblock; i++){
2096 put32(p, PCIWADDR(ctlr->fwmem.block[i].p) >> FWPageshift);
2105 return cmd(ctlr, 79 | (1<<8), c, p-c);
2109 enablepaging(Ctlr *ctlr)
2115 if(ctlr->fwmem.css == nil)
2119 /* clear everything */
2120 memset(ctlr->fwmem.css, 0, FWPagesize);
2121 for(i = 0; i < ctlr->fwmem.nblock; i++)
2122 memset(ctlr->fwmem.block[i].p, 0, ctlr->fwmem.block[i].size);
2125 if(ctlr->calib.done == 0){
2126 sect = ctlr->fw->init.sect;
2127 nsect = ctlr->fw->init.nsect;
2129 sect = ctlr->fw->main.sect;
2130 nsect = ctlr->fw->main.nsect;
2133 /* first CSS segment */
2134 for(i = 0; i < nsect; i++) {
2135 if(sect[i].addr == 0xAAAABBBB){
2142 return "firmware misses CSS+paging sections";
2144 if(sect[i].size > FWPagesize)
2145 return "CSS section too big";
2146 if(sect[i+1].size > (ctlr->fwmem.npage << FWPageshift))
2147 return "paged section too big";
2149 memmove(ctlr->fwmem.css, sect[i].data, sect[i].size);
2151 for(j = 0, o = 0; o < sect[i+1].size; o += n, j++){
2152 n = sect[i+1].size - o;
2153 if(n > ctlr->fwmem.block[j].size)
2154 n = ctlr->fwmem.block[j].size;
2155 memmove(ctlr->fwmem.block[j].p, sect[i+1].data + o, n);
2158 return sendpagingcmd(ctlr);
2162 readnvmsect1(Ctlr *ctlr, int type, void *data, int len, int off)
2164 uchar c[2+2+2+2], *p;
2168 *p++ = 0; // read op
2179 ctlr->nvm.type = -1;
2182 ctlr->nvm.buf = data;
2183 ctlr->nvm.len = len;
2185 if((err = cmd(ctlr, 136, c, p - c)) != nil){
2186 ctlr->nvm.buf = nil;
2188 print("readnvmsect: %s\n", err);
2192 if(ctlr->nvm.ret < len)
2193 len = ctlr->nvm.ret;
2195 if(ctlr->nvm.sts != 0 || ctlr->nvm.off != off || (ctlr->nvm.type & 0xFF) != type)
2202 readnvmsect(Ctlr *ctlr, int type, void *data, int len, int off)
2206 for(o = 0; o < len; o += n){
2210 if((n = readnvmsect1(ctlr, type, (char*)data + o, r, o+off)) < 0)
2221 readnvmconfig(Ctlr *ctlr)
2223 uchar *ea = ctlr->edev->ea;
2228 if(readnvmsect(ctlr, 1, buf, 8, 0) != 8)
2229 return "can't read nvm version";
2231 ctlr->nvm.version = get16(buf);
2232 if (ctlr->family == 7000) {
2235 ctlr->rfcfg.type = (u >> 4) & 3;
2236 ctlr->rfcfg.step = (u >> 2) & 3;
2237 ctlr->rfcfg.dash = (u >> 0) & 3;
2238 ctlr->rfcfg.pnum = (u >> 6) & 3;
2240 ctlr->rfcfg.txantmask = (u >> 8) & 15;
2241 ctlr->rfcfg.rxantmask = (u >> 12) & 15;
2244 if(readnvmsect(ctlr, 12, buf, 8, 0) != 8)
2245 return "can't read nvm phy config";
2249 ctlr->rfcfg.type = (u >> 12) & 0xFFF;
2250 ctlr->rfcfg.step = (u >> 8) & 15;
2251 ctlr->rfcfg.dash = (u >> 4) & 15;
2252 ctlr->rfcfg.pnum = (u >> 6) & 3;
2254 ctlr->rfcfg.txantmask = (u >> 24) & 15;
2255 ctlr->rfcfg.rxantmask = (u >> 28) & 15;
2257 if(ctlr->family >= 8000){
2258 if(readnvmsect(ctlr, 11, ea, Eaddrlen, 0x01<<1) != Eaddrlen){
2261 if((err = niclock(ctlr)) != nil)
2263 a0 = prphread(ctlr, 0xa03080);
2264 a1 = prphread(ctlr, 0xa03084);
2275 readnvmsect(ctlr, 0, ea, Eaddrlen, 0x15<<1);
2277 memmove(ctlr->edev->addr, ea, Eaddrlen);
2283 sendtxantconfig(Ctlr *ctlr, uint val)
2288 return cmd(ctlr, 152, c, 4);
2292 sendphyconfig(Ctlr *ctlr, u32int physku, u32int flowmask, u32int eventmask)
2297 put32(c+4, flowmask);
2298 put32(c+8, eventmask);
2299 return cmd(ctlr, 106, c, 3*4);
2303 delstation(Ctlr *ctlr, Station *sta)
2311 memset(p = c, 0, sizeof(c));
2314 if((err = cmd(ctlr, 25, c, 4)) != nil)
2323 StaTypeGeneralPurpose,
2330 setstation(Ctlr *ctlr, int id, int type, uchar addr[6], Station *sta)
2332 uchar c[Tcmdsize], *p;
2335 memset(p = c, 0, sizeof(c));
2337 *p++ = 0; /* control (1 = update) */
2339 if(ctlr->family >= 7000){
2342 put32(p, ctlr->macid);
2345 p += 2; /* reserved */
2348 memmove(p, addr, 6);
2351 *p++ = id; /* sta id */
2353 if(ctlr->family >= 7000){
2354 *p++ = 1 << 1; /* modify mask */
2355 p += 2; /* reserved */
2357 put32(p, 0<<26 | 0<<28);
2358 p += 4; /* station_flags */
2360 put32(p, 3<<26 | 3<<28);
2361 p += 4; /* station_flags_mask */
2363 p++; /* add_immediate_ba_tid */
2364 p++; /* remove_immediate_ba_tid */
2365 p += 2; /* add_immediate_ba_ssn */
2366 p += 2; /* sleep_tx_count */
2367 p++; /* sleep state flags */
2369 *p++ = (ctlr->fw->api[0] & (1<<30)) != 0 ? type : 0; /* station_type */
2371 p += 2; /* assoc id */
2373 p += 2; /* beamform flags */
2376 p += 4; /* tfd_queue_mask */
2379 p += 2; /* rx_ba_window */
2380 p++; /* sp_length */
2381 p++; /* uapsd_acs */
2385 p += 2; /* kflags */
2388 p += 5*2; /* ttak */
2392 if(ctlr->type != Type4965){
2397 p += 4; /* htflags */
2399 p += 2; /* disable tid */
2400 p += 2; /* reserved */
2401 p++; /* add ba tid */
2402 p++; /* del ba tid */
2403 p += 2; /* add ba ssn */
2404 p += 4; /* reserved */
2407 if((err = cmd(ctlr, 24, c, p - c)) != nil)
2414 setphycontext(Ctlr *ctlr, int amr)
2416 uchar c[Tcmdsize], *p;
2420 phyid = ctlr->phyid;
2422 if(amr == CmdRemove)
2426 } else if(amr == CmdAdd)
2429 memset(p = c, 0, sizeof(c));
2430 put32(p, phyid); // id and color
2434 put32(p, 0); // apply time 0 = immediate
2436 put32(p, 0); // tx param color ????
2439 *p++ = (ctlr->rxflags & RFlag24Ghz) != 0;
2440 *p++ = ctlr->channel; // channel number
2441 *p++ = 0; // channel width (20MHz<<val)
2442 *p++ = 0; // pos1 below
2444 put32(p, ctlr->rfcfg.txantmask);
2446 put32(p, ctlr->rfcfg.rxantmask<<1 | (1<<10) | (1<<12));
2448 put32(p, 0); // acquisition_data ????
2450 put32(p, 0); // dsp_cfg_flags
2453 if((err = cmd(ctlr, 8, c, p - c)) != nil)
2456 if(amr == CmdRemove)
2458 ctlr->phyid = phyid;
2463 reciprocal(u32int v)
2465 return v != 0 ? 0xFFFFFFFFU / v : 0;
2469 setmaccontext(Ether *edev, Ctlr *ctlr, int amr, Wnode *bss)
2471 uchar c[4+4 + 4+4 + 8+8 + 4+4+4+4+4+4+4 + 5*8 + 12*4], *p;
2475 macid = ctlr->macid;
2477 if(amr == CmdRemove)
2481 } else if(amr == CmdAdd)
2484 memset(p = c, 0, sizeof(c));
2490 put32(p, 5); // mac type 5 = bss
2493 put32(p, 0); // tsf id ???
2496 memmove(p, edev->ea, 6);
2499 memmove(p, ctlr->bssid, 6);
2502 put32(p, bss == nil? 0xF : (bss->validrates & 0xF));
2504 put32(p, bss == nil? 0xFF : (bss->validrates >> 4));
2507 put32(p, 0); // protection flags
2510 put32(p, ctlr->rxflags & RFlagShPreamble);
2512 put32(p, ctlr->rxflags & RFlagShSlot);
2514 put32(p, ctlr->rxfilter);
2517 put32(p, 0); // qos flags
2520 for(i = 0; i < 4; i++){
2521 put16(p, 0x07); // cw_min
2523 put16(p, 0x0f); // cw_max
2526 *p++ = (1<<i); // fifos_mask
2527 put16(p, 102*32); // edca_txop
2533 int dtimoff = bss->ival * (int)bss->dtimcount * 1024;
2536 put32(p, bss->aid != 0);
2539 /* dtim time (system time) */
2540 put32(p, bss->rs + dtimoff);
2544 put64(p, bss->ts + dtimoff);
2547 /* beacon interval */
2548 put32(p, bss->ival);
2550 put32(p, reciprocal(bss->ival));
2554 put32(p, bss->ival * bss->dtimperiod);
2556 put32(p, reciprocal(bss->ival * bss->dtimperiod));
2559 /* listen interval */
2564 put32(p, bss->aid & 0x3fff);
2567 /* assoc beacon arrive time */
2573 if((err = cmd(ctlr, 40, c, sizeof(c))) != nil)
2576 if(amr == CmdRemove)
2578 ctlr->macid = macid;
2584 setbindingcontext(Ctlr *ctlr, int amr)
2586 uchar c[Tcmdsize], *p;
2591 bindid = ctlr->bindid;
2593 if(amr == CmdRemove)
2597 } else if(amr == CmdAdd)
2601 return "setbindingcontext: no phyid";
2603 return "setbindingcontext: no macid";
2612 if(amr != CmdRemove){
2613 put32(p, ctlr->macid);
2621 put32(p, ctlr->phyid);
2624 if((err = cmd(ctlr, 43, c, p - c)) != nil)
2627 if(amr == CmdRemove)
2629 ctlr->bindid = bindid;
2634 timeeventdone(void *arg)
2637 return ctlr->te.id == -1 || ctlr->te.active != 0;
2641 settimeevent(Ctlr *ctlr, int amr, int ival)
2643 int duration, delay, timeid;
2649 timeid = ctlr->te.id;
2659 timeid = ctlr->te.id;
2673 memset(p = c, 0, sizeof(c));
2674 put32(p, ctlr->macid);
2681 put32(p, 0); // apply time
2685 put32(p, 0); // depends on
2687 put32(p, 1); // interval
2692 *p++ = 0; // max frags
2693 put16(p, 1<<0 | 1<<1 | 1<<11); // policy
2696 ctlr->te.active = 0;
2697 if((err = cmd(ctlr, 41, c, p - c)) != nil)
2700 if(amr == CmdRemove){
2701 ctlr->te.active = 0;
2705 tsleep(&ctlr->te, timeeventdone, ctlr, 100);
2706 return ctlr->te.active? nil: "timeevent did not start";
2711 setbindingquotas(Ctlr *ctlr, int bindid)
2713 uchar c[4*(3*4)], *p;
2737 return cmd(ctlr, 44, c, p - c);
2741 setmcastfilter(Ctlr *ctlr)
2750 *p++ = 1; // filter own
2751 *p++ = 0; // port id
2753 *p++ = 1; // pass all
2755 memmove(p, ctlr->bssid, 6);
2761 if((err = qcmd(ctlr, 4, 208, nil, 0, b)) != nil){
2765 return flushq(ctlr, 4);
2769 setmacpowermode(Ctlr *ctlr)
2771 uchar c[4 + 2+2 + 4+4+4+4 + 1+1 + 2+2 + 1+1+1+1 + 1+1+1+1 + 1+1], *p;
2774 put32(p, ctlr->macid);
2777 put16(p, 0); // flags
2779 put16(p, 5); // keep alive seconds
2782 put32(p, 0); // rx data timeout
2784 put32(p, 0); // tx data timeout
2786 put32(p, 0); // rx data timeout uapsd
2788 put32(p, 0); // tx data timeout uapsd
2791 *p++ = 0; // lprx rssi threshold
2792 *p++ = 0; // skip dtim periods
2794 put16(p, 0); // snooze interval
2796 put16(p, 0); // snooze window
2799 *p++ = 0; // snooze step
2800 *p++ = 0; // qndp tid
2801 *p++ = 0; // uapsd ac flags
2802 *p++ = 0; // uapsd max sp
2804 *p++ = 0; // heavy tx thld packets
2805 *p++ = 0; // heavy rx thld packets
2807 *p++ = 0; // heavy tx thld percentage
2808 *p++ = 0; // heavy rx thld percentage
2810 *p++ = 0; // limited ps threshold
2811 *p++ = 0; // reserved
2813 return cmd(ctlr, 169, c, p - c);
2817 disablebeaconfilter(Ctlr *ctlr)
2821 memset(c, 0, sizeof(c));
2822 return cmd(ctlr, 210, c, 11*4);
2826 tttxbackoff(Ctlr *ctlr)
2831 cmd(ctlr, 126, c, sizeof(c));
2835 updatedevicepower(Ctlr *ctlr)
2839 memset(c, 0, sizeof(c));
2840 put16(c, 0<<13 | 1<<0); // cont active off, pm enable
2842 return cmd(ctlr, 119, c, 4);
2846 postboot7000(Ctlr *ctlr)
2850 if(ctlr->calib.done == 0){
2851 if((err = readnvmconfig(ctlr)) != nil)
2855 if((err = sendtxantconfig(ctlr, ctlr->rfcfg.txantmask)) != nil)
2858 if(ctlr->calib.done == 0){
2859 if((err = sendphyconfig(ctlr,
2861 ctlr->fw->init.defcalib.flowmask,
2862 ctlr->fw->init.defcalib.eventmask)) != nil)
2865 /* wait to collect calibration records */
2866 if(irqwait(ctlr, Ierr, 2000))
2867 return "calibration failed";
2869 if(ctlr->calib.done == 0){
2870 print("iwl: no calibration results\n");
2871 ctlr->calib.done = 1;
2877 for(i = 0; i < nelem(ctlr->calib.cmd); i++){
2878 if((b = ctlr->calib.cmd[i]) == nil)
2880 b = copyblock(b, BLEN(b));
2881 if((qcmd(ctlr, 4, 108, nil, 0, b)) != nil){
2885 if((err = flushq(ctlr, 4)) != nil)
2889 if((err = sendphyconfig(ctlr,
2891 ctlr->fw->main.defcalib.flowmask,
2892 ctlr->fw->main.defcalib.eventmask)) != nil)
2895 if((err = sendbtcoexadv(ctlr)) != nil)
2898 /* Initialize tx backoffs to the minimum. */
2899 if(ctlr->family == 7000)
2902 if((err = updatedevicepower(ctlr)) != nil){
2903 print("can't update device power: %s\n", err);
2906 if((err = sendmccupdate(ctlr, "ZZ")) != nil){
2907 print("can't disable beacon filter: %s\n", err);
2910 if((err = disablebeaconfilter(ctlr)) != nil){
2911 print("can't disable beacon filter: %s\n", err);
2920 postboot6000(Ctlr *ctlr)
2925 /* disable wimax coexistance */
2926 memset(c, 0, sizeof(c));
2927 if((err = cmd(ctlr, 90, c, 4+4*16)) != nil)
2930 /* 6235 times out if we calibrate the crystal immediately */
2931 tsleep(&up->sleep, return0, nil, 10);
2932 if(ctlr->type != Type5150){
2933 /* calibrate crystal */
2934 memset(c, 0, sizeof(c));
2935 c[0] = 15; /* code */
2936 c[1] = 0; /* group */
2937 c[2] = 1; /* ngroup */
2938 c[3] = 1; /* isvalid */
2939 c[4] = ctlr->eeprom.crystal;
2940 c[5] = ctlr->eeprom.crystal>>16;
2941 /* for some reason 8086:4238 needs a second try */
2942 if(cmd(ctlr, 176, c, 8) != nil && (err = cmd(ctlr, 176, c, 8)) != nil)
2946 if(ctlr->calib.done == 0){
2947 /* query calibration (init firmware) */
2948 memset(c, 0, sizeof(c));
2949 put32(c + 0*(5*4) + 0, 0xffffffff);
2950 put32(c + 0*(5*4) + 4, 0xffffffff);
2951 put32(c + 0*(5*4) + 8, 0xffffffff);
2952 put32(c + 2*(5*4) + 0, 0xffffffff);
2953 if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil)
2956 /* wait to collect calibration records */
2957 if(irqwait(ctlr, Ierr, 2000))
2958 return "calibration failed";
2960 if(ctlr->calib.done == 0){
2961 print("iwl: no calibration results\n");
2962 ctlr->calib.done = 1;
2965 static uchar cmds[] = {8, 9, 11, 17, 16};
2968 /* send calibration records (runtime firmware) */
2969 for(q=0; q<nelem(cmds); q++){
2974 if(i == 8 && ctlr->type != Type5150 && ctlr->type != Type2030 &&
2975 ctlr->type != Type2000)
2977 if(i == 17 && (ctlr->type >= Type6000 || ctlr->type == Type5150) &&
2978 ctlr->type != Type2030 && ctlr->type != Type2000)
2981 if((b = ctlr->calib.cmd[i]) == nil)
2983 b = copyblock(b, BLEN(b));
2984 if((err = qcmd(ctlr, 4, 176, nil, 0, b)) != nil){
2988 if((err = flushq(ctlr, 4)) != nil)
2992 /* temperature sensor offset */
2993 switch (ctlr->type){
2995 memset(c, 0, sizeof(c));
3001 if((err = cmd(ctlr, 176, c, 4+2+2)) != nil)
3007 memset(c, 0, sizeof(c));
3012 if(ctlr->eeprom.rawtemp != 0){
3013 put16(c + 4, ctlr->eeprom.temp);
3014 put16(c + 6, ctlr->eeprom.rawtemp);
3019 put16(c + 8, ctlr->eeprom.volt);
3020 if((err = cmd(ctlr, 176, c, 4+2+2+2+2)) != nil)
3025 if(ctlr->type == Type6005 || ctlr->type == Type6050){
3026 /* runtime DC calibration */
3027 memset(c, 0, sizeof(c));
3028 put32(c + 0*(5*4) + 0, 0xffffffff);
3029 put32(c + 0*(5*4) + 4, 1<<1);
3030 if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil)
3034 if((err = sendtxantconfig(ctlr, ctlr->rfcfg.txantmask & 7)) != nil)
3037 if(ctlr->type == Type2030){
3038 if((err = sendbtcoexadv(ctlr)) != nil)
3046 initqueue(Ctlr *ctlr, int qid, int fifo, int chainmode, int window)
3048 csr32w(ctlr, HbusTargWptr, (qid << 8) | 0);
3050 if(ctlr->family >= 7000 || ctlr->type != Type4965){
3051 if(ctlr->family >= 7000)
3052 prphwrite(ctlr, SchedQueueStatus + qid*4, 1 << 19);
3055 prphwrite(ctlr, SchedQChainSel, prphread(ctlr, SchedQChainSel) | (1<<qid));
3057 prphwrite(ctlr, SchedQChainSel, prphread(ctlr, SchedQChainSel) & ~(1<<qid));
3059 prphwrite(ctlr, SchedAggrSel, prphread(ctlr, SchedAggrSel) & ~(1<<qid));
3061 prphwrite(ctlr, SchedQueueRdptr + qid*4, 0);
3063 /* Set scheduler window size and frame limit. */
3064 memwrite(ctlr, ctlr->sched.base + SchedCtxOff + qid*8, 0);
3065 memwrite(ctlr, ctlr->sched.base + SchedCtxOff + qid*8 + 4, window<<16 | window);
3067 if(ctlr->family >= 7000){
3068 prphwrite(ctlr, SchedQueueStatus + qid*4, 0x017f0018 | fifo);
3070 prphwrite(ctlr, SchedQueueStatus + qid*4, 0x00ff0018 | fifo);
3074 prphwrite(ctlr, SchedQChainSel4965, prphread(ctlr, SchedQChainSel4965) | (1<<qid));
3076 prphwrite(ctlr, SchedQChainSel4965, prphread(ctlr, SchedQChainSel4965) & ~(1<<qid));
3078 prphwrite(ctlr, SchedQueueRdptr4965 + qid*4, 0);
3080 /* Set scheduler window size and frame limit. */
3081 memwrite(ctlr, ctlr->sched.base + SchedCtxOff4965 + qid*8, window);
3082 memwrite(ctlr, ctlr->sched.base + SchedCtxOff4965 + qid*8 + 4, window<<16);
3084 prphwrite(ctlr, SchedQueueStatus4965 + qid*4, 0x0007fc01 | fifo<<1);
3089 postboot(Ctlr *ctlr)
3091 uint ctxoff, ctxlen, dramaddr;
3095 if((err = niclock(ctlr)) != nil)
3098 if(ctlr->family >= 7000 || ctlr->type != Type4965){
3099 dramaddr = SchedDramAddr;
3100 ctxoff = SchedCtxOff;
3101 ctxlen = (SchedTransTblOff + 2*ctlr->ntxq) - ctxoff;
3103 dramaddr = SchedDramAddr4965;
3104 ctxoff = SchedCtxOff4965;
3105 ctxlen = SchedCtxLen4965;
3108 ctlr->sched.base = prphread(ctlr, SchedSramAddr);
3109 for(i=0; i < ctxlen; i += 4)
3110 memwrite(ctlr, ctlr->sched.base + ctxoff + i, 0);
3112 prphwrite(ctlr, dramaddr, PCIWADDR(ctlr->sched.s)>>10);
3114 if(ctlr->family >= 7000) {
3115 prphwrite(ctlr, SchedEnCtrl, 0);
3116 prphwrite(ctlr, SchedChainExtEn, 0);
3119 for(i = 0; i < nelem(ctlr->tx); i++){
3120 if(i == 4 && ctlr->family < 7000 && ctlr->type == Type4965)
3123 static char qid2fifo[] = {
3124 3, 2, 1, 0, 7, 5, 6,
3128 initqueue(ctlr, i, f, i != 4 && ctlr->type != Type4965, 64);
3131 /* Enable interrupts for all queues. */
3132 if(ctlr->family >= 7000){
3133 prphwrite(ctlr, SchedEnCtrl, 1 << 4);
3134 } else if(ctlr->type != Type4965) {
3135 prphwrite(ctlr, SchedIntrMask, (1<<ctlr->ntxq)-1);
3137 prphwrite(ctlr, SchedIntrMask4965, (1<<ctlr->ntxq)-1);
3140 /* Identify TX FIFO rings (0-7). */
3141 if(ctlr->family >= 7000 || ctlr->type != Type4965){
3142 prphwrite(ctlr, SchedTxFact, 0xff);
3144 prphwrite(ctlr, SchedTxFact4965, 0xff);
3147 /* Enable DMA channels */
3148 for(i = 0; i < ctlr->ndma; i++)
3149 csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna);
3151 /* Auto Retry Enable */
3152 csr32w(ctlr, FhTxChicken, csr32r(ctlr, FhTxChicken) | 2);
3156 if((err = enablepaging(ctlr)) != nil){
3157 ctlr->calib.done = 0;
3161 if(ctlr->family >= 7000)
3162 return postboot7000(ctlr);
3163 else if(ctlr->type != Type4965)
3164 return postboot6000(ctlr);
3170 loadfirmware1(Ctlr *ctlr, u32int dst, uchar *data, int size)
3172 enum { Maxchunk = 0x20000 };
3176 while(size > Maxchunk){
3177 if((err = loadfirmware1(ctlr, dst, data, Maxchunk)) != nil)
3184 dma = mallocalign(size, 16, 0, 0);
3186 return "no memory for dma";
3187 memmove(dma, data, size);
3190 if((err = niclock(ctlr)) != nil){
3195 if(ctlr->family >= 7000 && dst >= 0x40000 && dst < 0x57fff)
3196 prphwrite(ctlr, LmpmChick, prphread(ctlr, LmpmChick) | ExtAddr);
3198 prphwrite(ctlr, LmpmChick, prphread(ctlr, LmpmChick) & ~ExtAddr);
3200 csr32w(ctlr, FhTxConfig + 9*32, 0);
3201 csr32w(ctlr, FhSramAddr + 9*4, dst);
3202 csr32w(ctlr, FhTfbdCtrl0 + 9*8, PCIWADDR(dma));
3203 csr32w(ctlr, FhTfbdCtrl1 + 9*8, size);
3204 csr32w(ctlr, FhTxBufStatus + 9*32,
3205 (1<<FhTxBufStatusTbNumShift) |
3206 (1<<FhTxBufStatusTbIdxShift) |
3207 FhTxBufStatusTfbdValid);
3208 csr32w(ctlr, FhTxConfig + 9*32, FhTxConfigDmaEna | FhTxConfigCirqHostEndTfd);
3212 if(irqwait(ctlr, Ifhtx|Ierr, 5000) != Ifhtx)
3213 err = "dma error / timeout";
3215 if(niclock(ctlr) == nil){
3216 prphwrite(ctlr, LmpmChick, prphread(ctlr, LmpmChick) & ~ExtAddr);
3226 setloadstatus(Ctlr *ctlr, u32int val)
3230 if((err = niclock(ctlr)) != nil)
3232 csr32w(ctlr, UcodeLoadStatus, val);
3238 loadsections(Ctlr *ctlr, FWSect *sect, int nsect)
3243 if(ctlr->family >= 8000){
3244 if((err = niclock(ctlr)) != nil)
3246 prphwrite(ctlr, ReleaseCpuReset, CpuResetBit);
3251 for(i = 0; i < nsect; i++){
3252 if(sect[i].addr == 0xAAAABBBB)
3254 if(sect[i].addr == 0xFFFFCCCC)
3257 if(sect[i].data == nil || sect[i].size == 0)
3258 return "bad load section";
3259 if((err = loadfirmware1(ctlr, sect[i].addr, sect[i].data, sect[i].size)) != nil)
3263 if(ctlr->family >= 8000
3264 && (err = setloadstatus(ctlr, (1ULL << num)-1)) != nil)
3271 ucodestart(Ctlr *ctlr)
3273 memset(&ctlr->fwinfo, 0, sizeof(ctlr->fwinfo));
3274 if(ctlr->family >= 8000)
3275 return setloadstatus(ctlr, -1);
3276 csr32w(ctlr, Reset, 0);
3290 if(fw->boot.text.size == 0){
3291 if(ctlr->calib.done == 0){
3292 if((err = loadsections(ctlr, fw->init.sect, fw->init.nsect)) != nil)
3294 if((err = ucodestart(ctlr)) != nil)
3297 tsleep(&up->sleep, return0, 0, 100);
3299 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive|| !ctlr->fwinfo.valid){
3300 return "init firmware boot failed";
3302 if((err = postboot(ctlr)) != nil)
3304 if((err = reset(ctlr)) != nil)
3308 if((err = loadsections(ctlr, fw->main.sect, fw->main.nsect)) != nil)
3310 if((err= ucodestart(ctlr)) != nil)
3313 tsleep(&up->sleep, return0, 0, 100);
3315 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive || !ctlr->fwinfo.valid)
3316 return "main firmware boot failed";
3318 return postboot(ctlr);
3321 if(ctlr->family >= 7000)
3322 return "wrong firmware image";
3324 size = ROUND(fw->init.data.size, 16) + ROUND(fw->init.text.size, 16);
3325 dma = mallocalign(size, 16, 0, 0);
3327 return "no memory for dma";
3329 if((err = niclock(ctlr)) != nil){
3335 memmove(p, fw->init.data.data, fw->init.data.size);
3337 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
3338 prphwrite(ctlr, BsmDramDataSize, fw->init.data.size);
3339 p += ROUND(fw->init.data.size, 16);
3340 memmove(p, fw->init.text.data, fw->init.text.size);
3342 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
3343 prphwrite(ctlr, BsmDramTextSize, fw->init.text.size);
3346 if((err = niclock(ctlr)) != nil){
3351 p = fw->boot.text.data;
3352 n = fw->boot.text.size/4;
3353 for(i=0; i<n; i++, p += 4)
3354 prphwrite(ctlr, BsmSramBase+i*4, get32(p));
3356 prphwrite(ctlr, BsmWrMemSrc, 0);
3357 prphwrite(ctlr, BsmWrMemDst, 0);
3358 prphwrite(ctlr, BsmWrDwCount, n);
3360 prphwrite(ctlr, BsmWrCtrl, 1<<31);
3362 for(i=0; i<1000; i++){
3363 if((prphread(ctlr, BsmWrCtrl) & (1<<31)) == 0)
3370 return "bootcode timeout";
3373 prphwrite(ctlr, BsmWrCtrl, 1<<30);
3376 csr32w(ctlr, Reset, 0);
3377 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
3379 return "boot firmware boot failed";
3383 size = ROUND(fw->main.data.size, 16) + ROUND(fw->main.text.size, 16);
3384 dma = mallocalign(size, 16, 0, 0);
3386 return "no memory for dma";
3387 if((err = niclock(ctlr)) != nil){
3392 memmove(p, fw->main.data.data, fw->main.data.size);
3394 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
3395 prphwrite(ctlr, BsmDramDataSize, fw->main.data.size);
3396 p += ROUND(fw->main.data.size, 16);
3397 memmove(p, fw->main.text.data, fw->main.text.size);
3399 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
3400 prphwrite(ctlr, BsmDramTextSize, fw->main.text.size | (1<<31));
3403 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
3405 return "main firmware boot failed";
3408 return postboot(ctlr);
3415 return q->n < Ntxqmax;
3419 qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
3426 assert(qid < ctlr->ntxq);
3428 if((code & 0xFF00) != 0)
3433 if(hdrlen+size > Tcmdsize)
3434 bcmd = allocb(hdrlen + size);
3440 while(q->n >= Ntxqmax && !ctlr->broken){
3444 tsleep(q, txqready, q, 5);
3452 return "qcmd: broken";
3454 /* wake up the nic (just needed for 7k) */
3455 if(ctlr->family == 7000 && q->n == 0)
3456 if(niclock(ctlr) != nil){
3458 return "qcmd: busy";
3465 bcmd->next = q->b[q->i];
3469 bcmd->wp = c + hdrlen + size;
3471 c = q->c + q->i * Tcmdsize;
3477 c[1] = code>>8; /* group id */
3485 c[1] = 0; /* flags */
3490 memmove(c+hdrlen, data, size);
3493 /* build descriptor */
3494 d = q->d + q->i * Tdscsize;
3498 *d++ = 1 + (block != nil); /* nsegs */
3499 put32(d, PCIWADDR(c)); d += 4;
3500 put16(d, size << 4); d += 2;
3503 put32(d, PCIWADDR(block->rp)); d += 4;
3504 put16(d, size << 4); d += 2;
3510 q->i = (q->i+1) % Ntx;
3511 csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i);
3526 flushq(Ctlr *ctlr, uint qid)
3533 for(i = 0; i < 200 && !ctlr->broken; i++){
3539 tsleep(q, txqempty, q, 10);
3545 return "flushq: broken";
3547 return "flushq: timeout";
3551 cmd(Ctlr *ctlr, uint code, uchar *data, int size)
3555 if(0) print("cmd %ud\n", code);
3557 if((err = qcmd(ctlr, 4, code, data, size, nil)) != nil
3558 || (err = flushq(ctlr, 4)) != nil){
3559 print("#l%d: cmd %ud: %s\n", ctlr->edev->ctlrno, code, err);
3566 setled(Ctlr *ctlr, int which, int on, int off)
3570 if(ctlr->family >= 7000)
3573 csr32w(ctlr, Led, csr32r(ctlr, Led) & ~LedBsmCtrl);
3579 cmd(ctlr, 72, c, sizeof(c));
3583 rxoff7000(Ether *edev, Ctlr *ctlr)
3588 for(i = 0; i < nelem(ctlr->tx); i++)
3590 settimeevent(ctlr, CmdRemove, 0);
3592 if((err = setbindingquotas(ctlr, -1)) != nil){
3593 print("can't disable quotas: %s\n", err);
3596 if((err = delstation(ctlr, &ctlr->bss)) != nil){
3597 print("can't remove bss station: %s\n", err);
3600 if((err = delstation(ctlr, &ctlr->bcast)) != nil){
3601 print("can't remove bcast station: %s\n", err);
3604 if((err = setbindingcontext(ctlr, CmdRemove)) != nil){
3605 print("removing bindingcontext: %s\n", err);
3608 if((err = setmaccontext(edev, ctlr, CmdRemove, nil)) != nil){
3609 print("removing maccontext: %s\n", err);
3612 if((err = setphycontext(ctlr, CmdRemove)) != nil){
3613 print("setphycontext: %s\n", err);
3620 rxon7000(Ether *edev, Ctlr *ctlr)
3624 if((err = setphycontext(ctlr, CmdAdd)) != nil){
3625 print("setphycontext: %s\n", err);
3628 if((err = setmaccontext(edev, ctlr, CmdAdd, nil)) != nil){
3629 print("setmaccontext: %s\n", err);
3632 if((err = setbindingcontext(ctlr, CmdAdd)) != nil){
3633 print("removing bindingcontext: %s\n", err);
3636 if((err = setmcastfilter(ctlr)) != nil){
3637 print("can't set mcast filter: %s\n", err);
3640 if((err = setmacpowermode(ctlr)) != nil){
3641 print("can't set mac power: %s\n", err);
3644 if((err = setbindingquotas(ctlr, ctlr->aid != 0 ? ctlr->bindid : -1)) != nil){
3645 print("can't set binding quotas: %s\n", err);
3652 rxon6000(Ether *edev, Ctlr *ctlr)
3654 uchar c[Tcmdsize], *p;
3657 memset(p = c, 0, sizeof(c));
3658 memmove(p, edev->ea, 6); p += 8; /* myaddr */
3659 memmove(p, ctlr->bssid, 6); p += 8; /* bssid */
3660 memmove(p, edev->ea, 6); p += 8; /* wlap */
3661 *p++ = 3; /* mode (STA) */
3662 *p++ = 0; /* air (?) */
3664 put16(p, ((ctlr->rfcfg.rxantmask & 7)<<1) | (2<<10) | (2<<12));
3666 *p++ = 0xff; /* ofdm mask (not yet negotiated) */
3667 *p++ = 0x0f; /* cck mask (not yet negotiated) */
3668 put16(p, ctlr->aid & 0x3fff);
3670 put32(p, ctlr->rxflags);
3672 put32(p, ctlr->rxfilter);
3674 *p++ = ctlr->channel;
3676 *p++ = 0xff; /* ht single mask */
3677 *p++ = 0xff; /* ht dual mask */
3678 if(ctlr->type != Type4965){
3679 *p++ = 0xff; /* ht triple mask */
3681 put16(p, 0); p += 2; /* acquisition */
3682 p += 2; /* reserved */
3684 if((err = cmd(ctlr, 16, c, p - c)) != nil){
3685 print("rxon6000: %s\n", err);
3692 rxon(Ether *edev, Wnode *bss)
3694 Ctlr *ctlr = edev->ctlr;
3697 if(ctlr->family >= 7000)
3698 if((err = rxoff7000(edev, ctlr)) != nil)
3701 ctlr->rxfilter = FilterNoDecrypt | FilterMulticast | FilterBeacon;
3702 if(ctlr->family >= 7000)
3703 ctlr->rxfilter |= FilterNoDecryptMcast;
3705 ctlr->rxfilter |= FilterPromisc;
3707 ctlr->rxflags = RFlagTSF | RFlagCTSToSelf | RFlag24Ghz | RFlagAuto;
3709 ctlr->aid = bss->aid;
3710 ctlr->channel = bss->channel;
3711 memmove(ctlr->bssid, bss->bssid, sizeof(ctlr->bssid));
3712 if(bss->cap & (1<<5))
3713 ctlr->rxflags |= RFlagShPreamble;
3714 if(bss->cap & (1<<10))
3715 ctlr->rxflags |= RFlagShSlot;
3717 ctlr->rxfilter |= FilterBSS;
3718 ctlr->rxfilter &= ~FilterBeacon;
3721 ctlr->bcast.id = -1;
3725 memmove(ctlr->bssid, edev->bcast, sizeof(ctlr->bssid));
3726 ctlr->bcast.id = -1;
3731 setled(ctlr, 2, 0, 1); /* on when associated */
3732 else if(memcmp(ctlr->bssid, edev->bcast, sizeof(ctlr->bssid)) != 0)
3733 setled(ctlr, 2, 10, 10); /* slow blink when connecting */
3735 setled(ctlr, 2, 5, 5); /* fast blink when scanning */
3737 if(ctlr->wifi->debug)
3738 print("#l%d: rxon: bssid %E, aid %x, channel %d, rxfilter %ux, rxflags %ux\n",
3739 edev->ctlrno, ctlr->bssid, ctlr->aid, ctlr->channel, ctlr->rxfilter, ctlr->rxflags);
3741 if(ctlr->family >= 7000)
3742 err = rxon7000(edev, ctlr);
3744 err = rxon6000(edev, ctlr);
3748 if(ctlr->bcast.id == -1){
3749 if((err = setstation(ctlr,
3750 (ctlr->type != Type4965)? 15: 31,
3751 StaTypeGeneralPurpose,
3753 &ctlr->bcast)) != nil)
3756 if(ctlr->bss.id == -1 && bss != nil && ctlr->aid != 0){
3757 if((err = setstation(ctlr,
3761 &ctlr->bss)) != nil)
3764 if(ctlr->family >= 7000)
3765 if((err = setmaccontext(edev, ctlr, CmdModify, bss)) != nil)
3773 transmit(Wifi *wifi, Wnode *wn, Block *b)
3775 int flags, rate, ant;
3776 uchar c[Tcmdsize], *p;
3787 if(ctlr->attached == 0 || ctlr->broken){
3794 if((wn->channel != ctlr->channel)
3795 || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0))){
3796 if(rxon(edev, wn) != nil)
3801 * unless authenticated, the firmware will hop
3802 * channels unless we force it onto a channel using
3805 if(ctlr->aid == 0 && ctlr->family >= 7000)
3806 if(settimeevent(ctlr, CmdAdd, wn->ival) != nil)
3810 /* association note has no data to transmit */
3817 w = (Wifipkt*)b->rp;
3818 if((w->a1[0] & 1) == 0){
3819 flags |= TFlagNeedACK;
3822 flags |= TFlagNeedRTS;
3824 if((w->fc[0] & 0x0c) == 0x08 && ctlr->bss.id != -1){
3829 if(flags & (TFlagNeedRTS|TFlagNeedCTS)){
3830 if(ctlr->family >= 7000 || ctlr->type != Type4965){
3831 flags &= ~(TFlagNeedRTS|TFlagNeedCTS);
3832 flags |= TFlagNeedProtection;
3834 flags |= TFlagFullTxOp;
3841 if(p >= wifi->rates)
3842 rate = p - wifi->rates;
3846 /* select first available antenna */
3847 ant = ctlr->rfcfg.txantmask & 7;
3849 ant = ((ant - 1) & ant) ^ ant;
3851 memset(p = c, 0, sizeof(c));
3858 p += 4; /* scratch */
3860 *p++ = ratetab[rate].plcp;
3861 *p++ = ratetab[rate].flags | (ant<<6);
3863 p += 2; /* xflags */
3864 *p++ = sta->id; /* station id */
3865 *p++ = 0; /* security */
3866 *p++ = 0; /* linkq */
3870 p += 2; /* reserved */
3871 put32(p, ~0); /* lifetime */
3874 /* BUG: scratch ptr? not clear what this is for */
3875 put32(p, PCIWADDR(ctlr->kwpage));
3878 *p++ = 60; /* rts ntries */
3879 *p++ = 15; /* data ntries */
3881 put16(p, 0); /* timeout */
3886 if((err = qcmd(ctlr, 0, 28, c, p - c, b)) != nil){
3887 print("#l%d: transmit %s\n", edev->ctlrno, err);
3893 iwlctl(Ether *edev, void *buf, long n)
3898 if(n >= 5 && memcmp(buf, "reset", 5) == 0){
3903 return wifictl(ctlr->wifi, buf, n);
3908 iwlifstat(Ether *edev, void *buf, long n, ulong off)
3914 return wifistat(ctlr->wifi, buf, n, off);
3919 setoptions(Ether *edev)
3925 for(i = 0; i < edev->nopt; i++)
3926 wificfg(ctlr->wifi, edev->opt[i]);
3930 iwlpromiscuous(void *arg, int on)
3939 rxon(edev, ctlr->wifi->bss);
3944 iwlmulticast(void *, uchar*, int)
3949 iwlrecover(void *arg)
3959 tsleep(&up->sleep, return0, 0, 4000);
3963 if(ctlr->broken == 0)
3969 if((csr32r(ctlr, Gpc) & RfKill) == 0)
3972 if(reset(ctlr) != nil)
3974 if(boot(ctlr) != nil)
3977 rxon(edev, ctlr->wifi->bss);
3985 iwlattach(Ether *edev)
3994 print("#l%d: %s\n", edev->ctlrno, up->errstr);
4000 if(ctlr->attached == 0){
4001 if((csr32r(ctlr, Gpc) & RfKill) == 0)
4002 error("wifi disabled by switch");
4004 if(ctlr->fw == nil){
4009 fn = fwname[ctlr->type];
4010 if(ctlr->type == Type6005){
4011 switch(ctlr->pdev->did){
4012 case 0x0082: /* Centrino Advanced-N 6205 */
4013 case 0x0085: /* Centrino Advanced-N 6205 */
4015 default: /* Centrino Advanced-N 6030, 6235 */
4020 fw = readfirmware(fn);
4021 print("#l%d: firmware: %s, rev %ux, build %ud, size [%d] %ux+%ux + [%d] %ux+%ux + %ux\n",
4024 fw->main.nsect, fw->main.text.size, fw->main.data.size,
4025 fw->init.nsect, fw->init.text.size, fw->init.data.size,
4026 fw->boot.text.size);
4030 if(ctlr->family >= 7000){
4031 u32int u = ctlr->fw->physku;
4033 ctlr->rfcfg.type = u & 3; u >>= 2;
4034 ctlr->rfcfg.step = u & 3; u >>= 2;
4035 ctlr->rfcfg.dash = u & 3; u >>= 12;
4037 ctlr->rfcfg.txantmask = u & 15; u >>= 4;
4038 ctlr->rfcfg.rxantmask = u & 15;
4041 if((err = reset(ctlr)) != nil)
4043 if((err = boot(ctlr)) != nil)
4046 if(ctlr->wifi == nil){
4047 qsetlimit(edev->oq, MaxQueue);
4049 ctlr->wifi = wifiattach(edev, transmit);
4050 /* tested with 2230, it has transmit issues using higher bit rates */
4051 if(ctlr->family >= 7000 || ctlr->type != Type2030)
4052 ctlr->wifi->rates = iwlrates;
4059 kproc("iwlrecover", iwlrecover, edev);
4066 updatesystime(Ctlr *ctlr, u32int ts)
4068 u32int dt = ts - (u32int)ctlr->systime;
4069 ctlr->systime += dt;
4082 if(ctlr->broken || rx->s == nil || rx->b == nil)
4085 for(hw = get16(rx->s) % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){
4086 int type, flags, idx, qid, len;
4093 len = get32(d); d += 4;
4102 if((qid & 0x80) == 0 && qid < ctlr->ntxq){
4103 tx = &ctlr->tx[qid];
4110 if(len >= 0) switch(type){
4111 case 1: /* microcontroller ready */
4112 setfwinfo(ctlr, d, len);
4114 case 24: /* add node done */
4118 case 28: /* tx done */
4119 if(ctlr->family >= 7000){
4120 if(len <= 36 || d[36] == 1 || d[36] == 2)
4122 } else if(ctlr->type == Type4965){
4123 if(len <= 20 || d[20] == 1 || d[20] == 2)
4126 if(len <= 32 || d[32] == 1 || d[32] == 2)
4129 if(ctlr->wifi != nil)
4130 wifitxfail(ctlr->wifi, bb);
4137 if(ctlr->te.id == -1)
4138 ctlr->te.id = get32(d+8);
4143 if(ctlr->te.id == -1 || get32(d+8) != ctlr->te.id)
4145 switch(get32(d+16)){
4147 ctlr->te.active = 1;
4151 ctlr->te.active = 0;
4156 case 102: /* calibration result (Type5000 only) */
4157 if(ctlr->family >= 7000)
4163 if(idx < 0 || idx >= nelem(ctlr->calib.cmd))
4165 if(rbplant(ctlr, rx->i) < 0)
4167 if(ctlr->calib.cmd[idx] != nil)
4168 freeb(ctlr->calib.cmd[idx]);
4171 ctlr->calib.cmd[idx] = b;
4173 case 4: /* init complete (>= 7000 family) */
4174 if(ctlr->family < 7000)
4177 case 103: /* calibration done (Type5000 only) */
4178 ctlr->calib.done = 1;
4180 case 107: /* calibration result (>= 7000 family) */
4181 if(ctlr->family < 7000)
4192 idx = &ctlr->calib.cfg - &ctlr->calib.cmd[0];
4195 idx = &ctlr->calib.nch - &ctlr->calib.cmd[0];
4200 idx = &ctlr->calib.papd[get16(d+4) % nelem(ctlr->calib.papd)] - &ctlr->calib.cmd[0];
4205 idx = &ctlr->calib.txp[get16(d+4) % nelem(ctlr->calib.txp)] - &ctlr->calib.cmd[0];
4210 case 130: /* start scan */
4211 case 132: /* stop scan */
4213 case 136: /* NVM access (>= 7000 family) */
4214 if(ctlr->family < 7000)
4219 if(ctlr->nvm.len < len)
4220 len = ctlr->nvm.len;
4221 ctlr->nvm.off = get16(d + 0);
4222 ctlr->nvm.ret = get16(d + 2);
4223 ctlr->nvm.type= get16(d + 4);
4224 ctlr->nvm.sts = get16(d + 6);
4226 if(ctlr->nvm.ret < len)
4227 len = ctlr->nvm.ret;
4228 if(ctlr->nvm.buf != nil && len > 0)
4229 memmove(ctlr->nvm.buf, d, len);
4230 ctlr->nvm.buf = nil;
4233 case 156: /* rx statistics */
4234 case 157: /* beacon statistics */
4235 case 161: /* state changed */
4236 case 162: /* beacon missed */
4237 case 177: /* mduart load notification */
4239 case 192: /* rx phy */
4241 updatesystime(ctlr, get32(d+4));
4243 case 195: /* rx done */
4249 case 193: /* mpdu rx done */
4254 if(d + 48 + len > b->lim)
4256 updatesystime(ctlr, get32(d+36));
4257 if((d[12] & 3) != 3)
4262 if(d + len + 4 > b->lim)
4264 if((d[len] & 3) != 3)
4267 if(ctlr->wifi == nil)
4269 if(rbplant(ctlr, rx->i) < 0)
4274 put64(d - 8, ctlr->systime);
4275 b->flag |= Btimestamp;
4277 wifiiq(ctlr->wifi, b);
4279 case 197: /* rx compressed ba */
4283 if(tx != nil && tx->n > 0){
4286 /* unlock 7k family nics as all commands are done */
4287 if(ctlr->family == 7000 && tx->n == 0)
4293 csr32w(ctlr, FhRxQ0Wptr, ((hw+Nrx-1) % Nrx) & ~7);
4295 csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7);
4299 iwlinterrupt(Ureg*, void *arg)
4308 csr32w(ctlr, Imr, 0);
4309 isr = csr32r(ctlr, Isr);
4310 fhisr = csr32r(ctlr, FhIsr);
4311 if(isr == 0xffffffff || (isr & 0xfffffff0) == 0xa5a5a5a0){
4315 if(isr == 0 && fhisr == 0)
4317 csr32w(ctlr, Isr, isr);
4318 csr32w(ctlr, FhIsr, fhisr);
4320 if((isr & (Iswrx | Ifhrx | Irxperiodic | Ialive)) || (fhisr & Ifhrx))
4324 print("#l%d: fatal firmware error\n", edev->ctlrno);
4327 ctlr->wait.m |= isr;
4328 if(ctlr->wait.m & ctlr->wait.w)
4329 wakeup(&ctlr->wait);
4331 csr32w(ctlr, Imr, ctlr->ie);
4336 iwlshutdown(Ether *edev)
4344 pcidisable(ctlr->pdev);
4347 static Ctlr *iwlhead, *iwltail;
4357 while(pdev = pcimatch(pdev, 0, 0)) {
4361 if(pdev->ccrb != 2 || pdev->ccru != 0x80)
4363 if(pdev->vid != 0x8086)
4365 if(pdev->mem[0].bar & 1)
4371 case 0x0084: /* WiFi Link 1000 */
4372 case 0x4229: /* WiFi Link 4965 */
4373 case 0x4230: /* WiFi Link 4965 */
4374 case 0x4232: /* Wifi Link 5100 */
4375 case 0x4235: /* Intel Corporation Ultimate N WiFi Link 5300 */
4376 case 0x4236: /* WiFi Link 5300 AGN */
4377 case 0x4237: /* Wifi Link 5100 AGN */
4378 case 0x4239: /* Centrino Advanced-N 6200 */
4379 case 0x423d: /* Wifi Link 5150 */
4380 case 0x423b: /* PRO/Wireless 5350 AGN */
4381 case 0x0082: /* Centrino Advanced-N 6205 */
4382 case 0x0085: /* Centrino Advanced-N 6205 */
4383 case 0x422b: /* Centrino Ultimate-N 6300 variant 1 */
4384 case 0x4238: /* Centrino Ultimate-N 6300 variant 2 */
4385 case 0x08ae: /* Centrino Wireless-N 100 */
4386 case 0x0083: /* Centrino Wireless-N 1000 */
4387 case 0x008a: /* Centrino Wireless-N 1030 */
4388 case 0x0891: /* Centrino Wireless-N 2200 */
4389 case 0x0887: /* Centrino Wireless-N 2230 */
4390 case 0x0888: /* Centrino Wireless-N 2230 */
4391 case 0x0090: /* Centrino Advanced-N 6030 */
4392 case 0x0091: /* Centrino Advanced-N 6030 */
4393 case 0x088e: /* Centrino Advanced-N 6235 */
4394 case 0x088f: /* Centrino Advanced-N 6235 */
4398 case 0x08b1: /* Wireless AC 7260 */
4399 case 0x08b2: /* Wireless AC 7260 */
4403 case 0x24f3: /* Wireless AC 8260 */
4405 fwname = "iwm-8000C-34";
4407 case 0x24fd: /* Wireless AC 8265 */
4409 fwname = "iwm-8265-34";
4411 case 0x2526: /* Wireless AC 9260 */
4413 fwname = "iwm-9260-34";
4417 ctlr = malloc(sizeof(Ctlr));
4419 print("iwl: unable to alloc Ctlr\n");
4422 ctlr->port = pdev->mem[0].bar & ~0xF;
4423 mem = vmap(ctlr->port, pdev->mem[0].size);
4425 print("iwl: can't map %llux\n", ctlr->port);
4431 ctlr->fwname = fwname;
4432 ctlr->family = family;
4433 ctlr->mqrx = family >= 9000;
4436 iwltail->link = ctlr;
4451 for(ctlr = iwlhead; ctlr != nil; ctlr = ctlr->link){
4452 if(ctlr->edev != nil)
4454 if(edev->port == 0 || edev->port == ctlr->port){
4464 edev->port = ctlr->port;
4465 edev->irq = ctlr->pdev->intl;
4466 edev->tbdf = ctlr->pdev->tbdf;
4468 edev->attach = iwlattach;
4469 edev->ifstat = iwlifstat;
4471 edev->shutdown = iwlshutdown;
4472 edev->promiscuous = iwlpromiscuous;
4473 edev->multicast = iwlmulticast;
4476 pcienable(ctlr->pdev);
4477 if(iwlinit(edev) < 0){
4478 pcidisable(ctlr->pdev);
4479 ctlr->edev = (void*)-1;
4484 pcisetbme(ctlr->pdev);
4485 intrenable(edev->irq, iwlinterrupt, edev, edev->tbdf, edev->name);
4493 addethercard("iwl", iwlpnp);