Browse Source

fix: 临时修复键盘驱动与鼠标驱动冲突导致键盘无响应 (#1014)

暂时通过条件编译的方式解决. 目前认为是鼠标驱动问题,没有正确判断是不是自己的数据...
但是因为我们场景下,鼠标驱动几乎用不到,因此先条件编译屏蔽.

Signed-off-by: longjin <[email protected]>
LoGin 4 months ago
parent
commit
a9e28e9ce9

+ 1 - 0
kernel/Cargo.toml

@@ -23,6 +23,7 @@ kvm = []
 
 fatfs = []
 fatfs-secure = ["fatfs"]
+driver_ps2_mouse = []
 
 # kprobe
 kprobe_test = []

+ 0 - 1
kernel/src/arch/x86_64/asm/entry.S

@@ -54,7 +54,6 @@ Restore_all:
     popq %rax
     addq $0x10, %rsp // 弹出变量FUNC和errcode
     
-    sti
     iretq
 
 ret_from_exception:

+ 1 - 1
kernel/src/driver/input/mod.rs

@@ -1,4 +1,4 @@
 pub mod ps2_dev;
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", feature = "driver_ps2_mouse"))]
 pub mod ps2_mouse;
 pub mod serio;

+ 1 - 1
kernel/src/driver/input/serio/i8042/mod.rs

@@ -69,7 +69,7 @@ pub fn i8042_setup_aux() -> Result<(), SystemError> {
     )));
     serio_device_manager().register_port(aux_port.clone() as Arc<dyn SerioDevice>)?;
 
-    #[cfg(target_arch = "x86_64")]
+    #[cfg(all(target_arch = "x86_64", feature = "driver_ps2_mouse"))]
     crate::driver::input::ps2_mouse::ps_mouse_device::rs_ps2_mouse_device_init(
         aux_port.clone() as Arc<dyn Device>
     )?;

+ 41 - 18
kernel/src/driver/keyboard/ps2_keyboard.rs

@@ -8,7 +8,7 @@ use alloc::{
 use unified_init::macros::unified_init;
 
 use crate::{
-    arch::{io::PortIOArch, CurrentPortIOArch},
+    arch::{io::PortIOArch, CurrentIrqArch, CurrentPortIOArch},
     driver::{
         base::device::device_number::{DeviceNumber, Major},
         input::ps2_dev::Ps2StatusRegister,
@@ -17,7 +17,7 @@ use crate::{
         irqdata::IrqHandlerData,
         irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn},
         manage::irq_manager,
-        IrqNumber,
+        InterruptArch, IrqNumber,
     },
     filesystem::{
         devfs::{devfs_register, DevFS, DeviceINode},
@@ -186,17 +186,24 @@ impl IrqHandler for Ps2KeyboardIrqHandler {
         _dev_id: Option<Arc<dyn IrqHandlerData>>,
     ) -> Result<IrqReturn, SystemError> {
         // 先检查状态寄存器,看看是否有数据
-        let status = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into()) };
-        let status = Ps2StatusRegister::from(status);
-        if !status.outbuf_full() {
-            return Ok(IrqReturn::Handled);
+        let mut fsm = PS2_KEYBOARD_FSM.lock();
+        let mut handled = false;
+        loop {
+            let status = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into()) };
+            let status = Ps2StatusRegister::from(status);
+            if status.outbuf_full() {
+                let input = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_DATA.into()) };
+                fsm.parse(input);
+                handled = true;
+            } else {
+                break;
+            }
+        }
+        if handled {
+            Ok(IrqReturn::Handled)
+        } else {
+            Ok(IrqReturn::NotHandled)
         }
-
-        let input = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_DATA.into()) };
-        // wait_ps2_keyboard_read();
-        PS2_KEYBOARD_FSM.lock().parse(input);
-
-        return Ok(IrqReturn::Handled);
     }
 }
 
@@ -219,8 +226,27 @@ fn wait_ps2_keyboard_write() {
         spin_loop();
     }
 }
+
+fn force_clear_input_buffer() {
+    loop {
+        let status = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into()) };
+        let status = Ps2StatusRegister::from(status);
+        if status.outbuf_full() {
+            unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_DATA.into()) };
+        } else {
+            break;
+        }
+    }
+}
+
 #[unified_init(INITCALL_DEVICE)]
 fn ps2_keyboard_init() -> Result<(), SystemError> {
+    let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
+
+    // 先读一下键盘的数据,防止由于在键盘初始化之前,由于按键被按下从而导致接收不到中断。
+    // 清空键盘缓冲区
+    force_clear_input_buffer();
+
     // ======== 初始化键盘控制器,写入配置值 =========
     wait_ps2_keyboard_write();
     unsafe {
@@ -245,12 +271,9 @@ fn ps2_keyboard_init() -> Result<(), SystemError> {
         )
         .expect("Failed to request irq for ps2 keyboard");
 
-    // 先读一下键盘的数据,防止由于在键盘初始化之前,由于按键被按下从而导致接收不到中断。
-    let status = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into()) };
-    let status = Ps2StatusRegister::from(status);
-    if status.outbuf_full() {
-        unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_DATA.into()) };
-    }
+    // 清空键盘缓冲区
+    force_clear_input_buffer();
+    drop(irq_guard);
 
     // 将设备挂载到devfs
     ps2_keyboard_register();