#include "pch.h" #include "precomp.h" typedef ULONG64 POINTER; // // Port processing irp means the port driver is currently executing // instructions to complete the irp. The irp is NOT waiting for // resources on any queue. // #define RaidPortProcessingIrp (0xA8) // // Pending resources is when the irp is in an IO queue awaiting // resources. // #define RaidPendingResourcesIrp (0xA9) // // The irp takes on state Miniport Processing while the miniport has // control over the irp. That is, between the time we call HwStartIo // and when the miniport calls ScsiPortNotification with a completion // status for the irp. // #define RaidMiniportProcessingIrp (0xAA) // // The irp takes on the Pending Completion state when it is moved to // the completed list. // #define RaidPendingCompletionIrp (0xAB) // // We set the irp state to Completed just before we call IoCompleteRequest // for the irp. // #define RaidCompletedIrp (0xAC) //#define XRB_SIGNATURE (0x1F2E3D4CUL) #define ARRAY_COUNT(Array) (sizeof(Array)/sizeof(Array[0])) ULONG Verbose = 0; PCHAR DeviceStateTable [] = { "Not Present", // not present "Working", // working "Stopped", // stopped "P-Stop", // pending stop "P-Remove", // pending remove "Surprise", // surprise remove "Removed", // removed "Invalid" // invalid state }; PCHAR SystemPowerTable [] = { "Unspecified", "Working", "Sleeping1", "Sleeping2", "Sleeping3", "Hibernate", "Shutdown", "Maximum", "Invalid" }; PCHAR DevicePowerTable [] = { "Unspecified", "D0", "D1", "D2", "D3", "Maximum", "Invalid" }; char *SCSI6byteOpCode[] = { /* 0x00 - 0x1E */ "SCSI/TEST UNT RDY", "SCSI/REZERO UNIT ", "SCSI/REQ BLK ADDR", "SCSI/REQ SENSE ", "SCSI/FORMAT UNIT ", "SCSI/RD BLK LMTS ", "SCSI/NO OPCODE ", "SCSI/REASSGN BLKS", "SCSI/READ (06) ", "SCSI/INVALID ", "SCSI/WRITE (06) ", "SCSI/SEEK (06) ", "SCSI/SEEK BLOCK ", "SCSI/PARTITION ", "SCSI/NO OPCODE ", "SCSI/READ REVERSE", "SCSI/WRTE FILEMKS", "SCSI/SPACE ", "SCSI/INQUIRY ", "SCSI/VERIFY (06) ", "SCSI/RECVR BUFFRD", "SCSI/MODE SEL(06)", "SCSI/RESERVE UNIT", "SCSI/RELEASE UNIT", "SCSI/COPY ", "SCSI/ERASE ", "SCSI/MOD SNSE(06)", "SCSI/STRT/STP UNT", "SCSI/RECV DIAGNOS", "SCSI/SEND DIAGNOS", "SCSI/MEDIUM REMVL" }; char *SCSI10byteOpCode[] = { /* 0x23 - 0x5F */ "SCSI/RD FRMTD CAP", "SCSI/NOP ", "SCSI/READ CAP ", "SCSI/NOP ", "SCSI/NOP ", "SCSI/READ (10) ", "SCSI/NO OPCODE ", "SCSI/WRITE (10) ", "SCSI/SEEK (10) ", "SCSI/NOP ", "SCSI/NOP ", "SCSI/WRT&VRF (10)", "SCSI/VERIFY (10) ", "SCSI/SC DT H (10)", "SCSI/SC DT E (10)", "SCSI/SC DT L (10)", "SCSI/ST LMTS (10)", "SCSI/PRE-FETCH ", "SCSI/SYNC CACHE", "SCSI/LCK/UN CACHE", "SCSI/RD DF D (10)", "SCSI/NO OPCODE ", "SCSI/COMPARE ", "SCSI/CPY & VERIFY", "SCSI/WRT DAT BUFF", "SCSI/RD DAT BUFF ", "SCSI/NO OPCODE ", "SCSI/READ LONG ", "SCSI/WRITE LONG ", "SCSI/CHGE DEF ", "SCSI/RD SUB-CHNL ", "SCSI/READ TOC ", "SCSI/READ HEADER ", "SCSI/PLY AUD (10)", "SCSI/GET CONFIG ", "SCSI/PLY AUD MSF ", "SCSI/PLY TRK INDX", "SCSI/PLY TRK REL ", "SCSI/GET EVT STAT", "SCSI/PAUSE/RESUME", "SCSI/LOG SELECT ", "SCSI/LOG SENSE ", "SCSI/STP/PLY SCAN", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/RD DSK INFO ", "SCSI/RD TRK INFO ", "SCSI/RSRV TRCK RZ", "SCSI/SND OPC INFO", "SCSI/MOD SEL (10)", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/MOD SNS (10)", "SCSI/CLS TRCK SES", "SCSI/RD BUFF CAP ", "SCSI/SND CUE SHT ", "SCSI/PRS RSRV IN ", "SCSI/PRS RSRV OUT" }; char *SCSI12byteOpCode[] = { /* 0xA0 - 0xBF, 0xE7 */ "SCSI/REPORT LUNS ", "SCSI/BLANK ", "SCSI/NO OPCODE ", "SCSI/SEND KEY ", "SCSI/REPORT KEY ", "SCSI/MOVE MEDIUM ", "SCSI/LD/UNLD SLOT", "SCSI/SET RD AHEAD", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/RD DVD STRUC", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/NO OPCODE ", "SCSI/REQ VOL ELMT", "SCSI/SEND VOL TAG", "SCSI/NO OPCODE ", "SCSI/RD ELMT STAT", "SCSI/READ CD MSF ", "SCSI/SCAN CD ", "SCSI/SET CD SPEED", "SCSI/PLAY CD ", "SCSI/MECHNSM STAT", "SCSI/READ CD ", "SCSI/SND DVD STRC", "SCSI/INIT ELM RNG", /* 0xE7 */ }; PCHAR SrbFunctions [] = { "EXECUTE SCSI ", // 0x00 "CLAIM DEVICE ", // 0x01 "IO CONTROL ", // 0x02 "RECEIVE EVENT ", // 0x03 "RELEASE QUEUE ", // 0x04 "ATTACH DEVICE ", // 0x05 "RELEASE DEVICE ", // 0x06 "SHUTDOWN ", // 0x07 "FLUSH ", // 0x08 "NOP ", // 0x09 "NOP ", // 0x0A "NOP ", // 0x0B "NOP ", // 0x0C "NOP ", // 0x0D "NOP ", // 0x0E "NOP ", // 0x0F "ABORT COMMAND ", // 0x10 "RELEASE RECOVERY ", // 0x11 "RESET BUS ", // 0x12 "RESET DEVICE ", // 0x13 "TERMINATE IO ", // 0x14 "FLUSH QUEUE ", // 0x15 "REMOVE DEVICE ", // 0x16 "WMI ", // 0x17 "LOCK QUEUE ", // 0x18 "UNLOCK QUEUE ", // 0x19 "NOP ", // 0x1A "NOP ", // 0x1B "NOP ", // 0x1C "NOP ", // 0x1D "NOP ", // 0x1E "NOP ", // 0x1F "RESET LUN " // 0x20 }; VOID FixString ( PSZ Id ) { ULONG Pos; Pos = strlen(Id); if (Pos > 0) { Pos--; } while ( (Pos > 0) && (Id[Pos] == ' ') ) { Id[Pos]='\0'; Pos--; } } UCHAR GetIoState( IN POINTER Xrb ) { POINTER Irp; ULONG Offset; UCHAR State; POINTER ExEntry; GetFieldValue (Xrb, "storport!EXTENDED_REQUEST_BLOCK", "Irp", Irp); GetFieldOffset ("storport!IRP", "Tail.Overlay.DeviceQueueEntry", &Offset); ExEntry = Irp + Offset; GetFieldValue (ExEntry, "storport!EX_DEVICE_QUEUE_ENTRY", "State", State); return State; } BOOLEAN GetScsiCommand( IN POINTER Srb, OUT PUCHAR Command ) { ULONG Offset; *Command = 0xFF; GetFieldOffset("storport!SCSI_REQUEST_BLOCK", "Cdb", &Offset); ReadMemory(Srb + Offset, Command, sizeof (Command), NULL); return TRUE; } BOOLEAN VerifyXrb( IN POINTER Xrb ) { ULONG Signature; GetFieldValue (Xrb, "storport!EXTENDED_REQUEST_BLOCK", "Signature", Signature); return (Signature == XRB_SIGNATURE); } VOID GetUnitProductInfo ( IN ULONG64 UnitExtension, PSZ VendorId, PSZ ProductId ) { ULONG64 UnitInfoPtr; ULONG64 UnitInfo; ULONG offset; ZeroMemory(VendorId, 9); ZeroMemory(ProductId, 17); if (!GetFieldOffset("storport!RAID_UNIT_EXTENSION", "Identity", &offset)) { UnitInfoPtr = UnitExtension + offset; if (!GetFieldOffset("storport!STOR_SCSI_IDENTITY", "InquiryData", &offset)) { UnitInfoPtr = UnitInfoPtr + offset; ReadPointer(UnitInfoPtr, &UnitInfo); if (GetFieldData(UnitInfo, "storport!INQUIRYDATA", "VendorId", 8, VendorId)) { //dprintf("ERROR: Unable to retrieve VendorId field\n"); } if (GetFieldData(UnitInfo, "storport!INQUIRYDATA", "ProductId", 16, ProductId)) { //dprintf("ERROR: Unable to retrieve ProductId field\n"); } FixString(VendorId); FixString(ProductId); } else { dprintf("ERROR: Unable to retrieve InquiryData offset\n"); } } else { dprintf("ERROR: Unable to retrieve Identity offset\n"); } } VOID PrintAddressList ( IN ULONG64 Address ) { if (IsPtr64()) { dprintf("%16.16x ", Address); } else { dprintf("%8.8x ", Address); } } VOID GetScsiCommandString( IN UCHAR Command, IN PCHAR Buffer ) { UCHAR Index; if ((Command >= 0x00) && (Command <= 0x1E)) { Index = Command; sprintf(Buffer, "%s", SCSI6byteOpCode[Index]); return; } if ((Command >= 0x23) && (Command <= 0x5F)) { Index = Command - 0x23; sprintf(Buffer, "%s", SCSI10byteOpCode[Index]); return; } if ((Command >= 0xA0) && (Command <= 0xBF)) { Index = Command - 0xA0; sprintf(Buffer, "%s", SCSI12byteOpCode[Index]); return; } if (Command == 0xE7) { sprintf(Buffer, "%s", SCSI12byteOpCode[32]); return; } sprintf(Buffer, "NO OPCODE "); } VOID PrintAddress ( IN PSZ Name, IN ULONG64 Address ) { if (IsPtr64()) { dprintf("%s %16.16x ", Name, Address); } else { dprintf("%s %8.8x ", Name, Address); } } ULONG64 ContainingRecord ( IN ULONG64 Object, IN PSZ Type, IN PSZ Field ) { ULONG offset; if (GetFieldOffset(Type, Field, &offset)) { return 0; } else { return (Object - offset); } } BOOLEAN CheckRaidObject ( IN ULONG64 Object, IN RAID_OBJECT_TYPE Type ) { RAID_OBJECT_TYPE RetType; if (GetFieldValue(Object, "storport!RAID_COMMON_EXTENSION", "ObjectType", RetType )) { return FALSE; } else if (Type != RetType) { return FALSE; } return TRUE; } BOOLEAN IsDeviceObject ( IN ULONG64 address ) { CSHORT Type; if (GetFieldValue(address, "storport!DEVICE_OBJECT", "Type", Type)) { return FALSE; } else { return (Type == IO_TYPE_DEVICE); } } ULONG64 GetExtension ( IN ULONG64 address, IN RAID_OBJECT_TYPE Object ) { ULONG64 Extension; ULONG64 DeviceObject; ULONG64 temp; ULONG offset; if (CheckRaidObject(address, Object)) { Extension = address; if (Object == RaidAdapterObject) { InitTypeRead(Extension, storport!RAID_ADAPTER_EXTENSION); } else if (Object == RaidUnitObject) { InitTypeRead(Extension, storport!RAID_UNIT_EXTENSION); } DeviceObject = ReadField(DeviceObject); if (IsDeviceObject(DeviceObject)) { if (GetFieldOffset("storport!DEVICE_OBJECT", "DeviceExtension", &offset)) { dprintf("ERROR: Unable to retrieve Device Extension offset\n"); temp = 0; } else { ReadPointer(DeviceObject + offset, &temp); } if (temp == Extension) { return Extension; } } } DeviceObject = address; if (IsDeviceObject(DeviceObject)) { if (GetFieldOffset("storport!DEVICE_OBJECT", "DeviceExtension", &offset)) { dprintf("ERROR: Unable to retrieve Device Extension offset\n"); Extension = 0; } else { ReadPointer(DeviceObject + offset, &Extension); } if (CheckRaidObject(Extension, Object)) { if (Object == RaidAdapterObject) { InitTypeRead(Extension, storport!RAID_ADAPTER_EXTENSION); } else if (Object == RaidUnitObject) { InitTypeRead(Extension, storport!RAID_UNIT_EXTENSION); } DeviceObject = ReadField(DeviceObject); if (DeviceObject == address) { return Extension; } } } else { dprintf("ERROR: Invalid Device Object\n"); } return 0; } PCHAR DeviceStateToString ( IN ULONG State ) { if (State > 6) { return DeviceStateTable[7]; } return DeviceStateTable[State]; } PCHAR SystemPower ( IN ULONG State ) { if (State > 7) { return SystemPowerTable[8]; } return SystemPowerTable[State]; } PCHAR DevicePower ( IN ULONG State ) { if (State > 5) { return DevicePowerTable[6]; } return DevicePowerTable[State]; } PCHAR GetSrbFunction( IN UCHAR SrbFunctionCode ) { if (SrbFunctionCode >= ARRAY_COUNT (SrbFunctions)) { return "Invalid SRB Function"; } return SrbFunctions [SrbFunctionCode]; } ULONG GetRemLockCount ( IN ULONG64 Object, IN PSZ Type, IN PSZ Field ) { ULONG64 address; ULONG offset; ULONG IOCount; IOCount = -1; if (!GetFieldOffset(Type, Field, &offset)) { address = Object + offset; if (!GetFieldOffset("storport!IO_REMOVE_LOCK", "Common", &offset)) { address = address + offset; GetFieldValue(address,"storport!IO_REMOVE_LOCK_COMMON_BLOCK", "IoCount", IOCount); } } return IOCount; } VOID dindentf( IN ULONG Depth ) { ULONG i; for (i = 1; i <= Depth; i++) { dprintf(" "); } } VOID DumpQueuedRequests( IN POINTER DeviceQueue ) { ULONG64 ListHead; ULONG64 NextRequest; ULONG64 Irp; ULONG64 StackLocation; ULONG64 Srb; ULONG offset; ULONG CommandLength; ULONG TimeOut; UCHAR ScsiCommand; UCHAR SrbFunction; CHAR ScsiCommandString[100]; if (GetFieldOffset("storport!EXTENDED_DEVICE_QUEUE", "DeviceListHead", &offset)) { dprintf("ERROR: Unable to retrieve PendingQueue offset\n"); return; } ListHead = DeviceQueue + offset; for (GetFieldValue(ListHead, "storport!LIST_ENTRY", "Flink", NextRequest); NextRequest != 0 && NextRequest != ListHead; GetFieldValue(NextRequest, "storport!LIST_ENTRY", "Flink", NextRequest)) { Irp = ContainingRecord(NextRequest, "storport!IRP", "Tail.Overlay.DeviceQueueEntry.DeviceListEntry"); PrintAddressList(Irp); if (GetFieldOffset("storport!IRP", "Tail.Overlay.CurrentStackLocation", &offset)) { dprintf("ERROR: Unable to retrieve Current Stack Location offset\n"); return; } StackLocation = Irp + offset; ReadPtr(StackLocation, &StackLocation); if (GetFieldOffset("storport!IO_STACK_LOCATION", "Parameters.Scsi.Srb", &offset)) { dprintf("ERROR: Unable to retrieve Srb offset\n"); return; } Srb = StackLocation + offset; ReadPtr (Srb, &Srb); PrintAddressList(Srb); dprintf(" n/a "); GetFieldValue (Srb, "storport!SCSI_REQUEST_BLOCK", "Function", SrbFunction); if (SrbFunction == SRB_FUNCTION_EXECUTE_SCSI) { GetScsiCommand (Srb, &ScsiCommand), GetScsiCommandString (ScsiCommand, ScsiCommandString); } else { sprintf (ScsiCommandString, "%s ", GetSrbFunction (SrbFunction)); } dprintf ("%s ", ScsiCommandString); InitTypeRead(Irp, storport!IRP); PrintAddressList(ReadField(MdlAddress)); dprintf(" n/a "); GetFieldValue(Srb, "storport!SCSI_REQUEST_BLOCK", "TimeOutValue", TimeOut); dprintf("%d\n", TimeOut); } } #if 0 VOID ReadFlink( IN ULONG64 ListEntry, OUT PULONG64 NextListEntry ) { GetFieldValue (ListEntry, "nt!LIST_ENTRY", "Flink", *NextListEntry); } VOID IteratePendingRequests( IN ULONG64 DeviceQueue, IN ULONG Flags, IN PFN Callback ) { ULONG64 ListHead; ULONG64 NextRequest; ULONG64 Irp; ULONG64 StackLocation; ULONG64 Srb; ULONG offset; ULONG CommandLength; ULONG TimeOut; UCHAR Command; UCHAR SrbFunction; if (GetFieldOffset("storport!EXTENDED_DEVICE_QUEUE", "DeviceListHead", &offset)) { dprintf("ERROR: Unable to retrieve PendingQueue offset\n"); return; } ListHead = DeviceQueue + offset; for (ReadFlink (ListHead, NextRequest); NextRequest != 0 && NextRequest != ListHead; ReadFlink (NextRequest, NextRequest)) { Irp = ContainingRecord ( NextRequest, "storport!IRP", "Tail.Overlay.DeviceQueueEntry.DeviceListEntry"); Callback (Irp); } } #endif ULONG DumpRequests ( IN POINTER UnitExtension, IN UCHAR RequestedState ) /*++ Routine Description: Print out list of outstanding or pending requests depending on value of RequestedState parameter. Arguments: UnitExtension - Debuggee-Pointer to unit extension. RequestedState - Supplies the requested state to dump, must be either: RaidMiniportProcessingIrp for Outstanding requests. RaidPendingCompletionIrp for Completing requests. Return Value: Number of requests dumped. --*/ { POINTER address; POINTER NextRequest; POINTER Xrb; POINTER Srb; ULONG offset; ULONG TimeOut; UCHAR SrbFunction; UCHAR ScsiCommand; CHAR ScsiCommandString[100]; UCHAR IoState; ULONG Count; Count = 0; if (GetFieldOffset("storport!RAID_UNIT_EXTENSION", "PendingQueue", &offset)) { dprintf("ERROR: Unable to retrieve PendingQueue offset\n"); return 0; } address = UnitExtension + offset; if (GetFieldOffset("storport!STOR_EVENT_QUEUE", "List", &offset)) { dprintf("ERROR: Unable to retrieve PendingQueue offset\n"); return 0; } address += offset; for (GetFieldValue(address, "storport!LIST_ENTRY", "Flink", NextRequest); NextRequest != 0 && NextRequest != address; GetFieldValue(NextRequest, "storport!LIST_ENTRY", "Flink", NextRequest)) { Xrb = ContainingRecord (NextRequest, "storport!EXTENDED_REQUEST_BLOCK", "PendingLink.NextLink"); if (Verbose) { dprintf ("VERBOSE: Xrb %p\n", Xrb); } InitTypeRead(Xrb, storport!EXTENDED_REQUEST_BLOCK); if (!VerifyXrb (Xrb)) { dprintf ("ERROR: Request %p does not have an XRB signature!\n", Xrb); continue; } IoState = GetIoState (Xrb); if (Verbose) { dprintf ("VERBOSE: Irp state is %x\n", (ULONG)IoState); } if (IoState != RequestedState) { continue; } Count++; GetFieldValue (Xrb, "storport!EXTENDED_REQUEST_BLOCK", "Srb", Srb); PrintAddressList(ReadField(Irp)); PrintAddressList(Srb); PrintAddressList(Xrb); GetFieldValue (Srb, "storport!SCSI_REQUEST_BLOCK", "Function", SrbFunction); if (SrbFunction == SRB_FUNCTION_EXECUTE_SCSI) { GetScsiCommand (Srb, &ScsiCommand); GetScsiCommandString (ScsiCommand, ScsiCommandString); } else { sprintf (ScsiCommandString, "%s ", GetSrbFunction (SrbFunction)); } dprintf ("%s ", ScsiCommandString); InitTypeRead(Xrb, storport!EXTENDED_REQUEST_BLOCK); PrintAddressList (ReadField(Mdl)); PrintAddressList (ReadField(SgList)); GetFieldValue(Srb, "Storport!SCSI_REQUEST_BLOCK", "TimeOutValue", TimeOut); dprintf("%d\n", TimeOut); } return Count; } ULONG DumpOutstandingRequests( IN POINTER UnitExtension ) { return DumpRequests (UnitExtension, RaidMiniportProcessingIrp); } ULONG DumpCompletedRequests( IN POINTER UnitExtension ) { return DumpRequests (UnitExtension, RaidPendingCompletionIrp); } VOID PrintRequestListHeader( IN PCHAR Title ) { dprintf ("\n\n[%s]\n\n", Title); dprintf("IRP SRB XRB Command MDL " "SGList Timeout\n"); dprintf("----------------------------------------------------------" "-----------------\n"); } VOID DumpUnit ( IN ULONG64 address, IN ULONG Level, IN ULONG Depth ) { ULONG64 UnitExtension; ULONG64 VirtualBase; ULONG64 QueueTagList; ULONG64 IoQueue; ULONG64 DeviceQueue; ULONG64 IoGateway; ULONG64 EventQ; ULONG offset; ULONG RemLock_IOCount; UCHAR VendorId[9] = {0}; UCHAR ProductId[17] = {0}; PSZ SlowLock; UnitExtension = GetExtension(address, RaidUnitObject); if (UnitExtension == 0) { dprintf("ERROR: Unable to retrieve Unit Extension address\n"); return; } InitTypeRead(UnitExtension, storport!RAID_UNIT_EXTENSION); if (Level == 0) { GetUnitProductInfo(UnitExtension, VendorId, ProductId); dindentf(Depth); if (!GetFieldOffset("storport!RAID_UNIT_EXTENSION", "Address", &offset)) { InitTypeRead(UnitExtension + offset, storport!STOR_SCSI_ADDRESS); } else { dprintf("ERROR: Unable to retrieve STOR_SCSI_ADDRESS structure offset\n"); } dprintf("%-10.10s %-10.10s %2d %2d %2d ", VendorId, ProductId, (ULONG)ReadField(PathId), (ULONG)ReadField(TargetId), (ULONG)ReadField(Lun)); InitTypeRead(UnitExtension, storport!RAID_UNIT_EXTENSION); PrintAddressList(ReadField(DeviceObject)); PrintAddressList(UnitExtension); if (GetFieldOffset("storport!RAID_UNIT_EXTENSION", "IoQueue", &offset)) { dprintf("ERROR: Unable to retrieve IoQueue offset\n"); return; } IoQueue = UnitExtension + offset; if (GetFieldOffset("storport!IO_QUEUE", "DeviceQueue", &offset)) { dprintf("ERROR: Unable to retreive DeviceQueue offset\n"); return; } DeviceQueue = IoQueue + offset; InitTypeRead(DeviceQueue, storport!EXTENDED_DEVICE_QUEUE); dprintf("%3d %3d %2d ", (ULONG)ReadField(DeviceRequests), (ULONG)ReadField(OutstandingRequests), (ULONG)ReadField(ByPassRequests)); InitTypeRead(UnitExtension, storport!RAID_UNIT_EXTENSION); dprintf("%s\n", DeviceStateToString((ULONG)ReadField(DeviceState))); } else { ULONG OutstandingCount; ULONG Count; dprintf("UNIT\n"); Depth++; dindentf(Depth); PrintAddress("DO", ReadField(DeviceObject)); PrintAddress("Ext", UnitExtension); PrintAddress("Adapter", ReadField(Adapter)); dprintf("%s\n", DeviceStateToString((ULONG)ReadField(DeviceState))); GetUnitProductInfo(UnitExtension, VendorId, ProductId); dindentf(Depth); if (!GetFieldOffset("storport!RAID_UNIT_EXTENSION", "Address", &offset)) { InitTypeRead(UnitExtension + offset, storport!STOR_SCSI_ADDRESS); } else { dprintf("ERROR: Unable to retrieve STOR_SCSI_ADDRESS structure offset\n"); } dprintf("Vendor: %s Product: %s SCSI ID: (%d, %d, %d) \n", VendorId, ProductId, (ULONG)ReadField(PathId), (ULONG)ReadField(TargetId), (ULONG)ReadField(Lun)); InitTypeRead(UnitExtension, storport!RAID_UNIT_EXTENSION); dindentf(Depth); dprintf("%s %s %s %s \n", (ReadField(Flags.DeviceClaimed) ? "Claimed" : ""), (ReadField(Flags.QueueFrozen) ? "Frozen" : ""), (ReadField(Flags.QueueLocked) ? "Locked" : ""), (ReadField(Flags.Enumerated) ? "Enumerated" : "")); InitTypeRead(UnitExtension, storport!RAID_UNIT_EXTENSION); SlowLock = ReadField(SlowLock) ? "Held" : "Free"; RemLock_IOCount = GetRemLockCount(UnitExtension, "storport!RAID_UNIT_EXTENSION", "RemoveLock"); dindentf(Depth); dprintf("SlowLock %s RemLock %d PageCount %d\n", SlowLock, RemLock_IOCount, (ULONG)ReadField(PagingPathCount)); VirtualBase = ReadField(SrbExtensionRegion.VirtualBase); dindentf(Depth); PrintAddress("SrbExtensionRegion (Virtual Base)", VirtualBase); dprintf("(%d bytes)\n", (ULONG)ReadField(SrbExtensionRegion.Length)); if (GetFieldOffset("storport!RAID_UNIT_EXTENSION", "TagList", &offset)) { dprintf("ERROR: Unable to retrieve TagList offset\n"); return; } QueueTagList = UnitExtension + offset; dindentf(Depth); PrintAddress("QueueTagList:", QueueTagList); dprintf("(%d of %d used)\n", (ULONG)ReadField(TagList.OutstandingTags), (ULONG)ReadField(TagList.Count)); if (GetFieldOffset("storport!RAID_UNIT_EXTENSION", "IoQueue", &offset)) { dprintf("ERROR: Unable to retrieve IoQueue offset\n"); } IoQueue = UnitExtension + offset; if (GetFieldOffset("storport!IO_QUEUE", "DeviceQueue", &offset)) { dprintf("ERROR: Unable to retreive DeviceQueue offset\n"); } DeviceQueue = IoQueue + offset; if (GetFieldOffset ("storport!RAID_UNIT_EXTENSION", "PendingQueue", &offset)) { dprintf ("ERROR: Unable to retrieve PendingQueue offset\n"); } EventQ = UnitExtension + offset; InitTypeRead (EventQ, storport!STOR_EVENT_QUEUE); dindentf(Depth); dprintf("Outstanding: Head %p Tail %p Timeout %d\n", ReadField (List.Flink), ReadField (List.Blink), ReadField (Timeout)); InitTypeRead(DeviceQueue, storport!EXTENDED_DEVICE_QUEUE); dindentf(Depth); PrintAddress("DeviceQueue", DeviceQueue); dprintf("Depth: %d ", (ULONG)ReadField(Depth)); dprintf("Status: %s \n", (ReadField(Frozen) ? "Frozen" : "Not Frozen")); IoGateway = ReadField(Gateway); InitTypeRead(IoGateway, storport!STOR_IO_GATEWAY); dindentf(Depth); dprintf("IO Gateway: Busy Count %d Pause Count %d\n", (ULONG)ReadField(BusyCount), (ULONG)ReadField(PauseCount)); InitTypeRead(DeviceQueue, storport!EXTENDED_DEVICE_QUEUE); dindentf(Depth); OutstandingCount = (ULONG)ReadField (OutstandingRequests); dprintf("Requests: Outstanding %d Device %d ByPass %d\n", OutstandingCount, (ULONG)ReadField(DeviceRequests), (ULONG)ReadField(ByPassRequests)); PrintRequestListHeader ("Queued Requests"); DumpQueuedRequests (DeviceQueue); PrintRequestListHeader ("Outstanding Requests"); Count = DumpOutstandingRequests (UnitExtension); PrintRequestListHeader ("Completed Requests"); Count += DumpCompletedRequests (UnitExtension); if (Count < OutstandingCount) { dprintf ("\n\nNOTE: %d request(s) not found on the completed or outstanding list. The\n" " requests are probably being transferred from one list to another. On an\n" " MP machine this could be happening on a separate processor.\n", OutstandingCount - Count); } else if (Count > OutstandingCount) { dprintf ("ERROR: %d counted requests > %d outstanding requests\n\n", Count, OutstandingCount); } dprintf ("\n"); } } VOID ListAdapterUnits( IN ULONG64 AdapterExtension, IN ULONG Level, IN ULONG Depth ) { ULONG64 Units; ULONG64 NextUnit; ULONG64 UnitExtension; ULONG offset; if (!GetFieldOffset("storport!RAID_ADAPTER_EXTENSION", "UnitList.List", &offset)) { Units = AdapterExtension + offset; } else { dprintf("ERROR: Unable to retrieve Unit List offset\n"); return; } for (GetFieldValue(Units, "storport!LIST_ENTRY", "Flink", NextUnit); NextUnit != 0 && NextUnit != Units; GetFieldValue(NextUnit, "storport!LIST_ENTRY", "Flink", NextUnit)) { UnitExtension = ContainingRecord(NextUnit, "storport!RAID_UNIT_EXTENSION", "NextUnit"); if (!CheckRaidObject(UnitExtension, RaidUnitObject)) { dprintf("ERROR: Invalid RAID unit object\n"); return; } DumpUnit(UnitExtension, 0, Depth); } } VOID DumpAdapter ( IN ULONG64 address, IN ULONG Level, IN ULONG Depth ) { ULONG64 AdapterExtension; ULONG64 DriverNameBuffer; ULONG64 DriverNameLength; ULONG64 DriverObject; ULONG64 MiniportObject; ULONG64 HwInitData; ULONG64 HwDeviceExt; CHAR NameBuffer[512] = {0}; PSZ SlowLock; ULONG RemLock; ULONG offset; ULONG debugtemp; ULONG debugoffset; AdapterExtension = GetExtension(address, RaidAdapterObject); if (AdapterExtension == 0) { dprintf("ERROR: Unable to retrieve Adapter Extension address\n"); return; } InitTypeRead (AdapterExtension, storport!RAID_ADAPTER_EXTENSION); if (Level == 0) { if (GetFieldValue(ReadField(Driver), "storport!RAID_DRIVER_EXTENSION", "DriverObject", DriverObject)) { dprintf("ERROR: Unable to retrieve Driver Extension address\n"); return; } GetFieldValue(DriverObject, "storport!DRIVER_OBJECT", "DriverName.Buffer", DriverNameBuffer); GetFieldValue(DriverObject, "storport!DRIVER_OBJECT", "DriverName.Length", DriverNameLength); DriverNameLength = min(DriverNameLength, sizeof(NameBuffer)/sizeof(WCHAR)-1); ReadMemory(DriverNameBuffer, (PVOID)NameBuffer, (ULONG)DriverNameLength*sizeof(WCHAR), NULL); dprintf("%-20.20S ", NameBuffer); PrintAddressList(ReadField(DeviceObject)); PrintAddressList(AdapterExtension); dprintf(" %s\n", DeviceStateToString((ULONG)ReadField(DeviceState))); } else { dprintf("ADAPTER\n"); Depth++; dindentf(Depth); PrintAddress("DO", ReadField(DeviceObject)); PrintAddress("Ext", AdapterExtension); PrintAddress("Driver", ReadField(Driver)); dprintf("%s\n", DeviceStateToString((ULONG)ReadField(DeviceState))); dindentf(Depth); PrintAddress("LDO", ReadField(LowerDeviceObject)); PrintAddress("PDO", ReadField(PhysicalDeviceObject)); dprintf("\n"); SlowLock = ReadField(SlowLock) ? "Held" : "Free"; RemLock = GetRemLockCount(AdapterExtension, "storport!RAID_ADAPTER_EXTENSION", "RemoveLock"); dindentf(Depth); dprintf("SlowLock %s RemLock %d \n", SlowLock, RemLock); dindentf(Depth); dprintf("Power: %s %s %s\n", SystemPower((ULONG)ReadField(Power.SystemState)), DevicePower((ULONG)ReadField(Power.DeviceState)), (ReadField(IoModel) == StorSynchronizeFullDuplex ? "Full Duplex" : "Half Duplex")); dindentf(Depth); dprintf("Bus %d Slot %d ", (ULONG)ReadField(BusNumber), (ULONG)ReadField(SlotNumber)); PrintAddress("DMA", ReadField(Dma.DmaAdapter)); PrintAddress("Interrupt", ReadField(Interrupt)); dprintf("\n"); dindentf(Depth); PrintAddress("ResourceList: Allocated", ReadField(ResourceList.AllocatedResources)); PrintAddress("Translated", ReadField(ResourceList.TranslatedResources)); dprintf("\n"); dindentf(Depth); dprintf("Gateway: Outstanding %d Lower %d High %d\n", (ULONG)ReadField(Gateway.Outstanding), (ULONG)ReadField(Gateway.LowWaterMark), (ULONG)ReadField(Gateway.HighWaterMark)); GetFieldOffset("storport!RAID_ADAPTER_EXTENSION", "Miniport", &offset); MiniportObject = AdapterExtension + offset; InitTypeRead(MiniportObject, storport!RAID_MINIPORT); HwInitData = ReadField(HwInitializationData); GetFieldOffset("storport!RAID_MINIPORT", "PortConfiguration", &offset); dindentf(Depth); PrintAddress("PortConfigInfo", (MiniportObject + offset)); dprintf("\n"); dindentf(Depth); PrintAddress("HwInit", HwInitData); HwDeviceExt = ReadField(PrivateDeviceExt); if (!GetFieldOffset("storport!RAID_HW_DEVICE_EXT", "HwDeviceExtension", &offset)) { HwDeviceExt = HwDeviceExt + offset; } else { HwDeviceExt = 0; } PrintAddress("HwDeviceExt", HwDeviceExt); InitTypeRead(HwInitData, storport!HW_INITIALIZATION_DATA); dprintf("(%d bytes)\n", (ULONG)ReadField(DeviceExtensionSize)); dindentf(Depth); dprintf("SrbExt %d bytes LUExt %d bytes\n", (ULONG)ReadField(SrbExtensionSize), (ULONG)ReadField(SpecificLuExtensionSize)); dindentf(Depth); dprintf("Logical Units: \n"); dprintf("\n"); dindentf(Depth); dprintf("Product SCSI ID Object Extension Pnd Out Ct State\n"); dindentf(Depth); dprintf("----------------------------------------------------------------------------\n"); ListAdapterUnits(AdapterExtension, Level, Depth); } } VOID ListGeneral ( IN ULONG Level, IN ULONG Depth, IN CHAR Type ) { ULONG64 address; ULONG64 Drivers; ULONG64 Adapters; ULONG64 PortData; ULONG64 NextDriver; ULONG64 NextAdapter; ULONG64 DriverExtension; ULONG64 AdapterExtension; ULONG offset; address = GetExpression("storport!RaidpPortData"); if ((address != 0)) { ReadPointer(address, &PortData); if (!GetFieldOffset("storport!RAID_PORT_DATA", "DriverList.List", &offset)) { Drivers = PortData + offset; } else { dprintf("ERROR: Unable to retrieve Driver List offset\n"); return; } } else { dprintf("ERROR: Unable to lookup RAID_PORT_DATA structure\n"); return; } for (GetFieldValue(Drivers, "storport!LIST_ENTRY", "Flink", NextDriver); NextDriver != 0 && NextDriver != Drivers; GetFieldValue(NextDriver, "storport!LIST_ENTRY", "Flink", NextDriver)) { DriverExtension = ContainingRecord(NextDriver, "storport!RAID_DRIVER_EXTENSION", "DriverLink"); if (!CheckRaidObject(DriverExtension, RaidDriverObject)) { dprintf("ERROR: Not a valid RAID Driver Object\n"); return; } if (!GetFieldOffset("storport!RAID_DRIVER_EXTENSION", "AdapterList.List", &offset)) { Adapters = DriverExtension + offset; } else { dprintf("ERROR: Unable to retrieve Adapter List offset\n"); return; } if (Type == 'A') { dprintf("Driver Object Extension State\n"); dprintf("----------------------------------------------------\n"); } else if (Type == 'U') { dprintf("Product SCSI ID Object Extension Pnd Out Ct State\n"); dprintf("----------------------------------------------------------------------------\n"); } GetFieldValue(Adapters, "storport!LIST_ENTRY", "Flink", NextAdapter); //ASSERT(NextAdapter != 0); while (NextAdapter != 0 && NextAdapter != Adapters) { AdapterExtension = ContainingRecord( NextAdapter, "storport!RAID_ADAPTER_EXTENSION", "NextAdapter"); if (!CheckRaidObject(AdapterExtension, RaidAdapterObject)) { dprintf("ERROR: Not a valid RAID Adapter Object\n"); return; } if (Type == 'A') { DumpAdapter(AdapterExtension, Level, Depth); } else if (Type == 'U') { ListAdapterUnits(AdapterExtension, Level, Depth); } else { dprintf("ERROR: Wrong Type\n"); return; } GetFieldValue(NextAdapter, "storport!LIST_ENTRY", "Flink", NextAdapter); } } } __inline BOOL GetHelpExpressionEx( PCSTR Expression, PCSTR* Command ) { if (Expression[0] != '\0' ) { *Command = Expression; return TRUE; } return FALSE; } DECLARE_API (help) { PCSTR command; if(GetHelpExpressionEx(args, &command)) { if ((strcmp(command, "adapter") == 0) || (strcmp(command, "Adapter") == 0)) { dprintf("\nNAME: \n"); dprintf("\t!storkd.adapter\n"); dprintf("\nUSAGE: \n"); dprintf("\t!adapter [ADAPTER-OBJECT]\n"); dprintf("\nARGUMENTS: \n"); dprintf("\tADAPTER-OBJECT - pointer to a device object or an adapter extension\n"); dprintf("\tfor a given unit. If no ADAPTER-OBJECT is specified, all STOR adapters\n"); dprintf("\tused in the system are listed.\n"); return S_OK; } else if ((strcmp(command, "unit") == 0) || (strcmp(command, "UNIT") == 0) || (strcmp(command, "Unit") == 0)) { dprintf("\nNAME: \n"); dprintf("\t!storkd.unit\n"); dprintf("\nUSAGE: \n"); dprintf("\t!lun [UNIT-OBJECT]\n"); dprintf("\nARGUMENTS: \n"); dprintf("\tUNIT-OBJECT - pointer to a device object or an unit extension for a\n"); dprintf("\tgiven logical unit. If no UNIT-OBJECT is specified, all STOR logical\n"); dprintf("\tunits used in the system is listed.\n"); return S_OK; } else if ((strcmp(command, "help") == 0) || (strcmp(command, "HELP") == 0) || (strcmp(command, "Help") == 0)) { dprintf("\nNAME: \n"); dprintf("\t!storkd.help\n"); dprintf("\nUSAGE: \n"); dprintf("\t!help [COMMAND]\n"); dprintf("\nARGUMENTS: \n"); dprintf("\tCOMMAND - command name.\n"); return S_OK; } else { dprintf ("\nERROR: INVALID COMMAND\n"); return S_OK; } } else { dprintf("\n!adapter - list all adapters with summary information\n"); dprintf("!adapter
- provide detailed information about the adapter\n"); dprintf(" identified by its device object or device extension\n"); dprintf(" address\n"); dprintf("!unit - list all logical units with summary information\n"); dprintf("!unit - provide detailed information about the logical unit\n"); dprintf(" identified by its device object or device extension\n"); dprintf(" address\n"); dprintf("!help - list commands with description\n"); dprintf("\n"); return S_OK; } } DECLARE_API (adapter) { ULONG64 address; if (GetExpressionEx(args, &address, &args)) { DumpAdapter(address, 1, 0); } else { ListGeneral(0, 0, 'A'); } return S_OK; } DECLARE_API (unit) { ULONG64 address; if (GetExpressionEx(args, &address, &args)) { DumpUnit(address, 1, 0); } else { ListGeneral(0, 0, 'U'); } return S_OK; }