aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-scsi.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2012-07-05 08:18:20 -0400
committerJeff Garzik <jgarzik@redhat.com>2012-08-17 14:09:59 -0400
commit6ca8e79466d34874c188906e775c8f1f8c89b67a (patch)
treed9cd7e69f271335ee4a5fdf2ccbe9945d737e13e /drivers/ata/libata-scsi.c
parent3e451a495d6a529d9a01c487f272bb2c4241158f (diff)
[libata] scsi: support MODE SENSE request for changeable and default 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 <pbonzini@redhat.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r--drivers/ata/libata-scsi.c59
1 files changed, 43 insertions, 16 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 86c2663e00e6..67d23bd87950 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2205,9 +2205,33 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
2205} 2205}
2206 2206
2207/** 2207/**
2208 * modecpy - Prepare response for MODE SENSE
2209 * @dest: output buffer
2210 * @src: data being copied
2211 * @n: length of mode page
2212 * @changeable: whether changeable parameters are requested
2213 *
2214 * Generate a generic MODE SENSE page for either current or changeable
2215 * parameters.
2216 *
2217 * LOCKING:
2218 * None.
2219 */
2220static void modecpy(u8 *dest, const u8 *src, int n, bool changeable)
2221{
2222 if (changeable) {
2223 memcpy(dest, src, 2);
2224 memset(dest + 2, 0, n - 2);
2225 } else {
2226 memcpy(dest, src, n);
2227 }
2228}
2229
2230/**
2208 * ata_msense_caching - Simulate MODE SENSE caching info page 2231 * ata_msense_caching - Simulate MODE SENSE caching info page
2209 * @id: device IDENTIFY data 2232 * @id: device IDENTIFY data
2210 * @buf: output buffer 2233 * @buf: output buffer
2234 * @changeable: whether changeable parameters are requested
2211 * 2235 *
2212 * Generate a caching info page, which conditionally indicates 2236 * Generate a caching info page, which conditionally indicates
2213 * write caching to the SCSI layer, depending on device 2237 * write caching to the SCSI layer, depending on device
@@ -2216,12 +2240,12 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
2216 * LOCKING: 2240 * LOCKING:
2217 * None. 2241 * None.
2218 */ 2242 */
2219static unsigned int ata_msense_caching(u16 *id, u8 *buf) 2243static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable)
2220{ 2244{
2221 memcpy(buf, def_cache_mpage, sizeof(def_cache_mpage)); 2245 modecpy(buf, def_cache_mpage, sizeof(def_cache_mpage), changeable);
2222 if (ata_id_wcache_enabled(id)) 2246 if (!changeable && ata_id_wcache_enabled(id))
2223 buf[2] |= (1 << 2); /* write cache enable */ 2247 buf[2] |= (1 << 2); /* write cache enable */
2224 if (!ata_id_rahead_enabled(id)) 2248 if (!changeable && !ata_id_rahead_enabled(id))
2225 buf[12] |= (1 << 5); /* disable read ahead */ 2249 buf[12] |= (1 << 5); /* disable read ahead */
2226 return sizeof(def_cache_mpage); 2250 return sizeof(def_cache_mpage);
2227} 2251}
@@ -2229,30 +2253,33 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf)
2229/** 2253/**
2230 * ata_msense_ctl_mode - Simulate MODE SENSE control mode page 2254 * ata_msense_ctl_mode - Simulate MODE SENSE control mode page
2231 * @buf: output buffer 2255 * @buf: output buffer
2256 * @changeable: whether changeable parameters are requested
2232 * 2257 *
2233 * Generate a generic MODE SENSE control mode page. 2258 * Generate a generic MODE SENSE control mode page.
2234 * 2259 *
2235 * LOCKING: 2260 * LOCKING:
2236 * None. 2261 * None.
2237 */ 2262 */
2238static unsigned int ata_msense_ctl_mode(u8 *buf) 2263static unsigned int ata_msense_ctl_mode(u8 *buf, bool changeable)
2239{ 2264{
2240 memcpy(buf, def_control_mpage, sizeof(def_control_mpage)); 2265 modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable);
2241 return sizeof(def_control_mpage); 2266 return sizeof(def_control_mpage);
2242} 2267}
2243 2268
2244/** 2269/**
2245 * ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page 2270 * ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
2246 * @buf: output buffer 2271 * @buf: output buffer
2272 * @changeable: whether changeable parameters are requested
2247 * 2273 *
2248 * Generate a generic MODE SENSE r/w error recovery page. 2274 * Generate a generic MODE SENSE r/w error recovery page.
2249 * 2275 *
2250 * LOCKING: 2276 * LOCKING:
2251 * None. 2277 * None.
2252 */ 2278 */
2253static unsigned int ata_msense_rw_recovery(u8 *buf) 2279static unsigned int ata_msense_rw_recovery(u8 *buf, bool changeable)
2254{ 2280{
2255 memcpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage)); 2281 modecpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage),
2282 changeable);
2256 return sizeof(def_rw_recovery_mpage); 2283 return sizeof(def_rw_recovery_mpage);
2257} 2284}
2258 2285
@@ -2316,11 +2343,11 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
2316 page_control = scsicmd[2] >> 6; 2343 page_control = scsicmd[2] >> 6;
2317 switch (page_control) { 2344 switch (page_control) {
2318 case 0: /* current */ 2345 case 0: /* current */
2346 case 1: /* changeable */
2347 case 2: /* defaults */
2319 break; /* supported */ 2348 break; /* supported */
2320 case 3: /* saved */ 2349 case 3: /* saved */
2321 goto saving_not_supp; 2350 goto saving_not_supp;
2322 case 1: /* changeable */
2323 case 2: /* defaults */
2324 default: 2351 default:
2325 goto invalid_fld; 2352 goto invalid_fld;
2326 } 2353 }
@@ -2341,21 +2368,21 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
2341 2368
2342 switch(pg) { 2369 switch(pg) {
2343 case RW_RECOVERY_MPAGE: 2370 case RW_RECOVERY_MPAGE:
2344 p += ata_msense_rw_recovery(p); 2371 p += ata_msense_rw_recovery(p, page_control == 1);
2345 break; 2372 break;
2346 2373
2347 case CACHE_MPAGE: 2374 case CACHE_MPAGE:
2348 p += ata_msense_caching(args->id, p); 2375 p += ata_msense_caching(args->id, p, page_control == 1);
2349 break; 2376 break;
2350 2377
2351 case CONTROL_MPAGE: 2378 case CONTROL_MPAGE:
2352 p += ata_msense_ctl_mode(p); 2379 p += ata_msense_ctl_mode(p, page_control == 1);
2353 break; 2380 break;
2354 2381
2355 case ALL_MPAGES: 2382 case ALL_MPAGES:
2356 p += ata_msense_rw_recovery(p); 2383 p += ata_msense_rw_recovery(p, page_control == 1);
2357 p += ata_msense_caching(args->id, p); 2384 p += ata_msense_caching(args->id, p, page_control == 1);
2358 p += ata_msense_ctl_mode(p); 2385 p += ata_msense_ctl_mode(p, page_control == 1);
2359 break; 2386 break;
2360 2387
2361 default: /* invalid page code */ 2388 default: /* invalid page code */