summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/amd64/amd64/acpi_machdep.c154
-rw-r--r--sys/arch/amd64/amd64/conf.c4
-rw-r--r--sys/arch/amd64/amd64/machdep.c16
-rw-r--r--sys/arch/amd64/amd64/mainbus.c24
-rw-r--r--sys/arch/amd64/conf/GENERIC9
-rw-r--r--sys/arch/amd64/conf/files.amd648
-rw-r--r--sys/arch/amd64/include/conf.h9
-rw-r--r--sys/arch/i386/conf/GENERIC9
-rw-r--r--sys/arch/i386/conf/files.i3865
-rw-r--r--sys/arch/i386/i386/acpi_machdep.c175
-rw-r--r--sys/arch/i386/i386/conf.c4
-rw-r--r--sys/arch/i386/i386/mainbus.c21
-rw-r--r--sys/arch/i386/include/conf.h10
-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
21 files changed, 1957 insertions, 17 deletions
diff --git a/sys/arch/amd64/amd64/acpi_machdep.c b/sys/arch/amd64/amd64/acpi_machdep.c
new file mode 100644
index 00000000000..c9596fe5368
--- /dev/null
+++ b/sys/arch/amd64/amd64/acpi_machdep.c
@@ -0,0 +1,154 @@
+/* $OpenBSD: acpi_machdep.c,v 1.1 2005/06/02 20:09:38 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/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/bus.h>
+#include <machine/biosvar.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+
+#define ACPI_BIOS_RSDP_WINDOW_BASE 0xe0000
+#define ACPI_BIOS_RSDP_WINDOW_SIZE 0x20000
+
+u_int8_t *acpi_scan(struct acpi_mem_map *, paddr_t, size_t);
+
+int
+acpi_map(paddr_t pa, size_t len, struct acpi_mem_map *handle)
+{
+ paddr_t pgpa = x86_trunc_page(pa);
+ paddr_t endpa = x86_round_page(pa + len);
+ vaddr_t va = uvm_km_valloc(kernel_map, endpa - pgpa);
+
+ if (va == 0)
+ return (ENOMEM);
+
+ handle->baseva = va;
+ handle->va = (u_int8_t *)(va + (pa & PGOFSET));
+ handle->vsize = endpa - pgpa;
+ handle->pa = pa;
+
+ do {
+ pmap_kenter_pa(va, pgpa, VM_PROT_READ);
+ va += NBPG;
+ pgpa += NBPG;
+ } while (pgpa < endpa);
+
+ return 0;
+}
+
+void
+acpi_unmap(struct acpi_mem_map *handle)
+{
+ pmap_kremove(handle->baseva, handle->vsize);
+ uvm_km_free(kernel_map, handle->baseva, handle->vsize);
+}
+
+u_int8_t *
+acpi_scan(struct acpi_mem_map *handle, paddr_t pa, size_t len)
+{
+ size_t i;
+ u_int8_t *ptr;
+ struct acpi_rsdp1 *rsdp;
+
+ if (acpi_map(pa, len, handle))
+ return (NULL);
+ for (ptr = handle->va, i = 0;
+ i < len;
+ ptr += 16, i += 16)
+ if (memcmp(ptr, RSDP_SIG, sizeof(RSDP_SIG) - 1) == 0) {
+ rsdp = (struct acpi_rsdp1 *)ptr;
+ /*
+ * Only checksum whichever portion of the
+ * RSDP that is actually present
+ */
+ if (rsdp->revision == 0 &&
+ acpi_checksum(ptr, sizeof(struct acpi_rsdp1)) == 0)
+ return (ptr);
+ else if (rsdp->revision == 2 &&
+ acpi_checksum(ptr, sizeof(struct acpi_rsdp)) == 0)
+ return (ptr);
+ }
+ acpi_unmap(handle);
+
+ return (NULL);
+}
+
+int
+acpi_probe(struct device *parent, struct cfdata *match, struct acpi_attach_args *aaa)
+{
+ struct acpi_mem_map handle;
+ u_int8_t *ptr;
+ paddr_t ebda;
+ bios_memmap_t *im;
+
+ /*
+ * First look for ACPI entries in the BIOS memory map
+ */
+ for (im = bios_memmap; im->type != BIOS_MAP_END; im++)
+ if (im->type == BIOS_MAP_ACPI) {
+ if ((ptr = acpi_scan(&handle, im->addr, im->size)))
+ goto havebase;
+ }
+
+ /*
+ * Next try to find ACPI table entries in the EBDA
+ */
+ if (acpi_map(0, NBPG, &handle))
+ printf("acpi: failed to map BIOS data area\n");
+ else {
+ ebda = *(const u_int16_t *)(&handle.va[0x40e]);
+ ebda <<= 4;
+ acpi_unmap(&handle);
+
+ if (ebda && ebda < IOM_BEGIN) {
+ if ((ptr = acpi_scan(&handle, ebda, 1024)))
+ goto havebase;
+ }
+ }
+
+ /*
+ * Finally try to find the ACPI table entries in the
+ * BIOS memory
+ */
+ if ((ptr = acpi_scan(&handle, ACPI_BIOS_RSDP_WINDOW_BASE,
+ ACPI_BIOS_RSDP_WINDOW_SIZE)))
+ goto havebase;
+
+ return (0);
+
+havebase:
+ aaa->aaa_pbase = ptr - handle.va + handle.pa;
+ acpi_unmap(&handle);
+
+ return (1);
+}
+
+void
+acpi_attach_machdep(struct acpi_softc *sc)
+{
+ sc->sc_interrupt = intr_establish(sc->sc_fadt->sci_int, &i8259_pic, sc->sc_fadt->sci_int,
+ IST_LEVEL, IPL_TTY, acpi_interrupt, sc, "acpi");
+}
diff --git a/sys/arch/amd64/amd64/conf.c b/sys/arch/amd64/amd64/conf.c
index ffa6fb787c9..d2fa2a4e57d 100644
--- a/sys/arch/amd64/amd64/conf.c
+++ b/sys/arch/amd64/amd64/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.6 2004/05/30 08:11:26 grange Exp $ */
+/* $OpenBSD: conf.c,v 1.7 2005/06/02 20:09:38 tholo Exp $ */
/*
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
@@ -159,6 +159,7 @@ cdev_decl(mcd);
#include "midi.h"
#include "sequencer.h"
cdev_decl(music);
+#include "acpi.h"
#include "iop.h"
#ifdef XFS
#include <xfs/nxfs.h>
@@ -297,6 +298,7 @@ struct cdevsw cdevsw[] =
cdev_notdef(), /* 80: gpr? XXX */
cdev_ptm_init(NPTY,ptm), /* 81: pseudo-tty ptm device */
cdev_hotplug_init(NHOTPLUG,hotplug), /* 82: devices hot plugging */
+ cdev_acpi_init(NACPI,acpi), /* 83: ACPI */
};
int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index 7ce605412d7..cdd4ffa0843 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.30 2004/08/03 00:56:22 art Exp $ */
+/* $OpenBSD: machdep.c,v 1.31 2005/06/02 20:09:38 tholo Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
@@ -131,16 +131,22 @@
#include <dev/isa/isareg.h>
#include <machine/isa_machdep.h>
#include <dev/ic/i8042reg.h>
+#include <dev/acpi/acpivar.h>
#ifdef DDB
#include <machine/db_machdep.h>
#include <ddb/db_extern.h>
#endif
+#include "acpi.h"
#include "isa.h"
#include "isadma.h"
#include "ksyms.h"
+#if NACPI > 0
+extern struct acpi_softc *acpi_softc;
+#endif
+
/* the following is used externally (sysctl_hw) */
char machine[] = "amd64"; /* cpu "architecture" */
char machine_arch[] = "amd64"; /* machine == machine_arch */
@@ -893,9 +899,11 @@ haltsys:
if (howto & RB_HALT) {
if (howto & RB_POWERDOWN) {
#if NACPI > 0
- delay(500000);
- acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5);
- printf("WARNING: powerdown failed!\n");
+ if (acpi_softc) {
+ delay(500000);
+ acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5);
+ printf("WARNING: powerdown failed!\n");
+ }
#endif
}
diff --git a/sys/arch/amd64/amd64/mainbus.c b/sys/arch/amd64/amd64/mainbus.c
index e4c5e6d32fd..8625cb64de5 100644
--- a/sys/arch/amd64/amd64/mainbus.c
+++ b/sys/arch/amd64/amd64/mainbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mainbus.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $OpenBSD: mainbus.c,v 1.2 2005/06/02 20:09:38 tholo Exp $ */
/* $NetBSD: mainbus.c,v 1.1 2003/04/26 18:39:29 fvdl Exp $ */
/*
@@ -44,14 +44,16 @@
#include "pci.h"
#include "isa.h"
+#include "acpi.h"
#include <machine/cpuvar.h>
#include <machine/i82093var.h>
#include <machine/mpbiosvar.h>
-/*
- * XXXfvdl ACPI
- */
+#if NACPI > 0
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+#endif
int mainbus_match(struct device *, void *, void *);
void mainbus_attach(struct device *, struct device *, void *);
@@ -72,6 +74,9 @@ union mainbus_attach_args {
struct isabus_attach_args mba_iba;
struct cpu_attach_args mba_caa;
struct apic_attach_args aaa_caa;
+#if NACPI > 0
+ struct acpi_attach_args mba_aaa;
+#endif
};
/*
@@ -131,6 +136,17 @@ mainbus_attach(parent, self, aux)
printf("\n");
+#if NACPI > 0
+ {
+ memset(&mba.mba_aaa, 0, sizeof(mba.mba_aaa));
+ mba.mba_aaa.aaa_name = "acpi";
+ mba.mba_aaa.aaa_iot = X86_BUS_SPACE_IO;
+ mba.mba_aaa.aaa_memt = X86_BUS_SPACE_MEM;
+
+ config_found(self, &mba.mba_aaa, mainbus_print);
+ }
+#endif
+
#ifdef MPBIOS
mpbios_present = mpbios_probe(self);
#endif
diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
index c213f546627..8d9be42b133 100644
--- a/sys/arch/amd64/conf/GENERIC
+++ b/sys/arch/amd64/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.70 2005/05/27 06:36:23 jason Exp $
+# $OpenBSD: GENERIC,v 1.71 2005/06/02 20:09:39 tholo Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -41,6 +41,13 @@ isa0 at mainbus0
#isa0 at pcib?
pci* at mainbus0
+#acpi0 at mainbus?
+#acpitimer* at acpi?
+#hpet* at acpi?
+
+#option ACPIVERBOSE
+#option ACPI_ENABLE
+
option PCIVERBOSE
option USBVERBOSE
diff --git a/sys/arch/amd64/conf/files.amd64 b/sys/arch/amd64/conf/files.amd64
index e77341ac1b3..f45e713e16f 100644
--- a/sys/arch/amd64/conf/files.amd64
+++ b/sys/arch/amd64/conf/files.amd64
@@ -1,4 +1,4 @@
-# $OpenBSD: files.amd64,v 1.11 2005/05/27 06:28:41 jason Exp $
+# $OpenBSD: files.amd64,v 1.12 2005/06/02 20:09:39 tholo Exp $
maxpartitions 16
maxusers 2 16 128
@@ -142,6 +142,12 @@ file dev/isa/fd.c fd needs-flag
include "dev/usb/files.usb"
#
+# ACPI
+#
+include "../../../dev/acpi/files.acpi"
+file arch/amd64/amd64/acpi_machdep.c acpi
+
+#
# device major numbers
#
diff --git a/sys/arch/amd64/include/conf.h b/sys/arch/amd64/include/conf.h
index 0eeee30a029..688c8eda04d 100644
--- a/sys/arch/amd64/include/conf.h
+++ b/sys/arch/amd64/include/conf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $OpenBSD: conf.h,v 1.2 2005/06/02 20:09:39 tholo Exp $ */
/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */
/*
@@ -43,3 +43,10 @@ cdev_decl(spkr);
#define biosselect seltrue
cdev_decl(bios);
+
+#define cdev_acpi_init(c,n) {\
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, (dev_type_poll((*))) enodev, \
+ (dev_type_mmap((*))) enodev, D_KQFILTER, dev_init(c,n,kqfilter) }
+cdev_decl(acpi);
diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC
index 42a9a622555..43c2cca9c6e 100644
--- a/sys/arch/i386/conf/GENERIC
+++ b/sys/arch/i386/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.416 2005/05/27 02:08:14 martin Exp $
+# $OpenBSD: GENERIC,v 1.417 2005/06/02 20:09:39 tholo Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -56,6 +56,13 @@ isa0 at gscpcib?
eisa0 at mainbus0
pci* at mainbus0
+#acpi0 at mainbus?
+#acpitimer* at acpi?
+#hpet* at acpi?
+
+option ACPIVERBOSE
+#option ACPI_ENABLE
+
option PCIVERBOSE
option EISAVERBOSE
option USBVERBOSE
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386
index c92ad29ca6c..a61bfa4fbf7 100644
--- a/sys/arch/i386/conf/files.i386
+++ b/sys/arch/i386/conf/files.i386
@@ -1,4 +1,4 @@
-# $OpenBSD: files.i386,v 1.134 2005/05/21 19:13:55 brad Exp $
+# $OpenBSD: files.i386,v 1.135 2005/06/02 20:09:39 tholo Exp $
#
# new style config file for i386 architecture
#
@@ -396,3 +396,6 @@ include "dev/i2c/files.i2c"
# Machine-independent GPIO drivers
#
include "dev/gpio/files.gpio"
+
+include "../../../dev/acpi/files.acpi"
+file arch/i386/i386/acpi_machdep.c acpi
diff --git a/sys/arch/i386/i386/acpi_machdep.c b/sys/arch/i386/i386/acpi_machdep.c
new file mode 100644
index 00000000000..51f674c2cd0
--- /dev/null
+++ b/sys/arch/i386/i386/acpi_machdep.c
@@ -0,0 +1,175 @@
+/* $OpenBSD: acpi_machdep.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/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/bus.h>
+#include <i386/isa/isa_machdep.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+
+#include "bios.h"
+#include "apm.h"
+
+#if NBIOS > 0
+#include <machine/biosvar.h>
+#endif
+
+#define ACPI_BIOS_RSDP_WINDOW_BASE 0xe0000
+#define ACPI_BIOS_RSDP_WINDOW_SIZE 0x20000
+
+#if NAPM > 0 && NBIOS > 0
+extern bios_apminfo_t *apm;
+#endif
+
+u_int8_t *acpi_scan(struct acpi_mem_map *, paddr_t, size_t);
+
+int
+acpi_map(paddr_t pa, size_t len, struct acpi_mem_map *handle)
+{
+ paddr_t pgpa = i386_trunc_page(pa);
+ paddr_t endpa = i386_round_page(pa + len);
+ vaddr_t va = uvm_km_valloc(kernel_map, endpa - pgpa);
+
+ if (va == 0)
+ return (ENOMEM);
+
+ handle->baseva = va;
+ handle->va = (u_int8_t *)(va + (pa & PGOFSET));
+ handle->vsize = endpa - pgpa;
+ handle->pa = pa;
+
+ do {
+ pmap_kenter_pa(va, pgpa, VM_PROT_READ);
+ va += NBPG;
+ pgpa += NBPG;
+ } while (pgpa < endpa);
+
+ return 0;
+}
+
+void
+acpi_unmap(struct acpi_mem_map *handle)
+{
+ pmap_kremove(handle->baseva, handle->vsize);
+ uvm_km_free(kernel_map, handle->baseva, handle->vsize);
+}
+
+u_int8_t *
+acpi_scan(struct acpi_mem_map *handle, paddr_t pa, size_t len)
+{
+ size_t i;
+ u_int8_t *ptr;
+ struct acpi_rsdp1 *rsdp;
+
+ if (acpi_map(pa, len, handle))
+ return (NULL);
+ for (ptr = handle->va, i = 0;
+ i < len;
+ ptr += 16, i += 16)
+ if (memcmp(ptr, RSDP_SIG, sizeof(RSDP_SIG) - 1) == 0) {
+ rsdp = (struct acpi_rsdp1 *)ptr;
+ /*
+ * Only checksum whichever portion of the
+ * RSDP that is actually present
+ */
+ if (rsdp->revision == 0 &&
+ acpi_checksum(ptr, sizeof(struct acpi_rsdp1)) == 0)
+ return (ptr);
+ else if (rsdp->revision == 2 &&
+ acpi_checksum(ptr, sizeof(struct acpi_rsdp)) == 0)
+ return (ptr);
+ }
+ acpi_unmap(handle);
+
+ return (NULL);
+}
+
+int
+acpi_probe(struct device *parent, struct cfdata *match, struct acpi_attach_args *aaa)
+{
+ struct acpi_mem_map handle;
+ u_int8_t *ptr;
+ paddr_t ebda;
+#if NBIOS > 0
+ bios_memmap_t *im;
+
+ /*
+ * First look for ACPI entries in the BIOS memory map
+ */
+ for (im = bios_memmap; im->type != BIOS_MAP_END; im++)
+ if (im->type == BIOS_MAP_ACPI) {
+ if ((ptr = acpi_scan(&handle, im->addr, im->size)))
+ goto havebase;
+ }
+#endif
+
+ /*
+ * Next try to find ACPI table entries in the EBDA
+ */
+ if (acpi_map(0, NBPG, &handle))
+ printf("acpi: failed to map BIOS data area\n");
+ else {
+ ebda = *(const u_int16_t *)(&handle.va[0x40e]);
+ ebda <<= 4;
+ acpi_unmap(&handle);
+
+ if (ebda && ebda < IOM_BEGIN) {
+ if ((ptr = acpi_scan(&handle, ebda, 1024)))
+ goto havebase;
+ }
+ }
+
+ /*
+ * Finally try to find the ACPI table entries in the
+ * BIOS memory
+ */
+ if ((ptr = acpi_scan(&handle, ACPI_BIOS_RSDP_WINDOW_BASE,
+ ACPI_BIOS_RSDP_WINDOW_SIZE)))
+ goto havebase;
+
+ return (0);
+
+havebase:
+ aaa->aaa_pbase = ptr - handle.va + handle.pa;
+ acpi_unmap(&handle);
+
+#ifdef notyet
+ /*
+ * Disable APM if we are using ACPI
+ */
+#if NAPM > 0 && NBIOS > 0
+ apm = NULL;
+#endif
+#endif
+ return (1);
+}
+
+void
+acpi_attach_machdep(struct acpi_softc *sc)
+{
+ sc->sc_interrupt = isa_intr_establish(NULL, sc->sc_fadt->sci_int, IST_LEVEL,
+ IPL_TTY, acpi_interrupt, sc, "acpi");
+}
diff --git a/sys/arch/i386/i386/conf.c b/sys/arch/i386/i386/conf.c
index 38072585d96..8a5ead04876 100644
--- a/sys/arch/i386/i386/conf.c
+++ b/sys/arch/i386/i386/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.109 2004/10/03 21:28:34 jcs Exp $ */
+/* $OpenBSD: conf.c,v 1.110 2005/06/02 20:09:39 tholo Exp $ */
/* $NetBSD: conf.c,v 1.75 1996/05/03 19:40:20 christos Exp $ */
/*
@@ -168,6 +168,7 @@ cdev_decl(mcd);
#include "sequencer.h"
cdev_decl(music);
#include "joy.h"
+#include "acpi.h"
#include "apm.h"
#include "pctr.h"
#include "bios.h"
@@ -324,6 +325,7 @@ struct cdevsw cdevsw[] =
cdev_hotplug_init(NHOTPLUG,hotplug), /* 82: devices hot plugging */
cdev_gpio_init(NGPIO,gpio), /* 83: GPIO interface */
cdev_nvram_init(NNVRAM,nvram), /* 84: NVRAM interface */
+ cdev_acpi_init(NACPI,acpi), /* 85: ACPI */
};
int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
diff --git a/sys/arch/i386/i386/mainbus.c b/sys/arch/i386/i386/mainbus.c
index c242f14e5da..053a78ee8d5 100644
--- a/sys/arch/i386/i386/mainbus.c
+++ b/sys/arch/i386/i386/mainbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mainbus.c,v 1.16 2004/06/13 21:49:15 niklas Exp $ */
+/* $OpenBSD: mainbus.c,v 1.17 2005/06/02 20:09:39 tholo Exp $ */
/* $NetBSD: mainbus.c,v 1.21 1997/06/06 23:14:20 thorpej Exp $ */
/*
@@ -50,6 +50,7 @@
#include "apm.h"
#include "bios.h"
#include "mpbios.h"
+#include "acpi.h"
#include <machine/cpuvar.h>
#include <machine/i82093var.h>
@@ -59,6 +60,11 @@
#include <machine/biosvar.h>
#endif
+#if NACPI > 0
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+#endif
+
#if 0
#ifdef SMP /* XXX MULTIPROCESSOR */
#include <machine/mp.h>
@@ -88,6 +94,9 @@ union mainbus_attach_args {
#endif
struct cpu_attach_args mba_caa;
struct apic_attach_args aaa_caa;
+#if NACPI > 0
+ struct acpi_attach_args mba_aaa;
+#endif
};
/*
@@ -121,6 +130,16 @@ mainbus_attach(parent, self, aux)
printf("\n");
+#if NACPI > 0
+ {
+ memset(&mba.mba_aaa, 0, sizeof(mba.mba_aaa));
+ mba.mba_aaa.aaa_name = "acpi";
+ mba.mba_aaa.aaa_iot = I386_BUS_SPACE_IO;
+ mba.mba_aaa.aaa_memt = I386_BUS_SPACE_MEM;
+
+ config_found(self, &mba.mba_aaa, mainbus_print);
+ }
+#endif
#if NBIOS > 0
{
mba.mba_bios.bios_dev = "bios";
diff --git a/sys/arch/i386/include/conf.h b/sys/arch/i386/include/conf.h
index 82a4f670620..33276008ce1 100644
--- a/sys/arch/i386/include/conf.h
+++ b/sys/arch/i386/include/conf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.h,v 1.10 2003/09/23 16:51:11 millert Exp $ */
+/* $OpenBSD: conf.h,v 1.11 2005/06/02 20:09:39 tholo Exp $ */
/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */
/*
@@ -55,6 +55,12 @@ cdev_decl(pc);
(dev_type_stop((*))) enodev, 0, (dev_type_poll((*))) enodev, \
(dev_type_mmap((*))) enodev, D_KQFILTER, dev_init(c,n,kqfilter) }
+#define cdev_acpi_init(c,n) {\
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, (dev_type_poll((*))) enodev, \
+ (dev_type_mmap((*))) enodev, D_KQFILTER, dev_init(c,n,kqfilter) }
+
cdev_decl(spkr);
cdev_decl(mms);
@@ -68,6 +74,8 @@ cdev_decl(joy);
#define biospoll seltrue
cdev_decl(bios);
+cdev_decl(acpi);
+
cdev_decl(apm);
#define pctrpoll seltrue
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