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_fe_write() return value */
54
qemu_chr_fe_write(dev->chardev, buf, len);
57
static int spapr_vty_init(VIOsPAPRDevice *sdev)
59
VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
62
fprintf(stderr, "spapr-vty: Can't create vty without a chardev!\n");
66
qemu_chr_add_handlers(dev->chardev, vty_can_receive,
67
vty_receive, NULL, dev);
72
/* Forward declaration */
73
static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg);
75
static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
76
target_ulong opcode, target_ulong *args)
78
target_ulong reg = args[0];
79
target_ulong len = args[1];
80
target_ulong char0_7 = args[2];
81
target_ulong char8_15 = args[3];
85
sdev = vty_lookup(spapr, reg);
94
*((uint64_t *)buf) = cpu_to_be64(char0_7);
95
*((uint64_t *)buf + 1) = cpu_to_be64(char8_15);
97
vty_putchars(sdev, buf, len);
102
static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr,
103
target_ulong opcode, target_ulong *args)
105
target_ulong reg = args[0];
106
target_ulong *len = args + 0;
107
target_ulong *char0_7 = args + 1;
108
target_ulong *char8_15 = args + 2;
109
VIOsPAPRDevice *sdev;
112
sdev = vty_lookup(spapr, reg);
117
*len = vty_getchars(sdev, buf, sizeof(buf));
119
memset(buf + *len, 0, 16 - *len);
122
*char0_7 = be64_to_cpu(*((uint64_t *)buf));
123
*char8_15 = be64_to_cpu(*((uint64_t *)buf + 1));
128
void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev)
132
dev = qdev_create(&bus->bus, "spapr-vty");
133
qdev_prop_set_uint32(dev, "reg", reg);
134
qdev_prop_set_chr(dev, "chardev", chardev);
135
qdev_init_nofail(dev);
138
static void vty_hcalls(VIOsPAPRBus *bus)
140
spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
141
spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
144
static VIOsPAPRDeviceInfo spapr_vty = {
145
.init = spapr_vty_init,
148
.dt_compatible = "hvterm1",
149
.hcalls = vty_hcalls,
150
.qdev.name = "spapr-vty",
151
.qdev.size = sizeof(VIOsPAPRVTYDevice),
152
.qdev.props = (Property[]) {
153
DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, SPAPR_VTY_BASE_ADDRESS, 0),
154
DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
155
DEFINE_PROP_END_OF_LIST(),
159
static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
161
VIOsPAPRDevice *sdev;
163
sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
164
if (!sdev && reg == 0) {
167
/* Hack for kernel early debug, which always specifies reg==0.
168
* We search all VIO devices, and grab the first available vty
169
* device. This attempts to mimic existing PowerVM behaviour
170
* (early debug does work there, despite having no vty with
172
QTAILQ_FOREACH(qdev, &spapr->vio_bus->bus.children, sibling) {
173
if (qdev->info == &spapr_vty.qdev) {
174
return DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
182
static void spapr_vty_register(void)
184
spapr_vio_bus_register_withprop(&spapr_vty);
186
device_init(spapr_vty_register);