aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/input/pckbd.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c
index 516ed5a..62a3b29 100644
--- a/hw/input/pckbd.c
+++ b/hw/input/pckbd.c
@@ -136,14 +136,19 @@
#define KBD_MIGR_TIMER_PENDING 0x1
+#define KBD_OBSRC_KBD 0x01
+#define KBD_OBSRC_MOUSE 0x02
+
typedef struct KBDState {
uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
uint8_t status;
uint8_t mode;
uint8_t outport;
uint32_t migration_flags;
+ uint32_t obsrc;
bool outport_present;
bool extended_state;
+ bool extended_state_loaded;
/* Bitmask of devices with data available. */
uint8_t pending;
uint8_t obdata;
@@ -200,6 +205,9 @@ static void kbd_update_irq(KBDState *s)
if (s->pending == KBD_PENDING_AUX) {
s->status |= KBD_STAT_MOUSE_OBF;
s->outport |= KBD_OUT_MOUSE_OBF;
+ s->obsrc = KBD_OBSRC_MOUSE;
+ } else {
+ s->obsrc = KBD_OBSRC_KBD;
}
}
kbd_update_irq_lines(s);
@@ -370,18 +378,17 @@ static uint64_t kbd_read_data(void *opaque, hwaddr addr,
unsigned size)
{
KBDState *s = opaque;
- uint8_t status = s->status;
- if (status & KBD_STAT_OBF) {
+ if (s->status & KBD_STAT_OBF) {
kbd_deassert_irq(s);
- if (status & KBD_STAT_MOUSE_OBF) {
- s->obdata = ps2_read_data(s->mouse);
- } else {
+ if (s->obsrc & KBD_OBSRC_KBD) {
if (s->throttle_timer) {
timer_mod(s->throttle_timer,
qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + 1000);
}
s->obdata = ps2_read_data(s->kbd);
+ } else if (s->obsrc & KBD_OBSRC_MOUSE) {
+ s->obdata = ps2_read_data(s->mouse);
}
}
@@ -498,6 +505,7 @@ static int kbd_extended_state_post_load(void *opaque, int version_id)
if (s->migration_flags & KBD_MIGR_TIMER_PENDING) {
kbd_throttle_timeout(s);
}
+ s->extended_state_loaded = true;
return 0;
}
@@ -516,11 +524,20 @@ static const VMStateDescription vmstate_kbd_extended_state = {
.needed = kbd_extended_state_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT32(migration_flags, KBDState),
+ VMSTATE_UINT32(obsrc, KBDState),
VMSTATE_UINT8(obdata, KBDState),
VMSTATE_END_OF_LIST()
}
};
+static int kbd_pre_load(void *opaque)
+{
+ KBDState *s = opaque;
+
+ s->extended_state_loaded = false;
+ return 0;
+}
+
static int kbd_post_load(void *opaque, int version_id)
{
KBDState *s = opaque;
@@ -528,6 +545,11 @@ static int kbd_post_load(void *opaque, int version_id)
s->outport = kbd_outport_default(s);
}
s->outport_present = false;
+ if (!s->extended_state_loaded) {
+ s->obsrc = s->status & KBD_STAT_OBF ?
+ (s->status & KBD_STAT_MOUSE_OBF ? KBD_OBSRC_MOUSE : KBD_OBSRC_KBD) :
+ 0;
+ }
return 0;
}
@@ -535,6 +557,7 @@ static const VMStateDescription vmstate_kbd = {
.name = "pckbd",
.version_id = 3,
.minimum_version_id = 3,
+ .pre_load = kbd_pre_load,
.post_load = kbd_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT8(write_cmd, KBDState),