2 * Acess2 Kernel (x86 Core)
3 * - By John Hodge (thePowersGang)
9 #define _AcpiModuleName "Shim"
10 #define _COMPONENT "Acess"
14 #include <semaphore.h>
16 #define ONEMEG (1024*1024)
19 // - RSDP Address from uEFI
20 tPAddr gACPI_RSDPOverride = 0;
23 int ACPICA_Initialise(void);
24 void ACPI_int_InterruptProxy(int IRQ, void *data);
28 int ACPICA_Initialise(void)
32 #ifdef ACPI_DEBUG_OUTPUT
33 AcpiDbgLevel = ACPI_DB_ALL;
36 rv = AcpiInitializeSubsystem();
37 if( ACPI_FAILURE(rv) )
39 Log_Error("ACPI", "AcpiInitializeSubsystem: %i", rv);
43 rv = AcpiInitializeTables(NULL, 16, FALSE);
44 if( ACPI_FAILURE(rv) )
46 Log_Error("ACPI", "AcpiInitializeTables: %i", rv);
51 // AcpiInitializeTables?
52 rv = AcpiLoadTables();
53 if( ACPI_FAILURE(rv) )
55 Log_Error("ACPI", "AcpiLoadTables: %i", rv);
60 rv = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
61 if( ACPI_FAILURE(rv) )
63 Log_Error("ACPI", "AcpiEnableSubsystem: %i", rv);
74 ACPI_STATUS AcpiOsInitialize(void)
79 ACPI_STATUS AcpiOsTerminate(void)
84 ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer(void)
89 if( gACPI_RSDPOverride )
90 return gACPI_RSDPOverride;
92 rv = AcpiFindRootPointer(&val);
93 if( ACPI_FAILURE(rv) )
102 ACPI_STATUS AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *PredefinedObject, ACPI_STRING *NewValue)
108 ACPI_STATUS AcpiOsTableOverride(ACPI_TABLE_HEADER *ExisitingTable, ACPI_TABLE_HEADER **NewTable)
114 ACPI_STATUS AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *ExisitingTable, ACPI_PHYSICAL_ADDRESS *NewAddress, UINT32 *NewTableLength)
120 // -- Memory Management ---
130 ACPI_STATUS AcpiOsCreateCache(char *CacheName, UINT16 ObjectSize, UINT16 MaxDepth, ACPI_CACHE_T **ReturnCache)
133 int namelen = (CacheName ? strlen(CacheName) : 0) + 1;
134 LOG("CacheName=%s, ObjSize=%x, MaxDepth=%x", CacheName, ObjectSize, MaxDepth);
136 ret = malloc(sizeof(*ret) + MaxDepth*sizeof(char) + namelen + MaxDepth*ObjectSize);
137 if( !ret ) return AE_NO_MEMORY;
139 ret->nObj = MaxDepth;
140 ret->ObjectSize = ObjectSize;
141 ret->Name = (char*)(ret->ObjectStates + MaxDepth);
142 ret->First = ret->Name + namelen;
144 strcpy(ret->Name, CacheName);
147 memset(ret->ObjectStates, 0, sizeof(char)*MaxDepth);
149 LOG("Allocated cache '%s' (%i x 0x%x)", CacheName, MaxDepth, ObjectSize);
156 ACPI_STATUS AcpiOsDeleteCache(ACPI_CACHE_T *Cache)
159 return AE_BAD_PARAMETER;
165 ACPI_STATUS AcpiOsPurgeCache(ACPI_CACHE_T *Cache)
168 return AE_BAD_PARAMETER;
170 memset(Cache->ObjectStates, 0, sizeof(char)*Cache->nObj);
175 void *AcpiOsAcquireObject(ACPI_CACHE_T *Cache)
177 LOG("(Cache=%p)", Cache);
178 for(int i = 0; i < Cache->nObj; i ++ )
180 if( !Cache->ObjectStates[i] ) {
181 Cache->ObjectStates[i] = 1;
182 return (char*)Cache->First + i*Cache->ObjectSize;
189 ACPI_STATUS AcpiOsReleaseObject(ACPI_CACHE_T *Cache, void *Object)
191 if( Cache == NULL || Object == NULL )
192 return AE_BAD_PARAMETER;
194 tVAddr delta = (tVAddr)Object - (tVAddr)Cache->First;
195 delta /= Cache->ObjectSize;
197 if( delta > Cache->nObj )
198 return AE_BAD_PARAMETER;
200 Cache->ObjectStates[delta] = 0;
205 void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length)
207 if( PhysicalAddress < ONEMEG )
208 return (void*)(KERNEL_BASE | PhysicalAddress);
210 Uint ofs = PhysicalAddress & (PAGE_SIZE-1);
211 int npages = (ofs + Length + (PAGE_SIZE-1)) / PAGE_SIZE;
212 void *rv = ((char*)MM_MapHWPages(PhysicalAddress, npages)) + ofs;
213 LOG("Map (%P+%i pg) to %p", PhysicalAddress, npages, rv);
217 void AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length)
219 if( (tVAddr)LogicalAddress - KERNEL_BASE < ONEMEG )
222 LOG("%p", LogicalAddress);
224 Uint ofs = (tVAddr)LogicalAddress & (PAGE_SIZE-1);
225 int npages = (ofs + Length + (PAGE_SIZE-1)) / PAGE_SIZE;
226 // TODO: Validate `Length` is the same as was passed to AcpiOsMapMemory
227 MM_UnmapHWPages( (tVAddr)LogicalAddress, npages);
230 ACPI_STATUS AcpiOsGetPhysicalAddress(void *LogicalAddress, ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
232 if( LogicalAddress == NULL || PhysicalAddress == NULL )
233 return AE_BAD_PARAMETER;
235 tPAddr rv = MM_GetPhysAddr(LogicalAddress);
238 *PhysicalAddress = rv;
242 void *AcpiOsAllocate(ACPI_SIZE Size)
247 void AcpiOsFree(void *Memory)
252 BOOLEAN AcpiOsReadable(void *Memory, ACPI_SIZE Length)
254 return CheckMem(Memory, Length);
257 BOOLEAN AcpiOsWritable(void *Memory, ACPI_SIZE Length)
259 // TODO: Actually check if it's writable
260 return CheckMem(Memory, Length);
265 ACPI_THREAD_ID AcpiOsGetThreadId(void)
267 return Threads_GetTID() + 1;
270 ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function, void *Context)
272 // TODO: Need to store currently executing functions
273 if( Function == NULL )
274 return AE_BAD_PARAMETER;
275 Proc_SpawnWorker(Function, Context);
279 void AcpiOsSleep(UINT64 Milliseconds)
281 Time_Delay(Milliseconds);
284 void AcpiOsStall(UINT32 Microseconds)
286 // TODO: need a microsleep function
287 Microseconds += (1000-1);
288 Microseconds /= 1000;
289 Time_Delay(Microseconds);
292 void AcpiOsWaitEventsComplete(void)
297 // --- Mutexes etc ---
298 ACPI_STATUS AcpiOsCreateMutex(ACPI_MUTEX *OutHandle)
302 return AE_BAD_PARAMETER;
303 tMutex *ret = calloc( sizeof(tMutex), 1 );
306 ret->Name = "AcpiOsCreateMutex";
312 void AcpiOsDeleteMutex(ACPI_MUTEX Handle)
314 Mutex_Acquire(Handle);
318 ACPI_STATUS AcpiOsAcquireMutex(ACPI_MUTEX Handle, UINT16 Timeout)
321 return AE_BAD_PARAMETER;
323 Mutex_Acquire(Handle);
328 void AcpiOsReleaseMutex(ACPI_MUTEX Handle)
330 Mutex_Release(Handle);
333 ACPI_STATUS AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, ACPI_SEMAPHORE *OutHandle)
335 LOG("(MaxUnits=%i,InitialUnits=%i)", MaxUnits, InitialUnits);
337 return AE_BAD_PARAMETER;
338 tSemaphore *ret = calloc( sizeof(tSemaphore), 1 );
342 Semaphore_Init(ret, InitialUnits, MaxUnits, "AcpiOsCreateSemaphore", "");
347 ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_SEMAPHORE Handle)
350 return AE_BAD_PARAMETER;
357 ACPI_STATUS AcpiOsWaitSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units, UINT16 Timeout)
360 return AE_BAD_PARAMETER;
365 // NOTE: Possible race condition
366 if( Semaphore_GetValue(Handle) >= Units ) {
367 Semaphore_Wait(Handle, Units);
375 while(rem && now() - start < Timeout)
377 rem -= Semaphore_Wait(Handle, rem);
381 Semaphore_Signal(Handle, Units - rem);
388 ACPI_STATUS AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units)
391 return AE_BAD_PARAMETER;
393 // TODO: Support AE_LIMIT detection early (to avoid blocks)
396 int rv = Semaphore_Signal(Handle, Units);
403 ACPI_STATUS AcpiOsCreateLock(ACPI_SPINLOCK *OutHandle)
407 return AE_BAD_PARAMETER;
408 tShortSpinlock *lock = calloc(sizeof(tShortSpinlock), 1);
416 void AcpiOsDeleteLock(ACPI_SPINLOCK Handle)
421 ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK Handle)
427 void AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags)
432 // --- Interrupt handling ---
433 #define N_INT_LEVELS 16
434 ACPI_OSD_HANDLER gaACPI_InterruptHandlers[N_INT_LEVELS];
435 void *gaACPI_InterruptData[N_INT_LEVELS];
436 int gaACPI_InterruptHandles[N_INT_LEVELS];
438 void ACPI_int_InterruptProxy(int IRQ, void *data)
440 if( !gaACPI_InterruptHandlers[IRQ] )
442 gaACPI_InterruptHandlers[IRQ](gaACPI_InterruptData[IRQ]);
445 ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler, void *Context)
447 if( InterruptLevel >= N_INT_LEVELS || Handler == NULL )
448 return AE_BAD_PARAMETER;
449 if( gaACPI_InterruptHandlers[InterruptLevel] )
450 return AE_ALREADY_EXISTS;
452 gaACPI_InterruptHandlers[InterruptLevel] = Handler;
453 gaACPI_InterruptData[InterruptLevel] = Context;
455 gaACPI_InterruptHandles[InterruptLevel] = IRQ_AddHandler(InterruptLevel, ACPI_int_InterruptProxy, NULL);
459 ACPI_STATUS AcpiOsRemoveInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler)
461 if( InterruptLevel >= N_INT_LEVELS || Handler == NULL )
462 return AE_BAD_PARAMETER;
463 if( gaACPI_InterruptHandlers[InterruptLevel] != Handler )
465 gaACPI_InterruptHandlers[InterruptLevel] = NULL;
466 IRQ_RemHandler(gaACPI_InterruptHandles[InterruptLevel]);
470 // --- Memory Access ---
471 ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width)
474 if( Address < ONEMEG ) {
475 ptr = (void*)(KERNEL_BASE | Address);
478 ptr = (char*)MM_MapTemp(Address) + (Address & 0xFFF);
483 case 8: *Value = *(Uint8 *)ptr; break;
484 case 16: *Value = *(Uint16*)ptr; break;
485 case 32: *Value = *(Uint32*)ptr; break;
486 case 64: *Value = *(Uint64*)ptr; break;
489 if( Address >= ONEMEG ) {
496 ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width)
499 if( Address < ONEMEG ) {
500 ptr = (void*)(KERNEL_BASE | Address);
503 ptr = (char*)MM_MapTemp(Address) + (Address & 0xFFF);
508 case 8: *(Uint8 *)ptr = Value; break;
509 case 16: *(Uint16*)ptr = Value; break;
510 case 32: *(Uint32*)ptr = Value; break;
511 case 64: *(Uint64*)ptr = Value; break;
513 return AE_BAD_PARAMETER;
516 if( Address >= 1024*1024 ) {
523 // --- Port Input / Output ---
524 ACPI_STATUS AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
528 case 8: *Value = inb(Address); break;
529 case 16: *Value = inw(Address); break;
530 case 32: *Value = ind(Address); break;
532 return AE_BAD_PARAMETER;
537 ACPI_STATUS AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
541 case 8: outb(Address, Value); break;
542 case 16: outw(Address, Value); break;
543 case 32: outd(Address, Value); break;
545 return AE_BAD_PARAMETER;
550 // --- PCI Configuration Space Access ---
551 ACPI_STATUS AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value, UINT32 Width)
554 return AE_NOT_IMPLEMENTED;
557 ACPI_STATUS AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 Value, UINT32 Width)
560 return AE_NOT_IMPLEMENTED;
563 // --- Formatted Output ---
564 void AcpiOsPrintf(const char *Format, ...)
567 va_start(args, Format);
574 void AcpiOsVprintf(const char *Format, va_list Args)
579 void AcpiOsRedirectOutput(void *Destination)
581 // TODO: Do I even need to impliment this?
584 // --- Miscellaneous ---
585 UINT64 AcpiOsGetTimer(void)
587 return now() * 10 * 1000;
590 ACPI_STATUS AcpiOsSignal(UINT32 Function, void *Info)
594 case ACPI_SIGNAL_FATAL: {
595 ACPI_SIGNAL_FATAL_INFO *finfo = Info;
596 Log_Error("ACPI AML", "Fatal %x %x %x", finfo->Type, finfo->Code, finfo->Argument);
598 case ACPI_SIGNAL_BREAKPOINT: {
599 Log_Notice("ACPI AML", "Breakpoint %s", Info);
605 ACPI_STATUS AcpiOsGetLine(char *Buffer, UINT32 BufferLength, UINT32 *BytesRead)
608 return AE_NOT_IMPLEMENTED;