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