allow the mpt2 driver to treat 512e drives as 4k sector drives. strategy: use sdscsifis, which supports this, rather than sdscsi. this allows us to drop sdscsi. also, correct mapping of direct-attach drives. use device page to find the correct port number. the hack to ignore direct-attach drives for controlers that can't support them needs revisiting. there appears to be no way to interrogate the hardware and see if we've got a mezz card or normal hba. (the ioc configuration pages are exactly the same for both. and incorrect on either to boot!) Reference: /n/atom/patch/applied2013/sdmpt2512e Date: Thu Nov 14 23:31:05 CET 2013 Signed-off-by: quanstro@quanstro.net # rm /sys/src/nix/port/sdscsi.c --- /sys/src/nix/k10/sdmpt2.c Thu Nov 14 23:23:34 2013 +++ /sys/src/nix/k10/sdmpt2.c Thu Nov 14 23:23:34 2013 @@ -12,6 +12,8 @@ #include "../port/error.h" #include "../port/sd.h" +#include +#include "../port/sdfis.h" #define B2W(x) ((x) / BIT32SZ) #define W2B(x) ((x) * BIT32SZ) @@ -151,6 +153,8 @@ typedef struct Unit Unit; struct Unit { + Sfisx; + int state; u16int devh; uchar link; @@ -196,20 +200,23 @@ Req *reqfree; Lock reqfreelock; Lock reqpostlock; - ushort reqcredit; - ushort iocreqfsz; - ushort reqfsz; + u16int reqcredit; + u16int iocreqfsz; + u16int reqfsz; u32int *reply; u32int *replyfree; u32int *replypost; uchar replyfsz; - ushort replyq; - ushort replyfreeq; - ushort replypostq; - ushort replypostmax; - ulong replyfreep; - ulong replypostp; + u16int replyq; + u16int replyfreeq; + u16int replypostq; + u16int replypostmax; + u32int replyfreep; + u32int replypostp; + + char allphysenc; + char direct; Queue *eventq; }; @@ -698,9 +705,65 @@ freereq(ctlr, r); } +enum { + /* page types */ + IO_UNIT_PAGE = 0x0, + IOC_PAGE = 0x1, + BIOS_PAGE = 0x2, + RAID_VOL_PAGE = 0x8, + MFG_PAGE = 0x9, + RAID_DISK_PAGE = 0xa, + EXT_PAGE = 0xf, + + /* extended page types */ + SAS_IO_UNIT = 0x10, + SAS_EXPANDER = 0x11, + SAS_DEVICE = 0x12, + SAS_PHY = 0x13, + LOG = 0x14, + ENCLOSURE = 0x15, + RAID_CONFIG = 0x16, + DRIVER_MAPPING = 0x17, + SAS_PORT = 0x18, + ETHERNET = 0x19, + EXT_MFG = 0x1a, +}; + +static int +getpage(Ctlr *ctlr, uint devh, int ptype, int exptype, int pnum, u32int *page, int npage) +{ + u32int buf[7+2]; + + memset(buf, 0, W2B(7)); + buf[0] = Config<<24; /* Function */ + buf[0] |= 0x00; /* Action (PAGE_HEADER) */ + buf[1] = exptype<<16; /* ExtPageType */ + buf[5] = ptype<<24; /* PageType (Extended) */ + buf[5] |= pnum<<16; /* PageNumber */ + mksge32(buf+7, nil, 0, 0); /* PageBufferSGE (empty) */ + + doorbell(ctlr, buf, 7+2); + ckstatus(ctlr, buf); + + buf[0] |= 0x01; /* Action (READ_CURRENT) */ + buf[6] = 0x2<<28 | devh; /* PageAddress (HANDLE) */ + mksge32(buf+7, page, npage, 0); /* PageBufferSGE */ + + doorbell(ctlr, buf, 7+2); + if(!ckstatus(ctlr, buf)) + return -1; + return 0; +} + static int devpage(Ctlr *ctlr, uint devh, u32int page[14]) { + return getpage(ctlr, devh, EXT_PAGE, SAS_DEVICE, 0, page, 4*14); +} + +static int +·devpage(Ctlr *ctlr, uint devh, u32int page[14]) +{ u32int buf[7+2]; /* @@ -710,6 +773,8 @@ * via the System Doorbell to simplify access to the page * header. */ + getpage(ctlr, devh, EXT_PAGE, SAS_DEVICE, 0, buf, sizeof buf); + memset(buf, 0, W2B(7)); buf[0] = Config<<24; /* Function */ buf[0] |= 0x00; /* Action (PAGE_HEADER) */ @@ -986,30 +1051,25 @@ * temporary hack */ static int -port2unit(Ctlr *ctlr, uint devh, uint port, uint exph, uint ench) +port2unit(Ctlr *ctlr, uint devh, uint /*exph*/, uint ench) { int unitidx, encidx; u32int slot, page[14]; - /* hack: ignore direct ports if controler has 1 port */ - if(ctlr->numports == 1) + /* hack: ignore direct ports when all phys externally mapped */ + if(ctlr->allphysenc && ctlr->direct == -1) encidx = ench - 2; else encidx = ench - 1; if(encidx < 0 || encidx >= Nenclosure) return -1; - /* direct? */ - if(exph == 0 && ench == 1) - unitidx = port; - else{ - if(devpage(ctlr, devh, page) == -1) - return -1; - slot = page[2] & 0xffff; - if(slot >= Nunitperenc) - return -1; /* too many drives per enclosure */ - unitidx = encidx*Nunitperenc + slot; - } + if(devpage(ctlr, devh, page) == -1) + return -1; + slot = page[2] & 0xffff; + if(slot >= Nunitperenc) + return -1; + unitidx = encidx*Nunitperenc + slot; if(unitidx >= Nunit) return -1; @@ -1056,10 +1116,14 @@ b = data[2]>>8 & 0xff; e = data[2] & 0xff; /* NumEntries */ - if(exph == 0 && ench == 1) - if(!anyconnected(data + 3, e)){ - print(" none connected\n"); - return; + if(exph == 0 && ench == 1){ + if(!anyconnected(data + 3, e)){ + if(ctlr->direct == 0) + ctlr->direct = -1; + return; + } + if(ctlr->direct == 0) + ctlr->direct = 1; } for(i = 0; i < e; i++){ @@ -1069,9 +1133,9 @@ reason = *p>>24 & 0xf; if(devh == 1 || devh == 0) continue; /* ignore self; empty */ - unitno = port2unit(ctlr, devh, i, exph, ench); + unitno = port2unit(ctlr, devh, exph, ench); if(unitno == -1 || unitno >= ctlr->sdev->nunit){ - print(" entry %d exph %d ench %d\n", i, exph, ench); + print(" entry %d exph %d ench %d unitno %d\n", i, exph, ench, unitno); continue; } u = UNIT(ctlr, unitno); @@ -1080,8 +1144,8 @@ unitconfig(ctlr, u, devh); u->exph = exph; u->ench = ench; - print("unit %d slot %d:%d devh %.4ux rate %x stat %x online wwn %llux\n", - i+b, ench, u->slot, devh, rate, *p>>28, u->wwn); + print("unit %d→%d slot %d:%d devh %.4ux rate %x stat %x online wwn %llux\n", + i+b, unitno, ench, u->slot, devh, rate, *p>>28, u->wwn); u->state = Online; break; case 2: /* offline */ @@ -1099,16 +1163,20 @@ } static void -encevent(Ctlr *, u32int *data) +encevent(Ctlr *ctlr, u32int *data) { char *reason; - int s, n; + int s, n, phymap; + phymap = data[4]; switch(data[0]>>16 & 0xff){ default: reason = "*gok*"; break; case 1: + /* hack: assume 8 phys */ + if(phymap == 0xff) + ctlr->allphysenc++; reason = "added"; break; case 2: @@ -1118,7 +1186,7 @@ s = data[3] >> 16; n = data[3] & 0xffff; print("mpt2: enc %d %s: port %d wwn %llux slots %d-%d phy %b\n", data[0]>>0 & 0xffff, reason, - data[0]>>24, (uvlong)data[2]<<32 | data[1], s, s+n, data[4]); + data[0]>>24, (uvlong)data[2]<<32 | data[1], s, s+n, phymap); } static void @@ -1139,7 +1207,7 @@ encevent(ctlr, data); break; default: - panic("sdmpt2: doevent: %s: bad event %#.4ux", ctlr->name, event); + print("sdmpt2: doevent: %s: bad event %#.4ux", ctlr->name, event); break; } if(reply[1]>>16 & 0xff) /* AckRequired */ @@ -1582,9 +1650,9 @@ /* hotpluggable. report all the ports (or slots) we've got */ static int -mpt2verify(SDunit *u) +mpt2verify(SDunit*) { - scsiverify(u); +// scsiverify(u); return 1; } @@ -1701,6 +1769,41 @@ sdev->name, ctlr->name, ctlr->port, ctlr->pcidev->intl); } +static int +mpt2online(SDunit *unit) +{ + int r; + Ctlr *ctlr; + Unit *u; + + ctlr = unit->dev->ctlr; + u = ctlr->unit + unit->subno; + + /* short circuit if state has not changed */ + if(u->state == Online ^ unit->sectors == 0) + return 1; + u->drivechange = 0; + r = scsionlinex(unit, u) == SDok; + if(r){ + unit->sectors = u->sectors; + unit->secsize = u->secsize; + } + return r; +} + +static long +mpt2bio(SDunit *unit, int lun, int write, void *data, long count, uvlong lba) +{ + Ctlr *ctlr; + Unit *u; + + ctlr = unit->dev->ctlr; + u = ctlr->unit + unit->subno; +// if(u->feat & Datapi || u->type == Sas) + return scsibiox(unit, u, lun, write, data, count, lba); +// return atabio(unit, u, lun, write, data, count, lba); +} + SDifc sdmpt2ifc = { "mpt2", /* name */ @@ -1710,12 +1813,12 @@ mpt2disable, /* disable */ mpt2verify, /* verify */ - scsionline, /* online */ + mpt2online, /* online */ mpt2rio, /* rio */ mpt2rctl, /* rctl */ nil, /* wctl */ - scsibio, /* bio */ + mpt2bio, /* bio */ nil, /* probe */ nil, /* clear */ mpt2rtopctl, /* rtopctl */ --- /sys/src/nix/k10/cpu Thu Nov 14 23:23:34 2013 +++ /sys/src/nix/k10/cpu Thu Nov 14 23:23:34 2013 @@ -44,14 +44,19 @@ link +dev resmem + ether8169 pci ethermii # ether82557 pci ether82563 pci etherbcm pci ethermii etherigbe pci ethermii + ether82598 pci # ether57711 pci etherm10g pci + + etheri40 pci + ethermedium # loopbackmedium # netdevmedium @@ -65,6 +70,7 @@ sdide sdscsifis sdatafis sdodin sdscsifis sdatafis sdvanir sdscsifis sdatafis + sdmpt2 sdscsifis sdatafis sdloop misc +dev