Statistics
| Branch: | Revision:

root / hw / sysbus.c @ 5e22c276

History | View | Annotate | Download (7.7 kB)

1 aae9460e Paul Brook
/*
2 aae9460e Paul Brook
 *  System (CPU) Bus device support code
3 aae9460e Paul Brook
 *
4 aae9460e Paul Brook
 *  Copyright (c) 2009 CodeSourcery
5 aae9460e Paul Brook
 *
6 aae9460e Paul Brook
 * This library is free software; you can redistribute it and/or
7 aae9460e Paul Brook
 * modify it under the terms of the GNU Lesser General Public
8 aae9460e Paul Brook
 * License as published by the Free Software Foundation; either
9 aae9460e Paul Brook
 * version 2 of the License, or (at your option) any later version.
10 aae9460e Paul Brook
 *
11 aae9460e Paul Brook
 * This library is distributed in the hope that it will be useful,
12 aae9460e Paul Brook
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 aae9460e Paul Brook
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 aae9460e Paul Brook
 * Lesser General Public License for more details.
15 aae9460e Paul Brook
 *
16 aae9460e Paul Brook
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 aae9460e Paul Brook
 */
19 aae9460e Paul Brook
20 aae9460e Paul Brook
#include "sysbus.h"
21 83c9089e Paolo Bonzini
#include "monitor/monitor.h"
22 022c62cb Paolo Bonzini
#include "exec/address-spaces.h"
23 aae9460e Paul Brook
24 10c4c98a Gerd Hoffmann
static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
25 c646f74f Gleb Natapov
static char *sysbus_get_fw_dev_path(DeviceState *dev);
26 10c4c98a Gerd Hoffmann
27 0d936928 Anthony Liguori
static void system_bus_class_init(ObjectClass *klass, void *data)
28 0d936928 Anthony Liguori
{
29 0d936928 Anthony Liguori
    BusClass *k = BUS_CLASS(klass);
30 0d936928 Anthony Liguori
31 0d936928 Anthony Liguori
    k->print_dev = sysbus_dev_print;
32 0d936928 Anthony Liguori
    k->get_fw_dev_path = sysbus_get_fw_dev_path;
33 0d936928 Anthony Liguori
}
34 0d936928 Anthony Liguori
35 0d936928 Anthony Liguori
static const TypeInfo system_bus_info = {
36 0d936928 Anthony Liguori
    .name = TYPE_SYSTEM_BUS,
37 0d936928 Anthony Liguori
    .parent = TYPE_BUS,
38 0d936928 Anthony Liguori
    .instance_size = sizeof(BusState),
39 0d936928 Anthony Liguori
    .class_init = system_bus_class_init,
40 10c4c98a Gerd Hoffmann
};
41 10c4c98a Gerd Hoffmann
42 aae9460e Paul Brook
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
43 aae9460e Paul Brook
{
44 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_irq);
45 660f11be Blue Swirl
    dev->irqs[n] = NULL;
46 aae9460e Paul Brook
    if (dev->irqp[n]) {
47 aae9460e Paul Brook
        *dev->irqp[n] = irq;
48 aae9460e Paul Brook
    }
49 aae9460e Paul Brook
}
50 aae9460e Paul Brook
51 a8170e5e Avi Kivity
void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr)
52 aae9460e Paul Brook
{
53 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_mmio);
54 aae9460e Paul Brook
55 aae9460e Paul Brook
    if (dev->mmio[n].addr == addr) {
56 aae9460e Paul Brook
        /* ??? region already mapped here.  */
57 aae9460e Paul Brook
        return;
58 aae9460e Paul Brook
    }
59 a8170e5e Avi Kivity
    if (dev->mmio[n].addr != (hwaddr)-1) {
60 aae9460e Paul Brook
        /* Unregister previous mapping.  */
61 e114fead Peter Maydell
        memory_region_del_subregion(get_system_memory(), dev->mmio[n].memory);
62 aae9460e Paul Brook
    }
63 aae9460e Paul Brook
    dev->mmio[n].addr = addr;
64 e114fead Peter Maydell
    memory_region_add_subregion(get_system_memory(),
65 e114fead Peter Maydell
                                addr,
66 e114fead Peter Maydell
                                dev->mmio[n].memory);
67 aae9460e Paul Brook
}
68 aae9460e Paul Brook
69 aae9460e Paul Brook
70 aae9460e Paul Brook
/* Request an IRQ source.  The actual IRQ object may be populated later.  */
71 aae9460e Paul Brook
void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p)
72 aae9460e Paul Brook
{
73 aae9460e Paul Brook
    int n;
74 aae9460e Paul Brook
75 aae9460e Paul Brook
    assert(dev->num_irq < QDEV_MAX_IRQ);
76 aae9460e Paul Brook
    n = dev->num_irq++;
77 aae9460e Paul Brook
    dev->irqp[n] = p;
78 aae9460e Paul Brook
}
79 aae9460e Paul Brook
80 aae9460e Paul Brook
/* Pass IRQs from a target device.  */
81 aae9460e Paul Brook
void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target)
82 aae9460e Paul Brook
{
83 aae9460e Paul Brook
    int i;
84 aae9460e Paul Brook
    assert(dev->num_irq == 0);
85 aae9460e Paul Brook
    dev->num_irq = target->num_irq;
86 aae9460e Paul Brook
    for (i = 0; i < dev->num_irq; i++) {
87 aae9460e Paul Brook
        dev->irqp[i] = target->irqp[i];
88 aae9460e Paul Brook
    }
89 aae9460e Paul Brook
}
90 aae9460e Paul Brook
91 750ecd44 Avi Kivity
void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory)
92 ec3bb837 Avi Kivity
{
93 ec3bb837 Avi Kivity
    int n;
94 ec3bb837 Avi Kivity
95 ec3bb837 Avi Kivity
    assert(dev->num_mmio < QDEV_MAX_MMIO);
96 ec3bb837 Avi Kivity
    n = dev->num_mmio++;
97 ec3bb837 Avi Kivity
    dev->mmio[n].addr = -1;
98 ec3bb837 Avi Kivity
    dev->mmio[n].memory = memory;
99 ec3bb837 Avi Kivity
}
100 ec3bb837 Avi Kivity
101 46c305ef Peter Maydell
MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n)
102 46c305ef Peter Maydell
{
103 46c305ef Peter Maydell
    return dev->mmio[n].memory;
104 46c305ef Peter Maydell
}
105 46c305ef Peter Maydell
106 c646f74f Gleb Natapov
void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size)
107 c646f74f Gleb Natapov
{
108 c646f74f Gleb Natapov
    pio_addr_t i;
109 c646f74f Gleb Natapov
110 c646f74f Gleb Natapov
    for (i = 0; i < size; i++) {
111 c646f74f Gleb Natapov
        assert(dev->num_pio < QDEV_MAX_PIO);
112 c646f74f Gleb Natapov
        dev->pio[dev->num_pio++] = ioport++;
113 c646f74f Gleb Natapov
    }
114 c646f74f Gleb Natapov
}
115 c646f74f Gleb Natapov
116 d307af79 Anthony Liguori
static int sysbus_device_init(DeviceState *dev)
117 aae9460e Paul Brook
{
118 999e12bb Anthony Liguori
    SysBusDevice *sd = SYS_BUS_DEVICE(dev);
119 999e12bb Anthony Liguori
    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(sd);
120 aae9460e Paul Brook
121 999e12bb Anthony Liguori
    return sbc->init(sd);
122 aae9460e Paul Brook
}
123 aae9460e Paul Brook
124 aae9460e Paul Brook
DeviceState *sysbus_create_varargs(const char *name,
125 a8170e5e Avi Kivity
                                   hwaddr addr, ...)
126 aae9460e Paul Brook
{
127 aae9460e Paul Brook
    DeviceState *dev;
128 aae9460e Paul Brook
    SysBusDevice *s;
129 aae9460e Paul Brook
    va_list va;
130 aae9460e Paul Brook
    qemu_irq irq;
131 aae9460e Paul Brook
    int n;
132 aae9460e Paul Brook
133 aae9460e Paul Brook
    dev = qdev_create(NULL, name);
134 aae9460e Paul Brook
    s = sysbus_from_qdev(dev);
135 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
136 a8170e5e Avi Kivity
    if (addr != (hwaddr)-1) {
137 aae9460e Paul Brook
        sysbus_mmio_map(s, 0, addr);
138 aae9460e Paul Brook
    }
139 aae9460e Paul Brook
    va_start(va, addr);
140 aae9460e Paul Brook
    n = 0;
141 aae9460e Paul Brook
    while (1) {
142 4912371f Blue Swirl
        irq = va_arg(va, qemu_irq);
143 4912371f Blue Swirl
        if (!irq) {
144 4912371f Blue Swirl
            break;
145 4912371f Blue Swirl
        }
146 4912371f Blue Swirl
        sysbus_connect_irq(s, n, irq);
147 4912371f Blue Swirl
        n++;
148 4912371f Blue Swirl
    }
149 d0bc5bc3 Markus Armbruster
    va_end(va);
150 4912371f Blue Swirl
    return dev;
151 4912371f Blue Swirl
}
152 4912371f Blue Swirl
153 4912371f Blue Swirl
DeviceState *sysbus_try_create_varargs(const char *name,
154 a8170e5e Avi Kivity
                                       hwaddr addr, ...)
155 4912371f Blue Swirl
{
156 4912371f Blue Swirl
    DeviceState *dev;
157 4912371f Blue Swirl
    SysBusDevice *s;
158 4912371f Blue Swirl
    va_list va;
159 4912371f Blue Swirl
    qemu_irq irq;
160 4912371f Blue Swirl
    int n;
161 4912371f Blue Swirl
162 4912371f Blue Swirl
    dev = qdev_try_create(NULL, name);
163 4912371f Blue Swirl
    if (!dev) {
164 4912371f Blue Swirl
        return NULL;
165 4912371f Blue Swirl
    }
166 4912371f Blue Swirl
    s = sysbus_from_qdev(dev);
167 4912371f Blue Swirl
    qdev_init_nofail(dev);
168 a8170e5e Avi Kivity
    if (addr != (hwaddr)-1) {
169 4912371f Blue Swirl
        sysbus_mmio_map(s, 0, addr);
170 4912371f Blue Swirl
    }
171 4912371f Blue Swirl
    va_start(va, addr);
172 4912371f Blue Swirl
    n = 0;
173 4912371f Blue Swirl
    while (1) {
174 aae9460e Paul Brook
        irq = va_arg(va, qemu_irq);
175 aae9460e Paul Brook
        if (!irq) {
176 aae9460e Paul Brook
            break;
177 aae9460e Paul Brook
        }
178 aae9460e Paul Brook
        sysbus_connect_irq(s, n, irq);
179 aae9460e Paul Brook
        n++;
180 aae9460e Paul Brook
    }
181 d0bc5bc3 Markus Armbruster
    va_end(va);
182 aae9460e Paul Brook
    return dev;
183 aae9460e Paul Brook
}
184 cae4956e Gerd Hoffmann
185 10c4c98a Gerd Hoffmann
static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
186 cae4956e Gerd Hoffmann
{
187 cae4956e Gerd Hoffmann
    SysBusDevice *s = sysbus_from_qdev(dev);
188 a8170e5e Avi Kivity
    hwaddr size;
189 cae4956e Gerd Hoffmann
    int i;
190 cae4956e Gerd Hoffmann
191 0fba9fd6 Dmitry Eremin-Solenikov
    monitor_printf(mon, "%*sirq %d\n", indent, "", s->num_irq);
192 cae4956e Gerd Hoffmann
    for (i = 0; i < s->num_mmio; i++) {
193 e114fead Peter Maydell
        size = memory_region_size(s->mmio[i].memory);
194 cae4956e Gerd Hoffmann
        monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
195 3f7f1c80 Avi Kivity
                       indent, "", s->mmio[i].addr, size);
196 cae4956e Gerd Hoffmann
    }
197 cae4956e Gerd Hoffmann
}
198 c646f74f Gleb Natapov
199 c646f74f Gleb Natapov
static char *sysbus_get_fw_dev_path(DeviceState *dev)
200 c646f74f Gleb Natapov
{
201 c646f74f Gleb Natapov
    SysBusDevice *s = sysbus_from_qdev(dev);
202 c646f74f Gleb Natapov
    char path[40];
203 c646f74f Gleb Natapov
    int off;
204 c646f74f Gleb Natapov
205 c646f74f Gleb Natapov
    off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
206 c646f74f Gleb Natapov
207 c646f74f Gleb Natapov
    if (s->num_mmio) {
208 c646f74f Gleb Natapov
        snprintf(path + off, sizeof(path) - off, "@"TARGET_FMT_plx,
209 c646f74f Gleb Natapov
                 s->mmio[0].addr);
210 c646f74f Gleb Natapov
    } else if (s->num_pio) {
211 c646f74f Gleb Natapov
        snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]);
212 c646f74f Gleb Natapov
    }
213 c646f74f Gleb Natapov
214 a5cf8262 Jim Meyering
    return g_strdup(path);
215 c646f74f Gleb Natapov
}
216 2b985d9c Avi Kivity
217 a8170e5e Avi Kivity
void sysbus_add_memory(SysBusDevice *dev, hwaddr addr,
218 2b985d9c Avi Kivity
                       MemoryRegion *mem)
219 2b985d9c Avi Kivity
{
220 2b985d9c Avi Kivity
    memory_region_add_subregion(get_system_memory(), addr, mem);
221 2b985d9c Avi Kivity
}
222 2b985d9c Avi Kivity
223 a8170e5e Avi Kivity
void sysbus_add_memory_overlap(SysBusDevice *dev, hwaddr addr,
224 d40b2af8 Avi Kivity
                               MemoryRegion *mem, unsigned priority)
225 d40b2af8 Avi Kivity
{
226 d40b2af8 Avi Kivity
    memory_region_add_subregion_overlap(get_system_memory(), addr, mem,
227 d40b2af8 Avi Kivity
                                        priority);
228 d40b2af8 Avi Kivity
}
229 d40b2af8 Avi Kivity
230 2b985d9c Avi Kivity
void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem)
231 2b985d9c Avi Kivity
{
232 2b985d9c Avi Kivity
    memory_region_del_subregion(get_system_memory(), mem);
233 2b985d9c Avi Kivity
}
234 2b985d9c Avi Kivity
235 a8170e5e Avi Kivity
void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
236 2b985d9c Avi Kivity
                       MemoryRegion *mem)
237 2b985d9c Avi Kivity
{
238 2b985d9c Avi Kivity
    memory_region_add_subregion(get_system_io(), addr, mem);
239 2b985d9c Avi Kivity
}
240 2b985d9c Avi Kivity
241 2b985d9c Avi Kivity
void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem)
242 2b985d9c Avi Kivity
{
243 2b985d9c Avi Kivity
    memory_region_del_subregion(get_system_io(), mem);
244 2b985d9c Avi Kivity
}
245 62ec4832 Avi Kivity
246 62ec4832 Avi Kivity
MemoryRegion *sysbus_address_space(SysBusDevice *dev)
247 62ec4832 Avi Kivity
{
248 62ec4832 Avi Kivity
    return get_system_memory();
249 62ec4832 Avi Kivity
}
250 999e12bb Anthony Liguori
251 39bffca2 Anthony Liguori
static void sysbus_device_class_init(ObjectClass *klass, void *data)
252 39bffca2 Anthony Liguori
{
253 39bffca2 Anthony Liguori
    DeviceClass *k = DEVICE_CLASS(klass);
254 39bffca2 Anthony Liguori
    k->init = sysbus_device_init;
255 0d936928 Anthony Liguori
    k->bus_type = TYPE_SYSTEM_BUS;
256 39bffca2 Anthony Liguori
}
257 39bffca2 Anthony Liguori
258 999e12bb Anthony Liguori
static TypeInfo sysbus_device_type_info = {
259 999e12bb Anthony Liguori
    .name = TYPE_SYS_BUS_DEVICE,
260 999e12bb Anthony Liguori
    .parent = TYPE_DEVICE,
261 999e12bb Anthony Liguori
    .instance_size = sizeof(SysBusDevice),
262 999e12bb Anthony Liguori
    .abstract = true,
263 999e12bb Anthony Liguori
    .class_size = sizeof(SysBusDeviceClass),
264 39bffca2 Anthony Liguori
    .class_init = sysbus_device_class_init,
265 999e12bb Anthony Liguori
};
266 999e12bb Anthony Liguori
267 8185d216 Paolo Bonzini
/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
268 8185d216 Paolo Bonzini
static BusState *main_system_bus;
269 8185d216 Paolo Bonzini
270 8185d216 Paolo Bonzini
static void main_system_bus_create(void)
271 8185d216 Paolo Bonzini
{
272 8185d216 Paolo Bonzini
    /* assign main_system_bus before qbus_create_inplace()
273 8185d216 Paolo Bonzini
     * in order to make "if (bus != sysbus_get_default())" work */
274 0d936928 Anthony Liguori
    main_system_bus = g_malloc0(system_bus_info.instance_size);
275 0d936928 Anthony Liguori
    qbus_create_inplace(main_system_bus, TYPE_SYSTEM_BUS, NULL,
276 8185d216 Paolo Bonzini
                        "main-system-bus");
277 64b625f4 Paolo Bonzini
    OBJECT(main_system_bus)->free = g_free;
278 f968fc68 Anthony Liguori
    object_property_add_child(container_get(qdev_get_machine(),
279 f968fc68 Anthony Liguori
                                            "/unattached"),
280 f968fc68 Anthony Liguori
                              "sysbus", OBJECT(main_system_bus), NULL);
281 8185d216 Paolo Bonzini
}
282 8185d216 Paolo Bonzini
283 8185d216 Paolo Bonzini
BusState *sysbus_get_default(void)
284 8185d216 Paolo Bonzini
{
285 8185d216 Paolo Bonzini
    if (!main_system_bus) {
286 8185d216 Paolo Bonzini
        main_system_bus_create();
287 8185d216 Paolo Bonzini
    }
288 8185d216 Paolo Bonzini
    return main_system_bus;
289 8185d216 Paolo Bonzini
}
290 8185d216 Paolo Bonzini
291 83f7d43a Andreas Färber
static void sysbus_register_types(void)
292 999e12bb Anthony Liguori
{
293 0d936928 Anthony Liguori
    type_register_static(&system_bus_info);
294 999e12bb Anthony Liguori
    type_register_static(&sysbus_device_type_info);
295 999e12bb Anthony Liguori
}
296 999e12bb Anthony Liguori
297 83f7d43a Andreas Färber
type_init(sysbus_register_types)