/*++ Copyright (c) 1997 Microsoft Corporation Module Name: resource.c Abstract: WinDbg Extension Api for interpretting ACPI data structures Author: Stephane Plante (splante) 21-Mar-1997 Based on Code by: Peter Wieland (peterwie) 16-Oct-1995 Environment: User Mode. Revision History: --*/ #include "pch.h" VOID dumpPnPResources( IN ULONG_PTR Address ) /*++ Routine Description: This routine processes the ACPI version of a PnP resource list given the address that it starts at Arguments: Address - The Starting address Return Value: NULL --*/ { BOOL success; PUCHAR dataBuffer = NULL; UCHAR currentTag; ULONG_PTR currentAddress = Address; ULONG i; ULONG indentLevel = 0; ULONG returnLength; ULONG tagCount = 0; USHORT increment; // // repeat forever // while (1) { // // Allow a way to end this // if (CheckControlC()) { break; } // // Read the current tag // success = ReadMemory( currentAddress, ¤tTag, sizeof(UCHAR), &returnLength ); if (!success || returnLength != sizeof(UCHAR)) { dprintf( "dumpPnPResources: could not read tag at 0x%08lx\n", currentAddress ); return; } // // Determine what we are looking at // if ( !(currentTag & LARGE_RESOURCE_TAG)) { // // We are looking at a small tag // increment = (USHORT) (currentTag & SMALL_TAG_SIZE_MASK) + 1; currentTag &= SMALL_TAG_MASK; } else { // // We are looking at a large Tag. We must read the length as // the next short in memory // success = ReadMemory( currentAddress + 1, &increment, sizeof(USHORT), &returnLength ); if (!success || returnLength != sizeof(USHORT)) { dprintf( "dumpPnPResources: could not read increment at 0x%08lx\n", currentAddress + 1 ); break; } // // Account for the increment // increment += 3; } // // Allocate space for the buffer // if (increment > 1) { dataBuffer = LocalAlloc( LPTR, increment); if (dataBuffer == NULL) { dprintf( "dumpPnPResources: could not allocate 0x%x bytes\n", (increment - 1) ); } // // Read the data into the buffer // success = ReadMemory( currentAddress, dataBuffer, increment, &returnLength ); if (!success || returnLength != (ULONG) increment) { dprintf( "dumpPnPResources: read buffer at 0x%08lx (0x%x)\n", currentAddress, increment ); LocalFree( dataBuffer ); return; } } // // Indent the tag // for (i = 0; i < indentLevel; i++) { dprintf("| "); } // // What tag are we looking at // switch (currentTag) { case TAG_IRQ: { PPNP_IRQ_DESCRIPTOR res = (PPNP_IRQ_DESCRIPTOR) dataBuffer; if (res) { USHORT mask = res->IrqMask; USHORT interrupt = 0; dprintf("%d - TAG_IRQ -", tagCount ); for( ;mask; interrupt++, mask >>= 1) { if (mask & 1) { dprintf(" %d", interrupt ); } } if ( (res->Tag & SMALL_TAG_SIZE_MASK) == 3) { if (res->Information & PNP_IRQ_LATCHED) { dprintf(" Lat"); } if (res->Information & PNP_IRQ_LEVEL) { dprintf(" Lvl"); } if (res->Information & PNP_IRQ_SHARED) { dprintf(" Shr"); } else { dprintf(" Exc"); } } else { dprintf(" Edg Sha"); } dprintf("\n"); } break; } case TAG_EXTENDED_IRQ: { PPNP_EXTENDED_IRQ_DESCRIPTOR res = (PPNP_EXTENDED_IRQ_DESCRIPTOR) dataBuffer; UCHAR tableCount = 0; UCHAR tableSize = res->TableSize; dprintf("%d - TAG_EXTENDED_IRQ -", tagCount ); for (; tableCount < tableSize; tableCount++) { dprintf(" %d", res->Table[tableCount] ); } if (res->Flags & PNP_EXTENDED_IRQ_MODE) { dprintf(" Lat"); } if (res->Flags & PNP_EXTENDED_IRQ_POLARITY ) { dprintf(" Edg"); } if (res->Flags & PNP_EXTENDED_IRQ_SHARED) { dprintf(" Shr"); } else { dprintf(" Exc"); } if (res->Flags & PNP_EXTENDED_IRQ_RESOURCE_CONSUMER_ONLY) { dprintf(" Con"); } else { dprintf(" Prod Con"); } dprintf("\n"); break; } case TAG_DMA: { PPNP_DMA_DESCRIPTOR res = (PPNP_DMA_DESCRIPTOR) dataBuffer; UCHAR channel = 0; UCHAR mask = res->ChannelMask; dprintf("%d - TAG_DMA -", tagCount ); for (; mask; channel++, mask >>= 1) { if (mask & 1) { dprintf(" %d", channel); } } switch( (res->Flags & PNP_DMA_SIZE_MASK) ) { case PNP_DMA_SIZE_8: dprintf(" 8bit"); break; case PNP_DMA_SIZE_8_AND_16: dprintf(" 8-16bit"); break; case PNP_DMA_SIZE_16: dprintf(" 16bit"); break; case PNP_DMA_SIZE_RESERVED: default: dprintf(" ??bit"); break; } if (res->Flags & PNP_DMA_BUS_MASTER) { dprintf(" BM"); } switch( (res->Flags & PNP_DMA_TYPE_MASK) ) { default: case PNP_DMA_TYPE_COMPATIBLE: dprintf(" Com"); break; case PNP_DMA_TYPE_A: dprintf(" A"); break; case PNP_DMA_TYPE_B: dprintf(" B"); break; case PNP_DMA_TYPE_F: dprintf(" F"); } dprintf("\n"); break; } case TAG_START_DEPEND: indentLevel++; dprintf("%d - TAG_START_DEPEND\n", tagCount); break; case TAG_END_DEPEND: indentLevel = 0; dprintf("%d - TAG_END_DEPEND\n", tagCount); break; case TAG_IO: { PPNP_PORT_DESCRIPTOR res = (PPNP_PORT_DESCRIPTOR) dataBuffer; dprintf( "%d - TAG_IO - 0x%x-0x%x A:0x%x L:0x%x", tagCount, res->MinimumAddress, res->MaximumAddress, res->Alignment, res->Length ); switch (res->Information & PNP_PORT_DECODE_MASK) { default: case PNP_PORT_10_BIT_DECODE: dprintf(" 10bit"); break; case PNP_PORT_16_BIT_DECODE: dprintf(" 16bit"); break; } dprintf("\n"); break; } case TAG_IO_FIXED: { PPNP_FIXED_PORT_DESCRIPTOR res = (PPNP_FIXED_PORT_DESCRIPTOR) dataBuffer; dprintf( "%d - TAG_FIXED_IO - 0x%x L:0x%x\n", tagCount, res->MinimumAddress, res->Length ); break; } case TAG_MEMORY: { PPNP_MEMORY_DESCRIPTOR res = (PPNP_MEMORY_DESCRIPTOR) dataBuffer; dprintf( "%d - TAG_MEMORY24 - 0x%x-0x%x A:0x%x L:0x%x", tagCount, res->MinimumAddress, res->MaximumAddress, res->Alignment, res->MemorySize ); if (res->Information & PNP_MEMORY_READ_WRITE) { dprintf(" RW"); } else { dprintf(" R"); } break; } case TAG_MEMORY32: { PPNP_MEMORY32_DESCRIPTOR res = (PPNP_MEMORY32_DESCRIPTOR) dataBuffer; dprintf( "%d - TAG_MEMORY32 - 0x%x-0x%x A:0x%x L:0x%x", tagCount, res->MinimumAddress, res->MaximumAddress, res->Alignment, res->MemorySize ); if (res->Information & PNP_MEMORY_READ_WRITE) { dprintf(" RW"); } else { dprintf(" R"); } break; } case TAG_MEMORY32_FIXED: { PPNP_FIXED_MEMORY32_DESCRIPTOR res = (PPNP_FIXED_MEMORY32_DESCRIPTOR) dataBuffer; dprintf( "%d - TAG_FIXED_MEMORY32 - 0x%x L:0x%x", tagCount, res->BaseAddress, res->MemorySize ); if (res->Information & PNP_MEMORY_READ_WRITE) { dprintf(" RW"); } else { dprintf(" R"); } break; } case TAG_WORD_ADDRESS: { PPNP_WORD_ADDRESS_DESCRIPTOR res = (PPNP_WORD_ADDRESS_DESCRIPTOR) dataBuffer; dprintf("%d - TAG_WORD_ADDRESS -", tagCount); switch (res->RFlag) { case 0: // // Memory range // dprintf( "Mem 0x%x-0x%x A:0x%x T:0x%x L:0x%x", res->MinimumAddress, res->MaximumAddress, res->Granularity, res->TranslationAddress, res->AddressLength ); if (res->TFlag & PNP_ADDRESS_TYPE_MEMORY_READ_WRITE) { dprintf(" RW"); } else { dprintf(" R"); } switch (res->TFlag & PNP_ADDRESS_TYPE_MEMORY_MASK) { default: case PNP_ADDRESS_TYPE_MEMORY_NONCACHEABLE: dprintf(" NC"); break; case PNP_ADDRESS_TYPE_MEMORY_CACHEABLE: dprintf(" C"); break; case PNP_ADDRESS_TYPE_MEMORY_WRITE_COMBINE: dprintf(" WC"); break; case PNP_ADDRESS_TYPE_MEMORY_PREFETCHABLE: dprintf(" PC"); break; } break; case 1: // // IO range // dprintf( "IO 0x%x-0x%x A:0x%x T:0x%x L:0x%x", res->MinimumAddress, res->MaximumAddress, res->Granularity, res->TranslationAddress, res->AddressLength ); if (res->TFlag & PNP_ADDRESS_TYPE_IO_ISA_RANGE) { dprintf(" ISA"); } if (res->TFlag & PNP_ADDRESS_TYPE_IO_NON_ISA_RANGE) { dprintf(" Non-ISA"); } break; case 2: dprintf( "Bus 0x%x-0x%x A:0x%x T:0x%x L:0x%x", res->MinimumAddress, res->MaximumAddress, res->Granularity, res->TranslationAddress, res->AddressLength ); break; } // switch( buffer->RFlag ) // // Global Flags // if (res->GFlag & PNP_ADDRESS_FLAG_CONSUMED_ONLY) { dprintf(" Consumed"); } if (res->GFlag & PNP_ADDRESS_FLAG_SUBTRACTIVE_DECODE) { dprintf(" Subtractive"); } if (res->GFlag & PNP_ADDRESS_FLAG_MINIMUM_FIXED) { dprintf(" MinFixed"); } if (res->GFlag & PNP_ADDRESS_FLAG_MAXIMUM_FIXED) { dprintf(" MaxFixed"); } if (increment > sizeof(PNP_WORD_ADDRESS_DESCRIPTOR) + 1) { dprintf( " %d<-%s", dataBuffer[sizeof(PNP_WORD_ADDRESS_DESCRIPTOR)], &(dataBuffer[sizeof(PNP_WORD_ADDRESS_DESCRIPTOR)+1]) ); } dprintf("\n"); break; } case TAG_DOUBLE_ADDRESS: { PPNP_DWORD_ADDRESS_DESCRIPTOR res = (PPNP_DWORD_ADDRESS_DESCRIPTOR) dataBuffer; dprintf("%d - TAG_DWORD_ADDRESS -", tagCount); switch (res->RFlag) { case 0: // // Memory range // dprintf( "Mem 0x%x-0x%x A:0x%x T:0x%x L:0x%x", res->MinimumAddress, res->MaximumAddress, res->Granularity, res->TranslationAddress, res->AddressLength ); if (res->TFlag & PNP_ADDRESS_TYPE_MEMORY_READ_WRITE) { dprintf(" RW"); } else { dprintf(" R"); } switch (res->TFlag & PNP_ADDRESS_TYPE_MEMORY_MASK) { default: case PNP_ADDRESS_TYPE_MEMORY_NONCACHEABLE: dprintf(" NC"); break; case PNP_ADDRESS_TYPE_MEMORY_CACHEABLE: dprintf(" C"); break; case PNP_ADDRESS_TYPE_MEMORY_WRITE_COMBINE: dprintf(" WC"); break; case PNP_ADDRESS_TYPE_MEMORY_PREFETCHABLE: dprintf(" PC"); break; } break; case 1: // // IO range // dprintf( "IO 0x%x-0x%x A:0x%x T:0x%x L:0x%x", res->MinimumAddress, res->MaximumAddress, res->Granularity, res->TranslationAddress, res->AddressLength ); if (res->TFlag & PNP_ADDRESS_TYPE_IO_ISA_RANGE) { dprintf(" ISA"); } if (res->TFlag & PNP_ADDRESS_TYPE_IO_NON_ISA_RANGE) { dprintf(" Non-ISA"); } break; case 2: dprintf( "Bus 0x%x-0x%x A:0x%x T:0x%x L:0x%x", res->MinimumAddress, res->MaximumAddress, res->Granularity, res->TranslationAddress, res->AddressLength ); break; } // switch( buffer->RFlag ) // // Global Flags // if (res->GFlag & PNP_ADDRESS_FLAG_CONSUMED_ONLY) { dprintf(" Consumed"); } if (res->GFlag & PNP_ADDRESS_FLAG_SUBTRACTIVE_DECODE) { dprintf(" Subtractive"); } if (res->GFlag & PNP_ADDRESS_FLAG_MINIMUM_FIXED) { dprintf(" MinFixed"); } if (res->GFlag & PNP_ADDRESS_FLAG_MAXIMUM_FIXED) { dprintf(" MaxFixed"); } if (increment > sizeof(PNP_DWORD_ADDRESS_DESCRIPTOR) + 1) { dprintf( " %d<-%s", (UCHAR) dataBuffer[sizeof(PNP_DWORD_ADDRESS_DESCRIPTOR)], &(dataBuffer[sizeof(PNP_DWORD_ADDRESS_DESCRIPTOR)+1]) ); } dprintf("\n"); break; } case TAG_QUAD_ADDRESS: { PPNP_QWORD_ADDRESS_DESCRIPTOR res = (PPNP_QWORD_ADDRESS_DESCRIPTOR) dataBuffer; dprintf("%d - TAG_QWORD_ADDRESS -", tagCount); switch (res->RFlag) { case 0: // // Memory range // dprintf( "Mem 0x%x-0x%x A:0x%x T:0x%x L:0x%x", res->MinimumAddress, res->MaximumAddress, res->Granularity, res->TranslationAddress, res->AddressLength ); if (res->TFlag & PNP_ADDRESS_TYPE_MEMORY_READ_WRITE) { dprintf(" RW"); } else { dprintf(" R"); } switch (res->TFlag & PNP_ADDRESS_TYPE_MEMORY_MASK) { default: case PNP_ADDRESS_TYPE_MEMORY_NONCACHEABLE: dprintf(" NC"); break; case PNP_ADDRESS_TYPE_MEMORY_CACHEABLE: dprintf(" C"); break; case PNP_ADDRESS_TYPE_MEMORY_WRITE_COMBINE: dprintf(" WC"); break; case PNP_ADDRESS_TYPE_MEMORY_PREFETCHABLE: dprintf(" PC"); break; } break; case 1: // // IO range // dprintf( "IO 0x%x-0x%x A:0x%x T:0x%x L:0x%x", res->MinimumAddress, res->MaximumAddress, res->Granularity, res->TranslationAddress, res->AddressLength ); if (res->TFlag & PNP_ADDRESS_TYPE_IO_ISA_RANGE) { dprintf(" ISA"); } if (res->TFlag & PNP_ADDRESS_TYPE_IO_NON_ISA_RANGE) { dprintf(" Non-ISA"); } break; case 2: dprintf( "Bus 0x%x-0x%x A:0x%x T:0x%x L:0x%x", res->MinimumAddress, res->MaximumAddress, res->Granularity, res->TranslationAddress, res->AddressLength ); break; } // switch( buffer->RFlag ) // // Global Flags // if (res->GFlag & PNP_ADDRESS_FLAG_CONSUMED_ONLY) { dprintf(" Consumed"); } if (res->GFlag & PNP_ADDRESS_FLAG_SUBTRACTIVE_DECODE) { dprintf(" Subtractive"); } if (res->GFlag & PNP_ADDRESS_FLAG_MINIMUM_FIXED) { dprintf(" MinFixed"); } if (res->GFlag & PNP_ADDRESS_FLAG_MAXIMUM_FIXED) { dprintf(" MaxFixed"); } if (increment > sizeof(PNP_QWORD_ADDRESS_DESCRIPTOR) + 1) { dprintf( " %d<-%s", (UCHAR) dataBuffer[sizeof(PNP_QWORD_ADDRESS_DESCRIPTOR)], &(dataBuffer[sizeof(PNP_QWORD_ADDRESS_DESCRIPTOR)+1]) ); } dprintf("\n"); break; } case TAG_END: dprintf("%d - TAG_END\n", tagCount); if (dataBuffer) { LocalFree(dataBuffer ); } return; default: dprintf("%d - TAG_UNKNOWN %d\n", tagCount, currentTag ); break; } // switch // // Free the buffer if it was allocated // if (dataBuffer != NULL) { LocalFree( dataBuffer ); dataBuffer = NULL; } // // Update the current address and tag number // tagCount++; currentAddress += increment; } // while }