zoukankan      html  css  js  c++  java
  • 关于ioremap,request_mem_region

    文章内容来自:http://blog.csdn.net/fudan_abc/archive/2007/10/04/1811451.aspx

    以我们家 Intel 为代表的 i386 系列处理器中 , 内存和外部 IO 是独立编址独立寻址的 , 于是有一个地址空间叫做内存空间 , 另有一个地址空间叫做 I/O 空间 . 也就是说 , 从处理器的角度来说 ,i386 提供了一些单独的指令用来访问 I/O 空间 . 换言之 , 访问 I/O 空间和访问普通的内存得使用不同的指令 . 而在一些玩嵌入式的处理器中 , 比如 PowerPC, 他们家就只使用一个空间 , 那就是内存空间 , 那像这种情况 , 外设的 I/O 端口的物理地址就被映射到内存地址空间中 , 这就是传说中的 Memory-mapped, 内存映射 . 而我们家那种情况 , 外设的 I/O 端口的物理地址就被映射到 I/O 地址空间中 , 这就是传说中的 I/O-mapped, 即 I/O 映射 .

    要使用 I/O 内存首先要申请 , 然后要映射 , 而要使用 I/O 端口首先要申请 , 或者叫请求 , 对于 I/O 端口的请求意思是让内核知道你要访问这个端口 , 这样内核知道了以后它就不会再让别人也访问这个端口了 . 毕竟这个世界僧多粥少啊 . 申请 I/O 端口的函数是 request_region, 这个函数来自 include/linux/ioport.h,

    /* Convenience shorthand with allocation */

    #define request_region(start,n,name)    __request_region(&ioport_resource, (start), (n), (name))

    #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name))

    #define rename_region(region, newname) do { (region)->name = (newname); } while (0)

    extern struct resource * __request_region(struct resource *,

                                             resource_size_t start,

                                             resource_size_t n, const char *name);

    这里我们看到的那个 request_mem_region 是申请 I/O 内存用的 . 申请了之后 , 还需要使用 ioremap 或者 ioremap_nocache 函数来映射 .对于 request_region, 三个参数 start,n,name 表示你想使用从 start 开始的 size 为 n 的 I/O port 资源 ,name 自然就是你的名字了 .

    这两个函数在内核的驱动中几乎都会出现,例如ohci-at91.c里面的probe函数:

    view plaincopy to clipboardprint?

    1. hcd->rsrc_start = pdev->resource[0].start; 
    2.     hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; 
    3. if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 
    4.         pr_debug("request_mem_region failed\n"); 
    5.         retval = -EBUSY; 
    6. goto err1; 
    7.     } 
    8.     hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); 
    9. if (!hcd->regs) { 
    10.         pr_debug("ioremap failed\n"); 
    11.         retval = -EIO; 
    12. goto err2; 
    13.     } 

    hcd->rsrc_start = pdev->resource[0].start; hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { pr_debug("request_mem_region failed\n"); retval = -EBUSY; goto err1; } hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { pr_debug("ioremap failed\n"); retval = -EIO; goto err2; }

    这样的好处是寄存器访问方式比较好看,只要加个偏移地址就可以了。

    不过我有时候又不太喜欢用。因为这两句话说到底是为了访问寄存器用的。相当于获得寄存器虚拟地址。但是我们在初始化的时候虚拟地址就已经映射过了,所以我喜欢直接操作寄存器的虚拟地址。

  • 相关阅读:
    [java] 怎么去掉小数点后面不需要的0
    [SoapUI] 在SoapUI script里获取Response(Json格式)某个节点值
    nacos启动不停打印日志[com.alibaba.nacos.client.naming.updater] INFO com.alibaba.nacos.client.naming:192
    sppringcloud应用启动 访问gateway无法path无法路由到目标应用,404
    springcloud项目启动gateway报错org.springframework.cloud.gateway.config.GatewayAutoConfiguration required a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' that could not be found
    nacos 01
    微服务spring-cloud day2
    springcloud本地启动指定profile后错误If you are using the git profile, you need to set a Git URI in your configuration.
    微服务spring-cloud day1
    金融云部署sofaboot应用指定了项目路径健康检查无法通过,windows格式/unix格式/mac格式的坑
  • 原文地址:https://www.cnblogs.com/cute/p/1992651.html
Copyright © 2011-2022 走看看