I/O記憶體的配置與映射

使用I/O記憶區之前,必須要求核心配置存取權。記憶區的配置程序類似I/O埠,由定義於<linux/ioport.h>的request_mem_region()函式來執行:

void request_mem_region(unsigned long start,unsigned long len,char *name);

此函式將start開始的len個位址組的範圍保留給你。如果配置失敗,會得到一個NULL。從/proc/iomem可以得知核心將哪些I/O記憶區配置給驅動程式。 不再使用I/O記憶區時,將該段位址範圍還給核心:

void release_mem_region(unsigned long start,unsigned long len);

此外,還有一個可檢查I/O記憶區是否被占用的函式:

int check_mem_region(unsigned long start,unsigned long len);

配置好的記憶區還不能使用,必須用ioremap()函式將它映射到一段虛擬位置。

#include <asm/io.h>

void *ioremap(unsigned long phys_addr,unsigned long size);
void *ioremap_nocache(unsigned long phys_addr,unsigned long size);u
void iounremap(void *addr);

ioremap_nocache()的存在是當記憶區含有暫存控制器,不宜併寫(write combining),也不宜快讀(read caching),大部分平台上其實跟ioremap()是沒甚麼差異性的。

存取I/O記憶體

某些平台上,可以將ioremap()回傳值直接拿來當指標使用。但有時候會造成移植性的問題,因此核心有定義一組可以用來讀取I/O記憶體的函式:

unsigned int ioread8(void *addr);
unsigned int ioread16(void *addr);
unsigned int ioread32(void *addr);

addr是ioremap()回傳的虛擬位址值。如果要寫入則是用:

unsigned int iowrite8(void *addr);
unsigned int iowrite16(void *addr);
unsigned int iowrite32(void *addr);

連續重複讀寫:

unsigned int ioread8_rep(void *addr,void *buf,unsigned long count);
unsigned int ioread16_rep(void *addr,void *buf,unsigned long count);
unsigned int ioread32_rep(void *addr,void *buf,unsigned long count);
unsigned int iowrite8_rep(void *addr,const *buf,unsigned long count);
unsigned int iowrite16_rep(void *addr,const *buf,unsigned long count);
unsigned int iowrite32_rep(void *addr,const *buf,unsigned long count);

如果要操作一塊連續的io記憶體,使用下列函式:

void memset_io(void *addr,u8 value,unsigned int count);
void memcpy_fromio(void *dest,void *source,unsigned int count);
void memcpy_toio(void *dest,void *source,unsigned int count);

將I/O埠當程I/O記憶體

有些硬體會有I/O埠或式I/O記憶體操作方式,為了減少兩邊操作的差異性,核心提供了一組叫做ioport_map的函式:

void *ioport_map(unsigned long port,unsigned int count);

此函式將count個I/O ports重新映射到I/O記憶區,並傳回該記憶區的指標,讓驅動程式可用於ioread8()系列的函式來存取該段變造過的I/O記憶區。 不需要用一樣要將其解除:

void ioport_unmap(void *addr);

results matching ""

    No results matching ""