/*
- * linux/drivers/ide/setup-pci.c Version 1.14 2004/08/10
+ * linux/drivers/ide/setup-pci.c Version 1.10 2002/08/19
*
* Copyright (c) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- * Copyright (c) 2004 Red Hat <alan@redhat.com>
*
* Copyright (c) 1995-1998 Mark Lord
* May be copied or modified under the terms of the GNU General Public License
* Use pci_set_master
* Fix misreporting of I/O v MMIO problems
* Initial fixups for simplex devices
- * Hot unplug paths
*/
/*
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/ide.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/irq.h>
* Match a PCI IDE port against an entry in ide_hwifs[],
* based on io_base port if possible. Return the matching hwif,
* or a new hwif. If we find an error (clashing, out of devices, etc)
- * return NULL. The caller must hold the ide_cfg_sem.
+ * return NULL
*
* FIXME: we need to handle mmio matches here too
*/
*
* Unless there is a bootable card that does not use the standard
* ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag.
- *
- * FIXME: migrate use of ide_unknown to also use ->configured
*/
if (bootable) {
for (h = 0; h < MAX_HWIFS; ++h) {
second_chance_to_dma:
#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
- if ((hwif->mmio) && (hwif->dma_base))
+ if (hwif->mmio)
return hwif->dma_base;
if (hwif->mate && hwif->mate->dma_base) {
dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
} else {
- dma_base = (hwif->mmio) ?
- ((unsigned long) hwif->hwif_data) :
- (pci_resource_start(dev, 4));
+ dma_base = pci_resource_start(dev, 4);
if (!dma_base) {
- printk(KERN_ERR "%s: dma_base is invalid (0x%04lx)\n",
- hwif->cds->name, dma_base);
- dma_base = 0;
+ printk(KERN_ERR "%s: dma_base is invalid\n",
+ hwif->cds->name);
}
}
case PCI_DEVICE_ID_AMD_VIPER_7409:
case PCI_DEVICE_ID_CMD_643:
case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+ case PCI_DEVICE_ID_REVOLUTION:
simplex_stat = hwif->INB(dma_base + 2);
hwif->OUTB((simplex_stat&0x60),(dma_base + 2));
simplex_stat = hwif->INB(dma_base + 2);
simplex_stat = hwif->INB(dma_base + 2);
if (simplex_stat & 0x80) {
/* simplex device? */
-#if 0
/*
* At this point we haven't probed the drives so we can't make the
* appropriate decision. Really we should defer this problem
* to be the DMA end. This has to be become dynamic to handle hot
* plug.
*/
- /* Don't enable DMA on a simplex channel with no drives */
- if (!hwif->drives[0].present && !hwif->drives[1].present)
- {
- printk(KERN_INFO "%s: simplex device with no drives: DMA disabled\n",
- hwif->cds->name);
- dma_base = 0;
- }
- /* If our other channel has DMA then we cannot */
- else
-#endif
- if(hwif->mate && hwif->mate->dma_base)
- {
+ if (hwif->mate && hwif->mate->dma_base) {
printk(KERN_INFO "%s: simplex device: "
"DMA disabled\n",
hwif->cds->name);
static int ide_pci_enable(struct pci_dev *dev, ide_pci_device_t *d)
{
-
+ int ret;
+
if (pci_enable_device(dev)) {
- if (pci_enable_device_bars(dev, 1 << 4)) {
+ ret = pci_enable_device_bars(dev, 1 << 4);
+ if (ret < 0) {
printk(KERN_WARNING "%s: (ide_setup_pci_device:) "
"Could not enable device.\n", d->name);
- return -EBUSY;
- } else
- printk(KERN_WARNING "%s: BIOS configuration fixed.\n", d->name);
+ goto out;
+ }
+ printk(KERN_WARNING "%s: BIOS configuration fixed.\n", d->name);
}
/*
* dma mask field to the ide_pci_device_t if we need it (or let
* lower level driver set the dma mask)
*/
- if (pci_set_dma_mask(dev, 0xffffffff)) {
+ ret = pci_set_dma_mask(dev, DMA_32BIT_MASK);
+ if (ret < 0) {
printk(KERN_ERR "%s: can't set dma mask\n", d->name);
- return -EBUSY;
+ goto out;
}
-
+
/* FIXME: Temporary - until we put in the hotplug interface logic
- Check that the bits we want are not in use by someone else */
- if (pci_request_region(dev, 4, "ide_tmp"))
- return -EBUSY;
+ Check that the bits we want are not in use by someone else. */
+ ret = pci_request_region(dev, 4, "ide_tmp");
+ if (ret < 0)
+ goto out;
+
pci_release_region(dev, 4);
-
- return 0;
+out:
+ return ret;
}
/**
ctl = port ? 0x374 : 0x3f4;
base = port ? 0x170 : 0x1f0;
}
-
- /*
- * Protect against a hwif being unloaded as we attach to it
- */
- down(&ide_cfg_sem);
-
if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL)
- {
- up(&ide_cfg_sem);
return NULL; /* no room in ide_hwifs[] */
- }
-
if (hwif->io_ports[IDE_DATA_OFFSET] != base ||
hwif->io_ports[IDE_CONTROL_OFFSET] != (ctl | 2)) {
memset(&hwif->hw, 0, sizeof(hwif->hw));
+#ifndef IDE_ARCH_OBSOLETE_INIT
+ ide_std_init_ports(&hwif->hw, base, (ctl | 2));
+ hwif->hw.io_ports[IDE_IRQ_OFFSET] = 0;
+#else
ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL);
+#endif
memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
}
hwif->pci_dev = dev;
hwif->cds = (struct ide_pci_device_s *) d;
hwif->channel = port;
- hwif->configured = 1;
-
- up(&ide_cfg_sem);
if (!hwif->irq)
hwif->irq = irq;
* Set up BM-DMA capability
* (PnP BIOS should have done this)
*/
- if ((d->flags & IDEPCI_FLAG_FORCE_MASTER) == 0) {
- /*
- * default DMA off if we had to
- * configure it here
- */
- hwif->autodma = 0;
- }
+ /* default DMA off if we had to configure it here */
+ hwif->autodma = 0;
pci_set_master(dev);
if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
printk(KERN_ERR "%s: %s error updating PCICMD\n",
}
}
}
+
+#ifndef CONFIG_IDEDMA_PCI_AUTO
+#warning CONFIG_IDEDMA_PCI_AUTO=n support is obsolete, and will be removed soon.
+#endif
+
#endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/
/**
static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, int noisy, int *config)
{
- int ret = 0;
+ int ret;
u32 class_rev;
u16 pcicmd;
- if (!noautodma)
- ret = 1;
-
if (noisy)
ide_setup_pci_noise(dev, d);
- if (ide_pci_enable(dev, d))
- return -EBUSY;
-
- if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) {
+ ret = ide_pci_enable(dev, d);
+ if (ret < 0)
+ goto out;
+
+ ret = pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
+ if (ret < 0) {
printk(KERN_ERR "%s: error accessing PCI regs\n", d->name);
- return -EIO;
+ goto out;
}
if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */
- if (ide_pci_configure(dev, d))
- return -ENODEV;
- /* default DMA off if we had to configure it here */
- ret = 0;
+ ret = ide_pci_configure(dev, d);
+ if (ret < 0)
+ goto out;
*config = 1;
printk(KERN_INFO "%s: device enabled (Linux)\n", d->name);
}
class_rev &= 0xff;
if (noisy)
printk(KERN_INFO "%s: chipset revision %d\n", d->name, class_rev);
+out:
return ret;
}
* ide_pci_setup_ports - configure ports/devices on PCI IDE
* @dev: PCI device
* @d: IDE pci device info
- * @autodma: Should we enable DMA
* @pciirq: IRQ line
* @index: ata index to update
*
* where the chipset setup is not the default PCI IDE one.
*/
-void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int autodma, int pciirq, ata_index_t *index)
+void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, ata_index_t *index)
{
int port;
int at_least_one_hwif_enabled = 0;
if (d->autodma == NODMA)
goto bypass_legacy_dma;
- if (d->autodma == NOAUTODMA)
- autodma = 0;
- if (autodma)
- hwif->autodma = 1;
-
+
if(d->init_setup_dma)
d->init_setup_dma(dev, d, hwif);
else
* we "know" about, this information is in the ide_pci_device_t struct;
* for all other chipsets, we just assume both interfaces are enabled.
*/
-static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d, u8 noisy)
+static int do_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d,
+ ata_index_t *index, u8 noisy)
{
- int autodma = 0;
- int pciirq = 0;
+ static ata_index_t ata_index = { .b = { .low = 0xff, .high = 0xff } };
int tried_config = 0;
- ata_index_t index = { .b = { .low = 0xff, .high = 0xff } };
+ int pciirq, ret;
- if((autodma = ide_setup_pci_controller(dev, d, noisy, &tried_config)) < 0)
- return index;
+ ret = ide_setup_pci_controller(dev, d, noisy, &tried_config);
+ if (ret < 0)
+ goto out;
/*
* Can we trust the reported IRQ?
* space, place chipset into init-mode, and/or preserve
* an interrupt if the card is not native ide support.
*/
- pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : 0;
+ ret = d->init_chipset ? d->init_chipset(dev, d->name) : 0;
+ if (ret < 0)
+ goto out;
+ pciirq = ret;
} else if (tried_config) {
if (noisy)
printk(KERN_INFO "%s: will probe irqs later\n", d->name);
d->name, pciirq);
pciirq = 0;
} else {
- if (d->init_chipset)
- {
- if(d->init_chipset(dev, d->name) < 0)
- return index;
+ if (d->init_chipset) {
+ ret = d->init_chipset(dev, d->name);
+ if (ret < 0)
+ goto out;
}
if (noisy)
#ifdef __sparc__
d->name, pciirq);
#endif
}
-
- if(pciirq < 0) /* Error not an IRQ */
- return index;
- ide_pci_setup_ports(dev, d, autodma, pciirq, &index);
+ /* FIXME: silent failure can happen */
- return index;
-}
-
-/**
- * probe_pci_hwif_init - probe the hwif then allow fixups
- * @hwif: interface to probe
- * @d: PCI device
- *
- * Perform the generic probe and if it is successful invoke any
- * remaining post probe fixup logic in the driver itself.
- */
-static void probe_pci_hwif_init(ide_hwif_t *hwif, ide_pci_device_t *d) {
- probe_hwif_init_with_fixup(hwif, d->fixup);
+ *index = ata_index;
+ ide_pci_setup_ports(dev, d, pciirq, index);
+out:
+ return ret;
}
-void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d)
+int ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
{
- ata_index_t index_list = do_ide_setup_pci_device(dev, d, 1);
+ ata_index_t index_list;
+ int ret;
+
+ ret = do_ide_setup_pci_device(dev, d, &index_list, 1);
+ if (ret < 0)
+ goto out;
if ((index_list.b.low & 0xf0) != 0xf0)
- probe_pci_hwif_init(&ide_hwifs[index_list.b.low], d);
+ probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.low], d->fixup);
if ((index_list.b.high & 0xf0) != 0xf0)
- probe_pci_hwif_init(&ide_hwifs[index_list.b.high], d);
+ probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.high], d->fixup);
create_proc_ide_interfaces();
+out:
+ return ret;
}
EXPORT_SYMBOL_GPL(ide_setup_pci_device);
-void ide_setup_pci_devices (struct pci_dev *dev, struct pci_dev *dev2, ide_pci_device_t *d)
+int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
+ ide_pci_device_t *d)
{
- ata_index_t index_list = do_ide_setup_pci_device(dev, d, 1);
- ata_index_t index_list2 = do_ide_setup_pci_device(dev2, d, 0);
-
- if ((index_list.b.low & 0xf0) != 0xf0)
- probe_pci_hwif_init(&ide_hwifs[index_list.b.low], d);
- if ((index_list.b.high & 0xf0) != 0xf0)
- probe_pci_hwif_init(&ide_hwifs[index_list.b.high], d);
- if ((index_list2.b.low & 0xf0) != 0xf0)
- probe_pci_hwif_init(&ide_hwifs[index_list2.b.low], d);
- if ((index_list2.b.high & 0xf0) != 0xf0)
- probe_pci_hwif_init(&ide_hwifs[index_list2.b.high], d);
-
- create_proc_ide_interfaces();
-}
+ struct pci_dev *pdev[] = { dev1, dev2 };
+ ata_index_t index_list[2];
+ int ret, i;
-EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
+ for (i = 0; i < 2; i++) {
+ ret = do_ide_setup_pci_device(pdev[i], d, index_list + i, !i);
+ /*
+ * FIXME: Mom, mom, they stole me the helper function to undo
+ * do_ide_setup_pci_device() on the first device!
+ */
+ if (ret < 0)
+ goto out;
+ }
-/**
- * ide_pci_remove_hwifs - remove PCI interfaces
- * @dev: PCI device
- *
- * Remove any hwif attached to this PCI device. This will call
- * back the various hwif->remove functions. In order to get the
- * best results when delays occur we kill the iops before we
- * potentially start blocking for long periods untangling the
- * IDE layer.
- *
- * Takes the ide_cfg_sem in order to protect against races with
- * new/old hwifs. Calls functions that take all the other locks
- * so should be called with no locks held.
- */
-
-void ide_pci_remove_hwifs(struct pci_dev *dev)
-{
- int i;
- ide_hwif_t *hwif = ide_hwifs;
+ for (i = 0; i < 2; i++) {
+ u8 idx[2] = { index_list[i].b.low, index_list[i].b.high };
+ int j;
- down(&ide_cfg_sem);
-#if 0
- for(i = 0; i < MAX_HWIFS; i++)
- {
- if(hwif->configured && hwif->pci_dev == dev)
- {
- removed_hwif_iops(hwif);
+ for (j = 0; j < 2; j++) {
+ if ((idx[j] & 0xf0) != 0xf0)
+ probe_hwif_init(ide_hwifs + idx[j]);
}
- i++;
- hwif++;
}
-#endif
- hwif = ide_hwifs;
-
- for(i = 0; i < MAX_HWIFS; i++)
- {
- if(hwif->configured && hwif->pci_dev == dev)
- __ide_unregister_hwif(hwif);
- i++;
- hwif++;
- }
- up(&ide_cfg_sem);
-}
-EXPORT_SYMBOL_GPL(ide_pci_remove_hwifs);
+ create_proc_ide_interfaces();
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
/*
* Module interfaces
static LIST_HEAD(ide_pci_drivers);
/*
- * ide_register_pci_driver - attach IDE driver
+ * __ide_pci_register_driver - attach IDE driver
* @driver: pci driver
+ * @module: owner module of the driver
*
* Registers a driver with the IDE layer. The IDE layer arranges that
* boot time setup is done in the expected device order and then
* Returns are the same as for pci_register_driver
*/
-int ide_pci_register_driver(struct pci_driver *driver)
+int __ide_pci_register_driver(struct pci_driver *driver, struct module *module)
{
if(!pre_init)
- return pci_module_init(driver);
+ return __pci_register_driver(driver, module);
+ driver->driver.owner = module;
list_add_tail(&driver->node, &ide_pci_drivers);
return 0;
}
-EXPORT_SYMBOL_GPL(ide_pci_register_driver);
+EXPORT_SYMBOL_GPL(__ide_pci_register_driver);
/**
* ide_unregister_pci_driver - unregister an IDE driver
d = list_entry(l, struct pci_driver, node);
if(d->id_table)
{
- const struct pci_device_id *id = pci_match_device(d->id_table, dev);
+ const struct pci_device_id *id = pci_match_id(d->id_table, dev);
if(id != NULL)
{
if(d->probe(dev, id) >= 0)
{
list_del(l);
d = list_entry(l, struct pci_driver, node);
- pci_register_driver(d);
+ __pci_register_driver(d, d->driver.owner);
}
}