免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2886 | 回复: 5
打印 上一主题 下一主题

DMA的疑惑 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-04-10 16:00 |只看该作者 |倒序浏览
下面的这段话摘自互联网上,我搞不懂"实际的传输也不借助慢速的ISA DMAC来进行,而是由内嵌在PCI卡中的DMA电路(比传统的ISA DMAC要快)来完成"这句话的意思,难道是说每个PCI卡上都有一个DMAC?

DMA是外设与主存之间的一种数据传输机制。一般来说,外设与主存之间存在两种数据传输方法:(1)Pragrammed I/O(PIO)方法,也即由CPU通过内存读写指令或I/O指令来持续地读写外设的内存单元(8位、16位或32位),直到整个数据传输过程完成。(2)DMA,即由DMA控制器(DMA Controller,简称DMAC)来完成整个数据传输过程。在此期间,CPU可以并发地执行其他任务,当DMA结束后,DMAC通过中断通知CPU数据传输已经结束,然后由CPU执行相应的ISR进行后处理。

   DMA技术产生时正是ISA总线在PC中流行的时侯。因此,ISA卡的DMA数据传输是通过ISA总线控制芯片组中的两个级联8237 DMAC来实现的。这种DMA机制也称为“标准DMA”(standard DMA)。标准DMA有时也称为“第三方DMA”(third-party DMA),这是因为:系统DMAC完成实际的传输过程,所以它相对于传输过程的“前两方”(传输的发送者和接收者)来说是“第三方”。

   标准DMA技术主要有两个缺点:(1)8237 DMAC的数据传输速度太慢,不能与更高速的总线(如PCI)配合使用。(2)两个8237 DMAC一起只提供了8个DMA通道,这也成为了限制系统I/O吞吐率提升的瓶颈。

   鉴于上述两个原因,PCI总线体系结构设计一种成为“第一方DMA”(first-party DMA)的DMA机制,也称为“Bus Mastering”(总线主控)。在这种情况下,进行传输的PCI卡必须取得系统总线的主控权后才能进行数据传输。实际的传输也不借助慢速的ISA DMAC来进行,而是由内嵌在PCI卡中的DMA电路(比传统的ISA DMAC要快)来完成。Bus Mastering方式的DMA可以让PCI外设得到它们想要的传输带宽,因此它比标准DMA功能满足现代高性能外设的要求。

   随着计算机外设技术的不断发展,现代能提供更快传输速率的Ultra DMA(UDMA)也已经被广泛使用了。本为随后的篇幅只讨论ISA总线的标准DMA技术在Linux中的实现。记住:ISA卡几乎不使用Bus Mastering模式的DMA;而PCI卡只使用Bus Mastering模式的DMA,它从不使用标准DMA。

论坛徽章:
0
2 [报告]
发表于 2006-04-10 16:32 |只看该作者
这不说的很清楚么?记住:ISA卡几乎不使用Bus Mastering模式的DMA;而PCI卡只使用Bus Mastering模式的DMA,它从不使用标准DMA。

论坛徽章:
0
3 [报告]
发表于 2006-04-10 17:11 |只看该作者
1.standard dma 在南桥还是在北桥,或者其他地方?
2.现在isa基本上淘汰了,那么standard dma不就是多于的了?

论坛徽章:
5
4 [报告]
发表于 2006-04-10 17:46 |只看该作者
原帖由 qtdszws 于 2006-4-10 16:00 发表
下面的这段话摘自互联网上,我搞不懂"实际的传输也不借助慢速的ISA DMAC来进行,而是由内嵌在PCI卡中的DMA电路(比传统的ISA DMAC要快)来完成"这句话的意思,难道是说每个PCI卡上都有一个DMAC?


是的

论坛徽章:
0
5 [报告]
发表于 2006-04-11 08:35 |只看该作者
原帖由 qtdszws 于 2006-4-10 17:11 发表
1.standard dma 在南桥还是在北桥,或者其他地方?
2.现在isa基本上淘汰了,那么standard dma不就是多于的了?


1.标准dma应该是集成在南桥的

2.我想保留它主要是为了兼容吧。PC体系结构最大的成功就在于,即便是目前最新的PC机,也可以安装和使用DOS。就和APIC和PIC的关系一样,PIC实际上可以淘汰不用的。

论坛徽章:
0
6 [报告]
发表于 2006-04-11 08:52 |只看该作者
下面的文字摘自linuxforum上,我还是不知道create_bounce的真实意图.如果说为了考虑DMA的寻址能力而设的,那么:
1.对于standard dma,寻址能力16M,但是create_bounce中申请跳板页时使用的是page = alloc_page(GFP_BUFFER);显然没有考虑16M的限制
2.对于PCI卡上的DMA,它的寻址能力好象是32位(4G),但是create_bounce中测试是否要建立跳板的条件是if (!PageHighMem(bh_orig->b_page))        return bh_orig;也就是地址>896M才建立跳板
我什么地方的思考有问题,谢谢!

http://www.linuxforum.net/forum/ ... &o=186&vc=1

kmap_atomic使用fixmap中保留的两个虚存页面,提供了可以在irq环境中使用的
highmem访问接口.
   另外注意__GFP_HIGH不是要分配highmem的内存,__GFP_HIGHMEM才是,看看
struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig)
不要把这两个东西搞混了.create_bounce为处于highmem的bh分配一个非highmem的
内存页面,并继承bh其他的所有东西.在io完成之前后负责在highmem和这个跳板页
面直接复制数据. 或许是dma不能处理himem故需要这个跳板(should be this).
  看看什么情况下对HigMemPage进行io:
  内核尽量给用户分配highmem页面,在某种情况下需要将数据写到这些页面.比如用
户将文件mmap到内存,然后内核为这些页面分配了Highmem Page,现在需要读入数据.
直接看block_read_full_page,
............
        if (!buffer_mapped(bh)) {
                 memset(kmap(page) + i*blocksize, 0, blocksize);
                 flush_dcache_page(page);
                 kunmap(page);
                 set_bit(BH_Uptodate, &bh->b_state);
                 continue;
        }
...............
    可以看到kmap,映射高端内存的操作.证明这个流程需要处理Highmem Page.看
submit_bh->generic_make_request->q->make_request_fn这个函数度于ide就是
__make_request(见函数blk_init_queue):
#if CONFIG_HIGHMEM
        bh = create_bounce(rw, bh);
#endif
     利用了highmem提供的这个跳板.

struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig)
{
        struct page *page;
        struct buffer_head *bh;

        if (!PageHighMem(bh_orig->b_page))
                return bh_orig;

repeat_bh:
        bh = kmem_cache_alloc(bh_cachep, SLAB_BUFFER);
        if (!bh) {
                wakeup_bdflush(1);  /* Sets task->state to TASK_RUNNING */
                goto repeat_bh;
        }
        /*
         * This is wasteful for 1k buffers, but this is a stopgap measure
         * and we are being ineffective anyway. This approach simplifies
         * things immensly. On boxes with more than 4GB RAM this should
         * not be an issue anyway.
         */
repeat_page:
        page = alloc_page(GFP_BUFFER);
        if (!page) {
                wakeup_bdflush(1);  /* Sets task->state to TASK_RUNNING */
                goto repeat_page;
        }
        set_bh_page(bh, page, 0);

        bh->b_next = NULL;
        bh->b_blocknr = bh_orig->b_blocknr;
        bh->b_size = bh_orig->b_size;
        bh->b_list = -1;
        bh->b_dev = bh_orig->b_dev;
        bh->b_count = bh_orig->b_count;
        bh->b_rdev = bh_orig->b_rdev;
        bh->b_state = bh_orig->b_state;
        bh->b_flushtime = jiffies;
        bh->b_next_free = NULL;
        bh->b_prev_free = NULL;
        /* bh->b_this_page */
        bh->b_reqnext = NULL;
        bh->b_pprev = NULL;
        /* bh->b_page */
        if (rw == WRITE) {
                bh->b_end_io = bounce_end_io_write;
                copy_from_high_bh(bh, bh_orig);
        } else
                bh->b_end_io = bounce_end_io_read;
        bh->b_private = (void *)bh_orig;
        bh->b_rsector = bh_orig->b_rsector;
        memset(&bh->b_wait, -1, sizeof(bh->b_wait));

        return bh;
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP