Пример #1
0
NDIS_STATUS
VNicStopBSSHelper(
    _In_  PVNIC                   pVNic
    )
{
    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;

    ASSERT(VNicIsLocked(pVNic));
    ASSERT(VNicIsActive(pVNic) && !VNicIsInReset(pVNic));

    do
    {                
        /*
            We call the hardware for starting the BSS. We need to give up our lock before
            calling the hardware. The context switch ref count will be decremented when we
            have completed the call
            */
        // add the context switch ref count 
        VNicAddCtxSRef(pVNic, REF_STOP_BSS);

        _Analysis_assume_lock_held_(pVNic->Lock.SpinLock);
        VNicUnlock(pVNic);
        Hw11StopBSS(pVNic->pvHwContext);
        VNicLock(pVNic);

        MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Called the hardware for stopping a BSS 0x%x\n", VNIC_PORT_NO, ndisStatus));
        
        VNicRemoveCtxSRef(pVNic, REF_STOP_BSS);
    } while (FALSE);

    return ndisStatus;
}
Пример #2
0
VOID
VNicCancelPendingSends(
    _In_  PVNIC                   pVNic
    )
{
    PMP_TX_MSDU   pendingPackets = NULL;

    ASSERT(VNicIsLocked(pVNic));
    
    do
    {
        if (!PktQueueIsEmpty(&pVNic->TxQueue))
        {
            MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Cancelling %d sends\n", VNIC_PORT_NO, PktQueueDepth(&pVNic->TxQueue)));
            
            pendingPackets = DeQueuePktList(&pVNic->TxQueue);

            _Analysis_assume_lock_held_(pVNic->Lock.SpinLock);

            // give up lock before calling into the port
            VNicUnlock(pVNic);            
            Port11SendCompletePackets(pVNic->pvPort, pendingPackets, 0);
            VNicLock(pVNic);
        }
        else
        {
            MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): No sends are pending. Nothing to cancel\n", VNIC_PORT_NO));
        }
    } while (FALSE);    
}
Пример #3
0
NDIS_STATUS 
VNicJoinComplete(
    _In_ PVNIC pVNic,
    _In_ BOOLEAN fReferenced,
    _In_ PORT11_GENERIC_CALLBACK_FUNC JoinCompleteHandler,
    _In_ PVOID Data
    )
{
    PVOID pvPort = NULL;
    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;

    MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Completing the Join operation \n", VNIC_PORT_NO));

    pvPort = pVNic->pvPort;

    // remove the ref count that was added for the join operation
    if (fReferenced)
    {
        VNicRemoveCtxSRef(pVNic, REF_JOIN);
    }

    // give up lock before calling into the port
    _Analysis_assume_lock_held_(pVNic->Lock.SpinLock);
    VNicUnlock(pVNic);

    // Call the completion handler in the port
    if (JoinCompleteHandler)
    {
        ndisStatus = JoinCompleteHandler(pvPort, Data);
    }

    VNicLock(pVNic);

    return ndisStatus;
}
Пример #4
0
NDIS_STATUS
VNicJoinBSSHelper(
    _In_  PVNIC                   pVNic,
    _In_  PMP_BSS_DESCRIPTION     BSSDescription,
    _In_  ULONG                   JoinFailureTimeout,
    _In_  PVNIC_COMPLETION_CTX    pCtx
    )
{
    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
    BOOLEAN fReferenced = FALSE;

    ASSERT(VNicIsLocked(pVNic));
    ASSERT(VNicIsActive(pVNic) && !VNicIsInReset(pVNic));

    do
    {
        /*
            We can call the hardware for a join. We need to give up our lock before
            calling the hardware. The context switch ref count will be decremented when we
            have completed the join
            */

        // add the context switch ref count for the async join call to the hardware
        VNicAddCtxSRef(pVNic, REF_JOIN);
        fReferenced = TRUE;

        _Analysis_assume_lock_held_(pVNic->Lock.SpinLock);
        VNicUnlock(pVNic);
        
        ndisStatus = Hw11JoinBSS(
                        pVNic->pvHwContext, 
                        BSSDescription, 
                        JoinFailureTimeout, 
                        VNic11JoinCompleteCallback,
                        pCtx
                        );

        MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Called the hardware for the Join operation 0x%x\n", VNIC_PORT_NO, ndisStatus));
        
        VNicLock(pVNic);

    } while (FALSE);

    if (NDIS_STATUS_PENDING != ndisStatus)
    {
        // the call to the hardware completed. Remove the join ref count we added
        if (fReferenced)
        {
            VNicRemoveCtxSRef(pVNic, REF_JOIN);
        }
    }    
       
    return ndisStatus;
}
Пример #5
0
VOID
HvlNotifyAllVNics(
    PHVL pHvl,
    PVOID pvNotif
    )
{
    LIST_ENTRY *pEntryVNic = NULL;
    PVNIC pVNic = NULL;
    PNOTIFICATION_DATA_HEADER pHdr = NULL;

    ASSERT(HvlIsLocked(pHvl));

    pHdr = (PNOTIFICATION_DATA_HEADER)pvNotif;
    
    pEntryVNic = pHvl->VNiclist.Flink;
    while (pEntryVNic != &pHvl->VNiclist)
    {
        pVNic = CONTAINING_RECORD(pEntryVNic, VNIC, VNicLink);

        // do not notify if this VNIC is the source of the notification
        if (pVNic != pHdr->pSourceVNic)
        {
            _Analysis_assume_lock_held_(pHvl->Lock.SpinLock);

            HvlUnlock(pHvl);
            VNic11Notify(pVNic, pvNotif);
            HvlLock(pHvl);
        }
        
        pEntryVNic = pEntryVNic->Flink;
    }

    // Also send the notification to the helper port
    pEntryVNic = pHvl->pHelperPortCtx->VNicList.Flink;
    pVNic = CONTAINING_RECORD(pEntryVNic, VNIC, CtxLink);

    _Analysis_assume_lock_held_(pHvl->Lock.SpinLock);
    HvlUnlock(pHvl);
    VNic11Notify(pVNic, pvNotif);
    HvlLock(pHvl);
}
Пример #6
0
/*
    This function releases the lock during its processing
    */
VOID
VNicProcessQueuedPkts(
    _In_ PVNIC pVNic, 
    BOOLEAN fDispatchLevel
    )
{
    ULONG                   ulNumPkts = 0;
    PMP_TX_MSDU             PacketList = NULL;
    BOOLEAN fFailSends = FALSE;
    
    ASSERT(VNicIsLocked(pVNic));
    ASSERT(VNicIsActive(pVNic));
    ASSERT(!PktQueueIsEmpty(&pVNic->TxQueue));

    do
    {
        if (VNicIsInReset(pVNic))
        {
            fFailSends = TRUE;
            ulNumPkts = PktQueueDepth(&pVNic->TxQueue);
            PacketList = DeQueuePktList(&pVNic->TxQueue);
            MpTrace(COMP_HVL, DBG_NORMAL, ("VNIC(%d) is in reset. Failing %d sends. \n", VNIC_PORT_NO, ulNumPkts));
            break;
        }        

        if (Hw11CanTransmit(pVNic->pvHwContext))
        {
            ulNumPkts = PktQueueDepth(&pVNic->TxQueue);
            PacketList = DeQueuePktList(&pVNic->TxQueue);
            
            MpTrace(COMP_HVL, DBG_NORMAL, ("VNIC(%d): Processing %d queued packets \n", VNIC_PORT_NO, ulNumPkts));

            VNicSendPktsToHw(pVNic, ulNumPkts, PacketList, 0);
        }
        else
        {
            MpTrace(COMP_HVL, DBG_NORMAL, ("VNIC(%d): The hardware is not yet ready to accept packets\n", VNIC_PORT_NO));
        }
    } while (FALSE);

    if (fFailSends)
    {
        _Analysis_assume_lock_held_((& pVNic->Lock)->SpinLock);

        VNicUnlockAtDispatch(pVNic, fDispatchLevel);
        Port11SendCompletePackets(pVNic->pvPort, PacketList, 0);
        VNicLockAtDispatch(pVNic, fDispatchLevel);
    }    
    
    return;
}
Пример #7
0
/*
    NOTE
    This packet gives up the VNIC lock before calling into the hardware. The VNIC state might get
    changed during the course of the call
    */
VOID
VNicSendPktsToHw(    
    _In_ PVNIC                   pVNic,
    _In_ ULONG                   ulNumPkts,
    _In_ PMP_TX_MSDU             PacketList,
    _In_ ULONG                   SendFlags
    )
{
    BOOLEAN fDispatchLevel = SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL ? TRUE : FALSE;
    PMP_TX_MSDU currentPacket = NULL;
    ULONG myCount = 0;

    currentPacket = PacketList;
    while (currentPacket != NULL)
    {
        myCount++;
        currentPacket = MP_TX_MSDU_NEXT_MSDU(currentPacket);
    }
    MPASSERT(myCount == ulNumPkts);

    ASSERT(VNicIsLocked(pVNic));
    ASSERT(VNicIsActive(pVNic));
    
    MpTrace(COMP_HVL, DBG_LOUD, ("VNic(%d): Sending %d packets to the hardware \n", VNIC_PORT_NO, ulNumPkts));

    /*
        We can call the hardware for sending packets. We need to increment the context 
        switch ref count to avoid becoming inactive. The context switch ref count will be 
        decremented when we receive the send completionAlso we need to give up our lock 
        before calling the hardware. 
        */
    VNicIncCtxSRef(pVNic, ulNumPkts, REF_SEND_PKTS);

    // we also need to keep track of the sends outstanding to the hardware
    VNicIncOutstandingSends(pVNic, ulNumPkts);
    
    _Analysis_assume_lock_held_((& pVNic->Lock)->SpinLock);
    VNicUnlockAtDispatch(pVNic, fDispatchLevel);
    
    Hw11SendPackets(pVNic->pvHwContext, PacketList, SendFlags);

    VNicLockAtDispatch(pVNic, fDispatchLevel);
}
Пример #8
0
VOID
HvlNotifyAllVNicsInContext(
    PHVL            pHvl,
    PHVL_CONTEXT    pCtx,
    PVNIC_FUNCTION  pVnicFn,
    ULONG           ulFlags
    )
{
    LIST_ENTRY *pEntryVNic = NULL;
    PVNIC pVNic = NULL;

    _Analysis_assume_lock_held_(pHvl->Lock.SpinLock);

    HvlUnlock(pHvl);
    
    pEntryVNic = pCtx->VNicList.Flink;
    while (pEntryVNic != &pCtx->VNicList)
    {
        pVNic = CONTAINING_RECORD(pEntryVNic, VNIC, CtxLink);
        pVnicFn(pVNic, ulFlags);
        pEntryVNic = pEntryVNic->Flink;
    }
    HvlLock(pHvl);
}
Пример #9
0
VOID
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
CdOplockComplete (
    _Inout_ PIRP_CONTEXT IrpContext,
    _Inout_ PIRP Irp
    )

/*++

Routine Description:

    This routine is called by the oplock package when an oplock break has
    completed, allowing an Irp to resume execution.  If the status in
    the Irp is STATUS_SUCCESS, then we queue the Irp to the Fsp queue.
    Otherwise we complete the Irp with the status in the Irp.

    If we are completing due to an error then check if there is any
    cleanup to do.

Arguments:

    Irp - I/O Request Packet.

Return Value:

    None.

--*/

{
    BOOLEAN RemovedFcb;

    PAGED_CODE();

    //
    //  Check on the return value in the Irp.  If success then we
    //  are to post this request.
    //

    if (Irp->IoStatus.Status == STATUS_SUCCESS) {

        //
        //  Check if there is any cleanup work to do.
        //

        switch (IrpContext->MajorFunction) {

        case IRP_MJ_CREATE :

            //
            //  If called from the oplock package then there is an
            //  Fcb to possibly teardown.  We will call the teardown
            //  routine and release the Fcb if still present.  The cleanup
            //  code in create will know not to release this Fcb because
            //  we will clear the pointer.
            //

            if (IrpContext->TeardownFcb != NULL) {

                CdTeardownStructures( IrpContext, *(IrpContext->TeardownFcb), &RemovedFcb );

                if (!RemovedFcb) {

                    _Analysis_assume_lock_held_((*IrpContext->TeardownFcb)->FcbNonpaged->FcbResource);
                    CdReleaseFcb( IrpContext, *(IrpContext->TeardownFcb) );
                }

                *(IrpContext->TeardownFcb) = NULL;
                IrpContext->TeardownFcb = NULL;
            }

            break;
        }

        //
        //  Insert the Irp context in the workqueue.
        //

        CdAddToWorkque( IrpContext, Irp );

    //
    //  Otherwise complete the request.
    //

    } else {

        CdCompleteRequest( IrpContext, Irp, Irp->IoStatus.Status );
    }

    return;
}
Пример #10
0
VOID
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
CdPrePostIrp (
    _Inout_ PIRP_CONTEXT IrpContext,
    _Inout_ PIRP Irp
    )

/*++

Routine Description:

    This routine performs any neccessary work before STATUS_PENDING is
    returned with the Fsd thread.  This routine is called within the
    filesystem and by the oplock package.

Arguments:

    Context - Pointer to the IrpContext to be queued to the Fsp

    Irp - I/O Request Packet.

Return Value:

    None.

--*/

{
    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    BOOLEAN RemovedFcb;

    PAGED_CODE();

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    //
    //  Case on the type of the operation.
    //

    switch (IrpContext->MajorFunction) {

    case IRP_MJ_CREATE :

        //
        //  If called from the oplock package then there is an
        //  Fcb to possibly teardown.  We will call the teardown
        //  routine and release the Fcb if still present.  The cleanup
        //  code in create will know not to release this Fcb because
        //  we will clear the pointer.
        //

        if ((IrpContext->TeardownFcb != NULL) &&
            *(IrpContext->TeardownFcb) != NULL) {

            CdTeardownStructures( IrpContext, *(IrpContext->TeardownFcb), &RemovedFcb );

            if (!RemovedFcb) {

                _Analysis_assume_lock_held_((*IrpContext->TeardownFcb)->FcbNonpaged->FcbResource);
                CdReleaseFcb( IrpContext, *(IrpContext->TeardownFcb) );
            }

            *(IrpContext->TeardownFcb) = NULL;
            IrpContext->TeardownFcb = NULL;
        }

        break;

    //
    //  We need to lock the user's buffer, unless this is an MDL read/write,
    //  in which case there is no user buffer.
    //

    case IRP_MJ_READ :

        if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL )) {

            CdLockUserBuffer( IrpContext, IrpSp->Parameters.Read.Length, IoWriteAccess );
        }

        break;

    case IRP_MJ_WRITE :

        if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL )) {

            CdLockUserBuffer( IrpContext, IrpSp->Parameters.Read.Length, IoReadAccess );
        }

        break;

    //
    //  We also need to check whether this is a query file operation.
    //

    case IRP_MJ_DIRECTORY_CONTROL :

        if (IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) {

            CdLockUserBuffer( IrpContext, IrpSp->Parameters.QueryDirectory.Length, IoWriteAccess );
        }

        break;
    }

    //
    //  Cleanup the IrpContext for the post.
    //

    SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
    CdCleanupIrpContext( IrpContext, TRUE );

    //
    //  Mark the Irp to show that we've already returned pending to the user.
    //

    IoMarkIrpPending( Irp );

    return;
}