Revision 4040ab72
b/Makefile.target | ||
---|---|---|
231 | 231 |
obj-ppc-y += ppc_oldworld.o |
232 | 232 |
# NewWorld PowerMac |
233 | 233 |
obj-ppc-y += ppc_newworld.o |
234 |
# IBM pSeries (sPAPR)i
|
|
234 |
# IBM pSeries (sPAPR) |
|
235 | 235 |
ifeq ($(CONFIG_FDT)$(TARGET_PPC64),yy) |
236 |
obj-ppc-y += spapr.o spapr_hcall.o |
|
236 |
obj-ppc-y += spapr.o spapr_hcall.o spapr_vio.o |
|
237 |
obj-ppc-y += spapr_vty.o |
|
237 | 238 |
endif |
238 | 239 |
# PowerPC 4xx boards |
239 | 240 |
obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o |
b/hw/spapr.c | ||
---|---|---|
25 | 25 |
* |
26 | 26 |
*/ |
27 | 27 |
#include "sysemu.h" |
28 |
#include "qemu-char.h" |
|
29 | 28 |
#include "hw.h" |
30 | 29 |
#include "elf.h" |
31 | 30 |
|
... | ... | |
34 | 33 |
#include "hw/loader.h" |
35 | 34 |
|
36 | 35 |
#include "hw/spapr.h" |
36 |
#include "hw/spapr_vio.h" |
|
37 | 37 |
|
38 | 38 |
#include <libfdt.h> |
39 | 39 |
|
... | ... | |
60 | 60 |
uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size); |
61 | 61 |
int i; |
62 | 62 |
char *modelname; |
63 |
int ret; |
|
63 | 64 |
|
64 | 65 |
#define _FDT(exp) \ |
65 | 66 |
do { \ |
... | ... | |
159 | 160 |
|
160 | 161 |
_FDT((fdt_end_node(fdt))); |
161 | 162 |
|
163 |
/* vdevice */ |
|
164 |
_FDT((fdt_begin_node(fdt, "vdevice"))); |
|
165 |
|
|
166 |
_FDT((fdt_property_string(fdt, "device_type", "vdevice"))); |
|
167 |
_FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice"))); |
|
168 |
_FDT((fdt_property_cell(fdt, "#address-cells", 0x1))); |
|
169 |
_FDT((fdt_property_cell(fdt, "#size-cells", 0x0))); |
|
170 |
|
|
171 |
_FDT((fdt_end_node(fdt))); |
|
172 |
|
|
162 | 173 |
_FDT((fdt_end_node(fdt))); /* close root node */ |
163 | 174 |
_FDT((fdt_finish(fdt))); |
164 | 175 |
|
176 |
/* re-expand to allow for further tweaks */ |
|
177 |
_FDT((fdt_open_into(fdt, fdt, FDT_MAX_SIZE))); |
|
178 |
|
|
179 |
ret = spapr_populate_vdevice(spapr->vio_bus, fdt); |
|
180 |
if (ret < 0) { |
|
181 |
fprintf(stderr, "couldn't setup vio devices in fdt\n"); |
|
182 |
exit(1); |
|
183 |
} |
|
184 |
|
|
185 |
_FDT((fdt_pack(fdt))); |
|
186 |
|
|
165 | 187 |
*fdt_size = fdt_totalsize(fdt); |
166 | 188 |
|
167 | 189 |
return fdt; |
... | ... | |
177 | 199 |
env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]); |
178 | 200 |
} |
179 | 201 |
|
180 |
/* FIXME: hack until we implement the proper VIO console */ |
|
181 |
static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr, |
|
182 |
target_ulong opcode, target_ulong *args) |
|
183 |
{ |
|
184 |
uint8_t buf[16]; |
|
185 |
|
|
186 |
stq_p(buf, args[2]); |
|
187 |
stq_p(buf + 8, args[3]); |
|
188 |
|
|
189 |
qemu_chr_write(serial_hds[0], buf, args[1]); |
|
190 |
|
|
191 |
return 0; |
|
192 |
} |
|
193 |
|
|
194 |
|
|
195 | 202 |
/* pSeries LPAR / sPAPR hardware init */ |
196 | 203 |
static void ppc_spapr_init(ram_addr_t ram_size, |
197 | 204 |
const char *boot_device, |
... | ... | |
243 | 250 |
ram_offset = qemu_ram_alloc(NULL, "ppc_spapr.ram", ram_size); |
244 | 251 |
cpu_register_physical_memory(0, ram_size, ram_offset); |
245 | 252 |
|
246 |
spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char); |
|
253 |
spapr->vio_bus = spapr_vio_bus_init(); |
|
254 |
|
|
255 |
for (i = 0; i < MAX_SERIAL_PORTS; i++) { |
|
256 |
if (serial_hds[i]) { |
|
257 |
spapr_vty_create(spapr->vio_bus, i, serial_hds[i]); |
|
258 |
} |
|
259 |
} |
|
247 | 260 |
|
248 | 261 |
if (kernel_filename) { |
249 | 262 |
uint64_t lowaddr = 0; |
... | ... | |
276 | 289 |
initrd_base = 0; |
277 | 290 |
initrd_size = 0; |
278 | 291 |
} |
279 |
|
|
280 | 292 |
} else { |
281 | 293 |
fprintf(stderr, "pSeries machine needs -kernel for now"); |
282 | 294 |
exit(1); |
b/hw/spapr.h | ||
---|---|---|
1 | 1 |
#if !defined(__HW_SPAPR_H__) |
2 | 2 |
#define __HW_SPAPR_H__ |
3 | 3 |
|
4 |
struct VIOsPAPRBus; |
|
5 |
|
|
4 | 6 |
typedef struct sPAPREnvironment { |
7 |
struct VIOsPAPRBus *vio_bus; |
|
5 | 8 |
} sPAPREnvironment; |
6 | 9 |
|
7 | 10 |
#define H_SUCCESS 0 |
b/hw/spapr_vio.c | ||
---|---|---|
1 |
/* |
|
2 |
* QEMU sPAPR VIO code |
|
3 |
* |
|
4 |
* Copyright (c) 2010 David Gibson, IBM Corporation <dwg@au1.ibm.com> |
|
5 |
* Based on the s390 virtio bus code: |
|
6 |
* Copyright (c) 2009 Alexander Graf <agraf@suse.de> |
|
7 |
* |
|
8 |
* This library is free software; you can redistribute it and/or |
|
9 |
* modify it under the terms of the GNU Lesser General Public |
|
10 |
* License as published by the Free Software Foundation; either |
|
11 |
* version 2 of the License, or (at your option) any later version. |
|
12 |
* |
|
13 |
* This library is distributed in the hope that it will be useful, |
|
14 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
16 |
* Lesser General Public License for more details. |
|
17 |
* |
|
18 |
* You should have received a copy of the GNU Lesser General Public |
|
19 |
* License along with this library; if not, see <http://www.gnu.org/licenses/>. |
|
20 |
*/ |
|
21 |
|
|
22 |
#include "hw.h" |
|
23 |
#include "sysemu.h" |
|
24 |
#include "boards.h" |
|
25 |
#include "monitor.h" |
|
26 |
#include "loader.h" |
|
27 |
#include "elf.h" |
|
28 |
#include "hw/sysbus.h" |
|
29 |
#include "kvm.h" |
|
30 |
#include "device_tree.h" |
|
31 |
|
|
32 |
#include "hw/spapr.h" |
|
33 |
#include "hw/spapr_vio.h" |
|
34 |
|
|
35 |
#ifdef CONFIG_FDT |
|
36 |
#include <libfdt.h> |
|
37 |
#endif /* CONFIG_FDT */ |
|
38 |
|
|
39 |
/* #define DEBUG_SPAPR */ |
|
40 |
|
|
41 |
#ifdef DEBUG_SPAPR |
|
42 |
#define dprintf(fmt, ...) \ |
|
43 |
do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) |
|
44 |
#else |
|
45 |
#define dprintf(fmt, ...) \ |
|
46 |
do { } while (0) |
|
47 |
#endif |
|
48 |
|
|
49 |
static struct BusInfo spapr_vio_bus_info = { |
|
50 |
.name = "spapr-vio", |
|
51 |
.size = sizeof(VIOsPAPRBus), |
|
52 |
}; |
|
53 |
|
|
54 |
VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg) |
|
55 |
{ |
|
56 |
DeviceState *qdev; |
|
57 |
VIOsPAPRDevice *dev = NULL; |
|
58 |
|
|
59 |
QLIST_FOREACH(qdev, &bus->bus.children, sibling) { |
|
60 |
dev = (VIOsPAPRDevice *)qdev; |
|
61 |
if (dev->reg == reg) { |
|
62 |
break; |
|
63 |
} |
|
64 |
} |
|
65 |
|
|
66 |
return dev; |
|
67 |
} |
|
68 |
|
|
69 |
#ifdef CONFIG_FDT |
|
70 |
static int vio_make_devnode(VIOsPAPRDevice *dev, |
|
71 |
void *fdt) |
|
72 |
{ |
|
73 |
VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info; |
|
74 |
int vdevice_off, node_off; |
|
75 |
int ret; |
|
76 |
|
|
77 |
vdevice_off = fdt_path_offset(fdt, "/vdevice"); |
|
78 |
if (vdevice_off < 0) { |
|
79 |
return vdevice_off; |
|
80 |
} |
|
81 |
|
|
82 |
node_off = fdt_add_subnode(fdt, vdevice_off, dev->qdev.id); |
|
83 |
if (node_off < 0) { |
|
84 |
return node_off; |
|
85 |
} |
|
86 |
|
|
87 |
ret = fdt_setprop_cell(fdt, node_off, "reg", dev->reg); |
|
88 |
if (ret < 0) { |
|
89 |
return ret; |
|
90 |
} |
|
91 |
|
|
92 |
if (info->dt_type) { |
|
93 |
ret = fdt_setprop_string(fdt, node_off, "device_type", |
|
94 |
info->dt_type); |
|
95 |
if (ret < 0) { |
|
96 |
return ret; |
|
97 |
} |
|
98 |
} |
|
99 |
|
|
100 |
if (info->dt_compatible) { |
|
101 |
ret = fdt_setprop_string(fdt, node_off, "compatible", |
|
102 |
info->dt_compatible); |
|
103 |
if (ret < 0) { |
|
104 |
return ret; |
|
105 |
} |
|
106 |
} |
|
107 |
|
|
108 |
if (info->devnode) { |
|
109 |
ret = (info->devnode)(dev, fdt, node_off); |
|
110 |
if (ret < 0) { |
|
111 |
return ret; |
|
112 |
} |
|
113 |
} |
|
114 |
|
|
115 |
return node_off; |
|
116 |
} |
|
117 |
#endif /* CONFIG_FDT */ |
|
118 |
|
|
119 |
static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo) |
|
120 |
{ |
|
121 |
VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo; |
|
122 |
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev; |
|
123 |
char *id; |
|
124 |
|
|
125 |
if (asprintf(&id, "%s@%x", info->dt_name, dev->reg) < 0) { |
|
126 |
return -1; |
|
127 |
} |
|
128 |
|
|
129 |
dev->qdev.id = id; |
|
130 |
|
|
131 |
return info->init(dev); |
|
132 |
} |
|
133 |
|
|
134 |
void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info) |
|
135 |
{ |
|
136 |
info->qdev.init = spapr_vio_busdev_init; |
|
137 |
info->qdev.bus_info = &spapr_vio_bus_info; |
|
138 |
|
|
139 |
assert(info->qdev.size >= sizeof(VIOsPAPRDevice)); |
|
140 |
qdev_register(&info->qdev); |
|
141 |
} |
|
142 |
|
|
143 |
VIOsPAPRBus *spapr_vio_bus_init(void) |
|
144 |
{ |
|
145 |
VIOsPAPRBus *bus; |
|
146 |
BusState *qbus; |
|
147 |
DeviceState *dev; |
|
148 |
DeviceInfo *qinfo; |
|
149 |
|
|
150 |
/* Create bridge device */ |
|
151 |
dev = qdev_create(NULL, "spapr-vio-bridge"); |
|
152 |
qdev_init_nofail(dev); |
|
153 |
|
|
154 |
/* Create bus on bridge device */ |
|
155 |
|
|
156 |
qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio"); |
|
157 |
bus = DO_UPCAST(VIOsPAPRBus, bus, qbus); |
|
158 |
|
|
159 |
for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) { |
|
160 |
VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo; |
|
161 |
|
|
162 |
if (qinfo->bus_info != &spapr_vio_bus_info) { |
|
163 |
continue; |
|
164 |
} |
|
165 |
|
|
166 |
if (info->hcalls) { |
|
167 |
info->hcalls(bus); |
|
168 |
} |
|
169 |
} |
|
170 |
|
|
171 |
return bus; |
|
172 |
} |
|
173 |
|
|
174 |
/* Represents sPAPR hcall VIO devices */ |
|
175 |
|
|
176 |
static int spapr_vio_bridge_init(SysBusDevice *dev) |
|
177 |
{ |
|
178 |
/* nothing */ |
|
179 |
return 0; |
|
180 |
} |
|
181 |
|
|
182 |
static SysBusDeviceInfo spapr_vio_bridge_info = { |
|
183 |
.init = spapr_vio_bridge_init, |
|
184 |
.qdev.name = "spapr-vio-bridge", |
|
185 |
.qdev.size = sizeof(SysBusDevice), |
|
186 |
.qdev.no_user = 1, |
|
187 |
}; |
|
188 |
|
|
189 |
static void spapr_vio_register_devices(void) |
|
190 |
{ |
|
191 |
sysbus_register_withprop(&spapr_vio_bridge_info); |
|
192 |
} |
|
193 |
|
|
194 |
device_init(spapr_vio_register_devices) |
|
195 |
|
|
196 |
#ifdef CONFIG_FDT |
|
197 |
int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt) |
|
198 |
{ |
|
199 |
DeviceState *qdev; |
|
200 |
int ret = 0; |
|
201 |
|
|
202 |
QLIST_FOREACH(qdev, &bus->bus.children, sibling) { |
|
203 |
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev; |
|
204 |
|
|
205 |
ret = vio_make_devnode(dev, fdt); |
|
206 |
|
|
207 |
if (ret < 0) { |
|
208 |
return ret; |
|
209 |
} |
|
210 |
} |
|
211 |
|
|
212 |
return 0; |
|
213 |
} |
|
214 |
#endif /* CONFIG_FDT */ |
b/hw/spapr_vio.h | ||
---|---|---|
1 |
#ifndef _HW_SPAPR_VIO_H |
|
2 |
#define _HW_SPAPR_VIO_H |
|
3 |
/* |
|
4 |
* QEMU sPAPR VIO bus definitions |
|
5 |
* |
|
6 |
* Copyright (c) 2010 David Gibson, IBM Corporation <david@gibson.dropbear.id.au> |
|
7 |
* Based on the s390 virtio bus definitions: |
|
8 |
* Copyright (c) 2009 Alexander Graf <agraf@suse.de> |
|
9 |
* |
|
10 |
* This library is free software; you can redistribute it and/or |
|
11 |
* modify it under the terms of the GNU Lesser General Public |
|
12 |
* License as published by the Free Software Foundation; either |
|
13 |
* version 2 of the License, or (at your option) any later version. |
|
14 |
* |
|
15 |
* This library is distributed in the hope that it will be useful, |
|
16 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
17 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
18 |
* Lesser General Public License for more details. |
|
19 |
* |
|
20 |
* You should have received a copy of the GNU Lesser General Public |
|
21 |
* License along with this library; if not, see <http://www.gnu.org/licenses/>. |
|
22 |
*/ |
|
23 |
|
|
24 |
typedef struct VIOsPAPRDevice { |
|
25 |
DeviceState qdev; |
|
26 |
uint32_t reg; |
|
27 |
} VIOsPAPRDevice; |
|
28 |
|
|
29 |
typedef struct VIOsPAPRBus { |
|
30 |
BusState bus; |
|
31 |
} VIOsPAPRBus; |
|
32 |
|
|
33 |
typedef struct { |
|
34 |
DeviceInfo qdev; |
|
35 |
const char *dt_name, *dt_type, *dt_compatible; |
|
36 |
int (*init)(VIOsPAPRDevice *dev); |
|
37 |
void (*hcalls)(VIOsPAPRBus *bus); |
|
38 |
int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off); |
|
39 |
} VIOsPAPRDeviceInfo; |
|
40 |
|
|
41 |
extern VIOsPAPRBus *spapr_vio_bus_init(void); |
|
42 |
extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg); |
|
43 |
extern void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info); |
|
44 |
extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt); |
|
45 |
|
|
46 |
void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len); |
|
47 |
void spapr_vty_create(VIOsPAPRBus *bus, |
|
48 |
uint32_t reg, CharDriverState *chardev); |
|
49 |
|
|
50 |
#endif /* _HW_SPAPR_VIO_H */ |
b/hw/spapr_vty.c | ||
---|---|---|
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); |
Also available in: Unified diff