<ref name="pciFunc"/>
</attribute>
</define>
+ <define name="driveaddress">
+ <optional>
+ <attribute name="controller">
+ <ref name="driveController"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="bus">
+ <ref name="driveBus"/>
+ </attribute>
+ </optional>
+ <attribute name="unit">
+ <ref name="driveUnit"/>
+ </attribute>
+ </define>
<!--
Devices attached to a domain.
-->
</attribute>
<ref name="pciaddress"/>
</group>
+ <group>
+ <attribute name="type">
+ <value>drive</value>
+ </attribute>
+ <ref name="driveaddress"/>
+ </group>
</choice>
</element>
</define>
<param name="pattern">(0x)?[0-7]</param>
</data>
</define>
+ <define name="driveController">
+ <data type="string">
+ <param name="pattern">[0-9]{1,2}</param>
+ </data>
+ </define>
+ <define name="driveBus">
+ <data type="string">
+ <param name="pattern">[0-9]{1,2}</param>
+ </data>
+ </define>
+ <define name="driveUnit">
+ <data type="string">
+ <param name="pattern">[0-9]{1,2}</param>
+ </data>
+ </define>
<define name="featureName">
<data type="string">
<param name='pattern'>[a-zA-Z0-9\-_]+</param>
VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
"none",
- "pci")
+ "pci",
+ "drive");
VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
"block",
switch (info->type) {
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
return virDomainDevicePCIAddressIsValid(&info->addr.pci);
+
+ case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
+ return virDomainDeviceDriveAddressIsValid(&info->addr.drive);
}
return 0;
}
+int virDomainDeviceDriveAddressIsValid(virDomainDeviceDriveAddressPtr addr ATTRIBUTE_UNUSED)
+{
+ /*return addr->controller || addr->bus || addr->unit;*/
+ return 1; /* 0 is valid for all fields, so any successfully parsed addr is valid */
+}
+
+
int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info)
{
if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
info->addr.pci.function);
break;
+ case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
+ virBufferVSprintf(buf, " controller='%d' bus='%d' unit='%d'",
+ info->addr.drive.controller,
+ info->addr.drive.bus,
+ info->addr.drive.unit);
+ break;
+
default:
virDomainReportError(NULL, VIR_ERR_INTERNAL_ERROR,
_("unknown address type '%d'"), info->type);
}
+int virDomainDeviceDriveAddressEqual(virDomainDeviceDriveAddressPtr a,
+ virDomainDeviceDriveAddressPtr b)
+{
+ if (a->controller == b->controller &&
+ a->bus == b->bus &&
+ a->unit == b->unit)
+ return 1;
+
+ return 0;
+}
+
+
static int
virDomainDevicePCIAddressParseXML(virConnectPtr conn,
xmlNodePtr node,
}
+static int
+virDomainDeviceDriveAddressParseXML(virConnectPtr conn,
+ xmlNodePtr node,
+ virDomainDeviceDriveAddressPtr addr)
+{
+ char *bus, *unit, *controller;
+ int ret = -1;
+
+ memset(addr, 0, sizeof(*addr));
+
+ controller = virXMLPropString(node, "controller");
+ bus = virXMLPropString(node, "bus");
+ unit = virXMLPropString(node, "unit");
+
+ if (controller &&
+ virStrToLong_ui(controller, NULL, 10, &addr->controller) < 0) {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot parse <address> 'controller' attribute"));
+ goto cleanup;
+ }
+
+ if (bus &&
+ virStrToLong_ui(bus, NULL, 10, &addr->bus) < 0) {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot parse <address> 'bus' attribute"));
+ goto cleanup;
+ }
+
+ if (unit &&
+ virStrToLong_ui(unit, NULL, 10, &addr->unit) < 0) {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot parse <address> 'unit' attribute"));
+ goto cleanup;
+ }
+
+ if (!virDomainDeviceDriveAddressIsValid(addr)) {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Insufficient specification for drive address"));
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(controller);
+ VIR_FREE(bus);
+ VIR_FREE(unit);
+ return ret;
+}
+
/* Parse the XML definition for a device address
* @param node XML nodeset to parse for device address definition
*/
goto cleanup;
break;
+ case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
+ if (virDomainDeviceDriveAddressParseXML(conn, node, &info->addr.drive) < 0)
+ goto cleanup;
+ break;
+
default:
/* Should not happen */
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
enum virDomainDeviceAddressType {
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE,
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI,
+ VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE,
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST
};
unsigned int function;
};
+typedef struct _virDomainDeviceDriveAddress virDomainDeviceDriveAddress;
+typedef virDomainDeviceDriveAddress *virDomainDeviceDriveAddressPtr;
+struct _virDomainDeviceDriveAddress {
+ unsigned int controller;
+ unsigned int bus;
+ unsigned int unit;
+};
+
typedef struct _virDomainDeviceInfo virDomainDeviceInfo;
typedef virDomainDeviceInfo *virDomainDeviceInfoPtr;
struct _virDomainDeviceInfo {
int type;
union {
virDomainDevicePCIAddress pci;
+ virDomainDeviceDriveAddress drive;
} addr;
};
void virDomainDeviceDefFree(virDomainDeviceDefPtr def);
int virDomainDevicePCIAddressEqual(virDomainDevicePCIAddressPtr a,
virDomainDevicePCIAddressPtr b);
+int virDomainDeviceDriveAddressEqual(virDomainDeviceDriveAddressPtr a,
+ virDomainDeviceDriveAddressPtr b);
int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
int type);
int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr);
+int virDomainDeviceDriveAddressIsValid(virDomainDeviceDriveAddressPtr addr);
int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info);
void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info);
void virDomainDefFree(virDomainDefPtr vm);