]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/etheriwl.c
add Intel (R) WiFi Link 5100 AGN, vid/did: 8086/4237
[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
23         Ntxlog          = 8,
24         Ntx             = 1<<Ntxlog,
25         Nrxlog          = 8,
26         Nrx             = 1<<Nrxlog,
27
28         Rstatsize       = 16,
29         Rbufsize        = 4*1024,
30         Rdscsize        = 8,
31
32         Tbufsize        = 4*1024,
33         Tdscsize        = 128,
34         Tcmdsize        = 140,
35 };
36
37 /* registers */
38 enum {
39         Cfg             = 0x000,        /* config register */
40                 MacSi           = 1<<8,
41                 RadioSi         = 1<<9,
42                 EepromLocked    = 1<<21,
43                 NicReady        = 1<<22,
44                 HapwakeL1A      = 1<<23,
45                 PrepareDone     = 1<<25,
46                 Prepare         = 1<<27,
47
48         Isr             = 0x008,        /* interrupt status */
49         Imr             = 0x00c,        /* interrupt mask */
50                 Ialive          = 1<<0,
51                 Iwakeup         = 1<<1,
52                 Iswrx           = 1<<3,
53                 Ictreached      = 1<<6,
54                 Irftoggled      = 1<<7,
55                 Iswerr          = 1<<25,
56                 Isched          = 1<<26,
57                 Ifhtx           = 1<<27,
58                 Irxperiodic     = 1<<28,
59                 Ihwerr          = 1<<29,
60                 Ifhrx           = 1<<31,
61
62                 Ierr            = Iswerr | Ihwerr,
63                 Idefmask        = Ierr | Ifhtx | Ifhrx | Ialive | Iwakeup | Iswrx | Ictreached | Irftoggled,
64
65         FhIsr           = 0x010,        /* second interrupt status */
66
67         Reset           = 0x020,
68
69         Rev             = 0x028,        /* hardware revision */
70
71         EepromIo        = 0x02c,        /* EEPROM i/o register */
72         EepromGp        = 0x030,
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         Led             = 0x094,
91                 LedBsmCtrl      = 1<<5,
92                 LedOn           = 0x38,
93                 LedOff          = 0x78,
94
95         UcodeGp1Clr     = 0x05c,
96                 UcodeGp1RfKill          = 1<<1,
97                 UcodeGp1CmdBlocked      = 1<<2,
98                 UcodeGp1CtempStopRf     = 1<<3,
99
100         ShadowRegCtrl   = 0x0a8,
101
102         Giochicken      = 0x100,
103                 L1AnoL0Srx      = 1<<23,
104                 DisL0Stimer     = 1<<29,
105
106         AnaPll          = 0x20c,
107
108         Dbghpetmem      = 0x240,
109
110         MemRaddr        = 0x40c,
111         MemWaddr        = 0x410,
112         MemWdata        = 0x418,
113         MemRdata        = 0x41c,
114
115         PrphWaddr       = 0x444,
116         PrphRaddr       = 0x448,
117         PrphWdata       = 0x44c,
118         PrphRdata       = 0x450,
119
120         HbusTargWptr    = 0x460,
121 };
122
123 /*
124  * Flow-Handler registers.
125  */
126 enum {
127         FhTfbdCtrl0     = 0x1900,       // +q*8
128         FhTfbdCtrl1     = 0x1904,       // +q*8
129
130         FhKwAddr        = 0x197c,
131
132         FhSramAddr      = 0x19a4,       // +q*4
133         FhCbbcQueue     = 0x19d0,       // +q*4
134         FhStatusWptr    = 0x1bc0,
135         FhRxBase        = 0x1bc4,
136         FhRxWptr        = 0x1bc8,
137         FhRxConfig      = 0x1c00,
138                 FhRxConfigEna           = 1<<31,
139                 FhRxConfigRbSize8K      = 1<<16,
140                 FhRxConfigSingleFrame   = 1<<15,
141                 FhRxConfigIrqDstHost    = 1<<12,
142                 FhRxConfigIgnRxfEmpty   = 1<<2,
143
144                 FhRxConfigNrbdShift     = 20,
145                 FhRxConfigRbTimeoutShift= 4,
146
147         FhRxStatus      = 0x1c44,
148
149         FhTxConfig      = 0x1d00,       // +q*32
150                 FhTxConfigDmaCreditEna  = 1<<3,
151                 FhTxConfigDmaEna        = 1<<31,
152                 FhTxConfigCirqHostEndTfd= 1<<20,
153
154         FhTxBufStatus   = 0x1d08,       // +q*32
155                 FhTxBufStatusTbNumShift = 20,
156                 FhTxBufStatusTbIdxShift = 12,
157                 FhTxBufStatusTfbdValid  = 3,
158
159         FhTxChicken     = 0x1e98,
160         FhTxStatus      = 0x1eb0,
161 };
162
163 /*
164  * NIC internal memory offsets.
165  */
166 enum {
167         ApmgClkCtrl     = 0x3000,
168         ApmgClkEna      = 0x3004,
169         ApmgClkDis      = 0x3008,
170                 DmaClkRqt       = 1<<9,
171                 BsmClkRqt       = 1<<11,
172
173         ApmgPs          = 0x300c,
174                 EarlyPwroffDis  = 1<<22,
175                 PwrSrcVMain     = 0<<24,
176                 PwrSrcVAux      = 2<<24,
177                 PwrSrcMask      = 3<<24,
178                 ResetReq        = 1<<26,
179
180         ApmgDigitalSvr  = 0x3058,
181         ApmgAnalogSvr   = 0x306c,
182         ApmgPciStt      = 0x3010,
183         BsmWrCtrl       = 0x3400,
184         BsmWrMemSrc     = 0x3404,
185         BsmWrMemDst     = 0x3408,
186         BsmWrDwCount    = 0x340c,
187         BsmDramTextAddr = 0x3490,
188         BsmDramTextSize = 0x3494,
189         BsmDramDataAddr = 0x3498,
190         BsmDramDataSize = 0x349c,
191         BsmSramBase     = 0x3800,
192 };
193
194 /*
195  * TX scheduler registers.
196  */
197 enum {
198         SchedBase               = 0xa02c00,
199         SchedSramAddr           = SchedBase,
200         SchedDramAddr5000       = SchedBase+0x008,
201         SchedDramAddr4965       = SchedBase+0x010,
202         SchedTxFact5000         = SchedBase+0x010,
203         SchedTxFact4965         = SchedBase+0x01c,
204         SchedQueueRdptr4965     = SchedBase+0x064,      // +q*4
205         SchedQueueRdptr5000     = SchedBase+0x068,      // +q*4
206         SchedQChainSel4965      = SchedBase+0x0d0,
207         SchedIntrMask4965       = SchedBase+0x0e4,
208         SchedQChainSel5000      = SchedBase+0x0e8,
209         SchedQueueStatus4965    = SchedBase+0x104,      // +q*4
210         SchedIntrMask5000       = SchedBase+0x108,
211         SchedQueueStatus5000    = SchedBase+0x10c,      // +q*4
212         SchedAggrSel5000        = SchedBase+0x248,
213 };
214
215 enum {
216         SchedCtxOff4965         = 0x380,
217         SchedCtxLen4965         = 416,
218         SchedTransTblOff4965    = 0x500,
219
220         SchedCtxOff5000         = 0x600,
221         SchedCtxLen5000         = 512,
222         SchedTransTblOff5000    = 0x7e0,
223 };
224
225 typedef struct FWInfo FWInfo;
226 typedef struct FWImage FWImage;
227 typedef struct FWSect FWSect;
228
229 typedef struct TXQ TXQ;
230 typedef struct RXQ RXQ;
231
232 typedef struct Ctlr Ctlr;
233
234 typedef struct Ctlrtype Ctlrtype;
235
236 struct FWSect
237 {
238         uchar   *data;
239         uint    size;
240 };
241
242 struct FWImage
243 {
244         struct {
245                 FWSect  text;
246                 FWSect  data;
247         } init, main, boot;
248
249         uint    rev;
250         uint    build;
251         char    descr[64+1];
252         uchar   data[];
253 };
254
255 struct FWInfo
256 {
257         uchar   major;
258         uchar   minjor;
259         uchar   type;
260         uchar   subtype;
261
262         u32int  logptr;
263         u32int  errptr;
264         u32int  tstamp;
265         u32int  valid;
266 };
267
268 struct TXQ
269 {
270         uint    n;
271         uint    i;
272         Block   **b;
273         uchar   *d;
274         uchar   *c;
275
276         Rendez;
277         QLock;
278 };
279
280 struct RXQ
281 {
282         uint    i;
283         Block   **b;
284         u32int  *p;
285         uchar   *s;
286 };
287
288 struct Ctlr {
289         Lock;
290         QLock;
291
292         Ctlr *link;
293         Pcidev *pdev;
294         Wifi *wifi;
295
296         int type;
297         int port;
298         int active;
299         int attached;
300
301         u32int ie;
302
303         u32int *nic;
304         uchar *kwpage;
305
306         int channel;
307
308         RXQ rx;
309         TXQ tx[20];
310
311         struct {
312                 Rendez;
313                 u32int  m;
314                 u32int  w;
315                 u32int  r;
316         } wait;
317
318         struct {
319                 uchar   type;
320                 uchar   step;
321                 uchar   dash;
322                 uchar   txantmask;
323                 uchar   rxantmask;
324         } rfcfg;
325
326         struct {
327                 u32int  crystal;
328         } eeprom;
329
330         struct {
331                 u32int  base;
332                 uchar   *s;
333         } sched;
334
335         FWInfo fwinfo;
336         FWImage *fw;
337 };
338
339 /* controller types */
340 enum {
341         Type4965        = 0,
342         Type5300        = 2,
343         Type5350        = 3,
344         Type5150        = 4,
345         Type5100        = 5,
346         Type1000        = 6,
347         Type6000        = 7,
348         Type6050        = 8,
349         Type6005        = 11,
350 };
351
352 struct Ctlrtype
353 {
354         char    *fwname;
355 };
356
357 static Ctlrtype ctlrtype[16] = {
358         [Type4965] {
359                 .fwname = "iwn-4965",
360         },
361         [Type5300] {
362                 .fwname = "iwn-5000",
363         },
364         [Type5350] {
365                 .fwname = "iwn-5000",
366         },
367         [Type5150] {
368                 .fwname = "iwn-5150",
369         },
370         [Type5100] {
371                 .fwname = "iwn-5000",
372         },
373         [Type1000] {
374                 .fwname = "iwn-1000",
375         },
376         [Type6000] {
377                 .fwname = "iwn-6000",
378         },
379         [Type6050] {
380                 .fwname = "iwn-6050",
381         },
382         [Type6005] {
383                 .fwname = "iwn-6005",
384         },
385 };
386
387 #define csr32r(c, r)    (*((c)->nic+((r)/4)))
388 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
389
390 static uint
391 get16(uchar *p){
392         return *((u16int*)p);
393 }
394 static uint
395 get32(uchar *p){
396         return *((u32int*)p);
397 }
398 static void
399 put32(uchar *p, uint v){
400         *((u32int*)p) = v;
401 }
402 static void
403 put16(uchar *p, uint v){
404         *((u16int*)p) = v;
405 };
406
407 static char*
408 niclock(Ctlr *ctlr)
409 {
410         int i;
411
412         csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq);
413         for(i=0; i<1000; i++){
414                 if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna)
415                         return 0;
416                 delay(10);
417         }
418         return "niclock: timeout";
419 }
420
421 static void
422 nicunlock(Ctlr *ctlr)
423 {
424         csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq);
425 }
426
427 static u32int
428 prphread(Ctlr *ctlr, uint off)
429 {
430         csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off);
431         coherence();
432         return csr32r(ctlr, PrphRdata);
433 }
434 static void
435 prphwrite(Ctlr *ctlr, uint off, u32int data)
436 {
437         csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off);
438         coherence();
439         csr32w(ctlr, PrphWdata, data);
440 }
441
442 static u32int
443 memread(Ctlr *ctlr, uint off)
444 {
445         csr32w(ctlr, MemRaddr, off);
446         coherence();
447         return csr32r(ctlr, MemRdata);
448 }
449 static void
450 memwrite(Ctlr *ctlr, uint off, u32int data)
451 {
452         csr32w(ctlr, MemWaddr, off);
453         coherence();
454         csr32w(ctlr, MemWdata, data);
455 }
456
457 static void
458 setfwinfo(Ctlr *ctlr, uchar *d, int len)
459 {
460         FWInfo *i;
461
462         if(len < 32)
463                 return;
464         i = &ctlr->fwinfo;
465         i->minjor = *d++;
466         i->major = *d++;
467         d += 2+8;
468         i->type = *d++;
469         i->subtype = *d++;
470         d += 2;
471         i->logptr = get32(d); d += 4;
472         i->errptr = get32(d); d += 4;
473         i->tstamp = get32(d); d += 4;
474         i->valid = get32(d);
475 };
476
477 static void
478 dumpctlr(Ctlr *ctlr)
479 {
480         u32int dump[13];
481         int i;
482
483         if(ctlr->fwinfo.errptr == 0){
484                 print("no error pointer\n");
485                 return;
486         }
487         for(i=0; i<nelem(dump); i++)
488                 dump[i] = memread(ctlr, ctlr->fwinfo.errptr + i*4);
489         print(  "error:\tid %ux, pc %ux,\n"
490                 "\tbranchlink %.8ux %.8ux, interruptlink %.8ux %.8ux,\n"
491                 "\terrordata %.8ux %.8ux, srcline %ud, tsf %ux, time %ux\n",
492                 dump[1], dump[2],
493                 dump[4], dump[3], dump[6], dump[5],
494                 dump[7], dump[8], dump[9], dump[10], dump[11]);
495 }
496
497 static char*
498 eepromlock(Ctlr *ctlr)
499 {
500         int i, j;
501
502         for(i=0; i<100; i++){
503                 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | EepromLocked);
504                 for(j=0; j<100; j++){
505                         if(csr32r(ctlr, Cfg) & EepromLocked)
506                                 return 0;
507                         delay(10);
508                 }
509         }
510         return "eepromlock: timeout";
511 }
512 static void
513 eepromunlock(Ctlr *ctlr)
514 {
515         csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) & ~EepromLocked);
516 }
517 static char*
518 eepromread(Ctlr *ctlr, void *data, int count, uint off)
519 {
520         uchar *out = data;
521         u32int w;
522         int i;
523
524         w = 0;
525         for(; count > 0; count -= 2, off++){
526                 csr32w(ctlr, EepromIo, off << 2);
527                 for(i=0; i<10; i++){
528                         w = csr32r(ctlr, EepromIo);
529                         if(w & 1)
530                                 break;
531                         delay(5);
532                 }
533                 if(i == 10)
534                         return "eepromread: timeout";
535                 *out++ = w >> 16;
536                 if(count > 1)
537                         *out++ = w >> 24;
538         }
539         return 0;
540 }
541
542 static char*
543 handover(Ctlr *ctlr)
544 {
545         int i;
546
547         csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
548         for(i=0; i<5; i++){
549                 if(csr32r(ctlr, Cfg) & NicReady)
550                         return 0;
551                 delay(10);
552         }
553         csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | Prepare);
554         for(i=0; i<15000; i++){
555                 if((csr32r(ctlr, Cfg) & PrepareDone) == 0)
556                         break;
557                 delay(10);
558         }
559         if(i >= 15000)
560                 return "handover: timeout";
561         csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
562         for(i=0; i<5; i++){
563                 if(csr32r(ctlr, Cfg) & NicReady)
564                         return 0;
565                 delay(10);
566         }
567         return "handover: timeout";
568 }
569
570 static char*
571 clockwait(Ctlr *ctlr)
572 {
573         int i;
574
575         /* Set "initialization complete" bit. */
576         csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone);
577         for(i=0; i<2500; i++){
578                 if(csr32r(ctlr, Gpc) & MacClockReady)
579                         return 0;
580                 delay(10);
581         }
582         return "clockwait: timeout";
583 }
584
585 static char*
586 poweron(Ctlr *ctlr)
587 {
588         int capoff;
589         char *err;
590
591         /* Disable L0s exit timer (NMI bug workaround). */
592         csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | DisL0Stimer);
593
594         /* Don't wait for ICH L0s (ICH bug workaround). */
595         csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | L1AnoL0Srx);
596
597         /* Set FH wait threshold to max (HW bug under stress workaround). */
598         csr32w(ctlr, Dbghpetmem, csr32r(ctlr, Dbghpetmem) | 0xffff0000);
599
600         /* Enable HAP INTA to move adapter from L1a to L0s. */
601         csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | HapwakeL1A);
602
603         capoff = pcicap(ctlr->pdev, PciCapPCIe);
604         if(capoff != -1){
605                 /* Workaround for HW instability in PCIe L0->L0s->L1 transition. */
606                 if(pcicfgr16(ctlr->pdev, capoff + 0x10) & 0x2)  /* LCSR -> L1 Entry enabled. */
607                         csr32w(ctlr, Gio, csr32r(ctlr, Gio) | EnaL0S);
608                 else
609                         csr32w(ctlr, Gio, csr32r(ctlr, Gio) & ~EnaL0S);
610         }
611
612         if(ctlr->type != Type4965 && ctlr->type <= Type1000)
613                 csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | 0x00880300);
614
615         /* Wait for clock stabilization before accessing prph. */
616         if((err = clockwait(ctlr)) != nil)
617                 return err;
618
619         if((err = niclock(ctlr)) != nil)
620                 return err;
621
622         /* Enable DMA and BSM (Bootstrap State Machine). */
623         if(ctlr->type == Type4965)
624                 prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt);
625         else
626                 prphwrite(ctlr, ApmgClkEna, DmaClkRqt);
627         delay(20);
628
629         /* Disable L1-Active. */
630         prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11));
631
632         nicunlock(ctlr);
633         return 0;
634 }
635
636 static int
637 iwlinit(Ether *edev)
638 {
639         Ctlr *ctlr;
640         char *err;
641         uchar b[2];
642         uint u;
643
644         ctlr = edev->ctlr;
645         if((err = handover(ctlr)) != nil)
646                 goto Err;
647         if((err = poweron(ctlr)) != nil)
648                 goto Err;
649         if((csr32r(ctlr, EepromGp) & 0x7) == 0){
650                 err = "bad rom signature";
651                 goto Err;
652         }
653         if((err = eepromlock(ctlr)) != nil)
654                 goto Err;
655         if((err = eepromread(ctlr, edev->ea, sizeof(edev->ea), 0x15)) != nil){
656                 eepromunlock(ctlr);
657                 goto Err;
658         }
659         if(ctlr->type != Type4965){
660                 if((err = eepromread(ctlr, b, 2, 0x048)) != nil){
661                         eepromunlock(ctlr);
662                         goto Err;
663                 }
664                 u = get16(b);
665                 ctlr->rfcfg.type = u & 3;       u >>= 2;
666                 ctlr->rfcfg.step = u & 3;       u >>= 2;
667                 ctlr->rfcfg.dash = u & 3;       u >>= 4;
668                 ctlr->rfcfg.txantmask = u & 15; u >>= 4;
669                 ctlr->rfcfg.rxantmask = u & 15;
670                 if((err = eepromread(ctlr, b, 4, 0x128)) != nil){
671                         eepromunlock(ctlr);
672                         goto Err;
673                 }
674                 ctlr->eeprom.crystal = get32(b);
675         }
676         eepromunlock(ctlr);
677
678         switch(ctlr->type){
679         case Type4965:
680                 ctlr->rfcfg.txantmask = 3;
681                 ctlr->rfcfg.rxantmask = 7;
682                 break;
683         case Type5100:
684                 ctlr->rfcfg.txantmask = 2;
685                 ctlr->rfcfg.rxantmask = 3;
686                 break;
687         case Type6000:
688                 if(ctlr->pdev->did == 0x422c || ctlr->pdev->did == 0x4230){
689                         ctlr->rfcfg.txantmask = 6;
690                         ctlr->rfcfg.rxantmask = 6;
691                 }
692                 break;
693         }
694
695         ctlr->ie = 0;
696         csr32w(ctlr, Isr, ~0);  /* clear pending interrupts */
697         csr32w(ctlr, Imr, 0);   /* no interrupts for now */
698
699         return 0;
700 Err:
701         print("iwlinit: %s\n", err);
702         return -1;
703 }
704
705 static char*
706 crackfw(FWImage *i, uchar *data, uint size, int alt)
707 {
708         uchar *p, *e;
709         FWSect *s;
710
711         memset(i, 0, sizeof(*i));
712         if(size < 4){
713 Tooshort:
714                 return "firmware image too short";
715         }
716         p = data;
717         e = p + size;
718         i->rev = get32(p); p += 4;
719         if(i->rev == 0){
720                 uvlong altmask;
721
722                 if(size < (4+64+4+4+8))
723                         goto Tooshort;
724                 if(memcmp(p, "IWL\n", 4) != 0)
725                         return "bad firmware signature";
726                 p += 4;
727                 strncpy(i->descr, (char*)p, 64);
728                 i->descr[sizeof(i->descr)-1] = 0;
729                 p += 64;
730                 i->rev = get32(p); p += 4;
731                 i->build = get32(p); p += 4;
732                 altmask = get32(p); p += 4;
733                 altmask |= (uvlong)get32(p) << 32; p += 4;
734                 while(alt > 0 && (altmask & (1ULL<<alt)) == 0)
735                         alt--;
736                 while(p < e){
737                         FWSect dummy;
738
739                         if((p + 2+2+4) > e)
740                                 goto Tooshort;
741                         switch(get16(p)){
742                         case 1: s = &i->main.text; break;
743                         case 2: s = &i->main.data; break;
744                         case 3: s = &i->init.text; break;
745                         case 4: s = &i->init.data; break;
746                         case 5: s = &i->boot.text; break;
747                         default:s = &dummy;
748                         }
749                         p += 2;
750                         if(get16(p) != alt)
751                                 s = &dummy;
752                         p += 2;
753                         s->size = get32(p); p += 4;
754                         s->data = p;
755                         if((p + s->size) > e)
756                                 goto Tooshort;
757                         p += (s->size + 3) & ~3;
758                 }
759         } else {
760                 if(((i->rev>>8) & 0xFF) < 2)
761                         return "need firmware api >= 2";
762                 if(((i->rev>>8) & 0xFF) >= 3){
763                         i->build = get32(p); p += 4;
764                 }
765                 if((p + 5*4) > e)
766                         goto Tooshort;
767                 i->main.text.size = get32(p); p += 4;
768                 i->main.data.size = get32(p); p += 4;
769                 i->init.text.size = get32(p); p += 4;
770                 i->init.data.size = get32(p); p += 4;
771                 i->boot.text.size = get32(p); p += 4;
772                 i->main.text.data = p; p += i->main.text.size;
773                 i->main.data.data = p; p += i->main.data.size;
774                 i->init.text.data = p; p += i->init.text.size;
775                 i->init.data.data = p; p += i->init.data.size;
776                 i->boot.text.data = p; p += i->boot.text.size;
777                 if(p > e)
778                         goto Tooshort;
779         }
780         return 0;
781 }
782
783 static FWImage*
784 readfirmware(char *name)
785 {
786         uchar dirbuf[sizeof(Dir)+100], *data;
787         char buf[128], *err;
788         FWImage *fw;
789         int n, r;
790         Chan *c;
791         Dir d;
792
793         if(!iseve())
794                 error(Eperm);
795         if(!waserror()){
796                 snprint(buf, sizeof buf, "/boot/%s", name);
797                 c = namec(buf, Aopen, OREAD, 0);
798                 poperror();
799         } else {
800                 snprint(buf, sizeof buf, "/lib/firmware/%s", name);
801                 c = namec(buf, Aopen, OREAD, 0);
802         }
803         if(waserror()){
804                 cclose(c);
805                 nexterror();
806         }
807         n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf);
808         if(n <= 0)
809                 error("can't stat firmware");
810         convM2D(dirbuf, n, &d, nil);
811         fw = smalloc(sizeof(*fw) + 16 + d.length);
812         data = (uchar*)(fw+1);
813         if(waserror()){
814                 free(fw);
815                 nexterror();
816         }
817         r = 0;
818         while(r < d.length){
819                 n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r);
820                 if(n <= 0)
821                         break;
822                 r += n;
823         }
824         if((err = crackfw(fw, data, r, 1)) != nil)
825                 error(err);
826         poperror();
827         poperror();
828         cclose(c);
829         return fw;
830 }
831
832 typedef struct Irqwait Irqwait;
833 struct Irqwait {
834         Ctlr    *ctlr;
835         u32int  mask;
836 };
837
838 static int
839 gotirq(void *arg)
840 {
841         Irqwait *w;
842         Ctlr *ctlr;
843
844         w = arg;
845         ctlr = w->ctlr;
846         ctlr->wait.r = ctlr->wait.m & w->mask;
847         if(ctlr->wait.r){
848                 ctlr->wait.m &= ~ctlr->wait.r;
849                 return 1;
850         }
851         ctlr->wait.w = w->mask;
852         return 0;
853 }
854
855 static u32int
856 irqwait(Ctlr *ctlr, u32int mask, int timeout)
857 {
858         Irqwait w;
859
860         w.ctlr = ctlr;
861         w.mask = mask;
862         tsleep(&ctlr->wait, gotirq, &w, timeout);
863         ctlr->wait.w = 0;
864         return ctlr->wait.r & mask;
865 }
866
867 static char*
868 loadfirmware1(Ctlr *ctlr, u32int dst, uchar *data, int size)
869 {
870         uchar *dma;
871         char *err;
872
873         dma = mallocalign(size, 16, 0, 0);
874         if(dma == nil)
875                 return "no memory for dma";
876         memmove(dma, data, size);
877         coherence();
878         if((err = niclock(ctlr)) != 0){
879                 free(dma);
880                 return err;
881         }
882         csr32w(ctlr, FhTxConfig + 9*32, 0);
883         csr32w(ctlr, FhSramAddr + 9*4, dst);
884         csr32w(ctlr, FhTfbdCtrl0 + 9*8, PCIWADDR(dma));
885         csr32w(ctlr, FhTfbdCtrl1 + 9*8, size);
886         csr32w(ctlr, FhTxBufStatus + 9*32,
887                 (1<<FhTxBufStatusTbNumShift) |
888                 (1<<FhTxBufStatusTbIdxShift) |
889                 FhTxBufStatusTfbdValid);
890         csr32w(ctlr, FhTxConfig + 9*32, FhTxConfigDmaEna | FhTxConfigCirqHostEndTfd);
891         nicunlock(ctlr);
892         if(irqwait(ctlr, Ifhtx|Ierr, 5000) != Ifhtx){
893                 free(dma);
894                 return "dma error / timeout";
895         }
896         free(dma);
897         return 0;
898 }
899
900 static char*
901 bootfirmware(Ctlr *ctlr)
902 {
903         int i, n, size;
904         uchar *p, *dma;
905         FWImage *fw;
906         char *err;
907
908         dma = nil;
909         fw = ctlr->fw;
910
911         if(fw->boot.text.size == 0){
912                 if((err = loadfirmware1(ctlr, 0x00000000, fw->main.text.data, fw->main.text.size)) != nil)
913                         return err;
914                 if((err = loadfirmware1(ctlr, 0x00800000, fw->main.data.data, fw->main.data.size)) != nil)
915                         return err;
916                 goto bootmain;
917         }
918
919         size = ROUND(fw->init.data.size, 16) + ROUND(fw->init.text.size, 16);
920         dma = mallocalign(size, 16, 0, 0);
921         if(dma == nil)
922                 return "no memory for dma";
923
924         if((err = niclock(ctlr)) != nil){
925                 free(dma);
926                 return err;
927         }
928
929         p = dma;
930         memmove(p, fw->init.data.data, fw->init.data.size);
931         coherence();
932         prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
933         prphwrite(ctlr, BsmDramDataSize, fw->init.data.size);
934         p += ROUND(fw->init.data.size, 16);
935         memmove(p, fw->init.text.data, fw->init.text.size);
936         coherence();
937         prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
938         prphwrite(ctlr, BsmDramTextSize, fw->init.text.size);
939
940         p = fw->boot.text.data;
941         n = fw->boot.text.size/4;
942         for(i=0; i<n; i++, p += 4)
943                 prphwrite(ctlr, BsmSramBase+i*4, get32(p));
944
945         prphwrite(ctlr, BsmWrMemSrc, 0);
946         prphwrite(ctlr, BsmWrMemDst, 0);
947         prphwrite(ctlr, BsmWrDwCount, n);
948
949         prphwrite(ctlr, BsmWrCtrl, 1<<31);
950
951         for(i=0; i<1000; i++){
952                 if((prphread(ctlr, BsmWrCtrl) & (1<<31)) == 0)
953                         break;
954                 delay(10);
955         }
956         if(i == 1000){
957                 nicunlock(ctlr);
958                 free(dma);
959                 return "bootfirmware: bootcode timeout";
960         }
961
962         prphwrite(ctlr, BsmWrCtrl, 1<<30);
963         nicunlock(ctlr);
964
965         csr32w(ctlr, Reset, 0);
966         if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
967                 free(dma);
968                 return "init firmware boot failed";
969         }
970         free(dma);
971
972         size = ROUND(fw->main.data.size, 16) + ROUND(fw->main.text.size, 16);
973         dma = mallocalign(size, 16, 0, 0);
974         if(dma == nil)
975                 return "no memory for dma";
976         if((err = niclock(ctlr)) != nil){
977                 free(dma);
978                 return err;
979         }
980         p = dma;
981         memmove(p, fw->main.data.data, fw->main.data.size);
982         coherence();
983         prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
984         prphwrite(ctlr, BsmDramDataSize, fw->main.data.size);
985         p += ROUND(fw->main.data.size, 16);
986         memmove(p, fw->main.text.data, fw->main.text.size);
987         coherence();
988         prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
989         prphwrite(ctlr, BsmDramTextSize, fw->main.text.size | (1<<31));
990         nicunlock(ctlr);
991
992 bootmain:
993         csr32w(ctlr, Reset, 0);
994         if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
995                 free(dma);
996                 return "main firmware boot failed";
997         }
998         free(dma);
999         return nil;
1000 }
1001
1002 static int
1003 txqready(void *arg)
1004 {
1005         TXQ *q = arg;
1006         return q->n < Ntx;
1007 }
1008
1009 static void
1010 qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
1011 {
1012         uchar *d, *c;
1013         TXQ *q;
1014
1015         assert(qid < nelem(ctlr->tx));
1016         assert(size <= Tcmdsize-4);
1017
1018         ilock(ctlr);
1019         q = &ctlr->tx[qid];
1020         while(q->n >= Ntx){
1021                 iunlock(ctlr);
1022                 eqlock(q);
1023                 if(waserror()){
1024                         qunlock(q);
1025                         nexterror();
1026                 }
1027                 tsleep(q, txqready, q, 10);
1028                 qunlock(q);
1029                 ilock(ctlr);
1030         }
1031         q->n++;
1032
1033         q->b[q->i] = block;
1034         c = q->c + q->i * Tcmdsize;
1035         d = q->d + q->i * Tdscsize;
1036
1037         /* build command */
1038         c[0] = code;
1039         c[1] = 0;       /* flags */
1040         c[2] = q->i;
1041         c[3] = qid;
1042
1043         memmove(c+4, data, size);
1044
1045         size += 4;
1046
1047         /* build descriptor */
1048         *d++ = 0;
1049         *d++ = 0;
1050         *d++ = 0;
1051         *d++ = 1 + (block != nil); /* nsegs */
1052         put32(d, PCIWADDR(c));  d += 4;
1053         put16(d, size << 4); d += 2;
1054         if(block != nil){
1055                 size = BLEN(block);
1056                 if(size > Tbufsize)
1057                         size = Tbufsize;
1058                 put32(d, PCIWADDR(block->rp)); d += 4;
1059                 put16(d, size << 4);
1060         }
1061
1062         coherence();
1063
1064         q->i = (q->i+1) % Ntx;
1065         csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i);
1066
1067         iunlock(ctlr);
1068 }
1069
1070 static void
1071 cmd(Ctlr *ctlr, uint code, uchar *data, int size)
1072 {
1073         qcmd(ctlr, 4, code, data, size, nil);
1074 }
1075
1076 static void
1077 setled(Ctlr *ctlr, int which, int on, int off)
1078 {
1079         uchar c[8];
1080
1081         csr32w(ctlr, Led, csr32r(ctlr, Led) & ~LedBsmCtrl);
1082
1083         memset(c, 0, sizeof(c));
1084         put32(c, 10000);
1085         c[4] = which;
1086         c[5] = on;
1087         c[6] = off;
1088         cmd(ctlr, 72, c, sizeof(c));
1089 }
1090
1091 /*
1092  * initialization which runs after the firmware has been booted up
1093  */
1094 static void
1095 postboot(Ctlr *ctlr)
1096 {
1097         uint ctxoff, ctxlen, dramaddr, txfact;
1098         uchar c[8];
1099         char *err;
1100         int i, q;
1101
1102         /* main led turn on! (verify that firmware processes commands) */
1103         setled(ctlr, 2, 0, 1);
1104
1105         if((err = niclock(ctlr)) != nil)
1106                 error(err);
1107
1108         if(ctlr->type != Type4965){
1109                 dramaddr = SchedDramAddr5000;
1110                 ctxoff = SchedCtxOff5000;
1111                 ctxlen = SchedCtxLen5000;
1112                 txfact = SchedTxFact5000;
1113         } else {
1114                 dramaddr = SchedDramAddr4965;
1115                 ctxoff = SchedCtxOff4965;
1116                 ctxlen = SchedCtxLen4965;
1117                 txfact = SchedTxFact4965;
1118         }
1119
1120         ctlr->sched.base = prphread(ctlr, SchedSramAddr);
1121         for(i=0; i < ctxlen/4; i++)
1122                 memwrite(ctlr, ctlr->sched.base + ctxoff + i*4, 0);
1123
1124         prphwrite(ctlr, dramaddr, PCIWADDR(ctlr->sched.s)>>10);
1125
1126         csr32w(ctlr, FhTxChicken, csr32r(ctlr, FhTxChicken) | 2);
1127
1128         if(ctlr->type != Type4965){
1129                 /* Enable chain mode for all queues, except command queue 4. */
1130                 prphwrite(ctlr, SchedQChainSel5000, 0xfffef);
1131                 prphwrite(ctlr, SchedAggrSel5000, 0);
1132
1133                 for(q=0; q<nelem(ctlr->tx); q++){
1134                         prphwrite(ctlr, SchedQueueRdptr5000 + q*4, 0);
1135                         csr32w(ctlr, HbusTargWptr, q << 8);
1136
1137                         memwrite(ctlr, ctlr->sched.base + ctxoff + q*8, 0);
1138                         /* Set scheduler window size and frame limit. */
1139                         memwrite(ctlr, ctlr->sched.base + ctxoff + q*8 + 4, 64<<16 | 64);
1140                 }
1141                 /* Enable interrupts for all our 20 queues. */
1142                 prphwrite(ctlr, SchedIntrMask5000, 0xfffff);
1143         } else {
1144                 /* Disable chain mode for all our 16 queues. */
1145                 prphwrite(ctlr, SchedQChainSel4965, 0);
1146
1147                 for(q=0; q<16; q++) {
1148                         prphwrite(ctlr, SchedQueueRdptr4965 + q*4, 0);
1149                         csr32w(ctlr, HbusTargWptr, q << 8);
1150
1151                         /* Set scheduler window size. */
1152                         memwrite(ctlr, ctlr->sched.base + ctxoff + q*8, 64);
1153                         /* Set scheduler window size and frame limit. */
1154                         memwrite(ctlr, ctlr->sched.base + ctxoff + q*8 + 4, 64<<16);
1155                 }
1156                 /* Enable interrupts for all our 16 queues. */
1157                 prphwrite(ctlr, SchedIntrMask4965, 0xffff);
1158         }
1159
1160         /* Identify TX FIFO rings (0-7). */
1161         prphwrite(ctlr, txfact, 0xff);
1162
1163         /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
1164         for(q=0; q<7; q++){
1165                 static uchar qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
1166                 if(ctlr->type != Type4965)
1167                         prphwrite(ctlr, SchedQueueStatus5000 + q*4, 0x00ff0018 | qid2fifo[q]);
1168                 else
1169                         prphwrite(ctlr, SchedQueueStatus4965 + q*4, 0x0007fc01 | qid2fifo[q]);
1170         }
1171         nicunlock(ctlr);
1172
1173         if(ctlr->type != Type5150){
1174                 memset(c, 0, sizeof(c));
1175                 c[0] = 15;      /* code */
1176                 c[1] = 0;       /* grup */
1177                 c[2] = 1;       /* ngroup */
1178                 c[3] = 1;       /* isvalid */
1179                 put16(c+4, ctlr->eeprom.crystal);
1180                 cmd(ctlr, 176, c, 8);
1181         }
1182
1183         if(ctlr->type != Type4965){
1184                 put32(c, ctlr->rfcfg.txantmask & 7);
1185                 cmd(ctlr, 152, c, 4);
1186         }
1187 }
1188
1189 static void
1190 addnode(Ctlr *ctlr, uchar id, uchar *addr)
1191 {
1192         uchar c[Tcmdsize], *p;
1193
1194         memset(p = c, 0, sizeof(c));
1195         *p++ = 0;       /* control (1 = update) */
1196         p += 3;         /* reserved */
1197         memmove(p, addr, 6);
1198         p += 6;
1199         p += 2;         /* reserved */
1200         *p++ = id;      /* node id */
1201         p++;            /* flags */
1202         p += 2;         /* reserved */
1203         p += 2;         /* kflags */
1204         p++;            /* tcs2 */
1205         p++;            /* reserved */
1206         p += 5*2;       /* ttak */
1207         p++;            /* kid */
1208         p++;            /* reserved */
1209         p += 16;        /* key */
1210         if(ctlr->type != Type4965){
1211                 p += 8;         /* tcs */
1212                 p += 8;         /* rxmic */
1213                 p += 8;         /* txmic */
1214                 p += 4;         /* htflags */
1215                 p += 4;         /* mask */
1216                 p += 2;         /* disable tid */
1217                 p += 2;         /* reserved */
1218                 p++;            /* add ba tid */
1219                 p++;            /* del ba tid */
1220                 p += 2;         /* add ba ssn */
1221                 p += 4;         /* reserved */
1222         }
1223         cmd(ctlr, 24, c, p - c);
1224 }
1225
1226 void
1227 rxon(Ether *edev, Wnode *bss)
1228 {
1229         uchar c[Tcmdsize], *p;
1230         Ctlr *ctlr;
1231
1232         ctlr = edev->ctlr;
1233         memset(p = c, 0, sizeof(c));
1234         memmove(p, edev->ea, 6); p += 8;        /* myaddr */
1235         memmove(p, (bss != nil) ? bss->bssid : edev->bcast, 6);
1236         p += 8;                                 /* bssid */
1237         memmove(p, edev->ea, 6); p += 8;        /* wlap */
1238         *p++ = 3;                               /* mode (STA) */
1239         *p++ = 0;                               /* air (?) */
1240         /* rxchain */
1241         put16(p, ((ctlr->rfcfg.rxantmask & 7)<<1) | (2<<10) | (2<<12));
1242         p += 2;
1243         *p++ = 0xff;                            /* ofdm mask (not yet negotiated) */
1244         *p++ = 0x0f;                            /* cck mask (not yet negotiated) */
1245         if(bss != nil)
1246                 put16(p, bss->aid & ~0xc000);
1247         p += 2;                                 /* aid */
1248         put32(p, (1<<15)|(1<<30)|(1<<0));       /* flags (TSF | CTS_TO_SELF | 24GHZ) */
1249         p += 4;
1250         put32(p, 8|4|1);                        /* filter (NODECRYPT|MULTICAST|PROMISC) */
1251         p += 4;
1252         *p++ = bss != nil ? bss->channel : ctlr->channel;
1253         p++;                                    /* reserved */
1254         *p++ = 0xff;                            /* ht single mask */
1255         *p++ = 0xff;                            /* ht dual mask */
1256         if(ctlr->type != Type4965){
1257                 *p++ = 0xff;                    /* ht triple mask */
1258                 p++;                            /* reserved */
1259                 put16(p, 0); p += 2;            /* acquisition */
1260                 p += 2;                         /* reserved */
1261         }
1262         cmd(ctlr, 16, c, p - c);
1263
1264         addnode(ctlr, (ctlr->type != Type4965) ? 15 : 31, edev->bcast);
1265         if(bss != nil)
1266                 addnode(ctlr, 0, bss->bssid);
1267 }
1268
1269 static struct ratetab {
1270         uchar   rate;
1271         uchar   plcp;
1272         uchar   flags;
1273 } ratetab[] = {
1274         {   2,  10, 1<<1 },
1275         {   4,  20, 1<<1 },
1276         {  11,  55, 1<<1 },
1277         {  22, 110, 1<<1 },
1278         {  12, 0xd, 0 },
1279         {  18, 0xf, 0 },
1280         {  24, 0x5, 0 },
1281         {  36, 0x7, 0 },
1282         {  48, 0x9, 0 },
1283         {  72, 0xb, 0 },
1284         {  96, 0x1, 0 },
1285         { 108, 0x3, 0 },
1286         { 120, 0x3, 0 }
1287 };
1288
1289 static void
1290 transmit(Wifi *wifi, Wnode *, Block *b)
1291 {
1292         uchar c[Tcmdsize], *p;
1293         Ctlr *ctlr;
1294
1295         ctlr = wifi->ether->ctlr;
1296
1297         memset(p = c, 0, sizeof(c));
1298         put16(p, BLEN(b));
1299         p += 2;
1300         p += 2;         /* lnext */
1301         put32(p, 0);    /* flags */
1302         p += 4;
1303         put32(p, 0);
1304         p += 4;         /* scratch */
1305
1306         /* BUG: hardcode 11Mbit */
1307         *p++ = ratetab[2].plcp;                 /* plcp */
1308         *p++ = ratetab[2].flags | (1<<6);       /* rflags */
1309
1310         p += 2;         /* xflags */
1311
1312         /* BUG: we always use broadcast node! */
1313         *p++ = (ctlr->type != Type4965) ? 15 : 31;
1314
1315         *p++ = 0;       /* security */
1316         *p++ = 0;       /* linkq */
1317         p++;            /* reserved */
1318         p += 16;        /* key */
1319         p += 2;         /* fnext */
1320         p += 2;         /* reserved */
1321         put32(p, ~0);   /* lifetime */
1322         p += 4;
1323
1324         /* BUG: scratch ptr? not clear what this is for */
1325         put32(p, PCIWADDR(ctlr->kwpage));
1326         p += 5;
1327
1328         *p++ = 60;      /* rts ntries */
1329         *p++ = 15;      /* data ntries */
1330         *p++ = 0;       /* tid */
1331         put16(p, 0);    /* timeout */
1332         p += 2;
1333         p += 2;         /* txop */
1334         qcmd(ctlr, 0, 28, c, p - c, b);
1335 }
1336
1337 static int
1338 rbplant(Ctlr *ctlr, int i)
1339 {
1340         Block *b;
1341
1342         b = iallocb(Rbufsize + 256);
1343         if(b == nil)
1344                 return -1;
1345         b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, 256);
1346         memset(b->rp, 0, Rdscsize);
1347         ctlr->rx.b[i] = b;
1348         ctlr->rx.p[i] = PCIWADDR(b->rp) >> 8;
1349         return 0;
1350 }
1351
1352 static long
1353 iwlctl(Ether *edev, void *buf, long n)
1354 {
1355         Ctlr *ctlr;
1356
1357         ctlr = edev->ctlr;
1358         if(ctlr->wifi)
1359                 return wifictl(ctlr->wifi, buf, n);
1360         return 0;
1361 }
1362
1363 static long
1364 iwlifstat(Ether *edev, void *buf, long n, ulong off)
1365 {
1366         Ctlr *ctlr;
1367
1368         ctlr = edev->ctlr;
1369         if(ctlr->wifi)
1370                 return wifistat(ctlr->wifi, buf, n, off);
1371         return 0;
1372 }
1373
1374 static void
1375 setoptions(Ether *edev)
1376 {
1377         Ctlr *ctlr;
1378         char buf[64];
1379         int i;
1380
1381         ctlr = edev->ctlr;
1382         ctlr->channel = 3;
1383         for(i = 0; i < edev->nopt; i++){
1384                 if(strncmp(edev->opt[i], "channel=", 8) == 0)
1385                         ctlr->channel = atoi(edev->opt[i]+8);
1386                 else
1387                 if(strncmp(edev->opt[i], "essid=", 6) == 0){
1388                         snprint(buf, sizeof(buf), "essid %s", edev->opt[i]+6);
1389                         if(!waserror()){
1390                                 wifictl(ctlr->wifi, buf, strlen(buf));
1391                                 poperror();
1392                         }
1393                 }
1394         }
1395 }
1396
1397 static void
1398 iwlattach(Ether *edev)
1399 {
1400         FWImage *fw;
1401         Ctlr *ctlr;
1402         char *err;
1403         RXQ *rx;
1404         TXQ *tx;
1405         int i, q;
1406
1407         ctlr = edev->ctlr;
1408         eqlock(ctlr);
1409         if(waserror()){
1410                 qunlock(ctlr);
1411                 nexterror();
1412         }
1413         if(ctlr->attached == 0){
1414                 if((csr32r(ctlr, Gpc) & RfKill) == 0){
1415                         print("#l%d: wifi disabled by switch\n", edev->ctlrno);
1416                         error("wifi disabled by switch");
1417                 }
1418
1419                 if(ctlr->wifi == nil)
1420                         ctlr->wifi = wifiattach(edev, transmit);
1421
1422                 if(ctlr->fw == nil){
1423                         fw = readfirmware(ctlrtype[ctlr->type].fwname);
1424                         print("#l%d: firmware: %s, rev %ux, build %ud, size %ux+%ux+%ux+%ux+%ux\n",
1425                                 edev->ctlrno,
1426                                 ctlrtype[ctlr->type].fwname,
1427                                 fw->rev, fw->build,
1428                                 fw->main.text.size, fw->main.data.size,
1429                                 fw->init.text.size, fw->init.data.size,
1430                                 fw->boot.text.size);
1431                         ctlr->fw = fw;
1432                 }
1433
1434                 rx = &ctlr->rx;
1435                 rx->i = 0;
1436                 if(rx->b == nil)
1437                         rx->b = malloc(sizeof(Block*) * Nrx);
1438                 if(rx->p == nil)
1439                         rx->p = mallocalign(sizeof(u32int) * Nrx, 256, 0, 0);
1440                 if(rx->s == nil)
1441                         rx->s = mallocalign(Rstatsize, 16, 0, 0);
1442                 if(rx->b == nil || rx->p == nil || rx->s == nil)
1443                         error("no memory for rx ring");
1444                 memset(rx->s, 0, Rstatsize);
1445                 for(i=0; i<Nrx; i++){
1446                         rx->p[i] = 0;
1447                         if(rx->b[i] != nil){
1448                                 freeb(rx->b[i]);
1449                                 rx->b[i] = nil;
1450                         }
1451                         if(rbplant(ctlr, i) < 0)
1452                                 error("no memory for rx descriptors");
1453                 }
1454
1455                 for(q=0; q<nelem(ctlr->tx); q++){
1456                         tx = &ctlr->tx[q];
1457                         tx->i = 0;
1458                         tx->n = 0;
1459                         if(tx->b == nil)
1460                                 tx->b = malloc(sizeof(Block*) * Ntx);
1461                         if(tx->d == nil)
1462                                 tx->d = mallocalign(Tdscsize * Ntx, 256, 0, 0);
1463                         if(tx->c == nil)
1464                                 tx->c = mallocalign(Tcmdsize * Ntx, 4, 0, 0);
1465                         if(tx->b == nil || tx->d == nil || tx->c == nil)
1466                                 error("no memory for tx ring");
1467                         memset(tx->d, 0, Tdscsize * Ntx);
1468                 }
1469
1470                 if(ctlr->sched.s == nil)
1471                         ctlr->sched.s = mallocalign(512 * nelem(ctlr->tx) * 2, 1024, 0, 0);
1472                 if(ctlr->kwpage == nil)
1473                         ctlr->kwpage = mallocalign(4096, 4096, 0, 0);
1474
1475                 if((err = niclock(ctlr)) != nil)
1476                         error(err);
1477                 prphwrite(ctlr, ApmgPs, (prphread(ctlr, ApmgPs) & ~PwrSrcMask) | PwrSrcVMain);
1478                 nicunlock(ctlr);
1479
1480                 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | RadioSi | MacSi);
1481
1482                 if((err = niclock(ctlr)) != nil)
1483                         error(err);
1484                 prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | EarlyPwroffDis);
1485                 nicunlock(ctlr);
1486
1487                 if((err = niclock(ctlr)) != nil)
1488                         error(err);
1489                 csr32w(ctlr, FhRxConfig, 0);
1490                 csr32w(ctlr, FhRxWptr, 0);
1491                 csr32w(ctlr, FhRxBase, PCIWADDR(ctlr->rx.p) >> 8);
1492                 csr32w(ctlr, FhStatusWptr, PCIWADDR(ctlr->rx.s) >> 4);
1493                 csr32w(ctlr, FhRxConfig,
1494                         FhRxConfigEna | 
1495                         FhRxConfigIgnRxfEmpty |
1496                         FhRxConfigIrqDstHost | 
1497                         FhRxConfigSingleFrame |
1498                         (Nrxlog << FhRxConfigNrbdShift));
1499                 csr32w(ctlr, FhRxWptr, (Nrx-1) & ~7);
1500                 nicunlock(ctlr);
1501
1502                 if((err = niclock(ctlr)) != nil)
1503                         error(err);
1504
1505                 prphwrite(ctlr, SchedTxFact5000, 0);
1506
1507                 csr32w(ctlr, FhKwAddr, PCIWADDR(ctlr->kwpage) >> 4);
1508
1509                 for(q=0; q<nelem(ctlr->tx); q++)
1510                         if(q < 15 || ctlr->type != Type4965)
1511                                 csr32w(ctlr, FhCbbcQueue + q*4, PCIWADDR(ctlr->tx[q].d) >> 8);
1512                 nicunlock(ctlr);
1513
1514                 for(i=0; i<8; i++)
1515                         if(i < 7 || ctlr->type != Type4965)
1516                                 csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna);
1517
1518                 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
1519                 csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
1520
1521                 ctlr->ie = Idefmask;
1522                 csr32w(ctlr, Imr, ctlr->ie);
1523                 csr32w(ctlr, Isr, ~0);
1524
1525                 if(ctlr->type >= Type6000)
1526                         csr32w(ctlr, ShadowRegCtrl, csr32r(ctlr, ShadowRegCtrl) | 0x800fffff);
1527
1528                 bootfirmware(ctlr);
1529                 postboot(ctlr);
1530
1531                 setoptions(edev);
1532
1533                 rxon(edev, nil);
1534
1535                 edev->prom = 1;
1536                 edev->link = 1;
1537                 ctlr->attached = 1;
1538         }
1539         qunlock(ctlr);
1540         poperror();
1541 }
1542
1543 static void
1544 receive(Ctlr *ctlr)
1545 {
1546         Block *b, *bb;
1547         uchar *d, *dd, *cc;
1548         RXQ *rx;
1549         TXQ *tx;
1550         uint hw;
1551
1552         rx = &ctlr->rx;
1553         if(rx->s == nil || rx->b == nil)
1554                 return;
1555         for(hw = get16(rx->s) % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){
1556                 uchar type, flags, idx, qid;
1557                 u32int len;
1558
1559                 b = rx->b[rx->i];
1560                 if(b == nil)
1561                         continue;
1562
1563                 d = b->rp;
1564                 len = get32(d); d += 4;
1565                 type = *d++;
1566                 flags = *d++;
1567                 USED(flags);
1568                 idx = *d++;
1569                 qid = *d++;
1570
1571                 if((qid & 0x80) == 0 && qid < nelem(ctlr->tx)){
1572                         tx = &ctlr->tx[qid];
1573                         if(tx->n > 0){
1574                                 bb = tx->b[idx];
1575                                 if(bb != nil){
1576                                         tx->b[idx] = nil;
1577                                         freeb(bb);
1578                                 }
1579                                 /* paranoia: clear tx descriptors */
1580                                 dd = tx->d + idx*Tdscsize;
1581                                 cc = tx->c + idx*Tcmdsize;
1582                                 memset(dd, 0, Tdscsize);
1583                                 memset(cc, 0, Tcmdsize);
1584                                 tx->n--;
1585
1586                                 wakeup(tx);
1587                         }
1588                 }
1589
1590                 len &= 0x3fff;
1591                 if(len < 4 || type == 0)
1592                         continue;
1593
1594                 len -= 4;
1595                 switch(type){
1596                 case 1:         /* microcontroller ready */
1597                         setfwinfo(ctlr, d, len);
1598                         break;
1599                 case 24:        /* add node done */
1600                         break;
1601                 case 28:        /* tx done */
1602                         break;
1603                 case 102:       /* calibration result (Type5000 only) */
1604                         break;
1605                 case 103:       /* calibration done (Type5000 only) */
1606                         break;
1607                 case 130:       /* start scan */
1608                         break;
1609                 case 132:       /* stop scan */
1610                         break;
1611                 case 156:       /* rx statistics */
1612                         break;
1613                 case 157:       /* beacon statistics */
1614                         break;
1615                 case 161:       /* state changed */
1616                         break;
1617                 case 162:       /* beacon missed */
1618                         break;
1619                 case 192:       /* rx phy */
1620                         break;
1621                 case 195:       /* rx done */
1622                         if(d + 60 > b->lim)
1623                                 break;
1624                         d += 60;
1625                 case 193:       /* mpdu rx done */
1626                         if(d + 4 > b->lim)
1627                                 break;
1628                         len = get16(d); d += 4;
1629                         if(d + len + 4 > b->lim)
1630                                 break;
1631                         if((get32(d + len) & 3) != 3)
1632                                 break;
1633                         if(ctlr->wifi == nil)
1634                                 break;
1635                         if(rbplant(ctlr, rx->i) < 0)
1636                                 break;
1637                         b->rp = d;
1638                         b->wp = d + len;
1639                         wifiiq(ctlr->wifi, b);
1640                         continue;
1641                 case 197:       /* rx compressed ba */
1642                         break;
1643                 }
1644                 /* paranoia: clear the descriptor */
1645                 memset(b->rp, 0, Rdscsize);
1646         }
1647         csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7);
1648 }
1649
1650 static void
1651 iwlinterrupt(Ureg*, void *arg)
1652 {
1653         u32int isr, fhisr;
1654         Ether *edev;
1655         Ctlr *ctlr;
1656
1657         edev = arg;
1658         ctlr = edev->ctlr;
1659         ilock(ctlr);
1660         csr32w(ctlr, Imr, 0);
1661         isr = csr32r(ctlr, Isr);
1662         fhisr = csr32r(ctlr, FhIsr);
1663         if(isr == 0xffffffff || (isr & 0xfffffff0) == 0xa5a5a5a0){
1664                 iunlock(ctlr);
1665                 return;
1666         }
1667         if(isr == 0 && fhisr == 0)
1668                 goto done;
1669         csr32w(ctlr, Isr, isr);
1670         csr32w(ctlr, FhIsr, fhisr);
1671         if((isr & (Iswrx | Ifhrx | Irxperiodic)) || (fhisr & Ifhrx))
1672                 receive(ctlr);
1673         if(isr & Ierr){
1674                 iprint("#l%d: fatal firmware error\n", edev->ctlrno);
1675                 dumpctlr(ctlr);
1676         }
1677         ctlr->wait.m |= isr;
1678         if(ctlr->wait.m & ctlr->wait.w){
1679                 ctlr->wait.r = ctlr->wait.m & ctlr->wait.w;
1680                 ctlr->wait.m &= ~ctlr->wait.r;
1681                 wakeup(&ctlr->wait);
1682         }
1683 done:
1684         csr32w(ctlr, Imr, ctlr->ie);
1685         iunlock(ctlr);
1686 }
1687
1688 static Ctlr *iwlhead, *iwltail;
1689
1690 static void
1691 iwlpci(void)
1692 {
1693         Pcidev *pdev;
1694         
1695         pdev = nil;
1696         while(pdev = pcimatch(pdev, 0, 0)) {
1697                 Ctlr *ctlr;
1698                 void *mem;
1699                 
1700                 if(pdev->ccrb != 2 || pdev->ccru != 0x80)
1701                         continue;
1702                 if(pdev->vid != 0x8086)
1703                         continue;
1704
1705                 switch(pdev->did){
1706                 default:
1707                         continue;
1708                 case 0x4236:    /* WiFi Link 5300 AGN */
1709                 case 0x4237:    /* Wifi Link 5200 AGN */
1710                         break;
1711                 }
1712
1713                 /* Clear device-specific "PCI retry timeout" register (41h). */
1714                 if(pcicfgr8(pdev, 0x41) != 0)
1715                         pcicfgw8(pdev, 0x41, 0);
1716
1717                 /* Clear interrupt disable bit. Hardware bug workaround. */
1718                 if(pdev->pcr & 0x400){
1719                         pdev->pcr &= ~0x400;
1720                         pcicfgw16(pdev, PciPCR, pdev->pcr);
1721                 }
1722
1723                 pcisetbme(pdev);
1724                 pcisetpms(pdev, 0);
1725
1726                 ctlr = malloc(sizeof(Ctlr));
1727                 if(ctlr == nil) {
1728                         print("iwl: unable to alloc Ctlr\n");
1729                         continue;
1730                 }
1731                 ctlr->port = pdev->mem[0].bar & ~0x0F;
1732                 mem = vmap(pdev->mem[0].bar & ~0x0F, pdev->mem[0].size);
1733                 if(mem == nil) {
1734                         print("iwl: can't map %8.8luX\n", pdev->mem[0].bar);
1735                         free(ctlr);
1736                         continue;
1737                 }
1738                 ctlr->nic = mem;
1739                 ctlr->pdev = pdev;
1740                 ctlr->type = (csr32r(ctlr, Rev) >> 4) & 0xF;
1741
1742                 if(ctlrtype[ctlr->type].fwname == nil){
1743                         print("iwl: unsupported controller type %d\n", ctlr->type);
1744                         vunmap(mem, pdev->mem[0].size);
1745                         free(ctlr);
1746                         continue;
1747                 }
1748
1749                 if(iwlhead != nil)
1750                         iwltail->link = ctlr;
1751                 else
1752                         iwlhead = ctlr;
1753                 iwltail = ctlr;
1754         }
1755 }
1756
1757 static int
1758 iwlpnp(Ether* edev)
1759 {
1760         Ctlr *ctlr;
1761         
1762         if(iwlhead == nil)
1763                 iwlpci();
1764 again:
1765         for(ctlr = iwlhead; ctlr != nil; ctlr = ctlr->link){
1766                 if(ctlr->active)
1767                         continue;
1768                 if(edev->port == 0 || edev->port == ctlr->port){
1769                         ctlr->active = 1;
1770                         break;
1771                 }
1772         }
1773
1774         if(ctlr == nil)
1775                 return -1;
1776
1777         edev->ctlr = ctlr;
1778         edev->port = ctlr->port;
1779         edev->irq = ctlr->pdev->intl;
1780         edev->tbdf = ctlr->pdev->tbdf;
1781         edev->arg = edev;
1782         edev->interrupt = iwlinterrupt;
1783         edev->attach = iwlattach;
1784         edev->ifstat = iwlifstat;
1785         edev->ctl = iwlctl;
1786         edev->promiscuous = nil;
1787         edev->multicast = nil;
1788         edev->mbps = 10;
1789
1790         if(iwlinit(edev) < 0){
1791                 edev->ctlr = nil;
1792                 goto again;
1793         }
1794         
1795         return 0;
1796 }
1797
1798 void
1799 etheriwllink(void)
1800 {
1801         addethercard("iwl", iwlpnp);
1802 }