Commit 4f4cf51e authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] split up setup-pci further

This allows drivers to do partial setup themselves and to handle boards
that don't follow the normal PCI BAR4 allocation policy. Also fix the
oops on boot and simplex bits.
parent 58558795
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
* Split the set up function into multiple functions * Split the set up function into multiple functions
* Use pci_set_master * Use pci_set_master
* Fix misreporting of I/O v MMIO problems * Fix misreporting of I/O v MMIO problems
* Initial fixups for simplex devices
*/ */
/* /*
...@@ -42,6 +43,8 @@ ...@@ -42,6 +43,8 @@
* based on io_base port if possible. Return the matching hwif, * 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) * or a new hwif. If we find an error (clashing, out of devices, etc)
* return NULL * return NULL
*
* FIXME: we need to handle mmio matches here too
*/ */
static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name) static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name)
...@@ -144,34 +147,9 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) ...@@ -144,34 +147,9 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
} }
#if 0
/*
* At this point we have enabled the device, but may previously
* have done a BAR4 enable alone. We should be prepared to assign
* resources here.
*/
/*
* Setup base registers for IDE command/control
* spaces for each interface:
*/
for (reg = 0; reg < 4; reg++) {
struct resource *res = dev->resource + reg;
if ((res->flags & IORESOURCE_IO) == 0)
continue;
if (!res->start) {
if(pci_assign_resource(dev, reg)) {
printk(KERN_ERR "%s: Missing I/O address #%d\n", name, reg);
return -ENXIO;
}
}
}
#endif
return 0; return 0;
} }
#ifdef CONFIG_BLK_DEV_IDEDMA
#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED #ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
/* /*
* Long lost data from 2.0.34 that is now in 2.0.39 * Long lost data from 2.0.34 that is now in 2.0.39
...@@ -192,9 +170,6 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) ...@@ -192,9 +170,6 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
* Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space: * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
* If need be we set up the DMA base. Where a device has a partner that * If need be we set up the DMA base. Where a device has a partner that
* is already in DMA mode we check and enforce IDE simplex rules. * is already in DMA mode we check and enforce IDE simplex rules.
*
* FIXME: currently we are sometimes enforicng simplex when it is not
* needed. We fail the safe way but why is it occurring ??
*/ */
static unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif) static unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif)
...@@ -274,7 +249,14 @@ static unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif) ...@@ -274,7 +249,14 @@ static unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif)
simplex_stat = hwif->INB(dma_base + 2); simplex_stat = hwif->INB(dma_base + 2);
if (simplex_stat & 0x80) { if (simplex_stat & 0x80) {
/* simplex device? */ /* 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
* until we tune the drive then try to grab DMA ownership if we want
* 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 */ /* Don't enable DMA on a simplex channel with no drives */
if (!hwif->drives[0].present && !hwif->drives[1].present) if (!hwif->drives[0].present && !hwif->drives[1].present)
{ {
...@@ -283,7 +265,9 @@ static unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif) ...@@ -283,7 +265,9 @@ static unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif)
dma_base = 0; dma_base = 0;
} }
/* If our other channel has DMA then we cannot */ /* If our other channel has DMA then we cannot */
else if(hwif->mate && hwif->mate->dma_base) else
#endif
if(hwif->mate && hwif->mate->dma_base)
{ {
printk(KERN_INFO "%s: simplex device: " printk(KERN_INFO "%s: simplex device: "
"DMA disabled\n", "DMA disabled\n",
...@@ -295,9 +279,8 @@ static unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif) ...@@ -295,9 +279,8 @@ static unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif)
} }
return dma_base; return dma_base;
} }
#endif /* CONFIG_BLK_DEV_IDEDMA */
static void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d) void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d)
{ {
if ((d->vendor != dev->vendor) && (d->device != dev->device)) { if ((d->vendor != dev->vendor) && (d->device != dev->device)) {
printk(KERN_INFO "%s: unknown IDE controller at PCI slot " printk(KERN_INFO "%s: unknown IDE controller at PCI slot "
...@@ -309,6 +292,9 @@ static void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d) ...@@ -309,6 +292,9 @@ static void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d)
} }
} }
EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
/** /**
* ide_pci_enable - do PCI enables * ide_pci_enable - do PCI enables
* @dev: PCI device * @dev: PCI device
...@@ -414,8 +400,7 @@ static int ide_pci_check_iomem(struct pci_dev *dev, ide_pci_device_t *d, int bar ...@@ -414,8 +400,7 @@ static int ide_pci_check_iomem(struct pci_dev *dev, ide_pci_device_t *d, int bar
"<andre@linux-ide.org>.\n", d->name); "<andre@linux-ide.org>.\n", d->name);
return -EINVAL; return -EINVAL;
} }
/** /**
* ide_hwif_configure - configure an IDE interface * ide_hwif_configure - configure an IDE interface
* @dev: PCI device holding interface * @dev: PCI device holding interface
...@@ -434,16 +419,19 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, ide_pci_device_t *d, ...@@ -434,16 +419,19 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, ide_pci_device_t *d,
unsigned long ctl = 0, base = 0; unsigned long ctl = 0, base = 0;
ide_hwif_t *hwif; ide_hwif_t *hwif;
/* Possibly we should fail if these checks report true */ if(!d->isa_ports)
ide_pci_check_iomem(dev, d, 2*port); {
ide_pci_check_iomem(dev, d, 2*port+1); /* Possibly we should fail if these checks report true */
ide_pci_check_iomem(dev, d, 2*port);
ide_pci_check_iomem(dev, d, 2*port+1);
ctl = pci_resource_start(dev, 2*port+1); ctl = pci_resource_start(dev, 2*port+1);
base = pci_resource_start(dev, 2*port); base = pci_resource_start(dev, 2*port);
if ((ctl && !base) || (base && !ctl)) { if ((ctl && !base) || (base && !ctl)) {
printk(KERN_ERR "%s: inconsistent baseregs (BIOS) " printk(KERN_ERR "%s: inconsistent baseregs (BIOS) "
"for port %d, skipping\n", d->name, port); "for port %d, skipping\n", d->name, port);
return NULL; return NULL;
}
} }
if (!ctl) if (!ctl)
{ {
...@@ -500,8 +488,9 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi ...@@ -500,8 +488,9 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi
* Set up BM-DMA capability * Set up BM-DMA capability
* (PnP BIOS should have done this) * (PnP BIOS should have done this)
*/ */
if ((d->device != PCI_DEVICE_ID_CYRIX_5530_IDE) if (!((d->device == PCI_DEVICE_ID_CYRIX_5530_IDE && d->vendor == PCI_VENDOR_ID_CYRIX)
&& (d->vendor != PCI_VENDOR_ID_CYRIX)) { ||(d->device == PCI_DEVICE_ID_NS_SCx200_IDE && d->vendor == PCI_VENDOR_ID_NS)))
{
/* /*
* default DMA off if we had to * default DMA off if we had to
* configure it here * configure it here
...@@ -575,75 +564,33 @@ static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, in ...@@ -575,75 +564,33 @@ static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, in
return ret; return ret;
} }
/* /**
* ide_setup_pci_device() looks at the primary/secondary interfaces * ide_pci_setup_ports - configure ports/devices on PCI IDE
* on a PCI IDE device and, if they are enabled, prepares the IDE driver * @dev: PCI device
* for use with them. This generic code works for most PCI chipsets. * @d: IDE pci device info
* @autodma: Should we enable DMA
* @pciirq: IRQ line
* @index: ata index to update
* *
* One thing that is not standardized is the location of the * Scan the interfaces attached to this device and do any
* primary/secondary interface "enable/disable" bits. For chipsets that * neccessary per port setup. Attach the devices and ask the
* we "know" about, this information is in the ide_pci_device_t struct; * generic DMA layer to do its work for us.
* for all other chipsets, we just assume both interfaces are enabled. *
* Normally called automaticall from do_ide_pci_setup_device,
* but is also used directly as a helper function by some controllers
* where the chipset setup is not the default PCI IDE one.
*/ */
static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d, u8 noisy)
void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int autodma, int pciirq, ata_index_t *index)
{ {
u32 port, at_least_one_hwif_enabled = 0, autodma = 0; int port;
int pciirq = 0; int at_least_one_hwif_enabled = 0;
int tried_config = 0;
int drive0_tune, drive1_tune;
ata_index_t index;
u8 tmp = 0;
ide_hwif_t *hwif, *mate = NULL; ide_hwif_t *hwif, *mate = NULL;
static int secondpdc = 0; static int secondpdc = 0;
int drive0_tune, drive1_tune;
u8 tmp;
index.all = 0xf0f0; index->all = 0xf0f0;
if((autodma = ide_setup_pci_controller(dev, d, noisy, &tried_config)) < 0)
return index;
/*
* Can we trust the reported IRQ?
*/
pciirq = dev->irq;
if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
if (noisy)
printk(KERN_INFO "%s: not 100%% native mode: "
"will probe irqs later\n", d->name);
/*
* This allows offboard ide-pci cards the enable a BIOS,
* verify interrupt settings of split-mirror pci-config
* 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;
} else if (tried_config) {
if (noisy)
printk(KERN_INFO "%s: will probe irqs later\n", d->name);
pciirq = 0;
} else if (!pciirq) {
if (noisy)
printk(KERN_WARNING "%s: bad irq (%d): will probe later\n",
d->name, pciirq);
pciirq = 0;
} else {
if (d->init_chipset)
{
if(d->init_chipset(dev, d->name) < 0)
return index;
}
if (noisy)
#ifdef __sparc__
printk(KERN_INFO "%s: 100%% native mode on irq %s\n",
d->name, __irq_itoa(pciirq));
#else
printk(KERN_INFO "%s: 100%% native mode on irq %d\n",
d->name, pciirq);
#endif
}
if(pciirq < 0) /* Error not an IRQ */
return index;
/* /*
* Set up the IDE ports * Set up the IDE ports
...@@ -671,7 +618,7 @@ static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_ ...@@ -671,7 +618,7 @@ static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_
controller_ok: controller_ok:
if (d->channels <= port) if (d->channels <= port)
return index; break;
if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL) if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL)
continue; continue;
...@@ -680,25 +627,27 @@ static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_ ...@@ -680,25 +627,27 @@ static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_
hwif->gendev.parent = &dev->dev; hwif->gendev.parent = &dev->dev;
if (hwif->channel) { if (hwif->channel) {
index.b.high = hwif->index; index->b.high = hwif->index;
} else { } else {
index.b.low = hwif->index; index->b.low = hwif->index;
} }
if (d->init_iops) if (d->init_iops)
d->init_iops(hwif); d->init_iops(hwif);
#ifdef CONFIG_BLK_DEV_IDEDMA
if (d->autodma == NODMA) if (d->autodma == NODMA)
goto bypass_legacy_dma; goto bypass_legacy_dma;
if (d->autodma == NOAUTODMA) if (d->autodma == NOAUTODMA)
autodma = 0; autodma = 0;
if (autodma) if (autodma)
hwif->autodma = 1; hwif->autodma = 1;
ide_hwif_setup_dma(dev, d, hwif);
if(d->init_setup_dma)
d->init_setup_dma(dev, d, hwif);
else
ide_hwif_setup_dma(dev, d, hwif);
bypass_legacy_dma: bypass_legacy_dma:
#endif /* CONFIG_BLK_DEV_IDEDMA */
drive0_tune = hwif->drives[0].autotune; drive0_tune = hwif->drives[0].autotune;
drive1_tune = hwif->drives[1].autotune; drive1_tune = hwif->drives[1].autotune;
...@@ -708,7 +657,13 @@ static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_ ...@@ -708,7 +657,13 @@ static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_
* for each enabled hwif * for each enabled hwif
*/ */
d->init_hwif(hwif); d->init_hwif(hwif);
/*
* This is in the wrong place. The driver may
* do set up based on the autotune value and this
* will then trash it. Torben please move it and
* propogate the fixes into the drivers
*/
if (drive0_tune == IDE_TUNE_BIOS) /* biostimings */ if (drive0_tune == IDE_TUNE_BIOS) /* biostimings */
hwif->drives[0].autotune = IDE_TUNE_BIOS; hwif->drives[0].autotune = IDE_TUNE_BIOS;
if (drive1_tune == IDE_TUNE_BIOS) if (drive1_tune == IDE_TUNE_BIOS)
...@@ -719,6 +674,76 @@ static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_ ...@@ -719,6 +674,76 @@ static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_
} }
if (!at_least_one_hwif_enabled) if (!at_least_one_hwif_enabled)
printk(KERN_INFO "%s: neither IDE port enabled (BIOS)\n", d->name); printk(KERN_INFO "%s: neither IDE port enabled (BIOS)\n", d->name);
}
EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
/*
* ide_setup_pci_device() looks at the primary/secondary interfaces
* on a PCI IDE device and, if they are enabled, prepares the IDE driver
* for use with them. This generic code works for most PCI chipsets.
*
* One thing that is not standardized is the location of the
* primary/secondary interface "enable/disable" bits. For chipsets that
* 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)
{
int autodma = 0;
int pciirq = 0;
int tried_config = 0;
ata_index_t index;
if((autodma = ide_setup_pci_controller(dev, d, noisy, &tried_config)) < 0)
return index;
/*
* Can we trust the reported IRQ?
*/
pciirq = dev->irq;
if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
if (noisy)
printk(KERN_INFO "%s: not 100%% native mode: "
"will probe irqs later\n", d->name);
/*
* This allows offboard ide-pci cards the enable a BIOS,
* verify interrupt settings of split-mirror pci-config
* 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;
} else if (tried_config) {
if (noisy)
printk(KERN_INFO "%s: will probe irqs later\n", d->name);
pciirq = 0;
} else if (!pciirq) {
if (noisy)
printk(KERN_WARNING "%s: bad irq (%d): will probe later\n",
d->name, pciirq);
pciirq = 0;
} else {
if (d->init_chipset)
{
if(d->init_chipset(dev, d->name) < 0)
return index;
}
if (noisy)
#ifdef __sparc__
printk(KERN_INFO "%s: 100%% native mode on irq %s\n",
d->name, __irq_itoa(pciirq));
#else
printk(KERN_INFO "%s: 100%% native mode on irq %d\n",
d->name, pciirq);
#endif
}
if(pciirq < 0) /* Error not an IRQ */
return index;
ide_pci_setup_ports(dev, d, autodma, pciirq, &index);
return index; return index;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment