Statistics
| Branch: | Revision:

root / hw / ps2.c @ 0dad6c35

History | View | Annotate | Download (20.2 kB)

1
/*
2
 * QEMU PS/2 keyboard/mouse emulation
3
 *
4
 * Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "hw.h"
25
#include "ps2.h"
26
#include "console.h"
27

    
28
/* debug PC keyboard */
29
//#define DEBUG_KBD
30

    
31
/* debug PC keyboard : only mouse */
32
//#define DEBUG_MOUSE
33

    
34
/* Keyboard Commands */
35
#define KBD_CMD_SET_LEDS        0xED        /* Set keyboard leds */
36
#define KBD_CMD_ECHO             0xEE
37
#define KBD_CMD_SCANCODE        0xF0        /* Get/set scancode set */
38
#define KBD_CMD_GET_ID                 0xF2        /* get keyboard ID */
39
#define KBD_CMD_SET_RATE        0xF3        /* Set typematic rate */
40
#define KBD_CMD_ENABLE                0xF4        /* Enable scanning */
41
#define KBD_CMD_RESET_DISABLE        0xF5        /* reset and disable scanning */
42
#define KBD_CMD_RESET_ENABLE           0xF6    /* reset and enable scanning */
43
#define KBD_CMD_RESET                0xFF        /* Reset */
44

    
45
/* Keyboard Replies */
46
#define KBD_REPLY_POR                0xAA        /* Power on reset */
47
#define KBD_REPLY_ID                0xAB        /* Keyboard ID */
48
#define KBD_REPLY_ACK                0xFA        /* Command ACK */
49
#define KBD_REPLY_RESEND        0xFE        /* Command NACK, send the cmd again */
50

    
51
/* Mouse Commands */
52
#define AUX_SET_SCALE11                0xE6        /* Set 1:1 scaling */
53
#define AUX_SET_SCALE21                0xE7        /* Set 2:1 scaling */
54
#define AUX_SET_RES                0xE8        /* Set resolution */
55
#define AUX_GET_SCALE                0xE9        /* Get scaling factor */
56
#define AUX_SET_STREAM                0xEA        /* Set stream mode */
57
#define AUX_POLL                0xEB        /* Poll */
58
#define AUX_RESET_WRAP                0xEC        /* Reset wrap mode */
59
#define AUX_SET_WRAP                0xEE        /* Set wrap mode */
60
#define AUX_SET_REMOTE                0xF0        /* Set remote mode */
61
#define AUX_GET_TYPE                0xF2        /* Get type */
62
#define AUX_SET_SAMPLE                0xF3        /* Set sample rate */
63
#define AUX_ENABLE_DEV                0xF4        /* Enable aux device */
64
#define AUX_DISABLE_DEV                0xF5        /* Disable aux device */
65
#define AUX_SET_DEFAULT                0xF6
66
#define AUX_RESET                0xFF        /* Reset aux device */
67
#define AUX_ACK                        0xFA        /* Command byte ACK. */
68

    
69
#define MOUSE_STATUS_REMOTE     0x40
70
#define MOUSE_STATUS_ENABLED    0x20
71
#define MOUSE_STATUS_SCALE21    0x10
72

    
73
#define PS2_QUEUE_SIZE 256
74

    
75
typedef struct {
76
    uint8_t data[PS2_QUEUE_SIZE];
77
    int rptr, wptr, count;
78
} PS2Queue;
79

    
80
typedef struct {
81
    PS2Queue queue;
82
    int32_t write_cmd;
83
    void (*update_irq)(void *, int);
84
    void *update_arg;
85
} PS2State;
86

    
87
typedef struct {
88
    PS2State common;
89
    int scan_enabled;
90
    /* Qemu uses translated PC scancodes internally.  To avoid multiple
91
       conversions we do the translation (if any) in the PS/2 emulation
92
       not the keyboard controller.  */
93
    int translate;
94
    int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
95
    int ledstate;
96
} PS2KbdState;
97

    
98
typedef struct {
99
    PS2State common;
100
    uint8_t mouse_status;
101
    uint8_t mouse_resolution;
102
    uint8_t mouse_sample_rate;
103
    uint8_t mouse_wrap;
104
    uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
105
    uint8_t mouse_detect_state;
106
    int mouse_dx; /* current values, needed for 'poll' mode */
107
    int mouse_dy;
108
    int mouse_dz;
109
    uint8_t mouse_buttons;
110
} PS2MouseState;
111

    
112
/* Table to convert from PC scancodes to raw scancodes.  */
113
static const unsigned char ps2_raw_keycode[128] = {
114
  0, 118,  22,  30,  38,  37,  46,  54,  61,  62,  70,  69,  78,  85, 102,  13,
115
 21,  29,  36,  45,  44,  53,  60,  67,  68,  77,  84,  91,  90,  20,  28,  27,
116
 35,  43,  52,  51,  59,  66,  75,  76,  82,  14,  18,  93,  26,  34,  33,  42,
117
 50,  49,  58,  65,  73,  74,  89, 124,  17,  41,  88,   5,   6,   4,  12,   3,
118
 11,   2,  10,   1,   9, 119, 126, 108, 117, 125, 123, 107, 115, 116, 121, 105,
119
114, 122, 112, 113, 127,  96,  97, 120,   7,  15,  23,  31,  39,  47,  55,  63,
120
 71,  79,  86,  94,   8,  16,  24,  32,  40,  48,  56,  64,  72,  80,  87, 111,
121
 19,  25,  57,  81,  83,  92,  95,  98,  99, 100, 101, 103, 104, 106, 109, 110
122
};
123
static const unsigned char ps2_raw_keycode_set3[128] = {
124
  0,   8,  22,  30,  38,  37,  46,  54,  61,  62,  70,  69,  78,  85, 102,  13,
125
 21,  29,  36,  45,  44,  53,  60,  67,  68,  77,  84,  91,  90,  17,  28,  27,
126
 35,  43,  52,  51,  59,  66,  75,  76,  82,  14,  18,  92,  26,  34,  33,  42,
127
 50,  49,  58,  65,  73,  74,  89, 126,  25,  41,  20,   7,  15,  23,  31,  39,
128
 47,   2,  63,  71,  79, 118,  95, 108, 117, 125, 132, 107, 115, 116, 124, 105,
129
114, 122, 112, 113, 127,  96,  97,  86,  94,  15,  23,  31,  39,  47,  55,  63,
130
 71,  79,  86,  94,   8,  16,  24,  32,  40,  48,  56,  64,  72,  80,  87, 111,
131
 19,  25,  57,  81,  83,  92,  95,  98,  99, 100, 101, 103, 104, 106, 109, 110
132
};
133

    
134
void ps2_queue(void *opaque, int b)
135
{
136
    PS2State *s = (PS2State *)opaque;
137
    PS2Queue *q = &s->queue;
138

    
139
    if (q->count >= PS2_QUEUE_SIZE)
140
        return;
141
    q->data[q->wptr] = b;
142
    if (++q->wptr == PS2_QUEUE_SIZE)
143
        q->wptr = 0;
144
    q->count++;
145
    s->update_irq(s->update_arg, 1);
146
}
147

    
148
/*
149
   keycode is expressed as follow:
150
   bit 7    - 0 key pressed, 1 = key released
151
   bits 6-0 - translated scancode set 2
152
 */
153
static void ps2_put_keycode(void *opaque, int keycode)
154
{
155
    PS2KbdState *s = opaque;
156

    
157
    /* XXX: add support for scancode set 1 */
158
    if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) {
159
        if (keycode & 0x80) {
160
            ps2_queue(&s->common, 0xf0);
161
        }
162
        if (s->scancode_set == 2) {
163
            keycode = ps2_raw_keycode[keycode & 0x7f];
164
        } else if (s->scancode_set == 3) {
165
            keycode = ps2_raw_keycode_set3[keycode & 0x7f];
166
        }
167
      }
168
    ps2_queue(&s->common, keycode);
169
}
170

    
171
uint32_t ps2_read_data(void *opaque)
172
{
173
    PS2State *s = (PS2State *)opaque;
174
    PS2Queue *q;
175
    int val, index;
176

    
177
    q = &s->queue;
178
    if (q->count == 0) {
179
        /* NOTE: if no data left, we return the last keyboard one
180
           (needed for EMM386) */
181
        /* XXX: need a timer to do things correctly */
182
        index = q->rptr - 1;
183
        if (index < 0)
184
            index = PS2_QUEUE_SIZE - 1;
185
        val = q->data[index];
186
    } else {
187
        val = q->data[q->rptr];
188
        if (++q->rptr == PS2_QUEUE_SIZE)
189
            q->rptr = 0;
190
        q->count--;
191
        /* reading deasserts IRQ */
192
        s->update_irq(s->update_arg, 0);
193
        /* reassert IRQs if data left */
194
        s->update_irq(s->update_arg, q->count != 0);
195
    }
196
    return val;
197
}
198

    
199
static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
200
{
201
    s->ledstate = ledstate;
202
    kbd_put_ledstate(ledstate);
203
}
204

    
205
static void ps2_reset_keyboard(PS2KbdState *s)
206
{
207
    s->scan_enabled = 1;
208
    s->scancode_set = 2;
209
    ps2_set_ledstate(s, 0);
210
}
211

    
212
void ps2_write_keyboard(void *opaque, int val)
213
{
214
    PS2KbdState *s = (PS2KbdState *)opaque;
215

    
216
    switch(s->common.write_cmd) {
217
    default:
218
    case -1:
219
        switch(val) {
220
        case 0x00:
221
            ps2_queue(&s->common, KBD_REPLY_ACK);
222
            break;
223
        case 0x05:
224
            ps2_queue(&s->common, KBD_REPLY_RESEND);
225
            break;
226
        case KBD_CMD_GET_ID:
227
            ps2_queue(&s->common, KBD_REPLY_ACK);
228
            /* We emulate a MF2 AT keyboard here */
229
            ps2_queue(&s->common, KBD_REPLY_ID);
230
            if (s->translate)
231
                ps2_queue(&s->common, 0x41);
232
            else
233
                ps2_queue(&s->common, 0x83);
234
            break;
235
        case KBD_CMD_ECHO:
236
            ps2_queue(&s->common, KBD_CMD_ECHO);
237
            break;
238
        case KBD_CMD_ENABLE:
239
            s->scan_enabled = 1;
240
            ps2_queue(&s->common, KBD_REPLY_ACK);
241
            break;
242
        case KBD_CMD_SCANCODE:
243
        case KBD_CMD_SET_LEDS:
244
        case KBD_CMD_SET_RATE:
245
            s->common.write_cmd = val;
246
            ps2_queue(&s->common, KBD_REPLY_ACK);
247
            break;
248
        case KBD_CMD_RESET_DISABLE:
249
            ps2_reset_keyboard(s);
250
            s->scan_enabled = 0;
251
            ps2_queue(&s->common, KBD_REPLY_ACK);
252
            break;
253
        case KBD_CMD_RESET_ENABLE:
254
            ps2_reset_keyboard(s);
255
            s->scan_enabled = 1;
256
            ps2_queue(&s->common, KBD_REPLY_ACK);
257
            break;
258
        case KBD_CMD_RESET:
259
            ps2_reset_keyboard(s);
260
            ps2_queue(&s->common, KBD_REPLY_ACK);
261
            ps2_queue(&s->common, KBD_REPLY_POR);
262
            break;
263
        default:
264
            ps2_queue(&s->common, KBD_REPLY_ACK);
265
            break;
266
        }
267
        break;
268
    case KBD_CMD_SCANCODE:
269
        if (val == 0) {
270
            if (s->scancode_set == 1)
271
                ps2_put_keycode(s, 0x43);
272
            else if (s->scancode_set == 2)
273
                ps2_put_keycode(s, 0x41);
274
            else if (s->scancode_set == 3)
275
                ps2_put_keycode(s, 0x3f);
276
        } else {
277
            if (val >= 1 && val <= 3)
278
                s->scancode_set = val;
279
            ps2_queue(&s->common, KBD_REPLY_ACK);
280
        }
281
        s->common.write_cmd = -1;
282
        break;
283
    case KBD_CMD_SET_LEDS:
284
        ps2_set_ledstate(s, val);
285
        ps2_queue(&s->common, KBD_REPLY_ACK);
286
        s->common.write_cmd = -1;
287
        break;
288
    case KBD_CMD_SET_RATE:
289
        ps2_queue(&s->common, KBD_REPLY_ACK);
290
        s->common.write_cmd = -1;
291
        break;
292
    }
293
}
294

    
295
/* Set the scancode translation mode.
296
   0 = raw scancodes.
297
   1 = translated scancodes (used by qemu internally).  */
298

    
299
void ps2_keyboard_set_translation(void *opaque, int mode)
300
{
301
    PS2KbdState *s = (PS2KbdState *)opaque;
302
    s->translate = mode;
303
}
304

    
305
static void ps2_mouse_send_packet(PS2MouseState *s)
306
{
307
    unsigned int b;
308
    int dx1, dy1, dz1;
309

    
310
    dx1 = s->mouse_dx;
311
    dy1 = s->mouse_dy;
312
    dz1 = s->mouse_dz;
313
    /* XXX: increase range to 8 bits ? */
314
    if (dx1 > 127)
315
        dx1 = 127;
316
    else if (dx1 < -127)
317
        dx1 = -127;
318
    if (dy1 > 127)
319
        dy1 = 127;
320
    else if (dy1 < -127)
321
        dy1 = -127;
322
    b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
323
    ps2_queue(&s->common, b);
324
    ps2_queue(&s->common, dx1 & 0xff);
325
    ps2_queue(&s->common, dy1 & 0xff);
326
    /* extra byte for IMPS/2 or IMEX */
327
    switch(s->mouse_type) {
328
    default:
329
        break;
330
    case 3:
331
        if (dz1 > 127)
332
            dz1 = 127;
333
        else if (dz1 < -127)
334
                dz1 = -127;
335
        ps2_queue(&s->common, dz1 & 0xff);
336
        break;
337
    case 4:
338
        if (dz1 > 7)
339
            dz1 = 7;
340
        else if (dz1 < -7)
341
            dz1 = -7;
342
        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
343
        ps2_queue(&s->common, b);
344
        break;
345
    }
346

    
347
    /* update deltas */
348
    s->mouse_dx -= dx1;
349
    s->mouse_dy -= dy1;
350
    s->mouse_dz -= dz1;
351
}
352

    
353
static void ps2_mouse_event(void *opaque,
354
                            int dx, int dy, int dz, int buttons_state)
355
{
356
    PS2MouseState *s = opaque;
357

    
358
    /* check if deltas are recorded when disabled */
359
    if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
360
        return;
361

    
362
    s->mouse_dx += dx;
363
    s->mouse_dy -= dy;
364
    s->mouse_dz += dz;
365
    /* XXX: SDL sometimes generates nul events: we delete them */
366
    if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
367
        s->mouse_buttons == buttons_state)
368
        return;
369
    s->mouse_buttons = buttons_state;
370

    
371
    if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
372
        (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
373
        for(;;) {
374
            /* if not remote, send event. Multiple events are sent if
375
               too big deltas */
376
            ps2_mouse_send_packet(s);
377
            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
378
                break;
379
        }
380
    }
381
}
382

    
383
void ps2_mouse_fake_event(void *opaque)
384
{
385
    ps2_mouse_event(opaque, 1, 0, 0, 0);
386
}
387

    
388
void ps2_write_mouse(void *opaque, int val)
389
{
390
    PS2MouseState *s = (PS2MouseState *)opaque;
391
#ifdef DEBUG_MOUSE
392
    printf("kbd: write mouse 0x%02x\n", val);
393
#endif
394
    switch(s->common.write_cmd) {
395
    default:
396
    case -1:
397
        /* mouse command */
398
        if (s->mouse_wrap) {
399
            if (val == AUX_RESET_WRAP) {
400
                s->mouse_wrap = 0;
401
                ps2_queue(&s->common, AUX_ACK);
402
                return;
403
            } else if (val != AUX_RESET) {
404
                ps2_queue(&s->common, val);
405
                return;
406
            }
407
        }
408
        switch(val) {
409
        case AUX_SET_SCALE11:
410
            s->mouse_status &= ~MOUSE_STATUS_SCALE21;
411
            ps2_queue(&s->common, AUX_ACK);
412
            break;
413
        case AUX_SET_SCALE21:
414
            s->mouse_status |= MOUSE_STATUS_SCALE21;
415
            ps2_queue(&s->common, AUX_ACK);
416
            break;
417
        case AUX_SET_STREAM:
418
            s->mouse_status &= ~MOUSE_STATUS_REMOTE;
419
            ps2_queue(&s->common, AUX_ACK);
420
            break;
421
        case AUX_SET_WRAP:
422
            s->mouse_wrap = 1;
423
            ps2_queue(&s->common, AUX_ACK);
424
            break;
425
        case AUX_SET_REMOTE:
426
            s->mouse_status |= MOUSE_STATUS_REMOTE;
427
            ps2_queue(&s->common, AUX_ACK);
428
            break;
429
        case AUX_GET_TYPE:
430
            ps2_queue(&s->common, AUX_ACK);
431
            ps2_queue(&s->common, s->mouse_type);
432
            break;
433
        case AUX_SET_RES:
434
        case AUX_SET_SAMPLE:
435
            s->common.write_cmd = val;
436
            ps2_queue(&s->common, AUX_ACK);
437
            break;
438
        case AUX_GET_SCALE:
439
            ps2_queue(&s->common, AUX_ACK);
440
            ps2_queue(&s->common, s->mouse_status);
441
            ps2_queue(&s->common, s->mouse_resolution);
442
            ps2_queue(&s->common, s->mouse_sample_rate);
443
            break;
444
        case AUX_POLL:
445
            ps2_queue(&s->common, AUX_ACK);
446
            ps2_mouse_send_packet(s);
447
            break;
448
        case AUX_ENABLE_DEV:
449
            s->mouse_status |= MOUSE_STATUS_ENABLED;
450
            ps2_queue(&s->common, AUX_ACK);
451
            break;
452
        case AUX_DISABLE_DEV:
453
            s->mouse_status &= ~MOUSE_STATUS_ENABLED;
454
            ps2_queue(&s->common, AUX_ACK);
455
            break;
456
        case AUX_SET_DEFAULT:
457
            s->mouse_sample_rate = 100;
458
            s->mouse_resolution = 2;
459
            s->mouse_status = 0;
460
            ps2_queue(&s->common, AUX_ACK);
461
            break;
462
        case AUX_RESET:
463
            s->mouse_sample_rate = 100;
464
            s->mouse_resolution = 2;
465
            s->mouse_status = 0;
466
            s->mouse_type = 0;
467
            ps2_queue(&s->common, AUX_ACK);
468
            ps2_queue(&s->common, 0xaa);
469
            ps2_queue(&s->common, s->mouse_type);
470
            break;
471
        default:
472
            break;
473
        }
474
        break;
475
    case AUX_SET_SAMPLE:
476
        s->mouse_sample_rate = val;
477
        /* detect IMPS/2 or IMEX */
478
        switch(s->mouse_detect_state) {
479
        default:
480
        case 0:
481
            if (val == 200)
482
                s->mouse_detect_state = 1;
483
            break;
484
        case 1:
485
            if (val == 100)
486
                s->mouse_detect_state = 2;
487
            else if (val == 200)
488
                s->mouse_detect_state = 3;
489
            else
490
                s->mouse_detect_state = 0;
491
            break;
492
        case 2:
493
            if (val == 80)
494
                s->mouse_type = 3; /* IMPS/2 */
495
            s->mouse_detect_state = 0;
496
            break;
497
        case 3:
498
            if (val == 80)
499
                s->mouse_type = 4; /* IMEX */
500
            s->mouse_detect_state = 0;
501
            break;
502
        }
503
        ps2_queue(&s->common, AUX_ACK);
504
        s->common.write_cmd = -1;
505
        break;
506
    case AUX_SET_RES:
507
        s->mouse_resolution = val;
508
        ps2_queue(&s->common, AUX_ACK);
509
        s->common.write_cmd = -1;
510
        break;
511
    }
512
}
513

    
514
static void ps2_common_reset(PS2State *s)
515
{
516
    PS2Queue *q;
517
    s->write_cmd = -1;
518
    q = &s->queue;
519
    q->rptr = 0;
520
    q->wptr = 0;
521
    q->count = 0;
522
    s->update_irq(s->update_arg, 0);
523
}
524

    
525
static void ps2_kbd_reset(void *opaque)
526
{
527
    PS2KbdState *s = (PS2KbdState *) opaque;
528

    
529
    ps2_common_reset(&s->common);
530
    s->scan_enabled = 0;
531
    s->translate = 0;
532
    s->scancode_set = 0;
533
}
534

    
535
static void ps2_mouse_reset(void *opaque)
536
{
537
    PS2MouseState *s = (PS2MouseState *) opaque;
538

    
539
    ps2_common_reset(&s->common);
540
    s->mouse_status = 0;
541
    s->mouse_resolution = 0;
542
    s->mouse_sample_rate = 0;
543
    s->mouse_wrap = 0;
544
    s->mouse_type = 0;
545
    s->mouse_detect_state = 0;
546
    s->mouse_dx = 0;
547
    s->mouse_dy = 0;
548
    s->mouse_dz = 0;
549
    s->mouse_buttons = 0;
550
}
551

    
552
static const VMStateDescription vmstate_ps2_common = {
553
    .name = "PS2 Common State",
554
    .version_id = 3,
555
    .minimum_version_id = 2,
556
    .minimum_version_id_old = 2,
557
    .fields      = (VMStateField []) {
558
        VMSTATE_INT32(write_cmd, PS2State),
559
        VMSTATE_INT32(queue.rptr, PS2State),
560
        VMSTATE_INT32(queue.wptr, PS2State),
561
        VMSTATE_INT32(queue.count, PS2State),
562
        VMSTATE_BUFFER(queue.data, PS2State),
563
        VMSTATE_END_OF_LIST()
564
    }
565
};
566

    
567
static bool ps2_keyboard_ledstate_needed(void *opaque)
568
{
569
    PS2KbdState *s = opaque;
570

    
571
    return s->ledstate != 0; /* 0 is default state */
572
}
573

    
574
static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
575
{
576
    PS2KbdState *s = opaque;
577

    
578
    kbd_put_ledstate(s->ledstate);
579
    return 0;
580
}
581

    
582
static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
583
    .name = "ps2kbd/ledstate",
584
    .version_id = 3,
585
    .minimum_version_id = 2,
586
    .minimum_version_id_old = 2,
587
    .post_load = ps2_kbd_ledstate_post_load,
588
    .fields      = (VMStateField []) {
589
        VMSTATE_INT32(ledstate, PS2KbdState),
590
        VMSTATE_END_OF_LIST()
591
    }
592
};
593

    
594
static int ps2_kbd_post_load(void* opaque, int version_id)
595
{
596
    PS2KbdState *s = (PS2KbdState*)opaque;
597

    
598
    if (version_id == 2)
599
        s->scancode_set=2;
600
    return 0;
601
}
602

    
603
static const VMStateDescription vmstate_ps2_keyboard = {
604
    .name = "ps2kbd",
605
    .version_id = 3,
606
    .minimum_version_id = 2,
607
    .minimum_version_id_old = 2,
608
    .post_load = ps2_kbd_post_load,
609
    .fields      = (VMStateField []) {
610
        VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
611
        VMSTATE_INT32(scan_enabled, PS2KbdState),
612
        VMSTATE_INT32(translate, PS2KbdState),
613
        VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
614
        VMSTATE_END_OF_LIST()
615
    },
616
    .subsections = (VMStateSubsection []) {
617
        {
618
            .vmsd = &vmstate_ps2_keyboard_ledstate,
619
            .needed = ps2_keyboard_ledstate_needed,
620
        }, {
621
            /* empty */
622
        }
623
    }
624
};
625

    
626
static const VMStateDescription vmstate_ps2_mouse = {
627
    .name = "ps2mouse",
628
    .version_id = 2,
629
    .minimum_version_id = 2,
630
    .minimum_version_id_old = 2,
631
    .fields      = (VMStateField []) {
632
        VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
633
        VMSTATE_UINT8(mouse_status, PS2MouseState),
634
        VMSTATE_UINT8(mouse_resolution, PS2MouseState),
635
        VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
636
        VMSTATE_UINT8(mouse_wrap, PS2MouseState),
637
        VMSTATE_UINT8(mouse_type, PS2MouseState),
638
        VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
639
        VMSTATE_INT32(mouse_dx, PS2MouseState),
640
        VMSTATE_INT32(mouse_dy, PS2MouseState),
641
        VMSTATE_INT32(mouse_dz, PS2MouseState),
642
        VMSTATE_UINT8(mouse_buttons, PS2MouseState),
643
        VMSTATE_END_OF_LIST()
644
    }
645
};
646

    
647
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
648
{
649
    PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
650

    
651
    s->common.update_irq = update_irq;
652
    s->common.update_arg = update_arg;
653
    s->scancode_set = 2;
654
    vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
655
    qemu_add_kbd_event_handler(ps2_put_keycode, s);
656
    qemu_register_reset(ps2_kbd_reset, s);
657
    return s;
658
}
659

    
660
void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
661
{
662
    PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
663

    
664
    s->common.update_irq = update_irq;
665
    s->common.update_arg = update_arg;
666
    vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
667
    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
668
    qemu_register_reset(ps2_mouse_reset, s);
669
    return s;
670
}