ide: add ide_read_error() inline helper
[deliverable/linux.git] / drivers / ide / ide-lib.c
index 562f5efae9c6226d51dd60c9636a171d554f33f7..1ff676cc6473f56dd9a5cc00b7f31d57c4899e4d 100644 (file)
@@ -358,8 +358,10 @@ void ide_toggle_bounce(ide_drive_t *drive, int on)
        if (!PCI_DMA_BUS_IS_PHYS) {
                addr = BLK_BOUNCE_ANY;
        } else if (on && drive->media == ide_disk) {
-               if (HWIF(drive)->pci_dev)
-                       addr = HWIF(drive)->pci_dev->dma_mask;
+               struct device *dev = drive->hwif->dev;
+
+               if (dev && dev->dma_mask)
+                       addr = *dev->dma_mask;
        }
 
        if (drive->queue)
@@ -441,6 +443,12 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
         * case could happen iff the transfer mode has already been set on
         * the device by ide-proc.c::set_xfer_rate()).
         */
+       if (rate < XFER_PIO_0) {
+               if (hwif->host_flags & IDE_HFLAG_ABUSE_SET_DMA_MODE)
+                       return ide_set_dma_mode(drive, rate);
+               else
+                       return ide_config_drive_speed(drive, rate);
+       }
 
        return ide_set_dma_mode(drive, rate);
 }
@@ -448,8 +456,7 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
 static void ide_dump_opcode(ide_drive_t *drive)
 {
        struct request *rq;
-       u8 opcode = 0;
-       int found = 0;
+       ide_task_t *task = NULL;
 
        spin_lock(&ide_lock);
        rq = NULL;
@@ -458,108 +465,100 @@ static void ide_dump_opcode(ide_drive_t *drive)
        spin_unlock(&ide_lock);
        if (!rq)
                return;
-       if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
-               char *args = rq->buffer;
-               if (args) {
-                       opcode = args[0];
-                       found = 1;
-               }
-       } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
-               ide_task_t *args = rq->special;
-               if (args) {
-                       opcode = args->tf.command;
-                       found = 1;
-               }
-       }
+
+       if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
+               task = rq->special;
 
        printk("ide: failed opcode was: ");
-       if (!found)
-               printk("unknown\n");
+       if (task == NULL)
+               printk(KERN_CONT "unknown\n");
        else
-               printk("0x%02x\n", opcode);
+               printk(KERN_CONT "0x%02x\n", task->tf.command);
 }
 
-static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
+u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-       unsigned long flags;
-       u8 err = 0;
+       u32 high, low;
 
-       local_irq_save(flags);
-       printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
-       if (stat & BUSY_STAT)
-               printk("Busy ");
-       else {
-               if (stat & READY_STAT)  printk("DriveReady ");
-               if (stat & WRERR_STAT)  printk("DeviceFault ");
-               if (stat & SEEK_STAT)   printk("SeekComplete ");
-               if (stat & DRQ_STAT)    printk("DataRequest ");
-               if (stat & ECC_STAT)    printk("CorrectedError ");
-               if (stat & INDEX_STAT)  printk("Index ");
-               if (stat & ERR_STAT)    printk("Error ");
+       if (lba48)
+               high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) |
+                       tf->hob_lbal;
+       else
+               high = tf->device & 0xf;
+       low  = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal;
+
+       return ((u64)high << 24) | low;
+}
+EXPORT_SYMBOL_GPL(ide_get_lba_addr);
+
+static void ide_dump_sector(ide_drive_t *drive)
+{
+       ide_task_t task;
+       struct ide_taskfile *tf = &task.tf;
+       int lba48 = (drive->addressing == 1) ? 1 : 0;
+
+       memset(&task, 0, sizeof(task));
+       if (lba48)
+               task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA |
+                               IDE_TFLAG_LBA48;
+       else
+               task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
+
+       ide_tf_read(drive, &task);
+
+       if (lba48 || (tf->device & ATA_LBA))
+               printk(", LBAsect=%llu",
+                       (unsigned long long)ide_get_lba_addr(tf, lba48));
+       else
+               printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
+                                        tf->device & 0xf, tf->lbal);
+}
+
+static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
+{
+       printk("{ ");
+       if (err & ABRT_ERR)     printk("DriveStatusError ");
+       if (err & ICRC_ERR)
+               printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
+       if (err & ECC_ERR)      printk("UncorrectableError ");
+       if (err & ID_ERR)       printk("SectorIdNotFound ");
+       if (err & TRK0_ERR)     printk("TrackZeroNotFound ");
+       if (err & MARK_ERR)     printk("AddrMarkNotFound ");
+       printk("}");
+       if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
+           (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
+               ide_dump_sector(drive);
+               if (HWGROUP(drive) && HWGROUP(drive)->rq)
+                       printk(", sector=%llu",
+                              (unsigned long long)HWGROUP(drive)->rq->sector);
        }
+       printk("\n");
+}
+
+static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
+{
+       printk("{ ");
+       if (err & ILI_ERR)      printk("IllegalLengthIndication ");
+       if (err & EOM_ERR)      printk("EndOfMedia ");
+       if (err & ABRT_ERR)     printk("AbortedCommand ");
+       if (err & MCR_ERR)      printk("MediaChangeRequested ");
+       if (err & LFS_ERR)      printk("LastFailedSense=0x%02x ",
+                                      (err & LFS_ERR) >> 4);
        printk("}\n");
-       if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
-               err = hwif->INB(IDE_ERROR_REG);
-               printk("%s: %s: error=0x%02x { ", drive->name, msg, err);
-               if (err & ABRT_ERR)     printk("DriveStatusError ");
-               if (err & ICRC_ERR)
-                       printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
-               if (err & ECC_ERR)      printk("UncorrectableError ");
-               if (err & ID_ERR)       printk("SectorIdNotFound ");
-               if (err & TRK0_ERR)     printk("TrackZeroNotFound ");
-               if (err & MARK_ERR)     printk("AddrMarkNotFound ");
-               printk("}");
-               if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
-                   (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
-                       if (drive->addressing == 1) {
-                               __u64 sectors = 0;
-                               u32 low = 0, high = 0;
-                               hwif->OUTB(drive->ctl&~0x80, IDE_CONTROL_REG);
-                               low = ide_read_24(drive);
-                               hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
-                               high = ide_read_24(drive);
-                               sectors = ((__u64)high << 24) | low;
-                               printk(", LBAsect=%llu, high=%d, low=%d",
-                                      (unsigned long long) sectors,
-                                      high, low);
-                       } else {
-                               u8 cur = hwif->INB(IDE_SELECT_REG);
-                               if (cur & 0x40) {       /* using LBA? */
-                                       printk(", LBAsect=%ld", (unsigned long)
-                                        ((cur&0xf)<<24)
-                                        |(hwif->INB(IDE_HCYL_REG)<<16)
-                                        |(hwif->INB(IDE_LCYL_REG)<<8)
-                                        | hwif->INB(IDE_SECTOR_REG));
-                               } else {
-                                       printk(", CHS=%d/%d/%d",
-                                        (hwif->INB(IDE_HCYL_REG)<<8) +
-                                         hwif->INB(IDE_LCYL_REG),
-                                         cur & 0xf,
-                                         hwif->INB(IDE_SECTOR_REG));
-                               }
-                       }
-                       if (HWGROUP(drive) && HWGROUP(drive)->rq)
-                               printk(", sector=%llu",
-                                       (unsigned long long)HWGROUP(drive)->rq->sector);
-               }
-               printk("\n");
-       }
-       ide_dump_opcode(drive);
-       local_irq_restore(flags);
-       return err;
 }
 
 /**
- *     ide_dump_atapi_status       -       print human readable atapi status
+ *     ide_dump_status         -       translate ATA/ATAPI error
  *     @drive: drive that status applies to
  *     @msg: text message to print
  *     @stat: status byte to decode
  *
  *     Error reporting, in human readable form (luxurious, but a memory hog).
+ *     Combines the drive name, message and status byte to provide a
+ *     user understandable explanation of the device error.
  */
 
-static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat)
+u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
 {
        unsigned long flags;
        u8 err = 0;
@@ -579,37 +578,16 @@ static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat)
        }
        printk("}\n");
        if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
-               err = drive->hwif->INB(IDE_ERROR_REG);
-               printk("%s: %s: error=0x%02x { ", drive->name, msg, err);
-               if (err & ILI_ERR)      printk("IllegalLengthIndication ");
-               if (err & EOM_ERR)      printk("EndOfMedia ");
-               if (err & ABRT_ERR)     printk("AbortedCommand ");
-               if (err & MCR_ERR)      printk("MediaChangeRequested ");
-               if (err & LFS_ERR)      printk("LastFailedSense=0x%02x ",
-                                               (err & LFS_ERR) >> 4);
-               printk("}\n");
+               err = ide_read_error(drive);
+               printk("%s: %s: error=0x%02x ", drive->name, msg, err);
+               if (drive->media == ide_disk)
+                       ide_dump_ata_error(drive, err);
+               else
+                       ide_dump_atapi_error(drive, err);
        }
        ide_dump_opcode(drive);
        local_irq_restore(flags);
        return err;
 }
 
-/**
- *     ide_dump_status         -       translate ATA/ATAPI error
- *     @drive: drive the error occured on
- *     @msg: information string
- *     @stat: status byte
- *
- *     Error reporting, in human readable form (luxurious, but a memory hog).
- *     Combines the drive name, message and status byte to provide a
- *     user understandable explanation of the device error.
- */
-
-u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
-{
-       if (drive->media == ide_disk)
-               return ide_dump_ata_status(drive, msg, stat);
-       return ide_dump_atapi_status(drive, msg, stat);
-}
-
 EXPORT_SYMBOL(ide_dump_status);
This page took 0.033271 seconds and 5 git commands to generate.