2 * Acess2 Kernel (x86 Core)
3 * - By John Hodge (thePowersGang)
8 #define ACPI_DEBUG_OUTPUT 0
10 #define _AcpiModuleName "Shim"
11 #define _COMPONENT "Acess"
15 #include <semaphore.h>
17 #define ONEMEG (1024*1024)
20 // - RSDP Address from uEFI
21 tPAddr gACPI_RSDPOverride = 0;
24 int ACPICA_Initialise(void);
25 void ACPI_int_InterruptProxy(int IRQ, void *data);
29 int ACPICA_Initialise(void)
33 #ifdef ACPI_DEBUG_OUTPUT
34 AcpiDbgLevel = ACPI_DB_ALL;
37 rv = AcpiInitializeSubsystem();
38 if( ACPI_FAILURE(rv) )
40 Log_Error("ACPI", "AcpiInitializeSubsystem: %i", rv);
44 rv = AcpiInitializeTables(NULL, 16, FALSE);
45 if( ACPI_FAILURE(rv) )
47 Log_Error("ACPI", "AcpiInitializeTables: %i", rv);
52 // AcpiInitializeTables?
53 rv = AcpiLoadTables();
54 if( ACPI_FAILURE(rv) )
56 Log_Error("ACPI", "AcpiLoadTables: %i", rv);
61 rv = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
62 if( ACPI_FAILURE(rv) )
64 Log_Error("ACPI", "AcpiEnableSubsystem: %i", rv);
75 ACPI_STATUS AcpiOsInitialize(void)
80 ACPI_STATUS AcpiOsTerminate(void)
85 ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer(void)
90 if( gACPI_RSDPOverride )
91 return gACPI_RSDPOverride;
93 rv = AcpiFindRootPointer(&val);
94 if( ACPI_FAILURE(rv) )
103 ACPI_STATUS AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *PredefinedObject, ACPI_STRING *NewValue)
109 ACPI_STATUS AcpiOsTableOverride(ACPI_TABLE_HEADER *ExisitingTable, ACPI_TABLE_HEADER **NewTable)
115 ACPI_STATUS AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *ExisitingTable, ACPI_PHYSICAL_ADDRESS *NewAddress, UINT32 *NewTableLength)
121 // -- Memory Management ---
131 ACPI_STATUS AcpiOsCreateCache(char *CacheName, UINT16 ObjectSize, UINT16 MaxDepth, ACPI_CACHE_T **ReturnCache)
134 int namelen = (CacheName ? strlen(CacheName) : 0) + 1;
135 LOG("CacheName=%s, ObjSize=%x, MaxDepth=%x", CacheName, ObjectSize, MaxDepth);
137 namelen = (namelen + 3) & ~3;
139 ret = malloc(sizeof(*ret) + MaxDepth*sizeof(char) + namelen + MaxDepth*ObjectSize);
141 Log_Notice("ACPICA", "%s: malloc() fail", __func__);
145 ret->nObj = MaxDepth;
146 ret->ObjectSize = ObjectSize;
147 ret->Name = (char*)(ret->ObjectStates + MaxDepth);
148 ret->First = ret->Name + namelen;
150 strcpy(ret->Name, CacheName);
153 memset(ret->ObjectStates, 0, sizeof(char)*MaxDepth);
155 LOG("Allocated cache %p '%s' (%i x 0x%x)", ret, CacheName, MaxDepth, ObjectSize);
162 ACPI_STATUS AcpiOsDeleteCache(ACPI_CACHE_T *Cache)
165 return AE_BAD_PARAMETER;
171 ACPI_STATUS AcpiOsPurgeCache(ACPI_CACHE_T *Cache)
173 ENTER("pCache", Cache);
174 if( Cache == NULL ) {
175 LEAVE('i', AE_BAD_PARAMETER);
176 return AE_BAD_PARAMETER;
179 memset(Cache->ObjectStates, 0, sizeof(char)*Cache->nObj);
185 void *AcpiOsAcquireObject(ACPI_CACHE_T *Cache)
187 ENTER("pCache", Cache);
188 for(int i = 0; i < Cache->nObj; i ++ )
190 if( !Cache->ObjectStates[i] ) {
191 Cache->ObjectStates[i] = 1;
192 void *rv = (char*)Cache->First + i*Cache->ObjectSize;
193 memset(rv, 0, Cache->ObjectSize);
199 Log_Debug("ACPICA", "AcpiOsAcquireObject: All %i objects used in '%s'",
200 Cache->nObj, Cache->Name);
206 ACPI_STATUS AcpiOsReleaseObject(ACPI_CACHE_T *Cache, void *Object)
208 if( Cache == NULL || Object == NULL )
209 return AE_BAD_PARAMETER;
210 ENTER("pCache pObject", Cache, Object);
212 tVAddr delta = (tVAddr)Object - (tVAddr)Cache->First;
213 delta /= Cache->ObjectSize;
214 LOG("Cache=%p, delta = %i, (limit %i)", Cache, delta, Cache->nObj);
216 if( delta >= Cache->nObj )
217 return AE_BAD_PARAMETER;
219 Cache->ObjectStates[delta] = 0;
225 void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length)
227 if( PhysicalAddress < ONEMEG )
228 return (void*)(KERNEL_BASE | PhysicalAddress);
230 Uint ofs = PhysicalAddress & (PAGE_SIZE-1);
231 int npages = (ofs + Length + (PAGE_SIZE-1)) / PAGE_SIZE;
232 char *maploc = (void*)MM_MapHWPages(PhysicalAddress, npages);
234 LOG("Mapping %P+0x%x failed", PhysicalAddress, Length);
237 // MM_DumpTables(0, -1);
238 void *rv = maploc + ofs;
239 LOG("Map (%P+%i pg) to %p", PhysicalAddress, npages, rv);
243 void AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length)
245 if( (tVAddr)LogicalAddress - KERNEL_BASE < ONEMEG )
248 LOG("%p", LogicalAddress);
250 Uint ofs = (tVAddr)LogicalAddress & (PAGE_SIZE-1);
251 int npages = (ofs + Length + (PAGE_SIZE-1)) / PAGE_SIZE;
252 // TODO: Validate `Length` is the same as was passed to AcpiOsMapMemory
253 MM_UnmapHWPages( (tVAddr)LogicalAddress, npages);
256 ACPI_STATUS AcpiOsGetPhysicalAddress(void *LogicalAddress, ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
258 if( LogicalAddress == NULL || PhysicalAddress == NULL )
259 return AE_BAD_PARAMETER;
261 tPAddr rv = MM_GetPhysAddr(LogicalAddress);
264 *PhysicalAddress = rv;
268 void *AcpiOsAllocate(ACPI_SIZE Size)
273 void AcpiOsFree(void *Memory)
278 BOOLEAN AcpiOsReadable(void *Memory, ACPI_SIZE Length)
280 return CheckMem(Memory, Length);
283 BOOLEAN AcpiOsWritable(void *Memory, ACPI_SIZE Length)
285 // TODO: Actually check if it's writable
286 return CheckMem(Memory, Length);
291 ACPI_THREAD_ID AcpiOsGetThreadId(void)
293 return Threads_GetTID() + 1;
296 ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function, void *Context)
298 // TODO: Need to store currently executing functions
299 if( Function == NULL )
300 return AE_BAD_PARAMETER;
301 Proc_SpawnWorker(Function, Context);
305 void AcpiOsSleep(UINT64 Milliseconds)
307 Time_Delay(Milliseconds);
310 void AcpiOsStall(UINT32 Microseconds)
312 // TODO: need a microsleep function
313 Microseconds += (1000-1);
314 Microseconds /= 1000;
315 Time_Delay(Microseconds);
318 void AcpiOsWaitEventsComplete(void)
323 // --- Mutexes etc ---
324 ACPI_STATUS AcpiOsCreateMutex(ACPI_MUTEX *OutHandle)
328 return AE_BAD_PARAMETER;
329 tMutex *ret = calloc( sizeof(tMutex), 1 );
331 Log_Notice("ACPICA", "%s: malloc() fail", __func__);
334 ret->Name = "AcpiOsCreateMutex";
340 void AcpiOsDeleteMutex(ACPI_MUTEX Handle)
342 Mutex_Acquire(Handle);
346 ACPI_STATUS AcpiOsAcquireMutex(ACPI_MUTEX Handle, UINT16 Timeout)
349 return AE_BAD_PARAMETER;
351 Mutex_Acquire(Handle);
356 void AcpiOsReleaseMutex(ACPI_MUTEX Handle)
358 Mutex_Release(Handle);
361 ACPI_STATUS AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, ACPI_SEMAPHORE *OutHandle)
363 LOG("(MaxUnits=%i,InitialUnits=%i)", MaxUnits, InitialUnits);
365 return AE_BAD_PARAMETER;
366 tSemaphore *ret = calloc( sizeof(tSemaphore), 1 );
368 Log_Notice("ACPICA", "%s: malloc() fail", __func__);
372 Semaphore_Init(ret, InitialUnits, MaxUnits, "AcpiOsCreateSemaphore", "");
377 ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_SEMAPHORE Handle)
380 return AE_BAD_PARAMETER;
387 ACPI_STATUS AcpiOsWaitSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units, UINT16 Timeout)
390 return AE_BAD_PARAMETER;
395 // NOTE: Possible race condition
396 if( Semaphore_GetValue(Handle) >= Units ) {
397 Semaphore_Wait(Handle, Units);
405 while(rem && now() - start < Timeout)
407 rem -= Semaphore_Wait(Handle, rem);
411 Semaphore_Signal(Handle, Units - rem);
418 ACPI_STATUS AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units)
421 return AE_BAD_PARAMETER;
423 // TODO: Support AE_LIMIT detection early (to avoid blocks)
426 int rv = Semaphore_Signal(Handle, Units);
433 ACPI_STATUS AcpiOsCreateLock(ACPI_SPINLOCK *OutHandle)
437 return AE_BAD_PARAMETER;
438 tShortSpinlock *lock = calloc(sizeof(tShortSpinlock), 1);
446 void AcpiOsDeleteLock(ACPI_SPINLOCK Handle)
451 ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK Handle)
457 void AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags)
462 // --- Interrupt handling ---
463 #define N_INT_LEVELS 16
464 ACPI_OSD_HANDLER gaACPI_InterruptHandlers[N_INT_LEVELS];
465 void *gaACPI_InterruptData[N_INT_LEVELS];
466 int gaACPI_InterruptHandles[N_INT_LEVELS];
468 void ACPI_int_InterruptProxy(int IRQ, void *data)
470 if( !gaACPI_InterruptHandlers[IRQ] )
472 gaACPI_InterruptHandlers[IRQ](gaACPI_InterruptData[IRQ]);
475 ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler, void *Context)
477 if( InterruptLevel >= N_INT_LEVELS || Handler == NULL )
478 return AE_BAD_PARAMETER;
479 if( gaACPI_InterruptHandlers[InterruptLevel] )
480 return AE_ALREADY_EXISTS;
482 gaACPI_InterruptHandlers[InterruptLevel] = Handler;
483 gaACPI_InterruptData[InterruptLevel] = Context;
485 gaACPI_InterruptHandles[InterruptLevel] = IRQ_AddHandler(InterruptLevel, ACPI_int_InterruptProxy, NULL);
489 ACPI_STATUS AcpiOsRemoveInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler)
491 if( InterruptLevel >= N_INT_LEVELS || Handler == NULL )
492 return AE_BAD_PARAMETER;
493 if( gaACPI_InterruptHandlers[InterruptLevel] != Handler )
495 gaACPI_InterruptHandlers[InterruptLevel] = NULL;
496 IRQ_RemHandler(gaACPI_InterruptHandles[InterruptLevel]);
500 // --- Memory Access ---
501 ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width)
504 if( Address < ONEMEG ) {
505 ptr = (void*)(KERNEL_BASE | Address);
508 ptr = (char*)MM_MapTemp(Address) + (Address & 0xFFF);
513 case 8: *Value = *(Uint8 *)ptr; break;
514 case 16: *Value = *(Uint16*)ptr; break;
515 case 32: *Value = *(Uint32*)ptr; break;
516 case 64: *Value = *(Uint64*)ptr; break;
519 if( Address >= ONEMEG ) {
526 ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width)
529 if( Address < ONEMEG ) {
530 ptr = (void*)(KERNEL_BASE | Address);
533 ptr = (char*)MM_MapTemp(Address) + (Address & 0xFFF);
538 case 8: *(Uint8 *)ptr = Value; break;
539 case 16: *(Uint16*)ptr = Value; break;
540 case 32: *(Uint32*)ptr = Value; break;
541 case 64: *(Uint64*)ptr = Value; break;
543 return AE_BAD_PARAMETER;
546 if( Address >= 1024*1024 ) {
553 // --- Port Input / Output ---
554 ACPI_STATUS AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
558 case 8: *Value = inb(Address); break;
559 case 16: *Value = inw(Address); break;
560 case 32: *Value = ind(Address); break;
562 return AE_BAD_PARAMETER;
567 ACPI_STATUS AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
571 case 8: outb(Address, Value); break;
572 case 16: outw(Address, Value); break;
573 case 32: outd(Address, Value); break;
575 return AE_BAD_PARAMETER;
580 // --- PCI Configuration Space Access ---
581 ACPI_STATUS AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value, UINT32 Width)
584 return AE_NOT_IMPLEMENTED;
587 ACPI_STATUS AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 Value, UINT32 Width)
590 return AE_NOT_IMPLEMENTED;
593 // --- Formatted Output ---
594 void AcpiOsPrintf(const char *Format, ...)
597 va_start(args, Format);
604 void AcpiOsVprintf(const char *Format, va_list Args)
609 void AcpiOsRedirectOutput(void *Destination)
611 // TODO: Do I even need to impliment this?
614 // --- Miscellaneous ---
615 UINT64 AcpiOsGetTimer(void)
617 return now() * 10 * 1000;
620 ACPI_STATUS AcpiOsSignal(UINT32 Function, void *Info)
624 case ACPI_SIGNAL_FATAL: {
625 ACPI_SIGNAL_FATAL_INFO *finfo = Info;
626 Log_Error("ACPI AML", "Fatal %x %x %x", finfo->Type, finfo->Code, finfo->Argument);
628 case ACPI_SIGNAL_BREAKPOINT: {
629 Log_Notice("ACPI AML", "Breakpoint %s", Info);
635 ACPI_STATUS AcpiOsGetLine(char *Buffer, UINT32 BufferLength, UINT32 *BytesRead)
638 return AE_NOT_IMPLEMENTED;