linux/drivers/ide/ide-taskfile.c
<<
>>
Prefs
   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/export.h>
  15#include <linux/sched.h>
  16#include <linux/interrupt.h>
  17#include <linux/errno.h>
  18#include <linux/slab.h>
  19#include <linux/delay.h>
  20#include <linux/hdreg.h>
  21#include <linux/ide.h>
  22#include <linux/nmi.h>
  23#include <linux/scatterlist.h>
  24#include <linux/uaccess.h>
  25
  26#include <asm/io.h>
  27
  28void ide_tf_readback(ide_drive_t *drive, struct ide_cmd *cmd)
  29{
  30        ide_hwif_t *hwif = drive->hwif;
  31        const struct ide_tp_ops *tp_ops = hwif->tp_ops;
  32
  33        /* Be sure we're looking at the low order bytes */
  34        tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
  35
  36        tp_ops->tf_read(drive, &cmd->tf, cmd->valid.in.tf);
  37
  38        if (cmd->tf_flags & IDE_TFLAG_LBA48) {
  39                tp_ops->write_devctl(hwif, ATA_HOB | ATA_DEVCTL_OBS);
  40
  41                tp_ops->tf_read(drive, &cmd->hob, cmd->valid.in.hob);
  42        }
  43}
  44
  45void ide_tf_dump(const char *s, struct ide_cmd *cmd)
  46{
  47#ifdef DEBUG
  48        printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x "
  49                "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n",
  50               s, cmd->tf.feature, cmd->tf.nsect,
  51               cmd->tf.lbal, cmd->tf.lbam, cmd->tf.lbah,
  52               cmd->tf.device, cmd->tf.command);
  53        printk("%s: hob: nsect 0x%02x lbal 0x%02x lbam 0x%02x lbah 0x%02x\n",
  54               s, cmd->hob.nsect, cmd->hob.lbal, cmd->hob.lbam, cmd->hob.lbah);
  55#endif
  56}
  57
  58int taskfile_lib_get_identify(ide_drive_t *drive, u8 *buf)
  59{
  60        struct ide_cmd cmd;
  61
  62        memset(&cmd, 0, sizeof(cmd));
  63        cmd.tf.nsect = 0x01;
  64        if (drive->media == ide_disk)
  65                cmd.tf.command = ATA_CMD_ID_ATA;
  66        else
  67                cmd.tf.command = ATA_CMD_ID_ATAPI;
  68        cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
  69        cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
  70        cmd.protocol = ATA_PROT_PIO;
  71
  72        return ide_raw_taskfile(drive, &cmd, buf, 1);
  73}
  74
  75static ide_startstop_t task_no_data_intr(ide_drive_t *);
  76static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct ide_cmd *);
  77static ide_startstop_t task_pio_intr(ide_drive_t *);
  78
  79ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd)
  80{
  81        ide_hwif_t *hwif = drive->hwif;
  82        struct ide_cmd *cmd = &hwif->cmd;
  83        struct ide_taskfile *tf = &cmd->tf;
  84        ide_handler_t *handler = NULL;
  85        const struct ide_tp_ops *tp_ops = hwif->tp_ops;
  86        const struct ide_dma_ops *dma_ops = hwif->dma_ops;
  87
  88        if (orig_cmd->protocol == ATA_PROT_PIO &&
  89            (orig_cmd->tf_flags & IDE_TFLAG_MULTI_PIO) &&
  90            drive->mult_count == 0) {
  91                pr_err("%s: multimode not set!\n", drive->name);
  92                return ide_stopped;
  93        }
  94
  95        if (orig_cmd->ftf_flags & IDE_FTFLAG_FLAGGED)
  96                orig_cmd->ftf_flags |= IDE_FTFLAG_SET_IN_FLAGS;
  97
  98        memcpy(cmd, orig_cmd, sizeof(*cmd));
  99
 100        if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
 101                ide_tf_dump(drive->name, cmd);
 102                tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
 103
 104                if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) {
 105                        u8 data[2] = { cmd->tf.data, cmd->hob.data };
 106
 107                        tp_ops->output_data(drive, cmd, data, 2);
 108                }
 109
 110                if (cmd->valid.out.tf & IDE_VALID_DEVICE) {
 111                        u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ?
 112                                  0xE0 : 0xEF;
 113
 114                        if (!(cmd->ftf_flags & IDE_FTFLAG_FLAGGED))
 115                                cmd->tf.device &= HIHI;
 116                        cmd->tf.device |= drive->select;
 117                }
 118
 119                tp_ops->tf_load(drive, &cmd->hob, cmd->valid.out.hob);
 120                tp_ops->tf_load(drive, &cmd->tf,  cmd->valid.out.tf);
 121        }
 122
 123        switch (cmd->protocol) {
 124        case ATA_PROT_PIO:
 125                if (cmd->tf_flags & IDE_TFLAG_WRITE) {
 126                        tp_ops->exec_command(hwif, tf->command);
 127                        ndelay(400);    /* FIXME */
 128                        return pre_task_out_intr(drive, cmd);
 129                }
 130                handler = task_pio_intr;
 131                /* fall through */
 132        case ATA_PROT_NODATA:
 133                if (handler == NULL)
 134                        handler = task_no_data_intr;
 135                ide_execute_command(drive, cmd, handler, WAIT_WORSTCASE);
 136                return ide_started;
 137        case ATA_PROT_DMA:
 138                if (ide_dma_prepare(drive, cmd))
 139                        return ide_stopped;
 140                hwif->expiry = dma_ops->dma_timer_expiry;
 141                ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD);
 142                dma_ops->dma_start(drive);
 143                /* fall through */
 144        default:
 145                return ide_started;
 146        }
 147}
 148EXPORT_SYMBOL_GPL(do_rw_taskfile);
 149
 150static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
 151{
 152        ide_hwif_t *hwif = drive->hwif;
 153        struct ide_cmd *cmd = &hwif->cmd;
 154        struct ide_taskfile *tf = &cmd->tf;
 155        int custom = (cmd->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) ? 1 : 0;
 156        int retries = (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) ? 5 : 1;
 157        u8 stat;
 158
 159        local_irq_enable_in_hardirq();
 160
 161        while (1) {
 162                stat = hwif->tp_ops->read_status(hwif);
 163                if ((stat & ATA_BUSY) == 0 || retries-- == 0)
 164                        break;
 165                udelay(10);
 166        };
 167
 168        if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
 169                if (custom && tf->command == ATA_CMD_SET_MULTI) {
 170                        drive->mult_req = drive->mult_count = 0;
 171                        drive->special_flags |= IDE_SFLAG_RECALIBRATE;
 172                        (void)ide_dump_status(drive, __func__, stat);
 173                        return ide_stopped;
 174                } else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) {
 175                        if ((stat & (ATA_ERR | ATA_DRQ)) == 0) {
 176                                ide_set_handler(drive, &task_no_data_intr,
 177                                                WAIT_WORSTCASE);
 178                                return ide_started;
 179                        }
 180                }
 181                return ide_error(drive, "task_no_data_intr", stat);
 182        }
 183
 184        if (custom && tf->command == ATA_CMD_SET_MULTI)
 185                drive->mult_count = drive->mult_req;
 186
 187        if (custom == 0 || tf->command == ATA_CMD_IDLEIMMEDIATE ||
 188            tf->command == ATA_CMD_CHK_POWER) {
 189                struct request *rq = hwif->rq;
 190
 191                if (ata_pm_request(rq))
 192                        ide_complete_pm_rq(drive, rq);
 193                else
 194                        ide_finish_cmd(drive, cmd, stat);
 195        }
 196
 197        return ide_stopped;
 198}
 199
 200static u8 wait_drive_not_busy(ide_drive_t *drive)
 201{
 202        ide_hwif_t *hwif = drive->hwif;
 203        int retries;
 204        u8 stat;
 205
 206        /*
 207         * Last sector was transferred, wait until device is ready.  This can
 208         * take up to 6 ms on some ATAPI devices, so we will wait max 10 ms.
 209         */
 210        for (retries = 0; retries < 1000; retries++) {
 211                stat = hwif->tp_ops->read_status(hwif);
 212
 213                if (stat & ATA_BUSY)
 214                        udelay(10);
 215                else
 216                        break;
 217        }
 218
 219        if (stat & ATA_BUSY)
 220                pr_err("%s: drive still BUSY!\n", drive->name);
 221
 222        return stat;
 223}
 224
 225void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd,
 226                   unsigned int write, unsigned int len)
 227{
 228        ide_hwif_t *hwif = drive->hwif;
 229        struct scatterlist *sg = hwif->sg_table;
 230        struct scatterlist *cursg = cmd->cursg;
 231        unsigned long uninitialized_var(flags);
 232        struct page *page;
 233        unsigned int offset;
 234        u8 *buf;
 235
 236        if (cursg == NULL)
 237                cursg = cmd->cursg = sg;
 238
 239        while (len) {
 240                unsigned nr_bytes = min(len, cursg->length - cmd->cursg_ofs);
 241
 242                page = sg_page(cursg);
 243                offset = cursg->offset + cmd->cursg_ofs;
 244
 245                /* get the current page and offset */
 246                page = nth_page(page, (offset >> PAGE_SHIFT));
 247                offset %= PAGE_SIZE;
 248
 249                nr_bytes = min_t(unsigned, nr_bytes, (PAGE_SIZE - offset));
 250
 251                buf = kmap_atomic(page) + offset;
 252
 253                cmd->nleft -= nr_bytes;
 254                cmd->cursg_ofs += nr_bytes;
 255
 256                if (cmd->cursg_ofs == cursg->length) {
 257                        cursg = cmd->cursg = sg_next(cmd->cursg);
 258                        cmd->cursg_ofs = 0;
 259                }
 260
 261                /* do the actual data transfer */
 262                if (write)
 263                        hwif->tp_ops->output_data(drive, cmd, buf, nr_bytes);
 264                else
 265                        hwif->tp_ops->input_data(drive, cmd, buf, nr_bytes);
 266
 267                kunmap_atomic(buf);
 268
 269                len -= nr_bytes;
 270        }
 271}
 272EXPORT_SYMBOL_GPL(ide_pio_bytes);
 273
 274static void ide_pio_datablock(ide_drive_t *drive, struct ide_cmd *cmd,
 275                              unsigned int write)
 276{
 277        unsigned int nr_bytes;
 278
 279        u8 saved_io_32bit = drive->io_32bit;
 280
 281        if (cmd->tf_flags & IDE_TFLAG_FS)
 282                scsi_req(cmd->rq)->result = 0;
 283
 284        if (cmd->tf_flags & IDE_TFLAG_IO_16BIT)
 285                drive->io_32bit = 0;
 286
 287        touch_softlockup_watchdog();
 288
 289        if (cmd->tf_flags & IDE_TFLAG_MULTI_PIO)
 290                nr_bytes = min_t(unsigned, cmd->nleft, drive->mult_count << 9);
 291        else
 292                nr_bytes = SECTOR_SIZE;
 293
 294        ide_pio_bytes(drive, cmd, write, nr_bytes);
 295
 296        drive->io_32bit = saved_io_32bit;
 297}
 298
 299static void ide_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
 300{
 301        if (cmd->tf_flags & IDE_TFLAG_FS) {
 302                int nr_bytes = cmd->nbytes - cmd->nleft;
 303
 304                if (cmd->protocol == ATA_PROT_PIO &&
 305                    ((cmd->tf_flags & IDE_TFLAG_WRITE) || cmd->nleft == 0)) {
 306                        if (cmd->tf_flags & IDE_TFLAG_MULTI_PIO)
 307                                nr_bytes -= drive->mult_count << 9;
 308                        else
 309                                nr_bytes -= SECTOR_SIZE;
 310                }
 311
 312                if (nr_bytes > 0)
 313                        ide_complete_rq(drive, BLK_STS_OK, nr_bytes);
 314        }
 315}
 316
 317void ide_finish_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat)
 318{
 319        struct request *rq = drive->hwif->rq;
 320        u8 err = ide_read_error(drive), nsect = cmd->tf.nsect;
 321        u8 set_xfer = !!(cmd->tf_flags & IDE_TFLAG_SET_XFER);
 322
 323        ide_complete_cmd(drive, cmd, stat, err);
 324        scsi_req(rq)->result = err;
 325
 326        if (err == 0 && set_xfer) {
 327                ide_set_xfer_rate(drive, nsect);
 328                ide_driveid_update(drive);
 329        }
 330
 331        ide_complete_rq(drive, err ? BLK_STS_IOERR : BLK_STS_OK, blk_rq_bytes(rq));
 332}
 333
 334/*
 335 * Handler for command with PIO data phase.
 336 */
 337static ide_startstop_t task_pio_intr(ide_drive_t *drive)
 338{
 339        ide_hwif_t *hwif = drive->hwif;
 340        struct ide_cmd *cmd = &drive->hwif->cmd;
 341        u8 stat = hwif->tp_ops->read_status(hwif);
 342        u8 write = !!(cmd->tf_flags & IDE_TFLAG_WRITE);
 343
 344        if (write == 0) {
 345                /* Error? */
 346                if (stat & ATA_ERR)
 347                        goto out_err;
 348
 349                /* Didn't want any data? Odd. */
 350                if ((stat & ATA_DRQ) == 0) {
 351                        /* Command all done? */
 352                        if (OK_STAT(stat, ATA_DRDY, ATA_BUSY))
 353                                goto out_end;
 354
 355                        /* Assume it was a spurious irq */
 356                        goto out_wait;
 357                }
 358        } else {
 359                if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
 360                        goto out_err;
 361
 362                /* Deal with unexpected ATA data phase. */
 363                if (((stat & ATA_DRQ) == 0) ^ (cmd->nleft == 0))
 364                        goto out_err;
 365        }
 366
 367        if (write && cmd->nleft == 0)
 368                goto out_end;
 369
 370        /* Still data left to transfer. */
 371        ide_pio_datablock(drive, cmd, write);
 372
 373        /* Are we done? Check status and finish transfer. */
 374        if (write == 0 && cmd->nleft == 0) {
 375                stat = wait_drive_not_busy(drive);
 376                if (!OK_STAT(stat, 0, BAD_STAT))
 377                        goto out_err;
 378
 379                goto out_end;
 380        }
 381out_wait:
 382        /* Still data left to transfer. */
 383        ide_set_handler(drive, &task_pio_intr, WAIT_WORSTCASE);
 384        return ide_started;
 385out_end:
 386        if ((cmd->tf_flags & IDE_TFLAG_FS) == 0)
 387                ide_finish_cmd(drive, cmd, stat);
 388        else
 389                ide_complete_rq(drive, BLK_STS_OK, blk_rq_sectors(cmd->rq) << 9);
 390        return ide_stopped;
 391out_err:
 392        ide_error_cmd(drive, cmd);
 393        return ide_error(drive, __func__, stat);
 394}
 395
 396static ide_startstop_t pre_task_out_intr(ide_drive_t *drive,
 397                                         struct ide_cmd *cmd)
 398{
 399        ide_startstop_t startstop;
 400
 401        if (ide_wait_stat(&startstop, drive, ATA_DRQ,
 402                          drive->bad_wstat, WAIT_DRQ)) {
 403                pr_err("%s: no DRQ after issuing %sWRITE%s\n", drive->name,
 404                        (cmd->tf_flags & IDE_TFLAG_MULTI_PIO) ? "MULT" : "",
 405                        (drive->dev_flags & IDE_DFLAG_LBA48) ? "_EXT" : "");
 406                return startstop;
 407        }
 408
 409        if (!force_irqthreads && (drive->dev_flags & IDE_DFLAG_UNMASK) == 0)
 410                local_irq_disable();
 411
 412        ide_set_handler(drive, &task_pio_intr, WAIT_WORSTCASE);
 413
 414        ide_pio_datablock(drive, cmd, 1);
 415
 416        return ide_started;
 417}
 418
 419int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf,
 420                     u16 nsect)
 421{
 422        struct request *rq;
 423        int error;
 424
 425        rq = blk_get_request(drive->queue,
 426                (cmd->tf_flags & IDE_TFLAG_WRITE) ?
 427                        REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
 428        ide_req(rq)->type = ATA_PRIV_TASKFILE;
 429
 430        /*
 431         * (ks) We transfer currently only whole sectors.
 432         * This is suffient for now.  But, it would be great,
 433         * if we would find a solution to transfer any size.
 434         * To support special commands like READ LONG.
 435         */
 436        if (nsect) {
 437                error = blk_rq_map_kern(drive->queue, rq, buf,
 438                                        nsect * SECTOR_SIZE, GFP_NOIO);
 439                if (error)
 440                        goto put_req;
 441        }
 442
 443        rq->special = cmd;
 444        cmd->rq = rq;
 445
 446        blk_execute_rq(drive->queue, NULL, rq, 0);
 447        error = scsi_req(rq)->result ? -EIO : 0;
 448put_req:
 449        blk_put_request(rq);
 450        return error;
 451}
 452EXPORT_SYMBOL(ide_raw_taskfile);
 453
 454int ide_no_data_taskfile(ide_drive_t *drive, struct ide_cmd *cmd)
 455{
 456        cmd->protocol = ATA_PROT_NODATA;
 457
 458        return ide_raw_taskfile(drive, cmd, NULL, 0);
 459}
 460EXPORT_SYMBOL_GPL(ide_no_data_taskfile);
 461
 462#ifdef CONFIG_IDE_TASK_IOCTL
 463int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg)
 464{
 465        ide_task_request_t      *req_task;
 466        struct ide_cmd          cmd;
 467        u8 *outbuf              = NULL;
 468        u8 *inbuf               = NULL;
 469        u8 *data_buf            = NULL;
 470        int err                 = 0;
 471        int tasksize            = sizeof(struct ide_task_request_s);
 472        unsigned int taskin     = 0;
 473        unsigned int taskout    = 0;
 474        u16 nsect               = 0;
 475        char __user *buf = (char __user *)arg;
 476
 477        req_task = memdup_user(buf, tasksize);
 478        if (IS_ERR(req_task))
 479                return PTR_ERR(req_task);
 480
 481        taskout = req_task->out_size;
 482        taskin  = req_task->in_size;
 483
 484        if (taskin > 65536 || taskout > 65536) {
 485                err = -EINVAL;
 486                goto abort;
 487        }
 488
 489        if (taskout) {
 490                int outtotal = tasksize;
 491                outbuf = kzalloc(taskout, GFP_KERNEL);
 492                if (outbuf == NULL) {
 493                        err = -ENOMEM;
 494                        goto abort;
 495                }
 496                if (copy_from_user(outbuf, buf + outtotal, taskout)) {
 497                        err = -EFAULT;
 498                        goto abort;
 499                }
 500        }
 501
 502        if (taskin) {
 503                int intotal = tasksize + taskout;
 504                inbuf = kzalloc(taskin, GFP_KERNEL);
 505                if (inbuf == NULL) {
 506                        err = -ENOMEM;
 507                        goto abort;
 508                }
 509                if (copy_from_user(inbuf, buf + intotal, taskin)) {
 510                        err = -EFAULT;
 511                        goto abort;
 512                }
 513        }
 514
 515        memset(&cmd, 0, sizeof(cmd));
 516
 517        memcpy(&cmd.hob, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2);
 518        memcpy(&cmd.tf,  req_task->io_ports,  HDIO_DRIVE_TASK_HDR_SIZE);
 519
 520        cmd.valid.out.tf = IDE_VALID_DEVICE;
 521        cmd.valid.in.tf  = IDE_VALID_DEVICE | IDE_VALID_IN_TF;
 522        cmd.tf_flags = IDE_TFLAG_IO_16BIT;
 523
 524        if (drive->dev_flags & IDE_DFLAG_LBA48) {
 525                cmd.tf_flags |= IDE_TFLAG_LBA48;
 526                cmd.valid.in.hob = IDE_VALID_IN_HOB;
 527        }
 528
 529        if (req_task->out_flags.all) {
 530                cmd.ftf_flags |= IDE_FTFLAG_FLAGGED;
 531
 532                if (req_task->out_flags.b.data)
 533                        cmd.ftf_flags |= IDE_FTFLAG_OUT_DATA;
 534
 535                if (req_task->out_flags.b.nsector_hob)
 536                        cmd.valid.out.hob |= IDE_VALID_NSECT;
 537                if (req_task->out_flags.b.sector_hob)
 538                        cmd.valid.out.hob |= IDE_VALID_LBAL;
 539                if (req_task->out_flags.b.lcyl_hob)
 540                        cmd.valid.out.hob |= IDE_VALID_LBAM;
 541                if (req_task->out_flags.b.hcyl_hob)
 542                        cmd.valid.out.hob |= IDE_VALID_LBAH;
 543
 544                if (req_task->out_flags.b.error_feature)
 545                        cmd.valid.out.tf  |= IDE_VALID_FEATURE;
 546                if (req_task->out_flags.b.nsector)
 547                        cmd.valid.out.tf  |= IDE_VALID_NSECT;
 548                if (req_task->out_flags.b.sector)
 549                        cmd.valid.out.tf  |= IDE_VALID_LBAL;
 550                if (req_task->out_flags.b.lcyl)
 551                        cmd.valid.out.tf  |= IDE_VALID_LBAM;
 552                if (req_task->out_flags.b.hcyl)
 553                        cmd.valid.out.tf  |= IDE_VALID_LBAH;
 554        } else {
 555                cmd.valid.out.tf |= IDE_VALID_OUT_TF;
 556                if (cmd.tf_flags & IDE_TFLAG_LBA48)
 557                        cmd.valid.out.hob |= IDE_VALID_OUT_HOB;
 558        }
 559
 560        if (req_task->in_flags.b.data)
 561                cmd.ftf_flags |= IDE_FTFLAG_IN_DATA;
 562
 563        if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE) {
 564                /* fixup data phase if needed */
 565                if (req_task->data_phase == TASKFILE_IN_DMAQ ||
 566                    req_task->data_phase == TASKFILE_IN_DMA)
 567                        cmd.tf_flags |= IDE_TFLAG_WRITE;
 568        }
 569
 570        cmd.protocol = ATA_PROT_DMA;
 571
 572        switch (req_task->data_phase) {
 573        case TASKFILE_MULTI_OUT:
 574                if (!drive->mult_count) {
 575                        /* (hs): give up if multcount is not set */
 576                        pr_err("%s: %s Multimode Write multcount is not set\n",
 577                                drive->name, __func__);
 578                        err = -EPERM;
 579                        goto abort;
 580                }
 581                cmd.tf_flags |= IDE_TFLAG_MULTI_PIO;
 582                /* fall through */
 583        case TASKFILE_OUT:
 584                cmd.protocol = ATA_PROT_PIO;
 585                /* fall through */
 586        case TASKFILE_OUT_DMAQ:
 587        case TASKFILE_OUT_DMA:
 588                cmd.tf_flags |= IDE_TFLAG_WRITE;
 589                nsect = taskout / SECTOR_SIZE;
 590                data_buf = outbuf;
 591                break;
 592        case TASKFILE_MULTI_IN:
 593                if (!drive->mult_count) {
 594                        /* (hs): give up if multcount is not set */
 595                        pr_err("%s: %s Multimode Read multcount is not set\n",
 596                                drive->name, __func__);
 597                        err = -EPERM;
 598                        goto abort;
 599                }
 600                cmd.tf_flags |= IDE_TFLAG_MULTI_PIO;
 601                /* fall through */
 602        case TASKFILE_IN:
 603                cmd.protocol = ATA_PROT_PIO;
 604                /* fall through */
 605        case TASKFILE_IN_DMAQ:
 606        case TASKFILE_IN_DMA:
 607                nsect = taskin / SECTOR_SIZE;
 608                data_buf = inbuf;
 609                break;
 610        case TASKFILE_NO_DATA:
 611                cmd.protocol = ATA_PROT_NODATA;
 612                break;
 613        default:
 614                err = -EFAULT;
 615                goto abort;
 616        }
 617
 618        if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA)
 619                nsect = 0;
 620        else if (!nsect) {
 621                nsect = (cmd.hob.nsect << 8) | cmd.tf.nsect;
 622
 623                if (!nsect) {
 624                        pr_err("%s: in/out command without data\n",
 625                                        drive->name);
 626                        err = -EFAULT;
 627                        goto abort;
 628                }
 629        }
 630
 631        err = ide_raw_taskfile(drive, &cmd, data_buf, nsect);
 632
 633        memcpy(req_task->hob_ports, &cmd.hob, HDIO_DRIVE_HOB_HDR_SIZE - 2);
 634        memcpy(req_task->io_ports,  &cmd.tf,  HDIO_DRIVE_TASK_HDR_SIZE);
 635
 636        if ((cmd.ftf_flags & IDE_FTFLAG_SET_IN_FLAGS) &&
 637            req_task->in_flags.all == 0) {
 638                req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
 639                if (drive->dev_flags & IDE_DFLAG_LBA48)
 640                        req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
 641        }
 642
 643        if (copy_to_user(buf, req_task, tasksize)) {
 644                err = -EFAULT;
 645                goto abort;
 646        }
 647        if (taskout) {
 648                int outtotal = tasksize;
 649                if (copy_to_user(buf + outtotal, outbuf, taskout)) {
 650                        err = -EFAULT;
 651                        goto abort;
 652                }
 653        }
 654        if (taskin) {
 655                int intotal = tasksize + taskout;
 656                if (copy_to_user(buf + intotal, inbuf, taskin)) {
 657                        err = -EFAULT;
 658                        goto abort;
 659                }
 660        }
 661abort:
 662        kfree(req_task);
 663        kfree(outbuf);
 664        kfree(inbuf);
 665
 666        return err;
 667}
 668#endif
 669