diff options
author | Mark Lord <liml@rtr.ca> | 2007-04-17 18:26:07 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-04-28 14:40:40 -0400 |
commit | 169439c2e35f01e7832a9b4fc8a7446980c3d593 (patch) | |
tree | 83cbc6898be74b2bfb49bd4eaa966913c49de9da /drivers/ata | |
parent | 1e999736cafdffc374f22eed37b291129ef82e4e (diff) |
libata: Handle drives that require a spin-up command before first access
(S)ATA drives can be configured for "power-up in standby",
a mode whereby a specific "spin up now!" command is required
before the first media access.
Currently, a drive with this feature enabled can not be used at all
with libata, and once in this mode, the drive becomes a doorstop.
The older drivers/ide subsystem at least enumerates the drive,
so that it can be woken up after the fact from a userspace HDIO_*
command, but not libata.
This patch adds support to libata for the "power-up in standby"
mode where a "spin up now!" command (SET_FEATURES) is needed.
With this, libata will recognize such drives, spin them up,
and then re-IDENTIFY them if necessary to get a full/complete
set of drive features data.
Drives in this state are determined by looking for
special values in id[2], as documented in the current ATA specs.
Signed-off-by: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-core.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 6d0a946afe84..227399e48470 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -1649,13 +1649,13 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, | |||
1649 | struct ata_taskfile tf; | 1649 | struct ata_taskfile tf; |
1650 | unsigned int err_mask = 0; | 1650 | unsigned int err_mask = 0; |
1651 | const char *reason; | 1651 | const char *reason; |
1652 | int tried_spinup = 0; | ||
1652 | int rc; | 1653 | int rc; |
1653 | 1654 | ||
1654 | if (ata_msg_ctl(ap)) | 1655 | if (ata_msg_ctl(ap)) |
1655 | ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__); | 1656 | ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__); |
1656 | 1657 | ||
1657 | ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ | 1658 | ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ |
1658 | |||
1659 | retry: | 1659 | retry: |
1660 | ata_tf_init(dev, &tf); | 1660 | ata_tf_init(dev, &tf); |
1661 | 1661 | ||
@@ -1712,6 +1712,32 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, | |||
1712 | goto err_out; | 1712 | goto err_out; |
1713 | } | 1713 | } |
1714 | 1714 | ||
1715 | if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) { | ||
1716 | tried_spinup = 1; | ||
1717 | /* | ||
1718 | * Drive powered-up in standby mode, and requires a specific | ||
1719 | * SET_FEATURES spin-up subcommand before it will accept | ||
1720 | * anything other than the original IDENTIFY command. | ||
1721 | */ | ||
1722 | ata_tf_init(dev, &tf); | ||
1723 | tf.command = ATA_CMD_SET_FEATURES; | ||
1724 | tf.feature = SETFEATURES_SPINUP; | ||
1725 | tf.protocol = ATA_PROT_NODATA; | ||
1726 | tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; | ||
1727 | err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); | ||
1728 | if (err_mask) { | ||
1729 | rc = -EIO; | ||
1730 | reason = "SPINUP failed"; | ||
1731 | goto err_out; | ||
1732 | } | ||
1733 | /* | ||
1734 | * If the drive initially returned incomplete IDENTIFY info, | ||
1735 | * we now must reissue the IDENTIFY command. | ||
1736 | */ | ||
1737 | if (id[2] == 0x37c8) | ||
1738 | goto retry; | ||
1739 | } | ||
1740 | |||
1715 | if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) { | 1741 | if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) { |
1716 | /* | 1742 | /* |
1717 | * The exact sequence expected by certain pre-ATA4 drives is: | 1743 | * The exact sequence expected by certain pre-ATA4 drives is: |