149ab747fSPaolo Bonzini /*
249ab747fSPaolo Bonzini * isa bus support for qdev.
349ab747fSPaolo Bonzini *
449ab747fSPaolo Bonzini * Copyright (c) 2009 Gerd Hoffmann <kraxel@redhat.com>
549ab747fSPaolo Bonzini *
649ab747fSPaolo Bonzini * This library is free software; you can redistribute it and/or
749ab747fSPaolo Bonzini * modify it under the terms of the GNU Lesser General Public
849ab747fSPaolo Bonzini * License as published by the Free Software Foundation; either
961f3c91aSChetan Pant * version 2.1 of the License, or (at your option) any later version.
1049ab747fSPaolo Bonzini *
1149ab747fSPaolo Bonzini * This library is distributed in the hope that it will be useful,
1249ab747fSPaolo Bonzini * but WITHOUT ANY WARRANTY; without even the implied warranty of
1349ab747fSPaolo Bonzini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1449ab747fSPaolo Bonzini * Lesser General Public License for more details.
1549ab747fSPaolo Bonzini *
1649ab747fSPaolo Bonzini * You should have received a copy of the GNU Lesser General Public
1749ab747fSPaolo Bonzini * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1849ab747fSPaolo Bonzini */
190b8fa32fSMarkus Armbruster
200430891cSPeter Maydell #include "qemu/osdep.h"
211081ed2cSAlistair Francis #include "qemu/error-report.h"
220b8fa32fSMarkus Armbruster #include "qemu/module.h"
23da34e65cSMarkus Armbruster #include "qapi/error.h"
2449ab747fSPaolo Bonzini #include "hw/sysbus.h"
2549ab747fSPaolo Bonzini #include "sysemu/sysemu.h"
2649ab747fSPaolo Bonzini #include "hw/isa/isa.h"
2749ab747fSPaolo Bonzini
2849ab747fSPaolo Bonzini static ISABus *isabus;
2949ab747fSPaolo Bonzini
3049ab747fSPaolo Bonzini static char *isabus_get_fw_dev_path(DeviceState *dev);
3149ab747fSPaolo Bonzini
isa_bus_class_init(ObjectClass * klass,void * data)3249ab747fSPaolo Bonzini static void isa_bus_class_init(ObjectClass *klass, void *data)
3349ab747fSPaolo Bonzini {
3449ab747fSPaolo Bonzini BusClass *k = BUS_CLASS(klass);
3549ab747fSPaolo Bonzini
3649ab747fSPaolo Bonzini k->get_fw_dev_path = isabus_get_fw_dev_path;
3749ab747fSPaolo Bonzini }
3849ab747fSPaolo Bonzini
395484f30bSHervé Poussineau static const TypeInfo isa_dma_info = {
405484f30bSHervé Poussineau .name = TYPE_ISADMA,
415484f30bSHervé Poussineau .parent = TYPE_INTERFACE,
425484f30bSHervé Poussineau .class_size = sizeof(IsaDmaClass),
435484f30bSHervé Poussineau };
445484f30bSHervé Poussineau
4549ab747fSPaolo Bonzini static const TypeInfo isa_bus_info = {
4649ab747fSPaolo Bonzini .name = TYPE_ISA_BUS,
4749ab747fSPaolo Bonzini .parent = TYPE_BUS,
4849ab747fSPaolo Bonzini .instance_size = sizeof(ISABus),
4949ab747fSPaolo Bonzini .class_init = isa_bus_class_init,
5049ab747fSPaolo Bonzini };
5149ab747fSPaolo Bonzini
isa_bus_new(DeviceState * dev,MemoryRegion * address_space,MemoryRegion * address_space_io,Error ** errp)52bb2ed009SHervé Poussineau ISABus *isa_bus_new(DeviceState *dev, MemoryRegion* address_space,
53d10e5432SMarkus Armbruster MemoryRegion *address_space_io, Error **errp)
5449ab747fSPaolo Bonzini {
55*675d717bSPhilippe Mathieu-Daudé DeviceState *bridge = NULL;
56*675d717bSPhilippe Mathieu-Daudé
5749ab747fSPaolo Bonzini if (isabus) {
58d10e5432SMarkus Armbruster error_setg(errp, "Can't create a second ISA bus");
5949ab747fSPaolo Bonzini return NULL;
6049ab747fSPaolo Bonzini }
61337a3e5cSGonglei if (!dev) {
62*675d717bSPhilippe Mathieu-Daudé bridge = qdev_new("isabus-bridge");
63*675d717bSPhilippe Mathieu-Daudé dev = bridge;
6449ab747fSPaolo Bonzini }
6549ab747fSPaolo Bonzini
669388d170SPeter Maydell isabus = ISA_BUS(qbus_new(TYPE_ISA_BUS, dev, NULL));
67bb2ed009SHervé Poussineau isabus->address_space = address_space;
6849ab747fSPaolo Bonzini isabus->address_space_io = address_space_io;
69*675d717bSPhilippe Mathieu-Daudé
70*675d717bSPhilippe Mathieu-Daudé if (bridge) {
71*675d717bSPhilippe Mathieu-Daudé sysbus_realize_and_unref(SYS_BUS_DEVICE(bridge), &error_fatal);
72*675d717bSPhilippe Mathieu-Daudé }
73*675d717bSPhilippe Mathieu-Daudé
7449ab747fSPaolo Bonzini return isabus;
7549ab747fSPaolo Bonzini }
7649ab747fSPaolo Bonzini
isa_bus_register_input_irqs(ISABus * bus,qemu_irq * irqs_in)777067887eSPhilippe Mathieu-Daudé void isa_bus_register_input_irqs(ISABus *bus, qemu_irq *irqs_in)
7849ab747fSPaolo Bonzini {
797067887eSPhilippe Mathieu-Daudé bus->irqs_in = irqs_in;
8049ab747fSPaolo Bonzini }
8149ab747fSPaolo Bonzini
isa_bus_get_irq(ISABus * bus,unsigned irqnum)82d2fbec57SPhilippe Mathieu-Daudé qemu_irq isa_bus_get_irq(ISABus *bus, unsigned irqnum)
83d2fbec57SPhilippe Mathieu-Daudé {
84d2fbec57SPhilippe Mathieu-Daudé assert(irqnum < ISA_NUM_IRQS);
85d2fbec57SPhilippe Mathieu-Daudé assert(bus->irqs_in);
86d2fbec57SPhilippe Mathieu-Daudé return bus->irqs_in[irqnum];
87d2fbec57SPhilippe Mathieu-Daudé }
88d2fbec57SPhilippe Mathieu-Daudé
8949ab747fSPaolo Bonzini /*
907067887eSPhilippe Mathieu-Daudé * isa_get_irq() returns the corresponding input qemu_irq entry for the i8259.
9149ab747fSPaolo Bonzini *
9249ab747fSPaolo Bonzini * This function is only for special cases such as the 'ferr', and
9349ab747fSPaolo Bonzini * temporary use for normal devices until they are converted to qdev.
9449ab747fSPaolo Bonzini */
isa_get_irq(ISADevice * dev,unsigned isairq)953c29e188SPaolo Bonzini qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq)
9649ab747fSPaolo Bonzini {
972ae0e48dSAndreas Färber assert(!dev || ISA_BUS(qdev_get_parent_bus(DEVICE(dev))) == isabus);
98d2fbec57SPhilippe Mathieu-Daudé return isa_bus_get_irq(isabus, isairq);
9949ab747fSPaolo Bonzini }
10049ab747fSPaolo Bonzini
isa_connect_gpio_out(ISADevice * isadev,int gpioirq,unsigned isairq)1013c29e188SPaolo Bonzini void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, unsigned isairq)
10225026303SEfimov Vasily {
103d2fbec57SPhilippe Mathieu-Daudé qemu_irq input_irq = isa_get_irq(isadev, isairq);
104d2fbec57SPhilippe Mathieu-Daudé qdev_connect_gpio_out(DEVICE(isadev), gpioirq, input_irq);
10525026303SEfimov Vasily }
10625026303SEfimov Vasily
isa_bus_dma(ISABus * bus,IsaDma * dma8,IsaDma * dma16)1075484f30bSHervé Poussineau void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16)
1085484f30bSHervé Poussineau {
1095484f30bSHervé Poussineau assert(bus && dma8 && dma16);
1105484f30bSHervé Poussineau assert(!bus->dma[0] && !bus->dma[1]);
1115484f30bSHervé Poussineau bus->dma[0] = dma8;
1125484f30bSHervé Poussineau bus->dma[1] = dma16;
1135484f30bSHervé Poussineau }
1145484f30bSHervé Poussineau
isa_bus_get_dma(ISABus * bus,int nchan)115dc8d6cf2SPhilippe Mathieu-Daudé IsaDma *isa_bus_get_dma(ISABus *bus, int nchan)
1165484f30bSHervé Poussineau {
1175484f30bSHervé Poussineau assert(bus);
1185484f30bSHervé Poussineau return bus->dma[nchan > 3 ? 1 : 0];
1195484f30bSHervé Poussineau }
1205484f30bSHervé Poussineau
isa_init_ioport(ISADevice * dev,uint16_t ioport)12149ab747fSPaolo Bonzini static inline void isa_init_ioport(ISADevice *dev, uint16_t ioport)
12249ab747fSPaolo Bonzini {
12349ab747fSPaolo Bonzini if (dev && (dev->ioport_id == 0 || ioport < dev->ioport_id)) {
12449ab747fSPaolo Bonzini dev->ioport_id = ioport;
12549ab747fSPaolo Bonzini }
12649ab747fSPaolo Bonzini }
12749ab747fSPaolo Bonzini
isa_register_ioport(ISADevice * dev,MemoryRegion * io,uint16_t start)12849ab747fSPaolo Bonzini void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start)
12949ab747fSPaolo Bonzini {
130e5bf2779SPhilippe Mathieu-Daudé memory_region_add_subregion(isa_address_space_io(dev), start, io);
13149ab747fSPaolo Bonzini isa_init_ioport(dev, start);
13249ab747fSPaolo Bonzini }
13349ab747fSPaolo Bonzini
isa_register_portio_list(ISADevice * dev,PortioList * piolist,uint16_t start,const MemoryRegionPortio * pio_start,void * opaque,const char * name)1349405d87bSThomas Huth int isa_register_portio_list(ISADevice *dev,
135e305a165SMarc-André Lureau PortioList *piolist, uint16_t start,
13649ab747fSPaolo Bonzini const MemoryRegionPortio *pio_start,
13749ab747fSPaolo Bonzini void *opaque, const char *name)
13849ab747fSPaolo Bonzini {
139e305a165SMarc-André Lureau assert(piolist && !piolist->owner);
14049ab747fSPaolo Bonzini
1419405d87bSThomas Huth if (!isabus) {
1429405d87bSThomas Huth return -ENODEV;
1439405d87bSThomas Huth }
1449405d87bSThomas Huth
14549ab747fSPaolo Bonzini /* START is how we should treat DEV, regardless of the actual
14649ab747fSPaolo Bonzini contents of the portio array. This is how the old code
14749ab747fSPaolo Bonzini actually handled e.g. the FDC device. */
14849ab747fSPaolo Bonzini isa_init_ioport(dev, start);
14949ab747fSPaolo Bonzini
150e305a165SMarc-André Lureau portio_list_init(piolist, OBJECT(dev), pio_start, opaque, name);
151e5bf2779SPhilippe Mathieu-Daudé portio_list_add(piolist, isa_address_space_io(dev), start);
1529405d87bSThomas Huth
1539405d87bSThomas Huth return 0;
15449ab747fSPaolo Bonzini }
15549ab747fSPaolo Bonzini
isa_new(const char * name)1560fe9d901SMarkus Armbruster ISADevice *isa_new(const char *name)
1570fe9d901SMarkus Armbruster {
1580fe9d901SMarkus Armbruster return ISA_DEVICE(qdev_new(name));
1590fe9d901SMarkus Armbruster }
1600fe9d901SMarkus Armbruster
isa_try_new(const char * name)1610fe9d901SMarkus Armbruster ISADevice *isa_try_new(const char *name)
1620fe9d901SMarkus Armbruster {
1630fe9d901SMarkus Armbruster return ISA_DEVICE(qdev_try_new(name));
1640fe9d901SMarkus Armbruster }
1650fe9d901SMarkus Armbruster
isa_create_simple(ISABus * bus,const char * name)16649ab747fSPaolo Bonzini ISADevice *isa_create_simple(ISABus *bus, const char *name)
16749ab747fSPaolo Bonzini {
16849ab747fSPaolo Bonzini ISADevice *dev;
16949ab747fSPaolo Bonzini
17096927c74SMarkus Armbruster dev = isa_new(name);
17196927c74SMarkus Armbruster isa_realize_and_unref(dev, bus, &error_fatal);
17249ab747fSPaolo Bonzini return dev;
17349ab747fSPaolo Bonzini }
17449ab747fSPaolo Bonzini
isa_realize_and_unref(ISADevice * dev,ISABus * bus,Error ** errp)1750fe9d901SMarkus Armbruster bool isa_realize_and_unref(ISADevice *dev, ISABus *bus, Error **errp)
1760fe9d901SMarkus Armbruster {
1770fe9d901SMarkus Armbruster return qdev_realize_and_unref(&dev->parent_obj, &bus->parent_obj, errp);
1780fe9d901SMarkus Armbruster }
1790fe9d901SMarkus Armbruster
isa_bus_from_device(ISADevice * dev)18023c69bb8SPhilippe Mathieu-Daudé ISABus *isa_bus_from_device(ISADevice *dev)
18123c69bb8SPhilippe Mathieu-Daudé {
18223c69bb8SPhilippe Mathieu-Daudé return ISA_BUS(qdev_get_parent_bus(DEVICE(dev)));
18323c69bb8SPhilippe Mathieu-Daudé }
18423c69bb8SPhilippe Mathieu-Daudé
isa_vga_init(ISABus * bus)18549ab747fSPaolo Bonzini ISADevice *isa_vga_init(ISABus *bus)
18649ab747fSPaolo Bonzini {
187f9bcb2d6SGautam Agrawal vga_interface_created = true;
18849ab747fSPaolo Bonzini switch (vga_interface_type) {
18949ab747fSPaolo Bonzini case VGA_CIRRUS:
19049ab747fSPaolo Bonzini return isa_create_simple(bus, "isa-cirrus-vga");
19149ab747fSPaolo Bonzini case VGA_QXL:
1921081ed2cSAlistair Francis error_report("%s: qxl: no PCI bus", __func__);
19349ab747fSPaolo Bonzini return NULL;
19449ab747fSPaolo Bonzini case VGA_STD:
19549ab747fSPaolo Bonzini return isa_create_simple(bus, "isa-vga");
19649ab747fSPaolo Bonzini case VGA_VMWARE:
1971081ed2cSAlistair Francis error_report("%s: vmware_vga: no PCI bus", __func__);
19849ab747fSPaolo Bonzini return NULL;
199a94f0c5cSGerd Hoffmann case VGA_VIRTIO:
2001081ed2cSAlistair Francis error_report("%s: virtio-vga: no PCI bus", __func__);
201a94f0c5cSGerd Hoffmann return NULL;
20249ab747fSPaolo Bonzini case VGA_NONE:
20349ab747fSPaolo Bonzini default:
20449ab747fSPaolo Bonzini return NULL;
20549ab747fSPaolo Bonzini }
20649ab747fSPaolo Bonzini }
20749ab747fSPaolo Bonzini
isabus_bridge_class_init(ObjectClass * klass,void * data)20849ab747fSPaolo Bonzini static void isabus_bridge_class_init(ObjectClass *klass, void *data)
20949ab747fSPaolo Bonzini {
21049ab747fSPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass);
21149ab747fSPaolo Bonzini
2125658ffa3SThomas Huth set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
21349ab747fSPaolo Bonzini dc->fw_name = "isa";
21449ab747fSPaolo Bonzini }
21549ab747fSPaolo Bonzini
21649ab747fSPaolo Bonzini static const TypeInfo isabus_bridge_info = {
21749ab747fSPaolo Bonzini .name = "isabus-bridge",
21849ab747fSPaolo Bonzini .parent = TYPE_SYS_BUS_DEVICE,
21949ab747fSPaolo Bonzini .instance_size = sizeof(SysBusDevice),
22049ab747fSPaolo Bonzini .class_init = isabus_bridge_class_init,
22149ab747fSPaolo Bonzini };
22249ab747fSPaolo Bonzini
isa_device_class_init(ObjectClass * klass,void * data)22349ab747fSPaolo Bonzini static void isa_device_class_init(ObjectClass *klass, void *data)
22449ab747fSPaolo Bonzini {
22549ab747fSPaolo Bonzini DeviceClass *k = DEVICE_CLASS(klass);
22649ab747fSPaolo Bonzini k->bus_type = TYPE_ISA_BUS;
22749ab747fSPaolo Bonzini }
22849ab747fSPaolo Bonzini
22949ab747fSPaolo Bonzini static const TypeInfo isa_device_type_info = {
23049ab747fSPaolo Bonzini .name = TYPE_ISA_DEVICE,
23149ab747fSPaolo Bonzini .parent = TYPE_DEVICE,
23249ab747fSPaolo Bonzini .instance_size = sizeof(ISADevice),
23349ab747fSPaolo Bonzini .abstract = true,
23449ab747fSPaolo Bonzini .class_init = isa_device_class_init,
23549ab747fSPaolo Bonzini };
23649ab747fSPaolo Bonzini
isabus_register_types(void)23749ab747fSPaolo Bonzini static void isabus_register_types(void)
23849ab747fSPaolo Bonzini {
2395484f30bSHervé Poussineau type_register_static(&isa_dma_info);
24049ab747fSPaolo Bonzini type_register_static(&isa_bus_info);
24149ab747fSPaolo Bonzini type_register_static(&isabus_bridge_info);
24249ab747fSPaolo Bonzini type_register_static(&isa_device_type_info);
24349ab747fSPaolo Bonzini }
24449ab747fSPaolo Bonzini
isabus_get_fw_dev_path(DeviceState * dev)24549ab747fSPaolo Bonzini static char *isabus_get_fw_dev_path(DeviceState *dev)
24649ab747fSPaolo Bonzini {
2474a17cc4fSAndreas Färber ISADevice *d = ISA_DEVICE(dev);
24849ab747fSPaolo Bonzini char path[40];
24949ab747fSPaolo Bonzini int off;
25049ab747fSPaolo Bonzini
25149ab747fSPaolo Bonzini off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
25249ab747fSPaolo Bonzini if (d->ioport_id) {
25349ab747fSPaolo Bonzini snprintf(path + off, sizeof(path) - off, "@%04x", d->ioport_id);
25449ab747fSPaolo Bonzini }
25549ab747fSPaolo Bonzini
25649ab747fSPaolo Bonzini return g_strdup(path);
25749ab747fSPaolo Bonzini }
25849ab747fSPaolo Bonzini
isa_address_space(ISADevice * dev)25949ab747fSPaolo Bonzini MemoryRegion *isa_address_space(ISADevice *dev)
26049ab747fSPaolo Bonzini {
261bb2ed009SHervé Poussineau if (dev) {
262bb2ed009SHervé Poussineau return isa_bus_from_device(dev)->address_space;
263bb2ed009SHervé Poussineau }
264bb2ed009SHervé Poussineau
265bb2ed009SHervé Poussineau return isabus->address_space;
26649ab747fSPaolo Bonzini }
26749ab747fSPaolo Bonzini
isa_address_space_io(ISADevice * dev)26849ab747fSPaolo Bonzini MemoryRegion *isa_address_space_io(ISADevice *dev)
26949ab747fSPaolo Bonzini {
27049ab747fSPaolo Bonzini if (dev) {
27149ab747fSPaolo Bonzini return isa_bus_from_device(dev)->address_space_io;
27249ab747fSPaolo Bonzini }
27349ab747fSPaolo Bonzini
27449ab747fSPaolo Bonzini return isabus->address_space_io;
27549ab747fSPaolo Bonzini }
27649ab747fSPaolo Bonzini
27749ab747fSPaolo Bonzini type_init(isabus_register_types)
278