diff options
| author | Jeff Garzik <jgarzik@redhat.com> | 2004-05-16 16:21:15 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@redhat.com> | 2004-05-16 16:21:15 -0400 |
| commit | ffb17d43e7e39a0a323a261bae0124012ae83709 (patch) | |
| tree | abcc98ed71ddf79e6b94f60ec05781133bcfcecd | |
| parent | a163af74bf0a7dc9906c31f05a687cf2253fbff7 (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.c | 48 | ||||
| -rw-r--r-- | include/linux/ata.h | 1 |
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)) |
