aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-01-25 16:17:07 -0500
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-01-25 16:17:07 -0500
commit74095a91ed02f6727b62d4416be00a041f2d7436 (patch)
tree033cc52877103739c5b55a2cfdd3bfaf6996d5d3 /drivers
parent9a3c49be5c5f7388eefb712be9a383904140532e (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')
-rw-r--r--drivers/ide/ide-disk.c3
-rw-r--r--drivers/ide/ide-io.c31
-rw-r--r--drivers/ide/ide-taskfile.c180
3 files changed, 96 insertions, 118 deletions
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index b534fe97d476..6182c23d2020 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -159,6 +159,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
159 159
160 memset(&task, 0, sizeof(task)); 160 memset(&task, 0, sizeof(task));
161 task.tf_flags = IDE_TFLAG_NO_SELECT_MASK; /* FIXME? */ 161 task.tf_flags = IDE_TFLAG_NO_SELECT_MASK; /* FIXME? */
162 task.tf_flags |= IDE_TFLAG_OUT_TF;
162 163
163 if (drive->select.b.lba) { 164 if (drive->select.b.lba) {
164 if (lba48) { 165 if (lba48) {
@@ -182,7 +183,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
182 tf->hob_lbah, tf->hob_lbam, tf->hob_lbal, 183 tf->hob_lbah, tf->hob_lbam, tf->hob_lbal,
183 tf->lbah, tf->lbam, tf->lbal); 184 tf->lbah, tf->lbam, tf->lbal);
184#endif 185#endif
185 task.tf_flags |= IDE_TFLAG_LBA48; 186 task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB);
186 } else { 187 } else {
187 tf->nsect = nsectors.b.low; 188 tf->nsect = nsectors.b.low;
188 tf->lbal = block; 189 tf->lbal = block;
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index dc984c5b0d13..33458fe7f490 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -192,15 +192,11 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
192 args->tf.command = WIN_FLUSH_CACHE_EXT; 192 args->tf.command = WIN_FLUSH_CACHE_EXT;
193 else 193 else
194 args->tf.command = 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->tf.command = 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);
@@ -215,9 +211,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
215 211
216 case idedisk_pm_idle: /* Resume step 2 (idle) */ 212 case idedisk_pm_idle: /* Resume step 2 (idle) */
217 args->tf.command = 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 /*
@@ -236,6 +230,14 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
236 } 230 }
237 pm->pm_step = ide_pm_state_completed; 231 pm->pm_step = ide_pm_state_completed;
238 return ide_stopped; 232 return ide_stopped;
233
234out_do_tf:
235 args->tf_flags = IDE_TFLAG_OUT_TF;
236 if (drive->addressing == 1)
237 args->tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB);
238 args->command_type = IDE_DRIVE_TASK_NO_DATA;
239 args->handler = task_no_data_intr;
240 return do_rw_taskfile(drive, args);
239} 241}
240 242
241/** 243/**
@@ -730,6 +732,10 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
730 return ide_stopped; 732 return ide_stopped;
731 } 733 }
732 734
735 args.tf_flags = IDE_TFLAG_OUT_TF;
736 if (drive->addressing == 1)
737 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB);
738
733 do_rw_taskfile(drive, &args); 739 do_rw_taskfile(drive, &args);
734 740
735 return ide_started; 741 return ide_started;
@@ -883,8 +889,13 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
883 break; 889 break;
884 } 890 }
885 891
886 if (args->tf_out_flags.all != 0) 892 if (args->tf_flags & IDE_TFLAG_FLAGGED)
887 return flagged_taskfile(drive, args); 893 return flagged_taskfile(drive, args);
894
895 args->tf_flags |= IDE_TFLAG_OUT_TF;
896 if (drive->addressing == 1)
897 args->tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB);
898
888 return do_rw_taskfile(drive, args); 899 return do_rw_taskfile(drive, args);
889 } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) { 900 } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
890 u8 *args = rq->buffer; 901 u8 *args = rq->buffer;
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
127static 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
113ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) 146ide_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 */
783ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) 822ide_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}