diff options
author | Tejun Heo <htejun@gmail.com> | 2007-04-17 10:44:07 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-04-28 14:16:03 -0400 |
commit | 21b0ad4fb8306ac2bf5a249ffc978b1b8924c7d0 (patch) | |
tree | 9f82cc6a4bca146ce1021f0825cc12f18f9063b9 /drivers/ata/libata-sff.c | |
parent | d491b27b1959565671e2c05dff09b5f535a854ce (diff) |
libata: add init helpers including ata_pci_prepare_native_host()
These will be used to convert LLDs to new init model.
* Add irq_handler field to port_info. In new init model, requesting
IRQ is LLD's responsibility and libata doesn't need to know about
irq_handler. Most LLDs can simply register their irq_handler but
some need different irq_handler depending on specific chip. The
added port_info->irq_handler field can be used by LLDs to select
the matching IRQ handler in such cases.
* Add ata_dummy_port_info.
* Implement ata_pci_prepare_native_host(), a helper to alloc ATA host,
acquire all resources and init the host in one go.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-sff.c')
-rw-r--r-- | drivers/ata/libata-sff.c | 67 |
1 files changed, 65 insertions, 2 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index d551fa1cb104..142120cab874 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
@@ -663,13 +663,12 @@ static int ata_pci_init_bmdma(struct ata_host *host) | |||
663 | 663 | ||
664 | for (i = 0; i < 2; i++) { | 664 | for (i = 0; i < 2; i++) { |
665 | struct ata_port *ap = host->ports[i]; | 665 | struct ata_port *ap = host->ports[i]; |
666 | struct ata_ioports *ioaddr = &ap->ioaddr; | ||
667 | void __iomem *bmdma = host->iomap[4] + 8 * i; | 666 | void __iomem *bmdma = host->iomap[4] + 8 * i; |
668 | 667 | ||
669 | if (ata_port_is_dummy(ap)) | 668 | if (ata_port_is_dummy(ap)) |
670 | continue; | 669 | continue; |
671 | 670 | ||
672 | ioaddr->bmdma_addr = bmdma; | 671 | ap->ioaddr.bmdma_addr = bmdma; |
673 | if ((!(ap->flags & ATA_FLAG_IGN_SIMPLEX)) && | 672 | if ((!(ap->flags & ATA_FLAG_IGN_SIMPLEX)) && |
674 | (ioread8(bmdma + 2) & 0x80)) | 673 | (ioread8(bmdma + 2) & 0x80)) |
675 | host->flags |= ATA_HOST_SIMPLEX; | 674 | host->flags |= ATA_HOST_SIMPLEX; |
@@ -742,6 +741,70 @@ int ata_pci_init_native_host(struct ata_host *host, unsigned int port_mask) | |||
742 | return 0; | 741 | return 0; |
743 | } | 742 | } |
744 | 743 | ||
744 | /** | ||
745 | * ata_pci_prepare_native_host - helper to prepare native PCI ATA host | ||
746 | * @pdev: target PCI device | ||
747 | * @ppi: array of port_info | ||
748 | * @n_ports: number of ports to allocate | ||
749 | * @r_host: out argument for the initialized ATA host | ||
750 | * | ||
751 | * Helper to allocate ATA host for @pdev, acquire all native PCI | ||
752 | * resources and initialize it accordingly in one go. | ||
753 | * | ||
754 | * LOCKING: | ||
755 | * Inherited from calling layer (may sleep). | ||
756 | * | ||
757 | * RETURNS: | ||
758 | * 0 on success, -errno otherwise. | ||
759 | */ | ||
760 | int ata_pci_prepare_native_host(struct pci_dev *pdev, | ||
761 | const struct ata_port_info * const * ppi, | ||
762 | int n_ports, struct ata_host **r_host) | ||
763 | { | ||
764 | struct ata_host *host; | ||
765 | unsigned int port_mask; | ||
766 | int rc; | ||
767 | |||
768 | if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) | ||
769 | return -ENOMEM; | ||
770 | |||
771 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2); | ||
772 | if (!host) { | ||
773 | dev_printk(KERN_ERR, &pdev->dev, | ||
774 | "failed to allocate ATA host\n"); | ||
775 | rc = -ENOMEM; | ||
776 | goto err_out; | ||
777 | } | ||
778 | |||
779 | port_mask = ATA_PORT_PRIMARY; | ||
780 | if (n_ports > 1) | ||
781 | port_mask |= ATA_PORT_SECONDARY; | ||
782 | |||
783 | rc = ata_pci_init_native_host(host, port_mask); | ||
784 | if (rc) | ||
785 | goto err_out; | ||
786 | |||
787 | /* init DMA related stuff */ | ||
788 | rc = ata_pci_init_bmdma(host); | ||
789 | if (rc) | ||
790 | goto err_bmdma; | ||
791 | |||
792 | devres_remove_group(&pdev->dev, NULL); | ||
793 | *r_host = host; | ||
794 | return 0; | ||
795 | |||
796 | err_bmdma: | ||
797 | /* This is necessary because PCI and iomap resources are | ||
798 | * merged and releasing the top group won't release the | ||
799 | * acquired resources if some of those have been acquired | ||
800 | * before entering this function. | ||
801 | */ | ||
802 | pcim_iounmap_regions(pdev, 0xf); | ||
803 | err_out: | ||
804 | devres_release_group(&pdev->dev, NULL); | ||
805 | return rc; | ||
806 | } | ||
807 | |||
745 | struct ata_legacy_devres { | 808 | struct ata_legacy_devres { |
746 | unsigned int mask; | 809 | unsigned int mask; |
747 | unsigned long cmd_port[2]; | 810 | unsigned long cmd_port[2]; |