ps2: QOMify PS2KbdState
Make PS2KbdState into a new PS2_KBD_DEVICE QOM type which inherits from the abstract PS2_DEVICE type. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Acked-by: Helge Deller <deller@gmx.de> Message-Id: <20220624134109.881989-4-mark.cave-ayland@ilande.co.uk>
This commit is contained in:
parent
64bbdd138a
commit
8f84e53cd0
104
hw/input/ps2.c
104
hw/input/ps2.c
@ -31,6 +31,7 @@
|
|||||||
#include "ui/input.h"
|
#include "ui/input.h"
|
||||||
#include "sysemu/reset.h"
|
#include "sysemu/reset.h"
|
||||||
#include "sysemu/runstate.h"
|
#include "sysemu/runstate.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
@ -108,15 +109,19 @@ struct PS2State {
|
|||||||
#define TYPE_PS2_DEVICE "ps2-device"
|
#define TYPE_PS2_DEVICE "ps2-device"
|
||||||
OBJECT_DECLARE_SIMPLE_TYPE(PS2State, PS2_DEVICE)
|
OBJECT_DECLARE_SIMPLE_TYPE(PS2State, PS2_DEVICE)
|
||||||
|
|
||||||
typedef struct {
|
struct PS2KbdState {
|
||||||
PS2State common;
|
PS2State parent_obj;
|
||||||
|
|
||||||
int scan_enabled;
|
int scan_enabled;
|
||||||
int translate;
|
int translate;
|
||||||
int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
|
int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
|
||||||
int ledstate;
|
int ledstate;
|
||||||
bool need_high_bit;
|
bool need_high_bit;
|
||||||
unsigned int modifiers; /* bitmask of MOD_* constants above */
|
unsigned int modifiers; /* bitmask of MOD_* constants above */
|
||||||
} PS2KbdState;
|
};
|
||||||
|
|
||||||
|
#define TYPE_PS2_KBD_DEVICE "ps2-kbd"
|
||||||
|
OBJECT_DECLARE_SIMPLE_TYPE(PS2KbdState, PS2_KBD_DEVICE)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PS2State common;
|
PS2State common;
|
||||||
@ -330,6 +335,7 @@ static void ps2_cqueue_reset(PS2State *s)
|
|||||||
static void ps2_put_keycode(void *opaque, int keycode)
|
static void ps2_put_keycode(void *opaque, int keycode)
|
||||||
{
|
{
|
||||||
PS2KbdState *s = opaque;
|
PS2KbdState *s = opaque;
|
||||||
|
PS2State *ps = PS2_DEVICE(s);
|
||||||
|
|
||||||
trace_ps2_put_keycode(opaque, keycode);
|
trace_ps2_put_keycode(opaque, keycode);
|
||||||
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
|
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
|
||||||
@ -338,13 +344,13 @@ static void ps2_put_keycode(void *opaque, int keycode)
|
|||||||
if (keycode == 0xf0) {
|
if (keycode == 0xf0) {
|
||||||
s->need_high_bit = true;
|
s->need_high_bit = true;
|
||||||
} else if (s->need_high_bit) {
|
} else if (s->need_high_bit) {
|
||||||
ps2_queue(&s->common, translate_table[keycode] | 0x80);
|
ps2_queue(ps, translate_table[keycode] | 0x80);
|
||||||
s->need_high_bit = false;
|
s->need_high_bit = false;
|
||||||
} else {
|
} else {
|
||||||
ps2_queue(&s->common, translate_table[keycode]);
|
ps2_queue(ps, translate_table[keycode]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ps2_queue(&s->common, keycode);
|
ps2_queue(ps, keycode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,96 +623,99 @@ static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
|
|||||||
|
|
||||||
static void ps2_reset_keyboard(PS2KbdState *s)
|
static void ps2_reset_keyboard(PS2KbdState *s)
|
||||||
{
|
{
|
||||||
|
PS2State *ps2 = PS2_DEVICE(s);
|
||||||
|
|
||||||
trace_ps2_reset_keyboard(s);
|
trace_ps2_reset_keyboard(s);
|
||||||
s->scan_enabled = 1;
|
s->scan_enabled = 1;
|
||||||
s->scancode_set = 2;
|
s->scancode_set = 2;
|
||||||
ps2_reset_queue(&s->common);
|
ps2_reset_queue(ps2);
|
||||||
ps2_set_ledstate(s, 0);
|
ps2_set_ledstate(s, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ps2_write_keyboard(void *opaque, int val)
|
void ps2_write_keyboard(void *opaque, int val)
|
||||||
{
|
{
|
||||||
PS2KbdState *s = (PS2KbdState *)opaque;
|
PS2KbdState *s = (PS2KbdState *)opaque;
|
||||||
|
PS2State *ps2 = PS2_DEVICE(s);
|
||||||
|
|
||||||
trace_ps2_write_keyboard(opaque, val);
|
trace_ps2_write_keyboard(opaque, val);
|
||||||
ps2_cqueue_reset(&s->common);
|
ps2_cqueue_reset(ps2);
|
||||||
switch (s->common.write_cmd) {
|
switch (ps2->write_cmd) {
|
||||||
default:
|
default:
|
||||||
case -1:
|
case -1:
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
|
ps2_cqueue_1(ps2, KBD_REPLY_ACK);
|
||||||
break;
|
break;
|
||||||
case 0x05:
|
case 0x05:
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_RESEND);
|
ps2_cqueue_1(ps2, KBD_REPLY_RESEND);
|
||||||
break;
|
break;
|
||||||
case KBD_CMD_GET_ID:
|
case KBD_CMD_GET_ID:
|
||||||
/* We emulate a MF2 AT keyboard here */
|
/* We emulate a MF2 AT keyboard here */
|
||||||
ps2_cqueue_3(&s->common, KBD_REPLY_ACK, KBD_REPLY_ID,
|
ps2_cqueue_3(ps2, KBD_REPLY_ACK, KBD_REPLY_ID,
|
||||||
s->translate ? 0x41 : 0x83);
|
s->translate ? 0x41 : 0x83);
|
||||||
break;
|
break;
|
||||||
case KBD_CMD_ECHO:
|
case KBD_CMD_ECHO:
|
||||||
ps2_cqueue_1(&s->common, KBD_CMD_ECHO);
|
ps2_cqueue_1(ps2, KBD_CMD_ECHO);
|
||||||
break;
|
break;
|
||||||
case KBD_CMD_ENABLE:
|
case KBD_CMD_ENABLE:
|
||||||
s->scan_enabled = 1;
|
s->scan_enabled = 1;
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
|
ps2_cqueue_1(ps2, KBD_REPLY_ACK);
|
||||||
break;
|
break;
|
||||||
case KBD_CMD_SCANCODE:
|
case KBD_CMD_SCANCODE:
|
||||||
case KBD_CMD_SET_LEDS:
|
case KBD_CMD_SET_LEDS:
|
||||||
case KBD_CMD_SET_RATE:
|
case KBD_CMD_SET_RATE:
|
||||||
case KBD_CMD_SET_MAKE_BREAK:
|
case KBD_CMD_SET_MAKE_BREAK:
|
||||||
s->common.write_cmd = val;
|
ps2->write_cmd = val;
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
|
ps2_cqueue_1(ps2, KBD_REPLY_ACK);
|
||||||
break;
|
break;
|
||||||
case KBD_CMD_RESET_DISABLE:
|
case KBD_CMD_RESET_DISABLE:
|
||||||
ps2_reset_keyboard(s);
|
ps2_reset_keyboard(s);
|
||||||
s->scan_enabled = 0;
|
s->scan_enabled = 0;
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
|
ps2_cqueue_1(ps2, KBD_REPLY_ACK);
|
||||||
break;
|
break;
|
||||||
case KBD_CMD_RESET_ENABLE:
|
case KBD_CMD_RESET_ENABLE:
|
||||||
ps2_reset_keyboard(s);
|
ps2_reset_keyboard(s);
|
||||||
s->scan_enabled = 1;
|
s->scan_enabled = 1;
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
|
ps2_cqueue_1(ps2, KBD_REPLY_ACK);
|
||||||
break;
|
break;
|
||||||
case KBD_CMD_RESET:
|
case KBD_CMD_RESET:
|
||||||
ps2_reset_keyboard(s);
|
ps2_reset_keyboard(s);
|
||||||
ps2_cqueue_2(&s->common,
|
ps2_cqueue_2(ps2,
|
||||||
KBD_REPLY_ACK,
|
KBD_REPLY_ACK,
|
||||||
KBD_REPLY_POR);
|
KBD_REPLY_POR);
|
||||||
break;
|
break;
|
||||||
case KBD_CMD_SET_TYPEMATIC:
|
case KBD_CMD_SET_TYPEMATIC:
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
|
ps2_cqueue_1(ps2, KBD_REPLY_ACK);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_RESEND);
|
ps2_cqueue_1(ps2, KBD_REPLY_RESEND);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KBD_CMD_SET_MAKE_BREAK:
|
case KBD_CMD_SET_MAKE_BREAK:
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
|
ps2_cqueue_1(ps2, KBD_REPLY_ACK);
|
||||||
s->common.write_cmd = -1;
|
ps2->write_cmd = -1;
|
||||||
break;
|
break;
|
||||||
case KBD_CMD_SCANCODE:
|
case KBD_CMD_SCANCODE:
|
||||||
if (val == 0) {
|
if (val == 0) {
|
||||||
ps2_cqueue_2(&s->common, KBD_REPLY_ACK, s->translate ?
|
ps2_cqueue_2(ps2, KBD_REPLY_ACK, s->translate ?
|
||||||
translate_table[s->scancode_set] : s->scancode_set);
|
translate_table[s->scancode_set] : s->scancode_set);
|
||||||
} else if (val >= 1 && val <= 3) {
|
} else if (val >= 1 && val <= 3) {
|
||||||
s->scancode_set = val;
|
s->scancode_set = val;
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
|
ps2_cqueue_1(ps2, KBD_REPLY_ACK);
|
||||||
} else {
|
} else {
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_RESEND);
|
ps2_cqueue_1(ps2, KBD_REPLY_RESEND);
|
||||||
}
|
}
|
||||||
s->common.write_cmd = -1;
|
ps2->write_cmd = -1;
|
||||||
break;
|
break;
|
||||||
case KBD_CMD_SET_LEDS:
|
case KBD_CMD_SET_LEDS:
|
||||||
ps2_set_ledstate(s, val);
|
ps2_set_ledstate(s, val);
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
|
ps2_cqueue_1(ps2, KBD_REPLY_ACK);
|
||||||
s->common.write_cmd = -1;
|
ps2->write_cmd = -1;
|
||||||
break;
|
break;
|
||||||
case KBD_CMD_SET_RATE:
|
case KBD_CMD_SET_RATE:
|
||||||
ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
|
ps2_cqueue_1(ps2, KBD_REPLY_ACK);
|
||||||
s->common.write_cmd = -1;
|
ps2->write_cmd = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1075,9 +1084,10 @@ static void ps2_common_post_load(PS2State *s)
|
|||||||
static void ps2_kbd_reset(void *opaque)
|
static void ps2_kbd_reset(void *opaque)
|
||||||
{
|
{
|
||||||
PS2KbdState *s = (PS2KbdState *) opaque;
|
PS2KbdState *s = (PS2KbdState *) opaque;
|
||||||
|
PS2State *ps2 = PS2_DEVICE(s);
|
||||||
|
|
||||||
trace_ps2_kbd_reset(opaque);
|
trace_ps2_kbd_reset(opaque);
|
||||||
ps2_common_reset(&s->common);
|
ps2_common_reset(ps2);
|
||||||
s->scan_enabled = 1;
|
s->scan_enabled = 1;
|
||||||
s->translate = 0;
|
s->translate = 0;
|
||||||
s->scancode_set = 2;
|
s->scancode_set = 2;
|
||||||
@ -1164,15 +1174,16 @@ static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
|
|||||||
static bool ps2_keyboard_cqueue_needed(void *opaque)
|
static bool ps2_keyboard_cqueue_needed(void *opaque)
|
||||||
{
|
{
|
||||||
PS2KbdState *s = opaque;
|
PS2KbdState *s = opaque;
|
||||||
|
PS2State *ps2 = PS2_DEVICE(s);
|
||||||
|
|
||||||
return s->common.queue.cwptr != -1; /* the queue is mostly empty */
|
return ps2->queue.cwptr != -1; /* the queue is mostly empty */
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_ps2_keyboard_cqueue = {
|
static const VMStateDescription vmstate_ps2_keyboard_cqueue = {
|
||||||
.name = "ps2kbd/command_reply_queue",
|
.name = "ps2kbd/command_reply_queue",
|
||||||
.needed = ps2_keyboard_cqueue_needed,
|
.needed = ps2_keyboard_cqueue_needed,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_INT32(common.queue.cwptr, PS2KbdState),
|
VMSTATE_INT32(parent_obj.queue.cwptr, PS2KbdState),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1180,7 +1191,7 @@ static const VMStateDescription vmstate_ps2_keyboard_cqueue = {
|
|||||||
static int ps2_kbd_post_load(void *opaque, int version_id)
|
static int ps2_kbd_post_load(void *opaque, int version_id)
|
||||||
{
|
{
|
||||||
PS2KbdState *s = (PS2KbdState *)opaque;
|
PS2KbdState *s = (PS2KbdState *)opaque;
|
||||||
PS2State *ps2 = &s->common;
|
PS2State *ps2 = PS2_DEVICE(s);
|
||||||
|
|
||||||
if (version_id == 2) {
|
if (version_id == 2) {
|
||||||
s->scancode_set = 2;
|
s->scancode_set = 2;
|
||||||
@ -1197,7 +1208,8 @@ static const VMStateDescription vmstate_ps2_keyboard = {
|
|||||||
.minimum_version_id = 2,
|
.minimum_version_id = 2,
|
||||||
.post_load = ps2_kbd_post_load,
|
.post_load = ps2_kbd_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
|
VMSTATE_STRUCT(parent_obj, PS2KbdState, 0, vmstate_ps2_common,
|
||||||
|
PS2State),
|
||||||
VMSTATE_INT32(scan_enabled, PS2KbdState),
|
VMSTATE_INT32(scan_enabled, PS2KbdState),
|
||||||
VMSTATE_INT32(translate, PS2KbdState),
|
VMSTATE_INT32(translate, PS2KbdState),
|
||||||
VMSTATE_INT32_V(scancode_set, PS2KbdState, 3),
|
VMSTATE_INT32_V(scancode_set, PS2KbdState, 3),
|
||||||
@ -1250,11 +1262,18 @@ static QemuInputHandler ps2_keyboard_handler = {
|
|||||||
|
|
||||||
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
|
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
|
||||||
{
|
{
|
||||||
PS2KbdState *s = g_new0(PS2KbdState, 1);
|
DeviceState *dev;
|
||||||
|
PS2KbdState *s;
|
||||||
|
PS2State *ps2;
|
||||||
|
|
||||||
|
dev = qdev_new(TYPE_PS2_KBD_DEVICE);
|
||||||
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||||
|
s = PS2_KBD_DEVICE(dev);
|
||||||
|
ps2 = PS2_DEVICE(s);
|
||||||
|
|
||||||
trace_ps2_kbd_init(s);
|
trace_ps2_kbd_init(s);
|
||||||
s->common.update_irq = update_irq;
|
ps2->update_irq = update_irq;
|
||||||
s->common.update_arg = update_arg;
|
ps2->update_arg = update_arg;
|
||||||
s->scancode_set = 2;
|
s->scancode_set = 2;
|
||||||
vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
|
vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
|
||||||
qemu_input_handler_register((DeviceState *)s,
|
qemu_input_handler_register((DeviceState *)s,
|
||||||
@ -1284,6 +1303,12 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const TypeInfo ps2_kbd_info = {
|
||||||
|
.name = TYPE_PS2_KBD_DEVICE,
|
||||||
|
.parent = TYPE_PS2_DEVICE,
|
||||||
|
.instance_size = sizeof(PS2KbdState),
|
||||||
|
};
|
||||||
|
|
||||||
static void ps2_class_init(ObjectClass *klass, void *data)
|
static void ps2_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
@ -1302,6 +1327,7 @@ static const TypeInfo ps2_info = {
|
|||||||
static void ps2_register_types(void)
|
static void ps2_register_types(void)
|
||||||
{
|
{
|
||||||
type_register_static(&ps2_info);
|
type_register_static(&ps2_info);
|
||||||
|
type_register_static(&ps2_kbd_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(ps2_register_types)
|
type_init(ps2_register_types)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user