request_mem_region 申請內存函數講解

request_mem_region

這裏我們看到的那個 request_mem_region 是申請 I/O 內存用的 . 申請了之後 , 還需要使用 ioremap 或者 ioremap_nocache 函數來映射 .對於 request_region, 三個參數 start,n,name 表示你想使用從 start 開始的 size 爲 n 的 I/O port 資源 ,name 自然就是你的名字了

以我們家 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?
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; 
}
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;
}

這樣的好處是寄存器訪問方式比較好看,只要加個偏移地址就可以了。

不過我有時候又不太喜歡用。因爲這兩句話說到底是爲了訪問寄存器用的。相當於獲得寄存器虛擬地址。但是我們在初始化的時候虛擬地址就已經映射過了,所以我喜歡直接操作寄存器的虛擬地址
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章