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

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