VOID VIOSerialCtrlWorkHandler( IN WDFDEVICE Device ) { struct virtqueue *vq; PPORT_BUFFER buf; UINT len; NTSTATUS status = STATUS_SUCCESS; PPORTS_DEVICE pContext = GetPortsDevice(Device); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP, "--> %s\n", __FUNCTION__); vq = pContext->c_ivq; ASSERT(vq); WdfSpinLockAcquire(pContext->CInVqLock); while ((buf = virtqueue_get_buf(vq, &len))) { WdfSpinLockRelease(pContext->CInVqLock); buf->len = len; buf->offset = 0; VIOSerialHandleCtrlMsg(Device, buf); WdfSpinLockAcquire(pContext->CInVqLock); status = VIOSerialAddInBuf(vq, buf); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "%s::%d Error adding buffer to queue\n", __FUNCTION__, __LINE__); VIOSerialFreeBuffer(buf); } } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP, "<-- %s\n", __FUNCTION__); WdfSpinLockRelease(pContext->CInVqLock); }
VOID VIOSerialPortClose( IN WDFFILEOBJECT FileObject ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData( WdfFileObjectGetDevice(FileObject)); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "--> %s\n", __FUNCTION__); if (!pdoData->port->Removed && pdoData->port->GuestConnected) { VIOSerialSendCtrlMsg(pdoData->port->BusDevice, pdoData->port->PortId, VIRTIO_CONSOLE_PORT_OPEN, 0); } pdoData->port->GuestConnected = FALSE; WdfSpinLockAcquire(pdoData->port->InBufLock); VIOSerialDiscardPortDataLocked(pdoData->port); WdfSpinLockRelease(pdoData->port->InBufLock); WdfSpinLockAcquire(pdoData->port->OutVqLock); VIOSerialReclaimConsumedBuffers(pdoData->port); WdfSpinLockRelease(pdoData->port->OutVqLock); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "<-- %s\n", __FUNCTION__); }
NTSTATUS VIOSerialFillQueue( IN struct virtqueue *vq, IN WDFSPINLOCK Lock ) { NTSTATUS status = STATUS_SUCCESS; PPORT_BUFFER buf = NULL; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "--> %s\n", __FUNCTION__); for (;;) { buf = VIOSerialAllocateBuffer(PAGE_SIZE); if(buf == NULL) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "VIOSerialAllocateBuffer failed\n"); return STATUS_INSUFFICIENT_RESOURCES; } WdfSpinLockAcquire(Lock); status = VIOSerialAddInBuf(vq, buf); if(!NT_SUCCESS(status)) { VIOSerialFreeBuffer(buf); WdfSpinLockRelease(Lock); break; } WdfSpinLockRelease(Lock); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "<-- %s\n", __FUNCTION__); return STATUS_SUCCESS; }
/* Source: WDK/src_5239/kmdf/1394/isochapi.c, line 1178. */ void t1394_IsochTimeout( PDEVICE_EXTENSION DeviceExtension, /* added for SLAyer */ /* IN PKDPC Dpc, */ /* IN */ PISOCH_DETACH_DATA IsochDetachData/* , */ /* IN PVOID SystemArgument1, */ /* IN PVOID SystemArgument2 */ ) { /* PDEVICE_EXTENSION DeviceExtension; */ /* UNREFERENCED_PARAMETER(Dpc); */ /* UNREFERENCED_PARAMETER(SystemArgument1); */ /* UNREFERENCED_PARAMETER(SystemArgument2); */ /* ENTER("t1394_IsochTimeout"); */ /* TRACE(TL_WARNING, ("Isoch Timeout!\n")); */ // // ISSUE: the device extension we are referencing comes from the IsochDetachData // but it is possible this memory has been freed before we enter this function. // The only way to check is to validate against our DeviceExtension->IsochDetachList // but if the IsochDetachData has been freed then that won't be accessible // /* DeviceExtension = IsochDetachData->DeviceExtension; */ if (DeviceExtension) { // make sure nobody else has already handled this request yet WdfSpinLockAcquire(DeviceExtension->IsochSpinLock); if (t1394_IsOnList(&IsochDetachData->IsochDetachList, &DeviceExtension->IsochDetachData)) { RemoveEntryList(&IsochDetachData->IsochDetachList); WdfSpinLockRelease(DeviceExtension->IsochSpinLock); /* if(KeCancelTimer(&IsochDetachData->Timer)) */ { /* TRACE(TL_TRACE, ("IsochTimeout: IsochDetachData = 0x%x\n", IsochDetachData)); */ /* TRACE(TL_TRACE, ("IsochTimeout: IsochDetachData->Irp = 0x%x\n", IsochDetachData->Request)); */ /* TRACE(TL_TRACE, ("IsochTimeout: IsochDetachData->newIrp = 0x%x\n", IsochDetachData->newIrp)); */ // need to save the status of the attach // we'll clean up in the same spot for success's and timeout's /* IsochDetachData->AttachStatus = STATUS_TIMEOUT; */ t1394_IsochCleanup(IsochDetachData); } } else { WdfSpinLockRelease(DeviceExtension->IsochSpinLock); } } /* EXIT("t1394_IsochTimeout", 0); */ } // t1394_IsochTimeout
NTSTATUS VIOSerialPortEvtDeviceD0Exit( IN WDFDEVICE Device, IN WDF_POWER_DEVICE_STATE TargetState ) { PVIOSERIAL_PORT Port = RawPdoSerialPortGetData(Device)->port; PPORT_BUFFER buf; PSINGLE_LIST_ENTRY iter; UNREFERENCED_PARAMETER(TargetState); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "--> %s\n", __FUNCTION__); WdfIoQueuePurge(Port->ReadQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT); WdfIoQueuePurge(Port->WriteQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT); WdfIoQueuePurge(Port->IoctlQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT); VIOSerialDisableInterruptQueue(GetInQueue(Port)); WdfSpinLockAcquire(Port->InBufLock); VIOSerialDiscardPortDataLocked(Port); Port->InBuf = NULL; WdfSpinLockRelease(Port->InBufLock); WdfSpinLockAcquire(Port->OutVqLock); VIOSerialReclaimConsumedBuffers(Port); WdfSpinLockRelease(Port->OutVqLock); while (buf = (PPORT_BUFFER)VirtIODeviceDetachUnusedBuf(GetInQueue(Port))) { VIOSerialFreeBuffer(buf); } iter = PopEntryList(&Port->WriteBuffersList); while (iter != NULL) { PWRITE_BUFFER_ENTRY entry = CONTAINING_RECORD(iter, WRITE_BUFFER_ENTRY, ListEntry); ExFreePoolWithTag(entry->Buffer, VIOSERIAL_DRIVER_MEMORY_TAG); ExFreePoolWithTag(entry, VIOSERIAL_DRIVER_MEMORY_TAG); iter = PopEntryList(&Port->WriteBuffersList); }; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "<-- %s\n", __FUNCTION__); return STATUS_SUCCESS; }
VOID VIOSerialPortIoStop( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG ActionFlags ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(Queue)); PVIOSERIAL_PORT pport = pdoData->port; ASSERT(pport->PendingReadRequest == Request); TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "-->%s\n", __FUNCTION__); WdfSpinLockAcquire(pport->InBufLock); if (ActionFlags & WdfRequestStopActionSuspend ) { WdfRequestStopAcknowledge(Request, FALSE); } else if(ActionFlags & WdfRequestStopActionPurge) { if (WdfRequestUnmarkCancelable(Request) != STATUS_CANCELLED) { pport->PendingReadRequest = NULL; WdfRequestCompleteWithInformation(Request , STATUS_CANCELLED, 0L); } } WdfSpinLockRelease(pport->InBufLock); return; }
VOID VIOSerialPortWriteRequestCancel(IN WDFREQUEST Request) { PVIOSERIAL_PORT Port = RawPdoSerialPortGetData( WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)))->port; PSINGLE_LIST_ENTRY iter; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> %s Request: 0x%p\n", __FUNCTION__, Request); // synchronize with VIOSerialReclaimConsumedBuffers because the pending // request is not guaranteed to be alive after we return from this callback WdfSpinLockAcquire(Port->OutVqLock); iter = &Port->WriteBuffersList; while ((iter = iter->Next) != NULL) { PWRITE_BUFFER_ENTRY entry = CONTAINING_RECORD(iter, WRITE_BUFFER_ENTRY, ListEntry); if (entry->Request == Request) { entry->Request = NULL; break; } } WdfSpinLockRelease(Port->OutVqLock); WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- %s\n", __FUNCTION__); }
VOID VIOSerialPortReadRequestCancel( IN WDFREQUEST Request ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request))); BOOLEAN reqComplete = FALSE; TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "-->%s called on request 0x%p\n", __FUNCTION__, Request); WdfSpinLockAcquire(pdoData->port->InBufLock); ASSERT(pdoData->port->PendingReadRequest == Request); if (pdoData->port->PendingReadRequest) { pdoData->port->PendingReadRequest = NULL; reqComplete = TRUE; } WdfSpinLockRelease(pdoData->port->InBufLock); if (reqComplete) { WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,"<-- %s\n", __FUNCTION__); return; }
VOID BusDogTraceFifoCleanUp( VOID ) { ULONG i; PAGED_CODE (); // // Clean up anything in the trace fifo // WdfSpinLockAcquire(BusDogTraceFifoLock); for (i = 0; i < BUSDOG_FILTER_TRACE_FIFO_LENGTH; i++) { if (BusDogTraceFifo.TraceItems[i] != NULL) { ExFreePool(BusDogTraceFifo.TraceItems[i]); BusDogTraceFifo.TraceItems[i] = NULL; } } BusDogTraceFifo.WriteIndex = 0; BusDogTraceFifo.ReadIndex = 0; WdfSpinLockRelease(BusDogTraceFifoLock); }
VOID VIOSerialPortWriteIoStop(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG ActionFlags) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData( WdfIoQueueGetDevice(Queue)); PVIOSERIAL_PORT pport = pdoData->port; TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "--> %s\n", __FUNCTION__); WdfSpinLockAcquire(pport->OutVqLock); if (ActionFlags & WdfRequestStopActionSuspend) { WdfRequestStopAcknowledge(Request, FALSE); } else if (ActionFlags & WdfRequestStopActionPurge) { if (WdfRequestUnmarkCancelable(Request) != STATUS_CANCELLED) { pport->PendingWriteRequest = NULL; WdfRequestComplete(Request, STATUS_OBJECT_NO_LONGER_EXISTS); } } WdfSpinLockRelease(pport->OutVqLock); TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "<-- %s\n", __FUNCTION__); }
static NTSTATUS HIDKeyboardSendStatus( PINPUT_DEVICE pContext, USHORT uType, USHORT uCode, ULONG uValue, WDFREQUEST Request) { PVIRTIO_INPUT_EVENT_WITH_REQUEST pEvent; NTSTATUS status; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> %s\n", __FUNCTION__); pEvent = VIOInputAlloc(sizeof(VIRTIO_INPUT_EVENT_WITH_REQUEST)); if (pEvent == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; } else { pEvent->Event.type = uType; pEvent->Event.code = uCode; pEvent->Event.value = uValue; pEvent->Request = Request; WdfSpinLockAcquire(pContext->StatusQLock); status = VIOInputAddOutBuf(pContext->StatusQ, &pEvent->Event); WdfSpinLockRelease(pContext->StatusQLock); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- %s\n", __FUNCTION__); return status; }
VOID NICFreeQueuedSendPackets( IN PFDO_DATA FdoData ) /*++ Routine Description: Free and complete the pended sends on SendQueueHead Assumption: This function is called with the Send SPINLOCK held. Arguments: FdoData Pointer to our FdoData Return Value: None --*/ { WDFREQUEST request; NTSTATUS status; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> NICFreeQueuedSendPackets\n"); do { status = WdfIoQueueRetrieveNextRequest( FdoData->PendingWriteQueue, &request ); if(!NT_SUCCESS(status) ) { if(STATUS_NO_MORE_ENTRIES != status){ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "WdfIoQueueRetrieveNextRequest failed %x\n", status); } break; } FdoData->nWaitSend--; WdfSpinLockRelease(FdoData->SendLock); WdfRequestCompleteWithInformation(request, status, 0); WdfSpinLockAcquire(FdoData->SendLock); } WHILE (TRUE); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- NICFreeQueuedSendPackets\n"); }
__inline VOID MP_FREE_SEND_PACKET( IN PFDO_DATA FdoData, IN PMP_TCB pMpTcb, IN NTSTATUS Status ) /*++ Routine Description: Recycle a MP_TCB and complete the packet if necessary Assumption: This function is called with the Send SPINLOCK held. Arguments: FdoData Pointer to our FdoData pMpTcb Pointer to MP_TCB Return Value: None --*/ { WDFREQUEST request; WDFDMATRANSACTION dmaTransaction; size_t length; ASSERT(MP_TEST_FLAG(pMpTcb, fMP_TCB_IN_USE)); dmaTransaction = pMpTcb->DmaTransaction; pMpTcb->DmaTransaction = NULL; MP_CLEAR_FLAGS(pMpTcb); FdoData->CurrSendHead = FdoData->CurrSendHead->Next; FdoData->nBusySend--; request = WdfDmaTransactionGetRequest(dmaTransaction); length = WdfDmaTransactionGetBytesTransferred(dmaTransaction); WdfObjectDelete( dmaTransaction ); if (request) { WdfSpinLockRelease(FdoData->SendLock); WdfRequestCompleteWithInformation(request, Status, length); FdoData->BytesTransmitted += length; WdfSpinLockAcquire(FdoData->SendLock); } }
VOID PepPendWorkRequest ( _In_ PPEP_WORK_CONTEXT WorkRequest ) /*++ Routine Description: This routine adds the given work request to the pending queue. Arguments: WorkRequest - Supplies a pointer to the work request. Return Value: None. --*/ { // // Ensure that the request is not already on some other queue. // NT_ASSERT(IsListEmpty(&WorkRequest->ListEntry) != FALSE); TraceEvents(INFO, DBG_PEP, "%s: Insert pending work request. " "Device=%p, WorkType=%d, NotificationId=%d.\n", __FUNCTION__, (PVOID)WorkRequest->PepInternalDevice, (ULONG)WorkRequest->WorkType, (ULONG)WorkRequest->NotificationId); // // Add the new request to the end of tail of the pending work queue. // WdfSpinLockAcquire(PepWorkListLock); InsertTailList(&PepPendingWorkList, &WorkRequest->ListEntry); WdfSpinLockRelease(PepWorkListLock); // // Schedule a worker to pick up the new work. // PepScheduleWorker(WorkRequest); return; }
VOID UfxDeviceSetRunStop ( _In_ UFXDEVICE UfxDevice, _In_ BOOLEAN Set ) /*++ Routine Description: Function that sets or clears the run/stop state on the controller. Setting the run state will initiate a connect to the host. Arguments: UfxDevice - Wdf object representing the UFXDEVICE Set - TRUE if setting the run state, FALSE if clearing the run state. --*/ { PCONTROLLER_CONTEXT ControllerContext; PUFXDEVICE_CONTEXT DeviceContext; BOOLEAN EventComplete; TraceEntry(); DeviceContext = UfxDeviceGetContext(UfxDevice); ControllerContext = DeviceGetControllerContext(DeviceContext->FdoWdfDevice); EventComplete = TRUE; WdfSpinLockAcquire(ControllerContext->DpcLock); if (Set) { // // #### TODO: Insert code to set the run state on the controller #### // } else { // // #### TODO: Insert code to clear the run state on the controller #### // } WdfSpinLockRelease(ControllerContext->DpcLock); if (EventComplete) { UfxDeviceEventComplete(UfxDevice, STATUS_SUCCESS); } TraceExit(); }
size_t VIOSerialSendBuffers(IN PVIOSERIAL_PORT Port, IN PVOID Buffer, IN size_t Length) { struct virtqueue *vq = GetOutQueue(Port); struct VirtIOBufferDescriptor sg[QUEUE_DESCRIPTORS]; PVOID buffer = Buffer; size_t length = Length; int out = 0; int ret; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> %s Buffer: %p Length: %d\n", __FUNCTION__, Buffer, Length); if (BYTES_TO_PAGES(Length) > QUEUE_DESCRIPTORS) { return 0; } while (length > 0) { sg[out].physAddr = MmGetPhysicalAddress(buffer); sg[out].length = min(length, PAGE_SIZE); buffer = (PVOID)((LONG_PTR)buffer + sg[out].length); length -= sg[out].length; out += 1; } WdfSpinLockAcquire(Port->OutVqLock); ret = virtqueue_add_buf(vq, sg, out, 0, Buffer, NULL, 0); virtqueue_kick(vq); if (ret >= 0) { Port->OutVqFull = (ret == 0); } else { Length = 0; TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "Error adding buffer to queue (ret = %d)\n", ret); } WdfSpinLockRelease(Port->OutVqLock); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- %s\n", __FUNCTION__); return Length; }
VOID VIOSerialSendCtrlMsg( IN WDFDEVICE Device, IN ULONG id, IN USHORT event, IN USHORT value ) { struct VirtIOBufferDescriptor sg; struct virtqueue *vq; UINT len; PPORTS_DEVICE pContext = GetPortsDevice(Device); VIRTIO_CONSOLE_CONTROL cpkt; int cnt = 0; if (!pContext->isHostMultiport) { return; } vq = pContext->c_ovq; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s vq = %p\n", __FUNCTION__, vq); cpkt.id = id; cpkt.event = event; cpkt.value = value; sg.physAddr = MmGetPhysicalAddress(&cpkt); sg.ulSize = sizeof(cpkt); WdfSpinLockAcquire(pContext->CVqLock); if(0 <= vq->vq_ops->add_buf(vq, &sg, 1, 0, &cpkt, NULL, 0)) { vq->vq_ops->kick(vq); while(!vq->vq_ops->get_buf(vq, &len)) { KeStallExecutionProcessor(50); if(++cnt > RETRY_THRESHOLD) { TraceEvents(TRACE_LEVEL_FATAL, DBG_PNP, "<-> %s retries = %d\n", __FUNCTION__, cnt); break; } } } WdfSpinLockRelease(pContext->CVqLock); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s cnt = %d\n", __FUNCTION__, cnt); }
NTSTATUS BusDogFufillRequestWithTraces( IN WDFREQUEST Request, OUT size_t* bytesWritten ) { NTSTATUS status; WdfSpinLockAcquire(BusDogTraceFifoLock); status = __BusDogFufillRequestWithTraces(Request, bytesWritten); WdfSpinLockRelease(BusDogTraceFifoLock); return status; }
void BthEchoConnectionObjectDisconnectCompletion( _In_ WDFREQUEST Request, _In_ WDFIOTARGET Target, _In_ PWDF_REQUEST_COMPLETION_PARAMS Params, _In_ WDFCONTEXT Context ) /*++ Description: Completion routine for disconnect BRB completion In this routine we set the connection to disconnect and set the DisconnectEvent. Arguments: Request - Request completed Target - Target to which request was sent Params - Completion parameters Context - We receive connection as the context --*/ { PBTHECHO_CONNECTION connection = (PBTHECHO_CONNECTION) Context; UNREFERENCED_PARAMETER(Request); UNREFERENCED_PARAMETER(Target); UNREFERENCED_PARAMETER(Params); WdfSpinLockAcquire(connection->ConnectionLock); connection->ConnectionState = ConnectionStateDisconnected; WdfSpinLockRelease(connection->ConnectionLock); // // Disconnect complete, set the event // KeSetEvent( &connection->DisconnectEvent, 0, FALSE ); }
NTSTATUS VIOSerialPortEvtDeviceD0Exit( IN WDFDEVICE Device, IN WDF_POWER_DEVICE_STATE TargetState ) { PVIOSERIAL_PORT Port = RawPdoSerialPortGetData(Device)->port; PPORT_BUFFER buf; PSINGLE_LIST_ENTRY iter; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "--> %s TargetState: %d\n", __FUNCTION__, TargetState); Port->Removed = TRUE; VIOSerialDisableInterruptQueue(GetInQueue(Port)); WdfSpinLockAcquire(Port->InBufLock); VIOSerialDiscardPortDataLocked(Port); Port->InBuf = NULL; WdfSpinLockRelease(Port->InBufLock); VIOSerialReclaimConsumedBuffers(Port); while (buf = (PPORT_BUFFER)virtqueue_detach_unused_buf(GetInQueue(Port))) { VIOSerialFreeBuffer(buf); } iter = PopEntryList(&Port->WriteBuffersList); while (iter != NULL) { PWRITE_BUFFER_ENTRY entry = CONTAINING_RECORD(iter, WRITE_BUFFER_ENTRY, ListEntry); ExFreePoolWithTag(entry->Buffer, VIOSERIAL_DRIVER_MEMORY_TAG); WdfObjectDelete(entry->EntryHandle); iter = PopEntryList(&Port->WriteBuffersList); }; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "<-- %s\n", __FUNCTION__); return STATUS_SUCCESS; }
VOID VIOSerialPortWriteRequestCancel(IN WDFREQUEST Request) { PVIOSERIAL_PORT Port = RawPdoSerialPortGetData( WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)))->port; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> %s Request: 0x%p\n", __FUNCTION__, Request); // synchronize with VIOSerialReclaimConsumedBuffers because the pending // request is not guaranteed to be alive after we return from this callback WdfSpinLockAcquire(Port->OutVqLock); Port->PendingWriteRequest = NULL; WdfSpinLockRelease(Port->OutVqLock); WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- %s\n", __FUNCTION__); }
VOID VIOSerialPortCreate( IN WDFDEVICE WdfDevice, IN WDFREQUEST Request, IN WDFFILEOBJECT FileObject ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WdfDevice); NTSTATUS status = STATUS_SUCCESS; UNREFERENCED_PARAMETER(FileObject); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "%s Port id = %d\n", __FUNCTION__, pdoData->port->PortId); if (pdoData->port->Removed) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "Connect request on removed port id %d\n", pdoData->port->PortId); status = STATUS_OBJECT_NO_LONGER_EXISTS; } else if (pdoData->port->GuestConnected == TRUE) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "Guest already connected to port id %d\n", pdoData->port->PortId); status = STATUS_OBJECT_NAME_EXISTS; } else { pdoData->port->GuestConnected = TRUE; WdfSpinLockAcquire(pdoData->port->OutVqLock); VIOSerialReclaimConsumedBuffers(pdoData->port); WdfSpinLockRelease(pdoData->port->OutVqLock); VIOSerialSendCtrlMsg(pdoData->port->BusDevice, pdoData->port->PortId, VIRTIO_CONSOLE_PORT_OPEN, 1); } WdfRequestComplete(Request, status); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "<-- %s\n", __FUNCTION__); }
VOID VIOSerialPortReadRequestCancel( IN WDFREQUEST Request ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request))); TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "-->%s called on request 0x%p\n", __FUNCTION__, Request); // synchronize with VIOSerialQueuesInterruptDpc because the pending // request is not guaranteed to be alive after we return from this callback WdfSpinLockAcquire(pdoData->port->InBufLock); pdoData->port->PendingReadRequest = NULL; WdfSpinLockRelease(pdoData->port->InBufLock); WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE, "<-- %s\n", __FUNCTION__); }
BOOLEAN VIOSerialWillWriteBlock( IN PVIOSERIAL_PORT port ) { BOOLEAN ret = FALSE; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"--> %s\n", __FUNCTION__); if (!port->HostConnected) { return TRUE; } WdfSpinLockAcquire(port->OutVqLock); VIOSerialReclaimConsumedBuffers(port); ret = port->OutVqFull; WdfSpinLockRelease(port->OutVqLock); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"<-- %s\n", __FUNCTION__); return ret; }
VOID VirtRngEvtRequestCancel(IN WDFREQUEST Request) { PDEVICE_CONTEXT context = GetDeviceContext(WdfIoQueueGetDevice( WdfRequestGetIoQueue(Request))); PSINGLE_LIST_ENTRY iter; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "--> %!FUNC! Cancelled Request: %p", Request); WdfSpinLockAcquire(context->VirtQueueLock); WdfRequestComplete(Request, STATUS_CANCELLED); iter = &context->ReadBuffersList; while (iter->Next != NULL) { PREAD_BUFFER_ENTRY entry = CONTAINING_RECORD(iter->Next, READ_BUFFER_ENTRY, ListEntry); if (Request == entry->Request) { TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Clear entry %p request.", entry); entry->Request = NULL; break; } else { iter = iter->Next; } }; WdfSpinLockRelease(context->VirtQueueLock); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<-- %!FUNC!"); }
VOID VIOSerialPortWriteIoStop(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG ActionFlags) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData( WdfIoQueueGetDevice(Queue)); PVIOSERIAL_PORT pport = pdoData->port; TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "--> %s\n", __FUNCTION__); WdfSpinLockAcquire(pport->OutVqLock); if (ActionFlags & WdfRequestStopActionSuspend) { WdfRequestStopAcknowledge(Request, FALSE); } else if (ActionFlags & WdfRequestStopActionPurge) { if (WdfRequestUnmarkCancelable(Request) != STATUS_CANCELLED) { PSINGLE_LIST_ENTRY iter = &pport->WriteBuffersList; while ((iter = iter->Next) != NULL) { PWRITE_BUFFER_ENTRY entry = CONTAINING_RECORD(iter, WRITE_BUFFER_ENTRY, ListEntry); if (entry->Request == Request) { entry->Request = NULL; break; } } WdfRequestComplete(Request, STATUS_OBJECT_NO_LONGER_EXISTS); } } WdfSpinLockRelease(pport->OutVqLock); TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "<-- %s\n", __FUNCTION__); }
VOID BusDogAddTraceToFifo( WDFDEVICE device, ULONG DeviceId, BUSDOG_REQUEST_TYPE Type, BUSDOG_REQUEST_PARAMS Params, PVOID TraceBuffer, ULONG BufferLength ) { PBUSDOG_FILTER_TRACE_FIFO_ITEM pTraceItem = NULL; WDFREQUEST request; NTSTATUS status; WdfSpinLockAcquire(BusDogTraceFifoLock); // // First add trace to the fifo // pTraceItem = BusDogTraceFifo.TraceItems[BusDogTraceFifo.WriteIndex]; pTraceItem = __BusDogCreateTrace( pTraceItem, DeviceId, Type, Params, TraceBuffer, BufferLength); BusDogTraceFifo.TraceItems[BusDogTraceFifo.WriteIndex] = pTraceItem; BusDogTraceFifo.WriteIndex++; if (BusDogTraceFifo.WriteIndex >= BUSDOG_FILTER_TRACE_FIFO_LENGTH) BusDogTraceFifo.WriteIndex = 0; if (BusDogTraceFifo.WriteIndex == BusDogTraceFifo.ReadIndex) { BusDogPrint(BUSDOG_DEBUG_ERROR, "On noes! We have overflow\n"); } // // Now see if we can complete a request from the manual queue // status = WdfIoQueueRetrieveNextRequest( BufferRequestQueue, &request); if (NT_SUCCESS(status)) { size_t bytesWritten; status = __BusDogFufillRequestWithTraces(request, &bytesWritten); // // Ok for better or worse we finally completed this request // WdfRequestCompleteWithInformation(request, status, bytesWritten); } else { if (status != STATUS_NO_MORE_ENTRIES) { BusDogPrint(BUSDOG_DEBUG_ERROR, "WdfIoQueueRetrieveNextRequest failed - 0x%x\n", status); } } WdfSpinLockRelease(BusDogTraceFifoLock); }
BOOLEAN NICEvtProgramDmaFunction( IN WDFDMATRANSACTION Transaction, IN WDFDEVICE Device, IN PVOID Context, IN WDF_DMA_DIRECTION Direction, IN PSCATTER_GATHER_LIST ScatterGather ) /*++ Routine Description: Arguments: Return Value: --*/ { PFDO_DATA fdoData; WDFREQUEST request; NTSTATUS status; UNREFERENCED_PARAMETER( Context ); UNREFERENCED_PARAMETER( Direction ); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> NICEvtProgramDmaFunction\n"); fdoData = FdoGetData(Device); request = WdfDmaTransactionGetRequest(Transaction); WdfSpinLockAcquire(fdoData->SendLock); // // If tcb or link is not available, queue the request // if (!MP_TCB_RESOURCES_AVAIABLE(fdoData)) { TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "Resource is not available: queue Request %p\n", request); // // Must abort the transaction before deleting. // (VOID) WdfDmaTransactionDmaCompletedFinal(Transaction, 0, &status); ASSERT(NT_SUCCESS(status)); WdfObjectDelete( Transaction ); // // Queue the request for later processing. // status = WdfRequestForwardToIoQueue(request, fdoData->PendingWriteQueue); if(!NT_SUCCESS(status)) { ASSERTMSG(" WdfRequestForwardToIoQueue failed ", FALSE); WdfSpinLockRelease(fdoData->SendLock); WdfRequestCompleteWithInformation(request, STATUS_UNSUCCESSFUL, 0); return FALSE; } fdoData->nWaitSend++; } else { status = NICWritePacket(fdoData, Transaction, ScatterGather); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "<-- NICEvtProgramDmaFunction returning %!STATUS!\n", status); // // Must abort the transaction before deleting. // (VOID )WdfDmaTransactionDmaCompletedFinal(Transaction, 0, &status); ASSERT(NT_SUCCESS(status)); WdfObjectDelete( Transaction ); WdfSpinLockRelease(fdoData->SendLock); WdfRequestCompleteWithInformation(request, STATUS_UNSUCCESSFUL, 0); return FALSE; } } WdfSpinLockRelease(fdoData->SendLock); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- NICEvtProgramDmaFunction\n"); return TRUE; }
/* 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); */ }
VOID VIOSerialPortRead( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(Queue)); size_t length; NTSTATUS status; PVOID systemBuffer; BOOLEAN nonBlock; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ, "-->%s\n", __FUNCTION__); nonBlock = ((WdfFileObjectGetFlags(WdfRequestGetFileObject(Request)) & FO_SYNCHRONOUS_IO) != FO_SYNCHRONOUS_IO); status = WdfRequestRetrieveOutputBuffer(Request, Length, &systemBuffer, &length); if (!NT_SUCCESS(status)) { WdfRequestComplete(Request, status); return; } WdfSpinLockAcquire(pdoData->port->InBufLock); if (!VIOSerialPortHasDataLocked(pdoData->port)) { if (!pdoData->port->HostConnected) { WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); } else { ASSERT (pdoData->port->PendingReadRequest == NULL); status = WdfRequestMarkCancelableEx(Request, VIOSerialPortReadRequestCancel); if (!NT_SUCCESS(status)) { WdfRequestComplete(Request, status); } else { pdoData->port->PendingReadRequest = Request; } } } else { length = (ULONG)VIOSerialFillReadBufLocked(pdoData->port, systemBuffer, length); if (length) { WdfRequestCompleteWithInformation(Request, status, (ULONG_PTR)length); } else { WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); } } WdfSpinLockRelease(pdoData->port->InBufLock); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,"<-- %s\n", __FUNCTION__); return; }