Statistics
| Branch: | Revision:

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)