Kernel/x86 - Added USE_ACPICA makefile variable to easily enable/disable
[tpg/acess2.git] / KernelLand / Kernel / arch / x86 / acpica.c
1 /*
2  * Acess2 Kernel (x86 Core)
3  * - By John Hodge (thePowersGang)
4  *
5  * acpica.c
6  * - ACPICA Interface
7  */
8 #define ACPI_DEBUG_OUTPUT       1
9 #define DEBUG   1
10 #define _AcpiModuleName "Shim"
11 #define _COMPONENT      "Acess"
12 #include <acpi.h>
13 #include <timers.h>
14 #include <mutex.h>
15 #include <semaphore.h>
16
17 #define ONEMEG  (1024*1024)
18
19 // === GLOBALS ===
20 // - RSDP Address from uEFI
21 tPAddr  gACPI_RSDPOverride = 0;
22
23 // === PROTOTYPES ===
24 int     ACPICA_Initialise(void);
25 void    ACPI_int_InterruptProxy(int IRQ, void *data);
26
27
28 // === CODE ===
29 int ACPICA_Initialise(void)
30 {
31         ACPI_STATUS     rv;
32
33         #ifdef ACPI_DEBUG_OUTPUT
34         AcpiDbgLevel = ACPI_DB_ALL;
35         #endif
36
37         rv = AcpiInitializeSubsystem();
38         if( ACPI_FAILURE(rv) )
39         {
40                 Log_Error("ACPI", "AcpiInitializeSubsystem: %i", rv);
41                 return -1;
42         }
43         
44         rv = AcpiInitializeTables(NULL, 16, FALSE);
45         if( ACPI_FAILURE(rv) )
46         {
47                 Log_Error("ACPI", "AcpiInitializeTables: %i", rv);
48                 AcpiTerminate();
49                 return -1;
50         }
51
52         // AcpiInitializeTables?
53         rv = AcpiLoadTables();
54         if( ACPI_FAILURE(rv) )
55         {
56                 Log_Error("ACPI", "AcpiLoadTables: %i", rv);
57                 AcpiTerminate();
58                 return -1;
59         }
60         
61         rv = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
62         if( ACPI_FAILURE(rv) )
63         {
64                 Log_Error("ACPI", "AcpiEnableSubsystem: %i", rv);
65                 AcpiTerminate();
66                 return -1;
67         }
68
69         return 0;
70 }
71
72 // ---------------
73 // --- Exports ---
74 // ---------------
75 ACPI_STATUS AcpiOsInitialize(void)
76 {
77         return AE_OK;
78 }
79
80 ACPI_STATUS AcpiOsTerminate(void)
81 {
82         return AE_OK;
83 }
84
85 ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer(void)
86 {
87         ACPI_SIZE       val;
88         ACPI_STATUS     rv;
89
90         if( gACPI_RSDPOverride )
91                 return gACPI_RSDPOverride;      
92
93         rv = AcpiFindRootPointer(&val);
94         if( ACPI_FAILURE(rv) )
95                 return 0;
96
97         LOG("val=%x", val);
98         
99         return val;
100         // (Or use EFI)
101 }
102
103 ACPI_STATUS AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *PredefinedObject, ACPI_STRING *NewValue)
104 {
105         *NewValue = NULL;
106         return AE_OK;
107 }
108
109 ACPI_STATUS AcpiOsTableOverride(ACPI_TABLE_HEADER *ExisitingTable, ACPI_TABLE_HEADER **NewTable)
110 {
111         *NewTable = NULL;
112         return AE_OK;
113 }
114
115 ACPI_STATUS AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *ExisitingTable, ACPI_PHYSICAL_ADDRESS *NewAddress, UINT32 *NewTableLength)
116 {
117         *NewAddress = 0;
118         return AE_OK;
119 }
120
121 // -- Memory Management ---
122 struct sACPICache
123 {
124         Uint16  nObj;
125         Uint16  ObjectSize;
126         char    *Name;
127         void    *First;
128         char    ObjectStates[];
129 };
130
131 ACPI_STATUS AcpiOsCreateCache(char *CacheName, UINT16 ObjectSize, UINT16 MaxDepth, ACPI_CACHE_T **ReturnCache)
132 {
133         tACPICache      *ret;
134          int    namelen = (CacheName ? strlen(CacheName) : 0) + 1;
135         LOG("CacheName=%s, ObjSize=%x, MaxDepth=%x", CacheName, ObjectSize, MaxDepth);
136
137         namelen = (namelen + 3) & ~3;
138
139         ret = malloc(sizeof(*ret) + MaxDepth*sizeof(char) + namelen + MaxDepth*ObjectSize);
140         if( !ret )      return AE_NO_MEMORY;
141
142         ret->nObj = MaxDepth;
143         ret->ObjectSize = ObjectSize;
144         ret->Name = (char*)(ret->ObjectStates + MaxDepth);
145         ret->First = ret->Name + namelen;
146         if( CacheName )
147                 strcpy(ret->Name, CacheName);
148         else
149                 ret->Name[0] = 0;
150         memset(ret->ObjectStates, 0, sizeof(char)*MaxDepth);
151
152         LOG("Allocated cache '%s' (%i x 0x%x)", CacheName, MaxDepth, ObjectSize);
153         
154         *ReturnCache = ret;
155         
156         return AE_OK;
157 }
158
159 ACPI_STATUS AcpiOsDeleteCache(ACPI_CACHE_T *Cache)
160 {
161         if( Cache == NULL )
162                 return AE_BAD_PARAMETER;
163
164         free(Cache);
165         return AE_OK;
166 }
167
168 ACPI_STATUS AcpiOsPurgeCache(ACPI_CACHE_T *Cache)
169 {
170         if( Cache == NULL )
171                 return AE_BAD_PARAMETER;
172
173         memset(Cache->ObjectStates, 0, sizeof(char)*Cache->nObj);
174
175         return AE_OK;
176 }
177
178 void *AcpiOsAcquireObject(ACPI_CACHE_T *Cache)
179 {
180         ENTER("pCache", Cache);
181         for(int i = 0; i < Cache->nObj; i ++ )
182         {
183                 if( !Cache->ObjectStates[i] ) {
184                         Cache->ObjectStates[i] = 1;
185                         void *rv = (char*)Cache->First + i*Cache->ObjectSize;
186                         LEAVE('p', rv);
187                         return rv;
188                 }
189         }
190         
191         LEAVE('n');
192         return NULL;
193 }
194
195 ACPI_STATUS AcpiOsReleaseObject(ACPI_CACHE_T *Cache, void *Object)
196 {
197         if( Cache == NULL || Object == NULL )
198                 return AE_BAD_PARAMETER;
199
200         tVAddr delta = (tVAddr)Object - (tVAddr)Cache->First;
201         delta /= Cache->ObjectSize;
202         LOG("delta = %i, (limit %i)", delta, Cache->nObj);
203         
204         if( delta > Cache->nObj )
205                 return AE_BAD_PARAMETER;
206         
207         Cache->ObjectStates[delta] = 0;
208
209         return AE_OK;
210 }
211
212 void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length)
213 {
214         if( PhysicalAddress < ONEMEG )
215                 return (void*)(KERNEL_BASE | PhysicalAddress);
216         
217         Uint    ofs = PhysicalAddress & (PAGE_SIZE-1);
218         int npages = (ofs + Length + (PAGE_SIZE-1)) / PAGE_SIZE;
219         void *rv = ((char*)MM_MapHWPages(PhysicalAddress, npages)) + ofs;
220 //      MM_DumpTables(0, -1);
221         LOG("Map (%P+%i pg) to %p", PhysicalAddress, npages, rv);
222         return rv;
223 }
224
225 void AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length)
226 {
227         if( (tVAddr)LogicalAddress - KERNEL_BASE < ONEMEG )
228                 return ;
229
230         LOG("%p", LogicalAddress);
231
232         Uint    ofs = (tVAddr)LogicalAddress & (PAGE_SIZE-1);
233         int npages = (ofs + Length + (PAGE_SIZE-1)) / PAGE_SIZE;
234         // TODO: Validate `Length` is the same as was passed to AcpiOsMapMemory
235         MM_UnmapHWPages( (tVAddr)LogicalAddress, npages);
236 }
237
238 ACPI_STATUS AcpiOsGetPhysicalAddress(void *LogicalAddress, ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
239 {
240         if( LogicalAddress == NULL || PhysicalAddress == NULL )
241                 return AE_BAD_PARAMETER;
242         
243         tPAddr  rv = MM_GetPhysAddr(LogicalAddress);
244         if( rv == 0 )
245                 return AE_ERROR;
246         *PhysicalAddress = rv;
247         return AE_OK;
248 }
249
250 void *AcpiOsAllocate(ACPI_SIZE Size)
251 {
252         return malloc(Size);
253 }
254
255 void AcpiOsFree(void *Memory)
256 {
257         return free(Memory);
258 }
259
260 BOOLEAN AcpiOsReadable(void *Memory, ACPI_SIZE Length)
261 {
262         return CheckMem(Memory, Length);
263 }
264
265 BOOLEAN AcpiOsWritable(void *Memory, ACPI_SIZE Length)
266 {
267         // TODO: Actually check if it's writable
268         return CheckMem(Memory, Length);
269 }
270
271
272 // --- Threads ---
273 ACPI_THREAD_ID AcpiOsGetThreadId(void)
274 {
275         return Threads_GetTID() + 1;
276 }
277
278 ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function, void *Context)
279 {
280         // TODO: Need to store currently executing functions
281         if( Function == NULL )
282                 return AE_BAD_PARAMETER;
283         Proc_SpawnWorker(Function, Context);
284         return AE_OK;
285 }
286
287 void AcpiOsSleep(UINT64 Milliseconds)
288 {
289         Time_Delay(Milliseconds);
290 }
291
292 void AcpiOsStall(UINT32 Microseconds)
293 {
294         // TODO: need a microsleep function
295         Microseconds += (1000-1);
296         Microseconds /= 1000;
297         Time_Delay(Microseconds);
298 }
299
300 void AcpiOsWaitEventsComplete(void)
301 {
302         // TODO: 
303 }
304
305 // --- Mutexes etc ---
306 ACPI_STATUS AcpiOsCreateMutex(ACPI_MUTEX *OutHandle)
307 {
308         LOG("()");
309         if( !OutHandle )
310                 return AE_BAD_PARAMETER;
311         tMutex  *ret = calloc( sizeof(tMutex), 1 );
312         if( !ret )
313                 return AE_NO_MEMORY;
314         ret->Name = "AcpiOsCreateMutex";
315         *OutHandle = ret;
316         
317         return AE_OK;
318 }
319
320 void AcpiOsDeleteMutex(ACPI_MUTEX Handle)
321 {
322         Mutex_Acquire(Handle);
323         free(Handle);
324 }
325
326 ACPI_STATUS AcpiOsAcquireMutex(ACPI_MUTEX Handle, UINT16 Timeout)
327 {
328         if( Handle == NULL )
329                 return AE_BAD_PARAMETER;
330
331         Mutex_Acquire(Handle);  
332
333         return AE_OK;
334 }
335
336 void AcpiOsReleaseMutex(ACPI_MUTEX Handle)
337 {
338         Mutex_Release(Handle);
339 }
340
341 ACPI_STATUS AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, ACPI_SEMAPHORE *OutHandle)
342 {
343         LOG("(MaxUnits=%i,InitialUnits=%i)", MaxUnits, InitialUnits);
344         if( !OutHandle )
345                 return AE_BAD_PARAMETER;
346         tSemaphore      *ret = calloc( sizeof(tSemaphore), 1 );
347         if( !ret )
348                 return AE_NO_MEMORY;
349         
350         Semaphore_Init(ret, InitialUnits, MaxUnits, "AcpiOsCreateSemaphore", "");
351         *OutHandle = ret;
352         return AE_OK;
353 }
354
355 ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_SEMAPHORE Handle)
356 {
357         if( !Handle )
358                 return AE_BAD_PARAMETER;
359
360         free(Handle);   
361
362         return AE_OK;
363 }
364
365 ACPI_STATUS AcpiOsWaitSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units, UINT16 Timeout)
366 {
367         if( !Handle )
368                 return AE_BAD_PARAMETER;
369
370         // Special case
371         if( Timeout == 0 )
372         {
373                 // NOTE: Possible race condition
374                 if( Semaphore_GetValue(Handle) >= Units ) {
375                         Semaphore_Wait(Handle, Units);
376                         return AE_OK;
377                 }
378                 return AE_TIME;
379         }
380
381         tTime   start = now();
382         UINT32  rem = Units;
383         while(rem && now() - start < Timeout)
384         {
385                 rem -= Semaphore_Wait(Handle, rem);
386         }
387
388         if( rem ) {
389                 Semaphore_Signal(Handle, Units - rem);
390                 return AE_TIME;
391         }
392
393         return AE_OK;
394 }
395
396 ACPI_STATUS AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units)
397 {
398         if( !Handle )
399                 return AE_BAD_PARAMETER;
400
401         // TODO: Support AE_LIMIT detection early (to avoid blocks)
402
403         // NOTE: Blocks
404         int rv = Semaphore_Signal(Handle, Units);
405         if( rv != Units )
406                 return AE_LIMIT;
407         
408         return AE_OK;
409 }
410
411 ACPI_STATUS AcpiOsCreateLock(ACPI_SPINLOCK *OutHandle)
412 {
413         LOG("()");
414         if( !OutHandle )
415                 return AE_BAD_PARAMETER;
416         tShortSpinlock  *lock = calloc(sizeof(tShortSpinlock), 1);
417         if( !lock )
418                 return AE_NO_MEMORY;
419         
420         *OutHandle = lock;
421         return AE_OK;
422 }
423
424 void AcpiOsDeleteLock(ACPI_SPINLOCK Handle)
425 {
426         free(Handle);
427 }
428
429 ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK Handle)
430 {
431         SHORTLOCK(Handle);
432         return 0;
433 }
434
435 void AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags)
436 {
437         SHORTREL(Handle);
438 }
439
440 // --- Interrupt handling ---
441 #define N_INT_LEVELS    16
442 ACPI_OSD_HANDLER        gaACPI_InterruptHandlers[N_INT_LEVELS];
443 void    *gaACPI_InterruptData[N_INT_LEVELS];
444  int    gaACPI_InterruptHandles[N_INT_LEVELS];
445
446 void ACPI_int_InterruptProxy(int IRQ, void *data)
447 {
448         if( !gaACPI_InterruptHandlers[IRQ] )
449                 return ;
450         gaACPI_InterruptHandlers[IRQ](gaACPI_InterruptData[IRQ]);
451 }
452
453 ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler, void *Context)
454 {
455         if( InterruptLevel >= N_INT_LEVELS || Handler == NULL )
456                 return AE_BAD_PARAMETER;
457         if( gaACPI_InterruptHandlers[InterruptLevel] )
458                 return AE_ALREADY_EXISTS;
459
460         gaACPI_InterruptHandlers[InterruptLevel] = Handler;
461         gaACPI_InterruptData[InterruptLevel] = Context;
462
463         gaACPI_InterruptHandles[InterruptLevel] = IRQ_AddHandler(InterruptLevel, ACPI_int_InterruptProxy, NULL);
464         return AE_OK;
465 }
466
467 ACPI_STATUS AcpiOsRemoveInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler)
468 {
469         if( InterruptLevel >= N_INT_LEVELS || Handler == NULL )
470                 return AE_BAD_PARAMETER;
471         if( gaACPI_InterruptHandlers[InterruptLevel] != Handler )
472                 return AE_NOT_EXIST;
473         gaACPI_InterruptHandlers[InterruptLevel] = NULL;
474         IRQ_RemHandler(gaACPI_InterruptHandles[InterruptLevel]);
475         return AE_OK;
476 }
477
478 // --- Memory Access ---
479 ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width)
480 {
481         void *ptr;
482         if( Address < ONEMEG ) {
483                 ptr = (void*)(KERNEL_BASE | Address);
484         }
485         else {
486                 ptr = (char*)MM_MapTemp(Address) + (Address & 0xFFF);
487         }
488
489         switch(Width)
490         {
491         case 8:         *Value = *(Uint8 *)ptr; break;
492         case 16:        *Value = *(Uint16*)ptr; break;
493         case 32:        *Value = *(Uint32*)ptr; break;
494         case 64:        *Value = *(Uint64*)ptr; break;
495         }
496
497         if( Address >= ONEMEG ) {
498                 MM_FreeTemp(ptr);
499         }
500
501         return AE_OK;
502 }
503
504 ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width)
505 {
506         void *ptr;
507         if( Address < ONEMEG ) {
508                 ptr = (void*)(KERNEL_BASE | Address);
509         }
510         else {
511                 ptr = (char*)MM_MapTemp(Address) + (Address & 0xFFF);
512         }
513
514         switch(Width)
515         {
516         case 8:         *(Uint8 *)ptr = Value;  break;
517         case 16:        *(Uint16*)ptr = Value;  break;
518         case 32:        *(Uint32*)ptr = Value;  break;
519         case 64:        *(Uint64*)ptr = Value;  break;
520         default:
521                 return AE_BAD_PARAMETER;
522         }
523
524         if( Address >= 1024*1024 ) {
525                 MM_FreeTemp(ptr);
526         }
527         
528         return AE_OK;
529 }
530
531 // --- Port Input / Output ---
532 ACPI_STATUS AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
533 {
534         switch(Width)
535         {
536         case 8:         *Value = inb(Address);  break;
537         case 16:        *Value = inw(Address);  break;
538         case 32:        *Value = ind(Address);  break;
539         default:
540                 return AE_BAD_PARAMETER;
541         }
542         return AE_OK;
543 }
544
545 ACPI_STATUS AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
546 {
547         switch(Width)
548         {
549         case 8:         outb(Address, Value);   break;
550         case 16:        outw(Address, Value);   break;
551         case 32:        outd(Address, Value);   break;
552         default:
553                 return AE_BAD_PARAMETER;
554         }
555         return AE_OK;
556 }
557
558 // --- PCI Configuration Space Access ---
559 ACPI_STATUS AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value, UINT32 Width)
560 {
561         UNIMPLEMENTED();
562         return AE_NOT_IMPLEMENTED;
563 }
564
565 ACPI_STATUS AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 Value, UINT32 Width)
566 {
567         UNIMPLEMENTED();
568         return AE_NOT_IMPLEMENTED;
569 }
570
571 // --- Formatted Output ---
572 void AcpiOsPrintf(const char *Format, ...)
573 {
574         va_list args;
575         va_start(args, Format);
576
577         LogFV(Format, args);
578
579         va_end(args);
580 }
581
582 void AcpiOsVprintf(const char *Format, va_list Args)
583 {
584         LogFV(Format, Args);
585 }
586
587 void AcpiOsRedirectOutput(void *Destination)
588 {
589         // TODO: Do I even need to impliment this?
590 }
591
592 // --- Miscellaneous ---
593 UINT64 AcpiOsGetTimer(void)
594 {
595         return now() * 10 * 1000;
596 }
597
598 ACPI_STATUS AcpiOsSignal(UINT32 Function, void *Info)
599 {
600         switch(Function)
601         {
602         case ACPI_SIGNAL_FATAL: {
603                 ACPI_SIGNAL_FATAL_INFO  *finfo = Info;
604                 Log_Error("ACPI AML", "Fatal %x %x %x", finfo->Type, finfo->Code, finfo->Argument);
605                 break; }
606         case ACPI_SIGNAL_BREAKPOINT: {
607                 Log_Notice("ACPI AML", "Breakpoint %s", Info);
608                 break; };
609         }
610         return AE_OK;
611 }
612
613 ACPI_STATUS AcpiOsGetLine(char *Buffer, UINT32 BufferLength, UINT32 *BytesRead)
614 {
615         UNIMPLEMENTED();
616         return AE_NOT_IMPLEMENTED;
617 }
618

UCC git Repository :: git.ucc.asn.au