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,6 +34,7 @@ | ||
| 34 | /* Keyboard Commands */ | 34 | /* Keyboard Commands */ |
| 35 | #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ | 35 | #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ |
| 36 | #define KBD_CMD_ECHO 0xEE | 36 | #define KBD_CMD_ECHO 0xEE |
| 37 | +#define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */ | ||
| 37 | #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */ | 38 | #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */ |
| 38 | #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ | 39 | #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ |
| 39 | #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ | 40 | #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ |
| @@ -89,6 +90,7 @@ typedef struct { | @@ -89,6 +90,7 @@ typedef struct { | ||
| 89 | conversions we do the translation (if any) in the PS/2 emulation | 90 | conversions we do the translation (if any) in the PS/2 emulation |
| 90 | not the keyboard controller. */ | 91 | not the keyboard controller. */ |
| 91 | int translate; | 92 | int translate; |
| 93 | + int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */ | ||
| 92 | } PS2KbdState; | 94 | } PS2KbdState; |
| 93 | 95 | ||
| 94 | typedef struct { | 96 | typedef struct { |
| @@ -131,10 +133,13 @@ void ps2_queue(void *opaque, int b) | @@ -131,10 +133,13 @@ void ps2_queue(void *opaque, int b) | ||
| 131 | s->update_irq(s->update_arg, 1); | 133 | s->update_irq(s->update_arg, 1); |
| 132 | } | 134 | } |
| 133 | 135 | ||
| 136 | +/* keycode is expressed in scancode set 2 */ | ||
| 134 | static void ps2_put_keycode(void *opaque, int keycode) | 137 | static void ps2_put_keycode(void *opaque, int keycode) |
| 135 | { | 138 | { |
| 136 | PS2KbdState *s = opaque; | 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 | if (keycode & 0x80) | 144 | if (keycode & 0x80) |
| 140 | ps2_queue(&s->common, 0xf0); | 145 | ps2_queue(&s->common, 0xf0); |
| @@ -174,6 +179,7 @@ uint32_t ps2_read_data(void *opaque) | @@ -174,6 +179,7 @@ uint32_t ps2_read_data(void *opaque) | ||
| 174 | static void ps2_reset_keyboard(PS2KbdState *s) | 179 | static void ps2_reset_keyboard(PS2KbdState *s) |
| 175 | { | 180 | { |
| 176 | s->scan_enabled = 1; | 181 | s->scan_enabled = 1; |
| 182 | + s->scancode_set = 2; | ||
| 177 | } | 183 | } |
| 178 | 184 | ||
| 179 | void ps2_write_keyboard(void *opaque, int val) | 185 | void ps2_write_keyboard(void *opaque, int val) |
| @@ -192,8 +198,9 @@ void ps2_write_keyboard(void *opaque, int val) | @@ -192,8 +198,9 @@ void ps2_write_keyboard(void *opaque, int val) | ||
| 192 | break; | 198 | break; |
| 193 | case KBD_CMD_GET_ID: | 199 | case KBD_CMD_GET_ID: |
| 194 | ps2_queue(&s->common, KBD_REPLY_ACK); | 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 | break; | 204 | break; |
| 198 | case KBD_CMD_ECHO: | 205 | case KBD_CMD_ECHO: |
| 199 | ps2_queue(&s->common, KBD_CMD_ECHO); | 206 | ps2_queue(&s->common, KBD_CMD_ECHO); |
| @@ -202,6 +209,7 @@ void ps2_write_keyboard(void *opaque, int val) | @@ -202,6 +209,7 @@ void ps2_write_keyboard(void *opaque, int val) | ||
| 202 | s->scan_enabled = 1; | 209 | s->scan_enabled = 1; |
| 203 | ps2_queue(&s->common, KBD_REPLY_ACK); | 210 | ps2_queue(&s->common, KBD_REPLY_ACK); |
| 204 | break; | 211 | break; |
| 212 | + case KBD_CMD_SCANCODE: | ||
| 205 | case KBD_CMD_SET_LEDS: | 213 | case KBD_CMD_SET_LEDS: |
| 206 | case KBD_CMD_SET_RATE: | 214 | case KBD_CMD_SET_RATE: |
| 207 | s->common.write_cmd = val; | 215 | s->common.write_cmd = val; |
| @@ -227,6 +235,21 @@ void ps2_write_keyboard(void *opaque, int val) | @@ -227,6 +235,21 @@ void ps2_write_keyboard(void *opaque, int val) | ||
| 227 | break; | 235 | break; |
| 228 | } | 236 | } |
| 229 | break; | 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 | case KBD_CMD_SET_LEDS: | 253 | case KBD_CMD_SET_LEDS: |
| 231 | ps2_queue(&s->common, KBD_REPLY_ACK); | 254 | ps2_queue(&s->common, KBD_REPLY_ACK); |
| 232 | s->common.write_cmd = -1; | 255 | s->common.write_cmd = -1; |
| @@ -493,6 +516,7 @@ static void ps2_kbd_save(QEMUFile* f, void* opaque) | @@ -493,6 +516,7 @@ static void ps2_kbd_save(QEMUFile* f, void* opaque) | ||
| 493 | ps2_common_save (f, &s->common); | 516 | ps2_common_save (f, &s->common); |
| 494 | qemu_put_be32(f, s->scan_enabled); | 517 | qemu_put_be32(f, s->scan_enabled); |
| 495 | qemu_put_be32(f, s->translate); | 518 | qemu_put_be32(f, s->translate); |
| 519 | + qemu_put_be32(f, s->scancode_set); | ||
| 496 | } | 520 | } |
| 497 | 521 | ||
| 498 | static void ps2_mouse_save(QEMUFile* f, void* opaque) | 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,12 +540,16 @@ static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id) | ||
| 516 | { | 540 | { |
| 517 | PS2KbdState *s = (PS2KbdState*)opaque; | 541 | PS2KbdState *s = (PS2KbdState*)opaque; |
| 518 | 542 | ||
| 519 | - if (version_id != 2) | 543 | + if (version_id != 2 && version_id != 3) |
| 520 | return -EINVAL; | 544 | return -EINVAL; |
| 521 | 545 | ||
| 522 | ps2_common_load (f, &s->common); | 546 | ps2_common_load (f, &s->common); |
| 523 | s->scan_enabled=qemu_get_be32(f); | 547 | s->scan_enabled=qemu_get_be32(f); |
| 524 | s->translate=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; | ||
| 525 | return 0; | 553 | return 0; |
| 526 | } | 554 | } |
| 527 | 555 | ||
| @@ -552,8 +580,9 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) | @@ -552,8 +580,9 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) | ||
| 552 | 580 | ||
| 553 | s->common.update_irq = update_irq; | 581 | s->common.update_irq = update_irq; |
| 554 | s->common.update_arg = update_arg; | 582 | s->common.update_arg = update_arg; |
| 583 | + s->scancode_set = 2; | ||
| 555 | ps2_reset(&s->common); | 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 | qemu_add_kbd_event_handler(ps2_put_keycode, s); | 586 | qemu_add_kbd_event_handler(ps2_put_keycode, s); |
| 558 | qemu_register_reset(ps2_reset, &s->common); | 587 | qemu_register_reset(ps2_reset, &s->common); |
| 559 | return s; | 588 | return s; |