#include "parser/madt_parser.h"
-static acpi_context* toc = NULL;
+static acpi_context* ctx = NULL;
LOG_MODULE("ACPI")
acpi_rsdt_t* rsdt = rsdp->rsdt;
- toc = lxcalloc(1, sizeof(acpi_context));
- assert_msg(toc, "Fail to create ACPI context");
+ ctx = lxcalloc(1, sizeof(acpi_context));
+ assert_msg(ctx, "Fail to create ACPI context");
- strncpy(toc->oem_id, rsdt->header.oem_id, 6);
- toc->oem_id[6] = '\0';
+ strncpy(ctx->oem_id, rsdt->header.oem_id, 6);
+ ctx->oem_id[6] = '\0';
size_t entry_n = (rsdt->header.length - sizeof(acpi_sdthdr_t)) >> 2;
for (size_t i = 0; i < entry_n; i++) {
acpi_sdthdr_t* sdthdr = ((acpi_apic_t**)&(rsdt->entry))[i];
switch (sdthdr->signature) {
case ACPI_MADT_SIG:
- madt_parse((acpi_madt_t*)sdthdr, toc);
+ madt_parse((acpi_madt_t*)sdthdr, ctx);
+ break;
+ case ACPI_FADT_SIG:
+ // FADT just a plain structure, no need to parse.
+ ctx->fadt = *(acpi_fadt_t*)sdthdr;
break;
default:
break;
}
}
- kprintf(KINFO "OEM: %s\n", toc->oem_id);
- kprintf(KINFO "IOAPIC address: %p\n", toc->madt.ioapic->ioapic_addr);
- kprintf(KINFO "APIC address: %p\n", toc->madt.apic_addr);
+ kprintf(KINFO "OEM: %s\n", ctx->oem_id);
+ kprintf(KINFO "IOAPIC address: %p\n", ctx->madt.ioapic->ioapic_addr);
+ kprintf(KINFO "APIC address: %p\n", ctx->madt.apic_addr);
for (size_t i = 0; i < 24; i++) {
- acpi_intso_t* intso = toc->madt.irq_exception[i];
+ acpi_intso_t* intso = ctx->madt.irq_exception[i];
if (!intso)
continue;
acpi_context*
acpi_get_context()
{
- assert_msg(toc, "ACPI is not initialized");
- return toc;
+ assert_msg(ctx, "ACPI is not initialized");
+ return ctx;
}
int
uint8_t* mem_start = 0x4000;
for (; mem_start < 0x100000; mem_start += 16) {
uint32_t sig_low = *((uint32_t*)(mem_start));
+ // XXX: do we need to compare this as well?
// uint32_t sig_high = *((uint32_t*)(mem_start+j) + 1);
if (sig_low == ACPI_RSDP_SIG_L) {
rsdp = (acpi_rsdp_t*)(mem_start);
#include "sdt.h"
#include "madt.h"
+#include "fadt.h"
+
+// * for quick conversion from a table name into ACPI favoured signature
+// * use `echo <TableName> | xxd -eg4`
#define ACPI_RSDP_SIG_L 0x20445352 // 'RSD '
#define ACPI_RSDP_SIG_H 0x20525450 // 'PTR '
#define ACPI_MADT_SIG 0x43495041 // 'APIC'
+#define ACPI_FADT_SIG 0x50434146 // 'FACP' Notice that it is not 'FADT'.
typedef struct {
uint32_t signature_l;
// Make it as null terminated
char oem_id[7];
acpi_madt_toc_t madt;
+ acpi_fadt_t fadt;
} acpi_context;
int
--- /dev/null
+#ifndef __LUNAIX_FADT_H
+#define __LUNAIX_FADT_H
+
+#include "sdt.h"
+
+// Pulled from ACPI Specification (v6.4) section 5.2.9
+
+enum PMProfile {
+ Desktop = 1,
+ Mobile = 2,
+ Workstation = 3,
+ EnterpriseServer = 4,
+ SOHOServer = 5,
+ AppliancePC = 6,
+ PerformanceServer = 7,
+ Tablet = 8,
+};
+
+#define IPM1AEVT_BLK_PORT 0
+#define IPM1BEVT_BLK_PORT 1
+#define IPM1ACNT_BLK_PORT 2
+#define IPM1BCNT_BLK_PORT 3
+#define IPM2CNT_BLK_PORT 4
+#define IPMTMR_BLK_PORT 5
+
+#define IPM1EVT_BLK_LEN 0
+#define IPM1CNT_BLK_LEN 1
+#define IPM2CNT_BLK_LEN 2
+#define IPMTMR_BLK_LEN 3
+
+#define ITIME_DAY_ALARM 0
+#define ITIME_MON_ALARM 1
+#define ITIME_CENTURY 2
+
+#define IAPC_ARCH_LEGACY 0x1
+#define IAPC_ARCH_8042 0x2
+#define IAPC_ARCH_NO_VGA 0x4
+#define IAPC_ARCH_NO_MSI 0x8
+#define IAPC_ARCH_ASPM 0x10
+#define IAPC_ARCH_NO_RTC 0x20
+
+typedef struct acpi_fadt {
+ acpi_sdthdr_t header;
+ uint32_t firmware_controller_addr;
+ uint32_t dsdt_addr;
+ uint8_t pm_profile;
+ uint16_t sci_int;
+ uint32_t smi_cmd_port_addr;
+ uint8_t smi_acpi_enable;
+ uint8_t smi_acpi_disable;
+ uint8_t smi_s4bios_state;
+ uint8_t smi_pstate;
+ uint32_t pm_reg_ports[6];
+ uint32_t gpe0_port_addr;
+ uint32_t gpe1_port_addr;
+ uint8_t pm_reg_lens[4];
+ uint8_t gpe0_len;
+ uint8_t gpe1_len;
+ uint8_t gpe1_base;
+ uint8_t cst_cnt;
+ uint16_t p_lvl2_lat;
+ uint16_t p_lvl3_lat;
+ uint16_t flush_size;
+ uint16_t flush_stride;
+ uint8_t duty_offset;
+ uint8_t duty_width;
+ uint8_t time_info[3];
+ uint16_t boot_arch;
+} ACPI_TABLE_PACKED acpi_fadt_t;
+
+
+// TODO: FADT parser & support
+
+#endif /* __LUNAIX_FADT_H */
{
uint8_t type;
uint8_t length;
-} __attribute__((packed)) acpi_ics_hdr_t;
+} ACPI_TABLE_PACKED acpi_ics_hdr_t;
/**
* @brief ACPI Processor Local APIC Structure (PLAS)
uint8_t processor_id;
uint8_t apic_id;
uint32_t flags;
-} __attribute__((packed)) acpi_apic_t;
+} ACPI_TABLE_PACKED acpi_apic_t;
/**
* @brief ACPI IO APIC Structure (IOAS)
uint32_t ioapic_addr;
// The global system interrupt offset for this IOAPIC. (Kind of IRQ offset for a slave IOAPIC)
uint32_t gis_offset;
-} __attribute__((packed)) acpi_ioapic_t;
+} ACPI_TABLE_PACKED acpi_ioapic_t;
/**
* @brief ACPI Interrupt Source Override (INTSO)
// global system interrupt. The override of source in APIC mode
uint32_t gsi;
uint16_t flags;
-} __attribute__((packed)) acpi_intso_t;
+} ACPI_TABLE_PACKED acpi_intso_t;
typedef struct
{
void* apic_addr;
uint32_t flags;
// Here is a bunch of packed ICS reside here back-to-back.
-} __attribute__((packed)) acpi_madt_t;
+} ACPI_TABLE_PACKED acpi_madt_t;
typedef struct
{
acpi_apic_t* apic;
acpi_ioapic_t* ioapic;
acpi_intso_t** irq_exception;
-} __attribute__((packed)) acpi_madt_toc_t;
+} ACPI_TABLE_PACKED acpi_madt_toc_t;
#endif /* __LUNAIX_ACPI_MADT_H */
#include <stdint.h>
-typedef struct
+#define ACPI_TABLE_PACKED __attribute__((packed))
+
+typedef struct acpi_sdthdr
{
uint32_t signature;
uint32_t length;
uint32_t oem_rev;
uint32_t vendor_id;
uint32_t vendor_rev;
-} __attribute__((packed)) acpi_sdthdr_t;
+} ACPI_TABLE_PACKED acpi_sdthdr_t;
-typedef struct
+typedef struct acpi_rsdt
{
acpi_sdthdr_t header;
acpi_sdthdr_t* entry;
-} __attribute__((packed)) acpi_rsdt_t;
+} ACPI_TABLE_PACKED acpi_rsdt_t;
#endif /* __LUNAIX_ACPI_SDT_H */
#include <lunaix/timer.h>
#include <lunaix/common.h>
#include <lunaix/syslog.h>
+#include <hal/acpi/acpi.h>
#include <hal/cpu.h>
#include <arch/x86/interrupts.h>
kbd_state.translation_table = scancode_set2;
kbd_state.state = KBD_STATE_KWAIT;
+ acpi_context* acpi_ctx = acpi_get_context();
+ if (!(acpi_ctx->fadt.boot_arch & IAPC_ARCH_8042)) {
+ kprintf(KERROR "No PS/2 controller detected.\n");
+ // FUTURE: Some alternative fallback on this? Check PCI bus for USB controller instead?
+ return;
+ }
+
cpu_disable_interrupt();
- // XXX: 是否需要使用FADT探测PS/2控制器的存在?
-
// 1、禁用任何的PS/2设备
ps2_post_cmd(PS2_PORT_CTRL_CMDREG, PS2_CMD_PORT1_DISABLE, PS2_NO_ARG);
ps2_post_cmd(PS2_PORT_CTRL_CMDREG, PS2_CMD_PORT2_DISABLE, PS2_NO_ARG);