]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/etheriwl.c
etheriwl: support type 2000 devices and the 2200 chip in x230t
[plan9front.git] / sys / src / 9 / pc / etheriwl.c
1 /*
2  * Intel WiFi Link driver.
3  *
4  * Written without any documentation but Damien Bergaminis
5  * OpenBSD iwn(4) driver sources. Requires intel firmware
6  * to be present in /lib/firmware/iwn-* on attach.
7  */
8
9 #include "u.h"
10 #include "../port/lib.h"
11 #include "mem.h"
12 #include "dat.h"
13 #include "fns.h"
14 #include "io.h"
15 #include "../port/error.h"
16 #include "../port/netif.h"
17 #include "../port/etherif.h"
18 #include "../port/wifi.h"
19
20 enum {
21         MaxQueue        = 24*1024,      /* total buffer is 2*MaxQueue: 48k at 22Mbit ≅ 20ms */
22
23         Ntxlog          = 8,
24         Ntx             = 1<<Ntxlog,
25         Ntxqmax         = MaxQueue/1500,
26
27         Nrxlog          = 8,
28         Nrx             = 1<<Nrxlog,
29
30         Rstatsize       = 16,
31         Rbufsize        = 4*1024,
32         Rdscsize        = 8,
33
34         Tbufsize        = 4*1024,
35         Tdscsize        = 128,
36         Tcmdsize        = 140,
37 };
38
39 /* registers */
40 enum {
41         Cfg             = 0x000,        /* config register */
42                 MacSi           = 1<<8,
43                 RadioSi         = 1<<9,
44                 EepromLocked    = 1<<21,
45                 NicReady        = 1<<22,
46                 HapwakeL1A      = 1<<23,
47                 PrepareDone     = 1<<25,
48                 Prepare         = 1<<27,
49
50         Isr             = 0x008,        /* interrupt status */
51         Imr             = 0x00c,        /* interrupt mask */
52                 Ialive          = 1<<0,
53                 Iwakeup         = 1<<1,
54                 Iswrx           = 1<<3,
55                 Ictreached      = 1<<6,
56                 Irftoggled      = 1<<7,
57                 Iswerr          = 1<<25,
58                 Isched          = 1<<26,
59                 Ifhtx           = 1<<27,
60                 Irxperiodic     = 1<<28,
61                 Ihwerr          = 1<<29,
62                 Ifhrx           = 1<<31,
63
64                 Ierr            = Iswerr | Ihwerr,
65                 Idefmask        = Ierr | Ifhtx | Ifhrx | Ialive | Iwakeup | Iswrx | Ictreached | Irftoggled,
66
67         FhIsr           = 0x010,        /* second interrupt status */
68
69         Reset           = 0x020,
70                 
71         Rev             = 0x028,        /* hardware revision */
72
73         EepromIo        = 0x02c,        /* EEPROM i/o register */
74         EepromGp        = 0x030,
75                 
76         OtpromGp        = 0x034,
77                 DevSelOtp       = 1<<16,
78                 RelativeAccess  = 1<<17,
79                 EccCorrStts     = 1<<20,
80                 EccUncorrStts   = 1<<21,
81
82         Gpc             = 0x024,        /* gp cntrl */
83                 MacAccessEna    = 1<<0,
84                 MacClockReady   = 1<<0,
85                 InitDone        = 1<<2,
86                 MacAccessReq    = 1<<3,
87                 NicSleep        = 1<<4,
88                 RfKill          = 1<<27,
89
90         Gio             = 0x03c,
91                 EnaL0S          = 1<<1,
92
93         GpDrv   = 0x050,
94                 GpDrvCalV6      = 1<<2,
95                 GpDrv1X2        = 1<<3,
96                 GpDrvRadioIqInvert      = 1<<7, 
97
98         Led             = 0x094,
99                 LedBsmCtrl      = 1<<5,
100                 LedOn           = 0x38,
101                 LedOff          = 0x78,
102
103         UcodeGp1Clr     = 0x05c,
104                 UcodeGp1RfKill          = 1<<1,
105                 UcodeGp1CmdBlocked      = 1<<2,
106                 UcodeGp1CtempStopRf     = 1<<3,
107
108         ShadowRegCtrl   = 0x0a8,
109
110         Giochicken      = 0x100,
111                 L1AnoL0Srx      = 1<<23,
112                 DisL0Stimer     = 1<<29,
113
114         AnaPll          = 0x20c,
115
116         Dbghpetmem      = 0x240,
117         Dbglinkpwrmgmt  = 0x250,
118
119         MemRaddr        = 0x40c,
120         MemWaddr        = 0x410,
121         MemWdata        = 0x418,
122         MemRdata        = 0x41c,
123
124         PrphWaddr       = 0x444,
125         PrphRaddr       = 0x448,
126         PrphWdata       = 0x44c,
127         PrphRdata       = 0x450,
128
129         HbusTargWptr    = 0x460,
130 };
131
132 /*
133  * Flow-Handler registers.
134  */
135 enum {
136         FhTfbdCtrl0     = 0x1900,       // +q*8
137         FhTfbdCtrl1     = 0x1904,       // +q*8
138
139         FhKwAddr        = 0x197c,
140
141         FhSramAddr      = 0x19a4,       // +q*4
142         FhCbbcQueue     = 0x19d0,       // +q*4
143         FhStatusWptr    = 0x1bc0,
144         FhRxBase        = 0x1bc4,
145         FhRxWptr        = 0x1bc8,
146         FhRxConfig      = 0x1c00,
147                 FhRxConfigEna           = 1<<31,
148                 FhRxConfigRbSize8K      = 1<<16,
149                 FhRxConfigSingleFrame   = 1<<15,
150                 FhRxConfigIrqDstHost    = 1<<12,
151                 FhRxConfigIgnRxfEmpty   = 1<<2,
152
153                 FhRxConfigNrbdShift     = 20,
154                 FhRxConfigRbTimeoutShift= 4,
155
156         FhRxStatus      = 0x1c44,
157
158         FhTxConfig      = 0x1d00,       // +q*32
159                 FhTxConfigDmaCreditEna  = 1<<3,
160                 FhTxConfigDmaEna        = 1<<31,
161                 FhTxConfigCirqHostEndTfd= 1<<20,
162
163         FhTxBufStatus   = 0x1d08,       // +q*32
164                 FhTxBufStatusTbNumShift = 20,
165                 FhTxBufStatusTbIdxShift = 12,
166                 FhTxBufStatusTfbdValid  = 3,
167
168         FhTxChicken     = 0x1e98,
169         FhTxStatus      = 0x1eb0,
170 };
171
172 /*
173  * NIC internal memory offsets.
174  */
175 enum {
176         ApmgClkCtrl     = 0x3000,
177         ApmgClkEna      = 0x3004,
178         ApmgClkDis      = 0x3008,
179                 DmaClkRqt       = 1<<9,
180                 BsmClkRqt       = 1<<11,
181
182         ApmgPs          = 0x300c,
183                 EarlyPwroffDis  = 1<<22,
184                 PwrSrcVMain     = 0<<24,
185                 PwrSrcVAux      = 2<<24,
186                 PwrSrcMask      = 3<<24,
187                 ResetReq        = 1<<26,
188
189         ApmgDigitalSvr  = 0x3058,
190         ApmgAnalogSvr   = 0x306c,
191         ApmgPciStt      = 0x3010,
192         BsmWrCtrl       = 0x3400,
193         BsmWrMemSrc     = 0x3404,
194         BsmWrMemDst     = 0x3408,
195         BsmWrDwCount    = 0x340c,
196         BsmDramTextAddr = 0x3490,
197         BsmDramTextSize = 0x3494,
198         BsmDramDataAddr = 0x3498,
199         BsmDramDataSize = 0x349c,
200         BsmSramBase     = 0x3800,
201 };
202
203 /*
204  * TX scheduler registers.
205  */
206 enum {
207         SchedBase               = 0xa02c00,
208         SchedSramAddr           = SchedBase,
209
210         SchedDramAddr4965       = SchedBase+0x010,
211         SchedTxFact4965         = SchedBase+0x01c,
212         SchedQueueRdptr4965     = SchedBase+0x064,      // +q*4
213         SchedQChainSel4965      = SchedBase+0x0d0,
214         SchedIntrMask4965       = SchedBase+0x0e4,
215         SchedQueueStatus4965    = SchedBase+0x104,      // +q*4
216
217         SchedDramAddr5000       = SchedBase+0x008,
218         SchedTxFact5000         = SchedBase+0x010,
219         SchedQueueRdptr5000     = SchedBase+0x068,      // +q*4
220         SchedQChainSel5000      = SchedBase+0x0e8,
221         SchedIntrMask5000       = SchedBase+0x108,
222         SchedQueueStatus5000    = SchedBase+0x10c,      // +q*4
223         SchedAggrSel5000        = SchedBase+0x248,
224 };
225
226 enum {
227         SchedCtxOff4965         = 0x380,
228         SchedCtxLen4965         = 416,
229
230         SchedCtxOff5000         = 0x600,
231         SchedCtxLen5000         = 512,
232 };
233
234 enum {
235         FilterPromisc           = 1<<0,
236         FilterCtl               = 1<<1,
237         FilterMulticast         = 1<<2,
238         FilterNoDecrypt         = 1<<3,
239         FilterBSS               = 1<<5,
240         FilterBeacon            = 1<<6,
241 };
242
243 enum {
244         RFlag24Ghz              = 1<<0,
245         RFlagCCK                = 1<<1,
246         RFlagAuto               = 1<<2,
247         RFlagShSlot             = 1<<4,
248         RFlagShPreamble         = 1<<5,
249         RFlagNoDiversity        = 1<<7,
250         RFlagAntennaA           = 1<<8,
251         RFlagAntennaB           = 1<<9,
252         RFlagTSF                = 1<<15,
253         RFlagCTSToSelf          = 1<<30,
254 };
255
256 typedef struct FWInfo FWInfo;
257 typedef struct FWImage FWImage;
258 typedef struct FWSect FWSect;
259
260 typedef struct TXQ TXQ;
261 typedef struct RXQ RXQ;
262
263 typedef struct Ctlr Ctlr;
264
265 struct FWSect
266 {
267         uchar   *data;
268         uint    size;
269 };
270
271 struct FWImage
272 {
273         struct {
274                 FWSect  text;
275                 FWSect  data;
276         } init, main, boot;
277
278         uint    rev;
279         uint    build;
280         char    descr[64+1];
281         uchar   data[];
282 };
283
284 struct FWInfo
285 {
286         uchar   major;
287         uchar   minjor;
288         uchar   type;
289         uchar   subtype;
290
291         u32int  logptr;
292         u32int  errptr;
293         u32int  tstamp;
294         u32int  valid;
295 };
296
297 struct TXQ
298 {
299         uint    n;
300         uint    i;
301         Block   **b;
302         uchar   *d;
303         uchar   *c;
304
305         uint    lastcmd;
306
307         Rendez;
308         QLock;
309 };
310
311 struct RXQ
312 {
313         uint    i;
314         Block   **b;
315         u32int  *p;
316         uchar   *s;
317 };
318
319 struct Ctlr {
320         Lock;
321         QLock;
322
323         Ctlr *link;
324         Pcidev *pdev;
325         Wifi *wifi;
326
327         int type;
328         int port;
329         int power;
330         int active;
331         int broken;
332         int attached;
333
334         u32int ie;
335
336         u32int *nic;
337         uchar *kwpage;
338
339         /* assigned node ids in hardware node table or -1 if unassigned */
340         int bcastnodeid;
341         int bssnodeid;
342
343         /* current receiver settings */
344         uchar bssid[Eaddrlen];
345         int channel;
346         int prom;
347         int aid;
348
349         RXQ rx;
350         TXQ tx[20];
351
352         struct {
353                 Rendez;
354                 u32int  m;
355                 u32int  w;
356         } wait;
357
358         struct {
359                 uchar   type;
360                 uchar   step;
361                 uchar   dash;
362                 uchar   txantmask;
363                 uchar   rxantmask;
364         } rfcfg;
365
366         struct {
367                 int     otp;
368                 uint    off;
369
370                 uchar   version;
371                 uchar   type;
372                 u16int  volt;
373                 u16int  temp;
374                 u16int  rawtemp;
375
376                 char    regdom[4+1];
377
378                 u32int  crystal;
379         } eeprom;
380
381         struct {
382                 Block   *cmd[21];
383                 int     done;
384         } calib;
385
386         struct {
387                 u32int  base;
388                 uchar   *s;
389         } sched;
390
391         FWInfo fwinfo;
392         FWImage *fw;
393 };
394
395 /* controller types */
396 enum {
397         Type4965        = 0,
398         Type5300        = 2,
399         Type5350        = 3,
400         Type5150        = 4,
401         Type5100        = 5,
402         Type1000        = 6,
403         Type6000        = 7,
404         Type6050        = 8,
405         Type6005        = 11,   /* also Centrino Advanced-N 6030, 6235 */
406         Type2030        = 12,
407         Type2000        = 16,
408 };
409
410 static char *fwname[32] = {
411         [Type4965] "iwn-4965",
412         [Type5300] "iwn-5000",
413         [Type5350] "iwn-5000",
414         [Type5150] "iwn-5150",
415         [Type5100] "iwn-5000",
416         [Type1000] "iwn-1000",
417         [Type6000] "iwn-6000",
418         [Type6050] "iwn-6050",
419         [Type6005] "iwn-6005", /* see in iwlattach() below */
420         [Type2030] "iwn-2030",
421         [Type2000] "iwn-2000",
422 };
423
424 static char *qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block);
425 static char *flushq(Ctlr *ctlr, uint qid);
426 static char *cmd(Ctlr *ctlr, uint code, uchar *data, int size);
427
428 #define csr32r(c, r)    (*((c)->nic+((r)/4)))
429 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
430
431 static uint
432 get16(uchar *p){
433         return *((u16int*)p);
434 }
435 static uint
436 get32(uchar *p){
437         return *((u32int*)p);
438 }
439 static void
440 put32(uchar *p, uint v){
441         *((u32int*)p) = v;
442 }
443 static void
444 put16(uchar *p, uint v){
445         *((u16int*)p) = v;
446 };
447
448 static char*
449 niclock(Ctlr *ctlr)
450 {
451         int i;
452
453         csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq);
454         for(i=0; i<1000; i++){
455                 if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna)
456                         return 0;
457                 delay(10);
458         }
459         return "niclock: timeout";
460 }
461
462 static void
463 nicunlock(Ctlr *ctlr)
464 {
465         csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq);
466 }
467
468 static u32int
469 prphread(Ctlr *ctlr, uint off)
470 {
471         csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off);
472         coherence();
473         return csr32r(ctlr, PrphRdata);
474 }
475 static void
476 prphwrite(Ctlr *ctlr, uint off, u32int data)
477 {
478         csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off);
479         coherence();
480         csr32w(ctlr, PrphWdata, data);
481 }
482
483 static u32int
484 memread(Ctlr *ctlr, uint off)
485 {
486         csr32w(ctlr, MemRaddr, off);
487         coherence();
488         return csr32r(ctlr, MemRdata);
489 }
490 static void
491 memwrite(Ctlr *ctlr, uint off, u32int data)
492 {
493         csr32w(ctlr, MemWaddr, off);
494         coherence();
495         csr32w(ctlr, MemWdata, data);
496 }
497
498 static void
499 setfwinfo(Ctlr *ctlr, uchar *d, int len)
500 {
501         FWInfo *i;
502
503         if(len < 32)
504                 return;
505         i = &ctlr->fwinfo;
506         i->minjor = *d++;
507         i->major = *d++;
508         d += 2+8;
509         i->type = *d++;
510         i->subtype = *d++;
511         d += 2;
512         i->logptr = get32(d); d += 4;
513         i->errptr = get32(d); d += 4;
514         i->tstamp = get32(d); d += 4;
515         i->valid = get32(d);
516 };
517
518 static void
519 dumpctlr(Ctlr *ctlr)
520 {
521         u32int dump[13];
522         int i;
523
524         print("lastcmd: %ud (0x%ux)\n", ctlr->tx[4].lastcmd,  ctlr->tx[4].lastcmd);
525         if(ctlr->fwinfo.errptr == 0){
526                 print("no error pointer\n");
527                 return;
528         }
529         for(i=0; i<nelem(dump); i++)
530                 dump[i] = memread(ctlr, ctlr->fwinfo.errptr + i*4);
531         print(  "error:\tid %ux, pc %ux,\n"
532                 "\tbranchlink %.8ux %.8ux, interruptlink %.8ux %.8ux,\n"
533                 "\terrordata %.8ux %.8ux, srcline %ud, tsf %ux, time %ux\n",
534                 dump[1], dump[2],
535                 dump[4], dump[3], dump[6], dump[5],
536                 dump[7], dump[8], dump[9], dump[10], dump[11]);
537 }
538
539 static char*
540 eepromlock(Ctlr *ctlr)
541 {
542         int i, j;
543
544         for(i=0; i<100; i++){
545                 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | EepromLocked);
546                 for(j=0; j<100; j++){
547                         if(csr32r(ctlr, Cfg) & EepromLocked)
548                                 return 0;
549                         delay(10);
550                 }
551         }
552         return "eepromlock: timeout";
553 }
554 static void
555 eepromunlock(Ctlr *ctlr)
556 {
557         csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) & ~EepromLocked);
558 }
559 static char*
560 eepromread(Ctlr *ctlr, void *data, int count, uint off)
561 {
562         uchar *out = data;
563         u32int w, s;
564         int i;
565
566         w = 0;
567         off += ctlr->eeprom.off;
568         for(; count > 0; count -= 2, off++){
569                 csr32w(ctlr, EepromIo, off << 2);
570                 for(i=0; i<10; i++){
571                         w = csr32r(ctlr, EepromIo);
572                         if(w & 1)
573                                 break;
574                         delay(5);
575                 }
576                 if(i == 10)
577                         return "eepromread: timeout";
578                 if(ctlr->eeprom.otp){
579                         s = csr32r(ctlr, OtpromGp);
580                         if(s & EccUncorrStts)
581                                 return "eepromread: otprom ecc error";
582                         if(s & EccCorrStts)
583                                 csr32w(ctlr, OtpromGp, s);
584                 }
585                 *out++ = w >> 16;
586                 if(count > 1)
587                         *out++ = w >> 24;
588         }
589         return 0;
590 }
591
592 static char*
593 handover(Ctlr *ctlr)
594 {
595         int i;
596
597         csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
598         for(i=0; i<5; i++){
599                 if(csr32r(ctlr, Cfg) & NicReady)
600                         return 0;
601                 delay(10);
602         }
603         csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | Prepare);
604         for(i=0; i<15000; i++){
605                 if((csr32r(ctlr, Cfg) & PrepareDone) == 0)
606                         break;
607                 delay(10);
608         }
609         if(i >= 15000)
610                 return "handover: timeout";
611         csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
612         for(i=0; i<5; i++){
613                 if(csr32r(ctlr, Cfg) & NicReady)
614                         return 0;
615                 delay(10);
616         }
617         return "handover: timeout";
618 }
619
620 static char*
621 clockwait(Ctlr *ctlr)
622 {
623         int i;
624
625         /* Set "initialization complete" bit. */
626         csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone);
627         for(i=0; i<2500; i++){
628                 if(csr32r(ctlr, Gpc) & MacClockReady)
629                         return 0;
630                 delay(10);
631         }
632         return "clockwait: timeout";
633 }
634
635 static char*
636 poweron(Ctlr *ctlr)
637 {
638         int capoff;
639         char *err;
640
641         /* Disable L0s exit timer (NMI bug workaround). */
642         csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | DisL0Stimer);
643
644         /* Don't wait for ICH L0s (ICH bug workaround). */
645         csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | L1AnoL0Srx);
646
647         /* Set FH wait threshold to max (HW bug under stress workaround). */
648         csr32w(ctlr, Dbghpetmem, csr32r(ctlr, Dbghpetmem) | 0xffff0000);
649
650         /* Enable HAP INTA to move adapter from L1a to L0s. */
651         csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | HapwakeL1A);
652
653         capoff = pcicap(ctlr->pdev, PciCapPCIe);
654         if(capoff != -1){
655                 /* Workaround for HW instability in PCIe L0->L0s->L1 transition. */
656                 if(pcicfgr16(ctlr->pdev, capoff + 0x10) & 0x2)  /* LCSR -> L1 Entry enabled. */
657                         csr32w(ctlr, Gio, csr32r(ctlr, Gio) | EnaL0S);
658                 else
659                         csr32w(ctlr, Gio, csr32r(ctlr, Gio) & ~EnaL0S);
660         }
661
662         if(ctlr->type != Type4965 && ctlr->type <= Type1000)
663                 csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | 0x00880300);
664
665         /* Wait for clock stabilization before accessing prph. */
666         if((err = clockwait(ctlr)) != nil)
667                 return err;
668
669         if((err = niclock(ctlr)) != nil)
670                 return err;
671
672         /* Enable DMA and BSM (Bootstrap State Machine). */
673         if(ctlr->type == Type4965)
674                 prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt);
675         else
676                 prphwrite(ctlr, ApmgClkEna, DmaClkRqt);
677         delay(20);
678
679         /* Disable L1-Active. */
680         prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11));
681
682         nicunlock(ctlr);
683
684         ctlr->power = 1;
685
686         return 0;
687 }
688
689 static void
690 poweroff(Ctlr *ctlr)
691 {
692         int i, j;
693
694         csr32w(ctlr, Reset, 1);
695
696         /* Disable interrupts */
697         ctlr->ie = 0;
698         csr32w(ctlr, Imr, 0);
699         csr32w(ctlr, Isr, ~0);
700         csr32w(ctlr, FhIsr, ~0);
701
702         /* Stop scheduler */
703         if(ctlr->type != Type4965)
704                 prphwrite(ctlr, SchedTxFact5000, 0);
705         else
706                 prphwrite(ctlr, SchedTxFact4965, 0);
707
708         /* Stop TX ring */
709         if(niclock(ctlr) == nil){
710                 for(i = (ctlr->type != Type4965) ? 7 : 6; i >= 0; i--){
711                         csr32w(ctlr, FhTxConfig + i*32, 0);
712                         for(j = 0; j < 200; j++){
713                                 if(csr32r(ctlr, FhTxStatus) & (0x10000<<i))
714                                         break;
715                                 delay(10);
716                         }
717                 }
718                 nicunlock(ctlr);
719         }
720
721         /* Stop RX ring */
722         if(niclock(ctlr) == nil){
723                 csr32w(ctlr, FhRxConfig, 0);
724                 for(j = 0; j < 200; j++){
725                         if(csr32r(ctlr, FhRxStatus) & 0x1000000)
726                                 break;
727                         delay(10);
728                 }
729                 nicunlock(ctlr);
730         }
731
732         /* Disable DMA */
733         if(niclock(ctlr) == nil){
734                 prphwrite(ctlr, ApmgClkDis, DmaClkRqt);
735                 nicunlock(ctlr);
736         }
737         delay(5);
738
739         /* Stop busmaster DMA activity. */
740         csr32w(ctlr, Reset, csr32r(ctlr, Reset) | (1<<9));
741         for(j = 0; j < 100; j++){
742                 if(csr32r(ctlr, Reset) & (1<<8))
743                         break;
744                 delay(10);
745         }
746
747         /* Reset the entire device. */
748         csr32w(ctlr, Reset, csr32r(ctlr, Reset) | (1<<7));
749         delay(10);
750
751         /* Clear "initialization complete" bit. */
752         csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~InitDone);
753
754         ctlr->power = 0;
755 }
756
757 static char*
758 rominit(Ctlr *ctlr)
759 {
760         uint prev, last;
761         uchar buf[2];
762         char *err;
763         int i;
764
765         ctlr->eeprom.otp = 0;
766         ctlr->eeprom.off = 0;
767         if(ctlr->type < Type1000 || (csr32r(ctlr, OtpromGp) & DevSelOtp) == 0)
768                 return nil;
769
770         /* Wait for clock stabilization before accessing prph. */
771         if((err = clockwait(ctlr)) != nil)
772                 return err;
773
774         if((err = niclock(ctlr)) != nil)
775                 return err;
776         prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | ResetReq);
777         delay(5);
778         prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) & ~ResetReq);
779         nicunlock(ctlr);
780
781         /* Set auto clock gate disable bit for HW with OTP shadow RAM. */
782         if(ctlr->type != Type1000)
783                 csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31));
784
785         csr32w(ctlr, EepromGp, csr32r(ctlr, EepromGp) & ~0x00000180);
786
787         /* Clear ECC status. */
788         csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) | (EccCorrStts | EccUncorrStts));
789
790         ctlr->eeprom.otp = 1;
791         if(ctlr->type != Type1000)
792                 return nil;
793
794         /* Switch to absolute addressing mode. */
795         csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) & ~RelativeAccess);
796
797         /*
798          * Find the block before last block (contains the EEPROM image)
799          * for HW without OTP shadow RAM.
800          */
801         prev = last = 0;
802         for(i=0; i<3; i++){
803                 if((err = eepromread(ctlr, buf, 2, last)) != nil)
804                         return err;
805                 if(get16(buf) == 0)
806                         break;
807                 prev = last;
808                 last = get16(buf);
809         }
810         if(i == 0 || i >= 3)
811                 return "rominit: missing eeprom image";
812
813         ctlr->eeprom.off = prev+1;
814         return nil;
815 }
816
817 static int
818 iwlinit(Ether *edev)
819 {
820         Ctlr *ctlr;
821         char *err;
822         uchar b[4];
823         uint u, caloff, regoff;
824
825         ctlr = edev->ctlr;
826
827         /* Clear device-specific "PCI retry timeout" register (41h). */
828         if(pcicfgr8(ctlr->pdev, 0x41) != 0)
829                 pcicfgw8(ctlr->pdev, 0x41, 0);
830
831         /* Clear interrupt disable bit. Hardware bug workaround. */
832         if(ctlr->pdev->pcr & 0x400){
833                 ctlr->pdev->pcr &= ~0x400;
834                 pcicfgw16(ctlr->pdev, PciPCR, ctlr->pdev->pcr);
835         }
836
837         ctlr->type = (csr32r(ctlr, Rev) >> 4) & 0x1F;
838         if(fwname[ctlr->type] == nil){
839                 print("iwl: unsupported controller type %d\n", ctlr->type);
840                 return -1;
841         }
842
843         if((err = handover(ctlr)) != nil)
844                 goto Err;
845         if((err = poweron(ctlr)) != nil)
846                 goto Err;
847         if((csr32r(ctlr, EepromGp) & 0x7) == 0){
848                 err = "bad rom signature";
849                 goto Err;
850         }
851         if((err = eepromlock(ctlr)) != nil)
852                 goto Err;
853         if((err = rominit(ctlr)) != nil)
854                 goto Err2;
855         if((err = eepromread(ctlr, edev->ea, sizeof(edev->ea), 0x15)) != nil){
856                 eepromunlock(ctlr);
857                 goto Err;
858         }
859         if((err = eepromread(ctlr, b, 2, 0x048)) != nil){
860         Err2:
861                 eepromunlock(ctlr);
862                 goto Err;
863         }
864         u = get16(b);
865         ctlr->rfcfg.type = u & 3;       u >>= 2;
866         ctlr->rfcfg.step = u & 3;       u >>= 2;
867         ctlr->rfcfg.dash = u & 3;       u >>= 4;
868         ctlr->rfcfg.txantmask = u & 15; u >>= 4;
869         ctlr->rfcfg.rxantmask = u & 15;
870         if((err = eepromread(ctlr, b, 2, 0x66)) != nil)
871                 goto Err2;
872         regoff = get16(b);
873         if((err = eepromread(ctlr, b, 4, regoff+1)) != nil)
874                 goto Err2;
875         strncpy(ctlr->eeprom.regdom, (char*)b, 4);
876         ctlr->eeprom.regdom[4] = 0;
877         if((err = eepromread(ctlr, b, 2, 0x67)) != nil)
878                 goto Err2;
879         caloff = get16(b);
880         if((err = eepromread(ctlr, b, 4, caloff)) != nil)
881                 goto Err2;
882         ctlr->eeprom.version = b[0];
883         ctlr->eeprom.type = b[1];
884         ctlr->eeprom.volt = get16(b+2);
885
886         ctlr->eeprom.temp = 0;
887         ctlr->eeprom.rawtemp = 0;
888         if(ctlr->type == Type2030 || ctlr->type == Type2000){
889                 if((err = eepromread(ctlr, b, 2, caloff + 0x12a)) != nil)
890                         goto Err2;
891                 ctlr->eeprom.temp = get16(b);
892                 if((err = eepromread(ctlr, b, 2, caloff + 0x12b)) != nil)
893                         goto Err2;
894                 ctlr->eeprom.rawtemp = get16(b);
895         }
896
897         if(ctlr->type != Type4965 && ctlr->type != Type5150){
898                 if((err = eepromread(ctlr, b, 4, caloff + 0x128)) != nil)
899                         goto Err2;
900                 ctlr->eeprom.crystal = get32(b);
901         }
902         eepromunlock(ctlr);
903
904         switch(ctlr->type){
905         case Type4965:
906                 ctlr->rfcfg.txantmask = 3;
907                 ctlr->rfcfg.rxantmask = 7;
908                 break;
909         case Type5100:
910                 ctlr->rfcfg.txantmask = 2;
911                 ctlr->rfcfg.rxantmask = 3;
912                 break;
913         case Type6000:
914                 if(ctlr->pdev->did == 0x422c || ctlr->pdev->did == 0x4230){
915                         ctlr->rfcfg.txantmask = 6;
916                         ctlr->rfcfg.rxantmask = 6;
917                 }
918                 break;
919         }
920         poweroff(ctlr);
921         return 0;
922 Err:
923         print("iwlinit: %s\n", err);
924         poweroff(ctlr);
925         return -1;
926 }
927
928 static char*
929 crackfw(FWImage *i, uchar *data, uint size, int alt)
930 {
931         uchar *p, *e;
932         FWSect *s;
933
934         memset(i, 0, sizeof(*i));
935         if(size < 4){
936 Tooshort:
937                 return "firmware image too short";
938         }
939         p = data;
940         e = p + size;
941         i->rev = get32(p); p += 4;
942         if(i->rev == 0){
943                 uvlong altmask;
944
945                 if(size < (4+64+4+4+8))
946                         goto Tooshort;
947                 if(memcmp(p, "IWL\n", 4) != 0)
948                         return "bad firmware signature";
949                 p += 4;
950                 strncpy(i->descr, (char*)p, 64);
951                 i->descr[64] = 0;
952                 p += 64;
953                 i->rev = get32(p); p += 4;
954                 i->build = get32(p); p += 4;
955                 altmask = get32(p); p += 4;
956                 altmask |= (uvlong)get32(p) << 32; p += 4;
957                 while(alt > 0 && (altmask & (1ULL<<alt)) == 0)
958                         alt--;
959                 while(p < e){
960                         FWSect dummy;
961
962                         if((p + 2+2+4) > e)
963                                 goto Tooshort;
964                         switch(get16(p)){
965                         case 1: s = &i->main.text; break;
966                         case 2: s = &i->main.data; break;
967                         case 3: s = &i->init.text; break;
968                         case 4: s = &i->init.data; break;
969                         case 5: s = &i->boot.text; break;
970                         default:s = &dummy;
971                         }
972                         p += 2;
973                         if(get16(p) != 0 && get16(p) != alt)
974                                 s = &dummy;
975                         p += 2;
976                         s->size = get32(p); p += 4;
977                         s->data = p;
978                         if((p + s->size) > e)
979                                 goto Tooshort;
980                         p += (s->size + 3) & ~3;
981                 }
982         } else {
983                 if(((i->rev>>8) & 0xFF) < 2)
984                         return "need firmware api >= 2";
985                 if(((i->rev>>8) & 0xFF) >= 3){
986                         i->build = get32(p); p += 4;
987                 }
988                 if((p + 5*4) > e)
989                         goto Tooshort;
990                 i->main.text.size = get32(p); p += 4;
991                 i->main.data.size = get32(p); p += 4;
992                 i->init.text.size = get32(p); p += 4;
993                 i->init.data.size = get32(p); p += 4;
994                 i->boot.text.size = get32(p); p += 4;
995                 i->main.text.data = p; p += i->main.text.size;
996                 i->main.data.data = p; p += i->main.data.size;
997                 i->init.text.data = p; p += i->init.text.size;
998                 i->init.data.data = p; p += i->init.data.size;
999                 i->boot.text.data = p; p += i->boot.text.size;
1000                 if(p > e)
1001                         goto Tooshort;
1002         }
1003         return 0;
1004 }
1005
1006 static FWImage*
1007 readfirmware(char *name)
1008 {
1009         uchar dirbuf[sizeof(Dir)+100], *data;
1010         char buf[128], *err;
1011         FWImage *fw;
1012         int n, r;
1013         Chan *c;
1014         Dir d;
1015
1016         if(!iseve())
1017                 error(Eperm);
1018         if(!waserror()){
1019                 snprint(buf, sizeof buf, "/boot/%s", name);
1020                 c = namec(buf, Aopen, OREAD, 0);
1021                 poperror();
1022         } else {
1023                 snprint(buf, sizeof buf, "/lib/firmware/%s", name);
1024                 c = namec(buf, Aopen, OREAD, 0);
1025         }
1026         if(waserror()){
1027                 cclose(c);
1028                 nexterror();
1029         }
1030         n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf);
1031         if(n <= 0)
1032                 error("can't stat firmware");
1033         convM2D(dirbuf, n, &d, nil);
1034         fw = smalloc(sizeof(*fw) + 16 + d.length);
1035         data = (uchar*)(fw+1);
1036         if(waserror()){
1037                 free(fw);
1038                 nexterror();
1039         }
1040         r = 0;
1041         while(r < d.length){
1042                 n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r);
1043                 if(n <= 0)
1044                         break;
1045                 r += n;
1046         }
1047         if((err = crackfw(fw, data, r, 1)) != nil)
1048                 error(err);
1049         poperror();
1050         poperror();
1051         cclose(c);
1052         return fw;
1053 }
1054
1055
1056 static int
1057 gotirq(void *arg)
1058 {
1059         Ctlr *ctlr = arg;
1060         return (ctlr->wait.m & ctlr->wait.w) != 0;
1061 }
1062
1063 static u32int
1064 irqwait(Ctlr *ctlr, u32int mask, int timeout)
1065 {
1066         u32int r;
1067
1068         ilock(ctlr);
1069         r = ctlr->wait.m & mask;
1070         if(r == 0){
1071                 ctlr->wait.w = mask;
1072                 iunlock(ctlr);
1073                 if(!waserror()){
1074                         tsleep(&ctlr->wait, gotirq, ctlr, timeout);
1075                         poperror();
1076                 }
1077                 ilock(ctlr);
1078                 ctlr->wait.w = 0;
1079                 r = ctlr->wait.m & mask;
1080         }
1081         ctlr->wait.m &= ~r;
1082         iunlock(ctlr);
1083         return r;
1084 }
1085
1086 static int
1087 rbplant(Ctlr *ctlr, int i)
1088 {
1089         Block *b;
1090
1091         b = iallocb(Rbufsize + 256);
1092         if(b == nil)
1093                 return -1;
1094         b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, 256);
1095         memset(b->rp, 0, Rdscsize);
1096         ctlr->rx.b[i] = b;
1097         ctlr->rx.p[i] = PCIWADDR(b->rp) >> 8;
1098         return 0;
1099 }
1100
1101 static char*
1102 initring(Ctlr *ctlr)
1103 {
1104         RXQ *rx;
1105         TXQ *tx;
1106         int i, q;
1107
1108         rx = &ctlr->rx;
1109         if(rx->b == nil)
1110                 rx->b = malloc(sizeof(Block*) * Nrx);
1111         if(rx->p == nil)
1112                 rx->p = mallocalign(sizeof(u32int) * Nrx, 256, 0, 0);
1113         if(rx->s == nil)
1114                 rx->s = mallocalign(Rstatsize, 16, 0, 0);
1115         if(rx->b == nil || rx->p == nil || rx->s == nil)
1116                 return "no memory for rx ring";
1117         memset(ctlr->rx.s, 0, Rstatsize);
1118         for(i=0; i<Nrx; i++){
1119                 rx->p[i] = 0;
1120                 if(rx->b[i] != nil){
1121                         freeb(rx->b[i]);
1122                         rx->b[i] = nil;
1123                 }
1124                 if(rbplant(ctlr, i) < 0)
1125                         return "no memory for rx descriptors";
1126         }
1127         rx->i = 0;
1128
1129         if(ctlr->sched.s == nil)
1130                 ctlr->sched.s = mallocalign(512 * nelem(ctlr->tx) * 2, 1024, 0, 0);
1131         if(ctlr->sched.s == nil)
1132                 return "no memory for sched buffer";
1133         memset(ctlr->sched.s, 0, 512 * nelem(ctlr->tx));
1134
1135         for(q=0; q<nelem(ctlr->tx); q++){
1136                 tx = &ctlr->tx[q];
1137                 if(tx->b == nil)
1138                         tx->b = malloc(sizeof(Block*) * Ntx);
1139                 if(tx->d == nil)
1140                         tx->d = mallocalign(Tdscsize * Ntx, 256, 0, 0);
1141                 if(tx->c == nil)
1142                         tx->c = mallocalign(Tcmdsize * Ntx, 4, 0, 0);
1143                 if(tx->b == nil || tx->d == nil || tx->c == nil)
1144                         return "no memory for tx ring";
1145                 memset(tx->d, 0, Tdscsize * Ntx);
1146                 memset(tx->c, 0, Tcmdsize * Ntx);
1147                 for(i=0; i<Ntx; i++){
1148                         if(tx->b[i] != nil){
1149                                 freeb(tx->b[i]);
1150                                 tx->b[i] = nil;
1151                         }
1152                 }
1153                 tx->i = 0;
1154                 tx->n = 0;
1155                 tx->lastcmd = 0;
1156         }
1157
1158         if(ctlr->kwpage == nil)
1159                 ctlr->kwpage = mallocalign(4096, 4096, 0, 0);
1160         if(ctlr->kwpage == nil)
1161                 return "no memory for kwpage";          
1162         memset(ctlr->kwpage, 0, 4096);
1163
1164         return nil;
1165 }
1166
1167 static char*
1168 reset(Ctlr *ctlr)
1169 {
1170         char *err;
1171         int i, q;
1172
1173         if(ctlr->power)
1174                 poweroff(ctlr);
1175         if((err = initring(ctlr)) != nil)
1176                 return err;
1177         if((err = poweron(ctlr)) != nil)
1178                 return err;
1179
1180         if((err = niclock(ctlr)) != nil)
1181                 return err;
1182         prphwrite(ctlr, ApmgPs, (prphread(ctlr, ApmgPs) & ~PwrSrcMask) | PwrSrcVMain);
1183         nicunlock(ctlr);
1184
1185         csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | RadioSi | MacSi);
1186
1187         if((err = niclock(ctlr)) != nil)
1188                 return err;
1189         if(ctlr->type != Type4965)
1190                 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | EarlyPwroffDis);
1191         if(ctlr->type == Type1000){
1192                 /*
1193                  * Select first Switching Voltage Regulator (1.32V) to
1194                  * solve a stability issue related to noisy DC2DC line
1195                  * in the silicon of 1000 Series.
1196                  */
1197                 prphwrite(ctlr, ApmgDigitalSvr, 
1198                         (prphread(ctlr, ApmgDigitalSvr) & ~(0xf<<5)) | (3<<5));
1199         }
1200         nicunlock(ctlr);
1201
1202         if((err = niclock(ctlr)) != nil)
1203                 return err;
1204         if((ctlr->type == Type6005 || ctlr->type == Type6050) && ctlr->eeprom.version == 6)
1205                 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvCalV6);
1206         if(ctlr->type == Type6005)
1207                 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrv1X2);
1208         if(ctlr->type == Type2030 || ctlr->type == Type2000)
1209                 csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvRadioIqInvert);
1210         nicunlock(ctlr);
1211
1212         if((err = niclock(ctlr)) != nil)
1213                 return err;
1214         csr32w(ctlr, FhRxConfig, 0);
1215         csr32w(ctlr, FhRxWptr, 0);
1216         csr32w(ctlr, FhRxBase, PCIWADDR(ctlr->rx.p) >> 8);
1217         csr32w(ctlr, FhStatusWptr, PCIWADDR(ctlr->rx.s) >> 4);
1218         csr32w(ctlr, FhRxConfig,
1219                 FhRxConfigEna | 
1220                 FhRxConfigIgnRxfEmpty |
1221                 FhRxConfigIrqDstHost | 
1222                 FhRxConfigSingleFrame |
1223                 (Nrxlog << FhRxConfigNrbdShift));
1224         csr32w(ctlr, FhRxWptr, (Nrx-1) & ~7);
1225         nicunlock(ctlr);
1226
1227         if((err = niclock(ctlr)) != nil)
1228                 return err;
1229         if(ctlr->type != Type4965)
1230                 prphwrite(ctlr, SchedTxFact5000, 0);
1231         else
1232                 prphwrite(ctlr, SchedTxFact4965, 0);
1233         csr32w(ctlr, FhKwAddr, PCIWADDR(ctlr->kwpage) >> 4);
1234         for(q = (ctlr->type != Type4965) ? 19 : 15; q >= 0; q--)
1235                 csr32w(ctlr, FhCbbcQueue + q*4, PCIWADDR(ctlr->tx[q].d) >> 8);
1236         nicunlock(ctlr);
1237
1238         for(i = (ctlr->type != Type4965) ? 7 : 6; i >= 0; i--)
1239                 csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna);
1240
1241         csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
1242         csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
1243
1244         ctlr->broken = 0;
1245         ctlr->wait.m = 0;
1246         ctlr->wait.w = 0;
1247
1248         ctlr->ie = Idefmask;
1249         csr32w(ctlr, Imr, ctlr->ie);
1250         csr32w(ctlr, Isr, ~0);
1251
1252         if(ctlr->type >= Type6000)
1253                 csr32w(ctlr, ShadowRegCtrl, csr32r(ctlr, ShadowRegCtrl) | 0x800fffff);
1254
1255         return nil;
1256 }
1257
1258 static char*
1259 sendbtcoexadv(Ctlr *ctlr)
1260 {
1261         static u32int btcoex3wire[12] = {
1262                 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
1263                 0xcc00ff28,     0x0000aaaa, 0xcc00aaaa, 0x0000aaaa,
1264                 0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,
1265         };
1266
1267         uchar c[Tcmdsize], *p;
1268         char *err;
1269         int i;
1270
1271         /* set BT config */
1272         memset(c, 0, sizeof(c));
1273         p = c;
1274
1275         if(ctlr->type == Type2030){
1276                 *p++ = 145; /* flags */
1277                 p++; /* lead time */
1278                 *p++ = 5; /* max kill */
1279                 *p++ = 1; /* bt3 t7 timer */
1280                 put32(p, 0xffff0000); /* kill ack */
1281                 p += 4;
1282                 put32(p, 0xffff0000); /* kill cts */
1283                 p += 4;
1284                 *p++ = 2; /* sample time */
1285                 *p++ = 0xc; /* bt3 t2 timer */
1286                 p += 2; /* bt4 reaction */
1287                 for (i = 0; i < nelem(btcoex3wire); i++){
1288                         put32(p, btcoex3wire[i]);
1289                         p += 4;
1290                 }
1291                 p += 2; /* bt4 decision */
1292                 put16(p, 0xff); /* valid */
1293                 p += 2;
1294                 put32(p, 0xf0); /* prio boost */
1295                 p += 4;
1296                 p++; /* reserved */
1297                 p++; /* tx prio boost */
1298                 p += 2; /* rx prio boost */
1299         }
1300         if((err = cmd(ctlr, 155, c, p-c)) != nil)
1301                 return err;
1302
1303         /* set BT priority */
1304         memset(c, 0, sizeof(c));
1305         p = c;
1306
1307         *p++ = 0x6; /* init1 */
1308         *p++ = 0x7; /* init2 */
1309         *p++ = 0x2; /* periodic low1 */
1310         *p++ = 0x3; /* periodic low2 */
1311         *p++ = 0x4; /* periodic high1 */
1312         *p++ = 0x5; /* periodic high2 */
1313         *p++ = 0x6; /* dtim */
1314         *p++ = 0x8; /* scan52 */
1315         *p++ = 0xa; /* scan24 */
1316         p += 7; /* reserved */
1317         if((err = cmd(ctlr, 204, c, p-c)) != nil)
1318                 return err;
1319
1320         /* force BT state machine change */
1321         memset(c, 0, sizeof(c));
1322         p = c;
1323
1324         *p++ = 1; /* open */
1325         *p++ = 1; /* type */
1326         p += 2; /* reserved */
1327         if((err = cmd(ctlr, 205, c, p-c)) != nil)
1328                 return err;
1329
1330         c[0] = 0; /* open */
1331         return cmd(ctlr, 205, c, p-c);
1332 }
1333
1334 static char*
1335 postboot(Ctlr *ctlr)
1336 {
1337         uint ctxoff, ctxlen, dramaddr;
1338         char *err;
1339         int i, q;
1340
1341         if((err = niclock(ctlr)) != nil)
1342                 return err;
1343
1344         if(ctlr->type != Type4965){
1345                 dramaddr = SchedDramAddr5000;
1346                 ctxoff = SchedCtxOff5000;
1347                 ctxlen = SchedCtxLen5000;
1348         } else {
1349                 dramaddr = SchedDramAddr4965;
1350                 ctxoff = SchedCtxOff4965;
1351                 ctxlen = SchedCtxLen4965;
1352         }
1353
1354         ctlr->sched.base = prphread(ctlr, SchedSramAddr);
1355         for(i=0; i < ctxlen; i += 4)
1356                 memwrite(ctlr, ctlr->sched.base + ctxoff + i, 0);
1357
1358         prphwrite(ctlr, dramaddr, PCIWADDR(ctlr->sched.s)>>10);
1359
1360         csr32w(ctlr, FhTxChicken, csr32r(ctlr, FhTxChicken) | 2);
1361
1362         if(ctlr->type != Type4965){
1363                 /* Enable chain mode for all queues, except command queue 4. */
1364                 prphwrite(ctlr, SchedQChainSel5000, 0xfffef);
1365                 prphwrite(ctlr, SchedAggrSel5000, 0);
1366
1367                 for(q=0; q<20; q++){
1368                         prphwrite(ctlr, SchedQueueRdptr5000 + q*4, 0);
1369                         csr32w(ctlr, HbusTargWptr, q << 8);
1370
1371                         memwrite(ctlr, ctlr->sched.base + ctxoff + q*8, 0);
1372                         /* Set scheduler window size and frame limit. */
1373                         memwrite(ctlr, ctlr->sched.base + ctxoff + q*8 + 4, 64<<16 | 64);
1374                 }
1375                 /* Enable interrupts for all our 20 queues. */
1376                 prphwrite(ctlr, SchedIntrMask5000, 0xfffff);
1377
1378                 /* Identify TX FIFO rings (0-7). */
1379                 prphwrite(ctlr, SchedTxFact5000, 0xff);
1380         } else {
1381                 /* Disable chain mode for all our 16 queues. */
1382                 prphwrite(ctlr, SchedQChainSel4965, 0);
1383
1384                 for(q=0; q<16; q++) {
1385                         prphwrite(ctlr, SchedQueueRdptr4965 + q*4, 0);
1386                         csr32w(ctlr, HbusTargWptr, q << 8);
1387
1388                         /* Set scheduler window size. */
1389                         memwrite(ctlr, ctlr->sched.base + ctxoff + q*8, 64);
1390                         /* Set scheduler window size and frame limit. */
1391                         memwrite(ctlr, ctlr->sched.base + ctxoff + q*8 + 4, 64<<16);
1392                 }
1393                 /* Enable interrupts for all our 16 queues. */
1394                 prphwrite(ctlr, SchedIntrMask4965, 0xffff);
1395
1396                 /* Identify TX FIFO rings (0-7). */
1397                 prphwrite(ctlr, SchedTxFact4965, 0xff);
1398         }
1399
1400         /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
1401         for(q=0; q<7; q++){
1402                 if(ctlr->type != Type4965){
1403                         static uchar qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
1404                         prphwrite(ctlr, SchedQueueStatus5000 + q*4, 0x00ff0018 | qid2fifo[q]);
1405                 } else {
1406                         static uchar qid2fifo[] = { 3, 2, 1, 0, 4, 5, 6 };
1407                         prphwrite(ctlr, SchedQueueStatus4965 + q*4, 0x0007fc01 | qid2fifo[q]<<1);
1408                 }
1409         }
1410         nicunlock(ctlr);
1411
1412         if(ctlr->type != Type4965){
1413                 uchar c[Tcmdsize];
1414
1415                 /* disable wimax coexistance */
1416                 memset(c, 0, sizeof(c));
1417                 if((err = cmd(ctlr, 90, c, 4+4*16)) != nil)
1418                         return err;
1419
1420                 if(ctlr->type != Type5150){
1421                         /* calibrate crystal */
1422                         memset(c, 0, sizeof(c));
1423                         c[0] = 15;      /* code */
1424                         c[1] = 0;       /* group */
1425                         c[2] = 1;       /* ngroup */
1426                         c[3] = 1;       /* isvalid */
1427                         c[4] = ctlr->eeprom.crystal;
1428                         c[5] = ctlr->eeprom.crystal>>16;
1429                         /* for some reason 8086:4238 needs a second try */
1430                         if(cmd(ctlr, 176, c, 8) != nil && (err = cmd(ctlr, 176, c, 8)) != nil)
1431                                 return err;
1432                 }
1433
1434                 if(ctlr->calib.done == 0){
1435                         /* query calibration (init firmware) */
1436                         memset(c, 0, sizeof(c));
1437                         put32(c + 0*(5*4) + 0, 0xffffffff);
1438                         put32(c + 0*(5*4) + 4, 0xffffffff);
1439                         put32(c + 0*(5*4) + 8, 0xffffffff);
1440                         put32(c + 2*(5*4) + 0, 0xffffffff);
1441                         if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil)
1442                                 return err;
1443
1444                         /* wait to collect calibration records */
1445                         if(irqwait(ctlr, Ierr, 2000))
1446                                 return "calibration failed";
1447
1448                         if(ctlr->calib.done == 0){
1449                                 print("iwl: no calibration results\n");
1450                                 ctlr->calib.done = 1;
1451                         }
1452                 } else {
1453                         static uchar cmds[] = {8, 9, 11, 17, 16};
1454
1455                         /* send calibration records (runtime firmware) */
1456                         for(q=0; q<nelem(cmds); q++){
1457                                 Block *b;
1458
1459                                 i = cmds[q];
1460                                 if(i == 8 && ctlr->type != Type5150 && ctlr->type != Type2030 &&
1461                                         ctlr->type != Type2000)
1462                                         continue;
1463                                 if(i == 17 && (ctlr->type >= Type6000 || ctlr->type == Type5150) &&
1464                                         ctlr->type != Type2030 && ctlr->type != Type2000)
1465                                         continue;
1466
1467                                 if((b = ctlr->calib.cmd[i]) == nil)
1468                                         continue;
1469                                 b = copyblock(b, BLEN(b));
1470                                 if((err = qcmd(ctlr, 4, 176, nil, 0, b)) != nil){
1471                                         freeb(b);
1472                                         return err;
1473                                 }
1474                                 if((err = flushq(ctlr, 4)) != nil)
1475                                         return err;
1476                         }
1477
1478                         /* temperature sensor offset */
1479                         switch (ctlr->type){
1480                         case Type6005:
1481                                 memset(c, 0, sizeof(c));
1482                                 c[0] = 18;
1483                                 c[1] = 0;
1484                                 c[2] = 1;
1485                                 c[3] = 1;
1486                                 put16(c + 4, 2700);
1487                                 if((err = cmd(ctlr, 176, c, 4+2+2)) != nil)
1488                                         return err;
1489                                 break;
1490
1491                         case Type2030:
1492                         case Type2000:
1493                                 memset(c, 0, sizeof(c));
1494                                 c[0] = 18;
1495                                 c[1] = 0;
1496                                 c[2] = 1;
1497                                 c[3] = 1;
1498                                 if(ctlr->eeprom.rawtemp != 0){
1499                                         put16(c + 4, ctlr->eeprom.temp);
1500                                         put16(c + 6, ctlr->eeprom.rawtemp);
1501                                 } else{
1502                                         put16(c + 4, 2700);
1503                                         put16(c + 6, 2700);
1504                                 }
1505                                 put16(c + 8, ctlr->eeprom.volt);
1506                                 if((err = cmd(ctlr, 176, c, 4+2+2+2+2)) != nil)
1507                                         return err;
1508                                 break;
1509                         }
1510
1511                         if(ctlr->type == Type6005 || ctlr->type == Type6050){
1512                                 /* runtime DC calibration */
1513                                 memset(c, 0, sizeof(c));
1514                                 put32(c + 0*(5*4) + 0, 0xffffffff);
1515                                 put32(c + 0*(5*4) + 4, 1<<1);
1516                                 if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil)
1517                                         return err;
1518                         }
1519
1520                         /* set tx antenna config */
1521                         put32(c, ctlr->rfcfg.txantmask & 7);
1522                         if((err = cmd(ctlr, 152, c, 4)) != nil)
1523                                 return err;
1524
1525                         if(ctlr->type == Type2030){
1526                                 if((err = sendbtcoexadv(ctlr)) != nil)
1527                                         return err;
1528                         }
1529                 }
1530         }
1531
1532         return nil;
1533 }
1534
1535 static char*
1536 loadfirmware1(Ctlr *ctlr, u32int dst, uchar *data, int size)
1537 {
1538         uchar *dma;
1539         char *err;
1540
1541         dma = mallocalign(size, 16, 0, 0);
1542         if(dma == nil)
1543                 return "no memory for dma";
1544         memmove(dma, data, size);
1545         coherence();
1546         if((err = niclock(ctlr)) != 0){
1547                 free(dma);
1548                 return err;
1549         }
1550         csr32w(ctlr, FhTxConfig + 9*32, 0);
1551         csr32w(ctlr, FhSramAddr + 9*4, dst);
1552         csr32w(ctlr, FhTfbdCtrl0 + 9*8, PCIWADDR(dma));
1553         csr32w(ctlr, FhTfbdCtrl1 + 9*8, size);
1554         csr32w(ctlr, FhTxBufStatus + 9*32,
1555                 (1<<FhTxBufStatusTbNumShift) |
1556                 (1<<FhTxBufStatusTbIdxShift) |
1557                 FhTxBufStatusTfbdValid);
1558         csr32w(ctlr, FhTxConfig + 9*32, FhTxConfigDmaEna | FhTxConfigCirqHostEndTfd);
1559         nicunlock(ctlr);
1560         if(irqwait(ctlr, Ifhtx|Ierr, 5000) != Ifhtx){
1561                 free(dma);
1562                 return "dma error / timeout";
1563         }
1564         free(dma);
1565         return 0;
1566 }
1567
1568 static char*
1569 boot(Ctlr *ctlr)
1570 {
1571         int i, n, size;
1572         uchar *p, *dma;
1573         FWImage *fw;
1574         char *err;
1575
1576         fw = ctlr->fw;
1577
1578         if(fw->boot.text.size == 0){
1579                 if(ctlr->calib.done == 0){
1580                         if((err = loadfirmware1(ctlr, 0x00000000, fw->init.text.data, fw->init.text.size)) != nil)
1581                                 return err;
1582                         if((err = loadfirmware1(ctlr, 0x00800000, fw->init.data.data, fw->init.data.size)) != nil)
1583                                 return err;
1584                         csr32w(ctlr, Reset, 0);
1585                         if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive)
1586                                 return "init firmware boot failed";
1587                         if((err = postboot(ctlr)) != nil)
1588                                 return err;
1589                         if((err = reset(ctlr)) != nil)
1590                                 return err;
1591                 }
1592                 if((err = loadfirmware1(ctlr, 0x00000000, fw->main.text.data, fw->main.text.size)) != nil)
1593                         return err;
1594                 if((err = loadfirmware1(ctlr, 0x00800000, fw->main.data.data, fw->main.data.size)) != nil)
1595                         return err;
1596                 csr32w(ctlr, Reset, 0);
1597                 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive)
1598                         return "main firmware boot failed";
1599                 return postboot(ctlr);
1600         }
1601
1602         size = ROUND(fw->init.data.size, 16) + ROUND(fw->init.text.size, 16);
1603         dma = mallocalign(size, 16, 0, 0);
1604         if(dma == nil)
1605                 return "no memory for dma";
1606
1607         if((err = niclock(ctlr)) != nil){
1608                 free(dma);
1609                 return err;
1610         }
1611
1612         p = dma;
1613         memmove(p, fw->init.data.data, fw->init.data.size);
1614         coherence();
1615         prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
1616         prphwrite(ctlr, BsmDramDataSize, fw->init.data.size);
1617         p += ROUND(fw->init.data.size, 16);
1618         memmove(p, fw->init.text.data, fw->init.text.size);
1619         coherence();
1620         prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
1621         prphwrite(ctlr, BsmDramTextSize, fw->init.text.size);
1622
1623         nicunlock(ctlr);
1624         if((err = niclock(ctlr)) != nil){
1625                 free(dma);
1626                 return err;
1627         }
1628
1629         p = fw->boot.text.data;
1630         n = fw->boot.text.size/4;
1631         for(i=0; i<n; i++, p += 4)
1632                 prphwrite(ctlr, BsmSramBase+i*4, get32(p));
1633
1634         prphwrite(ctlr, BsmWrMemSrc, 0);
1635         prphwrite(ctlr, BsmWrMemDst, 0);
1636         prphwrite(ctlr, BsmWrDwCount, n);
1637
1638         prphwrite(ctlr, BsmWrCtrl, 1<<31);
1639
1640         for(i=0; i<1000; i++){
1641                 if((prphread(ctlr, BsmWrCtrl) & (1<<31)) == 0)
1642                         break;
1643                 delay(10);
1644         }
1645         if(i == 1000){
1646                 nicunlock(ctlr);
1647                 free(dma);
1648                 return "bootcode timeout";
1649         }
1650
1651         prphwrite(ctlr, BsmWrCtrl, 1<<30);
1652         nicunlock(ctlr);
1653
1654         csr32w(ctlr, Reset, 0);
1655         if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
1656                 free(dma);
1657                 return "init firmware boot failed";
1658         }
1659         free(dma);
1660
1661         size = ROUND(fw->main.data.size, 16) + ROUND(fw->main.text.size, 16);
1662         dma = mallocalign(size, 16, 0, 0);
1663         if(dma == nil)
1664                 return "no memory for dma";
1665         if((err = niclock(ctlr)) != nil){
1666                 free(dma);
1667                 return err;
1668         }
1669         p = dma;
1670         memmove(p, fw->main.data.data, fw->main.data.size);
1671         coherence();
1672         prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
1673         prphwrite(ctlr, BsmDramDataSize, fw->main.data.size);
1674         p += ROUND(fw->main.data.size, 16);
1675         memmove(p, fw->main.text.data, fw->main.text.size);
1676         coherence();
1677         prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
1678         prphwrite(ctlr, BsmDramTextSize, fw->main.text.size | (1<<31));
1679         nicunlock(ctlr);
1680
1681         if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
1682                 free(dma);
1683                 return "main firmware boot failed";
1684         }
1685         free(dma);
1686         return postboot(ctlr);
1687 }
1688
1689 static int
1690 txqready(void *arg)
1691 {
1692         TXQ *q = arg;
1693         return q->n < Ntxqmax;
1694 }
1695
1696 static char*
1697 qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
1698 {
1699         uchar *d, *c;
1700         TXQ *q;
1701
1702         assert(qid < nelem(ctlr->tx));
1703         assert(size <= Tcmdsize-4);
1704
1705         ilock(ctlr);
1706         q = &ctlr->tx[qid];
1707         while(q->n >= Ntxqmax && !ctlr->broken){
1708                 iunlock(ctlr);
1709                 qlock(q);
1710                 if(!waserror()){
1711                         tsleep(q, txqready, q, 5);
1712                         poperror();
1713                 }
1714                 qunlock(q);
1715                 ilock(ctlr);
1716         }
1717         if(ctlr->broken){
1718                 iunlock(ctlr);
1719                 return "qcmd: broken";
1720         }
1721         q->n++;
1722
1723         q->lastcmd = code;
1724         q->b[q->i] = block;
1725         c = q->c + q->i * Tcmdsize;
1726         d = q->d + q->i * Tdscsize;
1727
1728         /* build command */
1729         c[0] = code;
1730         c[1] = 0;       /* flags */
1731         c[2] = q->i;
1732         c[3] = qid;
1733
1734         if(size > 0)
1735                 memmove(c+4, data, size);
1736
1737         size += 4;
1738
1739         /* build descriptor */
1740         *d++ = 0;
1741         *d++ = 0;
1742         *d++ = 0;
1743         *d++ = 1 + (block != nil); /* nsegs */
1744         put32(d, PCIWADDR(c));  d += 4;
1745         put16(d, size << 4); d += 2;
1746         if(block != nil){
1747                 size = BLEN(block);
1748                 put32(d, PCIWADDR(block->rp)); d += 4;
1749                 put16(d, size << 4);
1750         }
1751
1752         coherence();
1753
1754         q->i = (q->i+1) % Ntx;
1755         csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i);
1756
1757         iunlock(ctlr);
1758
1759         return nil;
1760 }
1761
1762 static int
1763 txqempty(void *arg)
1764 {
1765         TXQ *q = arg;
1766         return q->n == 0;
1767 }
1768
1769 static char*
1770 flushq(Ctlr *ctlr, uint qid)
1771 {
1772         TXQ *q;
1773         int i;
1774
1775         q = &ctlr->tx[qid];
1776         qlock(q);
1777         for(i = 0; i < 200 && !ctlr->broken; i++){
1778                 if(txqempty(q)){
1779                         qunlock(q);
1780                         return nil;
1781                 }
1782                 if(!waserror()){
1783                         tsleep(q, txqempty, q, 10);
1784                         poperror();
1785                 }
1786         }
1787         qunlock(q);
1788         if(ctlr->broken)
1789                 return "flushq: broken";
1790         return "flushq: timeout";
1791 }
1792
1793 static char*
1794 cmd(Ctlr *ctlr, uint code, uchar *data, int size)
1795 {
1796         char *err;
1797
1798         if(0) print("cmd %ud\n", code);
1799         if((err = qcmd(ctlr, 4, code, data, size, nil)) != nil)
1800                 return err;
1801         return flushq(ctlr, 4);
1802 }
1803
1804 static void
1805 setled(Ctlr *ctlr, int which, int on, int off)
1806 {
1807         uchar c[8];
1808
1809         csr32w(ctlr, Led, csr32r(ctlr, Led) & ~LedBsmCtrl);
1810
1811         memset(c, 0, sizeof(c));
1812         put32(c, 10000);
1813         c[4] = which;
1814         c[5] = on;
1815         c[6] = off;
1816         cmd(ctlr, 72, c, sizeof(c));
1817 }
1818
1819 static void
1820 addnode(Ctlr *ctlr, uchar id, uchar *addr)
1821 {
1822         uchar c[Tcmdsize], *p;
1823
1824         memset(p = c, 0, sizeof(c));
1825         *p++ = 0;       /* control (1 = update) */
1826         p += 3;         /* reserved */
1827         memmove(p, addr, 6);
1828         p += 6;
1829         p += 2;         /* reserved */
1830         *p++ = id;      /* node id */
1831         p++;            /* flags */
1832         p += 2;         /* reserved */
1833         p += 2;         /* kflags */
1834         p++;            /* tcs2 */
1835         p++;            /* reserved */
1836         p += 5*2;       /* ttak */
1837         p++;            /* kid */
1838         p++;            /* reserved */
1839         p += 16;        /* key */
1840         if(ctlr->type != Type4965){
1841                 p += 8;         /* tcs */
1842                 p += 8;         /* rxmic */
1843                 p += 8;         /* txmic */
1844         }
1845         p += 4;         /* htflags */
1846         p += 4;         /* mask */
1847         p += 2;         /* disable tid */
1848         p += 2;         /* reserved */
1849         p++;            /* add ba tid */
1850         p++;            /* del ba tid */
1851         p += 2;         /* add ba ssn */
1852         p += 4;         /* reserved */
1853         cmd(ctlr, 24, c, p - c);
1854 }
1855
1856 static void
1857 rxon(Ether *edev, Wnode *bss)
1858 {
1859         uchar c[Tcmdsize], *p;
1860         int filter, flags;
1861         Ctlr *ctlr;
1862         char *err;
1863
1864         ctlr = edev->ctlr;
1865         filter = FilterNoDecrypt | FilterMulticast | FilterBeacon;
1866         if(ctlr->prom){
1867                 filter |= FilterPromisc;
1868                 if(bss != nil)
1869                         ctlr->channel = bss->channel;
1870                 bss = nil;
1871         }
1872         flags = RFlagTSF | RFlagCTSToSelf | RFlag24Ghz | RFlagAuto;
1873         if(bss != nil){
1874                 if(bss->cap & (1<<5))
1875                         flags |= RFlagShPreamble;
1876                 if(bss->cap & (1<<10))
1877                         flags |= RFlagShSlot;
1878                 ctlr->channel = bss->channel;
1879                 memmove(ctlr->bssid, bss->bssid, Eaddrlen);
1880                 ctlr->aid = bss->aid;
1881                 if(ctlr->aid != 0){
1882                         filter |= FilterBSS;
1883                         filter &= ~FilterBeacon;
1884                         ctlr->bssnodeid = -1;
1885                 } else
1886                         ctlr->bcastnodeid = -1;
1887         } else {
1888                 memmove(ctlr->bssid, edev->bcast, Eaddrlen);
1889                 ctlr->aid = 0;
1890                 ctlr->bcastnodeid = -1;
1891                 ctlr->bssnodeid = -1;
1892         }
1893
1894         if(ctlr->aid != 0)
1895                 setled(ctlr, 2, 0, 1);          /* on when associated */
1896         else if(memcmp(ctlr->bssid, edev->bcast, Eaddrlen) != 0)
1897                 setled(ctlr, 2, 10, 10);        /* slow blink when connecting */
1898         else
1899                 setled(ctlr, 2, 5, 5);          /* fast blink when scanning */
1900
1901         if(ctlr->wifi->debug)
1902                 print("#l%d: rxon: bssid %E, aid %x, channel %d, filter %x, flags %x\n",
1903                         edev->ctlrno, ctlr->bssid, ctlr->aid, ctlr->channel, filter, flags);
1904
1905         memset(p = c, 0, sizeof(c));
1906         memmove(p, edev->ea, 6); p += 8;        /* myaddr */
1907         memmove(p, ctlr->bssid, 6); p += 8;     /* bssid */
1908         memmove(p, edev->ea, 6); p += 8;        /* wlap */
1909         *p++ = 3;                               /* mode (STA) */
1910         *p++ = 0;                               /* air (?) */
1911         /* rxchain */
1912         put16(p, ((ctlr->rfcfg.rxantmask & 7)<<1) | (2<<10) | (2<<12));
1913         p += 2;
1914         *p++ = 0xff;                            /* ofdm mask (not yet negotiated) */
1915         *p++ = 0x0f;                            /* cck mask (not yet negotiated) */
1916         put16(p, ctlr->aid & 0x3fff);
1917         p += 2;                                 /* aid */
1918         put32(p, flags);
1919         p += 4;
1920         put32(p, filter);
1921         p += 4;
1922         *p++ = ctlr->channel;
1923         p++;                                    /* reserved */
1924         *p++ = 0xff;                            /* ht single mask */
1925         *p++ = 0xff;                            /* ht dual mask */
1926         if(ctlr->type != Type4965){
1927                 *p++ = 0xff;                    /* ht triple mask */
1928                 p++;                            /* reserved */
1929                 put16(p, 0); p += 2;            /* acquisition */
1930                 p += 2;                         /* reserved */
1931         }
1932         if((err = cmd(ctlr, 16, c, p - c)) != nil){
1933                 print("rxon: %s\n", err);
1934                 return;
1935         }
1936
1937         if(ctlr->bcastnodeid == -1){
1938                 ctlr->bcastnodeid = (ctlr->type != Type4965) ? 15 : 31;
1939                 addnode(ctlr, ctlr->bcastnodeid, edev->bcast);
1940         }
1941         if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){
1942                 ctlr->bssnodeid = 0;
1943                 addnode(ctlr, ctlr->bssnodeid, bss->bssid);
1944         }
1945 }
1946
1947 static struct ratetab {
1948         uchar   rate;
1949         uchar   plcp;
1950         uchar   flags;
1951 } ratetab[] = {
1952         {   2,  10, RFlagCCK },
1953         {   4,  20, RFlagCCK },
1954         {  11,  55, RFlagCCK },
1955         {  22, 110, RFlagCCK },
1956
1957         {  12, 0xd, 0 },
1958         {  18, 0xf, 0 },
1959         {  24, 0x5, 0 },
1960         {  36, 0x7, 0 },
1961         {  48, 0x9, 0 },
1962         {  72, 0xb, 0 },
1963         {  96, 0x1, 0 },
1964         { 108, 0x3, 0 },
1965         { 120, 0x3, 0 }
1966 };
1967
1968 static uchar iwlrates[] = {
1969         0x80 | 2,
1970         0x80 | 4,
1971         0x80 | 11,
1972         0x80 | 22,
1973
1974         0x80 | 12,
1975         0x80 | 18,
1976         0x80 | 24,
1977         0x80 | 36,
1978         0x80 | 48,
1979         0x80 | 72,
1980         0x80 | 96,
1981         0x80 | 108,
1982         0x80 | 120,
1983
1984         0
1985 };
1986
1987 enum {
1988         TFlagNeedProtection     = 1<<0,
1989         TFlagNeedRTS            = 1<<1,
1990         TFlagNeedCTS            = 1<<2,
1991         TFlagNeedACK            = 1<<3,
1992         TFlagLinkq              = 1<<4,
1993         TFlagImmBa              = 1<<6,
1994         TFlagFullTxOp           = 1<<7,
1995         TFlagBtDis              = 1<<12,
1996         TFlagAutoSeq            = 1<<13,
1997         TFlagMoreFrag           = 1<<14,
1998         TFlagInsertTs           = 1<<16,
1999         TFlagNeedPadding        = 1<<20,
2000 };
2001
2002 static void
2003 transmit(Wifi *wifi, Wnode *wn, Block *b)
2004 {
2005         int flags, nodeid, rate, ant;
2006         uchar c[Tcmdsize], *p;
2007         Ether *edev;
2008         Ctlr *ctlr;
2009         Wifipkt *w;
2010         char *err;
2011
2012         edev = wifi->ether;
2013         ctlr = edev->ctlr;
2014
2015         qlock(ctlr);
2016         if(ctlr->attached == 0 || ctlr->broken){
2017                 qunlock(ctlr);
2018                 freeb(b);
2019                 return;
2020         }
2021
2022         if((wn->channel != ctlr->channel)
2023         || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0)))
2024                 rxon(edev, wn);
2025
2026         if(b == nil){
2027                 /* association note has no data to transmit */
2028                 qunlock(ctlr);
2029                 return;
2030         }
2031
2032         flags = 0;
2033         nodeid = ctlr->bcastnodeid;
2034         p = wn->minrate;
2035         w = (Wifipkt*)b->rp;
2036         if((w->a1[0] & 1) == 0){
2037                 flags |= TFlagNeedACK;
2038
2039                 if(BLEN(b) > 512-4)
2040                         flags |= TFlagNeedRTS;
2041
2042                 if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){
2043                         nodeid = ctlr->bssnodeid;
2044                         p = wn->actrate;
2045                 }
2046
2047                 if(flags & (TFlagNeedRTS|TFlagNeedCTS)){
2048                         if(ctlr->type != Type4965){
2049                                 flags &= ~(TFlagNeedRTS|TFlagNeedCTS);
2050                                 flags |= TFlagNeedProtection;
2051                         } else
2052                                 flags |= TFlagFullTxOp;
2053                 }
2054         }
2055         if(p >= wifi->rates)
2056                 rate = p - wifi->rates;
2057         else
2058                 rate = 0;
2059         qunlock(ctlr);
2060
2061         /* select first available antenna */
2062         ant = ctlr->rfcfg.txantmask & 7;
2063         ant |= (ant == 0);
2064         ant = ((ant - 1) & ant) ^ ant;
2065
2066         memset(p = c, 0, sizeof(c));
2067         put16(p, BLEN(b));
2068         p += 2;
2069         p += 2;         /* lnext */
2070         put32(p, flags);
2071         p += 4;
2072         put32(p, 0);
2073         p += 4;         /* scratch */
2074
2075         *p++ = ratetab[rate].plcp;
2076         *p++ = ratetab[rate].flags | (ant<<6);
2077
2078         p += 2;         /* xflags */
2079         *p++ = nodeid;
2080         *p++ = 0;       /* security */
2081         *p++ = 0;       /* linkq */
2082         p++;            /* reserved */
2083         p += 16;        /* key */
2084         p += 2;         /* fnext */
2085         p += 2;         /* reserved */
2086         put32(p, ~0);   /* lifetime */
2087         p += 4;
2088
2089         /* BUG: scratch ptr? not clear what this is for */
2090         put32(p, PCIWADDR(ctlr->kwpage));
2091         p += 5;
2092
2093         *p++ = 60;      /* rts ntries */
2094         *p++ = 15;      /* data ntries */
2095         *p++ = 0;       /* tid */
2096         put16(p, 0);    /* timeout */
2097         p += 2;
2098         p += 2;         /* txop */
2099         if((err = qcmd(ctlr, 0, 28, c, p - c, b)) != nil){
2100                 print("transmit: %s\n", err);
2101                 freeb(b);
2102         }
2103 }
2104
2105 static long
2106 iwlctl(Ether *edev, void *buf, long n)
2107 {
2108         Ctlr *ctlr;
2109
2110         ctlr = edev->ctlr;
2111         if(n >= 5 && memcmp(buf, "reset", 5) == 0){
2112                 ctlr->broken = 1;
2113                 return n;
2114         }
2115         if(ctlr->wifi)
2116                 return wifictl(ctlr->wifi, buf, n);
2117         return 0;
2118 }
2119
2120 static long
2121 iwlifstat(Ether *edev, void *buf, long n, ulong off)
2122 {
2123         Ctlr *ctlr;
2124
2125         ctlr = edev->ctlr;
2126         if(ctlr->wifi)
2127                 return wifistat(ctlr->wifi, buf, n, off);
2128         return 0;
2129 }
2130
2131 static void
2132 setoptions(Ether *edev)
2133 {
2134         Ctlr *ctlr;
2135         int i;
2136
2137         ctlr = edev->ctlr;
2138         for(i = 0; i < edev->nopt; i++)
2139                 wificfg(ctlr->wifi, edev->opt[i]);
2140 }
2141
2142 static void
2143 iwlpromiscuous(void *arg, int on)
2144 {
2145         Ether *edev;
2146         Ctlr *ctlr;
2147
2148         edev = arg;
2149         ctlr = edev->ctlr;
2150         qlock(ctlr);
2151         ctlr->prom = on;
2152         rxon(edev, ctlr->wifi->bss);
2153         qunlock(ctlr);
2154 }
2155
2156 static void
2157 iwlmulticast(void *, uchar*, int)
2158 {
2159 }
2160
2161 static void
2162 iwlrecover(void *arg)
2163 {
2164         Ether *edev;
2165         Ctlr *ctlr;
2166
2167         edev = arg;
2168         ctlr = edev->ctlr;
2169         while(waserror())
2170                 ;
2171         for(;;){
2172                 tsleep(&up->sleep, return0, 0, 4000);
2173
2174                 qlock(ctlr);
2175                 for(;;){
2176                         if(ctlr->broken == 0)
2177                                 break;
2178
2179                         if(ctlr->power)
2180                                 poweroff(ctlr);
2181
2182                         if((csr32r(ctlr, Gpc) & RfKill) == 0)
2183                                 break;
2184
2185                         if(reset(ctlr) != nil)
2186                                 break;
2187                         if(boot(ctlr) != nil)
2188                                 break;
2189
2190                         ctlr->bcastnodeid = -1;
2191                         ctlr->bssnodeid = -1;
2192                         ctlr->aid = 0;
2193                         rxon(edev, ctlr->wifi->bss);
2194                         break;
2195                 }
2196                 qunlock(ctlr);
2197         }
2198 }
2199
2200 static void
2201 iwlattach(Ether *edev)
2202 {
2203         FWImage *fw;
2204         Ctlr *ctlr;
2205         char *err;
2206
2207         ctlr = edev->ctlr;
2208         eqlock(ctlr);
2209         if(waserror()){
2210                 print("#l%d: %s\n", edev->ctlrno, up->errstr);
2211                 if(ctlr->power)
2212                         poweroff(ctlr);
2213                 qunlock(ctlr);
2214                 nexterror();
2215         }
2216         if(ctlr->attached == 0){
2217                 if((csr32r(ctlr, Gpc) & RfKill) == 0)
2218                         error("wifi disabled by switch");
2219
2220                 if(ctlr->wifi == nil){
2221                         qsetlimit(edev->oq, MaxQueue);
2222
2223                         ctlr->wifi = wifiattach(edev, transmit);
2224                         /* tested with 2230, it has transmit issues using higher bit rates */
2225                         if(ctlr->type != Type2030)
2226                                 ctlr->wifi->rates = iwlrates;
2227                 }
2228
2229                 if(ctlr->fw == nil){
2230                         char *fn = fwname[ctlr->type];
2231                         if(ctlr->type == Type6005){
2232                                 switch(ctlr->pdev->did){
2233                                 case 0x0082:    /* Centrino Advanced-N 6205 */
2234                                 case 0x0085:    /* Centrino Advanced-N 6205 */
2235                                         break;
2236                                 default:        /* Centrino Advanced-N 6030, 6235 */
2237                                         fn = "iwn-6030";
2238                                 }
2239                         }
2240                         fw = readfirmware(fn);
2241                         print("#l%d: firmware: %s, rev %ux, build %ud, size %ux+%ux+%ux+%ux+%ux\n",
2242                                 edev->ctlrno, fn,
2243                                 fw->rev, fw->build,
2244                                 fw->main.text.size, fw->main.data.size,
2245                                 fw->init.text.size, fw->init.data.size,
2246                                 fw->boot.text.size);
2247                         ctlr->fw = fw;
2248                 }
2249
2250                 if((err = reset(ctlr)) != nil)
2251                         error(err);
2252                 if((err = boot(ctlr)) != nil)
2253                         error(err);
2254
2255                 ctlr->bcastnodeid = -1;
2256                 ctlr->bssnodeid = -1;
2257                 ctlr->channel = 1;
2258                 ctlr->aid = 0;
2259
2260                 setoptions(edev);
2261
2262                 ctlr->attached = 1;
2263
2264                 kproc("iwlrecover", iwlrecover, edev);
2265         }
2266         qunlock(ctlr);
2267         poperror();
2268 }
2269
2270 static void
2271 receive(Ctlr *ctlr)
2272 {
2273         Block *b, *bb;
2274         uchar *d;
2275         RXQ *rx;
2276         TXQ *tx;
2277         uint hw;
2278
2279         rx = &ctlr->rx;
2280         if(ctlr->broken || rx->s == nil || rx->b == nil)
2281                 return;
2282
2283         bb = nil;
2284         for(hw = get16(rx->s) % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){
2285                 uchar type, flags, idx, qid;
2286                 u32int len;
2287
2288                 b = rx->b[rx->i];
2289                 if(b == nil)
2290                         continue;
2291
2292                 d = b->rp;
2293                 len = get32(d); d += 4;
2294                 type = *d++;
2295                 flags = *d++;
2296                 USED(flags);
2297                 idx = *d++;
2298                 qid = *d++;
2299
2300                 if(bb != nil){
2301                         freeb(bb);
2302                         bb = nil;
2303                 }
2304                 if((qid & 0x80) == 0 && qid < nelem(ctlr->tx)){
2305                         tx = &ctlr->tx[qid];
2306                         if(tx->n > 0){
2307                                 bb = tx->b[idx];
2308                                 tx->b[idx] = nil;
2309                                 tx->n--;
2310
2311                                 wakeup(tx);
2312                         }
2313                 }
2314
2315                 len &= 0x3fff;
2316                 if(len < 4 || type == 0)
2317                         continue;
2318
2319                 len -= 4;
2320                 switch(type){
2321                 case 1:         /* microcontroller ready */
2322                         setfwinfo(ctlr, d, len);
2323                         break;
2324                 case 24:        /* add node done */
2325                         break;
2326                 case 28:        /* tx done */
2327                         if(ctlr->type == Type4965){
2328                                 if(len <= 20 || d[20] == 1 || d[20] == 2)
2329                                         break;
2330                         } else {
2331                                 if(len <= 32 || d[32] == 1 || d[32] == 2)
2332                                         break;
2333                         }
2334                         wifitxfail(ctlr->wifi, bb);
2335                         break;
2336                 case 102:       /* calibration result (Type5000 only) */
2337                         if(len < 4)
2338                                 break;
2339                         idx = d[0];
2340                         if(idx >= nelem(ctlr->calib.cmd))
2341                                 break;
2342                         if(rbplant(ctlr, rx->i) < 0)
2343                                 break;
2344                         if(ctlr->calib.cmd[idx] != nil)
2345                                 freeb(ctlr->calib.cmd[idx]);
2346                         b->rp = d;
2347                         b->wp = d + len;
2348                         ctlr->calib.cmd[idx] = b;
2349                         continue;
2350                 case 103:       /* calibration done (Type5000 only) */
2351                         ctlr->calib.done = 1;
2352                         break;
2353                 case 130:       /* start scan */
2354                         break;
2355                 case 132:       /* stop scan */
2356                         break;
2357                 case 156:       /* rx statistics */
2358                         break;
2359                 case 157:       /* beacon statistics */
2360                         break;
2361                 case 161:       /* state changed */
2362                         break;
2363                 case 162:       /* beacon missed */
2364                         break;
2365                 case 192:       /* rx phy */
2366                         break;
2367                 case 195:       /* rx done */
2368                         if(d + 2 > b->lim)
2369                                 break;
2370                         d += d[1];
2371                         d += 56;
2372                 case 193:       /* mpdu rx done */
2373                         if(d + 4 > b->lim)
2374                                 break;
2375                         len = get16(d); d += 4;
2376                         if(d + len + 4 > b->lim)
2377                                 break;
2378                         if((get32(d + len) & 3) != 3)
2379                                 break;
2380                         if(ctlr->wifi == nil)
2381                                 break;
2382                         if(rbplant(ctlr, rx->i) < 0)
2383                                 break;
2384                         b->rp = d;
2385                         b->wp = d + len;
2386                         wifiiq(ctlr->wifi, b);
2387                         continue;
2388                 case 197:       /* rx compressed ba */
2389                         break;
2390                 }
2391         }
2392         csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7);
2393         if(bb != nil)
2394                 freeb(bb);
2395 }
2396
2397 static void
2398 iwlinterrupt(Ureg*, void *arg)
2399 {
2400         u32int isr, fhisr;
2401         Ether *edev;
2402         Ctlr *ctlr;
2403
2404         edev = arg;
2405         ctlr = edev->ctlr;
2406         ilock(ctlr);
2407         csr32w(ctlr, Imr, 0);
2408         isr = csr32r(ctlr, Isr);
2409         fhisr = csr32r(ctlr, FhIsr);
2410         if(isr == 0xffffffff || (isr & 0xfffffff0) == 0xa5a5a5a0){
2411                 iunlock(ctlr);
2412                 return;
2413         }
2414         if(isr == 0 && fhisr == 0)
2415                 goto done;
2416         csr32w(ctlr, Isr, isr);
2417         csr32w(ctlr, FhIsr, fhisr);
2418         if((isr & (Iswrx | Ifhrx | Irxperiodic)) || (fhisr & Ifhrx))
2419                 receive(ctlr);
2420         if(isr & Ierr){
2421                 ctlr->broken = 1;
2422                 print("#l%d: fatal firmware error\n", edev->ctlrno);
2423                 dumpctlr(ctlr);
2424         }
2425         ctlr->wait.m |= isr;
2426         if(ctlr->wait.m & ctlr->wait.w)
2427                 wakeup(&ctlr->wait);
2428 done:
2429         csr32w(ctlr, Imr, ctlr->ie);
2430         iunlock(ctlr);
2431 }
2432
2433 static void
2434 iwlshutdown(Ether *edev)
2435 {
2436         Ctlr *ctlr;
2437
2438         ctlr = edev->ctlr;
2439         if(ctlr->power)
2440                 poweroff(ctlr);
2441         ctlr->broken = 0;
2442 }
2443
2444 static Ctlr *iwlhead, *iwltail;
2445
2446 static void
2447 iwlpci(void)
2448 {
2449         Pcidev *pdev;
2450         
2451         pdev = nil;
2452         while(pdev = pcimatch(pdev, 0, 0)) {
2453                 Ctlr *ctlr;
2454                 void *mem;
2455                 
2456                 if(pdev->ccrb != 2 || pdev->ccru != 0x80)
2457                         continue;
2458                 if(pdev->vid != 0x8086)
2459                         continue;
2460
2461                 switch(pdev->did){
2462                 default:
2463                         continue;
2464                 case 0x0084:    /* WiFi Link 1000 */
2465                 case 0x4229:    /* WiFi Link 4965 */
2466                 case 0x4230:    /* WiFi Link 4965 */
2467                 case 0x4232:    /* Wifi Link 5100 */
2468                 case 0x4235:    /* Intel Corporation Ultimate N WiFi Link 5300 */
2469                 case 0x4236:    /* WiFi Link 5300 AGN */
2470                 case 0x4237:    /* Wifi Link 5100 AGN */
2471                 case 0x4239:    /* Centrino Advanced-N 6200 */
2472                 case 0x423d:    /* Wifi Link 5150 */
2473                 case 0x423b:    /* PRO/Wireless 5350 AGN */
2474                 case 0x0082:    /* Centrino Advanced-N 6205 */
2475                 case 0x0085:    /* Centrino Advanced-N 6205 */
2476                 case 0x422b:    /* Centrino Ultimate-N 6300 variant 1 */
2477                 case 0x4238:    /* Centrino Ultimate-N 6300 variant 2 */
2478                 case 0x08ae:    /* Centrino Wireless-N 100 */
2479                 case 0x0083:    /* Centrino Wireless-N 1000 */
2480                 case 0x0891:    /* Centrino Wireless-N 2200 */
2481                 case 0x0887:    /* Centrino Wireless-N 2230 */
2482                 case 0x0888:    /* Centrino Wireless-N 2230 */
2483                 case 0x0090:    /* Centrino Advanced-N 6030 */
2484                 case 0x0091:    /* Centrino Advanced-N 6030 */
2485                 case 0x088e:    /* Centrino Advanced-N 6235 */
2486                 case 0x088f:    /* Centrino Advanced-N 6235 */
2487                         break;
2488                 }
2489
2490                 ctlr = malloc(sizeof(Ctlr));
2491                 if(ctlr == nil) {
2492                         print("iwl: unable to alloc Ctlr\n");
2493                         continue;
2494                 }
2495                 ctlr->port = pdev->mem[0].bar & ~0x0F;
2496                 mem = vmap(pdev->mem[0].bar & ~0x0F, pdev->mem[0].size);
2497                 if(mem == nil) {
2498                         print("iwl: can't map %8.8luX\n", pdev->mem[0].bar);
2499                         free(ctlr);
2500                         continue;
2501                 }
2502                 ctlr->nic = mem;
2503                 ctlr->pdev = pdev;
2504
2505                 if(iwlhead != nil)
2506                         iwltail->link = ctlr;
2507                 else
2508                         iwlhead = ctlr;
2509                 iwltail = ctlr;
2510         }
2511 }
2512
2513 static int
2514 iwlpnp(Ether* edev)
2515 {
2516         Ctlr *ctlr;
2517         
2518         if(iwlhead == nil)
2519                 iwlpci();
2520 again:
2521         for(ctlr = iwlhead; ctlr != nil; ctlr = ctlr->link){
2522                 if(ctlr->active)
2523                         continue;
2524                 if(edev->port == 0 || edev->port == ctlr->port){
2525                         ctlr->active = 1;
2526                         break;
2527                 }
2528         }
2529
2530         if(ctlr == nil)
2531                 return -1;
2532
2533         edev->ctlr = ctlr;
2534         edev->port = ctlr->port;
2535         edev->irq = ctlr->pdev->intl;
2536         edev->tbdf = ctlr->pdev->tbdf;
2537         edev->arg = edev;
2538         edev->attach = iwlattach;
2539         edev->ifstat = iwlifstat;
2540         edev->ctl = iwlctl;
2541         edev->shutdown = iwlshutdown;
2542         edev->promiscuous = iwlpromiscuous;
2543         edev->multicast = iwlmulticast;
2544         edev->mbps = 54;
2545
2546         pcienable(ctlr->pdev);
2547         if(iwlinit(edev) < 0){
2548                 pcidisable(ctlr->pdev);
2549                 edev->ctlr = nil;
2550                 goto again;
2551         }
2552
2553         pcisetbme(ctlr->pdev);
2554         intrenable(edev->irq, iwlinterrupt, edev, edev->tbdf, edev->name);
2555         
2556         return 0;
2557 }
2558
2559 void
2560 etheriwllink(void)
2561 {
2562         addethercard("iwl", iwlpnp);
2563 }