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