Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
d0ecdda0
Commit
d0ecdda0
authored
Aug 17, 2004
by
Alan Cox
Committed by
Jeff Garzik
Aug 17, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[libata] improve translation of ATA errors to SCSI sense codes
parent
19b4c542
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
142 additions
and
18 deletions
+142
-18
drivers/scsi/libata-scsi.c
drivers/scsi/libata-scsi.c
+141
-17
drivers/scsi/libata.h
drivers/scsi/libata.h
+1
-1
No files found.
drivers/scsi/libata-scsi.c
View file @
d0ecdda0
...
@@ -160,34 +160,158 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
...
@@ -160,34 +160,158 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
* ata_to_sense_error - convert ATA error to SCSI error
* ata_to_sense_error - convert ATA error to SCSI error
* @qc: Command that we are erroring out
* @qc: Command that we are erroring out
*
*
* Converts an ATA error into a SCSI error.
* 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
* Right now, this routine is laughably primitive. We
* have some idea what really happened at the non make-believe
* don't even examine what ATA told us, we just look at
* layer.
* the command data direction, and return a fatal SCSI
* sense error based on that.
*
*
* LOCKING:
* LOCKING:
* spin_lock_irqsave(host_set lock)
* 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
;
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
->
result
=
SAM_STAT_CHECK_CONDITION
;
cmd
->
sense_buffer
[
0
]
=
0x70
;
/*
cmd
->
sense_buffer
[
2
]
=
MEDIUM_ERROR
;
* Is this an error we can process/parse
cmd
->
sense_buffer
[
7
]
=
14
-
8
;
/* addnl. sense len. FIXME: correct? */
*/
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] */
/* additional-sense-code[-qualifier] */
sb
[
0
]
=
0x70
;
sb
[
2
]
=
MEDIUM_ERROR
;
sb
[
7
]
=
0x0A
;
if
(
cmd
->
sc_data_direction
==
SCSI_DATA_READ
)
{
if
(
cmd
->
sc_data_direction
==
SCSI_DATA_READ
)
{
cmd
->
sense_buffer
[
12
]
=
0x11
;
/* "unrecovered read error" */
sb
[
12
]
=
0x11
;
/* "unrecovered read error" */
cmd
->
sense_buffer
[
13
]
=
0x04
;
sb
[
13
]
=
0x04
;
}
else
{
}
else
{
cmd
->
sense_buffer
[
12
]
=
0x0C
;
/* "write error - */
sb
[
12
]
=
0x0C
;
/* "write error - */
cmd
->
sense_buffer
[
13
]
=
0x02
;
/* auto-reallocation failed" */
sb
[
13
]
=
0x02
;
/* auto-reallocation failed" */
}
}
}
}
...
@@ -500,7 +624,7 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
...
@@ -500,7 +624,7 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
struct
scsi_cmnd
*
cmd
=
qc
->
scsicmd
;
struct
scsi_cmnd
*
cmd
=
qc
->
scsicmd
;
if
(
unlikely
(
drv_stat
&
(
ATA_ERR
|
ATA_BUSY
|
ATA_DRQ
)))
if
(
unlikely
(
drv_stat
&
(
ATA_ERR
|
ATA_BUSY
|
ATA_DRQ
)))
ata_to_sense_error
(
qc
);
ata_to_sense_error
(
qc
,
drv_stat
);
else
else
cmd
->
result
=
SAM_STAT_GOOD
;
cmd
->
result
=
SAM_STAT_GOOD
;
...
...
drivers/scsi/libata.h
View file @
d0ecdda0
...
@@ -46,7 +46,7 @@ extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
...
@@ -46,7 +46,7 @@ extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
/* libata-scsi.c */
/* libata-scsi.c */
extern
void
ata_to_sense_error
(
struct
ata_queued_cmd
*
qc
);
extern
void
ata_to_sense_error
(
struct
ata_queued_cmd
*
qc
,
u8
drv_stat
);
extern
int
ata_scsi_error
(
struct
Scsi_Host
*
host
);
extern
int
ata_scsi_error
(
struct
Scsi_Host
*
host
);
extern
unsigned
int
ata_scsiop_inq_std
(
struct
ata_scsi_args
*
args
,
u8
*
rbuf
,
extern
unsigned
int
ata_scsiop_inq_std
(
struct
ata_scsi_args
*
args
,
u8
*
rbuf
,
unsigned
int
buflen
);
unsigned
int
buflen
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment