mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Make the ATAPI sense data accessible when using the ioctl interface
MFC candidate.
This commit is contained in:
parent
3bbd6d8ae6
commit
cd8a592bb3
8 changed files with 107 additions and 93 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue