svn commit: r220858 - stable/8/sys/dev/mvs
Alexander Motin
mav at FreeBSD.org
Tue Apr 19 17:08:30 UTC 2011
Author: mav
Date: Tue Apr 19 17:08:29 2011
New Revision: 220858
URL: http://svn.freebsd.org/changeset/base/220858
Log:
MFC r220569:
Implement automatic SCSI sense fetching for mvs(4).
Make few improvements/changes to ATAPI PIO support to pass most of scgcheck
(cdrtools) tests.
Modified:
stable/8/sys/dev/mvs/mvs.c
stable/8/sys/dev/mvs/mvs.h
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
Modified: stable/8/sys/dev/mvs/mvs.c
==============================================================================
--- stable/8/sys/dev/mvs/mvs.c Tue Apr 19 17:06:43 2011 (r220857)
+++ stable/8/sys/dev/mvs/mvs.c Tue Apr 19 17:08:29 2011 (r220858)
@@ -85,14 +85,21 @@ static void mvs_requeue_frozen(device_t
static void mvs_execute_transaction(struct mvs_slot *slot);
static void mvs_end_transaction(struct mvs_slot *slot, enum mvs_err_type et);
-static void mvs_issue_read_log(device_t dev);
+static void mvs_issue_recovery(device_t dev);
static void mvs_process_read_log(device_t dev, union ccb *ccb);
+static void mvs_process_request_sense(device_t dev, union ccb *ccb);
static void mvsaction(struct cam_sim *sim, union ccb *ccb);
static void mvspoll(struct cam_sim *sim);
MALLOC_DEFINE(M_MVS, "MVS driver", "MVS driver data buffers");
+#define recovery_type spriv_field0
+#define RECOVERY_NONE 0
+#define RECOVERY_READ_LOG 1
+#define RECOVERY_REQUEST_SENSE 2
+#define recovery_slot spriv_field1
+
static int
mvs_ch_probe(device_t dev)
{
@@ -821,7 +828,8 @@ mvs_legacy_intr(device_t dev)
union ccb *ccb = slot->ccb;
enum mvs_err_type et = MVS_ERR_NONE;
int port;
- u_int length;
+ u_int length, resid, size;
+ uint8_t buf[2];
uint8_t status, ireason;
/* Clear interrupt and get status. */
@@ -894,6 +902,7 @@ mvs_legacy_intr(device_t dev)
} else { /* ATAPI PIO */
length = ATA_INB(ch->r_mem,ATA_CYL_LSB) |
(ATA_INB(ch->r_mem,ATA_CYL_MSB) << 8);
+ size = min(ch->transfersize, length);
ireason = ATA_INB(ch->r_mem,ATA_IREASON);
switch ((ireason & (ATA_I_CMD | ATA_I_IN)) |
(status & ATA_S_DRQ)) {
@@ -912,7 +921,10 @@ mvs_legacy_intr(device_t dev)
}
ATA_OUTSW_STRM(ch->r_mem, ATA_DATA,
(uint16_t *)(ccb->csio.data_ptr + ch->donecount),
- length / 2);
+ (size + 1) / 2);
+ for (resid = ch->transfersize + (size & 1);
+ resid < length; resid += sizeof(int16_t))
+ ATA_OUTW(ch->r_mem, ATA_DATA, 0);
ch->donecount += length;
/* Set next transfer size according to HW capabilities */
ch->transfersize = min(ccb->csio.dxfer_len - ch->donecount,
@@ -926,9 +938,19 @@ mvs_legacy_intr(device_t dev)
et = MVS_ERR_TFE;
goto end_finished;
}
- ATA_INSW_STRM(ch->r_mem, ATA_DATA,
- (uint16_t *)(ccb->csio.data_ptr + ch->donecount),
- length / 2);
+ if (size >= 2) {
+ ATA_INSW_STRM(ch->r_mem, ATA_DATA,
+ (uint16_t *)(ccb->csio.data_ptr + ch->donecount),
+ size / 2);
+ }
+ if (size & 1) {
+ ATA_INSW_STRM(ch->r_mem, ATA_DATA, (void*)buf, 1);
+ ((uint8_t *)ccb->csio.data_ptr + ch->donecount +
+ (size & ~1))[0] = buf[0];
+ }
+ for (resid = ch->transfersize + (size & 1);
+ resid < length; resid += sizeof(int16_t))
+ ATA_INW(ch->r_mem, ATA_DATA);
ch->donecount += length;
/* Set next transfer size according to HW capabilities */
ch->transfersize = min(ccb->csio.dxfer_len - ch->donecount,
@@ -1362,8 +1384,7 @@ mvs_legacy_execute_transaction(struct mv
ATA_OUTL(ch->r_mem, DMA_C, DMA_C_START |
(((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) ?
DMA_C_READ : 0));
- } else if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
- ch->fake_busy = 1;
+ }
}
/* Start command execution timeout */
callout_reset(&slot->timeout, (int)ccb->ccb_h.timeout * hz / 1000,
@@ -1578,6 +1599,10 @@ mvs_end_transaction(struct mvs_slot *slo
mvs_tfd_read(dev, ccb);
} else
bzero(res, sizeof(*res));
+ } else {
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE &&
+ ch->basic_dma == 0)
+ ccb->csio.resid = ccb->csio.dxfer_len - ch->donecount;
}
if (ch->numpslots == 0 || ch->basic_dma) {
if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
@@ -1590,7 +1615,7 @@ mvs_end_transaction(struct mvs_slot *slo
if (et != MVS_ERR_NONE)
ch->eslots |= (1 << slot->slot);
/* In case of error, freeze device for proper recovery. */
- if ((et != MVS_ERR_NONE) && (!ch->readlog) &&
+ if ((et != MVS_ERR_NONE) && (!ch->recoverycmd) &&
!(ccb->ccb_h.status & CAM_DEV_QFRZN)) {
xpt_freeze_devq(ccb->ccb_h.path, 1);
ccb->ccb_h.status |= CAM_DEV_QFRZN;
@@ -1621,7 +1646,7 @@ mvs_end_transaction(struct mvs_slot *slo
break;
case MVS_ERR_SATA:
ch->fatalerr = 1;
- if (!ch->readlog) {
+ if (!ch->recoverycmd) {
xpt_freeze_simq(ch->sim, 1);
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
@@ -1629,7 +1654,7 @@ mvs_end_transaction(struct mvs_slot *slo
ccb->ccb_h.status |= CAM_UNCOR_PARITY;
break;
case MVS_ERR_TIMEOUT:
- if (!ch->readlog) {
+ if (!ch->recoverycmd) {
xpt_freeze_simq(ch->sim, 1);
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
@@ -1671,10 +1696,15 @@ mvs_end_transaction(struct mvs_slot *slo
xpt_release_simq(ch->sim, TRUE);
}
/* If it was our READ LOG command - process it. */
- if (ch->readlog) {
+ if (ccb->ccb_h.recovery_type == RECOVERY_READ_LOG) {
mvs_process_read_log(dev, ccb);
- /* If it was NCQ command error, put result on hold. */
- } else if (et == MVS_ERR_NCQ) {
+ /* If it was our REQUEST SENSE command - process it. */
+ } else if (ccb->ccb_h.recovery_type == RECOVERY_REQUEST_SENSE) {
+ mvs_process_request_sense(dev, ccb);
+ /* If it was NCQ or ATAPI command error, put result on hold. */
+ } else if (et == MVS_ERR_NCQ ||
+ ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR &&
+ (ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0)) {
ch->hold[slot->slot] = ccb;
ch->holdtag[slot->slot] = slot->tag;
ch->numhslots++;
@@ -1699,8 +1729,8 @@ mvs_end_transaction(struct mvs_slot *slo
ch->eslots = 0;
}
/* if there commands on hold, we can do READ LOG. */
- if (!ch->readlog && ch->numhslots)
- mvs_issue_read_log(dev);
+ if (!ch->recoverycmd && ch->numhslots)
+ mvs_issue_recovery(dev);
}
/* If all the rest of commands are in timeout - give them chance. */
} else if ((ch->rslots & ~ch->toslots) == 0 &&
@@ -1715,14 +1745,15 @@ mvs_end_transaction(struct mvs_slot *slo
}
static void
-mvs_issue_read_log(device_t dev)
+mvs_issue_recovery(device_t dev)
{
struct mvs_channel *ch = device_get_softc(dev);
union ccb *ccb;
struct ccb_ataio *ataio;
+ struct ccb_scsiio *csio;
int i;
- ch->readlog = 1;
+ ch->recoverycmd = 1;
/* Find some holden command. */
for (i = 0; i < MVS_MAX_SLOTS; i++) {
if (ch->hold[i])
@@ -1734,25 +1765,44 @@ mvs_issue_read_log(device_t dev)
return; /* XXX */
}
ccb->ccb_h = ch->hold[i]->ccb_h; /* Reuse old header. */
- ccb->ccb_h.func_code = XPT_ATA_IO;
- ccb->ccb_h.flags = CAM_DIR_IN;
- ccb->ccb_h.timeout = 1000; /* 1s should be enough. */
- ataio = &ccb->ataio;
- ataio->data_ptr = malloc(512, M_MVS, M_NOWAIT);
- if (ataio->data_ptr == NULL) {
- xpt_free_ccb(ccb);
- device_printf(dev, "Unable allocate memory for READ LOG command");
- return; /* XXX */
+ if (ccb->ccb_h.func_code == XPT_ATA_IO) {
+ /* READ LOG */
+ ccb->ccb_h.recovery_type = RECOVERY_READ_LOG;
+ ccb->ccb_h.func_code = XPT_ATA_IO;
+ ccb->ccb_h.flags = CAM_DIR_IN;
+ ccb->ccb_h.timeout = 1000; /* 1s should be enough. */
+ ataio = &ccb->ataio;
+ ataio->data_ptr = malloc(512, M_MVS, M_NOWAIT);
+ if (ataio->data_ptr == NULL) {
+ xpt_free_ccb(ccb);
+ device_printf(dev, "Unable allocate memory for READ LOG command");
+ return; /* XXX */
+ }
+ ataio->dxfer_len = 512;
+ bzero(&ataio->cmd, sizeof(ataio->cmd));
+ ataio->cmd.flags = CAM_ATAIO_48BIT;
+ ataio->cmd.command = 0x2F; /* READ LOG EXT */
+ ataio->cmd.sector_count = 1;
+ ataio->cmd.sector_count_exp = 0;
+ ataio->cmd.lba_low = 0x10;
+ ataio->cmd.lba_mid = 0;
+ ataio->cmd.lba_mid_exp = 0;
+ } else {
+ /* REQUEST SENSE */
+ ccb->ccb_h.recovery_type = RECOVERY_REQUEST_SENSE;
+ ccb->ccb_h.recovery_slot = i;
+ ccb->ccb_h.func_code = XPT_SCSI_IO;
+ ccb->ccb_h.flags = CAM_DIR_IN;
+ ccb->ccb_h.status = 0;
+ ccb->ccb_h.timeout = 1000; /* 1s should be enough. */
+ csio = &ccb->csio;
+ csio->data_ptr = (void *)&ch->hold[i]->csio.sense_data;
+ csio->dxfer_len = ch->hold[i]->csio.sense_len;
+ csio->cdb_len = 6;
+ bzero(&csio->cdb_io, sizeof(csio->cdb_io));
+ csio->cdb_io.cdb_bytes[0] = 0x03;
+ csio->cdb_io.cdb_bytes[4] = csio->dxfer_len;
}
- ataio->dxfer_len = 512;
- bzero(&ataio->cmd, sizeof(ataio->cmd));
- ataio->cmd.flags = CAM_ATAIO_48BIT;
- ataio->cmd.command = 0x2F; /* READ LOG EXT */
- ataio->cmd.sector_count = 1;
- ataio->cmd.sector_count_exp = 0;
- ataio->cmd.lba_low = 0x10;
- ataio->cmd.lba_mid = 0;
- ataio->cmd.lba_mid_exp = 0;
/* Freeze SIM while doing READ LOG EXT. */
xpt_freeze_simq(ch->sim, 1);
mvs_begin_transaction(dev, ccb);
@@ -1766,7 +1816,7 @@ mvs_process_read_log(device_t dev, union
struct ata_res *res;
int i;
- ch->readlog = 0;
+ ch->recoverycmd = 0;
data = ccb->ataio.data_ptr;
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
@@ -1819,6 +1869,28 @@ mvs_process_read_log(device_t dev, union
xpt_release_simq(ch->sim, TRUE);
}
+static void
+mvs_process_request_sense(device_t dev, union ccb *ccb)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ int i;
+
+ ch->recoverycmd = 0;
+
+ i = ccb->ccb_h.recovery_slot;
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ ch->hold[i]->ccb_h.status |= CAM_AUTOSNS_VALID;
+ } else {
+ ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK;
+ ch->hold[i]->ccb_h.status |= CAM_AUTOSENSE_FAIL;
+ }
+ xpt_done(ch->hold[i]);
+ ch->hold[i] = NULL;
+ ch->numhslots--;
+ xpt_free_ccb(ccb);
+ xpt_release_simq(ch->sim, TRUE);
+}
+
static int
mvs_wait(device_t dev, u_int s, u_int c, int t)
{
@@ -2051,6 +2123,7 @@ mvsaction(struct cam_sim *sim, union ccb
ccb->ccb_h.status = CAM_SEL_TIMEOUT;
break;
}
+ ccb->ccb_h.recovery_type = RECOVERY_NONE;
/* Check for command collision. */
if (mvs_check_collision(dev, ccb)) {
/* Freeze command. */
Modified: stable/8/sys/dev/mvs/mvs.h
==============================================================================
--- stable/8/sys/dev/mvs/mvs.h Tue Apr 19 17:06:43 2011 (r220857)
+++ stable/8/sys/dev/mvs/mvs.h Tue Apr 19 17:08:29 2011 (r220858)
@@ -557,7 +557,7 @@ struct mvs_channel {
int numtslots; /* Number of NCQ slots */
int numtslotspd[16];/* Number of NCQ slots per dev */
int numhslots; /* Number of holden slots */
- int readlog; /* Our READ LOG active */
+ int recoverycmd; /* Our READ LOG active */
int fatalerr; /* Fatal error happend */
int lastslot; /* Last used slot */
int taggedtarget; /* Last tagged target */
More information about the svn-src-stable-8
mailing list