qemu/hw/ps2.c
<<
>>
Prefs
   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
  75typedef struct {
  76    uint8_t data[PS2_QUEUE_SIZE];
  77    int rptr, wptr, count;
  78} PS2Queue;
  79
  80typedef struct {
  81    PS2Queue queue;
  82    int32_t write_cmd;
  83    void (*update_irq)(void *, int);
  84    void *update_arg;
  85} PS2State;
  86
  87typedef 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} PS2KbdState;
  96
  97typedef struct {
  98    PS2State common;
  99    uint8_t mouse_status;
 100    uint8_t mouse_resolution;
 101    uint8_t mouse_sample_rate;
 102    uint8_t mouse_wrap;
 103    uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
 104    uint8_t mouse_detect_state;
 105    int mouse_dx; /* current values, needed for 'poll' mode */
 106    int mouse_dy;
 107    int mouse_dz;
 108    uint8_t mouse_buttons;
 109} PS2MouseState;
 110
 111/* Table to convert from PC scancodes to raw scancodes.  */
 112static const unsigned char ps2_raw_keycode[128] = {
 113          0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
 114         21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
 115         35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
 116         50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
 117         11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
 118        114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
 119         71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
 120         19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
 121};
 122
 123void ps2_queue(void *opaque, int b)
 124{
 125    PS2State *s = (PS2State *)opaque;
 126    PS2Queue *q = &s->queue;
 127
 128    if (q->count >= PS2_QUEUE_SIZE)
 129        return;
 130    q->data[q->wptr] = b;
 131    if (++q->wptr == PS2_QUEUE_SIZE)
 132        q->wptr = 0;
 133    q->count++;
 134    s->update_irq(s->update_arg, 1);
 135}
 136
 137/*
 138   keycode is expressed as follow:
 139   bit 7    - 0 key pressed, 1 = key released
 140   bits 6-0 - translated scancode set 2
 141 */
 142static void ps2_put_keycode(void *opaque, int keycode)
 143{
 144    PS2KbdState *s = opaque;
 145
 146    /* XXX: add support for scancode sets 1 and 3 */
 147    if (!s->translate && keycode < 0xe0 && s->scancode_set == 2)
 148      {
 149        if (keycode & 0x80)
 150            ps2_queue(&s->common, 0xf0);
 151        keycode = ps2_raw_keycode[keycode & 0x7f];
 152      }
 153    ps2_queue(&s->common, keycode);
 154}
 155
 156uint32_t ps2_read_data(void *opaque)
 157{
 158    PS2State *s = (PS2State *)opaque;
 159    PS2Queue *q;
 160    int val, index;
 161
 162    q = &s->queue;
 163    if (q->count == 0) {
 164        /* NOTE: if no data left, we return the last keyboard one
 165           (needed for EMM386) */
 166        /* XXX: need a timer to do things correctly */
 167        index = q->rptr - 1;
 168        if (index < 0)
 169            index = PS2_QUEUE_SIZE - 1;
 170        val = q->data[index];
 171    } else {
 172        val = q->data[q->rptr];
 173        if (++q->rptr == PS2_QUEUE_SIZE)
 174            q->rptr = 0;
 175        q->count--;
 176        /* reading deasserts IRQ */
 177        s->update_irq(s->update_arg, 0);
 178        /* reassert IRQs if data left */
 179        s->update_irq(s->update_arg, q->count != 0);
 180    }
 181    return val;
 182}
 183
 184static void ps2_reset_keyboard(PS2KbdState *s)
 185{
 186    s->scan_enabled = 1;
 187    s->scancode_set = 2;
 188}
 189
 190void ps2_write_keyboard(void *opaque, int val)
 191{
 192    PS2KbdState *s = (PS2KbdState *)opaque;
 193
 194    switch(s->common.write_cmd) {
 195    default:
 196    case -1:
 197        switch(val) {
 198        case 0x00:
 199            ps2_queue(&s->common, KBD_REPLY_ACK);
 200            break;
 201        case 0x05:
 202            ps2_queue(&s->common, KBD_REPLY_RESEND);
 203            break;
 204        case KBD_CMD_GET_ID:
 205            ps2_queue(&s->common, KBD_REPLY_ACK);
 206            /* We emulate a MF2 AT keyboard here */
 207            ps2_queue(&s->common, KBD_REPLY_ID);
 208            if (s->translate)
 209                ps2_queue(&s->common, 0x41);
 210            else
 211                ps2_queue(&s->common, 0x83);
 212            break;
 213        case KBD_CMD_ECHO:
 214            ps2_queue(&s->common, KBD_CMD_ECHO);
 215            break;
 216        case KBD_CMD_ENABLE:
 217            s->scan_enabled = 1;
 218            ps2_queue(&s->common, KBD_REPLY_ACK);
 219            break;
 220        case KBD_CMD_SCANCODE:
 221        case KBD_CMD_SET_LEDS:
 222        case KBD_CMD_SET_RATE:
 223            s->common.write_cmd = val;
 224            ps2_queue(&s->common, KBD_REPLY_ACK);
 225            break;
 226        case KBD_CMD_RESET_DISABLE:
 227            ps2_reset_keyboard(s);
 228            s->scan_enabled = 0;
 229            ps2_queue(&s->common, KBD_REPLY_ACK);
 230            break;
 231        case KBD_CMD_RESET_ENABLE:
 232            ps2_reset_keyboard(s);
 233            s->scan_enabled = 1;
 234            ps2_queue(&s->common, KBD_REPLY_ACK);
 235            break;
 236        case KBD_CMD_RESET:
 237            ps2_reset_keyboard(s);
 238            ps2_queue(&s->common, KBD_REPLY_ACK);
 239            ps2_queue(&s->common, KBD_REPLY_POR);
 240            break;
 241        default:
 242            ps2_queue(&s->common, KBD_REPLY_ACK);
 243            break;
 244        }
 245        break;
 246    case KBD_CMD_SCANCODE:
 247        if (val == 0) {
 248            if (s->scancode_set == 1)
 249                ps2_put_keycode(s, 0x43);
 250            else if (s->scancode_set == 2)
 251                ps2_put_keycode(s, 0x41);
 252            else if (s->scancode_set == 3)
 253                ps2_put_keycode(s, 0x3f);
 254        } else {
 255            if (val >= 1 && val <= 3)
 256                s->scancode_set = val;
 257            ps2_queue(&s->common, KBD_REPLY_ACK);
 258        }
 259        s->common.write_cmd = -1;
 260        break;
 261    case KBD_CMD_SET_LEDS:
 262        ps2_queue(&s->common, KBD_REPLY_ACK);
 263        s->common.write_cmd = -1;
 264        break;
 265    case KBD_CMD_SET_RATE:
 266        ps2_queue(&s->common, KBD_REPLY_ACK);
 267        s->common.write_cmd = -1;
 268        break;
 269    }
 270}
 271
 272/* Set the scancode translation mode.
 273   0 = raw scancodes.
 274   1 = translated scancodes (used by qemu internally).  */
 275
 276void ps2_keyboard_set_translation(void *opaque, int mode)
 277{
 278    PS2KbdState *s = (PS2KbdState *)opaque;
 279    s->translate = mode;
 280}
 281
 282static void ps2_mouse_send_packet(PS2MouseState *s)
 283{
 284    unsigned int b;
 285    int dx1, dy1, dz1;
 286
 287    dx1 = s->mouse_dx;
 288    dy1 = s->mouse_dy;
 289    dz1 = s->mouse_dz;
 290    /* XXX: increase range to 8 bits ? */
 291    if (dx1 > 127)
 292        dx1 = 127;
 293    else if (dx1 < -127)
 294        dx1 = -127;
 295    if (dy1 > 127)
 296        dy1 = 127;
 297    else if (dy1 < -127)
 298        dy1 = -127;
 299    b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
 300    ps2_queue(&s->common, b);
 301    ps2_queue(&s->common, dx1 & 0xff);
 302    ps2_queue(&s->common, dy1 & 0xff);
 303    /* extra byte for IMPS/2 or IMEX */
 304    switch(s->mouse_type) {
 305    default:
 306        break;
 307    case 3:
 308        if (dz1 > 127)
 309            dz1 = 127;
 310        else if (dz1 < -127)
 311                dz1 = -127;
 312        ps2_queue(&s->common, dz1 & 0xff);
 313        break;
 314    case 4:
 315        if (dz1 > 7)
 316            dz1 = 7;
 317        else if (dz1 < -7)
 318            dz1 = -7;
 319        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
 320        ps2_queue(&s->common, b);
 321        break;
 322    }
 323
 324    /* update deltas */
 325    s->mouse_dx -= dx1;
 326    s->mouse_dy -= dy1;
 327    s->mouse_dz -= dz1;
 328}
 329
 330static void ps2_mouse_event(void *opaque,
 331                            int dx, int dy, int dz, int buttons_state)
 332{
 333    PS2MouseState *s = opaque;
 334
 335    /* check if deltas are recorded when disabled */
 336    if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
 337        return;
 338
 339    s->mouse_dx += dx;
 340    s->mouse_dy -= dy;
 341    s->mouse_dz += dz;
 342    /* XXX: SDL sometimes generates nul events: we delete them */
 343    if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
 344        s->mouse_buttons == buttons_state)
 345        return;
 346    s->mouse_buttons = buttons_state;
 347
 348    if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
 349        (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
 350        for(;;) {
 351            /* if not remote, send event. Multiple events are sent if
 352               too big deltas */
 353            ps2_mouse_send_packet(s);
 354            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
 355                break;
 356        }
 357    }
 358}
 359
 360void ps2_mouse_fake_event(void *opaque)
 361{
 362    ps2_mouse_event(opaque, 1, 0, 0, 0);
 363}
 364
 365void ps2_write_mouse(void *opaque, int val)
 366{
 367    PS2MouseState *s = (PS2MouseState *)opaque;
 368#ifdef DEBUG_MOUSE
 369    printf("kbd: write mouse 0x%02x\n", val);
 370#endif
 371    switch(s->common.write_cmd) {
 372    default:
 373    case -1:
 374        /* mouse command */
 375        if (s->mouse_wrap) {
 376            if (val == AUX_RESET_WRAP) {
 377                s->mouse_wrap = 0;
 378                ps2_queue(&s->common, AUX_ACK);
 379                return;
 380            } else if (val != AUX_RESET) {
 381                ps2_queue(&s->common, val);
 382                return;
 383            }
 384        }
 385        switch(val) {
 386        case AUX_SET_SCALE11:
 387            s->mouse_status &= ~MOUSE_STATUS_SCALE21;
 388            ps2_queue(&s->common, AUX_ACK);
 389            break;
 390        case AUX_SET_SCALE21:
 391            s->mouse_status |= MOUSE_STATUS_SCALE21;
 392            ps2_queue(&s->common, AUX_ACK);
 393            break;
 394        case AUX_SET_STREAM:
 395            s->mouse_status &= ~MOUSE_STATUS_REMOTE;
 396            ps2_queue(&s->common, AUX_ACK);
 397            break;
 398        case AUX_SET_WRAP:
 399            s->mouse_wrap = 1;
 400            ps2_queue(&s->common, AUX_ACK);
 401            break;
 402        case AUX_SET_REMOTE:
 403            s->mouse_status |= MOUSE_STATUS_REMOTE;
 404            ps2_queue(&s->common, AUX_ACK);
 405            break;
 406        case AUX_GET_TYPE:
 407            ps2_queue(&s->common, AUX_ACK);
 408            ps2_queue(&s->common, s->mouse_type);
 409            break;
 410        case AUX_SET_RES:
 411        case AUX_SET_SAMPLE:
 412            s->common.write_cmd = val;
 413            ps2_queue(&s->common, AUX_ACK);
 414            break;
 415        case AUX_GET_SCALE:
 416            ps2_queue(&s->common, AUX_ACK);
 417            ps2_queue(&s->common, s->mouse_status);
 418            ps2_queue(&s->common, s->mouse_resolution);
 419            ps2_queue(&s->common, s->mouse_sample_rate);
 420            break;
 421        case AUX_POLL:
 422            ps2_queue(&s->common, AUX_ACK);
 423            ps2_mouse_send_packet(s);
 424            break;
 425        case AUX_ENABLE_DEV:
 426            s->mouse_status |= MOUSE_STATUS_ENABLED;
 427            ps2_queue(&s->common, AUX_ACK);
 428            break;
 429        case AUX_DISABLE_DEV:
 430            s->mouse_status &= ~MOUSE_STATUS_ENABLED;
 431            ps2_queue(&s->common, AUX_ACK);
 432            break;
 433        case AUX_SET_DEFAULT:
 434            s->mouse_sample_rate = 100;
 435            s->mouse_resolution = 2;
 436            s->mouse_status = 0;
 437            ps2_queue(&s->common, AUX_ACK);
 438            break;
 439        case AUX_RESET:
 440            s->mouse_sample_rate = 100;
 441            s->mouse_resolution = 2;
 442            s->mouse_status = 0;
 443            s->mouse_type = 0;
 444            ps2_queue(&s->common, AUX_ACK);
 445            ps2_queue(&s->common, 0xaa);
 446            ps2_queue(&s->common, s->mouse_type);
 447            break;
 448        default:
 449            break;
 450        }
 451        break;
 452    case AUX_SET_SAMPLE:
 453        s->mouse_sample_rate = val;
 454        /* detect IMPS/2 or IMEX */
 455        switch(s->mouse_detect_state) {
 456        default:
 457        case 0:
 458            if (val == 200)
 459                s->mouse_detect_state = 1;
 460            break;
 461        case 1:
 462            if (val == 100)
 463                s->mouse_detect_state = 2;
 464            else if (val == 200)
 465                s->mouse_detect_state = 3;
 466            else
 467                s->mouse_detect_state = 0;
 468            break;
 469        case 2:
 470            if (val == 80)
 471                s->mouse_type = 3; /* IMPS/2 */
 472            s->mouse_detect_state = 0;
 473            break;
 474        case 3:
 475            if (val == 80)
 476                s->mouse_type = 4; /* IMEX */
 477            s->mouse_detect_state = 0;
 478            break;
 479        }
 480        ps2_queue(&s->common, AUX_ACK);
 481        s->common.write_cmd = -1;
 482        break;
 483    case AUX_SET_RES:
 484        s->mouse_resolution = val;
 485        ps2_queue(&s->common, AUX_ACK);
 486        s->common.write_cmd = -1;
 487        break;
 488    }
 489}
 490
 491static void ps2_common_reset(PS2State *s)
 492{
 493    PS2Queue *q;
 494    s->write_cmd = -1;
 495    q = &s->queue;
 496    q->rptr = 0;
 497    q->wptr = 0;
 498    q->count = 0;
 499    s->update_irq(s->update_arg, 0);
 500}
 501
 502static void ps2_kbd_reset(void *opaque)
 503{
 504    PS2KbdState *s = (PS2KbdState *) opaque;
 505
 506    ps2_common_reset(&s->common);
 507    s->scan_enabled = 0;
 508    s->translate = 0;
 509    s->scancode_set = 0;
 510}
 511
 512static void ps2_mouse_reset(void *opaque)
 513{
 514    PS2MouseState *s = (PS2MouseState *) opaque;
 515
 516    ps2_common_reset(&s->common);
 517    s->mouse_status = 0;
 518    s->mouse_resolution = 0;
 519    s->mouse_sample_rate = 0;
 520    s->mouse_wrap = 0;
 521    s->mouse_type = 0;
 522    s->mouse_detect_state = 0;
 523    s->mouse_dx = 0;
 524    s->mouse_dy = 0;
 525    s->mouse_dz = 0;
 526    s->mouse_buttons = 0;
 527}
 528
 529static void ps2_common_save (QEMUFile *f, PS2State *s)
 530{
 531    qemu_put_be32 (f, s->write_cmd);
 532    qemu_put_be32 (f, s->queue.rptr);
 533    qemu_put_be32 (f, s->queue.wptr);
 534    qemu_put_be32 (f, s->queue.count);
 535    qemu_put_buffer (f, s->queue.data, sizeof (s->queue.data));
 536}
 537
 538static void ps2_common_load (QEMUFile *f, PS2State *s)
 539{
 540    s->write_cmd=qemu_get_be32 (f);
 541    s->queue.rptr=qemu_get_be32 (f);
 542    s->queue.wptr=qemu_get_be32 (f);
 543    s->queue.count=qemu_get_be32 (f);
 544    qemu_get_buffer (f, s->queue.data, sizeof (s->queue.data));
 545}
 546
 547static void ps2_kbd_save(QEMUFile* f, void* opaque)
 548{
 549    PS2KbdState *s = (PS2KbdState*)opaque;
 550
 551    ps2_common_save (f, &s->common);
 552    qemu_put_be32(f, s->scan_enabled);
 553    qemu_put_be32(f, s->translate);
 554    qemu_put_be32(f, s->scancode_set);
 555}
 556
 557static void ps2_mouse_save(QEMUFile* f, void* opaque)
 558{
 559    PS2MouseState *s = (PS2MouseState*)opaque;
 560
 561    ps2_common_save (f, &s->common);
 562    qemu_put_8s(f, &s->mouse_status);
 563    qemu_put_8s(f, &s->mouse_resolution);
 564    qemu_put_8s(f, &s->mouse_sample_rate);
 565    qemu_put_8s(f, &s->mouse_wrap);
 566    qemu_put_8s(f, &s->mouse_type);
 567    qemu_put_8s(f, &s->mouse_detect_state);
 568    qemu_put_be32(f, s->mouse_dx);
 569    qemu_put_be32(f, s->mouse_dy);
 570    qemu_put_be32(f, s->mouse_dz);
 571    qemu_put_8s(f, &s->mouse_buttons);
 572}
 573
 574static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id)
 575{
 576    PS2KbdState *s = (PS2KbdState*)opaque;
 577
 578    if (version_id != 2 && version_id != 3)
 579        return -EINVAL;
 580
 581    ps2_common_load (f, &s->common);
 582    s->scan_enabled=qemu_get_be32(f);
 583    s->translate=qemu_get_be32(f);
 584    if (version_id == 3)
 585        s->scancode_set=qemu_get_be32(f);
 586    else
 587        s->scancode_set=2;
 588    return 0;
 589}
 590
 591static int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id)
 592{
 593    PS2MouseState *s = (PS2MouseState*)opaque;
 594
 595    if (version_id != 2)
 596        return -EINVAL;
 597
 598    ps2_common_load (f, &s->common);
 599    qemu_get_8s(f, &s->mouse_status);
 600    qemu_get_8s(f, &s->mouse_resolution);
 601    qemu_get_8s(f, &s->mouse_sample_rate);
 602    qemu_get_8s(f, &s->mouse_wrap);
 603    qemu_get_8s(f, &s->mouse_type);
 604    qemu_get_8s(f, &s->mouse_detect_state);
 605    s->mouse_dx=qemu_get_be32(f);
 606    s->mouse_dy=qemu_get_be32(f);
 607    s->mouse_dz=qemu_get_be32(f);
 608    qemu_get_8s(f, &s->mouse_buttons);
 609    return 0;
 610}
 611
 612void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
 613{
 614    PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
 615
 616    s->common.update_irq = update_irq;
 617    s->common.update_arg = update_arg;
 618    s->scancode_set = 2;
 619    ps2_kbd_reset(s);
 620    register_savevm("ps2kbd", 0, 3, ps2_kbd_save, ps2_kbd_load, s);
 621    qemu_add_kbd_event_handler(ps2_put_keycode, s);
 622    qemu_register_reset(ps2_kbd_reset, s);
 623    return s;
 624}
 625
 626void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
 627{
 628    PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
 629
 630    s->common.update_irq = update_irq;
 631    s->common.update_arg = update_arg;
 632    ps2_mouse_reset(s);
 633    register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
 634    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
 635    qemu_register_reset(ps2_mouse_reset, s);
 636    return s;
 637}
 638