summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2004-02-28 17:47:27 +0000
committersos <sos@FreeBSD.org>2004-02-28 17:47:27 +0000
commit8b2299dc542c413a5aac77f13be6585d55b3cd37 (patch)
tree32dac47fc457ef35a1b075a574d0d026be4491b7
parentcfa84beb14b57fb04e0c99796c7b1ef9f4719274 (diff)
downloadFreeBSD-src-8b2299dc542c413a5aac77f13be6585d55b3cd37.zip
FreeBSD-src-8b2299dc542c413a5aac77f13be6585d55b3cd37.tar.gz
Issue a request sense command automagically when ATAPI commands fail
with a valid sense key.
-rw-r--r--sys/dev/ata/ata-all.h46
-rw-r--r--sys/dev/ata/ata-queue.c98
2 files changed, 86 insertions, 58 deletions
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index ff7d62f..9be401b 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -156,6 +156,28 @@
#define ATA_OP_CONTINUES 0
#define ATA_OP_FINISHED 1
+/* ATAPI request sense structure */
+struct atapi_sense {
+ u_int8_t error_code :7; /* current or deferred errors */
+ u_int8_t valid :1; /* follows ATAPI spec */
+ u_int8_t segment; /* Segment number */
+ u_int8_t sense_key :4; /* sense key */
+ u_int8_t reserved2_4 :1; /* reserved */
+ u_int8_t ili :1; /* incorrect length indicator */
+ u_int8_t eom :1; /* end of medium */
+ u_int8_t filemark :1; /* filemark */
+ u_int32_t cmd_info __packed; /* cmd information */
+ u_int8_t sense_length; /* additional sense len (n-7) */
+ u_int32_t cmd_specific_info __packed; /* additional cmd spec info */
+ u_int8_t asc; /* additional sense code */
+ u_int8_t ascq; /* additional sense code qual */
+ u_int8_t replaceable_unit_code; /* replaceable unit code */
+ u_int8_t sk_specific :7; /* sense key specific */
+ u_int8_t sksv :1; /* sense key specific info OK */
+ u_int8_t sk_specific1; /* sense key specific */
+ u_int8_t sk_specific2; /* sense key specific */
+};
+
struct ata_request {
struct ata_device *device; /* ptr to device softc */
void *driver; /* driver specific */
@@ -169,6 +191,8 @@ struct ata_request {
} ata;
struct {
u_int8_t ccb[16]; /* ATAPI command block */
+ u_int8_t sense_key; /* ATAPI request sense key */
+ struct atapi_sense sense_data; /* ATAPI request sense data */
} atapi;
} u;
@@ -333,28 +357,6 @@ struct ata_channel {
void *running; /* currently running request */
};
-/* ATAPI request sense structure */
-struct atapi_sense {
- u_int8_t error_code :7; /* current or deferred errors */
- u_int8_t valid :1; /* follows ATAPI spec */
- u_int8_t segment; /* Segment number */
- u_int8_t sense_key :4; /* sense key */
- u_int8_t reserved2_4 :1; /* reserved */
- u_int8_t ili :1; /* incorrect length indicator */
- u_int8_t eom :1; /* end of medium */
- u_int8_t filemark :1; /* filemark */
- u_int32_t cmd_info __packed; /* cmd information */
- u_int8_t sense_length; /* additional sense len (n-7) */
- u_int32_t cmd_specific_info __packed; /* additional cmd spec info */
- u_int8_t asc; /* additional sense code */
- u_int8_t ascq; /* additional sense code qual */
- u_int8_t replaceable_unit_code; /* replaceable unit code */
- u_int8_t sk_specific :7; /* sense key specific */
- u_int8_t sksv :1; /* sense key specific info OK */
- u_int8_t sk_specific1; /* sense key specific */
- u_int8_t sk_specific2; /* sense key specific */
-};
-
/* disk bay/enclosure related */
#define ATA_LED_OFF 0x00
#define ATA_LED_RED 0x01
diff --git a/sys/dev/ata/ata-queue.c b/sys/dev/ata/ata-queue.c
index 3a909a5..a243efc 100644
--- a/sys/dev/ata/ata-queue.c
+++ b/sys/dev/ata/ata-queue.c
@@ -131,15 +131,14 @@ ata_atapicmd(struct ata_device *atadev, u_int8_t *ccb, caddr_t data,
int count, int flags, int timeout)
{
struct ata_request *request = ata_alloc_request();
- int packet_size, error = ENOMEM;
+ int error = ENOMEM;
if (request) {
+ request->device = atadev;
if ((atadev->param->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12)
- packet_size = 12;
+ bcopy(ccb, request->u.atapi.ccb, 12);
else
- packet_size = 16;
- request->device = atadev;
- bcopy(ccb, request->u.atapi.ccb, packet_size);
+ bcopy(ccb, request->u.atapi.ccb, 16);
request->data = data;
request->bytecount = count;
request->transfersize = min(request->bytecount, 65534);
@@ -332,43 +331,70 @@ ata_completed(void *context, int dummy)
if (request->result)
break;
- if (request->error) {
- switch ((request->error & ATA_SK_MASK)) {
- case ATA_SK_RECOVERED_ERROR:
- ata_prtdev(request->device, "WARNING - %s recovered error\n",
- ata_cmd2str(request));
- /* FALLTHROUGH */
+ /* if we have a sensekey -> request sense from device */
+ if (request->error & ATA_SK_MASK &&
+ request->u.atapi.ccb[0] != ATAPI_REQUEST_SENSE) {
+ static u_int8_t ccb[16] = { ATAPI_REQUEST_SENSE, 0, 0, 0,
+ sizeof(struct atapi_sense),
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ bcopy(ccb, request->u.atapi.ccb, 16);
+ request->u.atapi.sense_key = request->error;
+ request->data = (caddr_t)&request->u.atapi.sense_data;
+ request->bytecount = sizeof(struct atapi_sense);
+ request->transfersize = sizeof(struct atapi_sense);
+ request->timeout = 5;
+ request->flags =
+ ATA_R_ATAPI | ATA_R_READ | ATA_R_IMMEDIATE | ATA_R_REQUEUE;
+ ata_queue_request(request);
+ return;
+ }
- case ATA_SK_NO_SENSE:
- request->result = 0;
- break;
+ switch (request->u.atapi.sense_key & ATA_SK_MASK) {
+ case ATA_SK_RECOVERED_ERROR:
+ ata_prtdev(request->device, "WARNING - %s recovered error\n",
+ ata_cmd2str(request));
+ /* FALLTHROUGH */
- case ATA_SK_NOT_READY:
- request->result = EBUSY;
- break;
+ case ATA_SK_NO_SENSE:
+ request->result = 0;
+ break;
- case ATA_SK_UNIT_ATTENTION:
- request->device->flags |= ATA_D_MEDIA_CHANGED;
- request->result = EIO;
+ case ATA_SK_NOT_READY:
+ request->result = EBUSY;
+ break;
+
+ case ATA_SK_UNIT_ATTENTION:
+ request->device->flags |= ATA_D_MEDIA_CHANGED;
+ request->result = EIO;
+ break;
+
+ default:
+ request->result = EIO;
+ if (request->flags & ATA_R_QUIET)
break;
- default:
- if (!(request->flags & ATA_R_QUIET))
- ata_prtdev(request->device,
- "FAILURE - %s status=%b sensekey=%s error=%b\n",
- ata_cmd2str(request),
- request->status, "\20\10BUSY\7READY\6DMA"
- "\5DSC\4DRQ\3CORRECTABLE\2INDEX\1ERROR",
- ata_skey2str((request->error & ATA_SK_MASK)>>4),
- (request->error & ATA_E_MASK),
- "\20\4MEDIA_CHANGE_REQUEST\3ABORTED"
- "\2NO_MEDIA\1ILLEGAL_LENGTH");
- request->result = EIO;
- }
- if (request->error & ATA_E_MASK)
- request->result = EIO;
+ ata_prtdev(request->device,
+ "FAILURE - %s %s asc=0x%02x ascq=0x%02x ",
+ ata_cmd2str(request), ata_skey2str(
+ (request->u.atapi.sense_key & ATA_SK_MASK) >> 4),
+ request->u.atapi.sense_data.asc,
+ request->u.atapi.sense_data.ascq);
+ if (request->u.atapi.sense_data.sksv)
+ printf("sks=0x%02x 0x%02x 0x%02x ",
+ request->u.atapi.sense_data.sk_specific,
+ request->u.atapi.sense_data.sk_specific1,
+ request->u.atapi.sense_data.sk_specific2);
+ printf("status=%b error=%b\n",
+ request->status, "\20\10BUSY\7READY\6DMA"
+ "\5DSC\4DRQ\3CORRECTABLE\2INDEX\1ERROR",
+ (request->error & ATA_E_MASK),
+ "\20\4MEDIA_CHANGE_REQUEST\3ABORTED"
+ "\2NO_MEDIA\1ILLEGAL_LENGTH");
}
- break;
+
+ if (request->error & ATA_E_MASK)
+ request->result = EIO;
}
ATA_DEBUG_RQ(request, "completed callback/wakeup");
OpenPOWER on IntegriCloud