]> git.proxmox.com Git - qemu.git/blobdiff - hw/ps2.c
Use glib memory allocation and free functions
[qemu.git] / hw / ps2.c
index 666e7b8dbbd4fee9d1c014268e7cd722159cb938..24228c1539fab514bbb7c45e4e4977c316bf2af5 100644 (file)
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -44,6 +44,7 @@
 
 /* Keyboard Replies */
 #define KBD_REPLY_POR          0xAA    /* Power on reset */
+#define KBD_REPLY_ID           0xAB    /* Keyboard ID */
 #define KBD_REPLY_ACK          0xFA    /* Command ACK */
 #define KBD_REPLY_RESEND       0xFE    /* Command NACK, send the cmd again */
 
@@ -109,14 +110,24 @@ typedef struct {
 
 /* Table to convert from PC scancodes to raw scancodes.  */
 static const unsigned char ps2_raw_keycode[128] = {
-          0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
-         21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
-         35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
-         50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
-         11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
-        114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
-         71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
-         19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
+  0, 118,  22,  30,  38,  37,  46,  54,  61,  62,  70,  69,  78,  85, 102,  13,
+ 21,  29,  36,  45,  44,  53,  60,  67,  68,  77,  84,  91,  90,  20,  28,  27,
+ 35,  43,  52,  51,  59,  66,  75,  76,  82,  14,  18,  93,  26,  34,  33,  42,
+ 50,  49,  58,  65,  73,  74,  89, 124,  17,  41,  88,   5,   6,   4,  12,   3,
+ 11,   2,  10,   1,   9, 119, 126, 108, 117, 125, 123, 107, 115, 116, 121, 105,
+114, 122, 112, 113, 127,  96,  97, 120,   7,  15,  23,  31,  39,  47,  55,  63,
+ 71,  79,  86,  94,   8,  16,  24,  32,  40,  48,  56,  64,  72,  80,  87, 111,
+ 19,  25,  57,  81,  83,  92,  95,  98,  99, 100, 101, 103, 104, 106, 109, 110
+};
+static const unsigned char ps2_raw_keycode_set3[128] = {
+  0,   8,  22,  30,  38,  37,  46,  54,  61,  62,  70,  69,  78,  85, 102,  13,
+ 21,  29,  36,  45,  44,  53,  60,  67,  68,  77,  84,  91,  90,  17,  28,  27,
+ 35,  43,  52,  51,  59,  66,  75,  76,  82,  14,  18,  92,  26,  34,  33,  42,
+ 50,  49,  58,  65,  73,  74,  89, 126,  25,  41,  20,   7,  15,  23,  31,  39,
+ 47,   2,  63,  71,  79, 118,  95, 108, 117, 125, 132, 107, 115, 116, 124, 105,
+114, 122, 112, 113, 127,  96,  97,  86,  94,  15,  23,  31,  39,  47,  55,  63,
+ 71,  79,  86,  94,   8,  16,  24,  32,  40,  48,  56,  64,  72,  80,  87, 111,
+ 19,  25,  57,  81,  83,  92,  95,  98,  99, 100, 101, 103, 104, 106, 109, 110
 };
 
 void ps2_queue(void *opaque, int b)
@@ -133,17 +144,25 @@ void ps2_queue(void *opaque, int b)
     s->update_irq(s->update_arg, 1);
 }
 
-/* keycode is expressed in scancode set 2 */
+/*
+   keycode is expressed as follow:
+   bit 7    - 0 key pressed, 1 = key released
+   bits 6-0 - translated scancode set 2
+ */
 static void ps2_put_keycode(void *opaque, int keycode)
 {
     PS2KbdState *s = opaque;
 
-    /* XXX: add support for scancode sets 1 and 3 */
-    if (!s->translate && keycode < 0xe0 && s->scancode_set == 2)
-      {
-        if (keycode & 0x80)
+    /* XXX: add support for scancode set 1 */
+    if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) {
+        if (keycode & 0x80) {
             ps2_queue(&s->common, 0xf0);
-        keycode = ps2_raw_keycode[keycode & 0x7f];
+        }
+        if (s->scancode_set == 2) {
+            keycode = ps2_raw_keycode[keycode & 0x7f];
+        } else if (s->scancode_set == 3) {
+            keycode = ps2_raw_keycode_set3[keycode & 0x7f];
+        }
       }
     ps2_queue(&s->common, keycode);
 }
@@ -180,6 +199,7 @@ static void ps2_reset_keyboard(PS2KbdState *s)
 {
     s->scan_enabled = 1;
     s->scancode_set = 2;
+    kbd_put_ledstate(0);
 }
 
 void ps2_write_keyboard(void *opaque, int val)
@@ -199,8 +219,11 @@ void ps2_write_keyboard(void *opaque, int val)
         case KBD_CMD_GET_ID:
             ps2_queue(&s->common, KBD_REPLY_ACK);
             /* We emulate a MF2 AT keyboard here */
-            ps2_put_keycode(s, 0xab);
-            ps2_put_keycode(s, 0x83);
+            ps2_queue(&s->common, KBD_REPLY_ID);
+            if (s->translate)
+                ps2_queue(&s->common, 0x41);
+            else
+                ps2_queue(&s->common, 0x83);
             break;
         case KBD_CMD_ECHO:
             ps2_queue(&s->common, KBD_CMD_ECHO);
@@ -251,6 +274,7 @@ void ps2_write_keyboard(void *opaque, int val)
         s->common.write_cmd = -1;
         break;
     case KBD_CMD_SET_LEDS:
+        kbd_put_ledstate(val);
         ps2_queue(&s->common, KBD_REPLY_ACK);
         s->common.write_cmd = -1;
         break;
@@ -480,123 +504,125 @@ void ps2_write_mouse(void *opaque, int val)
     }
 }
 
-static void ps2_reset(void *opaque)
+static void ps2_common_reset(PS2State *s)
 {
-    PS2State *s = (PS2State *)opaque;
     PS2Queue *q;
     s->write_cmd = -1;
     q = &s->queue;
     q->rptr = 0;
     q->wptr = 0;
     q->count = 0;
+    s->update_irq(s->update_arg, 0);
 }
 
-static void ps2_common_save (QEMUFile *f, PS2State *s)
+static void ps2_kbd_reset(void *opaque)
 {
-    qemu_put_be32 (f, s->write_cmd);
-    qemu_put_be32 (f, s->queue.rptr);
-    qemu_put_be32 (f, s->queue.wptr);
-    qemu_put_be32 (f, s->queue.count);
-    qemu_put_buffer (f, s->queue.data, sizeof (s->queue.data));
-}
+    PS2KbdState *s = (PS2KbdState *) opaque;
 
-static void ps2_common_load (QEMUFile *f, PS2State *s)
-{
-    s->write_cmd=qemu_get_be32 (f);
-    s->queue.rptr=qemu_get_be32 (f);
-    s->queue.wptr=qemu_get_be32 (f);
-    s->queue.count=qemu_get_be32 (f);
-    qemu_get_buffer (f, s->queue.data, sizeof (s->queue.data));
+    ps2_common_reset(&s->common);
+    s->scan_enabled = 0;
+    s->translate = 0;
+    s->scancode_set = 0;
 }
 
-static void ps2_kbd_save(QEMUFile* f, void* opaque)
+static void ps2_mouse_reset(void *opaque)
 {
-    PS2KbdState *s = (PS2KbdState*)opaque;
-
-    ps2_common_save (f, &s->common);
-    qemu_put_be32(f, s->scan_enabled);
-    qemu_put_be32(f, s->translate);
-    qemu_put_be32(f, s->scancode_set);
+    PS2MouseState *s = (PS2MouseState *) opaque;
+
+    ps2_common_reset(&s->common);
+    s->mouse_status = 0;
+    s->mouse_resolution = 0;
+    s->mouse_sample_rate = 0;
+    s->mouse_wrap = 0;
+    s->mouse_type = 0;
+    s->mouse_detect_state = 0;
+    s->mouse_dx = 0;
+    s->mouse_dy = 0;
+    s->mouse_dz = 0;
+    s->mouse_buttons = 0;
 }
 
-static void ps2_mouse_save(QEMUFile* f, void* opaque)
-{
-    PS2MouseState *s = (PS2MouseState*)opaque;
-
-    ps2_common_save (f, &s->common);
-    qemu_put_8s(f, &s->mouse_status);
-    qemu_put_8s(f, &s->mouse_resolution);
-    qemu_put_8s(f, &s->mouse_sample_rate);
-    qemu_put_8s(f, &s->mouse_wrap);
-    qemu_put_8s(f, &s->mouse_type);
-    qemu_put_8s(f, &s->mouse_detect_state);
-    qemu_put_be32(f, s->mouse_dx);
-    qemu_put_be32(f, s->mouse_dy);
-    qemu_put_be32(f, s->mouse_dz);
-    qemu_put_8s(f, &s->mouse_buttons);
-}
+static const VMStateDescription vmstate_ps2_common = {
+    .name = "PS2 Common State",
+    .version_id = 3,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
+    .fields      = (VMStateField []) {
+        VMSTATE_INT32(write_cmd, PS2State),
+        VMSTATE_INT32(queue.rptr, PS2State),
+        VMSTATE_INT32(queue.wptr, PS2State),
+        VMSTATE_INT32(queue.count, PS2State),
+        VMSTATE_BUFFER(queue.data, PS2State),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
-static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id)
+static int ps2_kbd_post_load(void* opaque, int version_id)
 {
     PS2KbdState *s = (PS2KbdState*)opaque;
 
-    if (version_id != 2 && version_id != 3)
-        return -EINVAL;
-
-    ps2_common_load (f, &s->common);
-    s->scan_enabled=qemu_get_be32(f);
-    s->translate=qemu_get_be32(f);
-    if (version_id == 3)
-        s->scancode_set=qemu_get_be32(f);
-    else
+    if (version_id == 2)
         s->scancode_set=2;
     return 0;
 }
 
-static int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id)
-{
-    PS2MouseState *s = (PS2MouseState*)opaque;
-
-    if (version_id != 2)
-        return -EINVAL;
-
-    ps2_common_load (f, &s->common);
-    qemu_get_8s(f, &s->mouse_status);
-    qemu_get_8s(f, &s->mouse_resolution);
-    qemu_get_8s(f, &s->mouse_sample_rate);
-    qemu_get_8s(f, &s->mouse_wrap);
-    qemu_get_8s(f, &s->mouse_type);
-    qemu_get_8s(f, &s->mouse_detect_state);
-    s->mouse_dx=qemu_get_be32(f);
-    s->mouse_dy=qemu_get_be32(f);
-    s->mouse_dz=qemu_get_be32(f);
-    qemu_get_8s(f, &s->mouse_buttons);
-    return 0;
-}
+static const VMStateDescription vmstate_ps2_keyboard = {
+    .name = "ps2kbd",
+    .version_id = 3,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
+    .post_load = ps2_kbd_post_load,
+    .fields      = (VMStateField []) {
+        VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
+        VMSTATE_INT32(scan_enabled, PS2KbdState),
+        VMSTATE_INT32(translate, PS2KbdState),
+        VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_ps2_mouse = {
+    .name = "ps2mouse",
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
+    .fields      = (VMStateField []) {
+        VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
+        VMSTATE_UINT8(mouse_status, PS2MouseState),
+        VMSTATE_UINT8(mouse_resolution, PS2MouseState),
+        VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
+        VMSTATE_UINT8(mouse_wrap, PS2MouseState),
+        VMSTATE_UINT8(mouse_type, PS2MouseState),
+        VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
+        VMSTATE_INT32(mouse_dx, PS2MouseState),
+        VMSTATE_INT32(mouse_dy, PS2MouseState),
+        VMSTATE_INT32(mouse_dz, PS2MouseState),
+        VMSTATE_UINT8(mouse_buttons, PS2MouseState),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
 {
-    PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
+    PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
 
     s->common.update_irq = update_irq;
     s->common.update_arg = update_arg;
     s->scancode_set = 2;
-    ps2_reset(&s->common);
-    register_savevm("ps2kbd", 0, 3, ps2_kbd_save, ps2_kbd_load, s);
+    vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
     qemu_add_kbd_event_handler(ps2_put_keycode, s);
-    qemu_register_reset(ps2_reset, &s->common);
+    qemu_register_reset(ps2_kbd_reset, s);
     return s;
 }
 
 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
 {
-    PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
+    PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
 
     s->common.update_irq = update_irq;
     s->common.update_arg = update_arg;
-    ps2_reset(&s->common);
-    register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
+    vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
     qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
-    qemu_register_reset(ps2_reset, &s->common);
+    qemu_register_reset(ps2_mouse_reset, s);
     return s;
 }