Re: [acpi-jp 2190] Re: Outstanding ACPI issues for 5.1-RELEASE

From: Magnus B{ckstr|m <b_at_etek.chalmers.se>
Date: Thu, 8 May 2003 10:28:56 +0200 (CEST)
On Thu, 8 May 2003, User Takawata wrote:
>
> That's because the _HID format is not conform to the standard.
> Add following change and check whether Host PCI bus bridge appears or not.

>         !acpi_disabled("pci") &&
> -       acpi_MatchHid(dev, "PNP0A03")) {
> +       acpi_MatchHid(dev, "*PNP0A03")) {
>

I'm afraid this may not be the end of it.  An N800c I encountered a few
weeks ago consistently had _HIDs with asterisks.  If I may contribute
an untested general workaround (untested because I don't currently have
access to the hardware):

Index: src/sys/dev/acpica/acpi.c
diff -u src/sys/dev/acpica/acpi.c:1.1.1.6.2.1 src/sys/dev/acpica/acpi.c:1.1.1.6.2.2
--- src/sys/dev/acpica/acpi.c:1.1.1.6.2.1	Wed Apr 16 16:06:20 2003
+++ src/sys/dev/acpica/acpi.c	Thu May  8 10:00:28 2003
_at__at_ -1041,8 +1041,21 _at__at_
 	return(FALSE);
     if (ACPI_FAILURE(error = AcpiGetObjectInfo(h, &devinfo)))
 	return(FALSE);
-    if ((devinfo.Valid & ACPI_VALID_HID) && !strcmp(hid, devinfo.HardwareId))
-	return(TRUE);
+
+    /*
+     * Some vendors erronously report HIDs with leading asterisks.
+     * The below workaround accomodates this.
+     */
+    if (devinfo.Valid & ACPI_VALID_HID) {
+	    if (devinfo.HardwareId[0] == '*') {
+		    if (strcmp(hid, (devinfo.HardwareId + 1)) == 0)
+			    return TRUE;
+	    }
+
+	    if (strcmp(hid, devinfo.HardwareId) == 0)
+		    return (TRUE);
+    }
+
     if (ACPI_FAILURE(error = acpi_EvaluateInteger(h, "_CID", &cid)))
 	return(FALSE);
     if (cid == PNP_EISAID(hid))


Furthermore, the laptop used idioms that were a bit too modern for
our ACPI implementation.  CIDs are allowed to be not only integers,
but also buffers (think `char *') with images of ACPI_INTEGERs, and
packages with multiple integer objects in them (for multiple possible
CIDs).  The below -should- fix this but is also untested.

Index: src/sys/dev/acpica/acpi.c
diff -u src/sys/dev/acpica/acpi.c:1.1.1.6.2.2 src/sys/dev/acpica/acpi.c:1.1.1.6.2.3
--- src/sys/dev/acpica/acpi.c:1.1.1.6.2.2	Thu May  8 10:00:28 2003
+++ src/sys/dev/acpica/acpi.c	Thu May  8 10:06:17 2003
_at__at_ -1160,20 +1160,57 _at__at_
 {
     ACPI_OBJECT	*p;
     int		i;
+    ACPI_INTEGER num;

     p = (ACPI_OBJECT *)bufp->Pointer;
     if (p->Type == ACPI_TYPE_INTEGER) {
 	*number = p->Integer.Value;
 	return(AE_OK);
     }
-    if (p->Type != ACPI_TYPE_BUFFER)
+    if (p->Type == ACPI_TYPE_PACKAGE) {
+	/*
+	 * Shrewdly guess that the vendor is likely to put the most
+	 * useful element last in the package.
+	 */
+	if (p->Package.Elements[p->Package.Count-1].Type ==ACPI_TYPE_INTEGER) {
+	    *number = (int) p->Package.Elements[1].Integer.Value;
+	    return (AE_OK);
+	}
+
+    }
+    if (p->Type != ACPI_TYPE_BUFFER) {
+	printf("acpi_ConvertBufferToInteger: Unknown p->Type %d\n", p->Type);
 	return(AE_TYPE);
-    if (p->Buffer.Length > sizeof(int))
-	return(AE_BAD_DATA);
-    *number = 0;
-    for (i = 0; i < p->Buffer.Length; i++)
-	*number += (*(p->Buffer.Pointer + i) << (i * 8));
-    return(AE_OK);
+    }
+
+    /*
+     * In ACPI 2.0 an ACPI_INTEGER is 64 bit.  In 1.0 it was 32 bit.
+     * We comply with either.
+     */
+    if (p->Buffer.Length == sizeof(ACPI_INTEGER)) {
+	num = 0;
+
+	for (i = 0; i < p->Buffer.Length; i++)
+	    num += (*(p->Buffer.Pointer + i) << (i * 8));
+
+	*number = (int) num;
+	return(AE_OK);
+    }
+
+    /* ACPI 1.0 case. */
+    if (p->Buffer.Length == sizeof(int)) {
+	*number = 0;
+
+	for (i = 0; i < p->Buffer.Length; i++)
+	    *number += (*(p->Buffer.Pointer + i) << (i * 8));
+
+	return (AE_OK);
+    }
+
+    printf("acpi_ConvertBufferToInteger: bad buffer length %d\n",
+	   p->Buffer.Length);
+
+    return (AE_BAD_DATA);
 }

 /*


Best regards,
Magnus
Received on Wed May 07 2003 - 23:29:01 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:07 UTC