for (i = 0; i < MAX_SERIAL_PORTS; i++) {
if (serial_hds[i]) {
- spapr_vty_create(spapr->vio_bus, SPAPR_VTY_BASE_ADDRESS + i,
- serial_hds[i]);
+ spapr_vty_create(spapr->vio_bus, serial_hds[i]);
}
}
}
if (strcmp(nd->model, "ibmveth") == 0) {
- spapr_vlan_create(spapr->vio_bus, 0x1000 + i, nd);
+ spapr_vlan_create(spapr->vio_bus, nd);
} else {
pci_nic_init_nofail(&nd_table[i], nd->model, NULL);
}
}
for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
- spapr_vscsi_create(spapr->vio_bus, 0x2000 + i);
+ spapr_vscsi_create(spapr->vio_bus);
}
if (rma_size < (MIN_RMA_SLOF << 20)) {
return 0;
}
-void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd)
+void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd)
{
DeviceState *dev;
dev = qdev_create(&bus->bus, "spapr-vlan");
- qdev_prop_set_uint32(dev, "reg", reg);
qdev_set_nic_properties(dev, nd);
}
static Property spapr_vlan_properties[] = {
- DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev, 0x1000, 0x10000000),
+ DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev, 0x10000000),
DEFINE_NIC_PROPERTIES(VIOsPAPRVLANDevice, nicconf),
DEFINE_PROP_END_OF_LIST(),
};
rtas_st(rets, 0, 0);
}
-static int spapr_vio_check_reg(VIOsPAPRDevice *sdev)
+static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
{
- VIOsPAPRDevice *other_sdev;
+ VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
DeviceState *qdev;
- VIOsPAPRBus *sbus;
-
- sbus = DO_UPCAST(VIOsPAPRBus, bus, sdev->qdev.parent_bus);
+ VIOsPAPRDevice *other;
/*
- * Check two device aren't given clashing addresses by the user (or some
- * other mechanism). We have to open code this because we have to check
- * for matches with devices other than us.
+ * Check for a device other than the given one which is already
+ * using the requested address. We have to open code this because
+ * the given dev might already be in the list.
*/
- QTAILQ_FOREACH(qdev, &sbus->bus.children, sibling) {
- other_sdev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+ QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
+ other = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
- if (other_sdev != sdev && other_sdev->reg == sdev->reg) {
- fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
- object_get_typename(OBJECT(sdev)),
- object_get_typename(OBJECT(qdev)),
- sdev->reg);
- return -EEXIST;
+ if (other != dev && other->reg == dev->reg) {
+ return other;
}
}
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
char *id;
- int ret;
- ret = spapr_vio_check_reg(dev);
- if (ret) {
- return ret;
+ if (dev->reg != -1) {
+ /*
+ * Explicitly assigned address, just verify that no-one else
+ * is using it. other mechanism). We have to open code this
+ * rather than using spapr_vio_find_by_reg() because sdev
+ * itself is already in the list.
+ */
+ VIOsPAPRDevice *other = reg_conflict(dev);
+
+ if (other) {
+ fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
+ object_get_typename(OBJECT(qdev)),
+ object_get_typename(OBJECT(&other->qdev)),
+ dev->reg);
+ return -1;
+ }
+ } else {
+ /* Need to assign an address */
+ VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
+
+ do {
+ dev->reg = bus->next_reg++;
+ } while (reg_conflict(dev));
}
/* Don't overwrite ids assigned on the command line */
qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio");
bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
+ bus->next_reg = 0x1000;
/* hcall-vio */
spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
SPAPR_TCE_RW = 3,
};
-#define SPAPR_VTY_BASE_ADDRESS 0x30000000
-
#define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device"
#define VIO_SPAPR_DEVICE(obj) \
OBJECT_CHECK(VIOsPAPRDevice, (obj), TYPE_VIO_SPAPR_DEVICE)
VIOsPAPR_CRQ crq;
};
-#define DEFINE_SPAPR_PROPERTIES(type, field, default_reg, default_dma_window) \
- DEFINE_PROP_UINT32("reg", type, field.reg, default_reg), \
+#define DEFINE_SPAPR_PROPERTIES(type, field, default_dma_window) \
+ DEFINE_PROP_UINT32("reg", type, field.reg, -1), \
DEFINE_PROP_UINT32("dma-window", type, field.rtce_window_size, \
default_dma_window)
struct VIOsPAPRBus {
BusState bus;
+ uint32_t next_reg;
int (*init)(VIOsPAPRDevice *dev);
int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
};
VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg);
void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
-void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev);
-void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd);
-void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg);
+void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev);
+void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd);
+void spapr_vscsi_create(VIOsPAPRBus *bus);
VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus);
return 0;
}
-void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg)
+void spapr_vscsi_create(VIOsPAPRBus *bus)
{
DeviceState *dev;
dev = qdev_create(&bus->bus, "spapr-vscsi");
- qdev_prop_set_uint32(dev, "reg", reg);
qdev_init_nofail(dev);
}
}
static Property spapr_vscsi_properties[] = {
- DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev, 0x2000, 0x10000000),
+ DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev, 0x10000000),
DEFINE_PROP_END_OF_LIST(),
};
return H_SUCCESS;
}
-void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev)
+void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev)
{
DeviceState *dev;
dev = qdev_create(&bus->bus, "spapr-vty");
- qdev_prop_set_uint32(dev, "reg", reg);
qdev_prop_set_chr(dev, "chardev", chardev);
qdev_init_nofail(dev);
}
static Property spapr_vty_properties[] = {
- DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, SPAPR_VTY_BASE_ADDRESS, 0),
+ DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, 0),
DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
DEFINE_PROP_END_OF_LIST(),
};