/* * 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 * License along with this library; If not, see * . * * Author: Daniel P. Berrange */ #include #include "virterror_internal.h" #include "datatypes.h" #include "memory.h" #include "xml.h" #include "uuid.h" #include "util.h" #include "buf.h" #include "device_conf.h" #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
'domain' attribute")); goto cleanup; } if (bus && virStrToLong_ui(bus, NULL, 0, &addr->bus) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Cannot parse
'bus' attribute")); goto cleanup; } if (slot && virStrToLong_ui(slot, NULL, 0, &addr->slot) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Cannot parse
'slot' attribute")); goto cleanup; } if (function && virStrToLong_ui(function, NULL, 0, &addr->function) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Cannot parse
'function' attribute")); goto cleanup; } if (multi && ((addr->multi = virDeviceAddressPciMultiTypeFromString(multi)) <= 0)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unknown value '%s' for
'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, "
\n", includeTypeInAddr ? "type='pci' " : "", addr.domain, addr.bus, addr.slot, addr.function); return 0; } int virDevicePCIAddressEqual(virDevicePCIAddress addr1, virDevicePCIAddress addr2) { int ret = -1; if (addr1.domain == addr2.domain && addr1.bus == addr2.bus && addr1.slot == addr2.slot && addr1.function == addr2.function) { ret = 0; } return ret; }