Commit e7d93956508d86838d508345867ee8d2fe587459
1 parent
cf7a2fe2
Add KBD_CMD_SCANCODE command.
(Hervé Poussineau) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4082 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
34 additions
and
5 deletions
hw/ps2.c
| ... | ... | @@ -34,6 +34,7 @@ |
| 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,6 +90,7 @@ typedef struct { |
| 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,10 +133,13 @@ void ps2_queue(void *opaque, int b) |
| 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,6 +179,7 @@ uint32_t ps2_read_data(void *opaque) |
| 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,8 +198,9 @@ 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,6 +209,7 @@ void ps2_write_keyboard(void *opaque, int val) |
| 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,6 +235,21 @@ void ps2_write_keyboard(void *opaque, int 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,6 +516,7 @@ static void ps2_kbd_save(QEMUFile* f, void* opaque) |
| 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,12 +540,16 @@ static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id) |
| 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,8 +580,9 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) |
| 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; | ... | ... |