Statistics
| Branch: | Revision:

root / hw / spapr_vty.c @ 4040ab72

History | View | Annotate | Download (3.8 kB)

1 4040ab72 David Gibson
#include "qdev.h"
2 4040ab72 David Gibson
#include "qemu-char.h"
3 4040ab72 David Gibson
#include "hw/spapr.h"
4 4040ab72 David Gibson
#include "hw/spapr_vio.h"
5 4040ab72 David Gibson
6 4040ab72 David Gibson
#define VTERM_BUFSIZE   16
7 4040ab72 David Gibson
8 4040ab72 David Gibson
typedef struct VIOsPAPRVTYDevice {
9 4040ab72 David Gibson
    VIOsPAPRDevice sdev;
10 4040ab72 David Gibson
    CharDriverState *chardev;
11 4040ab72 David Gibson
    uint32_t in, out;
12 4040ab72 David Gibson
    uint8_t buf[VTERM_BUFSIZE];
13 4040ab72 David Gibson
} VIOsPAPRVTYDevice;
14 4040ab72 David Gibson
15 4040ab72 David Gibson
static int vty_can_receive(void *opaque)
16 4040ab72 David Gibson
{
17 4040ab72 David Gibson
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
18 4040ab72 David Gibson
19 4040ab72 David Gibson
    return (dev->in - dev->out) < VTERM_BUFSIZE;
20 4040ab72 David Gibson
}
21 4040ab72 David Gibson
22 4040ab72 David Gibson
static void vty_receive(void *opaque, const uint8_t *buf, int size)
23 4040ab72 David Gibson
{
24 4040ab72 David Gibson
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
25 4040ab72 David Gibson
    int i;
26 4040ab72 David Gibson
27 4040ab72 David Gibson
    for (i = 0; i < size; i++) {
28 4040ab72 David Gibson
        assert((dev->in - dev->out) < VTERM_BUFSIZE);
29 4040ab72 David Gibson
        dev->buf[dev->in++ % VTERM_BUFSIZE] = buf[i];
30 4040ab72 David Gibson
    }
31 4040ab72 David Gibson
}
32 4040ab72 David Gibson
33 4040ab72 David Gibson
static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
34 4040ab72 David Gibson
{
35 4040ab72 David Gibson
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
36 4040ab72 David Gibson
    int n = 0;
37 4040ab72 David Gibson
38 4040ab72 David Gibson
    while ((n < max) && (dev->out != dev->in)) {
39 4040ab72 David Gibson
        buf[n++] = dev->buf[dev->out++ % VTERM_BUFSIZE];
40 4040ab72 David Gibson
    }
41 4040ab72 David Gibson
42 4040ab72 David Gibson
    return n;
43 4040ab72 David Gibson
}
44 4040ab72 David Gibson
45 4040ab72 David Gibson
void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
46 4040ab72 David Gibson
{
47 4040ab72 David Gibson
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
48 4040ab72 David Gibson
49 4040ab72 David Gibson
    /* FIXME: should check the qemu_chr_write() return value */
50 4040ab72 David Gibson
    qemu_chr_write(dev->chardev, buf, len);
51 4040ab72 David Gibson
}
52 4040ab72 David Gibson
53 4040ab72 David Gibson
static int spapr_vty_init(VIOsPAPRDevice *sdev)
54 4040ab72 David Gibson
{
55 4040ab72 David Gibson
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
56 4040ab72 David Gibson
57 4040ab72 David Gibson
    qemu_chr_add_handlers(dev->chardev, vty_can_receive,
58 4040ab72 David Gibson
                          vty_receive, NULL, dev);
59 4040ab72 David Gibson
60 4040ab72 David Gibson
    return 0;
61 4040ab72 David Gibson
}
62 4040ab72 David Gibson
63 4040ab72 David Gibson
static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
64 4040ab72 David Gibson
                                    target_ulong opcode, target_ulong *args)
65 4040ab72 David Gibson
{
66 4040ab72 David Gibson
    target_ulong reg = args[0];
67 4040ab72 David Gibson
    target_ulong len = args[1];
68 4040ab72 David Gibson
    target_ulong char0_7 = args[2];
69 4040ab72 David Gibson
    target_ulong char8_15 = args[3];
70 4040ab72 David Gibson
    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
71 4040ab72 David Gibson
    uint8_t buf[16];
72 4040ab72 David Gibson
73 4040ab72 David Gibson
    if (!sdev) {
74 4040ab72 David Gibson
        return H_PARAMETER;
75 4040ab72 David Gibson
    }
76 4040ab72 David Gibson
77 4040ab72 David Gibson
    if (len > 16) {
78 4040ab72 David Gibson
        return H_PARAMETER;
79 4040ab72 David Gibson
    }
80 4040ab72 David Gibson
81 4040ab72 David Gibson
    *((uint64_t *)buf) = cpu_to_be64(char0_7);
82 4040ab72 David Gibson
    *((uint64_t *)buf + 1) = cpu_to_be64(char8_15);
83 4040ab72 David Gibson
84 4040ab72 David Gibson
    vty_putchars(sdev, buf, len);
85 4040ab72 David Gibson
86 4040ab72 David Gibson
    return H_SUCCESS;
87 4040ab72 David Gibson
}
88 4040ab72 David Gibson
89 4040ab72 David Gibson
static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr,
90 4040ab72 David Gibson
                                    target_ulong opcode, target_ulong *args)
91 4040ab72 David Gibson
{
92 4040ab72 David Gibson
    target_ulong reg = args[0];
93 4040ab72 David Gibson
    target_ulong *len = args + 0;
94 4040ab72 David Gibson
    target_ulong *char0_7 = args + 1;
95 4040ab72 David Gibson
    target_ulong *char8_15 = args + 2;
96 4040ab72 David Gibson
    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
97 4040ab72 David Gibson
    uint8_t buf[16];
98 4040ab72 David Gibson
99 4040ab72 David Gibson
    if (!sdev) {
100 4040ab72 David Gibson
        return H_PARAMETER;
101 4040ab72 David Gibson
    }
102 4040ab72 David Gibson
103 4040ab72 David Gibson
    *len = vty_getchars(sdev, buf, sizeof(buf));
104 4040ab72 David Gibson
    if (*len < 16) {
105 4040ab72 David Gibson
        memset(buf + *len, 0, 16 - *len);
106 4040ab72 David Gibson
    }
107 4040ab72 David Gibson
108 4040ab72 David Gibson
    *char0_7 = be64_to_cpu(*((uint64_t *)buf));
109 4040ab72 David Gibson
    *char8_15 = be64_to_cpu(*((uint64_t *)buf + 1));
110 4040ab72 David Gibson
111 4040ab72 David Gibson
    return H_SUCCESS;
112 4040ab72 David Gibson
}
113 4040ab72 David Gibson
114 4040ab72 David Gibson
void spapr_vty_create(VIOsPAPRBus *bus,
115 4040ab72 David Gibson
                      uint32_t reg, CharDriverState *chardev)
116 4040ab72 David Gibson
{
117 4040ab72 David Gibson
    DeviceState *dev;
118 4040ab72 David Gibson
119 4040ab72 David Gibson
    dev = qdev_create(&bus->bus, "spapr-vty");
120 4040ab72 David Gibson
    qdev_prop_set_uint32(dev, "reg", reg);
121 4040ab72 David Gibson
    qdev_prop_set_chr(dev, "chardev", chardev);
122 4040ab72 David Gibson
    qdev_init_nofail(dev);
123 4040ab72 David Gibson
}
124 4040ab72 David Gibson
125 4040ab72 David Gibson
static void vty_hcalls(VIOsPAPRBus *bus)
126 4040ab72 David Gibson
{
127 4040ab72 David Gibson
    spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
128 4040ab72 David Gibson
    spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
129 4040ab72 David Gibson
}
130 4040ab72 David Gibson
131 4040ab72 David Gibson
static VIOsPAPRDeviceInfo spapr_vty = {
132 4040ab72 David Gibson
    .init = spapr_vty_init,
133 4040ab72 David Gibson
    .dt_name = "vty",
134 4040ab72 David Gibson
    .dt_type = "serial",
135 4040ab72 David Gibson
    .dt_compatible = "hvterm1",
136 4040ab72 David Gibson
    .hcalls = vty_hcalls,
137 4040ab72 David Gibson
    .qdev.name = "spapr-vty",
138 4040ab72 David Gibson
    .qdev.size = sizeof(VIOsPAPRVTYDevice),
139 4040ab72 David Gibson
    .qdev.props = (Property[]) {
140 4040ab72 David Gibson
        DEFINE_PROP_UINT32("reg", VIOsPAPRDevice, reg, 0),
141 4040ab72 David Gibson
        DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
142 4040ab72 David Gibson
        DEFINE_PROP_END_OF_LIST(),
143 4040ab72 David Gibson
    },
144 4040ab72 David Gibson
};
145 4040ab72 David Gibson
146 4040ab72 David Gibson
static void spapr_vty_register(void)
147 4040ab72 David Gibson
{
148 4040ab72 David Gibson
    spapr_vio_bus_register_withprop(&spapr_vty);
149 4040ab72 David Gibson
}
150 4040ab72 David Gibson
device_init(spapr_vty_register);