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