In atapi_wdc.c, issue a 'REQUEST SENSE' command when appropriate.
Return XS_SENSE when the full sense info has been retrieved, or XS_SHORTSENSE if only the sense key was available (from the error register) Make atapi_interpret_sense() deal with this, and call scsipi_interpret_sense() for XS_SENSE. (XXX sd_interpret_sense() and the ioctl code needs to be made aware of XS_SHORTSENSE too ! sense hanlding for these is now less broken for devices that support 'REQUEST SENSE') All the ATAPI devices I have access to seems to honnor the SENSE_REQUEST command, but I suspect some ATAPI devices will not (althouh it's mandatory). The code should be able to deal with this, but is untested ...
This commit is contained in:
parent
00d93f776b
commit
0d0ff884e5
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: atapi_base.c,v 1.10 1998/10/12 16:09:23 bouyer Exp $ */
|
||||
/* $NetBSD: atapi_base.c,v 1.11 1998/11/17 14:45:39 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -67,7 +67,6 @@ atapi_interpret_sense(xs)
|
||||
struct scsipi_link *sc_link = xs->sc_link;
|
||||
char *msg = NULL;
|
||||
|
||||
key = (xs->sense.atapi_sense & 0xf0) >> 4;
|
||||
/*
|
||||
* If the device has it's own error handler, call it first.
|
||||
* If it returns a legit error value, return that, otherwise
|
||||
@ -80,7 +79,14 @@ atapi_interpret_sense(xs)
|
||||
if (error != SCSIRET_CONTINUE)
|
||||
return (error); /* error >= 0 better ? */
|
||||
}
|
||||
/* otherwise use the default */
|
||||
/*
|
||||
* otherwise use the default, call the generic sense handler if we have
|
||||
* more than the sense key
|
||||
*/
|
||||
if (xs->error == XS_SENSE)
|
||||
return (scsipi_interpret_sense(xs));
|
||||
|
||||
key = (xs->sense.atapi_sense & 0xf0) >> 4;
|
||||
switch (key) {
|
||||
case SKEY_RECOVERED_ERROR:
|
||||
msg = "soft error (corrected)";
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: atapi_wdc.c,v 1.7 1998/10/19 12:28:03 bouyer Exp $ */
|
||||
/* $NetBSD: atapi_wdc.c,v 1.8 1998/11/17 14:45:39 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Manuel Bouyer.
|
||||
@ -310,6 +310,10 @@ wdc_atapi_intr(chp, xfer)
|
||||
int len, phase, i, retries=0;
|
||||
int ire, dma_err = 0;
|
||||
int dma_flags = 0;
|
||||
struct scsipi_generic _cmd_reqsense;
|
||||
struct scsipi_sense *cmd_reqsense =
|
||||
(struct scsipi_sense *)&_cmd_reqsense;
|
||||
void *cmd;
|
||||
|
||||
WDCDEBUG_PRINT(("wdc_atapi_intr %s:%d:%d\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, drvp->drive), DEBUG_INTR);
|
||||
@ -332,13 +336,17 @@ wdc_atapi_intr(chp, xfer)
|
||||
wdc_atapi_reset(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
/* Error here only if the command is aborted */
|
||||
if ((chp->ch_status & WDCS_ERR) != 0 &&
|
||||
/*
|
||||
* if the request sense command was aborted, report the short sense
|
||||
* previously recorded, else continue normal processing
|
||||
*/
|
||||
|
||||
if ((xfer->c_flags & C_SENSE) != 0 &&
|
||||
(chp->ch_status & WDCS_ERR) != 0 &&
|
||||
(chp->ch_error & WDCE_ABRT) != 0) {
|
||||
sc_xfer->error = XS_SENSE;
|
||||
sc_xfer->sense.atapi_sense = chp->ch_error;
|
||||
WDCDEBUG_PRINT(("wdc_atapi_intr: wdc_atapi_done(), "
|
||||
"sense 0x%x\n", sc_xfer->sense.atapi_sense), DEBUG_INTR);
|
||||
WDCDEBUG_PRINT(("wdc_atapi_intr: request_sense aborted, "
|
||||
"calling wdc_atapi_done(), sense 0x%x\n",
|
||||
sc_xfer->sense.atapi_sense), DEBUG_INTR);
|
||||
wdc_atapi_done(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
@ -359,12 +367,20 @@ again:
|
||||
|
||||
switch (phase) {
|
||||
case PHASE_CMDOUT:
|
||||
if (xfer->c_flags & C_SENSE) {
|
||||
memset(cmd_reqsense, 0, sizeof(struct scsipi_generic));
|
||||
cmd_reqsense->opcode = REQUEST_SENSE;
|
||||
cmd_reqsense->length = xfer->c_bcount;
|
||||
cmd = cmd_reqsense;
|
||||
} else {
|
||||
cmd = sc_xfer->cmd;
|
||||
}
|
||||
WDCDEBUG_PRINT(("PHASE_CMDOUT\n"), DEBUG_INTR);
|
||||
/* Init the DMA channel if necessary */
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
if ((*chp->wdc->dma_init)(chp->wdc->dma_arg,
|
||||
chp->channel, xfer->drive,
|
||||
xfer->databuf, sc_xfer->datalen, dma_flags) != 0) {
|
||||
xfer->databuf, xfer->c_bcount, dma_flags) != 0) {
|
||||
sc_xfer->error = XS_DRIVER_STUFFUP;
|
||||
break;
|
||||
}
|
||||
@ -375,24 +391,24 @@ again:
|
||||
if (drvp->drive_flags & DRIVE_CAP32) {
|
||||
bus_space_write_multi_4(chp->data32iot,
|
||||
chp->data32ioh, 0,
|
||||
(u_int32_t *)sc_xfer->cmd,
|
||||
(u_int32_t *)cmd,
|
||||
sc_xfer->cmdlen >> 2);
|
||||
} else {
|
||||
bus_space_write_multi_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
(u_int16_t *)sc_xfer->cmd,
|
||||
(u_int16_t *)cmd,
|
||||
sc_xfer->cmdlen >> 1);
|
||||
}
|
||||
} else {
|
||||
if (drvp->drive_flags & DRIVE_CAP32) {
|
||||
bus_space_write_multi_stream_4(chp->data32iot,
|
||||
chp->data32ioh, 0,
|
||||
(u_int32_t *)sc_xfer->cmd,
|
||||
(u_int32_t *)cmd,
|
||||
sc_xfer->cmdlen >> 2);
|
||||
} else {
|
||||
bus_space_write_multi_stream_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
(u_int16_t *)sc_xfer->cmd,
|
||||
(u_int16_t *)cmd,
|
||||
sc_xfer->cmdlen >> 1);
|
||||
}
|
||||
}
|
||||
@ -478,7 +494,8 @@ again:
|
||||
case PHASE_DATAIN:
|
||||
/* Read data */
|
||||
WDCDEBUG_PRINT(("PHASE_DATAIN\n"), DEBUG_INTR);
|
||||
if ((sc_xfer->flags & SCSI_DATA_IN) == 0 ||
|
||||
if (((sc_xfer->flags & SCSI_DATA_IN) == 0 &&
|
||||
(xfer->c_flags & C_SENSE) == 0) ||
|
||||
(xfer->c_flags & C_DMA) != 0) {
|
||||
printf("wdc_atapi_intr: bad data phase DATAIN");
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
@ -547,12 +564,32 @@ again:
|
||||
chp->channel, xfer->drive, dma_flags);
|
||||
xfer->c_bcount -= sc_xfer->datalen;
|
||||
}
|
||||
|
||||
if (chp->ch_status & WDCS_ERR) {
|
||||
sc_xfer->error = XS_SENSE;
|
||||
sc_xfer->sense.atapi_sense = chp->ch_error;
|
||||
} else if (dma_err < 0) {
|
||||
sc_xfer->error = XS_DRIVER_STUFFUP;
|
||||
if (xfer->c_flags & C_SENSE) {
|
||||
if ((chp->ch_status & WDCS_ERR) || dma_err < 0) {
|
||||
/*
|
||||
* request sense failed ! it's not suppossed
|
||||
* to be possible
|
||||
*/
|
||||
sc_xfer->error = XS_DRIVER_STUFFUP;
|
||||
} else {
|
||||
/* use the sense we just read */
|
||||
sc_xfer->error = XS_SENSE;
|
||||
}
|
||||
} else {
|
||||
if (chp->ch_status & WDCS_ERR) {
|
||||
/* save the short sense */
|
||||
sc_xfer->error = XS_SHORTSENSE;
|
||||
sc_xfer->sense.atapi_sense = chp->ch_error;
|
||||
/* let the driver issue a 'request sense' */
|
||||
xfer->databuf = &sc_xfer->sense;
|
||||
xfer->c_bcount =
|
||||
sizeof(sc_xfer->sense.scsi_sense);
|
||||
xfer->c_flags |= C_SENSE;
|
||||
wdc_atapi_start(chp, xfer);
|
||||
return 1;
|
||||
} else if (dma_err < 0) {
|
||||
sc_xfer->error = XS_DRIVER_STUFFUP;
|
||||
}
|
||||
}
|
||||
if (xfer->c_bcount != 0) {
|
||||
WDCDEBUG_PRINT(("wdc_atapi_intr: bcount value is "
|
||||
@ -577,7 +614,7 @@ again:
|
||||
}
|
||||
printf("wdc_atapi_intr: unknown phase 0x%x\n", phase);
|
||||
if (chp->ch_status & WDCS_ERR) {
|
||||
sc_xfer->error = XS_SENSE;
|
||||
sc_xfer->error = XS_SHORTSENSE;
|
||||
sc_xfer->sense.atapi_sense = chp->ch_error;
|
||||
} else {
|
||||
sc_xfer->error = XS_DRIVER_STUFFUP;
|
||||
@ -676,7 +713,7 @@ error:
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
|
||||
errstring);
|
||||
printf("error (0x%x)\n", chp->ch_error);
|
||||
sc_xfer->error = XS_SENSE;
|
||||
sc_xfer->error = XS_SHORTSENSE;
|
||||
sc_xfer->sense.atapi_sense = chp->ch_error;
|
||||
wdc_atapi_reset(chp, xfer);
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user