Jeff, This patch is against lk 2.6.13-rc6 + SSU_for_libata (patch #2 that you requested). ChangeLog: - add TEST UNIT READY SCSI command implementation to libata, based on SAT draft revision 5 Signed-off-by: Douglas Gilbert <dougg@xxxxxxxxxx>
--- linux/drivers/scsi/libata-scsi.c 2005-08-11 15:41:47.000000000 +1000 +++ linux/drivers/scsi/libata-scsi.c2613rc6sstur 2005-08-06 17:53:08.000000000 +1000 @@ -391,6 +391,32 @@ } /** + * ata_scsi_tur_xlat - Translate SCSI TEST UNIT READY command + * @qc: Storage for translated ATA taskfile + * @scsicmd: SCSI command to translate (ignored) + * + * Sets up an ATA taskfile to issue CHECK POWER MODE. + * [See SAT revision 5 at www.t10.org] + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Zero on success, non-zero on error. + */ + +static unsigned int ata_scsi_tur_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) +{ + struct ata_taskfile *tf = &qc->tf; + + tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; + tf->protocol = ATA_PROT_NODATA; + tf->command = ATA_CMD_CHK_POWER; + + return 0; +} + +/** * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command * @qc: Storage for translated ATA taskfile * @scsicmd: SCSI command to translate @@ -686,7 +712,30 @@ if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) ata_to_sense_error(qc, drv_stat); - else + else if (cmd->cmnd[0] == TEST_UNIT_READY) { + unsigned char *sb = cmd->sense_buffer; + struct ata_taskfile resp_tf; + + memset(&resp_tf, 0, sizeof(resp_tf)); + qc->ap->ops->tf_read(qc->ap, &resp_tf); + /* result value in sector count field */ + if (resp_tf.nsect == 0) { + /* standby mode, respond as per sat-r05 */ + sb[0] = 0x70; + sb[2] = NOT_READY; + sb[7] = 0x0a; + sb[12] = 0x4; /* Logical unit not ready .. */ + sb[13] = 0x2; /* .. initializing command required */ + cmd->result = SAM_STAT_CHECK_CONDITION; + } else if (resp_tf.nsect == 0x80) { + /* idle mode */ + DPRINTK("CHECK POWER MODE reports idle\n"); + cmd->result = SAM_STAT_GOOD; + } else { + /* nsect should be 0xff implying active or idle */ + cmd->result = SAM_STAT_GOOD; + } + } else cmd->result = SAM_STAT_GOOD; qc->scsidone(cmd); @@ -1488,6 +1537,8 @@ case VERIFY: case VERIFY_16: return ata_scsi_verify_xlat; + case TEST_UNIT_READY: + return ata_scsi_tur_xlat; case START_STOP: return ata_scsi_start_stop_xlat; } @@ -1600,7 +1651,6 @@ case REZERO_UNIT: case SEEK_6: case SEEK_10: - case TEST_UNIT_READY: case FORMAT_UNIT: /* FIXME: correct? */ case SEND_DIAGNOSTIC: /* FIXME: correct? */ ata_scsi_rbuf_fill(&args, ata_scsiop_noop);