support ich-style flash devices through bar[1]. identify actual device correctly. Reference: /n/sources/patch/applied/82563ich Date: Sun Jan 6 21:15:21 CET 2008 Signed-off-by: quanstro@quanstro.net --- /sys/src/9/pc/ether82563.c Sun Jan 6 21:13:33 2008 +++ /sys/src/9/pc/ether82563.c Sun Jan 6 21:13:23 2008 @@ -357,6 +357,33 @@ CssSHIFT = 8, }; +typedef struct{ + ushort *reg; + u32int *reg32; + int sz; +}Flash; + +enum{ + /* 16 and 32-bit flash registers for ich flash parts. */ + Bfpr = 0x00/4, /* flash base 0:12; lim 16:28 */ + Fsts = 0x04/2, /* flash status; Hsfs */ + Fctl = 0x06/2, /* flash control; */ + Faddr = 0x08/4, /* flash address to r/w */ + Fdata = 0x10/4, /* data @ address */ + + /* status register */ + Fdone = 1<<0, /* flash cycle done */ + Fcerr = 1<<1, /* cycle error; write 1 to clear */ + Ael = 1<<2, /* direct access error log; 1 to clear */ + Scip = 1<<5, /* spi cycle in progress */ + Fvalid = 1<<14, /* flash descriptor valid */ + + /* control register */ + Fgo = 1<<0, /* start cycle */ + Flcycle = 1<<1, /* two bits: r=0; w=2 */ + Fdbc = 1<<8, /* bytes to read; 5 bits */ +}; + enum { Nrd = 256, /* power of two */ Ntd = 128, /* power of two */ @@ -403,7 +430,7 @@ int nrd; int ntd; int nrb; /* how many this Ctlr has in the pool */ - unsigned rbsz; /* unsigned for % and / by 1024 */ + int rbsz; int *nic; Lock imlock; @@ -441,7 +468,6 @@ Rendez trendez; QLock tlock; int tbusy; - int tdfree; Td *tdba; /* transmit descriptor base address */ Block **tb; /* transmit buffers */ int tdh; /* transmit descriptor head */ @@ -763,7 +789,6 @@ } memset(&ctlr->tdba[i], 0, sizeof(Td)); } - ctlr->tdfree = ctlr->ntd; csr32w(ctlr, Tidv, 128); r = csr32r(ctlr, Txdctl); r &= ~WthreshMASK; @@ -1084,7 +1109,7 @@ break; case i82571: case i82572: - i = (i-1) & 3; + i = i-1 & 3; break; } @@ -1292,7 +1317,7 @@ } static ushort -eeread(Ctlr* ctlr, int adr) +eeread(Ctlr *ctlr, int adr) { csr32w(ctlr, Eerd, EEstart | adr << 2); while ((csr32r(ctlr, Eerd) & EEdone) == 0) @@ -1301,7 +1326,7 @@ } static int -eeload(Ctlr* ctlr) +eeload(Ctlr *ctlr) { ushort sum; int data, adr; @@ -1315,6 +1340,80 @@ return sum; } +int +fcycle(Ctlr *, Flash *f) +{ + ushort s, i; + + s = f->reg[Fsts]; + if((s&Fvalid) == 0) + return -1; + f->reg[Fsts] |= Fcerr|Ael; + for(i = 0; i < 10; i++){ + if((s&Scip) == 0) + return 0; + delay(1); + s = f->reg[Fsts]; + } + return -1; +} + +int +fread(Ctlr *c, Flash *f, int ladr) +{ + ushort s; + + delay(1); + if(fcycle(c, f) == -1) + return -1; + f->reg[Fsts] |= Fdone; + f->reg32[Faddr] = ladr; + + /* setup flash control register */ + s = f->reg[Fctl]; + s &= ~(0x1f<<8); + s |= 2-1<<8; /* 2 bytes */ + s &= ~(2*Flcycle); /* read */ + f->reg[Fctl] = s|Fgo; + + while((f->reg[Fsts]&Fdone) == 0) + ; + if(f->reg[Fsts]&(Fcerr|Ael)) + return -1; + return f->reg32[Fdata]&0xffff; +} + +static int +fload(Ctlr *c) +{ + Flash f; + ulong data, io, r, adr; + ushort sum; + + io = c->pcidev->mem[1].bar & ~0x0f; + f.reg = vmap(io, c->pcidev->mem[1].size); + if(f.reg == nil) + return -1; + f.reg32 = (u32int*)f.reg; + f.sz = f.reg32[Bfpr]; + if(csr32r(c, Eec)&1<<22){ + r = f.sz>>16 & 0x1fff; + r = r+1<<12; + }else + r = (f.sz&0x1fff)<<12; + + sum = 0; + for (adr = 0; adr < 0x40; adr++) { + data = fread(c, &f, r+adr*2); + if(data == -1) + break; + c->eeprom[adr] = data; + sum += data; + } + vunmap(f.reg, c->pcidev->mem[1].size); + return sum; +} + static int i82563reset(Ctlr *ctlr) { @@ -1322,7 +1421,10 @@ if(i82563detach(ctlr)) return -1; - r = eeload(ctlr); + if(ctlr->type == i82566) + r = fload(ctlr); + else + r = eeload(ctlr); if (r != 0 && r != 0xBABA){ print("%s: bad EEPROM checksum - %#.4ux\n", Type, r); return -1; @@ -1425,26 +1527,27 @@ pnp(Ether* edev, int type) { Ctlr *ctlr; + static int done; - if(i82563ctlrhead == nil) + if(done++ == 0) i82563pci(); /* * Any adapter matches if no edev->port is supplied, * otherwise the ports must match. */ - for(ctlr = i82563ctlrhead; ctlr != nil; ctlr = ctlr->next){ + for(ctlr = i82563ctlrhead; ; ctlr = ctlr->next){ + if(ctlr == nil) + return -1; if(ctlr->active) continue; - if(type != 0 && ctlr->type != type) + if(type != -1 && ctlr->type != type) continue; if(edev->port == 0 || edev->port == ctlr->port){ ctlr->active = 1; break; } } - if(ctlr == nil) - return -1; edev->ctlr = ctlr; edev->port = ctlr->port; @@ -1474,7 +1577,7 @@ static int anypnp(Ether *e) { - return pnp(e, 0); + return pnp(e, -1); } static int