#include <scsi/scsi.h>
+#define DRV_NAME "ide-atapi"
+#define PFX DRV_NAME ": "
+
#ifdef DEBUG
#define debug_log(fmt, args...) \
printk(KERN_INFO "ide: " fmt, ## args)
GFP_NOIO);
if (unlikely(err)) {
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;
}
{
/* deferred failure from ide_prep_sense() */
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);
return -ENOMEM;
}
break;
default:
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]);
wait = 0;
break;
}
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
* command. We will transfer some of the data (as requested by the drive)
if (rc || (drive->media == ide_tape && (stat & ATA_ERR))) {
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)
? "write" : "read");
pc->flags |= PC_FLAG_DMA_ERROR;
pc->rq->errors++;
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);
}
if (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);
return ide_do_reset(drive);
}
/* Get the number of bytes to transfer on this interrupt. */
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);
- }
-
- 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);
ide_pio_bytes(drive, cmd, write, done);
while (retries-- && ((ireason & ATAPI_COD) == 0 ||
(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);
udelay(100);
ireason = ide_read_ireason(drive);
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);
ireason |= ATAPI_COD;
ireason &= ~ATAPI_IO;
u8 ireason;
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);
return startstop;
}
ireason = ide_wait_ireason(drive, ireason);
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);
}