From 69fb696b657ca9767e91ff4ad17e2aad0822b1d7 Mon Sep 17 00:00:00 2001 From: sos Date: Fri, 31 Mar 2006 08:09:05 +0000 Subject: Make the ATAPI sense data accessible when using the ioctl interface MFC candidate. --- sys/dev/ata/ata-all.c | 6 ++++- sys/dev/ata/ata-all.h | 49 ++++---------------------------------- sys/dev/ata/ata-disk.c | 13 +++++++--- sys/dev/ata/ata-queue.c | 63 ++++++++++++++++++++++++++----------------------- sys/dev/ata/ata-usb.c | 6 +---- sys/dev/ata/atapi-cam.c | 4 ++-- sys/dev/ata/atapi-cd.c | 16 ++++++------- sys/sys/ata.h | 43 +++++++++++++++++++++++++++++++++ 8 files changed, 107 insertions(+), 93 deletions(-) diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 3b64060..b68cbe9 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -485,7 +485,11 @@ ata_device_ioctl(device_t dev, u_long cmd, caddr_t data) if (ioc_request->flags & ATA_CMD_WRITE) request->flags |= ATA_R_WRITE; ata_queue_request(request); - if (!(request->flags & ATA_R_ATAPI)) { + if (request->flags & ATA_R_ATAPI) { + bcopy(&request->u.atapi.sense, &ioc_request->u.atapi.sense, + sizeof(struct atapi_sense)); + } + else { ioc_request->u.ata.command = request->u.ata.command; ioc_request->u.ata.feature = request->u.ata.feature; ioc_request->u.ata.lba = request->u.ata.lba; diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 2bd3e37..8f98589 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -53,24 +53,7 @@ #define ATA_E_MC 0x20 /* media changed */ #define ATA_E_UNC 0x40 /* uncorrectable data */ #define ATA_E_ICRC 0x80 /* UDMA crc error */ -#define ATA_E_MASK 0x0f /* error mask */ -#define ATA_SK_MASK 0xf0 /* sense key mask */ -#define ATA_SK_NO_SENSE 0x00 /* no specific sense key info */ -#define ATA_SK_RECOVERED_ERROR 0x10 /* command OK, data recovered */ -#define ATA_SK_NOT_READY 0x20 /* no access to drive */ -#define ATA_SK_MEDIUM_ERROR 0x30 /* non-recovered data error */ -#define ATA_SK_HARDWARE_ERROR 0x40 /* non-recoverable HW failure */ -#define ATA_SK_ILLEGAL_REQUEST 0x50 /* invalid command param(s) */ -#define ATA_SK_UNIT_ATTENTION 0x60 /* media changed */ -#define ATA_SK_DATA_PROTECT 0x70 /* write protect */ -#define ATA_SK_BLANK_CHECK 0x80 /* blank check */ -#define ATA_SK_VENDOR_SPECIFIC 0x90 /* vendor specific skey */ -#define ATA_SK_COPY_ABORTED 0xa0 /* copy aborted */ -#define ATA_SK_ABORTED_COMMAND 0xb0 /* command aborted, try again */ -#define ATA_SK_EQUAL 0xc0 /* equal */ -#define ATA_SK_VOLUME_OVERFLOW 0xd0 /* volume overflow */ -#define ATA_SK_MISCOMPARE 0xe0 /* data dont match the medium */ -#define ATA_SK_RESERVED 0xf0 +#define ATA_E_ATAPI_SENSE_MASK 0xf0 /* ATAPI sense key mask */ #define ATA_IREASON 9 /* (R) interrupt reason */ #define ATA_I_CMD 0x01 /* cmd (1) | data (0) */ @@ -284,7 +267,8 @@ #define ATA_PC98_BANKADDR_RID 9 #define ATA_IRQ_RID 0 #define ATA_DEV(device) ((device == ATA_MASTER) ? 0 : 1) -#define ATA_CFA_MAGIC 0x848A +#define ATA_CFA_MAGIC1 0x844A +#define ATA_CFA_MAGIC2 0x848A #define ATAPI_MAGIC_LSB 0x14 #define ATAPI_MAGIC_MSB 0xeb #define ATAPI_P_READ (ATA_S_DRQ | ATA_I_IN) @@ -298,28 +282,6 @@ #define ATA_OP_FINISHED 1 #define ATA_MAX_28BIT_LBA 268435455UL -/* 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 */ -}; - /* structure used for composite atomic operations */ #define MAX_COMPOSITES 32 /* u_int32_t bits */ struct ata_composite { @@ -348,9 +310,8 @@ struct ata_request { } ata; struct { u_int8_t ccb[16]; /* ATAPI command block */ - struct atapi_sense sense_data; /* ATAPI request sense data */ - u_int8_t sense_key; /* ATAPI request sense key */ - u_int8_t sense_cmd; /* ATAPI saved command */ + struct atapi_sense sense; /* ATAPI request sense data */ + u_int8_t saved_cmd; /* ATAPI saved command */ } atapi; } u; u_int32_t bytecount; /* bytes to transfer */ diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index fb8942e..6d90b40 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -71,7 +71,8 @@ ad_probe(device_t dev) struct ata_device *atadev = device_get_softc(dev); if (!(atadev->param.config & ATA_PROTO_ATAPI) || - (atadev->param.config == ATA_CFA_MAGIC)) + (atadev->param.config == ATA_CFA_MAGIC1) || + (atadev->param.config == ATA_CFA_MAGIC2)) return 0; else return ENXIO; @@ -295,8 +296,14 @@ ad_dump(void *arg, void *virtual, vm_offset_t physical, struct bio bp; /* length zero is special and really means flush buffers to media */ - if (!length) - return ata_controlcmd(dp->d_drv1, ATA_FLUSHCACHE, 0, 0, 0); + if (!length) { + struct ata_device *atadev = device_get_softc(dp->d_drv1); + int error = 0; + + if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE) + error = ata_controlcmd(dp->d_drv1, ATA_FLUSHCACHE, 0, 0, 0); + return error; + } bzero(&bp, sizeof(struct bio)); bp.bio_disk = dp; diff --git a/sys/dev/ata/ata-queue.c b/sys/dev/ata/ata-queue.c index a3b142e..4957eac 100644 --- a/sys/dev/ata/ata-queue.c +++ b/sys/dev/ata/ata-queue.c @@ -51,13 +51,20 @@ static char *ata_skey2str(u_int8_t); void ata_queue_request(struct ata_request *request) { - struct ata_channel *ch = device_get_softc(device_get_parent(request->dev)); + struct ata_channel *ch; - /* mark request as virgin (this might be a ATA_R_REQUEUE) */ + /* treat request as virgin (this might be an ATA_R_REQUEUE) */ request->result = request->status = request->error = 0; - request->parent = device_get_parent(request->dev); - callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED); + /* check that that the device is still valid */ + if (!(request->parent = device_get_parent(request->dev))) { + request->result = ENXIO; + if (request->callback) + (request->callback)(request); + return; + } + ch = device_get_softc(request->parent); + callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED); if (!request->callback && !(request->flags & ATA_R_REQUEUE)) sema_init(&request->done, 0, "ATA request done"); @@ -368,16 +375,15 @@ ata_completed(void *context, int dummy) break; /* if we have a sensekey -> request sense from device */ - if (request->error & ATA_SK_MASK && - request->u.atapi.ccb[0] != ATAPI_REQUEST_SENSE) { + if ((request->error & ATA_E_ATAPI_SENSE_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 }; - request->u.atapi.sense_key = request->error; - request->u.atapi.sense_cmd = request->u.atapi.ccb[0]; + request->u.atapi.saved_cmd = request->u.atapi.ccb[0]; bcopy(ccb, request->u.atapi.ccb, 16); - request->data = (caddr_t)&request->u.atapi.sense_data; + request->data = (caddr_t)&request->u.atapi.sense; request->bytecount = sizeof(struct atapi_sense); request->donecount = 0; request->transfersize = sizeof(struct atapi_sense); @@ -389,21 +395,21 @@ ata_completed(void *context, int dummy) return; } - switch (request->u.atapi.sense_key & ATA_SK_MASK) { - case ATA_SK_RECOVERED_ERROR: + switch (request->u.atapi.sense.key & ATA_SENSE_KEY_MASK) { + case ATA_SENSE_RECOVERED_ERROR: device_printf(request->dev, "WARNING - %s recovered error\n", ata_cmd2str(request)); /* FALLTHROUGH */ - case ATA_SK_NO_SENSE: + case ATA_SENSE_NO_SENSE: request->result = 0; break; - case ATA_SK_NOT_READY: + case ATA_SENSE_NOT_READY: request->result = EBUSY; break; - case ATA_SK_UNIT_ATTENTION: + case ATA_SENSE_UNIT_ATTENTION: atadev->flags |= ATA_D_MEDIA_CHANGED; request->result = EIO; break; @@ -416,22 +422,19 @@ ata_completed(void *context, int dummy) device_printf(request->dev, "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("error=%b\n", - (request->u.atapi.sense_key & ATA_E_MASK), - "\20\4MEDIA_CHANGE_REQUEST\3ABORTED" - "\2NO_MEDIA\1ILLEGAL_LENGTH"); + (request->u.atapi.sense.key & ATA_SENSE_KEY_MASK)), + request->u.atapi.sense.asc, + request->u.atapi.sense.ascq); + if (request->u.atapi.sense.specific & ATA_SENSE_SPEC_VALID) + printf("sks=0x%02x 0x%02x 0x%02x\n", + request->u.atapi.sense.specific & ATA_SENSE_SPEC_MASK, + request->u.atapi.sense.specific1, + request->u.atapi.sense.specific2); } - if ((request->u.atapi.sense_key ? - request->u.atapi.sense_key : request->error) & ATA_E_MASK) + if ((request->u.atapi.sense.key & ATA_SENSE_KEY_MASK ? + request->u.atapi.sense.key & ATA_SENSE_KEY_MASK : + request->error)) request->result = EIO; } @@ -625,8 +628,8 @@ ata_cmd2str(struct ata_request *request) static char buffer[20]; if (request->flags & ATA_R_ATAPI) { - switch (request->u.atapi.sense_key ? - request->u.atapi.sense_cmd : request->u.atapi.ccb[0]) { + switch (request->u.atapi.sense.key ? + request->u.atapi.saved_cmd : request->u.atapi.ccb[0]) { case 0x00: return ("TEST_UNIT_READY"); case 0x01: return ("REZERO"); case 0x03: return ("REQUEST_SENSE"); diff --git a/sys/dev/ata/ata-usb.c b/sys/dev/ata/ata-usb.c index 9f181ef..19d0196 100644 --- a/sys/dev/ata/ata-usb.c +++ b/sys/dev/ata/ata-usb.c @@ -683,8 +683,7 @@ atausb_bbb_finish(usbd_xfer_handle xfer, usbd_private_handle priv, else if (sc->csw.status == CSWSTATUS_FAILED) { if (atausbdebug) device_printf(sc->dev, "CSWSTATUS_FAILED\n"); - //request->result = ENODEV; - request->error = ATA_SK_RESERVED; + request->error = ATA_E_ATAPI_SENSE_MASK ; sc->state = ATAUSB_S_IDLE; ata_interrupt(device_get_softc(request->parent)); return; @@ -824,9 +823,6 @@ ata_usbchannel_end_transaction(struct ata_request *request) *ptr = ntohs(*ptr); request->result = 0; } - if ((request->flags & ATA_R_ATAPI) && - (request->u.atapi.ccb[0] == ATAPI_REQUEST_SENSE)) - request->u.atapi.sense_key = request->u.atapi.sense_data.sense_key << 4; return ATA_OP_FINISHED; } diff --git a/sys/dev/ata/atapi-cam.c b/sys/dev/ata/atapi-cam.c index 386de14..8a24638 100644 --- a/sys/dev/ata/atapi-cam.c +++ b/sys/dev/ata/atapi-cam.c @@ -661,7 +661,7 @@ atapi_cb(struct ata_request *request) csio = &hcb->ccb->csio; #ifdef CAMDEBUG -# define err (request->u.atapi.sense_key) +# define err (request->u.atapi.sense.key) if (CAM_DEBUGGED(csio->ccb_h.path, CAM_DEBUG_CDB)) { printf("atapi_cb: hcb@%p error = %02x: (sk = %02x%s%s%s)\n", hcb, err, err >> 4, @@ -704,7 +704,7 @@ atapi_cb(struct ata_request *request) /* The ATA driver has already requested sense for us. */ if (request->error == 0) { /* The ATA autosense suceeded. */ - bcopy (&request->u.atapi.sense_data, &csio->sense_data, sizeof(struct atapi_sense)); + bcopy (&request->u.atapi.sense, &csio->sense_data, sizeof(struct atapi_sense)); csio->ccb_h.status |= CAM_AUTOSNS_VALID; } #endif diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index cf7d159..bdfa167 100644 --- a/sys/dev/ata/atapi-cd.c +++ b/sys/dev/ata/atapi-cd.c @@ -702,10 +702,10 @@ acd_geom_access(struct g_provider *pp, int dr, int dw, int de) request->timeout = 5; ata_queue_request(request); if (!request->error && - (request->u.atapi.sense_data.sense_key == 2 || - request->u.atapi.sense_data.sense_key == 7) && - request->u.atapi.sense_data.asc == 4 && - request->u.atapi.sense_data.ascq == 1) + (request->u.atapi.sense.key == 2 || + request->u.atapi.sense.key == 7) && + request->u.atapi.sense.asc == 4 && + request->u.atapi.sense.ascq == 1) tsleep(&timeout, PRIBIO, "acdld", hz / 2); else break; @@ -1008,7 +1008,7 @@ acd_read_toc(device_t dev) cdp->disk_size, cdp->block_size, cdp->toc.hdr.ending_track-cdp->toc.hdr.starting_track+1); if (cdp->toc.tab[0].control & 4) - printf("%dMB\n", cdp->disk_size / 512); + printf("%dMB\n", cdp->disk_size * cdp->block_size / 1048576); else printf("%d:%d audio\n", cdp->disk_size / 75 / 60, cdp->disk_size / 75 % 60); @@ -1234,9 +1234,9 @@ acd_get_progress(device_t dev, int *finished) request->flags = ATA_R_ATAPI | ATA_R_READ; request->timeout = 30; ata_queue_request(request); - if (!request->error && request->u.atapi.sense_data.sksv) - *finished = ((request->u.atapi.sense_data.sk_specific2 | - (request->u.atapi.sense_data.sk_specific1<<8))*100)/65535; + if (!request->error && request->u.atapi.sense.error & ATA_SENSE_VALID) + *finished = ((request->u.atapi.sense.specific2 | + (request->u.atapi.sense.specific1 << 8)) * 100) / 65535; else *finished = 0; ata_free_request(request); diff --git a/sys/sys/ata.h b/sys/sys/ata.h index 36a6d35..36f2558 100644 --- a/sys/sys/ata.h +++ b/sys/sys/ata.h @@ -349,6 +349,48 @@ struct ata_ioc_devices { #define IOCATADETACH _IOW('a', 4, int) #define IOCATADEVICES _IOWR('a', 5, struct ata_ioc_devices) +/* ATAPI request sense structure */ +struct atapi_sense { + u_int8_t error; /* current or deferred errors */ +#define ATA_SENSE_VALID 0x80 + + u_int8_t segment; /* segment number */ + u_int8_t key; /* sense key */ +#define ATA_SENSE_KEY_MASK 0x0f /* sense key mask */ +#define ATA_SENSE_NO_SENSE 0x00 /* no specific sense key info */ +#define ATA_SENSE_RECOVERED_ERROR 0x01 /* command OK, data recovered */ +#define ATA_SENSE_NOT_READY 0x02 /* no access to drive */ +#define ATA_SENSE_MEDIUM_ERROR 0x03 /* non-recovered data error */ +#define ATA_SENSE_HARDWARE_ERROR 0x04 /* non-recoverable HW failure */ +#define ATA_SENSE_ILLEGAL_REQUEST 0x05 /* invalid command param(s) */ +#define ATA_SENSE_UNIT_ATTENTION 0x06 /* media changed */ +#define ATA_SENSE_DATA_PROTECT 0x07 /* write protect */ +#define ATA_SENSE_BLANK_CHECK 0x08 /* blank check */ +#define ATA_SENSE_VENDOR_SPECIFIC 0x09 /* vendor specific skey */ +#define ATA_SENSE_COPY_ABORTED 0x0a /* copy aborted */ +#define ATA_SENSE_ABORTED_COMMAND 0x0b /* command aborted, try again */ +#define ATA_SENSE_EQUAL 0x0c /* equal */ +#define ATA_SENSE_VOLUME_OVERFLOW 0x0d /* volume overflow */ +#define ATA_SENSE_MISCOMPARE 0x0e /* data dont match the medium */ +#define ATA_SENSE_RESERVED 0x0f +#define ATA_SENSE_ILI 0x20; +#define ATA_SENSE_EOM 0x40; +#define ATA_SENSE_FILEMARK 0x80; + + u_int32_t cmd_info; /* cmd information */ + u_int8_t sense_length; /* additional sense len (n-7) */ + u_int32_t cmd_specific_info; /* 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 specific; /* sense key specific */ +#define ATA_SENSE_SPEC_VALID 0x80 +#define ATA_SENSE_SPEC_MASK 0x7f + + u_int8_t specific1; /* sense key specific */ + u_int8_t specific2; /* sense key specific */ +} __packed; + struct ata_ioc_request { union { struct { @@ -359,6 +401,7 @@ struct ata_ioc_request { } ata; struct { char ccb[16]; + struct atapi_sense sense; } atapi; } u; caddr_t data; -- cgit v1.1