- Check that the memory location that we are trying to read is valid
[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 Register + Width > PCI_COMMON_HDR_LENGTH)
471 return AE_ERROR;
472
473 slot.u.AsULONG = 0;
474 slot.u.bits.DeviceNumber = PciId->Device;
475 slot.u.bits.FunctionNumber = PciId->Function;
476
477 DPRINT("AcpiOsReadPciConfiguration, slot=0x%X, func=0x%X\n", slot.u.AsULONG, Register);
478 Status = HalGetBusDataByOffset(PCIConfiguration,
479 PciId->Bus,
480 slot.u.AsULONG,
481 Value,
482 Register,
483 Width);
484
485 if (NT_SUCCESS(Status))
486 return AE_OK;
487 else
488 return AE_ERROR;
489 }
490
491 ACPI_STATUS
492 AcpiOsWritePciConfiguration (
493 ACPI_PCI_ID *PciId,
494 UINT32 Register,
495 ACPI_INTEGER Value,
496 UINT32 Width)
497 {
498 NTSTATUS Status;
499 ULONG buf = Value;
500 PCI_SLOT_NUMBER slot;
501
502 if (Register == 0 || PciId->Device == 0 ||
503 Register + Width > PCI_COMMON_HDR_LENGTH)
504 return AE_ERROR;
505
506 slot.u.AsULONG = 0;
507 slot.u.bits.DeviceNumber = PciId->Device;
508 slot.u.bits.FunctionNumber = PciId->Function;
509
510 DPRINT("AcpiOsWritePciConfiguration, slot=0x%x\n", slot.u.AsULONG);
511 Status = HalSetBusDataByOffset(PCIConfiguration,
512 PciId->Bus,
513 slot.u.AsULONG,
514 &buf,
515 Register,
516 Width);
517
518 if (NT_SUCCESS(Status))
519 return AE_OK;
520 else
521 return AE_ERROR;
522 }
523
524 ACPI_STATUS
525 AcpiOsCreateSemaphore (
526 UINT32 MaxUnits,
527 UINT32 InitialUnits,
528 ACPI_SEMAPHORE *OutHandle)
529 {
530 PFAST_MUTEX Mutex;
531
532 Mutex = ExAllocatePool(NonPagedPool, sizeof(FAST_MUTEX));
533 if (!Mutex)
534 return AE_NO_MEMORY;
535
536 DPRINT("AcpiOsCreateSemaphore() at 0x%X\n", Mutex);
537
538 ExInitializeFastMutex(Mutex);
539
540 *OutHandle = Mutex;
541 return AE_OK;
542 }
543
544 ACPI_STATUS
545 AcpiOsDeleteSemaphore (
546 ACPI_SEMAPHORE Handle)
547 {
548 PFAST_MUTEX Mutex = (PFAST_MUTEX)Handle;
549
550 DPRINT("AcpiOsDeleteSemaphore(handle 0x%X)\n", Handle);
551
552 if (!Mutex)
553 return AE_BAD_PARAMETER;
554
555 ExFreePool(Mutex);
556 return AE_OK;
557 }
558
559 ACPI_STATUS
560 AcpiOsWaitSemaphore(
561 ACPI_SEMAPHORE Handle,
562 UINT32 units,
563 UINT16 timeout)
564 {
565 PFAST_MUTEX Mutex = (PFAST_MUTEX)Handle;
566
567 if (!Mutex || (units < 1))
568 {
569 DPRINT("AcpiOsWaitSemaphore(handle 0x%X, units %d) Bad parameters\n",
570 Mutex, units);
571 return AE_BAD_PARAMETER;
572 }
573
574 DPRINT("Waiting for semaphore %p\n", Handle);
575 ASSERT(Mutex);
576
577 ExAcquireFastMutex(Mutex);
578 return AE_OK;
579 }
580
581 ACPI_STATUS
582 AcpiOsSignalSemaphore (
583 ACPI_HANDLE Handle,
584 UINT32 Units)
585 {
586 PFAST_MUTEX Mutex = (PFAST_MUTEX)Handle;
587
588 DPRINT("AcpiOsSignalSemaphore %p\n",Handle);
589 ASSERT(Mutex);
590
591 ExReleaseFastMutex(Mutex);
592 return AE_OK;
593 }
594
595 ACPI_STATUS
596 AcpiOsCreateLock (
597 ACPI_SPINLOCK *OutHandle)
598 {
599 DPRINT("AcpiOsCreateLock\n");
600 return (AcpiOsCreateSemaphore (1, 1, OutHandle));
601 }
602
603 void
604 AcpiOsDeleteLock (
605 ACPI_SPINLOCK Handle)
606 {
607 DPRINT("AcpiOsDeleteLock %p\n", Handle);
608 AcpiOsDeleteSemaphore (Handle);
609 }
610
611
612 ACPI_CPU_FLAGS
613 AcpiOsAcquireLock (
614 ACPI_HANDLE Handle)
615 {
616 DPRINT("AcpiOsAcquireLock, %p\n", Handle);
617 AcpiOsWaitSemaphore (Handle, 1, 0xFFFF);
618 return (0);
619 }
620
621
622 void
623 AcpiOsReleaseLock (
624 ACPI_SPINLOCK Handle,
625 ACPI_CPU_FLAGS Flags)
626 {
627 DPRINT("AcpiOsReleaseLock %p\n",Handle);
628 AcpiOsSignalSemaphore (Handle, 1);
629 }
630
631 ACPI_STATUS
632 AcpiOsSignal (
633 UINT32 Function,
634 void *Info)
635 {
636
637 switch (Function)
638 {
639 case ACPI_SIGNAL_FATAL:
640 if (Info)
641 AcpiOsPrintf ("AcpiOsBreakpoint: %s ****\n", Info);
642 else
643 AcpiOsPrintf ("AcpiOsBreakpoint ****\n");
644 break;
645 case ACPI_SIGNAL_BREAKPOINT:
646 if (Info)
647 AcpiOsPrintf ("AcpiOsBreakpoint: %s ****\n", Info);
648 else
649 AcpiOsPrintf ("AcpiOsBreakpoint ****\n");
650 break;
651 }
652
653 return (AE_OK);
654 }
655
656
657 ACPI_THREAD_ID
658 AcpiOsGetThreadId (void)
659 {
660 return (ULONG)PsGetCurrentThreadId();
661 }
662
663 ACPI_STATUS
664 AcpiOsExecute (
665 ACPI_EXECUTE_TYPE Type,
666 ACPI_OSD_EXEC_CALLBACK Function,
667 void *Context)
668 {
669 DPRINT("AcpiOsExecute\n");
670
671 KeInsertQueueDpc(&AcpiDpc, (PVOID)Function, (PVOID)Context);
672
673 #ifdef _MULTI_THREADED
674 //_beginthread (Function, (unsigned) 0, Context);
675 #endif
676
677 return 0;
678 }
679
680 UINT64
681 AcpiOsGetTimer (void)
682 {
683 DPRINT("AcpiOsGetTimer\n");
684 LARGE_INTEGER Timer;
685 KeQueryTickCount(&Timer);
686
687 return Timer.QuadPart;
688 }
689
690 void
691 AcpiOsDerivePciId(
692 ACPI_HANDLE rhandle,
693 ACPI_HANDLE chandle,
694 ACPI_PCI_ID **PciId)
695 {
696 DPRINT("AcpiOsDerivePciId\n");
697 return;
698 }
699
700 ACPI_STATUS
701 AcpiOsPredefinedOverride (
702 const ACPI_PREDEFINED_NAMES *InitVal,
703 ACPI_STRING *NewVal)
704 {
705 if (!InitVal || !NewVal)
706 return AE_BAD_PARAMETER;
707
708 *NewVal = ACPI_OS_NAME;
709 DPRINT("AcpiOsPredefinedOverride\n");
710 return AE_OK;
711 }
712
713 ACPI_PHYSICAL_ADDRESS
714 AcpiOsGetRootPointer (
715 void);
716
717 ACPI_STATUS
718 AcpiOsTableOverride (
719 ACPI_TABLE_HEADER *ExistingTable,
720 ACPI_TABLE_HEADER **NewTable)
721 {
722 DPRINT("AcpiOsTableOverride\n");
723 *NewTable = NULL;
724 return (AE_OK);
725 }
726
727 ACPI_STATUS
728 AcpiOsValidateInterface (
729 char *Interface)
730 {
731 DPRINT("AcpiOsValidateInterface\n");
732 return (AE_OK);
733 }
734
735 ACPI_STATUS
736 AcpiOsValidateAddress (
737 UINT8 SpaceId,
738 ACPI_PHYSICAL_ADDRESS Address,
739 ACPI_SIZE Length)
740 {
741 DPRINT("AcpiOsValidateAddress\n");
742 return (AE_OK);
743 }
744
745 ACPI_PHYSICAL_ADDRESS
746 AcpiOsGetRootPointer (
747 void)
748 {
749 DPRINT("AcpiOsGetRootPointer\n");
750 ACPI_PHYSICAL_ADDRESS pa = 0;
751
752 AcpiFindRootPointer(&pa);
753 return pa;
754 }