xref: /haiku/src/add-ons/kernel/bus_managers/acpi/ACPICAHaiku.cpp (revision bb83316a5811a550c4f850d07fa8e328e7ac0a94)
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  
146  ACPI_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
179  extern pci_module_info *gPCIManager;
180  extern dpc_module_info *gDPC;
181  extern void *gDPCHandle;
182  #endif
183  
184  extern FILE *AcpiGbl_DebugFile;
185  FILE *AcpiGbl_OutputFile;
186  
187  static ACPI_PHYSICAL_ADDRESS sACPIRoot = 0;
188  static 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   *****************************************************************************/
202  ACPI_STATUS
203  AcpiOsInitialize()
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  
215  ACPI_STATUS
216  AcpiOsTerminate()
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   *****************************************************************************/
234  ACPI_PHYSICAL_ADDRESS
235  AcpiOsGetRootPointer()
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   *****************************************************************************/
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: %" 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   *****************************************************************************/
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: %" 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   *****************************************************************************/
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: %" 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   *****************************************************************************/
593  ACPI_STATUS
594  AcpiOsDeleteSemaphore(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   *****************************************************************************/
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: %" 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   *****************************************************************************/
768  ACPI_STATUS
769  AcpiOsRemoveInterruptHandler(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   *****************************************************************************/
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: %" 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   *****************************************************************************/
854  void
855  AcpiOsSleep(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   *****************************************************************************/
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: %" 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   *****************************************************************************/
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: %" 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   *****************************************************************************/
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  
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   */
1229  int
1230  AcpiOsAcquireGlobalLock(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   */
1253  int
1254  AcpiOsReleaseGlobalLock(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  
1268  ACPI_STATUS
1269  AcpiOsCreateMutex(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  
1281  void
1282  AcpiOsDeleteMutex(ACPI_MUTEX handle)
1283  {
1284  	DEBUG_FUNCTION_F("mutex: %ld", (addr_t)handle);
1285  	mutex_destroy(handle);
1286  	free((void*)handle);
1287  }
1288  
1289  
1290  ACPI_STATUS
1291  AcpiOsAcquireMutex(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  
1323  void
1324  AcpiOsReleaseMutex(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   *****************************************************************************/
1343  void
1344  AcpiOsWaitEventsComplete()
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  
1367  ACPI_STATUS
1368  AcpiOsEnterSleep (
1369  	UINT8                   SleepState,
1370  	UINT32                  RegaValue,
1371  	UINT32                  RegbValue)
1372  {
1373  	return (AE_OK);
1374  }
1375