2012-08-16 15:41:06 +00:00
|
|
|
/*
|
|
|
|
* device_conf.c: device XML handling
|
|
|
|
*
|
|
|
|
* Copyright (C) 2006-2012 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-08-16 15:41:06 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-08-16 15:41:06 +00:00
|
|
|
#include "datatypes.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 18:13:21 +00:00
|
|
|
#include "virxml.h"
|
2012-12-13 18:01:25 +00:00
|
|
|
#include "viruuid.h"
|
2012-12-04 12:04:07 +00:00
|
|
|
#include "virbuffer.h"
|
2012-08-16 15:41:06 +00:00
|
|
|
#include "device_conf.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2012-08-16 15:41:06 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_DEVICE
|
|
|
|
|
|
|
|
VIR_ENUM_IMPL(virDeviceAddressPciMulti,
|
|
|
|
VIR_DEVICE_ADDRESS_PCI_MULTI_LAST,
|
|
|
|
"default",
|
|
|
|
"on",
|
|
|
|
"off")
|
|
|
|
|
|
|
|
int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr)
|
|
|
|
{
|
|
|
|
/* PCI bus has 32 slots and 8 functions per slot */
|
|
|
|
if (addr->slot >= 32 || addr->function >= 8)
|
|
|
|
return 0;
|
|
|
|
return addr->domain || addr->bus || addr->slot;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virDevicePCIAddressParseXML(xmlNodePtr node,
|
|
|
|
virDevicePCIAddressPtr addr)
|
|
|
|
{
|
|
|
|
char *domain, *slot, *bus, *function, *multi;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
memset(addr, 0, sizeof(*addr));
|
|
|
|
|
|
|
|
domain = virXMLPropString(node, "domain");
|
|
|
|
bus = virXMLPropString(node, "bus");
|
|
|
|
slot = virXMLPropString(node, "slot");
|
|
|
|
function = virXMLPropString(node, "function");
|
|
|
|
multi = virXMLPropString(node, "multifunction");
|
|
|
|
|
|
|
|
if (domain &&
|
|
|
|
virStrToLong_ui(domain, NULL, 0, &addr->domain) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Cannot parse <address> 'domain' attribute"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bus &&
|
|
|
|
virStrToLong_ui(bus, NULL, 0, &addr->bus) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Cannot parse <address> 'bus' attribute"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (slot &&
|
|
|
|
virStrToLong_ui(slot, NULL, 0, &addr->slot) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Cannot parse <address> 'slot' attribute"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (function &&
|
|
|
|
virStrToLong_ui(function, NULL, 0, &addr->function) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Cannot parse <address> 'function' attribute"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (multi &&
|
|
|
|
((addr->multi = virDeviceAddressPciMultiTypeFromString(multi)) <= 0)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("Unknown value '%s' for <address> 'multifunction' attribute"),
|
|
|
|
multi);
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
}
|
|
|
|
if (!virDevicePCIAddressIsValid(addr)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Insufficient specification for PCI address"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(domain);
|
|
|
|
VIR_FREE(bus);
|
|
|
|
VIR_FREE(slot);
|
|
|
|
VIR_FREE(function);
|
|
|
|
VIR_FREE(multi);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virDevicePCIAddressFormat(virBufferPtr buf,
|
|
|
|
virDevicePCIAddress addr,
|
|
|
|
bool includeTypeInAddr)
|
|
|
|
{
|
|
|
|
virBufferAsprintf(buf, "<address %sdomain='0x%.4x' bus='0x%.2x' "
|
|
|
|
"slot='0x%.2x' function='0x%.1x'/>\n",
|
|
|
|
includeTypeInAddr ? "type='pci' " : "",
|
|
|
|
addr.domain,
|
|
|
|
addr.bus,
|
|
|
|
addr.slot,
|
|
|
|
addr.function);
|
|
|
|
return 0;
|
|
|
|
}
|
2012-08-16 15:42:14 +00:00
|
|
|
|
2012-10-11 16:34:14 +00:00
|
|
|
bool
|
|
|
|
virDevicePCIAddressEqual(virDevicePCIAddress *addr1,
|
|
|
|
virDevicePCIAddress *addr2)
|
2012-08-16 15:42:14 +00:00
|
|
|
{
|
2012-10-11 16:34:14 +00:00
|
|
|
if (addr1->domain == addr2->domain &&
|
|
|
|
addr1->bus == addr2->bus &&
|
|
|
|
addr1->slot == addr2->slot &&
|
|
|
|
addr1->function == addr2->function) {
|
|
|
|
return true;
|
2012-08-16 15:42:14 +00:00
|
|
|
}
|
2012-10-11 16:34:14 +00:00
|
|
|
return false;
|
2012-08-16 15:42:14 +00:00
|
|
|
}
|