PERFORCE change 177174 for review
Alexander Motin
mav at FreeBSD.org
Wed Apr 21 12:08:06 UTC 2010
http://p4web.freebsd.org/@@177174?ac=10
Change 177174 by mav at mav_mavtest on 2010/04/21 12:07:13
Implement error handling.
Affected files ...
.. //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs.c#4 edit
.. //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs.h#4 edit
Differences ...
==== //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs.c#4 (text+ko) ====
@@ -87,6 +87,7 @@
static void mvs_legacy_execute_transaction(struct mvs_slot *slot);
static void mvs_timeout(struct mvs_slot *slot);
static void mvs_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error);
+static void mvs_requeue_frozen(device_t dev);
static void mvs_execute_transaction(struct mvs_slot *slot);
static void mvs_end_transaction(struct mvs_slot *slot, enum mvs_err_type et);
@@ -843,6 +844,7 @@
ch->curr_mode = mode;
ch->fbs_enabled = 0;
ch->fake_busy = 0;
+ device_printf(dev, "EDMA mode: %d\n", mode);
if (mode == MVS_EDMA_OFF)
return;
/* Configure new mode. */
@@ -865,10 +867,10 @@
ATA_OUTL(ch->r_mem, EDMA_CFG, reg);
mvs_setup_edma_queues(dev);
/* Configure FBS */
- device_printf(dev, "fisc %08x\n",ATA_INL(ch->r_mem, SATA_FISC));
- device_printf(dev, "ltmode %08x\n",ATA_INL(ch->r_mem, SATA_LTM));
- device_printf(dev, "edmacfg %08x\n",ATA_INL(ch->r_mem, EDMA_CFG));
- device_printf(dev, "haltcond %08x\n",ATA_INL(ch->r_mem, EDMA_HC));
+// device_printf(dev, "fisc %08x\n",ATA_INL(ch->r_mem, SATA_FISC));
+// device_printf(dev, "ltmode %08x\n",ATA_INL(ch->r_mem, SATA_LTM));
+// device_printf(dev, "edmacfg %08x\n",ATA_INL(ch->r_mem, EDMA_CFG));
+// device_printf(dev, "haltcond %08x\n",ATA_INL(ch->r_mem, EDMA_HC));
/* Run EDMA. */
ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EENEDMA);
}
@@ -977,10 +979,13 @@
device_t dev = (device_t)arg->arg;
struct mvs_channel *ch = device_get_softc(dev);
uint32_t iec, serr = 0, fisic = 0;
+ enum mvs_err_type et;
+ int i, ccs, port = -1;
+ int edma = (ch->numtslots != 0 || ch->numdslots != 0);
-//device_printf(dev, "irq cause %02x IEC %08x\n",
-// arg->cause, ATA_INL(ch->r_mem, EDMA_IEC));
- if ((ch->numtslots != 0 || ch->numdslots != 0) && (arg->cause & 2))
+//device_printf(dev, "irq cause %02x EDMA %d IEC %08x\n",
+// arg->cause, edma, ATA_INL(ch->r_mem, EDMA_IEC));
+ if ((arg->cause & 2) && edma)
mvs_crbq_intr(dev);
if (arg->cause & 1) {
iec = ATA_INL(ch->r_mem, EDMA_IEC);
@@ -991,12 +996,82 @@
}
if (iec & EDMA_IE_ETRANSINT) {
fisic = ATA_INL(ch->r_mem, SATA_FISIC);
- ATA_OUTL(ch->r_mem, SATA_FISIC, ~fisic);
device_printf(dev, "FISC %08x\n", ATA_INL(ch->r_mem, SATA_FISC));
device_printf(dev, "FISIC %08x\n", fisic);
device_printf(dev, "FISIM %08x\n", ATA_INL(ch->r_mem, SATA_FISIM));
}
ATA_OUTL(ch->r_mem, EDMA_IEC, ~iec);
+ /* Interface errors or Device error. */
+ if (iec & (0xfffff000 | EDMA_IE_EDEVERR)) {
+ port = -1;
+ if (ch->numpslots != 0) {
+ ccs = 0;
+ } else {
+ if (ch->quirks & MVS_Q_GENIIE)
+ ccs = EDMA_S_EIOID(ATA_INL(ch->r_mem, EDMA_S));
+ else
+ ccs = EDMA_S_EDEVQUETAG(ATA_INL(ch->r_mem, EDMA_S));
+ /* Check if error is one-PMP-port-specific, */
+ if (ch->fbs_enabled) {
+ /* Which ports were active. */
+ for (i = 0; i < 16; i++) {
+ if (ch->numrslotspd[i] == 0)
+ continue;
+ if (port == -1)
+ port = i;
+ else if (port != i) {
+ port = -2;
+ break;
+ }
+ }
+ /* If several ports were active and EDMA still enabled -
+ * other ports are probably unaffected and may continue.
+ */
+ if (port == -2 && (iec & EDMA_IE_ESELFDIS) == 0) {
+ uint16_t p = ATA_INL(ch->r_mem, SATA_SATAITC) >> 16;
+ port = ffs(p) - 1;
+ if (port != (fls(p) - 1))
+ port = -2;
+ }
+ }
+ }
+device_printf(dev, "err slot %d port %d\n", ccs, port);
+ mvs_requeue_frozen(dev);
+ for (i = 0; i < MVS_MAX_SLOTS; i++) {
+ /* XXX: reqests in loading state. */
+ if (((ch->rslots >> i) & 1) == 0)
+ continue;
+ if (port >= 0 &&
+ ch->slot[i].ccb->ccb_h.target_id != port)
+ continue;
+ if (iec & EDMA_IE_EDEVERR) { /* Device error. */
+ if (port != -2) {
+ if (ch->numtslots == 0) {
+ /* Untagged operation. */
+ if (i == ccs)
+ et = MVS_ERR_TFE;
+ else
+ et = MVS_ERR_INNOCENT;
+ } else {
+ /* Tagged operation. */
+ et = MVS_ERR_NCQ;
+ }
+ } else {
+ et = MVS_ERR_TFE;
+ ch->fatalerr = 1;
+ }
+ } else if (iec & 0xfffff000) {
+ if (ch->numtslots == 0 && i != ccs && port != -2)
+ et = MVS_ERR_INNOCENT;
+ else
+ et = MVS_ERR_SATA;
+ } else
+ et = MVS_ERR_INVALID;
+ mvs_end_transaction(&ch->slot[i], et);
+ }
+ }
+ if (fisic)
+ ATA_OUTL(ch->r_mem, SATA_FISIC, ~fisic);
if (iec & EDMA_IE_ESELFDIS)
ch->curr_mode = MVS_EDMA_OFF;
if ((iec & (EDMA_IE_EDEVDIS | EDMA_IE_EDEVCON)) ||
@@ -1005,146 +1080,8 @@
if (fisic & SATA_FISC_FISWAIT4HOSTRDYEN_B1)
mvs_notify_events(dev, ch->pm_present ? 0x8000 : 0x0001);
}
- if ((ch->numpslots != 0) && (arg->cause & 2))
+ if ((arg->cause & 2) && !edma)
mvs_legacy_intr(dev);
-#if 0
- uint32_t istatus, sstatus, cstatus, serr = 0, sntf = 0, ok, err;
- enum mvs_err_type et;
- int i, ccs, port;
-
- /* Read and clear interrupt statuses. */
- istatus = ATA_INL(ch->r_mem, MVS_P_IS);
- if (istatus == 0)
- return;
- ATA_OUTL(ch->r_mem, MVS_P_IS, istatus);
- /* Read command statuses. */
- sstatus = ATA_INL(ch->r_mem, MVS_P_SACT);
- cstatus = ATA_INL(ch->r_mem, MVS_P_CI);
- if (istatus & MVS_P_IX_SDB) {
- if (ch->caps & MVS_CAP_SSNTF)
- sntf = ATA_INL(ch->r_mem, MVS_P_SNTF);
- else if (ch->fbs_enabled) {
- u_int8_t *fis = ch->dma.rfis + 0x58;
-
- for (i = 0; i < 16; i++) {
- if (fis[1] & 0x80) {
- fis[1] &= 0x7f;
- sntf |= 1 << i;
- }
- fis += 256;
- }
- } else {
- u_int8_t *fis = ch->dma.rfis + 0x58;
-
- if (fis[1] & 0x80)
- sntf = (1 << (fis[1] & 0x0f));
- }
- }
- /* Process PHY events */
- if (istatus & (MVS_P_IX_PC | MVS_P_IX_PRC | MVS_P_IX_OF |
- MVS_P_IX_IF | MVS_P_IX_HBD | MVS_P_IX_HBF | MVS_P_IX_TFE)) {
- serr = ATA_INL(ch->r_mem, SATA_SE);
- if (serr) {
- ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff);
- mvs_phy_check_events(dev, serr);
- }
- }
- /* Process command errors */
- if (istatus & (MVS_P_IX_OF | MVS_P_IX_IF |
- MVS_P_IX_HBD | MVS_P_IX_HBF | MVS_P_IX_TFE)) {
- ccs = (ATA_INL(ch->r_mem, MVS_P_CMD) & MVS_P_CMD_CCS_MASK)
- >> MVS_P_CMD_CCS_SHIFT;
-//device_printf(dev, "%s ERROR is %08x cs %08x ss %08x rs %08x tfd %02x serr %08x fbs %08x ccs %d\n",
-// __func__, istatus, cstatus, sstatus, ch->rslots, ATA_INL(ch->r_mem, MVS_P_TFD),
-// serr, ATA_INL(ch->r_mem, MVS_P_FBS), ccs);
- port = -1;
- if (ch->fbs_enabled) {
- uint32_t fbs = ATA_INL(ch->r_mem, MVS_P_FBS);
- if (fbs & MVS_P_FBS_SDE) {
- port = (fbs & MVS_P_FBS_DWE)
- >> MVS_P_FBS_DWE_SHIFT;
- } else {
- for (i = 0; i < 16; i++) {
- if (ch->numrslotspd[i] == 0)
- continue;
- if (port == -1)
- port = i;
- else if (port != i) {
- port = -2;
- break;
- }
- }
- }
- }
- err = ch->rslots & (cstatus | sstatus);
- } else {
- ccs = 0;
- err = 0;
- port = -1;
- }
- /* Complete all successfull commands. */
- ok = ch->rslots & ~(cstatus | sstatus);
- for (i = 0; i < MVS_MAX_SLOTS; i++) {
- if ((ok >> i) & 1)
- mvs_end_transaction(&ch->slot[i], MVS_ERR_NONE);
- }
- /* On error, complete the rest of commands with error statuses. */
- if (err) {
- if (ch->frozen) {
- union ccb *fccb = ch->frozen;
- ch->frozen = NULL;
- fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
- if (!(fccb->ccb_h.status & CAM_DEV_QFRZN)) {
- xpt_freeze_devq(fccb->ccb_h.path, 1);
- fccb->ccb_h.status |= CAM_DEV_QFRZN;
- }
- xpt_done(fccb);
- }
- for (i = 0; i < MVS_MAX_SLOTS; i++) {
- /* XXX: reqests in loading state. */
- if (((err >> i) & 1) == 0)
- continue;
- if (port >= 0 &&
- ch->slot[i].ccb->ccb_h.target_id != port)
- continue;
- if (istatus & MVS_P_IX_TFE) {
- if (port != -2) {
- /* Task File Error */
- if (ch->numtslotspd[
- ch->slot[i].ccb->ccb_h.target_id] == 0) {
- /* Untagged operation. */
- if (i == ccs)
- et = MVS_ERR_TFE;
- else
- et = MVS_ERR_INNOCENT;
- } else {
- /* Tagged operation. */
- et = MVS_ERR_NCQ;
- }
- } else {
- et = MVS_ERR_TFE;
- ch->fatalerr = 1;
- }
- } else if (istatus & MVS_P_IX_IF) {
- if (ch->numtslots == 0 && i != ccs && port != -2)
- et = MVS_ERR_INNOCENT;
- else
- et = MVS_ERR_SATA;
- } else
- et = MVS_ERR_INVALID;
- mvs_end_transaction(&ch->slot[i], et);
- }
- /*
- * We can't reinit port if there are some other
- * commands active, use resume to complete them.
- */
- if (ch->rslots != 0)
- ATA_OUTL(ch->r_mem, MVS_P_FBS, MVS_P_FBS_EN | MVS_P_FBS_DEC);
- }
- /* Process NOTIFY events */
- if (sntf)
- mvs_notify_events(dev, sntf);
-#endif
}
static uint8_t
@@ -1166,7 +1103,8 @@
mvs_legacy_intr(device_t dev)
{
struct mvs_channel *ch = device_get_softc(dev);
- union ccb *ccb = ch->slot[0].ccb;
+ struct mvs_slot *slot = &ch->slot[0]; /* PIO is always in slot 0. */
+ union ccb *ccb = slot->ccb;
enum mvs_err_type et = MVS_ERR_NONE;
int port = ccb->ccb_h.target_id & 0x0f;
u_int length;
@@ -1176,7 +1114,7 @@
status = mvs_getstatus(dev, 1);
// device_printf(dev, "Legacy intr status %02x\n",
// status);
- if (ch->slot[0].state < MVS_SLOT_RUNNING) {
+ if (slot->state < MVS_SLOT_RUNNING) {
// device_printf(dev, "Stray irq\n");
return;
}
@@ -1343,7 +1281,7 @@
mvs_tfd_read(dev, ccb);
// device_printf(dev, "After complete status %02x\n",
// ATA_INB(ch->r_mem, ATA_ALTSTAT));
- mvs_end_transaction(&ch->slot[0], et);
+ mvs_end_transaction(slot, et);
}
static void
@@ -1363,15 +1301,24 @@
crpb = (struct mvs_crpb *)
(ch->dma.workrp + MVS_CRPB_OFFSET + (MVS_CRPB_SIZE * ch->in_idx));
slot = le16toh(crpb->id) & MVS_CRPB_TAG_MASK;
- if (ch->slot[slot].state >= MVS_SLOT_RUNNING) {
-//device_printf(dev, "CRPB %d %d %04x\n", ch->in_idx, slot, le16toh(crpb->rspflg));
- flags = le16toh(crpb->rspflg);
- ccb = ch->slot[slot].ccb;
- ccb->ataio.res.status = (flags & MVS_CRPB_ATASTS_MASK) >>
- MVS_CRPB_ATASTS_SHIFT;
- mvs_end_transaction(&ch->slot[slot], MVS_ERR_NONE);
- } else
-device_printf(dev, "EMPTY CRPB %d %d %04x\n", ch->in_idx, slot, le16toh(crpb->rspflg));
+ flags = le16toh(crpb->rspflg);
+//device_printf(dev, "CRPB %d %d %04x\n", ch->in_idx, slot, flags);
+ /*
+ * Handle only successfull completions.
+ * Errors will be handled by main intr handler.
+ */
+ if (ch->numtslots != 0 || (flags & EDMA_IE_EDEVERR) == 0) {
+if ((flags >> 8) & ATA_S_ERROR)
+device_printf(dev, "ERROR STATUS CRPB %d %d %04x\n", ch->in_idx, slot, flags);
+ if (ch->slot[slot].state >= MVS_SLOT_RUNNING) {
+ ccb = ch->slot[slot].ccb;
+ ccb->ataio.res.status = (flags & MVS_CRPB_ATASTS_MASK) >>
+ MVS_CRPB_ATASTS_SHIFT;
+ mvs_end_transaction(&ch->slot[slot], MVS_ERR_NONE);
+ } else
+device_printf(dev, "EMPTY CRPB %d %d %04x\n", ch->in_idx, slot, flags);
+ } else
+device_printf(dev, "ERROR FLAGS CRPB %d %d %04x\n", ch->in_idx, slot, flags);
ch->in_idx = (ch->in_idx + 1) & (MVS_MAX_SLOTS - 1);
}
@@ -1682,8 +1629,8 @@
int port = ccb->ccb_h.target_id & 0x0f;
int i;
-// device_printf(dev, "%d EDMA command %02x size %d (%p) slot %d tag %d\n",
-// port, ccb->ataio.cmd.command, ccb->ataio.dxfer_len, ccb->ataio.data_ptr, slot->slot, slot->tag);
+ device_printf(dev, "%d EDMA command %02x size %d (%p) slot %d tag %d\n",
+ port, ccb->ataio.cmd.command, ccb->ataio.dxfer_len, ccb->ataio.data_ptr, slot->slot, slot->tag);
/* Get address of the prepared EPRD */
eprd = ch->dma.workrq_bus + MVS_EPRD_OFFSET + (MVS_EPRD_SIZE * slot->slot);
/* Prepare CRQB. Gen IIe uses different CRQB format. */
@@ -1776,7 +1723,7 @@
ATA_OUTL(ch->r_mem, EDMA_REQQIP,
ch->dma.workrq_bus + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx));
/* Start command execution timeout */
- callout_reset(&slot->timeout, (int)ccb->ccb_h.timeout * hz / 2000,
+ callout_reset(&slot->timeout, (int)ccb->ccb_h.timeout * hz / 1000,
(timeout_t*)mvs_timeout, slot);
return;
}
@@ -1826,70 +1773,26 @@
{
device_t dev = slot->dev;
struct mvs_channel *ch = device_get_softc(dev);
-// uint32_t sstatus;
-// int ccs;
- int i;
/* Check for stale timeout. */
if (slot->state < MVS_SLOT_RUNNING)
return;
-#if 0
- /* Check if slot was not being executed last time we checked. */
- if (slot->state < MVS_SLOT_EXECUTING) {
- /* Check if slot started executing. */
- sstatus = ATA_INL(ch->r_mem, MVS_P_SACT);
- ccs = (ATA_INL(ch->r_mem, MVS_P_CMD) & MVS_P_CMD_CCS_MASK)
- >> MVS_P_CMD_CCS_SHIFT;
- if ((sstatus & (1 << slot->slot)) != 0 || ccs == slot->slot ||
- ch->fbs_enabled)
- slot->state = MVS_SLOT_EXECUTING;
-
- callout_reset(&slot->timeout,
- (int)slot->ccb->ccb_h.timeout * hz / 2000,
- (timeout_t*)mvs_timeout, slot);
- return;
- }
-#endif
device_printf(dev, "Timeout on slot %d\n", slot->slot);
device_printf(dev, "ic %08x iec %08x edma_s %08x dma_c %08x dma_s %08x rs %08x tfd %02x serr %08x\n",
ATA_INL(ch->r_mem, HC_IC), ATA_INL(ch->r_mem, EDMA_IEC),
ATA_INL(ch->r_mem, EDMA_S), ATA_INL(ch->r_mem, DMA_C), ATA_INL(ch->r_mem, DMA_S), ch->rslots,
ATA_INB(ch->r_mem, ATA_ALTSTAT), ATA_INL(ch->r_mem, SATA_SE));
-
/* Handle frozen command. */
- if (ch->frozen) {
- union ccb *fccb = ch->frozen;
- ch->frozen = NULL;
- fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
- if (!(fccb->ccb_h.status & CAM_DEV_QFRZN)) {
- xpt_freeze_devq(fccb->ccb_h.path, 1);
- fccb->ccb_h.status |= CAM_DEV_QFRZN;
- }
- xpt_done(fccb);
- }
- if (ch->fbs_enabled == 0 || ch->pm_present == 0) {
- /* Without FBS we know real timeout source. */
- ch->fatalerr = 1;
- /* Handle command with timeout. */
- mvs_end_transaction(&ch->slot[slot->slot], MVS_ERR_TIMEOUT);
- /* Handle the rest of commands. */
- for (i = 0; i < MVS_MAX_SLOTS; i++) {
- /* Do we have a running request on slot? */
- if (ch->slot[i].state < MVS_SLOT_RUNNING)
- continue;
- mvs_end_transaction(&ch->slot[i], MVS_ERR_INNOCENT);
- }
- } else {
- /* With FBS we wait for other commands timeout and pray. */
- if (ch->toslots == 0)
- xpt_freeze_simq(ch->sim, 1);
- ch->toslots |= (1 << slot->slot);
- if ((ch->rslots & ~ch->toslots) == 0)
- mvs_process_timeout(dev);
- else
- device_printf(dev, " ... waiting for slots %08x\n",
- ch->rslots & ~ch->toslots);
- }
+ mvs_requeue_frozen(dev);
+ /* We wait for other commands timeout and pray. */
+ if (ch->toslots == 0)
+ xpt_freeze_simq(ch->sim, 1);
+ ch->toslots |= (1 << slot->slot);
+ if ((ch->rslots & ~ch->toslots) == 0)
+ mvs_process_timeout(dev);
+ else
+ device_printf(dev, " ... waiting for slots %08x\n",
+ ch->rslots & ~ch->toslots);
}
/* Must be called with channel locked. */
@@ -1900,6 +1803,7 @@
struct mvs_channel *ch = device_get_softc(dev);
union ccb *ccb = slot->ccb;
+device_printf(dev, "cmd done status %d\n", et);
bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map,
BUS_DMASYNC_POSTWRITE);
/* Read result registers to the result struct
@@ -2008,6 +1912,7 @@
/* If it was NCQ command error, put result on hold. */
} else if (et == MVS_ERR_NCQ) {
ch->hold[slot->slot] = ccb;
+ ch->holdtag[slot->slot] = slot->tag;
ch->numhslots++;
} else
xpt_done(ccb);
@@ -2026,8 +1931,8 @@
} else {
/* if we have slots in error, we can reinit port. */
if (ch->eslots != 0) {
-// mvs_stop(dev);
-// mvs_start(dev, 1);
+ mvs_set_edma_mode(dev, MVS_EDMA_OFF);
+ ch->eslots = 0;
}
/* if there commands on hold, we can do READ LOG. */
if (!ch->readlog && ch->numhslots)
@@ -2103,7 +2008,9 @@
for (i = 0; i < MVS_MAX_SLOTS; i++) {
if (!ch->hold[i])
continue;
- if ((data[0] & 0x1F) == i) {
+ if (ch->hold[i]->ccb_h.target_id != ccb->ccb_h.target_id)
+ continue;
+ if ((data[0] & 0x1F) == ch->holdtag[i]) {
res = &ch->hold[i]->ataio.res;
res->status = data[2];
res->error = data[3];
@@ -2133,6 +2040,8 @@
for (i = 0; i < MVS_MAX_SLOTS; i++) {
if (!ch->hold[i])
continue;
+ if (ch->hold[i]->ccb_h.target_id != ccb->ccb_h.target_id)
+ continue;
xpt_done(ch->hold[i]);
ch->hold[i] = NULL;
ch->numhslots--;
@@ -2161,18 +2070,12 @@
}
static void
-mvs_reset(device_t dev)
+mvs_requeue_frozen(device_t dev)
{
struct mvs_channel *ch = device_get_softc(dev);
-// struct mvs_controller *ctlr = device_get_softc(device_get_parent(dev));
- int i;
+ union ccb *fccb = ch->frozen;
- xpt_freeze_simq(ch->sim, 1);
- if (bootverbose)
- device_printf(dev, "MVS reset...\n");
- /* Requeue freezed command. */
- if (ch->frozen) {
- union ccb *fccb = ch->frozen;
+ if (fccb) {
ch->frozen = NULL;
fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
if (!(fccb->ccb_h.status & CAM_DEV_QFRZN)) {
@@ -2181,6 +2084,19 @@
}
xpt_done(fccb);
}
+}
+
+static void
+mvs_reset(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ int i;
+
+ xpt_freeze_simq(ch->sim, 1);
+ if (bootverbose)
+ device_printf(dev, "MVS reset...\n");
+ /* Requeue freezed command. */
+ mvs_requeue_frozen(dev);
/* Kill the engine and requeue all running commands. */
mvs_set_edma_mode(dev, MVS_EDMA_OFF);
for (i = 0; i < MVS_MAX_SLOTS; i++) {
==== //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs.h#4 (text+ko) ====
@@ -510,6 +510,7 @@
struct mvs_slot slot[MVS_MAX_SLOTS];
union ccb *hold[MVS_MAX_SLOTS];
+ int holdtag[MVS_MAX_SLOTS]; /* Tags used for holden commands. */
struct mtx mtx; /* state lock */
int devices; /* What is present */
int pm_present; /* PM presence reported */
More information about the p4-projects
mailing list