rom.c revision 761a3ac08c63718dacde12aaf0ec6d6760e8c2b7
1/* 2 * drivers/pci/rom.c 3 * 4 * (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com> 5 * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com> 6 * 7 * PCI ROM access routines 8 */ 9#include <linux/config.h> 10#include <linux/kernel.h> 11#include <linux/pci.h> 12 13#include "pci.h" 14 15/** 16 * pci_enable_rom - enable ROM decoding for a PCI device 17 * @pdev: PCI device to enable 18 * 19 * Enable ROM decoding on @dev. This involves simply turning on the last 20 * bit of the PCI ROM BAR. Note that some cards may share address decoders 21 * between the ROM and other resources, so enabling it may disable access 22 * to MMIO registers or other card memory. 23 */ 24static void pci_enable_rom(struct pci_dev *pdev) 25{ 26 u32 rom_addr; 27 28 pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr); 29 rom_addr |= PCI_ROM_ADDRESS_ENABLE; 30 pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr); 31} 32 33/** 34 * pci_disable_rom - disable ROM decoding for a PCI device 35 * @pdev: PCI device to disable 36 * 37 * Disable ROM decoding on a PCI device by turning off the last bit in the 38 * ROM BAR. 39 */ 40static void pci_disable_rom(struct pci_dev *pdev) 41{ 42 u32 rom_addr; 43 pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr); 44 rom_addr &= ~PCI_ROM_ADDRESS_ENABLE; 45 pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr); 46} 47 48/** 49 * pci_map_rom - map a PCI ROM to kernel space 50 * @pdev: pointer to pci device struct 51 * @size: pointer to receive size of pci window over ROM 52 * @return: kernel virtual pointer to image of ROM 53 * 54 * Map a PCI ROM into kernel space. If ROM is boot video ROM, 55 * the shadow BIOS copy will be returned instead of the 56 * actual ROM. 57 */ 58void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) 59{ 60 struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; 61 loff_t start; 62 void __iomem *rom; 63 void __iomem *image; 64 int last_image; 65 66 /* IORESOURCE_ROM_SHADOW only set on x86 */ 67 if (res->flags & IORESOURCE_ROM_SHADOW) { 68 /* primary video rom always starts here */ 69 start = (loff_t)0xC0000; 70 *size = 0x20000; /* cover C000:0 through E000:0 */ 71 } else { 72 if (res->flags & IORESOURCE_ROM_COPY) { 73 *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); 74 return (void __iomem *)pci_resource_start(pdev, PCI_ROM_RESOURCE); 75 } else { 76 /* assign the ROM an address if it doesn't have one */ 77 if (res->parent == NULL) 78 pci_assign_resource(pdev, PCI_ROM_RESOURCE); 79 80 start = pci_resource_start(pdev, PCI_ROM_RESOURCE); 81 *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); 82 if (*size == 0) 83 return NULL; 84 85 /* Enable ROM space decodes */ 86 pci_enable_rom(pdev); 87 } 88 } 89 90 rom = ioremap(start, *size); 91 if (!rom) { 92 /* restore enable if ioremap fails */ 93 if (!(res->flags & (IORESOURCE_ROM_ENABLE | 94 IORESOURCE_ROM_SHADOW | 95 IORESOURCE_ROM_COPY))) 96 pci_disable_rom(pdev); 97 return NULL; 98 } 99 100 /* 101 * Try to find the true size of the ROM since sometimes the PCI window 102 * size is much larger than the actual size of the ROM. 103 * True size is important if the ROM is going to be copied. 104 */ 105 image = rom; 106 do { 107 void __iomem *pds; 108 /* Standard PCI ROMs start out with these bytes 55 AA */ 109 if (readb(image) != 0x55) 110 break; 111 if (readb(image + 1) != 0xAA) 112 break; 113 /* get the PCI data structure and check its signature */ 114 pds = image + readw(image + 24); 115 if (readb(pds) != 'P') 116 break; 117 if (readb(pds + 1) != 'C') 118 break; 119 if (readb(pds + 2) != 'I') 120 break; 121 if (readb(pds + 3) != 'R') 122 break; 123 last_image = readb(pds + 21) & 0x80; 124 /* this length is reliable */ 125 image += readw(pds + 16) * 512; 126 } while (!last_image); 127 128 /* never return a size larger than the PCI resource window */ 129 /* there are known ROMs that get the size wrong */ 130 *size = min((size_t)(image - rom), *size); 131 132 return rom; 133} 134 135/** 136 * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy 137 * @pdev: pointer to pci device struct 138 * @size: pointer to receive size of pci window over ROM 139 * @return: kernel virtual pointer to image of ROM 140 * 141 * Map a PCI ROM into kernel space. If ROM is boot video ROM, 142 * the shadow BIOS copy will be returned instead of the 143 * actual ROM. 144 */ 145void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size) 146{ 147 struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; 148 void __iomem *rom; 149 150 rom = pci_map_rom(pdev, size); 151 if (!rom) 152 return NULL; 153 154 if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW)) 155 return rom; 156 157 res->start = (unsigned long)kmalloc(*size, GFP_KERNEL); 158 if (!res->start) 159 return rom; 160 161 res->end = res->start + *size; 162 memcpy_fromio((void*)res->start, rom, *size); 163 pci_unmap_rom(pdev, rom); 164 res->flags |= IORESOURCE_ROM_COPY; 165 166 return (void __iomem *)res->start; 167} 168 169/** 170 * pci_unmap_rom - unmap the ROM from kernel space 171 * @pdev: pointer to pci device struct 172 * @rom: virtual address of the previous mapping 173 * 174 * Remove a mapping of a previously mapped ROM 175 */ 176void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom) 177{ 178 struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; 179 180 if (res->flags & IORESOURCE_ROM_COPY) 181 return; 182 183 iounmap(rom); 184 185 /* Disable again before continuing, leave enabled if pci=rom */ 186 if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW))) 187 pci_disable_rom(pdev); 188} 189 190/** 191 * pci_remove_rom - disable the ROM and remove its sysfs attribute 192 * @pdev: pointer to pci device struct 193 * 194 * Remove the rom file in sysfs and disable ROM decoding. 195 */ 196void pci_remove_rom(struct pci_dev *pdev) 197{ 198 struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; 199 200 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) 201 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); 202 if (!(res->flags & (IORESOURCE_ROM_ENABLE | 203 IORESOURCE_ROM_SHADOW | 204 IORESOURCE_ROM_COPY))) 205 pci_disable_rom(pdev); 206} 207 208/** 209 * pci_cleanup_rom - internal routine for freeing the ROM copy created 210 * by pci_map_rom_copy called from remove.c 211 * @pdev: pointer to pci device struct 212 * 213 * Free the copied ROM if we allocated one. 214 */ 215void pci_cleanup_rom(struct pci_dev *pdev) 216{ 217 struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; 218 if (res->flags & IORESOURCE_ROM_COPY) { 219 kfree((void*)res->start); 220 res->flags &= ~IORESOURCE_ROM_COPY; 221 res->start = 0; 222 res->end = 0; 223 } 224} 225 226EXPORT_SYMBOL(pci_map_rom); 227EXPORT_SYMBOL(pci_map_rom_copy); 228EXPORT_SYMBOL(pci_unmap_rom); 229EXPORT_SYMBOL(pci_remove_rom); 230