__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); } }
__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: Send spinlock has been acquired Arguments: FdoData Pointer to our FdoData pMpTcb Pointer to MP_TCB Status Irp completion status Return Value: None --*/ { PIRP Irp; ASSERT(MP_TEST_FLAG(pMpTcb, fMP_TCB_IN_USE)); Irp = pMpTcb->Irp; pMpTcb->Irp = NULL; pMpTcb->Count = 0; MP_CLEAR_FLAGS(pMpTcb); FdoData->CurrSendHead = FdoData->CurrSendHead->Next; FdoData->nBusySend--; ASSERT(FdoData->nBusySend >= 0); if (Irp) { KeReleaseSpinLockFromDpcLevel(&FdoData->SendLock); NICCompleteSendRequest(FdoData, Irp, Status, pMpTcb->PacketLength, TRUE // Yes, we are calling at DISPATCH_LEVEL ); KeAcquireSpinLockAtDpcLevel(&FdoData->SendLock); } }