diff options
author | Albert Lee <albertcc@tw.ibm.com> | 2005-10-12 03:06:27 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-18 17:16:13 -0400 |
commit | 8cbd6df1f0ce977ab7b61feffa59879bb5e0ed8f (patch) | |
tree | c460778581293ad479ec4983690ccc46bcb4df56 /drivers | |
parent | 07506697d1c615924298406f2357810709c09bcd (diff) |
[PATCH] libata CHS: calculate read/write commands and protocol on the fly (revise #6)
- merge ata_prot_to_cmd() and ata_dev_set_protocol() as
ata_rwcmd_protocol()
- pave road for read/write multiple support
- remove usage of pre-cached command and protocol values and call
ata_rwcmd_protocol() instead
Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
==============
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/libata-core.c | 105 | ||||
-rw-r--r-- | drivers/scsi/libata-scsi.c | 13 | ||||
-rw-r--r-- | drivers/scsi/libata.h | 1 |
3 files changed, 44 insertions, 75 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 55d4dee133af..19d3d717faf6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -616,79 +616,53 @@ void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf) | |||
616 | tf->hob_nsect = fis[13]; | 616 | tf->hob_nsect = fis[13]; |
617 | } | 617 | } |
618 | 618 | ||
619 | /** | 619 | static const u8 ata_rw_cmds[] = { |
620 | * ata_prot_to_cmd - determine which read/write opcodes to use | 620 | /* pio multi */ |
621 | * @protocol: ATA_PROT_xxx taskfile protocol | 621 | ATA_CMD_READ_MULTI, |
622 | * @lba48: true is lba48 is present | 622 | ATA_CMD_WRITE_MULTI, |
623 | * | 623 | ATA_CMD_READ_MULTI_EXT, |
624 | * Given necessary input, determine which read/write commands | 624 | ATA_CMD_WRITE_MULTI_EXT, |
625 | * to use to transfer data. | 625 | /* pio */ |
626 | * | 626 | ATA_CMD_PIO_READ, |
627 | * LOCKING: | 627 | ATA_CMD_PIO_WRITE, |
628 | * None. | 628 | ATA_CMD_PIO_READ_EXT, |
629 | */ | 629 | ATA_CMD_PIO_WRITE_EXT, |
630 | static int ata_prot_to_cmd(int protocol, int lba48) | 630 | /* dma */ |
631 | { | 631 | ATA_CMD_READ, |
632 | int rcmd = 0, wcmd = 0; | 632 | ATA_CMD_WRITE, |
633 | 633 | ATA_CMD_READ_EXT, | |
634 | switch (protocol) { | 634 | ATA_CMD_WRITE_EXT |
635 | case ATA_PROT_PIO: | 635 | }; |
636 | if (lba48) { | ||
637 | rcmd = ATA_CMD_PIO_READ_EXT; | ||
638 | wcmd = ATA_CMD_PIO_WRITE_EXT; | ||
639 | } else { | ||
640 | rcmd = ATA_CMD_PIO_READ; | ||
641 | wcmd = ATA_CMD_PIO_WRITE; | ||
642 | } | ||
643 | break; | ||
644 | |||
645 | case ATA_PROT_DMA: | ||
646 | if (lba48) { | ||
647 | rcmd = ATA_CMD_READ_EXT; | ||
648 | wcmd = ATA_CMD_WRITE_EXT; | ||
649 | } else { | ||
650 | rcmd = ATA_CMD_READ; | ||
651 | wcmd = ATA_CMD_WRITE; | ||
652 | } | ||
653 | break; | ||
654 | |||
655 | default: | ||
656 | return -1; | ||
657 | } | ||
658 | |||
659 | return rcmd | (wcmd << 8); | ||
660 | } | ||
661 | 636 | ||
662 | /** | 637 | /** |
663 | * ata_dev_set_protocol - set taskfile protocol and r/w commands | 638 | * ata_rwcmd_protocol - set taskfile r/w commands and protocol |
664 | * @dev: device to examine and configure | 639 | * @qc: command to examine and configure |
665 | * | 640 | * |
666 | * Examine the device configuration, after we have | 641 | * Examine the device configuration and tf->flags to calculate |
667 | * read the identify-device page and configured the | 642 | * the proper read/write commands and protocol to use. |
668 | * data transfer mode. Set internal state related to | ||
669 | * the ATA taskfile protocol (pio, pio mult, dma, etc.) | ||
670 | * and calculate the proper read/write commands to use. | ||
671 | * | 643 | * |
672 | * LOCKING: | 644 | * LOCKING: |
673 | * caller. | 645 | * caller. |
674 | */ | 646 | */ |
675 | static void ata_dev_set_protocol(struct ata_device *dev) | 647 | void ata_rwcmd_protocol(struct ata_queued_cmd *qc) |
676 | { | 648 | { |
677 | int pio = (dev->flags & ATA_DFLAG_PIO); | 649 | struct ata_taskfile *tf = &qc->tf; |
678 | int lba48 = (dev->flags & ATA_DFLAG_LBA48); | 650 | struct ata_device *dev = qc->dev; |
679 | int proto, cmd; | ||
680 | 651 | ||
681 | if (pio) | 652 | int index, lba48, write; |
682 | proto = dev->xfer_protocol = ATA_PROT_PIO; | 653 | |
683 | else | 654 | lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0; |
684 | proto = dev->xfer_protocol = ATA_PROT_DMA; | 655 | write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0; |
685 | 656 | ||
686 | cmd = ata_prot_to_cmd(proto, lba48); | 657 | if (dev->flags & ATA_DFLAG_PIO) { |
687 | if (cmd < 0) | 658 | tf->protocol = ATA_PROT_PIO; |
688 | BUG(); | 659 | index = dev->multi_count ? 0 : 4; |
660 | } else { | ||
661 | tf->protocol = ATA_PROT_DMA; | ||
662 | index = 8; | ||
663 | } | ||
689 | 664 | ||
690 | dev->read_cmd = cmd & 0xff; | 665 | tf->command = ata_rw_cmds[index + lba48 + write]; |
691 | dev->write_cmd = (cmd >> 8) & 0xff; | ||
692 | } | 666 | } |
693 | 667 | ||
694 | static const char * xfer_mode_str[] = { | 668 | static const char * xfer_mode_str[] = { |
@@ -1641,7 +1615,7 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode, | |||
1641 | */ | 1615 | */ |
1642 | static void ata_set_mode(struct ata_port *ap) | 1616 | static void ata_set_mode(struct ata_port *ap) |
1643 | { | 1617 | { |
1644 | unsigned int i, xfer_shift; | 1618 | unsigned int xfer_shift; |
1645 | u8 xfer_mode; | 1619 | u8 xfer_mode; |
1646 | int rc; | 1620 | int rc; |
1647 | 1621 | ||
@@ -1670,11 +1644,6 @@ static void ata_set_mode(struct ata_port *ap) | |||
1670 | if (ap->ops->post_set_mode) | 1644 | if (ap->ops->post_set_mode) |
1671 | ap->ops->post_set_mode(ap); | 1645 | ap->ops->post_set_mode(ap); |
1672 | 1646 | ||
1673 | for (i = 0; i < 2; i++) { | ||
1674 | struct ata_device *dev = &ap->device[i]; | ||
1675 | ata_dev_set_protocol(dev); | ||
1676 | } | ||
1677 | |||
1678 | return; | 1647 | return; |
1679 | 1648 | ||
1680 | err_out: | 1649 | err_out: |
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ea7a4d8a6fc9..90bf22204668 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -742,15 +742,10 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
742 | u32 n_block; | 742 | u32 n_block; |
743 | 743 | ||
744 | tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; | 744 | tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; |
745 | tf->protocol = qc->dev->xfer_protocol; | ||
746 | 745 | ||
747 | if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 || | 746 | if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 || |
748 | scsicmd[0] == READ_16) { | 747 | scsicmd[0] == WRITE_16) |
749 | tf->command = qc->dev->read_cmd; | ||
750 | } else { | ||
751 | tf->command = qc->dev->write_cmd; | ||
752 | tf->flags |= ATA_TFLAG_WRITE; | 748 | tf->flags |= ATA_TFLAG_WRITE; |
753 | } | ||
754 | 749 | ||
755 | /* Calculate the SCSI LBA and transfer length. */ | 750 | /* Calculate the SCSI LBA and transfer length. */ |
756 | switch (scsicmd[0]) { | 751 | switch (scsicmd[0]) { |
@@ -812,6 +807,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
812 | tf->device |= (block >> 24) & 0xf; | 807 | tf->device |= (block >> 24) & 0xf; |
813 | } | 808 | } |
814 | 809 | ||
810 | ata_rwcmd_protocol(qc); | ||
811 | |||
815 | qc->nsect = n_block; | 812 | qc->nsect = n_block; |
816 | tf->nsect = n_block & 0xff; | 813 | tf->nsect = n_block & 0xff; |
817 | 814 | ||
@@ -828,6 +825,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
828 | if ((block >> 28) || (n_block > 256)) | 825 | if ((block >> 28) || (n_block > 256)) |
829 | goto out_of_range; | 826 | goto out_of_range; |
830 | 827 | ||
828 | ata_rwcmd_protocol(qc); | ||
829 | |||
831 | /* Convert LBA to CHS */ | 830 | /* Convert LBA to CHS */ |
832 | track = (u32)block / dev->sectors; | 831 | track = (u32)block / dev->sectors; |
833 | cyl = track / dev->heads; | 832 | cyl = track / dev->heads; |
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index a18f2ac1d4a1..67d752ca8ae2 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h | |||
@@ -42,6 +42,7 @@ extern int atapi_enabled; | |||
42 | extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat); | 42 | extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat); |
43 | extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, | 43 | extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, |
44 | struct ata_device *dev); | 44 | struct ata_device *dev); |
45 | extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc); | ||
45 | extern void ata_qc_free(struct ata_queued_cmd *qc); | 46 | extern void ata_qc_free(struct ata_queued_cmd *qc); |
46 | extern int ata_qc_issue(struct ata_queued_cmd *qc); | 47 | extern int ata_qc_issue(struct ata_queued_cmd *qc); |
47 | extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); | 48 | extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); |