qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] ps2 keyboard:fix can't use ps2 keyboard if typing m


From: penghao122
Subject: [Qemu-devel] [PATCH] ps2 keyboard:fix can't use ps2 keyboard if typing many times After leaving grub and before finishing linux kernel ps2 driver initialization
Date: Sun, 26 Apr 2015 10:26:27 +0800

Starting  a linux guest with ps2 keyboard ,if you type many times during leaving grub and into linux kernel ,then you can't use keyboard after linux initialization finished.

during grub,the work method of ps2 keyboard is like this:

first ,ps2 keyboard driver send command KBD_CCMD_KBD_ENABLE,

second,if there is a keyboard input,then  ps2 keyboard driver read data.

third ,ps2 keyboard driver send command KBD_CCMD_KBD_ENABLE,

...

this is diffrent method of linux kernel .

After leaving  grub and before finishing linux kernel ps2 driver initialization,if you type many times,the input data keep saving the ps2 queue in qemu .Before linux kernel initialize ps2 keyboard,linux call i8042_init->i8042_controller_check,if i8042_controller_check return fail,then linux kernel ps2 keyboard driver will never initialize.

(linux kernel 2.6.32 i8042.c)

static int i8042_controller_check(void)
{
 if (i8042_flush() == I8042_BUFFER_SIZE)
  return -ENODEV;

 return 0;
}

static int i8042_flush(void)

{...

while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) {
  udelay(50);
  data = "">  i++;
  }

return i;

}

 

during calling i8042_flush it is full in qemu queue .

ps_read_data:

                       s->update_irq(s->update_arg, 0);

                       s->update_irq(s->update_arg, q->count != 0);

because q->count!=0, kbd_update_irq can set I8042_STR_OBF.Then i8042_flush()  will return I8042_BUFFER_SIZE.

 

 

--- ps2.c.orig 2015-04-25 09:44:38.865777168 -0400
+++ ps2.c 2015-04-25 09:48:46.385121172 -0400
@@ -150,7 +150,12 @@
     q->count++;
     s->update_irq(s->update_arg, 1);
 }
-
+void ps2_clear_queue(void *opaque)
+{
+    PS2State *s = (PS2State *)opaque;
+    PS2Queue *q = &s->queue;
+    q->wptr = q->rptr = q->count = 0;
+}
 /*
    keycode is expressed as follow:
    bit 7    - 0 key pressed, 1 = key released

 

--- pckbd.c.orig 2015-04-25 09:36:59.960640241 -0400
+++ pckbd.c 2015-04-25 09:44:27.298562406 -0400
@@ -207,6 +207,8 @@
     KBDState *s = opaque;
     int val;
     val = s->status;
+    if(s->write-cmd == KBD_CCMD_KBD_ENABLE)
+        val &= ~KBD_STAT_OBF;   
     DPRINTF("kbd: read status=0x%02x\n", val);
     return val;
 }
@@ -251,9 +253,10 @@
         else
             val = KBD_CCMD_NO_OP;
     }
-
+    s->write_cmd = 0;
     switch(val) {
     case KBD_CCMD_READ_MODE:
+        ps2_clear_queue(s->kbd);
         kbd_queue(s, s->mode, 0);
         break;
     case KBD_CCMD_WRITE_MODE:
@@ -284,6 +287,7 @@
         kbd_update_irq(s);
         break;
     case KBD_CCMD_KBD_ENABLE:
+        s->write_cmd = KBD_CCMD_KBD_ENABLE;
         s->mode &= ~KBD_MODE_DISABLE_KBD;
         kbd_update_irq(s);
         break;


reply via email to

[Prev in Thread] Current Thread [Next in Thread]