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