acpi: /dev/acpi

This commit is contained in:
Matheus
2024-09-01 21:41:08 -03:00
parent 65edcf0417
commit 5793dda4d9
5 changed files with 129 additions and 2 deletions
+2
View File
@@ -80,6 +80,8 @@ void kernel_entry() {
sockfs_init();
ext2_init();
acpi_initdevice();
tty_init();
pty_init();
+6 -1
View File
@@ -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
+1
View File
@@ -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);
+1 -1
View File
@@ -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) {
+119
View File
@@ -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);
}