/* * -------------------------------------------------------------------------- * Implements filter driver's FilterOidRequestComplete function. * -------------------------------------------------------------------------- */ VOID OvsExtOidRequestComplete(NDIS_HANDLE filterModuleContext, PNDIS_OID_REQUEST oidRequest, NDIS_STATUS status) { POVS_SWITCH_CONTEXT switchObject = (POVS_SWITCH_CONTEXT)filterModuleContext; PNDIS_OID_REQUEST origReq = OvsOidGetOrigRequest(oidRequest); POVS_OID_CONTEXT oidContext = OvsOidGetContext(oidRequest); /* Only one of the two should be set */ ASSERT(origReq != NULL || oidContext != NULL); ASSERT(oidContext != NULL || origReq != NULL); OVS_LOG_TRACE("Enter: oidRequest %p, reqType: %d", oidRequest, oidRequest->RequestType); if (origReq == NULL) { NdisInterlockedDecrement(&(switchObject->pendingOidCount)); oidContext->status = status; NdisSetEvent(&oidContext->oidComplete); OVS_LOG_INFO("Internally generated request"); goto done; } switch(oidRequest->RequestType) { case NdisRequestMethod: OvsOidRequestCompleteMethod(switchObject, oidRequest, origReq, status); break; case NdisRequestSetInformation: OvsOidRequestCompleteSetInfo(switchObject, oidRequest, origReq, status); break; case NdisRequestQueryInformation: case NdisRequestQueryStatistics: default: OvsOidRequestCompleteQuery(switchObject, oidRequest, origReq, status); break; } OvsOidSetOrigRequest(oidRequest, NULL); NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, oidRequest); NdisFOidRequestComplete(switchObject->NdisFilterHandle, origReq, status); NdisInterlockedDecrement(&(switchObject->pendingOidCount)); done: OVS_LOG_TRACE("Exit"); }
//------------------------------------------------------------------------------ void eventkcal_getEventForUser(void* pEvent_p, size_t* pSize_p) { tOplkError error; BOOL fRet; UINT32 timeout = 500; // Check parameter validity ASSERT(pEvent_p != NULL); ASSERT(pSize_p != NULL); if (!instance_l.fInitialized) return; fRet = NdisWaitEvent(&instance_l.userWaitEvent, timeout); if (fRet && (instance_l.userEventCount == 0)) { NdisResetEvent(&instance_l.userWaitEvent); return; } NdisResetEvent(&instance_l.userWaitEvent); // Kernel-to-user queue is processed with higher priority. if (eventkcal_getEventCountCircbuf(kEventQueueK2U) > 0) { NdisInterlockedDecrement(&instance_l.userEventCount); error = eventkcal_getEventCircbuf(kEventQueueK2U, pEvent_p, pSize_p); if ((error != kErrorOk) || (pEvent_p == NULL)) { DEBUG_LVL_ERROR_TRACE("%s() Error reading K2U events %d!\n", __func__, error); } return; } else if (eventkcal_getEventCountCircbuf(kEventQueueUInt) > 0) { NdisInterlockedDecrement(&instance_l.userEventCount); error = eventkcal_getEventCircbuf(kEventQueueUInt, pEvent_p, pSize_p); if (error != kErrorOk) { DEBUG_LVL_ERROR_TRACE("%s() Error reading UINT events %d!\n", __func__, error); return; } } }
VOID TXNblRelease( _In_ PMP_ADAPTER Adapter, _In_ PNET_BUFFER_LIST NetBufferList, _In_ BOOLEAN fAtDispatch) /*++ Routine Description: Releases a reference on a NBL that is being transmitted. If the last reference is released, the NBL is returned to the protocol. Runs at IRQL <= DISPATCH_LEVEL. Arguments: Adapter Pointer to our adapter NetBufferList The NBL to release fAtDispatch TRUE if the current IRQL is DISPATCH_LEVEL Return Value: None. --*/ { if (0 == NdisInterlockedDecrement(&SEND_REF_FROM_NBL(NetBufferList))) { DEBUGP(MP_TRACE, "[%p] Send NBL %p complete.\n", Adapter, NetBufferList); NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL; NdisMSendNetBufferListsComplete( Adapter->AdapterHandle, NetBufferList, fAtDispatch ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL:0); } else { DEBUGP(MP_TRACE, "[%p] Send NBL %p not complete. RefCount: %i.\n", Adapter, NetBufferList, SEND_REF_FROM_NBL(NetBufferList)); } NdisInterlockedDecrement(&Adapter->nBusySend); }
//------------------------------------------------------------------------------ static void eventThread(void* pArg) { INT timeout = 50; PKTHREAD thread; BOOL fRet = FALSE; UNUSED_PARAMETER(pArg); // increase the priority of the thread thread = KeGetCurrentThread(); KeSetPriorityThread(thread, HIGH_PRIORITY); instance_l.fThreadIsRunning = TRUE; while (!instance_l.fStopThread) { fRet = NdisWaitEvent(&instance_l.kernelWaitEvent, timeout); if (fRet && (instance_l.kernelEventCount == 0)) { // Timeout occurred, continue to wait. NdisResetEvent(&instance_l.kernelWaitEvent); continue; } NdisResetEvent(&instance_l.kernelWaitEvent); /* first handle all kernel internal events --> higher priority! */ while (eventkcal_getEventCountCircbuf(kEventQueueKInt) > 0) { eventkcal_processEventCircbuf(kEventQueueKInt); NdisInterlockedDecrement(&instance_l.kernelEventCount); } if (eventkcal_getEventCountCircbuf(kEventQueueU2K) > 0) { eventkcal_processEventCircbuf(kEventQueueU2K); NdisInterlockedDecrement(&instance_l.kernelEventCount); } } instance_l.fThreadIsRunning = FALSE; }
VOID MPReturnPacket( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet) /*++ Routine Description: NDIS Miniport entry point called whenever protocols are done with a packet that we had indicated up and they had queued up for returning later. Arguments: MiniportAdapterContext - pointer to MP_ADAPTER structure Packet - packet being returned. Return Value: None. --*/ { PRCB pRCB = NULL; PMP_ADAPTER Adapter; BOOLEAN datagramsover=FALSE; UNREFERENCED_PARAMETER(MiniportAdapterContext); DEBUGP(MP_TRACE, ("---> MPReturnPacket\n")); pRCB = *(PRCB *)Packet->MiniportReserved; Adapter = pRCB->Adapter; ASSERT(Adapter); Adapter->nPacketsReturned++; ncmdivi: if(NdisInterlockedDecrement(&pRCB->Ref) == 0) { if(FALSE==datagramsover) { pRCB->Ref=1; datagramsover=cdc_ncm_rx_fixup(Adapter,pRCB); goto ncmdivi; } NICFreeRCB(pRCB); } DEBUGP(MP_TRACE, ("<--- MPReturnPacket\n")); }
VOID tapWaitForReceiveNblInFlightCountZeroEvent(__in PTAP_ADAPTER_CONTEXT Adapter) { LONG nblCount; // // Wait until higher-level protocol has returned all NBLs // to the driver. // // Add one NBL "bias" to insure allow event to be reset safely. nblCount = NdisInterlockedIncrement(&Adapter->ReceiveNblInFlightCount); ASSERT(nblCount > 0); NdisResetEvent(&Adapter->ReceiveNblInFlightCountZeroEvent); // // Now remove the bias and wait for the ReceiveNblInFlightCountZeroEvent // if the count returned is not zero. // nblCount = NdisInterlockedDecrement(&Adapter->ReceiveNblInFlightCount); ASSERT(nblCount >= 0); if (nblCount) { LARGE_INTEGER startTime, currentTime; NdisGetSystemUpTimeEx(&startTime); for (;;) { BOOLEAN waitResult = NdisWaitEvent(&Adapter->ReceiveNblInFlightCountZeroEvent, TAP_WAIT_POLL_LOOP_TIMEOUT); NdisGetSystemUpTimeEx(¤tTime); if (waitResult) { break; } DEBUGP(("[%s] Waiting for %d in-flight receive NBLs to be returned.\n", MINIPORT_INSTANCE_ID(Adapter), Adapter->ReceiveNblInFlightCount)); } DEBUGP(("[%s] Waited %d ms for all in-flight NBLs to be returned.\n", MINIPORT_INSTANCE_ID(Adapter), (currentTime.LowPart - startTime.LowPart))); } }
A_STATUS CAR6KMini::WMISendControlPacket( IN PVOID osbuf, IN HTC_ENDPOINT_ID endPoint) { A_STATUS status = A_OK; if (WMI_CONTROL_MBOX != endPoint) NdisInterlockedIncrement(&m_TxPending); status = Ar6000SendPkt(endPoint,osbuf,AR6K_CONTROL_PKT_TAG); if (A_OK != status && A_PENDING != status && WMI_CONTROL_MBOX != endPoint) { NDIS_DEBUG_PRINTF(DBG_ERR, " %s(), Ar6000SendPkt Fail, status = %d \r\n", __FUNCTION__,status); NdisInterlockedDecrement(&m_TxPending); } return status; }
VOID ndisprotDerefOpen( IN PNDISPROT_OPEN_CONTEXT pOpenContext ) /*++ Routine Description: Dereference the given open context. If the ref count goes to zero, free it. NOTE: called without holding the opencontext lock Arguments: pOpenContext - pointer to open context Return Value: None --*/ { if (NdisInterlockedDecrement((PLONG)&pOpenContext->RefCount) == 0) { DEBUGP(DL_INFO, ("DerefOpen: Open %p, Flags %x, ref count is zero!\n", pOpenContext, pOpenContext->Flags)); NPROT_ASSERT(pOpenContext->BindingHandle == NULL); NPROT_ASSERT(pOpenContext->RefCount == 0); NPROT_ASSERT(pOpenContext->pFileObject == NULL); pOpenContext->oc_sig++; // // Free it. // NPROT_FREE_MEM(pOpenContext); } }
void netgSendToMiniportComplete(IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pNdisPacket, IN NDIS_STATUS Status) { PIRP pIrp; PIO_STACK_LOCATION pIrpSp; PADAPT pAdapt; POPEN_CONTEXT pOpenContext; PNDIS_BUFFER pNdisBuffer; PVOID VirtualAddr; UINT BufferLength; UINT TotalLength; DBGPRINT(("==> netgSendToMiniportComplete\n")); pAdapt = (PADAPT)ProtocolBindingContext; pOpenContext = pAdapt->pOpenContext; pIrp = (((PNPROT_SEND_PACKET_RSVD)&((pNdisPacket)->ProtocolReserved[0]))->pIrp); // Free buffer NdisGetFirstBufferFromPacket(pNdisPacket, &pNdisBuffer, &VirtualAddr, &BufferLength, &TotalLength); NdisFreeBuffer(pNdisBuffer); // Free packet if (NdisInterlockedDecrement((PLONG)&((PNPROT_SEND_PACKET_RSVD)&((pNdisPacket)->ProtocolReserved[0]))->RefCount) == 0) { \ NdisFreePacket(pNdisPacket); } CompleteTheIRP: // Complete the Write IRP with the right status. pIrpSp = IoGetCurrentIrpStackLocation(pIrp); if (Status == NDIS_STATUS_SUCCESS) { pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length; pIrp->IoStatus.Status = STATUS_SUCCESS; } else { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; } IoCompleteRequest(pIrp, IO_NO_INCREMENT); DBGPRINT(("<== netgSendToMiniportComplete\n")); }
/************************************************************************** * SteMiniportReturnPacket() * * NDIS Miniport エントリポイント * このドライバが上位プロトコルに通知したパケットが、プロトコルによって * 処理が終了した場合に NDIS によって呼ばれる。 * * 引数: * * MiniportAdapterContext : ADAPTER 構造体のポインタ * Packet : リターンされてきたパケット * * 返り値: * * 無し * **************************************************************************/ VOID SteMiniportReturnPacket( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet) { STE_ADAPTER *Adapter; Adapter = (STE_ADAPTER *)MiniportAdapterContext; DEBUG_PRINT0(3, "SteMiniportReturnPacket called\n"); SteFreeRecvPacket( Adapter, //IN STE_ADAPTER Packet //IN NDIS_PACKET ); NdisInterlockedDecrement( (PLONG)&Adapter->RecvIndicatedPackets //IN PLONG ); return; }
A_STATUS CAR6KMini::WMISendControlPacket( IN PVOID osbuf, HTC_ENDPOINT_ID Endpoint) { A_STATUS status; ndis_mini_buf_t *pNb; pNb = (ndis_mini_buf_t *)osbuf; SET_HTC_PACKET_INFO_TX(&pNb->HtcPacket, osbuf, a_netbuf_to_data(osbuf), a_netbuf_to_len(osbuf), Endpoint, AR6K_CONTROL_PKT_TAG); status = HTCSendPkt(m_pHTCTarget, &pNb->HtcPacket); if (A_OK != status && A_PENDING != status && m_ControlEp != Endpoint) NdisInterlockedDecrement(&m_TxPending); return status; }
VOID NICFreeNotify( IN PNOTICB pNotiCB) /*++ Routine Description: pRCB - pointer to RCB block Arguments: This routine reinitializes the RCB block and puts it back into the RecvFreeList for reuse. Return Value: VOID --*/ { PMP_ADAPTER Adapter = pNotiCB->Adapter; DEBUGP(MP_TRACE, ("--> NICFreeNotify %p\n", pNotiCB)); ASSERT(pNotiCB->Irp); // shouldn't be NULL ASSERT(!pNotiCB->Ref); // should be 0 ASSERT(pNotiCB->Adapter); // shouldn't be NULL IoReuseIrp(pNotiCB->Irp, STATUS_SUCCESS); pNotiCB->ulSize=0; // // Set the MDL field to NULL so that we don't end up double freeing the // MDL in our call to IoFreeIrp. // pNotiCB->Irp->MdlAddress = NULL; // // Insert the RCB back in the Recv free list // NdisAcquireSpinLock(&Adapter->InterruptNotifyLock); RemoveEntryList(&pNotiCB->List); InsertTailList(&Adapter->InterruptFreeList, &pNotiCB->List); NdisInterlockedDecrement(&Adapter->nBusyNotify); ASSERT(Adapter->nBusyNotify >= 0); NdisReleaseSpinLock(&Adapter->InterruptNotifyLock); // // For performance, instead of scheduling a workitem at the end of // every read completion, we will do it only when the number of // outstanding IRPs goes below NIC_SEND_LOW_WATERMARK. // We shouldn't queue a workitem if it's already scheduled and waiting in // the system workitem queue to be fired. // if((Adapter->nBusyNotify ==0) && MP_TEST_FLAG(Adapter, fMP_POST_INTERRUPT)) { MP_INC_REF(Adapter); NdisScheduleWorkItem(&Adapter->InterruptNotifyItem); } DEBUGP(MP_TRACE, ("<-- NICFreeNotify %d\n", Adapter->nBusyNotify)); }
/* * -------------------------------------------------------------------------- * Utility function to issue the specified OID to the NDIS stack. The OID is * directed towards the miniport edge of the extensible switch. * An OID that gets issued may not complete immediately, and in such cases, the * function waits for the OID to complete. Thus, this function must not be * called at the PASSIVE_LEVEL. * -------------------------------------------------------------------------- */ static NDIS_STATUS OvsIssueOidRequest(POVS_SWITCH_CONTEXT switchContext, NDIS_REQUEST_TYPE oidType, UINT32 oidRequestEnum, PVOID oidInputBuffer, UINT32 inputSize, PVOID oidOutputBuffer, UINT32 outputSize, UINT32 *outputSizeNeeded) { NDIS_STATUS status; PNDIS_OID_REQUEST oidRequest; POVS_OID_CONTEXT oidContext; ULONG OvsExtOidRequestId = 'ISVO'; DBG_UNREFERENCED_PARAMETER(inputSize); DBG_UNREFERENCED_PARAMETER(oidInputBuffer); OVS_LOG_TRACE("Enter: switchContext: %p, oidType: %d", switchContext, oidType); ASSERT(oidInputBuffer == NULL || inputSize != 0); ASSERT(oidOutputBuffer == NULL || outputSize != 0); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); oidRequest = OvsAllocateMemoryWithTag(sizeof *oidRequest, OVS_OID_POOL_TAG); if (!oidRequest) { status = NDIS_STATUS_RESOURCES; goto done; } oidContext = OvsAllocateMemoryWithTag(sizeof *oidContext, OVS_OID_POOL_TAG); if (!oidContext) { OvsFreeMemoryWithTag(oidRequest, OVS_OID_POOL_TAG); status = NDIS_STATUS_RESOURCES; goto done; } RtlZeroMemory(oidRequest, sizeof *oidRequest); RtlZeroMemory(oidContext, sizeof *oidContext); oidRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; oidRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1; oidRequest->Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1; oidRequest->RequestType = oidType; oidRequest->PortNumber = 0; oidRequest->Timeout = 0; oidRequest->RequestId = (PVOID)OvsExtOidRequestId; switch(oidType) { case NdisRequestQueryInformation: oidRequest->DATA.QUERY_INFORMATION.Oid = oidRequestEnum; oidRequest->DATA.QUERY_INFORMATION.InformationBuffer = oidOutputBuffer; oidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = outputSize; break; default: ASSERT(FALSE); status = NDIS_STATUS_INVALID_PARAMETER; break; } /* * We make use of the SourceReserved field in the OID request to store * pointers to the original OID (if any), and also context for completion * (if any). */ oidContext->status = NDIS_STATUS_SUCCESS; NdisInitializeEvent(&oidContext->oidComplete); OvsOidSetOrigRequest(oidRequest, NULL); OvsOidSetContext(oidRequest, oidContext); NdisInterlockedIncrement(&(switchContext->pendingOidCount)); status = NdisFOidRequest(switchContext->NdisFilterHandle, oidRequest); if (status == NDIS_STATUS_PENDING) { NdisWaitEvent(&oidContext->oidComplete, 0); } else { NdisInterlockedDecrement(&(switchContext->pendingOidCount)); } if (status == NDIS_STATUS_INVALID_LENGTH || oidContext->status == NDIS_STATUS_INVALID_LENGTH) { switch(oidType) { case NdisRequestQueryInformation: *outputSizeNeeded = oidRequest->DATA.QUERY_INFORMATION.BytesNeeded; } } status = oidContext->status; ASSERT(status != NDIS_STATUS_PENDING); OvsFreeMemoryWithTag(oidRequest, OVS_OID_POOL_TAG); OvsFreeMemoryWithTag(oidContext, OVS_OID_POOL_TAG); done: OVS_LOG_TRACE("Exit: status %8x.", status); return status; }
// // FilterOidRequestComplete Function // http://msdn.microsoft.com/en-us/library/ff549956(v=VS.85).aspx // _Use_decl_annotations_ VOID SxNdisOidRequestComplete( NDIS_HANDLE FilterModuleContext, PNDIS_OID_REQUEST NdisOidRequest, NDIS_STATUS Status ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; PNDIS_OID_REQUEST originalRequest; PVOID *oidRequestContext; PNDIS_SWITCH_NIC_OID_REQUEST nicOidRequestBuf; PNDIS_OBJECT_HEADER header; DEBUGP(DL_TRACE, ("===>SxOidRequestComplete, NdisOidRequest %p.\n", NdisOidRequest)); oidRequestContext = (PVOID*)(&NdisOidRequest->SourceReserved[0]); originalRequest = (*oidRequestContext); // // This is the internal request // if (originalRequest == NULL) { SxpNdisCompleteInternalOidRequest(switchObject, NdisOidRequest, Status); goto Cleanup; } // // Copy the information from the returned request to the original request // switch(NdisOidRequest->RequestType) { case NdisRequestMethod: originalRequest->DATA.METHOD_INFORMATION.OutputBufferLength = NdisOidRequest->DATA.METHOD_INFORMATION.OutputBufferLength; originalRequest->DATA.METHOD_INFORMATION.BytesRead = NdisOidRequest->DATA.METHOD_INFORMATION.BytesRead; originalRequest->DATA.METHOD_INFORMATION.BytesNeeded = NdisOidRequest->DATA.METHOD_INFORMATION.BytesNeeded; originalRequest->DATA.METHOD_INFORMATION.BytesWritten = NdisOidRequest->DATA.METHOD_INFORMATION.BytesWritten; if (NdisOidRequest->DATA.METHOD_INFORMATION.Oid == OID_SWITCH_NIC_REQUEST && switchObject->OldNicRequest != NULL) { nicOidRequestBuf = NdisOidRequest->DATA.METHOD_INFORMATION.InformationBuffer; Status = SxExtProcessNicRequestComplete(switchObject, switchObject->ExtensionContext, nicOidRequestBuf->OidRequest, nicOidRequestBuf->SourcePortId, nicOidRequestBuf->SourceNicIndex, nicOidRequestBuf->DestinationPortId, nicOidRequestBuf->DestinationNicIndex, Status); originalRequest->DATA.METHOD_INFORMATION.InformationBuffer = switchObject->OldNicRequest; switchObject->OldNicRequest = NULL; ExFreePoolWithTag(nicOidRequestBuf, SxExtAllocationTag); } break; case NdisRequestSetInformation: header = originalRequest->DATA.SET_INFORMATION.InformationBuffer; originalRequest->DATA.SET_INFORMATION.BytesRead = NdisOidRequest->DATA.SET_INFORMATION.BytesRead; originalRequest->DATA.SET_INFORMATION.BytesNeeded = NdisOidRequest->DATA.SET_INFORMATION.BytesNeeded; if (NdisOidRequest->DATA.METHOD_INFORMATION.Oid == OID_SWITCH_PORT_CREATE && Status != NDIS_STATUS_SUCCESS) { SxExtDeletePort(switchObject, switchObject->ExtensionContext, (PNDIS_SWITCH_PORT_PARAMETERS)header); } else if (NdisOidRequest->DATA.METHOD_INFORMATION.Oid == OID_SWITCH_PORT_CREATE && Status != NDIS_STATUS_SUCCESS) { SxExtDeleteNic(switchObject, switchObject->ExtensionContext, (PNDIS_SWITCH_NIC_PARAMETERS)header); } break; case NdisRequestQueryInformation: case NdisRequestQueryStatistics: default: originalRequest->DATA.QUERY_INFORMATION.BytesWritten = NdisOidRequest->DATA.QUERY_INFORMATION.BytesWritten; originalRequest->DATA.QUERY_INFORMATION.BytesNeeded = NdisOidRequest->DATA.QUERY_INFORMATION.BytesNeeded; break; } (*oidRequestContext) = NULL; NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, NdisOidRequest); NdisFOidRequestComplete(switchObject->NdisFilterHandle, originalRequest, Status); DEBUGP(DL_TRACE, ("<===SxOidRequestComplete.\n")); Cleanup: NdisInterlockedDecrement(&switchObject->PendingOidCount); }
NDIS_STATUS OvsExtOidRequest(NDIS_HANDLE filterModuleContext, PNDIS_OID_REQUEST oidRequest) { POVS_SWITCH_CONTEXT switchObject = (POVS_SWITCH_CONTEXT)filterModuleContext; NDIS_STATUS status = NDIS_STATUS_SUCCESS; PNDIS_OID_REQUEST clonedOidRequest = NULL; struct _METHOD *methodInfo = &(oidRequest->DATA.METHOD_INFORMATION); BOOLEAN completeOid = FALSE; ULONG bytesNeeded = 0; OVS_LOG_TRACE("Enter: oidRequest %p, reqType: %d", oidRequest, oidRequest->RequestType); status = NdisAllocateCloneOidRequest(switchObject->NdisFilterHandle, oidRequest, OVS_MEMORY_TAG, &clonedOidRequest); if (status != NDIS_STATUS_SUCCESS) { goto done; } NdisInterlockedIncrement(&(switchObject->pendingOidCount)); /* set the original oid request in cloned one. */ OvsOidSetOrigRequest(clonedOidRequest, oidRequest); OvsOidSetContext(clonedOidRequest, NULL); switch(clonedOidRequest->RequestType) { case NdisRequestSetInformation: status = OvsProcessSetOid(switchObject, clonedOidRequest, &completeOid); break; case NdisRequestMethod: status = OvsProcessMethodOid(switchObject, clonedOidRequest, &completeOid, &bytesNeeded); break; default: /* We do not handle other request types as of now. * We are just a passthrough for those. */ break; } if (completeOid == TRUE) { /* dont leave any reference back to original request, * even if we are freeing it up. */ OVS_LOG_INFO("Complete True oidRequest %p.", oidRequest); OvsOidSetOrigRequest(clonedOidRequest, NULL); NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, clonedOidRequest); methodInfo->BytesNeeded = bytesNeeded; NdisInterlockedDecrement(&switchObject->pendingOidCount); goto done; } /* pass the request down */ status = NdisFOidRequest(switchObject->NdisFilterHandle, clonedOidRequest); if (status != NDIS_STATUS_PENDING) { OvsExtOidRequestComplete(switchObject, clonedOidRequest, status); /* sample code says so */ status = NDIS_STATUS_PENDING; } done: OVS_LOG_TRACE("Exit: status %8x.", status); return status; }
// Write lock on the list must be held // Returns an entry that can be expired. The caller frees it PMP_BSS_ENTRY HelperPortExpireBSSEntry( __in PMP_BSS_LIST pBSSList, __in ULONGLONG ullMaxActiveTime, __in ULONGLONG ullExpireTimeStamp ) { PLIST_ENTRY pHead = NULL, pEntry = NULL; PMP_BSS_ENTRY pBSSEntry = NULL; BOOLEAN bFound = FALSE; // // We can expire an entry that has been around for longer // than this time // if (ullMaxActiveTime <= ullExpireTimeStamp) ullExpireTimeStamp -= ullMaxActiveTime; pHead = &(pBSSList->List); pEntry = pHead->Flink; while(pEntry != pHead) { pBSSEntry = CONTAINING_RECORD(pEntry, MP_BSS_ENTRY, Link); pEntry = pEntry->Flink; NdisAcquireSpinLock(&(pBSSEntry->Lock)); // // If the entry is older than we expected and its not in // use, we can expire it // if (pBSSEntry->HostTimestamp < ullExpireTimeStamp) { if (NdisInterlockedDecrement(&(pBSSEntry->RefCount)) == 0) { MpTrace(COMP_SCAN, DBG_LOUD, ("Expiring AP: %02X-%02X-%02X-%02X-%02X-%02X\n", pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5])); MPASSERT(pBSSEntry->pAssocRequest == NULL); MPASSERT(pBSSEntry->pAssocResponse == NULL); // // This is the entry we can expire. Remove it from the list. // NdisReleaseSpinLock(&(pBSSEntry->Lock)); HelperPortRemoveBSSEntry(pBSSList, pBSSEntry); bFound = TRUE; break; } else { // Someone is using the entry, we cannot remove/delete this. Add back // a ref and we will delete later on // This is subobtimal. Ideally the last person to decrement // refcount should delete the entry and not us. Modify to remove // the entry from the list, decrement its refcount and only free // the memory if the refcount has gone to zero NdisInterlockedIncrement(&(pBSSEntry->RefCount)); } } NdisReleaseSpinLock(&(pBSSEntry->Lock)); } if (bFound != TRUE) { pBSSEntry = NULL; } return pBSSEntry;
NDIS_STATUS HelperPortFlushBSSList( __in PMP_PORT Port ) { MP_RW_LOCK_STATE LockState; PLIST_ENTRY pListEntry; PMP_BSS_ENTRY pBSSEntry = NULL; LONG APRefCount; LIST_ENTRY TempList; PMP_HELPER_PORT HelperPort = MP_GET_HELPPORT(Port); PMP_BSS_LIST pDiscoveredBSSList = &(HelperPort->BSSList); // // Entries that are currently in use (eg for connection) // we cannot flush and instead would put in the temporary queue // InitializeListHead(&TempList); MP_ACQUIRE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState); while (!IsListEmpty(&(pDiscoveredBSSList->List))) { pListEntry = RemoveHeadList(&(pDiscoveredBSSList->List)); pBSSEntry = CONTAINING_RECORD(pListEntry, MP_BSS_ENTRY, Link); APRefCount = NdisInterlockedDecrement(&(pBSSEntry->RefCount)); if (APRefCount == 0) { NdisAcquireSpinLock(&(pBSSEntry->Lock)); MPASSERT(pBSSEntry->pAssocRequest == NULL); MPASSERT(pBSSEntry->pAssocResponse == NULL); if (pBSSEntry->pDot11BeaconFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame); pBSSEntry->pDot11BeaconFrame = NULL; pBSSEntry->BeaconFrameSize = 0; pBSSEntry->MaxBeaconFrameSize= 0; } if (pBSSEntry->pDot11ProbeFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame); pBSSEntry->pDot11ProbeFrame = NULL; pBSSEntry->ProbeFrameSize = 0; pBSSEntry->MaxProbeFrameSize= 0; } pBSSEntry->pDot11InfoElemBlob = NULL; pBSSEntry->InfoElemBlobSize = 0; NdisReleaseSpinLock(&(pBSSEntry->Lock)); MP_FREE_MEMORY(pBSSEntry); } else { // Restore refcount and save for adding back to list NdisInterlockedIncrement(&(pBSSEntry->RefCount)); InsertTailList(&TempList, pListEntry); } } pDiscoveredBSSList->NumOfBSSEntries = 0; // // Restore entries that are in use // while (!IsListEmpty(&TempList)) { pListEntry = RemoveHeadList(&TempList); InsertTailList(&(pDiscoveredBSSList->List), pListEntry); pDiscoveredBSSList->NumOfBSSEntries++; } // Since our scan list is flushed, also clear the last scan time HelperPort->ScanContext.LastScanTime = 0; MP_RELEASE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState); return NDIS_STATUS_SUCCESS;
VOID tapCompleteIrpAndFreeReceiveNetBufferList( __in PTAP_ADAPTER_CONTEXT Adapter, __in PNET_BUFFER_LIST NetBufferList, // Only one NB here... __in NTSTATUS IoCompletionStatus ) { PIRP irp; ULONG frameType, netBufferCount, byteCount; LONG nblCount; // Fetch NB frame type. frameType = tapGetNetBufferFrameType(NET_BUFFER_LIST_FIRST_NB(NetBufferList)); // Fetch statistics for all NBs linked to the NB. netBufferCount = tapGetNetBufferCountsFromNetBufferList( NetBufferList, &byteCount ); // Update statistics by frame type if(IoCompletionStatus == STATUS_SUCCESS) { switch(frameType) { case NDIS_PACKET_TYPE_DIRECTED: Adapter->FramesRxDirected += netBufferCount; Adapter->BytesRxDirected += byteCount; break; case NDIS_PACKET_TYPE_BROADCAST: Adapter->FramesRxBroadcast += netBufferCount; Adapter->BytesRxBroadcast += byteCount; break; case NDIS_PACKET_TYPE_MULTICAST: Adapter->FramesRxMulticast += netBufferCount; Adapter->BytesRxMulticast += byteCount; break; default: ASSERT(FALSE); break; } } // // Handle P2P Packet // ----------------- // Free MDL allocated for P2P Ethernet header. // if(TAP_RX_NBL_FLAG_TEST(NetBufferList,TAP_RX_NBL_FLAGS_IS_P2P)) { PNET_BUFFER netBuffer; PMDL mdl; netBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList); mdl = NET_BUFFER_FIRST_MDL(netBuffer); mdl->Next = NULL; NdisFreeMdl(mdl); } // // Handle Injected Packet // ----------------------- // Free MDL and data buffer allocated for injected packet. // if(TAP_RX_NBL_FLAG_TEST(NetBufferList,TAP_RX_NBL_FLAGS_IS_INJECTED)) { PNET_BUFFER netBuffer; PMDL mdl; PUCHAR injectBuffer; netBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList); mdl = NET_BUFFER_FIRST_MDL(netBuffer); injectBuffer = (PUCHAR )MmGetSystemAddressForMdlSafe(mdl,NormalPagePriority); if(injectBuffer) { NdisFreeMemory(injectBuffer,0,0); } NdisFreeMdl(mdl); } // // Complete the IRP // irp = (PIRP )NetBufferList->MiniportReserved[0]; if(irp) { irp->IoStatus.Status = IoCompletionStatus; IoCompleteRequest(irp, IO_NO_INCREMENT); } // Decrement in-flight receive NBL count. nblCount = NdisInterlockedDecrement(&Adapter->ReceiveNblInFlightCount); ASSERT(nblCount >= 0 ); if (0 == nblCount) { NdisSetEvent(&Adapter->ReceiveNblInFlightCountZeroEvent); } // Free the NBL NdisFreeNetBufferList(NetBufferList); }
NDIS_STATUS SxLibIssueOidRequest( _In_ PSX_SWITCH_OBJECT Switch, _In_ NDIS_REQUEST_TYPE RequestType, _In_ NDIS_OID Oid, _In_opt_ PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _In_ ULONG OutputBufferLength, _In_ ULONG MethodId, _In_ UINT Timeout, _Out_ PULONG BytesNeeded ) { NDIS_STATUS status; PSX_OID_REQUEST oidRequest; PNDIS_OID_REQUEST ndisOidRequest; ULONG bytesNeeded; BOOLEAN asyncCompletion; status = NDIS_STATUS_SUCCESS; oidRequest = NULL; bytesNeeded = 0; asyncCompletion = FALSE; NdisInterlockedIncrement(&Switch->PendingOidCount); if (Switch->ControlFlowState != SxSwitchAttached) { status = NDIS_STATUS_CLOSING; goto Cleanup; } // // Dynamically allocate filter request so that we can handle asynchronous // completion. // oidRequest = (PSX_OID_REQUEST)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(SX_OID_REQUEST), SxExtAllocationTag); if (oidRequest == NULL) { goto Cleanup; } NdisZeroMemory(oidRequest, sizeof(SX_OID_REQUEST)); ndisOidRequest = &oidRequest->NdisOidRequest; NdisInitializeEvent(&oidRequest->ReqEvent); ndisOidRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; ndisOidRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1; ndisOidRequest->Header.Size = sizeof(NDIS_OID_REQUEST); ndisOidRequest->RequestType = RequestType; ndisOidRequest->Timeout = Timeout; switch (RequestType) { case NdisRequestQueryInformation: ndisOidRequest->DATA.QUERY_INFORMATION.Oid = Oid; ndisOidRequest->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer; ndisOidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength; break; case NdisRequestSetInformation: ndisOidRequest->DATA.SET_INFORMATION.Oid = Oid; ndisOidRequest->DATA.SET_INFORMATION.InformationBuffer = InformationBuffer; ndisOidRequest->DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength; break; case NdisRequestMethod: ndisOidRequest->DATA.METHOD_INFORMATION.Oid = Oid; ndisOidRequest->DATA.METHOD_INFORMATION.MethodId = MethodId; ndisOidRequest->DATA.METHOD_INFORMATION.InformationBuffer = InformationBuffer; ndisOidRequest->DATA.METHOD_INFORMATION.InputBufferLength = InformationBufferLength; ndisOidRequest->DATA.METHOD_INFORMATION.OutputBufferLength = OutputBufferLength; break; default: NT_ASSERT(FALSE); break; } ndisOidRequest->RequestId = (PVOID)SxExtOidRequestId; status = NdisFOidRequest(Switch->NdisFilterHandle, ndisOidRequest); if (status == NDIS_STATUS_PENDING) { asyncCompletion = TRUE; NdisWaitEvent(&oidRequest->ReqEvent, 0); } else { SxpNdisCompleteInternalOidRequest(Switch, ndisOidRequest, status); } bytesNeeded = oidRequest->BytesNeeded; status = oidRequest->Status; Cleanup: if (BytesNeeded != NULL) { *BytesNeeded = bytesNeeded; } if (!asyncCompletion) { NdisInterlockedDecrement(&Switch->PendingOidCount); } if (oidRequest != NULL) { ExFreePoolWithTag(oidRequest, SxExtAllocationTag); } return status; }
NTSTATUS InterruptPipeCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) /*++ Routine Description: Completion routine for the read request. This routine indicates the received packet from the WDM driver to NDIS. This routine also handles the case where another thread has canceled the read request. Arguments: DeviceObject - not used. Should be NULL Irp - Pointer to our read IRP Context - pointer to our adapter context structure Return Value: STATUS_MORE_PROCESSING_REQUIRED - because this is an asynchronouse IRP and we want to reuse it. --*/ { PNOTICB pNotiCB = (PNOTICB)Context; PMP_ADAPTER Adapter = pNotiCB->Adapter; ULONG bytesRead = 0; UNREFERENCED_PARAMETER(DeviceObject); DEBUGP(MP_TRACE, ("--> InterruptPipeCompletion\n")); if(!NT_SUCCESS(Irp->IoStatus.Status)) { Adapter->nReadsCompletedWithError++; DEBUGP (MP_LOUD, ("Read request failed %x\n", Irp->IoStatus.Status)); // // Clear the flag to prevent any more reads from being // posted to the target device. // MP_CLEAR_FLAG(Adapter, fMP_POST_INTERRUPT); } else { bytesRead = (ULONG)pNotiCB->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength; DEBUGP (MP_VERY_LOUD, ("Read %d bytes\n", bytesRead)); pNotiCB->ulSize=bytesRead; } if (InterlockedExchange((PVOID)&pNotiCB->IrpLock, IRPLOCK_COMPLETED) == IRPLOCK_CANCEL_STARTED) { // // NICFreeBusyRecvPackets has got the control of the IRP. It will // now take the responsibility of freeing the IRP. // Therefore... return STATUS_MORE_PROCESSING_REQUIRED; } if (NT_SUCCESS(Irp->IoStatus.Status)) { cdc_ncm_status(Adapter,pNotiCB->pData,pNotiCB->ulSize); } if(NdisInterlockedDecrement(&pNotiCB->Ref) == 0) { NICFreeNotify(pNotiCB); } DEBUGP(MP_TRACE, ("<-- InterruptPipeCompletion\n")); return STATUS_MORE_PROCESSING_REQUIRED; }
VOID NICFreeRCB( IN PRCB pRCB) /*++ Routine Description: pRCB - pointer to RCB block Arguments: This routine reinitializes the RCB block and puts it back into the RecvFreeList for reuse. Return Value: VOID --*/ { PMP_ADAPTER Adapter = pRCB->Adapter; ULONG ulSendLowW= NIC_SEND_LOW_WATERMARK; DEBUGP(MP_TRACE, ("--> NICFreeRCB %p\n", pRCB)); ASSERT(pRCB->Irp); // shouldn't be NULL ASSERT(!pRCB->Ref); // should be 0 ASSERT(pRCB->Adapter); // shouldn't be NULL IoReuseIrp(pRCB->Irp, STATUS_SUCCESS); pRCB->nextndeoffset=0; pRCB->nextndpoffset=0; pRCB->bIsOver=FALSE; pRCB->ulSize=0; // // Set the MDL field to NULL so that we don't end up double freeing the // MDL in our call to IoFreeIrp. // pRCB->Irp->MdlAddress = NULL; // // Re adjust the length to the originl size // //NdisAdjustBufferLength(pRCB->BufferArray[0], pRCB->ulBufferSize); // // Insert the RCB back in the Recv free list // NdisAcquireSpinLock(&Adapter->RecvLock); RemoveEntryList(&pRCB->List); InsertTailList(&Adapter->RecvFreeList, &pRCB->List); NdisInterlockedDecrement(&Adapter->nBusyRecv); ASSERT(Adapter->nBusyRecv >= 0); NdisReleaseSpinLock(&Adapter->RecvLock); // // For performance, instead of scheduling a workitem at the end of // every read completion, we will do it only when the number of // outstanding IRPs goes below NIC_SEND_LOW_WATERMARK. // We shouldn't queue a workitem if it's already scheduled and waiting in // the system workitem queue to be fired. // if((!ulSendLowW || Adapter->nBusyRecv <= NIC_SEND_LOW_WATERMARK) && MP_TEST_FLAG(Adapter, fMP_POST_READS) && (InterlockedExchange(&Adapter->IsReadWorkItemQueued, TRUE) == FALSE)) { Adapter->nReadWorkItemScheduled++; MP_INC_REF(Adapter); NdisScheduleWorkItem(&Adapter->ReadWorkItem); } DEBUGP(MP_TRACE, ("<-- NICFreeRCB %d\n", Adapter->nBusyRecv)); }
// // FilterOidRequest Function // http://msdn.microsoft.com/en-us/library/ff549954(v=VS.85).aspx // _Use_decl_annotations_ NDIS_STATUS SxNdisOidRequest( NDIS_HANDLE FilterModuleContext, PNDIS_OID_REQUEST OidRequest ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; NDIS_STATUS status; PNDIS_OID_REQUEST clonedRequest=NULL; PVOID *cloneRequestContext; BOOLEAN completeOid = FALSE; ULONG bytesNeeded = 0; status = NDIS_STATUS_SUCCESS; DEBUGP(DL_TRACE, ("===>SxOidRequest: OidRequest %p.\n", OidRequest)); NdisInterlockedIncrement(&switchObject->PendingOidCount); status = NdisAllocateCloneOidRequest(switchObject->NdisFilterHandle, OidRequest, SxExtAllocationTag, &clonedRequest); if (status != NDIS_STATUS_SUCCESS) { DEBUGP(DL_WARN, ("FilerOidRequest: Cannot Clone OidRequest\n")); goto Cleanup; } cloneRequestContext = (PVOID*)(&clonedRequest->SourceReserved[0]); *cloneRequestContext = OidRequest; switch (clonedRequest->RequestType) { case NdisRequestSetInformation: status = SxpNdisProcessSetOid(switchObject, clonedRequest, &completeOid); break; case NdisRequestMethod: status = SxpNdisProcessMethodOid(switchObject, clonedRequest, &completeOid, &bytesNeeded); break; } if (completeOid) { NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, clonedRequest); OidRequest->DATA.METHOD_INFORMATION.BytesNeeded = bytesNeeded; NdisInterlockedDecrement(&switchObject->PendingOidCount); goto Cleanup; } status = NdisFOidRequest(switchObject->NdisFilterHandle, clonedRequest); if (status != NDIS_STATUS_PENDING) { SxNdisOidRequestComplete(switchObject, clonedRequest, status); // // We must still return status as pending because we complete the // request using NdisFOidRequestComplete() in SxOidRequestComplete(). // status = NDIS_STATUS_PENDING; } Cleanup: DEBUGP(DL_TRACE, ("<===SxOidRequest: status %8x.\n", status)); return status; }
NTSTATUS NICReadRequestCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) /*++ Routine Description: Completion routine for the read request. This routine indicates the received packet from the WDM driver to NDIS. This routine also handles the case where another thread has canceled the read request. Arguments: DeviceObject - not used. Should be NULL Irp - Pointer to our read IRP Context - pointer to our adapter context structure Return Value: STATUS_MORE_PROCESSING_REQUIRED - because this is an asynchronouse IRP and we want to reuse it. --*/ { PRCB pRCB = (PRCB)Context; PMP_ADAPTER Adapter = pRCB->Adapter; ULONG bytesRead = 0; BOOLEAN bIndicateReceive = FALSE; BOOLEAN datagramsover=TRUE; UNREFERENCED_PARAMETER(DeviceObject); DEBUGP(MP_TRACE, ("--> NICReadRequestCompletion\n")); if(!NT_SUCCESS(Irp->IoStatus.Status)) { Adapter->nReadsCompletedWithError++; DEBUGP (MP_LOUD, ("Read request failed %x\n", Irp->IoStatus.Status)); // // Clear the flag to prevent any more reads from being // posted to the target device. // MP_CLEAR_FLAG(Adapter, fMP_POST_READS); } else { bytesRead = (ULONG)pRCB->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength; DEBUGP (MP_VERY_LOUD, ("Read %d bytes\n", bytesRead)); Adapter->nBytesRead += bytesRead; pRCB->ulSize=bytesRead; pRCB->nextndeoffset=pRCB->nextndpoffset=0; pRCB->bIsOver=FALSE; bIndicateReceive = TRUE; } if (InterlockedExchange((PVOID)&pRCB->IrpLock, IRPLOCK_COMPLETED) == IRPLOCK_CANCEL_STARTED) { // // NICFreeBusyRecvPackets has got the control of the IRP. It will // now take the responsibility of freeing the IRP. // Therefore... return STATUS_MORE_PROCESSING_REQUIRED; } ncmdivi: if(bIndicateReceive) { datagramsover=cdc_ncm_rx_fixup(Adapter,pRCB); } if(NdisInterlockedDecrement(&pRCB->Ref) == 0) { if(FALSE==datagramsover) { pRCB->Ref=1; goto ncmdivi; } NICFreeRCB(pRCB); } return STATUS_MORE_PROCESSING_REQUIRED; }
VOID NdisProtSendComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pNdisPacket, IN NDIS_STATUS Status ) /*++ Routine Description: NDIS entry point called to signify completion of a packet send. We pick up and complete the Write IRP corresponding to this packet. NDIS 5.1: Arguments: ProtocolBindingContext - pointer to open context pNdisPacket - packet that completed send Status - status of send Return Value: None --*/ { PIRP pIrp; PIO_STACK_LOCATION pIrpSp; PNDISPROT_OPEN_CONTEXT pOpenContext; pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext; NPROT_STRUCT_ASSERT(pOpenContext, oc); pIrp = NPROT_IRP_FROM_SEND_PKT(pNdisPacket); if (pOpenContext->bRunningOnWin9x) { // // We would have attached our own NDIS_BUFFER. Take it out // and free it. // #ifndef NDIS51 PNDIS_BUFFER pNdisBuffer; PVOID VirtualAddr; UINT BufferLength; UINT TotalLength; #endif #ifdef NDIS51 NPROT_ASSERT(FALSE); // NDIS 5.1 not on Win9X! #else NdisGetFirstBufferFromPacket( pNdisPacket, &pNdisBuffer, &VirtualAddr, &BufferLength, &TotalLength); NPROT_ASSERT(pNdisBuffer != NULL); NdisFreeBuffer(pNdisBuffer); #endif } #ifdef NDIS51 IoSetCancelRoutine(pIrp, NULL); NPROT_ACQUIRE_LOCK(&pOpenContext->Lock); NPROT_REMOVE_ENTRY_LIST(&pIrp->Tail.Overlay.ListEntry); NPROT_RELEASE_LOCK(&pOpenContext->Lock); #endif // // We are done with the NDIS_PACKET: // NPROT_DEREF_SEND_PKT(pNdisPacket); // // Complete the Write IRP with the right status. // pIrpSp = IoGetCurrentIrpStackLocation(pIrp); if (Status == NDIS_STATUS_SUCCESS) { pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length; pIrp->IoStatus.Status = STATUS_SUCCESS; } else { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; } DEBUGP(DL_INFO, ("SendComplete: packet %p/IRP %p/Length %d " "completed with status %x\n", pNdisPacket, pIrp, pIrp->IoStatus.Information, pIrp->IoStatus.Status)); IoCompleteRequest(pIrp, IO_NO_INCREMENT); NdisInterlockedDecrement((PLONG)&pOpenContext->PendedSendCount); NPROT_DEREF_OPEN(pOpenContext); // send complete - dequeued send IRP }
VOID NICFreeBusyRecvPackets( PMP_ADAPTER Adapter ) /*++ Routine Description: This function tries to cancel all the outstanding read IRP if it is not already completed and frees the RCB block. This routine is called only by the Halt handler. Arguments: Adapter - pointer to the MP_ADAPTER structure Return value: VOID --*/ { PLIST_ENTRY pEntry = NULL; PRCB pRCB = NULL; DEBUGP(MP_TRACE, ("--> NICFreeBusyRecvPackets\n")); if(!MP_TEST_FLAG(Adapter, fMP_RECV_SIDE_RESOURCE_ALLOCATED)){ return; } NdisAcquireSpinLock(&Adapter->RecvLock); while(!IsListEmpty(&Adapter->RecvBusyList)) { pEntry = (PLIST_ENTRY)RemoveHeadList(&Adapter->RecvBusyList); pRCB = CONTAINING_RECORD(pEntry, RCB, List); NdisInitializeListHead(&pRCB->List); NdisReleaseSpinLock(&Adapter->RecvLock); if (InterlockedExchange((PVOID)&pRCB->IrpLock, IRPLOCK_CANCEL_STARTED) == IRPLOCK_CANCELABLE) { // // We got it to the IRP before it was completed. We can cancel // the IRP without fear of losing it, as the completion routine // will not let go of the IRP until we say so. // IoCancelIrp(pRCB->Irp); // // Release the completion routine. If it already got there, // then we need to free it ourself. Otherwise, we got // through IoCancelIrp before the IRP completed entirely. // if (InterlockedExchange((PVOID)&pRCB->IrpLock, IRPLOCK_CANCEL_COMPLETE) == IRPLOCK_COMPLETED) { if(NdisInterlockedDecrement(&pRCB->Ref) == 0) { NICFreeRCB(pRCB); } else { ASSERTMSG("Only we have the right to free RCB\n", FALSE); } } } NdisAcquireSpinLock(&Adapter->RecvLock); } NdisReleaseSpinLock(&Adapter->RecvLock); DEBUGP(MP_TRACE, ("<-- NICFreeBusyRecvPackets\n")); return ; }