diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/nubus/mac-nubus-bridge.c | 4 | ||||
-rw-r--r-- | hw/nubus/nubus-bus.c | 5 | ||||
-rw-r--r-- | hw/nubus/nubus-device.c | 29 |
3 files changed, 31 insertions, 7 deletions
diff --git a/hw/nubus/mac-nubus-bridge.c b/hw/nubus/mac-nubus-bridge.c index 7c329300b8..3f075789e9 100644 --- a/hw/nubus/mac-nubus-bridge.c +++ b/hw/nubus/mac-nubus-bridge.c @@ -18,6 +18,10 @@ static void mac_nubus_bridge_init(Object *obj) s->bus = NUBUS_BUS(qbus_create(TYPE_NUBUS_BUS, DEVICE(s), NULL)); + /* Macintosh only has slots 0x9 to 0xe available */ + s->bus->slot_available_mask = MAKE_64BIT_MASK(MAC_NUBUS_FIRST_SLOT, + MAC_NUBUS_SLOT_NB); + sysbus_init_mmio(sbd, &s->bus->super_slot_io); sysbus_init_mmio(sbd, &s->bus->slot_io); } diff --git a/hw/nubus/nubus-bus.c b/hw/nubus/nubus-bus.c index f4410803ff..3cd7534864 100644 --- a/hw/nubus/nubus-bus.c +++ b/hw/nubus/nubus-bus.c @@ -86,13 +86,14 @@ static void nubus_init(Object *obj) memory_region_init_io(&nubus->super_slot_io, obj, &nubus_super_slot_ops, nubus, "nubus-super-slots", - NUBUS_SUPER_SLOT_NB * NUBUS_SUPER_SLOT_SIZE); + (NUBUS_SUPER_SLOT_NB + 1) * NUBUS_SUPER_SLOT_SIZE); memory_region_init_io(&nubus->slot_io, obj, &nubus_slot_ops, nubus, "nubus-slots", NUBUS_SLOT_NB * NUBUS_SLOT_SIZE); - nubus->current_slot = NUBUS_FIRST_SLOT; + nubus->slot_available_mask = MAKE_64BIT_MASK(NUBUS_FIRST_SLOT, + NUBUS_SLOT_NB); } static void nubus_class_init(ObjectClass *oc, void *data) diff --git a/hw/nubus/nubus-device.c b/hw/nubus/nubus-device.c index 4e23df1280..2e96d6b4fc 100644 --- a/hw/nubus/nubus-device.c +++ b/hw/nubus/nubus-device.c @@ -161,13 +161,26 @@ static void nubus_device_realize(DeviceState *dev, Error **errp) char *name; hwaddr slot_offset; - if (nubus->current_slot < NUBUS_FIRST_SLOT || - nubus->current_slot > NUBUS_LAST_SLOT) { - error_setg(errp, "Cannot register nubus card, not enough slots"); - return; + if (nd->slot == -1) { + /* No slot specified, find first available free slot */ + int s = ctz32(nubus->slot_available_mask); + if (s != 32) { + nd->slot = s; + } else { + error_setg(errp, "Cannot register nubus card, no free slot " + "available"); + return; + } + } else { + /* Slot specified, make sure the slot is available */ + if (!(nubus->slot_available_mask & BIT(nd->slot))) { + error_setg(errp, "Cannot register nubus card, slot %d is " + "unavailable or already occupied", nd->slot); + return; + } } - nd->slot = nubus->current_slot++; + nubus->slot_available_mask &= ~BIT(nd->slot); /* Super */ slot_offset = nd->slot * NUBUS_SUPER_SLOT_SIZE; @@ -191,12 +204,18 @@ static void nubus_device_realize(DeviceState *dev, Error **errp) nubus_register_format_block(nd); } +static Property nubus_device_properties[] = { + DEFINE_PROP_INT32("slot", NubusDevice, slot, -1), + DEFINE_PROP_END_OF_LIST() +}; + static void nubus_device_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); dc->realize = nubus_device_realize; dc->bus_type = TYPE_NUBUS_BUS; + device_class_set_props(dc, nubus_device_properties); } static const TypeInfo nubus_device_type_info = { |