aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-taskfile.c
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/ide/ide-taskfile.c
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/ide/ide-taskfile.c')
-rw-r--r--drivers/ide/ide-taskfile.c180
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
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}