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

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