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