~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to hw/ps2.c

  • Committer: ths
  • Date: 2007-06-17 15:32:30 UTC
  • Revision ID: git-v1:ffb04fcf089865952592f1f8855c2848d4514a89
Allow relative paths for the interpreter prefix in linux-user emulation.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2984 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * QEMU PS/2 keyboard/mouse emulation
3
 
 *
 
3
 * 
4
4
 * Copyright (c) 2003 Fabrice Bellard
5
 
 *
 
5
 * 
6
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
 * of this software and associated documentation files (the "Software"), to deal
8
8
 * in the Software without restriction, including without limitation the rights
21
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
22
 * THE SOFTWARE.
23
23
 */
24
 
#include "hw.h"
25
 
#include "ps2.h"
26
 
#include "console.h"
 
24
#include "vl.h"
27
25
 
28
26
/* debug PC keyboard */
29
27
//#define DEBUG_KBD
34
32
/* Keyboard Commands */
35
33
#define KBD_CMD_SET_LEDS        0xED    /* Set keyboard leds */
36
34
#define KBD_CMD_ECHO            0xEE
37
 
#define KBD_CMD_SCANCODE        0xF0    /* Get/set scancode set */
38
35
#define KBD_CMD_GET_ID          0xF2    /* get keyboard ID */
39
36
#define KBD_CMD_SET_RATE        0xF3    /* Set typematic rate */
40
37
#define KBD_CMD_ENABLE          0xF4    /* Enable scanning */
44
41
 
45
42
/* Keyboard Replies */
46
43
#define KBD_REPLY_POR           0xAA    /* Power on reset */
47
 
#define KBD_REPLY_ID            0xAB    /* Keyboard ID */
48
44
#define KBD_REPLY_ACK           0xFA    /* Command ACK */
49
45
#define KBD_REPLY_RESEND        0xFE    /* Command NACK, send the cmd again */
50
46
 
91
87
       conversions we do the translation (if any) in the PS/2 emulation
92
88
       not the keyboard controller.  */
93
89
    int translate;
94
 
    int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
95
90
} PS2KbdState;
96
91
 
97
92
typedef struct {
134
129
    s->update_irq(s->update_arg, 1);
135
130
}
136
131
 
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
 
 */
142
132
static void ps2_put_keycode(void *opaque, int keycode)
143
133
{
144
134
    PS2KbdState *s = opaque;
145
 
 
146
 
    /* XXX: add support for scancode sets 1 and 3 */
147
 
    if (!s->translate && keycode < 0xe0 && s->scancode_set == 2)
 
135
    if (!s->translate && keycode < 0xe0)
148
136
      {
149
137
        if (keycode & 0x80)
150
138
            ps2_queue(&s->common, 0xf0);
158
146
    PS2State *s = (PS2State *)opaque;
159
147
    PS2Queue *q;
160
148
    int val, index;
161
 
 
 
149
    
162
150
    q = &s->queue;
163
151
    if (q->count == 0) {
164
152
        /* NOTE: if no data left, we return the last keyboard one
184
172
static void ps2_reset_keyboard(PS2KbdState *s)
185
173
{
186
174
    s->scan_enabled = 1;
187
 
    s->scancode_set = 2;
188
175
}
189
176
 
190
177
void ps2_write_keyboard(void *opaque, int val)
203
190
            break;
204
191
        case KBD_CMD_GET_ID:
205
192
            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);
 
193
            ps2_queue(&s->common, 0xab);
 
194
            ps2_queue(&s->common, 0x83);
212
195
            break;
213
196
        case KBD_CMD_ECHO:
214
197
            ps2_queue(&s->common, KBD_CMD_ECHO);
217
200
            s->scan_enabled = 1;
218
201
            ps2_queue(&s->common, KBD_REPLY_ACK);
219
202
            break;
220
 
        case KBD_CMD_SCANCODE:
221
203
        case KBD_CMD_SET_LEDS:
222
204
        case KBD_CMD_SET_RATE:
223
205
            s->common.write_cmd = val;
243
225
            break;
244
226
        }
245
227
        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
228
    case KBD_CMD_SET_LEDS:
262
229
        ps2_queue(&s->common, KBD_REPLY_ACK);
263
230
        s->common.write_cmd = -1;
327
294
    s->mouse_dz -= dz1;
328
295
}
329
296
 
330
 
static void ps2_mouse_event(void *opaque,
 
297
static void ps2_mouse_event(void *opaque, 
331
298
                            int dx, int dy, int dz, int buttons_state)
332
299
{
333
300
    PS2MouseState *s = opaque;
344
311
        s->mouse_buttons == buttons_state)
345
312
        return;
346
313
    s->mouse_buttons = buttons_state;
347
 
 
 
314
    
348
315
    if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
349
316
        (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
350
317
        for(;;) {
467
434
                s->mouse_detect_state = 0;
468
435
            break;
469
436
        case 2:
470
 
            if (val == 80)
 
437
            if (val == 80) 
471
438
                s->mouse_type = 3; /* IMPS/2 */
472
439
            s->mouse_detect_state = 0;
473
440
            break;
474
441
        case 3:
475
 
            if (val == 80)
 
442
            if (val == 80) 
476
443
                s->mouse_type = 4; /* IMEX */
477
444
            s->mouse_detect_state = 0;
478
445
            break;
501
468
 
502
469
static void ps2_common_save (QEMUFile *f, PS2State *s)
503
470
{
504
 
    qemu_put_be32 (f, s->write_cmd);
505
 
    qemu_put_be32 (f, s->queue.rptr);
506
 
    qemu_put_be32 (f, s->queue.wptr);
507
 
    qemu_put_be32 (f, s->queue.count);
 
471
    qemu_put_be32s (f, &s->write_cmd);
 
472
    qemu_put_be32s (f, &s->queue.rptr);
 
473
    qemu_put_be32s (f, &s->queue.wptr);
 
474
    qemu_put_be32s (f, &s->queue.count);
508
475
    qemu_put_buffer (f, s->queue.data, sizeof (s->queue.data));
509
476
}
510
477
 
511
478
static void ps2_common_load (QEMUFile *f, PS2State *s)
512
479
{
513
 
    s->write_cmd=qemu_get_be32 (f);
514
 
    s->queue.rptr=qemu_get_be32 (f);
515
 
    s->queue.wptr=qemu_get_be32 (f);
516
 
    s->queue.count=qemu_get_be32 (f);
 
480
    qemu_get_be32s (f, &s->write_cmd);
 
481
    qemu_get_be32s (f, &s->queue.rptr);
 
482
    qemu_get_be32s (f, &s->queue.wptr);
 
483
    qemu_get_be32s (f, &s->queue.count);
517
484
    qemu_get_buffer (f, s->queue.data, sizeof (s->queue.data));
518
485
}
519
486
 
522
489
    PS2KbdState *s = (PS2KbdState*)opaque;
523
490
 
524
491
    ps2_common_save (f, &s->common);
525
 
    qemu_put_be32(f, s->scan_enabled);
526
 
    qemu_put_be32(f, s->translate);
527
 
    qemu_put_be32(f, s->scancode_set);
 
492
    qemu_put_be32s(f, &s->scan_enabled);
 
493
    qemu_put_be32s(f, &s->translate);
528
494
}
529
495
 
530
496
static void ps2_mouse_save(QEMUFile* f, void* opaque)
538
504
    qemu_put_8s(f, &s->mouse_wrap);
539
505
    qemu_put_8s(f, &s->mouse_type);
540
506
    qemu_put_8s(f, &s->mouse_detect_state);
541
 
    qemu_put_be32(f, s->mouse_dx);
542
 
    qemu_put_be32(f, s->mouse_dy);
543
 
    qemu_put_be32(f, s->mouse_dz);
 
507
    qemu_put_be32s(f, &s->mouse_dx);
 
508
    qemu_put_be32s(f, &s->mouse_dy);
 
509
    qemu_put_be32s(f, &s->mouse_dz);
544
510
    qemu_put_8s(f, &s->mouse_buttons);
545
511
}
546
512
 
548
514
{
549
515
    PS2KbdState *s = (PS2KbdState*)opaque;
550
516
 
551
 
    if (version_id != 2 && version_id != 3)
 
517
    if (version_id != 2)
552
518
        return -EINVAL;
553
519
 
554
520
    ps2_common_load (f, &s->common);
555
 
    s->scan_enabled=qemu_get_be32(f);
556
 
    s->translate=qemu_get_be32(f);
557
 
    if (version_id == 3)
558
 
        s->scancode_set=qemu_get_be32(f);
559
 
    else
560
 
        s->scancode_set=2;
 
521
    qemu_get_be32s(f, &s->scan_enabled);
 
522
    qemu_get_be32s(f, &s->translate);
561
523
    return 0;
562
524
}
563
525
 
575
537
    qemu_get_8s(f, &s->mouse_wrap);
576
538
    qemu_get_8s(f, &s->mouse_type);
577
539
    qemu_get_8s(f, &s->mouse_detect_state);
578
 
    s->mouse_dx=qemu_get_be32(f);
579
 
    s->mouse_dy=qemu_get_be32(f);
580
 
    s->mouse_dz=qemu_get_be32(f);
 
540
    qemu_get_be32s(f, &s->mouse_dx);
 
541
    qemu_get_be32s(f, &s->mouse_dy);
 
542
    qemu_get_be32s(f, &s->mouse_dz);
581
543
    qemu_get_8s(f, &s->mouse_buttons);
582
544
    return 0;
583
545
}
588
550
 
589
551
    s->common.update_irq = update_irq;
590
552
    s->common.update_arg = update_arg;
591
 
    s->scancode_set = 2;
592
553
    ps2_reset(&s->common);
593
 
    register_savevm("ps2kbd", 0, 3, ps2_kbd_save, ps2_kbd_load, s);
 
554
    register_savevm("ps2kbd", 0, 2, ps2_kbd_save, ps2_kbd_load, s);
594
555
    qemu_add_kbd_event_handler(ps2_put_keycode, s);
595
556
    qemu_register_reset(ps2_reset, &s->common);
596
557
    return s;