Kill pcibios_update_resource(), replacing it with pci_update_resource().
pci_update_resource() uses pcibios_resource_to_bus() to convert a
resource to a device BAR - the transformation should be exactly the
same as the transformation used for the PCI bridges.
pci_update_resource "knows" about 64-bit BARs, but doesn't attempt to
set the high 32-bits to anything non-zero - currently no architecture
attempts to do something different. If anyone cares, please fix; I'm
going to reflect current behaviour for the time being.
Ivan pointed out the following architectures need to examine their
pcibios_update_resource() implementation - they should make sure that
this new implementation does the right thing. #warning's have been
added where appropriate.
ia64
mips
mips64
This cset also includes a fix for the problem reported by AKPM where
64-bit arch compilers complain about the resource mask being placed
in a u32.
}
}
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- struct pci_controller *hose = dev->sysdata;
- struct resource *root;
- int where;
- u32 reg;
-
- if (resource < PCI_ROM_RESOURCE)
- where = PCI_BASE_ADDRESS_0 + (resource * 4);
- else if (resource == PCI_ROM_RESOURCE)
- where = dev->rom_base_reg;
- else {
- return; /* Don't update non-standard resources here. */
- }
-
- /* Point root at the hose root. */
- if (res->flags & IORESOURCE_IO)
- root = hose->io_space;
- else if (res->flags & IORESOURCE_MEM)
- root = hose->mem_space;
- else {
- return; /* Don't update non-standard resources here. */
- }
-
- reg = (res->start - root->start) | (res->flags & 0xf);
- pci_write_config_dword(dev, where, reg);
- if ((res->flags & (PCI_BASE_ADDRESS_SPACE
- | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
- == (PCI_BASE_ADDRESS_SPACE_MEMORY
- | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
- pci_write_config_dword(dev, where+4, 0);
- printk(KERN_WARNING "PCI: dev %s type 64-bit\n", dev->dev.name);
- }
-
- /* ??? FIXME -- record old value for shutdown. */
-}
-
void __init
pcibios_update_irq(struct pci_dev *dev, int irq)
{
}, { 0 }
};
-void __devinit
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- struct pci_sys_data *sys = dev->sysdata;
- u32 val, check;
- int reg;
-
- if (debug_pci)
- printk("PCI: Assigning %3s %08lx to %s\n",
- res->flags & IORESOURCE_IO ? "IO" : "MEM",
- res->start, dev->dev.name);
-
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- reg = dev->rom_base_reg;
- } else {
- /* Somebody might have asked allocation of a
- * non-standard resource.
- */
- return;
- }
-
- val = res->start;
- if (res->flags & IORESOURCE_MEM)
- val -= sys->mem_offset;
- else
- val -= sys->io_offset;
- val |= res->flags & PCI_REGION_FLAG_MASK;
-
- pci_write_config_dword(dev, reg, val);
- pci_read_config_dword(dev, reg, &check);
- if ((val ^ check) & ((val & PCI_BASE_ADDRESS_SPACE_IO) ?
- PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name,
- resource, val, check);
- }
-}
-
void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
{
if (debug_pci)
#include "pci.h"
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- u32 new, check;
- int reg;
-
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= PCI_ROM_ADDRESS_ENABLE;
- new |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /* Somebody might have asked allocation of a non-standard resource */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
- new, check);
- }
-}
-
/*
* We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the
return;
}
-void __devinit
-pcibios_update_resource (struct pci_dev *dev, struct resource *res,
- int resource)
-{
- unsigned long where, size;
- u32 reg;
-
- where = PCI_BASE_ADDRESS_0 + (resource * 4);
- size = res->end - res->start;
- pci_read_config_dword(dev, where, ®);
- /* FIXME - this doesn't work for PCI-PCI bridges. */
- reg = (reg & size) | (((u32)(res->start - res->parent->start)) & ~size);
- pci_write_config_dword(dev, where, reg);
-
- /* ??? FIXME -- record old value for shutdown. */
-}
+#warning pcibios_update_resource() is now a generic implementation - please check
void __devinit
pcibios_update_irq (struct pci_dev *dev, int irq)
return pcibios_enable_resources(dev);
}
-void pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- u32 new, check;
- int reg;
-
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4 * resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /*
- * Somebody might have asked allocation of a non-standard
- * resource
- */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) &
- ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
- PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
- new, check);
- }
-}
-
void pcibios_align_resource(void *data, struct resource *res,
unsigned long size, unsigned long align)
{
return pcibios_enable_resources(dev);
}
-void pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- u32 new, check;
- int reg;
-
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4 * resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /*
- * Somebody might have asked allocation of a non-standard
- * resource
- */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) &
- ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
- PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
- new, check);
- }
-}
-
void pcibios_align_resource(void *data, struct resource *res,
unsigned long size, unsigned long align)
{
/* this should not be called */
MIPS_ASSERT(1 == 0);
}
-
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- /* this should not be called */
- MIPS_ASSERT(1 == 0);
-}
return pcibios_enable_resources(dev);
}
-void pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- u32 new, check;
- int reg;
-
- return;
-
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4 * resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /*
- * Somebody might have asked allocation of a non-standard
- * resource
- */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) &
- ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
- PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
- new, check);
- }
-}
-
void pcibios_align_resource(void *data, struct resource *res,
unsigned long size, unsigned long align)
{
return str;
}
-void __init
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- unsigned long where, size;
- u32 reg;
-
- where = PCI_BASE_ADDRESS_0 + (resource * 4);
- size = res->end - res->start;
- pci_read_config_dword(dev, where, ®);
- /* FIXME - this doesn't work for PCI-PCI bridges. */
- reg = (reg & size) | (((u32)(res->start - res->parent->start)) & ~size);
- pci_write_config_dword(dev, where, reg);
-}
+#warning pcibios_update_resource() is now a generic implementation - please check
void __init pcibios_fixup_bus(struct pci_bus *b)
{
{
/* this should not be called */
}
-
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- /* this should not be called */
-}
{ 0 }
};
-void __init
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- unsigned long where, size;
- u32 reg;
-
- where = PCI_BASE_ADDRESS_0 + (resource * 4);
- size = res->end - res->start;
- pci_read_config_dword(dev, where, ®);
- /* FIXME - this doesn't work for PCI-PCI bridges. */
- reg = (reg & size) | (((u32)(res->start - res->parent->start)) & ~size);
- pci_write_config_dword(dev, where, reg);
-}
+#warning pcibios_update_resource() is now a generic implementation - please check
/*
* Called after each bus is probed, but before its children
{
}
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- u32 new, check;
- int reg;
-
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= PCI_ROM_ADDRESS_ENABLE;
- new |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /* Somebody might have asked allocation of a non-standard resource */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
- new, check);
- }
-}
-
void __init pcibios_init(void)
{
struct pci_ops *ops = &sni_pci_ops;
{ 0 }
};
-void __init
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- unsigned long where, size;
- u32 reg;
-
- where = PCI_BASE_ADDRESS_0 + (resource * 4);
- size = res->end - res->start;
- pci_read_config_dword(dev, where, ®);
- /* FIXME - this doesn't work for PCI-PCI bridges. */
- reg = (reg & size) | (((u32)(res->start - res->parent->start)) & ~size);
- pci_write_config_dword(dev, where, reg);
-}
+#warning pcibios_update_resource() is now a generic implementation - please check
unsigned __init int pcibios_assign_all_busses(void)
{
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
-void __init
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- unsigned long where, size;
- u32 reg;
-
- where = PCI_BASE_ADDRESS_0 + (resource * 4);
- size = res->end - res->start;
- pci_read_config_dword(dev, where, ®);
- /* FIXME - this doesn't work for PCI-PCI bridges. */
- reg = (reg & size) | (((u32)(res->start - res->parent->start)) & ~size);
- pci_write_config_dword(dev, where, reg);
-}
+#warning pcibios_update_resource() is now a generic implementation - please check
void __init
pcibios_fixup_bus(struct pci_bus *b)
{
}
-void __init pcibios_update_resource (struct pci_dev *dev, struct resource *res,
- int resource)
-{
-}
-
void __init pcibios_update_irq (struct pci_dev *dev, int irq)
{
pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);
}
-/* ------------------------------------
-**
-** Program one BAR in PCI config space.
-**
-** ------------------------------------
-** PAT PDC systems need this routine. PA legacy PDC does not.
-**
-** When BAR's are configured by linux, this routine will update
-** configuration space with the "normalized" address. "root" indicates
-** where the range starts and res is some portion of that range.
-**
-** VCLASS: For all PA-RISC systems except V-class, root->start would be zero.
-**
-** PAT PDC can tell us which MMIO ranges are available or already in use.
-** I/O port space and such are not memory mapped anyway for PA-Risc.
-*/
-void __devinit
-pcibios_update_resource(
- struct pci_dev *dev,
- struct resource *res,
- int barnum
- )
-{
- int where;
- u32 barval = 0;
-
- DBG_RES("pcibios_update_resource(%s, ..., %d) [%lx,%lx]/%x\n",
- dev->slot_name,
- barnum, res->start, res->end, (int) res->flags);
-
- if (barnum >= PCI_BRIDGE_RESOURCES) {
- /* handled in PCI-PCI bridge specific support */
- return;
- }
-
- if (barnum == PCI_ROM_RESOURCE) {
- where = PCI_ROM_ADDRESS;
- } else {
- /* 0-5 standard PCI "regions" */
- where = PCI_BASE_ADDRESS_0 + (barnum * 4);
- }
-
- if (res->flags & IORESOURCE_IO) {
- barval = PCI_PORT_ADDR(res->start);
- } else if (res->flags & IORESOURCE_MEM) {
- barval = PCI_BUS_ADDR(HBA_DATA(dev->bus->dev->platform_data), res->start);
- } else {
- panic("pcibios_update_resource() WTF? flags not IO or MEM");
- }
-
- pci_write_config_dword(dev, where, barval);
-
-/* XXX FIXME - Elroy does support 64-bit (dual cycle) addressing.
-** But at least one device (Symbios 53c896) which has 64-bit BAR
-** doesn't actually work right with dual cycle addresses.
-** So ignore the whole mess for now.
-*/
-
- if ((res->flags & (PCI_BASE_ADDRESS_SPACE
- | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
- == (PCI_BASE_ADDRESS_SPACE_MEMORY
- | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
- pci_write_config_dword(dev, where+4, 0);
- DBGC("PCIBIOS: dev %s type 64-bit\n", dev->name);
- }
-}
-
/*
** Called by pci_set_master() - a driver interface.
**
}
}
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- u32 new, check;
- int reg;
- struct pci_controller* hose = dev->sysdata;
- unsigned long io_offset;
-
- new = res->start;
- res->flags &= ~IORESOURCE_UNSET;
- if (hose && res->flags & IORESOURCE_IO) {
- io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
- new -= io_offset;
- }
- if (hose && res->flags & IORESOURCE_MEM)
- new -= hose->pci_mem_offset;
- new |= (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /* Somebody might have asked allocation of a non-standard resource */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
- new, check);
- }
- printk(KERN_INFO "PCI: moved device %s resource %d (%lx) to %x\n",
- dev->slot_name, resource, res->flags,
- new & ~PCI_REGION_FLAG_MASK);
-}
-
static void
pcibios_fixup_resources(struct pci_dev *dev)
{
return NULL;
}
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- u32 new, check;
- int reg;
- struct pci_controller* hose = PCI_GET_PHB_PTR(dev);
-
- new = res->start;
- if (hose && res->flags & IORESOURCE_MEM)
- new -= hose->pci_mem_offset;
- new |= (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /* Somebody might have asked allocation of a non-standard resource */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
- new, check);
- }
-}
-
static void
pcibios_fixup_resources(struct pci_dev* dev)
{
* This is GPL'd.
*
* Provided here are generic versions of:
- * pcibios_update_resource()
* pcibios_align_resource()
* pcibios_enable_device()
* pcibios_set_master()
#include <linux/pci.h>
#include <linux/init.h>
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- u32 new, check;
- int reg;
-
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= PCI_ROM_ADDRESS_ENABLE;
- new |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /* Somebody might have asked allocation of a non-standard resource */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
- new, check);
- }
-}
-
/*
* We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the
return str;
}
-/*
- */
-void pcibios_update_resource(struct pci_dev *pdev, struct resource *res,
- int index)
-{
-}
-
void pcibios_align_resource(void *data, struct resource *res,
unsigned long size, unsigned long align)
{
return err;
}
-void pcibios_update_resource(struct pci_dev *pdev, struct resource *res,
- int index)
-{
-}
-
void pcibios_update_irq(struct pci_dev *pdev, int irq)
{
}
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
- struct pbus_set_ranges_data *pranges)
-{
-}
-
void pcibios_align_resource(void *data, struct resource *res,
unsigned long size, unsigned long align)
{
pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);
}
-void __nomods_init
-pcibios_update_resource (struct pci_dev *dev, struct resource *r, int resource)
+void __devinit
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
{
- u32 new, check;
- int reg;
-
- if (r->flags & IORESOURCE_IO)
- new = (((r->start - MB_A_PCI_IO_ADDR)
- & PCI_BASE_ADDRESS_IO_MASK)
- | PCI_BASE_ADDRESS_SPACE_IO);
- else if (r->flags & IORESOURCE_MEM)
- new = (((r->start - MB_A_PCI_MEM_ADDR)
- & PCI_BASE_ADDRESS_MEM_MASK)
- | PCI_BASE_ADDRESS_MEM_TYPE_32
- | ((r->flags & IORESOURCE_PREFETCH)
- ? PCI_BASE_ADDRESS_MEM_PREFETCH
- : 0)
- | PCI_BASE_ADDRESS_SPACE_MEMORY);
- else
- panic ("pcibios_update_resource: unknown resource type");
-
- if (resource < 6)
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- else if (resource == PCI_ROM_RESOURCE) {
- r->flags |= PCI_ROM_ADDRESS_ENABLE;
- new |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else
- return;
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk (KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
- new, check);
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO) {
+ offset = MB_A_PCI_IO_ADDR;
+ } else if (res->flags & IORESOURCE_MEM) {
+ offset = MB_A_PCI_MEM_ADDR;
}
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
}
\f
#include "pci.h"
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *res,
- int resource)
-{
- u32 new, check;
- int reg;
-
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= PCI_ROM_ADDRESS_ENABLE;
- new |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /* Somebody might have asked allocation of a non-standard resource */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
- new, check);
- }
-}
-
/*
* We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the
#endif
+static void
+pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
+{
+ struct pci_bus_region region;
+ u32 new, check, mask;
+ int reg;
+
+ pcibios_resource_to_bus(dev, ®ion, res);
+
+ DBGC((KERN_ERR " got res [%lx:%lx] bus [%lx:%lx] for "
+ "resource %d of %s\n", res->start, res->end,
+ region.start, region.end, resno, dev->dev.name));
+
+ new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
+ if (res->flags & IORESOURCE_IO)
+ mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
+ else
+ mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
+
+ if (resno < 6) {
+ reg = PCI_BASE_ADDRESS_0 + 4 * resno;
+ } else if (resno == PCI_ROM_RESOURCE) {
+ new |= res->flags & PCI_ROM_ADDRESS_ENABLE;
+ reg = dev->rom_base_reg;
+ } else {
+ /* Hmm, non-standard resource. */
+ printk("PCI: trying to set non-standard region %s/%d\n",
+ dev->slot_name, resno);
+ return;
+ }
+
+ pci_write_config_dword(dev, reg, new);
+ pci_read_config_dword(dev, reg, &check);
+
+ if ((new ^ check) & mask) {
+ printk(KERN_ERR "PCI: Error while updating region "
+ "%s/%d (%08x != %08x)\n", dev->slot_name, resno,
+ new, check);
+ }
+
+ if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
+ (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+ new = 0; /* currently everyone zeros the high address */
+ pci_write_config_dword(dev, reg + 4, new);
+ pci_read_config_dword(dev, reg + 4, &check);
+ if (check != new) {
+ printk(KERN_ERR "PCI: Error updating region "
+ "%s/%d (high %08x != %08x)\n",
+ dev->slot_name, resno, new, check);
+ }
+ }
+}
+
int __init
pci_claim_resource(struct pci_dev *dev, int resource)
{
printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
resno, res->start, res->end, dev->slot_name);
} else {
- DBGC((KERN_ERR " got res[%lx:%lx] for resource %d of %s\n",
- res->start, res->end, resno, dev->dev.name));
- /* Update PCI config space. */
- pcibios_update_resource(dev, res, resno);
+ pci_update_resource(dev, res, resno);
}
return ret;
/* Used only when drivers/pci/setup.c is used */
void pcibios_align_resource(void *, struct resource *,
unsigned long, unsigned long);
-void pcibios_update_resource(struct pci_dev *, struct resource *, int);
void pcibios_update_irq(struct pci_dev *, int irq);
/* Generic PCI functions used internally */