git-svn-id: svn://kolibrios.org@2293 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2011-10-17 12:16:37 +00:00
parent 6cfca28b78
commit f86662005e
8 changed files with 720 additions and 0 deletions

View File

@ -0,0 +1,50 @@
CC = gcc
FASM = e:/fasm/fasm.exe
CFLAGS = -c -O2 -fomit-frame-pointer -fno-builtin-printf
DRV_DIR = $(CURDIR)/../..
DRV_INCLUDES = $(DRV_DIR)/include
INCLUDES = -I$(DRV_INCLUDES) -I$(DRV_DIR)/include/linux
DEFINES = -D__KERNEL__ -DCONFIG_X86_32
LDFLAGS = -nostdlib -shared -s -Map acpi.map --image-base 0\
--file-alignment 512 --section-alignment 4096
LIBPATH:= -L$(DRV_DIR)/ddk
LIBS:= -lgcc -lddk -lcore
NAME= acpi
NAME_SRCS= main.c \
acpi.c \
utils.asm
all: $(NAME).dll
NAME_OBJS = $(patsubst %.S, %.o, $(patsubst %.asm, %.o,\
$(patsubst %.c, %.o, $(NAME_SRCS))))
$(NAME).dll: $(NAME_OBJS) acpi.lds Makefile
ld $(LIBPATH) $(LDFLAGS) -T acpi.lds -o $@ $(NAME_OBJS) $(LIBS)
%.o : %.c $(HFILES) Makefile
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
%.o : %.S $(HFILES) Makefile
as -o $@ $<
%.o : %.asm $(HFILES) Makefile
fasm $< $@

View File

@ -0,0 +1,50 @@
#include <ddk.h>
#include <syscall.h>
#include "acpi.h"
extern acpi_rsdp_t* acpi_rsdp;
extern acpi_rsdt_t* acpi_rsdt;
addr_t acpi_ioapic;
addr_t acpi_local_apic;
u8_t __fastcall acpi_table_checksum(u32_t length, u8_t *buffer);
acpi_rsdp_t* acpi_locate()
{
/** @todo checksum, check version */
addr_t p;
for (p = ACPI_HI_RSDP_WINDOW_START; p < ACPI_HI_RSDP_WINDOW_END; p+=16)
{
acpi_rsdp_t* r = (acpi_rsdp_t*) p;
if ((r->sig[0] == 0x20445352) &&
(r->sig[1] == 0x20525450) &&
acpi_table_checksum(ACPI_RSDP_CHECKSUM_LENGTH, (u8_t*)r)==0 )
{
return r;
};
};
/* not found */
return NULL;
};
addr_t __fastcall rsdt_find(acpi_rsdt_t *rsdt, u32_t sig)
{
addr_t head = 0;
u32_t i;
for (i = 0; i < ((rsdt->header.len-sizeof(acpi_thead_t))/
sizeof(rsdt->ptrs[0])); i++)
{
acpi_thead_t* t= (acpi_thead_t*)acpi_remap_table(rsdt->ptrs[i]);
if (t->sig == sig)
{
head = rsdt->ptrs[i];
break;
};
}
return head;
};

View File

@ -0,0 +1,164 @@
#include <ddk.h>
#include <syscall.h>
#include "acpi.h"
extern acpi_rsdp_t* acpi_rsdp;
extern acpi_rsdt_t* acpi_rsdt;
addr_t acpi_ioapic;
addr_t acpi_local_apic;
u8_t __fastcall acpi_table_checksum(u32_t length, u8_t *buffer);
u8_t __fastcall acpi_table_checksum(u32_t length, u8_t *buffer)
{
u8_t sum = 0;
u8_t *end = buffer + length;
while (buffer < end)
{
sum = (u8_t)(sum + *(buffer++));
}
return sum;
};
void* acpi_remap_table(addr_t table)
{
addr_t ptr;
if( (table >= acpi_rsdp->rsdt_ptr)&&
(table < acpi_rsdp->rsdt_ptr+0x10000))
ptr = (table - acpi_rsdp->rsdt_ptr+(addr_t)acpi_rsdt);
return (void*)ptr;
};
void print_rsdt(acpi_rsdt_t *rsdt)
{
u32_t i;
dbgprintf("ACPI RSD Table\n");
for (i = 0; i < ((rsdt->header.len-sizeof(acpi_thead_t))/
sizeof(rsdt->ptrs[0])); i++)
{
acpi_thead_t* t = (acpi_thead_t*)acpi_remap_table(rsdt->ptrs[i]);
char *p = (char*)&t->sig;
dbgprintf("sig %d: %c%c%c%c base %x\n", i,
p[0],p[1],p[2],p[3], t);
};
};
void print_madt (acpi_madt_t * madt)
{
u32_t i;
acpi_local_apic = madt->local_apic_addr;
dbgprintf ("Local APIC at 0x%x\n\n", acpi_local_apic);
for (i = 0; i < (madt->header.len - sizeof (acpi_madt_t));)
{
acpi_madt_hdr_t * h = (acpi_madt_hdr_t*) &madt->data[i];
switch (h->type)
{
case 0:
{
// Local APIC
acpi_madt_lapic_t * lapic = (acpi_madt_lapic_t *) h;
dbgprintf ("Local APIC ");
dbgprintf ("[Id: 0x%x, CPU Id: 0x%x, %s]\n",
lapic->id, lapic->apic_processor_id,
lapic->flags.enabled ? "enabled" : "disabled");
break;
}
case 1:
{
// I/O Apic
acpi_madt_ioapic_t * ioapic = (acpi_madt_ioapic_t *) h;
acpi_ioapic = ioapic->address;
dbgprintf ("I/O APIC ");
dbgprintf ("[Id: 0x%x, IRQ base: %d, Addr: 0x%x]\n",
ioapic->id, ioapic->irq_base, acpi_ioapic);
break;
}
case 2:
{
// Interrupt Source Override
acpi_madt_irq_t * irq = (acpi_madt_irq_t *) h;
polarity_t p = irq_get_polarity(irq);
trigger_mode_t t = irq_get_trigger_mode(irq);
dbgprintf ("Interrupt Override ");
dbgprintf ("[%s, Bus IRQ: %d, Glob IRQ: %d, Pol: %s, Trigger: %s]\n",
irq->src_bus == 0 ? "ISA" : "unknown bus",
irq->src_irq, irq->dest,
p == conform_polarity ? "conform" :
p == active_high ? "active high" :
p == active_low ? "active low" : "?",
t == conform_trigger ? "conform" :
t == edge ? "edge" :
t == level ? "level" : "?");
break;
}
case 3:
{
// NMI Source
acpi_madt_nmi_t * nmi = (acpi_madt_nmi_t *) h;
polarity_t p = nmi_get_polarity(nmi);
trigger_mode_t t = nmi_get_trigger_mode(nmi);
dbgprintf ("NMI Source ");
dbgprintf ("[Glob IRQ: %d, Pol: %s, Trigger: %s]\n",
nmi->irq,
p == conform_polarity ? "conform" :
p == active_high ? "active high" :
p == active_low ? "active low" : "?",
t == conform_trigger ? "conform" :
t == edge ? "edge" :
t == level ? "level" : "?");
break;
}
case 4:
{
// Local APIC NMI
acpi_lapic_nmi_t *nmi = (acpi_lapic_nmi_t *) h;
polarity_t p = lapic_nmi_get_polarity(nmi);
trigger_mode_t t = lapic_nmi_get_trigger_mode(nmi);
dbgprintf ("Local APIC NMI\n");
dbgprintf ("[CPU id: %d, LINT#: %d Pol: %s, Trigger: %s]\n",
nmi->apic_processor_id,
nmi->lint,
p == conform_polarity ? "conform" :
p == active_high ? "active high" :
p == active_low ? "active low" : "?",
t == conform_trigger ? "conform" :
t == edge ? "edge" :
t == level ? "level" : "?");
break;
}
case 5:
{
// Local APIC Address Override
dbgprintf ("Local APIC Address Override\n");
break;
}
case 8:
{
// Platform Interrupt Source
dbgprintf ("Platform Interrupt Source\n");
break;
}
}
i += h->len;
}
};

View File

@ -0,0 +1,250 @@
#define ACPI_NAME_SIZE 4
#define ACPI_OEM_ID_SIZE 6
#define ACPI_OEM_TABLE_ID_SIZE 8
typedef struct __attribute__((packed))
{
u8_t type;
u8_t len;
}acpi_madt_hdr_t;
typedef struct __attribute__((packed))
{
acpi_madt_hdr_t header;
u8_t apic_processor_id;
u8_t id;
struct {
u32_t enabled : 1;
u32_t : 31;
} flags;
}acpi_madt_lapic_t;
typedef struct __attribute__((packed))
{
acpi_madt_hdr_t header;
u8_t id; /* APIC id */
u8_t _rsvd_3;
u32_t address; /* physical address */
u32_t irq_base; /* global irq number base */
}acpi_madt_ioapic_t;
typedef enum {
conform_polarity = 0,
active_high = 1,
reserved_polarity = 2,
active_low = 3
}polarity_t ;
typedef enum {
conform_trigger = 0,
edge = 1,
reserved_trigger = 2,
level = 3
}trigger_mode_t;
typedef struct __attribute__((packed))
{
acpi_madt_hdr_t header;
u8_t src_bus; /* source bus, fixed 0=ISA */
u8_t src_irq; /* source bus irq */
u32_t dest; /* global irq number */
union {
u16_t flags; /* irq flags */
struct {
u16_t polarity : 2;
u16_t trigger_mode : 2;
u16_t reserved : 12;
} x;
};
}acpi_madt_irq_t;
static inline polarity_t irq_get_polarity(acpi_madt_irq_t *irq)
{ return (polarity_t) irq->x.polarity; }
static inline trigger_mode_t irq_get_trigger_mode(acpi_madt_irq_t *irq)
{ return (trigger_mode_t) irq->x.trigger_mode; }
typedef struct __attribute__((packed))
{
acpi_madt_hdr_t header;
union {
u16_t flags;
struct {
u16_t polarity : 2;
u16_t trigger_mode : 2;
u16_t reserved : 12;
} x;
};
u32_t irq;
}acpi_madt_nmi_t;
static inline polarity_t nmi_get_polarity(acpi_madt_nmi_t *nmi)
{ return (polarity_t) nmi->x.polarity; }
static inline trigger_mode_t nmi_get_trigger_mode(acpi_madt_nmi_t *nmi)
{ return (trigger_mode_t) nmi->x.trigger_mode; }
typedef struct __attribute__((packed))
{
acpi_madt_hdr_t header;
u8_t apic_processor_id;
union {
u16_t flags;
struct {
u16_t polarity : 2;
u16_t trigger_mode : 2;
u16_t reserved : 12;
} x;
};
u8_t lint;
}acpi_lapic_nmi_t;
static inline polarity_t lapic_nmi_get_polarity(acpi_lapic_nmi_t *nmi)
{ return (polarity_t) nmi->x.polarity; }
static inline trigger_mode_t lapic_nmi_get_trigger_mode(acpi_lapic_nmi_t *nmi)
{ return (trigger_mode_t) nmi->x.trigger_mode; }
typedef struct __attribute__((packed))
{
u32_t sig;
u32_t len;
u8_t rev;
u8_t csum;
char oem_id[ACPI_OEM_ID_SIZE];
char oem_tid[ACPI_OEM_TABLE_ID_SIZE];
u32_t oem_rev;
u32_t creator_id;
u32_t creator_rev;
}acpi_thead_t;
typedef struct __attribute__((packed))
{
acpi_thead_t header;
u32_t local_apic_addr;
u32_t apic_flags;
u8_t data[0];
} acpi_madt_t;
typedef struct __attribute__((packed))
{
acpi_thead_t header;
u32_t ptrs[0];
}acpi_rsdt_t;
typedef struct __attribute__((packed))
{
acpi_thead_t header;
u64_t ptrs[0];
}acpi_xsdt_t;
typedef struct
{
u32_t sig[2];
u8_t csum;
char oemid[6];
u8_t rev;
u32_t rsdt_ptr;
u32_t rsdt_len;
u64_t xsdt_ptr;
u8_t xcsum;
u8_t _rsvd_33[3];
}acpi_rsdp_t;
typedef struct __attribute__((packed))
{
u8_t SpaceId; /* Address space where struct or register exists */
u8_t BitWidth; /* Size in bits of given register */
u8_t BitOffset; /* Bit offset within the register */
u8_t AccessWidth; /* Minimum Access size (ACPI 3.0) */
u64_t Address; /* 64-bit address of struct or register */
} acpi_address_t;
typedef struct __attribute__((packed))
{
acpi_thead_t Header; /* Common ACPI table header */
u32_t Facs; /* 32-bit physical address of FACS */
u32_t Dsdt; /* 32-bit physical address of DSDT */
u8_t Model; /* System Interrupt Model (ACPI 1.0) - not used in ACPI 2.0+ */
u8_t PreferredProfile; /* Conveys preferred power management profile to OSPM. */
u16_t SciInterrupt; /* System vector of SCI interrupt */
u32_t SmiCommand; /* 32-bit Port address of SMI command port */
u8_t AcpiEnable; /* Value to write to smi_cmd to enable ACPI */
u8_t AcpiDisable; /* Value to write to smi_cmd to disable ACPI */
u8_t S4BiosRequest; /* Value to write to SMI CMD to enter S4BIOS state */
u8_t PstateControl; /* Processor performance state control*/
u32_t Pm1aEventBlock; /* 32-bit Port address of Power Mgt 1a Event Reg Blk */
u32_t Pm1bEventBlock; /* 32-bit Port address of Power Mgt 1b Event Reg Blk */
u32_t Pm1aControlBlock; /* 32-bit Port address of Power Mgt 1a Control Reg Blk */
u32_t Pm1bControlBlock; /* 32-bit Port address of Power Mgt 1b Control Reg Blk */
u32_t Pm2ControlBlock; /* 32-bit Port address of Power Mgt 2 Control Reg Blk */
u32_t PmTimerBlock; /* 32-bit Port address of Power Mgt Timer Ctrl Reg Blk */
u32_t Gpe0Block; /* 32-bit Port address of General Purpose Event 0 Reg Blk */
u32_t Gpe1Block; /* 32-bit Port address of General Purpose Event 1 Reg Blk */
u8_t Pm1EventLength; /* Byte Length of ports at Pm1xEventBlock */
u8_t Pm1ControlLength; /* Byte Length of ports at Pm1xControlBlock */
u8_t Pm2ControlLength; /* Byte Length of ports at Pm2ControlBlock */
u8_t PmTimerLength; /* Byte Length of ports at PmTimerBlock */
u8_t Gpe0BlockLength; /* Byte Length of ports at Gpe0Block */
u8_t Gpe1BlockLength; /* Byte Length of ports at Gpe1Block */
u8_t Gpe1Base; /* Offset in GPE number space where GPE1 events start */
u8_t CstControl; /* Support for the _CST object and C States change notification */
u16_t C2Latency; /* Worst case HW latency to enter/exit C2 state */
u16_t C3Latency; /* Worst case HW latency to enter/exit C3 state */
u16_t FlushSize; /* Processor's memory cache line width, in bytes */
u16_t FlushStride; /* Number of flush strides that need to be read */
u8_t DutyOffset; /* Processor duty cycle index in processor's P_CNT reg*/
u8_t DutyWidth; /* Processor duty cycle value bit width in P_CNT register.*/
u8_t DayAlarm; /* Index to day-of-month alarm in RTC CMOS RAM */
u8_t MonthAlarm; /* Index to month-of-year alarm in RTC CMOS RAM */
u8_t Century; /* Index to century in RTC CMOS RAM */
u16_t BootFlags; /* IA-PC Boot Architecture Flags. See Table 5-10 for description */
u8_t Reserved; /* Reserved, must be zero */
u32_t Flags; /* Miscellaneous flag bits (see below for individual flags) */
acpi_address_t ResetRegister; /* 64-bit address of the Reset register */
u8_t ResetValue; /* Value to write to the ResetRegister port to reset the system */
u8_t Reserved4[3]; /* Reserved, must be zero */
u64_t XFacs; /* 64-bit physical address of FACS */
u64_t XDsdt; /* 64-bit physical address of DSDT */
acpi_address_t XPm1aEventBlock; /* 64-bit Extended Power Mgt 1a Event Reg Blk address */
acpi_address_t XPm1bEventBlock; /* 64-bit Extended Power Mgt 1b Event Reg Blk address */
acpi_address_t XPm1aControlBlock; /* 64-bit Extended Power Mgt 1a Control Reg Blk address */
acpi_address_t XPm1bControlBlock; /* 64-bit Extended Power Mgt 1b Control Reg Blk address */
acpi_address_t XPm2ControlBlock; /* 64-bit Extended Power Mgt 2 Control Reg Blk address */
acpi_address_t XPmTimerBlock; /* 64-bit Extended Power Mgt Timer Ctrl Reg Blk address */
acpi_address_t XGpe0Block; /* 64-bit Extended General Purpose Event 0 Reg Blk address */
acpi_address_t XGpe1Block; /* 64-bit Extended General Purpose Event 1 Reg Blk address */
} acpi_fadt_t;
#define OS_BASE 0x80000000
#define ACPI_HI_RSDP_WINDOW_START (OS_BASE+0x000E0000)
#define ACPI_HI_RSDP_WINDOW_END (OS_BASE+0x00100000)
#define ACPI_RSDP_CHECKSUM_LENGTH 20
#define ACPI_RSDP_XCHECKSUM_LENGTH 36
#define ACPI_MADT_SIGN 0x43495041
#define addr_offset(addr, off) \
(addr_t)((addr_t)(addr) + (addr_t)(off))
#define ACPI_ADDR(x) \
(addr_t)((addr_t)(x)+OS_BASE)
#define acpi_remap(x) (x)

View File

@ -0,0 +1,56 @@
OUTPUT_FORMAT(pei-i386)
ENTRY("_drvEntry")
SECTIONS
{
. = SIZEOF_HEADERS;
. = ALIGN(__section_alignment__);
.text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) :
{
*(.text) *(.rdata)
}
.data ALIGN(__section_alignment__) :
{
*(.data)
}
.bss ALIGN(__section_alignment__):
{
*(.bss)
*(COMMON)
}
/DISCARD/ :
{
*(.debug$S)
*(.debug$T)
*(.debug$F)
*(.drectve)
*(.edata)
}
.idata ALIGN(__section_alignment__):
{
SORT(*)(.idata$2)
SORT(*)(.idata$3)
/* These zeroes mark the end of the import list. */
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
SORT(*)(.idata$4)
SORT(*)(.idata$5)
SORT(*)(.idata$6)
SORT(*)(.idata$7)
}
.reloc ALIGN(__section_alignment__) :
{
*(.reloc)
}
}

View File

@ -0,0 +1,71 @@
#include <ddk.h>
#include <syscall.h>
#include "acpi.h"
acpi_rsdp_t* acpi_locate();
acpi_rsdp_t* acpi_rsdp;
acpi_rsdt_t* acpi_rsdt;
acpi_madt_t* acpi_madt;
addr_t acpi_rsdt_base;
addr_t acpi_madt_base;
addr_t acpi_lapic_base;
addr_t acpi_ioapic_base;
addr_t __fastcall rsdt_find(acpi_rsdt_t *rsdt, u32_t sig);
u32_t drvEntry(int action, char *cmdline)
{
u32_t ret;
if(action != 1)
return 0;
if( !dbg_open("/rd/1/drivers/acpi.log") )
{
printf("Can't open /rd/1/drivers/acpi.log\nExit\n");
return 0;
}
acpi_rsdp = acpi_locate();
if (unlikely(acpi_rsdp == NULL))
{
dbgprintf("No ACPI RSD table\n");
return 0;
};
dbgprintf("rsd base address %x\n", acpi_rsdp);
acpi_rsdt_base = acpi_rsdp->rsdt_ptr;
acpi_rsdt = (acpi_rsdt_t*)(MapIoMem(acpi_rsdt_base,0x10000,5));
dbgprintf("rsdt base 0x%x, kernel 0x%x\n", acpi_rsdt_base, acpi_rsdt);
if (unlikely(acpi_rsdt == NULL))
{
dbgprintf("Invalid ACPI RSD table\n");
return 0;
};
// print_rsdt(acpi_rsdt);
acpi_madt_base = rsdt_find(acpi_rsdt, ACPI_MADT_SIGN);
if( unlikely(acpi_madt_base == 0) )
{
dbgprintf("No ACPI MAD Table\n");
return 0;
};
acpi_madt =(acpi_madt_t*)acpi_remap_table(acpi_madt_base);
dbgprintf("madt base 0x%x, kernel 0x%x\n", acpi_madt_base, acpi_madt);
// print_madt(acpi_madt);
return 0;
};

View File

View File

@ -0,0 +1,79 @@
format MS COFF
extrn _acpi_rsdt_base
public _acpi_locate
public @rsdt_find@8
OS_BASE equ 0x80000000
ACPI_HI_RSDP_WINDOW_START equ (OS_BASE+0x000E0000)
ACPI_HI_RSDP_WINDOW_END equ (OS_BASE+0x00100000)
ACPI_RSDP_CHECKSUM_LENGTH equ 20
section '.text' code readable executable align 16
_acpi_locate:
push ebx
mov ebx, ACPI_HI_RSDP_WINDOW_START
.check:
cmp [ebx], dword 0x20445352
jne .next
cmp [ebx+4], dword 0x20525450
jne .next
mov edx, ebx
mov ecx, ACPI_RSDP_CHECKSUM_LENGTH
xor eax, eax
.sum:
add al, [edx]
inc edx
loop .sum
test al, al
jnz .next
mov eax, ebx
pop ebx
ret
.next:
add ebx, 16
cmp ebx, ACPI_HI_RSDP_WINDOW_END
jb .check
pop ebx
xor eax, eax
ret
align 4
@rsdt_find@8: ;ecx= rsdt edx= SIG
push ebx
push esi
lea ebx, [ecx+36]
mov esi, [ecx+4]
add esi, ecx
.next:
mov eax, [ebx]
sub eax, [_acpi_rsdt_base]
add eax, ecx
cmp [eax], edx
je .done
add ebx, 4
cmp ebx, esi
jb .next
xor eax, eax
pop esi
pop ebx
ret
.done:
mov eax, [ebx]
pop esi
pop ebx
ret