Merge tag 'mips_4.19_2' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux
[linux-2.6-microblaze.git] / drivers / acpi / acpica / dbcmds.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /*******************************************************************************
3  *
4  * Module Name: dbcmds - Miscellaneous debug commands and output routines
5  *
6  ******************************************************************************/
7
8 #include <acpi/acpi.h>
9 #include "accommon.h"
10 #include "acevents.h"
11 #include "acdebug.h"
12 #include "acnamesp.h"
13 #include "acresrc.h"
14 #include "actables.h"
15
16 #define _COMPONENT          ACPI_CA_DEBUGGER
17 ACPI_MODULE_NAME("dbcmds")
18
19 /* Local prototypes */
20 static void
21 acpi_dm_compare_aml_resources(u8 *aml1_buffer,
22                               acpi_rsdesc_size aml1_buffer_length,
23                               u8 *aml2_buffer,
24                               acpi_rsdesc_size aml2_buffer_length);
25
26 static acpi_status
27 acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name);
28
29 static acpi_status
30 acpi_db_resource_callback(struct acpi_resource *resource, void *context);
31
32 static acpi_status
33 acpi_db_device_resources(acpi_handle obj_handle,
34                          u32 nesting_level, void *context, void **return_value);
35
36 static void acpi_db_do_one_sleep_state(u8 sleep_state);
37
38 static char *acpi_db_trace_method_name = NULL;
39
40 /*******************************************************************************
41  *
42  * FUNCTION:    acpi_db_convert_to_node
43  *
44  * PARAMETERS:  in_string           - String to convert
45  *
46  * RETURN:      Pointer to a NS node
47  *
48  * DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or
49  *              alphanumeric strings.
50  *
51  ******************************************************************************/
52
53 struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string)
54 {
55         struct acpi_namespace_node *node;
56         acpi_size address;
57
58         if ((*in_string >= 0x30) && (*in_string <= 0x39)) {
59
60                 /* Numeric argument, convert */
61
62                 address = strtoul(in_string, NULL, 16);
63                 node = ACPI_TO_POINTER(address);
64                 if (!acpi_os_readable(node, sizeof(struct acpi_namespace_node))) {
65                         acpi_os_printf("Address %p is invalid", node);
66                         return (NULL);
67                 }
68
69                 /* Make sure pointer is valid NS node */
70
71                 if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
72                         acpi_os_printf
73                             ("Address %p is not a valid namespace node [%s]\n",
74                              node, acpi_ut_get_descriptor_name(node));
75                         return (NULL);
76                 }
77         } else {
78                 /*
79                  * Alpha argument: The parameter is a name string that must be
80                  * resolved to a Namespace object.
81                  */
82                 node = acpi_db_local_ns_lookup(in_string);
83                 if (!node) {
84                         acpi_os_printf
85                             ("Could not find [%s] in namespace, defaulting to root node\n",
86                              in_string);
87                         node = acpi_gbl_root_node;
88                 }
89         }
90
91         return (node);
92 }
93
94 /*******************************************************************************
95  *
96  * FUNCTION:    acpi_db_sleep
97  *
98  * PARAMETERS:  object_arg          - Desired sleep state (0-5). NULL means
99  *                                    invoke all possible sleep states.
100  *
101  * RETURN:      Status
102  *
103  * DESCRIPTION: Simulate sleep/wake sequences
104  *
105  ******************************************************************************/
106
107 acpi_status acpi_db_sleep(char *object_arg)
108 {
109         u8 sleep_state;
110         u32 i;
111
112         ACPI_FUNCTION_TRACE(acpi_db_sleep);
113
114         /* Null input (no arguments) means to invoke all sleep states */
115
116         if (!object_arg) {
117                 acpi_os_printf("Invoking all possible sleep states, 0-%d\n",
118                                ACPI_S_STATES_MAX);
119
120                 for (i = 0; i <= ACPI_S_STATES_MAX; i++) {
121                         acpi_db_do_one_sleep_state((u8)i);
122                 }
123
124                 return_ACPI_STATUS(AE_OK);
125         }
126
127         /* Convert argument to binary and invoke the sleep state */
128
129         sleep_state = (u8)strtoul(object_arg, NULL, 0);
130         acpi_db_do_one_sleep_state(sleep_state);
131         return_ACPI_STATUS(AE_OK);
132 }
133
134 /*******************************************************************************
135  *
136  * FUNCTION:    acpi_db_do_one_sleep_state
137  *
138  * PARAMETERS:  sleep_state         - Desired sleep state (0-5)
139  *
140  * RETURN:      None
141  *
142  * DESCRIPTION: Simulate a sleep/wake sequence
143  *
144  ******************************************************************************/
145
146 static void acpi_db_do_one_sleep_state(u8 sleep_state)
147 {
148         acpi_status status;
149         u8 sleep_type_a;
150         u8 sleep_type_b;
151
152         /* Validate parameter */
153
154         if (sleep_state > ACPI_S_STATES_MAX) {
155                 acpi_os_printf("Sleep state %d out of range (%d max)\n",
156                                sleep_state, ACPI_S_STATES_MAX);
157                 return;
158         }
159
160         acpi_os_printf("\n---- Invoking sleep state S%d (%s):\n",
161                        sleep_state, acpi_gbl_sleep_state_names[sleep_state]);
162
163         /* Get the values for the sleep type registers (for display only) */
164
165         status =
166             acpi_get_sleep_type_data(sleep_state, &sleep_type_a, &sleep_type_b);
167         if (ACPI_FAILURE(status)) {
168                 acpi_os_printf("Could not evaluate [%s] method, %s\n",
169                                acpi_gbl_sleep_state_names[sleep_state],
170                                acpi_format_exception(status));
171                 return;
172         }
173
174         acpi_os_printf
175             ("Register values for sleep state S%d: Sleep-A: %.2X, Sleep-B: %.2X\n",
176              sleep_state, sleep_type_a, sleep_type_b);
177
178         /* Invoke the various sleep/wake interfaces */
179
180         acpi_os_printf("**** Sleep: Prepare to sleep (S%d) ****\n",
181                        sleep_state);
182         status = acpi_enter_sleep_state_prep(sleep_state);
183         if (ACPI_FAILURE(status)) {
184                 goto error_exit;
185         }
186
187         acpi_os_printf("**** Sleep: Going to sleep (S%d) ****\n", sleep_state);
188         status = acpi_enter_sleep_state(sleep_state);
189         if (ACPI_FAILURE(status)) {
190                 goto error_exit;
191         }
192
193         acpi_os_printf("**** Wake: Prepare to return from sleep (S%d) ****\n",
194                        sleep_state);
195         status = acpi_leave_sleep_state_prep(sleep_state);
196         if (ACPI_FAILURE(status)) {
197                 goto error_exit;
198         }
199
200         acpi_os_printf("**** Wake: Return from sleep (S%d) ****\n",
201                        sleep_state);
202         status = acpi_leave_sleep_state(sleep_state);
203         if (ACPI_FAILURE(status)) {
204                 goto error_exit;
205         }
206
207         return;
208
209 error_exit:
210         ACPI_EXCEPTION((AE_INFO, status, "During invocation of sleep state S%d",
211                         sleep_state));
212 }
213
214 /*******************************************************************************
215  *
216  * FUNCTION:    acpi_db_display_locks
217  *
218  * PARAMETERS:  None
219  *
220  * RETURN:      None
221  *
222  * DESCRIPTION: Display information about internal mutexes.
223  *
224  ******************************************************************************/
225
226 void acpi_db_display_locks(void)
227 {
228         u32 i;
229
230         for (i = 0; i < ACPI_MAX_MUTEX; i++) {
231                 acpi_os_printf("%26s : %s\n", acpi_ut_get_mutex_name(i),
232                                acpi_gbl_mutex_info[i].thread_id ==
233                                ACPI_MUTEX_NOT_ACQUIRED ? "Locked" : "Unlocked");
234         }
235 }
236
237 /*******************************************************************************
238  *
239  * FUNCTION:    acpi_db_display_table_info
240  *
241  * PARAMETERS:  table_arg           - Name of table to be displayed
242  *
243  * RETURN:      None
244  *
245  * DESCRIPTION: Display information about loaded tables. Current
246  *              implementation displays all loaded tables.
247  *
248  ******************************************************************************/
249
250 void acpi_db_display_table_info(char *table_arg)
251 {
252         u32 i;
253         struct acpi_table_desc *table_desc;
254         acpi_status status;
255
256         /* Header */
257
258         acpi_os_printf("Idx ID  Status Type                    "
259                        "TableHeader (Sig, Address, Length, Misc)\n");
260
261         /* Walk the entire root table list */
262
263         for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
264                 table_desc = &acpi_gbl_root_table_list.tables[i];
265
266                 /* Index and Table ID */
267
268                 acpi_os_printf("%3u %.2u ", i, table_desc->owner_id);
269
270                 /* Decode the table flags */
271
272                 if (!(table_desc->flags & ACPI_TABLE_IS_LOADED)) {
273                         acpi_os_printf("NotLoaded ");
274                 } else {
275                         acpi_os_printf(" Loaded ");
276                 }
277
278                 switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
279                 case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
280
281                         acpi_os_printf("External/virtual ");
282                         break;
283
284                 case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
285
286                         acpi_os_printf("Internal/physical ");
287                         break;
288
289                 case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
290
291                         acpi_os_printf("Internal/virtual ");
292                         break;
293
294                 default:
295
296                         acpi_os_printf("INVALID TYPE    ");
297                         break;
298                 }
299
300                 /* Make sure that the table is mapped */
301
302                 status = acpi_tb_validate_table(table_desc);
303                 if (ACPI_FAILURE(status)) {
304                         return;
305                 }
306
307                 /* Dump the table header */
308
309                 if (table_desc->pointer) {
310                         acpi_tb_print_table_header(table_desc->address,
311                                                    table_desc->pointer);
312                 } else {
313                         /* If the pointer is null, the table has been unloaded */
314
315                         ACPI_INFO(("%4.4s - Table has been unloaded",
316                                    table_desc->signature.ascii));
317                 }
318         }
319 }
320
321 /*******************************************************************************
322  *
323  * FUNCTION:    acpi_db_unload_acpi_table
324  *
325  * PARAMETERS:  object_name         - Namespace pathname for an object that
326  *                                    is owned by the table to be unloaded
327  *
328  * RETURN:      None
329  *
330  * DESCRIPTION: Unload an ACPI table, via any namespace node that is owned
331  *              by the table.
332  *
333  ******************************************************************************/
334
335 void acpi_db_unload_acpi_table(char *object_name)
336 {
337         struct acpi_namespace_node *node;
338         acpi_status status;
339
340         /* Translate name to an Named object */
341
342         node = acpi_db_convert_to_node(object_name);
343         if (!node) {
344                 return;
345         }
346
347         status = acpi_unload_parent_table(ACPI_CAST_PTR(acpi_handle, node));
348         if (ACPI_SUCCESS(status)) {
349                 acpi_os_printf("Parent of [%s] (%p) unloaded and uninstalled\n",
350                                object_name, node);
351         } else {
352                 acpi_os_printf("%s, while unloading parent table of [%s]\n",
353                                acpi_format_exception(status), object_name);
354         }
355 }
356
357 /*******************************************************************************
358  *
359  * FUNCTION:    acpi_db_send_notify
360  *
361  * PARAMETERS:  name                - Name of ACPI object where to send notify
362  *              value               - Value of the notify to send.
363  *
364  * RETURN:      None
365  *
366  * DESCRIPTION: Send an ACPI notification. The value specified is sent to the
367  *              named object as an ACPI notify.
368  *
369  ******************************************************************************/
370
371 void acpi_db_send_notify(char *name, u32 value)
372 {
373         struct acpi_namespace_node *node;
374         acpi_status status;
375
376         /* Translate name to an Named object */
377
378         node = acpi_db_convert_to_node(name);
379         if (!node) {
380                 return;
381         }
382
383         /* Dispatch the notify if legal */
384
385         if (acpi_ev_is_notify_object(node)) {
386                 status = acpi_ev_queue_notify_request(node, value);
387                 if (ACPI_FAILURE(status)) {
388                         acpi_os_printf("Could not queue notify\n");
389                 }
390         } else {
391                 acpi_os_printf("Named object [%4.4s] Type %s, "
392                                "must be Device/Thermal/Processor type\n",
393                                acpi_ut_get_node_name(node),
394                                acpi_ut_get_type_name(node->type));
395         }
396 }
397
398 /*******************************************************************************
399  *
400  * FUNCTION:    acpi_db_display_interfaces
401  *
402  * PARAMETERS:  action_arg          - Null, "install", or "remove"
403  *              interface_name_arg  - Name for install/remove options
404  *
405  * RETURN:      None
406  *
407  * DESCRIPTION: Display or modify the global _OSI interface list
408  *
409  ******************************************************************************/
410
411 void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg)
412 {
413         struct acpi_interface_info *next_interface;
414         char *sub_string;
415         acpi_status status;
416
417         /* If no arguments, just display current interface list */
418
419         if (!action_arg) {
420                 (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex,
421                                             ACPI_WAIT_FOREVER);
422
423                 next_interface = acpi_gbl_supported_interfaces;
424                 while (next_interface) {
425                         if (!(next_interface->flags & ACPI_OSI_INVALID)) {
426                                 acpi_os_printf("%s\n", next_interface->name);
427                         }
428
429                         next_interface = next_interface->next;
430                 }
431
432                 acpi_os_release_mutex(acpi_gbl_osi_mutex);
433                 return;
434         }
435
436         /* If action_arg exists, so must interface_name_arg */
437
438         if (!interface_name_arg) {
439                 acpi_os_printf("Missing Interface Name argument\n");
440                 return;
441         }
442
443         /* Uppercase the action for match below */
444
445         acpi_ut_strupr(action_arg);
446
447         /* install - install an interface */
448
449         sub_string = strstr("INSTALL", action_arg);
450         if (sub_string) {
451                 status = acpi_install_interface(interface_name_arg);
452                 if (ACPI_FAILURE(status)) {
453                         acpi_os_printf("%s, while installing \"%s\"\n",
454                                        acpi_format_exception(status),
455                                        interface_name_arg);
456                 }
457                 return;
458         }
459
460         /* remove - remove an interface */
461
462         sub_string = strstr("REMOVE", action_arg);
463         if (sub_string) {
464                 status = acpi_remove_interface(interface_name_arg);
465                 if (ACPI_FAILURE(status)) {
466                         acpi_os_printf("%s, while removing \"%s\"\n",
467                                        acpi_format_exception(status),
468                                        interface_name_arg);
469                 }
470                 return;
471         }
472
473         /* Invalid action_arg */
474
475         acpi_os_printf("Invalid action argument: %s\n", action_arg);
476         return;
477 }
478
479 /*******************************************************************************
480  *
481  * FUNCTION:    acpi_db_display_template
482  *
483  * PARAMETERS:  buffer_arg          - Buffer name or address
484  *
485  * RETURN:      None
486  *
487  * DESCRIPTION: Dump a buffer that contains a resource template
488  *
489  ******************************************************************************/
490
491 void acpi_db_display_template(char *buffer_arg)
492 {
493         struct acpi_namespace_node *node;
494         acpi_status status;
495         struct acpi_buffer return_buffer;
496
497         /* Translate buffer_arg to an Named object */
498
499         node = acpi_db_convert_to_node(buffer_arg);
500         if (!node || (node == acpi_gbl_root_node)) {
501                 acpi_os_printf("Invalid argument: %s\n", buffer_arg);
502                 return;
503         }
504
505         /* We must have a buffer object */
506
507         if (node->type != ACPI_TYPE_BUFFER) {
508                 acpi_os_printf
509                     ("Not a Buffer object, cannot be a template: %s\n",
510                      buffer_arg);
511                 return;
512         }
513
514         return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
515         return_buffer.pointer = acpi_gbl_db_buffer;
516
517         /* Attempt to convert the raw buffer to a resource list */
518
519         status = acpi_rs_create_resource_list(node->object, &return_buffer);
520
521         acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
522         acpi_dbg_level |= ACPI_LV_RESOURCES;
523
524         if (ACPI_FAILURE(status)) {
525                 acpi_os_printf
526                     ("Could not convert Buffer to a resource list: %s, %s\n",
527                      buffer_arg, acpi_format_exception(status));
528                 goto dump_buffer;
529         }
530
531         /* Now we can dump the resource list */
532
533         acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource,
534                                                  return_buffer.pointer));
535
536 dump_buffer:
537         acpi_os_printf("\nRaw data buffer:\n");
538         acpi_ut_debug_dump_buffer((u8 *)node->object->buffer.pointer,
539                                   node->object->buffer.length,
540                                   DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
541
542         acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
543         return;
544 }
545
546 /*******************************************************************************
547  *
548  * FUNCTION:    acpi_dm_compare_aml_resources
549  *
550  * PARAMETERS:  aml1_buffer         - Contains first resource list
551  *              aml1_buffer_length  - Length of first resource list
552  *              aml2_buffer         - Contains second resource list
553  *              aml2_buffer_length  - Length of second resource list
554  *
555  * RETURN:      None
556  *
557  * DESCRIPTION: Compare two AML resource lists, descriptor by descriptor (in
558  *              order to isolate a miscompare to an individual resource)
559  *
560  ******************************************************************************/
561
562 static void
563 acpi_dm_compare_aml_resources(u8 *aml1_buffer,
564                               acpi_rsdesc_size aml1_buffer_length,
565                               u8 *aml2_buffer,
566                               acpi_rsdesc_size aml2_buffer_length)
567 {
568         u8 *aml1;
569         u8 *aml2;
570         u8 *aml1_end;
571         u8 *aml2_end;
572         acpi_rsdesc_size aml1_length;
573         acpi_rsdesc_size aml2_length;
574         acpi_rsdesc_size offset = 0;
575         u8 resource_type;
576         u32 count = 0;
577         u32 i;
578
579         /* Compare overall buffer sizes (may be different due to size rounding) */
580
581         if (aml1_buffer_length != aml2_buffer_length) {
582                 acpi_os_printf("**** Buffer length mismatch in converted "
583                                "AML: Original %X, New %X ****\n",
584                                aml1_buffer_length, aml2_buffer_length);
585         }
586
587         aml1 = aml1_buffer;
588         aml2 = aml2_buffer;
589         aml1_end = aml1_buffer + aml1_buffer_length;
590         aml2_end = aml2_buffer + aml2_buffer_length;
591
592         /* Walk the descriptor lists, comparing each descriptor */
593
594         while ((aml1 < aml1_end) && (aml2 < aml2_end)) {
595
596                 /* Get the lengths of each descriptor */
597
598                 aml1_length = acpi_ut_get_descriptor_length(aml1);
599                 aml2_length = acpi_ut_get_descriptor_length(aml2);
600                 resource_type = acpi_ut_get_resource_type(aml1);
601
602                 /* Check for descriptor length match */
603
604                 if (aml1_length != aml2_length) {
605                         acpi_os_printf
606                             ("**** Length mismatch in descriptor [%.2X] type %2.2X, "
607                              "Offset %8.8X Len1 %X, Len2 %X ****\n", count,
608                              resource_type, offset, aml1_length, aml2_length);
609                 }
610
611                 /* Check for descriptor byte match */
612
613                 else if (memcmp(aml1, aml2, aml1_length)) {
614                         acpi_os_printf
615                             ("**** Data mismatch in descriptor [%.2X] type %2.2X, "
616                              "Offset %8.8X ****\n", count, resource_type,
617                              offset);
618
619                         for (i = 0; i < aml1_length; i++) {
620                                 if (aml1[i] != aml2[i]) {
621                                         acpi_os_printf
622                                             ("Mismatch at byte offset %.2X: is %2.2X, "
623                                              "should be %2.2X\n", i, aml2[i],
624                                              aml1[i]);
625                                 }
626                         }
627                 }
628
629                 /* Exit on end_tag descriptor */
630
631                 if (resource_type == ACPI_RESOURCE_NAME_END_TAG) {
632                         return;
633                 }
634
635                 /* Point to next descriptor in each buffer */
636
637                 count++;
638                 offset += aml1_length;
639                 aml1 += aml1_length;
640                 aml2 += aml2_length;
641         }
642 }
643
644 /*******************************************************************************
645  *
646  * FUNCTION:    acpi_dm_test_resource_conversion
647  *
648  * PARAMETERS:  node                - Parent device node
649  *              name                - resource method name (_CRS)
650  *
651  * RETURN:      Status
652  *
653  * DESCRIPTION: Compare the original AML with a conversion of the AML to
654  *              internal resource list, then back to AML.
655  *
656  ******************************************************************************/
657
658 static acpi_status
659 acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name)
660 {
661         acpi_status status;
662         struct acpi_buffer return_buffer;
663         struct acpi_buffer resource_buffer;
664         struct acpi_buffer new_aml;
665         union acpi_object *original_aml;
666
667         acpi_os_printf("Resource Conversion Comparison:\n");
668
669         new_aml.length = ACPI_ALLOCATE_LOCAL_BUFFER;
670         return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
671         resource_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
672
673         /* Get the original _CRS AML resource template */
674
675         status = acpi_evaluate_object(node, name, NULL, &return_buffer);
676         if (ACPI_FAILURE(status)) {
677                 acpi_os_printf("Could not obtain %s: %s\n",
678                                name, acpi_format_exception(status));
679                 return (status);
680         }
681
682         /* Get the AML resource template, converted to internal resource structs */
683
684         status = acpi_get_current_resources(node, &resource_buffer);
685         if (ACPI_FAILURE(status)) {
686                 acpi_os_printf("AcpiGetCurrentResources failed: %s\n",
687                                acpi_format_exception(status));
688                 goto exit1;
689         }
690
691         /* Convert internal resource list to external AML resource template */
692
693         status = acpi_rs_create_aml_resources(&resource_buffer, &new_aml);
694         if (ACPI_FAILURE(status)) {
695                 acpi_os_printf("AcpiRsCreateAmlResources failed: %s\n",
696                                acpi_format_exception(status));
697                 goto exit2;
698         }
699
700         /* Compare original AML to the newly created AML resource list */
701
702         original_aml = return_buffer.pointer;
703
704         acpi_dm_compare_aml_resources(original_aml->buffer.pointer,
705                                       (acpi_rsdesc_size)original_aml->buffer.
706                                       length, new_aml.pointer,
707                                       (acpi_rsdesc_size)new_aml.length);
708
709         /* Cleanup and exit */
710
711         ACPI_FREE(new_aml.pointer);
712 exit2:
713         ACPI_FREE(resource_buffer.pointer);
714 exit1:
715         ACPI_FREE(return_buffer.pointer);
716         return (status);
717 }
718
719 /*******************************************************************************
720  *
721  * FUNCTION:    acpi_db_resource_callback
722  *
723  * PARAMETERS:  acpi_walk_resource_callback
724  *
725  * RETURN:      Status
726  *
727  * DESCRIPTION: Simple callback to exercise acpi_walk_resources and
728  *              acpi_walk_resource_buffer.
729  *
730  ******************************************************************************/
731
732 static acpi_status
733 acpi_db_resource_callback(struct acpi_resource *resource, void *context)
734 {
735
736         return (AE_OK);
737 }
738
739 /*******************************************************************************
740  *
741  * FUNCTION:    acpi_db_device_resources
742  *
743  * PARAMETERS:  acpi_walk_callback
744  *
745  * RETURN:      Status
746  *
747  * DESCRIPTION: Display the _PRT/_CRS/_PRS resources for a device object.
748  *
749  ******************************************************************************/
750
751 static acpi_status
752 acpi_db_device_resources(acpi_handle obj_handle,
753                          u32 nesting_level, void *context, void **return_value)
754 {
755         struct acpi_namespace_node *node;
756         struct acpi_namespace_node *prt_node = NULL;
757         struct acpi_namespace_node *crs_node = NULL;
758         struct acpi_namespace_node *prs_node = NULL;
759         struct acpi_namespace_node *aei_node = NULL;
760         char *parent_path;
761         struct acpi_buffer return_buffer;
762         acpi_status status;
763
764         node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
765         parent_path = acpi_ns_get_normalized_pathname(node, TRUE);
766         if (!parent_path) {
767                 return (AE_NO_MEMORY);
768         }
769
770         /* Get handles to the resource methods for this device */
771
772         (void)acpi_get_handle(node, METHOD_NAME__PRT,
773                               ACPI_CAST_PTR(acpi_handle, &prt_node));
774         (void)acpi_get_handle(node, METHOD_NAME__CRS,
775                               ACPI_CAST_PTR(acpi_handle, &crs_node));
776         (void)acpi_get_handle(node, METHOD_NAME__PRS,
777                               ACPI_CAST_PTR(acpi_handle, &prs_node));
778         (void)acpi_get_handle(node, METHOD_NAME__AEI,
779                               ACPI_CAST_PTR(acpi_handle, &aei_node));
780
781         if (!prt_node && !crs_node && !prs_node && !aei_node) {
782                 goto cleanup;   /* Nothing to do */
783         }
784
785         acpi_os_printf("\nDevice: %s\n", parent_path);
786
787         /* Prepare for a return object of arbitrary size */
788
789         return_buffer.pointer = acpi_gbl_db_buffer;
790         return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
791
792         /* _PRT */
793
794         if (prt_node) {
795                 acpi_os_printf("Evaluating _PRT\n");
796
797                 status =
798                     acpi_evaluate_object(prt_node, NULL, NULL, &return_buffer);
799                 if (ACPI_FAILURE(status)) {
800                         acpi_os_printf("Could not evaluate _PRT: %s\n",
801                                        acpi_format_exception(status));
802                         goto get_crs;
803                 }
804
805                 return_buffer.pointer = acpi_gbl_db_buffer;
806                 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
807
808                 status = acpi_get_irq_routing_table(node, &return_buffer);
809                 if (ACPI_FAILURE(status)) {
810                         acpi_os_printf("GetIrqRoutingTable failed: %s\n",
811                                        acpi_format_exception(status));
812                         goto get_crs;
813                 }
814
815                 acpi_rs_dump_irq_list(ACPI_CAST_PTR(u8, acpi_gbl_db_buffer));
816         }
817
818         /* _CRS */
819
820 get_crs:
821         if (crs_node) {
822                 acpi_os_printf("Evaluating _CRS\n");
823
824                 return_buffer.pointer = acpi_gbl_db_buffer;
825                 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
826
827                 status =
828                     acpi_evaluate_object(crs_node, NULL, NULL, &return_buffer);
829                 if (ACPI_FAILURE(status)) {
830                         acpi_os_printf("Could not evaluate _CRS: %s\n",
831                                        acpi_format_exception(status));
832                         goto get_prs;
833                 }
834
835                 /* This code exercises the acpi_walk_resources interface */
836
837                 status = acpi_walk_resources(node, METHOD_NAME__CRS,
838                                              acpi_db_resource_callback, NULL);
839                 if (ACPI_FAILURE(status)) {
840                         acpi_os_printf("AcpiWalkResources failed: %s\n",
841                                        acpi_format_exception(status));
842                         goto get_prs;
843                 }
844
845                 /* Get the _CRS resource list (test ALLOCATE buffer) */
846
847                 return_buffer.pointer = NULL;
848                 return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
849
850                 status = acpi_get_current_resources(node, &return_buffer);
851                 if (ACPI_FAILURE(status)) {
852                         acpi_os_printf("AcpiGetCurrentResources failed: %s\n",
853                                        acpi_format_exception(status));
854                         goto get_prs;
855                 }
856
857                 /* This code exercises the acpi_walk_resource_buffer interface */
858
859                 status = acpi_walk_resource_buffer(&return_buffer,
860                                                    acpi_db_resource_callback,
861                                                    NULL);
862                 if (ACPI_FAILURE(status)) {
863                         acpi_os_printf("AcpiWalkResourceBuffer failed: %s\n",
864                                        acpi_format_exception(status));
865                         goto end_crs;
866                 }
867
868                 /* Dump the _CRS resource list */
869
870                 acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource,
871                                                          return_buffer.
872                                                          pointer));
873
874                 /*
875                  * Perform comparison of original AML to newly created AML. This
876                  * tests both the AML->Resource conversion and the Resource->AML
877                  * conversion.
878                  */
879                 (void)acpi_dm_test_resource_conversion(node, METHOD_NAME__CRS);
880
881                 /* Execute _SRS with the resource list */
882
883                 acpi_os_printf("Evaluating _SRS\n");
884
885                 status = acpi_set_current_resources(node, &return_buffer);
886                 if (ACPI_FAILURE(status)) {
887                         acpi_os_printf("AcpiSetCurrentResources failed: %s\n",
888                                        acpi_format_exception(status));
889                         goto end_crs;
890                 }
891
892 end_crs:
893                 ACPI_FREE(return_buffer.pointer);
894         }
895
896         /* _PRS */
897
898 get_prs:
899         if (prs_node) {
900                 acpi_os_printf("Evaluating _PRS\n");
901
902                 return_buffer.pointer = acpi_gbl_db_buffer;
903                 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
904
905                 status =
906                     acpi_evaluate_object(prs_node, NULL, NULL, &return_buffer);
907                 if (ACPI_FAILURE(status)) {
908                         acpi_os_printf("Could not evaluate _PRS: %s\n",
909                                        acpi_format_exception(status));
910                         goto get_aei;
911                 }
912
913                 return_buffer.pointer = acpi_gbl_db_buffer;
914                 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
915
916                 status = acpi_get_possible_resources(node, &return_buffer);
917                 if (ACPI_FAILURE(status)) {
918                         acpi_os_printf("AcpiGetPossibleResources failed: %s\n",
919                                        acpi_format_exception(status));
920                         goto get_aei;
921                 }
922
923                 acpi_rs_dump_resource_list(ACPI_CAST_PTR
924                                            (struct acpi_resource,
925                                             acpi_gbl_db_buffer));
926         }
927
928         /* _AEI */
929
930 get_aei:
931         if (aei_node) {
932                 acpi_os_printf("Evaluating _AEI\n");
933
934                 return_buffer.pointer = acpi_gbl_db_buffer;
935                 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
936
937                 status =
938                     acpi_evaluate_object(aei_node, NULL, NULL, &return_buffer);
939                 if (ACPI_FAILURE(status)) {
940                         acpi_os_printf("Could not evaluate _AEI: %s\n",
941                                        acpi_format_exception(status));
942                         goto cleanup;
943                 }
944
945                 return_buffer.pointer = acpi_gbl_db_buffer;
946                 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
947
948                 status = acpi_get_event_resources(node, &return_buffer);
949                 if (ACPI_FAILURE(status)) {
950                         acpi_os_printf("AcpiGetEventResources failed: %s\n",
951                                        acpi_format_exception(status));
952                         goto cleanup;
953                 }
954
955                 acpi_rs_dump_resource_list(ACPI_CAST_PTR
956                                            (struct acpi_resource,
957                                             acpi_gbl_db_buffer));
958         }
959
960 cleanup:
961         ACPI_FREE(parent_path);
962         return (AE_OK);
963 }
964
965 /*******************************************************************************
966  *
967  * FUNCTION:    acpi_db_display_resources
968  *
969  * PARAMETERS:  object_arg          - String object name or object pointer.
970  *                                    NULL or "*" means "display resources for
971  *                                    all devices"
972  *
973  * RETURN:      None
974  *
975  * DESCRIPTION: Display the resource objects associated with a device.
976  *
977  ******************************************************************************/
978
979 void acpi_db_display_resources(char *object_arg)
980 {
981         struct acpi_namespace_node *node;
982
983         acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
984         acpi_dbg_level |= ACPI_LV_RESOURCES;
985
986         /* Asterisk means "display resources for all devices" */
987
988         if (!object_arg || (!strcmp(object_arg, "*"))) {
989                 (void)acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
990                                           ACPI_UINT32_MAX,
991                                           acpi_db_device_resources, NULL, NULL,
992                                           NULL);
993         } else {
994                 /* Convert string to object pointer */
995
996                 node = acpi_db_convert_to_node(object_arg);
997                 if (node) {
998                         if (node->type != ACPI_TYPE_DEVICE) {
999                                 acpi_os_printf
1000                                     ("%4.4s: Name is not a device object (%s)\n",
1001                                      node->name.ascii,
1002                                      acpi_ut_get_type_name(node->type));
1003                         } else {
1004                                 (void)acpi_db_device_resources(node, 0, NULL,
1005                                                                NULL);
1006                         }
1007                 }
1008         }
1009
1010         acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
1011 }
1012
1013 #if (!ACPI_REDUCED_HARDWARE)
1014 /*******************************************************************************
1015  *
1016  * FUNCTION:    acpi_db_generate_gpe
1017  *
1018  * PARAMETERS:  gpe_arg             - Raw GPE number, ascii string
1019  *              block_arg           - GPE block number, ascii string
1020  *                                    0 or 1 for FADT GPE blocks
1021  *
1022  * RETURN:      None
1023  *
1024  * DESCRIPTION: Simulate firing of a GPE
1025  *
1026  ******************************************************************************/
1027
1028 void acpi_db_generate_gpe(char *gpe_arg, char *block_arg)
1029 {
1030         u32 block_number = 0;
1031         u32 gpe_number;
1032         struct acpi_gpe_event_info *gpe_event_info;
1033
1034         gpe_number = strtoul(gpe_arg, NULL, 0);
1035
1036         /*
1037          * If no block arg, or block arg == 0 or 1, use the FADT-defined
1038          * GPE blocks.
1039          */
1040         if (block_arg) {
1041                 block_number = strtoul(block_arg, NULL, 0);
1042                 if (block_number == 1) {
1043                         block_number = 0;
1044                 }
1045         }
1046
1047         gpe_event_info =
1048             acpi_ev_get_gpe_event_info(ACPI_TO_POINTER(block_number),
1049                                        gpe_number);
1050         if (!gpe_event_info) {
1051                 acpi_os_printf("Invalid GPE\n");
1052                 return;
1053         }
1054
1055         (void)acpi_ev_gpe_dispatch(NULL, gpe_event_info, gpe_number);
1056 }
1057
1058 /*******************************************************************************
1059  *
1060  * FUNCTION:    acpi_db_generate_sci
1061  *
1062  * PARAMETERS:  None
1063  *
1064  * RETURN:      None
1065  *
1066  * DESCRIPTION: Simulate an SCI -- just call the SCI dispatch.
1067  *
1068  ******************************************************************************/
1069
1070 void acpi_db_generate_sci(void)
1071 {
1072         acpi_ev_sci_dispatch();
1073 }
1074
1075 #endif                          /* !ACPI_REDUCED_HARDWARE */
1076
1077 /*******************************************************************************
1078  *
1079  * FUNCTION:    acpi_db_trace
1080  *
1081  * PARAMETERS:  enable_arg          - ENABLE/AML to enable tracer
1082  *                                    DISABLE to disable tracer
1083  *              method_arg          - Method to trace
1084  *              once_arg            - Whether trace once
1085  *
1086  * RETURN:      None
1087  *
1088  * DESCRIPTION: Control method tracing facility
1089  *
1090  ******************************************************************************/
1091
1092 void acpi_db_trace(char *enable_arg, char *method_arg, char *once_arg)
1093 {
1094         u32 debug_level = 0;
1095         u32 debug_layer = 0;
1096         u32 flags = 0;
1097
1098         acpi_ut_strupr(enable_arg);
1099         acpi_ut_strupr(once_arg);
1100
1101         if (method_arg) {
1102                 if (acpi_db_trace_method_name) {
1103                         ACPI_FREE(acpi_db_trace_method_name);
1104                         acpi_db_trace_method_name = NULL;
1105                 }
1106
1107                 acpi_db_trace_method_name =
1108                     ACPI_ALLOCATE(strlen(method_arg) + 1);
1109                 if (!acpi_db_trace_method_name) {
1110                         acpi_os_printf("Failed to allocate method name (%s)\n",
1111                                        method_arg);
1112                         return;
1113                 }
1114
1115                 strcpy(acpi_db_trace_method_name, method_arg);
1116         }
1117
1118         if (!strcmp(enable_arg, "ENABLE") ||
1119             !strcmp(enable_arg, "METHOD") || !strcmp(enable_arg, "OPCODE")) {
1120                 if (!strcmp(enable_arg, "ENABLE")) {
1121
1122                         /* Inherit current console settings */
1123
1124                         debug_level = acpi_gbl_db_console_debug_level;
1125                         debug_layer = acpi_dbg_layer;
1126                 } else {
1127                         /* Restrict console output to trace points only */
1128
1129                         debug_level = ACPI_LV_TRACE_POINT;
1130                         debug_layer = ACPI_EXECUTER;
1131                 }
1132
1133                 flags = ACPI_TRACE_ENABLED;
1134
1135                 if (!strcmp(enable_arg, "OPCODE")) {
1136                         flags |= ACPI_TRACE_OPCODE;
1137                 }
1138
1139                 if (once_arg && !strcmp(once_arg, "ONCE")) {
1140                         flags |= ACPI_TRACE_ONESHOT;
1141                 }
1142         }
1143
1144         (void)acpi_debug_trace(acpi_db_trace_method_name,
1145                                debug_level, debug_layer, flags);
1146 }