summaryrefslogtreecommitdiff
path: root/sys/dev/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/acpi')
-rw-r--r--sys/dev/acpi/acpi.c597
-rw-r--r--sys/dev/acpi/acpireg.h428
-rw-r--r--sys/dev/acpi/acpitimer.c152
-rw-r--r--sys/dev/acpi/acpiutil.c42
-rw-r--r--sys/dev/acpi/acpivar.h111
-rw-r--r--sys/dev/acpi/files.acpi20
-rw-r--r--sys/dev/acpi/hpet.c144
-rw-r--r--sys/dev/acpi/hpetreg.h32
8 files changed, 1526 insertions, 0 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
new file mode 100644
index 00000000000..77cdcc04ec1
--- /dev/null
+++ b/sys/dev/acpi/acpi.c
@@ -0,0 +1,597 @@
+/* $OpenBSD: acpi.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */
+/*
+ * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/fcntl.h>
+#include <sys/ioccom.h>
+#include <sys/event.h>
+
+#include <machine/conf.h>
+#include <machine/bus.h>
+
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+
+int acpimatch(struct device *, void *, void *);
+void acpiattach(struct device *, struct device *, void *);
+int acpi_submatch(struct device *, void *, void *);
+int acpi_print(void *, const char *);
+int acpi_loadtables(struct acpi_softc *, struct acpi_rsdp *);
+void acpi_load_table(paddr_t, size_t, acpi_qhead_t *);
+void acpi_load_dsdt(paddr_t, struct acpi_q **);
+void acpi_softintr(void *);
+void acpi_filtdetach(struct knote *);
+int acpi_filtread(struct knote *, long);
+
+#define ACPI_LOCK(sc)
+#define ACPI_UNLOCK(sc)
+
+struct filterops acpiread_filtops = {
+ 1, NULL, acpi_filtdetach, acpi_filtread
+};
+
+struct cfattach acpi_ca = {
+ sizeof(struct acpi_softc), acpimatch, acpiattach
+};
+
+struct cfdriver acpi_cd = {
+ NULL, "acpi", DV_DULL
+};
+
+int acpi_evindex;
+struct acpi_softc *acpi_softc;
+
+int
+acpimatch(struct device *parent, void *match, void *aux)
+{
+ struct acpi_attach_args *aaa = aux;
+ struct cfdata *cf = match;
+
+ /* sanity */
+ if (strcmp(aaa->aaa_name, cf->cf_driver->cd_name))
+ return (0);
+
+ if (!acpi_probe(parent, cf, aaa))
+ return (0);
+
+ return (1);
+}
+
+void
+acpiattach(struct device *parent, struct device *self, void *aux)
+{
+#ifdef ACPI_ENABLE
+ bus_space_handle_t ioh;
+#endif
+ struct acpi_attach_args *aaa = aux;
+ struct acpi_softc *sc = (struct acpi_softc *)self;
+ struct acpi_mem_map handle;
+ struct acpi_rsdp *rsdp;
+ struct acpi_q *entry;
+ paddr_t facspa;
+
+ sc->sc_iot = aaa->aaa_iot;
+ sc->sc_memt = aaa->aaa_memt;
+
+ printf(": ");
+ if (acpi_map(aaa->aaa_pbase, sizeof(struct acpi_rsdp), &handle))
+ goto fail;
+
+ rsdp = (struct acpi_rsdp *)handle.va;
+ printf("revision %d ", (int)rsdp->rsdp_revision);
+
+ SIMPLEQ_INIT(&sc->sc_tables);
+
+ sc->sc_fadt = NULL;
+ sc->sc_facs = NULL;
+ sc->sc_powerbtn = 0;
+ sc->sc_sleepbtn = 0;
+
+ sc->sc_note = malloc(sizeof(struct klist), M_DEVBUF, M_NOWAIT);
+ memset(sc->sc_note, 0, sizeof(struct klist));
+
+ if (acpi_loadtables(sc, rsdp)) {
+ acpi_unmap(&handle);
+ return;
+ }
+
+ acpi_unmap(&handle);
+
+ /*
+ * Find the FADT
+ */
+ SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
+ if (memcmp(entry->q_table, FADT_SIG, sizeof(FADT_SIG) - 1) == 0) {
+ sc->sc_fadt = entry->q_table;
+ break;
+ }
+ }
+ if (sc->sc_fadt == NULL)
+ goto fail;
+
+ /*
+ * Check if we are able to enable ACPI control
+ */
+ if (!sc->sc_fadt->smi_cmd ||
+ (!sc->sc_fadt->acpi_enable && !sc->sc_fadt->acpi_disable))
+ goto fail;
+
+ /*
+ * Load the DSDT from the FADT pointer -- use the
+ * extended (64-bit) pointer if it exists
+ */
+ if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_dsdt == 0)
+ acpi_load_dsdt(sc->sc_fadt->dsdt, &entry);
+ else
+ acpi_load_dsdt(sc->sc_fadt->x_dsdt, &entry);
+
+ if (entry == NULL)
+ printf("!DSDT ");
+ SIMPLEQ_INSERT_HEAD(&sc->sc_tables, entry, q_next);
+
+ /*
+ * Set up a pointer to the firmware control structure
+ */
+ if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_firmware_ctl == 0)
+ facspa = sc->sc_fadt->firmware_ctl;
+ else
+ facspa = sc->sc_fadt->x_firmware_ctl;
+
+ if (acpi_map(facspa, sizeof(struct acpi_facs), &handle))
+ printf("!FACS ");
+ else
+ sc->sc_facs = (struct acpi_facs *)handle.va;
+
+ /*
+ * Take over ACPI control. Note that once we do this, we
+ * effectively tell the system that we have ownership of
+ * the ACPI hardware registers, and that SMI should leave
+ * them alone
+ *
+ * This may prevent thermal control on some systems where
+ * that actually does work
+ */
+#ifdef ACPI_ENABLE
+ bus_space_map(sc->sc_iot, sc->sc_fadt->smi_cmd, 1, 0, &ioh);
+ bus_space_write_1(sc->sc_iot, ioh, 0, sc->sc_fadt->acpi_enable);
+ bus_space_unmap(sc->sc_iot, ioh, 1);
+#endif
+
+ bus_space_map(sc->sc_iot,
+ sc->sc_fadt->pm1a_evt_blk, sc->sc_fadt->pm1_evt_len,
+ 0, &sc->sc_ioh_pm1a_evt);
+
+#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
+ sc->sc_softih = softintr_establish(IPL_TTY, acpi_softintr, sc);
+#else
+ timeout_set(&sc->sc_timeout, acpi_softintr, sc);
+#endif
+ acpi_attach_machdep(sc);
+
+ /*
+ * If we have an interrupt handler, we can get notification
+ * when certain status bits changes in the ACPI registers,
+ * so let us enable some events we can forward to userland
+ */
+ if (sc->sc_interrupt) {
+ int16_t flags;
+
+ flags = bus_space_read_2(sc->sc_iot, sc->sc_ioh_pm1a_evt,
+ sc->sc_fadt->pm1_evt_len / 2);
+ flags |= ACPI_PM1_PWRBTN_EN | ACPI_PM1_SLPBTN_EN;
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh_pm1a_evt,
+ sc->sc_fadt->pm1_evt_len / 2, flags);
+ }
+
+ printf("attached\n");
+
+ /*
+ * ACPI is enabled now -- attach timer
+ */
+ {
+ struct acpi_attach_args aaa;
+
+ memset(&aaa, 0, sizeof(aaa));
+ aaa.aaa_name = "acpitimer";
+ aaa.aaa_iot = sc->sc_iot;
+ aaa.aaa_memt = sc->sc_memt;
+#if 0
+ aaa.aaa_pcit = sc->sc_pcit;
+ aaa.aaa_smbust = sc->sc_smbust;
+#endif
+ config_found(self, &aaa, acpi_print);
+ }
+
+ /*
+ * Attach table-defined devices
+ */
+ SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
+ struct acpi_attach_args aaa;
+
+ memset(&aaa, 0, sizeof(aaa));
+ aaa.aaa_iot = sc->sc_iot;
+ aaa.aaa_memt = sc->sc_memt;
+#if 0
+ aaa.aaa_pcit = sc->sc_pcit;
+ aaa.aaa_smbust = sc->sc_smbust;
+#endif
+ aaa.aaa_table = entry->q_table;
+
+ config_found_sm(self, &aaa, acpi_print, acpi_submatch);
+ }
+
+ acpi_softc = sc;
+
+ return;
+
+fail:
+ printf(" failed attach\n");
+}
+
+int
+acpi_submatch(struct device *parent, void *match, void *aux)
+{
+ struct acpi_attach_args *aaa = (struct acpi_attach_args *)aux;
+ struct cfdata *cf = match;
+
+ if (aaa->aaa_table == NULL)
+ return (0);
+ return ((*cf->cf_attach->ca_match)(parent, match, aux));
+}
+
+int
+acpi_print(void *aux, const char *pnp)
+{
+ struct acpi_attach_args *aa = aux;
+#ifdef ACPIVERBOSE
+ struct acpi_table_header *hdr = (struct acpi_table_header *)aa->aaa_table;
+#endif
+
+ if (pnp) {
+ if (aa->aaa_name)
+ printf("%s at %s", aa->aaa_name, pnp);
+#ifdef ACPIVERBOSE
+ else
+ printf("acpi device at %s from", pnp);
+#endif
+ }
+#ifdef ACPIVERBOSE
+ if (hdr)
+ printf(" table %c%c%c%c",
+ hdr->signature[0], hdr->signature[1],
+ hdr->signature[2], hdr->signature[3]);
+#endif
+
+ return (UNCONF);
+}
+
+int
+acpi_loadtables(struct acpi_softc *sc, struct acpi_rsdp *rsdp)
+{
+ struct acpi_mem_map hrsdt, handle;
+ struct acpi_table_header *hdr;
+ int i, ntables;
+ size_t len;
+
+ if (rsdp->rsdp_revision == 2) {
+ struct acpi_xsdt *xsdt;
+
+ if (acpi_map(rsdp->rsdp_xsdt, sizeof(*hdr), &handle)) {
+ printf("couldn't map rsdt\n");
+ return (ENOMEM);
+ }
+
+ hdr = (struct acpi_table_header *)handle.va;
+ len = hdr->length;
+ acpi_unmap(&handle);
+ hdr = NULL;
+
+ acpi_map(rsdp->rsdp_xsdt, len, &hrsdt);
+ xsdt = (struct acpi_xsdt *)hrsdt.va;
+
+ ntables = (len - sizeof(struct acpi_table_header)) /
+ sizeof(xsdt->table_offsets[0]);
+
+ for (i = 0; i < ntables; i++) {
+ acpi_map(xsdt->table_offsets[i], sizeof(*hdr), &handle);
+ hdr = (struct acpi_table_header *)handle.va;
+ acpi_load_table(xsdt->table_offsets[i], hdr->length, &sc->sc_tables);
+ acpi_unmap(&handle);
+ }
+ acpi_unmap(&hrsdt);
+ }
+ else {
+ struct acpi_rsdt *rsdt;
+
+ if (acpi_map(rsdp->rsdp_rsdt, sizeof(*hdr), &handle)) {
+ printf("couldn't map rsdt\n");
+ return (ENOMEM);
+ }
+
+ hdr = (struct acpi_table_header *)handle.va;
+ len = hdr->length;
+ acpi_unmap(&handle);
+ hdr = NULL;
+
+ acpi_map(rsdp->rsdp_rsdt, len, &hrsdt);
+ rsdt = (struct acpi_rsdt *)hrsdt.va;
+
+ ntables = (len - sizeof(struct acpi_table_header)) /
+ sizeof(rsdt->table_offsets[0]);
+
+ for (i = 0; i < ntables; i++) {
+ acpi_map(rsdt->table_offsets[i], sizeof(*hdr), &handle);
+ hdr = (struct acpi_table_header *)handle.va;
+ acpi_load_table(rsdt->table_offsets[i], hdr->length, &sc->sc_tables);
+ acpi_unmap(&handle);
+ }
+ acpi_unmap(&hrsdt);
+ }
+
+ return (0);
+}
+
+void
+acpi_load_table(paddr_t pa, size_t len, acpi_qhead_t *queue)
+{
+ struct acpi_mem_map handle;
+ struct acpi_q *entry;
+
+ entry = malloc(len + sizeof(struct acpi_q), M_DEVBUF, M_NOWAIT);
+
+ if (entry != NULL) {
+ if (acpi_map(pa, len, &handle)) {
+ free(entry, M_DEVBUF);
+ return;
+ }
+ memcpy(entry->q_data, handle.va, len);
+ entry->q_table = entry->q_data;
+ acpi_unmap(&handle);
+ SIMPLEQ_INSERT_TAIL(queue, entry, q_next);
+ }
+}
+
+void
+acpi_load_dsdt(paddr_t pa, struct acpi_q **dsdt)
+{
+ struct acpi_mem_map handle;
+ struct acpi_table_header *hdr;
+ size_t len;
+
+ if (acpi_map(pa, sizeof(*hdr), &handle))
+ return;
+ hdr = (struct acpi_table_header *)handle.va;
+ len = hdr->length;
+ acpi_unmap(&handle);
+
+ *dsdt = malloc(len + sizeof(struct acpi_q), M_DEVBUF, M_NOWAIT);
+
+ if (*dsdt != NULL) {
+ if (acpi_map(pa, len, &handle)) {
+ free(*dsdt, M_DEVBUF);
+ *dsdt = NULL;
+ return;
+ }
+ memcpy((*dsdt)->q_data, handle.va, len);
+ (*dsdt)->q_table = (*dsdt)->q_data;
+ acpi_unmap(&handle);
+ }
+}
+
+int
+acpi_interrupt(void *arg)
+{
+ struct acpi_softc *sc = (struct acpi_softc *)arg;
+ u_int16_t flags;
+
+ flags = bus_space_read_2(sc->sc_iot, sc->sc_ioh_pm1a_evt, ACPI_PM1_STATUS);
+ if (flags & (ACPI_PM1_PWRBTN_STS | ACPI_PM1_SLPBTN_STS)) {
+ if (flags & ACPI_PM1_PWRBTN_STS) {
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh_pm1a_evt,
+ ACPI_PM1_STATUS, ACPI_PM1_PWRBTN_STS);
+ /*
+ * Power-button has been pressed, do something!
+ */
+ sc->sc_powerbtn = 1;
+ }
+ if (flags & ACPI_PM1_SLPBTN_STS) {
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh_pm1a_evt,
+ ACPI_PM1_STATUS, ACPI_PM1_SLPBTN_STS);
+ /*
+ * Sleep-button has been pressed, do something!
+ */
+ sc->sc_sleepbtn = 1;
+ }
+#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
+ softintr_schedule(sc->sc_softih);
+#else
+ if (!timeout_pending(&sc->sc_timeout))
+ timeout_add(&sc->sc_timeout, 0);
+#endif
+ return (1);
+ }
+ return (0);
+}
+
+void
+acpi_softintr(void *arg)
+{
+ struct acpi_softc *sc = arg;
+
+ if (sc->sc_powerbtn) {
+ sc->sc_powerbtn = 0;
+ acpi_evindex++;
+ KNOTE(sc->sc_note, ACPI_EVENT_COMPOSE(ACPI_EV_PWRBTN, acpi_evindex));
+ }
+ if (sc->sc_sleepbtn) {
+ sc->sc_sleepbtn = 0;
+ acpi_evindex++;
+ KNOTE(sc->sc_note, ACPI_EVENT_COMPOSE(ACPI_EV_SLPBTN, acpi_evindex));
+ }
+}
+
+int
+acpiopen(dev_t dev, int flag, int mode, struct proc *p)
+{
+ struct acpi_softc *sc;
+ int error = 0;
+
+ if (!acpi_cd.cd_ndevs || minor(dev) != 0 ||
+ !(sc = acpi_cd.cd_devs[minor(dev)]))
+ return (ENXIO);
+
+ if (!(flag & FREAD) || (flag & FWRITE))
+ error = EINVAL;
+
+ return (error);
+}
+
+void
+acpi_enter_sleep_state(struct acpi_softc *sc, int state)
+{
+#ifdef ACPI_ENABLE
+ bus_space_handle_t ioh;
+ u_int16_t bits;
+
+ bus_space_map(sc->sc_iot,
+ sc->sc_fadt->pm1a_cnt_blk, sc->sc_fadt->pm1_cnt_len,
+ 0, &ioh);
+ bits = bus_space_read_2(sc->sc_iot, ioh, 0);
+ bits |= state << 10; /* XXX This is sick and wrong and illegal! */
+ bus_space_write_2(sc->sc_iot, ioh, 0, bits);
+ bits |= ACPI_PM1_SLP_EN;
+ bus_space_write_2(sc->sc_iot, ioh, 0, bits);
+ bus_space_unmap(sc->sc_iot, ioh, sc->sc_fadt->pm1_cnt_len);
+#endif
+}
+
+int
+acpiclose(dev_t dev, int flag, int mode, struct proc *p)
+{
+ struct acpi_softc *sc;
+
+ if (!acpi_cd.cd_ndevs || minor(dev) != 0 ||
+ !(sc = acpi_cd.cd_devs[minor(dev)]))
+ return (ENXIO);
+
+ return (0);
+}
+
+int
+acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+ struct acpi_softc *sc;
+ int error = 0;
+
+ if (!acpi_cd.cd_ndevs || minor(dev) != 0 ||
+ !(sc = acpi_cd.cd_devs[minor(dev)]))
+ return (ENXIO);
+
+ ACPI_LOCK(sc);
+ switch (cmd) {
+ case ACPI_IOC_GETFACS:
+ if (suser(p, 0) != 0)
+ error = EPERM;
+ else {
+ struct acpi_facs *facs = (struct acpi_facs *)data;
+
+ bcopy(sc->sc_facs, facs, sc->sc_facs->length);
+ }
+ break;
+
+ case ACPI_IOC_GETTABLE:
+ if (suser(p, 0) != 0)
+ error = EPERM;
+ else {
+ struct acpi_table *table = (struct acpi_table *)data;
+ struct acpi_table_header *hdr;
+ struct acpi_q *entry;
+
+ error = ENOENT;
+ SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
+ if (table->offset-- == 0) {
+ hdr = (struct acpi_table_header *)entry->q_table;
+ if (table->table == NULL) {
+ table->size = hdr->length;
+ error = 0;
+ }
+ else if (hdr->length > table->size)
+ error = ENOSPC;
+ else
+ error = copyout(hdr, table->table, hdr->length);
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ error = ENOTTY;
+ }
+
+ ACPI_UNLOCK(sc);
+ return (error);
+}
+
+void
+acpi_filtdetach(struct knote *kn)
+{
+ struct acpi_softc *sc = kn->kn_hook;
+
+ ACPI_LOCK(sc);
+ SLIST_REMOVE(sc->sc_note, kn, knote, kn_selnext);
+ ACPI_UNLOCK(sc);
+}
+
+int
+acpi_filtread(struct knote *kn, long hint)
+{
+ /* XXX weird kqueue_scan() semantics */
+ if (hint & !kn->kn_data)
+ kn->kn_data = hint;
+
+ return(1);
+}
+
+int
+acpikqfilter(dev_t dev, struct knote *kn)
+{
+ struct acpi_softc *sc;
+
+ if (!acpi_cd.cd_ndevs || minor(dev) != 0 ||
+ !(sc = acpi_cd.cd_devs[minor(dev)]))
+ return (ENXIO);
+
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ kn->kn_fop = &acpiread_filtops;
+ break;
+ default:
+ return (1);
+ }
+
+ kn->kn_hook = sc;
+
+ ACPI_LOCK(sc);
+ SLIST_INSERT_HEAD(sc->sc_note, kn, kn_selnext);
+ ACPI_UNLOCK(sc);
+
+ return (0);
+}
diff --git a/sys/dev/acpi/acpireg.h b/sys/dev/acpi/acpireg.h
new file mode 100644
index 00000000000..9b3c965ffe8
--- /dev/null
+++ b/sys/dev/acpi/acpireg.h
@@ -0,0 +1,428 @@
+/* $OpenBSD: acpireg.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */
+/*
+ * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* Root System Descriptor Pointer */
+struct acpi_rsdp1 {
+ u_int8_t signature[8];
+#define RSDP_SIG "RSD PTR "
+#define rsdp_signaturee rsdp1.signature
+ u_int8_t checksum; /* make sum == 0 */
+#define rsdp_checksum rsdp1.checksum
+ u_int8_t oemid[6];
+#define rsdp_oemid rsdp1.oemid
+ u_int8_t revision; /* 0 for 1, 2 for 2 */
+#define rsdp_revision rsdp1.revision
+ u_int32_t rsdt; /* physical */
+#define rsdp_rsdt rsdp1.rsdt
+} __packed;
+
+struct acpi_rsdp {
+ struct acpi_rsdp1 rsdp1;
+ /*
+ * The following values are only valid
+ * when rsdp_revision == 2
+ */
+ u_int32_t rsdp_length; /* length of rsdp */
+ u_int64_t rsdp_xsdt; /* physical */
+ u_int8_t rsdp_extchecksum; /* entire table */
+ u_int8_t rsdp_reserved[3]; /* must be zero */
+} __packed;
+
+struct acpi_table_header {
+ u_int8_t signature[4];
+#define hdr_signature hdr.signature
+ u_int32_t length;
+#define hdr_length hdr.length
+ u_int8_t revision;
+#define hdr_revision hdr.revision
+ u_int8_t checksum;
+#define hdr_checksum hdr.checksum
+ u_int8_t oemid[6];
+#define hdr_oemid hdr.oemid
+ u_int8_t oemtableid[8];
+#define hdr_oemtableid hdr.oemtableid
+ u_int32_t oemrevision;
+#define hdr_oemrevision hdr.oemrevision
+ u_int8_t aslcompilerid[4];
+#define hdr_aslcompilerid hdr.aslcompilerid
+ u_int32_t aslcompilerrevision;
+#define hdr_aslcompilerrevision hdr.aslcompilerrevision
+} __packed;
+
+struct acpi_rsdt {
+ struct acpi_table_header hdr;
+#define RSDT_SIG "RSDT"
+ u_int32_t table_offsets[1];
+} __packed;
+
+struct acpi_xsdt {
+ struct acpi_table_header hdr;
+#define XSDT_SIG "XSDT"
+ u_int64_t table_offsets[1];
+} __packed;
+
+struct acpi_gas {
+ u_int8_t address_space_id;
+#define GAS_SYSTEM_MEMORY 0
+#define GAS_SYSTEM_IOSPACE 1
+#define GAS_PCI_CFG_SPACE 2
+#define GAS_EMBEDDED 3
+#define GAS_SMBUS 4
+#define GAS_FUNCTIONAL_FIXED 127
+ u_int8_t register_bit_width;
+ u_int8_t register_bit_offset;
+ u_int8_t access_size;
+#define GAS_ACCESS_UNDEFINED 0
+#define GAS_ACCESS_BYTE 1
+#define GAS_ACCESS_WORD 2
+#define GAS_ACCESS_DWORD 3
+#define GAS_ACCESS_QWORD 4
+ u_int64_t address;
+} __packed;
+
+struct acpi_fadt {
+ struct acpi_table_header hdr;
+#define FADT_SIG "FACP"
+ u_int32_t firmware_ctl; /* phys addr FACS */
+ u_int32_t dsdt; /* phys addr DSDT */
+ u_int8_t int_model; /* interrupt model (hdr_revision < 3) */
+#define FADT_INT_DUAL_PIC 0
+#define FADT_INT_MULTI_APIC 1
+ u_int8_t pm_profile; /* power mgmt profile */
+#define FADT_PM_UNSPEC 0
+#define FADT_PM_DESKTOP 1
+#define FADT_PM_MOBILE 2
+#define FADT_PM_WORKSTATION 3
+#define FADT_PM_ENT_SERVER 4
+#define FADT_PM_SOHO_SERVER 5
+#define FADT_PM_APPLIANCE 6
+#define FADT_PM_PERF_SERVER 7
+ u_int16_t sci_int; /* SCI interrupt */
+ u_int32_t smi_cmd; /* SMI command port */
+ u_int8_t acpi_enable; /* value to enable */
+ u_int8_t acpi_disable; /* value to disable */
+ u_int8_t s4bios_req; /* value for S4 */
+ u_int8_t pstate_cnt; /* value for performance (hdr_revision > 2) */
+ u_int32_t pm1a_evt_blk; /* power management 1a */
+ u_int32_t pm1b_evt_blk; /* power mangement 1b */
+ u_int32_t pm1a_cnt_blk; /* pm control 1a */
+ u_int32_t pm1b_cnt_blk; /* pm control 1b */
+ u_int32_t pm2_cnt_blk; /* pm control 2 */
+ u_int32_t pm_tmr_blk;
+ u_int32_t gpe0_blk;
+ u_int32_t gpe1_blk;
+ u_int8_t pm1_evt_len;
+ u_int8_t pm1_cnt_len;
+ u_int8_t pm2_cnt_len;
+ u_int8_t pm_tmr_len;
+ u_int8_t gpe0_blk_len;
+ u_int8_t gpe1_blk_len;
+ u_int8_t gpe1_base;
+ u_int8_t cst_cnt; /* (hdr_revision > 2) */
+ u_int16_t p_lvl2_lat;
+ u_int16_t p_lvl3_lat;
+ u_int16_t flush_size;
+ u_int16_t flush_stride;
+ u_int8_t duty_offset;
+ u_int8_t duty_width;
+ u_int8_t day_alrm;
+ u_int8_t mon_alrm;
+ u_int8_t century;
+ u_int16_t iapc_boot_arch; /* (hdr_revision > 2) */
+#define FADT_LEGACY_DEVICES 0x0001 /* Legacy devices supported */
+#define FADT_i8042 0x0002 /* Keyboard controller present */
+#define FADT_NO_VGA 0x0004 /* Do not probe VGA */
+ u_int8_t reserved1;
+ u_int32_t flags;
+#define FADT_WBINVD 0x00000001
+#define FADT_WBINVD_FLUSH 0x00000002
+#define FADT_PROC_C1 0x00000004
+#define FADT_P_LVL2_UP 0x00000008
+#define FADT_PWR_BUTTON 0x00000010
+#define FADT_SLP_BUTTON 0x00000020
+#define FADT_FIX_RTC 0x00000040
+#define FADT_RTC_S4 0x00000080
+#define FADT_TMR_VAL_EXT 0x00000100
+#define FADT_DCK_CAP 0x00000200
+#define FADT_RESET_REG_SUP 0x00000400
+#define FADT_SEALED_CASE 0x00000800
+#define FADT_HEADLESS 0x00001000
+#define FADT_CPU_SW_SLP 0x00002000
+#define FADT_PCI_EXP_WAK 0x00004000
+#define FADT_USE_PLATFORM_CLOCK 0x00008000
+#define FADT_S4_RTC_STS_VALID 0x00010000
+#define FADT_REMOTE_POWER_ON_CAPABLE 0x00020000
+#define FADT_FORCE_APIC_CLUSTER_MODEL 0x00040000
+#define FADT_FORCE_APIC_PHYS_DEST_MODE 0x00080000
+ /*
+ * Following values only exist when rev > 1
+ * If the extended addresses exists, they
+ * must be used in preferense to the non-
+ * extended values above
+ */
+ struct acpi_gas reset_reg;
+ u_int8_t reset_value;
+ u_int8_t reserved2a;
+ u_int8_t reserved2b;
+ u_int8_t reserved2c;
+ u_int64_t x_firmware_ctl;
+ u_int64_t x_dsdt;
+ struct acpi_gas x_pm1a_evt_blk;
+ struct acpi_gas x_pm1b_evt_blk;
+ struct acpi_gas x_pm1a_cnt_blk;
+ struct acpi_gas x_pm1b_cnt_blk;
+ struct acpi_gas x_pm2_cnt_blk;
+ struct acpi_gas x_pm_tmr_blk;
+ struct acpi_gas x_gpe0_blk;
+ struct acpi_gas x_gpe1_blk;
+} __packed;
+
+struct acpi_dsdt {
+ struct acpi_table_header hdr;
+#define DSDT_SIG "DSDT"
+ u_int8_t aml[1];
+} __packed;
+
+struct acpi_ssdt {
+ struct acpi_table_header hdr;
+#define SSDT_SIG "SSDT"
+ u_int8_t aml[1];
+} __packed;
+
+/*
+ * Table deprecated by ACPI 2.0
+ */
+struct acpi_psdt {
+ struct acpi_table_header hdr;
+#define PSDT_SIG "PSDT"
+} __packed;
+
+struct acpi_madt {
+ struct acpi_table_header hdr;
+#define MADT_SIG "APIC"
+ u_int32_t local_apic_address;
+ u_int32_t flags;
+#define ACPI_APIC_PCAT_COMPAT 0x00000001
+} __packed;
+
+struct acpi_madt_lapic {
+ u_int8_t apic_type;
+#define ACPI_MADT_LAPIC 0
+ u_int8_t length;
+ u_int8_t acpi_proc_id;
+ u_int8_t apic_id;
+ u_int32_t flags;
+#define ACPI_PROC_ENABLE 0x00000001
+} __packed;
+
+struct acpi_madt_ioapic {
+ u_int8_t apic_type;
+#define ACPI_MADT_IOAPIC 1
+ u_int8_t length;
+ u_int8_t acpi_ioapic_id;
+ u_int8_t reserved;
+ u_int32_t address;
+ u_int32_t global_int_base;
+} __packed;
+
+struct acpi_madt_override {
+ u_int8_t apic_type;
+#define ACPI_MADT_OVERRIDE 2
+ u_int8_t length;
+ u_int8_t bus;
+#define ACPI_OVERRIDE_BUS_ISA 0
+ u_int8_t source;
+ u_int32_t global_int;
+ u_int16_t flags;
+#define ACPI_OVERRIDE_POLARITY_BITS 0x3
+#define ACPI_OVERRIDE_POLARITY_BUS 0x0
+#define ACPI_OVERRIDE_POLARITY_HIGH 0x1
+#define ACPI_OVERRIDE_POLARITY_LOW 0x3
+#define ACPI_OVERRIDE_TRIGGER_BITS 0xc
+#define ACPI_OVERRIDE_TRIGGER_BUS 0x0
+#define ACPI_OVERRIDE_TRIGGER_EDGE 0x4
+#define ACPI_OVERRIDE_TRIGGER_LEVEL 0xc
+} __packed;
+
+struct acpi_madt_nmi {
+ u_int8_t apic_type;
+#define ACPI_MADT_NMI 3
+ u_int8_t length;
+ u_int16_t flags; /* Same flags as acpi_madt_override */
+ u_int32_t global_int;
+} __packed;
+
+struct acpi_madt_lapic_nmi {
+ u_int8_t apic_type;
+#define ACPI_MADT_LAPIC_NMI 4
+ u_int8_t length;
+ u_int8_t acpi_proc_id;
+ u_int16_t flags; /* Same flags as acpi_madt_override */
+ u_int8_t local_apic_lint;
+} __packed;
+
+struct acpi_madt_lapic_override {
+ u_int8_t apic_type;
+#define ACPI_MADT_LAPIC_OVERRIDE 5
+ u_int8_t length;
+ u_int16_t reserved;
+ u_int64_t lapic_address;
+} __packed;
+
+struct acpi_madt_io_sapic {
+ u_int8_t apic_type;
+#define ACPI_MADT_IO_SAPIC 6
+ u_int8_t length;
+ u_int8_t iosapic_id;
+ u_int8_t reserved;
+ u_int32_t global_int_base;
+ u_int64_t iosapic_address;
+} __packed;
+
+struct acpi_madt_local_sapic {
+ u_int8_t apic_type;
+#define ACPI_MADT_LOCAL_SAPIC 7
+ u_int8_t length;
+ u_int8_t acpi_proc_id;
+ u_int8_t local_sapic_id;
+ u_int8_t local_sapic_eid;
+ u_int8_t reserved[3];
+ u_int32_t flags; /* Same flags as acpi_madt_lapic */
+ u_int32_t acpi_proc_uid;
+ u_int8_t acpi_proc_uid_string[1];
+} __packed;
+
+struct acpi_madt_platform_int {
+ u_int8_t apic_type;
+#define ACPI_MADT_PLATFORM_INT 8
+ u_int8_t length;
+ u_int16_t flags; /* Same flags as acpi_madt_override */
+ u_int8_t int_type;
+#define ACPI_MADT_PLATFORM_PMI 1
+#define ACPI_MADT_PLATFORM_INIT 2
+#define ACPI_MADT_PLATFORM_CORR_ERROR 3
+ u_int8_t proc_id;
+ u_int8_t proc_eid;
+ u_int8_t io_sapic_vec;
+ u_int32_t global_int;
+ u_int32_t platform_int_flags;
+#define ACPI_MADT_PLATFORM_CPEI 0x00000001
+} __packed;
+
+union acpi_madt_entry {
+ struct acpi_madt_lapic madt_lapic;
+ struct acpi_madt_ioapic madt_ioapic;
+ struct acpi_madt_override madt_override;
+ struct acpi_madt_nmi madt_nmi;
+ struct acpi_madt_lapic_nmi madt_lapic_nmi;
+ struct acpi_madt_lapic_override madt_lapic_override;
+ struct acpi_madt_io_sapic madt_io_sapic;
+ struct acpi_madt_local_sapic madt_local_sapic;
+ struct acpi_madt_platform_int madt_platform_int;
+} __packed;
+
+struct acpi_sbst {
+ struct acpi_table_header hdr;
+#define SBST_SIG "SBST"
+ u_int32_t warning_energy_level;
+ u_int32_t low_energy_level;
+ u_int32_t critical_energy_level;
+} __packed;
+
+struct acpi_ecdt {
+ struct acpi_table_header hdr;
+#define ECDT_SIG "ECDT"
+ struct acpi_gas ec_control;
+ struct acpi_gas ec_data;
+ u_int32_t uid;
+ u_int8_t gpe_bit;
+ u_int8_t ec_id[1];
+} __packed;
+
+struct acpi_srat {
+ struct acpi_table_header hdr;
+#define SRAT_SIG "SRAT"
+ u_int32_t reserved1;
+ u_int64_t reserved2;
+} __packed;
+
+struct acpi_slit {
+ struct acpi_table_header hdr;
+#define SLIT_SIG "SLIT"
+ u_int64_t number_of_localities;
+} __packed;
+
+struct acpi_hpet {
+ struct acpi_table_header hdr;
+#define HPET_SIG "HPET"
+ u_int32_t event_timer_block_id;
+ struct acpi_gas base_address;
+ u_int8_t hpet_number;
+ u_int16_t main_counter_min_clock_tick;
+ u_int8_t page_protection;
+} __packed;
+
+struct acpi_facs {
+ u_int8_t signature[4];
+#define FACS_SIG "FACS"
+ u_int32_t length;
+ u_int32_t hardware_signature;
+ u_int32_t wakeup_vector;
+ u_int32_t global_lock;
+#define FACS_LOCK_PENDING 0x00000001
+#define FACS_LOCK_OWNED 0x00000002
+ u_int32_t flags;
+#define FACS_S4BIOS_F 0x00000001 /* S4BIOS_REQ supported */
+ struct acpi_gas x_wakeup_vector;
+ u_int8_t version;
+ u_int8_t reserved[31];
+} __packed;
+
+#define ACPI_FREQUENCY 3579545 /* Per ACPI spec */
+
+/*
+ * PM1 Status Registers Fixed Hardware Feature Status Bits
+ */
+#define ACPI_PM1_STATUS 0x00
+#define ACPI_PM1_TMR_STS 0x0001
+#define ACPI_PM1_BM_STS 0x0010
+#define ACPI_PM1_GBL_STS 0x0020
+#define ACPI_PM1_PWRBTN_STS 0x0100
+#define ACPI_PM1_SLPBTN_STS 0x0200
+#define ACPI_PM1_RTC_STS 0x0400
+#define ACPI_PM1_PCIEXP_WAKE_STS 0x4000
+#define ACPI_PM1_WAK_STS 0x8000
+
+/*
+ * PM1 Enable Registers
+ */
+#define ACPI_PM1_ENABLE 0x02
+#define ACPI_PM1_TMR_EN 0x0001
+#define ACPI_PM1_GBL_EN 0x0020
+#define ACPI_PM1_PWRBTN_EN 0x0100
+#define ACPI_PM1_SLPBTN_EN 0x0200
+#define ACPI_PM1_RTC_EN 0x0400
+#define ACPI_PM1_PCIEXP_WAKE_DIS 0x4000
+
+/*
+ * PM1 Control Registers
+ */
+#define ACPI_PM1_CONTROL 0x00
+#define ACPI_PM1_SCI_EN 0x0001
+#define ACPI_PM1_BM_RLD 0x0002
+#define ACPI_PM1_GBL_RLS 0x0004
+#define ACPI_PM1_SLP_EN 0x2000
diff --git a/sys/dev/acpi/acpitimer.c b/sys/dev/acpi/acpitimer.c
new file mode 100644
index 00000000000..2cf89d6efda
--- /dev/null
+++ b/sys/dev/acpi/acpitimer.c
@@ -0,0 +1,152 @@
+/* $OpenBSD: acpitimer.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */
+/*
+ * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#ifdef __HAVE_TIMECOUNTER
+#include <sys/timetc.h>
+#endif
+
+#include <machine/bus.h>
+
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+
+int acpitimermatch(struct device *, void *, void *);
+void acpitimerattach(struct device *, struct device *, void *);
+
+#ifdef __HAVE_TIMECOUNTER
+u_int acpi_get_timecount(struct timecounter *tc);
+
+static struct timecounter acpi_timecounter = {
+ acpi_get_timecount, /* get_timecount */
+ 0, /* no poll_pps */
+ 0x00ffffff, /* counter_mask (24 bits) */
+ ACPI_FREQUENCY, /* frequency */
+ 0, /* name */
+ 1000 /* quality */
+};
+#endif
+
+struct acpitimer_softc {
+ struct device sc_dev;
+
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+};
+
+struct cfattach acpitimer_ca = {
+ sizeof(struct acpitimer_softc), acpitimermatch, acpitimerattach
+};
+
+struct cfdriver acpitimer_cd = {
+ NULL, "acpitimer", DV_DULL
+};
+
+int
+acpitimermatch(struct device *parent, void *match, void *aux)
+{
+ struct acpi_attach_args *aa = aux;
+ struct cfdata *cf = match;
+
+ /* sanity */
+ if (aa->aaa_name == NULL ||
+ strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 ||
+ aa->aaa_table != NULL)
+ return (0);
+
+ return (1);
+}
+
+void
+acpitimerattach(struct device *parent, struct device *self, void *aux)
+{
+ struct acpitimer_softc *sc = (struct acpitimer_softc *) self;
+ struct acpi_softc *psc = (struct acpi_softc *) parent;
+ struct acpi_attach_args *aa = aux;
+ bus_addr_t address;
+ bus_size_t size;
+
+ if (psc->sc_fadt->hdr_revision > 1) {
+ switch (psc->sc_fadt->x_pm_tmr_blk.address_space_id) {
+ case GAS_SYSTEM_MEMORY:
+ sc->sc_iot = aa->aaa_memt;
+ break;
+
+ case GAS_SYSTEM_IOSPACE:
+ sc->sc_iot = aa->aaa_iot;
+ break;
+
+#if 0
+ case GAS_SYSTEM_PCI_CFG_SPACE:
+ sc->sc_iot = aa->aaa_pcit;
+ break;
+
+ case GAS_SYSTEM_SMBUS:
+ sc->sc_iot = aa->aaa_smbust;
+ break;
+#endif
+
+ default:
+ printf(": can't identify bus\n");
+ return;
+ }
+ address = psc->sc_fadt->x_pm_tmr_blk.address;
+ }
+ else {
+ sc->sc_iot = aa->aaa_iot;
+ address = psc->sc_fadt->pm_tmr_blk;
+ }
+ size = psc->sc_fadt->pm_tmr_len;
+
+ if (bus_space_map(sc->sc_iot, address, size, 0, &sc->sc_ioh)) {
+ printf(": can't map i/o space\n");
+ return;
+ }
+
+ printf(": %ld Hz, %d bits\n", ACPI_FREQUENCY,
+ psc->sc_fadt->flags & FADT_TMR_VAL_EXT ? 32 : 24);
+
+#ifdef __HAVE_TIMECOUNTER
+ if (psc->sc_fadt->flags & FADT_TMR_VAL_EXT)
+ acpi_timecounter.tc_counter_mask = 0xffffffffU;
+ acpi_timecounter.tc_priv = sc;
+ acpi_timecounter.tc_name = sc->sc_dev.dv_xname;
+ tc_init(&acpi_timecounter);
+#endif
+}
+
+
+#ifdef __HAVE_TIMECOUNTER
+u_int
+acpi_get_timecount(struct timecounter *tc)
+{
+ struct acpitimer_softc *sc = tc->tc_priv;
+ u_int u1, u2, u3;
+
+ u2 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 0);
+ u3 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 0);
+ do {
+ u1 = u2;
+ u2 = u3;
+ u3 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 0);
+ } while (u1 > u2 || u2 > u3);
+ return (u2);
+}
+#endif
diff --git a/sys/dev/acpi/acpiutil.c b/sys/dev/acpi/acpiutil.c
new file mode 100644
index 00000000000..c364c97d03b
--- /dev/null
+++ b/sys/dev/acpi/acpiutil.c
@@ -0,0 +1,42 @@
+/* $OpenBSD: acpiutil.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */
+/*
+ * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+
+u_int
+acpi_checksum(const void *v, size_t len)
+{
+ const u_char *p = v;
+ u_char s;
+ int i;
+
+ s = 0;
+ for (i = 0; i < len; i++)
+ s += p[i];
+
+ if (s)
+ printf("acpi: bad checksum at %p\n", v);
+
+ return (s);
+}
diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h
new file mode 100644
index 00000000000..b654a45bba4
--- /dev/null
+++ b/sys/dev/acpi/acpivar.h
@@ -0,0 +1,111 @@
+/* $OpenBSD: acpivar.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */
+/*
+ * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/timeout.h>
+
+struct klist;
+
+struct acpi_attach_args {
+ char *aaa_name;
+ bus_space_tag_t aaa_iot;
+ bus_space_tag_t aaa_memt;
+ void *aaa_table;
+ paddr_t aaa_pbase; /* Physical base address of ACPI tables */
+};
+
+struct acpi_mem_map {
+ vaddr_t baseva;
+ u_int8_t *va;
+ size_t vsize;
+ paddr_t pa;
+};
+
+struct acpi_q {
+ SIMPLEQ_ENTRY(acpi_q) q_next;
+ void *q_table;
+ u_int8_t q_data[0];
+};
+
+typedef SIMPLEQ_HEAD(, acpi_q) acpi_qhead_t;
+
+struct acpi_softc {
+ struct device sc_dev;
+
+ bus_space_tag_t sc_iot;
+ bus_space_tag_t sc_memt;
+#if 0
+ bus_space_tag_t sc_pcit;
+ bus_space_tag_t sc_smbust;
+#endif
+
+ /*
+ * First-level ACPI tables
+ */
+ struct acpi_fadt *sc_fadt;
+ acpi_qhead_t sc_tables;
+
+ /*
+ * Second-level information from FADT
+ */
+ struct acpi_facs *sc_facs; /* Shared with firmware! */
+
+ struct klist *sc_note;
+ bus_space_handle_t sc_ioh_pm1a_evt;
+
+ void *sc_interrupt;
+#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
+ void *sc_softih;
+#else
+ struct timeout sc_timeout;
+#endif
+
+ int sc_powerbtn;
+ int sc_sleepbtn;
+};
+
+struct acpi_table {
+ int offset;
+ size_t size;
+ void *table;
+};
+
+#define ACPI_IOC_GETFACS _IOR('A', 0, struct acpi_facs)
+#define ACPI_IOC_GETTABLE _IOWR('A', 1, struct acpi_table)
+
+#define ACPI_EV_PWRBTN 0x0001 /* Power button was pushed */
+#define ACPI_EV_SLPBTN 0x0002 /* Sleep button was pushed */
+
+#define ACPI_EVENT_MASK 0x0003
+
+#define ACPI_EVENT_COMPOSE(t,i) (((i) & 0x7fff) << 16 | ((t) & ACPI_EVENT_MASK))
+#define ACPI_EVENT_TYPE(e) ((e) & ACPI_EVENT_MASK)
+#define ACPI_EVENT_INDEX(e) ((e) >> 16)
+
+/*
+ * Sleep states
+ */
+#define ACPI_STATE_S5 5
+
+#if defined(_KERNEL)
+int acpi_map(paddr_t, size_t, struct acpi_mem_map *);
+void acpi_unmap(struct acpi_mem_map *);
+int acpi_probe(struct device *, struct cfdata *, struct acpi_attach_args *);
+u_int acpi_checksum(const void *, size_t);
+void acpi_attach_machdep(struct acpi_softc *);
+int acpi_interrupt(void *);
+void acpi_enter_sleep_state(struct acpi_softc *, int);
+#endif
diff --git a/sys/dev/acpi/files.acpi b/sys/dev/acpi/files.acpi
new file mode 100644
index 00000000000..c03ba10e83e
--- /dev/null
+++ b/sys/dev/acpi/files.acpi
@@ -0,0 +1,20 @@
+# $OpenBSD: files.acpi,v 1.1 2005/06/02 20:09:39 tholo Exp $
+#
+# Config file and device description for machine-independent ACPI code.
+# Included by ports that need it.
+
+define acpi {}
+device acpi
+attach acpi at mainbus
+file dev/acpi/acpi.c acpi needs-flag
+file dev/acpi/acpiutil.c acpi
+
+# ACPI timer
+device acpitimer
+attach acpitimer at acpi
+file dev/acpi/acpitimer.c acpitimer
+
+# High Precision Event Timer
+device hpet
+attach hpet at acpi
+file dev/acpi/hpet.c hpet \ No newline at end of file
diff --git a/sys/dev/acpi/hpet.c b/sys/dev/acpi/hpet.c
new file mode 100644
index 00000000000..e79e7a42627
--- /dev/null
+++ b/sys/dev/acpi/hpet.c
@@ -0,0 +1,144 @@
+/* $OpenBSD: hpet.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */
+/*
+ * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#ifdef __HAVE_TIMECOUNTER
+#include <sys/timetc.h>
+#endif
+
+#include <machine/bus.h>
+
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+#include <dev/acpi/hpetreg.h>
+
+int hpetmatch(struct device *, void *, void *);
+void hpetattach(struct device *, struct device *, void *);
+
+#ifdef __HAVE_TIMECOUNTER
+u_int hpet_get_timecount(struct timecounter *tc);
+
+static struct timecounter hpet_timecounter = {
+ hpet_get_timecount, /* get_timecount */
+ 0, /* no poll_pps */
+ 0xffffffff, /* counter_mask (24 bits) */
+ 0, /* frequency */
+ 0, /* name */
+ 1000 /* quality */
+};
+#endif
+
+struct hpet_softc {
+ struct device sc_dev;
+
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+};
+
+struct cfattach hpet_ca = {
+ sizeof(struct hpet_softc), hpetmatch, hpetattach
+};
+
+struct cfdriver hpet_cd = {
+ NULL, "hpet", DV_DULL
+};
+
+int
+hpetmatch(struct device *parent, void *match, void *aux)
+{
+ struct acpi_attach_args *aaa = aux;
+ struct acpi_table_header *hdr;
+
+ /*
+ * If we do not have a table, it is not us
+ */
+ if (aaa->aaa_table == NULL)
+ return (0);
+
+ /*
+ * If it is an HPET table, we can attach
+ */
+ hdr = (struct acpi_table_header *)aaa->aaa_table;
+ if (memcmp(hdr->signature, HPET_SIG, sizeof(HPET_SIG) - 1) != 0)
+ return (0);
+
+ return (1);
+}
+
+void
+hpetattach(struct device *parent, struct device *self, void *aux)
+{
+ struct hpet_softc *sc = (struct hpet_softc *) self;
+ struct acpi_attach_args *aa = aux;
+ struct acpi_hpet *hpet = (struct acpi_hpet *)aa->aaa_table;
+ u_int64_t period, freq; /* timer period in femtoseconds (10^-15) */
+
+ switch (hpet->base_address.address_space_id) {
+ case GAS_SYSTEM_MEMORY:
+ sc->sc_iot = aa->aaa_memt;
+ break;
+
+ case GAS_SYSTEM_IOSPACE:
+ sc->sc_iot = aa->aaa_iot;
+ break;
+
+#if 0
+ case GAS_SYSTEM_PCI_CFG_SPACE:
+ sc->sc_iot = aa->aaa_pcit;
+ break;
+
+ case GAS_SYSTEM_SMBUS:
+ sc->sc_iot = aa->aaa_smbust;
+ break;
+#endif
+
+ default:
+ printf(": can't identify bus\n");
+ return;
+ }
+
+ if (bus_space_map(sc->sc_iot, hpet->base_address.address, HPET_REG_SIZE,
+ 0, &sc->sc_ioh)) {
+ printf(": can't map i/o space\n");
+ return;
+ }
+
+ period = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+ HPET_CAPABILITIES + sizeof(u_int32_t));
+ freq = 1000000000000000ull / period;
+ printf(": %lld Hz\n", freq);
+
+#ifdef __HAVE_TIMECOUNTER
+ hpet_timecounter.tc_frequency = (u_int32_t)freq;
+ hpet_timecounter.tc_priv = sc;
+ hpet_timecounter.tc_name = sc->sc_dev.dv_xname;
+ tc_init(&hpet_timecounter);
+#endif
+}
+
+#ifdef __HAVE_TIMECOUNTER
+u_int
+hpet_get_timecount(struct timecounter *tc)
+{
+ struct hpet_softc *sc = tc->tc_priv;
+
+ return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, HPET_MAIN_COUNTER));
+}
+#endif
diff --git a/sys/dev/acpi/hpetreg.h b/sys/dev/acpi/hpetreg.h
new file mode 100644
index 00000000000..7c5bae72a82
--- /dev/null
+++ b/sys/dev/acpi/hpetreg.h
@@ -0,0 +1,32 @@
+/* $OpenBSD: hpetreg.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */
+/*
+ * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define HPET_REG_SIZE 1024
+
+#define HPET_CAPABILITIES 0x000
+#define HPET_CONFIGURATION 0x010
+#define HPET_INTERRUPT_STATUS 0x020
+#define HPET_MAIN_COUNTER 0x0F0
+#define HPET_TIMER0_CONFIG 0x100
+#define HPET_TIMER0_COMPARE 0x108
+#define HPET_TIMER0_INTERRUPT 0x110
+#define HPET_TIMER1_CONFIG 0x200
+#define HPET_TIMER1_COMPARE 0x208
+#define HPET_TIMER1_INTERRUPT 0x310
+#define HPET_TIMER2_CONFIG 0x400
+#define HPET_TIMER2_COMPARE 0x408
+#define HPET_TIMER2_INTERRUPT 0x510