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; | ... | ... |