#ifndef _GEN_DSM_H_ #define _GEN_DSM_H_ #include #include #include "dsm.h" // // Set an arbitrary limit of 4 paths. // #define MAX_PATHS 4 // // Device State defines. // #define DEV_ACTIVE 0x00000001 #define DEV_PASSIVE 0x00000002 #define DEV_FAILED 0x00000003 #define DEV_PENDING_REMOVE 0x00000004 #define DEV_REMOVED 0x00000005 // // Multi-path Group State // // // Fail-Over Group State // #define FG_NORMAL 0x00000001 #define FG_PENDING 0x00000002 #define FG_FAILBACK 0x00000003 #define FG_FAILED 0x00000004 // // Load-Balance Types // #define LB_ACTIVE_PASSIVE 0x01 #define LB_STATIC 0x02 #define LB_MIN_QUEUE 0x03 #define LB_ROUNDROBIN 0x04 #define DSM_DEVICE_SIG 0xAAAAAAAA #define DSM_GROUP_SIG 0x55555555 #define DSM_FOG_SIG 0x88888888 // // Internal structures. // // // Statistics structure. Used by the device // and path routines. // typedef struct _DSM_STATS { ULONG NumberReads; LARGE_INTEGER BytesRead; ULONG NumberWrites; LARGE_INTEGER BytesWritten; } DSM_STATS, *PDSM_STATS; // // Dsm Context is the global driver // context that gets pushed to each of // the dsm entry points. // typedef struct _DSM_CONTEXT { UNICODE_STRING SupportedDevices; KSPIN_LOCK SpinLock; ULONG NumberDevices; ULONG NumberGroups; ULONG NumberFOGroups; LIST_ENTRY DeviceList; LIST_ENTRY GroupList; LIST_ENTRY FailGroupList; PVOID MPIOContext; ULONG ControllerId; NPAGED_LOOKASIDE_LIST ContextList; } DSM_CONTEXT, *PDSM_CONTEXT; typedef struct _GROUP_ENTRY; typedef struct _FAILOVER_GROUP; // // Information about each device that's // supported. // typedef struct _DEVICE_INFO { LIST_ENTRY ListEntry; ULONG DeviceSig; PVOID DsmContext; PDEVICE_OBJECT PortPdo; PDEVICE_OBJECT TargetObject; struct _GROUP_ENTRY *Group; struct _FAILOVER_GROUP *FailGroup; ULONG State; BOOLEAN NeedsVerification; UCHAR Reserved[3]; LONG Requests; DSM_STATS Stats; PUCHAR SerialNumber; STORAGE_DEVICE_DESCRIPTOR Descriptor; } DEVICE_INFO, *PDEVICE_INFO; // // Information about multi-path groups: // The same device found via multiple paths. // typedef struct _GROUP_ENTRY { LIST_ENTRY ListEntry; ULONG GroupSig; ULONG GroupNumber; BOOLEAN LoadBalanceInit; UCHAR LoadBalanceType; UCHAR Reserved[2]; ULONG NumberDevices; PDEVICE_INFO DeviceList[MAX_PATHS]; } GROUP_ENTRY, *PGROUP_ENTRY; // // The collection of devices on one path. // These fail-over as a unit. // typedef struct _FAILOVER_GROUP { LIST_ENTRY ListEntry; ULONG FailOverSig; PVOID PathId; PDEVICE_OBJECT MPIOPath; PVOID AlternatePath; ULONG State; ULONG Count; // // BUGBUG: Revisit using an array // PDEVICE_INFO DeviceList[32]; } FAILOVER_GROUP, *PFAILOVER_GROUP; // // Completion context structure. // typedef struct _COMPLETION_CONTEXT { LARGE_INTEGER TickCount; PDEVICE_INFO DeviceInfo; PDSM_CONTEXT DsmContext; } COMPLETION_CONTEXT, *PCOMPLETION_CONTEXT; NTSTATUS DsmInquire ( IN PVOID DsmContext, IN PDEVICE_OBJECT TargetDevice, IN PDEVICE_OBJECT PortObject, IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor, IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceIdList, OUT PVOID *DsmIdentifier ); BOOLEAN DsmCompareDevices( IN PVOID DsmContext, IN PVOID DsmId1, IN PVOID DsmId2 ); NTSTATUS DsmSetDeviceInfo( IN PVOID DsmContext, IN PDEVICE_OBJECT TargetObject, IN PVOID DsmId, IN OUT PVOID *PathId ); NTSTATUS DsmGetControllerInfo( IN PVOID DsmContext, IN PVOID DsmId, IN ULONG Flags, IN OUT PCONTROLLER_INFO *ControllerInfo ); BOOLEAN DsmIsPathActive( IN PVOID DsmContext, IN PVOID PathId ); NTSTATUS DsmPathVerify( IN PVOID DsmContext, IN PVOID DsmId, IN PVOID PathId ); NTSTATUS DsmInvalidatePath( IN PVOID DsmContext, IN ULONG ErrorMask, IN PVOID PathId, IN OUT PVOID *NewPathId ); NTSTATUS DsmMoveDevice( IN PVOID DsmContext, IN PDSM_IDS DsmIds, IN PVOID MPIOPath, IN PVOID SuggestedPath, IN ULONG Flags ); NTSTATUS DsmRemovePending( IN PVOID DsmContext, IN PVOID DsmId ); NTSTATUS DsmRemoveDevice( IN PVOID DsmContext, IN PVOID DsmId, IN PVOID PathId ); NTSTATUS DsmRemovePath( IN PDSM_CONTEXT DsmContext, IN PVOID PathId ); NTSTATUS DsmBringPathOnLine( IN PVOID DsmContext, IN PVOID PathId, OUT PULONG DSMError ); PVOID DsmLBGetPath( IN PVOID DsmContext, IN PSCSI_REQUEST_BLOCK Srb, IN PDSM_IDS DsmList, IN PVOID CurrentPath, OUT NTSTATUS *Status ); ULONG DsmCategorizeRequest( IN PVOID DsmContext, IN PDSM_IDS DsmIds, IN PIRP Irp, IN PSCSI_REQUEST_BLOCK Srb, IN PVOID CurrentPath, OUT PVOID *PathId, OUT NTSTATUS *Status ); NTSTATUS DsmBroadcastRequest( IN PVOID DsmContext, IN PDSM_IDS DsmIds, IN PIRP Irp, IN PSCSI_REQUEST_BLOCK Srb, IN PKEVENT Event ); NTSTATUS DsmSrbDeviceControl( IN PVOID DsmContext, IN PDSM_IDS DsmIds, IN PIRP Irp, IN PSCSI_REQUEST_BLOCK Srb, IN PKEVENT Event ); VOID DsmSetCompletion( IN PVOID DsmContext, IN PVOID DsmId, IN PIRP Irp, IN PSCSI_REQUEST_BLOCK Srb, IN OUT PDSM_COMPLETION_INFO DsmCompletion ); ULONG DsmInterpretError( IN PVOID DsmContext, IN PVOID DsmId, IN PSCSI_REQUEST_BLOCK Srb, IN OUT NTSTATUS *Status, OUT PBOOLEAN Retry ); NTSTATUS DsmUnload( IN PVOID DsmContext ); // // Various utility functions. // VOID DsmWmiInitialize( IN PDSM_WMILIB_CONTEXT WmiInfo ); PGROUP_ENTRY DsmFindDevice( IN PDSM_CONTEXT DsmContext, IN PDEVICE_INFO DeviceInfo ); PGROUP_ENTRY DsmBuildGroupEntry ( IN PDSM_CONTEXT DsmContext, IN PDEVICE_INFO deviceInfo ); NTSTATUS DsmAddGroupEntry( IN PDSM_CONTEXT DsmContext, IN PGROUP_ENTRY Group ); NTSTATUS DsmAddDeviceEntry( IN PDSM_CONTEXT DsmContext, IN PGROUP_ENTRY Group, IN PDEVICE_INFO DeviceInfo, IN ULONG DeviceState ); VOID DsmRemoveDeviceEntry( IN PDSM_CONTEXT DsmContext, IN PGROUP_ENTRY Group, IN PDEVICE_INFO DeviceInfo ); PFAILOVER_GROUP DsmFindFOGroup( IN PDSM_CONTEXT DsmContext, IN PVOID PathId ); PFAILOVER_GROUP DsmBuildFOGroup( IN PDSM_CONTEXT DsmContext, IN PDEVICE_INFO DeviceInfo, IN PVOID PathId ); NTSTATUS DsmUpdateFOGroup( IN PDSM_CONTEXT DsmContext, IN PFAILOVER_GROUP FailGroup, IN PDEVICE_INFO DeviceInfo ); VOID DsmRemoveDeviceFailGroup( IN PDSM_CONTEXT DsmContext, IN PFAILOVER_GROUP FailGroup, IN PDEVICE_INFO DeviceInfo ); PFAILOVER_GROUP DsmSetNewPath( IN PDSM_CONTEXT DsmContext, IN PGROUP_ENTRY Group, IN PDEVICE_INFO FailingDevice, IN PFAILOVER_GROUP SelectedPath ); VOID DsmLBInit( IN PDSM_CONTEXT DsmContext, IN PGROUP_ENTRY Group ); #define DEBUG_BUFFER_LENGTH 255 UCHAR DebugBuffer[DEBUG_BUFFER_LENGTH + 1]; ULONG GenDSMDebug = 1; VOID DsmDebugPrint( ULONG DebugPrintLevel, PCCHAR DebugMessage, ... ); #ifdef DebugPrint #undef DebugPrint #define DebugPrint(x) DsmDebugPrint x #endif #endif // _GEN_DSM_H