下载

1下载券

加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 IO端口和IO内存

IO端口和IO内存.doc

IO端口和IO内存

331090274
2011-07-20 0人阅读 举报 0 0 暂无简介

简介:本文档为《IO端口和IO内存doc》,可适用于IT/计算机领域

IO端口和IO内存IO端口和IO内存IO端口和IO内存设备驱动程序要直接访问外设或其接口卡上的物理电路这部分通常都是以寄存器的形式出现。外设寄存器也称为IO端口通常包括:控制寄存器、状态寄存器和数据寄存器三大类。根据访问外设寄存器的不同方式可以把CPU分成两大类。一类CPU(如MKPowerPC等)把这些寄存器看作内存的一部分寄存器参与内存统一编址访问寄存器就通过访问一般的内存指令进行所以这种CPU没有专门用于设备IO的指令。这就是所谓的“IO内存”方式。另一类CPU(典型地如X)将外设的寄存器看成一个独立的地址空间所以访问内存的指令不能用来访问这些寄存器而要为对外设寄存器的读/写设置专用指令如IN和OUT指令。这就是所谓的”IO端口”方式。但是用于IO指令的“地址空间”相对来说是很小的。事实上现在x的IO地址空间已经非常拥挤。但是随着计算机技术的发展单纯的IO端口方式无法满足实际需要了因为这种方式只能对外设中的几个寄存器进行操作。而实际上需求在不断发生变化例如在PC上可以插上一块图形卡有MB的存储空间甚至可能还带有ROM,其中装有可执行代码。自从PCI总线出现后不管是CPU的设计采用IO端口方式还是IO内存方式都必须将外设卡上的存储器映射到内存空间实际上是采用了虚存空间的手段这样的映射是通过ioremap()来建立的。访问IO端口  in、out、ins和outs汇编语言指令都可以访问IO端口。内核中包含了以下辅助函数来简化这种访问:inb()、inw()、inl()分别从IO端口读取、或个连续字节。后缀“b”、“w”、“l”分别代表一个字节(位)、一个字(位)以及一个长整型(位)。inbp()、inwp()、inlp()分别从IO端口读取、或个连续字节然后执行一条“哑元(dummy即空指令)”指令使CPU暂停。outb()、outw()、outl()分别向一个IO端口写入、或个连续字节。outbp()、outwp()、outlp()分别向一个IO端口写入、或个连续字节然后执行一条“哑元”指令使CPU暂停。insb()、insw()、insl()分别从IO端口读入以、或个字节为一组的连续字节序列。字节序列的长度由该函数的参数给出。outsb()、outsw()、outsl()分别向IO端口写入以、或个字节为一组的连续字节序列。虽然访问IO端口非常简单但是检测哪些IO端口已经分配给IO设备可能就不这么简单了对基于ISA总线的系统来说更是如此。通常IO设备驱动程序为了探测硬件设备需要盲目地向某一IO端口写入数据但是如果其他硬件设备已经使用这个端口那么系统就会崩溃。为了防止这种情况的发生内核必须使用“资源”来记录分配给每个硬件设备的IO端口。资源表示某个实体的一部分这部分被互斥地分配给设备驱动程序。在这里资源表示IO端口地址的一个范围。每个资源对应的信息存放在resource数据结构中:structresource{        resourcesizetstart        resourcesizetend        constchar*name        unsignedlongflags        structresource*parent,*sibling,*child}其字段如表所示。所有的同种资源都插入到一个树型数据结构(父亲、兄弟和孩子)中例如表示IO端口地址范围的所有资源都包括在一个根节点为ioportresource的树中。表:resource数据结构中的字段 类型字段描述constchar*name资源拥有者的名字unsignedlongstart资源范围的开始unsignedlongend资源范围的结束unsignedlongflags各种标志structresource*parent指向资源树中父亲的指针structresource*sibling指向资源树中兄弟的指针structresource*child指向资源树中第一个孩子的指针 节点的孩子被收集在一个链表中其第一个元素由child指向。sibling字段指向链表中的下一个节点。为什么使用树?例如考虑一下IDE硬盘接口所使用的IO端口地址-比如说从xf到xff。那么start字段为xf且end字段为xff的这样一个资源包含在树中控制器的常规名字存放在name字段中。但是IDE设备驱动程序需要记住另外的信息也就是IDE链主盘使用xf到xf的子范围从盘使用xf到xff的子范围。为了做到这点设备驱动程序把两个子范围对应的孩子插入到从xf到xff的整个范围对应的资源下。一般来说树中的每个节点肯定相当于父节点对应范围的一个子范围。IO端口资源树(ioportresource)的根节点跨越了整个IO地址空间(从端口到)。任何设备驱动程序都可以使用下面三个函数传递给它们的参数为资源树的根节点和要插入的新资源数据结构的地址:requestresource()把一个给定范围分配给一个IO设备。allocateresource()在资源树中寻找一个给定大小和排列方式的可用范围若存在将这个范围分配给一个IO设备(主要由PCI设备驱动程序使用可以使用任意的端口号和主板上的内存地址对其进行配置)。releaseresource()释放以前分配给IO设备的给定范围。内核也为以上函数定义了一些应用于IO端口的快捷函数:requestregion()分配IO端口的给定范围releaseregion()释放以前分配给IO端口的范围。当前分配给IO设备的所有IO地址的树都可以从procioports文件中获得。把IO端口映射到内存空间访问IO端口的另一种方式映射函数的原型为:void*ioportmap(unsignedlongport,unsignedintcount)通过这个函数可以把port开始的count个连续的IO端口重映射为一段“内存空间”。然后就可以在其返回的地址上像访问IO内存一样访问这些IO端口。但请注意在进行映射前还必须通过requestregion()分配IO端口。当不再需要这种映射时需要调用下面的函数来撤消:voidioportunmap(void*addr)在设备的物理地址被映射到虚拟地址之后尽管可以直接通过指针访问这些地址但是工程师宜使用Linux内核的如下一组函数来完成访问IO内存:·读IO内存unsignedintioread(void*addr)unsignedintioread(void*addr)unsignedintioread(void*addr)与上述函数对应的较早版本的函数为(这些函数在Linux中仍然被支持):unsignedreadb(address)unsignedreadw(address)unsignedreadl(address)·写IO内存voidiowrite(uvalue,void*addr)voidiowrite(uvalue,void*addr)voidiowrite(uvalue,void*addr)与上述函数对应的较早版本的函数为(这些函数在Linux中仍然被支持):voidwriteb(unsignedvalue,address)voidwritew(unsignedvalue,address)voidwritel(unsignedvalue,address)访问IO内存Linux内核也提供了一组函数申请和释放某一范围的IO内存:structresource*requsetmemregion(unsignedlongstart,unsignedlonglen,char*name)  这个函数从内核申请len个内存地址(在G~G之间的虚地址)而这里的start为IO物理地址name为设备的名称。注意。如果分配成功则返回非否则返回。另外可以通过prociomem查看系统给各种设备的内存范围。要释放所申请的IO内存应当使用releasememregion()函数:voidreleasememregion(unsignedlongstart,unsignedlonglen)申请一组IO内存后调用ioremap()函数:void*ioremap(unsignedlongphysaddr,unsignedlongsize,unsignedlongflags)其中三个参数的含义为:physaddr:与requsetmemregion函数中参数start相同的IO物理地址size:要映射的空间的大小flags:要映射的IO空间的和权限有关的标志功能:将一个IO地址空间映射到内核的虚拟地址空间上(通过releasememregion()申请到的)

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

文档小程序码

使用微信“扫一扫”扫码寻找文档

1

打开微信

2

扫描小程序码

3

发布寻找信息

4

等待寻找结果

我知道了
评分:

/6

IO端口和IO内存

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利