[PATCH] libata: separate out ata_dev_read_id()

Separate out ata_dev_read_id() from ata_dev_identify().  This is the
first half of splitting ata_dev_identify().  ata_dev_read_id() will
also be used for revalidation.  This patch does not make any behavior
change.

ata_dev_read_id() doesn't modify any of libata-internal data
structures.  It simply reads IDENTIFY page and returns error code on
failure.  INIT_DEV_PARAMS and EDD wrong class code are also handled by
this function.

Re-reading IDENTIFY after INIT_DEV_PARAMS is performed by jumping to
retry: instead of calling ata_dev_reread_id().  This is done because
1. there's retry label anyway 2. ata_dev_reread_id() cannot be used
anywhere else so there's no reason to keep it.

This function is probably the place to set transfer mode to PIO0
before IDENTIFY.  However, reset -> identify -> init_dev_params order
should be kept for pre-ATA4 devices so we cannot set transfer mode
before IDENTIFY for them.  How do we know if a device is post-ATA4
before IDENTIFY?

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
This commit is contained in:
Tejun Heo 2006-02-21 02:12:11 +09:00 committed by Jeff Garzik
parent f131883e73
commit 49016aca2e
1 changed files with 143 additions and 97 deletions

View File

@ -902,6 +902,145 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
return 0;
}
/**
* ata_dev_read_id - Read ID data from the specified device
* @ap: port on which target device resides
* @dev: target device
* @p_class: pointer to class of the target device (may be changed)
* @post_reset: is this read ID post-reset?
* @id: buffer to fill IDENTIFY page into
*
* Read ID data from the specified device. ATA_CMD_ID_ATA is
* performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI
* devices. This function also takes care of EDD signature
* misreporting (to be removed once EDD support is gone) and
* issues ATA_CMD_INIT_DEV_PARAMS for pre-ATA4 drives.
*
* LOCKING:
* Kernel thread context (may sleep)
*
* RETURNS:
* 0 on success, -errno otherwise.
*/
static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
unsigned int *p_class, int post_reset, u16 *id)
{
unsigned int class = *p_class;
unsigned int using_edd;
struct ata_taskfile tf;
unsigned int err_mask = 0;
const char *reason;
int rc;
DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno);
if (ap->ops->probe_reset ||
ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET))
using_edd = 0;
else
using_edd = 1;
ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
retry:
ata_tf_init(ap, &tf, dev->devno);
switch (class) {
case ATA_DEV_ATA:
tf.command = ATA_CMD_ID_ATA;
break;
case ATA_DEV_ATAPI:
tf.command = ATA_CMD_ID_ATAPI;
break;
default:
rc = -ENODEV;
reason = "unsupported class";
goto err_out;
}
tf.protocol = ATA_PROT_PIO;
err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
id, sizeof(id[0]) * ATA_ID_WORDS);
if (err_mask) {
rc = -EIO;
reason = "I/O error";
if (err_mask & ~AC_ERR_DEV)
goto err_out;
/*
* arg! EDD works for all test cases, but seems to return
* the ATA signature for some ATAPI devices. Until the
* reason for this is found and fixed, we fix up the mess
* here. If IDENTIFY DEVICE returns command aborted
* (as ATAPI devices do), then we issue an
* IDENTIFY PACKET DEVICE.
*
* ATA software reset (SRST, the default) does not appear
* to have this problem.
*/
if ((using_edd) && (class == ATA_DEV_ATA)) {
u8 err = tf.feature;
if (err & ATA_ABORTED) {
class = ATA_DEV_ATAPI;
goto retry;
}
}
goto err_out;
}
swap_buf_le16(id, ATA_ID_WORDS);
/* print device capabilities */
printk(KERN_DEBUG "ata%u: dev %u cfg "
"49:%04x 82:%04x 83:%04x 84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n",
ap->id, dev->devno,
id[49], id[82], id[83], id[84], id[85], id[86], id[87], id[88]);
/* sanity check */
if ((class == ATA_DEV_ATA) != ata_id_is_ata(id)) {
rc = -EINVAL;
reason = "device reports illegal type";
goto err_out;
}
if (post_reset && class == ATA_DEV_ATA) {
/*
* The exact sequence expected by certain pre-ATA4 drives is:
* SRST RESET
* IDENTIFY
* INITIALIZE DEVICE PARAMETERS
* anything else..
* Some drives were very specific about that exact sequence.
*/
if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
err_mask = ata_dev_init_params(ap, dev);
if (err_mask) {
rc = -EIO;
reason = "INIT_DEV_PARAMS failed";
goto err_out;
}
/* current CHS translation info (id[53-58]) might be
* changed. reread the identify device info.
*/
post_reset = 0;
goto retry;
}
}
*p_class = class;
return 0;
err_out:
printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n",
ap->id, dev->devno, reason);
kfree(id);
return rc;
}
/**
* ata_dev_identify - obtain IDENTIFY x DEVICE page
* @ap: port on which device we wish to probe resides
@ -927,11 +1066,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
static void ata_dev_identify(struct ata_port *ap, unsigned int device)
{
struct ata_device *dev = &ap->device[device];
unsigned int major_version;
unsigned long xfer_modes;
unsigned int using_edd;
struct ata_taskfile tf;
unsigned int err_mask;
int i, rc;
if (!ata_dev_present(dev)) {
@ -940,69 +1075,11 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
return;
}
if (ap->ops->probe_reset ||
ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET))
using_edd = 0;
else
using_edd = 1;
DPRINTK("ENTER, host %u, dev %u\n", ap->id, device);
WARN_ON(dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ATAPI &&
dev->class != ATA_DEV_NONE);
ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
retry:
ata_tf_init(ap, &tf, device);
if (dev->class == ATA_DEV_ATA) {
tf.command = ATA_CMD_ID_ATA;
DPRINTK("do ATA identify\n");
} else {
tf.command = ATA_CMD_ID_ATAPI;
DPRINTK("do ATAPI identify\n");
}
tf.protocol = ATA_PROT_PIO;
err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
dev->id, sizeof(dev->id));
if (err_mask) {
if (err_mask & ~AC_ERR_DEV)
goto err_out;
/*
* arg! EDD works for all test cases, but seems to return
* the ATA signature for some ATAPI devices. Until the
* reason for this is found and fixed, we fix up the mess
* here. If IDENTIFY DEVICE returns command aborted
* (as ATAPI devices do), then we issue an
* IDENTIFY PACKET DEVICE.
*
* ATA software reset (SRST, the default) does not appear
* to have this problem.
*/
if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
u8 err = tf.feature;
if (err & ATA_ABORTED) {
dev->class = ATA_DEV_ATAPI;
goto retry;
}
}
rc = ata_dev_read_id(ap, dev, &dev->class, 1, dev->id);
if (rc)
goto err_out;
}
swap_buf_le16(dev->id, ATA_ID_WORDS);
/* print device capabilities */
printk(KERN_DEBUG "ata%u: dev %u cfg "
"49:%04x 82:%04x 83:%04x 84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n",
ap->id, device, dev->id[49],
dev->id[82], dev->id[83], dev->id[84],
dev->id[85], dev->id[86], dev->id[87],
dev->id[88]);
/*
* common ATA, ATAPI feature tests
@ -1027,34 +1104,6 @@ retry:
if (dev->class == ATA_DEV_ATA) {
dev->n_sectors = ata_id_n_sectors(dev->id);
if (!ata_id_is_ata(dev->id)) /* sanity check */
goto err_out_nosup;
/* get major version */
major_version = ata_id_major_version(dev->id);
/*
* The exact sequence expected by certain pre-ATA4 drives is:
* SRST RESET
* IDENTIFY
* INITIALIZE DEVICE PARAMETERS
* anything else..
* Some drives were very specific about that exact sequence.
*/
if (major_version < 4 || (!ata_id_has_lba(dev->id))) {
err_mask = ata_dev_init_params(ap, dev);
if (err_mask) {
printk(KERN_ERR "ata%u: failed to init "
"parameters, disabled\n", ap->id);
goto err_out;
}
/* current CHS translation info (id[53-58]) might be
* changed. reread the identify device info.
*/
ata_dev_reread_id(ap, dev);
}
if (ata_id_has_lba(dev->id)) {
dev->flags |= ATA_DFLAG_LBA;
@ -1064,7 +1113,7 @@ retry:
/* print device info to dmesg */
printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n",
ap->id, device,
major_version,
ata_id_major_version(dev->id),
ata_mode_string(xfer_modes),
(unsigned long long)dev->n_sectors,
dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA");
@ -1086,7 +1135,7 @@ retry:
/* print device info to dmesg */
printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n",
ap->id, device,
major_version,
ata_id_major_version(dev->id),
ata_mode_string(xfer_modes),
(unsigned long long)dev->n_sectors,
(int)dev->cylinders, (int)dev->heads, (int)dev->sectors);
@ -1098,9 +1147,6 @@ retry:
/* ATAPI-specific feature tests */
else if (dev->class == ATA_DEV_ATAPI) {
if (ata_id_is_ata(dev->id)) /* sanity check */
goto err_out_nosup;
rc = atapi_cdb_len(dev->id);
if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id);