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#include "arch_init.h"
144
145
146ACPI_MODULE_NAME("Haiku ACPI Module")
147
148#define _COMPONENT ACPI_OS_SERVICES
149
150// verbosity level 0 = off, 1 = normal, 2 = all
151#define DEBUG_OSHAIKU 0
152
153#if DEBUG_OSHAIKU <= 0
154// No debugging, do nothing
155#	define DEBUG_FUNCTION()
156#	define DEBUG_FUNCTION_F(x, y...)
157#	define DEBUG_FUNCTION_V()
158#	define DEBUG_FUNCTION_VF(x, y...)
159#else
160#	define DEBUG_FUNCTION() \
161		dprintf("acpi[%" B_PRId32 "]: %s\n", find_thread(NULL), __PRETTY_FUNCTION__);
162#	define DEBUG_FUNCTION_F(x, y...) \
163		dprintf("acpi[%" B_PRId32 "]: %s(" x ")\n", find_thread(NULL), __PRETTY_FUNCTION__, y);
164#	if DEBUG_OSHAIKU == 1
165// No verbose debugging, do nothing
166#		define DEBUG_FUNCTION_V()
167#		define DEBUG_FUNCTION_VF(x, y...)
168#	else
169// Full debugging
170#		define DEBUG_FUNCTION_V() \
171			dprintf("acpi[%" B_PRId32 "]: %s\n", find_thread(NULL), __PRETTY_FUNCTION__);
172#		define DEBUG_FUNCTION_VF(x, y...) \
173			dprintf("acpi[%" B_PRId32 "]: %s(" x ")\n", find_thread(NULL), __PRETTY_FUNCTION__, y);
174#	endif
175#endif
176
177
178#ifdef _KERNEL_MODE
179extern pci_module_info *gPCIManager;
180extern dpc_module_info *gDPC;
181extern void *gDPCHandle;
182#endif
183
184extern FILE *AcpiGbl_DebugFile;
185FILE *AcpiGbl_OutputFile;
186
187static ACPI_PHYSICAL_ADDRESS sACPIRoot = 0;
188static void *sInterruptHandlerData[32];
189
190
191/******************************************************************************
192 *
193 * FUNCTION:    AcpiOsInitialize, AcpiOsTerminate
194 *
195 * PARAMETERS:  None
196 *
197 * RETURN:      Status
198 *
199 * DESCRIPTION: Init and terminate.  Nothing to do.
200 *
201 *****************************************************************************/
202ACPI_STATUS
203AcpiOsInitialize()
204{
205#ifndef _KERNEL_MODE
206	AcpiGbl_OutputFile = stdout;
207#else
208	AcpiGbl_OutputFile = NULL;
209#endif
210	DEBUG_FUNCTION();
211	return AE_OK;
212}
213
214
215ACPI_STATUS
216AcpiOsTerminate()
217{
218	DEBUG_FUNCTION();
219	return AE_OK;
220}
221
222
223/******************************************************************************
224 *
225 * FUNCTION:    AcpiOsGetRootPointer
226 *
227 * PARAMETERS:  None
228 *
229 * RETURN:      RSDP physical address
230 *
231 * DESCRIPTION: Gets the root pointer (RSDP)
232 *
233 *****************************************************************************/
234ACPI_PHYSICAL_ADDRESS
235AcpiOsGetRootPointer()
236{
237#ifdef _KERNEL_MODE
238	DEBUG_FUNCTION();
239	if (sACPIRoot == 0) {
240		phys_addr_t* acpiRootPointer = (phys_addr_t*)get_boot_item("ACPI_ROOT_POINTER", NULL);
241		if (acpiRootPointer != NULL)
242			sACPIRoot = *acpiRootPointer;
243
244		if (sACPIRoot == 0)
245			sACPIRoot = arch_init_find_root_pointer();
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 *****************************************************************************/
267ACPI_STATUS
268AcpiOsPredefinedOverride(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 *****************************************************************************/
293ACPI_STATUS
294AcpiOsTableOverride(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
328ACPI_STATUS
329AcpiOsPhysicalTableOverride(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 *****************************************************************************/
348void
349AcpiOsRedirectOutput(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 *****************************************************************************/
367void ACPI_INTERNAL_VAR_XFACE
368AcpiOsPrintf(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 *****************************************************************************/
391void
392AcpiOsVprintf(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 *****************************************************************************/
432UINT32
433AcpiOsGetLine(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: %" B_PRIu32, 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 *****************************************************************************/
467void *
468AcpiOsMapMemory(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: %" B_PRId32,
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 *****************************************************************************/
505void
506AcpiOsUnmapMemory(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 *****************************************************************************/
524void *
525AcpiOsAllocate(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 *****************************************************************************/
544void
545AcpiOsFree(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 *****************************************************************************/
564ACPI_STATUS
565AcpiOsCreateSemaphore(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: %" B_PRIu32 "; count: %" B_PRIu32 "; result: %" PRId32,
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 *****************************************************************************/
593ACPI_STATUS
594AcpiOsDeleteSemaphore(ACPI_SEMAPHORE handle)
595{
596	DEBUG_FUNCTION_F("sem: %" B_PRId32, 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 *****************************************************************************/
614ACPI_STATUS
615AcpiOsWaitSemaphore(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 *****************************************************************************/
659ACPI_STATUS
660AcpiOsSignalSemaphore(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 *****************************************************************************/
677ACPI_STATUS
678AcpiOsCreateLock(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
690void
691AcpiOsDeleteLock(ACPI_SPINLOCK handle)
692{
693	DEBUG_FUNCTION();
694	free((void*)handle);
695}
696
697
698ACPI_CPU_FLAGS
699AcpiOsAcquireLock(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
709void
710AcpiOsReleaseLock(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 *****************************************************************************/
732UINT32
733AcpiOsInstallInterruptHandler(UINT32 interruptNumber,
734		ACPI_OSD_HANDLER serviceRoutine, void *context)
735{
736	status_t result;
737	DEBUG_FUNCTION_F("vector: %" B_PRIu32 "; 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: %" B_PRIu32 "; handler: %p context %p returned %" B_PRId32,
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 *****************************************************************************/
768ACPI_STATUS
769AcpiOsRemoveInterruptHandler(UINT32 interruptNumber,
770		ACPI_OSD_HANDLER serviceRoutine)
771{
772	DEBUG_FUNCTION_F("vector: %" B_PRIu32 "; 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 *****************************************************************************/
797ACPI_STATUS
798AcpiOsExecute(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 *****************************************************************************/
834void
835AcpiOsStall(UINT32 microseconds)
836{
837	DEBUG_FUNCTION_F("microseconds: %" B_PRIu32, (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 *****************************************************************************/
854void
855AcpiOsSleep(ACPI_INTEGER milliseconds)
856{
857	DEBUG_FUNCTION_F("milliseconds: %" B_PRIu32, (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 *****************************************************************************/
876UINT64
877AcpiOsGetTimer()
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 *****************************************************************************/
898ACPI_STATUS
899AcpiOsReadPciConfiguration(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 *****************************************************************************/
936ACPI_STATUS
937AcpiOsWritePciConfiguration(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 *****************************************************************************/
964ACPI_STATUS
965AcpiOsReadPort(ACPI_IO_ADDRESS address, UINT32 *value, UINT32 width)
966{
967#ifdef _KERNEL_MODE
968	DEBUG_FUNCTION_F("addr: 0x%08lx; width: %" B_PRIu32, (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 *****************************************************************************/
1006ACPI_STATUS
1007AcpiOsWritePort(ACPI_IO_ADDRESS address, UINT32 value, UINT32 width)
1008{
1009#ifdef _KERNEL_MODE
1010	DEBUG_FUNCTION_F("addr: 0x%08lx; value: %" B_PRIu32 "; width: %" B_PRIu32,
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 *****************************************************************************/
1049ACPI_STATUS
1050AcpiOsReadMemory(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 *****************************************************************************/
1077ACPI_STATUS
1078AcpiOsWriteMemory(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 *****************************************************************************/
1104BOOLEAN
1105AcpiOsReadable(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 *****************************************************************************/
1136BOOLEAN
1137AcpiOsWritable(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 *****************************************************************************/
1171ACPI_THREAD_ID
1172AcpiOsGetThreadId()
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 *****************************************************************************/
1194ACPI_STATUS
1195AcpiOsSignal(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
1222/*
1223 * Adapted from FreeBSD since the documentation of its intended impl
1224 * is lacking.
1225 * Acquire the global lock.  If busy, set the pending bit.  The caller
1226 * will wait for notification from the BIOS that the lock is available
1227 * and then attempt to acquire it again.
1228 */
1229int
1230AcpiOsAcquireGlobalLock(volatile uint32_t *lock)
1231{
1232	uint32_t newValue;
1233	uint32_t oldValue;
1234
1235	do {
1236		oldValue = *lock;
1237		newValue = ((oldValue & ~ACPI_GLOCK_PENDING) | ACPI_GLOCK_OWNED);
1238		if ((oldValue & ACPI_GLOCK_OWNED) != 0)
1239			newValue |= ACPI_GLOCK_PENDING;
1240	} while (atomic_test_and_set((int32*)lock, newValue, oldValue) != (int32)oldValue);
1241
1242	return (newValue & ACPI_GLOCK_PENDING) == 0;
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(volatile uint32_t *lock)
1255{
1256	uint32 newValue;
1257	uint32 oldValue;
1258
1259	do {
1260		oldValue = *lock;
1261		newValue = oldValue & ~(ACPI_GLOCK_PENDING | ACPI_GLOCK_OWNED);
1262	} while (atomic_test_and_set((int32*)lock, newValue, oldValue) != (int32)oldValue);
1263
1264	return (oldValue & ACPI_GLOCK_PENDING) != 0;
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", (addr_t)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: %p; 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 if (timeout == ACPI_DO_NOT_WAIT) {
1299		result = (mutex_trylock(handle) == B_OK) ? AE_OK : AE_TIME;
1300	} else {
1301		switch (mutex_lock_with_timeout(handle, B_RELATIVE_TIMEOUT,
1302			(bigtime_t)timeout * 1000)) {
1303			case B_OK:
1304				result = AE_OK;
1305				break;
1306			case B_INTERRUPTED:
1307			case B_TIMED_OUT:
1308			case B_WOULD_BLOCK:
1309				result = AE_TIME;
1310				break;
1311			case B_BAD_VALUE:
1312			default:
1313				result = AE_BAD_PARAMETER;
1314				break;
1315		}
1316	}
1317	DEBUG_FUNCTION_VF("mutex: %p; timeout: %u result: %lu",
1318		handle, timeout, (uint32)result);
1319	return result;
1320}
1321
1322
1323void
1324AcpiOsReleaseMutex(ACPI_MUTEX handle)
1325{
1326	DEBUG_FUNCTION_F("mutex: %p", handle);
1327	mutex_unlock(handle);
1328}
1329
1330
1331/******************************************************************************
1332 *
1333 * FUNCTION:    AcpiOsWaitEventsComplete
1334 *
1335 * PARAMETERS:  None
1336 *
1337 * RETURN:      None
1338 *
1339 * DESCRIPTION: Wait for all asynchronous events to complete. This
1340 *              implementation does nothing.
1341 *
1342 *****************************************************************************/
1343void
1344AcpiOsWaitEventsComplete()
1345{
1346    //TODO: FreeBSD See description.
1347    return;
1348}
1349
1350
1351/******************************************************************************
1352 *
1353 * FUNCTION:    AcpiOsEnterSleep
1354 *
1355 * PARAMETERS:  SleepState          - Which sleep state to enter
1356 *              RegaValue           - Register A value
1357 *              RegbValue           - Register B value
1358 *
1359 * RETURN:      Status
1360 *
1361 * DESCRIPTION: A hook before writing sleep registers to enter the sleep
1362 *              state. Return AE_CTRL_TERMINATE to skip further sleep register
1363 *              writes.
1364 *
1365 *****************************************************************************/
1366
1367ACPI_STATUS
1368AcpiOsEnterSleep (
1369	UINT8                   SleepState,
1370	UINT32                  RegaValue,
1371	UINT32                  RegbValue)
1372{
1373	return (AE_OK);
1374}
1375