aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-taskfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-taskfile.c')
-rw-r--r--drivers/ide/ide-taskfile.c155
1 files changed, 68 insertions, 87 deletions
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 2d63ea9ee61b..5eb6fa15dc4d 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -35,34 +35,6 @@
35#include <asm/uaccess.h> 35#include <asm/uaccess.h>
36#include <asm/io.h> 36#include <asm/io.h>
37 37
38static void ata_bswap_data (void *buffer, int wcount)
39{
40 u16 *p = buffer;
41
42 while (wcount--) {
43 *p = *p << 8 | *p >> 8; p++;
44 *p = *p << 8 | *p >> 8; p++;
45 }
46}
47
48static void taskfile_input_data(ide_drive_t *drive, void *buffer, u32 wcount)
49{
50 HWIF(drive)->ata_input_data(drive, buffer, wcount);
51 if (drive->bswap)
52 ata_bswap_data(buffer, wcount);
53}
54
55static void taskfile_output_data(ide_drive_t *drive, void *buffer, u32 wcount)
56{
57 if (drive->bswap) {
58 ata_bswap_data(buffer, wcount);
59 HWIF(drive)->ata_output_data(drive, buffer, wcount);
60 ata_bswap_data(buffer, wcount);
61 } else {
62 HWIF(drive)->ata_output_data(drive, buffer, wcount);
63 }
64}
65
66void ide_tf_load(ide_drive_t *drive, ide_task_t *task) 38void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
67{ 39{
68 ide_hwif_t *hwif = drive->hwif; 40 ide_hwif_t *hwif = drive->hwif;
@@ -77,10 +49,13 @@ void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
77 "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n", 49 "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n",
78 drive->name, tf->feature, tf->nsect, tf->lbal, 50 drive->name, tf->feature, tf->nsect, tf->lbal,
79 tf->lbam, tf->lbah, tf->device, tf->command); 51 tf->lbam, tf->lbah, tf->device, tf->command);
52 printk("%s: hob: nsect 0x%02x lbal 0x%02x "
53 "lbam 0x%02x lbah 0x%02x\n",
54 drive->name, tf->hob_nsect, tf->hob_lbal,
55 tf->hob_lbam, tf->hob_lbah);
80#endif 56#endif
81 57
82 if (IDE_CONTROL_REG) 58 ide_set_irq(drive, 1);
83 hwif->OUTB(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
84 59
85 if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0) 60 if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
86 SELECT_MASK(drive, 0); 61 SELECT_MASK(drive, 0);
@@ -124,7 +99,7 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
124 args.tf.command = WIN_IDENTIFY; 99 args.tf.command = WIN_IDENTIFY;
125 else 100 else
126 args.tf.command = WIN_PIDENTIFY; 101 args.tf.command = WIN_PIDENTIFY;
127 args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; 102 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
128 args.data_phase = TASKFILE_IN; 103 args.data_phase = TASKFILE_IN;
129 return ide_raw_taskfile(drive, &args, buf, 1); 104 return ide_raw_taskfile(drive, &args, buf, 1);
130} 105}
@@ -285,7 +260,7 @@ static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
285 return ide_stopped; 260 return ide_stopped;
286} 261}
287 262
288static u8 wait_drive_not_busy(ide_drive_t *drive) 263u8 wait_drive_not_busy(ide_drive_t *drive)
289{ 264{
290 ide_hwif_t *hwif = HWIF(drive); 265 ide_hwif_t *hwif = HWIF(drive);
291 int retries; 266 int retries;
@@ -293,8 +268,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
293 268
294 /* 269 /*
295 * Last sector was transfered, wait until drive is ready. 270 * Last sector was transfered, wait until drive is ready.
296 * This can take up to 10 usec, but we will wait max 1 ms 271 * This can take up to 10 usec, but we will wait max 1 ms.
297 * (drive_cmd_intr() waits that long).
298 */ 272 */
299 for (retries = 0; retries < 100; retries++) { 273 for (retries = 0; retries < 100; retries++) {
300 if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) 274 if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT)
@@ -349,9 +323,9 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
349 323
350 /* do the actual data transfer */ 324 /* do the actual data transfer */
351 if (write) 325 if (write)
352 taskfile_output_data(drive, buf, SECTOR_WORDS); 326 hwif->ata_output_data(drive, buf, SECTOR_WORDS);
353 else 327 else
354 taskfile_input_data(drive, buf, SECTOR_WORDS); 328 hwif->ata_input_data(drive, buf, SECTOR_WORDS);
355 329
356 kunmap_atomic(buf, KM_BIO_SRC_IRQ); 330 kunmap_atomic(buf, KM_BIO_SRC_IRQ);
357#ifdef CONFIG_HIGHMEM 331#ifdef CONFIG_HIGHMEM
@@ -371,9 +345,18 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write)
371static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, 345static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
372 unsigned int write) 346 unsigned int write)
373{ 347{
348 u8 saved_io_32bit = drive->io_32bit;
349
374 if (rq->bio) /* fs request */ 350 if (rq->bio) /* fs request */
375 rq->errors = 0; 351 rq->errors = 0;
376 352
353 if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
354 ide_task_t *task = rq->special;
355
356 if (task->tf_flags & IDE_TFLAG_IO_16BIT)
357 drive->io_32bit = 0;
358 }
359
377 touch_softlockup_watchdog(); 360 touch_softlockup_watchdog();
378 361
379 switch (drive->hwif->data_phase) { 362 switch (drive->hwif->data_phase) {
@@ -385,6 +368,8 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
385 ide_pio_sector(drive, write); 368 ide_pio_sector(drive, write);
386 break; 369 break;
387 } 370 }
371
372 drive->io_32bit = saved_io_32bit;
388} 373}
389 374
390static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, 375static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
@@ -422,27 +407,22 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
422 return ide_error(drive, s, stat); 407 return ide_error(drive, s, stat);
423} 408}
424 409
425static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) 410void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
426{ 411{
427 HWIF(drive)->cursg = NULL;
428
429 if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { 412 if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
430 ide_task_t *task = rq->special; 413 u8 err = drive->hwif->INB(IDE_ERROR_REG);
431 414
432 if (task->tf_flags & IDE_TFLAG_FLAGGED) { 415 ide_end_drive_cmd(drive, stat, err);
433 u8 err = drive->hwif->INB(IDE_ERROR_REG); 416 return;
434 ide_end_drive_cmd(drive, stat, err);
435 return;
436 }
437 } 417 }
438 418
439 if (rq->rq_disk) { 419 if (rq->rq_disk) {
440 ide_driver_t *drv; 420 ide_driver_t *drv;
441 421
442 drv = *(ide_driver_t **)rq->rq_disk->private_data;; 422 drv = *(ide_driver_t **)rq->rq_disk->private_data;;
443 drv->end_request(drive, 1, rq->hard_nr_sectors); 423 drv->end_request(drive, 1, rq->nr_sectors);
444 } else 424 } else
445 ide_end_request(drive, 1, rq->hard_nr_sectors); 425 ide_end_request(drive, 1, rq->nr_sectors);
446} 426}
447 427
448/* 428/*
@@ -455,7 +435,7 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive)
455 u8 stat = hwif->INB(IDE_STATUS_REG); 435 u8 stat = hwif->INB(IDE_STATUS_REG);
456 436
457 /* new way for dealing with premature shared PCI interrupts */ 437 /* new way for dealing with premature shared PCI interrupts */
458 if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { 438 if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
459 if (stat & (ERR_STAT | DRQ_STAT)) 439 if (stat & (ERR_STAT | DRQ_STAT))
460 return task_error(drive, rq, __FUNCTION__, stat); 440 return task_error(drive, rq, __FUNCTION__, stat);
461 /* No data yet, so wait for another IRQ. */ 441 /* No data yet, so wait for another IRQ. */
@@ -468,7 +448,7 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive)
468 /* If it was the last datablock check status and finish transfer. */ 448 /* If it was the last datablock check status and finish transfer. */
469 if (!hwif->nleft) { 449 if (!hwif->nleft) {
470 stat = wait_drive_not_busy(drive); 450 stat = wait_drive_not_busy(drive);
471 if (!OK_STAT(stat, 0, BAD_R_STAT)) 451 if (!OK_STAT(stat, 0, BAD_STAT))
472 return task_error(drive, rq, __FUNCTION__, stat); 452 return task_error(drive, rq, __FUNCTION__, stat);
473 task_end_request(drive, rq, stat); 453 task_end_request(drive, rq, stat);
474 return ide_stopped; 454 return ide_stopped;
@@ -512,7 +492,7 @@ static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
512{ 492{
513 ide_startstop_t startstop; 493 ide_startstop_t startstop;
514 494
515 if (ide_wait_stat(&startstop, drive, DATA_READY, 495 if (ide_wait_stat(&startstop, drive, DRQ_STAT,
516 drive->bad_wstat, WAIT_DRQ)) { 496 drive->bad_wstat, WAIT_DRQ)) {
517 printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n", 497 printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
518 drive->name, 498 drive->name,
@@ -580,7 +560,6 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
580 unsigned int taskin = 0; 560 unsigned int taskin = 0;
581 unsigned int taskout = 0; 561 unsigned int taskout = 0;
582 u16 nsect = 0; 562 u16 nsect = 0;
583 u8 io_32bit = drive->io_32bit;
584 char __user *buf = (char __user *)arg; 563 char __user *buf = (char __user *)arg;
585 564
586// printk("IDE Taskfile ...\n"); 565// printk("IDE Taskfile ...\n");
@@ -633,9 +612,10 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
633 612
634 args.data_phase = req_task->data_phase; 613 args.data_phase = req_task->data_phase;
635 614
636 args.tf_flags = IDE_TFLAG_OUT_DEVICE; 615 args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE |
616 IDE_TFLAG_IN_TF;
637 if (drive->addressing == 1) 617 if (drive->addressing == 1)
638 args.tf_flags |= IDE_TFLAG_LBA48; 618 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB);
639 619
640 if (req_task->out_flags.all) { 620 if (req_task->out_flags.all) {
641 args.tf_flags |= IDE_TFLAG_FLAGGED; 621 args.tf_flags |= IDE_TFLAG_FLAGGED;
@@ -671,7 +651,6 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
671 if (req_task->in_flags.b.data) 651 if (req_task->in_flags.b.data)
672 args.tf_flags |= IDE_TFLAG_IN_DATA; 652 args.tf_flags |= IDE_TFLAG_IN_DATA;
673 653
674 drive->io_32bit = 0;
675 switch(req_task->data_phase) { 654 switch(req_task->data_phase) {
676 case TASKFILE_MULTI_OUT: 655 case TASKFILE_MULTI_OUT:
677 if (!drive->mult_count) { 656 if (!drive->mult_count) {
@@ -767,41 +746,24 @@ abort:
767 746
768// printk("IDE Taskfile ioctl ended. rc = %i\n", err); 747// printk("IDE Taskfile ioctl ended. rc = %i\n", err);
769 748
770 drive->io_32bit = io_32bit;
771
772 return err; 749 return err;
773} 750}
774#endif 751#endif
775 752
776int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *buf)
777{
778 struct request rq;
779 u8 buffer[4];
780
781 if (!buf)
782 buf = buffer;
783 memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors);
784 ide_init_drive_cmd(&rq);
785 rq.buffer = buf;
786 *buf++ = cmd;
787 *buf++ = nsect;
788 *buf++ = feature;
789 *buf++ = sectors;
790 return ide_do_drive_cmd(drive, &rq, ide_wait);
791}
792
793int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) 753int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
794{ 754{
795 int err = 0; 755 u8 *buf = NULL;
796 u8 args[4], *argbuf = args; 756 int bufsize = 0, err = 0;
797 u8 xfer_rate = 0; 757 u8 args[4], xfer_rate = 0;
798 int argsize = 4;
799 ide_task_t tfargs; 758 ide_task_t tfargs;
800 struct ide_taskfile *tf = &tfargs.tf; 759 struct ide_taskfile *tf = &tfargs.tf;
801 760
802 if (NULL == (void *) arg) { 761 if (NULL == (void *) arg) {
803 struct request rq; 762 struct request rq;
763
804 ide_init_drive_cmd(&rq); 764 ide_init_drive_cmd(&rq);
765 rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
766
805 return ide_do_drive_cmd(drive, &rq, ide_wait); 767 return ide_do_drive_cmd(drive, &rq, ide_wait);
806 } 768 }
807 769
@@ -810,23 +772,39 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
810 772
811 memset(&tfargs, 0, sizeof(ide_task_t)); 773 memset(&tfargs, 0, sizeof(ide_task_t));
812 tf->feature = args[2]; 774 tf->feature = args[2];
813 tf->nsect = args[3]; 775 if (args[0] == WIN_SMART) {
814 tf->lbal = args[1]; 776 tf->nsect = args[3];
777 tf->lbal = args[1];
778 tf->lbam = 0x4f;
779 tf->lbah = 0xc2;
780 tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT;
781 } else {
782 tf->nsect = args[1];
783 tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
784 IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
785 }
815 tf->command = args[0]; 786 tf->command = args[0];
787 tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
816 788
817 if (args[3]) { 789 if (args[3]) {
818 argsize = 4 + (SECTOR_WORDS * 4 * args[3]); 790 tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
819 argbuf = kzalloc(argsize, GFP_KERNEL); 791 bufsize = SECTOR_WORDS * 4 * args[3];
820 if (argbuf == NULL) 792 buf = kzalloc(bufsize, GFP_KERNEL);
793 if (buf == NULL)
821 return -ENOMEM; 794 return -ENOMEM;
822 } 795 }
796
823 if (set_transfer(drive, &tfargs)) { 797 if (set_transfer(drive, &tfargs)) {
824 xfer_rate = args[1]; 798 xfer_rate = args[1];
825 if (ide_ata66_check(drive, &tfargs)) 799 if (ide_ata66_check(drive, &tfargs))
826 goto abort; 800 goto abort;
827 } 801 }
828 802
829 err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf); 803 err = ide_raw_taskfile(drive, &tfargs, buf, args[3]);
804
805 args[0] = tf->status;
806 args[1] = tf->error;
807 args[2] = tf->nsect;
830 808
831 if (!err && xfer_rate) { 809 if (!err && xfer_rate) {
832 /* active-retuning-calls future */ 810 /* active-retuning-calls future */
@@ -834,10 +812,13 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
834 ide_driveid_update(drive); 812 ide_driveid_update(drive);
835 } 813 }
836abort: 814abort:
837 if (copy_to_user((void __user *)arg, argbuf, argsize)) 815 if (copy_to_user((void __user *)arg, &args, 4))
838 err = -EFAULT; 816 err = -EFAULT;
839 if (argsize > 4) 817 if (buf) {
840 kfree(argbuf); 818 if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
819 err = -EFAULT;
820 kfree(buf);
821 }
841 return err; 822 return err;
842} 823}
843 824
@@ -854,7 +835,7 @@ int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
854 memset(&task, 0, sizeof(task)); 835 memset(&task, 0, sizeof(task));
855 memcpy(&task.tf_array[7], &args[1], 6); 836 memcpy(&task.tf_array[7], &args[1], 6);
856 task.tf.command = args[0]; 837 task.tf.command = args[0];
857 task.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; 838 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
858 839
859 err = ide_no_data_taskfile(drive, &task); 840 err = ide_no_data_taskfile(drive, &task);
860 841