diff options
-rw-r--r-- | drivers/scsi/libata-scsi.c | 56 | ||||
-rw-r--r-- | include/linux/ata.h | 2 |
2 files changed, 58 insertions, 0 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 6a75ec2187fd..f58311b8c050 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -392,6 +392,60 @@ int ata_scsi_error(struct Scsi_Host *host) | |||
392 | } | 392 | } |
393 | 393 | ||
394 | /** | 394 | /** |
395 | * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command | ||
396 | * @qc: Storage for translated ATA taskfile | ||
397 | * @scsicmd: SCSI command to translate | ||
398 | * | ||
399 | * Sets up an ATA taskfile to issue STANDBY (to stop) or READ VERIFY | ||
400 | * (to start). Perhaps these commands should be preceded by | ||
401 | * CHECK POWER MODE to see what power mode the device is already in. | ||
402 | * [See SAT revision 5 at www.t10.org] | ||
403 | * | ||
404 | * LOCKING: | ||
405 | * spin_lock_irqsave(host_set lock) | ||
406 | * | ||
407 | * RETURNS: | ||
408 | * Zero on success, non-zero on error. | ||
409 | */ | ||
410 | |||
411 | static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc, | ||
412 | u8 *scsicmd) | ||
413 | { | ||
414 | struct ata_taskfile *tf = &qc->tf; | ||
415 | |||
416 | tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; | ||
417 | tf->protocol = ATA_PROT_NODATA; | ||
418 | if (scsicmd[1] & 0x1) { | ||
419 | ; /* ignore IMMED bit, violates sat-r05 */ | ||
420 | } | ||
421 | if (scsicmd[4] & 0x2) | ||
422 | return 1; /* LOEJ bit set not supported */ | ||
423 | if (((scsicmd[4] >> 4) & 0xf) != 0) | ||
424 | return 1; /* power conditions not supported */ | ||
425 | if (scsicmd[4] & 0x1) { | ||
426 | tf->nsect = 1; /* 1 sector, lba=0 */ | ||
427 | tf->lbah = 0x0; | ||
428 | tf->lbam = 0x0; | ||
429 | tf->lbal = 0x0; | ||
430 | tf->device |= ATA_LBA; | ||
431 | tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ | ||
432 | } else { | ||
433 | tf->nsect = 0; /* time period value (0 implies now) */ | ||
434 | tf->command = ATA_CMD_STANDBY; | ||
435 | /* Consider: ATA STANDBY IMMEDIATE command */ | ||
436 | } | ||
437 | /* | ||
438 | * Standby and Idle condition timers could be implemented but that | ||
439 | * would require libata to implement the Power condition mode page | ||
440 | * and allow the user to change it. Changing mode pages requires | ||
441 | * MODE SELECT to be implemented. | ||
442 | */ | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | |||
448 | /** | ||
395 | * ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command | 449 | * ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command |
396 | * @qc: Storage for translated ATA taskfile | 450 | * @qc: Storage for translated ATA taskfile |
397 | * @scsicmd: SCSI command to translate (ignored) | 451 | * @scsicmd: SCSI command to translate (ignored) |
@@ -1435,6 +1489,8 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) | |||
1435 | case VERIFY: | 1489 | case VERIFY: |
1436 | case VERIFY_16: | 1490 | case VERIFY_16: |
1437 | return ata_scsi_verify_xlat; | 1491 | return ata_scsi_verify_xlat; |
1492 | case START_STOP: | ||
1493 | return ata_scsi_start_stop_xlat; | ||
1438 | } | 1494 | } |
1439 | 1495 | ||
1440 | return NULL; | 1496 | return NULL; |
diff --git a/include/linux/ata.h b/include/linux/ata.h index ca5fcadf9981..9d25e9886d60 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h | |||
@@ -108,6 +108,8 @@ enum { | |||
108 | 108 | ||
109 | /* ATA device commands */ | 109 | /* ATA device commands */ |
110 | ATA_CMD_CHK_POWER = 0xE5, /* check power mode */ | 110 | ATA_CMD_CHK_POWER = 0xE5, /* check power mode */ |
111 | ATA_CMD_STANDBY = 0xE2, /* place in standby power mode */ | ||
112 | ATA_CMD_IDLE = 0xE3, /* place in idle power mode */ | ||
111 | ATA_CMD_EDD = 0x90, /* execute device diagnostic */ | 113 | ATA_CMD_EDD = 0x90, /* execute device diagnostic */ |
112 | ATA_CMD_FLUSH = 0xE7, | 114 | ATA_CMD_FLUSH = 0xE7, |
113 | ATA_CMD_FLUSH_EXT = 0xEA, | 115 | ATA_CMD_FLUSH_EXT = 0xEA, |