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