您的位置:首页 > 产品设计 > UI/UE

关于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函数:



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;
	}




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

不过我有时候又不太喜欢用。因为这两句话说到底是为了访问寄存器用的。相当于获得寄存器虚拟地址。但是我们在初始化的时候虚拟地址就已经映射过了,所以我喜欢直接操作寄存器的虚拟地址。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: