一个简单的使用DMA 例子

示例:下面是一个简单的使用DMA进行传输的驱动程序,它是一个假想的设备,只列出DMA相关的部分来说明驱动程序中如何使用DMA的。

函数dad_transfer是设置DMA对内存buffer的传输操作函数,它使用流式映射将buffer的虚拟地址转换到物理地址,设置好DMA控制器,然后开始传输数据。

int dad_transfer(struct dad_dev *dev, int write, void *buffer,                 size_t count) {    dma_addr_t bus_addr;    unsigned long flags;    /* Map the buffer for DMA */    dev->dma_dir = (write ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);    dev->dma_size = count; //流式映射,将buffer的虚拟地址转化成物理地址    bus_addr = pci_map_single(dev->pci_dev, buffer, count,                              dev->dma_dir);    dev->dma_addr = bus_addr; //DMA传送的buffer物理地址    //将操作控制写入到DMA控制器寄存器,从而建立起设备    writeb(dev->registers.command, DAD_CMD_DISABLEDMA); //设置传输方向--读还是写 writeb(dev->registers.command, write ? DAD_CMD_WR : DAD_CMD_RD);    writel(dev->registers.addr, cpu_to_le32(bus_addr));//buffer物理地址    writel(dev->registers.len, cpu_to_le32(count)); //传输的字节数    //开始激活DMA进行数据传输操作    writeb(dev->registers.command, DAD_CMD_ENABLEDMA);    return 0; }

函数dad_interrupt是中断处理函数,当DMA传输完时,调用这个中断函数来取消buffer上的DMA映射,从而让内核程序可以访问这个buffer。

void dad_interrupt(int irq, void *dev_id, struct pt_regs *regs)

{

struct dad_dev *dev = (struct dad_dev *) dev_id;

/* Make sure it's really our device interrupting */

/* Unmap the DMA buffer */   pci_unmap_single(dev->pci_dev, dev->dma_addr, dev->dma_size,        dev->dma_dir);

/* Only now is it safe to access the buffer, copy to user, etc. */   ...

}

函数dad_open打开设备,此时应申请中断号及DMA通道。

int dad_open (struct inode *inode, struct file *filp)

{

struct dad_device *my_device;

// SA_INTERRUPT表示快速中断处理且不支持共享 IRQ 信号线   if ( (error = request_irq(my_device.irq, dad_interrupt,                             SA_INTERRUPT, "dad", NULL)) )       return error; /* or implement blocking open */

if ( (error = request_dma(my_device.dma, "dad")) ) {       free_irq(my_device.irq, NULL);       return error; /* or implement blocking open */   }

return 0;

}

在与open 相对应的 close 函数中应该释放DMA及中断号。

void dad_close (struct inode *inode, struct file *filp)

{

struct dad_device *my_device;   free_dma(my_device.dma);   free_irq(my_device.irq, NULL);   ……

}

函数dad_dma_prepare初始化DMA控制器,设置DMA控制器的寄存器的值,为 DMA 传输作准备。

int dad_dma_prepare(int channel, int mode, unsigned int buf,

unsigned int count)

{

unsigned long flags;

flags = claim_dma_lock();   disable_dma(channel);   clear_dma_ff(channel);   set_dma_mode(channel, mode);   set_dma_addr(channel, virt_to_bus(buf));   set_dma_count(channel, count);   enable_dma(channel);   release_dma_lock(flags);

return 0;

}

函数dad_dma_isdone用来检查 DMA 传输是否成功结束。

int dad_dma_isdone(int channel) {    int residue;    unsigned long flags = claim_dma_lock ();    residue = get_dma_residue(channel);    release_dma_lock(flags);    return (residue == 0); }

linux 简单的DMA例程的更多相关文章

  1. [原创]linux简单之美(一)

    原文链接:linux简单之美(一) 话说windows也有syscall,这是必须的.但是win的syscall可以直接call吗?可以是可以但是破费周折,搞成SDT之类的复杂概念.下面看看linux ...

  2. [原创]linux简单之美(二)

    原文链接:linux简单之美(二) 我们在前一章中看到了如何仅仅用syscall做一些简单的事,现在我们看能不能直接调用C标准库中的函数快速做一些"复杂"的事: section . ...

  3. [原创]linux简单之美(三)

    原文链接:linux简单之美(三) 在linux简单之美(二)中我们尝试使用了C库的函数完成功能,那么能不能用syscall方式来搞呢?显然可以! section .data ft db sectio ...

  4. Linux学习之十七-配置Linux简单的脚本文件自启动

    配置Linux简单的脚本文件自启动 在Linux中使用shell脚本解决一些问题会比单独执行多条命令要有效率,脚本文件规定命名以.sh结尾,最基本的规则就是其内容是命令,想要脚本文件开机自启动,就需要 ...

  5. 五大Linux简单命令解决系统性能问题

    五大Linux简单命令解决系统性能问题 2010-12-17 10:07 James Turnbull TechTarget中国 字号:T | T 管理Linux主机的性能看起来经常象是在变魔术一样. ...

  6. Linux简单Shell脚本监控MySQL、Apache Web和磁盘空间

    Linux简单Shell脚本监控MySQL.Apache Web和磁盘空间 1. 目的或任务 当MySQL数据库.Apache Web服务器停止运行时,重新启动运行,并发送邮件通知: 当服务器磁盘的空 ...

  7. 一篇文章带你了解服务器操作系统——Linux简单入门

    一篇文章带你了解服务器操作系统--Linux简单入门 Linux作为服务器的常用操作系统,身为工作人员自然是要有所了解的 在本篇中我们会简单介绍Linux的特点,安装,相关指令使用以及内部程序的安装等 ...

  8. Linux 简单字符设备驱动程序 (自顶向下)

    第零章:扯扯淡 特此总结一下写的一个简单字符设备驱动程序的过程,我要强调一下“自顶向下”这个介绍方法,因为我觉得这样更容易让没有接触过设备驱动程序的童鞋更容易理解,“自顶向下”最初从<计算机网络 ...

  9. linux简单配置

    lsof -i lsof -i:211.判断apache查找httpd路径: ps aux | grep httpd 结果:  /usr/local/apache/bin/httpd /usr/loc ...

随机推荐

  1. .Net性能优化时应该关注的数据

    解决性能问题的时候,我往往会让客户添加下面一些计数器进行性能收集. Process object下的所有计数器: Processor object下的所有计数器: System object下的所有计 ...

  2. nodejs安装及环境配置

    简单的说 Node.js 就是运行在服务端的 JavaScript. Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台. Node.js是一个事件驱动I/O服务端Ja ...

  3. 苹果系列机型专业刷机,解锁,解ID

    如有软件开发需求,请留言或在猪八戒网主页留言http://home.zhubajie.com/8506525/,常年接收c.c++(vs2010.RAD studio xe5\RAD studio 2 ...

  4. C语言文法 改

    <程序> ->  <外部声明> |  <程序>  <外部声明> <外部声明>  ->   <函数定义>  |  &l ...

  5. CICS的database中R D中参数的含义

    见链接 http://blog.163.com/ajj_star/blog/static/1626772542010328113513429/ Region Definitions (RD) 定义了所 ...

  6. 如何解决谷歌浏览器下jquery无法获取图片的尺寸

    代码如下: $(document).ready(function(){ var img_h=$img.height(); var img_w=$img.width(); }) 以上代码在IE和火狐中没 ...

  7. Silverlight中动画的性能浅析

    Silverlight中提供了StoryBoard实现动画,可是StoryBoard的性能实在不敢恭维,特别是动画很大的时候,计算机的CPU和内存的狂增,如此一来性能实在太差,在默认的动画效果中动画实 ...

  8. CentOS 下如何查看并清理系统内存空间

    有时候在服务器上打开了很多会占用内存的程序但关闭这些程序后,发现内存空间还是和没有关闭应用程序时的占用一样,以致使其它应用程序打开时内存不够或很卡,那么此时就想清理掉以前的程序打开时所占用的内存.而大 ...

  9. php验证是否是md5编码的代码

    php验证是否是md5编码的示例. 代码很简单,使用了正则表达式. function is_md5($password) {     return preg_match("/^[a-z0-9 ...

  10. 重拾C,一天一点点_9-指针与数组

    这一章节很重要,一定要多思考.理解! 指针是一种保存变量地址的变量. 通常的机器 都有一系列连续编号或编址的存储单元.一个字节可存char类型,两相邻字节存储单元可存一个short,依此类推. p = ...