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