diff options
Diffstat (limited to 'drivers/ide/ide-taskfile.c')
-rw-r--r-- | drivers/ide/ide-taskfile.c | 97 |
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 | ||
26 | void ide_tf_dump(const char *s, struct ide_taskfile *tf) | 26 | void 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 | |||
43 | void 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) { |