summaryrefslogtreecommitdiffstats
path: root/drivers/ide/pci/siimage.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/pci/siimage.c')
-rw-r--r--drivers/ide/pci/siimage.c171
1 files changed, 99 insertions, 72 deletions
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 6e9d7655d89..db2b88a369a 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -44,6 +44,8 @@
#include <linux/init.h>
#include <linux/io.h>
+#define DRV_NAME "siimage"
+
/**
* pdev_is_sata - check if device is SATA
* @pdev: PCI device to check
@@ -127,9 +129,10 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
{
+ struct ide_host *host = pci_get_drvdata(dev);
u8 tmp = 0;
- if (pci_get_drvdata(dev))
+ if (host->host_priv)
tmp = readb((void __iomem *)addr);
else
pci_read_config_byte(dev, addr, &tmp);
@@ -139,9 +142,10 @@ static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
{
+ struct ide_host *host = pci_get_drvdata(dev);
u16 tmp = 0;
- if (pci_get_drvdata(dev))
+ if (host->host_priv)
tmp = readw((void __iomem *)addr);
else
pci_read_config_word(dev, addr, &tmp);
@@ -151,7 +155,9 @@ static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
{
- if (pci_get_drvdata(dev))
+ struct ide_host *host = pci_get_drvdata(dev);
+
+ if (host->host_priv)
writeb(val, (void __iomem *)addr);
else
pci_write_config_byte(dev, addr, val);
@@ -159,7 +165,9 @@ static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
{
- if (pci_get_drvdata(dev))
+ struct ide_host *host = pci_get_drvdata(dev);
+
+ if (host->host_priv)
writew(val, (void __iomem *)addr);
else
pci_write_config_word(dev, addr, val);
@@ -167,7 +175,9 @@ static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
static void sil_iowrite32(struct pci_dev *dev, u32 val, unsigned long addr)
{
- if (pci_get_drvdata(dev))
+ struct ide_host *host = pci_get_drvdata(dev);
+
+ if (host->host_priv)
writel(val, (void __iomem *)addr);
else
pci_write_config_dword(dev, addr, val);
@@ -334,7 +344,7 @@ static int siimage_io_dma_test_irq(ide_drive_t *drive)
unsigned long addr = siimage_selreg(hwif, 1);
/* return 1 if INTR asserted */
- if (hwif->INB(hwif->dma_status) & 4)
+ if (inb(hwif->dma_base + ATA_DMA_STATUS) & 4)
return 1;
/* return 1 if Device INTR asserted */
@@ -382,7 +392,7 @@ static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
}
/* return 1 if INTR asserted */
- if (readb((void __iomem *)hwif->dma_status) & 0x04)
+ if (readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)) & 4)
return 1;
/* return 1 if Device INTR asserted */
@@ -445,66 +455,24 @@ static void sil_sata_pre_reset(ide_drive_t *drive)
}
/**
- * setup_mmio_siimage - switch controller into MMIO mode
- * @dev: PCI device we are configuring
- * @name: device name
- *
- * Attempt to put the device into MMIO mode. There are some slight
- * complications here with certain systems where the MMIO BAR isn't
- * mapped, so we have to be sure that we can fall back to I/O.
- */
-
-static unsigned int setup_mmio_siimage(struct pci_dev *dev, const char *name)
-{
- resource_size_t bar5 = pci_resource_start(dev, 5);
- unsigned long barsize = pci_resource_len(dev, 5);
- void __iomem *ioaddr;
-
- /*
- * Drop back to PIO if we can't map the MMIO. Some systems
- * seem to get terminally confused in the PCI spaces.
- */
- if (!request_mem_region(bar5, barsize, name)) {
- printk(KERN_WARNING "siimage: IDE controller MMIO ports not "
- "available.\n");
- return 0;
- }
-
- ioaddr = ioremap(bar5, barsize);
- if (ioaddr == NULL) {
- release_mem_region(bar5, barsize);
- return 0;
- }
-
- pci_set_master(dev);
- pci_set_drvdata(dev, (void *) ioaddr);
-
- return 1;
-}
-
-/**
* init_chipset_siimage - set up an SI device
* @dev: PCI device
- * @name: device name
*
* Perform the initial PCI set up for this device. Attempt to switch
* to 133 MHz clocking if the system isn't already set up to do it.
*/
-static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
- const char *name)
+static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev)
{
+ struct ide_host *host = pci_get_drvdata(dev);
+ void __iomem *ioaddr = host->host_priv;
unsigned long base, scsc_addr;
- void __iomem *ioaddr = NULL;
- u8 rev = dev->revision, tmp, BA5_EN;
+ u8 rev = dev->revision, tmp;
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255);
- pci_read_config_byte(dev, 0x8A, &BA5_EN);
-
- if ((BA5_EN & 0x01) || pci_resource_start(dev, 5))
- if (setup_mmio_siimage(dev, name))
- ioaddr = pci_get_drvdata(dev);
+ if (ioaddr)
+ pci_set_master(dev);
base = (unsigned long)ioaddr;
@@ -571,7 +539,8 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
{ "== 100", "== 133", "== 2X PCI", "DISABLED!" };
tmp >>= 4;
- printk(KERN_INFO "%s: BASE CLOCK %s\n", name, clk_str[tmp & 3]);
+ printk(KERN_INFO DRV_NAME " %s: BASE CLOCK %s\n",
+ pci_name(dev), clk_str[tmp & 3]);
}
return 0;
@@ -592,7 +561,8 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- void *addr = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ void *addr = host->host_priv;
u8 ch = hwif->channel;
struct ide_io_ports *io_ports = &hwif->io_ports;
unsigned long base;
@@ -601,7 +571,7 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
* Fill in the basic hwif bits
*/
hwif->host_flags |= IDE_HFLAG_MMIO;
- default_hwif_mmiops(hwif);
+
hwif->hwif_data = addr;
/*
@@ -669,7 +639,7 @@ static int is_dev_seagate_sata(ide_drive_t *drive)
* that can occur before we know what drives are present.
*/
-static void __devinit sil_quirkproc(ide_drive_t *drive)
+static void sil_quirkproc(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
@@ -691,16 +661,15 @@ static void __devinit sil_quirkproc(ide_drive_t *drive)
static void __devinit init_iops_siimage(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct ide_host *host = pci_get_drvdata(dev);
hwif->hwif_data = NULL;
/* Pessimal until we finish probing */
hwif->rqsize = 15;
- if (pci_get_drvdata(dev) == NULL)
- return;
-
- init_mmio_iops_siimage(hwif);
+ if (host->host_priv)
+ init_mmio_iops_siimage(hwif);
}
/**
@@ -710,7 +679,7 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif)
* Check for the presence of an ATA66 capable cable on the interface.
*/
-static u8 __devinit sil_cable_detect(ide_hwif_t *hwif)
+static u8 sil_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long addr = siimage_selreg(hwif, 0);
@@ -748,9 +717,9 @@ static const struct ide_dma_ops sil_dma_ops = {
.dma_lost_irq = ide_dma_lost_irq,
};
-#define DECLARE_SII_DEV(name_str, p_ops) \
+#define DECLARE_SII_DEV(p_ops) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_siimage, \
.init_iops = init_iops_siimage, \
.port_ops = p_ops, \
@@ -761,9 +730,8 @@ static const struct ide_dma_ops sil_dma_ops = {
}
static const struct ide_port_info siimage_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_SII_DEV("SiI680", &sil_pata_port_ops),
- /* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA", &sil_sata_port_ops),
- /* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA", &sil_sata_port_ops)
+ /* 0: SiI680 */ DECLARE_SII_DEV(&sil_pata_port_ops),
+ /* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops)
};
/**
@@ -778,8 +746,13 @@ static const struct ide_port_info siimage_chipsets[] __devinitdata = {
static int __devinit siimage_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
+ void __iomem *ioaddr = NULL;
+ resource_size_t bar5 = pci_resource_start(dev, 5);
+ unsigned long barsize = pci_resource_len(dev, 5);
+ int rc;
struct ide_port_info d;
u8 idx = id->driver_data;
+ u8 BA5_EN;
d = siimage_chipsets[idx];
@@ -787,7 +760,7 @@ static int __devinit siimage_init_one(struct pci_dev *dev,
static int first = 1;
if (first) {
- printk(KERN_INFO "siimage: For full SATA support you "
+ printk(KERN_INFO DRV_NAME ": For full SATA support you "
"should use the libata sata_sil module.\n");
first = 0;
}
@@ -795,14 +768,61 @@ static int __devinit siimage_init_one(struct pci_dev *dev,
d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
}
- return ide_setup_pci_device(dev, &d);
+ rc = pci_enable_device(dev);
+ if (rc)
+ return rc;
+
+ pci_read_config_byte(dev, 0x8A, &BA5_EN);
+ if ((BA5_EN & 0x01) || bar5) {
+ /*
+ * Drop back to PIO if we can't map the MMIO. Some systems
+ * seem to get terminally confused in the PCI spaces.
+ */
+ if (!request_mem_region(bar5, barsize, d.name)) {
+ printk(KERN_WARNING DRV_NAME " %s: MMIO ports not "
+ "available\n", pci_name(dev));
+ } else {
+ ioaddr = ioremap(bar5, barsize);
+ if (ioaddr == NULL)
+ release_mem_region(bar5, barsize);
+ }
+ }
+
+ rc = ide_pci_init_one(dev, &d, ioaddr);
+ if (rc) {
+ if (ioaddr) {
+ iounmap(ioaddr);
+ release_mem_region(bar5, barsize);
+ }
+ pci_disable_device(dev);
+ }
+
+ return rc;
+}
+
+static void __devexit siimage_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ void __iomem *ioaddr = host->host_priv;
+
+ ide_pci_remove(dev);
+
+ if (ioaddr) {
+ resource_size_t bar5 = pci_resource_start(dev, 5);
+ unsigned long barsize = pci_resource_len(dev, 5);
+
+ iounmap(ioaddr);
+ release_mem_region(bar5, barsize);
+ }
+
+ pci_disable_device(dev);
}
static const struct pci_device_id siimage_pci_tbl[] = {
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), 0 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_3112), 1 },
- { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 2 },
+ { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 1 },
#endif
{ 0, },
};
@@ -812,6 +832,7 @@ static struct pci_driver driver = {
.name = "SiI_IDE",
.id_table = siimage_pci_tbl,
.probe = siimage_init_one,
+ .remove = __devexit_p(siimage_remove),
};
static int __init siimage_ide_init(void)
@@ -819,7 +840,13 @@ static int __init siimage_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit siimage_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(siimage_ide_init);
+module_exit(siimage_ide_exit);
MODULE_AUTHOR("Andre Hedrick, Alan Cox");
MODULE_DESCRIPTION("PCI driver module for SiI IDE");