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 * @dev: 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 */ 24 static 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 * @dev: 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 */ 40 static 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 * @dev: 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 */ 58 void __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 *size = image - rom; 129 130 return rom; 131 } 132 133 /** 134 * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy 135 * @dev: pointer to pci device struct 136 * @size: pointer to receive size of pci window over ROM 137 * @return: kernel virtual pointer to image of ROM 138 * 139 * Map a PCI ROM into kernel space. If ROM is boot video ROM, 140 * the shadow BIOS copy will be returned instead of the 141 * actual ROM. 142 */ 143 void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size) 144 { 145 struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; 146 void __iomem *rom; 147 148 rom = pci_map_rom(pdev, size); 149 if (!rom) 150 return NULL; 151 152 if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW)) 153 return rom; 154 155 res->start = (unsigned long)kmalloc(*size, GFP_KERNEL); 156 if (!res->start) 157 return rom; 158 159 res->end = res->start + *size; 160 memcpy_fromio((void*)res->start, rom, *size); 161 pci_unmap_rom(pdev, rom); 162 res->flags |= IORESOURCE_ROM_COPY; 163 164 return (void __iomem *)res->start; 165 } 166 167 /** 168 * pci_unmap_rom - unmap the ROM from kernel space 169 * @dev: pointer to pci device struct 170 * @rom: virtual address of the previous mapping 171 * 172 * Remove a mapping of a previously mapped ROM 173 */ 174 void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom) 175 { 176 struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; 177 178 if (res->flags & IORESOURCE_ROM_COPY) 179 return; 180 181 iounmap(rom); 182 183 /* Disable again before continuing, leave enabled if pci=rom */ 184 if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW))) 185 pci_disable_rom(pdev); 186 } 187 188 /** 189 * pci_remove_rom - disable the ROM and remove its sysfs attribute 190 * @dev: pointer to pci device struct 191 * 192 * Remove the rom file in sysfs and disable ROM decoding. 193 */ 194 void pci_remove_rom(struct pci_dev *pdev) 195 { 196 struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; 197 198 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) 199 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); 200 if (!(res->flags & (IORESOURCE_ROM_ENABLE | 201 IORESOURCE_ROM_SHADOW | 202 IORESOURCE_ROM_COPY))) 203 pci_disable_rom(pdev); 204 } 205 206 /** 207 * pci_cleanup_rom - internal routine for freeing the ROM copy created 208 * by pci_map_rom_copy called from remove.c 209 * @dev: pointer to pci device struct 210 * 211 * Free the copied ROM if we allocated one. 212 */ 213 void pci_cleanup_rom(struct pci_dev *pdev) 214 { 215 struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; 216 if (res->flags & IORESOURCE_ROM_COPY) { 217 kfree((void*)res->start); 218 res->flags &= ~IORESOURCE_ROM_COPY; 219 res->start = 0; 220 res->end = 0; 221 } 222 } 223 224 EXPORT_SYMBOL(pci_map_rom); 225 EXPORT_SYMBOL(pci_map_rom_copy); 226 EXPORT_SYMBOL(pci_unmap_rom); 227 EXPORT_SYMBOL(pci_remove_rom); 228