xref: /haiku/src/add-ons/kernel/bus_managers/acpi/ACPICAHaiku.cpp (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
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",
473 		(phys_addr_t)where, length, B_ANY_KERNEL_ADDRESS,
474 		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, &there);
475 
476 	DEBUG_FUNCTION_F("addr: 0x%08lx; length: %lu; mapped: %p; area: %ld",
477 		(addr_t)where, (size_t)length, there, area);
478 	if (area < 0) {
479 		dprintf("ACPI: cannot map memory at 0x%" B_PRIu64 ", length %"
480 			B_PRIu64 "\n", (uint64)where, (uint64)length);
481 		return NULL;
482 	}
483 	return there;
484 #else
485 	return NULL;
486 #endif
487 
488 	// return ACPI_TO_POINTER((ACPI_SIZE) where);
489 }
490 
491 
492 /******************************************************************************
493  *
494  * FUNCTION:    AcpiOsUnmapMemory
495  *
496  * PARAMETERS:  where               Logical address of memory to be unmapped
497  *              length              How much memory to unmap
498  *
499  * RETURN:      None.
500  *
501  * DESCRIPTION: Delete a previously created mapping.  Where and Length must
502  *              correspond to a previous mapping exactly.
503  *
504  *****************************************************************************/
505 void
506 AcpiOsUnmapMemory(void *where, ACPI_SIZE length)
507 {
508 	DEBUG_FUNCTION_F("mapped: %p; length: %lu", where, (size_t)length);
509 	delete_area(area_for(where));
510 }
511 
512 
513 /******************************************************************************
514  *
515  * FUNCTION:    AcpiOsAllocate
516  *
517  * PARAMETERS:  size                Amount to allocate, in bytes
518  *
519  * RETURN:      Pointer to the new allocation.  Null on error.
520  *
521  * DESCRIPTION: Allocate memory.  Algorithm is dependent on the OS.
522  *
523  *****************************************************************************/
524 void *
525 AcpiOsAllocate(ACPI_SIZE size)
526 {
527 	void *mem = (void *) malloc(size);
528 	DEBUG_FUNCTION_VF("result: %p", mem);
529 	return mem;
530 }
531 
532 
533 /******************************************************************************
534  *
535  * FUNCTION:    AcpiOsFree
536  *
537  * PARAMETERS:  mem                 Pointer to previously allocated memory
538  *
539  * RETURN:      None.
540  *
541  * DESCRIPTION: Free memory allocated via AcpiOsAllocate
542  *
543  *****************************************************************************/
544 void
545 AcpiOsFree(void *mem)
546 {
547 	DEBUG_FUNCTION_VF("mem: %p", mem);
548 	free(mem);
549 }
550 
551 
552 /******************************************************************************
553  *
554  * FUNCTION:    AcpiOsCreateSemaphore
555  *
556  * PARAMETERS:  initialUnits        - Units to be assigned to the new semaphore
557  *              outHandle           - Where a handle will be returned
558  *
559  * RETURN:      Status
560  *
561  * DESCRIPTION: Create an OS semaphore
562  *
563  *****************************************************************************/
564 ACPI_STATUS
565 AcpiOsCreateSemaphore(UINT32 maxUnits, UINT32 initialUnits,
566 		ACPI_SEMAPHORE *outHandle)
567 {
568 	if (!outHandle)
569     	return AE_BAD_PARAMETER;
570 
571 	*outHandle = create_sem(initialUnits, "acpi_sem");
572 	DEBUG_FUNCTION_F("max: %lu; count: %lu; result: %ld",
573 		(uint32)maxUnits, (uint32)initialUnits, *outHandle);
574 
575 	if (*outHandle >= B_OK)
576 		return AE_OK;
577 
578 	return *outHandle == B_BAD_VALUE ? AE_BAD_PARAMETER : AE_NO_MEMORY;
579 }
580 
581 
582 /******************************************************************************
583  *
584  * FUNCTION:    AcpiOsDeleteSemaphore
585  *
586  * PARAMETERS:  handle              - Handle returned by AcpiOsCreateSemaphore
587  *
588  * RETURN:      Status
589  *
590  * DESCRIPTION: Delete an OS semaphore
591  *
592  *****************************************************************************/
593 ACPI_STATUS
594 AcpiOsDeleteSemaphore(ACPI_SEMAPHORE handle)
595 {
596 	DEBUG_FUNCTION_F("sem: %ld", handle);
597 	return delete_sem(handle) == B_OK ? AE_OK : AE_BAD_PARAMETER;
598 }
599 
600 
601 /******************************************************************************
602  *
603  * FUNCTION:    AcpiOsWaitSemaphore
604  *
605  * PARAMETERS:  handle              - Handle returned by AcpiOsCreateSemaphore
606  *              units               - How many units to wait for
607  *              timeout             - How long to wait
608  *
609  * RETURN:      Status
610  *
611  * DESCRIPTION: Wait for units
612  *
613  *****************************************************************************/
614 ACPI_STATUS
615 AcpiOsWaitSemaphore(ACPI_SEMAPHORE handle, UINT32 units, UINT16 timeout)
616 {
617 	ACPI_STATUS result = AE_OK;
618 	DEBUG_FUNCTION_VF("sem: %ld; count: %lu; timeout: %u",
619 		handle, (uint32)units, timeout);
620 
621 	if (timeout == ACPI_WAIT_FOREVER) {
622 		result = acquire_sem_etc(handle, units, 0, 0)
623 			== B_OK ? AE_OK : AE_BAD_PARAMETER;
624 	} else {
625 		switch (acquire_sem_etc(handle, units, B_RELATIVE_TIMEOUT,
626 			(bigtime_t)timeout * 1000)) {
627 			case B_OK:
628 				result = AE_OK;
629 				break;
630 			case B_INTERRUPTED:
631 			case B_TIMED_OUT:
632 			case B_WOULD_BLOCK:
633 				result = AE_TIME;
634 				break;
635 			case B_BAD_VALUE:
636 			default:
637 				result = AE_BAD_PARAMETER;
638 				break;
639 		}
640 	}
641 	DEBUG_FUNCTION_VF("sem: %ld; count: %lu; timeout: %u result: %lu",
642 		handle, (uint32)units, timeout, (uint32)result);
643 	return result;
644 }
645 
646 
647 /******************************************************************************
648  *
649  * FUNCTION:    AcpiOsSignalSemaphore
650  *
651  * PARAMETERS:  handle              - Handle returned by AcpiOsCreateSemaphore
652  *              units               - Number of units to send
653  *
654  * RETURN:      Status
655  *
656  * DESCRIPTION: Send units
657  *
658  *****************************************************************************/
659 ACPI_STATUS
660 AcpiOsSignalSemaphore(ACPI_SEMAPHORE handle, UINT32 units)
661 {
662 	status_t result;
663 	DEBUG_FUNCTION_VF("sem: %ld; count: %lu", handle, (uint32)units);
664 	// We can be called from interrupt handler, so don't reschedule
665 	result = release_sem_etc(handle, units, B_DO_NOT_RESCHEDULE);
666 	return result == B_OK ? AE_OK : AE_BAD_PARAMETER;
667 }
668 
669 
670 /******************************************************************************
671  *
672  * FUNCTION:    Spinlock interfaces
673  *
674  * DESCRIPTION: Map these interfaces to semaphore interfaces
675  *
676  *****************************************************************************/
677 ACPI_STATUS
678 AcpiOsCreateLock(ACPI_SPINLOCK *outHandle)
679 {
680 	*outHandle = (ACPI_SPINLOCK) malloc(sizeof(spinlock));
681 	DEBUG_FUNCTION_F("result: %p", *outHandle);
682 	if (*outHandle == NULL)
683 		return AE_NO_MEMORY;
684 
685 	B_INITIALIZE_SPINLOCK(*outHandle);
686 	return AE_OK;
687 }
688 
689 
690 void
691 AcpiOsDeleteLock(ACPI_SPINLOCK handle)
692 {
693 	DEBUG_FUNCTION();
694 	free((void*)handle);
695 }
696 
697 
698 ACPI_CPU_FLAGS
699 AcpiOsAcquireLock(ACPI_SPINLOCK handle)
700 {
701 	cpu_status cpu;
702 	DEBUG_FUNCTION_F("spinlock: %p", handle);
703 	cpu = disable_interrupts();
704 	acquire_spinlock(handle);
705 	return cpu;
706 }
707 
708 
709 void
710 AcpiOsReleaseLock(ACPI_SPINLOCK handle, ACPI_CPU_FLAGS flags)
711 {
712 	release_spinlock(handle);
713 	restore_interrupts(flags);
714 	DEBUG_FUNCTION_F("spinlock: %p", handle);
715 }
716 
717 
718 /******************************************************************************
719  *
720  * FUNCTION:    AcpiOsInstallInterruptHandler
721  *
722  * PARAMETERS:  interruptNumber     Level handler should respond to.
723  *              Isr                 Address of the ACPI interrupt handler
724  *              ExceptPtr           Where status is returned
725  *
726  * RETURN:      Handle to the newly installed handler.
727  *
728  * DESCRIPTION: Install an interrupt handler.  Used to install the ACPI
729  *              OS-independent handler.
730  *
731  *****************************************************************************/
732 UINT32
733 AcpiOsInstallInterruptHandler(UINT32 interruptNumber,
734 		ACPI_OSD_HANDLER serviceRoutine, void *context)
735 {
736 	status_t result;
737 	DEBUG_FUNCTION_F("vector: %lu; handler: %p context %p",
738 		(uint32)interruptNumber, serviceRoutine, context);
739 
740 #ifdef _KERNEL_MODE
741 	// It so happens that the Haiku and ACPI-CA interrupt handler routines
742 	// return the same values with the same meanings
743 	sInterruptHandlerData[interruptNumber] = context;
744 	result = install_io_interrupt_handler(interruptNumber,
745 		(interrupt_handler)serviceRoutine, context, 0);
746 
747 	DEBUG_FUNCTION_F("vector: %lu; handler: %p context %p returned %lu",
748 		(uint32)interruptNumber, serviceRoutine, context, (uint32)result);
749 
750 	return result == B_OK ? AE_OK : AE_BAD_PARAMETER;
751 #else
752 	return AE_BAD_PARAMETER;
753 #endif
754 }
755 
756 
757 /******************************************************************************
758  *
759  * FUNCTION:    AcpiOsRemoveInterruptHandler
760  *
761  * PARAMETERS:  Handle              Returned when handler was installed
762  *
763  * RETURN:      Status
764  *
765  * DESCRIPTION: Uninstalls an interrupt handler.
766  *
767  *****************************************************************************/
768 ACPI_STATUS
769 AcpiOsRemoveInterruptHandler(UINT32 interruptNumber,
770 		ACPI_OSD_HANDLER serviceRoutine)
771 {
772 	DEBUG_FUNCTION_F("vector: %lu; handler: %p", (uint32)interruptNumber,
773 		serviceRoutine);
774 #ifdef _KERNEL_MODE
775 	return remove_io_interrupt_handler(interruptNumber,
776 		(interrupt_handler)serviceRoutine,
777 		sInterruptHandlerData[interruptNumber]) == B_OK ? AE_OK : AE_ERROR;
778 #else
779 	return AE_ERROR;
780 #endif
781 }
782 
783 
784 /******************************************************************************
785  *
786  * FUNCTION:    AcpiOsExecute
787  *
788  * PARAMETERS:  type            - Type of execution
789  *              function        - Address of the function to execute
790  *              context         - Passed as a parameter to the function
791  *
792  * RETURN:      Status.
793  *
794  * DESCRIPTION: Execute a new thread
795  *
796  *****************************************************************************/
797 ACPI_STATUS
798 AcpiOsExecute(ACPI_EXECUTE_TYPE type, ACPI_OSD_EXEC_CALLBACK  function,
799 		void *context)
800 {
801 	DEBUG_FUNCTION();
802 /* TODO: Prioritize urgent?
803 	switch (type) {
804 		case OSL_GLOBAL_LOCK_HANDLER:
805 		case OSL_NOTIFY_HANDLER:
806 		case OSL_GPE_HANDLER:
807 		case OSL_DEBUGGER_THREAD:
808 		case OSL_EC_POLL_HANDLER:
809 		case OSL_EC_BURST_HANDLER:
810 			break;
811 	}
812 */
813 
814 	if (gDPC->queue_dpc(gDPCHandle, function, context) != B_OK) {
815 		DEBUG_FUNCTION_F("Serious failure in AcpiOsExecute! function: %p",
816 			function);
817 		return AE_BAD_PARAMETER;
818 	}
819 	return AE_OK;
820 }
821 
822 
823 /******************************************************************************
824  *
825  * FUNCTION:    AcpiOsStall
826  *
827  * PARAMETERS:  microseconds        To sleep
828  *
829  * RETURN:      Blocks until sleep is completed.
830  *
831  * DESCRIPTION: Sleep at microsecond granularity
832  *
833  *****************************************************************************/
834 void
835 AcpiOsStall(UINT32 microseconds)
836 {
837 	DEBUG_FUNCTION_F("microseconds: %lu", (uint32)microseconds);
838 	if (microseconds)
839 		spin(microseconds);
840 }
841 
842 
843 /******************************************************************************
844  *
845  * FUNCTION:    AcpiOsSleep
846  *
847  * PARAMETERS:  milliseconds        To sleep
848  *
849  * RETURN:      Blocks until sleep is completed.
850  *
851  * DESCRIPTION: Sleep at millisecond granularity
852  *
853  *****************************************************************************/
854 void
855 AcpiOsSleep(ACPI_INTEGER milliseconds)
856 {
857 	DEBUG_FUNCTION_F("milliseconds: %lu", (uint32)milliseconds);
858 	if (gKernelStartup)
859 		spin(milliseconds * 1000);
860 	else
861 		snooze(milliseconds * 1000);
862 }
863 
864 
865 /******************************************************************************
866  *
867  * FUNCTION:    AcpiOsGetTimer
868  *
869  * PARAMETERS:  None
870  *
871  * RETURN:      Current time in 100 nanosecond units
872  *
873  * DESCRIPTION: Get the current system time
874  *
875  *****************************************************************************/
876 UINT64
877 AcpiOsGetTimer()
878 {
879 	DEBUG_FUNCTION();
880 	return system_time() * 10;
881 }
882 
883 
884 /******************************************************************************
885  *
886  * FUNCTION:    AcpiOsReadPciConfiguration
887  *
888  * PARAMETERS:  pciId               Seg/Bus/Dev
889  *              reg                 Device Register
890  *              value               Buffer where value is placed
891  *              width               Number of bits
892  *
893  * RETURN:      Status
894  *
895  * DESCRIPTION: Read data from PCI configuration space
896  *
897  *****************************************************************************/
898 ACPI_STATUS
899 AcpiOsReadPciConfiguration(ACPI_PCI_ID *pciId, UINT32 reg, UINT64 *value,
900 		UINT32 width)
901 {
902 #ifdef _KERNEL_MODE
903 	DEBUG_FUNCTION();
904 
905 	switch (width) {
906 		case 8:
907 		case 16:
908 		case 32:
909 			*value = gPCIManager->read_pci_config(
910 				pciId->Bus, pciId->Device, pciId->Function, reg, width / 8);
911 			break;
912 		default:
913 			return AE_ERROR;
914 	}
915 	return AE_OK;
916 #else
917 	return AE_ERROR;
918 #endif
919 }
920 
921 
922 /******************************************************************************
923  *
924  * FUNCTION:    AcpiOsWritePciConfiguration
925  *
926  * PARAMETERS:  pciId               Seg/Bus/Dev
927  *              reg                 Device Register
928  *              value               Value to be written
929  *              width               Number of bits
930  *
931  * RETURN:      Status.
932  *
933  * DESCRIPTION: Write data to PCI configuration space
934  *
935  *****************************************************************************/
936 ACPI_STATUS
937 AcpiOsWritePciConfiguration(ACPI_PCI_ID *pciId, UINT32 reg,
938 		ACPI_INTEGER value, UINT32 width)
939 {
940 #ifdef _KERNEL_MODE
941 	DEBUG_FUNCTION();
942 	gPCIManager->write_pci_config(
943 		pciId->Bus, pciId->Device, pciId->Function, reg, width / 8, value);
944 	return AE_OK;
945 #else
946 	return AE_ERROR;
947 #endif
948 }
949 
950 
951 /******************************************************************************
952  *
953  * FUNCTION:    AcpiOsReadPort
954  *
955  * PARAMETERS:  address             Address of I/O port/register to read
956  *              Value               Where value is placed
957  *              width               Number of bits
958  *
959  * RETURN:      Value read from port
960  *
961  * DESCRIPTION: Read data from an I/O port or register
962  *
963  *****************************************************************************/
964 ACPI_STATUS
965 AcpiOsReadPort(ACPI_IO_ADDRESS address, UINT32 *value, UINT32 width)
966 {
967 #ifdef _KERNEL_MODE
968 	DEBUG_FUNCTION_F("addr: 0x%08lx; width: %lu", (addr_t)address, (uint32)width);
969 	switch (width) {
970 		case 8:
971 			*value = gPCIManager->read_io_8(address);
972 			break;
973 
974 		case 16:
975 			*value = gPCIManager->read_io_16(address);
976 			break;
977 
978 		case 32:
979 			*value = gPCIManager->read_io_32(address);
980 			break;
981 
982 		default:
983 			return AE_ERROR;
984 	}
985 
986 	return AE_OK;
987 #else
988 	return AE_ERROR;
989 #endif
990 }
991 
992 
993 /******************************************************************************
994  *
995  * FUNCTION:    AcpiOsWritePort
996  *
997  * PARAMETERS:  address             Address of I/O port/register to write
998  *              value               Value to write
999  *              width               Number of bits
1000  *
1001  * RETURN:      None
1002  *
1003  * DESCRIPTION: Write data to an I/O port or register
1004  *
1005  *****************************************************************************/
1006 ACPI_STATUS
1007 AcpiOsWritePort(ACPI_IO_ADDRESS address, UINT32 value, UINT32 width)
1008 {
1009 #ifdef _KERNEL_MODE
1010 	DEBUG_FUNCTION_F("addr: 0x%08lx; value: %lu; width: %lu",
1011 		(addr_t)address, (uint32)value, (uint32)width);
1012 	switch (width) {
1013 		case 8:
1014 			gPCIManager->write_io_8(address, value);
1015 			break;
1016 
1017 		case 16:
1018 			gPCIManager->write_io_16(address,value);
1019 			break;
1020 
1021 		case 32:
1022 			gPCIManager->write_io_32(address,value);
1023 			break;
1024 
1025 		default:
1026 			return AE_ERROR;
1027 	}
1028 
1029 	return AE_OK;
1030 #else
1031 	return AE_ERROR;
1032 #endif
1033 }
1034 
1035 
1036 /******************************************************************************
1037  *
1038  * FUNCTION:    AcpiOsReadMemory
1039  *
1040  * PARAMETERS:  address             Physical Memory Address to read
1041  *              value               Where value is placed
1042  *              width               Number of bits
1043  *
1044  * RETURN:      Value read from physical memory address
1045  *
1046  * DESCRIPTION: Read data from a physical memory address
1047  *
1048  *****************************************************************************/
1049 ACPI_STATUS
1050 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 *value, UINT32 width)
1051 {
1052 #ifdef _KERNEL_MODE
1053 	if (vm_memcpy_from_physical(value, (phys_addr_t)address, width / 8, false)
1054 		!= B_OK) {
1055 		return AE_ERROR;
1056 	}
1057 	return AE_OK;
1058 #else
1059 	return AE_ERROR;
1060 #endif
1061 }
1062 
1063 
1064 /******************************************************************************
1065  *
1066  * FUNCTION:    AcpiOsWriteMemory
1067  *
1068  * PARAMETERS:  address             Physical Memory Address to write
1069  *              value               Value to write
1070  *              width               Number of bits
1071  *
1072  * RETURN:      None
1073  *
1074  * DESCRIPTION: Write data to a physical memory address
1075  *
1076  *****************************************************************************/
1077 ACPI_STATUS
1078 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 value, UINT32 width)
1079 {
1080 #ifdef _KERNEL_MODE
1081 	if (vm_memcpy_to_physical((phys_addr_t)address, &value, width / 8, false)
1082 			!= B_OK) {
1083 		return AE_ERROR;
1084 	}
1085 	return AE_OK;
1086 #else
1087 	return AE_ERROR;
1088 #endif
1089 }
1090 
1091 
1092 /******************************************************************************
1093  *
1094  * FUNCTION:    AcpiOsReadable
1095  *
1096  * PARAMETERS:  pointer             - Area to be verified
1097  *              length              - Size of area
1098  *
1099  * RETURN:      TRUE if readable for entire length
1100  *
1101  * DESCRIPTION: Verify that a pointer is valid for reading
1102  *
1103  *****************************************************************************/
1104 BOOLEAN
1105 AcpiOsReadable(void *pointer, ACPI_SIZE length)
1106 {
1107 #ifdef _KERNEL_MODE
1108 	return true;
1109 #else
1110 	area_id id;
1111 	area_info info;
1112 
1113 	DEBUG_FUNCTION_F("addr: %p; length: %lu", pointer, (size_t)length);
1114 
1115 	id = area_for(pointer);
1116 	if (id == B_ERROR) return false;
1117 	if (get_area_info(id, &info) != B_OK) return false;
1118 	return (info.protection & B_READ_AREA) != 0 &&
1119 			((char *)pointer) + length <= info.address + info.ram_size;
1120 #endif
1121 }
1122 
1123 
1124 /******************************************************************************
1125  *
1126  * FUNCTION:    AcpiOsWritable
1127  *
1128  * PARAMETERS:  pointer             - Area to be verified
1129  *              length              - Size of area
1130  *
1131  * RETURN:      TRUE if writable for entire length
1132  *
1133  * DESCRIPTION: Verify that a pointer is valid for writing
1134  *
1135  *****************************************************************************/
1136 BOOLEAN
1137 AcpiOsWritable(void *pointer, ACPI_SIZE length)
1138 {
1139 #ifdef _KERNEL_MODE
1140 	return true;
1141 #else
1142 	area_id id;
1143 	area_info info;
1144 
1145 	DEBUG_FUNCTION_F("addr: %p; length: %lu", pointer, (size_t)length);
1146 
1147 	id = area_for(pointer);
1148 	if (id == B_ERROR) return false;
1149 	if (get_area_info(id, &info) != B_OK) return false;
1150 	return (info.protection & B_READ_AREA) != 0 &&
1151 			(info.protection & B_WRITE_AREA) != 0 &&
1152 			((char *)pointer) + length <= info.address + info.ram_size;
1153 #endif
1154 }
1155 
1156 
1157 /******************************************************************************
1158  *
1159  * FUNCTION:    AcpiOsGetThreadId
1160  *
1161  * PARAMETERS:  None
1162  *
1163  * RETURN:      Id of the running thread
1164  *
1165  * DESCRIPTION: Get the Id of the current (running) thread
1166  *
1167  * NOTE:        The environment header should contain this line:
1168  *                  #define ACPI_THREAD_ID pthread_t
1169  *
1170  *****************************************************************************/
1171 ACPI_THREAD_ID
1172 AcpiOsGetThreadId()
1173 {
1174 	thread_id thread = find_thread(NULL);
1175 	// TODO: We arn't allowed threads with id 0, handle this case.
1176 	// ACPI treats a 0 return as an error,
1177 	// but we are thread 0 in early boot
1178 	return thread;
1179 }
1180 
1181 
1182 /******************************************************************************
1183  *
1184  * FUNCTION:    AcpiOsSignal
1185  *
1186  * PARAMETERS:  function            ACPI CA signal function code
1187  *              info                Pointer to function-dependent structure
1188  *
1189  * RETURN:      Status
1190  *
1191  * DESCRIPTION: Miscellaneous functions. Example implementation only.
1192  *
1193  *****************************************************************************/
1194 ACPI_STATUS
1195 AcpiOsSignal(UINT32 function, void *info)
1196 {
1197 	DEBUG_FUNCTION();
1198 
1199 	switch (function) {
1200 		case ACPI_SIGNAL_FATAL:
1201 #ifdef _KERNEL_MODE
1202 			panic("%s", info == NULL ? "AcpiOsSignal: fatal" : (const char*)info);
1203 			break;
1204 #endif
1205 		case ACPI_SIGNAL_BREAKPOINT:
1206 			if (info != NULL)
1207 				AcpiOsPrintf("AcpiOsBreakpoint: %s ****\n", (const char*)info);
1208 			else
1209 				AcpiOsPrintf("At AcpiOsBreakpoint ****\n");
1210 			break;
1211 	}
1212 
1213 	return AE_OK;
1214 }
1215 
1216 
1217 /*
1218  * Adapted from FreeBSD since the documentation of its intended impl
1219  * is lacking.
1220  *  Section 5.2.10.1: global lock acquire/release functions */
1221 #define GL_ACQUIRED     (-1)
1222 #define GL_BUSY         0
1223 #define GL_BIT_PENDING  0x01
1224 #define GL_BIT_OWNED    0x02
1225 #define GL_BIT_MASK     (GL_BIT_PENDING | GL_BIT_OWNED)
1226 
1227 
1228 /*
1229  * Adapted from FreeBSD since the documentation of its intended impl
1230  * is lacking.
1231  * Acquire the global lock.  If busy, set the pending bit.  The caller
1232  * will wait for notification from the BIOS that the lock is available
1233  * and then attempt to acquire it again.
1234  */
1235 int
1236 AcpiOsAcquireGlobalLock(uint32 *lock)
1237 {
1238 	uint32 newValue;
1239 	uint32 oldValue;
1240 
1241 	do {
1242 		oldValue = *lock;
1243 		newValue = ((oldValue & ~GL_BIT_MASK) | GL_BIT_OWNED) |
1244 				((oldValue >> 1) & GL_BIT_PENDING);
1245 		atomic_test_and_set((int32*)lock, newValue, oldValue);
1246 	} while (*lock == oldValue);
1247 	return ((newValue < GL_BIT_MASK) ? GL_ACQUIRED : GL_BUSY);
1248 }
1249 
1250 
1251 /*
1252  * Adapted from FreeBSD since the documentation of its intended impl
1253  * is lacking.
1254  * Release the global lock, returning whether there is a waiter pending.
1255  * If the BIOS set the pending bit, OSPM must notify the BIOS when it
1256  * releases the lock.
1257  */
1258 int
1259 AcpiOsReleaseGlobalLock(uint32 *lock)
1260 {
1261 	uint32 newValue;
1262 	uint32 oldValue;
1263 
1264 	do {
1265 		oldValue = *lock;
1266 		newValue = oldValue & ~GL_BIT_MASK;
1267 		atomic_test_and_set((int32*)lock, newValue, oldValue);
1268 	} while (*lock == oldValue);
1269 	return (oldValue & GL_BIT_PENDING);
1270 }
1271 
1272 
1273 ACPI_STATUS
1274 AcpiOsCreateMutex(ACPI_MUTEX* outHandle)
1275 {
1276 	*outHandle = (ACPI_MUTEX) malloc(sizeof(mutex));
1277 	DEBUG_FUNCTION_F("result: %p", *outHandle);
1278 	if (*outHandle == NULL)
1279 		return AE_NO_MEMORY;
1280 
1281 	mutex_init(*outHandle, "acpi mutex");
1282 	return AE_OK;
1283 }
1284 
1285 
1286 void
1287 AcpiOsDeleteMutex(ACPI_MUTEX handle)
1288 {
1289 	DEBUG_FUNCTION_F("mutex: %ld", (addr_t)handle);
1290 	mutex_destroy(handle);
1291 	free((void*)handle);
1292 }
1293 
1294 
1295 ACPI_STATUS
1296 AcpiOsAcquireMutex(ACPI_MUTEX handle, UINT16 timeout)
1297 {
1298 	ACPI_STATUS result = AE_OK;
1299 	DEBUG_FUNCTION_VF("mutex: %p; timeout: %u", handle, timeout);
1300 
1301 	if (timeout == ACPI_WAIT_FOREVER) {
1302 		result = (mutex_lock(handle) == B_OK) ? AE_OK : AE_BAD_PARAMETER;
1303 	} else if (timeout == ACPI_DO_NOT_WAIT) {
1304 		result = (mutex_trylock(handle) == B_OK) ? AE_OK : AE_TIME;
1305 	} else {
1306 		switch (mutex_lock_with_timeout(handle, B_RELATIVE_TIMEOUT,
1307 			(bigtime_t)timeout * 1000)) {
1308 			case B_OK:
1309 				result = AE_OK;
1310 				break;
1311 			case B_INTERRUPTED:
1312 			case B_TIMED_OUT:
1313 			case B_WOULD_BLOCK:
1314 				result = AE_TIME;
1315 				break;
1316 			case B_BAD_VALUE:
1317 			default:
1318 				result = AE_BAD_PARAMETER;
1319 				break;
1320 		}
1321 	}
1322 	DEBUG_FUNCTION_VF("mutex: %p; timeout: %u result: %lu",
1323 		handle, timeout, (uint32)result);
1324 	return result;
1325 }
1326 
1327 
1328 void
1329 AcpiOsReleaseMutex(ACPI_MUTEX handle)
1330 {
1331 	DEBUG_FUNCTION_F("mutex: %p", handle);
1332 	mutex_unlock(handle);
1333 }
1334 
1335 
1336 /******************************************************************************
1337  *
1338  * FUNCTION:    AcpiOsWaitEventsComplete
1339  *
1340  * PARAMETERS:  None
1341  *
1342  * RETURN:      None
1343  *
1344  * DESCRIPTION: Wait for all asynchronous events to complete. This
1345  *              implementation does nothing.
1346  *
1347  *****************************************************************************/
1348 void
1349 AcpiOsWaitEventsComplete()
1350 {
1351     //TODO: FreeBSD See description.
1352     return;
1353 }
1354 
1355 
1356 /******************************************************************************
1357  *
1358  * FUNCTION:    AcpiOsEnterSleep
1359  *
1360  * PARAMETERS:  SleepState          - Which sleep state to enter
1361  *              RegaValue           - Register A value
1362  *              RegbValue           - Register B value
1363  *
1364  * RETURN:      Status
1365  *
1366  * DESCRIPTION: A hook before writing sleep registers to enter the sleep
1367  *              state. Return AE_CTRL_TERMINATE to skip further sleep register
1368  *              writes.
1369  *
1370  *****************************************************************************/
1371 
1372 ACPI_STATUS
1373 AcpiOsEnterSleep (
1374 	UINT8                   SleepState,
1375 	UINT32                  RegaValue,
1376 	UINT32                  RegbValue)
1377 {
1378 	return (AE_OK);
1379 }
1380