root / hw / s390x / virtio-ccw.c @ f53f81e0
History | View | Annotate | Download (41.8 kB)
1 | a5cf2bb4 | Cornelia Huck | /*
|
---|---|---|---|
2 | a5cf2bb4 | Cornelia Huck | * virtio ccw target implementation
|
3 | a5cf2bb4 | Cornelia Huck | *
|
4 | a5cf2bb4 | Cornelia Huck | * Copyright 2012 IBM Corp.
|
5 | a5cf2bb4 | Cornelia Huck | * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
|
6 | a5cf2bb4 | Cornelia Huck | *
|
7 | a5cf2bb4 | Cornelia Huck | * This work is licensed under the terms of the GNU GPL, version 2 or (at
|
8 | a5cf2bb4 | Cornelia Huck | * your option) any later version. See the COPYING file in the top-level
|
9 | a5cf2bb4 | Cornelia Huck | * directory.
|
10 | a5cf2bb4 | Cornelia Huck | */
|
11 | a5cf2bb4 | Cornelia Huck | |
12 | a5cf2bb4 | Cornelia Huck | #include "hw/hw.h" |
13 | a5cf2bb4 | Cornelia Huck | #include "block/block.h" |
14 | a5cf2bb4 | Cornelia Huck | #include "sysemu/blockdev.h" |
15 | a5cf2bb4 | Cornelia Huck | #include "sysemu/sysemu.h" |
16 | a5cf2bb4 | Cornelia Huck | #include "net/net.h" |
17 | a5cf2bb4 | Cornelia Huck | #include "monitor/monitor.h" |
18 | 0d09e41a | Paolo Bonzini | #include "hw/virtio/virtio.h" |
19 | 0d09e41a | Paolo Bonzini | #include "hw/virtio/virtio-serial.h" |
20 | 0d09e41a | Paolo Bonzini | #include "hw/virtio/virtio-net.h" |
21 | a5cf2bb4 | Cornelia Huck | #include "hw/sysbus.h" |
22 | a5cf2bb4 | Cornelia Huck | #include "qemu/bitops.h" |
23 | 0d09e41a | Paolo Bonzini | #include "hw/virtio/virtio-bus.h" |
24 | a5cf2bb4 | Cornelia Huck | |
25 | a5cf2bb4 | Cornelia Huck | #include "ioinst.h" |
26 | a5cf2bb4 | Cornelia Huck | #include "css.h" |
27 | a5cf2bb4 | Cornelia Huck | #include "virtio-ccw.h" |
28 | a5cf2bb4 | Cornelia Huck | #include "trace.h" |
29 | a5cf2bb4 | Cornelia Huck | |
30 | 1bf4d7aa | Andreas Färber | static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size, |
31 | 1bf4d7aa | Andreas Färber | VirtioCcwDevice *dev); |
32 | d51fcfac | KONRAD Frederic | |
33 | dcc20931 | Paolo Bonzini | static void virtual_css_bus_reset(BusState *qbus) |
34 | a5cf2bb4 | Cornelia Huck | { |
35 | a5cf2bb4 | Cornelia Huck | /* This should actually be modelled via the generic css */
|
36 | a5cf2bb4 | Cornelia Huck | css_reset(); |
37 | a5cf2bb4 | Cornelia Huck | } |
38 | a5cf2bb4 | Cornelia Huck | |
39 | a5cf2bb4 | Cornelia Huck | |
40 | a5cf2bb4 | Cornelia Huck | static void virtual_css_bus_class_init(ObjectClass *klass, void *data) |
41 | a5cf2bb4 | Cornelia Huck | { |
42 | a5cf2bb4 | Cornelia Huck | BusClass *k = BUS_CLASS(klass); |
43 | a5cf2bb4 | Cornelia Huck | |
44 | a5cf2bb4 | Cornelia Huck | k->reset = virtual_css_bus_reset; |
45 | a5cf2bb4 | Cornelia Huck | } |
46 | a5cf2bb4 | Cornelia Huck | |
47 | a5cf2bb4 | Cornelia Huck | static const TypeInfo virtual_css_bus_info = { |
48 | a5cf2bb4 | Cornelia Huck | .name = TYPE_VIRTUAL_CSS_BUS, |
49 | a5cf2bb4 | Cornelia Huck | .parent = TYPE_BUS, |
50 | a5cf2bb4 | Cornelia Huck | .instance_size = sizeof(VirtualCssBus),
|
51 | a5cf2bb4 | Cornelia Huck | .class_init = virtual_css_bus_class_init, |
52 | a5cf2bb4 | Cornelia Huck | }; |
53 | a5cf2bb4 | Cornelia Huck | |
54 | a5cf2bb4 | Cornelia Huck | VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch) |
55 | a5cf2bb4 | Cornelia Huck | { |
56 | a5cf2bb4 | Cornelia Huck | VirtIODevice *vdev = NULL;
|
57 | f24a6840 | Paolo Bonzini | VirtioCcwDevice *dev = sch->driver_data; |
58 | a5cf2bb4 | Cornelia Huck | |
59 | f24a6840 | Paolo Bonzini | if (dev) {
|
60 | f24a6840 | Paolo Bonzini | vdev = virtio_bus_get_device(&dev->bus); |
61 | a5cf2bb4 | Cornelia Huck | } |
62 | a5cf2bb4 | Cornelia Huck | return vdev;
|
63 | a5cf2bb4 | Cornelia Huck | } |
64 | a5cf2bb4 | Cornelia Huck | |
65 | b4436a0b | Cornelia Huck | static int virtio_ccw_set_guest2host_notifier(VirtioCcwDevice *dev, int n, |
66 | b4436a0b | Cornelia Huck | bool assign, bool set_handler) |
67 | b4436a0b | Cornelia Huck | { |
68 | f24a6840 | Paolo Bonzini | VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); |
69 | f24a6840 | Paolo Bonzini | VirtQueue *vq = virtio_get_queue(vdev, n); |
70 | b4436a0b | Cornelia Huck | EventNotifier *notifier = virtio_queue_get_host_notifier(vq); |
71 | b4436a0b | Cornelia Huck | int r = 0; |
72 | b4436a0b | Cornelia Huck | SubchDev *sch = dev->sch; |
73 | b4436a0b | Cornelia Huck | uint32_t sch_id = (css_build_subchannel_id(sch) << 16) | sch->schid;
|
74 | b4436a0b | Cornelia Huck | |
75 | b4436a0b | Cornelia Huck | if (assign) {
|
76 | b4436a0b | Cornelia Huck | r = event_notifier_init(notifier, 1);
|
77 | b4436a0b | Cornelia Huck | if (r < 0) { |
78 | b4436a0b | Cornelia Huck | error_report("%s: unable to init event notifier: %d", __func__, r);
|
79 | b4436a0b | Cornelia Huck | return r;
|
80 | b4436a0b | Cornelia Huck | } |
81 | b4436a0b | Cornelia Huck | virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
|
82 | cc3ac9c4 | Cornelia Huck | r = s390_assign_subch_ioeventfd(notifier, sch_id, n, assign); |
83 | b4436a0b | Cornelia Huck | if (r < 0) { |
84 | b4436a0b | Cornelia Huck | error_report("%s: unable to assign ioeventfd: %d", __func__, r);
|
85 | b4436a0b | Cornelia Huck | virtio_queue_set_host_notifier_fd_handler(vq, false, false); |
86 | b4436a0b | Cornelia Huck | event_notifier_cleanup(notifier); |
87 | b4436a0b | Cornelia Huck | return r;
|
88 | b4436a0b | Cornelia Huck | } |
89 | b4436a0b | Cornelia Huck | } else {
|
90 | b4436a0b | Cornelia Huck | virtio_queue_set_host_notifier_fd_handler(vq, false, false); |
91 | cc3ac9c4 | Cornelia Huck | s390_assign_subch_ioeventfd(notifier, sch_id, n, assign); |
92 | b4436a0b | Cornelia Huck | event_notifier_cleanup(notifier); |
93 | b4436a0b | Cornelia Huck | } |
94 | b4436a0b | Cornelia Huck | return r;
|
95 | b4436a0b | Cornelia Huck | } |
96 | b4436a0b | Cornelia Huck | |
97 | b4436a0b | Cornelia Huck | static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev) |
98 | b4436a0b | Cornelia Huck | { |
99 | f24a6840 | Paolo Bonzini | VirtIODevice *vdev; |
100 | b4436a0b | Cornelia Huck | int n, r;
|
101 | b4436a0b | Cornelia Huck | |
102 | b4436a0b | Cornelia Huck | if (!(dev->flags & VIRTIO_CCW_FLAG_USE_IOEVENTFD) ||
|
103 | 320ce850 | Cornelia Huck | dev->ioeventfd_disabled || |
104 | b4436a0b | Cornelia Huck | dev->ioeventfd_started) { |
105 | b4436a0b | Cornelia Huck | return;
|
106 | b4436a0b | Cornelia Huck | } |
107 | f24a6840 | Paolo Bonzini | vdev = virtio_bus_get_device(&dev->bus); |
108 | b4436a0b | Cornelia Huck | for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) { |
109 | f24a6840 | Paolo Bonzini | if (!virtio_queue_get_num(vdev, n)) {
|
110 | b4436a0b | Cornelia Huck | continue;
|
111 | b4436a0b | Cornelia Huck | } |
112 | b4436a0b | Cornelia Huck | r = virtio_ccw_set_guest2host_notifier(dev, n, true, true); |
113 | b4436a0b | Cornelia Huck | if (r < 0) { |
114 | b4436a0b | Cornelia Huck | goto assign_error;
|
115 | b4436a0b | Cornelia Huck | } |
116 | b4436a0b | Cornelia Huck | } |
117 | b4436a0b | Cornelia Huck | dev->ioeventfd_started = true;
|
118 | b4436a0b | Cornelia Huck | return;
|
119 | b4436a0b | Cornelia Huck | |
120 | b4436a0b | Cornelia Huck | assign_error:
|
121 | b4436a0b | Cornelia Huck | while (--n >= 0) { |
122 | f24a6840 | Paolo Bonzini | if (!virtio_queue_get_num(vdev, n)) {
|
123 | b4436a0b | Cornelia Huck | continue;
|
124 | b4436a0b | Cornelia Huck | } |
125 | b4436a0b | Cornelia Huck | r = virtio_ccw_set_guest2host_notifier(dev, n, false, false); |
126 | b4436a0b | Cornelia Huck | assert(r >= 0);
|
127 | b4436a0b | Cornelia Huck | } |
128 | b4436a0b | Cornelia Huck | dev->ioeventfd_started = false;
|
129 | b4436a0b | Cornelia Huck | /* Disable ioeventfd for this device. */
|
130 | b4436a0b | Cornelia Huck | dev->flags &= ~VIRTIO_CCW_FLAG_USE_IOEVENTFD; |
131 | b4436a0b | Cornelia Huck | error_report("%s: failed. Fallback to userspace (slower).", __func__);
|
132 | b4436a0b | Cornelia Huck | } |
133 | b4436a0b | Cornelia Huck | |
134 | b4436a0b | Cornelia Huck | static void virtio_ccw_stop_ioeventfd(VirtioCcwDevice *dev) |
135 | b4436a0b | Cornelia Huck | { |
136 | f24a6840 | Paolo Bonzini | VirtIODevice *vdev; |
137 | b4436a0b | Cornelia Huck | int n, r;
|
138 | b4436a0b | Cornelia Huck | |
139 | b4436a0b | Cornelia Huck | if (!dev->ioeventfd_started) {
|
140 | b4436a0b | Cornelia Huck | return;
|
141 | b4436a0b | Cornelia Huck | } |
142 | f24a6840 | Paolo Bonzini | vdev = virtio_bus_get_device(&dev->bus); |
143 | b4436a0b | Cornelia Huck | for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) { |
144 | f24a6840 | Paolo Bonzini | if (!virtio_queue_get_num(vdev, n)) {
|
145 | b4436a0b | Cornelia Huck | continue;
|
146 | b4436a0b | Cornelia Huck | } |
147 | b4436a0b | Cornelia Huck | r = virtio_ccw_set_guest2host_notifier(dev, n, false, false); |
148 | b4436a0b | Cornelia Huck | assert(r >= 0);
|
149 | b4436a0b | Cornelia Huck | } |
150 | b4436a0b | Cornelia Huck | dev->ioeventfd_started = false;
|
151 | b4436a0b | Cornelia Huck | } |
152 | b4436a0b | Cornelia Huck | |
153 | a5cf2bb4 | Cornelia Huck | VirtualCssBus *virtual_css_bus_init(void)
|
154 | a5cf2bb4 | Cornelia Huck | { |
155 | a5cf2bb4 | Cornelia Huck | VirtualCssBus *cbus; |
156 | a5cf2bb4 | Cornelia Huck | BusState *bus; |
157 | a5cf2bb4 | Cornelia Huck | DeviceState *dev; |
158 | a5cf2bb4 | Cornelia Huck | |
159 | a5cf2bb4 | Cornelia Huck | /* Create bridge device */
|
160 | a5cf2bb4 | Cornelia Huck | dev = qdev_create(NULL, "virtual-css-bridge"); |
161 | a5cf2bb4 | Cornelia Huck | qdev_init_nofail(dev); |
162 | a5cf2bb4 | Cornelia Huck | |
163 | a5cf2bb4 | Cornelia Huck | /* Create bus on bridge device */
|
164 | a5cf2bb4 | Cornelia Huck | bus = qbus_create(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css");
|
165 | a5cf2bb4 | Cornelia Huck | cbus = VIRTUAL_CSS_BUS(bus); |
166 | a5cf2bb4 | Cornelia Huck | |
167 | a5cf2bb4 | Cornelia Huck | /* Enable hotplugging */
|
168 | a5cf2bb4 | Cornelia Huck | bus->allow_hotplug = 1;
|
169 | a5cf2bb4 | Cornelia Huck | |
170 | a5cf2bb4 | Cornelia Huck | return cbus;
|
171 | a5cf2bb4 | Cornelia Huck | } |
172 | a5cf2bb4 | Cornelia Huck | |
173 | a5cf2bb4 | Cornelia Huck | /* Communication blocks used by several channel commands. */
|
174 | a5cf2bb4 | Cornelia Huck | typedef struct VqInfoBlock { |
175 | a5cf2bb4 | Cornelia Huck | uint64_t queue; |
176 | a5cf2bb4 | Cornelia Huck | uint32_t align; |
177 | a5cf2bb4 | Cornelia Huck | uint16_t index; |
178 | a5cf2bb4 | Cornelia Huck | uint16_t num; |
179 | a5cf2bb4 | Cornelia Huck | } QEMU_PACKED VqInfoBlock; |
180 | a5cf2bb4 | Cornelia Huck | |
181 | a5cf2bb4 | Cornelia Huck | typedef struct VqConfigBlock { |
182 | a5cf2bb4 | Cornelia Huck | uint16_t index; |
183 | a5cf2bb4 | Cornelia Huck | uint16_t num_max; |
184 | a5cf2bb4 | Cornelia Huck | } QEMU_PACKED VqConfigBlock; |
185 | a5cf2bb4 | Cornelia Huck | |
186 | a5cf2bb4 | Cornelia Huck | typedef struct VirtioFeatDesc { |
187 | a5cf2bb4 | Cornelia Huck | uint32_t features; |
188 | a5cf2bb4 | Cornelia Huck | uint8_t index; |
189 | a5cf2bb4 | Cornelia Huck | } QEMU_PACKED VirtioFeatDesc; |
190 | a5cf2bb4 | Cornelia Huck | |
191 | a5cf2bb4 | Cornelia Huck | /* Specify where the virtqueues for the subchannel are in guest memory. */
|
192 | a5cf2bb4 | Cornelia Huck | static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align, |
193 | a5cf2bb4 | Cornelia Huck | uint16_t index, uint16_t num) |
194 | a5cf2bb4 | Cornelia Huck | { |
195 | f24a6840 | Paolo Bonzini | VirtIODevice *vdev = virtio_ccw_get_vdev(sch); |
196 | a5cf2bb4 | Cornelia Huck | |
197 | a5cf2bb4 | Cornelia Huck | if (index > VIRTIO_PCI_QUEUE_MAX) {
|
198 | a5cf2bb4 | Cornelia Huck | return -EINVAL;
|
199 | a5cf2bb4 | Cornelia Huck | } |
200 | a5cf2bb4 | Cornelia Huck | |
201 | a5cf2bb4 | Cornelia Huck | /* Current code in virtio.c relies on 4K alignment. */
|
202 | a5cf2bb4 | Cornelia Huck | if (addr && (align != 4096)) { |
203 | a5cf2bb4 | Cornelia Huck | return -EINVAL;
|
204 | a5cf2bb4 | Cornelia Huck | } |
205 | a5cf2bb4 | Cornelia Huck | |
206 | f24a6840 | Paolo Bonzini | if (!vdev) {
|
207 | a5cf2bb4 | Cornelia Huck | return -EINVAL;
|
208 | a5cf2bb4 | Cornelia Huck | } |
209 | a5cf2bb4 | Cornelia Huck | |
210 | f24a6840 | Paolo Bonzini | virtio_queue_set_addr(vdev, index, addr); |
211 | a5cf2bb4 | Cornelia Huck | if (!addr) {
|
212 | f24a6840 | Paolo Bonzini | virtio_queue_set_vector(vdev, index, 0);
|
213 | a5cf2bb4 | Cornelia Huck | } else {
|
214 | a5cf2bb4 | Cornelia Huck | /* Fail if we don't have a big enough queue. */
|
215 | a5cf2bb4 | Cornelia Huck | /* TODO: Add interface to handle vring.num changing */
|
216 | f24a6840 | Paolo Bonzini | if (virtio_queue_get_num(vdev, index) > num) {
|
217 | a5cf2bb4 | Cornelia Huck | return -EINVAL;
|
218 | a5cf2bb4 | Cornelia Huck | } |
219 | f24a6840 | Paolo Bonzini | virtio_queue_set_vector(vdev, index, index); |
220 | a5cf2bb4 | Cornelia Huck | } |
221 | a5cf2bb4 | Cornelia Huck | /* tell notify handler in case of config change */
|
222 | f24a6840 | Paolo Bonzini | vdev->config_vector = VIRTIO_PCI_QUEUE_MAX; |
223 | a5cf2bb4 | Cornelia Huck | return 0; |
224 | a5cf2bb4 | Cornelia Huck | } |
225 | a5cf2bb4 | Cornelia Huck | |
226 | a5cf2bb4 | Cornelia Huck | static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) |
227 | a5cf2bb4 | Cornelia Huck | { |
228 | a5cf2bb4 | Cornelia Huck | int ret;
|
229 | a5cf2bb4 | Cornelia Huck | VqInfoBlock info; |
230 | a5cf2bb4 | Cornelia Huck | uint8_t status; |
231 | a5cf2bb4 | Cornelia Huck | VirtioFeatDesc features; |
232 | a5cf2bb4 | Cornelia Huck | void *config;
|
233 | a5cf2bb4 | Cornelia Huck | hwaddr indicators; |
234 | a5cf2bb4 | Cornelia Huck | VqConfigBlock vq_config; |
235 | a5cf2bb4 | Cornelia Huck | VirtioCcwDevice *dev = sch->driver_data; |
236 | f24a6840 | Paolo Bonzini | VirtIODevice *vdev = virtio_ccw_get_vdev(sch); |
237 | a5cf2bb4 | Cornelia Huck | bool check_len;
|
238 | a5cf2bb4 | Cornelia Huck | int len;
|
239 | a5cf2bb4 | Cornelia Huck | hwaddr hw_len; |
240 | a5cf2bb4 | Cornelia Huck | |
241 | a5cf2bb4 | Cornelia Huck | if (!dev) {
|
242 | a5cf2bb4 | Cornelia Huck | return -EINVAL;
|
243 | a5cf2bb4 | Cornelia Huck | } |
244 | a5cf2bb4 | Cornelia Huck | |
245 | a5cf2bb4 | Cornelia Huck | trace_virtio_ccw_interpret_ccw(sch->cssid, sch->ssid, sch->schid, |
246 | a5cf2bb4 | Cornelia Huck | ccw.cmd_code); |
247 | a5cf2bb4 | Cornelia Huck | check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC)); |
248 | a5cf2bb4 | Cornelia Huck | |
249 | a5cf2bb4 | Cornelia Huck | /* Look at the command. */
|
250 | a5cf2bb4 | Cornelia Huck | switch (ccw.cmd_code) {
|
251 | a5cf2bb4 | Cornelia Huck | case CCW_CMD_SET_VQ:
|
252 | a5cf2bb4 | Cornelia Huck | if (check_len) {
|
253 | a5cf2bb4 | Cornelia Huck | if (ccw.count != sizeof(info)) { |
254 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
255 | a5cf2bb4 | Cornelia Huck | break;
|
256 | a5cf2bb4 | Cornelia Huck | } |
257 | a5cf2bb4 | Cornelia Huck | } else if (ccw.count < sizeof(info)) { |
258 | a5cf2bb4 | Cornelia Huck | /* Can't execute command. */
|
259 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
260 | a5cf2bb4 | Cornelia Huck | break;
|
261 | a5cf2bb4 | Cornelia Huck | } |
262 | a5cf2bb4 | Cornelia Huck | if (!ccw.cda) {
|
263 | a5cf2bb4 | Cornelia Huck | ret = -EFAULT; |
264 | a5cf2bb4 | Cornelia Huck | } else {
|
265 | 2c17449b | Edgar E. Iglesias | info.queue = ldq_phys(&address_space_memory, ccw.cda); |
266 | fdfba1a2 | Edgar E. Iglesias | info.align = ldl_phys(&address_space_memory, |
267 | fdfba1a2 | Edgar E. Iglesias | ccw.cda + sizeof(info.queue));
|
268 | 41701aa4 | Edgar E. Iglesias | info.index = lduw_phys(&address_space_memory, |
269 | 41701aa4 | Edgar E. Iglesias | ccw.cda + sizeof(info.queue)
|
270 | a5cf2bb4 | Cornelia Huck | + sizeof(info.align));
|
271 | 41701aa4 | Edgar E. Iglesias | info.num = lduw_phys(&address_space_memory, |
272 | 41701aa4 | Edgar E. Iglesias | ccw.cda + sizeof(info.queue)
|
273 | a5cf2bb4 | Cornelia Huck | + sizeof(info.align)
|
274 | a5cf2bb4 | Cornelia Huck | + sizeof(info.index));
|
275 | a5cf2bb4 | Cornelia Huck | ret = virtio_ccw_set_vqs(sch, info.queue, info.align, info.index, |
276 | a5cf2bb4 | Cornelia Huck | info.num); |
277 | a5cf2bb4 | Cornelia Huck | sch->curr_status.scsw.count = 0;
|
278 | a5cf2bb4 | Cornelia Huck | } |
279 | a5cf2bb4 | Cornelia Huck | break;
|
280 | a5cf2bb4 | Cornelia Huck | case CCW_CMD_VDEV_RESET:
|
281 | b4436a0b | Cornelia Huck | virtio_ccw_stop_ioeventfd(dev); |
282 | f24a6840 | Paolo Bonzini | virtio_reset(vdev); |
283 | a5cf2bb4 | Cornelia Huck | ret = 0;
|
284 | a5cf2bb4 | Cornelia Huck | break;
|
285 | a5cf2bb4 | Cornelia Huck | case CCW_CMD_READ_FEAT:
|
286 | a5cf2bb4 | Cornelia Huck | if (check_len) {
|
287 | a5cf2bb4 | Cornelia Huck | if (ccw.count != sizeof(features)) { |
288 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
289 | a5cf2bb4 | Cornelia Huck | break;
|
290 | a5cf2bb4 | Cornelia Huck | } |
291 | a5cf2bb4 | Cornelia Huck | } else if (ccw.count < sizeof(features)) { |
292 | a5cf2bb4 | Cornelia Huck | /* Can't execute command. */
|
293 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
294 | a5cf2bb4 | Cornelia Huck | break;
|
295 | a5cf2bb4 | Cornelia Huck | } |
296 | a5cf2bb4 | Cornelia Huck | if (!ccw.cda) {
|
297 | a5cf2bb4 | Cornelia Huck | ret = -EFAULT; |
298 | a5cf2bb4 | Cornelia Huck | } else {
|
299 | 2c17449b | Edgar E. Iglesias | features.index = ldub_phys(&address_space_memory, |
300 | 2c17449b | Edgar E. Iglesias | ccw.cda + sizeof(features.features));
|
301 | a5cf2bb4 | Cornelia Huck | if (features.index < ARRAY_SIZE(dev->host_features)) {
|
302 | a5cf2bb4 | Cornelia Huck | features.features = dev->host_features[features.index]; |
303 | a5cf2bb4 | Cornelia Huck | } else {
|
304 | a5cf2bb4 | Cornelia Huck | /* Return zeroes if the guest supports more feature bits. */
|
305 | a5cf2bb4 | Cornelia Huck | features.features = 0;
|
306 | a5cf2bb4 | Cornelia Huck | } |
307 | ab1da857 | Edgar E. Iglesias | stl_le_phys(&address_space_memory, ccw.cda, features.features); |
308 | a5cf2bb4 | Cornelia Huck | sch->curr_status.scsw.count = ccw.count - sizeof(features);
|
309 | a5cf2bb4 | Cornelia Huck | ret = 0;
|
310 | a5cf2bb4 | Cornelia Huck | } |
311 | a5cf2bb4 | Cornelia Huck | break;
|
312 | a5cf2bb4 | Cornelia Huck | case CCW_CMD_WRITE_FEAT:
|
313 | a5cf2bb4 | Cornelia Huck | if (check_len) {
|
314 | a5cf2bb4 | Cornelia Huck | if (ccw.count != sizeof(features)) { |
315 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
316 | a5cf2bb4 | Cornelia Huck | break;
|
317 | a5cf2bb4 | Cornelia Huck | } |
318 | a5cf2bb4 | Cornelia Huck | } else if (ccw.count < sizeof(features)) { |
319 | a5cf2bb4 | Cornelia Huck | /* Can't execute command. */
|
320 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
321 | a5cf2bb4 | Cornelia Huck | break;
|
322 | a5cf2bb4 | Cornelia Huck | } |
323 | a5cf2bb4 | Cornelia Huck | if (!ccw.cda) {
|
324 | a5cf2bb4 | Cornelia Huck | ret = -EFAULT; |
325 | a5cf2bb4 | Cornelia Huck | } else {
|
326 | 2c17449b | Edgar E. Iglesias | features.index = ldub_phys(&address_space_memory, |
327 | 2c17449b | Edgar E. Iglesias | ccw.cda + sizeof(features.features));
|
328 | fdfba1a2 | Edgar E. Iglesias | features.features = ldl_le_phys(&address_space_memory, ccw.cda); |
329 | a5cf2bb4 | Cornelia Huck | if (features.index < ARRAY_SIZE(dev->host_features)) {
|
330 | 181103cd | KONRAD Frederic | virtio_bus_set_vdev_features(&dev->bus, features.features); |
331 | f24a6840 | Paolo Bonzini | vdev->guest_features = features.features; |
332 | a5cf2bb4 | Cornelia Huck | } else {
|
333 | a5cf2bb4 | Cornelia Huck | /*
|
334 | a5cf2bb4 | Cornelia Huck | * If the guest supports more feature bits, assert that it
|
335 | a5cf2bb4 | Cornelia Huck | * passes us zeroes for those we don't support.
|
336 | a5cf2bb4 | Cornelia Huck | */
|
337 | a5cf2bb4 | Cornelia Huck | if (features.features) {
|
338 | a5cf2bb4 | Cornelia Huck | fprintf(stderr, "Guest bug: features[%i]=%x (expected 0)\n",
|
339 | a5cf2bb4 | Cornelia Huck | features.index, features.features); |
340 | a5cf2bb4 | Cornelia Huck | /* XXX: do a unit check here? */
|
341 | a5cf2bb4 | Cornelia Huck | } |
342 | a5cf2bb4 | Cornelia Huck | } |
343 | a5cf2bb4 | Cornelia Huck | sch->curr_status.scsw.count = ccw.count - sizeof(features);
|
344 | a5cf2bb4 | Cornelia Huck | ret = 0;
|
345 | a5cf2bb4 | Cornelia Huck | } |
346 | a5cf2bb4 | Cornelia Huck | break;
|
347 | a5cf2bb4 | Cornelia Huck | case CCW_CMD_READ_CONF:
|
348 | a5cf2bb4 | Cornelia Huck | if (check_len) {
|
349 | f24a6840 | Paolo Bonzini | if (ccw.count > vdev->config_len) {
|
350 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
351 | a5cf2bb4 | Cornelia Huck | break;
|
352 | a5cf2bb4 | Cornelia Huck | } |
353 | a5cf2bb4 | Cornelia Huck | } |
354 | f24a6840 | Paolo Bonzini | len = MIN(ccw.count, vdev->config_len); |
355 | a5cf2bb4 | Cornelia Huck | if (!ccw.cda) {
|
356 | a5cf2bb4 | Cornelia Huck | ret = -EFAULT; |
357 | a5cf2bb4 | Cornelia Huck | } else {
|
358 | f24a6840 | Paolo Bonzini | virtio_bus_get_vdev_config(&dev->bus, vdev->config); |
359 | a5cf2bb4 | Cornelia Huck | /* XXX config space endianness */
|
360 | f24a6840 | Paolo Bonzini | cpu_physical_memory_write(ccw.cda, vdev->config, len); |
361 | a5cf2bb4 | Cornelia Huck | sch->curr_status.scsw.count = ccw.count - len; |
362 | a5cf2bb4 | Cornelia Huck | ret = 0;
|
363 | a5cf2bb4 | Cornelia Huck | } |
364 | a5cf2bb4 | Cornelia Huck | break;
|
365 | a5cf2bb4 | Cornelia Huck | case CCW_CMD_WRITE_CONF:
|
366 | a5cf2bb4 | Cornelia Huck | if (check_len) {
|
367 | f24a6840 | Paolo Bonzini | if (ccw.count > vdev->config_len) {
|
368 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
369 | a5cf2bb4 | Cornelia Huck | break;
|
370 | a5cf2bb4 | Cornelia Huck | } |
371 | a5cf2bb4 | Cornelia Huck | } |
372 | f24a6840 | Paolo Bonzini | len = MIN(ccw.count, vdev->config_len); |
373 | a5cf2bb4 | Cornelia Huck | hw_len = len; |
374 | a5cf2bb4 | Cornelia Huck | if (!ccw.cda) {
|
375 | a5cf2bb4 | Cornelia Huck | ret = -EFAULT; |
376 | a5cf2bb4 | Cornelia Huck | } else {
|
377 | a5cf2bb4 | Cornelia Huck | config = cpu_physical_memory_map(ccw.cda, &hw_len, 0);
|
378 | a5cf2bb4 | Cornelia Huck | if (!config) {
|
379 | a5cf2bb4 | Cornelia Huck | ret = -EFAULT; |
380 | a5cf2bb4 | Cornelia Huck | } else {
|
381 | a5cf2bb4 | Cornelia Huck | len = hw_len; |
382 | a5cf2bb4 | Cornelia Huck | /* XXX config space endianness */
|
383 | f24a6840 | Paolo Bonzini | memcpy(vdev->config, config, len); |
384 | a5cf2bb4 | Cornelia Huck | cpu_physical_memory_unmap(config, hw_len, 0, hw_len);
|
385 | f24a6840 | Paolo Bonzini | virtio_bus_set_vdev_config(&dev->bus, vdev->config); |
386 | a5cf2bb4 | Cornelia Huck | sch->curr_status.scsw.count = ccw.count - len; |
387 | a5cf2bb4 | Cornelia Huck | ret = 0;
|
388 | a5cf2bb4 | Cornelia Huck | } |
389 | a5cf2bb4 | Cornelia Huck | } |
390 | a5cf2bb4 | Cornelia Huck | break;
|
391 | a5cf2bb4 | Cornelia Huck | case CCW_CMD_WRITE_STATUS:
|
392 | a5cf2bb4 | Cornelia Huck | if (check_len) {
|
393 | a5cf2bb4 | Cornelia Huck | if (ccw.count != sizeof(status)) { |
394 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
395 | a5cf2bb4 | Cornelia Huck | break;
|
396 | a5cf2bb4 | Cornelia Huck | } |
397 | a5cf2bb4 | Cornelia Huck | } else if (ccw.count < sizeof(status)) { |
398 | a5cf2bb4 | Cornelia Huck | /* Can't execute command. */
|
399 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
400 | a5cf2bb4 | Cornelia Huck | break;
|
401 | a5cf2bb4 | Cornelia Huck | } |
402 | a5cf2bb4 | Cornelia Huck | if (!ccw.cda) {
|
403 | a5cf2bb4 | Cornelia Huck | ret = -EFAULT; |
404 | a5cf2bb4 | Cornelia Huck | } else {
|
405 | 2c17449b | Edgar E. Iglesias | status = ldub_phys(&address_space_memory, ccw.cda); |
406 | b4436a0b | Cornelia Huck | if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
407 | b4436a0b | Cornelia Huck | virtio_ccw_stop_ioeventfd(dev); |
408 | b4436a0b | Cornelia Huck | } |
409 | f24a6840 | Paolo Bonzini | virtio_set_status(vdev, status); |
410 | f24a6840 | Paolo Bonzini | if (vdev->status == 0) { |
411 | f24a6840 | Paolo Bonzini | virtio_reset(vdev); |
412 | a5cf2bb4 | Cornelia Huck | } |
413 | b4436a0b | Cornelia Huck | if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
|
414 | b4436a0b | Cornelia Huck | virtio_ccw_start_ioeventfd(dev); |
415 | b4436a0b | Cornelia Huck | } |
416 | a5cf2bb4 | Cornelia Huck | sch->curr_status.scsw.count = ccw.count - sizeof(status);
|
417 | a5cf2bb4 | Cornelia Huck | ret = 0;
|
418 | a5cf2bb4 | Cornelia Huck | } |
419 | a5cf2bb4 | Cornelia Huck | break;
|
420 | a5cf2bb4 | Cornelia Huck | case CCW_CMD_SET_IND:
|
421 | a5cf2bb4 | Cornelia Huck | if (check_len) {
|
422 | a5cf2bb4 | Cornelia Huck | if (ccw.count != sizeof(indicators)) { |
423 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
424 | a5cf2bb4 | Cornelia Huck | break;
|
425 | a5cf2bb4 | Cornelia Huck | } |
426 | a5cf2bb4 | Cornelia Huck | } else if (ccw.count < sizeof(indicators)) { |
427 | a5cf2bb4 | Cornelia Huck | /* Can't execute command. */
|
428 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
429 | a5cf2bb4 | Cornelia Huck | break;
|
430 | a5cf2bb4 | Cornelia Huck | } |
431 | d1db1fa8 | Cornelia Huck | if (!ccw.cda) {
|
432 | a5cf2bb4 | Cornelia Huck | ret = -EFAULT; |
433 | a5cf2bb4 | Cornelia Huck | } else {
|
434 | 2c17449b | Edgar E. Iglesias | indicators = ldq_phys(&address_space_memory, ccw.cda); |
435 | a5cf2bb4 | Cornelia Huck | dev->indicators = indicators; |
436 | a5cf2bb4 | Cornelia Huck | sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
|
437 | a5cf2bb4 | Cornelia Huck | ret = 0;
|
438 | a5cf2bb4 | Cornelia Huck | } |
439 | a5cf2bb4 | Cornelia Huck | break;
|
440 | a5cf2bb4 | Cornelia Huck | case CCW_CMD_SET_CONF_IND:
|
441 | a5cf2bb4 | Cornelia Huck | if (check_len) {
|
442 | a5cf2bb4 | Cornelia Huck | if (ccw.count != sizeof(indicators)) { |
443 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
444 | a5cf2bb4 | Cornelia Huck | break;
|
445 | a5cf2bb4 | Cornelia Huck | } |
446 | a5cf2bb4 | Cornelia Huck | } else if (ccw.count < sizeof(indicators)) { |
447 | a5cf2bb4 | Cornelia Huck | /* Can't execute command. */
|
448 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
449 | a5cf2bb4 | Cornelia Huck | break;
|
450 | a5cf2bb4 | Cornelia Huck | } |
451 | d1db1fa8 | Cornelia Huck | if (!ccw.cda) {
|
452 | a5cf2bb4 | Cornelia Huck | ret = -EFAULT; |
453 | a5cf2bb4 | Cornelia Huck | } else {
|
454 | 2c17449b | Edgar E. Iglesias | indicators = ldq_phys(&address_space_memory, ccw.cda); |
455 | a5cf2bb4 | Cornelia Huck | dev->indicators2 = indicators; |
456 | a5cf2bb4 | Cornelia Huck | sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
|
457 | a5cf2bb4 | Cornelia Huck | ret = 0;
|
458 | a5cf2bb4 | Cornelia Huck | } |
459 | a5cf2bb4 | Cornelia Huck | break;
|
460 | a5cf2bb4 | Cornelia Huck | case CCW_CMD_READ_VQ_CONF:
|
461 | a5cf2bb4 | Cornelia Huck | if (check_len) {
|
462 | a5cf2bb4 | Cornelia Huck | if (ccw.count != sizeof(vq_config)) { |
463 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
464 | a5cf2bb4 | Cornelia Huck | break;
|
465 | a5cf2bb4 | Cornelia Huck | } |
466 | a5cf2bb4 | Cornelia Huck | } else if (ccw.count < sizeof(vq_config)) { |
467 | a5cf2bb4 | Cornelia Huck | /* Can't execute command. */
|
468 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
469 | a5cf2bb4 | Cornelia Huck | break;
|
470 | a5cf2bb4 | Cornelia Huck | } |
471 | a5cf2bb4 | Cornelia Huck | if (!ccw.cda) {
|
472 | a5cf2bb4 | Cornelia Huck | ret = -EFAULT; |
473 | a5cf2bb4 | Cornelia Huck | } else {
|
474 | 41701aa4 | Edgar E. Iglesias | vq_config.index = lduw_phys(&address_space_memory, ccw.cda); |
475 | f24a6840 | Paolo Bonzini | vq_config.num_max = virtio_queue_get_num(vdev, |
476 | a5cf2bb4 | Cornelia Huck | vq_config.index); |
477 | 5ce5944d | Edgar E. Iglesias | stw_phys(&address_space_memory, |
478 | 5ce5944d | Edgar E. Iglesias | ccw.cda + sizeof(vq_config.index), vq_config.num_max);
|
479 | a5cf2bb4 | Cornelia Huck | sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
|
480 | a5cf2bb4 | Cornelia Huck | ret = 0;
|
481 | a5cf2bb4 | Cornelia Huck | } |
482 | a5cf2bb4 | Cornelia Huck | break;
|
483 | a5cf2bb4 | Cornelia Huck | default:
|
484 | 8d034a6f | Cornelia Huck | ret = -ENOSYS; |
485 | a5cf2bb4 | Cornelia Huck | break;
|
486 | a5cf2bb4 | Cornelia Huck | } |
487 | a5cf2bb4 | Cornelia Huck | return ret;
|
488 | a5cf2bb4 | Cornelia Huck | } |
489 | a5cf2bb4 | Cornelia Huck | |
490 | a5cf2bb4 | Cornelia Huck | static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev) |
491 | a5cf2bb4 | Cornelia Huck | { |
492 | a5cf2bb4 | Cornelia Huck | unsigned int cssid = 0; |
493 | a5cf2bb4 | Cornelia Huck | unsigned int ssid = 0; |
494 | a5cf2bb4 | Cornelia Huck | unsigned int schid; |
495 | a5cf2bb4 | Cornelia Huck | unsigned int devno; |
496 | a5cf2bb4 | Cornelia Huck | bool have_devno = false; |
497 | a5cf2bb4 | Cornelia Huck | bool found = false; |
498 | a5cf2bb4 | Cornelia Huck | SubchDev *sch; |
499 | a5cf2bb4 | Cornelia Huck | int ret;
|
500 | a5cf2bb4 | Cornelia Huck | int num;
|
501 | a5cf2bb4 | Cornelia Huck | DeviceState *parent = DEVICE(dev); |
502 | a5cf2bb4 | Cornelia Huck | |
503 | a5cf2bb4 | Cornelia Huck | sch = g_malloc0(sizeof(SubchDev));
|
504 | a5cf2bb4 | Cornelia Huck | |
505 | a5cf2bb4 | Cornelia Huck | sch->driver_data = dev; |
506 | a5cf2bb4 | Cornelia Huck | dev->sch = sch; |
507 | a5cf2bb4 | Cornelia Huck | |
508 | a5cf2bb4 | Cornelia Huck | dev->indicators = 0;
|
509 | a5cf2bb4 | Cornelia Huck | |
510 | a5cf2bb4 | Cornelia Huck | /* Initialize subchannel structure. */
|
511 | a5cf2bb4 | Cornelia Huck | sch->channel_prog = 0x0;
|
512 | a5cf2bb4 | Cornelia Huck | sch->last_cmd_valid = false;
|
513 | a5cf2bb4 | Cornelia Huck | sch->orb = NULL;
|
514 | a5cf2bb4 | Cornelia Huck | /*
|
515 | a5cf2bb4 | Cornelia Huck | * Use a device number if provided. Otherwise, fall back to subchannel
|
516 | a5cf2bb4 | Cornelia Huck | * number.
|
517 | a5cf2bb4 | Cornelia Huck | */
|
518 | a5cf2bb4 | Cornelia Huck | if (dev->bus_id) {
|
519 | a5cf2bb4 | Cornelia Huck | num = sscanf(dev->bus_id, "%x.%x.%04x", &cssid, &ssid, &devno);
|
520 | a5cf2bb4 | Cornelia Huck | if (num == 3) { |
521 | a5cf2bb4 | Cornelia Huck | if ((cssid > MAX_CSSID) || (ssid > MAX_SSID)) {
|
522 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
523 | a5cf2bb4 | Cornelia Huck | error_report("Invalid cssid or ssid: cssid %x, ssid %x",
|
524 | a5cf2bb4 | Cornelia Huck | cssid, ssid); |
525 | a5cf2bb4 | Cornelia Huck | goto out_err;
|
526 | a5cf2bb4 | Cornelia Huck | } |
527 | a5cf2bb4 | Cornelia Huck | /* Enforce use of virtual cssid. */
|
528 | a5cf2bb4 | Cornelia Huck | if (cssid != VIRTUAL_CSSID) {
|
529 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
530 | a5cf2bb4 | Cornelia Huck | error_report("cssid %x not valid for virtio devices", cssid);
|
531 | a5cf2bb4 | Cornelia Huck | goto out_err;
|
532 | a5cf2bb4 | Cornelia Huck | } |
533 | a5cf2bb4 | Cornelia Huck | if (css_devno_used(cssid, ssid, devno)) {
|
534 | a5cf2bb4 | Cornelia Huck | ret = -EEXIST; |
535 | a5cf2bb4 | Cornelia Huck | error_report("Device %x.%x.%04x already exists", cssid, ssid,
|
536 | a5cf2bb4 | Cornelia Huck | devno); |
537 | a5cf2bb4 | Cornelia Huck | goto out_err;
|
538 | a5cf2bb4 | Cornelia Huck | } |
539 | a5cf2bb4 | Cornelia Huck | sch->cssid = cssid; |
540 | a5cf2bb4 | Cornelia Huck | sch->ssid = ssid; |
541 | a5cf2bb4 | Cornelia Huck | sch->devno = devno; |
542 | a5cf2bb4 | Cornelia Huck | have_devno = true;
|
543 | a5cf2bb4 | Cornelia Huck | } else {
|
544 | a5cf2bb4 | Cornelia Huck | ret = -EINVAL; |
545 | a5cf2bb4 | Cornelia Huck | error_report("Malformed devno parameter '%s'", dev->bus_id);
|
546 | a5cf2bb4 | Cornelia Huck | goto out_err;
|
547 | a5cf2bb4 | Cornelia Huck | } |
548 | a5cf2bb4 | Cornelia Huck | } |
549 | a5cf2bb4 | Cornelia Huck | |
550 | a5cf2bb4 | Cornelia Huck | /* Find the next free id. */
|
551 | a5cf2bb4 | Cornelia Huck | if (have_devno) {
|
552 | a5cf2bb4 | Cornelia Huck | for (schid = 0; schid <= MAX_SCHID; schid++) { |
553 | a5cf2bb4 | Cornelia Huck | if (!css_find_subch(1, cssid, ssid, schid)) { |
554 | a5cf2bb4 | Cornelia Huck | sch->schid = schid; |
555 | a5cf2bb4 | Cornelia Huck | css_subch_assign(cssid, ssid, schid, devno, sch); |
556 | a5cf2bb4 | Cornelia Huck | found = true;
|
557 | a5cf2bb4 | Cornelia Huck | break;
|
558 | a5cf2bb4 | Cornelia Huck | } |
559 | a5cf2bb4 | Cornelia Huck | } |
560 | a5cf2bb4 | Cornelia Huck | if (!found) {
|
561 | a5cf2bb4 | Cornelia Huck | ret = -ENODEV; |
562 | a5cf2bb4 | Cornelia Huck | error_report("No free subchannel found for %x.%x.%04x", cssid, ssid,
|
563 | a5cf2bb4 | Cornelia Huck | devno); |
564 | a5cf2bb4 | Cornelia Huck | goto out_err;
|
565 | a5cf2bb4 | Cornelia Huck | } |
566 | a5cf2bb4 | Cornelia Huck | trace_virtio_ccw_new_device(cssid, ssid, schid, devno, |
567 | a5cf2bb4 | Cornelia Huck | "user-configured");
|
568 | a5cf2bb4 | Cornelia Huck | } else {
|
569 | a5cf2bb4 | Cornelia Huck | cssid = VIRTUAL_CSSID; |
570 | a5cf2bb4 | Cornelia Huck | for (ssid = 0; ssid <= MAX_SSID; ssid++) { |
571 | a5cf2bb4 | Cornelia Huck | for (schid = 0; schid <= MAX_SCHID; schid++) { |
572 | a5cf2bb4 | Cornelia Huck | if (!css_find_subch(1, cssid, ssid, schid)) { |
573 | a5cf2bb4 | Cornelia Huck | sch->cssid = cssid; |
574 | a5cf2bb4 | Cornelia Huck | sch->ssid = ssid; |
575 | a5cf2bb4 | Cornelia Huck | sch->schid = schid; |
576 | a5cf2bb4 | Cornelia Huck | devno = schid; |
577 | a5cf2bb4 | Cornelia Huck | /*
|
578 | a5cf2bb4 | Cornelia Huck | * If the devno is already taken, look further in this
|
579 | a5cf2bb4 | Cornelia Huck | * subchannel set.
|
580 | a5cf2bb4 | Cornelia Huck | */
|
581 | a5cf2bb4 | Cornelia Huck | while (css_devno_used(cssid, ssid, devno)) {
|
582 | a5cf2bb4 | Cornelia Huck | if (devno == MAX_SCHID) {
|
583 | a5cf2bb4 | Cornelia Huck | devno = 0;
|
584 | a5cf2bb4 | Cornelia Huck | } else if (devno == schid - 1) { |
585 | a5cf2bb4 | Cornelia Huck | ret = -ENODEV; |
586 | a5cf2bb4 | Cornelia Huck | error_report("No free devno found");
|
587 | a5cf2bb4 | Cornelia Huck | goto out_err;
|
588 | a5cf2bb4 | Cornelia Huck | } else {
|
589 | a5cf2bb4 | Cornelia Huck | devno++; |
590 | a5cf2bb4 | Cornelia Huck | } |
591 | a5cf2bb4 | Cornelia Huck | } |
592 | a5cf2bb4 | Cornelia Huck | sch->devno = devno; |
593 | a5cf2bb4 | Cornelia Huck | css_subch_assign(cssid, ssid, schid, devno, sch); |
594 | a5cf2bb4 | Cornelia Huck | found = true;
|
595 | a5cf2bb4 | Cornelia Huck | break;
|
596 | a5cf2bb4 | Cornelia Huck | } |
597 | a5cf2bb4 | Cornelia Huck | } |
598 | a5cf2bb4 | Cornelia Huck | if (found) {
|
599 | a5cf2bb4 | Cornelia Huck | break;
|
600 | a5cf2bb4 | Cornelia Huck | } |
601 | a5cf2bb4 | Cornelia Huck | } |
602 | a5cf2bb4 | Cornelia Huck | if (!found) {
|
603 | a5cf2bb4 | Cornelia Huck | ret = -ENODEV; |
604 | a5cf2bb4 | Cornelia Huck | error_report("Virtual channel subsystem is full!");
|
605 | a5cf2bb4 | Cornelia Huck | goto out_err;
|
606 | a5cf2bb4 | Cornelia Huck | } |
607 | a5cf2bb4 | Cornelia Huck | trace_virtio_ccw_new_device(cssid, ssid, schid, devno, |
608 | a5cf2bb4 | Cornelia Huck | "auto-configured");
|
609 | a5cf2bb4 | Cornelia Huck | } |
610 | a5cf2bb4 | Cornelia Huck | |
611 | a5cf2bb4 | Cornelia Huck | /* Build initial schib. */
|
612 | a5cf2bb4 | Cornelia Huck | css_sch_build_virtual_schib(sch, 0, VIRTIO_CCW_CHPID_TYPE);
|
613 | a5cf2bb4 | Cornelia Huck | |
614 | a5cf2bb4 | Cornelia Huck | sch->ccw_cb = virtio_ccw_cb; |
615 | a5cf2bb4 | Cornelia Huck | |
616 | a5cf2bb4 | Cornelia Huck | /* Build senseid data. */
|
617 | a5cf2bb4 | Cornelia Huck | memset(&sch->id, 0, sizeof(SenseId)); |
618 | a5cf2bb4 | Cornelia Huck | sch->id.reserved = 0xff;
|
619 | a5cf2bb4 | Cornelia Huck | sch->id.cu_type = VIRTIO_CCW_CU_TYPE; |
620 | f24a6840 | Paolo Bonzini | sch->id.cu_model = vdev->device_id; |
621 | a5cf2bb4 | Cornelia Huck | |
622 | a5cf2bb4 | Cornelia Huck | /* Only the first 32 feature bits are used. */
|
623 | 181103cd | KONRAD Frederic | dev->host_features[0] = virtio_bus_get_vdev_features(&dev->bus,
|
624 | 181103cd | KONRAD Frederic | dev->host_features[0]);
|
625 | 181103cd | KONRAD Frederic | |
626 | a5cf2bb4 | Cornelia Huck | dev->host_features[0] |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY; |
627 | a5cf2bb4 | Cornelia Huck | dev->host_features[0] |= 0x1 << VIRTIO_F_BAD_FEATURE; |
628 | a5cf2bb4 | Cornelia Huck | |
629 | a5cf2bb4 | Cornelia Huck | css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, |
630 | a5cf2bb4 | Cornelia Huck | parent->hotplugged, 1);
|
631 | a5cf2bb4 | Cornelia Huck | return 0; |
632 | a5cf2bb4 | Cornelia Huck | |
633 | a5cf2bb4 | Cornelia Huck | out_err:
|
634 | a5cf2bb4 | Cornelia Huck | dev->sch = NULL;
|
635 | a5cf2bb4 | Cornelia Huck | g_free(sch); |
636 | a5cf2bb4 | Cornelia Huck | return ret;
|
637 | a5cf2bb4 | Cornelia Huck | } |
638 | a5cf2bb4 | Cornelia Huck | |
639 | a5cf2bb4 | Cornelia Huck | static int virtio_ccw_exit(VirtioCcwDevice *dev) |
640 | a5cf2bb4 | Cornelia Huck | { |
641 | a5cf2bb4 | Cornelia Huck | SubchDev *sch = dev->sch; |
642 | a5cf2bb4 | Cornelia Huck | |
643 | a5cf2bb4 | Cornelia Huck | if (sch) {
|
644 | a5cf2bb4 | Cornelia Huck | css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
|
645 | a5cf2bb4 | Cornelia Huck | g_free(sch); |
646 | a5cf2bb4 | Cornelia Huck | } |
647 | a5cf2bb4 | Cornelia Huck | dev->indicators = 0;
|
648 | a5cf2bb4 | Cornelia Huck | return 0; |
649 | a5cf2bb4 | Cornelia Huck | } |
650 | a5cf2bb4 | Cornelia Huck | |
651 | 89334c8b | KONRAD Frederic | static int virtio_ccw_net_init(VirtioCcwDevice *ccw_dev) |
652 | a5cf2bb4 | Cornelia Huck | { |
653 | 800ced8c | KONRAD Frederic | DeviceState *qdev = DEVICE(ccw_dev); |
654 | 89334c8b | KONRAD Frederic | VirtIONetCcw *dev = VIRTIO_NET_CCW(ccw_dev); |
655 | 89334c8b | KONRAD Frederic | DeviceState *vdev = DEVICE(&dev->vdev); |
656 | a5cf2bb4 | Cornelia Huck | |
657 | 89334c8b | KONRAD Frederic | virtio_net_set_config_size(&dev->vdev, ccw_dev->host_features[0]);
|
658 | 800ced8c | KONRAD Frederic | virtio_net_set_netclient_name(&dev->vdev, qdev->id, |
659 | 800ced8c | KONRAD Frederic | object_get_typename(OBJECT(qdev))); |
660 | 89334c8b | KONRAD Frederic | qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); |
661 | 89334c8b | KONRAD Frederic | if (qdev_init(vdev) < 0) { |
662 | a5cf2bb4 | Cornelia Huck | return -1; |
663 | a5cf2bb4 | Cornelia Huck | } |
664 | a5cf2bb4 | Cornelia Huck | |
665 | 89334c8b | KONRAD Frederic | return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
|
666 | a5cf2bb4 | Cornelia Huck | } |
667 | a5cf2bb4 | Cornelia Huck | |
668 | 89334c8b | KONRAD Frederic | static void virtio_ccw_net_instance_init(Object *obj) |
669 | a5cf2bb4 | Cornelia Huck | { |
670 | 89334c8b | KONRAD Frederic | VirtIONetCcw *dev = VIRTIO_NET_CCW(obj); |
671 | 213f0c4f | Andreas Färber | object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NET);
|
672 | 89334c8b | KONRAD Frederic | object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); |
673 | a5cf2bb4 | Cornelia Huck | } |
674 | a5cf2bb4 | Cornelia Huck | |
675 | 3400c455 | KONRAD Frederic | static int virtio_ccw_blk_init(VirtioCcwDevice *ccw_dev) |
676 | a5cf2bb4 | Cornelia Huck | { |
677 | 3400c455 | KONRAD Frederic | VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(ccw_dev); |
678 | 3400c455 | KONRAD Frederic | DeviceState *vdev = DEVICE(&dev->vdev); |
679 | 3400c455 | KONRAD Frederic | virtio_blk_set_conf(vdev, &(dev->blk)); |
680 | 3400c455 | KONRAD Frederic | qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); |
681 | 3400c455 | KONRAD Frederic | if (qdev_init(vdev) < 0) { |
682 | a5cf2bb4 | Cornelia Huck | return -1; |
683 | a5cf2bb4 | Cornelia Huck | } |
684 | a5cf2bb4 | Cornelia Huck | |
685 | 3400c455 | KONRAD Frederic | return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
|
686 | a5cf2bb4 | Cornelia Huck | } |
687 | a5cf2bb4 | Cornelia Huck | |
688 | 3400c455 | KONRAD Frederic | static void virtio_ccw_blk_instance_init(Object *obj) |
689 | a5cf2bb4 | Cornelia Huck | { |
690 | 3400c455 | KONRAD Frederic | VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(obj); |
691 | 213f0c4f | Andreas Färber | object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK);
|
692 | 3400c455 | KONRAD Frederic | object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); |
693 | a5cf2bb4 | Cornelia Huck | } |
694 | a5cf2bb4 | Cornelia Huck | |
695 | 6acf69cd | KONRAD Frederic | static int virtio_ccw_serial_init(VirtioCcwDevice *ccw_dev) |
696 | a5cf2bb4 | Cornelia Huck | { |
697 | 6acf69cd | KONRAD Frederic | VirtioSerialCcw *dev = VIRTIO_SERIAL_CCW(ccw_dev); |
698 | 6acf69cd | KONRAD Frederic | DeviceState *vdev = DEVICE(&dev->vdev); |
699 | 80270a19 | KONRAD Frederic | DeviceState *proxy = DEVICE(ccw_dev); |
700 | 80270a19 | KONRAD Frederic | char *bus_name;
|
701 | 80270a19 | KONRAD Frederic | |
702 | 80270a19 | KONRAD Frederic | /*
|
703 | 80270a19 | KONRAD Frederic | * For command line compatibility, this sets the virtio-serial-device bus
|
704 | 80270a19 | KONRAD Frederic | * name as before.
|
705 | 80270a19 | KONRAD Frederic | */
|
706 | 80270a19 | KONRAD Frederic | if (proxy->id) {
|
707 | 80270a19 | KONRAD Frederic | bus_name = g_strdup_printf("%s.0", proxy->id);
|
708 | 80270a19 | KONRAD Frederic | virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name); |
709 | 80270a19 | KONRAD Frederic | g_free(bus_name); |
710 | 80270a19 | KONRAD Frederic | } |
711 | a5cf2bb4 | Cornelia Huck | |
712 | 6acf69cd | KONRAD Frederic | qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); |
713 | 6acf69cd | KONRAD Frederic | if (qdev_init(vdev) < 0) { |
714 | a5cf2bb4 | Cornelia Huck | return -1; |
715 | a5cf2bb4 | Cornelia Huck | } |
716 | a5cf2bb4 | Cornelia Huck | |
717 | 6acf69cd | KONRAD Frederic | return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
|
718 | a5cf2bb4 | Cornelia Huck | } |
719 | a5cf2bb4 | Cornelia Huck | |
720 | 6acf69cd | KONRAD Frederic | |
721 | 6acf69cd | KONRAD Frederic | static void virtio_ccw_serial_instance_init(Object *obj) |
722 | a5cf2bb4 | Cornelia Huck | { |
723 | 6acf69cd | KONRAD Frederic | VirtioSerialCcw *dev = VIRTIO_SERIAL_CCW(obj); |
724 | 213f0c4f | Andreas Färber | object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SERIAL);
|
725 | 6acf69cd | KONRAD Frederic | object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); |
726 | a5cf2bb4 | Cornelia Huck | } |
727 | a5cf2bb4 | Cornelia Huck | |
728 | 30bff6a0 | KONRAD Frederic | static int virtio_ccw_balloon_init(VirtioCcwDevice *ccw_dev) |
729 | a5cf2bb4 | Cornelia Huck | { |
730 | 30bff6a0 | KONRAD Frederic | VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(ccw_dev); |
731 | 30bff6a0 | KONRAD Frederic | DeviceState *vdev = DEVICE(&dev->vdev); |
732 | a5cf2bb4 | Cornelia Huck | |
733 | 30bff6a0 | KONRAD Frederic | qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); |
734 | 30bff6a0 | KONRAD Frederic | if (qdev_init(vdev) < 0) { |
735 | a5cf2bb4 | Cornelia Huck | return -1; |
736 | a5cf2bb4 | Cornelia Huck | } |
737 | a5cf2bb4 | Cornelia Huck | |
738 | 30bff6a0 | KONRAD Frederic | return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
|
739 | a5cf2bb4 | Cornelia Huck | } |
740 | a5cf2bb4 | Cornelia Huck | |
741 | 24a6e7f4 | KONRAD Frederic | static void balloon_ccw_stats_get_all(Object *obj, struct Visitor *v, |
742 | 24a6e7f4 | KONRAD Frederic | void *opaque, const char *name, |
743 | 24a6e7f4 | KONRAD Frederic | Error **errp) |
744 | 24a6e7f4 | KONRAD Frederic | { |
745 | 24a6e7f4 | KONRAD Frederic | VirtIOBalloonCcw *dev = opaque; |
746 | 24a6e7f4 | KONRAD Frederic | object_property_get(OBJECT(&dev->vdev), v, "guest-stats", errp);
|
747 | 24a6e7f4 | KONRAD Frederic | } |
748 | 24a6e7f4 | KONRAD Frederic | |
749 | 24a6e7f4 | KONRAD Frederic | static void balloon_ccw_stats_get_poll_interval(Object *obj, struct Visitor *v, |
750 | 24a6e7f4 | KONRAD Frederic | void *opaque, const char *name, |
751 | 24a6e7f4 | KONRAD Frederic | Error **errp) |
752 | 24a6e7f4 | KONRAD Frederic | { |
753 | 24a6e7f4 | KONRAD Frederic | VirtIOBalloonCcw *dev = opaque; |
754 | 24a6e7f4 | KONRAD Frederic | object_property_get(OBJECT(&dev->vdev), v, "guest-stats-polling-interval",
|
755 | 24a6e7f4 | KONRAD Frederic | errp); |
756 | 24a6e7f4 | KONRAD Frederic | } |
757 | 24a6e7f4 | KONRAD Frederic | |
758 | 24a6e7f4 | KONRAD Frederic | static void balloon_ccw_stats_set_poll_interval(Object *obj, struct Visitor *v, |
759 | 24a6e7f4 | KONRAD Frederic | void *opaque, const char *name, |
760 | 24a6e7f4 | KONRAD Frederic | Error **errp) |
761 | 24a6e7f4 | KONRAD Frederic | { |
762 | 24a6e7f4 | KONRAD Frederic | VirtIOBalloonCcw *dev = opaque; |
763 | 24a6e7f4 | KONRAD Frederic | object_property_set(OBJECT(&dev->vdev), v, "guest-stats-polling-interval",
|
764 | 24a6e7f4 | KONRAD Frederic | errp); |
765 | 24a6e7f4 | KONRAD Frederic | } |
766 | 24a6e7f4 | KONRAD Frederic | |
767 | 30bff6a0 | KONRAD Frederic | static void virtio_ccw_balloon_instance_init(Object *obj) |
768 | a5cf2bb4 | Cornelia Huck | { |
769 | 30bff6a0 | KONRAD Frederic | VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(obj); |
770 | 213f0c4f | Andreas Färber | object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON);
|
771 | 30bff6a0 | KONRAD Frederic | object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); |
772 | 24a6e7f4 | KONRAD Frederic | |
773 | 24a6e7f4 | KONRAD Frederic | object_property_add(obj, "guest-stats", "guest statistics", |
774 | 24a6e7f4 | KONRAD Frederic | balloon_ccw_stats_get_all, NULL, NULL, dev, NULL); |
775 | 24a6e7f4 | KONRAD Frederic | |
776 | 24a6e7f4 | KONRAD Frederic | object_property_add(obj, "guest-stats-polling-interval", "int", |
777 | 24a6e7f4 | KONRAD Frederic | balloon_ccw_stats_get_poll_interval, |
778 | 24a6e7f4 | KONRAD Frederic | balloon_ccw_stats_set_poll_interval, |
779 | 24a6e7f4 | KONRAD Frederic | NULL, dev, NULL); |
780 | a5cf2bb4 | Cornelia Huck | } |
781 | a5cf2bb4 | Cornelia Huck | |
782 | c908ea10 | KONRAD Frederic | static int virtio_ccw_scsi_init(VirtioCcwDevice *ccw_dev) |
783 | a5cf2bb4 | Cornelia Huck | { |
784 | c908ea10 | KONRAD Frederic | VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(ccw_dev); |
785 | c908ea10 | KONRAD Frederic | DeviceState *vdev = DEVICE(&dev->vdev); |
786 | 6f32a6b4 | KONRAD Frederic | DeviceState *qdev = DEVICE(ccw_dev); |
787 | 6f32a6b4 | KONRAD Frederic | char *bus_name;
|
788 | 6f32a6b4 | KONRAD Frederic | |
789 | 6f32a6b4 | KONRAD Frederic | /*
|
790 | 6f32a6b4 | KONRAD Frederic | * For command line compatibility, this sets the virtio-scsi-device bus
|
791 | 6f32a6b4 | KONRAD Frederic | * name as before.
|
792 | 6f32a6b4 | KONRAD Frederic | */
|
793 | 6f32a6b4 | KONRAD Frederic | if (qdev->id) {
|
794 | 6f32a6b4 | KONRAD Frederic | bus_name = g_strdup_printf("%s.0", qdev->id);
|
795 | 6f32a6b4 | KONRAD Frederic | virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name); |
796 | 6f32a6b4 | KONRAD Frederic | g_free(bus_name); |
797 | 6f32a6b4 | KONRAD Frederic | } |
798 | a5cf2bb4 | Cornelia Huck | |
799 | c908ea10 | KONRAD Frederic | qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); |
800 | c908ea10 | KONRAD Frederic | if (qdev_init(vdev) < 0) { |
801 | a5cf2bb4 | Cornelia Huck | return -1; |
802 | a5cf2bb4 | Cornelia Huck | } |
803 | a5cf2bb4 | Cornelia Huck | |
804 | c908ea10 | KONRAD Frederic | return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
|
805 | a5cf2bb4 | Cornelia Huck | } |
806 | a5cf2bb4 | Cornelia Huck | |
807 | c908ea10 | KONRAD Frederic | static void virtio_ccw_scsi_instance_init(Object *obj) |
808 | a5cf2bb4 | Cornelia Huck | { |
809 | c908ea10 | KONRAD Frederic | VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(obj); |
810 | 213f0c4f | Andreas Färber | object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SCSI);
|
811 | c908ea10 | KONRAD Frederic | object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); |
812 | a5cf2bb4 | Cornelia Huck | } |
813 | a5cf2bb4 | Cornelia Huck | |
814 | ccf6916c | Paolo Bonzini | #ifdef CONFIG_VHOST_SCSI
|
815 | ccf6916c | Paolo Bonzini | static int vhost_ccw_scsi_init(VirtioCcwDevice *ccw_dev) |
816 | ccf6916c | Paolo Bonzini | { |
817 | ccf6916c | Paolo Bonzini | VHostSCSICcw *dev = VHOST_SCSI_CCW(ccw_dev); |
818 | ccf6916c | Paolo Bonzini | DeviceState *vdev = DEVICE(&dev->vdev); |
819 | ccf6916c | Paolo Bonzini | |
820 | ccf6916c | Paolo Bonzini | qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); |
821 | ccf6916c | Paolo Bonzini | if (qdev_init(vdev) < 0) { |
822 | ccf6916c | Paolo Bonzini | return -1; |
823 | ccf6916c | Paolo Bonzini | } |
824 | ccf6916c | Paolo Bonzini | |
825 | ccf6916c | Paolo Bonzini | return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
|
826 | ccf6916c | Paolo Bonzini | } |
827 | ccf6916c | Paolo Bonzini | |
828 | ccf6916c | Paolo Bonzini | static void vhost_ccw_scsi_instance_init(Object *obj) |
829 | ccf6916c | Paolo Bonzini | { |
830 | ccf6916c | Paolo Bonzini | VHostSCSICcw *dev = VHOST_SCSI_CCW(obj); |
831 | 213f0c4f | Andreas Färber | object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VHOST_SCSI);
|
832 | ccf6916c | Paolo Bonzini | object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); |
833 | ccf6916c | Paolo Bonzini | } |
834 | ccf6916c | Paolo Bonzini | #endif
|
835 | ccf6916c | Paolo Bonzini | |
836 | 2db26d4c | KONRAD Frederic | static int virtio_ccw_rng_init(VirtioCcwDevice *ccw_dev) |
837 | 2362ecc5 | Cornelia Huck | { |
838 | 2db26d4c | KONRAD Frederic | VirtIORNGCcw *dev = VIRTIO_RNG_CCW(ccw_dev); |
839 | 2db26d4c | KONRAD Frederic | DeviceState *vdev = DEVICE(&dev->vdev); |
840 | 2362ecc5 | Cornelia Huck | |
841 | 2db26d4c | KONRAD Frederic | qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); |
842 | 2db26d4c | KONRAD Frederic | if (qdev_init(vdev) < 0) { |
843 | 2362ecc5 | Cornelia Huck | return -1; |
844 | 2362ecc5 | Cornelia Huck | } |
845 | 2362ecc5 | Cornelia Huck | |
846 | 2db26d4c | KONRAD Frederic | object_property_set_link(OBJECT(dev), |
847 | 5b456438 | Cole Robinson | OBJECT(dev->vdev.conf.rng), "rng",
|
848 | 2db26d4c | KONRAD Frederic | NULL);
|
849 | 2db26d4c | KONRAD Frederic | |
850 | 2db26d4c | KONRAD Frederic | return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
|
851 | 2362ecc5 | Cornelia Huck | } |
852 | 2362ecc5 | Cornelia Huck | |
853 | a5cf2bb4 | Cornelia Huck | /* DeviceState to VirtioCcwDevice. Note: used on datapath,
|
854 | a5cf2bb4 | Cornelia Huck | * be careful and test performance if you change this.
|
855 | a5cf2bb4 | Cornelia Huck | */
|
856 | a5cf2bb4 | Cornelia Huck | static inline VirtioCcwDevice *to_virtio_ccw_dev_fast(DeviceState *d) |
857 | a5cf2bb4 | Cornelia Huck | { |
858 | a5cf2bb4 | Cornelia Huck | return container_of(d, VirtioCcwDevice, parent_obj);
|
859 | a5cf2bb4 | Cornelia Huck | } |
860 | a5cf2bb4 | Cornelia Huck | |
861 | a5cf2bb4 | Cornelia Huck | static void virtio_ccw_notify(DeviceState *d, uint16_t vector) |
862 | a5cf2bb4 | Cornelia Huck | { |
863 | a5cf2bb4 | Cornelia Huck | VirtioCcwDevice *dev = to_virtio_ccw_dev_fast(d); |
864 | a5cf2bb4 | Cornelia Huck | SubchDev *sch = dev->sch; |
865 | a5cf2bb4 | Cornelia Huck | uint64_t indicators; |
866 | a5cf2bb4 | Cornelia Huck | |
867 | a5cf2bb4 | Cornelia Huck | if (vector >= 128) { |
868 | a5cf2bb4 | Cornelia Huck | return;
|
869 | a5cf2bb4 | Cornelia Huck | } |
870 | a5cf2bb4 | Cornelia Huck | |
871 | a5cf2bb4 | Cornelia Huck | if (vector < VIRTIO_PCI_QUEUE_MAX) {
|
872 | 7c486976 | Cornelia Huck | if (!dev->indicators) {
|
873 | 7c486976 | Cornelia Huck | return;
|
874 | 7c486976 | Cornelia Huck | } |
875 | 2c17449b | Edgar E. Iglesias | indicators = ldq_phys(&address_space_memory, dev->indicators); |
876 | 19380b1b | Cornelia Huck | indicators |= 1ULL << vector;
|
877 | f606604f | Edgar E. Iglesias | stq_phys(&address_space_memory, dev->indicators, indicators); |
878 | a5cf2bb4 | Cornelia Huck | } else {
|
879 | 7c486976 | Cornelia Huck | if (!dev->indicators2) {
|
880 | 7c486976 | Cornelia Huck | return;
|
881 | 7c486976 | Cornelia Huck | } |
882 | a5cf2bb4 | Cornelia Huck | vector = 0;
|
883 | 2c17449b | Edgar E. Iglesias | indicators = ldq_phys(&address_space_memory, dev->indicators2); |
884 | 19380b1b | Cornelia Huck | indicators |= 1ULL << vector;
|
885 | f606604f | Edgar E. Iglesias | stq_phys(&address_space_memory, dev->indicators2, indicators); |
886 | a5cf2bb4 | Cornelia Huck | } |
887 | a5cf2bb4 | Cornelia Huck | |
888 | a5cf2bb4 | Cornelia Huck | css_conditional_io_interrupt(sch); |
889 | a5cf2bb4 | Cornelia Huck | |
890 | a5cf2bb4 | Cornelia Huck | } |
891 | a5cf2bb4 | Cornelia Huck | |
892 | a5cf2bb4 | Cornelia Huck | static unsigned virtio_ccw_get_features(DeviceState *d) |
893 | a5cf2bb4 | Cornelia Huck | { |
894 | a5cf2bb4 | Cornelia Huck | VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); |
895 | a5cf2bb4 | Cornelia Huck | |
896 | a5cf2bb4 | Cornelia Huck | /* Only the first 32 feature bits are used. */
|
897 | a5cf2bb4 | Cornelia Huck | return dev->host_features[0]; |
898 | a5cf2bb4 | Cornelia Huck | } |
899 | a5cf2bb4 | Cornelia Huck | |
900 | a5cf2bb4 | Cornelia Huck | static void virtio_ccw_reset(DeviceState *d) |
901 | a5cf2bb4 | Cornelia Huck | { |
902 | a5cf2bb4 | Cornelia Huck | VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); |
903 | f24a6840 | Paolo Bonzini | VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); |
904 | a5cf2bb4 | Cornelia Huck | |
905 | b4436a0b | Cornelia Huck | virtio_ccw_stop_ioeventfd(dev); |
906 | f24a6840 | Paolo Bonzini | virtio_reset(vdev); |
907 | a5cf2bb4 | Cornelia Huck | css_reset_sch(dev->sch); |
908 | 6504a930 | Christian Borntraeger | dev->indicators = 0;
|
909 | 6504a930 | Christian Borntraeger | dev->indicators2 = 0;
|
910 | a5cf2bb4 | Cornelia Huck | } |
911 | a5cf2bb4 | Cornelia Huck | |
912 | b4436a0b | Cornelia Huck | static void virtio_ccw_vmstate_change(DeviceState *d, bool running) |
913 | b4436a0b | Cornelia Huck | { |
914 | b4436a0b | Cornelia Huck | VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); |
915 | b4436a0b | Cornelia Huck | |
916 | b4436a0b | Cornelia Huck | if (running) {
|
917 | b4436a0b | Cornelia Huck | virtio_ccw_start_ioeventfd(dev); |
918 | b4436a0b | Cornelia Huck | } else {
|
919 | b4436a0b | Cornelia Huck | virtio_ccw_stop_ioeventfd(dev); |
920 | b4436a0b | Cornelia Huck | } |
921 | b4436a0b | Cornelia Huck | } |
922 | b4436a0b | Cornelia Huck | |
923 | 320ce850 | Cornelia Huck | static bool virtio_ccw_query_guest_notifiers(DeviceState *d) |
924 | 320ce850 | Cornelia Huck | { |
925 | 320ce850 | Cornelia Huck | VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); |
926 | 320ce850 | Cornelia Huck | |
927 | 320ce850 | Cornelia Huck | return !!(dev->sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA);
|
928 | 320ce850 | Cornelia Huck | } |
929 | 320ce850 | Cornelia Huck | |
930 | 320ce850 | Cornelia Huck | static int virtio_ccw_set_host_notifier(DeviceState *d, int n, bool assign) |
931 | 320ce850 | Cornelia Huck | { |
932 | 320ce850 | Cornelia Huck | VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); |
933 | 320ce850 | Cornelia Huck | |
934 | 320ce850 | Cornelia Huck | /* Stop using the generic ioeventfd, we are doing eventfd handling
|
935 | 320ce850 | Cornelia Huck | * ourselves below */
|
936 | 320ce850 | Cornelia Huck | dev->ioeventfd_disabled = assign; |
937 | 320ce850 | Cornelia Huck | if (assign) {
|
938 | 320ce850 | Cornelia Huck | virtio_ccw_stop_ioeventfd(dev); |
939 | 320ce850 | Cornelia Huck | } |
940 | 320ce850 | Cornelia Huck | return virtio_ccw_set_guest2host_notifier(dev, n, assign, false); |
941 | 320ce850 | Cornelia Huck | } |
942 | 320ce850 | Cornelia Huck | |
943 | 320ce850 | Cornelia Huck | static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n, |
944 | 320ce850 | Cornelia Huck | bool assign, bool with_irqfd) |
945 | 320ce850 | Cornelia Huck | { |
946 | f24a6840 | Paolo Bonzini | VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); |
947 | f24a6840 | Paolo Bonzini | VirtQueue *vq = virtio_get_queue(vdev, n); |
948 | 320ce850 | Cornelia Huck | EventNotifier *notifier = virtio_queue_get_guest_notifier(vq); |
949 | f24a6840 | Paolo Bonzini | VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); |
950 | 320ce850 | Cornelia Huck | |
951 | 320ce850 | Cornelia Huck | if (assign) {
|
952 | 320ce850 | Cornelia Huck | int r = event_notifier_init(notifier, 0); |
953 | 320ce850 | Cornelia Huck | |
954 | 320ce850 | Cornelia Huck | if (r < 0) { |
955 | 320ce850 | Cornelia Huck | return r;
|
956 | 320ce850 | Cornelia Huck | } |
957 | 320ce850 | Cornelia Huck | virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
|
958 | 320ce850 | Cornelia Huck | /* We do not support irqfd for classic I/O interrupts, because the
|
959 | 320ce850 | Cornelia Huck | * classic interrupts are intermixed with the subchannel status, that
|
960 | 320ce850 | Cornelia Huck | * is queried with test subchannel. We want to use vhost, though.
|
961 | 320ce850 | Cornelia Huck | * Lets make sure to have vhost running and wire up the irq fd to
|
962 | 320ce850 | Cornelia Huck | * land in qemu (and only the irq fd) in this code.
|
963 | 320ce850 | Cornelia Huck | */
|
964 | 320ce850 | Cornelia Huck | if (k->guest_notifier_mask) {
|
965 | f24a6840 | Paolo Bonzini | k->guest_notifier_mask(vdev, n, false);
|
966 | 320ce850 | Cornelia Huck | } |
967 | 320ce850 | Cornelia Huck | /* get lost events and re-inject */
|
968 | 320ce850 | Cornelia Huck | if (k->guest_notifier_pending &&
|
969 | f24a6840 | Paolo Bonzini | k->guest_notifier_pending(vdev, n)) { |
970 | 320ce850 | Cornelia Huck | event_notifier_set(notifier); |
971 | 320ce850 | Cornelia Huck | } |
972 | 320ce850 | Cornelia Huck | } else {
|
973 | 320ce850 | Cornelia Huck | if (k->guest_notifier_mask) {
|
974 | f24a6840 | Paolo Bonzini | k->guest_notifier_mask(vdev, n, true);
|
975 | 320ce850 | Cornelia Huck | } |
976 | 320ce850 | Cornelia Huck | virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
|
977 | 320ce850 | Cornelia Huck | event_notifier_cleanup(notifier); |
978 | 320ce850 | Cornelia Huck | } |
979 | 320ce850 | Cornelia Huck | return 0; |
980 | 320ce850 | Cornelia Huck | } |
981 | 320ce850 | Cornelia Huck | |
982 | 320ce850 | Cornelia Huck | static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs, |
983 | 320ce850 | Cornelia Huck | bool assigned)
|
984 | 320ce850 | Cornelia Huck | { |
985 | 320ce850 | Cornelia Huck | VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); |
986 | f24a6840 | Paolo Bonzini | VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); |
987 | 320ce850 | Cornelia Huck | int r, n;
|
988 | 320ce850 | Cornelia Huck | |
989 | 320ce850 | Cornelia Huck | for (n = 0; n < nvqs; n++) { |
990 | 320ce850 | Cornelia Huck | if (!virtio_queue_get_num(vdev, n)) {
|
991 | 320ce850 | Cornelia Huck | break;
|
992 | 320ce850 | Cornelia Huck | } |
993 | 320ce850 | Cornelia Huck | /* false -> true, as soon as irqfd works */
|
994 | 320ce850 | Cornelia Huck | r = virtio_ccw_set_guest_notifier(dev, n, assigned, false);
|
995 | 320ce850 | Cornelia Huck | if (r < 0) { |
996 | 320ce850 | Cornelia Huck | goto assign_error;
|
997 | 320ce850 | Cornelia Huck | } |
998 | 320ce850 | Cornelia Huck | } |
999 | 320ce850 | Cornelia Huck | return 0; |
1000 | 320ce850 | Cornelia Huck | |
1001 | 320ce850 | Cornelia Huck | assign_error:
|
1002 | 320ce850 | Cornelia Huck | while (--n >= 0) { |
1003 | 320ce850 | Cornelia Huck | virtio_ccw_set_guest_notifier(dev, n, !assigned, false);
|
1004 | 320ce850 | Cornelia Huck | } |
1005 | 320ce850 | Cornelia Huck | return r;
|
1006 | 320ce850 | Cornelia Huck | } |
1007 | 320ce850 | Cornelia Huck | |
1008 | a5cf2bb4 | Cornelia Huck | /**************** Virtio-ccw Bus Device Descriptions *******************/
|
1009 | a5cf2bb4 | Cornelia Huck | |
1010 | a5cf2bb4 | Cornelia Huck | static Property virtio_ccw_net_properties[] = {
|
1011 | a5cf2bb4 | Cornelia Huck | DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
1012 | a5cf2bb4 | Cornelia Huck | DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features[0]),
|
1013 | 89334c8b | KONRAD Frederic | DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetCcw, vdev.net_conf), |
1014 | 89334c8b | KONRAD Frederic | DEFINE_NIC_PROPERTIES(VirtIONetCcw, vdev.nic_conf), |
1015 | b4436a0b | Cornelia Huck | DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
1016 | b4436a0b | Cornelia Huck | VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
1017 | a5cf2bb4 | Cornelia Huck | DEFINE_PROP_END_OF_LIST(), |
1018 | a5cf2bb4 | Cornelia Huck | }; |
1019 | a5cf2bb4 | Cornelia Huck | |
1020 | a5cf2bb4 | Cornelia Huck | static void virtio_ccw_net_class_init(ObjectClass *klass, void *data) |
1021 | a5cf2bb4 | Cornelia Huck | { |
1022 | a5cf2bb4 | Cornelia Huck | DeviceClass *dc = DEVICE_CLASS(klass); |
1023 | a5cf2bb4 | Cornelia Huck | VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass); |
1024 | a5cf2bb4 | Cornelia Huck | |
1025 | a5cf2bb4 | Cornelia Huck | k->init = virtio_ccw_net_init; |
1026 | 89334c8b | KONRAD Frederic | k->exit = virtio_ccw_exit; |
1027 | a5cf2bb4 | Cornelia Huck | dc->reset = virtio_ccw_reset; |
1028 | a5cf2bb4 | Cornelia Huck | dc->props = virtio_ccw_net_properties; |
1029 | a5cf2bb4 | Cornelia Huck | } |
1030 | a5cf2bb4 | Cornelia Huck | |
1031 | a5cf2bb4 | Cornelia Huck | static const TypeInfo virtio_ccw_net = { |
1032 | 89334c8b | KONRAD Frederic | .name = TYPE_VIRTIO_NET_CCW, |
1033 | a5cf2bb4 | Cornelia Huck | .parent = TYPE_VIRTIO_CCW_DEVICE, |
1034 | 89334c8b | KONRAD Frederic | .instance_size = sizeof(VirtIONetCcw),
|
1035 | 89334c8b | KONRAD Frederic | .instance_init = virtio_ccw_net_instance_init, |
1036 | a5cf2bb4 | Cornelia Huck | .class_init = virtio_ccw_net_class_init, |
1037 | a5cf2bb4 | Cornelia Huck | }; |
1038 | a5cf2bb4 | Cornelia Huck | |
1039 | a5cf2bb4 | Cornelia Huck | static Property virtio_ccw_blk_properties[] = {
|
1040 | a5cf2bb4 | Cornelia Huck | DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
1041 | a5cf2bb4 | Cornelia Huck | DEFINE_VIRTIO_BLK_FEATURES(VirtioCcwDevice, host_features[0]),
|
1042 | fe42d7fb | Cornelia Huck | DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkCcw, blk), |
1043 | b4436a0b | Cornelia Huck | DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
1044 | b4436a0b | Cornelia Huck | VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
1045 | bf72d89f | Dominik Dingel | #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
|
1046 | bf72d89f | Dominik Dingel | DEFINE_PROP_BIT("x-data-plane", VirtIOBlkCcw, blk.data_plane, 0, false), |
1047 | bf72d89f | Dominik Dingel | #endif
|
1048 | a5cf2bb4 | Cornelia Huck | DEFINE_PROP_END_OF_LIST(), |
1049 | a5cf2bb4 | Cornelia Huck | }; |
1050 | a5cf2bb4 | Cornelia Huck | |
1051 | a5cf2bb4 | Cornelia Huck | static void virtio_ccw_blk_class_init(ObjectClass *klass, void *data) |
1052 | a5cf2bb4 | Cornelia Huck | { |
1053 | a5cf2bb4 | Cornelia Huck | DeviceClass *dc = DEVICE_CLASS(klass); |
1054 | a5cf2bb4 | Cornelia Huck | VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass); |
1055 | a5cf2bb4 | Cornelia Huck | |
1056 | a5cf2bb4 | Cornelia Huck | k->init = virtio_ccw_blk_init; |
1057 | 3400c455 | KONRAD Frederic | k->exit = virtio_ccw_exit; |
1058 | a5cf2bb4 | Cornelia Huck | dc->reset = virtio_ccw_reset; |
1059 | a5cf2bb4 | Cornelia Huck | dc->props = virtio_ccw_blk_properties; |
1060 | a5cf2bb4 | Cornelia Huck | } |
1061 | a5cf2bb4 | Cornelia Huck | |
1062 | a5cf2bb4 | Cornelia Huck | static const TypeInfo virtio_ccw_blk = { |
1063 | 3400c455 | KONRAD Frederic | .name = TYPE_VIRTIO_BLK_CCW, |
1064 | a5cf2bb4 | Cornelia Huck | .parent = TYPE_VIRTIO_CCW_DEVICE, |
1065 | 3400c455 | KONRAD Frederic | .instance_size = sizeof(VirtIOBlkCcw),
|
1066 | 3400c455 | KONRAD Frederic | .instance_init = virtio_ccw_blk_instance_init, |
1067 | a5cf2bb4 | Cornelia Huck | .class_init = virtio_ccw_blk_class_init, |
1068 | a5cf2bb4 | Cornelia Huck | }; |
1069 | a5cf2bb4 | Cornelia Huck | |
1070 | a5cf2bb4 | Cornelia Huck | static Property virtio_ccw_serial_properties[] = {
|
1071 | a5cf2bb4 | Cornelia Huck | DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
1072 | 6acf69cd | KONRAD Frederic | DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtioSerialCcw, vdev.serial), |
1073 | a5cf2bb4 | Cornelia Huck | DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
|
1074 | b4436a0b | Cornelia Huck | DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
1075 | b4436a0b | Cornelia Huck | VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
1076 | a5cf2bb4 | Cornelia Huck | DEFINE_PROP_END_OF_LIST(), |
1077 | a5cf2bb4 | Cornelia Huck | }; |
1078 | a5cf2bb4 | Cornelia Huck | |
1079 | a5cf2bb4 | Cornelia Huck | static void virtio_ccw_serial_class_init(ObjectClass *klass, void *data) |
1080 | a5cf2bb4 | Cornelia Huck | { |
1081 | a5cf2bb4 | Cornelia Huck | DeviceClass *dc = DEVICE_CLASS(klass); |
1082 | a5cf2bb4 | Cornelia Huck | VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass); |
1083 | a5cf2bb4 | Cornelia Huck | |
1084 | a5cf2bb4 | Cornelia Huck | k->init = virtio_ccw_serial_init; |
1085 | 6acf69cd | KONRAD Frederic | k->exit = virtio_ccw_exit; |
1086 | a5cf2bb4 | Cornelia Huck | dc->reset = virtio_ccw_reset; |
1087 | a5cf2bb4 | Cornelia Huck | dc->props = virtio_ccw_serial_properties; |
1088 | a5cf2bb4 | Cornelia Huck | } |
1089 | a5cf2bb4 | Cornelia Huck | |
1090 | a5cf2bb4 | Cornelia Huck | static const TypeInfo virtio_ccw_serial = { |
1091 | 6acf69cd | KONRAD Frederic | .name = TYPE_VIRTIO_SERIAL_CCW, |
1092 | a5cf2bb4 | Cornelia Huck | .parent = TYPE_VIRTIO_CCW_DEVICE, |
1093 | 6acf69cd | KONRAD Frederic | .instance_size = sizeof(VirtioSerialCcw),
|
1094 | 6acf69cd | KONRAD Frederic | .instance_init = virtio_ccw_serial_instance_init, |
1095 | a5cf2bb4 | Cornelia Huck | .class_init = virtio_ccw_serial_class_init, |
1096 | a5cf2bb4 | Cornelia Huck | }; |
1097 | a5cf2bb4 | Cornelia Huck | |
1098 | a5cf2bb4 | Cornelia Huck | static Property virtio_ccw_balloon_properties[] = {
|
1099 | a5cf2bb4 | Cornelia Huck | DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
1100 | a5cf2bb4 | Cornelia Huck | DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
|
1101 | b4436a0b | Cornelia Huck | DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
1102 | b4436a0b | Cornelia Huck | VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
1103 | a5cf2bb4 | Cornelia Huck | DEFINE_PROP_END_OF_LIST(), |
1104 | a5cf2bb4 | Cornelia Huck | }; |
1105 | a5cf2bb4 | Cornelia Huck | |
1106 | a5cf2bb4 | Cornelia Huck | static void virtio_ccw_balloon_class_init(ObjectClass *klass, void *data) |
1107 | a5cf2bb4 | Cornelia Huck | { |
1108 | a5cf2bb4 | Cornelia Huck | DeviceClass *dc = DEVICE_CLASS(klass); |
1109 | a5cf2bb4 | Cornelia Huck | VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass); |
1110 | a5cf2bb4 | Cornelia Huck | |
1111 | a5cf2bb4 | Cornelia Huck | k->init = virtio_ccw_balloon_init; |
1112 | 30bff6a0 | KONRAD Frederic | k->exit = virtio_ccw_exit; |
1113 | a5cf2bb4 | Cornelia Huck | dc->reset = virtio_ccw_reset; |
1114 | a5cf2bb4 | Cornelia Huck | dc->props = virtio_ccw_balloon_properties; |
1115 | a5cf2bb4 | Cornelia Huck | } |
1116 | a5cf2bb4 | Cornelia Huck | |
1117 | a5cf2bb4 | Cornelia Huck | static const TypeInfo virtio_ccw_balloon = { |
1118 | 30bff6a0 | KONRAD Frederic | .name = TYPE_VIRTIO_BALLOON_CCW, |
1119 | a5cf2bb4 | Cornelia Huck | .parent = TYPE_VIRTIO_CCW_DEVICE, |
1120 | 30bff6a0 | KONRAD Frederic | .instance_size = sizeof(VirtIOBalloonCcw),
|
1121 | 30bff6a0 | KONRAD Frederic | .instance_init = virtio_ccw_balloon_instance_init, |
1122 | a5cf2bb4 | Cornelia Huck | .class_init = virtio_ccw_balloon_class_init, |
1123 | a5cf2bb4 | Cornelia Huck | }; |
1124 | a5cf2bb4 | Cornelia Huck | |
1125 | a5cf2bb4 | Cornelia Huck | static Property virtio_ccw_scsi_properties[] = {
|
1126 | a5cf2bb4 | Cornelia Huck | DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
1127 | 292c8e50 | Paolo Bonzini | DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSICcw, vdev.parent_obj.conf), |
1128 | 4bfeb18a | KONRAD Frederic | DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]),
|
1129 | b4436a0b | Cornelia Huck | DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
1130 | b4436a0b | Cornelia Huck | VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
1131 | a5cf2bb4 | Cornelia Huck | DEFINE_PROP_END_OF_LIST(), |
1132 | a5cf2bb4 | Cornelia Huck | }; |
1133 | a5cf2bb4 | Cornelia Huck | |
1134 | a5cf2bb4 | Cornelia Huck | static void virtio_ccw_scsi_class_init(ObjectClass *klass, void *data) |
1135 | a5cf2bb4 | Cornelia Huck | { |
1136 | a5cf2bb4 | Cornelia Huck | DeviceClass *dc = DEVICE_CLASS(klass); |
1137 | a5cf2bb4 | Cornelia Huck | VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass); |
1138 | a5cf2bb4 | Cornelia Huck | |
1139 | a5cf2bb4 | Cornelia Huck | k->init = virtio_ccw_scsi_init; |
1140 | c908ea10 | KONRAD Frederic | k->exit = virtio_ccw_exit; |
1141 | a5cf2bb4 | Cornelia Huck | dc->reset = virtio_ccw_reset; |
1142 | a5cf2bb4 | Cornelia Huck | dc->props = virtio_ccw_scsi_properties; |
1143 | a5cf2bb4 | Cornelia Huck | } |
1144 | a5cf2bb4 | Cornelia Huck | |
1145 | a5cf2bb4 | Cornelia Huck | static const TypeInfo virtio_ccw_scsi = { |
1146 | c908ea10 | KONRAD Frederic | .name = TYPE_VIRTIO_SCSI_CCW, |
1147 | a5cf2bb4 | Cornelia Huck | .parent = TYPE_VIRTIO_CCW_DEVICE, |
1148 | c908ea10 | KONRAD Frederic | .instance_size = sizeof(VirtIOSCSICcw),
|
1149 | c908ea10 | KONRAD Frederic | .instance_init = virtio_ccw_scsi_instance_init, |
1150 | a5cf2bb4 | Cornelia Huck | .class_init = virtio_ccw_scsi_class_init, |
1151 | a5cf2bb4 | Cornelia Huck | }; |
1152 | a5cf2bb4 | Cornelia Huck | |
1153 | ccf6916c | Paolo Bonzini | #ifdef CONFIG_VHOST_SCSI
|
1154 | ccf6916c | Paolo Bonzini | static Property vhost_ccw_scsi_properties[] = {
|
1155 | ccf6916c | Paolo Bonzini | DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
1156 | ccf6916c | Paolo Bonzini | DEFINE_VHOST_SCSI_PROPERTIES(VirtIOSCSICcw, vdev.parent_obj.conf), |
1157 | ccf6916c | Paolo Bonzini | DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
|
1158 | ccf6916c | Paolo Bonzini | DEFINE_PROP_END_OF_LIST(), |
1159 | ccf6916c | Paolo Bonzini | }; |
1160 | ccf6916c | Paolo Bonzini | |
1161 | ccf6916c | Paolo Bonzini | static void vhost_ccw_scsi_class_init(ObjectClass *klass, void *data) |
1162 | ccf6916c | Paolo Bonzini | { |
1163 | ccf6916c | Paolo Bonzini | DeviceClass *dc = DEVICE_CLASS(klass); |
1164 | ccf6916c | Paolo Bonzini | VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass); |
1165 | ccf6916c | Paolo Bonzini | |
1166 | ccf6916c | Paolo Bonzini | k->init = vhost_ccw_scsi_init; |
1167 | ccf6916c | Paolo Bonzini | k->exit = virtio_ccw_exit; |
1168 | ccf6916c | Paolo Bonzini | dc->reset = virtio_ccw_reset; |
1169 | ccf6916c | Paolo Bonzini | dc->props = vhost_ccw_scsi_properties; |
1170 | ccf6916c | Paolo Bonzini | } |
1171 | ccf6916c | Paolo Bonzini | |
1172 | ccf6916c | Paolo Bonzini | static const TypeInfo vhost_ccw_scsi = { |
1173 | ccf6916c | Paolo Bonzini | .name = TYPE_VHOST_SCSI_CCW, |
1174 | ccf6916c | Paolo Bonzini | .parent = TYPE_VIRTIO_CCW_DEVICE, |
1175 | ccf6916c | Paolo Bonzini | .instance_size = sizeof(VirtIOSCSICcw),
|
1176 | ccf6916c | Paolo Bonzini | .instance_init = vhost_ccw_scsi_instance_init, |
1177 | ccf6916c | Paolo Bonzini | .class_init = vhost_ccw_scsi_class_init, |
1178 | ccf6916c | Paolo Bonzini | }; |
1179 | ccf6916c | Paolo Bonzini | #endif
|
1180 | ccf6916c | Paolo Bonzini | |
1181 | 2db26d4c | KONRAD Frederic | static void virtio_ccw_rng_instance_init(Object *obj) |
1182 | 2362ecc5 | Cornelia Huck | { |
1183 | 2db26d4c | KONRAD Frederic | VirtIORNGCcw *dev = VIRTIO_RNG_CCW(obj); |
1184 | 213f0c4f | Andreas Färber | object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
|
1185 | 2db26d4c | KONRAD Frederic | object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); |
1186 | 2362ecc5 | Cornelia Huck | object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
|
1187 | 2db26d4c | KONRAD Frederic | (Object **)&dev->vdev.conf.rng, NULL);
|
1188 | 2362ecc5 | Cornelia Huck | } |
1189 | 2362ecc5 | Cornelia Huck | |
1190 | 2362ecc5 | Cornelia Huck | static Property virtio_ccw_rng_properties[] = {
|
1191 | 2362ecc5 | Cornelia Huck | DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
1192 | 2362ecc5 | Cornelia Huck | DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
|
1193 | 2db26d4c | KONRAD Frederic | DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORNGCcw, vdev.conf), |
1194 | b4436a0b | Cornelia Huck | DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
1195 | b4436a0b | Cornelia Huck | VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
1196 | 2362ecc5 | Cornelia Huck | DEFINE_PROP_END_OF_LIST(), |
1197 | 2362ecc5 | Cornelia Huck | }; |
1198 | 2362ecc5 | Cornelia Huck | |
1199 | 2362ecc5 | Cornelia Huck | static void virtio_ccw_rng_class_init(ObjectClass *klass, void *data) |
1200 | 2362ecc5 | Cornelia Huck | { |
1201 | 2362ecc5 | Cornelia Huck | DeviceClass *dc = DEVICE_CLASS(klass); |
1202 | 2362ecc5 | Cornelia Huck | VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass); |
1203 | 2362ecc5 | Cornelia Huck | |
1204 | 2362ecc5 | Cornelia Huck | k->init = virtio_ccw_rng_init; |
1205 | 2db26d4c | KONRAD Frederic | k->exit = virtio_ccw_exit; |
1206 | 2362ecc5 | Cornelia Huck | dc->reset = virtio_ccw_reset; |
1207 | 2362ecc5 | Cornelia Huck | dc->props = virtio_ccw_rng_properties; |
1208 | 2362ecc5 | Cornelia Huck | } |
1209 | 2362ecc5 | Cornelia Huck | |
1210 | 2362ecc5 | Cornelia Huck | static const TypeInfo virtio_ccw_rng = { |
1211 | 2db26d4c | KONRAD Frederic | .name = TYPE_VIRTIO_RNG_CCW, |
1212 | 2362ecc5 | Cornelia Huck | .parent = TYPE_VIRTIO_CCW_DEVICE, |
1213 | 2db26d4c | KONRAD Frederic | .instance_size = sizeof(VirtIORNGCcw),
|
1214 | 2db26d4c | KONRAD Frederic | .instance_init = virtio_ccw_rng_instance_init, |
1215 | 2362ecc5 | Cornelia Huck | .class_init = virtio_ccw_rng_class_init, |
1216 | 2362ecc5 | Cornelia Huck | }; |
1217 | 2362ecc5 | Cornelia Huck | |
1218 | a5cf2bb4 | Cornelia Huck | static int virtio_ccw_busdev_init(DeviceState *dev) |
1219 | a5cf2bb4 | Cornelia Huck | { |
1220 | a5cf2bb4 | Cornelia Huck | VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev; |
1221 | a5cf2bb4 | Cornelia Huck | VirtIOCCWDeviceClass *_info = VIRTIO_CCW_DEVICE_GET_CLASS(dev); |
1222 | a5cf2bb4 | Cornelia Huck | |
1223 | 1bf4d7aa | Andreas Färber | virtio_ccw_bus_new(&_dev->bus, sizeof(_dev->bus), _dev);
|
1224 | a5cf2bb4 | Cornelia Huck | |
1225 | a5cf2bb4 | Cornelia Huck | return _info->init(_dev);
|
1226 | a5cf2bb4 | Cornelia Huck | } |
1227 | a5cf2bb4 | Cornelia Huck | |
1228 | a5cf2bb4 | Cornelia Huck | static int virtio_ccw_busdev_exit(DeviceState *dev) |
1229 | a5cf2bb4 | Cornelia Huck | { |
1230 | a5cf2bb4 | Cornelia Huck | VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev; |
1231 | a5cf2bb4 | Cornelia Huck | VirtIOCCWDeviceClass *_info = VIRTIO_CCW_DEVICE_GET_CLASS(dev); |
1232 | a5cf2bb4 | Cornelia Huck | |
1233 | a5cf2bb4 | Cornelia Huck | return _info->exit(_dev);
|
1234 | a5cf2bb4 | Cornelia Huck | } |
1235 | a5cf2bb4 | Cornelia Huck | |
1236 | a5cf2bb4 | Cornelia Huck | static int virtio_ccw_busdev_unplug(DeviceState *dev) |
1237 | a5cf2bb4 | Cornelia Huck | { |
1238 | a5cf2bb4 | Cornelia Huck | VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev; |
1239 | a5cf2bb4 | Cornelia Huck | SubchDev *sch = _dev->sch; |
1240 | a5cf2bb4 | Cornelia Huck | |
1241 | 0b81c1ef | Paolo Bonzini | virtio_ccw_stop_ioeventfd(_dev); |
1242 | 0b81c1ef | Paolo Bonzini | |
1243 | a5cf2bb4 | Cornelia Huck | /*
|
1244 | a5cf2bb4 | Cornelia Huck | * We should arrive here only for device_del, since we don't support
|
1245 | a5cf2bb4 | Cornelia Huck | * direct hot(un)plug of channels, but only through virtio.
|
1246 | a5cf2bb4 | Cornelia Huck | */
|
1247 | a5cf2bb4 | Cornelia Huck | assert(sch != NULL);
|
1248 | a5cf2bb4 | Cornelia Huck | /* Subchannel is now disabled and no longer valid. */
|
1249 | a5cf2bb4 | Cornelia Huck | sch->curr_status.pmcw.flags &= ~(PMCW_FLAGS_MASK_ENA | |
1250 | a5cf2bb4 | Cornelia Huck | PMCW_FLAGS_MASK_DNV); |
1251 | a5cf2bb4 | Cornelia Huck | |
1252 | a5cf2bb4 | Cornelia Huck | css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0); |
1253 | a5cf2bb4 | Cornelia Huck | |
1254 | 02a5c4c9 | Stefan Hajnoczi | object_unparent(OBJECT(dev)); |
1255 | a5cf2bb4 | Cornelia Huck | return 0; |
1256 | a5cf2bb4 | Cornelia Huck | } |
1257 | a5cf2bb4 | Cornelia Huck | |
1258 | a5cf2bb4 | Cornelia Huck | static void virtio_ccw_device_class_init(ObjectClass *klass, void *data) |
1259 | a5cf2bb4 | Cornelia Huck | { |
1260 | a5cf2bb4 | Cornelia Huck | DeviceClass *dc = DEVICE_CLASS(klass); |
1261 | a5cf2bb4 | Cornelia Huck | |
1262 | a5cf2bb4 | Cornelia Huck | dc->init = virtio_ccw_busdev_init; |
1263 | a5cf2bb4 | Cornelia Huck | dc->exit = virtio_ccw_busdev_exit; |
1264 | a5cf2bb4 | Cornelia Huck | dc->unplug = virtio_ccw_busdev_unplug; |
1265 | a5cf2bb4 | Cornelia Huck | dc->bus_type = TYPE_VIRTUAL_CSS_BUS; |
1266 | a5cf2bb4 | Cornelia Huck | |
1267 | a5cf2bb4 | Cornelia Huck | } |
1268 | a5cf2bb4 | Cornelia Huck | |
1269 | a5cf2bb4 | Cornelia Huck | static const TypeInfo virtio_ccw_device_info = { |
1270 | a5cf2bb4 | Cornelia Huck | .name = TYPE_VIRTIO_CCW_DEVICE, |
1271 | a5cf2bb4 | Cornelia Huck | .parent = TYPE_DEVICE, |
1272 | a5cf2bb4 | Cornelia Huck | .instance_size = sizeof(VirtioCcwDevice),
|
1273 | a5cf2bb4 | Cornelia Huck | .class_init = virtio_ccw_device_class_init, |
1274 | a5cf2bb4 | Cornelia Huck | .class_size = sizeof(VirtIOCCWDeviceClass),
|
1275 | a5cf2bb4 | Cornelia Huck | .abstract = true,
|
1276 | a5cf2bb4 | Cornelia Huck | }; |
1277 | a5cf2bb4 | Cornelia Huck | |
1278 | a5cf2bb4 | Cornelia Huck | /***************** Virtual-css Bus Bridge Device ********************/
|
1279 | a5cf2bb4 | Cornelia Huck | /* Only required to have the virtio bus as child in the system bus */
|
1280 | a5cf2bb4 | Cornelia Huck | |
1281 | a5cf2bb4 | Cornelia Huck | static int virtual_css_bridge_init(SysBusDevice *dev) |
1282 | a5cf2bb4 | Cornelia Huck | { |
1283 | a5cf2bb4 | Cornelia Huck | /* nothing */
|
1284 | a5cf2bb4 | Cornelia Huck | return 0; |
1285 | a5cf2bb4 | Cornelia Huck | } |
1286 | a5cf2bb4 | Cornelia Huck | |
1287 | a5cf2bb4 | Cornelia Huck | static void virtual_css_bridge_class_init(ObjectClass *klass, void *data) |
1288 | a5cf2bb4 | Cornelia Huck | { |
1289 | a5cf2bb4 | Cornelia Huck | SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); |
1290 | a5cf2bb4 | Cornelia Huck | |
1291 | a5cf2bb4 | Cornelia Huck | k->init = virtual_css_bridge_init; |
1292 | a5cf2bb4 | Cornelia Huck | } |
1293 | a5cf2bb4 | Cornelia Huck | |
1294 | a5cf2bb4 | Cornelia Huck | static const TypeInfo virtual_css_bridge_info = { |
1295 | a5cf2bb4 | Cornelia Huck | .name = "virtual-css-bridge",
|
1296 | a5cf2bb4 | Cornelia Huck | .parent = TYPE_SYS_BUS_DEVICE, |
1297 | a5cf2bb4 | Cornelia Huck | .instance_size = sizeof(SysBusDevice),
|
1298 | a5cf2bb4 | Cornelia Huck | .class_init = virtual_css_bridge_class_init, |
1299 | a5cf2bb4 | Cornelia Huck | }; |
1300 | a5cf2bb4 | Cornelia Huck | |
1301 | a5cf2bb4 | Cornelia Huck | /* virtio-ccw-bus */
|
1302 | a5cf2bb4 | Cornelia Huck | |
1303 | 1bf4d7aa | Andreas Färber | static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size, |
1304 | 1bf4d7aa | Andreas Färber | VirtioCcwDevice *dev) |
1305 | a5cf2bb4 | Cornelia Huck | { |
1306 | a5cf2bb4 | Cornelia Huck | DeviceState *qdev = DEVICE(dev); |
1307 | a5cf2bb4 | Cornelia Huck | BusState *qbus; |
1308 | f4dd69aa | KONRAD Frederic | char virtio_bus_name[] = "virtio-bus"; |
1309 | a5cf2bb4 | Cornelia Huck | |
1310 | fb17dfe0 | Andreas Färber | qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_CCW_BUS, |
1311 | fb17dfe0 | Andreas Färber | qdev, virtio_bus_name); |
1312 | a5cf2bb4 | Cornelia Huck | qbus = BUS(bus); |
1313 | cbd19063 | KONRAD Frederic | qbus->allow_hotplug = 1;
|
1314 | a5cf2bb4 | Cornelia Huck | } |
1315 | a5cf2bb4 | Cornelia Huck | |
1316 | a5cf2bb4 | Cornelia Huck | static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data) |
1317 | a5cf2bb4 | Cornelia Huck | { |
1318 | a5cf2bb4 | Cornelia Huck | VirtioBusClass *k = VIRTIO_BUS_CLASS(klass); |
1319 | a5cf2bb4 | Cornelia Huck | BusClass *bus_class = BUS_CLASS(klass); |
1320 | a5cf2bb4 | Cornelia Huck | |
1321 | a5cf2bb4 | Cornelia Huck | bus_class->max_dev = 1;
|
1322 | a5cf2bb4 | Cornelia Huck | k->notify = virtio_ccw_notify; |
1323 | a5cf2bb4 | Cornelia Huck | k->get_features = virtio_ccw_get_features; |
1324 | b4436a0b | Cornelia Huck | k->vmstate_change = virtio_ccw_vmstate_change; |
1325 | 320ce850 | Cornelia Huck | k->query_guest_notifiers = virtio_ccw_query_guest_notifiers; |
1326 | 320ce850 | Cornelia Huck | k->set_host_notifier = virtio_ccw_set_host_notifier; |
1327 | 320ce850 | Cornelia Huck | k->set_guest_notifiers = virtio_ccw_set_guest_notifiers; |
1328 | a5cf2bb4 | Cornelia Huck | } |
1329 | a5cf2bb4 | Cornelia Huck | |
1330 | a5cf2bb4 | Cornelia Huck | static const TypeInfo virtio_ccw_bus_info = { |
1331 | a5cf2bb4 | Cornelia Huck | .name = TYPE_VIRTIO_CCW_BUS, |
1332 | a5cf2bb4 | Cornelia Huck | .parent = TYPE_VIRTIO_BUS, |
1333 | a5cf2bb4 | Cornelia Huck | .instance_size = sizeof(VirtioCcwBusState),
|
1334 | a5cf2bb4 | Cornelia Huck | .class_init = virtio_ccw_bus_class_init, |
1335 | a5cf2bb4 | Cornelia Huck | }; |
1336 | a5cf2bb4 | Cornelia Huck | |
1337 | a5cf2bb4 | Cornelia Huck | static void virtio_ccw_register(void) |
1338 | a5cf2bb4 | Cornelia Huck | { |
1339 | a5cf2bb4 | Cornelia Huck | type_register_static(&virtio_ccw_bus_info); |
1340 | a5cf2bb4 | Cornelia Huck | type_register_static(&virtual_css_bus_info); |
1341 | a5cf2bb4 | Cornelia Huck | type_register_static(&virtio_ccw_device_info); |
1342 | a5cf2bb4 | Cornelia Huck | type_register_static(&virtio_ccw_serial); |
1343 | a5cf2bb4 | Cornelia Huck | type_register_static(&virtio_ccw_blk); |
1344 | a5cf2bb4 | Cornelia Huck | type_register_static(&virtio_ccw_net); |
1345 | a5cf2bb4 | Cornelia Huck | type_register_static(&virtio_ccw_balloon); |
1346 | a5cf2bb4 | Cornelia Huck | type_register_static(&virtio_ccw_scsi); |
1347 | b702d2ae | Ed Maste | #ifdef CONFIG_VHOST_SCSI
|
1348 | ccf6916c | Paolo Bonzini | type_register_static(&vhost_ccw_scsi); |
1349 | b702d2ae | Ed Maste | #endif
|
1350 | 2362ecc5 | Cornelia Huck | type_register_static(&virtio_ccw_rng); |
1351 | a5cf2bb4 | Cornelia Huck | type_register_static(&virtual_css_bridge_info); |
1352 | a5cf2bb4 | Cornelia Huck | } |
1353 | a5cf2bb4 | Cornelia Huck | |
1354 | a5cf2bb4 | Cornelia Huck | type_init(virtio_ccw_register) |