You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6184 lines
184 KiB
6184 lines
184 KiB
/*++
|
|
|
|
Copyright (c) 1997-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
devnode.c
|
|
|
|
Abstract:
|
|
|
|
WinDbg Extension Api
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
//#include "pci.h"
|
|
#pragma hdrstop
|
|
|
|
#include "stddef.h"
|
|
#include <initguid.h>
|
|
#include "devnode.h"
|
|
|
|
|
|
#define FLAG_NAME(flag) {flag, # flag}
|
|
|
|
FLAG_NAME DeviceNodeFlags[] = {
|
|
FLAG_NAME(DNF_MADEUP), // 00000001
|
|
FLAG_NAME(DNF_DUPLICATE), // 00000002
|
|
FLAG_NAME(DNF_HAL_NODE), // 00000004
|
|
FLAG_NAME(DNF_REENUMERATE), // 00000008
|
|
FLAG_NAME(DNF_ENUMERATED), // 00000010
|
|
FLAG_NAME(DNF_IDS_QUERIED), // 00000020
|
|
FLAG_NAME(DNF_HAS_BOOT_CONFIG), // 00000040
|
|
FLAG_NAME(DNF_BOOT_CONFIG_RESERVED), // 00000080
|
|
FLAG_NAME(DNF_NO_RESOURCE_REQUIRED), // 00000100
|
|
FLAG_NAME(DNF_RESOURCE_REQUIREMENTS_NEED_FILTERED), // 00000200
|
|
FLAG_NAME(DNF_RESOURCE_REQUIREMENTS_CHANGED), // 00000400
|
|
FLAG_NAME(DNF_NON_STOPPED_REBALANCE), // 00000800
|
|
FLAG_NAME(DNF_LEGACY_DRIVER), // 00001000
|
|
FLAG_NAME(DNF_HAS_PROBLEM), // 00002000
|
|
FLAG_NAME(DNF_HAS_PRIVATE_PROBLEM), // 00004000
|
|
FLAG_NAME(DNF_HARDWARE_VERIFICATION), // 00008000
|
|
FLAG_NAME(DNF_DEVICE_GONE), // 00010000
|
|
FLAG_NAME(DNF_LEGACY_RESOURCE_DEVICENODE), // 00020000
|
|
FLAG_NAME(DNF_NEEDS_REBALANCE), // 00040000
|
|
FLAG_NAME(DNF_LOCKED_FOR_EJECT), // 00080000
|
|
FLAG_NAME(DNF_DRIVER_BLOCKED), // 00100000
|
|
{0,0}
|
|
};
|
|
|
|
FLAG_NAME DeviceNodeUserFlags[] = {
|
|
FLAG_NAME(DNUF_WILL_BE_REMOVED), // 00000001
|
|
FLAG_NAME(DNUF_DONT_SHOW_IN_UI), // 00000002
|
|
FLAG_NAME(DNUF_NEED_RESTART), // 00000004
|
|
FLAG_NAME(DNUF_NOT_DISABLEABLE), // 00000008
|
|
FLAG_NAME(DNUF_SHUTDOWN_QUERIED), // 00000010
|
|
FLAG_NAME(DNUF_SHUTDOWN_SUBTREE_DONE), // 00000020
|
|
{0,0}
|
|
};
|
|
|
|
#define DeviceD1 0x00000001
|
|
#define DeviceD2 0x00000002
|
|
#define LockSupported 0x00000004
|
|
#define EjectSupported 0x00000008
|
|
#define Removable 0x00000010
|
|
#define DockDevice 0x00000020
|
|
#define UniqueID 0x00000040
|
|
#define SilentInstall 0x00000080
|
|
#define RawDeviceOK 0x00000100
|
|
#define SurpriseRemovalOK 0x00000200
|
|
#define WakeFromD0 0x00000400
|
|
#define WakeFromD1 0x00000800
|
|
#define WakeFromD2 0x00001000
|
|
#define WakeFromD3 0x00002000
|
|
#define HardwareDisabled 0x00004000
|
|
#define NonDynamic 0x00008000
|
|
#define WarmEjectSupported 0x00010000
|
|
#define NoDisplayInUI 0x00020000
|
|
|
|
FLAG_NAME DeviceNodeCapabilityFlags[] = {
|
|
FLAG_NAME(DeviceD1), // 00000001
|
|
FLAG_NAME(DeviceD2), // 00000002
|
|
FLAG_NAME(LockSupported), // 00000004
|
|
FLAG_NAME(EjectSupported), // 00000008
|
|
FLAG_NAME(Removable), // 00000010
|
|
FLAG_NAME(DockDevice), // 00000020
|
|
FLAG_NAME(UniqueID), // 00000040
|
|
FLAG_NAME(SilentInstall), // 00000080
|
|
FLAG_NAME(RawDeviceOK), // 00000100
|
|
FLAG_NAME(SurpriseRemovalOK), // 00000200
|
|
FLAG_NAME(WakeFromD0), // 00000400
|
|
FLAG_NAME(WakeFromD1), // 00000800
|
|
FLAG_NAME(WakeFromD2), // 00001000
|
|
FLAG_NAME(WakeFromD3), // 00002000
|
|
FLAG_NAME(HardwareDisabled), // 00004000
|
|
FLAG_NAME(NonDynamic), // 00008000
|
|
FLAG_NAME(WarmEjectSupported), // 00010000
|
|
FLAG_NAME(NoDisplayInUI), // 00020000
|
|
{0,0}
|
|
};
|
|
|
|
#define PROBLEM_MAP_SIZE 0x33
|
|
|
|
#if PROBLEM_MAP_SIZE != NUM_CM_PROB
|
|
#error Add new problem code to DevNodeProblems and update PROBLEM_MAP_SIZE.
|
|
#endif
|
|
|
|
PUCHAR DevNodeProblems[] = {
|
|
NULL,
|
|
"CM_PROB_NOT_CONFIGURED",
|
|
"CM_PROB_DEVLOADER_FAILED",
|
|
"CM_PROB_OUT_OF_MEMORY",
|
|
"CM_PROB_ENTRY_IS_WRONG_TYPE",
|
|
"CM_PROB_LACKED_ARBITRATOR",
|
|
"CM_PROB_BOOT_CONFIG_CONFLICT",
|
|
"CM_PROB_FAILED_FILTER",
|
|
"CM_PROB_DEVLOADER_NOT_FOUND",
|
|
"CM_PROB_INVALID_DATA",
|
|
"CM_PROB_FAILED_START",
|
|
"CM_PROB_LIAR",
|
|
"CM_PROB_NORMAL_CONFLICT",
|
|
"CM_PROB_NOT_VERIFIED",
|
|
"CM_PROB_NEED_RESTART",
|
|
"CM_PROB_REENUMERATION",
|
|
"CM_PROB_PARTIAL_LOG_CONF",
|
|
"CM_PROB_UNKNOWN_RESOURCE",
|
|
"CM_PROB_REINSTALL",
|
|
"CM_PROB_REGISTRY",
|
|
"CM_PROB_VXDLDR",
|
|
"CM_PROB_WILL_BE_REMOVED",
|
|
"CM_PROB_DISABLED",
|
|
"CM_PROB_DEVLOADER_NOT_READY",
|
|
"CM_PROB_DEVICE_NOT_THERE",
|
|
"CM_PROB_MOVED",
|
|
"CM_PROB_TOO_EARLY",
|
|
"CM_PROB_NO_VALID_LOG_CONF",
|
|
"CM_PROB_FAILED_INSTALL",
|
|
"CM_PROB_HARDWARE_DISABLED",
|
|
"CM_PROB_CANT_SHARE_IRQ",
|
|
"CM_PROB_FAILED_ADD",
|
|
"CM_PROB_DISABLED_SERVICE",
|
|
"CM_PROB_TRANSLATION_FAILED",
|
|
"CM_PROB_NO_SOFTCONFIG",
|
|
"CM_PROB_BIOS_TABLE",
|
|
"CM_PROB_IRQ_TRANSLATION_FAILED",
|
|
"CM_PROB_FAILED_DRIVER_ENTRY",
|
|
"CM_PROB_DRIVER_FAILED_PRIOR_UNLOAD",
|
|
"CM_PROB_DRIVER_FAILED_LOAD",
|
|
"CM_PROB_DRIVER_SERVICE_KEY_INVALID",
|
|
"CM_PROB_LEGACY_SERVICE_NO_DEVICES",
|
|
"CM_PROB_DUPLICATE_DEVICE",
|
|
"CM_PROB_FAILED_POST_START",
|
|
"CM_PROB_HALTED",
|
|
"CM_PROB_PHANTOM",
|
|
"CM_PROB_SYSTEM_SHUTDOWN",
|
|
"CM_PROB_HELD_FOR_EJECT",
|
|
"CM_PROB_DRIVER_BLOCKED",
|
|
"CM_PROB_REGISTRY_TOO_LARGE",
|
|
"CM_PROB_SETPROPERTIES_FAILED"
|
|
};
|
|
|
|
extern
|
|
VOID
|
|
DevExtIsapnp(
|
|
ULONG64 Extension
|
|
);
|
|
|
|
extern
|
|
VOID
|
|
DevExtPcmcia(
|
|
ULONG64 Extension
|
|
);
|
|
|
|
extern
|
|
VOID
|
|
DevExtHID(
|
|
ULONG64 Extension
|
|
);
|
|
|
|
VOID
|
|
DumpResourceDescriptorHeader(
|
|
ULONG Depth,
|
|
ULONG Number,
|
|
UCHAR Option,
|
|
UCHAR Type,
|
|
UCHAR SharingDisposition,
|
|
USHORT Flags
|
|
);
|
|
|
|
BOOLEAN
|
|
DumpDevNode(
|
|
ULONG64 DeviceNode,
|
|
ULONG Depth,
|
|
BOOLEAN DumpSibling,
|
|
BOOLEAN DumpChild,
|
|
BOOLEAN DumpCmRes,
|
|
BOOLEAN DumpCmResReqList,
|
|
BOOLEAN DumpCmResTrans,
|
|
BOOLEAN DumpOnlyDevnodesWithProblems,
|
|
BOOLEAN DumpOnlyNonStartedDevnodes,
|
|
PUNICODE_STRING ServiceName,
|
|
BOOLEAN PrintDefault,
|
|
BOOLEAN DumpStateHistory
|
|
);
|
|
|
|
BOOLEAN
|
|
DumpPendingEjects(
|
|
BOOLEAN DumpCmRes,
|
|
BOOLEAN DumpCmResReqList,
|
|
BOOLEAN DumpCmResTrans
|
|
);
|
|
|
|
BOOLEAN
|
|
DumpPendingRemovals(
|
|
BOOLEAN DumpCmRes,
|
|
BOOLEAN DumpCmResReqList,
|
|
BOOLEAN DumpCmResTrans
|
|
);
|
|
|
|
|
|
BOOLEAN
|
|
DumpDeviceEventEntry(
|
|
ULONG64 DeviceEvent,
|
|
ULONG64 ListHead,
|
|
BOOL FollowLinks
|
|
);
|
|
VOID
|
|
DumpPlugPlayEventBlock(
|
|
ULONG64 PlugPlayEventBlock,
|
|
ULONG Size
|
|
);
|
|
|
|
|
|
BOOLEAN
|
|
DumpResourceList64(
|
|
LPSTR Description,
|
|
ULONG Depth,
|
|
ULONG64 ResourceList
|
|
);
|
|
|
|
BOOLEAN
|
|
DumpResourceRequirementList64(
|
|
ULONG Depth,
|
|
ULONG64 ResourceRequirementList
|
|
);
|
|
|
|
BOOLEAN
|
|
DumpE820ResourceList64(
|
|
ULONG Depth,
|
|
ULONG64 ResourceList
|
|
);
|
|
|
|
BOOLEAN
|
|
DumpArbiter(
|
|
IN DWORD Depth,
|
|
IN ULONG64 ArbiterAddr,
|
|
IN BOOLEAN DisplayAliases
|
|
);
|
|
|
|
#define ARBITER_DUMP_IO 0x1
|
|
#define ARBITER_DUMP_MEMORY 0x2
|
|
#define ARBITER_DUMP_IRQ 0x4
|
|
#define ARBITER_DUMP_DMA 0x8
|
|
#define ARBITER_DUMP_BUS_NUMBER 0x10
|
|
#define ARBITER_NO_DUMP_ALIASES 0x100
|
|
|
|
#define ARBITER_DUMP_ALL (ARBITER_DUMP_IO | \
|
|
ARBITER_DUMP_MEMORY | \
|
|
ARBITER_DUMP_IRQ | \
|
|
ARBITER_DUMP_DMA | \
|
|
ARBITER_DUMP_BUS_NUMBER)
|
|
|
|
BOOLEAN
|
|
DumpArbitersForDevNode(
|
|
IN DWORD Depth,
|
|
IN ULONG64 DevNodeAddr,
|
|
IN DWORD Flags
|
|
);
|
|
|
|
VOID
|
|
PrintDevNodeState(
|
|
IN ULONG Depth,
|
|
IN PUCHAR Field,
|
|
IN ULONG State
|
|
);
|
|
|
|
DECLARE_API( ioreslist )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump a device object.
|
|
|
|
Arguments:
|
|
|
|
args - the location of the device object to dump.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 requirementList;
|
|
|
|
requirementList = GetExpression(args);
|
|
DumpResourceRequirementList64(0, requirementList);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
DECLARE_API( cmreslist )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump a device object.
|
|
|
|
Arguments:
|
|
|
|
args - the location of the device object to dump.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 resourceList;
|
|
|
|
resourceList = GetExpression(args);
|
|
DumpResourceList64("CmResourceList", 0, resourceList);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
DECLARE_API( e820reslist )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump an e820 resource table
|
|
|
|
Arguments:
|
|
|
|
args - the location of the resources list to dump
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
ULONG64 resourceList;
|
|
|
|
resourceList = GetExpression(args);
|
|
DumpE820ResourceList64(0, resourceList );
|
|
return S_OK;
|
|
}
|
|
|
|
#define DUMP_CHILD 1
|
|
#define DUMP_CM_RES 2
|
|
#define DUMP_CM_RES_REQ_LIST 4
|
|
#define DUMP_CM_RES_TRANS 8
|
|
#define DUMP_NOT_STARTED 0x10
|
|
#define DUMP_PROBLEMS 0x20
|
|
|
|
BOOLEAN
|
|
xReadMemory(
|
|
ULONG64 S,
|
|
PVOID D,
|
|
ULONG Len
|
|
)
|
|
{
|
|
ULONG result;
|
|
|
|
return (ReadMemory((S), D, Len, &result) && (result == Len));
|
|
}
|
|
|
|
DECLARE_API( devnode )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump a device object.
|
|
|
|
Arguments:
|
|
|
|
args - the location of the device object to dump.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 deviceNode=0;
|
|
ULONG verbose = 0;
|
|
PUCHAR buffer = NULL;
|
|
UNICODE_STRING serviceName;
|
|
ANSI_STRING ansiString;
|
|
BOOLEAN serviceNameAllocated = FALSE;
|
|
NTSTATUS status;
|
|
ULONG64 tmp;
|
|
|
|
buffer = LocalAlloc(LPTR, 256);
|
|
if (buffer) {
|
|
|
|
RtlZeroMemory(buffer, 256);
|
|
|
|
if (GetExpressionEx(args, &deviceNode, &args)) {
|
|
if (sscanf(args, "%lx %255s", &verbose, buffer)) {
|
|
|
|
if (buffer [0] != '\0') {
|
|
|
|
RtlInitAnsiString(&ansiString, (PCSZ)buffer);
|
|
|
|
status = RtlAnsiStringToUnicodeString(&serviceName,
|
|
&ansiString,
|
|
TRUE);
|
|
if (NT_SUCCESS(status)) {
|
|
serviceNameAllocated = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
LocalFree(buffer);
|
|
} else if (GetExpressionEx(args, &deviceNode, &args)) {
|
|
if (sscanf(args,"%lx", &tmp)) {
|
|
verbose = (ULONG) tmp;
|
|
}
|
|
}
|
|
|
|
if (deviceNode == 0) {
|
|
ULONG64 addr = GetExpression( "nt!IopRootDeviceNode" );
|
|
ULONG64 dummy;
|
|
|
|
if (addr == 0) {
|
|
dprintf("Error retrieving address of IopRootDeviceNode\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!ReadPointer(addr, &deviceNode)) {
|
|
dprintf("Error reading value of IopRootDeviceNode (%#010p)\n", addr);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
dprintf("Dumping IopRootDeviceNode (= %#08p)\n", deviceNode);
|
|
|
|
} else if (deviceNode == 1) {
|
|
|
|
DumpPendingRemovals((BOOLEAN) ((verbose & DUMP_CM_RES) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_CM_RES_REQ_LIST) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_CM_RES_TRANS) != 0)
|
|
);
|
|
return E_INVALIDARG;
|
|
|
|
} else if (deviceNode == 2) {
|
|
|
|
DumpPendingEjects((BOOLEAN) ((verbose & DUMP_CM_RES) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_CM_RES_REQ_LIST) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_CM_RES_TRANS) != 0)
|
|
);
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
if (serviceNameAllocated) {
|
|
DumpDevNode( deviceNode,
|
|
0,
|
|
FALSE,
|
|
(BOOLEAN) ((verbose & DUMP_CHILD) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_CM_RES) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_CM_RES_REQ_LIST) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_CM_RES_TRANS) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_PROBLEMS) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_NOT_STARTED) != 0),
|
|
&serviceName,
|
|
FALSE,
|
|
TRUE
|
|
);
|
|
RtlFreeUnicodeString(&serviceName);
|
|
} else {
|
|
DumpDevNode( deviceNode,
|
|
0,
|
|
FALSE,
|
|
(BOOLEAN) ((verbose & DUMP_CHILD) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_CM_RES) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_CM_RES_REQ_LIST) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_CM_RES_TRANS) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_PROBLEMS) != 0),
|
|
(BOOLEAN) ((verbose & DUMP_NOT_STARTED) != 0),
|
|
NULL,
|
|
FALSE,
|
|
TRUE
|
|
);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static CCHAR DebugBuffer[300];
|
|
|
|
VOID
|
|
xdprintf(
|
|
ULONG Depth,
|
|
PCCHAR S,
|
|
...
|
|
)
|
|
{
|
|
va_list ap;
|
|
ULONG i;
|
|
|
|
for (i=0; i<Depth; i++) {
|
|
dprintf (" ");
|
|
}
|
|
|
|
va_start(ap, S);
|
|
|
|
vsprintf(DebugBuffer, S, ap);
|
|
|
|
dprintf(DebugBuffer);
|
|
|
|
va_end(ap);
|
|
}
|
|
|
|
VOID
|
|
DumpFlags(
|
|
ULONG Depth,
|
|
LPSTR FlagDescription,
|
|
ULONG Flags,
|
|
PFLAG_NAME FlagTable
|
|
)
|
|
{
|
|
ULONG i;
|
|
ULONG mask = 0;
|
|
ULONG count = 0;
|
|
|
|
UCHAR prolog[64];
|
|
|
|
if (StringCbPrintf(prolog, sizeof(prolog), "%s (%#010x) ", FlagDescription, Flags) != S_OK)
|
|
{
|
|
return;
|
|
}
|
|
|
|
xdprintf(Depth, "%s", prolog);
|
|
|
|
if (Flags == 0) {
|
|
dprintf("\n");
|
|
return;
|
|
}
|
|
|
|
memset(prolog, ' ', strlen(prolog));
|
|
|
|
for (i = 0; FlagTable[i].Name != 0; i++) {
|
|
|
|
PFLAG_NAME flag = &(FlagTable[i]);
|
|
|
|
mask |= flag->Flag;
|
|
|
|
if ((Flags & flag->Flag) == flag->Flag) {
|
|
|
|
//
|
|
// print trailing comma
|
|
//
|
|
|
|
if (count != 0) {
|
|
|
|
dprintf(", ");
|
|
|
|
//
|
|
// Only print two flags per line.
|
|
//
|
|
|
|
if ((count % 2) == 0) {
|
|
dprintf("\n");
|
|
xdprintf(Depth, "%s", prolog);
|
|
}
|
|
}
|
|
|
|
dprintf("%s", flag->Name);
|
|
|
|
count++;
|
|
}
|
|
}
|
|
|
|
dprintf("\n");
|
|
|
|
if ((Flags & (~mask)) != 0) {
|
|
xdprintf(Depth, "%sUnknown flags %#010lx\n", prolog, (Flags & (~mask)));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
BOOLEAN
|
|
DumpE820ResourceList64(
|
|
ULONG Depth,
|
|
ULONG64 ResourceList
|
|
)
|
|
{
|
|
BOOLEAN continueDump = TRUE;
|
|
CHAR Buff[80];
|
|
ULONG i;
|
|
ULONG ListOffset;
|
|
ULONG64 Count;
|
|
ULONG64 Type;
|
|
ULONG64 V1;
|
|
ULONG64 V2;
|
|
|
|
#define Res2(F, V) GetFieldValue(ResourceList, "nt!_ACPI_BIOS_MULTI_NODE", #F, V)
|
|
#define Res(F) GetFieldValue(ResourceList, "nt!_ACPI_BIOS_MULTI_NODE", #F, F)
|
|
#define Entry(F,V) (sprintf(Buff,"E820Entry[%lx].%s",i,#F),\
|
|
GetFieldValue(ResourceList,"nt!_ACPI_BIOS_MULTI_NODE", Buff, V))
|
|
|
|
|
|
if (ResourceList == 0) {
|
|
goto GetOut;
|
|
}
|
|
if (Res(Count)) {
|
|
goto GetOut;
|
|
}
|
|
if (Count == 0) {
|
|
goto GetOut;
|
|
}
|
|
|
|
xdprintf(Depth, "ACPI_BIOS_MULTI_NODE (an E820 Resource List) at %#010p\n", ResourceList);
|
|
Depth++;
|
|
|
|
for (i = 0; i < Count; i++) {
|
|
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
break;
|
|
}
|
|
Entry(Type,Type);
|
|
|
|
switch(Type) {
|
|
case 1: // AcpiAddressRangeMemory
|
|
xdprintf(Depth,"Memory - ");
|
|
break;
|
|
case 2: // AcpiAddressRangeReserved
|
|
xdprintf(Depth,"Reserved - ");
|
|
break;
|
|
case 3: // AcpiAddressRangeACPI
|
|
xdprintf(Depth,"ACPI - ");
|
|
break;
|
|
case 4: // AcpiAddressRangeNVS
|
|
xdprintf(Depth,"NVS - ");
|
|
break;
|
|
case 5: // AcpiAddressRangeMaximum
|
|
default:
|
|
xdprintf(Depth,"Unknown - ");
|
|
break;
|
|
}
|
|
|
|
Entry(Base.QuadPart, V1);
|
|
Entry(Length.QuadPart, V2);
|
|
dprintf( "%16I64x - %#16I64x (Length %#10I64x)", V1, (V1 + V2 - 1), V2 );
|
|
if (Type == 2) {
|
|
dprintf(" [Ignored]");
|
|
}
|
|
if (Type == 3 || Type == 4) {
|
|
if (V2 > 0xFFFFFFFF) {
|
|
dprintf(" [Illegal Range]");
|
|
}
|
|
}
|
|
dprintf("\n");
|
|
}
|
|
GetOut:
|
|
#undef Res
|
|
#undef Res2
|
|
#undef Entry
|
|
return continueDump;
|
|
}
|
|
|
|
BOOLEAN
|
|
DumpResourceRequirementList64(
|
|
ULONG Depth,
|
|
ULONG64 ResourceRequirementList
|
|
)
|
|
{
|
|
ULONG64 requirementList = 0;
|
|
ULONG64 resourceList;
|
|
ULONG64 descriptors;
|
|
ULONG ListSize;
|
|
|
|
ULONG i;
|
|
ULONG j;
|
|
ULONG k;
|
|
ULONG result;
|
|
BOOLEAN continueDump = TRUE;
|
|
ULONG InterfaceType, BusNumber, SlotNumber, Reserved1, Reserved2, Reserved3;
|
|
ULONG AlternativeLists;
|
|
ULONG ListOffset, SizeOfIoResList, SizeofIoDesc;
|
|
|
|
#define Res2(F, V) GetFieldValue(ResourceRequirementList, "nt!_IO_RESOURCE_REQUIREMENTS_LIST", #F, V)
|
|
#define Res(F) GetFieldValue(ResourceRequirementList, "nt!_IO_RESOURCE_REQUIREMENTS_LIST", #F, F)
|
|
|
|
if (ResourceRequirementList == 0) {
|
|
goto GetOut;
|
|
}
|
|
|
|
if (Res(ListSize)) {
|
|
goto GetOut;
|
|
}
|
|
|
|
if (ListSize == 0) {
|
|
goto GetOut;
|
|
}
|
|
|
|
Res(InterfaceType); Res(BusNumber); Res(SlotNumber);
|
|
xdprintf(Depth, "IoResList at ");
|
|
dprintf("%#010p : Interface %#x Bus %#x Slot %#x\n",
|
|
ResourceRequirementList,
|
|
InterfaceType,
|
|
BusNumber,
|
|
SlotNumber);
|
|
|
|
Res2(Reserved[0], Reserved1); Res2(Reserved[1], Reserved2);
|
|
Res2(Reserved[2], Reserved3);
|
|
if ((Reserved1 |
|
|
Reserved2 |
|
|
Reserved3) != 0) {
|
|
|
|
xdprintf(Depth, "Reserved Values = {%#010lx, %#010lx, %#010lx}\n",
|
|
Reserved1,
|
|
Reserved2,
|
|
Reserved3);
|
|
}
|
|
|
|
Depth++;
|
|
|
|
Res(AlternativeLists);
|
|
GetFieldOffset("nt!_IO_RESOURCE_REQUIREMENTS_LIST", "List", &ListOffset);
|
|
resourceList = ResourceRequirementList + ListOffset;
|
|
SizeOfIoResList = GetTypeSize("IO_RESOURCE_LIST");
|
|
SizeofIoDesc = GetTypeSize("IO_RESOURCE_DESCRIPTOR");
|
|
for (i = 0; i < AlternativeLists; i++) {
|
|
ULONG Version, Revision, Count;
|
|
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
break;
|
|
}
|
|
|
|
GetFieldValue(resourceList, "nt!_IO_RESOURCE_LIST", "Version", Version);
|
|
GetFieldValue(resourceList, "nt!_IO_RESOURCE_LIST", "Revision", Revision);
|
|
GetFieldValue(resourceList, "nt!_IO_RESOURCE_LIST", "Count", Count);
|
|
|
|
xdprintf(Depth, "Alternative %d (Version %d.%d)\n",
|
|
i,
|
|
Version,
|
|
Revision);
|
|
|
|
Depth++;
|
|
|
|
for (j = 0; j < Count; j++) {
|
|
CHAR Buff[80];
|
|
ULONG64 Q1, Q2;
|
|
ULONG Option, Type, ShareDisposition, Flags, V1, V2, V3, Data[3];
|
|
|
|
#define Desc(F,V) (sprintf(Buff,"Descriptors[%lx].%s",j, #F), \
|
|
GetFieldValue(resourceList, "nt!_IO_RESOURCE_LIST", Buff, V))
|
|
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
goto GetOut;
|
|
}
|
|
|
|
// descriptors = resourceList->Descriptors + j;
|
|
|
|
Desc(Option,Option); Desc(Type,Type);
|
|
Desc(ShareDisposition,ShareDisposition);
|
|
Desc(Flags,Flags);
|
|
|
|
DumpResourceDescriptorHeader(Depth,
|
|
j,
|
|
(UCHAR)Option,
|
|
(UCHAR) Type,
|
|
(UCHAR) ShareDisposition,
|
|
(USHORT) Flags);
|
|
|
|
Depth++;
|
|
|
|
switch (Type) {
|
|
case CmResourceTypeBusNumber:
|
|
|
|
Desc(u.BusNumber.MinBusNumber, V1);
|
|
Desc(u.BusNumber.MaxBusNumber, V2);
|
|
Desc(u.BusNumber.Length, V3);
|
|
xdprintf(Depth, "0x%x - 0x%x for length 0x%x\n",
|
|
V1, V2, V3);
|
|
break;
|
|
|
|
case CmResourceTypePort:
|
|
case CmResourceTypeMemory:
|
|
Desc(u.Generic.Length, V1);
|
|
Desc(u.Generic.Alignment, V2);
|
|
Desc(u.Port.MinimumAddress.QuadPart, Q1);
|
|
Desc(u.Port.MaximumAddress.QuadPart, Q2);
|
|
xdprintf(Depth, "%#08lx byte range with alignment %#08lx\n", V1, V2);
|
|
xdprintf(Depth, "%I64x - %#I64x\n", Q1, Q2);
|
|
break;
|
|
|
|
case CmResourceTypeInterrupt:
|
|
|
|
Desc(u.Interrupt.MinimumVector,V1);
|
|
Desc(u.Interrupt.MaximumVector,V2);
|
|
xdprintf(Depth, "0x%x - 0x%x\n", V1,V2);
|
|
break;
|
|
|
|
default:
|
|
Desc(u.DevicePrivate.Data, Data);
|
|
xdprintf(Depth,
|
|
"Data: : 0x%x 0x%x 0x%x\n",
|
|
Data[0],
|
|
Data[1],
|
|
Data[2]);
|
|
break;
|
|
}
|
|
|
|
Depth--;
|
|
#undef Desc
|
|
}
|
|
|
|
Depth--;
|
|
|
|
resourceList += (SizeOfIoResList + SizeofIoDesc*(j-1));
|
|
}
|
|
|
|
GetOut:
|
|
xdprintf(Depth, "\n");
|
|
#undef Res
|
|
#undef Res2
|
|
return continueDump;
|
|
}
|
|
|
|
BOOLEAN
|
|
DumpResourceList64(
|
|
LPSTR Description,
|
|
ULONG Depth,
|
|
ULONG64 ResourceList
|
|
)
|
|
{
|
|
ULONG64 resourceListWalker;
|
|
ULONG i;
|
|
ULONG j;
|
|
ULONG k;
|
|
BOOLEAN continueDump = TRUE;
|
|
ULONG Count, ListSize, ListOffset;
|
|
ULONG64 ListAddr;
|
|
|
|
if (ResourceList == 0) {
|
|
|
|
goto GetOut;
|
|
}
|
|
|
|
resourceListWalker = ResourceList;
|
|
|
|
if (GetFieldOffset("nt!_CM_RESOURCE_LIST", "List", &ListOffset)) {
|
|
goto GetOut;
|
|
}
|
|
ListAddr = ResourceList + ListOffset;
|
|
|
|
|
|
GetFieldValue(ResourceList, "nt!_CM_RESOURCE_LIST", "Count", Count);
|
|
|
|
|
|
resourceListWalker = ListAddr;
|
|
|
|
for (i = 0; i < Count; i++) {
|
|
ULONG Partial_Count=0, PartialListAddr, BusNumber=0, Partial_Version=0, Partial_Revision=0;
|
|
CHAR ResListType[] = "nt!_CM_FULL_RESOURCE_DESCRIPTOR";
|
|
ULONG64 InterfaceType=0;
|
|
ULONG PartDescOffset;
|
|
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
break;
|
|
}
|
|
|
|
GetFieldValue(resourceListWalker, ResListType, "InterfaceType", InterfaceType);
|
|
GetFieldValue(resourceListWalker, ResListType, "BusNumber", BusNumber);
|
|
GetFieldValue(resourceListWalker, ResListType, "PartialResourceList.Version", Partial_Version);
|
|
GetFieldValue(resourceListWalker, ResListType, "PartialResourceList.Revision", Partial_Revision);
|
|
GetFieldValue(resourceListWalker, ResListType, "PartialResourceList.Count", Partial_Count);
|
|
|
|
GetFieldOffset(ResListType, "PartialResourceList.PartialDescriptors", &PartDescOffset);
|
|
resourceListWalker = resourceListWalker + PartDescOffset;
|
|
|
|
xdprintf(Depth, "%s at ", Description);
|
|
dprintf("%#010p Version %d.%d Interface %#x Bus #%#x\n",
|
|
ResourceList,
|
|
Partial_Version,
|
|
Partial_Revision,
|
|
(ULONG) InterfaceType,
|
|
BusNumber);
|
|
|
|
Depth++;
|
|
|
|
for (j = 0; j < Partial_Count; j++) {
|
|
CHAR PartResType[] = "nt!_CM_PARTIAL_RESOURCE_DESCRIPTOR";
|
|
ULONG Type=0, ShareDisposition=0, Flags=0, sz, u_Port_Length=0, u_Memory_Length=0,
|
|
u_Interrupt_Level=0, u_Interrupt_Vector=0,
|
|
u_Dma_Channel=0, u_Dma_Port=0, u_Dma_Reserved1=0, u_BusNumber_Start=0,
|
|
u_BusNumber_Length=0, u_DevicePrivate_Data[3];
|
|
ULONG64 u_Port_QuadPart=0, u_Memory_QuadPart=0, u_Interrupt_Affinity=0;
|
|
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
goto GetOut;
|
|
}
|
|
|
|
sz = GetTypeSize(PartResType);
|
|
if (GetFieldValue(resourceListWalker,
|
|
PartResType,
|
|
"Type",
|
|
Type)) {
|
|
goto GetOut;
|
|
}
|
|
GetFieldValue(resourceListWalker, PartResType, "ShareDisposition", ShareDisposition);
|
|
GetFieldValue(resourceListWalker, PartResType, "Flags", Flags);
|
|
|
|
|
|
xdprintf(Depth, "Entry %d - %s (%#x) %s (%#x)\n",
|
|
j,
|
|
(Type == CmResourceTypeNull ? "Null" :
|
|
Type == CmResourceTypePort ? "Port" :
|
|
Type == CmResourceTypeInterrupt ? "Interrupt" :
|
|
Type == CmResourceTypeMemory ? "Memory" :
|
|
Type == CmResourceTypeDma ? "Dma" :
|
|
Type == CmResourceTypeDeviceSpecific ? "DeviceSpecific" :
|
|
Type == CmResourceTypeBusNumber ? "BusNumber" :
|
|
Type == CmResourceTypeDevicePrivate ? "DevicePrivate" :
|
|
Type == CmResourceTypeConfigData ? "ConfigData" : "Unknown"),
|
|
Type,
|
|
(ShareDisposition == CmResourceShareUndetermined ? "Undetermined Sharing" :
|
|
ShareDisposition == CmResourceShareDeviceExclusive ? "Device Exclusive" :
|
|
ShareDisposition == CmResourceShareDriverExclusive ? "Driver Exclusive" :
|
|
ShareDisposition == CmResourceShareShared ? "Shared" : "Unknown Sharing"),
|
|
ShareDisposition);
|
|
|
|
Depth++;
|
|
|
|
xdprintf(Depth, "Flags (%#04wx) - ", Flags);
|
|
|
|
switch (Type) {
|
|
|
|
case CmResourceTypePort:
|
|
|
|
//
|
|
// CM_RESOURCE_PORT_MEMORY = ~CM_RESOURCE_PORT_IO
|
|
//
|
|
if ( (~Flags) & ~CM_RESOURCE_PORT_MEMORY) {
|
|
dprintf("PORT_MEMORY ");
|
|
}
|
|
if (Flags & CM_RESOURCE_PORT_IO) {
|
|
dprintf("PORT_IO ");
|
|
}
|
|
if (Flags & CM_RESOURCE_PORT_10_BIT_DECODE) {
|
|
dprintf("10_BIT_DECODE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_PORT_12_BIT_DECODE) {
|
|
dprintf("12_BIT_DECODE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_PORT_16_BIT_DECODE) {
|
|
dprintf("16_BIT_DECODE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_PORT_POSITIVE_DECODE) {
|
|
dprintf("POSITIVE_DECODE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_PORT_PASSIVE_DECODE) {
|
|
dprintf ("PASSIVE_DECODE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_PORT_WINDOW_DECODE) {
|
|
dprintf ("WINDOW_DECODE ");
|
|
}
|
|
|
|
dprintf("\n");
|
|
|
|
GetFieldValue(resourceListWalker, PartResType, "u.Port.Start.QuadPart", u_Port_QuadPart);
|
|
GetFieldValue(resourceListWalker, PartResType, "u.Port.Length", u_Port_Length);
|
|
|
|
xdprintf(Depth, "Range starts at %#I64lx for %#x bytes\n",
|
|
u_Port_QuadPart,
|
|
u_Port_Length);
|
|
|
|
break;
|
|
|
|
case CmResourceTypeMemory:
|
|
|
|
if (Flags == CM_RESOURCE_MEMORY_READ_WRITE) {
|
|
dprintf("READ_WRITE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_MEMORY_READ_ONLY) {
|
|
dprintf("READ_ONLY ");
|
|
}
|
|
if (Flags & CM_RESOURCE_MEMORY_WRITE_ONLY) {
|
|
dprintf("WRITE_ONLY ");
|
|
}
|
|
if (Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) {
|
|
dprintf("PREFETCHABLE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_MEMORY_COMBINEDWRITE) {
|
|
dprintf("COMBINEDWRITE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_MEMORY_24) {
|
|
dprintf("MEMORY_24 ");
|
|
}
|
|
|
|
dprintf("\n");
|
|
|
|
GetFieldValue(resourceListWalker, PartResType, "u.Memory.Start.QuadPart", u_Memory_QuadPart);
|
|
GetFieldValue(resourceListWalker, PartResType, "u.Memory.Length", u_Memory_Length);
|
|
|
|
xdprintf(Depth, "Range starts at %#018I64lx for %#x bytes\n",
|
|
u_Memory_QuadPart,
|
|
u_Memory_Length);
|
|
|
|
break;
|
|
|
|
case CmResourceTypeInterrupt:
|
|
|
|
if (Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) {
|
|
dprintf("LEVEL_SENSITIVE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_INTERRUPT_LATCHED) {
|
|
dprintf("LATCHED ");
|
|
}
|
|
|
|
dprintf("\n");
|
|
|
|
GetFieldValue(resourceListWalker, PartResType, "u.Interrupt.Level", u_Interrupt_Level);
|
|
GetFieldValue(resourceListWalker, PartResType, "u.Interrupt.Vector", u_Interrupt_Vector);
|
|
GetFieldValue(resourceListWalker, PartResType, "u.Interrupt.Affinity", u_Interrupt_Affinity);
|
|
|
|
xdprintf(Depth, "Level %#x, Vector %#x, Affinity %#I64x\n",
|
|
u_Interrupt_Level,
|
|
u_Interrupt_Vector,
|
|
u_Interrupt_Affinity);
|
|
|
|
break;
|
|
|
|
case CmResourceTypeDma:
|
|
|
|
if (Flags & CM_RESOURCE_DMA_8) {
|
|
dprintf("DMA_8 ");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_16) {
|
|
dprintf("DMA_16 ");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_32) {
|
|
dprintf("DMA_32 ");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_8_AND_16) {
|
|
dprintf("DMA_8_AND_16 ");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_BUS_MASTER) {
|
|
dprintf("DMA_BUS_MASTER ");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_TYPE_A) {
|
|
dprintf("DMA_A ");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_TYPE_B) {
|
|
dprintf("DMA_B ");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_TYPE_F) {
|
|
dprintf("DMA_F ");
|
|
}
|
|
dprintf("\n");
|
|
|
|
GetFieldValue(resourceListWalker, PartResType, "u.Dma.Channel", u_Dma_Channel);
|
|
GetFieldValue(resourceListWalker, PartResType, "u.Dma.Port", u_Dma_Port);
|
|
GetFieldValue(resourceListWalker, PartResType, "u.Dma.Reserved1", u_Dma_Reserved1);
|
|
|
|
xdprintf(Depth, "Channel %#x Port %#x (Reserved1 %#x)\n",
|
|
u_Dma_Channel,
|
|
u_Dma_Port,
|
|
u_Dma_Reserved1);
|
|
break;
|
|
|
|
case CmResourceTypeBusNumber:
|
|
|
|
dprintf("\n");
|
|
|
|
GetFieldValue(resourceListWalker, PartResType, "u.BusNumber.Start", u_BusNumber_Start);
|
|
GetFieldValue(resourceListWalker, PartResType, "u.BusNumber.Length", u_BusNumber_Length);
|
|
|
|
xdprintf(Depth, "Range starts at %#010lx for %#x values\n",
|
|
u_BusNumber_Start,
|
|
u_BusNumber_Length);
|
|
break;
|
|
|
|
default:
|
|
|
|
dprintf("\n");
|
|
|
|
GetFieldValue(resourceListWalker, PartResType, "u.DevicePrivate.Data", u_DevicePrivate_Data);
|
|
|
|
xdprintf(Depth, "Data - {%#010lx, %#010lx, %#010lx}\n",
|
|
u_DevicePrivate_Data[0],
|
|
u_DevicePrivate_Data[1],
|
|
u_DevicePrivate_Data[2]);
|
|
break;
|
|
}
|
|
|
|
Depth--;
|
|
resourceListWalker += sz; // sizeof(partialDescriptors);
|
|
}
|
|
}
|
|
|
|
GetOut:
|
|
xdprintf(Depth, "\n");
|
|
|
|
return continueDump;
|
|
}
|
|
|
|
BOOLEAN
|
|
DumpRelationsList(
|
|
ULONG64 RelationsList,
|
|
BOOLEAN DumpCmRes,
|
|
BOOLEAN DumpCmResReqList,
|
|
BOOLEAN DumpCmResTrans
|
|
)
|
|
{
|
|
ULONG64 listEntryAddr;
|
|
ULONG64 deviceObjectAddr;
|
|
ULONG i, j, EntrySize;
|
|
BOOLEAN continueDump = TRUE;
|
|
CHAR RelListType[] = "nt!_RELATION_LIST", RelListentryType[] = "nt!_RELATION_LIST_ENTRY";
|
|
ULONG64 EntryAddr;
|
|
ULONG Count=0, TagCount=0, FirstLevel=0, MaxLevel=0;
|
|
ULONG EntryOffset;
|
|
|
|
if (GetFieldValue(RelationsList, RelListType, "Count",Count)) {
|
|
xdprintf(1, "Error reading relation list @ ");
|
|
dprintf("0x%08p)\n", RelationsList);
|
|
return continueDump;
|
|
}
|
|
EntrySize = DBG_PTR_SIZE;
|
|
GetFieldOffset(RelListType, "Entries", &EntryOffset);
|
|
EntryAddr=RelationsList + EntryOffset;
|
|
|
|
|
|
GetFieldValue(RelationsList, RelListType, "TagCount", TagCount);
|
|
GetFieldValue(RelationsList, RelListType, "FirstLevel", FirstLevel);
|
|
GetFieldValue(RelationsList, RelListType, "MaxLevel", MaxLevel);
|
|
|
|
xdprintf(1, "Relation List @ "); dprintf("0x%08p\n", RelationsList);
|
|
xdprintf(2, "Count = %d, TagCount = %d, FirstLevel = %d, MaxLevel = %d\n",
|
|
Count,
|
|
TagCount,
|
|
FirstLevel,
|
|
MaxLevel);
|
|
|
|
for (i = 0; i <= (MaxLevel - FirstLevel); i++) {
|
|
ULONG res,Entry_Count=0, MaxCount=0, DeviceSize;
|
|
ULONG64 DeviceAddr;
|
|
FIELD_INFO relListEntryFields[] = {
|
|
{"Devices", "", 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL},
|
|
};
|
|
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
break;
|
|
}
|
|
|
|
listEntryAddr = 0;
|
|
if (ReadPointer( EntryAddr + i*EntrySize,
|
|
&listEntryAddr)) {
|
|
|
|
if (!listEntryAddr) {
|
|
xdprintf(2, "Null relation list entry\n");
|
|
|
|
}else if (!GetFieldValue(listEntryAddr, RelListentryType,
|
|
"Count",Entry_Count)) {
|
|
ULONG DeviceOffset;
|
|
|
|
GetFieldOffset(RelListentryType, "Devices", &DeviceOffset);
|
|
DeviceAddr = listEntryAddr + DeviceOffset;
|
|
DeviceSize = EntrySize; // == pointer size
|
|
|
|
|
|
GetFieldValue(listEntryAddr, RelListentryType, "MaxCount", MaxCount);
|
|
|
|
xdprintf(2, "Relation List Entry @ "); dprintf("0x%08p\n", listEntryAddr);
|
|
xdprintf(3, "Count = %d, MaxCount = %d\n", Entry_Count, MaxCount);
|
|
xdprintf(3, "Devices at level %d\n", FirstLevel + i);
|
|
|
|
|
|
for (j = 0; j < Entry_Count; j++) {
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (ReadPointer( DeviceAddr + j*DeviceSize,
|
|
&deviceObjectAddr)) {
|
|
ULONG64 DeviceNode=0;
|
|
FIELD_INFO DevObjFields[] = {
|
|
// Implicitly reads the pointer DeviceObjectExtension and its field DeviceNode
|
|
{"DeviceObjectExtension", "", 0, DBG_DUMP_FIELD_RECUR_ON_THIS, 0, NULL},
|
|
{"DeviceObjectExtension.DeviceNode", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &DeviceNode}
|
|
};
|
|
|
|
if (!deviceObjectAddr) {
|
|
continue;
|
|
}
|
|
|
|
xdprintf(4, "Device Object = ");
|
|
dprintf("0x%08p (%sagged, %sirect)\n",
|
|
deviceObjectAddr & ~3,
|
|
(deviceObjectAddr & 1) ? "T" : "Not t",
|
|
(deviceObjectAddr & 2) ? "D" : "Ind");
|
|
|
|
if (!GetFieldValue(deviceObjectAddr, "nt!_DEVICE_OBJECT",
|
|
"DeviceObjectExtension.DeviceNode",
|
|
DeviceNode)) {
|
|
if (DeviceNode) {
|
|
continueDump = DumpDevNode(DeviceNode,
|
|
5,
|
|
FALSE,
|
|
FALSE,
|
|
DumpCmRes,
|
|
DumpCmResReqList,
|
|
DumpCmResTrans,
|
|
FALSE,
|
|
FALSE,
|
|
(PUNICODE_STRING)NULL,
|
|
TRUE,
|
|
TRUE
|
|
);
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
xdprintf(5, "Error reading device object @ ");
|
|
dprintf("0x%08p)\n",deviceObjectAddr);
|
|
}
|
|
} else {
|
|
|
|
xdprintf(4, "Error reading relation list entry device ");
|
|
dprintf("%d @ 0x%08p)\n",
|
|
j,
|
|
DeviceAddr + j*DeviceSize);
|
|
}
|
|
if (!continueDump) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
xdprintf(2, "Error reading relation list entry @ ");
|
|
dprintf("0x%08p)\n",
|
|
listEntryAddr);
|
|
}
|
|
} else {
|
|
xdprintf(1, "Error reading relation list entry ");
|
|
dprintf("%d @ 0x%08p)\n",
|
|
i,
|
|
EntryAddr + i*EntrySize);
|
|
}
|
|
if (!continueDump) {
|
|
break;
|
|
}
|
|
}
|
|
return continueDump;
|
|
}
|
|
|
|
BOOLEAN
|
|
DumpPendingRemovals(
|
|
BOOLEAN DumpCmRes,
|
|
BOOLEAN DumpCmResReqList,
|
|
BOOLEAN DumpCmResTrans
|
|
)
|
|
{
|
|
ULONG64 listHeadAddr, pendingEntryAddr;
|
|
BOOLEAN continueDump = TRUE;
|
|
ULONG64 Head_Blink=0, Head_Flink=0, Link_Flink=0;
|
|
|
|
listHeadAddr = GetExpression( "nt!IopPendingSurpriseRemovals" );
|
|
|
|
if (listHeadAddr == 0) {
|
|
dprintf("Error retrieving address of IopPendingSurpriseRemovals\n");
|
|
return continueDump;
|
|
}
|
|
|
|
if (GetFieldValue(listHeadAddr, "nt!_LIST_ENTRY", "Flink", Head_Flink) ||
|
|
GetFieldValue(listHeadAddr, "nt!_LIST_ENTRY", "Blink", Head_Blink)) {
|
|
dprintf("Error reading value of IopPendingSurpriseRemovals (0x%08p)\n", listHeadAddr);
|
|
return continueDump;
|
|
}
|
|
|
|
if (Head_Flink == listHeadAddr) {
|
|
dprintf("There are no removals currently pending\n");
|
|
return continueDump;
|
|
}
|
|
|
|
for (pendingEntryAddr = Head_Flink;
|
|
pendingEntryAddr != listHeadAddr;
|
|
pendingEntryAddr = Link_Flink) {
|
|
ULONG64 RelationsList=0, DeviceObject=0;
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
break;
|
|
}
|
|
|
|
|
|
if (GetFieldValue(pendingEntryAddr, "nt!_PENDING_RELATIONS_LIST_ENTRY", "DeviceObject", DeviceObject)){
|
|
dprintf("Error reading pending relations list entry (0x%08p)\n", pendingEntryAddr);
|
|
return continueDump;
|
|
}
|
|
GetFieldValue(pendingEntryAddr, "nt!_PENDING_RELATIONS_LIST_ENTRY", "Link.Flink", Link_Flink);
|
|
GetFieldValue(pendingEntryAddr, "nt!_PENDING_RELATIONS_LIST_ENTRY", "RelationsList", RelationsList);
|
|
|
|
dprintf("Pending Removal of PDO 0x%08p, Pending Relations List Entry @ 0x%08p\n",
|
|
DeviceObject,
|
|
pendingEntryAddr
|
|
);
|
|
|
|
continueDump = DumpRelationsList( RelationsList,
|
|
DumpCmRes,
|
|
DumpCmResReqList,
|
|
DumpCmResTrans
|
|
);
|
|
|
|
if (!continueDump) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return continueDump;
|
|
}
|
|
|
|
BOOLEAN
|
|
DumpPendingEjects(
|
|
BOOLEAN DumpCmRes,
|
|
BOOLEAN DumpCmResReqList,
|
|
BOOLEAN DumpCmResTrans
|
|
)
|
|
{
|
|
ULONG64 listHeadAddr, pendingEntryAddr;
|
|
BOOLEAN continueDump = TRUE;
|
|
ULONG64 Head_Blink=0, Head_Flink=0, Link_Flink=0;
|
|
|
|
listHeadAddr = GetExpression( "nt!IopPendingEjects" );
|
|
|
|
if (listHeadAddr == 0) {
|
|
dprintf("Error retrieving address of IopEjects\n");
|
|
return continueDump;
|
|
}
|
|
|
|
if (GetFieldValue(listHeadAddr, "nt!_LIST_ENTRY", "Flink", Head_Flink) ||
|
|
GetFieldValue(listHeadAddr, "nt!_LIST_ENTRY", "Blink", Head_Blink)) {
|
|
dprintf("Error reading value of IopPendingSurpriseRemovals (0x%08p)\n", listHeadAddr);
|
|
return continueDump;
|
|
}
|
|
|
|
if (Head_Flink == listHeadAddr) {
|
|
dprintf("There are no ejects currently pending\n");
|
|
return continueDump;
|
|
}
|
|
|
|
for (pendingEntryAddr = Head_Flink;
|
|
pendingEntryAddr != listHeadAddr;
|
|
pendingEntryAddr = Link_Flink) {
|
|
ULONG64 RelationsList=0, DeviceObject=0, EjectIrp=0;
|
|
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (GetFieldValue(pendingEntryAddr, "nt!_PENDING_RELATIONS_LIST_ENTRY", "DeviceObject", DeviceObject)){
|
|
dprintf("Error reading pending relations list entry (0x%08p)\n", pendingEntryAddr);
|
|
return continueDump;
|
|
}
|
|
GetFieldValue(pendingEntryAddr, "nt!_PENDING_RELATIONS_LIST_ENTRY", "Link.Flink", Link_Flink);
|
|
GetFieldValue(pendingEntryAddr, "nt!_PENDING_RELATIONS_LIST_ENTRY", "RelationsList", RelationsList);
|
|
GetFieldValue(pendingEntryAddr, "nt!_PENDING_RELATIONS_LIST_ENTRY", "EjectIrp", EjectIrp);
|
|
|
|
dprintf("Pending Eject of PDO 0x%08p, EjectIrp = 0x%08p, \nPending Relations List Entry @ 0x%08p\n",
|
|
DeviceObject,
|
|
EjectIrp,
|
|
pendingEntryAddr
|
|
);
|
|
|
|
continueDump = DumpRelationsList( RelationsList,
|
|
DumpCmRes,
|
|
DumpCmResReqList,
|
|
DumpCmResTrans
|
|
);
|
|
|
|
if (!continueDump) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return continueDump;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
DumpDevNode(
|
|
ULONG64 DeviceNode,
|
|
ULONG Depth,
|
|
BOOLEAN DumpSibling,
|
|
BOOLEAN DumpChild,
|
|
BOOLEAN DumpCmRes,
|
|
BOOLEAN DumpCmResReqList,
|
|
BOOLEAN DumpCmResTrans,
|
|
BOOLEAN DumpOnlyDevnodesWithProblems,
|
|
BOOLEAN DumpOnlyNonStartedDevnodes,
|
|
PUNICODE_STRING ServiceName OPTIONAL,
|
|
BOOLEAN PrintDefault,
|
|
BOOLEAN DumpStateHistory
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays the driver name for the device object if FullDetail == FALSE.
|
|
Otherwise displays more information about the device and the device queue.
|
|
|
|
Arguments:
|
|
|
|
DeviceAddress - address of device object to dump.
|
|
FullDetail - TRUE means the device object name, driver name, and
|
|
information about Irps queued to the device.
|
|
|
|
DumpOnlyDevnodesWithFlags -
|
|
if set, then the only devnodes that will be dumped are
|
|
those with one of the FlagsSet bits set or one of the
|
|
FlagsNotSet bits not set.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG result;
|
|
// DEVICE_NODE deviceNode;
|
|
BOOLEAN print = TRUE;
|
|
BOOLEAN continueDump = TRUE;
|
|
CHAR DevNodeType[]="nt!_DEVICE_NODE";
|
|
USHORT ServiceName_Len=0, ServiceName_MaxLen=0, InstancePath_Len=0, InstancePath_Max=0;
|
|
ULONG Flags=0, BusNumber=0, Header_SignalState=0, UserFlags=0;
|
|
ULONG CapabilityFlags=0, DisableableDepends=0, Problem=0;
|
|
ULONG FailureStatus=0, State=0, PreviousState=0;
|
|
ULONG StateHistoryEntry = 0;
|
|
ULONG StateHistoryValue = 0;
|
|
ULONG64 ServiceName_Buff=0, PhysicalDeviceObject=0, Parent=0, Sibling=0,
|
|
Child=0, InterfaceType=0, DuplicatePDO=0, TargetDeviceNotify_Blink=0, TargetDeviceNotify_Flink=0,
|
|
PreviousResourceList=0, ResourceList=0, BootResources=0, ResourceListTranslated=0,
|
|
ResourceRequirements=0, InstancePath_Buff=0, PreviousResourceRequirements=0;
|
|
ULONG64 TargetDeviceNotifyAddress;
|
|
ULONG AmountRead;
|
|
|
|
PNP_DEVNODE_STATE StateHistory[STATE_HISTORY_SIZE];
|
|
|
|
if (CheckControlC()) {
|
|
return FALSE;
|
|
}
|
|
|
|
GetFieldOffset("nt!_DEVICE_NODE", "TargetDeviceNotify", &result);
|
|
TargetDeviceNotifyAddress = DeviceNode + result;
|
|
|
|
#define DevFld(F) GetFieldValue(DeviceNode, DevNodeType, #F, F)
|
|
#define DevFld2(F, V) GetFieldValue(DeviceNode, DevNodeType, #F, V)
|
|
|
|
if (DevFld2(ServiceName.Length, ServiceName_Len)) {
|
|
xdprintf(Depth, "");
|
|
dprintf("%08p: Could not read device node\n", DeviceNode);
|
|
return TRUE;
|
|
}
|
|
|
|
DevFld2(ServiceName.MaximumLength, ServiceName_MaxLen);
|
|
DevFld2(ServiceName.Buffer, ServiceName_Buff);
|
|
DevFld(Flags); DevFld(PhysicalDeviceObject); DevFld(Parent);
|
|
DevFld(Sibling); DevFld(Child); DevFld(InterfaceType);
|
|
DevFld(BusNumber);DevFld(DuplicatePDO); DevFld(State);
|
|
DevFld(PreviousState);
|
|
DevFld2(InstancePath.Length, InstancePath_Len);
|
|
DevFld2(InstancePath.MaximumLength, InstancePath_Max);
|
|
DevFld2(InstancePath.Buffer, InstancePath_Buff);
|
|
DevFld2(TargetDeviceNotify.Blink, TargetDeviceNotify_Blink);
|
|
DevFld2(TargetDeviceNotify.Flink, TargetDeviceNotify_Flink);
|
|
DevFld(UserFlags); DevFld(CapabilityFlags); DevFld(DisableableDepends);
|
|
DevFld(Problem); DevFld(FailureStatus);
|
|
DevFld(PreviousResourceList); DevFld(PreviousResourceRequirements);
|
|
DevFld(ResourceList);
|
|
DevFld(BootResources); DevFld(ResourceListTranslated);
|
|
DevFld(ResourceRequirements); DevFld(StateHistoryEntry);
|
|
#undef DevFld
|
|
#undef DevFld2
|
|
|
|
//
|
|
// Check if printing should be suppressed
|
|
//
|
|
if (!PrintDefault && ServiceName != NULL) {
|
|
if ((ServiceName_Buff == 0) || (ServiceName_MaxLen <= 0) ||
|
|
(ServiceName_MaxLen > 1024)) {
|
|
print = FALSE;
|
|
} else {
|
|
//
|
|
// Compare the service names
|
|
//
|
|
UNICODE_STRING v;
|
|
|
|
v.Buffer = LocalAlloc(LPTR, ServiceName_MaxLen);
|
|
if (v.Buffer != NULL) {
|
|
v.MaximumLength = ServiceName_MaxLen;
|
|
v.Length = ServiceName_Len;
|
|
if (ReadMemory(ServiceName_Buff,
|
|
v.Buffer,
|
|
ServiceName_Len,
|
|
(PULONG) &AmountRead)) {
|
|
|
|
if (RtlCompareUnicodeString(ServiceName,
|
|
&v,
|
|
TRUE) != 0) {
|
|
//
|
|
// We are not interested in this devnode
|
|
//
|
|
print = FALSE;
|
|
}
|
|
}
|
|
LocalFree(v.Buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (DumpOnlyDevnodesWithProblems) {
|
|
print = (BOOLEAN) ((Flags & (DNF_HAS_PROBLEM | DNF_HAS_PRIVATE_PROBLEM)) != 0);
|
|
} else if (DumpOnlyNonStartedDevnodes) {
|
|
print = (BOOLEAN) (State != DeviceNodeStarted);
|
|
}
|
|
|
|
if (print) {
|
|
xdprintf(Depth, "");
|
|
dprintf("DevNode %#010p for PDO %#010p\n",
|
|
DeviceNode,
|
|
PhysicalDeviceObject);
|
|
Depth++;
|
|
|
|
if (!DumpChild) {
|
|
xdprintf(Depth, "");
|
|
dprintf("Parent %#010p Sibling %#010p Child %#010p\n",
|
|
Parent,
|
|
Sibling,
|
|
Child);
|
|
|
|
if ((LONG) InterfaceType != -1 ||
|
|
(BusNumber != -1 && BusNumber != -16)) {
|
|
|
|
xdprintf(Depth, "InterfaceType %#x Bus Number %#x\n",
|
|
(LONG) InterfaceType,
|
|
BusNumber);
|
|
}
|
|
|
|
if (DuplicatePDO != 0) {
|
|
dprintf("Duplicate PDO %#010p", DuplicatePDO);
|
|
}
|
|
}
|
|
|
|
if (InstancePath_Buff != 0) {
|
|
UNICODE_STRING64 v;
|
|
|
|
xdprintf(Depth, "InstancePath is \"");
|
|
v.MaximumLength = InstancePath_Max;
|
|
v.Length = InstancePath_Len;
|
|
v.Buffer = InstancePath_Buff;
|
|
DumpUnicode64(v);
|
|
dprintf("\"\n");
|
|
}
|
|
|
|
if (ServiceName_Buff != 0) {
|
|
UNICODE_STRING64 v;
|
|
|
|
xdprintf(Depth, "ServiceName is \"");
|
|
v.MaximumLength = ServiceName_MaxLen;
|
|
v.Length = ServiceName_Len;
|
|
v.Buffer = ServiceName_Buff;
|
|
DumpUnicode64(v);
|
|
dprintf("\"\n");
|
|
}
|
|
|
|
if ((TargetDeviceNotify_Flink != 0 ||
|
|
TargetDeviceNotify_Blink != 0) &&
|
|
(TargetDeviceNotify_Blink != TargetDeviceNotifyAddress ||
|
|
TargetDeviceNotify_Flink != TargetDeviceNotifyAddress)) {
|
|
xdprintf(Depth, "TargetDeviceNotify List - ");
|
|
dprintf ("f %#010p b %#010p\n",
|
|
TargetDeviceNotify_Flink,
|
|
TargetDeviceNotify_Blink);
|
|
}
|
|
|
|
PrintDevNodeState(Depth, "State", State);
|
|
|
|
PrintDevNodeState(Depth, "Previous State", PreviousState);
|
|
|
|
if (!DumpChild) {
|
|
|
|
if (DumpStateHistory) {
|
|
|
|
GetFieldOffset("nt!_DEVICE_NODE", "StateHistory", &result);
|
|
|
|
if (ReadMemory(DeviceNode+result,
|
|
StateHistory,
|
|
sizeof(StateHistory),
|
|
&AmountRead)) {
|
|
|
|
UCHAR Description[20];
|
|
ULONG index;
|
|
INT i;
|
|
|
|
for (i = STATE_HISTORY_SIZE - 1; i >= 0; i--) {
|
|
|
|
index = (i + StateHistoryEntry) % STATE_HISTORY_SIZE;
|
|
|
|
sprintf(Description, "StateHistory[%02d]", index);
|
|
PrintDevNodeState(Depth, Description, StateHistory[index]);
|
|
}
|
|
}
|
|
DumpFlags(Depth, "Flags", Flags, DeviceNodeFlags);
|
|
|
|
if (UserFlags != 0) {
|
|
DumpFlags(Depth, "UserFlags", UserFlags, DeviceNodeUserFlags);
|
|
}
|
|
|
|
if (CapabilityFlags != 0) {
|
|
DumpFlags(Depth, "CapabilityFlags", CapabilityFlags, DeviceNodeCapabilityFlags);
|
|
}
|
|
|
|
if (DisableableDepends != 0) {
|
|
xdprintf(Depth, "DisableableDepends = %d (%s)\n", DisableableDepends,
|
|
(UserFlags&DNUF_NOT_DISABLEABLE)?"including self":"from children");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Flags & DNF_HAS_PROBLEM) {
|
|
|
|
if (Problem < NUM_CM_PROB && DevNodeProblems[Problem] != NULL) {
|
|
xdprintf(Depth, "Problem = %s\n", DevNodeProblems[Problem]);
|
|
} else {
|
|
xdprintf(Depth, "Problem = Unknown problem (%d)\n", Problem);
|
|
}
|
|
if (Problem == CM_PROB_FAILED_START) {
|
|
xdprintf(Depth, "Failure Status %#010lx\n", FailureStatus);
|
|
continueDump = DumpResourceList64( "Previous CmResourceList",
|
|
Depth,
|
|
PreviousResourceList);
|
|
|
|
if (continueDump) {
|
|
|
|
continueDump = DumpResourceRequirementList64( Depth,
|
|
PreviousResourceRequirements);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (continueDump && DumpCmRes) {
|
|
continueDump = DumpResourceList64( "CmResourceList",
|
|
Depth,
|
|
ResourceList);
|
|
|
|
if (continueDump) {
|
|
continueDump = DumpResourceList64( "BootResourcesList",
|
|
Depth,
|
|
BootResources);
|
|
}
|
|
}
|
|
|
|
if (continueDump && DumpCmResTrans) {
|
|
continueDump = DumpResourceList64( "TranslatedResourceList",
|
|
Depth,
|
|
ResourceListTranslated);
|
|
}
|
|
|
|
if (continueDump && DumpCmResReqList) {
|
|
continueDump = DumpResourceRequirementList64( Depth,
|
|
ResourceRequirements);
|
|
}
|
|
}
|
|
|
|
if (continueDump && DumpChild && Child) {
|
|
continueDump = DumpDevNode( Child,
|
|
Depth,
|
|
DumpChild, // whem dumping a child, dump its siblings, too
|
|
DumpChild,
|
|
DumpCmRes,
|
|
DumpCmResReqList,
|
|
DumpCmResTrans,
|
|
DumpOnlyDevnodesWithProblems,
|
|
DumpOnlyNonStartedDevnodes,
|
|
ServiceName,
|
|
print,
|
|
DumpStateHistory
|
|
);
|
|
}
|
|
|
|
if (continueDump && DumpSibling && Sibling) {
|
|
continueDump = DumpDevNode( Sibling,
|
|
(print ? (Depth - 1):Depth),
|
|
DumpSibling,
|
|
DumpChild,
|
|
DumpCmRes,
|
|
DumpCmResReqList,
|
|
DumpCmResTrans,
|
|
DumpOnlyDevnodesWithProblems,
|
|
DumpOnlyNonStartedDevnodes,
|
|
ServiceName,
|
|
PrintDefault,
|
|
DumpStateHistory
|
|
);
|
|
}
|
|
|
|
return continueDump;
|
|
}
|
|
|
|
LPSTR
|
|
GetCmResourceTypeString(
|
|
IN UCHAR Type
|
|
)
|
|
{
|
|
LPSTR typeString;
|
|
|
|
switch (Type) {
|
|
case CmResourceTypeNull:
|
|
typeString = "Null";
|
|
break;
|
|
|
|
case CmResourceTypePort:
|
|
typeString = "Port";
|
|
break;
|
|
|
|
case CmResourceTypeInterrupt:
|
|
typeString = "Interrupt";
|
|
break;
|
|
|
|
case CmResourceTypeMemory:
|
|
typeString = "Memory";
|
|
break;
|
|
|
|
case CmResourceTypeDma:
|
|
typeString = "Dma";
|
|
break;
|
|
|
|
case CmResourceTypeDeviceSpecific:
|
|
typeString = "DeviceSpeific";
|
|
break;
|
|
|
|
case CmResourceTypeBusNumber:
|
|
typeString = "BusNumber";
|
|
break;
|
|
|
|
case CmResourceTypeMaximum:
|
|
typeString = "Maximum";
|
|
break;
|
|
|
|
case CmResourceTypeNonArbitrated:
|
|
typeString = "NonArbitrated/ConfigData";
|
|
break;
|
|
|
|
case CmResourceTypeDevicePrivate:
|
|
typeString = "DevicePrivate";
|
|
break;
|
|
|
|
case CmResourceTypePcCardConfig:
|
|
typeString = "PcCardConfig";
|
|
break;
|
|
|
|
default:
|
|
typeString = "Unknown";
|
|
break;
|
|
}
|
|
|
|
return typeString;
|
|
}
|
|
|
|
VOID
|
|
DumpResourceDescriptorHeader(
|
|
ULONG Depth,
|
|
ULONG Number,
|
|
UCHAR Option,
|
|
UCHAR Type,
|
|
UCHAR SharingDisposition,
|
|
USHORT Flags
|
|
)
|
|
{
|
|
PUCHAR typeString;
|
|
PUCHAR sharingString;
|
|
|
|
xdprintf (Depth, "");
|
|
|
|
if (Option & IO_RESOURCE_PREFERRED) {
|
|
dprintf("Preferred ");
|
|
}
|
|
if (Option & IO_RESOURCE_DEFAULT) {
|
|
dprintf("Default ");
|
|
}
|
|
if (Option & IO_RESOURCE_ALTERNATIVE) {
|
|
dprintf("Alternative ");
|
|
}
|
|
|
|
dprintf ("Descriptor %d - ", Number);
|
|
|
|
typeString = GetCmResourceTypeString(Type);
|
|
|
|
switch (SharingDisposition) {
|
|
case CmResourceShareUndetermined:
|
|
sharingString = "Undetermined Sharing";
|
|
break;
|
|
|
|
case CmResourceShareDeviceExclusive:
|
|
sharingString = "Device Exclusive";
|
|
break;
|
|
|
|
case CmResourceShareDriverExclusive:
|
|
sharingString = "Driver Exclusive";
|
|
break;
|
|
|
|
case CmResourceShareShared:
|
|
sharingString = "Shared";
|
|
break;
|
|
|
|
default:
|
|
sharingString = "Unknown Sharing";
|
|
break;
|
|
}
|
|
|
|
dprintf("%s (%#x) %s (%#x)\n",
|
|
typeString,
|
|
Type,
|
|
sharingString,
|
|
SharingDisposition);
|
|
|
|
Depth++;
|
|
|
|
xdprintf (Depth, "Flags (%#04wx) - ", Flags);
|
|
|
|
switch (Type) {
|
|
|
|
case CmResourceTypePort:
|
|
|
|
if (Flags == CM_RESOURCE_PORT_MEMORY) {
|
|
dprintf ("PORT_MEMORY ");
|
|
}
|
|
if (Flags & CM_RESOURCE_PORT_IO) {
|
|
dprintf ("PORT_IO ");
|
|
}
|
|
if (Flags & CM_RESOURCE_PORT_10_BIT_DECODE) {
|
|
dprintf ("10_BIT_DECODE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_PORT_12_BIT_DECODE) {
|
|
dprintf ("12_BIT_DECODE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_PORT_16_BIT_DECODE) {
|
|
dprintf ("16_BIT_DECODE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_PORT_POSITIVE_DECODE) {
|
|
dprintf ("POSITIVE_DECODE ");
|
|
}
|
|
break;
|
|
|
|
case CmResourceTypeMemory:
|
|
|
|
if (Flags == CM_RESOURCE_MEMORY_READ_WRITE) {
|
|
dprintf ("READ_WRITE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_MEMORY_READ_ONLY) {
|
|
dprintf ("READ_ONLY ");
|
|
}
|
|
if (Flags & CM_RESOURCE_MEMORY_WRITE_ONLY) {
|
|
dprintf ("WRITE_ONLY ");
|
|
}
|
|
if (Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) {
|
|
dprintf ("PREFETCHABLE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_MEMORY_COMBINEDWRITE) {
|
|
dprintf ("COMBINEDWRITE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_MEMORY_24) {
|
|
dprintf ("MEMORY_24 ");
|
|
}
|
|
break;
|
|
|
|
case CmResourceTypeInterrupt:
|
|
|
|
if (Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) {
|
|
dprintf ("LEVEL_SENSITIVE ");
|
|
}
|
|
if (Flags & CM_RESOURCE_INTERRUPT_LATCHED) {
|
|
dprintf ("LATCHED ");
|
|
}
|
|
break;
|
|
|
|
case CmResourceTypeDma:
|
|
|
|
if (Flags & CM_RESOURCE_DMA_8) {
|
|
dprintf ("DMA_8 ");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_16) {
|
|
dprintf ("DMA_16 ");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_32) {
|
|
dprintf ("DMA_32 ");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_8_AND_16) {
|
|
dprintf ("DMA_8_AND_16");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_TYPE_A) {
|
|
dprintf ("DMA_TYPE_A");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_TYPE_B) {
|
|
dprintf ("DMA_TYPE_B");
|
|
}
|
|
if (Flags & CM_RESOURCE_DMA_TYPE_F) {
|
|
dprintf ("DMA_TYPE_F");
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
dprintf("\n");
|
|
}
|
|
|
|
DECLARE_API( arbiter )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps all the arbiters in the system, their allocated ranges, and
|
|
the owners of the ranges.
|
|
|
|
!arbiter [flags]
|
|
flags 1 - I/O port arbiters
|
|
2 - memory arbiters
|
|
4 - IRQ arbiters
|
|
8 - DMA arbiters
|
|
|
|
|
|
If no flags are specified, all arbiters are dumped.
|
|
|
|
Arguments:
|
|
|
|
args - optional flags specifying which arbiters to dump
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD Flags=0;
|
|
ULONG64 addr;
|
|
ULONG64 deviceNode;
|
|
|
|
Flags = (ULONG) GetExpression(args);
|
|
|
|
if (Flags == 0) {
|
|
Flags = ARBITER_DUMP_ALL;
|
|
} else if (Flags == ARBITER_NO_DUMP_ALIASES) {
|
|
Flags = ARBITER_NO_DUMP_ALIASES + ARBITER_DUMP_ALL;
|
|
}
|
|
|
|
//
|
|
// Find the root devnode and dump its arbiters
|
|
//
|
|
|
|
addr = GetExpression( "nt!IopRootDeviceNode" );
|
|
if (addr == 0) {
|
|
dprintf("Error retrieving address of IopRootDeviceNode\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!ReadPointer(addr, &deviceNode)) {
|
|
dprintf("Error reading value of IopRootDeviceNode (%#010p)\n", addr);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
DumpArbitersForDevNode(0, deviceNode, Flags);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
DumpArbitersForDevNode(
|
|
IN DWORD Depth,
|
|
IN ULONG64 DevNodeAddr,
|
|
IN DWORD Flags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps all the arbiters for the specified devnode. Recursively calls
|
|
itself on the specified devnode's children.
|
|
|
|
Arguments:
|
|
|
|
Depth - Supplies the print depth.
|
|
|
|
DevNodeAddr - Supplies the address of the devnode.
|
|
|
|
Flags - Supplies the type of arbiters to dump:
|
|
ARBITER_DUMP_IO
|
|
ARBITER_DUMP_MEMORY
|
|
ARBITER_DUMP_IRQ
|
|
ARBITER_DUMP_DMA
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG result;
|
|
ULONG64 NextArbiter, startAddress;
|
|
ULONG64 ArbiterAddr;
|
|
BOOLEAN PrintedHeader = FALSE;
|
|
BOOLEAN continueDump = TRUE;
|
|
UCHAR devNodeType[] = "nt!_DEVICE_NODE";
|
|
ULONG DevArbOffset, DevNodeOffset;
|
|
ULONG64 DeviceArbiterList_Flink=0, InstancePath_Buffer=0, Child=0, Sibling=0;
|
|
UNICODE_STRING64 InstancePath;
|
|
|
|
// Get offset for listing
|
|
if (GetFieldOffset("nt!_PI_RESOURCE_ARBITER_ENTRY", "DeviceArbiterList.Flink", &DevArbOffset)) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (GetFieldValue(DevNodeAddr, devNodeType, "DeviceArbiterList.Flink", DeviceArbiterList_Flink)) {
|
|
xdprintf(Depth, ""); dprintf("%08p: Could not read device node\n", DevNodeAddr);
|
|
return TRUE;
|
|
}
|
|
GetFieldOffset("nt!_DEVICE_NODE", "DeviceArbiterList.Flink", &DevNodeOffset);
|
|
GetFieldValue(DevNodeAddr, devNodeType, "Child", Child);
|
|
GetFieldValue(DevNodeAddr, devNodeType, "Sibling", Sibling);
|
|
GetFieldValue(DevNodeAddr, devNodeType, "InstancePath.Buffer", InstancePath.Buffer);
|
|
GetFieldValue(DevNodeAddr, devNodeType, "InstancePath.Length", InstancePath.Length);
|
|
GetFieldValue(DevNodeAddr, devNodeType, "InstancePath.MaximumLength", InstancePath.MaximumLength);
|
|
|
|
|
|
//
|
|
// Dump the list of arbiters
|
|
//
|
|
startAddress = DevNodeAddr + DevNodeOffset;
|
|
|
|
NextArbiter = DeviceArbiterList_Flink;
|
|
while (NextArbiter != startAddress) {
|
|
ULONG ResourceType=0;
|
|
if (CheckControlC()) {
|
|
return FALSE;
|
|
}
|
|
ArbiterAddr = NextArbiter - DevArbOffset;
|
|
// CONTAINING_RECORD(NextArbiter, PI_RESOURCE_ARBITER_ENTRY, DeviceArbiterList);
|
|
|
|
|
|
if (GetFieldValue(ArbiterAddr, "nt!_PI_RESOURCE_ARBITER_ENTRY", "ResourceType", ResourceType)) {
|
|
xdprintf(Depth, "Could not read arbiter entry ");
|
|
dprintf("%08p for devnode %08p\n", ArbiterAddr, DevNodeAddr);
|
|
break;
|
|
}
|
|
|
|
if (((ResourceType == CmResourceTypePort) && (Flags & ARBITER_DUMP_IO)) ||
|
|
((ResourceType == CmResourceTypeInterrupt) && (Flags & ARBITER_DUMP_IRQ)) ||
|
|
((ResourceType == CmResourceTypeMemory) && (Flags & ARBITER_DUMP_MEMORY)) ||
|
|
((ResourceType == CmResourceTypeDma) && (Flags & ARBITER_DUMP_DMA)) ||
|
|
((ResourceType == CmResourceTypeBusNumber) && (Flags & ARBITER_DUMP_BUS_NUMBER))) {
|
|
|
|
if (!PrintedHeader) {
|
|
dprintf("\n");
|
|
xdprintf(Depth, ""); dprintf("DEVNODE %08p ", DevNodeAddr);
|
|
|
|
if (InstancePath.Buffer != 0) {
|
|
dprintf("(");
|
|
DumpUnicode64(InstancePath);
|
|
dprintf(")");
|
|
}
|
|
dprintf("\n");
|
|
PrintedHeader = TRUE;
|
|
}
|
|
|
|
continueDump = DumpArbiter( Depth+1,
|
|
ArbiterAddr,
|
|
// &ArbiterEntry,
|
|
(BOOLEAN)!(Flags & ARBITER_NO_DUMP_ALIASES)
|
|
);
|
|
|
|
if (!continueDump) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
GetFieldValue(ArbiterAddr, "nt!_PI_RESOURCE_ARBITER_ENTRY", "DeviceArbiterList.Flink", NextArbiter);
|
|
}
|
|
|
|
//
|
|
// Dump this devnode's children (if any)
|
|
//
|
|
if (continueDump && Child) {
|
|
continueDump = DumpArbitersForDevNode( Depth + 1, Child, Flags);
|
|
}
|
|
|
|
//
|
|
// Dump this devnode's siblings (if any)
|
|
//
|
|
if (continueDump && Sibling) {
|
|
continueDump = DumpArbitersForDevNode( Depth, Sibling, Flags);
|
|
}
|
|
|
|
return continueDump;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
DumpArbiter(
|
|
IN DWORD Depth,
|
|
IN ULONG64 ArbiterAddr,
|
|
IN BOOLEAN DisplayAliases
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps out the specified arbiter.
|
|
|
|
Arguments:
|
|
|
|
Depth - Supplies the print depth.
|
|
|
|
ArbiterAddr - Supplies the original address of the arbiter (on the target)
|
|
|
|
Arbiter - Supplies the arbiter
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 PciInstance;
|
|
ULONG64 InstanceAddr;
|
|
BOOL IsPciArbiter = FALSE;
|
|
WCHAR NameBuffer[64];
|
|
BOOLEAN continueDump = TRUE;
|
|
UCHAR ArbiterTyp[] = "nt!_PI_RESOURCE_ARBITER_ENTRY";
|
|
UCHAR ArbIntfTyp[] = "nt!_ARBITER_INTERFACE";
|
|
ULONG64 ArbiterInterface=0, Context=0, NamePtr=0, ResourceType=0;
|
|
ULONG ListHeadOff;
|
|
|
|
//
|
|
// First obtain the ARBITER_INTERFACE.
|
|
//
|
|
if (GetFieldValue(ArbiterAddr, ArbiterTyp, "ArbiterInterface", ArbiterInterface)) {
|
|
dprintf("Error reading ArbiterInterface %08p for ArbiterEntry at %08p\n",
|
|
ArbiterInterface,
|
|
ArbiterAddr);
|
|
return continueDump;
|
|
}
|
|
if (!ArbiterInterface ||
|
|
GetFieldValue(ArbiterInterface, ArbIntfTyp, "Context", Context)) {
|
|
dprintf("Error reading ArbiterInterface %08p for ArbiterEntry at %08p\n",
|
|
ArbiterInterface,
|
|
ArbiterAddr);
|
|
return continueDump;
|
|
}
|
|
|
|
//
|
|
// Now that we have the ARBITER_INTERFACE we need to get the ARBITER_INSTANCE.
|
|
// This is not as easy as it should be since PeterJ is paranoid and encrypts the
|
|
// pointer to it. Luckily, we know his secret encryption method and can decrypt it.
|
|
// First we have to figure out if this is PCI's arbiter. Quick hack check is to see
|
|
// if the low bit is set.
|
|
//
|
|
if (Context & 1) {
|
|
ULONG Offset;
|
|
|
|
GetFieldOffset("nt!_PCI_ARBITER_INSTANCE", "CommonInstance", &Offset);
|
|
|
|
IsPciArbiter = TRUE;
|
|
PciInstance = (Context ^ PciFdoExtensionType);
|
|
InstanceAddr = PciInstance + Offset;
|
|
} else {
|
|
//
|
|
// We will assume that the context is just a pointer to an ARBITER_INSTANCE structure
|
|
//
|
|
InstanceAddr = Context;
|
|
}
|
|
|
|
//
|
|
// Read the instance
|
|
//
|
|
if (GetFieldValue(InstanceAddr, "nt!_ARBITER_INSTANCE", "Name", NamePtr)) {
|
|
dprintf("Error reading ArbiterInstance %08p for ArbiterInterface at %08p\n",
|
|
InstanceAddr,
|
|
ArbiterInterface);
|
|
return continueDump;
|
|
}
|
|
|
|
GetFieldValue(InstanceAddr, "nt!_ARBITER_INSTANCE", "ResourceType", ResourceType);
|
|
xdprintf(Depth,
|
|
"%s Arbiter \"",
|
|
GetCmResourceTypeString((UCHAR)ResourceType));
|
|
|
|
if (NamePtr != 0) {
|
|
ULONG result;
|
|
|
|
if (ReadMemory(NamePtr,NameBuffer,sizeof(NameBuffer),&result)) {
|
|
NameBuffer[sizeof(NameBuffer)/sizeof(WCHAR) - 1] = 0;
|
|
dprintf("%ws",NameBuffer);
|
|
}
|
|
}
|
|
|
|
dprintf("\" at %08p\n",InstanceAddr);
|
|
|
|
xdprintf(Depth+1,"Allocated ranges:\n");
|
|
|
|
GetFieldOffset("nt!_RTL_RANGE_LIST", "ListHead", &ListHeadOff);
|
|
InitTypeRead(InstanceAddr, nt!_ARBITER_INSTANCE);
|
|
continueDump = DumpRangeList( Depth+2,
|
|
ReadField(Allocation) + ListHeadOff,
|
|
FALSE,
|
|
TRUE,
|
|
DisplayAliases,
|
|
NULL);
|
|
|
|
if (continueDump) {
|
|
|
|
InitTypeRead(InstanceAddr, nt!_ARBITER_INSTANCE);
|
|
xdprintf(Depth+1,"Possible allocation:\n");
|
|
continueDump = DumpRangeList(Depth+2, ReadField(PossibleAllocation) + ListHeadOff,
|
|
FALSE, TRUE, DisplayAliases, NULL);
|
|
}
|
|
|
|
return continueDump;
|
|
}
|
|
|
|
VOID
|
|
DumpRangeEntry(
|
|
IN DWORD Depth,
|
|
IN ULONG64 RangeEntry,
|
|
IN BOOLEAN OwnerIsDevObj,
|
|
IN BOOLEAN DisplayAliases,
|
|
IN pUserDataInterpretationFunction PrintUserData OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps out the specified RTLP_RANGE_LIST_ENTRY
|
|
|
|
Arguments:
|
|
|
|
Depth - Supplies the print depth.
|
|
|
|
RangeList - Supplies the address of the RTLP_RANGE_LIST_ENTRY
|
|
|
|
OwnerIsDevObj - Indicates that the owner field is a pointer to a DEVICE_OBJECT
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG PrivateFlags=0, Attributes=0, PublicFlags=0;
|
|
ULONG64 Owner=0, Start=0, End=0, UserData=0;
|
|
|
|
if (GetFieldValue(RangeEntry, "nt!_RTLP_RANGE_LIST_ENTRY", "PrivateFlags", PrivateFlags)) {
|
|
dprintf("Cannot find _RTLP_RANGE_LIST_ENTRY type.\n");
|
|
return ;
|
|
}
|
|
|
|
// dprintf("Range Entry %p\n", RangeEntry);
|
|
|
|
GetFieldValue(RangeEntry, "nt!_RTLP_RANGE_LIST_ENTRY", "Attributes", Attributes);
|
|
GetFieldValue(RangeEntry, "nt!_RTLP_RANGE_LIST_ENTRY", "Start", Start);
|
|
GetFieldValue(RangeEntry, "nt!_RTLP_RANGE_LIST_ENTRY", "End", End);
|
|
GetFieldValue(RangeEntry, "nt!_RTLP_RANGE_LIST_ENTRY", "PublicFlags", PublicFlags);
|
|
GetFieldValue(RangeEntry, "nt!_RTLP_RANGE_LIST_ENTRY", "Allocated.Owner", Owner);
|
|
GetFieldValue(RangeEntry, "nt!_RTLP_RANGE_LIST_ENTRY", "Allocated.UserData", UserData);
|
|
|
|
if (!(PrivateFlags & RTLP_RANGE_LIST_ENTRY_MERGED)) {
|
|
ULONG64 DeviceObjectExtension=0, DeviceNode=0;
|
|
|
|
if ((Attributes & ARBITER_RANGE_ALIAS) && !DisplayAliases) {
|
|
return;
|
|
}
|
|
|
|
if (OwnerIsDevObj && Owner) {
|
|
|
|
if (GetFieldValue(Owner, "nt!_DEVICE_OBJECT", "DeviceObjectExtension", DeviceObjectExtension)) {
|
|
dprintf("Error reading DeviceObject %08p\n",
|
|
Owner
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (GetFieldValue(DeviceObjectExtension, "nt!_DEVOBJ_EXTENSION", "DeviceNode", DeviceNode)) {
|
|
dprintf("Error reading DeviceObjectExtension %08p\n",
|
|
DeviceObjectExtension
|
|
);
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
xdprintf(Depth,
|
|
"%016I64x - %016I64x %c%c%c%c%c",
|
|
Start,
|
|
End,
|
|
PublicFlags & RTL_RANGE_SHARED ? 'S' : ' ',
|
|
PublicFlags & RTL_RANGE_CONFLICT ? 'C' : ' ',
|
|
(Attributes & ARBITER_RANGE_BOOT_ALLOCATED)? 'B' : (Attributes & ARBITER_RANGE_SHARE_DRIVER_EXCLUSIVE)? 'D' : ' ',
|
|
Attributes & ARBITER_RANGE_ALIAS ? 'A' : ' ',
|
|
Attributes & ARBITER_RANGE_POSITIVE_DECODE ? 'P' : ' ');
|
|
dprintf(" %08p ",Owner);
|
|
|
|
if (Owner) {
|
|
UNICODE_STRING64 ServiceName;
|
|
|
|
GetFieldValue(DeviceNode, "nt!_DEVICE_NODE", "ServiceName.Buffer", ServiceName.Buffer);
|
|
if (OwnerIsDevObj && ServiceName.Buffer) {
|
|
GetFieldValue(DeviceNode, "nt!_DEVICE_NODE", "ServiceName.Length", ServiceName.Length);
|
|
GetFieldValue(DeviceNode, "nt!_DEVICE_NODE", "ServiceName.MaximumLength", ServiceName.MaximumLength);
|
|
|
|
dprintf(" (");
|
|
DumpUnicode64(ServiceName);
|
|
dprintf(")");
|
|
}
|
|
} else {
|
|
|
|
dprintf("<Not on bus>");
|
|
|
|
}
|
|
|
|
if (PrintUserData) {
|
|
PrintUserData(UserData);
|
|
}
|
|
|
|
} else {
|
|
|
|
xdprintf(Depth,
|
|
"%016I64x - %016I64x %c%c ",
|
|
Start,
|
|
End,
|
|
PublicFlags & RTL_RANGE_SHARED ? 'S' : ' ',
|
|
PublicFlags & RTL_RANGE_CONFLICT ? 'C' : ' '
|
|
);
|
|
}
|
|
|
|
dprintf("\n");
|
|
}
|
|
|
|
BOOLEAN
|
|
DumpRangeList(
|
|
IN DWORD Depth,
|
|
IN ULONG64 RangeListHead,
|
|
IN BOOLEAN IsMerged,
|
|
IN BOOLEAN OwnerIsDevObj,
|
|
IN BOOLEAN DisplayAliases,
|
|
IN pUserDataInterpretationFunction PrintUserData OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps out the specified RTL_RANGE_LIST
|
|
|
|
Arguments:
|
|
|
|
Depth - Supplies the print depth.
|
|
|
|
RangeListHead - Supplies the address of the LIST_ENTRY containing the RTLP_RANGE_LIST_ENTRYs
|
|
|
|
IsMerged - Indicates whether this list is in a merged range
|
|
|
|
OwnerIsDevObj - Indicates that the owner field is a pointer to a DEVICE_OBJECT
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 ListEntry, EntryAddr;
|
|
ULONG ListEntryOffset, ListHeadOffset;
|
|
BOOLEAN continueDump = TRUE;
|
|
|
|
GetFieldOffset("nt!_RTLP_RANGE_LIST_ENTRY", "ListEntry", &ListEntryOffset);
|
|
GetFieldOffset("nt!_RTLP_RANGE_LIST_ENTRY", "Merged.ListHead", &ListHeadOffset);
|
|
|
|
//
|
|
// Read the range list
|
|
//
|
|
if (GetFieldValue(RangeListHead, "nt!_LIST_ENTRY", "Flink", ListEntry)) {
|
|
dprintf("Error reading RangeList %08p\n", RangeListHead);
|
|
return TRUE;
|
|
}
|
|
|
|
if (ListEntry == RangeListHead) {
|
|
xdprintf(Depth, "< none >\n");
|
|
return TRUE;
|
|
}
|
|
|
|
while (ListEntry != RangeListHead) {
|
|
ULONG PrivateFlags=0;
|
|
ULONG64 ListHeadAddr=0;
|
|
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
break;
|
|
}
|
|
|
|
EntryAddr = ListEntry - ListEntryOffset;
|
|
if (GetFieldValue(EntryAddr, "nt!_RTLP_RANGE_LIST_ENTRY", "PrivateFlags", PrivateFlags)) {
|
|
dprintf("Error reading RangeEntry %08p from RangeList %08p\n",
|
|
EntryAddr,
|
|
RangeListHead);
|
|
return TRUE;
|
|
}
|
|
|
|
if (PrivateFlags & RTLP_RANGE_LIST_ENTRY_MERGED) {
|
|
//
|
|
// This is a merged range list, call ourselves recursively
|
|
//
|
|
DumpRangeEntry(Depth, EntryAddr, FALSE, DisplayAliases, PrintUserData);
|
|
|
|
continueDump = DumpRangeList(Depth + 1, EntryAddr + ListHeadOffset, TRUE, TRUE, DisplayAliases, PrintUserData);
|
|
|
|
if (!continueDump) {
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
|
|
DumpRangeEntry(Depth, EntryAddr, OwnerIsDevObj, DisplayAliases, PrintUserData);
|
|
|
|
}
|
|
|
|
GetFieldValue(EntryAddr, "nt!_RTLP_RANGE_LIST_ENTRY", "ListEntry.Flink", ListEntry);
|
|
}
|
|
|
|
return continueDump;
|
|
}
|
|
|
|
DECLARE_API( range )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps an RTL_RANGE_LIST
|
|
|
|
Arguments:
|
|
|
|
args - specifies the address of the RTL_RANGE_LIST
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
ULONG ListHeadOffset;
|
|
BOOLEAN continueDump = TRUE;
|
|
ULONG64 RangeList;
|
|
|
|
if (GetFieldOffset("nt!_RTL_RANGE_LIST", "ListHead", &ListHeadOffset)) {
|
|
dprintf("Cannot find _RTL_RANGE_LIST type.\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
RangeList = GetExpression(args);
|
|
|
|
DumpRangeList(0, RangeList + ListHeadOffset, FALSE, FALSE, TRUE, NULL);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
ULONG
|
|
DumpArbList(
|
|
PFIELD_INFO ListElement,
|
|
PVOID Context
|
|
)
|
|
{
|
|
UCHAR andOr = ' ';
|
|
ULONG resourceType = 0xffffffff;
|
|
ULONG remaining;
|
|
PULONG data;
|
|
|
|
PCHAR headingDefault = " Owner Data";
|
|
PCHAR formatDefault = "%c %s %c %08x %08x %08x %08x %08x %08x\n";
|
|
|
|
PCHAR headingMemIo = " Owner Length Alignment Minimum Address - Maximum Address\n";
|
|
PCHAR formatMemIo = "%c %s %c %8x %8x %08x%08x - %08x%08x\n";
|
|
|
|
PCHAR headingIrqDma = " Owner Minimum - Maximum\n";
|
|
PCHAR formatIrqDma = "%c %s %c %8x - %-8x\n";
|
|
|
|
PCHAR heading = headingDefault;
|
|
PCHAR format = formatDefault;
|
|
|
|
CHAR shared;
|
|
CHAR ownerBuffer[20];
|
|
PCHAR ownerBlank = " ";
|
|
PCHAR ownerText = ownerBlank;
|
|
ULONG64 pcurrent=ListElement->address;
|
|
ULONG64 palternative;
|
|
static ULONG64 previousOwner = 0;
|
|
BOOLEAN doHeading = TRUE;
|
|
BOOLEAN verbose = FALSE;
|
|
ULONG Flag = *((PULONG) Context);
|
|
ULONG AlternativeCount=0, resDescSize;
|
|
ULONG64 PhysicalDeviceObject, Alternatives;
|
|
ULONG Flags=0, InterfaceType=0, RequestSource=0;
|
|
|
|
//
|
|
// Check if user wants out.
|
|
//
|
|
|
|
if (CheckControlC()) {
|
|
dprintf("User terminated with <control>C\n");
|
|
return TRUE;
|
|
}
|
|
|
|
if ((LONG64)pcurrent >= 0) {
|
|
dprintf("List broken, forward entry is not a valid kernel address.\n");
|
|
return TRUE;
|
|
}
|
|
|
|
if (Flag & 1) {
|
|
verbose = TRUE;
|
|
}
|
|
|
|
//
|
|
// Get the arbitration list entry from host memory.
|
|
//
|
|
|
|
if (GetFieldValue(pcurrent, "nt!_ARBITER_LIST_ENTRY", "PhysicalDeviceObject", PhysicalDeviceObject)) {
|
|
dprintf("Couldn't read _ARBITER_LIST_ENTRY at %p\n", pcurrent);
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Check if we've changed device objects.
|
|
//
|
|
|
|
if (previousOwner != PhysicalDeviceObject) {
|
|
previousOwner = PhysicalDeviceObject;
|
|
sprintf(ownerBuffer, "%08I64lx", previousOwner);
|
|
ownerText = ownerBuffer;
|
|
andOr = ' ';
|
|
if (verbose) {
|
|
doHeading = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Run the alternatives for this device object.
|
|
//
|
|
|
|
GetFieldValue(pcurrent, "nt!_ARBITER_LIST_ENTRY", "AlternativeCount", AlternativeCount);
|
|
GetFieldValue(pcurrent, "nt!_ARBITER_LIST_ENTRY", "Alternatives", Alternatives);
|
|
|
|
GetFieldValue(pcurrent, "nt!_ARBITER_LIST_ENTRY", "Flags", Flags);
|
|
GetFieldValue(pcurrent, "nt!_ARBITER_LIST_ENTRY", "InterfaceType", InterfaceType);
|
|
GetFieldValue(pcurrent, "nt!_ARBITER_LIST_ENTRY", "RequestSource", RequestSource);
|
|
|
|
resDescSize = GetTypeSize("nt!_IO_RESOURCE_DESCRIPTOR");
|
|
for (remaining = AlternativeCount, palternative = Alternatives;
|
|
remaining;
|
|
remaining--, palternative+=resDescSize) {
|
|
ULONG Type=0, ShareDisposition=0, Gen_Length=0, Gen_Alignment=0;
|
|
ULONG Gen_Min_Low, Gen_Min_Hi=0, Gen_Max_Low=0, Gen_Max_Hi=0;
|
|
ULONG Int_Min=0, Int_Max=0, DevData[6]={0};
|
|
|
|
//
|
|
// Check if user wants out.
|
|
//
|
|
|
|
if (CheckControlC()) {
|
|
dprintf("User terminated with <control>C\n");
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Read this resource descriptor from memory. (An optimization
|
|
// would be to read the entire array or to buffer it).
|
|
//
|
|
|
|
if (GetFieldValue(palternative, "nt!_IO_RESOURCE_DESCRIPTOR", "Type", Type)){
|
|
dprintf("Couldn't read IO_RESOURCE_DESCRIPTOR at %08p, quitting.\n",
|
|
palternative
|
|
);
|
|
return TRUE;
|
|
}
|
|
if (Type != resourceType) {
|
|
if (resourceType == 0xffffffff) {
|
|
|
|
//
|
|
// Go look at the first alternative to figure out what
|
|
// resource type is being arbitrated.
|
|
//
|
|
|
|
resourceType = Type;
|
|
|
|
switch (resourceType) {
|
|
case CmResourceTypeNull:
|
|
dprintf("Arbitration list resource type is NULL. Seems odd.\n");
|
|
break;
|
|
case CmResourceTypePort:
|
|
dprintf("Arbitrating CmResourceTypePort resources\n");
|
|
format = formatMemIo;
|
|
heading = headingMemIo;
|
|
break;
|
|
case CmResourceTypeInterrupt:
|
|
dprintf("Arbitrating CmResourceTypeInterrupt resources\n");
|
|
format = formatIrqDma;
|
|
heading = headingIrqDma;
|
|
break;
|
|
case CmResourceTypeMemory:
|
|
dprintf("Arbitrating CmResourceTypeMemory resources\n");
|
|
format = formatMemIo;
|
|
heading = headingMemIo;
|
|
break;
|
|
case CmResourceTypeDma:
|
|
dprintf("Arbitrating CmResourceTypeDma resources\n");
|
|
format = formatIrqDma;
|
|
heading = headingIrqDma;
|
|
break;
|
|
default:
|
|
dprintf("Arbitrating resource type 0x%x\n", Type);
|
|
}
|
|
} else {
|
|
dprintf("error: Resource Type change, arbiters don't do multiple\n");
|
|
dprintf("types. Resource Type was 0x%x, new type 0x%x, quitting.\n",
|
|
resourceType, Type);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (doHeading) {
|
|
if (verbose) {
|
|
dprintf("Owning object %08p, Flags 0x%x, Interface 0x%x, Source 0x%x\n",
|
|
PhysicalDeviceObject,
|
|
Flags,
|
|
InterfaceType,
|
|
RequestSource
|
|
);
|
|
}
|
|
dprintf(heading);
|
|
doHeading = FALSE;
|
|
}
|
|
|
|
GetFieldValue(palternative, "nt!_IO_RESOURCE_DESCRIPTOR", "ShareDisposition", ShareDisposition);
|
|
|
|
shared = ShareDisposition == CmResourceShareShared ? 'S' : ' ';
|
|
|
|
switch (resourceType) {
|
|
case CmResourceTypePort:
|
|
case CmResourceTypeMemory:
|
|
GetFieldValue(palternative, "nt!_IO_RESOURCE_DESCRIPTOR", "u.Generic.Length", Gen_Length);
|
|
GetFieldValue(palternative, "nt!_IO_RESOURCE_DESCRIPTOR", "u.Generic.Alignment", Gen_Alignment);
|
|
GetFieldValue(palternative, "nt!_IO_RESOURCE_DESCRIPTOR", "u.Generic.MinimumAddress.HighPart", Gen_Min_Hi);
|
|
GetFieldValue(palternative, "nt!_IO_RESOURCE_DESCRIPTOR", "u.Generic.MinimumAddress.LowPart", Gen_Min_Low);
|
|
GetFieldValue(palternative, "nt!_IO_RESOURCE_DESCRIPTOR", "u.Generic.MaximumAddress.HighPart", Gen_Max_Hi);
|
|
GetFieldValue(palternative, "nt!_IO_RESOURCE_DESCRIPTOR", "u.Generic.MaximumAddress.LowPart", Gen_Max_Low );
|
|
|
|
dprintf(format,
|
|
andOr,
|
|
ownerText,
|
|
shared,
|
|
Gen_Length,
|
|
Gen_Alignment,
|
|
Gen_Min_Hi,
|
|
Gen_Min_Low,
|
|
Gen_Max_Hi,
|
|
Gen_Max_Low
|
|
);
|
|
break;
|
|
case CmResourceTypeInterrupt:
|
|
case CmResourceTypeDma:
|
|
|
|
//
|
|
// Dma and Interrupt are same format,... overload.
|
|
//
|
|
GetFieldValue(palternative, "nt!_IO_RESOURCE_DESCRIPTOR", "u.Interrupt.MinimumVector", Int_Min);
|
|
GetFieldValue(palternative, "nt!_IO_RESOURCE_DESCRIPTOR", "u.Interrupt.MaximumVector", Int_Max);
|
|
|
|
dprintf(format,
|
|
andOr,
|
|
ownerText,
|
|
shared,
|
|
Int_Min,
|
|
Int_Max
|
|
);
|
|
break;
|
|
default:
|
|
GetFieldValue(palternative, "nt!_IO_RESOURCE_DESCRIPTOR", "u.DevicePrivate.Data", DevData);
|
|
data = DevData;
|
|
dprintf(format,
|
|
andOr,
|
|
ownerText,
|
|
shared,
|
|
*data,
|
|
*(data + 0),
|
|
*(data + 1),
|
|
*(data + 2),
|
|
*(data + 3),
|
|
*(data + 4),
|
|
*(data + 5)
|
|
);
|
|
break;
|
|
}
|
|
ownerText = ownerBlank;
|
|
andOr = '|';
|
|
}
|
|
if (AlternativeCount == 0) {
|
|
|
|
//
|
|
// Get here if the alternatives list was empty.
|
|
//
|
|
|
|
if (doHeading) {
|
|
dprintf("Owning object %08p, Flags 0x%x, Interface 0x%x\n",
|
|
PhysicalDeviceObject,
|
|
Flags,
|
|
InterfaceType
|
|
);
|
|
}
|
|
dprintf("Arbiter list entry (@%08p) has 0 resources. Seems odd.\n",
|
|
pcurrent
|
|
);
|
|
}
|
|
andOr = '&';
|
|
|
|
return FALSE; // Continue dumping the list
|
|
}
|
|
|
|
DECLARE_API( arblist )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps an arbitration list (2nd parameter to PnpTestAllocation).
|
|
|
|
!arblist address
|
|
|
|
If no address specified we try to tell you what to do.
|
|
|
|
Arguments:
|
|
|
|
address of the arbitration list.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 ArbitrationList = 0;
|
|
ULONG Flags = 0;
|
|
ULONG64 pcurrent;
|
|
ULONG64 palternative;
|
|
ULONG64 KModeCheck;
|
|
BOOL Ptr64 = IsPtr64();
|
|
|
|
if (GetExpressionEx(args, &ArbitrationList, &args)) {
|
|
Flags = (ULONG) GetExpression(args);
|
|
}
|
|
|
|
if (ArbitrationList == 0) {
|
|
dprintf("!arblist <address> [flags]\n");
|
|
dprintf(" <address> is the address of an arbitration list.\n");
|
|
dprintf(" [flags] Bitmask used to adjust what is printed.\n");
|
|
dprintf(" 0001 Include interface, flags and source for each device\n");
|
|
dprintf("\n");
|
|
dprintf(" Prints out an arbitration list. An arbitration list\n");
|
|
dprintf(" is the set of resources for which arbitration is\n");
|
|
dprintf(" needed. (eg second parameter to PnpTestAllocation).\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (Ptr64) {
|
|
KModeCheck = 0x8000000000000000L;
|
|
} else {
|
|
KModeCheck = 0xffffffff80000000L;
|
|
}
|
|
|
|
//
|
|
// The argument is a pointer to a list head.
|
|
//
|
|
|
|
if (!((LONG64)ArbitrationList & KModeCheck)) {
|
|
dprintf("The arbitration list pointer must be a kernel mode address.\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (GetFieldValue(ArbitrationList, "nt!_LIST_ENTRY", "Flink", pcurrent)) {
|
|
dprintf("error reading arbitration list ListHead, cannot continue.\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// A little validation.
|
|
//
|
|
|
|
if (!(pcurrent & KModeCheck)) {
|
|
dprintf("%08p does not point to a valid list head.\n", ArbitrationList);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (pcurrent == ArbitrationList) {
|
|
dprintf("%08p points to an empty list.\n", ArbitrationList);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Run the list.
|
|
//
|
|
|
|
ListType("_ARBITER_LIST_ENTRY", pcurrent, TRUE, "ListEntry.Flink", (PVOID) &Flags, DumpArbList);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
ULONG
|
|
TokenizeString(
|
|
PUCHAR Input,
|
|
PUCHAR *Output,
|
|
ULONG Max
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert an input string of white space delimited tokens into
|
|
an array of strings. The routine will produce an array of
|
|
pointers to strings where the (maximum) size of the array is
|
|
given by Max. Note, if Max is too small to fully tokenize the
|
|
string, the last element of the array will point to the remainder
|
|
of the string.
|
|
|
|
Arguments:
|
|
|
|
Input Input string
|
|
Output Pointer to an array which will be filled in with
|
|
pointers to each new token.
|
|
Max Maximum number of strings.
|
|
|
|
Return Value:
|
|
|
|
Number of tokens found.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG count = 0;
|
|
PUCHAR tok;
|
|
BOOLEAN inToken = FALSE;
|
|
UCHAR c;
|
|
|
|
if (Max == 0) {
|
|
return 0;
|
|
}
|
|
|
|
while ((c = *Input++) != '\0') {
|
|
|
|
if (isspace(c)) {
|
|
|
|
if (!inToken) {
|
|
|
|
//
|
|
// Continue skipping characters.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Found end of Token, delimit it and change state.
|
|
//
|
|
|
|
inToken = FALSE;
|
|
*(Input - 1) = '\0';
|
|
|
|
} else {
|
|
|
|
//
|
|
// Non-blank character.
|
|
//
|
|
|
|
if (inToken) {
|
|
|
|
//
|
|
// Continue search for end of token.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// New Token.
|
|
//
|
|
|
|
inToken = TRUE;
|
|
*Output++ = Input - 1;
|
|
count++;
|
|
|
|
if (count == Max) {
|
|
|
|
//
|
|
// We can't find any more so return what we still
|
|
// have as the last thing.
|
|
//
|
|
|
|
return count;
|
|
}
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
//
|
|
// DevExtPCI
|
|
//
|
|
// Data structures and functions to implement !devext pci.
|
|
//
|
|
|
|
PUCHAR DevExtPciDeviceState[] = {
|
|
"PciNotStarted",
|
|
"PciStarted",
|
|
"PciDeleted",
|
|
"PciStopped",
|
|
"PciSurpriseRemoved",
|
|
"PciSynchronizedOperation"
|
|
};
|
|
|
|
PUCHAR DevExtPciSystemPowerState[] = {
|
|
"Unspecified",
|
|
"Working",
|
|
"Sleeping1",
|
|
"Sleeping2",
|
|
"Sleeping3",
|
|
"Hibernate",
|
|
"Shutdown"
|
|
};
|
|
|
|
PUCHAR DevExtPciDevicePowerState[] = {
|
|
"Unspecified",
|
|
"D0",
|
|
"D1",
|
|
"D2",
|
|
"D3"
|
|
};
|
|
|
|
struct {
|
|
USHORT VendorId;
|
|
PUCHAR VendorName;
|
|
} DevExtPciVendors[] = {
|
|
{ 0x003D, "LOCKHEED MARTIN"},
|
|
{ 0x0E11, "COMPAQ"},
|
|
{ 0x1002, "ATI TECHNOLOGIES INC"},
|
|
{ 0x1003, "ULSI SYSTEMS"},
|
|
{ 0x1004, "VLSI TECHNOLOGY INC"},
|
|
{ 0x1006, "REPLY GROUP"},
|
|
{ 0x1007, "NETFRAME SYSTEMS INC"},
|
|
{ 0x1008, "EPSON"},
|
|
{ 0x100A, "PHOENIX TECHNOLOGIES"},
|
|
{ 0x100B, "NATIONAL SEMICONDUCTOR CORPORATION"},
|
|
{ 0x100C, "TSENG LABS INC"},
|
|
{ 0x100D, "AST RESEARCH INC"},
|
|
{ 0x1010, "VIDEO LOGIC LTD"},
|
|
{ 0x1011, "DIGITAL EQUIPMENT CORPORATION"},
|
|
{ 0x1012, "MICRONICS COMPUTERS INC"},
|
|
{ 0x1013, "CIRRUS LOGIC"},
|
|
{ 0x1014, "IBM"},
|
|
{ 0x1015, "LSI LOGIC CORP OF CANADA"},
|
|
{ 0x1016, "ICL PERSONAL SYSTEMS"},
|
|
{ 0x1017, "SPEA SOFTWARE AG"},
|
|
{ 0x1018, "UNISYS SYSTEMS"},
|
|
{ 0x1019, "ELITEGROUP COMPUTER SYS"},
|
|
{ 0x101A, "NCR"},
|
|
{ 0x101C, "WESTERN DIGITAL"},
|
|
{ 0x101E, "AMERICAN MEGATRENDS"},
|
|
{ 0x101F, "PICTURETEL"},
|
|
{ 0x1021, "OKI ELECTRIC INDUSTRY"},
|
|
{ 0x1022, "ADVANCED MICRO DEVICES"},
|
|
{ 0x1023, "TRIDENT MICROSYSTEMS"},
|
|
{ 0x1025, "ACER INCORPORATED"},
|
|
{ 0x1028, "DELL COMPUTER CORPORATION"},
|
|
{ 0x102B, "MATROX"},
|
|
{ 0x102C, "CHIPS AND TECHNOLOGIES"},
|
|
{ 0x102E, "OLIVETTI ADVANCED TECHNOLOGY"},
|
|
{ 0x102F, "TOSHIBA AMERICA ELECT."},
|
|
{ 0x1030, "TMC RESEARCH"},
|
|
{ 0x1031, "MIRO COMPUTER PRODUCTS AG"},
|
|
{ 0x1033, "NEC CORPORATION"},
|
|
{ 0x1033, "NEC CORPORATION"},
|
|
{ 0x1034, "BURNDY CORPORATION"},
|
|
{ 0x1035, "COMP.&COMM. RESH. LAB"},
|
|
{ 0x1036, "FUTURE DOMAIN"},
|
|
{ 0x1037, "HITACHI MICRO SYSTEMS"},
|
|
{ 0x1038, "AMP, INC"},
|
|
{ 0x1039, "SILICON INTEGRATED SYSTEM"},
|
|
{ 0x103A, "SEIKO EPSON CORPORATION"},
|
|
{ 0x103B, "TATUNG CO. OF AMERICA"},
|
|
{ 0x103C, "HEWLETT PACKARD"},
|
|
{ 0x103E, "SOLLIDAY ENGINEERING"},
|
|
{ 0x103F, "SYNOPSYS INC."},
|
|
{ 0x1040, "ACCELGRAPHICS INC."},
|
|
{ 0x1042, "PC TECHNOLOGY INC"},
|
|
{ 0x1043, "ASUSTEK COMPUTER, INC."},
|
|
{ 0x1044, "DISTRIBUTED PROCESSING TECHNOLOGY"},
|
|
{ 0x1045, "OPTI"},
|
|
{ 0x1046, "IPC CORPORATION, LTD."},
|
|
{ 0x1047, "GENOA SYSTEMS CORP"},
|
|
{ 0x1048, "ELSA GMBH"},
|
|
{ 0x1049, "FOUNTAIN TECHNOLOGY"},
|
|
{ 0x104A, "SGS THOMSON"},
|
|
{ 0x104B, "BUSLOGIC"},
|
|
{ 0x104C, "TEXAS INSTRUMENTS"},
|
|
{ 0x104D, "SONY CORPORATION"},
|
|
{ 0x104E, "OAK TECHNOLOGY, INC"},
|
|
{ 0x1050, "WINBOND ELECTRONICS CORP"},
|
|
{ 0x1051, "ANIGMA, INC."},
|
|
{ 0x1055, "EFAR MICROSYSTEMS"},
|
|
{ 0x1057, "MOTOROLA"},
|
|
{ 0x1058, "ELECTRONICS & TELEC. RSH"},
|
|
{ 0x1059, "TEKNOR INDUSTRIAL COMPUTERS INC"},
|
|
{ 0x105A, "PROMISE TECHNOLOGY"},
|
|
{ 0x105B, "FOXCONN INTERNATIONAL"},
|
|
{ 0x105C, "WIPRO INFOTECH LIMITED"},
|
|
{ 0x105D, "NUMBER 9 COMPUTER COMPANY"},
|
|
{ 0x105E, "VTECH COMPUTERS LTD"},
|
|
{ 0x105F, "INFOTRONIC AMERICA INC"},
|
|
{ 0x1060, "UNITED MICROELECTRONICS"},
|
|
{ 0x1061, "I.T.T."},
|
|
{ 0x1062, "MASPAR COMPUTER CORP"},
|
|
{ 0x1063, "OCEAN OFFICE AUTOMATION"},
|
|
{ 0x1064, "ALCATEL CIT"},
|
|
{ 0x1065, "TEXAS MICROSYSTEMS"},
|
|
{ 0x1066, "PICOPOWER TECHNOLOGY"},
|
|
{ 0x1067, "MITSUBISHI ELECTRONICS"},
|
|
{ 0x1068, "DIVERSIFIED TECHNOLOGY"},
|
|
{ 0x1069, "MYLEX CORPORATION"},
|
|
{ 0x106B, "APPLE COMPUTER INC."},
|
|
{ 0x106C, "HYUNDAI ELECTRONICS AMERI"},
|
|
{ 0x106D, "SEQUENT"},
|
|
{ 0x106E, "DFI, INC"},
|
|
{ 0x106F, "CITY GATE DEVELOPMENT LTD"},
|
|
{ 0x1070, "DAEWOO TELECOM LTD"},
|
|
{ 0x1073, "YAMAHA CORPORATION"},
|
|
{ 0x1074, "NEXGEN MICROSYSTEME"},
|
|
{ 0x1075, "ADVANCED INTEGRATION RES."},
|
|
{ 0x1076, "CHAINTECH COMPUTER CO. LTD"},
|
|
{ 0x1077, "Q LOGIC"},
|
|
{ 0x1078, "CYRIX CORPORATION"},
|
|
{ 0x1079, "I-BUS"},
|
|
{ 0x107B, "GATEWAY 2000"},
|
|
{ 0x107C, "LG ELECTRONICS"},
|
|
{ 0x107D, "LEADTEK RESEARCH INC."},
|
|
{ 0x107E, "INTERPHASE CORPORATION"},
|
|
{ 0x107F, "DATA TECHNOLOGY CORPORATION"},
|
|
{ 0x1080, "CYPRESS SEMICONDUCTOR"},
|
|
{ 0x1081, "RADIUS"},
|
|
{ 0x1083, "FOREX COMPUTER CORPORATION"},
|
|
{ 0x1085, "TULIP COMPUTERS INT.B.V."},
|
|
{ 0x1089, "DATA GENERAL CORPORATION"},
|
|
{ 0x108A, "BIT 3 COMPUTER"},
|
|
{ 0x108C, "OAKLEIGH SYSTEMS INC."},
|
|
{ 0x108D, "OLICOM"},
|
|
{ 0x108E, "SUN MICROSYSTEMS"},
|
|
{ 0x108F, "SYSTEMSOFT"},
|
|
{ 0x1090, "ENCORE COMPUTER CORPORATION"},
|
|
{ 0x1091, "INTERGRAPH CORPORATION"},
|
|
{ 0x1092, "DIAMOND MULTMEDIA SYSTEMS"},
|
|
{ 0x1093, "NATIONAL INSTRUMENTS"},
|
|
{ 0x1094, "FIRST INT'L COMPUTERS"},
|
|
{ 0x1095, "CMD TECHNOLOGY INC"},
|
|
{ 0x1096, "ALACRON"},
|
|
{ 0x1098, "QUANTUM DESIGNS (H.K.) LTD"},
|
|
{ 0x109B, "GEMLIGHT COMPUTER LTD."},
|
|
{ 0x109E, "BROOKTREE CORPORATION"},
|
|
{ 0x109F, "TRIGEM COMPUTER INC."},
|
|
{ 0x10A0, "MEIDENSHA CORPORATION"},
|
|
{ 0x10A2, "QUANTUM CORPORATION"},
|
|
{ 0x10A3, "EVEREX SYSTEMS INC"},
|
|
{ 0x10A5, "RACAL INTERLAN"},
|
|
{ 0x10A8, "SIERRA SEMICONDUCTOR"},
|
|
{ 0x10A9, "SILICON GRAPHICS"},
|
|
{ 0x10AA, "ACC MICROELECTRONICS"},
|
|
{ 0x10AD, "SYMPHONY LABS"},
|
|
{ 0x10AE, "CORNERSTONE TECHNOLOGY"},
|
|
{ 0x10B0, "CARDEXPERT TECHNOLOGY"},
|
|
{ 0x10B1, "CABLETRON SYSTEMS INC"},
|
|
{ 0x10B2, "RAYTHEON COMPANY"},
|
|
{ 0x10B3, "DATABOOK INC"},
|
|
{ 0x10B4, "STB SYSTEMS INC"},
|
|
{ 0x10B5, "PLX TECHNOLOGY"},
|
|
{ 0x10B6, "MADGE NETWORKS"},
|
|
{ 0x10B7, "3COM CORPORATION"},
|
|
{ 0x10B8, "STANDARD MICROSYSTEMS"},
|
|
{ 0x10B9, "ACER LABS"},
|
|
{ 0x10BA, "MITSUBISHI ELECTRONICS CORP."},
|
|
{ 0x10BC, "ADVANCED LOGIC RESEARCH"},
|
|
{ 0x10BD, "SURECOM TECHNOLOGY"},
|
|
{ 0x10C0, "BOCA RESEARCH INC."},
|
|
{ 0x10C1, "ICM CO., LTD."},
|
|
{ 0x10C2, "AUSPEX SYSTEMS INC."},
|
|
{ 0x10C3, "SAMSUNG SEMICONDUCTORS"},
|
|
{ 0x10C4, "AWARD SOFTWARE INTERNATIONAL INC."},
|
|
{ 0x10C5, "XEROX CORPORATION"},
|
|
{ 0x10C6, "RAMBUS INC."},
|
|
{ 0x10C8, "NEOMAGIC CORPORATION"},
|
|
{ 0x10C9, "DATAEXPERT CORPORATION"},
|
|
{ 0x10CB, "OMRON CORPORATION"},
|
|
{ 0x10CC, "MENTOR ARC INC"},
|
|
{ 0x10CD, "ADVANCED SYSTEM PRODUCTS, INC"},
|
|
{ 0x10D0, "FUJITSU LIMITED"},
|
|
{ 0x10D1, "FUTURE+ SYSTEMS"},
|
|
{ 0x10D2, "MOLEX INCORPORATED"},
|
|
{ 0x10D3, "JABIL CIRCUIT INC"},
|
|
{ 0x10D4, "HUALON MICROELECTRONICS"},
|
|
{ 0x10D6, "CETIA"},
|
|
{ 0x10D7, "BCM ADVANCED"},
|
|
{ 0x10D8, "ADVANCED PERIPHERALS LABS"},
|
|
{ 0x10DA, "THOMAS-CONRAD CORPORATION"},
|
|
{ 0x10DC, "CERN/ECP/EDU"},
|
|
{ 0x10DD, "EVANS & SUTHERLAND"},
|
|
{ 0x10DE, "NVIDIA CORPORATION"},
|
|
{ 0x10DF, "EMULEX CORPORATION"},
|
|
{ 0x10E0, "INTEGRATED MICRO SOLUTIONS INC."},
|
|
{ 0x10E1, "TEKRAM TECHNOLOGY CO.,LTD."},
|
|
{ 0x10E2, "APTIX CORPORATION"},
|
|
{ 0x10E3, "TUNDRA SEMICONDUCTOR (formerly NEWBRIDGE MICROSYSTEMS)"},
|
|
{ 0x10E4, "TANDEM COMPUTERS"},
|
|
{ 0x10E5, "MICRO INDUSTRIES CORPORATION"},
|
|
{ 0x10E6, "GAINBERY COMPUTER PRODUCTS INC."},
|
|
{ 0x10E7, "VADEM"},
|
|
{ 0x10E8, "APPLIED MICRO CIRCUITS CORPORATION"},
|
|
{ 0x10E9, "ALPS ELECTRIC CO. LTD."},
|
|
{ 0x10EB, "ARTISTS GRAPHICS"},
|
|
{ 0x10EC, "REALTEK SEMICONDUCTOR CO., LTD."},
|
|
{ 0x10ED, "ASCII CORPORATION"},
|
|
{ 0x10EE, "XILINX CORPORATION"},
|
|
{ 0x10EF, "RACORE COMPUTER PRODUCTS, INC."},
|
|
{ 0x10F0, "PERITEK CORPORATION"},
|
|
{ 0x10F1, "TYAN COMPUTER"},
|
|
{ 0x10F3, "ALARIS, INC."},
|
|
{ 0x10F4, "S-MOS SYSTEMS"},
|
|
{ 0x10F5, "NKK CORPORATION"},
|
|
{ 0x10F6, "CREATIVE ELECTRONIC SYSTEMS SA"},
|
|
{ 0x10F7, "MATSUSHITA ELECTRIC INDUSTRIAL CO., LTD."},
|
|
{ 0x10F8, "ALTOS INDIA LTD"},
|
|
{ 0x10F9, "PC DIRECT"},
|
|
{ 0x10FA, "TRUEVISION"},
|
|
{ 0x10FB, "THESYS GES. F. MIKROELEKTRONIK MGH"},
|
|
{ 0x10FC, "I-O DATA DEVICE, INC."},
|
|
{ 0x10FD, "SOYO COMPUTER INC."},
|
|
{ 0x10FE, "FAST ELECTRONIC GMBH"},
|
|
{ 0x10FF, "NCUBE"},
|
|
{ 0x1100, "JAZZ MULTIMEDIA"},
|
|
{ 0x1101, "INITIO CORPORATION"},
|
|
{ 0x1102, "CREATIVE LABS"},
|
|
{ 0x1103, "TRIONES TECHNOLOGIES, INC."},
|
|
{ 0x1104, "RASTEROPS"},
|
|
{ 0x1105, "SIGMA DESIGNS, INC"},
|
|
{ 0x1106, "VIA TECHNOLOGIES, INC."},
|
|
{ 0x1107, "STRATUS COMPUTERS"},
|
|
{ 0x1108, "PROTEON, INC."},
|
|
{ 0x1109, "COGENT DATA TECHNOLOGIES"},
|
|
{ 0x110A, "SIEMENS NIXDORF IS/AG"},
|
|
{ 0x110B, "CHROMATIC RESEARCH INC."},
|
|
{ 0x110C, "MINI-MAX TECHNOLOGY, INC."},
|
|
{ 0x110D, "ZNYX ADVANCED SYSTEMS"},
|
|
{ 0x110E, "CPU TECHNOLOGY"},
|
|
{ 0x110F, "ROSS TECHNOLOGY"},
|
|
{ 0x1110, "Fire Power Systems, Inc."},
|
|
{ 0x1111, "SANTA CRUZ OPERATION"},
|
|
{ 0x1112, "RNS (formerly ROCKWELL NETWORK SYSTEMS)"},
|
|
{ 0x1114, "ATMEL CORPORATION"},
|
|
{ 0x1117, "DATACUBE, INC"},
|
|
{ 0x1118, "BERG ELECTRONICS"},
|
|
{ 0x1119, "VORTEX COMPUTERSYSTEME GMBH"},
|
|
{ 0x111A, "EFFICIENT NETWORKS"},
|
|
{ 0x111B, "LITTON GCS"},
|
|
{ 0x111C, "TRICORD SYSTEMS"},
|
|
{ 0x111D, "INTEGRATED DEVICE TECH"},
|
|
{ 0x111F, "PRECISION DIGITAL IMAGES"},
|
|
{ 0x1120, "EMC CORPORATION"},
|
|
{ 0x1122, "MULTI-TECH SYSTEMS, INC."},
|
|
{ 0x1123, "EXCELLENT DESIGN, INC."},
|
|
{ 0x1124, "LEUTRON VISION AG"},
|
|
{ 0x1127, "FORE SYSTEMS INC"},
|
|
{ 0x1129, "FIRMWORKS"},
|
|
{ 0x112A, "HERMES ELECTRONICS COMPANY, LTD."},
|
|
{ 0x112B, "LINOTYPE - HELL AG"},
|
|
{ 0x112C, "ZENITH DATA SYSTEMS"},
|
|
{ 0x112E, "INFOMEDIA MICROELECTRONICS INC."},
|
|
{ 0x112F, "IMAGING TECHNLOGY INC"},
|
|
{ 0x1130, "COMPUTERVISION"},
|
|
{ 0x1131, "PHILIPS SEMICONDUCTORS"},
|
|
{ 0x1132, "MITEL CORP."},
|
|
{ 0x1133, "EICON TECHNOLOGY CORPORATION"},
|
|
{ 0x1134, "MERCURY COMPUTER SYSTEMS"},
|
|
{ 0x1135, "FUJI XEROX CO LTD"},
|
|
{ 0x1136, "MOMENTUM DATA SYSTEMS"},
|
|
{ 0x1137, "CISCO SYSTEMS INC"},
|
|
{ 0x1138, "ZIATECH CORPORATION"},
|
|
{ 0x1139, "DYNAMIC PICTURES INC"},
|
|
{ 0x113A, "FWB INC"},
|
|
{ 0x113B, "NETWORK COMPUTING DEVICES"},
|
|
{ 0x113C, "CYCLONE MICROSYSTEMS"},
|
|
{ 0x113D, "LEADING EDGE PRODUCTS INC"},
|
|
{ 0x113E, "SANYO ELECTRIC CO"},
|
|
{ 0x113F, "EQUINOX SYSTEMS"},
|
|
{ 0x1140, "INTERVOICE INC"},
|
|
{ 0x1141, "CREST MICROSYSTEM INC"},
|
|
{ 0x1142, "ALLIANCE SEMICONDUCTOR CORPORATION"},
|
|
{ 0x1143, "NETPOWER, INC"},
|
|
{ 0x1144, "CINCINNATI MILACRON"},
|
|
{ 0x1145, "WORKBIT CORP"},
|
|
{ 0x1146, "FORCE COMPUTERS"},
|
|
{ 0x1147, "INTERFACE CORP"},
|
|
{ 0x1148, "SYSKONNECT"},
|
|
{ 0x1149, "WIN SYSTEM CORPORATION"},
|
|
{ 0x114A, "VMIC"},
|
|
{ 0x114B, "CANOPUS CO., LTD"},
|
|
{ 0x114C, "ANNABOOKS"},
|
|
{ 0x114D, "IC CORPORATION"},
|
|
{ 0x114E, "NIKON SYSTEMS INC"},
|
|
{ 0x114F, "DIGI INTERNATIONAL"},
|
|
{ 0x1151, "JAE ELECTRONICS INC."},
|
|
{ 0x1152, "MEGATEK"},
|
|
{ 0x1153, "LAND WIN ELECTRONIC CORP"},
|
|
{ 0x1154, "MELCO INC"},
|
|
{ 0x1155, "PINE TECHNOLOGY LTD"},
|
|
{ 0x1156, "PERISCOPE ENGINEERING"},
|
|
{ 0x1157, "AVSYS CORPORATION"},
|
|
{ 0x1158, "VOARX R & D INC"},
|
|
{ 0x1159, "MUTECH CORP"},
|
|
{ 0x115A, "HARLEQUIN LTD"},
|
|
{ 0x115B, "PARALLAX GRAPHICS"},
|
|
{ 0x115C, "PHOTRON LTD."},
|
|
{ 0x115D, "XIRCOM"},
|
|
{ 0x115E, "PEER PROTOCOLS INC"},
|
|
{ 0x115F, "MAXTOR CORPORATION"},
|
|
{ 0x1160, "MEGASOFT INC"},
|
|
{ 0x1161, "PFU LIMITED"},
|
|
{ 0x1162, "OA LABORATORY CO LTD"},
|
|
{ 0x1163, "RENDITION"},
|
|
{ 0x1164, "ADVANCED PERIPHERALS TECH"},
|
|
{ 0x1165, "IMAGRAPH"},
|
|
{ 0x1166, "RELIANCE COMPUTER CORP."},
|
|
{ 0x1167, "MUTOH INDUSTRIES INC"},
|
|
{ 0x1168, "THINE ELECTRONICS INC"},
|
|
{ 0x116A, "POLARIS COMMUNICATIONS"},
|
|
{ 0x116B, "CONNECTWARE INC"},
|
|
{ 0x116C, "INTELLIGENT RESOURCES"},
|
|
{ 0x116E, "ELECTRONICS FOR IMAGING"},
|
|
{ 0x116F, "WORKSTATION TECHNOLOGY"},
|
|
{ 0x1170, "INVENTEC CORPORATION"},
|
|
{ 0x1171, "LOUGHBOROUGH SOUND IMAGES"},
|
|
{ 0x1172, "ALTERA CORPORATION"},
|
|
{ 0x1173, "ADOBE SYSTEMS, INC"},
|
|
{ 0x1174, "BRIDGEPORT MACHINES"},
|
|
{ 0x1175, "MITRON COMPUTER INC."},
|
|
{ 0x1176, "SBE INCORPORATED"},
|
|
{ 0x1177, "SILICON ENGINEERING"},
|
|
{ 0x1178, "ALFA, INC."},
|
|
{ 0x117A, "A-TREND TECHNOLOGY"},
|
|
{ 0x117C, "ATTO TECHNOLOGY"},
|
|
{ 0x117D, "BECTON & DICKINSON"},
|
|
{ 0x117E, "T/R SYSTEMS"},
|
|
{ 0x117F, "INTEGRATED CIRCUIT SYSTEMS"},
|
|
{ 0x1180, "RICOH CO LTD"},
|
|
{ 0x1181, "TELMATICS INTERNATIONAL"},
|
|
{ 0x1183, "FUJIKURA LTD"},
|
|
{ 0x1184, "FORKS INC"},
|
|
{ 0x1185, "DATAWORLD"},
|
|
{ 0x1186, "D-LINK SYSTEM INC"},
|
|
{ 0x1187, "ADVANCED TECHNOLOGY LABORATORIES"},
|
|
{ 0x1188, "SHIMA SEIKI MANUFACTURING LTD."},
|
|
{ 0x1189, "MATSUSHITA ELECTRONICS CO LTD"},
|
|
{ 0x118A, "HILEVEL TECHNOLOGY"},
|
|
{ 0x118B, "HYPERTEC PTY LIMITED"},
|
|
{ 0x118C, "COROLLARY, INC"},
|
|
{ 0x118D, "BITFLOW INC"},
|
|
{ 0x118E, "HERMSTEDT GMBH"},
|
|
{ 0x118F, "GREEN LOGIC"},
|
|
{ 0x1191, "ARTOP ELECTRONIC CORP"},
|
|
{ 0x1192, "DENSAN CO., LTD"},
|
|
{ 0x1193, "ZEITNET INC."},
|
|
{ 0x1194, "TOUCAN TECHNOLOGY"},
|
|
{ 0x1195, "RATOC SYSTEM INC"},
|
|
{ 0x1196, "HYTEC ELECTRONICS LTD"},
|
|
{ 0x1197, "GAGE APPLIED SCIENCES, INC."},
|
|
{ 0x1198, "LAMBDA SYSTEMS INC"},
|
|
{ 0x1199, "ATTACHMATE CORPORATION"},
|
|
{ 0x1199, "DIGITAL COMMUNICATIONS ASSOCIATES INC"},
|
|
{ 0x119A, "MIND SHARE, INC."},
|
|
{ 0x119B, "OMEGA MICRO INC."},
|
|
{ 0x119C, "INFORMATION TECHNOLOGY INST."},
|
|
{ 0x119D, "BUG SAPPORO JAPAN"},
|
|
{ 0x119E, "FUJITSU"},
|
|
{ 0x119F, "BULL HN INFORMATION SYSTEMS"},
|
|
{ 0x11A0, "CONVEX COMPUTER CORPORATION"},
|
|
{ 0x11A1, "HAMAMATSU PHOTONICS K.K."},
|
|
{ 0x11A2, "SIERRA RESEARCH AND TECHNOLOGY"},
|
|
{ 0x11A4, "BARCO GRAPHICS NV"},
|
|
{ 0x11A5, "MICROUNITY SYSTEMS ENG. INC"},
|
|
{ 0x11A6, "PURE DATA"},
|
|
{ 0x11A7, "POWER COMPUTING CORP."},
|
|
{ 0x11A8, "SYSTECH CORP."},
|
|
{ 0x11A9, "INNOSYS"},
|
|
{ 0x11AA, "ACTEL"},
|
|
{ 0x11AB, "GALILEO TECHNOLOGY LTD."},
|
|
{ 0x11AC, "CANON INFORMATION SYSTEMS"},
|
|
{ 0x11AD, "LITE-ON COMMUNICATIONS INC"},
|
|
{ 0x11AE, "AZTECH SYSTEM LTD"},
|
|
{ 0x11AE, "SCITEX CORPORATION"},
|
|
{ 0x11AF, "AVID TECHNOLOGY INC"},
|
|
{ 0x11AF, "PRO-LOG CORPORATION"},
|
|
{ 0x11B0, "V3 SEMICONDUCTOR"},
|
|
{ 0x11B1, "APRICOT COMPUTERS"},
|
|
{ 0x11B2, "EASTMAN KODAK"},
|
|
{ 0x11B3, "BARR SYSTEMS INC."},
|
|
{ 0x11B4, "LEITCH TECHNOLOGY INTERNATIONAL"},
|
|
{ 0x11B5, "RADSTONE TECHNOLOGY PLC"},
|
|
{ 0x11B6, "UNITED VIDEO CORP"},
|
|
{ 0x11B8, "XPOINT TECHNOLOGIES INC"},
|
|
{ 0x11B9, "PATHLIGHT TECHNOLOGY INC"},
|
|
{ 0x11BA, "VIDEOTRON CORP"},
|
|
{ 0x11BB, "PYRAMID TECHNOLOGY"},
|
|
{ 0x11BC, "NETWORK PERIPHERALS INC"},
|
|
{ 0x11BD, "PINNACLE SYSTEMS INC."},
|
|
{ 0x11BE, "INTERNATIONAL MICROCIRCUITS INC"},
|
|
{ 0x11BF, "ASTRODESIGN, INC."},
|
|
{ 0x11C0, "HEWLETT PACKARD"},
|
|
{ 0x11C1, "AT&T MICROELECTRONICS"},
|
|
{ 0x11C2, "SAND MICROELECTRONICS"},
|
|
{ 0x11C4, "DOCUMENT TECHNOLOGIES, IND"},
|
|
{ 0x11C5, "SHIVA CORPORATION"},
|
|
{ 0x11C6, "DAINIPPON SCREEN MFG. CO. LTD"},
|
|
{ 0x11C7, "D.C.M. DATA SYSTEMS"},
|
|
{ 0x11C8, "DOLPHIN INTERCONNECT"},
|
|
{ 0x11C9, "MAGMA"},
|
|
{ 0x11CA, "LSI SYSTEMS, INC"},
|
|
{ 0x11CB, "SPECIALIX RESEARCH LTD"},
|
|
{ 0x11CC, "MICHELS & KLEBERHOFF COMPUTER GMBH"},
|
|
{ 0x11CD, "HAL COMPUTER SYSTEMS, INC."},
|
|
{ 0x11CE, "PRIMARY RATE INC"},
|
|
{ 0x11CF, "PIONEER ELECTRONIC CORPORATION"},
|
|
{ 0x11D0, "LORAL FREDERAL SYSTEMS - MANASSAS"},
|
|
{ 0x11D1, "AURAVISION"},
|
|
{ 0x11D2, "INTERCOM INC."},
|
|
{ 0x11D3, "TRANCELL SYSTEMS INC"},
|
|
{ 0x11D4, "ANALOG DEVICES"},
|
|
{ 0x11D5, "IKON CORPORATION"},
|
|
{ 0x11D6, "TEKELEC TECHNOLOGIES"},
|
|
{ 0x11D7, "TRENTON TERMINALS INC"},
|
|
{ 0x11D8, "IMAGE TECHNOLOGIES DEVELOPMENT"},
|
|
{ 0x11D9, "TEC CORPORATION"},
|
|
{ 0x11DA, "NOVELL"},
|
|
{ 0x11DB, "SEGA ENTERPRISES LITD"},
|
|
{ 0x11DC, "QUESTRA CORPORATION"},
|
|
{ 0x11DD, "CROSFIELD ELECTRONICS LIMITED"},
|
|
{ 0x11DE, "ZORAN CORPORATION"},
|
|
{ 0x11DF, "NEW WAVE PDG"},
|
|
{ 0x11E0, "CRAY COMMUNICATIONS A/S"},
|
|
{ 0x11E1, "GEC PLESSEY SEMI INC."},
|
|
{ 0x11E2, "SAMSUNG INFORMATION SYSTEMS AMERICA"},
|
|
{ 0x11E3, "QUICKLOGIC CORPORATION"},
|
|
{ 0x11E4, "SECOND WAVE INC"},
|
|
{ 0x11E5, "IIX CONSULTING"},
|
|
{ 0x11E6, "MITSUI-ZOSEN SYSTEM RESEARCH"},
|
|
{ 0x11E7, "TOSHIBA AMERICA, ELEC. COMPANY"},
|
|
{ 0x11E8, "DIGITAL PROCESSING SYSTEMS INC."},
|
|
{ 0x11E9, "HIGHWATER DESIGNS LTD."},
|
|
{ 0x11EA, "ELSAG BAILEY"},
|
|
{ 0x11EB, "FORMATION INC."},
|
|
{ 0x11EC, "CORECO INC"},
|
|
{ 0x11ED, "MEDIAMATICS"},
|
|
{ 0x11EE, "DOME IMAGING SYSTEMS INC"},
|
|
{ 0x11EF, "NICOLET TECHNOLOGIES B.V."},
|
|
{ 0x11F0, "COMPU-SHACK GMBH"},
|
|
{ 0x11F1, "SYMBIOS LOGIC INC"},
|
|
{ 0x11F2, "PICTURE TEL JAPAN K.K."},
|
|
{ 0x11F3, "KEITHLEY METRABYTE"},
|
|
{ 0x11F4, "KINETIC SYSTEMS CORPORATION"},
|
|
{ 0x11F5, "COMPUTING DEVICES INTERNATIONAL"},
|
|
{ 0x11F6, "POWERMATIC DATA SYSTEMS LTD"},
|
|
{ 0x11F7, "SCIENTIFIC ATLANTA"},
|
|
{ 0x11F8, "PMC-SIERRA INC"},
|
|
{ 0x11F9, "I-CUBE INC"},
|
|
{ 0x11FA, "KASAN ELECTRONICS COMPANY, LTD."},
|
|
{ 0x11FB, "DATEL INC"},
|
|
{ 0x11FC, "SILICON MAGIC"},
|
|
{ 0x11FD, "HIGH STREET CONSULTANTS"},
|
|
{ 0x11FE, "COMTROL CORPORATION"},
|
|
{ 0x11FF, "SCION CORPORATION"},
|
|
{ 0x1200, "CSS CORPORATION"},
|
|
{ 0x1201, "VISTA CONTROLS CORP"},
|
|
{ 0x1202, "NETWORK GENERAL CORP."},
|
|
{ 0x1203, "BAYER CORPORATION, AGFA DIVISION"},
|
|
{ 0x1204, "LATTICE SEMICONDUCTOR CORPORATION"},
|
|
{ 0x1205, "ARRAY CORPORATION"},
|
|
{ 0x1206, "AMDAHL CORPORATION"},
|
|
{ 0x1208, "PARSYTEC GMBH"},
|
|
{ 0x1209, "SCI SYSTEMS INC"},
|
|
{ 0x120A, "SYNAPTEL"},
|
|
{ 0x120B, "ADAPTIVE SOLUTIONS"},
|
|
{ 0x120D, "COMPRESSION LABS, INC."},
|
|
{ 0x120E, "CYCLADES CORPORATION"},
|
|
{ 0x120F, "ESSENTIAL COMMUNICATIONS"},
|
|
{ 0x1210, "HYPERPARALLEL TECHNOLOGIES"},
|
|
{ 0x1211, "BRAINTECH INC"},
|
|
{ 0x1212, "KINGSTON TECHNOLOGY CORP."},
|
|
{ 0x1213, "APPLIED INTELLIGENT SYSTEMS, INC."},
|
|
{ 0x1214, "PERFORMANCE TECHNOLOGIES, INC."},
|
|
{ 0x1215, "INTERWARE CO., LTD"},
|
|
{ 0x1216, "PURUP PREPRESS A/S"},
|
|
{ 0x1217, "2 MICRO, INC."},
|
|
{ 0x1218, "HYBRICON CORP."},
|
|
{ 0x1219, "FIRST VIRTUAL CORPORATION"},
|
|
{ 0x121A, "3DFX INTERACTIVE, INC."},
|
|
{ 0x121B, "ADVANCED TELECOMMUNICATIONS MODULES"},
|
|
{ 0x121C, "NIPPON TEXA CO., LTD"},
|
|
{ 0x121D, "LIPPERT AUTOMATIONSTECHNIK GMBH"},
|
|
{ 0x121E, "CSPI"},
|
|
{ 0x121F, "ARCUS TECHNOLOGY, INC."},
|
|
{ 0x1220, "ARIEL CORPORATION"},
|
|
{ 0x1221, "CONTEC CO., LTD"},
|
|
{ 0x1222, "ANCOR COMMUNICATIONS, INC."},
|
|
{ 0x1223, "HEURIKON/COMPUTER PRODUCTS"},
|
|
{ 0x122C, "SICAN GMBH"},
|
|
{ 0x1234, "TECHNICAL CORP."},
|
|
{ 0x1239, "THE 3DO Company"},
|
|
{ 0x124F, "INFORTREND TECHNOLOGY INC."},
|
|
{ 0x126F, "SILICON MOTION"},
|
|
{ 0x1275, "NETWORK APPLIANCE"},
|
|
{ 0x1278, "TRANSTECH PARALLEL SYSTEMS"},
|
|
{ 0x127B, "PIXERA CORPORATION"},
|
|
{ 0x1297, "HOLCO ENTERPRISE"},
|
|
{ 0x12A1, "SIMPACT, INC"},
|
|
{ 0x12BA, "BITTWARE RESEARCH SYSTEMS, INC."},
|
|
{ 0x12E7, "SEBRING SYSTEMS, INC."},
|
|
{ 0x12EB, "AUREAL SEMICONDUCTOR"},
|
|
{ 0x3D3D, "3DLABS"},
|
|
{ 0x4005, "AVANCE LOGIC INC"},
|
|
{ 0x5333, "S3 INC."},
|
|
{ 0x8086, "INTEL"},
|
|
{ 0x8E0E, "COMPUTONE CORPORATION"},
|
|
{ 0x9004, "ADAPTEC"},
|
|
{ 0xE159, "TIGER JET NETWORK INC."},
|
|
{ 0xEDD8, "ARK LOGIC INC"}
|
|
};
|
|
|
|
//
|
|
// Taken from the PCI driver
|
|
//
|
|
#define PCI_TYPE0_RANGE_COUNT ((PCI_TYPE0_ADDRESSES) + 1)
|
|
#define PCI_TYPE1_RANGE_COUNT ((PCI_TYPE1_ADDRESSES) + 4)
|
|
#define PCI_TYPE2_RANGE_COUNT ((PCI_TYPE2_ADDRESSES) + 1)
|
|
|
|
#if PCI_TYPE0_RANGE_COUNT > PCI_TYPE1_RANGE_COUNT
|
|
#if PCI_TYPE0_RANGE_COUNT > PCI_TYPE2_RANGE_COUNT
|
|
#define PCI_MAX_RANGE_COUNT PCI_TYPE0_RANGE_COUNT
|
|
#else
|
|
#define PCI_MAX_RANGE_COUNT PCI_TYPE2_RANGE_COUNT
|
|
#endif
|
|
#else
|
|
#if PCI_TYPE1_RANGE_COUNT > PCI_TYPE2_RANGE_COUNT
|
|
#define PCI_MAX_RANGE_COUNT PCI_TYPE1_RANGE_COUNT
|
|
#else
|
|
#define PCI_MAX_RANGE_COUNT PCI_TYPE2_RANGE_COUNT
|
|
#endif
|
|
#endif
|
|
|
|
|
|
VOID
|
|
DevExtUsage()
|
|
{
|
|
dprintf("!devext [<address> <type>]\n");
|
|
dprintf(" <address> is the address of a device extension to\n");
|
|
dprintf(" be dumped.\n");
|
|
dprintf(" <type> is the type of the object owning this extension:\n");
|
|
dprintf(" PCI if it is a PCI device extension\n");
|
|
dprintf(" ISAPNP if it is an ISAPNP device extension\n");
|
|
dprintf(" PCMCIA if it is a PCMCIA device extension\n");
|
|
dprintf(" HID if it is an HID device extension\n");
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
DevExtPciFindClassCodes(
|
|
ULONG PdoxBaseClass,
|
|
ULONG PdoxSubClass,
|
|
PUCHAR * BaseClass,
|
|
PUCHAR * SubClass
|
|
)
|
|
{
|
|
PUCHAR bc = "Unknown Base Class";
|
|
PUCHAR sc = "Unknown Sub Class";
|
|
|
|
switch (PdoxBaseClass) {
|
|
case PCI_CLASS_PRE_20:
|
|
|
|
// Class 00 - PCI_CLASS_PRE_20:
|
|
|
|
bc = "Pre PCI 2.0";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_PRE_20_NON_VGA:
|
|
sc = "Pre PCI 2.0 Non-VGA Device";
|
|
break;
|
|
case PCI_SUBCLASS_PRE_20_VGA:
|
|
sc = "Pre PCI 2.0 VGA Device";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_MASS_STORAGE_CTLR:
|
|
|
|
// Class 01 - PCI_CLASS_MASS_STORAGE_CTLR:
|
|
|
|
bc = "Mass Storage Controller";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_MSC_SCSI_BUS_CTLR:
|
|
sc = "SCSI";
|
|
break;
|
|
case PCI_SUBCLASS_MSC_IDE_CTLR:
|
|
sc = "IDE";
|
|
break;
|
|
case PCI_SUBCLASS_MSC_FLOPPY_CTLR:
|
|
sc = "Floppy";
|
|
break;
|
|
case PCI_SUBCLASS_MSC_IPI_CTLR:
|
|
sc = "IPI";
|
|
break;
|
|
case PCI_SUBCLASS_MSC_RAID_CTLR:
|
|
sc = "RAID";
|
|
break;
|
|
case PCI_SUBCLASS_MSC_OTHER:
|
|
sc = "'Other'";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_NETWORK_CTLR:
|
|
|
|
// Class 02 - PCI_CLASS_NETWORK_CTLR:
|
|
|
|
bc = "Network Controller";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_NET_ETHERNET_CTLR:
|
|
sc = "Ethernet";
|
|
break;
|
|
case PCI_SUBCLASS_NET_TOKEN_RING_CTLR:
|
|
sc = "Token Ring";
|
|
break;
|
|
case PCI_SUBCLASS_NET_FDDI_CTLR:
|
|
sc = "FDDI";
|
|
break;
|
|
case PCI_SUBCLASS_NET_ATM_CTLR:
|
|
sc = "ATM";
|
|
break;
|
|
case PCI_SUBCLASS_NET_OTHER:
|
|
sc = "'Other'";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_DISPLAY_CTLR:
|
|
|
|
// Class 03 - PCI_CLASS_DISPLAY_CTLR:
|
|
|
|
// N.B. Sub Class 00 could be VGA or 8514 depending on Interface byte:
|
|
|
|
bc = "Display Controller";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_VID_VGA_CTLR:
|
|
sc = "VGA";
|
|
break;
|
|
case PCI_SUBCLASS_VID_XGA_CTLR:
|
|
sc = "XGA";
|
|
break;
|
|
case PCI_SUBCLASS_VID_OTHER:
|
|
sc = "'Other'";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_MULTIMEDIA_DEV:
|
|
|
|
// Class 04 - PCI_CLASS_MULTIMEDIA_DEV:
|
|
|
|
bc = "Multimedia Device";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_MM_VIDEO_DEV:
|
|
sc = "Video";
|
|
break;
|
|
case PCI_SUBCLASS_MM_AUDIO_DEV:
|
|
sc = "Audio";
|
|
break;
|
|
case PCI_SUBCLASS_MM_OTHER:
|
|
sc = "'Other'";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_MEMORY_CTLR:
|
|
|
|
// Class 05 - PCI_CLASS_MEMORY_CTLR:
|
|
|
|
bc = "Memory Controller";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_MEM_RAM:
|
|
sc = "RAM";
|
|
break;
|
|
case PCI_SUBCLASS_MEM_FLASH:
|
|
sc = "FLASH";
|
|
break;
|
|
case PCI_SUBCLASS_MEM_OTHER:
|
|
sc = "'Other'";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_BRIDGE_DEV:
|
|
|
|
// Class 06 - PCI_CLASS_BRIDGE_DEV:
|
|
|
|
bc = "Bridge";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_BR_HOST:
|
|
sc = "HOST to PCI";
|
|
break;
|
|
case PCI_SUBCLASS_BR_ISA:
|
|
sc = "PCI to ISA";
|
|
break;
|
|
case PCI_SUBCLASS_BR_EISA:
|
|
sc = "PCI to EISA";
|
|
break;
|
|
case PCI_SUBCLASS_BR_MCA:
|
|
sc = "PCI to MCA";
|
|
break;
|
|
case PCI_SUBCLASS_BR_PCI_TO_PCI:
|
|
sc = "PCI to PCI";
|
|
break;
|
|
case PCI_SUBCLASS_BR_PCMCIA:
|
|
sc = "PCI to PCMCIA";
|
|
break;
|
|
case PCI_SUBCLASS_BR_NUBUS:
|
|
sc = "PCI to NUBUS";
|
|
break;
|
|
case PCI_SUBCLASS_BR_CARDBUS:
|
|
sc = "PCI to CardBus";
|
|
break;
|
|
case PCI_SUBCLASS_BR_OTHER:
|
|
sc = "PCI to 'Other'";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_SIMPLE_COMMS_CTLR:
|
|
|
|
// Class 07 - PCI_CLASS_SIMPLE_COMMS_CTLR:
|
|
|
|
// N.B. Sub Class 00 and 01 additional info in Interface byte:
|
|
|
|
bc = "Simple Serial Communications Controller";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_COM_SERIAL:
|
|
sc = "Serial Port";
|
|
break;
|
|
case PCI_SUBCLASS_COM_PARALLEL:
|
|
sc = "Parallel Port";
|
|
break;
|
|
case PCI_SUBCLASS_COM_OTHER:
|
|
sc = "'Other'";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_BASE_SYSTEM_DEV:
|
|
|
|
// Class 08 - PCI_CLASS_BASE_SYSTEM_DEV:
|
|
|
|
// N.B. See Interface byte for additional info.:
|
|
|
|
bc = "Base System Device";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_SYS_INTERRUPT_CTLR:
|
|
sc = "Interrupt Controller";
|
|
break;
|
|
case PCI_SUBCLASS_SYS_DMA_CTLR:
|
|
sc = "DMA Controller";
|
|
break;
|
|
case PCI_SUBCLASS_SYS_SYSTEM_TIMER:
|
|
sc = "System Timer";
|
|
break;
|
|
case PCI_SUBCLASS_SYS_REAL_TIME_CLOCK:
|
|
sc = "Real Time Clock";
|
|
break;
|
|
case PCI_SUBCLASS_SYS_OTHER:
|
|
sc = "'Other' base system device";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_INPUT_DEV:
|
|
|
|
// Class 09 - PCI_CLASS_INPUT_DEV:
|
|
|
|
bc = "Input Device";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_INP_KEYBOARD:
|
|
sc = "Keyboard";
|
|
break;
|
|
case PCI_SUBCLASS_INP_DIGITIZER:
|
|
sc = "Digitizer";
|
|
break;
|
|
case PCI_SUBCLASS_INP_MOUSE:
|
|
sc = "Mouse";
|
|
break;
|
|
case PCI_SUBCLASS_INP_OTHER:
|
|
sc = "'Other'";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_DOCKING_STATION:
|
|
|
|
// Class 0a - PCI_CLASS_DOCKING_STATION:
|
|
|
|
bc = "Docking Station";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_DOC_GENERIC:
|
|
sc = "Generic";
|
|
break;
|
|
case PCI_SUBCLASS_DOC_OTHER:
|
|
sc = "'Other'";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_PROCESSOR:
|
|
|
|
// Class 0b - PCI_CLASS_PROCESSOR:
|
|
|
|
bc = "Processor";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_PROC_386:
|
|
sc = "386";
|
|
break;
|
|
case PCI_SUBCLASS_PROC_486:
|
|
sc = "486";
|
|
break;
|
|
case PCI_SUBCLASS_PROC_PENTIUM:
|
|
sc = "Pentium";
|
|
break;
|
|
case PCI_SUBCLASS_PROC_ALPHA:
|
|
sc = "Alpha";
|
|
break;
|
|
case PCI_SUBCLASS_PROC_POWERPC:
|
|
sc = "PowerPC";
|
|
break;
|
|
case PCI_SUBCLASS_PROC_COPROCESSOR:
|
|
sc = "CoProcessor";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_SERIAL_BUS_CTLR:
|
|
|
|
// Class 0c - PCI_CLASS_SERIAL_BUS_CTLR:
|
|
|
|
bc = "Serial Bus Controller";
|
|
|
|
switch (PdoxSubClass) {
|
|
case PCI_SUBCLASS_SB_IEEE1394:
|
|
sc = "1394";
|
|
break;
|
|
case PCI_SUBCLASS_SB_ACCESS:
|
|
sc = "Access Bus";
|
|
break;
|
|
case PCI_SUBCLASS_SB_SSA:
|
|
sc = "SSA";
|
|
break;
|
|
case PCI_SUBCLASS_SB_USB:
|
|
sc = "USB";
|
|
break;
|
|
case PCI_SUBCLASS_SB_FIBRE_CHANNEL:
|
|
sc = "Fibre Channel";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PCI_CLASS_NOT_DEFINED:
|
|
|
|
bc = "(Explicitly) Undefined";
|
|
break;
|
|
}
|
|
*BaseClass = bc;
|
|
*SubClass = sc;
|
|
}
|
|
|
|
|
|
VOID
|
|
DevExtPciPrintDeviceState(
|
|
PCI_OBJECT_STATE State
|
|
)
|
|
{
|
|
if ((sizeof(DevExtPciDeviceState) / sizeof(DevExtPciDeviceState[0])) !=
|
|
PciMaxObjectState) {
|
|
dprintf("\nWARNING: PCI_OBJECT_STATE enumeration changed, please review.\n");
|
|
}
|
|
|
|
if (State >= PciMaxObjectState) {
|
|
dprintf("Unknown PCI Object state.\n");
|
|
return;
|
|
}
|
|
|
|
dprintf(" Driver State = %s\n", DevExtPciDeviceState[State]);
|
|
}
|
|
|
|
//#if 0
|
|
VOID
|
|
DevExtPciPrintPowerState(
|
|
ULONG64 Power
|
|
)
|
|
{
|
|
#define MAXSYSPOWSTATES \
|
|
(sizeof(DevExtPciSystemPowerState) / sizeof(DevExtPciSystemPowerState[0]))
|
|
#define MAXDEVPOWSTATES \
|
|
(sizeof(DevExtPciDevicePowerState) / sizeof(DevExtPciDevicePowerState[0]))
|
|
|
|
SYSTEM_POWER_STATE index;
|
|
DEVICE_POWER_STATE systemStateMapping[PowerSystemMaximum];
|
|
ULONG64 pwrState, waitWakeIrp=0;
|
|
PUCHAR sw, sc, dd, dc, dw;
|
|
|
|
//
|
|
// A little sanity.
|
|
//
|
|
|
|
if (MAXSYSPOWSTATES != PowerSystemMaximum) {
|
|
dprintf("WARNING: System Power State definition has changed, ext dll is out of date.\n");
|
|
}
|
|
|
|
if (MAXDEVPOWSTATES != PowerDeviceMaximum) {
|
|
dprintf("WARNING: Device Power State definition has changed, ext dll is out of date.\n");
|
|
}
|
|
|
|
sw = sc = dc = dw = "<*BAD VAL*>";
|
|
|
|
GetFieldValue(Power, "pci!PCI_POWER_STATE", "CurrentSystemState", pwrState);
|
|
if (pwrState < PowerSystemMaximum) {
|
|
sc = DevExtPciSystemPowerState[pwrState];
|
|
}
|
|
|
|
GetFieldValue(Power, "pci!PCI_POWER_STATE", "CurrentDeviceState", pwrState);
|
|
if (pwrState < PowerDeviceMaximum) {
|
|
dc = DevExtPciDevicePowerState[pwrState];
|
|
}
|
|
|
|
GetFieldValue(Power, "pci!PCI_POWER_STATE", "DeviceWakeLevel", pwrState);
|
|
if (pwrState < PowerDeviceMaximum) {
|
|
dw = DevExtPciDevicePowerState[pwrState];
|
|
}
|
|
|
|
GetFieldValue(Power, "pci!PCI_POWER_STATE", "SystemWakeLevel", pwrState);
|
|
if (pwrState < PowerSystemMaximum) {
|
|
sw = DevExtPciSystemPowerState[pwrState];
|
|
}
|
|
|
|
dprintf(
|
|
" CurrentState: System %s, Device %s\n"
|
|
" WakeLevel: System %s, Device %s\n",
|
|
sc,
|
|
dc,
|
|
sw,
|
|
dw
|
|
);
|
|
|
|
GetFieldValue(Power, "pci!PCI_POWER_STATE", "SystemStateMapping", systemStateMapping);
|
|
|
|
for (index = PowerSystemWorking; index < PowerSystemMaximum; index++) {
|
|
|
|
if (systemStateMapping[index] != PowerDeviceUnspecified) {
|
|
|
|
if (systemStateMapping[index] < PowerDeviceMaximum) {
|
|
|
|
dc = DevExtPciDevicePowerState[systemStateMapping[index]];
|
|
|
|
} else {
|
|
|
|
dc = "<*BAD VAL*>";
|
|
|
|
}
|
|
dprintf(" %s:\t%s\n",
|
|
DevExtPciSystemPowerState[index],
|
|
dc
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GetFieldValue(Power, "pci!PCI_POWER_STATE", "WaitWakeIrp", waitWakeIrp);
|
|
|
|
if (waitWakeIrp) {
|
|
dprintf(" WaitWakeIrp: %#08p\n",
|
|
waitWakeIrp
|
|
);
|
|
}
|
|
|
|
#undef MAXSYSPOWSTATES
|
|
#undef MAXDEVPOWSTATES
|
|
}
|
|
|
|
VOID
|
|
DevExtPciPrintSecondaryExtensions(
|
|
ULONG64 ListEntry
|
|
)
|
|
{
|
|
ULONG64 extension = 0, extype = 0;
|
|
|
|
if (!ListEntry) {
|
|
return;
|
|
}
|
|
xdprintf(1, "Secondary Extensions\n");
|
|
do {
|
|
|
|
GetFieldValue(ListEntry, "pci!PCI_SECONDARY_EXTENSION", "ExtensionType", extype);
|
|
|
|
switch (extype) {
|
|
case PciArb_Io:
|
|
xdprintf(2, "Arbiter - IO Port");
|
|
break;
|
|
case PciArb_Memory:
|
|
xdprintf(2, "Arbiter - Memory");
|
|
break;
|
|
case PciArb_Interrupt:
|
|
xdprintf(2, "Arbiter - Interrupt");
|
|
break;
|
|
case PciArb_BusNumber:
|
|
xdprintf(2, "Arbiter - Bus Number");
|
|
break;
|
|
case PciTrans_Interrupt:
|
|
xdprintf(2, "Translator - Interrupt");
|
|
break;
|
|
case PciInterface_BusHandler:
|
|
xdprintf(2, "Interface - Bus Handler");
|
|
break;
|
|
case PciInterface_IntRouteHandler:
|
|
xdprintf(2, "Interface - Interrupt Route Handler");
|
|
break;
|
|
default:
|
|
xdprintf(2, "Unknown Extension Type.");
|
|
break;
|
|
}
|
|
dprintf("\n");
|
|
|
|
GetFieldValue(ListEntry, "nt!_SINGLE_LIST_ENTRY", "Next", ListEntry);
|
|
|
|
} while (ListEntry);
|
|
}
|
|
|
|
PUCHAR
|
|
DevExtPciFindVendorId(
|
|
USHORT VendorId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the vendor name given the vendor ID (assuming we know it).
|
|
|
|
Arguments:
|
|
|
|
VendorId 16 bit PCI Vendor ID.
|
|
|
|
Return Value:
|
|
|
|
Pointer to the vendor's name (or NULL).
|
|
|
|
--*/
|
|
|
|
{
|
|
#define PCIIDCOUNT (sizeof(DevExtPciVendors) / sizeof(DevExtPciVendors[0]))
|
|
|
|
ULONG index;
|
|
|
|
//
|
|
// Yep, a binary search would be much faster, good thing we only
|
|
// do this once per user iteration.
|
|
//
|
|
|
|
for (index = 0; index < PCIIDCOUNT; index++) {
|
|
if (DevExtPciVendors[index].VendorId == VendorId) {
|
|
return DevExtPciVendors[index].VendorName;
|
|
}
|
|
}
|
|
return NULL;
|
|
|
|
#undef PCIIDCOUNT
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define GET_PCI_PDO_FIELD(Pdo,Field,Value) \
|
|
GetPciExtensionField(TRUE, Pdo, Field, sizeof(Value), (PVOID)(&(Value)))
|
|
|
|
#define GET_PCI_FDO_FIELD(Fdo,Field,Value) \
|
|
GetPciExtensionField(FALSE, Fdo, Field, sizeof(Value), (PVOID)(&(Value)))
|
|
|
|
ULONG
|
|
GetPciExtensionField(
|
|
IN BOOLEAN IsPdo, // TRUE for PDO, false for FDO
|
|
IN ULONG64 TypeAddress,
|
|
IN PUCHAR Field,
|
|
IN ULONG OutSize,
|
|
OUT PVOID OutValue
|
|
)
|
|
{
|
|
ULONG ret;
|
|
static PCHAR pciFDO = "nt!_PCI_FDO_EXTENSION", pciPDO = "nt!_PCI_PDO_EXTENSION";
|
|
|
|
|
|
|
|
//
|
|
// Try the post Win2k name for a pci extension (includes a PCI_ prefix)
|
|
//
|
|
|
|
// This would work for public symbols
|
|
ret = GetFieldData(TypeAddress,
|
|
IsPdo ? pciPDO : pciFDO,
|
|
Field,
|
|
OutSize,
|
|
OutValue
|
|
);
|
|
if (ret) {
|
|
|
|
pciFDO = "pci!PCI_FDO_EXTENSION";
|
|
pciPDO = "pci!PCI_PDO_EXTENSION";
|
|
|
|
//
|
|
// If we have private symbols, nt won't have those types, so try in pci
|
|
//
|
|
ret = GetFieldData(TypeAddress,
|
|
IsPdo ? pciPDO : pciFDO,
|
|
Field,
|
|
OutSize,
|
|
OutValue
|
|
);
|
|
}
|
|
|
|
|
|
//
|
|
// If that failed then fall back on the name without the PCI_ prefix. This
|
|
// allows debugging Win2k clients with the post Win2k debugger
|
|
//
|
|
|
|
if (ret) {
|
|
ret = GetFieldData(TypeAddress,
|
|
IsPdo ? "pci!PDO_EXTENSION" : "pci!FDO_EXTENSION",
|
|
Field,
|
|
OutSize,
|
|
OutValue
|
|
);
|
|
}
|
|
|
|
if (ret) {
|
|
// didn't find anything, reste these
|
|
pciFDO = "nt!_PCI_FDO_EXTENSION";
|
|
pciPDO = "nt!_PCI_PDO_EXTENSION";
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
typedef struct _PCI_SLOT_NUMBER {
|
|
union {
|
|
struct {
|
|
ULONG DeviceNumber:5;
|
|
ULONG FunctionNumber:3;
|
|
ULONG Reserved:24;
|
|
} bits;
|
|
ULONG AsULONG;
|
|
} u;
|
|
} PCI_SLOT_NUMBER, *PPCI_SLOT_NUMBER;
|
|
|
|
|
|
VOID
|
|
DevExtPciGetBusDevFunc(
|
|
IN ULONG64 PdoExt,
|
|
OUT PULONG Bus,
|
|
OUT PULONG Dev,
|
|
OUT PULONG Func
|
|
)
|
|
{
|
|
ULONG BaseBus=0;
|
|
ULONG64 ParentFdoExtension=0;
|
|
PCI_SLOT_NUMBER slot;
|
|
|
|
|
|
GET_PCI_PDO_FIELD(PdoExt, "ParentFdoExtension", ParentFdoExtension);
|
|
|
|
if (GET_PCI_FDO_FIELD(ParentFdoExtension, "BaseBus", BaseBus)) {
|
|
dprintf(
|
|
"Failed to read memory at %08x for sizeof FDO Extension.\n",
|
|
ParentFdoExtension
|
|
);
|
|
}
|
|
|
|
if (GET_PCI_PDO_FIELD(PdoExt, "Slot", slot)){
|
|
dprintf(
|
|
"Failed to read memory at %08x\n",
|
|
PdoExt
|
|
);
|
|
}
|
|
|
|
*Bus = BaseBus;
|
|
*Dev = slot.u.bits.DeviceNumber;
|
|
*Func = slot.u.bits.FunctionNumber;
|
|
|
|
}
|
|
|
|
VOID
|
|
DevExtPci(
|
|
ULONG64 Extension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump a PCI Device extension.
|
|
|
|
Arguments:
|
|
|
|
Extension Address of the extension to be dumped.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG64 pdo=0, fdoX=0, pdoX=0, pcifield=0;
|
|
ULONG Signature=0, fieldoffset=0;
|
|
ULONG bus=0xff,dev=0xff,func=0xff;
|
|
USHORT vendorId=0xffff, deviceId=0xffff, subsystemVendorId=0xfff, subsystemId=0xffff;
|
|
UCHAR deviceState, baseClass, subClass, progIf, revisionId, interruptPin, rawInterruptLine, adjustedInterruptLine;
|
|
UCHAR secBus=0xff, subBus=0xff;
|
|
PUCHAR s;
|
|
PUCHAR bc;
|
|
PUCHAR sc;
|
|
ULONG i;
|
|
BOOLEAN found, subDecode=FALSE, isaBit=FALSE, vgaBit=FALSE;
|
|
|
|
if (GET_PCI_PDO_FIELD(Extension, "ExtensionType", Signature)) {
|
|
dprintf(
|
|
"Failed to read PCI object signature at %008p, giving up.\n",
|
|
Extension
|
|
);
|
|
return;
|
|
}
|
|
|
|
switch (Signature) {
|
|
case PciPdoExtensionType:
|
|
|
|
//
|
|
// PDO Extension.
|
|
//
|
|
|
|
DevExtPciGetBusDevFunc(Extension, &bus, &dev, &func);
|
|
dprintf("PDO Extension, Bus 0x%x, Device %x, Function %d.\n",
|
|
bus, dev, func
|
|
);
|
|
|
|
GET_PCI_PDO_FIELD(Extension, "PhysicalDeviceObject", pdo);
|
|
GET_PCI_PDO_FIELD(Extension, "ParentFdoExtension", fdoX);
|
|
|
|
dprintf(" DevObj %#08p PCI Parent Bus FDO DevExt %#08p\n",
|
|
pdo, fdoX
|
|
);
|
|
|
|
GET_PCI_PDO_FIELD(Extension, "DeviceState", deviceState);
|
|
GET_PCI_PDO_FIELD(Extension, "VendorId", vendorId);
|
|
GET_PCI_PDO_FIELD(Extension, "DeviceId", deviceId);
|
|
|
|
DevExtPciPrintDeviceState(deviceState);
|
|
|
|
s = DevExtPciFindVendorId(vendorId);
|
|
if (s != NULL) {
|
|
dprintf(" Vendor ID %04x (%s) Device ID %04X\n",
|
|
vendorId,
|
|
s,
|
|
deviceId
|
|
);
|
|
} else {
|
|
dprintf(
|
|
" Vendor ID %04x, Device ID %04X\n",
|
|
vendorId,
|
|
deviceId
|
|
);
|
|
}
|
|
|
|
GET_PCI_PDO_FIELD(Extension, "SubsystemVendorId", subsystemVendorId);
|
|
GET_PCI_PDO_FIELD(Extension, "SubsystemId", subsystemId);
|
|
|
|
if (subsystemVendorId || subsystemId) {
|
|
s = DevExtPciFindVendorId(subsystemVendorId);
|
|
if (s != NULL) {
|
|
dprintf(
|
|
" Subsystem Vendor ID %04x (%s) Subsystem ID %04X\n",
|
|
subsystemVendorId,
|
|
s,
|
|
subsystemId
|
|
);
|
|
} else {
|
|
dprintf(" Subsystem Vendor ID %04x, Subsystem ID %04X\n",
|
|
subsystemVendorId,
|
|
subsystemId
|
|
);
|
|
}
|
|
}
|
|
|
|
GET_PCI_PDO_FIELD(Extension, "BaseClass", baseClass);
|
|
GET_PCI_PDO_FIELD(Extension, "SubClass", subClass);
|
|
|
|
DevExtPciFindClassCodes(baseClass, subClass, &bc, &sc);
|
|
|
|
dprintf(" Class Base/Sub %02x/%02x (%s/%s)\n",
|
|
baseClass,
|
|
subClass,
|
|
bc,
|
|
sc);
|
|
|
|
GET_PCI_PDO_FIELD(Extension, "ProgIf", progIf);
|
|
GET_PCI_PDO_FIELD(Extension, "RevisionId", revisionId);
|
|
GET_PCI_PDO_FIELD(Extension, "InterruptPin", interruptPin);
|
|
GET_PCI_PDO_FIELD(Extension, "RawInterruptLine", rawInterruptLine);
|
|
GET_PCI_PDO_FIELD(Extension, "AdjustedInterruptLine", adjustedInterruptLine);
|
|
dprintf(" Programming Interface: %02x, Revision: %02x, IntPin: %02x, Line Raw/Adj %02x/%02x\n",
|
|
progIf,
|
|
revisionId,
|
|
interruptPin,
|
|
rawInterruptLine,
|
|
adjustedInterruptLine
|
|
);
|
|
|
|
{
|
|
USHORT enables=0;
|
|
|
|
GET_PCI_PDO_FIELD(Extension, "CommandEnables", enables);
|
|
|
|
dprintf(" Enables ((cmd & 7) = %x): %s%s%s",
|
|
enables,
|
|
enables == 0 ? "<none>" :
|
|
(enables & PCI_ENABLE_BUS_MASTER) ? "B" : "",
|
|
(enables & PCI_ENABLE_MEMORY_SPACE) ? "M" : "",
|
|
(enables & PCI_ENABLE_IO_SPACE) ? "I" : ""
|
|
);
|
|
|
|
GET_PCI_PDO_FIELD(Extension, "CapabilitiesPtr", pcifield);
|
|
|
|
|
|
if (pcifield) {
|
|
dprintf(" Capabilities Pointer = %02x\n", pcifield);
|
|
} else {
|
|
dprintf(" Capabilities Pointer = <none>\n");
|
|
}
|
|
}
|
|
|
|
GetFieldOffset("pci!PCI_PDO_EXTENSION", "PowerState", &fieldoffset);
|
|
|
|
DevExtPciPrintPowerState(Extension+fieldoffset);
|
|
|
|
if (baseClass == PCI_CLASS_BRIDGE_DEV) {
|
|
|
|
if ((subClass == PCI_SUBCLASS_BR_PCI_TO_PCI) ||
|
|
(subClass == PCI_SUBCLASS_BR_CARDBUS)) {
|
|
|
|
GetFieldOffset("pci!PCI_PDO_EXTENSION", "Dependent", &fieldoffset);
|
|
|
|
GetFieldValue(Extension+fieldoffset,
|
|
"pci!PCI_HEADER_TYPE_DEPENDENT",
|
|
"type1.SecondaryBus",
|
|
secBus);
|
|
|
|
GetFieldValue(Extension+fieldoffset,
|
|
"pci!PCI_HEADER_TYPE_DEPENDENT",
|
|
"type1.SecondaryBus",
|
|
subBus);
|
|
|
|
dprintf(" Bridge PCI-%s Secondary Bus = 0x%x, Subordinate Bus = 0x%x\n",
|
|
subClass == PCI_SUBCLASS_BR_PCI_TO_PCI
|
|
? "PCI" : "CardBus",
|
|
secBus,
|
|
subBus
|
|
);
|
|
|
|
GetFieldValue(Extension+fieldoffset,
|
|
"pci!PCI_HEADER_TYPE_DEPENDENT",
|
|
"type1.SubtractiveDecode",
|
|
subDecode);
|
|
|
|
GetFieldValue(Extension+fieldoffset,
|
|
"pci!PCI_HEADER_TYPE_DEPENDENT",
|
|
"type1.IsaBitSet",
|
|
isaBit);
|
|
|
|
GetFieldValue(Extension+fieldoffset,
|
|
"pci!PCI_HEADER_TYPE_DEPENDENT",
|
|
"type1.VgaBitSet",
|
|
vgaBit);
|
|
|
|
if (subDecode || isaBit || vgaBit) {
|
|
CHAR preceed = ' ';
|
|
|
|
dprintf(" Bridge Flags:");
|
|
|
|
if (subDecode) {
|
|
dprintf("%c Subtractive Decode", preceed);
|
|
preceed = ',';
|
|
}
|
|
if (isaBit) {
|
|
dprintf("%c ISA", preceed);
|
|
preceed = ',';
|
|
}
|
|
if (vgaBit) {
|
|
dprintf("%c VGA", preceed);
|
|
preceed = ',';
|
|
}
|
|
dprintf("\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now lets parse our PCI_FUNCTION_RESOURCES struct
|
|
//
|
|
|
|
pcifield = 0;
|
|
GET_PCI_PDO_FIELD(Extension, "Resources", pcifield);
|
|
|
|
dprintf(" Requirements:");
|
|
|
|
if (pcifield) {
|
|
|
|
ULONG64 limit = 0, current=0;
|
|
ULONG ioSize=0, cmSize=0, type=0;
|
|
ULONG alignment, length, minhighpart, minlowpart, maxhighpart, maxlowpart;
|
|
|
|
ioSize = GetTypeSize("nt!IO_RESOURCE_DESCRIPTOR");
|
|
cmSize = GetTypeSize("nt!CM_PARTIAL_RESOURCE_DESCRIPTOR");
|
|
|
|
//
|
|
// Limit begins at offset 0
|
|
//
|
|
limit = pcifield;
|
|
|
|
found = FALSE;
|
|
dprintf(" Alignment Length Minimum Maximum\n");
|
|
for (i = 0; i < PCI_MAX_RANGE_COUNT; i++) {
|
|
|
|
type=0;
|
|
|
|
GetFieldValue(limit, "nt!IO_RESOURCE_DESCRIPTOR", "Type", type);
|
|
|
|
if (type == CmResourceTypeNull) {
|
|
continue;
|
|
}
|
|
|
|
GetFieldValue(limit, "nt!IO_RESOURCE_DESCRIPTOR", "u.Generic.Alignment", alignment);
|
|
GetFieldValue(limit, "nt!IO_RESOURCE_DESCRIPTOR", "u.Generic.Length", length);
|
|
GetFieldValue(limit, "nt!IO_RESOURCE_DESCRIPTOR", "u.Generic.MinimumAddress.HighPart", minhighpart);
|
|
GetFieldValue(limit, "nt!IO_RESOURCE_DESCRIPTOR", "u.Generic.MinimumAddress.LowPart", minlowpart);
|
|
GetFieldValue(limit, "nt!IO_RESOURCE_DESCRIPTOR", "u.Generic.MaximumAddress.HighPart", maxhighpart);
|
|
GetFieldValue(limit, "nt!IO_RESOURCE_DESCRIPTOR", "u.Generic.MaximumAddress.LowPart", maxlowpart);
|
|
|
|
dprintf(" %s: %08x %08x %08x%08x %08x%08x\n",
|
|
type == CmResourceTypeMemory ? "Memory" : " Io",
|
|
alignment,
|
|
length,
|
|
minhighpart,
|
|
minlowpart,
|
|
maxhighpart,
|
|
maxlowpart
|
|
);
|
|
|
|
limit += ioSize;
|
|
}
|
|
|
|
//
|
|
// Get the offset for Current so we can dump it next
|
|
//
|
|
GetFieldOffset("pci!PCI_FUNCTION_RESOURCES", "Current", &fieldoffset);
|
|
|
|
current = pcifield+fieldoffset;
|
|
|
|
dprintf(" Current:");
|
|
for (i = 0; i < PCI_MAX_RANGE_COUNT; i++) {
|
|
|
|
type=0;
|
|
length=0;
|
|
maxhighpart=0;
|
|
maxlowpart=0;
|
|
|
|
GetFieldValue(current, "nt!CM_PARTIAL_RESOURCE_DESCRIPTOR", "Type", type);
|
|
|
|
if (type == CmResourceTypeNull) {
|
|
continue;
|
|
}
|
|
|
|
if (!found) {
|
|
dprintf(" Start Length\n");
|
|
found = TRUE;
|
|
}
|
|
|
|
GetFieldValue(current, "nt!CM_PARTIAL_RESOURCE_DESCRIPTOR", "u.Generic.Start.HighPart", maxhighpart);
|
|
GetFieldValue(current, "nt!CM_PARTIAL_RESOURCE_DESCRIPTOR", "u.Generic.Start.LowPart", maxlowpart);
|
|
GetFieldValue(current, "nt!CM_PARTIAL_RESOURCE_DESCRIPTOR", "u.Generic.Length", length);
|
|
|
|
dprintf(" %s: %08x%08x %08x\n",
|
|
type == CmResourceTypeMemory ? "Memory" : " Io",
|
|
maxhighpart,
|
|
maxlowpart,
|
|
length
|
|
);
|
|
|
|
current += cmSize;
|
|
}
|
|
|
|
if (!found) {
|
|
dprintf(" <none>\n");
|
|
}
|
|
|
|
} else {
|
|
dprintf(" <none>\n");
|
|
}
|
|
|
|
GetFieldOffset("pci!PCI_PDO_EXTENSION", "SecondaryExtension", &fieldoffset);
|
|
|
|
GetFieldValue(Extension+fieldoffset, "nt!_SINGLE_LIST_ENTRY", "Next", pcifield);
|
|
|
|
DevExtPciPrintSecondaryExtensions(pcifield);
|
|
|
|
break;
|
|
|
|
case PciFdoExtensionType:
|
|
|
|
//
|
|
// FDO Extension
|
|
//
|
|
|
|
GET_PCI_FDO_FIELD(Extension, "BaseBus", bus);
|
|
GET_PCI_FDO_FIELD(Extension, "PhysicalDeviceObject", pdo);
|
|
|
|
dprintf("FDO Extension, Bus 0x%x, Parent PDO %#08p Bus is ", bus,pdo);
|
|
|
|
GET_PCI_FDO_FIELD(Extension, "BusRootFdoExtension", pcifield);
|
|
|
|
if (pcifield == Extension) {
|
|
dprintf("a root bus.\n");
|
|
} else {
|
|
|
|
GET_PCI_FDO_FIELD(Extension, "PhysicalDeviceObject", pcifield);
|
|
|
|
GetFieldValue(pcifield, "nt!_DEVICE_OBJECT", "DeviceExtension", pdoX);
|
|
|
|
if (!pdoX) {
|
|
dprintf("a child bus.\n");
|
|
}else{
|
|
DevExtPciGetBusDevFunc(pdoX, &bus, &dev, &func);
|
|
dprintf("a child of bus 0x%x.\n", bus);
|
|
}
|
|
|
|
}
|
|
|
|
GET_PCI_FDO_FIELD(Extension, "DeviceState", deviceState);
|
|
DevExtPciPrintDeviceState(deviceState);
|
|
|
|
GetFieldOffset("pci!PCI_FDO_EXTENSION", "PowerState", &fieldoffset);
|
|
DevExtPciPrintPowerState(Extension+fieldoffset);
|
|
|
|
GET_PCI_FDO_FIELD(Extension, "ChildWaitWakeCount", pcifield);
|
|
|
|
if (pcifield) {
|
|
dprintf("Number of PDO's with outstanding WAIT_WAKEs = %d\n", pcifield);
|
|
}
|
|
|
|
{
|
|
PUCHAR heading = " Child PDOXs:";
|
|
ULONG counter = 0;
|
|
ULONG64 list = 0;
|
|
|
|
GET_PCI_FDO_FIELD(Extension, "ChildPdoList", list);
|
|
|
|
while (list) {
|
|
if (counter == 0) {
|
|
dprintf(heading);
|
|
heading = "\n ";
|
|
counter = 1;
|
|
} else if (counter == 2) {
|
|
counter = 0;
|
|
} else {
|
|
counter++;
|
|
}
|
|
dprintf(" %#08p", list);
|
|
|
|
GET_PCI_PDO_FIELD(list, "Next", list);
|
|
}
|
|
|
|
dprintf("\n");
|
|
|
|
}
|
|
|
|
GetFieldOffset("pci!PCI_FDO_EXTENSION", "SecondaryExtension", &fieldoffset);
|
|
|
|
GetFieldValue(Extension+fieldoffset, "nt!_SINGLE_LIST_ENTRY", "Next", pcifield);
|
|
|
|
DevExtPciPrintSecondaryExtensions(pcifield);
|
|
|
|
break;
|
|
default:
|
|
dprintf("%08x doesn't seem to point to a PCI PDO or FDO extension,\n", Signature);
|
|
dprintf("the PCI Device object extension signatures don't match.\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
DECLARE_API( devext )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps a device extension.
|
|
|
|
Arguments:
|
|
|
|
address Address of the device extension to be dumped.
|
|
type Type of device extension.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
#define DEVEXT_MAXTOKENS 3
|
|
#define DEVEXT_MAXBUFFER 80
|
|
#define DEVEXT_USAGE() { DevExtUsage(); return E_INVALIDARG; }
|
|
|
|
ULONG64 Extension = 0;
|
|
PUCHAR ExtensionType;
|
|
PUCHAR Tokens[DEVEXT_MAXTOKENS];
|
|
UCHAR Buffer[DEVEXT_MAXBUFFER];
|
|
PUCHAR s;
|
|
UCHAR c;
|
|
ULONG count;
|
|
|
|
//
|
|
// Validate parameters. Tokenize the incoming string, the first
|
|
// argument should be a (kernel mode) address, the second a string.
|
|
//
|
|
|
|
//
|
|
// args is const, we need to modify the buffer, copy it.
|
|
//
|
|
|
|
for (count = 0; count < DEVEXT_MAXBUFFER; count++) {
|
|
if ((Buffer[count] = args[count]) == '\0') {
|
|
break;
|
|
}
|
|
}
|
|
if (count == DEVEXT_MAXBUFFER) {
|
|
dprintf("Buffer to small to contain input arguments\n");
|
|
DEVEXT_USAGE();
|
|
}
|
|
|
|
if (TokenizeString(Buffer, Tokens, DEVEXT_MAXTOKENS) !=
|
|
(DEVEXT_MAXTOKENS - 1)) {
|
|
DEVEXT_USAGE();
|
|
}
|
|
|
|
if ((Extension = GetExpression(Tokens[0])) == 0) {
|
|
DEVEXT_USAGE();
|
|
}
|
|
|
|
// Signextend it
|
|
if (DBG_PTR_SIZE == sizeof(ULONG)) {
|
|
Extension = (ULONG64) (LONG64) (LONG) Extension;
|
|
}
|
|
if ((LONG64)Extension >= 0) {
|
|
DEVEXT_USAGE();
|
|
}
|
|
|
|
//
|
|
// The second argument should be a string telling us what kind of
|
|
// device extension to dump. Convert it to upper case to make life
|
|
// easier.
|
|
//
|
|
|
|
s = Tokens[1];
|
|
while ((c = *s) != '\0') {
|
|
*s++ = (UCHAR)toupper(c);
|
|
}
|
|
|
|
s = Tokens[1];
|
|
if (!strcmp(s, "PCI")) {
|
|
|
|
//
|
|
// It's a PCI device extension.
|
|
//
|
|
DevExtPci(Extension);
|
|
|
|
} else if (!strcmp(s, "PCMCIA")) {
|
|
//
|
|
// It's a PCMCIA device extension
|
|
//
|
|
DevExtPcmcia(Extension);
|
|
|
|
} else if (!strcmp(s, "HID")) {
|
|
//
|
|
// It's a HID device extension
|
|
//
|
|
DevExtHID(Extension);
|
|
|
|
} else if (!strcmp(s, "ISAPNP")) {
|
|
//
|
|
// Congratulations! It's an ISAPNP device extension
|
|
//
|
|
DevExtIsapnp(Extension);
|
|
|
|
#if 0
|
|
|
|
} else if (!strcmp(s, "SOME_OTHER_EXTENSION_TYPE")) {
|
|
|
|
//
|
|
// It's some other extension type.
|
|
//
|
|
|
|
DevExtSomeOther(Extension);
|
|
|
|
#endif
|
|
} else {
|
|
dprintf("Device extension type '%s' is not handled by !devext.\n", s);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// pcitree data structures and functions
|
|
//
|
|
|
|
BOOLEAN
|
|
pcitreeProcessBus(
|
|
ULONG Indent,
|
|
ULONG64 InMemoryBusFdoX,
|
|
ULONG64 TreeTop
|
|
)
|
|
{
|
|
ULONG64 BusFdoX=InMemoryBusFdoX;
|
|
ULONG64 next;
|
|
PUCHAR bc, sc, vendor;
|
|
ULONG BaseBus, BaseClass, SubClass;
|
|
ULONG64 ChildPdoList;
|
|
|
|
#define PdoxFld(F,V) GET_PCI_PDO_FIELD(next, #F, V)
|
|
|
|
GET_PCI_FDO_FIELD(BusFdoX, "BaseBus", BaseBus);
|
|
GET_PCI_FDO_FIELD(BusFdoX, "ChildPdoList", next);
|
|
xdprintf(Indent,"");
|
|
dprintf( "Bus 0x%x (FDO Ext %08p)\n",
|
|
BaseBus,
|
|
InMemoryBusFdoX);
|
|
|
|
if (next == 0) {
|
|
xdprintf(Indent, "No devices have been enumerated on this bus.\n");
|
|
return TRUE;
|
|
}
|
|
|
|
Indent++;
|
|
do {
|
|
ULONG DeviceId, VendorId, DeviceNumber, FunctionNumber;
|
|
ULONG64 BridgeFdoExtension;
|
|
|
|
if (CheckControlC()) {
|
|
return FALSE;
|
|
}
|
|
if (PdoxFld(BaseClass,BaseClass)) {
|
|
xdprintf(Indent,"FAILED to read PDO Ext at ");
|
|
dprintf("%08p, cannot continue this bus.\n",
|
|
next
|
|
);
|
|
return TRUE;
|
|
}
|
|
|
|
PdoxFld(SubClass,SubClass);
|
|
PdoxFld(DeviceId,DeviceId);
|
|
PdoxFld(VendorId,VendorId);
|
|
PdoxFld(Slot.u.bits.DeviceNumber,DeviceNumber);
|
|
PdoxFld(Slot.u.bits.FunctionNumber,FunctionNumber);
|
|
|
|
DevExtPciFindClassCodes(BaseClass, SubClass, &bc, &sc);
|
|
|
|
xdprintf(Indent, "");
|
|
dprintf("%02x%02x %04x%04x (d=%x,%s f=%d) devext %08p %s/%s\n",
|
|
BaseClass,
|
|
SubClass,
|
|
DeviceId,
|
|
VendorId,
|
|
DeviceNumber,
|
|
(DeviceNumber > 9 ? "" : " "),
|
|
FunctionNumber,
|
|
next,
|
|
bc,
|
|
sc
|
|
);
|
|
|
|
#if 0
|
|
|
|
// removed, too talkative. plj.
|
|
|
|
vendor = DevExtPciFindVendorId(PdoX.VendorId);
|
|
if (vendor) {
|
|
xdprintf(Indent, " (%s)\n", vendor);
|
|
}
|
|
|
|
#endif
|
|
|
|
if (BaseClass == PCI_CLASS_BRIDGE_DEV && SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI) {
|
|
|
|
//
|
|
// Process child bus.
|
|
//
|
|
|
|
|
|
PdoxFld(BridgeFdoExtension,BridgeFdoExtension);
|
|
|
|
//
|
|
// Recurse.
|
|
//
|
|
|
|
if (pcitreeProcessBus(Indent, BridgeFdoExtension, TreeTop) == FALSE) {
|
|
|
|
//
|
|
// Error, exit.
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
PdoxFld(Next, next);
|
|
|
|
} while (next);
|
|
|
|
#undef PdoxFld
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DECLARE_API( pcitree )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps the pci tree. (Why is this here? Because the other PCI stuff
|
|
ended up in here because devnode was such a useful base).
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Signature;
|
|
ULONG64 TreeTop;
|
|
ULONG64 list;
|
|
ULONG64 addr;
|
|
ULONG indent = 0;
|
|
ULONG rootCount = 0;
|
|
|
|
addr = GetExpression("Pci!PciFdoExtensionListHead");
|
|
|
|
if (addr == 0) {
|
|
dprintf("Error retrieving address of PciFdoExtensionListHead\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!ReadPointer(addr, &list)) {
|
|
dprintf("Error reading PciFdoExtensionListHead (@%08p)\n", addr);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (list == 0) {
|
|
dprintf(
|
|
"PciFdoExtensionListHead forward pointer is NULL, list is empty\n"
|
|
);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
TreeTop = list;
|
|
|
|
do {
|
|
ULONG64 BusRootFdoExtension;
|
|
|
|
if (CheckControlC()) {
|
|
dprintf("User terminated with <control>C\n");
|
|
break;
|
|
}
|
|
|
|
if (GET_PCI_FDO_FIELD(list, "BusRootFdoExtension", BusRootFdoExtension)) {
|
|
dprintf(
|
|
"Error reading PCI FDO extension at %08p, quitting.\n",
|
|
list
|
|
);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (BusRootFdoExtension == list) {
|
|
|
|
//
|
|
// This is the FDO for a root bus.
|
|
//
|
|
|
|
rootCount++;
|
|
if (pcitreeProcessBus(0, list, TreeTop) == FALSE) {
|
|
|
|
//
|
|
// Asked not to continue;
|
|
//
|
|
|
|
dprintf("User terminated output.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
GET_PCI_FDO_FIELD(list, "List.Next", list);
|
|
|
|
} while (list != 0);
|
|
|
|
dprintf("Total PCI Root busses processed = %d\n", rootCount);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpDeviceCapabilities(
|
|
ULONG64 caps
|
|
) {
|
|
FIELD_INFO fields [] = {
|
|
{ "DeviceD1", "Spare1", 0, 0, 0, NULL},
|
|
{ "DeviceD2", "\tDeviceD2", 0, 0, 0, NULL},
|
|
{ "LockSupported", "\tLock", 0, 0, 0, NULL},
|
|
{ "EjectSupported","\tEject", 0, 0, 0, NULL},
|
|
{ "Removeable", "\tRemoveable", 0, 0, 0, NULL},
|
|
{ "DockDevice", "\nDock Device",0, 0, 0, NULL},
|
|
{ "UniqueID", "Unique ID", 0, 0, 0, NULL},
|
|
{ "SilentInstall", "\tSilent Install", 0, 0, 0, NULL},
|
|
{ "RawDeviceOK", "\tRawDeviceOK",0, 0, 0, NULL},
|
|
{ "Address", "\nAddress", 0, 0, 0, NULL},
|
|
{ "UINumber", "", 0, 0, 0, NULL},
|
|
{ "DeviceState", "\nDevice State : ", 0, DBG_DUMP_FIELD_ARRAY , 0, NULL},
|
|
{ "SystemWake", "\nSystemWake", 0, 0, 0, NULL},
|
|
{ "DeviceWake", "", 0, 0, 0, NULL},
|
|
};
|
|
UCHAR nm[] = "_DEVICE_CAPABILITIES";
|
|
SYM_DUMP_PARAM Sym = {
|
|
sizeof (SYM_DUMP_PARAM),
|
|
&nm[0],
|
|
DBG_DUMP_NO_OFFSET | DBG_DUMP_COMPACT_OUT,
|
|
caps,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
sizeof (fields) / sizeof (FIELD_INFO),
|
|
&fields[0],
|
|
};
|
|
dprintf ("PnP CAPS: \n");
|
|
|
|
Ioctl(IG_DUMP_SYMBOL_INFO, &Sym, sizeof (Sym));
|
|
|
|
}
|
|
|
|
#if 0
|
|
VOID
|
|
DumpDeviceCapabilities(
|
|
PDEVICE_CAPABILITIES caps
|
|
)
|
|
{
|
|
ULONG i,j,k;
|
|
ULONG bitmask;
|
|
|
|
PCHAR bits [] = {
|
|
"Spare1",
|
|
"Spare1",
|
|
"Lock",
|
|
"Eject",
|
|
"Removeable",
|
|
"Dock Device",
|
|
"Unique ID",
|
|
"Silent Install",
|
|
"RawDeviceOK"
|
|
};
|
|
|
|
bitmask = * (((PULONG) caps) + 1);
|
|
|
|
dprintf ("PnP CAPS: ");
|
|
for (i = 0, j = 1, k = 0; i < sizeof (bits); i++, j <<= 1) {
|
|
|
|
if (bitmask & j) {
|
|
|
|
if (k) {
|
|
dprintf("\n ");
|
|
}
|
|
k ^= 1;
|
|
|
|
dprintf(bits [i]);
|
|
}
|
|
}
|
|
dprintf("\n");
|
|
|
|
dprintf(" Address %x UINumber %x \n",
|
|
caps->Address,
|
|
caps->UINumber);
|
|
|
|
dprintf(" Device State [");
|
|
|
|
for (i = 0; i < PowerSystemMaximum; i ++) {
|
|
dprintf ("%02x ", (caps->DeviceState [i] & 0xFF));
|
|
}
|
|
dprintf("]\n");
|
|
|
|
dprintf(" System Wake %x Device Wake %x\n",
|
|
caps->SystemWake,
|
|
caps->DeviceWake);
|
|
dprintf("\n");
|
|
}
|
|
#endif
|
|
|
|
VOID
|
|
DumpTranslator(
|
|
IN DWORD Depth,
|
|
IN ULONG64 TranslatorAddr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps out the specified translator.
|
|
|
|
Arguments:
|
|
|
|
Depth - Supplies the print depth.
|
|
|
|
TranslatorAddr - Supplies the original address of the arbiter (on the target)
|
|
|
|
Translator - Supplies the arbiter
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
// TRANSLATOR_INTERFACE interface;
|
|
UCHAR buffer[256];
|
|
ULONG64 displacement;
|
|
ULONG ResourceType;
|
|
ULONG64 TranslatorInterface, TranslateResources, TranslateResourceRequirements;
|
|
|
|
if (GetFieldValue(TranslatorAddr,
|
|
"nt!_PI_RESOURCE_TRANSLATOR_ENTRY",
|
|
"ResourceType",
|
|
ResourceType)) {
|
|
xdprintf( Depth, "");
|
|
dprintf( "Could not read translator entry %08p\n",
|
|
TranslatorAddr
|
|
);
|
|
return;
|
|
}
|
|
|
|
GetFieldValue(TranslatorAddr,"nt!_PI_RESOURCE_TRANSLATOR_ENTRY","TranslatorInterface", TranslatorInterface);
|
|
xdprintf(Depth,
|
|
"%s Translator\n",
|
|
GetCmResourceTypeString((UCHAR)ResourceType)
|
|
);
|
|
|
|
if (GetFieldValue(TranslatorInterface,
|
|
"nt!_TRANSLATOR_INTERFACE",
|
|
"TranslateResources",
|
|
TranslateResources)) {
|
|
dprintf("Error reading TranslatorInterface %08p for TranslatorEntry at %08p\n",
|
|
TranslatorInterface,
|
|
TranslatorAddr);
|
|
|
|
return;
|
|
}
|
|
|
|
GetSymbol(TranslateResources, buffer, &displacement);
|
|
|
|
xdprintf(Depth+1, "Resources: %s", buffer, displacement);
|
|
|
|
if (displacement != 0) {
|
|
dprintf("+0x%1p\n", displacement);
|
|
} else {
|
|
dprintf("\n");
|
|
}
|
|
|
|
GetFieldValue(TranslatorInterface,"nt!_TRANSLATOR_INTERFACE",
|
|
"TranslateResourceRequirements",TranslateResourceRequirements);
|
|
GetSymbol(TranslateResourceRequirements, buffer, &displacement);
|
|
|
|
xdprintf(Depth+1, "Requirements: %s", buffer, displacement);
|
|
|
|
if (displacement != 0) {
|
|
dprintf("+0x%1p\n", displacement);
|
|
} else {
|
|
dprintf("\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
DumpTranslatorsForDevNode(
|
|
IN DWORD Depth,
|
|
IN ULONG64 DevNodeAddr,
|
|
IN DWORD Flags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps all the translators for the specified devnode. Recursively calls
|
|
itself on the specified devnode's children.
|
|
|
|
Arguments:
|
|
|
|
Depth - Supplies the print depth.
|
|
|
|
DevNodeAddr - Supplies the address of the devnode.
|
|
|
|
Flags - Supplies the type of arbiters to dump:
|
|
ARBITER_DUMP_IO
|
|
ARBITER_DUMP_MEMORY
|
|
ARBITER_DUMP_IRQ
|
|
ARBITER_DUMP_DMA
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG result;
|
|
ULONG64 nextTranslator;
|
|
ULONG64 translatorAddr;
|
|
BOOLEAN PrintedHeader = FALSE;
|
|
BOOLEAN continueDump = TRUE;
|
|
ULONG DeviceTranslatorListOffset, TransEntryOffset;
|
|
ULONG64 Child, Sibling;
|
|
|
|
if (GetFieldOffset("nt!_DEVICE_NODE", "DeviceTranslatorList", &DeviceTranslatorListOffset)) {
|
|
dprintf("_DEVICE_NODE type not found.\n");
|
|
return continueDump;
|
|
}
|
|
if (GetFieldOffset("nt!_PI_RESOURCE_TRANSLATOR_ENTRY", "DeviceTranslatorList", &TransEntryOffset)) {
|
|
dprintf("_PI_RESOURCE_TRANSLATOR_ENTRY type not found.\n");
|
|
return continueDump;
|
|
}
|
|
|
|
if (GetFieldValue(DevNodeAddr,
|
|
"nt!_DEVICE_NODE",
|
|
"DeviceTranslatorList.Flink",
|
|
nextTranslator)) {
|
|
xdprintf(Depth, ""); dprintf("%08p: Could not read device node\n", DevNodeAddr);
|
|
return continueDump;
|
|
}
|
|
|
|
// dprintf("Next %p, Devnode %p, Trans Off %x", nextTranslator, DevNodeAddr, DeviceTranslatorListOffset);
|
|
//
|
|
// Dump the list of translators
|
|
//
|
|
while (nextTranslator != DevNodeAddr+DeviceTranslatorListOffset) {
|
|
ULONG ResourceType;
|
|
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
break;
|
|
}
|
|
|
|
translatorAddr = (nextTranslator-TransEntryOffset);
|
|
if (GetFieldValue(translatorAddr,
|
|
"nt!_PI_RESOURCE_TRANSLATOR_ENTRY",
|
|
"ResourceType",
|
|
ResourceType)) {
|
|
xdprintf( Depth, "");
|
|
dprintf ("Could not read translator entry %08p for devnode %08p\n",
|
|
translatorAddr,
|
|
DevNodeAddr);
|
|
break;
|
|
}
|
|
|
|
if (!PrintedHeader) {
|
|
UNICODE_STRING64 u;
|
|
|
|
dprintf("\n");
|
|
xdprintf(Depth, ""); dprintf("DEVNODE %08p ", DevNodeAddr);
|
|
GetFieldValue(DevNodeAddr,"nt!_DEVICE_NODE","InstancePath.Buffer", u.Buffer);
|
|
GetFieldValue(DevNodeAddr,"nt!_DEVICE_NODE","InstancePath.Length", u.Length);
|
|
GetFieldValue(DevNodeAddr,"nt!_DEVICE_NODE","InstancePath.MaximumLength", u.MaximumLength);
|
|
if (u.Buffer != 0) {
|
|
dprintf("(");
|
|
DumpUnicode64(u);
|
|
dprintf(")");
|
|
}
|
|
dprintf("\n");
|
|
PrintedHeader = TRUE;
|
|
}
|
|
|
|
|
|
if (((ResourceType == CmResourceTypePort) && (Flags & ARBITER_DUMP_IO)) ||
|
|
((ResourceType == CmResourceTypeInterrupt) && (Flags & ARBITER_DUMP_IRQ)) ||
|
|
((ResourceType == CmResourceTypeMemory) && (Flags & ARBITER_DUMP_MEMORY)) ||
|
|
((ResourceType == CmResourceTypeDma) && (Flags & ARBITER_DUMP_DMA)) ||
|
|
((ResourceType == CmResourceTypeBusNumber) && (Flags & ARBITER_DUMP_BUS_NUMBER))) {
|
|
|
|
DumpTranslator( Depth+1, translatorAddr);
|
|
}
|
|
|
|
GetFieldValue(translatorAddr,"nt!_PI_RESOURCE_TRANSLATOR_ENTRY","DeviceTranslatorList.Flink",nextTranslator);
|
|
}
|
|
|
|
GetFieldValue(DevNodeAddr,"nt!_DEVICE_NODE","Sibling", Sibling);
|
|
GetFieldValue(DevNodeAddr,"nt!_DEVICE_NODE","Child", Child);
|
|
|
|
//
|
|
// Dump this devnode's children (if any)
|
|
//
|
|
if (continueDump && Child) {
|
|
continueDump = DumpTranslatorsForDevNode( Depth+1, Child, Flags);
|
|
}
|
|
|
|
//
|
|
// Dump this devnode's siblings (if any)
|
|
//
|
|
if (continueDump && Sibling) {
|
|
continueDump = DumpTranslatorsForDevNode( Depth, Sibling, Flags);
|
|
}
|
|
|
|
return continueDump;
|
|
}
|
|
|
|
|
|
DECLARE_API( translator )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps all the translators in the system
|
|
|
|
!translator [flags]
|
|
flags 1 - I/O port arbiters
|
|
2 - memory arbiters
|
|
4 - IRQ arbiters
|
|
8 - DMA arbiters
|
|
|
|
If no flags are specified, all translators are dumped.
|
|
|
|
Arguments:
|
|
|
|
args - optional flags specifying which arbiters to dump
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD Flags=0;
|
|
ULONG64 addr;
|
|
ULONG64 deviceNode;
|
|
|
|
if (!(Flags = (ULONG) GetExpression(args))) {
|
|
Flags = ARBITER_DUMP_ALL;
|
|
}
|
|
|
|
//
|
|
// Find the root devnode and dump its arbiters
|
|
//
|
|
|
|
addr = GetExpression( "nt!IopRootDeviceNode" );
|
|
if (addr == 0) {
|
|
dprintf("Error retrieving address of IopRootDeviceNode\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!ReadPointer(addr, &deviceNode)) {
|
|
dprintf("Error reading value of IopRootDeviceNode (%#010p)\n", addr);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
DumpTranslatorsForDevNode(0, deviceNode, Flags);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
#define RAW_RANGE_DUMP_STATS_ONLY 0x00000001
|
|
|
|
VOID
|
|
DumpRawRangeEntry(
|
|
IN DWORD Depth,
|
|
IN ULONG64 RangeEntry
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps out the specified RTLP_RANGE_LIST_ENTRY
|
|
|
|
Arguments:
|
|
|
|
Depth - Supplies the print depth.
|
|
|
|
RangeList - Supplies the address of the RTLP_RANGE_LIST_ENTRY
|
|
|
|
OwnerIsDevObj - Indicates that the owner field is a pointer to a DEVICE_OBJECT
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG PublicFlags;
|
|
ULONG64 UserData, Owner;
|
|
ULONG64 Start, End;
|
|
|
|
GetFieldValue(RangeEntry, "nt!_RTLP_RANGE_LIST_ENTRY", "Start", Start);
|
|
GetFieldValue(RangeEntry, "nt!_RTLP_RANGE_LIST_ENTRY", "End", End);
|
|
GetFieldValue(RangeEntry, "nt!_RTLP_RANGE_LIST_ENTRY", "PublicFlags", PublicFlags);
|
|
GetFieldValue(RangeEntry, "nt!_RTLP_RANGE_LIST_ENTRY", "Allocated.UserData", UserData);
|
|
GetFieldValue(RangeEntry, "nt!_RTLP_RANGE_LIST_ENTRY", "Allocated.Owner", Owner);
|
|
|
|
xdprintf(Depth, "");
|
|
dprintf ("%016I64x - %016I64x %c%c %08p %08p\n",
|
|
Start,
|
|
End,
|
|
PublicFlags & RTL_RANGE_SHARED ? 'S' : ' ',
|
|
PublicFlags & RTL_RANGE_CONFLICT ? 'C' : ' ',
|
|
UserData,
|
|
Owner
|
|
);
|
|
}
|
|
|
|
BOOLEAN
|
|
DumpRawRangeList(
|
|
IN DWORD Depth,
|
|
IN ULONG64 RangeListHead,
|
|
IN ULONG Flags,
|
|
IN PULONG MergedCount OPTIONAL,
|
|
IN PULONG EntryCount
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps out the specified RTL_RANGE_LIST
|
|
|
|
Arguments:
|
|
|
|
Depth - Supplies the print depth.
|
|
|
|
RangeListHead - Supplies the address of the LIST_ENTRY containing the RTLP_RANGE_LIST_ENTRYs
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 EntryAddr;
|
|
ULONG64 ListEntry;
|
|
ULONG ListEntryOffset;
|
|
BOOLEAN continueDump = TRUE;
|
|
|
|
//
|
|
// Read the range list
|
|
//
|
|
if (GetFieldValue(RangeListHead, "nt!_LIST_ENTRY", "Flink", ListEntry)) {
|
|
dprintf("Error reading RangeList %08p\n", RangeListHead);
|
|
return continueDump;
|
|
}
|
|
|
|
if (ListEntry == RangeListHead) {
|
|
xdprintf(Depth, "< none >\n");
|
|
return continueDump;
|
|
}
|
|
GetFieldOffset("nt!RTLP_RANGE_LIST_ENTRY", "ListEntry", &ListEntryOffset);
|
|
|
|
while (ListEntry != RangeListHead) {
|
|
ULONG PrivateFlags;
|
|
ULONG64 Start, End;
|
|
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
break;
|
|
}
|
|
|
|
EntryAddr = ( ListEntry - ListEntryOffset);
|
|
|
|
if (GetFieldValue(EntryAddr, "nt!_RTLP_RANGE_LIST_ENTRY",
|
|
"PrivateFlags", PrivateFlags)) {
|
|
dprintf("Error reading RangeEntry %08p from RangeList %08p\n",
|
|
EntryAddr,
|
|
RangeListHead);
|
|
return continueDump;
|
|
}
|
|
|
|
(*EntryCount)++;
|
|
|
|
if (PrivateFlags & RTLP_RANGE_LIST_ENTRY_MERGED) {
|
|
ULONG MergedOffset;
|
|
|
|
//
|
|
// This is a merged range list, call ourselves recursively
|
|
//
|
|
if (MergedCount) {
|
|
(*MergedCount)++;
|
|
}
|
|
if (!(Flags & RAW_RANGE_DUMP_STATS_ONLY)) {
|
|
GetFieldValue(EntryAddr, "nt!_RTLP_RANGE_LIST_ENTRY", "Start", Start);
|
|
GetFieldValue(EntryAddr, "nt!_RTLP_RANGE_LIST_ENTRY", "End", End);
|
|
xdprintf(Depth, "Merged Range - %I64x-%I64x\n", Start, End);
|
|
}
|
|
|
|
GetFieldOffset("nt!_RTLP_RANGE_LIST_ENTRY", "Merged.ListHead", &MergedOffset);
|
|
continueDump = DumpRawRangeList( Depth+1,
|
|
EntryAddr + MergedOffset,
|
|
Flags,
|
|
MergedCount,
|
|
EntryCount);
|
|
|
|
if (!continueDump) {
|
|
break;
|
|
}
|
|
|
|
} else if (!(Flags & RAW_RANGE_DUMP_STATS_ONLY)) {
|
|
DumpRawRangeEntry(Depth, EntryAddr);
|
|
}
|
|
|
|
GetFieldValue(EntryAddr, "nt!_RTLP_RANGE_LIST_ENTRY", "ListEntry.Flink", ListEntry);
|
|
}
|
|
|
|
return continueDump;
|
|
}
|
|
|
|
DECLARE_API( rawrange )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps an RTL_RANGE_LIST
|
|
|
|
Arguments:
|
|
|
|
args - specifies the address of the RTL_RANGE_LIST
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
ULONG64 RangeList=0;
|
|
ULONG mergedCount = 0, entryCount = 0, flags=0, Offset;
|
|
|
|
if (GetExpressionEx(args, &RangeList, &args)) {
|
|
flags = (ULONG) GetExpression(args);
|
|
}
|
|
|
|
GetFieldOffset("nt!_RTLP_RANGE_LIST_ENTRY", "ListHead", &Offset);
|
|
DumpRawRangeList(0, RangeList + Offset, flags, &mergedCount, &entryCount);
|
|
|
|
dprintf("Stats\nMerged = %i\nEntries = %i\n", mergedCount, entryCount);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpIoResourceDescriptor(
|
|
IN ULONG Depth,
|
|
IN ULONG64 Descriptor
|
|
)
|
|
{
|
|
ULONG64 Q1, Q2;
|
|
ULONG Option, Type, ShareDisposition, Flags, V1, V2, V3, Data[3];
|
|
|
|
#define Desc(F,V) GetFieldValue(Descriptor, "nt!IO_RESOURCE_LIST", #F, V)
|
|
|
|
Desc(Option,Option); Desc(Type,Type);
|
|
Desc(ShareDisposition,ShareDisposition);
|
|
Desc(Flags,Flags);
|
|
|
|
DumpResourceDescriptorHeader(Depth,
|
|
0,
|
|
(UCHAR) Option,
|
|
(UCHAR) Type,
|
|
(UCHAR) ShareDisposition,
|
|
(USHORT) Flags);
|
|
|
|
Depth++;
|
|
|
|
switch (Type) {
|
|
case CmResourceTypeBusNumber:
|
|
|
|
Desc(u.BusNumber.MinBusNumber, V1);
|
|
Desc(u.BusNumber.MaxBusNumber, V2);
|
|
Desc(u.BusNumber.Length, V3);
|
|
xdprintf(Depth, "0x%x - 0x%x for length 0x%x\n",
|
|
V1, V2, V3);
|
|
break;
|
|
|
|
case CmResourceTypePort:
|
|
case CmResourceTypeMemory:
|
|
Desc(u.Generic.Length, V1);
|
|
Desc(u.Generic.Alignment, V2);
|
|
Desc(u.Port.MinimumAddress.QuadPart, Q1);
|
|
Desc(u.Port.MaximumAddress.QuadPart, Q2);
|
|
xdprintf(Depth, "%#08lx byte range with alignment %#08lx\n", V1, V2);
|
|
xdprintf(Depth, "%I64x - %#I64x\n", Q1, Q2);
|
|
|
|
case CmResourceTypeInterrupt:
|
|
|
|
Desc(u.Interrupt.MinimumVector,V1);
|
|
Desc(u.Interrupt.MaximumVector,V2);
|
|
xdprintf(Depth, "0x%x - 0x%x\n", V1,V2);
|
|
break;
|
|
|
|
case CmResourceTypeDma:
|
|
|
|
Desc(u.Dma.MinimumChannel,V1);
|
|
Desc(u.Dma.MaximumChannel,V2);
|
|
xdprintf(Depth, "0x%x - 0x%x\n",V1, V2);
|
|
break;
|
|
|
|
|
|
default:
|
|
Desc(u.DevicePrivate.Data, Data);
|
|
xdprintf(Depth,
|
|
"Data: : 0x%x 0x%x 0x%x\n",
|
|
Data[0],
|
|
Data[1],
|
|
Data[2]);
|
|
break;
|
|
}
|
|
#undef Desc
|
|
}
|
|
|
|
DECLARE_API( ioresdes )
|
|
{
|
|
ULONG64 descriptorAddr;
|
|
|
|
descriptorAddr = GetExpression(args);
|
|
|
|
DumpIoResourceDescriptor(0, descriptorAddr);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
DECLARE_API(pnpevent)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump a device object.
|
|
|
|
Arguments:
|
|
|
|
args - the location of the device object to dump.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 deviceEventListAddr;
|
|
ULONG64 listHead;
|
|
ULONG64 deviceEvent = 0;
|
|
ULONG verbose = 0;
|
|
ULONG64 address;
|
|
ULONG offset;
|
|
BOOL followLinks;
|
|
ULONG64 status = 0, flink = 0, blink = 0;
|
|
ULONG eventQ_Header_SignalState = 0, lk_Event_Hdr_SignalState = 0;
|
|
|
|
|
|
address = GetExpression( "nt!PpDeviceEventList" );
|
|
|
|
if (address == 0) {
|
|
dprintf("Error retrieving address of PpDeviceEventList\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!ReadPointer(address, &deviceEventListAddr)) {
|
|
dprintf("Error reading value of PpDeviceEventList (%#010lx)\n", address);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (GetFieldOffset("nt!_PNP_DEVICE_EVENT_LIST", "List", &offset)) {
|
|
dprintf("Cannot find _PNP_DEVICE_EVENT_LIST.List type.\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
listHead = deviceEventListAddr + offset;
|
|
|
|
dprintf("\n********************************************************************************\n");
|
|
dprintf("Dumping PnP DeviceEvent Queue @ 0x%08p\n", deviceEventListAddr);
|
|
dprintf("********************************************************************************\n\n");
|
|
|
|
if (GetFieldValue(deviceEventListAddr, "nt!_PNP_DEVICE_EVENT_LIST", "Status", status)) {
|
|
dprintf("Error reading PpDeviceEventList->Status (%#010p)\n", deviceEventListAddr);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (GetFieldValue(deviceEventListAddr, "nt!_PNP_DEVICE_EVENT_LIST", "EventQueueMutex.Header.SignalState", eventQ_Header_SignalState)) {
|
|
dprintf("Error reading PpDeviceEventList->EventQueueMutex.Header.SignalState (%#010p)\n", deviceEventListAddr);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (GetFieldValue(deviceEventListAddr, "nt!_PNP_DEVICE_EVENT_LIST", "Lock.Event.Header.SignalState", lk_Event_Hdr_SignalState)) {
|
|
dprintf("Error reading PpDeviceEventList->Lock.Event.Header.SignalState (%#010p)\n", deviceEventListAddr);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (GetFieldValue(deviceEventListAddr, "nt!_PNP_DEVICE_EVENT_LIST", "List.Flink", flink)) {
|
|
dprintf("Error reading PpDeviceEventList->List.Flink (%#010p)\n", deviceEventListAddr);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (GetFieldValue(deviceEventListAddr, "nt!_PNP_DEVICE_EVENT_LIST", "List.Blink", blink)) {
|
|
dprintf("Error reading PpDeviceEventList->List.Blink (%#010p)\n", deviceEventListAddr);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
dprintf(" Status = 0x%08I64X, EventQueueMutex is %sheld, Lock is %sheld\n",
|
|
status,
|
|
eventQ_Header_SignalState ? "not " : "",
|
|
lk_Event_Hdr_SignalState ? "not " : "");
|
|
|
|
dprintf(" List = 0x%08p, 0x%08p\n", flink, blink);
|
|
|
|
if (GetExpressionEx(args, &deviceEvent, &args)) {
|
|
verbose = (ULONG) GetExpression(args);
|
|
}
|
|
|
|
if (deviceEvent == 0) {
|
|
|
|
ULONG listEntryOffset = 0;
|
|
|
|
if (flink == listHead) {
|
|
dprintf("Event list is empty\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Now get addtess of PNP_DEVICE_EVENT_ENTRY
|
|
//
|
|
if (GetFieldOffset("nt!_PNP_DEVICE_EVENT_ENTRY", "ListEntry", &offset)) {
|
|
dprintf("Cannot find _PNP_DEVICE_EVENT_ENTRY type.\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
deviceEvent = flink - offset; // CONTAINING_RECORD(deviceEventList.List.Flink, PNP_DEVICE_EVENT_ENTRY, ListEntry);
|
|
|
|
followLinks = TRUE;
|
|
|
|
} else {
|
|
|
|
followLinks = FALSE;
|
|
}
|
|
|
|
DumpDeviceEventEntry( deviceEvent, listHead, followLinks );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
BOOLEAN
|
|
DumpDeviceEventEntry(
|
|
ULONG64 DeviceEvent,
|
|
ULONG64 ListHead,
|
|
BOOL FollowLinks
|
|
)
|
|
{
|
|
BOOLEAN continueDump = TRUE;
|
|
ULONG64 flink=0, blink=0, argument=0, callerEvent=0, callback=0, context=0;
|
|
ULONG64 vetoType=0, vetoName=0;
|
|
ULONG dataSize=0;
|
|
ULONG offset;
|
|
ULONG64 dataAddress;
|
|
|
|
dprintf("\nDumping DeviceEventEntry @ 0x%08p\n", DeviceEvent);
|
|
|
|
if (GetFieldValue(DeviceEvent, "nt!_PNP_DEVICE_EVENT_ENTRY", "ListEntry.Flink", flink)) {
|
|
dprintf("Error reading DeviceEvent->ListEntry.Flink (%#010p)\n", DeviceEvent);
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetFieldValue(DeviceEvent, "nt!_PNP_DEVICE_EVENT_ENTRY", "ListEntry.Blink", blink)) {
|
|
dprintf("Error reading DeviceEvent->ListEntry.Blink (%#010p)\n", DeviceEvent);
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetFieldValue(DeviceEvent, "nt!_PNP_DEVICE_EVENT_ENTRY", "CallerEvent", callerEvent)) {
|
|
dprintf("Error reading DeviceEvent->CallerEvent (%#010p)\n", DeviceEvent);
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetFieldValue(DeviceEvent, "nt!_PNP_DEVICE_EVENT_ENTRY", "Callback", callback)) {
|
|
dprintf("Error reading DeviceEvent->Callback (%#010p)\n", DeviceEvent);
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetFieldValue(DeviceEvent, "nt!_PNP_DEVICE_EVENT_ENTRY", "Context", context)) {
|
|
dprintf("Error reading DeviceEvent->Context (%#010p)\n", DeviceEvent);
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetFieldValue(DeviceEvent, "nt!_PNP_DEVICE_EVENT_ENTRY", "VetoType", vetoType)) {
|
|
dprintf("Error reading DeviceEvent->VetoType (%#010p)\n", DeviceEvent);
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetFieldValue(DeviceEvent, "nt!_PNP_DEVICE_EVENT_ENTRY", "VetoName", vetoName)) {
|
|
dprintf("Error reading DeviceEvent->VetoName (%#010p)\n", DeviceEvent);
|
|
return FALSE;
|
|
}
|
|
|
|
dprintf(" ListEntry = 0x%08p, 0x%08p, Argument = 0x%08I64x\n",
|
|
flink, blink, argument);
|
|
|
|
dprintf(" CallerEvent = 0x%08p, Callback = 0x%08p, Context = 0x%08p\n",
|
|
callerEvent, callback, context);
|
|
|
|
dprintf(" VetoType = 0x%08p, VetoName = 0x%08p\n",
|
|
vetoType, vetoName);
|
|
|
|
if (GetFieldOffset("nt!_PNP_DEVICE_EVENT_ENTRY", "Data", &offset)) {
|
|
dprintf("Cannot find offset of Data in _PNP_DEVICE_EVENT_ENTRY type.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
dataAddress = DeviceEvent + offset;
|
|
|
|
if (GetFieldValue(DeviceEvent, "nt!_PNP_DEVICE_EVENT_ENTRY", "Data.TotalSize", dataSize)) {
|
|
dprintf("Error reading DeviceEvent->Data.TotalSize (%#010p)\n", DeviceEvent);
|
|
return FALSE;
|
|
}
|
|
|
|
DumpPlugPlayEventBlock( dataAddress, dataSize );
|
|
|
|
if (FollowLinks && flink != ListHead) {
|
|
if (CheckControlC()) {
|
|
continueDump = FALSE;
|
|
} else {
|
|
|
|
if (GetFieldOffset("nt!_PNP_DEVICE_EVENT_ENTRY", "ListEntry", &offset)) {
|
|
dprintf("Cannot find offset of ListEntry in _PNP_DEVICE_EVENT_ENTRY type.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
continueDump = DumpDeviceEventEntry(flink - offset,
|
|
ListHead,
|
|
TRUE);
|
|
}
|
|
}
|
|
|
|
return continueDump;
|
|
}
|
|
|
|
PUCHAR DevNodeStateNames[] = {
|
|
"DeviceNodeUnspecified",
|
|
"DeviceNodeUninitialized",
|
|
"DeviceNodeInitialized",
|
|
"DeviceNodeDriversAdded",
|
|
"DeviceNodeResourcesAssigned",
|
|
"DeviceNodeStartPending",
|
|
"DeviceNodeStartCompletion",
|
|
"DeviceNodeStartPostWork",
|
|
"DeviceNodeStarted",
|
|
"DeviceNodeQueryStopped",
|
|
"DeviceNodeStopped",
|
|
"DeviceNodeRestartCompletion",
|
|
"DeviceNodeEnumeratePending",
|
|
"DeviceNodeEnumerateCompletion",
|
|
"DeviceNodeAwaitingQueuedDeletion",
|
|
"DeviceNodeAwaitingQueuedRemoval",
|
|
"DeviceNodeQueryRemoved",
|
|
"DeviceNodeRemovePendingCloses",
|
|
"DeviceNodeRemoved",
|
|
"DeviceNodeDeletePendingCloses",
|
|
"DeviceNodeDeleted"
|
|
};
|
|
|
|
#define DEVNODE_STATE_NAMES_SIZE (sizeof(DevNodeStateNames) / sizeof(DevNodeStateNames[0]))
|
|
|
|
|
|
VOID
|
|
PrintDevNodeState(
|
|
IN ULONG Depth,
|
|
IN PUCHAR Field,
|
|
IN ULONG State
|
|
)
|
|
{
|
|
UCHAR *Description;
|
|
ULONG stateIndex;
|
|
|
|
stateIndex = State - 0x300; //DeviceNodeUnspecified;
|
|
|
|
if (stateIndex < DEVNODE_STATE_NAMES_SIZE) {
|
|
|
|
Description = DevNodeStateNames[stateIndex];
|
|
} else {
|
|
Description = "Unknown State";
|
|
}
|
|
|
|
xdprintf(Depth, "%s = %s (0x%x)\n", Field, Description, State);
|
|
}
|
|
|
|
VOID
|
|
DumpMultiSz(
|
|
IN PWCHAR MultiSz
|
|
)
|
|
{
|
|
PWCHAR p = MultiSz;
|
|
ULONG length;
|
|
|
|
while (*p) {
|
|
length = wcslen(p);
|
|
dprintf(" %S\n", p);
|
|
p += length + 1;
|
|
}
|
|
}
|
|
struct {
|
|
CONST GUID *Guid;
|
|
PCHAR Name;
|
|
} EventGuidTable[] = {
|
|
// From wdmguid.h
|
|
{ &GUID_HWPROFILE_QUERY_CHANGE, "GUID_HWPROFILE_QUERY_CHANGE" },
|
|
{ &GUID_HWPROFILE_CHANGE_CANCELLED, "GUID_HWPROFILE_CHANGE_CANCELLED" },
|
|
{ &GUID_HWPROFILE_CHANGE_COMPLETE, "GUID_HWPROFILE_CHANGE_COMPLETE" },
|
|
{ &GUID_DEVICE_INTERFACE_ARRIVAL, "GUID_DEVICE_INTERFACE_ARRIVAL" },
|
|
{ &GUID_DEVICE_INTERFACE_REMOVAL, "GUID_DEVICE_INTERFACE_REMOVAL" },
|
|
{ &GUID_TARGET_DEVICE_QUERY_REMOVE, "GUID_TARGET_DEVICE_QUERY_REMOVE" },
|
|
{ &GUID_TARGET_DEVICE_REMOVE_CANCELLED, "GUID_TARGET_DEVICE_REMOVE_CANCELLED" },
|
|
{ &GUID_TARGET_DEVICE_REMOVE_COMPLETE, "GUID_TARGET_DEVICE_REMOVE_COMPLETE" },
|
|
{ &GUID_PNP_CUSTOM_NOTIFICATION, "GUID_PNP_CUSTOM_NOTIFICATION" },
|
|
{ &GUID_PNP_POWER_NOTIFICATION, "GUID_PNP_POWER_NOTIFICATION" },
|
|
// From pnpmgr.h
|
|
{ &GUID_DEVICE_ARRIVAL, "GUID_DEVICE_ARRIVAL" },
|
|
{ &GUID_DEVICE_ENUMERATED, "GUID_DEVICE_ENUMERATED" },
|
|
{ &GUID_DEVICE_ENUMERATE_REQUEST, "GUID_DEVICE_ENUMERATE_REQUEST" },
|
|
{ &GUID_DEVICE_START_REQUEST, "GUID_DEVICE_START_REQUEST" },
|
|
{ &GUID_DEVICE_REMOVE_PENDING, "GUID_DEVICE_REMOVE_PENDING" },
|
|
{ &GUID_DEVICE_QUERY_AND_REMOVE, "GUID_DEVICE_QUERY_AND_REMOVE" },
|
|
{ &GUID_DEVICE_EJECT, "GUID_DEVICE_EJECT" },
|
|
{ &GUID_DEVICE_NOOP, "GUID_DEVICE_NOOP" },
|
|
{ &GUID_DEVICE_SURPRISE_REMOVAL, "GUID_DEVICE_SURPRISE_REMOVAL" },
|
|
{ &GUID_DRIVER_BLOCKED, "GUID_DRIVER_BLOCKED" },
|
|
};
|
|
#define EVENT_GUID_TABLE_SIZE (sizeof(EventGuidTable) / sizeof(EventGuidTable[0]))
|
|
|
|
VOID
|
|
LookupGuid(
|
|
IN CONST GUID *Guid,
|
|
IN OUT PCHAR String,
|
|
IN ULONG StringLength
|
|
)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < EVENT_GUID_TABLE_SIZE; i++) {
|
|
if (memcmp(Guid, EventGuidTable[i].Guid, sizeof(Guid)) == 0) {
|
|
strncpy(String, EventGuidTable[i].Name, StringLength - 1);
|
|
String[StringLength - 1] = '\0';
|
|
return;
|
|
}
|
|
}
|
|
|
|
_snprintf( String, StringLength, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
|
Guid->Data1,
|
|
Guid->Data2,
|
|
Guid->Data3,
|
|
Guid->Data4[0],
|
|
Guid->Data4[1],
|
|
Guid->Data4[2],
|
|
Guid->Data4[3],
|
|
Guid->Data4[4],
|
|
Guid->Data4[5],
|
|
Guid->Data4[6],
|
|
Guid->Data4[7] );
|
|
}
|
|
|
|
PUCHAR EventCategoryStrings[] = {
|
|
"HardwareProfileChangeEvent",
|
|
"TargetDeviceChangeEvent",
|
|
"DeviceClassChangeEvent",
|
|
"CustomDeviceEvent",
|
|
"DeviceInstallEvent",
|
|
"DeviceArrivalEvent",
|
|
"PowerEvent",
|
|
"VetoEvent",
|
|
"BlockedDriverEvent"
|
|
};
|
|
|
|
#define N_EVENT_CATEGORIES (sizeof(EventCategoryStrings) / sizeof(EventCategoryStrings[0]))
|
|
|
|
VOID
|
|
DumpPlugPlayEventBlock(
|
|
ULONG64 PlugPlayEventBlock,
|
|
ULONG Size
|
|
)
|
|
{
|
|
GUID EventGuid;
|
|
UCHAR guidString[256];
|
|
UCHAR PnpEventTyp[] = "nt!PLUGPLAY_EVENT_BLOCK";
|
|
char categoryString[80];
|
|
ULONG64 Result=0, DeviceObject=0;
|
|
ULONG EventCategory=0, TotalSize=0, Flags=0;
|
|
ULONG64 PtrVal=0;
|
|
ULONG offset;
|
|
PUCHAR buffer;
|
|
ULONG powerData;
|
|
|
|
dprintf("\n Dumping PlugPlayEventBlock @ 0x%08X\n", PlugPlayEventBlock);
|
|
|
|
if (GetFieldValue(PlugPlayEventBlock, PnpEventTyp, "EventGuid", EventGuid)) {
|
|
dprintf("Error reading PlugPlayEventBlock (%#010p)\n", PlugPlayEventBlock);
|
|
return;
|
|
}
|
|
|
|
LookupGuid(&EventGuid, guidString, sizeof(guidString));
|
|
|
|
GetFieldValue(PlugPlayEventBlock, PnpEventTyp, "EventCategory", EventCategory);
|
|
GetFieldValue(PlugPlayEventBlock, PnpEventTyp, "Result", Result );
|
|
GetFieldValue(PlugPlayEventBlock, PnpEventTyp, "Flags", Flags );
|
|
GetFieldValue(PlugPlayEventBlock, PnpEventTyp, "TotalSize", TotalSize );
|
|
GetFieldValue(PlugPlayEventBlock, PnpEventTyp, "DeviceObject", DeviceObject );
|
|
|
|
if ( EventCategory > N_EVENT_CATEGORIES) {
|
|
sprintf(categoryString, "Unknown category (%d)", EventCategory);
|
|
} else {
|
|
if (StringCchCopy(categoryString, sizeof(categoryString), EventCategoryStrings[ EventCategory ]) != S_OK)
|
|
{
|
|
categoryString[0] = 0;
|
|
}
|
|
}
|
|
|
|
dprintf(" EventGuid = %s\n Category = %s\n",
|
|
guidString, categoryString);
|
|
dprintf(" Result = 0x%08p, Flags = 0x%08X, TotalSize = %d\n",
|
|
Result, Flags, TotalSize );
|
|
|
|
dprintf(" DeviceObject = 0x%08p\n", DeviceObject);
|
|
|
|
switch (EventCategory) {
|
|
case HardwareProfileChangeEvent:
|
|
GetFieldValue(PlugPlayEventBlock, PnpEventTyp, "u.ProfileNotification.Notification", PtrVal);
|
|
dprintf( " Notification = 0x%08p\n", PtrVal );
|
|
break;
|
|
|
|
case DeviceArrivalEvent:
|
|
break;
|
|
|
|
case TargetDeviceChangeEvent:
|
|
dprintf( " DeviceIds:\n");
|
|
|
|
GetFieldOffset(PnpEventTyp, "u.TargetDevice.DeviceIds", &offset);
|
|
buffer = LocalAlloc(LPTR, Size - offset);
|
|
xReadMemory(PlugPlayEventBlock + offset, buffer, Size - offset);
|
|
DumpMultiSz( (PWCHAR)buffer );
|
|
LocalFree(buffer);
|
|
break;
|
|
|
|
case DeviceClassChangeEvent:
|
|
#if DEBUGGER_GETS_FIXED
|
|
GetFieldValue(PlugPlayEventBlock, PnpEventTyp, "u.DeviceClass.ClassGuid", EventGuid);
|
|
#else
|
|
GetFieldOffset(PnpEventTyp, "u.DeviceClass.ClassGuid", &offset);
|
|
xReadMemory(PlugPlayEventBlock + offset, &EventGuid, sizeof(EventGuid));
|
|
#endif
|
|
LookupGuid(&EventGuid, guidString, sizeof(guidString));
|
|
dprintf( " ClassGuid = %s\n", guidString );
|
|
|
|
GetFieldOffset(PnpEventTyp, "u.DeviceClass.SymbolicLinkName", &offset);
|
|
buffer = LocalAlloc(LPTR, Size - offset);
|
|
xReadMemory(PlugPlayEventBlock + offset, buffer, Size - offset);
|
|
dprintf( " SymbolicLinkName = %S\n", (PWCHAR) buffer );
|
|
LocalFree(buffer);
|
|
|
|
break;
|
|
|
|
case CustomDeviceEvent:
|
|
GetFieldValue(PlugPlayEventBlock, PnpEventTyp, "u.CustomNotification.NotificationStructure", PtrVal);
|
|
dprintf( " NotificationStructure = 0x%08p\n DeviceIds:\n",
|
|
PtrVal);
|
|
|
|
GetFieldOffset(PnpEventTyp, "u.CustomNotification.DeviceIds", &offset);
|
|
buffer = LocalAlloc(LPTR, Size - offset);
|
|
xReadMemory(PlugPlayEventBlock + offset, buffer, Size - offset);
|
|
DumpMultiSz( (PWCHAR) buffer );
|
|
LocalFree(buffer);
|
|
break;
|
|
|
|
case DeviceInstallEvent:
|
|
GetFieldOffset(PnpEventTyp, "u.InstallDevice.DeviceId", &offset);
|
|
buffer = LocalAlloc(LPTR, Size - offset);
|
|
xReadMemory(PlugPlayEventBlock + offset, buffer, Size - offset);
|
|
dprintf( " DeviceId = %S\n", (PWCHAR) buffer );
|
|
LocalFree(buffer);
|
|
break;
|
|
|
|
case PowerEvent:
|
|
GetFieldValue(PlugPlayEventBlock, PnpEventTyp, "u.PowerNotification.NotificationCode", powerData);
|
|
dprintf( " NotificationCode = 0x%08X\n", powerData );
|
|
GetFieldValue(PlugPlayEventBlock, PnpEventTyp, "u.PowerNotification.NotificationData", powerData);
|
|
dprintf( " NotificationData = 0x%08X\n", powerData );
|
|
break;
|
|
|
|
case BlockedDriverEvent:
|
|
#if DEBUGGER_GETS_FIXED
|
|
GetFieldValue(PlugPlayEventBlock, PnpEventTyp, "u.BlockedDriverNotification.BlockedDriverGuid", EventGuid);
|
|
#else
|
|
GetFieldOffset(PnpEventTyp, "u.BlockedDriverNotification.BlockedDriverGuid", &offset);
|
|
xReadMemory(PlugPlayEventBlock + offset, &EventGuid, sizeof(EventGuid));
|
|
#endif
|
|
LookupGuid(&EventGuid, guidString, sizeof(guidString));
|
|
dprintf( " BlockedDriverGuid = %s\n", guidString );
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
DECLARE_API( rellist )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump a device object.
|
|
|
|
Arguments:
|
|
|
|
args - the location of the device object to dump.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 relationList=0;
|
|
ULONG verbose=0;
|
|
|
|
if (GetExpressionEx(args, &relationList, &args)) {
|
|
verbose = (ULONG) GetExpression(args);
|
|
}
|
|
|
|
DumpRelationsList( relationList,
|
|
(BOOLEAN) (verbose & DUMP_CM_RES),
|
|
(BOOLEAN) (verbose & DUMP_CM_RES_REQ_LIST),
|
|
(BOOLEAN) (verbose & DUMP_CM_RES_TRANS)
|
|
);
|
|
return S_OK;
|
|
}
|
|
|
|
DECLARE_API( lbt )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump the legacy bus information table.
|
|
|
|
Arguments:
|
|
|
|
args - none.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
CHAR buffer[256];
|
|
ULONG size, deviceNodeOffset;
|
|
ULONG64 deviceNode;
|
|
ULONG64 listHeadAddr, legacyBusEntryAddr;
|
|
ULONG64 head_Flink, head_Blink, link_Flink;
|
|
USHORT instancePath_Len, instancePath_Max;
|
|
ULONG busNumber;
|
|
ULONG64 instancePath_Buff, interfaceType;
|
|
CHAR deviceNodeType[] ="nt!_DEVICE_NODE";
|
|
CHAR listEntryType[] = "nt!_LIST_ENTRY" ;
|
|
INTERFACE_TYPE Iface;
|
|
|
|
if ((size = GetTypeSize(listEntryType)) == 0) {
|
|
|
|
dprintf("Failed to get the size of %s\n", listEntryType);
|
|
return E_INVALIDARG;
|
|
}
|
|
if (GetFieldOffset(deviceNodeType, "LegacyBusListEntry.Flink", &deviceNodeOffset)) {
|
|
|
|
dprintf("Failed to get the offset of LegacyBusListEntry from %s\n", deviceNodeType);
|
|
return E_INVALIDARG;
|
|
}
|
|
dprintf("Legacy Bus Information Table...\n");
|
|
for (Iface = Internal; Iface < MaximumInterfaceType; Iface++) {
|
|
|
|
sprintf(buffer, "nt!IopLegacyBusInformationTable + %x", Iface * size);
|
|
if ((listHeadAddr = GetExpression(buffer)) == 0) {
|
|
|
|
dprintf("Error retrieving address of bus number list for interface %d\n", Iface);
|
|
continue;
|
|
}
|
|
if (GetFieldValue(listHeadAddr, listEntryType, "Flink", head_Flink) ||
|
|
GetFieldValue(listHeadAddr, listEntryType, "Blink", head_Blink)) {
|
|
|
|
dprintf("Error reading value of bus number list head (0x%08p) for interface %d\n", listHeadAddr, Iface);
|
|
continue;
|
|
}
|
|
if (head_Flink == listHeadAddr) {
|
|
|
|
continue;
|
|
}
|
|
for ( legacyBusEntryAddr = head_Flink;
|
|
legacyBusEntryAddr != listHeadAddr;
|
|
legacyBusEntryAddr = link_Flink) {
|
|
|
|
deviceNode = legacyBusEntryAddr - deviceNodeOffset;
|
|
if (GetFieldValue(deviceNode, deviceNodeType, "BusNumber", busNumber)) {
|
|
|
|
dprintf("Error reading BusNumber from (0x%08p)\n", deviceNode);
|
|
break;
|
|
}
|
|
if (GetFieldValue(deviceNode, deviceNodeType, "InstancePath.Length", instancePath_Len)) {
|
|
|
|
dprintf("Error reading InstancePath.Length from (0x%08p)\n", deviceNode);
|
|
break;
|
|
}
|
|
if (GetFieldValue(deviceNode, deviceNodeType, "InstancePath.MaximumLength", instancePath_Max)) {
|
|
|
|
dprintf("Error reading InstancePath.MaximumLength from (0x%08p)\n", deviceNode);
|
|
break;
|
|
}
|
|
if (GetFieldValue(deviceNode, deviceNodeType, "InstancePath.Buffer", instancePath_Buff)) {
|
|
|
|
dprintf("Error reading InstancePath.Buffer from (0x%08p)\n", deviceNode);
|
|
break;
|
|
}
|
|
if (instancePath_Buff != 0) {
|
|
|
|
UNICODE_STRING64 v;
|
|
|
|
switch (Iface) {
|
|
|
|
case InterfaceTypeUndefined: dprintf("InterfaceTypeUndefined"); break;
|
|
case Internal: dprintf("Internal"); break;
|
|
case Isa: dprintf("Isa"); break;
|
|
case Eisa: dprintf("Eisa"); break;
|
|
case MicroChannel: dprintf("Micro Channel"); break;
|
|
case TurboChannel: dprintf("Turbo Channel"); break;
|
|
case PCIBus: dprintf("PCI"); break;
|
|
case VMEBus: dprintf("VME"); break;
|
|
case NuBus: dprintf("NuBus"); break;
|
|
case PCMCIABus: dprintf("PCMCIA"); break;
|
|
case CBus: dprintf("CBus"); break;
|
|
case MPIBus: dprintf("MPIBus"); break;
|
|
case MPSABus: dprintf("MPSABus"); break;
|
|
case ProcessorInternal: dprintf("Processor Internal"); break;
|
|
case InternalPowerBus: dprintf("Internal Power Bus"); break;
|
|
case PNPISABus: dprintf("PnP Isa"); break;
|
|
case PNPBus: dprintf("PnP Bus"); break;
|
|
default: dprintf("** Unknown Interface Type **"); break;
|
|
|
|
}
|
|
dprintf("%d - !devnode 0x%08p\n", busNumber, deviceNode);
|
|
v.Buffer = instancePath_Buff;
|
|
v.Length = instancePath_Len;
|
|
v.MaximumLength = instancePath_Max;
|
|
dprintf("\t\""); DumpUnicode64(v); dprintf("\"\n");
|
|
}
|
|
|
|
if (GetFieldValue(legacyBusEntryAddr, listEntryType, "Flink", link_Flink)) {
|
|
|
|
dprintf("Error reading Flink from (0x%08p)\n", legacyBusEntryAddr);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|