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>
+  ...
+

Device leases

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);