--- /sys/src/9/pc/etheriwl.c +++ /sys/src/9/pc/etheriwl.c @@ -329,7 +329,25 @@ SchedTransTblOff = 0x7E0, // +q*2 }; +/* + * uCode API flags + */ enum { + UcodeFlgTe2 = 1<<9, +}; + +/* + * uCode capabilities + */ +enum { + /* capa[0] */ + UcodeCapLar = 1<<1, + + /* capa[2] */ + UcodeCapLar2 = 1<<9, +}; + +enum { FilterPromisc = 1<<0, FilterCtl = 1<<1, FilterMulticast = 1<<2, @@ -418,6 +436,7 @@ uint build; char descr[64+1]; + u32int flags; u32int capa[4]; u32int api[4]; @@ -635,7 +654,7 @@ Type2030 = 12, Type2000 = 16, - Type7260 = 30, + Type7260 = 20, Type8265 = 35, }; @@ -1478,6 +1497,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 +2008,7 @@ *p++ = mcc[0]; *p++ = 0; *p++ = 0; // reserved - if(1){ + if(ctlr->fw->capa[2] & UcodeCapLar2){ p += 4; p += 5*4; } @@ -2272,7 +2296,9 @@ ea[5] = a1 >> 0; } } else { - readnvmsect(ctlr, 0, ea, Eaddrlen, 0x15<<1); + /* fw gets angry if we read 6 bytes instead of 8 */ + readnvmsect(ctlr, 0, buf, 8, 0x15<<1); + memmove(ea, buf, Eaddrlen); } memmove(ctlr->edev->addr, ea, Eaddrlen); @@ -2641,7 +2667,7 @@ settimeevent(Ctlr *ctlr, int amr, int ival) { int duration, delay, timeid; - uchar c[9*4], *p; + uchar c[14*4], *p; char *err; switch(amr){ @@ -2682,16 +2708,40 @@ p += 4; put32(p, delay); p += 4; + if((ctlr->fw->flags & UcodeFlgTe2) == 0){ + put32(p, 0); // dep policy + 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((ctlr->fw->flags & UcodeFlgTe2) == 0){ + put32(p, 0); // is present (reverse of absence flag) + p += 4; + } + + if(ctlr->fw->flags & UcodeFlgTe2){ + 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; + }else{ + put32(p, 0); // max frags + p += 4; + put32(p, 1); // interval + p += 4; + put32(p, 0); // interval reciprocal (UNUSED) + p += 4; + put32(p, duration); + p += 4; + put32(p, 1); // repeat + p += 4; + put32(p, 1<<0 | 1<<1); // notify + p += 4; + } ctlr->te.active = 0; if((err = cmd(ctlr, 41, c, p - c)) != nil) @@ -2822,13 +2872,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* @@ -2897,16 +2947,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 +3468,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 +3503,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; @@ -4283,8 +4334,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); } }