|
5 访问I/O端口空间
在驱动程序请求了I/O端口空间中的端口资源后,它就可以通过CPU的IO指定来读写这些I/O端口了。在读写I/O端口时要注意的一点就是,大多数平台都区分8位、16位和32位的端口,也即要注意I/O端口的宽度。
Linux在include/asm/io.h头文件(对于i386平台就是include/asm-i386/io.h)中定义了一系列读写不同宽度I/O端口的宏函数。如下所示:
⑴读写8位宽的I/O端口
unsigned char inb(unsigned port);
void outb(unsigned char value,unsigned port);
|
其中,port参数指定I/O端口空间中的端口地址。在大多数平台上(如x86)它都是unsigned short类型的,其它的一些平台上则是unsigned int类型的。显然,端口地址的类型是由I/O端口空间的大小来决定的。
⑵读写16位宽的I/O端口
unsigned short inw(unsigned port);
void outw(unsigned short value,unsigned port);
|
⑶读写32位宽的I/O端口
unsigned int inl(unsigned port);
void outl(unsigned int value,unsigned port);
|
1 对I/O端口的字符串操作
除了上述这些“单发”(single-shot)的I/O操作外,某些CPU也支持对某个I/O端口进行连续的读写操作,也即对单个I/O端口读或写一系列字节、字或32位整数,这就是所谓的“字符串I/O指令”(String Instruction)。这种指令在速度上显然要比用循环来实现同样的功能要快得多。
Linux同样在io.h文件中定义了字符串I/O读写函数:
⑴8位宽的字符串I/O操作
void insb(unsigned port,void * addr,unsigned long count);
void outsb(unsigned port ,void * addr,unsigned long count);
|
⑵16位宽的字符串I/O操作
void insw(unsigned port,void * addr,unsigned long count);
void outsw(unsigned port ,void * addr,unsigned long count);
|
⑶32位宽的字符串I/O操作
void insl(unsigned port,void * addr,unsigned long count);
void outsl(unsigned port ,void * addr,unsigned long count);
|
2 Pausing I/O
在一些平台上(典型地如X86),对于老式总线(如ISA)上的慢速外设来说,如果CPU读写其I/O端口的速度太快,那就可能会发生丢失数据的现象。对于这个问题的解决方法就是在两次连续的I/O操作之间插入一段微小的时延,以便等待慢速外设。这就是所谓的“Pausing I/O”。
对于Pausing I/O,Linux也在io.h头文件中定义了它的I/O读写函数,而且都以XXX_p命名,比如:inb_p()、outb_p()等等。下面我们就以out_p()为例进行分析。
共6页: 上一页 [1] [2] [3] 4 [5] [6] 下一页
|