Exemple #1
0
NTSTATUS
NICStartRecv(
    IN  PFDO_DATA  FdoData
    )
/*++
Routine Description:

    Start the receive unit if it's not in a ready state

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

Arguments:

    FdoData     Pointer to our FdoData

Return Value:

    NT Status code

--*/
{
    PMP_RFD         pMpRfd;
    NTSTATUS        status = STATUS_SUCCESS;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "---> NICStartRecv\n");
    ASSERT(!IsListEmpty(&FdoData->RecvList));

    //
    // Get the MP_RFD head
    //
    pMpRfd = (PMP_RFD)GetListHeadEntry(&FdoData->RecvList);

    NICHandleRecvInterrupt(FdoData);
    ASSERT(!IsListEmpty(&FdoData->RecvList));

    //
    // Get the new MP_RFD head
    //
    pMpRfd = (PMP_RFD)GetListHeadEntry(&FdoData->RecvList);

exit:
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<--- NICStartRecv, Status=%x\n", status);
    return status;
}
VOID
NICEvtInterruptDpc(
    IN WDFINTERRUPT WdfInterrupt,
    IN WDFOBJECT    WdfDevice
    )

/*++

Routine Description:

    DPC callback for ISR.

Arguments:

    WdfInterrupt - Handle to the framework interrupt object

    WdfDevice - Associated device object.

Return Value:

--*/
{
    PFDO_DATA fdoData = NULL;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "--> NICEvtInterruptDpc\n");

    fdoData = FdoGetData(WdfDevice);


    WdfSpinLockAcquire(fdoData->RcvLock);

    NICHandleRecvInterrupt(fdoData);


    WdfSpinLockRelease(fdoData->RcvLock);

    //
    // Handle send interrupt
    //

    WdfSpinLockAcquire(fdoData->SendLock);

    NICHandleSendInterrupt(fdoData);


    WdfSpinLockRelease(fdoData->SendLock);

    //
    // Check if any queued Sends need to be reprocessed.
    //
    NICCheckForQueuedSends(fdoData);

    //
    // Start the receive unit if it had stopped
    //

    WdfSpinLockAcquire(fdoData->RcvLock);

    NICStartRecv(fdoData);


    WdfSpinLockRelease(fdoData->RcvLock);

    //
    // Re-enable the interrupt (disabled in MPIsr)
    //
    WdfInterruptSynchronize(
        WdfInterrupt,
        NICEnableInterrupt,
        fdoData);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "<-- NICEvtInterruptDpc\n");

}
NTSTATUS
NICStartRecv(
    IN  PFDO_DATA  FdoData
    )
/*++
Routine Description:

    Start the receive unit if it's not in a ready state

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

Arguments:

    FdoData     Pointer to our FdoData

Return Value:

    NT Status code

--*/
{
    PMP_RFD         pMpRfd;
    NTSTATUS        status;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "---> NICStartRecv\n");

    //
    // If the receiver is ready, then don't try to restart.
    //
    if (NIC_IS_RECV_READY(FdoData))
    {
        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Receive unit already active\n");
        return STATUS_SUCCESS;
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Re-start receive unit...\n");
    ASSERT(!IsListEmpty(&FdoData->RecvList));

    //
    // Get the MP_RFD head
    //
    pMpRfd = (PMP_RFD)GetListHeadEntry(&FdoData->RecvList);

    //
    // If more packets are received, clean up RFD chain again
    //
    if (NIC_RFD_GET_STATUS(pMpRfd->HwRfd))
    {
        NICHandleRecvInterrupt(FdoData);
        ASSERT(!IsListEmpty(&FdoData->RecvList));

        //
        // Get the new MP_RFD head
        //
        pMpRfd = (PMP_RFD)GetListHeadEntry(&FdoData->RecvList);
    }

    //
    // Wait for the SCB to clear before we set the general pointer
    //
    if (!WaitScb(FdoData))
    {
        status = STATUS_DEVICE_DATA_ERROR;
        goto exit;
    }

    if (FdoData->DevicePowerState > PowerDeviceD0)
    {
        status = STATUS_DEVICE_DATA_ERROR;
        goto exit;
    }
    //
    // Set the SCB General Pointer to point the current Rfd
    //
    FdoData->CSRAddress->ScbGeneralPointer = pMpRfd->HwRfdPhys;

    //
    // Issue the SCB RU start command
    //
    status = D100IssueScbCommand(FdoData, SCB_RUC_START, FALSE);
    if (status == STATUS_SUCCESS)
    {
        // wait for the command to be accepted
        if (!WaitScb(FdoData))
        {
            status = STATUS_DEVICE_DATA_ERROR;
        }
    }

    exit:

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<--- NICStartRecv, Status=%x\n", status);
    return status;
}