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