2 * QEMU HP Lasi PS/2 interface emulation
4 * Copyright (c) 2019 Sven Schnelle
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
24 #include "qemu/osdep.h"
26 #include "hw/qdev-properties.h"
27 #include "hw/sysbus.h"
28 #include "hw/input/ps2.h"
29 #include "hw/input/lasips2.h"
30 #include "exec/hwaddr.h"
32 #include "exec/address-spaces.h"
33 #include "migration/vmstate.h"
35 #include "qapi/error.h"
38 static const VMStateDescription vmstate_lasips2_port
= {
39 .name
= "lasips2-port",
41 .minimum_version_id
= 1,
42 .fields
= (const VMStateField
[]) {
43 VMSTATE_UINT8(control
, LASIPS2Port
),
44 VMSTATE_UINT8(buf
, LASIPS2Port
),
45 VMSTATE_BOOL(loopback_rbne
, LASIPS2Port
),
50 static const VMStateDescription vmstate_lasips2
= {
53 .minimum_version_id
= 1,
54 .fields
= (const VMStateField
[]) {
55 VMSTATE_UINT8(int_status
, LASIPS2State
),
56 VMSTATE_STRUCT(kbd_port
.parent_obj
, LASIPS2State
, 1,
57 vmstate_lasips2_port
, LASIPS2Port
),
58 VMSTATE_STRUCT(mouse_port
.parent_obj
, LASIPS2State
, 1,
59 vmstate_lasips2_port
, LASIPS2Port
),
74 } lasips2_write_reg_t
;
77 LASIPS2_CONTROL_ENABLE
= 0x01,
78 LASIPS2_CONTROL_LOOPBACK
= 0x02,
79 LASIPS2_CONTROL_DIAG
= 0x20,
80 LASIPS2_CONTROL_DATDIR
= 0x40,
81 LASIPS2_CONTROL_CLKDIR
= 0x80,
82 } lasips2_control_reg_t
;
85 LASIPS2_STATUS_RBNE
= 0x01,
86 LASIPS2_STATUS_TBNE
= 0x02,
87 LASIPS2_STATUS_TERR
= 0x04,
88 LASIPS2_STATUS_PERR
= 0x08,
89 LASIPS2_STATUS_CMPINTR
= 0x10,
90 LASIPS2_STATUS_DATSHD
= 0x40,
91 LASIPS2_STATUS_CLKSHD
= 0x80,
92 } lasips2_status_reg_t
;
94 static const char *lasips2_read_reg_name(uint64_t addr
)
100 case REG_PS2_RCVDATA
:
101 return " PS2_RCVDATA";
103 case REG_PS2_CONTROL
:
104 return " PS2_CONTROL";
107 return " PS2_STATUS";
114 static const char *lasips2_write_reg_name(uint64_t addr
)
116 switch (addr
& 0x0c) {
120 case REG_PS2_XMTDATA
:
121 return " PS2_XMTDATA";
123 case REG_PS2_CONTROL
:
124 return " PS2_CONTROL";
131 static void lasips2_update_irq(LASIPS2State
*s
)
133 int level
= s
->int_status
? 1 : 0;
135 trace_lasips2_intr(level
);
136 qemu_set_irq(s
->irq
, level
);
139 static void lasips2_set_irq(void *opaque
, int n
, int level
)
141 LASIPS2State
*s
= LASIPS2(opaque
);
144 s
->int_status
|= BIT(n
);
146 s
->int_status
&= ~BIT(n
);
149 lasips2_update_irq(s
);
152 static void lasips2_reg_write(void *opaque
, hwaddr addr
, uint64_t val
,
155 LASIPS2Port
*lp
= LASIPS2_PORT(opaque
);
157 trace_lasips2_reg_write(size
, lp
->id
, addr
,
158 lasips2_write_reg_name(addr
), val
);
160 switch (addr
& 0xc) {
161 case REG_PS2_CONTROL
:
165 case REG_PS2_XMTDATA
:
166 if (lp
->control
& LASIPS2_CONTROL_LOOPBACK
) {
168 lp
->loopback_rbne
= true;
169 qemu_set_irq(lp
->irq
, 1);
174 ps2_write_mouse(PS2_MOUSE_DEVICE(lp
->ps2dev
), val
);
176 ps2_write_keyboard(PS2_KBD_DEVICE(lp
->ps2dev
), val
);
184 qemu_log_mask(LOG_UNIMP
, "%s: unknown register 0x%02" HWADDR_PRIx
"\n",
190 static uint64_t lasips2_reg_read(void *opaque
, hwaddr addr
, unsigned size
)
192 LASIPS2Port
*lp
= LASIPS2_PORT(opaque
);
195 switch (addr
& 0xc) {
200 case REG_PS2_RCVDATA
:
201 if (lp
->control
& LASIPS2_CONTROL_LOOPBACK
) {
202 lp
->loopback_rbne
= false;
203 qemu_set_irq(lp
->irq
, 0);
208 ret
= ps2_read_data(lp
->ps2dev
);
211 case REG_PS2_CONTROL
:
216 ret
= LASIPS2_STATUS_DATSHD
| LASIPS2_STATUS_CLKSHD
;
218 if (lp
->control
& LASIPS2_CONTROL_DIAG
) {
219 if (!(lp
->control
& LASIPS2_CONTROL_DATDIR
)) {
220 ret
&= ~LASIPS2_STATUS_DATSHD
;
223 if (!(lp
->control
& LASIPS2_CONTROL_CLKDIR
)) {
224 ret
&= ~LASIPS2_STATUS_CLKSHD
;
228 if (lp
->control
& LASIPS2_CONTROL_LOOPBACK
) {
229 if (lp
->loopback_rbne
) {
230 ret
|= LASIPS2_STATUS_RBNE
;
233 if (!ps2_queue_empty(lp
->ps2dev
)) {
234 ret
|= LASIPS2_STATUS_RBNE
;
238 if (lp
->lasips2
->int_status
) {
239 ret
|= LASIPS2_STATUS_CMPINTR
;
244 qemu_log_mask(LOG_UNIMP
, "%s: unknown register 0x%02" HWADDR_PRIx
"\n",
249 trace_lasips2_reg_read(size
, lp
->id
, addr
,
250 lasips2_read_reg_name(addr
), ret
);
254 static const MemoryRegionOps lasips2_reg_ops
= {
255 .read
= lasips2_reg_read
,
256 .write
= lasips2_reg_write
,
258 .min_access_size
= 1,
259 .max_access_size
= 4,
261 .endianness
= DEVICE_BIG_ENDIAN
,
264 static void lasips2_realize(DeviceState
*dev
, Error
**errp
)
266 LASIPS2State
*s
= LASIPS2(dev
);
269 lp
= LASIPS2_PORT(&s
->kbd_port
);
270 if (!(qdev_realize(DEVICE(lp
), NULL
, errp
))) {
274 qdev_connect_gpio_out(DEVICE(lp
), 0,
275 qdev_get_gpio_in_named(dev
, "lasips2-port-input-irq",
278 lp
= LASIPS2_PORT(&s
->mouse_port
);
279 if (!(qdev_realize(DEVICE(lp
), NULL
, errp
))) {
283 qdev_connect_gpio_out(DEVICE(lp
), 0,
284 qdev_get_gpio_in_named(dev
, "lasips2-port-input-irq",
288 static void lasips2_init(Object
*obj
)
290 LASIPS2State
*s
= LASIPS2(obj
);
293 object_initialize_child(obj
, "lasips2-kbd-port", &s
->kbd_port
,
294 TYPE_LASIPS2_KBD_PORT
);
295 object_initialize_child(obj
, "lasips2-mouse-port", &s
->mouse_port
,
296 TYPE_LASIPS2_MOUSE_PORT
);
298 lp
= LASIPS2_PORT(&s
->kbd_port
);
299 sysbus_init_mmio(SYS_BUS_DEVICE(obj
), &lp
->reg
);
300 lp
= LASIPS2_PORT(&s
->mouse_port
);
301 sysbus_init_mmio(SYS_BUS_DEVICE(obj
), &lp
->reg
);
303 sysbus_init_irq(SYS_BUS_DEVICE(obj
), &s
->irq
);
305 qdev_init_gpio_in_named(DEVICE(obj
), lasips2_set_irq
,
306 "lasips2-port-input-irq", 2);
309 static void lasips2_class_init(ObjectClass
*klass
, void *data
)
311 DeviceClass
*dc
= DEVICE_CLASS(klass
);
313 dc
->realize
= lasips2_realize
;
314 dc
->vmsd
= &vmstate_lasips2
;
315 set_bit(DEVICE_CATEGORY_INPUT
, dc
->categories
);
318 static const TypeInfo lasips2_info
= {
319 .name
= TYPE_LASIPS2
,
320 .parent
= TYPE_SYS_BUS_DEVICE
,
321 .instance_init
= lasips2_init
,
322 .instance_size
= sizeof(LASIPS2State
),
323 .class_init
= lasips2_class_init
,
326 static void lasips2_port_set_irq(void *opaque
, int n
, int level
)
328 LASIPS2Port
*s
= LASIPS2_PORT(opaque
);
330 qemu_set_irq(s
->irq
, level
);
333 static void lasips2_port_realize(DeviceState
*dev
, Error
**errp
)
335 LASIPS2Port
*s
= LASIPS2_PORT(dev
);
337 qdev_connect_gpio_out(DEVICE(s
->ps2dev
), PS2_DEVICE_IRQ
,
338 qdev_get_gpio_in_named(dev
, "ps2-input-irq", 0));
341 static void lasips2_port_init(Object
*obj
)
343 LASIPS2Port
*s
= LASIPS2_PORT(obj
);
345 qdev_init_gpio_out(DEVICE(obj
), &s
->irq
, 1);
346 qdev_init_gpio_in_named(DEVICE(obj
), lasips2_port_set_irq
,
350 static void lasips2_port_class_init(ObjectClass
*klass
, void *data
)
352 DeviceClass
*dc
= DEVICE_CLASS(klass
);
355 * The PS/2 mouse port is integreal part of LASI and can not be
356 * created by users without LASI.
358 dc
->user_creatable
= false;
359 dc
->realize
= lasips2_port_realize
;
362 static const TypeInfo lasips2_port_info
= {
363 .name
= TYPE_LASIPS2_PORT
,
364 .parent
= TYPE_DEVICE
,
365 .instance_init
= lasips2_port_init
,
366 .instance_size
= sizeof(LASIPS2Port
),
367 .class_init
= lasips2_port_class_init
,
368 .class_size
= sizeof(LASIPS2PortDeviceClass
),
372 static void lasips2_kbd_port_realize(DeviceState
*dev
, Error
**errp
)
374 LASIPS2KbdPort
*s
= LASIPS2_KBD_PORT(dev
);
375 LASIPS2Port
*lp
= LASIPS2_PORT(dev
);
376 LASIPS2PortDeviceClass
*lpdc
= LASIPS2_PORT_GET_CLASS(lp
);
378 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->kbd
), errp
)) {
382 lp
->ps2dev
= PS2_DEVICE(&s
->kbd
);
383 lpdc
->parent_realize(dev
, errp
);
386 static void lasips2_kbd_port_init(Object
*obj
)
388 LASIPS2KbdPort
*s
= LASIPS2_KBD_PORT(obj
);
389 LASIPS2Port
*lp
= LASIPS2_PORT(obj
);
391 memory_region_init_io(&lp
->reg
, obj
, &lasips2_reg_ops
, lp
, "lasips2-kbd",
394 object_initialize_child(obj
, "kbd", &s
->kbd
, TYPE_PS2_KBD_DEVICE
);
397 lp
->lasips2
= container_of(s
, LASIPS2State
, kbd_port
);
400 static void lasips2_kbd_port_class_init(ObjectClass
*klass
, void *data
)
402 DeviceClass
*dc
= DEVICE_CLASS(klass
);
403 LASIPS2PortDeviceClass
*lpdc
= LASIPS2_PORT_CLASS(klass
);
406 * The PS/2 keyboard port is integreal part of LASI and can not be
407 * created by users without LASI.
409 dc
->user_creatable
= false;
410 device_class_set_parent_realize(dc
, lasips2_kbd_port_realize
,
411 &lpdc
->parent_realize
);
414 static const TypeInfo lasips2_kbd_port_info
= {
415 .name
= TYPE_LASIPS2_KBD_PORT
,
416 .parent
= TYPE_LASIPS2_PORT
,
417 .instance_size
= sizeof(LASIPS2KbdPort
),
418 .instance_init
= lasips2_kbd_port_init
,
419 .class_init
= lasips2_kbd_port_class_init
,
422 static void lasips2_mouse_port_realize(DeviceState
*dev
, Error
**errp
)
424 LASIPS2MousePort
*s
= LASIPS2_MOUSE_PORT(dev
);
425 LASIPS2Port
*lp
= LASIPS2_PORT(dev
);
426 LASIPS2PortDeviceClass
*lpdc
= LASIPS2_PORT_GET_CLASS(lp
);
428 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->mouse
), errp
)) {
432 lp
->ps2dev
= PS2_DEVICE(&s
->mouse
);
433 lpdc
->parent_realize(dev
, errp
);
436 static void lasips2_mouse_port_init(Object
*obj
)
438 LASIPS2MousePort
*s
= LASIPS2_MOUSE_PORT(obj
);
439 LASIPS2Port
*lp
= LASIPS2_PORT(obj
);
441 memory_region_init_io(&lp
->reg
, obj
, &lasips2_reg_ops
, lp
, "lasips2-mouse",
444 object_initialize_child(obj
, "mouse", &s
->mouse
, TYPE_PS2_MOUSE_DEVICE
);
447 lp
->lasips2
= container_of(s
, LASIPS2State
, mouse_port
);
450 static void lasips2_mouse_port_class_init(ObjectClass
*klass
, void *data
)
452 DeviceClass
*dc
= DEVICE_CLASS(klass
);
453 LASIPS2PortDeviceClass
*lpdc
= LASIPS2_PORT_CLASS(klass
);
455 device_class_set_parent_realize(dc
, lasips2_mouse_port_realize
,
456 &lpdc
->parent_realize
);
459 static const TypeInfo lasips2_mouse_port_info
= {
460 .name
= TYPE_LASIPS2_MOUSE_PORT
,
461 .parent
= TYPE_LASIPS2_PORT
,
462 .instance_size
= sizeof(LASIPS2MousePort
),
463 .instance_init
= lasips2_mouse_port_init
,
464 .class_init
= lasips2_mouse_port_class_init
,
467 static void lasips2_register_types(void)
469 type_register_static(&lasips2_info
);
470 type_register_static(&lasips2_port_info
);
471 type_register_static(&lasips2_kbd_port_info
);
472 type_register_static(&lasips2_mouse_port_info
);
475 type_init(lasips2_register_types
)