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

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