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;
|
|||
|
}
|
|||
|
|