Archived
14
0
Fork 0

[PATCH] libata: improve SCSI sense data generation

Update ata_gen_ata_sense() to use desc format sense data to report the
first failed block.  The first failed block is read from result_tf
using ata_tf_read_block() which can handle all three address formats.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
Tejun Heo 2006-11-14 22:37:35 +09:00 committed by Jeff Garzik
parent 35b649fe25
commit d25614bad6

View file

@ -746,53 +746,53 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
* ata_gen_ata_sense - generate a SCSI fixed sense block * ata_gen_ata_sense - generate a SCSI fixed sense block
* @qc: Command that we are erroring out * @qc: Command that we are erroring out
* *
* Leverage ata_to_sense_error() to give us the codes. Fit our * Generate sense block for a failed ATA command @qc. Descriptor
* LBA in here if there's room. * format is used to accomodate LBA48 block address.
* *
* LOCKING: * LOCKING:
* None. * None.
*/ */
static void ata_gen_ata_sense(struct ata_queued_cmd *qc) static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
{ {
struct ata_device *dev = qc->dev;
struct scsi_cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
struct ata_taskfile *tf = &qc->result_tf; struct ata_taskfile *tf = &qc->result_tf;
unsigned char *sb = cmd->sense_buffer; unsigned char *sb = cmd->sense_buffer;
unsigned char *desc = sb + 8;
int verbose = qc->ap->ops->error_handler == NULL; int verbose = qc->ap->ops->error_handler == NULL;
u64 block;
memset(sb, 0, SCSI_SENSE_BUFFERSIZE); memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
/* /* sense data is current and format is descriptor */
* Use ata_to_sense_error() to map status register bits sb[0] = 0x72;
/* Use ata_to_sense_error() to map status register bits
* onto sense key, asc & ascq. * onto sense key, asc & ascq.
*/ */
if (qc->err_mask || if (qc->err_mask ||
tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
ata_to_sense_error(qc->ap->id, tf->command, tf->feature, ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
&sb[2], &sb[12], &sb[13], verbose); &sb[1], &sb[2], &sb[3], verbose);
sb[2] &= 0x0f; sb[1] &= 0x0f;
} }
sb[0] = 0x70; block = ata_tf_read_block(&qc->result_tf, dev);
sb[7] = 0x0a;
if (tf->flags & ATA_TFLAG_LBA48) { /* information sense data descriptor */
/* TODO: find solution for LBA48 descriptors */ sb[7] = 12;
} desc[0] = 0x00;
desc[1] = 10;
else if (tf->flags & ATA_TFLAG_LBA) { desc[2] |= 0x80; /* valid */
/* A small (28b) LBA will fit in the 32b info field */ desc[6] = block >> 40;
sb[0] |= 0x80; /* set valid bit */ desc[7] = block >> 32;
sb[3] = tf->device & 0x0f; desc[8] = block >> 24;
sb[4] = tf->lbah; desc[9] = block >> 16;
sb[5] = tf->lbam; desc[10] = block >> 8;
sb[6] = tf->lbal; desc[11] = block;
}
else {
/* TODO: C/H/S */
}
} }
static void ata_scsi_sdev_config(struct scsi_device *sdev) static void ata_scsi_sdev_config(struct scsi_device *sdev)