KDmaAdapter类:
一、Overview
KDmaAdapter提供了对系统DMA适配器对象的一种抽象。像KController类一样,这个类主要是提供了串行控制一种特定资源的方法,对于这个类来说,要控制的资源就是一个DMA通道或者总线主控适配器。
这个类使一个驱动程序可以识别处一个DMA通道的特征,并且当驱动被授予控制通道(channel)的权限时请求一个回调函数的执行。(channel这个名次使用广泛,它不仅指工业标准结构(ISA)类型的控制传输机制,而且指在主板上不需要任何资源情况下的总线控制传输机制)如果驱动获得了通道控制权,系统将在DISPATCH_LEVEL中断级上调用驱动程序提供的回调函数,并且初始化传输操作。
KDmaAdapter类并不驱动DMA传输,传输是KDmaTransfer类的任务。
这个类的目的只是要封装系统识别一个通道的机制,并实现对它的串行化控制。
二、Member Functions
1、KDmaAdapter - Constructor (3 forms)构造函数三种原型
2、Initialize - Initializes the object when in an invalid state (4 forms)初始化对象
3、Invalidate - Removes the object from an initialized state在初始化了的状态释放资源
4、IsValid - Test if the object is initialized测试对象是否已经初始化
5、ReadCounter - Get the current counter value获得当前DMA的计数器的值
6、QueueSynchRequest - Request invocation of callback function when access to the channel is granted当获得通道控制权时请求调用回调函数
7、Release - Release the adapter channel释放适配器通道
8、ReleaseRegisters - Release mapping registers释放映射过来的寄存器资源(在释放Adapter以后)
9、Description - Accessor to retrieve adapter description返回当前适配器的描述信息(一个PDEVICE_DESCRIPTION结构体指针)
10、MaxRegisters - Accessor to retrieve maximum register count获取最大寄存器数量
11、Channel - Accessor to retrieve the channel number获取通道的序号
12、operator PADAPTER_OBJECT重载操作符,获取底层系统适配器对象的地址
KDmaTransfer类:
一、Overview
这个类负责管理DMA的传输(transfer)。一个DMA调用是在内存和一个设备之间的一次数据传输,这里的设备要由作用于传输的总线周期不被CPU生成这个事实来区分。相反,总线周期或者由设备自身产生,或者由系统主板上的一个DMA控制器产生。
那些能够为一次传输产生总线周期的设备被归类为总线主设备,那些依靠系统DMA控制器的设备被归类为从设备。存取从设备通常也被归类为系统DMA传输。
作为DMA传输的源或目的的内存区域,通常是物理连续的。这个条件很必要因为系统DMA控制器和一些其他总线控制器规定只能从单一物理地址存取。某些总线控制器可以从多个物理地址存取,并且这种特性被成为对scatter/gather(分散/聚合)的支持。一个支持scatter/gather的总线控制器为DMA传输请求的内存不要求是物理连续的。
依赖于DMA传输送据的设备在构造一个KDevice派生类时经常设置DO_DIRECT_IO标志位。用DMA进行传输的驱动程序通常需要串行化处理IRP。这样做使系统在授权DMA通道控制权时可以确定哪个是当前的请求。
KDmaTransfer类的使用需要一个KDmaAdapter类的对象。一个驱动程序必须首先创建一个KDmaAdapter类的对象,这个对象要符合相应要传输数据的设备。来自适配器对象的信息告诉了传输对象传输的类型(是总线控制器还是系统控制)。适配器信息也告诉了传输对象是不是支持scatter/gather,并且对于从设备来说将使用哪个DMA通道。
一个KDmaAdapter实例可以有选择的使用KCommonDmaBuffer类实例。这是一个保证可以被适配器对象访问的物理上连续的内存空间。传输(Transfer)对象负责从commom buffer里拷贝数据,或将数据考到common里去。当然,前提是在KDmaTransfer构造是提供了这么一个common buffer。
与DMA传输相关的过程是这样进行的(*****):
1、驱动程序构造一个KDmaTransfer类实例。它可以是一个全局的静态实例、一个从heap(内存堆)里分配的实例、或者一个设备对象的成员。
2、当操作被请求时,驱动程序调用Initiate()函数。这个函数有两种原型。如果用没有参数的默认形式来创建对象,驱动程序必须调用扩展形式的Initiate()函数。
3、Initiate()函数申请了适配器,完成传输的初始化部分,并且调用驱动的回调函数。
4、回调函数通知设备说,当前部分已经准备好了,然后就开始传输当前的这部分数据了。
5、驱动程序(通常用中断)检测一下当前部分传输完了没,完了的话就执行Continue()函数。
6、Continue()函数完成当前部分的传输,并且如果有必要的话建立下一部分的数据,再次调用驱动程序的回调函数。
7、回调函数检查一下是否还有需要传输的数据。如果还有,就返回到第3步后面继续。如果没有了,就调用Terminate()函数,并且删除KDmaTransfer对象。
注意一点,所有以上步骤描述的是DMA逻辑的同步化操作。KDmaTransfer类中没有包含反对异步处理的成员函数。这就意味着只有在一个被上下文描述为同步化操作的状态下,才能安全的使用KDmaTransfer类的成员函数。任何会影响到DMA操作的异步事件(比如说cancel例程的调用)都必须被DMA状态机进行同步化。进行这种同步化的符合逻辑的地方应该是在驱动程序已经控制了它的时候,比如说,驱动程序回调例程。
二、Member Functions
1、KDmaTransfer - Constructor构造函数
2、Initiate - Initiate the transfer初始化传输
3、GetTransferDescriptors - Retrieve the physical addresses and sizes for the current segment.获得当前部分的物理地址和大小
4、Continue - Called to continue the transfer after each segment每一部分传完后都要调用它继续传输
5、Terminate - Terminate the transfer结束传输
6、Direction - Accessor to retrieve the direction of the transfer获取传输的方向(FromDeviceToMemory或FromMemoryToDevice)
7、BytesRemaining - Returns the number of bytes remaining to be transferred.返回剩余待传输的字节数
KCommonDmaBuffer类:
一、Overview
系统为DMA提供了特殊的缓冲区(buffer),并且DriverWorks用此类对这个buffer对象进行了封装。这个common buffer对于CPU和指定的DMA适配器来说都是可用的,并且可以向适配器保证是物理上连续的内存区。
一个common buffer对于总线控制器会发送未请求数据过来的驱动程序,是很有帮助的。因为这个buffer是始终可用的,总线控制器可以在没有跟驱动协商的情况下就往里面写数据,并且同时用一个中断告诉驱动:现在缓冲区里有需要你处理的数据了。
Common buffer对于使用自动初始化模式对系统DMA控制器进行初始化的从设备来说,也是很有用的。在这种模式下,当传输完成后,控制器将把自己重设到传输前的可编程内存区。这使得从设备可以在没有驱动程序干涉的情况下进行数据传输。
Common buffer使用了系统资源。物理连续的内存区应该节约使用。支持scatter/gather的设备并不需要物理连续的内存,所以对于这类设备可能会禁用common buffer。
二、Member Functions
1、KCommonDmaBuffer – Constructor (2 forms).构造函数两种原型,这里用的是非分页内存(non-paged memory)
2、Initialize – Initializes the object when in an invalid state.初始化
3、Invalidate – Removes the object from an initialized state.删除对象
4、IsValid – Test if the object is initialized.测试对象是否已经初始化
5、Mdl – Accessor to retrieve associated memory descriptor object.获得内存描述符对象,一个KMemory对象
6、Size – Accessor to retrieve size.获取缓存的大小,以字节为单位
7、VirtualAddress – Accessor to retrieve virtual address.获得虚拟地址,buffer的内核模式地址
8、LogicalAddress – Accessor to retrieve logical (physical) address.获得逻辑(物理)地址
----------------
§ 译自"DriverWorks帮助文件" §
§ 李文凯 2008年03月31日 §
----------------