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