|
@@ -10,6 +10,9 @@
|
|
|
|
|
|
#include <scsi/scsi.h>
|
|
#include <scsi/scsi.h>
|
|
|
|
|
|
|
|
+#define DRV_NAME "ide-atapi"
|
|
|
|
+#define PFX DRV_NAME ": "
|
|
|
|
+
|
|
#ifdef DEBUG
|
|
#ifdef DEBUG
|
|
#define debug_log(fmt, args...) \
|
|
#define debug_log(fmt, args...) \
|
|
printk(KERN_INFO "ide: " fmt, ## args)
|
|
printk(KERN_INFO "ide: " fmt, ## args)
|
|
@@ -197,8 +200,8 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
|
|
GFP_NOIO);
|
|
GFP_NOIO);
|
|
if (unlikely(err)) {
|
|
if (unlikely(err)) {
|
|
if (printk_ratelimit())
|
|
if (printk_ratelimit())
|
|
- printk(KERN_WARNING "%s: failed to map sense buffer\n",
|
|
|
|
- drive->name);
|
|
|
|
|
|
+ printk(KERN_WARNING PFX "%s: failed to map sense "
|
|
|
|
+ "buffer\n", drive->name);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -219,7 +222,7 @@ int ide_queue_sense_rq(ide_drive_t *drive, void *special)
|
|
{
|
|
{
|
|
/* deferred failure from ide_prep_sense() */
|
|
/* deferred failure from ide_prep_sense() */
|
|
if (!drive->sense_rq_armed) {
|
|
if (!drive->sense_rq_armed) {
|
|
- printk(KERN_WARNING "%s: failed queue sense request\n",
|
|
|
|
|
|
+ printk(KERN_WARNING PFX "%s: error queuing a sense request\n",
|
|
drive->name);
|
|
drive->name);
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
}
|
|
}
|
|
@@ -292,7 +295,7 @@ int ide_cd_expiry(ide_drive_t *drive)
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
if (!(rq->cmd_flags & REQ_QUIET))
|
|
if (!(rq->cmd_flags & REQ_QUIET))
|
|
- printk(KERN_INFO "cmd 0x%x timed out\n",
|
|
|
|
|
|
+ printk(KERN_INFO PFX "cmd 0x%x timed out\n",
|
|
rq->cmd[0]);
|
|
rq->cmd[0]);
|
|
wait = 0;
|
|
wait = 0;
|
|
break;
|
|
break;
|
|
@@ -325,6 +328,55 @@ void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
|
|
EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Check the contents of the interrupt reason register and attempt to recover if
|
|
|
|
+ * there are problems.
|
|
|
|
+ *
|
|
|
|
+ * Returns:
|
|
|
|
+ * - 0 if everything's ok
|
|
|
|
+ * - 1 if the request has to be terminated.
|
|
|
|
+ */
|
|
|
|
+int ide_check_ireason(ide_drive_t *drive, struct request *rq, int len,
|
|
|
|
+ int ireason, int rw)
|
|
|
|
+{
|
|
|
|
+ ide_hwif_t *hwif = drive->hwif;
|
|
|
|
+
|
|
|
|
+ debug_log("ireason: 0x%x, rw: 0x%x\n", ireason, rw);
|
|
|
|
+
|
|
|
|
+ if (ireason == (!rw << 1))
|
|
|
|
+ return 0;
|
|
|
|
+ else if (ireason == (rw << 1)) {
|
|
|
|
+ printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n",
|
|
|
|
+ drive->name, __func__);
|
|
|
|
+
|
|
|
|
+ if (dev_is_idecd(drive))
|
|
|
|
+ ide_pad_transfer(drive, rw, len);
|
|
|
|
+ } else if (!rw && ireason == ATAPI_COD) {
|
|
|
|
+ if (dev_is_idecd(drive)) {
|
|
|
|
+ /*
|
|
|
|
+ * Some drives (ASUS) seem to tell us that status info
|
|
|
|
+ * is available. Just get it and ignore.
|
|
|
|
+ */
|
|
|
|
+ (void)hwif->tp_ops->read_status(hwif);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if (ireason & ATAPI_COD)
|
|
|
|
+ printk(KERN_ERR PFX "%s: CoD != 0 in %s\n", drive->name,
|
|
|
|
+ __func__);
|
|
|
|
+
|
|
|
|
+ /* drive wants a command packet, or invalid ireason... */
|
|
|
|
+ printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n",
|
|
|
|
+ drive->name, __func__, ireason);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (dev_is_idecd(drive) && rq->cmd_type == REQ_TYPE_ATA_PC)
|
|
|
|
+ rq->cmd_flags |= REQ_FAILED;
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(ide_check_ireason);
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* This is the usual interrupt handler which will be called during a packet
|
|
* This is the usual interrupt handler which will be called during a packet
|
|
* command. We will transfer some of the data (as requested by the drive)
|
|
* command. We will transfer some of the data (as requested by the drive)
|
|
@@ -359,7 +411,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
|
|
|
|
|
|
if (rc || (drive->media == ide_tape && (stat & ATA_ERR))) {
|
|
if (rc || (drive->media == ide_tape && (stat & ATA_ERR))) {
|
|
if (drive->media == ide_floppy)
|
|
if (drive->media == ide_floppy)
|
|
- printk(KERN_ERR "%s: DMA %s error\n",
|
|
|
|
|
|
+ printk(KERN_ERR PFX "%s: DMA %s error\n",
|
|
drive->name, rq_data_dir(pc->rq)
|
|
drive->name, rq_data_dir(pc->rq)
|
|
? "write" : "read");
|
|
? "write" : "read");
|
|
pc->flags |= PC_FLAG_DMA_ERROR;
|
|
pc->flags |= PC_FLAG_DMA_ERROR;
|
|
@@ -391,8 +443,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
|
|
pc->rq->errors++;
|
|
pc->rq->errors++;
|
|
|
|
|
|
if (rq->cmd[0] == REQUEST_SENSE) {
|
|
if (rq->cmd[0] == REQUEST_SENSE) {
|
|
- printk(KERN_ERR "%s: I/O error in request sense"
|
|
|
|
- " command\n", drive->name);
|
|
|
|
|
|
+ printk(KERN_ERR PFX "%s: I/O error in request "
|
|
|
|
+ "sense command\n", drive->name);
|
|
return ide_do_reset(drive);
|
|
return ide_do_reset(drive);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -434,8 +486,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
|
|
|
|
|
|
if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
|
|
if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
|
|
pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
|
|
pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
|
|
- printk(KERN_ERR "%s: The device wants to issue more interrupts "
|
|
|
|
- "in DMA mode\n", drive->name);
|
|
|
|
|
|
+ printk(KERN_ERR PFX "%s: The device wants to issue more "
|
|
|
|
+ "interrupts in DMA mode\n", drive->name);
|
|
ide_dma_off(drive);
|
|
ide_dma_off(drive);
|
|
return ide_do_reset(drive);
|
|
return ide_do_reset(drive);
|
|
}
|
|
}
|
|
@@ -443,19 +495,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
|
|
/* Get the number of bytes to transfer on this interrupt. */
|
|
/* Get the number of bytes to transfer on this interrupt. */
|
|
ide_read_bcount_and_ireason(drive, &bcount, &ireason);
|
|
ide_read_bcount_and_ireason(drive, &bcount, &ireason);
|
|
|
|
|
|
- if (ireason & ATAPI_COD) {
|
|
|
|
- printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
|
|
|
|
|
|
+ if (ide_check_ireason(drive, rq, bcount, ireason, write))
|
|
return ide_do_reset(drive);
|
|
return ide_do_reset(drive);
|
|
- }
|
|
|
|
-
|
|
|
|
- if (((ireason & ATAPI_IO) == ATAPI_IO) == write) {
|
|
|
|
- /* Hopefully, we will never get here */
|
|
|
|
- printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
|
|
|
|
- "to %s!\n", drive->name,
|
|
|
|
- (ireason & ATAPI_IO) ? "Write" : "Read",
|
|
|
|
- (ireason & ATAPI_IO) ? "Read" : "Write");
|
|
|
|
- return ide_do_reset(drive);
|
|
|
|
- }
|
|
|
|
|
|
|
|
done = min_t(unsigned int, bcount, cmd->nleft);
|
|
done = min_t(unsigned int, bcount, cmd->nleft);
|
|
ide_pio_bytes(drive, cmd, write, done);
|
|
ide_pio_bytes(drive, cmd, write, done);
|
|
@@ -503,13 +544,13 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
|
|
|
|
|
|
while (retries-- && ((ireason & ATAPI_COD) == 0 ||
|
|
while (retries-- && ((ireason & ATAPI_COD) == 0 ||
|
|
(ireason & ATAPI_IO))) {
|
|
(ireason & ATAPI_IO))) {
|
|
- printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
|
|
|
|
|
|
+ printk(KERN_ERR PFX "%s: (IO,CoD != (0,1) while issuing "
|
|
"a packet command, retrying\n", drive->name);
|
|
"a packet command, retrying\n", drive->name);
|
|
udelay(100);
|
|
udelay(100);
|
|
ireason = ide_read_ireason(drive);
|
|
ireason = ide_read_ireason(drive);
|
|
if (retries == 0) {
|
|
if (retries == 0) {
|
|
- printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
|
|
|
|
- "a packet command, ignoring\n",
|
|
|
|
|
|
+ printk(KERN_ERR PFX "%s: (IO,CoD != (0,1) while issuing"
|
|
|
|
+ " a packet command, ignoring\n",
|
|
drive->name);
|
|
drive->name);
|
|
ireason |= ATAPI_COD;
|
|
ireason |= ATAPI_COD;
|
|
ireason &= ~ATAPI_IO;
|
|
ireason &= ~ATAPI_IO;
|
|
@@ -540,7 +581,7 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
|
|
u8 ireason;
|
|
u8 ireason;
|
|
|
|
|
|
if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) {
|
|
if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) {
|
|
- printk(KERN_ERR "%s: Strange, packet command initiated yet "
|
|
|
|
|
|
+ printk(KERN_ERR PFX "%s: Strange, packet command initiated yet "
|
|
"DRQ isn't asserted\n", drive->name);
|
|
"DRQ isn't asserted\n", drive->name);
|
|
return startstop;
|
|
return startstop;
|
|
}
|
|
}
|
|
@@ -582,8 +623,8 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
|
|
ireason = ide_wait_ireason(drive, ireason);
|
|
ireason = ide_wait_ireason(drive, ireason);
|
|
|
|
|
|
if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
|
|
if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
|
|
- printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
|
|
|
|
- "a packet command\n", drive->name);
|
|
|
|
|
|
+ printk(KERN_ERR PFX "%s: (IO,CoD) != (0,1) while "
|
|
|
|
+ "issuing a packet command\n", drive->name);
|
|
|
|
|
|
return ide_do_reset(drive);
|
|
return ide_do_reset(drive);
|
|
}
|
|
}
|