@@ -20,6 +20,7 @@ static void pci_bios_init_device_in_bus(int bus);
static u32 pci_bios_io_addr;
static u32 pci_bios_mem_addr;
static u32 pci_bios_prefmem_addr;
+static u64 pci_bios_64bit_addr;
/* host irqs corresponding to PCI irqs A-D */
const u8 pci_irqs[4] = {
10, 10, 11, 11
@@ -56,9 +57,11 @@ static int pci_bios_allocate_region(u16 bdf, int region_num)
{
u32 *paddr;
u32 ofs = pci_bar(bdf, region_num);
-
u32 old = pci_config_readl(bdf, ofs);
u32 mask;
+ u32 limit_addr;
+ int is_64bit;
+
if (region_num == PCI_ROM_SLOT) {
mask = PCI_ROM_ADDRESS_MASK;
pci_config_writel(bdf, ofs, mask);
@@ -73,50 +76,49 @@ static int pci_bios_allocate_region(u16 bdf, int region_num)
pci_config_writel(bdf, ofs, old);
u32 size = (~(val & mask)) + 1;
- if (val != 0) {
- if (val & PCI_BASE_ADDRESS_SPACE_IO) {
- paddr = &pci_bios_io_addr;
- if (ALIGN(*paddr, size) + size >= 64 * 1024) {
- dprintf(1,
- "io region of (bdf 0x%x bar %d) can't be mapped.\n",
- bdf, region_num);
- size = 0;
- }
- } else if ((val & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
- /* keep behaviour on bus = 0 */
- pci_bdf_to_bus(bdf) != 0 &&
- /* If pci_bios_prefmem_addr == 0, keep old behaviour */
- pci_bios_prefmem_addr != 0) {
- paddr = &pci_bios_prefmem_addr;
- if (ALIGN(*paddr, size) + size >= BUILD_PCIPREFMEM_END) {
- dprintf(1,
- "prefmem region of (bdf 0x%x bar %d) can't be mapped. "
- "decrease BUILD_PCIMEM_SIZE and recompile. size %x\n",
- bdf, region_num, BUILD_PCIPREFMEM_SIZE);
- size = 0;
- }
- } else {
- paddr = &pci_bios_mem_addr;
- if (ALIGN(*paddr, size) + size >= BUILD_PCIMEM_END) {
+ if (!val || !size)
+ return 0;
+
+ is_64bit = !(val & PCI_BASE_ADDRESS_SPACE_IO) &&
+ (val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64;
+
+ if (val & PCI_BASE_ADDRESS_SPACE_IO) {
+ paddr = &pci_bios_io_addr;
+ limit_addr = 64 * 1024;
+ } else if ((val & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
+ /* keep behaviour on bus = 0 */
+ pci_bdf_to_bus(bdf) != 0 &&
+ /* If pci_bios_prefmem_addr == 0, keep old behaviour */
+ pci_bios_prefmem_addr != 0) {
+ paddr = &pci_bios_prefmem_addr;
+ limit_addr = BUILD_PCIPREFMEM_END;
+ } else {
+ paddr = &pci_bios_mem_addr;
+ limit_addr = BUILD_PCIMEM_END;
+ }
+
+ /* The region is out of allowed 32bit mapping range */
+ if ((ALIGN(*paddr, size) + size >= limit_addr) ||
+ (ALIGN(*paddr, size) + size <= *paddr)) {
+ if (!is_64bit) {
dprintf(1,
"mem region of (bdf 0x%x bar %d) can't be mapped. "
- "increase BUILD_PCIMEM_SIZE and recompile. size %x\n",
- bdf, region_num, BUILD_PCIMEM_SIZE);
- size = 0;
+ "Region size %x\n", bdf, region_num, size);
+ return 0;
}
- }
- if (size > 0) {
- *paddr = ALIGN(*paddr, size);
- pci_set_io_region_addr(bdf, region_num, *paddr);
- *paddr += size;
- }
+ pci_bios_64bit_addr = ALIGN(pci_bios_64bit_addr, size);
+ pci_set_io_region_addr(bdf, region_num, (u32)pci_bios_64bit_addr);
+ pci_set_io_region_addr(bdf, region_num + 1,
+ (u32)(pci_bios_64bit_addr >> 32));
+ pci_bios_64bit_addr += size;
+ return is_64bit;
}
- int is_64bit = !(val & PCI_BASE_ADDRESS_SPACE_IO) &&
- (val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64;
- if (is_64bit && size > 0) {
- pci_config_writel(bdf, ofs + 4, 0);
- }
+ *paddr = ALIGN(*paddr, size);
+ pci_set_io_region_addr(bdf, region_num, *paddr);
+ if (is_64bit)
+ pci_set_io_region_addr(bdf, region_num + 1, 0);
+ *paddr += size;
return is_64bit;
}
@@ -409,6 +411,7 @@ pci_setup(void)
pci_bios_io_addr = 0xc000;
pci_bios_mem_addr = BUILD_PCIMEM_START;
pci_bios_prefmem_addr = BUILD_PCIPREFMEM_START;
+ pci_bios_64bit_addr = ALIGN(RamSizeOver4G + 0x100000000ull, 0x100000000ull);
pci_bios_init_bus();