From c1289cd6702ce3eadf2e26de57a2077f871139be Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Sat, 1 Dec 2012 16:46:36 +0800 Subject: [PATCH] Kernel - Adding (unused) ACPI code --- KernelLand/Kernel/Makefile | 6 +- KernelLand/Kernel/arch/x86/Makefile | 6 +- KernelLand/Kernel/arch/x86/acpica.c | 497 ++++++++++++++++++++++++++++ KernelLand/Kernel/arch/x86/irq.c | 11 +- KernelLand/Kernel/debug.c | 22 +- 5 files changed, 530 insertions(+), 12 deletions(-) create mode 100644 KernelLand/Kernel/arch/x86/acpica.c diff --git a/KernelLand/Kernel/Makefile b/KernelLand/Kernel/Makefile index a82bbc99..df2c26ee 100644 --- a/KernelLand/Kernel/Makefile +++ b/KernelLand/Kernel/Makefile @@ -85,6 +85,10 @@ clean: @$(RM) $(BIN) ../Acess2.$(ARCH).gz $(BIN).dsm ../Map.$(ARCH).txt LineCounts.$(ARCH).txt @$(RM) -r $(OBJDIR) $(OBJ) $(DEPFILES) $(BUILDINFO_SRC) +# Lower to avoid taking default target from 'all' +-include $(addprefix ../../Externals/,$(addsuffix /Makefile.kinc, $(EXTERNS))) + + # Creates a stripped and compressed copy of the kernel # and installs it to the target install: $(BIN) @@ -101,7 +105,7 @@ apidoc: # - Does whatever architecture defined rules $(BIN): $(OBJ) $(MODS) arch/$(ARCHDIR)/link.ld Makefile ../../BuildConf/$(ARCH)/Makefile.cfg ../../BuildConf/$(ARCH)/$(PLATFORM).mk @echo --- LD -o $(BIN) - @$(LD) $(LDFLAGS) -o $(BIN) $(OBJ) $(MODS) $(LIBGCC_PATH) --defsym __buildnum=$$(( $(BUILD_NUM) + 1 )) -Map ../Map.$(ARCH).txt + @$(LD) $(LDFLAGS) -o $(BIN) $(OBJ) $(MODS) $(EXTERN_OBJS) $(LIBGCC_PATH) --defsym __buildnum=$$(( $(BUILD_NUM) + 1 )) -Map ../Map.$(ARCH).txt @$(DISASM) -S $(BIN) > $(BIN).dsm @echo BUILD_NUM = $$(( $(BUILD_NUM) + 1 )) > Makefile.BuildNum.$(ARCH) $(POSTBUILD) diff --git a/KernelLand/Kernel/arch/x86/Makefile b/KernelLand/Kernel/arch/x86/Makefile index 7372839d..c8152b9e 100644 --- a/KernelLand/Kernel/arch/x86/Makefile +++ b/KernelLand/Kernel/arch/x86/Makefile @@ -5,7 +5,7 @@ AS_SUFFIX = asm -CPPFLAGS = +CPPFLAGS = CFLAGS = ASFLAGS = -f elf @@ -24,3 +24,7 @@ A_OBJ = start.ao main.o mboot.o lib.o desctab.ao errors.o irq.o A_OBJ += mm_phys.o mm_virt.o A_OBJ += proc.o proc.ao time.o vm8086.o A_OBJ += kpanic.o pci.o vpci.o +A_OBJ += acpica.o + +EXTERNS += ACPICA + diff --git a/KernelLand/Kernel/arch/x86/acpica.c b/KernelLand/Kernel/arch/x86/acpica.c new file mode 100644 index 00000000..e2346493 --- /dev/null +++ b/KernelLand/Kernel/arch/x86/acpica.c @@ -0,0 +1,497 @@ +/* + * Acess2 Kernel (x86 Core) + * - By John Hodge (thePowersGang) + * + * acpica.c + * - ACPICA Interface + */ +#include +#include +#include +#include + +// === PROTOTYPES === +int ACPICA_Initialise(void); + + +// === CODE === +int ACPICA_Initialise(void) +{ + ACPI_STATUS rv; + + rv = AcpiInitializeSubsystem(); + + // AcpiInitializeTables? + rv = AcpiLoadTables(); + + rv = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION); + + return 0; +} + +// --------------- +// --- Exports --- +// --------------- +ACPI_STATUS AcpiOsInitialize(void) +{ + return AE_OK; +} + +ACPI_STATUS AcpiOsTerminate(void) +{ + return AE_OK; +} + +ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer(void) +{ + ACPI_SIZE val; + ACPI_STATUS rv; + + rv = AcpiFindRootPointer(&val); + if( ACPI_FAILURE(rv) ) + return 0; + + return val; + // (Or use EFI) +} + +ACPI_STATUS AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *PredefinedObject, ACPI_STRING *NewValue) +{ + return AE_NOT_IMPLEMENTED; +} + +ACPI_STATUS AcpiOsTableOverride(ACPI_TABLE_HEADER *ExisitingTable, ACPI_TABLE_HEADER **NewTable) +{ + return AE_NOT_IMPLEMENTED; +} + +ACPI_STATUS AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *ExisitingTable, ACPI_PHYSICAL_ADDRESS *NewAddress, UINT32 *NewTableLength) +{ + return AE_NOT_IMPLEMENTED; +} + +// -- Memory Management --- +ACPI_STATUS AcpiOsCreateCache(char *CacheName, UINT16 ObjectSize, UINT16 MaxDepth, ACPI_CACHE_T **ReturnCache) +{ + return AE_NOT_IMPLEMENTED; +} + +ACPI_STATUS AcpiOsDeleteCache(ACPI_CACHE_T *Cache) +{ + if( Cache == NULL ) + return AE_BAD_PARAMETER; + + return AE_NOT_IMPLEMENTED; +} + +ACPI_STATUS AcpiOsPurgeCache(ACPI_CACHE_T *Cache) +{ + if( Cache == NULL ) + return AE_BAD_PARAMETER; + + return AE_NOT_IMPLEMENTED; +} + +void *AcpiOsAcquireObject(ACPI_CACHE_T *Cache) +{ + // TODO + return NULL; +} + +ACPI_STATUS AcpiOsReleaseObject(ACPI_CACHE_T *Cache, void *Object) +{ + if( Cache == NULL || Object == NULL ) + return AE_BAD_PARAMETER; + return AE_NOT_IMPLEMENTED; +} + +void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length) +{ + Uint ofs = PhysicalAddress & (PAGE_SIZE-1); + int npages = (ofs + Length + (PAGE_SIZE-1)) / PAGE_SIZE; + return (char*)MM_MapHWPages(PhysicalAddress, npages) + ofs; +} + +void AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length) +{ + Uint ofs = (tVAddr)LogicalAddress & (PAGE_SIZE-1); + int npages = (ofs + Length + (PAGE_SIZE-1)) / PAGE_SIZE; + // TODO: Validate `Length` is the same as was passed to AcpiOsMapMemory + MM_UnmapHWPages( (tVAddr)LogicalAddress, npages); +} + +ACPI_STATUS AcpiOsGetPhysicalAddress(void *LogicalAddress, ACPI_PHYSICAL_ADDRESS *PhysicalAddress) +{ + if( LogicalAddress == NULL || PhysicalAddress == NULL ) + return AE_BAD_PARAMETER; + + tPAddr rv = MM_GetPhysAddr(LogicalAddress); + if( rv == 0 ) + return AE_ERROR; + *PhysicalAddress = rv; + return AE_OK; +} + +void *AcpiOsAllocate(ACPI_SIZE Size) +{ + return malloc(Size); +} + +void AcpiOsFree(void *Memory) +{ + return free(Memory); +} + +BOOLEAN AcpiOsReadable(void *Memory, ACPI_SIZE Length) +{ + return CheckMem(Memory, Length); +} + +BOOLEAN AcpiOsWritable(void *Memory, ACPI_SIZE Length) +{ + // TODO: Actually check if it's writable + return CheckMem(Memory, Length); +} + + +// --- Threads --- +ACPI_THREAD_ID AcpiOsGetThreadId(void) +{ + return Threads_GetTID(); +} + +ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function, void *Context) +{ + // TODO: Need to store currently executing functions + if( Function == NULL ) + return AE_BAD_PARAMETER; + Proc_SpawnWorker(Function, Context); + return AE_OK; +} + +void AcpiOsSleep(UINT64 Milliseconds) +{ + Time_Delay(Milliseconds); +} + +void AcpiOsStall(UINT32 Microseconds) +{ + // TODO: need a microsleep function + Microseconds += (1000-1); + Microseconds /= 1000; + Time_Delay(Microseconds); +} + +void AcpiOsWaitEventsComplete(void) +{ + // TODO: +} + +// --- Mutexes etc --- +ACPI_STATUS AcpiOsCreateMutex(ACPI_MUTEX *OutHandle) +{ + if( !OutHandle ) + return AE_BAD_PARAMETER; + tMutex *ret = calloc( sizeof(tMutex), 1 ); + if( !ret ) + return AE_NO_MEMORY; + ret->Name = "AcpiOsCreateMutex"; + *OutHandle = ret; + + return AE_OK; +} + +void AcpiOsDeleteMutex(ACPI_MUTEX Handle) +{ + Mutex_Acquire(Handle); + free(Handle); +} + +ACPI_STATUS AcpiOsAcquireMutex(ACPI_MUTEX Handle, UINT16 Timeout) +{ + if( Handle == NULL ) + return AE_BAD_PARAMETER; + + Mutex_Acquire(Handle); + + return AE_OK; +} + +void AcpiOsReleaseMutex(ACPI_MUTEX Handle) +{ + Mutex_Release(Handle); +} + +ACPI_STATUS AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, ACPI_SEMAPHORE *OutHandle) +{ + if( !OutHandle ) + return AE_BAD_PARAMETER; + tSemaphore *ret = calloc( sizeof(tSemaphore), 1 ); + if( !ret ) + return AE_NO_MEMORY; + + Semaphore_Init(ret, InitialUnits, MaxUnits, "AcpiOsCreateSemaphore", ""); + *OutHandle = ret; + return AE_OK; +} + +ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_SEMAPHORE Handle) +{ + if( !Handle ) + return AE_BAD_PARAMETER; + + free(Handle); + + return AE_OK; +} + +ACPI_STATUS AcpiOsWaitSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units, UINT16 Timeout) +{ + if( !Handle ) + return AE_BAD_PARAMETER; + + // Special case + if( Timeout == 0 ) + { + // NOTE: Possible race condition + if( Semaphore_GetValue(Handle) >= Units ) { + Semaphore_Wait(Handle, Units); + return AE_OK; + } + return AE_TIME; + } + + tTime start = now(); + UINT32 rem = Units; + while(rem && now() - start < Timeout) + { + rem -= Semaphore_Wait(Handle, rem); + } + + if( rem ) { + Semaphore_Signal(Handle, Units - rem); + return AE_TIME; + } + + return AE_OK; +} + +ACPI_STATUS AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units) +{ + if( !Handle ) + return AE_BAD_PARAMETER; + + // TODO: Support AE_LIMIT detection early (to avoid blocks) + + // NOTE: Blocks + int rv = Semaphore_Signal(Handle, Units); + if( rv != Units ) + return AE_LIMIT; + + return AE_OK; +} + +ACPI_STATUS AcpiOsCreateLock(ACPI_SPINLOCK *OutHandle) +{ + if( !OutHandle ) + return AE_BAD_PARAMETER; + tShortSpinlock *lock = calloc(sizeof(tShortSpinlock), 1); + if( !lock ) + return AE_NO_MEMORY; + + *OutHandle = lock; + return AE_OK; +} + +void AcpiOsDeleteLock(ACPI_SPINLOCK Handle) +{ + free(Handle); +} + +ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK Handle) +{ + SHORTLOCK(Handle); + return 0; +} + +void AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags) +{ + SHORTREL(Handle); +} + +// --- Interrupt handling --- +#define N_INT_LEVELS 16 +ACPI_OSD_HANDLER gaACPI_InterruptHandlers[N_INT_LEVELS]; +void *gaACPI_InterruptData[N_INT_LEVELS]; + int gaACPI_InterruptHandles[N_INT_LEVELS]; + +void ACPI_int_InterruptProxy(int IRQ, void *data) +{ + if( !gaACPI_InterruptHandlers[IRQ] ) + return ; + gaACPI_InterruptHandlers[IRQ](gaACPI_InterruptData[IRQ]); +} + +ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler, void *Context) +{ + if( InterruptLevel >= N_INT_LEVELS || Handler == NULL ) + return AE_BAD_PARAMETER; + if( gaACPI_InterruptHandlers[InterruptLevel] ) + return AE_ALREADY_EXISTS; + + gaACPI_InterruptHandlers[InterruptLevel] = Handler; + gaACPI_InterruptData[InterruptLevel] = Context; + + gaACPI_InterruptHandles[InterruptLevel] = IRQ_AddHandler(InterruptLevel, ACPI_int_InterruptProxy, NULL); + return AE_OK; +} + +ACPI_STATUS AcpiOsRemoveInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler) +{ + if( InterruptLevel >= N_INT_LEVELS || Handler == NULL ) + return AE_BAD_PARAMETER; + if( gaACPI_InterruptHandlers[InterruptLevel] != Handler ) + return AE_NOT_EXIST; + gaACPI_InterruptHandlers[InterruptLevel] = NULL; + IRQ_RemHandler(gaACPI_InterruptHandles[InterruptLevel]); + return AE_OK; +} + +// --- Memory Access --- +ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width) +{ + void *ptr; + if( Address < 1024*1024 ) { + ptr = (void*)(KERNEL_BASE | Address); + } + else { + ptr = (char*)MM_MapTemp(Address) + (Address & 0xFFF); + } + + switch(Width) + { + case 8: *Value = *(Uint8 *)ptr; break; + case 16: *Value = *(Uint16*)ptr; break; + case 32: *Value = *(Uint32*)ptr; break; + case 64: *Value = *(Uint64*)ptr; break; + } + + if( Address >= 1024*1024 ) { + MM_FreeTemp(ptr); + } + + return AE_OK; +} + +ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width) +{ + void *ptr; + if( Address < 1024*1024 ) { + ptr = (void*)(KERNEL_BASE | Address); + } + else { + ptr = (char*)MM_MapTemp(Address) + (Address & 0xFFF); + } + + switch(Width) + { + case 8: *(Uint8 *)ptr = Value; break; + case 16: *(Uint16*)ptr = Value; break; + case 32: *(Uint32*)ptr = Value; break; + case 64: *(Uint64*)ptr = Value; break; + default: + return AE_BAD_PARAMETER; + } + + if( Address >= 1024*1024 ) { + MM_FreeTemp(ptr); + } + + return AE_OK; +} + +// --- Port Input / Output --- +ACPI_STATUS AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width) +{ + switch(Width) + { + case 8: *Value = inb(Address); break; + case 16: *Value = inw(Address); break; + case 32: *Value = ind(Address); break; + default: + return AE_BAD_PARAMETER; + } + return AE_OK; +} + +ACPI_STATUS AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width) +{ + switch(Width) + { + case 8: outb(Address, Value); break; + case 16: outw(Address, Value); break; + case 32: outd(Address, Value); break; + default: + return AE_BAD_PARAMETER; + } + return AE_OK; +} + +// --- PCI Configuration Space Access --- +ACPI_STATUS AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value, UINT32 Width) +{ + return AE_NOT_IMPLEMENTED; +} + +ACPI_STATUS AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 Value, UINT32 Width) +{ + return AE_NOT_IMPLEMENTED; +} + +// --- Formatted Output --- +void AcpiOsPrintf(const char *Format, ...) +{ + va_list args; + va_start(args, Format); + + LogV(Format, args); + + va_end(args); +} + +void AcpiOsVprintf(const char *Format, va_list Args) +{ + LogV(Format, Args); +} + +void AcpiOsRedirectOutput(void *Destination) +{ + // TODO: is this needed? +} + +// --- Miscellaneous --- +UINT64 AcpiOsGetTimer(void) +{ + return now() * 10 * 1000; +} + +ACPI_STATUS AcpiOsSignal(UINT32 Function, void *Info) +{ + switch(Function) + { + case ACPI_SIGNAL_FATAL: { + ACPI_SIGNAL_FATAL_INFO *finfo = Info; + Log_Error("ACPI AML", "Fatal %x %x %x", finfo->Type, finfo->Code, finfo->Argument); + break; } + case ACPI_SIGNAL_BREAKPOINT: { + Log_Notice("ACPI AML", "Breakpoint %s", Info); + break; }; + } + return AE_OK; +} + +ACPI_STATUS AcpiOsGetLine(char *Buffer, UINT32 BufferLength, UINT32 *BytesRead) +{ + return AE_NOT_IMPLEMENTED; +} + diff --git a/KernelLand/Kernel/arch/x86/irq.c b/KernelLand/Kernel/arch/x86/irq.c index 0a195104..7250debe 100644 --- a/KernelLand/Kernel/arch/x86/irq.c +++ b/KernelLand/Kernel/arch/x86/irq.c @@ -66,10 +66,17 @@ int IRQ_AddHandler( int Num, void (*Callback)(int, void*), void *Ptr ) Log_Log("IRQ", "Added IRQ%i Cb#%i %p", Num, i, Callback); gIRQ_Handlers[Num][i] = Callback; gaIRQ_DataPointers[Num][i] = Ptr; - return 1; + return Num * MAX_CALLBACKS_PER_IRQ + i; } } Log_Warning("IRQ", "No free callbacks on IRQ%i", Num); - return 0; + return -1; +} + +void IRQ_RemHandler(int Handle) +{ + int Num = Handle / MAX_CALLBACKS_PER_IRQ; + int id = Handle % MAX_CALLBACKS_PER_IRQ; + gIRQ_Handlers[Num][id] = NULL; } diff --git a/KernelLand/Kernel/debug.c b/KernelLand/Kernel/debug.c index ab3dd672..9104262a 100644 --- a/KernelLand/Kernel/debug.c +++ b/KernelLand/Kernel/debug.c @@ -162,27 +162,33 @@ void Debug(const char *Fmt, ...) SHORTREL(&glDebug_Lock); #endif } -/** - * \fn void Log(const char *Msg, ...) - */ -void Log(const char *Fmt, ...) + +void LogV(const char *Fmt, va_list args) { - va_list args; - #if LOCK_DEBUG_OUTPUT SHORTLOCK(&glDebug_Lock); #endif Debug_Puts(1, "Log: "); - va_start(args, Fmt); Debug_Fmt(1, Fmt, args); - va_end(args); Debug_Puts(1, "\r\n"); #if LOCK_DEBUG_OUTPUT SHORTREL(&glDebug_Lock); #endif } + +/** + * \fn void Log(const char *Msg, ...) + */ +void Log(const char *Fmt, ...) +{ + va_list args; + va_start(args, Fmt); + LogV(Fmt, args); + va_end(args); +} + void Warning(const char *Fmt, ...) { va_list args; -- 2.20.1