#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
+#include <linux/slab.h>
#include "pci.h"
/**
* pci_enable_rom - enable ROM decoding for a PCI device
- * @dev: PCI device to enable
+ * @pdev: PCI device to enable
*
* Enable ROM decoding on @dev. This involves simply turning on the last
* bit of the PCI ROM BAR. Note that some cards may share address decoders
* between the ROM and other resources, so enabling it may disable access
* to MMIO registers or other card memory.
*/
-static void pci_enable_rom(struct pci_dev *pdev)
+static int pci_enable_rom(struct pci_dev *pdev)
{
+ struct resource *res = pdev->resource + PCI_ROM_RESOURCE;
+ struct pci_bus_region region;
u32 rom_addr;
+ if (!res->flags)
+ return -1;
+
+ pcibios_resource_to_bus(pdev, ®ion, res);
pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
- rom_addr |= PCI_ROM_ADDRESS_ENABLE;
+ rom_addr &= ~PCI_ROM_ADDRESS_MASK;
+ rom_addr |= region.start | PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
+ return 0;
}
/**
* pci_disable_rom - disable ROM decoding for a PCI device
- * @dev: PCI device to disable
+ * @pdev: PCI device to disable
*
* Disable ROM decoding on a PCI device by turning off the last bit in the
* ROM BAR.
/**
* pci_map_rom - map a PCI ROM to kernel space
- * @dev: pointer to pci device struct
+ * @pdev: pointer to pci device struct
* @size: pointer to receive size of pci window over ROM
* @return: kernel virtual pointer to image of ROM
*
} else {
if (res->flags & IORESOURCE_ROM_COPY) {
*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
- return (void __iomem *)pci_resource_start(pdev, PCI_ROM_RESOURCE);
+ return (void __iomem *)pci_resource_start(pdev,
+ PCI_ROM_RESOURCE);
} else {
/* assign the ROM an address if it doesn't have one */
- if (res->parent == NULL)
- pci_assign_resource(pdev, PCI_ROM_RESOURCE);
-
+ if (res->parent == NULL &&
+ pci_assign_resource(pdev,PCI_ROM_RESOURCE))
+ return NULL;
start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
if (*size == 0)
return NULL;
/* Enable ROM space decodes */
- pci_enable_rom(pdev);
+ if (pci_enable_rom(pdev))
+ return NULL;
}
}
image += readw(pds + 16) * 512;
} while (!last_image);
- *size = image - rom;
+ /* never return a size larger than the PCI resource window */
+ /* there are known ROMs that get the size wrong */
+ *size = min((size_t)(image - rom), *size);
return rom;
}
/**
* pci_map_rom_copy - map a PCI ROM to kernel space, create a copy
- * @dev: pointer to pci device struct
+ * @pdev: pointer to pci device struct
* @size: pointer to receive size of pci window over ROM
* @return: kernel virtual pointer to image of ROM
*
/**
* pci_unmap_rom - unmap the ROM from kernel space
- * @dev: pointer to pci device struct
+ * @pdev: pointer to pci device struct
* @rom: virtual address of the previous mapping
*
* Remove a mapping of a previously mapped ROM
/**
* pci_remove_rom - disable the ROM and remove its sysfs attribute
- * @dev: pointer to pci device struct
+ * @pdev: pointer to pci device struct
*
* Remove the rom file in sysfs and disable ROM decoding.
*/
/**
* pci_cleanup_rom - internal routine for freeing the ROM copy created
* by pci_map_rom_copy called from remove.c
- * @dev: pointer to pci device struct
+ * @pdev: pointer to pci device struct
*
* Free the copied ROM if we allocated one.
*/