diff options
Diffstat (limited to 'drivers/ide/ide-taskfile.c')
-rw-r--r-- | drivers/ide/ide-taskfile.c | 105 |
1 files changed, 25 insertions, 80 deletions
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 8da8d26db7ed..a4c2d91179b3 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
@@ -53,9 +53,6 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) | |||
53 | } | 53 | } |
54 | 54 | ||
55 | static ide_startstop_t task_no_data_intr(ide_drive_t *); | 55 | static ide_startstop_t task_no_data_intr(ide_drive_t *); |
56 | static ide_startstop_t set_geometry_intr(ide_drive_t *); | ||
57 | static ide_startstop_t recal_intr(ide_drive_t *); | ||
58 | static ide_startstop_t set_multmode_intr(ide_drive_t *); | ||
59 | static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *); | 56 | static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *); |
60 | static ide_startstop_t task_in_intr(ide_drive_t *); | 57 | static ide_startstop_t task_in_intr(ide_drive_t *); |
61 | 58 | ||
@@ -79,6 +76,8 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) | |||
79 | if (task->tf_flags & IDE_TFLAG_FLAGGED) | 76 | if (task->tf_flags & IDE_TFLAG_FLAGGED) |
80 | task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS; | 77 | task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS; |
81 | 78 | ||
79 | memcpy(&hwif->task, task, sizeof(*task)); | ||
80 | |||
82 | if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { | 81 | if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { |
83 | ide_tf_dump(drive->name, tf); | 82 | ide_tf_dump(drive->name, tf); |
84 | tp_ops->set_irq(hwif, 1); | 83 | tp_ops->set_irq(hwif, 1); |
@@ -99,19 +98,6 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) | |||
99 | case TASKFILE_NO_DATA: | 98 | case TASKFILE_NO_DATA: |
100 | if (handler == NULL) | 99 | if (handler == NULL) |
101 | handler = task_no_data_intr; | 100 | handler = task_no_data_intr; |
102 | if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) { | ||
103 | switch (tf->command) { | ||
104 | case ATA_CMD_INIT_DEV_PARAMS: | ||
105 | handler = set_geometry_intr; | ||
106 | break; | ||
107 | case ATA_CMD_RESTORE: | ||
108 | handler = recal_intr; | ||
109 | break; | ||
110 | case ATA_CMD_SET_MULTI: | ||
111 | handler = set_multmode_intr; | ||
112 | break; | ||
113 | } | ||
114 | } | ||
115 | ide_execute_command(drive, tf->command, handler, | 101 | ide_execute_command(drive, tf->command, handler, |
116 | WAIT_WORSTCASE, NULL); | 102 | WAIT_WORSTCASE, NULL); |
117 | return ide_started; | 103 | return ide_started; |
@@ -127,33 +113,15 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) | |||
127 | EXPORT_SYMBOL_GPL(do_rw_taskfile); | 113 | EXPORT_SYMBOL_GPL(do_rw_taskfile); |
128 | 114 | ||
129 | /* | 115 | /* |
130 | * set_multmode_intr() is invoked on completion of a ATA_CMD_SET_MULTI cmd. | 116 | * Handler for commands without a data phase |
131 | */ | ||
132 | static ide_startstop_t set_multmode_intr(ide_drive_t *drive) | ||
133 | { | ||
134 | ide_hwif_t *hwif = drive->hwif; | ||
135 | u8 stat; | ||
136 | |||
137 | local_irq_enable_in_hardirq(); | ||
138 | stat = hwif->tp_ops->read_status(hwif); | ||
139 | |||
140 | if (OK_STAT(stat, ATA_DRDY, BAD_STAT)) | ||
141 | drive->mult_count = drive->mult_req; | ||
142 | else { | ||
143 | drive->mult_req = drive->mult_count = 0; | ||
144 | drive->special.b.recalibrate = 1; | ||
145 | (void) ide_dump_status(drive, "set_multmode", stat); | ||
146 | } | ||
147 | return ide_stopped; | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * set_geometry_intr() is invoked on completion of a ATA_CMD_INIT_DEV_PARAMS cmd. | ||
152 | */ | 117 | */ |
153 | static ide_startstop_t set_geometry_intr(ide_drive_t *drive) | 118 | static ide_startstop_t task_no_data_intr(ide_drive_t *drive) |
154 | { | 119 | { |
155 | ide_hwif_t *hwif = drive->hwif; | 120 | ide_hwif_t *hwif = drive->hwif; |
156 | int retries = 5; | 121 | ide_task_t *task = &hwif->task; |
122 | struct ide_taskfile *tf = &task->tf; | ||
123 | int custom = (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) ? 1 : 0; | ||
124 | int retries = (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) ? 5 : 1; | ||
157 | u8 stat; | 125 | u8 stat; |
158 | 126 | ||
159 | local_irq_enable_in_hardirq(); | 127 | local_irq_enable_in_hardirq(); |
@@ -165,50 +133,27 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive) | |||
165 | udelay(10); | 133 | udelay(10); |
166 | }; | 134 | }; |
167 | 135 | ||
168 | if (OK_STAT(stat, ATA_DRDY, BAD_STAT)) | 136 | if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { |
169 | return ide_stopped; | 137 | if (custom && tf->command == ATA_CMD_SET_MULTI) { |
170 | 138 | drive->mult_req = drive->mult_count = 0; | |
171 | if (stat & (ATA_ERR | ATA_DRQ)) | 139 | drive->special.b.recalibrate = 1; |
172 | return ide_error(drive, "set_geometry_intr", stat); | 140 | (void)ide_dump_status(drive, __func__, stat); |
173 | 141 | return ide_stopped; | |
174 | ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL); | 142 | } else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) { |
175 | return ide_started; | 143 | if ((stat & (ATA_ERR | ATA_DRQ)) == 0) { |
176 | } | 144 | ide_set_handler(drive, &task_no_data_intr, |
177 | 145 | WAIT_WORSTCASE, NULL); | |
178 | /* | 146 | return ide_started; |
179 | * recal_intr() is invoked on completion of a ATA_CMD_RESTORE (recalibrate) cmd. | 147 | } |
180 | */ | 148 | } |
181 | static ide_startstop_t recal_intr(ide_drive_t *drive) | ||
182 | { | ||
183 | ide_hwif_t *hwif = drive->hwif; | ||
184 | u8 stat; | ||
185 | |||
186 | local_irq_enable_in_hardirq(); | ||
187 | stat = hwif->tp_ops->read_status(hwif); | ||
188 | |||
189 | if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) | ||
190 | return ide_error(drive, "recal_intr", stat); | ||
191 | return ide_stopped; | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * Handler for commands without a data phase | ||
196 | */ | ||
197 | static ide_startstop_t task_no_data_intr(ide_drive_t *drive) | ||
198 | { | ||
199 | ide_hwif_t *hwif = drive->hwif; | ||
200 | ide_task_t *args = hwif->hwgroup->rq->special; | ||
201 | u8 stat; | ||
202 | |||
203 | local_irq_enable_in_hardirq(); | ||
204 | stat = hwif->tp_ops->read_status(hwif); | ||
205 | |||
206 | if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) | ||
207 | return ide_error(drive, "task_no_data_intr", stat); | 149 | return ide_error(drive, "task_no_data_intr", stat); |
208 | /* calls ide_end_drive_cmd */ | 150 | /* calls ide_end_drive_cmd */ |
151 | } | ||
209 | 152 | ||
210 | if (args) | 153 | if (!custom) |
211 | ide_end_drive_cmd(drive, stat, ide_read_error(drive)); | 154 | ide_end_drive_cmd(drive, stat, ide_read_error(drive)); |
155 | else if (tf->command == ATA_CMD_SET_MULTI) | ||
156 | drive->mult_count = drive->mult_req; | ||
212 | 157 | ||
213 | return ide_stopped; | 158 | return ide_stopped; |
214 | } | 159 | } |