Exemple #1
0
NTSTATUS PciDtfDeviceGetDma(IN WDFDEVICE Device, IN WDFREQUEST Request)
{
	PDEVICE_DATA DeviceData = GetDeviceData(Device);
	PCIDTF_DMA_INFO *ReqData;
	WDFCOMMONBUFFER CommonBuffer;
	NTSTATUS Status = STATUS_SUCCESS;

	__try {
		Status = WdfRequestRetrieveInputBuffer(Request,
						       sizeof(PCIDTF_DMA_INFO),
						       (PVOID *) & ReqData,
						       NULL);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfRequestRetrieveInputBuffer", Status);
			__leave;
		}
		Status = WdfRequestRetrieveOutputBuffer(Request,
							sizeof(PCIDTF_DMA_INFO),
							(PVOID *) & ReqData,
							NULL);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfRequestRetrieveOutputBuffer", Status);
			__leave;
		}
		CommonBuffer =
		    PciDtfCommonBufferFind(DeviceData, ReqData->id, FALSE);
		if (CommonBuffer == NULL) {
			Status = STATUS_INVALID_PARAMETER;
			__leave;
		}
		ReqData->addr =
		    WdfCommonBufferGetAlignedLogicalAddress
		    (CommonBuffer).QuadPart;
		ReqData->len = (int)WdfCommonBufferGetLength(CommonBuffer);
		WdfRequestSetInformation(Request, sizeof(PCIDTF_DMA_INFO));
	}
	__finally {
		WdfRequestComplete(Request, Status);
	}
	return Status;
}
Exemple #2
0
NTSTATUS PciDtfDeviceReadWriteDma(IN WDFDEVICE Device, IN WDFREQUEST Request,
				  IN BOOLEAN Read)
{
	PDEVICE_DATA DeviceData = GetDeviceData(Device);
	PCIDTF_DMA_DATA *ReqData;
	WDFCOMMONBUFFER CommonBuffer;
	NTSTATUS Status = STATUS_SUCCESS;

	__try {
		Status = WdfRequestRetrieveInputBuffer(Request,
						       sizeof(PCIDTF_DMA_DATA),
						       (PVOID *) & ReqData,
						       NULL);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfRequestRetrieveInputBuffer", Status);
			__leave;
		}
		TRACE_MSG(TRACE_LEVEL_VERBOSE, TRACE_FLAG_QUEUE,
			  "id=%d, off=%d, len=%d, buf=0x%p, read=%u\n",
			  ReqData->id, ReqData->off, ReqData->len, ReqData->buf,
			  Read);
		CommonBuffer = PciDtfCommonBufferFind(DeviceData,
						      ReqData->id, FALSE);
		if (CommonBuffer == NULL) {
			Status = STATUS_INVALID_PARAMETER;
			__leave;
		}
		Status = PciDtfDmaReadWrite(ReqData,
					    WdfCommonBufferGetAlignedVirtualAddress
					    (CommonBuffer),
					    (ULONG) WdfCommonBufferGetLength
					    (CommonBuffer), Read);
	}
	__finally {
		WdfRequestComplete(Request, Status);
	}
	return Status;
}
Exemple #3
0
NTSTATUS PciDtfDeviceAllocDma(IN WDFDEVICE Device, IN WDFREQUEST Request)
{
	PDEVICE_DATA DeviceData = GetDeviceData(Device);
	PCIDTF_DMA_INFO *ReqData;
	WDF_OBJECT_ATTRIBUTES ObjectAttributes;
	WDFCOMMONBUFFER CommonBuffer = NULL;
	PCOMMON_BUFFER_DATA CommonBufferData;
	NTSTATUS Status = STATUS_SUCCESS;

	__try {
		Status = WdfRequestRetrieveInputBuffer(Request,
						       sizeof(PCIDTF_DMA_INFO),
						       (PVOID *) & ReqData,
						       NULL);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfRequestRetrieveInputBuffer", Status);
			__leave;
		}
		Status = WdfRequestRetrieveOutputBuffer(Request,
							sizeof(PCIDTF_DMA_INFO),
							(PVOID *) & ReqData,
							NULL);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfRequestRetrieveOutputBuffer", Status);
			__leave;
		}
		WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ObjectAttributes,
							COMMON_BUFFER_DATA);
		Status = WdfCommonBufferCreate(DeviceData->DmaEnabler,
					       ReqData->len, &ObjectAttributes,
					       &CommonBuffer);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfCommonBufferCreate", Status);
			__leave;
		}
		CommonBufferData = GetCommonBufferData(CommonBuffer);
		CommonBufferData->ID = PciDtfCommonBufferAssignId(DeviceData);
		Status = WdfCollectionAdd(DeviceData->CommonBuffers,
					  CommonBuffer);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfCollectionAdd", Status);
			__leave;
		}
		ReqData->id = CommonBufferData->ID;
		ReqData->addr =
		    WdfCommonBufferGetAlignedLogicalAddress
		    (CommonBuffer).QuadPart;
		WdfRequestSetInformation(Request, sizeof(PCIDTF_DMA_INFO));

		TRACE_MSG(TRACE_LEVEL_VERBOSE, TRACE_FLAG_QUEUE,
			  "va 0x%p, pa 0x%llX, len 0x%X\n",
			  WdfCommonBufferGetAlignedVirtualAddress(CommonBuffer),
			  WdfCommonBufferGetAlignedLogicalAddress
			  (CommonBuffer).QuadPart,
			  WdfCommonBufferGetLength(CommonBuffer));
	}
	__finally {
		if (!NT_SUCCESS(Status) && CommonBuffer != NULL) {
			WdfObjectDelete(CommonBuffer);
		}
		WdfRequestComplete(Request, Status);
	}
	return Status;
}
Exemple #4
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;
}