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