--- /sys/src/9/pc/etheriwl.c +++ /sys/src/9/pc/etheriwl.c @@ -329,7 +329,29 @@ SchedTransTblOff = 0x7E0, // +q*2 }; +/* + * uCode TLV api + */ enum { + /* api[0] */ + UcodeApiSta = 1<<30, +}; + +/* + * uCode capabilities + */ +enum { + /* capa[0] */ + UcodeCapLar = 1<<1, + + /* capa[1] */ + UcodeCapQuota = 1<<12, + + /* capa[2] */ + UcodeCapLar2 = 1<<9, +}; + +enum { FilterPromisc = 1<<0, FilterCtl = 1<<1, FilterMulticast = 1<<2, @@ -418,6 +440,7 @@ uint build; char descr[64+1]; + u32int flags; u32int capa[4]; u32int api[4]; @@ -635,7 +658,7 @@ Type2030 = 12, Type2000 = 16, - Type7260 = 30, + Type7260 = 20, Type8265 = 35, }; @@ -1478,6 +1501,11 @@ s = &i->boot.text; s->addr = 0x00000000; goto Sect; + case 18: + if(l < 4) + goto Tooshort; + i->flags = get32(p); + break; case 19: if(i->main.nsect >= nelem(i->main.sect)) return "too many main sections"; @@ -1984,7 +2012,7 @@ *p++ = mcc[0]; *p++ = 0; *p++ = 0; // reserved - if(1){ + if(ctlr->fw->capa[2] & UcodeCapLar2){ p += 4; p += 5*4; } @@ -2272,7 +2300,9 @@ ea[5] = a1 >> 0; } } else { - readnvmsect(ctlr, 0, ea, Eaddrlen, 0x15<<1); + /* fw gets angry if we read 6 bytes */ + readnvmsect(ctlr, 0, buf, 8, 0x15<<1); + memmove(ea, buf, Eaddrlen); } memmove(ctlr->edev->addr, ea, Eaddrlen); @@ -2366,7 +2396,7 @@ p += 2; /* sleep_tx_count */ p++; /* sleep state flags */ - *p++ = (ctlr->fw->api[0] & (1<<30)) != 0 ? type : 0; /* station_type */ + *p++ = ctlr->fw->api[0] & UcodeApiSta ? type : 0; /* station_type */ p += 2; /* assoc id */ @@ -2375,7 +2405,7 @@ put32(p, 1<<0); p += 4; /* tfd_queue_mask */ - if(1){ + if(ctlr->fw->api[0] & UcodeApiSta){ p += 2; /* rx_ba_window */ p++; /* sp_length */ p++; /* uapsd_acs */ @@ -2640,7 +2670,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 +2692,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,32 +2700,36 @@ 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) return err; + tsleep(&ctlr->te, timeeventdone, ctlr, 100); if(amr == CmdRemove){ ctlr->te.active = 0; ctlr->te.id = -1; return nil; - } - tsleep(&ctlr->te, timeeventdone, ctlr, 100); - return ctlr->te.active? nil: "timeevent did not start"; + }else + return ctlr->te.active? nil: "timeevent did not start"; } @@ -2713,6 +2739,9 @@ uchar c[4*(3*4)], *p; int i; + if((ctlr->fw->capa[1] & UcodeCapQuota) == 0) + return nil; + i = 0; p = c; @@ -2822,13 +2851,13 @@ return cmd(ctlr, 210, c, 11*4); } -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* @@ -2848,6 +2877,9 @@ char *err; if(ctlr->calib.done == 0){ + if(ctlr->family == 7000) + if((err = sendbtcoexadv(ctlr)) != nil) + return err; if((err = readnvmconfig(ctlr)) != nil) return err; } @@ -2897,16 +2929,16 @@ /* 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); return err; } - if((err = sendmccupdate(ctlr, "ZZ")) != nil){ - print("can't disable beacon filter: %s\n", err); - return err; - } + if(ctlr->fw->capa[0] & UcodeCapLar) + if((err = sendmccupdate(ctlr, "ZZ")) != nil) + return err; if((err = disablebeaconfilter(ctlr)) != nil){ print("can't disable beacon filter: %s\n", err); return err; @@ -3418,6 +3450,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; @@ -3452,10 +3485,10 @@ return "qcmd: broken"; } /* wake up the nic (just needed for 7k) */ - if(ctlr->family == 7000 && q->n == 0) - if(niclock(ctlr) != nil){ + if(ctlr->family == 7000 && qid == 4 && q->n == 0) + if((err = niclock(ctlr)) != nil){ iunlock(ctlr); - return "qcmd: busy"; + return err; } q->n++; q->lastcmd = code; @@ -3586,9 +3619,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 +3670,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){ @@ -4283,8 +4323,8 @@ 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) + /* unlock 7k family nics as the command is done */ + if(ctlr->family == 7000 && qid == 4 && tx->n == 0) nicunlock(ctlr); } }