summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@redhat.com>2004-05-16 16:21:15 -0400
committerJeff Garzik <jgarzik@redhat.com>2004-05-16 16:21:15 -0400
commitffb17d43e7e39a0a323a261bae0124012ae83709 (patch)
treeabcc98ed71ddf79e6b94f60ec05781133bcfcecd
parenta163af74bf0a7dc9906c31f05a687cf2253fbff7 (diff)
[libata] scsi simulator improvements: MODE SENSE, SEEK(6,10), REZERO_UNIT
* SEEK(6), SEEK(10), and REZERO_UNIT are no-ops. Unconditionally complete these commands with success. * MODE SENSE caching page work: * correct page length * set bit, if read-ahead is disabled * set bit, if writeback caching is enabled (previously, this bit was never set, even if writeback caching was enabled) * add MODE SENSE r/w error recovery page
-rw-r--r--drivers/scsi/libata-scsi.c48
-rw-r--r--include/linux/ata.h1
2 files changed, 46 insertions, 3 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 947f9ed36672..f5a1cd723a95 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -695,9 +695,17 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last,
static unsigned int ata_msense_caching(struct ata_device *dev, u8 **ptr_io,
const u8 *last)
{
- u8 page[7] = { 0xf, 0, 0x10, 0, 0x8, 0xa, 0 };
- if (dev->flags & ATA_DFLAG_WCACHE)
- page[6] = 0x4;
+ u8 page[] = {
+ 0x8, /* page code */
+ 0x12, /* page length */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 zeroes */
+ 0, 0, 0, 0, 0, 0, 0, 0 /* 8 zeroes */
+ };
+
+ if (ata_id_wcache_enabled(dev))
+ page[2] |= (1 << 2); /* write cache enable */
+ if (!ata_id_rahead_enabled(dev))
+ page[12] |= (1 << 5); /* disable read ahead */
ata_msense_push(ptr_io, last, page, sizeof(page));
return sizeof(page);
@@ -724,6 +732,31 @@ static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
}
/**
+ * ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
+ * @dev: Device associated with this MODE SENSE command
+ * @ptr_io: (input/output) Location to store more output data
+ * @last: End of output data buffer
+ *
+ * Generate a generic MODE SENSE r/w error recovery page.
+ *
+ * LOCKING:
+ * None.
+ */
+
+static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
+{
+ const u8 page[] = {
+ 0x1, /* page code */
+ 0xa, /* page length */
+ (1 << 7) | (1 << 6), /* note auto r/w reallocation */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 9 zeroes */
+ };
+
+ ata_msense_push(ptr_io, last, page, sizeof(page));
+ return sizeof(page);
+}
+
+/**
* ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
* @args: Port / device / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
@@ -762,6 +795,10 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
last = rbuf + buflen - 1;
switch(scsicmd[2] & 0x3f) {
+ case 0x01: /* r/w error recovery */
+ output_len += ata_msense_rw_recovery(&p, last);
+ break;
+
case 0x08: /* caching */
output_len += ata_msense_caching(dev, &p, last);
break;
@@ -772,6 +809,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
}
case 0x3f: /* all pages */
+ output_len += ata_msense_rw_recovery(&p, last);
output_len += ata_msense_caching(dev, &p, last);
output_len += ata_msense_ctl_mode(&p, last);
break;
@@ -1118,6 +1156,10 @@ static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
args.done = done;
switch(scsicmd[0]) {
+ /* no-op's, complete with success */
+ case REZERO_UNIT:
+ case SEEK_6:
+ case SEEK_10:
case TEST_UNIT_READY:
case FORMAT_UNIT: /* FIXME: correct? */
case SEND_DIAGNOSTIC: /* FIXME: correct? */
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 45c2b4670739..919509f32327 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -202,6 +202,7 @@ struct ata_taskfile {
};
#define ata_id_is_ata(dev) (((dev)->id[0] & (1 << 15)) == 0)
+#define ata_id_rahead_enabled(dev) ((dev)->id[85] & (1 << 6))
#define ata_id_wcache_enabled(dev) ((dev)->id[85] & (1 << 5))
#define ata_id_has_lba48(dev) ((dev)->id[83] & (1 << 10))
#define ata_id_has_wcache(dev) ((dev)->id[82] & (1 << 5))