xref: /qemu/hw/isa/isa-bus.c (revision e995d5cce4a022afc4624471cafd2e4eb72962e6)
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.1 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 "qemu/osdep.h"
21  #include "qemu/error-report.h"
22  #include "qemu/module.h"
23  #include "qapi/error.h"
24  #include "hw/sysbus.h"
25  #include "sysemu/sysemu.h"
26  #include "hw/isa/isa.h"
27  
28  static ISABus *isabus;
29  
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->get_fw_dev_path = isabus_get_fw_dev_path;
37  }
38  
39  static const TypeInfo isa_dma_info = {
40      .name = TYPE_ISADMA,
41      .parent = TYPE_INTERFACE,
42      .class_size = sizeof(IsaDmaClass),
43  };
44  
45  static const TypeInfo isa_bus_info = {
46      .name = TYPE_ISA_BUS,
47      .parent = TYPE_BUS,
48      .instance_size = sizeof(ISABus),
49      .class_init = isa_bus_class_init,
50  };
51  
52  ISABus *isa_bus_new(DeviceState *dev, MemoryRegion* address_space,
53                      MemoryRegion *address_space_io, Error **errp)
54  {
55      if (isabus) {
56          error_setg(errp, "Can't create a second ISA bus");
57          return NULL;
58      }
59      if (!dev) {
60          dev = qdev_new("isabus-bridge");
61          sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
62      }
63  
64      isabus = ISA_BUS(qbus_new(TYPE_ISA_BUS, dev, NULL));
65      isabus->address_space = address_space;
66      isabus->address_space_io = address_space_io;
67      return isabus;
68  }
69  
70  void isa_bus_register_input_irqs(ISABus *bus, qemu_irq *irqs_in)
71  {
72      bus->irqs_in = irqs_in;
73  }
74  
75  qemu_irq isa_bus_get_irq(ISABus *bus, unsigned irqnum)
76  {
77      assert(irqnum < ISA_NUM_IRQS);
78      assert(bus->irqs_in);
79      return bus->irqs_in[irqnum];
80  }
81  
82  /*
83   * isa_get_irq() returns the corresponding input qemu_irq entry for the i8259.
84   *
85   * This function is only for special cases such as the 'ferr', and
86   * temporary use for normal devices until they are converted to qdev.
87   */
88  qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq)
89  {
90      assert(!dev || ISA_BUS(qdev_get_parent_bus(DEVICE(dev))) == isabus);
91      return isa_bus_get_irq(isabus, isairq);
92  }
93  
94  void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, unsigned isairq)
95  {
96      qemu_irq input_irq = isa_get_irq(isadev, isairq);
97      qdev_connect_gpio_out(DEVICE(isadev), gpioirq, input_irq);
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_bus_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(isa_address_space_io(dev), start, io);
124      isa_init_ioport(dev, start);
125  }
126  
127  int isa_register_portio_list(ISADevice *dev,
128                               PortioList *piolist, uint16_t start,
129                               const MemoryRegionPortio *pio_start,
130                               void *opaque, const char *name)
131  {
132      assert(piolist && !piolist->owner);
133  
134      if (!isabus) {
135          return -ENODEV;
136      }
137  
138      /* START is how we should treat DEV, regardless of the actual
139         contents of the portio array.  This is how the old code
140         actually handled e.g. the FDC device.  */
141      isa_init_ioport(dev, start);
142  
143      portio_list_init(piolist, OBJECT(dev), pio_start, opaque, name);
144      portio_list_add(piolist, isa_address_space_io(dev), start);
145  
146      return 0;
147  }
148  
149  ISADevice *isa_new(const char *name)
150  {
151      return ISA_DEVICE(qdev_new(name));
152  }
153  
154  ISADevice *isa_try_new(const char *name)
155  {
156      return ISA_DEVICE(qdev_try_new(name));
157  }
158  
159  ISADevice *isa_create_simple(ISABus *bus, const char *name)
160  {
161      ISADevice *dev;
162  
163      dev = isa_new(name);
164      isa_realize_and_unref(dev, bus, &error_fatal);
165      return dev;
166  }
167  
168  bool isa_realize_and_unref(ISADevice *dev, ISABus *bus, Error **errp)
169  {
170      return qdev_realize_and_unref(&dev->parent_obj, &bus->parent_obj, errp);
171  }
172  
173  ISABus *isa_bus_from_device(ISADevice *dev)
174  {
175      return ISA_BUS(qdev_get_parent_bus(DEVICE(dev)));
176  }
177  
178  ISADevice *isa_vga_init(ISABus *bus)
179  {
180      vga_interface_created = true;
181      switch (vga_interface_type) {
182      case VGA_CIRRUS:
183          return isa_create_simple(bus, "isa-cirrus-vga");
184      case VGA_QXL:
185          error_report("%s: qxl: no PCI bus", __func__);
186          return NULL;
187      case VGA_STD:
188          return isa_create_simple(bus, "isa-vga");
189      case VGA_VMWARE:
190          error_report("%s: vmware_vga: no PCI bus", __func__);
191          return NULL;
192      case VGA_VIRTIO:
193          error_report("%s: virtio-vga: no PCI bus", __func__);
194          return NULL;
195      case VGA_NONE:
196      default:
197          return NULL;
198      }
199  }
200  
201  static void isabus_bridge_class_init(ObjectClass *klass, void *data)
202  {
203      DeviceClass *dc = DEVICE_CLASS(klass);
204  
205      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
206      dc->fw_name = "isa";
207  }
208  
209  static const TypeInfo isabus_bridge_info = {
210      .name          = "isabus-bridge",
211      .parent        = TYPE_SYS_BUS_DEVICE,
212      .instance_size = sizeof(SysBusDevice),
213      .class_init    = isabus_bridge_class_init,
214  };
215  
216  static void isa_device_class_init(ObjectClass *klass, void *data)
217  {
218      DeviceClass *k = DEVICE_CLASS(klass);
219      k->bus_type = TYPE_ISA_BUS;
220  }
221  
222  static const TypeInfo isa_device_type_info = {
223      .name = TYPE_ISA_DEVICE,
224      .parent = TYPE_DEVICE,
225      .instance_size = sizeof(ISADevice),
226      .abstract = true,
227      .class_init = isa_device_class_init,
228  };
229  
230  static void isabus_register_types(void)
231  {
232      type_register_static(&isa_dma_info);
233      type_register_static(&isa_bus_info);
234      type_register_static(&isabus_bridge_info);
235      type_register_static(&isa_device_type_info);
236  }
237  
238  static char *isabus_get_fw_dev_path(DeviceState *dev)
239  {
240      ISADevice *d = ISA_DEVICE(dev);
241      char path[40];
242      int off;
243  
244      off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
245      if (d->ioport_id) {
246          snprintf(path + off, sizeof(path) - off, "@%04x", d->ioport_id);
247      }
248  
249      return g_strdup(path);
250  }
251  
252  MemoryRegion *isa_address_space(ISADevice *dev)
253  {
254      if (dev) {
255          return isa_bus_from_device(dev)->address_space;
256      }
257  
258      return isabus->address_space;
259  }
260  
261  MemoryRegion *isa_address_space_io(ISADevice *dev)
262  {
263      if (dev) {
264          return isa_bus_from_device(dev)->address_space_io;
265      }
266  
267      return isabus->address_space_io;
268  }
269  
270  type_init(isabus_register_types)
271