diff options
Diffstat (limited to 'drivers/ide/ide-io.c')
-rw-r--r-- | drivers/ide/ide-io.c | 293 |
1 files changed, 139 insertions, 154 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index bef781fec500..2711b5a6962d 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -189,18 +189,14 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * | |||
189 | return ide_stopped; | 189 | return ide_stopped; |
190 | } | 190 | } |
191 | if (ide_id_has_flush_cache_ext(drive->id)) | 191 | if (ide_id_has_flush_cache_ext(drive->id)) |
192 | args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; | 192 | args->tf.command = WIN_FLUSH_CACHE_EXT; |
193 | else | 193 | else |
194 | args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; | 194 | args->tf.command = WIN_FLUSH_CACHE; |
195 | args->command_type = IDE_DRIVE_TASK_NO_DATA; | 195 | goto out_do_tf; |
196 | args->handler = &task_no_data_intr; | ||
197 | return do_rw_taskfile(drive, args); | ||
198 | 196 | ||
199 | case idedisk_pm_standby: /* Suspend step 2 (standby) */ | 197 | case idedisk_pm_standby: /* Suspend step 2 (standby) */ |
200 | args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1; | 198 | args->tf.command = WIN_STANDBYNOW1; |
201 | args->command_type = IDE_DRIVE_TASK_NO_DATA; | 199 | goto out_do_tf; |
202 | args->handler = &task_no_data_intr; | ||
203 | return do_rw_taskfile(drive, args); | ||
204 | 200 | ||
205 | case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */ | 201 | case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */ |
206 | ide_set_max_pio(drive); | 202 | ide_set_max_pio(drive); |
@@ -214,10 +210,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * | |||
214 | return ide_stopped; | 210 | return ide_stopped; |
215 | 211 | ||
216 | case idedisk_pm_idle: /* Resume step 2 (idle) */ | 212 | case idedisk_pm_idle: /* Resume step 2 (idle) */ |
217 | args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE; | 213 | args->tf.command = WIN_IDLEIMMEDIATE; |
218 | args->command_type = IDE_DRIVE_TASK_NO_DATA; | 214 | goto out_do_tf; |
219 | args->handler = task_no_data_intr; | ||
220 | return do_rw_taskfile(drive, args); | ||
221 | 215 | ||
222 | case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */ | 216 | case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */ |
223 | /* | 217 | /* |
@@ -227,7 +221,6 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * | |||
227 | */ | 221 | */ |
228 | if (drive->hwif->ide_dma_on == NULL) | 222 | if (drive->hwif->ide_dma_on == NULL) |
229 | break; | 223 | break; |
230 | drive->hwif->dma_off_quietly(drive); | ||
231 | /* | 224 | /* |
232 | * TODO: respect ->using_dma setting | 225 | * TODO: respect ->using_dma setting |
233 | */ | 226 | */ |
@@ -236,6 +229,11 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * | |||
236 | } | 229 | } |
237 | pm->pm_step = ide_pm_state_completed; | 230 | pm->pm_step = ide_pm_state_completed; |
238 | return ide_stopped; | 231 | return ide_stopped; |
232 | |||
233 | out_do_tf: | ||
234 | args->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; | ||
235 | args->data_phase = TASKFILE_NO_DATA; | ||
236 | return do_rw_taskfile(drive, args); | ||
239 | } | 237 | } |
240 | 238 | ||
241 | /** | 239 | /** |
@@ -298,6 +296,48 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq) | |||
298 | spin_unlock_irqrestore(&ide_lock, flags); | 296 | spin_unlock_irqrestore(&ide_lock, flags); |
299 | } | 297 | } |
300 | 298 | ||
299 | void ide_tf_read(ide_drive_t *drive, ide_task_t *task) | ||
300 | { | ||
301 | ide_hwif_t *hwif = drive->hwif; | ||
302 | struct ide_taskfile *tf = &task->tf; | ||
303 | |||
304 | if (task->tf_flags & IDE_TFLAG_IN_DATA) { | ||
305 | u16 data = hwif->INW(IDE_DATA_REG); | ||
306 | |||
307 | tf->data = data & 0xff; | ||
308 | tf->hob_data = (data >> 8) & 0xff; | ||
309 | } | ||
310 | |||
311 | /* be sure we're looking at the low order bits */ | ||
312 | hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG); | ||
313 | |||
314 | if (task->tf_flags & IDE_TFLAG_IN_NSECT) | ||
315 | tf->nsect = hwif->INB(IDE_NSECTOR_REG); | ||
316 | if (task->tf_flags & IDE_TFLAG_IN_LBAL) | ||
317 | tf->lbal = hwif->INB(IDE_SECTOR_REG); | ||
318 | if (task->tf_flags & IDE_TFLAG_IN_LBAM) | ||
319 | tf->lbam = hwif->INB(IDE_LCYL_REG); | ||
320 | if (task->tf_flags & IDE_TFLAG_IN_LBAH) | ||
321 | tf->lbah = hwif->INB(IDE_HCYL_REG); | ||
322 | if (task->tf_flags & IDE_TFLAG_IN_DEVICE) | ||
323 | tf->device = hwif->INB(IDE_SELECT_REG); | ||
324 | |||
325 | if (task->tf_flags & IDE_TFLAG_LBA48) { | ||
326 | hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG); | ||
327 | |||
328 | if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | ||
329 | tf->hob_feature = hwif->INB(IDE_FEATURE_REG); | ||
330 | if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
331 | tf->hob_nsect = hwif->INB(IDE_NSECTOR_REG); | ||
332 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
333 | tf->hob_lbal = hwif->INB(IDE_SECTOR_REG); | ||
334 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
335 | tf->hob_lbam = hwif->INB(IDE_LCYL_REG); | ||
336 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
337 | tf->hob_lbah = hwif->INB(IDE_HCYL_REG); | ||
338 | } | ||
339 | } | ||
340 | |||
301 | /** | 341 | /** |
302 | * ide_end_drive_cmd - end an explicit drive command | 342 | * ide_end_drive_cmd - end an explicit drive command |
303 | * @drive: command | 343 | * @drive: command |
@@ -332,51 +372,22 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) | |||
332 | args[1] = err; | 372 | args[1] = err; |
333 | args[2] = hwif->INB(IDE_NSECTOR_REG); | 373 | args[2] = hwif->INB(IDE_NSECTOR_REG); |
334 | } | 374 | } |
335 | } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) { | ||
336 | u8 *args = (u8 *) rq->buffer; | ||
337 | if (rq->errors == 0) | ||
338 | rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); | ||
339 | |||
340 | if (args) { | ||
341 | args[0] = stat; | ||
342 | args[1] = err; | ||
343 | /* be sure we're looking at the low order bits */ | ||
344 | hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG); | ||
345 | args[2] = hwif->INB(IDE_NSECTOR_REG); | ||
346 | args[3] = hwif->INB(IDE_SECTOR_REG); | ||
347 | args[4] = hwif->INB(IDE_LCYL_REG); | ||
348 | args[5] = hwif->INB(IDE_HCYL_REG); | ||
349 | args[6] = hwif->INB(IDE_SELECT_REG); | ||
350 | } | ||
351 | } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { | 375 | } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { |
352 | ide_task_t *args = (ide_task_t *) rq->special; | 376 | ide_task_t *args = (ide_task_t *) rq->special; |
353 | if (rq->errors == 0) | 377 | if (rq->errors == 0) |
354 | rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); | 378 | rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); |
355 | 379 | ||
356 | if (args) { | 380 | if (args) { |
357 | if (args->tf_in_flags.b.data) { | 381 | struct ide_taskfile *tf = &args->tf; |
358 | u16 data = hwif->INW(IDE_DATA_REG); | 382 | |
359 | args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; | 383 | tf->error = err; |
360 | args->hobRegister[IDE_DATA_OFFSET] = (data >> 8) & 0xFF; | 384 | tf->status = stat; |
361 | } | 385 | |
362 | args->tfRegister[IDE_ERROR_OFFSET] = err; | 386 | args->tf_flags |= (IDE_TFLAG_IN_TF|IDE_TFLAG_IN_DEVICE); |
363 | /* be sure we're looking at the low order bits */ | 387 | if (args->tf_flags & IDE_TFLAG_LBA48) |
364 | hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG); | 388 | args->tf_flags |= IDE_TFLAG_IN_HOB; |
365 | args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); | 389 | |
366 | args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); | 390 | ide_tf_read(drive, args); |
367 | args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); | ||
368 | args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG); | ||
369 | args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG); | ||
370 | args->tfRegister[IDE_STATUS_OFFSET] = stat; | ||
371 | |||
372 | if (drive->addressing == 1) { | ||
373 | hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); | ||
374 | args->hobRegister[IDE_FEATURE_OFFSET] = hwif->INB(IDE_FEATURE_REG); | ||
375 | args->hobRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); | ||
376 | args->hobRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); | ||
377 | args->hobRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); | ||
378 | args->hobRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG); | ||
379 | } | ||
380 | } | 391 | } |
381 | } else if (blk_pm_request(rq)) { | 392 | } else if (blk_pm_request(rq)) { |
382 | struct request_pm_state *pm = rq->data; | 393 | struct request_pm_state *pm = rq->data; |
@@ -616,28 +627,6 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg) | |||
616 | } | 627 | } |
617 | 628 | ||
618 | /** | 629 | /** |
619 | * ide_cmd - issue a simple drive command | ||
620 | * @drive: drive the command is for | ||
621 | * @cmd: command byte | ||
622 | * @nsect: sector byte | ||
623 | * @handler: handler for the command completion | ||
624 | * | ||
625 | * Issue a simple drive command with interrupts. | ||
626 | * The drive must be selected beforehand. | ||
627 | */ | ||
628 | |||
629 | static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, | ||
630 | ide_handler_t *handler) | ||
631 | { | ||
632 | ide_hwif_t *hwif = HWIF(drive); | ||
633 | if (IDE_CONTROL_REG) | ||
634 | hwif->OUTB(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ | ||
635 | SELECT_MASK(drive,0); | ||
636 | hwif->OUTB(nsect,IDE_NSECTOR_REG); | ||
637 | ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL); | ||
638 | } | ||
639 | |||
640 | /** | ||
641 | * drive_cmd_intr - drive command completion interrupt | 630 | * drive_cmd_intr - drive command completion interrupt |
642 | * @drive: drive the completion interrupt occurred on | 631 | * @drive: drive the completion interrupt occurred on |
643 | * | 632 | * |
@@ -673,32 +662,26 @@ static ide_startstop_t drive_cmd_intr (ide_drive_t *drive) | |||
673 | return ide_stopped; | 662 | return ide_stopped; |
674 | } | 663 | } |
675 | 664 | ||
676 | static void ide_init_specify_cmd(ide_drive_t *drive, ide_task_t *task) | 665 | static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) |
677 | { | 666 | { |
678 | task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; | 667 | tf->nsect = drive->sect; |
679 | task->tfRegister[IDE_SECTOR_OFFSET] = drive->sect; | 668 | tf->lbal = drive->sect; |
680 | task->tfRegister[IDE_LCYL_OFFSET] = drive->cyl; | 669 | tf->lbam = drive->cyl; |
681 | task->tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8; | 670 | tf->lbah = drive->cyl >> 8; |
682 | task->tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF; | 671 | tf->device = ((drive->head - 1) | drive->select.all) & ~ATA_LBA; |
683 | task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY; | 672 | tf->command = WIN_SPECIFY; |
684 | |||
685 | task->handler = &set_geometry_intr; | ||
686 | } | 673 | } |
687 | 674 | ||
688 | static void ide_init_restore_cmd(ide_drive_t *drive, ide_task_t *task) | 675 | static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf) |
689 | { | 676 | { |
690 | task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; | 677 | tf->nsect = drive->sect; |
691 | task->tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE; | 678 | tf->command = WIN_RESTORE; |
692 | |||
693 | task->handler = &recal_intr; | ||
694 | } | 679 | } |
695 | 680 | ||
696 | static void ide_init_setmult_cmd(ide_drive_t *drive, ide_task_t *task) | 681 | static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf) |
697 | { | 682 | { |
698 | task->tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req; | 683 | tf->nsect = drive->mult_req; |
699 | task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT; | 684 | tf->command = WIN_SETMULT; |
700 | |||
701 | task->handler = &set_multmode_intr; | ||
702 | } | 685 | } |
703 | 686 | ||
704 | static ide_startstop_t ide_disk_special(ide_drive_t *drive) | 687 | static ide_startstop_t ide_disk_special(ide_drive_t *drive) |
@@ -707,19 +690,19 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive) | |||
707 | ide_task_t args; | 690 | ide_task_t args; |
708 | 691 | ||
709 | memset(&args, 0, sizeof(ide_task_t)); | 692 | memset(&args, 0, sizeof(ide_task_t)); |
710 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | 693 | args.data_phase = TASKFILE_NO_DATA; |
711 | 694 | ||
712 | if (s->b.set_geometry) { | 695 | if (s->b.set_geometry) { |
713 | s->b.set_geometry = 0; | 696 | s->b.set_geometry = 0; |
714 | ide_init_specify_cmd(drive, &args); | 697 | ide_tf_set_specify_cmd(drive, &args.tf); |
715 | } else if (s->b.recalibrate) { | 698 | } else if (s->b.recalibrate) { |
716 | s->b.recalibrate = 0; | 699 | s->b.recalibrate = 0; |
717 | ide_init_restore_cmd(drive, &args); | 700 | ide_tf_set_restore_cmd(drive, &args.tf); |
718 | } else if (s->b.set_multmode) { | 701 | } else if (s->b.set_multmode) { |
719 | s->b.set_multmode = 0; | 702 | s->b.set_multmode = 0; |
720 | if (drive->mult_req > drive->id->max_multsect) | 703 | if (drive->mult_req > drive->id->max_multsect) |
721 | drive->mult_req = drive->id->max_multsect; | 704 | drive->mult_req = drive->id->max_multsect; |
722 | ide_init_setmult_cmd(drive, &args); | 705 | ide_tf_set_setmult_cmd(drive, &args.tf); |
723 | } else if (s->all) { | 706 | } else if (s->all) { |
724 | int special = s->all; | 707 | int special = s->all; |
725 | s->all = 0; | 708 | s->all = 0; |
@@ -727,6 +710,9 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive) | |||
727 | return ide_stopped; | 710 | return ide_stopped; |
728 | } | 711 | } |
729 | 712 | ||
713 | args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE | | ||
714 | IDE_TFLAG_CUSTOM_HANDLER; | ||
715 | |||
730 | do_rw_taskfile(drive, &args); | 716 | do_rw_taskfile(drive, &args); |
731 | 717 | ||
732 | return ide_started; | 718 | return ide_started; |
@@ -861,13 +847,17 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, | |||
861 | struct request *rq) | 847 | struct request *rq) |
862 | { | 848 | { |
863 | ide_hwif_t *hwif = HWIF(drive); | 849 | ide_hwif_t *hwif = HWIF(drive); |
850 | u8 *args = rq->buffer; | ||
851 | ide_task_t ltask; | ||
852 | struct ide_taskfile *tf = <ask.tf; | ||
853 | |||
864 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { | 854 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { |
865 | ide_task_t *args = rq->special; | 855 | ide_task_t *task = rq->special; |
866 | 856 | ||
867 | if (!args) | 857 | if (task == NULL) |
868 | goto done; | 858 | goto done; |
869 | 859 | ||
870 | hwif->data_phase = args->data_phase; | 860 | hwif->data_phase = task->data_phase; |
871 | 861 | ||
872 | switch (hwif->data_phase) { | 862 | switch (hwif->data_phase) { |
873 | case TASKFILE_MULTI_OUT: | 863 | case TASKFILE_MULTI_OUT: |
@@ -880,55 +870,34 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, | |||
880 | break; | 870 | break; |
881 | } | 871 | } |
882 | 872 | ||
883 | if (args->tf_out_flags.all != 0) | 873 | return do_rw_taskfile(drive, task); |
884 | return flagged_taskfile(drive, args); | 874 | } |
885 | return do_rw_taskfile(drive, args); | 875 | |
886 | } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) { | 876 | if (args == NULL) |
887 | u8 *args = rq->buffer; | 877 | goto done; |
888 | 878 | ||
889 | if (!args) | 879 | memset(<ask, 0, sizeof(ltask)); |
890 | goto done; | 880 | if (rq->cmd_type == REQ_TYPE_ATA_CMD) { |
891 | #ifdef DEBUG | ||
892 | printk("%s: DRIVE_TASK_CMD ", drive->name); | ||
893 | printk("cmd=0x%02x ", args[0]); | ||
894 | printk("fr=0x%02x ", args[1]); | ||
895 | printk("ns=0x%02x ", args[2]); | ||
896 | printk("sc=0x%02x ", args[3]); | ||
897 | printk("lcyl=0x%02x ", args[4]); | ||
898 | printk("hcyl=0x%02x ", args[5]); | ||
899 | printk("sel=0x%02x\n", args[6]); | ||
900 | #endif | ||
901 | hwif->OUTB(args[1], IDE_FEATURE_REG); | ||
902 | hwif->OUTB(args[3], IDE_SECTOR_REG); | ||
903 | hwif->OUTB(args[4], IDE_LCYL_REG); | ||
904 | hwif->OUTB(args[5], IDE_HCYL_REG); | ||
905 | hwif->OUTB((args[6] & 0xEF)|drive->select.all, IDE_SELECT_REG); | ||
906 | ide_cmd(drive, args[0], args[2], &drive_cmd_intr); | ||
907 | return ide_started; | ||
908 | } else if (rq->cmd_type == REQ_TYPE_ATA_CMD) { | ||
909 | u8 *args = rq->buffer; | ||
910 | |||
911 | if (!args) | ||
912 | goto done; | ||
913 | #ifdef DEBUG | 881 | #ifdef DEBUG |
914 | printk("%s: DRIVE_CMD ", drive->name); | 882 | printk("%s: DRIVE_CMD\n", drive->name); |
915 | printk("cmd=0x%02x ", args[0]); | ||
916 | printk("sc=0x%02x ", args[1]); | ||
917 | printk("fr=0x%02x ", args[2]); | ||
918 | printk("xx=0x%02x\n", args[3]); | ||
919 | #endif | 883 | #endif |
920 | if (args[0] == WIN_SMART) { | 884 | tf->feature = args[2]; |
921 | hwif->OUTB(0x4f, IDE_LCYL_REG); | 885 | if (args[0] == WIN_SMART) { |
922 | hwif->OUTB(0xc2, IDE_HCYL_REG); | 886 | tf->nsect = args[3]; |
923 | hwif->OUTB(args[2],IDE_FEATURE_REG); | 887 | tf->lbal = args[1]; |
924 | hwif->OUTB(args[1],IDE_SECTOR_REG); | 888 | tf->lbam = 0x4f; |
925 | ide_cmd(drive, args[0], args[3], &drive_cmd_intr); | 889 | tf->lbah = 0xc2; |
926 | return ide_started; | 890 | ltask.tf_flags = IDE_TFLAG_OUT_TF; |
927 | } | 891 | } else { |
928 | hwif->OUTB(args[2],IDE_FEATURE_REG); | 892 | tf->nsect = args[1]; |
929 | ide_cmd(drive, args[0], args[1], &drive_cmd_intr); | 893 | ltask.tf_flags = IDE_TFLAG_OUT_FEATURE | |
930 | return ide_started; | 894 | IDE_TFLAG_OUT_NSECT; |
895 | } | ||
931 | } | 896 | } |
897 | tf->command = args[0]; | ||
898 | ide_tf_load(drive, <ask); | ||
899 | ide_execute_command(drive, args[0], &drive_cmd_intr, WAIT_WORSTCASE, NULL); | ||
900 | return ide_started; | ||
932 | 901 | ||
933 | done: | 902 | done: |
934 | /* | 903 | /* |
@@ -1003,6 +972,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | |||
1003 | 972 | ||
1004 | /* bail early if we've exceeded max_failures */ | 973 | /* bail early if we've exceeded max_failures */ |
1005 | if (drive->max_failures && (drive->failures > drive->max_failures)) { | 974 | if (drive->max_failures && (drive->failures > drive->max_failures)) { |
975 | rq->cmd_flags |= REQ_FAILED; | ||
1006 | goto kill_rq; | 976 | goto kill_rq; |
1007 | } | 977 | } |
1008 | 978 | ||
@@ -1035,7 +1005,6 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | |||
1035 | ide_config_drive_speed(drive, drive->desired_speed); | 1005 | ide_config_drive_speed(drive, drive->desired_speed); |
1036 | 1006 | ||
1037 | if (rq->cmd_type == REQ_TYPE_ATA_CMD || | 1007 | if (rq->cmd_type == REQ_TYPE_ATA_CMD || |
1038 | rq->cmd_type == REQ_TYPE_ATA_TASK || | ||
1039 | rq->cmd_type == REQ_TYPE_ATA_TASKFILE) | 1008 | rq->cmd_type == REQ_TYPE_ATA_TASKFILE) |
1040 | return execute_drive_cmd(drive, rq); | 1009 | return execute_drive_cmd(drive, rq); |
1041 | else if (blk_pm_request(rq)) { | 1010 | else if (blk_pm_request(rq)) { |
@@ -1247,8 +1216,12 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) | |||
1247 | if (hwgroup->hwif->sharing_irq && | 1216 | if (hwgroup->hwif->sharing_irq && |
1248 | hwif != hwgroup->hwif && | 1217 | hwif != hwgroup->hwif && |
1249 | hwif->io_ports[IDE_CONTROL_OFFSET]) { | 1218 | hwif->io_ports[IDE_CONTROL_OFFSET]) { |
1250 | /* set nIEN for previous hwif */ | 1219 | /* |
1251 | SELECT_INTERRUPT(drive); | 1220 | * set nIEN for previous hwif, drives in the |
1221 | * quirk_list may not like intr setups/cleanups | ||
1222 | */ | ||
1223 | if (drive->quirk_list != 1) | ||
1224 | hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG); | ||
1252 | } | 1225 | } |
1253 | hwgroup->hwif = hwif; | 1226 | hwgroup->hwif = hwif; |
1254 | hwgroup->drive = drive; | 1227 | hwgroup->drive = drive; |
@@ -1454,12 +1427,8 @@ void ide_timer_expiry (unsigned long data) | |||
1454 | */ | 1427 | */ |
1455 | spin_unlock(&ide_lock); | 1428 | spin_unlock(&ide_lock); |
1456 | hwif = HWIF(drive); | 1429 | hwif = HWIF(drive); |
1457 | #if DISABLE_IRQ_NOSYNC | ||
1458 | disable_irq_nosync(hwif->irq); | ||
1459 | #else | ||
1460 | /* disable_irq_nosync ?? */ | 1430 | /* disable_irq_nosync ?? */ |
1461 | disable_irq(hwif->irq); | 1431 | disable_irq(hwif->irq); |
1462 | #endif /* DISABLE_IRQ_NOSYNC */ | ||
1463 | /* local CPU only, | 1432 | /* local CPU only, |
1464 | * as if we were handling an interrupt */ | 1433 | * as if we were handling an interrupt */ |
1465 | local_irq_disable(); | 1434 | local_irq_disable(); |
@@ -1785,3 +1754,19 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio | |||
1785 | } | 1754 | } |
1786 | 1755 | ||
1787 | EXPORT_SYMBOL(ide_do_drive_cmd); | 1756 | EXPORT_SYMBOL(ide_do_drive_cmd); |
1757 | |||
1758 | void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma) | ||
1759 | { | ||
1760 | ide_task_t task; | ||
1761 | |||
1762 | memset(&task, 0, sizeof(task)); | ||
1763 | task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM | | ||
1764 | IDE_TFLAG_OUT_FEATURE | tf_flags; | ||
1765 | task.tf.feature = dma; /* Use PIO/DMA */ | ||
1766 | task.tf.lbam = bcount & 0xff; | ||
1767 | task.tf.lbah = (bcount >> 8) & 0xff; | ||
1768 | |||
1769 | ide_tf_load(drive, &task); | ||
1770 | } | ||
1771 | |||
1772 | EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load); | ||