From: Douglas Gilbert <dougg@torque.net>
To: Jeff Garzik <jgarzik@pobox.com>
Cc: linux-scsi@vger.kernel.org
Subject: [PATCH] start stop libata attached SATA disks, take 2
Date: Sat, 06 Aug 2005 18:27:23 +1000 [thread overview]
Message-ID: <42F4746B.6030303@torque.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 2020 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Jeff,
Here is another (more successful) attempt at that patch.
ChangeLog:
- adds minimal START STOP UNIT SCSI command functionality
to libata (follows sat-r05 apart from the IMMED bit).
- implements the TEST UNIT READY SCSI command as indicated
by sat-r05.
Patch against lk 2.6.13-rc5 .
Tested on my ST380013AS Seagate SATA disk with a Sil 3112
HBA. Stop (spin down [enter standby power mode]) seems to
work as does start. Start takes 3.8 seconds to spin up
on my disk. TEST UNIT READY works returning GOOD status
(after 0 ms) when the disk is active or idle and the
"initializing command required" sense (after 180 ms)
when the disk is in standby power mode.
I looked a bit closer at the power condition states in
SBC-2 and I assume there is an equivalence with SATA
disks:
State Disk mechanics
- ----------------------------------
Active Spinning, heads on track
Idle Spinning, heads parked
Standby Spun down, " "
Stop Spun down, " "
The difference between "standby" and "stop" is that an
initializing command is required (i.e. START STOP UNIT
command, start=1) to transition out of "stop" state
(but not "standby"). As far as I can see ATA disks don't
have a "stop" state that can be accessed via the ATA
command set so the the SAT draft says to translate a
SCSI START STOP UNIT command, start=0 (i.e. stop) into
SATA disk being placed into standby mode. That is fine
but a SATA (and PATA) disk doesn't need an initializing
command to go into active state, any media access command
will do that. This is all fine, I just find it a little
curious what SAT is defining should happen for the TEST
UNIT READY translation.
Signed-off-by: Douglas Gilbert <dougg@torque.net>
Doug Gilbert
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
iD8DBQFC9HRqnayo+9E+FQIRAmWQAJ44Aq/qgo42MF/E6VHdREHVRxw7qwCfceGA
kklbxZFB/fMgFXQChvC3A7k=
=a/U2
-----END PGP SIGNATURE-----
[-- Attachment #2: libata2613rc5_stop.diff --]
[-- Type: text/x-patch, Size: 4503 bytes --]
--- linux/include/linux/ata.h 2005-07-30 10:22:08.000000000 +1000
+++ linux/include/linux/ata.h2613rc5standby 2005-08-06 14:36:03.000000000 +1000
@@ -108,6 +108,8 @@
/* ATA device commands */
ATA_CMD_CHK_POWER = 0xE5, /* check power mode */
+ ATA_CMD_STANDBY = 0xE2, /* place in standby power mode */
+ ATA_CMD_IDLE = 0xE3, /* place in idle power mode */
ATA_CMD_EDD = 0x90, /* execute device diagnostic */
ATA_CMD_FLUSH = 0xE7,
ATA_CMD_FLUSH_EXT = 0xEA,
--- linux/drivers/scsi/libata-scsi.c 2005-07-30 10:22:02.000000000 +1000
+++ linux/drivers/scsi/libata-scsi.c2613rc5stop 2005-08-06 17:39:34.000000000 +1000
@@ -391,6 +391,86 @@
}
/**
+ * 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
+ *
+ * Sets up an ATA taskfile to issue STANDBY (to stop) or READ VERIFY
+ * (to start). Perhaps these commands should be preceded by
+ * CHECK POWER MODE to see what power mode the device is already in.
+ * [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_start_stop_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;
+ if (scsicmd[1] & 0x1) {
+ ; /* ignore IMMED bit, violates sat-r05 */
+ }
+ if (scsicmd[4] & 0x2)
+ return 1; /* LOEJ bit set not supported */
+ if (((scsicmd[4] >> 4) & 0xf) != 0)
+ return 1; /* power conditions not supported */
+ if (scsicmd[4] & 0x1) {
+ tf->nsect = 1; /* 1 sector, lba=0 */
+ tf->lbah = 0x0;
+ tf->lbam = 0x0;
+ tf->lbal = 0x0;
+ tf->device |= ATA_LBA;
+ tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
+ } else {
+ tf->nsect = 0; /* time period value (0 implies now) */
+ tf->command = ATA_CMD_STANDBY;
+ /* Consider: ATA STANDBY IMMEDIATE command */
+ }
+ /*
+ * Standby and Idle condition timers could be implemented but that
+ * would require libata to implement the Power condition mode page
+ * and allow the user to change it. Changing mode pages requires
+ * MODE SELECT to be implemented.
+ */
+
+ return 0;
+}
+
+
+/**
* ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
* @qc: Storage for translated ATA taskfile
* @scsicmd: SCSI command to translate (ignored)
@@ -632,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);
@@ -1434,6 +1537,10 @@
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;
}
return NULL;
@@ -1544,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);
next reply other threads:[~2005-08-06 8:27 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-08-06 8:27 Douglas Gilbert [this message]
2005-08-11 4:01 ` [PATCH] start stop libata attached SATA disks, take 2 Jeff Garzik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=42F4746B.6030303@torque.net \
--to=dougg@torque.net \
--cc=jgarzik@pobox.com \
--cc=linux-scsi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.