]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/etheriwl.c
etheriwl: fix bugs, support for Centrino Ultimate-N 6300
[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->calib.done == 0){
1234                         /* query calibration (init firmware) */
1235                         memset(c, 0, sizeof(c));
1236                         put32(c + 0*(5*4) + 0, 0xffffffff);
1237                         put32(c + 0*(5*4) + 4, 0xffffffff);
1238                         put32(c + 0*(5*4) + 8, 0xffffffff);
1239                         put32(c + 2*(5*4) + 0, 0xffffffff);
1240                         if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil)
1241                                 return err;
1242
1243                         /* wait to collect calibration records */
1244                         if(irqwait(ctlr, Ierr, 2000))
1245                                 return "calibration failed";
1246
1247                         if(ctlr->calib.done == 0){
1248                                 print("iwl: no calibration results\n");
1249                                 ctlr->calib.done = 1;
1250                         }
1251                 } else {
1252                         static uchar cmds[] = {8, 9, 11, 17, 16};
1253
1254                         /* send calibration records (runtime firmware) */
1255                         for(q=0; q<nelem(cmds); q++){
1256                                 Block *b;
1257
1258                                 i = cmds[q];
1259                                 if(i == 8 && ctlr->type != Type5150)
1260                                         continue;
1261                                 if(i == 17 && (ctlr->type >= Type6000 || ctlr->type == Type5150))
1262                                         continue;
1263                                 if((b = ctlr->calib.cmd[i]) == nil)
1264                                         continue;
1265                                 b->ref++;       /* dont free on command completion */
1266                                 if((err = qcmd(ctlr, 4, 176, nil, 0, b)) != nil)
1267                                         return err;
1268                                 if((err = flushq(ctlr, 4)) != nil)
1269                                         return err;
1270                         }
1271
1272                         /* set tx antenna config */
1273                         put32(c, ctlr->rfcfg.txantmask & 7);
1274                         if((err = cmd(ctlr, 152, c, 4)) != nil)
1275                                 return err;
1276                 }
1277         }
1278
1279         return nil;
1280 }
1281
1282 static char*
1283 loadfirmware1(Ctlr *ctlr, u32int dst, uchar *data, int size)
1284 {
1285         uchar *dma;
1286         char *err;
1287
1288         dma = mallocalign(size, 16, 0, 0);
1289         if(dma == nil)
1290                 return "no memory for dma";
1291         memmove(dma, data, size);
1292         coherence();
1293         if((err = niclock(ctlr)) != 0){
1294                 free(dma);
1295                 return err;
1296         }
1297         csr32w(ctlr, FhTxConfig + 9*32, 0);
1298         csr32w(ctlr, FhSramAddr + 9*4, dst);
1299         csr32w(ctlr, FhTfbdCtrl0 + 9*8, PCIWADDR(dma));
1300         csr32w(ctlr, FhTfbdCtrl1 + 9*8, size);
1301         csr32w(ctlr, FhTxBufStatus + 9*32,
1302                 (1<<FhTxBufStatusTbNumShift) |
1303                 (1<<FhTxBufStatusTbIdxShift) |
1304                 FhTxBufStatusTfbdValid);
1305         csr32w(ctlr, FhTxConfig + 9*32, FhTxConfigDmaEna | FhTxConfigCirqHostEndTfd);
1306         nicunlock(ctlr);
1307         if(irqwait(ctlr, Ifhtx|Ierr, 5000) != Ifhtx){
1308                 free(dma);
1309                 return "dma error / timeout";
1310         }
1311         free(dma);
1312         return 0;
1313 }
1314
1315 static char*
1316 boot(Ctlr *ctlr)
1317 {
1318         int i, n, size;
1319         uchar *p, *dma;
1320         FWImage *fw;
1321         char *err;
1322
1323         fw = ctlr->fw;
1324
1325         if(fw->boot.text.size == 0){
1326                 if(ctlr->calib.done == 0){
1327                         if((err = loadfirmware1(ctlr, 0x00000000, fw->init.text.data, fw->init.text.size)) != nil)
1328                                 return err;
1329                         if((err = loadfirmware1(ctlr, 0x00800000, fw->init.data.data, fw->init.data.size)) != nil)
1330                                 return err;
1331                         csr32w(ctlr, Reset, 0);
1332                         if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive)
1333                                 return "init firmware boot failed";
1334                         if((err = postboot(ctlr)) != nil)
1335                                 return err;
1336                         if((err = reset(ctlr)) != nil)
1337                                 return err;
1338                 }
1339                 if((err = loadfirmware1(ctlr, 0x00000000, fw->main.text.data, fw->main.text.size)) != nil)
1340                         return err;
1341                 if((err = loadfirmware1(ctlr, 0x00800000, fw->main.data.data, fw->main.data.size)) != nil)
1342                         return err;
1343                 csr32w(ctlr, Reset, 0);
1344                 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive)
1345                         return "main firmware boot failed";
1346                 return postboot(ctlr);
1347         }
1348
1349         size = ROUND(fw->init.data.size, 16) + ROUND(fw->init.text.size, 16);
1350         dma = mallocalign(size, 16, 0, 0);
1351         if(dma == nil)
1352                 return "no memory for dma";
1353
1354         if((err = niclock(ctlr)) != nil){
1355                 free(dma);
1356                 return err;
1357         }
1358
1359         p = dma;
1360         memmove(p, fw->init.data.data, fw->init.data.size);
1361         coherence();
1362         prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
1363         prphwrite(ctlr, BsmDramDataSize, fw->init.data.size);
1364         p += ROUND(fw->init.data.size, 16);
1365         memmove(p, fw->init.text.data, fw->init.text.size);
1366         coherence();
1367         prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
1368         prphwrite(ctlr, BsmDramTextSize, fw->init.text.size);
1369
1370         nicunlock(ctlr);
1371         if((err = niclock(ctlr)) != nil){
1372                 free(dma);
1373                 return err;
1374         }
1375
1376         p = fw->boot.text.data;
1377         n = fw->boot.text.size/4;
1378         for(i=0; i<n; i++, p += 4)
1379                 prphwrite(ctlr, BsmSramBase+i*4, get32(p));
1380
1381         prphwrite(ctlr, BsmWrMemSrc, 0);
1382         prphwrite(ctlr, BsmWrMemDst, 0);
1383         prphwrite(ctlr, BsmWrDwCount, n);
1384
1385         prphwrite(ctlr, BsmWrCtrl, 1<<31);
1386
1387         for(i=0; i<1000; i++){
1388                 if((prphread(ctlr, BsmWrCtrl) & (1<<31)) == 0)
1389                         break;
1390                 delay(10);
1391         }
1392         if(i == 1000){
1393                 nicunlock(ctlr);
1394                 free(dma);
1395                 return "bootcode timeout";
1396         }
1397
1398         prphwrite(ctlr, BsmWrCtrl, 1<<30);
1399         nicunlock(ctlr);
1400
1401         csr32w(ctlr, Reset, 0);
1402         if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
1403                 free(dma);
1404                 return "init firmware boot failed";
1405         }
1406         free(dma);
1407
1408         size = ROUND(fw->main.data.size, 16) + ROUND(fw->main.text.size, 16);
1409         dma = mallocalign(size, 16, 0, 0);
1410         if(dma == nil)
1411                 return "no memory for dma";
1412         if((err = niclock(ctlr)) != nil){
1413                 free(dma);
1414                 return err;
1415         }
1416         p = dma;
1417         memmove(p, fw->main.data.data, fw->main.data.size);
1418         coherence();
1419         prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4);
1420         prphwrite(ctlr, BsmDramDataSize, fw->main.data.size);
1421         p += ROUND(fw->main.data.size, 16);
1422         memmove(p, fw->main.text.data, fw->main.text.size);
1423         coherence();
1424         prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
1425         prphwrite(ctlr, BsmDramTextSize, fw->main.text.size | (1<<31));
1426         nicunlock(ctlr);
1427
1428         if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
1429                 free(dma);
1430                 return "main firmware boot failed";
1431         }
1432         free(dma);
1433         return postboot(ctlr);
1434 }
1435
1436 static int
1437 txqready(void *arg)
1438 {
1439         TXQ *q = arg;
1440         return q->n < Ntx;
1441 }
1442
1443 static char*
1444 qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
1445 {
1446         uchar *d, *c;
1447         TXQ *q;
1448
1449         assert(qid < nelem(ctlr->tx));
1450         assert(size <= Tcmdsize-4);
1451
1452         ilock(ctlr);
1453         q = &ctlr->tx[qid];
1454         while(!ctlr->broken && q->n >= Ntx){
1455                 iunlock(ctlr);
1456                 qlock(q);
1457                 if(!waserror()){
1458                         tsleep(q, txqready, q, 10);
1459                         poperror();
1460                 }
1461                 qunlock(q);
1462                 ilock(ctlr);
1463         }
1464         if(ctlr->broken){
1465                 iunlock(ctlr);
1466                 return "qcmd: broken";
1467         }
1468         q->n++;
1469
1470         q->lastcmd = code;
1471         q->b[q->i] = block;
1472         c = q->c + q->i * Tcmdsize;
1473         d = q->d + q->i * Tdscsize;
1474
1475         /* build command */
1476         c[0] = code;
1477         c[1] = 0;       /* flags */
1478         c[2] = q->i;
1479         c[3] = qid;
1480
1481         if(size > 0)
1482                 memmove(c+4, data, size);
1483
1484         size += 4;
1485
1486         /* build descriptor */
1487         *d++ = 0;
1488         *d++ = 0;
1489         *d++ = 0;
1490         *d++ = 1 + (block != nil); /* nsegs */
1491         put32(d, PCIWADDR(c));  d += 4;
1492         put16(d, size << 4); d += 2;
1493         if(block != nil){
1494                 put32(d, PCIWADDR(block->rp)); d += 4;
1495                 put16(d, BLEN(block) << 4);
1496         }
1497
1498         coherence();
1499
1500         q->i = (q->i+1) % Ntx;
1501         csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i);
1502
1503         iunlock(ctlr);
1504
1505         return nil;
1506 }
1507
1508 static int
1509 txqempty(void *arg)
1510 {
1511         TXQ *q = arg;
1512         return q->n == 0;
1513 }
1514
1515 static char*
1516 flushq(Ctlr *ctlr, uint qid)
1517 {
1518         TXQ *q;
1519         int i;
1520
1521         q = &ctlr->tx[qid];
1522         qlock(q);
1523         for(i = 0; i < 200 && !ctlr->broken; i++){
1524                 if(txqempty(q)){
1525                         qunlock(q);
1526                         return nil;
1527                 }
1528                 if(!waserror()){
1529                         tsleep(q, txqempty, q, 10);
1530                         poperror();
1531                 }
1532         }
1533         qunlock(q);
1534         if(ctlr->broken)
1535                 return "flushq: broken";
1536         return "flushq: timeout";
1537 }
1538
1539 static char*
1540 cmd(Ctlr *ctlr, uint code, uchar *data, int size)
1541 {
1542         char *err;
1543
1544         if(0) print("cmd %ud\n", code);
1545         if((err = qcmd(ctlr, 4, code, data, size, nil)) != nil)
1546                 return err;
1547         return flushq(ctlr, 4);
1548 }
1549
1550 static void
1551 setled(Ctlr *ctlr, int which, int on, int off)
1552 {
1553         uchar c[8];
1554
1555         csr32w(ctlr, Led, csr32r(ctlr, Led) & ~LedBsmCtrl);
1556
1557         memset(c, 0, sizeof(c));
1558         put32(c, 10000);
1559         c[4] = which;
1560         c[5] = on;
1561         c[6] = off;
1562         cmd(ctlr, 72, c, sizeof(c));
1563 }
1564
1565 static void
1566 addnode(Ctlr *ctlr, uchar id, uchar *addr)
1567 {
1568         uchar c[Tcmdsize], *p;
1569
1570         memset(p = c, 0, sizeof(c));
1571         *p++ = 0;       /* control (1 = update) */
1572         p += 3;         /* reserved */
1573         memmove(p, addr, 6);
1574         p += 6;
1575         p += 2;         /* reserved */
1576         *p++ = id;      /* node id */
1577         p++;            /* flags */
1578         p += 2;         /* reserved */
1579         p += 2;         /* kflags */
1580         p++;            /* tcs2 */
1581         p++;            /* reserved */
1582         p += 5*2;       /* ttak */
1583         p++;            /* kid */
1584         p++;            /* reserved */
1585         p += 16;        /* key */
1586         if(ctlr->type != Type4965){
1587                 p += 8;         /* tcs */
1588                 p += 8;         /* rxmic */
1589                 p += 8;         /* txmic */
1590         }
1591         p += 4;         /* htflags */
1592         p += 4;         /* mask */
1593         p += 2;         /* disable tid */
1594         p += 2;         /* reserved */
1595         p++;            /* add ba tid */
1596         p++;            /* del ba tid */
1597         p += 2;         /* add ba ssn */
1598         p += 4;         /* reserved */
1599         cmd(ctlr, 24, c, p - c);
1600 }
1601
1602 void
1603 rxon(Ether *edev, Wnode *bss)
1604 {
1605         uchar c[Tcmdsize], *p;
1606         int filter, flags;
1607         Ctlr *ctlr;
1608         char *err;
1609
1610         ctlr = edev->ctlr;
1611         filter = FilterMulticast | FilterBeacon;
1612         if(ctlr->prom){
1613                 filter |= FilterPromisc;
1614                 bss = nil;
1615         }
1616         if(bss != nil){
1617                 ctlr->channel = bss->channel;
1618                 memmove(ctlr->bssid, bss->bssid, Eaddrlen);
1619                 ctlr->aid = bss->aid;
1620                 if(ctlr->aid != 0){
1621                         filter |= FilterBSS;
1622                         filter &= ~FilterBeacon;
1623                         ctlr->bssnodeid = -1;
1624                 } else
1625                         ctlr->bcastnodeid = -1;
1626         } else {
1627                 memmove(ctlr->bssid, edev->bcast, Eaddrlen);
1628                 ctlr->aid = 0;
1629                 ctlr->bcastnodeid = -1;
1630                 ctlr->bssnodeid = -1;
1631         }
1632         flags = RFlagTSF | RFlagCTSToSelf | RFlag24Ghz | RFlagAuto;
1633
1634         if(0) print("rxon: bssid %E, aid %x, channel %d, filter %x, flags %x\n",
1635                 ctlr->bssid, ctlr->aid, ctlr->channel, filter, flags);
1636
1637         memset(p = c, 0, sizeof(c));
1638         memmove(p, edev->ea, 6); p += 8;        /* myaddr */
1639         memmove(p, ctlr->bssid, 6); p += 8;     /* bssid */
1640         memmove(p, edev->ea, 6); p += 8;        /* wlap */
1641         *p++ = 3;                               /* mode (STA) */
1642         *p++ = 0;                               /* air (?) */
1643         /* rxchain */
1644         put16(p, ((ctlr->rfcfg.rxantmask & 7)<<1) | (2<<10) | (2<<12));
1645         p += 2;
1646         *p++ = 0xff;                            /* ofdm mask (not yet negotiated) */
1647         *p++ = 0x0f;                            /* cck mask (not yet negotiated) */
1648         put16(p, ctlr->aid & 0x3fff);
1649         p += 2;                                 /* aid */
1650         put32(p, flags);
1651         p += 4;
1652         put32(p, filter);
1653         p += 4;
1654         *p++ = ctlr->channel;
1655         p++;                                    /* reserved */
1656         *p++ = 0xff;                            /* ht single mask */
1657         *p++ = 0xff;                            /* ht dual mask */
1658         if(ctlr->type != Type4965){
1659                 *p++ = 0xff;                    /* ht triple mask */
1660                 p++;                            /* reserved */
1661                 put16(p, 0); p += 2;            /* acquisition */
1662                 p += 2;                         /* reserved */
1663         }
1664         if((err = cmd(ctlr, 16, c, p - c)) != nil){
1665                 print("rxon error: %s\n", err);
1666                 return;
1667         }
1668
1669         if(ctlr->bcastnodeid == -1){
1670                 ctlr->bcastnodeid = (ctlr->type != Type4965) ? 15 : 31;
1671                 addnode(ctlr, ctlr->bcastnodeid, edev->bcast);
1672         }
1673         if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){
1674                 ctlr->bssnodeid = 0;
1675                 addnode(ctlr, ctlr->bssnodeid, bss->bssid);
1676         }
1677 }
1678
1679 static struct ratetab {
1680         uchar   rate;
1681         uchar   plcp;
1682         uchar   flags;
1683 } ratetab[] = {
1684         {   2,  10, RFlagCCK },
1685         {   4,  20, RFlagCCK },
1686         {  11,  55, RFlagCCK },
1687         {  22, 110, RFlagCCK },
1688         {  12, 0xd, 0 },
1689         {  18, 0xf, 0 },
1690         {  24, 0x5, 0 },
1691         {  36, 0x7, 0 },
1692         {  48, 0x9, 0 },
1693         {  72, 0xb, 0 },
1694         {  96, 0x1, 0 },
1695         { 108, 0x3, 0 },
1696         { 120, 0x3, 0 }
1697 };
1698
1699 enum {
1700         TFlagNeedProtection     = 1<<0,
1701         TFlagNeedRTS            = 1<<1,
1702         TFlagNeedCTS            = 1<<2,
1703         TFlagNeedACK            = 1<<3,
1704         TFlagLinkq              = 1<<4,
1705         TFlagImmBa              = 1<<6,
1706         TFlagFullTxOp           = 1<<7,
1707         TFlagBtDis              = 1<<12,
1708         TFlagAutoSeq            = 1<<13,
1709         TFlagMoreFrag           = 1<<14,
1710         TFlagInsertTs           = 1<<16,
1711         TFlagNeedPadding        = 1<<20,
1712 };
1713
1714 static void
1715 transmit(Wifi *wifi, Wnode *wn, Block *b)
1716 {
1717         uchar c[Tcmdsize], *p;
1718         Ether *edev;
1719         Ctlr *ctlr;
1720         Wifipkt *w;
1721         int flags, nodeid, rate;
1722
1723         w = (Wifipkt*)b->rp;
1724         edev = wifi->ether;
1725         ctlr = edev->ctlr;
1726
1727         qlock(ctlr);
1728         if(ctlr->attached == 0 || ctlr->broken){
1729                 qunlock(ctlr);
1730                 freeb(b);
1731                 return;
1732         }
1733
1734         if(ctlr->prom == 0)
1735         if(wn->aid != ctlr->aid
1736         || wn->channel != ctlr->channel
1737         || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0)
1738                 rxon(edev, wn);
1739
1740         rate = 0;
1741         flags = 0;
1742         nodeid = ctlr->bcastnodeid;
1743         if((w->a1[0] & 1) == 0){
1744                 flags |= TFlagNeedACK;
1745
1746                 if(BLEN(b) > 512-4)
1747                         flags |= TFlagNeedRTS;
1748
1749                 if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){
1750                         nodeid = ctlr->bssnodeid;
1751                         rate = 2; /* BUG: hardcode 11Mbit */
1752                 }
1753
1754                 if(flags & (TFlagNeedRTS|TFlagNeedCTS)){
1755                         if(ctlr->type != Type4965){
1756                                 flags &= ~(TFlagNeedRTS|TFlagNeedCTS);
1757                                 flags |= TFlagNeedProtection;
1758                         } else
1759                                 flags |= TFlagFullTxOp;
1760                 }
1761         }
1762         qunlock(ctlr);
1763
1764         memset(p = c, 0, sizeof(c));
1765         put16(p, BLEN(b));
1766         p += 2;
1767         p += 2;         /* lnext */
1768         put32(p, flags);
1769         p += 4;
1770         put32(p, 0);
1771         p += 4;         /* scratch */
1772
1773         *p++ = ratetab[rate].plcp;
1774         *p++ = ratetab[rate].flags | (1<<6);
1775
1776         p += 2;         /* xflags */
1777         *p++ = nodeid;
1778         *p++ = 0;       /* security */
1779         *p++ = 0;       /* linkq */
1780         p++;            /* reserved */
1781         p += 16;        /* key */
1782         p += 2;         /* fnext */
1783         p += 2;         /* reserved */
1784         put32(p, ~0);   /* lifetime */
1785         p += 4;
1786
1787         /* BUG: scratch ptr? not clear what this is for */
1788         put32(p, PCIWADDR(ctlr->kwpage));
1789         p += 5;
1790
1791         *p++ = 60;      /* rts ntries */
1792         *p++ = 15;      /* data ntries */
1793         *p++ = 0;       /* tid */
1794         put16(p, 0);    /* timeout */
1795         p += 2;
1796         p += 2;         /* txop */
1797         qcmd(ctlr, 0, 28, c, p - c, b);
1798 }
1799
1800 static long
1801 iwlctl(Ether *edev, void *buf, long n)
1802 {
1803         Ctlr *ctlr;
1804
1805         ctlr = edev->ctlr;
1806         if(ctlr->wifi)
1807                 return wifictl(ctlr->wifi, buf, n);
1808         return 0;
1809 }
1810
1811 static long
1812 iwlifstat(Ether *edev, void *buf, long n, ulong off)
1813 {
1814         Ctlr *ctlr;
1815
1816         ctlr = edev->ctlr;
1817         if(ctlr->wifi)
1818                 return wifistat(ctlr->wifi, buf, n, off);
1819         return 0;
1820 }
1821
1822 static void
1823 setoptions(Ether *edev)
1824 {
1825         Ctlr *ctlr;
1826         char buf[64];
1827         int i;
1828
1829         ctlr = edev->ctlr;
1830         for(i = 0; i < edev->nopt; i++){
1831                 if(strncmp(edev->opt[i], "essid=", 6) == 0){
1832                         snprint(buf, sizeof(buf), "essid %s", edev->opt[i]+6);
1833                         if(!waserror()){
1834                                 wifictl(ctlr->wifi, buf, strlen(buf));
1835                                 poperror();
1836                         }
1837                 }
1838         }
1839 }
1840
1841 static void
1842 iwlpromiscuous(void *arg, int on)
1843 {
1844         Ether *edev;
1845         Ctlr *ctlr;
1846
1847         edev = arg;
1848         ctlr = edev->ctlr;
1849         qlock(ctlr);
1850         ctlr->prom = on;
1851         rxon(edev, ctlr->wifi->bss);
1852         qunlock(ctlr);
1853 }
1854
1855 static void
1856 iwlproc(void *arg)
1857 {
1858         Ether *edev;
1859         Ctlr *ctlr;
1860         Wifi *wifi;
1861         Wnode *bss;
1862
1863         edev = arg;
1864         ctlr = edev->ctlr;
1865         wifi = ctlr->wifi;
1866
1867         for(;;){
1868                 /* hop channels for catching beacons */
1869                 setled(ctlr, 2, 5, 5);
1870                 while(wifi->bss == nil){
1871                         qlock(ctlr);
1872                         if(wifi->bss != nil){
1873                                 qunlock(ctlr);
1874                                 break;
1875                         }
1876                         ctlr->channel = 1 + ctlr->channel % 11;
1877                         ctlr->aid = 0;
1878                         rxon(edev, nil);
1879                         qunlock(ctlr);
1880                         tsleep(&up->sleep, return0, 0, 1000);
1881                 }
1882
1883                 /* wait for association */
1884                 setled(ctlr, 2, 10, 10);
1885                 while((bss = wifi->bss) != nil){
1886                         if(bss->aid != 0)
1887                                 break;
1888                         tsleep(&up->sleep, return0, 0, 1000);
1889                 }
1890
1891                 if(bss == nil)
1892                         continue;
1893
1894                 /* wait for disassociation */
1895                 edev->link = 1;
1896                 setled(ctlr, 2, 0, 1);
1897                 while((bss = wifi->bss) != nil){
1898                         if(bss->aid == 0)
1899                                 break;
1900                         tsleep(&up->sleep, return0, 0, 1000);
1901                 }
1902                 edev->link = 0;
1903         }
1904 }
1905
1906 static void
1907 iwlattach(Ether *edev)
1908 {
1909         char name[32];
1910         FWImage *fw;
1911         Ctlr *ctlr;
1912         char *err;
1913
1914         ctlr = edev->ctlr;
1915         eqlock(ctlr);
1916         if(waserror()){
1917                 print("#l%d: %s\n", edev->ctlrno, up->errstr);
1918                 if(ctlr->power)
1919                         poweroff(ctlr);
1920                 qunlock(ctlr);
1921                 nexterror();
1922         }
1923         if(ctlr->attached == 0){
1924                 if((csr32r(ctlr, Gpc) & RfKill) == 0)
1925                         error("wifi disabled by switch");
1926
1927                 if(ctlr->wifi == nil)
1928                         ctlr->wifi = wifiattach(edev, transmit);
1929
1930                 if(ctlr->fw == nil){
1931                         fw = readfirmware(fwname[ctlr->type]);
1932                         print("#l%d: firmware: %s, rev %ux, build %ud, size %ux+%ux+%ux+%ux+%ux\n",
1933                                 edev->ctlrno,
1934                                 fwname[ctlr->type],
1935                                 fw->rev, fw->build,
1936                                 fw->main.text.size, fw->main.data.size,
1937                                 fw->init.text.size, fw->init.data.size,
1938                                 fw->boot.text.size);
1939                         ctlr->fw = fw;
1940                 }
1941
1942                 if((err = reset(ctlr)) != nil)
1943                         error(err);
1944                 if((err = boot(ctlr)) != nil)
1945                         error(err);
1946
1947                 ctlr->bcastnodeid = -1;
1948                 ctlr->bssnodeid = -1;
1949                 ctlr->channel = 1;
1950                 ctlr->aid = 0;
1951
1952                 setoptions(edev);
1953
1954                 snprint(name, sizeof(name), "#l%diwl", edev->ctlrno);
1955                 kproc(name, iwlproc, edev);
1956
1957                 ctlr->attached = 1;
1958         }
1959         qunlock(ctlr);
1960         poperror();
1961 }
1962
1963 static void
1964 receive(Ctlr *ctlr)
1965 {
1966         Block *b, *bb;
1967         uchar *d, *dd, *cc;
1968         RXQ *rx;
1969         TXQ *tx;
1970         uint hw;
1971
1972         rx = &ctlr->rx;
1973         if(ctlr->broken || rx->s == nil || rx->b == nil)
1974                 return;
1975         for(hw = get16(rx->s) % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){
1976                 uchar type, flags, idx, qid;
1977                 u32int len;
1978
1979                 b = rx->b[rx->i];
1980                 if(b == nil)
1981                         continue;
1982
1983                 d = b->rp;
1984                 len = get32(d); d += 4;
1985                 type = *d++;
1986                 flags = *d++;
1987                 USED(flags);
1988                 idx = *d++;
1989                 qid = *d++;
1990
1991                 if((qid & 0x80) == 0 && qid < nelem(ctlr->tx)){
1992                         tx = &ctlr->tx[qid];
1993                         if(tx->n > 0){
1994                                 bb = tx->b[idx];
1995                                 if(bb != nil){
1996                                         tx->b[idx] = nil;
1997                                         freeb(bb);
1998                                 }
1999                                 /* paranoia: clear tx descriptors */
2000                                 dd = tx->d + idx*Tdscsize;
2001                                 cc = tx->c + idx*Tcmdsize;
2002                                 memset(dd, 0, Tdscsize);
2003                                 memset(cc, 0, Tcmdsize);
2004                                 tx->n--;
2005
2006                                 wakeup(tx);
2007                         }
2008                 }
2009
2010                 len &= 0x3fff;
2011                 if(len < 4 || type == 0)
2012                         continue;
2013
2014                 len -= 4;
2015                 switch(type){
2016                 case 1:         /* microcontroller ready */
2017                         setfwinfo(ctlr, d, len);
2018                         break;
2019                 case 24:        /* add node done */
2020                         break;
2021                 case 28:        /* tx done */
2022                         break;
2023                 case 102:       /* calibration result (Type5000 only) */
2024                         if(len < 4)
2025                                 break;
2026                         idx = d[0];
2027                         if(idx >= nelem(ctlr->calib.cmd))
2028                                 break;
2029                         if(rbplant(ctlr, rx->i) < 0)
2030                                 break;
2031                         if(ctlr->calib.cmd[idx] != nil)
2032                                 freeb(ctlr->calib.cmd[idx]);
2033                         b->rp = d;
2034                         b->wp = d + len;
2035                         ctlr->calib.cmd[idx] = b;
2036                         continue;
2037                 case 103:       /* calibration done (Type5000 only) */
2038                         ctlr->calib.done = 1;
2039                         break;
2040                 case 130:       /* start scan */
2041                         break;
2042                 case 132:       /* stop scan */
2043                         break;
2044                 case 156:       /* rx statistics */
2045                         break;
2046                 case 157:       /* beacon statistics */
2047                         break;
2048                 case 161:       /* state changed */
2049                         break;
2050                 case 162:       /* beacon missed */
2051                         break;
2052                 case 192:       /* rx phy */
2053                         break;
2054                 case 195:       /* rx done */
2055                         if(d + 2 > b->lim)
2056                                 break;
2057                         d += d[1];
2058                         d += 56;
2059                 case 193:       /* mpdu rx done */
2060                         if(d + 4 > b->lim)
2061                                 break;
2062                         len = get16(d); d += 4;
2063                         if(d + len + 4 > b->lim)
2064                                 break;
2065                         if((get32(d + len) & 3) != 3)
2066                                 break;
2067                         if(ctlr->wifi == nil)
2068                                 break;
2069                         if(rbplant(ctlr, rx->i) < 0)
2070                                 break;
2071                         b->rp = d;
2072                         b->wp = d + len;
2073                         wifiiq(ctlr->wifi, b);
2074                         continue;
2075                 case 197:       /* rx compressed ba */
2076                         break;
2077                 }
2078                 /* paranoia: clear the descriptor */
2079                 memset(b->rp, 0, Rdscsize);
2080         }
2081         csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7);
2082 }
2083
2084 static void
2085 iwlinterrupt(Ureg*, void *arg)
2086 {
2087         u32int isr, fhisr;
2088         Ether *edev;
2089         Ctlr *ctlr;
2090
2091         edev = arg;
2092         ctlr = edev->ctlr;
2093         ilock(ctlr);
2094         csr32w(ctlr, Imr, 0);
2095         isr = csr32r(ctlr, Isr);
2096         fhisr = csr32r(ctlr, FhIsr);
2097         if(isr == 0xffffffff || (isr & 0xfffffff0) == 0xa5a5a5a0){
2098                 iunlock(ctlr);
2099                 return;
2100         }
2101         if(isr == 0 && fhisr == 0)
2102                 goto done;
2103         csr32w(ctlr, Isr, isr);
2104         csr32w(ctlr, FhIsr, fhisr);
2105         if((isr & (Iswrx | Ifhrx | Irxperiodic)) || (fhisr & Ifhrx))
2106                 receive(ctlr);
2107         if(isr & Ierr){
2108                 ctlr->broken = 1;
2109                 iprint("#l%d: fatal firmware error\n", edev->ctlrno);
2110                 dumpctlr(ctlr);
2111         }
2112         ctlr->wait.m |= isr;
2113         if(ctlr->wait.m & ctlr->wait.w){
2114                 ctlr->wait.r = ctlr->wait.m & ctlr->wait.w;
2115                 ctlr->wait.m &= ~ctlr->wait.r;
2116                 wakeup(&ctlr->wait);
2117         }
2118 done:
2119         csr32w(ctlr, Imr, ctlr->ie);
2120         iunlock(ctlr);
2121 }
2122
2123 static Ctlr *iwlhead, *iwltail;
2124
2125 static void
2126 iwlpci(void)
2127 {
2128         Pcidev *pdev;
2129         
2130         pdev = nil;
2131         while(pdev = pcimatch(pdev, 0, 0)) {
2132                 Ctlr *ctlr;
2133                 void *mem;
2134                 
2135                 if(pdev->ccrb != 2 || pdev->ccru != 0x80)
2136                         continue;
2137                 if(pdev->vid != 0x8086)
2138                         continue;
2139
2140                 switch(pdev->did){
2141                 default:
2142                         continue;
2143                 case 0x4229:    /* WiFi Link 4965 */
2144                 case 0x4230:    /* WiFi Link 4965 */
2145                 case 0x4236:    /* WiFi Link 5300 AGN */
2146                 case 0x4237:    /* Wifi Link 5100 AGN */
2147                 case 0x422b:    /* Centrino Ultimate-N 6300 */
2148                         break;
2149                 }
2150
2151                 /* Clear device-specific "PCI retry timeout" register (41h). */
2152                 if(pcicfgr8(pdev, 0x41) != 0)
2153                         pcicfgw8(pdev, 0x41, 0);
2154
2155                 /* Clear interrupt disable bit. Hardware bug workaround. */
2156                 if(pdev->pcr & 0x400){
2157                         pdev->pcr &= ~0x400;
2158                         pcicfgw16(pdev, PciPCR, pdev->pcr);
2159                 }
2160
2161                 pcisetbme(pdev);
2162                 pcisetpms(pdev, 0);
2163
2164                 ctlr = malloc(sizeof(Ctlr));
2165                 if(ctlr == nil) {
2166                         print("iwl: unable to alloc Ctlr\n");
2167                         continue;
2168                 }
2169                 ctlr->port = pdev->mem[0].bar & ~0x0F;
2170                 mem = vmap(pdev->mem[0].bar & ~0x0F, pdev->mem[0].size);
2171                 if(mem == nil) {
2172                         print("iwl: can't map %8.8luX\n", pdev->mem[0].bar);
2173                         free(ctlr);
2174                         continue;
2175                 }
2176                 ctlr->nic = mem;
2177                 ctlr->pdev = pdev;
2178                 ctlr->type = (csr32r(ctlr, Rev) >> 4) & 0xF;
2179
2180                 if(fwname[ctlr->type] == nil){
2181                         print("iwl: unsupported controller type %d\n", ctlr->type);
2182                         vunmap(mem, pdev->mem[0].size);
2183                         free(ctlr);
2184                         continue;
2185                 }
2186
2187                 if(iwlhead != nil)
2188                         iwltail->link = ctlr;
2189                 else
2190                         iwlhead = ctlr;
2191                 iwltail = ctlr;
2192         }
2193 }
2194
2195 static int
2196 iwlpnp(Ether* edev)
2197 {
2198         Ctlr *ctlr;
2199         
2200         if(iwlhead == nil)
2201                 iwlpci();
2202 again:
2203         for(ctlr = iwlhead; ctlr != nil; ctlr = ctlr->link){
2204                 if(ctlr->active)
2205                         continue;
2206                 if(edev->port == 0 || edev->port == ctlr->port){
2207                         ctlr->active = 1;
2208                         break;
2209                 }
2210         }
2211
2212         if(ctlr == nil)
2213                 return -1;
2214
2215         edev->ctlr = ctlr;
2216         edev->port = ctlr->port;
2217         edev->irq = ctlr->pdev->intl;
2218         edev->tbdf = ctlr->pdev->tbdf;
2219         edev->arg = edev;
2220         edev->interrupt = iwlinterrupt;
2221         edev->attach = iwlattach;
2222         edev->ifstat = iwlifstat;
2223         edev->ctl = iwlctl;
2224         edev->promiscuous = iwlpromiscuous;
2225         edev->multicast = nil;
2226         edev->mbps = 10;
2227
2228         if(iwlinit(edev) < 0){
2229                 edev->ctlr = nil;
2230                 goto again;
2231         }
2232         
2233         return 0;
2234 }
2235
2236 void
2237 etheriwllink(void)
2238 {
2239         addethercard("iwl", iwlpnp);
2240 }