LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2863|回复: 7

关于CPU对IO寻址的问题(I/O端口和I/O内存)

[复制链接]
发表于 2005-7-25 16:45:54 | 显示全部楼层 |阅读模式
几乎每一种外设都是通过读写设备上的寄存器来进行的。外设寄存器也称为“I/O端口”,通常包括:控制寄存器、状态寄存器和数据寄存器三大类,而且一个外设的寄存器通常被连续地编址。CPU对外设IO端口物理地址的编址方式有两种:一种是I/O映射方式(I/O-mapped),另一种是内存映射方式(Memory-mapped)。而具体采用哪一种则取决于CPU的体系结构。

我想问的是,对我们而言,编程的时候,I/O映射方式和内存映射方式有什么不同啊?
因为我需要写一个驱动,可是现在一些基础知识还有些模糊。
谢谢拉!
发表于 2005-7-25 21:14:51 | 显示全部楼层
内存映射时候可以直接用open,close,read这些接口
而I/0 mapped 就直接out,in
我记得就是这么点区别
回复 支持 反对

使用道具 举报

发表于 2005-7-26 10:00:33 | 显示全部楼层
Post by cupid
几乎每一种外设都是通过读写设备上的寄存器来进行的。外设寄存器也称为“I/O端口”,通常包括:控制寄存器、状态寄存器和数据寄存器三大类,而且一个外设的寄存器通常被连续地编址。CPU对外设IO端口物理地址的编址方式有两种:一种是I/O映射方式(I/O-mapped),另一种是内存映射方式(Memory-mapped)。而具体采用哪一种则取决于CPU的体系结构。

我想问的是,对我们而言,编程的时候,I/O映射方式和内存映射方式有什么不同啊?
因为我需要写一个驱动,可是现在一些基础知识还有些模糊。
谢谢拉!

io-map的寄存器用outb/w/l,inb/w/l指令访问
mem-map的寄存器直接用指针赋值即可,但是由于对内存访问可能被gcc优化掉,所以最好使用linux提供的包装函数:readb/w/l,writeb/w/l。
io-map也有相应的包装函数/宏。

具体的定义可以参见内核源代码include/asm-i386/io.h的定义
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-7-26 10:54:46 | 显示全部楼层
谢谢啊。
在使用I/O端口时,request_region的参数是实际的物理地址,而不是偏移量吧?另外,Linux系统也不会把它当成虚拟地址进行转换吧?

下面都是cs8900驱动,但是,好像request_region的参数不一样,也不知道哪个是对的?
驱动1:
#define EPORT_ADDR      0x300
#define EIOADDR         (EIO_BASE+EPORT_ADDR)
request_region(EPORT_ADDR, NETCARD_IO_EXTENT,"cs89x0");

驱动2:
static int io = 0xd0000300;
request_region(dev_cs89x0.base_addr, NETCARD_IO_EXTENT, "cs8900a");

谢谢拉!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-7-26 14:21:42 | 显示全部楼层
还有一个问题,对某种外围芯片来说,我如何操作它的端口,采用I/O端口还是I/O内存方法?比如,以PC的并口芯片为例呢。
回复 支持 反对

使用道具 举报

发表于 2005-7-27 09:44:22 | 显示全部楼层
Post by cupid
还有一个问题,对某种外围芯片来说,我如何操作它的端口,采用I/O端口还是I/O内存方法?比如,以PC的并口芯片为例呢。

并口一般都是io map的。

传统的pc芯片大部分是io map的(目前大多集成进了南桥,具体的map的方法可以参考主板的datasheet,一般说来会保持和IBM PC的兼容性)。PCI设备则根据config space的配置寄存器有关。
回复 支持 反对

使用道具 举报

发表于 2005-7-27 09:51:14 | 显示全部楼层
Post by cupid
谢谢啊。
在使用I/O端口时,request_region的参数是实际的物理地址,而不是偏移量吧?另外,Linux系统也不会把它当成虚拟地址进行转换吧?

下面都是cs8900驱动,但是,好像request_region的参数不一样,也不知道哪个是对的?
驱动1:
#define EPORT_ADDR      0x300
#define EIOADDR         (EIO_BASE+EPORT_ADDR)
request_region(EPORT_ADDR, NETCARD_IO_EXTENT,"cs89x0");

驱动2:
static int io = 0xd0000300;
request_region(dev_cs89x0.base_addr, NETCARD_IO_EXTENT, "cs8900a");

谢谢拉!

是物理地址。

另外第二个问题不知道楼主是什么意思
回复 支持 反对

使用道具 举报

发表于 2006-2-9 14:45:28 | 显示全部楼层
看看,学习一下
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表