From ee2587bc3e508a784844dda64b0400dc7daa83a5 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Wed, 12 Oct 2005 15:09:42 +0800 Subject: [PATCH] --- yaml --- r: 9924 b: refs/heads/master c: 59a10b172fccaea793352c00fd9065f0a5b4ef70 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/scsi/libata-core.c | 65 +++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 95f937dbf8aa..d32a2a175053 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 8cbd6df1f0ce977ab7b61feffa59879bb5e0ed8f +refs/heads/master: 59a10b172fccaea793352c00fd9065f0a5b4ef70 diff --git a/trunk/drivers/scsi/libata-core.c b/trunk/drivers/scsi/libata-core.c index 19d3d717faf6..175d4646333d 100644 --- a/trunk/drivers/scsi/libata-core.c +++ b/trunk/drivers/scsi/libata-core.c @@ -63,6 +63,7 @@ static unsigned int ata_busy_sleep (struct ata_port *ap, unsigned long tmout_pat, unsigned long tmout); +static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev); static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); static void ata_set_mode(struct ata_port *ap); static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); @@ -1240,9 +1241,15 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) * anything else.. * Some drives were very specific about that exact sequence. */ - if (major_version < 4 || (!ata_id_has_lba(dev->id))) + if (major_version < 4 || (!ata_id_has_lba(dev->id))) { ata_dev_init_params(ap, dev); + /* 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; @@ -2150,6 +2157,62 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) DPRINTK("EXIT\n"); } +/** + * ata_dev_reread_id - Reread the device identify device info + * @ap: port where the device is + * @dev: device to reread the identify device info + * + * LOCKING: + */ + +static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev) +{ + DECLARE_COMPLETION(wait); + struct ata_queued_cmd *qc; + unsigned long flags; + int rc; + + qc = ata_qc_new_init(ap, dev); + BUG_ON(qc == NULL); + + ata_sg_init_one(qc, dev->id, sizeof(dev->id)); + qc->dma_dir = DMA_FROM_DEVICE; + + if (dev->class == ATA_DEV_ATA) { + qc->tf.command = ATA_CMD_ID_ATA; + DPRINTK("do ATA identify\n"); + } else { + qc->tf.command = ATA_CMD_ID_ATAPI; + DPRINTK("do ATAPI identify\n"); + } + + qc->tf.flags |= ATA_TFLAG_DEVICE; + qc->tf.protocol = ATA_PROT_PIO; + qc->nsect = 1; + + qc->waiting = &wait; + qc->complete_fn = ata_qc_complete_noop; + + spin_lock_irqsave(&ap->host_set->lock, flags); + rc = ata_qc_issue(qc); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + if (rc) + goto err_out; + + wait_for_completion(&wait); + + swap_buf_le16(dev->id, ATA_ID_WORDS); + + ata_dump_id(dev); + + DPRINTK("EXIT\n"); + + return; +err_out: + ata_port_disable(ap); +} + /** * ata_dev_init_params - Issue INIT DEV PARAMS command * @ap: Port associated with device @dev