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