Linux内核完全注释 阅读笔记:2.2、I/O端口寻址和访问控制方式
 2018.09.03    |      Linux内核完全注释    |     AilsonJack    |     暂无评论    |     483 views
By: Ailson Jack
Date: 2018-09-02
个人博客: http://www.only2fire.com/
<p class="artical_littlestyle1">1、I/O端口和寻址</p><p style="text-indent: 2em;">CPU为了访问I/O接口控制器或控制卡上的数据和状态信息,需要首先指定它们的地址。这种地址就称为I/O端口地址或者简称端口。通常一个I/O控制器包含访问数据的数据端口、输出命令的命令端口和访问控制器执行状态的状态端口。端口地址的设置方法一般有两种:统一编址和独立编址。<br/></p><p style="text-indent: 2em;">端口统一编址的原理是把I/O控制器中的端口地址归入存储器寻址地址空间范围内。因此这种编址方式也称为存储器映像编址。CPU访问一个端口的操作与访问内存的操作一样,也使用访问内存的指令。端口独立编址的方法是把I/O控制器和控制卡的寻址空间单独作为一个独立的地址空间对待,称为I/O地址空间。每个端口有一个I/O地址与之对应,并且使用专门的I/O指令来访问端口。<br/></p><p style="text-indent: 2em;">IBM PC及其兼容微机主要使用独立编址方式,采用了一个独立的I/O地址空间对控制设备中的寄存器进行寻址和访问。使用ISA总线结构的传统PC机其I/O地址空间范围是0x000~0x3ff,有1024个I/O端口地址可供使用。各个控制器和控制卡所默认分配使用的端口地址范围如下表所示:<br/></p><p style="text-indent: 2em; text-align: center;">表2-1 I/O端口地址分配</p><table><tbody><tr class="firstRow"><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">端口地址范围</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">分配说明</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x000 --- 0x01F<br/></td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">8237A DMA控制器1</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x020 --- 0x03F</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">8259A可编程中断控制器1</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x040 --- 0x05F</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">8253/8254A 定时计数器</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x060 --- 0x06F</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">8042键盘控制器</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x070 --- 0x07F</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">访问CMOS RAM/实时时钟RTC(Real Time Clock)端口</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x080 --- 0x09F</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">DMA页面寄存器访问端口</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x0A0 --- 0x0BF</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">8259A可编程中断控制器2<br/></td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x0C0 --- 0x0DF</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">8237A DMA控制器2</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x0F0 --- 0x0FF</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">协处理器访问端口</td></tr><tr><td colspan="1" rowspan="1" style="border-width: 1px; word-break: break-all; border-style: solid;" valign="top">0x170 --- 0x177</td><td colspan="1" rowspan="1" style="border-width: 1px; word-break: break-all; border-style: solid;" valign="top">IDE硬盘控制器1</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x1F0 --- 0x1F7</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">IDE硬盘控制器0</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x278 --- 0x27F</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">并行打印机端口2</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x2F8 --- 0x2FF</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">串行控制器2</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x378 --- 0x37F</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">并行打印机端口1</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x3B0 --- 0x3BF</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">单色MDA显示控制器</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x3C0 --- 0x3CF</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">彩色CGA显示控制器</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x3D0 --- 0x3DF</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">彩色EGA/VGA显示控制器</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x3F0 --- 0x3F7</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">软盘控制器</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x3F8 --- 0x3FF</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">串行控制器1<br/></td></tr></tbody></table><p style="text-indent: 2em; text-align: left;">另外,IBM PC机也部分的使用了统一编址方式。例如,CGA显示卡上显示内存的地址就直接占用了存储器地址空间0xB800 --- 0xBC00范围。因此若要让一个字符显示在屏幕上,可以直接使用内存操作指令往这个内存区域执行写操作。<br/></p><p style="text-indent: 2em; text-align: left;">对于使用EISA或者是PCI等总线结构的现代PC机,有64KB的I/O地址空间可供使用。在普通Linux系统下通过查看/proc/ioports文件可以得到相关控制器或设置使用的I/O地址范围,如下如所示:<br/></p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.09.03/1535981030585281.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.09.03/1535981030585281.png&#39;)"/></p><p class="artical_littlestyle2">2、接口访问控制</p><p style="text-indent: 2em; text-align: left;">PC机I/O接口数据传输控制方式一般可采用:<span style="color: rgb(0, 112, 192);">程序循环查询方式</span>、<span style="color: rgb(0, 112, 192);">中断处理方式</span>和<span style="color: rgb(0, 112, 192);">DMA传输方式</span>。<br/></p><p style="text-indent: 2em; text-align: left;">循环查询方式是指CPU通过在程序中循环查询指定设备控制器中的状态来判断是否可以与设备进行数据交互。这种方式不需要过多的硬件支持,使用和编程都比较简单,但是特别耗费CPU宝贵的时间。因此在多任务操作系统中,除非等待时间极短或必须,否则就不应该使用这种方式。在Linux操作系统中,只有在设备或控制器能够立刻返回信息时,才会在很少的几个地方采用这种方式。<br/></p><p style="text-indent: 2em; text-align: left;">中断处理控制方式需要中断控制器的支持。在这种控制方式下,只有当I/O设备通过中断向CPU提出处理请求时,CPU才会暂时中断当前执行的程序转而去执行相应的I/O中断处理服务程序。当执行完该中断处理服务程序后,CPU又会继续执行刚才被中断的程序。在I/O控制器或设备发出中断请求时,CPU通过使用中断向量表(或中断描述表)来寻址相对应的中断处理服务程序的入口地址。因此采用中断控制方式时,要首先设置好中断向量表,并编制好相应的中断处理服务程序。Linux操作系统中,大多数设备I/O控制都采用中断处理方式。<br/></p><p style="text-indent: 2em; text-align: left;">直接存储器访问DMA(Direct Memory Access)方式用于I/O设备与系统内存间进行批量数据传送,整个操作过程需要使用专门的DMA控制器来进行而无需CPU插手。由于在传输过程中不需要软件介入,因此操作效率很高。在Linux操作系统中,软盘驱动程序使用中断和DMA方式配合来实现数据的传输工作。<br/></p>
欢迎关注博主的公众号呀,精彩内容随时掌握:
热情邀请仔细浏览下博客中的广告,万一有对自己有用或感兴趣的呢。◕ᴗ◕。。
如果这篇文章对你有帮助,记得点赞和关注博主就行了^_^,当然了能够赞赏博主,那就非常感谢啦!
注: 转载请注明出处,谢谢!^_^
暂无评论,要不要来个沙发
发表评论

 
Copyright © 2015~2023  说好一起走   保留所有权利   |  百度统计  蜀ICP备15004292号