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
= {
41 .minimum_version_id
= 0,
42 .fields
= (VMStateField
[]) {
43 VMSTATE_UINT8(kbd_port
.parent_obj
.control
, LASIPS2State
),
44 VMSTATE_UINT8(kbd_port
.parent_obj
.id
, LASIPS2State
),
45 VMSTATE_BOOL(kbd_port
.parent_obj
.birq
, LASIPS2State
),
46 VMSTATE_UINT8(mouse_port
.parent_obj
.control
, LASIPS2State
),
47 VMSTATE_UINT8(mouse_port
.parent_obj
.id
, LASIPS2State
),
48 VMSTATE_BOOL(mouse_port
.parent_obj
.birq
, LASIPS2State
),
63 } lasips2_write_reg_t
;
66 LASIPS2_CONTROL_ENABLE
= 0x01,
67 LASIPS2_CONTROL_LOOPBACK
= 0x02,
68 LASIPS2_CONTROL_DIAG
= 0x20,
69 LASIPS2_CONTROL_DATDIR
= 0x40,
70 LASIPS2_CONTROL_CLKDIR
= 0x80,
71 } lasips2_control_reg_t
;
74 LASIPS2_STATUS_RBNE
= 0x01,
75 LASIPS2_STATUS_TBNE
= 0x02,
76 LASIPS2_STATUS_TERR
= 0x04,
77 LASIPS2_STATUS_PERR
= 0x08,
78 LASIPS2_STATUS_CMPINTR
= 0x10,
79 LASIPS2_STATUS_DATSHD
= 0x40,
80 LASIPS2_STATUS_CLKSHD
= 0x80,
81 } lasips2_status_reg_t
;
83 static const char *lasips2_read_reg_name(uint64_t addr
)
90 return " PS2_RCVDATA";
93 return " PS2_CONTROL";
103 static const char *lasips2_write_reg_name(uint64_t addr
)
105 switch (addr
& 0x0c) {
109 case REG_PS2_XMTDATA
:
110 return " PS2_XMTDATA";
112 case REG_PS2_CONTROL
:
113 return " PS2_CONTROL";
120 static void lasips2_update_irq(LASIPS2State
*s
)
122 trace_lasips2_intr(s
->kbd_port
.parent_obj
.birq
|
123 s
->mouse_port
.parent_obj
.birq
);
124 qemu_set_irq(s
->irq
, s
->kbd_port
.parent_obj
.birq
|
125 s
->mouse_port
.parent_obj
.birq
);
128 static void lasips2_set_irq(void *opaque
, int n
, int level
)
130 LASIPS2State
*s
= LASIPS2(opaque
);
133 s
->int_status
|= BIT(n
);
135 s
->int_status
&= ~BIT(n
);
138 lasips2_update_irq(s
);
141 static void lasips2_reg_write(void *opaque
, hwaddr addr
, uint64_t val
,
144 LASIPS2Port
*port
= opaque
;
146 trace_lasips2_reg_write(size
, port
->id
, addr
,
147 lasips2_write_reg_name(addr
), val
);
149 switch (addr
& 0xc) {
150 case REG_PS2_CONTROL
:
154 case REG_PS2_XMTDATA
:
155 if (port
->control
& LASIPS2_CONTROL_LOOPBACK
) {
158 port
->loopback_rbne
= true;
159 lasips2_update_irq(port
->parent
);
164 ps2_write_mouse(PS2_MOUSE_DEVICE(port
->ps2dev
), val
);
166 ps2_write_keyboard(PS2_KBD_DEVICE(port
->ps2dev
), val
);
174 qemu_log_mask(LOG_UNIMP
, "%s: unknown register 0x%02" HWADDR_PRIx
"\n",
180 static uint64_t lasips2_reg_read(void *opaque
, hwaddr addr
, unsigned size
)
182 LASIPS2Port
*port
= opaque
;
185 switch (addr
& 0xc) {
190 case REG_PS2_RCVDATA
:
191 if (port
->control
& LASIPS2_CONTROL_LOOPBACK
) {
193 port
->loopback_rbne
= false;
194 lasips2_update_irq(port
->parent
);
199 ret
= ps2_read_data(port
->ps2dev
);
202 case REG_PS2_CONTROL
:
207 ret
= LASIPS2_STATUS_DATSHD
| LASIPS2_STATUS_CLKSHD
;
209 if (port
->control
& LASIPS2_CONTROL_DIAG
) {
210 if (!(port
->control
& LASIPS2_CONTROL_DATDIR
)) {
211 ret
&= ~LASIPS2_STATUS_DATSHD
;
214 if (!(port
->control
& LASIPS2_CONTROL_CLKDIR
)) {
215 ret
&= ~LASIPS2_STATUS_CLKSHD
;
219 if (port
->control
& LASIPS2_CONTROL_LOOPBACK
) {
220 if (port
->loopback_rbne
) {
221 ret
|= LASIPS2_STATUS_RBNE
;
224 if (!ps2_queue_empty(port
->ps2dev
)) {
225 ret
|= LASIPS2_STATUS_RBNE
;
229 if (port
->parent
->kbd_port
.parent_obj
.birq
||
230 port
->parent
->mouse_port
.parent_obj
.birq
) {
231 ret
|= LASIPS2_STATUS_CMPINTR
;
236 qemu_log_mask(LOG_UNIMP
, "%s: unknown register 0x%02" HWADDR_PRIx
"\n",
241 trace_lasips2_reg_read(size
, port
->id
, addr
,
242 lasips2_read_reg_name(addr
), ret
);
246 static const MemoryRegionOps lasips2_reg_ops
= {
247 .read
= lasips2_reg_read
,
248 .write
= lasips2_reg_write
,
250 .min_access_size
= 1,
251 .max_access_size
= 4,
253 .endianness
= DEVICE_NATIVE_ENDIAN
,
256 static void lasips2_set_kbd_irq(void *opaque
, int n
, int level
)
258 LASIPS2State
*s
= LASIPS2(opaque
);
259 LASIPS2Port
*port
= LASIPS2_PORT(&s
->kbd_port
);
262 lasips2_update_irq(port
->parent
);
265 static void lasips2_set_mouse_irq(void *opaque
, int n
, int level
)
267 LASIPS2State
*s
= LASIPS2(opaque
);
268 LASIPS2Port
*port
= LASIPS2_PORT(&s
->mouse_port
);
271 lasips2_update_irq(port
->parent
);
274 static void lasips2_realize(DeviceState
*dev
, Error
**errp
)
276 LASIPS2State
*s
= LASIPS2(dev
);
279 lp
= LASIPS2_PORT(&s
->kbd_port
);
280 if (!(qdev_realize(DEVICE(lp
), NULL
, errp
))) {
284 qdev_connect_gpio_out(DEVICE(lp
->ps2dev
), PS2_DEVICE_IRQ
,
285 qdev_get_gpio_in_named(dev
, "ps2-kbd-input-irq",
288 lp
= LASIPS2_PORT(&s
->mouse_port
);
289 if (!(qdev_realize(DEVICE(lp
), NULL
, errp
))) {
293 qdev_connect_gpio_out(DEVICE(lp
->ps2dev
), PS2_DEVICE_IRQ
,
294 qdev_get_gpio_in_named(dev
, "ps2-mouse-input-irq",
298 static void lasips2_init(Object
*obj
)
300 LASIPS2State
*s
= LASIPS2(obj
);
303 object_initialize_child(obj
, "lasips2-kbd-port", &s
->kbd_port
,
304 TYPE_LASIPS2_KBD_PORT
);
305 object_initialize_child(obj
, "lasips2-mouse-port", &s
->mouse_port
,
306 TYPE_LASIPS2_MOUSE_PORT
);
308 lp
= LASIPS2_PORT(&s
->kbd_port
);
309 sysbus_init_mmio(SYS_BUS_DEVICE(obj
), &lp
->reg
);
310 lp
= LASIPS2_PORT(&s
->mouse_port
);
311 sysbus_init_mmio(SYS_BUS_DEVICE(obj
), &lp
->reg
);
313 sysbus_init_irq(SYS_BUS_DEVICE(obj
), &s
->irq
);
315 qdev_init_gpio_in_named(DEVICE(obj
), lasips2_set_kbd_irq
,
316 "ps2-kbd-input-irq", 1);
317 qdev_init_gpio_in_named(DEVICE(obj
), lasips2_set_mouse_irq
,
318 "ps2-mouse-input-irq", 1);
319 qdev_init_gpio_in_named(DEVICE(obj
), lasips2_set_irq
,
320 "lasips2-port-input-irq", 2);
323 static void lasips2_class_init(ObjectClass
*klass
, void *data
)
325 DeviceClass
*dc
= DEVICE_CLASS(klass
);
327 dc
->realize
= lasips2_realize
;
328 dc
->vmsd
= &vmstate_lasips2
;
329 set_bit(DEVICE_CATEGORY_INPUT
, dc
->categories
);
332 static const TypeInfo lasips2_info
= {
333 .name
= TYPE_LASIPS2
,
334 .parent
= TYPE_SYS_BUS_DEVICE
,
335 .instance_init
= lasips2_init
,
336 .instance_size
= sizeof(LASIPS2State
),
337 .class_init
= lasips2_class_init
,
340 static void lasips2_port_set_irq(void *opaque
, int n
, int level
)
342 LASIPS2Port
*s
= LASIPS2_PORT(opaque
);
344 qemu_set_irq(s
->irq
, level
);
347 static void lasips2_port_realize(DeviceState
*dev
, Error
**errp
)
349 LASIPS2Port
*s
= LASIPS2_PORT(dev
);
351 qdev_connect_gpio_out(DEVICE(s
->ps2dev
), PS2_DEVICE_IRQ
,
352 qdev_get_gpio_in_named(dev
, "ps2-input-irq", 0));
355 static void lasips2_port_init(Object
*obj
)
357 LASIPS2Port
*s
= LASIPS2_PORT(obj
);
359 qdev_init_gpio_out(DEVICE(obj
), &s
->irq
, 1);
360 qdev_init_gpio_in_named(DEVICE(obj
), lasips2_port_set_irq
,
364 static void lasips2_port_class_init(ObjectClass
*klass
, void *data
)
366 DeviceClass
*dc
= DEVICE_CLASS(klass
);
368 dc
->realize
= lasips2_port_realize
;
371 static const TypeInfo lasips2_port_info
= {
372 .name
= TYPE_LASIPS2_PORT
,
373 .parent
= TYPE_DEVICE
,
374 .instance_init
= lasips2_port_init
,
375 .instance_size
= sizeof(LASIPS2Port
),
376 .class_init
= lasips2_port_class_init
,
377 .class_size
= sizeof(LASIPS2PortDeviceClass
),
381 static void lasips2_kbd_port_realize(DeviceState
*dev
, Error
**errp
)
383 LASIPS2Port
*lp
= LASIPS2_PORT(dev
);
385 lp
->ps2dev
= ps2_kbd_init();
388 static void lasips2_kbd_port_init(Object
*obj
)
390 LASIPS2KbdPort
*s
= LASIPS2_KBD_PORT(obj
);
391 LASIPS2Port
*lp
= LASIPS2_PORT(obj
);
393 memory_region_init_io(&lp
->reg
, obj
, &lasips2_reg_ops
, lp
, "lasips2-kbd",
396 lp
->parent
= container_of(s
, LASIPS2State
, kbd_port
);
399 static void lasips2_kbd_port_class_init(ObjectClass
*klass
, void *data
)
401 DeviceClass
*dc
= DEVICE_CLASS(klass
);
402 LASIPS2PortDeviceClass
*lpdc
= LASIPS2_PORT_CLASS(klass
);
404 device_class_set_parent_realize(dc
, lasips2_kbd_port_realize
,
405 &lpdc
->parent_realize
);
408 static const TypeInfo lasips2_kbd_port_info
= {
409 .name
= TYPE_LASIPS2_KBD_PORT
,
410 .parent
= TYPE_LASIPS2_PORT
,
411 .instance_size
= sizeof(LASIPS2KbdPort
),
412 .instance_init
= lasips2_kbd_port_init
,
413 .class_init
= lasips2_kbd_port_class_init
,
416 static void lasips2_mouse_port_realize(DeviceState
*dev
, Error
**errp
)
418 LASIPS2Port
*lp
= LASIPS2_PORT(dev
);
420 lp
->ps2dev
= ps2_mouse_init();
423 static void lasips2_mouse_port_init(Object
*obj
)
425 LASIPS2MousePort
*s
= LASIPS2_MOUSE_PORT(obj
);
426 LASIPS2Port
*lp
= LASIPS2_PORT(obj
);
428 memory_region_init_io(&lp
->reg
, obj
, &lasips2_reg_ops
, lp
, "lasips2-mouse",
431 lp
->parent
= container_of(s
, LASIPS2State
, mouse_port
);
434 static void lasips2_mouse_port_class_init(ObjectClass
*klass
, void *data
)
436 DeviceClass
*dc
= DEVICE_CLASS(klass
);
437 LASIPS2PortDeviceClass
*lpdc
= LASIPS2_PORT_CLASS(klass
);
439 device_class_set_parent_realize(dc
, lasips2_mouse_port_realize
,
440 &lpdc
->parent_realize
);
443 static const TypeInfo lasips2_mouse_port_info
= {
444 .name
= TYPE_LASIPS2_MOUSE_PORT
,
445 .parent
= TYPE_LASIPS2_PORT
,
446 .instance_size
= sizeof(LASIPS2MousePort
),
447 .instance_init
= lasips2_mouse_port_init
,
448 .class_init
= lasips2_mouse_port_class_init
,
451 static void lasips2_register_types(void)
453 type_register_static(&lasips2_info
);
454 type_register_static(&lasips2_port_info
);
455 type_register_static(&lasips2_kbd_port_info
);
456 type_register_static(&lasips2_mouse_port_info
);
459 type_init(lasips2_register_types
)