device_conf.c 4.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * 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
17
 * License along with this library.  If not, see
18 19 20 21 22 23
 * <http://www.gnu.org/licenses/>.
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

#include <config.h>
24
#include "virerror.h"
25
#include "datatypes.h"
26
#include "viralloc.h"
27
#include "virxml.h"
28
#include "viruuid.h"
29
#include "virbuffer.h"
30
#include "device_conf.h"
31
#include "virstring.h"
32 33 34

#define VIR_FROM_THIS VIR_FROM_DEVICE

35
VIR_ENUM_IMPL(virDeviceAddressPCIMulti,
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
              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 &&
94
        ((addr->multi = virDeviceAddressPCIMultiTypeFromString(multi)) <= 0)) {
95 96 97 98 99 100 101 102 103 104 105 106 107 108
        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;

109
 cleanup:
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
    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;
}
132

133 134 135
bool
virDevicePCIAddressEqual(virDevicePCIAddress *addr1,
                         virDevicePCIAddress *addr2)
136
{
137 138 139 140 141
    if (addr1->domain == addr2->domain &&
        addr1->bus == addr2->bus &&
        addr1->slot == addr2->slot &&
        addr1->function == addr2->function) {
        return true;
142
    }
143
    return false;
144
}