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.c97
1 files changed, 62 insertions, 35 deletions
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 243421ce40d0..4aa6223c11be 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -23,17 +23,33 @@
23#include <asm/uaccess.h> 23#include <asm/uaccess.h>
24#include <asm/io.h> 24#include <asm/io.h>
25 25
26void ide_tf_dump(const char *s, struct ide_taskfile *tf) 26void ide_tf_readback(ide_drive_t *drive, struct ide_cmd *cmd)
27{
28 ide_hwif_t *hwif = drive->hwif;
29 const struct ide_tp_ops *tp_ops = hwif->tp_ops;
30
31 /* Be sure we're looking at the low order bytes */
32 tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
33
34 tp_ops->tf_read(drive, &cmd->tf, cmd->valid.in.tf);
35
36 if (cmd->tf_flags & IDE_TFLAG_LBA48) {
37 tp_ops->write_devctl(hwif, ATA_HOB | ATA_DEVCTL_OBS);
38
39 tp_ops->tf_read(drive, &cmd->hob, cmd->valid.in.hob);
40 }
41}
42
43void ide_tf_dump(const char *s, struct ide_cmd *cmd)
27{ 44{
28#ifdef DEBUG 45#ifdef DEBUG
29 printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x " 46 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", 47 "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n",
31 s, tf->feature, tf->nsect, tf->lbal, 48 s, cmd->tf.feature, cmd->tf.nsect,
32 tf->lbam, tf->lbah, tf->device, tf->command); 49 cmd->tf.lbal, cmd->tf.lbam, cmd->tf.lbah,
33 printk("%s: hob: nsect 0x%02x lbal 0x%02x " 50 cmd->tf.device, cmd->tf.command);
34 "lbam 0x%02x lbah 0x%02x\n", 51 printk("%s: hob: nsect 0x%02x lbal 0x%02x lbam 0x%02x lbah 0x%02x\n",
35 s, tf->hob_nsect, tf->hob_lbal, 52 s, cmd->hob.nsect, cmd->hob.lbal, cmd->hob.lbam, cmd->hob.lbah);
36 tf->hob_lbam, tf->hob_lbah);
37#endif 53#endif
38} 54}
39 55
@@ -47,7 +63,8 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
47 cmd.tf.command = ATA_CMD_ID_ATA; 63 cmd.tf.command = ATA_CMD_ID_ATA;
48 else 64 else
49 cmd.tf.command = ATA_CMD_ID_ATAPI; 65 cmd.tf.command = ATA_CMD_ID_ATAPI;
50 cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; 66 cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
67 cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
51 cmd.protocol = ATA_PROT_PIO; 68 cmd.protocol = ATA_PROT_PIO;
52 69
53 return ide_raw_taskfile(drive, &cmd, buf, 1); 70 return ide_raw_taskfile(drive, &cmd, buf, 1);
@@ -79,16 +96,27 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd)
79 memcpy(cmd, orig_cmd, sizeof(*cmd)); 96 memcpy(cmd, orig_cmd, sizeof(*cmd));
80 97
81 if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { 98 if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
82 ide_tf_dump(drive->name, tf); 99 ide_tf_dump(drive->name, cmd);
83 tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); 100 tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
84 SELECT_MASK(drive, 0); 101 SELECT_MASK(drive, 0);
85 102
86 if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) { 103 if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) {
87 u8 data[2] = { tf->data, tf->hob_data }; 104 u8 data[2] = { cmd->tf.data, cmd->hob.data };
88 105
89 tp_ops->output_data(drive, cmd, data, 2); 106 tp_ops->output_data(drive, cmd, data, 2);
90 } 107 }
91 tp_ops->tf_load(drive, cmd); 108
109 if (cmd->valid.out.tf & IDE_VALID_DEVICE) {
110 u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ?
111 0xE0 : 0xEF;
112
113 if (!(cmd->ftf_flags & IDE_FTFLAG_FLAGGED))
114 cmd->tf.device &= HIHI;
115 cmd->tf.device |= drive->select;
116 }
117
118 tp_ops->tf_load(drive, &cmd->hob, cmd->valid.out.hob);
119 tp_ops->tf_load(drive, &cmd->tf, cmd->valid.out.tf);
92 } 120 }
93 121
94 switch (cmd->protocol) { 122 switch (cmd->protocol) {
@@ -489,16 +517,17 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg)
489 517
490 memset(&cmd, 0, sizeof(cmd)); 518 memset(&cmd, 0, sizeof(cmd));
491 519
492 memcpy(&cmd.tf_array[0], req_task->hob_ports, 520 memcpy(&cmd.hob, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2);
493 HDIO_DRIVE_HOB_HDR_SIZE - 2); 521 memcpy(&cmd.tf, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
494 memcpy(&cmd.tf_array[6], req_task->io_ports,
495 HDIO_DRIVE_TASK_HDR_SIZE);
496 522
497 cmd.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE | 523 cmd.valid.out.tf = IDE_VALID_DEVICE;
498 IDE_TFLAG_IN_TF; 524 cmd.valid.in.tf = IDE_VALID_DEVICE | IDE_VALID_IN_TF;
525 cmd.tf_flags = IDE_TFLAG_IO_16BIT;
499 526
500 if (drive->dev_flags & IDE_DFLAG_LBA48) 527 if (drive->dev_flags & IDE_DFLAG_LBA48) {
501 cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB); 528 cmd.tf_flags |= IDE_TFLAG_LBA48;
529 cmd.valid.in.hob = IDE_VALID_IN_HOB;
530 }
502 531
503 if (req_task->out_flags.all) { 532 if (req_task->out_flags.all) {
504 cmd.ftf_flags |= IDE_FTFLAG_FLAGGED; 533 cmd.ftf_flags |= IDE_FTFLAG_FLAGGED;
@@ -507,28 +536,28 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg)
507 cmd.ftf_flags |= IDE_FTFLAG_OUT_DATA; 536 cmd.ftf_flags |= IDE_FTFLAG_OUT_DATA;
508 537
509 if (req_task->out_flags.b.nsector_hob) 538 if (req_task->out_flags.b.nsector_hob)
510 cmd.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT; 539 cmd.valid.out.hob |= IDE_VALID_NSECT;
511 if (req_task->out_flags.b.sector_hob) 540 if (req_task->out_flags.b.sector_hob)
512 cmd.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL; 541 cmd.valid.out.hob |= IDE_VALID_LBAL;
513 if (req_task->out_flags.b.lcyl_hob) 542 if (req_task->out_flags.b.lcyl_hob)
514 cmd.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM; 543 cmd.valid.out.hob |= IDE_VALID_LBAM;
515 if (req_task->out_flags.b.hcyl_hob) 544 if (req_task->out_flags.b.hcyl_hob)
516 cmd.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH; 545 cmd.valid.out.hob |= IDE_VALID_LBAH;
517 546
518 if (req_task->out_flags.b.error_feature) 547 if (req_task->out_flags.b.error_feature)
519 cmd.tf_flags |= IDE_TFLAG_OUT_FEATURE; 548 cmd.valid.out.tf |= IDE_VALID_FEATURE;
520 if (req_task->out_flags.b.nsector) 549 if (req_task->out_flags.b.nsector)
521 cmd.tf_flags |= IDE_TFLAG_OUT_NSECT; 550 cmd.valid.out.tf |= IDE_VALID_NSECT;
522 if (req_task->out_flags.b.sector) 551 if (req_task->out_flags.b.sector)
523 cmd.tf_flags |= IDE_TFLAG_OUT_LBAL; 552 cmd.valid.out.tf |= IDE_VALID_LBAL;
524 if (req_task->out_flags.b.lcyl) 553 if (req_task->out_flags.b.lcyl)
525 cmd.tf_flags |= IDE_TFLAG_OUT_LBAM; 554 cmd.valid.out.tf |= IDE_VALID_LBAM;
526 if (req_task->out_flags.b.hcyl) 555 if (req_task->out_flags.b.hcyl)
527 cmd.tf_flags |= IDE_TFLAG_OUT_LBAH; 556 cmd.valid.out.tf |= IDE_VALID_LBAH;
528 } else { 557 } else {
529 cmd.tf_flags |= IDE_TFLAG_OUT_TF; 558 cmd.valid.out.tf |= IDE_VALID_OUT_TF;
530 if (cmd.tf_flags & IDE_TFLAG_LBA48) 559 if (cmd.tf_flags & IDE_TFLAG_LBA48)
531 cmd.tf_flags |= IDE_TFLAG_OUT_HOB; 560 cmd.valid.out.hob |= IDE_VALID_OUT_HOB;
532 } 561 }
533 562
534 if (req_task->in_flags.b.data) 563 if (req_task->in_flags.b.data)
@@ -594,7 +623,7 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg)
594 if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA) 623 if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA)
595 nsect = 0; 624 nsect = 0;
596 else if (!nsect) { 625 else if (!nsect) {
597 nsect = (cmd.tf.hob_nsect << 8) | cmd.tf.nsect; 626 nsect = (cmd.hob.nsect << 8) | cmd.tf.nsect;
598 627
599 if (!nsect) { 628 if (!nsect) {
600 printk(KERN_ERR "%s: in/out command without data\n", 629 printk(KERN_ERR "%s: in/out command without data\n",
@@ -606,10 +635,8 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg)
606 635
607 err = ide_raw_taskfile(drive, &cmd, data_buf, nsect); 636 err = ide_raw_taskfile(drive, &cmd, data_buf, nsect);
608 637
609 memcpy(req_task->hob_ports, &cmd.tf_array[0], 638 memcpy(req_task->hob_ports, &cmd.hob, HDIO_DRIVE_HOB_HDR_SIZE - 2);
610 HDIO_DRIVE_HOB_HDR_SIZE - 2); 639 memcpy(req_task->io_ports, &cmd.tf, HDIO_DRIVE_TASK_HDR_SIZE);
611 memcpy(req_task->io_ports, &cmd.tf_array[6],
612 HDIO_DRIVE_TASK_HDR_SIZE);
613 640
614 if ((cmd.ftf_flags & IDE_FTFLAG_SET_IN_FLAGS) && 641 if ((cmd.ftf_flags & IDE_FTFLAG_SET_IN_FLAGS) &&
615 req_task->in_flags.all == 0) { 642 req_task->in_flags.all == 0) {