diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-01-25 16:17:07 -0500 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-01-25 16:17:07 -0500 |
commit | 74095a91ed02f6727b62d4416be00a041f2d7436 (patch) | |
tree | 033cc52877103739c5b55a2cfdd3bfaf6996d5d3 /drivers/ide/ide-taskfile.c | |
parent | 9a3c49be5c5f7388eefb712be9a383904140532e (diff) |
ide: use do_rw_taskfile() in flagged_taskfile()
Based on the earlier work by Tejun Heo.
* Move setting IDE_TFLAG_LBA48 taskfile flag from do_rw_taskfile()
function to the callers.
* Add IDE_TFLAG_FLAGGED taskfile flag for flagged taskfiles coming
from ide_taskfile_ioctl(). Check it instead of ->tf_out_flags.all.
* Add IDE_TFLAG_OUT_DATA taskfile flag to indicate the need to load
IDE data register in ide_tf_load().
* Add IDE_TFLAG_OUT_* taskfile flags to indicate the need to load
particular IDE taskfile registers in ide_tf_load().
* Update do_rw_taskfile() and ide_tf_load() users to set respective
IDE_TFLAG_OUT_* taksfile flags.
* Add task_dma_ok() helper.
* Use IDE_TFLAG_FLAGGED taskfile flag to select HIHI mask in ide_tf_load().
* Use do_rw_taskfile() in flagged_taskfile().
* Remove no longer needed 'tf_out_flags' field from ide_task_t.
There should be no functionality changes caused by this patch.
Cc: Tejun Heo <htejun@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-taskfile.c')
-rw-r--r-- | drivers/ide/ide-taskfile.c | 180 |
1 files changed, 73 insertions, 107 deletions
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 7cb674f81315..a7668b459fe1 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
@@ -69,25 +69,39 @@ void ide_tf_load(ide_drive_t *drive, ide_task_t *task) | |||
69 | struct ide_taskfile *tf = &task->tf; | 69 | struct ide_taskfile *tf = &task->tf; |
70 | u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; | 70 | u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; |
71 | 71 | ||
72 | if (task->tf_flags & IDE_TFLAG_FLAGGED) | ||
73 | HIHI = 0xFF; | ||
74 | |||
72 | if (IDE_CONTROL_REG) | 75 | if (IDE_CONTROL_REG) |
73 | hwif->OUTB(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ | 76 | hwif->OUTB(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ |
74 | 77 | ||
75 | if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0) | 78 | if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0) |
76 | SELECT_MASK(drive, 0); | 79 | SELECT_MASK(drive, 0); |
77 | 80 | ||
78 | if (task->tf_flags & IDE_TFLAG_LBA48) { | 81 | if (task->tf_flags & IDE_TFLAG_OUT_DATA) |
82 | hwif->OUTW((tf->hob_data << 8) | tf->data, IDE_DATA_REG); | ||
83 | |||
84 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | ||
79 | hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG); | 85 | hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG); |
86 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | ||
80 | hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG); | 87 | hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG); |
88 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) | ||
81 | hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG); | 89 | hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG); |
90 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) | ||
82 | hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG); | 91 | hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG); |
92 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) | ||
83 | hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG); | 93 | hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG); |
84 | } | ||
85 | 94 | ||
86 | hwif->OUTB(tf->feature, IDE_FEATURE_REG); | 95 | if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) |
87 | hwif->OUTB(tf->nsect, IDE_NSECTOR_REG); | 96 | hwif->OUTB(tf->feature, IDE_FEATURE_REG); |
88 | hwif->OUTB(tf->lbal, IDE_SECTOR_REG); | 97 | if (task->tf_flags & IDE_TFLAG_OUT_NSECT) |
89 | hwif->OUTB(tf->lbam, IDE_LCYL_REG); | 98 | hwif->OUTB(tf->nsect, IDE_NSECTOR_REG); |
90 | hwif->OUTB(tf->lbah, IDE_HCYL_REG); | 99 | if (task->tf_flags & IDE_TFLAG_OUT_LBAL) |
100 | hwif->OUTB(tf->lbal, IDE_SECTOR_REG); | ||
101 | if (task->tf_flags & IDE_TFLAG_OUT_LBAM) | ||
102 | hwif->OUTB(tf->lbam, IDE_LCYL_REG); | ||
103 | if (task->tf_flags & IDE_TFLAG_OUT_LBAH) | ||
104 | hwif->OUTB(tf->lbah, IDE_HCYL_REG); | ||
91 | 105 | ||
92 | hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG); | 106 | hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG); |
93 | } | 107 | } |
@@ -110,14 +124,30 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) | |||
110 | return ide_raw_taskfile(drive, &args, buf); | 124 | return ide_raw_taskfile(drive, &args, buf); |
111 | } | 125 | } |
112 | 126 | ||
127 | static int inline task_dma_ok(ide_task_t *task) | ||
128 | { | ||
129 | if (task->tf_flags & IDE_TFLAG_FLAGGED) | ||
130 | return 1; | ||
131 | |||
132 | switch (task->tf.command) { | ||
133 | case WIN_WRITEDMA_ONCE: | ||
134 | case WIN_WRITEDMA: | ||
135 | case WIN_WRITEDMA_EXT: | ||
136 | case WIN_READDMA_ONCE: | ||
137 | case WIN_READDMA: | ||
138 | case WIN_READDMA_EXT: | ||
139 | case WIN_IDENTIFY_DMA: | ||
140 | return 1; | ||
141 | } | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
113 | ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) | 146 | ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) |
114 | { | 147 | { |
115 | ide_hwif_t *hwif = HWIF(drive); | 148 | ide_hwif_t *hwif = HWIF(drive); |
116 | struct ide_taskfile *tf = &task->tf; | 149 | struct ide_taskfile *tf = &task->tf; |
117 | 150 | ||
118 | if (drive->addressing == 1) | ||
119 | task->tf_flags |= IDE_TFLAG_LBA48; | ||
120 | |||
121 | ide_tf_load(drive, task); | 151 | ide_tf_load(drive, task); |
122 | 152 | ||
123 | if (task->handler != NULL) { | 153 | if (task->handler != NULL) { |
@@ -130,26 +160,10 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) | |||
130 | return ide_started; | 160 | return ide_started; |
131 | } | 161 | } |
132 | 162 | ||
133 | if (!drive->using_dma) | 163 | if (task_dma_ok(task) && drive->using_dma && !hwif->dma_setup(drive)) { |
134 | return ide_stopped; | 164 | hwif->dma_exec_cmd(drive, tf->command); |
135 | 165 | hwif->dma_start(drive); | |
136 | switch (tf->command) { | 166 | return ide_started; |
137 | case WIN_WRITEDMA_ONCE: | ||
138 | case WIN_WRITEDMA: | ||
139 | case WIN_WRITEDMA_EXT: | ||
140 | case WIN_READDMA_ONCE: | ||
141 | case WIN_READDMA: | ||
142 | case WIN_READDMA_EXT: | ||
143 | case WIN_IDENTIFY_DMA: | ||
144 | if (!hwif->dma_setup(drive)) { | ||
145 | hwif->dma_exec_cmd(drive, tf->command); | ||
146 | hwif->dma_start(drive); | ||
147 | return ide_started; | ||
148 | } | ||
149 | break; | ||
150 | default: | ||
151 | if (task->handler == NULL) | ||
152 | return ide_stopped; | ||
153 | } | 167 | } |
154 | 168 | ||
155 | return ide_stopped; | 169 | return ide_stopped; |
@@ -373,7 +387,7 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) | |||
373 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { | 387 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { |
374 | ide_task_t *task = rq->special; | 388 | ide_task_t *task = rq->special; |
375 | 389 | ||
376 | if (task->tf_out_flags.all) { | 390 | if (task->tf_flags & IDE_TFLAG_FLAGGED) { |
377 | u8 err = drive->hwif->INB(IDE_ERROR_REG); | 391 | u8 err = drive->hwif->INB(IDE_ERROR_REG); |
378 | ide_end_drive_cmd(drive, stat, err); | 392 | ide_end_drive_cmd(drive, stat, err); |
379 | return; | 393 | return; |
@@ -594,10 +608,36 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) | |||
594 | memcpy(&args.tf_array[0], req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2); | 608 | memcpy(&args.tf_array[0], req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2); |
595 | memcpy(&args.tf_array[6], req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE); | 609 | memcpy(&args.tf_array[6], req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE); |
596 | args.tf_in_flags = req_task->in_flags; | 610 | args.tf_in_flags = req_task->in_flags; |
597 | args.tf_out_flags = req_task->out_flags; | ||
598 | args.data_phase = req_task->data_phase; | 611 | args.data_phase = req_task->data_phase; |
599 | args.command_type = req_task->req_cmd; | 612 | args.command_type = req_task->req_cmd; |
600 | 613 | ||
614 | if (req_task->out_flags.all) { | ||
615 | args.tf_flags |= IDE_TFLAG_FLAGGED; | ||
616 | |||
617 | if (req_task->out_flags.b.data) | ||
618 | args.tf_flags |= IDE_TFLAG_OUT_DATA; | ||
619 | |||
620 | if (req_task->out_flags.b.nsector_hob) | ||
621 | args.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT; | ||
622 | if (req_task->out_flags.b.sector_hob) | ||
623 | args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL; | ||
624 | if (req_task->out_flags.b.lcyl_hob) | ||
625 | args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM; | ||
626 | if (req_task->out_flags.b.hcyl_hob) | ||
627 | args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH; | ||
628 | |||
629 | if (req_task->out_flags.b.error_feature) | ||
630 | args.tf_flags |= IDE_TFLAG_OUT_FEATURE; | ||
631 | if (req_task->out_flags.b.nsector) | ||
632 | args.tf_flags |= IDE_TFLAG_OUT_NSECT; | ||
633 | if (req_task->out_flags.b.sector) | ||
634 | args.tf_flags |= IDE_TFLAG_OUT_LBAL; | ||
635 | if (req_task->out_flags.b.lcyl) | ||
636 | args.tf_flags |= IDE_TFLAG_OUT_LBAM; | ||
637 | if (req_task->out_flags.b.hcyl) | ||
638 | args.tf_flags |= IDE_TFLAG_OUT_LBAH; | ||
639 | } | ||
640 | |||
601 | drive->io_32bit = 0; | 641 | drive->io_32bit = 0; |
602 | switch(req_task->data_phase) { | 642 | switch(req_task->data_phase) { |
603 | case TASKFILE_OUT_DMAQ: | 643 | case TASKFILE_OUT_DMAQ: |
@@ -649,7 +689,6 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) | |||
649 | memcpy(req_task->hob_ports, &args.tf_array[0], HDIO_DRIVE_HOB_HDR_SIZE - 2); | 689 | memcpy(req_task->hob_ports, &args.tf_array[0], HDIO_DRIVE_HOB_HDR_SIZE - 2); |
650 | memcpy(req_task->io_ports, &args.tf_array[6], HDIO_DRIVE_TASK_HDR_SIZE); | 690 | memcpy(req_task->io_ports, &args.tf_array[6], HDIO_DRIVE_TASK_HDR_SIZE); |
651 | req_task->in_flags = args.tf_in_flags; | 691 | req_task->in_flags = args.tf_in_flags; |
652 | req_task->out_flags = args.tf_out_flags; | ||
653 | 692 | ||
654 | if (copy_to_user(buf, req_task, tasksize)) { | 693 | if (copy_to_user(buf, req_task, tasksize)) { |
655 | err = -EFAULT; | 694 | err = -EFAULT; |
@@ -782,9 +821,6 @@ int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) | |||
782 | */ | 821 | */ |
783 | ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) | 822 | ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) |
784 | { | 823 | { |
785 | ide_hwif_t *hwif = HWIF(drive); | ||
786 | struct ide_taskfile *tf = &task->tf; | ||
787 | |||
788 | if (task->data_phase == TASKFILE_MULTI_IN || | 824 | if (task->data_phase == TASKFILE_MULTI_IN || |
789 | task->data_phase == TASKFILE_MULTI_OUT) { | 825 | task->data_phase == TASKFILE_MULTI_OUT) { |
790 | if (!drive->mult_count) { | 826 | if (!drive->mult_count) { |
@@ -807,75 +843,5 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) | |||
807 | task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8); | 843 | task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8); |
808 | } | 844 | } |
809 | 845 | ||
810 | /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ | 846 | return do_rw_taskfile(drive, task); |
811 | if (IDE_CONTROL_REG) | ||
812 | /* clear nIEN */ | ||
813 | hwif->OUTB(drive->ctl, IDE_CONTROL_REG); | ||
814 | SELECT_MASK(drive, 0); | ||
815 | |||
816 | if (task->tf_out_flags.b.data) | ||
817 | hwif->OUTW((tf->hob_data << 8) | tf->data, IDE_DATA_REG); | ||
818 | |||
819 | /* (ks) send hob registers first */ | ||
820 | if (task->tf_out_flags.b.nsector_hob) | ||
821 | hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG); | ||
822 | if (task->tf_out_flags.b.sector_hob) | ||
823 | hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG); | ||
824 | if (task->tf_out_flags.b.lcyl_hob) | ||
825 | hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG); | ||
826 | if (task->tf_out_flags.b.hcyl_hob) | ||
827 | hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG); | ||
828 | |||
829 | /* (ks) Send now the standard registers */ | ||
830 | if (task->tf_out_flags.b.error_feature) | ||
831 | hwif->OUTB(tf->feature, IDE_FEATURE_REG); | ||
832 | /* refers to number of sectors to transfer */ | ||
833 | if (task->tf_out_flags.b.nsector) | ||
834 | hwif->OUTB(tf->nsect, IDE_NSECTOR_REG); | ||
835 | /* refers to sector offset or start sector */ | ||
836 | if (task->tf_out_flags.b.sector) | ||
837 | hwif->OUTB(tf->lbal, IDE_SECTOR_REG); | ||
838 | if (task->tf_out_flags.b.lcyl) | ||
839 | hwif->OUTB(tf->lbam, IDE_LCYL_REG); | ||
840 | if (task->tf_out_flags.b.hcyl) | ||
841 | hwif->OUTB(tf->lbah, IDE_HCYL_REG); | ||
842 | |||
843 | /* | ||
844 | * (ks) In the flagged taskfile approch, we will use all specified | ||
845 | * registers and the register value will not be changed, except the | ||
846 | * select bit (master/slave) in the drive_head register. We must make | ||
847 | * sure that the desired drive is selected. | ||
848 | */ | ||
849 | hwif->OUTB(tf->device | drive->select.all, IDE_SELECT_REG); | ||
850 | switch(task->data_phase) { | ||
851 | |||
852 | case TASKFILE_OUT_DMAQ: | ||
853 | case TASKFILE_OUT_DMA: | ||
854 | case TASKFILE_IN_DMAQ: | ||
855 | case TASKFILE_IN_DMA: | ||
856 | if (!drive->using_dma) | ||
857 | break; | ||
858 | |||
859 | if (!hwif->dma_setup(drive)) { | ||
860 | hwif->dma_exec_cmd(drive, tf->command); | ||
861 | hwif->dma_start(drive); | ||
862 | return ide_started; | ||
863 | } | ||
864 | break; | ||
865 | |||
866 | default: | ||
867 | if (task->handler == NULL) | ||
868 | return ide_stopped; | ||
869 | |||
870 | /* Issue the command */ | ||
871 | if (task->prehandler) { | ||
872 | hwif->OUTBSYNC(drive, tf->command, IDE_COMMAND_REG); | ||
873 | ndelay(400); /* FIXME */ | ||
874 | return task->prehandler(drive, task->rq); | ||
875 | } | ||
876 | ide_execute_command(drive, tf->command, task->handler, WAIT_WORSTCASE, NULL); | ||
877 | return ide_started; | ||
878 | } | ||
879 | |||
880 | return ide_stopped; | ||
881 | } | 847 | } |