1 /* 2 * isa bus support for qdev. 3 * 4 * Copyright (c) 2009 Gerd Hoffmann <kraxel@redhat.com> 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 #include "qemu/osdep.h" 20 #include "hw/hw.h" 21 #include "monitor/monitor.h" 22 #include "hw/sysbus.h" 23 #include "sysemu/sysemu.h" 24 #include "hw/isa/isa.h" 25 #include "hw/i386/pc.h" 26 27 static ISABus *isabus; 28 29 static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent); 30 static char *isabus_get_fw_dev_path(DeviceState *dev); 31 32 static void isa_bus_class_init(ObjectClass *klass, void *data) 33 { 34 BusClass *k = BUS_CLASS(klass); 35 36 k->print_dev = isabus_dev_print; 37 k->get_fw_dev_path = isabus_get_fw_dev_path; 38 } 39 40 static const TypeInfo isa_bus_info = { 41 .name = TYPE_ISA_BUS, 42 .parent = TYPE_BUS, 43 .instance_size = sizeof(ISABus), 44 .class_init = isa_bus_class_init, 45 }; 46 47 ISABus *isa_bus_new(DeviceState *dev, MemoryRegion* address_space, 48 MemoryRegion *address_space_io, Error **errp) 49 { 50 if (isabus) { 51 error_setg(errp, "Can't create a second ISA bus"); 52 return NULL; 53 } 54 if (!dev) { 55 dev = qdev_create(NULL, "isabus-bridge"); 56 qdev_init_nofail(dev); 57 } 58 59 isabus = ISA_BUS(qbus_create(TYPE_ISA_BUS, dev, NULL)); 60 isabus->address_space = address_space; 61 isabus->address_space_io = address_space_io; 62 return isabus; 63 } 64 65 void isa_bus_irqs(ISABus *bus, qemu_irq *irqs) 66 { 67 bus->irqs = irqs; 68 } 69 70 /* 71 * isa_get_irq() returns the corresponding qemu_irq entry for the i8259. 72 * 73 * This function is only for special cases such as the 'ferr', and 74 * temporary use for normal devices until they are converted to qdev. 75 */ 76 qemu_irq isa_get_irq(ISADevice *dev, int isairq) 77 { 78 assert(!dev || ISA_BUS(qdev_get_parent_bus(DEVICE(dev))) == isabus); 79 if (isairq < 0 || isairq > 15) { 80 hw_error("isa irq %d invalid", isairq); 81 } 82 return isabus->irqs[isairq]; 83 } 84 85 void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq) 86 { 87 assert(dev->nirqs < ARRAY_SIZE(dev->isairq)); 88 dev->isairq[dev->nirqs] = isairq; 89 *p = isa_get_irq(dev, isairq); 90 dev->nirqs++; 91 } 92 93 static inline void isa_init_ioport(ISADevice *dev, uint16_t ioport) 94 { 95 if (dev && (dev->ioport_id == 0 || ioport < dev->ioport_id)) { 96 dev->ioport_id = ioport; 97 } 98 } 99 100 void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start) 101 { 102 memory_region_add_subregion(isabus->address_space_io, start, io); 103 isa_init_ioport(dev, start); 104 } 105 106 void isa_register_portio_list(ISADevice *dev, uint16_t start, 107 const MemoryRegionPortio *pio_start, 108 void *opaque, const char *name) 109 { 110 PortioList piolist; 111 112 /* START is how we should treat DEV, regardless of the actual 113 contents of the portio array. This is how the old code 114 actually handled e.g. the FDC device. */ 115 isa_init_ioport(dev, start); 116 117 /* FIXME: the device should store created PortioList in its state. Note 118 that DEV can be NULL here and that single device can register several 119 portio lists. Current implementation is leaking memory allocated 120 in portio_list_init. The leak is not critical because it happens only 121 at initialization time. */ 122 portio_list_init(&piolist, OBJECT(dev), pio_start, opaque, name); 123 portio_list_add(&piolist, isabus->address_space_io, start); 124 } 125 126 static void isa_device_init(Object *obj) 127 { 128 ISADevice *dev = ISA_DEVICE(obj); 129 130 dev->isairq[0] = -1; 131 dev->isairq[1] = -1; 132 } 133 134 ISADevice *isa_create(ISABus *bus, const char *name) 135 { 136 DeviceState *dev; 137 138 dev = qdev_create(BUS(bus), name); 139 return ISA_DEVICE(dev); 140 } 141 142 ISADevice *isa_try_create(ISABus *bus, const char *name) 143 { 144 DeviceState *dev; 145 146 dev = qdev_try_create(BUS(bus), name); 147 return ISA_DEVICE(dev); 148 } 149 150 ISADevice *isa_create_simple(ISABus *bus, const char *name) 151 { 152 ISADevice *dev; 153 154 dev = isa_create(bus, name); 155 qdev_init_nofail(DEVICE(dev)); 156 return dev; 157 } 158 159 ISADevice *isa_vga_init(ISABus *bus) 160 { 161 switch (vga_interface_type) { 162 case VGA_CIRRUS: 163 return isa_create_simple(bus, "isa-cirrus-vga"); 164 case VGA_QXL: 165 fprintf(stderr, "%s: qxl: no PCI bus\n", __func__); 166 return NULL; 167 case VGA_STD: 168 return isa_create_simple(bus, "isa-vga"); 169 case VGA_VMWARE: 170 fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __func__); 171 return NULL; 172 case VGA_VIRTIO: 173 fprintf(stderr, "%s: virtio-vga: no PCI bus\n", __func__); 174 return NULL; 175 case VGA_NONE: 176 default: 177 return NULL; 178 } 179 } 180 181 static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent) 182 { 183 ISADevice *d = ISA_DEVICE(dev); 184 185 if (d->isairq[1] != -1) { 186 monitor_printf(mon, "%*sisa irqs %d,%d\n", indent, "", 187 d->isairq[0], d->isairq[1]); 188 } else if (d->isairq[0] != -1) { 189 monitor_printf(mon, "%*sisa irq %d\n", indent, "", 190 d->isairq[0]); 191 } 192 } 193 194 static void isabus_bridge_class_init(ObjectClass *klass, void *data) 195 { 196 DeviceClass *dc = DEVICE_CLASS(klass); 197 198 dc->fw_name = "isa"; 199 } 200 201 static const TypeInfo isabus_bridge_info = { 202 .name = "isabus-bridge", 203 .parent = TYPE_SYS_BUS_DEVICE, 204 .instance_size = sizeof(SysBusDevice), 205 .class_init = isabus_bridge_class_init, 206 }; 207 208 static void isa_device_class_init(ObjectClass *klass, void *data) 209 { 210 DeviceClass *k = DEVICE_CLASS(klass); 211 k->bus_type = TYPE_ISA_BUS; 212 } 213 214 static const TypeInfo isa_device_type_info = { 215 .name = TYPE_ISA_DEVICE, 216 .parent = TYPE_DEVICE, 217 .instance_size = sizeof(ISADevice), 218 .instance_init = isa_device_init, 219 .abstract = true, 220 .class_size = sizeof(ISADeviceClass), 221 .class_init = isa_device_class_init, 222 }; 223 224 static void isabus_register_types(void) 225 { 226 type_register_static(&isa_bus_info); 227 type_register_static(&isabus_bridge_info); 228 type_register_static(&isa_device_type_info); 229 } 230 231 static char *isabus_get_fw_dev_path(DeviceState *dev) 232 { 233 ISADevice *d = ISA_DEVICE(dev); 234 char path[40]; 235 int off; 236 237 off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev)); 238 if (d->ioport_id) { 239 snprintf(path + off, sizeof(path) - off, "@%04x", d->ioport_id); 240 } 241 242 return g_strdup(path); 243 } 244 245 MemoryRegion *isa_address_space(ISADevice *dev) 246 { 247 if (dev) { 248 return isa_bus_from_device(dev)->address_space; 249 } 250 251 return isabus->address_space; 252 } 253 254 MemoryRegion *isa_address_space_io(ISADevice *dev) 255 { 256 if (dev) { 257 return isa_bus_from_device(dev)->address_space_io; 258 } 259 260 return isabus->address_space_io; 261 } 262 263 type_init(isabus_register_types) 264 265 static void parallel_init(ISABus *bus, int index, CharDriverState *chr) 266 { 267 DeviceState *dev; 268 ISADevice *isadev; 269 270 isadev = isa_create(bus, "isa-parallel"); 271 dev = DEVICE(isadev); 272 qdev_prop_set_uint32(dev, "index", index); 273 qdev_prop_set_chr(dev, "chardev", chr); 274 qdev_init_nofail(dev); 275 } 276 277 void parallel_hds_isa_init(ISABus *bus, int n) 278 { 279 int i; 280 281 assert(n <= MAX_PARALLEL_PORTS); 282 283 for (i = 0; i < n; i++) { 284 if (parallel_hds[i]) { 285 parallel_init(bus, i, parallel_hds[i]); 286 } 287 } 288 } 289