Rev 2326 | Rev 2351 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2326 | Rev 2327 | ||
---|---|---|---|
Line 661... | Line 661... | ||
661 | { |
661 | { |
662 | IO_COND(addr, /* nothing */, iounmap(addr)); |
662 | IO_COND(addr, /* nothing */, iounmap(addr)); |
663 | }>=>>>><>><>><>>4)><4)> |
663 | } |
664 | 664 | ||
Line -... | Line 665... | ||
- | 665 | ||
- | 666 | struct pci_bus_region { |
|
- | 667 | resource_size_t start; |
|
- | 668 | resource_size_t end; |
|
- | 669 | }; |
|
- | 670 | ||
- | 671 | static inline void |
|
- | 672 | pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, |
|
- | 673 | struct resource *res) |
|
- | 674 | { |
|
- | 675 | region->start = res->start; |
|
- | 676 | region->end = res->end; |
|
- | 677 | } |
|
- | 678 | ||
- | 679 | static inline int pci_read_config_dword(struct pci_dev *dev, int where, |
|
- | 680 | u32 *val) |
|
- | 681 | { |
|
- | 682 | *val = PciRead32(dev->busnr, dev->devfn, where); |
|
- | 683 | return 1; |
|
- | 684 | } |
|
- | 685 | ||
- | 686 | static inline int pci_write_config_dword(struct pci_dev *dev, int where, |
|
- | 687 | u32 val) |
|
- | 688 | { |
|
- | 689 | PciWrite32(dev->busnr, dev->devfn, where, val); |
|
- | 690 | return 1; |
|
- | 691 | } |
|
- | 692 | ||
- | 693 | int pci_enable_rom(struct pci_dev *pdev) |
|
- | 694 | { |
|
- | 695 | struct resource *res = pdev->resource + PCI_ROM_RESOURCE; |
|
- | 696 | struct pci_bus_region region; |
|
- | 697 | u32 rom_addr; |
|
- | 698 | ||
- | 699 | if (!res->flags) |
|
- | 700 | return -1; |
|
- | 701 | ||
- | 702 | pcibios_resource_to_bus(pdev, ®ion, res); |
|
- | 703 | pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr); |
|
- | 704 | rom_addr &= ~PCI_ROM_ADDRESS_MASK; |
|
- | 705 | rom_addr |= region.start | PCI_ROM_ADDRESS_ENABLE; |
|
- | 706 | pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr); |
|
- | 707 | return 0; |
|
- | 708 | } |
|
- | 709 | ||
- | 710 | void pci_disable_rom(struct pci_dev *pdev) |
|
- | 711 | { |
|
- | 712 | u32 rom_addr; |
|
- | 713 | pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr); |
|
- | 714 | rom_addr &= ~PCI_ROM_ADDRESS_ENABLE; |
|
- | 715 | pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr); |
|
- | 716 | } |
|
- | 717 | ||
- | 718 | /** |
|
- | 719 | * pci_get_rom_size - obtain the actual size of the ROM image |
|
- | 720 | * @pdev: target PCI device |
|
- | 721 | * @rom: kernel virtual pointer to image of ROM |
|
- | 722 | * @size: size of PCI window |
|
- | 723 | * return: size of actual ROM image |
|
- | 724 | * |
|
- | 725 | * Determine the actual length of the ROM image. |
|
- | 726 | * The PCI window size could be much larger than the |
|
- | 727 | * actual image size. |
|
- | 728 | */ |
|
- | 729 | size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size) |
|
- | 730 | { |
|
- | 731 | void __iomem *image; |
|
- | 732 | int last_image; |
|
- | 733 | ||
- | 734 | image = rom; |
|
- | 735 | do { |
|
- | 736 | void __iomem *pds; |
|
- | 737 | /* Standard PCI ROMs start out with these bytes 55 AA */ |
|
- | 738 | if (readb(image) != 0x55) { |
|
- | 739 | dev_err(&pdev->dev, "Invalid ROM contents\n"); |
|
- | 740 | break; |
|
- | 741 | } |
|
- | 742 | if (readb(image + 1) != 0xAA) |
|
- | 743 | break; |
|
- | 744 | /* get the PCI data structure and check its signature */ |
|
- | 745 | pds = image + readw(image + 24); |
|
- | 746 | if (readb(pds) != 'P') |
|
- | 747 | break; |
|
- | 748 | if (readb(pds + 1) != 'C') |
|
- | 749 | break; |
|
- | 750 | if (readb(pds + 2) != 'I') |
|
- | 751 | break; |
|
- | 752 | if (readb(pds + 3) != 'R') |
|
- | 753 | break; |
|
- | 754 | last_image = readb(pds + 21) & 0x80; |
|
- | 755 | /* this length is reliable */ |
|
- | 756 | image += readw(pds + 16) * 512; |
|
- | 757 | } while (!last_image); |
|
- | 758 | ||
- | 759 | /* never return a size larger than the PCI resource window */ |
|
- | 760 | /* there are known ROMs that get the size wrong */ |
|
- | 761 | return min((size_t)(image - rom), size); |
|
- | 762 | } |
|
- | 763 | ||
- | 764 | ||
- | 765 | /** |
|
- | 766 | * pci_map_rom - map a PCI ROM to kernel space |
|
- | 767 | * @pdev: pointer to pci device struct |
|
- | 768 | * @size: pointer to receive size of pci window over ROM |
|
- | 769 | * |
|
- | 770 | * Return: kernel virtual pointer to image of ROM |
|
- | 771 | * |
|
- | 772 | * Map a PCI ROM into kernel space. If ROM is boot video ROM, |
|
- | 773 | * the shadow BIOS copy will be returned instead of the |
|
- | 774 | * actual ROM. |
|
- | 775 | */ |
|
- | 776 | void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) |
|
- | 777 | { |
|
- | 778 | struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; |
|
- | 779 | loff_t start; |
|
- | 780 | void __iomem *rom; |
|
- | 781 | ||
- | 782 | /* |
|
- | 783 | * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy |
|
- | 784 | * memory map if the VGA enable bit of the Bridge Control register is |
|
- | 785 | * set for embedded VGA. |
|
- | 786 | */ |
|
- | 787 | if (res->flags & IORESOURCE_ROM_SHADOW) { |
|
- | 788 | /* primary video rom always starts here */ |
|
- | 789 | start = (loff_t)0xC0000; |
|
- | 790 | *size = 0x20000; /* cover C000:0 through E000:0 */ |
|
- | 791 | } else { |
|
- | 792 | if (res->flags & |
|
- | 793 | (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) { |
|
- | 794 | *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); |
|
- | 795 | return (void __iomem *)(unsigned long) |
|
- | 796 | pci_resource_start(pdev, PCI_ROM_RESOURCE); |
|
- | 797 | } else { |
|
- | 798 | /* assign the ROM an address if it doesn't have one */ |
|
- | 799 | // if (res->parent == NULL && |
|
- | 800 | // pci_assign_resource(pdev,PCI_ROM_RESOURCE)) |
|
- | 801 | return NULL; |
|
- | 802 | // start = pci_resource_start(pdev, PCI_ROM_RESOURCE); |
|
- | 803 | // *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); |
|
- | 804 | // if (*size == 0) |
|
- | 805 | // return NULL; |
|
- | 806 | ||
- | 807 | /* Enable ROM space decodes */ |
|
- | 808 | // if (pci_enable_rom(pdev)) |
|
- | 809 | // return NULL; |
|
- | 810 | } |
|
- | 811 | } |
|
- | 812 | ||
- | 813 | rom = ioremap(start, *size); |
|
- | 814 | if (!rom) { |
|
- | 815 | /* restore enable if ioremap fails */ |
|
- | 816 | if (!(res->flags & (IORESOURCE_ROM_ENABLE | |
|
- | 817 | IORESOURCE_ROM_SHADOW | |
|
- | 818 | IORESOURCE_ROM_COPY))) |
|
- | 819 | pci_disable_rom(pdev); |
|
- | 820 | return NULL; |
|
- | 821 | } |
|
- | 822 | ||
- | 823 | /* |
|
- | 824 | * Try to find the true size of the ROM since sometimes the PCI window |
|
- | 825 | * size is much larger than the actual size of the ROM. |
|
- | 826 | * True size is important if the ROM is going to be copied. |
|
- | 827 | */ |
|
- | 828 | *size = pci_get_rom_size(pdev, rom, *size); |
|
- | 829 | return rom; |
|
- | 830 | } |
|
- | 831 | ||
- | 832 | void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom) |
|
- | 833 | { |
|
- | 834 | struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; |
|
- | 835 | ||
- | 836 | if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) |
|
- | 837 | return; |
|
- | 838 | ||
- | 839 | iounmap(rom); |
|
- | 840 | ||
- | 841 | /* Disable again before continuing, leave enabled if pci=rom */ |
|
- | 842 | if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW))) |
|
- | 843 | pci_disable_rom(pdev); |
|
- | 844 | }>=>>>><>><>><>>4)><4)> |
|
- | 845 |