⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 61.html

📁 linux 0.11中文版 有注释
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<html>
<head>
<title>kernel/chr_drv/keyboard.S</title>
<meta name='robots' content='noindex,nofollow'>
<meta name='generator' content='GLOBAL-5.4.1'>
</head>
<body text='#191970' bgcolor='#f5f5dc' vlink='gray'>
<a name='TOP'><h2><a href='../mains.html'>root</a>/<a href='../files/104.html'>kernel</a>/<a href='../files/106.html'>chr_drv</a>/keyboard.S</h2>
<i><font color='green'>/* [&lt;][&gt;][^][v][top]<a href='#BOTTOM'>[bottom]</a><a href='../mains.html'>[index]</a><a href='../help.html'>[help]</a> */</font></i>
<hr>
<pre>
<a name='L1'><i><font color='green'>/*</font></i>
<a name='L2'><i><font color='green'>* linux/kernel/keyboard.S</font></i>
<a name='L3'><i><font color='green'>*</font></i>
<a name='L4'><i><font color='green'>* (C) 1991 Linus Torvalds</font></i>
<a name='L5'><i><font color='green'>*/</font></i>
<a name='L6'>
<a name='L7'><i><font color='green'>/*</font></i>
<a name='L8'><i><font color='green'>* Thanks to Alfred Leung for US keyboard patches</font></i>
<a name='L9'><i><font color='green'>* Wolfgang Thiel for German keyboard patches</font></i>
<a name='L10'><i><font color='green'>* Marc Corsini for the French keyboard</font></i>
<a name='L11'><i><font color='green'>*/</font></i>
<a name='L12'><i><font color='green'>/*</font></i>
<a name='L13'><i><font color='green'>* 感谢Alfred Leung 添加了US 键盘补丁程序;</font></i>
<a name='L14'><i><font color='green'>* Wolfgang Thiel 添加了德语键盘补丁程序;</font></i>
<a name='L15'><i><font color='green'>* Marc Corsini 添加了法文键盘补丁程序。</font></i>
<a name='L16'><i><font color='green'>*/</font></i>
<a name='L17'>
<a name='L18'><font color='darkred'>#include</font> &lt;<a href='30.html'>linux/config.h</a>&gt; <i><font color='green'>// 内核配置头文件。定义键盘语言和硬盘类型(HD_TYPE)可选项。</font></i>
<a name='L19'>
<a name='L20'>.text
<a name='L21'>.globl _keyboard_interrupt
<a name='L22'>
<a name='L23'><i><font color='green'>/*</font></i>
<a name='L24'><i><font color='green'>* these are for the keyboard read functions</font></i>
<a name='L25'><i><font color='green'>*/</font></i>
<a name='L26'><i><font color='green'>/*</font></i>
<a name='L27'><i><font color='green'>* 以下这些是用于键盘读操作。</font></i>
<a name='L28'><i><font color='green'>*/</font></i>
<a name='L29'><i><font color='green'>// size 是键盘缓冲区的长度(字节数)。</font></i>
<a name='L30'>size = 1024 <i><font color='green'>/* must be a power of two ! And MUST be the same</font></i>
<a name='L31'><i><font color='green'>as in tty_io.c !!!! */</font></i>
<a name='L32'><i><font color='green'>/* 数值必须是2 的次方!并且与tty_io.c 中的值匹配!!!! */</font></i>
<a name='L33'><i><font color='green'>// 以下这些是缓冲队列结构中的偏移量 */</font></i>
<a name='L34'>head = 4 <i><font color='green'>// 缓冲区中头指针字段偏移。</font></i>
<a name='L35'>tail = 8 <i><font color='green'>// 缓冲区中尾指针字段偏移。</font></i>
<a name='L36'>proc_list = 12 <i><font color='green'>// 等待该缓冲队列的进程字段偏移。</font></i>
<a name='L37'>buf = 16 <i><font color='green'>// 缓冲区字段偏移。</font></i>
<a name='L38'>
<a name='L39'><i><font color='green'>// mode 是键盘特殊键的按下状态标志。</font></i>
<a name='L40'><i><font color='green'>// 表示大小写转换键(caps)、交换键(alt)、控制键(ctrl)和换档键(shift)的状态。</font></i>
<a name='L41'><i><font color='green'>// 位7 caps 键按下;</font></i>
<a name='L42'><i><font color='green'>// 位6 caps 键的状态(应该与leds 中的对应标志位一样);</font></i>
<a name='L43'><i><font color='green'>// 位5 右alt 键按下;</font></i>
<a name='L44'><i><font color='green'>// 位4 左alt 键按下;</font></i>
<a name='L45'><i><font color='green'>// 位3 右ctrl 键按下;</font></i>
<a name='L46'><i><font color='green'>// 位2 左ctrl 键按下;</font></i>
<a name='L47'><i><font color='green'>// 位1 右shift 键按下;</font></i>
<a name='L48'><i><font color='green'>// 位0 左shift 键按下。</font></i>
<a name='L49'>mode: .byte 0 <i><font color='green'>/* caps, alt, ctrl and shift mode */</font></i>
<a name='L50'><i><font color='green'>// 数字锁定键(num-lock)、大小写转换键(caps-lock)和滚动锁定键(scroll-lock)的LED 发光管状态。</font></i>
<a name='L51'><i><font color='green'>// 位7-3 全0 不用;</font></i>
<a name='L52'><i><font color='green'>// 位2 caps-lock;</font></i>
<a name='L53'><i><font color='green'>// 位1 num-lock(初始置1,也即设置数字锁定键(num-lock)发光管为亮);</font></i>
<a name='L54'><i><font color='green'>// 位0 scroll-lock。</font></i>
<a name='L55'>leds: .byte 2 <i><font color='green'>/* num-lock, caps, scroll-lock mode (nom-lock on) */</font></i>
<a name='L56'><i><font color='green'>// 当扫描码是0xe0 或0xe1 时,置该标志。表示其后还跟随着1 个或2 个字符扫描码,参见列表后说明。</font></i>
<a name='L57'><i><font color='green'>// 位1 =1 收到0xe1 标志;</font></i>
<a name='L58'><i><font color='green'>// 位0 =1 收到0xe0 标志。</font></i>
<a name='L59'>e0: .byte 0
<a name='L60'>
<a name='L61'><i><font color='green'>/*</font></i>
<a name='L62'><i><font color='green'>* con_int is the real interrupt routine that reads the</font></i>
<a name='L63'><i><font color='green'>* keyboard scan-code and converts it into the appropriate</font></i>
<a name='L64'><i><font color='green'>* ascii character(s).</font></i>
<a name='L65'><i><font color='green'>*/</font></i>
<a name='L66'><i><font color='green'>/*</font></i>
<a name='L67'><i><font color='green'>* con_int 是实际的中断处理子程序,用于读键盘扫描码并将其转换</font></i>
<a name='L68'><i><font color='green'>* 成相应的ascii 字符。</font></i>
<a name='L69'><i><font color='green'>*/</font></i>
<a name='L70'><i><font color='green'>//// 键盘中断处理程序入口点。</font></i>
<a name='L71'>_keyboard_interrupt:
<a name='L72'>pushl %eax
<a name='L73'>pushl %ebx
<a name='L74'>pushl %ecx
<a name='L75'>pushl %edx
<a name='L76'>push %ds
<a name='L77'>push %es
<a name='L78'>movl $0x10,%eax <i><font color='green'>// 将ds、es 段寄存器置为内核数据段。</font></i>
<a name='L79'>mov %ax,%ds
<a name='L80'>mov %ax,%es
<a name='L81'>xorl %al,%al <i><font color='green'>/* %eax is scan code */</font></i> <i><font color='green'>/* eax 中是扫描码 */</font></i>
<a name='L82'>inb $0x60,%al <i><font color='green'>// 读取扫描码??al。</font></i>
<a name='L83'>cmpb $0xe0,%al <i><font color='green'>// 该扫描码是0xe0 吗?如果是则跳转到设置e0 标志代码处。</font></i>
<a name='L84'>je set_e0
<a name='L85'>cmpb $0xe1,%al <i><font color='green'>// 扫描码是0xe1 吗?如果是则跳转到设置e1 标志代码处。</font></i>
<a name='L86'>je set_e1
<a name='L87'>call key_table(,%eax,4) <i><font color='green'>// 调用键处理程序ker_table + eax * 4(参见下面502 行)。</font></i>
<a name='L88'>movb $0,e0 <i><font color='green'>// 复位e0 标志。</font></i>
<a name='L89'><i><font color='green'>// 下面这段代码(55-65 行)是针对使用8255A 的PC 标准键盘电路进行硬件复位处理。端口0x61 是</font></i>
<a name='L90'><i><font color='green'>// 8255A 输出口B 的地址,该输出端口的第7 位(PB7)用于禁止和允许对键盘数据的处理。</font></i>
<a name='L91'><i><font color='green'>// 这段程序用于对收到的扫描码做出应答。方法是首先禁止键盘,然后立刻重新允许键盘工作。</font></i>
<a name='L92'>e0_e1: inb $0x61,%al <i><font color='green'>// 取PPI 端口B 状态,其位7 用于允许/禁止(0/1)键盘。</font></i>
<a name='L93'>jmp 1f <i><font color='green'>// 延迟一会。</font></i>
<a name='L94'>1: jmp 1f
<a name='L95'>1: orb $0x80,%al <i><font color='green'>// al 位7 置位(禁止键盘工作)。</font></i>
<a name='L96'>jmp 1f <i><font color='green'>// 再延迟一会。</font></i>
<a name='L97'>1: jmp 1f
<a name='L98'>1: outb %al,$0x61 <i><font color='green'>// 使PPI PB7 位置位。</font></i>
<a name='L99'>jmp 1f <i><font color='green'>// 延迟一会。</font></i>
<a name='L100'>1: jmp 1f
<a name='L101'>1: andb $0x7F,%al <i><font color='green'>// al 位7 复位。</font></i>
<a name='L102'>outb %al,$0x61 <i><font color='green'>// 使PPI PB7 位复位(允许键盘工作)。</font></i>
<a name='L103'>movb $0x20,%al <i><font color='green'>// 向8259 中断芯片发送EOI(中断结束)信号。</font></i>
<a name='L104'>outb %al,$0x20
<a name='L105'>pushl $0 <i><font color='green'>// 控制台tty 号=0,作为参数入栈。</font></i>
<a name='L106'>call _do_tty_interrupt <i><font color='green'>// 将收到的数据复制成规范模式数据并存放在规范字符缓冲队列中。</font></i>
<a name='L107'>addl $4,%esp <i><font color='green'>// 丢弃入栈的参数,弹出保留的寄存器,并中断返回。</font></i>
<a name='L108'>pop %es
<a name='L109'>pop %ds
<a name='L110'>popl %edx
<a name='L111'>popl %ecx
<a name='L112'>popl %ebx
<a name='L113'>popl %eax
<a name='L114'>iret
<a name='L115'>set_e0: movb $1,e0 <i><font color='green'>// 收到扫描前导码0xe0 时,设置e0 标志(位0)。</font></i>
<a name='L116'>jmp e0_e1
<a name='L117'>set_e1: movb $2,e0 <i><font color='green'>// 收到扫描前导码0xe1 时,设置e1 标志(位1)。</font></i>
<a name='L118'>jmp e0_e1
<a name='L119'>
<a name='L120'><i><font color='green'>/*</font></i>
<a name='L121'><i><font color='green'>* This routine fills the buffer with max 8 bytes, taken from</font></i>
<a name='L122'><i><font color='green'>* %ebx:%eax. (%edx is high). The bytes are written in the</font></i>
<a name='L123'><i><font color='green'>* order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.</font></i>
<a name='L124'><i><font color='green'>*/</font></i>
<a name='L125'><i><font color='green'>/*</font></i>
<a name='L126'><i><font color='green'>* 下面该子程序把ebx:eax 中的最多8 个字符添入缓冲队列中。(edx 是</font></i>
<a name='L127'><i><font color='green'>* 所写入字符的顺序是al,ah,eal,eah,bl,bh...直到eax 等于0。</font></i>
<a name='L128'><i><font color='green'>*/</font></i>
<a name='L129'>put_queue:
<a name='L130'>pushl %ecx <i><font color='green'>// 保存ecx,edx 内容。</font></i>
<a name='L131'>pushl %edx <i><font color='green'>// 取控制台tty 结构中读缓冲队列指针。</font></i>
<a name='L132'>movl _table_list,%edx # read-queue for console
<a name='L133'>movl head(%edx),%ecx <i><font color='green'>// 取缓冲队列中头指针??ecx。</font></i>
<a name='L134'>1: movb %al,buf(%edx,%ecx) <i><font color='green'>// 将al 中的字符放入缓冲队列头指针位置处。</font></i>
<a name='L135'>incl %ecx <i><font color='green'>// 头指针前移1 字节。</font></i>
<a name='L136'>andl $size-1,%ecx <i><font color='green'>// 以缓冲区大小调整头指针(若超出则返回缓冲区开始)。</font></i>
<a name='L137'>cmpl tail(%edx),%ecx # buffer full - discard everything
<a name='L138'><i><font color='green'>// 头指针==尾指针吗(缓冲队列满)?</font></i>
<a name='L139'>je 3f <i><font color='green'>// 如果已满,则后面未放入的字符全抛弃。</font></i>
<a name='L140'>shrdl $8,%ebx,%eax <i><font color='green'>// 将ebx 中8 位比特位右移8 位到eax 中,但ebx 不变。</font></i>
<a name='L141'>je 2f <i><font color='green'>// 还有字符吗?若没有(等于0)则跳转。</font></i>
<a name='L142'>shrl $8,%ebx <i><font color='green'>// 将ebx 中比特位右移8 位,并跳转到标号1 继续操作。</font></i>
<a name='L143'>jmp 1b
<a name='L144'>2: movl %ecx,head(%edx) <i><font color='green'>// 若已将所有字符都放入了队列,则保存头指针。</font></i>
<a name='L145'>movl proc_list(%edx),%ecx <i><font color='green'>// 该队列的等待进程指针?</font></i>
<a name='L146'>testl %ecx,%ecx <i><font color='green'>// 检测任务结构指针是否为空(有等待该队列的进程吗?)。</font></i>
<a name='L147'>je 3f <i><font color='green'>// 无,则跳转;</font></i>
<a name='L148'>movl $0,(%ecx) <i><font color='green'>// 有,则置该进程为可运行就绪状态(唤醒该进程)。</font></i>
<a name='L149'>3: popl %edx <i><font color='green'>// 弹出保留的寄存器并返回。</font></i>
<a name='L150'>popl %ecx
<a name='L151'>ret
<a name='L152'>
<a name='L153'><i><font color='green'>// 下面这段代码根据ctrl 或alt 的扫描码,分别设置模式标志中相应位。如果该扫描码之前收到过</font></i>
<a name='L154'><i><font color='green'>// 0xe0 扫描码(e0 标志置位),则说明按下的是键盘右边的ctrl 或alt 键,则对应设置ctrl 或alt</font></i>
<a name='L155'><i><font color='green'>// 在模式标志mode 中的比特位。</font></i>
<a name='L156'>ctrl: movb $0x04,%al <i><font color='green'>// 0x4 是模式标志mode 中左ctrl 键对应的比特位(位2)。</font></i>
<a name='L157'>jmp 1f
<a name='L158'>alt: movb $0x10,%al <i><font color='green'>// 0x10 是模式标志mode 中左alt 键对应的比特位(位4)。</font></i>
<a name='L159'>1: cmpb $0,e0 <i><font color='green'>// e0 标志置位了吗(按下的是右边的ctrl 或alt 键吗)?</font></i>
<a name='L160'>je 2f <i><font color='green'>// 不是则转。</font></i>
<a name='L161'>addb %al,%al <i><font color='green'>// 是,则改成置相应右键的标志位(位3 或位5)。</font></i>
<a name='L162'>2: orb %al,mode <i><font color='green'>// 设置模式标志mode 中对应的比特位。</font></i>
<a name='L163'>ret
<a name='L164'><i><font color='green'>// 这段代码处理ctrl 或alt 键松开的扫描码,对应复位模式标志mode 中的比特位。在处理时要根据</font></i>
<a name='L165'><i><font color='green'>// e0 标志是否置位来判断是否是键盘右边的ctrl 或alt 键。</font></i>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -