bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 3/5] libacpica: Add acpi_init


From: Damien Zammit
Subject: [PATCH 3/5] libacpica: Add acpi_init
Date: Sat, 3 Apr 2021 23:16:33 +1100

---
 libacpica/acpi_init.c | 612 ++++++++++++++++++++++++++++++++++++++++++
 libacpica/acpi_init.h |  10 +
 2 files changed, 622 insertions(+)
 create mode 100644 libacpica/acpi_init.c
 create mode 100644 libacpica/acpi_init.h

diff --git a/libacpica/acpi_init.c b/libacpica/acpi_init.c
new file mode 100644
index 00000000..f5ab987b
--- /dev/null
+++ b/libacpica/acpi_init.c
@@ -0,0 +1,612 @@
+#define EXPORT_ACPI_INTERFACES
+#define DEFINE_ACPI_GLOBALS
+#include "acpi_init.h"
+#include "accommon.h"
+#include "acglobal.h"
+#include "utglobal.c"
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/io.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <mach/vm_param.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <semaphore.h>
+
+#define ACPI_MAX_TABLES 128
+
+// Lets keep the ACPI tables in this module
+static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES];
+
+struct slots {
+       uint8_t bus;
+       uint16_t dev;
+       uint16_t func;
+       acpi_handle handle;
+       struct slots *next;
+};
+
+acpi_status
+acpi_os_enter_sleep(u8 sleep_state, u32 pm1a, u32 pm1b)
+{
+       return AE_OK;
+}
+
+void
+acpi_ds_dump_method_stack(acpi_status status, ...)
+//                       struct acpi_walk_state *walk_state,
+//                       union acpi_parse_object *op)
+{
+       return;
+}
+
+void
+acpi_os_printf(const char *fmt, ...)
+{
+       va_list args;
+       va_start(args, fmt);
+       acpi_os_vprintf(fmt, args);
+       va_end(args);
+}
+
+void
+acpi_os_vprintf(const char *fmt, va_list args)
+{
+       vprintf(fmt, args);
+}
+
+acpi_status
+acpi_os_create_lock(acpi_spinlock *lockp)
+{
+       acpi_semaphore sema = NULL;
+       if (acpi_os_create_semaphore(1, 0, &sema) == AE_OK) {
+               *lockp = sema;
+               return AE_OK;
+       }
+       return AE_ERROR;
+}
+
+acpi_cpu_flags
+acpi_os_acquire_lock(acpi_spinlock lockp)
+{
+       acpi_os_wait_semaphore(lockp, 1, 0);
+       return 0;
+}
+
+void
+acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags)
+{
+       acpi_os_signal_semaphore(lockp, 1);
+}
+
+void
+acpi_os_delete_lock(acpi_spinlock lockp)
+{
+       acpi_os_delete_semaphore(lockp);
+}
+
+acpi_status
+acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_semaphore * 
handle)
+{
+       acpi_semaphore sema = NULL;
+
+       sema = acpi_os_allocate_zeroed(sizeof (sem_t));
+
+       if (!sem_init(sema, 0, initial_units)) {
+               *handle = sema;
+               return AE_OK;
+       }
+       return AE_ERROR;
+
+
+}
+
+acpi_status
+acpi_os_delete_semaphore(acpi_semaphore handle)
+{
+       if (!sem_destroy(handle)) {
+               free (handle);
+               return AE_OK;
+       }
+       return AE_ERROR;
+}
+
+acpi_status
+acpi_os_wait_semaphore(acpi_semaphore handle, u32 units, u16 timeout)
+{
+       int i;
+
+       if (!timeout)
+               timeout = 1;
+
+       for (i = 0; i < timeout; i++) {
+               if (!sem_trywait(handle)) {
+                       return AE_OK;
+               }
+       }
+
+       return AE_ERROR;
+}
+
+acpi_status
+acpi_os_signal_semaphore(acpi_semaphore handle, u32 units)
+{
+       if (!sem_post(handle)) {
+               return AE_OK;
+       }
+       return AE_ERROR;
+}
+
+acpi_status
+acpi_os_execute(acpi_execute_type type,
+               acpi_osd_exec_callback function, void *context)
+{
+       pthread_t thread;
+
+       if (pthread_create (&thread, NULL, (void *)function, context))
+               return AE_ERROR;
+
+       pthread_detach(thread);
+       return AE_OK;
+}
+
+acpi_physical_address
+acpi_os_get_root_pointer(void)
+{
+       acpi_physical_address pa;
+
+       acpi_find_root_pointer(&pa);
+       return pa;
+}
+
+/* Supposed to be 64 bit free-running
+ * monotonic timer with 100ns granularity
+ */
+u64
+acpi_os_get_timer(void)
+{
+       struct timespec now;
+
+       clock_gettime(CLOCK_MONOTONIC, &now);
+       return (u64)(now.tv_sec * 10000000 + (now.tv_nsec / 100));
+}
+
+void *
+acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
+{
+       int fd_mem;
+       void * virt_addr;
+       uintptr_t into_page = phys % PAGE_SIZE;
+       uintptr_t nearest_page = (uintptr_t)trunc_page(phys);
+
+       if ((fd_mem = open("/dev/mem", O_RDWR)) < 0) {
+               acpi_os_printf("Can't open /dev/mem\n");
+               return (void *)-1;
+       }
+
+       /* MAP_FIXED so we can access particular physical regions */
+       virt_addr = mmap(NULL, into_page + size, PROT_READ | PROT_WRITE,
+                        MAP_SHARED | MAP_FIXED, fd_mem, nearest_page);
+       if (virt_addr == MAP_FAILED) {
+               acpi_os_printf("Can't map memory 0x%llx\n", phys);
+               return (void *)-1;
+       }
+
+       return virt_addr + into_page;
+}
+
+acpi_status
+acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
+{
+       if (!value)
+               return AE_ERROR;
+
+       switch (width) {
+       case 8:
+               *((u8 *)value) = inb(port);
+               return AE_OK;
+       case 16:
+               *((u16 *)value) = inw(port);
+               return AE_OK;
+       case 32:
+               *((u32 *)value) = inl(port);
+               return AE_OK;
+       default:
+               acpi_os_printf("ACPI: read port invalid width\n");
+               return AE_ERROR;
+       }
+       return AE_ERROR;
+}
+
+acpi_status
+acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
+                           acpi_string *new_val)
+{
+       if (!init_val || !new_val)
+               return AE_BAD_PARAMETER;
+
+       *new_val = init_val->val;
+
+       return AE_OK;
+}
+
+acpi_status
+acpi_os_signal(u32 function, void *info)
+{
+       switch (function) {
+       case ACPI_SIGNAL_FATAL:
+               acpi_os_printf("ACPI: Fatal opcode executed\n");
+               break;
+       case ACPI_SIGNAL_BREAKPOINT:
+               break;
+       default:
+               break;
+       }
+       return AE_OK;
+}
+
+acpi_status
+acpi_os_physical_table_override(struct acpi_table_header *existing_table,
+                               acpi_physical_address *address,
+                               u32 *table_length)
+{
+       *table_length = 0;
+       *address = 0;
+       return AE_OK;
+}
+
+acpi_status
+acpi_os_table_override(struct acpi_table_header *existing_table,
+                      struct acpi_table_header **new_table)
+{
+       if (!existing_table || !new_table)
+               return AE_BAD_PARAMETER;
+
+       *new_table = NULL;
+       return AE_OK;
+}
+
+void
+acpi_os_unmap_memory(void *virt, acpi_size size)
+{
+       void *freeme = (void *)trunc_page(virt);
+       if (!freeme) {
+               acpi_os_printf("Nothing to unmap\n");
+               return;
+       }
+       munmap(freeme, size + size);
+}
+
+static acpi_status
+acpi_os_read_iomem(void *virt_addr, u64 *value, u32 width)
+{
+
+       switch (width) {
+       case 8:
+               *(u8 *) value = *((volatile u8 *)virt_addr);
+               break;
+       case 16:
+               *(u16 *) value = *((volatile u16 *)virt_addr);
+               break;
+       case 32:
+               *(u32 *) value = *((volatile u32 *)virt_addr);
+               break;
+       case 64:
+               *(u64 *) value = *((volatile u64 *)virt_addr);
+               break;
+       default:
+               return AE_ERROR;
+       }
+       return AE_OK;
+}
+
+acpi_status
+acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width)
+{
+       void *virt_addr;
+       unsigned int size = width / 8;
+       acpi_status err = AE_BAD_ADDRESS;
+
+       if (!value)
+               return err;
+
+       virt_addr = acpi_os_map_memory (phys_addr, size);
+       if (!virt_addr)
+               return err;
+
+       if (!acpi_os_read_iomem (virt_addr, value, width))
+               err = AE_OK;
+
+       acpi_os_unmap_memory (virt_addr, size);
+
+       return err;
+}
+
+void
+acpi_os_sleep(u64 ms)
+{
+       usleep(1000 * ms);
+}
+
+void
+acpi_os_stall(u32 us)
+{
+       usleep(us);
+}
+
+void acpi_os_wait_events_complete(void)
+{
+       return;
+}
+
+acpi_status
+acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width)
+{
+       void *virt_addr;
+       unsigned int size = width / 8;
+       acpi_status err = AE_OK;
+
+       virt_addr = acpi_os_map_memory (phys_addr, size);
+       if (!virt_addr)
+               return AE_BAD_ADDRESS;
+
+       switch (width) {
+       case 8:
+               *((volatile u8 *)virt_addr) = (u8)value;
+               break;
+       case 16:
+               *((volatile u16 *)virt_addr) = (u16)value;
+               break;
+       case 32:
+               *((volatile u32 *)virt_addr) = (u32)value;
+               break;
+       case 64:
+               *((volatile u64 *)virt_addr) = value;
+               break;
+       default:
+               acpi_os_printf("ACPI: Bad write memory width\n");
+               err = AE_BAD_ADDRESS;
+               break;
+       }
+
+       acpi_os_unmap_memory (virt_addr, size);
+
+       return err;
+}
+
+acpi_status
+acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
+{
+       switch (width) {
+       case 8:
+               outb(port, value);
+               return AE_OK;
+       case 16:
+               outw(port, value);
+               return AE_OK;
+       case 32:
+               outl(port, value);
+               return AE_OK;
+       default:
+               acpi_os_printf("ACPI: Bad write port width\n");
+               return AE_ERROR;
+       }
+
+       return AE_ERROR;
+}
+
+
+acpi_status
+acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
+                                 void *context)
+{
+       acpi_os_printf("TODO: install interrupt handler for acpi\n");
+       return AE_ERROR;
+}
+
+acpi_status
+acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler handler)
+{
+       acpi_os_printf("TODO: remove interrupt handler for acpi\n");
+       return AE_ERROR;
+}
+
+acpi_status
+acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
+                              u64 *value, u32 width)
+{
+       acpi_os_printf("ACPI: Tried to read pci config\n");
+       return AE_ERROR;
+}
+
+acpi_status
+acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
+                               u64 value, u32 width)
+{
+       acpi_os_printf("ACPI: Tried to write pci config\n");
+       return AE_ERROR;
+}
+
+acpi_status
+acpi_os_initialize(void)
+{
+       if (ioperm(0, 0x10000, 1)) {
+               fprintf(stderr, "EPERM on ioperm()\n");
+               return AE_IO_ERROR;
+       }
+       return AE_OK;
+}
+
+acpi_status
+acpi_os_terminate(void)
+{
+       acpi_os_printf("Bye!\n");
+       return AE_OK;
+}
+
+static acpi_status
+register_slot(acpi_handle handle, u32 lev, void *context, void **rv)
+{
+       struct slots *s;
+       struct acpi_device *acpi_dev;
+       uint64_t addr;
+       acpi_status err;
+
+       context = (void *)malloc(sizeof (struct slots));
+       s = (struct slots *)context;
+
+       if (acpi_get_data(handle, NULL, (void **)&acpi_dev))
+               return AE_ERROR;
+
+       {
+               struct acpi_buffer buffer = { 0, NULL };
+               union acpi_object element;
+               buffer.pointer = &element;
+               err = acpi_evaluate_object(handle, "_BBN", NULL, &buffer);
+               if (ACPI_FAILURE(err))
+                       return err;
+               if (element.type != ACPI_TYPE_INTEGER)
+                       return AE_BAD_DATA;
+               addr = element.integer.value;
+       }
+
+       s->bus = addr & 0xff;
+
+       {
+               struct acpi_buffer buffer = { 0, NULL };
+               union acpi_object element;
+               buffer.pointer = &element;
+               err = acpi_evaluate_object(handle, "_ADR", NULL, &buffer);
+               if (ACPI_FAILURE(err))
+                       return err;
+               if (element.type != ACPI_TYPE_INTEGER)
+                       return AE_BAD_DATA;
+               addr = element.integer.value;
+       }
+
+       s->dev = (addr >> 16) & 0xffff;
+       s->func = addr & 0xffff;
+       s->handle = handle;
+
+       return AE_OK; 
+}
+
+void
+acpi_enter_sleep(int sleep_state)
+{
+       acpi_hw_legacy_sleep (sleep_state);
+}
+
+int
+acpi_get_irq_number(uint16_t bus, uint16_t dev, uint16_t func)
+{
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       struct acpi_pci_routing_table *entry;
+       acpi_handle handle = ACPI_ROOT_OBJECT;
+       acpi_handle parent_handle = NULL;
+       acpi_handle lnk = NULL;
+       acpi_status err = AE_OK;
+       u16 prt_dev, prt_func;
+       struct slots *pcislots = NULL, *iter;
+       int nslots = 0;
+
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, register_slot, NULL, 
pcislots, NULL);
+
+       for (iter = pcislots; iter; iter = iter->next) {
+               if ((iter->bus == bus) && (iter->dev == dev) && (iter->func & 
func)) {
+                       handle = iter->handle;
+               }
+               nslots++;
+       }
+
+       err = acpi_get_parent(handle, &parent_handle);
+       if (ACPI_FAILURE(err))
+               return err;
+
+       err = acpi_get_irq_routing_table(parent_handle, &buffer);
+       if (ACPI_FAILURE(err)) {
+               free(buffer.pointer);
+               // FIXME free the pcislots list
+               return -1;
+       }
+
+       entry = buffer.pointer;
+       while (entry && (entry->length > 0)) {
+               /* Already applies to the bus of the device */
+               prt_dev = (entry->address >> 16) & 0xffff;
+               prt_func = entry->address & 0xffff;
+               if ((prt_dev == dev) && (prt_func & func)) {
+                       if (entry->source[0]) {
+                               /* Dynamic:
+                                * - source field specifies PCI interrupt LNK
+                                * - source_index specifies which resource 
descriptor in
+                                *   resource template of LNK to allocate this 
interrupt
+                                */
+                               acpi_get_handle(entry, entry->source, &lnk);
+                               // FIXME check the LNK irq _CRS and then set it 
with _SRS
+
+                       } else {
+                               /* Static:
+                                * - source field is zero
+                                * - source_index specifies IRQ value hardwired 
to
+                                *   interrupt inputs on controller
+                                */
+                               return entry->source_index;
+                       }
+               }
+               entry = (struct acpi_pci_routing_table *)((size_t)entry + 
entry->length);
+       }
+       return -1;
+}
+
+void acpi_init(void)
+{
+       acpi_status err;
+
+       // Hack to increase verbosity except parsing AML
+       //acpi_dbg_level = (ACPI_LV_ALL) & ~(ACPI_LV_FUNCTIONS);
+
+       err = acpi_initialize_subsystem ();
+       if (ACPI_FAILURE (err)) {
+               goto die;
+       }
+
+       err = acpi_initialize_tables (initial_tables, ACPI_MAX_TABLES, 0);
+       if (ACPI_FAILURE (err)) {
+               goto die;
+       }
+
+       err = acpi_reallocate_root_table ();
+       if (ACPI_FAILURE (err)) {
+               goto die;
+       }
+
+       err = acpi_load_tables ();
+       if (ACPI_FAILURE (err)) {
+               goto die;
+       }
+
+       err = acpi_initialize_objects (ACPI_FULL_INITIALIZATION);
+       if (ACPI_FAILURE (err)) {
+               goto die;
+       }
+/*
+       err = acpi_enable_subsystem (ACPI_FULL_INITIALIZATION);
+       if (ACPI_FAILURE (err)) {
+               goto die;
+       }
+*/
+       acpi_os_printf("PASS!\n");
+       return;
+die:
+       acpi_os_printf("OUCH!\n");
+}
diff --git a/libacpica/acpi_init.h b/libacpica/acpi_init.h
new file mode 100644
index 00000000..9d996f29
--- /dev/null
+++ b/libacpica/acpi_init.h
@@ -0,0 +1,10 @@
+#ifndef ACPI_INIT_H
+#define ACPI_INIT_H
+
+#include <acpi/acpi.h>
+
+void acpi_enter_sleep(int sleep_state);
+int acpi_get_irq_number(uint16_t bus, uint16_t dev, uint16_t func);
+void acpi_init(void);
+
+#endif
-- 
2.30.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]