1 /* 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 25 #include "hw/hw.h" 26 #include "qemu/error-report.h" 27 #include "hw/qdev.h" 28 #include "hw/virtio/virtio-bus.h" 29 #include "hw/virtio/virtio.h" 30 31 /* #define DEBUG_VIRTIO_BUS */ 32 33 #ifdef DEBUG_VIRTIO_BUS 34 #define DPRINTF(fmt, ...) \ 35 do { printf("virtio_bus: " fmt , ## __VA_ARGS__); } while (0) 36 #else 37 #define DPRINTF(fmt, ...) do { } while (0) 38 #endif 39 40 /* Plug the VirtIODevice */ 41 int virtio_bus_plug_device(VirtIODevice *vdev) 42 { 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 49 bus->vdev = vdev; 50 51 /* 52 * The lines below will disappear when we drop VirtIOBindings, at the end 53 * of the series. 54 */ 55 bus->bindings.notify = klass->notify; 56 bus->bindings.save_config = klass->save_config; 57 bus->bindings.save_queue = klass->save_queue; 58 bus->bindings.load_config = klass->load_config; 59 bus->bindings.load_queue = klass->load_queue; 60 bus->bindings.load_done = klass->load_done; 61 bus->bindings.get_features = klass->get_features; 62 bus->bindings.query_guest_notifiers = klass->query_guest_notifiers; 63 bus->bindings.set_guest_notifiers = klass->set_guest_notifiers; 64 bus->bindings.set_host_notifier = klass->set_host_notifier; 65 bus->bindings.vmstate_change = klass->vmstate_change; 66 virtio_bind_device(bus->vdev, &bus->bindings, qbus->parent); 67 68 if (klass->device_plugged != NULL) { 69 klass->device_plugged(qbus->parent); 70 } 71 72 return 0; 73 } 74 75 /* Reset the virtio_bus */ 76 void virtio_bus_reset(VirtioBusState *bus) 77 { 78 DPRINTF("%s: reset device.\n", qbus->name); 79 if (bus->vdev != NULL) { 80 virtio_reset(bus->vdev); 81 } 82 } 83 84 /* Destroy the VirtIODevice */ 85 void virtio_bus_destroy_device(VirtioBusState *bus) 86 { 87 DeviceState *qdev; 88 BusState *qbus = BUS(bus); 89 VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus); 90 DPRINTF("%s: remove device.\n", qbus->name); 91 92 if (bus->vdev != NULL) { 93 if (klass->device_unplug != NULL) { 94 klass->device_unplug(qbus->parent); 95 } 96 qdev = DEVICE(bus->vdev); 97 qdev_free(qdev); 98 bus->vdev = NULL; 99 } 100 } 101 102 /* Get the device id of the plugged device. */ 103 uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus) 104 { 105 assert(bus->vdev != NULL); 106 return bus->vdev->device_id; 107 } 108 109 /* Get the config_len field of the plugged device. */ 110 size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus) 111 { 112 assert(bus->vdev != NULL); 113 return bus->vdev->config_len; 114 } 115 116 /* Get the features of the plugged device. */ 117 uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus, 118 uint32_t requested_features) 119 { 120 VirtioDeviceClass *k; 121 assert(bus->vdev != NULL); 122 k = VIRTIO_DEVICE_GET_CLASS(bus->vdev); 123 assert(k->get_features != NULL); 124 return k->get_features(bus->vdev, requested_features); 125 } 126 127 /* Get bad features of the plugged device. */ 128 uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus) 129 { 130 VirtioDeviceClass *k; 131 assert(bus->vdev != NULL); 132 k = VIRTIO_DEVICE_GET_CLASS(bus->vdev); 133 if (k->bad_features != NULL) { 134 return k->bad_features(bus->vdev); 135 } else { 136 return 0; 137 } 138 } 139 140 /* Get config of the plugged device. */ 141 void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config) 142 { 143 VirtioDeviceClass *k; 144 assert(bus->vdev != NULL); 145 k = VIRTIO_DEVICE_GET_CLASS(bus->vdev); 146 if (k->get_config != NULL) { 147 k->get_config(bus->vdev, config); 148 } 149 } 150 151 static const TypeInfo virtio_bus_info = { 152 .name = TYPE_VIRTIO_BUS, 153 .parent = TYPE_BUS, 154 .instance_size = sizeof(VirtioBusState), 155 .abstract = true, 156 .class_size = sizeof(VirtioBusClass), 157 }; 158 159 static void virtio_register_types(void) 160 { 161 type_register_static(&virtio_bus_info); 162 } 163 164 type_init(virtio_register_types) 165