#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/ide.h>
-#include <linux/delay.h>
#include <asm/io.h>
#include <asm/irq.h>
second_chance_to_dma:
#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
- if (hwif->mmio)
+ if ((hwif->mmio) && (hwif->dma_base))
return hwif->dma_base;
if (hwif->mate && hwif->mate->dma_base) {
dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
} else {
- dma_base = pci_resource_start(dev, 4);
+ dma_base = (hwif->mmio) ?
+ ((unsigned long) hwif->hwif_data) :
+ (pci_resource_start(dev, 4));
if (!dma_base) {
- printk(KERN_ERR "%s: dma_base is invalid\n",
- hwif->cds->name);
+ printk(KERN_ERR "%s: dma_base is invalid (0x%04lx)\n",
+ hwif->cds->name, dma_base);
+ dma_base = 0;
}
}
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.
*/
- if (hwif->mate && hwif->mate->dma_base) {
+ /* 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)
+ {
printk(KERN_INFO "%s: simplex device: "
"DMA disabled\n",
hwif->cds->name);
* Set up BM-DMA capability
* (PnP BIOS should have done this)
*/
- /* default DMA off if we had to configure it here */
- hwif->autodma = 0;
+ if ((d->flags & IDEPCI_FLAG_FORCE_MASTER) == 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;
u32 class_rev;
u16 pcicmd;
+ if (!noautodma)
+ ret = 1;
+
if (noisy)
ide_setup_pci_noise(dev, d);
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;
*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);
- return 0;
+ 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 pciirq, ata_index_t *index)
+void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int autodma, 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
*/
static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d, u8 noisy)
{
+ int autodma = 0;
int pciirq = 0;
int tried_config = 0;
ata_index_t index = { .b = { .low = 0xff, .high = 0xff } };
- if (ide_setup_pci_controller(dev, d, noisy, &tried_config) < 0)
+ if((autodma = ide_setup_pci_controller(dev, d, noisy, &tried_config)) < 0)
return index;
/*
if(pciirq < 0) /* Error not an IRQ */
return index;
- ide_pci_setup_ports(dev, d, pciirq, &index);
+ ide_pci_setup_ports(dev, d, autodma, pciirq, &index);
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);
+}
+
void 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);
if ((index_list.b.low & 0xf0) != 0xf0)
- probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.low], d->fixup);
+ probe_pci_hwif_init(&ide_hwifs[index_list.b.low], d);
if ((index_list.b.high & 0xf0) != 0xf0)
- probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.high], d->fixup);
+ probe_pci_hwif_init(&ide_hwifs[index_list.b.high], d);
create_proc_ide_interfaces();
}
ata_index_t index_list2 = do_ide_setup_pci_device(dev2, d, 0);
if ((index_list.b.low & 0xf0) != 0xf0)
- probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.low], d->fixup);
+ probe_pci_hwif_init(&ide_hwifs[index_list.b.low], d);
if ((index_list.b.high & 0xf0) != 0xf0)
- probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.high], d->fixup);
+ probe_pci_hwif_init(&ide_hwifs[index_list.b.high], d);
if ((index_list2.b.low & 0xf0) != 0xf0)
- probe_hwif_init_with_fixup(&ide_hwifs[index_list2.b.low], d->fixup);
+ probe_pci_hwif_init(&ide_hwifs[index_list2.b.low], d);
if ((index_list2.b.high & 0xf0) != 0xf0)
- probe_hwif_init_with_fixup(&ide_hwifs[index_list2.b.high], d->fixup);
+ probe_pci_hwif_init(&ide_hwifs[index_list2.b.high], d);
create_proc_ide_interfaces();
}
EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
-
-static int ide_pci_try_unregister(struct pci_dev *dev)
-{
- int i;
- int err = 0;
- ide_hwif_t *hwif = ide_hwifs;
-
- for(i = 0; i < MAX_HWIFS; i++) {
- if(hwif->configured && hwif->pci_dev == dev)
- err |= __ide_unregister_hwif(hwif);
- i++;
- hwif++;
- }
- return err;
-}
-
/**
* ide_pci_remove_hwifs - remove PCI interfaces
* @dev: PCI device
{
int i;
ide_hwif_t *hwif = ide_hwifs;
- int err;
down(&ide_cfg_sem);
-
- err = ide_pci_try_unregister(dev);
-
- if(err < 0) {
- printk(KERN_ERR "ide: PCI interfaces busy during hotplug. Waiting....\n");
- for(i = 0; i < MAX_HWIFS; i++) {
- if(hwif->configured && hwif->pci_dev == dev)
- removed_hwif_iops(hwif);
- i++;
- hwif++;
+#if 0
+ for(i = 0; i < MAX_HWIFS; i++)
+ {
+ if(hwif->configured && hwif->pci_dev == dev)
+ {
+ removed_hwif_iops(hwif);
}
+ 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++;
}
- /* Should drop this out to a work queue I think ? */
- while(ide_pci_try_unregister(dev) < 0)
- msleep(1000);
up(&ide_cfg_sem);
}