diff options
Diffstat (limited to 'drivers/ide/ide-lib.c')
-rw-r--r-- | drivers/ide/ide-lib.c | 207 |
1 files changed, 94 insertions, 113 deletions
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 062d3bcb2471..a3bd8e8ed6b0 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c | |||
@@ -441,6 +441,12 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) | |||
441 | * case could happen iff the transfer mode has already been set on | 441 | * case could happen iff the transfer mode has already been set on |
442 | * the device by ide-proc.c::set_xfer_rate()). | 442 | * the device by ide-proc.c::set_xfer_rate()). |
443 | */ | 443 | */ |
444 | if (rate < XFER_PIO_0) { | ||
445 | if (hwif->host_flags & IDE_HFLAG_ABUSE_SET_DMA_MODE) | ||
446 | return ide_set_dma_mode(drive, rate); | ||
447 | else | ||
448 | return ide_config_drive_speed(drive, rate); | ||
449 | } | ||
444 | 450 | ||
445 | return ide_set_dma_mode(drive, rate); | 451 | return ide_set_dma_mode(drive, rate); |
446 | } | 452 | } |
@@ -458,8 +464,7 @@ static void ide_dump_opcode(ide_drive_t *drive) | |||
458 | spin_unlock(&ide_lock); | 464 | spin_unlock(&ide_lock); |
459 | if (!rq) | 465 | if (!rq) |
460 | return; | 466 | return; |
461 | if (rq->cmd_type == REQ_TYPE_ATA_CMD || | 467 | if (rq->cmd_type == REQ_TYPE_ATA_CMD) { |
462 | rq->cmd_type == REQ_TYPE_ATA_TASK) { | ||
463 | char *args = rq->buffer; | 468 | char *args = rq->buffer; |
464 | if (args) { | 469 | if (args) { |
465 | opcode = args[0]; | 470 | opcode = args[0]; |
@@ -468,8 +473,7 @@ static void ide_dump_opcode(ide_drive_t *drive) | |||
468 | } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { | 473 | } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { |
469 | ide_task_t *args = rq->special; | 474 | ide_task_t *args = rq->special; |
470 | if (args) { | 475 | if (args) { |
471 | task_struct_t *tf = (task_struct_t *) args->tfRegister; | 476 | opcode = args->tf.command; |
472 | opcode = tf->command; | ||
473 | found = 1; | 477 | found = 1; |
474 | } | 478 | } |
475 | } | 479 | } |
@@ -481,141 +485,118 @@ static void ide_dump_opcode(ide_drive_t *drive) | |||
481 | printk("0x%02x\n", opcode); | 485 | printk("0x%02x\n", opcode); |
482 | } | 486 | } |
483 | 487 | ||
484 | static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat) | 488 | u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48) |
485 | { | 489 | { |
486 | ide_hwif_t *hwif = HWIF(drive); | 490 | u32 high, low; |
487 | unsigned long flags; | ||
488 | u8 err = 0; | ||
489 | 491 | ||
490 | local_irq_save(flags); | 492 | if (lba48) |
491 | printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); | 493 | high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) | |
492 | if (stat & BUSY_STAT) | 494 | tf->hob_lbal; |
493 | printk("Busy "); | 495 | else |
494 | else { | 496 | high = tf->device & 0xf; |
495 | if (stat & READY_STAT) printk("DriveReady "); | 497 | low = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal; |
496 | if (stat & WRERR_STAT) printk("DeviceFault "); | 498 | |
497 | if (stat & SEEK_STAT) printk("SeekComplete "); | 499 | return ((u64)high << 24) | low; |
498 | if (stat & DRQ_STAT) printk("DataRequest "); | 500 | } |
499 | if (stat & ECC_STAT) printk("CorrectedError "); | 501 | EXPORT_SYMBOL_GPL(ide_get_lba_addr); |
500 | if (stat & INDEX_STAT) printk("Index "); | 502 | |
501 | if (stat & ERR_STAT) printk("Error "); | 503 | static void ide_dump_sector(ide_drive_t *drive) |
504 | { | ||
505 | ide_task_t task; | ||
506 | struct ide_taskfile *tf = &task.tf; | ||
507 | int lba48 = (drive->addressing == 1) ? 1 : 0; | ||
508 | |||
509 | memset(&task, 0, sizeof(task)); | ||
510 | if (lba48) | ||
511 | task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA | | ||
512 | IDE_TFLAG_LBA48; | ||
513 | else | ||
514 | task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE; | ||
515 | |||
516 | ide_tf_read(drive, &task); | ||
517 | |||
518 | if (lba48 || (tf->device & ATA_LBA)) | ||
519 | printk(", LBAsect=%llu", | ||
520 | (unsigned long long)ide_get_lba_addr(tf, lba48)); | ||
521 | else | ||
522 | printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam, | ||
523 | tf->device & 0xf, tf->lbal); | ||
524 | } | ||
525 | |||
526 | static void ide_dump_ata_error(ide_drive_t *drive, u8 err) | ||
527 | { | ||
528 | printk("{ "); | ||
529 | if (err & ABRT_ERR) printk("DriveStatusError "); | ||
530 | if (err & ICRC_ERR) | ||
531 | printk((err & ABRT_ERR) ? "BadCRC " : "BadSector "); | ||
532 | if (err & ECC_ERR) printk("UncorrectableError "); | ||
533 | if (err & ID_ERR) printk("SectorIdNotFound "); | ||
534 | if (err & TRK0_ERR) printk("TrackZeroNotFound "); | ||
535 | if (err & MARK_ERR) printk("AddrMarkNotFound "); | ||
536 | printk("}"); | ||
537 | if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || | ||
538 | (err & (ECC_ERR|ID_ERR|MARK_ERR))) { | ||
539 | ide_dump_sector(drive); | ||
540 | if (HWGROUP(drive) && HWGROUP(drive)->rq) | ||
541 | printk(", sector=%llu", | ||
542 | (unsigned long long)HWGROUP(drive)->rq->sector); | ||
502 | } | 543 | } |
544 | printk("\n"); | ||
545 | } | ||
546 | |||
547 | static void ide_dump_atapi_error(ide_drive_t *drive, u8 err) | ||
548 | { | ||
549 | printk("{ "); | ||
550 | if (err & ILI_ERR) printk("IllegalLengthIndication "); | ||
551 | if (err & EOM_ERR) printk("EndOfMedia "); | ||
552 | if (err & ABRT_ERR) printk("AbortedCommand "); | ||
553 | if (err & MCR_ERR) printk("MediaChangeRequested "); | ||
554 | if (err & LFS_ERR) printk("LastFailedSense=0x%02x ", | ||
555 | (err & LFS_ERR) >> 4); | ||
503 | printk("}\n"); | 556 | printk("}\n"); |
504 | if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { | ||
505 | err = hwif->INB(IDE_ERROR_REG); | ||
506 | printk("%s: %s: error=0x%02x { ", drive->name, msg, err); | ||
507 | if (err & ABRT_ERR) printk("DriveStatusError "); | ||
508 | if (err & ICRC_ERR) | ||
509 | printk((err & ABRT_ERR) ? "BadCRC " : "BadSector "); | ||
510 | if (err & ECC_ERR) printk("UncorrectableError "); | ||
511 | if (err & ID_ERR) printk("SectorIdNotFound "); | ||
512 | if (err & TRK0_ERR) printk("TrackZeroNotFound "); | ||
513 | if (err & MARK_ERR) printk("AddrMarkNotFound "); | ||
514 | printk("}"); | ||
515 | if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || | ||
516 | (err & (ECC_ERR|ID_ERR|MARK_ERR))) { | ||
517 | if (drive->addressing == 1) { | ||
518 | __u64 sectors = 0; | ||
519 | u32 low = 0, high = 0; | ||
520 | hwif->OUTB(drive->ctl&~0x80, IDE_CONTROL_REG); | ||
521 | low = ide_read_24(drive); | ||
522 | hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); | ||
523 | high = ide_read_24(drive); | ||
524 | sectors = ((__u64)high << 24) | low; | ||
525 | printk(", LBAsect=%llu, high=%d, low=%d", | ||
526 | (unsigned long long) sectors, | ||
527 | high, low); | ||
528 | } else { | ||
529 | u8 cur = hwif->INB(IDE_SELECT_REG); | ||
530 | if (cur & 0x40) { /* using LBA? */ | ||
531 | printk(", LBAsect=%ld", (unsigned long) | ||
532 | ((cur&0xf)<<24) | ||
533 | |(hwif->INB(IDE_HCYL_REG)<<16) | ||
534 | |(hwif->INB(IDE_LCYL_REG)<<8) | ||
535 | | hwif->INB(IDE_SECTOR_REG)); | ||
536 | } else { | ||
537 | printk(", CHS=%d/%d/%d", | ||
538 | (hwif->INB(IDE_HCYL_REG)<<8) + | ||
539 | hwif->INB(IDE_LCYL_REG), | ||
540 | cur & 0xf, | ||
541 | hwif->INB(IDE_SECTOR_REG)); | ||
542 | } | ||
543 | } | ||
544 | if (HWGROUP(drive) && HWGROUP(drive)->rq) | ||
545 | printk(", sector=%llu", | ||
546 | (unsigned long long)HWGROUP(drive)->rq->sector); | ||
547 | } | ||
548 | printk("\n"); | ||
549 | } | ||
550 | ide_dump_opcode(drive); | ||
551 | local_irq_restore(flags); | ||
552 | return err; | ||
553 | } | 557 | } |
554 | 558 | ||
555 | /** | 559 | /** |
556 | * ide_dump_atapi_status - print human readable atapi status | 560 | * ide_dump_status - translate ATA/ATAPI error |
557 | * @drive: drive that status applies to | 561 | * @drive: drive that status applies to |
558 | * @msg: text message to print | 562 | * @msg: text message to print |
559 | * @stat: status byte to decode | 563 | * @stat: status byte to decode |
560 | * | 564 | * |
561 | * Error reporting, in human readable form (luxurious, but a memory hog). | 565 | * Error reporting, in human readable form (luxurious, but a memory hog). |
566 | * Combines the drive name, message and status byte to provide a | ||
567 | * user understandable explanation of the device error. | ||
562 | */ | 568 | */ |
563 | 569 | ||
564 | static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat) | 570 | u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat) |
565 | { | 571 | { |
566 | unsigned long flags; | 572 | unsigned long flags; |
573 | u8 err = 0; | ||
567 | 574 | ||
568 | atapi_status_t status; | ||
569 | atapi_error_t error; | ||
570 | |||
571 | status.all = stat; | ||
572 | error.all = 0; | ||
573 | local_irq_save(flags); | 575 | local_irq_save(flags); |
574 | printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); | 576 | printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); |
575 | if (status.b.bsy) | 577 | if (stat & BUSY_STAT) |
576 | printk("Busy "); | 578 | printk("Busy "); |
577 | else { | 579 | else { |
578 | if (status.b.drdy) printk("DriveReady "); | 580 | if (stat & READY_STAT) printk("DriveReady "); |
579 | if (status.b.df) printk("DeviceFault "); | 581 | if (stat & WRERR_STAT) printk("DeviceFault "); |
580 | if (status.b.dsc) printk("SeekComplete "); | 582 | if (stat & SEEK_STAT) printk("SeekComplete "); |
581 | if (status.b.drq) printk("DataRequest "); | 583 | if (stat & DRQ_STAT) printk("DataRequest "); |
582 | if (status.b.corr) printk("CorrectedError "); | 584 | if (stat & ECC_STAT) printk("CorrectedError "); |
583 | if (status.b.idx) printk("Index "); | 585 | if (stat & INDEX_STAT) printk("Index "); |
584 | if (status.b.check) printk("Error "); | 586 | if (stat & ERR_STAT) printk("Error "); |
585 | } | 587 | } |
586 | printk("}\n"); | 588 | printk("}\n"); |
587 | if (status.b.check && !status.b.bsy) { | 589 | if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { |
588 | error.all = HWIF(drive)->INB(IDE_ERROR_REG); | 590 | err = drive->hwif->INB(IDE_ERROR_REG); |
589 | printk("%s: %s: error=0x%02x { ", drive->name, msg, error.all); | 591 | printk("%s: %s: error=0x%02x ", drive->name, msg, err); |
590 | if (error.b.ili) printk("IllegalLengthIndication "); | 592 | if (drive->media == ide_disk) |
591 | if (error.b.eom) printk("EndOfMedia "); | 593 | ide_dump_ata_error(drive, err); |
592 | if (error.b.abrt) printk("AbortedCommand "); | 594 | else |
593 | if (error.b.mcr) printk("MediaChangeRequested "); | 595 | ide_dump_atapi_error(drive, err); |
594 | if (error.b.sense_key) printk("LastFailedSense=0x%02x ", | ||
595 | error.b.sense_key); | ||
596 | printk("}\n"); | ||
597 | } | 596 | } |
598 | ide_dump_opcode(drive); | 597 | ide_dump_opcode(drive); |
599 | local_irq_restore(flags); | 598 | local_irq_restore(flags); |
600 | return error.all; | 599 | return err; |
601 | } | ||
602 | |||
603 | /** | ||
604 | * ide_dump_status - translate ATA/ATAPI error | ||
605 | * @drive: drive the error occured on | ||
606 | * @msg: information string | ||
607 | * @stat: status byte | ||
608 | * | ||
609 | * Error reporting, in human readable form (luxurious, but a memory hog). | ||
610 | * Combines the drive name, message and status byte to provide a | ||
611 | * user understandable explanation of the device error. | ||
612 | */ | ||
613 | |||
614 | u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat) | ||
615 | { | ||
616 | if (drive->media == ide_disk) | ||
617 | return ide_dump_ata_status(drive, msg, stat); | ||
618 | return ide_dump_atapi_status(drive, msg, stat); | ||
619 | } | 600 | } |
620 | 601 | ||
621 | EXPORT_SYMBOL(ide_dump_status); | 602 | EXPORT_SYMBOL(ide_dump_status); |