1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxPkgIo.hpp 8 9 Abstract: 10 11 This module implements the I/O package for the driver frameworks. 12 13 Author: 14 15 16 17 Environment: 18 19 Both kernel and user mode 20 21 Revision History: 22 23 --*/ 24 25 #ifndef _FXPKGIO_H_ 26 #define _FXPKGIO_H_ 27 28 29 30 31 #include "fxpkgioshared.hpp" 32 #include "fxirpdynamicdispatchinfo.hpp" 33 #include "fxdevicecallbacks.hpp" 34 #include "fxcxdeviceinfo.hpp" 35 36 // 37 // This flag is or-ed with a pointer value that is ptr aligned, only lower 2 bits are available. 38 // 39 #define FX_IN_DISPATCH_CALLBACK 0x00000001 40 41 enum FxIoIteratorList { 42 FxIoQueueIteratorListInvalid = 0, 43 FxIoQueueIteratorListPowerOn, 44 FxIoQueueIteratorListPowerOff, 45 }; 46 47 #define IO_ITERATOR_FLUSH_TAG (PVOID) 'sulf' 48 #define IO_ITERATOR_POWER_TAG (PVOID) 'ewop' 49 50 // 51 // This class is allocated by the driver frameworks manager 52 // PER DEVICE, and is not package global, but per device global, 53 // data. 54 // 55 // This is similar to the NT DeviceExtension. 56 // 57 class FxPkgIo : public FxPackage 58 { 59 60 private: 61 62 FxIoQueue* m_DefaultQueue; 63 64 // 65 // This is the list of IoQueue objects allocated by the driver 66 // and associated with this device. The IoPackage instance 67 // will release these references automatically when the device 68 // is removed. 69 // 70 LIST_ENTRY m_IoQueueListHead; 71 72 // 73 // This is the forwarding table 74 // 75 FxIoQueue* m_DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]; 76 77 // 78 // This is the seed value used to pass to the 79 // FxRandom for testing forward progress 80 // 81 ULONG m_RandomSeed; 82 83 // TRUE if behave as a filter (forward default requests) 84 BOOLEAN m_Filter; 85 86 BOOLEAN m_PowerStateOn; 87 88 // 89 // TRUE if queues are shutting down (surprise_remove/remove in progress). 90 // 91 BOOLEAN m_QueuesAreShuttingDown; 92 93 // 94 // We'll maintain the dynamic dispatch table "per device" so that it is possible 95 // to have different callbacks for each device. 96 // Note that each device may be associted with multiple class extension in the future. 97 // 98 LIST_ENTRY m_DynamicDispatchInfoListHead; 99 100 // 101 // If !=NULL, a pre-process callback was registered 102 // 103 FxIoInCallerContext m_InCallerContextCallback; 104 105 public: 106 107 FxPkgIo( 108 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 109 __in CfxDevice *Device 110 ); 111 112 ~FxPkgIo(); 113 114 // 115 // Package manager dispatch entries 116 // 117 _Must_inspect_result_ 118 virtual 119 NTSTATUS 120 Dispatch( 121 __inout MdIrp Irp 122 ); 123 124 // 125 // Returns the Top level queue for the Io based on the Irp MajorFunction 126 // 127 FxIoQueue* GetDispatchQueue(_In_ UCHAR MajorFunction)128 GetDispatchQueue( 129 _In_ UCHAR MajorFunction 130 ) 131 { 132 return m_DispatchTable[MajorFunction]; 133 } 134 135 // Do not specify argument names 136 FX_DECLARE_VF_FUNCTION_P1( 137 NTSTATUS, 138 VerifyDispatchContext, 139 _In_ WDFCONTEXT 140 ); 141 142 // 143 // Api's supplied by this package 144 // 145 _Must_inspect_result_ 146 NTSTATUS 147 __fastcall 148 DispatchStep1( 149 __inout MdIrp Irp, 150 __in WDFCONTEXT DispatchContext 151 ); 152 153 _Must_inspect_result_ 154 NTSTATUS 155 __fastcall 156 DispatchStep2( 157 __inout MdIrp Irp, 158 __in_opt FxIoInCallerContext* IoInCallerCtx, 159 __in_opt FxIoQueue* Queue 160 ); 161 162 /*++ 163 164 Routine Description: 165 166 Initializes the default queue, and allows the driver to 167 pass configuration information. 168 169 The driver callbacks registered in this call are used 170 to supply the callbacks for the driver default I/O queue. 171 172 Arguments: 173 174 hDevice - Pointer Device Object 175 176 Return Value: 177 178 NTSTATUS 179 180 --*/ 181 _Must_inspect_result_ 182 NTSTATUS 183 InitializeDefaultQueue( 184 __in CfxDevice * Device, 185 __inout FxIoQueue * Queue 186 ); 187 188 // 189 // Register the I/O in-caller context callback 190 // 191 __inline 192 VOID SetIoInCallerContextCallback(__inout PFN_WDF_IO_IN_CALLER_CONTEXT EvtIoInCallerContext)193 SetIoInCallerContextCallback( 194 __inout PFN_WDF_IO_IN_CALLER_CONTEXT EvtIoInCallerContext 195 ) 196 { 197 m_InCallerContextCallback.m_Method = EvtIoInCallerContext; 198 } 199 200 // Do not specify argument names 201 FX_DECLARE_VF_FUNCTION_P2( 202 NTSTATUS, 203 VerifyEnqueueRequestUpdateFlags, 204 _In_ FxRequest*, 205 _Inout_ SHORT* 206 ); 207 208 // Do not specify argument names 209 FX_DECLARE_VF_FUNCTION_P2( 210 VOID, 211 VerifyEnqueueRequestRestoreFlags, 212 _In_ FxRequest*, 213 _In_ SHORT 214 ); 215 216 // 217 // Enqueue a request to the I/O processing pipeline 218 // from the device driver 219 // 220 _Must_inspect_result_ 221 NTSTATUS 222 EnqueueRequest( 223 __in CfxDevice* Device, 224 __inout FxRequest* pRequest 225 ); 226 227 FxDriver* 228 GetDriver( 229 VOID 230 ); 231 232 __inline 233 CfxDevice* GetDevice(VOID)234 GetDevice( 235 VOID 236 ) 237 { 238 return m_Device; 239 } 240 241 __inline 242 FxIoQueue* GetDefaultQueue(VOID)243 GetDefaultQueue( 244 VOID 245 ) 246 { 247 return m_DefaultQueue; 248 } 249 250 __inline 251 BOOLEAN IsFilter(VOID)252 IsFilter( 253 VOID 254 ) 255 { 256 return m_Filter; 257 } 258 259 // 260 // This is called as a result of a power management state 261 // that requests that all I/O in progress stop. 262 // 263 // 264 // FxIoStopProcessingForPowerHold: 265 // the function returns when the driver has acknowledged that it has 266 // stopped all I/O processing, but may have outstanding "in-flight" requests 267 // that have not been completed. 268 // 269 // FxIoStopProcessingForPowerPurge: 270 // the function returns when all requests have been completed and/or 271 // cancelled., and there are no more in-flight requests. 272 // 273 // Any queues not marked as PowerManaged will be left alone. 274 // 275 // This is called on a PASSIVE_LEVEL thread that can block until 276 // I/O has been stopped, or completed/cancelled. 277 // 278 _Must_inspect_result_ 279 NTSTATUS 280 StopProcessingForPower( 281 __in FxIoStopProcessingForPowerAction Action 282 ); 283 284 // 285 // This is called to start, or resume processing when PNP/Power 286 // resources have been supplied to the device driver. 287 // 288 // The driver is notified of resumption for any in-flight I/O. 289 // 290 _Must_inspect_result_ 291 NTSTATUS 292 ResumeProcessingForPower(); 293 294 // 295 // This is called on a device which has been restarted from the removed 296 // state. It will reset purged queues so that they can accept new requests 297 // when ResumeProcessingForPower is called afterwards. 298 // 299 VOID 300 ResetStateForRestart( 301 VOID 302 ); 303 304 // 305 // Called by CfxDevice when WdfDeviceSetFilter is called. 306 // 307 _Must_inspect_result_ 308 NTSTATUS 309 SetFilter( 310 __in BOOLEAN Value 311 ); 312 313 // 314 // Create an IoQueue and associate it with the FxIoPkg per device 315 // instance. 316 // 317 _Must_inspect_result_ 318 NTSTATUS 319 CreateQueue( 320 __in PWDF_IO_QUEUE_CONFIG Config, 321 __in PWDF_OBJECT_ATTRIBUTES QueueAttributes, 322 __in_opt FxDriver* Caller, 323 __deref_out FxIoQueue** ppQueue 324 ); 325 326 VOID 327 RemoveQueueReferences( 328 __inout FxIoQueue* pQueue 329 ); 330 331 _Must_inspect_result_ 332 NTSTATUS 333 ConfigureDynamicDispatching( 334 __in UCHAR MajorFunction, 335 __in_opt FxCxDeviceInfo* CxDeviceInfo, 336 __in PFN_WDFDEVICE_WDM_IRP_DISPATCH EvtDeviceWdmIrpDispatch, 337 __in_opt WDFCONTEXT DriverContext 338 ); 339 340 _Must_inspect_result_ 341 NTSTATUS 342 ConfigureForwarding( 343 __inout FxIoQueue* TargetQueue, 344 __in WDF_REQUEST_TYPE RequestType 345 ); 346 347 _Must_inspect_result_ 348 NTSTATUS 349 FlushAllQueuesByFileObject( 350 __in MdFileObject FileObject 351 ); 352 353 __inline 354 VOID RequestCompletedCallback(__in FxRequest * Request)355 RequestCompletedCallback( 356 __in FxRequest* Request 357 ) 358 { 359 UNREFERENCED_PARAMETER(Request); 360 361 // 362 // If this is called, the driver called WDFREQUEST.Complete 363 // from the PreProcess callback handler. 364 // 365 // Since we have a handler, the FXREQUEST object will 366 // dereference itself upon return from this callback, which 367 // will destroy the final reference count. 368 // 369 } 370 371 __inline 372 BOOLEAN IsTopLevelQueue(__in FxIoQueue * Queue)373 IsTopLevelQueue( 374 __in FxIoQueue* Queue 375 ) 376 { 377 UCHAR index; 378 379 for (index = 0; index <= IRP_MJ_MAXIMUM_FUNCTION; index++) { 380 if (m_DispatchTable[index] == Queue) { 381 return TRUE; 382 } 383 } 384 return FALSE; 385 } 386 387 NTSTATUS 388 DispathToInCallerContextCallback( 389 __in FxIoInCallerContext *InCallerContextInfo, 390 __in FxRequest *Request, 391 __inout MdIrp Irp 392 ); 393 394 __inline 395 FxIoInCallerContext* GetIoInCallerContextCallback(__in_opt FxCxDeviceInfo * CxDeviceInfo)396 GetIoInCallerContextCallback( 397 __in_opt FxCxDeviceInfo* CxDeviceInfo 398 ) 399 { 400 if (CxDeviceInfo != NULL) { 401 return &CxDeviceInfo->IoInCallerContextCallback; 402 } 403 else { 404 return &m_InCallerContextCallback; 405 } 406 } 407 408 private: 409 410 VOID 411 AddIoQueue( 412 __inout FxIoQueue* IoQueue 413 ); 414 415 VOID 416 RemoveIoQueue( 417 __inout FxIoQueue* IoQueue 418 ); 419 420 FxIoQueue* 421 GetFirstIoQueueLocked( 422 __in FxIoQueueNode* QueueBookmark, 423 __in PVOID Tag 424 ); 425 426 FxIoQueue* 427 GetNextIoQueueLocked( 428 __in FxIoQueueNode* QueueBookmark, 429 __in PVOID Tag 430 ); 431 432 VOID 433 GetIoQueueListLocked( 434 __in PSINGLE_LIST_ENTRY SListHead, 435 __inout FxIoIteratorList ListType 436 ); 437 438 _Must_inspect_result_ 439 NTSTATUS 440 VerifierFreeRequestToTestForwardProgess( 441 __in FxRequest* Request 442 ); 443 444 }; 445 446 #endif // _FXPKGIO_H 447