1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Module Name: osunixxf - UNIX OSL interfaces |
5 | * |
6 | * Copyright (C) 2000 - 2023, Intel Corp. |
7 | * |
8 | *****************************************************************************/ |
9 | |
10 | /* |
11 | * These interfaces are required in order to compile the ASL compiler and the |
12 | * various ACPICA tools under Linux or other Unix-like system. |
13 | */ |
14 | #include <acpi/acpi.h> |
15 | #include "accommon.h" |
16 | #include "amlcode.h" |
17 | #include "acparser.h" |
18 | #include "acdebug.h" |
19 | |
20 | #include <stdio.h> |
21 | #include <stdlib.h> |
22 | #include <stdarg.h> |
23 | #include <unistd.h> |
24 | #include <sys/time.h> |
25 | #include <semaphore.h> |
26 | #include <pthread.h> |
27 | #include <errno.h> |
28 | |
29 | #define _COMPONENT ACPI_OS_SERVICES |
30 | ACPI_MODULE_NAME("osunixxf" ) |
31 | |
32 | /* Upcalls to acpi_exec */ |
33 | void |
34 | ae_table_override(struct acpi_table_header *existing_table, |
35 | struct acpi_table_header **new_table); |
36 | |
37 | typedef void *(*PTHREAD_CALLBACK) (void *); |
38 | |
39 | /* Buffer used by acpi_os_vprintf */ |
40 | |
41 | #define ACPI_VPRINTF_BUFFER_SIZE 512 |
42 | #define _ASCII_NEWLINE '\n' |
43 | |
44 | /* Terminal support for acpi_exec only */ |
45 | |
46 | #ifdef ACPI_EXEC_APP |
47 | #include <termios.h> |
48 | |
49 | struct termios original_term_attributes; |
50 | int term_attributes_were_set = 0; |
51 | |
52 | acpi_status acpi_ut_read_line(char *buffer, u32 buffer_length, u32 *bytes_read); |
53 | |
54 | static void os_enter_line_edit_mode(void); |
55 | |
56 | static void os_exit_line_edit_mode(void); |
57 | |
58 | /****************************************************************************** |
59 | * |
60 | * FUNCTION: os_enter_line_edit_mode, os_exit_line_edit_mode |
61 | * |
62 | * PARAMETERS: None |
63 | * |
64 | * RETURN: None |
65 | * |
66 | * DESCRIPTION: Enter/Exit the raw character input mode for the terminal. |
67 | * |
68 | * Interactive line-editing support for the AML debugger. Used with the |
69 | * common/acgetline module. |
70 | * |
71 | * readline() is not used because of non-portability. It is not available |
72 | * on all systems, and if it is, often the package must be manually installed. |
73 | * |
74 | * Therefore, we use the POSIX tcgetattr/tcsetattr and do the minimal line |
75 | * editing that we need in acpi_os_get_line. |
76 | * |
77 | * If the POSIX tcgetattr/tcsetattr interfaces are unavailable, these |
78 | * calls will also work: |
79 | * For os_enter_line_edit_mode: system ("stty cbreak -echo") |
80 | * For os_exit_line_edit_mode: system ("stty cooked echo") |
81 | * |
82 | *****************************************************************************/ |
83 | |
84 | static void os_enter_line_edit_mode(void) |
85 | { |
86 | struct termios local_term_attributes; |
87 | |
88 | term_attributes_were_set = 0; |
89 | |
90 | /* STDIN must be a terminal */ |
91 | |
92 | if (!isatty(STDIN_FILENO)) { |
93 | return; |
94 | } |
95 | |
96 | /* Get and keep the original attributes */ |
97 | |
98 | if (tcgetattr(STDIN_FILENO, &original_term_attributes)) { |
99 | fprintf(stderr, "Could not get terminal attributes!\n" ); |
100 | return; |
101 | } |
102 | |
103 | /* Set the new attributes to enable raw character input */ |
104 | |
105 | memcpy(&local_term_attributes, &original_term_attributes, |
106 | sizeof(struct termios)); |
107 | |
108 | local_term_attributes.c_lflag &= ~(ICANON | ECHO); |
109 | local_term_attributes.c_cc[VMIN] = 1; |
110 | local_term_attributes.c_cc[VTIME] = 0; |
111 | |
112 | if (tcsetattr(STDIN_FILENO, TCSANOW, &local_term_attributes)) { |
113 | fprintf(stderr, "Could not set terminal attributes!\n" ); |
114 | return; |
115 | } |
116 | |
117 | term_attributes_were_set = 1; |
118 | } |
119 | |
120 | static void os_exit_line_edit_mode(void) |
121 | { |
122 | |
123 | if (!term_attributes_were_set) { |
124 | return; |
125 | } |
126 | |
127 | /* Set terminal attributes back to the original values */ |
128 | |
129 | if (tcsetattr(STDIN_FILENO, TCSANOW, &original_term_attributes)) { |
130 | fprintf(stderr, "Could not restore terminal attributes!\n" ); |
131 | } |
132 | } |
133 | |
134 | #else |
135 | |
136 | /* These functions are not needed for other ACPICA utilities */ |
137 | |
138 | #define os_enter_line_edit_mode() |
139 | #define os_exit_line_edit_mode() |
140 | #endif |
141 | |
142 | /****************************************************************************** |
143 | * |
144 | * FUNCTION: acpi_os_initialize, acpi_os_terminate |
145 | * |
146 | * PARAMETERS: None |
147 | * |
148 | * RETURN: Status |
149 | * |
150 | * DESCRIPTION: Initialize and terminate this module. |
151 | * |
152 | *****************************************************************************/ |
153 | |
154 | acpi_status acpi_os_initialize(void) |
155 | { |
156 | acpi_status status; |
157 | |
158 | acpi_gbl_output_file = stdout; |
159 | |
160 | os_enter_line_edit_mode(); |
161 | |
162 | status = acpi_os_create_lock(&acpi_gbl_print_lock); |
163 | if (ACPI_FAILURE(status)) { |
164 | return (status); |
165 | } |
166 | |
167 | return (AE_OK); |
168 | } |
169 | |
170 | acpi_status acpi_os_terminate(void) |
171 | { |
172 | |
173 | os_exit_line_edit_mode(); |
174 | return (AE_OK); |
175 | } |
176 | |
177 | #ifndef ACPI_USE_NATIVE_RSDP_POINTER |
178 | /****************************************************************************** |
179 | * |
180 | * FUNCTION: acpi_os_get_root_pointer |
181 | * |
182 | * PARAMETERS: None |
183 | * |
184 | * RETURN: RSDP physical address |
185 | * |
186 | * DESCRIPTION: Gets the ACPI root pointer (RSDP) |
187 | * |
188 | *****************************************************************************/ |
189 | |
190 | acpi_physical_address acpi_os_get_root_pointer(void) |
191 | { |
192 | |
193 | return (0); |
194 | } |
195 | #endif |
196 | |
197 | /****************************************************************************** |
198 | * |
199 | * FUNCTION: acpi_os_predefined_override |
200 | * |
201 | * PARAMETERS: init_val - Initial value of the predefined object |
202 | * new_val - The new value for the object |
203 | * |
204 | * RETURN: Status, pointer to value. Null pointer returned if not |
205 | * overriding. |
206 | * |
207 | * DESCRIPTION: Allow the OS to override predefined names |
208 | * |
209 | *****************************************************************************/ |
210 | |
211 | acpi_status |
212 | acpi_os_predefined_override(const struct acpi_predefined_names *init_val, |
213 | acpi_string *new_val) |
214 | { |
215 | |
216 | if (!init_val || !new_val) { |
217 | return (AE_BAD_PARAMETER); |
218 | } |
219 | |
220 | *new_val = NULL; |
221 | return (AE_OK); |
222 | } |
223 | |
224 | /****************************************************************************** |
225 | * |
226 | * FUNCTION: acpi_os_table_override |
227 | * |
228 | * PARAMETERS: existing_table - Header of current table (probably |
229 | * firmware) |
230 | * new_table - Where an entire new table is returned. |
231 | * |
232 | * RETURN: Status, pointer to new table. Null pointer returned if no |
233 | * table is available to override |
234 | * |
235 | * DESCRIPTION: Return a different version of a table if one is available |
236 | * |
237 | *****************************************************************************/ |
238 | |
239 | acpi_status |
240 | acpi_os_table_override(struct acpi_table_header *existing_table, |
241 | struct acpi_table_header **new_table) |
242 | { |
243 | |
244 | if (!existing_table || !new_table) { |
245 | return (AE_BAD_PARAMETER); |
246 | } |
247 | |
248 | *new_table = NULL; |
249 | |
250 | #ifdef ACPI_EXEC_APP |
251 | |
252 | ae_table_override(existing_table, new_table); |
253 | return (AE_OK); |
254 | #else |
255 | |
256 | return (AE_NO_ACPI_TABLES); |
257 | #endif |
258 | } |
259 | |
260 | /****************************************************************************** |
261 | * |
262 | * FUNCTION: acpi_os_physical_table_override |
263 | * |
264 | * PARAMETERS: existing_table - Header of current table (probably firmware) |
265 | * new_address - Where new table address is returned |
266 | * (Physical address) |
267 | * new_table_length - Where new table length is returned |
268 | * |
269 | * RETURN: Status, address/length of new table. Null pointer returned |
270 | * if no table is available to override. |
271 | * |
272 | * DESCRIPTION: Returns AE_SUPPORT, function not used in user space. |
273 | * |
274 | *****************************************************************************/ |
275 | |
276 | acpi_status |
277 | acpi_os_physical_table_override(struct acpi_table_header *existing_table, |
278 | acpi_physical_address *new_address, |
279 | u32 *new_table_length) |
280 | { |
281 | |
282 | return (AE_SUPPORT); |
283 | } |
284 | |
285 | /****************************************************************************** |
286 | * |
287 | * FUNCTION: acpi_os_enter_sleep |
288 | * |
289 | * PARAMETERS: sleep_state - Which sleep state to enter |
290 | * rega_value - Register A value |
291 | * regb_value - Register B value |
292 | * |
293 | * RETURN: Status |
294 | * |
295 | * DESCRIPTION: A hook before writing sleep registers to enter the sleep |
296 | * state. Return AE_CTRL_TERMINATE to skip further sleep register |
297 | * writes. |
298 | * |
299 | *****************************************************************************/ |
300 | |
301 | acpi_status acpi_os_enter_sleep(u8 sleep_state, u32 rega_value, u32 regb_value) |
302 | { |
303 | |
304 | return (AE_OK); |
305 | } |
306 | |
307 | /****************************************************************************** |
308 | * |
309 | * FUNCTION: acpi_os_redirect_output |
310 | * |
311 | * PARAMETERS: destination - An open file handle/pointer |
312 | * |
313 | * RETURN: None |
314 | * |
315 | * DESCRIPTION: Causes redirect of acpi_os_printf and acpi_os_vprintf |
316 | * |
317 | *****************************************************************************/ |
318 | |
319 | void acpi_os_redirect_output(void *destination) |
320 | { |
321 | |
322 | acpi_gbl_output_file = destination; |
323 | } |
324 | |
325 | /****************************************************************************** |
326 | * |
327 | * FUNCTION: acpi_os_printf |
328 | * |
329 | * PARAMETERS: fmt, ... - Standard printf format |
330 | * |
331 | * RETURN: None |
332 | * |
333 | * DESCRIPTION: Formatted output. Note: very similar to acpi_os_vprintf |
334 | * (performance), changes should be tracked in both functions. |
335 | * |
336 | *****************************************************************************/ |
337 | |
338 | void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *fmt, ...) |
339 | { |
340 | va_list args; |
341 | u8 flags; |
342 | |
343 | flags = acpi_gbl_db_output_flags; |
344 | if (flags & ACPI_DB_REDIRECTABLE_OUTPUT) { |
345 | |
346 | /* Output is directable to either a file (if open) or the console */ |
347 | |
348 | if (acpi_gbl_debug_file) { |
349 | |
350 | /* Output file is open, send the output there */ |
351 | |
352 | va_start(args, fmt); |
353 | vfprintf(acpi_gbl_debug_file, fmt, args); |
354 | va_end(args); |
355 | } else { |
356 | /* No redirection, send output to console (once only!) */ |
357 | |
358 | flags |= ACPI_DB_CONSOLE_OUTPUT; |
359 | } |
360 | } |
361 | |
362 | if (flags & ACPI_DB_CONSOLE_OUTPUT) { |
363 | va_start(args, fmt); |
364 | vfprintf(acpi_gbl_output_file, fmt, args); |
365 | va_end(args); |
366 | } |
367 | } |
368 | |
369 | /****************************************************************************** |
370 | * |
371 | * FUNCTION: acpi_os_vprintf |
372 | * |
373 | * PARAMETERS: fmt - Standard printf format |
374 | * args - Argument list |
375 | * |
376 | * RETURN: None |
377 | * |
378 | * DESCRIPTION: Formatted output with argument list pointer. Note: very |
379 | * similar to acpi_os_printf, changes should be tracked in both |
380 | * functions. |
381 | * |
382 | *****************************************************************************/ |
383 | |
384 | void acpi_os_vprintf(const char *fmt, va_list args) |
385 | { |
386 | u8 flags; |
387 | char buffer[ACPI_VPRINTF_BUFFER_SIZE]; |
388 | |
389 | /* |
390 | * We build the output string in a local buffer because we may be |
391 | * outputting the buffer twice. Using vfprintf is problematic because |
392 | * some implementations modify the args pointer/structure during |
393 | * execution. Thus, we use the local buffer for portability. |
394 | * |
395 | * Note: Since this module is intended for use by the various ACPICA |
396 | * utilities/applications, we can safely declare the buffer on the stack. |
397 | * Also, This function is used for relatively small error messages only. |
398 | */ |
399 | vsnprintf(buf: buffer, ACPI_VPRINTF_BUFFER_SIZE, fmt, args); |
400 | |
401 | flags = acpi_gbl_db_output_flags; |
402 | if (flags & ACPI_DB_REDIRECTABLE_OUTPUT) { |
403 | |
404 | /* Output is directable to either a file (if open) or the console */ |
405 | |
406 | if (acpi_gbl_debug_file) { |
407 | |
408 | /* Output file is open, send the output there */ |
409 | |
410 | fputs(buffer, acpi_gbl_debug_file); |
411 | } else { |
412 | /* No redirection, send output to console (once only!) */ |
413 | |
414 | flags |= ACPI_DB_CONSOLE_OUTPUT; |
415 | } |
416 | } |
417 | |
418 | if (flags & ACPI_DB_CONSOLE_OUTPUT) { |
419 | fputs(buffer, acpi_gbl_output_file); |
420 | } |
421 | } |
422 | |
423 | #ifndef ACPI_EXEC_APP |
424 | /****************************************************************************** |
425 | * |
426 | * FUNCTION: acpi_os_get_line |
427 | * |
428 | * PARAMETERS: buffer - Where to return the command line |
429 | * buffer_length - Maximum length of Buffer |
430 | * bytes_read - Where the actual byte count is returned |
431 | * |
432 | * RETURN: Status and actual bytes read |
433 | * |
434 | * DESCRIPTION: Get the next input line from the terminal. NOTE: For the |
435 | * acpi_exec utility, we use the acgetline module instead to |
436 | * provide line-editing and history support. |
437 | * |
438 | *****************************************************************************/ |
439 | |
440 | acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read) |
441 | { |
442 | int input_char; |
443 | u32 end_of_line; |
444 | |
445 | /* Standard acpi_os_get_line for all utilities except acpi_exec */ |
446 | |
447 | for (end_of_line = 0;; end_of_line++) { |
448 | if (end_of_line >= buffer_length) { |
449 | return (AE_BUFFER_OVERFLOW); |
450 | } |
451 | |
452 | if ((input_char = getchar()) == EOF) { |
453 | return (AE_ERROR); |
454 | } |
455 | |
456 | if (!input_char || input_char == _ASCII_NEWLINE) { |
457 | break; |
458 | } |
459 | |
460 | buffer[end_of_line] = (char)input_char; |
461 | } |
462 | |
463 | /* Null terminate the buffer */ |
464 | |
465 | buffer[end_of_line] = 0; |
466 | |
467 | /* Return the number of bytes in the string */ |
468 | |
469 | if (bytes_read) { |
470 | *bytes_read = end_of_line; |
471 | } |
472 | |
473 | return (AE_OK); |
474 | } |
475 | #endif |
476 | |
477 | #ifndef ACPI_USE_NATIVE_MEMORY_MAPPING |
478 | /****************************************************************************** |
479 | * |
480 | * FUNCTION: acpi_os_map_memory |
481 | * |
482 | * PARAMETERS: where - Physical address of memory to be mapped |
483 | * length - How much memory to map |
484 | * |
485 | * RETURN: Pointer to mapped memory. Null on error. |
486 | * |
487 | * DESCRIPTION: Map physical memory into caller's address space |
488 | * |
489 | *****************************************************************************/ |
490 | |
491 | void *acpi_os_map_memory(acpi_physical_address where, acpi_size length) |
492 | { |
493 | |
494 | return (ACPI_TO_POINTER((acpi_size)where)); |
495 | } |
496 | |
497 | /****************************************************************************** |
498 | * |
499 | * FUNCTION: acpi_os_unmap_memory |
500 | * |
501 | * PARAMETERS: where - Logical address of memory to be unmapped |
502 | * length - How much memory to unmap |
503 | * |
504 | * RETURN: None. |
505 | * |
506 | * DESCRIPTION: Delete a previously created mapping. Where and Length must |
507 | * correspond to a previous mapping exactly. |
508 | * |
509 | *****************************************************************************/ |
510 | |
511 | void acpi_os_unmap_memory(void *where, acpi_size length) |
512 | { |
513 | |
514 | return; |
515 | } |
516 | #endif |
517 | |
518 | /****************************************************************************** |
519 | * |
520 | * FUNCTION: acpi_os_allocate |
521 | * |
522 | * PARAMETERS: size - Amount to allocate, in bytes |
523 | * |
524 | * RETURN: Pointer to the new allocation. Null on error. |
525 | * |
526 | * DESCRIPTION: Allocate memory. Algorithm is dependent on the OS. |
527 | * |
528 | *****************************************************************************/ |
529 | |
530 | void *acpi_os_allocate(acpi_size size) |
531 | { |
532 | void *mem; |
533 | |
534 | mem = (void *)malloc((size_t) size); |
535 | return (mem); |
536 | } |
537 | |
538 | #ifdef USE_NATIVE_ALLOCATE_ZEROED |
539 | /****************************************************************************** |
540 | * |
541 | * FUNCTION: acpi_os_allocate_zeroed |
542 | * |
543 | * PARAMETERS: size - Amount to allocate, in bytes |
544 | * |
545 | * RETURN: Pointer to the new allocation. Null on error. |
546 | * |
547 | * DESCRIPTION: Allocate and zero memory. Algorithm is dependent on the OS. |
548 | * |
549 | *****************************************************************************/ |
550 | |
551 | void *acpi_os_allocate_zeroed(acpi_size size) |
552 | { |
553 | void *mem; |
554 | |
555 | mem = (void *)calloc(1, (size_t) size); |
556 | return (mem); |
557 | } |
558 | #endif |
559 | |
560 | /****************************************************************************** |
561 | * |
562 | * FUNCTION: acpi_os_free |
563 | * |
564 | * PARAMETERS: mem - Pointer to previously allocated memory |
565 | * |
566 | * RETURN: None. |
567 | * |
568 | * DESCRIPTION: Free memory allocated via acpi_os_allocate |
569 | * |
570 | *****************************************************************************/ |
571 | |
572 | void acpi_os_free(void *mem) |
573 | { |
574 | |
575 | free(mem); |
576 | } |
577 | |
578 | #ifdef ACPI_SINGLE_THREADED |
579 | /****************************************************************************** |
580 | * |
581 | * FUNCTION: Semaphore stub functions |
582 | * |
583 | * DESCRIPTION: Stub functions used for single-thread applications that do |
584 | * not require semaphore synchronization. Full implementations |
585 | * of these functions appear after the stubs. |
586 | * |
587 | *****************************************************************************/ |
588 | |
589 | acpi_status |
590 | acpi_os_create_semaphore(u32 max_units, |
591 | u32 initial_units, acpi_handle *out_handle) |
592 | { |
593 | *out_handle = (acpi_handle)1; |
594 | return (AE_OK); |
595 | } |
596 | |
597 | acpi_status acpi_os_delete_semaphore(acpi_handle handle) |
598 | { |
599 | return (AE_OK); |
600 | } |
601 | |
602 | acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) |
603 | { |
604 | return (AE_OK); |
605 | } |
606 | |
607 | acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) |
608 | { |
609 | return (AE_OK); |
610 | } |
611 | |
612 | #else |
613 | /****************************************************************************** |
614 | * |
615 | * FUNCTION: acpi_os_create_semaphore |
616 | * |
617 | * PARAMETERS: initial_units - Units to be assigned to the new semaphore |
618 | * out_handle - Where a handle will be returned |
619 | * |
620 | * RETURN: Status |
621 | * |
622 | * DESCRIPTION: Create an OS semaphore |
623 | * |
624 | *****************************************************************************/ |
625 | |
626 | acpi_status |
627 | acpi_os_create_semaphore(u32 max_units, |
628 | u32 initial_units, acpi_handle *out_handle) |
629 | { |
630 | sem_t *sem; |
631 | |
632 | if (!out_handle) { |
633 | return (AE_BAD_PARAMETER); |
634 | } |
635 | #ifdef __APPLE__ |
636 | { |
637 | static int semaphore_count = 0; |
638 | char semaphore_name[32]; |
639 | |
640 | snprintf(semaphore_name, sizeof(semaphore_name), "acpi_sem_%d" , |
641 | semaphore_count++); |
642 | printf("%s\n" , semaphore_name); |
643 | sem = |
644 | sem_open(semaphore_name, O_EXCL | O_CREAT, 0755, |
645 | initial_units); |
646 | if (!sem) { |
647 | return (AE_NO_MEMORY); |
648 | } |
649 | sem_unlink(semaphore_name); /* This just deletes the name */ |
650 | } |
651 | |
652 | #else |
653 | sem = acpi_os_allocate(sizeof(sem_t)); |
654 | if (!sem) { |
655 | return (AE_NO_MEMORY); |
656 | } |
657 | |
658 | if (sem_init(sem, 0, initial_units) == -1) { |
659 | acpi_os_free(sem); |
660 | return (AE_BAD_PARAMETER); |
661 | } |
662 | #endif |
663 | |
664 | *out_handle = (acpi_handle)sem; |
665 | return (AE_OK); |
666 | } |
667 | |
668 | /****************************************************************************** |
669 | * |
670 | * FUNCTION: acpi_os_delete_semaphore |
671 | * |
672 | * PARAMETERS: handle - Handle returned by acpi_os_create_semaphore |
673 | * |
674 | * RETURN: Status |
675 | * |
676 | * DESCRIPTION: Delete an OS semaphore |
677 | * |
678 | *****************************************************************************/ |
679 | |
680 | acpi_status acpi_os_delete_semaphore(acpi_handle handle) |
681 | { |
682 | sem_t *sem = (sem_t *) handle; |
683 | |
684 | if (!sem) { |
685 | return (AE_BAD_PARAMETER); |
686 | } |
687 | #ifdef __APPLE__ |
688 | if (sem_close(sem) == -1) { |
689 | return (AE_BAD_PARAMETER); |
690 | } |
691 | #else |
692 | if (sem_destroy(sem) == -1) { |
693 | return (AE_BAD_PARAMETER); |
694 | } |
695 | #endif |
696 | |
697 | return (AE_OK); |
698 | } |
699 | |
700 | /****************************************************************************** |
701 | * |
702 | * FUNCTION: acpi_os_wait_semaphore |
703 | * |
704 | * PARAMETERS: handle - Handle returned by acpi_os_create_semaphore |
705 | * units - How many units to wait for |
706 | * msec_timeout - How long to wait (milliseconds) |
707 | * |
708 | * RETURN: Status |
709 | * |
710 | * DESCRIPTION: Wait for units |
711 | * |
712 | *****************************************************************************/ |
713 | |
714 | acpi_status |
715 | acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 msec_timeout) |
716 | { |
717 | acpi_status status = AE_OK; |
718 | sem_t *sem = (sem_t *) handle; |
719 | int ret_val; |
720 | #ifndef ACPI_USE_ALTERNATE_TIMEOUT |
721 | struct timespec time; |
722 | #endif |
723 | |
724 | if (!sem) { |
725 | return (AE_BAD_PARAMETER); |
726 | } |
727 | |
728 | switch (msec_timeout) { |
729 | /* |
730 | * No Wait: |
731 | * -------- |
732 | * A zero timeout value indicates that we shouldn't wait - just |
733 | * acquire the semaphore if available otherwise return AE_TIME |
734 | * (a.k.a. 'would block'). |
735 | */ |
736 | case 0: |
737 | |
738 | if (sem_trywait(sem) == -1) { |
739 | status = (AE_TIME); |
740 | } |
741 | break; |
742 | |
743 | /* Wait Indefinitely */ |
744 | |
745 | case ACPI_WAIT_FOREVER: |
746 | |
747 | while (((ret_val = sem_wait(sem)) == -1) && (errno == EINTR)) { |
748 | continue; /* Restart if interrupted */ |
749 | } |
750 | if (ret_val != 0) { |
751 | status = (AE_TIME); |
752 | } |
753 | break; |
754 | |
755 | /* Wait with msec_timeout */ |
756 | |
757 | default: |
758 | |
759 | #ifdef ACPI_USE_ALTERNATE_TIMEOUT |
760 | /* |
761 | * Alternate timeout mechanism for environments where |
762 | * sem_timedwait is not available or does not work properly. |
763 | */ |
764 | while (msec_timeout) { |
765 | if (sem_trywait(sem) == 0) { |
766 | |
767 | /* Got the semaphore */ |
768 | return (AE_OK); |
769 | } |
770 | |
771 | if (msec_timeout >= 10) { |
772 | msec_timeout -= 10; |
773 | usleep(10 * ACPI_USEC_PER_MSEC); /* ten milliseconds */ |
774 | } else { |
775 | msec_timeout--; |
776 | usleep(ACPI_USEC_PER_MSEC); /* one millisecond */ |
777 | } |
778 | } |
779 | status = (AE_TIME); |
780 | #else |
781 | /* |
782 | * The interface to sem_timedwait is an absolute time, so we need to |
783 | * get the current time, then add in the millisecond Timeout value. |
784 | */ |
785 | if (clock_gettime(CLOCK_REALTIME, &time) == -1) { |
786 | perror("clock_gettime" ); |
787 | return (AE_TIME); |
788 | } |
789 | |
790 | time.tv_sec += (msec_timeout / ACPI_MSEC_PER_SEC); |
791 | time.tv_nsec += |
792 | ((msec_timeout % ACPI_MSEC_PER_SEC) * ACPI_NSEC_PER_MSEC); |
793 | |
794 | /* Handle nanosecond overflow (field must be less than one second) */ |
795 | |
796 | if (time.tv_nsec >= ACPI_NSEC_PER_SEC) { |
797 | time.tv_sec += (time.tv_nsec / ACPI_NSEC_PER_SEC); |
798 | time.tv_nsec = (time.tv_nsec % ACPI_NSEC_PER_SEC); |
799 | } |
800 | |
801 | while (((ret_val = sem_timedwait(sem, &time)) == -1) |
802 | && (errno == EINTR)) { |
803 | continue; /* Restart if interrupted */ |
804 | |
805 | } |
806 | |
807 | if (ret_val != 0) { |
808 | if (errno != ETIMEDOUT) { |
809 | perror("sem_timedwait" ); |
810 | } |
811 | status = (AE_TIME); |
812 | } |
813 | #endif |
814 | break; |
815 | } |
816 | |
817 | return (status); |
818 | } |
819 | |
820 | /****************************************************************************** |
821 | * |
822 | * FUNCTION: acpi_os_signal_semaphore |
823 | * |
824 | * PARAMETERS: handle - Handle returned by acpi_os_create_semaphore |
825 | * units - Number of units to send |
826 | * |
827 | * RETURN: Status |
828 | * |
829 | * DESCRIPTION: Send units |
830 | * |
831 | *****************************************************************************/ |
832 | |
833 | acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) |
834 | { |
835 | sem_t *sem = (sem_t *) handle; |
836 | |
837 | if (!sem) { |
838 | return (AE_BAD_PARAMETER); |
839 | } |
840 | |
841 | if (sem_post(sem) == -1) { |
842 | return (AE_LIMIT); |
843 | } |
844 | |
845 | return (AE_OK); |
846 | } |
847 | |
848 | #endif /* ACPI_SINGLE_THREADED */ |
849 | |
850 | /****************************************************************************** |
851 | * |
852 | * FUNCTION: Spinlock interfaces |
853 | * |
854 | * DESCRIPTION: Map these interfaces to semaphore interfaces |
855 | * |
856 | *****************************************************************************/ |
857 | |
858 | acpi_status acpi_os_create_lock(acpi_spinlock * out_handle) |
859 | { |
860 | |
861 | return (acpi_os_create_semaphore(1, 1, out_handle)); |
862 | } |
863 | |
864 | void acpi_os_delete_lock(acpi_spinlock handle) |
865 | { |
866 | acpi_os_delete_semaphore(handle); |
867 | } |
868 | |
869 | acpi_cpu_flags acpi_os_acquire_lock(acpi_handle handle) |
870 | { |
871 | acpi_os_wait_semaphore(handle, units: 1, msec_timeout: 0xFFFF); |
872 | return (0); |
873 | } |
874 | |
875 | void acpi_os_release_lock(acpi_spinlock handle, acpi_cpu_flags flags) |
876 | { |
877 | acpi_os_signal_semaphore(handle, units: 1); |
878 | } |
879 | |
880 | /****************************************************************************** |
881 | * |
882 | * FUNCTION: acpi_os_install_interrupt_handler |
883 | * |
884 | * PARAMETERS: interrupt_number - Level handler should respond to. |
885 | * isr - Address of the ACPI interrupt handler |
886 | * except_ptr - Where status is returned |
887 | * |
888 | * RETURN: Handle to the newly installed handler. |
889 | * |
890 | * DESCRIPTION: Install an interrupt handler. Used to install the ACPI |
891 | * OS-independent handler. |
892 | * |
893 | *****************************************************************************/ |
894 | |
895 | u32 |
896 | acpi_os_install_interrupt_handler(u32 interrupt_number, |
897 | acpi_osd_handler service_routine, |
898 | void *context) |
899 | { |
900 | |
901 | return (AE_OK); |
902 | } |
903 | |
904 | /****************************************************************************** |
905 | * |
906 | * FUNCTION: acpi_os_remove_interrupt_handler |
907 | * |
908 | * PARAMETERS: handle - Returned when handler was installed |
909 | * |
910 | * RETURN: Status |
911 | * |
912 | * DESCRIPTION: Uninstalls an interrupt handler. |
913 | * |
914 | *****************************************************************************/ |
915 | |
916 | acpi_status |
917 | acpi_os_remove_interrupt_handler(u32 interrupt_number, |
918 | acpi_osd_handler service_routine) |
919 | { |
920 | |
921 | return (AE_OK); |
922 | } |
923 | |
924 | /****************************************************************************** |
925 | * |
926 | * FUNCTION: acpi_os_stall |
927 | * |
928 | * PARAMETERS: microseconds - Time to sleep |
929 | * |
930 | * RETURN: Blocks until sleep is completed. |
931 | * |
932 | * DESCRIPTION: Sleep at microsecond granularity |
933 | * |
934 | *****************************************************************************/ |
935 | |
936 | void acpi_os_stall(u32 microseconds) |
937 | { |
938 | |
939 | if (microseconds) { |
940 | usleep(microseconds); |
941 | } |
942 | } |
943 | |
944 | /****************************************************************************** |
945 | * |
946 | * FUNCTION: acpi_os_sleep |
947 | * |
948 | * PARAMETERS: milliseconds - Time to sleep |
949 | * |
950 | * RETURN: Blocks until sleep is completed. |
951 | * |
952 | * DESCRIPTION: Sleep at millisecond granularity |
953 | * |
954 | *****************************************************************************/ |
955 | |
956 | void acpi_os_sleep(u64 milliseconds) |
957 | { |
958 | |
959 | /* Sleep for whole seconds */ |
960 | |
961 | sleep(milliseconds / ACPI_MSEC_PER_SEC); |
962 | |
963 | /* |
964 | * Sleep for remaining microseconds. |
965 | * Arg to usleep() is in usecs and must be less than 1,000,000 (1 second). |
966 | */ |
967 | usleep((milliseconds % ACPI_MSEC_PER_SEC) * ACPI_USEC_PER_MSEC); |
968 | } |
969 | |
970 | /****************************************************************************** |
971 | * |
972 | * FUNCTION: acpi_os_get_timer |
973 | * |
974 | * PARAMETERS: None |
975 | * |
976 | * RETURN: Current time in 100 nanosecond units |
977 | * |
978 | * DESCRIPTION: Get the current system time |
979 | * |
980 | *****************************************************************************/ |
981 | |
982 | u64 acpi_os_get_timer(void) |
983 | { |
984 | struct timeval time; |
985 | |
986 | /* This timer has sufficient resolution for user-space application code */ |
987 | |
988 | gettimeofday(&time, NULL); |
989 | |
990 | /* (Seconds * 10^7 = 100ns(10^-7)) + (Microseconds(10^-6) * 10^1 = 100ns) */ |
991 | |
992 | return (((u64)time.tv_sec * ACPI_100NSEC_PER_SEC) + |
993 | ((u64)time.tv_usec * ACPI_100NSEC_PER_USEC)); |
994 | } |
995 | |
996 | /****************************************************************************** |
997 | * |
998 | * FUNCTION: acpi_os_read_pci_configuration |
999 | * |
1000 | * PARAMETERS: pci_id - Seg/Bus/Dev |
1001 | * pci_register - Device Register |
1002 | * value - Buffer where value is placed |
1003 | * width - Number of bits |
1004 | * |
1005 | * RETURN: Status |
1006 | * |
1007 | * DESCRIPTION: Read data from PCI configuration space |
1008 | * |
1009 | *****************************************************************************/ |
1010 | |
1011 | acpi_status |
1012 | acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id, |
1013 | u32 pci_register, u64 *value, u32 width) |
1014 | { |
1015 | |
1016 | *value = 0; |
1017 | return (AE_OK); |
1018 | } |
1019 | |
1020 | /****************************************************************************** |
1021 | * |
1022 | * FUNCTION: acpi_os_write_pci_configuration |
1023 | * |
1024 | * PARAMETERS: pci_id - Seg/Bus/Dev |
1025 | * pci_register - Device Register |
1026 | * value - Value to be written |
1027 | * width - Number of bits |
1028 | * |
1029 | * RETURN: Status. |
1030 | * |
1031 | * DESCRIPTION: Write data to PCI configuration space |
1032 | * |
1033 | *****************************************************************************/ |
1034 | |
1035 | acpi_status |
1036 | acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id, |
1037 | u32 pci_register, u64 value, u32 width) |
1038 | { |
1039 | |
1040 | return (AE_OK); |
1041 | } |
1042 | |
1043 | /****************************************************************************** |
1044 | * |
1045 | * FUNCTION: acpi_os_read_port |
1046 | * |
1047 | * PARAMETERS: address - Address of I/O port/register to read |
1048 | * value - Where value is placed |
1049 | * width - Number of bits |
1050 | * |
1051 | * RETURN: Value read from port |
1052 | * |
1053 | * DESCRIPTION: Read data from an I/O port or register |
1054 | * |
1055 | *****************************************************************************/ |
1056 | |
1057 | acpi_status acpi_os_read_port(acpi_io_address address, u32 *value, u32 width) |
1058 | { |
1059 | |
1060 | switch (width) { |
1061 | case 8: |
1062 | |
1063 | *value = 0xFF; |
1064 | break; |
1065 | |
1066 | case 16: |
1067 | |
1068 | *value = 0xFFFF; |
1069 | break; |
1070 | |
1071 | case 32: |
1072 | |
1073 | *value = 0xFFFFFFFF; |
1074 | break; |
1075 | |
1076 | default: |
1077 | |
1078 | return (AE_BAD_PARAMETER); |
1079 | } |
1080 | |
1081 | return (AE_OK); |
1082 | } |
1083 | |
1084 | /****************************************************************************** |
1085 | * |
1086 | * FUNCTION: acpi_os_write_port |
1087 | * |
1088 | * PARAMETERS: address - Address of I/O port/register to write |
1089 | * value - Value to write |
1090 | * width - Number of bits |
1091 | * |
1092 | * RETURN: None |
1093 | * |
1094 | * DESCRIPTION: Write data to an I/O port or register |
1095 | * |
1096 | *****************************************************************************/ |
1097 | |
1098 | acpi_status acpi_os_write_port(acpi_io_address address, u32 value, u32 width) |
1099 | { |
1100 | |
1101 | return (AE_OK); |
1102 | } |
1103 | |
1104 | /****************************************************************************** |
1105 | * |
1106 | * FUNCTION: acpi_os_read_memory |
1107 | * |
1108 | * PARAMETERS: address - Physical Memory Address to read |
1109 | * value - Where value is placed |
1110 | * width - Number of bits (8,16,32, or 64) |
1111 | * |
1112 | * RETURN: Value read from physical memory address. Always returned |
1113 | * as a 64-bit integer, regardless of the read width. |
1114 | * |
1115 | * DESCRIPTION: Read data from a physical memory address |
1116 | * |
1117 | *****************************************************************************/ |
1118 | |
1119 | acpi_status |
1120 | acpi_os_read_memory(acpi_physical_address address, u64 *value, u32 width) |
1121 | { |
1122 | |
1123 | switch (width) { |
1124 | case 8: |
1125 | case 16: |
1126 | case 32: |
1127 | case 64: |
1128 | |
1129 | *value = 0; |
1130 | break; |
1131 | |
1132 | default: |
1133 | |
1134 | return (AE_BAD_PARAMETER); |
1135 | } |
1136 | return (AE_OK); |
1137 | } |
1138 | |
1139 | /****************************************************************************** |
1140 | * |
1141 | * FUNCTION: acpi_os_write_memory |
1142 | * |
1143 | * PARAMETERS: address - Physical Memory Address to write |
1144 | * value - Value to write |
1145 | * width - Number of bits (8,16,32, or 64) |
1146 | * |
1147 | * RETURN: None |
1148 | * |
1149 | * DESCRIPTION: Write data to a physical memory address |
1150 | * |
1151 | *****************************************************************************/ |
1152 | |
1153 | acpi_status |
1154 | acpi_os_write_memory(acpi_physical_address address, u64 value, u32 width) |
1155 | { |
1156 | |
1157 | return (AE_OK); |
1158 | } |
1159 | |
1160 | /****************************************************************************** |
1161 | * |
1162 | * FUNCTION: acpi_os_readable |
1163 | * |
1164 | * PARAMETERS: pointer - Area to be verified |
1165 | * length - Size of area |
1166 | * |
1167 | * RETURN: TRUE if readable for entire length |
1168 | * |
1169 | * DESCRIPTION: Verify that a pointer is valid for reading |
1170 | * |
1171 | *****************************************************************************/ |
1172 | |
1173 | u8 acpi_os_readable(void *pointer, acpi_size length) |
1174 | { |
1175 | |
1176 | return (TRUE); |
1177 | } |
1178 | |
1179 | /****************************************************************************** |
1180 | * |
1181 | * FUNCTION: acpi_os_writable |
1182 | * |
1183 | * PARAMETERS: pointer - Area to be verified |
1184 | * length - Size of area |
1185 | * |
1186 | * RETURN: TRUE if writable for entire length |
1187 | * |
1188 | * DESCRIPTION: Verify that a pointer is valid for writing |
1189 | * |
1190 | *****************************************************************************/ |
1191 | |
1192 | u8 acpi_os_writable(void *pointer, acpi_size length) |
1193 | { |
1194 | |
1195 | return (TRUE); |
1196 | } |
1197 | |
1198 | /****************************************************************************** |
1199 | * |
1200 | * FUNCTION: acpi_os_signal |
1201 | * |
1202 | * PARAMETERS: function - ACPI A signal function code |
1203 | * info - Pointer to function-dependent structure |
1204 | * |
1205 | * RETURN: Status |
1206 | * |
1207 | * DESCRIPTION: Miscellaneous functions. Example implementation only. |
1208 | * |
1209 | *****************************************************************************/ |
1210 | |
1211 | acpi_status acpi_os_signal(u32 function, void *info) |
1212 | { |
1213 | |
1214 | switch (function) { |
1215 | case ACPI_SIGNAL_FATAL: |
1216 | |
1217 | break; |
1218 | |
1219 | case ACPI_SIGNAL_BREAKPOINT: |
1220 | |
1221 | break; |
1222 | |
1223 | default: |
1224 | |
1225 | break; |
1226 | } |
1227 | |
1228 | return (AE_OK); |
1229 | } |
1230 | |
1231 | /* Optional multi-thread support */ |
1232 | |
1233 | #ifndef ACPI_SINGLE_THREADED |
1234 | /****************************************************************************** |
1235 | * |
1236 | * FUNCTION: acpi_os_get_thread_id |
1237 | * |
1238 | * PARAMETERS: None |
1239 | * |
1240 | * RETURN: Id of the running thread |
1241 | * |
1242 | * DESCRIPTION: Get the ID of the current (running) thread |
1243 | * |
1244 | *****************************************************************************/ |
1245 | |
1246 | acpi_thread_id acpi_os_get_thread_id(void) |
1247 | { |
1248 | pthread_t thread; |
1249 | |
1250 | thread = pthread_self(); |
1251 | return (ACPI_CAST_PTHREAD_T(thread)); |
1252 | } |
1253 | |
1254 | /****************************************************************************** |
1255 | * |
1256 | * FUNCTION: acpi_os_execute |
1257 | * |
1258 | * PARAMETERS: type - Type of execution |
1259 | * function - Address of the function to execute |
1260 | * context - Passed as a parameter to the function |
1261 | * |
1262 | * RETURN: Status. |
1263 | * |
1264 | * DESCRIPTION: Execute a new thread |
1265 | * |
1266 | *****************************************************************************/ |
1267 | |
1268 | acpi_status |
1269 | acpi_os_execute(acpi_execute_type type, |
1270 | acpi_osd_exec_callback function, void *context) |
1271 | { |
1272 | pthread_t thread; |
1273 | int ret; |
1274 | |
1275 | ret = |
1276 | pthread_create(&thread, NULL, (PTHREAD_CALLBACK) function, context); |
1277 | if (ret) { |
1278 | acpi_os_printf(fmt: "Create thread failed" ); |
1279 | } |
1280 | return (0); |
1281 | } |
1282 | |
1283 | #else /* ACPI_SINGLE_THREADED */ |
1284 | acpi_thread_id acpi_os_get_thread_id(void) |
1285 | { |
1286 | return (1); |
1287 | } |
1288 | |
1289 | acpi_status |
1290 | acpi_os_execute(acpi_execute_type type, |
1291 | acpi_osd_exec_callback function, void *context) |
1292 | { |
1293 | |
1294 | function(context); |
1295 | |
1296 | return (AE_OK); |
1297 | } |
1298 | |
1299 | #endif /* ACPI_SINGLE_THREADED */ |
1300 | |
1301 | /****************************************************************************** |
1302 | * |
1303 | * FUNCTION: acpi_os_wait_events_complete |
1304 | * |
1305 | * PARAMETERS: None |
1306 | * |
1307 | * RETURN: None |
1308 | * |
1309 | * DESCRIPTION: Wait for all asynchronous events to complete. This |
1310 | * implementation does nothing. |
1311 | * |
1312 | *****************************************************************************/ |
1313 | |
1314 | void acpi_os_wait_events_complete(void) |
1315 | { |
1316 | return; |
1317 | } |
1318 | |