2 #include "../port/lib.h"
7 #include "../port/pci.h"
8 #include "../port/error.h"
9 #include "../port/netif.h"
10 #include "../port/etherif.h"
11 #include "../port/wifi.h"
14 MaxQueue = 24*1024, /* total buffer is 2*MaxQueue: 48k at 22Mbit ≅ 20ms */
18 Ntxqmax = MaxQueue/1500,
48 Ierr = Iswerr | Ihwerr,
49 Idefmask = Ierr | Ifhtx | Ifhrx | Ialive | Iwakeup | Iswrx | Irftoggled,
55 MasterDisabled = 1<<8,
69 UcodeGp1RfKill = 1<<1,
70 UcodeGp1CmdBlocked = 1<<2,
86 * Flow-Handler registers.
92 FhRxConfigDmaEna = 1<<31,
93 FhRxConfigRdrbdEna = 1<<29,
94 FhRxConfigWrstatusEna = 1<<27,
95 FhRxConfigMaxfrag = 1<<24,
96 FhRxConfigIrqDstHost = 1<<12,
98 FhRxConfigNrdbShift = 20,
99 FhRxConfigIrqRbthShift = 4,
102 FhRxRptrAddr = 0xc24,
105 FhTxConfig = 0xd00, // +q*32
112 * NIC internal memory offsets.
115 AlmSchedMode = 0x2e00,
116 AlmSchedArastat = 0x2e04,
117 AlmSchedTxfact = 0x2e10,
118 AlmSchedTxf4mf = 0x2e14,
119 AlmSchedTxf5mf = 0x2e20,
120 AlmSchedBP1 = 0x2e2c,
121 AlmSchedBP2 = 0x2e30,
133 BsmWrMemSrc = 0x3404,
134 BsmWrMemDst = 0x3408,
135 BsmWrDwCount = 0x340c,
136 BsmDramTextAddr = 0x3490,
137 BsmDramTextSize = 0x3494,
138 BsmDramDataAddr = 0x3498,
139 BsmDramDataSize = 0x349c,
140 BsmSramBase = 0x3800,
144 FilterPromisc = 1<<0,
146 FilterMulticast = 1<<2,
147 FilterNoDecrypt = 1<<3,
156 RFlagShPreamble = 1<<5,
157 RFlagNoDiversity = 1<<7,
158 RFlagAntennaA = 1<<8,
159 RFlagAntennaB = 1<<9,
163 typedef struct FWSect FWSect;
164 typedef struct FWImage FWImage;
166 typedef struct TXQ TXQ;
167 typedef struct RXQ RXQ;
169 typedef struct Shared Shared;
170 typedef struct Sample Sample;
171 typedef struct Powergrp Powergrp;
173 typedef struct Ctlr Ctlr;
252 /* assigned node ids in hardware node table or -1 if unassigned */
256 /* current receiver settings */
257 uchar bssid[Eaddrlen];
288 static void setled(Ctlr *ctlr, int which, int on, int off);
290 #define csr32r(c, r) (*((c)->nic+((r)/4)))
291 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
295 return *((u32int*)p);
300 return *((u16int*)p);
303 put32(uchar *p, uint v){
307 put16(uchar *p, uint v){
316 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq);
317 for(i=0; i<1000; i++){
318 if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna)
322 return "niclock: timeout";
326 nicunlock(Ctlr *ctlr)
328 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq);
332 prphread(Ctlr *ctlr, uint off)
334 csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off);
336 return csr32r(ctlr, PrphRdata);
339 prphwrite(Ctlr *ctlr, uint off, u32int data)
341 csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off);
343 csr32w(ctlr, PrphWdata, data);
347 eepromread(Ctlr *ctlr, void *data, int count, uint off)
354 if((err = niclock(ctlr)) != nil)
357 for(; count > 0; count -= 2, off++){
358 csr32w(ctlr, Eeprom, off << 2);
359 csr32w(ctlr, Eeprom, csr32r(ctlr, Eeprom) & ~(1<<1));
361 for(i = 0; i < 10; i++){
362 w = csr32r(ctlr, Eeprom);
376 return "eeprompread: timeout";
381 clockwait(Ctlr *ctlr)
385 /* Set "initialization complete" bit. */
386 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone);
387 for(i=0; i<2500; i++){
388 if(csr32r(ctlr, Gpc) & MacClockReady)
392 return "clockwait: timeout";
403 csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | Init);
405 csr32w(ctlr, GioChicken, csr32r(ctlr, GioChicken) | L1AnoL0Srx);
407 if((err = clockwait(ctlr)) != nil)
410 if((err = niclock(ctlr)) != nil)
413 prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt);
417 prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11));
431 csr32w(ctlr, Reset, Nevo);
433 /* Disable interrupts. */
434 csr32w(ctlr, Imr, 0);
435 csr32w(ctlr, Isr, ~0);
436 csr32w(ctlr, FhIsr, ~0);
438 if(niclock(ctlr) == nil){
439 /* Stop TX scheduler. */
440 prphwrite(ctlr, AlmSchedMode, 0);
441 prphwrite(ctlr, AlmSchedTxfact, 0);
443 /* Stop all DMA channels */
444 for(i = 0; i < 6; i++){
445 csr32w(ctlr, FhTxConfig + i*32, 0);
446 for(j = 0; j < 100; j++){
447 if((csr32r(ctlr, FhTxStatus) & (0x1010000<<i)) == (0x1010000<<i))
456 if(niclock(ctlr) == nil){
457 csr32w(ctlr, FhRxConfig, 0);
458 for(j = 0; j < 100; j++){
459 if(csr32r(ctlr, FhRxStatus) & (1<<24))
466 if(niclock(ctlr) == nil){
467 prphwrite(ctlr, ApmgClkDis, DmaClkRqt);
472 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | StopMaster);
474 if((csr32r(ctlr, Gpc) & (7<<24)) != (4<<24)){
475 for(j = 0; j < 100; j++){
476 if(csr32r(ctlr, Reset) & MasterDisabled)
482 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | SW);
488 u32int addr; /* offset in EEPROM */
493 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 } },
495 { 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 } },
497 { 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 } },
499 { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 } },
501 { 145, 149, 153, 157, 161, 165 } }
514 if((err = poweron(ctlr)) != nil)
516 if((csr32r(ctlr, EepromGp) & 0x6) == 0){
517 err = "bad rom signature";
520 /* Clear HW ownership of EEPROM. */
521 csr32w(ctlr, EepromGp, csr32r(ctlr, EepromGp) & ~0x180);
523 if((err = eepromread(ctlr, b, 1, 0x45)) != nil)
525 ctlr->eeprom.cap = b[0];
526 if((err = eepromread(ctlr, b, 2, 0x35)) != nil)
528 ctlr->eeprom.rev = get16(b);
529 if((err = eepromread(ctlr, b, 1, 0x4a)) != nil)
531 ctlr->eeprom.type = b[0];
532 if((err = eepromread(ctlr, b, 4, 0x60)) != nil)
534 strncpy(ctlr->eeprom.regdom, (char*)b, 4);
535 ctlr->eeprom.regdom[4] = '\0';
537 print("wpi: %X %X %X %s\n", ctlr->eeprom.cap, ctlr->eeprom.rev, ctlr->eeprom.type, ctlr->eeprom.regdom);
539 if((err = eepromread(ctlr, b, 6, 0x15)) != nil)
541 memmove(edev->ea, b, Eaddrlen);
543 memset(ctlr->maxpwr, 0, sizeof(ctlr->maxpwr));
544 for(i = 0; i < nelem(bands); i++){
545 if((err = eepromread(ctlr, b, 2*bands[i].nchan, bands[i].addr)) != nil)
547 for(j = 0; j < bands[i].nchan; j++){
550 ctlr->maxpwr[bands[i].chan[j]] = b[j*2+1];
554 for(i = 0; i < nelem(ctlr->eeprom.pwrgrps); i++){
555 if((err = eepromread(ctlr, b, 64, 0x100 + i*32)) != nil)
557 g = &ctlr->eeprom.pwrgrps[i];
560 g->temp = get16(b+62);
561 for(j = 0; j < 5; j++){
562 g->samples[j].index = b[j*4];
563 g->samples[j].power = b[j*4+1];
570 print("wpiinit: %s\n", err);
576 crackfw(FWImage *i, uchar *data, uint size)
580 memset(i, 0, sizeof(*i));
583 return "firmware image too short";
587 i->version = get32(p); p += 4;
588 i->main.text.size = get32(p); p += 4;
589 i->main.data.size = get32(p); p += 4;
590 i->init.text.size = get32(p); p += 4;
591 i->init.data.size = get32(p); p += 4;
592 i->boot.text.size = get32(p); p += 4;
593 i->main.text.data = p; p += i->main.text.size;
594 i->main.data.data = p; p += i->main.data.size;
595 i->init.text.data = p; p += i->init.text.size;
596 i->init.data.data = p; p += i->init.data.size;
597 i->boot.text.data = p; p += i->boot.text.size;
606 uchar dirbuf[sizeof(Dir)+100], *data;
616 c = namec("/boot/wpi-3945abg", Aopen, OREAD, 0);
619 c = namec("/lib/firmware/wpi-3945abg", Aopen, OREAD, 0);
624 n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf);
626 error("can't stat firmware");
627 convM2D(dirbuf, n, &d, nil);
628 fw = smalloc(sizeof(*fw) + 16 + d.length);
629 data = (uchar*)(fw+1);
636 n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r);
641 if((err = crackfw(fw, data, r)) != nil)
653 return (ctlr->wait.m & ctlr->wait.w) != 0;
657 irqwait(Ctlr *ctlr, u32int mask, int timeout)
662 r = ctlr->wait.m & mask;
667 tsleep(&ctlr->wait, gotirq, ctlr, timeout);
672 r = ctlr->wait.m & mask;
680 rbplant(Ctlr *ctlr, int i)
684 b = iallocb(Rbufsize+127);
687 b->rp = b->wp = (uchar*)((((uintptr)b->base+127)&~127));
688 memset(b->rp, 0, Rdscsize);
691 ctlr->rx.p[i] = PCIWADDR(b->rp);
704 rx->b = malloc(sizeof(Block*) * Nrx);
706 rx->p = mallocalign(sizeof(u32int) * Nrx, 16 * 1024, 0, 0);
707 if(rx->b == nil || rx->p == nil)
708 return "no memory for rx ring";
709 for(i = 0; i<Nrx; i++){
715 if(rbplant(ctlr, i) < 0)
716 return "no memory for rx descriptors";
720 if(ctlr->shared == nil)
721 ctlr->shared = mallocalign(4096, 4096, 0, 0);
722 if(ctlr->shared == nil)
723 return "no memory for shared buffer";
724 memset(ctlr->shared, 0, 4096);
726 for(q=0; q<nelem(ctlr->tx); q++){
729 tx->b = malloc(sizeof(Block*) * Ntx);
731 tx->d = mallocalign(Tdscsize * Ntx, 16 * 1024, 0, 0);
733 tx->c = mallocalign(Tcmdsize * Ntx, 4, 0, 0);
734 if(tx->b == nil || tx->d == nil || tx->c == nil)
735 return "no memory for tx ring";
736 memset(tx->d, 0, Tdscsize * Ntx);
737 memset(tx->c, 0, Tcmdsize * Ntx);
738 for(i=0; i<Ntx; i++){
744 ctlr->shared->txbase[q] = PCIWADDR(tx->d);
761 if((err = initring(ctlr)) != nil)
763 if((err = poweron(ctlr)) != nil)
766 /* Select VMAIN power source. */
767 if((err = niclock(ctlr)) != nil)
769 prphwrite(ctlr, ApmgPs, (prphread(ctlr, ApmgPs) & ~PwrSrcMask) | PwrSrcVMain);
771 /* Spin until VMAIN gets selected. */
772 for(i = 0; i < 5000; i++){
773 if(csr32r(ctlr, GpioIn) & (1 << 9))
778 /* Perform adapter initialization. */
779 rev = ctlr->pdev->rid;
780 if((rev & 0xc0) == 0x40)
781 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | AlmMb);
782 else if(!(rev & 0x80))
783 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | AlmMm);
785 if(ctlr->eeprom.cap == 0x80)
786 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | SkuMrc);
788 if((ctlr->eeprom.rev & 0xf0) == 0xd0)
789 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | RevD);
791 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) & ~RevD);
793 if(ctlr->eeprom.type > 1)
794 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | TypeB);
796 /* Initialize RX ring. */
797 if((err = niclock(ctlr)) != nil)
801 csr32w(ctlr, FhRxBase, PCIWADDR(ctlr->rx.p));
802 csr32w(ctlr, FhRxRptrAddr, PCIWADDR(&ctlr->shared->next));
803 csr32w(ctlr, FhRxWptr, 0);
804 csr32w(ctlr, FhRxConfig,
807 FhRxConfigWrstatusEna |
809 (Nrxlog << FhRxConfigNrdbShift) |
810 FhRxConfigIrqDstHost |
811 (1 << FhRxConfigIrqRbthShift));
812 USED(csr32r(ctlr, FhRssrTbl));
813 csr32w(ctlr, FhRxWptr, (Nrx-1) & ~7);
816 /* Initialize TX rings. */
817 if((err = niclock(ctlr)) != nil)
819 prphwrite(ctlr, AlmSchedMode, 2);
820 prphwrite(ctlr, AlmSchedArastat, 1);
821 prphwrite(ctlr, AlmSchedTxfact, 0x3f);
822 prphwrite(ctlr, AlmSchedBP1, 0x10000);
823 prphwrite(ctlr, AlmSchedBP2, 0x30002);
824 prphwrite(ctlr, AlmSchedTxf4mf, 4);
825 prphwrite(ctlr, AlmSchedTxf5mf, 5);
826 csr32w(ctlr, FhTxBase, PCIWADDR(ctlr->shared));
827 csr32w(ctlr, FhMsgConfig, 0xffff05a5);
828 for(i = 0; i < 6; i++){
829 csr32w(ctlr, FhCbbcCtrl+i*8, 0);
830 csr32w(ctlr, FhCbbcBase+i*8, 0);
831 csr32w(ctlr, FhTxConfig+i*32, 0x80200008);
834 USED(csr32r(ctlr, FhTxBase));
836 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
837 csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
844 csr32w(ctlr, Imr, ctlr->ie);
845 csr32w(ctlr, Isr, ~0);
847 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
848 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
865 /* 16 byte padding may not be necessary. */
866 size = ROUND(fw->init.data.size, 16) + ROUND(fw->init.text.size, 16);
867 dma = mallocalign(size, 16, 0, 0);
869 return "no memory for dma";
871 if((err = niclock(ctlr)) != nil){
877 memmove(p, fw->init.data.data, fw->init.data.size);
879 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p));
880 prphwrite(ctlr, BsmDramDataSize, fw->init.data.size);
881 p += ROUND(fw->init.data.size, 16);
882 memmove(p, fw->init.text.data, fw->init.text.size);
884 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p));
885 prphwrite(ctlr, BsmDramTextSize, fw->init.text.size);
888 if((err = niclock(ctlr)) != nil){
893 /* Copy microcode image into NIC memory. */
894 p = fw->boot.text.data;
895 n = fw->boot.text.size/4;
896 for(i=0; i<n; i++, p += 4)
897 prphwrite(ctlr, BsmSramBase+i*4, get32(p));
899 prphwrite(ctlr, BsmWrMemSrc, 0);
900 prphwrite(ctlr, BsmWrMemDst, 0);
901 prphwrite(ctlr, BsmWrDwCount, n);
903 /* Start boot load now. */
904 prphwrite(ctlr, BsmWrCtrl, 1<<31);
906 /* Wait for transfer to complete. */
907 for(i=0; i<1000; i++){
908 if((prphread(ctlr, BsmWrCtrl) & (1<<31)) == 0)
915 return "bootcode timeout";
918 /* Enable boot after power up. */
919 prphwrite(ctlr, BsmWrCtrl, 1<<30);
922 /* Now press "execute". */
923 csr32w(ctlr, Reset, 0);
925 /* Wait at most one second for first alive notification. */
926 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
928 return "init firmware boot failed";
932 size = ROUND(fw->main.data.size, 16) + ROUND(fw->main.text.size, 16);
933 dma = mallocalign(size, 16, 0, 0);
935 return "no memory for dma";
936 if((err = niclock(ctlr)) != nil){
941 memmove(p, fw->main.data.data, fw->main.data.size);
943 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p));
944 prphwrite(ctlr, BsmDramDataSize, fw->main.data.size);
945 p += ROUND(fw->main.data.size, 16);
946 memmove(p, fw->main.text.data, fw->main.text.size);
948 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p));
949 prphwrite(ctlr, BsmDramTextSize, fw->main.text.size | (1<<31));
952 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
954 return "main firmware boot failed";
957 return postboot(ctlr);
964 return q->n < Ntxqmax;
968 qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
974 assert(qid < nelem(ctlr->tx));
975 assert(size <= Tcmdsize-4);
979 while(q->n >= Ntxqmax && !ctlr->broken){
983 tsleep(q, txqready, q, 5);
991 return "qcmd: broken";
997 c = q->c + q->i * Tcmdsize;
998 d = q->d + q->i * Tdscsize;
1002 c[1] = 0; /* flags */
1007 memmove(c+4, data, size);
1010 memset(d, 0, Tdscsize);
1015 pad = ((pad + 3) & ~3) - pad;
1017 put32(d, (pad << 28) | ((1 + (block != nil)) << 24)), d += 4;
1018 put32(d, PCIWADDR(c)), d += 4;
1019 put32(d, size), d += 4;
1023 put32(d, PCIWADDR(block->rp)), d += 4;
1024 put32(d, size), d += 4;
1031 q->i = (q->i+1) % Ntx;
1032 csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i);
1047 flushq(Ctlr *ctlr, uint qid)
1054 for(i = 0; i < 200 && !ctlr->broken; i++){
1059 if(islo() && !waserror()){
1060 tsleep(q, txqempty, q, 10);
1066 return "flushq: broken";
1067 return "flushq: timeout";
1071 cmd(Ctlr *ctlr, uint code, uchar *data, int size)
1075 if((err = qcmd(ctlr, 4, code, data, size, nil)) != nil)
1077 return flushq(ctlr, 4);
1081 setled(Ctlr *ctlr, int which, int on, int off)
1085 memset(c, 0, sizeof(c));
1090 cmd(ctlr, 72, c, sizeof(c));
1096 uchar c[Tcmdsize], *p;
1098 /* configure bluetooth coexistance. */
1100 *p++ = 3; /* flags WPI_BT_COEX_MODE_4WIRE */
1101 *p++ = 30; /* lead time */
1102 *p++ = 5; /* max kill */
1103 *p++ = 0; /* reserved */
1104 put32(p, 0), p += 4; /* kill_ack */
1105 put32(p, 0), p += 4; /* kill_cts */
1106 return cmd(ctlr, 155, c, p-c);
1110 powermode(Ctlr *ctlr)
1115 memset(c, 0, sizeof(c));
1116 capoff = pcicap(ctlr->pdev, PciCapPCIe);
1118 reg = pcicfgr8(ctlr->pdev, capoff+1);
1119 if((reg & 1) == 0) /* PCI_PCIE_LCR_ASPM_L0S */
1120 c[0] |= 1<<3; /* WPI_PS_PCI_PMGT */
1122 return cmd(ctlr, 119, c, 4*(3+5));
1126 postboot(Ctlr *ctlr)
1128 while((ctlr->temp = (int)csr32r(ctlr, UcodeGp2)) == 0)
1134 if((err = btcoex(ctlr)) != nil)
1135 print("btcoex: %s\n", err);
1136 if((err = powermode(ctlr)) != nil)
1137 print("powermode: %s\n", err);
1143 static uchar wpirates[] = {
1180 static u8int rfgain_2ghz[] = {
1181 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xbb, 0xbb, 0xbb,
1182 0xbb, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xd3, 0xd3, 0xb3, 0xb3, 0xb3,
1183 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x73, 0xeb, 0xeb, 0xeb,
1184 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xab, 0xab, 0xab, 0x8b,
1185 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xa3,
1186 0xa3, 0xa3, 0xa3, 0x83, 0x83, 0x83, 0x83, 0x63, 0x63, 0x63, 0x63,
1187 0x43, 0x43, 0x43, 0x43, 0x23, 0x23, 0x23, 0x23, 0x03, 0x03, 0x03,
1191 static u8int dspgain_2ghz[] = {
1192 0x7f, 0x7f, 0x7f, 0x7f, 0x7d, 0x6e, 0x69, 0x62, 0x7d, 0x73, 0x6c,
1193 0x63, 0x77, 0x6f, 0x69, 0x61, 0x5c, 0x6a, 0x64, 0x78, 0x71, 0x6b,
1194 0x7d, 0x77, 0x70, 0x6a, 0x65, 0x61, 0x5b, 0x6b, 0x79, 0x73, 0x6d,
1195 0x7f, 0x79, 0x73, 0x6c, 0x66, 0x60, 0x5c, 0x6e, 0x68, 0x62, 0x74,
1196 0x7d, 0x77, 0x71, 0x6b, 0x65, 0x60, 0x71, 0x6a, 0x66, 0x5f, 0x71,
1197 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f,
1198 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66,
1203 pwridx(Ctlr *ctlr, Powergrp *pwgr, int chan, int rate)
1205 /* Fixed-point arithmetic division using a n-bit fractional part. */
1206 #define fdivround(a, b, n) \
1207 ((((1 << n) * (a)) / (b) + (1 << n) / 2) / (1 << n))
1209 /* Linear interpolation. */
1210 #define interpolate(x, x1, y1, x2, y2, n) \
1211 ((y1) + fdivround(((x) - (x1)) * ((y2) - (y1)), (x2) - (x1), n))
1217 /* Default TX power is group maximum TX power minus 3dB. */
1218 pwr = pwgr->maxpwr / 2;
1220 /* Decrease TX power for highest OFDM rates to reduce distortion. */
1222 case 5: /* WPI_RIDX_OFDM36 */
1225 case 6: /* WPI_RIDX_OFDM48 */
1228 case 7: /* WPI_RIDX_OFDM54 */
1233 /* Never exceed the channel maximum allowed TX power. */
1234 pwr = MIN(pwr, ctlr->maxpwr[chan]);
1236 /* Retrieve TX power index into gain tables from samples. */
1237 for(sample = pwgr->samples; sample < &pwgr->samples[3]; sample++)
1238 if(pwr > sample[1].power)
1240 /* Fixed-point linear interpolation using a 19-bit fractional part. */
1241 idx = interpolate(pwr, sample[0].power, sample[0].index,
1242 sample[1].power, sample[1].index, 19);
1245 * Adjust power index based on current temperature:
1246 * - if cooler than factory-calibrated: decrease output power
1247 * - if warmer than factory-calibrated: increase output power
1249 idx -= (ctlr->temp - pwgr->temp) * 11 / 100;
1251 /* Decrease TX power for CCK rates (-5dB). */
1255 /* Make sure idx stays in a valid range. */
1258 else if (idx >= nelem(rfgain_2ghz))
1259 idx = nelem(rfgain_2ghz)-1;
1266 addnode(Ctlr *ctlr, uchar id, uchar *addr, int plcp, int antenna)
1268 uchar c[Tcmdsize], *p;
1270 memset(p = c, 0, sizeof(c));
1271 *p++ = 0; /* control (1 = update) */
1272 p += 3; /* reserved */
1273 memmove(p, addr, 6);
1275 p += 2; /* reserved */
1276 *p++ = id; /* node id */
1278 p += 2; /* reserved */
1279 p += 2; /* kflags */
1282 p += 5*2; /* ttak */
1283 p += 2; /* reserved */
1285 put32(p, 4); /* action (4 = set_rate) */
1289 *p++ = plcp; /* plcp */
1290 *p++ = antenna; /* antenna */
1293 p++; /* add_imm_start */
1294 cmd(ctlr, 24, c, p - c);
1298 rxon(Ether *edev, Wnode *bss)
1300 uchar c[Tcmdsize], *p;
1301 int filter, flags, rate;
1307 filter = FilterNoDecrypt | FilterMulticast;
1309 filter |= FilterPromisc;
1311 ctlr->channel = bss->channel;
1314 flags = RFlagTSF | RFlag24Ghz | RFlagAuto;
1316 if(bss->cap & (1<<5))
1317 flags |= RFlagShPreamble;
1318 if(bss->cap & (1<<10))
1319 flags |= RFlagShSlot;
1320 ctlr->channel = bss->channel;
1321 memmove(ctlr->bssid, bss->bssid, Eaddrlen);
1322 ctlr->aid = bss->aid;
1324 filter |= FilterBSS;
1325 ctlr->bssnodeid = -1;
1327 ctlr->bcastnodeid = -1;
1329 memmove(ctlr->bssid, edev->bcast, Eaddrlen);
1331 ctlr->bcastnodeid = -1;
1332 ctlr->bssnodeid = -1;
1336 setled(ctlr, 2, 0, 1); /* on when associated */
1337 else if(memcmp(ctlr->bssid, edev->bcast, Eaddrlen) != 0)
1338 setled(ctlr, 2, 10, 10); /* slow blink when connecting */
1340 setled(ctlr, 2, 5, 5); /* fast blink when scanning */
1342 memset(p = c, 0, sizeof(c));
1343 memmove(p, edev->ea, 6); p += 8; /* myaddr */
1344 memmove(p, ctlr->bssid, 6); p += 16; /* bssid */
1345 *p++ = 3; /* mode (STA) */
1347 *p++ = 0xff; /* ofdm mask (not yet negotiated) */
1348 *p++ = 0x0f; /* cck mask (not yet negotiated) */
1349 put16(p, ctlr->aid & 0x3fff); /* associd */
1355 *p++ = ctlr->channel;
1358 if((err = cmd(ctlr, 16, c, p - c)) != nil){
1359 print("rxon: %s\n", err);
1363 if(ctlr->maxpwr[ctlr->channel] != 0){
1365 memset(p = c, 0, sizeof(c));
1366 *p++ = 1; /* band (0 = 5ghz) */
1368 put16(p, ctlr->channel), p += 2;
1369 for(rate = 0; rate < nelem(ratetab); rate++){
1370 idx = pwridx(ctlr, &ctlr->eeprom.pwrgrps[0], ctlr->channel, rate);
1371 *p++ = ratetab[rate].plcp;
1372 *p++ = rfgain_2ghz[idx]; /* rf_gain */
1373 *p++ = dspgain_2ghz[idx]; /* dsp_gain */
1376 cmd(ctlr, 151, c, p - c);
1379 if(ctlr->bcastnodeid == -1){
1380 ctlr->bcastnodeid = 24;
1381 addnode(ctlr, ctlr->bcastnodeid, edev->bcast, ratetab[0].plcp, 3<<6);
1383 if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){
1384 ctlr->bssnodeid = 0;
1385 addnode(ctlr, ctlr->bssnodeid, bss->bssid, ratetab[0].plcp, 3<<6);
1390 TFlagNeedRTS = 1<<1,
1391 TFlagNeedCTS = 1<<2,
1392 TFlagNeedACK = 1<<3,
1393 TFlagFullTxOp = 1<<7,
1395 TFlagAutoSeq = 1<<13,
1396 TFlagInsertTs = 1<<16,
1400 transmit(Wifi *wifi, Wnode *wn, Block *b)
1402 uchar c[Tcmdsize], *p;
1406 int flags, nodeid, rate, timeout;
1413 if(ctlr->attached == 0 || ctlr->broken){
1419 if((wn->channel != ctlr->channel)
1420 || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0)))
1424 /* association note has no data to transmit */
1431 nodeid = ctlr->bcastnodeid;
1433 w = (Wifipkt*)b->rp;
1434 if((w->a1[0] & 1) == 0){
1435 flags |= TFlagNeedACK;
1438 flags |= TFlagNeedRTS|TFlagFullTxOp;
1440 if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){
1442 nodeid = ctlr->bssnodeid;
1446 if(p >= wifi->rates)
1447 rate = p - wifi->rates;
1452 memset(p = c, 0, sizeof(c));
1453 put16(p, BLEN(b)), p += 2;
1454 put16(p, 0), p += 2; /* lnext */
1455 put32(p, flags), p += 4;
1456 *p++ = ratetab[rate].plcp;
1459 *p++ = 0; /* security */
1460 p += 16+8; /* key/iv */
1461 put32(p, 0), p += 4; /* fnext */
1462 put32(p, 0xffffffff), p += 4; /* livetime infinite */
1467 put16(p, timeout), p += 2;
1468 put16(p, 0), p += 2; /* txop */
1470 if((err = qcmd(ctlr, 0, 28, c, p - c, b)) != nil){
1471 print("transmit: %s\n", err);
1477 wpictl(Ether *edev, void *buf, long n)
1482 if(n >= 5 && memcmp(buf, "reset", 5) == 0){
1487 return wifictl(ctlr->wifi, buf, n);
1492 wpiifstat(Ether *edev, void *buf, long n, ulong off)
1498 return wifistat(ctlr->wifi, buf, n, off);
1503 setoptions(Ether *edev)
1509 for(i = 0; i < edev->nopt; i++)
1510 wificfg(ctlr->wifi, edev->opt[i]);
1514 wpipromiscuous(void *arg, int on)
1523 rxon(edev, ctlr->wifi->bss);
1528 wpimulticast(void *, uchar*, int)
1533 wpirecover(void *arg)
1543 tsleep(&up->sleep, return0, 0, 4000);
1547 if(ctlr->broken == 0)
1553 if((csr32r(ctlr, Gpc) & RfKill) == 0)
1556 if(reset(ctlr) != nil)
1558 if(boot(ctlr) != nil)
1561 ctlr->bcastnodeid = -1;
1562 ctlr->bssnodeid = -1;
1564 rxon(edev, ctlr->wifi->bss);
1572 wpiattach(Ether *edev)
1581 print("#l%d: %s\n", edev->ctlrno, up->errstr);
1587 if(ctlr->attached == 0){
1588 if((csr32r(ctlr, Gpc) & RfKill) == 0)
1589 error("wifi disabled by switch");
1591 if(ctlr->wifi == nil){
1592 qsetlimit(edev->oq, MaxQueue);
1594 ctlr->wifi = wifiattach(edev, transmit);
1595 ctlr->wifi->rates = wpirates;
1598 if(ctlr->fw == nil){
1599 fw = readfirmware();
1600 print("#l%d: firmware: %ux, size: %ux+%ux+%ux+%ux+%ux\n",
1601 edev->ctlrno, fw->version,
1602 fw->main.text.size, fw->main.data.size,
1603 fw->init.text.size, fw->init.data.size,
1604 fw->boot.text.size);
1608 if((err = reset(ctlr)) != nil)
1610 if((err = boot(ctlr)) != nil)
1613 ctlr->bcastnodeid = -1;
1614 ctlr->bssnodeid = -1;
1622 kproc("wpirecover", wpirecover, edev);
1638 if(ctlr->broken || ctlr->shared == nil || rx->b == nil)
1642 for(hw = ctlr->shared->next % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){
1643 uchar type, flags, idx, qid;
1651 len = get32(d); d += 4;
1660 if(0) iprint("rxdesc[%d] type=%d len=%d idx=%d qid=%d\n", rx->i, type, len, idx, qid);
1666 if((qid & 0x80) == 0 && qid < nelem(ctlr->tx)){
1667 tx = &ctlr->tx[qid];
1677 case 1: /* uc ready */
1680 case 24: /* add node done */
1683 case 27: /* rx done */
1688 if(d + 6 + 2 > b->lim){
1693 if(d + len + 4 > b->lim){
1696 if((get32(d + len) & 3) != 3){
1699 if(ctlr->wifi == nil)
1701 if(rbplant(ctlr, rx->i) < 0)
1705 wifiiq(ctlr->wifi, b);
1708 case 28: /* tx done */
1709 if(len <= 8 || d[8] == 1)
1711 wifitxfail(ctlr->wifi, bb);
1714 case 130: /* start scan */
1717 case 132: /* stop scan */
1720 case 161: /* state change */
1724 csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7);
1730 wpiinterrupt(Ureg*, void *arg)
1739 csr32w(ctlr, Imr, 0);
1740 isr = csr32r(ctlr, Isr);
1741 fhisr = csr32r(ctlr, FhIsr);
1742 if(isr == 0xffffffff || (isr & 0xfffffff0) == 0xa5a5a5a0){
1746 if(isr == 0 && fhisr == 0)
1748 csr32w(ctlr, Isr, isr);
1749 csr32w(ctlr, FhIsr, fhisr);
1750 if((isr & (Iswrx | Ifhrx)) || (fhisr & Ifhrx))
1754 iprint("#l%d: fatal firmware error, lastcmd %ud\n", edev->ctlrno, ctlr->tx[4].lastcmd);
1756 ctlr->wait.m |= isr;
1757 if(ctlr->wait.m & ctlr->wait.w)
1758 wakeup(&ctlr->wait);
1760 csr32w(ctlr, Imr, ctlr->ie);
1765 wpishutdown(Ether *edev)
1775 static Ctlr *wpihead, *wpitail;
1783 while(pdev = pcimatch(pdev, 0x8086, 0)){
1793 if(pdev->mem[0].bar & 1)
1796 /* Clear device-specific "PCI retry timeout" register (41h). */
1797 if(pcicfgr8(pdev, 0x41) != 0)
1798 pcicfgw8(pdev, 0x41, 0);
1800 ctlr = malloc(sizeof(Ctlr));
1802 print("wpi: unable to alloc Ctlr\n");
1805 ctlr->port = pdev->mem[0].bar & ~0xF;
1806 mem = vmap(ctlr->port, pdev->mem[0].size);
1808 print("wpi: can't map %llux\n", ctlr->port);
1816 wpitail->link = ctlr;
1832 for(ctlr = wpihead; ctlr != nil; ctlr = ctlr->link){
1835 if(edev->port == 0 || edev->port == ctlr->port){
1845 edev->port = ctlr->port;
1846 edev->irq = ctlr->pdev->intl;
1847 edev->tbdf = ctlr->pdev->tbdf;
1849 edev->attach = wpiattach;
1850 edev->ifstat = wpiifstat;
1852 edev->shutdown = wpishutdown;
1853 edev->promiscuous = wpipromiscuous;
1854 edev->multicast = wpimulticast;
1857 pcienable(ctlr->pdev);
1858 if(wpiinit(edev) < 0){
1859 pcidisable(ctlr->pdev);
1863 pcisetbme(ctlr->pdev);
1864 intrenable(edev->irq, wpiinterrupt, edev, edev->tbdf, edev->name);
1872 addethercard("wpi", wpipnp);