Add USB companion controllers support

Companion controllers take an extra 'master' attribute to associate
them.

Also add tests for this
This commit is contained in:
Marc-André Lureau 2011-09-02 22:03:51 +08:00 committed by Daniel Veillard
parent 22c0d433ab
commit f3ce59621f
8 changed files with 140 additions and 1 deletions

View File

@ -1245,6 +1245,28 @@
sub-element. sub-element.
</p> </p>
<p>
USB companion controllers have an optional
sub-element <code>&lt;master&gt;</code> 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 <code>index</code> value should be equal.
</p>
<pre>
...
&lt;devices&gt;
&lt;controller type='usb' index='0' model='ich9-ehci1'&gt;
&lt;address type='pci' domain='0' bus='0' slot='4' function='7'/&gt;
&lt;/controller&gt;
&lt;controller type='usb' index='0' model='ich9-uhci1'&gt;
&lt;master startport='0'/&gt;
&lt;address type='pci' domain='0' bus='0' slot='4' function='0'/&gt;
&lt;/controller&gt;
...
&lt;/devices&gt;
...</pre>
<h4><a name="elementsLease">Device leases</a></h4> <h4><a name="elementsLease">Device leases</a></h4>
<p> <p>

View File

@ -923,6 +923,9 @@
</choice> </choice>
</attribute> </attribute>
</optional> </optional>
<optional>
<ref name="usbmaster"/>
</optional>
<optional> <optional>
<ref name="address"/> <ref name="address"/>
</optional> </optional>
@ -2379,6 +2382,15 @@
</element> </element>
</define> </define>
<define name="usbmaster">
<element name="master">
<attribute name="startport">
<ref name="usbAddr"/>
</attribute>
<empty/>
</element>
</define>
<define name="filterref-node-attributes"> <define name="filterref-node-attributes">
<attribute name="filter"> <attribute name="filter">
<data type="NCName"/> <data type="NCName"/>

View File

@ -1556,6 +1556,11 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
virBufferAsprintf(buf, " <alias name='%s'/>\n", info->alias); virBufferAsprintf(buf, " <alias name='%s'/>\n", info->alias);
} }
if (info->mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
virBufferAsprintf(buf, " <master startport='%d'/>\n",
info->master.usb.startport);
}
if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
return 0; return 0;
@ -1833,6 +1838,31 @@ cleanup:
return ret; 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 <master> 'startport' attribute"));
goto cleanup;
}
ret = 0;
cleanup:
VIR_FREE(startport);
return ret;
}
/* Parse the XML definition for a device address /* Parse the XML definition for a device address
* @param node XML nodeset to parse for device address definition * @param node XML nodeset to parse for device address definition
*/ */
@ -1843,6 +1873,7 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
{ {
xmlNodePtr cur; xmlNodePtr cur;
xmlNodePtr address = NULL; xmlNodePtr address = NULL;
xmlNodePtr master = NULL;
xmlNodePtr alias = NULL; xmlNodePtr alias = NULL;
char *type = NULL; char *type = NULL;
int ret = -1; int ret = -1;
@ -1859,6 +1890,9 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
} else if (address == NULL && } else if (address == NULL &&
xmlStrEqual(cur->name, BAD_CAST "address")) { xmlStrEqual(cur->name, BAD_CAST "address")) {
address = cur; address = cur;
} else if (master == NULL &&
xmlStrEqual(cur->name, BAD_CAST "master")) {
master = cur;
} }
} }
cur = cur->next; cur = cur->next;
@ -1867,6 +1901,12 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
if (alias) if (alias)
info->alias = virXMLPropString(alias, "name"); 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) if (!address)
return 0; return 0;

View File

@ -113,6 +113,19 @@ struct _virDomainDeviceUSBAddress {
unsigned int port; 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 struct _virDomainDeviceInfo virDomainDeviceInfo;
typedef virDomainDeviceInfo *virDomainDeviceInfoPtr; typedef virDomainDeviceInfo *virDomainDeviceInfoPtr;
struct _virDomainDeviceInfo { struct _virDomainDeviceInfo {
@ -125,6 +138,10 @@ struct _virDomainDeviceInfo {
virDomainDeviceCcidAddress ccid; virDomainDeviceCcidAddress ccid;
virDomainDeviceUSBAddress usb; virDomainDeviceUSBAddress usb;
} addr; } addr;
int mastertype;
union {
virDomainDeviceUSBMaster usb;
} master;
}; };
typedef struct _virDomainLeaseDef virDomainLeaseDef; typedef struct _virDomainLeaseDef virDomainLeaseDef;

View File

@ -1767,7 +1767,16 @@ qemuBuildUSBControllerDevStr(virDomainControllerDefPtr def,
return -1; 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; return 0;
} }

View File

@ -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

View File

@ -0,0 +1,30 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory>219136</memory>
<currentMemory>219200</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<devices>
<emulator>/usr/bin/qemu</emulator>
<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>
<controller type='usb' index='0' model='ich9-uhci2'>
<master startport='2'/>
<address type='pci' domain='0' bus='0' slot='4' function='1'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci3'>
<master startport='4'/>
<address type='pci' domain='0' bus='0' slot='4' function='2'/>
</controller>
<memballoon model='virtio'/>
</devices>
</domain>

View File

@ -498,6 +498,9 @@ mymain(void)
QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1); QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1);
DO_TEST("input-usbmouse-addr", false, DO_TEST("input-usbmouse-addr", false,
QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); 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); DO_TEST("smbios", false, QEMU_CAPS_SMBIOS_TYPE);