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.
1405 lines
29 KiB
1405 lines
29 KiB
|
|
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
raid.c
|
|
|
|
Abstract:
|
|
|
|
Extensions for RAID port driver.
|
|
|
|
Author:
|
|
|
|
Matthew D Hendel (math) 14-June-2000
|
|
|
|
Revision History:
|
|
|
|
|
|
!raid.help
|
|
|
|
!raid.help
|
|
|
|
adapter - Dump an adapter object.
|
|
|
|
unit - Dump a unit object.
|
|
|
|
Type !raid.help "command" for more information about the command.
|
|
|
|
|
|
|
|
NAME:
|
|
|
|
unit
|
|
|
|
USAGE:
|
|
|
|
unit [UNIT-OBJECT [DETAIL]]
|
|
|
|
ARGUMENTS:
|
|
|
|
UNIT-OBJECT -
|
|
|
|
DETAIL -
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
!raid.adapter
|
|
|
|
RAID Adapters:
|
|
|
|
Name DO Ext
|
|
-------------------------------------
|
|
dac960nt 84000000 84100000
|
|
foobar 84000000 84100000
|
|
ami95044 84000000 84100000
|
|
XXAABB 84000000 84100000
|
|
|
|
RAID Units:
|
|
|
|
Product SCSI ID DO Ext Reqs
|
|
--------------------------------------------------------------------
|
|
MYLEX DAC960 3 1 1 84000000 84100000 200
|
|
AMI DDD5455 200 200 200 84000000 84100000 0
|
|
|
|
!raid.unit
|
|
Dump a raid unit
|
|
|
|
!raid.adapter
|
|
Dump a raid adapter
|
|
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
#include "precomp.h"
|
|
|
|
|
|
//
|
|
// Prototypes
|
|
//
|
|
|
|
VOID
|
|
DumpUnit(
|
|
IN ULONG64 Unit,
|
|
IN ULONG Level
|
|
);
|
|
|
|
VOID
|
|
DumpAdapter(
|
|
IN ULONG64 Adapter,
|
|
IN ULONG Level
|
|
);
|
|
|
|
//
|
|
// Data
|
|
//
|
|
|
|
PCHAR StateTable [] = {
|
|
"Removed", // not present
|
|
"Working", // working
|
|
"Stopped", // stopped
|
|
"P-Stop", // pending stop
|
|
"P-Remove", // pending remove
|
|
"Surprise", // surprise remove
|
|
};
|
|
|
|
|
|
BOOLEAN Verbose = FALSE;
|
|
|
|
//
|
|
// Functions
|
|
//
|
|
|
|
|
|
BOOLEAN
|
|
CheckRaidObject(
|
|
IN ULONG64 Object,
|
|
IN RAID_OBJECT_TYPE ObjectType
|
|
)
|
|
{
|
|
|
|
ULONG Ret;
|
|
|
|
if (Object == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
Ret = GetFieldData (Object,
|
|
"raidport!RAID_COMMON_EXTENSION",
|
|
"ObjectType",
|
|
sizeof (ObjectType),
|
|
&ObjectType);
|
|
|
|
|
|
if (Ret != 0 || ObjectType != ObjectType) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
ULONG64
|
|
GetListHead(
|
|
IN ULONG64 Object,
|
|
IN PSZ ObjectType,
|
|
IN PSZ FieldName,
|
|
OUT PULONG64 ListHead
|
|
)
|
|
{
|
|
ULONG64 NextEntry;
|
|
ULONG Offset;
|
|
ULONG Ret;
|
|
|
|
Ret = GetFieldOffset (ObjectType, FieldName, &Offset);
|
|
|
|
if (Ret != 0) {
|
|
return 0;
|
|
}
|
|
|
|
*ListHead = (Object + Offset);
|
|
ReadPointer (*ListHead, &NextEntry);
|
|
|
|
return NextEntry;
|
|
}
|
|
|
|
|
|
ULONG64
|
|
GetNextListEntry(
|
|
IN ULONG64 ListElement
|
|
)
|
|
{
|
|
ULONG64 NextEntry;
|
|
ULONG Ret;
|
|
|
|
Ret = GetFieldData (ListElement,
|
|
"raidport!LIST_ENTRY",
|
|
"Flink",
|
|
sizeof (NextEntry),
|
|
&NextEntry);
|
|
|
|
if (Ret != 0) {
|
|
dprintf ("ERROR: Couldn't get next list entry for element %08x\n", ListElement);
|
|
return 0;
|
|
}
|
|
|
|
return NextEntry;
|
|
}
|
|
|
|
ULONG64
|
|
ContainingRecord(
|
|
IN ULONG64 Object,
|
|
IN PSZ ObjectType,
|
|
IN PSZ FieldName
|
|
)
|
|
{
|
|
ULONG Offset;
|
|
ULONG Ret;
|
|
|
|
Ret = GetFieldOffset (ObjectType, FieldName, &Offset);
|
|
|
|
if (Ret != 0) {
|
|
return 0;
|
|
}
|
|
|
|
return (Object - Offset);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
ListDriverAdapters(
|
|
IN ULONG64 Driver,
|
|
IN ULONG Level
|
|
)
|
|
{
|
|
ULONG64 ListHead;
|
|
ULONG64 Adapter;
|
|
ULONG64 NextEntry;
|
|
|
|
#if 0
|
|
BOOLEAN Succ;
|
|
|
|
Succ = GetDriverInformation (Driver,
|
|
DriverName,
|
|
&BaseAddress,
|
|
&CreationTime);
|
|
|
|
if (!Succ) {
|
|
return;
|
|
}
|
|
|
|
GetFieldOffset ("raidport!RAID_DRIVER_EXTENSION",
|
|
"AdapterList.List",
|
|
&Offset);
|
|
|
|
ListHead = Driver + Offset;
|
|
#endif
|
|
|
|
NextEntry = GetListHead (Driver,
|
|
"raidport!RAID_DRIVER_EXTENSION",
|
|
"AdapterList.List.Flink",
|
|
&ListHead);
|
|
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: ListHead = %08x, NextEntry = %08x\n",
|
|
(ULONG)ListHead, (ULONG)NextEntry);
|
|
}
|
|
for ( /* NOTHING */ ;
|
|
NextEntry != 0 && NextEntry != ListHead;
|
|
NextEntry = GetNextListEntry (NextEntry)) {
|
|
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: Adapter ListEntry %08x\n", NextEntry);
|
|
}
|
|
|
|
Adapter = ContainingRecord (NextEntry,
|
|
"raidport!RAID_ADAPTER_EXTENSION",
|
|
"NextAdapter");
|
|
|
|
if (!CheckRaidObject (Adapter, RaidAdapterObject)) {
|
|
dprintf ("ERROR: Object at %08x not an raid adapter\n", Adapter);
|
|
return;
|
|
}
|
|
|
|
if (CheckControlC()) {
|
|
return;
|
|
}
|
|
|
|
DumpAdapter (Adapter, Level);
|
|
}
|
|
}
|
|
|
|
ULONG64
|
|
GetPortData(
|
|
)
|
|
{
|
|
ULONG Ret;
|
|
ULONG64 PortDataPtr;
|
|
ULONG64 PortData;
|
|
|
|
PortDataPtr = GetExpression ("raidport!RaidpPortData");
|
|
if (PortDataPtr == 0) {
|
|
dprintf ("ERROR: couldn't get raidport!RaidpPortData\n");
|
|
return 0;
|
|
}
|
|
ReadPointer (PortDataPtr, &PortData);
|
|
|
|
return PortData;
|
|
}
|
|
|
|
|
|
VOID
|
|
ListAllAdapters(
|
|
IN ULONG Level
|
|
)
|
|
{
|
|
ULONG Ret;
|
|
ULONG64 PortDataPtr;
|
|
ULONG64 PortData;
|
|
ULONG64 ListHead;
|
|
ULONG64 NextEntry;
|
|
ULONG64 Driver;
|
|
ULONG Offset;
|
|
|
|
|
|
PortDataPtr = GetExpression ("raidport!RaidpPortData");
|
|
if (PortDataPtr == 0) {
|
|
dprintf ("ERROR: couldn't get raidport!RaidpPortData\n");
|
|
return;
|
|
}
|
|
ReadPointer (PortDataPtr, &PortData);
|
|
Ret = GetFieldOffset ("raidport!RAID_PORT_DATA",
|
|
"DriverList.List",
|
|
&Offset);
|
|
|
|
if (Ret != 0) {
|
|
dprintf ("ERROR: Could lookup RAID_PORT_DATA structure\n");
|
|
return ;
|
|
}
|
|
|
|
ListHead = PortData + Offset;
|
|
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: dumping adapter list at %I64x\n", ListHead);
|
|
}
|
|
|
|
dprintf ("Driver Object Ext State\n");
|
|
dprintf ("--------------------------------------------------------\n");
|
|
|
|
for (GetFieldValue (ListHead, "raidport!LIST_ENTRY", "Flink", NextEntry);
|
|
NextEntry != 0 && NextEntry != ListHead;
|
|
GetFieldValue (NextEntry, "raidport!LIST_ENTRY", "Flink", NextEntry)) {
|
|
|
|
GetFieldOffset ("raidport!RAID_DRIVER_EXTENSION", "DriverLink", &Offset);
|
|
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: ListEntry at %08x\n", NextEntry);
|
|
}
|
|
|
|
Driver = NextEntry - Offset;
|
|
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: Driver at %08x\n", Driver);
|
|
}
|
|
|
|
if (!CheckRaidObject (Driver, RaidDriverObject)) {
|
|
dprintf ("ERROR: %08x is not a driver object\n", Driver);
|
|
return;
|
|
}
|
|
|
|
if (CheckControlC()) {
|
|
return;
|
|
}
|
|
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: dumping driver at %I64x\n", Driver);
|
|
}
|
|
|
|
ListDriverAdapters (Driver, Level);
|
|
}
|
|
|
|
dprintf ("\n");
|
|
}
|
|
|
|
VOID
|
|
ListAdapterUnits(
|
|
IN ULONG64 Adapter,
|
|
IN ULONG Level
|
|
)
|
|
{
|
|
ULONG64 NextEntry;
|
|
ULONG64 Unit;
|
|
ULONG64 ListHead;
|
|
|
|
NextEntry = GetListHead (Adapter,
|
|
"raidport!RAID_ADAPTER_EXTENSION",
|
|
"UnitList.List.Flink",
|
|
&ListHead);
|
|
|
|
for ( ;
|
|
NextEntry != 0 && NextEntry != ListHead;
|
|
NextEntry = GetNextListEntry (NextEntry)) {
|
|
|
|
Unit = ContainingRecord (NextEntry,
|
|
"raidport!RAID_UNIT_EXTENSION",
|
|
"NextUnit");
|
|
|
|
if (!CheckRaidObject (Unit, RaidUnitObject)) {
|
|
dprintf ("ERROR: Object at %08x is not a raid unit object\n", Unit);
|
|
return;
|
|
}
|
|
|
|
if (CheckControlC()) {
|
|
return;
|
|
}
|
|
|
|
DumpUnit (Unit, Level);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ListDriverUnits(
|
|
IN ULONG64 Driver,
|
|
IN ULONG Level
|
|
)
|
|
{
|
|
ULONG64 ListHead;
|
|
ULONG64 Adapter;
|
|
ULONG64 NextEntry;
|
|
|
|
NextEntry = GetListHead (Driver,
|
|
"raidport!RAID_DRIVER_EXTENSION",
|
|
"AdapterList.List.Flink",
|
|
&ListHead);
|
|
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: ListHead = %08x, NextEntry = %08x\n",
|
|
(ULONG)ListHead, (ULONG)NextEntry);
|
|
}
|
|
|
|
for ( ;
|
|
NextEntry != 0 && NextEntry != ListHead;
|
|
NextEntry = GetNextListEntry (NextEntry)) {
|
|
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: Adapter ListEntry %08x\n", NextEntry);
|
|
}
|
|
|
|
Adapter = ContainingRecord (NextEntry,
|
|
"raidport!RAID_ADAPTER_EXTENSION",
|
|
"NextAdapter");
|
|
|
|
if (!CheckRaidObject (Adapter, RaidAdapterObject)) {
|
|
dprintf ("ERROR: Object at %08x not an raid adapter\n", Adapter);
|
|
return;
|
|
}
|
|
|
|
if (CheckControlC()) {
|
|
return;
|
|
}
|
|
|
|
ListAdapterUnits (Adapter, Level);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ListAllUnits(
|
|
IN ULONG Level
|
|
)
|
|
{
|
|
ULONG64 PortData;
|
|
ULONG64 NextEntry;
|
|
ULONG64 Driver;
|
|
ULONG64 ListHead;
|
|
|
|
PortData = GetPortData ();
|
|
|
|
NextEntry = GetListHead (PortData,
|
|
"raidport!RAID_PORT_DATA",
|
|
"DriverList.List.Flink",
|
|
&ListHead);
|
|
|
|
dprintf ("Product SCSI ID OBJ EXT Reqs State\n");
|
|
dprintf ("--------------------------------------------------------------\n");
|
|
|
|
for ( ;
|
|
NextEntry != 0 && NextEntry != ListHead;
|
|
NextEntry = GetNextListEntry (NextEntry)) {
|
|
|
|
Driver = ContainingRecord (NextEntry,
|
|
"raidport!RAID_DRIVER_EXTENSION",
|
|
"DriverLink");
|
|
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: dumping driver %08x\n", Driver);
|
|
}
|
|
|
|
if (!CheckRaidObject (Driver, RaidDriverObject)) {
|
|
dprintf ("ERROR: Object at %08x not a raid driver\n", Driver);
|
|
return;
|
|
}
|
|
|
|
if (CheckControlC()) {
|
|
return;
|
|
}
|
|
|
|
ListDriverUnits (Driver, Level);
|
|
}
|
|
|
|
dprintf ("\n");
|
|
}
|
|
|
|
|
|
|
|
PCHAR
|
|
StateToString(
|
|
IN ULONG State
|
|
)
|
|
{
|
|
if (State > 5) {
|
|
return "invalid state";
|
|
}
|
|
return StateTable[State];
|
|
}
|
|
|
|
|
|
ULONG64
|
|
GetDriverObject(
|
|
IN ULONG64 Driver
|
|
)
|
|
{
|
|
ULONG Ret;
|
|
CSHORT Type;
|
|
ULONG64 DriverObject;
|
|
|
|
if (CheckRaidObject (Driver, RaidDriverObject)) {
|
|
Ret = GetFieldData (Driver,
|
|
"raidport!RAID_DRIVER_EXTENSION",
|
|
"DriverObject",
|
|
sizeof (DriverObject),
|
|
&DriverObject);
|
|
|
|
if (Ret != 0) {
|
|
DriverObject = 0;
|
|
}
|
|
} else {
|
|
DriverObject = Driver;
|
|
}
|
|
|
|
Ret = GetFieldValue (DriverObject, "raidport!DRIVER_OBJECT", "Type", Type);
|
|
|
|
if (Ret != 0 || Type != IO_TYPE_DRIVER) {
|
|
DriverObject = 0;
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: %08x is not a RAID_DRIVER_EXTENSION or DRIVER_OBJECT\n");
|
|
}
|
|
}
|
|
|
|
return DriverObject;
|
|
}
|
|
|
|
|
|
VOID
|
|
GetDriverName(
|
|
IN ULONG64 Driver,
|
|
IN PUCHAR Buffer
|
|
)
|
|
{
|
|
ULONG Count;
|
|
ULONG Offset;
|
|
WCHAR UnicodeBuffer[256];
|
|
ULONG Ret;
|
|
ULONG BytesRead;
|
|
ULONG64 DriverObject;
|
|
ULONG64 String;
|
|
PWCHAR DriverName;
|
|
|
|
DriverObject = GetDriverObject (Driver);
|
|
|
|
if (DriverObject == 0) {
|
|
dprintf ("ERROR: %08x is not a driver\n", DriverObject);
|
|
return;
|
|
}
|
|
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: Getting driver name for DRIVER_OBJECT %08x\n", DriverObject);
|
|
}
|
|
|
|
Ret = GetFieldData (DriverObject,
|
|
"raidport!DRIVER_OBJECT",
|
|
"DriverName.Length",
|
|
sizeof (Count),
|
|
&Count);
|
|
|
|
if (Ret != 0) {
|
|
dprintf ("ERROR: couldn't get field of DRIVER_OBJECT. Symbols may be bad.\n");
|
|
return;
|
|
}
|
|
|
|
Ret = GetFieldOffset("raidport!DRIVER_OBJECT",
|
|
"DriverName.Buffer",
|
|
&Offset);
|
|
|
|
if (Ret != 0) {
|
|
dprintf ("ERROR: couldn't get field of DRIVER_OBJECT. Symbols may be bad.\n");
|
|
return;
|
|
}
|
|
|
|
if (Count > 0 && Count <= 256) {
|
|
ReadPointer (DriverObject + Offset, &String);
|
|
ReadMemory (String, UnicodeBuffer, Count, &BytesRead);
|
|
}
|
|
|
|
UnicodeBuffer[Count++] = '\000';
|
|
DriverName = wcsrchr (UnicodeBuffer, L'\\');
|
|
if (DriverName == NULL) {
|
|
DriverName = UnicodeBuffer;
|
|
} else {
|
|
DriverName++;
|
|
}
|
|
|
|
sprintf (Buffer, "%ws", DriverName);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
IsDeviceObject(
|
|
IN ULONG64 DeviceObject
|
|
)
|
|
{
|
|
CSHORT Type;
|
|
|
|
GetFieldValue (DeviceObject, "raidport!DEVICE_OBJECT", "Type", Type);
|
|
|
|
return (Type == IO_TYPE_DEVICE);
|
|
}
|
|
|
|
|
|
ULONG64
|
|
GetDeviceExtension(
|
|
IN ULONG64 DeviceObject
|
|
)
|
|
{
|
|
ULONG Ret;
|
|
ULONG Offset;
|
|
ULONG64 Extension = -1;
|
|
|
|
Ret = GetFieldOffset ("raidport!DEVICE_OBJECT",
|
|
"DeviceExtension",
|
|
&Offset);
|
|
|
|
if (Ret != 0) {
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: couldn't read DeviceExtension\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
ReadPointer (DeviceObject + Offset, &Extension);
|
|
|
|
return Extension;
|
|
}
|
|
|
|
ULONG
|
|
GetEmbeddedRemlockCount(
|
|
IN ULONG64 ObjectPtr,
|
|
IN PSZ ObjectType,
|
|
IN PSZ FieldName
|
|
)
|
|
{
|
|
ULONG Ret;
|
|
ULONG Remlock_IoCount;
|
|
ULONG Remlock_Offset;
|
|
ULONG Remlock_Common_Offset;
|
|
|
|
|
|
Remlock_IoCount = -1;
|
|
Ret = GetFieldOffset (ObjectType,
|
|
FieldName,
|
|
&Remlock_Offset);
|
|
if (Ret == STATUS_SUCCESS) {
|
|
Ret = GetFieldOffset ("raidport!IO_REMOVE_LOCK",
|
|
"Common",
|
|
&Remlock_Common_Offset);
|
|
if (Ret == STATUS_SUCCESS) {
|
|
GetFieldData (ObjectPtr + Remlock_Offset + Remlock_Common_Offset,
|
|
"raidport!IO_REMOVE_LOCK_COMMON_BLOCK",
|
|
"IoCount",
|
|
sizeof (Remlock_IoCount),
|
|
&Remlock_IoCount);
|
|
}
|
|
}
|
|
|
|
if (Ret != STATUS_SUCCESS) {
|
|
printf ("WARN: couldn't get IO_REMOVE_LOCK status\n");
|
|
}
|
|
|
|
return Remlock_IoCount;
|
|
}
|
|
|
|
|
|
|
|
ULONG64
|
|
GetAdapterExtension(
|
|
IN ULONG64 Adapter
|
|
)
|
|
{
|
|
ULONG64 Temp;
|
|
ULONG64 AdapterExt;
|
|
ULONG64 DeviceObject;
|
|
|
|
|
|
if (CheckRaidObject (Adapter, RaidAdapterObject)) {
|
|
AdapterExt = Adapter;
|
|
InitTypeRead (AdapterExt, raidport!RAID_ADAPTER_EXTENSION);
|
|
DeviceObject = ReadField (DeviceObject);
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: Checking if %08x is a device object\n", DeviceObject);
|
|
}
|
|
if (IsDeviceObject (DeviceObject)) {
|
|
Temp = GetDeviceExtension (DeviceObject);
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: Ext = %08x, Computed Ext = %08x\n",
|
|
AdapterExt, Temp);
|
|
}
|
|
if (Temp == AdapterExt) {
|
|
return AdapterExt;
|
|
}
|
|
} else {
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: %08x is not a device object\n", DeviceObject);
|
|
}
|
|
}
|
|
} else {
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: %08x not a RaidAdapterObject\n");
|
|
}
|
|
}
|
|
|
|
if (IsDeviceObject (Adapter)) {
|
|
AdapterExt = GetDeviceExtension (Adapter);
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: Checking if %08x is an adapter extension\n", AdapterExt);
|
|
}
|
|
if (CheckRaidObject (AdapterExt, RaidAdapterObject)) {
|
|
InitTypeRead (AdapterExt, raidport!RAID_ADAPTER_EXTENSION);
|
|
DeviceObject = ReadField (DeviceObject);
|
|
if (DeviceObject == Adapter) {
|
|
return AdapterExt;
|
|
} else if (Verbose) {
|
|
dprintf ("VERBOSE: DO %I64x != Adapter %I64x\n",
|
|
(ULONG)DeviceObject,
|
|
(ULONG)Adapter);
|
|
}
|
|
|
|
} else if (Verbose) {
|
|
dprintf ("VERBOSE: Ext %08x not RaidAdapterObject\n",
|
|
(ULONG)AdapterExt);
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
VOID
|
|
DumpMiniport(
|
|
IN ULONG64 AdapterPtr
|
|
)
|
|
{
|
|
ULONG Ret;
|
|
ULONG Offset;
|
|
ULONG64 HwDeviceExt;
|
|
ULONG64 DeviceExtPtr;
|
|
ULONG64 MiniportPtr;
|
|
ULONG64 HwInitData;
|
|
|
|
//
|
|
// PortConfig 80000000 HwInitData 77000000 HwDeviceExt a0000000 27 bytes
|
|
// LuExt 32 bytes SrbExt 32 bytes
|
|
//
|
|
|
|
GetFieldOffset ("raidport!RAID_ADAPTER_EXTENSION",
|
|
"Miniport",
|
|
&Offset);
|
|
MiniportPtr = AdapterPtr + Offset;
|
|
|
|
InitTypeRead (MiniportPtr, raidport!RAID_MINIPORT);
|
|
|
|
HwInitData = ReadField (HwInitializationData);
|
|
|
|
GetFieldOffset ("raidport!RAID_MINIPORT",
|
|
"PortConfiguration",
|
|
&Offset);
|
|
|
|
dprintf (" PortConfig %08x HwInit %08x\n", (ULONG)(MiniportPtr + Offset),
|
|
(ULONG)HwInitData);
|
|
|
|
DeviceExtPtr = ReadField (PrivateDeviceExt);
|
|
|
|
if (DeviceExtPtr == 0) {
|
|
HwDeviceExt = 0;
|
|
} else {
|
|
Ret = GetFieldOffset ("raidport!RAID_HW_DEVICE_EXT",
|
|
"HwDeviceExtension",
|
|
&Offset);
|
|
if (Ret != 0) {
|
|
HwDeviceExt = 0;
|
|
} else {
|
|
HwDeviceExt = DeviceExtPtr + Offset;
|
|
}
|
|
}
|
|
|
|
InitTypeRead (HwInitData, raidport!HW_INITIALIZATION_DATA);
|
|
|
|
dprintf (" HwDeviceExt %08x %d bytes\n",
|
|
(ULONG)HwDeviceExt, (ULONG)ReadField (DeviceExtensionSize));
|
|
|
|
dprintf (" LuExt %d bytes SrbExt %d bytes\n",
|
|
(ULONG)ReadField (SpecificLuExtensionSize),
|
|
(ULONG)ReadField (SrbExtensionSize));
|
|
}
|
|
|
|
VOID
|
|
DumpAdapter(
|
|
IN ULONG64 Adapter,
|
|
IN ULONG Level
|
|
)
|
|
/*++
|
|
|
|
ADAPTER f0345600
|
|
Ext 8e000000 Driver 8000000 Next 8000000 Working
|
|
LDO 80000000 PDO 00000000 HwExt 00000000
|
|
SlowLock Free RemLock 10 Power D0 S0 Full Duplex
|
|
Bus 08080808 Number 1 Slot 0 Dma 88888888 Interrupt 88888888
|
|
AdQueue: Outstanding 200, Low 100, High 200 Busy
|
|
ResourceList: Allocated 80808080 Translated 80808080
|
|
|
|
MappedAddressList:
|
|
|
|
Virtual Physical Size Bus
|
|
80808080 8000000000000000 1500 1
|
|
80808080 8000000000000000 1500 1
|
|
80808080 8000000000000000 1500 1
|
|
80808080 8000000000000000 1500 1
|
|
80808080 8000000000000000 1500 1
|
|
80808080 8000000000000000 1500 1
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
{
|
|
ULONG64 AdapterPtr;
|
|
ULONG64 Driver;
|
|
CHAR DriverName[100];
|
|
|
|
if (Verbose) {
|
|
dprintf ("VERBOSE: dumping adapter %08x\n", Adapter);
|
|
}
|
|
|
|
AdapterPtr = GetAdapterExtension (Adapter);
|
|
|
|
if (AdapterPtr == 0) {
|
|
dprintf ("ERROR: %08x is not a valid adapter object\n", Adapter);
|
|
return;
|
|
}
|
|
|
|
if (Level == 0) {
|
|
|
|
Driver = ReadField (Driver);
|
|
GetDriverName (Driver, DriverName);
|
|
dprintf ("%8.8s %08x %08x %s\n",
|
|
DriverName,
|
|
(ULONG)ReadField (DeviceObject),
|
|
(ULONG)Adapter,
|
|
StateToString ((ULONG)ReadField (DeviceState))
|
|
);
|
|
} else {
|
|
PSZ Adapter_SlowLock;
|
|
ULONG Remlock_IoCount;
|
|
|
|
|
|
dprintf ("ADAPTER %08x\n", ReadField (DeviceObject));
|
|
dprintf (" Ext %08x Driver %08x Next %08x %s\n",
|
|
(ULONG)AdapterPtr,
|
|
(ULONG)ReadField (Driver),
|
|
(ULONG)0,
|
|
StateToString ((ULONG)ReadField (DeviceState)));
|
|
|
|
|
|
dprintf (" LDO %08x PDO %08x\n",
|
|
(ULONG)ReadField (LowerDeviceObject),
|
|
(ULONG)ReadField (PhysicalDeviceObject));
|
|
|
|
if (ReadField ("SlowLock") == 0) {
|
|
Adapter_SlowLock = "Free";
|
|
} else {
|
|
Adapter_SlowLock = "Held";
|
|
}
|
|
|
|
Remlock_IoCount = GetEmbeddedRemlockCount (AdapterPtr,
|
|
"raidport!RAID_ADAPTER_EXTENSION",
|
|
"RemoveLock");
|
|
|
|
dprintf (" SlowLock %s RemLock %d Power %s %s %s\n",
|
|
Adapter_SlowLock,
|
|
Remlock_IoCount,
|
|
"S0", "D0",
|
|
(ReadField (Mode) == RaidSynchronizeFullDuplex ?
|
|
"Full Duplex" :
|
|
"Half Duplex")
|
|
);
|
|
|
|
dprintf (" Bus %08x Number %d Slot %d Dma %08x Interrupt %08x\n",
|
|
(ULONG)0,
|
|
(ULONG)ReadField (BusNumber),
|
|
(ULONG)ReadField (SlotNumber),
|
|
(ULONG)ReadField (Dma.DmaAdapter),
|
|
(ULONG)ReadField (Interrupt));
|
|
|
|
dprintf (" ResourceList: Allocated %08x Translated %08x\n",
|
|
(ULONG)ReadField (ResourceList.AllocatedResources),
|
|
(ULONG)ReadField (ResourceList.TranslatedResources));
|
|
|
|
dprintf (" Gateway: Outstanding %d Lower %d High %d\n",
|
|
ReadField (AdapterQueue->Outstanding),
|
|
ReadField (AdapterQueue->LowWaterMark),
|
|
ReadField (AdapterQueue->HighWaterMark));
|
|
|
|
DumpMiniport (AdapterPtr);
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
FixPaddedString(
|
|
PSZ String
|
|
)
|
|
{
|
|
ULONG Pos;
|
|
|
|
Pos = strlen (String);
|
|
if (Pos > 0) {
|
|
Pos--;
|
|
}
|
|
|
|
while (Pos && String[Pos] == ' ') {
|
|
String[Pos--] = '\000';
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
GetUnitProductInfo(
|
|
ULONG64 Unit,
|
|
PSZ VendorId,
|
|
PSZ ProductId,
|
|
PSZ Revision
|
|
)
|
|
{
|
|
ULONG Offset;
|
|
ULONG64 InquiryData;
|
|
|
|
GetFieldOffset ("raidport!RAID_UNIT_EXTENSION",
|
|
"InquiryData",
|
|
&Offset);
|
|
|
|
ReadPointer (Unit + Offset, &InquiryData);
|
|
|
|
if (VendorId) {
|
|
ZeroMemory (VendorId, 9);
|
|
GetFieldData (InquiryData,
|
|
"raidport!INQUIRYDATA",
|
|
"VendorId",
|
|
8,
|
|
VendorId);
|
|
FixPaddedString (VendorId);
|
|
}
|
|
|
|
if (ProductId) {
|
|
ZeroMemory (ProductId, 17);
|
|
GetFieldData (InquiryData,
|
|
"raidport!INQUIRYDATA",
|
|
"ProductId",
|
|
16,
|
|
ProductId);
|
|
FixPaddedString (ProductId);
|
|
}
|
|
|
|
if (Revision) {
|
|
ZeroMemory (Revision, 5);
|
|
GetFieldData (InquiryData,
|
|
"raidport!INQUIRYDATA",
|
|
"ProductRevisionLevel",
|
|
4,
|
|
Revision);
|
|
FixPaddedString (Revision);
|
|
}
|
|
}
|
|
|
|
|
|
ULONG
|
|
GetUnitIoQueueRequests(
|
|
IN ULONG64 UnitPtr
|
|
)
|
|
{
|
|
ULONG Ret;
|
|
ULONG64 Unit_IoQueue;
|
|
ULONG64 IoQueue_DeviceQueue;
|
|
ULONG Offset;
|
|
ULONG Requests;
|
|
|
|
Ret = GetFieldOffset ("raidport!RAID_UNIT_EXTENSION",
|
|
"IoQueue",
|
|
&Offset);
|
|
|
|
if (Ret != STATUS_SUCCESS) {
|
|
dprintf ("WARN: failed to get IoQueue offset from unit.\n");
|
|
}
|
|
|
|
Unit_IoQueue = UnitPtr + Offset;
|
|
|
|
Ret = GetFieldOffset ("raidport!IO_QUEUE",
|
|
"DeviceQueue",
|
|
&Offset);
|
|
if (Ret != STATUS_SUCCESS) {
|
|
dprintf ("WARN: failed to get DeviceQueue offset from unit(1).\n");
|
|
}
|
|
|
|
IoQueue_DeviceQueue = Unit_IoQueue + Offset;
|
|
|
|
GetFieldData (IoQueue_DeviceQueue,
|
|
"raidport!EXTENDED_DEVICE_QUEUE",
|
|
"OutstandingRequests",
|
|
sizeof (Requests),
|
|
&Requests);
|
|
|
|
return Requests;
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpUnit(
|
|
IN ULONG64 Unit,
|
|
IN ULONG Level
|
|
)
|
|
{
|
|
ULONG64 UnitPtr;
|
|
CSHORT DeviceObject_Type;
|
|
|
|
GetFieldValue (Unit, "raidport!DEVICE_OBJECT", "Type", DeviceObject_Type);
|
|
|
|
if (DeviceObject_Type == IO_TYPE_DEVICE) {
|
|
GetFieldValue (Unit, "raidport!DEVICE_OBJECT", "DeviceExtension", UnitPtr);
|
|
if (!CheckRaidObject (UnitPtr, RaidUnitObject)) {
|
|
dprintf ("ERROR: DeviceObject %8.8x is not a raid unit\n", UnitPtr);
|
|
return;
|
|
}
|
|
} else if (CheckRaidObject (Unit, RaidUnitObject)) {
|
|
UnitPtr = Unit;
|
|
} else {
|
|
dprintf ("ERROR: Pointer %8.8x is not a device object or raid unit object\n",
|
|
Unit);
|
|
return;
|
|
}
|
|
|
|
InitTypeRead (UnitPtr, raidport!RAID_UNIT_EXTENSION);
|
|
|
|
if (Level == 0) {
|
|
|
|
CHAR VendorId[9] = {0};
|
|
CHAR ProductId[17] = {0};
|
|
CHAR Product[25];
|
|
|
|
GetUnitProductInfo (UnitPtr, VendorId, ProductId, NULL);
|
|
|
|
sprintf (Product, "%s %s", VendorId, ProductId);
|
|
|
|
|
|
dprintf ("%-15.15s %3d %3d %3d %08x %08x %-3d %-8.8s\n",
|
|
Product,
|
|
(ULONG)ReadField (PathId),
|
|
(ULONG)ReadField (TargetId),
|
|
(ULONG)ReadField (Lun),
|
|
(ULONG)ReadField (DeviceObject),
|
|
(ULONG)UnitPtr,
|
|
GetUnitIoQueueRequests (UnitPtr),
|
|
StateToString ((ULONG)ReadField (DeviceState)));
|
|
} else {
|
|
|
|
ULONG Ret;
|
|
ULONG Remlock_IoCount;
|
|
ULONG Remlock_Offset;
|
|
ULONG Remlock_Common_Offset;
|
|
PCHAR SlowLock;
|
|
ULONG64 Unit_QueueFrozen;
|
|
ULONG64 Unit_QueueLocked;
|
|
ULONG64 Unit_TagList;
|
|
ULONG64 Unit_IoQueue;
|
|
ULONG64 IoQueue_DeviceQueue;
|
|
ULONG Offset;
|
|
ULONG Device_Offset;
|
|
ULONG ByPass_Offset;
|
|
ULONG64 Pointer;
|
|
CHAR VendorId[9] = {0};
|
|
CHAR ProductId[17] = {0};
|
|
CHAR Revision[5] = {0};
|
|
ULONG64 InquiryData;
|
|
|
|
|
|
dprintf ("UNIT %08x\n", ReadField (DeviceObject));
|
|
dprintf (" Ext %08x Adapter %08x Next %08x %s\n",
|
|
(ULONG)UnitPtr,
|
|
(ULONG)ReadField(Adapter),
|
|
(ULONG) 0 /*BUGBUG: pull out NextField*/,
|
|
StateToString((ULONG)ReadField(DeviceState)));
|
|
|
|
GetFieldOffset ("raidport!RAID_UNIT_EXTENSION",
|
|
"InquiryData",
|
|
&Offset);
|
|
|
|
ReadPointer (UnitPtr + Offset, &InquiryData);
|
|
|
|
GetUnitProductInfo (UnitPtr, VendorId, ProductId, Revision);
|
|
|
|
dprintf (" SCSI %d %d %d %s %s %s Inquiry %08x\n",
|
|
(ULONG)ReadField(PathId),
|
|
(ULONG)ReadField(TargetId),
|
|
(ULONG)ReadField(Lun),
|
|
VendorId,
|
|
ProductId,
|
|
Revision,
|
|
(ULONG)InquiryData);
|
|
|
|
Remlock_IoCount = -1;
|
|
Ret = GetFieldOffset ("raidport!RAID_UNIT_EXTENSION",
|
|
"RemoveLock",
|
|
&Remlock_Offset);
|
|
if (Ret == STATUS_SUCCESS) {
|
|
Ret = GetFieldOffset ("raidport!IO_REMOVE_LOCK",
|
|
"Common",
|
|
&Remlock_Common_Offset);
|
|
if (Ret == STATUS_SUCCESS) {
|
|
GetFieldData (UnitPtr + Remlock_Offset + Remlock_Common_Offset,
|
|
"raidport!IO_REMOVE_LOCK_COMMON_BLOCK",
|
|
"IoCount",
|
|
sizeof (Remlock_IoCount),
|
|
&Remlock_IoCount);
|
|
}
|
|
}
|
|
|
|
if (Ret != STATUS_SUCCESS) {
|
|
printf ("WARN: couldn't get IO_REMOVE_LOCK status\n");
|
|
}
|
|
|
|
|
|
if (ReadField ("SlowLock") == 0) {
|
|
SlowLock = "Free";
|
|
} else {
|
|
SlowLock = "Held";
|
|
}
|
|
|
|
dprintf (" SlowLock %s RemLock %d PageCount %d\n",
|
|
SlowLock,
|
|
Remlock_IoCount,
|
|
(ULONG)ReadField (PagingPathCount));
|
|
|
|
Pointer = ReadField (SrbExtensionRegion.VirtualBase);
|
|
dprintf (" SrbExtension Size %d Start %08x End %08x\n",
|
|
0, // BUGBUG: Get srb extension size from the miniport
|
|
(ULONG)Pointer,
|
|
(ULONG)Pointer + (ULONG)ReadField (SrbExtensionRegion.Length));
|
|
|
|
Ret = GetFieldOffset ("raidport!RAID_UNIT_EXTENSION",
|
|
"TagList",
|
|
&Offset);
|
|
|
|
if (Ret != STATUS_SUCCESS) {
|
|
dprintf ("WARN: Couldn't read TagList field\n");
|
|
}
|
|
|
|
Unit_QueueFrozen = ReadField (Flags.QueueFrozen);
|
|
Unit_QueueLocked = ReadField (Flags.QueueLocked);
|
|
|
|
Unit_TagList = UnitPtr + Offset;
|
|
|
|
dprintf (" TagList %08x (%d of %d used)\n",
|
|
(ULONG)(Unit_TagList),
|
|
(ULONG)ReadField(TagList.OutstandingTags),
|
|
(ULONG)ReadField(TagList.Count));
|
|
|
|
Ret = GetFieldOffset ("raidport!RAID_UNIT_EXTENSION",
|
|
"IoQueue",
|
|
&Offset);
|
|
|
|
if (Ret != STATUS_SUCCESS) {
|
|
dprintf ("WARN: failed to get IoQueue offset from unit.\n");
|
|
}
|
|
Unit_IoQueue = UnitPtr + Offset;
|
|
|
|
Ret = GetFieldOffset ("raidport!IO_QUEUE",
|
|
"DeviceQueue",
|
|
&Offset);
|
|
if (Ret != STATUS_SUCCESS) {
|
|
dprintf ("WARN: failed to get DeviceQueue offset from unit.\n");
|
|
}
|
|
|
|
IoQueue_DeviceQueue = Unit_IoQueue + Offset;
|
|
InitTypeRead (IoQueue_DeviceQueue, raidport!EXTENDED_DEVICE_QUEUE);
|
|
|
|
dprintf (" IoQueue %s %s; Outstanding %d Device %d ByPass %d\n",
|
|
Unit_QueueFrozen ? "Frozen" : "Unfrozen",
|
|
Unit_QueueLocked ? "Locked" : "Unlocked",
|
|
(ULONG)ReadField(OutstandingRequests),
|
|
(ULONG)ReadField(DeviceRequests),
|
|
(ULONG)ReadField(ByPassRequests));
|
|
|
|
Ret = GetFieldOffset ("raidport!EXTENDED_DEVICE_QUEUE",
|
|
"DeviceListHead",
|
|
&Device_Offset);
|
|
|
|
if (Ret != STATUS_SUCCESS) {
|
|
dprintf ("WARN: offset of DeviceListHead within EXTENDED_DEVICE_QUEUE failed\n");
|
|
}
|
|
|
|
Ret = GetFieldOffset ("raidport!EXTENDED_DEVICE_QUEUE",
|
|
"ByPassListHead",
|
|
&ByPass_Offset);
|
|
|
|
|
|
if (Ret != STATUS_SUCCESS) {
|
|
dprintf ("WARN: offset of ByPassListHead within EXTENDED_DEVICE_QUEUE failed\n");
|
|
}
|
|
|
|
dprintf (" Depth %d DeviceList %08x ByPassList %08x\n",
|
|
(ULONG)ReadField(Depth),
|
|
(ULONG)(IoQueue_DeviceQueue + Device_Offset),
|
|
(ULONG)(IoQueue_DeviceQueue + ByPass_Offset));
|
|
}
|
|
|
|
|
|
/*
|
|
|
|
UNIT 8f888888
|
|
Ext 8e000000 Adapter 8100000000 Next 8e888888 Working
|
|
SCSI [3, 0, 0] MYLEX DAC960 122222 InquiryData 08080808
|
|
SlowLock Free RemLock 10 PageCount 20
|
|
SrbExtension Size 20 VA Start 90000000 End 20000000
|
|
TagList 08080808 (20 of 256 used)
|
|
IoQueue Unfrozen Unlocked; Outstanding 200, Device 200, ByPass 200
|
|
Depth 254 DeviceListHead 00000000 ByPassListHead 88888888
|
|
|
|
Outstanding IRPs:
|
|
|
|
IRP 00000000 Scsi ExecuteScsi function
|
|
IRP 00000000 Scsi ExecuteScsi function
|
|
IRP 00000000 Scsi ExecuteScsi function
|
|
IRP 00000000 Scsi ExecuteScsi function
|
|
IRP 00000000 Scsi ExecuteScsi function
|
|
IRP 00000000 Scsi ExecuteScsi function
|
|
IRP 00000000 Scsi ExecuteScsi function
|
|
IRP 00000000 Scsi ExecuteScsi function
|
|
|
|
Device IRPs:
|
|
|
|
IRP 00000000 ssssssssssssssssssssssss
|
|
IRP 00000000 ssssssssssssssssssssssss
|
|
IRP 00000000 ssssssssssssssssssssssss
|
|
IRP 00000000 ssssssssssssssssssssssss
|
|
IRP 00000000 ssssssssssssssssssssssss
|
|
|
|
ByPass IRPs:
|
|
|
|
IRP 00000000 ssssssssssssssssssssssss
|
|
IRP 00000000 ssssssssssssssssssssssss
|
|
IRP 00000000 ssssssssssssssssssssssss
|
|
IRP 00000000 ssssssssssssssssssssssss
|
|
IRP 00000000 ssssssssssssssssssssssss
|
|
|
|
|
|
*/
|
|
}
|
|
|
|
|
|
VOID
|
|
ParseArgs(
|
|
IN PSZ Args,
|
|
OUT PULONG64 UnitPtr,
|
|
OUT PULONG Level
|
|
)
|
|
{
|
|
LONG Unit;
|
|
|
|
*UnitPtr = -1;
|
|
*Level = 0;
|
|
|
|
if (Args[0] != '\000') {
|
|
Unit = (LONG)strtoul (Args, &Args, 16);
|
|
*UnitPtr = (ULONG64)(LONG64)Unit;
|
|
|
|
if (Args[0] != '\000') {
|
|
strtoul (Args, &Args, 10);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
DECLARE_API ( unit )
|
|
{
|
|
ULONG Level;
|
|
ULONG64 Unit;
|
|
|
|
Unit = -1;
|
|
Level = -1;
|
|
|
|
ParseArgs ( (PSZ)args, &Unit, &Level);
|
|
|
|
if (Unit == -1) {
|
|
if (Level == -1) {
|
|
Level = 1;
|
|
}
|
|
ListAllUnits (Level);
|
|
} else {
|
|
if (Level == -1) {
|
|
Level = 2;
|
|
}
|
|
DumpUnit (Unit, 2);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
DECLARE_API ( adapter )
|
|
{
|
|
ULONG Level;
|
|
ULONG64 Adapter;
|
|
|
|
Adapter = -1;
|
|
Level = -1;
|
|
|
|
ParseArgs ( (PSZ)args, &Adapter, &Level);
|
|
|
|
if (Adapter == -1) {
|
|
if (Level == -1) {
|
|
Level = 1;
|
|
}
|
|
ListAllAdapters (Level);
|
|
} else {
|
|
if (Level == -1) {
|
|
Level = 2;
|
|
}
|
|
DumpAdapter (Adapter, 2);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
DECLARE_API ( verbose )
|
|
{
|
|
ULONG NewValue;
|
|
|
|
NewValue = strtoul (args, NULL, 16);
|
|
dprintf ("Setting Verbose from %d to %d\n", (ULONG)Verbose, (ULONG)NewValue);
|
|
Verbose = (BOOLEAN) NewValue;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DECLARE_API ( help )
|
|
{
|
|
dprintf (" !raid.help [command] - Get help.\n");
|
|
dprintf (" !raid.adapter [adapter [detail]] - Get adapter information.\n");
|
|
dprintf (" !raid.unit [unit [detail]] - Get unit information.\n");
|
|
|
|
#if 0
|
|
if (args != NULL && (_stricmp (args, "adapter") == 00)) {
|
|
dprintf ("------------------------------------------------------------------------------\n");
|
|
dprintf ("\n");
|
|
dprintf ("NAME:\n");
|
|
dprintf ("\n");
|
|
dprintf (" !raid.adapter\n");
|
|
dprintf ("\n");
|
|
dprintf ("USAGE:\n");
|
|
dprintf ("\n");
|
|
dprintf (" adapter [ADAPTER-OBJECT [DETAIL-LEVEL]]\n");
|
|
dprintf ("\n");
|
|
dprintf ("ARGUMENTS:\n");
|
|
dprintf ("\n");
|
|
dprintf (" ADAPTER-OBJECT - Pointer to a device object representing an adapter\n");
|
|
dprintf (" or pointer to an adapter extension. If ADAPTER is 0 or the\n");
|
|
dprintf (" argument is not present, the command will dump information about\n");
|
|
dprintf (" all adapters, not just the adapter specified.\n");
|
|
dprintf ("\n");
|
|
dprintf (" DETAIL-LEVEL - Detail level for dump adapter structs.\n");
|
|
dprintf ("\n");
|
|
dprintf ("-----------------------------------------------------------------------------\n");
|
|
} else if (args != NULL && (_stricmp (args, "unit") == 00)) {
|
|
dprintf ("Unit help\n");
|
|
} else {
|
|
dprintf (" !raid.help [command] - Get help.\n");
|
|
dprintf (" !raid.adapter [adapter [detail]] - Get adapter information.\n");
|
|
dprintf (" !raid.unit [unit [detail]] - Get unit information.\n");
|
|
}
|
|
#endif
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|