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); |