static VOID XenVbd_StopRing(PXENVBD_DEVICE_DATA xvdd, BOOLEAN suspend) { PXENVBD_FILTER_DATA xvfd = (PXENVBD_FILTER_DATA)xvdd->xvfd; NTSTATUS status; WDFREQUEST request; WDF_REQUEST_SEND_OPTIONS send_options; IO_STACK_LOCATION stack; SCSI_REQUEST_BLOCK srb; SRB_IO_CONTROL sic; FUNCTION_ENTER(); /* send a 'stop' down if we are suspending */ if (suspend) { status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, xvfd->wdf_target, &request); FUNCTION_MSG("WdfRequestCreate = %08x\n", status); RtlZeroMemory(&stack, sizeof(IO_STACK_LOCATION)); stack.MajorFunction = IRP_MJ_SCSI; stack.MinorFunction = IRP_MN_SCSI_CLASS; stack.Parameters.Scsi.Srb = &srb; RtlZeroMemory(&srb, SCSI_REQUEST_BLOCK_SIZE); srb.SrbFlags = SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE; srb.Length = SCSI_REQUEST_BLOCK_SIZE; srb.PathId = 0; srb.TargetId = 0; srb.Lun = 0; srb.OriginalRequest = WdfRequestWdmGetIrp(request); srb.Function = SRB_FUNCTION_IO_CONTROL; srb.DataBuffer = &sic; RtlZeroMemory(&sic, sizeof(SRB_IO_CONTROL)); sic.HeaderLength = sizeof(SRB_IO_CONTROL); memcpy(sic.Signature, XENVBD_CONTROL_SIG, 8); sic.Timeout = 60; sic.ControlCode = XENVBD_CONTROL_STOP; WdfRequestWdmFormatUsingStackLocation(request, &stack); WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS); if (!WdfRequestSend(request, xvfd->wdf_target, &send_options)) { FUNCTION_MSG("Request was _NOT_ sent\n"); } #if DBG status = WdfRequestGetStatus(request); FUNCTION_MSG("Request Status = %08x\n", status); FUNCTION_MSG("SRB Status = %08x\n", srb.SrbStatus); #endif WdfObjectDelete(request); } status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "state", XenbusStateClosing); FUNCTION_EXIT(); }
static VOID XenVbd_SendEvent(WDFDEVICE device) { PXENVBD_FILTER_DATA xvfd = GetXvfd(device); NTSTATUS status; WDFREQUEST request; WDF_REQUEST_SEND_OPTIONS send_options; IO_STACK_LOCATION stack; PUCHAR buf; PSCSI_REQUEST_BLOCK srb; PSRB_IO_CONTROL sic; status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, xvfd->wdf_target, &request); if (status != STATUS_SUCCESS) { FUNCTION_MSG("WdfRequestCreate failed %08x\n", status); /* this is bad - event will be dropped */ return; } buf = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL) + sizeof(LARGE_INTEGER), XENVBD_POOL_TAG); RtlZeroMemory(buf, sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL)); srb = (PSCSI_REQUEST_BLOCK)(buf); sic = (PSRB_IO_CONTROL)(buf + sizeof(SCSI_REQUEST_BLOCK)); srb->Length = sizeof(SCSI_REQUEST_BLOCK); srb->SrbFlags = SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE; srb->PathId = 0; srb->TargetId = 0; srb->Lun = 0; srb->OriginalRequest = WdfRequestWdmGetIrp(request); srb->Function = SRB_FUNCTION_IO_CONTROL; srb->DataBuffer = sic; srb->DataTransferLength = sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL); srb->TimeOutValue = (ULONG)-1; sic->HeaderLength = sizeof(SRB_IO_CONTROL); memcpy(sic->Signature, XENVBD_CONTROL_SIG, 8); sic->Timeout = (ULONG)-1; sic->ControlCode = XENVBD_CONTROL_EVENT; KeQuerySystemTime((PLARGE_INTEGER)((PUCHAR)buf + sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL))); RtlZeroMemory(&stack, sizeof(IO_STACK_LOCATION)); stack.MajorFunction = IRP_MJ_SCSI; stack.MinorFunction = IRP_MN_SCSI_CLASS; stack.Parameters.Scsi.Srb = srb; WdfRequestWdmFormatUsingStackLocation(request, &stack); WdfRequestSetCompletionRoutine(request, XenVbd_SendEventComplete, buf); WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, 0); //WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE); if (!WdfRequestSend(request, xvfd->wdf_target, &send_options)) { FUNCTION_MSG("Error sending request\n"); } }
NTSTATUS BthEchoSharedDeviceContextHeaderInit( PBTHECHOSAMPLE_DEVICE_CONTEXT_HEADER Header, WDFDEVICE Device ) /*++ Description: Initializes the common context header between server and client Arguments: Header - Contex header Device - Framework device object Return Value: NTSTATUS Status code. --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES attributes; Header->Device = Device; Header->IoTarget = WdfDeviceGetIoTarget(Device); // // Initialize request object // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = Device; status = WdfRequestCreate( &attributes, Header->IoTarget, &Header->Request ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "Failed to pre-allocate request in device context, Status code %!STATUS!\n", status); goto exit; } exit: return status; }
NTSTATUS CreateRequest( _In_ WDFDEVICE Device, _In_ WDFIOTARGET IoTarget, _Outptr_ WDFREQUEST * Request ) { NTSTATUS Status = STATUS_SUCCESS; WDF_OBJECT_ATTRIBUTES Attributes; WDF_OBJECT_ATTRIBUTES_INIT(&Attributes); Attributes.ParentObject = Device; Status = WdfRequestCreate(&Attributes, IoTarget, Request); if(!NT_SUCCESS(Status)) { return Status; } return Status; }
NTSTATUS BthEchoCliRetrieveServerSdpRecord( __in PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx, __out PBTH_SDP_STREAM_RESPONSE * ServerSdpRecord ) /*++ Description: Retrive server SDP record. We call this function on every file open to get the PSM Arguments: DevCtx - Client context ServerSdpRecord - SDP record retrieved Return Value: NTSTATUS Status code. --*/ { NTSTATUS status, statusReuse, disconnectStatus; WDF_MEMORY_DESCRIPTOR inMemDesc; WDF_MEMORY_DESCRIPTOR outMemDesc; WDF_REQUEST_REUSE_PARAMS ReuseParams; BTH_SDP_CONNECT connect = {0}; BTH_SDP_DISCONNECT disconnect = {0}; BTH_SDP_SERVICE_ATTRIBUTE_SEARCH_REQUEST requestSdp = {0}; BTH_SDP_STREAM_RESPONSE responseSdp = {0}; ULONG requestSize; PBTH_SDP_STREAM_RESPONSE serverSdpRecord = NULL; WDFREQUEST request; WDF_OBJECT_ATTRIBUTES attributes; PAGED_CODE(); // // Allocate the request we will use for obtaining sdp record // NOTE that we do it for every file open, hence we // // can't use reserve request from the context // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); status = WdfRequestCreate( &attributes, DevCtx->Header.IoTarget, &request ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "Failed to allocate request for retriving server sdp record, Status code %!STATUS!\n", status); goto exit; } connect.bthAddress = DevCtx->ServerBthAddress; connect.requestTimeout = SDP_REQUEST_TO_DEFAULT; connect.fSdpConnect = 0; // // Connect to the SDP service. // WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &inMemDesc, &connect, sizeof(connect) ); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &outMemDesc, &connect, sizeof(connect) ); status = WdfIoTargetSendIoctlSynchronously( DevCtx->Header.IoTarget, request, IOCTL_BTH_SDP_CONNECT, &inMemDesc, &outMemDesc, NULL, //sendOptions NULL //bytesReturned ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "IOCTL_BTH_SDP_CONNECT failed, Status code %!STATUS!\n", status); goto exit1; } // // Obtain the required size of the SDP record // requestSdp.hConnection = connect.hConnection; requestSdp.uuids[0].u.uuid128 = BTHECHOSAMPLE_SVC_GUID; requestSdp.uuids[0].uuidType = SDP_ST_UUID128; requestSdp.range[0].minAttribute = 0; requestSdp.range[0].maxAttribute = 0xFFFF; WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED); statusReuse = WdfRequestReuse(request, &ReuseParams); ASSERT(NT_SUCCESS(statusReuse)); UNREFERENCED_PARAMETER(statusReuse); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &inMemDesc, &requestSdp, sizeof(requestSdp) ); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &outMemDesc, &responseSdp, sizeof(responseSdp) ); status = WdfIoTargetSendIoctlSynchronously( DevCtx->Header.IoTarget, request, IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH, &inMemDesc, &outMemDesc, NULL, //sendOptions NULL //bytesReturned ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH failed while querying response size, " "status code %!STATUS!\n", status); goto exit2; } // // Allocate the required size for SDP record // status = RtlULongAdd( responseSdp.requiredSize, sizeof(BTH_SDP_STREAM_RESPONSE), &requestSize ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "SDP record size too large, status code %!STATUS!\n", status); goto exit2; } serverSdpRecord = ExAllocatePoolWithTag(NonPagedPool, requestSize, POOLTAG_BTHECHOSAMPLE); if (NULL == serverSdpRecord) { status = STATUS_INSUFFICIENT_RESOURCES; TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "Allocating SDP record failed, returning status code %!STATUS!\n", status); goto exit2; } // // Send request with required size // WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED); statusReuse = WdfRequestReuse(request, &ReuseParams); ASSERT(NT_SUCCESS(statusReuse)); UNREFERENCED_PARAMETER(statusReuse); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &inMemDesc, &requestSdp, sizeof(requestSdp) ); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &outMemDesc, serverSdpRecord, requestSize ); status = WdfIoTargetSendIoctlSynchronously( DevCtx->Header.IoTarget, request, IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH, &inMemDesc, &outMemDesc, NULL, //sendOptions NULL //bytesReturned ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH failed, status code %!STATUS!\n", status); ExFreePoolWithTag(serverSdpRecord, POOLTAG_BTHECHOSAMPLE); } else { *ServerSdpRecord = serverSdpRecord; } exit2: // // Disconnect from SDP service. // WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED); statusReuse = WdfRequestReuse(request, &ReuseParams); ASSERT(NT_SUCCESS(statusReuse)); UNREFERENCED_PARAMETER(statusReuse); disconnect.hConnection = connect.hConnection; WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &inMemDesc, &disconnect, sizeof(disconnect) ); disconnectStatus = WdfIoTargetSendIoctlSynchronously( DevCtx->Header.IoTarget, request, IOCTL_BTH_SDP_DISCONNECT, &inMemDesc, NULL, //outMemDesc NULL, //sendOptions NULL //bytesReturned ); ASSERT(NT_SUCCESS(disconnectStatus)); //Disconnect should not fail if (!NT_SUCCESS(disconnectStatus)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "IOCTL_BTH_SDP_DISCONNECT failed, Status code %!STATUS!\n", status); } exit1: WdfObjectDelete(request); exit: return status; }
/* Source: WDK/src_5239/kmdf/1394/pnp.c, line 634. */ VOID t1394_EvtDeviceSelfManagedIoCleanup( /* IN WDFDEVICE Device */ PDEVICE_EXTENSION deviceExtension /* added for SLAyer */ ) { PLIST_ENTRY listEntry; // // Remove any isoch resource data // WHILE (TRUE) { WdfSpinLockAcquire(deviceExtension->IsochResourceSpinLock); if (!IsListEmpty(&deviceExtension->IsochResourceData)) { PISOCH_RESOURCE_DATA IsochResourceData = NULL; /* SLAyer: memory unsafety in original code. Reported as Windows 8 Bug #59410. Fixed by Patrick Maninger 9/Aug/2010. */ listEntry = RemoveHeadList(&deviceExtension->CromData); IsochResourceData = CONTAINING_RECORD(listEntry, ISOCH_RESOURCE_DATA, IsochResourceList); WdfSpinLockRelease(deviceExtension->IsochResourceSpinLock); /* TRACE(TL_TRACE, ("Surprise Removal: IsochResourceData = 0x%x\n", */ /* IsochResourceData)); */ if (IsochResourceData) { PIRB pIrb; WDFREQUEST request; NTSTATUS status; /* TRACE(TL_TRACE, ("Surprise Removal: Freeing hResource = 0x%x\n", */ /* IsochResourceData->hResource)); */ status = WdfRequestCreate( WDF_NO_OBJECT_ATTRIBUTES, deviceExtension->StackIoTarget, &request); if (!NT_SUCCESS(status)) { /* TRACE(TL_ERROR, ("Failed to allocate request %x\n", status)); */ free(IsochResourceData); /* SLAyer: added */ } else { pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), POOLTAG_1394); if (!pIrb) { WdfObjectDelete(request); /* TRACE(TL_ERROR, ("Failed to allocate pIrb!\n")); */ free(IsochResourceData); /* SLAyer: added */ } else { RtlZeroMemory (pIrb, sizeof (IRB)); pIrb->FunctionNumber = REQUEST_ISOCH_FREE_RESOURCES; pIrb->Flags = 0; pIrb->u.IsochFreeResources.hResource = IsochResourceData->hResource; status = t1394_SubmitIrpSynch(deviceExtension->StackIoTarget, request, pIrb); free(IsochResourceData); /* SLAyer: added */ if (!NT_SUCCESS(status)) { /* TRACE(TL_ERROR, ("SubmitIrpSync failed = 0x%x\n", status)); */ } ExFreePool(pIrb); WdfObjectDelete(request); } } } } else { WdfSpinLockRelease(deviceExtension->IsochResourceSpinLock); break; } } /* EXIT("t1394_PnpRemoveDevice", STATUS_SUCCESS); */ }
NTSTATUS Toastmon_OpenDevice( WDFDEVICE Device, PUNICODE_STRING SymbolicLink, WDFIOTARGET *Target ) /*++ Routine Description: Open the I/O target and preallocate any resources required to communicate with the target device. Arguments: Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; PTARGET_DEVICE_INFO targetDeviceInfo = NULL; WDF_IO_TARGET_OPEN_PARAMS openParams; WDFIOTARGET ioTarget; WDF_OBJECT_ATTRIBUTES attributes; PDEVICE_EXTENSION deviceExtension = GetDeviceExtension(Device); WDF_TIMER_CONFIG wdfTimerConfig; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, TARGET_DEVICE_INFO); status = WdfIoTargetCreate(deviceExtension->WdfDevice, &attributes, &ioTarget); if (!NT_SUCCESS(status)) { KdPrint(("WdfIoTargetCreate failed 0x%x\n", status)); return status; } targetDeviceInfo = GetTargetDeviceInfo(ioTarget); targetDeviceInfo->DeviceExtension = deviceExtension; // // Warning: It's not recommended to open the targetdevice // from a pnp notification callback routine, because if // the target device initiates any kind of PnP action as // a result of this open, the PnP manager could deadlock. // You should queue a workitem to do that. // For example, SWENUM devices in conjunction with KS // initiate an enumeration of a device when you do the // open on the device interface. // We can open the target device here because we know the // toaster function driver doesn't trigger any pnp action. // WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( &openParams, SymbolicLink, STANDARD_RIGHTS_ALL); openParams.ShareAccess = FILE_SHARE_WRITE | FILE_SHARE_READ; // // Framework provides default action for all of these if you don't register // these callbacks -it will close the handle to the target when the device is // being query-removed and reopen it if the query-remove fails. // In this sample, we use a periodic timers to post requests to the target. // So we need to register these callbacks so that we can start and stop // the timer when the state of the target device changes. Since we are // registering these callbacks, we are now responsbile for closing and // reopening the target. // openParams.EvtIoTargetQueryRemove = ToastMon_EvtIoTargetQueryRemove; openParams.EvtIoTargetRemoveCanceled = ToastMon_EvtIoTargetRemoveCanceled; openParams.EvtIoTargetRemoveComplete = ToastMon_EvtIoTargetRemoveComplete; status = WdfIoTargetOpen(ioTarget, &openParams); if (!NT_SUCCESS(status)) { KdPrint(("WdfIoTargetOpen failed with status 0x%x\n", status)); WdfObjectDelete(ioTarget); return status; } KdPrint(("Target Device 0x%x, PDO 0x%x, Fileobject 0x%x, Filehandle 0x%x\n", WdfIoTargetWdmGetTargetDeviceObject(ioTarget), WdfIoTargetWdmGetTargetPhysicalDevice(ioTarget), WdfIoTargetWdmGetTargetFileObject(ioTarget), WdfIoTargetWdmGetTargetFileHandle(ioTarget))); // // Create two requests - one for read and one for write. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = ioTarget; status = WdfRequestCreate(&attributes, ioTarget, &targetDeviceInfo->ReadRequest); if (!NT_SUCCESS(status)) { WdfObjectDelete(ioTarget); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = ioTarget; status = WdfRequestCreate(&attributes, ioTarget, &targetDeviceInfo->WriteRequest); if (!NT_SUCCESS(status)) { WdfObjectDelete(ioTarget); return status; } // // Create a passive timer to post requests to the I/O target. // WDF_TIMER_CONFIG_INIT(&wdfTimerConfig, Toastmon_EvtTimerPostRequests); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, TIMER_CONTEXT); // // Make IoTarget as parent of the timer to prevent the ioTarget // from deleted until the dpc has runto completion. // attributes.ParentObject = ioTarget; // // By specifying WdfExecutionLevelPassive the framework will invoke // the timer callback Toastmon_EvtTimerPostRequests at PASSIVE_LEVEL. // attributes.ExecutionLevel = WdfExecutionLevelPassive; // // Setting the AutomaticSerialization to FALSE prevents // WdfTimerCreate to fail if the parent device object's // execution level is set to WdfExecutionLevelPassive. // wdfTimerConfig.AutomaticSerialization = FALSE; status = WdfTimerCreate(&wdfTimerConfig, &attributes, &targetDeviceInfo->TimerForPostingRequests ); if(!NT_SUCCESS(status)) { KdPrint(("WdfTimerCreate failed 0x%x\n", status)); WdfObjectDelete(ioTarget); return status; } GetTimerContext(targetDeviceInfo->TimerForPostingRequests)->IoTarget = ioTarget; // // Start the passive timer. The first timer will be queued after 1ms interval and // after that it will be requeued in the timer callback function. // The value of 1 ms (lowest timer resoltion allowed on NT) is chosen here so // that timer would fire right away. // WdfTimerStart(targetDeviceInfo->TimerForPostingRequests, WDF_REL_TIMEOUT_IN_MS(1)); *Target = ioTarget; return status; }
NTSTATUS kmdf1394_UpdateGenerationCount ( IN WDFDEVICE Device) /*++ Routine Description: Routine to get and update generation count for the 1394 controller Arguments: Device - WDF Device object Return Value: NTSTATUS value --*/ { PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device); NTSTATUS ntStatus = STATUS_SUCCESS; PIRB Irb = NULL; WDFREQUEST request = NULL; ENTER("kmdf1394_UpdateGenerationCountWorkItem"); ntStatus = WdfRequestCreate ( WDF_NO_OBJECT_ATTRIBUTES, deviceExtension->StackIoTarget, &request); if (!NT_SUCCESS(ntStatus)) { TRACE(TL_ERROR, ("Failed to allocate request!\n")); return STATUS_INSUFFICIENT_RESOURCES; } Irb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV); if (!Irb) { TRACE(TL_ERROR, ("Failed to allocate Irb!\n")); WdfObjectDelete (request); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory (Irb, sizeof (IRB)); Irb->FunctionNumber = REQUEST_GET_GENERATION_COUNT; Irb->Flags = 0; ntStatus = kmdf1394_SubmitIrpSynch (deviceExtension->StackIoTarget, request, Irb); if (NT_SUCCESS(ntStatus)) { TRACE(TL_TRACE, ("GenerationCount = 0x%x\n", deviceExtension->GenerationCount)); // // Update our local copy of the GenerationCount // deviceExtension->GenerationCount = Irb->u.GetGenerationCount.GenerationCount; } else { TRACE(TL_ERROR, ("SubmitIrpSync failed = 0x%x\n", ntStatus)); } WdfObjectDelete(request); ExFreePoolWithTag(Irb,POOLTAG_KMDF_VDEV); EXIT("kmdf1394_UpdateGenerationCountWorkItem", ntStatus); return ntStatus; } // kmdf1394_UpdateGenerationCount
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 BthEchoConnectionObjectInit( _In_ WDFOBJECT ConnectionObject, _In_ PBTHECHOSAMPLE_DEVICE_CONTEXT_HEADER DevCtxHdr ) /*++ Description: This routine initializes connection object. It is invoked by BthEchoConnectionObjectCreate. Arguments: ConnectionObject - Object to initialize DevCtxHdr - Device context header Return Value: NTSTATUS Status code. --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES attributes; PBTHECHO_CONNECTION connection = GetConnectionObjectContext(ConnectionObject); connection->DevCtxHdr = DevCtxHdr; connection->ConnectionState = ConnectionStateInitialized; // // Initialize spinlock // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = ConnectionObject; status = WdfSpinLockCreate( &attributes, &connection->ConnectionLock ); if (!NT_SUCCESS(status)) { goto exit; } // // Create connect/disconnect request // status = WdfRequestCreate( &attributes, DevCtxHdr->IoTarget, &connection->ConnectDisconnectRequest ); if (!NT_SUCCESS(status)) { return status; } // // Initialize event // KeInitializeEvent(&connection->DisconnectEvent, NotificationEvent, TRUE); // // Initalize list entry // InitializeListHead(&connection->ConnectionListEntry); connection->ConnectionState = ConnectionStateInitialized; exit: return status; }
NTSTATUS BthEchoRepeatReaderInitialize( _In_ PBTHECHO_CONNECTION Connection, _In_ PBTHECHO_REPEAT_READER RepeatReader, _In_ size_t BufferSize ) /*++ Description: This routine initializes repeat reader. Arguments: Connection - Connection with which this repeat reader is associated RepeatReader - Repeat reader BufferSize - Buffer size for read Return Value: NTSTATUS Status code. --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES attributes; // // Create request object for pending read // Set connection object as the parent for the request // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = WdfObjectContextGetObject(Connection); status = WdfRequestCreate( &attributes, Connection->DevCtxHdr->IoTarget, &RepeatReader->RequestPendingRead ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER, "Creating request for pending read failed, " "Status code %!STATUS!\n", status ); goto exit; } if (BufferSize <= 0) { TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER, "BufferSize has an invalid value: %I64d\n", BufferSize ); status = STATUS_INVALID_PARAMETER; goto exit; } // // Create memory object for the pending read // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = RepeatReader->RequestPendingRead; status = WdfMemoryCreate( &attributes, NonPagedPoolNx, POOLTAG_BTHECHOSAMPLE, BufferSize, &RepeatReader->MemoryPendingRead, NULL //buffer ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER, "Creating memory for pending read failed, " "Status code %!STATUS!\n", status ); goto exit; } // // Initialize Dpc that we will use for resubmitting pending read // KeInitializeDpc( &RepeatReader->ResubmitDpc, BthEchoRepeatReaderResubmitReadDpc, Connection->DevCtxHdr ); // // Initialize event used to wait for stop. // This even is created as signalled. It gets cleared when // request is submitted. // KeInitializeEvent(&RepeatReader->StopEvent, NotificationEvent, TRUE); RepeatReader->Connection = Connection; exit: if (!NT_SUCCESS(status)) { BthEchoRepeatReaderUninitialize(RepeatReader); } return status; }
NTSTATUS I2COpen( _In_ PDEVICE_CONTEXT DeviceContext ) /*++ Routine Description: This routine opens a handle to the I2C controller. Arguments: DeviceContext - a pointer to the device context Return Value: NTSTATUS --*/ { TRACE_FUNC_ENTRY(TRACE_I2C); PAGED_CODE(); NTSTATUS status; WDF_IO_TARGET_OPEN_PARAMS openParams; WDF_OBJECT_ATTRIBUTES requestAttributes; WDF_OBJECT_ATTRIBUTES workitemAttributes; WDF_WORKITEM_CONFIG workitemConfig; // Create the device path using the connection ID. DECLARE_UNICODE_STRING_SIZE(DevicePath, RESOURCE_HUB_PATH_SIZE); RESOURCE_HUB_CREATE_PATH_FROM_ID( &DevicePath, DeviceContext->I2CConnectionId.LowPart, DeviceContext->I2CConnectionId.HighPart); TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_I2C, "Opening handle to I2C target via %wZ", &DevicePath); status = WdfIoTargetCreate(DeviceContext->Device, WDF_NO_OBJECT_ATTRIBUTES, &DeviceContext->I2CIoTarget); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C, "WdfIoTargetCreate failed - %!STATUS!", status); goto Exit; } // Open a handle to the I2C controller. WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( &openParams, &DevicePath, (GENERIC_READ | GENERIC_WRITE)); openParams.ShareAccess = 0; openParams.CreateDisposition = FILE_OPEN; openParams.FileAttributes = FILE_ATTRIBUTE_NORMAL; status = WdfIoTargetOpen(DeviceContext->I2CIoTarget, &openParams); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C, "Failed to open I2C I/O target - %!STATUS!", status); goto Exit; } // Create a WDFMEMORY object. Do call WdfMemoryAssignBuffer before use it, status = WdfMemoryCreatePreallocated( WDF_NO_OBJECT_ATTRIBUTES, static_cast<PVOID>(&status), // initial value does not matter sizeof(status), &DeviceContext->I2CMemory); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C, "WdfMemoryCreatePreallocated failed with status %!STATUS!", status); goto Exit; } WDF_OBJECT_ATTRIBUTES_INIT(&requestAttributes); requestAttributes.ParentObject = DeviceContext->I2CIoTarget; for (ULONG i = 0; i < I2CRequestSourceMax; i++) { status = WdfRequestCreate(&requestAttributes, DeviceContext->I2CIoTarget, &DeviceContext->OutgoingRequests[i]); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C, "WdfRequestCreate failed with status %!STATUS!", status); goto Exit; } } WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&workitemAttributes, WORKITEM_CONTEXT); workitemAttributes.ParentObject = DeviceContext->I2CIoTarget; WDF_WORKITEM_CONFIG_INIT(&workitemConfig, EvtWorkItemGetStatus); status = WdfWorkItemCreate(&workitemConfig, &workitemAttributes, &DeviceContext->I2CWorkItemGetStatus); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C, "WdfWorkItemCreate failed with status %!STATUS!", status); goto Exit; } WDF_WORKITEM_CONFIG_INIT(&workitemConfig, EvtWorkItemGetControl); status = WdfWorkItemCreate(&workitemConfig, &workitemAttributes, &DeviceContext->I2CWorkItemGetControl); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C, "WdfWorkItemCreate failed with status %!STATUS!", status); goto Exit; } Exit: TRACE_FUNC_EXIT(TRACE_I2C); return status; }
NTSTATUS kmdf1394_BusResetNotification ( IN WDFDEVICE Device, IN WDFREQUEST Request, IN ULONG fulFlags) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device); PIRB pIrb = NULL; WDFREQUEST newRequest = NULL; ENTER("kmdf1394_BusResetNotification"); pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV); if (!pIrb) { TRACE(TL_ERROR, ("Failed to allocate pIrb!\n")); return STATUS_INSUFFICIENT_RESOURCES; } if(!Request) { ntStatus = WdfRequestCreate ( WDF_NO_OBJECT_ATTRIBUTES, deviceExtension->StackIoTarget, &newRequest); if (!NT_SUCCESS (ntStatus)) { TRACE(TL_ERROR, ("Failed to allocate request!\n")); ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); return ntStatus; } Request = newRequest; } RtlZeroMemory (pIrb, sizeof (IRB)); pIrb->FunctionNumber = REQUEST_BUS_RESET_NOTIFICATION; pIrb->Flags = 0; pIrb->u.BusResetNotification.fulFlags = fulFlags; pIrb->u.BusResetNotification.ResetRoutine = kmdf1394_BusResetRoutine; pIrb->u.BusResetNotification.ResetContext = Device; ntStatus = kmdf1394_SubmitIrpSynch( deviceExtension->StackIoTarget, Request, pIrb); if (!NT_SUCCESS(ntStatus)) { TRACE(TL_ERROR, ("SubmitIrpSync failed = 0x%x\n", ntStatus)); } ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); if (newRequest) { WdfObjectDelete (newRequest); } EXIT("kmdf1394_BusResetNotification", ntStatus); return ntStatus; } // kmdf1394_BusResetNotification