Skip to content

Commit

Permalink
[libata] scsi: support MODE SENSE request for changeable and default …
Browse files Browse the repository at this point in the history
…parameters

Since the next patch will introduce support for MODE SELECT, it
makes sense to start advertising which bits are actually changeable.
For now, the answer is none.

Default parameters can also be reported, they are simply the same
as the current parameters.

Signed-off-by: Paolo Bonzini <[email protected]>
Signed-off-by: Jeff Garzik <[email protected]>
  • Loading branch information
bonzini authored and Jeff Garzik committed Aug 17, 2012
1 parent 3e451a4 commit 6ca8e79
Showing 1 changed file with 43 additions and 16 deletions.
59 changes: 43 additions & 16 deletions drivers/ata/libata-scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2204,10 +2204,34 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
return 0;
}

/**
* modecpy - Prepare response for MODE SENSE
* @dest: output buffer
* @src: data being copied
* @n: length of mode page
* @changeable: whether changeable parameters are requested
*
* Generate a generic MODE SENSE page for either current or changeable
* parameters.
*
* LOCKING:
* None.
*/
static void modecpy(u8 *dest, const u8 *src, int n, bool changeable)
{
if (changeable) {
memcpy(dest, src, 2);
memset(dest + 2, 0, n - 2);
} else {
memcpy(dest, src, n);
}
}

/**
* ata_msense_caching - Simulate MODE SENSE caching info page
* @id: device IDENTIFY data
* @buf: output buffer
* @changeable: whether changeable parameters are requested
*
* Generate a caching info page, which conditionally indicates
* write caching to the SCSI layer, depending on device
Expand All @@ -2216,43 +2240,46 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
* LOCKING:
* None.
*/
static unsigned int ata_msense_caching(u16 *id, u8 *buf)
static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable)
{
memcpy(buf, def_cache_mpage, sizeof(def_cache_mpage));
if (ata_id_wcache_enabled(id))
modecpy(buf, def_cache_mpage, sizeof(def_cache_mpage), changeable);
if (!changeable && ata_id_wcache_enabled(id))
buf[2] |= (1 << 2); /* write cache enable */
if (!ata_id_rahead_enabled(id))
if (!changeable && !ata_id_rahead_enabled(id))
buf[12] |= (1 << 5); /* disable read ahead */
return sizeof(def_cache_mpage);
}

/**
* ata_msense_ctl_mode - Simulate MODE SENSE control mode page
* @buf: output buffer
* @changeable: whether changeable parameters are requested
*
* Generate a generic MODE SENSE control mode page.
*
* LOCKING:
* None.
*/
static unsigned int ata_msense_ctl_mode(u8 *buf)
static unsigned int ata_msense_ctl_mode(u8 *buf, bool changeable)
{
memcpy(buf, def_control_mpage, sizeof(def_control_mpage));
modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable);
return sizeof(def_control_mpage);
}

/**
* ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
* @buf: output buffer
* @changeable: whether changeable parameters are requested
*
* Generate a generic MODE SENSE r/w error recovery page.
*
* LOCKING:
* None.
*/
static unsigned int ata_msense_rw_recovery(u8 *buf)
static unsigned int ata_msense_rw_recovery(u8 *buf, bool changeable)
{
memcpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage));
modecpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage),
changeable);
return sizeof(def_rw_recovery_mpage);
}

Expand Down Expand Up @@ -2316,11 +2343,11 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
page_control = scsicmd[2] >> 6;
switch (page_control) {
case 0: /* current */
case 1: /* changeable */
case 2: /* defaults */
break; /* supported */
case 3: /* saved */
goto saving_not_supp;
case 1: /* changeable */
case 2: /* defaults */
default:
goto invalid_fld;
}
Expand All @@ -2341,21 +2368,21 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)

switch(pg) {
case RW_RECOVERY_MPAGE:
p += ata_msense_rw_recovery(p);
p += ata_msense_rw_recovery(p, page_control == 1);
break;

case CACHE_MPAGE:
p += ata_msense_caching(args->id, p);
p += ata_msense_caching(args->id, p, page_control == 1);
break;

case CONTROL_MPAGE:
p += ata_msense_ctl_mode(p);
p += ata_msense_ctl_mode(p, page_control == 1);
break;

case ALL_MPAGES:
p += ata_msense_rw_recovery(p);
p += ata_msense_caching(args->id, p);
p += ata_msense_ctl_mode(p);
p += ata_msense_rw_recovery(p, page_control == 1);
p += ata_msense_caching(args->id, p, page_control == 1);
p += ata_msense_ctl_mode(p, page_control == 1);
break;

default: /* invalid page code */
Expand Down

0 comments on commit 6ca8e79

Please sign in to comment.