From f3ce59621f0c6fca635da5f676e88db34f4f2224 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?=
Date: Fri, 2 Sep 2011 22:03:51 +0800
Subject: [PATCH] Add USB companion controllers support
Companion controllers take an extra 'master' attribute to associate
them.
Also add tests for this
---
docs/formatdomain.html.in | 22 ++++++++++
docs/schemas/domain.rng | 12 ++++++
src/conf/domain_conf.c | 40 +++++++++++++++++++
src/conf/domain_conf.h | 17 ++++++++
src/qemu/qemu_command.c | 11 ++++-
.../qemuxml2argv-usb-ich9-companion.args | 6 +++
.../qemuxml2argv-usb-ich9-companion.xml | 30 ++++++++++++++
tests/qemuxml2argvtest.c | 3 ++
8 files changed, 140 insertions(+), 1 deletion(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index ee9709436a..8bd1433724 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1245,6 +1245,28 @@
sub-element.
+
+ USB companion controllers have an optional
+ sub-element <master>
to specify the exact
+ relationship of the companion to its master controller.
+ A companion controller is on the same bus as its master, so
+ the companion index
value should be equal.
+
+
+
+ ...
+ <devices>
+ <controller type='usb' index='0' model='ich9-ehci1'>
+ <address type='pci' domain='0' bus='0' slot='4' function='7'/>
+ </controller>
+ <controller type='usb' index='0' model='ich9-uhci1'>
+ <master startport='0'/>
+ <address type='pci' domain='0' bus='0' slot='4' function='0'/>
+ </controller>
+ ...
+ </devices>
+ ...
+
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 0c72a9f28a..a4b5575c27 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -923,6 +923,9 @@
+
+
+
@@ -2379,6 +2382,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index ef9fb53401..73a7772fd6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1556,6 +1556,11 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
virBufferAsprintf(buf, " \n", info->alias);
}
+ if (info->mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
+ virBufferAsprintf(buf, " \n",
+ info->master.usb.startport);
+ }
+
if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
return 0;
@@ -1833,6 +1838,31 @@ cleanup:
return ret;
}
+static int
+virDomainDeviceUSBMasterParseXML(xmlNodePtr node,
+ virDomainDeviceUSBMasterPtr master)
+{
+ char *startport;
+ int ret = -1;
+
+ memset(master, 0, sizeof(*master));
+
+ startport = virXMLPropString(node, "startport");
+
+ if (startport &&
+ virStrToLong_ui(startport, NULL, 10, &master->startport) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot parse 'startport' attribute"));
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(startport);
+ return ret;
+}
+
/* Parse the XML definition for a device address
* @param node XML nodeset to parse for device address definition
*/
@@ -1843,6 +1873,7 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
{
xmlNodePtr cur;
xmlNodePtr address = NULL;
+ xmlNodePtr master = NULL;
xmlNodePtr alias = NULL;
char *type = NULL;
int ret = -1;
@@ -1859,6 +1890,9 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
} else if (address == NULL &&
xmlStrEqual(cur->name, BAD_CAST "address")) {
address = cur;
+ } else if (master == NULL &&
+ xmlStrEqual(cur->name, BAD_CAST "master")) {
+ master = cur;
}
}
cur = cur->next;
@@ -1867,6 +1901,12 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
if (alias)
info->alias = virXMLPropString(alias, "name");
+ if (master) {
+ info->mastertype = VIR_DOMAIN_CONTROLLER_MASTER_USB;
+ if (virDomainDeviceUSBMasterParseXML(master, &info->master.usb) < 0)
+ goto cleanup;
+ }
+
if (!address)
return 0;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 60a296a42d..09c13383b7 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -113,6 +113,19 @@ struct _virDomainDeviceUSBAddress {
unsigned int port;
};
+enum virDomainControllerMaster {
+ VIR_DOMAIN_CONTROLLER_MASTER_NONE,
+ VIR_DOMAIN_CONTROLLER_MASTER_USB,
+
+ VIR_DOMAIN_CONTROLLER_MASTER_LAST
+};
+
+typedef struct _virDomainDeviceUSBMaster virDomainDeviceUSBMaster;
+typedef virDomainDeviceUSBMaster *virDomainDeviceUSBMasterPtr;
+struct _virDomainDeviceUSBMaster {
+ unsigned int startport;
+};
+
typedef struct _virDomainDeviceInfo virDomainDeviceInfo;
typedef virDomainDeviceInfo *virDomainDeviceInfoPtr;
struct _virDomainDeviceInfo {
@@ -125,6 +138,10 @@ struct _virDomainDeviceInfo {
virDomainDeviceCcidAddress ccid;
virDomainDeviceUSBAddress usb;
} addr;
+ int mastertype;
+ union {
+ virDomainDeviceUSBMaster usb;
+ } master;
};
typedef struct _virDomainLeaseDef virDomainLeaseDef;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index c8e76ada8e..e8d6068508 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1767,7 +1767,16 @@ qemuBuildUSBControllerDevStr(virDomainControllerDefPtr def,
return -1;
}
- virBufferAsprintf(buf, "%s,id=usb%d", smodel, def->idx);
+ virBufferAsprintf(buf, "%s", smodel);
+
+ if (def->info.mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
+ virBufferAsprintf(buf, ",masterbus=usb%d.0", def->idx);
+ virBufferAsprintf(buf, ",firstport=%d", def->info.master.usb.startport);
+ } else {
+ virBufferAsprintf(buf, ",id=usb%d", def->idx);
+ }
+
+
return 0;
}
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args
new file mode 100644
index 0000000000..b37dbf6b77
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args
@@ -0,0 +1,6 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c \
+-device ich9-usb-ehci1,id=usb0,bus=pci.0,multifunction=on,addr=0x4.0x7 \
+-device ich9-usb-uhci1,masterbus=usb0.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4.0x0 \
+-device ich9-usb-uhci2,masterbus=usb0.0,firstport=2,bus=pci.0,multifunction=on,addr=0x4.0x1 \
+-device ich9-usb-uhci3,masterbus=usb0.0,firstport=4,bus=pci.0,multifunction=on,addr=0x4.0x2 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,multifunction=on,addr=0x3.0x0
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml
new file mode 100644
index 0000000000..05a6adf6ef
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml
@@ -0,0 +1,30 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219200
+ 1
+
+ hvm
+
+
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 9d3409e58f..f44536b882 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -498,6 +498,9 @@ mymain(void)
QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1);
DO_TEST("input-usbmouse-addr", false,
QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
+ DO_TEST("usb-ich9-companion", false,
+ QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
+ QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1);
DO_TEST("smbios", false, QEMU_CAPS_SMBIOS_TYPE);