LSI Fusion-MPT SAS 2.0 SCSI Host Adapter Reference: /n/atom/patch/applied2013/sdmpt2 Date: Fri Aug 16 23:19:10 CES 2013 Signed-off-by: sstallion@gmail.com --- /sys/src/9/pc/sdmpt2.c Fri Aug 16 23:18:46 2013 +++ /sys/src/9/pc/sdmpt2.c Fri Aug 16 23:18:46 2013 @@ -1,5 +1,5 @@ /* - * LSI Fusion-MPT SAS 2.0 SCSI Host Adapter. + * LSI Fusion-MPT SAS 2.0 SCSI Host Adapter */ #include "u.h" #include "../port/lib.h" @@ -7,14 +7,10 @@ #include "dat.h" #include "fns.h" #include "io.h" -#include "ureg.h" #include "../port/error.h" #include "../port/sd.h" -#define B2W(x) ((x) / BIT32SZ) -#define W2B(x) ((x) * BIT32SZ) - extern SDifc sdmpt2ifc; static char Ebadunit[] = "invalid unit"; @@ -137,34 +133,19 @@ HbdPhyEvent = 0x0024, }; -enum { - Nunit = 16, - - Offline = 0, - Online, -}; - +typedef struct Ctlr Ctlr; +typedef struct Req Req; typedef struct Unit Unit; + struct Unit { - int state; - ushort devh; + uchar status; uchar link; + ushort devh; ulong info; ushort flags; uchar wwn[8]; }; -typedef struct Req Req; -struct Req { - Rendez; - ushort smid; - ulong *req; - SDreq *sdreq; - int done; - Req *next; -}; - -typedef struct Ctlr Ctlr; struct Ctlr { Lock; int ioc; @@ -178,7 +159,7 @@ Lock doorlock; RWlock tasklock; - Unit unit[Nunit]; + Unit unit[16]; uchar numports; ushort maxtargs; @@ -205,16 +186,25 @@ Queue *eventq; }; +struct Req { + Rendez; + ushort smid; + ulong *req; + SDreq *sdreq; + int done; + Req *next; +}; + static ulong iocread(Ctlr *ctlr, int reg) { - return inl(ctlr->port + reg); + return inl(ctlr->port+reg); } static void iocwrite(Ctlr *ctlr, int reg, ulong val) { - outl(ctlr->port + reg, val); + outl(ctlr->port+reg, val); } static ulong @@ -232,7 +222,7 @@ if(!(val & mask)) return val; if(TK2MS(MACHP(0)->ticks - t) > 10*1000) /* PG §3.7.1 */ - panic("iocwait: %s: wedge reg 0x%02ux val 0x%08ulx", + panic("iocwait: %s: wedge reg %#.2ux val %#.8ulx", ctlr->name, reg, val); microdelay(500); } @@ -245,7 +235,7 @@ val = iocread(ctlr, Doorbell); if(val & StateMask != state) - panic("ckstate: %s: bad state 0x%08ulx", ctlr->name, val); + panic("ckstate: %s: bad state %#.8ulx", ctlr->name, val); } static int @@ -254,19 +244,19 @@ ushort status; /* - * IOC Status is provided in every reply, which may - * be used to determine the success of a given function - * independent of message content. In the event an - * unexpected status is returned, a panic is issued. + * IOC Status is provided in every reply, which may be used + * to determine the success of a given function independent of + * message content. In the event an unexpected status is + * returned, a panic is issued. */ status = reply[3]>>16 & 0x7fff; /* IOCStatus */ if(status == 0x0000) /* SUCCESS */ return 1; /* - * Some functions support nominal failure modes; rather - * than panic, we allow the caller to determine the - * severity of the condition. + * Some functions support nominal failure modes; rather than + * panic, we allow the caller to determine the severity of the + * condition. */ switch(reply[0]>>24){ /* Function */ case ScsiIoRequest: @@ -299,7 +289,7 @@ } break; } - panic("ckstatus: %s: bad status 0x%04ux", ctlr->name, status); + panic("ckstatus: %s: bad status %#.4ux", ctlr->name, status); return -1; /* not reached */ } @@ -329,17 +319,17 @@ /* * We do something sneaky here; replies are written back - * into the request buffer during handshake. Buffers must - * be sized to accomodate the larger of the two messages. + * into the request buffer during handshake. Buffers must be + * sized to accomodate the larger of the two messages. * * Doorbell reads yield 16 bits at a time; upper bits are - * considered reserved. The reply MsgLength is located - * in the first 32-bit word; a reply will always contain - * at least DefaultReplyLength words. + * considered reserved. The reply MsgLength is located in the + * first 32-bit word; a reply will always contain at least + * DefaultReplyLength words. */ reply = (ushort *)req; nwords = DefaultReplyLength; - for(i = 0; i < nwords * BIT16SZ; ++i){ + for(i = 0; i < nwords*2; ++i){ iocwait(ctlr, HostInterruptStatus, Ioc2SysDbStatus, 1); reply[i] = iocread(ctlr, Doorbell); iocwrite(ctlr, HostInterruptStatus, 0); @@ -397,6 +387,24 @@ } static char * +unitstatus(Unit *u) +{ + switch(u->status & 0xf){ /* Reason Code */ + case 0x1: + case 0x5: + return "online"; + case 0x2: + return "missing"; + case 0x3: + return "linkchange"; + case 0x4: + return "nolinkchange"; + default: + return "unknown"; + } +} + +static char * unitlink(Unit *u) { switch(u->link>>4){ /* Current Link Rate */ @@ -413,14 +421,15 @@ } } -static char * -unitstate(Unit *u) +static int +unitonline(Unit *u) { - switch(u->state){ - case Online: - return "online"; + switch(u->status & 0xf){ /* Reason Code */ + case 0x1: + case 0x5: + return 1; default: - return "offline"; + return 0; } } @@ -439,9 +448,9 @@ * contiguously, aligned on a 16-byte boundary, and be a * multiple of 16 bytes in length. */ - n = W2B(ctlr->iocreqfsz) + ROUNDUP(sizeof(Req), 16); - ctlr->reqfsz = B2W(n); - ctlr->req = mallocalign(ctlr->reqcredit * n, 16, 0, 0); + n = (ctlr->iocreqfsz + ROUNDUP(sizeof(Req), 16))*BY2WD; + ctlr->reqfsz = n/BY2WD; + ctlr->req = mallocalign(ctlr->reqcredit*n, 16, 0, 0); if(ctlr->req == nil) print("reallocreq: %s: out of memory\n", ctlr->name); return ctlr->req; @@ -491,6 +500,7 @@ ; tsleep(r, reqdone, r, ms); poperror(); + if(!r->done) error(Etimeout); } @@ -547,7 +557,7 @@ { ulong buf[16]; - memset(buf, 0, W2B(3)); + memset(buf, 0, 3*BY2WD); buf[0] = IocFacts<<24; /* Function */ doorbell(ctlr, buf, 3); @@ -566,7 +576,7 @@ { ulong buf[18]; - memset(buf, 0, W2B(18)); + memset(buf, 0, 18*BY2WD); buf[0] = IocInit<<24; /* Function */ buf[6] = ctlr->reqfsz<<16; /* SystemRequestFrameSize */ buf[7] = ctlr->replyfreeq<<16; /* ReplyFreeQueueDepth */ @@ -587,15 +597,15 @@ { ulong buf[11]; - memset(buf, 0, W2B(11)); + memset(buf, 0, 11*BY2WD); buf[0] = EventNotification<<24; /* Function */ /* * Event notifications are masked using the bit identified * by the value of the event; see MPI §8.4. PG §3.7.4 - * suggests a number of SAS events required for proper - * host mapping, however the SAS_TOPOLOGY_CHANGE_LIST - * event is merely sufficient. + * suggests a number of SAS events required for proper host + * mapping, however the SAS_TOPOLOGY_CHANGE_LIST event is + * merely sufficient. */ buf[5] = ~EVENT(SasTopologyChangeList); buf[6] = ~0; @@ -616,7 +626,7 @@ r = nextreq(ctlr); if(r == nil) error(Enoreqs); - memset(r->req, 0, W2B(5)); + memset(r->req, 0, 5*BY2WD); r->req[0] = EventAck<<24; /* Function */ r->req[3] = event; /* Event */ r->req[4] = context; /* EventContext */ @@ -636,13 +646,13 @@ /* * The Port Enable message is posted using the Request * Descriptor Post Queue for reliable delivery of events. - * Use of the System Doorbell will miss events when used - * on a uniprocessor. + * Use of the System Doorbell will miss events on a + * uniprocessor. */ r = nextreq(ctlr); if(r == nil) error(Enoreqs); - memset(r->req, 0, W2B(3)); + memset(r->req, 0, 3*BY2WD); r->req[0] = PortEnable<<24; /* Function */ desc[0] = r->smid<<16 | 0x4<<1; /* Default Request */ @@ -657,13 +667,12 @@ ulong buf[7+2], page[14]; /* - * Unit configuration is pulled from SAS Device Page 0. - * The DeviceInfo and Flags fields provide device - * interconnect and capabilities. We obtain configuration - * via the System Doorbell to simplify access to the page - * header. + * Unit configuration is pulled from SAS Device Page 0. The + * DeviceInfo and Flags fields provide device interconnect and + * capabilities. We obtain configuration via the System + * Doorbell to simplify access to the page header. */ - memset(buf, 0, W2B(7)); + memset(buf, 0, 7*BY2WD); buf[0] = Config<<24; /* Function */ buf[0] |= 0x00; /* Action (PAGE_HEADER) */ buf[1] = 0x12<<16; /* ExtPageType (SAS_DEVICE) */ @@ -672,7 +681,8 @@ mksge(buf+7, nil, 0, 0); /* PageBufferSGE (empty) */ doorbell(ctlr, buf, 7+2); - ckstatus(ctlr, buf); + if(!ckstatus(ctlr, buf)) + error(Ebadunit); buf[0] |= 0x01; /* Action (READ_CURRENT) */ buf[6] = 0x2<<28 | u->devh; /* PageAddress (HANDLE) */ @@ -696,7 +706,7 @@ r = nextreq(ctlr); if(r == nil) error(Enoreqs); - memset(r->req, 0, W2B(11)); + memset(r->req, 0, 11*BY2WD); r->req[0] = SasIoUnitControl<<24; /* Function */ r->req[0] |= 0x0d; /* Operation (REMOVE_DEVICE) */ r->req[1] = u->devh; /* DevHandle */ @@ -716,7 +726,7 @@ r = nextreq(ctlr); if(r == nil) error(Enoreqs); - memset(r->req, 0, W2B(13)); + memset(r->req, 0, 13*BY2WD); r->req[0] = ScsiTaskManagement<<24; /* Function */ r->req[0] |= u->devh; /* DevHandle */ r->req[1] = 0x03<<8; /* TaskType (Target Reset) */ @@ -736,7 +746,7 @@ r = nextreq(ctlr); if(r == nil) error(Enoreqs); - memset(r->req, 0, W2B(13)); + memset(r->req, 0, 13*BY2WD); r->req[0] = ScsiTaskManagement<<24; /* Function */ r->req[0] |= u->devh; /* DevHandle */ r->req[1] = 0x01<<8; /* TaskType (Abort Task) */ @@ -760,7 +770,7 @@ return; } r->sdreq = sdreq; - memset(r->req, 0, W2B(24)); + memset(r->req, 0, 24*BY2WD); r->req[0] = ScsiIoRequest<<24; /* Function */ r->req[0] |= u->devh; /* DevHandle */ r->req[3] = PCIWADDR(sdreq->sense); /* SenseBufferLowAddress */ @@ -797,7 +807,7 @@ freereq(ctlr, r); } -#define REPLY(ctlr, n) ((ctlr)->reply + (n)*1) +#define REPLY(ctlr, n) ((ctlr)->reply + (n)*(ctlr)->replyfsz) #define REPLYPOST(ctlr, n) ((ctlr)->replypost + (n)*2) static ulong * @@ -806,13 +816,12 @@ free(ctlr->reply); /* - * System Reply Message Frames are less disciplined; they - * do not have to be contiguous, must be aligned on a - * 4-byte boundary, and must be a multiple of 4 bytes in - * length. + * System Reply Message Frames are less disciplined; they do + * not have to be contiguous, must be aligned on a 4-byte + * boundary, and must be a multiple of 4 bytes in length. */ ctlr->replyq = ctlr->reqcredit + 32; /* PG §3.1.3 */ - ctlr->reply = mallocz(ctlr->replyq * W2B(ctlr->replyfsz), 0); + ctlr->reply = mallocz(ctlr->replyq * ctlr->replyfsz*BY2WD, 0); if(ctlr->reply == nil) print("reallocreply: %s: out of memory\n", ctlr->name); return ctlr->reply; @@ -825,11 +834,11 @@ /* * The Reply Free Queue must be allocated contiguously, - * aligned on a 16-byte boundary, and must have a depth - * that is a multiple of 16 bytes. + * aligned on a 16-byte boundary, and must have a depth that + * is a multiple of 16 bytes. */ ctlr->replyfreeq = ROUNDUP(ctlr->replyq + 1, 16); - ctlr->replyfree = mallocalign(ctlr->replyfreeq * W2B(1), 16, 0, 0); + ctlr->replyfree = mallocalign(ctlr->replyfreeq * BY2WD, 16, 0, 0); if(ctlr->replyfree == nil) print("reallocreplyfree: %s: out of memory\n", ctlr->name); return ctlr->replyfree; @@ -842,13 +851,13 @@ /* * The Reply Descriptor Post Queue must be allocated - * contiguously and aligned on a 16-byte boundary. The - * depth must not exceed MaxReplyDescriptorPostQueueDepth - * returned in the IOC Facts reply. + * contiguously and aligned on a 16-byte boundary. The depth + * must not exceed MaxReplyDescriptorPostQueueDepth returned + * in the IOC Facts reply. */ ctlr->replypostq = MIN(ctlr->replypostmax, ROUNDUP(ctlr->replyq + ctlr->reqcredit + 1, 16)); - ctlr->replypost = mallocalign(ctlr->replypostq * W2B(2), 16, 0, 0); + ctlr->replypost = mallocalign(ctlr->replypostq * 2*BY2WD, 16, 0, 0); if(ctlr->replypost == nil) print("reallocreplypost: %s: out of memory\n", ctlr->name); return ctlr->replypost; @@ -933,8 +942,8 @@ /* * Unfortunately, devsd limits us to 16 devices, which * essentially precludes support for SAS expanders and/or - * enclosures. A one-to-one mapping exists between a - * direct attached PHY and a device for simplicity. + * enclosures. A one-to-one mapping exists between a direct + * attached PHY and a device for simplicity. */ if(data[0]>>16 != 0x0) /* ExpanderDevHandle */ return; @@ -942,29 +951,28 @@ return; /* - * SAS topology changes are handled in two phases; we - * first obtain identifying information from event data. - * New units require additional configuration information - * and missing units must have resources released. + * SAS topology changes are handled in two phases; we first + * obtain identifying information from event data. New units + * require additional configuration information and missing + * units must have resources released. */ p = data + 3; e = p + (data[2] & 0xff); /* NumEntries */ i = data[2]>>8 & 0xff; /* StartPhyNum */ - for(; p < e && i < Nunit; ++p, ++i){ + for(; p < e && i < nelem(ctlr->unit); ++p, ++i){ u = UNIT(ctlr, i); - switch(*p>>24 & 0xf){ /* PhyStatus (Reason Code) */ + u->status = *p>>24 & 0xff; /* PhyStatus */ + u->link = *p>>16 & 0xff; /* LinkRate */ + switch(u->status & 0xf){ /* Reason Code */ case 0x1: u->devh = *p & 0xffff; /* AttachedDevHandle */ unitconfig(ctlr, u); - u->state = Online; break; case 0x2: - u->state = Offline; unitreset(ctlr, u); unitremove(ctlr, u); break; } - u->link = *p>>16 & 0xff; /* LinkRate */ } } @@ -983,7 +991,7 @@ topoevent(ctlr, data); break; default: - panic("doevent: %s: bad event 0x%04ux", ctlr->name, event); + panic("doevent: %s: bad event %#.4ux", ctlr->name, event); } if(reply[1]>>16 & 0xff) /* AckRequired */ eventack(ctlr, event, context); @@ -995,7 +1003,7 @@ int n; Block *bp; - n = W2B(reply[0]>>16 & 0xff); /* MsgLength */ + n = (reply[0]>>16 & 0xff)*BY2WD; /* MsgLength */ bp = iallocb(n); if(bp == nil) panic("qevent: %s: out of memory", ctlr->name); @@ -1026,18 +1034,18 @@ case EventNotification: /* * We queue events for handling in a separate - * process to ensure sanity when the IOC - * requires synchronization via acknowledgement. + * process to ensure sanity when the IOC requires + * synchronization via acknowledgement. */ qevent(ctlr, reply); break; default: - panic("addressreply: %s: bad function 0x%02ux", ctlr->name, fn); + panic("addressreply: %s: bad function %#.2ux", ctlr->name, fn); } /* - * To simplify handing a System Reply Message Frame back - * to the IOC, we update the ReplyFreeHostIndex register + * To simplify handing a System Reply Message Frame back to + * the IOC, we update the ReplyFreeHostIndex register * immediately. Unfortunately, this requires additional * coherence. */ @@ -1100,9 +1108,9 @@ /* * Each time the controller is reset, an IOC Facts reponse - * may return different values. We err on the side of - * caution and reallocate resources prior to issuing an - * IOC Init request. + * may return different values. We err on the side of caution + * and reallocate resources prior to issuing an IOC Init + * request. */ iocfacts(ctlr); if(reallocreq(ctlr)) @@ -1117,25 +1125,23 @@ /* * Initialize System Request Message Frames and associated * structures. A SMID is written once to avoid headaches - * constructing messages in the I/O path. A SMID of 0 must - * be initialized and is considered reserved; it may not be + * constructing messages in the I/O path. A SMID of 0 must be + * initialized and is considered reserved; it may not be * placed on the free list or used by the host in any way. */ ctlr->reqfree = nil; - for(i = 0; i < ctlr->reqcredit; ++i) - if(i > 0){ - r = REQ(ctlr, i); - r->smid = i; - r->req = (ulong *)r - ctlr->iocreqfsz; - freereq(ctlr, r); - } + for(i = 1; i < ctlr->reqcredit; ++i){ + r = REQ(ctlr, i); + r->smid = i; + r->req = (ulong *)r - ctlr->iocreqfsz; + freereq(ctlr, r); + } /* * The Reply Descriptor Post Queue must be initialized with * the unused descriptor type for each entry. This is - * slightly reordered to take advantage of coherence - * required when updating the ReplyFreeHostIndex register - * below. + * slightly reordered to take advantage of coherence required + * when updating the ReplyFreeHostIndex register below. */ ctlr->replypostp = 0; for(i = 0; i < ctlr->replypostq; ++i){ @@ -1144,10 +1150,10 @@ } /* - * The Reply Free Queue is initialized with the lower - * 32 bits of the PADDR for each System Reply Frame. The - * ReplyFreeHostIndex register is initialized with the - * next (unused) entry. + * The Reply Free Queue is initialized with the lower 32 + * bits of the PADDR for each System Reply Frame. The + * ReplyFreeHostIndex register is initialized with the next + * (unused) entry. */ ctlr->replyfreep = 0; for(i = 0; i < ctlr->replyq; ++i){ @@ -1220,22 +1226,22 @@ } ioc = iocs++; snprint(name, sizeof name, "ioc%d", ioc); - ctlr = malloc(sizeof(Ctlr)); + ctlr = malloc(sizeof *ctlr); if(ctlr == nil){ print("mpt2pnp: %s: out of memory\n", name); continue; } ctlr->ioc = ioc; - strncpy(ctlr->name, name, sizeof(ctlr->name)); - ctlr->port = ioalloc(p->mem[0].bar & ~1, p->mem[0].size, 0, "mpt2"); - if(ctlr->port < 0){ - print("mpt2pnp: %s: ioalloc failed\n", name); + strncpy(ctlr->name, name, sizeof ctlr->name); + ctlr->port = p->mem[0].bar & ~1; + if(ioalloc(ctlr->port, p->mem[0].size, 0, "mpt2") < 0){ + print("mpt2pnp: %s: port %ux in use\n", name, ctlr->port); freectlr(ctlr); continue; } pcisetbme(p); ctlr->pcidev = p; - ctlr->eventq = qopen(0, Qmsg | Qclosed, nil, nil); + ctlr->eventq = qopen(0, Qmsg|Qclosed, nil, nil); if(ctlr->eventq == nil){ print("mpt2pnp: %s: qopen failed\n", name); freectlr(ctlr); @@ -1247,7 +1253,7 @@ freectlr(ctlr); continue; } - sdev = malloc(sizeof(SDev)); + sdev = malloc(sizeof *sdev); if(sdev == nil){ print("mpt2pnp: %s: out of memory\n", name); freectlr(ctlr); @@ -1256,7 +1262,7 @@ sdev->ifc = &sdmpt2ifc; sdev->ctlr = ctlr; sdev->idno = 'M' + ioc; - sdev->nunit = Nunit; + sdev->nunit = nelem(ctlr->unit); ctlr->sdev = sdev; print("#S/sd%c: %s: mpt2 sas-2 with %d ports, %d max targets\n", sdev->idno, name, ctlr->numports, ctlr->maxtargs); @@ -1283,10 +1289,7 @@ iunlock(ctlr); return; } - for(;;){ - desc = nextreplypost(ctlr); - if(desc == nil) - break; + while(desc = nextreplypost(ctlr)){ switch(desc[0] & 0xf){ /* ReplyFlags */ case ScsiIoSuccess: smid = desc[0]>>16; /* SMID */ @@ -1298,7 +1301,7 @@ addressreply(ctlr, smid, reply); break; default: - panic("mpt2interrupt: %s: bad reply 0x%08ulx 0x%08ulx", + panic("mpt2interrupt: %s: bad reply %#.8ulx %#.8ulx", ctlr->name, desc[0], desc[1]); } freereplypost(ctlr, desc); @@ -1353,9 +1356,9 @@ /* * For the unwary, a pending reset will first close the - * eventq, which will cause qbread to eventually error. - * The control structure below yields to the reset kproc - * until the eventq is reopened and sanity is restored. + * eventq, which will cause qbread to eventually error. The + * control structure below yields to the reset kproc until the + * eventq is reopened and sanity is restored. */ ctlr = arg; while(waserror()) @@ -1366,8 +1369,7 @@ runlock(&ctlr->resetlock); nexterror(); } - bp = qbread(ctlr->eventq, 0); - if(bp) + if(bp = qbread(ctlr->eventq, 0)) if(waserror()) wakeup(&ctlr->reset); else{ @@ -1401,13 +1403,14 @@ kproc("mpt2reset", mpt2reset, ctlr); kproc("mpt2event", mpt2event, ctlr); } + if(waserror()) print("mpt2enable: %s: %s\n", ctlr->name, up->errstr); else{ portenable(ctlr); poperror(); } - return 1; + return 0; } static int @@ -1425,7 +1428,7 @@ snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name); intrdisable(p->intl, mpt2interrupt, ctlr, p->tbdf, name); - return 1; + return 0; } static int @@ -1441,7 +1444,7 @@ runlock(&ctlr->resetlock); return SDeio; } - if(u->state != Online) + if(!unitonline(u)) error(Ebadunit); if(waserror()){ wakeup(&ctlr->reset); @@ -1470,10 +1473,10 @@ u = UNIT(ctlr, unit->subno); getunitcaps(u, buf, sizeof buf); p = seprint(p, e, "capabilities %s\n", buf); - p = seprint(p, e, "wwn %ullx\n", GBIT64(u->wwn)); + p = seprint(p, e, "wwn %ullx\n", getle(u->wwn, 8)); p = seprint(p, e, "type %s\n", unittype(u)); + p = seprint(p, e, "status %s\n", unitstatus(u)); p = seprint(p, e, "link %s\n", unitlink(u)); - p = seprint(p, e, "state %s\n", unitstate(u)); p = seprint(p, e, "geometry %ulld %uld\n", unit->sectors, unit->secsize); return p - o; --- /sys/src/9/pc/pc Fri Aug 16 23:18:46 2013 +++ /sys/src/9/pc/pc Fri Aug 16 23:18:46 2013 @@ -99,6 +99,7 @@ # sd53c8xx pci sdscsi # sdmylex pci sdscsi # sdodin pci sdscsi led +# sdmpt2 pci sdscsi uarti8250 uartp8250 uartpci pci uartp8250 --- /sys/src/9/pc/pccd Fri Aug 16 23:18:46 2013 +++ /sys/src/9/pc/pccd Fri Aug 16 23:18:46 2013 @@ -94,6 +94,7 @@ sd53c8xx pci sdscsi sdmylex pci sdscsi # sdodin pci sdscsi led +# sdmpt2 pci sdscsi uarti8250 uartp8250 uartpci pci uartp8250 --- /sys/src/9/pc/pccpu Fri Aug 16 23:18:46 2013 +++ /sys/src/9/pc/pccpu Fri Aug 16 23:18:46 2013 @@ -84,11 +84,11 @@ sdide pci sdscsi sdiahci pci sdscsi led sdmv50xx pci sdscsi - sdmpt2 pci sdscsi sdloop # sd53c8xx pci sdscsi # sdmylex pci sdscsi sdodin pci sdscsi led + sdmpt2 pci sdscsi ip il --- /sys/src/9/pc/pccpud Fri Aug 16 23:18:46 2013 +++ /sys/src/9/pc/pccpud Fri Aug 16 23:18:46 2013 @@ -70,6 +70,7 @@ sd53c8xx pci sdscsi sdmylex pci sdscsi sdodin pci sdscsi led + sdmpt2 pci sdscsi # uartaxp pci uarti8250 uartp8250 --- /sys/src/9/pc/pccpuf Fri Aug 16 23:18:46 2013 +++ /sys/src/9/pc/pccpuf Fri Aug 16 23:18:46 2013 @@ -90,6 +90,7 @@ sd53c8xx pci sdscsi sdmylex pci sdscsi sdodin pci sdscsi led + sdmpt2 pci sdscsi # uartaxp pci uarti8250 uartp8250 --- /sys/src/9/pc/pcdisk Fri Aug 16 23:18:46 2013 +++ /sys/src/9/pc/pcdisk Fri Aug 16 23:18:46 2013 @@ -96,6 +96,7 @@ sd53c8xx pci sdscsi sdmylex pci sdscsi sdodin pci sdscsi led + sdmpt2 pci sdscsi uarti8250 uartp8250 uartpci pci uartp8250 --- /sys/src/9/pc/pcdist Fri Aug 16 23:18:46 2013 +++ /sys/src/9/pc/pcdist Fri Aug 16 23:18:46 2013 @@ -88,6 +88,7 @@ sdiahci pci sdscsi led # sdmv50xx pci sdscsi # sdodin pci sdscsi led +# sdmpt2 pci sdscsi uarti8250 uartp8250 # uartpci pci uartp8250 --- /sys/src/9/pc/pcf Fri Aug 16 23:18:46 2013 +++ /sys/src/9/pc/pcf Fri Aug 16 23:18:46 2013 @@ -97,6 +97,7 @@ # sd53c8xx pci sdscsi # sdmylex pci sdscsi sdodin pci sdscsi led + sdmpt2 pci sdscsi uarti8250 uartp8250 uartpci pci uartp8250 --- /sys/src/9/pc/pcflop Fri Aug 16 23:18:46 2013 +++ /sys/src/9/pc/pcflop Fri Aug 16 23:18:46 2013 @@ -90,6 +90,7 @@ sdiahci pci sdscsi led # sdmv50xx pci sdscsi # sdodin pci sdscsi led +# sdmpt2 pci sdscsi uarti8250 uartp8250 # uartpci pci uartp8250 --- /sys/src/9/pcpae/sdmpt2.c Fri Aug 16 23:18:46 2013 +++ /sys/src/9/pcpae/sdmpt2.c Fri Aug 16 23:18:46 2013 @@ -1,5 +1,5 @@ /* - * LSI Fusion-MPT SAS 2.0 SCSI Host Adapter. + * LSI Fusion-MPT SAS 2.0 SCSI Host Adapter */ #include "u.h" #include "../port/lib.h" @@ -7,14 +7,10 @@ #include "dat.h" #include "fns.h" #include "io.h" -#include "ureg.h" #include "../port/error.h" #include "../port/sd.h" -#define B2W(x) ((x) / BIT32SZ) -#define W2B(x) ((x) * BIT32SZ) - extern SDifc sdmpt2ifc; static char Ebadunit[] = "invalid unit"; @@ -137,34 +133,19 @@ HbdPhyEvent = 0x0024, }; -enum { - Nunit = 16, - - Offline = 0, - Online, -}; - +typedef struct Ctlr Ctlr; +typedef struct Req Req; typedef struct Unit Unit; + struct Unit { - int state; - ushort devh; + uchar status; uchar link; + ushort devh; ulong info; ushort flags; uchar wwn[8]; }; -typedef struct Req Req; -struct Req { - Rendez; - ushort smid; - ulong *req; - SDreq *sdreq; - int done; - Req *next; -}; - -typedef struct Ctlr Ctlr; struct Ctlr { Lock; int ioc; @@ -178,7 +159,7 @@ Lock doorlock; RWlock tasklock; - Unit unit[Nunit]; + Unit unit[16]; uchar numports; ushort maxtargs; @@ -205,16 +186,25 @@ Queue *eventq; }; +struct Req { + Rendez; + ushort smid; + ulong *req; + SDreq *sdreq; + int done; + Req *next; +}; + static ulong iocread(Ctlr *ctlr, int reg) { - return inl(ctlr->port + reg); + return inl(ctlr->port+reg); } static void iocwrite(Ctlr *ctlr, int reg, ulong val) { - outl(ctlr->port + reg, val); + outl(ctlr->port+reg, val); } static ulong @@ -232,7 +222,7 @@ if(!(val & mask)) return val; if(TK2MS(MACHP(0)->ticks - t) > 10*1000) /* PG §3.7.1 */ - panic("iocwait: %s: wedge reg 0x%02ux val 0x%08ulx", + panic("iocwait: %s: wedge reg %#.2ux val %#.8ulx", ctlr->name, reg, val); microdelay(500); } @@ -245,7 +235,7 @@ val = iocread(ctlr, Doorbell); if(val & StateMask != state) - panic("ckstate: %s: bad state 0x%08ulx", ctlr->name, val); + panic("ckstate: %s: bad state %#.8ulx", ctlr->name, val); } static int @@ -254,19 +244,19 @@ ushort status; /* - * IOC Status is provided in every reply, which may - * be used to determine the success of a given function - * independent of message content. In the event an - * unexpected status is returned, a panic is issued. + * IOC Status is provided in every reply, which may be used + * to determine the success of a given function independent of + * message content. In the event an unexpected status is + * returned, a panic is issued. */ status = reply[3]>>16 & 0x7fff; /* IOCStatus */ if(status == 0x0000) /* SUCCESS */ return 1; /* - * Some functions support nominal failure modes; rather - * than panic, we allow the caller to determine the - * severity of the condition. + * Some functions support nominal failure modes; rather than + * panic, we allow the caller to determine the severity of the + * condition. */ switch(reply[0]>>24){ /* Function */ case ScsiIoRequest: @@ -299,7 +289,7 @@ } break; } - panic("ckstatus: %s: bad status 0x%04ux", ctlr->name, status); + panic("ckstatus: %s: bad status %#.4ux", ctlr->name, status); return -1; /* not reached */ } @@ -329,17 +319,17 @@ /* * We do something sneaky here; replies are written back - * into the request buffer during handshake. Buffers must - * be sized to accomodate the larger of the two messages. + * into the request buffer during handshake. Buffers must be + * sized to accomodate the larger of the two messages. * * Doorbell reads yield 16 bits at a time; upper bits are - * considered reserved. The reply MsgLength is located - * in the first 32-bit word; a reply will always contain - * at least DefaultReplyLength words. + * considered reserved. The reply MsgLength is located in the + * first 32-bit word; a reply will always contain at least + * DefaultReplyLength words. */ reply = (ushort *)req; nwords = DefaultReplyLength; - for(i = 0; i < nwords * BIT16SZ; ++i){ + for(i = 0; i < nwords*2; ++i){ iocwait(ctlr, HostInterruptStatus, Ioc2SysDbStatus, 1); reply[i] = iocread(ctlr, Doorbell); iocwrite(ctlr, HostInterruptStatus, 0); @@ -397,6 +387,24 @@ } static char * +unitstatus(Unit *u) +{ + switch(u->status & 0xf){ /* Reason Code */ + case 0x1: + case 0x5: + return "online"; + case 0x2: + return "missing"; + case 0x3: + return "linkchange"; + case 0x4: + return "nolinkchange"; + default: + return "unknown"; + } +} + +static char * unitlink(Unit *u) { switch(u->link>>4){ /* Current Link Rate */ @@ -413,14 +421,15 @@ } } -static char * -unitstate(Unit *u) +static int +unitonline(Unit *u) { - switch(u->state){ - case Online: - return "online"; + switch(u->status & 0xf){ /* Reason Code */ + case 0x1: + case 0x5: + return 1; default: - return "offline"; + return 0; } } @@ -439,9 +448,9 @@ * contiguously, aligned on a 16-byte boundary, and be a * multiple of 16 bytes in length. */ - n = W2B(ctlr->iocreqfsz) + ROUNDUP(sizeof(Req), 16); - ctlr->reqfsz = B2W(n); - ctlr->req = mallocalign(ctlr->reqcredit * n, 16, 0, 0); + n = (ctlr->iocreqfsz + ROUNDUP(sizeof(Req), 16))*BY2WD; + ctlr->reqfsz = n/BY2WD; + ctlr->req = mallocalign(ctlr->reqcredit*n, 16, 0, 0); if(ctlr->req == nil) print("reallocreq: %s: out of memory\n", ctlr->name); return ctlr->req; @@ -491,6 +500,7 @@ ; tsleep(r, reqdone, r, ms); poperror(); + if(!r->done) error(Etimeout); } @@ -547,7 +557,7 @@ { ulong buf[16]; - memset(buf, 0, W2B(3)); + memset(buf, 0, 3*BY2WD); buf[0] = IocFacts<<24; /* Function */ doorbell(ctlr, buf, 3); @@ -566,7 +576,7 @@ { ulong buf[18]; - memset(buf, 0, W2B(18)); + memset(buf, 0, 18*BY2WD); buf[0] = IocInit<<24; /* Function */ buf[6] = ctlr->reqfsz<<16; /* SystemRequestFrameSize */ buf[7] = ctlr->replyfreeq<<16; /* ReplyFreeQueueDepth */ @@ -587,15 +597,15 @@ { ulong buf[11]; - memset(buf, 0, W2B(11)); + memset(buf, 0, 11*BY2WD); buf[0] = EventNotification<<24; /* Function */ /* * Event notifications are masked using the bit identified * by the value of the event; see MPI §8.4. PG §3.7.4 - * suggests a number of SAS events required for proper - * host mapping, however the SAS_TOPOLOGY_CHANGE_LIST - * event is merely sufficient. + * suggests a number of SAS events required for proper host + * mapping, however the SAS_TOPOLOGY_CHANGE_LIST event is + * merely sufficient. */ buf[5] = ~EVENT(SasTopologyChangeList); buf[6] = ~0; @@ -616,7 +626,7 @@ r = nextreq(ctlr); if(r == nil) error(Enoreqs); - memset(r->req, 0, W2B(5)); + memset(r->req, 0, 5*BY2WD); r->req[0] = EventAck<<24; /* Function */ r->req[3] = event; /* Event */ r->req[4] = context; /* EventContext */ @@ -636,13 +646,13 @@ /* * The Port Enable message is posted using the Request * Descriptor Post Queue for reliable delivery of events. - * Use of the System Doorbell will miss events when used - * on a uniprocessor. + * Use of the System Doorbell will miss events on a + * uniprocessor. */ r = nextreq(ctlr); if(r == nil) error(Enoreqs); - memset(r->req, 0, W2B(3)); + memset(r->req, 0, 3*BY2WD); r->req[0] = PortEnable<<24; /* Function */ desc[0] = r->smid<<16 | 0x4<<1; /* Default Request */ @@ -657,13 +667,12 @@ ulong buf[7+2], page[14]; /* - * Unit configuration is pulled from SAS Device Page 0. - * The DeviceInfo and Flags fields provide device - * interconnect and capabilities. We obtain configuration - * via the System Doorbell to simplify access to the page - * header. + * Unit configuration is pulled from SAS Device Page 0. The + * DeviceInfo and Flags fields provide device interconnect and + * capabilities. We obtain configuration via the System + * Doorbell to simplify access to the page header. */ - memset(buf, 0, W2B(7)); + memset(buf, 0, 7*BY2WD); buf[0] = Config<<24; /* Function */ buf[0] |= 0x00; /* Action (PAGE_HEADER) */ buf[1] = 0x12<<16; /* ExtPageType (SAS_DEVICE) */ @@ -672,7 +681,8 @@ mksge(buf+7, nil, 0, 0); /* PageBufferSGE (empty) */ doorbell(ctlr, buf, 7+2); - ckstatus(ctlr, buf); + if(!ckstatus(ctlr, buf)) + error(Ebadunit); buf[0] |= 0x01; /* Action (READ_CURRENT) */ buf[6] = 0x2<<28 | u->devh; /* PageAddress (HANDLE) */ @@ -696,7 +706,7 @@ r = nextreq(ctlr); if(r == nil) error(Enoreqs); - memset(r->req, 0, W2B(11)); + memset(r->req, 0, 11*BY2WD); r->req[0] = SasIoUnitControl<<24; /* Function */ r->req[0] |= 0x0d; /* Operation (REMOVE_DEVICE) */ r->req[1] = u->devh; /* DevHandle */ @@ -716,7 +726,7 @@ r = nextreq(ctlr); if(r == nil) error(Enoreqs); - memset(r->req, 0, W2B(13)); + memset(r->req, 0, 13*BY2WD); r->req[0] = ScsiTaskManagement<<24; /* Function */ r->req[0] |= u->devh; /* DevHandle */ r->req[1] = 0x03<<8; /* TaskType (Target Reset) */ @@ -736,7 +746,7 @@ r = nextreq(ctlr); if(r == nil) error(Enoreqs); - memset(r->req, 0, W2B(13)); + memset(r->req, 0, 13*BY2WD); r->req[0] = ScsiTaskManagement<<24; /* Function */ r->req[0] |= u->devh; /* DevHandle */ r->req[1] = 0x01<<8; /* TaskType (Abort Task) */ @@ -760,7 +770,7 @@ return; } r->sdreq = sdreq; - memset(r->req, 0, W2B(24)); + memset(r->req, 0, 24*BY2WD); r->req[0] = ScsiIoRequest<<24; /* Function */ r->req[0] |= u->devh; /* DevHandle */ r->req[3] = PCIWADDR(sdreq->sense); /* SenseBufferLowAddress */ @@ -797,7 +807,7 @@ freereq(ctlr, r); } -#define REPLY(ctlr, n) ((ctlr)->reply + (n)*1) +#define REPLY(ctlr, n) ((ctlr)->reply + (n)*(ctlr)->replyfsz) #define REPLYPOST(ctlr, n) ((ctlr)->replypost + (n)*2) static ulong * @@ -806,13 +816,12 @@ free(ctlr->reply); /* - * System Reply Message Frames are less disciplined; they - * do not have to be contiguous, must be aligned on a - * 4-byte boundary, and must be a multiple of 4 bytes in - * length. + * System Reply Message Frames are less disciplined; they do + * not have to be contiguous, must be aligned on a 4-byte + * boundary, and must be a multiple of 4 bytes in length. */ ctlr->replyq = ctlr->reqcredit + 32; /* PG §3.1.3 */ - ctlr->reply = mallocz(ctlr->replyq * W2B(ctlr->replyfsz), 0); + ctlr->reply = mallocz(ctlr->replyq * ctlr->replyfsz*BY2WD, 0); if(ctlr->reply == nil) print("reallocreply: %s: out of memory\n", ctlr->name); return ctlr->reply; @@ -825,11 +834,11 @@ /* * The Reply Free Queue must be allocated contiguously, - * aligned on a 16-byte boundary, and must have a depth - * that is a multiple of 16 bytes. + * aligned on a 16-byte boundary, and must have a depth that + * is a multiple of 16 bytes. */ ctlr->replyfreeq = ROUNDUP(ctlr->replyq + 1, 16); - ctlr->replyfree = mallocalign(ctlr->replyfreeq * W2B(1), 16, 0, 0); + ctlr->replyfree = mallocalign(ctlr->replyfreeq * BY2WD, 16, 0, 0); if(ctlr->replyfree == nil) print("reallocreplyfree: %s: out of memory\n", ctlr->name); return ctlr->replyfree; @@ -842,13 +851,13 @@ /* * The Reply Descriptor Post Queue must be allocated - * contiguously and aligned on a 16-byte boundary. The - * depth must not exceed MaxReplyDescriptorPostQueueDepth - * returned in the IOC Facts reply. + * contiguously and aligned on a 16-byte boundary. The depth + * must not exceed MaxReplyDescriptorPostQueueDepth returned + * in the IOC Facts reply. */ ctlr->replypostq = MIN(ctlr->replypostmax, ROUNDUP(ctlr->replyq + ctlr->reqcredit + 1, 16)); - ctlr->replypost = mallocalign(ctlr->replypostq * W2B(2), 16, 0, 0); + ctlr->replypost = mallocalign(ctlr->replypostq * 2*BY2WD, 16, 0, 0); if(ctlr->replypost == nil) print("reallocreplypost: %s: out of memory\n", ctlr->name); return ctlr->replypost; @@ -933,8 +942,8 @@ /* * Unfortunately, devsd limits us to 16 devices, which * essentially precludes support for SAS expanders and/or - * enclosures. A one-to-one mapping exists between a - * direct attached PHY and a device for simplicity. + * enclosures. A one-to-one mapping exists between a direct + * attached PHY and a device for simplicity. */ if(data[0]>>16 != 0x0) /* ExpanderDevHandle */ return; @@ -942,29 +951,28 @@ return; /* - * SAS topology changes are handled in two phases; we - * first obtain identifying information from event data. - * New units require additional configuration information - * and missing units must have resources released. + * SAS topology changes are handled in two phases; we first + * obtain identifying information from event data. New units + * require additional configuration information and missing + * units must have resources released. */ p = data + 3; e = p + (data[2] & 0xff); /* NumEntries */ i = data[2]>>8 & 0xff; /* StartPhyNum */ - for(; p < e && i < Nunit; ++p, ++i){ + for(; p < e && i < nelem(ctlr->unit); ++p, ++i){ u = UNIT(ctlr, i); - switch(*p>>24 & 0xf){ /* PhyStatus (Reason Code) */ + u->status = *p>>24 & 0xff; /* PhyStatus */ + u->link = *p>>16 & 0xff; /* LinkRate */ + switch(u->status & 0xf){ /* Reason Code */ case 0x1: u->devh = *p & 0xffff; /* AttachedDevHandle */ unitconfig(ctlr, u); - u->state = Online; break; case 0x2: - u->state = Offline; unitreset(ctlr, u); unitremove(ctlr, u); break; } - u->link = *p>>16 & 0xff; /* LinkRate */ } } @@ -983,7 +991,7 @@ topoevent(ctlr, data); break; default: - panic("doevent: %s: bad event 0x%04ux", ctlr->name, event); + panic("doevent: %s: bad event %#.4ux", ctlr->name, event); } if(reply[1]>>16 & 0xff) /* AckRequired */ eventack(ctlr, event, context); @@ -995,7 +1003,7 @@ int n; Block *bp; - n = W2B(reply[0]>>16 & 0xff); /* MsgLength */ + n = (reply[0]>>16 & 0xff)*BY2WD; /* MsgLength */ bp = iallocb(n); if(bp == nil) panic("qevent: %s: out of memory", ctlr->name); @@ -1026,18 +1034,18 @@ case EventNotification: /* * We queue events for handling in a separate - * process to ensure sanity when the IOC - * requires synchronization via acknowledgement. + * process to ensure sanity when the IOC requires + * synchronization via acknowledgement. */ qevent(ctlr, reply); break; default: - panic("addressreply: %s: bad function 0x%02ux", ctlr->name, fn); + panic("addressreply: %s: bad function %#.2ux", ctlr->name, fn); } /* - * To simplify handing a System Reply Message Frame back - * to the IOC, we update the ReplyFreeHostIndex register + * To simplify handing a System Reply Message Frame back to + * the IOC, we update the ReplyFreeHostIndex register * immediately. Unfortunately, this requires additional * coherence. */ @@ -1100,9 +1108,9 @@ /* * Each time the controller is reset, an IOC Facts reponse - * may return different values. We err on the side of - * caution and reallocate resources prior to issuing an - * IOC Init request. + * may return different values. We err on the side of caution + * and reallocate resources prior to issuing an IOC Init + * request. */ iocfacts(ctlr); if(reallocreq(ctlr)) @@ -1117,25 +1125,23 @@ /* * Initialize System Request Message Frames and associated * structures. A SMID is written once to avoid headaches - * constructing messages in the I/O path. A SMID of 0 must - * be initialized and is considered reserved; it may not be + * constructing messages in the I/O path. A SMID of 0 must be + * initialized and is considered reserved; it may not be * placed on the free list or used by the host in any way. */ ctlr->reqfree = nil; - for(i = 0; i < ctlr->reqcredit; ++i) - if(i > 0){ - r = REQ(ctlr, i); - r->smid = i; - r->req = (ulong *)r - ctlr->iocreqfsz; - freereq(ctlr, r); - } + for(i = 1; i < ctlr->reqcredit; ++i){ + r = REQ(ctlr, i); + r->smid = i; + r->req = (ulong *)r - ctlr->iocreqfsz; + freereq(ctlr, r); + } /* * The Reply Descriptor Post Queue must be initialized with * the unused descriptor type for each entry. This is - * slightly reordered to take advantage of coherence - * required when updating the ReplyFreeHostIndex register - * below. + * slightly reordered to take advantage of coherence required + * when updating the ReplyFreeHostIndex register below. */ ctlr->replypostp = 0; for(i = 0; i < ctlr->replypostq; ++i){ @@ -1144,10 +1150,10 @@ } /* - * The Reply Free Queue is initialized with the lower - * 32 bits of the PADDR for each System Reply Frame. The - * ReplyFreeHostIndex register is initialized with the - * next (unused) entry. + * The Reply Free Queue is initialized with the lower 32 + * bits of the PADDR for each System Reply Frame. The + * ReplyFreeHostIndex register is initialized with the next + * (unused) entry. */ ctlr->replyfreep = 0; for(i = 0; i < ctlr->replyq; ++i){ @@ -1220,22 +1226,22 @@ } ioc = iocs++; snprint(name, sizeof name, "ioc%d", ioc); - ctlr = malloc(sizeof(Ctlr)); + ctlr = malloc(sizeof *ctlr); if(ctlr == nil){ print("mpt2pnp: %s: out of memory\n", name); continue; } ctlr->ioc = ioc; - strncpy(ctlr->name, name, sizeof(ctlr->name)); - ctlr->port = ioalloc(p->mem[0].bar & ~1, p->mem[0].size, 0, "mpt2"); - if(ctlr->port < 0){ - print("mpt2pnp: %s: ioalloc failed\n", name); + strncpy(ctlr->name, name, sizeof ctlr->name); + ctlr->port = p->mem[0].bar & ~1; + if(ioalloc(ctlr->port, p->mem[0].size, 0, "mpt2") < 0){ + print("mpt2pnp: %s: port %ux in use\n", name, ctlr->port); freectlr(ctlr); continue; } pcisetbme(p); ctlr->pcidev = p; - ctlr->eventq = qopen(0, Qmsg | Qclosed, nil, nil); + ctlr->eventq = qopen(0, Qmsg|Qclosed, nil, nil); if(ctlr->eventq == nil){ print("mpt2pnp: %s: qopen failed\n", name); freectlr(ctlr); @@ -1247,7 +1253,7 @@ freectlr(ctlr); continue; } - sdev = malloc(sizeof(SDev)); + sdev = malloc(sizeof *sdev); if(sdev == nil){ print("mpt2pnp: %s: out of memory\n", name); freectlr(ctlr); @@ -1256,7 +1262,7 @@ sdev->ifc = &sdmpt2ifc; sdev->ctlr = ctlr; sdev->idno = 'M' + ioc; - sdev->nunit = Nunit; + sdev->nunit = nelem(ctlr->unit); ctlr->sdev = sdev; print("#S/sd%c: %s: mpt2 sas-2 with %d ports, %d max targets\n", sdev->idno, name, ctlr->numports, ctlr->maxtargs); @@ -1283,10 +1289,7 @@ iunlock(ctlr); return; } - for(;;){ - desc = nextreplypost(ctlr); - if(desc == nil) - break; + while(desc = nextreplypost(ctlr)){ switch(desc[0] & 0xf){ /* ReplyFlags */ case ScsiIoSuccess: smid = desc[0]>>16; /* SMID */ @@ -1298,7 +1301,7 @@ addressreply(ctlr, smid, reply); break; default: - panic("mpt2interrupt: %s: bad reply 0x%08ulx 0x%08ulx", + panic("mpt2interrupt: %s: bad reply %#.8ulx %#.8ulx", ctlr->name, desc[0], desc[1]); } freereplypost(ctlr, desc); @@ -1353,9 +1356,9 @@ /* * For the unwary, a pending reset will first close the - * eventq, which will cause qbread to eventually error. - * The control structure below yields to the reset kproc - * until the eventq is reopened and sanity is restored. + * eventq, which will cause qbread to eventually error. The + * control structure below yields to the reset kproc until the + * eventq is reopened and sanity is restored. */ ctlr = arg; while(waserror()) @@ -1366,8 +1369,7 @@ runlock(&ctlr->resetlock); nexterror(); } - bp = qbread(ctlr->eventq, 0); - if(bp) + if(bp = qbread(ctlr->eventq, 0)) if(waserror()) wakeup(&ctlr->reset); else{ @@ -1401,13 +1403,14 @@ kproc("mpt2reset", mpt2reset, ctlr); kproc("mpt2event", mpt2event, ctlr); } + if(waserror()) print("mpt2enable: %s: %s\n", ctlr->name, up->errstr); else{ portenable(ctlr); poperror(); } - return 1; + return 0; } static int @@ -1425,7 +1428,7 @@ snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name); intrdisable(p->intl, mpt2interrupt, ctlr, p->tbdf, name); - return 1; + return 0; } static int @@ -1441,7 +1444,7 @@ runlock(&ctlr->resetlock); return SDeio; } - if(u->state != Online) + if(!unitonline(u)) error(Ebadunit); if(waserror()){ wakeup(&ctlr->reset); @@ -1470,10 +1473,10 @@ u = UNIT(ctlr, unit->subno); getunitcaps(u, buf, sizeof buf); p = seprint(p, e, "capabilities %s\n", buf); - p = seprint(p, e, "wwn %ullx\n", GBIT64(u->wwn)); + p = seprint(p, e, "wwn %ullx\n", getle(u->wwn, 8)); p = seprint(p, e, "type %s\n", unittype(u)); + p = seprint(p, e, "status %s\n", unitstatus(u)); p = seprint(p, e, "link %s\n", unitlink(u)); - p = seprint(p, e, "state %s\n", unitstate(u)); p = seprint(p, e, "geometry %ulld %uld\n", unit->sectors, unit->secsize); return p - o; --- /sys/src/9/pcpae/paecpu Fri Aug 16 23:18:46 2013 +++ /sys/src/9/pcpae/paecpu Fri Aug 16 23:18:46 2013 @@ -68,9 +68,9 @@ sdaoe sdide pci sdiahci pci sdscsi led - sdmpt2 pci sdscsi sdloop sdodin pci sdscsi led + sdmpt2 pci sdscsi ip il