1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8 #include "../port/netif.h"
9
10 #include "etherif.h"
11 #include "wifi.h"
12
13 enum {
14 Nrxlog = 6,
15 Nrx = 1<<Nrxlog,
16 Ntx = 256,
17
18 Rbufsize = 3*1024,
19 Rdscsize = 8,
20
21 Tdscsize = 64,
22 Tcmdsize = 128,
23 };
24
25 /* registers */
26 enum {
27 Cfg = 0x000,
28 AlmMb = 1<<8,
29 AlmMm = 1<<9,
30 SkuMrc = 1<<10,
31 RevD = 1<<11,
32 TypeB = 1<<12,
33 Isr = 0x008,
34 Imr = 0x00c,
35 Ialive = 1<<0,
36 Iwakeup = 1<<1,
37 Iswrx = 1<<3,
38 Irftoggled = 1<<7,
39 Iswerr = 1<<25,
40 Ifhtx = 1<<27,
41 Ihwerr = 1<<29,
42 Ifhrx = 1<<31,
43 Ierr = Iswerr | Ihwerr,
44 Idefmask = Ierr | Ifhtx | Ifhrx | Ialive | Iwakeup | Iswrx | Irftoggled,
45 FhIsr = 0x010,
46 GpioIn = 0x018,
47 Reset = 0x020,
48 Nevo = 1<<0,
49 SW = 1<<7,
50 MasterDisabled = 1<<8,
51 StopMaster = 1<<9,
52
53 Gpc = 0x024,
54 MacAccessEna = 1<<0,
55 MacClockReady = 1<<0,
56 InitDone = 1<<2,
57 MacAccessReq = 1<<3,
58 NicSleep = 1<<4,
59 RfKill = 1<<27,
60 Eeprom = 0x02c,
61 EepromGp = 0x030,
62
63 UcodeGp1Clr = 0x05c,
64 UcodeGp1RfKill = 1<<1,
65 UcodeGp1CmdBlocked = 1<<2,
66 UcodeGp2 = 0x060,
67
68 GioChicken = 0x100,
69 L1AnoL0Srx = 1<<23,
70 AnaPll = 0x20c,
71 Init = 1<<24,
72
73 PrphWaddr = 0x444,
74 PrphRaddr = 0x448,
75 PrphWdata = 0x44c,
76 PrphRdata = 0x450,
77 HbusTargWptr = 0x460,
78 };
79
80 /*
81 * Flow-Handler registers.
82 */
83 enum {
84 FhCbbcCtrl = 0x940,
85 FhCbbcBase = 0x944,
86 FhRxConfig = 0xc00,
87 FhRxConfigDmaEna = 1<<31,
88 FhRxConfigRdrbdEna = 1<<29,
89 FhRxConfigWrstatusEna = 1<<27,
90 FhRxConfigMaxfrag = 1<<24,
91 FhRxConfigIrqDstHost = 1<<12,
92
93 FhRxConfigNrdbShift = 20,
94 FhRxConfigIrqRbthShift = 4,
95 FhRxBase = 0xc04,
96 FhRxWptr = 0xc20,
97 FhRxRptrAddr = 0xc24,
98 FhRssrTbl = 0xcc0,
99 FhRxStatus = 0xcc4,
100 FhTxConfig = 0xd00, // +q*32
101 FhTxBase = 0xe80,
102 FhMsgConfig = 0xe88,
103 FhTxStatus = 0xe90,
104 };
105
106 /*
107 * NIC internal memory offsets.
108 */
109 enum {
110 AlmSchedMode = 0x2e00,
111 AlmSchedArastat = 0x2e04,
112 AlmSchedTxfact = 0x2e10,
113 AlmSchedTxf4mf = 0x2e14,
114 AlmSchedTxf5mf = 0x2e20,
115 AlmSchedBP1 = 0x2e2c,
116 AlmSchedBP2 = 0x2e30,
117 ApmgClkEna = 0x3004,
118 ApmgClkDis = 0x3008,
119 DmaClkRqt = 1<<9,
120 BsmClkRqt = 1<<11,
121 ApmgPs = 0x300c,
122 PwrSrcVMain = 0<<24,
123 PwrSrcMask = 3<<24,
124
125 ApmgPciStt = 0x3010,
126
127 BsmWrCtrl = 0x3400,
128 BsmWrMemSrc = 0x3404,
129 BsmWrMemDst = 0x3408,
130 BsmWrDwCount = 0x340c,
131 BsmDramTextAddr = 0x3490,
132 BsmDramTextSize = 0x3494,
133 BsmDramDataAddr = 0x3498,
134 BsmDramDataSize = 0x349c,
135 BsmSramBase = 0x3800,
136 };
137
138 enum {
139 FilterPromisc = 1<<0,
140 FilterCtl = 1<<1,
141 FilterMulticast = 1<<2,
142 FilterNoDecrypt = 1<<3,
143 FilterBSS = 1<<5,
144 };
145
146 enum {
147 RFlag24Ghz = 1<<0,
148 RFlagCCK = 1<<1,
149 RFlagAuto = 1<<2,
150 RFlagShSlot = 1<<4,
151 RFlagShPreamble = 1<<5,
152 RFlagNoDiversity = 1<<7,
153 RFlagAntennaA = 1<<8,
154 RFlagAntennaB = 1<<9,
155 RFlagTSF = 1<<15,
156 };
157
158 typedef struct FWSect FWSect;
159 typedef struct FWImage FWImage;
160
161 typedef struct TXQ TXQ;
162 typedef struct RXQ RXQ;
163
164 typedef struct Shared Shared;
165 typedef struct Sample Sample;
166 typedef struct Powergrp Powergrp;
167
168 typedef struct Ctlr Ctlr;
169
170 struct FWSect
171 {
172 uchar *data;
173 uint size;
174 };
175
176 struct FWImage
177 {
178 struct {
179 FWSect text;
180 FWSect data;
181 } init, main, boot;
182
183 uint version;
184 uchar data[];
185 };
186
187 struct TXQ
188 {
189 uint n;
190 uint i;
191 Block **b;
192 uchar *d;
193 uchar *c;
194
195 uint lastcmd;
196
197 Rendez;
198 QLock;
199 };
200
201 struct RXQ
202 {
203 uint i;
204 Block **b;
205 u32int *p;
206 };
207
208 struct Shared
209 {
210 u32int txbase[8];
211 u32int next;
212 u32int reserved[2];
213 };
214
215 struct Sample
216 {
217 uchar index;
218 char power;
219 };
220
221 struct Powergrp
222 {
223 uchar chan;
224 char maxpwr;
225 short temp;
226 Sample samples[5];
227 };
228
229 struct Ctlr {
230 Lock;
231 QLock;
232
233 Ctlr *link;
234 Pcidev *pdev;
235 Wifi *wifi;
236
237 int port;
238 int power;
239 int active;
240 int broken;
241 int attached;
242
243 int temp;
244 u32int ie;
245 u32int *nic;
246
247 /* assigned node ids in hardware node table or -1 if unassigned */
248 int bcastnodeid;
249 int bssnodeid;
250
251 /* current receiver settings */
252 uchar bssid[Eaddrlen];
253 int channel;
254 int prom;
255 int aid;
256
257 RXQ rx;
258 TXQ tx[8];
259
260 struct {
261 Rendez;
262 u32int m;
263 u32int w;
264 } wait;
265
266 struct {
267 uchar cap;
268 u16int rev;
269 uchar type;
270
271 char regdom[4+1];
272
273 Powergrp pwrgrps[5];
274 } eeprom;
275
276 char maxpwr[256];
277
278 Shared *shared;
279
280 FWImage *fw;
281 };
282
283 static void setled(Ctlr *ctlr, int which, int on, int off);
284
285 #define csr32r(c, r) (*((c)->nic+((r)/4)))
286 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
287
288 static uint
get32(uchar * p)289 get32(uchar *p){
290 return *((u32int*)p);
291 }
292 static uint
get16(uchar * p)293 get16(uchar *p)
294 {
295 return *((u16int*)p);
296 }
297 static void
put32(uchar * p,uint v)298 put32(uchar *p, uint v){
299 *((u32int*)p) = v;
300 }
301 static void
put16(uchar * p,uint v)302 put16(uchar *p, uint v){
303 *((u16int*)p) = v;
304 };
305
306 static char*
niclock(Ctlr * ctlr)307 niclock(Ctlr *ctlr)
308 {
309 int i;
310
311 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq);
312 for(i=0; i<1000; i++){
313 if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna)
314 return 0;
315 delay(10);
316 }
317 return "niclock: timeout";
318 }
319
320 static void
nicunlock(Ctlr * ctlr)321 nicunlock(Ctlr *ctlr)
322 {
323 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq);
324 }
325
326 static u32int
prphread(Ctlr * ctlr,uint off)327 prphread(Ctlr *ctlr, uint off)
328 {
329 csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off);
330 coherence();
331 return csr32r(ctlr, PrphRdata);
332 }
333 static void
prphwrite(Ctlr * ctlr,uint off,u32int data)334 prphwrite(Ctlr *ctlr, uint off, u32int data)
335 {
336 csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off);
337 coherence();
338 csr32w(ctlr, PrphWdata, data);
339 }
340
341 static char*
eepromread(Ctlr * ctlr,void * data,int count,uint off)342 eepromread(Ctlr *ctlr, void *data, int count, uint off)
343 {
344 uchar *out = data;
345 char *err;
346 u32int w = 0;
347 int i;
348
349 if((err = niclock(ctlr)) != nil)
350 return err;
351
352 for(; count > 0; count -= 2, off++){
353 csr32w(ctlr, Eeprom, off << 2);
354 csr32w(ctlr, Eeprom, csr32r(ctlr, Eeprom) & ~(1<<1));
355
356 for(i = 0; i < 10; i++){
357 w = csr32r(ctlr, Eeprom);
358 if(w & 1)
359 break;
360 delay(5);
361 }
362 if(i == 10)
363 break;
364 *out++ = w >> 16;
365 if(count > 1)
366 *out++ = w >> 24;
367 }
368 nicunlock(ctlr);
369
370 if(count > 0)
371 return "eeprompread: timeout";
372 return nil;
373 }
374
375 static char*
clockwait(Ctlr * ctlr)376 clockwait(Ctlr *ctlr)
377 {
378 int i;
379
380 /* Set "initialization complete" bit. */
381 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone);
382 for(i=0; i<2500; i++){
383 if(csr32r(ctlr, Gpc) & MacClockReady)
384 return nil;
385 delay(10);
386 }
387 return "clockwait: timeout";
388 }
389
390 static char*
poweron(Ctlr * ctlr)391 poweron(Ctlr *ctlr)
392 {
393 char *err;
394
395 if(ctlr->power)
396 return nil;
397
398 csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | Init);
399 /* Disable L0s. */
400 csr32w(ctlr, GioChicken, csr32r(ctlr, GioChicken) | L1AnoL0Srx);
401
402 if((err = clockwait(ctlr)) != nil)
403 return err;
404
405 if((err = niclock(ctlr)) != nil)
406 return err;
407
408 prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt);
409 delay(20);
410
411 /* Disable L1. */
412 prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11));
413
414 nicunlock(ctlr);
415
416 ctlr->power = 1;
417
418 return nil;
419 }
420
421 static void
poweroff(Ctlr * ctlr)422 poweroff(Ctlr *ctlr)
423 {
424 int i, j;
425
426 csr32w(ctlr, Reset, Nevo);
427
428 /* Disable interrupts. */
429 csr32w(ctlr, Imr, 0);
430 csr32w(ctlr, Isr, ~0);
431 csr32w(ctlr, FhIsr, ~0);
432
433 if(niclock(ctlr) == nil){
434 /* Stop TX scheduler. */
435 prphwrite(ctlr, AlmSchedMode, 0);
436 prphwrite(ctlr, AlmSchedTxfact, 0);
437
438 /* Stop all DMA channels */
439 for(i = 0; i < 6; i++){
440 csr32w(ctlr, FhTxConfig + i*32, 0);
441 for(j = 0; j < 100; j++){
442 if((csr32r(ctlr, FhTxStatus) & (0x1010000<<i)) == (0x1010000<<i))
443 break;
444 delay(10);
445 }
446 }
447 nicunlock(ctlr);
448 }
449
450 /* Stop RX ring. */
451 if(niclock(ctlr) == nil){
452 csr32w(ctlr, FhRxConfig, 0);
453 for(j = 0; j < 100; j++){
454 if(csr32r(ctlr, FhRxStatus) & (1<<24))
455 break;
456 delay(10);
457 }
458 nicunlock(ctlr);
459 }
460
461 if(niclock(ctlr) == nil){
462 prphwrite(ctlr, ApmgClkDis, DmaClkRqt);
463 nicunlock(ctlr);
464 }
465 delay(5);
466
467 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | StopMaster);
468
469 if((csr32r(ctlr, Gpc) & (7<<24)) != (4<<24)){
470 for(j = 0; j < 100; j++){
471 if(csr32r(ctlr, Reset) & MasterDisabled)
472 break;
473 delay(10);
474 }
475 }
476
477 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | SW);
478
479 ctlr->power = 0;
480 }
481
482 static struct {
483 u32int addr; /* offset in EEPROM */
484 u8int nchan;
485 u8int chan[14];
486 } bands[5] = {
487 { 0x63, 14,
488 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 } },
489 { 0x72, 13,
490 { 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 } },
491 { 0x80, 12,
492 { 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 } },
493 { 0x8d, 11,
494 { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 } },
495 { 0x99, 6,
496 { 145, 149, 153, 157, 161, 165 } }
497 };
498
499 static int
wpiinit(Ether * edev)500 wpiinit(Ether *edev)
501 {
502 Ctlr *ctlr;
503 char *err;
504 uchar b[64];
505 int i, j;
506 Powergrp *g;
507
508 ctlr = edev->ctlr;
509 if((err = poweron(ctlr)) != nil)
510 goto Err;
511 if((csr32r(ctlr, EepromGp) & 0x6) == 0){
512 err = "bad rom signature";
513 goto Err;
514 }
515 /* Clear HW ownership of EEPROM. */
516 csr32w(ctlr, EepromGp, csr32r(ctlr, EepromGp) & ~0x180);
517
518 if((err = eepromread(ctlr, b, 1, 0x45)) != nil)
519 goto Err;
520 ctlr->eeprom.cap = b[0];
521 if((err = eepromread(ctlr, b, 2, 0x35)) != nil)
522 goto Err;
523 ctlr->eeprom.rev = get16(b);
524 if((err = eepromread(ctlr, b, 1, 0x4a)) != nil)
525 goto Err;
526 ctlr->eeprom.type = b[0];
527 if((err = eepromread(ctlr, b, 4, 0x60)) != nil)
528 goto Err;
529 strncpy(ctlr->eeprom.regdom, (char*)b, 4);
530 ctlr->eeprom.regdom[4] = '\0';
531
532 print("wpi: %X %X %X %s\n", ctlr->eeprom.cap, ctlr->eeprom.rev, ctlr->eeprom.type, ctlr->eeprom.regdom);
533
534 if((err = eepromread(ctlr, b, 6, 0x15)) != nil)
535 goto Err;
536 memmove(edev->ea, b, Eaddrlen);
537
538 memset(ctlr->maxpwr, 0, sizeof(ctlr->maxpwr));
539 for(i = 0; i < nelem(bands); i++){
540 if((err = eepromread(ctlr, b, 2*bands[i].nchan, bands[i].addr)) != nil)
541 goto Err;
542 for(j = 0; j < bands[i].nchan; j++){
543 if(!(b[j*2] & 1))
544 continue;
545 ctlr->maxpwr[bands[i].chan[j]] = b[j*2+1];
546 }
547 }
548
549 for(i = 0; i < nelem(ctlr->eeprom.pwrgrps); i++){
550 if((err = eepromread(ctlr, b, 64, 0x100 + i*32)) != nil)
551 goto Err;
552 g = &ctlr->eeprom.pwrgrps[i];
553 g->maxpwr = b[60];
554 g->chan = b[61];
555 g->temp = get16(b+62);
556 for(j = 0; j < 5; j++){
557 g->samples[j].index = b[j*4];
558 g->samples[j].power = b[j*4+1];
559 }
560 }
561
562 poweroff(ctlr);
563 return 0;
564 Err:
565 print("wpiinit: %s\n", err);
566 poweroff(ctlr);
567 return -1;
568 }
569
570 static char*
crackfw(FWImage * i,uchar * data,uint size)571 crackfw(FWImage *i, uchar *data, uint size)
572 {
573 uchar *p, *e;
574
575 memset(i, 0, sizeof(*i));
576 if(size < 4*6){
577 Tooshort:
578 return "firmware image too short";
579 }
580 p = data;
581 e = p + size;
582 i->version = get32(p); p += 4;
583 i->main.text.size = get32(p); p += 4;
584 i->main.data.size = get32(p); p += 4;
585 i->init.text.size = get32(p); p += 4;
586 i->init.data.size = get32(p); p += 4;
587 i->boot.text.size = get32(p); p += 4;
588 i->main.text.data = p; p += i->main.text.size;
589 i->main.data.data = p; p += i->main.data.size;
590 i->init.text.data = p; p += i->init.text.size;
591 i->init.data.data = p; p += i->init.data.size;
592 i->boot.text.data = p; p += i->boot.text.size;
593 if(p > e)
594 goto Tooshort;
595 return nil;
596 }
597
598 static FWImage*
readfirmware(void)599 readfirmware(void)
600 {
601 uchar dirbuf[sizeof(Dir)+100], *data;
602 char *err;
603 FWImage *fw;
604 int n, r;
605 Chan *c;
606 Dir d;
607
608 if(!iseve())
609 error(Eperm);
610 if(!waserror()){
611 c = namec("/boot/wpi-3945abg", Aopen, OREAD, 0);
612 poperror();
613 }else
614 c = namec("/lib/firmware/wpi-3945abg", Aopen, OREAD, 0);
615 if(waserror()){
616 cclose(c);
617 nexterror();
618 }
619 n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf);
620 if(n <= 0)
621 error("can't stat firmware");
622 convM2D(dirbuf, n, &d, nil);
623 fw = smalloc(sizeof(*fw) + 16 + d.length);
624 data = (uchar*)(fw+1);
625 if(waserror()){
626 free(fw);
627 nexterror();
628 }
629 r = 0;
630 while(r < d.length){
631 n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r);
632 if(n <= 0)
633 break;
634 r += n;
635 }
636 if((err = crackfw(fw, data, r)) != nil)
637 error(err);
638 poperror();
639 poperror();
640 cclose(c);
641 return fw;
642 }
643
644 static int
gotirq(void * arg)645 gotirq(void *arg)
646 {
647 Ctlr *ctlr = arg;
648 return (ctlr->wait.m & ctlr->wait.w) != 0;
649 }
650
651 static u32int
irqwait(Ctlr * ctlr,u32int mask,int timeout)652 irqwait(Ctlr *ctlr, u32int mask, int timeout)
653 {
654 u32int r;
655
656 ilock(ctlr);
657 r = ctlr->wait.m & mask;
658 if(r == 0){
659 ctlr->wait.w = mask;
660 iunlock(ctlr);
661 if(!waserror()){
662 tsleep(&ctlr->wait, gotirq, ctlr, timeout);
663 poperror();
664 }
665 ilock(ctlr);
666 ctlr->wait.w = 0;
667 r = ctlr->wait.m & mask;
668 }
669 ctlr->wait.m &= ~r;
670 iunlock(ctlr);
671 return r;
672 }
673
674 static int
rbplant(Ctlr * ctlr,int i)675 rbplant(Ctlr *ctlr, int i)
676 {
677 Block *b;
678
679 b = iallocb(Rbufsize+127);
680 if(b == nil)
681 return -1;
682 b->rp = b->wp = (uchar*)((((uintptr)b->base+127)&~127));
683 memset(b->rp, 0, Rdscsize);
684 coherence();
685 ctlr->rx.b[i] = b;
686 ctlr->rx.p[i] = PCIWADDR(b->rp);
687 return 0;
688 }
689
690 static char*
initring(Ctlr * ctlr)691 initring(Ctlr *ctlr)
692 {
693 RXQ *rx;
694 TXQ *tx;
695 int i, q;
696
697 rx = &ctlr->rx;
698 if(rx->b == nil)
699 rx->b = malloc(sizeof(Block*) * Nrx);
700 if(rx->p == nil)
701 rx->p = mallocalign(sizeof(u32int) * Nrx, 16 * 1024, 0, 0);
702 if(rx->b == nil || rx->p == nil)
703 return "no memory for rx ring";
704 for(i = 0; i<Nrx; i++){
705 rx->p[i] = 0;
706 if(rx->b[i] != nil){
707 freeb(rx->b[i]);
708 rx->b[i] = nil;
709 }
710 if(rbplant(ctlr, i) < 0)
711 return "no memory for rx descriptors";
712 }
713 rx->i = 0;
714
715 if(ctlr->shared == nil)
716 ctlr->shared = mallocalign(4096, 4096, 0, 0);
717 if(ctlr->shared == nil)
718 return "no memory for shared buffer";
719 memset(ctlr->shared, 0, 4096);
720
721 for(q=0; q<nelem(ctlr->tx); q++){
722 tx = &ctlr->tx[q];
723 if(tx->b == nil)
724 tx->b = malloc(sizeof(Block*) * Ntx);
725 if(tx->d == nil)
726 tx->d = mallocalign(Tdscsize * Ntx, 16 * 1024, 0, 0);
727 if(tx->c == nil)
728 tx->c = mallocalign(Tcmdsize * Ntx, 4, 0, 0);
729 if(tx->b == nil || tx->d == nil || tx->c == nil)
730 return "no memory for tx ring";
731 memset(tx->d, 0, Tdscsize * Ntx);
732 memset(tx->c, 0, Tcmdsize * Ntx);
733 for(i=0; i<Ntx; i++){
734 if(tx->b[i] != nil){
735 freeb(tx->b[i]);
736 tx->b[i] = nil;
737 }
738 }
739 ctlr->shared->txbase[q] = PCIWADDR(tx->d);
740 tx->i = 0;
741 tx->n = 0;
742 tx->lastcmd = 0;
743 }
744 return nil;
745 }
746
747 static char*
reset(Ctlr * ctlr)748 reset(Ctlr *ctlr)
749 {
750 uchar rev;
751 char *err;
752 int i;
753
754 if(ctlr->power)
755 poweroff(ctlr);
756 if((err = initring(ctlr)) != nil)
757 return err;
758 if((err = poweron(ctlr)) != nil)
759 return err;
760
761 /* Select VMAIN power source. */
762 if((err = niclock(ctlr)) != nil)
763 return err;
764 prphwrite(ctlr, ApmgPs, (prphread(ctlr, ApmgPs) & ~PwrSrcMask) | PwrSrcVMain);
765 nicunlock(ctlr);
766 /* Spin until VMAIN gets selected. */
767 for(i = 0; i < 5000; i++){
768 if(csr32r(ctlr, GpioIn) & (1 << 9))
769 break;
770 delay(10);
771 }
772
773 /* Perform adapter initialization. */
774 rev = ctlr->pdev->rid;
775 if((rev & 0xc0) == 0x40)
776 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | AlmMb);
777 else if(!(rev & 0x80))
778 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | AlmMm);
779
780 if(ctlr->eeprom.cap == 0x80)
781 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | SkuMrc);
782
783 if((ctlr->eeprom.rev & 0xf0) == 0xd0)
784 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | RevD);
785 else
786 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) & ~RevD);
787
788 if(ctlr->eeprom.type > 1)
789 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | TypeB);
790
791 /* Initialize RX ring. */
792 if((err = niclock(ctlr)) != nil)
793 return err;
794
795 coherence();
796 csr32w(ctlr, FhRxBase, PCIWADDR(ctlr->rx.p));
797 csr32w(ctlr, FhRxRptrAddr, PCIWADDR(&ctlr->shared->next));
798 csr32w(ctlr, FhRxWptr, 0);
799 csr32w(ctlr, FhRxConfig,
800 FhRxConfigDmaEna |
801 FhRxConfigRdrbdEna |
802 FhRxConfigWrstatusEna |
803 FhRxConfigMaxfrag |
804 (Nrxlog << FhRxConfigNrdbShift) |
805 FhRxConfigIrqDstHost |
806 (1 << FhRxConfigIrqRbthShift));
807 USED(csr32r(ctlr, FhRssrTbl));
808 csr32w(ctlr, FhRxWptr, (Nrx-1) & ~7);
809 nicunlock(ctlr);
810
811 /* Initialize TX rings. */
812 if((err = niclock(ctlr)) != nil)
813 return err;
814 prphwrite(ctlr, AlmSchedMode, 2);
815 prphwrite(ctlr, AlmSchedArastat, 1);
816 prphwrite(ctlr, AlmSchedTxfact, 0x3f);
817 prphwrite(ctlr, AlmSchedBP1, 0x10000);
818 prphwrite(ctlr, AlmSchedBP2, 0x30002);
819 prphwrite(ctlr, AlmSchedTxf4mf, 4);
820 prphwrite(ctlr, AlmSchedTxf5mf, 5);
821 csr32w(ctlr, FhTxBase, PCIWADDR(ctlr->shared));
822 csr32w(ctlr, FhMsgConfig, 0xffff05a5);
823 for(i = 0; i < 6; i++){
824 csr32w(ctlr, FhCbbcCtrl+i*8, 0);
825 csr32w(ctlr, FhCbbcBase+i*8, 0);
826 csr32w(ctlr, FhTxConfig+i*32, 0x80200008);
827 }
828 nicunlock(ctlr);
829 USED(csr32r(ctlr, FhTxBase));
830
831 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
832 csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
833
834 ctlr->broken = 0;
835 ctlr->wait.m = 0;
836 ctlr->wait.w = 0;
837
838 ctlr->ie = Idefmask;
839 csr32w(ctlr, Imr, ctlr->ie);
840 csr32w(ctlr, Isr, ~0);
841
842 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
843 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
844
845 return nil;
846 }
847
848 static char*
849 postboot(Ctlr *);
850
851 static char*
boot(Ctlr * ctlr)852 boot(Ctlr *ctlr)
853 {
854 int i, n, size;
855 uchar *dma, *p;
856 FWImage *fw;
857 char *err;
858
859 fw = ctlr->fw;
860 /* 16 byte padding may not be necessary. */
861 size = ROUND(fw->init.data.size, 16) + ROUND(fw->init.text.size, 16);
862 dma = mallocalign(size, 16, 0, 0);
863 if(dma == nil)
864 return "no memory for dma";
865
866 if((err = niclock(ctlr)) != nil){
867 free(dma);
868 return err;
869 }
870
871 p = dma;
872 memmove(p, fw->init.data.data, fw->init.data.size);
873 coherence();
874 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p));
875 prphwrite(ctlr, BsmDramDataSize, fw->init.data.size);
876 p += ROUND(fw->init.data.size, 16);
877 memmove(p, fw->init.text.data, fw->init.text.size);
878 coherence();
879 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p));
880 prphwrite(ctlr, BsmDramTextSize, fw->init.text.size);
881
882 nicunlock(ctlr);
883 if((err = niclock(ctlr)) != nil){
884 free(dma);
885 return err;
886 }
887
888 /* Copy microcode image into NIC memory. */
889 p = fw->boot.text.data;
890 n = fw->boot.text.size/4;
891 for(i=0; i<n; i++, p += 4)
892 prphwrite(ctlr, BsmSramBase+i*4, get32(p));
893
894 prphwrite(ctlr, BsmWrMemSrc, 0);
895 prphwrite(ctlr, BsmWrMemDst, 0);
896 prphwrite(ctlr, BsmWrDwCount, n);
897
898 /* Start boot load now. */
899 prphwrite(ctlr, BsmWrCtrl, 1<<31);
900
901 /* Wait for transfer to complete. */
902 for(i=0; i<1000; i++){
903 if((prphread(ctlr, BsmWrCtrl) & (1<<31)) == 0)
904 break;
905 delay(10);
906 }
907 if(i == 1000){
908 nicunlock(ctlr);
909 free(dma);
910 return "bootcode timeout";
911 }
912
913 /* Enable boot after power up. */
914 prphwrite(ctlr, BsmWrCtrl, 1<<30);
915 nicunlock(ctlr);
916
917 /* Now press "execute". */
918 csr32w(ctlr, Reset, 0);
919
920 /* Wait at most one second for first alive notification. */
921 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
922 free(dma);
923 return "init firmware boot failed";
924 }
925 free(dma);
926
927 size = ROUND(fw->main.data.size, 16) + ROUND(fw->main.text.size, 16);
928 dma = mallocalign(size, 16, 0, 0);
929 if(dma == nil)
930 return "no memory for dma";
931 if((err = niclock(ctlr)) != nil){
932 free(dma);
933 return err;
934 }
935 p = dma;
936 memmove(p, fw->main.data.data, fw->main.data.size);
937 coherence();
938 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p));
939 prphwrite(ctlr, BsmDramDataSize, fw->main.data.size);
940 p += ROUND(fw->main.data.size, 16);
941 memmove(p, fw->main.text.data, fw->main.text.size);
942 coherence();
943 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p));
944 prphwrite(ctlr, BsmDramTextSize, fw->main.text.size | (1<<31));
945 nicunlock(ctlr);
946
947 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
948 free(dma);
949 return "main firmware boot failed";
950 }
951 free(dma);
952 return postboot(ctlr);
953 }
954
955 static int
txqready(void * arg)956 txqready(void *arg)
957 {
958 TXQ *q = arg;
959 return q->n < Ntx;
960 }
961
962 static char*
qcmd(Ctlr * ctlr,uint qid,uint code,uchar * data,int size,Block * block)963 qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
964 {
965 uchar *d, *c;
966 int pad;
967 TXQ *q;
968
969 assert(qid < nelem(ctlr->tx));
970 assert(size <= Tcmdsize-4);
971
972 ilock(ctlr);
973 q = &ctlr->tx[qid];
974 while(q->n >= Ntx && !ctlr->broken){
975 iunlock(ctlr);
976 qlock(q);
977 if(!waserror()){
978 tsleep(q, txqready, q, 10);
979 poperror();
980 }
981 qunlock(q);
982 ilock(ctlr);
983 }
984 if(ctlr->broken){
985 iunlock(ctlr);
986 return "qcmd: broken";
987 }
988 q->n++;
989
990 q->lastcmd = code;
991 q->b[q->i] = block;
992 c = q->c + q->i * Tcmdsize;
993 d = q->d + q->i * Tdscsize;
994
995 /* build command */
996 c[0] = code;
997 c[1] = 0; /* flags */
998 c[2] = q->i;
999 c[3] = qid;
1000
1001 if(size > 0)
1002 memmove(c+4, data, size);
1003 size += 4;
1004
1005 memset(d, 0, Tdscsize);
1006
1007 pad = size - 4;
1008 if(block != nil)
1009 pad += BLEN(block);
1010 pad = ((pad + 3) & ~3) - pad;
1011
1012 put32(d, (pad << 28) | ((1 + (block != nil)) << 24)), d += 4;
1013 put32(d, PCIWADDR(c)), d += 4;
1014 put32(d, size), d += 4;
1015
1016 if(block != nil){
1017 size = BLEN(block);
1018 put32(d, PCIWADDR(block->rp)), d += 4;
1019 put32(d, size), d += 4;
1020 }
1021
1022 USED(d);
1023
1024 coherence();
1025
1026 q->i = (q->i+1) % Ntx;
1027 csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i);
1028
1029 iunlock(ctlr);
1030
1031 return nil;
1032 }
1033
1034 static int
txqempty(void * arg)1035 txqempty(void *arg)
1036 {
1037 TXQ *q = arg;
1038 return q->n == 0;
1039 }
1040
1041 static char*
flushq(Ctlr * ctlr,uint qid)1042 flushq(Ctlr *ctlr, uint qid)
1043 {
1044 TXQ *q;
1045 int i;
1046
1047 q = &ctlr->tx[qid];
1048 qlock(q);
1049 for(i = 0; i < 200 && !ctlr->broken; i++){
1050 if(txqempty(q)){
1051 qunlock(q);
1052 return nil;
1053 }
1054 if(islo() && !waserror()){
1055 tsleep(q, txqempty, q, 10);
1056 poperror();
1057 }
1058 }
1059 qunlock(q);
1060 if(ctlr->broken)
1061 return "flushq: broken";
1062 return "flushq: timeout";
1063 }
1064
1065 static char*
cmd(Ctlr * ctlr,uint code,uchar * data,int size)1066 cmd(Ctlr *ctlr, uint code, uchar *data, int size)
1067 {
1068 char *err;
1069
1070 if((err = qcmd(ctlr, 4, code, data, size, nil)) != nil)
1071 return err;
1072 return flushq(ctlr, 4);
1073 }
1074
1075 static void
setled(Ctlr * ctlr,int which,int on,int off)1076 setled(Ctlr *ctlr, int which, int on, int off)
1077 {
1078 uchar c[8];
1079
1080 memset(c, 0, sizeof(c));
1081 put32(c, 10000);
1082 c[4] = which;
1083 c[5] = on;
1084 c[6] = off;
1085 cmd(ctlr, 72, c, sizeof(c));
1086 }
1087
1088 static char*
btcoex(Ctlr * ctlr)1089 btcoex(Ctlr *ctlr)
1090 {
1091 uchar c[Tcmdsize], *p;
1092
1093 /* configure bluetooth coexistance. */
1094 p = c;
1095 *p++ = 3; /* flags WPI_BT_COEX_MODE_4WIRE */
1096 *p++ = 30; /* lead time */
1097 *p++ = 5; /* max kill */
1098 *p++ = 0; /* reserved */
1099 put32(p, 0), p += 4; /* kill_ack */
1100 put32(p, 0), p += 4; /* kill_cts */
1101 return cmd(ctlr, 155, c, p-c);
1102 }
1103
1104 static char*
powermode(Ctlr * ctlr)1105 powermode(Ctlr *ctlr)
1106 {
1107 uchar c[Tcmdsize];
1108 int capoff, reg;
1109
1110 memset(c, 0, sizeof(c));
1111 capoff = pcicap(ctlr->pdev, PciCapPCIe);
1112 if(capoff >= 0){
1113 reg = pcicfgr8(ctlr->pdev, capoff+1);
1114 if((reg & 1) == 0) /* PCI_PCIE_LCR_ASPM_L0S */
1115 c[0] |= 1<<3; /* WPI_PS_PCI_PMGT */
1116 }
1117 return cmd(ctlr, 119, c, 4*(3+5));
1118 }
1119
1120 static char*
postboot(Ctlr * ctlr)1121 postboot(Ctlr *ctlr)
1122 {
1123 while((ctlr->temp = (int)csr32r(ctlr, UcodeGp2)) == 0)
1124 delay(10);
1125
1126 if(0){
1127 char *err;
1128
1129 if((err = btcoex(ctlr)) != nil)
1130 print("btcoex: %s\n", err);
1131 if((err = powermode(ctlr)) != nil)
1132 print("powermode: %s\n", err);
1133 }
1134
1135 return nil;
1136 }
1137
1138 static uchar wpirates[] = {
1139 0x80 | 12,
1140 0x80 | 18,
1141 0x80 | 24,
1142 0x80 | 36,
1143 0x80 | 48,
1144 0x80 | 72,
1145 0x80 | 96,
1146 0x80 | 108,
1147 0x80 | 2,
1148 0x80 | 4,
1149 0x80 | 11,
1150 0x80 | 22,
1151
1152 0
1153 };
1154
1155 static struct {
1156 uchar rate;
1157 uchar plcp;
1158 } ratetab[] = {
1159 { 12, 0xd },
1160 { 18, 0xf },
1161 { 24, 0x5 },
1162 { 36, 0x7 },
1163 { 48, 0x9 },
1164 { 72, 0xb },
1165 { 96, 0x1 },
1166 { 108, 0x3 },
1167 { 2, 10 },
1168 { 4, 20 },
1169 { 11, 55 },
1170 { 22, 110 },
1171 };
1172
1173 static u8int rfgain_2ghz[] = {
1174 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xbb, 0xbb, 0xbb,
1175 0xbb, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xd3, 0xd3, 0xb3, 0xb3, 0xb3,
1176 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x73, 0xeb, 0xeb, 0xeb,
1177 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xab, 0xab, 0xab, 0x8b,
1178 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xa3,
1179 0xa3, 0xa3, 0xa3, 0x83, 0x83, 0x83, 0x83, 0x63, 0x63, 0x63, 0x63,
1180 0x43, 0x43, 0x43, 0x43, 0x23, 0x23, 0x23, 0x23, 0x03, 0x03, 0x03,
1181 0x03
1182 };
1183
1184 static u8int dspgain_2ghz[] = {
1185 0x7f, 0x7f, 0x7f, 0x7f, 0x7d, 0x6e, 0x69, 0x62, 0x7d, 0x73, 0x6c,
1186 0x63, 0x77, 0x6f, 0x69, 0x61, 0x5c, 0x6a, 0x64, 0x78, 0x71, 0x6b,
1187 0x7d, 0x77, 0x70, 0x6a, 0x65, 0x61, 0x5b, 0x6b, 0x79, 0x73, 0x6d,
1188 0x7f, 0x79, 0x73, 0x6c, 0x66, 0x60, 0x5c, 0x6e, 0x68, 0x62, 0x74,
1189 0x7d, 0x77, 0x71, 0x6b, 0x65, 0x60, 0x71, 0x6a, 0x66, 0x5f, 0x71,
1190 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f,
1191 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66,
1192 0x5f
1193 };
1194
1195 static int
pwridx(Ctlr * ctlr,Powergrp * pwgr,int chan,int rate)1196 pwridx(Ctlr *ctlr, Powergrp *pwgr, int chan, int rate)
1197 {
1198 /* Fixed-point arithmetic division using a n-bit fractional part. */
1199 #define fdivround(a, b, n) \
1200 ((((1 << n) * (a)) / (b) + (1 << n) / 2) / (1 << n))
1201
1202 /* Linear interpolation. */
1203 #define interpolate(x, x1, y1, x2, y2, n) \
1204 ((y1) + fdivround(((x) - (x1)) * ((y2) - (y1)), (x2) - (x1), n))
1205
1206 int pwr;
1207 Sample *sample;
1208 int idx;
1209
1210 /* Default TX power is group maximum TX power minus 3dB. */
1211 pwr = pwgr->maxpwr / 2;
1212
1213 /* Decrease TX power for highest OFDM rates to reduce distortion. */
1214 switch(rate){
1215 case 5: /* WPI_RIDX_OFDM36 */
1216 pwr -= 0;
1217 break;
1218 case 6: /* WPI_RIDX_OFDM48 */
1219 pwr -=7;
1220 break;
1221 case 7: /* WPI_RIDX_OFDM54 */
1222 pwr -= 9;
1223 break;
1224 }
1225
1226 /* Never exceed the channel maximum allowed TX power. */
1227 pwr = MIN(pwr, ctlr->maxpwr[chan]);
1228
1229 /* Retrieve TX power index into gain tables from samples. */
1230 for(sample = pwgr->samples; sample < &pwgr->samples[3]; sample++)
1231 if(pwr > sample[1].power)
1232 break;
1233 /* Fixed-point linear interpolation using a 19-bit fractional part. */
1234 idx = interpolate(pwr, sample[0].power, sample[0].index,
1235 sample[1].power, sample[1].index, 19);
1236
1237 /*-
1238 * Adjust power index based on current temperature:
1239 * - if cooler than factory-calibrated: decrease output power
1240 * - if warmer than factory-calibrated: increase output power
1241 */
1242 idx -= (ctlr->temp - pwgr->temp) * 11 / 100;
1243
1244 /* Decrease TX power for CCK rates (-5dB). */
1245 if (rate >= 8)
1246 idx += 10;
1247
1248 /* Make sure idx stays in a valid range. */
1249 if (idx < 0)
1250 idx = 0;
1251 else if (idx >= nelem(rfgain_2ghz))
1252 idx = nelem(rfgain_2ghz)-1;
1253 return idx;
1254 #undef fdivround
1255 #undef interpolate
1256 }
1257
1258 static void
addnode(Ctlr * ctlr,uchar id,uchar * addr,int plcp,int antenna)1259 addnode(Ctlr *ctlr, uchar id, uchar *addr, int plcp, int antenna)
1260 {
1261 uchar c[Tcmdsize], *p;
1262
1263 memset(p = c, 0, sizeof(c));
1264 *p++ = 0; /* control (1 = update) */
1265 p += 3; /* reserved */
1266 memmove(p, addr, 6);
1267 p += 6;
1268 p += 2; /* reserved */
1269 *p++ = id; /* node id */
1270 p++; /* flags */
1271 p += 2; /* reserved */
1272 p += 2; /* kflags */
1273 p++; /* tcs2 */
1274 p++; /* reserved */
1275 p += 5*2; /* ttak */
1276 p += 2; /* reserved */
1277 p += 16; /* key */
1278 put32(p, 4); /* action (4 = set_rate) */
1279 p += 4;
1280 p += 4; /* mask */
1281 p += 2; /* tid */
1282 *p++ = plcp; /* plcp */
1283 *p++ = antenna; /* antenna */
1284 p++; /* add_imm */
1285 p++; /* del_imm */
1286 p++; /* add_imm_start */
1287 cmd(ctlr, 24, c, p - c);
1288 }
1289
1290 static void
rxon(Ether * edev,Wnode * bss)1291 rxon(Ether *edev, Wnode *bss)
1292 {
1293 uchar c[Tcmdsize], *p;
1294 int filter, flags, rate;
1295 Ctlr *ctlr;
1296 char *err;
1297 int idx;
1298
1299 ctlr = edev->ctlr;
1300 filter = FilterNoDecrypt | FilterMulticast;
1301 if(ctlr->prom){
1302 filter |= FilterPromisc;
1303 if(bss != nil)
1304 ctlr->channel = bss->channel;
1305 bss = nil;
1306 }
1307 flags = RFlagTSF | RFlag24Ghz | RFlagAuto;
1308 if(bss != nil){
1309 if(bss->cap & (1<<5))
1310 flags |= RFlagShPreamble;
1311 if(bss->cap & (1<<10))
1312 flags |= RFlagShSlot;
1313 ctlr->channel = bss->channel;
1314 memmove(ctlr->bssid, bss->bssid, Eaddrlen);
1315 ctlr->aid = bss->aid;
1316 if(ctlr->aid != 0){
1317 filter |= FilterBSS;
1318 ctlr->bssnodeid = -1;
1319 }else
1320 ctlr->bcastnodeid = -1;
1321 }else{
1322 memmove(ctlr->bssid, edev->bcast, Eaddrlen);
1323 ctlr->aid = 0;
1324 ctlr->bcastnodeid = -1;
1325 ctlr->bssnodeid = -1;
1326 }
1327
1328 if(ctlr->aid != 0)
1329 setled(ctlr, 2, 0, 1); /* on when associated */
1330 else if(memcmp(ctlr->bssid, edev->bcast, Eaddrlen) != 0)
1331 setled(ctlr, 2, 10, 10); /* slow blink when connecting */
1332 else
1333 setled(ctlr, 2, 5, 5); /* fast blink when scanning */
1334
1335 memset(p = c, 0, sizeof(c));
1336 memmove(p, edev->ea, 6); p += 8; /* myaddr */
1337 memmove(p, ctlr->bssid, 6); p += 16; /* bssid */
1338 *p++ = 3; /* mode (STA) */
1339 p += 3;
1340 *p++ = 0xff; /* ofdm mask (not yet negotiated) */
1341 *p++ = 0x0f; /* cck mask (not yet negotiated) */
1342 put16(p, ctlr->aid & 0x3fff); /* associd */
1343 p += 2;
1344 put32(p, flags);
1345 p += 4;
1346 put32(p, filter);
1347 p += 4;
1348 *p++ = ctlr->channel;
1349 p += 3;
1350
1351 if((err = cmd(ctlr, 16, c, p - c)) != nil){
1352 print("rxon: %s\n", err);
1353 return;
1354 }
1355
1356 if(ctlr->maxpwr[ctlr->channel] != 0){
1357 /* tx power */
1358 memset(p = c, 0, sizeof(c));
1359 *p++ = 1; /* band (0 = 5ghz) */
1360 p++; /* reserved */
1361 put16(p, ctlr->channel), p += 2;
1362 for(rate = 0; rate < nelem(ratetab); rate++){
1363 idx = pwridx(ctlr, &ctlr->eeprom.pwrgrps[0], ctlr->channel, rate);
1364 *p++ = ratetab[rate].plcp;
1365 *p++ = rfgain_2ghz[idx]; /* rf_gain */
1366 *p++ = dspgain_2ghz[idx]; /* dsp_gain */
1367 p++; /* reservd */
1368 }
1369 cmd(ctlr, 151, c, p - c);
1370 }
1371
1372 if(ctlr->bcastnodeid == -1){
1373 ctlr->bcastnodeid = 24;
1374 addnode(ctlr, ctlr->bcastnodeid, edev->bcast, ratetab[0].plcp, 3<<6);
1375 }
1376 if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){
1377 ctlr->bssnodeid = 0;
1378 addnode(ctlr, ctlr->bssnodeid, bss->bssid, ratetab[0].plcp, 3<<6);
1379 }
1380 }
1381
1382 enum {
1383 TFlagNeedRTS = 1<<1,
1384 TFlagNeedCTS = 1<<2,
1385 TFlagNeedACK = 1<<3,
1386 TFlagFullTxOp = 1<<7,
1387 TFlagBtDis = 1<<12,
1388 TFlagAutoSeq = 1<<13,
1389 TFlagInsertTs = 1<<16,
1390 };
1391
1392 static void
transmit(Wifi * wifi,Wnode * wn,Block * b)1393 transmit(Wifi *wifi, Wnode *wn, Block *b)
1394 {
1395 uchar c[Tcmdsize], *p;
1396 Ether *edev;
1397 Ctlr *ctlr;
1398 Wifipkt *w;
1399 int flags, nodeid, rate, timeout;
1400 char *err;
1401
1402 edev = wifi->ether;
1403 ctlr = edev->ctlr;
1404
1405 qlock(ctlr);
1406 if(ctlr->attached == 0 || ctlr->broken){
1407 qunlock(ctlr);
1408 freeb(b);
1409 return;
1410 }
1411
1412 if((wn->channel != ctlr->channel)
1413 || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0)))
1414 rxon(edev, wn);
1415
1416 if(b == nil){
1417 /* association note has no data to transmit */
1418 qunlock(ctlr);
1419 return;
1420 }
1421
1422 flags = 0;
1423 timeout = 3;
1424 nodeid = ctlr->bcastnodeid;
1425 p = wn->minrate;
1426 w = (Wifipkt*)b->rp;
1427 if((w->a1[0] & 1) == 0){
1428 flags |= TFlagNeedACK;
1429
1430 if(BLEN(b) > 512-4)
1431 flags |= TFlagNeedRTS|TFlagFullTxOp;
1432
1433 if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){
1434 timeout = 0;
1435 nodeid = ctlr->bssnodeid;
1436 p = wn->actrate;
1437 }
1438 }
1439 qunlock(ctlr);
1440
1441 rate = 0;
1442 if(p >= wpirates && p < &wpirates[nelem(ratetab)])
1443 rate = p - wpirates;
1444
1445 memset(p = c, 0, sizeof(c));
1446 put16(p, BLEN(b)), p += 2;
1447 put16(p, 0), p += 2; /* lnext */
1448 put32(p, flags), p += 4;
1449 *p++ = ratetab[rate].plcp;
1450 *p++ = nodeid;
1451 *p++ = 0; /* tid */
1452 *p++ = 0; /* security */
1453 p += 16+8; /* key/iv */
1454 put32(p, 0), p += 4; /* fnext */
1455 put32(p, 0xffffffff), p += 4; /* livetime infinite */
1456 *p++ = 0xff;
1457 *p++ = 0x0f;
1458 *p++ = 7;
1459 *p++ = 15;
1460 put16(p, timeout), p += 2;
1461 put16(p, 0), p += 2; /* txop */
1462
1463 if((err = qcmd(ctlr, 0, 28, c, p - c, b)) != nil){
1464 print("transmit: %s\n", err);
1465 freeb(b);
1466 }
1467 }
1468
1469 static long
wpictl(Ether * edev,void * buf,long n)1470 wpictl(Ether *edev, void *buf, long n)
1471 {
1472 Ctlr *ctlr;
1473
1474 ctlr = edev->ctlr;
1475 if(n >= 5 && memcmp(buf, "reset", 5) == 0){
1476 ctlr->broken = 1;
1477 return n;
1478 }
1479 if(ctlr->wifi)
1480 return wifictl(ctlr->wifi, buf, n);
1481 return 0;
1482 }
1483
1484 static long
wpiifstat(Ether * edev,void * buf,long n,ulong off)1485 wpiifstat(Ether *edev, void *buf, long n, ulong off)
1486 {
1487 Ctlr *ctlr;
1488
1489 ctlr = edev->ctlr;
1490 if(ctlr->wifi)
1491 return wifistat(ctlr->wifi, buf, n, off);
1492 return 0;
1493 }
1494
1495 static void
setoptions(Ether * edev)1496 setoptions(Ether *edev)
1497 {
1498 Ctlr *ctlr;
1499 int i;
1500
1501 ctlr = edev->ctlr;
1502 for(i = 0; i < edev->nopt; i++)
1503 wificfg(ctlr->wifi, edev->opt[i]);
1504 }
1505
1506 static void
wpipromiscuous(void * arg,int on)1507 wpipromiscuous(void *arg, int on)
1508 {
1509 Ether *edev;
1510 Ctlr *ctlr;
1511
1512 edev = arg;
1513 ctlr = edev->ctlr;
1514 qlock(ctlr);
1515 ctlr->prom = on;
1516 rxon(edev, ctlr->wifi->bss);
1517 qunlock(ctlr);
1518 }
1519
1520 static void
wpimulticast(void *,uchar *,int)1521 wpimulticast(void *, uchar*, int)
1522 {
1523 }
1524
1525 static void
wpirecover(void * arg)1526 wpirecover(void *arg)
1527 {
1528 Ether *edev;
1529 Ctlr *ctlr;
1530
1531 edev = arg;
1532 ctlr = edev->ctlr;
1533 while(waserror())
1534 ;
1535 for(;;){
1536 tsleep(&up->sleep, return0, 0, 4000);
1537
1538 qlock(ctlr);
1539 for(;;){
1540 if(ctlr->broken == 0)
1541 break;
1542
1543 if(ctlr->power)
1544 poweroff(ctlr);
1545
1546 if((csr32r(ctlr, Gpc) & RfKill) == 0)
1547 break;
1548
1549 if(reset(ctlr) != nil)
1550 break;
1551 if(boot(ctlr) != nil)
1552 break;
1553
1554 ctlr->bcastnodeid = -1;
1555 ctlr->bssnodeid = -1;
1556 ctlr->aid = 0;
1557 rxon(edev, ctlr->wifi->bss);
1558 break;
1559 }
1560 qunlock(ctlr);
1561 }
1562 }
1563
1564 static void
wpiattach(Ether * edev)1565 wpiattach(Ether *edev)
1566 {
1567 FWImage *fw;
1568 Ctlr *ctlr;
1569 char *err;
1570
1571 ctlr = edev->ctlr;
1572 qlock(ctlr);
1573 if(waserror()){
1574 print("#l%d: %s\n", edev->ctlrno, up->errstr);
1575 if(ctlr->power)
1576 poweroff(ctlr);
1577 qunlock(ctlr);
1578 nexterror();
1579 }
1580 if(ctlr->attached == 0){
1581 if((csr32r(ctlr, Gpc) & RfKill) == 0)
1582 error("wifi disabled by switch");
1583
1584 if(ctlr->wifi == nil){
1585 ctlr->wifi = wifiattach(edev, transmit);
1586 ctlr->wifi->rates = wpirates;
1587 }
1588
1589 if(ctlr->fw == nil){
1590 fw = readfirmware();
1591 print("#l%d: firmware: %ux, size: %ux+%ux+%ux+%ux+%ux\n",
1592 edev->ctlrno, fw->version,
1593 fw->main.text.size, fw->main.data.size,
1594 fw->init.text.size, fw->init.data.size,
1595 fw->boot.text.size);
1596 ctlr->fw = fw;
1597 }
1598
1599 if((err = reset(ctlr)) != nil)
1600 error(err);
1601 if((err = boot(ctlr)) != nil)
1602 error(err);
1603
1604 ctlr->bcastnodeid = -1;
1605 ctlr->bssnodeid = -1;
1606 ctlr->channel = 1;
1607 ctlr->aid = 0;
1608
1609 setoptions(edev);
1610
1611 ctlr->attached = 1;
1612
1613 kproc("wpirecover", wpirecover, edev);
1614 }
1615 qunlock(ctlr);
1616 poperror();
1617 }
1618
1619 static void
receive(Ctlr * ctlr)1620 receive(Ctlr *ctlr)
1621 {
1622 Block *b, *bb;
1623 uchar *d;
1624 RXQ *rx;
1625 TXQ *tx;
1626 u32int hw;
1627
1628 rx = &ctlr->rx;
1629 if(ctlr->broken || ctlr->shared == nil || rx->b == nil)
1630 return;
1631
1632 bb = nil;
1633 for(hw = ctlr->shared->next % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){
1634 uchar type, flags, idx, qid;
1635 u32int len;
1636
1637 b = rx->b[rx->i];
1638 if(b == nil)
1639 continue;
1640
1641 d = b->rp;
1642 len = get32(d); d += 4;
1643 type = *d++;
1644 flags = *d++;
1645 idx = *d++;
1646 qid = *d++;
1647
1648 USED(len);
1649 USED(flags);
1650
1651 if(0) iprint("rxdesc[%d] type=%d len=%d idx=%d qid=%d\n", rx->i, type, len, idx, qid);
1652
1653 if(bb != nil){
1654 freeb(bb);
1655 bb = nil;
1656 }
1657 if((qid & 0x80) == 0 && qid < nelem(ctlr->tx)){
1658 tx = &ctlr->tx[qid];
1659 if(tx->n > 0){
1660 bb = tx->b[idx];
1661 tx->b[idx] = nil;
1662 tx->n--;
1663 wakeup(tx);
1664 }
1665 }
1666
1667 switch(type){
1668 case 1: /* uc ready */
1669 break;
1670
1671 case 24: /* add node done */
1672 break;
1673
1674 case 27: /* rx done */
1675 if(d + 1 > b->lim)
1676 break;
1677 d += d[0];
1678 d += 8;
1679 if(d + 6 + 2 > b->lim){
1680 break;
1681 }
1682 len = get16(d+6);
1683 d += 8;
1684 if(d + len + 4 > b->lim){
1685 break;
1686 }
1687 if((get32(d + len) & 3) != 3){
1688 break;
1689 }
1690 if(ctlr->wifi == nil)
1691 break;
1692 if(rbplant(ctlr, rx->i) < 0)
1693 break;
1694 b->rp = d;
1695 b->wp = d + len;
1696 wifiiq(ctlr->wifi, b);
1697 continue;
1698
1699 case 28: /* tx done */
1700 if(len <= 8 || d[8] == 1)
1701 break;
1702 wifitxfail(ctlr->wifi, bb);
1703 break;
1704
1705 case 130: /* start scan */
1706 break;
1707
1708 case 132: /* stop scan */
1709 break;
1710
1711 case 161: /* state change */
1712 break;
1713 }
1714 }
1715 csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7);
1716 if(bb != nil)
1717 freeb(bb);
1718 }
1719
1720 static void
wpiinterrupt(Ureg *,void * arg)1721 wpiinterrupt(Ureg*, void *arg)
1722 {
1723 u32int isr, fhisr;
1724 Ether *edev;
1725 Ctlr *ctlr;
1726
1727 edev = arg;
1728 ctlr = edev->ctlr;
1729 ilock(ctlr);
1730 csr32w(ctlr, Imr, 0);
1731 isr = csr32r(ctlr, Isr);
1732 fhisr = csr32r(ctlr, FhIsr);
1733 if(isr == 0xffffffff || (isr & 0xfffffff0) == 0xa5a5a5a0){
1734 iunlock(ctlr);
1735 return;
1736 }
1737 if(isr == 0 && fhisr == 0)
1738 goto done;
1739 csr32w(ctlr, Isr, isr);
1740 csr32w(ctlr, FhIsr, fhisr);
1741 if((isr & (Iswrx | Ifhrx)) || (fhisr & Ifhrx))
1742 receive(ctlr);
1743 if(isr & Ierr){
1744 ctlr->broken = 1;
1745 iprint("#l%d: fatal firmware error, lastcmd %ud\n", edev->ctlrno, ctlr->tx[4].lastcmd);
1746 }
1747 ctlr->wait.m |= isr;
1748 if(ctlr->wait.m & ctlr->wait.w)
1749 wakeup(&ctlr->wait);
1750 done:
1751 csr32w(ctlr, Imr, ctlr->ie);
1752 iunlock(ctlr);
1753 }
1754
1755 static void
wpishutdown(Ether * edev)1756 wpishutdown(Ether *edev)
1757 {
1758 Ctlr *ctlr;
1759
1760 ctlr = edev->ctlr;
1761 if(ctlr->power)
1762 poweroff(ctlr);
1763 ctlr->broken = 0;
1764 }
1765
1766 static Ctlr *wpihead, *wpitail;
1767
1768 static void
wpipci(void)1769 wpipci(void)
1770 {
1771 Pcidev *pdev;
1772
1773 pdev = nil;
1774 while(pdev = pcimatch(pdev, 0x8086, 0)){
1775 Ctlr *ctlr;
1776 void *mem;
1777 switch(pdev->did){
1778 default:
1779 continue;
1780 case 0x4227:
1781 break;
1782 }
1783
1784 /* Clear device-specific "PCI retry timeout" register (41h). */
1785 if(pcicfgr8(pdev, 0x41) != 0)
1786 pcicfgw8(pdev, 0x41, 0);
1787
1788 pcisetbme(pdev);
1789 pcisetpms(pdev, 0);
1790
1791 ctlr = malloc(sizeof(Ctlr));
1792 if(ctlr == nil) {
1793 print("wpi: unable to alloc Ctlr\n");
1794 continue;
1795 }
1796 ctlr->port = pdev->mem[0].bar & ~0x0F;
1797 mem = vmap(pdev->mem[0].bar & ~0x0F, pdev->mem[0].size);
1798 if(mem == nil) {
1799 print("wpi: can't map %8.8luX\n", pdev->mem[0].bar);
1800 free(ctlr);
1801 continue;
1802 }
1803 ctlr->nic = mem;
1804 ctlr->pdev = pdev;
1805
1806 if(wpihead != nil)
1807 wpitail->link = ctlr;
1808 else
1809 wpihead = ctlr;
1810 wpitail = ctlr;
1811 }
1812 }
1813
1814 static int
wpipnp(Ether * edev)1815 wpipnp(Ether *edev)
1816 {
1817 Ctlr *ctlr;
1818
1819 if(wpihead == nil)
1820 wpipci();
1821
1822 again:
1823 for(ctlr = wpihead; ctlr != nil; ctlr = ctlr->link){
1824 if(ctlr->active)
1825 continue;
1826 if(edev->port == 0 || edev->port == ctlr->port){
1827 ctlr->active = 1;
1828 break;
1829 }
1830 }
1831
1832 if(ctlr == nil)
1833 return -1;
1834
1835 edev->ctlr = ctlr;
1836 edev->port = ctlr->port;
1837 edev->irq = ctlr->pdev->intl;
1838 edev->tbdf = ctlr->pdev->tbdf;
1839 edev->arg = edev;
1840 edev->interrupt = wpiinterrupt;
1841 edev->attach = wpiattach;
1842 edev->ifstat = wpiifstat;
1843 edev->ctl = wpictl;
1844 edev->shutdown = wpishutdown;
1845 edev->promiscuous = wpipromiscuous;
1846 edev->multicast = wpimulticast;
1847 edev->mbps = 54;
1848
1849 if(wpiinit(edev) < 0){
1850 edev->ctlr = nil;
1851 goto again;
1852 }
1853
1854 return 0;
1855 }
1856
1857 void
etherwpilink(void)1858 etherwpilink(void)
1859 {
1860 addethercard("wpi", wpipnp);
1861 }
1862