mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 20:58:22 +00:00
acpi: /dev/acpi
This commit is contained in:
@@ -80,6 +80,8 @@ void kernel_entry() {
|
||||
sockfs_init();
|
||||
ext2_init();
|
||||
|
||||
acpi_initdevice();
|
||||
|
||||
tty_init();
|
||||
pty_init();
|
||||
|
||||
|
||||
@@ -10,4 +10,9 @@ void acpi_init(void);
|
||||
int acpi_poweroff(void);
|
||||
int acpi_reboot(void);
|
||||
|
||||
#endif
|
||||
void acpi_signaldevice(char c);
|
||||
|
||||
// Depends on devfs
|
||||
void acpi_initdevice(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define DEV_MAJOR_NET 10
|
||||
#define DEV_MAJOR_MOUSE 11
|
||||
#define DEV_MAJOR_PTY 12
|
||||
#define DEV_MAJOR_ACPI 13
|
||||
|
||||
typedef struct {
|
||||
int (*open)(int minor, vnode_t **vnode, int flags);
|
||||
|
||||
@@ -22,7 +22,7 @@ void acpi_early_init(void) {
|
||||
|
||||
void acpi_dopoweroff(uacpi_handle ctx) {
|
||||
(void)ctx;
|
||||
acpi_poweroff();
|
||||
acpi_signaldevice('p');
|
||||
}
|
||||
|
||||
static uacpi_interrupt_ret handle_pwrbtn(uacpi_handle ctx) {
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
#include <kernel/acpi.h>
|
||||
#include <kernel/devfs.h>
|
||||
#include <kernel/poll.h>
|
||||
#include <spinlock.h>
|
||||
#include <ringbuffer.h>
|
||||
#include <logging.h>
|
||||
|
||||
static ringbuffer_t ringbuffer;
|
||||
static pollheader_t pollheader;
|
||||
static spinlock_t lock;
|
||||
|
||||
void acpi_signaldevice(char c) {
|
||||
long ipl = spinlock_acquireraiseipl(&lock, IPL_DPC);
|
||||
|
||||
if (ringbuffer_write(&ringbuffer, &c, 1))
|
||||
poll_event(&pollheader, POLLIN);
|
||||
|
||||
spinlock_releaseloweripl(&lock, ipl);
|
||||
}
|
||||
|
||||
static int internalpoll(polldata_t *data, int events) {
|
||||
int revents = 0;
|
||||
if (events & POLLOUT)
|
||||
revents |= POLLOUT;
|
||||
|
||||
if ((events & POLLIN) && RINGBUFFER_DATACOUNT(&ringbuffer))
|
||||
revents |= POLLIN;
|
||||
|
||||
if (revents == 0)
|
||||
poll_add(&pollheader, data, events);
|
||||
|
||||
return revents;
|
||||
}
|
||||
|
||||
static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
||||
*readc = 0;
|
||||
|
||||
if (size < 1)
|
||||
return 0;
|
||||
|
||||
polldesc_t desc;
|
||||
int error = poll_initdesc(&desc, 1);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
for (;;) {
|
||||
long ipl = spinlock_acquireraiseipl(&lock, IPL_DPC);
|
||||
|
||||
int revents = internalpoll(&desc.data[0], POLLIN);
|
||||
|
||||
spinlock_releaseloweripl(&lock, ipl);
|
||||
|
||||
if (revents)
|
||||
break;
|
||||
|
||||
if (flags & V_FFLAGS_NONBLOCKING) {
|
||||
error = EAGAIN;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
error = poll_dowait(&desc, 0);
|
||||
|
||||
if (error)
|
||||
goto leave;
|
||||
|
||||
poll_leave(&desc);
|
||||
}
|
||||
|
||||
long ipl = spinlock_acquireraiseipl(&lock, IPL_DPC);
|
||||
|
||||
*readc = ringbuffer_read(&ringbuffer, buffer, size);
|
||||
|
||||
spinlock_releaseloweripl(&lock, ipl);
|
||||
|
||||
leave:
|
||||
poll_leave(&desc);
|
||||
poll_destroydesc(&desc);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int write(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec) {
|
||||
if (size < 1) {
|
||||
*writec = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *c = buffer;
|
||||
switch (*c) {
|
||||
case 'p':
|
||||
acpi_poweroff();
|
||||
break;
|
||||
case 'r':
|
||||
acpi_reboot();
|
||||
break;
|
||||
}
|
||||
|
||||
return EIO;
|
||||
}
|
||||
|
||||
static int poll(int minor, polldata_t *data, int events) {
|
||||
long ipl = spinlock_acquireraiseipl(&lock, IPL_DPC);
|
||||
|
||||
int revents = internalpoll(data, events);
|
||||
|
||||
spinlock_releaseloweripl(&lock, ipl);
|
||||
return revents;
|
||||
}
|
||||
|
||||
static devops_t acpiops = {
|
||||
.read = read,
|
||||
.write = write,
|
||||
.poll = poll
|
||||
};
|
||||
|
||||
void acpi_initdevice(void) {
|
||||
__assert(devfs_register(&acpiops, "acpi", V_TYPE_CHDEV, DEV_MAJOR_ACPI, 0, 0600, NULL) == 0);
|
||||
__assert(ringbuffer_init(&ringbuffer, 64) == 0);
|
||||
POLL_INITHEADER(&pollheader);
|
||||
}
|
||||
Reference in New Issue
Block a user