[SeaBIOS] [PATCH] pciinit: make pci ressources configurable

Gerd Hoffmann kraxel at redhat.com
Mon May 7 14:51:35 CEST 2012


Using kevins ssdt approach.

Also trying to address the winxp issue by only adding the 64bit window
to the _crs in case we actually have mapped pci bars high.  That bit
doesn't work though, the "LEqual(QW2, 0x00)" expression seems to never
evaluate to true for some reason.  Ideas anyone?

---
 src/acpi-dsdt.dsl |   47 ++++++++++++++++++++++++++++++++++++++++++++---
 src/acpi.c        |   25 ++++++++++++++++++++++++-
 src/pci.h         |    2 ++
 src/pciinit.c     |   22 +++++++++++++++++-----
 4 files changed, 87 insertions(+), 9 deletions(-)

diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl
index 227e4a3..17d6d87 100644
--- a/src/acpi-dsdt.dsl
+++ b/src/acpi-dsdt.dsl
@@ -132,7 +132,7 @@ DefinitionBlock (
                 B0EJ, 32,
             }
 
-            Name (_CRS, ResourceTemplate ()
+            Name (CRES, ResourceTemplate ()
             {
                 WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
                     0x0000,             // Address Space Granularity
@@ -174,15 +174,56 @@ DefinitionBlock (
                     0xFEBFFFFF,         // Address Range Maximum
                     0x00000000,         // Address Translation Offset
                     0x1EC00000,         // Address Length
-                    ,, , AddressRangeMemory, TypeStatic)
+                    ,, PW32, AddressRangeMemory, TypeStatic)
+            })
+            Name (CR64, ResourceTemplate ()
+            {
                 QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                     0x00000000,          // Address Space Granularity
                     0x8000000000,        // Address Range Minimum
                     0xFFFFFFFFFF,        // Address Range Maximum
                     0x00000000,          // Address Translation Offset
                     0x8000000000,        // Address Length
-                    ,, , AddressRangeMemory, TypeStatic)
+                    ,, PW64, AddressRangeMemory, TypeStatic)
             })
+            Method (_CRS, 0)
+            {
+                External (\_SB.BDAT)
+                Field(\_SB.BDAT, QWordAcc, NoLock, Preserve) {
+                    QW0, 64,
+                    QW1, 64,
+                    QW2, 64,
+                    QW3, 64,
+                }
+
+                /* fixup 32bit pci io window */
+		CreateDWordField (CRES,\_SB.PCI0.PW32._MIN, PS32)
+		CreateDWordField (CRES,\_SB.PCI0.PW32._MAX, PE32)
+		CreateDWordField (CRES,\_SB.PCI0.PW32._LEN, PL32)
+		Store (QW0, PS32)
+		Store (QW1, PE32)
+		Subtract (QW1, QW0, PL32)
+
+		If (LEqual(QW2, 0x00)) {
+		    DBUG("PCI0 _CRS: 32bit only")
+		    Return (CRES)
+		} Else {
+		    DBUG("PCI0 _CRS: add 64bit window")
+		    DBUG(QW2)
+		    DBUG(QW3)
+
+		    /* fixup and add 64bit pci io window */
+		    CreateQWordField (CR64,\_SB.PCI0.PW64._MIN, PS64)
+		    CreateQWordField (CR64,\_SB.PCI0.PW64._MAX, PE64)
+		    CreateQWordField (CR64,\_SB.PCI0.PW64._LEN, PL64)
+		    Store (QW2, PS64)
+		    Store (QW3, PE64)
+		    Subtract (QW3, QW2, PL64)
+
+		    ConcatenateResTemplate (CRES, CR64, Local0)
+		    Return (Local0)
+		}
+            }
         }
     }
 
diff --git a/src/acpi.c b/src/acpi.c
index 30888b9..930924c 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -415,7 +415,8 @@ build_ssdt(void)
     int length = ((1+3+4)
                   + (acpi_cpus * SD_SIZEOF)
                   + (1+2+5+(12*acpi_cpus))
-                  + (6+2+1+(1*acpi_cpus)));
+                  + (6+2+1+(1*acpi_cpus))
+                  + 17);
     u8 *ssdt = malloc_high(sizeof(struct acpi_table_header) + length);
     if (! ssdt) {
         warn_noalloc();
@@ -477,6 +478,28 @@ build_ssdt(void)
     for (i=0; i<acpi_cpus; i++)
         *(ssdt_ptr++) = (i < CountCPUs) ? 0x01 : 0x00;
 
+    // store pci io windows
+    u64 *pcimem = malloc_high(sizeof(*pcimem) * 4);
+    pcimem[0] = pcimem_start;
+    pcimem[1] = pcimem_end - 1;
+    pcimem[2] = pcimem64_start;
+    pcimem[3] = pcimem64_end - 1;
+
+    // build "OperationRegion(BDAT, SystemMemory, 0x12345678, 0x87654321)"
+    *(ssdt_ptr++) = 0x5B; // ExtOpPrefix
+    *(ssdt_ptr++) = 0x80; // OpRegionOp
+    *(ssdt_ptr++) = 'B';
+    *(ssdt_ptr++) = 'D';
+    *(ssdt_ptr++) = 'A';
+    *(ssdt_ptr++) = 'T';
+    *(ssdt_ptr++) = 0x00; // SystemMemory
+    *(ssdt_ptr++) = 0x0C; // DWordPrefix
+    *(u32*)ssdt_ptr = (u32)pcimem;
+    ssdt_ptr += 4;
+    *(ssdt_ptr++) = 0x0C; // DWordPrefix
+    *(u32*)ssdt_ptr = sizeof(*pcimem)*4;
+    ssdt_ptr += 4;
+
     build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
 
     //hexdump(ssdt, ssdt_ptr - ssdt);
diff --git a/src/pci.h b/src/pci.h
index 6be838c..ebf934c 100644
--- a/src/pci.h
+++ b/src/pci.h
@@ -56,6 +56,8 @@ struct pci_device {
     // Local information on device.
     int have_driver;
 };
+extern u64 pcimem_start, pcimem_end;
+extern u64 pcimem64_start, pcimem64_end;
 extern struct pci_device *PCIDevices;
 extern int MaxPCIBus;
 int pci_probe_host(void);
diff --git a/src/pciinit.c b/src/pciinit.c
index 8374603..b85d45e 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -29,6 +29,11 @@ static const char *region_type_name[] = {
     [ PCI_REGION_TYPE_PREFMEM ] = "prefmem",
 };
 
+u64 pcimem_start   = BUILD_PCIMEM_START;
+u64 pcimem_end     = BUILD_PCIMEM_END;
+u64 pcimem64_start = BUILD_PCIMEM64_START;
+u64 pcimem64_end   = BUILD_PCIMEM64_END;
+
 struct pci_region_entry {
     struct pci_device *dev;
     int bar;
@@ -517,13 +522,13 @@ static int pci_bios_init_root_regions(struct pci_bus *bus)
     }
     u64 sum = pci_region_sum(r_end);
     u64 align = pci_region_align(r_end);
-    r_end->base = ALIGN_DOWN((BUILD_PCIMEM_END - sum), align);
+    r_end->base = ALIGN_DOWN((pcimem_end - sum), align);
     sum = pci_region_sum(r_start);
     align = pci_region_align(r_start);
     r_start->base = ALIGN_DOWN((r_end->base - sum), align);
 
-    if ((r_start->base < BUILD_PCIMEM_START) ||
-         (r_start->base > BUILD_PCIMEM_END))
+    if ((r_start->base < pcimem_start) ||
+         (r_start->base > pcimem_end))
         // Memory range requested is larger than available.
         return -1;
     return 0;
@@ -601,14 +606,17 @@ static void pci_bios_map_devices(struct pci_bus *busses)
         if (pci_bios_init_root_regions(busses))
             panic("PCI: out of 32bit address space\n");
 
-        r64_mem.base = BUILD_PCIMEM64_START;
+        r64_mem.base = pcimem64_start;
         u64 sum = pci_region_sum(&r64_mem);
         u64 align = pci_region_align(&r64_pref);
         r64_pref.base = ALIGN(r64_mem.base + sum, align);
-        if (r64_pref.base + pci_region_sum(&r64_pref) > BUILD_PCIMEM64_END)
+        if (r64_pref.base + pci_region_sum(&r64_pref) > pcimem64_end)
             panic("PCI: out of 64bit address space\n");
         pci_region_map_entries(busses, &r64_mem);
         pci_region_map_entries(busses, &r64_pref);
+    } else {
+        // no bars mapped high -> drop 64bit window
+        pcimem64_start = 0;
     }
     // Map regions on each device.
     int bus;
@@ -634,6 +642,10 @@ pci_setup(void)
     }
 
     dprintf(3, "pci setup\n");
+    u64 pcimem64_size = (1LL << 36); // 64 MB
+    pcimem_start = RamSize;
+    pcimem64_start = (RamSizeOver4G + pcimem64_size) & ~(pcimem64_size-1);
+    pcimem64_end = pcimem64_start + pcimem64_size;
 
     dprintf(1, "=== PCI bus & bridge init ===\n");
     if (pci_probe_host() != 0) {
-- 
1.7.1




More information about the SeaBIOS mailing list