- 论坛徽章:
- 2
|
第9章 DMA
9.1 DMA:什么是DMA,它如何工作
Copyright © 1995,1997 Frank Durda IV , All Rights Reserved. 10 December 1996. Last Update 8 October 1997.
翻译 gvim
原文连接
http://www.freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/dma.html
直接内存访问(DMA)是一种传输数据的方式,它允许两个地址上的数据直接进行传输而无需CPU的介入。
DMA功能在不同计算机体系下的实现方式有所不同,因此这里的讨论只局限于IBM 个人计算机(IBM PC/AT以及它们的衍生系统)的DMA子系统的实现和工作方式上。
PC 上的DMA子系统使用的是Intel® 8237 DMA控制器。8237包含有四个DMA通道,这些通道可以被单独的编程,并且任何一个通道也可以在任何时刻被激活。
第一个DMA 控制器(0,1,2和3)在传输的时候一次只能移动一个字节(8-bits)。第二个DMA 控制器(4,5,6和7)在传输的时候一次可以从相邻内存空间里移动16-bits(2个字节)的数据。显然,进行传输的第一个字节一定来自偶数编号的地址上。
8237的每个通道上都有两个芯片信号引脚,一个是DRQ和-DACK。还有一些其他信号引脚,分别是 HRQ(请求保持信号), HLDA(应答保持信号), -EOP(过程结束信号), 和总线控制信号 –MEMR(内存读), -MEMW(内存写), -IOR(I/O读), -IOW(I/O写)。
8237 DMA 是一种“遥控型”的DMA控制器。这也就是说,在两个地址间移动的数据不会经过DMA芯片,也不会转储到DMA芯片上。因为这个特点,数据的DMA传输只可以在I/O端口和内存地址之间进行,而不可以发生在两个I/O端口或者两个内存区域之间。
注意:8237确实也可以工作在非“遥控型”的方式,只要把两个通道连接起来就可以进行内存到内存的DMA操作。不过在现实中的PC制造业中并没有制造商这样处理,因为DMA资源十分稀少,而且使用CPU进行内存间数据的移动比使用DMA要快不少。
在PC体系中,一般来说某个DMA通道仅在以下情况时被激活:如果某个硬件需要利用某个DMA通道进行数据的传输,它需要往DMA控制器的DRQ引脚发出请求信号。
9.1.1 DMA传输的例子
这里是一个例子,用来说明引发并执行DMA传输的步骤。在这个例子里,软盘控制器(FDC)从磁盘中读取一个字节,然后使用DMA将读取的数据存放在内存地址0x00123456上。
DMA 控制器检测到它的DRQ2引脚被触发。DMA控制器接下来首先需要验证DMA的2号通道已经被编程,并且该通道没有被屏蔽(即,可以被使用)。DMA还需要验证没有其他更高优先级的DMA通道是激活的(或者将要被激活)。仅当上面这些验证都通过了,DMA才会请求CPU释放对总线的控制权,转而由自己进行接管。DMA对总线控制权的请求,是通过发出HRQ(请求保持)信号来完成的,该信号被送往CPU。
CPU检测到HRQ信号,并将正在执行的指令执行完毕。一旦处理器不再需要总线,那CPU就释放它。现在,CPU的-MEMR, -MEMW, -IOR, -IOW 和其他一些信号线的引脚都处于高阻态(即不是高电平也不是低电平),接着CPU向DMA控制器发出HLDA信号,通知DMA控制器“从此刻开始,总线的控制权可以被它接管”。
虽然CPU当前不再拥有总线控制权,不过根据处理器的设计,它仍可能继续执行一些指令。但是随着CPU指令的执行,可能有一些指令/数据不在cache或者流水线中,这些内容只能从内存上取得,那么CPU也只有等待总线了。
现在,总线的控制权属于DMA控制器,DMA使用它自己的-MEMR, -MEMW, -IOR, -IOW 输出信号使用总线,并且将0x3456发送到总线的地址线上。这个地址就是数据将被写入的内存地址。
DMA接下来需要通知请求DMA传输的设备(译注:也就是FDC)知道,它请求的DMA传输可以开始了。该过程通过触发-DACK信号来完成(对软盘控制器来说,-DACK2被触发)。
现在,软盘控制器负责往总线的数据线上输出数据。如果软盘控制器不需要使用更多的时间将数据放到总线上(外设需要更多时间的话,它需要通过READY信号告诉DMA控制器),那么DMA会等待一个DMA时钟周期然后释放-MEMW和-IOR信号,这样内存控制器就锁住总线上的数据,并且将它们存入指定的内存地址,接着FDC会被应答它发送的数据已经被传输完毕。
因为一个DMA时钟周期就可以传输一个字节,所以FDC需要传输的数据已经完成,现在FDC可以释放DRQ2信号,此刻DMA也就知道FDC不再需要自己。接着DMA释放-DACK2应答信号,通知FD以后不可以再往总线上发送数据。
DMA控制器接下来检测是否其他DMA通道还有任何工作需要处理。如果所有通道上的DRQ引脚都没有收到请求,那么DMA控制器就可以完成它的这次工作,并将自己的-MEMR, -MEMW, -IOR, -IOW 引脚和地址信号都放在高阻态。
最后,DMA撤消HRQ信号。CPU检测到HRQ撤消之后,接着撤消HOLDA信号。现在CPU激活自己的-MEMR, -MEMW, -IOR, -IOW 和地址线。这样CPU就可以通过访问主存储器和外设(译注:可以取得cache中缺失的指令/数据)而继续它的工作了。
对于典型的软盘扇区,上面的过程需要循环512次,一次处理一个字节。每次字节被传输之后,DMA上的地址寄存器会被递增,DMA上用来记录剩余字节传输个数的计数器会被递减。
当计数器被减到0的时候,DMA引发EOP信号,用来表明计数器已经递减到0,当前已经没有需要被移动的数据了。DMA控制器的下一次使用需要CPU对其进行编程。这一事件也被称为终结计数(TC: Terminal Count)。因为只有一个EOP信号,所以在任意时刻只有一个DMA通道可以被激活。当前的活动DMA通道一定是正在处理任务的那个通道。
如果外设想在对缓冲的传输过程完毕之后产生一个中断,它可以检测自己的-DACKn 和EOP信号是否在某一时刻同时为高电平。如果是这样,就意味着DMA不再为这个外设传输任何多余信息(除非有CPU的干涉)。外设现在可以触发某个中断信号去通知处理器。在PC体系中,DMA芯片自己不会产生中断。外设和它相关的硬件负责产生中断。因为如此,也就允许外设在使用DMA之后可以不使用中断。
需要理解的一个很重要的问题是:尽管当DMA发出请求的时候,CPU总是将总线控制权释放给DMA,不过这个过程对应用程序和操作系统来讲都是不可见的。它们DMA的感知仅在于“当DMA活动时,CPU用于执行指令的总时间的细微变化”。因为如此,处理器为了得知某个DMA传输完毕的确切时间,它就必须轮询外设、轮询DMA芯片上的寄存器、或者接收来自外设的中断。
9.1.2 DMA页面寄存器与16Meg地址空间限制
你可能在前面已经意识到,DMA并没有在总线的地址线上将我们最开始要求的0x00123456放在上面,而是把0x3456放在地址线上。这里解释这样做的原因。
在IBM PC设计之初,IBM决定在PC中同时采用DMA和中断控制器,而这两个东西却是专为8085设计的(8085是一款8-bit处理器,拥有16bit(64K)地址空间)。由于IBM PC支持多于64K的内存,因此需要对DMA做一些处理让它可以读/写高于64K的内存区域。IBM 用来解决这个问题的方法是:为每个DMA通道增加一个额外的数据锁存器,用来保留读取或写入地址的高位。当DMA通道被激活时,锁存器的内容被放上地址线,并且一直保留直到该通道上的DMA操作完成。IBM 称这个锁存器为“页面寄存器”。
所以在我们上面的例子中,DMA需要将地址的0x3456部分送上总线,同时2号DMA通道的页面寄存器需要把0x0012xxxx放在总线上。这两部分一起形成一个完整的内存访问地址。
因为页面寄存锁存器是和DMA芯片独立的,因此DMA读/写的内存区域不可以跨越64K物理界限。例如,如果DMA当前访问内存地址0xffff,在传输完毕之后DMA需要递增它的地址寄存器,那么下一次的DMA操作将访问0x0000而不是0x10000。这样做的结果或许并不是你期望的。
注意:“物理”64K界限不应该和8086模式的64K“段”混淆,后者是由段寄存器和偏移寄存器内容算术叠加在一起而创建。页面寄存器没有地址的重叠,并且是算术或在一起。
接下来更深一步讨论。PC/AT上那个额外的DMA地址锁存器的长度只有8bits,因此只能寻址8+16=24bits,这也就意味着DMA只能够在内存区间0-16Meg之间寻址。对于新出现的多于16Meg内存的计算机,PC兼容的标准DMA不可以访问高于16Meg的内存区间。
为了解决这个困境,操作系统需要在16Meg以下的内存中保留一块RAM缓冲区(该缓冲区仍然不能跨越64K界限)。然后DMA被编程,完成外设和这块缓冲区之间的数据传输。一旦DMA将数据移入这块缓冲区之后,操作系统还需要将数据拷贝到真正存放它的地方去。
当需要将高于16Meg内存区间的内容写到支持DMA的外设时,数据需要首先从它的原始内存区间拷贝到某个低于16Meg的缓冲区,接着DMA开始处理缓冲区到硬件的数据传输。在FreeBSD中,这些保留的缓冲区被称之为“Bounce Buffers(回弹缓冲)”。在MS-DOS®中,这些缓冲有时候称之为“Smart Buffers(智能缓冲)”
注意:新实现的8237(称为82374)允许16位的页面寄存器长度,用来实现32bit地址空间的完全访问(从而不在需要bounce buffers)。
9.1.3 DMA 操作模式和设置
8237DMA可以在几种模式中操作。主要的模式如下:
Single
一次一个字节(或字)被传输。对于每个剩余的字节,DMA必须释放总线,然后重新请求总线控制权。这个模式常被用在那些不可以直接传输整个数据块的设备中。外设在每次传输就绪时都需要对DMA发出请求。
The standard PC-compatible floppy disk controller (NEC 765) only has a one-byte buffer, so it uses this mode.
PC兼容的标准磁盘控制器(NEC 765)仅有一个字节的缓冲区,因此它采用这个模式。
Block/Demand
只要DMA请求得到系统总线,就可以传输整个数据块(数据块最大不能超过64K)。如果外设需要更多的时间,它只需要简单的触发READY信号以挂起传输过程。READY不应该由于“为进行低速设备的传输”而被滥用,这时应使用单字节传输模式。
Block 和 Demand模式的区别是:一旦Block模式的传输启动之后,传输过程会一直持续到传输计数器递减到0为止。DRQ仅在-DACK触发之后才会被触发。Demand模式在DRQ撤销之前可以传输多个字节,当DRQ撤销的时候DMA传输过程被挂起,并将总线归还给CPU。当DRQ稍后再次被触发,传输过程就从它先前挂起的地方恢复。
旧的硬盘控制器使用Demand模式,这样的状况一直持续到CPU变的足够快速之前。在这以后,使用CPU进行数据传输的效率比使用Demand模式的DMA传输的效率高。特别是,当需要传输的内存区间高于16Meg的时候,CPU传输的效率更高。
Cascade
该模式允许DMA通道请求总线,但是接下来负责往总线上放地址信息的是有关的外围设备,而不是DMA。该机制也用来实现一种称之为“Bus Mastering”的技术。
处于Cascade模式的DMA通道接管总线控制权,但在DMA激活的时候它并不像处于其他模式那样负责向总线上输出地址和I/O控制信号。DMA仅仅为活动DMA通道触发-DACK信号。
这时,连接在DMA通道上的外设负责为发出地址信息和总线控制信号。外设对系统总线有完全的控制权,并且可以在任意低于16Meg的内存范围内进行数句的读/写。当外设的总线活动结束之后,它撤销DRQ信号,DMA控制器就可以将总线控制权返回给CPU(或者交给其他DMA通道)。
Cascade模式可以用来将多个DMA控制器链接在一起,而且这也正是PC体系中的4号DMA通道的实际使用方式。当外设在0,1,2或者3号DMA通道上请求总线的时候,从DMA控制器触发HLDREQ,但是这条信号线实际上是连接在主DMA控制器上的DRQ4(而不是直接发往CPU)。主DMA控制器此时认为在4号通道上有任务需要处理,因此它使用HLDREQ信号向CPU请求总线。一旦CPU可以将总线控制权转交给主DMA控制器,-DACK4信号有效,该信号线实际上被连接到从DMA控制器上的HLDA信号引脚上。接下来,从DMA控制器开始为DMA通道(某个请求总线事务的0,1,2或3号通道)进行数据传输,或者从DMA也可以将总线转交给具有bus-mastering能力的外设进行自行管理,比如SCSI控制器。
由于以上信号连线的排布,只有0,1,2,3,5,6和7号DMA通道可以被PC/AT系统上的外设使用。
注意:早期IBM PC电脑上的0号DMA通道被保留用作刷新操作。但在现代系统上,该通道一般都可以被外设使用。
当外设支持Bus Mastering进而对总线进行操作的时候,需要特别注意的是:当外设占有系统总线的时候,它连续不断地与内存进行数据的传输。如果外设不支持Bus Mastering操作,那它必须频繁的释放总线控制权,以便系统可以在主存储器上执行刷新操作。
用于所有PC上作为主存储器的动态DRAM必须频繁的进行访问,这样才可以保持已经存储在内存单元里(内存电容单元已经被充电)的比特位。动态DRAM本质上是由几百万个电容组成,每个电容保持一个比特位的数据。这些电容要么在充电之后存储电能的情况下表示一个1,要么在释放电能的情况下表示一个0。因为所有电容都会漏损电能,所以必须在规定的时间段内对电容补充电能,这样才能保证表示1的那些比特位的数据不会丢失。RAM中适当位置的内存单元的充电工作实际上由RAM芯片完成,但是当计算机上的其他设备进行这项工作的时候RAM芯片必须被通知到,这样刷新操作才不至于因为计算机对RAM的一般访问而受到干扰。如果计算机不能在几毫秒的时间内对内存数据进行刷新,内存中存储的数据就会被破坏。
因为对内存的读/写周期可以作为内存单元的刷新周期(动态RAM的刷新周期实际上是一次不完全的存储器读周期),所以只要外设控制器连续的在顺序内存区间内读取或写入数据,就可以对内存进行刷新。
Bus-mastering可以用在一些SCSI主机接口和其他一些高性能外设控制器上。
Autoinitialize
This mode causes the DMA to perform Byte, Block or Demand transfers, but when the DMA transfer counter reaches zero, the counter and address are set back to where they were when the DMA channel was originally programmed. This means that as long as the peripheral requests transfers, they will be granted. It is up to the CPU to move new data into the fixed buffer ahead of where the DMA is about to transfer it when doing output operations, and to read new data out of the buffer behind where the DMA is writing when doing input operations.
This technique is frequently used on audio devices that have small or no hardware “sample” buffers. There is additional CPU overhead to manage this “circular” buffer, but in some cases this may be the only way to eliminate the latency that occurs when the DMA counter reaches zero and the DMA stops transfers until it is reprogrammed.
9.1.4 对DMA编程
被编程的DMA通道在载入任何设置之前必须被“屏蔽”。这是因为硬件可能会不可思议的为通道引发DRQ信号,DMA可能会对信号进行响应,这个响应甚至发生在并非所有参数都已被载入或者更新完成之前。
被屏蔽之后,主机必须向DMA控制器指明以下信息:传输的方向(内存->I/O或是I/O->内存),用于传输的DMA操作模式(Single, Block, Demand, Cascade, etc),最后是地址和传输长度。DMA接收的传输长度比你期望DMA进行传输的总长度少1。地址和长度的信息分别被写入两个同样是8-bit的I/O端口(而它们的有效位数是16位,因此需要将16位数据分为LSB和MSB两部分,并在这些端口上分两次写入),所以端口的第一次写入必须是地址/长度数据的LSB字节,第二次写入的是MSB字节。
接着,不要忘记更新页面寄存器这个额外的DMA寄存器,它们可以分别在另一个I/O端口集合里访问。
一旦所有的设置都已就绪,DMA通道就可以去掉屏蔽了。DMA通道现在可以认为处于待命状态,并且只要它的DRQ信号线上有信号激发,它就可以进行响应。
更精细的编程细节可以参考有关8237的硬件数据书籍。你仍然需要参考PC系统上的I/O端口映射,这些映射描述了DMA和页面寄存器端口放在什么地方。下面有一份完整的端口映射表。
9.1.5 DMA Port Map
所有基于IBM-PC和PC/AT的系统都将DMA硬件放在相同的I/O端口。全部的端口附在下面的列表中。付给2号DMA控制器的端口在非AT设计的计算机中是无定义的。
9.1.5.4 0x400-0x4ff 82374 Enhanced DMA Registers
Intel 82374 EISA系统组件(ESC)于1996年年初被引入,它包含了一个DMA控制器。这颗独立的芯片,不仅将8237的功能封装在里面,同时也封装了其他PC兼容的核心外部组件。这颗芯片同时面向EISA和PCI平台,并且提供现代DMA特性,比如scatter-gather(汇聚/分散)、循环缓冲区,当然还可以直接访问任意32位地址内的地址空间。
即使要使用这些新特性,代码也应该同时提供兼容过去16年间的系统里拥有的类似功能,对过去PC的兼容是有价值的。由于兼容性的原因,每次传输的时候,82374的一些寄存器必须在对传统8237寄存器编程之后才能被编程。为了提供向后的软件兼容性,对传统8237的寄存器写入数据的同时,强制将82374的一些增强寄存器设置为0。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/11799/showart_257151.html |
|