blob: eb77019267503de1091636be03624f305b5cd8cc [file] [log] [blame]
KONRAD Fredericff8eca52013-01-15 00:08:01 +01001/*
2 * VirtioBus
3 *
4 * Copyright (C) 2012 : GreenSocs Ltd
5 * http://www.greensocs.com/ , email: info@greensocs.com
6 *
7 * Developed by :
8 * Frederic Konrad <fred.konrad@greensocs.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
Paolo Bonzini83c9f4c2013-02-04 15:40:22 +010025#include "hw/hw.h"
KONRAD Fredericff8eca52013-01-15 00:08:01 +010026#include "qemu/error-report.h"
Paolo Bonzini83c9f4c2013-02-04 15:40:22 +010027#include "hw/qdev.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010028#include "hw/virtio/virtio-bus.h"
29#include "hw/virtio/virtio.h"
KONRAD Fredericff8eca52013-01-15 00:08:01 +010030
31/* #define DEBUG_VIRTIO_BUS */
32
33#ifdef DEBUG_VIRTIO_BUS
34#define DPRINTF(fmt, ...) \
35do { printf("virtio_bus: " fmt , ## __VA_ARGS__); } while (0)
36#else
37#define DPRINTF(fmt, ...) do { } while (0)
38#endif
39
Paolo Bonzini5e96f5d2013-09-20 13:59:08 +020040/* A VirtIODevice is being plugged */
41int virtio_bus_device_plugged(VirtIODevice *vdev)
KONRAD Fredericff8eca52013-01-15 00:08:01 +010042{
43 DeviceState *qdev = DEVICE(vdev);
44 BusState *qbus = BUS(qdev_get_parent_bus(qdev));
45 VirtioBusState *bus = VIRTIO_BUS(qbus);
46 VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
47 DPRINTF("%s: plug device.\n", qbus->name);
48
KONRAD Fredericff8eca52013-01-15 00:08:01 +010049 if (klass->device_plugged != NULL) {
50 klass->device_plugged(qbus->parent);
51 }
52
53 return 0;
54}
55
56/* Reset the virtio_bus */
57void virtio_bus_reset(VirtioBusState *bus)
58{
Paolo Bonzini06d3dff2013-09-20 13:31:39 +020059 VirtIODevice *vdev = virtio_bus_get_device(bus);
60
KONRAD Fredericff8eca52013-01-15 00:08:01 +010061 DPRINTF("%s: reset device.\n", qbus->name);
Paolo Bonzini06d3dff2013-09-20 13:31:39 +020062 if (vdev != NULL) {
63 virtio_reset(vdev);
KONRAD Fredericff8eca52013-01-15 00:08:01 +010064 }
65}
66
Paolo Bonzini5e96f5d2013-09-20 13:59:08 +020067/* A VirtIODevice is being unplugged */
68void virtio_bus_device_unplugged(VirtIODevice *vdev)
KONRAD Fredericff8eca52013-01-15 00:08:01 +010069{
Paolo Bonzini5e96f5d2013-09-20 13:59:08 +020070 DeviceState *qdev = DEVICE(vdev);
71 BusState *qbus = BUS(qdev_get_parent_bus(qdev));
72 VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(qbus);
Paolo Bonzini06d3dff2013-09-20 13:31:39 +020073
KONRAD Fredericff8eca52013-01-15 00:08:01 +010074 DPRINTF("%s: remove device.\n", qbus->name);
75
Paolo Bonzini06d3dff2013-09-20 13:31:39 +020076 if (vdev != NULL) {
Paolo Bonzini5e96f5d2013-09-20 13:59:08 +020077 if (klass->device_unplugged != NULL) {
78 klass->device_unplugged(qbus->parent);
KONRAD Fredericff8eca52013-01-15 00:08:01 +010079 }
KONRAD Fredericff8eca52013-01-15 00:08:01 +010080 }
81}
82
83/* Get the device id of the plugged device. */
84uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus)
85{
Paolo Bonzini06d3dff2013-09-20 13:31:39 +020086 VirtIODevice *vdev = virtio_bus_get_device(bus);
87 assert(vdev != NULL);
88 return vdev->device_id;
KONRAD Fredericff8eca52013-01-15 00:08:01 +010089}
90
91/* Get the config_len field of the plugged device. */
92size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus)
93{
Paolo Bonzini06d3dff2013-09-20 13:31:39 +020094 VirtIODevice *vdev = virtio_bus_get_device(bus);
95 assert(vdev != NULL);
96 return vdev->config_len;
KONRAD Fredericff8eca52013-01-15 00:08:01 +010097}
98
KONRAD Frederic8e05db92013-01-15 00:08:02 +010099/* Get the features of the plugged device. */
100uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus,
101 uint32_t requested_features)
102{
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200103 VirtIODevice *vdev = virtio_bus_get_device(bus);
KONRAD Frederic8e05db92013-01-15 00:08:02 +0100104 VirtioDeviceClass *k;
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200105
106 assert(vdev != NULL);
107 k = VIRTIO_DEVICE_GET_CLASS(vdev);
KONRAD Frederic8e05db92013-01-15 00:08:02 +0100108 assert(k->get_features != NULL);
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200109 return k->get_features(vdev, requested_features);
KONRAD Frederic8e05db92013-01-15 00:08:02 +0100110}
111
KONRAD Frederic5d448f92013-04-24 10:21:17 +0200112/* Set the features of the plugged device. */
113void virtio_bus_set_vdev_features(VirtioBusState *bus,
114 uint32_t requested_features)
115{
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200116 VirtIODevice *vdev = virtio_bus_get_device(bus);
KONRAD Frederic5d448f92013-04-24 10:21:17 +0200117 VirtioDeviceClass *k;
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200118
119 assert(vdev != NULL);
120 k = VIRTIO_DEVICE_GET_CLASS(vdev);
KONRAD Frederic5d448f92013-04-24 10:21:17 +0200121 if (k->set_features != NULL) {
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200122 k->set_features(vdev, requested_features);
KONRAD Frederic5d448f92013-04-24 10:21:17 +0200123 }
124}
125
KONRAD Frederic8e05db92013-01-15 00:08:02 +0100126/* Get bad features of the plugged device. */
127uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus)
128{
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200129 VirtIODevice *vdev = virtio_bus_get_device(bus);
KONRAD Frederic8e05db92013-01-15 00:08:02 +0100130 VirtioDeviceClass *k;
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200131
132 assert(vdev != NULL);
133 k = VIRTIO_DEVICE_GET_CLASS(vdev);
KONRAD Frederic8e05db92013-01-15 00:08:02 +0100134 if (k->bad_features != NULL) {
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200135 return k->bad_features(vdev);
KONRAD Frederic8e05db92013-01-15 00:08:02 +0100136 } else {
137 return 0;
138 }
139}
140
141/* Get config of the plugged device. */
142void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config)
143{
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200144 VirtIODevice *vdev = virtio_bus_get_device(bus);
KONRAD Frederic8e05db92013-01-15 00:08:02 +0100145 VirtioDeviceClass *k;
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200146
147 assert(vdev != NULL);
148 k = VIRTIO_DEVICE_GET_CLASS(vdev);
KONRAD Frederic8e05db92013-01-15 00:08:02 +0100149 if (k->get_config != NULL) {
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200150 k->get_config(vdev, config);
KONRAD Frederic8e05db92013-01-15 00:08:02 +0100151 }
152}
153
KONRAD Frederic5d448f92013-04-24 10:21:17 +0200154/* Set config of the plugged device. */
155void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config)
156{
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200157 VirtIODevice *vdev = virtio_bus_get_device(bus);
KONRAD Frederic5d448f92013-04-24 10:21:17 +0200158 VirtioDeviceClass *k;
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200159
160 assert(vdev != NULL);
161 k = VIRTIO_DEVICE_GET_CLASS(vdev);
KONRAD Frederic5d448f92013-04-24 10:21:17 +0200162 if (k->set_config != NULL) {
Paolo Bonzini06d3dff2013-09-20 13:31:39 +0200163 k->set_config(vdev, config);
KONRAD Frederic5d448f92013-04-24 10:21:17 +0200164 }
165}
166
KONRAD Frederic6d468952013-05-16 19:06:07 +0200167static char *virtio_bus_get_dev_path(DeviceState *dev)
168{
169 BusState *bus = qdev_get_parent_bus(dev);
170 DeviceState *proxy = DEVICE(bus->parent);
171 return qdev_get_dev_path(proxy);
172}
173
Amos Kongbbfa18f2013-05-29 15:56:42 +0800174static char *virtio_bus_get_fw_dev_path(DeviceState *dev)
175{
176 return NULL;
177}
178
KONRAD Frederic6d468952013-05-16 19:06:07 +0200179static void virtio_bus_class_init(ObjectClass *klass, void *data)
180{
181 BusClass *bus_class = BUS_CLASS(klass);
182 bus_class->get_dev_path = virtio_bus_get_dev_path;
Amos Kongbbfa18f2013-05-29 15:56:42 +0800183 bus_class->get_fw_dev_path = virtio_bus_get_fw_dev_path;
KONRAD Frederic6d468952013-05-16 19:06:07 +0200184}
185
KONRAD Fredericff8eca52013-01-15 00:08:01 +0100186static const TypeInfo virtio_bus_info = {
187 .name = TYPE_VIRTIO_BUS,
188 .parent = TYPE_BUS,
189 .instance_size = sizeof(VirtioBusState),
190 .abstract = true,
191 .class_size = sizeof(VirtioBusClass),
KONRAD Frederic6d468952013-05-16 19:06:07 +0200192 .class_init = virtio_bus_class_init
KONRAD Fredericff8eca52013-01-15 00:08:01 +0100193};
194
195static void virtio_register_types(void)
196{
197 type_register_static(&virtio_bus_info);
198}
199
200type_init(virtio_register_types)