diff options
author | njl <njl@FreeBSD.org> | 2004-06-30 04:45:32 +0000 |
---|---|---|
committer | njl <njl@FreeBSD.org> | 2004-06-30 04:45:32 +0000 |
commit | e452f1561c7cbff9656dda5a0d7158ecf073c522 (patch) | |
tree | d6bf89cf655ae826abef14577ae67e79be48b801 /sys/dev/acpica/acpi_quirk.c | |
parent | 53a70792e9096e1fa022cf319d27bf15d6e708e1 (diff) | |
download | FreeBSD-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.c | 183 |
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); +} |