windows-nt/Source/XPSP1/NT/base/busdrv/mf/mfp.h
2020-09-26 16:20:57 +08:00

659 lines
14 KiB
C

/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
local.h
Abstract:
This header declares the stuctures and function prototypes shared between
the various modules.
Author:
Andy Thornton (andrewth) 20-Oct-97
Revision History:
--*/
#if !defined(_LOCAL_)
#define _LOCAL_
#include <ntddk.h>
#include <arbiter.h>
#include <wdmguid.h>
//#include <initguid.h>
#include <mf.h>
#include "msg.h"
#include "debug.h"
//
// --- Constants ---
//
#define MF_CM_RESOURCE_VERSION 1
#define MF_CM_RESOURCE_REVISION 1
#define MF_ARBITER_INTERFACE_VERSION 1
#define MF_TRANSLATOR_INTERFACE_VERSION 1
//
// These must be updated if any new PNP or PO irps are added
//
#define IRP_MN_PNP_MAXIMUM_FUNCTION IRP_MN_QUERY_LEGACY_BUS_INFORMATION
#define IRP_MN_PO_MAXIMUM_FUNCTION IRP_MN_QUERY_POWER
//
// Pool Tags
//
#define MF_POOL_TAG ' fM'
#define MF_RESOURCE_MAP_TAG 'MRfM'
#define MF_VARYING_MAP_TAG 'MVfM'
#define MF_CHILD_LIST_TAG 'LCfM'
#define MF_DEVICE_ID_TAG 'IDfM'
#define MF_INSTANCE_ID_TAG 'IIfM'
#define MF_CHILD_REQUIREMENTS_TAG 'QCfM'
#define MF_CHILD_RESOURCE_TAG 'RCfM'
#define MF_HARDWARE_COMPATIBLE_ID_TAG 'IHfM'
#define MF_PARENTS_RESOURCE_TAG 'RPfM'
#define MF_PARENTS_REQUIREMENTS_TAG 'QPfM'
#define MF_BUS_RELATIONS_TAG 'RBfM'
#define MF_TARGET_RELATIONS_TAG 'RTfM'
#define MF_REQUIREMENTS_INDEX_TAG 'IRfM'
#define MF_ARBITER_TAG 'rAfM'
//
// Device state flags
//
#define MF_DEVICE_STARTED 0x00000001
#define MF_DEVICE_REMOVED 0x00000002
#define MF_DEVICE_ENUMERATED 0x00000004
#define MF_DEVICE_REMOVE_PENDING 0x00000008 /* DEPRECATED */
#define MF_DEVICE_STOP_PENDING 0x00000010 /* DEPRECATED */
#define MF_DEVICE_CAPABILITIES_CAPTURED 0x00000020 /* DEPRECATED */
#define MF_DEVICE_REQUIREMENTS_CAPTURED 0x00000040 /* DEPRECATED */
#define MF_DEVICE_DELETED 0x00000080
#define MF_DEVICE_SURPRISE_REMOVED 0x00000100
//
// Flags to MfGetRegistryValue
//
#define MF_GETREG_SZ_TO_MULTI_SZ 0x00000001
//
// --- Type definitions ---
//
typedef enum _MF_OBJECT_TYPE {
MfPhysicalDeviceObject = 'dPfM',
MfFunctionalDeviceObject = 'dFfM'
} MF_OBJECT_TYPE;
typedef
NTSTATUS
(*PMF_DISPATCH)(
IN PIRP Irp,
IN PVOID Extension,
IN PIO_STACK_LOCATION IrpStack
);
typedef ULONG Mf_MSG_ID;
//
// Structures for storing the resource distributions
//
typedef struct _MF_ARBITER {
//
// List of arbiters
//
LIST_ENTRY ListEntry;
//
// The resource this arbiter arbitrates
//
CM_RESOURCE_TYPE Type;
//
// The arbiter instance
//
ARBITER_INSTANCE Instance;
} MF_ARBITER, *PMF_ARBITER;
typedef struct _MF_COMMON_EXTENSION {
//
// Type of device this is
//
MF_OBJECT_TYPE Type;
//
// Dispatch tables for Pnp and Power Irps.
//
PMF_DISPATCH *PnpDispatchTable;
PMF_DISPATCH *PoDispatchTable;
//
// Flags to indicate the device's current state (use MF_DEVICE_*)
//
ULONG DeviceState;
ULONG PagingCount;
ULONG HibernationCount;
ULONG DumpCount;
//
// The power state of the device
//
DEVICE_POWER_STATE PowerState;
} MF_COMMON_EXTENSION, *PMF_COMMON_EXTENSION;
typedef struct _MF_CHILD_EXTENSION *PMF_CHILD_EXTENSION;
typedef struct _MF_PARENT_EXTENSION *PMF_PARENT_EXTENSION;
typedef struct _MF_CHILD_EXTENSION {
//
// The common extension
//
MF_COMMON_EXTENSION Common;
//
// Various Flags
//
ULONG Flags;
//
// Backpointer to the device object we are are the extension of
//
PDEVICE_OBJECT Self;
//
// The FDO who enumerated us
//
PMF_PARENT_EXTENSION Parent;
//
// Other children enumerated by the same FDO
//
LIST_ENTRY ListEntry;
//
// The pnp device state of the device
//
PNP_DEVICE_STATE PnpDeviceState;
//
// The information about this device
//
MF_DEVICE_INFO Info;
} MF_CHILD_EXTENSION, *PMF_CHILD_EXTENSION;
typedef struct _MF_PARENT_EXTENSION {
//
// The common extension
//
MF_COMMON_EXTENSION Common;
//
// Backpointer to the device object of whom we are the extension
//
PDEVICE_OBJECT Self;
//
// The PDO for the multi-function device
//
PDEVICE_OBJECT PhysicalDeviceObject;
//
// Lock for the children database
//
KEVENT ChildrenLock;
//
// List of children enumerated by this device
//
LIST_ENTRY Children;
//
// The next device in the stack who we should send our IRPs down to
//
PDEVICE_OBJECT AttachedDevice;
//
// The resources with which the parent was stated
//
PCM_RESOURCE_LIST ResourceList;
PCM_RESOURCE_LIST TranslatedResourceList;
//
// The device and instance ID's of our parent
//
UNICODE_STRING DeviceID;
UNICODE_STRING InstanceID;
//
// The already instantiated arbiters for this device
//
LIST_ENTRY Arbiters;
//
// If we had to traverse the children in order to determine what
// the lowest power state the parent can go to, then the
// synchronization of the children list would become extremely
// complicated.
//
// Instead, have a spinlock protected data structure consisting of
// an array of device power states. Each element of the array is
// a count of how many children are in that power state.
//
KSPIN_LOCK PowerLock;
LONG ChildrenPowerReferences[PowerDeviceMaximum];
//
// Remove lock. Used to prevent the FDO from being removed while
// other operations are digging around in the extension.
//
IO_REMOVE_LOCK RemoveLock;
} MF_PARENT_EXTENSION, *PMF_PARENT_EXTENSION;
//
// A list of MF_CHILD_LIST_ENTRYs is returned by MfEnumerate
//
typedef struct _MF_CHILD_LIST_ENTRY {
LIST_ENTRY ListEntry;
MF_DEVICE_INFO Info;
} MF_CHILD_LIST_ENTRY, *PMF_CHILD_LIST_ENTRY;
//
// Registry structure - from our friends in Win9x so it must be byte aligned
//
#include <pshpack1.h>
typedef struct _MF_REGISTRY_VARYING_RESOURCE_MAP {
UCHAR ResourceIndex; // Win9x BYTE
ULONG Offset;
ULONG Size;
} MF_REGISTRY_VARYING_RESOURCE_MAP, *PMF_REGISTRY_VARYING_RESOURCE_MAP;
#include <poppack.h>
typedef
NTSTATUS
(*PMF_REQUIREMENT_FROM_RESOURCE)(
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource,
OUT PIO_RESOURCE_DESCRIPTOR Requirement
);
typedef
NTSTATUS
(*PMF_UPDATE_RESOURCE)(
IN OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource,
IN ULONGLONG Start,
IN ULONG Length
);
typedef struct _MF_RESOURCE_TYPE {
CM_RESOURCE_TYPE Type;
PARBITER_UNPACK_REQUIREMENT UnpackRequirement;
PARBITER_PACK_RESOURCE PackResource;
PARBITER_UNPACK_RESOURCE UnpackResource;
PMF_REQUIREMENT_FROM_RESOURCE RequirementFromResource;
PMF_UPDATE_RESOURCE UpdateResource;
} MF_RESOURCE_TYPE, *PMF_RESOURCE_TYPE;
typedef struct _MF_POWER_COMPLETION_CONTEXT {
//
// Event that will be set when the operation is complete
//
KEVENT Event;
//
// The status of the completed operation
//
NTSTATUS Status;
} MF_POWER_COMPLETION_CONTEXT, *PMF_POWER_COMPLETION_CONTEXT;
//
// --- Globals ---
//
extern PDRIVER_OBJECT MfDriverObject;
//
// --- Function prototypes ---
//
//
// arbiter.c
//
NTSTATUS
MfInitializeArbiters(
IN PMF_PARENT_EXTENSION Parent
);
//
// common.c
//
NTSTATUS
MfDeviceUsageNotificationCommon(
IN PIRP Irp,
IN PMF_COMMON_EXTENSION Common,
IN PIO_STACK_LOCATION IrpStack
);
//
// dispatch.c
//
NTSTATUS
MfAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
);
NTSTATUS
MfDispatchPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
MfDispatchPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
MfIrpNotSupported(
IN PIRP Irp,
IN PVOID Extension,
IN PIO_STACK_LOCATION IrpStack
);
NTSTATUS
MfForwardIrpToParent(
IN PIRP Irp,
IN PMF_CHILD_EXTENSION Extension,
IN PIO_STACK_LOCATION IrpStack
);
NTSTATUS
MfDispatchNop(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
//
// enum.c
//
NTSTATUS
MfEnumerate(
IN PMF_PARENT_EXTENSION Parent
);
NTSTATUS
MfBuildDeviceID(
IN PMF_PARENT_EXTENSION Parent,
OUT PWSTR *DeviceID
);
NTSTATUS
MfBuildInstanceID(
IN PMF_CHILD_EXTENSION Child,
OUT PWSTR *InstanceID
);
NTSTATUS
MfBuildChildRequirements(
IN PMF_CHILD_EXTENSION Child,
OUT PIO_RESOURCE_REQUIREMENTS_LIST *RequirementsList
);
//
// fdo.c
//
NTSTATUS
MfDispatchPnpFdo(
IN PDEVICE_OBJECT DeviceObject,
IN PMF_PARENT_EXTENSION Parent,
IN PIO_STACK_LOCATION IrpStack,
IN OUT PIRP Irp
);
NTSTATUS
MfDispatchPowerFdo(
IN PDEVICE_OBJECT DeviceObject,
IN PMF_PARENT_EXTENSION Parent,
IN PIO_STACK_LOCATION IrpStack,
IN OUT PIRP Irp
);
NTSTATUS
MfCreateFdo(
PDEVICE_OBJECT *Fdo
);
VOID
MfAcquireChildrenLock(
IN PMF_PARENT_EXTENSION Parent
);
VOID
MfReleaseChildrenLock(
IN PMF_PARENT_EXTENSION Parent
);
//
// init.c
//
//
// pdo.c
//
NTSTATUS
MfDispatchPnpPdo(
IN PDEVICE_OBJECT DeviceObject,
IN PMF_CHILD_EXTENSION Parent,
IN PIO_STACK_LOCATION IrpStack,
IN OUT PIRP Irp
);
NTSTATUS
MfDispatchPowerPdo(
IN PDEVICE_OBJECT DeviceObject,
IN PMF_CHILD_EXTENSION Parent,
IN PIO_STACK_LOCATION IrpStack,
IN OUT PIRP Irp
);
NTSTATUS
MfCreatePdo(
IN PMF_PARENT_EXTENSION Parent,
OUT PDEVICE_OBJECT *PhysicalDeviceObject
);
VOID
MfDeletePdo(
IN PMF_CHILD_EXTENSION Child
);
//
// resource.c
//
PMF_RESOURCE_TYPE
MfFindResourceType(
IN CM_RESOURCE_TYPE Type
);
//
// utils.c
//
NTSTATUS
MfGetSubkeyByIndex(
IN HANDLE ParentHandle,
IN ULONG Index,
IN ACCESS_MASK Access,
OUT PHANDLE ChildHandle,
OUT PUNICODE_STRING Name
);
VOID
MfInitCommonExtension(
IN OUT PMF_COMMON_EXTENSION Common,
IN MF_OBJECT_TYPE Type
);
VOID
MfFreeDeviceInfo(
PMF_DEVICE_INFO Info
);
NTSTATUS
MfGetRegistryValue(
IN HANDLE Handle,
IN PWSTR Name,
IN ULONG Type,
IN ULONG Flags,
IN OUT PULONG DataLength,
IN OUT PVOID *Data OPTIONAL
);
NTSTATUS
MfSendPnpIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIO_STACK_LOCATION Location,
OUT PULONG_PTR Information OPTIONAL
);
NTSTATUS
MfSendSetPowerIrp(
IN PDEVICE_OBJECT Target,
IN POWER_STATE State
);
DEVICE_POWER_STATE
MfUpdateChildrenPowerReferences(
IN PMF_PARENT_EXTENSION Parent,
IN DEVICE_POWER_STATE PreviousPowerState,
IN DEVICE_POWER_STATE NewPowerState
);
NTSTATUS
MfUpdateParentPowerState(
IN PMF_PARENT_EXTENSION Parent,
IN DEVICE_POWER_STATE TargetPowerState
);
//
// --- Macros ---
//
#define IS_FDO(Extension) \
(((PMF_COMMON_EXTENSION)Extension)->Type == MfFunctionalDeviceObject)
#define MfCompareGuid(a,b) \
(RtlEqualMemory((PVOID)(a), (PVOID)(b), sizeof(GUID)))
//
// Control macro (used like a for loop) which iterates over all entries in
// a standard doubly linked list. Head is the list head and the entries are of
// type Type. A member called ListEntry is assumed to be the LIST_ENTRY
// structure linking the entries together. Current contains a pointer to each
// entry in turn.
//
#define FOR_ALL_IN_LIST(Type, Head, Current) \
for((Current) = CONTAINING_RECORD((Head)->Flink, Type, ListEntry); \
(Head) != &(Current)->ListEntry; \
(Current) = CONTAINING_RECORD((Current)->ListEntry.Flink, \
Type, \
ListEntry) \
)
#define FOR_ALL_IN_LIST_SAFE(Type, Head, Current, Next) \
for((Current) = CONTAINING_RECORD((Head)->Flink, Type, ListEntry), \
(Next) = CONTAINING_RECORD((Current)->ListEntry.Flink, \
Type, ListEntry); \
(Head) != &(Current)->ListEntry; \
(Current) = (Next), \
(Next) = CONTAINING_RECORD((Current)->ListEntry.Flink, \
Type, ListEntry) \
)
//
// Similar to the above only iteration is over an array of length _Size.
//
#define FOR_ALL_IN_ARRAY(_Array, _Size, _Current) \
for ( (_Current) = (_Array); \
(_Current) < (_Array) + (_Size); \
(_Current)++ )
//
// FOR_ALL_CM_DESCRIPTORS(
// IN PCM_RESOURCE_LIST _ResList,
// OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR _Descriptor
// )
//
// Iterates over the resource descriptors in a CM_RESOURCE_LIST of Count 1
//
#define FOR_ALL_CM_DESCRIPTORS(_ResList, _Descriptor) \
ASSERT((_ResList)->Count == 1); \
FOR_ALL_IN_ARRAY( \
(_ResList)->List[0].PartialResourceList.PartialDescriptors, \
(_ResList)->List[0].PartialResourceList.Count, \
(_Descriptor) \
)
//
// BOOLEAN
// IS_ARBITRATED_RESOURCE(
// IN CM_RESOURCE_TYPE _Resource
// )
//
// If the top bit of the resource type (when viewed as a UCHAR) is set
// then the resource is nonarbitrated.
//
#define IS_ARBITRATED_RESOURCE(_Resource) \
(!(((UCHAR)(_Resource)) & 0x80) && \
!(((UCHAR)(_Resource)) == 0x00))
#define END_OF_RANGE(_Start, _Length) \
((_Start)+(_Length)-1)
#endif // !defined(_LOCAL_)