forked from luck/tmp_suning_uos_patched
[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:
parent
f131883e73
commit
49016aca2e
@ -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 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
|
||||
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 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
|
||||
/* 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 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
|
||||
/* 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 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
|
||||
|
||||
/* 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);
|
||||
|
Loading…
Reference in New Issue
Block a user