d86e70bcb7cf92888ffc9ba52422ed171a32eea2
[reactos.git] / reactos / drivers / bus / acpi / osl.c
1 /*******************************************************************************
2 * *
3 * ACPI Component Architecture Operating System Layer (OSL) for ReactOS *
4 * *
5 *******************************************************************************/
6 #include <ntddk.h>
7
8 #include <acpi.h>
9
10 #define NDEBUG
11 #include <debug.h>
12
13 #define NUM_SEMAPHORES 128
14
15 static PKINTERRUPT AcpiInterrupt;
16 static BOOLEAN AcpiInterruptHandlerRegistered = FALSE;
17 static ACPI_OSD_HANDLER AcpiIrqHandler = NULL;
18 static PVOID AcpiIrqContext = NULL;
19 static ULONG AcpiIrqNumber = 0;
20 static KDPC AcpiDpc;
21 static PVOID IVTVirtualAddress = NULL;
22
23
24 typedef struct semaphore_entry
25 {
26 UINT16 MaxUnits;
27 UINT16 CurrentUnits;
28 void *OsHandle;
29 } SEMAPHORE_ENTRY;
30
31 static SEMAPHORE_ENTRY AcpiGbl_Semaphores[NUM_SEMAPHORES];
32
33 VOID NTAPI
34 OslDpcStub(
35 IN PKDPC Dpc,
36 IN PVOID DeferredContext,
37 IN PVOID SystemArgument1,
38 IN PVOID SystemArgument2)
39 {
40 ACPI_OSD_EXEC_CALLBACK Routine = (ACPI_OSD_EXEC_CALLBACK)SystemArgument1;
41
42 DPRINT("OslDpcStub()\n");
43 DPRINT("Calling [%p]([%p])\n", Routine, SystemArgument2);
44 (*Routine)(SystemArgument2);
45 }
46
47 BOOLEAN NTAPI
48 OslIsrStub(
49 PKINTERRUPT Interrupt,
50 PVOID ServiceContext)
51 {
52 INT32 Status;
53
54 Status = (*AcpiIrqHandler)(AcpiIrqContext);
55
56 if (ACPI_SUCCESS(Status))
57 return TRUE;
58 else
59 return FALSE;
60 }
61
62 ACPI_STATUS
63 AcpiOsRemoveInterruptHandler (
64 UINT32 InterruptNumber,
65 ACPI_OSD_HANDLER ServiceRoutine);
66
67 ACPI_STATUS
68 AcpiOsInitialize (void)
69 {
70 DPRINT("AcpiOsInitialize called\n");
71
72 #ifndef NDEBUG
73 /* Verboseness level of the acpica core */
74 AcpiDbgLevel = 0x00FFFFFF;
75 AcpiDbgLayer = 0xFFFFFFFF;
76 #endif
77
78 UINT32 i;
79
80 for (i = 0; i < NUM_SEMAPHORES; i++)
81 {
82 AcpiGbl_Semaphores[i].OsHandle = NULL;
83 }
84
85 KeInitializeDpc(&AcpiDpc, OslDpcStub, NULL);
86
87 return AE_OK;
88 }
89
90 ACPI_STATUS
91 AcpiOsTerminate(void)
92 {
93 DPRINT("AcpiOsTerminate() called\n");
94
95 if (AcpiInterruptHandlerRegistered)
96 AcpiOsRemoveInterruptHandler(AcpiIrqNumber, AcpiIrqHandler);
97
98 return AE_OK;
99 }
100
101 void ACPI_INTERNAL_VAR_XFACE
102 AcpiOsPrintf (
103 const char *Fmt,
104 ...)
105 {
106 va_list Args;
107 va_start (Args, Fmt);
108
109 AcpiOsVprintf (Fmt, Args);
110
111 va_end (Args);
112 return;
113 }
114
115 void
116 AcpiOsVprintf (
117 const char *Fmt,
118 va_list Args)
119 {
120 vDbgPrintEx (-1, DPFLTR_ERROR_LEVEL, Fmt, Args);
121 return;
122 }
123
124 void *
125 AcpiOsAllocate (ACPI_SIZE size)
126 {
127 DPRINT("AcpiOsAllocate size %d\n",size);
128 return ExAllocatePool(NonPagedPool, size);
129 }
130
131 void *
132 AcpiOsCallocate(ACPI_SIZE size)
133 {
134 PVOID ptr = ExAllocatePool(NonPagedPool, size);
135 if (ptr)
136 memset(ptr, 0, size);
137 return ptr;
138 }
139
140 void
141 AcpiOsFree(void *ptr)
142 {
143 if (!ptr)
144 DPRINT1("Attempt to free null pointer!!!\n");
145 ExFreePool(ptr);
146 }
147
148 #ifndef ACPI_USE_LOCAL_CACHE
149
150 void*
151 AcpiOsAcquireObjectHelper (
152 POOL_TYPE PoolType,
153 SIZE_T NumberOfBytes,
154 ULONG Tag)
155 {
156 void* Alloc = ExAllocatePool(PoolType, NumberOfBytes);
157
158 /* acpica expects memory allocated from cache to be zeroed */
159 RtlZeroMemory(Alloc,NumberOfBytes);
160 return Alloc;
161 }
162
163 ACPI_STATUS
164 AcpiOsCreateCache (
165 char *CacheName,
166 UINT16 ObjectSize,
167 UINT16 MaxDepth,
168 ACPI_CACHE_T **ReturnCache)
169 {
170 PNPAGED_LOOKASIDE_LIST Lookaside =
171 ExAllocatePool(NonPagedPool,sizeof(NPAGED_LOOKASIDE_LIST));
172
173 ExInitializeNPagedLookasideList(Lookaside,
174 (PALLOCATE_FUNCTION)AcpiOsAcquireObjectHelper,// custom memory allocator
175 NULL,
176 0,
177 ObjectSize,
178 'IPCA',
179 0);
180 *ReturnCache = (ACPI_CACHE_T *)Lookaside;
181
182 DPRINT("AcpiOsCreateCache %p\n", Lookaside);
183 return (AE_OK);
184 }
185
186 ACPI_STATUS
187 AcpiOsDeleteCache (
188 ACPI_CACHE_T *Cache)
189 {
190 DPRINT("AcpiOsDeleteCache %p\n", Cache);
191 ExDeleteNPagedLookasideList(
192 (PNPAGED_LOOKASIDE_LIST) Cache);
193 ExFreePool(Cache);
194 return (AE_OK);
195 }
196
197 ACPI_STATUS
198 AcpiOsPurgeCache (
199 ACPI_CACHE_T *Cache)
200 {
201 DPRINT("AcpiOsPurgeCache\n");
202 /* No such functionality for LookAside lists */
203 return (AE_OK);
204 }
205
206 void *
207 AcpiOsAcquireObject (
208 ACPI_CACHE_T *Cache)
209 {
210 PNPAGED_LOOKASIDE_LIST List = (PNPAGED_LOOKASIDE_LIST)Cache;
211 DPRINT("AcpiOsAcquireObject from %p\n", Cache);
212 void* ptr =
213 ExAllocateFromNPagedLookasideList(List);
214 ASSERT(ptr);
215
216 RtlZeroMemory(ptr,List->L.Size);
217 return ptr;
218 }
219
220 ACPI_STATUS
221 AcpiOsReleaseObject (
222 ACPI_CACHE_T *Cache,
223 void *Object)
224 {
225 DPRINT("AcpiOsReleaseObject %p from %p\n",Object, Cache);
226 ExFreeToNPagedLookasideList(
227 (PNPAGED_LOOKASIDE_LIST)Cache,
228 Object);
229 return (AE_OK);
230 }
231
232 #endif
233
234 void *
235 AcpiOsMapMemory (
236 ACPI_PHYSICAL_ADDRESS phys,
237 ACPI_SIZE length)
238 {
239 PHYSICAL_ADDRESS Address;
240
241 DPRINT("AcpiOsMapMemory(phys 0x%X size 0x%X)\n", (ULONG)phys, length);
242 if (phys == 0x0)
243 {
244 IVTVirtualAddress = ExAllocatePool(NonPagedPool, length);
245 return IVTVirtualAddress;
246 }
247
248 Address.QuadPart = (ULONG)phys;
249 return MmMapIoSpace(Address, length, MmNonCached);
250 }
251
252 void
253 AcpiOsUnmapMemory (
254 void *virt,
255 ACPI_SIZE length)
256 {
257 DPRINT("AcpiOsUnmapMemory()\n");
258
259 if (virt == 0x0)
260 {
261 ExFreePool(IVTVirtualAddress);
262 return;
263 }
264 MmUnmapIoSpace(virt, length);
265 }
266
267 UINT32
268 AcpiOsInstallInterruptHandler (
269 UINT32 InterruptNumber,
270 ACPI_OSD_HANDLER ServiceRoutine,
271 void *Context)
272 {
273 ULONG Vector;
274 KIRQL DIrql;
275 KAFFINITY Affinity;
276 NTSTATUS Status;
277
278 DPRINT("AcpiOsInstallInterruptHandler()\n");
279 Vector = HalGetInterruptVector(
280 Internal,
281 0,
282 InterruptNumber,
283 0,
284 &DIrql,
285 &Affinity);
286
287 AcpiIrqNumber = InterruptNumber;
288 AcpiIrqHandler = ServiceRoutine;
289 AcpiIrqContext = Context;
290 AcpiInterruptHandlerRegistered = TRUE;
291
292 Status = IoConnectInterrupt(
293 &AcpiInterrupt,
294 OslIsrStub,
295 NULL,
296 NULL,
297 Vector,
298 DIrql,
299 DIrql,
300 LevelSensitive, /* FIXME: LevelSensitive or Latched? */
301 TRUE,
302 Affinity,
303 FALSE);
304
305 if (!NT_SUCCESS(Status))
306 {
307 DPRINT("Could not connect to interrupt %d\n", Vector);
308 return AE_ERROR;
309 }
310 return AE_OK;
311 }
312
313 ACPI_STATUS
314 AcpiOsRemoveInterruptHandler (
315 UINT32 InterruptNumber,
316 ACPI_OSD_HANDLER ServiceRoutine)
317 {
318 DPRINT("AcpiOsRemoveInterruptHandler()\n");
319 if (AcpiInterruptHandlerRegistered)
320 {
321 IoDisconnectInterrupt(AcpiInterrupt);
322 AcpiInterrupt = NULL;
323 AcpiInterruptHandlerRegistered = FALSE;
324 }
325
326 return AE_OK;
327 }
328
329 void
330 AcpiOsStall (UINT32 microseconds)
331 {
332 DPRINT("AcpiOsStall %d\n",microseconds);
333 KeStallExecutionProcessor(microseconds);
334 return;
335 }
336
337 void
338 AcpiOsSleep (ACPI_INTEGER milliseconds)
339 {
340 DPRINT("AcpiOsSleep %d\n", milliseconds);
341 KeStallExecutionProcessor(milliseconds*1000);
342 return;
343 }
344
345 ACPI_STATUS
346 AcpiOsReadPort (
347 ACPI_IO_ADDRESS Address,
348 UINT32 *Value,
349 UINT32 Width)
350 {
351 DPRINT("AcpiOsReadPort %p, width %d\n",Address,Width);
352
353 switch (Width)
354 {
355 case 8:
356 *Value = READ_PORT_UCHAR((PUCHAR)Address);
357 break;
358
359 case 16:
360 *Value = READ_PORT_USHORT((PUSHORT)Address);
361 break;
362
363 case 32:
364 *Value = READ_PORT_ULONG((PULONG)Address);
365 break;
366 default:
367 DPRINT1("AcpiOsReadPort got bad width: %d\n",Width);
368 return (AE_BAD_PARAMETER);
369 break;
370 }
371 return (AE_OK);
372 }
373
374 ACPI_STATUS
375 AcpiOsWritePort (
376 ACPI_IO_ADDRESS Address,
377 UINT32 Value,
378 UINT32 Width)
379 {
380 DPRINT("AcpiOsWritePort %p, width %d\n",Address,Width);
381 switch (Width)
382 {
383 case 8:
384 WRITE_PORT_UCHAR((PUCHAR)Address, Value);
385 break;
386
387 case 16:
388 WRITE_PORT_USHORT((PUSHORT)Address, Value);
389 break;
390
391 case 32:
392 WRITE_PORT_ULONG((PULONG)Address, Value);
393 break;
394
395 default:
396 DPRINT1("AcpiOsWritePort got bad width: %d\n",Width);
397 return (AE_BAD_PARAMETER);
398 break;
399 }
400 return (AE_OK);
401 }
402
403 ACPI_STATUS
404 AcpiOsReadMemory (
405 ACPI_PHYSICAL_ADDRESS Address,
406 UINT32 *Value,
407 UINT32 Width)
408 {
409 DPRINT("AcpiOsReadMemory %p\n", Address);
410 switch (Width)
411 {
412 case 8:
413 *Value = (*(PUCHAR)(ULONG)Address);
414 break;
415 case 16:
416 *Value = (*(PUSHORT)(ULONG)Address);
417 break;
418 case 32:
419 *Value = (*(PULONG)(ULONG)Address);
420 break;
421
422 default:
423 DPRINT1("AcpiOsReadMemory got bad width: %d\n",Width);
424 return (AE_BAD_PARAMETER);
425 break;
426 }
427 return (AE_OK);
428 }
429
430
431 ACPI_STATUS
432 AcpiOsWriteMemory (
433 ACPI_PHYSICAL_ADDRESS Address,
434 UINT32 Value,
435 UINT32 Width)
436 {
437 DPRINT("AcpiOsWriteMemory %p\n", Address);
438 switch (Width)
439 {
440 case 8:
441 *(PUCHAR)(ULONG)Address = Value;
442 break;
443 case 16:
444 *(PUSHORT)(ULONG)Address = Value;
445 break;
446 case 32:
447 *(PULONG)(ULONG)Address = Value;
448 break;
449
450 default:
451 DPRINT1("AcpiOsWriteMemory got bad width: %d\n",Width);
452 return (AE_BAD_PARAMETER);
453 break;
454 }
455
456 return (AE_OK);
457 }
458
459 ACPI_STATUS
460 AcpiOsReadPciConfiguration (
461 ACPI_PCI_ID *PciId,
462 UINT32 Register,
463 void *Value,
464 UINT32 Width)
465 {
466 NTSTATUS Status;
467 PCI_SLOT_NUMBER slot;
468
469 if (Register == 0 || PciId->Device == 0)
470 return AE_ERROR;
471
472 slot.u.AsULONG = 0;
473 slot.u.bits.DeviceNumber = PciId->Device;
474 slot.u.bits.FunctionNumber = PciId->Function;
475
476 DPRINT("AcpiOsReadPciConfiguration, slot=0x%X, func=0x%X\n", slot.u.AsULONG, Register);
477 Status = HalGetBusDataByOffset(PCIConfiguration,
478 PciId->Bus,
479 slot.u.AsULONG,
480 Value,
481 Register,
482 Width);
483
484 if (NT_SUCCESS(Status))
485 return AE_OK;
486 else
487 return AE_ERROR;
488 }
489
490 ACPI_STATUS
491 AcpiOsWritePciConfiguration (
492 ACPI_PCI_ID *PciId,
493 UINT32 Register,
494 ACPI_INTEGER Value,
495 UINT32 Width)
496 {
497 NTSTATUS Status;
498 ULONG buf = Value;
499 PCI_SLOT_NUMBER slot;
500
501 if (Register == 0 || PciId->Device == 0)
502 return AE_ERROR;
503
504 slot.u.AsULONG = 0;
505 slot.u.bits.DeviceNumber = PciId->Device;
506 slot.u.bits.FunctionNumber = PciId->Function;
507
508 DPRINT("AcpiOsWritePciConfiguration, slot=0x%x\n", slot.u.AsULONG);
509 Status = HalSetBusDataByOffset(PCIConfiguration,
510 PciId->Bus,
511 slot.u.AsULONG,
512 &buf,
513 Register,
514 Width);
515
516 if (NT_SUCCESS(Status))
517 return AE_OK;
518 else
519 return AE_ERROR;
520 }
521
522 ACPI_STATUS
523 AcpiOsCreateSemaphore (
524 UINT32 MaxUnits,
525 UINT32 InitialUnits,
526 ACPI_SEMAPHORE *OutHandle)
527 {
528 PFAST_MUTEX Mutex;
529
530 Mutex = ExAllocatePool(NonPagedPool, sizeof(FAST_MUTEX));
531 if (!Mutex)
532 return AE_NO_MEMORY;
533
534 DPRINT("AcpiOsCreateSemaphore() at 0x%X\n", Mutex);
535
536 ExInitializeFastMutex(Mutex);
537
538 *OutHandle = Mutex;
539 return AE_OK;
540 }
541
542 ACPI_STATUS
543 AcpiOsDeleteSemaphore (
544 ACPI_SEMAPHORE Handle)
545 {
546 PFAST_MUTEX Mutex = (PFAST_MUTEX)Handle;
547
548 DPRINT("AcpiOsDeleteSemaphore(handle 0x%X)\n", Handle);
549
550 if (!Mutex)
551 return AE_BAD_PARAMETER;
552
553 ExFreePool(Mutex);
554 return AE_OK;
555 }
556
557 ACPI_STATUS
558 AcpiOsWaitSemaphore(
559 ACPI_SEMAPHORE Handle,
560 UINT32 units,
561 UINT16 timeout)
562 {
563 PFAST_MUTEX Mutex = (PFAST_MUTEX)Handle;
564
565 if (!Mutex || (units < 1))
566 {
567 DPRINT("AcpiOsWaitSemaphore(handle 0x%X, units %d) Bad parameters\n",
568 Mutex, units);
569 return AE_BAD_PARAMETER;
570 }
571
572 DPRINT("Waiting for semaphore %p\n", Handle);
573 ASSERT(Mutex);
574
575 ExAcquireFastMutex(Mutex);
576 return AE_OK;
577 }
578
579 ACPI_STATUS
580 AcpiOsSignalSemaphore (
581 ACPI_HANDLE Handle,
582 UINT32 Units)
583 {
584 PFAST_MUTEX Mutex = (PFAST_MUTEX)Handle;
585
586 DPRINT("AcpiOsSignalSemaphore %p\n",Handle);
587 ASSERT(Mutex);
588
589 ExReleaseFastMutex(Mutex);
590 return AE_OK;
591 }
592
593 ACPI_STATUS
594 AcpiOsCreateLock (
595 ACPI_SPINLOCK *OutHandle)
596 {
597 DPRINT("AcpiOsCreateLock\n");
598 return (AcpiOsCreateSemaphore (1, 1, OutHandle));
599 }
600
601 void
602 AcpiOsDeleteLock (
603 ACPI_SPINLOCK Handle)
604 {
605 DPRINT("AcpiOsDeleteLock %p\n", Handle);
606 AcpiOsDeleteSemaphore (Handle);
607 }
608
609
610 ACPI_CPU_FLAGS
611 AcpiOsAcquireLock (
612 ACPI_HANDLE Handle)
613 {
614 DPRINT("AcpiOsAcquireLock, %p\n", Handle);
615 AcpiOsWaitSemaphore (Handle, 1, 0xFFFF);
616 return (0);
617 }
618
619
620 void
621 AcpiOsReleaseLock (
622 ACPI_SPINLOCK Handle,
623 ACPI_CPU_FLAGS Flags)
624 {
625 DPRINT("AcpiOsReleaseLock %p\n",Handle);
626 AcpiOsSignalSemaphore (Handle, 1);
627 }
628
629 ACPI_STATUS
630 AcpiOsSignal (
631 UINT32 Function,
632 void *Info)
633 {
634
635 switch (Function)
636 {
637 case ACPI_SIGNAL_FATAL:
638 if (Info)
639 AcpiOsPrintf ("AcpiOsBreakpoint: %s ****\n", Info);
640 else
641 AcpiOsPrintf ("AcpiOsBreakpoint ****\n");
642 break;
643 case ACPI_SIGNAL_BREAKPOINT:
644 if (Info)
645 AcpiOsPrintf ("AcpiOsBreakpoint: %s ****\n", Info);
646 else
647 AcpiOsPrintf ("AcpiOsBreakpoint ****\n");
648 break;
649 }
650
651 return (AE_OK);
652 }
653
654
655 ACPI_THREAD_ID
656 AcpiOsGetThreadId (void)
657 {
658 return (ULONG)PsGetCurrentThreadId();
659 }
660
661 ACPI_STATUS
662 AcpiOsExecute (
663 ACPI_EXECUTE_TYPE Type,
664 ACPI_OSD_EXEC_CALLBACK Function,
665 void *Context)
666 {
667 DPRINT("AcpiOsExecute\n");
668
669 KeInsertQueueDpc(&AcpiDpc, (PVOID)Function, (PVOID)Context);
670
671 #ifdef _MULTI_THREADED
672 //_beginthread (Function, (unsigned) 0, Context);
673 #endif
674
675 return 0;
676 }
677
678 UINT64
679 AcpiOsGetTimer (void)
680 {
681 DPRINT("AcpiOsGetTimer\n");
682 LARGE_INTEGER Timer;
683 KeQueryTickCount(&Timer);
684
685 return Timer.QuadPart;
686 }
687
688 void
689 AcpiOsDerivePciId(
690 ACPI_HANDLE rhandle,
691 ACPI_HANDLE chandle,
692 ACPI_PCI_ID **PciId)
693 {
694 DPRINT("AcpiOsDerivePciId\n");
695 return;
696 }
697
698 ACPI_STATUS
699 AcpiOsPredefinedOverride (
700 const ACPI_PREDEFINED_NAMES *InitVal,
701 ACPI_STRING *NewVal)
702 {
703 if (!InitVal || !NewVal)
704 return AE_BAD_PARAMETER;
705
706 *NewVal = ACPI_OS_NAME;
707 DPRINT("AcpiOsPredefinedOverride\n");
708 return AE_OK;
709 }
710
711 ACPI_PHYSICAL_ADDRESS
712 AcpiOsGetRootPointer (
713 void);
714
715 ACPI_STATUS
716 AcpiOsTableOverride (
717 ACPI_TABLE_HEADER *ExistingTable,
718 ACPI_TABLE_HEADER **NewTable)
719 {
720 DPRINT("AcpiOsTableOverride\n");
721 *NewTable = NULL;
722 return (AE_OK);
723 }
724
725 ACPI_STATUS
726 AcpiOsValidateInterface (
727 char *Interface)
728 {
729 DPRINT("AcpiOsValidateInterface\n");
730 return (AE_OK);
731 }
732
733 ACPI_STATUS
734 AcpiOsValidateAddress (
735 UINT8 SpaceId,
736 ACPI_PHYSICAL_ADDRESS Address,
737 ACPI_SIZE Length)
738 {
739 DPRINT("AcpiOsValidateAddress\n");
740 return (AE_OK);
741 }
742
743 ACPI_PHYSICAL_ADDRESS
744 AcpiOsGetRootPointer (
745 void)
746 {
747 DPRINT("AcpiOsGetRootPointer\n");
748 ACPI_PHYSICAL_ADDRESS pa = 0;
749
750 AcpiFindRootPointer(&pa);
751 return pa;
752 }