IO端口和IO内存

上传人:cjc****537 文档编号:53399414 上传时间:2022-02-10 格式:DOC 页数:7 大小:19KB
收藏 版权申诉 举报 下载
IO端口和IO内存_第1页
第1页 / 共7页
IO端口和IO内存_第2页
第2页 / 共7页
IO端口和IO内存_第3页
第3页 / 共7页
资源描述:

《IO端口和IO内存》由会员分享,可在线阅读,更多相关《IO端口和IO内存(7页珍藏版)》请在装配图网上搜索。

1、I/O端口和I/O内存I/O端口和I/O内存设备驱动程序要直接访问外设或其接口卡上的物理电路,这部分通常都是以寄存器的形式出现。外设寄存器也称为I/O端口,通常包括:控制寄存器、状态寄存器和数据寄存器三大类。根据访问外设寄存器的不同方式,可以把CPU分成两大类。一类CPU(如M68K,Power PC等)把这些寄存器看作内存的一部分,寄存器参与内存统一编址,访问寄存器就通过访问一般的内存指令进行,所以,这种CPU没有专门用于设备I/O的指令。这就是所谓的“I/O内存”方式。另一类CPU(典型地如X86)将外设的寄存器看成一个独立的地址空间,所以访问内存的指令不能用来访问这些寄存器,而要为对外设

2、寄存器的读写设置专用指令,如IN和OUT指令。这就是所谓的” I/O端口”方式 。但是,用于I/O指令的“地址空间”相对来说是很小的。事实上,现在x86的I/O地址空间已经非常拥挤。但是,随着计算机技术的发展,单纯的I/O端口方式无法满足实际需要了,因为这种方式只能对外设中的几个寄存器进行操作。而实际上,需求在不断发生变化,例如,在PC上可以插上一块图形卡,有2MB的存储空间,甚至可能还带有ROM,其中装有可执行代码。自从PCI总线出现后,不管是CPU的设计采用I/O端口方式还是I/O内存方式,都必须将外设卡上的存储器映射到内存空间,实际上是采用了虚存空间的手段,这样的映射是通过ioremap

3、()来建立的。2. 访问I/O端口 in、out、ins和outs汇编语言指令都可以访问I/O端口。内核中包含了以下辅助函数来简化这种访问:inb( )、inw( )、inl( )分别从I/O端口读取1、2或4个连续字节。后缀“b”、“w”、“l”分别代表一个字节(8位)、一个字(16位)以及一个长整型(32位)。inb_p( )、inw_p( )、inl_p( )分别从I/O端口读取1、2或4个连续字节,然后执行一条“哑元(dummy,即空指令)”指令使CPU暂停。outb( )、outw( )、outl( )分别向一个I/O端口写入1、2或4个连续字节。outb_p( )、outw_p(

4、)、outl_p( )分别向一个I/O端口写入1、2或4个连续字节,然后执行一条“哑元”指令使CPU暂停。insb( )、insw( )、insl( )分别从I/O端口读入以1、2或4个字节为一组的连续字节序列。字节序列的长度由该函数的参数给出。outsb( )、outsw( )、outsl( )分别向I/O端口写入以1、2或4个字节为一组的连续字节序列。虽然访问I/O端口非常简单,但是检测哪些I/O端口已经分配给I/O设备可能就不这么简单了,对基于ISA总线的系统来说更是如此。通常,I/O设备驱动程序为了探测硬件设备,需要盲目地向某一I/O端口写入数据;但是,如果其他硬件设备已经使用这个端口

5、,那么系统就会崩溃。为了防止这种情况的发生,内核必须使用“资源”来记录分配给每个硬件设备的I/O端口。资源表示某个实体的一部分,这部分被互斥地分配给设备驱动程序。在这里,资源表示I/O端口地址的一个范围。每个资源对应的信息存放在resource数据结构中:struct resource resource_size_t start; resource_size_t end; const char *name; unsigned long flags; struct resource *parent, *sibling, *child;其字段如表1所示。所有的同种资源都插入到一个树型数据结构(父亲

6、、兄弟和孩子)中;例如,表示I/O端口地址范围的所有资源都包括在一个根节点为ioport_resource的树中。表1: resource数据结构中的字段类型字段描述const char *name资源拥有者的名字unsigned longstart资源范围的开始unsigned longend资源范围的结束unsigned longflags各种标志struct resource *parent指向资源树中父亲的指针struct resource *sibling指向资源树中兄弟的指针struct resource *child指向资源树中第一个孩子的指针节点的孩子被收集在一个链表中,其第一

7、个元素由child指向。sibling字段指向链表中的下一个节点。为什么使用树?例如,考虑一下IDE硬盘接口所使用的I/O端口地址比如说从0xf000 到 0xf00f。那么,start字段为0xf000 且end 字段为0xf00f的这样一个资源包含在树中,控制器的常规名字存放在name字段中。但是,IDE设备驱动程序需要记住另外的信息,也就是IDE链主盘使用0xf000 到 0xf007的子范围,从盘使用0xf008 到 0xf00f的子范围。为了做到这点,设备驱动程序把两个子范围对应的孩子插入到从0xf000 到 0xf00f的整个范围对应的资源下。一般来说,树中的每个节点肯定相当于父节

8、点对应范围的一个子范围。I/O端口资源树(ioport_resource)的根节点跨越了整个I/O地址空间(从端口0到65535)。任何设备驱动程序都可以使用下面三个函数,传递给它们的参数为资源树的根节点和要插入的新资源数据结构的地址:request_resource( )把一个给定范围分配给一个I/O设备。allocate_resource( )在资源树中寻找一个给定大小和排列方式的可用范围;若存在,将这个范围分配给一个I/O设备(主要由PCI设备驱动程序使用,可以使用任意的端口号和主板上的内存地址对其进行配置)。release_resource( )释放以前分配给I/O设备的给定范围。内核

9、也为以上函数定义了一些应用于I/O端口的快捷函数:request_region( )分配I/O端口的给定范围,release_region( )释放以前分配给I/O端口的范围。当前分配给I/O设备的所有I/O地址的树都可以从/proc/ioports文件中获得。3.把I/O端口映射到内存空间-访问I/O端口的另一种方式映射函数的原型为:void *ioport_map(unsigned long port, unsigned int count);通过这个函数,可以把port开始的count个连续的I/O端口重映射为一段“内存空间”。然后就可以在其返回的地址上像访问I/O内存一样访问这些I/O

10、端口。但请注意,在进行映射前,还必须通过request_region( )分配I/O端口。当不再需要这种映射时,需要调用下面的函数来撤消:void ioport_unmap(void *addr);在设备的物理地址被映射到虚拟地址之后,尽管可以直接通过指针访问这些地址,但是工程师宜使用Linux内核的如下一组函数来完成访问I/O内存:读I/O内存unsigned int ioread8(void *addr);unsigned int ioread16(void *addr);unsigned int ioread32(void *addr);与上述函数对应的较早版本的函数为(这些函数在Lin

11、ux 2.6中仍然被支持):unsigned readb(address);unsigned readw(address);unsigned readl(address);写I/O内存void iowrite8(u8 value, void *addr);void iowrite16(u16 value, void *addr);void iowrite32(u32 value, void *addr);与上述函数对应的较早版本的函数为(这些函数在Linux 2.6中仍然被支持):void writeb(unsigned value, address);void writew(unsigned

12、 value, address);void writel(unsigned value, address);4. 访问I/O内存Linux内核也提供了一组函数申请和释放某一范围的I/O内存:struct resource *requset_mem_region(unsigned long start, unsigned long len,char *name); 这个函数从内核申请len个内存地址(在3G4G之间的虚地址),而这里的start为I/O物理地址,name为设备的名称。注意,。如果分配成功,则返回非NULL,否则,返回NULL。另外,可以通过/proc/iomem查看系统给各种设备

13、的内存范围。要释放所申请的I/O内存,应当使用release_mem_region()函数:void release_mem_region(unsigned long start, unsigned long len)申请一组I/O内存后, 调用ioremap()函数:void * ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);其中三个参数的含义为:phys_addr:与requset_mem_region函数中参数start相同的I/O物理地址;size:要映射的空间的大小;flags:要映射的IO空间的和权限有关的标志;功能:将一个I/O地址空间映射到内核的虚拟地址空间上(通过release_mem_region()申请到的)

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!