示例#1
0
文件: tcbrcb.c 项目: kcrazy/winekit
VOID
ReturnTCB(
    __in  PMP_ADAPTER  Adapter,
    __in  PTCB         Tcb)
{
    TXNblRelease(Adapter, NBL_FROM_SEND_NB(Tcb->NetBuffer), TRUE);
    Tcb->NetBuffer = NULL;

    NdisInterlockedInsertTailList(
            &Adapter->FreeTcbList,
            &Tcb->TcbLink,
            &Adapter->FreeTcbListLock);
}
示例#2
0
VOID
MPSendNetBufferLists(
    _In_  NDIS_HANDLE             MiniportAdapterContext,
    _In_  PNET_BUFFER_LIST        NetBufferLists,
    _In_  NDIS_PORT_NUMBER        PortNumber,
    _In_  ULONG                   SendFlags)
/*++

Routine Description:

    Send Packet Array handler. Called by NDIS whenever a protocol
    bound to our miniport sends one or more packets.

    The input packet descriptor pointers have been ordered according
    to the order in which the packets should be sent over the network
    by the protocol driver that set up the packet array. The NDIS
    library preserves the protocol-determined ordering when it submits
    each packet array to MiniportSendPackets

    As a deserialized driver, we are responsible for holding incoming send
    packets in our internal queue until they can be transmitted over the
    network and for preserving the protocol-determined ordering of packet
    descriptors incoming to its MiniportSendPackets function.
    A deserialized miniport driver must complete each incoming send packet
    with NdisMSendComplete, and it cannot call NdisMSendResourcesAvailable.

    Runs at IRQL <= DISPATCH_LEVEL

Arguments:

    MiniportAdapterContext      Pointer to our adapter
    NetBufferLists              Head of a list of NBLs to send
    PortNumber                  A miniport adapter port.  Default is 0.
    SendFlags                   Additional flags for the send operation

Return Value:

    None.  Write status directly into each NBL with the NET_BUFFER_LIST_STATUS
    macro.

--*/
{
    PMP_ADAPTER       Adapter = MP_ADAPTER_FROM_CONTEXT(MiniportAdapterContext);
    PNET_BUFFER_LIST  Nbl;
    PNET_BUFFER_LIST  NextNbl = NULL;
    BOOLEAN           fAtDispatch = (SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL) ? TRUE:FALSE;
    NDIS_STATUS       Status;
    ULONG             NumNbls=0;

    DEBUGP(MP_TRACE, "[%p] ---> MPSendNetBufferLists\n", Adapter);

    UNREFERENCED_PARAMETER(PortNumber);
    UNREFERENCED_PARAMETER(SendFlags);
    ASSERT(PortNumber == 0); // Only the default port is supported


    //
    // Each NET_BUFFER_LIST has a list of NET_BUFFERs.
    // Loop over all the NET_BUFFER_LISTs, sending each NET_BUFFER.
    //
    for (
        Nbl = NetBufferLists;
        Nbl!= NULL;
        Nbl = NextNbl, ++NumNbls)
    {
        PNET_BUFFER NetBuffer;

        NextNbl = NET_BUFFER_LIST_NEXT_NBL(Nbl);

        //
        // Unlink the NBL and prepare our bookkeeping.
        //
        // We use a reference count to make sure that we don't send complete
        // the NBL until we're done reading each NB on the NBL.
        //
        NET_BUFFER_LIST_NEXT_NBL(Nbl) = NULL;
        SEND_REF_FROM_NBL(Nbl) = 0;

        Status = TXNblReference(Adapter, Nbl);

        if(Status == NDIS_STATUS_SUCCESS)
        {
            NET_BUFFER_LIST_STATUS(Nbl) = NDIS_STATUS_SUCCESS;

            //
            // Queue each NB for transmission.
            //
            for (
                NetBuffer = NET_BUFFER_LIST_FIRST_NB(Nbl);
                NetBuffer != NULL;
                NetBuffer = NET_BUFFER_NEXT_NB(NetBuffer))
            {
                NBL_FROM_SEND_NB(NetBuffer) = Nbl;
                TXQueueNetBufferForSend(Adapter, NetBuffer);
            }

            TXNblRelease(Adapter, Nbl, fAtDispatch);
        }
        else
        {
            //
            // We can't send this NBL now.  Indicate failure.
            //
            if (MP_TEST_FLAG(Adapter, fMP_RESET_IN_PROGRESS))
            {
                NET_BUFFER_LIST_STATUS(Nbl) = NDIS_STATUS_RESET_IN_PROGRESS;
            }
            else if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_PAUSE_IN_PROGRESS|fMP_ADAPTER_PAUSED))
            {
                NET_BUFFER_LIST_STATUS(Nbl) = NDIS_STATUS_PAUSED;
            }
            else if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_LOW_POWER))
            {
                NET_BUFFER_LIST_STATUS(Nbl) = NDIS_STATUS_LOW_POWER_STATE;
            }
            else
            {
                NET_BUFFER_LIST_STATUS(Nbl) = Status;
            }

            NdisMSendNetBufferListsComplete(
                    Adapter->AdapterHandle,
                    Nbl,
                    fAtDispatch ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL:0);

            continue;
        }
    }

    DEBUGP(MP_TRACE, "[%p] %i NBLs processed.\n", Adapter, NumNbls);

    //
    // Now actually go send each of the queued NBs.
    //
    TXTransmitQueuedSends(Adapter, fAtDispatch);

    DEBUGP(MP_TRACE, "[%p] <--- MPSendNetBufferLists\n", Adapter);
}
示例#3
0
VOID
TXFlushSendQueue(
    _In_  PMP_ADAPTER  Adapter,
    _In_  NDIS_STATUS  CompleteStatus)
/*++

Routine Description:

    This routine is called by the Halt or Reset handler to fail all
    the queued up Send NBLs because the device is either gone, being
    stopped for resource rebalance, or reset.

Arguments:

    Adapter                     Pointer to our adapter
    CompleteStatus              The status code with which to complete each NBL

Return Value:

    None.

--*/
{
    PTCB Tcb;

    DEBUGP(MP_TRACE, "[%p] ---> TXFlushSendQueue Status = 0x%08x\n", Adapter, CompleteStatus);


    //
    // First, free anything queued in the driver.
    //

    while (TRUE)
    {
        PLIST_ENTRY pEntry;
        PNET_BUFFER NetBuffer;
        PNET_BUFFER_LIST NetBufferList;

        pEntry = NdisInterlockedRemoveHeadList(
                &Adapter->SendWaitList,
                &Adapter->SendWaitListLock);

        if (!pEntry)
        {
            // End of list -- nothing left to free.
            break;
        }

        NetBuffer = NB_FROM_SEND_WAIT_LIST(pEntry);
        NetBufferList = NBL_FROM_SEND_NB(NetBuffer);

        DEBUGP(MP_TRACE, "[%p] Dropping Send NB: 0x%p.\n", Adapter, NetBuffer);

        NET_BUFFER_LIST_STATUS(NetBufferList) = CompleteStatus;
        TXNblRelease(Adapter, NetBufferList, FALSE);
    }


    //
    // Next, cancel anything queued in the hardware.
    //

    while (NULL != (Tcb = TXGetNextTcbToSend(Adapter)))
    {
        NET_BUFFER_LIST_STATUS(NBL_FROM_SEND_NB(Tcb->NetBuffer)) = CompleteStatus;
        ReturnTCB(Adapter, Tcb);
    }


    DEBUGP(MP_TRACE, "[%p] <--- TXFlushSendQueue\n", Adapter);
}