Ejemplo n.º 1
0
VOID
AmccPciEvtIoDefault(
    __in WDFQUEUE       Queue,
    __in WDFREQUEST     Request
    )
/*++

Routine Description:

    Start the IRP on the device.  This driver allows only one I/O to
    be active on the adapter at any one time.  If multiple I/Os are sent
    to the driver, they will be queued and completed as they complete on
    the adapter (one IRP per interrupt).

Arguments:

    Queue - Default queue handle
    Request - Handle to the write request
    Parameters - Contains current stack location information from the IRP

Return Value:

    None

--*/
{
    PAMCC_DEVICE_EXTENSION    devExt;
    REQUEST_CONTEXT         * transfer;
    NTSTATUS                  status;
    size_t                    length;
    WDF_DMA_DIRECTION         direction;
    WDFDMATRANSACTION         dmaTransaction;
    WDF_REQUEST_PARAMETERS    params;

    WDF_REQUEST_PARAMETERS_INIT(&params);

    WdfRequestGetParameters(
        Request,
        &params
        );

    //
    // Get the device extension.
    //
    devExt = AmccPciGetDevExt(WdfIoQueueGetDevice( Queue ));

    //
    // Validate and gather parameters.
    //
    switch (params.Type) {

        case WdfRequestTypeRead:
            length    = params.Parameters.Read.Length;
            direction = WdfDmaDirectionReadFromDevice;
            break;

        case WdfRequestTypeWrite:
            length    = params.Parameters.Write.Length;
            direction = WdfDmaDirectionWriteToDevice;
            break;

        default:
            TraceEvents(TRACE_LEVEL_WARNING, AMCC_TRACE_IO,
                        "Request type not Read or Write\n");
            WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
            return;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_IO,
                "Request %p: %s %d bytes",
                Request, (direction)?"Write":"Read", (ULONG)length);

    //
    // The length must be non-zero.
    //
    if (length == 0) {
        TraceEvents(TRACE_LEVEL_WARNING, AMCC_TRACE_IO,
                    "Zero transfer length input to read/write");
        WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
        return;
    }

    transfer = GetRequestContext(Request);

    //
    // Create new DmaRequst to conduct this DMA transaction.
    //
    status = WdfDmaTransactionCreate( devExt->DmaEnabler,
                                      WDF_NO_OBJECT_ATTRIBUTES,
                                      &dmaTransaction );

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO,
                    "WdfDmaRequestCreate failed: %X", status);
        WdfRequestComplete(Request, status);
        return;
    }

    //
    // Create new DmaTransaction.
    //
    status = WdfDmaTransactionInitializeUsingRequest( dmaTransaction,
                                                      Request,
                                                      AmccPciProgramDma,
                                                      direction );

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO,
                    "WdfDmaRequestInitializeWithRequest failed: %X",
                    status);

        WdfObjectDelete(dmaTransaction);

        WdfRequestComplete(Request, status);
        return;
    }

    //
    // Fill transfer context structure
    //
    transfer->Request        = Request;
    transfer->DmaTransaction = dmaTransaction;

    //
    // Save the current Request as the "in-progress" request.
    //
    devExt->CurrentRequest = Request;

    //
    // Execute this dmaTransaction transaction.
    //
    status = WdfDmaTransactionExecute( dmaTransaction, WDF_NO_CONTEXT);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO,
                    "WdfDmaTransactionExecute failed: %X",
                    status);

        WdfObjectDelete(dmaTransaction);
        WdfRequestComplete(Request, status);
        return;
    }

    return;
}
Ejemplo n.º 2
0
NTSTATUS
NICInitiateDmaTransfer(
    IN PFDO_DATA        FdoData,
    IN WDFREQUEST       Request
    )
{
    WDFDMATRANSACTION   dmaTransaction;
    NTSTATUS            status;
    BOOLEAN             bCreated = FALSE;

    do {
        //
        // Create a new DmaTransaction.
        //
        status = WdfDmaTransactionCreate( FdoData->WdfDmaEnabler,
                                          WDF_NO_OBJECT_ATTRIBUTES,
                                          &dmaTransaction );

        if(!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                        "WdfDmaTransactionCreate failed %X\n", status);
            break;
        }

        bCreated = TRUE;
        //
        // Initialize the new DmaTransaction.
        //

        status = WdfDmaTransactionInitializeUsingRequest(
                                     dmaTransaction,
                                     Request,
                                     NICEvtProgramDmaFunction,
                                     WdfDmaDirectionWriteToDevice );

        if(!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                       "WdfDmaTransactionInitalizeUsingRequest failed %X\n",
                       status);
            break;
        }

        //
        // Execute this DmaTransaction.
        //
        status = WdfDmaTransactionExecute( dmaTransaction,
                                           dmaTransaction );

        if(!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                            "WdfDmaTransactionExecute failed %X\n", status);
            break;
        }

    } WHILE (FALSE);

    if(!NT_SUCCESS(status)){

        if(bCreated) {
            WdfObjectDelete( dmaTransaction );

        }
    }

    return status;
}
Ejemplo n.º 3
0
NTSTATUS
PLxInitializeDMA(
    IN PDEVICE_EXTENSION DevExt
    )
/*++
Routine Description:

    Initializes the DMA adapter.

Arguments:

    DevExt      Pointer to our DEVICE_EXTENSION

Return Value:

     None

--*/
{
    NTSTATUS    status;
    WDF_OBJECT_ATTRIBUTES attributes;

    PAGED_CODE();

    //
    // PLx PCI9656 DMA_TRANSFER_ELEMENTS must be 16-byte aligned
    //
    WdfDeviceSetAlignmentRequirement( DevExt->Device,
                                      PCI9656_DTE_ALIGNMENT_16 );

    //
    // Create a new DMA Enabler instance.
    // Use Scatter/Gather, 64-bit Addresses, Duplex-type profile.
    //
    {
        WDF_DMA_ENABLER_CONFIG   dmaConfig;

        WDF_DMA_ENABLER_CONFIG_INIT( &dmaConfig,
                                     WdfDmaProfileScatterGather64Duplex,
                                     DevExt->MaximumTransferLength );

        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                    " - The DMA Profile is WdfDmaProfileScatterGather64Duplex");

        status = WdfDmaEnablerCreate( DevExt->Device,
                                      &dmaConfig,
                                      WDF_NO_OBJECT_ATTRIBUTES,
                                      &DevExt->DmaEnabler );

        if (!NT_SUCCESS (status)) {

            TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                        "WdfDmaEnablerCreate failed: %!STATUS!", status);
            return status;
        }
    }

    //
    // Allocate common buffer for building writes
    //
    // NOTE: This common buffer will not be cached.
    //       Perhaps in some future revision, cached option could
    //       be used. This would have faster access, but requires
    //       flushing before starting the DMA in PLxStartWriteDma.
    //
    DevExt->WriteCommonBufferSize =
        sizeof(DMA_TRANSFER_ELEMENT) * DevExt->WriteTransferElements;

    _Analysis_assume_(DevExt->WriteCommonBufferSize > 0);
    status = WdfCommonBufferCreate( DevExt->DmaEnabler,
                                    DevExt->WriteCommonBufferSize,
                                    WDF_NO_OBJECT_ATTRIBUTES,
                                    &DevExt->WriteCommonBuffer );

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfCommonBufferCreate (write) failed: %!STATUS!", status);
        return status;
    }


    DevExt->WriteCommonBufferBase =
        WdfCommonBufferGetAlignedVirtualAddress(DevExt->WriteCommonBuffer);

    DevExt->WriteCommonBufferBaseLA =
        WdfCommonBufferGetAlignedLogicalAddress(DevExt->WriteCommonBuffer);

    RtlZeroMemory( DevExt->WriteCommonBufferBase,
                   DevExt->WriteCommonBufferSize);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                "WriteCommonBuffer 0x%p  (#0x%I64X), length %I64d",
                DevExt->WriteCommonBufferBase,
                DevExt->WriteCommonBufferBaseLA.QuadPart,
                WdfCommonBufferGetLength(DevExt->WriteCommonBuffer) );

    //
    // Allocate common buffer for building reads
    //
    // NOTE: This common buffer will not be cached.
    //       Perhaps in some future revision, cached option could
    //       be used. This would have faster access, but requires
    //       flushing before starting the DMA in PLxStartReadDma.
    //
    DevExt->ReadCommonBufferSize =
        sizeof(DMA_TRANSFER_ELEMENT) * DevExt->ReadTransferElements;

    _Analysis_assume_(DevExt->ReadCommonBufferSize > 0);
    status = WdfCommonBufferCreate( DevExt->DmaEnabler,
                                    DevExt->ReadCommonBufferSize,
                                    WDF_NO_OBJECT_ATTRIBUTES,
                                    &DevExt->ReadCommonBuffer );

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfCommonBufferCreate (read) failed %!STATUS!", status);
        return status;
    }

    DevExt->ReadCommonBufferBase =
        WdfCommonBufferGetAlignedVirtualAddress(DevExt->ReadCommonBuffer);

    DevExt->ReadCommonBufferBaseLA =
        WdfCommonBufferGetAlignedLogicalAddress(DevExt->ReadCommonBuffer);

    RtlZeroMemory( DevExt->ReadCommonBufferBase,
                   DevExt->ReadCommonBufferSize);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                "ReadCommonBuffer  0x%p  (#0x%I64X), length %I64d",
                DevExt->ReadCommonBufferBase,
                DevExt->ReadCommonBufferBaseLA.QuadPart,
                WdfCommonBufferGetLength(DevExt->ReadCommonBuffer) );

    //
    // Since we are using sequential queue and processing one request
    // at a time, we will create transaction objects upfront and reuse
    // them to do DMA transfer. Transactions objects are parented to
    // DMA enabler object by default. They will be deleted along with
    // along with the DMA enabler object. So need to delete them
    // explicitly.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, TRANSACTION_CONTEXT);
    
    status = WdfDmaTransactionCreate( DevExt->DmaEnabler,
                                      &attributes,
                                      &DevExt->ReadDmaTransaction);

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                    "WdfDmaTransactionCreate(read) failed: %!STATUS!", status);
        return status;
    }

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, TRANSACTION_CONTEXT);
    //
    // Create a new DmaTransaction.
    //
    status = WdfDmaTransactionCreate( DevExt->DmaEnabler,
                                      &attributes,
                                      &DevExt->WriteDmaTransaction );

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                    "WdfDmaTransactionCreate(write) failed: %!STATUS!", status);
        return status;
    }

    return status;
}