Revision e7d93956 hw/ps2.c

b/hw/ps2.c
34 34
/* Keyboard Commands */
35 35
#define KBD_CMD_SET_LEDS	0xED	/* Set keyboard leds */
36 36
#define KBD_CMD_ECHO     	0xEE
37
#define KBD_CMD_SCANCODE	0xF0	/* Get/set scancode set */
37 38
#define KBD_CMD_GET_ID 	        0xF2	/* get keyboard ID */
38 39
#define KBD_CMD_SET_RATE	0xF3	/* Set typematic rate */
39 40
#define KBD_CMD_ENABLE		0xF4	/* Enable scanning */
......
89 90
       conversions we do the translation (if any) in the PS/2 emulation
90 91
       not the keyboard controller.  */
91 92
    int translate;
93
    int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
92 94
} PS2KbdState;
93 95

  
94 96
typedef struct {
......
131 133
    s->update_irq(s->update_arg, 1);
132 134
}
133 135

  
136
/* keycode is expressed in scancode set 2 */
134 137
static void ps2_put_keycode(void *opaque, int keycode)
135 138
{
136 139
    PS2KbdState *s = opaque;
137
    if (!s->translate && keycode < 0xe0)
140

  
141
    /* XXX: add support for scancode sets 1 and 3 */
142
    if (!s->translate && keycode < 0xe0 && s->scancode_set == 2)
138 143
      {
139 144
        if (keycode & 0x80)
140 145
            ps2_queue(&s->common, 0xf0);
......
174 179
static void ps2_reset_keyboard(PS2KbdState *s)
175 180
{
176 181
    s->scan_enabled = 1;
182
    s->scancode_set = 2;
177 183
}
178 184

  
179 185
void ps2_write_keyboard(void *opaque, int val)
......
192 198
            break;
193 199
        case KBD_CMD_GET_ID:
194 200
            ps2_queue(&s->common, KBD_REPLY_ACK);
195
            ps2_queue(&s->common, 0xab);
196
            ps2_queue(&s->common, 0x83);
201
            /* We emulate a MF2 AT keyboard here */
202
            ps2_put_keycode(s, 0xab);
203
            ps2_put_keycode(s, 0x83);
197 204
            break;
198 205
        case KBD_CMD_ECHO:
199 206
            ps2_queue(&s->common, KBD_CMD_ECHO);
......
202 209
            s->scan_enabled = 1;
203 210
            ps2_queue(&s->common, KBD_REPLY_ACK);
204 211
            break;
212
        case KBD_CMD_SCANCODE:
205 213
        case KBD_CMD_SET_LEDS:
206 214
        case KBD_CMD_SET_RATE:
207 215
            s->common.write_cmd = val;
......
227 235
            break;
228 236
        }
229 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;
230 253
    case KBD_CMD_SET_LEDS:
231 254
        ps2_queue(&s->common, KBD_REPLY_ACK);
232 255
        s->common.write_cmd = -1;
......
493 516
    ps2_common_save (f, &s->common);
494 517
    qemu_put_be32(f, s->scan_enabled);
495 518
    qemu_put_be32(f, s->translate);
519
    qemu_put_be32(f, s->scancode_set);
496 520
}
497 521

  
498 522
static void ps2_mouse_save(QEMUFile* f, void* opaque)
......
516 540
{
517 541
    PS2KbdState *s = (PS2KbdState*)opaque;
518 542

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

  
522 546
    ps2_common_load (f, &s->common);
523 547
    s->scan_enabled=qemu_get_be32(f);
524 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;
525 553
    return 0;
526 554
}
527 555

  
......
552 580

  
553 581
    s->common.update_irq = update_irq;
554 582
    s->common.update_arg = update_arg;
583
    s->scancode_set = 2;
555 584
    ps2_reset(&s->common);
556
    register_savevm("ps2kbd", 0, 2, ps2_kbd_save, ps2_kbd_load, s);
585
    register_savevm("ps2kbd", 0, 3, ps2_kbd_save, ps2_kbd_load, s);
557 586
    qemu_add_kbd_event_handler(ps2_put_keycode, s);
558 587
    qemu_register_reset(ps2_reset, &s->common);
559 588
    return s;

Also available in: Unified diff