summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrpaulo <rpaulo@FreeBSD.org>2014-11-03 03:17:58 +0000
committerrpaulo <rpaulo@FreeBSD.org>2014-11-03 03:17:58 +0000
commitce9598bb33d22729216c4c791622668240cdfcdc (patch)
treec0349a5b6ed3a6bf2bbeaab759f052be4f66fafc
parent916cd4d89a2e10ed849144252c50899752520076 (diff)
downloadFreeBSD-src-ce9598bb33d22729216c4c791622668240cdfcdc.zip
FreeBSD-src-ce9598bb33d22729216c4c791622668240cdfcdc.tar.gz
MFC 273598 273602 273607 273613 273647:
Userland HPET support.
-rw-r--r--include/Makefile4
-rw-r--r--sys/dev/acpica/acpi_hpet.c81
2 files changed, 78 insertions, 7 deletions
diff --git a/include/Makefile b/include/Makefile
index a0a9cdf..5aa1a47 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -164,6 +164,8 @@ copies:
.endfor
cd ${.CURDIR}/../sys/dev/acpica; \
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 acpiio.h \
+ ${DESTDIR}${INCLUDEDIR}/dev/acpica; \
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 acpi_hpet.h \
${DESTDIR}${INCLUDEDIR}/dev/acpica
cd ${.CURDIR}/../sys/dev/agp; \
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 agpreg.h \
@@ -246,7 +248,7 @@ symlinks:
done
.endfor
cd ${.CURDIR}/../sys/dev/acpica; \
- for h in acpiio.h; do \
+ for h in acpiio.h acpi_hpet.h; do \
ln -fs ../../../../sys/dev/acpica/$$h \
${DESTDIR}${INCLUDEDIR}/dev/acpica; \
done
diff --git a/sys/dev/acpica/acpi_hpet.c b/sys/dev/acpica/acpi_hpet.c
index 4d600f5..8d8463c 100644
--- a/sys/dev/acpica/acpi_hpet.c
+++ b/sys/dev/acpica/acpi_hpet.c
@@ -35,11 +35,13 @@ __FBSDID("$FreeBSD$");
#include "opt_apic.h"
#endif
#include <sys/param.h>
+#include <sys/conf.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
+#include <sys/mman.h>
#include <sys/time.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
@@ -106,6 +108,19 @@ struct hpet_softc {
char name[8];
} t[32];
int num_timers;
+ struct cdev *pdev;
+ int mmap_allow;
+ int mmap_allow_write;
+};
+
+static d_open_t hpet_open;
+static d_mmap_t hpet_mmap;
+
+static struct cdevsw hpet_cdevsw = {
+ .d_version = D_VERSION,
+ .d_name = "hpet",
+ .d_open = hpet_open,
+ .d_mmap = hpet_mmap,
};
static u_int hpet_get_timecount(struct timecounter *tc);
@@ -314,8 +329,37 @@ hpet_find_irq_rid(device_t dev, u_long start, u_long end)
}
}
+static int
+hpet_open(struct cdev *cdev, int oflags, int devtype, struct thread *td)
+{
+ struct hpet_softc *sc;
+
+ sc = cdev->si_drv1;
+ if (!sc->mmap_allow)
+ return (EPERM);
+ else
+ return (0);
+}
+
+static int
+hpet_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr,
+ int nprot, vm_memattr_t *memattr)
+{
+ struct hpet_softc *sc;
+
+ sc = cdev->si_drv1;
+ if (offset > rman_get_size(sc->mem_res))
+ return (EINVAL);
+ if (!sc->mmap_allow_write && (nprot & PROT_WRITE))
+ return (EPERM);
+ *paddr = rman_get_start(sc->mem_res) + offset;
+ *memattr = VM_MEMATTR_UNCACHEABLE;
+
+ return (0);
+}
+
/* Discover the HPET via the ACPI table of the same name. */
-static void
+static void
hpet_identify(driver_t *driver, device_t parent)
{
ACPI_TABLE_HPET *hpet;
@@ -646,8 +690,8 @@ hpet_attach(device_t dev)
#ifdef DEV_APIC
if ((t->caps & HPET_TCAP_FSB_INT_DEL) && t->irq >= 0) {
uint64_t addr;
- uint32_t data;
-
+ uint32_t data;
+
if (PCIB_MAP_MSI(
device_get_parent(device_get_parent(dev)), dev,
t->irq, &addr, &data) == 0) {
@@ -697,6 +741,31 @@ hpet_attach(device_t dev)
maxhpetet++;
}
}
+
+ sc->pdev = make_dev(&hpet_cdevsw, 0, UID_ROOT, GID_WHEEL,
+ 0600, "hpet%d", device_get_unit(dev));
+ if (sc->pdev) {
+ sc->pdev->si_drv1 = sc;
+ sc->mmap_allow = 1;
+ TUNABLE_INT_FETCH("hw.acpi.hpet.mmap_allow",
+ &sc->mmap_allow);
+ sc->mmap_allow_write = 1;
+ TUNABLE_INT_FETCH("hw.acpi.hpet.mmap_allow_write",
+ &sc->mmap_allow_write);
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "mmap_allow",
+ CTLFLAG_RW, &sc->mmap_allow, 0,
+ "Allow userland to memory map HPET");
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "mmap_allow_write",
+ CTLFLAG_RW, &sc->mmap_allow_write, 0,
+ "Allow userland write to the HPET register space");
+ } else
+ device_printf(dev, "could not create /dev/hpet%d\n",
+ device_get_unit(dev));
+
return (0);
}
@@ -741,8 +810,8 @@ hpet_resume(device_t dev)
#ifdef DEV_APIC
if (t->irq >= 0 && (sc->legacy_route == 0 || i >= 2)) {
uint64_t addr;
- uint32_t data;
-
+ uint32_t data;
+
if (PCIB_MAP_MSI(
device_get_parent(device_get_parent(dev)), dev,
t->irq, &addr, &data) == 0) {
@@ -813,7 +882,7 @@ hpet_remap_intr(device_t dev, device_t child, u_int irq)
struct hpet_softc *sc = device_get_softc(dev);
struct hpet_timer *t;
uint64_t addr;
- uint32_t data;
+ uint32_t data;
int error, i;
for (i = 0; i < sc->num_timers; i++) {
OpenPOWER on IntegriCloud