diff options
Diffstat (limited to 'drivers/ata/libata-sff.c')
-rw-r--r-- | drivers/ata/libata-sff.c | 199 |
1 files changed, 111 insertions, 88 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index b7ac80b4b1fb..60cd4b179766 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
@@ -147,7 +147,9 @@ void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf) | |||
147 | * @tf: ATA taskfile register set for storing input | 147 | * @tf: ATA taskfile register set for storing input |
148 | * | 148 | * |
149 | * Reads ATA taskfile registers for currently-selected device | 149 | * Reads ATA taskfile registers for currently-selected device |
150 | * into @tf. | 150 | * into @tf. Assumes the device has a fully SFF compliant task file |
151 | * layout and behaviour. If you device does not (eg has a different | ||
152 | * status method) then you will need to provide a replacement tf_read | ||
151 | * | 153 | * |
152 | * LOCKING: | 154 | * LOCKING: |
153 | * Inherited from caller. | 155 | * Inherited from caller. |
@@ -156,7 +158,7 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) | |||
156 | { | 158 | { |
157 | struct ata_ioports *ioaddr = &ap->ioaddr; | 159 | struct ata_ioports *ioaddr = &ap->ioaddr; |
158 | 160 | ||
159 | tf->command = ata_chk_status(ap); | 161 | tf->command = ata_check_status(ap); |
160 | tf->feature = ioread8(ioaddr->error_addr); | 162 | tf->feature = ioread8(ioaddr->error_addr); |
161 | tf->nsect = ioread8(ioaddr->nsect_addr); | 163 | tf->nsect = ioread8(ioaddr->nsect_addr); |
162 | tf->lbal = ioread8(ioaddr->lbal_addr); | 164 | tf->lbal = ioread8(ioaddr->lbal_addr); |
@@ -415,7 +417,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
415 | ap->hsm_task_state = HSM_ST_IDLE; | 417 | ap->hsm_task_state = HSM_ST_IDLE; |
416 | 418 | ||
417 | if (qc && (qc->tf.protocol == ATA_PROT_DMA || | 419 | if (qc && (qc->tf.protocol == ATA_PROT_DMA || |
418 | qc->tf.protocol == ATA_PROT_ATAPI_DMA)) { | 420 | qc->tf.protocol == ATAPI_PROT_DMA)) { |
419 | u8 host_stat; | 421 | u8 host_stat; |
420 | 422 | ||
421 | host_stat = ap->ops->bmdma_status(ap); | 423 | host_stat = ap->ops->bmdma_status(ap); |
@@ -549,7 +551,7 @@ int ata_pci_init_bmdma(struct ata_host *host) | |||
549 | return rc; | 551 | return rc; |
550 | 552 | ||
551 | /* request and iomap DMA region */ | 553 | /* request and iomap DMA region */ |
552 | rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME); | 554 | rc = pcim_iomap_regions(pdev, 1 << 4, dev_driver_string(gdev)); |
553 | if (rc) { | 555 | if (rc) { |
554 | dev_printk(KERN_ERR, gdev, "failed to request/iomap BAR4\n"); | 556 | dev_printk(KERN_ERR, gdev, "failed to request/iomap BAR4\n"); |
555 | return -ENOMEM; | 557 | return -ENOMEM; |
@@ -619,7 +621,8 @@ int ata_pci_init_sff_host(struct ata_host *host) | |||
619 | continue; | 621 | continue; |
620 | } | 622 | } |
621 | 623 | ||
622 | rc = pcim_iomap_regions(pdev, 0x3 << base, DRV_NAME); | 624 | rc = pcim_iomap_regions(pdev, 0x3 << base, |
625 | dev_driver_string(gdev)); | ||
623 | if (rc) { | 626 | if (rc) { |
624 | dev_printk(KERN_WARNING, gdev, | 627 | dev_printk(KERN_WARNING, gdev, |
625 | "failed to request/iomap BARs for port %d " | 628 | "failed to request/iomap BARs for port %d " |
@@ -711,6 +714,99 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev, | |||
711 | } | 714 | } |
712 | 715 | ||
713 | /** | 716 | /** |
717 | * ata_pci_activate_sff_host - start SFF host, request IRQ and register it | ||
718 | * @host: target SFF ATA host | ||
719 | * @irq_handler: irq_handler used when requesting IRQ(s) | ||
720 | * @sht: scsi_host_template to use when registering the host | ||
721 | * | ||
722 | * This is the counterpart of ata_host_activate() for SFF ATA | ||
723 | * hosts. This separate helper is necessary because SFF hosts | ||
724 | * use two separate interrupts in legacy mode. | ||
725 | * | ||
726 | * LOCKING: | ||
727 | * Inherited from calling layer (may sleep). | ||
728 | * | ||
729 | * RETURNS: | ||
730 | * 0 on success, -errno otherwise. | ||
731 | */ | ||
732 | int ata_pci_activate_sff_host(struct ata_host *host, | ||
733 | irq_handler_t irq_handler, | ||
734 | struct scsi_host_template *sht) | ||
735 | { | ||
736 | struct device *dev = host->dev; | ||
737 | struct pci_dev *pdev = to_pci_dev(dev); | ||
738 | const char *drv_name = dev_driver_string(host->dev); | ||
739 | int legacy_mode = 0, rc; | ||
740 | |||
741 | rc = ata_host_start(host); | ||
742 | if (rc) | ||
743 | return rc; | ||
744 | |||
745 | if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { | ||
746 | u8 tmp8, mask; | ||
747 | |||
748 | /* TODO: What if one channel is in native mode ... */ | ||
749 | pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); | ||
750 | mask = (1 << 2) | (1 << 0); | ||
751 | if ((tmp8 & mask) != mask) | ||
752 | legacy_mode = 1; | ||
753 | #if defined(CONFIG_NO_ATA_LEGACY) | ||
754 | /* Some platforms with PCI limits cannot address compat | ||
755 | port space. In that case we punt if their firmware has | ||
756 | left a device in compatibility mode */ | ||
757 | if (legacy_mode) { | ||
758 | printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n"); | ||
759 | return -EOPNOTSUPP; | ||
760 | } | ||
761 | #endif | ||
762 | } | ||
763 | |||
764 | if (!devres_open_group(dev, NULL, GFP_KERNEL)) | ||
765 | return -ENOMEM; | ||
766 | |||
767 | if (!legacy_mode && pdev->irq) { | ||
768 | rc = devm_request_irq(dev, pdev->irq, irq_handler, | ||
769 | IRQF_SHARED, drv_name, host); | ||
770 | if (rc) | ||
771 | goto out; | ||
772 | |||
773 | ata_port_desc(host->ports[0], "irq %d", pdev->irq); | ||
774 | ata_port_desc(host->ports[1], "irq %d", pdev->irq); | ||
775 | } else if (legacy_mode) { | ||
776 | if (!ata_port_is_dummy(host->ports[0])) { | ||
777 | rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev), | ||
778 | irq_handler, IRQF_SHARED, | ||
779 | drv_name, host); | ||
780 | if (rc) | ||
781 | goto out; | ||
782 | |||
783 | ata_port_desc(host->ports[0], "irq %d", | ||
784 | ATA_PRIMARY_IRQ(pdev)); | ||
785 | } | ||
786 | |||
787 | if (!ata_port_is_dummy(host->ports[1])) { | ||
788 | rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev), | ||
789 | irq_handler, IRQF_SHARED, | ||
790 | drv_name, host); | ||
791 | if (rc) | ||
792 | goto out; | ||
793 | |||
794 | ata_port_desc(host->ports[1], "irq %d", | ||
795 | ATA_SECONDARY_IRQ(pdev)); | ||
796 | } | ||
797 | } | ||
798 | |||
799 | rc = ata_host_register(host, sht); | ||
800 | out: | ||
801 | if (rc == 0) | ||
802 | devres_remove_group(dev, NULL); | ||
803 | else | ||
804 | devres_release_group(dev, NULL); | ||
805 | |||
806 | return rc; | ||
807 | } | ||
808 | |||
809 | /** | ||
714 | * ata_pci_init_one - Initialize/register PCI IDE host controller | 810 | * ata_pci_init_one - Initialize/register PCI IDE host controller |
715 | * @pdev: Controller to be initialized | 811 | * @pdev: Controller to be initialized |
716 | * @ppi: array of port_info, must be enough for two ports | 812 | * @ppi: array of port_info, must be enough for two ports |
@@ -739,8 +835,6 @@ int ata_pci_init_one(struct pci_dev *pdev, | |||
739 | struct device *dev = &pdev->dev; | 835 | struct device *dev = &pdev->dev; |
740 | const struct ata_port_info *pi = NULL; | 836 | const struct ata_port_info *pi = NULL; |
741 | struct ata_host *host = NULL; | 837 | struct ata_host *host = NULL; |
742 | u8 mask; | ||
743 | int legacy_mode = 0; | ||
744 | int i, rc; | 838 | int i, rc; |
745 | 839 | ||
746 | DPRINTK("ENTER\n"); | 840 | DPRINTK("ENTER\n"); |
@@ -762,95 +856,24 @@ int ata_pci_init_one(struct pci_dev *pdev, | |||
762 | if (!devres_open_group(dev, NULL, GFP_KERNEL)) | 856 | if (!devres_open_group(dev, NULL, GFP_KERNEL)) |
763 | return -ENOMEM; | 857 | return -ENOMEM; |
764 | 858 | ||
765 | /* FIXME: Really for ATA it isn't safe because the device may be | ||
766 | multi-purpose and we want to leave it alone if it was already | ||
767 | enabled. Secondly for shared use as Arjan says we want refcounting | ||
768 | |||
769 | Checking dev->is_enabled is insufficient as this is not set at | ||
770 | boot for the primary video which is BIOS enabled | ||
771 | */ | ||
772 | |||
773 | rc = pcim_enable_device(pdev); | 859 | rc = pcim_enable_device(pdev); |
774 | if (rc) | 860 | if (rc) |
775 | goto err_out; | 861 | goto out; |
776 | 862 | ||
777 | if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { | 863 | /* prepare and activate SFF host */ |
778 | u8 tmp8; | ||
779 | |||
780 | /* TODO: What if one channel is in native mode ... */ | ||
781 | pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); | ||
782 | mask = (1 << 2) | (1 << 0); | ||
783 | if ((tmp8 & mask) != mask) | ||
784 | legacy_mode = 1; | ||
785 | #if defined(CONFIG_NO_ATA_LEGACY) | ||
786 | /* Some platforms with PCI limits cannot address compat | ||
787 | port space. In that case we punt if their firmware has | ||
788 | left a device in compatibility mode */ | ||
789 | if (legacy_mode) { | ||
790 | printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n"); | ||
791 | rc = -EOPNOTSUPP; | ||
792 | goto err_out; | ||
793 | } | ||
794 | #endif | ||
795 | } | ||
796 | |||
797 | /* prepare host */ | ||
798 | rc = ata_pci_prepare_sff_host(pdev, ppi, &host); | 864 | rc = ata_pci_prepare_sff_host(pdev, ppi, &host); |
799 | if (rc) | 865 | if (rc) |
800 | goto err_out; | 866 | goto out; |
801 | 867 | ||
802 | pci_set_master(pdev); | 868 | pci_set_master(pdev); |
869 | rc = ata_pci_activate_sff_host(host, pi->port_ops->irq_handler, | ||
870 | pi->sht); | ||
871 | out: | ||
872 | if (rc == 0) | ||
873 | devres_remove_group(&pdev->dev, NULL); | ||
874 | else | ||
875 | devres_release_group(&pdev->dev, NULL); | ||
803 | 876 | ||
804 | /* start host and request IRQ */ | ||
805 | rc = ata_host_start(host); | ||
806 | if (rc) | ||
807 | goto err_out; | ||
808 | |||
809 | if (!legacy_mode && pdev->irq) { | ||
810 | /* We may have no IRQ assigned in which case we can poll. This | ||
811 | shouldn't happen on a sane system but robustness is cheap | ||
812 | in this case */ | ||
813 | rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler, | ||
814 | IRQF_SHARED, DRV_NAME, host); | ||
815 | if (rc) | ||
816 | goto err_out; | ||
817 | |||
818 | ata_port_desc(host->ports[0], "irq %d", pdev->irq); | ||
819 | ata_port_desc(host->ports[1], "irq %d", pdev->irq); | ||
820 | } else if (legacy_mode) { | ||
821 | if (!ata_port_is_dummy(host->ports[0])) { | ||
822 | rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev), | ||
823 | pi->port_ops->irq_handler, | ||
824 | IRQF_SHARED, DRV_NAME, host); | ||
825 | if (rc) | ||
826 | goto err_out; | ||
827 | |||
828 | ata_port_desc(host->ports[0], "irq %d", | ||
829 | ATA_PRIMARY_IRQ(pdev)); | ||
830 | } | ||
831 | |||
832 | if (!ata_port_is_dummy(host->ports[1])) { | ||
833 | rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev), | ||
834 | pi->port_ops->irq_handler, | ||
835 | IRQF_SHARED, DRV_NAME, host); | ||
836 | if (rc) | ||
837 | goto err_out; | ||
838 | |||
839 | ata_port_desc(host->ports[1], "irq %d", | ||
840 | ATA_SECONDARY_IRQ(pdev)); | ||
841 | } | ||
842 | } | ||
843 | |||
844 | /* register */ | ||
845 | rc = ata_host_register(host, pi->sht); | ||
846 | if (rc) | ||
847 | goto err_out; | ||
848 | |||
849 | devres_remove_group(dev, NULL); | ||
850 | return 0; | ||
851 | |||
852 | err_out: | ||
853 | devres_release_group(dev, NULL); | ||
854 | return rc; | 877 | return rc; |
855 | } | 878 | } |
856 | 879 | ||