+/*
+ * 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);
+