diff options
Diffstat (limited to 'drivers/ide/ide-io.c')
-rw-r--r-- | drivers/ide/ide-io.c | 323 |
1 files changed, 30 insertions, 293 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 9ee51adf567..2e92497b58a 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -196,7 +196,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) | |||
196 | } | 196 | } |
197 | EXPORT_SYMBOL(ide_end_drive_cmd); | 197 | EXPORT_SYMBOL(ide_end_drive_cmd); |
198 | 198 | ||
199 | static void ide_kill_rq(ide_drive_t *drive, struct request *rq) | 199 | void ide_kill_rq(ide_drive_t *drive, struct request *rq) |
200 | { | 200 | { |
201 | if (rq->rq_disk) { | 201 | if (rq->rq_disk) { |
202 | struct ide_driver *drv; | 202 | struct ide_driver *drv; |
@@ -207,133 +207,6 @@ static void ide_kill_rq(ide_drive_t *drive, struct request *rq) | |||
207 | ide_end_request(drive, 0, 0); | 207 | ide_end_request(drive, 0, 0); |
208 | } | 208 | } |
209 | 209 | ||
210 | static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) | ||
211 | { | ||
212 | ide_hwif_t *hwif = drive->hwif; | ||
213 | |||
214 | if ((stat & ATA_BUSY) || | ||
215 | ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { | ||
216 | /* other bits are useless when BUSY */ | ||
217 | rq->errors |= ERROR_RESET; | ||
218 | } else if (stat & ATA_ERR) { | ||
219 | /* err has different meaning on cdrom and tape */ | ||
220 | if (err == ATA_ABORTED) { | ||
221 | if ((drive->dev_flags & IDE_DFLAG_LBA) && | ||
222 | /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */ | ||
223 | hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS) | ||
224 | return ide_stopped; | ||
225 | } else if ((err & BAD_CRC) == BAD_CRC) { | ||
226 | /* UDMA crc error, just retry the operation */ | ||
227 | drive->crc_count++; | ||
228 | } else if (err & (ATA_BBK | ATA_UNC)) { | ||
229 | /* retries won't help these */ | ||
230 | rq->errors = ERROR_MAX; | ||
231 | } else if (err & ATA_TRK0NF) { | ||
232 | /* help it find track zero */ | ||
233 | rq->errors |= ERROR_RECAL; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ && | ||
238 | (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) { | ||
239 | int nsect = drive->mult_count ? drive->mult_count : 1; | ||
240 | |||
241 | ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE); | ||
242 | } | ||
243 | |||
244 | if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) { | ||
245 | ide_kill_rq(drive, rq); | ||
246 | return ide_stopped; | ||
247 | } | ||
248 | |||
249 | if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) | ||
250 | rq->errors |= ERROR_RESET; | ||
251 | |||
252 | if ((rq->errors & ERROR_RESET) == ERROR_RESET) { | ||
253 | ++rq->errors; | ||
254 | return ide_do_reset(drive); | ||
255 | } | ||
256 | |||
257 | if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) | ||
258 | drive->special.b.recalibrate = 1; | ||
259 | |||
260 | ++rq->errors; | ||
261 | |||
262 | return ide_stopped; | ||
263 | } | ||
264 | |||
265 | static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) | ||
266 | { | ||
267 | ide_hwif_t *hwif = drive->hwif; | ||
268 | |||
269 | if ((stat & ATA_BUSY) || | ||
270 | ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { | ||
271 | /* other bits are useless when BUSY */ | ||
272 | rq->errors |= ERROR_RESET; | ||
273 | } else { | ||
274 | /* add decoding error stuff */ | ||
275 | } | ||
276 | |||
277 | if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) | ||
278 | /* force an abort */ | ||
279 | hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE); | ||
280 | |||
281 | if (rq->errors >= ERROR_MAX) { | ||
282 | ide_kill_rq(drive, rq); | ||
283 | } else { | ||
284 | if ((rq->errors & ERROR_RESET) == ERROR_RESET) { | ||
285 | ++rq->errors; | ||
286 | return ide_do_reset(drive); | ||
287 | } | ||
288 | ++rq->errors; | ||
289 | } | ||
290 | |||
291 | return ide_stopped; | ||
292 | } | ||
293 | |||
294 | static ide_startstop_t | ||
295 | __ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) | ||
296 | { | ||
297 | if (drive->media == ide_disk) | ||
298 | return ide_ata_error(drive, rq, stat, err); | ||
299 | return ide_atapi_error(drive, rq, stat, err); | ||
300 | } | ||
301 | |||
302 | /** | ||
303 | * ide_error - handle an error on the IDE | ||
304 | * @drive: drive the error occurred on | ||
305 | * @msg: message to report | ||
306 | * @stat: status bits | ||
307 | * | ||
308 | * ide_error() takes action based on the error returned by the drive. | ||
309 | * For normal I/O that may well include retries. We deal with | ||
310 | * both new-style (taskfile) and old style command handling here. | ||
311 | * In the case of taskfile command handling there is work left to | ||
312 | * do | ||
313 | */ | ||
314 | |||
315 | ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat) | ||
316 | { | ||
317 | struct request *rq; | ||
318 | u8 err; | ||
319 | |||
320 | err = ide_dump_status(drive, msg, stat); | ||
321 | |||
322 | rq = drive->hwif->rq; | ||
323 | if (rq == NULL) | ||
324 | return ide_stopped; | ||
325 | |||
326 | /* retry only "normal" I/O: */ | ||
327 | if (!blk_fs_request(rq)) { | ||
328 | rq->errors = 1; | ||
329 | ide_end_drive_cmd(drive, stat, err); | ||
330 | return ide_stopped; | ||
331 | } | ||
332 | |||
333 | return __ide_error(drive, rq, stat, err); | ||
334 | } | ||
335 | EXPORT_SYMBOL_GPL(ide_error); | ||
336 | |||
337 | static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) | 210 | static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) |
338 | { | 211 | { |
339 | tf->nsect = drive->sect; | 212 | tf->nsect = drive->sect; |
@@ -490,71 +363,16 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, | |||
490 | return ide_stopped; | 363 | return ide_stopped; |
491 | } | 364 | } |
492 | 365 | ||
493 | int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, | ||
494 | int arg) | ||
495 | { | ||
496 | struct request_queue *q = drive->queue; | ||
497 | struct request *rq; | ||
498 | int ret = 0; | ||
499 | |||
500 | if (!(setting->flags & DS_SYNC)) | ||
501 | return setting->set(drive, arg); | ||
502 | |||
503 | rq = blk_get_request(q, READ, __GFP_WAIT); | ||
504 | rq->cmd_type = REQ_TYPE_SPECIAL; | ||
505 | rq->cmd_len = 5; | ||
506 | rq->cmd[0] = REQ_DEVSET_EXEC; | ||
507 | *(int *)&rq->cmd[1] = arg; | ||
508 | rq->special = setting->set; | ||
509 | |||
510 | if (blk_execute_rq(q, NULL, rq, 0)) | ||
511 | ret = rq->errors; | ||
512 | blk_put_request(rq); | ||
513 | |||
514 | return ret; | ||
515 | } | ||
516 | EXPORT_SYMBOL_GPL(ide_devset_execute); | ||
517 | |||
518 | static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) | 366 | static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) |
519 | { | 367 | { |
520 | u8 cmd = rq->cmd[0]; | 368 | u8 cmd = rq->cmd[0]; |
521 | 369 | ||
522 | if (cmd == REQ_PARK_HEADS || cmd == REQ_UNPARK_HEADS) { | ||
523 | ide_task_t task; | ||
524 | struct ide_taskfile *tf = &task.tf; | ||
525 | |||
526 | memset(&task, 0, sizeof(task)); | ||
527 | if (cmd == REQ_PARK_HEADS) { | ||
528 | drive->sleep = *(unsigned long *)rq->special; | ||
529 | drive->dev_flags |= IDE_DFLAG_SLEEPING; | ||
530 | tf->command = ATA_CMD_IDLEIMMEDIATE; | ||
531 | tf->feature = 0x44; | ||
532 | tf->lbal = 0x4c; | ||
533 | tf->lbam = 0x4e; | ||
534 | tf->lbah = 0x55; | ||
535 | task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER; | ||
536 | } else /* cmd == REQ_UNPARK_HEADS */ | ||
537 | tf->command = ATA_CMD_CHK_POWER; | ||
538 | |||
539 | task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | ||
540 | task.rq = rq; | ||
541 | drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA; | ||
542 | return do_rw_taskfile(drive, &task); | ||
543 | } | ||
544 | |||
545 | switch (cmd) { | 370 | switch (cmd) { |
371 | case REQ_PARK_HEADS: | ||
372 | case REQ_UNPARK_HEADS: | ||
373 | return ide_do_park_unpark(drive, rq); | ||
546 | case REQ_DEVSET_EXEC: | 374 | case REQ_DEVSET_EXEC: |
547 | { | 375 | return ide_do_devset(drive, rq); |
548 | int err, (*setfunc)(ide_drive_t *, int) = rq->special; | ||
549 | |||
550 | err = setfunc(drive, *(int *)&rq->cmd[1]); | ||
551 | if (err) | ||
552 | rq->errors = err; | ||
553 | else | ||
554 | err = 1; | ||
555 | ide_end_request(drive, err, 0); | ||
556 | return ide_stopped; | ||
557 | } | ||
558 | case REQ_DRIVE_RESET: | 376 | case REQ_DRIVE_RESET: |
559 | return ide_do_reset(drive); | 377 | return ide_do_reset(drive); |
560 | default: | 378 | default: |
@@ -820,63 +638,6 @@ plug_device_2: | |||
820 | blk_plug_device(q); | 638 | blk_plug_device(q); |
821 | } | 639 | } |
822 | 640 | ||
823 | /* | ||
824 | * un-busy the port etc, and clear any pending DMA status. we want to | ||
825 | * retry the current request in pio mode instead of risking tossing it | ||
826 | * all away | ||
827 | */ | ||
828 | static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) | ||
829 | { | ||
830 | ide_hwif_t *hwif = drive->hwif; | ||
831 | struct request *rq; | ||
832 | ide_startstop_t ret = ide_stopped; | ||
833 | |||
834 | /* | ||
835 | * end current dma transaction | ||
836 | */ | ||
837 | |||
838 | if (error < 0) { | ||
839 | printk(KERN_WARNING "%s: DMA timeout error\n", drive->name); | ||
840 | (void)hwif->dma_ops->dma_end(drive); | ||
841 | ret = ide_error(drive, "dma timeout error", | ||
842 | hwif->tp_ops->read_status(hwif)); | ||
843 | } else { | ||
844 | printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name); | ||
845 | hwif->dma_ops->dma_timeout(drive); | ||
846 | } | ||
847 | |||
848 | /* | ||
849 | * disable dma for now, but remember that we did so because of | ||
850 | * a timeout -- we'll reenable after we finish this next request | ||
851 | * (or rather the first chunk of it) in pio. | ||
852 | */ | ||
853 | drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY; | ||
854 | drive->retry_pio++; | ||
855 | ide_dma_off_quietly(drive); | ||
856 | |||
857 | /* | ||
858 | * un-busy drive etc and make sure request is sane | ||
859 | */ | ||
860 | |||
861 | rq = hwif->rq; | ||
862 | if (!rq) | ||
863 | goto out; | ||
864 | |||
865 | hwif->rq = NULL; | ||
866 | |||
867 | rq->errors = 0; | ||
868 | |||
869 | if (!rq->bio) | ||
870 | goto out; | ||
871 | |||
872 | rq->sector = rq->bio->bi_sector; | ||
873 | rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; | ||
874 | rq->hard_cur_sectors = rq->current_nr_sectors; | ||
875 | rq->buffer = bio_data(rq->bio); | ||
876 | out: | ||
877 | return ret; | ||
878 | } | ||
879 | |||
880 | static void ide_plug_device(ide_drive_t *drive) | 641 | static void ide_plug_device(ide_drive_t *drive) |
881 | { | 642 | { |
882 | struct request_queue *q = drive->queue; | 643 | struct request_queue *q = drive->queue; |
@@ -888,6 +649,29 @@ static void ide_plug_device(ide_drive_t *drive) | |||
888 | spin_unlock_irqrestore(q->queue_lock, flags); | 649 | spin_unlock_irqrestore(q->queue_lock, flags); |
889 | } | 650 | } |
890 | 651 | ||
652 | static int drive_is_ready(ide_drive_t *drive) | ||
653 | { | ||
654 | ide_hwif_t *hwif = drive->hwif; | ||
655 | u8 stat = 0; | ||
656 | |||
657 | if (drive->waiting_for_dma) | ||
658 | return hwif->dma_ops->dma_test_irq(drive); | ||
659 | |||
660 | if (hwif->io_ports.ctl_addr && | ||
661 | (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) | ||
662 | stat = hwif->tp_ops->read_altstatus(hwif); | ||
663 | else | ||
664 | /* Note: this may clear a pending IRQ!! */ | ||
665 | stat = hwif->tp_ops->read_status(hwif); | ||
666 | |||
667 | if (stat & ATA_BUSY) | ||
668 | /* drive busy: definitely not interrupting */ | ||
669 | return 0; | ||
670 | |||
671 | /* drive ready: *might* be interrupting */ | ||
672 | return 1; | ||
673 | } | ||
674 | |||
891 | /** | 675 | /** |
892 | * ide_timer_expiry - handle lack of an IDE interrupt | 676 | * ide_timer_expiry - handle lack of an IDE interrupt |
893 | * @data: timer callback magic (hwif) | 677 | * @data: timer callback magic (hwif) |
@@ -908,7 +692,7 @@ void ide_timer_expiry (unsigned long data) | |||
908 | ide_drive_t *uninitialized_var(drive); | 692 | ide_drive_t *uninitialized_var(drive); |
909 | ide_handler_t *handler; | 693 | ide_handler_t *handler; |
910 | unsigned long flags; | 694 | unsigned long flags; |
911 | unsigned long wait = -1; | 695 | int wait = -1; |
912 | int plug_device = 0; | 696 | int plug_device = 0; |
913 | 697 | ||
914 | spin_lock_irqsave(&hwif->lock, flags); | 698 | spin_lock_irqsave(&hwif->lock, flags); |
@@ -1162,54 +946,7 @@ out_early: | |||
1162 | 946 | ||
1163 | return irq_ret; | 947 | return irq_ret; |
1164 | } | 948 | } |
1165 | 949 | EXPORT_SYMBOL_GPL(ide_intr); | |
1166 | /** | ||
1167 | * ide_do_drive_cmd - issue IDE special command | ||
1168 | * @drive: device to issue command | ||
1169 | * @rq: request to issue | ||
1170 | * | ||
1171 | * This function issues a special IDE device request | ||
1172 | * onto the request queue. | ||
1173 | * | ||
1174 | * the rq is queued at the head of the request queue, displacing | ||
1175 | * the currently-being-processed request and this function | ||
1176 | * returns immediately without waiting for the new rq to be | ||
1177 | * completed. This is VERY DANGEROUS, and is intended for | ||
1178 | * careful use by the ATAPI tape/cdrom driver code. | ||
1179 | */ | ||
1180 | |||
1181 | void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq) | ||
1182 | { | ||
1183 | struct request_queue *q = drive->queue; | ||
1184 | unsigned long flags; | ||
1185 | |||
1186 | drive->hwif->rq = NULL; | ||
1187 | |||
1188 | spin_lock_irqsave(q->queue_lock, flags); | ||
1189 | __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); | ||
1190 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
1191 | } | ||
1192 | EXPORT_SYMBOL(ide_do_drive_cmd); | ||
1193 | |||
1194 | void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma) | ||
1195 | { | ||
1196 | ide_hwif_t *hwif = drive->hwif; | ||
1197 | ide_task_t task; | ||
1198 | |||
1199 | memset(&task, 0, sizeof(task)); | ||
1200 | task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM | | ||
1201 | IDE_TFLAG_OUT_FEATURE | tf_flags; | ||
1202 | task.tf.feature = dma; /* Use PIO/DMA */ | ||
1203 | task.tf.lbam = bcount & 0xff; | ||
1204 | task.tf.lbah = (bcount >> 8) & 0xff; | ||
1205 | |||
1206 | ide_tf_dump(drive->name, &task.tf); | ||
1207 | hwif->tp_ops->set_irq(hwif, 1); | ||
1208 | SELECT_MASK(drive, 0); | ||
1209 | hwif->tp_ops->tf_load(drive, &task); | ||
1210 | } | ||
1211 | |||
1212 | EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load); | ||
1213 | 950 | ||
1214 | void ide_pad_transfer(ide_drive_t *drive, int write, int len) | 951 | void ide_pad_transfer(ide_drive_t *drive, int write, int len) |
1215 | { | 952 | { |