* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "monitor/monitor.h"
#include "exec/address-spaces.h"
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
{
+ SysBusDeviceClass *sbd = SYS_BUS_DEVICE_GET_CLASS(dev);
+
qdev_connect_gpio_out_named(DEVICE(dev), SYSBUS_DEVICE_GPIO_IRQ, n, irq);
+
+ if (sbd->connect_irq_notifier) {
+ sbd->connect_irq_notifier(dev, irq);
+ }
}
/* Check whether an MMIO region exists */
return dev->mmio[n].memory;
}
-void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size)
+void sysbus_init_ioports(SysBusDevice *dev, uint32_t ioport, uint32_t size)
{
- pio_addr_t i;
+ uint32_t i;
for (i = 0; i < size; i++) {
assert(dev->num_pio < QDEV_MAX_PIO);
static char *sysbus_get_fw_dev_path(DeviceState *dev)
{
SysBusDevice *s = SYS_BUS_DEVICE(dev);
- char path[40];
- int off;
-
- off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(s);
+ /* for the explicit unit address fallback case: */
+ char *addr, *fw_dev_path;
if (s->num_mmio) {
- snprintf(path + off, sizeof(path) - off, "@"TARGET_FMT_plx,
- s->mmio[0].addr);
- } else if (s->num_pio) {
- snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]);
+ return g_strdup_printf("%s@" TARGET_FMT_plx, qdev_fw_name(dev),
+ s->mmio[0].addr);
}
-
- return g_strdup(path);
+ if (s->num_pio) {
+ return g_strdup_printf("%s@i%04x", qdev_fw_name(dev), s->pio[0]);
+ }
+ if (sbc->explicit_ofw_unit_address) {
+ addr = sbc->explicit_ofw_unit_address(s);
+ if (addr) {
+ fw_dev_path = g_strdup_printf("%s@%s", qdev_fw_name(dev), addr);
+ g_free(addr);
+ return fw_dev_path;
+ }
+ }
+ return g_strdup(qdev_fw_name(dev));
}
void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
DeviceClass *k = DEVICE_CLASS(klass);
k->init = sysbus_device_init;
k->bus_type = TYPE_SYSTEM_BUS;
+ /*
+ * device_add plugs devices into a suitable bus. For "real" buses,
+ * that actually connects the device. For sysbus, the connections
+ * need to be made separately, and device_add can't do that. The
+ * device would be left unconnected, and will probably not work
+ *
+ * However, a few machines can handle device_add/-device with
+ * a few specific sysbus devices. In those cases, the device
+ * subclass needs to override it and set user_creatable=true.
+ */
+ k->user_creatable = false;
}
static const TypeInfo sysbus_device_type_info = {