Linux内核DMA机制

上传人:m**** 文档编号:493825961 上传时间:2023-04-09 格式:DOC 页数:29 大小:88.50KB
返回 下载 相关 举报
Linux内核DMA机制_第1页
第1页 / 共29页
Linux内核DMA机制_第2页
第2页 / 共29页
Linux内核DMA机制_第3页
第3页 / 共29页
Linux内核DMA机制_第4页
第4页 / 共29页
Linux内核DMA机制_第5页
第5页 / 共29页
点击查看更多>>
资源描述

《Linux内核DMA机制》由会员分享,可在线阅读,更多相关《Linux内核DMA机制(29页珍藏版)》请在金锄头文库上搜索。

1、-DMA控制器硬件构造1DMA通道使用的地址3DMA操作函数4DMA映射61建立一致 DMA 映射72建立流式 DMA 映射83分散/集中映射10DMA池11一个简单的使用DMA 例子16DMA控制器硬件构造DMA允许外围设备和主存之间直接传输 I/O 数据, DMA 依赖于系统。每一种体系构造DMA传输不同,编程接口也不同。 数据传输可以以两种方式触发:一种软件请求数据,另一种由硬件异步传输。 在第一种情况下,调用的步骤可以概括如下以read为例: 1在进程调用 read 时,驱动程序的方法分配一个 DMA 缓冲区,随后指示硬件传送它的数据。进程进入睡眠。 2硬件将数据写入 DMA 缓冲区并

2、在完成时产生一个中断。 3中断处理程序获得输入数据,应答中断,最后唤醒进程,该进程现在可以读取数据了。 第二种情形是在 DMA 被异步使用时发生的。以数据采集设备为例: 1硬件发出中断来通知新的数据已经到达。 2中断处理程序分配一个DMA缓冲区。 3外围设备将数据写入缓冲区,然后在完成时发出另一个中断。 4处理程序利用DMA分发新的数据,唤醒任何相关进程。 网卡传输也是如此,网卡有一个循环缓冲区通常叫做 DMA 环形缓冲区建立在与处理器共享的存中。每一个输入数据包被放置在环形缓冲区中下一个可用缓冲区,并且发出中断。然后驱动程序将网络数据包传给核的其它局部处理,并在环形缓冲区中放置一个新的 DM

3、A 缓冲区。 驱动程序在初始化时分配DMA缓冲区,并使用它们直到停顿运行。 DMA控制器依赖于平台硬件,这里只对i386的8237 DMA控制器做简单的说明,它有两个控制器,8个通道,具体说明如下: 控制器1: 通道0-3,字节操作, 端口为 00-1F 控制器2: 通道 4-7, 字操作, 端口咪 C0-DF - 所有存放器是8 bit,与传输大小无关。 - 通道 4 被用来将控制器1与控制器2级联起来。 - 通道 0-3 是字节操作,地址/计数都是字节的。 - 通道 5-7 是字操作,地址/计数都是以字为单位的。 - 传输器对于0-3通道必须不超过64K的物理边界,对于5-7必须不超过12

4、8K边界。 - 对于5-7通道page registers 不用数据 bit 0, 代表128K页 - 对于0-3通道page registers 使用 bit 0, 表示 64K页 DMA 传输器限制在低于16M物理存里。装入存放器的地址必须是物理地址,而不是逻辑地址。 对于0-3通道来说地址对存放器的映射如下: A23 . A16 A15 . A8 A7 . A0 (物理地址) | . | | . | | . | | . | | . | | . | | . | | . | | . | P7 . P0 A7 . A0 A7 . A0 | Page | Addr MSB | Addr LSB

5、| (DMA 地址存放器)对于5-7通道来说地址对存放器的映射如下: A23 . A17 A16 A15 . A9 A8 A7 . A1 A0 (物理地址) | . | . . | . | . . (没用) | . | . . P7 . P1 (0) A7 A6 . A0 A7 A6 . A0 | Page | Addr MSB | Addr LSB | (DMA 地址存放器)通道 5-7 传输以字为单位, 地址和计数都必须是以字对齐的。 在include/asm-i386/dma.h中有i386平台的8237 DMA控制器的各处存放器的地址及存放器的定义,这里只对控制存放器加以说明: DMA

6、 Channel Control/Status Register (DCSR*) 第31位 说明是否开场 第30位 选定Descriptor和Non-Descriptor模式 第29位 判断有无中断 第8位 请求处理 Request Pending 第3位 Channel是否运行 第2位 当前数据交换是否完成 第1位 是否由Descriptor产生中断 第0位 是否由总线错误引起中断 DMA通道使用的地址DMA通道用dma_chan构造数组表示,这个构造在kernel/dma.c中,列出如下: struct dma_chan int lock;const char *device_id;sta

7、tic struct dma_chan dma_chan_busyMA*_DMA_CHANNELS = 4 = 1, cascade ,;如果dma_chan_busyn.lock!= 0表示忙,DMA0保存为DRAM更新用,DMA4用作级联。DMA 缓冲区的主要问题是,当它大于一页时,它必须占据物理存中的连续页。 由于DMA需要连续的存,因而在引导时分配存或者为缓冲区保存物理 RAM 的顶部。在引导时给核传递一个mem=参数可以保存 RAM 的顶部。例如,如果系统有 32MB 存,参数mem=31M阻止核使用最顶部的一兆字节。稍后,模块可以使用下面的代码来访问这些保存的存: dmabuf =

8、 ioremap( 0*1F00000 /* 31M */, 0*100000 /* 1M */);分配 DMA 空间的方法,代码调用 kmallocGFP_ATOMIC 直到失败为止,然后它等待核释放假设干页面,接下来再一次进展分配。最终会发现由连续页面组成的DMA 缓冲区的出现。 一个使用 DMA 的设备驱动程序通常会与连接到接口总线上的硬件通讯,这些硬件使用物理地址,而程序代码使用虚拟地址。基于 DMA 的硬件使用总线地址而不是物理地址,有时,接口总线是通过将 I/O 地址映射到不同物理地址的桥接电路连接的。甚至*些系统有一个页面映射方案,能够使任意页面在外围总线上表现为连续的。 当驱动

9、程序需要向一个 I/O 设备例如扩展板或者DMA控制器发送地址信息时,必须使用 virt_to_bus 转换,在承受到来自连接到总线上硬件的地址信息时,必须使用 bus_to_virt 了。 DMA操作函数因为 DMA 控制器是一个系统级的资源,所以核协助处理这一资源。核使用 DMA 注册表为 DMA 通道提供了请求/释放机制,并且提供了一组函数在 DMA 控制器中配置通道信息。 DMA 控制器使用函数request_dma和free_dma来获取和释放 DMA 通道的所有权,请求 DMA 通道应在请求了中断线之后,并且在释放中断线之前释放它。每一个使用 DMA 的设备也必须使用中断信号线,否

10、则就无法发出数据传输完成的通知。这两个函数的声明列出如下在kernel/dma.c中: int request_dma(unsigned int channel, const char *name); void free_dma(unsigned int channel);DMA 控制器被dma_spin_lock 的自旋锁所保护。使用函数claim_dma_lock和release_dma_lock对获得和释放自旋锁。这两个函数的声明列出如下在kernel/dma.c中: unsigned long claim_dma_lock(); 获取 DMA 自旋锁,该函数会阻塞本地处理器上的中断,因

11、此,其返回值是标志值,在重新翻开中断时必须使用该值。 void release_dma_lock(unsigned long flags); 释放 DMA 自旋锁,并且恢复以前的中断状态。 DMA 控制器的控制设置信息由RAM 地址、传输的数据以字节或字为单位,以及传输的方向三局部组成。下面是i386平台的8237 DMA控制器的操作函数说明在include/asm-i386/dma.h中,使用这些函数设置DMA控制器时,应该持有自旋锁。但在驱动程序做I/O 操作时,不能持有自旋锁。 void set_dma_mode(unsigned int channel, char mode); 该函数

12、指出通道从设备读DMA_MODE_WRITE或写DMA_MODE_READ数据方式,当mode设置为 DMA_MODE_CASCADE时,表示释放对总线的控制。 void set_dma_addr(unsigned int channel, unsigned int addr); 函数给 DMA 缓冲区的地址赋值。该函数将 addr 的最低 24 位存储到控制器中。参数 addr 是总线地址。 void set_dma_count(unsigned int channel, unsigned int count);该函数对传输的字节数赋值。参数 count 也代表 16 位通道的字节数,在此情

13、况下,这个数字必须是偶数。 除了这些操作函数外,还有些对DMA状态进展控制的工具函数: void disable_dma(unsigned int channel); 该函数设置制止使用DMA 通道。这应该在配置 DMA 控制器之前设置。 void enable_dma(unsigned int channel); 在DMA 通道中包含了合法的数据时,该函数激活DMA 控制器。 int get_dma_residue(unsigned int channel); 该函数查询一个 DMA 传输还有多少字节还没传输完。函数返回没传完的字节数。当传输成功时,函数返回值是0。 void clear_d

14、ma_ff(unsigned int channel) 该函数去除 DMA 触发器flip-flop,该触发器用来控制对 16 位存放器的访问。可以通过两个连续的 8 位操作来访问这些存放器,触发器被去除时用来选择低字节,触发器被置位时用来选择高字节。在传输 8 位后,触发器会自动反转;在访问 DMA 存放器之前,程序员必须去除触发器将它设置为*个状态。 DMA映射一个DMA映射就是分配一个 DMA 缓冲区并为该缓冲区生成一个能够被设备访问的地址的组合操作。一般情况下,简单地调用函数virt_to_bus 就设备总线上的地址,但有些硬件映射存放器也被设置在总线硬件中。映射存放器mapping register是一个类似于外围设备的虚拟存等价物。在使用这些存放器的系统上,外围设备有一个相对较小的、专用的地址区段,可以在此区段执行 DMA。通过映射存放器,这些地址被重映射到系统 RAM。映射存放器具有一些好的特性,包括使分散的页面在设备地址空间看起来是连续的。但不是所有的体系构造都有映射存放器,特别地,PC 平台没有映射存放器。 在*些情况下,为设备设置有用的地址也意味着需要构造一个反弹bounce缓冲区。例如,当驱动程序试图在一个不能被外围设备访问的地址一个高端存地址上执行 DMA 时,反弹缓冲区被创立。然后,按照需要,数据被复制到反弹缓冲区,或者从反弹

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 医学/心理学 > 基础医学

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号