/*++ 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 = 0; ULONG result; ULONG64 detail = 0; CSHORT Type; if (GetExpressionEx(args, &address, &args)) { GetExpressionEx(args, &detail, &args); } // // 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, (ULONG)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 = 0; ULONG64 CompletedRequests; ULONG64 AddrOfCompletedRequests; ULONG64 ReadyLogicalUnit = 0; ULONG64 WmiMiniPortRequests = 0; 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 NextCompletedRequests; if(Detail != 0) { if(count == 0) { dprintf("\n"); } xdprintfEx(Depth, ("SrbData 0x%08p ", request)); } count++; result = GetFieldData(request, "scsiport!_SRB_DATA", "CompletedRequests", sizeof(ULONG64), &NextCompletedRequests ); 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 = NextCompletedRequests; } 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 logEntries; 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 ); } // // Dump the per-lun IO log. // InitTypeRead(LunAddress, scsiport!_LOGICAL_UNIT_EXTENSION); logEntries = (ULONG) ReadField(IoLogEntries); if (logEntries > 0) { ULONG index; ULONG offset; ULONG64 logAddress; SP_LUN_IO_LOG ioLog[10] = {0}; ULONG bytesRead; PSP_LUN_IO_LOG entry; ULONG i; dprintf("Log:\n"); if (logEntries >= 10) { // // The current index is the oldest entry in the log. // index = (ULONG) ReadField(IoLogIndex); if (index >= 10) { index = 0; } } else { // // we haven't wrapped so zero is the oldest entry in the log. // index = 0; } // // Get the offset of the log array relative to the beginning of the // logical unit extension. // result = GetFieldOffset("scsiport!_LOGICAL_UNIT_EXTENSION", "IoLog", &offset); if (result != 0) { goto NoLogEntry; } // // Calculate the address of the log. // logAddress = LunAddress + offset; // // Read all of the log entries. // result = ReadMemory(logAddress, (PVOID) ioLog, sizeof(SP_LUN_IO_LOG) * 10, &bytesRead); xdprintfEx(Depth, ("\n")); xdprintfEx(Depth, (" Srb Scsi \n")); xdprintfEx(Depth, ("TickCount Cmd Status Status Sector Tag\n")); xdprintfEx(Depth, ("--------- --- ------ ------ -------- ---\n")); // // Dump the log, beginning with the oldest entry. // for (i=0; iTickCount, entry->Cdb[0], entry->SrbStatus, entry->ScsiStatus, entry->QueueSortKey, entry->Tag )); if (entry->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) { PSENSE_DATA senseData = (PSENSE_DATA) entry->SenseData; dprintf(" (%x, %x, %x)\n", senseData->ErrorCode, senseData->AdditionalSenseCode, senseData->AdditionalSenseCodeQualifier); } else { dprintf("\n"); } index++; if (index == 10) { index = 0; } } } NoLogEntry: 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; 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 = 0; ULONG64 LogicalUnit = 0; ULONG64 CurrentSrb = 0; ULONG64 CurrentIrp = 0; ULONG64 RequestSenseSave = 0; ULONG QueueTag = 0; ULONG64 CompletedRequests = 0; ULONG ErrorLogRetryCount = 0; ULONG SequenceNumber = 0; ULONG Flags = 0; ULONG64 RequestListFlink = 0; ULONG64 RequestListBlink = 0; ULONG64 DataOffset = 0; ULONG64 OriginalDataBuffer = 0; ULONG64 MapRegisterBase = 0; ULONG NumberOfMapRegisters = 0; ULONG64 ScatterGatherList = 0; 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; GetExpressionEx(args, &address, &args); 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 { 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; }