1 /* 2 * System (CPU) Bus device support code 3 * 4 * Copyright (c) 2009 CodeSourcery 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "hw/sysbus.h" 21 #include "monitor/monitor.h" 22 #include "exec/address-spaces.h" 23 24 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent); 25 static char *sysbus_get_fw_dev_path(DeviceState *dev); 26 27 static void system_bus_class_init(ObjectClass *klass, void *data) 28 { 29 BusClass *k = BUS_CLASS(klass); 30 31 k->print_dev = sysbus_dev_print; 32 k->get_fw_dev_path = sysbus_get_fw_dev_path; 33 } 34 35 static const TypeInfo system_bus_info = { 36 .name = TYPE_SYSTEM_BUS, 37 .parent = TYPE_BUS, 38 .instance_size = sizeof(BusState), 39 .class_init = system_bus_class_init, 40 }; 41 42 void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) 43 { 44 assert(n >= 0 && n < dev->num_irq); 45 dev->irqs[n] = NULL; 46 if (dev->irqp[n]) { 47 *dev->irqp[n] = irq; 48 } 49 } 50 51 static void sysbus_mmio_map_common(SysBusDevice *dev, int n, hwaddr addr, 52 bool may_overlap, int priority) 53 { 54 assert(n >= 0 && n < dev->num_mmio); 55 56 if (dev->mmio[n].addr == addr) { 57 /* ??? region already mapped here. */ 58 return; 59 } 60 if (dev->mmio[n].addr != (hwaddr)-1) { 61 /* Unregister previous mapping. */ 62 memory_region_del_subregion(get_system_memory(), dev->mmio[n].memory); 63 } 64 dev->mmio[n].addr = addr; 65 if (may_overlap) { 66 memory_region_add_subregion_overlap(get_system_memory(), 67 addr, 68 dev->mmio[n].memory, 69 priority); 70 } 71 else { 72 memory_region_add_subregion(get_system_memory(), 73 addr, 74 dev->mmio[n].memory); 75 } 76 } 77 78 void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr) 79 { 80 sysbus_mmio_map_common(dev, n, addr, false, 0); 81 } 82 83 void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr, 84 int priority) 85 { 86 sysbus_mmio_map_common(dev, n, addr, true, priority); 87 } 88 89 /* Request an IRQ source. The actual IRQ object may be populated later. */ 90 void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p) 91 { 92 int n; 93 94 assert(dev->num_irq < QDEV_MAX_IRQ); 95 n = dev->num_irq++; 96 dev->irqp[n] = p; 97 } 98 99 /* Pass IRQs from a target device. */ 100 void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target) 101 { 102 int i; 103 assert(dev->num_irq == 0); 104 dev->num_irq = target->num_irq; 105 for (i = 0; i < dev->num_irq; i++) { 106 dev->irqp[i] = target->irqp[i]; 107 } 108 } 109 110 void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory) 111 { 112 int n; 113 114 assert(dev->num_mmio < QDEV_MAX_MMIO); 115 n = dev->num_mmio++; 116 dev->mmio[n].addr = -1; 117 dev->mmio[n].memory = memory; 118 } 119 120 MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n) 121 { 122 return dev->mmio[n].memory; 123 } 124 125 void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size) 126 { 127 pio_addr_t i; 128 129 for (i = 0; i < size; i++) { 130 assert(dev->num_pio < QDEV_MAX_PIO); 131 dev->pio[dev->num_pio++] = ioport++; 132 } 133 } 134 135 static int sysbus_device_init(DeviceState *dev) 136 { 137 SysBusDevice *sd = SYS_BUS_DEVICE(dev); 138 SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(sd); 139 140 if (!sbc->init) { 141 return 0; 142 } 143 return sbc->init(sd); 144 } 145 146 DeviceState *sysbus_create_varargs(const char *name, 147 hwaddr addr, ...) 148 { 149 DeviceState *dev; 150 SysBusDevice *s; 151 va_list va; 152 qemu_irq irq; 153 int n; 154 155 dev = qdev_create(NULL, name); 156 s = SYS_BUS_DEVICE(dev); 157 qdev_init_nofail(dev); 158 if (addr != (hwaddr)-1) { 159 sysbus_mmio_map(s, 0, addr); 160 } 161 va_start(va, addr); 162 n = 0; 163 while (1) { 164 irq = va_arg(va, qemu_irq); 165 if (!irq) { 166 break; 167 } 168 sysbus_connect_irq(s, n, irq); 169 n++; 170 } 171 va_end(va); 172 return dev; 173 } 174 175 DeviceState *sysbus_try_create_varargs(const char *name, 176 hwaddr addr, ...) 177 { 178 DeviceState *dev; 179 SysBusDevice *s; 180 va_list va; 181 qemu_irq irq; 182 int n; 183 184 dev = qdev_try_create(NULL, name); 185 if (!dev) { 186 return NULL; 187 } 188 s = SYS_BUS_DEVICE(dev); 189 qdev_init_nofail(dev); 190 if (addr != (hwaddr)-1) { 191 sysbus_mmio_map(s, 0, addr); 192 } 193 va_start(va, addr); 194 n = 0; 195 while (1) { 196 irq = va_arg(va, qemu_irq); 197 if (!irq) { 198 break; 199 } 200 sysbus_connect_irq(s, n, irq); 201 n++; 202 } 203 va_end(va); 204 return dev; 205 } 206 207 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent) 208 { 209 SysBusDevice *s = SYS_BUS_DEVICE(dev); 210 hwaddr size; 211 int i; 212 213 monitor_printf(mon, "%*sirq %d\n", indent, "", s->num_irq); 214 for (i = 0; i < s->num_mmio; i++) { 215 size = memory_region_size(s->mmio[i].memory); 216 monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n", 217 indent, "", s->mmio[i].addr, size); 218 } 219 } 220 221 static char *sysbus_get_fw_dev_path(DeviceState *dev) 222 { 223 SysBusDevice *s = SYS_BUS_DEVICE(dev); 224 char path[40]; 225 int off; 226 227 off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev)); 228 229 if (s->num_mmio) { 230 snprintf(path + off, sizeof(path) - off, "@"TARGET_FMT_plx, 231 s->mmio[0].addr); 232 } else if (s->num_pio) { 233 snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]); 234 } 235 236 return g_strdup(path); 237 } 238 239 void sysbus_add_io(SysBusDevice *dev, hwaddr addr, 240 MemoryRegion *mem) 241 { 242 memory_region_add_subregion(get_system_io(), addr, mem); 243 } 244 245 void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem) 246 { 247 memory_region_del_subregion(get_system_io(), mem); 248 } 249 250 MemoryRegion *sysbus_address_space(SysBusDevice *dev) 251 { 252 return get_system_memory(); 253 } 254 255 static void sysbus_device_class_init(ObjectClass *klass, void *data) 256 { 257 DeviceClass *k = DEVICE_CLASS(klass); 258 k->init = sysbus_device_init; 259 k->bus_type = TYPE_SYSTEM_BUS; 260 } 261 262 static const TypeInfo sysbus_device_type_info = { 263 .name = TYPE_SYS_BUS_DEVICE, 264 .parent = TYPE_DEVICE, 265 .instance_size = sizeof(SysBusDevice), 266 .abstract = true, 267 .class_size = sizeof(SysBusDeviceClass), 268 .class_init = sysbus_device_class_init, 269 }; 270 271 /* This is a nasty hack to allow passing a NULL bus to qdev_create. */ 272 static BusState *main_system_bus; 273 274 static void main_system_bus_create(void) 275 { 276 /* assign main_system_bus before qbus_create_inplace() 277 * in order to make "if (bus != sysbus_get_default())" work */ 278 main_system_bus = g_malloc0(system_bus_info.instance_size); 279 qbus_create_inplace(main_system_bus, system_bus_info.instance_size, 280 TYPE_SYSTEM_BUS, NULL, "main-system-bus"); 281 OBJECT(main_system_bus)->free = g_free; 282 object_property_add_child(container_get(qdev_get_machine(), 283 "/unattached"), 284 "sysbus", OBJECT(main_system_bus), NULL); 285 } 286 287 BusState *sysbus_get_default(void) 288 { 289 if (!main_system_bus) { 290 main_system_bus_create(); 291 } 292 return main_system_bus; 293 } 294 295 static void sysbus_register_types(void) 296 { 297 type_register_static(&system_bus_info); 298 type_register_static(&sysbus_device_type_info); 299 } 300 301 type_init(sysbus_register_types) 302