bus-master dma 注意事项

本文介绍了DMA中的System DMA与Bus-Master DMA的区别,重点讲述了Bus-Master DMA,其中设备具备直接控制数据传输的能力。在使用DMA时,通过获取DMA_ADAPTER并利用其回调实现传输。DeviceDescription的Version和MaximumLength对DMA操作有直接影响,IoGetDmaAdapter会根据MaximumLength确定最大传输长度和map regs数量。对于Storage设备,最大传输长度的设置会限制单次传输的大小。

    DMA通常包括system dma和bus-master dma。他们的区别在于system dma是依赖于系统,device本身并没有dma控制传输的能力,而bus-master则相反,device有dma控制传输的能力。通常比较多见的是bus-master dma方式。

    DMA的使用,首先在Start device中获取DMA_ADAPTER,透过DMA_ADAPTER提供的call back来实现dma传输。

    获取DMA_ADAPTER的函数:

IoGetDmaAdapter
The IoGetDmaAdapter routine returns a pointer to the DMA adapter structure for a physical device object.

PDMA_ADAPTER
  IoGetDmaAdapter(
    IN PDEVICE_OBJECT  PhysicalDeviceObject,
    IN PDEVICE_DESCRIPTION  DeviceDescription,
    OUT PULONG  NumberOfMapRegisters
    );


Parameters
PhysicalDeviceObject 
Pointer to the physical device object for the device requesting the DMA adapter structure. 
DeviceDescription 
Pointer to a DEVICE_DESCRIPTION structure, which describes the attributes of the physical device. 
NumberOfMapRegisters 
A pointer to, on output, the maximum number of map registers that the driver can allocate for any DMA transfer operation. 
Return Value
IoGetDmaAdapter returns a pointer to a DMA_ADAPTER structure, which contains pointers to functions that support system-defined DMA operations. If the structure cannot be allocated, the routine returns NULL. 

Comments
Before calling this routine, a driver must zero-initialize the structure passed at DeviceDescription and then supply the relevant information for its device.

On success, the DmaOperations member of the routine's return value points to a DMA_OPERATIONS structure, which is a table of pointers to functions that the driver can use to perform subsequent DMA operations. If the driver passes DEVICE_DESCRIPTION_VERSION or DEVICE_DESCRIPTION_VERSION1 in the Version member of the DeviceDescription parameter, IoGetDmaAdapter returns a pointer to version 1 of the DMA_OPERATIONS structure. If the driver passes DEVICE_DESCRIPTION_VERSION2, IoGetDmaAdapter returns version 2 of the table if version 2 is supported; otherwise, it returns NULL. Drivers must check to see if version 2 is supported before attempting to use any version 2 function.

A PnP driver calls IoGetDmaAdapter when its AddDevice routine is called or when it handles a PnP IRP_MN_START_DEVICE request for a device. This IRP includes information about the device's hardware resources that the driver must supply in the DeviceDescription structure.

The caller uses the MaximumLength member in the DeviceDescription structure to indicate the optimal number of map registers it can use. The I/O manager will attempt to allocate enough map registers to accommodate a DMA transfer operation of this maximum size. On output, the I/O manager returns, in the NumberOfMapRegisters parameter, the number of map registers that it allocates. Drivers should check the returned value; there is no guarantee a driver will receive the same number of map registers it requested.

To free the adapter object, the driver should call PutDmaAdapter through the pointer returned in the DMA_ADAPTER structure.

Note  As previously described, IoGetDmaAdapter returns NULL if it does not support the version of the DMA_ADAPTER structure that is specified by DeviceDescription->Version. Callers should rely on this behavior to determine whether the routine returns a pointer to the requested version of the DMA_ADAPTER structure. When IoGetDmaAdapter returns a pointer to version 1 or version 2 of the DMA_ADAPTER structure, the Version member of this structure is always set to 1. Thus, the caller cannot use the Version member of the returned DMA_ADAPTER structure to distinguish between versions 1 and 2 of this structure. 


Requirements
Versions: Available in Windows 2000 and later versions of Windows. 

IRQL: PASSIVE_LEVEL

Headers: Declared in Wdm.h. Include Wdm.h, Ntddk.h, or Ntifs.h. 

Library: Contained in Ntoskrnl.lib. 


上述API需要特别注意其中的几个参数:

DeviceDescription - 对应于所需要获取的DMA_ADAPTER的属性,此次的设置会对后续的引用产生直接的影响。DEVICE_DESCROPTION的定义如下

typedef struct _DEVICE_DESCRIPTION {
  ULONG  Version;		// *
  BOOLEAN  Master;		// bus-master or system
  BOOLEAN  ScatterGather;	// support scattergather or not
  BOOLEAN  DemandMode;		// system dma only	
  BOOLEAN  AutoInitialize;	// system dma only
  BOOLEAN  Dma32BitAddresses;	// use 32bit address or not
  BOOLEAN  IgnoreCount;		// related to version
  BOOLEAN  Reserved1;
  BOOLEAN  Dma64BitAddresses;	// use 64bit address or not
  ULONG  BusNumber; 
  ULONG  DmaChannel;		// for system dma only
  INTERFACE_TYPE  InterfaceType;
  DMA_WIDTH  DmaWidth;		// system dma only
  DMA_SPEED  DmaSpeed;		// system dma only	
  ULONG  MaximumLength;		// *
  ULONG  DmaPort;
} DEVICE_DESCRIPTION, *PDEVICE_DESCRIPTION;

1, Version 此处不同Version的区别在于DMA_ADAPTER中的DmaOperations不同,version3>version2>version1

Version3是win8中最新support的,具体可以参考DmaOperations的定义

The DMA_OPERATIONS structure provides a table of pointers to functions that control the operation of a DMA controller.

Syntax
C++
Copy
 
typedef struct _DMA_OPERATIONS {
  ULONG                               Size;
  PPUT_DMA_ADAPTER                    PutDmaAdapter;
  PALLOCATE_COMMON_BUFFER             AllocateCommonBuffer;
  PFREE_COMMON_BUFFER                 FreeCommonBuffer;
  PALLOCATE_ADAPTER_CHANNEL           AllocateAdapterChannel;
  PFLUSH_ADAPTER_BUFFERS              FlushAdapterBuffers;
  PFREE_ADAPTER_CHANNEL               FreeAdapterChannel;
  PFREE_MAP_REGISTERS                 FreeMapRegisters;
  PMAP_TRANSFER                       MapTransfer;
  PGET_DMA_ALIGNMENT                  GetDmaAlignment;
  PREAD_DMA_COUNTER                   ReadDmaCounter;
  PGET_SCATTER_GATHER_LIST            GetScatterGatherList;
  PPUT_SCATTER_GATHER_LIST            PutScatterGatherList;
  PCALCULATE_SCATTER_GATHER_LIST_SIZE CalculateScatterGatherList;
  PBUILD_SCATTER_GATHER_LIST          BuildScatterGatherList;
  PBUILD_MDL_FROM_SCATTER_GATHER_LIST BuildMdlFromScatterGatherList;
  PGET_DMA_ADAPTER_INFO               GetDmaAdapterInfo;
  PGET_DMA_TRANSFER_INFO              GetDmaTransferInfo;
  PINITIALIZE_DMA_TRANSFER_CONTEXT    InitializeDmaTransferContext;
  PALLOCATE_COMMON_BUFFER_EX          AllocateCommonBufferEx;
  PALLOCATE_ADAPTER_CHANNEL_EX        AllocateAdapterChannelEx;
  PCONFIGURE_ADAPTER_CHANNEL          ConfigureAdapterChannel;
  PCANCEL_ADAPTER_CHANNEL             CancelAdapterChannel;
  PMAP_TRANSFER_EX                    MapTransferEx;
  PGET_SCATTER_GATHER_LIST_EX         GetScatterGatherListEx;
  PBUILD_SCATTER_GATHER_LIST_EX       BuildScatterGatherListEx;
  PFLUSH_ADAPTER_BUFFERS_EX           FlushAdapterBuffersEx;
  PFREE_ADAPTER_OBJECT                FreeAdapterObject;
  PCANCEL_MAPPED_TRANSFER             CancelMappedTransfer;
} DMA_OPERATIONS, *PDMA_OPERATIONS;


Members
Size 
The size, in bytes, of this DMA_OPERATIONS structure.

PutDmaAdapter 
A pointer to a system-defined routine to free a DMA_ADAPTER structure. For more information, see PutDmaAdapter.

AllocateCommonBuffer 
A pointer to a system-defined routine to allocate a physically contiguous DMA buffer. For more information, see AllocateCommonBuffer.

FreeCommonBuffer 
A pointer to a system-defined routine to free a physically contiguous DMA buffer previously allocated by AllocateCommonBuffer. For more information, see FreeCommonBuffer.

AllocateAdapterChannel 
A pointer to a system-defined routine to allocate a channel for DMA operations. For more information, see AllocateAdapterChannel.

FlushAdapterBuffers 
A pointer to a system-defined routine to flush data from the system or bus-master adapter's internal cache after a DMA operation. For more information, see FlushAdapterBuffers.

FreeAdapterChannel 
A pointer to a system-defined routine to free a channel previously allocated for DMA operations by AllocateAdapterChannel. For more information, see FreeAdapterChannel.

FreeMapRegisters 
A pointer to a system-defined routine to free map registers allocated for DMA operations. For more information, see FreeMapRegisters.

MapTransfer 
A pointer to a system-defined routine to begin a DMA operation. For more information, see MapTransfer.

GetDmaAlignment 
A pointer to a system-defined routine to obtain the DMA alignment requirements of the controller. For more information, see GetDmaAlignment.

ReadDmaCounter 
A pointer to a system-defined routine to obtain the current transfer count for a DMA operation. For more information, see ReadDmaCounter.

GetScatterGatherList 
A pointer to a system-defined routine that allocates map registers and creates a scatter/gather list for DMA. For more information, see GetScatterGatherList.

PutScatterGatherList 
A pointer to a system-defined routine that frees map registers and a scatter/gather list after a DMA operation is complete. For more information, see PutScatterGatherList.

CalculateScatterGatherList 
A pointer to a system-defined routine that determines the buffer size needed to hold the scatter/gather list that describes an I/O data buffer. This member is available only in versions 2 and later of DMA_OPERATIONS. For more information, see CalculateScatterGatherList.

BuildScatterGatherList 
A pointer to a system-defined routine that allocates map registers and creates a scatter/gather list for DMA in a driver-supplied buffer. This member is available only in versions 2 and later of DMA_OPERATIONS. For more information, see BuildScatterGatherList.

BuildMdlFromScatterGatherList 
A pointer to a system-defined routine that builds an MDL corresponding to a scatter/gather list. This member is available only in versions 2 and later of DMA_OPERATIONS. For more information, see BuildMdlFromScatterGatherList.

GetDmaAdapterInfo 
A pointer to a system-defined routine that describes the capabilities of a bus-master DMA device or a system DMA controller. GetDmaAdapterInfo is available only in version 3 of DMA_OPERATIONS. For more information, see GetDmaAdapterInfo.

GetDmaTransferInfo 
A pointer to a system-defined routine that describes the allocation requirements for a scatter/gather list. This routine replaces CalculateScatterGatherList. GetDmaTransferInfo is available only in version 3 of DMA_OPERATIONS. For more information, see GetDmaTransferInfo.

InitializeDmaTransferContext 
A pointer to a system-defined routine that initializes an opaque DMA transfer context. The operating system stores the internal status of a DMA transfer in this context. InitializeDmaTransferContext is available only in version 3 of DMA_OPERATIONS. For more information, see InitializeDmaTransferContext.

AllocateCommonBufferEx 
A pointer to a system-defined routine that allocates memory for a common buffer and maps this memory so that it can accessed both by the processor and by a DMA device. AllocateCommonBufferEx is available only in version 3 of DMA_OPERATIONS. For more information, see AllocateCommonBufferEx.

AllocateAdapterChannelEx 
A pointer to a system-defined routine that allocates the resources required for a DMA transfer and then calls the driver-supplied AdapterControl routine to initiate the DMA transfer. AllocateAdapterChannelEx is available only in version 3 of DMA_OPERATIONS. For more information, see AllocateAdapterChannelEx.

ConfigureAdapterChannel 
A pointer to a system-defined routine enables a custom function that is implemented by the DMA controller. ConfigureAdapterChannel is available only in version 3 of DMA_OPERATIONS. For more information, see ConfigureAdapterChannel.

CancelAdapterChannel 
A pointer to a system-defined routine that tries to cancel a pending request to allocate a DMA channel. CancelAdapterChannel is available only in version 3 of DMA_OPERATIONS. For more information, see CancelAdapterChannel.

MapTransferEx 
A pointer to a system-defined routine that sets up map registers to map the physical addresses in a scatter/gather list to the logical addresses that are required to do a DMA transfer. MapTransferEx is available only in version 3 of DMA_OPERATIONS. For more information, see MapTransferEx.

GetScatterGatherListEx 
A pointer to a system-defined routine that allocates resources required for a DMA transfer, builds a scatter/gather list, and then calls the driver-supplied AdapterListControl routine to initiate the DMA transfer. GetScatterGatherListEx is available only in version 3 of DMA_OPERATIONS. For more information, see GetScatterGatherListEx. This routine is a wrapper of AllocateAdapterChannelEx and MapTransferEx.

BuildScatterGatherListEx 
A pointer to a system-defined routine that builds a scatter/gather list in a caller-allocated buffer, and then calls the driver-supplied AdapterListControl routine to initiate the DMA transfer. BuildScatterGatherListEx is available only in version 3 of DMA_OPERATIONS. For more information, see BuildScatterGatherListEx.

FlushAdapterBuffersEx 
A pointer to a system-defined routine that flushes any data that remains in the system DMA controller's internal cache or in a bus-master adapter's internal cache at the end of a DMA transfer. For a device that uses a system DMA controller, this routine cancels the current DMA transfer on the controller if the transfer is not complete. FlushAdapterBuffersEx is available only in version 3 of DMA_OPERATIONS. For more information, see FlushAdapterBuffersEx.

FreeAdapterObject 
A pointer to a system-defined routine that releases the specified adapter object after a driver has completed all DMA operations. FreeAdapterObject is available only in version 3 of DMA_OPERATIONS. For more information, see FreeAdapterObject.

CancelMappedTransfer 
A pointer to a system-defined routine that cancels a mapped transfer. CancelMappedTransfer is available only in version 3 of DMA_OPERATIONS. For more information, see CancelMappedTransfer.

2,MaximumLength指单次DMA可以操作的最大长度。需要在IoGetDmaAdapter时指定,此处的长度会决定单次最大传输长度、最大map regs。

IoGetDmaAdapter会依据MaximunLength来返回一个最大长度,如果MaxmumLength在允许范围内,返回的map regs数量=(一个可以描述此长度的map regs + 1)。如果MaximunLength超过了最大长度,则会返回一个允许的最大长度对应的 map regs。对于Storage这类device,通常最大传输长度是1M,对应于256个map reg。如果此处的长度设为64k,则storage单次可以传输的最大长度由1M减至64k。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值