feat: implement PCI subsystem and integrate uACPI support

See previous commit

Signed-off-by: kaguya <vpshinomiya@protonmail.com>
This commit is contained in:
kaguya
2026-04-15 13:33:18 -04:00
parent 840210ddc0
commit cc8351bf8d
15 changed files with 785 additions and 68 deletions
+119 -9
View File
@@ -19,6 +19,13 @@
#include "arch/x86_64/usermode.h"
#include "syscall/syscall.h"
#include "fs/vfs.h"
#include "time/time.h"
#include "arch/x86_64/pit.h"
#include <uacpi/uacpi.h>
#include <uacpi/event.h>
#include <uacpi/sleep.h>
#include "arch/x86_64/pci.h"
uintptr_t g_hhdm_offset;
#define CPU_STACK_SIZE (64 * 1024)
@@ -47,6 +54,13 @@ static volatile struct limine_memmap_request memmap_request = {
.revision = 6
};
__attribute__((used, section(".limine_requests")))
static volatile struct limine_rsdp_request rsdp_request = {
.id = LIMINE_RSDP_REQUEST_ID,
.revision = 6
};
__attribute__((used, section(".limine_requests")))
@@ -82,7 +96,34 @@ static void hcf(void) {
}
}
extern struct kernel_pagemap;
uint64_t g_rsdp_phys;
void shutdown(void) {
uacpi_status ret2 = uacpi_prepare_for_sleep_state(UACPI_SLEEP_STATE_S5);
if (uacpi_unlikely_error(ret2)) {
printf("failed to prepare for sleep: %s", uacpi_status_to_string(ret2));
}
ret2 = uacpi_enter_sleep_state(UACPI_SLEEP_STATE_S5);
if (uacpi_unlikely_error(ret2)) {
printf("failed to enter sleep: %s", uacpi_status_to_string(ret2));
}
}
static uacpi_interrupt_ret handle_power_button(uacpi_handle ctx) {
/*
* Shut down right here using the helper we have defined above.
*
* Note that it's generally terrible practice to run any AML from
* an interrupt handler, as it's allowed to allocate, map, sleep,
* stall, acquire mutexes, etc. So, if possible in your kernel,
* instead schedule the shutdown callback to be run in a normal
* preemptible context later.
*/
shutdown();
return UACPI_INTERRUPT_HANDLED;
}
// The following will be our kernel's entry point.
// If renaming kmain() to something else, make sure to change the
@@ -104,9 +145,13 @@ void kmain(void) {
struct limine_memmap_response *memmap_response = memmap_request.response;
struct limine_rsdp_response *rsdp_response = rsdp_request.response;
g_rsdp_phys = (uint64_t)rsdp_response->address - MEM_PHYS_OFFSET;
if (!memmap_response) {
hcf();
@@ -117,6 +162,7 @@ void kmain(void) {
fb_width = framebuffer->width;
fb_height = framebuffer->height;
fb_pitch = framebuffer->pitch / 4;
printf("Hello, Kernel!\n");
@@ -135,23 +181,29 @@ void kmain(void) {
/*uint32_t msr_lo, msr_hi;
uint32_t msr_lo, msr_hi;
asm volatile("rdmsr" : "=a"(msr_lo), "=d"(msr_hi) : "c"(0x1B));
msr_lo &= ~(1 << 11);
asm volatile("wrmsr" : : "a"(msr_lo), "d"(msr_hi), "c"(0x1B));*/
printf("init pmm");
asm volatile("wrmsr" : : "a"(msr_lo), "d"(msr_hi), "c"(0x1B));
printf("rsdp: 0x%x\n", g_rsdp_phys);
printf("init pmm\n");
pmm_init(memmap_response->entries, memmap_response->entry_count);
printf("init slab");
printf("init slab\n");
slab_init();
printf("init vmm");
printf("init vmm\n");
vmm_init(memmap_response->entries, memmap_response->entry_count);
printf("init gdt");
x86_64_GDT_Initialize();
x86_64_IDT_Initialize();
x86_64_ISR_Initialize();
x86_64_IRQ_Initialize();
x86_64_EnableInterrupts();
//lapic_timer_start(100);
x86_64_PIT_Initialize(1000);
asm volatile("sti");
calibrate_tsc();
//while (1) asm volatile("hlt");
ata_init();
ata_identify();
@@ -327,10 +379,68 @@ void kmain(void) {
printf("\nKirkOS %s\n", KIRKOS_VERSION);
x86_64_EnableInterrupts();
syscall_init();
start_userspace();
/*
* Start with this as the first step of the initialization. This loads all
* tables, brings the event subsystem online, and enters ACPI mode. We pass
* in 0 as the flags as we don't want to override any default behavior for now.
*/
uacpi_status ret = uacpi_initialize(0);
if (uacpi_unlikely_error(ret)) {
printf("uacpi_initialize error: %s", uacpi_status_to_string(ret));
}
/*
* Load the AML namespace. This feeds DSDT and all SSDTs to the interpreter
* for execution.
*/
ret = uacpi_namespace_load();
if (uacpi_unlikely_error(ret)) {
printf("uacpi_namespace_load error: %s", uacpi_status_to_string(ret));
}
/*
* Initialize the namespace. This calls all necessary _STA/_INI AML methods,
* as well as _REG for registered operation region handlers.
*/
ret = uacpi_namespace_initialize();
if (uacpi_unlikely_error(ret)) {
printf("uacpi_namespace_initialize error: %s", uacpi_status_to_string(ret));
}
/*
* Tell uACPI that we have marked all GPEs we wanted for wake (even though we haven't
* actually marked any, as we have no power management support right now). This is
* needed to let uACPI enable all unmarked GPEs that have a corresponding AML handler.
* These handlers are used by the firmware to dynamically execute AML code at runtime
* to e.g. react to thermal events or device hotplug.
*/
ret = uacpi_finalize_gpe_initialization();
if (uacpi_unlikely_error(ret)) {
printf("uACPI GPE initialization error: %s", uacpi_status_to_string(ret));
}
pci_init();
pci_device_t hda;
if (pci_find_hda(&hda)) {
printf("[PCI] Found HDA controller at %02x:%02x.%x %04x:%04x\n",
hda.addr.bus, hda.addr.device, hda.addr.function,
hda.vendor_id, hda.device_id);
// BAR0 is usually at hda.bar[0] & ~0xF (MMIO)
} else {
printf("[PCI] No HDA controller found!\n");
}
//syscall_init();
//start_userspace();
printf("tst");
// We're done, just hang...
hcf();
}