1277 lines
32 KiB
C
1277 lines
32 KiB
C
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dma.c
|
|
|
|
Abstract:
|
|
|
|
WinDbg Extension Api
|
|
|
|
Author:
|
|
|
|
Eric Nelson (enelson) 05-April-2000
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
typedef struct _DBG_LIST_ENTRY {
|
|
ULONG64 Flink;
|
|
ULONG64 Blink;
|
|
} DBG_LIST_ENTRY, *PDBG_LIST_ENTRY;
|
|
|
|
#define GetDbgListEntry(Address, DbgListEntry) \
|
|
(GetFieldValue((Address), "LIST_ENTRY", "Blink", ((PDBG_LIST_ENTRY)(DbgListEntry))->Blink) || GetFieldValue((Address), "LIST_ENTRY", "Flink", ((PDBG_LIST_ENTRY)(DbgListEntry))->Flink))
|
|
|
|
#define RECUR DBG_DUMP_FIELD_RECUR_ON_THIS
|
|
#define COPY DBG_DUMP_FIELD_COPY_FIELD_DATA
|
|
#define NOFF DBG_DUMP_NO_OFFSET
|
|
#define NOIN DBG_DUMP_NO_INDENT
|
|
|
|
#define MAP_REGISTER_FILE_SIGNATURE 0xACEFD00D
|
|
|
|
//
|
|
// Flags for specifying dump levels
|
|
//
|
|
#define DMA_DUMP_BASIC 0x0
|
|
#define DMA_DUMP_ADAPTER_INFORMATION 0x1
|
|
#define DMA_DUMP_MAP_REGISTER 0x2
|
|
#define DMA_DUMP_COMMON_BUFFER 0x4
|
|
#define DMA_DUMP_TRANSFER_INFORMATION 0x8
|
|
#define DMA_DUMP_DEVICE_DESCRIPTION 0x10
|
|
#define DMA_DUMP_WCB 0x20
|
|
#define DMA_DUMP_MAX 0x100
|
|
|
|
|
|
PUCHAR DbgInterfaceTypes[] =
|
|
{
|
|
"Internal",
|
|
"Isa",
|
|
"Eisa",
|
|
"MicroChannel",
|
|
"TurboChannel",
|
|
"PCIBus",
|
|
"VMEBus",
|
|
"NuBus",
|
|
"PCMCIABus",
|
|
"CBus",
|
|
"MPIBus",
|
|
"MPSABus",
|
|
"ProcessorInternal",
|
|
"InternalPowerBus",
|
|
"PNPISABus",
|
|
"PNPBus"
|
|
};
|
|
#define MAX_INTERFACE 15
|
|
|
|
ULONG
|
|
DumpDmaAdapter(
|
|
IN ULONG64 Adapter,
|
|
IN ULONG Flags
|
|
);
|
|
|
|
ULONG
|
|
ValidateAdapter(
|
|
IN ULONG64 Address
|
|
);
|
|
|
|
ULONG
|
|
DumpMasterAdapter(
|
|
ULONG64 MasterAdapter
|
|
);
|
|
|
|
ULONG
|
|
DumpWcb(
|
|
IN ULONG64 CurrentWcb
|
|
);
|
|
|
|
VOID DmaUsage(
|
|
VOID
|
|
);
|
|
|
|
ULONG64
|
|
GetVerifierAdapterInformation(
|
|
ULONG64 Address
|
|
);
|
|
|
|
|
|
VOID
|
|
DumpVerifiedMapRegisterFiles(
|
|
IN ULONG64 MapRegisterFileListHead
|
|
);
|
|
|
|
VOID
|
|
DumpVerifiedCommonBuffers(
|
|
IN ULONG64 CommonBufferListHead
|
|
);
|
|
|
|
VOID
|
|
DumpVerifiedScatterGatherLists(
|
|
IN ULONG64 ScatterGatherListHead
|
|
);
|
|
|
|
VOID
|
|
DumpDeviceDescription(
|
|
IN ULONG64 DeviceDescription
|
|
);
|
|
|
|
VOID
|
|
DumpSymbolicAddress(
|
|
ULONG64 Address,
|
|
PUCHAR Buffer,
|
|
BOOL AlwaysShowHex
|
|
)
|
|
{
|
|
ULONG64 displacement;
|
|
PCHAR s;
|
|
|
|
Buffer[0] = '!';
|
|
GetSymbol((ULONG64)Address, Buffer, &displacement);
|
|
s = (PCHAR) Buffer + strlen( (PCHAR) Buffer );
|
|
if (s == (PCHAR) Buffer) {
|
|
sprintf( s, "0x%08x", Address );
|
|
}
|
|
else {
|
|
if (displacement != 0) {
|
|
sprintf( s, "+0x%I64x", displacement );
|
|
}
|
|
if (AlwaysShowHex) {
|
|
sprintf( s, " (0x%08x)", Address );
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
DECLARE_API( dma )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps out 32-bit dma adapters
|
|
|
|
Arguments:
|
|
|
|
address
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
ULONG Offset;
|
|
ULONG Flags = 0;
|
|
|
|
ULONG64 Address = 0;
|
|
ULONG64 StartAddress = 0;
|
|
ULONG64 MasterAdapter = 0;
|
|
|
|
ULONG64 CallersAddress = 0;
|
|
ULONG64 AdapterInformation = 0;
|
|
|
|
DBG_LIST_ENTRY AdapterList = {0,0};
|
|
|
|
if (sscanf(args, "%lx %x", &Address, &Flags)) {
|
|
Address = GetExpression(args);
|
|
}
|
|
|
|
if (Flags > DMA_DUMP_MAX)
|
|
{
|
|
DmaUsage();
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
//
|
|
// Aha! Must not forget that we are in wierdo land and all 32 bit addresses
|
|
// must be sign extended to 64 bits. By order of the emperor.
|
|
//
|
|
if (!IsPtr64()) {
|
|
Address = (ULONG64)(LONG64)(LONG)Address;
|
|
}
|
|
|
|
|
|
if (Address)
|
|
//
|
|
// If we've been passed an adapter address, we are just printing out
|
|
// the single adapter
|
|
//
|
|
{
|
|
if (! ValidateAdapter(Address))
|
|
{
|
|
dprintf("\n%08p is not a valid adapter object\n",Address);
|
|
DmaUsage();
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Dump out info about the adapter
|
|
//
|
|
if (! DumpDmaAdapter(Address, Flags | DMA_DUMP_ADAPTER_INFORMATION))
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// A specific adapter address wasn't passed in so we are going to print out
|
|
// all adapters
|
|
//
|
|
|
|
//
|
|
// Find the address of the dma adapter list head
|
|
// This will also make sure that we are using the right
|
|
// version.
|
|
//
|
|
StartAddress = GetExpression("hal!HalpDmaAdapterList");
|
|
|
|
if (StartAddress == 0) {
|
|
dprintf("\nCould not find symbol hal!HalpDmaAdapterList.\n\n");
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Determine the list entry offset we will use to calculate
|
|
// adapter addresses
|
|
//
|
|
if (GetFieldOffset("hal!_ADAPTER_OBJECT", "AdapterList", &Offset)) {
|
|
dprintf("\nError retrieving adapter list offset.\n\n");
|
|
return S_FALSE;
|
|
}
|
|
|
|
//
|
|
// Read the dma adapter list head
|
|
//
|
|
if (GetDbgListEntry(StartAddress, &AdapterList)) {
|
|
dprintf("\nError reading dma adapter list head: 0x%08p\n\n",
|
|
StartAddress);
|
|
return S_FALSE;
|
|
}
|
|
|
|
//
|
|
// Report the empty list case
|
|
//
|
|
if (AdapterList.Flink == StartAddress) {
|
|
dprintf("\nThe dma adapter list is empty.\n\n");
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// Enumerate and dump all dma adapters that do not use channels
|
|
//
|
|
MasterAdapter = 0;
|
|
|
|
|
|
dprintf("\nDumping all DMA adapters...\n\n");
|
|
|
|
while (AdapterList.Flink != StartAddress) {
|
|
|
|
Address = AdapterList.Flink - Offset;
|
|
|
|
DumpDmaAdapter(Address, Flags);
|
|
|
|
//
|
|
// Read the next adapter list entry
|
|
//
|
|
Address = AdapterList.Flink;
|
|
if (GetDbgListEntry(Address, &AdapterList)) {
|
|
dprintf("\nError reading adapter list entry: 0x%08p\n", Address);
|
|
break;
|
|
}
|
|
|
|
if (CheckControlC())
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// Dump the master adapter
|
|
//
|
|
Address = GetExpression("hal!MasterAdapter32");
|
|
|
|
if (Address) {
|
|
|
|
if (Flags & DMA_DUMP_ADAPTER_INFORMATION) {
|
|
|
|
DumpMasterAdapter(Address);
|
|
|
|
} else {
|
|
|
|
dprintf("Master adapter: %08p\n", Address);
|
|
}
|
|
|
|
} else {
|
|
|
|
dprintf("\nCould not find symbol hal!MasterAdapter32.\n");
|
|
}
|
|
|
|
|
|
dprintf("\n");
|
|
|
|
return S_OK;
|
|
} // ! dma //
|
|
|
|
ULONG
|
|
DumpDmaAdapter(
|
|
IN ULONG64 Adapter,
|
|
IN ULONG Flags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given the address of a hal!_ADAPTER_OBJECT, this routine dumps
|
|
out all the useful information to the debugger
|
|
|
|
Arguments:
|
|
|
|
Adapter - Physical address of a hal!_ADAPTER_OBJECT in debuggee
|
|
Flags - What kind of information we want to print
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on SUCCESS
|
|
|
|
--*/
|
|
{
|
|
|
|
ULONG64 AdapterInformation = 0;
|
|
|
|
ULONG64 AllocatedAdapterChannels = 0, FreedAdapterChannels = 0;
|
|
|
|
AdapterInformation = GetVerifierAdapterInformation(Adapter);
|
|
|
|
//
|
|
// Print out: Adapter: <adapter> [<module allocating adapter>!CallingFunction+0x<offset>]
|
|
// (the part in brackets only shows up when we have dma verifier enabled for this adapter)
|
|
//
|
|
dprintf("Adapter: %08p ", Adapter);
|
|
|
|
|
|
if (AdapterInformation)
|
|
{
|
|
ULONG64 CallingAddress = 0;
|
|
CHAR CallerName[256];
|
|
|
|
GetFieldValue(AdapterInformation, "nt!_ADAPTER_INFORMATION","CallingAddress", CallingAddress);
|
|
|
|
if(CallingAddress)
|
|
{
|
|
|
|
DumpSymbolicAddress(CallingAddress, CallerName, TRUE);
|
|
dprintf(" Owner: %s",CallerName);
|
|
}
|
|
|
|
}
|
|
dprintf("\n");
|
|
|
|
|
|
if (Flags & DMA_DUMP_ADAPTER_INFORMATION)
|
|
{
|
|
ULONG64 MasterAdapter = 0;
|
|
ULONG64 MapRegistersPerChannel = 0;
|
|
ULONG64 AdapterBaseVa = 0;
|
|
ULONG64 MapRegisterBase = 0;
|
|
ULONG64 CommittedMapRegisters = 0;
|
|
ULONG64 NumberOfMapRegisters = 0;
|
|
ULONG64 CurrentWcb = 0;
|
|
|
|
GetFieldValue(Adapter, "hal!_ADAPTER_OBJECT","MasterAdapter", MasterAdapter);
|
|
GetFieldValue(Adapter, "hal!_ADAPTER_OBJECT","MapRegistersPerChannel", MapRegistersPerChannel);
|
|
GetFieldValue(Adapter, "hal!_ADAPTER_OBJECT","AdapterBaseVa", AdapterBaseVa);
|
|
GetFieldValue(Adapter, "hal!_ADAPTER_OBJECT","MapRegisterBase", MapRegisterBase);
|
|
GetFieldValue(Adapter, "hal!_ADAPTER_OBJECT","CommittedMapRegisters", CommittedMapRegisters);
|
|
GetFieldValue(Adapter, "hal!_ADAPTER_OBJECT","NumberOfMapRegisters", NumberOfMapRegisters);
|
|
GetFieldValue(Adapter, "hal!_ADAPTER_OBJECT","CurrentWcb", CurrentWcb);
|
|
|
|
|
|
|
|
dprintf(" MasterAdapter: %08p\n", MasterAdapter);
|
|
dprintf(" Adapter base Va %08p\n", AdapterBaseVa);
|
|
dprintf(" Map register base: %08p\n", MapRegisterBase);
|
|
dprintf(" WCB: %08p\n", CurrentWcb);
|
|
dprintf(" Map registers: %08p mapped, %08p allocated, %08p max\n",
|
|
CommittedMapRegisters, NumberOfMapRegisters, MapRegistersPerChannel);
|
|
|
|
|
|
|
|
if (AdapterInformation) {
|
|
//
|
|
// Adapter is being verified
|
|
//
|
|
|
|
ULONG64 DeviceObject = 0;
|
|
ULONG64 AllocatedMapRegisters = 0, ActiveMapRegisters = 0;
|
|
ULONG64 AllocatedScatterGatherLists = 0, ActiveScatterGatherLists = 0;
|
|
ULONG64 AllocatedCommonBuffers = 0, FreedCommonBuffers = 0;
|
|
|
|
ULONG64 MappedTransferWithoutFlushing = 0;
|
|
BOOLEAN Inactive = 0;
|
|
|
|
|
|
|
|
|
|
//
|
|
// If this adapter is being verified, get the dma verifier info we need
|
|
//
|
|
GetFieldValue(AdapterInformation, "nt!_ADAPTER_INFORMATION","DeviceObject", DeviceObject);
|
|
GetFieldValue(AdapterInformation, "nt!_ADAPTER_INFORMATION","AllocatedMapRegisters", AllocatedMapRegisters);
|
|
GetFieldValue(AdapterInformation, "nt!_ADAPTER_INFORMATION","ActiveMapRegisters", ActiveMapRegisters);
|
|
GetFieldValue(AdapterInformation, "nt!_ADAPTER_INFORMATION","AllocatedScatterGatherLists", AllocatedScatterGatherLists);
|
|
GetFieldValue(AdapterInformation, "nt!_ADAPTER_INFORMATION","ActiveScatterGatherLists", ActiveScatterGatherLists);
|
|
GetFieldValue(AdapterInformation, "nt!_ADAPTER_INFORMATION","AllocatedCommonBuffers", AllocatedCommonBuffers);
|
|
GetFieldValue(AdapterInformation, "nt!_ADAPTER_INFORMATION","FreedCommonBuffers", FreedCommonBuffers);
|
|
GetFieldValue(AdapterInformation, "nt!_ADAPTER_INFORMATION","AllocatedAdapterChannels", AllocatedAdapterChannels);
|
|
GetFieldValue(AdapterInformation, "nt!_ADAPTER_INFORMATION","FreedAdapterChannels", FreedAdapterChannels);
|
|
GetFieldValue(AdapterInformation, "nt!_ADAPTER_INFORMATION","MappedTransferWithoutFlushing", MappedTransferWithoutFlushing);
|
|
GetFieldValue(AdapterInformation, "nt!_ADAPTER_INFORMATION","Inactive", Inactive);
|
|
|
|
|
|
|
|
dprintf("\n Dma verifier additional information:\n");
|
|
|
|
if (Inactive)
|
|
dprintf("\n This adapter has been freed!\n\n");
|
|
|
|
dprintf(" DeviceObject: %08p\n", DeviceObject);
|
|
dprintf(" Map registers: %08p allocated, %08p freed\n", AllocatedMapRegisters,
|
|
AllocatedMapRegisters - ActiveMapRegisters);
|
|
|
|
dprintf(" Scatter-gather lists: %08p allocated, %08p freed\n", AllocatedScatterGatherLists,
|
|
AllocatedScatterGatherLists - ActiveScatterGatherLists);
|
|
dprintf(" Common buffers: %08p allocated, %08p freed\n", AllocatedCommonBuffers, FreedCommonBuffers);
|
|
dprintf(" Adapter channels: %08p allocated, %08p freed\n", AllocatedAdapterChannels, FreedAdapterChannels);
|
|
dprintf(" Bytes mapped since last flush: %08p\n", MappedTransferWithoutFlushing);
|
|
|
|
dprintf("\n");
|
|
|
|
} // Dma verifier enabled for adapter //
|
|
|
|
} // Flags & DMA_DUMP_ADAPTER_INFORMATION //
|
|
|
|
|
|
|
|
if (CheckControlC())
|
|
return TRUE;
|
|
|
|
if (Flags & DMA_DUMP_MAP_REGISTER && AdapterInformation) {
|
|
ULONG64 MapRegisterFileListHead = 0;
|
|
ULONG Offset;
|
|
|
|
|
|
if ( ! GetFieldOffset("nt!_ADAPTER_INFORMATION",
|
|
"MapRegisterFiles.ListEntry",
|
|
&Offset
|
|
)) {
|
|
|
|
|
|
MapRegisterFileListHead = AdapterInformation + Offset;
|
|
|
|
DumpVerifiedMapRegisterFiles(MapRegisterFileListHead);
|
|
}
|
|
}
|
|
|
|
if (CheckControlC())
|
|
return TRUE;
|
|
|
|
if (Flags & DMA_DUMP_COMMON_BUFFER && AdapterInformation) {
|
|
ULONG64 CommonBufferListHead = 0;
|
|
ULONG Offset;
|
|
|
|
if ( ! GetFieldOffset("nt!_ADAPTER_INFORMATION",
|
|
"CommonBuffers.ListEntry",
|
|
&Offset
|
|
)) {
|
|
|
|
CommonBufferListHead = AdapterInformation + Offset;
|
|
|
|
DumpVerifiedCommonBuffers(CommonBufferListHead);
|
|
|
|
}
|
|
}
|
|
|
|
if (CheckControlC())
|
|
return TRUE;
|
|
|
|
#if 0
|
|
if (Flags & DMA_DUMP_SCATTER_GATHER && AdapterInformation) {
|
|
ULONG64 ScatterGatherListHead = 0;
|
|
ULONG Offset;
|
|
|
|
if ( ! GetFieldOffset("nt!_ADAPTER_INFORMATION",
|
|
"ScatterGatherLists.ListEntry",
|
|
&Offset
|
|
)) {
|
|
|
|
ScatterGatherListHead = AdapterInformation + Offset;
|
|
|
|
DumpVerifiedScatterGatherLists(ScatterGatherListHead);
|
|
}
|
|
}
|
|
#endif
|
|
if (CheckControlC())
|
|
return TRUE;
|
|
|
|
|
|
if (Flags & DMA_DUMP_DEVICE_DESCRIPTION && AdapterInformation)
|
|
{
|
|
ULONG64 DeviceDescription;
|
|
ULONG Offset;
|
|
|
|
if ( ! GetFieldOffset("nt!_ADAPTER_INFORMATION",
|
|
"DeviceDescription",
|
|
&Offset
|
|
)) {
|
|
|
|
DeviceDescription = AdapterInformation + Offset;
|
|
|
|
DumpDeviceDescription(DeviceDescription);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (CheckControlC())
|
|
return TRUE;
|
|
|
|
|
|
if (Flags & DMA_DUMP_WCB ) {
|
|
|
|
if (! AdapterInformation) {
|
|
ULONG64 CurrentWcb = 0;
|
|
|
|
GetFieldValue(Adapter, "hal!_ADAPTER_OBJECT","CurrentWcb", CurrentWcb);
|
|
|
|
if (CurrentWcb)
|
|
DumpWcb(CurrentWcb);
|
|
}
|
|
else if (AllocatedAdapterChannels > FreedAdapterChannels && Flags & DMA_DUMP_WCB )
|
|
{
|
|
|
|
//DumpVerifiedWcb(Wcb)
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
ULONG
|
|
DumpMasterAdapter(
|
|
ULONG64 MasterAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given the address of a hal!_MASTER_ADAPTER_OBJECT, this routine dumps
|
|
out all the useful information to the debugger
|
|
|
|
Arguments:
|
|
|
|
MasterAdapter - Physical address of a hal!_MASTER_ADAPTER_OBJECT
|
|
in debuggee
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on SUCCESS
|
|
|
|
--*/
|
|
{
|
|
FIELD_INFO MasterAdapterFields[] = {
|
|
{ "AdapterObject", NULL, 0, 0, 0, 0 },
|
|
{ "MaxBufferPages", NULL, 0, 0, 0, 0 },
|
|
{ "MapBufferSize", NULL, 0, 0, 0, 0 },
|
|
{ "MapBufferPhysicalAddress", NULL, RECUR, 0, 0, 0 },
|
|
{ "MapBufferPhysicalAddress.HighPart", NULL, 0, 0, 0, 0 },
|
|
{ "MapBufferPhysicalAddress.LowPart", NULL, 0, 0, 0, 0 }
|
|
};
|
|
|
|
SYM_DUMP_PARAM MasterAdapterDumpParams = {
|
|
sizeof(SYM_DUMP_PARAM), "hal!_MASTER_ADAPTER_OBJECT", NOFF,
|
|
MasterAdapter, NULL, NULL, NULL,
|
|
sizeof(MasterAdapterFields) / sizeof(FIELD_INFO),
|
|
&MasterAdapterFields[0]
|
|
};
|
|
|
|
//
|
|
// This is so gnarly, dump all the cool stuff for me!
|
|
//
|
|
dprintf("\nMaster DMA adapter: 0x%08p\n", MasterAdapter);
|
|
if ((Ioctl(IG_DUMP_SYMBOL_INFO,
|
|
&MasterAdapterDumpParams,
|
|
MasterAdapterDumpParams.size))) {
|
|
dprintf("\nError reading master adapter: 0x%08p\n", MasterAdapter);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
ULONG
|
|
DumpWcb(
|
|
IN ULONG64 Wcb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given the address of a hal!_WAIT_CONTEXT_BLOCK, this routine dumps
|
|
out all the useful information to the debugger
|
|
|
|
Arguments:
|
|
|
|
Wcb - Physical address of a hal!_WAIT_CONTEXT_BLOCK in debuggee
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on SUCCESS
|
|
|
|
--*/
|
|
{
|
|
FIELD_INFO WcbFields[] = {
|
|
{ "DeviceRoutine", NULL, 0, 0, 0, 0 },
|
|
{ "NumberOfMapRegisters", NULL, 0, 0, 0, 0 }
|
|
};
|
|
|
|
SYM_DUMP_PARAM WcbDumpParams = {
|
|
sizeof(SYM_DUMP_PARAM), "hal!_WAIT_CONTEXT_BLOCK", NOFF, Wcb, NULL,
|
|
NULL, NULL, sizeof(WcbFields) / sizeof(FIELD_INFO), &WcbFields[0]
|
|
};
|
|
|
|
//
|
|
// This is so gnarly, dump all the cool stuff for me!
|
|
//
|
|
dprintf(" Wait context block: 0x%08p (may be free)\n", Wcb);
|
|
if ((Ioctl(IG_DUMP_SYMBOL_INFO,
|
|
&WcbDumpParams,
|
|
WcbDumpParams.size))) {
|
|
dprintf("\nError reading wait context block: 0x%08p\n", Wcb);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
ValidateAdapter(
|
|
IN ULONG64 Address
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Figures out whether this is a valid adapter.
|
|
|
|
Arguments:
|
|
|
|
Address -- Address of what we think may be an adapter object.
|
|
|
|
Return Value:
|
|
|
|
TRUE -- Valid adapter.
|
|
FALSE -- Not a valid adapter.
|
|
|
|
--*/
|
|
{
|
|
DBG_LIST_ENTRY AdapterList = {0,0};
|
|
ULONG64 StartAddress = 0;
|
|
ULONG64 CurrentAddress = 0;
|
|
|
|
ULONG Offset;
|
|
|
|
if (! Address )
|
|
return FALSE;
|
|
|
|
|
|
//
|
|
// Find the address of the dma adapter list head
|
|
// This will also make sure that we are using the right
|
|
// version.
|
|
//
|
|
StartAddress = GetExpression("hal!HalpDmaAdapterList");
|
|
|
|
if (StartAddress == 0) {
|
|
dprintf("\nCould not find symbol hal!HalpDmaAdapterList.\n\n");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Determine the list entry offset we will use to calculate
|
|
// adapter addresses
|
|
//
|
|
if (GetFieldOffset("hal!_ADAPTER_OBJECT", "AdapterList", &Offset)) {
|
|
dprintf("\nError retrieving adapter list offset.\n\n");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Read the dma adapter list head
|
|
//
|
|
if (GetDbgListEntry(StartAddress, &AdapterList)) {
|
|
dprintf("\nError reading dma adapter list head: 0x%08p\n\n",
|
|
StartAddress);
|
|
return FALSE;
|
|
}
|
|
|
|
while (AdapterList.Flink != StartAddress) {
|
|
|
|
|
|
CurrentAddress = AdapterList.Flink - Offset;
|
|
|
|
if (Address == CurrentAddress) {
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// Read the next adapter list entry
|
|
//
|
|
CurrentAddress = AdapterList.Flink;
|
|
if (GetDbgListEntry(CurrentAddress, &AdapterList)) {
|
|
dprintf("\nError reading adapter list entry: 0x%08p\n", AdapterList);
|
|
break;
|
|
}
|
|
|
|
|
|
if (CheckControlC())
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Check to see if we have the master adapter
|
|
//
|
|
CurrentAddress = GetExpression("hal!MasterAdapter32");
|
|
if(CurrentAddress == Address)
|
|
return TRUE;
|
|
|
|
|
|
//
|
|
// Check to see if it is on the verifier adapter list ...
|
|
// we leave adapters that have been 'put' there so that
|
|
// we can catch drivers that do dma after puting the adapter.
|
|
//
|
|
if (GetVerifierAdapterInformation(Address))
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
} // ValidateAdapter //
|
|
|
|
|
|
VOID DmaUsage(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints out correct usage for !dma
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
|
|
dprintf("\nUsage: !dma [adapter address] [flags]\n");
|
|
dprintf("Where: [adapter address] is address of specific dma adapter\n");
|
|
dprintf(" or 0x0 for all adapters\n");
|
|
dprintf(" [flags] are:\n");
|
|
dprintf(" 0x1: Dump generic adapter information\n");
|
|
dprintf(" 0x2: Dump map register information\n");
|
|
dprintf(" 0x4: Dump common buffer information\n");
|
|
dprintf(" 0x8: Dump scatter-gather list information\n");
|
|
dprintf(" 0x10: Dump device description for device\n");
|
|
dprintf(" 0x20: Dump Wait-context-block information\n");
|
|
dprintf("Note: flags {2,4,8,10} require dma verifier to be enabled for the adapter\n\n");
|
|
|
|
|
|
} // DmaUsage //
|
|
|
|
ULONG64
|
|
GetVerifierAdapterInformation(
|
|
ULONG64 AdapterAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Finds out whether the adapter at AdapterAddress is being verified. If it is, return a pointer
|
|
to the ADAPTER_INFORMATION structure corresponding to the adapter.
|
|
|
|
Arguments:
|
|
|
|
AdapterAddress -- Address of the adapter we are trying to find out if it is being verified
|
|
|
|
Return Value:
|
|
|
|
ULONG64 -- Address of ADAPTER_INFORMATION struct for verified adapter
|
|
0 -- Not verifying adapter;
|
|
|
|
--*/
|
|
{
|
|
DBG_LIST_ENTRY AdapterInfoList = {0,0};
|
|
ULONG64 StartAddress = 0;
|
|
ULONG64 CurrentAdapter = 0;
|
|
ULONG64 CurrentAdapterInfo = 0;
|
|
|
|
ULONG64 VerifiedDmaAdapter = 0;
|
|
ULONG ListEntryOffset = 0;
|
|
|
|
UINT64 VerifyingDma = 0;
|
|
|
|
if (! AdapterAddress )
|
|
return 0;
|
|
|
|
|
|
ReadPointer(GetExpression("nt!ViVerifyDma"), &VerifyingDma);
|
|
if (0 == VerifyingDma)
|
|
//
|
|
// Not verifying dma ...
|
|
//
|
|
{
|
|
return 0;
|
|
}
|
|
//
|
|
// Find the address of the dma adapter list head
|
|
//
|
|
|
|
StartAddress = GetExpression("nt!ViAdapterList");
|
|
|
|
if (StartAddress == 0) {
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Determine the list entry offset we will use to calculate
|
|
// adapter addresses
|
|
//
|
|
if (GetFieldOffset("nt!_ADAPTER_INFORMATION", "ListEntry", &ListEntryOffset)) {
|
|
dprintf("\nError retrieving verifier adapter information list offset.\n\n");
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Read the dma adapter list head
|
|
//
|
|
if (GetDbgListEntry(StartAddress, &AdapterInfoList)) {
|
|
dprintf("\nError reading verifier adapter information list head: 0x%08p\n\n",
|
|
StartAddress);
|
|
return 0;
|
|
}
|
|
|
|
if (AdapterInfoList.Flink == 0 || AdapterInfoList.Blink == 0)
|
|
return 0;
|
|
|
|
while (AdapterInfoList.Flink != StartAddress) {
|
|
|
|
CurrentAdapterInfo = AdapterInfoList.Flink - ListEntryOffset;
|
|
|
|
GetFieldValue(CurrentAdapterInfo, "nt!_ADAPTER_INFORMATION","DmaAdapter", VerifiedDmaAdapter);
|
|
|
|
if (AdapterAddress == VerifiedDmaAdapter)
|
|
{
|
|
return CurrentAdapterInfo;
|
|
}
|
|
//
|
|
// Read the next adapter list entry
|
|
//
|
|
if (GetDbgListEntry(AdapterInfoList.Flink, &AdapterInfoList)) {
|
|
dprintf("\nError reading adapter info list entry: 0x%08p\n", AdapterInfoList);
|
|
break;
|
|
}
|
|
|
|
|
|
if (CheckControlC())
|
|
break;
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
} // GetVerifierAdapterInformation //
|
|
|
|
|
|
|
|
VOID
|
|
DumpVerifiedMapRegisterFiles(
|
|
IN ULONG64 MapRegisterFileListHead
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump pertinent info pertaining to verified map registers.
|
|
NOTE: This may not be all map registers for the adapter -- just the ones
|
|
that are being verified. There is a limit to how many map registers
|
|
we verify for each adapter -- since each time we use three pages
|
|
of physical memory.
|
|
|
|
NOTE ON TERMINOLOGY: Map register file: a single allocation of map registers
|
|
recieved in the callback routine from IoAllocateAdapterChannel. Any number
|
|
or combination of these registers can be mapped at one time.
|
|
|
|
Arguments:
|
|
|
|
MapRegisterFileListHead -- head of list of map register files.
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
DBG_LIST_ENTRY MapRegisterFileListEntry = {0,0};
|
|
ULONG64 MapRegisterFile = 0;
|
|
|
|
ULONG ListEntryOffset = 0;
|
|
|
|
ULONG64 Signature = 0;
|
|
ULONG64 NumberOfMapRegisters = 0;
|
|
ULONG64 NumberOfRegistersMapped = 0;
|
|
ULONG64 MapRegisterMdl = 0;
|
|
|
|
ULONG64 MapRegister;
|
|
|
|
ULONG64 MappedToAddress;
|
|
ULONG64 BytesMapped;
|
|
ULONG64 MapRegisterStart;
|
|
|
|
ULONG SizeofMapRegister;
|
|
ULONG CurrentMapRegister;
|
|
ULONG MapRegisterOffset;
|
|
|
|
|
|
if (GetDbgListEntry(MapRegisterFileListHead, &MapRegisterFileListEntry))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (MapRegisterFileListEntry.Flink == MapRegisterFileListHead)
|
|
//
|
|
// Empty list
|
|
//
|
|
{
|
|
dprintf("\n No map register files\n\n");
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Determine the list entry offset we will use to calculate
|
|
// the beginning of the map register file
|
|
//
|
|
if (GetFieldOffset("nt!_MAP_REGISTER_FILE", "ListEntry", &ListEntryOffset)) {
|
|
dprintf("\nError retrieving list entry offset.\n\n");
|
|
return;
|
|
}
|
|
|
|
SizeofMapRegister = GetTypeSize("nt!_MAP_REGISTER");
|
|
if (! SizeofMapRegister )
|
|
{
|
|
dprintf("\n Could not get size of nt!_MAP_REGISTER\n\n");
|
|
return;
|
|
}
|
|
|
|
|
|
if (GetFieldOffset("nt!_MAP_REGISTER_FILE","MapRegisters", &MapRegisterOffset))
|
|
{
|
|
dprintf("\n Couuld not get map register offset\n\n");
|
|
}
|
|
|
|
while (MapRegisterFileListEntry.Flink != MapRegisterFileListHead) {
|
|
|
|
MapRegisterFile = MapRegisterFileListEntry.Flink - ListEntryOffset;
|
|
|
|
GetFieldValue(MapRegisterFile, "nt!_MAP_REGISTER_FILE","Signature", Signature);
|
|
|
|
if (((ULONG) Signature) != MAP_REGISTER_FILE_SIGNATURE) {
|
|
dprintf("\n Invalid signature for map register file %08p\n\n", MapRegisterFile);
|
|
return;
|
|
}
|
|
|
|
GetFieldValue(MapRegisterFile, "nt!_MAP_REGISTER_FILE","NumberOfMapRegisters", NumberOfMapRegisters);
|
|
GetFieldValue(MapRegisterFile, "nt!_MAP_REGISTER_FILE","NumberOfRegistersMapped", NumberOfRegistersMapped);
|
|
GetFieldValue(MapRegisterFile, "nt!_MAP_REGISTER_FILE","MapRegisterMdl", MapRegisterMdl);
|
|
|
|
|
|
|
|
|
|
dprintf(" Map register file %08p (%x/%x mapped)\n",
|
|
MapRegisterFile, (ULONG) NumberOfRegistersMapped, (ULONG) NumberOfMapRegisters);
|
|
dprintf(" Double buffer mdl: %08p\n", MapRegisterMdl);
|
|
dprintf(" Map registers:\n");
|
|
|
|
MapRegister = MapRegisterFile + MapRegisterOffset;
|
|
for (CurrentMapRegister = 0; CurrentMapRegister < NumberOfMapRegisters; CurrentMapRegister++) {
|
|
GetFieldValue(MapRegister, "nt!_MAP_REGISTER", "MappedToSa", MappedToAddress);
|
|
GetFieldValue(MapRegister, "nt!_MAP_REGISTER", "BytesMapped", BytesMapped);
|
|
|
|
dprintf(" %08x: ", MapRegister);
|
|
//dprintf(" %03x: ", CurrentMapRegister);
|
|
if (BytesMapped) {
|
|
|
|
dprintf("%04x bytes mapped to %08p\n", (ULONG) BytesMapped, MappedToAddress);
|
|
|
|
} else {
|
|
|
|
dprintf("Not mapped\n");
|
|
}
|
|
|
|
if (CheckControlC())
|
|
return;
|
|
//
|
|
// Increment our map register pointer
|
|
//
|
|
MapRegister += SizeofMapRegister;
|
|
} // End dump of map registers //
|
|
|
|
dprintf("\n");
|
|
|
|
|
|
//
|
|
// Advance to the next map register file
|
|
//
|
|
if (GetDbgListEntry(MapRegisterFileListEntry.Flink , &MapRegisterFileListEntry)) {
|
|
|
|
dprintf("\nError reading map register file list entry: 0x%08p\n",
|
|
MapRegisterFileListEntry.Flink);
|
|
break;
|
|
}
|
|
|
|
if (CheckControlC())
|
|
return;
|
|
|
|
} // End dump of map register files //
|
|
|
|
|
|
return;
|
|
} // DumpVerifiedMapRegisterFiles //
|
|
|
|
VOID
|
|
DumpVerifiedCommonBuffers(
|
|
IN ULONG64 CommonBufferListHead
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump pertinent info pertaining to verified common buffers
|
|
|
|
Arguments:
|
|
|
|
CommonBufferListHead -- head of list of common buffers for a single adapter
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
DBG_LIST_ENTRY CommonBufferListEntry = {0,0};
|
|
|
|
ULONG64 CommonBuffer;
|
|
ULONG AdvertisedLength;
|
|
|
|
UINT64 AdvertisedStartAddress;
|
|
UINT64 RealStartAddress;
|
|
UINT64 RealLogicalStartAddress;
|
|
UINT64 AdvertisedLogicalStartAddress;
|
|
|
|
UINT64 AllocatorAddress;
|
|
|
|
ULONG ListEntryOffset;
|
|
CHAR AllocatorName[256];
|
|
|
|
|
|
if (GetDbgListEntry(CommonBufferListHead, &CommonBufferListEntry))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (CommonBufferListEntry.Flink == CommonBufferListHead)
|
|
//
|
|
// Empty list
|
|
//
|
|
{
|
|
dprintf("\n No common buffers\n\n");
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Determine the list entry offset we will use to calculate
|
|
// the beginning of the map register file
|
|
//
|
|
if (GetFieldOffset("nt!_HAL_VERIFIER_BUFFER", "ListEntry", &ListEntryOffset)) {
|
|
dprintf("\n Error retrieving list entry offset.\n\n");
|
|
return;
|
|
}
|
|
|
|
while (CommonBufferListEntry.Flink != CommonBufferListHead) {
|
|
|
|
CommonBuffer = CommonBufferListEntry.Flink - ListEntryOffset;
|
|
|
|
|
|
GetFieldValue(CommonBuffer, "nt!_HAL_VERIFIER_BUFFER","AdvertisedLength", AdvertisedLength);
|
|
GetFieldValue(CommonBuffer, "nt!_HAL_VERIFIER_BUFFER","AdvertisedStartAddress", AdvertisedStartAddress);
|
|
GetFieldValue(CommonBuffer, "nt!_HAL_VERIFIER_BUFFER","RealStartAddress", RealStartAddress);
|
|
GetFieldValue(CommonBuffer, "nt!_HAL_VERIFIER_BUFFER","RealLogicalStartAddress", RealLogicalStartAddress);
|
|
GetFieldValue(CommonBuffer, "nt!_HAL_VERIFIER_BUFFER","AllocatorAddress", AllocatorAddress);
|
|
|
|
DumpSymbolicAddress(AllocatorAddress, AllocatorName, TRUE);
|
|
|
|
dprintf(" Common buffer allocated by %s:\n", AllocatorName);
|
|
|
|
dprintf(" Length: %x\n", AdvertisedLength);
|
|
dprintf(" Virtual address: %08p\n", AdvertisedStartAddress);
|
|
dprintf(" Physical address: %I64lx\n",
|
|
(AdvertisedStartAddress - RealStartAddress) + RealLogicalStartAddress);
|
|
|
|
dprintf("\n");
|
|
//
|
|
// Advance to the next common buffer in the list
|
|
//
|
|
if (GetDbgListEntry(CommonBufferListEntry.Flink , &CommonBufferListEntry)) {
|
|
|
|
dprintf("\nError reading common buffer list entry: 0x%08p\n",
|
|
CommonBufferListEntry.Flink);
|
|
break;
|
|
}
|
|
|
|
if (CheckControlC())
|
|
return;
|
|
|
|
} // End dump of common buffers //
|
|
|
|
|
|
return;
|
|
} // DumpVerifiedCommonBuffers //
|
|
|
|
VOID
|
|
DumpVerifiedScatterGatherLists(
|
|
IN ULONG64 ScatterGatherListHead
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump pertinent info pertaining to scatter gather lists in use by a single
|
|
adapter.
|
|
|
|
Arguments:
|
|
|
|
ScatterGatherListHead -- head of a list of ScatterGather lists.
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER(ScatterGatherListHead);
|
|
|
|
return;
|
|
} // DumpVerifiedScatterGatherLists //
|
|
|
|
VOID
|
|
DumpDeviceDescription(
|
|
IN ULONG64 DeviceDescription
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump pertinent info from a device description struct
|
|
|
|
Arguments:
|
|
|
|
ScatterGatherListHead -- head of a list of ScatterGather lists.
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
ULONG Version;
|
|
BOOLEAN Master;
|
|
BOOLEAN ScatterGather;
|
|
BOOLEAN Dma32BitAddresses;
|
|
BOOLEAN Dma64BitAddresses;
|
|
ULONG InterfaceType;
|
|
ULONG MaximumLength;
|
|
|
|
|
|
GetFieldValue(DeviceDescription, "hal!_DEVICE_DESCRIPTION","Version", Version);
|
|
|
|
if (Version > 2) {
|
|
dprintf("\nBad device description version: %x\n\n", Version);
|
|
return;
|
|
}
|
|
|
|
GetFieldValue(DeviceDescription, "hal!_DEVICE_DESCRIPTION","Master", Master);
|
|
GetFieldValue(DeviceDescription, "hal!_DEVICE_DESCRIPTION","ScatterGather", ScatterGather);
|
|
GetFieldValue(DeviceDescription, "hal!_DEVICE_DESCRIPTION","Dma32BitAddresses", Dma32BitAddresses);
|
|
GetFieldValue(DeviceDescription, "hal!_DEVICE_DESCRIPTION","Dma64BitAddresses", Dma64BitAddresses);
|
|
GetFieldValue(DeviceDescription, "hal!_DEVICE_DESCRIPTION","InterfaceType", InterfaceType);
|
|
|
|
dprintf(" Device Description Version %02x\n", Version);
|
|
|
|
if (InterfaceType < MAX_INTERFACE) {
|
|
|
|
dprintf(" Interface type %s\n", DbgInterfaceTypes[InterfaceType]);
|
|
|
|
} else {
|
|
|
|
dprintf(" Interface type unknown\n");
|
|
|
|
}
|
|
|
|
dprintf(" DMA Capabilities:\n");
|
|
|
|
if(Master) {
|
|
dprintf(" Busmaster\n");
|
|
} else {
|
|
dprintf(" Slave\n");
|
|
}
|
|
|
|
if (ScatterGather)
|
|
dprintf(" Scatter Gather\n");
|
|
|
|
if (Dma32BitAddresses)
|
|
dprintf(" 32-bit DMA\n");
|
|
if (Dma64BitAddresses)
|
|
dprintf(" 64-bit DMA\n");
|
|
if (! Dma32BitAddresses && ! Dma64BitAddresses)
|
|
dprintf(" 24-bit DMA only\n");
|
|
|
|
dprintf("\n");
|
|
|
|
|
|
|
|
|
|
} // DumpDeviceDescription //
|
|
|