Statistics
| Branch: | Revision:

root / hw / spapr_vty.c @ 4040ab72

History | View | Annotate | Download (3.8 kB)

1
#include "qdev.h"
2
#include "qemu-char.h"
3
#include "hw/spapr.h"
4
#include "hw/spapr_vio.h"
5

    
6
#define VTERM_BUFSIZE   16
7

    
8
typedef struct VIOsPAPRVTYDevice {
9
    VIOsPAPRDevice sdev;
10
    CharDriverState *chardev;
11
    uint32_t in, out;
12
    uint8_t buf[VTERM_BUFSIZE];
13
} VIOsPAPRVTYDevice;
14

    
15
static int vty_can_receive(void *opaque)
16
{
17
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
18

    
19
    return (dev->in - dev->out) < VTERM_BUFSIZE;
20
}
21

    
22
static void vty_receive(void *opaque, const uint8_t *buf, int size)
23
{
24
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
25
    int i;
26

    
27
    for (i = 0; i < size; i++) {
28
        assert((dev->in - dev->out) < VTERM_BUFSIZE);
29
        dev->buf[dev->in++ % VTERM_BUFSIZE] = buf[i];
30
    }
31
}
32

    
33
static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
34
{
35
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
36
    int n = 0;
37

    
38
    while ((n < max) && (dev->out != dev->in)) {
39
        buf[n++] = dev->buf[dev->out++ % VTERM_BUFSIZE];
40
    }
41

    
42
    return n;
43
}
44

    
45
void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
46
{
47
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
48

    
49
    /* FIXME: should check the qemu_chr_write() return value */
50
    qemu_chr_write(dev->chardev, buf, len);
51
}
52

    
53
static int spapr_vty_init(VIOsPAPRDevice *sdev)
54
{
55
    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
56

    
57
    qemu_chr_add_handlers(dev->chardev, vty_can_receive,
58
                          vty_receive, NULL, dev);
59

    
60
    return 0;
61
}
62

    
63
static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
64
                                    target_ulong opcode, target_ulong *args)
65
{
66
    target_ulong reg = args[0];
67
    target_ulong len = args[1];
68
    target_ulong char0_7 = args[2];
69
    target_ulong char8_15 = args[3];
70
    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
71
    uint8_t buf[16];
72

    
73
    if (!sdev) {
74
        return H_PARAMETER;
75
    }
76

    
77
    if (len > 16) {
78
        return H_PARAMETER;
79
    }
80

    
81
    *((uint64_t *)buf) = cpu_to_be64(char0_7);
82
    *((uint64_t *)buf + 1) = cpu_to_be64(char8_15);
83

    
84
    vty_putchars(sdev, buf, len);
85

    
86
    return H_SUCCESS;
87
}
88

    
89
static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr,
90
                                    target_ulong opcode, target_ulong *args)
91
{
92
    target_ulong reg = args[0];
93
    target_ulong *len = args + 0;
94
    target_ulong *char0_7 = args + 1;
95
    target_ulong *char8_15 = args + 2;
96
    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
97
    uint8_t buf[16];
98

    
99
    if (!sdev) {
100
        return H_PARAMETER;
101
    }
102

    
103
    *len = vty_getchars(sdev, buf, sizeof(buf));
104
    if (*len < 16) {
105
        memset(buf + *len, 0, 16 - *len);
106
    }
107

    
108
    *char0_7 = be64_to_cpu(*((uint64_t *)buf));
109
    *char8_15 = be64_to_cpu(*((uint64_t *)buf + 1));
110

    
111
    return H_SUCCESS;
112
}
113

    
114
void spapr_vty_create(VIOsPAPRBus *bus,
115
                      uint32_t reg, CharDriverState *chardev)
116
{
117
    DeviceState *dev;
118

    
119
    dev = qdev_create(&bus->bus, "spapr-vty");
120
    qdev_prop_set_uint32(dev, "reg", reg);
121
    qdev_prop_set_chr(dev, "chardev", chardev);
122
    qdev_init_nofail(dev);
123
}
124

    
125
static void vty_hcalls(VIOsPAPRBus *bus)
126
{
127
    spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
128
    spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
129
}
130

    
131
static VIOsPAPRDeviceInfo spapr_vty = {
132
    .init = spapr_vty_init,
133
    .dt_name = "vty",
134
    .dt_type = "serial",
135
    .dt_compatible = "hvterm1",
136
    .hcalls = vty_hcalls,
137
    .qdev.name = "spapr-vty",
138
    .qdev.size = sizeof(VIOsPAPRVTYDevice),
139
    .qdev.props = (Property[]) {
140
        DEFINE_PROP_UINT32("reg", VIOsPAPRDevice, reg, 0),
141
        DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
142
        DEFINE_PROP_END_OF_LIST(),
143
    },
144
};
145

    
146
static void spapr_vty_register(void)
147
{
148
    spapr_vio_bus_register_withprop(&spapr_vty);
149
}
150
device_init(spapr_vty_register);