diff 60adc40118dda2edf2a238d22d050a7bae5e0d66 uncommitted --- a/sys/src/9/pc/etheriwl.c +++ b/sys/src/9/pc/etheriwl.c @@ -3,7 +3,7 @@ * * Written without any documentation but Damien Bergamini's * iwn(4) and Stefan Sperling's iwm(4) OpenBSD driver sources. - * Requires Intel firmware to be present in /lib/firmware/iw[nm]-* + * Requires Intel firmware to be present in /lib/firmware/ * on attach. */ @@ -329,7 +329,20 @@ SchedTransTblOff = 0x7E0, // +q*2 }; +/* + * uCode capabilities + */ enum { + UcodeApiMMcc = 9, + UcodeApiSta = 30, + + UcodeCapaLar = 1, + UcodeCapaMMcc = 29, + UcodeCapaQuota = 44, + UcodeCapaLar2 = 73, +}; + +enum { FilterPromisc = 1<<0, FilterCtl = 1<<1, FilterMulticast = 1<<2, @@ -565,7 +578,6 @@ uchar type; uchar step; uchar dash; - uchar pnum; uchar txantmask; uchar rxantmask; } rfcfg; @@ -586,8 +598,6 @@ } eeprom; struct { - u32int version; - void *buf; int len; @@ -634,9 +644,6 @@ Type6005 = 11, /* also Centrino Advanced-N 6030, 6235 */ Type2030 = 12, Type2000 = 16, - - Type7260 = 30, - Type8265 = 35, }; static struct ratetab { @@ -687,10 +694,9 @@ [Type1000] "iwn-1000", [Type6000] "iwn-6000", [Type6050] "iwn-6050", - [Type6005] "iwn-6005", /* see in iwlattach() below */ + [Type6005] "iwn-6005", /* 6030/6235 uses iwn-6030, see iwlpci() */ [Type2030] "iwn-2030", [Type2000] "iwn-2000", - [Type7260] "iwm-7260-17", }; static char *qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block); @@ -697,8 +703,10 @@ static char *flushq(Ctlr *ctlr, uint qid); static char *cmd(Ctlr *ctlr, uint code, uchar *data, int size); -#define csr32r(c, r) (*((c)->nic+((r)/4))) -#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) +#define csr32r(c, r) ((c)->nic[(r)/4]) +#define csr32w(c, r, v) ((c)->nic[(r)/4] = (v)) +/* macro to help with ctlr->fw->(api|capa) */ +#define isset(a, i) ((a)[(i)/32] & 1U<<(i)%32) static uint get16(uchar *p){ @@ -728,10 +736,12 @@ int i; csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq); - for(i=0; i<1000; i++){ + if(ctlr->family >= 8000) + microdelay(2); + for(i=0; i<1500; i++){ if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna) return 0; - delay(10); + microdelay(10); } return "niclock: timeout"; } @@ -944,7 +954,7 @@ for(j=0; j<100; j++){ if(csr32r(ctlr, Cfg) & EepromLocked) return 0; - delay(10); + microdelay(10); } } return "eepromlock: timeout"; @@ -969,7 +979,7 @@ w = csr32r(ctlr, EepromIo); if(w & 1) break; - delay(5); + microdelay(5); } if(i == 10) return "eepromread: timeout"; @@ -990,34 +1000,35 @@ static char* handover(Ctlr *ctlr) { - int i; + int n, i, j; csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady); for(i=0; i<5; i++){ if(csr32r(ctlr, Cfg) & NicReady) goto Ready; - delay(10); + microdelay(10); } + if(ctlr->family >= 7000){ csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31)); delay(1); } - csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | Prepare); - for(i=0; i<15000; i++){ - if((csr32r(ctlr, Cfg) & PrepareDone) == 0) - break; - delay(10); - } - if(i >= 15000) - return "handover: timeout"; + for(n=0; n<10; n++){ + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | Prepare); - csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady); - for(i=0; i<5; i++){ - if(csr32r(ctlr, Cfg) & NicReady) - goto Ready; - delay(10); + for(i=0; i<750; i++){ + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady); + for(j=0; j<5; j++){ + if(csr32r(ctlr, Cfg) & NicReady) + goto Ready; + microdelay(10); + } + microdelay(200); + } + delay(25); } + return "handover: timeout"; Ready: if(ctlr->family >= 7000) @@ -1035,7 +1046,7 @@ for(i=0; i<2500; i++){ if(csr32r(ctlr, Gpc) & MacClockReady) return 0; - delay(10); + microdelay(10); } return "clockwait: timeout"; } @@ -1046,7 +1057,6 @@ int capoff; char *err; - if(ctlr->family >= 7000){ /* Reset entire device */ csr32w(ctlr, Reset, (1<<7)); @@ -1093,14 +1103,13 @@ nicunlock(ctlr); } - /* Enable the oscillator to count wake up time for L1 exit. (weird W/A) */ - if(ctlr->type == Type7260){ + /* Enable the oscillator to count wake up time for L1 exit. (W/A for 7260/3160) */ + if(ctlr->pdev->did >= 0x08b1 && ctlr->pdev->did <= 0x08b4){ if((err = niclock(ctlr)) != nil) return err; prphread(ctlr, OscClk); prphread(ctlr, OscClk); - delay(20); prphwrite(ctlr, OscClk, prphread(ctlr, OscClk) | OscClkCtrl); @@ -1119,7 +1128,7 @@ prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt); else prphwrite(ctlr, ApmgClkEna, DmaClkRqt); - delay(20); + microdelay(20); /* Disable L1-Active. */ prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11)); @@ -1158,7 +1167,7 @@ for(j = 0; j < 200; j++){ if(csr32r(ctlr, FhTxStatus) & (0x10000<mqrx){ prphwrite(ctlr, RfhDmaCfg, 0); - for(j = 0; j < 200; j++){ + for(j = 0; j < 1000; j++){ if(prphread(ctlr, RfhGenStatus) & RfhGenStatusDmaIdle) break; - delay(10); + microdelay(10); } } else { csr32w(ctlr, FhRxConfig, 0); - for(j = 0; j < 200; j++){ + for(j = 0; j < 1000; j++){ if(csr32r(ctlr, FhRxStatus) & 0x1000000) break; - delay(10); + microdelay(10); } } nicunlock(ctlr); @@ -1190,7 +1199,7 @@ prphwrite(ctlr, ApmgClkDis, DmaClkRqt); nicunlock(ctlr); } - delay(5); + microdelay(5); } if(ctlr->family >= 7000){ @@ -1206,12 +1215,12 @@ for(j = 0; j < 100; j++){ if(csr32r(ctlr, Reset) & (1<<8)) break; - delay(10); + microdelay(10); } /* Reset the entire device. */ csr32w(ctlr, Reset, csr32r(ctlr, Reset) | (1<<7)); - delay(10); + delay(5); /* Clear "initialization complete" bit. */ csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~InitDone); @@ -1239,7 +1248,7 @@ if((err = niclock(ctlr)) != nil) return err; prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | ResetReq); - delay(5); + microdelay(5); prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) & ~ResetReq); nicunlock(ctlr); @@ -1308,11 +1317,12 @@ ctlr->type &= 0x1FF; ctlr->dash = ctlr->type & 3, ctlr->type >>= 2; ctlr->step = ctlr->type & 3, ctlr->type >>= 2; - if(fwname[ctlr->type] == nil){ + } + if(ctlr->fwname == nil) + if(ctlr->type >= nelem(fwname) || (ctlr->fwname = fwname[ctlr->type]) == nil){ print("iwl: unsupported controller type %d\n", ctlr->type); return -1; } - } if((err = handover(ctlr)) != nil) goto Err; @@ -1828,34 +1838,34 @@ csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | RadioSi | MacSi); } - if(ctlr->family < 8000){ + if(ctlr->family <= 7000 && ctlr->type != Type4965){ if((err = niclock(ctlr)) != nil) return err; - if(ctlr->family == 7000 || ctlr->type != Type4965) - prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | EarlyPwroffDis); - nicunlock(ctlr); - } - if(ctlr->family < 7000){ - if((err = niclock(ctlr)) != nil) - return err; - if(ctlr->type == Type1000){ - /* - * Select first Switching Voltage Regulator (1.32V) to - * solve a stability issue related to noisy DC2DC line - * in the silicon of 1000 Series. - */ + prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | EarlyPwroffDis); + /* + * Select first Switching Voltage Regulator (1.32V) to + * solve a stability issue related to noisy DC2DC line + * in the silicon of 1000 Series. + */ + if(ctlr->type == Type1000) prphwrite(ctlr, ApmgDigitalSvr, (prphread(ctlr, ApmgDigitalSvr) & ~(0xf<<5)) | (3<<5)); - } - if((ctlr->type == Type6005 || ctlr->type == Type6050) && ctlr->eeprom.version == 6) - csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvCalV6); - if(ctlr->type == Type6005) - csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrv1X2); - if(ctlr->type == Type2030 || ctlr->type == Type2000) - csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvRadioIqInvert); nicunlock(ctlr); } + switch(ctlr->type){ + case Type6005: + csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrv1X2); + case Type6050: + if(ctlr->eeprom.version >= 6) + csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvCalV6); + break; + case Type2030: + case Type2000: + csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvRadioIqInvert); + break; + } + if((err = niclock(ctlr)) != nil) return err; @@ -1979,14 +1989,20 @@ { uchar c[2+1+1+4+5*4], *p; + if(!isset(ctlr->fw->capa, UcodeCapaLar)) + return nil; + memset(p = c, 0, sizeof(c)); *p++ = mcc[1]; *p++ = mcc[0]; - *p++ = 0; - *p++ = 0; // reserved - if(1){ - p += 4; - p += 5*4; + if(isset(ctlr->fw->api, UcodeApiMMcc) || isset(ctlr->fw->capa, UcodeCapaMMcc)) + *p++ = 0x10; /* source id */ + else + p++; /* reserved */ + p++; /* reserved */ + if(isset(ctlr->fw->capa, UcodeCapaLar2)){ + p += 4; /* integrity key (???) */ + p += 5*4; /* reserved */ } return cmd(ctlr, 200, c, p - c); } @@ -2009,10 +2025,9 @@ p = c; if(ctlr->family >= 7000){ - put32(p, 3); + put32(p, 3); /* mode */ p += 4; - put32(p, (1<<4)); - p += 4; + p += 4; /* enabled modules */ } else if(ctlr->type == Type2030){ *p++ = 145; /* flags */ p++; /* lead time */ @@ -2217,45 +2232,31 @@ return o; } +static int +invalidea(uchar *ea) +{ + static uchar reserved[] = {0x02, 0xcc, 0xaa, 0xff, 0xee, 0x00}; + + return ea[0] & 1 || memcmp(ea, reserved, Eaddrlen) == 0; +} + static char* readnvmconfig(Ctlr *ctlr) { uchar *ea = ctlr->edev->ea; uchar buf[8]; - uint u; char *err; - - if(readnvmsect(ctlr, 1, buf, 8, 0) != 8) - return "can't read nvm version"; - - ctlr->nvm.version = get16(buf); - if (ctlr->family == 7000) { - u = get16(buf + 2); - - ctlr->rfcfg.type = (u >> 4) & 3; - ctlr->rfcfg.step = (u >> 2) & 3; - ctlr->rfcfg.dash = (u >> 0) & 3; - ctlr->rfcfg.pnum = (u >> 6) & 3; - - ctlr->rfcfg.txantmask = (u >> 8) & 15; - ctlr->rfcfg.rxantmask = (u >> 12) & 15; - - } else { + + if(ctlr->family >= 8000){ if(readnvmsect(ctlr, 12, buf, 8, 0) != 8) return "can't read nvm phy config"; u = get32(buf); - ctlr->rfcfg.type = (u >> 12) & 0xFFF; - ctlr->rfcfg.step = (u >> 8) & 15; - ctlr->rfcfg.dash = (u >> 4) & 15; - ctlr->rfcfg.pnum = (u >> 6) & 3; - ctlr->rfcfg.txantmask = (u >> 24) & 15; ctlr->rfcfg.rxantmask = (u >> 28) & 15; - } - if(ctlr->family >= 8000){ - if(readnvmsect(ctlr, 11, ea, Eaddrlen, 0x01<<1) != Eaddrlen){ + + if(readnvmsect(ctlr, 11, ea, Eaddrlen, 1*2) != Eaddrlen || invalidea(ea)){ u32int a0, a1; if((err = niclock(ctlr)) != nil) @@ -2270,9 +2271,18 @@ ea[3] = a0 >> 0; ea[4] = a1 >> 8; ea[5] = a1 >> 0; - } - } else { - readnvmsect(ctlr, 0, ea, Eaddrlen, 0x15<<1); + } + }else{ + /* fw gets angry if we read 6 bytes, read 8 bytes to make the fw happy. */ + if(readnvmsect(ctlr, 0, buf, 8, (0x15-1)*2) != 8) + return "can't read ea from nvm"; + + ea[0] = buf[3]; + ea[1] = buf[2]; + ea[2] = buf[5]; + ea[3] = buf[4]; + ea[4] = buf[7]; + ea[5] = buf[6]; } memmove(ctlr->edev->addr, ea, Eaddrlen); @@ -2285,18 +2295,20 @@ uchar c[4]; put32(c, val); - return cmd(ctlr, 152, c, 4); + return cmd(ctlr, 152, c, sizeof(c)); } static char* -sendphyconfig(Ctlr *ctlr, u32int physku, u32int flowmask, u32int eventmask) +sendphyconfig(Ctlr *ctlr, u32int flowmask, u32int eventmask) { uchar c[3*4]; - put32(c+0, physku); + put32(c+0, ctlr->fw->physku & 0xff00ffff | + ctlr->rfcfg.txantmask << 16 | + ctlr->rfcfg.rxantmask << 20); put32(c+4, flowmask); put32(c+8, eventmask); - return cmd(ctlr, 106, c, 3*4); + return cmd(ctlr, 106, c, sizeof(c)); } static char* @@ -2311,7 +2323,7 @@ memset(p = c, 0, sizeof(c)); *p = sta->id; - if((err = cmd(ctlr, 25, c, 4)) != nil) + if((err = cmd(ctlr, 25, c, sizeof(c))) != nil) return err; sta->id = -1; @@ -2366,7 +2378,7 @@ p += 2; /* sleep_tx_count */ p++; /* sleep state flags */ - *p++ = (ctlr->fw->api[0] & (1<<30)) != 0 ? type : 0; /* station_type */ + *p++ = isset(ctlr->fw->api, UcodeApiSta) ? type : 0; /* station_type */ p += 2; /* assoc id */ @@ -2375,7 +2387,7 @@ put32(p, 1<<0); p += 4; /* tfd_queue_mask */ - if(1){ + if(isset(ctlr->fw->api, UcodeApiSta)){ p += 2; /* rx_ba_window */ p++; /* sp_length */ p++; /* uapsd_acs */ @@ -2640,7 +2652,7 @@ static char* settimeevent(Ctlr *ctlr, int amr, int ival) { - int duration, delay, timeid; + int timeid; uchar c[9*4], *p; char *err; @@ -2662,14 +2674,6 @@ break; } - if(ival){ - duration = ival*2; - delay = ival/2; - } else { - duration = 1024; - delay = 0; - } - memset(p = c, 0, sizeof(c)); put32(p, ctlr->macid); p += 4; @@ -2678,23 +2682,27 @@ put32(p, timeid); p += 4; - put32(p, 0); // apply time - p += 4; - put32(p, delay); - p += 4; - put32(p, 0); // depends on - p += 4; - put32(p, 1); // interval - p += 4; - put32(p, duration); - p += 4; - *p++ = 1; // repeat - *p++ = 0; // max frags - put16(p, 1<<0 | 1<<1 | 1<<11); // policy - p += 2; + if(amr == CmdRemove) + p += 6*4; + else{ + put32(p, 0); // apply time + p += 4; + put32(p, ival/2); // max delay + p += 4; + put32(p, 0); // depends on + p += 4; + put32(p, 1); // interval + p += 4; + put32(p, ival? ival*2: 1024); // duration + p += 4; + *p++ = 1; // repeat + *p++ = 0; // max frags + put16(p, 1<<0 | 1<<1 | 1<<11); // policy + p += 2; + } ctlr->te.active = 0; - if((err = cmd(ctlr, 41, c, p - c)) != nil) + if((err = cmd(ctlr, 41, c, p - c)) != nil) return err; if(amr == CmdRemove){ @@ -2713,6 +2721,9 @@ uchar c[4*(3*4)], *p; int i; + if(!isset(ctlr->fw->capa, UcodeCapaQuota)) + return nil; + i = 0; p = c; @@ -2819,16 +2830,16 @@ uchar c[11*4]; memset(c, 0, sizeof(c)); - return cmd(ctlr, 210, c, 11*4); + return cmd(ctlr, 210, c, sizeof(c)); } -static void +static char* tttxbackoff(Ctlr *ctlr) { uchar c[4]; put32(c, 0); - cmd(ctlr, 126, c, sizeof(c)); + return cmd(ctlr, 126, c, sizeof(c)); } static char* @@ -2839,7 +2850,7 @@ memset(c, 0, sizeof(c)); put16(c, 0<<13 | 1<<0); // cont active off, pm enable - return cmd(ctlr, 119, c, 4); + return cmd(ctlr, 119, c, sizeof(c)); } static char* @@ -2850,6 +2861,9 @@ if(ctlr->calib.done == 0){ if((err = readnvmconfig(ctlr)) != nil) return err; + if(ctlr->family == 7000) + if((err = sendbtcoexadv(ctlr)) != nil) + return err; } if((err = sendtxantconfig(ctlr, ctlr->rfcfg.txantmask)) != nil) @@ -2857,7 +2871,6 @@ if(ctlr->calib.done == 0){ if((err = sendphyconfig(ctlr, - ctlr->fw->physku, ctlr->fw->init.defcalib.flowmask, ctlr->fw->init.defcalib.eventmask)) != nil) return err; @@ -2871,6 +2884,7 @@ ctlr->calib.done = 1; } } else { + uchar c[4]; Block *b; int i; @@ -2877,8 +2891,23 @@ for(i = 0; i < nelem(ctlr->calib.cmd); i++){ if((b = ctlr->calib.cmd[i]) == nil) continue; + print("iwl: calibration command %d is going to be sent\n", i); + if(b == ctlr->calib.cfg) + put16(c, 1); + else if(b == ctlr->calib.nch) + put16(c, 2); + else if(ctlr->calib.cmd+i >= ctlr->calib.papd && + ctlr->calib.cmd+i < ctlr->calib.papd+nelem(ctlr->calib.papd)) + put16(c, 4); + else if(ctlr->calib.cmd+i >= ctlr->calib.txp && + ctlr->calib.cmd+i < ctlr->calib.txp+nelem(ctlr->calib.txp)) + put16(c, 5); + else + continue; + put16(c+2, BLEN(b)); + b = copyblock(b, BLEN(b)); - if((qcmd(ctlr, 4, 108, nil, 0, b)) != nil){ + if((qcmd(ctlr, 4, 108, c, sizeof(c), b)) != nil){ freeb(b); return err; } @@ -2887,7 +2916,6 @@ } if((err = sendphyconfig(ctlr, - ctlr->fw->physku, ctlr->fw->main.defcalib.flowmask, ctlr->fw->main.defcalib.eventmask)) != nil) return err; @@ -2895,9 +2923,9 @@ if((err = sendbtcoexadv(ctlr)) != nil) return err; - /* Initialize tx backoffs to the minimum. */ if(ctlr->family == 7000) - tttxbackoff(ctlr); + if((err = tttxbackoff(ctlr)) != nil) + return err; if((err = updatedevicepower(ctlr)) != nil){ print("can't update device power: %s\n", err); @@ -2904,7 +2932,7 @@ return err; } if((err = sendmccupdate(ctlr, "ZZ")) != nil){ - print("can't disable beacon filter: %s\n", err); + print("can't send mcc update: %s\n", err); return err; } if((err = disablebeaconfilter(ctlr)) != nil){ @@ -3034,10 +3062,9 @@ if((err = sendtxantconfig(ctlr, ctlr->rfcfg.txantmask & 7)) != nil) return err; - if(ctlr->type == Type2030){ + if(ctlr->type == Type2030) if((err = sendbtcoexadv(ctlr)) != nil) return err; - } } return nil; } @@ -3362,7 +3389,7 @@ for(i=0; i<1000; i++){ if((prphread(ctlr, BsmWrCtrl) & (1<<31)) == 0) break; - delay(10); + microdelay(10); } if(i == 1000){ nicunlock(ctlr); @@ -3418,6 +3445,7 @@ static char* qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block) { + char *err; int hdrlen; Block *bcmd; uchar *d, *c; @@ -3451,12 +3479,6 @@ iunlock(ctlr); return "qcmd: broken"; } - /* wake up the nic (just needed for 7k) */ - if(ctlr->family == 7000 && q->n == 0) - if(niclock(ctlr) != nil){ - iunlock(ctlr); - return "qcmd: busy"; - } q->n++; q->lastcmd = code; @@ -3507,6 +3529,13 @@ coherence(); + /* wake up the nic so it sees the command */ + if(ctlr->family == 7000 && qid == 4 && q->n == 0) + if((err = niclock(ctlr)) != nil){ + iunlock(ctlr); + return err; + } + q->i = (q->i+1) % Ntx; csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i); @@ -3586,9 +3615,16 @@ int i; for(i = 0; i < nelem(ctlr->tx); i++) - flushq(ctlr, i); - settimeevent(ctlr, CmdRemove, 0); + if((err = flushq(ctlr, i)) != nil){ + print("can't flush queue %d: %s\n", i, err); + return err; + } + if((err = settimeevent(ctlr, CmdRemove, 0)) != nil){ + print("can't remove time event: %s\n", err); + return err; + } + if((err = setbindingquotas(ctlr, -1)) != nil){ print("can't disable quotas: %s\n", err); return err; @@ -3630,7 +3666,7 @@ return err; } if((err = setbindingcontext(ctlr, CmdAdd)) != nil){ - print("removing bindingcontext: %s\n", err); + print("adding bindingcontext: %s\n", err); return err; } if((err = setmcastfilter(ctlr)) != nil){ @@ -3984,7 +4020,6 @@ static void iwlattach(Ether *edev) { - FWImage *fw; Ctlr *ctlr; char *err; @@ -4002,29 +4037,13 @@ error("wifi disabled by switch"); if(ctlr->fw == nil){ - char *fn; - - fn = ctlr->fwname; - if(fn == nil){ - 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); + ctlr->fw = readfirmware(ctlr->fwname); print("#l%d: firmware: %s, rev %ux, build %ud, size [%d] %ux+%ux + [%d] %ux+%ux + %ux\n", - edev->ctlrno, fn, - fw->rev, fw->build, - fw->main.nsect, fw->main.text.size, fw->main.data.size, - fw->init.nsect, fw->init.text.size, fw->init.data.size, - fw->boot.text.size); - ctlr->fw = fw; + edev->ctlrno, ctlr->fwname, + ctlr->fw->rev, ctlr->fw->build, + ctlr->fw->main.nsect, ctlr->fw->main.text.size, ctlr->fw->main.data.size, + ctlr->fw->init.nsect, ctlr->fw->init.text.size, ctlr->fw->init.data.size, + ctlr->fw->boot.text.size); } if(ctlr->family >= 7000){ @@ -4282,17 +4301,14 @@ freeblist(bb); if(tx != nil && tx->n > 0){ tx->n--; - wakeup(tx); /* unlock 7k family nics as all commands are done */ - if(ctlr->family == 7000 && tx->n == 0) + if(ctlr->family == 7000 && qid == 4 && tx->n == 0) nicunlock(ctlr); + wakeup(tx); } } - if(ctlr->mqrx){ - csr32w(ctlr, FhRxQ0Wptr, ((hw+Nrx-1) % Nrx) & ~7); - }else - csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7); + csr32w(ctlr, ctlr->mqrx ? FhRxQ0Wptr : FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7); } static void @@ -4354,14 +4370,12 @@ int family; pdev = nil; - while(pdev = pcimatch(pdev, 0, 0)) { + while(pdev = pcimatch(pdev, 0x8086, 0)){ Ctlr *ctlr; void *mem; if(pdev->ccrb != 2 || pdev->ccru != 0x80) continue; - if(pdev->vid != 0x8086) - continue; if(pdev->mem[0].bar & 1) continue; @@ -4389,19 +4403,28 @@ case 0x0891: /* Centrino Wireless-N 2200 */ case 0x0887: /* Centrino Wireless-N 2230 */ case 0x0888: /* Centrino Wireless-N 2230 */ + family = 0; + fwname = nil; + break; case 0x0090: /* Centrino Advanced-N 6030 */ case 0x0091: /* Centrino Advanced-N 6030 */ case 0x088e: /* Centrino Advanced-N 6235 */ case 0x088f: /* Centrino Advanced-N 6235 */ family = 0; - fwname = nil; + fwname = "iwn-6030"; break; case 0x08b1: /* Wireless AC 7260 */ case 0x08b2: /* Wireless AC 7260 */ family = 7000; - fwname = nil; + fwname = "iwm-7260-17"; break; + case 0x08b3: /* Wireless AC 3160 */ + case 0x08b4: /* Wireless AC 3160 */ + family = 7000; + fwname = "iwm-3160-17"; + break; case 0x24f3: /* Wireless AC 8260 */ + case 0x24f4: /* Wireless AC 8260 */ family = 8000; fwname = "iwm-8000C-34"; break;