linux/drivers/ide/ide-lib.c
<<
>>
Prefs
   1#include <linux/types.h>
   2#include <linux/string.h>
   3#include <linux/kernel.h>
   4#include <linux/export.h>
   5#include <linux/interrupt.h>
   6#include <linux/ide.h>
   7#include <linux/bitops.h>
   8
   9/**
  10 *      ide_toggle_bounce       -       handle bounce buffering
  11 *      @drive: drive to update
  12 *      @on: on/off boolean
  13 *
  14 *      Enable or disable bounce buffering for the device. Drives move
  15 *      between PIO and DMA and that changes the rules we need.
  16 */
  17
  18void ide_toggle_bounce(ide_drive_t *drive, int on)
  19{
  20        u64 addr = BLK_BOUNCE_HIGH;     /* dma64_addr_t */
  21
  22        if (!PCI_DMA_BUS_IS_PHYS) {
  23                addr = BLK_BOUNCE_ANY;
  24        } else if (on && drive->media == ide_disk) {
  25                struct device *dev = drive->hwif->dev;
  26
  27                if (dev && dev->dma_mask)
  28                        addr = *dev->dma_mask;
  29        }
  30
  31        if (drive->queue)
  32                blk_queue_bounce_limit(drive->queue, addr);
  33}
  34
  35u64 ide_get_lba_addr(struct ide_cmd *cmd, int lba48)
  36{
  37        struct ide_taskfile *tf = &cmd->tf;
  38        u32 high, low;
  39
  40        low  = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal;
  41        if (lba48) {
  42                tf = &cmd->hob;
  43                high = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal;
  44        } else
  45                high = tf->device & 0xf;
  46
  47        return ((u64)high << 24) | low;
  48}
  49EXPORT_SYMBOL_GPL(ide_get_lba_addr);
  50
  51static void ide_dump_sector(ide_drive_t *drive)
  52{
  53        struct ide_cmd cmd;
  54        struct ide_taskfile *tf = &cmd.tf;
  55        u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48);
  56
  57        memset(&cmd, 0, sizeof(cmd));
  58        if (lba48) {
  59                cmd.valid.in.tf  = IDE_VALID_LBA;
  60                cmd.valid.in.hob = IDE_VALID_LBA;
  61                cmd.tf_flags = IDE_TFLAG_LBA48;
  62        } else
  63                cmd.valid.in.tf  = IDE_VALID_LBA | IDE_VALID_DEVICE;
  64
  65        ide_tf_readback(drive, &cmd);
  66
  67        if (lba48 || (tf->device & ATA_LBA))
  68                printk(KERN_CONT ", LBAsect=%llu",
  69                        (unsigned long long)ide_get_lba_addr(&cmd, lba48));
  70        else
  71                printk(KERN_CONT ", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
  72                        tf->device & 0xf, tf->lbal);
  73}
  74
  75static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
  76{
  77        printk(KERN_CONT "{ ");
  78        if (err & ATA_ABORTED)
  79                printk(KERN_CONT "DriveStatusError ");
  80        if (err & ATA_ICRC)
  81                printk(KERN_CONT "%s",
  82                        (err & ATA_ABORTED) ? "BadCRC " : "BadSector ");
  83        if (err & ATA_UNC)
  84                printk(KERN_CONT "UncorrectableError ");
  85        if (err & ATA_IDNF)
  86                printk(KERN_CONT "SectorIdNotFound ");
  87        if (err & ATA_TRK0NF)
  88                printk(KERN_CONT "TrackZeroNotFound ");
  89        if (err & ATA_AMNF)
  90                printk(KERN_CONT "AddrMarkNotFound ");
  91        printk(KERN_CONT "}");
  92        if ((err & (ATA_BBK | ATA_ABORTED)) == ATA_BBK ||
  93            (err & (ATA_UNC | ATA_IDNF | ATA_AMNF))) {
  94                struct request *rq = drive->hwif->rq;
  95
  96                ide_dump_sector(drive);
  97
  98                if (rq)
  99                        printk(KERN_CONT ", sector=%llu",
 100                               (unsigned long long)blk_rq_pos(rq));
 101        }
 102        printk(KERN_CONT "\n");
 103}
 104
 105static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
 106{
 107        printk(KERN_CONT "{ ");
 108        if (err & ATAPI_ILI)
 109                printk(KERN_CONT "IllegalLengthIndication ");
 110        if (err & ATAPI_EOM)
 111                printk(KERN_CONT "EndOfMedia ");
 112        if (err & ATA_ABORTED)
 113                printk(KERN_CONT "AbortedCommand ");
 114        if (err & ATA_MCR)
 115                printk(KERN_CONT "MediaChangeRequested ");
 116        if (err & ATAPI_LFS)
 117                printk(KERN_CONT "LastFailedSense=0x%02x ",
 118                        (err & ATAPI_LFS) >> 4);
 119        printk(KERN_CONT "}\n");
 120}
 121
 122/**
 123 *      ide_dump_status         -       translate ATA/ATAPI error
 124 *      @drive: drive that status applies to
 125 *      @msg: text message to print
 126 *      @stat: status byte to decode
 127 *
 128 *      Error reporting, in human readable form (luxurious, but a memory hog).
 129 *      Combines the drive name, message and status byte to provide a
 130 *      user understandable explanation of the device error.
 131 */
 132
 133u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
 134{
 135        u8 err = 0;
 136
 137        printk(KERN_ERR "%s: %s: status=0x%02x { ", drive->name, msg, stat);
 138        if (stat & ATA_BUSY)
 139                printk(KERN_CONT "Busy ");
 140        else {
 141                if (stat & ATA_DRDY)
 142                        printk(KERN_CONT "DriveReady ");
 143                if (stat & ATA_DF)
 144                        printk(KERN_CONT "DeviceFault ");
 145                if (stat & ATA_DSC)
 146                        printk(KERN_CONT "SeekComplete ");
 147                if (stat & ATA_DRQ)
 148                        printk(KERN_CONT "DataRequest ");
 149                if (stat & ATA_CORR)
 150                        printk(KERN_CONT "CorrectedError ");
 151                if (stat & ATA_IDX)
 152                        printk(KERN_CONT "Index ");
 153                if (stat & ATA_ERR)
 154                        printk(KERN_CONT "Error ");
 155        }
 156        printk(KERN_CONT "}\n");
 157        if ((stat & (ATA_BUSY | ATA_ERR)) == ATA_ERR) {
 158                err = ide_read_error(drive);
 159                printk(KERN_ERR "%s: %s: error=0x%02x ", drive->name, msg, err);
 160                if (drive->media == ide_disk)
 161                        ide_dump_ata_error(drive, err);
 162                else
 163                        ide_dump_atapi_error(drive, err);
 164        }
 165
 166        printk(KERN_ERR "%s: possibly failed opcode: 0x%02x\n",
 167                drive->name, drive->hwif->cmd.tf.command);
 168
 169        return err;
 170}
 171EXPORT_SYMBOL(ide_dump_status);
 172
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.