i386/73380: [patch] kldload acpi_asus.ko causes page fault on Samsung P35

Sebastian Schulze Struchtrup sebastian at struchtrup.de
Mon Nov 1 05:14:45 PST 2004


Well, the patch got lost.
Here it is.


-------------- next part --------------
Index: acpi_asus.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/acpica/acpi_asus.c,v
retrieving revision 1.11
diff -u -p -r1.11 acpi_asus.c
--- acpi_asus.c	13 Aug 2004 06:22:29 -0000	1.11
+++ acpi_asus.c	1 Nov 2004 12:48:17 -0000
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: src/sys/i386/acpica/acpi_asus.c,v 1.11 2004/08/13 06:22:29 njl Exp $");
 
 /*
  * Driver for extra ACPI-controlled gadgets (hotkeys, leds, etc) found on
@@ -58,7 +58,7 @@ ACPI_MODULE_NAME("ASUS")
 
 struct acpi_asus_model {
 	char	*name;
-
+	char    *longname;
 	char	*mled_set;
 	char	*tled_set;
 	char	*wled_set;
@@ -103,9 +103,11 @@ struct acpi_asus_softc {
 };
 
 /* Models we know about */
+/* These are identified by name returned on ATK INIT */
 static struct acpi_asus_model acpi_asus_models[] = {
 	{
 		.name		= "L2D",
+		.longname	= "Asus L2D",
 		.mled_set	= "MLED",
 		.wled_set	= "WLED",
 		.brn_up		= "\\Q0E",
@@ -115,6 +117,7 @@ static struct acpi_asus_model acpi_asus_
 	},
 	{
 		.name		= "L3C",
+		.longname	= "Asus L3C",
 		.mled_set	= "MLED",
 		.wled_set	= "WLED",
 		.brn_get	= "GPLV",
@@ -124,6 +127,7 @@ static struct acpi_asus_model acpi_asus_
 	},
 	{
 		.name		= "L3D",
+		.longname	= "Asus L3D",
 		.mled_set	= "MLED",
 		.wled_set	= "WLED",
 		.brn_get	= "GPLV",
@@ -133,6 +137,7 @@ static struct acpi_asus_model acpi_asus_
 	},
 	{
 		.name		= "L3H",
+		.longname	= "Asus L3H",
 		.mled_set	= "MLED",
 		.wled_set	= "WLED",
 		.brn_get	= "GPLV",
@@ -143,11 +148,13 @@ static struct acpi_asus_model acpi_asus_
 		.disp_set	= "SDSP"
 	},
 	{
-		.name		= "L8L"
+		.name		= "L8L",
+		.longname	= "Asus L8L"
 		/* Only has hotkeys, apparantly */
 	},
 	{
 		.name		= "M1A",
+		.longname	= "Asus M1A",
 		.mled_set	= "MLED",
 		.brn_up		= "\\_SB.PCI0.PX40.EC0.Q0E",
 		.brn_dn		= "\\_SB.PCI0.PX40.EC0.Q0F",
@@ -156,6 +163,7 @@ static struct acpi_asus_model acpi_asus_
 	},
 	{
 		.name		= "M2E",
+		.longname	= "Asus M2E",
 		.mled_set	= "MLED",
 		.wled_set	= "WLED",
 		.brn_get	= "GPLV",
@@ -163,18 +171,33 @@ static struct acpi_asus_model acpi_asus_
 		.lcd_get	= "\\GP06",
 		.lcd_set	= "\\Q10"
 	},
+
+	{ .name = NULL }
+};
+
+/* This notebook are also supported, but cannon be identified by
+ * their name because ATK INIT does not return their name
+ * update the following enum when updating this table */
+
+static struct acpi_asus_model acpi_asus_extra_models[] = {
 	{
 		.name		= "P30",
+		.longname	= "Samsung P30/P35",
 		.wled_set	= "WLED",
 		.brn_up		= "\\_SB.PCI0.LPCB.EC0._Q68",
 		.brn_dn		= "\\_SB.PCI0.LPCB.EC0._Q69",
 		.lcd_get	= "\\BKLT",
 		.lcd_set	= "\\_SB.PCI0.LPCB.EC0._Q0E"
 	},
+};
 
-	{ .name = NULL }
+/* must be in sync with acpi_asus_extra_models above */
+enum acpi_asus_extra_models_idx
+{
+	SAMSUNG_P30 = 0	
 };
 
+
 ACPI_SERIAL_DECL(asus, "ACPI ASUS extras");
 
 /* Function prototypes */
@@ -218,6 +241,10 @@ acpi_asus_probe(device_t dev)
 	ACPI_BUFFER		Buf;
 	ACPI_OBJECT		Arg, *Obj;
 	ACPI_OBJECT_LIST	Args;
+	ACPI_TABLE_HEADER dsdt_header;
+	ACPI_STATUS	status;
+	int has_dsdt;
+
 	static char 		*asus_ids[] = { "ATK0100", NULL };
 
 	ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -233,6 +260,17 @@ acpi_asus_probe(device_t dev)
 		if (sb == NULL)
 			return (ENOMEM);
 
+		/* Get DSDT Header (copy the header into our dsdt_header struct) */
+		status = AcpiGetTableHeader(ACPI_TABLE_DSDT, 1, &dsdt_header);
+		if (ACPI_FAILURE(status))
+		{
+				device_printf(dev, "unable to load DSDT\n");
+				has_dsdt = 0;
+		}
+		else
+			has_dsdt = 1;
+
+		/* Call ATK INIT */
 		Arg.Type = ACPI_TYPE_INTEGER;
 		Arg.Integer.Value = 0;
 
@@ -243,33 +281,54 @@ acpi_asus_probe(device_t dev)
 		Buf.Length = ACPI_ALLOCATE_BUFFER;
 	
 		AcpiEvaluateObject(sc->handle, "INIT", &Args, &Buf);
-		
 		Obj = Buf.Pointer;
-
-		for (model = acpi_asus_models; model->name != NULL; model++)
-			if (strcmp(Obj->String.Pointer, model->name) == 0) {
-				sbuf_printf(sb, "Asus %s Laptop Extras",
-						Obj->String.Pointer);
-				sbuf_finish(sb);
-				
-				sc->model = model;
-				device_set_desc(dev, sbuf_data(sb));
-
-				sbuf_delete(sb);
-				AcpiOsFree(Buf.Pointer);
-				return (0);
+		
+		sc->model = NULL;
+		if ((Obj != NULL) && (Obj->String.Pointer != NULL))
+		{
+			/* got name, loop over known models */
+			for (model = acpi_asus_models; model->name != NULL; model++)
+				if (strcmp(Obj->String.Pointer, model->name) == 0) {
+					sc->model = model;
+				}
+
+			if (sc->model == NULL) {
+				sbuf_printf(sb, "Unsupported Asus laptop detected: %s\n",
+				Obj->String.Pointer);				
+			}
+			AcpiOsFree(Buf.Pointer);
+		}
+		else
+		{
+			/* some notebooks don't return anything on INIT (NULL)
+			   The Samsung P30/P35 are known to do this.
+			*/
+			if ((has_dsdt) && (strncmp("ODEM", dsdt_header.OemTableId, 4)==0)) {
+				sc->model = &acpi_asus_extra_models[SAMSUNG_P30];
+				sbuf_printf(sb, "Missing model name: "
+								"Identified as Samsung P30/P35\n");
 			}
+			else
+			{
+				sbuf_printf(sb, "Your notebook supports the asus ATK device,"
+								" but can't be identified\n");
+			}
+		}
 
-		sbuf_printf(sb, "Unsupported Asus laptop detected: %s\n",
-				Obj->String.Pointer);
 		sbuf_finish(sb);
-
 		device_printf(dev, sbuf_data(sb));
-
-		sbuf_delete(sb);
-		AcpiOsFree(Buf.Pointer);
+		
+		if (sc->model != NULL)
+		{
+			sbuf_clear(sb);
+			sbuf_printf(sb, "%s Laptop Extras", sc->model->longname);
+			sbuf_finish(sb);
+			device_set_desc(dev, sbuf_data(sb));
+			sbuf_delete(sb);
+			return(0);
+		}
 	}
-
+	/* either not identified or disabled */
 	return (ENXIO);
 }
 


More information about the freebsd-acpi mailing list