linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Douglas Gilbert <dougg@torque.net>
To: Alan Cox <alan@redhat.com>
Cc: jgarzik@pobox.com, linux-scsi@vger.kernel.org
Subject: Re: Prototype SATA -> SCSI error mapper
Date: Tue, 17 Aug 2004 19:33:18 +1000	[thread overview]
Message-ID: <4121D0DE.5070307@torque.net> (raw)
In-Reply-To: <20040816141243.GA3898@devserv.devel.redhat.com>

Alan,
With a MEDIUM or HARDWARE ERROR if you know the LBA of
the failure, then that value can be placed in the
(fixed format) sense buffer.

if (LBA_of_failure_known) {
     sb[0] |= 0x80;       /* set VALID bit */
     sb[3] = msb_of_LBA;  /* put LBA in INFORMATION field */
     sb[4] = umb_of_LBA;
     sb[5] = lmb_of_LBA;
     sb[6] = lsb_of_LBA;
}


The fixed format sense buffer cannot handle LBAs greater than
32 bits. This is one reason why "descriptor" format was
introduced. I'll send some patches soon to this list so
the mid-level can handle both descriptor formats.

Doug Gilbert


Alan Cox wrote:
> Would appreciate comment from any of the scsi gurus
> 
> 
> --- ../linux.vanilla-2.6.8-rc3/drivers/scsi/libata-scsi.c	2004-08-09 15:51:01.000000000 +0100
> +++ drivers/scsi/libata-scsi.c	2004-08-16 12:34:57.000000000 +0100
> @@ -120,34 +120,158 @@
>   *	ata_to_sense_error - convert ATA error to SCSI error
>   *	@qc: Command that we are erroring out
>   *
> - *	Converts an ATA error into a SCSI error.
> - *
> - *	Right now, this routine is laughably primitive.  We
> - *	don't even examine what ATA told us, we just look at
> - *	the command data direction, and return a fatal SCSI
> - *	sense error based on that.
> + *	Converts an ATA error into a SCSI error. While we are at it
> + *	we decode and dump the ATA error for the user so that they
> + *	have some idea what really happened at the non make-believe
> + *	layer.
>   *
>   *	LOCKING:
>   *	spin_lock_irqsave(host_set lock)
>   */
>  
> -void ata_to_sense_error(struct ata_queued_cmd *qc)
> +void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
>  {
>  	struct scsi_cmnd *cmd = qc->scsicmd;
> +	u8 err = 0;
> +	unsigned char *sb = cmd->sense_buffer;
> +	/* Based on the 3ware driver translation table */
> +	static unsigned char sense_table[][4] = {
> +		/* BBD|ECC|ID|MAR */
> +		{0xd1, 		ABORTED_COMMAND, 0x00, 0x00}, 	// Device busy                  Aborted command
> +		/* BBD|ECC|ID */
> +		{0xd0,  	ABORTED_COMMAND, 0x00, 0x00}, 	// Device busy                  Aborted command
> +		/* ECC|MC|MARK */
> +		{0x61, 		HARDWARE_ERROR, 0x00, 0x00}, 	// Device fault                 Hardware error
> +		/* ICRC|ABRT */		/* NB: ICRC & !ABRT is BBD */
> +		{0x84, 		ABORTED_COMMAND, 0x47, 0x00}, 	// Data CRC error               SCSI parity error
> +		/* MC|ID|ABRT|TRK0|MARK */
> +		{0x37, 		NOT_READY, 0x04, 0x00}, 	// Unit offline                 Not ready
> +		/* MCR|MARK */
> +		{0x09, 		NOT_READY, 0x04, 0x00}, 	// Unrecovered disk error       Not ready
> +		/*  Bad address mark */
> +		{0x01, 		MEDIUM_ERROR, 0x13, 0x00}, 	// Address mark not found       Address mark not found for data field
> +		/* TRK0 */
> +		{0x02, 		HARDWARE_ERROR, 0x00, 0x00}, 	// Track 0 not found		  Hardware error
> +		/* Abort & !ICRC */
> +		{0x04, 		ABORTED_COMMAND, 0x00, 0x00}, 	// Aborted command              Aborted command
> +		/* Media change request */
> +		{0x08, 		NOT_READY, 0x04, 0x00}, 	// Media change request	  FIXME: faking offline
> +		/* SRV */
> +		{0x10, 		ABORTED_COMMAND, 0x14, 0x00}, 	// ID not found                 Recorded entity not found
> +		/* Media change */
> +		{0x08,  	NOT_READY, 0x04, 0x00}, 	// Media change		  FIXME: faking offline
> +		/* ECC */
> +		{0x40, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Uncorrectable ECC error      Unrecovered read error
> +		/* BBD - block marked bad */
> +		{0x80, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Block marked bad		  Medium error, unrecovered read error
> +		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark 
> +	};
> +	static unsigned char stat_table[][4] = {
> +		/* Must be first because BUSY means no other bits valid */
> +		{0x80, 		ABORTED_COMMAND, 0x47, 0x00},	// Busy, fake parity for now
> +		{0x20, 		HARDWARE_ERROR,  0x00, 0x00}, 	// Device fault
> +		{0x08, 		ABORTED_COMMAND, 0x47, 0x00},	// Timed out in xfer, fake parity for now
> +		{0x04, 		RECOVERED_ERROR, 0x11, 0x00},	// Recovered ECC error	  Medium error, recovered
> +		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark 
> +	};
> +	int i = 0;
>  
>  	cmd->result = SAM_STAT_CHECK_CONDITION;
> -
> -	cmd->sense_buffer[0] = 0x70;
> -	cmd->sense_buffer[2] = MEDIUM_ERROR;
> -	cmd->sense_buffer[7] = 14 - 8;	/* addnl. sense len. FIXME: correct? */
> -
> +	
> +	/*
> +	 *	Is this an error we can process/parse
> +	 */
> +	 
> +	if(drv_stat & ATA_ERR)
> +		/* Read the err bits */
> +		err = ata_chk_err(qc->ap);
> +
> +	/* Display the ATA level error info */
> +	
> +	printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat);
> +	if(drv_stat & 0x80)
> +	{
> +		printk("Busy ");
> +		err = 0;	/* Data is not valid in this case */
> +	}
> +	else {
> +		if(drv_stat & 0x40)	printk("DriveReady ");
> +		if(drv_stat & 0x20)	printk("DeviceFault ");
> +		if(drv_stat & 0x10)	printk("SeekComplete ");
> +		if(drv_stat & 0x08)	printk("DataRequest ");
> +		if(drv_stat & 0x04)	printk("CorrectedError ");
> +		if(drv_stat & 0x02)	printk("Index ");
> +		if(drv_stat & 0x01)	printk("Error ");
> +	}
> +	printk("}\n");
> +	
> +	if(err)
> +	{
> +		printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err);
> +		if(err & 0x04)		printk("DriveStatusError ");
> +		if(err & 0x80)
> +		{
> +			if(err & 0x04)
> +				printk("BadCRC ");
> +			else
> +				printk("Sector ");
> +		}
> +		if(err & 0x40)		printk("UncorrectableError ");
> +		if(err & 0x10)		printk("SectorIdNotFound ");
> +		if(err & 0x02)		printk("TrackZeroNotFound ");
> +		if(err & 0x01)		printk("AddrMarkNotFound ");
> +		printk("}\n");
> +		
> +		/* Should we dump sector info here too ?? */
> +	}
> +		
> +	
> +	/* Look for err */
> +	while(sense_table[i][0] != 0xFF)
> +	{
> +		/* Look for best matches first */
> +		if((sense_table[i][0] & err) == sense_table[i][0])
> +		{
> +			sb[0] = 0x70;
> +			sb[2] = sense_table[i][1];
> +			sb[7] = 0x0a;
> +			sb[12] = sense_table[i][2];
> +			sb[13] = sense_table[i][3];
> +			return;
> +		}
> +		i++;
> +	}
> +	/* No immediate match */
> +	if(err)
> +		printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err);
> +	
> +	/* Fall back to interpreting status bits */
> +	while(stat_table[i][0] != 0xFF)
> +	{
> +		if(stat_table[i][0] & drv_stat)
> +		{
> +			sb[0] = 0x70;
> +			sb[2] = stat_table[i][1];
> +			sb[7] = 0x0a;
> +			sb[12] = stat_table[i][2];
> +			sb[13] = stat_table[i][3];
> +			return;
> +		}
> +		i++;
> +	}
> +	/* No error ?? */
> +	printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
>  	/* additional-sense-code[-qualifier] */
> +	
> +	sb[0] = 0x70;
> +	sb[2] = MEDIUM_ERROR;
> +	sb[7] = 0x0A;
>  	if (cmd->sc_data_direction == SCSI_DATA_READ) {
> -		cmd->sense_buffer[12] = 0x11; /* "unrecovered read error" */
> -		cmd->sense_buffer[13] = 0x04;
> +		sb[12] = 0x11; /* "unrecovered read error" */
> +		sb[13] = 0x04;
>  	} else {
> -		cmd->sense_buffer[12] = 0x0C; /* "write error -             */
> -		cmd->sense_buffer[13] = 0x02; /*  auto-reallocation failed" */
> +		sb[12] = 0x0C; /* "write error -             */
> +		sb[13] = 0x02; /*  auto-reallocation failed" */
>  	}
>  }
>  
> @@ -343,7 +467,7 @@
>  		if (is_atapi_taskfile(&qc->tf))
>  			cmd->result = SAM_STAT_CHECK_CONDITION;
>  		else
> -			ata_to_sense_error(qc);
> +			ata_to_sense_error(qc, drv_stat);
>  	} else {
>  		cmd->result = SAM_STAT_GOOD;
>  	}
> -
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


  reply	other threads:[~2004-08-17  9:34 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-08-16 14:12 Prototype SATA -> SCSI error mapper Alan Cox
2004-08-17  9:33 ` Douglas Gilbert [this message]
2004-08-17 11:57   ` Alan Cox
2004-08-18  5:56 ` Jeff Garzik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4121D0DE.5070307@torque.net \
    --to=dougg@torque.net \
    --cc=alan@redhat.com \
    --cc=jgarzik@pobox.com \
    --cc=linux-scsi@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).