diff options
author | sos <sos@FreeBSD.org> | 2004-02-28 17:47:27 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 2004-02-28 17:47:27 +0000 |
commit | 8b2299dc542c413a5aac77f13be6585d55b3cd37 (patch) | |
tree | 32dac47fc457ef35a1b075a574d0d026be4491b7 | |
parent | cfa84beb14b57fb04e0c99796c7b1ef9f4719274 (diff) | |
download | FreeBSD-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.h | 46 | ||||
-rw-r--r-- | sys/dev/ata/ata-queue.c | 98 |
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"); |