当前位置:文档之家› 字符设备驱动程序

字符设备驱动程序

字符设备驱动程序字符设备驱动程序与块设备不同。

所涉及的键盘驱动、控制台显示驱动和串口驱动以及与这些驱动有关的接口、算法程序都紧密相关。

他们共同协作实现控制台终端和串口终端功能。

下图反映了控制台键盘中断处理过程。

以上为总的处理流程,下面对每一个驱动分开分析。

首先是键盘驱动。

键盘驱动用汇编写的,比较难理解,牵涉内容较多,有键盘控制器804X的编程,还有扫描码(共3套,这里用第二套)和控制命令及控制序列(p209~210有讲解)。

由于键盘从XT发展到AT到现在PS/2,USB,无线键盘,发展较快,驱动各有不同,此版本驱动为兼容XT,将扫描码映射为XT再处理,因此仅供参考。

CNIX操作系统的键盘驱动实现为C语言,可读性更好。

键盘驱动键盘驱动就是上图键盘硬件中断的过程。

keyboard.S中的_keyboard_interrupt函数为中断主流程,文件中其他函数均被其调用。

以上打星处为键盘驱动的核心,即主要处理过程,针对不同扫描码分别处理,并最终将转换后所得ASCII 码或控制序列放入控制台tty 结构的读缓冲队列read_q 中。

键处理程序跳转表为key_table ,根据扫描码调用不同处理程序,对于“普通键”,即只有一个字符返回且没有含义变化的键,调用do_self 函数。

其他均为“特殊键”:1. crtrl 键的按下和释放 2. alt 键的按下和释放 3. shift 键的按下和释放 4. caps lock 键的按下和释放(释放直接返回,不作任何处理) 5. scroll lock 键的按下 6. num lock 的按下 7. 数字键盘的处理(包括alt-ctrl+delete 的处理,因为老式键盘delete 键在数字小键盘上。

还包括对光标移动键的分别处理) 8. 功能键(F1~F12)的处理 9. 减号的处理(老键盘’/’与’-’以0xe0加以区分,可能其中一键要按shift )do_self 是最常用的流程,即跳转表中使用频率最高的流程:控制台程序控制台程序分两部分:1. 控制台初始化 2. 控制台写函数控制台初始化函数根据EGA单色、MDA单色、EGA彩色、CGA各种显卡设置显卡类型、显存占用内存的起始地址、结束地址、显示索引寄存器端口和显示数据寄存器端口。

并将显卡类型打印在屏幕上。

初始化滚屏变量和光标位置,设置键盘中断陷阱门,复位键盘。

控制台写函数从终端对应的tty写缓冲队列中取字符,并显示在屏幕上。

思路是利用状态机原理对缓冲队列中的字符逐一处理(若是字符写在显存对应位置,若是光标,设置光标位置),最后向显示控制器发送光标显示位置。

上图中黑虚线表示不退出case循环读取下一字符,而是直接转到下一状态。

状态1的5、6与状态4的18、19相同。

(?)表示可能包含?串口程序一、串行通信原理通信方式:方向、连接、异步/同步;速度控制:波特率控制、收/发时钟、基准时钟; 差错控制:单/双端、信号重复、检错和纠错编码; 长距离传输:信号调制(调频、调幅、调相); 通道共享:时分多路、频分多路;通信协议:异步串行/同步串行通信协议;接口标准:类型(信号定义、逻辑特性、电气特性、机械特性)二、起止式异步串行通信协议通信前约定—波特率、字符(数据/校验/结束)格式;字符识别—空闲状态、字符开始、数据格式、字符结束、起点漂移解决; 抗干扰(信号重复)实现--起始位采样、数据采样; 字符正确性—校验码编码技术、检错与纠错三、串行通信接口标准标准类型:RS-232C 、RS-422A 、RS-423、RS-485 RS-232C 接口标准:信号定义:RxD、TxD、SG、DTR/DSR、RTS/CTS、DCD、RI逻辑特性:连接、信号使用/不使用MODEM时握手规则电气特性:信号电平、电平转换机械特性:连接器、有效传输距离四、INS8250内部结构内部总体结构中断控制逻辑LSRINTPRT端口定义和寄存器定义LCR—使用时,最后一次使D7=0并设置其它位;DLH/DLL—值为基准时钟频率÷(16×波特率);IIR—中断请求→IIR过程,对IIR读操作时其值的变化原理;与程序关系紧密的硬件是除数寄存器、接受缓冲、发送缓冲、中断允许寄存器、以及通信线路和Modem的控制和状态寄存器。

所谓的DLH/DLL值在除数寄存器中设定,即波特率因子。

同步控制时会以当前设定波特率的16倍频控制每一位信号的脉冲保持时间(即如果要求高信号必须是保持10ms,则同步控制会以10/16ms 的时间精度保证16次的10/16ms都为高脉冲),接收到信号以同样的原理检测信号。

(通常检测16倍频中的第7,8,9三个倍频处的脉冲,以少数服从多数原则判断脉冲的高低)。

中断的屏蔽与否取决于中断允许寄存器。

中断产生后都在中断标识寄存器中置位。

因此只要有中断标识在中断标识寄存器中置位且不屏蔽就会发出中断。

在实际处理中,在串口中断处理中循环判断是否在处理完上一中断后已产生下一中断,若有则直接处理,提高了效率。

串口程序分为初始化部分serial.c和中断处理部分rs_io.s。

串口初始化相当简单:串口中断处理程序也很简单:针对4个中断源的处理函数中两个函数:Modem状态改变的处理和接收状态有错处理都未作实际处理,只是复位相应寄存器。

另两个函数为已接收到数据处理和发送保持寄存器空的处理。

接收到数据中断的处理(read_char函数)(与读队列read_q 交互)发送保持寄存器空中断的处理(write_char函数)(与写队列write_q交互)字符设备(终端)的上层接口tty_io.c和tty_ioctl是终端(控制台和串口终端)的上层接口实现其实除了copy_to_cooked()函数提供完全供内核使用外。

字符设备接口函数(即与用户程序的接口)就三个:tty_read(),tty_write()和tty_ioctl()与用户程序的接口函数的特征是以设备号作为参数,而不会以某个内核数据结构作为参数。

tty_read函数实现用户接口从tty队列的secondary队列中读取字符。

读取的规则由p378的MIN和TIME机制决定。

tty_write函数将用户缓冲区的字符写入tty的write_q队列,未写完或write_q满了则睡眠,直到写完为止。

tty_iotcl是用户程序用来设置或取得tty设备(控制台终端或串口终端)参数的。

如设置或取得termios结构的属性、设置波特率。

获取或设置终端设备进程的组id等。

还有很多功能Linux0.11未实现,估计是为了兼容POSIX标准,已预留了接口。

tty_read(),tty_write()在系统中的位置如下图:值得一提的是tty_queue缓冲队列结构中缓冲区的算法,采用的是循环缓冲区的算法:tail指针处取字符,head指针处插字符。

tail取完一字符和head插完一字符,都将指针增1。

到了边界再转到缓冲区开头,详见p410 23~34行缓冲区操作宏函数。

缓冲区的数据结构如下图:tty_io.c和tty_ioctl.c两文件中与用户接口无关,只在内核中使用的函数是copy_to_cooked()函数。

它的功能是1. 将read_q中的字符复制成规范模式字符放在secondary队列中。

2. 对键盘中断符进行处理:向当前进程发送键盘中断信号,键盘退出信号。

3. 如果设置了回显标志,将相应字符放入write_q队列并调用tty->write直接输出到屏幕(con_write)或从串口输出(rs_write)4. 最后唤醒等待secondary的进程。

Linux0.11字符设备部分总结该部分尽管有键盘、显卡、串口的硬件驱动程序,但它们通过中断串联在了一起,即相互间紧密相关。

相关的方式是以功能为导向:1. 控制台终端 2. 串口终端1.控制台终端,见下面两图。

是以键盘中断触发的中断处理过程:键盘中断处理(扫描码转ASCII码或CSI)->行规则程序(copy_to_cooked)->屏幕显示(显卡驱动con_write,显示字符及光标位置和完成滚屏功能)2.串口驱动,与键盘只有一个中断源(按键)不同,串口有4个中断源,Linux0.11只对接收到数据中断和发送数据中断处理(其余2个只是复位寄存器,暂未处理)。

对于接收到数据中断:上图为串口中断接收到数据后的处理过程。

rs_write的作用是开启写保持空寄存器空中断,此中断会调用write_char中断处理程序。

因此此时是中断嵌套中断。

概括起来也是3步:串行口接收到字符中断->行规则程序(copy_to_cooked)->串口输出(开启写保持寄存器空中断,在中断中调用write_char将write_q中的字符全部输出)对于发送数据中断的处理上图为串口写保持寄存器空时的处理过程。

之前须调用rs_write开启发送保持寄存器空中断。

由上述分析可知,Linux0.11内核的字符设备驱动程序之间关系紧密相关,共同完成控制台终端或串口终端的功能。

管理它们的数据结构设计得也很巧妙:用户接口只能通过传入的设备号来索引tty_table数组从而查询或设置tty设备(控制台或串口终端)的参数。

核心数据结构即为tty_struct,其中又包含了termios结构用来管理控制台和三个tty_queue结构的队列(read_q、write_q、secondary)。

设计很巧妙。

tty_table中有3个tty_struct结构,用来支持控制台、串口1、串口2。

该数组在tty_io.c程序中被初始化,属内核全局数组。

因此只要键盘、串口、显卡被初始化后,字符设备的功能就可(通过中断)自动运行起来。

相关主题