Example #1
0
/*
 * --------------------------------------------------------------------------
 * 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;
        }
    }
}
Example #3
0
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"));
}
Example #6
0
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(&currentTime);

      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)));
  }
}
Example #7
0
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;
}
Example #8
0
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);
    }
}
Example #9
0
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"));
}
Example #10
0
/**************************************************************************
 * 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;
}
Example #11
0
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));
    
}
Example #13
0
/*
 * --------------------------------------------------------------------------
 * 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;
}
Example #14
0
//
// 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);
}
Example #15
0
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;
}
Example #16
0
// 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;
Example #17
0
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;
Example #18
0
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);
}
Example #19
0
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));
    
}
Example #22
0
//
// 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;
}
Example #24
0
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 ;
}