xref: /qemu/hw/isa/isa-bus.c (revision bf8d4924)
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_connect_gpio_out(ISADevice *isadev, int gpioirq, int isairq)
101 {
102     qemu_irq irq;
103     isa_init_irq(isadev, &irq, isairq);
104     qdev_connect_gpio_out(DEVICE(isadev), gpioirq, irq);
105 }
106 
107 void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16)
108 {
109     assert(bus && dma8 && dma16);
110     assert(!bus->dma[0] && !bus->dma[1]);
111     bus->dma[0] = dma8;
112     bus->dma[1] = dma16;
113 }
114 
115 IsaDma *isa_get_dma(ISABus *bus, int nchan)
116 {
117     assert(bus);
118     return bus->dma[nchan > 3 ? 1 : 0];
119 }
120 
121 static inline void isa_init_ioport(ISADevice *dev, uint16_t ioport)
122 {
123     if (dev && (dev->ioport_id == 0 || ioport < dev->ioport_id)) {
124         dev->ioport_id = ioport;
125     }
126 }
127 
128 void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start)
129 {
130     memory_region_add_subregion(isabus->address_space_io, start, io);
131     isa_init_ioport(dev, start);
132 }
133 
134 void isa_register_portio_list(ISADevice *dev, uint16_t start,
135                               const MemoryRegionPortio *pio_start,
136                               void *opaque, const char *name)
137 {
138     PortioList piolist;
139 
140     /* START is how we should treat DEV, regardless of the actual
141        contents of the portio array.  This is how the old code
142        actually handled e.g. the FDC device.  */
143     isa_init_ioport(dev, start);
144 
145     /* FIXME: the device should store created PortioList in its state.  Note
146        that DEV can be NULL here and that single device can register several
147        portio lists.  Current implementation is leaking memory allocated
148        in portio_list_init.  The leak is not critical because it happens only
149        at initialization time.  */
150     portio_list_init(&piolist, OBJECT(dev), pio_start, opaque, name);
151     portio_list_add(&piolist, isabus->address_space_io, start);
152 }
153 
154 static void isa_device_init(Object *obj)
155 {
156     ISADevice *dev = ISA_DEVICE(obj);
157 
158     dev->isairq[0] = -1;
159     dev->isairq[1] = -1;
160 }
161 
162 ISADevice *isa_create(ISABus *bus, const char *name)
163 {
164     DeviceState *dev;
165 
166     dev = qdev_create(BUS(bus), name);
167     return ISA_DEVICE(dev);
168 }
169 
170 ISADevice *isa_try_create(ISABus *bus, const char *name)
171 {
172     DeviceState *dev;
173 
174     dev = qdev_try_create(BUS(bus), name);
175     return ISA_DEVICE(dev);
176 }
177 
178 ISADevice *isa_create_simple(ISABus *bus, const char *name)
179 {
180     ISADevice *dev;
181 
182     dev = isa_create(bus, name);
183     qdev_init_nofail(DEVICE(dev));
184     return dev;
185 }
186 
187 ISADevice *isa_vga_init(ISABus *bus)
188 {
189     switch (vga_interface_type) {
190     case VGA_CIRRUS:
191         return isa_create_simple(bus, "isa-cirrus-vga");
192     case VGA_QXL:
193         fprintf(stderr, "%s: qxl: no PCI bus\n", __func__);
194         return NULL;
195     case VGA_STD:
196         return isa_create_simple(bus, "isa-vga");
197     case VGA_VMWARE:
198         fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __func__);
199         return NULL;
200     case VGA_VIRTIO:
201         fprintf(stderr, "%s: virtio-vga: no PCI bus\n", __func__);
202         return NULL;
203     case VGA_NONE:
204     default:
205         return NULL;
206     }
207 }
208 
209 static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent)
210 {
211     ISADevice *d = ISA_DEVICE(dev);
212 
213     if (d->isairq[1] != -1) {
214         monitor_printf(mon, "%*sisa irqs %d,%d\n", indent, "",
215                        d->isairq[0], d->isairq[1]);
216     } else if (d->isairq[0] != -1) {
217         monitor_printf(mon, "%*sisa irq %d\n", indent, "",
218                        d->isairq[0]);
219     }
220 }
221 
222 static void isabus_bridge_class_init(ObjectClass *klass, void *data)
223 {
224     DeviceClass *dc = DEVICE_CLASS(klass);
225 
226     dc->fw_name = "isa";
227 }
228 
229 static const TypeInfo isabus_bridge_info = {
230     .name          = "isabus-bridge",
231     .parent        = TYPE_SYS_BUS_DEVICE,
232     .instance_size = sizeof(SysBusDevice),
233     .class_init    = isabus_bridge_class_init,
234 };
235 
236 static void isa_device_class_init(ObjectClass *klass, void *data)
237 {
238     DeviceClass *k = DEVICE_CLASS(klass);
239     k->bus_type = TYPE_ISA_BUS;
240 }
241 
242 static const TypeInfo isa_device_type_info = {
243     .name = TYPE_ISA_DEVICE,
244     .parent = TYPE_DEVICE,
245     .instance_size = sizeof(ISADevice),
246     .instance_init = isa_device_init,
247     .abstract = true,
248     .class_size = sizeof(ISADeviceClass),
249     .class_init = isa_device_class_init,
250 };
251 
252 static void isabus_register_types(void)
253 {
254     type_register_static(&isa_dma_info);
255     type_register_static(&isa_bus_info);
256     type_register_static(&isabus_bridge_info);
257     type_register_static(&isa_device_type_info);
258 }
259 
260 static char *isabus_get_fw_dev_path(DeviceState *dev)
261 {
262     ISADevice *d = ISA_DEVICE(dev);
263     char path[40];
264     int off;
265 
266     off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
267     if (d->ioport_id) {
268         snprintf(path + off, sizeof(path) - off, "@%04x", d->ioport_id);
269     }
270 
271     return g_strdup(path);
272 }
273 
274 MemoryRegion *isa_address_space(ISADevice *dev)
275 {
276     if (dev) {
277         return isa_bus_from_device(dev)->address_space;
278     }
279 
280     return isabus->address_space;
281 }
282 
283 MemoryRegion *isa_address_space_io(ISADevice *dev)
284 {
285     if (dev) {
286         return isa_bus_from_device(dev)->address_space_io;
287     }
288 
289     return isabus->address_space_io;
290 }
291 
292 type_init(isabus_register_types)
293 
294 static void parallel_init(ISABus *bus, int index, CharDriverState *chr)
295 {
296     DeviceState *dev;
297     ISADevice *isadev;
298 
299     isadev = isa_create(bus, "isa-parallel");
300     dev = DEVICE(isadev);
301     qdev_prop_set_uint32(dev, "index", index);
302     qdev_prop_set_chr(dev, "chardev", chr);
303     qdev_init_nofail(dev);
304 }
305 
306 void parallel_hds_isa_init(ISABus *bus, int n)
307 {
308     int i;
309 
310     assert(n <= MAX_PARALLEL_PORTS);
311 
312     for (i = 0; i < n; i++) {
313         if (parallel_hds[i]) {
314             parallel_init(bus, i, parallel_hds[i]);
315         }
316     }
317 }
318