summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica/acpi_quirk.c
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-06-30 04:45:32 +0000
committernjl <njl@FreeBSD.org>2004-06-30 04:45:32 +0000
commite452f1561c7cbff9656dda5a0d7158ecf073c522 (patch)
treed6bf89cf655ae826abef14577ae67e79be48b801 /sys/dev/acpica/acpi_quirk.c
parent53a70792e9096e1fa022cf319d27bf15d6e708e1 (diff)
downloadFreeBSD-src-e452f1561c7cbff9656dda5a0d7158ecf073c522.zip
FreeBSD-src-e452f1561c7cbff9656dda5a0d7158ecf073c522.tar.gz
Add the table quirk matching code. It matches rules defined in acpi_quirks
and sets the flags. It also calls the machdep quirk code first. This allows table quirks (or whitelists) to override machdep quirks.
Diffstat (limited to 'sys/dev/acpica/acpi_quirk.c')
-rw-r--r--sys/dev/acpica/acpi_quirk.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/sys/dev/acpica/acpi_quirk.c b/sys/dev/acpica/acpi_quirk.c
new file mode 100644
index 0000000..f50bee3
--- /dev/null
+++ b/sys/dev/acpica/acpi_quirk.c
@@ -0,0 +1,183 @@
+/*-
+ * Copyright (c) 2004 Nate Lawson (SDG)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+#include "acpi.h"
+#include <dev/acpica/acpivar.h>
+
+enum ops_t {
+ OP_NONE,
+ OP_LEQ,
+ OP_GEQ,
+ OP_EQL,
+};
+
+enum val_t {
+ OEM,
+ OEM_REV,
+ CREATOR,
+ CREATOR_REV,
+};
+
+#define ACPI_TABLE_END (ACPI_TABLE_MAX + 1)
+
+struct acpi_q_rule {
+ int sig; /* Table signature to match */
+ enum val_t val;
+ union {
+ char *id;
+ enum ops_t op;
+ } x;
+ union {
+ char *tid;
+ int rev;
+ } y;
+};
+
+struct acpi_q_entry {
+ const struct acpi_q_rule *match;
+ int quirks;
+};
+
+#include "acpi_quirks.h"
+
+static int aq_revcmp(int revision, enum ops_t op, int value);
+static int aq_strcmp(char *actual, char *possible);
+static int aq_match_header(ACPI_TABLE_HEADER *hdr,
+ const struct acpi_q_rule *match);
+
+static int
+aq_revcmp(int revision, enum ops_t op, int value)
+{
+ switch (op) {
+ case OP_LEQ:
+ if (revision <= value)
+ return (TRUE);
+ break;
+ case OP_GEQ:
+ if (revision >= value)
+ return (TRUE);
+ break;
+ case OP_EQL:
+ if (revision == value)
+ return (TRUE);
+ break;
+ case OP_NONE:
+ return (TRUE);
+ default:
+ panic("aq_revcmp: invalid op %d", op);
+ }
+
+ return (FALSE);
+}
+
+static int
+aq_strcmp(char *actual, char *possible)
+{
+ if (actual == NULL || possible == NULL)
+ return (TRUE);
+ return (strncmp(actual, possible, strlen(possible)) == 0);
+}
+
+static int
+aq_match_header(ACPI_TABLE_HEADER *hdr, const struct acpi_q_rule *match)
+{
+ int result;
+
+ result = FALSE;
+ switch (match->val) {
+ case OEM:
+ if (aq_strcmp(hdr->OemId, match->x.id) &&
+ aq_strcmp(hdr->OemTableId, match->y.tid))
+ result = TRUE;
+ break;
+ case CREATOR:
+ if (aq_strcmp(hdr->AslCompilerId, match->x.id))
+ result = TRUE;
+ break;
+ case OEM_REV:
+ if (aq_revcmp(hdr->OemRevision, match->x.op, match->y.rev))
+ result = TRUE;
+ break;
+ case CREATOR_REV:
+ if (aq_revcmp(hdr->AslCompilerRevision, match->x.op, match->y.rev))
+ result = TRUE;
+ break;
+ }
+
+ return (result);
+}
+
+int
+acpi_table_quirks(int *quirks)
+{
+ const struct acpi_q_entry *entry;
+ const struct acpi_q_rule *match;
+ ACPI_TABLE_HEADER *hdr;
+ int done;
+
+ /* First, allow the machdep system to set its idea of quirks. */
+ KASSERT(quirks != NULL, ("acpi quirks ptr is NULL"));
+ acpi_machdep_quirks(quirks);
+
+ /* Then, override the quirks with any matched from table signatures. */
+ for (entry = acpi_quirks_table; entry->match; entry++) {
+ done = TRUE;
+ for (match = entry->match; match->sig != ACPI_TABLE_END; match++) {
+ switch (match->sig) {
+ case ACPI_TABLE_FADT:
+ hdr = (ACPI_TABLE_HEADER *)AcpiGbl_FADT;
+ break;
+ case ACPI_TABLE_DSDT:
+ hdr = (ACPI_TABLE_HEADER *)AcpiGbl_DSDT;
+ break;
+ case ACPI_TABLE_XSDT:
+ hdr = (ACPI_TABLE_HEADER *)AcpiGbl_XSDT;
+ break;
+ default:
+ panic("invalid quirk header\n");
+ }
+
+ /* If we don't match any, skip to the next entry. */
+ if (!aq_match_header(hdr, match)) {
+ done = FALSE;
+ break;
+ }
+ }
+
+ /* If all entries matched, update the quirks and return. */
+ if (done) {
+ *quirks = entry->quirks;
+ break;
+ }
+ }
+
+ return (0);
+}
OpenPOWER on IntegriCloud