X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fide%2Fide-lib.c;h=6806d407e9c12ab41250e69daffaccca919dd4d6;hb=65da6b7c3bf0bd6a149128079565e5f4efec28ac;hp=b2fa5eccdcad483f8df2218fbf2bf48269d63bb4;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index b2fa5eccd..6806d407e 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -15,12 +15,12 @@ #include #include #include +#include #include #include #include #include -#include /* * IDE library routines. These are plug in code that most @@ -421,8 +421,6 @@ void ide_toggle_bounce(ide_drive_t *drive, int on) blk_queue_bounce_limit(drive->queue, addr); } -EXPORT_SYMBOL(ide_toggle_bounce); - /** * ide_set_xfer_rate - set transfer rate * @drive: drive to set @@ -447,6 +445,114 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) EXPORT_SYMBOL_GPL(ide_set_xfer_rate); +static void ide_dump_opcode(ide_drive_t *drive) +{ + struct request *rq; + u8 opcode = 0; + int found = 0; + + spin_lock(&ide_lock); + rq = NULL; + if (HWGROUP(drive)) + rq = HWGROUP(drive)->rq; + spin_unlock(&ide_lock); + if (!rq) + return; + if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) { + char *args = rq->buffer; + if (args) { + opcode = args[0]; + found = 1; + } + } else if (rq->flags & REQ_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + if (args) { + task_struct_t *tf = (task_struct_t *) args->tfRegister; + opcode = tf->command; + found = 1; + } + } + + printk("ide: failed opcode was: "); + if (!found) + printk("unknown\n"); + else + printk("0x%02x\n", opcode); +} + +static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long flags; + u8 err = 0; + + local_irq_set(flags); + printk("%s: %s: status=0x%02x", drive->name, msg, stat); + printk(" { "); + 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 "); + } + printk("}"); + 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); + printk(" { "); + if (err & ABRT_ERR) printk("DriveStatusError "); + if (err & ICRC_ERR) + printk("Bad%s ", (err & ABRT_ERR) ? "CRC" : "Sector"); + 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; + 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 * @drive: drive that status applies to @@ -455,7 +561,8 @@ EXPORT_SYMBOL_GPL(ide_set_xfer_rate); * * Error reporting, in human readable form (luxurious, but a memory hog). */ -byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat) + +static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat) { unsigned long flags; @@ -463,9 +570,9 @@ byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat) atapi_error_t error; status.all = stat; + error.all = 0; local_irq_set(flags); - printk("%s: %s: status=0x%02x", drive->name, msg, stat); - printk(" { "); + printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); if (status.b.bsy) printk("Busy "); else { @@ -477,21 +584,39 @@ byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat) if (status.b.idx) printk("Index "); if (status.b.check) printk("Error "); } - printk("}"); - printk("\n"); - if ((status.all & (status.b.bsy|status.b.check)) == status.b.check) { + printk("}\n"); + if (status.b.check && !status.b.bsy) { error.all = HWIF(drive)->INB(IDE_ERROR_REG); - printk("%s: %s: error=0x%02x", drive->name, msg, error.all); + printk("%s: %s: error=0x%02x { ", drive->name, msg, error.all); if (error.b.ili) printk("IllegalLengthIndication "); if (error.b.eom) printk("EndOfMedia "); - if (error.b.abrt) printk("Aborted Command "); + if (error.b.abrt) printk("AbortedCommand "); if (error.b.mcr) printk("MediaChangeRequested "); - if (error.b.sense_key) printk("LastFailedSense 0x%02x ", + if (error.b.sense_key) printk("LastFailedSense=0x%02x ", error.b.sense_key); - printk("\n"); + printk("}\n"); } + ide_dump_opcode(drive); local_irq_restore(flags); return error.all; } -EXPORT_SYMBOL(ide_dump_atapi_status); +/** + * 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);