|
|
1.1 root 1: /*
2: * QEMU PS/2 keyboard/mouse emulation
1.1.1.4 root 3: *
1.1 root 4: * Copyright (c) 2003 Fabrice Bellard
1.1.1.4 root 5: *
1.1 root 6: * Permission is hereby granted, free of charge, to any person obtaining a copy
7: * of this software and associated documentation files (the "Software"), to deal
8: * in the Software without restriction, including without limitation the rights
9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10: * copies of the Software, and to permit persons to whom the Software is
11: * furnished to do so, subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22: * THE SOFTWARE.
23: */
1.1.1.4 root 24: #include "hw.h"
25: #include "ps2.h"
26: #include "console.h"
1.1 root 27:
28: /* debug PC keyboard */
29: //#define DEBUG_KBD
30:
31: /* debug PC keyboard : only mouse */
32: //#define DEBUG_MOUSE
33:
34: /* Keyboard Commands */
35: #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
36: #define KBD_CMD_ECHO 0xEE
1.1.1.5 root 37: #define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */
1.1 root 38: #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
39: #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
40: #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
41: #define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
42: #define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
43: #define KBD_CMD_RESET 0xFF /* Reset */
44:
45: /* Keyboard Replies */
46: #define KBD_REPLY_POR 0xAA /* Power on reset */
1.1.1.5 root 47: #define KBD_REPLY_ID 0xAB /* Keyboard ID */
1.1 root 48: #define KBD_REPLY_ACK 0xFA /* Command ACK */
49: #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
50:
51: /* Mouse Commands */
52: #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
53: #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
54: #define AUX_SET_RES 0xE8 /* Set resolution */
55: #define AUX_GET_SCALE 0xE9 /* Get scaling factor */
56: #define AUX_SET_STREAM 0xEA /* Set stream mode */
57: #define AUX_POLL 0xEB /* Poll */
58: #define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
59: #define AUX_SET_WRAP 0xEE /* Set wrap mode */
60: #define AUX_SET_REMOTE 0xF0 /* Set remote mode */
61: #define AUX_GET_TYPE 0xF2 /* Get type */
62: #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
63: #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
64: #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
65: #define AUX_SET_DEFAULT 0xF6
66: #define AUX_RESET 0xFF /* Reset aux device */
67: #define AUX_ACK 0xFA /* Command byte ACK. */
68:
69: #define MOUSE_STATUS_REMOTE 0x40
70: #define MOUSE_STATUS_ENABLED 0x20
71: #define MOUSE_STATUS_SCALE21 0x10
72:
73: #define PS2_QUEUE_SIZE 256
74:
75: typedef struct {
76: uint8_t data[PS2_QUEUE_SIZE];
77: int rptr, wptr, count;
78: } PS2Queue;
79:
80: typedef struct {
81: PS2Queue queue;
82: int32_t write_cmd;
83: void (*update_irq)(void *, int);
84: void *update_arg;
85: } PS2State;
86:
87: typedef struct {
88: PS2State common;
89: int scan_enabled;
1.1.1.2 root 90: /* Qemu uses translated PC scancodes internally. To avoid multiple
91: conversions we do the translation (if any) in the PS/2 emulation
92: not the keyboard controller. */
93: int translate;
1.1.1.5 root 94: int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
1.1.1.10! root 95: int ledstate;
1.1 root 96: } PS2KbdState;
97:
98: typedef struct {
99: PS2State common;
100: uint8_t mouse_status;
101: uint8_t mouse_resolution;
102: uint8_t mouse_sample_rate;
103: uint8_t mouse_wrap;
104: uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
105: uint8_t mouse_detect_state;
106: int mouse_dx; /* current values, needed for 'poll' mode */
107: int mouse_dy;
108: int mouse_dz;
109: uint8_t mouse_buttons;
110: } PS2MouseState;
111:
1.1.1.2 root 112: /* Table to convert from PC scancodes to raw scancodes. */
113: static const unsigned char ps2_raw_keycode[128] = {
1.1.1.9 root 114: 0, 118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13,
115: 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
116: 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
117: 50, 49, 58, 65, 73, 74, 89, 124, 17, 41, 88, 5, 6, 4, 12, 3,
118: 11, 2, 10, 1, 9, 119, 126, 108, 117, 125, 123, 107, 115, 116, 121, 105,
119: 114, 122, 112, 113, 127, 96, 97, 120, 7, 15, 23, 31, 39, 47, 55, 63,
120: 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111,
121: 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110
122: };
123: static const unsigned char ps2_raw_keycode_set3[128] = {
124: 0, 8, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13,
125: 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 17, 28, 27,
126: 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 92, 26, 34, 33, 42,
127: 50, 49, 58, 65, 73, 74, 89, 126, 25, 41, 20, 7, 15, 23, 31, 39,
128: 47, 2, 63, 71, 79, 118, 95, 108, 117, 125, 132, 107, 115, 116, 124, 105,
129: 114, 122, 112, 113, 127, 96, 97, 86, 94, 15, 23, 31, 39, 47, 55, 63,
130: 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111,
131: 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110
1.1.1.2 root 132: };
133:
1.1 root 134: void ps2_queue(void *opaque, int b)
135: {
136: PS2State *s = (PS2State *)opaque;
137: PS2Queue *q = &s->queue;
138:
139: if (q->count >= PS2_QUEUE_SIZE)
140: return;
141: q->data[q->wptr] = b;
142: if (++q->wptr == PS2_QUEUE_SIZE)
143: q->wptr = 0;
144: q->count++;
145: s->update_irq(s->update_arg, 1);
146: }
147:
1.1.1.5 root 148: /*
149: keycode is expressed as follow:
150: bit 7 - 0 key pressed, 1 = key released
151: bits 6-0 - translated scancode set 2
152: */
1.1 root 153: static void ps2_put_keycode(void *opaque, int keycode)
154: {
1.1.1.2 root 155: PS2KbdState *s = opaque;
1.1.1.5 root 156:
1.1.1.9 root 157: /* XXX: add support for scancode set 1 */
158: if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) {
159: if (keycode & 0x80) {
1.1.1.2 root 160: ps2_queue(&s->common, 0xf0);
1.1.1.9 root 161: }
162: if (s->scancode_set == 2) {
163: keycode = ps2_raw_keycode[keycode & 0x7f];
164: } else if (s->scancode_set == 3) {
165: keycode = ps2_raw_keycode_set3[keycode & 0x7f];
166: }
1.1.1.2 root 167: }
1.1 root 168: ps2_queue(&s->common, keycode);
169: }
170:
171: uint32_t ps2_read_data(void *opaque)
172: {
173: PS2State *s = (PS2State *)opaque;
174: PS2Queue *q;
175: int val, index;
1.1.1.4 root 176:
1.1 root 177: q = &s->queue;
178: if (q->count == 0) {
179: /* NOTE: if no data left, we return the last keyboard one
180: (needed for EMM386) */
181: /* XXX: need a timer to do things correctly */
182: index = q->rptr - 1;
183: if (index < 0)
184: index = PS2_QUEUE_SIZE - 1;
185: val = q->data[index];
186: } else {
187: val = q->data[q->rptr];
188: if (++q->rptr == PS2_QUEUE_SIZE)
189: q->rptr = 0;
190: q->count--;
191: /* reading deasserts IRQ */
192: s->update_irq(s->update_arg, 0);
193: /* reassert IRQs if data left */
194: s->update_irq(s->update_arg, q->count != 0);
195: }
196: return val;
197: }
198:
1.1.1.10! root 199: static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
! 200: {
! 201: s->ledstate = ledstate;
! 202: kbd_put_ledstate(ledstate);
! 203: }
! 204:
1.1 root 205: static void ps2_reset_keyboard(PS2KbdState *s)
206: {
207: s->scan_enabled = 1;
1.1.1.5 root 208: s->scancode_set = 2;
1.1.1.10! root 209: ps2_set_ledstate(s, 0);
1.1 root 210: }
211:
212: void ps2_write_keyboard(void *opaque, int val)
213: {
214: PS2KbdState *s = (PS2KbdState *)opaque;
215:
216: switch(s->common.write_cmd) {
217: default:
218: case -1:
219: switch(val) {
220: case 0x00:
221: ps2_queue(&s->common, KBD_REPLY_ACK);
222: break;
223: case 0x05:
224: ps2_queue(&s->common, KBD_REPLY_RESEND);
225: break;
226: case KBD_CMD_GET_ID:
227: ps2_queue(&s->common, KBD_REPLY_ACK);
1.1.1.5 root 228: /* We emulate a MF2 AT keyboard here */
229: ps2_queue(&s->common, KBD_REPLY_ID);
230: if (s->translate)
231: ps2_queue(&s->common, 0x41);
232: else
233: ps2_queue(&s->common, 0x83);
1.1 root 234: break;
235: case KBD_CMD_ECHO:
236: ps2_queue(&s->common, KBD_CMD_ECHO);
237: break;
238: case KBD_CMD_ENABLE:
239: s->scan_enabled = 1;
240: ps2_queue(&s->common, KBD_REPLY_ACK);
241: break;
1.1.1.5 root 242: case KBD_CMD_SCANCODE:
1.1 root 243: case KBD_CMD_SET_LEDS:
244: case KBD_CMD_SET_RATE:
245: s->common.write_cmd = val;
246: ps2_queue(&s->common, KBD_REPLY_ACK);
247: break;
248: case KBD_CMD_RESET_DISABLE:
249: ps2_reset_keyboard(s);
250: s->scan_enabled = 0;
251: ps2_queue(&s->common, KBD_REPLY_ACK);
252: break;
253: case KBD_CMD_RESET_ENABLE:
254: ps2_reset_keyboard(s);
255: s->scan_enabled = 1;
256: ps2_queue(&s->common, KBD_REPLY_ACK);
257: break;
258: case KBD_CMD_RESET:
259: ps2_reset_keyboard(s);
260: ps2_queue(&s->common, KBD_REPLY_ACK);
261: ps2_queue(&s->common, KBD_REPLY_POR);
262: break;
263: default:
264: ps2_queue(&s->common, KBD_REPLY_ACK);
265: break;
266: }
267: break;
1.1.1.5 root 268: case KBD_CMD_SCANCODE:
269: if (val == 0) {
270: if (s->scancode_set == 1)
271: ps2_put_keycode(s, 0x43);
272: else if (s->scancode_set == 2)
273: ps2_put_keycode(s, 0x41);
274: else if (s->scancode_set == 3)
275: ps2_put_keycode(s, 0x3f);
276: } else {
277: if (val >= 1 && val <= 3)
278: s->scancode_set = val;
279: ps2_queue(&s->common, KBD_REPLY_ACK);
280: }
281: s->common.write_cmd = -1;
282: break;
1.1 root 283: case KBD_CMD_SET_LEDS:
1.1.1.10! root 284: ps2_set_ledstate(s, val);
1.1 root 285: ps2_queue(&s->common, KBD_REPLY_ACK);
286: s->common.write_cmd = -1;
287: break;
288: case KBD_CMD_SET_RATE:
289: ps2_queue(&s->common, KBD_REPLY_ACK);
290: s->common.write_cmd = -1;
291: break;
292: }
293: }
294:
1.1.1.2 root 295: /* Set the scancode translation mode.
296: 0 = raw scancodes.
297: 1 = translated scancodes (used by qemu internally). */
298:
299: void ps2_keyboard_set_translation(void *opaque, int mode)
300: {
301: PS2KbdState *s = (PS2KbdState *)opaque;
302: s->translate = mode;
303: }
304:
1.1 root 305: static void ps2_mouse_send_packet(PS2MouseState *s)
306: {
307: unsigned int b;
308: int dx1, dy1, dz1;
309:
310: dx1 = s->mouse_dx;
311: dy1 = s->mouse_dy;
312: dz1 = s->mouse_dz;
313: /* XXX: increase range to 8 bits ? */
314: if (dx1 > 127)
315: dx1 = 127;
316: else if (dx1 < -127)
317: dx1 = -127;
318: if (dy1 > 127)
319: dy1 = 127;
320: else if (dy1 < -127)
321: dy1 = -127;
322: b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
323: ps2_queue(&s->common, b);
324: ps2_queue(&s->common, dx1 & 0xff);
325: ps2_queue(&s->common, dy1 & 0xff);
326: /* extra byte for IMPS/2 or IMEX */
327: switch(s->mouse_type) {
328: default:
329: break;
330: case 3:
331: if (dz1 > 127)
332: dz1 = 127;
333: else if (dz1 < -127)
334: dz1 = -127;
335: ps2_queue(&s->common, dz1 & 0xff);
336: break;
337: case 4:
338: if (dz1 > 7)
339: dz1 = 7;
340: else if (dz1 < -7)
341: dz1 = -7;
342: b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
343: ps2_queue(&s->common, b);
344: break;
345: }
346:
347: /* update deltas */
348: s->mouse_dx -= dx1;
349: s->mouse_dy -= dy1;
350: s->mouse_dz -= dz1;
351: }
352:
1.1.1.4 root 353: static void ps2_mouse_event(void *opaque,
1.1 root 354: int dx, int dy, int dz, int buttons_state)
355: {
356: PS2MouseState *s = opaque;
357:
358: /* check if deltas are recorded when disabled */
359: if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
360: return;
361:
362: s->mouse_dx += dx;
363: s->mouse_dy -= dy;
364: s->mouse_dz += dz;
365: /* XXX: SDL sometimes generates nul events: we delete them */
366: if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
367: s->mouse_buttons == buttons_state)
368: return;
369: s->mouse_buttons = buttons_state;
1.1.1.4 root 370:
1.1 root 371: if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
372: (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
373: for(;;) {
374: /* if not remote, send event. Multiple events are sent if
375: too big deltas */
376: ps2_mouse_send_packet(s);
377: if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
378: break;
379: }
380: }
381: }
382:
1.1.1.4 root 383: void ps2_mouse_fake_event(void *opaque)
384: {
385: ps2_mouse_event(opaque, 1, 0, 0, 0);
386: }
387:
1.1 root 388: void ps2_write_mouse(void *opaque, int val)
389: {
390: PS2MouseState *s = (PS2MouseState *)opaque;
391: #ifdef DEBUG_MOUSE
392: printf("kbd: write mouse 0x%02x\n", val);
393: #endif
394: switch(s->common.write_cmd) {
395: default:
396: case -1:
397: /* mouse command */
398: if (s->mouse_wrap) {
399: if (val == AUX_RESET_WRAP) {
400: s->mouse_wrap = 0;
401: ps2_queue(&s->common, AUX_ACK);
402: return;
403: } else if (val != AUX_RESET) {
404: ps2_queue(&s->common, val);
405: return;
406: }
407: }
408: switch(val) {
409: case AUX_SET_SCALE11:
410: s->mouse_status &= ~MOUSE_STATUS_SCALE21;
411: ps2_queue(&s->common, AUX_ACK);
412: break;
413: case AUX_SET_SCALE21:
414: s->mouse_status |= MOUSE_STATUS_SCALE21;
415: ps2_queue(&s->common, AUX_ACK);
416: break;
417: case AUX_SET_STREAM:
418: s->mouse_status &= ~MOUSE_STATUS_REMOTE;
419: ps2_queue(&s->common, AUX_ACK);
420: break;
421: case AUX_SET_WRAP:
422: s->mouse_wrap = 1;
423: ps2_queue(&s->common, AUX_ACK);
424: break;
425: case AUX_SET_REMOTE:
426: s->mouse_status |= MOUSE_STATUS_REMOTE;
427: ps2_queue(&s->common, AUX_ACK);
428: break;
429: case AUX_GET_TYPE:
430: ps2_queue(&s->common, AUX_ACK);
431: ps2_queue(&s->common, s->mouse_type);
432: break;
433: case AUX_SET_RES:
434: case AUX_SET_SAMPLE:
435: s->common.write_cmd = val;
436: ps2_queue(&s->common, AUX_ACK);
437: break;
438: case AUX_GET_SCALE:
439: ps2_queue(&s->common, AUX_ACK);
440: ps2_queue(&s->common, s->mouse_status);
441: ps2_queue(&s->common, s->mouse_resolution);
442: ps2_queue(&s->common, s->mouse_sample_rate);
443: break;
444: case AUX_POLL:
445: ps2_queue(&s->common, AUX_ACK);
446: ps2_mouse_send_packet(s);
447: break;
448: case AUX_ENABLE_DEV:
449: s->mouse_status |= MOUSE_STATUS_ENABLED;
450: ps2_queue(&s->common, AUX_ACK);
451: break;
452: case AUX_DISABLE_DEV:
453: s->mouse_status &= ~MOUSE_STATUS_ENABLED;
454: ps2_queue(&s->common, AUX_ACK);
455: break;
456: case AUX_SET_DEFAULT:
457: s->mouse_sample_rate = 100;
458: s->mouse_resolution = 2;
459: s->mouse_status = 0;
460: ps2_queue(&s->common, AUX_ACK);
461: break;
462: case AUX_RESET:
463: s->mouse_sample_rate = 100;
464: s->mouse_resolution = 2;
465: s->mouse_status = 0;
466: s->mouse_type = 0;
467: ps2_queue(&s->common, AUX_ACK);
468: ps2_queue(&s->common, 0xaa);
469: ps2_queue(&s->common, s->mouse_type);
470: break;
471: default:
472: break;
473: }
474: break;
475: case AUX_SET_SAMPLE:
476: s->mouse_sample_rate = val;
477: /* detect IMPS/2 or IMEX */
478: switch(s->mouse_detect_state) {
479: default:
480: case 0:
481: if (val == 200)
482: s->mouse_detect_state = 1;
483: break;
484: case 1:
485: if (val == 100)
486: s->mouse_detect_state = 2;
487: else if (val == 200)
488: s->mouse_detect_state = 3;
489: else
490: s->mouse_detect_state = 0;
491: break;
492: case 2:
1.1.1.4 root 493: if (val == 80)
1.1 root 494: s->mouse_type = 3; /* IMPS/2 */
495: s->mouse_detect_state = 0;
496: break;
497: case 3:
1.1.1.4 root 498: if (val == 80)
1.1 root 499: s->mouse_type = 4; /* IMEX */
500: s->mouse_detect_state = 0;
501: break;
502: }
503: ps2_queue(&s->common, AUX_ACK);
504: s->common.write_cmd = -1;
505: break;
506: case AUX_SET_RES:
507: s->mouse_resolution = val;
508: ps2_queue(&s->common, AUX_ACK);
509: s->common.write_cmd = -1;
510: break;
511: }
512: }
513:
1.1.1.6 root 514: static void ps2_common_reset(PS2State *s)
1.1 root 515: {
516: PS2Queue *q;
517: s->write_cmd = -1;
518: q = &s->queue;
519: q->rptr = 0;
520: q->wptr = 0;
521: q->count = 0;
1.1.1.5 root 522: s->update_irq(s->update_arg, 0);
1.1 root 523: }
524:
1.1.1.6 root 525: static void ps2_kbd_reset(void *opaque)
526: {
527: PS2KbdState *s = (PS2KbdState *) opaque;
528:
529: ps2_common_reset(&s->common);
530: s->scan_enabled = 0;
531: s->translate = 0;
532: s->scancode_set = 0;
533: }
534:
535: static void ps2_mouse_reset(void *opaque)
536: {
537: PS2MouseState *s = (PS2MouseState *) opaque;
538:
539: ps2_common_reset(&s->common);
540: s->mouse_status = 0;
541: s->mouse_resolution = 0;
542: s->mouse_sample_rate = 0;
543: s->mouse_wrap = 0;
544: s->mouse_type = 0;
545: s->mouse_detect_state = 0;
546: s->mouse_dx = 0;
547: s->mouse_dy = 0;
548: s->mouse_dz = 0;
549: s->mouse_buttons = 0;
550: }
551:
1.1.1.7 root 552: static const VMStateDescription vmstate_ps2_common = {
553: .name = "PS2 Common State",
554: .version_id = 3,
555: .minimum_version_id = 2,
556: .minimum_version_id_old = 2,
557: .fields = (VMStateField []) {
558: VMSTATE_INT32(write_cmd, PS2State),
559: VMSTATE_INT32(queue.rptr, PS2State),
560: VMSTATE_INT32(queue.wptr, PS2State),
561: VMSTATE_INT32(queue.count, PS2State),
562: VMSTATE_BUFFER(queue.data, PS2State),
563: VMSTATE_END_OF_LIST()
564: }
565: };
1.1 root 566:
1.1.1.10! root 567: static bool ps2_keyboard_ledstate_needed(void *opaque)
! 568: {
! 569: PS2KbdState *s = opaque;
! 570:
! 571: return s->ledstate != 0; /* 0 is default state */
! 572: }
! 573:
! 574: static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
! 575: {
! 576: PS2KbdState *s = opaque;
! 577:
! 578: kbd_put_ledstate(s->ledstate);
! 579: return 0;
! 580: }
! 581:
! 582: static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
! 583: .name = "ps2kbd/ledstate",
! 584: .version_id = 3,
! 585: .minimum_version_id = 2,
! 586: .minimum_version_id_old = 2,
! 587: .post_load = ps2_kbd_ledstate_post_load,
! 588: .fields = (VMStateField []) {
! 589: VMSTATE_INT32(ledstate, PS2KbdState),
! 590: VMSTATE_END_OF_LIST()
! 591: }
! 592: };
! 593:
1.1.1.7 root 594: static int ps2_kbd_post_load(void* opaque, int version_id)
1.1 root 595: {
596: PS2KbdState *s = (PS2KbdState*)opaque;
1.1.1.2 root 597:
1.1.1.7 root 598: if (version_id == 2)
1.1.1.5 root 599: s->scancode_set=2;
1.1 root 600: return 0;
601: }
602:
1.1.1.7 root 603: static const VMStateDescription vmstate_ps2_keyboard = {
604: .name = "ps2kbd",
605: .version_id = 3,
606: .minimum_version_id = 2,
607: .minimum_version_id_old = 2,
608: .post_load = ps2_kbd_post_load,
609: .fields = (VMStateField []) {
610: VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
611: VMSTATE_INT32(scan_enabled, PS2KbdState),
612: VMSTATE_INT32(translate, PS2KbdState),
613: VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
614: VMSTATE_END_OF_LIST()
1.1.1.10! root 615: },
! 616: .subsections = (VMStateSubsection []) {
! 617: {
! 618: .vmsd = &vmstate_ps2_keyboard_ledstate,
! 619: .needed = ps2_keyboard_ledstate_needed,
! 620: }, {
! 621: /* empty */
! 622: }
1.1.1.7 root 623: }
624: };
625:
626: static const VMStateDescription vmstate_ps2_mouse = {
627: .name = "ps2mouse",
628: .version_id = 2,
629: .minimum_version_id = 2,
630: .minimum_version_id_old = 2,
631: .fields = (VMStateField []) {
632: VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
633: VMSTATE_UINT8(mouse_status, PS2MouseState),
634: VMSTATE_UINT8(mouse_resolution, PS2MouseState),
635: VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
636: VMSTATE_UINT8(mouse_wrap, PS2MouseState),
637: VMSTATE_UINT8(mouse_type, PS2MouseState),
638: VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
639: VMSTATE_INT32(mouse_dx, PS2MouseState),
640: VMSTATE_INT32(mouse_dy, PS2MouseState),
641: VMSTATE_INT32(mouse_dz, PS2MouseState),
642: VMSTATE_UINT8(mouse_buttons, PS2MouseState),
643: VMSTATE_END_OF_LIST()
644: }
645: };
1.1 root 646:
647: void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
648: {
1.1.1.10! root 649: PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
1.1 root 650:
651: s->common.update_irq = update_irq;
652: s->common.update_arg = update_arg;
1.1.1.5 root 653: s->scancode_set = 2;
1.1.1.8 root 654: vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
1.1 root 655: qemu_add_kbd_event_handler(ps2_put_keycode, s);
1.1.1.6 root 656: qemu_register_reset(ps2_kbd_reset, s);
1.1 root 657: return s;
658: }
659:
660: void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
661: {
1.1.1.10! root 662: PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
1.1 root 663:
664: s->common.update_irq = update_irq;
665: s->common.update_arg = update_arg;
1.1.1.8 root 666: vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
1.1.1.3 root 667: qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
1.1.1.6 root 668: qemu_register_reset(ps2_mouse_reset, s);
1.1 root 669: return s;
670: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.