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.
442 lines
11 KiB
442 lines
11 KiB
|
|
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1992 - 2001
|
|
|
|
Module Name:
|
|
|
|
util.c
|
|
|
|
Abstract:
|
|
|
|
Utility library used for the various debugger extensions in this library.
|
|
|
|
Author:
|
|
|
|
Peter Wieland (peterwie) 16-Oct-1995
|
|
ervinp
|
|
|
|
Environment:
|
|
|
|
User Mode.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
#include "ideport.h"
|
|
|
|
PUCHAR devicePowerStateNames[] = {
|
|
"PowerDeviceUnspecified",
|
|
"PowerDeviceD0",
|
|
"PowerDeviceD1",
|
|
"PowerDeviceD2",
|
|
"PowerDeviceD3",
|
|
"PowerDeviceMaximum",
|
|
"Invalid"
|
|
};
|
|
|
|
FLAG_NAME SrbFlags[] = {
|
|
FLAG_NAME(SRB_FLAGS_QUEUE_ACTION_ENABLE),
|
|
FLAG_NAME(SRB_FLAGS_DISABLE_DISCONNECT),
|
|
FLAG_NAME(SRB_FLAGS_DISABLE_SYNCH_TRANSFER),
|
|
FLAG_NAME(SRB_FLAGS_BYPASS_FROZEN_QUEUE),
|
|
FLAG_NAME(SRB_FLAGS_DISABLE_AUTOSENSE),
|
|
FLAG_NAME(SRB_FLAGS_DATA_IN),
|
|
FLAG_NAME(SRB_FLAGS_DATA_OUT),
|
|
FLAG_NAME(SRB_FLAGS_NO_DATA_TRANSFER),
|
|
FLAG_NAME(SRB_FLAGS_UNSPECIFIED_DIRECTION),
|
|
FLAG_NAME(SRB_FLAGS_NO_QUEUE_FREEZE),
|
|
FLAG_NAME(SRB_FLAGS_ADAPTER_CACHE_ENABLE),
|
|
FLAG_NAME(SRB_FLAGS_IS_ACTIVE),
|
|
FLAG_NAME(SRB_FLAGS_ALLOCATED_FROM_ZONE),
|
|
FLAG_NAME(SRB_FLAGS_SGLIST_FROM_POOL),
|
|
FLAG_NAME(SRB_FLAGS_BYPASS_LOCKED_QUEUE),
|
|
FLAG_NAME(SRB_FLAGS_NO_KEEP_AWAKE),
|
|
{0,0}
|
|
};
|
|
|
|
FLAG_NAME LuFlags[] = {
|
|
FLAG_NAME(PD_QUEUE_FROZEN),
|
|
FLAG_NAME(PD_LOGICAL_UNIT_IS_ACTIVE),
|
|
FLAG_NAME(PD_NEED_REQUEST_SENSE),
|
|
FLAG_NAME(PD_LOGICAL_UNIT_IS_BUSY),
|
|
FLAG_NAME(PD_QUEUE_IS_FULL),
|
|
FLAG_NAME(PD_RESCAN_ACTIVE),
|
|
{0, 0}
|
|
};
|
|
|
|
FLAG_NAME PortFlags[] = {
|
|
FLAG_NAME(PD_DEVICE_IS_BUSY),
|
|
FLAG_NAME(PD_NOTIFICATION_REQUIRED),
|
|
FLAG_NAME(PD_READY_FOR_NEXT_REQUEST),
|
|
FLAG_NAME(PD_FLUSH_ADAPTER_BUFFERS),
|
|
FLAG_NAME(PD_MAP_TRANSFER),
|
|
FLAG_NAME(PD_LOG_ERROR),
|
|
FLAG_NAME(PD_RESET_HOLD),
|
|
FLAG_NAME(PD_HELD_REQUEST),
|
|
FLAG_NAME(PD_RESET_REPORTED),
|
|
FLAG_NAME(PD_PENDING_DEVICE_REQUEST),
|
|
FLAG_NAME(PD_DISCONNECT_RUNNING),
|
|
FLAG_NAME(PD_DISABLE_CALL_REQUEST),
|
|
FLAG_NAME(PD_DISABLE_INTERRUPTS),
|
|
FLAG_NAME(PD_ENABLE_CALL_REQUEST),
|
|
FLAG_NAME(PD_TIMER_CALL_REQUEST),
|
|
FLAG_NAME(PD_ALL_DEVICE_MISSING),
|
|
FLAG_NAME(PD_RESET_REQUEST),
|
|
{0,0}
|
|
};
|
|
|
|
FLAG_NAME DevFlags[] = {
|
|
FLAG_NAME(DFLAGS_DEVICE_PRESENT),
|
|
FLAG_NAME(DFLAGS_ATAPI_DEVICE),
|
|
FLAG_NAME(DFLAGS_TAPE_DEVICE),
|
|
FLAG_NAME(DFLAGS_INT_DRQ),
|
|
FLAG_NAME(DFLAGS_REMOVABLE_DRIVE),
|
|
FLAG_NAME(DFLAGS_MEDIA_STATUS_ENABLED),
|
|
FLAG_NAME(DFLAGS_USE_DMA),
|
|
FLAG_NAME(DFLAGS_LBA),
|
|
FLAG_NAME(DFLAGS_MULTI_LUN_INITED),
|
|
FLAG_NAME(DFLAGS_MSN_SUPPORT),
|
|
FLAG_NAME(DFLAGS_AUTO_EJECT_ZIP),
|
|
FLAG_NAME(DFLAGS_WD_MODE),
|
|
FLAG_NAME(DFLAGS_LS120_FORMAT),
|
|
FLAG_NAME(DFLAGS_USE_UDMA),
|
|
FLAG_NAME(DFLAGS_IDENTIFY_VALID),
|
|
FLAG_NAME(DFLAGS_IDENTIFY_INVALID),
|
|
FLAG_NAME(DFLAGS_RDP_SET),
|
|
FLAG_NAME(DFLAGS_SONY_MEMORYSTICK),
|
|
FLAG_NAME(DFLAGS_48BIT_LBA),
|
|
{0,0}
|
|
};
|
|
|
|
PUCHAR
|
|
DevicePowerStateToString(
|
|
IN DEVICE_POWER_STATE State
|
|
)
|
|
|
|
{
|
|
if(State > PowerDeviceMaximum) {
|
|
return "Invalid";
|
|
} else {
|
|
return devicePowerStateNames[(UCHAR) State];
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* xdprintf
|
|
*
|
|
* Prints formatted text with leading spaces.
|
|
*
|
|
* WARNING: DOES NOT HANDLE ULONG64 PROPERLY.
|
|
*/
|
|
VOID
|
|
xdprintf(
|
|
ULONG Depth,
|
|
PCCHAR S,
|
|
...
|
|
)
|
|
{
|
|
va_list ap;
|
|
ULONG i;
|
|
CCHAR DebugBuffer[256] = {0};
|
|
|
|
for (i=0; i<Depth; i++) {
|
|
dprintf (" ");
|
|
}
|
|
|
|
va_start(ap, S);
|
|
|
|
_vsnprintf(DebugBuffer, sizeof(DebugBuffer)-1, S, ap);
|
|
|
|
dprintf (DebugBuffer);
|
|
|
|
va_end(ap);
|
|
}
|
|
|
|
VOID
|
|
DumpFlags(
|
|
ULONG Depth,
|
|
PUCHAR Name,
|
|
ULONG Flags,
|
|
PFLAG_NAME FlagTable
|
|
)
|
|
{
|
|
ULONG i;
|
|
ULONG mask = 0;
|
|
ULONG count = 0;
|
|
UCHAR prolog[64] = {0};
|
|
|
|
_snprintf(prolog, sizeof(prolog)-1, "%s (0x%08x): ", Name, Flags);
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
/*
|
|
* GetULONGField
|
|
*
|
|
* Return the field or -1 in case of error.
|
|
* Yes, it screws up if the field is actually -1.
|
|
*/
|
|
ULONG64 GetULONGField(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName)
|
|
{
|
|
ULONG64 result;
|
|
ULONG dbgStat;
|
|
|
|
dbgStat = GetFieldData(StructAddr, StructType, FieldName, sizeof(ULONG64), &result);
|
|
if (dbgStat != 0){
|
|
dprintf("\n GetULONGField: GetFieldData failed with %xh retrieving field '%s' of struct '%s' @ %08p, returning bogus field value %08xh.\n",
|
|
dbgStat, FieldName, StructType, StructAddr, BAD_VALUE);
|
|
result = BAD_VALUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
* GetUSHORTField
|
|
*
|
|
* Return the field or -1 in case of error.
|
|
* Yes, it screws up if the field is actually -1.
|
|
*/
|
|
USHORT GetUSHORTField(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName)
|
|
{
|
|
USHORT result;
|
|
ULONG dbgStat;
|
|
|
|
dbgStat = GetFieldData(StructAddr, StructType, FieldName, sizeof(USHORT), &result);
|
|
if (dbgStat != 0){
|
|
dprintf("\n GetUSHORTField: GetFieldData failed with %xh retrieving field '%s' of struct '%s' @ %08p, returning bogus field value %08xh.\n",
|
|
dbgStat, FieldName, StructType, StructAddr, BAD_VALUE);
|
|
result = (USHORT)BAD_VALUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
* GetUCHARField
|
|
*
|
|
* Return the field or -1 in case of error.
|
|
* Yes, it screws up if the field is actually -1.
|
|
*/
|
|
UCHAR GetUCHARField(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName)
|
|
{
|
|
UCHAR result;
|
|
ULONG dbgStat;
|
|
|
|
dbgStat = GetFieldData(StructAddr, StructType, FieldName, sizeof(UCHAR), &result);
|
|
if (dbgStat != 0){
|
|
dprintf("\n GetUCHARField: GetFieldData failed with %xh retrieving field '%s' of struct '%s' @ %08p, returning bogus field value %08xh.\n",
|
|
dbgStat, FieldName, StructType, StructAddr, BAD_VALUE);
|
|
result = (UCHAR)BAD_VALUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
ULONG64 GetFieldAddr(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName)
|
|
{
|
|
ULONG64 result;
|
|
ULONG offset;
|
|
ULONG dbgStat;
|
|
|
|
dbgStat = GetFieldOffset(StructType, FieldName, &offset);
|
|
if (dbgStat == 0){
|
|
result = StructAddr+offset;
|
|
}
|
|
else {
|
|
dprintf("\n GetFieldAddr: GetFieldOffset failed with %xh retrieving offset of struct '%s' (@ %08p) field '%s'.\n",
|
|
dbgStat, StructType, StructAddr, FieldName);
|
|
result = BAD_VALUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
ULONG64 GetContainingRecord(ULONG64 FieldAddr, LPCSTR StructType, LPCSTR FieldName)
|
|
{
|
|
ULONG64 result;
|
|
ULONG offset;
|
|
ULONG dbgStat;
|
|
|
|
dbgStat = GetFieldOffset(StructType, FieldName, &offset);
|
|
if (dbgStat == 0){
|
|
result = FieldAddr-offset;
|
|
}
|
|
else {
|
|
dprintf("\n GetContainingRecord: GetFieldOffset failed with %xh retrieving offset of struct '%s' field '%s', returning bogus address %08xh.\n", dbgStat, StructType, FieldName, BAD_VALUE);
|
|
result = BAD_VALUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
* DumpObjListQueue
|
|
*
|
|
* Dump a list of objects queued by LIST_ENTRY's.
|
|
* Returns length of list.
|
|
*/
|
|
ULONG DumpObjListQueue(ULONG Depth, PCHAR Title, PCHAR StructName, PCHAR ListEntryFieldName, ULONG64 ListHeadAddr)
|
|
{
|
|
ULONG64 listEntryAddr;
|
|
ULONG numObjs= 0;
|
|
|
|
if (Title){
|
|
xdprintf(Depth, ""), dprintf("%s:\n", Title);
|
|
}
|
|
|
|
listEntryAddr = GetULONGField(ListHeadAddr, "nt!_LIST_ENTRY", "Flink");
|
|
while ((listEntryAddr != ListHeadAddr) && (listEntryAddr != BAD_VALUE)){
|
|
ULONG64 objAddr;
|
|
|
|
objAddr = GetContainingRecord(listEntryAddr, StructName, ListEntryFieldName);
|
|
if (objAddr == BAD_VALUE){
|
|
break;
|
|
}
|
|
else {
|
|
/*
|
|
* Dump this irp
|
|
*/
|
|
xdprintf(Depth+1, ""), dprintf("%08p\n", objAddr);
|
|
|
|
/*
|
|
* Go to the next irp
|
|
*/
|
|
numObjs++;
|
|
listEntryAddr = GetULONGField(listEntryAddr, "nt!_LIST_ENTRY", "Flink");
|
|
}
|
|
|
|
}
|
|
|
|
dprintf("\n");
|
|
return numObjs;
|
|
}
|
|
|
|
|
|
/*
|
|
* DumpIrpQueue
|
|
*
|
|
* Dump Irp queue linked by Irp->Tail.Overlay.ListEntry
|
|
*/
|
|
ULONG DumpIrpQueue(ULONG Depth, PCHAR Title, ULONG64 ListHeadAddr)
|
|
{
|
|
return DumpObjListQueue(Depth, Title, "nt!_IRP", "Tail.Overlay.ListEntry", ListHeadAddr);
|
|
}
|
|
|
|
|
|
/*
|
|
* DumpIrpDeviceQueue
|
|
*
|
|
* Dump Irp queue linked by Irp->Tail.Overlay.DeviceQueueEntry
|
|
*/
|
|
ULONG DumpIrpDeviceQueue(ULONG Depth, PCHAR Title, ULONG64 ListHeadAddr)
|
|
{
|
|
return DumpObjListQueue(Depth, Title, "nt!_IRP", "Tail.Overlay.DeviceQueueEntry", ListHeadAddr);
|
|
}
|
|
|
|
|
|
/*
|
|
* FindObjInListQueue
|
|
*
|
|
* Searches a list of objects queued by LIST_ENTRY's.
|
|
* Returns TRUE iff the given object is found.
|
|
*/
|
|
BOOLEAN FindObjInListQueue(ULONG64 ListHeadAddr, ULONG64 SpecificObjAddr, PCHAR StructName, PCHAR ListEntryFieldName)
|
|
{
|
|
ULONG64 listEntryAddr;
|
|
BOOLEAN found = FALSE;
|
|
|
|
listEntryAddr = GetULONGField(ListHeadAddr, "nt!_LIST_ENTRY", "Flink");
|
|
while ((listEntryAddr != ListHeadAddr) && (listEntryAddr != BAD_VALUE)){
|
|
ULONG64 objAddr = GetContainingRecord(listEntryAddr, StructName, ListEntryFieldName);
|
|
if (objAddr == BAD_VALUE){
|
|
break;
|
|
}
|
|
else if (objAddr == SpecificObjAddr){
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
else {
|
|
listEntryAddr = GetULONGField(listEntryAddr, "nt!_LIST_ENTRY", "Flink");
|
|
}
|
|
}
|
|
|
|
return found;
|
|
}
|
|
|
|
|
|
/*
|
|
* FindIrpInQueue
|
|
*
|
|
* Find Irp in Irp queue linked by Irp->Tail.Overlay.ListEntry
|
|
*/
|
|
BOOLEAN FindIrpInQueue(ULONG64 ListHeadAddr, ULONG64 IrpAddr)
|
|
{
|
|
return FindObjInListQueue(ListHeadAddr, IrpAddr, "nt!_IRP", "Tail.Overlay.ListEntry");
|
|
}
|
|
|
|
/*
|
|
* FindIrpInDeviceQueue
|
|
*
|
|
* Find Irp in Irp queue linked by Irp->Tail.Overlay.DeviceQueueEntry
|
|
*/
|
|
BOOLEAN FindIrpInDeviceQueue(ULONG64 ListHeadAddr, ULONG64 IrpAddr)
|
|
{
|
|
return FindObjInListQueue(ListHeadAddr, IrpAddr, "nt!_IRP", "Tail.Overlay.DeviceQueueEntry");
|
|
}
|