piix4: heuristic quirk for incorrect value of PM1a_CNT_BLK

Andriy Gapon avg at icyb.net.ua
Mon Mar 16 09:03:36 PDT 2009


I personally own two different systems (from different vendors) based on
PIIX4E/440BX chipset.
They both have incorrect value of PM1a_CNT_BLK and in both case it's 0x4040
instead 0x4004. I suspect that this was a common mistake that was made by a BIOS
vendor and then propagated into a number of BIOSes for different motehrboard vendors.
I've developed a local quirk/fix for this which works in heuristic way. It depends
on the fact that PIIX4 and later ICH chipsets have the same layout for several
ACPI-related registers in Power Management IO space.
So it forces Pm1aControlBlock to pm_base + 4 if Pm1aEventBlock is at pm_base + 0
and PmTimerBlock is at pm_base + 8.

But I am not sure if it won't break any non-Intel HW.
So this patch is not likely to be ever committed to freebsd sources, but it might
be useful for some people. This can help on the relevant systems that have
problems with shutdown/reboot via ACPI.

diff --git a/sys/dev/acpica/acpi_quirk.c b/sys/dev/acpica/acpi_quirk.c
index b75a527..bb44088 100644
--- a/sys/dev/acpica/acpi_quirk.c
+++ b/sys/dev/acpica/acpi_quirk.c
@@ -140,6 +140,7 @@ acpi_table_quirks(int *quirks)
     const struct acpi_q_entry *entry;
     const struct acpi_q_rule *match;
     ACPI_TABLE_HEADER fadt, dsdt, xsdt, *hdr;
+    UINT32 pm_base;
     int done;

     /* First, allow the machdep system to set its idea of quirks. */
@@ -180,5 +181,21 @@ acpi_table_quirks(int *quirks)
 	}
     }

+    /* Special check for incorrect PM1a_CNT_BLK address on PIIX4E systems,
+     * a mistake that was common for many BIOS vendors.
+     */
+    pm_base = AcpiGbl_FADT.Pm1aControlBlock & 0xffffff00;
+    if ((AcpiGbl_FADT.PmTimerBlock & 0xffffff00) == pm_base
+	&& (AcpiGbl_FADT.Pm1aEventBlock & 0xffffff00) == pm_base
+	&& (AcpiGbl_FADT.PmTimerBlock & 0xff) == 0x08
+	&& (AcpiGbl_FADT.Pm1aEventBlock & 0xff) == 0x00
+	&& (AcpiGbl_FADT.Pm1aControlBlock & 0xff) != 0x04)
+    {
+	printf("detected a system that looks like PIIX4E with incorrect "
+	    "PM1a_CNT_BLK address\n");
+	printf("PM_BASE: %#x, PM1a_CNT_BLK: %#x => %#x\n",
+	    pm_base, AcpiGbl_FADT.Pm1aControlBlock, pm_base | 0x04);
+	AcpiGbl_FADT.Pm1aControlBlock = pm_base | 0x04;
+    }
     return (0);
 }

-- 
Andriy Gapon


More information about the freebsd-acpi mailing list