__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 AmccPciEvtInterruptDpc( __in WDFINTERRUPT WdfInterrupt, __in WDFOBJECT WdfDevice ) /*++ Routine Description: DPC callback for ISR. Arguments: WdfInterrupt - Handle to the framework interrupt object WdfDevice - Associated device object. Return Value: --*/ { PAMCC_DEVICE_EXTENSION devExt; WDFREQUEST request; REQUEST_CONTEXT * transfer; NTSTATUS status; size_t transferred; BOOLEAN transactionComplete; UNREFERENCED_PARAMETER( WdfInterrupt ); devExt = AmccPciGetDevExt(WdfDevice); // // Retreive request and transfer. // request = devExt->CurrentRequest; transfer = GetRequestContext(request); // // Check to see if the request is cancelled by the system. While // we are DMAing a large buffer into multiple transaction, // there is good possibilty for the request to get cancelled because // the originator of the request exited or cancelled the I/O explicitly. // if(WdfRequestIsCanceled(request)) { TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO, "Aborted DMA transaction 0x%p", request); WdfObjectDelete( transfer->DmaTransaction ); devExt->CurrentRequest = NULL; WdfRequestComplete(request, STATUS_CANCELLED); return; } // // The boolean transactionComplete indicates whether the transaction has // exited the transfer state, e.g. no further transfers are scheduled. // // If transactionComplete == FALSE, then the next DMA transfer has been // scheduled, e.g. the next interrrupt will drive the ISR again. // // If transactionComplete == TRUE, then status indicates the reason; // SUCCESS is the nomative case, while non-SUCCESS indicates the // DMA transaction failed for "status" reason. // transactionComplete = WdfDmaTransactionDmaCompleted( transfer->DmaTransaction, &status ); if (transactionComplete) { ASSERT(status != STATUS_MORE_PROCESSING_REQUIRED); // // No more data: request is complete // TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_IO, "Request %p completed: status %X", request, status); // // Get the final bytes transferred count. // transferred = WdfDmaTransactionGetBytesTransferred( transfer->DmaTransaction ); TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_IO, "Bytes transfered %d", (int) transferred ); // // Delete this DmaTransaction transaction. // WdfObjectDelete( transfer->DmaTransaction ); // // Clean-up for this request. // devExt->CurrentRequest = NULL; // // Complete this IO request. // WdfRequestCompleteWithInformation( request, status, (NT_SUCCESS(status)) ? transferred : 0 ); } }