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