Commit ffb17d43 authored by Jeff Garzik's avatar Jeff Garzik

[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
parent a163af74
......@@ -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);
......@@ -723,6 +731,31 @@ static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
return sizeof(page);
}
/**
* 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.
......@@ -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? */
......
......@@ -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))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment