1847 lines
55 KiB
C
1847 lines
55 KiB
C
|
||
/*++
|
||
|
||
Copyright (C) Microsoft Corporation, 1992 - 1999
|
||
|
||
Module Name:
|
||
|
||
scsikd.c
|
||
|
||
Abstract:
|
||
|
||
Debugger Extension Api for interpretting scsiport structures
|
||
|
||
Author:
|
||
|
||
Peter Wieland (peterwie) 16-Oct-1995
|
||
|
||
Environment:
|
||
|
||
User Mode.
|
||
|
||
Revision History:
|
||
|
||
John Strange (johnstra) 17-Apr-2000 : make 64b friendly
|
||
|
||
--*/
|
||
|
||
#include "pch.h"
|
||
|
||
#include "port.h"
|
||
|
||
FLAG_NAME LuFlags[] = {
|
||
FLAG_NAME(LU_QUEUE_FROZEN), // 0001
|
||
FLAG_NAME(LU_LOGICAL_UNIT_IS_ACTIVE), // 0002
|
||
FLAG_NAME(LU_NEED_REQUEST_SENSE), // 0004
|
||
FLAG_NAME(LU_LOGICAL_UNIT_IS_BUSY), // 0008
|
||
FLAG_NAME(LU_QUEUE_IS_FULL), // 0010
|
||
FLAG_NAME(LU_PENDING_LU_REQUEST), // 0020
|
||
FLAG_NAME(LU_QUEUE_LOCKED), // 0040
|
||
FLAG_NAME(LU_QUEUE_PAUSED), // 0080
|
||
{0,0}
|
||
};
|
||
|
||
FLAG_NAME AdapterFlags[] = {
|
||
FLAG_NAME(PD_DEVICE_IS_BUSY), // 0X00001
|
||
FLAG_NAME(PD_NOTIFICATION_REQUIRED), // 0X00004
|
||
FLAG_NAME(PD_READY_FOR_NEXT_REQUEST), // 0X00008
|
||
FLAG_NAME(PD_FLUSH_ADAPTER_BUFFERS), // 0X00010
|
||
FLAG_NAME(PD_MAP_TRANSFER), // 0X00020
|
||
FLAG_NAME(PD_LOG_ERROR), // 0X00040
|
||
FLAG_NAME(PD_RESET_HOLD), // 0X00080
|
||
FLAG_NAME(PD_HELD_REQUEST), // 0X00100
|
||
FLAG_NAME(PD_RESET_REPORTED), // 0X00200
|
||
FLAG_NAME(PD_PENDING_DEVICE_REQUEST), // 0X00800
|
||
FLAG_NAME(PD_DISCONNECT_RUNNING), // 0X01000
|
||
FLAG_NAME(PD_DISABLE_CALL_REQUEST), // 0X02000
|
||
FLAG_NAME(PD_DISABLE_INTERRUPTS), // 0X04000
|
||
FLAG_NAME(PD_ENABLE_CALL_REQUEST), // 0X08000
|
||
FLAG_NAME(PD_TIMER_CALL_REQUEST), // 0X10000
|
||
FLAG_NAME(PD_WMI_REQUEST), // 0X20000
|
||
{0,0}
|
||
};
|
||
|
||
VOID
|
||
ScsiDumpPdo(
|
||
IN ULONG64 LunAddress,
|
||
IN ULONG Detail,
|
||
IN ULONG Depth
|
||
);
|
||
|
||
VOID
|
||
ScsiDumpFdo(
|
||
ULONG64 Address,
|
||
ULONG Detail,
|
||
ULONG Depth
|
||
);
|
||
|
||
VOID
|
||
ScsiDumpSrbData(
|
||
ULONG64 SrbData,
|
||
ULONG Depth
|
||
);
|
||
VOID
|
||
ScsiDumpAdapterPerfCounters(
|
||
ULONG64 Adapter,
|
||
ULONG Depth
|
||
);
|
||
|
||
VOID
|
||
ScsiDumpScatterGatherList(
|
||
ULONG64 List,
|
||
ULONG Entries,
|
||
ULONG Depth
|
||
);
|
||
|
||
VOID
|
||
ScsiDumpActiveRequests(
|
||
IN ULONG64 ListHead,
|
||
IN ULONG TickCount,
|
||
IN ULONG Depth
|
||
);
|
||
|
||
VOID
|
||
ScsiDumpScsiportExtension(
|
||
IN ULONG64 Address,
|
||
IN ULONG Detail,
|
||
IN ULONG Depth
|
||
);
|
||
|
||
VOID
|
||
ScsiDumpInterruptData(
|
||
IN ULONG64 Address,
|
||
IN ULONG Detail,
|
||
IN ULONG Depth
|
||
);
|
||
|
||
VOID
|
||
ScsiDumpChildren(
|
||
IN ULONG64 Adapter,
|
||
IN ULONG Depth
|
||
);
|
||
|
||
PUCHAR
|
||
SecondsToString(
|
||
ULONG Count
|
||
);
|
||
|
||
VOID
|
||
ScsiDumpLocks(
|
||
ULONG64 CommonExtension,
|
||
ULONG Depth
|
||
);
|
||
|
||
VOID
|
||
ScsiDumpQueuedRequests(
|
||
IN ULONG64 DeviceObject,
|
||
IN ULONG TickCount,
|
||
IN ULONG Depth
|
||
);
|
||
|
||
DECLARE_API(scsiext)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dumps the device extension for a given device object, or dumps the
|
||
given device extension
|
||
|
||
Arguments:
|
||
|
||
args - string containing the address of the device object or device
|
||
extension
|
||
|
||
Return Value:
|
||
|
||
none
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG64 address;
|
||
ULONG result;
|
||
ULONG detail = 0;
|
||
CSHORT Type;
|
||
|
||
//
|
||
// Parse the argument string for the address to dump and for any additional
|
||
// details the caller wishes to have dumped.
|
||
//
|
||
|
||
GetAddressAndDetailLevel64(args, &address, &detail);
|
||
|
||
//
|
||
// The supplied address may be either the address of a device object or the
|
||
// address of a device extension. To distinguish which, we treat the
|
||
// address as a device object and read what would be its type field. If
|
||
// the
|
||
//
|
||
|
||
result = GetFieldData(address,
|
||
"scsiport!_DEVICE_OBJECT",
|
||
"Type",
|
||
sizeof(CSHORT),
|
||
&Type
|
||
);
|
||
if (result) {
|
||
SCSIKD_PRINT_ERROR(result);
|
||
return E_FAIL;
|
||
}
|
||
|
||
//
|
||
// See if the supplied address holds a device object. If it does, read the
|
||
// address of the device extension. Otherwise, we assume the supplied
|
||
// addres holds a device extension and we use it directly.
|
||
//
|
||
|
||
if (Type == IO_TYPE_DEVICE) {
|
||
|
||
result = GetFieldData(address,
|
||
"scsiport!_DEVICE_OBJECT",
|
||
"DeviceExtension",
|
||
sizeof(ULONG64),
|
||
&address
|
||
);
|
||
if (result) {
|
||
SCSIKD_PRINT_ERROR(result);
|
||
return E_FAIL;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Call worker routine to dump the information.
|
||
//
|
||
|
||
ScsiDumpScsiportExtension(address, detail, 0);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
|
||
VOID
|
||
ScsiDumpScsiportExtension(
|
||
IN ULONG64 CommonExtension,
|
||
IN ULONG Detail,
|
||
IN ULONG Depth
|
||
)
|
||
{
|
||
ULONG tmp;
|
||
ULONG result;
|
||
|
||
ULONG64 DeviceObject = 0;
|
||
ULONG IsPdo = 0;
|
||
ULONG IsInitialized = 0;
|
||
ULONG WmiInitialized = 0;
|
||
ULONG WmiMiniPortSupport = 0;
|
||
ULONG CurrentPnpState = 0;
|
||
ULONG PreviousPnpState = 0;
|
||
ULONG IsRemoved = 0;
|
||
ULONG64 LowerDeviceObject = 0;
|
||
ULONG SrbFlags = 0;
|
||
ULONG64 MajorFunction = 0;
|
||
SYSTEM_POWER_STATE CurrentSystemState = 0;
|
||
DEVICE_POWER_STATE CurrentDeviceState = 0;
|
||
DEVICE_POWER_STATE DesiredDeviceState = 0;
|
||
ULONG64 IdleTimer = 0;
|
||
ULONG64 WmiScsiPortRegInfoBuf = 0;
|
||
ULONG WmiScsiPortRegInfoBufSize = 0;
|
||
ULONG PagingPathCount = 0;
|
||
ULONG HibernatePathCount = 0;
|
||
ULONG DumpPathCount = 0;
|
||
|
||
FIELD_INFO deviceFields[] = {
|
||
{"DeviceObject", NULL, 0, COPY, 0, (PVOID) &DeviceObject},
|
||
{"IsPdo", NULL, 0, COPY, 0, (PVOID) &IsPdo},
|
||
{"IsInitialized", NULL, 0, COPY, 0, (PVOID) &IsInitialized},
|
||
{"WmiInitialized", NULL, 0, COPY, 0, (PVOID) &WmiInitialized},
|
||
{"WmiMiniPortSupport", NULL, 0, COPY, 0, (PVOID) &WmiMiniPortSupport},
|
||
{"CurrentPnpState", NULL, 0, COPY, 0, (PVOID) &CurrentPnpState},
|
||
{"PreviousPnpState", NULL, 0, COPY, 0, (PVOID) &PreviousPnpState},
|
||
{"IsRemoved", NULL, 0, COPY, 0, (PVOID) &IsRemoved},
|
||
{"LowerDeviceObject", NULL, 0, COPY, 0, (PVOID) &LowerDeviceObject},
|
||
{"SrbFlags", NULL, 0, COPY, 0, (PVOID) &SrbFlags},
|
||
{"MajorFunction", NULL, 0, COPY, 0, (PVOID) &MajorFunction},
|
||
{"CurrentSystemState", NULL, 0, COPY, 0, (PVOID) &CurrentSystemState},
|
||
{"CurrentDeviceState", NULL, 0, COPY, 0, (PVOID) &CurrentDeviceState},
|
||
{"DesiredDeviceState", NULL, 0, COPY, 0, (PVOID) &DesiredDeviceState},
|
||
{"IdleTimer", NULL, 0, COPY, 0, (PVOID) &IdleTimer},
|
||
{"WmiScsiPortRegInfoBuf", NULL, 0, COPY, 0, (PVOID) &WmiScsiPortRegInfoBuf},
|
||
{"WmiScsiPortRegInfoBufSize", NULL, 0, COPY, 0, (PVOID) &WmiScsiPortRegInfoBufSize},
|
||
{"PagingPathCount", NULL, 0, COPY, 0, (PVOID) &PagingPathCount},
|
||
{"HibernatePathCount", NULL, 0, COPY, 0, (PVOID) &HibernatePathCount},
|
||
{"DumpPathCount", NULL, 0, COPY, 0, (PVOID) &DumpPathCount},
|
||
};
|
||
|
||
SYM_DUMP_PARAM DevSym = {
|
||
sizeof (SYM_DUMP_PARAM),
|
||
"scsiport!_COMMON_EXTENSION",
|
||
DBG_DUMP_NO_PRINT,
|
||
CommonExtension,
|
||
NULL, NULL, NULL,
|
||
sizeof (deviceFields) / sizeof (FIELD_INFO),
|
||
&deviceFields[0]
|
||
};
|
||
|
||
result = Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size);
|
||
if (result) {
|
||
dprintf("%08p: Could not read device object\n", CommonExtension);
|
||
return;
|
||
}
|
||
|
||
xdprintfEx(Depth, ("Scsiport %s device extension at address %p\n",
|
||
IsPdo ? "physical" : "functional", CommonExtension));
|
||
|
||
xdprintfEx(Depth, ("Common Extension:\n"));
|
||
|
||
Depth += 1;
|
||
|
||
tmp = Depth;
|
||
|
||
if(IsInitialized) {
|
||
xdprintfEx(tmp, ("Initialized "));
|
||
tmp = 0;
|
||
}
|
||
|
||
if(IsRemoved) {
|
||
xdprintfEx(tmp, ("Removed " ));
|
||
tmp = 0;
|
||
}
|
||
|
||
switch(IsRemoved) {
|
||
case REMOVE_PENDING: {
|
||
xdprintfEx(tmp, ("RemovePending"));
|
||
tmp = 0;
|
||
break;
|
||
}
|
||
|
||
case REMOVE_COMPLETE: {
|
||
xdprintfEx(tmp, ("RemoveComplete"));
|
||
tmp = 0;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if(WmiMiniPortSupport) {
|
||
if(WmiInitialized) {
|
||
xdprintfEx(tmp, ("WmiInit"));
|
||
} else {
|
||
xdprintfEx(tmp, ("Wmi"));
|
||
}
|
||
tmp = 0;
|
||
}
|
||
|
||
if(tmp == 0) {
|
||
dprintf("\n");
|
||
}
|
||
|
||
tmp = 0;
|
||
|
||
xdprintfEx(Depth, ("DO 0x%08p LowerObject 0x%08p SRB Flags %#08lx\n",
|
||
DeviceObject,
|
||
LowerDeviceObject,
|
||
SrbFlags));
|
||
|
||
xdprintfEx(Depth, ("Current Power (D%d,S%d) Desired Power D%d Idle %#08lx\n",
|
||
CurrentDeviceState - 1,
|
||
CurrentSystemState - 1,
|
||
DesiredDeviceState - 1,
|
||
IdleTimer));
|
||
|
||
xdprintfEx(Depth, ("Current PnP state 0x%x Previous state 0x%x\n",
|
||
CurrentPnpState,
|
||
PreviousPnpState));
|
||
|
||
xdprintfEx(Depth, ("DispatchTable %08p UsePathCounts (P%d, H%d, C%d)\n",
|
||
MajorFunction,
|
||
PagingPathCount,
|
||
HibernatePathCount,
|
||
DumpPathCount));
|
||
|
||
if(WmiMiniPortSupport) {
|
||
xdprintfEx(Depth, ("DispatchTable 0x%08p WmiInfoSize %#08lx\n",
|
||
WmiScsiPortRegInfoBuf,
|
||
WmiScsiPortRegInfoBufSize));
|
||
}
|
||
|
||
if(IsPdo) {
|
||
xdprintfEx(Depth - 1, ("Logical Unit Extension:\n"));
|
||
ScsiDumpPdo(CommonExtension, Detail, Depth);
|
||
} else {
|
||
xdprintfEx(Depth - 1, ("Adapter Extension:\n"));
|
||
ScsiDumpFdo(CommonExtension, Detail, Depth);
|
||
}
|
||
|
||
if(Detail > 1) {
|
||
ScsiDumpLocks(CommonExtension, Depth - 1);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
ScsiDumpFdo(
|
||
ULONG64 Address,
|
||
ULONG Detail,
|
||
ULONG Depth
|
||
)
|
||
{
|
||
ULONG tmp = Depth;
|
||
ULONG result;
|
||
ULONG NumOfFields;
|
||
|
||
ULONG PortNumber = 0;
|
||
UCHAR IsPnp = 0;
|
||
UCHAR IsMiniportDetected = 0;
|
||
UCHAR IsInVirtualSlot = 0;
|
||
UCHAR HasInterrupt = 0;
|
||
UCHAR DisablePower = 0;
|
||
UCHAR DisableStop = 0;
|
||
ULONG64 LowerPdo = 0;
|
||
ULONG64 HwDeviceExtension = 0;
|
||
LONG ActiveRequestCount = 0;
|
||
ULONG NumberOfBuses = 0;
|
||
ULONG MaximumTargetIds = 0;
|
||
ULONG MaxLuCount = 0;
|
||
ULONG Flags = 0;
|
||
ULONG64 NonCachedExtension = 0;
|
||
ULONG IoAddress = 0;
|
||
ULONG InterruptLevel = 0;
|
||
ULONG RealBusNumber = 0;
|
||
ULONG RealSlotNumber = 0;
|
||
LONG PortTimeoutCounter = 0;
|
||
ULONG DpcFlags = 0;
|
||
ULONG SequenceNumber = 0;
|
||
ULONG64 SrbExtensionListHeader = 0;
|
||
ULONG NumberOfRequests = 0;
|
||
ULONG64 QueueTagBitMap = 0;
|
||
ULONG QueueTagHint = 0;
|
||
ULONG HwLogicalUnitExtensionSize = 0;
|
||
ULONG SrbExtensionSize = 0;
|
||
ULONG LargeScatterGatherListSize = 0;
|
||
ULONG64 EmergencySrbData = 0;
|
||
ULONG CommonBufferSize = 0;
|
||
ULONG64 PhysicalCommonBuffer = 0;
|
||
ULONG64 SrbExtensionBuffer = 0;
|
||
ULONG64 InterruptObject = 0;
|
||
ULONG64 InterruptObject2 = 0;
|
||
ULONG64 DmaAdapterObject = 0;
|
||
ULONG64 AllocatedResources = 0;
|
||
ULONG64 TranslatedResources = 0;
|
||
ULONG64 PortConfig = 0;
|
||
ULONG64 PortDeviceMapKey = 0;
|
||
ULONG64 BusDeviceMapKeys = 0;
|
||
UCHAR RemoveTrackingLookasideListInitialized = 0;
|
||
ULONG64 AddrOfMaxQueueTag = 0;
|
||
ULONG64 SrbDataBlockedRequests = 0;
|
||
ULONG64 SrbDataLookasideList = 0;
|
||
ULONG64 MediumScatterGatherLookasideList = 0;
|
||
ULONG64 RemoveTrackingLookasideList = 0;
|
||
ULONG64 InterruptData = 0;
|
||
UCHAR MaxQueueTag = 0;
|
||
|
||
FIELD_INFO deviceFields[] = {
|
||
{"PortNumber", NULL, 0, COPY, 0, (PVOID) &PortNumber},
|
||
{"IsPnp", NULL, 0, COPY, 0, (PVOID) &IsPnp},
|
||
{"IsMiniportDetected", NULL, 0, COPY, 0, (PVOID) &IsMiniportDetected},
|
||
{"IsInVirtualSlot", NULL, 0, COPY, 0, (PVOID) &IsInVirtualSlot},
|
||
{"HasInterrupt", NULL, 0, COPY, 0, (PVOID) &HasInterrupt},
|
||
{"DisablePower", NULL, 0, COPY, 0, (PVOID) &DisablePower},
|
||
{"DisableStop", NULL, 0, COPY, 0, (PVOID) &DisableStop},
|
||
{"LowerPdo", NULL, 0, COPY, 0, (PVOID) &LowerPdo},
|
||
{"HwDeviceExtension", NULL, 0, COPY, 0, (PVOID) &HwDeviceExtension},
|
||
{"ActiveRequestCount", NULL, 0, COPY, 0, (PVOID) &ActiveRequestCount},
|
||
{"NumberOfBuses", NULL, 0, COPY, 0, (PVOID) &NumberOfBuses},
|
||
{"MaximumTargetIds", NULL, 0, COPY, 0, (PVOID) &MaximumTargetIds},
|
||
{"MaxLuCount", NULL, 0, COPY, 0, (PVOID) &MaxLuCount},
|
||
{"Flags", NULL, 0, COPY, 0, (PVOID) &Flags},
|
||
{"NonCachedExtension", NULL, 0, COPY, 0, (PVOID) &NonCachedExtension},
|
||
{"IoAddress", NULL, 0, COPY, 0, (PVOID) &IoAddress},
|
||
{"InterruptLevel", NULL, 0, COPY, 0, (PVOID) &InterruptLevel},
|
||
{"RealBusNumber", NULL, 0, COPY, 0, (PVOID) &RealBusNumber},
|
||
{"RealSlotNumber", NULL, 0, COPY, 0, (PVOID) &RealSlotNumber},
|
||
{"PortTimeoutCounter", NULL, 0, COPY, 0, (PVOID) &PortTimeoutCounter},
|
||
{"DpcFlags", NULL, 0, COPY, 0, (PVOID) &DpcFlags},
|
||
{"SequenceNumber", NULL, 0, COPY, 0, (PVOID) &SequenceNumber},
|
||
{"SrbExtensionListHeader", NULL, 0, COPY, 0, (PVOID) &SrbExtensionListHeader},
|
||
{"NumberOfRequests", NULL, 0, COPY, 0, (PVOID) &NumberOfRequests},
|
||
{"QueueTagBitMap", NULL, 0, COPY, 0, (PVOID) &QueueTagBitMap},
|
||
{"QueueTagHint", NULL, 0, COPY, 0, (PVOID) &QueueTagHint},
|
||
{"HwLogicalUnitExtensionSize", NULL, 0, COPY, 0, (PVOID) &HwLogicalUnitExtensionSize},
|
||
{"SrbExtensionSize", NULL, 0, COPY, 0, (PVOID) &SrbExtensionSize},
|
||
{"LargeScatterGatherListSize", NULL, 0, COPY, 0, (PVOID) &LargeScatterGatherListSize},
|
||
{"EmergencySrbData", NULL, 0, COPY, 0, (PVOID) &EmergencySrbData},
|
||
{"CommonBufferSize", NULL, 0, COPY, 0, (PVOID) &CommonBufferSize},
|
||
{"PhysicalCommonBuffer.QuadPart", NULL, 0, COPY, 0, (PVOID) &PhysicalCommonBuffer},
|
||
{"SrbExtensionBuffer", NULL, 0, COPY, 0, (PVOID) &SrbExtensionBuffer},
|
||
{"InterruptObject", NULL, 0, COPY, 0, (PVOID) &InterruptObject},
|
||
{"InterruptObject2", NULL, 0, COPY, 0, (PVOID) &InterruptObject2},
|
||
{"DmaAdapterObject", NULL, 0, COPY, 0, (PVOID) &DmaAdapterObject},
|
||
{"AllocatedResources", NULL, 0, COPY, 0, (PVOID) &AllocatedResources},
|
||
{"TranslatedResources", NULL, 0, COPY, 0, (PVOID) &TranslatedResources},
|
||
{"PortConfig", NULL, 0, COPY, 0, (PVOID) &PortConfig},
|
||
{"PortDeviceMapKey", NULL, 0, COPY, 0, (PVOID) &PortDeviceMapKey},
|
||
{"BusDeviceMapKeys", NULL, 0, COPY, 0, (PVOID) &BusDeviceMapKeys},
|
||
{"CommonExtension.RemoveTrackingLookasideListInitialized", NULL, 0, COPY, 0, (PVOID) &RemoveTrackingLookasideListInitialized},
|
||
{"MaxQueueTag", NULL, 0, ADDROF, 0, NULL},
|
||
{"SrbDataBlockedRequests", NULL, 0, ADDROF, 0, NULL},
|
||
{"SrbDataLookasideList", NULL, 0, ADDROF, 0, NULL},
|
||
{"MediumScatterGatherLookasideList", NULL, 0, ADDROF, 0, NULL},
|
||
{"CommonExtension.RemoveTrackingLookasideList", NULL, 0, ADDROF, 0, NULL},
|
||
{"InterruptData", NULL, 0, ADDROF, 0, NULL},
|
||
};
|
||
|
||
SYM_DUMP_PARAM DevSym = {
|
||
sizeof (SYM_DUMP_PARAM),
|
||
"scsiport!_ADAPTER_EXTENSION",
|
||
DBG_DUMP_NO_PRINT,
|
||
Address,
|
||
NULL, NULL, NULL,
|
||
sizeof (deviceFields) / sizeof (FIELD_INFO),
|
||
&deviceFields[0]
|
||
};
|
||
|
||
result = Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size);
|
||
if (result) {
|
||
SCSIKD_PRINT_ERROR(result);
|
||
return;
|
||
}
|
||
|
||
result = GetFieldData(Address,
|
||
"scsiport!_ADAPTER_EXTENSION",
|
||
"MaxQueueTag",
|
||
sizeof(UCHAR),
|
||
&MaxQueueTag
|
||
);
|
||
if (result) {
|
||
SCSIKD_PRINT_ERROR(result);
|
||
return;
|
||
}
|
||
|
||
NumOfFields = sizeof (deviceFields) / sizeof (FIELD_INFO);
|
||
InterruptData = deviceFields[NumOfFields-1].address;
|
||
RemoveTrackingLookasideList = deviceFields[NumOfFields-2].address;
|
||
MediumScatterGatherLookasideList = deviceFields[NumOfFields-3].address;
|
||
SrbDataLookasideList = deviceFields[NumOfFields-4].address;
|
||
SrbDataBlockedRequests = deviceFields[NumOfFields-5].address;
|
||
AddrOfMaxQueueTag = deviceFields[NumOfFields-6].address;
|
||
|
||
xdprintfEx(Depth, ("Port %d ", PortNumber));
|
||
|
||
if(IsPnp) {
|
||
xdprintfEx(tmp, ("IsPnp "));
|
||
tmp = 0;
|
||
}
|
||
|
||
if(IsMiniportDetected) {
|
||
xdprintfEx(tmp, ("MpDetected "));
|
||
tmp = 0;
|
||
}
|
||
|
||
if(IsInVirtualSlot) {
|
||
xdprintfEx(tmp, ("VirtualSlot "));
|
||
tmp = 0;
|
||
}
|
||
|
||
if(HasInterrupt) {
|
||
xdprintfEx(tmp, ("HasInterrupt"));
|
||
tmp = 0;
|
||
}
|
||
|
||
if(DisablePower) {
|
||
xdprintfEx(tmp, ("NoPower"));
|
||
tmp = 0;
|
||
}
|
||
|
||
if(DisableStop) {
|
||
xdprintfEx(tmp, ("NoStop"));
|
||
tmp = 0;
|
||
}
|
||
|
||
dprintf("\n");
|
||
|
||
xdprintfEx(Depth, ("LowerPdo 0x%08p HwDevExt 0x%08p Active Requests 0x%08lx\n",
|
||
LowerPdo,
|
||
HwDeviceExtension,
|
||
ActiveRequestCount));
|
||
|
||
xdprintfEx(Depth, ("MaxBus 0x%02x MaxTarget 0x%02x MaxLun 0x%02x\n",
|
||
NumberOfBuses,
|
||
MaximumTargetIds,
|
||
MaxLuCount));
|
||
|
||
DumpFlags(Depth, "Port Flags", Flags, AdapterFlags);
|
||
|
||
xdprintfEx(Depth, ("NonCacheExt 0x%08p IoBase 0x%08x Int 0x%02x\n",
|
||
NonCachedExtension,
|
||
IoAddress,
|
||
InterruptLevel));
|
||
|
||
xdprintfEx(Depth, ("RealBus# 0x%0x RealSlot# 0x%0x\n",
|
||
RealBusNumber,
|
||
RealSlotNumber));
|
||
|
||
xdprintfEx(Depth, ("Timeout 0x%08x DpcFlags 0x%08x Sequence 0x%08x\n",
|
||
PortTimeoutCounter,
|
||
DpcFlags,
|
||
SequenceNumber));
|
||
|
||
xdprintfEx(Depth, ("Srb Ext Header 0x%08p No. Requests 0x%08lx\n",
|
||
SrbExtensionListHeader, NumberOfRequests));
|
||
|
||
xdprintfEx(Depth, ("QueueTag BitMap 0x%08p Hint 0x%08lx\n",
|
||
QueueTagBitMap, QueueTagHint));
|
||
|
||
xdprintfEx(Depth, ("MaxQueueTag 0x%2x (@0x%08p)\n",
|
||
MaxQueueTag, AddrOfMaxQueueTag));
|
||
|
||
xdprintfEx(Depth, ("LuExt Size 0x%08lx SrbExt Size 0x%08lx\n",
|
||
HwLogicalUnitExtensionSize,
|
||
SrbExtensionSize));
|
||
|
||
xdprintfEx(Depth + 1, ("SG List Size - Small %d Large %d\n",
|
||
SP_SMALL_PHYSICAL_BREAK_VALUE,
|
||
LargeScatterGatherListSize));
|
||
|
||
Depth++;
|
||
|
||
xdprintfEx(Depth, ("Emergency - SrbData 0x%08p Blocked List @0x%08p\n",
|
||
EmergencySrbData,
|
||
SrbDataBlockedRequests));
|
||
|
||
xdprintfEx(Depth, ("CommonBuff - Size: 0x%08lx PA: 0x%016I64x VA: 0x%08p\n",
|
||
CommonBufferSize,
|
||
PhysicalCommonBuffer,
|
||
SrbExtensionBuffer));
|
||
|
||
xdprintfEx(Depth, ("Ke Objects - Int1: 0x%08p Int2: 0x%08p Dma: 0x%08p\n",
|
||
InterruptObject,
|
||
InterruptObject2,
|
||
DmaAdapterObject));
|
||
|
||
xdprintfEx(Depth, ("Lookaside - SrbData @ 0x%08p SgList @0x%08p Remove: @0x%08p\n",
|
||
SrbDataLookasideList,
|
||
MediumScatterGatherLookasideList,
|
||
(RemoveTrackingLookasideListInitialized ?
|
||
RemoveTrackingLookasideList : 0)));
|
||
|
||
xdprintfEx(Depth, ("Resources - Raw: 0x%08p Translated: 0x%08p\n",
|
||
AllocatedResources,
|
||
TranslatedResources));
|
||
|
||
xdprintfEx(Depth, ("Port Config %08p\n", PortConfig));
|
||
|
||
xdprintfEx(Depth, ("DeviceMap Handles: Port %p Busses %p\n",
|
||
PortDeviceMapKey, BusDeviceMapKeys));
|
||
|
||
Depth--;
|
||
ScsiDumpInterruptData(InterruptData,
|
||
Detail,
|
||
Depth);
|
||
|
||
ScsiDumpAdapterPerfCounters(Address, Depth);
|
||
|
||
ScsiDumpChildren(Address, Depth);
|
||
return;
|
||
}
|
||
|
||
|
||
VOID
|
||
ScsiDumpChildren(
|
||
IN ULONG64 AdapterExtensionAddr,
|
||
IN ULONG Depth
|
||
)
|
||
|
||
{
|
||
ULONG i;
|
||
ULONG64 realLun;
|
||
ULONG64 realLuns[8];
|
||
ULONG64 lun;
|
||
UCHAR CurrentPnpState=0, PreviousPnpState=0;
|
||
ULONG CurrentDeviceState=0;
|
||
ULONG DesiredDeviceState=0, CurrentSystemState=0;
|
||
ULONG64 DeviceObject=0, NextLogicalUnit=0;
|
||
ULONG result;
|
||
UCHAR PathId=0, TargetId=0, Lun=0;
|
||
UCHAR IsClaimed=0, IsMissing=0, IsEnumerated=0, IsVisible=0, IsMismatched=0;
|
||
ULONG64 b6, b7, b8;
|
||
|
||
InitTypeRead(AdapterExtensionAddr, scsiport!_ADAPTER_EXTENSION);
|
||
realLuns[0] = ReadField(LogicalUnitList[0].List);
|
||
realLuns[1] = ReadField(LogicalUnitList[1].List);
|
||
realLuns[2] = ReadField(LogicalUnitList[2].List);
|
||
realLuns[3] = ReadField(LogicalUnitList[3].List);
|
||
realLuns[4] = ReadField(LogicalUnitList[4].List);
|
||
realLuns[5] = ReadField(LogicalUnitList[5].List);
|
||
realLuns[6] = ReadField(LogicalUnitList[6].List);
|
||
realLuns[7] = ReadField(LogicalUnitList[7].List);
|
||
|
||
Depth++;
|
||
|
||
for (i = 0; i < NUMBER_LOGICAL_UNIT_BINS; i++) {
|
||
|
||
realLun = realLuns[i];
|
||
|
||
while ((realLun != 0) && (!CheckControlC())) {
|
||
|
||
FIELD_INFO deviceFields[] = {
|
||
{"PathId", NULL, 0, COPY, 0, (PVOID) &PathId},
|
||
{"TargetId", NULL, 0, COPY, 0, (PVOID) &TargetId},
|
||
{"IsClaimed", NULL, 0, COPY, 0, (PVOID) &IsClaimed},
|
||
{"IsMissing", NULL, 0, COPY, 0, (PVOID) &IsMissing},
|
||
{"IsEnumerated", NULL, 0, COPY, 0, (PVOID) &IsEnumerated},
|
||
{"IsVisible", NULL, 0, COPY, 0, (PVOID) &IsVisible},
|
||
{"IsMismatched", NULL, 0, COPY, 0, (PVOID) &IsMismatched},
|
||
{"DeviceObject", NULL, 0, COPY, 0, (PVOID) &DeviceObject},
|
||
{"NextLogicalUnit", NULL, 0, COPY, 0, (PVOID) &NextLogicalUnit},
|
||
{"CommonExtension.CurrentPnpState", NULL, 0, COPY, 0, (PVOID) &CurrentPnpState},
|
||
{"CommonExtension.PreviousPnpState" , NULL, 0, COPY, 0, (PVOID) &PreviousPnpState},
|
||
{"CommonExtension.CurrentDeviceState", NULL, 0, COPY, 0, (PVOID) &CurrentDeviceState},
|
||
{"CommonExtension.DesiredDeviceState", NULL, 0, COPY, 0, (PVOID) &DesiredDeviceState},
|
||
{"CommonExtension.CurrentSystemState", NULL, 0, COPY, 0, (PVOID) &CurrentSystemState},
|
||
};
|
||
SYM_DUMP_PARAM DevSym = {
|
||
sizeof (SYM_DUMP_PARAM),
|
||
"scsiport!_LOGICAL_UNIT_EXTENSION",
|
||
DBG_DUMP_NO_PRINT,
|
||
realLun,
|
||
NULL, NULL, NULL,
|
||
sizeof (deviceFields) / sizeof (FIELD_INFO),
|
||
&deviceFields[0]
|
||
};
|
||
|
||
xdprintfEx(Depth, ("LUN "));
|
||
dprintf("%08p ", realLun);
|
||
|
||
if ((Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size))) {
|
||
dprintf("%08lx: Could not read device object\n", realLun);
|
||
return;
|
||
}
|
||
|
||
result = (ULONG) InitTypeRead(realLun, scsiport!_LOGICAL_UNIT_EXTENSION);
|
||
if (result != 0) {
|
||
dprintf("could not init read type (%x)\n", result);
|
||
return;
|
||
}
|
||
lun = ReadField(Lun);
|
||
Lun = (UCHAR) lun;
|
||
#if 0
|
||
PathId = ReadField(PathId);
|
||
TargetId = ReadField(TargetId);
|
||
IsClaimed = ReadField(IsClaimed);
|
||
IsMissing = ReadField(IsMissing);
|
||
IsEnumerated = ReadField(IsEnumerated);
|
||
IsVisible = ReadField(IsVisible);
|
||
IsMismatched = ReadField(IsMismatched);
|
||
#endif
|
||
dprintf("@ (%3d,%3d,%3d) %c%c%c%c%c pnp(%02x/%02x) pow(%d%c,%d) DevObj %08p\n",
|
||
PathId,
|
||
TargetId,
|
||
Lun,
|
||
(IsClaimed ? 'c' : ' '),
|
||
(IsMissing ? 'm' : ' '),
|
||
(IsEnumerated ? 'e' : ' '),
|
||
(IsVisible ? 'v' : ' '),
|
||
(IsMismatched ? 'r' : ' '),
|
||
CurrentPnpState,
|
||
PreviousPnpState,
|
||
CurrentDeviceState - 1,
|
||
((DesiredDeviceState == PowerDeviceUnspecified) ? ' ' : '*'),
|
||
CurrentSystemState - 1,
|
||
DeviceObject);
|
||
|
||
realLun = ReadField(NextLogicalUnit);
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
ScsiDumpInterruptData(
|
||
IN ULONG64 Address,
|
||
IN ULONG Detail,
|
||
IN ULONG Depth
|
||
)
|
||
|
||
{
|
||
ULONG result;
|
||
ULONG NumOfFields;
|
||
|
||
//
|
||
// Architecture independent fields declarations.
|
||
//
|
||
//
|
||
|
||
ULONG InterruptFlags;
|
||
ULONG64 CompletedRequests;
|
||
ULONG64 AddrOfCompletedRequests;
|
||
ULONG64 ReadyLogicalUnit;
|
||
ULONG64 WmiMiniPortRequests;
|
||
|
||
FIELD_INFO deviceFields[] = {
|
||
{"InterruptFlags", NULL, 0, COPY, 0, (PVOID) &InterruptFlags},
|
||
{"ReadyLogicalUnit", NULL, 0, COPY, 0, (PVOID) &ReadyLogicalUnit},
|
||
{"WmiMiniPortRequests", NULL, 0, COPY, 0, (PVOID) &WmiMiniPortRequests},
|
||
{"CompletedRequests", NULL, 0, ADDROF, 0, NULL},
|
||
};
|
||
|
||
SYM_DUMP_PARAM DevSym = {
|
||
sizeof (SYM_DUMP_PARAM),
|
||
"scsiport!_INTERRUPT_DATA",
|
||
DBG_DUMP_NO_PRINT,
|
||
Address,
|
||
NULL, NULL, NULL,
|
||
sizeof (deviceFields) / sizeof (FIELD_INFO),
|
||
&deviceFields[0]
|
||
};
|
||
|
||
//
|
||
// Read in the top-level field data. Quit on failure.
|
||
//
|
||
|
||
result = Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size);
|
||
if (result) {
|
||
dprintf("error reading INTERRUPT_DATA @ %08p\n", Address);
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Get address-of information.
|
||
//
|
||
|
||
NumOfFields = sizeof (deviceFields) / sizeof (FIELD_INFO);
|
||
AddrOfCompletedRequests = deviceFields[NumOfFields-1].address;
|
||
|
||
//
|
||
// Do a separate get of the CompleteRequests field. This is necessary
|
||
// because the typedump Ioctl doesn't like retreiving both the addr-of
|
||
// and the data-of a field.
|
||
//
|
||
|
||
result = GetFieldData(Address,
|
||
"scsiport!_INTERRUPT_DATA",
|
||
"CompletedRequests",
|
||
sizeof(ULONG64),
|
||
&CompletedRequests
|
||
);
|
||
if (result) {
|
||
dprintf("error (%08x): @ %s %d\n", result, __FILE__, __LINE__);
|
||
return;
|
||
}
|
||
|
||
xdprintfEx(Depth, ("Interrupt Data @0x%08p:\n", Address));
|
||
|
||
Depth++;
|
||
|
||
DumpFlags(Depth, "Flags", InterruptFlags, AdapterFlags);
|
||
|
||
xdprintfEx(Depth, ("Ready LUN 0x%08p Wmi Events 0x%08p\n",
|
||
ReadyLogicalUnit,
|
||
WmiMiniPortRequests));
|
||
|
||
{
|
||
ULONG count = 0;
|
||
ULONG64 request = CompletedRequests;
|
||
|
||
xdprintfEx(Depth, ("Completed Request List (@0x%08p): ",
|
||
AddrOfCompletedRequests));
|
||
|
||
Depth += 1;
|
||
|
||
while((request != 0) && (!CheckControlC())) {
|
||
ULONG64 CompletedRequests;
|
||
|
||
if(Detail != 0) {
|
||
if(count == 0) {
|
||
dprintf("\n");
|
||
}
|
||
xdprintfEx(Depth, ("SrbData 0x%08p ", request));
|
||
}
|
||
|
||
count++;
|
||
|
||
result = GetFieldData(request,
|
||
"scsiport!_SRB_DATA",
|
||
"CompletedRequests",
|
||
sizeof(ULONG64),
|
||
&CompletedRequests
|
||
);
|
||
if (result) {
|
||
dprintf("error (%08x): @ %s %d\n", result, __FILE__, __LINE__);
|
||
return;
|
||
}
|
||
|
||
if(Detail != 0) {
|
||
ULONG64 CurrentSrb, CurrentIrp;
|
||
result = GetFieldData(request,
|
||
"scsiport!_SRB_DATA",
|
||
"CurrentSrb",
|
||
sizeof(ULONG64),
|
||
&CurrentSrb
|
||
);
|
||
if (result) {
|
||
dprintf("error (%08x): @ %s %d\n", result, __FILE__, __LINE__);
|
||
return;
|
||
}
|
||
result = GetFieldData(request,
|
||
"scsiport!_SRB_DATA",
|
||
"CurrentIrp",
|
||
sizeof(ULONG64),
|
||
&CurrentIrp
|
||
);
|
||
if (result) {
|
||
dprintf("error (%08x): @ %s %d\n", result, __FILE__, __LINE__);
|
||
return;
|
||
}
|
||
dprintf("Srb 0x%08p Irp 0x%08p\n",
|
||
CurrentSrb,
|
||
CurrentIrp);
|
||
}
|
||
|
||
request = CompletedRequests;
|
||
}
|
||
|
||
Depth -= 1;
|
||
|
||
if((Detail == 0) || (count == 0)) {
|
||
dprintf("%d entries\n", count);
|
||
} else {
|
||
xdprintfEx(Depth + 1, ("%d entries\n", count));
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
VOID
|
||
ScsiDumpPdo(
|
||
IN ULONG64 LunAddress,
|
||
IN ULONG Detail,
|
||
IN ULONG Depth
|
||
)
|
||
{
|
||
ULONG result;
|
||
ULONG Fields;
|
||
|
||
UCHAR PathId;
|
||
UCHAR TargetId;
|
||
UCHAR Lun;
|
||
ULONG PortNumber;
|
||
UCHAR IsClaimed;
|
||
UCHAR IsMissing;
|
||
UCHAR IsEnumerated;
|
||
UCHAR IsVisible;
|
||
UCHAR IsMismatched;
|
||
ULONG LunLuFlags;
|
||
UCHAR RetryCount;
|
||
ULONG CurrentKey;
|
||
ULONG QueueLockCount;
|
||
ULONG QueuePauseCount;
|
||
ULONG64 HwLogicalUnitExtension;
|
||
ULONG64 AdapterExtension;
|
||
LONG RequestTimeoutCounter;
|
||
ULONG64 NextLogicalUnit;
|
||
ULONG64 ReadyLogicalUnit;
|
||
ULONG64 PendingRequest;
|
||
ULONG64 BusyRequest;
|
||
ULONG64 CurrentUntaggedRequest;
|
||
ULONG64 CompletedAbort;
|
||
ULONG64 AbortSrb;
|
||
ULONG QueueCount;
|
||
ULONG MaxQueueDepth;
|
||
ULONG64 TargetDeviceMapKey;
|
||
ULONG64 LunDeviceMapKey;
|
||
ULONG64 ActiveFailedRequest;
|
||
ULONG64 BlockedFailedRequest;
|
||
ULONG64 RequestSenseIrp;
|
||
ULONG64 BypassSrbDataList_Next;
|
||
ULONG64 RequestList_Flink;
|
||
ULONG64 CommonExtension_DeviceObject;
|
||
ULONG64 AddrOf_InquiryData;
|
||
ULONG64 AddrOf_RequestSenseSrb;
|
||
ULONG64 AddrOf_RequestSenseMdl;
|
||
ULONG64 AddrOf_BypassSrbDataBlocks;
|
||
ULONG64 AddrOf_RequestList;
|
||
|
||
ULONG Adapter_TickCount;
|
||
|
||
FIELD_INFO deviceFields[] = {
|
||
{"PathId", NULL, 0, COPY, 0, (PVOID) &PathId},
|
||
{"TargetId", NULL, 0, COPY, 0, (PVOID) &TargetId},
|
||
{"Lun", NULL, 0, COPY, 0, (PVOID) &Lun},
|
||
{"PortNumber", NULL, 0, COPY, 0, (PVOID) &PortNumber},
|
||
{"IsClaimed", NULL, 0, COPY, 0, (PVOID) &IsClaimed},
|
||
{"IsMissing", NULL, 0, COPY, 0, (PVOID) &IsMissing},
|
||
{"IsEnumerated", NULL, 0, COPY, 0, (PVOID) &IsEnumerated},
|
||
{"IsVisible", NULL, 0, COPY, 0, (PVOID) &IsVisible},
|
||
{"IsMismatched", NULL, 0, COPY, 0, (PVOID) &IsMismatched},
|
||
{"LuFlags", NULL, 0, COPY, 0, (PVOID) &LunLuFlags},
|
||
{"RetryCount", NULL, 0, COPY, 0, (PVOID) &RetryCount},
|
||
{"CurrentKey", NULL, 0, COPY, 0, (PVOID) &CurrentKey},
|
||
{"QueueCount", NULL, 0, COPY, 0, (PVOID) &QueueCount},
|
||
{"QueueLockCount", NULL, 0, COPY, 0, (PVOID) &QueueLockCount},
|
||
{"QueuePauseCount", NULL, 0, COPY, 0, (PVOID) &QueuePauseCount},
|
||
{"HwLogicalUnitExtension", NULL, 0, COPY, 0, (PVOID) &HwLogicalUnitExtension},
|
||
{"AdapterExtension", NULL, 0, COPY, 0, (PVOID) &AdapterExtension},
|
||
{"RequestTimeoutCounter", NULL, 0, COPY, 0, (PVOID) &RequestTimeoutCounter},
|
||
{"NextLogicalUnit", NULL, 0, COPY, 0, (PVOID) &NextLogicalUnit},
|
||
{"ReadyLogicalUnit", NULL, 0, COPY, 0, (PVOID) &ReadyLogicalUnit},
|
||
{"PendingRequest", NULL, 0, COPY, 0, (PVOID) &PendingRequest},
|
||
{"BusyRequest", NULL, 0, COPY, 0, (PVOID) &BusyRequest},
|
||
{"CurrentUntaggedRequest", NULL, 0, COPY, 0, (PVOID) &CurrentUntaggedRequest},
|
||
{"CompletedAbort", NULL, 0, COPY, 0, (PVOID) &CompletedAbort},
|
||
{"AbortSrb", NULL, 0, COPY, 0, (PVOID) &AbortSrb},
|
||
{"MaxQueueDepth", NULL, 0, COPY, 0, (PVOID) &MaxQueueDepth},
|
||
{"TargetDeviceMapKey", NULL, 0, COPY, 0, (PVOID) &TargetDeviceMapKey},
|
||
{"LunDeviceMapKey", NULL, 0, COPY, 0, (PVOID) &LunDeviceMapKey},
|
||
{"ActiveFailedRequest", NULL, 0, COPY, 0, (PVOID) &ActiveFailedRequest},
|
||
{"BlockedFailedRequest", NULL, 0, COPY, 0, (PVOID) &BlockedFailedRequest},
|
||
{"RequestSenseIrp", NULL, 0, COPY, 0, (PVOID) &RequestSenseIrp},
|
||
{"BypassSrbDataList.Next", NULL, 0, COPY, 0, (PVOID) &BypassSrbDataList_Next},
|
||
{"InquiryData", NULL, 0, ADDROF, 0, NULL},
|
||
{"RequestSenseSrb", NULL, 0, ADDROF, 0, NULL},
|
||
{"RequestSenseMdl", NULL, 0, ADDROF, 0, NULL},
|
||
{"BypassSrbDataBlocks", NULL, 0, ADDROF, 0, NULL},
|
||
{"RequestList", NULL, 0, ADDROF, 0, NULL},
|
||
};
|
||
|
||
SYM_DUMP_PARAM DevSym = {
|
||
sizeof (SYM_DUMP_PARAM),
|
||
"scsiport!_LOGICAL_UNIT_EXTENSION",
|
||
DBG_DUMP_NO_PRINT,
|
||
LunAddress,
|
||
NULL, NULL, NULL,
|
||
sizeof (deviceFields) / sizeof (FIELD_INFO),
|
||
&deviceFields[0]
|
||
};
|
||
|
||
result = Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size);
|
||
if (result) {
|
||
dprintf("%08p: Could not read _LOGICAL_UNIT_EXTENSION\n", LunAddress);
|
||
return;
|
||
}
|
||
|
||
Fields = sizeof (deviceFields) / sizeof (FIELD_INFO);
|
||
AddrOf_RequestList = deviceFields[Fields-1].address;
|
||
AddrOf_BypassSrbDataBlocks = deviceFields[Fields-2].address;
|
||
AddrOf_RequestSenseMdl = deviceFields[Fields-3].address;
|
||
AddrOf_RequestSenseSrb = deviceFields[Fields-4].address;
|
||
AddrOf_InquiryData = deviceFields[Fields-5].address;
|
||
|
||
result = GetFieldData(AddrOf_RequestList,
|
||
"scsiport!LIST_ENTRY",
|
||
"Flink",
|
||
sizeof(ULONG64),
|
||
&RequestList_Flink);
|
||
if (result) {
|
||
dprintf("Error reading request list from adapter extension @%p\n", AdapterExtension);
|
||
return;
|
||
}
|
||
|
||
result = GetFieldData(AdapterExtension,
|
||
"scsiport!_ADAPTER_EXTENSION",
|
||
"TickCount",
|
||
sizeof(ULONG),
|
||
&Adapter_TickCount);
|
||
if (result) {
|
||
dprintf("Error reading TickCount from adapter extension @%p\n", AdapterExtension);
|
||
return;
|
||
}
|
||
|
||
InitTypeRead(LunAddress, scsiport!_LOGICAL_UNIT_EXTENSION);
|
||
QueueCount = (ULONG)ReadField(QueueCount);
|
||
|
||
xdprintfEx(Depth, ("Address (%d, %d, %d, %d) %s %s %s %s %s\n",
|
||
PortNumber, PathId, TargetId, Lun,
|
||
(IsClaimed ? "Claimed" : ""),
|
||
(IsMissing ? "Missing" : ""),
|
||
(IsEnumerated ? "Enumerated" : ""),
|
||
(IsVisible ? "Visible" : ""),
|
||
(IsMismatched ? "Mismatched" : "")));
|
||
|
||
//
|
||
// Print out the various LU flags
|
||
//
|
||
|
||
DumpFlags(Depth, "LuFlags", LunLuFlags, LuFlags);
|
||
|
||
xdprintfEx(Depth, ("Retry 0x%02x Key 0x%08lx\n",
|
||
RetryCount, CurrentKey));
|
||
|
||
xdprintfEx(Depth, ("Lock 0x%08lx Pause 0x%08lx CurrentLock: 0x%p\n",
|
||
QueueLockCount, QueuePauseCount, NULL));
|
||
|
||
xdprintfEx(Depth, ("HwLuExt 0x%08p Adapter 0x%08p Timeout 0x%08x\n",
|
||
HwLogicalUnitExtension, AdapterExtension,
|
||
RequestTimeoutCounter));
|
||
|
||
xdprintfEx(Depth, ("NextLun 0x%p ReadyLun 0x%p\n",
|
||
NextLogicalUnit, ReadyLogicalUnit));
|
||
|
||
xdprintfEx(Depth, ("Pending 0x%p Busy 0x%p Untagged 0x%p\n",
|
||
PendingRequest,
|
||
BusyRequest,
|
||
CurrentUntaggedRequest));
|
||
|
||
if((CompletedAbort != 0) || (AbortSrb != 0)) {
|
||
xdprintfEx(Depth, ("Abort 0x%p Completed Abort 0x%p\n",
|
||
AbortSrb, CompletedAbort));
|
||
}
|
||
|
||
xdprintfEx(Depth, ("Q Depth %03d (%03d) InquiryData 0x%p\n",
|
||
QueueCount, MaxQueueDepth, AddrOf_InquiryData));
|
||
|
||
xdprintfEx(Depth, ("DeviceMap Keys: Target %#08lx Lun %#08lx\n",
|
||
TargetDeviceMapKey, LunDeviceMapKey));
|
||
|
||
xdprintfEx(Depth, ("Bypass SRB_DATA blocks %d @ %08p List %08p\n",
|
||
NUMBER_BYPASS_SRB_DATA_BLOCKS,
|
||
AddrOf_BypassSrbDataBlocks,
|
||
BypassSrbDataList_Next));
|
||
|
||
if((ActiveFailedRequest != 0) ||
|
||
(BlockedFailedRequest != 0)) {
|
||
xdprintfEx(Depth, ("Failed Requests - "));
|
||
|
||
if(ActiveFailedRequest != 0) {
|
||
dprintf("Active %#08I ", ActiveFailedRequest);
|
||
}
|
||
|
||
if(BlockedFailedRequest != 0) {
|
||
dprintf("Blocked %#08I ", BlockedFailedRequest);
|
||
}
|
||
dprintf("\n");
|
||
}
|
||
|
||
xdprintfEx(Depth, ("RS Irp %p Srb @ %p MDL @ %p\n",
|
||
RequestSenseIrp,
|
||
AddrOf_RequestSenseSrb,
|
||
AddrOf_RequestSenseMdl));
|
||
|
||
if((RequestList_Flink) == AddrOf_RequestList) {
|
||
xdprintfEx(Depth, ("Request List @0x%p is empty\n",
|
||
AddrOf_RequestList));
|
||
} else {
|
||
xdprintfEx(Depth, ("Request list @0x%p:\n", AddrOf_RequestList));
|
||
ScsiDumpActiveRequests(AddrOf_RequestList,
|
||
Adapter_TickCount,
|
||
Depth + 2);
|
||
}
|
||
|
||
if (Detail != 0) {
|
||
|
||
//
|
||
// The caller wants additional detail. Dump the queued requests.
|
||
// Extract the address of the device object from the common extension
|
||
// and pass it to the routine that dumps queued requests.
|
||
//
|
||
|
||
ULONG64 DeviceObject;
|
||
result = GetFieldData(LunAddress,
|
||
"scsiport!_COMMON_EXTENSION",
|
||
"DeviceObject",
|
||
sizeof(ULONG64),
|
||
&DeviceObject);
|
||
if (result) {
|
||
dprintf("Error reading DeviceObject @%p\n", LunAddress);
|
||
return;
|
||
}
|
||
|
||
xdprintfEx(Depth, ("Queued requests:\n"));
|
||
ScsiDumpQueuedRequests(
|
||
DeviceObject,
|
||
Adapter_TickCount,
|
||
Depth + 2
|
||
);
|
||
}
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
ScsiDumpActiveRequests(
|
||
IN ULONG64 ListHead,
|
||
IN ULONG TickCount,
|
||
IN ULONG Depth
|
||
)
|
||
{
|
||
ULONG result;
|
||
|
||
ULONG64 lastEntry = 0;
|
||
ULONG64 entry = 0;
|
||
ULONG64 realEntry = 0;
|
||
ULONG64 CurrentSrb = 0;
|
||
ULONG64 CurrentIrp = 0;
|
||
ULONG64 RequestList = 0;
|
||
ULONG OffsetOfRequestList = 0;
|
||
ULONG SrbTickCount = 0;
|
||
ULONG Key = 0;
|
||
|
||
FIELD_INFO deviceFields[] = {
|
||
{"CurrentSrb", NULL, 0, COPY, 0, (PVOID) &CurrentSrb},
|
||
{"CurrentIrp", NULL, 0, COPY, 0, (PVOID) &CurrentIrp},
|
||
{"TickCount", NULL, 0, COPY, 0, (PVOID) &SrbTickCount},
|
||
{"RequestList", NULL, 0, ADDROF, 0, NULL},
|
||
};
|
||
|
||
SYM_DUMP_PARAM DevSym = {
|
||
sizeof (SYM_DUMP_PARAM),
|
||
"scsiport!_SRB_DATA",
|
||
DBG_DUMP_NO_PRINT,
|
||
0,
|
||
NULL, NULL, NULL,
|
||
sizeof (deviceFields) / sizeof (FIELD_INFO),
|
||
&deviceFields[0]
|
||
};
|
||
|
||
result = GetFieldOffset("scsiport!_SRB_DATA",
|
||
"RequestList",
|
||
&OffsetOfRequestList);
|
||
if (result) {
|
||
dprintf("failed to get offset of request list (%08X)\n", result);
|
||
return;
|
||
}
|
||
|
||
entry = ListHead;
|
||
realEntry = entry;
|
||
|
||
InitTypeRead(ListHead, nt!_LIST_ENTRY);
|
||
lastEntry = ReadField(Blink);
|
||
|
||
xdprintfEx(Depth, ("Tick count is %d\n", TickCount));
|
||
|
||
do {
|
||
|
||
ULONG64 realSrbData;
|
||
ULONG result;
|
||
|
||
GetFieldData(realEntry,
|
||
"scsiport!_LIST_ENTRY",
|
||
"Flink",
|
||
sizeof(ULONG64),
|
||
&entry);
|
||
|
||
//
|
||
// entry points to the list entry element of the srb data. Calculate
|
||
// the address of the start of the srb data block.
|
||
//
|
||
|
||
realSrbData = entry - OffsetOfRequestList;
|
||
|
||
xdprintfEx(Depth, ("SrbData %08p ", realSrbData));
|
||
|
||
//
|
||
// Read the SRB_DATA information we need.
|
||
//
|
||
|
||
DevSym.addr = realSrbData;
|
||
if ((Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size))) {
|
||
dprintf("%08p: Could not read device object\n", realSrbData);
|
||
return;
|
||
}
|
||
RequestList = deviceFields[3].address;
|
||
|
||
|
||
InitTypeRead(CurrentSrb, scsiport!_SCSI_REQUEST_BLOCK);
|
||
Key = (ULONG)ReadField(QueueSortKey);
|
||
|
||
//
|
||
// Update realEntry.
|
||
//
|
||
|
||
realEntry = RequestList;
|
||
|
||
dprintf("Srb %08p Irp %08p Key %x %s\n",
|
||
CurrentSrb,
|
||
CurrentIrp,
|
||
Key,
|
||
SecondsToString(TickCount - SrbTickCount));
|
||
|
||
} while((entry != lastEntry) && (!CheckControlC()));
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
ScsiDumpLocks(
|
||
ULONG64 CommonExtension,
|
||
ULONG Depth
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
dumps the remove locks for a given device object
|
||
|
||
Arguments:
|
||
|
||
CommonExtension - a pointer to the local copy of the device object
|
||
common extension
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG result;
|
||
|
||
LONG RemoveLock;
|
||
ULONG64 RemoveTrackingSpinlock;
|
||
ULONG64 RemoveTrackingList;
|
||
|
||
InitTypeRead(CommonExtension, scsiport!_COMMON_EXTENSION);
|
||
RemoveLock = (ULONG) ReadField(RemoveLock);
|
||
RemoveTrackingSpinlock = ReadField(RemoveTrackingSpinlock);
|
||
RemoveTrackingList = ReadField(RemoveTrackingList);
|
||
|
||
xdprintfEx(Depth, ("RemoveLock count is %d", RemoveLock));
|
||
|
||
if((PVOID)RemoveTrackingSpinlock != (PVOID)-1) {
|
||
|
||
ULONG64 lockEntryAddress = RemoveTrackingList;
|
||
|
||
dprintf(":\n");
|
||
Depth++;
|
||
|
||
if(RemoveTrackingSpinlock != 0) {
|
||
xdprintfEx(Depth, ("RemoveTrackingList is in intermediate state"
|
||
"@ %p\n", RemoveTrackingList));
|
||
return;
|
||
}
|
||
|
||
while((lockEntryAddress != 0L) && !CheckControlC()) {
|
||
|
||
UCHAR buffer[512];
|
||
ULONG64 File;
|
||
ULONG64 Tag;
|
||
ULONG64 NextBlock;
|
||
ULONG Line;
|
||
|
||
InitTypeRead(lockEntryAddress, scsiport!REMOVE_TRACKING_BLOCK);
|
||
File = ReadField(File);
|
||
Tag = ReadField(Tag);
|
||
Line = (ULONG) ReadField(Line);
|
||
NextBlock = ReadField(NextBlock);
|
||
|
||
result = sizeof(buffer);
|
||
|
||
if(!GetAnsiString(File,
|
||
buffer,
|
||
&result)) {
|
||
|
||
xdprintfEx(Depth, ("Tag 0x%p File 0x%p Line %d\n",
|
||
Tag,
|
||
File,
|
||
Line));
|
||
} else {
|
||
|
||
PUCHAR name;
|
||
|
||
name = &buffer[result];
|
||
|
||
while((result > 0) &&
|
||
(*(name - 1) != '\\') &&
|
||
(*(name - 1) != '/') &&
|
||
(!CheckControlC())) {
|
||
name--;
|
||
result--;
|
||
}
|
||
|
||
xdprintfEx(Depth, ("Tag 0x%p File %s Line %d\n",
|
||
Tag,
|
||
name,
|
||
Line));
|
||
}
|
||
|
||
lockEntryAddress = NextBlock;
|
||
}
|
||
} else {
|
||
dprintf(" (not tracked on free build)\n");
|
||
}
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
ScsiDumpSrbData(
|
||
ULONG64 SrbData,
|
||
ULONG Depth
|
||
)
|
||
{
|
||
ULONG result;
|
||
|
||
CSHORT Type;
|
||
ULONG64 LogicalUnit;
|
||
ULONG64 CurrentSrb;
|
||
ULONG64 CurrentIrp;
|
||
ULONG64 RequestSenseSave;
|
||
ULONG QueueTag;
|
||
ULONG64 CompletedRequests;
|
||
ULONG ErrorLogRetryCount;
|
||
ULONG SequenceNumber;
|
||
ULONG Flags;
|
||
ULONG64 RequestListFlink;
|
||
ULONG64 RequestListBlink;
|
||
ULONG64 DataOffset;
|
||
ULONG64 OriginalDataBuffer;
|
||
ULONG64 MapRegisterBase;
|
||
ULONG NumberOfMapRegisters;
|
||
ULONG64 ScatterGatherList;
|
||
|
||
FIELD_INFO deviceFields[] = {
|
||
{"Type", NULL, 0, COPY, 0, (PVOID) &Type},
|
||
{"LogicalUnit", NULL, 0, COPY, 0, (PVOID) &LogicalUnit},
|
||
{"CurrentSrb", NULL, 0, COPY, 0, (PVOID) &CurrentSrb},
|
||
{"CurrentIrp", NULL, 0, COPY, 0, (PVOID) &CurrentIrp},
|
||
{"RequestSenseSave", NULL, 0, COPY, 0, (PVOID) &RequestSenseSave},
|
||
{"QueueTag", NULL, 0, COPY, 0, (PVOID) &QueueTag},
|
||
{"CompletedRequests", NULL, 0, COPY, 0, (PVOID) &CompletedRequests},
|
||
{"ErrorLogRetryCount", NULL, 0, COPY, 0, (PVOID) &ErrorLogRetryCount},
|
||
{"SequenceNumber", NULL, 0, COPY, 0, (PVOID) &SequenceNumber},
|
||
{"Flags", NULL, 0, COPY, 0, (PVOID) &Flags},
|
||
{"RequestList.Flink", NULL, 0, COPY, 0, (PVOID) &RequestListFlink},
|
||
{"RequestList.Blink", NULL, 0, COPY, 0, (PVOID) &RequestListBlink},
|
||
{"DataOffset", NULL, 0, COPY, 0, (PVOID) &DataOffset},
|
||
{"OriginalDataBuffer", NULL, 0, COPY, 0, (PVOID) &OriginalDataBuffer},
|
||
{"MapRegisterBase", NULL, 0, COPY, 0, (PVOID) &MapRegisterBase},
|
||
{"NumberOfMapRegisters", NULL, 0, COPY, 0, (PVOID) &NumberOfMapRegisters},
|
||
{"ScatterGatherList", NULL, 0, COPY, 0, (PVOID) &ScatterGatherList},
|
||
};
|
||
|
||
SYM_DUMP_PARAM DevSym = {
|
||
sizeof (SYM_DUMP_PARAM),
|
||
"scsiport!_SRB_DATA",
|
||
DBG_DUMP_NO_PRINT,
|
||
SrbData,
|
||
NULL, NULL, NULL,
|
||
sizeof (deviceFields) / sizeof (FIELD_INFO),
|
||
&deviceFields[0]
|
||
};
|
||
|
||
result = Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size);
|
||
if (result) {
|
||
SCSIKD_PRINT_ERROR(result);
|
||
return;
|
||
}
|
||
|
||
if(Type != SRB_DATA_TYPE) {
|
||
dprintf("Type (%#x) does not match SRB_DATA_TYPE (%#x)\n",
|
||
Type, SRB_DATA_TYPE);
|
||
}
|
||
|
||
xdprintfEx(Depth, ("Lun 0x%p Srb 0x%p Irp 0x%p\n",
|
||
LogicalUnit, CurrentSrb, CurrentIrp));
|
||
|
||
xdprintfEx(Depth, ("Sense 0x%p Tag 0x%08lx Next Completed 0x%p\n",
|
||
RequestSenseSave,
|
||
QueueTag, CompletedRequests));
|
||
|
||
xdprintfEx(Depth, ("Retry 0x%02x Seq 0x%08lx Flags 0x%08lx\n",
|
||
ErrorLogRetryCount, SequenceNumber,
|
||
Flags));
|
||
|
||
xdprintfEx(Depth, ("Request List: Next 0x%p Previous 0x%p\n",
|
||
RequestListFlink, RequestListBlink));
|
||
|
||
xdprintfEx(Depth, ("Data Offset 0x%p Original Data Buffer 0x%p\n", DataOffset, OriginalDataBuffer));
|
||
|
||
xdprintfEx(Depth, ("Map Registers 0x%p (0x%02x) SG List 0x%p\n",
|
||
MapRegisterBase,
|
||
NumberOfMapRegisters,
|
||
ScatterGatherList));
|
||
|
||
if(ScatterGatherList != 0) {
|
||
|
||
ScsiDumpScatterGatherList(ScatterGatherList,
|
||
NumberOfMapRegisters,
|
||
Depth + 1);
|
||
}
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
ScsiDumpScatterGatherList(
|
||
ULONG64 List,
|
||
ULONG Entries,
|
||
ULONG Depth
|
||
)
|
||
{
|
||
ULONG result;
|
||
ULONG i;
|
||
ULONG start = TRUE;
|
||
ULONG64 PhysicalAddress;
|
||
ULONG Length;
|
||
|
||
for(i = 0; i < Entries; i++) {
|
||
|
||
InitTypeRead(List, nt!_SCATTER_GATHER_ELEMENT);
|
||
PhysicalAddress = ReadField(Address);
|
||
Length = (ULONG) ReadField(Length);
|
||
|
||
if(start) {
|
||
xdprintfEx(Depth, ("0x%016I64x (0x%08lx), ",
|
||
PhysicalAddress,
|
||
Length));
|
||
} else {
|
||
dprintf("0x%016I64x (0x%08lx),\n",
|
||
PhysicalAddress,
|
||
Length);
|
||
}
|
||
|
||
start = !start;
|
||
List += (IsPtr64() != 0) ? 0x18 : 0xc;
|
||
}
|
||
|
||
if(!start) {
|
||
dprintf("\n");
|
||
}
|
||
}
|
||
|
||
DECLARE_API(srbdata)
|
||
{
|
||
ULONG64 address;
|
||
|
||
GetAddress(args, &address);
|
||
|
||
dprintf("SrbData structure at %#p\n", address);
|
||
|
||
ScsiDumpSrbData(address, 1);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
VOID
|
||
ScsiDumpAdapterPerfCounters(
|
||
ULONG64 Adapter,
|
||
ULONG Depth
|
||
)
|
||
{
|
||
#if TEST_LISTS
|
||
ULONG result;
|
||
|
||
ULONG SmallAllocationCount;
|
||
ULONG LargeAllocationCount;
|
||
ULONG64 ScatterGatherAllocationCount;
|
||
ULONG64 SmallAllocationSize;
|
||
ULONG64 MediumAllocationSize;
|
||
ULONG64 LargeAllocationSize;
|
||
ULONG64 SrbDataAllocationCount;
|
||
ULONG64 SrbDataResurrectionCount;
|
||
ULONG64 SrbDataEmergencyFreeCount;
|
||
|
||
FIELD_INFO deviceFields[] = {
|
||
{"SmallAllocationCount", NULL, 0, COPY, 0, (PVOID) &SmallAllocationCount},
|
||
{"LargeAllocationCount", NULL, 0, COPY, 0, (PVOID) &LargeAllocationCount},
|
||
{"ScatterGatherAllocationCount", NULL, 0, COPY, 0, (PVOID) &ScatterGatherAllocationCount},
|
||
{"SmallAllocationSize", NULL, 0, COPY, 0, (PVOID) &SmallAllocationSize},
|
||
{"MediumAllocationSize", NULL, 0, COPY, 0, (PVOID) &MediumAllocationSize},
|
||
{"LargeAllocationSize", NULL, 0, COPY, 0, (PVOID) &LargeAllocationSize},
|
||
{"SrbDataAllocationCount", NULL, 0, COPY, 0, (PVOID) &SrbDataAllocationCount},
|
||
{"SrbDataResurrectionCount", NULL, 0, COPY, 0, (PVOID) &SrbDataResurrectionCount},
|
||
{"SrbDataEmergencyFreeCount", NULL, 0, COPY, 0, (PVOID) &SrbDataEmergencyFreeCount},
|
||
};
|
||
|
||
SYM_DUMP_PARAM DevSym = {
|
||
sizeof (SYM_DUMP_PARAM),
|
||
"scsiport!_ADAPTER_EXTENSION",
|
||
DBG_DUMP_NO_PRINT,
|
||
Adapter,
|
||
NULL, NULL, NULL,
|
||
sizeof (deviceFields) / sizeof (FIELD_INFO),
|
||
&deviceFields[0]
|
||
};
|
||
|
||
result = Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size);
|
||
if (result) {
|
||
SCSIKD_PRINT_ERROR(result);
|
||
return;
|
||
}
|
||
|
||
ULONG mediumAllocationCount = (ULONG)
|
||
(ScatterGatherAllocationCount -
|
||
(SmallAllocationCount +
|
||
LargeAllocationCount));
|
||
|
||
double average;
|
||
|
||
xdprintfEx(Depth, ("Performance Counters:\n"));
|
||
|
||
Depth++;
|
||
|
||
xdprintfEx(Depth, ("SGList Allocs - "));
|
||
dprintf("Small: %d, ", SmallAllocationCount);
|
||
dprintf("Med: %d, ",
|
||
(ScatterGatherAllocationCount -
|
||
SmallAllocationCount -
|
||
LargeAllocationCount));
|
||
dprintf("Large: %d, ", LargeAllocationCount);
|
||
dprintf("Total: %I64d\n",
|
||
ScatterGatherAllocationCount);
|
||
|
||
xdprintfEx(Depth, ("Average SG Entries - "));
|
||
|
||
if(SmallAllocationCount != 0) {
|
||
average = ((double) (SmallAllocationSize)) / SmallAllocationCount;
|
||
dprintf("Small: %.2f ", average);
|
||
}
|
||
|
||
if(mediumAllocationCount != 0) {
|
||
average = ((double) (MediumAllocationSize)) / mediumAllocationCount;
|
||
dprintf("Medium: %.2f ", average);
|
||
}
|
||
|
||
if(Adapter->LargeAllocationCount != 0) {
|
||
average = ((double) (Adapter->LargeAllocationSize)) / LargeAllocationCount;
|
||
dprintf("Large: %.2f", average);
|
||
}
|
||
|
||
dprintf("\n");
|
||
|
||
xdprintfEx(Depth, ("SrbData - Allocs: %I64d, ",
|
||
SrbDataAllocationCount));
|
||
|
||
dprintf("Resurrected: %I64d, ",
|
||
SrbDataResurrectionCount);
|
||
|
||
dprintf("Timer Serviced: %I64d,\n",
|
||
SrbDataServicedFromTickHandlerCount);
|
||
|
||
xdprintfEx(Depth, (" Queued: %I64d, ",
|
||
SrbDataQueueInsertionCount));
|
||
|
||
dprintf("Emergency Freed: %I64d\n",
|
||
SrbDataEmergencyFreeCount);
|
||
|
||
#endif
|
||
return;
|
||
}
|
||
|
||
PUCHAR
|
||
SecondsToString(
|
||
ULONG Count
|
||
)
|
||
{
|
||
static UCHAR string[64] = "";
|
||
UCHAR tmp[16];
|
||
|
||
ULONG seconds = 0;
|
||
ULONG minutes = 0;
|
||
ULONG hours = 0;
|
||
ULONG days = 0;
|
||
|
||
string[0] = '\0';
|
||
|
||
if(Count == 0) {
|
||
sprintf(string, "<1s");
|
||
return string;
|
||
}
|
||
|
||
seconds = Count % 60;
|
||
Count /= 60;
|
||
|
||
if(Count != 0) {
|
||
minutes = Count % 60;
|
||
Count /= 60;
|
||
}
|
||
|
||
if(Count != 0) {
|
||
hours = Count % 24;
|
||
Count /= 24;
|
||
}
|
||
|
||
if(Count != 0) {
|
||
days = Count;
|
||
}
|
||
|
||
if(days != 0) {
|
||
sprintf(tmp, "%dd", days);
|
||
strcat(string, tmp);
|
||
}
|
||
|
||
if(hours != 0) {
|
||
sprintf(tmp, "%dh", hours);
|
||
strcat(string, tmp);
|
||
}
|
||
|
||
if(minutes != 0) {
|
||
sprintf(tmp, "%dm", minutes);
|
||
strcat(string, tmp);
|
||
}
|
||
|
||
if(seconds != 0) {
|
||
sprintf(tmp, "%ds", seconds);
|
||
strcat(string, tmp);
|
||
}
|
||
|
||
return string;
|
||
}
|
||
|
||
VOID
|
||
ScsiDumpQueuedRequests(
|
||
IN ULONG64 DeviceObject,
|
||
IN ULONG TickCount,
|
||
IN ULONG Depth
|
||
)
|
||
{
|
||
ULONG result;
|
||
ULONG64 ListHeadFlink;
|
||
ULONG64 ListHeadBlink;
|
||
ULONG64 DeviceListHead;
|
||
ULONG64 realEntry;
|
||
|
||
//
|
||
// Get the address of the head of the device list in the device queue.
|
||
//
|
||
|
||
result = GetFieldData(
|
||
DeviceObject,
|
||
"scsiport!_DEVICE_OBJECT",
|
||
"DeviceQueue.DeviceListHead",
|
||
sizeof(ULONG64),
|
||
&DeviceListHead);
|
||
if (result) {
|
||
SCSIKD_PRINT_ERROR(result);
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Get the forward and backward link fields from the list head. If
|
||
// the queue is empty, we're done.
|
||
//
|
||
|
||
InitTypeRead(DeviceListHead, scsiport!_LIST_ENTRY);
|
||
ListHeadFlink = ReadField(CurrentSrb);
|
||
ListHeadBlink = ReadField(CurrentIrp);
|
||
|
||
if (ListHeadFlink == ListHeadBlink) {
|
||
xdprintfEx(Depth, ("Device Queue is empty\n"));
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Initialize a pointer the head of the list.
|
||
//
|
||
|
||
realEntry = DeviceListHead;
|
||
|
||
do {
|
||
|
||
ULONG result;
|
||
ULONG64 realIrp;
|
||
ULONG64 realStack;
|
||
ULONG64 realSrb;
|
||
ULONG64 realSrbData;
|
||
ULONG64 CurrentSrb;
|
||
ULONG64 CurrentIrp;
|
||
ULONG OffsetOfDeviceListEntry;
|
||
ULONG SrbDataTickCount;
|
||
|
||
//
|
||
// Get the address of the next entry in the queue.
|
||
//
|
||
|
||
result = GetFieldData(realEntry,
|
||
"scsiport!_LIST_ENTRY",
|
||
"Flink",
|
||
sizeof(ULONG64),
|
||
&realEntry);
|
||
if (result) {
|
||
SCSIKD_PRINT_ERROR(result);
|
||
break;
|
||
}
|
||
|
||
//
|
||
// We to calculate the address of the IRP using the address of the
|
||
// list entry. Can't use static CONTAINING_RECORD; we need a runtime
|
||
// equivalent. So we use type info to get the offset of the list
|
||
// entry and calculate the address of the beginning of the IRP. This
|
||
// makes the extension work for 32b and 64b debuggees.
|
||
//
|
||
|
||
result = GetFieldOffset(
|
||
"scsiport!_IRP",
|
||
"Tail.Overlay.DeviceQueueEntry.DeviceListEntry",
|
||
&OffsetOfDeviceListEntry);
|
||
if (result) {
|
||
SCSIKD_PRINT_ERROR(result);
|
||
break;
|
||
}
|
||
|
||
realIrp = realEntry - OffsetOfDeviceListEntry;
|
||
|
||
//
|
||
// Now we need to read in the address of the current IO stack
|
||
// location.
|
||
//
|
||
|
||
result = GetFieldData(
|
||
realIrp,
|
||
"scsiport!_IRP",
|
||
"Tail.Overlay.CurrentStackLocation",
|
||
sizeof(ULONG64),
|
||
&realStack);
|
||
if (result) {
|
||
SCSIKD_PRINT_ERROR(result);
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Load the SRB field of the stack location.
|
||
//
|
||
|
||
result = GetFieldData(
|
||
realStack,
|
||
"scsiport!_IO_STACK_LOCATION",
|
||
"Parameters.Scsi.Srb",
|
||
sizeof(ULONG64),
|
||
&realSrb);
|
||
if (result) {
|
||
SCSIKD_PRINT_ERROR(result);
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Pick out the pointer to the srb data and read that in.
|
||
//
|
||
|
||
result = GetFieldData(
|
||
realSrb,
|
||
"scsiport!_SCSI_REQUEST_BLOCK",
|
||
"OriginalRequest",
|
||
sizeof(ULONG64),
|
||
&realSrbData);
|
||
if (result) {
|
||
SCSIKD_PRINT_ERROR(result);
|
||
break;
|
||
}
|
||
|
||
xdprintfEx(Depth, ("SrbData 0x%p ", realSrbData));
|
||
|
||
//
|
||
// Read the SRB_DATA information we need.
|
||
//
|
||
|
||
InitTypeRead(realSrb, scsiport!_SRB_DATA);
|
||
CurrentSrb = ReadField(CurrentSrb);
|
||
CurrentIrp = ReadField(CurrentIrp);
|
||
SrbDataTickCount = (ULONG)ReadField(TickCount);
|
||
|
||
dprintf("Srb 0x%p Irp 0x%p %s\n",
|
||
CurrentSrb,
|
||
CurrentIrp,
|
||
SecondsToString(TickCount - SrbDataTickCount));
|
||
|
||
} while((realEntry != ListHeadBlink) && (!CheckControlC()));
|
||
|
||
return;
|
||
}
|
||
|