#include <sys/types.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/systimer.h>
#include <sys/sysctl.h>
#include <sys/signal.h>
#include <sys/interrupt.h>
#include <sys/bus.h>
#include <sys/time.h>
#include <sys/event.h>
#include <machine/cpu.h>
#include <machine/globaldata.h>
#include <machine/md_var.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <fcntl.h>
struct kqueue_info {
void (*func)(void *, struct intrframe *);
void *data;
int fd;
};
static int KQueueFd = -1;
void
init_kqueue(void)
{
#if 0
struct sigaction sa;
bzero(&sa, sizeof(sa));
sa.sa_flags = 0;
sa.sa_handler = kqueuesig;
sigemptyset(&sa.sa_mask);
sigaction(SIGIO, &sa, NULL);
#endif
KQueueFd = kqueue();
if (fcntl(KQueueFd, F_SETOWN, getpid()) < 0)
panic("Cannot configure kqueue for SIGIO, update your kernel");
if (fcntl(KQueueFd, F_SETFL, O_ASYNC) < 0)
panic("Cannot configure kqueue for SIGIO, update your kernel");
}
#if 0
static void
kqueuesig(int signo)
{
signalintr(1);
}
#endif
struct kqueue_info *
kqueue_add(int fd, void (*func)(void *, struct intrframe *), void *data)
{
struct timespec ts = { 0, 0 };
struct kqueue_info *info;
struct kevent kev;
info = kmalloc(sizeof(*info), M_DEVBUF, M_ZERO|M_INTWAIT);
info->func = func;
info->data = data;
info->fd = fd;
EV_SET(&kev, fd, EVFILT_READ, EV_ADD|EV_ENABLE|EV_CLEAR, 0, 0, info);
if (kevent(KQueueFd, &kev, 1, NULL, 0, &ts) < 0)
panic("kqueue: kevent() call could not add descriptor");
return(info);
}
#if 0
struct kqueue_info *
kqueue_add_timer(void (*func)(void *, struct intrframe *), void *data)
{
struct kqueue_info *info;
info = kmalloc(sizeof(*info), M_DEVBUF, M_ZERO|M_INTWAIT);
info->func = func;
info->data = data;
info->fd = (uintptr_t)info;
return(info);
}
void
kqueue_reload_timer(struct kqueue_info *info, int ms)
{
struct timespec ts = { 0, 0 };
struct kevent kev;
KKASSERT(ms > 0);
EV_SET(&kev, info->fd, EVFILT_TIMER,
EV_ADD|EV_ENABLE|EV_ONESHOT|EV_CLEAR, 0, (uintptr_t)ms, info);
if (kevent(KQueueFd, &kev, 1, NULL, 0, &ts) < 0)
panic("kqueue_reload_timer: Failed");
}
#endif
void
kqueue_del(struct kqueue_info *info)
{
struct timespec ts = { 0, 0 };
struct kevent kev;
KKASSERT(info->fd >= 0);
EV_SET(&kev, info->fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
if (kevent(KQueueFd, &kev, 1, NULL, 0, &ts) < 0)
panic("kevent: failed to delete descriptor %d", info->fd);
info->fd = -1;
kfree(info, M_DEVBUF);
}
void
kqueue_intr(struct intrframe *frame)
{
struct timespec ts;
struct kevent kevary[8];
int n;
int i;
ts.tv_sec = 0;
ts.tv_nsec = 0;
do {
n = kevent(KQueueFd, NULL, 0, kevary, 8, &ts);
for (i = 0; i < n; ++i) {
struct kevent *kev = &kevary[i];
struct kqueue_info *info = (void *)kev->udata;
info->func(info->data, frame);
}
} while (n == 8);
}