Linux Audio

Check our new training course

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