4 #include "hw/spapr_vio.h"
6 #define VTERM_BUFSIZE 16
8 typedef struct VIOsPAPRVTYDevice
{
10 CharDriverState
*chardev
;
12 uint8_t buf
[VTERM_BUFSIZE
];
15 static int vty_can_receive(void *opaque
)
17 VIOsPAPRVTYDevice
*dev
= (VIOsPAPRVTYDevice
*)opaque
;
19 return (dev
->in
- dev
->out
) < VTERM_BUFSIZE
;
22 static void vty_receive(void *opaque
, const uint8_t *buf
, int size
)
24 VIOsPAPRVTYDevice
*dev
= (VIOsPAPRVTYDevice
*)opaque
;
27 if ((dev
->in
== dev
->out
) && size
) {
28 /* toggle line to simulate edge interrupt */
29 qemu_irq_pulse(dev
->sdev
.qirq
);
31 for (i
= 0; i
< size
; i
++) {
32 assert((dev
->in
- dev
->out
) < VTERM_BUFSIZE
);
33 dev
->buf
[dev
->in
++ % VTERM_BUFSIZE
] = buf
[i
];
37 static int vty_getchars(VIOsPAPRDevice
*sdev
, uint8_t *buf
, int max
)
39 VIOsPAPRVTYDevice
*dev
= (VIOsPAPRVTYDevice
*)sdev
;
42 while ((n
< max
) && (dev
->out
!= dev
->in
)) {
43 buf
[n
++] = dev
->buf
[dev
->out
++ % VTERM_BUFSIZE
];
49 void vty_putchars(VIOsPAPRDevice
*sdev
, uint8_t *buf
, int len
)
51 VIOsPAPRVTYDevice
*dev
= (VIOsPAPRVTYDevice
*)sdev
;
53 /* FIXME: should check the qemu_chr_write() return value */
54 qemu_chr_write(dev
->chardev
, buf
, len
);
57 static int spapr_vty_init(VIOsPAPRDevice
*sdev
)
59 VIOsPAPRVTYDevice
*dev
= (VIOsPAPRVTYDevice
*)sdev
;
61 qemu_chr_add_handlers(dev
->chardev
, vty_can_receive
,
62 vty_receive
, NULL
, dev
);
67 static target_ulong
h_put_term_char(CPUState
*env
, sPAPREnvironment
*spapr
,
68 target_ulong opcode
, target_ulong
*args
)
70 target_ulong reg
= args
[0];
71 target_ulong len
= args
[1];
72 target_ulong char0_7
= args
[2];
73 target_ulong char8_15
= args
[3];
74 VIOsPAPRDevice
*sdev
= spapr_vio_find_by_reg(spapr
->vio_bus
, reg
);
85 *((uint64_t *)buf
) = cpu_to_be64(char0_7
);
86 *((uint64_t *)buf
+ 1) = cpu_to_be64(char8_15
);
88 vty_putchars(sdev
, buf
, len
);
93 static target_ulong
h_get_term_char(CPUState
*env
, sPAPREnvironment
*spapr
,
94 target_ulong opcode
, target_ulong
*args
)
96 target_ulong reg
= args
[0];
97 target_ulong
*len
= args
+ 0;
98 target_ulong
*char0_7
= args
+ 1;
99 target_ulong
*char8_15
= args
+ 2;
100 VIOsPAPRDevice
*sdev
= spapr_vio_find_by_reg(spapr
->vio_bus
, reg
);
107 *len
= vty_getchars(sdev
, buf
, sizeof(buf
));
109 memset(buf
+ *len
, 0, 16 - *len
);
112 *char0_7
= be64_to_cpu(*((uint64_t *)buf
));
113 *char8_15
= be64_to_cpu(*((uint64_t *)buf
+ 1));
118 void spapr_vty_create(VIOsPAPRBus
*bus
,
119 uint32_t reg
, CharDriverState
*chardev
,
120 qemu_irq qirq
, uint32_t vio_irq_num
)
123 VIOsPAPRDevice
*sdev
;
125 dev
= qdev_create(&bus
->bus
, "spapr-vty");
126 qdev_prop_set_uint32(dev
, "reg", reg
);
127 qdev_prop_set_chr(dev
, "chardev", chardev
);
128 qdev_init_nofail(dev
);
129 sdev
= (VIOsPAPRDevice
*)dev
;
131 sdev
->vio_irq_num
= vio_irq_num
;
134 static void vty_hcalls(VIOsPAPRBus
*bus
)
136 spapr_register_hypercall(H_PUT_TERM_CHAR
, h_put_term_char
);
137 spapr_register_hypercall(H_GET_TERM_CHAR
, h_get_term_char
);
140 static VIOsPAPRDeviceInfo spapr_vty
= {
141 .init
= spapr_vty_init
,
144 .dt_compatible
= "hvterm1",
145 .hcalls
= vty_hcalls
,
146 .qdev
.name
= "spapr-vty",
147 .qdev
.size
= sizeof(VIOsPAPRVTYDevice
),
148 .qdev
.props
= (Property
[]) {
149 DEFINE_PROP_UINT32("reg", VIOsPAPRDevice
, reg
, 0),
150 DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice
, chardev
),
151 DEFINE_PROP_END_OF_LIST(),
155 static void spapr_vty_register(void)
157 spapr_vio_bus_register_withprop(&spapr_vty
);
159 device_init(spapr_vty_register
);