diff options
Diffstat (limited to 'drivers/ide/ide-taskfile.c')
-rw-r--r-- | drivers/ide/ide-taskfile.c | 126 |
1 files changed, 64 insertions, 62 deletions
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 75b85a8cd2d4..cc8633cbe133 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
@@ -19,8 +19,8 @@ | |||
19 | #include <linux/hdreg.h> | 19 | #include <linux/hdreg.h> |
20 | #include <linux/ide.h> | 20 | #include <linux/ide.h> |
21 | #include <linux/scatterlist.h> | 21 | #include <linux/scatterlist.h> |
22 | #include <linux/uaccess.h> | ||
22 | 23 | ||
23 | #include <asm/uaccess.h> | ||
24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
25 | 25 | ||
26 | void ide_tf_readback(ide_drive_t *drive, struct ide_cmd *cmd) | 26 | void ide_tf_readback(ide_drive_t *drive, struct ide_cmd *cmd) |
@@ -53,7 +53,7 @@ void ide_tf_dump(const char *s, struct ide_cmd *cmd) | |||
53 | #endif | 53 | #endif |
54 | } | 54 | } |
55 | 55 | ||
56 | int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) | 56 | int taskfile_lib_get_identify(ide_drive_t *drive, u8 *buf) |
57 | { | 57 | { |
58 | struct ide_cmd cmd; | 58 | struct ide_cmd cmd; |
59 | 59 | ||
@@ -86,7 +86,7 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd) | |||
86 | if (orig_cmd->protocol == ATA_PROT_PIO && | 86 | if (orig_cmd->protocol == ATA_PROT_PIO && |
87 | (orig_cmd->tf_flags & IDE_TFLAG_MULTI_PIO) && | 87 | (orig_cmd->tf_flags & IDE_TFLAG_MULTI_PIO) && |
88 | drive->mult_count == 0) { | 88 | drive->mult_count == 0) { |
89 | printk(KERN_ERR "%s: multimode not set!\n", drive->name); | 89 | pr_err("%s: multimode not set!\n", drive->name); |
90 | return ide_stopped; | 90 | return ide_stopped; |
91 | } | 91 | } |
92 | 92 | ||
@@ -214,7 +214,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) | |||
214 | } | 214 | } |
215 | 215 | ||
216 | if (stat & ATA_BUSY) | 216 | if (stat & ATA_BUSY) |
217 | printk(KERN_ERR "%s: drive still BUSY!\n", drive->name); | 217 | pr_err("%s: drive still BUSY!\n", drive->name); |
218 | 218 | ||
219 | return stat; | 219 | return stat; |
220 | } | 220 | } |
@@ -225,8 +225,8 @@ void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, | |||
225 | ide_hwif_t *hwif = drive->hwif; | 225 | ide_hwif_t *hwif = drive->hwif; |
226 | struct scatterlist *sg = hwif->sg_table; | 226 | struct scatterlist *sg = hwif->sg_table; |
227 | struct scatterlist *cursg = cmd->cursg; | 227 | struct scatterlist *cursg = cmd->cursg; |
228 | unsigned long uninitialized_var(flags); | ||
228 | struct page *page; | 229 | struct page *page; |
229 | unsigned long flags; | ||
230 | unsigned int offset; | 230 | unsigned int offset; |
231 | u8 *buf; | 231 | u8 *buf; |
232 | 232 | ||
@@ -236,6 +236,7 @@ void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, | |||
236 | 236 | ||
237 | while (len) { | 237 | while (len) { |
238 | unsigned nr_bytes = min(len, cursg->length - cmd->cursg_ofs); | 238 | unsigned nr_bytes = min(len, cursg->length - cmd->cursg_ofs); |
239 | int page_is_high; | ||
239 | 240 | ||
240 | if (nr_bytes > PAGE_SIZE) | 241 | if (nr_bytes > PAGE_SIZE) |
241 | nr_bytes = PAGE_SIZE; | 242 | nr_bytes = PAGE_SIZE; |
@@ -247,7 +248,8 @@ void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, | |||
247 | page = nth_page(page, (offset >> PAGE_SHIFT)); | 248 | page = nth_page(page, (offset >> PAGE_SHIFT)); |
248 | offset %= PAGE_SIZE; | 249 | offset %= PAGE_SIZE; |
249 | 250 | ||
250 | if (PageHighMem(page)) | 251 | page_is_high = PageHighMem(page); |
252 | if (page_is_high) | ||
251 | local_irq_save(flags); | 253 | local_irq_save(flags); |
252 | 254 | ||
253 | buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset; | 255 | buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset; |
@@ -268,7 +270,7 @@ void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, | |||
268 | 270 | ||
269 | kunmap_atomic(buf, KM_BIO_SRC_IRQ); | 271 | kunmap_atomic(buf, KM_BIO_SRC_IRQ); |
270 | 272 | ||
271 | if (PageHighMem(page)) | 273 | if (page_is_high) |
272 | local_irq_restore(flags); | 274 | local_irq_restore(flags); |
273 | 275 | ||
274 | len -= nr_bytes; | 276 | len -= nr_bytes; |
@@ -322,10 +324,17 @@ static void ide_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd) | |||
322 | void ide_finish_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat) | 324 | void ide_finish_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat) |
323 | { | 325 | { |
324 | struct request *rq = drive->hwif->rq; | 326 | struct request *rq = drive->hwif->rq; |
325 | u8 err = ide_read_error(drive); | 327 | u8 err = ide_read_error(drive), nsect = cmd->tf.nsect; |
328 | u8 set_xfer = !!(cmd->tf_flags & IDE_TFLAG_SET_XFER); | ||
326 | 329 | ||
327 | ide_complete_cmd(drive, cmd, stat, err); | 330 | ide_complete_cmd(drive, cmd, stat, err); |
328 | rq->errors = err; | 331 | rq->errors = err; |
332 | |||
333 | if (err == 0 && set_xfer) { | ||
334 | ide_set_xfer_rate(drive, nsect); | ||
335 | ide_driveid_update(drive); | ||
336 | } | ||
337 | |||
329 | ide_complete_rq(drive, err ? -EIO : 0, blk_rq_bytes(rq)); | 338 | ide_complete_rq(drive, err ? -EIO : 0, blk_rq_bytes(rq)); |
330 | } | 339 | } |
331 | 340 | ||
@@ -398,8 +407,7 @@ static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, | |||
398 | 407 | ||
399 | if (ide_wait_stat(&startstop, drive, ATA_DRQ, | 408 | if (ide_wait_stat(&startstop, drive, ATA_DRQ, |
400 | drive->bad_wstat, WAIT_DRQ)) { | 409 | drive->bad_wstat, WAIT_DRQ)) { |
401 | printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n", | 410 | pr_err("%s: no DRQ after issuing %sWRITE%s\n", drive->name, |
402 | drive->name, | ||
403 | (cmd->tf_flags & IDE_TFLAG_MULTI_PIO) ? "MULT" : "", | 411 | (cmd->tf_flags & IDE_TFLAG_MULTI_PIO) ? "MULT" : "", |
404 | (drive->dev_flags & IDE_DFLAG_LBA48) ? "_EXT" : ""); | 412 | (drive->dev_flags & IDE_DFLAG_LBA48) ? "_EXT" : ""); |
405 | return startstop; | 413 | return startstop; |
@@ -449,7 +457,6 @@ put_req: | |||
449 | blk_put_request(rq); | 457 | blk_put_request(rq); |
450 | return error; | 458 | return error; |
451 | } | 459 | } |
452 | |||
453 | EXPORT_SYMBOL(ide_raw_taskfile); | 460 | EXPORT_SYMBOL(ide_raw_taskfile); |
454 | 461 | ||
455 | int ide_no_data_taskfile(ide_drive_t *drive, struct ide_cmd *cmd) | 462 | int ide_no_data_taskfile(ide_drive_t *drive, struct ide_cmd *cmd) |
@@ -475,10 +482,9 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg) | |||
475 | u16 nsect = 0; | 482 | u16 nsect = 0; |
476 | char __user *buf = (char __user *)arg; | 483 | char __user *buf = (char __user *)arg; |
477 | 484 | ||
478 | // printk("IDE Taskfile ...\n"); | ||
479 | |||
480 | req_task = kzalloc(tasksize, GFP_KERNEL); | 485 | req_task = kzalloc(tasksize, GFP_KERNEL); |
481 | if (req_task == NULL) return -ENOMEM; | 486 | if (req_task == NULL) |
487 | return -ENOMEM; | ||
482 | if (copy_from_user(req_task, buf, tasksize)) { | 488 | if (copy_from_user(req_task, buf, tasksize)) { |
483 | kfree(req_task); | 489 | kfree(req_task); |
484 | return -EFAULT; | 490 | return -EFAULT; |
@@ -486,7 +492,7 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg) | |||
486 | 492 | ||
487 | taskout = req_task->out_size; | 493 | taskout = req_task->out_size; |
488 | taskin = req_task->in_size; | 494 | taskin = req_task->in_size; |
489 | 495 | ||
490 | if (taskin > 65536 || taskout > 65536) { | 496 | if (taskin > 65536 || taskout > 65536) { |
491 | err = -EINVAL; | 497 | err = -EINVAL; |
492 | goto abort; | 498 | goto abort; |
@@ -576,51 +582,49 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg) | |||
576 | cmd.protocol = ATA_PROT_DMA; | 582 | cmd.protocol = ATA_PROT_DMA; |
577 | 583 | ||
578 | switch (req_task->data_phase) { | 584 | switch (req_task->data_phase) { |
579 | case TASKFILE_MULTI_OUT: | 585 | case TASKFILE_MULTI_OUT: |
580 | if (!drive->mult_count) { | 586 | if (!drive->mult_count) { |
581 | /* (hs): give up if multcount is not set */ | 587 | /* (hs): give up if multcount is not set */ |
582 | printk(KERN_ERR "%s: %s Multimode Write " \ | 588 | pr_err("%s: %s Multimode Write multcount is not set\n", |
583 | "multcount is not set\n", | 589 | drive->name, __func__); |
584 | drive->name, __func__); | 590 | err = -EPERM; |
585 | err = -EPERM; | 591 | goto abort; |
586 | goto abort; | 592 | } |
587 | } | 593 | cmd.tf_flags |= IDE_TFLAG_MULTI_PIO; |
588 | cmd.tf_flags |= IDE_TFLAG_MULTI_PIO; | 594 | /* fall through */ |
589 | /* fall through */ | 595 | case TASKFILE_OUT: |
590 | case TASKFILE_OUT: | 596 | cmd.protocol = ATA_PROT_PIO; |
591 | cmd.protocol = ATA_PROT_PIO; | 597 | /* fall through */ |
592 | /* fall through */ | 598 | case TASKFILE_OUT_DMAQ: |
593 | case TASKFILE_OUT_DMAQ: | 599 | case TASKFILE_OUT_DMA: |
594 | case TASKFILE_OUT_DMA: | 600 | cmd.tf_flags |= IDE_TFLAG_WRITE; |
595 | cmd.tf_flags |= IDE_TFLAG_WRITE; | 601 | nsect = taskout / SECTOR_SIZE; |
596 | nsect = taskout / SECTOR_SIZE; | 602 | data_buf = outbuf; |
597 | data_buf = outbuf; | 603 | break; |
598 | break; | 604 | case TASKFILE_MULTI_IN: |
599 | case TASKFILE_MULTI_IN: | 605 | if (!drive->mult_count) { |
600 | if (!drive->mult_count) { | 606 | /* (hs): give up if multcount is not set */ |
601 | /* (hs): give up if multcount is not set */ | 607 | pr_err("%s: %s Multimode Read multcount is not set\n", |
602 | printk(KERN_ERR "%s: %s Multimode Read failure " \ | 608 | drive->name, __func__); |
603 | "multcount is not set\n", | 609 | err = -EPERM; |
604 | drive->name, __func__); | ||
605 | err = -EPERM; | ||
606 | goto abort; | ||
607 | } | ||
608 | cmd.tf_flags |= IDE_TFLAG_MULTI_PIO; | ||
609 | /* fall through */ | ||
610 | case TASKFILE_IN: | ||
611 | cmd.protocol = ATA_PROT_PIO; | ||
612 | /* fall through */ | ||
613 | case TASKFILE_IN_DMAQ: | ||
614 | case TASKFILE_IN_DMA: | ||
615 | nsect = taskin / SECTOR_SIZE; | ||
616 | data_buf = inbuf; | ||
617 | break; | ||
618 | case TASKFILE_NO_DATA: | ||
619 | cmd.protocol = ATA_PROT_NODATA; | ||
620 | break; | ||
621 | default: | ||
622 | err = -EFAULT; | ||
623 | goto abort; | 610 | goto abort; |
611 | } | ||
612 | cmd.tf_flags |= IDE_TFLAG_MULTI_PIO; | ||
613 | /* fall through */ | ||
614 | case TASKFILE_IN: | ||
615 | cmd.protocol = ATA_PROT_PIO; | ||
616 | /* fall through */ | ||
617 | case TASKFILE_IN_DMAQ: | ||
618 | case TASKFILE_IN_DMA: | ||
619 | nsect = taskin / SECTOR_SIZE; | ||
620 | data_buf = inbuf; | ||
621 | break; | ||
622 | case TASKFILE_NO_DATA: | ||
623 | cmd.protocol = ATA_PROT_NODATA; | ||
624 | break; | ||
625 | default: | ||
626 | err = -EFAULT; | ||
627 | goto abort; | ||
624 | } | 628 | } |
625 | 629 | ||
626 | if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA) | 630 | if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA) |
@@ -629,7 +633,7 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg) | |||
629 | nsect = (cmd.hob.nsect << 8) | cmd.tf.nsect; | 633 | nsect = (cmd.hob.nsect << 8) | cmd.tf.nsect; |
630 | 634 | ||
631 | if (!nsect) { | 635 | if (!nsect) { |
632 | printk(KERN_ERR "%s: in/out command without data\n", | 636 | pr_err("%s: in/out command without data\n", |
633 | drive->name); | 637 | drive->name); |
634 | err = -EFAULT; | 638 | err = -EFAULT; |
635 | goto abort; | 639 | goto abort; |
@@ -671,8 +675,6 @@ abort: | |||
671 | kfree(outbuf); | 675 | kfree(outbuf); |
672 | kfree(inbuf); | 676 | kfree(inbuf); |
673 | 677 | ||
674 | // printk("IDE Taskfile ioctl ended. rc = %i\n", err); | ||
675 | |||
676 | return err; | 678 | return err; |
677 | } | 679 | } |
678 | #endif | 680 | #endif |