[ide] cleanup ide_error()

* move idedisk_error() and ide_cdrom_error() to ide-io.c
* rename idedisk_error() to ide_ata_error()
* rename ide_cdrom_error() to ide_atapi_error()
* use ide_{ata,atapi}_error() in ide_error()
Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent 49336484
......@@ -559,46 +559,6 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
(void) ide_do_drive_cmd(drive, rq, ide_preempt);
}
/*
* ide_error() takes action based on the error returned by the drive.
*/
static ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat)
{
struct request *rq;
byte err;
err = ide_dump_status(drive, msg, stat);
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
}
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
} else {
/* add decoding error stuff */
}
if (HWIF(drive)->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
/* force an abort */
HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
if (rq->errors >= ERROR_MAX) {
DRIVER(drive)->end_request(drive, 0, 0);
} else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
return ide_do_reset(drive);
}
++rq->errors;
}
return ide_stopped;
}
static ide_startstop_t ide_cdrom_abort (ide_drive_t *drive, const char *msg)
{
struct request *rq;
......@@ -3370,7 +3330,6 @@ static ide_driver_t ide_cdrom_driver = {
.supports_dsc_overlap = 1,
.cleanup = ide_cdrom_cleanup,
.do_request = ide_do_rw_cdrom,
.error = ide_cdrom_error,
.abort = ide_cdrom_abort,
.capacity = ide_cdrom_capacity,
.attach = ide_cdrom_attach,
......
......@@ -287,66 +287,6 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s
return __ide_do_rw_disk(drive, rq, block);
}
static ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, u8 stat)
{
ide_hwif_t *hwif;
struct request *rq;
u8 err;
err = ide_dump_status(drive, msg, stat);
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
hwif = HWIF(drive);
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
}
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
} else if (stat & ERR_STAT) {
/* err has different meaning on cdrom and tape */
if (err == ABRT_ERR) {
if (drive->select.b.lba &&
/* some newer drives don't support WIN_SPECIFY */
hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)
return ide_stopped;
} else if ((err & BAD_CRC) == BAD_CRC) {
/* UDMA crc error, just retry the operation */
drive->crc_count++;
} else if (err & (BBD_ERR | ECC_ERR)) {
/* retries won't help these */
rq->errors = ERROR_MAX;
} else if (err & TRK0_ERR) {
/* help it find track zero */
rq->errors |= ERROR_RECAL;
}
}
if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ)
try_to_flush_leftover_data(drive);
if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) {
/* force an abort */
hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
}
if (rq->errors >= ERROR_MAX || blk_noretry_request(rq))
DRIVER(drive)->end_request(drive, 0, 0);
else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
return ide_do_reset(drive);
}
if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
drive->special.b.recalibrate = 1;
++rq->errors;
}
return ide_stopped;
}
static ide_startstop_t idedisk_abort(ide_drive_t *drive, const char *msg)
{
ide_hwif_t *hwif;
......@@ -1255,7 +1195,6 @@ static ide_driver_t idedisk_driver = {
.supports_dsc_overlap = 0,
.cleanup = idedisk_cleanup,
.do_request = ide_do_rw_disk,
.error = idedisk_error,
.abort = idedisk_abort,
.pre_reset = idedisk_pre_reset,
.capacity = idedisk_capacity,
......
......@@ -454,9 +454,80 @@ void try_to_flush_leftover_data (ide_drive_t *drive)
EXPORT_SYMBOL(try_to_flush_leftover_data);
/*
* FIXME Add an ATAPI error
*/
static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
ide_hwif_t *hwif = drive->hwif;
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
} else if (stat & ERR_STAT) {
/* err has different meaning on cdrom and tape */
if (err == ABRT_ERR) {
if (drive->select.b.lba &&
/* some newer drives don't support WIN_SPECIFY */
hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)
return ide_stopped;
} else if ((err & BAD_CRC) == BAD_CRC) {
/* UDMA crc error, just retry the operation */
drive->crc_count++;
} else if (err & (BBD_ERR | ECC_ERR)) {
/* retries won't help these */
rq->errors = ERROR_MAX;
} else if (err & TRK0_ERR) {
/* help it find track zero */
rq->errors |= ERROR_RECAL;
}
}
if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ)
try_to_flush_leftover_data(drive);
if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
/* force an abort */
hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
if (rq->errors >= ERROR_MAX || blk_noretry_request(rq))
drive->driver->end_request(drive, 0, 0);
else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
return ide_do_reset(drive);
}
if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
drive->special.b.recalibrate = 1;
++rq->errors;
}
return ide_stopped;
}
static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
ide_hwif_t *hwif = drive->hwif;
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
} else {
/* add decoding error stuff */
}
if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
/* force an abort */
hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
if (rq->errors >= ERROR_MAX) {
drive->driver->end_request(drive, 0, 0);
} else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
return ide_do_reset(drive);
}
++rq->errors;
}
return ide_stopped;
}
/**
* ide_error - handle an error on the IDE
......@@ -473,74 +544,24 @@ EXPORT_SYMBOL(try_to_flush_leftover_data);
ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
{
ide_hwif_t *hwif;
struct request *rq;
u8 err;
err = ide_dump_status(drive, msg, stat);
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
hwif = HWIF(drive);
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
}
if (rq->flags & REQ_DRIVE_TASKFILE) {
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
}
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
} else {
if (drive->media != ide_disk)
goto media_out;
if (stat & ERR_STAT) {
/* err has different meaning on cdrom and tape */
if (err == ABRT_ERR) {
if (drive->select.b.lba &&
(hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY))
/* some newer drives don't
* support WIN_SPECIFY
*/
return ide_stopped;
} else if ((err & BAD_CRC) == BAD_CRC) {
drive->crc_count++;
/* UDMA crc error -- just retry the operation */
} else if (err & (BBD_ERR | ECC_ERR)) {
/* retries won't help these */
rq->errors = ERROR_MAX;
} else if (err & TRK0_ERR) {
/* help it find track zero */
rq->errors |= ERROR_RECAL;
}
}
media_out:
if ((stat & DRQ_STAT) && rq_data_dir(rq) != WRITE)
try_to_flush_leftover_data(drive);
}
if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) {
/* force an abort */
hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
}
if (rq->errors >= ERROR_MAX) {
DRIVER(drive)->end_request(drive, 0, 0);
} else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
return ide_do_reset(drive);
}
if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
drive->special.b.recalibrate = 1;
++rq->errors;
}
return ide_stopped;
if (drive->media == ide_disk)
return ide_ata_error(drive, rq, stat, err);
return ide_atapi_error(drive, rq, stat, err);
}
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment