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