xref: /haiku/src/add-ons/kernel/bus_managers/acpi/ACPICAHaiku.cpp (revision 7a74a5df454197933bc6e80a542102362ee98703)
1 /******************************************************************************
2  *
3  * Module Name: oshaiku - Haiku OSL interfaces
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights.  You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code.  No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision.  In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change.  Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee.  Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution.  In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government.  In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115 
116 
117 #include <stdio.h>
118 #include <sys/cdefs.h>
119 #include <time.h>
120 #include <unistd.h>
121 
122 #include <OS.h>
123 
124 #ifdef _KERNEL_MODE
125 #	include <KernelExport.h>
126 
127 #	include <dpc.h>
128 #	include <PCI.h>
129 
130 #	include <kernel.h>
131 #	include <vm/vm.h>
132 #endif
133 
134 __BEGIN_DECLS
135 #include "acpi.h"
136 #include "accommon.h"
137 #include "amlcode.h"
138 #include "acparser.h"
139 #include "acdebug.h"
140 __END_DECLS
141 
142 
143 ACPI_MODULE_NAME("Haiku ACPI Module")
144 
145 #define _COMPONENT ACPI_OS_SERVICES
146 
147 // verbosity level 0 = off, 1 = normal, 2 = all
148 #define DEBUG_OSHAIKU 0
149 
150 #if DEBUG_OSHAIKU <= 0
151 // No debugging, do nothing
152 #	define DEBUG_FUNCTION()
153 #	define DEBUG_FUNCTION_F(x, y...)
154 #	define DEBUG_FUNCTION_V()
155 #	define DEBUG_FUNCTION_VF(x, y...)
156 #else
157 #	define DEBUG_FUNCTION() \
158 		dprintf("acpi[%ld]: %s\n", find_thread(NULL), __PRETTY_FUNCTION__);
159 #	define DEBUG_FUNCTION_F(x, y...) \
160 		dprintf("acpi[%ld]: %s(" x ")\n", find_thread(NULL), __PRETTY_FUNCTION__, y);
161 #	if DEBUG_OSHAIKU == 1
162 // No verbose debugging, do nothing
163 #		define DEBUG_FUNCTION_V()
164 #		define DEBUG_FUNCTION_VF(x, y...)
165 #	else
166 // Full debugging
167 #		define DEBUG_FUNCTION_V() \
168 			dprintf("acpi[%ld]: %s\n", find_thread(NULL), __PRETTY_FUNCTION__);
169 #		define DEBUG_FUNCTION_VF(x, y...) \
170 			dprintf("acpi[%ld]: %s(" x ")\n", find_thread(NULL), __PRETTY_FUNCTION__, y);
171 #	endif
172 #endif
173 
174 
175 #ifdef _KERNEL_MODE
176 extern pci_module_info *gPCIManager;
177 extern dpc_module_info *gDPC;
178 extern void *gDPCHandle;
179 #endif
180 
181 extern FILE *AcpiGbl_DebugFile;
182 FILE *AcpiGbl_OutputFile;
183 
184 static uint32 sACPIRoot = 0;
185 static void *sInterruptHandlerData[32];
186 
187 
188 /******************************************************************************
189  *
190  * FUNCTION:    AcpiOsInitialize, AcpiOsTerminate
191  *
192  * PARAMETERS:  None
193  *
194  * RETURN:      Status
195  *
196  * DESCRIPTION: Init and terminate.  Nothing to do.
197  *
198  *****************************************************************************/
199 ACPI_STATUS
200 AcpiOsInitialize()
201 {
202 #ifndef _KERNEL_MODE
203 	AcpiGbl_OutputFile = stdout;
204 #else
205 	AcpiGbl_OutputFile = NULL;
206 #endif
207 	DEBUG_FUNCTION();
208 	return AE_OK;
209 }
210 
211 
212 ACPI_STATUS
213 AcpiOsTerminate()
214 {
215 	DEBUG_FUNCTION();
216 	return AE_OK;
217 }
218 
219 
220 /******************************************************************************
221  *
222  * FUNCTION:    AcpiOsGetRootPointer
223  *
224  * PARAMETERS:  None
225  *
226  * RETURN:      RSDP physical address
227  *
228  * DESCRIPTION: Gets the root pointer (RSDP)
229  *
230  *****************************************************************************/
231 ACPI_PHYSICAL_ADDRESS
232 AcpiOsGetRootPointer()
233 {
234 #ifdef _KERNEL_MODE
235 	ACPI_SIZE address;
236 	ACPI_STATUS status;
237 	DEBUG_FUNCTION();
238 	if (sACPIRoot == 0) {
239 		status = AcpiFindRootPointer(&address);
240 		if (status == AE_OK)
241 			sACPIRoot = address;
242 	}
243 	return sACPIRoot;
244 #else
245 	return AeLocalGetRootPointer();
246 #endif
247 }
248 
249 
250 /******************************************************************************
251  *
252  * FUNCTION:    AcpiOsPredefinedOverride
253  *
254  * PARAMETERS:  initVal     - Initial value of the predefined object
255  *              newVal      - The new value for the object
256  *
257  * RETURN:      Status, pointer to value.  Null pointer returned if not
258  *              overriding.
259  *
260  * DESCRIPTION: Allow the OS to override predefined names
261  *
262  *****************************************************************************/
263 ACPI_STATUS
264 AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *initVal,
265 		ACPI_STRING *newVal)
266 {
267 	DEBUG_FUNCTION();
268 	if (!initVal || !newVal)
269 		return AE_BAD_PARAMETER;
270 
271 	*newVal = NULL;
272 	return AE_OK;
273 }
274 
275 
276 /******************************************************************************
277  *
278  * FUNCTION:    AcpiOsTableOverride
279  *
280  * PARAMETERS:  existingTable   - Header of current table (probably firmware)
281  *              newTable        - Where an entire new table is returned.
282  *
283  * RETURN:      Status, pointer to new table.  Null pointer returned if no
284  *              table is available to override
285  *
286  * DESCRIPTION: Return a different version of a table if one is available
287  *
288  *****************************************************************************/
289 ACPI_STATUS
290 AcpiOsTableOverride(ACPI_TABLE_HEADER *existingTable,
291 		ACPI_TABLE_HEADER **newTable)
292 {
293 	DEBUG_FUNCTION();
294 	if (!existingTable || !newTable)
295 		return AE_BAD_PARAMETER;
296 
297 	*newTable = NULL;
298 
299 #ifdef ACPI_EXEC_APP
300 	AeTableOverride(existingTable, newTable);
301 	return AE_OK;
302 #else
303 	return AE_NO_ACPI_TABLES;
304 #endif
305 }
306 
307 
308 /******************************************************************************
309  *
310  * FUNCTION:    AcpiOsPhysicalTableOverride
311  *
312  * PARAMETERS:  existingTable       - Header of current table (probably firmware)
313  *              newAddress          - Where new table address is returned
314  *                                    (Physical address)
315  *              newTableLength      - Where new table length is returned
316  *
317  * RETURN:      Status, address/length of new table. Null pointer returned
318  *              if no table is available to override.
319  *
320  * DESCRIPTION: Returns AE_SUPPORT, function not used in user space.
321  *
322  *****************************************************************************/
323 
324 ACPI_STATUS
325 AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *existingTable,
326 	ACPI_PHYSICAL_ADDRESS *newAddress, UINT32 *newTableLength)
327 {
328 	DEBUG_FUNCTION();
329     return (AE_SUPPORT);
330 }
331 
332 
333 /******************************************************************************
334  *
335  * FUNCTION:    AcpiOsRedirectOutput
336  *
337  * PARAMETERS:  destination         - An open file handle/pointer
338  *
339  * RETURN:      None
340  *
341  * DESCRIPTION: Causes redirect of AcpiOsPrintf and AcpiOsVprintf
342  *
343  *****************************************************************************/
344 void
345 AcpiOsRedirectOutput(void *destination)
346 {
347 	DEBUG_FUNCTION();
348 	AcpiGbl_OutputFile = (FILE*)destination;
349 }
350 
351 
352 /******************************************************************************
353  *
354  * FUNCTION:    AcpiOsPrintf
355  *
356  * PARAMETERS:  fmt, ...            Standard printf format
357  *
358  * RETURN:      None
359  *
360  * DESCRIPTION: Formatted output
361  *
362  *****************************************************************************/
363 void ACPI_INTERNAL_VAR_XFACE
364 AcpiOsPrintf(const char *fmt, ...)
365 {
366 	va_list args;
367 
368 	DEBUG_FUNCTION();
369 	va_start(args, fmt);
370 	AcpiOsVprintf(fmt, args);
371 	va_end(args);
372 }
373 
374 
375 /******************************************************************************
376  *
377  * FUNCTION:    AcpiOsVprintf
378  *
379  * PARAMETERS:  fmt                 Standard printf format
380  *              args                Argument list
381  *
382  * RETURN:      None
383  *
384  * DESCRIPTION: Formatted output with argument list pointer
385  *
386  *****************************************************************************/
387 void
388 AcpiOsVprintf(const char *fmt, va_list args)
389 {
390 #ifndef _KERNEL_MODE
391 	UINT8 flags;
392 
393 	flags = AcpiGbl_DbOutputFlags;
394 	if (flags & ACPI_DB_REDIRECTABLE_OUTPUT) {
395 		// Output is directable to either a file (if open) or the console
396 		if (AcpiGbl_DebugFile) {
397 			// Output file is open, send the output there
398 			vfprintf(AcpiGbl_DebugFile, fmt, args);
399 		} else {
400 			// No redirection, send output to console (once only!)
401 			flags |= ACPI_DB_CONSOLE_OUTPUT;
402 		}
403 	}
404 
405 	if (flags & ACPI_DB_CONSOLE_OUTPUT) {
406 		vfprintf(AcpiGbl_OutputFile, fmt, args);
407     }
408 #else
409 	static char outputBuffer[1024];
410 	vsnprintf(outputBuffer, 1024, fmt, args);
411 	dprintf("%s", outputBuffer);
412 #endif
413 }
414 
415 
416 /******************************************************************************
417  *
418  * FUNCTION:    AcpiOsGetLine
419  *
420  * PARAMETERS:  fmt                 Standard printf format
421  *              args                Argument list
422  *
423  * RETURN:      Actual bytes read
424  *
425  * DESCRIPTION: Formatted input with argument list pointer
426  *
427  *****************************************************************************/
428 UINT32
429 AcpiOsGetLine(char *buffer)
430 {
431 	uint32 i = 0;
432 
433 #ifndef _KERNEL_MODE
434 	uint8 temp;
435 
436 	for (i = 0; ; i++) {
437 		scanf("%1c", &temp);
438 		if (!temp || temp == '\n')
439 			break;
440 
441 		buffer[i] = temp;
442 	}
443 #endif
444 
445 	buffer[i] = 0;
446 	DEBUG_FUNCTION_F("buffer: \"%s\"; result: %lu", buffer, i);
447 	return i;
448 }
449 
450 
451 /******************************************************************************
452  *
453  * FUNCTION:    AcpiOsMapMemory
454  *
455  * PARAMETERS:  where               Physical address of memory to be mapped
456  *              length              How much memory to map
457  *
458  * RETURN:      Pointer to mapped memory.  Null on error.
459  *
460  * DESCRIPTION: Map physical memory into caller's address space
461  *
462  *****************************************************************************/
463 void *
464 AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS where, ACPI_SIZE length)
465 {
466 #ifdef _KERNEL_MODE
467 	void *there;
468 	area_id area = map_physical_memory("acpi_physical_mem_area", where, length,
469 		B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, &there);
470 
471 	DEBUG_FUNCTION_F("addr: 0x%08lx; length: %lu; mapped: %p; area: %ld",
472 		(addr_t)where, (size_t)length, there, area);
473 	if (area < 0) {
474 		dprintf("ACPI: cannot map memory at 0x%08x, length %d\n", where, length);
475 		return NULL;
476 	}
477 	return there;
478 #else
479 	return NULL;
480 #endif
481 
482 	// return ACPI_TO_POINTER((ACPI_SIZE) where);
483 }
484 
485 
486 /******************************************************************************
487  *
488  * FUNCTION:    AcpiOsUnmapMemory
489  *
490  * PARAMETERS:  where               Logical address of memory to be unmapped
491  *              length              How much memory to unmap
492  *
493  * RETURN:      None.
494  *
495  * DESCRIPTION: Delete a previously created mapping.  Where and Length must
496  *              correspond to a previous mapping exactly.
497  *
498  *****************************************************************************/
499 void
500 AcpiOsUnmapMemory(void *where, ACPI_SIZE length)
501 {
502 	DEBUG_FUNCTION_F("mapped: %p; length: %lu", where, (size_t)length);
503 	delete_area(area_for(where));
504 }
505 
506 
507 /******************************************************************************
508  *
509  * FUNCTION:    AcpiOsAllocate
510  *
511  * PARAMETERS:  size                Amount to allocate, in bytes
512  *
513  * RETURN:      Pointer to the new allocation.  Null on error.
514  *
515  * DESCRIPTION: Allocate memory.  Algorithm is dependent on the OS.
516  *
517  *****************************************************************************/
518 void *
519 AcpiOsAllocate(ACPI_SIZE size)
520 {
521 	void *mem = (void *) malloc(size);
522 	DEBUG_FUNCTION_VF("result: %p", mem);
523 	return mem;
524 }
525 
526 
527 /******************************************************************************
528  *
529  * FUNCTION:    AcpiOsFree
530  *
531  * PARAMETERS:  mem                 Pointer to previously allocated memory
532  *
533  * RETURN:      None.
534  *
535  * DESCRIPTION: Free memory allocated via AcpiOsAllocate
536  *
537  *****************************************************************************/
538 void
539 AcpiOsFree(void *mem)
540 {
541 	DEBUG_FUNCTION_VF("mem: %p", mem);
542 	free(mem);
543 }
544 
545 
546 /******************************************************************************
547  *
548  * FUNCTION:    AcpiOsCreateSemaphore
549  *
550  * PARAMETERS:  initialUnits        - Units to be assigned to the new semaphore
551  *              outHandle           - Where a handle will be returned
552  *
553  * RETURN:      Status
554  *
555  * DESCRIPTION: Create an OS semaphore
556  *
557  *****************************************************************************/
558 ACPI_STATUS
559 AcpiOsCreateSemaphore(UINT32 maxUnits, UINT32 initialUnits,
560 		ACPI_SEMAPHORE *outHandle)
561 {
562 	if (!outHandle)
563     	return AE_BAD_PARAMETER;
564 
565 	*outHandle = create_sem(initialUnits, "acpi_sem");
566 	DEBUG_FUNCTION_F("max: %lu; count: %lu; result: %ld",
567 		maxUnits, initialUnits, *outHandle);
568 
569 	if (*outHandle >= B_OK)
570 		return AE_OK;
571 
572 	return *outHandle == B_BAD_VALUE ? AE_BAD_PARAMETER : AE_NO_MEMORY;
573 }
574 
575 
576 /******************************************************************************
577  *
578  * FUNCTION:    AcpiOsDeleteSemaphore
579  *
580  * PARAMETERS:  handle              - Handle returned by AcpiOsCreateSemaphore
581  *
582  * RETURN:      Status
583  *
584  * DESCRIPTION: Delete an OS semaphore
585  *
586  *****************************************************************************/
587 ACPI_STATUS
588 AcpiOsDeleteSemaphore(ACPI_SEMAPHORE handle)
589 {
590 	DEBUG_FUNCTION_F("sem: %ld", handle);
591 	return delete_sem(handle) == B_OK ? AE_OK : AE_BAD_PARAMETER;
592 }
593 
594 
595 /******************************************************************************
596  *
597  * FUNCTION:    AcpiOsWaitSemaphore
598  *
599  * PARAMETERS:  handle              - Handle returned by AcpiOsCreateSemaphore
600  *              units               - How many units to wait for
601  *              timeout             - How long to wait
602  *
603  * RETURN:      Status
604  *
605  * DESCRIPTION: Wait for units
606  *
607  *****************************************************************************/
608 ACPI_STATUS
609 AcpiOsWaitSemaphore(ACPI_SEMAPHORE handle, UINT32 units, UINT16 timeout)
610 {
611 	ACPI_STATUS result = AE_OK;
612 	DEBUG_FUNCTION_VF("sem: %ld; count: %lu; timeout: %u",
613 		handle, units, timeout);
614 
615 	if (timeout == ACPI_WAIT_FOREVER) {
616 		result = acquire_sem_etc(handle, units, 0, 0)
617 			== B_OK ? AE_OK : AE_BAD_PARAMETER;
618 	} else {
619 		switch (acquire_sem_etc(handle, units, B_RELATIVE_TIMEOUT,
620 			(bigtime_t)timeout * 1000)) {
621 			case B_OK:
622 				result = AE_OK;
623 				break;
624 			case B_INTERRUPTED:
625 			case B_TIMED_OUT:
626 			case B_WOULD_BLOCK:
627 				result = AE_TIME;
628 				break;
629 			case B_BAD_VALUE:
630 			default:
631 				result = AE_BAD_PARAMETER;
632 				break;
633 		}
634 	}
635 	DEBUG_FUNCTION_VF("sem: %ld; count: %lu; timeout: %u result: %lu",
636 		handle, units, timeout, (uint32)result);
637 	return result;
638 }
639 
640 
641 /******************************************************************************
642  *
643  * FUNCTION:    AcpiOsSignalSemaphore
644  *
645  * PARAMETERS:  handle              - Handle returned by AcpiOsCreateSemaphore
646  *              units               - Number of units to send
647  *
648  * RETURN:      Status
649  *
650  * DESCRIPTION: Send units
651  *
652  *****************************************************************************/
653 ACPI_STATUS
654 AcpiOsSignalSemaphore(ACPI_SEMAPHORE handle, UINT32 units)
655 {
656 	status_t result;
657 	DEBUG_FUNCTION_VF("sem: %ld; count: %lu", handle, units);
658 	// We can be called from interrupt handler, so don't reschedule
659 	result = release_sem_etc(handle, units, B_DO_NOT_RESCHEDULE);
660 	return result == B_OK ? AE_OK : AE_BAD_PARAMETER;
661 }
662 
663 
664 /******************************************************************************
665  *
666  * FUNCTION:    Spinlock interfaces
667  *
668  * DESCRIPTION: Map these interfaces to semaphore interfaces
669  *
670  *****************************************************************************/
671 ACPI_STATUS
672 AcpiOsCreateLock(ACPI_SPINLOCK *outHandle)
673 {
674 	*outHandle = (ACPI_SPINLOCK) malloc(sizeof(spinlock));
675 	DEBUG_FUNCTION_F("result: %p", *outHandle);
676 	if (*outHandle == NULL)
677 		return AE_NO_MEMORY;
678 
679 	**outHandle = B_SPINLOCK_INITIALIZER;
680 	return AE_OK;
681 }
682 
683 
684 void
685 AcpiOsDeleteLock(ACPI_SPINLOCK handle)
686 {
687 	DEBUG_FUNCTION();
688 	free((void*)handle);
689 }
690 
691 
692 ACPI_CPU_FLAGS
693 AcpiOsAcquireLock(ACPI_SPINLOCK handle)
694 {
695 	cpu_status cpu;
696 	DEBUG_FUNCTION_F("spinlock: %p", handle);
697 	cpu = disable_interrupts();
698 	acquire_spinlock(handle);
699 	return cpu;
700 }
701 
702 
703 void
704 AcpiOsReleaseLock(ACPI_SPINLOCK handle, ACPI_CPU_FLAGS flags)
705 {
706 	release_spinlock(handle);
707 	restore_interrupts(flags);
708 	DEBUG_FUNCTION_F("spinlock: %p", handle);
709 }
710 
711 
712 /******************************************************************************
713  *
714  * FUNCTION:    AcpiOsInstallInterruptHandler
715  *
716  * PARAMETERS:  interruptNumber     Level handler should respond to.
717  *              Isr                 Address of the ACPI interrupt handler
718  *              ExceptPtr           Where status is returned
719  *
720  * RETURN:      Handle to the newly installed handler.
721  *
722  * DESCRIPTION: Install an interrupt handler.  Used to install the ACPI
723  *              OS-independent handler.
724  *
725  *****************************************************************************/
726 UINT32
727 AcpiOsInstallInterruptHandler(UINT32 interruptNumber,
728 		ACPI_OSD_HANDLER serviceRoutine, void *context)
729 {
730 	status_t result;
731 	DEBUG_FUNCTION_F("vector: %lu; handler: %p context %p",
732 		interruptNumber, serviceRoutine, context);
733 
734 #ifdef _KERNEL_MODE
735 	// It so happens that the Haiku and ACPI-CA interrupt handler routines
736 	// return the same values with the same meanings
737 	sInterruptHandlerData[interruptNumber] = context;
738 	result = install_io_interrupt_handler(interruptNumber,
739 		(interrupt_handler)serviceRoutine, context, 0);
740 
741 	DEBUG_FUNCTION_F("vector: %lu; handler: %p context %p returned %d",
742 		interruptNumber, serviceRoutine, context, result);
743 
744 	return result == B_OK ? AE_OK : AE_BAD_PARAMETER;
745 #else
746 	return AE_BAD_PARAMETER;
747 #endif
748 }
749 
750 
751 /******************************************************************************
752  *
753  * FUNCTION:    AcpiOsRemoveInterruptHandler
754  *
755  * PARAMETERS:  Handle              Returned when handler was installed
756  *
757  * RETURN:      Status
758  *
759  * DESCRIPTION: Uninstalls an interrupt handler.
760  *
761  *****************************************************************************/
762 ACPI_STATUS
763 AcpiOsRemoveInterruptHandler(UINT32 interruptNumber,
764 		ACPI_OSD_HANDLER serviceRoutine)
765 {
766 	DEBUG_FUNCTION_F("vector: %lu; handler: %p", interruptNumber,
767 		serviceRoutine);
768 #ifdef _KERNEL_MODE
769 	remove_io_interrupt_handler(interruptNumber,
770 		(interrupt_handler) serviceRoutine,
771 		sInterruptHandlerData[interruptNumber]);
772 	return AE_OK;
773 #else
774 	return AE_ERROR;
775 #endif
776 }
777 
778 
779 /******************************************************************************
780  *
781  * FUNCTION:    AcpiOsExecute
782  *
783  * PARAMETERS:  type            - Type of execution
784  *              function        - Address of the function to execute
785  *              context         - Passed as a parameter to the function
786  *
787  * RETURN:      Status.
788  *
789  * DESCRIPTION: Execute a new thread
790  *
791  *****************************************************************************/
792 ACPI_STATUS
793 AcpiOsExecute(ACPI_EXECUTE_TYPE type, ACPI_OSD_EXEC_CALLBACK  function,
794 		void *context)
795 {
796 	DEBUG_FUNCTION();
797 /* TODO: Prioritize urgent?
798 	switch (type) {
799 		case OSL_GLOBAL_LOCK_HANDLER:
800 		case OSL_NOTIFY_HANDLER:
801 		case OSL_GPE_HANDLER:
802 		case OSL_DEBUGGER_THREAD:
803 		case OSL_EC_POLL_HANDLER:
804 		case OSL_EC_BURST_HANDLER:
805 			break;
806 	}
807 */
808 
809 	if (gDPC->queue_dpc(gDPCHandle, function, context) != B_OK) {
810 		DEBUG_FUNCTION_F("Serious failure in AcpiOsExecute! function: %p",
811 			function);
812 		return AE_BAD_PARAMETER;
813 	}
814 	return AE_OK;
815 }
816 
817 
818 /******************************************************************************
819  *
820  * FUNCTION:    AcpiOsStall
821  *
822  * PARAMETERS:  microseconds        To sleep
823  *
824  * RETURN:      Blocks until sleep is completed.
825  *
826  * DESCRIPTION: Sleep at microsecond granularity
827  *
828  *****************************************************************************/
829 void
830 AcpiOsStall(UINT32 microseconds)
831 {
832 	DEBUG_FUNCTION_F("microseconds: %lu", microseconds);
833 	if (microseconds)
834 		spin(microseconds);
835 }
836 
837 
838 /******************************************************************************
839  *
840  * FUNCTION:    AcpiOsSleep
841  *
842  * PARAMETERS:  milliseconds        To sleep
843  *
844  * RETURN:      Blocks until sleep is completed.
845  *
846  * DESCRIPTION: Sleep at millisecond granularity
847  *
848  *****************************************************************************/
849 void
850 AcpiOsSleep(ACPI_INTEGER milliseconds)
851 {
852 	DEBUG_FUNCTION_F("milliseconds: %lu", milliseconds);
853 	if (gKernelStartup)
854 		spin(milliseconds * 1000);
855 	else
856 		snooze(milliseconds * 1000);
857 }
858 
859 
860 /******************************************************************************
861  *
862  * FUNCTION:    AcpiOsGetTimer
863  *
864  * PARAMETERS:  None
865  *
866  * RETURN:      Current time in 100 nanosecond units
867  *
868  * DESCRIPTION: Get the current system time
869  *
870  *****************************************************************************/
871 UINT64
872 AcpiOsGetTimer()
873 {
874 	DEBUG_FUNCTION();
875 	return system_time() * 10;
876 }
877 
878 
879 /******************************************************************************
880  *
881  * FUNCTION:    AcpiOsReadPciConfiguration
882  *
883  * PARAMETERS:  pciId               Seg/Bus/Dev
884  *              reg                 Device Register
885  *              value               Buffer where value is placed
886  *              width               Number of bits
887  *
888  * RETURN:      Status
889  *
890  * DESCRIPTION: Read data from PCI configuration space
891  *
892  *****************************************************************************/
893 ACPI_STATUS
894 AcpiOsReadPciConfiguration(ACPI_PCI_ID *pciId, UINT32 reg, UINT64 *value,
895 		UINT32 width)
896 {
897 #ifdef _KERNEL_MODE
898 	DEBUG_FUNCTION();
899 
900 	switch (width) {
901 		case 8:
902 		case 16:
903 		case 32:
904 			*value = gPCIManager->read_pci_config(
905 				pciId->Bus, pciId->Device, pciId->Function, reg, width / 8);
906 			break;
907 		default:
908 			return AE_ERROR;
909 	}
910 	return AE_OK;
911 #else
912 	return AE_ERROR;
913 #endif
914 }
915 
916 
917 /******************************************************************************
918  *
919  * FUNCTION:    AcpiOsWritePciConfiguration
920  *
921  * PARAMETERS:  pciId               Seg/Bus/Dev
922  *              reg                 Device Register
923  *              value               Value to be written
924  *              width               Number of bits
925  *
926  * RETURN:      Status.
927  *
928  * DESCRIPTION: Write data to PCI configuration space
929  *
930  *****************************************************************************/
931 ACPI_STATUS
932 AcpiOsWritePciConfiguration(ACPI_PCI_ID *pciId, UINT32 reg,
933 		ACPI_INTEGER value, UINT32 width)
934 {
935 #ifdef _KERNEL_MODE
936 	DEBUG_FUNCTION();
937 	gPCIManager->write_pci_config(
938 		pciId->Bus, pciId->Device, pciId->Function, reg, width / 8, value);
939 	return AE_OK;
940 #else
941 	return AE_ERROR;
942 #endif
943 }
944 
945 
946 /******************************************************************************
947  *
948  * FUNCTION:    AcpiOsReadPort
949  *
950  * PARAMETERS:  address             Address of I/O port/register to read
951  *              Value               Where value is placed
952  *              width               Number of bits
953  *
954  * RETURN:      Value read from port
955  *
956  * DESCRIPTION: Read data from an I/O port or register
957  *
958  *****************************************************************************/
959 ACPI_STATUS
960 AcpiOsReadPort(ACPI_IO_ADDRESS address, UINT32 *value, UINT32 width)
961 {
962 #ifdef _KERNEL_MODE
963 	DEBUG_FUNCTION_F("addr: 0x%08lx; width: %lu", (addr_t)address, width);
964 	switch (width) {
965 		case 8:
966 			*value = gPCIManager->read_io_8(address);
967 			break;
968 
969 		case 16:
970 			*value = gPCIManager->read_io_16(address);
971 			break;
972 
973 		case 32:
974 			*value = gPCIManager->read_io_32(address);
975 			break;
976 
977 		default:
978 			return AE_ERROR;
979 	}
980 
981 	return AE_OK;
982 #else
983 	return AE_ERROR;
984 #endif
985 }
986 
987 
988 /******************************************************************************
989  *
990  * FUNCTION:    AcpiOsWritePort
991  *
992  * PARAMETERS:  address             Address of I/O port/register to write
993  *              value               Value to write
994  *              width               Number of bits
995  *
996  * RETURN:      None
997  *
998  * DESCRIPTION: Write data to an I/O port or register
999  *
1000  *****************************************************************************/
1001 ACPI_STATUS
1002 AcpiOsWritePort(ACPI_IO_ADDRESS address, UINT32 value, UINT32 width)
1003 {
1004 #ifdef _KERNEL_MODE
1005 	DEBUG_FUNCTION_F("addr: 0x%08lx; value: %lu; width: %lu",
1006 		(addr_t)address, value, width);
1007 	switch (width) {
1008 		case 8:
1009 			gPCIManager->write_io_8(address, value);
1010 			break;
1011 
1012 		case 16:
1013 			gPCIManager->write_io_16(address,value);
1014 			break;
1015 
1016 		case 32:
1017 			gPCIManager->write_io_32(address,value);
1018 			break;
1019 
1020 		default:
1021 			return AE_ERROR;
1022 	}
1023 
1024 	return AE_OK;
1025 #else
1026 	return AE_ERROR;
1027 #endif
1028 }
1029 
1030 
1031 /******************************************************************************
1032  *
1033  * FUNCTION:    AcpiOsReadMemory
1034  *
1035  * PARAMETERS:  address             Physical Memory Address to read
1036  *              value               Where value is placed
1037  *              width               Number of bits
1038  *
1039  * RETURN:      Value read from physical memory address
1040  *
1041  * DESCRIPTION: Read data from a physical memory address
1042  *
1043  *****************************************************************************/
1044 ACPI_STATUS
1045 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 *value, UINT32 width)
1046 {
1047 #ifdef _KERNEL_MODE
1048 	if (vm_memcpy_from_physical(value, (addr_t)address, width / 8, false)
1049 		!= B_OK) {
1050 		return AE_ERROR;
1051 	}
1052 	return AE_OK;
1053 #else
1054 	return AE_ERROR;
1055 #endif
1056 }
1057 
1058 
1059 /******************************************************************************
1060  *
1061  * FUNCTION:    AcpiOsWriteMemory
1062  *
1063  * PARAMETERS:  address             Physical Memory Address to write
1064  *              value               Value to write
1065  *              width               Number of bits
1066  *
1067  * RETURN:      None
1068  *
1069  * DESCRIPTION: Write data to a physical memory address
1070  *
1071  *****************************************************************************/
1072 ACPI_STATUS
1073 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 value, UINT32 width)
1074 {
1075 #ifdef _KERNEL_MODE
1076 	if (vm_memcpy_to_physical((addr_t)address, &value, width / 8, false)
1077 			!= B_OK) {
1078 		return AE_ERROR;
1079 	}
1080 	return AE_OK;
1081 #else
1082 	return AE_ERROR;
1083 #endif
1084 }
1085 
1086 
1087 /******************************************************************************
1088  *
1089  * FUNCTION:    AcpiOsReadable
1090  *
1091  * PARAMETERS:  pointer             - Area to be verified
1092  *              length              - Size of area
1093  *
1094  * RETURN:      TRUE if readable for entire length
1095  *
1096  * DESCRIPTION: Verify that a pointer is valid for reading
1097  *
1098  *****************************************************************************/
1099 BOOLEAN
1100 AcpiOsReadable(void *pointer, ACPI_SIZE length)
1101 {
1102 #ifdef _KERNEL_MODE
1103 	return true;
1104 #else
1105 	area_id id;
1106 	area_info info;
1107 
1108 	DEBUG_FUNCTION_F("addr: %p; length: %lu", pointer, (size_t)length);
1109 
1110 	id = area_for(pointer);
1111 	if (id == B_ERROR) return false;
1112 	if (get_area_info(id, &info) != B_OK) return false;
1113 	return (info.protection & B_READ_AREA) != 0 &&
1114 			pointer + length <= info.address + info.ram_size;
1115 #endif
1116 }
1117 
1118 
1119 /******************************************************************************
1120  *
1121  * FUNCTION:    AcpiOsWritable
1122  *
1123  * PARAMETERS:  pointer             - Area to be verified
1124  *              length              - Size of area
1125  *
1126  * RETURN:      TRUE if writable for entire length
1127  *
1128  * DESCRIPTION: Verify that a pointer is valid for writing
1129  *
1130  *****************************************************************************/
1131 BOOLEAN
1132 AcpiOsWritable(void *pointer, ACPI_SIZE length)
1133 {
1134 #ifdef _KERNEL_MODE
1135 	return true;
1136 #else
1137 	area_id id;
1138 	area_info info;
1139 
1140 	DEBUG_FUNCTION_F("addr: %p; length: %lu", pointer, (size_t)length);
1141 
1142 	id = area_for(pointer);
1143 	if (id == B_ERROR) return false;
1144 	if (get_area_info(id, &info) != B_OK) return false;
1145 	return (info.protection & B_READ_AREA) != 0 &&
1146 			(info.protection & B_WRITE_AREA) != 0 &&
1147 			pointer + length <= info.address + info.ram_size;
1148 #endif
1149 }
1150 
1151 
1152 /******************************************************************************
1153  *
1154  * FUNCTION:    AcpiOsGetThreadId
1155  *
1156  * PARAMETERS:  None
1157  *
1158  * RETURN:      Id of the running thread
1159  *
1160  * DESCRIPTION: Get the Id of the current (running) thread
1161  *
1162  * NOTE:        The environment header should contain this line:
1163  *                  #define ACPI_THREAD_ID pthread_t
1164  *
1165  *****************************************************************************/
1166 ACPI_THREAD_ID
1167 AcpiOsGetThreadId()
1168 {
1169 	thread_id thread = find_thread(NULL);
1170 	// TODO: We arn't allowed threads with id 0, handle this case.
1171 	// ACPI treats a 0 return as an error,
1172 	// but we are thread 0 in early boot
1173 	return thread;
1174 }
1175 
1176 
1177 /******************************************************************************
1178  *
1179  * FUNCTION:    AcpiOsSignal
1180  *
1181  * PARAMETERS:  function            ACPI CA signal function code
1182  *              info                Pointer to function-dependent structure
1183  *
1184  * RETURN:      Status
1185  *
1186  * DESCRIPTION: Miscellaneous functions. Example implementation only.
1187  *
1188  *****************************************************************************/
1189 ACPI_STATUS
1190 AcpiOsSignal(UINT32 function, void *info)
1191 {
1192 	DEBUG_FUNCTION();
1193 
1194 	switch (function) {
1195 		case ACPI_SIGNAL_FATAL:
1196 #ifdef _KERNEL_MODE
1197 			panic(info == NULL ? "AcpiOsSignal: fatal" : (const char*)info);
1198 			break;
1199 #endif
1200 		case ACPI_SIGNAL_BREAKPOINT:
1201 			if (info != NULL)
1202 				AcpiOsPrintf("AcpiOsBreakpoint: %s ****\n", info);
1203 			else
1204 				AcpiOsPrintf("At AcpiOsBreakpoint ****\n");
1205 			break;
1206 	}
1207 
1208 	return AE_OK;
1209 }
1210 
1211 
1212 /*
1213  * Adapted from FreeBSD since the documentation of its intended impl
1214  * is lacking.
1215  *  Section 5.2.10.1: global lock acquire/release functions */
1216 #define GL_ACQUIRED     (-1)
1217 #define GL_BUSY         0
1218 #define GL_BIT_PENDING  0x01
1219 #define GL_BIT_OWNED    0x02
1220 #define GL_BIT_MASK     (GL_BIT_PENDING | GL_BIT_OWNED)
1221 
1222 
1223 /*
1224  * Adapted from FreeBSD since the documentation of its intended impl
1225  * is lacking.
1226  * Acquire the global lock.  If busy, set the pending bit.  The caller
1227  * will wait for notification from the BIOS that the lock is available
1228  * and then attempt to acquire it again.
1229  */
1230 int
1231 AcpiOsAcquireGlobalLock(uint32 *lock)
1232 {
1233 	uint32 newValue;
1234 	uint32 oldValue;
1235 
1236 	do {
1237 		oldValue = *lock;
1238 		newValue = ((oldValue & ~GL_BIT_MASK) | GL_BIT_OWNED) |
1239 				((oldValue >> 1) & GL_BIT_PENDING);
1240 		atomic_test_and_set((int32*)lock, newValue, oldValue);
1241 	} while (*lock == oldValue);
1242 	return ((newValue < GL_BIT_MASK) ? GL_ACQUIRED : GL_BUSY);
1243 }
1244 
1245 
1246 /*
1247  * Adapted from FreeBSD since the documentation of its intended impl
1248  * is lacking.
1249  * Release the global lock, returning whether there is a waiter pending.
1250  * If the BIOS set the pending bit, OSPM must notify the BIOS when it
1251  * releases the lock.
1252  */
1253 int
1254 AcpiOsReleaseGlobalLock(uint32 *lock)
1255 {
1256 	uint32 newValue;
1257 	uint32 oldValue;
1258 
1259 	do {
1260 		oldValue = *lock;
1261 		newValue = oldValue & ~GL_BIT_MASK;
1262 		atomic_test_and_set((int32*)lock, newValue, oldValue);
1263 	} while (*lock == oldValue);
1264 	return (oldValue & GL_BIT_PENDING);
1265 }
1266 
1267 
1268 ACPI_STATUS
1269 AcpiOsCreateMutex(ACPI_MUTEX* outHandle)
1270 {
1271 	*outHandle = (ACPI_MUTEX) malloc(sizeof(mutex));
1272 	DEBUG_FUNCTION_F("result: %p", *outHandle);
1273 	if (*outHandle == NULL)
1274 		return AE_NO_MEMORY;
1275 
1276 	mutex_init(*outHandle, "acpi mutex");
1277 	return AE_OK;
1278 }
1279 
1280 
1281 void
1282 AcpiOsDeleteMutex(ACPI_MUTEX handle)
1283 {
1284 	DEBUG_FUNCTION_F("mutex: %ld", handle);
1285 	mutex_destroy(handle);
1286 	free((void*)handle);
1287 }
1288 
1289 
1290 ACPI_STATUS
1291 AcpiOsAcquireMutex(ACPI_MUTEX handle, UINT16 timeout)
1292 {
1293 	ACPI_STATUS result = AE_OK;
1294 	DEBUG_FUNCTION_VF("mutex: %ld; timeout: %u", handle, timeout);
1295 
1296 	if (timeout == ACPI_WAIT_FOREVER)
1297 		result = mutex_lock(handle) == B_OK ? AE_OK : AE_BAD_PARAMETER;
1298 	else {
1299 		switch (mutex_lock_with_timeout(handle, B_RELATIVE_TIMEOUT,
1300 			(bigtime_t)timeout * 1000)) {
1301 			case B_OK:
1302 				result = AE_OK;
1303 				break;
1304 			case B_INTERRUPTED:
1305 			case B_TIMED_OUT:
1306 			case B_WOULD_BLOCK:
1307 				result = AE_TIME;
1308 				break;
1309 			case B_BAD_VALUE:
1310 			default:
1311 				result = AE_BAD_PARAMETER;
1312 				break;
1313 		}
1314 	}
1315 	DEBUG_FUNCTION_VF("mutex: %ld; timeout: %u result: %lu",
1316 		handle, timeout, (uint32)result);
1317 	return result;
1318 }
1319 
1320 
1321 void
1322 AcpiOsReleaseMutex(ACPI_MUTEX handle)
1323 {
1324 	DEBUG_FUNCTION_F("mutex: %p", handle);
1325 	mutex_unlock(handle);
1326 }
1327 
1328 
1329 /******************************************************************************
1330  *
1331  * FUNCTION:    AcpiOsWaitEventsComplete
1332  *
1333  * PARAMETERS:  None
1334  *
1335  * RETURN:      None
1336  *
1337  * DESCRIPTION: Wait for all asynchronous events to complete. This
1338  *              implementation does nothing.
1339  *
1340  *****************************************************************************/
1341 void
1342 AcpiOsWaitEventsComplete()
1343 {
1344     //TODO: FreeBSD See description.
1345     return;
1346 }
1347