Statistics
| Branch: | Revision:

root / hw / ps2.c @ e7d93956

History | View | Annotate | Download (17.9 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_ACK                0xFA        /* Command ACK */
48
#define KBD_REPLY_RESEND        0xFE        /* Command NACK, send the cmd again */
49

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

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

    
72
#define PS2_QUEUE_SIZE 256
73

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

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

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

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

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

    
122
void ps2_queue(void *opaque, int b)
123
{
124
    PS2State *s = (PS2State *)opaque;
125
    PS2Queue *q = &s->queue;
126

    
127
    if (q->count >= PS2_QUEUE_SIZE)
128
        return;
129
    q->data[q->wptr] = b;
130
    if (++q->wptr == PS2_QUEUE_SIZE)
131
        q->wptr = 0;
132
    q->count++;
133
    s->update_irq(s->update_arg, 1);
134
}
135

    
136
/* keycode is expressed in scancode set 2 */
137
static void ps2_put_keycode(void *opaque, int keycode)
138
{
139
    PS2KbdState *s = opaque;
140

    
141
    /* XXX: add support for scancode sets 1 and 3 */
142
    if (!s->translate && keycode < 0xe0 && s->scancode_set == 2)
143
      {
144
        if (keycode & 0x80)
145
            ps2_queue(&s->common, 0xf0);
146
        keycode = ps2_raw_keycode[keycode & 0x7f];
147
      }
148
    ps2_queue(&s->common, keycode);
149
}
150

    
151
uint32_t ps2_read_data(void *opaque)
152
{
153
    PS2State *s = (PS2State *)opaque;
154
    PS2Queue *q;
155
    int val, index;
156

    
157
    q = &s->queue;
158
    if (q->count == 0) {
159
        /* NOTE: if no data left, we return the last keyboard one
160
           (needed for EMM386) */
161
        /* XXX: need a timer to do things correctly */
162
        index = q->rptr - 1;
163
        if (index < 0)
164
            index = PS2_QUEUE_SIZE - 1;
165
        val = q->data[index];
166
    } else {
167
        val = q->data[q->rptr];
168
        if (++q->rptr == PS2_QUEUE_SIZE)
169
            q->rptr = 0;
170
        q->count--;
171
        /* reading deasserts IRQ */
172
        s->update_irq(s->update_arg, 0);
173
        /* reassert IRQs if data left */
174
        s->update_irq(s->update_arg, q->count != 0);
175
    }
176
    return val;
177
}
178

    
179
static void ps2_reset_keyboard(PS2KbdState *s)
180
{
181
    s->scan_enabled = 1;
182
    s->scancode_set = 2;
183
}
184

    
185
void ps2_write_keyboard(void *opaque, int val)
186
{
187
    PS2KbdState *s = (PS2KbdState *)opaque;
188

    
189
    switch(s->common.write_cmd) {
190
    default:
191
    case -1:
192
        switch(val) {
193
        case 0x00:
194
            ps2_queue(&s->common, KBD_REPLY_ACK);
195
            break;
196
        case 0x05:
197
            ps2_queue(&s->common, KBD_REPLY_RESEND);
198
            break;
199
        case KBD_CMD_GET_ID:
200
            ps2_queue(&s->common, KBD_REPLY_ACK);
201
            /* We emulate a MF2 AT keyboard here */
202
            ps2_put_keycode(s, 0xab);
203
            ps2_put_keycode(s, 0x83);
204
            break;
205
        case KBD_CMD_ECHO:
206
            ps2_queue(&s->common, KBD_CMD_ECHO);
207
            break;
208
        case KBD_CMD_ENABLE:
209
            s->scan_enabled = 1;
210
            ps2_queue(&s->common, KBD_REPLY_ACK);
211
            break;
212
        case KBD_CMD_SCANCODE:
213
        case KBD_CMD_SET_LEDS:
214
        case KBD_CMD_SET_RATE:
215
            s->common.write_cmd = val;
216
            ps2_queue(&s->common, KBD_REPLY_ACK);
217
            break;
218
        case KBD_CMD_RESET_DISABLE:
219
            ps2_reset_keyboard(s);
220
            s->scan_enabled = 0;
221
            ps2_queue(&s->common, KBD_REPLY_ACK);
222
            break;
223
        case KBD_CMD_RESET_ENABLE:
224
            ps2_reset_keyboard(s);
225
            s->scan_enabled = 1;
226
            ps2_queue(&s->common, KBD_REPLY_ACK);
227
            break;
228
        case KBD_CMD_RESET:
229
            ps2_reset_keyboard(s);
230
            ps2_queue(&s->common, KBD_REPLY_ACK);
231
            ps2_queue(&s->common, KBD_REPLY_POR);
232
            break;
233
        default:
234
            ps2_queue(&s->common, KBD_REPLY_ACK);
235
            break;
236
        }
237
        break;
238
    case KBD_CMD_SCANCODE:
239
        if (val == 0) {
240
            if (s->scancode_set == 1)
241
                ps2_put_keycode(s, 0x43);
242
            else if (s->scancode_set == 2)
243
                ps2_put_keycode(s, 0x41);
244
            else if (s->scancode_set == 3)
245
                ps2_put_keycode(s, 0x3f);
246
        } else {
247
            if (val >= 1 && val <= 3)
248
                s->scancode_set = val;
249
            ps2_queue(&s->common, KBD_REPLY_ACK);
250
        }
251
        s->common.write_cmd = -1;
252
        break;
253
    case KBD_CMD_SET_LEDS:
254
        ps2_queue(&s->common, KBD_REPLY_ACK);
255
        s->common.write_cmd = -1;
256
        break;
257
    case KBD_CMD_SET_RATE:
258
        ps2_queue(&s->common, KBD_REPLY_ACK);
259
        s->common.write_cmd = -1;
260
        break;
261
    }
262
}
263

    
264
/* Set the scancode translation mode.
265
   0 = raw scancodes.
266
   1 = translated scancodes (used by qemu internally).  */
267

    
268
void ps2_keyboard_set_translation(void *opaque, int mode)
269
{
270
    PS2KbdState *s = (PS2KbdState *)opaque;
271
    s->translate = mode;
272
}
273

    
274
static void ps2_mouse_send_packet(PS2MouseState *s)
275
{
276
    unsigned int b;
277
    int dx1, dy1, dz1;
278

    
279
    dx1 = s->mouse_dx;
280
    dy1 = s->mouse_dy;
281
    dz1 = s->mouse_dz;
282
    /* XXX: increase range to 8 bits ? */
283
    if (dx1 > 127)
284
        dx1 = 127;
285
    else if (dx1 < -127)
286
        dx1 = -127;
287
    if (dy1 > 127)
288
        dy1 = 127;
289
    else if (dy1 < -127)
290
        dy1 = -127;
291
    b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
292
    ps2_queue(&s->common, b);
293
    ps2_queue(&s->common, dx1 & 0xff);
294
    ps2_queue(&s->common, dy1 & 0xff);
295
    /* extra byte for IMPS/2 or IMEX */
296
    switch(s->mouse_type) {
297
    default:
298
        break;
299
    case 3:
300
        if (dz1 > 127)
301
            dz1 = 127;
302
        else if (dz1 < -127)
303
                dz1 = -127;
304
        ps2_queue(&s->common, dz1 & 0xff);
305
        break;
306
    case 4:
307
        if (dz1 > 7)
308
            dz1 = 7;
309
        else if (dz1 < -7)
310
            dz1 = -7;
311
        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
312
        ps2_queue(&s->common, b);
313
        break;
314
    }
315

    
316
    /* update deltas */
317
    s->mouse_dx -= dx1;
318
    s->mouse_dy -= dy1;
319
    s->mouse_dz -= dz1;
320
}
321

    
322
static void ps2_mouse_event(void *opaque,
323
                            int dx, int dy, int dz, int buttons_state)
324
{
325
    PS2MouseState *s = opaque;
326

    
327
    /* check if deltas are recorded when disabled */
328
    if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
329
        return;
330

    
331
    s->mouse_dx += dx;
332
    s->mouse_dy -= dy;
333
    s->mouse_dz += dz;
334
    /* XXX: SDL sometimes generates nul events: we delete them */
335
    if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
336
        s->mouse_buttons == buttons_state)
337
        return;
338
    s->mouse_buttons = buttons_state;
339

    
340
    if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
341
        (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
342
        for(;;) {
343
            /* if not remote, send event. Multiple events are sent if
344
               too big deltas */
345
            ps2_mouse_send_packet(s);
346
            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
347
                break;
348
        }
349
    }
350
}
351

    
352
void ps2_mouse_fake_event(void *opaque)
353
{
354
    ps2_mouse_event(opaque, 1, 0, 0, 0);
355
}
356

    
357
void ps2_write_mouse(void *opaque, int val)
358
{
359
    PS2MouseState *s = (PS2MouseState *)opaque;
360
#ifdef DEBUG_MOUSE
361
    printf("kbd: write mouse 0x%02x\n", val);
362
#endif
363
    switch(s->common.write_cmd) {
364
    default:
365
    case -1:
366
        /* mouse command */
367
        if (s->mouse_wrap) {
368
            if (val == AUX_RESET_WRAP) {
369
                s->mouse_wrap = 0;
370
                ps2_queue(&s->common, AUX_ACK);
371
                return;
372
            } else if (val != AUX_RESET) {
373
                ps2_queue(&s->common, val);
374
                return;
375
            }
376
        }
377
        switch(val) {
378
        case AUX_SET_SCALE11:
379
            s->mouse_status &= ~MOUSE_STATUS_SCALE21;
380
            ps2_queue(&s->common, AUX_ACK);
381
            break;
382
        case AUX_SET_SCALE21:
383
            s->mouse_status |= MOUSE_STATUS_SCALE21;
384
            ps2_queue(&s->common, AUX_ACK);
385
            break;
386
        case AUX_SET_STREAM:
387
            s->mouse_status &= ~MOUSE_STATUS_REMOTE;
388
            ps2_queue(&s->common, AUX_ACK);
389
            break;
390
        case AUX_SET_WRAP:
391
            s->mouse_wrap = 1;
392
            ps2_queue(&s->common, AUX_ACK);
393
            break;
394
        case AUX_SET_REMOTE:
395
            s->mouse_status |= MOUSE_STATUS_REMOTE;
396
            ps2_queue(&s->common, AUX_ACK);
397
            break;
398
        case AUX_GET_TYPE:
399
            ps2_queue(&s->common, AUX_ACK);
400
            ps2_queue(&s->common, s->mouse_type);
401
            break;
402
        case AUX_SET_RES:
403
        case AUX_SET_SAMPLE:
404
            s->common.write_cmd = val;
405
            ps2_queue(&s->common, AUX_ACK);
406
            break;
407
        case AUX_GET_SCALE:
408
            ps2_queue(&s->common, AUX_ACK);
409
            ps2_queue(&s->common, s->mouse_status);
410
            ps2_queue(&s->common, s->mouse_resolution);
411
            ps2_queue(&s->common, s->mouse_sample_rate);
412
            break;
413
        case AUX_POLL:
414
            ps2_queue(&s->common, AUX_ACK);
415
            ps2_mouse_send_packet(s);
416
            break;
417
        case AUX_ENABLE_DEV:
418
            s->mouse_status |= MOUSE_STATUS_ENABLED;
419
            ps2_queue(&s->common, AUX_ACK);
420
            break;
421
        case AUX_DISABLE_DEV:
422
            s->mouse_status &= ~MOUSE_STATUS_ENABLED;
423
            ps2_queue(&s->common, AUX_ACK);
424
            break;
425
        case AUX_SET_DEFAULT:
426
            s->mouse_sample_rate = 100;
427
            s->mouse_resolution = 2;
428
            s->mouse_status = 0;
429
            ps2_queue(&s->common, AUX_ACK);
430
            break;
431
        case AUX_RESET:
432
            s->mouse_sample_rate = 100;
433
            s->mouse_resolution = 2;
434
            s->mouse_status = 0;
435
            s->mouse_type = 0;
436
            ps2_queue(&s->common, AUX_ACK);
437
            ps2_queue(&s->common, 0xaa);
438
            ps2_queue(&s->common, s->mouse_type);
439
            break;
440
        default:
441
            break;
442
        }
443
        break;
444
    case AUX_SET_SAMPLE:
445
        s->mouse_sample_rate = val;
446
        /* detect IMPS/2 or IMEX */
447
        switch(s->mouse_detect_state) {
448
        default:
449
        case 0:
450
            if (val == 200)
451
                s->mouse_detect_state = 1;
452
            break;
453
        case 1:
454
            if (val == 100)
455
                s->mouse_detect_state = 2;
456
            else if (val == 200)
457
                s->mouse_detect_state = 3;
458
            else
459
                s->mouse_detect_state = 0;
460
            break;
461
        case 2:
462
            if (val == 80)
463
                s->mouse_type = 3; /* IMPS/2 */
464
            s->mouse_detect_state = 0;
465
            break;
466
        case 3:
467
            if (val == 80)
468
                s->mouse_type = 4; /* IMEX */
469
            s->mouse_detect_state = 0;
470
            break;
471
        }
472
        ps2_queue(&s->common, AUX_ACK);
473
        s->common.write_cmd = -1;
474
        break;
475
    case AUX_SET_RES:
476
        s->mouse_resolution = val;
477
        ps2_queue(&s->common, AUX_ACK);
478
        s->common.write_cmd = -1;
479
        break;
480
    }
481
}
482

    
483
static void ps2_reset(void *opaque)
484
{
485
    PS2State *s = (PS2State *)opaque;
486
    PS2Queue *q;
487
    s->write_cmd = -1;
488
    q = &s->queue;
489
    q->rptr = 0;
490
    q->wptr = 0;
491
    q->count = 0;
492
}
493

    
494
static void ps2_common_save (QEMUFile *f, PS2State *s)
495
{
496
    qemu_put_be32 (f, s->write_cmd);
497
    qemu_put_be32 (f, s->queue.rptr);
498
    qemu_put_be32 (f, s->queue.wptr);
499
    qemu_put_be32 (f, s->queue.count);
500
    qemu_put_buffer (f, s->queue.data, sizeof (s->queue.data));
501
}
502

    
503
static void ps2_common_load (QEMUFile *f, PS2State *s)
504
{
505
    s->write_cmd=qemu_get_be32 (f);
506
    s->queue.rptr=qemu_get_be32 (f);
507
    s->queue.wptr=qemu_get_be32 (f);
508
    s->queue.count=qemu_get_be32 (f);
509
    qemu_get_buffer (f, s->queue.data, sizeof (s->queue.data));
510
}
511

    
512
static void ps2_kbd_save(QEMUFile* f, void* opaque)
513
{
514
    PS2KbdState *s = (PS2KbdState*)opaque;
515

    
516
    ps2_common_save (f, &s->common);
517
    qemu_put_be32(f, s->scan_enabled);
518
    qemu_put_be32(f, s->translate);
519
    qemu_put_be32(f, s->scancode_set);
520
}
521

    
522
static void ps2_mouse_save(QEMUFile* f, void* opaque)
523
{
524
    PS2MouseState *s = (PS2MouseState*)opaque;
525

    
526
    ps2_common_save (f, &s->common);
527
    qemu_put_8s(f, &s->mouse_status);
528
    qemu_put_8s(f, &s->mouse_resolution);
529
    qemu_put_8s(f, &s->mouse_sample_rate);
530
    qemu_put_8s(f, &s->mouse_wrap);
531
    qemu_put_8s(f, &s->mouse_type);
532
    qemu_put_8s(f, &s->mouse_detect_state);
533
    qemu_put_be32(f, s->mouse_dx);
534
    qemu_put_be32(f, s->mouse_dy);
535
    qemu_put_be32(f, s->mouse_dz);
536
    qemu_put_8s(f, &s->mouse_buttons);
537
}
538

    
539
static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id)
540
{
541
    PS2KbdState *s = (PS2KbdState*)opaque;
542

    
543
    if (version_id != 2 && version_id != 3)
544
        return -EINVAL;
545

    
546
    ps2_common_load (f, &s->common);
547
    s->scan_enabled=qemu_get_be32(f);
548
    s->translate=qemu_get_be32(f);
549
    if (version_id == 3)
550
        s->scancode_set=qemu_get_be32(f);
551
    else
552
        s->scancode_set=2;
553
    return 0;
554
}
555

    
556
static int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id)
557
{
558
    PS2MouseState *s = (PS2MouseState*)opaque;
559

    
560
    if (version_id != 2)
561
        return -EINVAL;
562

    
563
    ps2_common_load (f, &s->common);
564
    qemu_get_8s(f, &s->mouse_status);
565
    qemu_get_8s(f, &s->mouse_resolution);
566
    qemu_get_8s(f, &s->mouse_sample_rate);
567
    qemu_get_8s(f, &s->mouse_wrap);
568
    qemu_get_8s(f, &s->mouse_type);
569
    qemu_get_8s(f, &s->mouse_detect_state);
570
    s->mouse_dx=qemu_get_be32(f);
571
    s->mouse_dy=qemu_get_be32(f);
572
    s->mouse_dz=qemu_get_be32(f);
573
    qemu_get_8s(f, &s->mouse_buttons);
574
    return 0;
575
}
576

    
577
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
578
{
579
    PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
580

    
581
    s->common.update_irq = update_irq;
582
    s->common.update_arg = update_arg;
583
    s->scancode_set = 2;
584
    ps2_reset(&s->common);
585
    register_savevm("ps2kbd", 0, 3, ps2_kbd_save, ps2_kbd_load, s);
586
    qemu_add_kbd_event_handler(ps2_put_keycode, s);
587
    qemu_register_reset(ps2_reset, &s->common);
588
    return s;
589
}
590

    
591
void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
592
{
593
    PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
594

    
595
    s->common.update_irq = update_irq;
596
    s->common.update_arg = update_arg;
597
    ps2_reset(&s->common);
598
    register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
599
    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
600
    qemu_register_reset(ps2_reset, &s->common);
601
    return s;
602
}