| /* |
| * System (CPU) Bus device support code |
| * |
| * Copyright (c) 2009 CodeSourcery |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA |
| */ |
| |
| #include "exec/cpu-common.h" |
| #include "hw/sysbus.h" |
| #include "sysemu/sysemu.h" |
| #include "monitor/monitor.h" |
| |
| void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) |
| { |
| assert(n >= 0 && n < dev->num_irq); |
| dev->irqs[n] = 0; |
| if (dev->irqp[n]) { |
| *dev->irqp[n] = irq; |
| } |
| } |
| |
| void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr) |
| { |
| assert(n >= 0 && n < dev->num_mmio); |
| |
| if (dev->mmio[n].addr == addr) { |
| /* ??? region already mapped here. */ |
| return; |
| } |
| if (dev->mmio[n].addr != (hwaddr)-1) { |
| /* Unregister previous mapping. */ |
| cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size, |
| IO_MEM_UNASSIGNED); |
| } |
| dev->mmio[n].addr = addr; |
| if (dev->mmio[n].cb) { |
| dev->mmio[n].cb(dev, addr); |
| } else { |
| cpu_register_physical_memory(addr, dev->mmio[n].size, |
| dev->mmio[n].iofunc); |
| } |
| } |
| |
| |
| /* Request an IRQ source. The actual IRQ object may be populated later. */ |
| void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p) |
| { |
| int n; |
| |
| assert(dev->num_irq < QDEV_MAX_IRQ); |
| n = dev->num_irq++; |
| dev->irqp[n] = p; |
| } |
| |
| void sysbus_init_mmio(SysBusDevice *dev, hwaddr size, int iofunc) |
| { |
| int n; |
| |
| assert(dev->num_mmio < QDEV_MAX_MMIO); |
| n = dev->num_mmio++; |
| dev->mmio[n].addr = -1; |
| dev->mmio[n].size = size; |
| dev->mmio[n].iofunc = iofunc; |
| } |
| |
| static int sysbus_device_init(DeviceState *dev) |
| { |
| DeviceInfo *base = qdev_get_device_info(dev); |
| SysBusDeviceInfo *info = container_of(base, SysBusDeviceInfo, qdev); |
| |
| info->init(sysbus_from_qdev(dev)); |
| return 0; |
| } |
| |
| void sysbus_register_withprop(SysBusDeviceInfo *info) |
| { |
| info->qdev.init = sysbus_device_init; |
| info->qdev.bus_type = BUS_TYPE_SYSTEM; |
| |
| assert(info->qdev.size >= sizeof(SysBusDevice)); |
| qdev_register(&info->qdev); |
| } |
| |
| void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init) |
| { |
| SysBusDeviceInfo *info; |
| |
| info = g_malloc0(sizeof(*info)); |
| info->qdev.name = g_strdup(name); |
| info->qdev.size = size; |
| info->init = init; |
| sysbus_register_withprop(info); |
| } |