]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/pc/etheriwl.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / etheriwl.c
index aba316f0f83a85d7a7c4293db97954c75b5de372..22e92884bbda48457c733c1a8d220d2e8f11e325 100644 (file)
 #include "io.h"
 #include "../port/error.h"
 #include "../port/netif.h"
-
-#include "etherif.h"
-#include "wifi.h"
+#include "../port/etherif.h"
+#include "../port/wifi.h"
 
 enum {
+       MaxQueue        = 24*1024,      /* total buffer is 2*MaxQueue: 48k at 22Mbit ≅ 20ms */
+
        Ntxlog          = 8,
        Ntx             = 1<<Ntxlog,
+       Ntxqmax         = MaxQueue/1500,
+
        Nrxlog          = 8,
        Nrx             = 1<<Nrxlog,
 
@@ -399,11 +402,12 @@ enum {
        Type1000        = 6,
        Type6000        = 7,
        Type6050        = 8,
-       Type6005        = 11,
+       Type6005        = 11,   /* also Centrino Advanced-N 6030, 6235 */
        Type2030        = 12,
+       Type2000        = 16,
 };
 
-static char *fwname[16] = {
+static char *fwname[32] = {
        [Type4965] "iwn-4965",
        [Type5300] "iwn-5000",
        [Type5350] "iwn-5000",
@@ -412,8 +416,9 @@ static char *fwname[16] = {
        [Type1000] "iwn-1000",
        [Type6000] "iwn-6000",
        [Type6050] "iwn-6050",
-       [Type6005] "iwn-6005",
+       [Type6005] "iwn-6005", /* see in iwlattach() below */
        [Type2030] "iwn-2030",
+       [Type2000] "iwn-2000",
 };
 
 static char *qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block);
@@ -818,6 +823,23 @@ iwlinit(Ether *edev)
        uint u, caloff, regoff;
 
        ctlr = edev->ctlr;
+
+       /* Clear device-specific "PCI retry timeout" register (41h). */
+       if(pcicfgr8(ctlr->pdev, 0x41) != 0)
+               pcicfgw8(ctlr->pdev, 0x41, 0);
+
+       /* Clear interrupt disable bit. Hardware bug workaround. */
+       if(ctlr->pdev->pcr & 0x400){
+               ctlr->pdev->pcr &= ~0x400;
+               pcicfgw16(ctlr->pdev, PciPCR, ctlr->pdev->pcr);
+       }
+
+       ctlr->type = (csr32r(ctlr, Rev) >> 4) & 0x1F;
+       if(fwname[ctlr->type] == nil){
+               print("iwl: unsupported controller type %d\n", ctlr->type);
+               return -1;
+       }
+
        if((err = handover(ctlr)) != nil)
                goto Err;
        if((err = poweron(ctlr)) != nil)
@@ -863,7 +885,7 @@ iwlinit(Ether *edev)
 
        ctlr->eeprom.temp = 0;
        ctlr->eeprom.rawtemp = 0;
-       if(ctlr->type == Type2030){
+       if(ctlr->type == Type2030 || ctlr->type == Type2000){
                if((err = eepromread(ctlr, b, 2, caloff + 0x12a)) != nil)
                        goto Err2;
                ctlr->eeprom.temp = get16(b);
@@ -1183,7 +1205,7 @@ reset(Ctlr *ctlr)
                csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvCalV6);
        if(ctlr->type == Type6005)
                csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrv1X2);
-       if(ctlr->type == Type2030)
+       if(ctlr->type == Type2030 || ctlr->type == Type2000)
                csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvRadioIqInvert);
        nicunlock(ctlr);
 
@@ -1435,10 +1457,11 @@ postboot(Ctlr *ctlr)
                                Block *b;
 
                                i = cmds[q];
-                               if(i == 8 && ctlr->type != Type5150 && ctlr->type != Type2030)
+                               if(i == 8 && ctlr->type != Type5150 && ctlr->type != Type2030 &&
+                                       ctlr->type != Type2000)
                                        continue;
                                if(i == 17 && (ctlr->type >= Type6000 || ctlr->type == Type5150) &&
-                                       ctlr->type != Type2030)
+                                       ctlr->type != Type2030 && ctlr->type != Type2000)
                                        continue;
 
                                if((b = ctlr->calib.cmd[i]) == nil)
@@ -1466,6 +1489,7 @@ postboot(Ctlr *ctlr)
                                break;
 
                        case Type2030:
+                       case Type2000:
                                memset(c, 0, sizeof(c));
                                c[0] = 18;
                                c[1] = 0;
@@ -1666,7 +1690,7 @@ static int
 txqready(void *arg)
 {
        TXQ *q = arg;
-       return q->n < Ntx;
+       return q->n < Ntxqmax;
 }
 
 static char*
@@ -1680,11 +1704,11 @@ qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
 
        ilock(ctlr);
        q = &ctlr->tx[qid];
-       while(q->n >= Ntx && !ctlr->broken){
+       while(q->n >= Ntxqmax && !ctlr->broken){
                iunlock(ctlr);
                qlock(q);
                if(!waserror()){
-                       tsleep(q, txqready, q, 10);
+                       tsleep(q, txqready, q, 5);
                        poperror();
                }
                qunlock(q);
@@ -1845,7 +1869,12 @@ rxon(Ether *edev, Wnode *bss)
                        ctlr->channel = bss->channel;
                bss = nil;
        }
+       flags = RFlagTSF | RFlagCTSToSelf | RFlag24Ghz | RFlagAuto;
        if(bss != nil){
+               if(bss->cap & (1<<5))
+                       flags |= RFlagShPreamble;
+               if(bss->cap & (1<<10))
+                       flags |= RFlagShSlot;
                ctlr->channel = bss->channel;
                memmove(ctlr->bssid, bss->bssid, Eaddrlen);
                ctlr->aid = bss->aid;
@@ -1861,7 +1890,6 @@ rxon(Ether *edev, Wnode *bss)
                ctlr->bcastnodeid = -1;
                ctlr->bssnodeid = -1;
        }
-       flags = RFlagTSF | RFlagCTSToSelf | RFlag24Ghz | RFlagAuto;
 
        if(ctlr->aid != 0)
                setled(ctlr, 2, 0, 1);          /* on when associated */
@@ -1925,6 +1953,7 @@ static struct ratetab {
        {   4,  20, RFlagCCK },
        {  11,  55, RFlagCCK },
        {  22, 110, RFlagCCK },
+
        {  12, 0xd, 0 },
        {  18, 0xf, 0 },
        {  24, 0x5, 0 },
@@ -1941,6 +1970,7 @@ static uchar iwlrates[] = {
        0x80 | 4,
        0x80 | 11,
        0x80 | 22,
+
        0x80 | 12,
        0x80 | 18,
        0x80 | 24,
@@ -2022,12 +2052,12 @@ transmit(Wifi *wifi, Wnode *wn, Block *b)
                                flags |= TFlagFullTxOp;
                }
        }
+       if(p >= wifi->rates)
+               rate = p - wifi->rates;
+       else
+               rate = 0;
        qunlock(ctlr);
 
-       rate = 0;
-       if(p >= iwlrates && p < &iwlrates[nelem(ratetab)])
-               rate = p - iwlrates;
-
        /* select first available antenna */
        ant = ctlr->rfcfg.txantmask & 7;
        ant |= (ant == 0);
@@ -2188,6 +2218,8 @@ iwlattach(Ether *edev)
                        error("wifi disabled by switch");
 
                if(ctlr->wifi == nil){
+                       qsetlimit(edev->oq, MaxQueue);
+
                        ctlr->wifi = wifiattach(edev, transmit);
                        /* tested with 2230, it has transmit issues using higher bit rates */
                        if(ctlr->type != Type2030)
@@ -2195,10 +2227,19 @@ iwlattach(Ether *edev)
                }
 
                if(ctlr->fw == nil){
-                       fw = readfirmware(fwname[ctlr->type]);
+                       char *fn = fwname[ctlr->type];
+                       if(ctlr->type == Type6005){
+                               switch(ctlr->pdev->did){
+                               case 0x0082:    /* Centrino Advanced-N 6205 */
+                               case 0x0085:    /* Centrino Advanced-N 6205 */
+                                       break;
+                               default:        /* Centrino Advanced-N 6030, 6235 */
+                                       fn = "iwn-6030";
+                               }
+                       }
+                       fw = readfirmware(fn);
                        print("#l%d: firmware: %s, rev %ux, build %ud, size %ux+%ux+%ux+%ux+%ux\n",
-                               edev->ctlrno,
-                               fwname[ctlr->type],
+                               edev->ctlrno, fn,
                                fw->rev, fw->build,
                                fw->main.text.size, fw->main.data.size,
                                fw->init.text.size, fw->init.data.size,
@@ -2424,32 +2465,29 @@ iwlpci(void)
                case 0x4229:    /* WiFi Link 4965 */
                case 0x4230:    /* WiFi Link 4965 */
                case 0x4232:    /* Wifi Link 5100 */
+               case 0x4235:    /* Intel Corporation Ultimate N WiFi Link 5300 */
                case 0x4236:    /* WiFi Link 5300 AGN */
                case 0x4237:    /* Wifi Link 5100 AGN */
+               case 0x4239:    /* Centrino Advanced-N 6200 */
                case 0x423d:    /* Wifi Link 5150 */
+               case 0x423b:    /* PRO/Wireless 5350 AGN */
+               case 0x0082:    /* Centrino Advanced-N 6205 */
                case 0x0085:    /* Centrino Advanced-N 6205 */
                case 0x422b:    /* Centrino Ultimate-N 6300 variant 1 */
                case 0x4238:    /* Centrino Ultimate-N 6300 variant 2 */
                case 0x08ae:    /* Centrino Wireless-N 100 */
                case 0x0083:    /* Centrino Wireless-N 1000 */
+               case 0x008a:    /* Centrino Wireless-N 1030 */
+               case 0x0891:    /* Centrino Wireless-N 2200 */
                case 0x0887:    /* Centrino Wireless-N 2230 */
                case 0x0888:    /* Centrino Wireless-N 2230 */
+               case 0x0090:    /* Centrino Advanced-N 6030 */
+               case 0x0091:    /* Centrino Advanced-N 6030 */
+               case 0x088e:    /* Centrino Advanced-N 6235 */
+               case 0x088f:    /* Centrino Advanced-N 6235 */
                        break;
                }
 
-               /* Clear device-specific "PCI retry timeout" register (41h). */
-               if(pcicfgr8(pdev, 0x41) != 0)
-                       pcicfgw8(pdev, 0x41, 0);
-
-               /* Clear interrupt disable bit. Hardware bug workaround. */
-               if(pdev->pcr & 0x400){
-                       pdev->pcr &= ~0x400;
-                       pcicfgw16(pdev, PciPCR, pdev->pcr);
-               }
-
-               pcisetbme(pdev);
-               pcisetpms(pdev, 0);
-
                ctlr = malloc(sizeof(Ctlr));
                if(ctlr == nil) {
                        print("iwl: unable to alloc Ctlr\n");
@@ -2464,14 +2502,6 @@ iwlpci(void)
                }
                ctlr->nic = mem;
                ctlr->pdev = pdev;
-               ctlr->type = (csr32r(ctlr, Rev) >> 4) & 0xF;
-
-               if(fwname[ctlr->type] == nil){
-                       print("iwl: unsupported controller type %d\n", ctlr->type);
-                       vunmap(mem, pdev->mem[0].size);
-                       free(ctlr);
-                       continue;
-               }
 
                if(iwlhead != nil)
                        iwltail->link = ctlr;
@@ -2506,7 +2536,6 @@ again:
        edev->irq = ctlr->pdev->intl;
        edev->tbdf = ctlr->pdev->tbdf;
        edev->arg = edev;
-       edev->interrupt = iwlinterrupt;
        edev->attach = iwlattach;
        edev->ifstat = iwlifstat;
        edev->ctl = iwlctl;
@@ -2515,10 +2544,15 @@ again:
        edev->multicast = iwlmulticast;
        edev->mbps = 54;
 
+       pcienable(ctlr->pdev);
        if(iwlinit(edev) < 0){
+               pcidisable(ctlr->pdev);
                edev->ctlr = nil;
                goto again;
        }
+
+       pcisetbme(ctlr->pdev);
+       intrenable(edev->irq, iwlinterrupt, edev, edev->tbdf, edev->name);
        
        return 0;
 }