⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmap.html

📁 ADI 公司blackfin系列的用户使用文挡。
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head>  <title></title>  <link rel="stylesheet" media="screen" type="text/css" href="./style.css" />  <link rel="stylesheet" media="screen" type="text/css" href="./design.css" />  <link rel="stylesheet" media="print" type="text/css" href="./print.css" />  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><a href=start.html>start</a></br><div class="toc"><div class="tocheader toctoggle" id="toc__header">Table of Contents</div><div id="toc__inside"><ul class="toc"><li class="clear"><ul class="toc"><li class="clear"><ul class="toc"><li class="level3"><div class="li"><span class="li"><a href="#device_driver_mmap_interface" class="toc">Device Driver MMAP interface</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#mmap_in_user_space" class="toc">MMAP in user Space</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#mmap_kernel_code_example_1" class="toc">MMAP kernel code example 1</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#mmap_kernel_code_example_2" class="toc">MMAP kernel code example 2</a></span></div></li></ul></li></ul></li></ul></div></div><h3><a name="device_driver_mmap_interface" id="device_driver_mmap_interface">Device Driver MMAP interface</a></h3><div class="level3"><p> The mmap interface is used when a user space task wants to directly access kernel or device memory.</p><p>Typical uses are framebuffer drivers and I/O devices with their own on board memories.</p><p>In uClinux the normal access restrictions  on kernel memory space may not occur. You should take care to make the interface and any devices that use it as compatible as possible with &ldquo;normal&rdquo; Linux.</p><p>The mapping call will create a pointer in user space that can be addressed a a usual memory structure. This is trivial in uClinux with no mmu but to make a driver call that will work in both cases is not so straightforward.</p></div><!-- SECTION [1-654] --><h3><a name="mmap_in_user_space" id="mmap_in_user_space">MMAP in user Space</a></h3><div class="level3"><p> The user space interface is shown:</p><pre class="code c">  <span class="coMULTI">/*  the function prototype */</span>                                                                                                                    <span class="kw4">void</span>  *  mmap<span class="br0">&#40;</span><span class="kw4">void</span>  *start,  size_t length, <span class="kw4">int</span> prot , <span class="kw4">int</span>                    flags, <span class="kw4">int</span> fd, off_t offset<span class="br0">&#41;</span>;                                                                                                                                                                                  &nbsp;  <span class="coMULTI">/* A typical use ... make data addressable in virtual address space */</span>&nbsp;  <span class="co2">#include &lt;unistd.h&gt;                                                   </span>  <span class="co2">#include &lt;sys/mman.h&gt;                                                 </span>     <span class="kw4">char</span> * p;                                                               <span class="kw4">int</span> i;                                                                  <span class="kw4">int</span> fd;                                                                 <span class="kw4">int</span> len=SCMD_SIZE;                                                                                                                              fd = open<span class="br0">&#40;</span><span class="st0">"/dev/scmd"</span>,O_RDWR<span class="br0">&#41;</span>;                                                                                                                  p = <span class="br0">&#40;</span><span class="kw4">char</span> *<span class="br0">&#41;</span>mmap<span class="br0">&#40;</span><span class="nu0">0</span>, len, PROT_READ, MAP_PRIVATE, fd, <span class="nu0">0</span><span class="br0">&#41;</span>;                <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">"buffer address 0x%x <span class="es0">\n</span>"</span>,p<span class="br0">&#41;</span>;                                     <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">"buffer data &lt;%s&gt; <span class="es0">\n</span>"</span>,p<span class="br0">&#41;</span>;                                   &nbsp;</pre></div><!-- SECTION [655-2126] --><h3><a name="mmap_kernel_code_example_1" id="mmap_kernel_code_example_1">MMAP kernel code example 1</a></h3><div class="level3"><p> This code maps a memory area using <strong>remap_page_range</strong> to build a new set of page tables for the memory area. The memory area must start at a page boundary.</p><p>NOTE this is due to be replaced in the latest kernels by <strong>remap_pfn_range</strong> to allow the use of greater than 4G of memory space. </p><pre class="code c">  <span class="co2">#include &lt;linux/mm.h&gt;                                               </span>  <span class="coMULTI">/* needed for virt_to_phys() */</span>                                       <span class="co2">#include &lt;asm/io.h&gt; // virt_to_phys()                               </span>  <span class="co2">#include &lt;linux/wrapper.h&gt; // mem_map_[un]reserve()                 </span>                                                                        <span class="kw4">static</span> <span class="kw4">char</span> * buffer; <span class="co1">// we use this as a test                      </span>                                                                        <span class="kw4">static</span> <span class="kw4">int</span> scmd_mmap<span class="br0">&#40;</span><span class="kw4">struct</span> file * filp, <span class="kw4">struct</span> vm_area_struct *vma<span class="br0">&#41;</span>  <span class="br0">&#123;</span>                                                                        scmd_dev_t * dev;                                                     <span class="kw4">unsigned</span> <span class="kw4">long</span> page,pos,start,size,offset;                                                                                                   dev = <span class="br0">&#40;</span> scmd_dev_t * <span class="br0">&#41;</span>filp-&gt;private_data;                                                                                                   start=<span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">long</span><span class="br0">&#41;</span>vma-&gt;vm_start;                                   size=<span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">long</span><span class="br0">&#41;</span>vma-&gt;vm_end-vma-&gt;vm_start;                                                                                                                                                                 <span class="co2">#ifndef CONFIG_MMU                                                  </span>          <span class="coMULTI">/* this may not be correct yet */</span>                                     vma-&gt;vm_start = dev-&gt;data + vma-&gt;vm_offset;                           <span class="kw1">return</span> <span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span>;                                                   <span class="co2">#else /* /CONFIG_MMU */                                             </span>                                                                           offset = vma-&gt;vm_pgoff &lt;&lt; PAGE_SHIFT;                                 <span class="kw1">if</span> <span class="br0">&#40;</span>offset &gt;= __pa<span class="br0">&#40;</span>high_memory<span class="br0">&#41;</span> || <span class="br0">&#40;</span>filp-&gt;f_flags &amp; O_SYNC <span class="br0">&#41;</span><span class="br0">&#41;</span>            vma-&gt;vm_flags |= VM_IO;                                            vma-&gt;vm_flags |= VM_RESERVED;                                                                                                                      pos  = <span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">long</span><span class="br0">&#41;</span>buffer;                                         page = virt_to_phys<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">void</span> *<span class="br0">&#41;</span>pos<span class="br0">&#41;</span>;                                                                                                           <span class="kw1">if</span> <span class="br0">&#40;</span> remap_page_range<span class="br0">&#40;</span>start, page, size, vma-&gt;vm_page_prot | PAGE_SHARED<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>                                                             printk<span class="br0">&#40;</span><span class="st0">" scmd_mmap: error in remap page_range <span class="es0">\n</span>"</span><span class="br0">&#41;</span>;                   <span class="kw1">return</span> -EAGAIN;                                                    <span class="br0">&#125;</span>                                                                  <span class="co2">#endif  /* end NO_MM */                                             </span>     <span class="kw1">return</span> <span class="nu0">0</span>;                                                          <span class="br0">&#125;</span></pre><p> The following code is also added to set up the buffer </p><pre class="code c">&nbsp;  <span class="coMULTI">/* in scmd_init */</span>                                                                                       scmd_driver_fops.<span class="me1">mmap</span> = scmd_mmap;                                                                    buffer = kmalloc<span class="br0">&#40;</span><span class="nu0">4096</span>,GFP_KERNEL<span class="br0">&#41;</span>;                 printk<span class="br0">&#40;</span><span class="st0">" scmd_mmap buffer = %p<span class="es0">\n</span>"</span>,buffer<span class="br0">&#41;</span>;         <span class="kw1">if</span> <span class="br0">&#40;</span> buffer <span class="br0">&#41;</span> <span class="br0">&#123;</span>                                       <span class="kw4">struct</span> page *  page = virt_to_page<span class="br0">&#40;</span>buffer<span class="br0">&#41;</span>;        mem_map_reserve<span class="br0">&#40;</span>page<span class="br0">&#41;</span>;                             strcpy<span class="br0">&#40;</span>buffer,<span class="st0">"scmd_mmap test data"</span><span class="br0">&#41;</span>;           <span class="br0">&#125;</span>                                                                                                  <span class="coMULTI">/* in scmd_exit */</span>                                    <span class="kw1">if</span> <span class="br0">&#40;</span> buffer <span class="br0">&#41;</span> <span class="br0">&#123;</span>                                       <span class="kw4">struct</span> page * page = virt_to_page<span class="br0">&#40;</span>buffer<span class="br0">&#41;</span>;         mem_map_unreserve<span class="br0">&#40;</span>page<span class="br0">&#41;</span>;                           kfree<span class="br0">&#40;</span>buffer<span class="br0">&#41;</span>;                                  <span class="br0">&#125;</span></pre></div><!-- SECTION [2127-6325] --><h3><a name="mmap_kernel_code_example_2" id="mmap_kernel_code_example_2">MMAP kernel code example 2</a></h3><div class="level3"><p> In Blackfin uClinux we can reserve some memory for user application or driver (the kernel doesn&rsquo;t manage this memory buffer). To reserve memory just set bootargs in uboot &quot; max_mem=xxM$# mem=yyM &ldquo;. The &ldquo;yy - xx&rdquo; is the reserved memory, &ldquo;$#&rdquo; means enable cache. </p><pre class="code c"><span class="coMULTI">/* * Simple - REALLY simple memory mapping demonstration. * * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet * Copyright (C) 2001 O'Reilly &amp; Associates * * The source code in this file can be freely used, adapted, * and redistributed in source or binary form, so long as an * acknowledgment appears in derived source files.  The citation * should list that the code comes from the book &quot;Linux Device * Drivers&quot; by Alessandro Rubini and Jonathan Corbet, published * by O'Reilly &amp; Associates.   No warranty is attached; * we cannot take responsibility for errors or fitness for use. * * $Id: simple.c,v 1.12 2005/01/31 16:15:31 rubini Exp $ */</span>&nbsp;<span class="coMULTI">/* borrowed from &quot;Linux Device Driver&quot; --- see http://lwn.net/Kernel/LDD3/ */</span>&nbsp;<span class="co2">#include &lt;linux/config.h&gt;</span><span class="co2">#include &lt;linux/module.h&gt;</span><span class="co2">#include &lt;linux/moduleparam.h&gt;</span><span class="co2">#include &lt;linux/init.h&gt;</span>&nbsp;<span class="co2">#include &lt;linux/kernel.h&gt;   /* printk() */</span><span class="co2">#include &lt;linux/slab.h&gt;   /* kmalloc() */</span><span class="co2">#include &lt;linux/fs.h&gt;       /* everything... */</span><span class="co2">#include &lt;linux/errno.h&gt;    /* error codes */</span><span class="co2">#include &lt;linux/types.h&gt;    /* size_t */</span><span class="co2">#include &lt;linux/mm.h&gt;</span><span class="co2">#include &lt;linux/kdev_t.h&gt;</span><span class="co2">#include &lt;asm/page.h&gt;</span><span class="co2">#include &lt;linux/cdev.h&gt;</span>&nbsp;<span class="co2">#include &lt;linux/device.h&gt;</span>&nbsp;<span class="kw4">static</span> <span class="kw4">int</span> simple_major = <span class="nu0">0</span>;module_param<span class="br0">&#40;</span>simple_major, <span class="kw4">int</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;MODULE_AUTHOR<span class="br0">&#40;</span><span class="st0">"Jonathan Corbet"</span><span class="br0">&#41;</span>;MODULE_LICENSE<span class="br0">&#40;</span><span class="st0">"Dual BSD/GPL"</span><span class="br0">&#41;</span>;&nbsp;<span class="coMULTI">/* * Open the device; in fact, there's nothing to do here. */</span><span class="kw4">static</span> <span class="kw4">int</span> simple_open <span class="br0">&#40;</span><span class="kw4">struct</span> inode *inode, <span class="kw4">struct</span> file *filp<span class="br0">&#41;</span><span class="br0">&#123;</span>	<span class="kw1">return</span> <span class="nu0">0</span>;<span class="br0">&#125;</span>&nbsp;&nbsp;<span class="coMULTI">/* * Closing is just as simpler.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -