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

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