Linux内核完全注释 阅读笔记:2.4、控制器和控制卡
 2018.09.05    |      Linux内核完全注释    |     AilsonJack    |     暂无评论    |     703 views
By: Ailson Jack
Date: 2018-09-04
个人博客: http://www.only2fire.com/
<p class="artical_littlestyle1">1、中断控制器</p><p style="text-indent: 2em;">80x86兼容机使用两片级联的8259A可编程中断控制芯片组成一个中断控制器,用于实现I/O设备的中断控制数据存取方式,并且能为15个设备提供独立的中断控制功能,如下图所示:</p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.09.05/1536146498722002.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.09.05/1536146498722002.png&#39;)"/></p><p style="text-indent: 2em; text-align: left;">当一台PC机刚上电时,上图中的硬件中断请求号会被ROM BIOS设置成下表所示的对应中断向量号。Linux操作系统并不直接使用这些PC机默认设置好的中断向量号,当Linux系统执行初始化操作时,它会重新设置中断请求号与中断向量号的对应关系。<br/></p><p style="text-indent: 2em; text-align: center;">表2-2 开机时ROM BIOS设置的硬件请求处理中断号<br/></p><table><tbody><tr class="firstRow"><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">中断请求号</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">BIOS设置的中断号</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">用途</td></tr><tr><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">IRQ0</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">0x08(8)</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">8253发出的100HZ时钟中断</td></tr><tr><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">IRQ1<br/></td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">0x09(9)</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">键盘中断</td></tr><tr><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">IRQ2<br/></td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">0x0A(10)</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">连接从芯片</td></tr><tr><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">IRQ3</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">0x0B(11)</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">串行口2</td></tr><tr><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">IRQ4</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">0x0C(12)</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">串行口1</td></tr><tr><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">IRQ5</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">0x0D(13)</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">并行口2</td></tr><tr><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">IRQ6</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">0x0E(14)</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">软盘驱动器</td></tr><tr><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">IRQ7</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">0x0F(15)</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">并行口1</td></tr><tr><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">IRQ8</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">0x70(112)</td><td style="word-break: break-all; border-width: 1px; border-style: solid;" width="349" valign="top">实时钟中断</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">IRQ9<br/></td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x71(113)</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">改向至INT 0x0A</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">IRQ10</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x72(114)</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">IRQ11</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x73(115)</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">IRQ12</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x74(116)</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">PS/2鼠标口中断</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">IRQ13</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x75(117)</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">IRQ14</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x76(118)</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">IRQ15<br/></td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x77(119)</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top"><p>保留</p></td></tr></tbody></table><p><br/></p><p class="artical_littlestyle2">2、DMA控制器</p><p style="text-indent: 2em;">通常DMA控制器由机器上的Intel 8237芯片或其兼容芯片实现。通过对DMA控制器进行编程,外设与内存之间的数据传输能在不受CPU控制的条件下进行,因此在数据传输期间,CPU可以做其他事情。<br/></p><p style="text-indent: 2em;">在PC机中,使用了两片8237芯片,因此DMA控制器有8个独立的通道可供使用。其中后4个是16位通道,软盘控制器被专门指定使用DMA通道2。在使用一个DMA通道之前,涉及到对3个端口的设置:页面寄存器端口、(偏移)地址寄存器端口和数据计数寄存器端口。由于DMA寄存器是8位的,而地址和计数值是16位的,因此各自需要发送两次。<br/></p><p class="artical_littlestyle3">3、定时/计数器</p><p style="text-indent: 2em;">Intel 8253/8254是一个可编程定时/计数器(PIT-Programmable Interval Timer)芯片,用于处理计算机中的精确时间延迟。该芯片提供了3个独立的16位计数器通道,每个通道可工作在不同的工作方式下,并且这些工作方式均可以使用软件来进行设置。在软件中进行延时的一种方法是执行循环操作语句,但这样做很耗CPU时间。若机器中采用了8253/8254芯片,那么程序员就可以配置8253以满足自己的要求,并且使用其中一个计数器通道达到所期望的延时。在延时时间到了后,8253/8254将会向CPU发送一个中断信号。<br/></p><p style="text-indent: 2em;">对于PC及其兼容微机系统所采用的是8254芯片。3个定时/计数器通道被分别用于日时钟计时中断信号、动态内存DRAM刷新定时电路和主机扬声器音调合成。Linux 0.11操作系统只对通道0进行了重新设置,使得该计数器工作在方式3下,并且每间隔10ms发出一个信号以产生中断请求信号(IRQ0)。这个间隔定时产生的中断请求就是Linux 0.11内核工作的脉搏,它用于定时切换当前执行的任务和统计每个任务所使用的系统资源量(时间)。<br/></p><p class="artical_littlestyle4">4、键盘控制器</p><p style="text-indent: 2em;">当一个键被按下时,键盘发送的扫描码称为接通扫描码(Make code),或简称为接通码;当一个被按下的按键放开时发送的扫描码被称为断开扫描码(Break code),或简称为断开码。<br/></p><p style="text-indent: 2em;">主机键盘控制器专门用来对接收到的键盘扫描码进行解码,并把解码后的数据发送到操作系统的键盘数据队列中。因为每个按键的接通和断开码是不同的,所以键盘控制器根据扫描码就可以确定用户在操作哪个按键。整个键盘上所有按键的接通和断开码就组成了键盘的一个扫描码集(Scan Code Set)。根据计算机的发展,目前已经有3套扫描码集可供使用,它们分别是:<br/></p><p style="text-indent: 2em;">a、第一套扫描码集:原始XT键盘扫描码集。目前的键盘已经很少发送这类扫描码;<br/></p><p style="text-indent: 2em;">b、第二套扫描码集:现代键盘默认使用的扫描码集,通常称为AT键盘扫描码集;<br/></p><p style="text-indent: 2em;">c、第三套扫描码集:PS/2键盘扫描码集。原IBM推出PS/2微机时使用的扫描码集,已很少使用。<br/></p><p style="text-indent: 2em;"><span style="color: rgb(0, 112, 192);">AT键盘默认发送的是第二套扫描码集,虽然如此,主机键盘控制器为了与PC/XT机的软件兼容,仍然会把所有接收到的第二套键盘扫描码转换成第一套键盘扫描码,如图2-7所示。</span>因此,我们在为键盘控制器进行编程时通常只需要了解第一套键盘扫描码即可。这也是后面涉及键盘编程内容时,只给出XT键盘扫描码集的原因。<br/></p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.09.05/1536146498536944.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.09.05/1536146498536944.png&#39;)"/></p><p style="text-indent: 2em;">键盘控制器通常采用Intel 8042单片微处理器芯片或其兼容电路。现在的PC机都已经将键盘控制器集成在主板芯片组中,但是功能仍然与使用8042芯片的控制器相兼容。<span style="color: rgb(0, 112, 192);">键盘控制器接收键盘发送来的11位串行格式数据。其中第1位是起始位,第2-9位是8位键盘扫描码,第10位是奇校验校验位,第11位是停止位。</span>键盘控制器在接收到11位的串行数据后就将键盘扫描码转换成PC/XT标准键盘兼容的系统扫描码,然后通过中断控制器IRQ1引脚向CPU发送中断请求,当CPU响应该中断请求后,就会调用键盘中断处理程序来读取控制器中的XT键盘扫描码。<br/></p><p style="text-indent: 2em;">当一个按键被按下时,我们可以从键盘控制器端口接收到一个XT键盘接通码。例如,按下键’A’的接通码是30(0x1E)。当一个按下的键被松开时,从键盘控制器端口收到的就是一个断开码。<span style="color: rgb(0, 112, 192);">对于XT键盘,断开码是其接通码加上0x80,即最高有效位(bit7)置位时的接通码。</span>例如,’A’键的断开码就是0x1E + 0x80 = 0x9E。<span style="color: rgb(0, 112, 192);"><br/></span></p><p style="text-indent: 2em;"><span style="color: rgb(0, 112, 192);">对于那些PC/XT标准83键键盘以后新添加的AT键盘上的按键(例如右边的Ctrl键和右边的Alt键等),则其接通和断开扫描码通常有2到4个字节,并且第1个字节一定是0xE0。例如,按下左边的非扩展Ctrl键时,会产生1字节接通码0x1D;而按下右边的Ctrl键时就会产生扩展的2字节接通码0XE0、0x1D,对应的断开码是0xE0、0x9D。</span><br/></p><p class="artical_littlestyle1">5、串行控制卡</p><p style="text-indent: 2em;">串行通信是指在线路上以比特位数据流一次一个比特进行传输的通信方式。串行通信分为同步和异步两种类型,它们之间的主要区别在于传输时同步的通信单位或帧的长度不同。异步串行通信以一个字符作为一个通信单位或一帧进行传输,而同步串行通信则以多个字符或字节组成的序列作为一帧数据进行传输。<br/></p><p style="text-indent: 2em;">异步串行通信传输的帧格式如下图2-9所示。传输一个字符由起始位、数据位、奇偶校验位和停止位组成。其中起始位起同步作用,其值恒为0。数据位是传输的实际数据,其长度可以是5~8个比特。奇偶校验位可有可无,由程序设定。停止位恒为1,可由程序设定为1、1.5或2个比特位。在通信开始发送信息之前,双方必须设置成相同的格式,如具有相同数量的数据比特位和停止位。在异步通信规范中,把传送1称为传号(MARK),传送0称为空号(SPACE)。</p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.09.05/1536146498912675.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.09.05/1536146498912675.png&#39;)"/></p><p style="text-indent: 2em;">为实现串行通信,PC机上通常都带有2个符合RS-232C标准的串行接口,并使用通用异步接收/发送器控制芯片UART(Universal Asyncronous Receiver/Transmitter)组成的串行控制器来处理串行数据的收发工作。<br/></p><p style="text-indent: 2em;">以前的PC机都使用NS8250或NS16450 UART芯片。现在的PC机使用16650A及其兼容芯片,它支持FIFO传输方式,在这种方式下,UART可以在接收或者发送了最多16个字符后才引发一次中断,从而可以减轻系统和CPU的负担。当PC机上电启动时,系统RESET信号通过NS8250的MR引脚是的UART内部寄存器和控制逻辑复位。此后要使用UART就需要对其进行初始化编程操作,来设置UART的波特率、数据位以及工作方式等。<br/></p><p class="artical_littlestyle2">6、显示控制</p><p style="text-indent: 2em;">对于PC及其兼容机,可以使用彩色和单色显示卡。IBM最早推出的PC机视频系统标准有单色MDA标准,彩色CGA标准以及EGA和VGA标准。以后推出的所有高级显示卡(包括现在的AGP显示卡)虽然都具有极高的图形处理速度和智能加速处理功能,但它们都还是支持这几种标准。Linux 0.1.x操作系统仅使用了这几种标准都支持的文本显示方式。<br/><span style="background-color: rgb(118, 146, 60);">(1)、</span>MDA显示标准<br/></p><p style="text-indent: 2em;">单色显示适配器MDA(Monochrome Display Adapter)仅支持黑白两种颜色显示。并且只支持独有的文本字符显示方式(BIOS显示方式为7)。其屏幕显示规格为80列x25行(列号x=0…79,行号y=0…24),共可显示2000个字符。<span style="color: rgb(255, 0, 0);">每个字符还带有一个属性字节</span>,因此显示一屏(一帧)内容需要占4KB字节(2000*2=4000B)。其中偶地址字节存放字符代码,奇地址字节存放显示属性。MDA卡配置有8KB显示内存。在PC机内存寻址范围中,占用从0xB0000开始的8KB空间(0xB0000---0xB2000)。<span style="color: rgb(0, 112, 192);">如果显示屏行数是video_num_lines=25,列数是video_num_colums=80,那么位于屏幕列行值x、y处的字符和属性在内存中的位置是</span>:<br/></p><p style="text-indent: 2em;"><span style="color: rgb(255, 0, 0);">字符字节位置 = 0xB0000 + video_num_colums*2*y + x*2;<br/></span></p><p style="text-indent: 2em;"><span style="color: rgb(255, 0, 0);">属性字节位置 = 字符字节位置 + 1;</span><br/></p><p style="text-indent: 2em;">在MDA单色文本显示方式中,每个字符的属性字节格式如表2-4所示。其中,D7置1会使字符闪烁,D3置1会使字符高亮度显示。它与图2-10中的彩色文本字符的属性字节基本一致,但只有两种颜色:白色(0x111)和黑色(0x000)。</p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.09.05/1536146498413422.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.09.05/1536146498413422.png&#39;)"/></p><p style="text-indent: 0em;"><span style="background-color: rgb(118, 146, 60);">(2)、</span>CGA显示标准<br/></p><p style="text-indent: 2em;">彩色图形适配器CGA(Color Graphics Adapter)支持7种彩色和图形显示方式(BIOS显示方式0---6)。在80列x25行的文本字符显示方式下,有单色和16色彩色两种显示方式(BIOS显示方式2---3)。CGA卡标配有16KB显示内存(占用内存地址范围:0xB8000---0xBC000),因此其中共可以存放4帧显示信息。同样,在每一帧4KB显示内存中,偶地址字节存放字符代码,奇地址字节存放显示属性。但在console.c程序中只使用了其中8KB显示内存(0xB8000 --- 0xBA000)。在CGA彩色文本显示方式中,每个显示字符的属性字节格式定义如图2-10所示:<br/></p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.09.05/1536146498711140.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.09.05/1536146498711140.png&#39;)"/></p><p style="text-indent: 2em;">与单色显示一样,图中D7置1用于让显示字符闪烁,D3置1用于让字符高亮度显示,比特位D6、D5、D4和D2、D1、D0可以分别组合出8种颜色。前景色与高亮度比特位组合可以显示另外8种字符颜色。这些组合的颜色见表2-5所示:</p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.09.05/1536146501523555.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.09.05/1536146501523555.png&#39;)"/></p><p style="text-indent: 0em;"><span style="background-color: rgb(118, 146, 60);">(3)、</span>EGA/VGA显示标准<br/></p><p style="text-indent: 2em;">增强型图形适配器EGA(Enhanced Graphics Adapter)和视频图形阵列VGA(Video Graphics Adapter)除兼容或支持MDA和CGA的显示方式以外,还支持其他在图形显示方面的增强显示方式。在与MDA和CGA兼容的显示方式下,占用的内存地址起始位置和范围都分别相同。但EGA/VGA都标配有起码32KB的显示内存。在图形方式下占用从0xA0000开始的物理内存地址空间。<br/></p><p class="artical_littlestyle3">7、软盘和硬盘控制器</p><p style="text-indent: 2em;">在盘片上存储数据的基本方式是利用盘片表面上的一层磁性介质在磁化后的剩磁状态。软盘通常使用聚酯薄膜作基片,而硬盘片则通常使用金属铝合金作基片。一张软盘中含有一张聚酯薄膜圆盘片,使用上下两个磁头在盘片两面读写数据,盘片旋转速率大约300转/分钟。硬盘中通常起码包括2张或更多张金属盘片,因此具有多个读写磁头。例如,对于包含2个盘片的硬盘中就具有4个物理磁头,含有4个盘片的磁盘中有8个读写磁头。如图2-11所示。磁盘旋转速率很快,通常在4500转/分钟到10000转/分钟,因此磁盘数据的传输速度通常可以达到几十兆比特/秒。<br/></p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.09.05/1536146501454159.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.09.05/1536146501454159.png&#39;)"/></p><p style="text-indent: 2em;">为了读写磁盘(软盘和硬盘)上的数据,就必须使用磁盘控制器。磁盘控制器是CPU和驱动器之间的逻辑接口电路,它从CPU接收请求命令,向驱动器发送寻道、读/写和控制信号,并且控制和转换数据流形式。<br/></p><p style="text-indent: 2em;">PC机中软盘驱动控制器FDC(Floopy Disk Controller)采用的是NEC μPD765或其兼容芯片。它主要用于接收CPU发出的命令,并根据命令要求向驱动器输出各种硬件控制信号,见图2-13所示。在执行读/写操作时,它需要完成数据的转换(串---并)、编码和校验操作,并且时刻监视驱动器的运行状态。</p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.09.05/1536146505192332.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.09.05/1536146505192332.png&#39;)"/></p><p style="text-indent: 2em;">对磁盘控制器的编程过程就是通过I/O端口设置控制器中的相关寄存器内容,并通过寄存器获取操作的结果信息。至于扇区数据的传输,则软盘控制器与硬盘控制器不同。软盘控制器电路采用DMA信号,因此需要使用DMA控制器实施数据传输。而硬盘控制器采用高速数据块进行传输,不需要DMA控制器的介入。<br/></p><p style="text-indent: 2em;">由于软盘片比较容易遭到损坏(发霉或划伤),因此目前计算机中已经逐渐开始不配置软盘驱动器,取而代之的是使用容量较大并且更容易携带的U盘存储器。<br/></p>
欢迎关注博主的公众号呀,精彩内容随时掌握:
热情邀请仔细浏览下博客中的广告,万一有对自己有用或感兴趣的呢。◕ᴗ◕。。
如果这篇文章对你有帮助,记得点赞和关注博主就行了^_^,当然了能够赞赏博主,那就非常感谢啦!
注: 转载请注明出处,谢谢!^_^
暂无评论,要不要来个沙发
发表评论

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