关于ioremap,request_mem_region
2009-10-21 10:06
519 查看
文章内容来自: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函数:
这样的好处是寄存器访问方式比较好看,只要加个偏移地址就可以了。
不过我有时候又不太喜欢用。因为这两句话说到底是为了访问寄存器用的。相当于获得寄存器虚拟地址。但是我们在初始化的时候虚拟地址就已经映射过了,所以我喜欢直接操作寄存器的虚拟地址。
以我们家
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函数:
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; }
这样的好处是寄存器访问方式比较好看,只要加个偏移地址就可以了。
不过我有时候又不太喜欢用。因为这两句话说到底是为了访问寄存器用的。相当于获得寄存器虚拟地址。但是我们在初始化的时候虚拟地址就已经映射过了,所以我喜欢直接操作寄存器的虚拟地址。
相关文章推荐
- 关于ioremap,request_mem_region
- 关于ioremap,request_mem_region
- 关于ioremap,request_mem_region
- 关于ioremap,request_mem_region
- 关于ioremap,request_mem_region
- 关于ioremap,request_mem_region
- 关于ioremap,request_mem_region
- 关于ioremap,request_mem_region
- 关于ioremap,request_mem_region
- io资源访问,及request_mem_region和ioremap的理解
- 内核request_mem_region 和 ioremap的理解
- request_mem_region,ioremap和phys_to_virt()
- 内核request_mem_region 和 ioremap的理解【转】
- 内核request_mem_region 和 ioremap的理解
- 内核request_mem_region 和 ioremap的理解
- 内核request_mem_region 和 ioremap的理解
- request_mem_region,ioremap 和phys_to_virt()
- request_mem_region,ioremap
- 内核request_mem_region 和 ioremap的理解
- request_mem_region,ioremap