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