Exemple #1
0
VOID
NICFreeBusySendPackets(
    IN  PFDO_DATA  FdoData
    )
/*++
Routine Description:

    Free and complete the stopped active sends

    Assumption: This function is called with the Send SPINLOCK held.

Arguments:

    FdoData     Pointer to our FdoData

Return Value:

     None

--*/
{
    PMP_TCB  pMpTcb;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,
                "--> NICFreeBusySendPackets\n");

    //
    // Any packets being sent? Check the first TCB on the send list
    //
    while (FdoData->nBusySend > 0)
    {
        pMpTcb = FdoData->CurrSendHead;

        //
        // Is this TCB completed?
        //
        if ((pMpTcb->HwTcb->TxCbHeader.CbCommand & CB_CMD_MASK) != CB_MULTICAST)
        {
            MP_FREE_SEND_PACKET(FdoData, pMpTcb, STATUS_SUCCESS);
        }
        else
        {
            break;
        }
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,
                "<-- NICFreeBusySendPackets\n");
}
Exemple #2
0
VOID
NICFreeBusySendPackets(
    __in  PFDO_DATA  FdoData
    )
/*++
Routine Description:

    Free and complete the stopped active sends
    Assumption: Send spinlock has been acquired

Arguments:

    FdoData     Pointer to our FdoData

Return Value:

     None

--*/
{
    PMP_TCB     pMpTcb;
    NTSTATUS    status = MP_GET_STATUS_FROM_FLAGS(FdoData);

    DebugPrint(TRACE, DBG_WRITE, "--> NICFreeBusySendPackets\n");

    //
    // Any packets being sent? Check the first TCB on the send list
    //
    while (FdoData->nBusySend > 0)
    {
        pMpTcb = FdoData->CurrSendHead;

        //
        // Is this TCB completed?
        //
        if ((pMpTcb->HwTcb->TxCbHeader.CbCommand & CB_CMD_MASK) != CB_MULTICAST)
        {
            MP_FREE_SEND_PACKET(FdoData, pMpTcb, status);
        }
        else
        {
            break;
        }
    }

    DebugPrint(TRACE, DBG_WRITE, "<-- NICFreeBusySendPackets\n");
}
Exemple #3
0
NTSTATUS
NICHandleSendInterrupt(
    IN  PFDO_DATA  FdoData
    )
/*++
Routine Description:

    Interrupt handler for sending processing. Re-claim the send resources,
    complete sends and get more to send from the send wait queue.

    Assumption: This function is called with the Send SPINLOCK held.

Arguments:

    FdoData     Pointer to our FdoData

Return Value:

    NTSTATUS code

--*/
{
    NTSTATUS   status = STATUS_SUCCESS;
    PMP_TCB    pMpTcb;
    BOOLEAN transactionComplete;


#if DBG
    ULONG      i;
#endif

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,
                "--> NICHandleSendInterrupt\n");

    //
    // Any packets being sent? Any packet waiting in the send queue?
    //
    if (FdoData->nBusySend == 0)
    {
        ASSERT(FdoData->CurrSendHead == FdoData->CurrSendTail);
        return status;
    }

    //
    // Check the first TCB on the send list
    //
    while (FdoData->nBusySend > 0)
    {

#if DBG
        pMpTcb = FdoData->CurrSendHead;
        for (i = 0; i < FdoData->nBusySend; i++)
        {
            pMpTcb = pMpTcb->Next;
        }

        if (pMpTcb != FdoData->CurrSendTail)
        {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                        "nBusySend= %d\n", FdoData->nBusySend);
            TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                        "CurrSendhead= %p\n", FdoData->CurrSendHead);
            TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                        "CurrSendTail= %p\n", FdoData->CurrSendTail);
            ASSERT(FALSE);
        }
#endif

        pMpTcb = FdoData->CurrSendHead;

        ASSERT(pMpTcb->DmaTransaction);

        //
        // Indicate this DMA operation has completed:
        // This may drive the transfer on the next packet if
        // there is still data to be transfered in the DmaTransaction.
        //
        transactionComplete =
            WdfDmaTransactionDmaCompleted( pMpTcb->DmaTransaction,
                                           &status );
        if(transactionComplete == TRUE) {
            ASSERT(status == STATUS_SUCCESS);
            MP_FREE_SEND_PACKET(FdoData, pMpTcb, status);
        } else {
            //
            // NOTE: For this ethernet driver this should never
            //       be returned as the packets are <= 1514 bytes.
            //       It is included to show the complete DmaTransaction
            //       coding pattern.
            //
            ASSERT(!"STATUS_MORE_PROCESSING_REQUIRED");
        }
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,
                "<-- NICHandleSendInterrupt\n");
    return status;
}
Exemple #4
0
NTSTATUS
NICHandleSendInterrupt(
    __in  PFDO_DATA  FdoData
    )
/*++
Routine Description:

    Interrupt handler for sending processing. Re-claim the send resources,
    complete sends and get more to send from the send wait queue.

    Assumption: Send spinlock has been acquired

Arguments:

    FdoData     Pointer to our FdoData

Return Value:

    NTSTATUS code

--*/
{
    NTSTATUS        status = STATUS_SUCCESS;
    PMP_TCB         pMpTcb;

#if DBG
    LONG            i;
#endif

    DebugPrint(TRACE, DBG_WRITE, "---> NICHandleSendInterrupt\n");

    //
    // Any packets being sent? Any packet waiting in the send queue?
    //
    if (FdoData->nBusySend == 0 &&
        IsListEmpty(&FdoData->SendQueueHead))
    {
        ASSERT(FdoData->CurrSendHead == FdoData->CurrSendTail);
        DebugPrint(TRACE, DBG_WRITE, "<--- NICHandleSendInterrupt\n");
        return status;
    }

    //
    // Check the first TCB on the send list
    //
    while (FdoData->nBusySend > 0)
    {

#if DBG
        pMpTcb = FdoData->CurrSendHead;
        for (i = 0; i < FdoData->nBusySend; i++)
        {
            pMpTcb = pMpTcb->Next;
        }

        if (pMpTcb != FdoData->CurrSendTail)
        {
            DebugPrint(ERROR, DBG_WRITE, "nBusySend= %d\n", FdoData->nBusySend);
            DebugPrint(ERROR, DBG_WRITE, "CurrSendhead= %p\n", FdoData->CurrSendHead);
            DebugPrint(ERROR, DBG_WRITE, "CurrSendTail= %p\n", FdoData->CurrSendTail);
            ASSERT(FALSE);
        }
#endif

        pMpTcb = FdoData->CurrSendHead;

        //
        // Is this TCB completed?
        //
        if (pMpTcb->HwTcb->TxCbHeader.CbStatus & CB_STATUS_COMPLETE)
        {
            //
            // Check if this is a multicast hw workaround packet
            //
            if ((pMpTcb->HwTcb->TxCbHeader.CbCommand & CB_CMD_MASK) != CB_MULTICAST)
            {
                MP_FREE_SEND_PACKET(FdoData, pMpTcb, STATUS_SUCCESS);

            } else {
                ASSERTMSG("Not sure what to do", FALSE);
            }
        }
        else
        {
            break;
        }
    }

    //
    // If we queued any transmits because we didn't have any TCBs earlier,
    // dequeue and send those packets now, as long as we have free TCBs.
    //
    while (!IsListEmpty(&FdoData->SendQueueHead) &&
        MP_TCB_RESOURCES_AVAIABLE(FdoData))
    {
        PIRP irp;
        PLIST_ENTRY pEntry;

        pEntry = RemoveHeadList(&FdoData->SendQueueHead);

        ASSERT(pEntry);

        FdoData->nWaitSend--;

        irp = CONTAINING_RECORD(pEntry, IRP, Tail.Overlay.ListEntry);
        DebugPrint(LOUD, DBG_WRITE, "NICHandleSendInterrupt - send a queued packet\n");

        NICWritePacket(FdoData, irp, TRUE);
    }

    DebugPrint(TRACE, DBG_WRITE, "<--- NICHandleSendInterrupt\n");
    return status;
}
Exemple #5
0
VOID
NICWritePacket(
    __in  PFDO_DATA   FdoData,
    __in  PIRP        Irp,
    __in  BOOLEAN     bFromQueue
    )
/*++
Routine Description:

    Do the work to send a packet
    Assumption: Send spinlock has been acquired

Arguments:

    FdoData     Pointer to our FdoData
    Packet      The packet
    bFromQueue  TRUE if it's taken from the send wait queue

Return Value:

--*/
{
    PMP_TCB         pMpTcb = NULL;
    ULONG           packetLength;
    PVOID           virtualAddress;

    DebugPrint(TRACE, DBG_WRITE, "--> NICWritePacket, Irp= %p\n", Irp);

    //
    // Get the next free TCB and initialize it to represent the
    // request buffer.
    //
    pMpTcb = FdoData->CurrSendTail;
    ASSERT(!MP_TEST_FLAG(pMpTcb, fMP_TCB_IN_USE));

    //
    // If the adapter is not ready, fail the request.
    //
    if(MP_IS_NOT_READY(FdoData)) {
        MP_FREE_SEND_PACKET(FdoData, pMpTcb, STATUS_DEVICE_NOT_READY);
        return;
    }

    pMpTcb->FirstBuffer = Irp->MdlAddress;
    virtualAddress = MmGetMdlVirtualAddress(Irp->MdlAddress);
    pMpTcb->BufferCount = 1;
    pMpTcb->PacketLength = packetLength = MmGetMdlByteCount(Irp->MdlAddress);
    pMpTcb->PhysBufCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(virtualAddress,
                                            packetLength);
    pMpTcb->Irp = Irp;
    MP_SET_FLAG(pMpTcb, fMP_TCB_IN_USE);

    //
    // Call the send handler, it only needs to deal with the frag list
    //
    NICSendPacket(FdoData, pMpTcb, Irp->Tail.Overlay.DriverContext[3]);

    FdoData->nBusySend++;
    ASSERT(FdoData->nBusySend <= FdoData->NumTcb);
    FdoData->CurrSendTail = FdoData->CurrSendTail->Next;

    DebugPrint(TRACE, DBG_WRITE, "<-- NICWritePacket\n");
    return;

}