fix(keyboard): init() 对齐 mouse 写法 - 去掉 0xAD/0xAE 键盘接口禁用序列(CCB 回写失败会停在禁用态),并补 pic.clearMask(1)

This commit is contained in:
TermiNexus committed 2026-10-16 14:14:51 +08:00
1 parent d37eac32fe
commit 89907682ec
1 file changed
+13 -21
@@ -1,6 +1,7 @@
import asm
import intr.idt as idt
import drivers.serial.uart.serial as serial
import platform.pch.pic as pic
import string
import viperlib
import t, c
@@ -116,12 +117,12 @@ def has_data() -> int:
def init():
global _kbd_inited
# 幂等:init() 有两个调用点(devfs 注册 /dev/input/keyboard、kbd_svc.start),
# 重复执行会再次发 0xAD 禁用键盘接口,而那次 CCB 写入往往失败(键盘数据串入
# CCB 读取,回读为 0)⇒ 0xAE 恢复不了 ⇒ 接口停在禁用态 ⇒ 按键不再产生任何字节
# (现场:ki 恒为 2/3,desktop 轮询永远看不到键盘字节,键盘完全无法输入)。
# 硬件初始化只允许做一次。
if _kbd_inited != 0:
return
_kbd_inited = 1
# 清空控制器输出缓冲(上电自检字节 / 上一次遗留的 ACK 等)
drain: uint32
drain = 0
while (asm.inb(KBD_STATUS) & 0x01) != 0:
@@ -129,15 +130,12 @@ def init():
drain += 1
if drain > 1000: break
_wait_write()
asm.outb(KBD_COMMAND, 0xAD)
drain = 0
while (asm.inb(KBD_STATUS) & 0x01) != 0:
asm.inb(KBD_DATA)
drain += 1
if drain > 1000: break
# 读-改-写 CCB(与 mouse.init 同款写法):
# bit0=1 使能键盘 IRQ1;bit6=1 启用 scancode set1 翻译;bit4=0 使能键盘时钟。
# 这里**不再发 0xAD/0xAE**(禁用 / 启用键盘接口):QEMU 下 0xAD 之后那次 CCB 回写
# 经常失败(键盘数据串入 CCB 读取、回读为 0),0xAE 便恢复不了 ⇒ 键盘接口停在
# 禁用态 ⇒ 之后按键完全不产生任何字节/IRQ1(现场:ki 恒为 2/3、无任何键盘字节)。
# 鼠标没有这个序列,所以它一直正常 —— 键盘对齐鼠标的写法即可。
_wait_write()
asm.outb(KBD_COMMAND, 0x20)
_wait_read()
@@ -152,18 +150,12 @@ def init():
_wait_write()
asm.outb(KBD_DATA, ccb)
_wait_write()
asm.outb(KBD_COMMAND, 0xAE)
drain = 0
while (asm.inb(KBD_STATUS) & 0x01) != 0:
asm.inb(KBD_DATA)
drain += 1
if drain > 1000: break
# 使能键盘扫描(0xF4),并读走 ACK
_wait_write()
asm.outb(KBD_DATA, 0xF4)
_wait_read()
asm.inb(KBD_DATA)
# 解屏蔽 IRQ1(对齐 mouse.init 的 pic.clearMask(12)),再装 handler
pic.clearMask(1)
idt.irqInstallHandler(1, irq_handler, "keyboard")