IO SPACE.doc_第1页
IO SPACE.doc_第2页
IO SPACE.doc_第3页
IO SPACE.doc_第4页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1 I/O空间-I/O端口和I/O内存首先上图,如下:外设中的寄存器被称为I/O端口,外设中的内存被称为I/O内存。二者合起来统称为I/O空间。 设备驱动程序要直接访问外设或其接口卡上的物理电路,这部分通常都是以寄存器的形式出现。外设寄存器称为I/O端口,通常包括:控制寄存器、状态寄存器和数据寄存器三大类。根据访问外设寄存器的不同方式,可以把 CPU分成两大类。一类CPU(如M68K,Power PC,ARM,Unicore等)把这些寄存器看作内存的一部分,寄存器参与内存统一编址,访问寄存器就通过访问一般的内存指令进行,所以,这种CPU没有专门用于设备I/O的指令(可以以此判定体系为哪种)。这就是所谓的“I/O内存”方式。另一类CPU(如X86)将外设的寄存器看成一个独立的地址空间,所以访问内存的指令不能用来访问这些寄存 器,而要为对外设寄存器的读写设置专用指令,如IN和OUT指令。这就是所谓的” I/O端口”方式 。但是,用于I/O指令的“地址空间”相对来说是很小的。事实上,现在x86的I/O地址空间已经非常拥挤。但是,随着计算机技术的发 展,单纯的”I/O端口方式无法满足实际需要了,因为这种方式只能对外设中的几个寄存器进行操作。而实际上,需求在不断发生变化,例如,在PC上可以插上一 块图形卡,有2MB的存储空间(设备内存),甚至可能还带有ROM,其中装有可执行代码。自从PCI总线出现后,不管CPU的设计采用I/O端口方式还是I/O内存方式,都必须将外设卡上的存储器映射到内存空间,实际上是采用了虚存空间的手段,这样的映射是通过ioremap()来建立的。1. CPU是i386架构的情况在i386系列的处理中,内存和外部IO是独立编址,也是独立寻址的。MEM的内存空间是32位可以寻址到4G,IO空间是16位可以寻址到64K。2. 在Linux内核中,访问外设上的IO Port必须通过IO Port的寻址方式。而访问IO Mem就比较罗嗦,外部MEM不能和主存一样访问,虽然大小上不相上下,可是外部MEM是没有在系统中注册的。访问外部IO MEM必须通过remap映射到内核的MEM空间后才能访问。为了达到接口的同一性,内核提供了IO Port到IO Mem的映射函数。映射后IO Port就可以看作是IO Mem,按照IO Mem的访问方式即可。3. CPU是ARM 或PPC或Unicore 架构的情况:在这一类的嵌入式处理器中,IO Port的寻址方式是采用内存映射,也就是IO bus就是Mem bus。系统的寻址能力如果是32位,IO PortMem(包括IO Mem)可以达到4G。访问这类IO Port时,我们也可以用IO Port专用寻址方式。至于在对IO Port寻址时,内核是具体如何完成的,这个在内核移植时就已经完成。在这种架构的处理器中,仍然保持对IO Port的支持,完全是i386架构遗留下来的问题,在此不多讨论。而访问IO Mem的方式和i386一致。RISC指令系统的CPU(如ARM、PowerPC等)通常只实现一个物理地址空间,外设I/O端口成为内存的一部分。此时,CPU可以象访问一个内存单元那样访问外设I/O端口,而不需要设立专门的外设I/O指令。2 I/O端口编址方式先有个概念,I/O端口是CPU对外部设备的抽象。 对一个CPU来说,所有它所管理(或访问)的资源无非包括:1.寄存器组。粗糙的划分通常包括通用寄存器组(x86中就是你用的ex,bx等寄存器),特殊寄存器组(如标志寄存器,timer,interrupt等,当然这些设备你可以看作外部设备) 。2.存储器。粗糙的划分通常包括程序存储器,数据存储器。3.外部设备。比如打印机,PCI桥,USB等等。另外上面timer,interrupt等等有时也按外部设备处理。把这些资源统统放在一个大的集合中,就构成了CPU所管理的资源集。CPU管理这些资源时需要为这个集合中每个元素分配一个标志来区分。这个标志就是地址。编码地址由下面几个要素组成:地址 = 资源类别,资源大小;对CPU指令来说, 通常资源类别编码在指令码中(如i独立编址),也有编码在地址码中(如统一编址),还有直接硬件区分(如哈佛结构的程序存储器与数据存储器分开)。比如x86的in,inp,outp指令,实际上指令码本身就编码有资源类别信息。 资源大小编码在地址码中。按照上面的模型,那么CPU所有资源都可以以地址:资源类别,资源大小 来找到。这里I/O端口就对应实际的物理设备,而I/O空间地址就是该物理设备对应的标志码及设备地址。可以这样说,I/O Space代表所有I/O设备集合,而I/O端口是该集合中的一个元素。 (当然有时直接称I/O端口就是外部设备地址) 。IO 端口和 IO Space 的关系,其实就和 “虚拟地址和地址空间” 的关系一样。 例:虚拟地址 00401000 在 虚拟地址空间:0FFFFFFFF 中。 IO 端口是个物理地址,IO Space 是个物理地址空间。深入一点来说: IO 地址空间范围:0000 FFFF 共16位的空间里,分两种类型映射:固定映射和可变映射。 固定映射,比如 70/71 这些地址是固定的。 可变映射通过对芯片组控制(如南桥)将设备映射在可变地址空间。更进一步来说: IO 地址既可映射到 IO Space(独立编址),有些设备IO地址也可映射到 Memory space (统一编址)中去。同样对(北桥,南桥)进行设置,象 in al,71h 这条指令地址送往 south bridge(南桥)解析,典型就是 cmos 的地址。IO端口两种编址方式:独立编址和统一编制。统一编址:外设接口中的IO寄存器(即IO端口)与主存单元一样看待,每个端口占用一个存储单元的地址,将主存的一部分划出来用作IO地址空间,如,在 PDP-11中,把最高的4K主存作为IO设备寄存器地址。端口占用了存储器的地址空间,使存储量容量减小。统一编址也称为“I/O内存”方式,外设寄存器位于“内存空间”(很多外设有自己的内存、缓冲区,外设的寄存器和内存统称“I/O空间”)。独立编址(单独编址):IO地址与存储地址分开独立编址(I/O地址统一形成I/O Space),I/0端口地址不占用存储空间的地址范围,这样,在系统中就存在了另一种与存储地址无关的IO地 址,CPU也必须具有专用与输入输出操作的IO指令(IN、OUT等)和控制逻辑。独立编址下,地址总线上过来一个地址,设备不知道是给IO端口的、还是给存储器的,于是处理器通过MEMR/MEMW和IOR/IOW两组控制信号来实现对I/O端口和存储器的不同寻址。如,intel 80x86就采用单独编址,CPU内存和I/O是一起编址的,就是说内存一部分的地址和I/O地址是重叠的。 独立编址也称为“I/O端口”方式,外设寄存器位于“I/O(地址)空间”。 对于x86架构来说,通过IN/OUT指令访问。PC架构一共有65536个8bit的I/O端口,组成64K个I/O地址空间,编号从 00xFFFF,有16位,80x86用低16位地址线A0-A15来寻址。连续两个8bit的端口可以组成一个16bit的端口,连续4个组成一个 32bit的端口。I/O地址空间和CPU的物理地址空间是两个不同的概念,例如I/O地址空间为64K,一个32bit的CPU物理地址空间是4G。如,在Intel 8086+Redhat9.0 下用“more /proc/ioports”可看到:0000-001f : dma10020-003f : pic10040-005f : timer0060-006f : keyboard0070-007f : rtc0080-008f : dma page reg00a0-00bf : pic200c0-00df : dma200f0-00ff : fpu0170-0177 : ide1不过Intel x86平台普通使用了名为内存映射(MMIO)的技术,该技术是PCI规范的一部分,IO设备端口被映射到内存空间,映射后,CPU访问IO端口就如同访问内存一样。看Intel TA 719文档给出的x86/x64系统典型内存地址分配表:系统资源占用-BIOS 1M本地APIC 4K芯片组保留 2M IOAPIC 4KPCI设备 256MPCI Express设备 256MPCI设备(可选) 256M显示帧缓存 16MTSEG 1M对于某一既定的系统,它要么是独立编址、要么是统一编址,具体采用哪一种则取决于CPU的体系结构。 如,PowerPC、m68k等采用统一编址,而X86等则采用独立编址,存在IO空间的概念。目前,大多数嵌入式微控制器如ARM、PowerPC等并 不提供I/O空间,仅有内存空间,可直接用地址、指针访问。但对于Linux内核而言,它可能用于不同的CPU,所以它必须都要考虑这两种方式,于是它采用一种新的方法,将基于I/O映射方式的或内存映射方式的I/O端口通称为“I/O区域”(I/O region),不论你采用哪种方式,都要先申请IO区域:request_resource(),结束时释放 它:release_resource()。3 对I/O空间的访问1、访问I/O内存(I/O内存必须映射到内存空间)的流程是:request_mem_region() - ioremap() - ioread8()/iowrite8() - iounmap() - release_mem_region() 。前面说过,IO内存是统一编址下的概念,对于统一编址,IO地址空间是物理主存的一部分,对于编程而言,我们只能操作虚拟内存,所以,访问的第一步就是要把设备所处的物理地址映射到虚拟地址,Linux2.6下用ioremap(): void *ioremap(unsigned long offset, unsigned long size); ioremap()用来将IO资源的物理地址映射到内核虚地址空间(3GB - 4GB)中,参数addr是指向内核虚地址的指针。然后,我们可以直接通过指针来访问这些地址,但是也可以用Linux内核的一组函数来读写: ioread8(), iowrite16(), ioread8_rep(), iowrite8_rep().2、访问I/O端口访问IO端口有2种途径(对于独立编址系统体系):I/O映射方式(I/Omapped)、内存映射方式(Memorymapped

温馨提示

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

评论

0/150

提交评论