Second, the interface between stream class and minidriver
STREAM CLASS interface is mainly composed of a series of function calls between Class Driver and MiniDriver. Class Driver Controls the request flow, when it is necessary to access the adapter hardware, it calls the adapter's MiniDriver. Class Driver is also responsible for responding to multiprocessors and interrupt synchronization. After Class Driver and Minidriver are initialized, MiniDriver will be in a passive position, which can only be called by Class Driver, and most calls are very low-level service requests.
For MINIDRIVER, the most basic mechanism for controlling commands and information is a streaming request block. Each Minidriver has a range of SRBs to access certain features, and generally, each data stream supported by the device has corresponding SRBs and corresponding. This information (SRB) is passed to the device via the operating system-controlled DMA buffer (it is a ring queue).
A SRB consists of a command code field and other data associated with the command code. The structural hw_stream_request_block contains all information related to a particular SRB. We often use this structure as SRB, and it also contains some other parameters as supplementary information on the command code. The definition of the structural hw_stream_request_block is as follows:
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 ScatterGatherBufferULONG NumberOfPhysicalPages; ULONG Reserved [2];
} Hw_stream_request_block, * phw_stream_request_block; See DDK documentation on the interpretation of other parameters, see DDK documents, here is not described here.
The following figure explains the interactive action of stream class and minidriver during initialization.
· Initialization adapter
All streaming minidriver functions do not necessarily not synchronize with the Interrupt Service Routine, ISR of Minidriver, so that MiniDriver's code is unrebeiled (Non-Re-entRant, the corresponding concept is re-entry) Code, called pure code. For the concept of re-enter code, please refer to the West Electric version operating system textbook), that is, when the MiniDriver is executing a thread, any other functions in Minidriver cannot be called again, including interrupt service examples. The approach. This non-reusable feature is also present in the Windows NT / 2000 system that supports multi-processors, so that MINIDRIVER is more convenient. To achieve such features, stream class driver is executed when any routine in the Minidriver body is executed, and the interrupt request IRQ (and all low priority IRQs) is made through the kernel routine Kesynchronizeexecution. If you want to know more about synchronization, please see the MINIDRIVER synchronization chapter. Streaming minidriver can call WDM system services when necessary. However, MiniDriver has no equipment object, he is using ClassDriver's device object to complete the system call. Most MiniDriver is not required for WDM system calls, because almost all necessary features have been covered by Class Driver, and there is no need to perform system calls directly.
It must be known that when the WDM system service is called, all MiniDriver's entry points are called at interrupt priorities above Dispatch_level (note that the Dispatch_level interrupt priority) is not included. But there is an exception, that is, the StreamClassCallatnewPriority routine, this function is allowed in Dispatch_level
Or the Passive_LEVEL interrupt priority is made on system service calls, which priority depends on the priority specified when the call is called. If you want to modify this call limit for IRQL once once, you can implement it by simply seting the BOOL-type member variable of the HW_Initialization_Data structure to TRUE.