提交 169439c2 编写于 作者: M Mark Lord 提交者: Jeff Garzik

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: NMark Lord <mlord@pobox.com>
Signed-off-by: NJeff Garzik <jeff@garzik.org>
上级 1e999736
...@@ -1649,13 +1649,13 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, ...@@ -1649,13 +1649,13 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
struct ata_taskfile tf; struct ata_taskfile tf;
unsigned int err_mask = 0; unsigned int err_mask = 0;
const char *reason; const char *reason;
int tried_spinup = 0;
int rc; int rc;
if (ata_msg_ctl(ap)) if (ata_msg_ctl(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__); ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
retry: retry:
ata_tf_init(dev, &tf); ata_tf_init(dev, &tf);
...@@ -1712,6 +1712,32 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, ...@@ -1712,6 +1712,32 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
goto err_out; goto err_out;
} }
if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) {
tried_spinup = 1;
/*
* Drive powered-up in standby mode, and requires a specific
* SET_FEATURES spin-up subcommand before it will accept
* anything other than the original IDENTIFY command.
*/
ata_tf_init(dev, &tf);
tf.command = ATA_CMD_SET_FEATURES;
tf.feature = SETFEATURES_SPINUP;
tf.protocol = ATA_PROT_NODATA;
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
if (err_mask) {
rc = -EIO;
reason = "SPINUP failed";
goto err_out;
}
/*
* If the drive initially returned incomplete IDENTIFY info,
* we now must reissue the IDENTIFY command.
*/
if (id[2] == 0x37c8)
goto retry;
}
if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) { if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) {
/* /*
* The exact sequence expected by certain pre-ATA4 drives is: * The exact sequence expected by certain pre-ATA4 drives is:
......
...@@ -202,6 +202,8 @@ enum { ...@@ -202,6 +202,8 @@ enum {
SETFEATURES_WC_ON = 0x02, /* Enable write cache */ SETFEATURES_WC_ON = 0x02, /* Enable write cache */
SETFEATURES_WC_OFF = 0x82, /* Disable write cache */ SETFEATURES_WC_OFF = 0x82, /* Disable write cache */
SETFEATURES_SPINUP = 0x07, /* Spin-up drive */
/* ATAPI stuff */ /* ATAPI stuff */
ATAPI_PKT_DMA = (1 << 0), ATAPI_PKT_DMA = (1 << 0),
ATAPI_DMADIR = (1 << 2), /* ATAPI data dir: ATAPI_DMADIR = (1 << 2), /* ATAPI data dir:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册