diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a5246db38f..95d2ff22b8 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -200,7 +200,8 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST, "ccid", "usb", "spapr-vio", - "virtio-s390") + "virtio-s390", + "ccw") VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST, "block", @@ -2203,6 +2204,13 @@ void virDomainObjListRemove(virDomainObjListPtr doms, virObjectUnlock(doms); } +static int +virDomainDeviceCCWAddressIsValid(virDomainDeviceCCWAddressPtr addr) +{ + return addr->cssid <= VIR_DOMAIN_DEVICE_CCW_MAX_CSSID && + addr->ssid <= VIR_DOMAIN_DEVICE_CCW_MAX_SSID && + addr->devno <= VIR_DOMAIN_DEVICE_CCW_MAX_DEVNO; +} int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, int type) @@ -2217,6 +2225,12 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE: return 1; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390: + return 1; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: + return virDomainDeviceCCWAddressIsValid(&info->addr.ccw); + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB: return 1; } @@ -2298,6 +2312,19 @@ static int virDomainDeviceInfoClearPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUS return 0; } +static int +virDomainDeviceInfoClearCCWAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr device ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, + void *opaque ATTRIBUTE_UNUSED) +{ + if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + memset(&info->addr, 0, sizeof(info->addr)); + info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE; + } + return 0; +} + int virDomainDeviceInfoIterate(virDomainDefPtr def, virDomainDeviceInfoCallback cb, void *opaque) @@ -2447,6 +2474,11 @@ void virDomainDefClearPCIAddresses(virDomainDefPtr def) virDomainDeviceInfoIterate(def, virDomainDeviceInfoClearPCIAddress, NULL); } +void virDomainDefClearCCWAddresses(virDomainDefPtr def) +{ + virDomainDeviceInfoIterate(def, virDomainDeviceInfoClearCCWAddress, NULL); +} + void virDomainDefClearDeviceAliases(virDomainDefPtr def) { virDomainDeviceInfoIterate(def, virDomainDeviceInfoClearAlias, NULL); @@ -2548,6 +2580,13 @@ virDomainDeviceInfoFormat(virBufferPtr buf, virBufferAsprintf(buf, " reg='0x%llx'", info->addr.spaprvio.reg); break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: + virBufferAsprintf(buf, " cssid='0x%x' ssid='0x%x' devno='0x%04x'", + info->addr.ccw.cssid, + info->addr.ccw.ssid, + info->addr.ccw.devno); + break; + default: virReportError(VIR_ERR_INTERNAL_ERROR, _("unknown address type '%d'"), info->type); @@ -2657,6 +2696,64 @@ cleanup: return ret; } +static int +virDomainDeviceCCWAddressParseXML(xmlNodePtr node, + virDomainDeviceCCWAddressPtr addr) +{ + int ret = -1; + char *cssid; + char *ssid; + char *devno; + + memset(addr, 0, sizeof(*addr)); + + cssid = virXMLPropString(node, "cssid"); + ssid = virXMLPropString(node, "ssid"); + devno = virXMLPropString(node, "devno"); + + if (cssid && ssid && devno) { + if (cssid && + virStrToLong_ui(cssid, NULL, 0, &addr->cssid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse
'cssid' attribute")); + goto cleanup; + } + if (ssid && + virStrToLong_ui(ssid, NULL, 0, &addr->ssid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse 'ssid' attribute")); + goto cleanup; + } + if (devno && + virStrToLong_ui(devno, NULL, 0, &addr->devno) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse 'devno' attribute")); + goto cleanup; + } + if (!virDomainDeviceCCWAddressIsValid(addr)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid specification for virtio ccw" + " address: cssid='%s' ssid='%s' devno='%s'"), + cssid, ssid, devno); + goto cleanup; + } + addr->assigned = true; + } else if (cssid || ssid || devno) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Invalid partial specification for virtio ccw" + " address")); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(cssid); + VIR_FREE(ssid); + VIR_FREE(devno); + return ret; +} + static int virDomainDeviceCcidAddressParseXML(xmlNodePtr node, virDomainDeviceCcidAddressPtr addr) @@ -2950,6 +3047,12 @@ virDomainDeviceInfoParseXML(xmlNodePtr node, goto cleanup; break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: + if (virDomainDeviceCCWAddressParseXML + (address, &info->addr.ccw) < 0) + goto cleanup; + break; + default: /* Should not happen */ virReportError(VIR_ERR_INTERNAL_ERROR, @@ -4821,6 +4924,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO && + def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390 && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -5418,6 +5522,7 @@ virDomainNetDefParseXML(virCapsPtr caps, * them we should make sure address type is correct */ if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO && + def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390 && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f32244100d..0fe43c5869 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -195,6 +195,7 @@ enum virDomainDeviceAddressType { VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST }; @@ -224,6 +225,19 @@ struct _virDomainDeviceVirtioSerialAddress { unsigned int port; }; +# define VIR_DOMAIN_DEVICE_CCW_MAX_CSSID 254 +# define VIR_DOMAIN_DEVICE_CCW_MAX_SSID 3 +# define VIR_DOMAIN_DEVICE_CCW_MAX_DEVNO 65535 + +typedef struct _virDomainDeviceCCWAddress virDomainDeviceCCWAddress; +typedef virDomainDeviceCCWAddress *virDomainDeviceCCWAddressPtr; +struct _virDomainDeviceCCWAddress { + unsigned int cssid; + unsigned int ssid; + unsigned int devno; + bool assigned; +}; + typedef struct _virDomainDeviceCcidAddress virDomainDeviceCcidAddress; typedef virDomainDeviceCcidAddress *virDomainDeviceCcidAddressPtr; struct _virDomainDeviceCcidAddress { @@ -274,6 +288,7 @@ struct _virDomainDeviceInfo { virDomainDeviceCcidAddress ccid; virDomainDeviceUSBAddress usb; virDomainDeviceSpaprVioAddress spaprvio; + virDomainDeviceCCWAddress ccw; } addr; int mastertype; union { @@ -2016,6 +2031,7 @@ int virDomainDeviceInfoCopy(virDomainDeviceInfoPtr dst, virDomainDeviceInfoPtr src); void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info); void virDomainDefClearPCIAddresses(virDomainDefPtr def); +void virDomainDefClearCCWAddresses(virDomainDefPtr def); void virDomainDefClearDeviceAliases(virDomainDefPtr def); typedef int (*virDomainDeviceInfoCallback)(virDomainDefPtr def, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fbd540a8b8..5cad990076 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -110,6 +110,7 @@ virDomainCpuPlacementModeTypeToString; virDomainDefAddImplicitControllers; virDomainDefAddSecurityLabelDef; virDomainDefCheckABIStability; +virDomainDefClearCCWAddresses; virDomainDefClearDeviceAliases; virDomainDefClearPCIAddresses; virDomainDefCompatibleDevice;