VOID kmdf1394_EvtDeviceSelfManagedIoCleanup ( IN WDFDEVICE Device) /*++ Routine Description: EvtDeviceSelfManagedIoCleanup is called by the Framework when the device is being torn down, either in response to IRP_MN_REMOVE_DEVICE or IRP_MN_SURPRISE_REMOVE_DEVICE. It will be called only once. Its job is to stop all outstanding I/O in the driver that the Framework is not managing. Arguments: Device - Handle to a framework device object. Return Value: None --*/ { PDEVICE_EXTENSION deviceExtension = NULL; PLIST_ENTRY listEntry = NULL; Enter(); deviceExtension = GetDeviceContext(Device); DoTraceLevelMessage(TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "Removing KMDF1394VDEV.SYS.\n"); // // lets free up any crom data structs we've allocated... // WdfSpinLockAcquire (deviceExtension->CromSpinLock); while (!IsListEmpty (&deviceExtension->CromData)) { PCROM_DATA CromData; // // get struct off list // listEntry = RemoveHeadList (&deviceExtension->CromData); CromData = CONTAINING_RECORD (listEntry, CROM_DATA, CromList); // // need to free up everything associated with this allocate... // if (CromData) { if (CromData->Buffer) { ExFreePoolWithTag (CromData->Buffer, POOLTAG_KMDF_VDEV); } if (CromData->pMdl) { IoFreeMdl (CromData->pMdl); } // // we already checked CromData // ExFreePoolWithTag (CromData, POOLTAG_KMDF_VDEV); } } WdfSpinLockRelease (deviceExtension->CromSpinLock); // // lets free up any allocated addresses and deallocate all // memory associated with them... // WdfSpinLockAcquire (deviceExtension->AsyncSpinLock); while (!IsListEmpty (&deviceExtension->AsyncAddressData)) { PASYNC_ADDRESS_DATA AsyncAddressData; // // get struct off list // listEntry = RemoveHeadList (&deviceExtension->AsyncAddressData); AsyncAddressData = CONTAINING_RECORD ( listEntry, ASYNC_ADDRESS_DATA, AsyncAddressList); // // need to free up everything associated with this allocate... // if (AsyncAddressData->pMdl) { IoFreeMdl (AsyncAddressData->pMdl); } if (AsyncAddressData->Buffer) { ExFreePoolWithTag(AsyncAddressData->Buffer, POOLTAG_KMDF_VDEV); } if (AsyncAddressData->AddressRange) { ExFreePoolWithTag(AsyncAddressData->AddressRange, POOLTAG_KMDF_VDEV); } ExFreePoolWithTag(AsyncAddressData, POOLTAG_KMDF_VDEV); } WdfSpinLockRelease(deviceExtension->AsyncSpinLock); // // TODO: Free up any attached isoch buffers when // we get the attach / detach code inserted again. // // // Remove any isoch resource data // WHILE (TRUE) { WdfSpinLockAcquire(deviceExtension->IsochResourceSpinLock); if (!IsListEmpty(&deviceExtension->IsochResourceData)) { PISOCH_RESOURCE_DATA IsochResourceData = NULL; listEntry = RemoveHeadList(&deviceExtension->CromData); IsochResourceData = CONTAINING_RECORD ( listEntry, ISOCH_RESOURCE_DATA, IsochResourceList); WdfSpinLockRelease(deviceExtension->IsochResourceSpinLock); DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "Surprise Removal: IsochResourceData = 0x%p\n", IsochResourceData); if (IsochResourceData) { PIRB pIrb; WDFREQUEST request; NTSTATUS ntStatus; DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "Surprise Removal: Freeing hResource = 0x%p\n", IsochResourceData->hResource); ntStatus = WdfRequestCreate ( WDF_NO_OBJECT_ATTRIBUTES, deviceExtension->StackIoTarget, &request); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Failed to allocate request %!STATUS!\n", ntStatus); } else { pIrb = ExAllocatePoolWithTag( NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV); if (!pIrb) { WdfObjectDelete(request); DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Failed to allocate pIrb!\n"); } else { RtlZeroMemory (pIrb, sizeof (IRB)); pIrb->FunctionNumber = REQUEST_ISOCH_FREE_RESOURCES; pIrb->Flags = 0; pIrb->u.IsochFreeResources.hResource = \ IsochResourceData->hResource; ntStatus = kmdf1394_SubmitIrpSynch ( deviceExtension->StackIoTarget, request, pIrb); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "SubmitIrpSync failed = %!STATUS!\n", ntStatus); } ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); WdfObjectDelete (request); } // else } // else } // if (IsochResourceData) } // if (!IsListEmpty(&deviceExtension->IsochResourceData)) else { WdfSpinLockRelease (deviceExtension->IsochResourceSpinLock); break; } } ExitS(STATUS_SUCCESS); } // kmdf1394_EvtDeviceSelfManagedIoCleanup
NTSTATUS kmdf1394_AsyncWrite ( IN WDFDEVICE Device, IN WDFREQUEST Request, IN PASYNC_WRITE AsyncWrite) /*++ Routine Description: Async Write routine. Arguments: Device - the current WDFDEVICE Object. Request - the current request. AsyncWrite - the Data buffer from usermode to be worked on. Return Value: VOID --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device); PIRB pIrb = NULL; PMDL pMdl = NULL; WDFIOTARGET ioTarget = NULL; WDFMEMORY Memory; Enter(); ioTarget = deviceExtension->StackIoTarget; pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV); if (!pIrb) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed to allocate pIrb!\n"); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory (pIrb, sizeof (IRB)); pIrb->FunctionNumber = REQUEST_ASYNC_WRITE; pIrb->Flags = 0; pIrb->u.AsyncWrite.DestinationAddress = AsyncWrite->DestinationAddress; pIrb->u.AsyncWrite.nNumberOfBytesToWrite = AsyncWrite->nNumberOfBytesToWrite; pIrb->u.AsyncWrite.nBlockSize = AsyncWrite->nBlockSize; pIrb->u.AsyncWrite.fulFlags = AsyncWrite->fulFlags; if (AsyncWrite->bGetGeneration) { DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_ASYNC, "Retrieved Generation Count = 0x%X\n", pIrb->u.AsyncRead.ulGeneration); pIrb->u.AsyncRead.ulGeneration = deviceExtension->GenerationCount; } else { pIrb->u.AsyncRead.ulGeneration = AsyncWrite->ulGeneration; } pMdl = IoAllocateMdl ( AsyncWrite->Data, AsyncWrite->nNumberOfBytesToWrite, FALSE, FALSE, NULL); if(NULL == pMdl) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed to allocate mdl!\n"); ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); return STATUS_INSUFFICIENT_RESOURCES; } MmBuildMdlForNonPagedPool (pMdl); pIrb->u.AsyncWrite.Mdl = pMdl; // // We need to create a WDF Memory object for the IRB to nestle in // for an async request. // ntStatus = WdfMemoryCreatePreallocated ( WDF_NO_OBJECT_ATTRIBUTES, pIrb, sizeof (IRB), &Memory); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed WdfMemoryCreate %d\n", ntStatus); IoFreeMdl (pIrb->u.AsyncWrite.Mdl); ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); return ntStatus; } WdfRequestSetCompletionRoutine ( Request, kmdf1394_AsyncWriteCompletion, Memory); ntStatus = kmdf1394_SubmitIrpAsync (ioTarget, Request, Memory); if (!NT_SUCCESS(ntStatus)) { if (ntStatus != STATUS_INVALID_GENERATION) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "SubmitIrpSync failed = %!STATUS!\n", ntStatus); } else { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Invalid Generation count\n"); } IoFreeMdl (pIrb->u.AsyncWrite.Mdl); ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); WdfObjectDelete (Memory); } ExitS(ntStatus); return ntStatus; } // kmdf1394_AsyncWrite
NTSTATUS kmdf1394_EvtDeviceAdd ( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES fdoAttributes,lockAttributes; WDFDEVICE device; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_IO_QUEUE_CONFIG ioQueueConfig; UNREFERENCED_PARAMETER (Driver); PAGED_CODE(); Enter(); // // Zero out the PnpPowerCallbacks structure. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // Set Callbacks for any of the functions we are interested in. // If no callback is set, Framework will take the default action // by itself. // // These two callbacks set up and tear down hardware state, // specifically that which only has to be done once. // pnpPowerCallbacks.EvtDevicePrepareHardware = kmdf1394_EvtPrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = kmdf1394_EvtReleaseHardware; pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup = \ kmdf1394_EvtDeviceSelfManagedIoCleanup; pnpPowerCallbacks.EvtDeviceD0Entry = kmdf1394_EvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = kmdf1394_EvtDeviceD0Exit; // // Register the PnP and power callbacks. Power policy related callbacks // will be registered// later in SotwareInit. // WdfDeviceInitSetPnpPowerEventCallbacks (DeviceInit, &pnpPowerCallbacks); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceInitSetPnpPowerEventCallbacks failed %!STATUS!\n", ntStatus); return ntStatus; } // // We'll allow multiple handles to be opened to this device driver // so we'll set exclusivity to FALSE. // WdfDeviceInitSetExclusive (DeviceInit, FALSE); // // Specify the size and type of device context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE (&fdoAttributes, DEVICE_EXTENSION); ntStatus = WdfDeviceCreate (&DeviceInit, &fdoAttributes, &device); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceInitialize failed %!STATUS!\n", ntStatus); return ntStatus; } deviceExtension = GetDeviceContext (device); deviceExtension->WdfDevice = device; DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "PDO(0x%p) FDO(0x%p), Lower(0x%p) DevExt (0x%p)\n", WdfDeviceWdmGetPhysicalDevice (device), WdfDeviceWdmGetDeviceObject (device), WdfDeviceWdmGetAttachedDevice(device), deviceExtension); // // Tell the Framework that this device will need an interface so that // application can interact with it. // ntStatus = WdfDeviceCreateDeviceInterface ( device, (LPGUID) &GUID_KMDF_VDEV, NULL); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceCreateDeviceInterface failed %!STATUS!\n", ntStatus); return ntStatus; } // // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so // that you don't get the popup in usermode (on Win2K) when you surprise // remove the device. // WDF_DEVICE_PNP_CAPABILITIES_INIT (&pnpCaps); pnpCaps.SurpriseRemovalOK = WdfTrue; WdfDeviceSetPnpCapabilities (device, &pnpCaps); // // save the device object we created as our physical device object // deviceExtension->PhysicalDeviceObject = \ WdfDeviceWdmGetPhysicalDevice (device); if (NULL == deviceExtension->PhysicalDeviceObject) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceWdmGetPhysicalDevice: NULL DeviceObject\n"); return STATUS_UNSUCCESSFUL; } // // This is our default IoTarget representing the deviceobject // we are attached to. // deviceExtension->StackIoTarget = WdfDeviceGetIoTarget(device); deviceExtension->StackDeviceObject = WdfDeviceWdmGetAttachedDevice(device); if (NULL == deviceExtension->StackDeviceObject) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceWdmGetAttachedDevice: NULL DeviceObject\n"); return STATUS_UNSUCCESSFUL; } // // Create a automanaged queue for dispatching ioctl requests. // All other requests are automatically failed by the framework. // By creating an automanaged queue we don't have to worry about // PNP/Power synchronization. // A default queue gets all the requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE ( &ioQueueConfig, WdfIoQueueDispatchParallel); ioQueueConfig.EvtIoDeviceControl = kmdf1394_EvtIoDeviceControl; __analysis_assume(ioQueueConfig.EvtIoStop != 0); ntStatus = WdfIoQueueCreate ( deviceExtension->WdfDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceExtension->IoctlQueue); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfIoQueueCreate failed %!STATUS!\n", ntStatus); return ntStatus; } // // Create an additional queue to hold bus reset requests. // WDF_IO_QUEUE_CONFIG_INIT (&ioQueueConfig, WdfIoQueueDispatchManual); __analysis_assume(ioQueueConfig.EvtIoStop != 0); ntStatus = WdfIoQueueCreate ( deviceExtension->WdfDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceExtension->BusResetRequestsQueue); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Error Creating Reset Request Queue %!STATUS!\n", ntStatus); return ntStatus; } WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes); lockAttributes.ParentObject = device; ntStatus = WdfSpinLockCreate (&lockAttributes,&deviceExtension->CromSpinLock); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfSpinLockCreate CromSpinLock failed %!STATUS!\n", ntStatus); return ntStatus; } WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes); lockAttributes.ParentObject = device; ntStatus = WdfSpinLockCreate ( &lockAttributes, &deviceExtension->AsyncSpinLock); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfSpinLockCreate AsyncSpinLock failed %!STATUS!\n", ntStatus); return ntStatus; } WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes); lockAttributes.ParentObject = device; ntStatus = WdfSpinLockCreate ( &lockAttributes, &deviceExtension->IsochSpinLock ); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfSpinLockCreate IsochSpinLock failed %!STATUS!\n", ntStatus); return ntStatus; } WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes); lockAttributes.ParentObject = device; ntStatus = WdfSpinLockCreate ( &lockAttributes, &deviceExtension->IsochResourceSpinLock); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfSpinLockCreate IsochResourceSpinLock failed %!STATUS!\n", ntStatus); return ntStatus; } InitializeListHead (&deviceExtension->CromData); InitializeListHead (&deviceExtension->AsyncAddressData); InitializeListHead (&deviceExtension->IsochDetachData); InitializeListHead (&deviceExtension->IsochResourceData); ExitS(ntStatus); return(ntStatus); } // kmdf1394_PnpAddDevice
NTSTATUS kmdf1394_SetAddressData ( IN WDFDEVICE Device, IN WDFREQUEST Request, IN PSET_ADDRESS_DATA SetAddrData) /*++ Routine Description: Set Address Range routine. Arguments: Device - the current WDFDEVICE Object. Request - the current request. SetAddrData - the Data buffer from usermode to be worked on. Return Value: VOID --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device); PASYNC_ADDRESS_DATA AsyncAddressData = NULL; PLIST_ENTRY listHead, thisEntry; UNREFERENCED_PARAMETER(Request); Enter(); // // have to find our struct... // WdfSpinLockAcquire(deviceExtension->AsyncSpinLock); listHead = &deviceExtension->AsyncAddressData; for(thisEntry = listHead->Flink; thisEntry != listHead; AsyncAddressData = NULL, thisEntry = thisEntry->Flink) { AsyncAddressData = CONTAINING_RECORD( thisEntry, ASYNC_ADDRESS_DATA, AsyncAddressList); if (AsyncAddressData->hAddressRange == SetAddrData->hAddressRange) { PULONG pBuffer; // // found it, let's copy over the contents from data... // pBuffer = \ (PULONG)((ULONG_PTR)AsyncAddressData->Buffer + \ SetAddrData->ulOffset); DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_ASYNC, "pBuffer = 0x%p\n", pBuffer); DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_ASYNC, "Data = 0x%p\n", SetAddrData->Data); #pragma warning(suppress:28649) // PREFast warning is incorrectly issued here if(pBuffer && SetAddrData->Data) { RtlCopyMemory(pBuffer, SetAddrData->Data, SetAddrData->nLength); } break; } } WdfSpinLockRelease(deviceExtension->AsyncSpinLock); // // never found an entry... // if (!AsyncAddressData) { ntStatus = STATUS_INVALID_PARAMETER; } ExitS(ntStatus); return ntStatus; } // kmdf1394_SetAddressData
NTSTATUS kmdf1394_FreeAddressRange ( IN WDFDEVICE Device, IN WDFREQUEST Request, IN HANDLE hAddressRange) /*++ Routine Description: Allocate Address Range routine. Arguments: Device - the current WDFDEVICE Object. Request - the current request. hAddressRange - The Address Range to be freed. Return Value: VOID --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device); PIRB pIrb = NULL; PASYNC_ADDRESS_DATA AsyncAddressData = NULL; PLIST_ENTRY listHead, thisEntry; UNREFERENCED_PARAMETER(Request); Enter(); // // have to find our struct... // WdfSpinLockAcquire (deviceExtension->AsyncSpinLock); listHead = &deviceExtension->AsyncAddressData; for (thisEntry = listHead->Flink; thisEntry != listHead; AsyncAddressData = NULL, thisEntry = thisEntry->Flink) { AsyncAddressData = CONTAINING_RECORD ( thisEntry, ASYNC_ADDRESS_DATA, AsyncAddressList); if (AsyncAddressData->hAddressRange == hAddressRange) { RemoveEntryList(&AsyncAddressData->AsyncAddressList); break; } } WdfSpinLockRelease(deviceExtension->AsyncSpinLock); // // never found an entry... // if (!AsyncAddressData) { return STATUS_INVALID_PARAMETER; } // // got it, lets free it... // pIrb = ExAllocatePoolWithTag (NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV); if (!pIrb) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed to allocate pIrb!\n"); // // Catasrophic failure, insert the AddressData element back on // the list before existing // WdfSpinLockAcquire (deviceExtension->AsyncSpinLock); InsertHeadList ( &deviceExtension->AsyncAddressData, &AsyncAddressData->AsyncAddressList); WdfSpinLockRelease (deviceExtension->AsyncSpinLock); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory (pIrb, sizeof (IRB)); pIrb->FunctionNumber = REQUEST_FREE_ADDRESS_RANGE; pIrb->Flags = 0; pIrb->u.FreeAddressRange.nAddressesToFree = \ AsyncAddressData->nAddressesReturned; pIrb->u.FreeAddressRange.p1394AddressRange = AsyncAddressData->AddressRange; pIrb->u.FreeAddressRange.pAddressRange = &AsyncAddressData->hAddressRange; pIrb->u.FreeAddressRange.DeviceExtension = (PVOID)deviceExtension; // // We're going to send this one synchronously // ntStatus = kmdf1394_SubmitIrpSynch ( deviceExtension->StackIoTarget, Request, pIrb); if (!NT_SUCCESS (ntStatus)) { // // The free request failed, insert the element back on to our tracking // list and either try to free later, or release the resources on // driver tear down. // WdfSpinLockAcquire (deviceExtension->AsyncSpinLock); InsertHeadList ( &deviceExtension->AsyncAddressData, &AsyncAddressData->AsyncAddressList); WdfSpinLockRelease (deviceExtension->AsyncSpinLock); } else { // // need to free up everything associated with this from the allocate... // IoFreeMdl (AsyncAddressData->pMdl); ExFreePoolWithTag (AsyncAddressData->Buffer, POOLTAG_KMDF_VDEV); ExFreePoolWithTag (AsyncAddressData->AddressRange, POOLTAG_KMDF_VDEV); ExFreePoolWithTag (AsyncAddressData, POOLTAG_KMDF_VDEV); } ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); ExitS(ntStatus); return ntStatus; } // kmdf1394_FreeAddressRange
NTSTATUS kmdf1394_AllocateAddressRange ( IN WDFDEVICE Device, IN WDFREQUEST Request, IN OUT PALLOCATE_ADDRESS_RANGE AllocateAddrRange) /*++ Routine Description: Allocate Address Range routine. Arguments: Device - the current WDFDEVICE Object. Request - the current request. AllocateAddressRange - the Data buffer from usermode to be worked on. Return Value: VOID --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device); PIRB pIrb = NULL; PASYNC_ADDRESS_DATA pAsyncAddressData = NULL; ULONG nPages; WDFMEMORY Memory; CONTEXT_BUNDLE ContextBundle; Enter(); pIrb = ExAllocatePoolWithTag (NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV); if (!pIrb) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed to allocate pIrb!\n"); return STATUS_INSUFFICIENT_RESOURCES; } ContextBundle.Context0 = AllocateAddrRange; pAsyncAddressData = ExAllocatePoolWithTag ( NonPagedPool, sizeof(ASYNC_ADDRESS_DATA), POOLTAG_KMDF_VDEV); if (!pAsyncAddressData) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed to allocate pAsyncAddressData!\n"); ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); return STATUS_INSUFFICIENT_RESOURCES; } ContextBundle.Context1 = pAsyncAddressData; pAsyncAddressData->Buffer = ExAllocatePoolWithTag ( NonPagedPool, AllocateAddrRange->nLength, POOLTAG_KMDF_VDEV); if (!pAsyncAddressData->Buffer) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed to allocate Buffer!\n"); ExFreePoolWithTag (pAsyncAddressData, POOLTAG_KMDF_VDEV); ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); return STATUS_INSUFFICIENT_RESOURCES; } if ((0 == AllocateAddrRange->MaxSegmentSize) || (PAGE_SIZE == AllocateAddrRange->MaxSegmentSize)) { nPages = \ ADDRESS_AND_SIZE_TO_SPAN_PAGES ( AllocateAddrRange->Data, AllocateAddrRange->nLength); } else { nPages = \ (AllocateAddrRange->nLength % AllocateAddrRange->MaxSegmentSize) ? \ AllocateAddrRange->nLength / AllocateAddrRange->MaxSegmentSize + 1 : \ AllocateAddrRange->nLength / AllocateAddrRange->MaxSegmentSize; } pAsyncAddressData->AddressRange = ExAllocatePoolWithTag ( NonPagedPool, sizeof(ADDRESS_RANGE)*nPages, POOLTAG_KMDF_VDEV); if (!pAsyncAddressData->AddressRange) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed to allocate AddressRange!\n"); ExFreePoolWithTag(pAsyncAddressData->Buffer, POOLTAG_KMDF_VDEV); ExFreePoolWithTag(pAsyncAddressData, POOLTAG_KMDF_VDEV); ExFreePoolWithTag(pIrb, POOLTAG_KMDF_VDEV); return STATUS_INSUFFICIENT_RESOURCES; } pAsyncAddressData->pMdl = IoAllocateMdl ( pAsyncAddressData->Buffer, AllocateAddrRange->nLength, FALSE, FALSE, NULL); if (!pAsyncAddressData->pMdl) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed to create pMdl!\n"); ExFreePoolWithTag (pAsyncAddressData->AddressRange, POOLTAG_KMDF_VDEV); ExFreePoolWithTag (pAsyncAddressData->Buffer, POOLTAG_KMDF_VDEV); ExFreePoolWithTag (pAsyncAddressData, POOLTAG_KMDF_VDEV); ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); return STATUS_INSUFFICIENT_RESOURCES; } MmBuildMdlForNonPagedPool (pAsyncAddressData->pMdl); DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_ASYNC, "pMdl = 0x%p\n", pAsyncAddressData->pMdl); // // copy over the contents of data to our driver buffer // RtlCopyMemory ( pAsyncAddressData->Buffer, AllocateAddrRange->Data, AllocateAddrRange->nLength); pAsyncAddressData->nLength = AllocateAddrRange->nLength; RtlZeroMemory (pIrb, sizeof (IRB)); pIrb->FunctionNumber = REQUEST_ALLOCATE_ADDRESS_RANGE; pIrb->Flags = 0; pIrb->u.AllocateAddressRange.Mdl = pAsyncAddressData->pMdl; pIrb->u.AllocateAddressRange.fulFlags = AllocateAddrRange->fulFlags; pIrb->u.AllocateAddressRange.nLength = AllocateAddrRange->nLength; pIrb->u.AllocateAddressRange.MaxSegmentSize = \ AllocateAddrRange->MaxSegmentSize; pIrb->u.AllocateAddressRange.fulAccessType = \ AllocateAddrRange->fulAccessType; pIrb->u.AllocateAddressRange.fulNotificationOptions = \ AllocateAddrRange->fulNotificationOptions; pIrb->u.AllocateAddressRange.Callback = NULL; pIrb->u.AllocateAddressRange.Context = NULL; pIrb->u.AllocateAddressRange.Required1394Offset = \ AllocateAddrRange->Required1394Offset; pIrb->u.AllocateAddressRange.FifoSListHead = NULL; pIrb->u.AllocateAddressRange.FifoSpinLock = NULL; pIrb->u.AllocateAddressRange.AddressesReturned = 0; pIrb->u.AllocateAddressRange.p1394AddressRange = \ pAsyncAddressData->AddressRange; pIrb->u.AllocateAddressRange.DeviceExtension = deviceExtension; // // We need to create a WDF Memory object for the IRB to nestle in // for an async request. // ntStatus = WdfMemoryCreatePreallocated ( WDF_NO_OBJECT_ATTRIBUTES, pIrb, sizeof (IRB), &Memory); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed WdfMemoryCreate %d\n", ntStatus); IoFreeMdl (pAsyncAddressData->pMdl); ExFreePoolWithTag (pAsyncAddressData->AddressRange, POOLTAG_KMDF_VDEV); ExFreePoolWithTag (pAsyncAddressData->Buffer, POOLTAG_KMDF_VDEV); ExFreePoolWithTag (pAsyncAddressData, POOLTAG_KMDF_VDEV); ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); return ntStatus; } ContextBundle.Context2 = Memory; ContextBundle.Context3 = deviceExtension; WdfRequestSetCompletionRoutine ( Request, kmdf1394_AllocateAddressRangeCompletion, &ContextBundle); ntStatus = kmdf1394_SubmitIrpAsync ( deviceExtension->StackIoTarget, Request, Memory); ExitS(ntStatus); return ntStatus; } //kmdf1394_AllocateAddressRange
NTSTATUS kmdf1394_AsyncStream ( IN WDFDEVICE Device, IN WDFREQUEST Request, IN OUT PASYNC_STREAM AsyncStream) /*++ Routine Description: Async Stream routine. Arguments: Device - the current WDFDEVICE Object. Request - the current request. AsyncStream - the Data buffer from usermode to be worked on. Return Value: VOID --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension = GetDeviceContext (Device); PIRB pIrb = NULL; WDFIOTARGET ioTarget = deviceExtension->StackIoTarget; WDFMEMORY Memory; PMDL pMdl = NULL; Enter(); pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV); if (!pIrb) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed to allocate pIrb!\n"); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory (pIrb, sizeof (IRB)); pIrb->FunctionNumber = REQUEST_ASYNC_STREAM; pIrb->Flags = 0; pIrb->u.AsyncStream.nNumberOfBytesToStream = \ AsyncStream->nNumberOfBytesToStream; pIrb->u.AsyncStream.fulFlags = AsyncStream->fulFlags; pIrb->u.AsyncStream.ulTag = AsyncStream->ulTag; pIrb->u.AsyncStream.nChannel = AsyncStream->nChannel; pIrb->u.AsyncStream.ulSynch = AsyncStream->ulSynch; pIrb->u.AsyncStream.nSpeed = (UCHAR) AsyncStream->nSpeed; pMdl = IoAllocateMdl ( AsyncStream->Data, AsyncStream->nNumberOfBytesToStream, FALSE, FALSE, NULL); if (!pMdl) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed to allocate pMdl!\n"); ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); return STATUS_INSUFFICIENT_RESOURCES; } MmBuildMdlForNonPagedPool(pMdl); pIrb->u.AsyncStream.Mdl = pMdl; // // We need to create a WDF Memory object for the IRB to nestle in // for an async request. // ntStatus = WdfMemoryCreatePreallocated ( WDF_NO_OBJECT_ATTRIBUTES, pIrb, sizeof (IRB), &Memory); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed WdfMemoryCreate %d\n", ntStatus); IoFreeMdl (pIrb->u.AsyncStream.Mdl); ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); return ntStatus; } WdfRequestSetCompletionRoutine ( Request, kmdf1394_AsyncStreamCompletion, Memory); ntStatus = kmdf1394_SubmitIrpAsync (ioTarget, Request, Memory); if (!NT_SUCCESS(ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "SubmitIrpAsync failed = %!STATUS!\n", ntStatus); IoFreeMdl (pIrb->u.AsyncStream.Mdl); ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); WdfObjectDelete (Memory); } ExitS(ntStatus); return ntStatus; } // kmdf1394_AsyncStream
NTSTATUS kmdf1394_AsyncLock ( IN WDFDEVICE Device, IN WDFREQUEST Request, IN OUT PASYNC_LOCK AsyncLock) /*++ Routine Description: Async Lock routine. Arguments: Device - the current WDFDEVICE Object. Request - the current request. AsyncLock - the Data buffer from usermode to be worked on. Return Value: VOID --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PIRB pIrb = NULL; WDFMEMORY Memory; PDEVICE_EXTENSION deviceExtension = GetDeviceContext (Device); WDFIOTARGET ioTarget = NULL; Enter(); ioTarget = deviceExtension->StackIoTarget; pIrb = ExAllocatePoolWithTag (NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV); if (!pIrb) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed to allocate pIrb!\n"); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory (pIrb, sizeof (IRB)); pIrb->FunctionNumber = REQUEST_ASYNC_LOCK; pIrb->Flags = 0; pIrb->u.AsyncLock.DestinationAddress = AsyncLock->DestinationAddress; pIrb->u.AsyncLock.nNumberOfArgBytes = AsyncLock->nNumberOfArgBytes; pIrb->u.AsyncLock.nNumberOfDataBytes = AsyncLock->nNumberOfDataBytes; pIrb->u.AsyncLock.fulTransactionType = AsyncLock->fulTransactionType; pIrb->u.AsyncLock.fulFlags = AsyncLock->fulFlags; pIrb->u.AsyncLock.Arguments[0] = AsyncLock->Arguments[0]; pIrb->u.AsyncLock.Arguments[1] = AsyncLock->Arguments[1]; pIrb->u.AsyncLock.DataValues[0] = AsyncLock->DataValues[0]; pIrb->u.AsyncLock.DataValues[1] = AsyncLock->DataValues[1]; pIrb->u.AsyncLock.pBuffer = AsyncLock->Buffer; if (AsyncLock->bGetGeneration) { pIrb->u.AsyncLock.ulGeneration = deviceExtension->GenerationCount; DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_ASYNC, "Retrieved Generation Count = 0x%X\n", pIrb->u.AsyncLock.ulGeneration); } else { pIrb->u.AsyncLock.ulGeneration = AsyncLock->ulGeneration; } // // We need to create a WDF Memory object for the IRB to nestle in // for an async request. // ntStatus = WdfMemoryCreatePreallocated ( WDF_NO_OBJECT_ATTRIBUTES, pIrb, sizeof (IRB), &Memory); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Failed WdfMemoryCreate %d\n", ntStatus); ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); return ntStatus; } WdfRequestSetCompletionRoutine ( Request, kmdf1394_AsyncLockCompletion, Memory); ntStatus = kmdf1394_SubmitIrpAsync (ioTarget, Request, Memory); if (!NT_SUCCESS(ntStatus)) { if (STATUS_INVALID_GENERATION == ntStatus) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "Invalid Geneation count\n"); } else { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_ASYNC, "SubmitIrpSync failed = %!STATUS!\n", ntStatus); } ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); WdfObjectDelete (Memory); } ExitS(ntStatus); return ntStatus; } // kmdf1394_AsyncLock