From: Paolo Bonzini Date: Thu, 2 Aug 2012 13:07:26 +0000 (+0200) Subject: acpi: build PCI hotplug devices from a single template X-Git-Tag: rel-1.7.2~79 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=71ed8e3a46d3becabc80e59eeda628f19c2cd2a2;p=seabios.git acpi: build PCI hotplug devices from a single template More than 1kb of data is taken by the 32 copies of the PCI hotplug SSDT methods. We can build them from a single template like we do for CPUs (wrapped in a Scope(\_SB.PCI0) block). Three items differ for each slot: the device name, bits 16-23 of _ADR, the _SUN value. On top of this we have to rename the eject method for non-removable slots, like we already do in build_pcihp. There is a small change in the ASL: instead of including the number of the slot in the implementation of _EJ0, we just call _SUN. This is also similar to what we do for CPU hotplug. Once we do this, there is no need to keep a separate SSDT for PCI hotplug. Everything can reside in the same table. Signed-off-by: Paolo Bonzini --- diff --git a/src/acpi.c b/src/acpi.c index 9320787..6d239fa 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -407,12 +407,22 @@ encodeLen(u8 *ssdt_ptr, int length, int bytes) #define PROC_SIZEOF (*ssdt_proc_end - *ssdt_proc_start) #define PROC_AML (ssdp_proc_aml + *ssdt_proc_start) +/* 0x5B 0x82 DeviceOp PkgLength NameString */ +#define PCIHP_OFFSET_HEX (*ssdt_pcihp_name - *ssdt_pcihp_start + 1) +#define PCIHP_OFFSET_ID (*ssdt_pcihp_id - *ssdt_pcihp_start) +#define PCIHP_OFFSET_ADR (*ssdt_pcihp_adr - *ssdt_pcihp_start) +#define PCIHP_OFFSET_EJ0 (*ssdt_pcihp_ej0 - *ssdt_pcihp_start) +#define PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start) +#define PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start) #define PCI_SLOTS 32 #define SSDT_SIGNATURE 0x54445353 // SSDT #define SSDT_HEADER_LENGTH 36 #include "ssdt-susp.hex" +#include "ssdt-pcihp.hex" + +#define PCI_RMV_BASE 0xae0c static u8* build_notify(u8 *ssdt_ptr, const char *name, int skip, int count, @@ -444,6 +454,24 @@ build_notify(u8 *ssdt_ptr, const char *name, int skip, int count, return ssdt_ptr; } +static void patch_pcihp(int slot, u8 *ssdt_ptr, u32 eject) +{ + ssdt_ptr[PCIHP_OFFSET_HEX] = getHex(slot >> 4); + ssdt_ptr[PCIHP_OFFSET_HEX+1] = getHex(slot); + ssdt_ptr[PCIHP_OFFSET_ID] = slot; + ssdt_ptr[PCIHP_OFFSET_ADR + 2] = slot; + + /* Runtime patching of EJ0: to disable hotplug for a slot, + * replace the method name: _EJ0 by EJ0_. */ + /* Sanity check */ + if (memcmp(ssdt_ptr + PCIHP_OFFSET_EJ0, "_EJ0", 4)) { + warn_internalerror(); + } + if (!eject) { + memcpy(ssdt_ptr + PCIHP_OFFSET_EJ0, "EJ0_", 4); + } +} + static void* build_ssdt(void) { @@ -455,6 +483,7 @@ build_ssdt(void) + (6+2+1+(1*acpi_cpus)) // CPON + 17 // BDAT + (1+3+4) // Scope(PCI0) + + ((PCI_SLOTS - 1) * PCIHP_SIZEOF) // slots + (1+2+5+(12*(PCI_SLOTS - 1)))); // PCNT u8 *ssdt = malloc_high(length); if (! ssdt) { @@ -546,6 +575,15 @@ build_ssdt(void) *(ssdt_ptr++) = 'I'; *(ssdt_ptr++) = '0'; + // build Device object for each slot + u32 rmvc_pcrm = inl(PCI_RMV_BASE); + for (i=1; ichecksum = 0; - ((struct acpi_table_header*)ssdt)->checksum -= checksum(ssdt, sizeof(ssdp_pcihp_aml)); - return ssdt; -} - #define HPET_SIGNATURE 0x54455048 // HPET static void* build_hpet(void) @@ -780,7 +774,6 @@ acpi_bios_init(void) ACPI_INIT_TABLE(build_madt()); ACPI_INIT_TABLE(build_hpet()); ACPI_INIT_TABLE(build_srat()); - ACPI_INIT_TABLE(build_pcihp()); u16 i, external_tables = qemu_cfg_acpi_additional_tables(); diff --git a/src/ssdt-pcihp.dsl b/src/ssdt-pcihp.dsl index fd9c0bb..cd66b83 100644 --- a/src/ssdt-pcihp.dsl +++ b/src/ssdt-pcihp.dsl @@ -12,50 +12,23 @@ DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1) External (\_SB.PCI0.PCEJ, MethodObj) Scope(\_SB.PCI0) { + /* Bulk generated PCI hotplug devices */ + ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start + ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end + ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name + // Method _EJ0 can be patched by BIOS to EJ0_ // at runtime, if the slot is detected to not support hotplug. // Extract the offset of the address dword and the // _EJ0 name to allow this patching. -#define hotplug_slot(slot) \ - Device (S##slot) { \ - ACPI_EXTRACT_NAME_DWORD_CONST aml_adr_dword \ - Name (_ADR, 0x##slot##0000) \ - ACPI_EXTRACT_METHOD_STRING aml_ej0_name \ - Method (_EJ0, 1) { Return(PCEJ(0x##slot)) } \ - Name (_SUN, 0x##slot) \ + Device (SAA) { + ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id + Name (_SUN, 0xAA) + ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr + Name (_ADR, 0xAA0000) + ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0 + Method (_EJ0, 1) { Return(PCEJ(_SUN)) } } - - hotplug_slot(01) - hotplug_slot(02) - hotplug_slot(03) - hotplug_slot(04) - hotplug_slot(05) - hotplug_slot(06) - hotplug_slot(07) - hotplug_slot(08) - hotplug_slot(09) - hotplug_slot(0a) - hotplug_slot(0b) - hotplug_slot(0c) - hotplug_slot(0d) - hotplug_slot(0e) - hotplug_slot(0f) - hotplug_slot(10) - hotplug_slot(11) - hotplug_slot(12) - hotplug_slot(13) - hotplug_slot(14) - hotplug_slot(15) - hotplug_slot(16) - hotplug_slot(17) - hotplug_slot(18) - hotplug_slot(19) - hotplug_slot(1a) - hotplug_slot(1b) - hotplug_slot(1c) - hotplug_slot(1d) - hotplug_slot(1e) - hotplug_slot(1f) } }