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