Statistics
| Branch: | Revision:

root / hw / sysbus.c @ 71cf9e62

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 cae4956e Gerd Hoffmann
#include "monitor.h"
22 ec3bb837 Avi Kivity
#include "exec-memory.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 10c4c98a Gerd Hoffmann
struct BusInfo system_bus_info = {
28 10c4c98a Gerd Hoffmann
    .name       = "System",
29 10c4c98a Gerd Hoffmann
    .size       = sizeof(BusState),
30 10c4c98a Gerd Hoffmann
    .print_dev  = sysbus_dev_print,
31 c646f74f Gleb Natapov
    .get_fw_dev_path = sysbus_get_fw_dev_path,
32 10c4c98a Gerd Hoffmann
};
33 10c4c98a Gerd Hoffmann
34 aae9460e Paul Brook
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
35 aae9460e Paul Brook
{
36 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_irq);
37 660f11be Blue Swirl
    dev->irqs[n] = NULL;
38 aae9460e Paul Brook
    if (dev->irqp[n]) {
39 aae9460e Paul Brook
        *dev->irqp[n] = irq;
40 aae9460e Paul Brook
    }
41 aae9460e Paul Brook
}
42 aae9460e Paul Brook
43 c227f099 Anthony Liguori
void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
44 aae9460e Paul Brook
{
45 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_mmio);
46 aae9460e Paul Brook
47 aae9460e Paul Brook
    if (dev->mmio[n].addr == addr) {
48 aae9460e Paul Brook
        /* ??? region already mapped here.  */
49 aae9460e Paul Brook
        return;
50 aae9460e Paul Brook
    }
51 c227f099 Anthony Liguori
    if (dev->mmio[n].addr != (target_phys_addr_t)-1) {
52 aae9460e Paul Brook
        /* Unregister previous mapping.  */
53 ec3bb837 Avi Kivity
        if (dev->mmio[n].memory) {
54 ec3bb837 Avi Kivity
            memory_region_del_subregion(get_system_memory(),
55 ec3bb837 Avi Kivity
                                        dev->mmio[n].memory);
56 d7612013 Avi Kivity
        } else if (dev->mmio[n].unmap) {
57 d7612013 Avi Kivity
            dev->mmio[n].unmap(dev, dev->mmio[n].addr);
58 ec3bb837 Avi Kivity
        } else {
59 ec3bb837 Avi Kivity
            cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
60 ec3bb837 Avi Kivity
                                         IO_MEM_UNASSIGNED);
61 ec3bb837 Avi Kivity
        }
62 aae9460e Paul Brook
    }
63 aae9460e Paul Brook
    dev->mmio[n].addr = addr;
64 ec3bb837 Avi Kivity
    if (dev->mmio[n].memory) {
65 ec3bb837 Avi Kivity
        memory_region_add_subregion(get_system_memory(),
66 ec3bb837 Avi Kivity
                                    addr,
67 ec3bb837 Avi Kivity
                                    dev->mmio[n].memory);
68 ec3bb837 Avi Kivity
    } else if (dev->mmio[n].cb) {
69 aae9460e Paul Brook
        dev->mmio[n].cb(dev, addr);
70 aae9460e Paul Brook
    } else {
71 aae9460e Paul Brook
        cpu_register_physical_memory(addr, dev->mmio[n].size,
72 aae9460e Paul Brook
                                     dev->mmio[n].iofunc);
73 aae9460e Paul Brook
    }
74 aae9460e Paul Brook
}
75 aae9460e Paul Brook
76 aae9460e Paul Brook
77 aae9460e Paul Brook
/* Request an IRQ source.  The actual IRQ object may be populated later.  */
78 aae9460e Paul Brook
void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p)
79 aae9460e Paul Brook
{
80 aae9460e Paul Brook
    int n;
81 aae9460e Paul Brook
82 aae9460e Paul Brook
    assert(dev->num_irq < QDEV_MAX_IRQ);
83 aae9460e Paul Brook
    n = dev->num_irq++;
84 aae9460e Paul Brook
    dev->irqp[n] = p;
85 aae9460e Paul Brook
}
86 aae9460e Paul Brook
87 aae9460e Paul Brook
/* Pass IRQs from a target device.  */
88 aae9460e Paul Brook
void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target)
89 aae9460e Paul Brook
{
90 aae9460e Paul Brook
    int i;
91 aae9460e Paul Brook
    assert(dev->num_irq == 0);
92 aae9460e Paul Brook
    dev->num_irq = target->num_irq;
93 aae9460e Paul Brook
    for (i = 0; i < dev->num_irq; i++) {
94 aae9460e Paul Brook
        dev->irqp[i] = target->irqp[i];
95 aae9460e Paul Brook
    }
96 aae9460e Paul Brook
}
97 aae9460e Paul Brook
98 3f7132d1 Blue Swirl
void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size,
99 3f7132d1 Blue Swirl
                      ram_addr_t iofunc)
100 aae9460e Paul Brook
{
101 aae9460e Paul Brook
    int n;
102 aae9460e Paul Brook
103 aae9460e Paul Brook
    assert(dev->num_mmio < QDEV_MAX_MMIO);
104 aae9460e Paul Brook
    n = dev->num_mmio++;
105 aae9460e Paul Brook
    dev->mmio[n].addr = -1;
106 aae9460e Paul Brook
    dev->mmio[n].size = size;
107 aae9460e Paul Brook
    dev->mmio[n].iofunc = iofunc;
108 aae9460e Paul Brook
}
109 aae9460e Paul Brook
110 d7612013 Avi Kivity
void sysbus_init_mmio_cb2(SysBusDevice *dev,
111 d7612013 Avi Kivity
                          mmio_mapfunc cb, mmio_mapfunc unmap)
112 d7612013 Avi Kivity
{
113 d7612013 Avi Kivity
    int n;
114 d7612013 Avi Kivity
115 d7612013 Avi Kivity
    assert(dev->num_mmio < QDEV_MAX_MMIO);
116 d7612013 Avi Kivity
    n = dev->num_mmio++;
117 d7612013 Avi Kivity
    dev->mmio[n].addr = -1;
118 d7612013 Avi Kivity
    dev->mmio[n].size = 0;
119 d7612013 Avi Kivity
    dev->mmio[n].cb = cb;
120 d7612013 Avi Kivity
    dev->mmio[n].unmap = unmap;
121 d7612013 Avi Kivity
}
122 d7612013 Avi Kivity
123 ec3bb837 Avi Kivity
void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory)
124 ec3bb837 Avi Kivity
{
125 ec3bb837 Avi Kivity
    int n;
126 ec3bb837 Avi Kivity
127 ec3bb837 Avi Kivity
    assert(dev->num_mmio < QDEV_MAX_MMIO);
128 ec3bb837 Avi Kivity
    n = dev->num_mmio++;
129 ec3bb837 Avi Kivity
    dev->mmio[n].addr = -1;
130 ec3bb837 Avi Kivity
    dev->mmio[n].size = memory_region_size(memory);
131 ec3bb837 Avi Kivity
    dev->mmio[n].memory = memory;
132 ec3bb837 Avi Kivity
}
133 ec3bb837 Avi Kivity
134 46c305ef Peter Maydell
MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n)
135 46c305ef Peter Maydell
{
136 46c305ef Peter Maydell
    return dev->mmio[n].memory;
137 46c305ef Peter Maydell
}
138 46c305ef Peter Maydell
139 c646f74f Gleb Natapov
void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size)
140 c646f74f Gleb Natapov
{
141 c646f74f Gleb Natapov
    pio_addr_t i;
142 c646f74f Gleb Natapov
143 c646f74f Gleb Natapov
    for (i = 0; i < size; i++) {
144 c646f74f Gleb Natapov
        assert(dev->num_pio < QDEV_MAX_PIO);
145 c646f74f Gleb Natapov
        dev->pio[dev->num_pio++] = ioport++;
146 c646f74f Gleb Natapov
    }
147 c646f74f Gleb Natapov
}
148 c646f74f Gleb Natapov
149 81a322d4 Gerd Hoffmann
static int sysbus_device_init(DeviceState *dev, DeviceInfo *base)
150 aae9460e Paul Brook
{
151 02e2da45 Paul Brook
    SysBusDeviceInfo *info = container_of(base, SysBusDeviceInfo, qdev);
152 aae9460e Paul Brook
153 81a322d4 Gerd Hoffmann
    return info->init(sysbus_from_qdev(dev));
154 aae9460e Paul Brook
}
155 aae9460e Paul Brook
156 074f2fff Gerd Hoffmann
void sysbus_register_withprop(SysBusDeviceInfo *info)
157 aae9460e Paul Brook
{
158 02e2da45 Paul Brook
    info->qdev.init = sysbus_device_init;
159 10c4c98a Gerd Hoffmann
    info->qdev.bus_info = &system_bus_info;
160 02e2da45 Paul Brook
161 074f2fff Gerd Hoffmann
    assert(info->qdev.size >= sizeof(SysBusDevice));
162 074f2fff Gerd Hoffmann
    qdev_register(&info->qdev);
163 aae9460e Paul Brook
}
164 aae9460e Paul Brook
165 1431b6a1 Paul Brook
void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init)
166 1431b6a1 Paul Brook
{
167 1431b6a1 Paul Brook
    SysBusDeviceInfo *info;
168 1431b6a1 Paul Brook
169 7267c094 Anthony Liguori
    info = g_malloc0(sizeof(*info));
170 7267c094 Anthony Liguori
    info->qdev.name = g_strdup(name);
171 074f2fff Gerd Hoffmann
    info->qdev.size = size;
172 1431b6a1 Paul Brook
    info->init = init;
173 074f2fff Gerd Hoffmann
    sysbus_register_withprop(info);
174 1431b6a1 Paul Brook
}
175 1431b6a1 Paul Brook
176 aae9460e Paul Brook
DeviceState *sysbus_create_varargs(const char *name,
177 c227f099 Anthony Liguori
                                   target_phys_addr_t addr, ...)
178 aae9460e Paul Brook
{
179 aae9460e Paul Brook
    DeviceState *dev;
180 aae9460e Paul Brook
    SysBusDevice *s;
181 aae9460e Paul Brook
    va_list va;
182 aae9460e Paul Brook
    qemu_irq irq;
183 aae9460e Paul Brook
    int n;
184 aae9460e Paul Brook
185 aae9460e Paul Brook
    dev = qdev_create(NULL, name);
186 aae9460e Paul Brook
    s = sysbus_from_qdev(dev);
187 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
188 c227f099 Anthony Liguori
    if (addr != (target_phys_addr_t)-1) {
189 aae9460e Paul Brook
        sysbus_mmio_map(s, 0, addr);
190 aae9460e Paul Brook
    }
191 aae9460e Paul Brook
    va_start(va, addr);
192 aae9460e Paul Brook
    n = 0;
193 aae9460e Paul Brook
    while (1) {
194 4912371f Blue Swirl
        irq = va_arg(va, qemu_irq);
195 4912371f Blue Swirl
        if (!irq) {
196 4912371f Blue Swirl
            break;
197 4912371f Blue Swirl
        }
198 4912371f Blue Swirl
        sysbus_connect_irq(s, n, irq);
199 4912371f Blue Swirl
        n++;
200 4912371f Blue Swirl
    }
201 4912371f Blue Swirl
    return dev;
202 4912371f Blue Swirl
}
203 4912371f Blue Swirl
204 4912371f Blue Swirl
DeviceState *sysbus_try_create_varargs(const char *name,
205 4912371f Blue Swirl
                                       target_phys_addr_t addr, ...)
206 4912371f Blue Swirl
{
207 4912371f Blue Swirl
    DeviceState *dev;
208 4912371f Blue Swirl
    SysBusDevice *s;
209 4912371f Blue Swirl
    va_list va;
210 4912371f Blue Swirl
    qemu_irq irq;
211 4912371f Blue Swirl
    int n;
212 4912371f Blue Swirl
213 4912371f Blue Swirl
    dev = qdev_try_create(NULL, name);
214 4912371f Blue Swirl
    if (!dev) {
215 4912371f Blue Swirl
        return NULL;
216 4912371f Blue Swirl
    }
217 4912371f Blue Swirl
    s = sysbus_from_qdev(dev);
218 4912371f Blue Swirl
    qdev_init_nofail(dev);
219 4912371f Blue Swirl
    if (addr != (target_phys_addr_t)-1) {
220 4912371f Blue Swirl
        sysbus_mmio_map(s, 0, addr);
221 4912371f Blue Swirl
    }
222 4912371f Blue Swirl
    va_start(va, addr);
223 4912371f Blue Swirl
    n = 0;
224 4912371f Blue Swirl
    while (1) {
225 aae9460e Paul Brook
        irq = va_arg(va, qemu_irq);
226 aae9460e Paul Brook
        if (!irq) {
227 aae9460e Paul Brook
            break;
228 aae9460e Paul Brook
        }
229 aae9460e Paul Brook
        sysbus_connect_irq(s, n, irq);
230 aae9460e Paul Brook
        n++;
231 aae9460e Paul Brook
    }
232 aae9460e Paul Brook
    return dev;
233 aae9460e Paul Brook
}
234 cae4956e Gerd Hoffmann
235 10c4c98a Gerd Hoffmann
static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
236 cae4956e Gerd Hoffmann
{
237 cae4956e Gerd Hoffmann
    SysBusDevice *s = sysbus_from_qdev(dev);
238 cae4956e Gerd Hoffmann
    int i;
239 cae4956e Gerd Hoffmann
240 0fba9fd6 Dmitry Eremin-Solenikov
    monitor_printf(mon, "%*sirq %d\n", indent, "", s->num_irq);
241 cae4956e Gerd Hoffmann
    for (i = 0; i < s->num_mmio; i++) {
242 cae4956e Gerd Hoffmann
        monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
243 cae4956e Gerd Hoffmann
                       indent, "", s->mmio[i].addr, s->mmio[i].size);
244 cae4956e Gerd Hoffmann
    }
245 cae4956e Gerd Hoffmann
}
246 c646f74f Gleb Natapov
247 c646f74f Gleb Natapov
static char *sysbus_get_fw_dev_path(DeviceState *dev)
248 c646f74f Gleb Natapov
{
249 c646f74f Gleb Natapov
    SysBusDevice *s = sysbus_from_qdev(dev);
250 c646f74f Gleb Natapov
    char path[40];
251 c646f74f Gleb Natapov
    int off;
252 c646f74f Gleb Natapov
253 c646f74f Gleb Natapov
    off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
254 c646f74f Gleb Natapov
255 c646f74f Gleb Natapov
    if (s->num_mmio) {
256 c646f74f Gleb Natapov
        snprintf(path + off, sizeof(path) - off, "@"TARGET_FMT_plx,
257 c646f74f Gleb Natapov
                 s->mmio[0].addr);
258 c646f74f Gleb Natapov
    } else if (s->num_pio) {
259 c646f74f Gleb Natapov
        snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]);
260 c646f74f Gleb Natapov
    }
261 c646f74f Gleb Natapov
262 c646f74f Gleb Natapov
    return strdup(path);
263 c646f74f Gleb Natapov
}
264 2b985d9c Avi Kivity
265 2b985d9c Avi Kivity
void sysbus_add_memory(SysBusDevice *dev, target_phys_addr_t addr,
266 2b985d9c Avi Kivity
                       MemoryRegion *mem)
267 2b985d9c Avi Kivity
{
268 2b985d9c Avi Kivity
    memory_region_add_subregion(get_system_memory(), addr, mem);
269 2b985d9c Avi Kivity
}
270 2b985d9c Avi Kivity
271 d40b2af8 Avi Kivity
void sysbus_add_memory_overlap(SysBusDevice *dev, target_phys_addr_t addr,
272 d40b2af8 Avi Kivity
                               MemoryRegion *mem, unsigned priority)
273 d40b2af8 Avi Kivity
{
274 d40b2af8 Avi Kivity
    memory_region_add_subregion_overlap(get_system_memory(), addr, mem,
275 d40b2af8 Avi Kivity
                                        priority);
276 d40b2af8 Avi Kivity
}
277 d40b2af8 Avi Kivity
278 2b985d9c Avi Kivity
void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem)
279 2b985d9c Avi Kivity
{
280 2b985d9c Avi Kivity
    memory_region_del_subregion(get_system_memory(), mem);
281 2b985d9c Avi Kivity
}
282 2b985d9c Avi Kivity
283 2b985d9c Avi Kivity
void sysbus_add_io(SysBusDevice *dev, target_phys_addr_t addr,
284 2b985d9c Avi Kivity
                       MemoryRegion *mem)
285 2b985d9c Avi Kivity
{
286 2b985d9c Avi Kivity
    memory_region_add_subregion(get_system_io(), addr, mem);
287 2b985d9c Avi Kivity
}
288 2b985d9c Avi Kivity
289 2b985d9c Avi Kivity
void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem)
290 2b985d9c Avi Kivity
{
291 2b985d9c Avi Kivity
    memory_region_del_subregion(get_system_io(), mem);
292 2b985d9c Avi Kivity
}