Write the pci window location to memory and add a pointer to the SSDT (BDAT region). Turn \SB.PCI0._CRS into a method which looks up the information there and updates the ressources accordingly.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/acpi-dsdt.dsl | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/acpi.c | 28 ++++++++++++++++++++++- 2 files changed, 88 insertions(+), 3 deletions(-)
diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl index 4bdc268..5fd3bb2 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,8 +174,67 @@ 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 + ,, PW64, AddressRangeMemory, TypeStatic) }) + Method (_CRS, 0) + { + External (_SB.BDAT) + Field(_SB.BDAT, QWordAcc, NoLock, Preserve) { + QW0, 64, + QW1, 64, + QW2, 64, + QW3, 64, + QW4, 64, + QW5, 64, + } + Field(_SB.BDAT, DWordAcc, NoLock, Preserve) { + DWL0, 32, + DWH0, 32, + DWL1, 32, + DWH1, 32, + DWL2, 32, + DWH2, 32, + DWL3, 32, + DWH3, 32, + DWL4, 32, + DWH4, 32, + DWL5, 32, + DWH5, 32, + } + + /* 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 (DWL0, PS32) + Store (DWL1, PE32) + Store (DWL2, PL32) + + If (LAnd(LEqual(DWL3, 0x00),LEqual(DWH3, 0x00))) { + Return (CRES) + } Else { + /* fixup 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 (QW3, PS64) + Store (QW4, PE64) + Store (QW5, PL64) + /* add window and return result */ + ConcatenateResTemplate (CRES, CR64, Local0) + Return (Local0) + } + } } }
diff --git a/src/acpi.c b/src/acpi.c index 30888b9..a13298d 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,31 @@ build_ssdt(void) for (i=0; i<acpi_cpus; i++) *(ssdt_ptr++) = (i < CountCPUs) ? 0x01 : 0x00;
+ // store pci io windows: start, end, length + // this way we don't have to do the math in the dsdt + u64 *pcimem = malloc_high(sizeof(*pcimem) * 6); + pcimem[0] = pcimem_start; + pcimem[1] = pcimem_end - 1; + pcimem[2] = pcimem_end - pcimem_start - 1; + pcimem[3] = pcimem64_start; + pcimem[4] = pcimem64_end - 1; + pcimem[5] = pcimem64_end - pcimem64_start - 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) * 6; + ssdt_ptr += 4; + build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
//hexdump(ssdt, ssdt_ptr - ssdt);