xref: /plan9-contrib/sys/src/9/pc/etherwpi.c (revision 43f728cba48694b0a42c538a38fdf975a0ae5433)
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