diff --git a/hw/display/artist.c b/hw/display/artist.c index eadaef0d46..fde050c882 100644 --- a/hw/display/artist.c +++ b/hw/display/artist.c @@ -1358,7 +1358,7 @@ static void artist_create_buffer(ARTISTState *s, const char *name, { struct vram_buffer *buf = s->vram_buffer + idx; - memory_region_init_ram(&buf->mr, NULL, name, width * height, + memory_region_init_ram(&buf->mr, OBJECT(s), name, width * height, &error_fatal); memory_region_add_subregion_overlap(&s->mem_as_root, *offset, &buf->mr, 0); diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 63b9dd2396..44ecd446c3 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -280,8 +280,15 @@ static void machine_hppa_init(MachineState *machine) } /* PS/2 Keyboard/Mouse */ - lasips2_init(addr_space, LASI_PS2KBD_HPA, - qdev_get_gpio_in(lasi_dev, LASI_IRQ_PS2KBD_HPA)); + dev = DEVICE(lasips2_initfn(LASI_PS2KBD_HPA, + qdev_get_gpio_in(lasi_dev, + LASI_IRQ_PS2KBD_HPA))); + memory_region_add_subregion(addr_space, LASI_PS2KBD_HPA, + sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), + 0)); + memory_region_add_subregion(addr_space, LASI_PS2KBD_HPA + 0x100, + sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), + 1)); /* register power switch emulation */ qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier); diff --git a/hw/input/lasips2.c b/hw/input/lasips2.c index 94f18be4cd..9223cb0af4 100644 --- a/hw/input/lasips2.c +++ b/hw/input/lasips2.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "hw/qdev-properties.h" +#include "hw/sysbus.h" #include "hw/input/ps2.h" #include "hw/input/lasips2.h" #include "exec/hwaddr.h" @@ -31,26 +32,9 @@ #include "exec/address-spaces.h" #include "migration/vmstate.h" #include "hw/irq.h" +#include "qapi/error.h" -struct LASIPS2State; -typedef struct LASIPS2Port { - struct LASIPS2State *parent; - MemoryRegion reg; - void *dev; - uint8_t id; - uint8_t control; - uint8_t buf; - bool loopback_rbne; - bool irq; -} LASIPS2Port; - -typedef struct LASIPS2State { - LASIPS2Port kbd; - LASIPS2Port mouse; - qemu_irq irq; -} LASIPS2State; - static const VMStateDescription vmstate_lasips2 = { .name = "lasips2", .version_id = 0, @@ -205,7 +189,6 @@ static uint64_t lasips2_reg_read(void *opaque, hwaddr addr, unsigned size) break; case REG_PS2_STATUS: - ret = LASIPS2_STATUS_DATSHD | LASIPS2_STATUS_CLKSHD; if (port->control & LASIPS2_CONTROL_DIAG) { @@ -238,9 +221,9 @@ static uint64_t lasips2_reg_read(void *opaque, hwaddr addr, unsigned size) __func__, addr); break; } + trace_lasips2_reg_read(size, port->id, addr, lasips2_read_reg_name(addr), ret); - return ret; } @@ -254,35 +237,103 @@ static const MemoryRegionOps lasips2_reg_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void ps2dev_update_irq(void *opaque, int level) +static void lasips2_set_kbd_irq(void *opaque, int n, int level) { - LASIPS2Port *port = opaque; + LASIPS2State *s = LASIPS2(opaque); + LASIPS2Port *port = &s->kbd; + port->irq = level; lasips2_update_irq(port->parent); } -void lasips2_init(MemoryRegion *address_space, - hwaddr base, qemu_irq irq) +static void lasips2_set_mouse_irq(void *opaque, int n, int level) { - LASIPS2State *s; + LASIPS2State *s = LASIPS2(opaque); + LASIPS2Port *port = &s->mouse; - s = g_new0(LASIPS2State, 1); + port->irq = level; + lasips2_update_irq(port->parent); +} - s->irq = irq; +LASIPS2State *lasips2_initfn(hwaddr base, qemu_irq irq) +{ + DeviceState *dev; + + dev = qdev_new(TYPE_LASIPS2); + qdev_prop_set_uint64(dev, "base", base); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq); + + return LASIPS2(dev); +} + +static void lasips2_realize(DeviceState *dev, Error **errp) +{ + LASIPS2State *s = LASIPS2(dev); + + vmstate_register(NULL, s->base, &vmstate_lasips2, s); + + s->kbd.dev = ps2_kbd_init(); + qdev_connect_gpio_out(DEVICE(s->kbd.dev), PS2_DEVICE_IRQ, + qdev_get_gpio_in_named(dev, "ps2-kbd-input-irq", + 0)); + s->mouse.dev = ps2_mouse_init(); + qdev_connect_gpio_out(DEVICE(s->mouse.dev), PS2_DEVICE_IRQ, + qdev_get_gpio_in_named(dev, "ps2-mouse-input-irq", + 0)); +} + +static void lasips2_init(Object *obj) +{ + LASIPS2State *s = LASIPS2(obj); + + s->kbd.id = 0; s->mouse.id = 1; s->kbd.parent = s; s->mouse.parent = s; - vmstate_register(NULL, base, &vmstate_lasips2, s); - - s->kbd.dev = ps2_kbd_init(ps2dev_update_irq, &s->kbd); - s->mouse.dev = ps2_mouse_init(ps2dev_update_irq, &s->mouse); - - memory_region_init_io(&s->kbd.reg, NULL, &lasips2_reg_ops, &s->kbd, + memory_region_init_io(&s->kbd.reg, obj, &lasips2_reg_ops, &s->kbd, "lasips2-kbd", 0x100); - memory_region_add_subregion(address_space, base, &s->kbd.reg); - - memory_region_init_io(&s->mouse.reg, NULL, &lasips2_reg_ops, &s->mouse, + memory_region_init_io(&s->mouse.reg, obj, &lasips2_reg_ops, &s->mouse, "lasips2-mouse", 0x100); - memory_region_add_subregion(address_space, base + 0x100, &s->mouse.reg); + + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->kbd.reg); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mouse.reg); + + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); + + qdev_init_gpio_in_named(DEVICE(obj), lasips2_set_kbd_irq, + "ps2-kbd-input-irq", 1); + qdev_init_gpio_in_named(DEVICE(obj), lasips2_set_mouse_irq, + "ps2-mouse-input-irq", 1); } + +static Property lasips2_properties[] = { + DEFINE_PROP_UINT64("base", LASIPS2State, base, UINT64_MAX), + DEFINE_PROP_END_OF_LIST(), +}; + +static void lasips2_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = lasips2_realize; + device_class_set_props(dc, lasips2_properties); + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); +} + +static const TypeInfo lasips2_info = { + .name = TYPE_LASIPS2, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_init = lasips2_init, + .instance_size = sizeof(LASIPS2State), + .class_init = lasips2_class_init, +}; + +static void lasips2_register_types(void) +{ + type_register_static(&lasips2_info); +} + +type_init(lasips2_register_types) diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c index 45c40fe3f3..9184411c3e 100644 --- a/hw/input/pckbd.c +++ b/hw/input/pckbd.c @@ -39,49 +39,86 @@ #include "trace.h" -/* Keyboard Controller Commands */ -#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */ -#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */ -#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */ -#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */ -#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */ -#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */ -#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */ -#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */ -#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */ -#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */ -#define KBD_CCMD_READ_INPORT 0xC0 /* read input port */ -#define KBD_CCMD_READ_OUTPORT 0xD0 /* read output port */ -#define KBD_CCMD_WRITE_OUTPORT 0xD1 /* write output port */ -#define KBD_CCMD_WRITE_OBUF 0xD2 -#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if - initiated by the auxiliary device */ -#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */ -#define KBD_CCMD_DISABLE_A20 0xDD /* HP vectra only ? */ -#define KBD_CCMD_ENABLE_A20 0xDF /* HP vectra only ? */ -#define KBD_CCMD_PULSE_BITS_3_0 0xF0 /* Pulse bits 3-0 of the output port P2. */ -#define KBD_CCMD_RESET 0xFE /* Pulse bit 0 of the output port P2 = CPU reset. */ -#define KBD_CCMD_NO_OP 0xFF /* Pulse no bits of the output port P2. */ +/* Keyboard Controller Commands */ + +/* Read mode bits */ +#define KBD_CCMD_READ_MODE 0x20 +/* Write mode bits */ +#define KBD_CCMD_WRITE_MODE 0x60 +/* Get controller version */ +#define KBD_CCMD_GET_VERSION 0xA1 +/* Disable mouse interface */ +#define KBD_CCMD_MOUSE_DISABLE 0xA7 +/* Enable mouse interface */ +#define KBD_CCMD_MOUSE_ENABLE 0xA8 +/* Mouse interface test */ +#define KBD_CCMD_TEST_MOUSE 0xA9 +/* Controller self test */ +#define KBD_CCMD_SELF_TEST 0xAA +/* Keyboard interface test */ +#define KBD_CCMD_KBD_TEST 0xAB +/* Keyboard interface disable */ +#define KBD_CCMD_KBD_DISABLE 0xAD +/* Keyboard interface enable */ +#define KBD_CCMD_KBD_ENABLE 0xAE +/* read input port */ +#define KBD_CCMD_READ_INPORT 0xC0 +/* read output port */ +#define KBD_CCMD_READ_OUTPORT 0xD0 +/* write output port */ +#define KBD_CCMD_WRITE_OUTPORT 0xD1 +#define KBD_CCMD_WRITE_OBUF 0xD2 +/* Write to output buffer as if initiated by the auxiliary device */ +#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 +/* Write the following byte to the mouse */ +#define KBD_CCMD_WRITE_MOUSE 0xD4 +/* HP vectra only ? */ +#define KBD_CCMD_DISABLE_A20 0xDD +/* HP vectra only ? */ +#define KBD_CCMD_ENABLE_A20 0xDF +/* Pulse bits 3-0 of the output port P2. */ +#define KBD_CCMD_PULSE_BITS_3_0 0xF0 +/* Pulse bit 0 of the output port P2 = CPU reset. */ +#define KBD_CCMD_RESET 0xFE +/* Pulse no bits of the output port P2. */ +#define KBD_CCMD_NO_OP 0xFF /* Status Register Bits */ -#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ -#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ -#define KBD_STAT_SELFTEST 0x04 /* Self test successful */ -#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */ -#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */ -#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ -#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */ -#define KBD_STAT_PERR 0x80 /* Parity error */ + +/* Keyboard output buffer full */ +#define KBD_STAT_OBF 0x01 +/* Keyboard input buffer full */ +#define KBD_STAT_IBF 0x02 +/* Self test successful */ +#define KBD_STAT_SELFTEST 0x04 +/* Last write was a command write (0=data) */ +#define KBD_STAT_CMD 0x08 +/* Zero if keyboard locked */ +#define KBD_STAT_UNLOCKED 0x10 +/* Mouse output buffer full */ +#define KBD_STAT_MOUSE_OBF 0x20 +/* General receive/xmit timeout */ +#define KBD_STAT_GTO 0x40 +/* Parity error */ +#define KBD_STAT_PERR 0x80 /* Controller Mode Register Bits */ -#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */ -#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */ -#define KBD_MODE_SYS 0x04 /* The system flag (?) */ -#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */ -#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */ -#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */ -#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */ -#define KBD_MODE_RFU 0x80 + +/* Keyboard data generate IRQ1 */ +#define KBD_MODE_KBD_INT 0x01 +/* Mouse data generate IRQ12 */ +#define KBD_MODE_MOUSE_INT 0x02 +/* The system flag (?) */ +#define KBD_MODE_SYS 0x04 +/* The keylock doesn't affect the keyboard if set */ +#define KBD_MODE_NO_KEYLOCK 0x08 +/* Disable keyboard interface */ +#define KBD_MODE_DISABLE_KBD 0x10 +/* Disable mouse interface */ +#define KBD_MODE_DISABLE_MOUSE 0x20 +/* Scan code conversion to PC format */ +#define KBD_MODE_KCC 0x40 +#define KBD_MODE_RFU 0x80 /* Output Port Bits */ #define KBD_OUT_RESET 0x01 /* 1=normal mode, 0=reset */ @@ -89,7 +126,8 @@ #define KBD_OUT_OBF 0x10 /* Keyboard output buffer full */ #define KBD_OUT_MOUSE_OBF 0x20 /* Mouse output buffer full */ -/* OSes typically write 0xdd/0xdf to turn the A20 line off and on. +/* + * OSes typically write 0xdd/0xdf to turn the A20 line off and on. * We make the default value of the outport include these four bits, * so that the subsection is rarely necessary. */ @@ -108,33 +146,11 @@ #define KBD_OBSRC_MOUSE 0x02 #define KBD_OBSRC_CTRL 0x04 -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; - uint8_t cbdata; - uint8_t pending_tmp; - void *kbd; - void *mouse; - QEMUTimer *throttle_timer; - qemu_irq irq_kbd; - qemu_irq irq_mouse; - qemu_irq a20_out; - hwaddr mask; -} KBDState; - -/* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be - incorrect, but it avoids having to simulate exact delays */ +/* + * XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be + * incorrect, but it avoids having to simulate exact delays + */ static void kbd_update_irq_lines(KBDState *s) { int irq_kbd_level, irq_mouse_level; @@ -154,8 +170,8 @@ static void kbd_update_irq_lines(KBDState *s) } } } - qemu_set_irq(s->irq_kbd, irq_kbd_level); - qemu_set_irq(s->irq_mouse, irq_mouse_level); + qemu_set_irq(s->irqs[I8042_KBD_IRQ], irq_kbd_level); + qemu_set_irq(s->irqs[I8042_MOUSE_IRQ], irq_mouse_level); } static void kbd_deassert_irq(KBDState *s) @@ -302,21 +318,23 @@ static void kbd_write_command(void *opaque, hwaddr addr, trace_pckbd_kbd_write_command(val); - /* Bits 3-0 of the output port P2 of the keyboard controller may be pulsed + /* + * Bits 3-0 of the output port P2 of the keyboard controller may be pulsed * low for approximately 6 micro seconds. Bits 3-0 of the KBD_CCMD_PULSE * command specify the output port bits to be pulsed. * 0: Bit should be pulsed. 1: Bit should not be modified. * The only useful version of this command is pulsing bit 0, * which does a CPU reset. */ - if((val & KBD_CCMD_PULSE_BITS_3_0) == KBD_CCMD_PULSE_BITS_3_0) { - if(!(val & 1)) + if ((val & KBD_CCMD_PULSE_BITS_3_0) == KBD_CCMD_PULSE_BITS_3_0) { + if (!(val & 1)) { val = KBD_CCMD_RESET; - else + } else { val = KBD_CCMD_NO_OP; + } } - switch(val) { + switch (val) { case KBD_CCMD_READ_MODE: kbd_queue(s, s->mode, 0); break; @@ -409,7 +427,7 @@ static void kbd_write_data(void *opaque, hwaddr addr, trace_pckbd_kbd_write_data(val); - switch(s->write_cmd) { + switch (s->write_cmd) { case 0: ps2_write_keyboard(s->kbd, val); /* sending data to the keyboard reenables PS/2 communication */ @@ -607,7 +625,7 @@ static const VMStateDescription vmstate_kbd = { VMSTATE_UINT8(pending_tmp, KBDState), VMSTATE_END_OF_LIST() }, - .subsections = (const VMStateDescription*[]) { + .subsections = (const VMStateDescription * []) { &vmstate_kbd_outport, &vmstate_kbd_extended_state, NULL @@ -619,10 +637,11 @@ static uint64_t kbd_mm_readfn(void *opaque, hwaddr addr, unsigned size) { KBDState *s = opaque; - if (addr & s->mask) + if (addr & s->mask) { return kbd_read_status(s, 0, 1) & 0xff; - else + } else { return kbd_read_data(s, 0, 1) & 0xff; + } } static void kbd_mm_writefn(void *opaque, hwaddr addr, @@ -630,10 +649,11 @@ static void kbd_mm_writefn(void *opaque, hwaddr addr, { KBDState *s = opaque; - if (addr & s->mask) + if (addr & s->mask) { kbd_write_command(s, 0, value & 0xff, 1); - else + } else { kbd_write_data(s, 0, value & 0xff, 1); + } } @@ -645,35 +665,105 @@ static const MemoryRegionOps i8042_mmio_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, - MemoryRegion *region, ram_addr_t size, - hwaddr mask) +static void i8042_mmio_set_kbd_irq(void *opaque, int n, int level) { - KBDState *s = g_new0(KBDState, 1); + MMIOKBDState *s = I8042_MMIO(opaque); + KBDState *ks = &s->kbd; - s->irq_kbd = kbd_irq; - s->irq_mouse = mouse_irq; - s->mask = mask; - - s->extended_state = true; - - vmstate_register(NULL, 0, &vmstate_kbd, s); - - memory_region_init_io(region, NULL, &i8042_mmio_ops, s, "i8042", size); - - s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s); - s->mouse = ps2_mouse_init(kbd_update_aux_irq, s); - qemu_register_reset(kbd_reset, s); + kbd_update_kbd_irq(ks, level); } -struct ISAKBDState { - ISADevice parent_obj; +static void i8042_mmio_set_mouse_irq(void *opaque, int n, int level) +{ + MMIOKBDState *s = I8042_MMIO(opaque); + KBDState *ks = &s->kbd; - KBDState kbd; - bool kbd_throttle; - MemoryRegion io[2]; - uint8_t kbd_irq; - uint8_t mouse_irq; + kbd_update_aux_irq(ks, level); +} + +static void i8042_mmio_reset(DeviceState *dev) +{ + MMIOKBDState *s = I8042_MMIO(dev); + KBDState *ks = &s->kbd; + + kbd_reset(ks); +} + +static void i8042_mmio_realize(DeviceState *dev, Error **errp) +{ + MMIOKBDState *s = I8042_MMIO(dev); + KBDState *ks = &s->kbd; + + memory_region_init_io(&s->region, OBJECT(dev), &i8042_mmio_ops, ks, + "i8042", s->size); + + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->region); + + /* Note we can't use dc->vmsd without breaking migration compatibility */ + vmstate_register(NULL, 0, &vmstate_kbd, ks); + + ks->kbd = ps2_kbd_init(); + qdev_connect_gpio_out(DEVICE(ks->kbd), PS2_DEVICE_IRQ, + qdev_get_gpio_in_named(dev, "ps2-kbd-input-irq", + 0)); + ks->mouse = ps2_mouse_init(); + qdev_connect_gpio_out(DEVICE(ks->mouse), PS2_DEVICE_IRQ, + qdev_get_gpio_in_named(dev, "ps2-mouse-input-irq", + 0)); +} + +static void i8042_mmio_init(Object *obj) +{ + MMIOKBDState *s = I8042_MMIO(obj); + KBDState *ks = &s->kbd; + + ks->extended_state = true; + + qdev_init_gpio_out(DEVICE(obj), ks->irqs, 2); + qdev_init_gpio_in_named(DEVICE(obj), i8042_mmio_set_kbd_irq, + "ps2-kbd-input-irq", 1); + qdev_init_gpio_in_named(DEVICE(obj), i8042_mmio_set_mouse_irq, + "ps2-mouse-input-irq", 1); +} + +static Property i8042_mmio_properties[] = { + DEFINE_PROP_UINT64("mask", MMIOKBDState, kbd.mask, UINT64_MAX), + DEFINE_PROP_UINT32("size", MMIOKBDState, size, -1), + DEFINE_PROP_END_OF_LIST(), +}; + +static void i8042_mmio_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = i8042_mmio_realize; + dc->reset = i8042_mmio_reset; + device_class_set_props(dc, i8042_mmio_properties); + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); +} + +MMIOKBDState *i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, + ram_addr_t size, hwaddr mask) +{ + DeviceState *dev; + + dev = qdev_new(TYPE_I8042_MMIO); + qdev_prop_set_uint64(dev, "mask", mask); + qdev_prop_set_uint32(dev, "size", size); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + qdev_connect_gpio_out(dev, I8042_KBD_IRQ, kbd_irq); + qdev_connect_gpio_out(dev, I8042_MOUSE_IRQ, mouse_irq); + + return I8042_MMIO(dev); +} + +static const TypeInfo i8042_mmio_info = { + .name = TYPE_I8042_MMIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_init = i8042_mmio_init, + .instance_size = sizeof(MMIOKBDState), + .class_init = i8042_mmio_class_init }; void i8042_isa_mouse_fake_event(ISAKBDState *isa) @@ -718,6 +808,31 @@ static const MemoryRegionOps i8042_cmd_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +static void i8042_set_kbd_irq(void *opaque, int n, int level) +{ + ISAKBDState *s = I8042(opaque); + KBDState *ks = &s->kbd; + + kbd_update_kbd_irq(ks, level); +} + +static void i8042_set_mouse_irq(void *opaque, int n, int level) +{ + ISAKBDState *s = I8042(opaque); + KBDState *ks = &s->kbd; + + kbd_update_aux_irq(ks, level); +} + + +static void i8042_reset(DeviceState *dev) +{ + ISAKBDState *s = I8042(dev); + KBDState *ks = &s->kbd; + + kbd_reset(ks); +} + static void i8042_initfn(Object *obj) { ISAKBDState *isa_s = I8042(obj); @@ -729,6 +844,12 @@ static void i8042_initfn(Object *obj) "i8042-cmd", 1); qdev_init_gpio_out_named(DEVICE(obj), &s->a20_out, I8042_A20_LINE, 1); + + qdev_init_gpio_out(DEVICE(obj), s->irqs, 2); + qdev_init_gpio_in_named(DEVICE(obj), i8042_set_kbd_irq, + "ps2-kbd-input-irq", 1); + qdev_init_gpio_in_named(DEVICE(obj), i8042_set_mouse_irq, + "ps2-mouse-input-irq", 1); } static void i8042_realizefn(DeviceState *dev, Error **errp) @@ -749,14 +870,20 @@ static void i8042_realizefn(DeviceState *dev, Error **errp) return; } - s->irq_kbd = isa_get_irq(isadev, isa_s->kbd_irq); - s->irq_mouse = isa_get_irq(isadev, isa_s->mouse_irq); + isa_connect_gpio_out(isadev, I8042_KBD_IRQ, isa_s->kbd_irq); + isa_connect_gpio_out(isadev, I8042_MOUSE_IRQ, isa_s->mouse_irq); isa_register_ioport(isadev, isa_s->io + 0, 0x60); isa_register_ioport(isadev, isa_s->io + 1, 0x64); - s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s); - s->mouse = ps2_mouse_init(kbd_update_aux_irq, s); + s->kbd = ps2_kbd_init(); + qdev_connect_gpio_out(DEVICE(s->kbd), PS2_DEVICE_IRQ, + qdev_get_gpio_in_named(dev, "ps2-kbd-input-irq", + 0)); + s->mouse = ps2_mouse_init(); + qdev_connect_gpio_out(DEVICE(s->mouse), PS2_DEVICE_IRQ, + qdev_get_gpio_in_named(dev, "ps2-mouse-input-irq", + 0)); if (isa_s->kbd_throttle && !isa_s->kbd.extended_state) { warn_report(TYPE_I8042 ": can't enable kbd-throttle without" " extended-state, disabling kbd-throttle"); @@ -764,7 +891,6 @@ static void i8042_realizefn(DeviceState *dev, Error **errp) s->throttle_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, kbd_throttle_timeout, s); } - qemu_register_reset(kbd_reset, s); } static void i8042_build_aml(AcpiDevAmlIf *adev, Aml *scope) @@ -810,6 +936,7 @@ static void i8042_class_initfn(ObjectClass *klass, void *data) AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass); device_class_set_props(dc, i8042_properties); + dc->reset = i8042_reset; dc->realize = i8042_realizefn; dc->vmsd = &vmstate_kbd_isa; adevc->build_dev_aml = i8042_build_aml; @@ -831,6 +958,7 @@ static const TypeInfo i8042_info = { static void i8042_register_types(void) { type_register_static(&i8042_info); + type_register_static(&i8042_mmio_info); } type_init(i8042_register_types) diff --git a/hw/input/pl050.c b/hw/input/pl050.c index d279b6c148..209cc001cf 100644 --- a/hw/input/pl050.c +++ b/hw/input/pl050.c @@ -7,6 +7,14 @@ * This code is licensed under the GPL. */ +/* + * QEMU interface: + * + sysbus MMIO region 0: MemoryRegion defining the PL050 registers + * + Named GPIO input "ps2-input-irq": set to 1 if the downstream PS2 device + * has asserted its irq + * + sysbus IRQ 0: PL050 output irq + */ + #include "qemu/osdep.h" #include "hw/sysbus.h" #include "migration/vmstate.h" @@ -53,26 +61,34 @@ static const VMStateDescription vmstate_pl050 = { #define PL050_KMIC (1 << 1) #define PL050_KMID (1 << 0) -static const unsigned char pl050_id[] = -{ 0x50, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; +static const unsigned char pl050_id[] = { + 0x50, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 +}; -static void pl050_update(void *opaque, int level) +static void pl050_update_irq(PL050State *s) +{ + int level = (s->pending && (s->cr & 0x10) != 0) + || (s->cr & 0x08) != 0; + + qemu_set_irq(s->irq, level); +} + +static void pl050_set_irq(void *opaque, int n, int level) { PL050State *s = (PL050State *)opaque; - int raise; s->pending = level; - raise = (s->pending && (s->cr & 0x10) != 0) - || (s->cr & 0x08) != 0; - qemu_set_irq(s->irq, raise); + pl050_update_irq(s); } static uint64_t pl050_read(void *opaque, hwaddr offset, unsigned size) { PL050State *s = (PL050State *)opaque; - if (offset >= 0xfe0 && offset < 0x1000) + + if (offset >= 0xfe0 && offset < 0x1000) { return pl050_id[(offset - 0xfe0) >> 2]; + } switch (offset >> 2) { case 0: /* KMICR */ @@ -88,16 +104,19 @@ static uint64_t pl050_read(void *opaque, hwaddr offset, val = (val ^ (val >> 1)) & 1; stat = PL050_TXEMPTY; - if (val) + if (val) { stat |= PL050_RXPARITY; - if (s->pending) + } + if (s->pending) { stat |= PL050_RXFULL; + } return stat; } case 2: /* KMIDATA */ - if (s->pending) + if (s->pending) { s->last = ps2_read_data(s->dev); + } return s->last; case 3: /* KMICLKDIV */ return s->clk; @@ -114,10 +133,11 @@ static void pl050_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PL050State *s = (PL050State *)opaque; + switch (offset >> 2) { case 0: /* KMICR */ s->cr = value; - pl050_update(s, s->pending); + pl050_update_irq(s); /* ??? Need to implement the enable/disable bit. */ break; case 2: /* KMIDATA */ @@ -152,10 +172,12 @@ static void pl050_realize(DeviceState *dev, Error **errp) sysbus_init_mmio(sbd, &s->iomem); sysbus_init_irq(sbd, &s->irq); if (s->is_mouse) { - s->dev = ps2_mouse_init(pl050_update, s); + s->dev = ps2_mouse_init(); } else { - s->dev = ps2_kbd_init(pl050_update, s); + s->dev = ps2_kbd_init(); } + qdev_connect_gpio_out(DEVICE(s->dev), PS2_DEVICE_IRQ, + qdev_get_gpio_in_named(dev, "ps2-input-irq", 0)); } static void pl050_keyboard_init(Object *obj) @@ -184,6 +206,11 @@ static const TypeInfo pl050_mouse_info = { .instance_init = pl050_mouse_init, }; +static void pl050_init(Object *obj) +{ + qdev_init_gpio_in_named(DEVICE(obj), pl050_set_irq, "ps2-input-irq", 1); +} + static void pl050_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -195,6 +222,7 @@ static void pl050_class_init(ObjectClass *oc, void *data) static const TypeInfo pl050_type_info = { .name = TYPE_PL050, .parent = TYPE_SYS_BUS_DEVICE, + .instance_init = pl050_init, .instance_size = sizeof(PL050State), .abstract = true, .class_init = pl050_class_init, diff --git a/hw/input/ps2.c b/hw/input/ps2.c index c16df1de7a..59bac28ac8 100644 --- a/hw/input/ps2.c +++ b/hw/input/ps2.c @@ -24,61 +24,59 @@ #include "qemu/osdep.h" #include "qemu/log.h" +#include "hw/irq.h" +#include "hw/sysbus.h" #include "hw/input/ps2.h" #include "migration/vmstate.h" #include "ui/console.h" #include "ui/input.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" +#include "qapi/error.h" #include "trace.h" /* Keyboard Commands */ -#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ -#define KBD_CMD_ECHO 0xEE -#define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */ -#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */ -#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ -#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ -#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */ -#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */ -#define KBD_CMD_RESET 0xFF /* Reset */ +#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ +#define KBD_CMD_ECHO 0xEE +#define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */ +#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */ +#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ +#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ +#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */ +#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */ +#define KBD_CMD_RESET 0xFF /* Reset */ #define KBD_CMD_SET_MAKE_BREAK 0xFC /* Set Make and Break mode */ #define KBD_CMD_SET_TYPEMATIC 0xFA /* Set Typematic Make and Break mode */ /* Keyboard Replies */ -#define KBD_REPLY_POR 0xAA /* Power on reset */ -#define KBD_REPLY_ID 0xAB /* Keyboard ID */ -#define KBD_REPLY_ACK 0xFA /* Command ACK */ -#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ +#define KBD_REPLY_POR 0xAA /* Power on reset */ +#define KBD_REPLY_ID 0xAB /* Keyboard ID */ +#define KBD_REPLY_ACK 0xFA /* Command ACK */ +#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ /* Mouse Commands */ -#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ -#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ -#define AUX_SET_RES 0xE8 /* Set resolution */ -#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ -#define AUX_SET_STREAM 0xEA /* Set stream mode */ -#define AUX_POLL 0xEB /* Poll */ -#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */ -#define AUX_SET_WRAP 0xEE /* Set wrap mode */ -#define AUX_SET_REMOTE 0xF0 /* Set remote mode */ -#define AUX_GET_TYPE 0xF2 /* Get type */ -#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ -#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ -#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ -#define AUX_SET_DEFAULT 0xF6 -#define AUX_RESET 0xFF /* Reset aux device */ -#define AUX_ACK 0xFA /* Command byte ACK. */ +#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ +#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ +#define AUX_SET_RES 0xE8 /* Set resolution */ +#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ +#define AUX_SET_STREAM 0xEA /* Set stream mode */ +#define AUX_POLL 0xEB /* Poll */ +#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */ +#define AUX_SET_WRAP 0xEE /* Set wrap mode */ +#define AUX_SET_REMOTE 0xF0 /* Set remote mode */ +#define AUX_GET_TYPE 0xF2 /* Get type */ +#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ +#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ +#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ +#define AUX_SET_DEFAULT 0xF6 +#define AUX_RESET 0xFF /* Reset aux device */ +#define AUX_ACK 0xFA /* Command byte ACK. */ #define MOUSE_STATUS_REMOTE 0x40 #define MOUSE_STATUS_ENABLED 0x20 #define MOUSE_STATUS_SCALE21 0x10 -/* - * PS/2 buffer size. Keep 256 bytes for compatibility with - * older QEMU versions. - */ -#define PS2_BUFFER_SIZE 256 #define PS2_QUEUE_SIZE 16 /* Queue size required by PS/2 protocol */ #define PS2_QUEUE_HEADROOM 8 /* Queue size for keyboard command replies */ @@ -90,43 +88,6 @@ #define MOD_SHIFT_R (1 << 4) #define MOD_ALT_R (1 << 5) -typedef struct { - uint8_t data[PS2_BUFFER_SIZE]; - int rptr, wptr, cwptr, count; -} PS2Queue; - -struct PS2State { - PS2Queue queue; - int32_t write_cmd; - void (*update_irq)(void *, int); - void *update_arg; -}; - -typedef struct { - PS2State common; - int scan_enabled; - int translate; - int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */ - int ledstate; - bool need_high_bit; - unsigned int modifiers; /* bitmask of MOD_* constants above */ -} PS2KbdState; - -typedef struct { - PS2State common; - uint8_t mouse_status; - uint8_t mouse_resolution; - uint8_t mouse_sample_rate; - uint8_t mouse_wrap; - uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */ - uint8_t mouse_detect_state; - int mouse_dx; /* current values, needed for 'poll' mode */ - int mouse_dy; - int mouse_dz; - int mouse_dw; - uint8_t mouse_buttons; -} PS2MouseState; - static uint8_t translate_table[256] = { 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, @@ -212,9 +173,14 @@ void ps2_queue_noirq(PS2State *s, int b) q->count++; } -void ps2_raise_irq(PS2State *s) +static void ps2_raise_irq(PS2State *s) { - s->update_irq(s->update_arg, 1); + qemu_set_irq(s->irq, 1); +} + +static void ps2_lower_irq(PS2State *s) +{ + qemu_set_irq(s->irq, 0); } void ps2_queue(PS2State *s, int b) @@ -324,6 +290,7 @@ static void ps2_cqueue_reset(PS2State *s) static void ps2_put_keycode(void *opaque, int keycode) { PS2KbdState *s = opaque; + PS2State *ps = PS2_DEVICE(s); trace_ps2_put_keycode(opaque, keycode); qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL); @@ -332,13 +299,13 @@ static void ps2_put_keycode(void *opaque, int keycode) if (keycode == 0xf0) { s->need_high_bit = true; } 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; } else { - ps2_queue(&s->common, translate_table[keycode]); + ps2_queue(ps, translate_table[keycode]); } } else { - ps2_queue(&s->common, keycode); + ps2_queue(ps, keycode); } } @@ -436,8 +403,9 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src, } } } else { - if (qcode < qemu_input_map_qcode_to_atset1_len) + if (qcode < qemu_input_map_qcode_to_atset1_len) { keycode = qemu_input_map_qcode_to_atset1[qcode]; + } if (keycode) { if (keycode & 0xff00) { ps2_put_keycode(s, keycode >> 8); @@ -530,8 +498,9 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src, } } } else { - if (qcode < qemu_input_map_qcode_to_atset2_len) + if (qcode < qemu_input_map_qcode_to_atset2_len) { keycode = qemu_input_map_qcode_to_atset2[qcode]; + } if (keycode) { if (keycode & 0xff00) { ps2_put_keycode(s, keycode >> 8); @@ -546,8 +515,9 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src, } } } else if (s->scancode_set == 3) { - if (qcode < qemu_input_map_qcode_to_atset3_len) + if (qcode < qemu_input_map_qcode_to_atset3_len) { keycode = qemu_input_map_qcode_to_atset3[qcode]; + } if (keycode) { /* FIXME: break code should be configured on a key by key basis */ if (!key->down) { @@ -569,8 +539,10 @@ uint32_t ps2_read_data(PS2State *s) trace_ps2_read_data(s); q = &s->queue; if (q->count == 0) { - /* NOTE: if no data left, we return the last keyboard one - (needed for EMM386) */ + /* + * NOTE: if no data left, we return the last keyboard one + * (needed for EMM386) + */ /* XXX: need a timer to do things correctly */ index = q->rptr - 1; if (index < 0) { @@ -588,10 +560,10 @@ uint32_t ps2_read_data(PS2State *s) q->cwptr = -1; } /* reading deasserts IRQ */ - s->update_irq(s->update_arg, 0); + ps2_lower_irq(s); /* reassert IRQs if data left */ if (q->count) { - s->update_irq(s->update_arg, 1); + ps2_raise_irq(s); } } return val; @@ -606,119 +578,123 @@ static void ps2_set_ledstate(PS2KbdState *s, int ledstate) static void ps2_reset_keyboard(PS2KbdState *s) { + PS2State *ps2 = PS2_DEVICE(s); + trace_ps2_reset_keyboard(s); s->scan_enabled = 1; s->scancode_set = 2; - ps2_reset_queue(&s->common); + ps2_reset_queue(ps2); ps2_set_ledstate(s, 0); } -void ps2_write_keyboard(void *opaque, int val) +void ps2_write_keyboard(PS2KbdState *s, int val) { - PS2KbdState *s = (PS2KbdState *)opaque; + PS2State *ps2 = PS2_DEVICE(s); - trace_ps2_write_keyboard(opaque, val); - ps2_cqueue_reset(&s->common); - switch(s->common.write_cmd) { + trace_ps2_write_keyboard(s, val); + ps2_cqueue_reset(ps2); + switch (ps2->write_cmd) { default: case -1: - switch(val) { + switch (val) { case 0x00: - ps2_cqueue_1(&s->common, KBD_REPLY_ACK); + ps2_cqueue_1(ps2, KBD_REPLY_ACK); break; case 0x05: - ps2_cqueue_1(&s->common, KBD_REPLY_RESEND); + ps2_cqueue_1(ps2, KBD_REPLY_RESEND); break; case KBD_CMD_GET_ID: /* We emulate a MF2 AT keyboard here */ - ps2_cqueue_3(&s->common, KBD_REPLY_ACK, KBD_REPLY_ID, - s->translate ? 0x41 : 0x83); + ps2_cqueue_3(ps2, KBD_REPLY_ACK, KBD_REPLY_ID, + s->translate ? 0x41 : 0x83); break; case KBD_CMD_ECHO: - ps2_cqueue_1(&s->common, KBD_CMD_ECHO); + ps2_cqueue_1(ps2, KBD_CMD_ECHO); break; case KBD_CMD_ENABLE: s->scan_enabled = 1; - ps2_cqueue_1(&s->common, KBD_REPLY_ACK); + ps2_cqueue_1(ps2, KBD_REPLY_ACK); break; case KBD_CMD_SCANCODE: case KBD_CMD_SET_LEDS: case KBD_CMD_SET_RATE: case KBD_CMD_SET_MAKE_BREAK: - s->common.write_cmd = val; - ps2_cqueue_1(&s->common, KBD_REPLY_ACK); + ps2->write_cmd = val; + ps2_cqueue_1(ps2, KBD_REPLY_ACK); break; case KBD_CMD_RESET_DISABLE: ps2_reset_keyboard(s); s->scan_enabled = 0; - ps2_cqueue_1(&s->common, KBD_REPLY_ACK); + ps2_cqueue_1(ps2, KBD_REPLY_ACK); break; case KBD_CMD_RESET_ENABLE: ps2_reset_keyboard(s); s->scan_enabled = 1; - ps2_cqueue_1(&s->common, KBD_REPLY_ACK); + ps2_cqueue_1(ps2, KBD_REPLY_ACK); break; case KBD_CMD_RESET: ps2_reset_keyboard(s); - ps2_cqueue_2(&s->common, - KBD_REPLY_ACK, - KBD_REPLY_POR); + ps2_cqueue_2(ps2, + KBD_REPLY_ACK, + KBD_REPLY_POR); break; case KBD_CMD_SET_TYPEMATIC: - ps2_cqueue_1(&s->common, KBD_REPLY_ACK); + ps2_cqueue_1(ps2, KBD_REPLY_ACK); break; default: - ps2_cqueue_1(&s->common, KBD_REPLY_RESEND); + ps2_cqueue_1(ps2, KBD_REPLY_RESEND); break; } break; case KBD_CMD_SET_MAKE_BREAK: - ps2_cqueue_1(&s->common, KBD_REPLY_ACK); - s->common.write_cmd = -1; + ps2_cqueue_1(ps2, KBD_REPLY_ACK); + ps2->write_cmd = -1; break; case KBD_CMD_SCANCODE: 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); } else if (val >= 1 && val <= 3) { s->scancode_set = val; - ps2_cqueue_1(&s->common, KBD_REPLY_ACK); + ps2_cqueue_1(ps2, KBD_REPLY_ACK); } 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; case KBD_CMD_SET_LEDS: ps2_set_ledstate(s, val); - ps2_cqueue_1(&s->common, KBD_REPLY_ACK); - s->common.write_cmd = -1; + ps2_cqueue_1(ps2, KBD_REPLY_ACK); + ps2->write_cmd = -1; break; case KBD_CMD_SET_RATE: - ps2_cqueue_1(&s->common, KBD_REPLY_ACK); - s->common.write_cmd = -1; + ps2_cqueue_1(ps2, KBD_REPLY_ACK); + ps2->write_cmd = -1; break; } } -/* Set the scancode translation mode. - 0 = raw scancodes. - 1 = translated scancodes (used by qemu internally). */ +/* + * Set the scancode translation mode. + * 0 = raw scancodes. + * 1 = translated scancodes (used by qemu internally). + */ -void ps2_keyboard_set_translation(void *opaque, int mode) +void ps2_keyboard_set_translation(PS2KbdState *s, int mode) { - PS2KbdState *s = (PS2KbdState *)opaque; - trace_ps2_keyboard_set_translation(opaque, mode); + trace_ps2_keyboard_set_translation(s, mode); s->translate = mode; } static int ps2_mouse_send_packet(PS2MouseState *s) { + PS2State *ps2 = PS2_DEVICE(s); /* IMPS/2 and IMEX send 4 bytes, PS2 sends 3 bytes */ const int needed = s->mouse_type ? 4 : 3; unsigned int b; int dx1, dy1, dz1, dw1; - if (PS2_QUEUE_SIZE - s->common.queue.count < needed) { + if (PS2_QUEUE_SIZE - ps2->queue.count < needed) { return 0; } @@ -727,31 +703,34 @@ static int ps2_mouse_send_packet(PS2MouseState *s) dz1 = s->mouse_dz; dw1 = s->mouse_dw; /* XXX: increase range to 8 bits ? */ - if (dx1 > 127) + if (dx1 > 127) { dx1 = 127; - else if (dx1 < -127) + } else if (dx1 < -127) { dx1 = -127; - if (dy1 > 127) + } + if (dy1 > 127) { dy1 = 127; - else if (dy1 < -127) + } else if (dy1 < -127) { dy1 = -127; + } b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07); - ps2_queue_noirq(&s->common, b); - ps2_queue_noirq(&s->common, dx1 & 0xff); - ps2_queue_noirq(&s->common, dy1 & 0xff); + ps2_queue_noirq(ps2, b); + ps2_queue_noirq(ps2, dx1 & 0xff); + ps2_queue_noirq(ps2, dy1 & 0xff); /* extra byte for IMPS/2 or IMEX */ - switch(s->mouse_type) { + switch (s->mouse_type) { default: /* Just ignore the wheels if not supported */ s->mouse_dz = 0; s->mouse_dw = 0; break; case 3: - if (dz1 > 127) + if (dz1 > 127) { dz1 = 127; - else if (dz1 < -127) - dz1 = -127; - ps2_queue_noirq(&s->common, dz1 & 0xff); + } else if (dz1 < -127) { + dz1 = -127; + } + ps2_queue_noirq(ps2, dz1 & 0xff); s->mouse_dz -= dz1; s->mouse_dw = 0; break; @@ -787,11 +766,11 @@ static int ps2_mouse_send_packet(PS2MouseState *s) b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); s->mouse_dz -= dz1; } - ps2_queue_noirq(&s->common, b); + ps2_queue_noirq(ps2, b); break; } - ps2_raise_irq(&s->common); + ps2_raise_irq(ps2); trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b); /* update deltas */ @@ -816,8 +795,9 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src, InputBtnEvent *btn; /* check if deltas are recorded when disabled */ - if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) + if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) { return; + } switch (evt->type) { case INPUT_EVENT_KIND_REL: @@ -868,8 +848,10 @@ static void ps2_mouse_sync(DeviceState *dev) qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL); } if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) { - /* if not remote, send event. Multiple events are sent if - too big deltas */ + /* + * if not remote, send event. Multiple events are sent if + * too big deltas + */ while (ps2_mouse_send_packet(s)) { if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 && s->mouse_dw == 0) { @@ -879,96 +861,95 @@ static void ps2_mouse_sync(DeviceState *dev) } } -void ps2_mouse_fake_event(void *opaque) +void ps2_mouse_fake_event(PS2MouseState *s) { - PS2MouseState *s = opaque; - trace_ps2_mouse_fake_event(opaque); + trace_ps2_mouse_fake_event(s); s->mouse_dx++; - ps2_mouse_sync(opaque); + ps2_mouse_sync(DEVICE(s)); } -void ps2_write_mouse(void *opaque, int val) +void ps2_write_mouse(PS2MouseState *s, int val) { - PS2MouseState *s = (PS2MouseState *)opaque; + PS2State *ps2 = PS2_DEVICE(s); - trace_ps2_write_mouse(opaque, val); - switch(s->common.write_cmd) { + trace_ps2_write_mouse(s, val); + switch (ps2->write_cmd) { default: case -1: /* mouse command */ if (s->mouse_wrap) { if (val == AUX_RESET_WRAP) { s->mouse_wrap = 0; - ps2_queue(&s->common, AUX_ACK); + ps2_queue(ps2, AUX_ACK); return; } else if (val != AUX_RESET) { - ps2_queue(&s->common, val); + ps2_queue(ps2, val); return; } } - switch(val) { + switch (val) { case AUX_SET_SCALE11: s->mouse_status &= ~MOUSE_STATUS_SCALE21; - ps2_queue(&s->common, AUX_ACK); + ps2_queue(ps2, AUX_ACK); break; case AUX_SET_SCALE21: s->mouse_status |= MOUSE_STATUS_SCALE21; - ps2_queue(&s->common, AUX_ACK); + ps2_queue(ps2, AUX_ACK); break; case AUX_SET_STREAM: s->mouse_status &= ~MOUSE_STATUS_REMOTE; - ps2_queue(&s->common, AUX_ACK); + ps2_queue(ps2, AUX_ACK); break; case AUX_SET_WRAP: s->mouse_wrap = 1; - ps2_queue(&s->common, AUX_ACK); + ps2_queue(ps2, AUX_ACK); break; case AUX_SET_REMOTE: s->mouse_status |= MOUSE_STATUS_REMOTE; - ps2_queue(&s->common, AUX_ACK); + ps2_queue(ps2, AUX_ACK); break; case AUX_GET_TYPE: - ps2_queue_2(&s->common, + ps2_queue_2(ps2, AUX_ACK, s->mouse_type); break; case AUX_SET_RES: case AUX_SET_SAMPLE: - s->common.write_cmd = val; - ps2_queue(&s->common, AUX_ACK); + ps2->write_cmd = val; + ps2_queue(ps2, AUX_ACK); break; case AUX_GET_SCALE: - ps2_queue_4(&s->common, + ps2_queue_4(ps2, AUX_ACK, s->mouse_status, s->mouse_resolution, s->mouse_sample_rate); break; case AUX_POLL: - ps2_queue(&s->common, AUX_ACK); + ps2_queue(ps2, AUX_ACK); ps2_mouse_send_packet(s); break; case AUX_ENABLE_DEV: s->mouse_status |= MOUSE_STATUS_ENABLED; - ps2_queue(&s->common, AUX_ACK); + ps2_queue(ps2, AUX_ACK); break; case AUX_DISABLE_DEV: s->mouse_status &= ~MOUSE_STATUS_ENABLED; - ps2_queue(&s->common, AUX_ACK); + ps2_queue(ps2, AUX_ACK); break; case AUX_SET_DEFAULT: s->mouse_sample_rate = 100; s->mouse_resolution = 2; s->mouse_status = 0; - ps2_queue(&s->common, AUX_ACK); + ps2_queue(ps2, AUX_ACK); break; case AUX_RESET: s->mouse_sample_rate = 100; s->mouse_resolution = 2; s->mouse_status = 0; s->mouse_type = 0; - ps2_reset_queue(&s->common); - ps2_queue_3(&s->common, + ps2_reset_queue(ps2); + ps2_queue_3(ps2, AUX_ACK, 0xaa, s->mouse_type); @@ -980,47 +961,53 @@ void ps2_write_mouse(void *opaque, int val) case AUX_SET_SAMPLE: s->mouse_sample_rate = val; /* detect IMPS/2 or IMEX */ - switch(s->mouse_detect_state) { + switch (s->mouse_detect_state) { default: case 0: - if (val == 200) + if (val == 200) { s->mouse_detect_state = 1; + } break; case 1: - if (val == 100) + if (val == 100) { s->mouse_detect_state = 2; - else if (val == 200) + } else if (val == 200) { s->mouse_detect_state = 3; - else + } else { s->mouse_detect_state = 0; + } break; case 2: - if (val == 80) + if (val == 80) { s->mouse_type = 3; /* IMPS/2 */ + } s->mouse_detect_state = 0; break; case 3: - if (val == 80) + if (val == 80) { s->mouse_type = 4; /* IMEX */ + } s->mouse_detect_state = 0; break; } - ps2_queue(&s->common, AUX_ACK); - s->common.write_cmd = -1; + ps2_queue(ps2, AUX_ACK); + ps2->write_cmd = -1; break; case AUX_SET_RES: s->mouse_resolution = val; - ps2_queue(&s->common, AUX_ACK); - s->common.write_cmd = -1; + ps2_queue(ps2, AUX_ACK); + ps2->write_cmd = -1; break; } } -static void ps2_common_reset(PS2State *s) +static void ps2_reset(DeviceState *dev) { + PS2State *s = PS2_DEVICE(dev); + s->write_cmd = -1; ps2_reset_queue(s); - s->update_irq(s->update_arg, 0); + ps2_lower_irq(s); } static void ps2_common_post_load(PS2State *s) @@ -1049,24 +1036,28 @@ static void ps2_common_post_load(PS2State *s) q->cwptr = ccount ? (q->rptr + ccount) & (PS2_BUFFER_SIZE - 1) : -1; } -static void ps2_kbd_reset(void *opaque) +static void ps2_kbd_reset(DeviceState *dev) { - PS2KbdState *s = (PS2KbdState *) opaque; + PS2DeviceClass *ps2dc = PS2_DEVICE_GET_CLASS(dev); + PS2KbdState *s = PS2_KBD_DEVICE(dev); + + trace_ps2_kbd_reset(s); + ps2dc->parent_reset(dev); - trace_ps2_kbd_reset(opaque); - ps2_common_reset(&s->common); s->scan_enabled = 1; s->translate = 0; s->scancode_set = 2; s->modifiers = 0; } -static void ps2_mouse_reset(void *opaque) +static void ps2_mouse_reset(DeviceState *dev) { - PS2MouseState *s = (PS2MouseState *) opaque; + PS2DeviceClass *ps2dc = PS2_DEVICE_GET_CLASS(dev); + PS2MouseState *s = PS2_MOUSE_DEVICE(dev); + + trace_ps2_mouse_reset(s); + ps2dc->parent_reset(dev); - trace_ps2_mouse_reset(opaque); - ps2_common_reset(&s->common); s->mouse_status = 0; s->mouse_resolution = 0; s->mouse_sample_rate = 0; @@ -1141,26 +1132,28 @@ static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = { static bool ps2_keyboard_cqueue_needed(void *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 = { .name = "ps2kbd/command_reply_queue", .needed = ps2_keyboard_cqueue_needed, .fields = (VMStateField[]) { - VMSTATE_INT32(common.queue.cwptr, PS2KbdState), + VMSTATE_INT32(parent_obj.queue.cwptr, PS2KbdState), VMSTATE_END_OF_LIST() } }; -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; - PS2State *ps2 = &s->common; + PS2KbdState *s = (PS2KbdState *)opaque; + PS2State *ps2 = PS2_DEVICE(s); - if (version_id == 2) - s->scancode_set=2; + if (version_id == 2) { + s->scancode_set = 2; + } ps2_common_post_load(ps2); @@ -1173,13 +1166,14 @@ static const VMStateDescription vmstate_ps2_keyboard = { .minimum_version_id = 2, .post_load = ps2_kbd_post_load, .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(translate, PS2KbdState), - VMSTATE_INT32_V(scancode_set, PS2KbdState,3), + VMSTATE_INT32_V(scancode_set, PS2KbdState, 3), VMSTATE_END_OF_LIST() }, - .subsections = (const VMStateDescription*[]) { + .subsections = (const VMStateDescription * []) { &vmstate_ps2_keyboard_ledstate, &vmstate_ps2_keyboard_need_high_bit, &vmstate_ps2_keyboard_cqueue, @@ -1190,7 +1184,7 @@ static const VMStateDescription vmstate_ps2_keyboard = { static int ps2_mouse_post_load(void *opaque, int version_id) { PS2MouseState *s = (PS2MouseState *)opaque; - PS2State *ps2 = &s->common; + PS2State *ps2 = PS2_DEVICE(s); ps2_common_post_load(ps2); @@ -1203,7 +1197,8 @@ static const VMStateDescription vmstate_ps2_mouse = { .minimum_version_id = 2, .post_load = ps2_mouse_post_load, .fields = (VMStateField[]) { - VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State), + VMSTATE_STRUCT(parent_obj, PS2MouseState, 0, vmstate_ps2_common, + PS2State), VMSTATE_UINT8(mouse_status, PS2MouseState), VMSTATE_UINT8(mouse_resolution, PS2MouseState), VMSTATE_UINT8(mouse_sample_rate, PS2MouseState), @@ -1224,18 +1219,21 @@ static QemuInputHandler ps2_keyboard_handler = { .event = ps2_keyboard_event, }; -void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) +static void ps2_kbd_realize(DeviceState *dev, Error **errp) { - PS2KbdState *s = g_new0(PS2KbdState, 1); + qemu_input_handler_register(dev, &ps2_keyboard_handler); +} + +void *ps2_kbd_init(void) +{ + DeviceState *dev; + PS2KbdState *s; + + dev = qdev_new(TYPE_PS2_KBD_DEVICE); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + s = PS2_KBD_DEVICE(dev); trace_ps2_kbd_init(s); - s->common.update_irq = update_irq; - s->common.update_arg = update_arg; - s->scancode_set = 2; - vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s); - qemu_input_handler_register((DeviceState *)s, - &ps2_keyboard_handler); - qemu_register_reset(ps2_kbd_reset, s); return s; } @@ -1246,16 +1244,89 @@ static QemuInputHandler ps2_mouse_handler = { .sync = ps2_mouse_sync, }; -void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg) +static void ps2_mouse_realize(DeviceState *dev, Error **errp) { - PS2MouseState *s = g_new0(PS2MouseState, 1); + qemu_input_handler_register(dev, &ps2_mouse_handler); +} + +void *ps2_mouse_init(void) +{ + DeviceState *dev; + PS2MouseState *s; + + dev = qdev_new(TYPE_PS2_MOUSE_DEVICE); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + s = PS2_MOUSE_DEVICE(dev); trace_ps2_mouse_init(s); - s->common.update_irq = update_irq; - s->common.update_arg = update_arg; - vmstate_register(NULL, 0, &vmstate_ps2_mouse, s); - qemu_input_handler_register((DeviceState *)s, - &ps2_mouse_handler); - qemu_register_reset(ps2_mouse_reset, s); return s; } + +static void ps2_kbd_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PS2DeviceClass *ps2dc = PS2_DEVICE_CLASS(klass); + + dc->realize = ps2_kbd_realize; + device_class_set_parent_reset(dc, ps2_kbd_reset, &ps2dc->parent_reset); + dc->vmsd = &vmstate_ps2_keyboard; +} + +static const TypeInfo ps2_kbd_info = { + .name = TYPE_PS2_KBD_DEVICE, + .parent = TYPE_PS2_DEVICE, + .instance_size = sizeof(PS2KbdState), + .class_init = ps2_kbd_class_init +}; + +static void ps2_mouse_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PS2DeviceClass *ps2dc = PS2_DEVICE_CLASS(klass); + + dc->realize = ps2_mouse_realize; + device_class_set_parent_reset(dc, ps2_mouse_reset, + &ps2dc->parent_reset); + dc->vmsd = &vmstate_ps2_mouse; +} + +static const TypeInfo ps2_mouse_info = { + .name = TYPE_PS2_MOUSE_DEVICE, + .parent = TYPE_PS2_DEVICE, + .instance_size = sizeof(PS2MouseState), + .class_init = ps2_mouse_class_init +}; + +static void ps2_init(Object *obj) +{ + PS2State *s = PS2_DEVICE(obj); + + qdev_init_gpio_out(DEVICE(obj), &s->irq, 1); +} + +static void ps2_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = ps2_reset; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); +} + +static const TypeInfo ps2_info = { + .name = TYPE_PS2_DEVICE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_init = ps2_init, + .instance_size = sizeof(PS2State), + .class_init = ps2_class_init, + .class_size = sizeof(PS2DeviceClass), + .abstract = true +}; + +static void ps2_register_types(void) +{ + type_register_static(&ps2_info); + type_register_static(&ps2_kbd_info); + type_register_static(&ps2_mouse_info); +} + +type_init(ps2_register_types) diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index 96dc6ab32d..1eb8bd5018 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -136,11 +136,11 @@ static void mips_jazz_init(MachineState *machine, MemoryRegion *isa_mem = g_new(MemoryRegion, 1); MemoryRegion *isa_io = g_new(MemoryRegion, 1); MemoryRegion *rtc = g_new(MemoryRegion, 1); - MemoryRegion *i8042 = g_new(MemoryRegion, 1); MemoryRegion *dma_dummy = g_new(MemoryRegion, 1); MemoryRegion *dp8393x_prom = g_new(MemoryRegion, 1); NICInfo *nd; DeviceState *dev, *rc4030; + MMIOKBDState *i8042; SysBusDevice *sysbus; ISABus *isa_bus; ISADevice *pit; @@ -361,9 +361,12 @@ static void mips_jazz_init(MachineState *machine, memory_region_add_subregion(address_space, 0x80004000, rtc); /* Keyboard (i8042) */ - i8042_mm_init(qdev_get_gpio_in(rc4030, 6), qdev_get_gpio_in(rc4030, 7), - i8042, 0x1000, 0x1); - memory_region_add_subregion(address_space, 0x80005000, i8042); + i8042 = i8042_mm_init(qdev_get_gpio_in(rc4030, 6), + qdev_get_gpio_in(rc4030, 7), + 0x1000, 0x1); + memory_region_add_subregion(address_space, 0x80005000, + sysbus_mmio_get_region(SYS_BUS_DEVICE(i8042), + 0)); /* Serial ports */ serial_mm_init(address_space, 0x80006000, 0, diff --git a/include/hw/input/i8042.h b/include/hw/input/i8042.h index e070f546e4..ca933d8e1b 100644 --- a/include/hw/input/i8042.h +++ b/include/hw/input/i8042.h @@ -9,17 +9,86 @@ #define HW_INPUT_I8042_H #include "hw/isa/isa.h" +#include "hw/sysbus.h" #include "qom/object.h" +#define I8042_KBD_IRQ 0 +#define I8042_MOUSE_IRQ 1 + +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; + uint8_t cbdata; + uint8_t pending_tmp; + void *kbd; + void *mouse; + QEMUTimer *throttle_timer; + + qemu_irq irqs[2]; + qemu_irq a20_out; + hwaddr mask; +} KBDState; + +/* + * QEMU interface: + * + Named GPIO input "ps2-kbd-input-irq": set to 1 if the downstream PS2 + * keyboard device has asserted its irq + * + Named GPIO input "ps2-mouse-input-irq": set to 1 if the downstream PS2 + * mouse device has asserted its irq + * + Named GPIO output "a20": A20 line for x86 PCs + * + Unnamed GPIO output 0-1: i8042 output irqs for keyboard (0) or mouse (1) + */ + #define TYPE_I8042 "i8042" OBJECT_DECLARE_SIMPLE_TYPE(ISAKBDState, I8042) +struct ISAKBDState { + ISADevice parent_obj; + + KBDState kbd; + bool kbd_throttle; + MemoryRegion io[2]; + uint8_t kbd_irq; + uint8_t mouse_irq; +}; + +/* + * QEMU interface: + * + sysbus MMIO region 0: MemoryRegion defining the command/status/data + * registers (access determined by mask property and access type) + * + Named GPIO input "ps2-kbd-input-irq": set to 1 if the downstream PS2 + * keyboard device has asserted its irq + * + Named GPIO input "ps2-mouse-input-irq": set to 1 if the downstream PS2 + * mouse device has asserted its irq + * + Unnamed GPIO output 0-1: i8042 output irqs for keyboard (0) or mouse (1) + */ + +#define TYPE_I8042_MMIO "i8042-mmio" +OBJECT_DECLARE_SIMPLE_TYPE(MMIOKBDState, I8042_MMIO) + +struct MMIOKBDState { + SysBusDevice parent_obj; + + KBDState kbd; + uint32_t size; + MemoryRegion region; +}; + #define I8042_A20_LINE "a20" -void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, - MemoryRegion *region, ram_addr_t size, - hwaddr mask); +MMIOKBDState *i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, + ram_addr_t size, hwaddr mask); void i8042_isa_mouse_fake_event(ISAKBDState *isa); void i8042_setup_a20_line(ISADevice *dev, qemu_irq a20_out); diff --git a/include/hw/input/lasips2.h b/include/hw/input/lasips2.h index 0cd7b59064..03f0c9e9f9 100644 --- a/include/hw/input/lasips2.h +++ b/include/hw/input/lasips2.h @@ -4,13 +4,50 @@ * Copyright (c) 2019 Sven Schnelle * */ + +/* + * QEMU interface: + * + sysbus MMIO region 0: MemoryRegion defining the LASI PS2 keyboard + * registers + * + sysbus MMIO region 1: MemoryRegion defining the LASI PS2 mouse + * registers + * + sysbus IRQ 0: LASI PS2 output irq + * + Named GPIO input "ps2-kbd-input-irq": set to 1 if the downstream PS2 + * keyboard device has asserted its irq + * + Named GPIO input "ps2-mouse-input-irq": set to 1 if the downstream PS2 + * mouse device has asserted its irq + */ + #ifndef HW_INPUT_LASIPS2_H #define HW_INPUT_LASIPS2_H #include "exec/hwaddr.h" +#include "hw/sysbus.h" + +struct LASIPS2State; +typedef struct LASIPS2Port { + struct LASIPS2State *parent; + MemoryRegion reg; + void *dev; + uint8_t id; + uint8_t control; + uint8_t buf; + bool loopback_rbne; + bool irq; +} LASIPS2Port; + +struct LASIPS2State { + SysBusDevice parent_obj; + + hwaddr base; + LASIPS2Port kbd; + LASIPS2Port mouse; + qemu_irq irq; +}; #define TYPE_LASIPS2 "lasips2" +OBJECT_DECLARE_SIMPLE_TYPE(LASIPS2State, LASIPS2) -void lasips2_init(MemoryRegion *address_space, hwaddr base, qemu_irq irq); +LASIPS2State *lasips2_initfn(hwaddr base, qemu_irq irq); #endif /* HW_INPUT_LASIPS2_H */ diff --git a/include/hw/input/ps2.h b/include/hw/input/ps2.h index 35d983897a..a78619d8cb 100644 --- a/include/hw/input/ps2.h +++ b/include/hw/input/ps2.h @@ -25,28 +25,91 @@ #ifndef HW_PS2_H #define HW_PS2_H +#include "hw/sysbus.h" + #define PS2_MOUSE_BUTTON_LEFT 0x01 #define PS2_MOUSE_BUTTON_RIGHT 0x02 #define PS2_MOUSE_BUTTON_MIDDLE 0x04 #define PS2_MOUSE_BUTTON_SIDE 0x08 #define PS2_MOUSE_BUTTON_EXTRA 0x10 -typedef struct PS2State PS2State; +struct PS2DeviceClass { + SysBusDeviceClass parent_class; + + DeviceReset parent_reset; +}; + +/* + * PS/2 buffer size. Keep 256 bytes for compatibility with + * older QEMU versions. + */ +#define PS2_BUFFER_SIZE 256 + +typedef struct { + uint8_t data[PS2_BUFFER_SIZE]; + int rptr, wptr, cwptr, count; +} PS2Queue; + +/* Output IRQ */ +#define PS2_DEVICE_IRQ 0 + +struct PS2State { + SysBusDevice parent_obj; + + PS2Queue queue; + int32_t write_cmd; + qemu_irq irq; +}; + +#define TYPE_PS2_DEVICE "ps2-device" +OBJECT_DECLARE_TYPE(PS2State, PS2DeviceClass, PS2_DEVICE) + +struct PS2KbdState { + PS2State parent_obj; + + int scan_enabled; + int translate; + int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */ + int ledstate; + bool need_high_bit; + unsigned int modifiers; /* bitmask of MOD_* constants above */ +}; + +#define TYPE_PS2_KBD_DEVICE "ps2-kbd" +OBJECT_DECLARE_SIMPLE_TYPE(PS2KbdState, PS2_KBD_DEVICE) + +struct PS2MouseState { + PS2State parent_obj; + + uint8_t mouse_status; + uint8_t mouse_resolution; + uint8_t mouse_sample_rate; + uint8_t mouse_wrap; + uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */ + uint8_t mouse_detect_state; + int mouse_dx; /* current values, needed for 'poll' mode */ + int mouse_dy; + int mouse_dz; + int mouse_dw; + uint8_t mouse_buttons; +}; + +#define TYPE_PS2_MOUSE_DEVICE "ps2-mouse" +OBJECT_DECLARE_SIMPLE_TYPE(PS2MouseState, PS2_MOUSE_DEVICE) /* ps2.c */ -void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg); -void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg); -void ps2_write_mouse(void *, int val); -void ps2_write_keyboard(void *, int val); +void *ps2_kbd_init(void); +void *ps2_mouse_init(void); +void ps2_write_mouse(PS2MouseState *s, int val); +void ps2_write_keyboard(PS2KbdState *s, int val); uint32_t ps2_read_data(PS2State *s); void ps2_queue_noirq(PS2State *s, int b); -void ps2_raise_irq(PS2State *s); void ps2_queue(PS2State *s, int b); void ps2_queue_2(PS2State *s, int b1, int b2); void ps2_queue_3(PS2State *s, int b1, int b2, int b3); void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4); -void ps2_keyboard_set_translation(void *opaque, int mode); -void ps2_mouse_fake_event(void *opaque); +void ps2_keyboard_set_translation(PS2KbdState *s, int mode); +void ps2_mouse_fake_event(PS2MouseState *s); int ps2_queue_empty(PS2State *s); #endif /* HW_PS2_H */