diff options
Diffstat (limited to 'drivers/ide/ide-cd.c')
-rw-r--r-- | drivers/ide/ide-cd.c | 123 |
1 files changed, 92 insertions, 31 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 6de3cd3d6e8e..654d4cd09847 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -301,7 +301,6 @@ | |||
301 | 301 | ||
302 | #define IDECD_VERSION "4.61" | 302 | #define IDECD_VERSION "4.61" |
303 | 303 | ||
304 | #include <linux/config.h> | ||
305 | #include <linux/module.h> | 304 | #include <linux/module.h> |
306 | #include <linux/types.h> | 305 | #include <linux/types.h> |
307 | #include <linux/kernel.h> | 306 | #include <linux/kernel.h> |
@@ -395,7 +394,8 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq, | |||
395 | * we cannot reliably check if drive can auto-close | 394 | * we cannot reliably check if drive can auto-close |
396 | */ | 395 | */ |
397 | if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24) | 396 | if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24) |
398 | log = 0; | 397 | break; |
398 | log = 1; | ||
399 | break; | 399 | break; |
400 | case UNIT_ATTENTION: | 400 | case UNIT_ATTENTION: |
401 | /* | 401 | /* |
@@ -417,6 +417,11 @@ void cdrom_analyze_sense_data(ide_drive_t *drive, | |||
417 | struct request *failed_command, | 417 | struct request *failed_command, |
418 | struct request_sense *sense) | 418 | struct request_sense *sense) |
419 | { | 419 | { |
420 | unsigned long sector; | ||
421 | unsigned long bio_sectors; | ||
422 | unsigned long valid; | ||
423 | struct cdrom_info *info = drive->driver_data; | ||
424 | |||
420 | if (!cdrom_log_sense(drive, failed_command, sense)) | 425 | if (!cdrom_log_sense(drive, failed_command, sense)) |
421 | return; | 426 | return; |
422 | 427 | ||
@@ -429,6 +434,37 @@ void cdrom_analyze_sense_data(ide_drive_t *drive, | |||
429 | if (sense->sense_key == 0x05 && sense->asc == 0x24) | 434 | if (sense->sense_key == 0x05 && sense->asc == 0x24) |
430 | return; | 435 | return; |
431 | 436 | ||
437 | if (sense->error_code == 0x70) { /* Current Error */ | ||
438 | switch(sense->sense_key) { | ||
439 | case MEDIUM_ERROR: | ||
440 | case VOLUME_OVERFLOW: | ||
441 | case ILLEGAL_REQUEST: | ||
442 | if (!sense->valid) | ||
443 | break; | ||
444 | if (failed_command == NULL || | ||
445 | !blk_fs_request(failed_command)) | ||
446 | break; | ||
447 | sector = (sense->information[0] << 24) | | ||
448 | (sense->information[1] << 16) | | ||
449 | (sense->information[2] << 8) | | ||
450 | (sense->information[3]); | ||
451 | |||
452 | bio_sectors = bio_sectors(failed_command->bio); | ||
453 | if (bio_sectors < 4) | ||
454 | bio_sectors = 4; | ||
455 | if (drive->queue->hardsect_size == 2048) | ||
456 | sector <<= 2; /* Device sector size is 2K */ | ||
457 | sector &= ~(bio_sectors -1); | ||
458 | valid = (sector - failed_command->sector) << 9; | ||
459 | |||
460 | if (valid < 0) | ||
461 | valid = 0; | ||
462 | if (sector < get_capacity(info->disk) && | ||
463 | drive->probed_capacity - sector < 4 * 75) { | ||
464 | set_capacity(info->disk, sector); | ||
465 | } | ||
466 | } | ||
467 | } | ||
432 | #if VERBOSE_IDE_CD_ERRORS | 468 | #if VERBOSE_IDE_CD_ERRORS |
433 | { | 469 | { |
434 | int i; | 470 | int i; |
@@ -609,17 +645,23 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate) | |||
609 | sense = failed->sense; | 645 | sense = failed->sense; |
610 | failed->sense_len = rq->sense_len; | 646 | failed->sense_len = rq->sense_len; |
611 | } | 647 | } |
612 | 648 | cdrom_analyze_sense_data(drive, failed, sense); | |
613 | /* | 649 | /* |
614 | * now end failed request | 650 | * now end failed request |
615 | */ | 651 | */ |
616 | spin_lock_irqsave(&ide_lock, flags); | 652 | if (blk_fs_request(failed)) { |
617 | end_that_request_chunk(failed, 0, failed->data_len); | 653 | if (ide_end_dequeued_request(drive, failed, 0, |
618 | end_that_request_last(failed, 0); | 654 | failed->hard_nr_sectors)) |
619 | spin_unlock_irqrestore(&ide_lock, flags); | 655 | BUG(); |
620 | } | 656 | } else { |
621 | 657 | spin_lock_irqsave(&ide_lock, flags); | |
622 | cdrom_analyze_sense_data(drive, failed, sense); | 658 | end_that_request_chunk(failed, 0, |
659 | failed->data_len); | ||
660 | end_that_request_last(failed, 0); | ||
661 | spin_unlock_irqrestore(&ide_lock, flags); | ||
662 | } | ||
663 | } else | ||
664 | cdrom_analyze_sense_data(drive, NULL, sense); | ||
623 | } | 665 | } |
624 | 666 | ||
625 | if (!rq->current_nr_sectors && blk_fs_request(rq)) | 667 | if (!rq->current_nr_sectors && blk_fs_request(rq)) |
@@ -633,6 +675,13 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate) | |||
633 | ide_end_request(drive, uptodate, nsectors); | 675 | ide_end_request(drive, uptodate, nsectors); |
634 | } | 676 | } |
635 | 677 | ||
678 | static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat) | ||
679 | { | ||
680 | if (stat & 0x80) | ||
681 | return; | ||
682 | ide_dump_status(drive, msg, stat); | ||
683 | } | ||
684 | |||
636 | /* Returns 0 if the request should be continued. | 685 | /* Returns 0 if the request should be continued. |
637 | Returns 1 if the request was ended. */ | 686 | Returns 1 if the request was ended. */ |
638 | static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | 687 | static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) |
@@ -761,16 +810,16 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | |||
761 | sense_key == DATA_PROTECT) { | 810 | sense_key == DATA_PROTECT) { |
762 | /* No point in retrying after an illegal | 811 | /* No point in retrying after an illegal |
763 | request or data protect error.*/ | 812 | request or data protect error.*/ |
764 | ide_dump_status (drive, "command error", stat); | 813 | ide_dump_status_no_sense (drive, "command error", stat); |
765 | do_end_request = 1; | 814 | do_end_request = 1; |
766 | } else if (sense_key == MEDIUM_ERROR) { | 815 | } else if (sense_key == MEDIUM_ERROR) { |
767 | /* No point in re-trying a zillion times on a bad | 816 | /* No point in re-trying a zillion times on a bad |
768 | * sector... If we got here the error is not correctable */ | 817 | * sector... If we got here the error is not correctable */ |
769 | ide_dump_status (drive, "media error (bad sector)", stat); | 818 | ide_dump_status_no_sense (drive, "media error (bad sector)", stat); |
770 | do_end_request = 1; | 819 | do_end_request = 1; |
771 | } else if (sense_key == BLANK_CHECK) { | 820 | } else if (sense_key == BLANK_CHECK) { |
772 | /* Disk appears blank ?? */ | 821 | /* Disk appears blank ?? */ |
773 | ide_dump_status (drive, "media error (blank)", stat); | 822 | ide_dump_status_no_sense (drive, "media error (blank)", stat); |
774 | do_end_request = 1; | 823 | do_end_request = 1; |
775 | } else if ((err & ~ABRT_ERR) != 0) { | 824 | } else if ((err & ~ABRT_ERR) != 0) { |
776 | /* Go to the default handler | 825 | /* Go to the default handler |
@@ -782,13 +831,27 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | |||
782 | do_end_request = 1; | 831 | do_end_request = 1; |
783 | } | 832 | } |
784 | 833 | ||
785 | if (do_end_request) | 834 | /* End a request through request sense analysis when we have |
786 | cdrom_end_request(drive, 0); | 835 | sense data. We need this in order to perform end of media |
787 | 836 | processing */ | |
788 | /* If we got a CHECK_CONDITION status, | 837 | |
789 | queue a request sense command. */ | 838 | if (do_end_request) { |
790 | if ((stat & ERR_STAT) != 0) | 839 | if (stat & ERR_STAT) { |
791 | cdrom_queue_request_sense(drive, NULL, NULL); | 840 | unsigned long flags; |
841 | spin_lock_irqsave(&ide_lock, flags); | ||
842 | blkdev_dequeue_request(rq); | ||
843 | HWGROUP(drive)->rq = NULL; | ||
844 | spin_unlock_irqrestore(&ide_lock, flags); | ||
845 | |||
846 | cdrom_queue_request_sense(drive, rq->sense, rq); | ||
847 | } else | ||
848 | cdrom_end_request(drive, 0); | ||
849 | } else { | ||
850 | /* If we got a CHECK_CONDITION status, | ||
851 | queue a request sense command. */ | ||
852 | if (stat & ERR_STAT) | ||
853 | cdrom_queue_request_sense(drive, NULL, NULL); | ||
854 | } | ||
792 | } else { | 855 | } else { |
793 | blk_dump_rq_flags(rq, "ide-cd: bad rq"); | 856 | blk_dump_rq_flags(rq, "ide-cd: bad rq"); |
794 | cdrom_end_request(drive, 0); | 857 | cdrom_end_request(drive, 0); |
@@ -1491,8 +1554,7 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive) | |||
1491 | } | 1554 | } |
1492 | 1555 | ||
1493 | 1556 | ||
1494 | static | 1557 | static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) |
1495 | int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) | ||
1496 | { | 1558 | { |
1497 | struct request_sense sense; | 1559 | struct request_sense sense; |
1498 | int retries = 10; | 1560 | int retries = 10; |
@@ -2220,6 +2282,9 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) | |||
2220 | toc->capacity = 0x1fffff; | 2282 | toc->capacity = 0x1fffff; |
2221 | 2283 | ||
2222 | set_capacity(info->disk, toc->capacity * sectors_per_frame); | 2284 | set_capacity(info->disk, toc->capacity * sectors_per_frame); |
2285 | /* Save a private copy of te TOC capacity for error handling */ | ||
2286 | drive->probed_capacity = toc->capacity * sectors_per_frame; | ||
2287 | |||
2223 | blk_queue_hardsect_size(drive->queue, | 2288 | blk_queue_hardsect_size(drive->queue, |
2224 | sectors_per_frame << SECTOR_BITS); | 2289 | sectors_per_frame << SECTOR_BITS); |
2225 | 2290 | ||
@@ -2342,6 +2407,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) | |||
2342 | if (!stat && (last_written > toc->capacity)) { | 2407 | if (!stat && (last_written > toc->capacity)) { |
2343 | toc->capacity = last_written; | 2408 | toc->capacity = last_written; |
2344 | set_capacity(info->disk, toc->capacity * sectors_per_frame); | 2409 | set_capacity(info->disk, toc->capacity * sectors_per_frame); |
2410 | drive->probed_capacity = toc->capacity * sectors_per_frame; | ||
2345 | } | 2411 | } |
2346 | 2412 | ||
2347 | /* Remember that we've read this stuff. */ | 2413 | /* Remember that we've read this stuff. */ |
@@ -2698,14 +2764,11 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) | |||
2698 | * any other way to detect this... | 2764 | * any other way to detect this... |
2699 | */ | 2765 | */ |
2700 | if (sense.sense_key == NOT_READY) { | 2766 | if (sense.sense_key == NOT_READY) { |
2701 | if (sense.asc == 0x3a) { | 2767 | if (sense.asc == 0x3a && sense.ascq == 1) |
2702 | if (sense.ascq == 1) | 2768 | return CDS_NO_DISC; |
2703 | return CDS_NO_DISC; | 2769 | else |
2704 | else if (sense.ascq == 0 || sense.ascq == 2) | 2770 | return CDS_TRAY_OPEN; |
2705 | return CDS_TRAY_OPEN; | ||
2706 | } | ||
2707 | } | 2771 | } |
2708 | |||
2709 | return CDS_DRIVE_NOT_READY; | 2772 | return CDS_DRIVE_NOT_READY; |
2710 | } | 2773 | } |
2711 | 2774 | ||
@@ -3463,8 +3526,6 @@ static int ide_cd_probe(ide_drive_t *drive) | |||
3463 | drive->driver_data = info; | 3526 | drive->driver_data = info; |
3464 | 3527 | ||
3465 | g->minors = 1; | 3528 | g->minors = 1; |
3466 | snprintf(g->devfs_name, sizeof(g->devfs_name), | ||
3467 | "%s/cd", drive->devfs_name); | ||
3468 | g->driverfs_dev = &drive->gendev; | 3529 | g->driverfs_dev = &drive->gendev; |
3469 | g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; | 3530 | g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; |
3470 | if (ide_cdrom_setup(drive)) { | 3531 | if (ide_cdrom_setup(drive)) { |