2 #include "../port/lib.h"
7 #include "../port/error.h"
8 #include "../port/netif.h"
9 #include "../port/etherif.h"
10 #include "../port/wifi.h"
13 MaxQueue = 24*1024, /* total buffer is 2*MaxQueue: 48k at 22Mbit ≅ 20ms */
17 Ntxqmax = MaxQueue/1500,
47 Ierr = Iswerr | Ihwerr,
48 Idefmask = Ierr | Ifhtx | Ifhrx | Ialive | Iwakeup | Iswrx | Irftoggled,
54 MasterDisabled = 1<<8,
68 UcodeGp1RfKill = 1<<1,
69 UcodeGp1CmdBlocked = 1<<2,
85 * Flow-Handler registers.
91 FhRxConfigDmaEna = 1<<31,
92 FhRxConfigRdrbdEna = 1<<29,
93 FhRxConfigWrstatusEna = 1<<27,
94 FhRxConfigMaxfrag = 1<<24,
95 FhRxConfigIrqDstHost = 1<<12,
97 FhRxConfigNrdbShift = 20,
98 FhRxConfigIrqRbthShift = 4,
101 FhRxRptrAddr = 0xc24,
104 FhTxConfig = 0xd00, // +q*32
111 * NIC internal memory offsets.
114 AlmSchedMode = 0x2e00,
115 AlmSchedArastat = 0x2e04,
116 AlmSchedTxfact = 0x2e10,
117 AlmSchedTxf4mf = 0x2e14,
118 AlmSchedTxf5mf = 0x2e20,
119 AlmSchedBP1 = 0x2e2c,
120 AlmSchedBP2 = 0x2e30,
132 BsmWrMemSrc = 0x3404,
133 BsmWrMemDst = 0x3408,
134 BsmWrDwCount = 0x340c,
135 BsmDramTextAddr = 0x3490,
136 BsmDramTextSize = 0x3494,
137 BsmDramDataAddr = 0x3498,
138 BsmDramDataSize = 0x349c,
139 BsmSramBase = 0x3800,
143 FilterPromisc = 1<<0,
145 FilterMulticast = 1<<2,
146 FilterNoDecrypt = 1<<3,
155 RFlagShPreamble = 1<<5,
156 RFlagNoDiversity = 1<<7,
157 RFlagAntennaA = 1<<8,
158 RFlagAntennaB = 1<<9,
162 typedef struct FWSect FWSect;
163 typedef struct FWImage FWImage;
165 typedef struct TXQ TXQ;
166 typedef struct RXQ RXQ;
168 typedef struct Shared Shared;
169 typedef struct Sample Sample;
170 typedef struct Powergrp Powergrp;
172 typedef struct Ctlr Ctlr;
251 /* assigned node ids in hardware node table or -1 if unassigned */
255 /* current receiver settings */
256 uchar bssid[Eaddrlen];
287 static void setled(Ctlr *ctlr, int which, int on, int off);
289 #define csr32r(c, r) (*((c)->nic+((r)/4)))
290 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
294 return *((u32int*)p);
299 return *((u16int*)p);
302 put32(uchar *p, uint v){
306 put16(uchar *p, uint v){
315 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq);
316 for(i=0; i<1000; i++){
317 if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna)
321 return "niclock: timeout";
325 nicunlock(Ctlr *ctlr)
327 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq);
331 prphread(Ctlr *ctlr, uint off)
333 csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off);
335 return csr32r(ctlr, PrphRdata);
338 prphwrite(Ctlr *ctlr, uint off, u32int data)
340 csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off);
342 csr32w(ctlr, PrphWdata, data);
346 eepromread(Ctlr *ctlr, void *data, int count, uint off)
353 if((err = niclock(ctlr)) != nil)
356 for(; count > 0; count -= 2, off++){
357 csr32w(ctlr, Eeprom, off << 2);
358 csr32w(ctlr, Eeprom, csr32r(ctlr, Eeprom) & ~(1<<1));
360 for(i = 0; i < 10; i++){
361 w = csr32r(ctlr, Eeprom);
375 return "eeprompread: timeout";
380 clockwait(Ctlr *ctlr)
384 /* Set "initialization complete" bit. */
385 csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone);
386 for(i=0; i<2500; i++){
387 if(csr32r(ctlr, Gpc) & MacClockReady)
391 return "clockwait: timeout";
402 csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | Init);
404 csr32w(ctlr, GioChicken, csr32r(ctlr, GioChicken) | L1AnoL0Srx);
406 if((err = clockwait(ctlr)) != nil)
409 if((err = niclock(ctlr)) != nil)
412 prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt);
416 prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11));
430 csr32w(ctlr, Reset, Nevo);
432 /* Disable interrupts. */
433 csr32w(ctlr, Imr, 0);
434 csr32w(ctlr, Isr, ~0);
435 csr32w(ctlr, FhIsr, ~0);
437 if(niclock(ctlr) == nil){
438 /* Stop TX scheduler. */
439 prphwrite(ctlr, AlmSchedMode, 0);
440 prphwrite(ctlr, AlmSchedTxfact, 0);
442 /* Stop all DMA channels */
443 for(i = 0; i < 6; i++){
444 csr32w(ctlr, FhTxConfig + i*32, 0);
445 for(j = 0; j < 100; j++){
446 if((csr32r(ctlr, FhTxStatus) & (0x1010000<<i)) == (0x1010000<<i))
455 if(niclock(ctlr) == nil){
456 csr32w(ctlr, FhRxConfig, 0);
457 for(j = 0; j < 100; j++){
458 if(csr32r(ctlr, FhRxStatus) & (1<<24))
465 if(niclock(ctlr) == nil){
466 prphwrite(ctlr, ApmgClkDis, DmaClkRqt);
471 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | StopMaster);
473 if((csr32r(ctlr, Gpc) & (7<<24)) != (4<<24)){
474 for(j = 0; j < 100; j++){
475 if(csr32r(ctlr, Reset) & MasterDisabled)
481 csr32w(ctlr, Reset, csr32r(ctlr, Reset) | SW);
487 u32int addr; /* offset in EEPROM */
492 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 } },
494 { 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 } },
496 { 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 } },
498 { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 } },
500 { 145, 149, 153, 157, 161, 165 } }
513 if((err = poweron(ctlr)) != nil)
515 if((csr32r(ctlr, EepromGp) & 0x6) == 0){
516 err = "bad rom signature";
519 /* Clear HW ownership of EEPROM. */
520 csr32w(ctlr, EepromGp, csr32r(ctlr, EepromGp) & ~0x180);
522 if((err = eepromread(ctlr, b, 1, 0x45)) != nil)
524 ctlr->eeprom.cap = b[0];
525 if((err = eepromread(ctlr, b, 2, 0x35)) != nil)
527 ctlr->eeprom.rev = get16(b);
528 if((err = eepromread(ctlr, b, 1, 0x4a)) != nil)
530 ctlr->eeprom.type = b[0];
531 if((err = eepromread(ctlr, b, 4, 0x60)) != nil)
533 strncpy(ctlr->eeprom.regdom, (char*)b, 4);
534 ctlr->eeprom.regdom[4] = '\0';
536 print("wpi: %X %X %X %s\n", ctlr->eeprom.cap, ctlr->eeprom.rev, ctlr->eeprom.type, ctlr->eeprom.regdom);
538 if((err = eepromread(ctlr, b, 6, 0x15)) != nil)
540 memmove(edev->ea, b, Eaddrlen);
542 memset(ctlr->maxpwr, 0, sizeof(ctlr->maxpwr));
543 for(i = 0; i < nelem(bands); i++){
544 if((err = eepromread(ctlr, b, 2*bands[i].nchan, bands[i].addr)) != nil)
546 for(j = 0; j < bands[i].nchan; j++){
549 ctlr->maxpwr[bands[i].chan[j]] = b[j*2+1];
553 for(i = 0; i < nelem(ctlr->eeprom.pwrgrps); i++){
554 if((err = eepromread(ctlr, b, 64, 0x100 + i*32)) != nil)
556 g = &ctlr->eeprom.pwrgrps[i];
559 g->temp = get16(b+62);
560 for(j = 0; j < 5; j++){
561 g->samples[j].index = b[j*4];
562 g->samples[j].power = b[j*4+1];
569 print("wpiinit: %s\n", err);
575 crackfw(FWImage *i, uchar *data, uint size)
579 memset(i, 0, sizeof(*i));
582 return "firmware image too short";
586 i->version = get32(p); p += 4;
587 i->main.text.size = get32(p); p += 4;
588 i->main.data.size = get32(p); p += 4;
589 i->init.text.size = get32(p); p += 4;
590 i->init.data.size = get32(p); p += 4;
591 i->boot.text.size = get32(p); p += 4;
592 i->main.text.data = p; p += i->main.text.size;
593 i->main.data.data = p; p += i->main.data.size;
594 i->init.text.data = p; p += i->init.text.size;
595 i->init.data.data = p; p += i->init.data.size;
596 i->boot.text.data = p; p += i->boot.text.size;
605 uchar dirbuf[sizeof(Dir)+100], *data;
615 c = namec("/boot/wpi-3945abg", Aopen, OREAD, 0);
618 c = namec("/lib/firmware/wpi-3945abg", Aopen, OREAD, 0);
623 n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf);
625 error("can't stat firmware");
626 convM2D(dirbuf, n, &d, nil);
627 fw = smalloc(sizeof(*fw) + 16 + d.length);
628 data = (uchar*)(fw+1);
635 n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r);
640 if((err = crackfw(fw, data, r)) != nil)
652 return (ctlr->wait.m & ctlr->wait.w) != 0;
656 irqwait(Ctlr *ctlr, u32int mask, int timeout)
661 r = ctlr->wait.m & mask;
666 tsleep(&ctlr->wait, gotirq, ctlr, timeout);
671 r = ctlr->wait.m & mask;
679 rbplant(Ctlr *ctlr, int i)
683 b = iallocb(Rbufsize+127);
686 b->rp = b->wp = (uchar*)((((uintptr)b->base+127)&~127));
687 memset(b->rp, 0, Rdscsize);
690 ctlr->rx.p[i] = PCIWADDR(b->rp);
703 rx->b = malloc(sizeof(Block*) * Nrx);
705 rx->p = mallocalign(sizeof(u32int) * Nrx, 16 * 1024, 0, 0);
706 if(rx->b == nil || rx->p == nil)
707 return "no memory for rx ring";
708 for(i = 0; i<Nrx; i++){
714 if(rbplant(ctlr, i) < 0)
715 return "no memory for rx descriptors";
719 if(ctlr->shared == nil)
720 ctlr->shared = mallocalign(4096, 4096, 0, 0);
721 if(ctlr->shared == nil)
722 return "no memory for shared buffer";
723 memset(ctlr->shared, 0, 4096);
725 for(q=0; q<nelem(ctlr->tx); q++){
728 tx->b = malloc(sizeof(Block*) * Ntx);
730 tx->d = mallocalign(Tdscsize * Ntx, 16 * 1024, 0, 0);
732 tx->c = mallocalign(Tcmdsize * Ntx, 4, 0, 0);
733 if(tx->b == nil || tx->d == nil || tx->c == nil)
734 return "no memory for tx ring";
735 memset(tx->d, 0, Tdscsize * Ntx);
736 memset(tx->c, 0, Tcmdsize * Ntx);
737 for(i=0; i<Ntx; i++){
743 ctlr->shared->txbase[q] = PCIWADDR(tx->d);
760 if((err = initring(ctlr)) != nil)
762 if((err = poweron(ctlr)) != nil)
765 /* Select VMAIN power source. */
766 if((err = niclock(ctlr)) != nil)
768 prphwrite(ctlr, ApmgPs, (prphread(ctlr, ApmgPs) & ~PwrSrcMask) | PwrSrcVMain);
770 /* Spin until VMAIN gets selected. */
771 for(i = 0; i < 5000; i++){
772 if(csr32r(ctlr, GpioIn) & (1 << 9))
777 /* Perform adapter initialization. */
778 rev = ctlr->pdev->rid;
779 if((rev & 0xc0) == 0x40)
780 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | AlmMb);
781 else if(!(rev & 0x80))
782 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | AlmMm);
784 if(ctlr->eeprom.cap == 0x80)
785 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | SkuMrc);
787 if((ctlr->eeprom.rev & 0xf0) == 0xd0)
788 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | RevD);
790 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) & ~RevD);
792 if(ctlr->eeprom.type > 1)
793 csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | TypeB);
795 /* Initialize RX ring. */
796 if((err = niclock(ctlr)) != nil)
800 csr32w(ctlr, FhRxBase, PCIWADDR(ctlr->rx.p));
801 csr32w(ctlr, FhRxRptrAddr, PCIWADDR(&ctlr->shared->next));
802 csr32w(ctlr, FhRxWptr, 0);
803 csr32w(ctlr, FhRxConfig,
806 FhRxConfigWrstatusEna |
808 (Nrxlog << FhRxConfigNrdbShift) |
809 FhRxConfigIrqDstHost |
810 (1 << FhRxConfigIrqRbthShift));
811 USED(csr32r(ctlr, FhRssrTbl));
812 csr32w(ctlr, FhRxWptr, (Nrx-1) & ~7);
815 /* Initialize TX rings. */
816 if((err = niclock(ctlr)) != nil)
818 prphwrite(ctlr, AlmSchedMode, 2);
819 prphwrite(ctlr, AlmSchedArastat, 1);
820 prphwrite(ctlr, AlmSchedTxfact, 0x3f);
821 prphwrite(ctlr, AlmSchedBP1, 0x10000);
822 prphwrite(ctlr, AlmSchedBP2, 0x30002);
823 prphwrite(ctlr, AlmSchedTxf4mf, 4);
824 prphwrite(ctlr, AlmSchedTxf5mf, 5);
825 csr32w(ctlr, FhTxBase, PCIWADDR(ctlr->shared));
826 csr32w(ctlr, FhMsgConfig, 0xffff05a5);
827 for(i = 0; i < 6; i++){
828 csr32w(ctlr, FhCbbcCtrl+i*8, 0);
829 csr32w(ctlr, FhCbbcBase+i*8, 0);
830 csr32w(ctlr, FhTxConfig+i*32, 0x80200008);
833 USED(csr32r(ctlr, FhTxBase));
835 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
836 csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
843 csr32w(ctlr, Imr, ctlr->ie);
844 csr32w(ctlr, Isr, ~0);
846 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
847 csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
864 /* 16 byte padding may not be necessary. */
865 size = ROUND(fw->init.data.size, 16) + ROUND(fw->init.text.size, 16);
866 dma = mallocalign(size, 16, 0, 0);
868 return "no memory for dma";
870 if((err = niclock(ctlr)) != nil){
876 memmove(p, fw->init.data.data, fw->init.data.size);
878 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p));
879 prphwrite(ctlr, BsmDramDataSize, fw->init.data.size);
880 p += ROUND(fw->init.data.size, 16);
881 memmove(p, fw->init.text.data, fw->init.text.size);
883 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p));
884 prphwrite(ctlr, BsmDramTextSize, fw->init.text.size);
887 if((err = niclock(ctlr)) != nil){
892 /* Copy microcode image into NIC memory. */
893 p = fw->boot.text.data;
894 n = fw->boot.text.size/4;
895 for(i=0; i<n; i++, p += 4)
896 prphwrite(ctlr, BsmSramBase+i*4, get32(p));
898 prphwrite(ctlr, BsmWrMemSrc, 0);
899 prphwrite(ctlr, BsmWrMemDst, 0);
900 prphwrite(ctlr, BsmWrDwCount, n);
902 /* Start boot load now. */
903 prphwrite(ctlr, BsmWrCtrl, 1<<31);
905 /* Wait for transfer to complete. */
906 for(i=0; i<1000; i++){
907 if((prphread(ctlr, BsmWrCtrl) & (1<<31)) == 0)
914 return "bootcode timeout";
917 /* Enable boot after power up. */
918 prphwrite(ctlr, BsmWrCtrl, 1<<30);
921 /* Now press "execute". */
922 csr32w(ctlr, Reset, 0);
924 /* Wait at most one second for first alive notification. */
925 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
927 return "init firmware boot failed";
931 size = ROUND(fw->main.data.size, 16) + ROUND(fw->main.text.size, 16);
932 dma = mallocalign(size, 16, 0, 0);
934 return "no memory for dma";
935 if((err = niclock(ctlr)) != nil){
940 memmove(p, fw->main.data.data, fw->main.data.size);
942 prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p));
943 prphwrite(ctlr, BsmDramDataSize, fw->main.data.size);
944 p += ROUND(fw->main.data.size, 16);
945 memmove(p, fw->main.text.data, fw->main.text.size);
947 prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p));
948 prphwrite(ctlr, BsmDramTextSize, fw->main.text.size | (1<<31));
951 if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
953 return "main firmware boot failed";
956 return postboot(ctlr);
963 return q->n < Ntxqmax;
967 qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
973 assert(qid < nelem(ctlr->tx));
974 assert(size <= Tcmdsize-4);
978 while(q->n >= Ntxqmax && !ctlr->broken){
982 tsleep(q, txqready, q, 5);
990 return "qcmd: broken";
996 c = q->c + q->i * Tcmdsize;
997 d = q->d + q->i * Tdscsize;
1001 c[1] = 0; /* flags */
1006 memmove(c+4, data, size);
1009 memset(d, 0, Tdscsize);
1014 pad = ((pad + 3) & ~3) - pad;
1016 put32(d, (pad << 28) | ((1 + (block != nil)) << 24)), d += 4;
1017 put32(d, PCIWADDR(c)), d += 4;
1018 put32(d, size), d += 4;
1022 put32(d, PCIWADDR(block->rp)), d += 4;
1023 put32(d, size), d += 4;
1030 q->i = (q->i+1) % Ntx;
1031 csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i);
1046 flushq(Ctlr *ctlr, uint qid)
1053 for(i = 0; i < 200 && !ctlr->broken; i++){
1058 if(islo() && !waserror()){
1059 tsleep(q, txqempty, q, 10);
1065 return "flushq: broken";
1066 return "flushq: timeout";
1070 cmd(Ctlr *ctlr, uint code, uchar *data, int size)
1074 if((err = qcmd(ctlr, 4, code, data, size, nil)) != nil)
1076 return flushq(ctlr, 4);
1080 setled(Ctlr *ctlr, int which, int on, int off)
1084 memset(c, 0, sizeof(c));
1089 cmd(ctlr, 72, c, sizeof(c));
1095 uchar c[Tcmdsize], *p;
1097 /* configure bluetooth coexistance. */
1099 *p++ = 3; /* flags WPI_BT_COEX_MODE_4WIRE */
1100 *p++ = 30; /* lead time */
1101 *p++ = 5; /* max kill */
1102 *p++ = 0; /* reserved */
1103 put32(p, 0), p += 4; /* kill_ack */
1104 put32(p, 0), p += 4; /* kill_cts */
1105 return cmd(ctlr, 155, c, p-c);
1109 powermode(Ctlr *ctlr)
1114 memset(c, 0, sizeof(c));
1115 capoff = pcicap(ctlr->pdev, PciCapPCIe);
1117 reg = pcicfgr8(ctlr->pdev, capoff+1);
1118 if((reg & 1) == 0) /* PCI_PCIE_LCR_ASPM_L0S */
1119 c[0] |= 1<<3; /* WPI_PS_PCI_PMGT */
1121 return cmd(ctlr, 119, c, 4*(3+5));
1125 postboot(Ctlr *ctlr)
1127 while((ctlr->temp = (int)csr32r(ctlr, UcodeGp2)) == 0)
1133 if((err = btcoex(ctlr)) != nil)
1134 print("btcoex: %s\n", err);
1135 if((err = powermode(ctlr)) != nil)
1136 print("powermode: %s\n", err);
1142 static uchar wpirates[] = {
1179 static u8int rfgain_2ghz[] = {
1180 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xbb, 0xbb, 0xbb,
1181 0xbb, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xd3, 0xd3, 0xb3, 0xb3, 0xb3,
1182 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x73, 0xeb, 0xeb, 0xeb,
1183 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xab, 0xab, 0xab, 0x8b,
1184 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xa3,
1185 0xa3, 0xa3, 0xa3, 0x83, 0x83, 0x83, 0x83, 0x63, 0x63, 0x63, 0x63,
1186 0x43, 0x43, 0x43, 0x43, 0x23, 0x23, 0x23, 0x23, 0x03, 0x03, 0x03,
1190 static u8int dspgain_2ghz[] = {
1191 0x7f, 0x7f, 0x7f, 0x7f, 0x7d, 0x6e, 0x69, 0x62, 0x7d, 0x73, 0x6c,
1192 0x63, 0x77, 0x6f, 0x69, 0x61, 0x5c, 0x6a, 0x64, 0x78, 0x71, 0x6b,
1193 0x7d, 0x77, 0x70, 0x6a, 0x65, 0x61, 0x5b, 0x6b, 0x79, 0x73, 0x6d,
1194 0x7f, 0x79, 0x73, 0x6c, 0x66, 0x60, 0x5c, 0x6e, 0x68, 0x62, 0x74,
1195 0x7d, 0x77, 0x71, 0x6b, 0x65, 0x60, 0x71, 0x6a, 0x66, 0x5f, 0x71,
1196 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f,
1197 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66,
1202 pwridx(Ctlr *ctlr, Powergrp *pwgr, int chan, int rate)
1204 /* Fixed-point arithmetic division using a n-bit fractional part. */
1205 #define fdivround(a, b, n) \
1206 ((((1 << n) * (a)) / (b) + (1 << n) / 2) / (1 << n))
1208 /* Linear interpolation. */
1209 #define interpolate(x, x1, y1, x2, y2, n) \
1210 ((y1) + fdivround(((x) - (x1)) * ((y2) - (y1)), (x2) - (x1), n))
1216 /* Default TX power is group maximum TX power minus 3dB. */
1217 pwr = pwgr->maxpwr / 2;
1219 /* Decrease TX power for highest OFDM rates to reduce distortion. */
1221 case 5: /* WPI_RIDX_OFDM36 */
1224 case 6: /* WPI_RIDX_OFDM48 */
1227 case 7: /* WPI_RIDX_OFDM54 */
1232 /* Never exceed the channel maximum allowed TX power. */
1233 pwr = MIN(pwr, ctlr->maxpwr[chan]);
1235 /* Retrieve TX power index into gain tables from samples. */
1236 for(sample = pwgr->samples; sample < &pwgr->samples[3]; sample++)
1237 if(pwr > sample[1].power)
1239 /* Fixed-point linear interpolation using a 19-bit fractional part. */
1240 idx = interpolate(pwr, sample[0].power, sample[0].index,
1241 sample[1].power, sample[1].index, 19);
1244 * Adjust power index based on current temperature:
1245 * - if cooler than factory-calibrated: decrease output power
1246 * - if warmer than factory-calibrated: increase output power
1248 idx -= (ctlr->temp - pwgr->temp) * 11 / 100;
1250 /* Decrease TX power for CCK rates (-5dB). */
1254 /* Make sure idx stays in a valid range. */
1257 else if (idx >= nelem(rfgain_2ghz))
1258 idx = nelem(rfgain_2ghz)-1;
1265 addnode(Ctlr *ctlr, uchar id, uchar *addr, int plcp, int antenna)
1267 uchar c[Tcmdsize], *p;
1269 memset(p = c, 0, sizeof(c));
1270 *p++ = 0; /* control (1 = update) */
1271 p += 3; /* reserved */
1272 memmove(p, addr, 6);
1274 p += 2; /* reserved */
1275 *p++ = id; /* node id */
1277 p += 2; /* reserved */
1278 p += 2; /* kflags */
1281 p += 5*2; /* ttak */
1282 p += 2; /* reserved */
1284 put32(p, 4); /* action (4 = set_rate) */
1288 *p++ = plcp; /* plcp */
1289 *p++ = antenna; /* antenna */
1292 p++; /* add_imm_start */
1293 cmd(ctlr, 24, c, p - c);
1297 rxon(Ether *edev, Wnode *bss)
1299 uchar c[Tcmdsize], *p;
1300 int filter, flags, rate;
1306 filter = FilterNoDecrypt | FilterMulticast;
1308 filter |= FilterPromisc;
1310 ctlr->channel = bss->channel;
1313 flags = RFlagTSF | RFlag24Ghz | RFlagAuto;
1315 if(bss->cap & (1<<5))
1316 flags |= RFlagShPreamble;
1317 if(bss->cap & (1<<10))
1318 flags |= RFlagShSlot;
1319 ctlr->channel = bss->channel;
1320 memmove(ctlr->bssid, bss->bssid, Eaddrlen);
1321 ctlr->aid = bss->aid;
1323 filter |= FilterBSS;
1324 ctlr->bssnodeid = -1;
1326 ctlr->bcastnodeid = -1;
1328 memmove(ctlr->bssid, edev->bcast, Eaddrlen);
1330 ctlr->bcastnodeid = -1;
1331 ctlr->bssnodeid = -1;
1335 setled(ctlr, 2, 0, 1); /* on when associated */
1336 else if(memcmp(ctlr->bssid, edev->bcast, Eaddrlen) != 0)
1337 setled(ctlr, 2, 10, 10); /* slow blink when connecting */
1339 setled(ctlr, 2, 5, 5); /* fast blink when scanning */
1341 memset(p = c, 0, sizeof(c));
1342 memmove(p, edev->ea, 6); p += 8; /* myaddr */
1343 memmove(p, ctlr->bssid, 6); p += 16; /* bssid */
1344 *p++ = 3; /* mode (STA) */
1346 *p++ = 0xff; /* ofdm mask (not yet negotiated) */
1347 *p++ = 0x0f; /* cck mask (not yet negotiated) */
1348 put16(p, ctlr->aid & 0x3fff); /* associd */
1354 *p++ = ctlr->channel;
1357 if((err = cmd(ctlr, 16, c, p - c)) != nil){
1358 print("rxon: %s\n", err);
1362 if(ctlr->maxpwr[ctlr->channel] != 0){
1364 memset(p = c, 0, sizeof(c));
1365 *p++ = 1; /* band (0 = 5ghz) */
1367 put16(p, ctlr->channel), p += 2;
1368 for(rate = 0; rate < nelem(ratetab); rate++){
1369 idx = pwridx(ctlr, &ctlr->eeprom.pwrgrps[0], ctlr->channel, rate);
1370 *p++ = ratetab[rate].plcp;
1371 *p++ = rfgain_2ghz[idx]; /* rf_gain */
1372 *p++ = dspgain_2ghz[idx]; /* dsp_gain */
1375 cmd(ctlr, 151, c, p - c);
1378 if(ctlr->bcastnodeid == -1){
1379 ctlr->bcastnodeid = 24;
1380 addnode(ctlr, ctlr->bcastnodeid, edev->bcast, ratetab[0].plcp, 3<<6);
1382 if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){
1383 ctlr->bssnodeid = 0;
1384 addnode(ctlr, ctlr->bssnodeid, bss->bssid, ratetab[0].plcp, 3<<6);
1389 TFlagNeedRTS = 1<<1,
1390 TFlagNeedCTS = 1<<2,
1391 TFlagNeedACK = 1<<3,
1392 TFlagFullTxOp = 1<<7,
1394 TFlagAutoSeq = 1<<13,
1395 TFlagInsertTs = 1<<16,
1399 transmit(Wifi *wifi, Wnode *wn, Block *b)
1401 uchar c[Tcmdsize], *p;
1405 int flags, nodeid, rate, timeout;
1412 if(ctlr->attached == 0 || ctlr->broken){
1418 if((wn->channel != ctlr->channel)
1419 || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0)))
1423 /* association note has no data to transmit */
1430 nodeid = ctlr->bcastnodeid;
1432 w = (Wifipkt*)b->rp;
1433 if((w->a1[0] & 1) == 0){
1434 flags |= TFlagNeedACK;
1437 flags |= TFlagNeedRTS|TFlagFullTxOp;
1439 if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){
1441 nodeid = ctlr->bssnodeid;
1445 if(p >= wifi->rates)
1446 rate = p - wifi->rates;
1451 memset(p = c, 0, sizeof(c));
1452 put16(p, BLEN(b)), p += 2;
1453 put16(p, 0), p += 2; /* lnext */
1454 put32(p, flags), p += 4;
1455 *p++ = ratetab[rate].plcp;
1458 *p++ = 0; /* security */
1459 p += 16+8; /* key/iv */
1460 put32(p, 0), p += 4; /* fnext */
1461 put32(p, 0xffffffff), p += 4; /* livetime infinite */
1466 put16(p, timeout), p += 2;
1467 put16(p, 0), p += 2; /* txop */
1469 if((err = qcmd(ctlr, 0, 28, c, p - c, b)) != nil){
1470 print("transmit: %s\n", err);
1476 wpictl(Ether *edev, void *buf, long n)
1481 if(n >= 5 && memcmp(buf, "reset", 5) == 0){
1486 return wifictl(ctlr->wifi, buf, n);
1491 wpiifstat(Ether *edev, void *buf, long n, ulong off)
1497 return wifistat(ctlr->wifi, buf, n, off);
1502 setoptions(Ether *edev)
1508 for(i = 0; i < edev->nopt; i++)
1509 wificfg(ctlr->wifi, edev->opt[i]);
1513 wpipromiscuous(void *arg, int on)
1522 rxon(edev, ctlr->wifi->bss);
1527 wpimulticast(void *, uchar*, int)
1532 wpirecover(void *arg)
1542 tsleep(&up->sleep, return0, 0, 4000);
1546 if(ctlr->broken == 0)
1552 if((csr32r(ctlr, Gpc) & RfKill) == 0)
1555 if(reset(ctlr) != nil)
1557 if(boot(ctlr) != nil)
1560 ctlr->bcastnodeid = -1;
1561 ctlr->bssnodeid = -1;
1563 rxon(edev, ctlr->wifi->bss);
1571 wpiattach(Ether *edev)
1580 print("#l%d: %s\n", edev->ctlrno, up->errstr);
1586 if(ctlr->attached == 0){
1587 if((csr32r(ctlr, Gpc) & RfKill) == 0)
1588 error("wifi disabled by switch");
1590 if(ctlr->wifi == nil){
1591 qsetlimit(edev->oq, MaxQueue);
1593 ctlr->wifi = wifiattach(edev, transmit);
1594 ctlr->wifi->rates = wpirates;
1597 if(ctlr->fw == nil){
1598 fw = readfirmware();
1599 print("#l%d: firmware: %ux, size: %ux+%ux+%ux+%ux+%ux\n",
1600 edev->ctlrno, fw->version,
1601 fw->main.text.size, fw->main.data.size,
1602 fw->init.text.size, fw->init.data.size,
1603 fw->boot.text.size);
1607 if((err = reset(ctlr)) != nil)
1609 if((err = boot(ctlr)) != nil)
1612 ctlr->bcastnodeid = -1;
1613 ctlr->bssnodeid = -1;
1621 kproc("wpirecover", wpirecover, edev);
1637 if(ctlr->broken || ctlr->shared == nil || rx->b == nil)
1641 for(hw = ctlr->shared->next % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){
1642 uchar type, flags, idx, qid;
1650 len = get32(d); d += 4;
1659 if(0) iprint("rxdesc[%d] type=%d len=%d idx=%d qid=%d\n", rx->i, type, len, idx, qid);
1665 if((qid & 0x80) == 0 && qid < nelem(ctlr->tx)){
1666 tx = &ctlr->tx[qid];
1676 case 1: /* uc ready */
1679 case 24: /* add node done */
1682 case 27: /* rx done */
1687 if(d + 6 + 2 > b->lim){
1692 if(d + len + 4 > b->lim){
1695 if((get32(d + len) & 3) != 3){
1698 if(ctlr->wifi == nil)
1700 if(rbplant(ctlr, rx->i) < 0)
1704 wifiiq(ctlr->wifi, b);
1707 case 28: /* tx done */
1708 if(len <= 8 || d[8] == 1)
1710 wifitxfail(ctlr->wifi, bb);
1713 case 130: /* start scan */
1716 case 132: /* stop scan */
1719 case 161: /* state change */
1723 csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7);
1729 wpiinterrupt(Ureg*, void *arg)
1738 csr32w(ctlr, Imr, 0);
1739 isr = csr32r(ctlr, Isr);
1740 fhisr = csr32r(ctlr, FhIsr);
1741 if(isr == 0xffffffff || (isr & 0xfffffff0) == 0xa5a5a5a0){
1745 if(isr == 0 && fhisr == 0)
1747 csr32w(ctlr, Isr, isr);
1748 csr32w(ctlr, FhIsr, fhisr);
1749 if((isr & (Iswrx | Ifhrx)) || (fhisr & Ifhrx))
1753 iprint("#l%d: fatal firmware error, lastcmd %ud\n", edev->ctlrno, ctlr->tx[4].lastcmd);
1755 ctlr->wait.m |= isr;
1756 if(ctlr->wait.m & ctlr->wait.w)
1757 wakeup(&ctlr->wait);
1759 csr32w(ctlr, Imr, ctlr->ie);
1764 wpishutdown(Ether *edev)
1774 static Ctlr *wpihead, *wpitail;
1782 while(pdev = pcimatch(pdev, 0x8086, 0)){
1792 /* Clear device-specific "PCI retry timeout" register (41h). */
1793 if(pcicfgr8(pdev, 0x41) != 0)
1794 pcicfgw8(pdev, 0x41, 0);
1796 ctlr = malloc(sizeof(Ctlr));
1798 print("wpi: unable to alloc Ctlr\n");
1801 ctlr->port = pdev->mem[0].bar & ~0x0F;
1802 mem = vmap(pdev->mem[0].bar & ~0x0F, pdev->mem[0].size);
1804 print("wpi: can't map %8.8luX\n", pdev->mem[0].bar);
1812 wpitail->link = ctlr;
1828 for(ctlr = wpihead; ctlr != nil; ctlr = ctlr->link){
1831 if(edev->port == 0 || edev->port == ctlr->port){
1841 edev->port = ctlr->port;
1842 edev->irq = ctlr->pdev->intl;
1843 edev->tbdf = ctlr->pdev->tbdf;
1845 edev->attach = wpiattach;
1846 edev->ifstat = wpiifstat;
1848 edev->shutdown = wpishutdown;
1849 edev->promiscuous = wpipromiscuous;
1850 edev->multicast = wpimulticast;
1853 pcienable(ctlr->pdev);
1854 if(wpiinit(edev) < 0){
1855 pcidisable(ctlr->pdev);
1859 pcisetbme(ctlr->pdev);
1860 intrenable(edev->irq, wpiinterrupt, edev, edev->tbdf, edev->name);
1868 addethercard("wpi", wpipnp);