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