You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1517 lines
40 KiB
1517 lines
40 KiB
|
|
#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 <address> - 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 <address> - 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;
|
|
}
|