2 * Acess2 Kernel (x86 Core)
3 * - By John Hodge (thePowersGang)
12 #include <semaphore.h>
15 int ACPICA_Initialise(void);
16 void ACPI_int_InterruptProxy(int IRQ, void *data);
20 int ACPICA_Initialise(void)
24 rv = AcpiInitializeSubsystem();
25 if( ACPI_FAILURE(rv) )
27 Log_Error("ACPI", "AcpiInitializeSubsystem: %i", rv);
31 rv = AcpiInitializeTables(NULL, 16, FALSE);
32 if( ACPI_FAILURE(rv) )
34 Log_Error("ACPI", "AcpiInitializeTables: %i", rv);
39 // AcpiInitializeTables?
40 rv = AcpiLoadTables();
41 if( ACPI_FAILURE(rv) )
43 Log_Error("ACPI", "AcpiLoadTables: %i", rv);
48 rv = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
49 if( ACPI_FAILURE(rv) )
51 Log_Error("ACPI", "AcpiEnableSubsystem: %i", rv);
62 ACPI_STATUS AcpiOsInitialize(void)
67 ACPI_STATUS AcpiOsTerminate(void)
72 ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer(void)
77 rv = AcpiFindRootPointer(&val);
78 if( ACPI_FAILURE(rv) )
85 ACPI_STATUS AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *PredefinedObject, ACPI_STRING *NewValue)
91 ACPI_STATUS AcpiOsTableOverride(ACPI_TABLE_HEADER *ExisitingTable, ACPI_TABLE_HEADER **NewTable)
97 ACPI_STATUS AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *ExisitingTable, ACPI_PHYSICAL_ADDRESS *NewAddress, UINT32 *NewTableLength)
103 // -- Memory Management ---
113 ACPI_STATUS AcpiOsCreateCache(char *CacheName, UINT16 ObjectSize, UINT16 MaxDepth, ACPI_CACHE_T **ReturnCache)
116 int namelen = (CacheName ? strlen(CacheName) : 0) + 1;
117 LOG("CacheName=%s, ObjSize=%x, MaxDepth=%x", CacheName, ObjectSize, MaxDepth);
119 ret = malloc(sizeof(*ret) + MaxDepth*sizeof(char) + namelen + MaxDepth*ObjectSize);
120 if( !ret ) return AE_NO_MEMORY;
122 ret->nObj = MaxDepth;
123 ret->ObjectSize = ObjectSize;
124 ret->Name = (char*)(ret->ObjectStates + MaxDepth);
125 ret->First = ret->Name + namelen;
127 strcpy(ret->Name, CacheName);
130 memset(ret->ObjectStates, 0, sizeof(char)*MaxDepth);
132 LOG("Allocated cache '%s' (%i x 0x%x)", CacheName, MaxDepth, ObjectSize);
139 ACPI_STATUS AcpiOsDeleteCache(ACPI_CACHE_T *Cache)
142 return AE_BAD_PARAMETER;
148 ACPI_STATUS AcpiOsPurgeCache(ACPI_CACHE_T *Cache)
151 return AE_BAD_PARAMETER;
153 memset(Cache->ObjectStates, 0, sizeof(char)*Cache->nObj);
158 void *AcpiOsAcquireObject(ACPI_CACHE_T *Cache)
160 LOG("(Cache=%p)", Cache);
161 for(int i = 0; i < Cache->nObj; i ++ )
163 if( !Cache->ObjectStates[i] ) {
164 Cache->ObjectStates[i] = 1;
165 return (char*)Cache->First + i*Cache->ObjectSize;
172 ACPI_STATUS AcpiOsReleaseObject(ACPI_CACHE_T *Cache, void *Object)
174 if( Cache == NULL || Object == NULL )
175 return AE_BAD_PARAMETER;
177 tVAddr delta = (tVAddr)Object - (tVAddr)Cache->First;
178 delta /= Cache->ObjectSize;
180 if( delta > Cache->nObj )
181 return AE_BAD_PARAMETER;
183 Cache->ObjectStates[delta] = 0;
188 void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length)
190 Uint ofs = PhysicalAddress & (PAGE_SIZE-1);
191 int npages = (ofs + Length + (PAGE_SIZE-1)) / PAGE_SIZE;
192 return (char*)MM_MapHWPages(PhysicalAddress, npages) + ofs;
195 void AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length)
197 Uint ofs = (tVAddr)LogicalAddress & (PAGE_SIZE-1);
198 int npages = (ofs + Length + (PAGE_SIZE-1)) / PAGE_SIZE;
199 // TODO: Validate `Length` is the same as was passed to AcpiOsMapMemory
200 MM_UnmapHWPages( (tVAddr)LogicalAddress, npages);
203 ACPI_STATUS AcpiOsGetPhysicalAddress(void *LogicalAddress, ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
205 if( LogicalAddress == NULL || PhysicalAddress == NULL )
206 return AE_BAD_PARAMETER;
208 tPAddr rv = MM_GetPhysAddr(LogicalAddress);
211 *PhysicalAddress = rv;
215 void *AcpiOsAllocate(ACPI_SIZE Size)
220 void AcpiOsFree(void *Memory)
225 BOOLEAN AcpiOsReadable(void *Memory, ACPI_SIZE Length)
227 return CheckMem(Memory, Length);
230 BOOLEAN AcpiOsWritable(void *Memory, ACPI_SIZE Length)
232 // TODO: Actually check if it's writable
233 return CheckMem(Memory, Length);
238 ACPI_THREAD_ID AcpiOsGetThreadId(void)
240 return Threads_GetTID();
243 ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function, void *Context)
245 // TODO: Need to store currently executing functions
246 if( Function == NULL )
247 return AE_BAD_PARAMETER;
248 Proc_SpawnWorker(Function, Context);
252 void AcpiOsSleep(UINT64 Milliseconds)
254 Time_Delay(Milliseconds);
257 void AcpiOsStall(UINT32 Microseconds)
259 // TODO: need a microsleep function
260 Microseconds += (1000-1);
261 Microseconds /= 1000;
262 Time_Delay(Microseconds);
265 void AcpiOsWaitEventsComplete(void)
270 // --- Mutexes etc ---
271 ACPI_STATUS AcpiOsCreateMutex(ACPI_MUTEX *OutHandle)
275 return AE_BAD_PARAMETER;
276 tMutex *ret = calloc( sizeof(tMutex), 1 );
279 ret->Name = "AcpiOsCreateMutex";
285 void AcpiOsDeleteMutex(ACPI_MUTEX Handle)
287 Mutex_Acquire(Handle);
291 ACPI_STATUS AcpiOsAcquireMutex(ACPI_MUTEX Handle, UINT16 Timeout)
294 return AE_BAD_PARAMETER;
296 Mutex_Acquire(Handle);
301 void AcpiOsReleaseMutex(ACPI_MUTEX Handle)
303 Mutex_Release(Handle);
306 ACPI_STATUS AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, ACPI_SEMAPHORE *OutHandle)
308 LOG("(MaxUnits=%i,InitialUnits=%i)", MaxUnits, InitialUnits);
310 return AE_BAD_PARAMETER;
311 tSemaphore *ret = calloc( sizeof(tSemaphore), 1 );
315 Semaphore_Init(ret, InitialUnits, MaxUnits, "AcpiOsCreateSemaphore", "");
320 ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_SEMAPHORE Handle)
323 return AE_BAD_PARAMETER;
330 ACPI_STATUS AcpiOsWaitSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units, UINT16 Timeout)
333 return AE_BAD_PARAMETER;
338 // NOTE: Possible race condition
339 if( Semaphore_GetValue(Handle) >= Units ) {
340 Semaphore_Wait(Handle, Units);
348 while(rem && now() - start < Timeout)
350 rem -= Semaphore_Wait(Handle, rem);
354 Semaphore_Signal(Handle, Units - rem);
361 ACPI_STATUS AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units)
364 return AE_BAD_PARAMETER;
366 // TODO: Support AE_LIMIT detection early (to avoid blocks)
369 int rv = Semaphore_Signal(Handle, Units);
376 ACPI_STATUS AcpiOsCreateLock(ACPI_SPINLOCK *OutHandle)
380 return AE_BAD_PARAMETER;
381 tShortSpinlock *lock = calloc(sizeof(tShortSpinlock), 1);
389 void AcpiOsDeleteLock(ACPI_SPINLOCK Handle)
394 ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK Handle)
400 void AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags)
405 // --- Interrupt handling ---
406 #define N_INT_LEVELS 16
407 ACPI_OSD_HANDLER gaACPI_InterruptHandlers[N_INT_LEVELS];
408 void *gaACPI_InterruptData[N_INT_LEVELS];
409 int gaACPI_InterruptHandles[N_INT_LEVELS];
411 void ACPI_int_InterruptProxy(int IRQ, void *data)
413 if( !gaACPI_InterruptHandlers[IRQ] )
415 gaACPI_InterruptHandlers[IRQ](gaACPI_InterruptData[IRQ]);
418 ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler, void *Context)
420 if( InterruptLevel >= N_INT_LEVELS || Handler == NULL )
421 return AE_BAD_PARAMETER;
422 if( gaACPI_InterruptHandlers[InterruptLevel] )
423 return AE_ALREADY_EXISTS;
425 gaACPI_InterruptHandlers[InterruptLevel] = Handler;
426 gaACPI_InterruptData[InterruptLevel] = Context;
428 gaACPI_InterruptHandles[InterruptLevel] = IRQ_AddHandler(InterruptLevel, ACPI_int_InterruptProxy, NULL);
432 ACPI_STATUS AcpiOsRemoveInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler)
434 if( InterruptLevel >= N_INT_LEVELS || Handler == NULL )
435 return AE_BAD_PARAMETER;
436 if( gaACPI_InterruptHandlers[InterruptLevel] != Handler )
438 gaACPI_InterruptHandlers[InterruptLevel] = NULL;
439 IRQ_RemHandler(gaACPI_InterruptHandles[InterruptLevel]);
443 // --- Memory Access ---
444 ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width)
447 if( Address < 1024*1024 ) {
448 ptr = (void*)(KERNEL_BASE | Address);
451 ptr = (char*)MM_MapTemp(Address) + (Address & 0xFFF);
456 case 8: *Value = *(Uint8 *)ptr; break;
457 case 16: *Value = *(Uint16*)ptr; break;
458 case 32: *Value = *(Uint32*)ptr; break;
459 case 64: *Value = *(Uint64*)ptr; break;
462 if( Address >= 1024*1024 ) {
469 ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width)
472 if( Address < 1024*1024 ) {
473 ptr = (void*)(KERNEL_BASE | Address);
476 ptr = (char*)MM_MapTemp(Address) + (Address & 0xFFF);
481 case 8: *(Uint8 *)ptr = Value; break;
482 case 16: *(Uint16*)ptr = Value; break;
483 case 32: *(Uint32*)ptr = Value; break;
484 case 64: *(Uint64*)ptr = Value; break;
486 return AE_BAD_PARAMETER;
489 if( Address >= 1024*1024 ) {
496 // --- Port Input / Output ---
497 ACPI_STATUS AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
501 case 8: *Value = inb(Address); break;
502 case 16: *Value = inw(Address); break;
503 case 32: *Value = ind(Address); break;
505 return AE_BAD_PARAMETER;
510 ACPI_STATUS AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
514 case 8: outb(Address, Value); break;
515 case 16: outw(Address, Value); break;
516 case 32: outd(Address, Value); break;
518 return AE_BAD_PARAMETER;
523 // --- PCI Configuration Space Access ---
524 ACPI_STATUS AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value, UINT32 Width)
527 return AE_NOT_IMPLEMENTED;
530 ACPI_STATUS AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 Value, UINT32 Width)
533 return AE_NOT_IMPLEMENTED;
536 // --- Formatted Output ---
537 void AcpiOsPrintf(const char *Format, ...)
540 va_start(args, Format);
547 void AcpiOsVprintf(const char *Format, va_list Args)
552 void AcpiOsRedirectOutput(void *Destination)
554 // TODO: is this needed?
557 // --- Miscellaneous ---
558 UINT64 AcpiOsGetTimer(void)
560 return now() * 10 * 1000;
563 ACPI_STATUS AcpiOsSignal(UINT32 Function, void *Info)
567 case ACPI_SIGNAL_FATAL: {
568 ACPI_SIGNAL_FATAL_INFO *finfo = Info;
569 Log_Error("ACPI AML", "Fatal %x %x %x", finfo->Type, finfo->Code, finfo->Argument);
571 case ACPI_SIGNAL_BREAKPOINT: {
572 Log_Notice("ACPI AML", "Breakpoint %s", Info);
578 ACPI_STATUS AcpiOsGetLine(char *Buffer, UINT32 BufferLength, UINT32 *BytesRead)
581 return AE_NOT_IMPLEMENTED;