日期:2014-05-16 浏览次数:20671 次
1 IO端口和IO内存区别
像x86系列处理器有两种地址空间:一种是内存地址空间,一种是端口地址空间,访问端口有单独的指令,例如in/out指令,而像ARM这类处理器则使用单一的地址空间,没有端口地址空间的概念。在硬件层,IO端口和IO内存并无本质区别,都是通过向地址总线和控制总线发送地址和控制信号,再通过数据总线读写数据。
2 使用IO端口
2.1 IO端口分配
IO端口分配使用request_region函数,该函数用于取得该IO端口的独占访问,头文件在linux/ioport.h中,函数原型如下:
struct resourse *request_region(unsigned long first, unsigned long n, const char *name);
first表示起始端口号,n表示端口数量。
如果分配成功,返回非NULL值,如果request_region返回NULL,表示不能使用这些IO端口(有可能被其它程序占用了)。
2.2 IO端口释放
如果不在使用该IO端口,则调用release_region函数释放该IO端口的控制,函数原型如下:
void release_region(unsigned long start, unsigned long n);
2.3 检查IO端口是否可用
int check_region(unsigned long first, unsigned long n);
如果该端口不可用,则返回错误码。Linux中并不赞成使用这个函数,因为该函数只是对IO端口做检查,并不对IO端口进行锁定,这样有可能其它程序也能使用这组IO端口,这是一个比较老的函数。
2.4 操作IO端口
这组函数与具体的体系架构有关,所以头文件在asm/io.h中
unsigned inb(unsigned port);
void outb(unsigned char byte, unsigned port);
8位(字节)读写函数。
unsigned inw(unsigned port);
void outw(unsigned short word, unsigned port);
16位读写函数。
unsigned inl(unsigned port);
void out(unsinged long word, unsinged port);
32位读写函数。
3 使用IO内存
3.1 IO内存分配
在使用之前,必须首先分配IO内存,需要包含头文件linux/ioport.h,函数原型如下:
struct resourse *request_mem_region(unsigned long start, unsigned long len, char *name);
表示从start开始分配len字节的内存区域,如果成功,返回非NULL指针,否则返回NULL,所有的IO内存分配情况可以从/proc/iomem中看到。
3.2 IO内存释放
不再使用这段内存时,需要调用release_mem_region释放,函数原型如下:
void release_mem_region(unsigned long start, unsigned long len);
同样也提供了一个比较老的函数,用来检查IO内存是否可用
int check_mem_region(unsigned long start, unsigned long len);
同check_region一样,它也是不安全的,应该避免使用。
3.3 IO内存映射和释放
通常,是不能直接访问IO内存的,需要对IO内存进行映射,映射是将物理地址映射成虚拟地址,函数原型如下:
void *ioremap(unsigned long phys_addr, unsinged long size);
void iounmap(void *addr);
要使用这些函数需要包含头文件asm/io.h