xref: /haiku/src/add-ons/kernel/bus_managers/acpi/ACPICAHaiku.cpp (revision 9e25244c5e9051f6cd333820d6332397361abd6c)
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 <boot_item.h>
131 #	include <kernel.h>
132 #	include <vm/vm.h>
133 #endif
134 
135 __BEGIN_DECLS
136 #include "acpi.h"
137 #include "accommon.h"
138 #include "amlcode.h"
139 #include "acparser.h"
140 #include "acdebug.h"
141 __END_DECLS
142 
143 
144 ACPI_MODULE_NAME("Haiku ACPI Module")
145 
146 #define _COMPONENT ACPI_OS_SERVICES
147 
148 // verbosity level 0 = off, 1 = normal, 2 = all
149 #define DEBUG_OSHAIKU 0
150 
151 #if DEBUG_OSHAIKU <= 0
152 // No debugging, do nothing
153 #	define DEBUG_FUNCTION()
154 #	define DEBUG_FUNCTION_F(x, y...)
155 #	define DEBUG_FUNCTION_V()
156 #	define DEBUG_FUNCTION_VF(x, y...)
157 #else
158 #	define DEBUG_FUNCTION() \
159 		dprintf("acpi[%ld]: %s\n", find_thread(NULL), __PRETTY_FUNCTION__);
160 #	define DEBUG_FUNCTION_F(x, y...) \
161 		dprintf("acpi[%ld]: %s(" x ")\n", find_thread(NULL), __PRETTY_FUNCTION__, y);
162 #	if DEBUG_OSHAIKU == 1
163 // No verbose debugging, do nothing
164 #		define DEBUG_FUNCTION_V()
165 #		define DEBUG_FUNCTION_VF(x, y...)
166 #	else
167 // Full debugging
168 #		define DEBUG_FUNCTION_V() \
169 			dprintf("acpi[%ld]: %s\n", find_thread(NULL), __PRETTY_FUNCTION__);
170 #		define DEBUG_FUNCTION_VF(x, y...) \
171 			dprintf("acpi[%ld]: %s(" x ")\n", find_thread(NULL), __PRETTY_FUNCTION__, y);
172 #	endif
173 #endif
174 
175 
176 #ifdef _KERNEL_MODE
177 extern pci_module_info *gPCIManager;
178 extern dpc_module_info *gDPC;
179 extern void *gDPCHandle;
180 #endif
181 
182 extern FILE *AcpiGbl_DebugFile;
183 FILE *AcpiGbl_OutputFile;
184 
185 static ACPI_PHYSICAL_ADDRESS sACPIRoot = 0;
186 static void *sInterruptHandlerData[32];
187 
188 
189 /******************************************************************************
190  *
191  * FUNCTION:    AcpiOsInitialize, AcpiOsTerminate
192  *
193  * PARAMETERS:  None
194  *
195  * RETURN:      Status
196  *
197  * DESCRIPTION: Init and terminate.  Nothing to do.
198  *
199  *****************************************************************************/
200 ACPI_STATUS
201 AcpiOsInitialize()
202 {
203 #ifndef _KERNEL_MODE
204 	AcpiGbl_OutputFile = stdout;
205 #else
206 	AcpiGbl_OutputFile = NULL;
207 #endif
208 	DEBUG_FUNCTION();
209 	return AE_OK;
210 }
211 
212 
213 ACPI_STATUS
214 AcpiOsTerminate()
215 {
216 	DEBUG_FUNCTION();
217 	return AE_OK;
218 }
219 
220 
221 /******************************************************************************
222  *
223  * FUNCTION:    AcpiOsGetRootPointer
224  *
225  * PARAMETERS:  None
226  *
227  * RETURN:      RSDP physical address
228  *
229  * DESCRIPTION: Gets the root pointer (RSDP)
230  *
231  *****************************************************************************/
232 ACPI_PHYSICAL_ADDRESS
233 AcpiOsGetRootPointer()
234 {
235 #ifdef _KERNEL_MODE
236 	DEBUG_FUNCTION();
237 	if (sACPIRoot == 0) {
238 		phys_addr_t* acpiRootPointer = (phys_addr_t*)get_boot_item("ACPI_ROOT_POINTER", NULL);
239 		if (acpiRootPointer != NULL)
240 			sACPIRoot = *acpiRootPointer;
241 
242 		if (sACPIRoot == 0) {
243 			ACPI_PHYSICAL_ADDRESS address;
244 			ACPI_STATUS status = AcpiFindRootPointer(&address);
245 			if (status == AE_OK)
246 				sACPIRoot = address;
247 		}
248 	}
249 	return sACPIRoot;
250 #else
251 	return AeLocalGetRootPointer();
252 #endif
253 }
254 
255 
256 /******************************************************************************
257  *
258  * FUNCTION:    AcpiOsPredefinedOverride
259  *
260  * PARAMETERS:  initVal     - Initial value of the predefined object
261  *              newVal      - The new value for the object
262  *
263  * RETURN:      Status, pointer to value.  Null pointer returned if not
264  *              overriding.
265  *
266  * DESCRIPTION: Allow the OS to override predefined names
267  *
268  *****************************************************************************/
269 ACPI_STATUS
270 AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *initVal,
271 		ACPI_STRING *newVal)
272 {
273 	DEBUG_FUNCTION();
274 	if (!initVal || !newVal)
275 		return AE_BAD_PARAMETER;
276 
277 	*newVal = NULL;
278 	return AE_OK;
279 }
280 
281 
282 /******************************************************************************
283  *
284  * FUNCTION:    AcpiOsTableOverride
285  *
286  * PARAMETERS:  existingTable   - Header of current table (probably firmware)
287  *              newTable        - Where an entire new table is returned.
288  *
289  * RETURN:      Status, pointer to new table.  Null pointer returned if no
290  *              table is available to override
291  *
292  * DESCRIPTION: Return a different version of a table if one is available
293  *
294  *****************************************************************************/
295 ACPI_STATUS
296 AcpiOsTableOverride(ACPI_TABLE_HEADER *existingTable,
297 		ACPI_TABLE_HEADER **newTable)
298 {
299 	DEBUG_FUNCTION();
300 	if (!existingTable || !newTable)
301 		return AE_BAD_PARAMETER;
302 
303 	*newTable = NULL;
304 
305 #ifdef ACPI_EXEC_APP
306 	AeTableOverride(existingTable, newTable);
307 	return AE_OK;
308 #else
309 	return AE_NO_ACPI_TABLES;
310 #endif
311 }
312 
313 
314 /******************************************************************************
315  *
316  * FUNCTION:    AcpiOsPhysicalTableOverride
317  *
318  * PARAMETERS:  existingTable       - Header of current table (probably firmware)
319  *              newAddress          - Where new table address is returned
320  *                                    (Physical address)
321  *              newTableLength      - Where new table length is returned
322  *
323  * RETURN:      Status, address/length of new table. Null pointer returned
324  *              if no table is available to override.
325  *
326  * DESCRIPTION: Returns AE_SUPPORT, function not used in user space.
327  *
328  *****************************************************************************/
329 
330 ACPI_STATUS
331 AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *existingTable,
332 	ACPI_PHYSICAL_ADDRESS *newAddress, UINT32 *newTableLength)
333 {
334 	DEBUG_FUNCTION();
335     return (AE_SUPPORT);
336 }
337 
338 
339 /******************************************************************************
340  *
341  * FUNCTION:    AcpiOsRedirectOutput
342  *
343  * PARAMETERS:  destination         - An open file handle/pointer
344  *
345  * RETURN:      None
346  *
347  * DESCRIPTION: Causes redirect of AcpiOsPrintf and AcpiOsVprintf
348  *
349  *****************************************************************************/
350 void
351 AcpiOsRedirectOutput(void *destination)
352 {
353 	DEBUG_FUNCTION();
354 	AcpiGbl_OutputFile = (FILE*)destination;
355 }
356 
357 
358 /******************************************************************************
359  *
360  * FUNCTION:    AcpiOsPrintf
361  *
362  * PARAMETERS:  fmt, ...            Standard printf format
363  *
364  * RETURN:      None
365  *
366  * DESCRIPTION: Formatted output
367  *
368  *****************************************************************************/
369 void ACPI_INTERNAL_VAR_XFACE
370 AcpiOsPrintf(const char *fmt, ...)
371 {
372 	va_list args;
373 
374 	DEBUG_FUNCTION();
375 	va_start(args, fmt);
376 	AcpiOsVprintf(fmt, args);
377 	va_end(args);
378 }
379 
380 
381 /******************************************************************************
382  *
383  * FUNCTION:    AcpiOsVprintf
384  *
385  * PARAMETERS:  fmt                 Standard printf format
386  *              args                Argument list
387  *
388  * RETURN:      None
389  *
390  * DESCRIPTION: Formatted output with argument list pointer
391  *
392  *****************************************************************************/
393 void
394 AcpiOsVprintf(const char *fmt, va_list args)
395 {
396 #ifndef _KERNEL_MODE
397 	UINT8 flags;
398 
399 	flags = AcpiGbl_DbOutputFlags;
400 	if (flags & ACPI_DB_REDIRECTABLE_OUTPUT) {
401 		// Output is directable to either a file (if open) or the console
402 		if (AcpiGbl_DebugFile) {
403 			// Output file is open, send the output there
404 			vfprintf(AcpiGbl_DebugFile, fmt, args);
405 		} else {
406 			// No redirection, send output to console (once only!)
407 			flags |= ACPI_DB_CONSOLE_OUTPUT;
408 		}
409 	}
410 
411 	if (flags & ACPI_DB_CONSOLE_OUTPUT) {
412 		vfprintf(AcpiGbl_OutputFile, fmt, args);
413     }
414 #else
415 	static char outputBuffer[1024];
416 	vsnprintf(outputBuffer, 1024, fmt, args);
417 	dprintf("%s", outputBuffer);
418 #endif
419 }
420 
421 
422 /******************************************************************************
423  *
424  * FUNCTION:    AcpiOsGetLine
425  *
426  * PARAMETERS:  fmt                 Standard printf format
427  *              args                Argument list
428  *
429  * RETURN:      Actual bytes read
430  *
431  * DESCRIPTION: Formatted input with argument list pointer
432  *
433  *****************************************************************************/
434 UINT32
435 AcpiOsGetLine(char *buffer)
436 {
437 	uint32 i = 0;
438 
439 #ifndef _KERNEL_MODE
440 	uint8 temp;
441 
442 	for (i = 0; ; i++) {
443 		scanf("%1c", &temp);
444 		if (!temp || temp == '\n')
445 			break;
446 
447 		buffer[i] = temp;
448 	}
449 #endif
450 
451 	buffer[i] = 0;
452 	DEBUG_FUNCTION_F("buffer: \"%s\"; result: %lu", buffer, i);
453 	return i;
454 }
455 
456 
457 /******************************************************************************
458  *
459  * FUNCTION:    AcpiOsMapMemory
460  *
461  * PARAMETERS:  where               Physical address of memory to be mapped
462  *              length              How much memory to map
463  *
464  * RETURN:      Pointer to mapped memory.  Null on error.
465  *
466  * DESCRIPTION: Map physical memory into caller's address space
467  *
468  *****************************************************************************/
469 void *
470 AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS where, ACPI_SIZE length)
471 {
472 #ifdef _KERNEL_MODE
473 	void *there;
474 	area_id area = map_physical_memory("acpi_physical_mem_area",
475 		(phys_addr_t)where, length, B_ANY_KERNEL_ADDRESS,
476 		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, &there);
477 
478 	DEBUG_FUNCTION_F("addr: 0x%08lx; length: %lu; mapped: %p; area: %ld",
479 		(addr_t)where, (size_t)length, there, area);
480 	if (area < 0) {
481 		dprintf("ACPI: cannot map memory at 0x%" B_PRIu64 ", length %"
482 			B_PRIu64 "\n", (uint64)where, (uint64)length);
483 		return NULL;
484 	}
485 	return there;
486 #else
487 	return NULL;
488 #endif
489 
490 	// return ACPI_TO_POINTER((ACPI_SIZE) where);
491 }
492 
493 
494 /******************************************************************************
495  *
496  * FUNCTION:    AcpiOsUnmapMemory
497  *
498  * PARAMETERS:  where               Logical address of memory to be unmapped
499  *              length              How much memory to unmap
500  *
501  * RETURN:      None.
502  *
503  * DESCRIPTION: Delete a previously created mapping.  Where and Length must
504  *              correspond to a previous mapping exactly.
505  *
506  *****************************************************************************/
507 void
508 AcpiOsUnmapMemory(void *where, ACPI_SIZE length)
509 {
510 	DEBUG_FUNCTION_F("mapped: %p; length: %lu", where, (size_t)length);
511 	delete_area(area_for(where));
512 }
513 
514 
515 /******************************************************************************
516  *
517  * FUNCTION:    AcpiOsAllocate
518  *
519  * PARAMETERS:  size                Amount to allocate, in bytes
520  *
521  * RETURN:      Pointer to the new allocation.  Null on error.
522  *
523  * DESCRIPTION: Allocate memory.  Algorithm is dependent on the OS.
524  *
525  *****************************************************************************/
526 void *
527 AcpiOsAllocate(ACPI_SIZE size)
528 {
529 	void *mem = (void *) malloc(size);
530 	DEBUG_FUNCTION_VF("result: %p", mem);
531 	return mem;
532 }
533 
534 
535 /******************************************************************************
536  *
537  * FUNCTION:    AcpiOsFree
538  *
539  * PARAMETERS:  mem                 Pointer to previously allocated memory
540  *
541  * RETURN:      None.
542  *
543  * DESCRIPTION: Free memory allocated via AcpiOsAllocate
544  *
545  *****************************************************************************/
546 void
547 AcpiOsFree(void *mem)
548 {
549 	DEBUG_FUNCTION_VF("mem: %p", mem);
550 	free(mem);
551 }
552 
553 
554 /******************************************************************************
555  *
556  * FUNCTION:    AcpiOsCreateSemaphore
557  *
558  * PARAMETERS:  initialUnits        - Units to be assigned to the new semaphore
559  *              outHandle           - Where a handle will be returned
560  *
561  * RETURN:      Status
562  *
563  * DESCRIPTION: Create an OS semaphore
564  *
565  *****************************************************************************/
566 ACPI_STATUS
567 AcpiOsCreateSemaphore(UINT32 maxUnits, UINT32 initialUnits,
568 		ACPI_SEMAPHORE *outHandle)
569 {
570 	if (!outHandle)
571     	return AE_BAD_PARAMETER;
572 
573 	*outHandle = create_sem(initialUnits, "acpi_sem");
574 	DEBUG_FUNCTION_F("max: %lu; count: %lu; result: %ld",
575 		(uint32)maxUnits, (uint32)initialUnits, *outHandle);
576 
577 	if (*outHandle >= B_OK)
578 		return AE_OK;
579 
580 	return *outHandle == B_BAD_VALUE ? AE_BAD_PARAMETER : AE_NO_MEMORY;
581 }
582 
583 
584 /******************************************************************************
585  *
586  * FUNCTION:    AcpiOsDeleteSemaphore
587  *
588  * PARAMETERS:  handle              - Handle returned by AcpiOsCreateSemaphore
589  *
590  * RETURN:      Status
591  *
592  * DESCRIPTION: Delete an OS semaphore
593  *
594  *****************************************************************************/
595 ACPI_STATUS
596 AcpiOsDeleteSemaphore(ACPI_SEMAPHORE handle)
597 {
598 	DEBUG_FUNCTION_F("sem: %ld", handle);
599 	return delete_sem(handle) == B_OK ? AE_OK : AE_BAD_PARAMETER;
600 }
601 
602 
603 /******************************************************************************
604  *
605  * FUNCTION:    AcpiOsWaitSemaphore
606  *
607  * PARAMETERS:  handle              - Handle returned by AcpiOsCreateSemaphore
608  *              units               - How many units to wait for
609  *              timeout             - How long to wait
610  *
611  * RETURN:      Status
612  *
613  * DESCRIPTION: Wait for units
614  *
615  *****************************************************************************/
616 ACPI_STATUS
617 AcpiOsWaitSemaphore(ACPI_SEMAPHORE handle, UINT32 units, UINT16 timeout)
618 {
619 	ACPI_STATUS result = AE_OK;
620 	DEBUG_FUNCTION_VF("sem: %ld; count: %lu; timeout: %u",
621 		handle, (uint32)units, timeout);
622 
623 	if (timeout == ACPI_WAIT_FOREVER) {
624 		result = acquire_sem_etc(handle, units, 0, 0)
625 			== B_OK ? AE_OK : AE_BAD_PARAMETER;
626 	} else {
627 		switch (acquire_sem_etc(handle, units, B_RELATIVE_TIMEOUT,
628 			(bigtime_t)timeout * 1000)) {
629 			case B_OK:
630 				result = AE_OK;
631 				break;
632 			case B_INTERRUPTED:
633 			case B_TIMED_OUT:
634 			case B_WOULD_BLOCK:
635 				result = AE_TIME;
636 				break;
637 			case B_BAD_VALUE:
638 			default:
639 				result = AE_BAD_PARAMETER;
640 				break;
641 		}
642 	}
643 	DEBUG_FUNCTION_VF("sem: %ld; count: %lu; timeout: %u result: %lu",
644 		handle, (uint32)units, timeout, (uint32)result);
645 	return result;
646 }
647 
648 
649 /******************************************************************************
650  *
651  * FUNCTION:    AcpiOsSignalSemaphore
652  *
653  * PARAMETERS:  handle              - Handle returned by AcpiOsCreateSemaphore
654  *              units               - Number of units to send
655  *
656  * RETURN:      Status
657  *
658  * DESCRIPTION: Send units
659  *
660  *****************************************************************************/
661 ACPI_STATUS
662 AcpiOsSignalSemaphore(ACPI_SEMAPHORE handle, UINT32 units)
663 {
664 	status_t result;
665 	DEBUG_FUNCTION_VF("sem: %ld; count: %lu", handle, (uint32)units);
666 	// We can be called from interrupt handler, so don't reschedule
667 	result = release_sem_etc(handle, units, B_DO_NOT_RESCHEDULE);
668 	return result == B_OK ? AE_OK : AE_BAD_PARAMETER;
669 }
670 
671 
672 /******************************************************************************
673  *
674  * FUNCTION:    Spinlock interfaces
675  *
676  * DESCRIPTION: Map these interfaces to semaphore interfaces
677  *
678  *****************************************************************************/
679 ACPI_STATUS
680 AcpiOsCreateLock(ACPI_SPINLOCK *outHandle)
681 {
682 	*outHandle = (ACPI_SPINLOCK) malloc(sizeof(spinlock));
683 	DEBUG_FUNCTION_F("result: %p", *outHandle);
684 	if (*outHandle == NULL)
685 		return AE_NO_MEMORY;
686 
687 	B_INITIALIZE_SPINLOCK(*outHandle);
688 	return AE_OK;
689 }
690 
691 
692 void
693 AcpiOsDeleteLock(ACPI_SPINLOCK handle)
694 {
695 	DEBUG_FUNCTION();
696 	free((void*)handle);
697 }
698 
699 
700 ACPI_CPU_FLAGS
701 AcpiOsAcquireLock(ACPI_SPINLOCK handle)
702 {
703 	cpu_status cpu;
704 	DEBUG_FUNCTION_F("spinlock: %p", handle);
705 	cpu = disable_interrupts();
706 	acquire_spinlock(handle);
707 	return cpu;
708 }
709 
710 
711 void
712 AcpiOsReleaseLock(ACPI_SPINLOCK handle, ACPI_CPU_FLAGS flags)
713 {
714 	release_spinlock(handle);
715 	restore_interrupts(flags);
716 	DEBUG_FUNCTION_F("spinlock: %p", handle);
717 }
718 
719 
720 /******************************************************************************
721  *
722  * FUNCTION:    AcpiOsInstallInterruptHandler
723  *
724  * PARAMETERS:  interruptNumber     Level handler should respond to.
725  *              Isr                 Address of the ACPI interrupt handler
726  *              ExceptPtr           Where status is returned
727  *
728  * RETURN:      Handle to the newly installed handler.
729  *
730  * DESCRIPTION: Install an interrupt handler.  Used to install the ACPI
731  *              OS-independent handler.
732  *
733  *****************************************************************************/
734 UINT32
735 AcpiOsInstallInterruptHandler(UINT32 interruptNumber,
736 		ACPI_OSD_HANDLER serviceRoutine, void *context)
737 {
738 	status_t result;
739 	DEBUG_FUNCTION_F("vector: %lu; handler: %p context %p",
740 		(uint32)interruptNumber, serviceRoutine, context);
741 
742 #ifdef _KERNEL_MODE
743 	// It so happens that the Haiku and ACPI-CA interrupt handler routines
744 	// return the same values with the same meanings
745 	sInterruptHandlerData[interruptNumber] = context;
746 	result = install_io_interrupt_handler(interruptNumber,
747 		(interrupt_handler)serviceRoutine, context, 0);
748 
749 	DEBUG_FUNCTION_F("vector: %lu; handler: %p context %p returned %lu",
750 		(uint32)interruptNumber, serviceRoutine, context, (uint32)result);
751 
752 	return result == B_OK ? AE_OK : AE_BAD_PARAMETER;
753 #else
754 	return AE_BAD_PARAMETER;
755 #endif
756 }
757 
758 
759 /******************************************************************************
760  *
761  * FUNCTION:    AcpiOsRemoveInterruptHandler
762  *
763  * PARAMETERS:  Handle              Returned when handler was installed
764  *
765  * RETURN:      Status
766  *
767  * DESCRIPTION: Uninstalls an interrupt handler.
768  *
769  *****************************************************************************/
770 ACPI_STATUS
771 AcpiOsRemoveInterruptHandler(UINT32 interruptNumber,
772 		ACPI_OSD_HANDLER serviceRoutine)
773 {
774 	DEBUG_FUNCTION_F("vector: %lu; handler: %p", (uint32)interruptNumber,
775 		serviceRoutine);
776 #ifdef _KERNEL_MODE
777 	return remove_io_interrupt_handler(interruptNumber,
778 		(interrupt_handler)serviceRoutine,
779 		sInterruptHandlerData[interruptNumber]) == B_OK ? AE_OK : AE_ERROR;
780 #else
781 	return AE_ERROR;
782 #endif
783 }
784 
785 
786 /******************************************************************************
787  *
788  * FUNCTION:    AcpiOsExecute
789  *
790  * PARAMETERS:  type            - Type of execution
791  *              function        - Address of the function to execute
792  *              context         - Passed as a parameter to the function
793  *
794  * RETURN:      Status.
795  *
796  * DESCRIPTION: Execute a new thread
797  *
798  *****************************************************************************/
799 ACPI_STATUS
800 AcpiOsExecute(ACPI_EXECUTE_TYPE type, ACPI_OSD_EXEC_CALLBACK  function,
801 		void *context)
802 {
803 	DEBUG_FUNCTION();
804 /* TODO: Prioritize urgent?
805 	switch (type) {
806 		case OSL_GLOBAL_LOCK_HANDLER:
807 		case OSL_NOTIFY_HANDLER:
808 		case OSL_GPE_HANDLER:
809 		case OSL_DEBUGGER_THREAD:
810 		case OSL_EC_POLL_HANDLER:
811 		case OSL_EC_BURST_HANDLER:
812 			break;
813 	}
814 */
815 
816 	if (gDPC->queue_dpc(gDPCHandle, function, context) != B_OK) {
817 		DEBUG_FUNCTION_F("Serious failure in AcpiOsExecute! function: %p",
818 			function);
819 		return AE_BAD_PARAMETER;
820 	}
821 	return AE_OK;
822 }
823 
824 
825 /******************************************************************************
826  *
827  * FUNCTION:    AcpiOsStall
828  *
829  * PARAMETERS:  microseconds        To sleep
830  *
831  * RETURN:      Blocks until sleep is completed.
832  *
833  * DESCRIPTION: Sleep at microsecond granularity
834  *
835  *****************************************************************************/
836 void
837 AcpiOsStall(UINT32 microseconds)
838 {
839 	DEBUG_FUNCTION_F("microseconds: %lu", (uint32)microseconds);
840 	if (microseconds)
841 		spin(microseconds);
842 }
843 
844 
845 /******************************************************************************
846  *
847  * FUNCTION:    AcpiOsSleep
848  *
849  * PARAMETERS:  milliseconds        To sleep
850  *
851  * RETURN:      Blocks until sleep is completed.
852  *
853  * DESCRIPTION: Sleep at millisecond granularity
854  *
855  *****************************************************************************/
856 void
857 AcpiOsSleep(ACPI_INTEGER milliseconds)
858 {
859 	DEBUG_FUNCTION_F("milliseconds: %lu", (uint32)milliseconds);
860 	if (gKernelStartup)
861 		spin(milliseconds * 1000);
862 	else
863 		snooze(milliseconds * 1000);
864 }
865 
866 
867 /******************************************************************************
868  *
869  * FUNCTION:    AcpiOsGetTimer
870  *
871  * PARAMETERS:  None
872  *
873  * RETURN:      Current time in 100 nanosecond units
874  *
875  * DESCRIPTION: Get the current system time
876  *
877  *****************************************************************************/
878 UINT64
879 AcpiOsGetTimer()
880 {
881 	DEBUG_FUNCTION();
882 	return system_time() * 10;
883 }
884 
885 
886 /******************************************************************************
887  *
888  * FUNCTION:    AcpiOsReadPciConfiguration
889  *
890  * PARAMETERS:  pciId               Seg/Bus/Dev
891  *              reg                 Device Register
892  *              value               Buffer where value is placed
893  *              width               Number of bits
894  *
895  * RETURN:      Status
896  *
897  * DESCRIPTION: Read data from PCI configuration space
898  *
899  *****************************************************************************/
900 ACPI_STATUS
901 AcpiOsReadPciConfiguration(ACPI_PCI_ID *pciId, UINT32 reg, UINT64 *value,
902 		UINT32 width)
903 {
904 #ifdef _KERNEL_MODE
905 	DEBUG_FUNCTION();
906 
907 	switch (width) {
908 		case 8:
909 		case 16:
910 		case 32:
911 			*value = gPCIManager->read_pci_config(
912 				pciId->Bus, pciId->Device, pciId->Function, reg, width / 8);
913 			break;
914 		default:
915 			return AE_ERROR;
916 	}
917 	return AE_OK;
918 #else
919 	return AE_ERROR;
920 #endif
921 }
922 
923 
924 /******************************************************************************
925  *
926  * FUNCTION:    AcpiOsWritePciConfiguration
927  *
928  * PARAMETERS:  pciId               Seg/Bus/Dev
929  *              reg                 Device Register
930  *              value               Value to be written
931  *              width               Number of bits
932  *
933  * RETURN:      Status.
934  *
935  * DESCRIPTION: Write data to PCI configuration space
936  *
937  *****************************************************************************/
938 ACPI_STATUS
939 AcpiOsWritePciConfiguration(ACPI_PCI_ID *pciId, UINT32 reg,
940 		ACPI_INTEGER value, UINT32 width)
941 {
942 #ifdef _KERNEL_MODE
943 	DEBUG_FUNCTION();
944 	gPCIManager->write_pci_config(
945 		pciId->Bus, pciId->Device, pciId->Function, reg, width / 8, value);
946 	return AE_OK;
947 #else
948 	return AE_ERROR;
949 #endif
950 }
951 
952 
953 /******************************************************************************
954  *
955  * FUNCTION:    AcpiOsReadPort
956  *
957  * PARAMETERS:  address             Address of I/O port/register to read
958  *              Value               Where value is placed
959  *              width               Number of bits
960  *
961  * RETURN:      Value read from port
962  *
963  * DESCRIPTION: Read data from an I/O port or register
964  *
965  *****************************************************************************/
966 ACPI_STATUS
967 AcpiOsReadPort(ACPI_IO_ADDRESS address, UINT32 *value, UINT32 width)
968 {
969 #ifdef _KERNEL_MODE
970 	DEBUG_FUNCTION_F("addr: 0x%08lx; width: %lu", (addr_t)address, (uint32)width);
971 	switch (width) {
972 		case 8:
973 			*value = gPCIManager->read_io_8(address);
974 			break;
975 
976 		case 16:
977 			*value = gPCIManager->read_io_16(address);
978 			break;
979 
980 		case 32:
981 			*value = gPCIManager->read_io_32(address);
982 			break;
983 
984 		default:
985 			return AE_ERROR;
986 	}
987 
988 	return AE_OK;
989 #else
990 	return AE_ERROR;
991 #endif
992 }
993 
994 
995 /******************************************************************************
996  *
997  * FUNCTION:    AcpiOsWritePort
998  *
999  * PARAMETERS:  address             Address of I/O port/register to write
1000  *              value               Value to write
1001  *              width               Number of bits
1002  *
1003  * RETURN:      None
1004  *
1005  * DESCRIPTION: Write data to an I/O port or register
1006  *
1007  *****************************************************************************/
1008 ACPI_STATUS
1009 AcpiOsWritePort(ACPI_IO_ADDRESS address, UINT32 value, UINT32 width)
1010 {
1011 #ifdef _KERNEL_MODE
1012 	DEBUG_FUNCTION_F("addr: 0x%08lx; value: %lu; width: %lu",
1013 		(addr_t)address, (uint32)value, (uint32)width);
1014 	switch (width) {
1015 		case 8:
1016 			gPCIManager->write_io_8(address, value);
1017 			break;
1018 
1019 		case 16:
1020 			gPCIManager->write_io_16(address,value);
1021 			break;
1022 
1023 		case 32:
1024 			gPCIManager->write_io_32(address,value);
1025 			break;
1026 
1027 		default:
1028 			return AE_ERROR;
1029 	}
1030 
1031 	return AE_OK;
1032 #else
1033 	return AE_ERROR;
1034 #endif
1035 }
1036 
1037 
1038 /******************************************************************************
1039  *
1040  * FUNCTION:    AcpiOsReadMemory
1041  *
1042  * PARAMETERS:  address             Physical Memory Address to read
1043  *              value               Where value is placed
1044  *              width               Number of bits
1045  *
1046  * RETURN:      Value read from physical memory address
1047  *
1048  * DESCRIPTION: Read data from a physical memory address
1049  *
1050  *****************************************************************************/
1051 ACPI_STATUS
1052 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 *value, UINT32 width)
1053 {
1054 #ifdef _KERNEL_MODE
1055 	if (vm_memcpy_from_physical(value, (phys_addr_t)address, width / 8, false)
1056 		!= B_OK) {
1057 		return AE_ERROR;
1058 	}
1059 	return AE_OK;
1060 #else
1061 	return AE_ERROR;
1062 #endif
1063 }
1064 
1065 
1066 /******************************************************************************
1067  *
1068  * FUNCTION:    AcpiOsWriteMemory
1069  *
1070  * PARAMETERS:  address             Physical Memory Address to write
1071  *              value               Value to write
1072  *              width               Number of bits
1073  *
1074  * RETURN:      None
1075  *
1076  * DESCRIPTION: Write data to a physical memory address
1077  *
1078  *****************************************************************************/
1079 ACPI_STATUS
1080 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 value, UINT32 width)
1081 {
1082 #ifdef _KERNEL_MODE
1083 	if (vm_memcpy_to_physical((phys_addr_t)address, &value, width / 8, false)
1084 			!= B_OK) {
1085 		return AE_ERROR;
1086 	}
1087 	return AE_OK;
1088 #else
1089 	return AE_ERROR;
1090 #endif
1091 }
1092 
1093 
1094 /******************************************************************************
1095  *
1096  * FUNCTION:    AcpiOsReadable
1097  *
1098  * PARAMETERS:  pointer             - Area to be verified
1099  *              length              - Size of area
1100  *
1101  * RETURN:      TRUE if readable for entire length
1102  *
1103  * DESCRIPTION: Verify that a pointer is valid for reading
1104  *
1105  *****************************************************************************/
1106 BOOLEAN
1107 AcpiOsReadable(void *pointer, ACPI_SIZE length)
1108 {
1109 #ifdef _KERNEL_MODE
1110 	return true;
1111 #else
1112 	area_id id;
1113 	area_info info;
1114 
1115 	DEBUG_FUNCTION_F("addr: %p; length: %lu", pointer, (size_t)length);
1116 
1117 	id = area_for(pointer);
1118 	if (id == B_ERROR) return false;
1119 	if (get_area_info(id, &info) != B_OK) return false;
1120 	return (info.protection & B_READ_AREA) != 0 &&
1121 			((char *)pointer) + length <= info.address + info.ram_size;
1122 #endif
1123 }
1124 
1125 
1126 /******************************************************************************
1127  *
1128  * FUNCTION:    AcpiOsWritable
1129  *
1130  * PARAMETERS:  pointer             - Area to be verified
1131  *              length              - Size of area
1132  *
1133  * RETURN:      TRUE if writable for entire length
1134  *
1135  * DESCRIPTION: Verify that a pointer is valid for writing
1136  *
1137  *****************************************************************************/
1138 BOOLEAN
1139 AcpiOsWritable(void *pointer, ACPI_SIZE length)
1140 {
1141 #ifdef _KERNEL_MODE
1142 	return true;
1143 #else
1144 	area_id id;
1145 	area_info info;
1146 
1147 	DEBUG_FUNCTION_F("addr: %p; length: %lu", pointer, (size_t)length);
1148 
1149 	id = area_for(pointer);
1150 	if (id == B_ERROR) return false;
1151 	if (get_area_info(id, &info) != B_OK) return false;
1152 	return (info.protection & B_READ_AREA) != 0 &&
1153 			(info.protection & B_WRITE_AREA) != 0 &&
1154 			((char *)pointer) + length <= info.address + info.ram_size;
1155 #endif
1156 }
1157 
1158 
1159 /******************************************************************************
1160  *
1161  * FUNCTION:    AcpiOsGetThreadId
1162  *
1163  * PARAMETERS:  None
1164  *
1165  * RETURN:      Id of the running thread
1166  *
1167  * DESCRIPTION: Get the Id of the current (running) thread
1168  *
1169  * NOTE:        The environment header should contain this line:
1170  *                  #define ACPI_THREAD_ID pthread_t
1171  *
1172  *****************************************************************************/
1173 ACPI_THREAD_ID
1174 AcpiOsGetThreadId()
1175 {
1176 	thread_id thread = find_thread(NULL);
1177 	// TODO: We arn't allowed threads with id 0, handle this case.
1178 	// ACPI treats a 0 return as an error,
1179 	// but we are thread 0 in early boot
1180 	return thread;
1181 }
1182 
1183 
1184 /******************************************************************************
1185  *
1186  * FUNCTION:    AcpiOsSignal
1187  *
1188  * PARAMETERS:  function            ACPI CA signal function code
1189  *              info                Pointer to function-dependent structure
1190  *
1191  * RETURN:      Status
1192  *
1193  * DESCRIPTION: Miscellaneous functions. Example implementation only.
1194  *
1195  *****************************************************************************/
1196 ACPI_STATUS
1197 AcpiOsSignal(UINT32 function, void *info)
1198 {
1199 	DEBUG_FUNCTION();
1200 
1201 	switch (function) {
1202 		case ACPI_SIGNAL_FATAL:
1203 #ifdef _KERNEL_MODE
1204 			panic("%s", info == NULL ? "AcpiOsSignal: fatal" : (const char*)info);
1205 			break;
1206 #endif
1207 		case ACPI_SIGNAL_BREAKPOINT:
1208 			if (info != NULL)
1209 				AcpiOsPrintf("AcpiOsBreakpoint: %s ****\n", (const char*)info);
1210 			else
1211 				AcpiOsPrintf("At AcpiOsBreakpoint ****\n");
1212 			break;
1213 	}
1214 
1215 	return AE_OK;
1216 }
1217 
1218 
1219 /*
1220  * Adapted from FreeBSD since the documentation of its intended impl
1221  * is lacking.
1222  *  Section 5.2.10.1: global lock acquire/release functions */
1223 #define GL_ACQUIRED     (-1)
1224 #define GL_BUSY         0
1225 #define GL_BIT_PENDING  0x01
1226 #define GL_BIT_OWNED    0x02
1227 #define GL_BIT_MASK     (GL_BIT_PENDING | GL_BIT_OWNED)
1228 
1229 
1230 /*
1231  * Adapted from FreeBSD since the documentation of its intended impl
1232  * is lacking.
1233  * Acquire the global lock.  If busy, set the pending bit.  The caller
1234  * will wait for notification from the BIOS that the lock is available
1235  * and then attempt to acquire it again.
1236  */
1237 int
1238 AcpiOsAcquireGlobalLock(uint32 *lock)
1239 {
1240 	uint32 newValue;
1241 	uint32 oldValue;
1242 
1243 	do {
1244 		oldValue = *lock;
1245 		newValue = ((oldValue & ~GL_BIT_MASK) | GL_BIT_OWNED) |
1246 				((oldValue >> 1) & GL_BIT_PENDING);
1247 		atomic_test_and_set((int32*)lock, newValue, oldValue);
1248 	} while (*lock == oldValue);
1249 	return ((newValue < GL_BIT_MASK) ? GL_ACQUIRED : GL_BUSY);
1250 }
1251 
1252 
1253 /*
1254  * Adapted from FreeBSD since the documentation of its intended impl
1255  * is lacking.
1256  * Release the global lock, returning whether there is a waiter pending.
1257  * If the BIOS set the pending bit, OSPM must notify the BIOS when it
1258  * releases the lock.
1259  */
1260 int
1261 AcpiOsReleaseGlobalLock(uint32 *lock)
1262 {
1263 	uint32 newValue;
1264 	uint32 oldValue;
1265 
1266 	do {
1267 		oldValue = *lock;
1268 		newValue = oldValue & ~GL_BIT_MASK;
1269 		atomic_test_and_set((int32*)lock, newValue, oldValue);
1270 	} while (*lock == oldValue);
1271 	return (oldValue & GL_BIT_PENDING);
1272 }
1273 
1274 
1275 ACPI_STATUS
1276 AcpiOsCreateMutex(ACPI_MUTEX* outHandle)
1277 {
1278 	*outHandle = (ACPI_MUTEX) malloc(sizeof(mutex));
1279 	DEBUG_FUNCTION_F("result: %p", *outHandle);
1280 	if (*outHandle == NULL)
1281 		return AE_NO_MEMORY;
1282 
1283 	mutex_init(*outHandle, "acpi mutex");
1284 	return AE_OK;
1285 }
1286 
1287 
1288 void
1289 AcpiOsDeleteMutex(ACPI_MUTEX handle)
1290 {
1291 	DEBUG_FUNCTION_F("mutex: %ld", (addr_t)handle);
1292 	mutex_destroy(handle);
1293 	free((void*)handle);
1294 }
1295 
1296 
1297 ACPI_STATUS
1298 AcpiOsAcquireMutex(ACPI_MUTEX handle, UINT16 timeout)
1299 {
1300 	ACPI_STATUS result = AE_OK;
1301 	DEBUG_FUNCTION_VF("mutex: %p; timeout: %u", handle, timeout);
1302 
1303 	if (timeout == ACPI_WAIT_FOREVER) {
1304 		result = (mutex_lock(handle) == B_OK) ? AE_OK : AE_BAD_PARAMETER;
1305 	} else if (timeout == ACPI_DO_NOT_WAIT) {
1306 		result = (mutex_trylock(handle) == B_OK) ? AE_OK : AE_TIME;
1307 	} else {
1308 		switch (mutex_lock_with_timeout(handle, B_RELATIVE_TIMEOUT,
1309 			(bigtime_t)timeout * 1000)) {
1310 			case B_OK:
1311 				result = AE_OK;
1312 				break;
1313 			case B_INTERRUPTED:
1314 			case B_TIMED_OUT:
1315 			case B_WOULD_BLOCK:
1316 				result = AE_TIME;
1317 				break;
1318 			case B_BAD_VALUE:
1319 			default:
1320 				result = AE_BAD_PARAMETER;
1321 				break;
1322 		}
1323 	}
1324 	DEBUG_FUNCTION_VF("mutex: %p; timeout: %u result: %lu",
1325 		handle, timeout, (uint32)result);
1326 	return result;
1327 }
1328 
1329 
1330 void
1331 AcpiOsReleaseMutex(ACPI_MUTEX handle)
1332 {
1333 	DEBUG_FUNCTION_F("mutex: %p", handle);
1334 	mutex_unlock(handle);
1335 }
1336 
1337 
1338 /******************************************************************************
1339  *
1340  * FUNCTION:    AcpiOsWaitEventsComplete
1341  *
1342  * PARAMETERS:  None
1343  *
1344  * RETURN:      None
1345  *
1346  * DESCRIPTION: Wait for all asynchronous events to complete. This
1347  *              implementation does nothing.
1348  *
1349  *****************************************************************************/
1350 void
1351 AcpiOsWaitEventsComplete()
1352 {
1353     //TODO: FreeBSD See description.
1354     return;
1355 }
1356 
1357 
1358 /******************************************************************************
1359  *
1360  * FUNCTION:    AcpiOsEnterSleep
1361  *
1362  * PARAMETERS:  SleepState          - Which sleep state to enter
1363  *              RegaValue           - Register A value
1364  *              RegbValue           - Register B value
1365  *
1366  * RETURN:      Status
1367  *
1368  * DESCRIPTION: A hook before writing sleep registers to enter the sleep
1369  *              state. Return AE_CTRL_TERMINATE to skip further sleep register
1370  *              writes.
1371  *
1372  *****************************************************************************/
1373 
1374 ACPI_STATUS
1375 AcpiOsEnterSleep (
1376 	UINT8                   SleepState,
1377 	UINT32                  RegaValue,
1378 	UINT32                  RegbValue)
1379 {
1380 	return (AE_OK);
1381 }
1382