Statistics
| Branch: | Revision:

root / hw / spapr_vty.c @ ad2d30f7

History | View | Annotate | Download (4.1 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 0201e2da David Gibson
    if ((dev->in == dev->out) && size) {
28 0201e2da David Gibson
        /* toggle line to simulate edge interrupt */
29 0201e2da David Gibson
        qemu_irq_pulse(dev->sdev.qirq);
30 0201e2da David Gibson
    }
31 4040ab72 David Gibson
    for (i = 0; i < size; i++) {
32 4040ab72 David Gibson
        assert((dev->in - dev->out) < VTERM_BUFSIZE);
33 4040ab72 David Gibson
        dev->buf[dev->in++ % VTERM_BUFSIZE] = buf[i];
34 4040ab72 David Gibson
    }
35 4040ab72 David Gibson
}
36 4040ab72 David Gibson
37 4040ab72 David Gibson
static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
38 4040ab72 David Gibson
{
39 4040ab72 David Gibson
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
40 4040ab72 David Gibson
    int n = 0;
41 4040ab72 David Gibson
42 4040ab72 David Gibson
    while ((n < max) && (dev->out != dev->in)) {
43 4040ab72 David Gibson
        buf[n++] = dev->buf[dev->out++ % VTERM_BUFSIZE];
44 4040ab72 David Gibson
    }
45 4040ab72 David Gibson
46 4040ab72 David Gibson
    return n;
47 4040ab72 David Gibson
}
48 4040ab72 David Gibson
49 4040ab72 David Gibson
void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
50 4040ab72 David Gibson
{
51 4040ab72 David Gibson
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
52 4040ab72 David Gibson
53 4040ab72 David Gibson
    /* FIXME: should check the qemu_chr_write() return value */
54 4040ab72 David Gibson
    qemu_chr_write(dev->chardev, buf, len);
55 4040ab72 David Gibson
}
56 4040ab72 David Gibson
57 4040ab72 David Gibson
static int spapr_vty_init(VIOsPAPRDevice *sdev)
58 4040ab72 David Gibson
{
59 4040ab72 David Gibson
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
60 4040ab72 David Gibson
61 4040ab72 David Gibson
    qemu_chr_add_handlers(dev->chardev, vty_can_receive,
62 4040ab72 David Gibson
                          vty_receive, NULL, dev);
63 4040ab72 David Gibson
64 4040ab72 David Gibson
    return 0;
65 4040ab72 David Gibson
}
66 4040ab72 David Gibson
67 4040ab72 David Gibson
static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
68 4040ab72 David Gibson
                                    target_ulong opcode, target_ulong *args)
69 4040ab72 David Gibson
{
70 4040ab72 David Gibson
    target_ulong reg = args[0];
71 4040ab72 David Gibson
    target_ulong len = args[1];
72 4040ab72 David Gibson
    target_ulong char0_7 = args[2];
73 4040ab72 David Gibson
    target_ulong char8_15 = args[3];
74 4040ab72 David Gibson
    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
75 4040ab72 David Gibson
    uint8_t buf[16];
76 4040ab72 David Gibson
77 4040ab72 David Gibson
    if (!sdev) {
78 4040ab72 David Gibson
        return H_PARAMETER;
79 4040ab72 David Gibson
    }
80 4040ab72 David Gibson
81 4040ab72 David Gibson
    if (len > 16) {
82 4040ab72 David Gibson
        return H_PARAMETER;
83 4040ab72 David Gibson
    }
84 4040ab72 David Gibson
85 4040ab72 David Gibson
    *((uint64_t *)buf) = cpu_to_be64(char0_7);
86 4040ab72 David Gibson
    *((uint64_t *)buf + 1) = cpu_to_be64(char8_15);
87 4040ab72 David Gibson
88 4040ab72 David Gibson
    vty_putchars(sdev, buf, len);
89 4040ab72 David Gibson
90 4040ab72 David Gibson
    return H_SUCCESS;
91 4040ab72 David Gibson
}
92 4040ab72 David Gibson
93 4040ab72 David Gibson
static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr,
94 4040ab72 David Gibson
                                    target_ulong opcode, target_ulong *args)
95 4040ab72 David Gibson
{
96 4040ab72 David Gibson
    target_ulong reg = args[0];
97 4040ab72 David Gibson
    target_ulong *len = args + 0;
98 4040ab72 David Gibson
    target_ulong *char0_7 = args + 1;
99 4040ab72 David Gibson
    target_ulong *char8_15 = args + 2;
100 4040ab72 David Gibson
    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
101 4040ab72 David Gibson
    uint8_t buf[16];
102 4040ab72 David Gibson
103 4040ab72 David Gibson
    if (!sdev) {
104 4040ab72 David Gibson
        return H_PARAMETER;
105 4040ab72 David Gibson
    }
106 4040ab72 David Gibson
107 4040ab72 David Gibson
    *len = vty_getchars(sdev, buf, sizeof(buf));
108 4040ab72 David Gibson
    if (*len < 16) {
109 4040ab72 David Gibson
        memset(buf + *len, 0, 16 - *len);
110 4040ab72 David Gibson
    }
111 4040ab72 David Gibson
112 4040ab72 David Gibson
    *char0_7 = be64_to_cpu(*((uint64_t *)buf));
113 4040ab72 David Gibson
    *char8_15 = be64_to_cpu(*((uint64_t *)buf + 1));
114 4040ab72 David Gibson
115 4040ab72 David Gibson
    return H_SUCCESS;
116 4040ab72 David Gibson
}
117 4040ab72 David Gibson
118 4040ab72 David Gibson
void spapr_vty_create(VIOsPAPRBus *bus,
119 0201e2da David Gibson
                      uint32_t reg, CharDriverState *chardev,
120 0201e2da David Gibson
                      qemu_irq qirq, uint32_t vio_irq_num)
121 4040ab72 David Gibson
{
122 4040ab72 David Gibson
    DeviceState *dev;
123 0201e2da David Gibson
    VIOsPAPRDevice *sdev;
124 4040ab72 David Gibson
125 4040ab72 David Gibson
    dev = qdev_create(&bus->bus, "spapr-vty");
126 4040ab72 David Gibson
    qdev_prop_set_uint32(dev, "reg", reg);
127 4040ab72 David Gibson
    qdev_prop_set_chr(dev, "chardev", chardev);
128 4040ab72 David Gibson
    qdev_init_nofail(dev);
129 0201e2da David Gibson
    sdev = (VIOsPAPRDevice *)dev;
130 0201e2da David Gibson
    sdev->qirq = qirq;
131 0201e2da David Gibson
    sdev->vio_irq_num = vio_irq_num;
132 4040ab72 David Gibson
}
133 4040ab72 David Gibson
134 4040ab72 David Gibson
static void vty_hcalls(VIOsPAPRBus *bus)
135 4040ab72 David Gibson
{
136 4040ab72 David Gibson
    spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
137 4040ab72 David Gibson
    spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
138 4040ab72 David Gibson
}
139 4040ab72 David Gibson
140 4040ab72 David Gibson
static VIOsPAPRDeviceInfo spapr_vty = {
141 4040ab72 David Gibson
    .init = spapr_vty_init,
142 4040ab72 David Gibson
    .dt_name = "vty",
143 4040ab72 David Gibson
    .dt_type = "serial",
144 4040ab72 David Gibson
    .dt_compatible = "hvterm1",
145 4040ab72 David Gibson
    .hcalls = vty_hcalls,
146 4040ab72 David Gibson
    .qdev.name = "spapr-vty",
147 4040ab72 David Gibson
    .qdev.size = sizeof(VIOsPAPRVTYDevice),
148 4040ab72 David Gibson
    .qdev.props = (Property[]) {
149 4040ab72 David Gibson
        DEFINE_PROP_UINT32("reg", VIOsPAPRDevice, reg, 0),
150 4040ab72 David Gibson
        DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
151 4040ab72 David Gibson
        DEFINE_PROP_END_OF_LIST(),
152 4040ab72 David Gibson
    },
153 4040ab72 David Gibson
};
154 4040ab72 David Gibson
155 4040ab72 David Gibson
static void spapr_vty_register(void)
156 4040ab72 David Gibson
{
157 4040ab72 David Gibson
    spapr_vio_bus_register_withprop(&spapr_vty);
158 4040ab72 David Gibson
}
159 4040ab72 David Gibson
device_init(spapr_vty_register);