aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-10-13 15:39:41 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-10-13 15:39:41 -0400
commitd6ff9f64e68d23feab44efa07cc6aee01f3ef32b (patch)
tree902fb2b10372c396447c4ddb6097a088c809693b
parent0e3d84a500d4e1672332b4961b98c35f6168e6f1 (diff)
ide: merge all TASKFILE_NO_DATA data phase handlers into taskfile_no_intr()
* Add 'struct task_s' to ide_hwif_t and init it to the current command in do_rw_taskfile(). * Merge all TASKFILE_NO_DATA data phase handlers into taskfile_no_intr(). Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r--drivers/ide/ide-taskfile.c105
-rw-r--r--include/linux/ide.h211
2 files changed, 131 insertions, 185 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
55static ide_startstop_t task_no_data_intr(ide_drive_t *); 55static ide_startstop_t task_no_data_intr(ide_drive_t *);
56static ide_startstop_t set_geometry_intr(ide_drive_t *);
57static ide_startstop_t recal_intr(ide_drive_t *);
58static ide_startstop_t set_multmode_intr(ide_drive_t *);
59static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *); 56static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
60static ide_startstop_t task_in_intr(ide_drive_t *); 57static 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)
127EXPORT_SYMBOL_GPL(do_rw_taskfile); 113EXPORT_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 */
132static 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 */
153static ide_startstop_t set_geometry_intr(ide_drive_t *drive) 118static 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 }
181static 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 */
197static 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}
diff --git a/include/linux/ide.h b/include/linux/ide.h
index a5e1888b1dab..14d489c2e5a9 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -282,6 +282,110 @@ typedef enum {
282 ide_started, /* a drive operation was started, handler was set */ 282 ide_started, /* a drive operation was started, handler was set */
283} ide_startstop_t; 283} ide_startstop_t;
284 284
285enum {
286 IDE_TFLAG_LBA48 = (1 << 0),
287 IDE_TFLAG_FLAGGED = (1 << 2),
288 IDE_TFLAG_OUT_DATA = (1 << 3),
289 IDE_TFLAG_OUT_HOB_FEATURE = (1 << 4),
290 IDE_TFLAG_OUT_HOB_NSECT = (1 << 5),
291 IDE_TFLAG_OUT_HOB_LBAL = (1 << 6),
292 IDE_TFLAG_OUT_HOB_LBAM = (1 << 7),
293 IDE_TFLAG_OUT_HOB_LBAH = (1 << 8),
294 IDE_TFLAG_OUT_HOB = IDE_TFLAG_OUT_HOB_FEATURE |
295 IDE_TFLAG_OUT_HOB_NSECT |
296 IDE_TFLAG_OUT_HOB_LBAL |
297 IDE_TFLAG_OUT_HOB_LBAM |
298 IDE_TFLAG_OUT_HOB_LBAH,
299 IDE_TFLAG_OUT_FEATURE = (1 << 9),
300 IDE_TFLAG_OUT_NSECT = (1 << 10),
301 IDE_TFLAG_OUT_LBAL = (1 << 11),
302 IDE_TFLAG_OUT_LBAM = (1 << 12),
303 IDE_TFLAG_OUT_LBAH = (1 << 13),
304 IDE_TFLAG_OUT_TF = IDE_TFLAG_OUT_FEATURE |
305 IDE_TFLAG_OUT_NSECT |
306 IDE_TFLAG_OUT_LBAL |
307 IDE_TFLAG_OUT_LBAM |
308 IDE_TFLAG_OUT_LBAH,
309 IDE_TFLAG_OUT_DEVICE = (1 << 14),
310 IDE_TFLAG_WRITE = (1 << 15),
311 IDE_TFLAG_FLAGGED_SET_IN_FLAGS = (1 << 16),
312 IDE_TFLAG_IN_DATA = (1 << 17),
313 IDE_TFLAG_CUSTOM_HANDLER = (1 << 18),
314 IDE_TFLAG_DMA_PIO_FALLBACK = (1 << 19),
315 IDE_TFLAG_IN_HOB_FEATURE = (1 << 20),
316 IDE_TFLAG_IN_HOB_NSECT = (1 << 21),
317 IDE_TFLAG_IN_HOB_LBAL = (1 << 22),
318 IDE_TFLAG_IN_HOB_LBAM = (1 << 23),
319 IDE_TFLAG_IN_HOB_LBAH = (1 << 24),
320 IDE_TFLAG_IN_HOB_LBA = IDE_TFLAG_IN_HOB_LBAL |
321 IDE_TFLAG_IN_HOB_LBAM |
322 IDE_TFLAG_IN_HOB_LBAH,
323 IDE_TFLAG_IN_HOB = IDE_TFLAG_IN_HOB_FEATURE |
324 IDE_TFLAG_IN_HOB_NSECT |
325 IDE_TFLAG_IN_HOB_LBA,
326 IDE_TFLAG_IN_FEATURE = (1 << 1),
327 IDE_TFLAG_IN_NSECT = (1 << 25),
328 IDE_TFLAG_IN_LBAL = (1 << 26),
329 IDE_TFLAG_IN_LBAM = (1 << 27),
330 IDE_TFLAG_IN_LBAH = (1 << 28),
331 IDE_TFLAG_IN_LBA = IDE_TFLAG_IN_LBAL |
332 IDE_TFLAG_IN_LBAM |
333 IDE_TFLAG_IN_LBAH,
334 IDE_TFLAG_IN_TF = IDE_TFLAG_IN_NSECT |
335 IDE_TFLAG_IN_LBA,
336 IDE_TFLAG_IN_DEVICE = (1 << 29),
337 IDE_TFLAG_HOB = IDE_TFLAG_OUT_HOB |
338 IDE_TFLAG_IN_HOB,
339 IDE_TFLAG_TF = IDE_TFLAG_OUT_TF |
340 IDE_TFLAG_IN_TF,
341 IDE_TFLAG_DEVICE = IDE_TFLAG_OUT_DEVICE |
342 IDE_TFLAG_IN_DEVICE,
343 /* force 16-bit I/O operations */
344 IDE_TFLAG_IO_16BIT = (1 << 30),
345 /* ide_task_t was allocated using kmalloc() */
346 IDE_TFLAG_DYN = (1 << 31),
347};
348
349struct ide_taskfile {
350 u8 hob_data; /* 0: high data byte (for TASKFILE IOCTL) */
351
352 u8 hob_feature; /* 1-5: additional data to support LBA48 */
353 u8 hob_nsect;
354 u8 hob_lbal;
355 u8 hob_lbam;
356 u8 hob_lbah;
357
358 u8 data; /* 6: low data byte (for TASKFILE IOCTL) */
359
360 union { /*  7: */
361 u8 error; /* read: error */
362 u8 feature; /* write: feature */
363 };
364
365 u8 nsect; /* 8: number of sectors */
366 u8 lbal; /* 9: LBA low */
367 u8 lbam; /* 10: LBA mid */
368 u8 lbah; /* 11: LBA high */
369
370 u8 device; /* 12: device select */
371
372 union { /* 13: */
373 u8 status; /*  read: status  */
374 u8 command; /* write: command */
375 };
376};
377
378typedef struct ide_task_s {
379 union {
380 struct ide_taskfile tf;
381 u8 tf_array[14];
382 };
383 u32 tf_flags;
384 int data_phase;
385 struct request *rq; /* copy of request */
386 void *special; /* valid_t generally */
387} ide_task_t;
388
285/* ATAPI packet command flags */ 389/* ATAPI packet command flags */
286enum { 390enum {
287 /* set when an error is considered normal - no retry (ide-tape) */ 391 /* set when an error is considered normal - no retry (ide-tape) */
@@ -567,7 +671,6 @@ typedef struct ide_drive_s ide_drive_t;
567#define ide_drv_g(disk, cont_type) \ 671#define ide_drv_g(disk, cont_type) \
568 container_of((disk)->private_data, struct cont_type, driver) 672 container_of((disk)->private_data, struct cont_type, driver)
569 673
570struct ide_task_s;
571struct ide_port_info; 674struct ide_port_info;
572 675
573struct ide_tp_ops { 676struct ide_tp_ops {
@@ -694,6 +797,8 @@ typedef struct hwif_s {
694 /* data phase of the active command (currently only valid for PIO/DMA) */ 797 /* data phase of the active command (currently only valid for PIO/DMA) */
695 int data_phase; 798 int data_phase;
696 799
800 struct ide_task_s task; /* current command */
801
697 unsigned int nsect; 802 unsigned int nsect;
698 unsigned int nleft; 803 unsigned int nleft;
699 struct scatterlist *cursg; 804 struct scatterlist *cursg;
@@ -1059,110 +1164,6 @@ extern void ide_do_drive_cmd(ide_drive_t *, struct request *);
1059 1164
1060extern void ide_end_drive_cmd(ide_drive_t *, u8, u8); 1165extern void ide_end_drive_cmd(ide_drive_t *, u8, u8);
1061 1166
1062enum {
1063 IDE_TFLAG_LBA48 = (1 << 0),
1064 IDE_TFLAG_FLAGGED = (1 << 2),
1065 IDE_TFLAG_OUT_DATA = (1 << 3),
1066 IDE_TFLAG_OUT_HOB_FEATURE = (1 << 4),
1067 IDE_TFLAG_OUT_HOB_NSECT = (1 << 5),
1068 IDE_TFLAG_OUT_HOB_LBAL = (1 << 6),
1069 IDE_TFLAG_OUT_HOB_LBAM = (1 << 7),
1070 IDE_TFLAG_OUT_HOB_LBAH = (1 << 8),
1071 IDE_TFLAG_OUT_HOB = IDE_TFLAG_OUT_HOB_FEATURE |
1072 IDE_TFLAG_OUT_HOB_NSECT |
1073 IDE_TFLAG_OUT_HOB_LBAL |
1074 IDE_TFLAG_OUT_HOB_LBAM |
1075 IDE_TFLAG_OUT_HOB_LBAH,
1076 IDE_TFLAG_OUT_FEATURE = (1 << 9),
1077 IDE_TFLAG_OUT_NSECT = (1 << 10),
1078 IDE_TFLAG_OUT_LBAL = (1 << 11),
1079 IDE_TFLAG_OUT_LBAM = (1 << 12),
1080 IDE_TFLAG_OUT_LBAH = (1 << 13),
1081 IDE_TFLAG_OUT_TF = IDE_TFLAG_OUT_FEATURE |
1082 IDE_TFLAG_OUT_NSECT |
1083 IDE_TFLAG_OUT_LBAL |
1084 IDE_TFLAG_OUT_LBAM |
1085 IDE_TFLAG_OUT_LBAH,
1086 IDE_TFLAG_OUT_DEVICE = (1 << 14),
1087 IDE_TFLAG_WRITE = (1 << 15),
1088 IDE_TFLAG_FLAGGED_SET_IN_FLAGS = (1 << 16),
1089 IDE_TFLAG_IN_DATA = (1 << 17),
1090 IDE_TFLAG_CUSTOM_HANDLER = (1 << 18),
1091 IDE_TFLAG_DMA_PIO_FALLBACK = (1 << 19),
1092 IDE_TFLAG_IN_HOB_FEATURE = (1 << 20),
1093 IDE_TFLAG_IN_HOB_NSECT = (1 << 21),
1094 IDE_TFLAG_IN_HOB_LBAL = (1 << 22),
1095 IDE_TFLAG_IN_HOB_LBAM = (1 << 23),
1096 IDE_TFLAG_IN_HOB_LBAH = (1 << 24),
1097 IDE_TFLAG_IN_HOB_LBA = IDE_TFLAG_IN_HOB_LBAL |
1098 IDE_TFLAG_IN_HOB_LBAM |
1099 IDE_TFLAG_IN_HOB_LBAH,
1100 IDE_TFLAG_IN_HOB = IDE_TFLAG_IN_HOB_FEATURE |
1101 IDE_TFLAG_IN_HOB_NSECT |
1102 IDE_TFLAG_IN_HOB_LBA,
1103 IDE_TFLAG_IN_FEATURE = (1 << 1),
1104 IDE_TFLAG_IN_NSECT = (1 << 25),
1105 IDE_TFLAG_IN_LBAL = (1 << 26),
1106 IDE_TFLAG_IN_LBAM = (1 << 27),
1107 IDE_TFLAG_IN_LBAH = (1 << 28),
1108 IDE_TFLAG_IN_LBA = IDE_TFLAG_IN_LBAL |
1109 IDE_TFLAG_IN_LBAM |
1110 IDE_TFLAG_IN_LBAH,
1111 IDE_TFLAG_IN_TF = IDE_TFLAG_IN_NSECT |
1112 IDE_TFLAG_IN_LBA,
1113 IDE_TFLAG_IN_DEVICE = (1 << 29),
1114 IDE_TFLAG_HOB = IDE_TFLAG_OUT_HOB |
1115 IDE_TFLAG_IN_HOB,
1116 IDE_TFLAG_TF = IDE_TFLAG_OUT_TF |
1117 IDE_TFLAG_IN_TF,
1118 IDE_TFLAG_DEVICE = IDE_TFLAG_OUT_DEVICE |
1119 IDE_TFLAG_IN_DEVICE,
1120 /* force 16-bit I/O operations */
1121 IDE_TFLAG_IO_16BIT = (1 << 30),
1122 /* ide_task_t was allocated using kmalloc() */
1123 IDE_TFLAG_DYN = (1 << 31),
1124};
1125
1126struct ide_taskfile {
1127 u8 hob_data; /* 0: high data byte (for TASKFILE IOCTL) */
1128
1129 u8 hob_feature; /* 1-5: additional data to support LBA48 */
1130 u8 hob_nsect;
1131 u8 hob_lbal;
1132 u8 hob_lbam;
1133 u8 hob_lbah;
1134
1135 u8 data; /* 6: low data byte (for TASKFILE IOCTL) */
1136
1137 union { /*  7: */
1138 u8 error; /* read: error */
1139 u8 feature; /* write: feature */
1140 };
1141
1142 u8 nsect; /* 8: number of sectors */
1143 u8 lbal; /* 9: LBA low */
1144 u8 lbam; /* 10: LBA mid */
1145 u8 lbah; /* 11: LBA high */
1146
1147 u8 device; /* 12: device select */
1148
1149 union { /* 13: */
1150 u8 status; /*  read: status  */
1151 u8 command; /* write: command */
1152 };
1153};
1154
1155typedef struct ide_task_s {
1156 union {
1157 struct ide_taskfile tf;
1158 u8 tf_array[14];
1159 };
1160 u32 tf_flags;
1161 int data_phase;
1162 struct request *rq; /* copy of request */
1163 void *special; /* valid_t generally */
1164} ide_task_t;
1165
1166void ide_tf_dump(const char *, struct ide_taskfile *); 1167void ide_tf_dump(const char *, struct ide_taskfile *);
1167 1168
1168void ide_exec_command(ide_hwif_t *, u8); 1169void ide_exec_command(ide_hwif_t *, u8);