diff options
Diffstat (limited to 'drivers/ide/ide-cd.c')
-rw-r--r-- | drivers/ide/ide-cd.c | 160 |
1 files changed, 77 insertions, 83 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index d99847157186..6e29dd532090 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -517,14 +517,9 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, | |||
517 | int xferlen, | 517 | int xferlen, |
518 | ide_handler_t *handler) | 518 | ide_handler_t *handler) |
519 | { | 519 | { |
520 | ide_startstop_t startstop; | ||
521 | struct cdrom_info *info = drive->driver_data; | 520 | struct cdrom_info *info = drive->driver_data; |
522 | ide_hwif_t *hwif = drive->hwif; | 521 | ide_hwif_t *hwif = drive->hwif; |
523 | 522 | ||
524 | /* wait for the controller to be idle */ | ||
525 | if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY)) | ||
526 | return startstop; | ||
527 | |||
528 | /* FIXME: for Virtual DMA we must check harder */ | 523 | /* FIXME: for Virtual DMA we must check harder */ |
529 | if (info->dma) | 524 | if (info->dma) |
530 | info->dma = !hwif->dma_ops->dma_setup(drive); | 525 | info->dma = !hwif->dma_ops->dma_setup(drive); |
@@ -604,28 +599,6 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive, | |||
604 | } | 599 | } |
605 | 600 | ||
606 | /* | 601 | /* |
607 | * Block read functions. | ||
608 | */ | ||
609 | static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len) | ||
610 | { | ||
611 | while (len > 0) { | ||
612 | int dum = 0; | ||
613 | xf(drive, NULL, &dum, sizeof(dum)); | ||
614 | len -= sizeof(dum); | ||
615 | } | ||
616 | } | ||
617 | |||
618 | static void ide_cd_drain_data(ide_drive_t *drive, int nsects) | ||
619 | { | ||
620 | while (nsects > 0) { | ||
621 | static char dum[SECTOR_SIZE]; | ||
622 | |||
623 | drive->hwif->input_data(drive, NULL, dum, sizeof(dum)); | ||
624 | nsects--; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | /* | ||
629 | * Check the contents of the interrupt reason register from the cdrom | 602 | * Check the contents of the interrupt reason register from the cdrom |
630 | * and attempt to recover if there are problems. Returns 0 if everything's | 603 | * and attempt to recover if there are problems. Returns 0 if everything's |
631 | * ok; nonzero if the request has been terminated. | 604 | * ok; nonzero if the request has been terminated. |
@@ -640,15 +613,12 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq, | |||
640 | if (ireason == (!rw << 1)) | 613 | if (ireason == (!rw << 1)) |
641 | return 0; | 614 | return 0; |
642 | else if (ireason == (rw << 1)) { | 615 | else if (ireason == (rw << 1)) { |
643 | ide_hwif_t *hwif = drive->hwif; | ||
644 | xfer_func_t *xf; | ||
645 | 616 | ||
646 | /* whoops... */ | 617 | /* whoops... */ |
647 | printk(KERN_ERR "%s: %s: wrong transfer direction!\n", | 618 | printk(KERN_ERR "%s: %s: wrong transfer direction!\n", |
648 | drive->name, __func__); | 619 | drive->name, __func__); |
649 | 620 | ||
650 | xf = rw ? hwif->output_data : hwif->input_data; | 621 | ide_pad_transfer(drive, rw, len); |
651 | ide_cd_pad_transfer(drive, xf, len); | ||
652 | } else if (rw == 0 && ireason == 1) { | 622 | } else if (rw == 0 && ireason == 1) { |
653 | /* | 623 | /* |
654 | * Some drives (ASUS) seem to tell us that status info is | 624 | * Some drives (ASUS) seem to tell us that status info is |
@@ -696,16 +666,9 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len) | |||
696 | 666 | ||
697 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *); | 667 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *); |
698 | 668 | ||
699 | /* | 669 | static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive, |
700 | * Routine to send a read/write packet command to the drive. This is usually | 670 | struct request *rq) |
701 | * called directly from cdrom_start_{read,write}(). However, for drq_interrupt | ||
702 | * devices, it is called from an interrupt when the drive is ready to accept | ||
703 | * the command. | ||
704 | */ | ||
705 | static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive) | ||
706 | { | 671 | { |
707 | struct request *rq = HWGROUP(drive)->rq; | ||
708 | |||
709 | if (rq_data_dir(rq) == READ) { | 672 | if (rq_data_dir(rq) == READ) { |
710 | unsigned short sectors_per_frame = | 673 | unsigned short sectors_per_frame = |
711 | queue_hardsect_size(drive->queue) >> SECTOR_BITS; | 674 | queue_hardsect_size(drive->queue) >> SECTOR_BITS; |
@@ -742,6 +705,19 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive) | |||
742 | /* set up the command */ | 705 | /* set up the command */ |
743 | rq->timeout = ATAPI_WAIT_PC; | 706 | rq->timeout = ATAPI_WAIT_PC; |
744 | 707 | ||
708 | return ide_started; | ||
709 | } | ||
710 | |||
711 | /* | ||
712 | * Routine to send a read/write packet command to the drive. This is usually | ||
713 | * called directly from cdrom_start_{read,write}(). However, for drq_interrupt | ||
714 | * devices, it is called from an interrupt when the drive is ready to accept | ||
715 | * the command. | ||
716 | */ | ||
717 | static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive) | ||
718 | { | ||
719 | struct request *rq = drive->hwif->hwgroup->rq; | ||
720 | |||
745 | /* send the command to the drive and return */ | 721 | /* send the command to the drive and return */ |
746 | return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr); | 722 | return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr); |
747 | } | 723 | } |
@@ -768,9 +744,8 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive) | |||
768 | return ide_stopped; | 744 | return ide_stopped; |
769 | } | 745 | } |
770 | 746 | ||
771 | static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive) | 747 | static void ide_cd_prepare_seek_request(ide_drive_t *drive, struct request *rq) |
772 | { | 748 | { |
773 | struct request *rq = HWGROUP(drive)->rq; | ||
774 | sector_t frame = rq->sector; | 749 | sector_t frame = rq->sector; |
775 | 750 | ||
776 | sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS); | 751 | sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS); |
@@ -780,17 +755,13 @@ static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive) | |||
780 | put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]); | 755 | put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]); |
781 | 756 | ||
782 | rq->timeout = ATAPI_WAIT_PC; | 757 | rq->timeout = ATAPI_WAIT_PC; |
783 | return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr); | ||
784 | } | 758 | } |
785 | 759 | ||
786 | static ide_startstop_t cdrom_start_seek(ide_drive_t *drive, unsigned int block) | 760 | static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive) |
787 | { | 761 | { |
788 | struct cdrom_info *info = drive->driver_data; | 762 | struct request *rq = drive->hwif->hwgroup->rq; |
789 | 763 | ||
790 | info->dma = 0; | 764 | return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr); |
791 | info->start_seek = jiffies; | ||
792 | return cdrom_start_packet_command(drive, 0, | ||
793 | cdrom_start_seek_continuation); | ||
794 | } | 765 | } |
795 | 766 | ||
796 | /* | 767 | /* |
@@ -1011,7 +982,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1011 | - bio_cur_sectors(rq->bio), | 982 | - bio_cur_sectors(rq->bio), |
1012 | thislen >> 9); | 983 | thislen >> 9); |
1013 | if (nskip > 0) { | 984 | if (nskip > 0) { |
1014 | ide_cd_drain_data(drive, nskip); | 985 | ide_pad_transfer(drive, write, nskip << 9); |
1015 | rq->current_nr_sectors -= nskip; | 986 | rq->current_nr_sectors -= nskip; |
1016 | thislen -= (nskip << 9); | 987 | thislen -= (nskip << 9); |
1017 | } | 988 | } |
@@ -1048,7 +1019,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1048 | * If the buffers are full, pipe the rest into | 1019 | * If the buffers are full, pipe the rest into |
1049 | * oblivion. | 1020 | * oblivion. |
1050 | */ | 1021 | */ |
1051 | ide_cd_drain_data(drive, thislen >> 9); | 1022 | ide_pad_transfer(drive, 0, thislen); |
1052 | else { | 1023 | else { |
1053 | printk(KERN_ERR "%s: confused, missing data\n", | 1024 | printk(KERN_ERR "%s: confused, missing data\n", |
1054 | drive->name); | 1025 | drive->name); |
@@ -1096,7 +1067,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1096 | 1067 | ||
1097 | /* pad, if necessary */ | 1068 | /* pad, if necessary */ |
1098 | if (!blk_fs_request(rq) && len > 0) | 1069 | if (!blk_fs_request(rq) && len > 0) |
1099 | ide_cd_pad_transfer(drive, xferfunc, len); | 1070 | ide_pad_transfer(drive, write, len); |
1100 | 1071 | ||
1101 | if (blk_pc_request(rq)) { | 1072 | if (blk_pc_request(rq)) { |
1102 | timeout = rq->timeout; | 1073 | timeout = rq->timeout; |
@@ -1165,21 +1136,17 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) | |||
1165 | if (write) | 1136 | if (write) |
1166 | cd->devinfo.media_written = 1; | 1137 | cd->devinfo.media_written = 1; |
1167 | 1138 | ||
1168 | /* start sending the read/write request to the drive */ | 1139 | return ide_started; |
1169 | return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont); | ||
1170 | } | 1140 | } |
1171 | 1141 | ||
1172 | static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive) | 1142 | static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive) |
1173 | { | 1143 | { |
1174 | struct request *rq = HWGROUP(drive)->rq; | 1144 | struct request *rq = HWGROUP(drive)->rq; |
1175 | 1145 | ||
1176 | if (!rq->timeout) | ||
1177 | rq->timeout = ATAPI_WAIT_PC; | ||
1178 | |||
1179 | return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr); | 1146 | return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr); |
1180 | } | 1147 | } |
1181 | 1148 | ||
1182 | static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) | 1149 | static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) |
1183 | { | 1150 | { |
1184 | struct cdrom_info *info = drive->driver_data; | 1151 | struct cdrom_info *info = drive->driver_data; |
1185 | 1152 | ||
@@ -1191,10 +1158,16 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) | |||
1191 | info->dma = 0; | 1158 | info->dma = 0; |
1192 | 1159 | ||
1193 | /* sg request */ | 1160 | /* sg request */ |
1194 | if (rq->bio) { | 1161 | if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) { |
1195 | int mask = drive->queue->dma_alignment; | 1162 | struct request_queue *q = drive->queue; |
1196 | unsigned long addr = | 1163 | unsigned int alignment; |
1197 | (unsigned long)page_address(bio_page(rq->bio)); | 1164 | unsigned long addr; |
1165 | unsigned long stack_mask = ~(THREAD_SIZE - 1); | ||
1166 | |||
1167 | if (rq->bio) | ||
1168 | addr = (unsigned long)bio_data(rq->bio); | ||
1169 | else | ||
1170 | addr = (unsigned long)rq->data; | ||
1198 | 1171 | ||
1199 | info->dma = drive->using_dma; | 1172 | info->dma = drive->using_dma; |
1200 | 1173 | ||
@@ -1204,23 +1177,25 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) | |||
1204 | * NOTE! The "len" and "addr" checks should possibly have | 1177 | * NOTE! The "len" and "addr" checks should possibly have |
1205 | * separate masks. | 1178 | * separate masks. |
1206 | */ | 1179 | */ |
1207 | if ((rq->data_len & 15) || (addr & mask)) | 1180 | alignment = queue_dma_alignment(q) | q->dma_pad_mask; |
1181 | if (addr & alignment || rq->data_len & alignment) | ||
1208 | info->dma = 0; | 1182 | info->dma = 0; |
1209 | } | ||
1210 | 1183 | ||
1211 | /* start sending the command to the drive */ | 1184 | if (!((addr & stack_mask) ^ |
1212 | return cdrom_start_packet_command(drive, rq->data_len, | 1185 | ((unsigned long)current->stack & stack_mask))) |
1213 | cdrom_do_newpc_cont); | 1186 | info->dma = 0; |
1187 | } | ||
1214 | } | 1188 | } |
1215 | 1189 | ||
1216 | /* | 1190 | /* |
1217 | * cdrom driver request routine. | 1191 | * cdrom driver request routine. |
1218 | */ | 1192 | */ |
1219 | static ide_startstop_t ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq, | 1193 | static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, |
1220 | sector_t block) | 1194 | sector_t block) |
1221 | { | 1195 | { |
1222 | ide_startstop_t action; | ||
1223 | struct cdrom_info *info = drive->driver_data; | 1196 | struct cdrom_info *info = drive->driver_data; |
1197 | ide_handler_t *fn; | ||
1198 | int xferlen; | ||
1224 | 1199 | ||
1225 | if (blk_fs_request(rq)) { | 1200 | if (blk_fs_request(rq)) { |
1226 | if (info->cd_flags & IDE_CD_FLAG_SEEKING) { | 1201 | if (info->cd_flags & IDE_CD_FLAG_SEEKING) { |
@@ -1240,29 +1215,48 @@ static ide_startstop_t ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq, | |||
1240 | } | 1215 | } |
1241 | if (rq_data_dir(rq) == READ && | 1216 | if (rq_data_dir(rq) == READ && |
1242 | IDE_LARGE_SEEK(info->last_block, block, | 1217 | IDE_LARGE_SEEK(info->last_block, block, |
1243 | IDECD_SEEK_THRESHOLD) && | 1218 | IDECD_SEEK_THRESHOLD) && |
1244 | drive->dsc_overlap) | 1219 | drive->dsc_overlap) { |
1245 | action = cdrom_start_seek(drive, block); | 1220 | xferlen = 0; |
1246 | else | 1221 | fn = cdrom_start_seek_continuation; |
1247 | action = cdrom_start_rw(drive, rq); | 1222 | |
1223 | info->dma = 0; | ||
1224 | info->start_seek = jiffies; | ||
1225 | |||
1226 | ide_cd_prepare_seek_request(drive, rq); | ||
1227 | } else { | ||
1228 | xferlen = 32768; | ||
1229 | fn = cdrom_start_rw_cont; | ||
1230 | |||
1231 | if (cdrom_start_rw(drive, rq) == ide_stopped) | ||
1232 | return ide_stopped; | ||
1233 | |||
1234 | if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped) | ||
1235 | return ide_stopped; | ||
1236 | } | ||
1248 | info->last_block = block; | 1237 | info->last_block = block; |
1249 | return action; | ||
1250 | } else if (blk_sense_request(rq) || blk_pc_request(rq) || | 1238 | } else if (blk_sense_request(rq) || blk_pc_request(rq) || |
1251 | rq->cmd_type == REQ_TYPE_ATA_PC) { | 1239 | rq->cmd_type == REQ_TYPE_ATA_PC) { |
1252 | return cdrom_do_block_pc(drive, rq); | 1240 | xferlen = rq->data_len; |
1241 | fn = cdrom_do_newpc_cont; | ||
1242 | |||
1243 | if (!rq->timeout) | ||
1244 | rq->timeout = ATAPI_WAIT_PC; | ||
1245 | |||
1246 | cdrom_do_block_pc(drive, rq); | ||
1253 | } else if (blk_special_request(rq)) { | 1247 | } else if (blk_special_request(rq)) { |
1254 | /* right now this can only be a reset... */ | 1248 | /* right now this can only be a reset... */ |
1255 | cdrom_end_request(drive, 1); | 1249 | cdrom_end_request(drive, 1); |
1256 | return ide_stopped; | 1250 | return ide_stopped; |
1251 | } else { | ||
1252 | blk_dump_rq_flags(rq, "ide-cd bad flags"); | ||
1253 | cdrom_end_request(drive, 0); | ||
1254 | return ide_stopped; | ||
1257 | } | 1255 | } |
1258 | 1256 | ||
1259 | blk_dump_rq_flags(rq, "ide-cd bad flags"); | 1257 | return cdrom_start_packet_command(drive, xferlen, fn); |
1260 | cdrom_end_request(drive, 0); | ||
1261 | return ide_stopped; | ||
1262 | } | 1258 | } |
1263 | 1259 | ||
1264 | |||
1265 | |||
1266 | /* | 1260 | /* |
1267 | * Ioctl handling. | 1261 | * Ioctl handling. |
1268 | * | 1262 | * |
@@ -1872,6 +1866,7 @@ static int ide_cdrom_setup(ide_drive_t *drive) | |||
1872 | 1866 | ||
1873 | blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn); | 1867 | blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn); |
1874 | blk_queue_dma_alignment(drive->queue, 31); | 1868 | blk_queue_dma_alignment(drive->queue, 31); |
1869 | blk_queue_update_dma_pad(drive->queue, 15); | ||
1875 | drive->queue->unplug_delay = (1 * HZ) / 1000; | 1870 | drive->queue->unplug_delay = (1 * HZ) / 1000; |
1876 | if (!drive->queue->unplug_delay) | 1871 | if (!drive->queue->unplug_delay) |
1877 | drive->queue->unplug_delay = 1; | 1872 | drive->queue->unplug_delay = 1; |
@@ -1954,10 +1949,9 @@ static ide_driver_t ide_cdrom_driver = { | |||
1954 | .version = IDECD_VERSION, | 1949 | .version = IDECD_VERSION, |
1955 | .media = ide_cdrom, | 1950 | .media = ide_cdrom, |
1956 | .supports_dsc_overlap = 1, | 1951 | .supports_dsc_overlap = 1, |
1957 | .do_request = ide_do_rw_cdrom, | 1952 | .do_request = ide_cd_do_request, |
1958 | .end_request = ide_end_request, | 1953 | .end_request = ide_end_request, |
1959 | .error = __ide_error, | 1954 | .error = __ide_error, |
1960 | .abort = __ide_abort, | ||
1961 | #ifdef CONFIG_IDE_PROC_FS | 1955 | #ifdef CONFIG_IDE_PROC_FS |
1962 | .proc = idecd_proc, | 1956 | .proc = idecd_proc, |
1963 | #endif | 1957 | #endif |