windows-nt/Source/XPSP1/NT/drivers/storage/kdext/scsikd/scsikd.c
2020-09-26 16:20:57 +08:00

1847 lines
55 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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;
}