feat: added basic ACPI support using LAI

This commit is contained in:
2021-08-30 19:56:36 +02:00
parent 462dd90890
commit e37222c346
17 changed files with 729 additions and 44 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "lai"]
path = lai
url = https://github.com/managarm/lai.git

View File

@@ -7,17 +7,18 @@ SET(CMAKE_C_COMPILER ${COMPILER_RT}/i686-elf-gcc)
SET(CMAKE_ASM_COMPILER ${COMPILER_RT}/i686-elf-gcc)
# Optionally enable cmake debugging
#SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(CMAKE_VERBOSE_MAKEFILE ON)
# Set compile flags
SET(CMAKE_C_FLAGS "-g -ffreestanding -Wall -Wextra -fno-exceptions -fstack-protector -fno-pie -m32")
SET(CMAKE_ASM_FLAGS "${CFLAGS} -m32 -x assembler-with-cpp")
SET(CMAKE_EXE_LINKER_FLAGS "-T${CMAKE_CURRENT_LIST_DIR}/linker.ld -lgcc -ffreestanding -nostdlib -no-pie")
SET(CMAKE_EXE_LINKER_FLAGS "-T${CMAKE_CURRENT_LIST_DIR}/linker.ld -nostdlib -lgcc")
include_directories(AFTER include)
include_directories(AFTER include lai/include)
set(CMAKE_C_STANDARD 99)
FILE(GLOB lai lai/core/*.c lai/helpers/*.c lai/driver/*.c)
FILE(GLOB_RECURSE kernel_src kernel/**.c)
FILE(GLOB_RECURSE kernel_asm kernel/**.S)
FILE(GLOB_RECURSE boot_asm boot/boot.S)
@@ -31,9 +32,11 @@ add_compile_definitions(ENABLE_SELF_TEST) # Support for pretty printing pci cla
add_compile_definitions(ENABLE_PCIPP) # Support for pretty printing pci class/subclass/interface
add_compile_definitions(K_SHELL)
add_executable(my-kernel.bin ${kernel_src} ${kernel_asm} ${boot_asm})
# find libgcc.a
add_library(libgcc STATIC IMPORTED)
set_target_properties(libgcc PROPERTIES IMPORTED_LOCATION ${COMPILER_RT}/../lib/gcc/i686-elf/10.2.0/libgcc.a)
add_executable(my-kernel.bin ${kernel_src} ${kernel_asm} ${boot_asm} ${lai})
target_link_libraries(my-kernel.bin libgcc)
set_source_files_properties(${kernel_src} PROPERTIES LANGUAGE C COMPILE_FLAGS "")
set_target_properties(my-kernel.bin PROPERTIES LINKER_LANGUAGE C PREFIX "" SUFFIX "" LINK_FLAGS "")
set_target_properties(my-kernel.bin PROPERTIES LINKER_LANGUAGE C PREFIX "" SUFFIX "" LINK_FLAGS "")

14
include/myke/acpi/acpi.h Normal file
View File

@@ -0,0 +1,14 @@
//
// Created by rick on 22-08-21.
//
#ifndef NEW_KERNEL_ACPI_H
#define NEW_KERNEL_ACPI_H
void acpi_parse();
void acpi_init();
void* acpi_find_table_by_name(const char* name, int skip);
#endif //NEW_KERNEL_ACPI_H

View File

@@ -0,0 +1,256 @@
//
// Created by rick on 22-08-21.
//
#ifndef NEW_KERNEL_STRUCTURES_H
#define NEW_KERNEL_STRUCTURES_H
#include <attributes.h>
#include <stdbool.h>
#include <sys/types.h>
#define RDSP_SIGNATURE_LENGTH 8
#define RSDP_SIGNATURE "RSD PTR "
enum generic_address_structure_address_space {
system_memory = 0,
system_io = 1,
pci_config_space = 2,
embedded_controller = 3,
system_management_bus = 4,
system_cmos = 5,
pci_device_bar = 6,
ipmi = 7,
gpio = 8,
gsb = 9,
pmc = 0x0A
};
enum generic_address_structure_access_size {
undefined = 0,
uint8 = 1,
uint16 = 2,
uint32 = 3,
uint64 = 4,
};
struct generic_address_structure {
uint8_t address_space;
uint8_t bit_width;
uint8_t bit_offset;
uint8_t access_size;
uint64_t address;
};
struct acpi_rsdp_descriptor {
char signature[8];
uint8_t checksum;
char oem_id[6];
uint8_t revision;
uint32_t rsdt_address;
} att_packed;
struct acpi_rsdp_descriptor_20 {
struct acpi_rsdp_descriptor rsdp;
uint32_t length;
uint64_t xsdt_address;
uint8_t extended_checksum;
uint32_t: 24; // reserved
} att_packed;
struct acpi_sdt_header {
char signature[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
char oem_id[6];
char oem_table_id[8];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
} att_packed;
struct acpi_rsdt {
struct acpi_sdt_header header;
uint32_t pointer_to_other_sdt[];
} att_packed;
struct acpi_xsdt {
struct acpi_sdt_header header;
uint64_t pointer_to_other_sdt[];
} att_packed;
struct acpi_fadt {
struct acpi_sdt_header header;
uint32_t firmware_ctrl;
uint32_t dsdt;
// field used in ACPI 1.0; no longer in use, for compatibility only
uint8_t: 8;
uint8_t preferred_power_management_profile;
uint16_t sci_interrupt;
uint32_t smi_command_port;
uint8_t acpi_enable;
uint8_t acpi_disable;
uint8_t s4bios_req;
uint8_t pstate_control;
uint32_t pm1a_event_block;
uint32_t pm1b_event_block;
uint32_t pm1a_control_block;
uint32_t pm1b_control_block;
uint32_t pm2_control_block;
uint32_t pm_timer_block;
uint32_t gpe0_block;
uint32_t gpe1_block;
uint8_t pm1_event_length;
uint8_t pm1_control_length;
uint8_t pm2_control_length;
uint8_t pm_timer_length;
uint8_t gpe0_length;
uint8_t gpe1_length;
uint8_t gpe1_base;
uint8_t cstate_control;
uint16_t worst_c2_latency;
uint16_t worst_c3_latency;
uint16_t flush_size;
uint16_t flush_stride;
uint8_t duty_offset;
uint8_t duty_width;
uint8_t day_alarm;
uint8_t month_alarm;
uint8_t century;
// reserved in ACPI 1.0; used since ACPI 2.0+
uint16_t boot_architecture_flags;
uint8_t: 8;
uint32_t flags;
// 12 byte structure; see below for details
struct generic_address_structure reset_reg;
uint8_t reset_value;
uint16_t arm_boot_arch;
uint8_t fadt_minor_version;
// 64bit pointers - Available on ACPI 2.0+
uint64_t x_firmware_control;
uint64_t x_dsdt;
struct generic_address_structure x_pm1a_event_block;
struct generic_address_structure x_pm1b_event_block;
struct generic_address_structure x_pm1a_control_block;
struct generic_address_structure x_pm1b_control_block;
struct generic_address_structure x_pm2_control_block;
struct generic_address_structure x_pm_timer_block;
struct generic_address_structure x_gpe0_block;
struct generic_address_structure x_gpe1_block;
struct generic_address_structure sleep_control_register;
struct generic_address_structure sleep_status_register;
uint64_t hypervisor_id;
} att_packed;
#define MADT_TYPE_PROCESSOR_LOCAL_APIC 0
#define MADT_TYPE_IO_APIC 1
#define MADT_TYPE_IO_APIC_INTERRUPT_SOURCE_OVERRIDE 2
#define MADT_TYPE_IO_APIC_NON_MASKABLE_INTERRUPT_SOURCE 3
#define MADT_TYPE_LOCAL_APIC_NON_MASKABLE_INTERRUPTS 4
#define MADT_TYPE_LOCAL_APIC_ADDRESS_OVERRIDE 5
#define MADT_TYPE_PROCESSOR_LOCAL_X2_APIC 9
union madt_local_apic_flags {
uint32_t flags_int;
struct {
bool processor_enabled: 1;
bool online_capable: 1;
} flags;
};
union madt_interrupt_flags {
uint16_t flags_int;
struct {
bool: 1; // 1
bool active_low: 1; // 2
bool: 1; // 4
bool level_triggered: 1; // 8
} att_packed;
};
struct acpi_madt {
struct acpi_sdt_header header;
uint32_t local_apic_addr;
union {
uint32_t flags_int;
struct {
bool dual_8259_legacy_pics: 1;
};
};
uint8_t entries[];
} att_packed;
struct acpi_madt_entry_header {
uint8_t type;
uint8_t length;
} att_packed;
struct acpi_madt_local_apic { // type 0
struct acpi_madt_entry_header header;
uint8_t processor_id;
uint8_t apic_id;
union madt_local_apic_flags flags;
} att_packed;
struct acpi_madt_io_apic { // type 1
struct acpi_madt_entry_header header;
uint8_t apic_id;
uint8_t: 8; // reserved
uint32_t io_apic_address;
uint32_t global_system_interrupt_base;
} att_packed;
struct acpi_madt_io_apic_interrupt_source_override { // type 2
struct acpi_madt_entry_header header;
uint8_t bus_source;
uint8_t irq_source;
uint32_t global_system_interrupt;
union madt_interrupt_flags flags;
} att_packed;
struct acpi_madt_io_apic_non_maskable_interrupt { // type 3
struct acpi_madt_entry_header header;
uint8_t nmi_source;
uint8_t: 8; // reserved
union madt_interrupt_flags flags;
uint32_t global_system_interrupt;
} att_packed;
struct acpi_madt_local_apic_non_maskable_interrupts {
struct acpi_madt_entry_header header;
uint8_t acpi_processor_id;
union madt_interrupt_flags flags;
uint8_t lint_no;
} att_packed;
struct acpi_madt_local_apic_address_override {
struct acpi_madt_entry_header header;
uint16_t: 16; // reserved
uint64_t physical_address_local_apic;
} att_packed;
struct acpi_madt_processor_local_x2_apic {
struct acpi_madt_entry_header header;
uint16_t: 16; // reserved
uint32_t processors_local_x2_apic_id;
union madt_local_apic_flags flags;
uint32_t acpi_id;
} att_packed;
struct acpi_type {
char name[4];
char *description;
void (*handle_table)(const struct acpi_sdt_header *addr);
};
#endif //NEW_KERNEL_STRUCTURES_H

View File

@@ -5,10 +5,13 @@
#ifndef NEW_KERNEL_PIC_H
#define NEW_KERNEL_PIC_H
#include <stdbool.h>
#include <sys/types.h>
void pic_init();
void pic_init(uint8_t isr_offset);
void pic_set_mask(uint16_t mask);
void pic_eoi(bool slave);
#endif //NEW_KERNEL_PIC_H

View File

@@ -7,12 +7,12 @@
#include <sys/types.h>
int init_timer(uint32_t freq);
int pit_init(uint32_t freq);
void print_current_tick();
uint32_t timer_get_tick();
uint32_t pit_get_tick();
void sleep(uint32_t milliseconds);
void pit_sleep(uint32_t milliseconds);
#endif //MY_KERNEL_TIMER_H

276
kernel/acpi/acpi.c Normal file
View File

@@ -0,0 +1,276 @@
//
// Created by rick on 22-08-21.
//
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <lai/core.h>
#include <lai/helpers/pc-bios.h>
#include <myke/acpi/acpi.h>
#include <myke/acpi/structures.h>
#include <myke/cpu/lapic.h>
#include <myke/libk/libk.h>
void acpi_handle_facp(const struct acpi_sdt_header *addr);
void acpi_handle_apic(const struct acpi_sdt_header *addr);
struct acpi_type acpi_types[] = {
{"APIC", "Multiple APIC Description Table (MADT)", acpi_handle_apic},
{"BGRT", "Boot Graphics Resource Table (BGRT; only supported on UEFI systems)", NULL},
{"BERT", "Boot Error Record Table (BERT)", NULL},
{"CPEP", "Corrected Platform Error Polling Table (CPEP)", NULL},
{"DSDT", "Differentiated System Description Table (DSDT)", NULL},
{"ECDT", "Embedded Controller Boot Resources Table (ECDT)", NULL},
{"EINJ", "Error Injection Table (EINJ)", NULL},
{"ERST", "Error Record Serialization Table (ERST)", NULL},
{"FACP", "Fixed ACPI Description Table (FADT)", acpi_handle_facp},
{"FACS", "Firmware ACPPI Control Structure (FACS)", NULL},
{"HEST", "Hardware Error Source Table (HEST)", NULL},
{"MSCT", "Maximum System Characteristics Table (MSCT)", NULL},
{"MPST", "Memory Power State Table (MPST)", NULL},
// {"OEMx", "OEM Specific Information Tables (Any table with a signature beginning with \"OEM\" falls into this definition)", NULL},
{"PMTT", "latform Memory Topology Table (PMTT)", NULL},
{"PSDT", "Persistent System Description Table (PSDT)", NULL},
{"RASF", "ACPI RAS FeatureTable (RASF)", NULL},
{"RSDT", "Root System Description Table (RSDT; 32-bit version of the XSDT)", NULL},
{"SBST", "Smart Battery Specification Table (SBST)", NULL},
{"SLIT", "System Locality System Information Table (SLIT)", NULL},
{"SRAT", "System Resource Affinity Table (SRAT)", NULL},
{"SSDT", "Secondary System Description Table (SSDT)", NULL},
{"XSDT", "Extended System Description Table (This wiki page; included for completeness)", NULL},
{"\0\0\0\0", NULL, NULL},
};
bool acpi_checksum(const void *table_addr, const size_t table_size) {
if (table_size < 1) {
return false; // invalid input
}
const uint8_t *table = table_addr;
uint8_t val = 0;
for (size_t i = 0; i < table_size; ++i) {
val += table[i];
}
return val == 0;
}
const struct acpi_rsdt *rsdt_table = NULL;
const struct acpi_xsdt *xsdt_table = NULL;
const struct acpi_fadt_t *fadt;
const struct acpi_sdt_header *dsdt;
void acpi_handle_facp(const struct acpi_sdt_header *addr) {
// parse the FACP/FADT
fadt = (const struct acpi_fadt_t *) addr;
if (fadt->header.revision > 5) {
// minor since 5.1
printf("ACPI Revision: %i.%i %.6s\n", fadt->header.revision, fadt->minor_version, fadt->header.oem);
} else {
printf("ACPI Revision: %i.0 %.6s\n", fadt->header.revision, fadt->header.oem);
}
if (fadt->x_dsdt != 0 && fadt->x_dsdt < UINT32_MAX) {
dsdt = (struct acpi_sdt_header *) fadt->x_dsdt;
} else if (fadt->dsdt != 0) {
dsdt = (struct acpi_sdt_header *) fadt->dsdt;
} else {
k_panics("No DSDT");
}
if (!acpi_checksum(dsdt, dsdt->length)) {
k_panics("DSDT is not valid");
}
}
void acpi_handle_apic(const struct acpi_sdt_header *addr) {
const struct acpi_madt *madt = (const struct acpi_madt *) addr;
printf("Local apic: %p %i\n", madt->local_apic_addr, madt->flags_int);
lapic_set_addr(madt->local_apic_addr);
const uint8_t *current = madt->entries;
const uint8_t *end = (const uint8_t *) (madt) + madt->header.length;
while (current < end) {
struct acpi_madt_entry_header *current_header = (struct acpi_madt_entry_header *) current;
switch (current_header->type) {
case MADT_TYPE_PROCESSOR_LOCAL_APIC: {
const struct acpi_madt_local_apic *la = (const struct acpi_madt_local_apic *) current_header;
printf("Local APIC %x for %x %x\n", la->apic_id, la->processor_id, la->flags);
break;
}
case MADT_TYPE_IO_APIC: {
const struct acpi_madt_io_apic *ia = (const struct acpi_madt_io_apic *) current_header;
printf("IO APIC %x at %x with %x\n", ia->apic_id, ia->io_apic_address,
ia->global_system_interrupt_base);
break;
}
case MADT_TYPE_IO_APIC_INTERRUPT_SOURCE_OVERRIDE: {
const struct acpi_madt_io_apic_interrupt_source_override *override = (const struct acpi_madt_io_apic_interrupt_source_override *) current_header;
printf("IO APIC Interrupt source override %x:%x -> %x %x\n", override->bus_source, override->irq_source,
override->global_system_interrupt, override->flags);
break;
}
case MADT_TYPE_IO_APIC_NON_MASKABLE_INTERRUPT_SOURCE: {
const struct acpi_madt_io_apic_non_maskable_interrupt *nmi = (const struct acpi_madt_io_apic_non_maskable_interrupt *) current_header;
printf("IO APIC NMI source %x %x %x\n", nmi->nmi_source, nmi->flags, nmi->global_system_interrupt);
break;
}
case MADT_TYPE_LOCAL_APIC_NON_MASKABLE_INTERRUPTS: {
const struct acpi_madt_local_apic_non_maskable_interrupts *nmi = (const struct acpi_madt_local_apic_non_maskable_interrupts *) current_header;
printf("Local APIC NMI CPU %x %x %x\n", nmi->acpi_processor_id, nmi->flags, nmi->lint_no);
break;
}
case MADT_TYPE_LOCAL_APIC_ADDRESS_OVERRIDE: {
const struct acpi_madt_local_apic_address_override *ao = (const struct acpi_madt_local_apic_address_override *) current_header;
printf("Local APIC addr override %x%x\n", ao->physical_address_local_apic >> 32,
ao->physical_address_local_apic & UINT32_MAX);
if (ao->physical_address_local_apic > UINT32_MAX) {
printf("Override above 4GB!");
} else {
lapic_set_addr(ao->physical_address_local_apic & UINT32_MAX);
}
break;
}
case MADT_TYPE_PROCESSOR_LOCAL_X2_APIC: {
const struct acpi_madt_processor_local_x2_apic *x2 = (const struct acpi_madt_processor_local_x2_apic *) current_header;
printf("Local x2APIC %x %x %x\n", x2->processors_local_x2_apic_id, x2->flags, x2->acpi_id);
break;
}
default:
printf("Unknown MADT entry %x", current_header->type);
break;
}
current += current_header->length;
}
printf("Lapic id %x v%x\n", lapic_get_id(), lapic_get_version());
}
void acpi_parse_table(uint32_t table_addr, uint32_t index) {
struct acpi_sdt_header *s_header = (struct acpi_sdt_header *) table_addr;
if (!acpi_checksum(s_header, s_header->length)) {
printf("%i: invalid acpi entry\n", index);
return;
}
struct acpi_type *c = &acpi_types[0];
while (c->name[0] != '\0') {
if (strncmp(s_header->signature, c->name, 4) == 0) {
printf("%i: %.4s %s\n", index, c->name, c->description);
if (c->handle_table != NULL) {
c->handle_table(s_header);
}
break;
}
c += 1;
}
if (c->name[0] == '\0') {
printf("%i: %.4s unknown\n", index, s_header->signature);
}
}
void acpi_parse_rsdt(uint32_t address) {
printf("Parsing RSDT\n");
rsdt_table = (const struct acpi_rsdt *) address;
if (!acpi_checksum(rsdt_table, rsdt_table->header.length)) {
k_panics("Malformed RSDT");
}
if (strncmp(rsdt_table->header.signature, "RSDT", 4) != 0) {
k_panics("RSDT pointer is not RSDT");
}
uint32_t entries = (rsdt_table->header.length - sizeof(struct acpi_sdt_header)) / sizeof(uint32_t);
for (uint32_t i = 0; i < entries; ++i) {
acpi_parse_table(rsdt_table->pointer_to_other_sdt[i], i);
}
}
void acpi_parse_xsdt(uint64_t address) {
printf("Parsing XSDT\n");
if (address > UINT32_MAX) {
k_panics("acpi table above 4GB");
}
xsdt_table = (const struct acpi_xsdt *) (uint32_t) address;
if (!acpi_checksum(xsdt_table, xsdt_table->header.length)) {
k_panics("Malformed XSDT");
}
if (strncmp(xsdt_table->header.signature, "XSDT", 4) != 0) {
k_panics("XSDT pointer is not XSDT");
}
uint32_t entries = (xsdt_table->header.length - sizeof(struct acpi_sdt_header)) / sizeof(uint64_t);
for (uint32_t i = 0; i < entries; ++i) {
const uint64_t entry_addr = xsdt_table->pointer_to_other_sdt[i];
if (entry_addr > UINT32_MAX) {
printf("%i: Above 4GB\n", i);
continue;
}
acpi_parse_table(xsdt_table->pointer_to_other_sdt[i], i);
}
}
void *acpi_find_table_by_name(const char *name, int skip) {
if (xsdt_table != NULL) {
uint32_t entries = (xsdt_table->header.length - sizeof(struct acpi_sdt_header)) / sizeof(uint64_t);
for (uint32_t i = 0; i < entries; ++i) {
const uint64_t entry_addr = xsdt_table->pointer_to_other_sdt[i];
if (entry_addr > UINT32_MAX) {
printf("%i: Above 4GB\n", i);
continue;
}
struct acpi_sdt_header *header = (struct acpi_sdt_header *) xsdt_table->pointer_to_other_sdt[i];
if (!acpi_checksum(header, header->length)) {
printf("Invalid header %d", i);
continue;
}
if (strncmp(header->signature, name, 4) == 0) {
if (skip > 0) {
skip--;
continue;
}
return header;
}
}
}
if (rsdt_table != NULL) {
uint32_t entries = (rsdt_table->header.length - sizeof(struct acpi_sdt_header)) / sizeof(uint32_t);
for (uint32_t i = 0; i < entries; ++i) {
struct acpi_sdt_header *header = (struct acpi_sdt_header *) rsdt_table->pointer_to_other_sdt[i];
if (!acpi_checksum(header, header->length)) {
printf("Invalid header %d", i);
continue;
}
if (strncmp(header->signature, name, 4) == 0) {
if (skip > 0) {
skip--;
continue;
}
return header;
}
}
}
// check if DSDT is requested, but was not present as normal table
if (strncmp(name, "DSDT", 4) == 0) {
return (void *) dsdt;
}
return NULL;
}
void acpi_parse() {
struct lai_rsdp_info lai_rsdp_info;
lai_api_error_t result = lai_bios_detect_rsdp(&lai_rsdp_info);
if (result != LAI_ERROR_NONE) {
printf("LAI: could not find rsdp: %s\n", lai_api_error_to_string(result));
k_panics("Could not init ACPI");
}
lai_set_acpi_revision(lai_rsdp_info.acpi_version);
if (lai_rsdp_info.xsdt_address != 0) {
acpi_parse_xsdt(lai_rsdp_info.xsdt_address);
} else if (lai_rsdp_info.rsdt_address != 0) {
acpi_parse_rsdt(lai_rsdp_info.rsdt_address);
} else {
k_panics("No rsdt nor xsdt");
}
}
void acpi_init() {
lai_create_namespace();
}

80
kernel/acpi/lailayer.c Normal file
View File

@@ -0,0 +1,80 @@
//
// Created by rick on 26-08-21.
//
#include <stdio.h>
#include <stdlib.h>
#include <lai/host.h>
#include <myke/acpi/acpi.h>
#include <myke/drivers/ports.h>
#include <myke/libk/libk.h>
const char *lai_loglevel_str(int level) {
switch (level) {
case LAI_DEBUG_LOG:
return "debug ";
case LAI_WARN_LOG:
return "warn ";
default:
return "unknown";
}
}
void laihost_log(int level, const char *msg) {
printf("lai [%s]: %s\n", lai_loglevel_str(level), msg);
}
void laihost_panic(const char *msg) {
k_panics(msg);
}
void *laihost_malloc(size_t size) {
return malloc(size);
}
void *laihost_realloc(void *data, size_t size, size_t old_size) {
return realloc(data, size);
}
void laihost_free(void *data, size_t size) {
free(data);
}
void *laihost_map(size_t address, size_t size) {
return (void *) address;
}
void laihost_unmap(void *pointer, size_t count) {
}
void *laihost_scan(const char *sig, size_t index) {
return acpi_find_table_by_name(sig, (int)index);
}
void laihost_outb(uint16_t port, uint8_t val) {
port_byte_out(port, val);
}
void laihost_outw(uint16_t port, uint16_t val) {
port_word_out(port, val);
}
void laihost_outd(uint16_t port, uint32_t val) {
port_double_word_out(port, val);
}
uint8_t laihost_inb(uint16_t port) {
return port_byte_in(port);
}
uint16_t laihost_inw(uint16_t port) {
return port_word_in(port);
}
uint32_t laihost_ind(uint16_t port) {
return port_double_word_in(port);
}
void laihost_sleep(uint64_t ms) {
return; // todo implement for real system
}

View File

@@ -9,7 +9,7 @@
#include <readline/readline.h>
#include <myke/command.h>
#include <myke/cpu/timer.h>
#include <myke/cpu/pit.h>
#include <myke/drivers/pci/ide.h>
#include <myke/drivers/pci/pci.h>
#include <myke/vfs/blockdev.h>

View File

@@ -9,12 +9,9 @@
#include <myke/cpu/idt.h>
#include <myke/cpu/pic.h>
#include <myke/cpu/syscall_handler.h>
#include <myke/drivers/ports.h>
#include <myke/libk/libk.h>
#include <myke/tasks/task.h>
#define PIC_END_OF_INTERRUPT 0x20
isr_t interrupt_handlers[256];
void isr_install() {
@@ -52,8 +49,7 @@ void isr_install() {
set_idt_gate(31, (uint32_t) isr31);
// Remap the PIC
// todo make readable
pic_init();
pic_init(IRQ0);
// Install the IRQs
set_idt_gate(32, (uint32_t) irq0); // 0x20
@@ -73,6 +69,7 @@ void isr_install() {
set_idt_gate(46, (uint32_t) irq14);
set_idt_gate(47, (uint32_t) irq15);
// 0x80 SYSCALL
set_idt_gate(128, (uint32_t) isr128);
set_idt(); // Load with ASM
@@ -116,7 +113,7 @@ char *exception_messages[] = {
"Reserved"
};
void isr_handler(isr_registers_t r) {
void att_used isr_handler(isr_registers_t r) {
char msg[256];
if (r.int_no == 128) {
syscall_handle(&r);
@@ -131,11 +128,10 @@ void register_interrupt_handler(uint8_t n, isr_t handler) {
interrupt_handlers[n] = handler;
}
void irq_handler(isr_registers_t r) {
void att_used irq_handler(isr_registers_t r) {
/* After every interrupt we need to send an EOI to the PICs
* or they will not send another interrupt again */
if (r.int_no >= 40) port_byte_out(PORT_PIC_SLAVE_COMMAND, PIC_END_OF_INTERRUPT); /* slave */
port_byte_out(PORT_PIC_MASTER_COMMAND, PIC_END_OF_INTERRUPT); /* master */
pic_eoi(r.int_no >= IRQ8);
if (r.int_no >= IRQ0 && r.int_no < IRQ15) {
task_notify_irq(r.int_no - IRQ0);

View File

@@ -1,6 +1,7 @@
//
// Created by rick on 22-08-21.
//
#include <stdbool.h>
#include <myke/cpu/pic.h>
#include <myke/drivers/ports.h>
@@ -17,15 +18,17 @@
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
void pic_init() {
#define PIC_END_OF_INTERRUPT 0x20
void pic_init(uint8_t isr_offset) {
// init both master and slave pic's
port_byte_out(PORT_PIC_MASTER_COMMAND, ICW1_INIT | ICW1_ICW4);
port_byte_out(PORT_PIC_SLAVE_COMMAND, ICW1_INIT | ICW1_ICW4);
// master with ICW4 offset 20, Slave on IRQ2, 8086 mode,
// master with ICW4 offset isr_offset, Slave on IRQ2, 8086 mode,
// ICW2
port_byte_out(PORT_PIC_MASTER_DATA, 0x20); // offset master
port_byte_out(PORT_PIC_SLAVE_DATA, 0x28); // offset slave
port_byte_out(PORT_PIC_MASTER_DATA, isr_offset); // offset master
port_byte_out(PORT_PIC_SLAVE_DATA, isr_offset + 8); // offset slave
// ICW3
port_byte_out(PORT_PIC_MASTER_DATA, 0x04); // slave PIC at IRQ2
port_byte_out(PORT_PIC_SLAVE_DATA, 0x02); // cascade identity
@@ -39,5 +42,10 @@ void pic_init() {
void pic_set_mask(uint16_t mask) {
port_byte_out(PORT_PIC_MASTER_DATA, mask & 0xFF);
port_byte_out(PORT_PIC_SLAVE_DATA, mask << 8);
port_byte_out(PORT_PIC_SLAVE_DATA, mask >> 8);
}
void pic_eoi(bool slave) {
if (slave) port_byte_out(PORT_PIC_SLAVE_COMMAND, PIC_END_OF_INTERRUPT); /* slave */
port_byte_out(PORT_PIC_MASTER_COMMAND, PIC_END_OF_INTERRUPT); /* master */
}

View File

@@ -5,7 +5,7 @@
#include <string.h>
#include <stdlib.h>
#include <myke/cpu/timer.h>
#include <myke/cpu/pit.h>
#include <myke/drivers/ports.h>
#include <myke/cpu/isr.h>
#include <myke/libk/libk.h>
@@ -33,19 +33,37 @@
#define PIT_CHANNEL_1 (0b01 << 6)
#define PIT_CHANNEL_2 (0b10 << 6)
#define PIT_CHANNEL_READ_BACK (0b11 << 6)
#define PIT_RB_LATCH_COUNT (0)
#define PIT_RB_LATCH_NO_COUNT (1 << 5)
#define PIT_RB_LATCH_STATUS (0)
#define PIT_RB_LATCH_NO_STATUS (1 << 4)
#define PIT_RB_CHANNEL_2 (1 << 3)
#define PIT_RB_CHANNEL_1 (1 << 2)
#define PIT_RB_CHANNEL_0 (1 << 1)
#define PIT_STATUS_OUTPUT_STATE (1 << 7)
#define PIT_STATUS_NULL_COUNT (1 << 6)
#define PIT_STATUS_ACCESS_MODE (0b11 >> 4)
#define PIT_STATUS_OPERATING_MODE (0b111 < 1)
#define PIT_STATUS_BCD_BIN (1)
#define PIT_FREQUENCY 1193182 /*Hz*/
uint32_t tick = 0;
static void timer_callback(isr_registers_t *regs) {
uint32_t pit_ms_to_div(uint32_t ms) {
uint32_t divisor = PIT_FREQUENCY / ms;
return divisor;
}
static void pit_callback(isr_registers_t *regs) {
tick++;
task_switch_next();
}
uint32_t timer_get_tick() {
uint32_t pit_get_tick() {
return tick;
}
void sleep(uint32_t milliseconds) {
void pit_sleep(uint32_t milliseconds) {
uint32_t done = tick + milliseconds;
while (tick != done) {
k_wait_for_interrupt();
@@ -60,10 +78,10 @@ void print_current_tick() {
kprint("\n");
}
int init_timer(uint32_t freq) {
register_interrupt_handler(IRQ0, timer_callback);
int pit_init(uint32_t freq) {
register_interrupt_handler(IRQ0, pit_callback);
uint32_t divisor = 1193180 / freq;
uint32_t divisor = PIT_FREQUENCY / freq;
uint8_t low = (uint8_t) (divisor & 0xFF);
uint8_t high = (uint8_t) ((divisor >> 8) & 0xFF);
port_byte_out(PORT_PIT_COMMAND,
@@ -72,3 +90,21 @@ int init_timer(uint32_t freq) {
port_byte_out(PORT_PIT_DATA_0, high);
return 0;
}
// pit_sleep without interrupts
void pit_sleep_ms(const uint32_t sleep) {
// todo locking
uint32_t divider = pit_ms_to_div(sleep);
if (divider > UINT16_MAX) {
k_panics("Sleep for to long");
}
port_byte_out(PORT_PIT_COMMAND,
PIT_MODE_BIN | PIT_MODE_INTERRUPT_ON_TERMINAL_COUNT | PIT_ACCESS_MODE_LH | PIT_CHANNEL_0);
port_byte_out(PORT_PIT_DATA_0, divider & 0xFF);
port_byte_out(PORT_PIT_DATA_0, divider >> 8);
do {
__builtin_ia32_pause();
port_byte_out(PORT_PIT_COMMAND,
PIT_CHANNEL_READ_BACK | PIT_RB_CHANNEL_0 | PIT_RB_LATCH_NO_COUNT | PIT_RB_LATCH_STATUS);
} while (port_byte_in(PORT_PIT_DATA_0) & PIT_STATUS_OUTPUT_STATE);
}

View File

@@ -9,7 +9,7 @@
#include <stdlib.h>
#include <sys/types.h>
#include <myke/cpu/timer.h>
#include <myke/cpu/pit.h>
#include <myke/debug/debug.h>
#include <myke/drivers/pci/ide.h>
#include <myke/drivers/pci/pci.h>
@@ -395,6 +395,10 @@ void ide_register_block_devices() {
if (!ide_devices[i].reserved) {
continue;
}
if (ide_devices[i].type == IDE_ATAPI) {
// skip ATAPI for now
continue;
}
ide_block_device_info *info = malloc(sizeof(ide_block_device_info)); // todo free for this one
info->device_number = i;
@@ -451,11 +455,11 @@ uint8_t att_used ide_pci_initialize(pci_device *device) {
// (I) Select Drive:
ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive.
sleep(1); // Wait 1ms for drive select to work.
pit_sleep(1); // Wait 1ms for drive select to work.
// (II) Send ATA Identify Command:
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
sleep(1); // This function should be implemented in your OS. which waits for 1 ms.
pit_sleep(1); // This function should be implemented in your OS. which waits for 1 ms.
// it is based on System Timer Device Driver.
// (III) Polling:
@@ -485,7 +489,7 @@ uint8_t att_used ide_pci_initialize(pci_device *device) {
}
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);
sleep(1);
pit_sleep(1);
}
// (V) Read Identification Space of the Device:

View File

@@ -4,11 +4,12 @@
#define DEBUG_INIT
#include <myke/acpi/acpi.h>
#include <myke/command.h>
#include <myke/cpu/cpuidx.h>
#include <myke/cpu/gdt.h>
#include <myke/cpu/isr.h>
#include <myke/cpu/timer.h>
#include <myke/cpu/pit.h>
#include <myke/debug/debug.h>
#include <myke/drivers/keyboard.h>
#include <myke/drivers/pci/pci.h>
@@ -64,6 +65,10 @@ void att_noreturn att_used kmain(multiboot_info_t *multiboot_info, uint32_t mb_n
// initialize kprint functionality
kprint_init();
// todo earlier in boot
acpi_parse();
acpi_init();
debug_store_info(multiboot_info);
// identify cpu
@@ -72,7 +77,7 @@ void att_noreturn att_used kmain(multiboot_info_t *multiboot_info, uint32_t mb_n
// enable interrupts
__asm__ __volatile__("sti");
// start the timer
init_timer(1000);
pit_init(1000);
// initialize devices
init_keyboard();
init_pci_system();

View File

@@ -85,6 +85,7 @@ uint32_t vasprintf(char *buf, const char *fmt, va_list args) {
buf[ptr++] = (char) va_arg(args, int);
break;
case 'x':
case 'p':
case 'X': // todo capitalize
print_int((uint32_t) va_arg(args, uint32_t), field_width, buf, &ptr, 16);
break;

View File

@@ -4,13 +4,12 @@
#include <attributes.h>
#include <myke/drivers/ports.h>
#include <lai/helpers/pm.h>
#include <myke/libk/libk.h>
#include <myke/util/power.h>
void att_noreturn power_shutdown() {
port_word_out(PORT_ACPI, PORT_ACPI_SHUTDOWN);
port_word_out(PORT_QEMU_COMMAND, PORT_QEMU_COMMAND_SHUTDOWN);
port_word_out(PORT_VBOX, PORT_VBOX_SHUTDOWN);
lai_enter_sleep(5);
k_panics("Failed to shut down!\n");
}

1
lai Submodule

Submodule lai added at 432546ee09