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