Example #1
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;
}
Example #2
0
_Use_decl_annotations_
VOID
PLxEvtInterruptDpc(
    WDFINTERRUPT Interrupt,
    WDFOBJECT    Device
    )
/*++

Routine Description:

    DPC callback for ISR. Please note that on a multiprocessor system,
    you could have more than one DPCs running simulataneously on
    multiple processors. So if you are accesing any global resources
    make sure to synchrnonize the accesses with a spinlock.

Arguments:

    Interupt  - Handle to WDFINTERRUPT Object for this device.
    Device    - WDFDEVICE object passed to InterruptCreate

Return Value:

--*/
{
    NTSTATUS            status;
    WDFDMATRANSACTION   dmaTransaction;
    PDEVICE_EXTENSION   devExt;
    BOOLEAN             writeInterrupt = FALSE;
    BOOLEAN             readInterrupt  = FALSE;

    UNREFERENCED_PARAMETER(Device);


    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "--> EvtInterruptDpc");

    devExt  = PLxGetDeviceContext(WdfInterruptGetDevice(Interrupt));

    //
    // Acquire this device's InterruptSpinLock.
    //
    WdfInterruptAcquireLock( Interrupt );


    if ((devExt->IntCsr.bits.DmaChan0IntActive) &&
        (devExt->Dma0Csr.bits.Done)) {

        //
        // If Dma0 channel 0 (write) is interrupting and the
        //  Done bit is set in the Dma0 CSR,
        //  we're interrupting because a WRITE is complete.
        // Clear the done bit and channel interrupting bit from
        //  our copies...
        //
        devExt->IntCsr.bits.DmaChan0IntActive = FALSE;
        devExt->Dma0Csr.uchar = 0;

        writeInterrupt = TRUE;
    }

    if ((devExt->IntCsr.bits.DmaChan1IntActive) &&
        (devExt->Dma1Csr.bits.Done)) {

        //
        // If DMA channel 1 is interrupting and the
        //  DONE bit is set in the DMA1 control/status
        //  register, we're interrupting because a READ
        //  is complete.
        // Clear the done bit and channel interrupting bit from
        //  our copies...
        //
        devExt->IntCsr.bits.DmaChan1IntActive = FALSE;
        devExt->Dma0Csr.uchar = 0;

        readInterrupt = TRUE;
    }

    //
    // Release our interrupt spinlock
    //
    WdfInterruptReleaseLock( Interrupt );

    //
    // Did a Write DMA complete?
    //
    if (writeInterrupt) {

        BOOLEAN transactionComplete;

        //
        // Get the current Write DmaTransaction.
        //
        dmaTransaction = devExt->WriteDmaTransaction;

        //
        // 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 request.
        //
        transactionComplete = WdfDmaTransactionDmaCompleted( dmaTransaction,
                                                         &status );

        if (transactionComplete) {
            //
            // Complete this DmaTransaction.
            //
            TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC,
                                     "Completing Write request in the DpcForIsr");

            PLxWriteRequestComplete( dmaTransaction, status );

        }
    }

    //
    // Did a Read DMA complete?
    //
    if (readInterrupt) {

        BOOLEAN                transactionComplete;
        PDMA_TRANSFER_ELEMENT  dteVA;
        size_t                 length;

        //
        // Get the current Read DmaTransaction.
        //
        dmaTransaction = devExt->ReadDmaTransaction;

        //
        // Only on Read-side --
        //    Use "DMA Clear-Count Mode" to get complemetary
        //    transferred byte count.
        //
        length = WdfDmaTransactionGetCurrentDmaTransferLength( dmaTransaction );

        dteVA = (PDMA_TRANSFER_ELEMENT) devExt->ReadCommonBufferBase;

        while(dteVA->DescPtr.LastElement == FALSE) {
            length -= dteVA->TransferSize;
            dteVA++;
        }
        length -= dteVA->TransferSize;

        //
        // 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 request.
        //
        transactionComplete =
            WdfDmaTransactionDmaCompletedWithLength( dmaTransaction,
                                                     length,
                                                     &status );

        if (transactionComplete) {
            //
            // Complete this DmaTransaction.
            //
            TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC,
                                    "Completing Read request in the DpcForIsr");

            PLxReadRequestComplete( dmaTransaction, status );

        }
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "<-- EvtInterruptDpc");

    return;
}
Example #3
0
VOID
AmccPciEvtInterruptDpc(
    __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:

--*/
{
    PAMCC_DEVICE_EXTENSION   devExt;
    WDFREQUEST               request;
    REQUEST_CONTEXT        * transfer;
    NTSTATUS                 status;
    size_t                   transferred;
    BOOLEAN                  transactionComplete;

    UNREFERENCED_PARAMETER( WdfInterrupt );

    devExt = AmccPciGetDevExt(WdfDevice);

    //
    // Retreive request and transfer.
    //
    request  = devExt->CurrentRequest;
    transfer = GetRequestContext(request);

    //
    // Check to see if the request is cancelled by the system. While
    // we are DMAing a large buffer into multiple transaction,
    // there is good possibilty for the request to get cancelled because
    // the originator of the request exited or cancelled the I/O explicitly.
    //
    if(WdfRequestIsCanceled(request)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO,
                                    "Aborted DMA transaction 0x%p",  request);
        WdfObjectDelete( transfer->DmaTransaction );
        devExt->CurrentRequest = NULL;
        WdfRequestComplete(request, STATUS_CANCELLED);
        return;
    }

    //
    // The boolean transactionComplete indicates whether the transaction has
    // exited the transfer state, e.g. no further transfers are scheduled.
    //
    // If transactionComplete == FALSE, then the next DMA transfer has been
    // scheduled, e.g. the next interrrupt will drive the ISR again.
    //
    // If transactionComplete == TRUE, then status indicates the reason;
    // SUCCESS is the nomative case, while non-SUCCESS indicates the
    // DMA transaction failed for "status" reason.
    //
    transactionComplete = WdfDmaTransactionDmaCompleted( transfer->DmaTransaction,
                                                     &status );

    if (transactionComplete) {

        ASSERT(status != STATUS_MORE_PROCESSING_REQUIRED);

        //
        // No more data: request is complete
        //
        TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_IO,
                    "Request %p completed: status %X",
                    request, status);

        //
        // Get the final bytes transferred count.
        //
        transferred =
            WdfDmaTransactionGetBytesTransferred( transfer->DmaTransaction );

        TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_IO,
                    "Bytes transfered %d", (int) transferred );

        //
        // Delete this DmaTransaction transaction.
        //
        WdfObjectDelete( transfer->DmaTransaction );

        //
        // Clean-up for this request.
        //
        devExt->CurrentRequest = NULL;

        //
        // Complete this IO request.
        //
        WdfRequestCompleteWithInformation( request,
                                           status,
                                           (NT_SUCCESS(status)) ?
                                           transferred : 0 );
    }

}