Diff markup
1 /* 1 /*
2 * Copyright (C) 2000-2002 Michael Cor 2 * Copyright (C) 2000-2002 Michael Cornwell <cornwell@acm.org>
3 * Copyright (C) 2000-2002 Andre Hedri 3 * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
4 * Copyright (C) 2001-2002 Klaus Smoli 4 * Copyright (C) 2001-2002 Klaus Smolin
5 * IBM St 5 * IBM Storage Technology Division
6 * Copyright (C) 2003-2004, 2007 Bartlomiej 6 * Copyright (C) 2003-2004, 2007 Bartlomiej Zolnierkiewicz
7 * 7 *
8 * The big the bad and the ugly. 8 * The big the bad and the ugly.
9 */ 9 */
10 10
11 #include <linux/module.h> 11 #include <linux/module.h>
12 #include <linux/types.h> 12 #include <linux/types.h>
13 #include <linux/string.h> 13 #include <linux/string.h>
14 #include <linux/kernel.h> 14 #include <linux/kernel.h>
15 #include <linux/timer.h> 15 #include <linux/timer.h>
16 #include <linux/mm.h> 16 #include <linux/mm.h>
17 #include <linux/sched.h> 17 #include <linux/sched.h>
18 #include <linux/interrupt.h> 18 #include <linux/interrupt.h>
19 #include <linux/major.h> 19 #include <linux/major.h>
20 #include <linux/errno.h> 20 #include <linux/errno.h>
21 #include <linux/genhd.h> 21 #include <linux/genhd.h>
22 #include <linux/blkpg.h> 22 #include <linux/blkpg.h>
23 #include <linux/slab.h> 23 #include <linux/slab.h>
24 #include <linux/pci.h> 24 #include <linux/pci.h>
25 #include <linux/delay.h> 25 #include <linux/delay.h>
26 #include <linux/hdreg.h> 26 #include <linux/hdreg.h>
27 #include <linux/ide.h> 27 #include <linux/ide.h>
28 #include <linux/bitops.h> 28 #include <linux/bitops.h>
29 #include <linux/scatterlist.h> 29 #include <linux/scatterlist.h>
30 30
31 #include <asm/byteorder.h> 31 #include <asm/byteorder.h>
32 #include <asm/irq.h> 32 #include <asm/irq.h>
33 #include <asm/uaccess.h> 33 #include <asm/uaccess.h>
34 #include <asm/io.h> 34 #include <asm/io.h>
35 35
36 void ide_tf_load(ide_drive_t *drive, ide_task_ 36 void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
37 { 37 {
38 ide_hwif_t *hwif = drive->hwif; 38 ide_hwif_t *hwif = drive->hwif;
39 struct ide_taskfile *tf = &task->tf; 39 struct ide_taskfile *tf = &task->tf;
40 u8 HIHI = (task->tf_flags & IDE_TFLAG_ 40 u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
41 41
42 if (task->tf_flags & IDE_TFLAG_FLAGGED 42 if (task->tf_flags & IDE_TFLAG_FLAGGED)
43 HIHI = 0xFF; 43 HIHI = 0xFF;
44 44
45 #ifdef DEBUG 45 #ifdef DEBUG
46 printk("%s: tf: feat 0x%02x nsect 0x%0 46 printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x "
47 "lbam 0x%02x lbah 0x%02x dev 0 47 "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n",
48 drive->name, tf->feature, tf-> 48 drive->name, tf->feature, tf->nsect, tf->lbal,
49 tf->lbam, tf->lbah, tf->device 49 tf->lbam, tf->lbah, tf->device, tf->command);
50 printk("%s: hob: nsect 0x%02x lbal 0x% 50 printk("%s: hob: nsect 0x%02x lbal 0x%02x "
51 "lbam 0x%02x lbah 0x%02x\n", 51 "lbam 0x%02x lbah 0x%02x\n",
52 drive->name, tf->hob_nsect, tf 52 drive->name, tf->hob_nsect, tf->hob_lbal,
53 tf->hob_lbam, tf->hob_lbah); 53 tf->hob_lbam, tf->hob_lbah);
54 #endif 54 #endif
55 55
56 ide_set_irq(drive, 1); 56 ide_set_irq(drive, 1);
57 57
58 if ((task->tf_flags & IDE_TFLAG_NO_SEL 58 if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
59 SELECT_MASK(drive, 0); 59 SELECT_MASK(drive, 0);
60 60
61 if (task->tf_flags & IDE_TFLAG_OUT_DAT 61 if (task->tf_flags & IDE_TFLAG_OUT_DATA)
62 hwif->OUTW((tf->hob_data << 8) 62 hwif->OUTW((tf->hob_data << 8) | tf->data, IDE_DATA_REG);
63 63
64 if (task->tf_flags & IDE_TFLAG_OUT_HOB 64 if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
65 hwif->OUTB(tf->hob_feature, ID 65 hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG);
66 if (task->tf_flags & IDE_TFLAG_OUT_HOB 66 if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
67 hwif->OUTB(tf->hob_nsect, IDE_ 67 hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG);
68 if (task->tf_flags & IDE_TFLAG_OUT_HOB 68 if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
69 hwif->OUTB(tf->hob_lbal, IDE_S 69 hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG);
70 if (task->tf_flags & IDE_TFLAG_OUT_HOB 70 if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
71 hwif->OUTB(tf->hob_lbam, IDE_L 71 hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG);
72 if (task->tf_flags & IDE_TFLAG_OUT_HOB 72 if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
73 hwif->OUTB(tf->hob_lbah, IDE_H 73 hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG);
74 74
75 if (task->tf_flags & IDE_TFLAG_OUT_FEA 75 if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
76 hwif->OUTB(tf->feature, IDE_FE 76 hwif->OUTB(tf->feature, IDE_FEATURE_REG);
77 if (task->tf_flags & IDE_TFLAG_OUT_NSE 77 if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
78 hwif->OUTB(tf->nsect, IDE_NSEC 78 hwif->OUTB(tf->nsect, IDE_NSECTOR_REG);
79 if (task->tf_flags & IDE_TFLAG_OUT_LBA 79 if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
80 hwif->OUTB(tf->lbal, IDE_SECTO 80 hwif->OUTB(tf->lbal, IDE_SECTOR_REG);
81 if (task->tf_flags & IDE_TFLAG_OUT_LBA 81 if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
82 hwif->OUTB(tf->lbam, IDE_LCYL_ 82 hwif->OUTB(tf->lbam, IDE_LCYL_REG);
83 if (task->tf_flags & IDE_TFLAG_OUT_LBA 83 if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
84 hwif->OUTB(tf->lbah, IDE_HCYL_ 84 hwif->OUTB(tf->lbah, IDE_HCYL_REG);
85 85
86 if (task->tf_flags & IDE_TFLAG_OUT_DEV 86 if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
87 hwif->OUTB((tf->device & HIHI) 87 hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG);
88 } 88 }
89 89
90 int taskfile_lib_get_identify (ide_drive_t *dr 90 int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
91 { 91 {
92 ide_task_t args; 92 ide_task_t args;
93 93
94 memset(&args, 0, sizeof(ide_task_t)); 94 memset(&args, 0, sizeof(ide_task_t));
95 args.tf.nsect = 0x01; 95 args.tf.nsect = 0x01;
96 if (drive->media == ide_disk) 96 if (drive->media == ide_disk)
97 args.tf.command = WIN_IDENTIFY 97 args.tf.command = WIN_IDENTIFY;
98 else 98 else
99 args.tf.command = WIN_PIDENTIF 99 args.tf.command = WIN_PIDENTIFY;
100 args.tf_flags = IDE_TFLAG_TF | IDE_T 100 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
101 args.data_phase = TASKFILE_IN; 101 args.data_phase = TASKFILE_IN;
102 return ide_raw_taskfile(drive, &args, 102 return ide_raw_taskfile(drive, &args, buf, 1);
103 } 103 }
104 104
105 static int inline task_dma_ok(ide_task_t *task 105 static int inline task_dma_ok(ide_task_t *task)
106 { 106 {
107 if (blk_fs_request(task->rq) || (task- 107 if (blk_fs_request(task->rq) || (task->tf_flags & IDE_TFLAG_FLAGGED))
108 return 1; 108 return 1;
109 109
110 switch (task->tf.command) { 110 switch (task->tf.command) {
111 case WIN_WRITEDMA_ONCE: 111 case WIN_WRITEDMA_ONCE:
112 case WIN_WRITEDMA: 112 case WIN_WRITEDMA:
113 case WIN_WRITEDMA_EXT: 113 case WIN_WRITEDMA_EXT:
114 case WIN_READDMA_ONCE: 114 case WIN_READDMA_ONCE:
115 case WIN_READDMA: 115 case WIN_READDMA:
116 case WIN_READDMA_EXT: 116 case WIN_READDMA_EXT:
117 case WIN_IDENTIFY_DMA: 117 case WIN_IDENTIFY_DMA:
118 return 1; 118 return 1;
119 } 119 }
120 120
121 return 0; 121 return 0;
122 } 122 }
123 123
124 static ide_startstop_t task_no_data_intr(ide_d 124 static ide_startstop_t task_no_data_intr(ide_drive_t *);
125 static ide_startstop_t set_geometry_intr(ide_d 125 static ide_startstop_t set_geometry_intr(ide_drive_t *);
126 static ide_startstop_t recal_intr(ide_drive_t 126 static ide_startstop_t recal_intr(ide_drive_t *);
127 static ide_startstop_t set_multmode_intr(ide_d 127 static ide_startstop_t set_multmode_intr(ide_drive_t *);
128 static ide_startstop_t pre_task_out_intr(ide_d 128 static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
129 static ide_startstop_t task_in_intr(ide_drive_ 129 static ide_startstop_t task_in_intr(ide_drive_t *);
130 130
131 ide_startstop_t do_rw_taskfile (ide_drive_t *d 131 ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
132 { 132 {
133 ide_hwif_t *hwif = HWIF(drive); 133 ide_hwif_t *hwif = HWIF(drive);
134 struct ide_taskfile *tf = &task->tf; 134 struct ide_taskfile *tf = &task->tf;
135 ide_handler_t *handler = NULL; 135 ide_handler_t *handler = NULL;
136 136
137 if (task->data_phase == TASKFILE_MULTI 137 if (task->data_phase == TASKFILE_MULTI_IN ||
138 task->data_phase == TASKFILE_MULTI 138 task->data_phase == TASKFILE_MULTI_OUT) {
139 if (!drive->mult_count) { 139 if (!drive->mult_count) {
140 printk(KERN_ERR "%s: m 140 printk(KERN_ERR "%s: multimode not set!\n",
141 drive- 141 drive->name);
142 return ide_stopped; 142 return ide_stopped;
143 } 143 }
144 } 144 }
145 145
146 if (task->tf_flags & IDE_TFLAG_FLAGGED 146 if (task->tf_flags & IDE_TFLAG_FLAGGED)
147 task->tf_flags |= IDE_TFLAG_FL 147 task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
148 148
149 if ((task->tf_flags & IDE_TFLAG_DMA_PI 149 if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0)
150 ide_tf_load(drive, task); 150 ide_tf_load(drive, task);
151 151
152 switch (task->data_phase) { 152 switch (task->data_phase) {
153 case TASKFILE_MULTI_OUT: 153 case TASKFILE_MULTI_OUT:
154 case TASKFILE_OUT: 154 case TASKFILE_OUT:
155 hwif->OUTBSYNC(drive, tf->comm 155 hwif->OUTBSYNC(drive, tf->command, IDE_COMMAND_REG);
156 ndelay(400); /* FIXME */ 156 ndelay(400); /* FIXME */
157 return pre_task_out_intr(drive 157 return pre_task_out_intr(drive, task->rq);
158 case TASKFILE_MULTI_IN: 158 case TASKFILE_MULTI_IN:
159 case TASKFILE_IN: 159 case TASKFILE_IN:
160 handler = task_in_intr; 160 handler = task_in_intr;
161 /* fall-through */ 161 /* fall-through */
162 case TASKFILE_NO_DATA: 162 case TASKFILE_NO_DATA:
163 if (handler == NULL) 163 if (handler == NULL)
164 handler = task_no_data 164 handler = task_no_data_intr;
165 /* WIN_{SPECIFY,RESTORE,SETMUL 165 /* WIN_{SPECIFY,RESTORE,SETMULT} use custom handlers */
166 if (task->tf_flags & IDE_TFLAG 166 if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) {
167 switch (tf->command) { 167 switch (tf->command) {
168 case WIN_SPECIFY: hand 168 case WIN_SPECIFY: handler = set_geometry_intr; break;
169 case WIN_RESTORE: hand 169 case WIN_RESTORE: handler = recal_intr; break;
170 case WIN_SETMULT: hand 170 case WIN_SETMULT: handler = set_multmode_intr; break;
171 } 171 }
172 } 172 }
173 ide_execute_command(drive, tf- 173 ide_execute_command(drive, tf->command, handler,
174 WAIT_WORST 174 WAIT_WORSTCASE, NULL);
175 return ide_started; 175 return ide_started;
176 default: 176 default:
177 if (task_dma_ok(task) == 0 || 177 if (task_dma_ok(task) == 0 || drive->using_dma == 0 ||
178 hwif->dma_setup(drive)) 178 hwif->dma_setup(drive))
179 return ide_stopped; 179 return ide_stopped;
180 hwif->dma_exec_cmd(drive, tf-> 180 hwif->dma_exec_cmd(drive, tf->command);
181 hwif->dma_start(drive); 181 hwif->dma_start(drive);
182 return ide_started; 182 return ide_started;
183 } 183 }
184 } 184 }
185 EXPORT_SYMBOL_GPL(do_rw_taskfile); 185 EXPORT_SYMBOL_GPL(do_rw_taskfile);
186 186
187 /* 187 /*
188 * set_multmode_intr() is invoked on completio 188 * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
189 */ 189 */
190 static ide_startstop_t set_multmode_intr(ide_d 190 static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
191 { 191 {
192 u8 stat = ide_read_status(drive); 192 u8 stat = ide_read_status(drive);
193 193
194 if (OK_STAT(stat, READY_STAT, BAD_STAT 194 if (OK_STAT(stat, READY_STAT, BAD_STAT))
195 drive->mult_count = drive->mul 195 drive->mult_count = drive->mult_req;
196 else { 196 else {
197 drive->mult_req = drive->mult_ 197 drive->mult_req = drive->mult_count = 0;
198 drive->special.b.recalibrate = 198 drive->special.b.recalibrate = 1;
199 (void) ide_dump_status(drive, 199 (void) ide_dump_status(drive, "set_multmode", stat);
200 } 200 }
201 return ide_stopped; 201 return ide_stopped;
202 } 202 }
203 203
204 /* 204 /*
205 * set_geometry_intr() is invoked on completio 205 * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
206 */ 206 */
207 static ide_startstop_t set_geometry_intr(ide_d 207 static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
208 { 208 {
209 int retries = 5; 209 int retries = 5;
210 u8 stat; 210 u8 stat;
211 211
212 while (((stat = ide_read_status(drive) 212 while (((stat = ide_read_status(drive)) & BUSY_STAT) && retries--)
213 udelay(10); 213 udelay(10);
214 214
215 if (OK_STAT(stat, READY_STAT, BAD_STAT 215 if (OK_STAT(stat, READY_STAT, BAD_STAT))
216 return ide_stopped; 216 return ide_stopped;
217 217
218 if (stat & (ERR_STAT|DRQ_STAT)) 218 if (stat & (ERR_STAT|DRQ_STAT))
219 return ide_error(drive, "set_g 219 return ide_error(drive, "set_geometry_intr", stat);
220 220
221 BUG_ON(HWGROUP(drive)->handler != NULL 221 BUG_ON(HWGROUP(drive)->handler != NULL);
222 ide_set_handler(drive, &set_geometry_i 222 ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL);
223 return ide_started; 223 return ide_started;
224 } 224 }
225 225
226 /* 226 /*
227 * recal_intr() is invoked on completion of a 227 * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
228 */ 228 */
229 static ide_startstop_t recal_intr(ide_drive_t 229 static ide_startstop_t recal_intr(ide_drive_t *drive)
230 { 230 {
231 u8 stat = ide_read_status(drive); 231 u8 stat = ide_read_status(drive);
232 232
233 if (!OK_STAT(stat, READY_STAT, BAD_STA 233 if (!OK_STAT(stat, READY_STAT, BAD_STAT))
234 return ide_error(drive, "recal 234 return ide_error(drive, "recal_intr", stat);
235 return ide_stopped; 235 return ide_stopped;
236 } 236 }
237 237
238 /* 238 /*
239 * Handler for commands without a data phase 239 * Handler for commands without a data phase
240 */ 240 */
241 static ide_startstop_t task_no_data_intr(ide_d 241 static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
242 { 242 {
243 ide_task_t *args = HWGROUP(driv 243 ide_task_t *args = HWGROUP(drive)->rq->special;
244 u8 stat; 244 u8 stat;
245 245
246 local_irq_enable_in_hardirq(); 246 local_irq_enable_in_hardirq();
247 stat = ide_read_status(drive); 247 stat = ide_read_status(drive);
248 248
249 if (!OK_STAT(stat, READY_STAT, BAD_STA 249 if (!OK_STAT(stat, READY_STAT, BAD_STAT))
250 return ide_error(drive, "task_ 250 return ide_error(drive, "task_no_data_intr", stat);
251 /* calls ide_end_drive_cmd */ 251 /* calls ide_end_drive_cmd */
252 252
253 if (args) 253 if (args)
254 ide_end_drive_cmd(drive, stat, 254 ide_end_drive_cmd(drive, stat, ide_read_error(drive));
255 255
256 return ide_stopped; 256 return ide_stopped;
257 } 257 }
258 258
259 static u8 wait_drive_not_busy(ide_drive_t *dri 259 static u8 wait_drive_not_busy(ide_drive_t *drive)
260 { 260 {
261 int retries; 261 int retries;
262 u8 stat; 262 u8 stat;
263 263
264 /* 264 /*
265 * Last sector was transfered, wait un 265 * Last sector was transfered, wait until drive is ready.
266 * This can take up to 10 usec, but we 266 * This can take up to 10 usec, but we will wait max 1 ms.
267 */ 267 */
268 for (retries = 0; retries < 100; retri 268 for (retries = 0; retries < 100; retries++) {
269 stat = ide_read_status(drive); 269 stat = ide_read_status(drive);
270 270
271 if (stat & BUSY_STAT) 271 if (stat & BUSY_STAT)
272 udelay(10); 272 udelay(10);
273 else 273 else
274 break; 274 break;
275 } 275 }
276 276
277 if (stat & BUSY_STAT) 277 if (stat & BUSY_STAT)
278 printk(KERN_ERR "%s: drive sti 278 printk(KERN_ERR "%s: drive still BUSY!\n", drive->name);
279 279
280 return stat; 280 return stat;
281 } 281 }
282 282
283 static void ide_pio_sector(ide_drive_t *drive, 283 static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
284 { 284 {
285 ide_hwif_t *hwif = drive->hwif; 285 ide_hwif_t *hwif = drive->hwif;
286 struct scatterlist *sg = hwif->sg_tabl 286 struct scatterlist *sg = hwif->sg_table;
287 struct scatterlist *cursg = hwif->curs 287 struct scatterlist *cursg = hwif->cursg;
288 struct page *page; 288 struct page *page;
289 #ifdef CONFIG_HIGHMEM 289 #ifdef CONFIG_HIGHMEM
290 unsigned long flags; 290 unsigned long flags;
291 #endif 291 #endif
292 unsigned int offset; 292 unsigned int offset;
293 u8 *buf; 293 u8 *buf;
294 294
295 cursg = hwif->cursg; 295 cursg = hwif->cursg;
296 if (!cursg) { 296 if (!cursg) {
297 cursg = sg; 297 cursg = sg;
298 hwif->cursg = sg; 298 hwif->cursg = sg;
299 } 299 }
300 300
301 page = sg_page(cursg); 301 page = sg_page(cursg);
302 offset = cursg->offset + hwif->cursg_o 302 offset = cursg->offset + hwif->cursg_ofs * SECTOR_SIZE;
303 303
304 /* get the current page and offset */ 304 /* get the current page and offset */
305 page = nth_page(page, (offset >> PAGE_ 305 page = nth_page(page, (offset >> PAGE_SHIFT));
306 offset %= PAGE_SIZE; 306 offset %= PAGE_SIZE;
307 307
308 #ifdef CONFIG_HIGHMEM 308 #ifdef CONFIG_HIGHMEM
309 local_irq_save(flags); !! 309 local_irq_save_nort(flags);
310 #endif 310 #endif
311 buf = kmap_atomic(page, KM_BIO_SRC_IRQ 311 buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset;
312 312
313 hwif->nleft--; 313 hwif->nleft--;
314 hwif->cursg_ofs++; 314 hwif->cursg_ofs++;
315 315
316 if ((hwif->cursg_ofs * SECTOR_SIZE) == 316 if ((hwif->cursg_ofs * SECTOR_SIZE) == cursg->length) {
317 hwif->cursg = sg_next(hwif->cu 317 hwif->cursg = sg_next(hwif->cursg);
318 hwif->cursg_ofs = 0; 318 hwif->cursg_ofs = 0;
319 } 319 }
320 320
321 /* do the actual data transfer */ 321 /* do the actual data transfer */
322 if (write) 322 if (write)
323 hwif->ata_output_data(drive, b 323 hwif->ata_output_data(drive, buf, SECTOR_WORDS);
324 else 324 else
325 hwif->ata_input_data(drive, bu 325 hwif->ata_input_data(drive, buf, SECTOR_WORDS);
326 326
327 kunmap_atomic(buf, KM_BIO_SRC_IRQ); 327 kunmap_atomic(buf, KM_BIO_SRC_IRQ);
328 #ifdef CONFIG_HIGHMEM 328 #ifdef CONFIG_HIGHMEM
329 local_irq_restore(flags); !! 329 local_irq_restore_nort(flags);
330 #endif 330 #endif
331 } 331 }
332 332
333 static void ide_pio_multi(ide_drive_t *drive, 333 static void ide_pio_multi(ide_drive_t *drive, unsigned int write)
334 { 334 {
335 unsigned int nsect; 335 unsigned int nsect;
336 336
337 nsect = min_t(unsigned int, drive->hwi 337 nsect = min_t(unsigned int, drive->hwif->nleft, drive->mult_count);
338 while (nsect--) 338 while (nsect--)
339 ide_pio_sector(drive, write); 339 ide_pio_sector(drive, write);
340 } 340 }
341 341
342 static void ide_pio_datablock(ide_drive_t *dri 342 static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
343 unsigned 343 unsigned int write)
344 { 344 {
345 u8 saved_io_32bit = drive->io_32bit; 345 u8 saved_io_32bit = drive->io_32bit;
346 346
347 if (rq->bio) /* fs request */ 347 if (rq->bio) /* fs request */
348 rq->errors = 0; 348 rq->errors = 0;
349 349
350 if (rq->cmd_type == REQ_TYPE_ATA_TASKF 350 if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
351 ide_task_t *task = rq->special 351 ide_task_t *task = rq->special;
352 352
353 if (task->tf_flags & IDE_TFLAG 353 if (task->tf_flags & IDE_TFLAG_IO_16BIT)
354 drive->io_32bit = 0; 354 drive->io_32bit = 0;
355 } 355 }
356 356
357 touch_softlockup_watchdog(); 357 touch_softlockup_watchdog();
358 358
359 switch (drive->hwif->data_phase) { 359 switch (drive->hwif->data_phase) {
360 case TASKFILE_MULTI_IN: 360 case TASKFILE_MULTI_IN:
361 case TASKFILE_MULTI_OUT: 361 case TASKFILE_MULTI_OUT:
362 ide_pio_multi(drive, write); 362 ide_pio_multi(drive, write);
363 break; 363 break;
364 default: 364 default:
365 ide_pio_sector(drive, write); 365 ide_pio_sector(drive, write);
366 break; 366 break;
367 } 367 }
368 368
369 drive->io_32bit = saved_io_32bit; 369 drive->io_32bit = saved_io_32bit;
370 } 370 }
371 371
372 static ide_startstop_t task_error(ide_drive_t 372 static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
373 const char * 373 const char *s, u8 stat)
374 { 374 {
375 if (rq->bio) { 375 if (rq->bio) {
376 ide_hwif_t *hwif = drive->hwif 376 ide_hwif_t *hwif = drive->hwif;
377 int sectors = hwif->nsect - hw 377 int sectors = hwif->nsect - hwif->nleft;
378 378
379 switch (hwif->data_phase) { 379 switch (hwif->data_phase) {
380 case TASKFILE_IN: 380 case TASKFILE_IN:
381 if (hwif->nleft) 381 if (hwif->nleft)
382 break; 382 break;
383 /* fall through */ 383 /* fall through */
384 case TASKFILE_OUT: 384 case TASKFILE_OUT:
385 sectors--; 385 sectors--;
386 break; 386 break;
387 case TASKFILE_MULTI_IN: 387 case TASKFILE_MULTI_IN:
388 if (hwif->nleft) 388 if (hwif->nleft)
389 break; 389 break;
390 /* fall through */ 390 /* fall through */
391 case TASKFILE_MULTI_OUT: 391 case TASKFILE_MULTI_OUT:
392 sectors -= drive->mult 392 sectors -= drive->mult_count;
393 default: 393 default:
394 break; 394 break;
395 } 395 }
396 396
397 if (sectors > 0) { 397 if (sectors > 0) {
398 ide_driver_t *drv; 398 ide_driver_t *drv;
399 399
400 drv = *(ide_driver_t * 400 drv = *(ide_driver_t **)rq->rq_disk->private_data;
401 drv->end_request(drive 401 drv->end_request(drive, 1, sectors);
402 } 402 }
403 } 403 }
404 return ide_error(drive, s, stat); 404 return ide_error(drive, s, stat);
405 } 405 }
406 406
407 void task_end_request(ide_drive_t *drive, stru 407 void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
408 { 408 {
409 if (rq->cmd_type == REQ_TYPE_ATA_TASKF 409 if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
410 u8 err = ide_read_error(drive) 410 u8 err = ide_read_error(drive);
411 411
412 ide_end_drive_cmd(drive, stat, 412 ide_end_drive_cmd(drive, stat, err);
413 return; 413 return;
414 } 414 }
415 415
416 if (rq->rq_disk) { 416 if (rq->rq_disk) {
417 ide_driver_t *drv; 417 ide_driver_t *drv;
418 418
419 drv = *(ide_driver_t **)rq->rq 419 drv = *(ide_driver_t **)rq->rq_disk->private_data;;
420 drv->end_request(drive, 1, rq- 420 drv->end_request(drive, 1, rq->nr_sectors);
421 } else 421 } else
422 ide_end_request(drive, 1, rq-> 422 ide_end_request(drive, 1, rq->nr_sectors);
423 } 423 }
424 424
425 /* 425 /*
426 * We got an interrupt on a task_in case, but 426 * We got an interrupt on a task_in case, but no errors and no DRQ.
427 * 427 *
428 * It might be a spurious irq (shared irq), bu 428 * It might be a spurious irq (shared irq), but it might be a
429 * command that had no output. 429 * command that had no output.
430 */ 430 */
431 static ide_startstop_t task_in_unexpected(ide_ 431 static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq, u8 stat)
432 { 432 {
433 /* Command all done? */ 433 /* Command all done? */
434 if (OK_STAT(stat, READY_STAT, BUSY_STA 434 if (OK_STAT(stat, READY_STAT, BUSY_STAT)) {
435 task_end_request(drive, rq, st 435 task_end_request(drive, rq, stat);
436 return ide_stopped; 436 return ide_stopped;
437 } 437 }
438 438
439 /* Assume it was a spurious irq */ 439 /* Assume it was a spurious irq */
440 ide_set_handler(drive, &task_in_intr, 440 ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
441 return ide_started; 441 return ide_started;
442 } 442 }
443 443
444 /* 444 /*
445 * Handler for command with PIO data-in phase 445 * Handler for command with PIO data-in phase (Read/Read Multiple).
446 */ 446 */
447 static ide_startstop_t task_in_intr(ide_drive_ 447 static ide_startstop_t task_in_intr(ide_drive_t *drive)
448 { 448 {
449 ide_hwif_t *hwif = drive->hwif; 449 ide_hwif_t *hwif = drive->hwif;
450 struct request *rq = HWGROUP(drive)->r 450 struct request *rq = HWGROUP(drive)->rq;
451 u8 stat = ide_read_status(drive); 451 u8 stat = ide_read_status(drive);
452 452
453 /* Error? */ 453 /* Error? */
454 if (stat & ERR_STAT) 454 if (stat & ERR_STAT)
455 return task_error(drive, rq, _ 455 return task_error(drive, rq, __FUNCTION__, stat);
456 456
457 /* Didn't want any data? Odd. */ 457 /* Didn't want any data? Odd. */
458 if (!(stat & DRQ_STAT)) 458 if (!(stat & DRQ_STAT))
459 return task_in_unexpected(driv 459 return task_in_unexpected(drive, rq, stat);
460 460
461 ide_pio_datablock(drive, rq, 0); 461 ide_pio_datablock(drive, rq, 0);
462 462
463 /* Are we done? Check status and finis 463 /* Are we done? Check status and finish transfer. */
464 if (!hwif->nleft) { 464 if (!hwif->nleft) {
465 stat = wait_drive_not_busy(dri 465 stat = wait_drive_not_busy(drive);
466 if (!OK_STAT(stat, 0, BAD_STAT 466 if (!OK_STAT(stat, 0, BAD_STAT))
467 return task_error(driv 467 return task_error(drive, rq, __FUNCTION__, stat);
468 task_end_request(drive, rq, st 468 task_end_request(drive, rq, stat);
469 return ide_stopped; 469 return ide_stopped;
470 } 470 }
471 471
472 /* Still data left to transfer. */ 472 /* Still data left to transfer. */
473 ide_set_handler(drive, &task_in_intr, 473 ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
474 474
475 return ide_started; 475 return ide_started;
476 } 476 }
477 477
478 /* 478 /*
479 * Handler for command with PIO data-out phase 479 * Handler for command with PIO data-out phase (Write/Write Multiple).
480 */ 480 */
481 static ide_startstop_t task_out_intr (ide_driv 481 static ide_startstop_t task_out_intr (ide_drive_t *drive)
482 { 482 {
483 ide_hwif_t *hwif = drive->hwif; 483 ide_hwif_t *hwif = drive->hwif;
484 struct request *rq = HWGROUP(drive)->r 484 struct request *rq = HWGROUP(drive)->rq;
485 u8 stat = ide_read_status(drive); 485 u8 stat = ide_read_status(drive);
486 486
487 if (!OK_STAT(stat, DRIVE_READY, drive- 487 if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
488 return task_error(drive, rq, _ 488 return task_error(drive, rq, __FUNCTION__, stat);
489 489
490 /* Deal with unexpected ATA data phase 490 /* Deal with unexpected ATA data phase. */
491 if (((stat & DRQ_STAT) == 0) ^ !hwif-> 491 if (((stat & DRQ_STAT) == 0) ^ !hwif->nleft)
492 return task_error(drive, rq, _ 492 return task_error(drive, rq, __FUNCTION__, stat);
493 493
494 if (!hwif->nleft) { 494 if (!hwif->nleft) {
495 task_end_request(drive, rq, st 495 task_end_request(drive, rq, stat);
496 return ide_stopped; 496 return ide_stopped;
497 } 497 }
498 498
499 /* Still data left to transfer. */ 499 /* Still data left to transfer. */
500 ide_pio_datablock(drive, rq, 1); 500 ide_pio_datablock(drive, rq, 1);
501 ide_set_handler(drive, &task_out_intr, 501 ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
502 502
503 return ide_started; 503 return ide_started;
504 } 504 }
505 505
506 static ide_startstop_t pre_task_out_intr(ide_d 506 static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
507 { 507 {
508 ide_startstop_t startstop; 508 ide_startstop_t startstop;
509 509
510 if (ide_wait_stat(&startstop, drive, D 510 if (ide_wait_stat(&startstop, drive, DRQ_STAT,
511 drive->bad_wstat, WA 511 drive->bad_wstat, WAIT_DRQ)) {
512 printk(KERN_ERR "%s: no DRQ af 512 printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
513 drive->name, 513 drive->name,
514 drive->hwif->d 514 drive->hwif->data_phase ? "MULT" : "",
515 drive->address 515 drive->addressing ? "_EXT" : "");
516 return startstop; 516 return startstop;
517 } 517 }
518 518
519 if (!drive->unmask) 519 if (!drive->unmask)
520 local_irq_disable(); !! 520 local_irq_disable_nort();
521 521
522 ide_set_handler(drive, &task_out_intr, 522 ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
523 ide_pio_datablock(drive, rq, 1); 523 ide_pio_datablock(drive, rq, 1);
524 524
525 return ide_started; 525 return ide_started;
526 } 526 }
527 527
528 int ide_raw_taskfile(ide_drive_t *drive, ide_t 528 int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
529 { 529 {
530 struct request rq; 530 struct request rq;
531 531
532 memset(&rq, 0, sizeof(rq)); 532 memset(&rq, 0, sizeof(rq));
533 rq.ref_count = 1; 533 rq.ref_count = 1;
534 rq.cmd_type = REQ_TYPE_ATA_TASKFILE; 534 rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
535 rq.buffer = buf; 535 rq.buffer = buf;
536 536
537 /* 537 /*
538 * (ks) We transfer currently only who 538 * (ks) We transfer currently only whole sectors.
539 * This is suffient for now. But, it 539 * This is suffient for now. But, it would be great,
540 * if we would find a solution to tran 540 * if we would find a solution to transfer any size.
541 * To support special commands like RE 541 * To support special commands like READ LONG.
542 */ 542 */
543 rq.hard_nr_sectors = rq.nr_sectors = n 543 rq.hard_nr_sectors = rq.nr_sectors = nsect;
544 rq.hard_cur_sectors = rq.current_nr_se 544 rq.hard_cur_sectors = rq.current_nr_sectors = nsect;
545 545
546 if (task->tf_flags & IDE_TFLAG_WRITE) 546 if (task->tf_flags & IDE_TFLAG_WRITE)
547 rq.cmd_flags |= REQ_RW; 547 rq.cmd_flags |= REQ_RW;
548 548
549 rq.special = task; 549 rq.special = task;
550 task->rq = &rq; 550 task->rq = &rq;
551 551
552 return ide_do_drive_cmd(drive, &rq, id 552 return ide_do_drive_cmd(drive, &rq, ide_wait);
553 } 553 }
554 554
555 EXPORT_SYMBOL(ide_raw_taskfile); 555 EXPORT_SYMBOL(ide_raw_taskfile);
556 556
557 int ide_no_data_taskfile(ide_drive_t *drive, i 557 int ide_no_data_taskfile(ide_drive_t *drive, ide_task_t *task)
558 { 558 {
559 task->data_phase = TASKFILE_NO_DATA; 559 task->data_phase = TASKFILE_NO_DATA;
560 560
561 return ide_raw_taskfile(drive, task, N 561 return ide_raw_taskfile(drive, task, NULL, 0);
562 } 562 }
563 EXPORT_SYMBOL_GPL(ide_no_data_taskfile); 563 EXPORT_SYMBOL_GPL(ide_no_data_taskfile);
564 564
565 #ifdef CONFIG_IDE_TASK_IOCTL 565 #ifdef CONFIG_IDE_TASK_IOCTL
566 int ide_taskfile_ioctl (ide_drive_t *drive, un 566 int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
567 { 567 {
568 ide_task_request_t *req_task; 568 ide_task_request_t *req_task;
569 ide_task_t args; 569 ide_task_t args;
570 u8 *outbuf = NULL; 570 u8 *outbuf = NULL;
571 u8 *inbuf = NULL; 571 u8 *inbuf = NULL;
572 u8 *data_buf = NULL; 572 u8 *data_buf = NULL;
573 int err = 0; 573 int err = 0;
574 int tasksize = sizeof(struc 574 int tasksize = sizeof(struct ide_task_request_s);
575 unsigned int taskin = 0; 575 unsigned int taskin = 0;
576 unsigned int taskout = 0; 576 unsigned int taskout = 0;
577 u16 nsect = 0; 577 u16 nsect = 0;
578 char __user *buf = (char __user *)arg; 578 char __user *buf = (char __user *)arg;
579 579
580 // printk("IDE Taskfile ...\n"); 580 // printk("IDE Taskfile ...\n");
581 581
582 req_task = kzalloc(tasksize, GFP_KERNE 582 req_task = kzalloc(tasksize, GFP_KERNEL);
583 if (req_task == NULL) return -ENOMEM; 583 if (req_task == NULL) return -ENOMEM;
584 if (copy_from_user(req_task, buf, task 584 if (copy_from_user(req_task, buf, tasksize)) {
585 kfree(req_task); 585 kfree(req_task);
586 return -EFAULT; 586 return -EFAULT;
587 } 587 }
588 588
589 taskout = req_task->out_size; 589 taskout = req_task->out_size;
590 taskin = req_task->in_size; 590 taskin = req_task->in_size;
591 591
592 if (taskin > 65536 || taskout > 65536) 592 if (taskin > 65536 || taskout > 65536) {
593 err = -EINVAL; 593 err = -EINVAL;
594 goto abort; 594 goto abort;
595 } 595 }
596 596
597 if (taskout) { 597 if (taskout) {
598 int outtotal = tasksize; 598 int outtotal = tasksize;
599 outbuf = kzalloc(taskout, GFP_ 599 outbuf = kzalloc(taskout, GFP_KERNEL);
600 if (outbuf == NULL) { 600 if (outbuf == NULL) {
601 err = -ENOMEM; 601 err = -ENOMEM;
602 goto abort; 602 goto abort;
603 } 603 }
604 if (copy_from_user(outbuf, buf 604 if (copy_from_user(outbuf, buf + outtotal, taskout)) {
605 err = -EFAULT; 605 err = -EFAULT;
606 goto abort; 606 goto abort;
607 } 607 }
608 } 608 }
609 609
610 if (taskin) { 610 if (taskin) {
611 int intotal = tasksize + tasko 611 int intotal = tasksize + taskout;
612 inbuf = kzalloc(taskin, GFP_KE 612 inbuf = kzalloc(taskin, GFP_KERNEL);
613 if (inbuf == NULL) { 613 if (inbuf == NULL) {
614 err = -ENOMEM; 614 err = -ENOMEM;
615 goto abort; 615 goto abort;
616 } 616 }
617 if (copy_from_user(inbuf, buf 617 if (copy_from_user(inbuf, buf + intotal, taskin)) {
618 err = -EFAULT; 618 err = -EFAULT;
619 goto abort; 619 goto abort;
620 } 620 }
621 } 621 }
622 622
623 memset(&args, 0, sizeof(ide_task_t)); 623 memset(&args, 0, sizeof(ide_task_t));
624 624
625 memcpy(&args.tf_array[0], req_task->ho 625 memcpy(&args.tf_array[0], req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2);
626 memcpy(&args.tf_array[6], req_task->io 626 memcpy(&args.tf_array[6], req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
627 627
628 args.data_phase = req_task->data_phase 628 args.data_phase = req_task->data_phase;
629 629
630 args.tf_flags = IDE_TFLAG_IO_16BIT | I 630 args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE |
631 IDE_TFLAG_IN_TF; 631 IDE_TFLAG_IN_TF;
632 if (drive->addressing == 1) 632 if (drive->addressing == 1)
633 args.tf_flags |= (IDE_TFLAG_LB 633 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB);
634 634
635 if (req_task->out_flags.all) { 635 if (req_task->out_flags.all) {
636 args.tf_flags |= IDE_TFLAG_FLA 636 args.tf_flags |= IDE_TFLAG_FLAGGED;
637 637
638 if (req_task->out_flags.b.data 638 if (req_task->out_flags.b.data)
639 args.tf_flags |= IDE_T 639 args.tf_flags |= IDE_TFLAG_OUT_DATA;
640 640
641 if (req_task->out_flags.b.nsec 641 if (req_task->out_flags.b.nsector_hob)
642 args.tf_flags |= IDE_T 642 args.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT;
643 if (req_task->out_flags.b.sect 643 if (req_task->out_flags.b.sector_hob)
644 args.tf_flags |= IDE_T 644 args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL;
645 if (req_task->out_flags.b.lcyl 645 if (req_task->out_flags.b.lcyl_hob)
646 args.tf_flags |= IDE_T 646 args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM;
647 if (req_task->out_flags.b.hcyl 647 if (req_task->out_flags.b.hcyl_hob)
648 args.tf_flags |= IDE_T 648 args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH;
649 649
650 if (req_task->out_flags.b.erro 650 if (req_task->out_flags.b.error_feature)
651 args.tf_flags |= IDE_T 651 args.tf_flags |= IDE_TFLAG_OUT_FEATURE;
652 if (req_task->out_flags.b.nsec 652 if (req_task->out_flags.b.nsector)
653 args.tf_flags |= IDE_T 653 args.tf_flags |= IDE_TFLAG_OUT_NSECT;
654 if (req_task->out_flags.b.sect 654 if (req_task->out_flags.b.sector)
655 args.tf_flags |= IDE_T 655 args.tf_flags |= IDE_TFLAG_OUT_LBAL;
656 if (req_task->out_flags.b.lcyl 656 if (req_task->out_flags.b.lcyl)
657 args.tf_flags |= IDE_T 657 args.tf_flags |= IDE_TFLAG_OUT_LBAM;
658 if (req_task->out_flags.b.hcyl 658 if (req_task->out_flags.b.hcyl)
659 args.tf_flags |= IDE_T 659 args.tf_flags |= IDE_TFLAG_OUT_LBAH;
660 } else { 660 } else {
661 args.tf_flags |= IDE_TFLAG_OUT 661 args.tf_flags |= IDE_TFLAG_OUT_TF;
662 if (args.tf_flags & IDE_TFLAG_ 662 if (args.tf_flags & IDE_TFLAG_LBA48)
663 args.tf_flags |= IDE_T 663 args.tf_flags |= IDE_TFLAG_OUT_HOB;
664 } 664 }
665 665
666 if (req_task->in_flags.b.data) 666 if (req_task->in_flags.b.data)
667 args.tf_flags |= IDE_TFLAG_IN_ 667 args.tf_flags |= IDE_TFLAG_IN_DATA;
668 668
669 switch(req_task->data_phase) { 669 switch(req_task->data_phase) {
670 case TASKFILE_MULTI_OUT: 670 case TASKFILE_MULTI_OUT:
671 if (!drive->mult_count 671 if (!drive->mult_count) {
672 /* (hs): give 672 /* (hs): give up if multcount is not set */
673 printk(KERN_ER 673 printk(KERN_ERR "%s: %s Multimode Write " \
674 "multc 674 "multcount is not set\n",
675 drive- 675 drive->name, __FUNCTION__);
676 err = -EPERM; 676 err = -EPERM;
677 goto abort; 677 goto abort;
678 } 678 }
679 /* fall through */ 679 /* fall through */
680 case TASKFILE_OUT: 680 case TASKFILE_OUT:
681 /* fall through */ 681 /* fall through */
682 case TASKFILE_OUT_DMAQ: 682 case TASKFILE_OUT_DMAQ:
683 case TASKFILE_OUT_DMA: 683 case TASKFILE_OUT_DMA:
684 nsect = taskout / SECT 684 nsect = taskout / SECTOR_SIZE;
685 data_buf = outbuf; 685 data_buf = outbuf;
686 break; 686 break;
687 case TASKFILE_MULTI_IN: 687 case TASKFILE_MULTI_IN:
688 if (!drive->mult_count 688 if (!drive->mult_count) {
689 /* (hs): give 689 /* (hs): give up if multcount is not set */
690 printk(KERN_ER 690 printk(KERN_ERR "%s: %s Multimode Read failure " \
691 "multc 691 "multcount is not set\n",
692 drive- 692 drive->name, __FUNCTION__);
693 err = -EPERM; 693 err = -EPERM;
694 goto abort; 694 goto abort;
695 } 695 }
696 /* fall through */ 696 /* fall through */
697 case TASKFILE_IN: 697 case TASKFILE_IN:
698 /* fall through */ 698 /* fall through */
699 case TASKFILE_IN_DMAQ: 699 case TASKFILE_IN_DMAQ:
700 case TASKFILE_IN_DMA: 700 case TASKFILE_IN_DMA:
701 nsect = taskin / SECTO 701 nsect = taskin / SECTOR_SIZE;
702 data_buf = inbuf; 702 data_buf = inbuf;
703 break; 703 break;
704 case TASKFILE_NO_DATA: 704 case TASKFILE_NO_DATA:
705 break; 705 break;
706 default: 706 default:
707 err = -EFAULT; 707 err = -EFAULT;
708 goto abort; 708 goto abort;
709 } 709 }
710 710
711 if (req_task->req_cmd == IDE_DRIVE_TAS 711 if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA)
712 nsect = 0; 712 nsect = 0;
713 else if (!nsect) { 713 else if (!nsect) {
714 nsect = (args.tf.hob_nsect << 714 nsect = (args.tf.hob_nsect << 8) | args.tf.nsect;
715 715
716 if (!nsect) { 716 if (!nsect) {
717 printk(KERN_ERR "%s: i 717 printk(KERN_ERR "%s: in/out command without data\n",
718 drive- 718 drive->name);
719 err = -EFAULT; 719 err = -EFAULT;
720 goto abort; 720 goto abort;
721 } 721 }
722 } 722 }
723 723
724 if (req_task->req_cmd == IDE_DRIVE_TAS 724 if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE)
725 args.tf_flags |= IDE_TFLAG_WRI 725 args.tf_flags |= IDE_TFLAG_WRITE;
726 726
727 err = ide_raw_taskfile(drive, &args, d 727 err = ide_raw_taskfile(drive, &args, data_buf, nsect);
728 728
729 memcpy(req_task->hob_ports, &args.tf_a 729 memcpy(req_task->hob_ports, &args.tf_array[0], HDIO_DRIVE_HOB_HDR_SIZE - 2);
730 memcpy(req_task->io_ports, &args.tf_ar 730 memcpy(req_task->io_ports, &args.tf_array[6], HDIO_DRIVE_TASK_HDR_SIZE);
731 731
732 if ((args.tf_flags & IDE_TFLAG_FLAGGED 732 if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) &&
733 req_task->in_flags.all == 0) { 733 req_task->in_flags.all == 0) {
734 req_task->in_flags.all = IDE_T 734 req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
735 if (drive->addressing == 1) 735 if (drive->addressing == 1)
736 req_task->in_flags.all 736 req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
737 } 737 }
738 738
739 if (copy_to_user(buf, req_task, tasksi 739 if (copy_to_user(buf, req_task, tasksize)) {
740 err = -EFAULT; 740 err = -EFAULT;
741 goto abort; 741 goto abort;
742 } 742 }
743 if (taskout) { 743 if (taskout) {
744 int outtotal = tasksize; 744 int outtotal = tasksize;
745 if (copy_to_user(buf + outtota 745 if (copy_to_user(buf + outtotal, outbuf, taskout)) {
746 err = -EFAULT; 746 err = -EFAULT;
747 goto abort; 747 goto abort;
748 } 748 }
749 } 749 }
750 if (taskin) { 750 if (taskin) {
751 int intotal = tasksize + tasko 751 int intotal = tasksize + taskout;
752 if (copy_to_user(buf + intotal 752 if (copy_to_user(buf + intotal, inbuf, taskin)) {
753 err = -EFAULT; 753 err = -EFAULT;
754 goto abort; 754 goto abort;
755 } 755 }
756 } 756 }
757 abort: 757 abort:
758 kfree(req_task); 758 kfree(req_task);
759 kfree(outbuf); 759 kfree(outbuf);
760 kfree(inbuf); 760 kfree(inbuf);
761 761
762 // printk("IDE Taskfile ioctl ended. rc = 762 // printk("IDE Taskfile ioctl ended. rc = %i\n", err);
763 763
764 return err; 764 return err;
765 } 765 }
766 #endif 766 #endif
767 767
768 int ide_cmd_ioctl (ide_drive_t *drive, unsigne 768 int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
769 { 769 {
770 u8 *buf = NULL; 770 u8 *buf = NULL;
771 int bufsize = 0, err = 0; 771 int bufsize = 0, err = 0;
772 u8 args[4], xfer_rate = 0; 772 u8 args[4], xfer_rate = 0;
773 ide_task_t tfargs; 773 ide_task_t tfargs;
774 struct ide_taskfile *tf = &tfargs.tf; 774 struct ide_taskfile *tf = &tfargs.tf;
775 struct hd_driveid *id = drive->id; 775 struct hd_driveid *id = drive->id;
776 776
777 if (NULL == (void *) arg) { 777 if (NULL == (void *) arg) {
778 struct request rq; 778 struct request rq;
779 779
780 ide_init_drive_cmd(&rq); 780 ide_init_drive_cmd(&rq);
781 rq.cmd_type = REQ_TYPE_ATA_TAS 781 rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
782 782
783 return ide_do_drive_cmd(drive, 783 return ide_do_drive_cmd(drive, &rq, ide_wait);
784 } 784 }
785 785
786 if (copy_from_user(args, (void __user 786 if (copy_from_user(args, (void __user *)arg, 4))
787 return -EFAULT; 787 return -EFAULT;
788 788
789 memset(&tfargs, 0, sizeof(ide_task_t)) 789 memset(&tfargs, 0, sizeof(ide_task_t));
790 tf->feature = args[2]; 790 tf->feature = args[2];
791 if (args[0] == WIN_SMART) { 791 if (args[0] == WIN_SMART) {
792 tf->nsect = args[3]; 792 tf->nsect = args[3];
793 tf->lbal = args[1]; 793 tf->lbal = args[1];
794 tf->lbam = 0x4f; 794 tf->lbam = 0x4f;
795 tf->lbah = 0xc2; 795 tf->lbah = 0xc2;
796 tfargs.tf_flags = IDE_TFLAG_OU 796 tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT;
797 } else { 797 } else {
798 tf->nsect = args[1]; 798 tf->nsect = args[1];
799 tfargs.tf_flags = IDE_TFLAG_OU 799 tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
800 IDE_TFLAG_OU 800 IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
801 } 801 }
802 tf->command = args[0]; 802 tf->command = args[0];
803 tfargs.data_phase = args[3] ? TASKFILE 803 tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
804 804
805 if (args[3]) { 805 if (args[3]) {
806 tfargs.tf_flags |= IDE_TFLAG_I 806 tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
807 bufsize = SECTOR_WORDS * 4 * a 807 bufsize = SECTOR_WORDS * 4 * args[3];
808 buf = kzalloc(bufsize, GFP_KER 808 buf = kzalloc(bufsize, GFP_KERNEL);
809 if (buf == NULL) 809 if (buf == NULL)
810 return -ENOMEM; 810 return -ENOMEM;
811 } 811 }
812 812
813 if (tf->command == WIN_SETFEATURES && 813 if (tf->command == WIN_SETFEATURES &&
814 tf->feature == SETFEATURES_XFER && 814 tf->feature == SETFEATURES_XFER &&
815 tf->nsect >= XFER_SW_DMA_0 && 815 tf->nsect >= XFER_SW_DMA_0 &&
816 (id->dma_ultra || id->dma_mword || 816 (id->dma_ultra || id->dma_mword || id->dma_1word)) {
817 xfer_rate = args[1]; 817 xfer_rate = args[1];
818 if (tf->nsect > XFER_UDMA_2 && 818 if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) {
819 printk(KERN_WARNING "% 819 printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
820 "b 820 "be set\n", drive->name);
821 goto abort; 821 goto abort;
822 } 822 }
823 } 823 }
824 824
825 err = ide_raw_taskfile(drive, &tfargs, 825 err = ide_raw_taskfile(drive, &tfargs, buf, args[3]);
826 826
827 args[0] = tf->status; 827 args[0] = tf->status;
828 args[1] = tf->error; 828 args[1] = tf->error;
829 args[2] = tf->nsect; 829 args[2] = tf->nsect;
830 830
831 if (!err && xfer_rate) { 831 if (!err && xfer_rate) {
832 /* active-retuning-calls futur 832 /* active-retuning-calls future */
833 ide_set_xfer_rate(drive, xfer_ 833 ide_set_xfer_rate(drive, xfer_rate);
834 ide_driveid_update(drive); 834 ide_driveid_update(drive);
835 } 835 }
836 abort: 836 abort:
837 if (copy_to_user((void __user *)arg, & 837 if (copy_to_user((void __user *)arg, &args, 4))
838 err = -EFAULT; 838 err = -EFAULT;
839 if (buf) { 839 if (buf) {
840 if (copy_to_user((void __user 840 if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
841 err = -EFAULT; 841 err = -EFAULT;
842 kfree(buf); 842 kfree(buf);
843 } 843 }
844 return err; 844 return err;
845 } 845 }
846 846
847 int ide_task_ioctl (ide_drive_t *drive, unsign 847 int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
848 { 848 {
849 void __user *p = (void __user *)arg; 849 void __user *p = (void __user *)arg;
850 int err = 0; 850 int err = 0;
851 u8 args[7]; 851 u8 args[7];
852 ide_task_t task; 852 ide_task_t task;
853 853
854 if (copy_from_user(args, p, 7)) 854 if (copy_from_user(args, p, 7))
855 return -EFAULT; 855 return -EFAULT;
856 856
857 memset(&task, 0, sizeof(task)); 857 memset(&task, 0, sizeof(task));
858 memcpy(&task.tf_array[7], &args[1], 6) 858 memcpy(&task.tf_array[7], &args[1], 6);
859 task.tf.command = args[0]; 859 task.tf.command = args[0];
860 task.tf_flags = IDE_TFLAG_TF | IDE_TFL 860 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
861 861
862 err = ide_no_data_taskfile(drive, &tas 862 err = ide_no_data_taskfile(drive, &task);
863 863
864 args[0] = task.tf.command; 864 args[0] = task.tf.command;
865 memcpy(&args[1], &task.tf_array[7], 6) 865 memcpy(&args[1], &task.tf_array[7], 6);
866 866
867 if (copy_to_user(p, args, 7)) 867 if (copy_to_user(p, args, 7))
868 err = -EFAULT; 868 err = -EFAULT;
869 869
870 return err; 870 return err;
871 } 871 }
872 872
|
This page was automatically generated by the
LXR engine.
|