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