Esempio n. 1
0
VOID
NICCheckForQueuedSends(
    IN  PFDO_DATA  FdoData
    )
/*++
Routine Description:

Arguments:

    FdoData     Pointer to our FdoData

Return Value:

--*/
{
    WDFREQUEST         request;
    WDFDMATRANSACTION  dmaTransaction;
    NTSTATUS           status;

    UNREFERENCED_PARAMETER( dmaTransaction );

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

    //
    // 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 (MP_TCB_RESOURCES_AVAIABLE(FdoData))
    {
        status = WdfIoQueueRetrieveNextRequest(
                     FdoData->PendingWriteQueue,
                     &request
                     );

        if(!NT_SUCCESS(status) ) {
            if(STATUS_NO_MORE_ENTRIES != status) {
                TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,
                    "WdfIoQueueRetrieveNextRequest failed %X\n", status);
            }
            break;
        }

        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,
                    "\t processing Request %p \n", request);

        status = NICInitiateDmaTransfer(FdoData, request);
        if(!NT_SUCCESS(status)) {
            WdfRequestCompleteWithInformation(request, status, 0);
        }

        FdoData->nWaitSend--;
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,
                "<-- NICCheckForQueuedSends\n");
}
Esempio n. 2
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;
}
Esempio n. 3
0
BOOLEAN
NICEvtProgramDmaFunction(
    IN  WDFDMATRANSACTION       Transaction,
    IN  WDFDEVICE               Device,
    IN  PVOID                   Context,
    IN  WDF_DMA_DIRECTION       Direction,
    IN  PSCATTER_GATHER_LIST    ScatterGather
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/
{
    PFDO_DATA           fdoData;
    WDFREQUEST          request;
    NTSTATUS            status;

    UNREFERENCED_PARAMETER( Context );
    UNREFERENCED_PARAMETER( Direction );

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

    fdoData = FdoGetData(Device);
    request = WdfDmaTransactionGetRequest(Transaction);


    WdfSpinLockAcquire(fdoData->SendLock);

    //
    // If tcb or link is not available, queue the request
    //
    if (!MP_TCB_RESOURCES_AVAIABLE(fdoData))
    {
        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,
                "Resource is not available: queue Request %p\n", request);

        //
        // Must abort the transaction before deleting.
        //
        (VOID) WdfDmaTransactionDmaCompletedFinal(Transaction, 0, &status);
        ASSERT(NT_SUCCESS(status));
        WdfObjectDelete( Transaction );

        //
        // Queue the request for later processing.
        //
        status = WdfRequestForwardToIoQueue(request,
                                           fdoData->PendingWriteQueue);

        if(!NT_SUCCESS(status)) {
            ASSERTMSG(" WdfRequestForwardToIoQueue failed ", FALSE);
            WdfSpinLockRelease(fdoData->SendLock);
            WdfRequestCompleteWithInformation(request, STATUS_UNSUCCESSFUL, 0);
            return FALSE;
        }
        fdoData->nWaitSend++;

    } else {

        status = NICWritePacket(fdoData, Transaction, ScatterGather);

        if(!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                        "<-- NICEvtProgramDmaFunction returning %!STATUS!\n",
                        status);
            //
            // Must abort the transaction before deleting.
            //
            (VOID )WdfDmaTransactionDmaCompletedFinal(Transaction, 0, &status);
            ASSERT(NT_SUCCESS(status));
            WdfObjectDelete( Transaction );

            WdfSpinLockRelease(fdoData->SendLock);
            WdfRequestCompleteWithInformation(request, STATUS_UNSUCCESSFUL, 0);
            return FALSE;
        }
    }


    WdfSpinLockRelease(fdoData->SendLock);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,
                "<-- NICEvtProgramDmaFunction\n");

    return TRUE;
}
Esempio n. 4
0
VOID
NICProcessSGList(
    PDEVICE_OBJECT          DeviceObject,
    PIRP                    Irp,//unused
    PSCATTER_GATHER_LIST    ScatterGather,
    PVOID                   Context
    )
/*++

Routine Description:

    This routine is called at IRQL = DISPATCH_LEVEL when the
    bus-master adapter is available.

Arguments:

    DeviceObject - This is the device object for the target device,
                    previously created by the driver's AddDevice routine.
    Irp  - Useful only if the driver has a StartIo routine.

    ScatterGather - Structure describing scatter/gather regions.

    Context - Pointer to the Request.

Return Value:

    None.

--*/
{
    PFDO_DATA       fdoData;
    PIRP            irp = (PIRP)Context;

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

    fdoData = DeviceObject->DeviceExtension;

    //
    // Save the ScatterGather pointer in the DriverContext so that we can free
    // the list when we complete the request.
    //
    irp->Tail.Overlay.DriverContext[3] = ScatterGather;

    KeAcquireSpinLockAtDpcLevel(&fdoData->SendLock);

    //
    // If tcb is not available or the device is doing link detection (during init),
    // queue the request
    //
    if (!MP_TCB_RESOURCES_AVAIABLE(fdoData) ||
        MP_TEST_FLAG(fdoData, fMP_ADAPTER_LINK_DETECTION))
    {
        //
        // Instead of locking up the map registers while the request is
        // waiting in the queue or, we could free it up and reallocate it whenever
        // we are ready to handle the request later.
        //
        //
        DebugPrint(TRACE, DBG_WRITE, "Resource or the link is not available, queue packet\n");
        InsertTailList(&fdoData->SendQueueHead, &irp->Tail.Overlay.ListEntry);
        fdoData->nWaitSend++;

    } else {

        NICWritePacket(fdoData, irp, FALSE);
    }

    KeReleaseSpinLockFromDpcLevel(&fdoData->SendLock);

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

    return;
}