二、Stream Class和 Minidriver之间的接口
流类接口(Stream Class Interface)主要由介于Class Driver和Minidriver之间的一系列的函数调用组成。Class Driver对请求的流程(Request Flow)进行控制,当有必要对适配器硬件进行存取时,它就调用适配器的Minidriver。Class Driver还负责对多处理器和中断同步作出响应。当Class Driver和Minidriver都初始化完毕之后,Minidriver将处于一个被动的地位,它只能被Class Driver所调用,而绝大多数的调用都是非常低级的服务请求。
对Minidriver来说,对命令和信息(Commands and Information)进行控制的最基本的机制就是流请求块(Streaming Request Block)。每个Minidriver都有一系列的SRB来对其某个特定的功能进行访问,而且一般说来,设备所支持的每种数据流都有相应的SRB与之对应。这些信息(SRB)通过操作系统控制的DMA缓冲区(它是一个环形队列)传递给设备。
一个SRB由一个命令码字段,以及与该命令码相关联的其他数据所组成。结构体HW_STREAM_REQUEST_BLOCK包含了和特定的SRB相关的所有信息。我们常常把这个结构体就简称为SRB,它体内还包含了一些作为对命令码的补充信息的其他参数。结构体HW_STREAM_REQUEST_BLOCK的定义如下:
typedef struct _HW_STREAM_REQUEST_BLOCK
{
ULONG SizeOfThisPacket;
SRB_COMMAND Command;
NTSTATUS Status;
PHW_STREAM_OBJECT StreamObject;
PVOID HwDeviceExtension;
PVOID SRBExtension;
union _CommandData
{
PKSSTREAM_HEADER DataBufferArray;
PHW_STREAM_DESCRIPTOR StreamBuffer;
KSSTATE StreamState;
PSTREAM_PROPERTY_DESCRIPTOR PropertyInfo;
PKSDATAFORMAT OpenFormat;
struct _PORT_CONFIGURATION_INFORMATION * ConfigInfo;
HANDLE MasterClockHandle;
DEVICE_POWER_STATE DeviceState;
PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
} CommandData;
ULONG NumberOfBuffers;
ULONG TimeoutCounter;
ULONG TimeoutOriginal;
struct _HW_STREAM_REQUEST_BLOCK* NextSRB;
PIRP Irp;
ULONG Flags;
PVOID HwInstanceExtension;
union
{
ULONG NumberOfBytesToTransfer;
ULONG ActualBytesTransferred;
};
PKSSCATTER_GATHER ScatterGatherBuffer
ULONG NumberOfPhysicalPages;
ULONG Reserved[2];
} HW_STREAM_REQUEST_BLOCK, *PHW_STREAM_REQUEST_BLOCK;
关于对以上其他参数的解释,参见DDK文档,这里不再赘述。
下图解释了流类(Stream Class)和Minidriver在初始化时所进行的交互动作。
·初始化适配器
所有的流式Minidriver函数并不一定非要和Minidriver的中断服务例程(Interrupt Service Routine,ISR)同步,因而Minidriver的代码是不可重入的(Non-re-entrant,相应的概念叫做可重入代码,又叫做纯代码。关于可重入代码的概念,请参考西电版操作系统教材),亦即,当Minidriver正在执行一个线程的时候,不能再调用Minidriver内其他任何函数,包括中断服务例程在内。这种非可重入的特性即便在支持多处理器的Windows NT/2000系统下也是存在的,这样可以令Minidriver编写起来更加方便。为了达到这样的特性,流类驱动(Stream Class Driver)会在Minidriver体内任何例程被执行时,通过内核例程KeSynchronizeExecution屏蔽Streaming Minidriver的中断请求IRQ(和所有低优先级的IRQ)。如果想了解更多关于同步的信息,请参看MiniDriver同步一章。Streaming Minidriver可以在必要的时候调用WDM系统服务。但是,Minidriver自己并没有设备对象,他是利用ClassDriver的设备对象来完成系统调用的。绝大多数Minidriver是不需要进行WDM系统调用的,因为几乎所有必要的功能都已经被Class Driver所涵盖了,没有必要直接进行系统调用。
必须知道的是,当进行WDM系统服务调用时,所有的Minidriver的入口点都会在高于DISPATCH_LEVEL的中断优先级下被调用(注意不包括DISPATCH_LEVEL中断优先级)。但有一个例外,那就是StreamClassCallAtNewPriority例程,此函数允许在DISPATCH_LEVEL
或PASSIVE_LEVEL中断优先级上进行系统服务调用,具体哪个优先级取决于调用时所指定的优先级别。如果要一劳永逸地修改这个对IRQL的调用限制,可以通过把HW_INITIALIZATION_DATA结构体中的BOOL型成员变量TurnOffSynchronization简单置为TRUE来实现之。