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