#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>
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;
}
/**
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];
}
* 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;
+ *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_hwif_init(&ide_hwifs[index_list.b.low]);
+ probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.low], d->fixup);
if ((index_list.b.high & 0xf0) != 0xf0)
- probe_hwif_init(&ide_hwifs[index_list.b.high]);
+ 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);
+ struct pci_dev *pdev[] = { dev1, dev2 };
+ ata_index_t index_list[2];
+ int ret, i;
- if ((index_list.b.low & 0xf0) != 0xf0)
- probe_hwif_init(&ide_hwifs[index_list.b.low]);
- if ((index_list.b.high & 0xf0) != 0xf0)
- probe_hwif_init(&ide_hwifs[index_list.b.high]);
- if ((index_list2.b.low & 0xf0) != 0xf0)
- probe_hwif_init(&ide_hwifs[index_list2.b.low]);
- if ((index_list2.b.high & 0xf0) != 0xf0)
- probe_hwif_init(&ide_hwifs[index_list2.b.high]);
+ 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;
+ }
+
+ for (i = 0; i < 2; i++) {
+ u8 idx[2] = { index_list[i].b.low, index_list[i].b.high };
+ int j;
+
+ for (j = 0; j < 2; j++) {
+ if ((idx[j] & 0xf0) != 0xf0)
+ probe_hwif_init(ide_hwifs + idx[j]);
+ }
+ }
create_proc_ide_interfaces();
+out:
+ return ret;
}
EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
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);
}
}