xref: /openbmc/qemu/hw/input/pckbd.c (revision 32be01575df7cac57c58a34388126ee3d6740842)
1 /*
2  * QEMU PC keyboard emulation
3  *
4  * Copyright (c) 2003 Fabrice Bellard
5  *
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  */
24 
25 #include "qemu/osdep.h"
26 #include "qemu/error-report.h"
27 #include "qemu/log.h"
28 #include "qemu/timer.h"
29 #include "qapi/error.h"
30 #include "hw/isa/isa.h"
31 #include "migration/vmstate.h"
32 #include "hw/acpi/acpi_aml_interface.h"
33 #include "hw/input/ps2.h"
34 #include "hw/irq.h"
35 #include "hw/input/i8042.h"
36 #include "hw/qdev-properties.h"
37 #include "sysemu/reset.h"
38 #include "sysemu/runstate.h"
39 
40 #include "trace.h"
41 
42 /* Keyboard Controller Commands */
43 
44 /* Read mode bits */
45 #define KBD_CCMD_READ_MODE         0x20
46 /* Write mode bits */
47 #define KBD_CCMD_WRITE_MODE        0x60
48 /* Get controller version */
49 #define KBD_CCMD_GET_VERSION       0xA1
50 /* Disable mouse interface */
51 #define KBD_CCMD_MOUSE_DISABLE     0xA7
52 /* Enable mouse interface */
53 #define KBD_CCMD_MOUSE_ENABLE      0xA8
54 /* Mouse interface test */
55 #define KBD_CCMD_TEST_MOUSE        0xA9
56 /* Controller self test */
57 #define KBD_CCMD_SELF_TEST         0xAA
58 /* Keyboard interface test */
59 #define KBD_CCMD_KBD_TEST          0xAB
60 /* Keyboard interface disable */
61 #define KBD_CCMD_KBD_DISABLE       0xAD
62 /* Keyboard interface enable */
63 #define KBD_CCMD_KBD_ENABLE        0xAE
64 /* read input port */
65 #define KBD_CCMD_READ_INPORT       0xC0
66 /* read output port */
67 #define KBD_CCMD_READ_OUTPORT      0xD0
68 /* write output port */
69 #define KBD_CCMD_WRITE_OUTPORT     0xD1
70 #define KBD_CCMD_WRITE_OBUF        0xD2
71 /* Write to output buffer as if initiated by the auxiliary device */
72 #define KBD_CCMD_WRITE_AUX_OBUF    0xD3
73 /* Write the following byte to the mouse */
74 #define KBD_CCMD_WRITE_MOUSE       0xD4
75 /* HP vectra only ? */
76 #define KBD_CCMD_DISABLE_A20       0xDD
77 /* HP vectra only ? */
78 #define KBD_CCMD_ENABLE_A20        0xDF
79 /* Pulse bits 3-0 of the output port P2. */
80 #define KBD_CCMD_PULSE_BITS_3_0    0xF0
81 /* Pulse bit 0 of the output port P2 = CPU reset. */
82 #define KBD_CCMD_RESET             0xFE
83 /* Pulse no bits of the output port P2. */
84 #define KBD_CCMD_NO_OP             0xFF
85 
86 /* Status Register Bits */
87 
88 /* Keyboard output buffer full */
89 #define KBD_STAT_OBF           0x01
90 /* Keyboard input buffer full */
91 #define KBD_STAT_IBF           0x02
92 /* Self test successful */
93 #define KBD_STAT_SELFTEST      0x04
94 /* Last write was a command write (0=data) */
95 #define KBD_STAT_CMD           0x08
96 /* Zero if keyboard locked */
97 #define KBD_STAT_UNLOCKED      0x10
98 /* Mouse output buffer full */
99 #define KBD_STAT_MOUSE_OBF     0x20
100 /* General receive/xmit timeout */
101 #define KBD_STAT_GTO           0x40
102 /* Parity error */
103 #define KBD_STAT_PERR          0x80
104 
105 /* Controller Mode Register Bits */
106 
107 /* Keyboard data generate IRQ1 */
108 #define KBD_MODE_KBD_INT       0x01
109 /* Mouse data generate IRQ12 */
110 #define KBD_MODE_MOUSE_INT     0x02
111 /* The system flag (?) */
112 #define KBD_MODE_SYS           0x04
113 /* The keylock doesn't affect the keyboard if set */
114 #define KBD_MODE_NO_KEYLOCK    0x08
115 /* Disable keyboard interface */
116 #define KBD_MODE_DISABLE_KBD   0x10
117 /* Disable mouse interface */
118 #define KBD_MODE_DISABLE_MOUSE 0x20
119 /* Scan code conversion to PC format */
120 #define KBD_MODE_KCC           0x40
121 #define KBD_MODE_RFU           0x80
122 
123 /* Output Port Bits */
124 #define KBD_OUT_RESET           0x01    /* 1=normal mode, 0=reset */
125 #define KBD_OUT_A20             0x02    /* x86 only */
126 #define KBD_OUT_OBF             0x10    /* Keyboard output buffer full */
127 #define KBD_OUT_MOUSE_OBF       0x20    /* Mouse output buffer full */
128 
129 /*
130  * OSes typically write 0xdd/0xdf to turn the A20 line off and on.
131  * We make the default value of the outport include these four bits,
132  * so that the subsection is rarely necessary.
133  */
134 #define KBD_OUT_ONES            0xcc
135 
136 #define KBD_PENDING_KBD_COMPAT  0x01
137 #define KBD_PENDING_AUX_COMPAT  0x02
138 #define KBD_PENDING_CTRL_KBD    0x04
139 #define KBD_PENDING_CTRL_AUX    0x08
140 #define KBD_PENDING_KBD         KBD_MODE_DISABLE_KBD    /* 0x10 */
141 #define KBD_PENDING_AUX         KBD_MODE_DISABLE_MOUSE  /* 0x20 */
142 
143 #define KBD_MIGR_TIMER_PENDING  0x1
144 
145 #define KBD_OBSRC_KBD           0x01
146 #define KBD_OBSRC_MOUSE         0x02
147 #define KBD_OBSRC_CTRL          0x04
148 
149 typedef struct KBDState {
150     uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
151     uint8_t status;
152     uint8_t mode;
153     uint8_t outport;
154     uint32_t migration_flags;
155     uint32_t obsrc;
156     bool outport_present;
157     bool extended_state;
158     bool extended_state_loaded;
159     /* Bitmask of devices with data available.  */
160     uint8_t pending;
161     uint8_t obdata;
162     uint8_t cbdata;
163     uint8_t pending_tmp;
164     void *kbd;
165     void *mouse;
166     QEMUTimer *throttle_timer;
167 
168     qemu_irq irq_kbd;
169     qemu_irq irq_mouse;
170     qemu_irq a20_out;
171     hwaddr mask;
172 } KBDState;
173 
174 /*
175  * XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be
176  * incorrect, but it avoids having to simulate exact delays
177  */
178 static void kbd_update_irq_lines(KBDState *s)
179 {
180     int irq_kbd_level, irq_mouse_level;
181 
182     irq_kbd_level = 0;
183     irq_mouse_level = 0;
184 
185     if (s->status & KBD_STAT_OBF) {
186         if (s->status & KBD_STAT_MOUSE_OBF) {
187             if (s->mode & KBD_MODE_MOUSE_INT) {
188                 irq_mouse_level = 1;
189             }
190         } else {
191             if ((s->mode & KBD_MODE_KBD_INT) &&
192                 !(s->mode & KBD_MODE_DISABLE_KBD)) {
193                 irq_kbd_level = 1;
194             }
195         }
196     }
197     qemu_set_irq(s->irq_kbd, irq_kbd_level);
198     qemu_set_irq(s->irq_mouse, irq_mouse_level);
199 }
200 
201 static void kbd_deassert_irq(KBDState *s)
202 {
203     s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
204     s->outport &= ~(KBD_OUT_OBF | KBD_OUT_MOUSE_OBF);
205     kbd_update_irq_lines(s);
206 }
207 
208 static uint8_t kbd_pending(KBDState *s)
209 {
210     if (s->extended_state) {
211         return s->pending & (~s->mode | ~(KBD_PENDING_KBD | KBD_PENDING_AUX));
212     } else {
213         return s->pending;
214     }
215 }
216 
217 /* update irq and KBD_STAT_[MOUSE_]OBF */
218 static void kbd_update_irq(KBDState *s)
219 {
220     uint8_t pending = kbd_pending(s);
221 
222     s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
223     s->outport &= ~(KBD_OUT_OBF | KBD_OUT_MOUSE_OBF);
224     if (pending) {
225         s->status |= KBD_STAT_OBF;
226         s->outport |= KBD_OUT_OBF;
227         if (pending & KBD_PENDING_CTRL_KBD) {
228             s->obsrc = KBD_OBSRC_CTRL;
229         } else if (pending & KBD_PENDING_CTRL_AUX) {
230             s->status |= KBD_STAT_MOUSE_OBF;
231             s->outport |= KBD_OUT_MOUSE_OBF;
232             s->obsrc = KBD_OBSRC_CTRL;
233         } else if (pending & KBD_PENDING_KBD) {
234             s->obsrc = KBD_OBSRC_KBD;
235         } else {
236             s->status |= KBD_STAT_MOUSE_OBF;
237             s->outport |= KBD_OUT_MOUSE_OBF;
238             s->obsrc = KBD_OBSRC_MOUSE;
239         }
240     }
241     kbd_update_irq_lines(s);
242 }
243 
244 static void kbd_safe_update_irq(KBDState *s)
245 {
246     /*
247      * with KBD_STAT_OBF set, a call to kbd_read_data() will eventually call
248      * kbd_update_irq()
249      */
250     if (s->status & KBD_STAT_OBF) {
251         return;
252     }
253     /* the throttle timer is pending and will call kbd_update_irq() */
254     if (s->throttle_timer && timer_pending(s->throttle_timer)) {
255         return;
256     }
257     if (kbd_pending(s)) {
258         kbd_update_irq(s);
259     }
260 }
261 
262 static void kbd_update_kbd_irq(void *opaque, int level)
263 {
264     KBDState *s = opaque;
265 
266     if (level) {
267         s->pending |= KBD_PENDING_KBD;
268     } else {
269         s->pending &= ~KBD_PENDING_KBD;
270     }
271     kbd_safe_update_irq(s);
272 }
273 
274 static void kbd_update_aux_irq(void *opaque, int level)
275 {
276     KBDState *s = opaque;
277 
278     if (level) {
279         s->pending |= KBD_PENDING_AUX;
280     } else {
281         s->pending &= ~KBD_PENDING_AUX;
282     }
283     kbd_safe_update_irq(s);
284 }
285 
286 static void kbd_throttle_timeout(void *opaque)
287 {
288     KBDState *s = opaque;
289 
290     if (kbd_pending(s)) {
291         kbd_update_irq(s);
292     }
293 }
294 
295 static uint64_t kbd_read_status(void *opaque, hwaddr addr,
296                                 unsigned size)
297 {
298     KBDState *s = opaque;
299     int val;
300     val = s->status;
301     trace_pckbd_kbd_read_status(val);
302     return val;
303 }
304 
305 static void kbd_queue(KBDState *s, int b, int aux)
306 {
307     if (s->extended_state) {
308         s->cbdata = b;
309         s->pending &= ~KBD_PENDING_CTRL_KBD & ~KBD_PENDING_CTRL_AUX;
310         s->pending |= aux ? KBD_PENDING_CTRL_AUX : KBD_PENDING_CTRL_KBD;
311         kbd_safe_update_irq(s);
312     } else {
313         ps2_queue(aux ? s->mouse : s->kbd, b);
314     }
315 }
316 
317 static uint8_t kbd_dequeue(KBDState *s)
318 {
319     uint8_t b = s->cbdata;
320 
321     s->pending &= ~KBD_PENDING_CTRL_KBD & ~KBD_PENDING_CTRL_AUX;
322     if (kbd_pending(s)) {
323         kbd_update_irq(s);
324     }
325     return b;
326 }
327 
328 static void outport_write(KBDState *s, uint32_t val)
329 {
330     trace_pckbd_outport_write(val);
331     s->outport = val;
332     qemu_set_irq(s->a20_out, (val >> 1) & 1);
333     if (!(val & 1)) {
334         qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
335     }
336 }
337 
338 static void kbd_write_command(void *opaque, hwaddr addr,
339                               uint64_t val, unsigned size)
340 {
341     KBDState *s = opaque;
342 
343     trace_pckbd_kbd_write_command(val);
344 
345     /*
346      * Bits 3-0 of the output port P2 of the keyboard controller may be pulsed
347      * low for approximately 6 micro seconds. Bits 3-0 of the KBD_CCMD_PULSE
348      * command specify the output port bits to be pulsed.
349      * 0: Bit should be pulsed. 1: Bit should not be modified.
350      * The only useful version of this command is pulsing bit 0,
351      * which does a CPU reset.
352      */
353     if ((val & KBD_CCMD_PULSE_BITS_3_0) == KBD_CCMD_PULSE_BITS_3_0) {
354         if (!(val & 1)) {
355             val = KBD_CCMD_RESET;
356         } else {
357             val = KBD_CCMD_NO_OP;
358         }
359     }
360 
361     switch (val) {
362     case KBD_CCMD_READ_MODE:
363         kbd_queue(s, s->mode, 0);
364         break;
365     case KBD_CCMD_WRITE_MODE:
366     case KBD_CCMD_WRITE_OBUF:
367     case KBD_CCMD_WRITE_AUX_OBUF:
368     case KBD_CCMD_WRITE_MOUSE:
369     case KBD_CCMD_WRITE_OUTPORT:
370         s->write_cmd = val;
371         break;
372     case KBD_CCMD_MOUSE_DISABLE:
373         s->mode |= KBD_MODE_DISABLE_MOUSE;
374         break;
375     case KBD_CCMD_MOUSE_ENABLE:
376         s->mode &= ~KBD_MODE_DISABLE_MOUSE;
377         kbd_safe_update_irq(s);
378         break;
379     case KBD_CCMD_TEST_MOUSE:
380         kbd_queue(s, 0x00, 0);
381         break;
382     case KBD_CCMD_SELF_TEST:
383         s->status |= KBD_STAT_SELFTEST;
384         kbd_queue(s, 0x55, 0);
385         break;
386     case KBD_CCMD_KBD_TEST:
387         kbd_queue(s, 0x00, 0);
388         break;
389     case KBD_CCMD_KBD_DISABLE:
390         s->mode |= KBD_MODE_DISABLE_KBD;
391         break;
392     case KBD_CCMD_KBD_ENABLE:
393         s->mode &= ~KBD_MODE_DISABLE_KBD;
394         kbd_safe_update_irq(s);
395         break;
396     case KBD_CCMD_READ_INPORT:
397         kbd_queue(s, 0x80, 0);
398         break;
399     case KBD_CCMD_READ_OUTPORT:
400         kbd_queue(s, s->outport, 0);
401         break;
402     case KBD_CCMD_ENABLE_A20:
403         qemu_irq_raise(s->a20_out);
404         s->outport |= KBD_OUT_A20;
405         break;
406     case KBD_CCMD_DISABLE_A20:
407         qemu_irq_lower(s->a20_out);
408         s->outport &= ~KBD_OUT_A20;
409         break;
410     case KBD_CCMD_RESET:
411         qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
412         break;
413     case KBD_CCMD_NO_OP:
414         /* ignore that */
415         break;
416     default:
417         qemu_log_mask(LOG_GUEST_ERROR,
418                       "unsupported keyboard cmd=0x%02" PRIx64 "\n", val);
419         break;
420     }
421 }
422 
423 static uint64_t kbd_read_data(void *opaque, hwaddr addr,
424                               unsigned size)
425 {
426     KBDState *s = opaque;
427 
428     if (s->status & KBD_STAT_OBF) {
429         kbd_deassert_irq(s);
430         if (s->obsrc & KBD_OBSRC_KBD) {
431             if (s->throttle_timer) {
432                 timer_mod(s->throttle_timer,
433                           qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + 1000);
434             }
435             s->obdata = ps2_read_data(s->kbd);
436         } else if (s->obsrc & KBD_OBSRC_MOUSE) {
437             s->obdata = ps2_read_data(s->mouse);
438         } else if (s->obsrc & KBD_OBSRC_CTRL) {
439             s->obdata = kbd_dequeue(s);
440         }
441     }
442 
443     trace_pckbd_kbd_read_data(s->obdata);
444     return s->obdata;
445 }
446 
447 static void kbd_write_data(void *opaque, hwaddr addr,
448                            uint64_t val, unsigned size)
449 {
450     KBDState *s = opaque;
451 
452     trace_pckbd_kbd_write_data(val);
453 
454     switch (s->write_cmd) {
455     case 0:
456         ps2_write_keyboard(s->kbd, val);
457         /* sending data to the keyboard reenables PS/2 communication */
458         s->mode &= ~KBD_MODE_DISABLE_KBD;
459         kbd_safe_update_irq(s);
460         break;
461     case KBD_CCMD_WRITE_MODE:
462         s->mode = val;
463         ps2_keyboard_set_translation(s->kbd, (s->mode & KBD_MODE_KCC) != 0);
464         /*
465          * a write to the mode byte interrupt enable flags directly updates
466          * the irq lines
467          */
468         kbd_update_irq_lines(s);
469         /*
470          * a write to the mode byte disable interface flags may raise
471          * an irq if there is pending data in the PS/2 queues.
472          */
473         kbd_safe_update_irq(s);
474         break;
475     case KBD_CCMD_WRITE_OBUF:
476         kbd_queue(s, val, 0);
477         break;
478     case KBD_CCMD_WRITE_AUX_OBUF:
479         kbd_queue(s, val, 1);
480         break;
481     case KBD_CCMD_WRITE_OUTPORT:
482         outport_write(s, val);
483         break;
484     case KBD_CCMD_WRITE_MOUSE:
485         ps2_write_mouse(s->mouse, val);
486         /* sending data to the mouse reenables PS/2 communication */
487         s->mode &= ~KBD_MODE_DISABLE_MOUSE;
488         kbd_safe_update_irq(s);
489         break;
490     default:
491         break;
492     }
493     s->write_cmd = 0;
494 }
495 
496 static void kbd_reset(void *opaque)
497 {
498     KBDState *s = opaque;
499 
500     s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;
501     s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
502     s->outport = KBD_OUT_RESET | KBD_OUT_A20 | KBD_OUT_ONES;
503     s->pending = 0;
504     kbd_deassert_irq(s);
505     if (s->throttle_timer) {
506         timer_del(s->throttle_timer);
507     }
508 }
509 
510 static uint8_t kbd_outport_default(KBDState *s)
511 {
512     return KBD_OUT_RESET | KBD_OUT_A20 | KBD_OUT_ONES
513            | (s->status & KBD_STAT_OBF ? KBD_OUT_OBF : 0)
514            | (s->status & KBD_STAT_MOUSE_OBF ? KBD_OUT_MOUSE_OBF : 0);
515 }
516 
517 static int kbd_outport_post_load(void *opaque, int version_id)
518 {
519     KBDState *s = opaque;
520     s->outport_present = true;
521     return 0;
522 }
523 
524 static bool kbd_outport_needed(void *opaque)
525 {
526     KBDState *s = opaque;
527     return s->outport != kbd_outport_default(s);
528 }
529 
530 static const VMStateDescription vmstate_kbd_outport = {
531     .name = "pckbd_outport",
532     .version_id = 1,
533     .minimum_version_id = 1,
534     .post_load = kbd_outport_post_load,
535     .needed = kbd_outport_needed,
536     .fields = (VMStateField[]) {
537         VMSTATE_UINT8(outport, KBDState),
538         VMSTATE_END_OF_LIST()
539     }
540 };
541 
542 static int kbd_extended_state_pre_save(void *opaque)
543 {
544     KBDState *s = opaque;
545 
546     s->migration_flags = 0;
547     if (s->throttle_timer && timer_pending(s->throttle_timer)) {
548         s->migration_flags |= KBD_MIGR_TIMER_PENDING;
549     }
550 
551     return 0;
552 }
553 
554 static int kbd_extended_state_post_load(void *opaque, int version_id)
555 {
556     KBDState *s = opaque;
557 
558     if (s->migration_flags & KBD_MIGR_TIMER_PENDING) {
559         kbd_throttle_timeout(s);
560     }
561     s->extended_state_loaded = true;
562 
563     return 0;
564 }
565 
566 static bool kbd_extended_state_needed(void *opaque)
567 {
568     KBDState *s = opaque;
569 
570     return s->extended_state;
571 }
572 
573 static const VMStateDescription vmstate_kbd_extended_state = {
574     .name = "pckbd/extended_state",
575     .post_load = kbd_extended_state_post_load,
576     .pre_save = kbd_extended_state_pre_save,
577     .needed = kbd_extended_state_needed,
578     .fields = (VMStateField[]) {
579         VMSTATE_UINT32(migration_flags, KBDState),
580         VMSTATE_UINT32(obsrc, KBDState),
581         VMSTATE_UINT8(obdata, KBDState),
582         VMSTATE_UINT8(cbdata, KBDState),
583         VMSTATE_END_OF_LIST()
584     }
585 };
586 
587 static int kbd_pre_save(void *opaque)
588 {
589     KBDState *s = opaque;
590 
591     if (s->extended_state) {
592         s->pending_tmp = s->pending;
593     } else {
594         s->pending_tmp = 0;
595         if (s->pending & KBD_PENDING_KBD) {
596             s->pending_tmp |= KBD_PENDING_KBD_COMPAT;
597         }
598         if (s->pending & KBD_PENDING_AUX) {
599             s->pending_tmp |= KBD_PENDING_AUX_COMPAT;
600         }
601     }
602     return 0;
603 }
604 
605 static int kbd_pre_load(void *opaque)
606 {
607     KBDState *s = opaque;
608 
609     s->outport_present = false;
610     s->extended_state_loaded = false;
611     return 0;
612 }
613 
614 static int kbd_post_load(void *opaque, int version_id)
615 {
616     KBDState *s = opaque;
617     if (!s->outport_present) {
618         s->outport = kbd_outport_default(s);
619     }
620     s->pending = s->pending_tmp;
621     if (!s->extended_state_loaded) {
622         s->obsrc = s->status & KBD_STAT_OBF ?
623             (s->status & KBD_STAT_MOUSE_OBF ? KBD_OBSRC_MOUSE : KBD_OBSRC_KBD) :
624             0;
625         if (s->pending & KBD_PENDING_KBD_COMPAT) {
626             s->pending |= KBD_PENDING_KBD;
627         }
628         if (s->pending & KBD_PENDING_AUX_COMPAT) {
629             s->pending |= KBD_PENDING_AUX;
630         }
631     }
632     /* clear all unused flags */
633     s->pending &= KBD_PENDING_CTRL_KBD | KBD_PENDING_CTRL_AUX |
634                   KBD_PENDING_KBD | KBD_PENDING_AUX;
635     return 0;
636 }
637 
638 static const VMStateDescription vmstate_kbd = {
639     .name = "pckbd",
640     .version_id = 3,
641     .minimum_version_id = 3,
642     .pre_load = kbd_pre_load,
643     .post_load = kbd_post_load,
644     .pre_save = kbd_pre_save,
645     .fields = (VMStateField[]) {
646         VMSTATE_UINT8(write_cmd, KBDState),
647         VMSTATE_UINT8(status, KBDState),
648         VMSTATE_UINT8(mode, KBDState),
649         VMSTATE_UINT8(pending_tmp, KBDState),
650         VMSTATE_END_OF_LIST()
651     },
652     .subsections = (const VMStateDescription * []) {
653         &vmstate_kbd_outport,
654         &vmstate_kbd_extended_state,
655         NULL
656     }
657 };
658 
659 /* Memory mapped interface */
660 static uint64_t kbd_mm_readfn(void *opaque, hwaddr addr, unsigned size)
661 {
662     KBDState *s = opaque;
663 
664     if (addr & s->mask) {
665         return kbd_read_status(s, 0, 1) & 0xff;
666     } else {
667         return kbd_read_data(s, 0, 1) & 0xff;
668     }
669 }
670 
671 static void kbd_mm_writefn(void *opaque, hwaddr addr,
672                            uint64_t value, unsigned size)
673 {
674     KBDState *s = opaque;
675 
676     if (addr & s->mask) {
677         kbd_write_command(s, 0, value & 0xff, 1);
678     } else {
679         kbd_write_data(s, 0, value & 0xff, 1);
680     }
681 }
682 
683 
684 static const MemoryRegionOps i8042_mmio_ops = {
685     .read = kbd_mm_readfn,
686     .write = kbd_mm_writefn,
687     .valid.min_access_size = 1,
688     .valid.max_access_size = 4,
689     .endianness = DEVICE_NATIVE_ENDIAN,
690 };
691 
692 void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
693                    MemoryRegion *region, ram_addr_t size,
694                    hwaddr mask)
695 {
696     KBDState *s = g_new0(KBDState, 1);
697 
698     s->irq_kbd = kbd_irq;
699     s->irq_mouse = mouse_irq;
700     s->mask = mask;
701 
702     s->extended_state = true;
703 
704     vmstate_register(NULL, 0, &vmstate_kbd, s);
705 
706     memory_region_init_io(region, NULL, &i8042_mmio_ops, s, "i8042", size);
707 
708     s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
709     s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
710     qemu_register_reset(kbd_reset, s);
711 }
712 
713 struct ISAKBDState {
714     ISADevice parent_obj;
715 
716     KBDState kbd;
717     bool kbd_throttle;
718     MemoryRegion io[2];
719     uint8_t kbd_irq;
720     uint8_t mouse_irq;
721 };
722 
723 void i8042_isa_mouse_fake_event(ISAKBDState *isa)
724 {
725     KBDState *s = &isa->kbd;
726 
727     ps2_mouse_fake_event(s->mouse);
728 }
729 
730 void i8042_setup_a20_line(ISADevice *dev, qemu_irq a20_out)
731 {
732     qdev_connect_gpio_out_named(DEVICE(dev), I8042_A20_LINE, 0, a20_out);
733 }
734 
735 static const VMStateDescription vmstate_kbd_isa = {
736     .name = "pckbd",
737     .version_id = 3,
738     .minimum_version_id = 3,
739     .fields = (VMStateField[]) {
740         VMSTATE_STRUCT(kbd, ISAKBDState, 0, vmstate_kbd, KBDState),
741         VMSTATE_END_OF_LIST()
742     }
743 };
744 
745 static const MemoryRegionOps i8042_data_ops = {
746     .read = kbd_read_data,
747     .write = kbd_write_data,
748     .impl = {
749         .min_access_size = 1,
750         .max_access_size = 1,
751     },
752     .endianness = DEVICE_LITTLE_ENDIAN,
753 };
754 
755 static const MemoryRegionOps i8042_cmd_ops = {
756     .read = kbd_read_status,
757     .write = kbd_write_command,
758     .impl = {
759         .min_access_size = 1,
760         .max_access_size = 1,
761     },
762     .endianness = DEVICE_LITTLE_ENDIAN,
763 };
764 
765 static void i8042_initfn(Object *obj)
766 {
767     ISAKBDState *isa_s = I8042(obj);
768     KBDState *s = &isa_s->kbd;
769 
770     memory_region_init_io(isa_s->io + 0, obj, &i8042_data_ops, s,
771                           "i8042-data", 1);
772     memory_region_init_io(isa_s->io + 1, obj, &i8042_cmd_ops, s,
773                           "i8042-cmd", 1);
774 
775     qdev_init_gpio_out_named(DEVICE(obj), &s->a20_out, I8042_A20_LINE, 1);
776 }
777 
778 static void i8042_realizefn(DeviceState *dev, Error **errp)
779 {
780     ISADevice *isadev = ISA_DEVICE(dev);
781     ISAKBDState *isa_s = I8042(dev);
782     KBDState *s = &isa_s->kbd;
783 
784     if (isa_s->kbd_irq >= ISA_NUM_IRQS) {
785         error_setg(errp, "Maximum value for \"kbd-irq\" is: %u",
786                    ISA_NUM_IRQS - 1);
787         return;
788     }
789 
790     if (isa_s->mouse_irq >= ISA_NUM_IRQS) {
791         error_setg(errp, "Maximum value for \"mouse-irq\" is: %u",
792                    ISA_NUM_IRQS - 1);
793         return;
794     }
795 
796     s->irq_kbd = isa_get_irq(isadev, isa_s->kbd_irq);
797     s->irq_mouse = isa_get_irq(isadev, isa_s->mouse_irq);
798 
799     isa_register_ioport(isadev, isa_s->io + 0, 0x60);
800     isa_register_ioport(isadev, isa_s->io + 1, 0x64);
801 
802     s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
803     s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
804     if (isa_s->kbd_throttle && !isa_s->kbd.extended_state) {
805         warn_report(TYPE_I8042 ": can't enable kbd-throttle without"
806                     " extended-state, disabling kbd-throttle");
807     } else if (isa_s->kbd_throttle) {
808         s->throttle_timer = timer_new_us(QEMU_CLOCK_VIRTUAL,
809                                          kbd_throttle_timeout, s);
810     }
811     qemu_register_reset(kbd_reset, s);
812 }
813 
814 static void i8042_build_aml(AcpiDevAmlIf *adev, Aml *scope)
815 {
816     ISAKBDState *isa_s = I8042(adev);
817     Aml *kbd;
818     Aml *mou;
819     Aml *crs;
820 
821     crs = aml_resource_template();
822     aml_append(crs, aml_io(AML_DECODE16, 0x0060, 0x0060, 0x01, 0x01));
823     aml_append(crs, aml_io(AML_DECODE16, 0x0064, 0x0064, 0x01, 0x01));
824     aml_append(crs, aml_irq_no_flags(isa_s->kbd_irq));
825 
826     kbd = aml_device("KBD");
827     aml_append(kbd, aml_name_decl("_HID", aml_eisaid("PNP0303")));
828     aml_append(kbd, aml_name_decl("_STA", aml_int(0xf)));
829     aml_append(kbd, aml_name_decl("_CRS", crs));
830 
831     crs = aml_resource_template();
832     aml_append(crs, aml_irq_no_flags(isa_s->mouse_irq));
833 
834     mou = aml_device("MOU");
835     aml_append(mou, aml_name_decl("_HID", aml_eisaid("PNP0F13")));
836     aml_append(mou, aml_name_decl("_STA", aml_int(0xf)));
837     aml_append(mou, aml_name_decl("_CRS", crs));
838 
839     aml_append(scope, kbd);
840     aml_append(scope, mou);
841 }
842 
843 static Property i8042_properties[] = {
844     DEFINE_PROP_BOOL("extended-state", ISAKBDState, kbd.extended_state, true),
845     DEFINE_PROP_BOOL("kbd-throttle", ISAKBDState, kbd_throttle, false),
846     DEFINE_PROP_UINT8("kbd-irq", ISAKBDState, kbd_irq, 1),
847     DEFINE_PROP_UINT8("mouse-irq", ISAKBDState, mouse_irq, 12),
848     DEFINE_PROP_END_OF_LIST(),
849 };
850 
851 static void i8042_class_initfn(ObjectClass *klass, void *data)
852 {
853     DeviceClass *dc = DEVICE_CLASS(klass);
854     AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
855 
856     device_class_set_props(dc, i8042_properties);
857     dc->realize = i8042_realizefn;
858     dc->vmsd = &vmstate_kbd_isa;
859     adevc->build_dev_aml = i8042_build_aml;
860     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
861 }
862 
863 static const TypeInfo i8042_info = {
864     .name          = TYPE_I8042,
865     .parent        = TYPE_ISA_DEVICE,
866     .instance_size = sizeof(ISAKBDState),
867     .instance_init = i8042_initfn,
868     .class_init    = i8042_class_initfn,
869     .interfaces = (InterfaceInfo[]) {
870         { TYPE_ACPI_DEV_AML_IF },
871         { },
872     },
873 };
874 
875 static void i8042_register_types(void)
876 {
877     type_register_static(&i8042_info);
878 }
879 
880 type_init(i8042_register_types)
881