aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlbert Lee <albertcc@tw.ibm.com>2005-10-12 03:06:27 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-10-18 17:16:13 -0400
commit8cbd6df1f0ce977ab7b61feffa59879bb5e0ed8f (patch)
treec460778581293ad479ec4983690ccc46bcb4df56
parent07506697d1c615924298406f2357810709c09bcd (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>
-rw-r--r--drivers/scsi/libata-core.c105
-rw-r--r--drivers/scsi/libata-scsi.c13
-rw-r--r--drivers/scsi/libata.h1
-rw-r--r--include/linux/ata.h4
-rw-r--r--include/linux/libata.h6
5 files changed, 50 insertions, 79 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/** 619static 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,
630static 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 */
675static void ata_dev_set_protocol(struct ata_device *dev) 647void 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
694static const char * xfer_mode_str[] = { 668static const char * xfer_mode_str[] = {
@@ -1641,7 +1615,7 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode,
1641 */ 1615 */
1642static void ata_set_mode(struct ata_port *ap) 1616static 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
1680err_out: 1649err_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;
42extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat); 42extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
43extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, 43extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
44 struct ata_device *dev); 44 struct ata_device *dev);
45extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
45extern void ata_qc_free(struct ata_queued_cmd *qc); 46extern void ata_qc_free(struct ata_queued_cmd *qc);
46extern int ata_qc_issue(struct ata_queued_cmd *qc); 47extern int ata_qc_issue(struct ata_queued_cmd *qc);
47extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); 48extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
diff --git a/include/linux/ata.h b/include/linux/ata.h
index ecb7346d0c16..630908c9378b 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -128,6 +128,10 @@ enum {
128 ATA_CMD_PIO_READ_EXT = 0x24, 128 ATA_CMD_PIO_READ_EXT = 0x24,
129 ATA_CMD_PIO_WRITE = 0x30, 129 ATA_CMD_PIO_WRITE = 0x30,
130 ATA_CMD_PIO_WRITE_EXT = 0x34, 130 ATA_CMD_PIO_WRITE_EXT = 0x34,
131 ATA_CMD_READ_MULTI = 0xC4,
132 ATA_CMD_READ_MULTI_EXT = 0x29,
133 ATA_CMD_WRITE_MULTI = 0xC5,
134 ATA_CMD_WRITE_MULTI_EXT = 0x39,
131 ATA_CMD_SET_FEATURES = 0xEF, 135 ATA_CMD_SET_FEATURES = 0xEF,
132 ATA_CMD_PACKET = 0xA0, 136 ATA_CMD_PACKET = 0xA0,
133 ATA_CMD_VERIFY = 0x40, 137 ATA_CMD_VERIFY = 0x40,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 7929cfc9318d..0261c55f3483 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -283,10 +283,8 @@ struct ata_device {
283 u8 xfer_mode; 283 u8 xfer_mode;
284 unsigned int xfer_shift; /* ATA_SHIFT_xxx */ 284 unsigned int xfer_shift; /* ATA_SHIFT_xxx */
285 285
286 /* cache info about current transfer mode */ 286 unsigned int multi_count; /* sectors count for
287 u8 xfer_protocol; /* taskfile xfer protocol */ 287 READ/WRITE MULTIPLE */
288 u8 read_cmd; /* opcode to use on read */
289 u8 write_cmd; /* opcode to use on write */
290 288
291 /* for CHS addressing */ 289 /* for CHS addressing */
292 u16 cylinders; /* Number of cylinders */ 290 u16 cylinders; /* Number of cylinders */