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