]> git.proxmox.com Git - qemu.git/blame - hw/s390x/virtio-ccw.c
acpi-build: disable with -no-acpi
[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
KF
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
b4436a0b 634 virtio_ccw_stop_ioeventfd(dev);
a5cf2bb4
CH
635 if (sch) {
636 css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
637 g_free(sch);
638 }
639 dev->indicators = 0;
640 return 0;
641}
642
89334c8b 643static int virtio_ccw_net_init(VirtioCcwDevice *ccw_dev)
a5cf2bb4 644{
800ced8c 645 DeviceState *qdev = DEVICE(ccw_dev);
89334c8b
KF
646 VirtIONetCcw *dev = VIRTIO_NET_CCW(ccw_dev);
647 DeviceState *vdev = DEVICE(&dev->vdev);
a5cf2bb4 648
89334c8b 649 virtio_net_set_config_size(&dev->vdev, ccw_dev->host_features[0]);
800ced8c
KF
650 virtio_net_set_netclient_name(&dev->vdev, qdev->id,
651 object_get_typename(OBJECT(qdev)));
89334c8b
KF
652 qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
653 if (qdev_init(vdev) < 0) {
a5cf2bb4
CH
654 return -1;
655 }
656
89334c8b 657 return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
a5cf2bb4
CH
658}
659
89334c8b 660static void virtio_ccw_net_instance_init(Object *obj)
a5cf2bb4 661{
89334c8b 662 VirtIONetCcw *dev = VIRTIO_NET_CCW(obj);
213f0c4f 663 object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NET);
89334c8b 664 object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
a5cf2bb4
CH
665}
666
3400c455 667static int virtio_ccw_blk_init(VirtioCcwDevice *ccw_dev)
a5cf2bb4 668{
3400c455
KF
669 VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(ccw_dev);
670 DeviceState *vdev = DEVICE(&dev->vdev);
671 virtio_blk_set_conf(vdev, &(dev->blk));
672 qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
673 if (qdev_init(vdev) < 0) {
a5cf2bb4
CH
674 return -1;
675 }
676
3400c455 677 return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
a5cf2bb4
CH
678}
679
3400c455 680static void virtio_ccw_blk_instance_init(Object *obj)
a5cf2bb4 681{
3400c455 682 VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(obj);
213f0c4f 683 object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK);
3400c455 684 object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
a5cf2bb4
CH
685}
686
6acf69cd 687static int virtio_ccw_serial_init(VirtioCcwDevice *ccw_dev)
a5cf2bb4 688{
6acf69cd
KF
689 VirtioSerialCcw *dev = VIRTIO_SERIAL_CCW(ccw_dev);
690 DeviceState *vdev = DEVICE(&dev->vdev);
80270a19
KF
691 DeviceState *proxy = DEVICE(ccw_dev);
692 char *bus_name;
693
694 /*
695 * For command line compatibility, this sets the virtio-serial-device bus
696 * name as before.
697 */
698 if (proxy->id) {
699 bus_name = g_strdup_printf("%s.0", proxy->id);
700 virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name);
701 g_free(bus_name);
702 }
a5cf2bb4 703
6acf69cd
KF
704 qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
705 if (qdev_init(vdev) < 0) {
a5cf2bb4
CH
706 return -1;
707 }
708
6acf69cd 709 return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
a5cf2bb4
CH
710}
711
6acf69cd
KF
712
713static void virtio_ccw_serial_instance_init(Object *obj)
a5cf2bb4 714{
6acf69cd 715 VirtioSerialCcw *dev = VIRTIO_SERIAL_CCW(obj);
213f0c4f 716 object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SERIAL);
6acf69cd 717 object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
a5cf2bb4
CH
718}
719
30bff6a0 720static int virtio_ccw_balloon_init(VirtioCcwDevice *ccw_dev)
a5cf2bb4 721{
30bff6a0
KF
722 VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(ccw_dev);
723 DeviceState *vdev = DEVICE(&dev->vdev);
a5cf2bb4 724
30bff6a0
KF
725 qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
726 if (qdev_init(vdev) < 0) {
a5cf2bb4
CH
727 return -1;
728 }
729
30bff6a0 730 return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
a5cf2bb4
CH
731}
732
24a6e7f4
KF
733static void balloon_ccw_stats_get_all(Object *obj, struct Visitor *v,
734 void *opaque, const char *name,
735 Error **errp)
736{
737 VirtIOBalloonCcw *dev = opaque;
738 object_property_get(OBJECT(&dev->vdev), v, "guest-stats", errp);
739}
740
741static void balloon_ccw_stats_get_poll_interval(Object *obj, struct Visitor *v,
742 void *opaque, const char *name,
743 Error **errp)
744{
745 VirtIOBalloonCcw *dev = opaque;
746 object_property_get(OBJECT(&dev->vdev), v, "guest-stats-polling-interval",
747 errp);
748}
749
750static void balloon_ccw_stats_set_poll_interval(Object *obj, struct Visitor *v,
751 void *opaque, const char *name,
752 Error **errp)
753{
754 VirtIOBalloonCcw *dev = opaque;
755 object_property_set(OBJECT(&dev->vdev), v, "guest-stats-polling-interval",
756 errp);
757}
758
30bff6a0 759static void virtio_ccw_balloon_instance_init(Object *obj)
a5cf2bb4 760{
30bff6a0 761 VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(obj);
213f0c4f 762 object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON);
30bff6a0 763 object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
24a6e7f4
KF
764
765 object_property_add(obj, "guest-stats", "guest statistics",
766 balloon_ccw_stats_get_all, NULL, NULL, dev, NULL);
767
768 object_property_add(obj, "guest-stats-polling-interval", "int",
769 balloon_ccw_stats_get_poll_interval,
770 balloon_ccw_stats_set_poll_interval,
771 NULL, dev, NULL);
a5cf2bb4
CH
772}
773
c908ea10 774static int virtio_ccw_scsi_init(VirtioCcwDevice *ccw_dev)
a5cf2bb4 775{
c908ea10
KF
776 VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(ccw_dev);
777 DeviceState *vdev = DEVICE(&dev->vdev);
6f32a6b4
KF
778 DeviceState *qdev = DEVICE(ccw_dev);
779 char *bus_name;
780
781 /*
782 * For command line compatibility, this sets the virtio-scsi-device bus
783 * name as before.
784 */
785 if (qdev->id) {
786 bus_name = g_strdup_printf("%s.0", qdev->id);
787 virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name);
788 g_free(bus_name);
789 }
a5cf2bb4 790
c908ea10
KF
791 qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
792 if (qdev_init(vdev) < 0) {
a5cf2bb4
CH
793 return -1;
794 }
795
c908ea10 796 return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
a5cf2bb4
CH
797}
798
c908ea10 799static void virtio_ccw_scsi_instance_init(Object *obj)
a5cf2bb4 800{
c908ea10 801 VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(obj);
213f0c4f 802 object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SCSI);
c908ea10 803 object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
a5cf2bb4
CH
804}
805
ccf6916c
PB
806#ifdef CONFIG_VHOST_SCSI
807static int vhost_ccw_scsi_init(VirtioCcwDevice *ccw_dev)
808{
809 VHostSCSICcw *dev = VHOST_SCSI_CCW(ccw_dev);
810 DeviceState *vdev = DEVICE(&dev->vdev);
811
812 qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
813 if (qdev_init(vdev) < 0) {
814 return -1;
815 }
816
817 return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
818}
819
820static void vhost_ccw_scsi_instance_init(Object *obj)
821{
822 VHostSCSICcw *dev = VHOST_SCSI_CCW(obj);
213f0c4f 823 object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VHOST_SCSI);
ccf6916c
PB
824 object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
825}
826#endif
827
2db26d4c 828static int virtio_ccw_rng_init(VirtioCcwDevice *ccw_dev)
2362ecc5 829{
2db26d4c
KF
830 VirtIORNGCcw *dev = VIRTIO_RNG_CCW(ccw_dev);
831 DeviceState *vdev = DEVICE(&dev->vdev);
2362ecc5 832
2db26d4c
KF
833 qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
834 if (qdev_init(vdev) < 0) {
2362ecc5
CH
835 return -1;
836 }
2362ecc5 837
2db26d4c 838 object_property_set_link(OBJECT(dev),
5b456438 839 OBJECT(dev->vdev.conf.rng), "rng",
2db26d4c
KF
840 NULL);
841
842 return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
2362ecc5
CH
843}
844
a5cf2bb4
CH
845/* DeviceState to VirtioCcwDevice. Note: used on datapath,
846 * be careful and test performance if you change this.
847 */
848static inline VirtioCcwDevice *to_virtio_ccw_dev_fast(DeviceState *d)
849{
850 return container_of(d, VirtioCcwDevice, parent_obj);
851}
852
853static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
854{
855 VirtioCcwDevice *dev = to_virtio_ccw_dev_fast(d);
856 SubchDev *sch = dev->sch;
857 uint64_t indicators;
858
859 if (vector >= 128) {
860 return;
861 }
862
863 if (vector < VIRTIO_PCI_QUEUE_MAX) {
7c486976
CH
864 if (!dev->indicators) {
865 return;
866 }
a5cf2bb4 867 indicators = ldq_phys(dev->indicators);
19380b1b 868 indicators |= 1ULL << vector;
a5cf2bb4
CH
869 stq_phys(dev->indicators, indicators);
870 } else {
7c486976
CH
871 if (!dev->indicators2) {
872 return;
873 }
a5cf2bb4
CH
874 vector = 0;
875 indicators = ldq_phys(dev->indicators2);
19380b1b 876 indicators |= 1ULL << vector;
a5cf2bb4
CH
877 stq_phys(dev->indicators2, indicators);
878 }
879
880 css_conditional_io_interrupt(sch);
881
882}
883
884static unsigned virtio_ccw_get_features(DeviceState *d)
885{
886 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
887
888 /* Only the first 32 feature bits are used. */
889 return dev->host_features[0];
890}
891
892static void virtio_ccw_reset(DeviceState *d)
893{
894 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
895
b4436a0b 896 virtio_ccw_stop_ioeventfd(dev);
a5cf2bb4
CH
897 virtio_reset(dev->vdev);
898 css_reset_sch(dev->sch);
6504a930
CB
899 dev->indicators = 0;
900 dev->indicators2 = 0;
a5cf2bb4
CH
901}
902
b4436a0b
CH
903static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
904{
905 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
906
907 if (running) {
908 virtio_ccw_start_ioeventfd(dev);
909 } else {
910 virtio_ccw_stop_ioeventfd(dev);
911 }
912}
913
320ce850
CH
914static bool virtio_ccw_query_guest_notifiers(DeviceState *d)
915{
916 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
917
918 return !!(dev->sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA);
919}
920
921static int virtio_ccw_set_host_notifier(DeviceState *d, int n, bool assign)
922{
923 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
924
925 /* Stop using the generic ioeventfd, we are doing eventfd handling
926 * ourselves below */
927 dev->ioeventfd_disabled = assign;
928 if (assign) {
929 virtio_ccw_stop_ioeventfd(dev);
930 }
931 return virtio_ccw_set_guest2host_notifier(dev, n, assign, false);
932}
933
934static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
935 bool assign, bool with_irqfd)
936{
937 VirtQueue *vq = virtio_get_queue(dev->vdev, n);
938 EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
939 VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(dev->vdev);
940
941 if (assign) {
942 int r = event_notifier_init(notifier, 0);
943
944 if (r < 0) {
945 return r;
946 }
947 virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
948 /* We do not support irqfd for classic I/O interrupts, because the
949 * classic interrupts are intermixed with the subchannel status, that
950 * is queried with test subchannel. We want to use vhost, though.
951 * Lets make sure to have vhost running and wire up the irq fd to
952 * land in qemu (and only the irq fd) in this code.
953 */
954 if (k->guest_notifier_mask) {
955 k->guest_notifier_mask(dev->vdev, n, false);
956 }
957 /* get lost events and re-inject */
958 if (k->guest_notifier_pending &&
959 k->guest_notifier_pending(dev->vdev, n)) {
960 event_notifier_set(notifier);
961 }
962 } else {
963 if (k->guest_notifier_mask) {
964 k->guest_notifier_mask(dev->vdev, n, true);
965 }
966 virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
967 event_notifier_cleanup(notifier);
968 }
969 return 0;
970}
971
972static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs,
973 bool assigned)
974{
975 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
976 VirtIODevice *vdev = dev->vdev;
977 int r, n;
978
979 for (n = 0; n < nvqs; n++) {
980 if (!virtio_queue_get_num(vdev, n)) {
981 break;
982 }
983 /* false -> true, as soon as irqfd works */
984 r = virtio_ccw_set_guest_notifier(dev, n, assigned, false);
985 if (r < 0) {
986 goto assign_error;
987 }
988 }
989 return 0;
990
991assign_error:
992 while (--n >= 0) {
993 virtio_ccw_set_guest_notifier(dev, n, !assigned, false);
994 }
995 return r;
996}
997
a5cf2bb4
CH
998/**************** Virtio-ccw Bus Device Descriptions *******************/
999
a5cf2bb4
CH
1000static Property virtio_ccw_net_properties[] = {
1001 DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
1002 DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features[0]),
89334c8b
KF
1003 DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetCcw, vdev.net_conf),
1004 DEFINE_NIC_PROPERTIES(VirtIONetCcw, vdev.nic_conf),
b4436a0b
CH
1005 DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
1006 VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
a5cf2bb4
CH
1007 DEFINE_PROP_END_OF_LIST(),
1008};
1009
1010static void virtio_ccw_net_class_init(ObjectClass *klass, void *data)
1011{
1012 DeviceClass *dc = DEVICE_CLASS(klass);
1013 VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
1014
1015 k->init = virtio_ccw_net_init;
89334c8b 1016 k->exit = virtio_ccw_exit;
a5cf2bb4
CH
1017 dc->reset = virtio_ccw_reset;
1018 dc->props = virtio_ccw_net_properties;
1019}
1020
1021static const TypeInfo virtio_ccw_net = {
89334c8b 1022 .name = TYPE_VIRTIO_NET_CCW,
a5cf2bb4 1023 .parent = TYPE_VIRTIO_CCW_DEVICE,
89334c8b
KF
1024 .instance_size = sizeof(VirtIONetCcw),
1025 .instance_init = virtio_ccw_net_instance_init,
a5cf2bb4
CH
1026 .class_init = virtio_ccw_net_class_init,
1027};
1028
1029static Property virtio_ccw_blk_properties[] = {
1030 DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
a5cf2bb4 1031 DEFINE_VIRTIO_BLK_FEATURES(VirtioCcwDevice, host_features[0]),
fe42d7fb 1032 DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkCcw, blk),
b4436a0b
CH
1033 DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
1034 VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
bf72d89f
DD
1035#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
1036 DEFINE_PROP_BIT("x-data-plane", VirtIOBlkCcw, blk.data_plane, 0, false),
1037#endif
a5cf2bb4
CH
1038 DEFINE_PROP_END_OF_LIST(),
1039};
1040
1041static void virtio_ccw_blk_class_init(ObjectClass *klass, void *data)
1042{
1043 DeviceClass *dc = DEVICE_CLASS(klass);
1044 VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
1045
1046 k->init = virtio_ccw_blk_init;
3400c455 1047 k->exit = virtio_ccw_exit;
a5cf2bb4
CH
1048 dc->reset = virtio_ccw_reset;
1049 dc->props = virtio_ccw_blk_properties;
1050}
1051
1052static const TypeInfo virtio_ccw_blk = {
3400c455 1053 .name = TYPE_VIRTIO_BLK_CCW,
a5cf2bb4 1054 .parent = TYPE_VIRTIO_CCW_DEVICE,
3400c455
KF
1055 .instance_size = sizeof(VirtIOBlkCcw),
1056 .instance_init = virtio_ccw_blk_instance_init,
a5cf2bb4
CH
1057 .class_init = virtio_ccw_blk_class_init,
1058};
1059
1060static Property virtio_ccw_serial_properties[] = {
1061 DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
6acf69cd 1062 DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtioSerialCcw, vdev.serial),
a5cf2bb4 1063 DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
b4436a0b
CH
1064 DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
1065 VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
a5cf2bb4
CH
1066 DEFINE_PROP_END_OF_LIST(),
1067};
1068
1069static void virtio_ccw_serial_class_init(ObjectClass *klass, void *data)
1070{
1071 DeviceClass *dc = DEVICE_CLASS(klass);
1072 VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
1073
1074 k->init = virtio_ccw_serial_init;
6acf69cd 1075 k->exit = virtio_ccw_exit;
a5cf2bb4
CH
1076 dc->reset = virtio_ccw_reset;
1077 dc->props = virtio_ccw_serial_properties;
1078}
1079
1080static const TypeInfo virtio_ccw_serial = {
6acf69cd 1081 .name = TYPE_VIRTIO_SERIAL_CCW,
a5cf2bb4 1082 .parent = TYPE_VIRTIO_CCW_DEVICE,
6acf69cd
KF
1083 .instance_size = sizeof(VirtioSerialCcw),
1084 .instance_init = virtio_ccw_serial_instance_init,
a5cf2bb4
CH
1085 .class_init = virtio_ccw_serial_class_init,
1086};
1087
1088static Property virtio_ccw_balloon_properties[] = {
1089 DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
1090 DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
b4436a0b
CH
1091 DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
1092 VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
a5cf2bb4
CH
1093 DEFINE_PROP_END_OF_LIST(),
1094};
1095
1096static void virtio_ccw_balloon_class_init(ObjectClass *klass, void *data)
1097{
1098 DeviceClass *dc = DEVICE_CLASS(klass);
1099 VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
1100
1101 k->init = virtio_ccw_balloon_init;
30bff6a0 1102 k->exit = virtio_ccw_exit;
a5cf2bb4
CH
1103 dc->reset = virtio_ccw_reset;
1104 dc->props = virtio_ccw_balloon_properties;
1105}
1106
1107static const TypeInfo virtio_ccw_balloon = {
30bff6a0 1108 .name = TYPE_VIRTIO_BALLOON_CCW,
a5cf2bb4 1109 .parent = TYPE_VIRTIO_CCW_DEVICE,
30bff6a0
KF
1110 .instance_size = sizeof(VirtIOBalloonCcw),
1111 .instance_init = virtio_ccw_balloon_instance_init,
a5cf2bb4
CH
1112 .class_init = virtio_ccw_balloon_class_init,
1113};
1114
1115static Property virtio_ccw_scsi_properties[] = {
1116 DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
292c8e50 1117 DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSICcw, vdev.parent_obj.conf),
4bfeb18a 1118 DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]),
b4436a0b
CH
1119 DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
1120 VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
a5cf2bb4
CH
1121 DEFINE_PROP_END_OF_LIST(),
1122};
1123
1124static void virtio_ccw_scsi_class_init(ObjectClass *klass, void *data)
1125{
1126 DeviceClass *dc = DEVICE_CLASS(klass);
1127 VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
1128
1129 k->init = virtio_ccw_scsi_init;
c908ea10 1130 k->exit = virtio_ccw_exit;
a5cf2bb4
CH
1131 dc->reset = virtio_ccw_reset;
1132 dc->props = virtio_ccw_scsi_properties;
1133}
1134
1135static const TypeInfo virtio_ccw_scsi = {
c908ea10 1136 .name = TYPE_VIRTIO_SCSI_CCW,
a5cf2bb4 1137 .parent = TYPE_VIRTIO_CCW_DEVICE,
c908ea10
KF
1138 .instance_size = sizeof(VirtIOSCSICcw),
1139 .instance_init = virtio_ccw_scsi_instance_init,
a5cf2bb4
CH
1140 .class_init = virtio_ccw_scsi_class_init,
1141};
1142
ccf6916c
PB
1143#ifdef CONFIG_VHOST_SCSI
1144static Property vhost_ccw_scsi_properties[] = {
1145 DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
1146 DEFINE_VHOST_SCSI_PROPERTIES(VirtIOSCSICcw, vdev.parent_obj.conf),
1147 DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
1148 DEFINE_PROP_END_OF_LIST(),
1149};
1150
1151static void vhost_ccw_scsi_class_init(ObjectClass *klass, void *data)
1152{
1153 DeviceClass *dc = DEVICE_CLASS(klass);
1154 VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
1155
1156 k->init = vhost_ccw_scsi_init;
1157 k->exit = virtio_ccw_exit;
1158 dc->reset = virtio_ccw_reset;
1159 dc->props = vhost_ccw_scsi_properties;
1160}
1161
1162static const TypeInfo vhost_ccw_scsi = {
1163 .name = TYPE_VHOST_SCSI_CCW,
1164 .parent = TYPE_VIRTIO_CCW_DEVICE,
1165 .instance_size = sizeof(VirtIOSCSICcw),
1166 .instance_init = vhost_ccw_scsi_instance_init,
1167 .class_init = vhost_ccw_scsi_class_init,
1168};
1169#endif
1170
2db26d4c 1171static void virtio_ccw_rng_instance_init(Object *obj)
2362ecc5 1172{
2db26d4c 1173 VirtIORNGCcw *dev = VIRTIO_RNG_CCW(obj);
213f0c4f 1174 object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
2db26d4c 1175 object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
2362ecc5 1176 object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
2db26d4c 1177 (Object **)&dev->vdev.conf.rng, NULL);
2362ecc5
CH
1178}
1179
1180static Property virtio_ccw_rng_properties[] = {
1181 DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
1182 DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
2db26d4c 1183 DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORNGCcw, vdev.conf),
b4436a0b
CH
1184 DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
1185 VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
2362ecc5
CH
1186 DEFINE_PROP_END_OF_LIST(),
1187};
1188
1189static void virtio_ccw_rng_class_init(ObjectClass *klass, void *data)
1190{
1191 DeviceClass *dc = DEVICE_CLASS(klass);
1192 VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
1193
1194 k->init = virtio_ccw_rng_init;
2db26d4c 1195 k->exit = virtio_ccw_exit;
2362ecc5
CH
1196 dc->reset = virtio_ccw_reset;
1197 dc->props = virtio_ccw_rng_properties;
1198}
1199
1200static const TypeInfo virtio_ccw_rng = {
2db26d4c 1201 .name = TYPE_VIRTIO_RNG_CCW,
2362ecc5 1202 .parent = TYPE_VIRTIO_CCW_DEVICE,
2db26d4c
KF
1203 .instance_size = sizeof(VirtIORNGCcw),
1204 .instance_init = virtio_ccw_rng_instance_init,
2362ecc5
CH
1205 .class_init = virtio_ccw_rng_class_init,
1206};
1207
a5cf2bb4
CH
1208static int virtio_ccw_busdev_init(DeviceState *dev)
1209{
1210 VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
1211 VirtIOCCWDeviceClass *_info = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
1212
1bf4d7aa 1213 virtio_ccw_bus_new(&_dev->bus, sizeof(_dev->bus), _dev);
a5cf2bb4
CH
1214
1215 return _info->init(_dev);
1216}
1217
1218static int virtio_ccw_busdev_exit(DeviceState *dev)
1219{
1220 VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
1221 VirtIOCCWDeviceClass *_info = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
1222
1223 return _info->exit(_dev);
1224}
1225
1226static int virtio_ccw_busdev_unplug(DeviceState *dev)
1227{
1228 VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
1229 SubchDev *sch = _dev->sch;
1230
1231 /*
1232 * We should arrive here only for device_del, since we don't support
1233 * direct hot(un)plug of channels, but only through virtio.
1234 */
1235 assert(sch != NULL);
1236 /* Subchannel is now disabled and no longer valid. */
1237 sch->curr_status.pmcw.flags &= ~(PMCW_FLAGS_MASK_ENA |
1238 PMCW_FLAGS_MASK_DNV);
1239
1240 css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
1241
02a5c4c9 1242 object_unparent(OBJECT(dev));
a5cf2bb4
CH
1243 return 0;
1244}
1245
1246static void virtio_ccw_device_class_init(ObjectClass *klass, void *data)
1247{
1248 DeviceClass *dc = DEVICE_CLASS(klass);
1249
1250 dc->init = virtio_ccw_busdev_init;
1251 dc->exit = virtio_ccw_busdev_exit;
1252 dc->unplug = virtio_ccw_busdev_unplug;
1253 dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
1254
1255}
1256
1257static const TypeInfo virtio_ccw_device_info = {
1258 .name = TYPE_VIRTIO_CCW_DEVICE,
1259 .parent = TYPE_DEVICE,
1260 .instance_size = sizeof(VirtioCcwDevice),
1261 .class_init = virtio_ccw_device_class_init,
1262 .class_size = sizeof(VirtIOCCWDeviceClass),
1263 .abstract = true,
1264};
1265
1266/***************** Virtual-css Bus Bridge Device ********************/
1267/* Only required to have the virtio bus as child in the system bus */
1268
1269static int virtual_css_bridge_init(SysBusDevice *dev)
1270{
1271 /* nothing */
1272 return 0;
1273}
1274
1275static void virtual_css_bridge_class_init(ObjectClass *klass, void *data)
1276{
1277 DeviceClass *dc = DEVICE_CLASS(klass);
1278 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
1279
1280 k->init = virtual_css_bridge_init;
1281 dc->no_user = 1;
1282}
1283
1284static const TypeInfo virtual_css_bridge_info = {
1285 .name = "virtual-css-bridge",
1286 .parent = TYPE_SYS_BUS_DEVICE,
1287 .instance_size = sizeof(SysBusDevice),
1288 .class_init = virtual_css_bridge_class_init,
1289};
1290
1291/* virtio-ccw-bus */
1292
1bf4d7aa
AF
1293static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
1294 VirtioCcwDevice *dev)
a5cf2bb4
CH
1295{
1296 DeviceState *qdev = DEVICE(dev);
1297 BusState *qbus;
f4dd69aa 1298 char virtio_bus_name[] = "virtio-bus";
a5cf2bb4 1299
fb17dfe0
AF
1300 qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_CCW_BUS,
1301 qdev, virtio_bus_name);
a5cf2bb4 1302 qbus = BUS(bus);
cbd19063 1303 qbus->allow_hotplug = 1;
a5cf2bb4
CH
1304}
1305
1306static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
1307{
1308 VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
1309 BusClass *bus_class = BUS_CLASS(klass);
1310
1311 bus_class->max_dev = 1;
1312 k->notify = virtio_ccw_notify;
1313 k->get_features = virtio_ccw_get_features;
b4436a0b 1314 k->vmstate_change = virtio_ccw_vmstate_change;
320ce850
CH
1315 k->query_guest_notifiers = virtio_ccw_query_guest_notifiers;
1316 k->set_host_notifier = virtio_ccw_set_host_notifier;
1317 k->set_guest_notifiers = virtio_ccw_set_guest_notifiers;
a5cf2bb4
CH
1318}
1319
1320static const TypeInfo virtio_ccw_bus_info = {
1321 .name = TYPE_VIRTIO_CCW_BUS,
1322 .parent = TYPE_VIRTIO_BUS,
1323 .instance_size = sizeof(VirtioCcwBusState),
1324 .class_init = virtio_ccw_bus_class_init,
1325};
1326
1327static void virtio_ccw_register(void)
1328{
1329 type_register_static(&virtio_ccw_bus_info);
1330 type_register_static(&virtual_css_bus_info);
1331 type_register_static(&virtio_ccw_device_info);
1332 type_register_static(&virtio_ccw_serial);
1333 type_register_static(&virtio_ccw_blk);
1334 type_register_static(&virtio_ccw_net);
1335 type_register_static(&virtio_ccw_balloon);
1336 type_register_static(&virtio_ccw_scsi);
b702d2ae 1337#ifdef CONFIG_VHOST_SCSI
ccf6916c 1338 type_register_static(&vhost_ccw_scsi);
b702d2ae 1339#endif
2362ecc5 1340 type_register_static(&virtio_ccw_rng);
a5cf2bb4
CH
1341 type_register_static(&virtual_css_bridge_info);
1342}
1343
1344type_init(virtio_ccw_register)