From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41685) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5zSq-0006y4-0o for qemu-devel@nongnu.org; Fri, 19 Jun 2015 12:48:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z5zSn-0007fw-7o for qemu-devel@nongnu.org; Fri, 19 Jun 2015 12:48:23 -0400 Received: from mailhub.sw.ru ([195.214.232.25]:12501 helo=relay.sw.ru) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5zSm-0007fb-Oi for qemu-devel@nongnu.org; Fri, 19 Jun 2015 12:48:21 -0400 From: "Denis V. Lunev" Date: Fri, 19 Jun 2015 19:51:33 +0300 Message-Id: <1434732693-24127-11-git-send-email-den@openvz.org> In-Reply-To: <1434732693-24127-1-git-send-email-den@openvz.org> References: <1434732693-24127-1-git-send-email-den@openvz.org> Subject: [Qemu-devel] [PATCH 10/10] qga: added GuestPCIAddress information List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Olga Krishtal , qemu-devel@nongnu.org, "Denis V. Lunev" From: Olga Krishtal PCIAddress inforfation is obtained via SetupApi, which provides the information about address, bus, etc. We look throught entire device tree in the system and try to find device object for given volume. For this PDO SetupDiGetDeviceRegistryProperty is called, which reads PCI configuration for a given devicei if it is possible. This is the most convinient way for a userspace service. The lookup is performed for every volume available. However, this information is not mandatory for vss-provider. In order to use SetupApi we need to notify linker about it. We do not need to install additional libs, so we do not make separate configuration option to use libsetupapi.su SetupApi gives as the same information as kernel driver with IRP_MN_QUERY_INTERFACE. https://support.microsoft.com/en-us/kb/253232 Signed-off-by: Olga Krishtal Signed-off-by: Denis V. Lunev CC: Eric Blake CC: Michael Roth --- configure | 2 +- qga/commands-win32.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 222694f..bf84c5a 100755 --- a/configure +++ b/configure @@ -731,7 +731,7 @@ if test "$mingw32" = "yes" ; then sysconfdir="\${prefix}" local_statedir= confsuffix="" - libs_qga="-lws2_32 -lwinmm -lpowrprof $libs_qga" + libs_qga="-lsetupapi -lws2_32 -lwinmm -lpowrprof $libs_qga" fi werror="" diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 09f0e82..f33ba7c 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include "qga/guest-agent-core.h" #include "qga/vss-win32.h" #include "qga-qmp-commands.h" @@ -29,6 +31,10 @@ #define SHTDN_REASON_FLAG_PLANNED 0x80000000 #endif +DEFINE_GUID(GUID_DEVINTERFACE_VOLUME, + 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2, + 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); + /* multiple of 100 nanoseconds elapsed between windows baseline * (1/1/1601) and Unix Epoch (1/1/1970), accounting for leap years */ #define W32_FT_OFFSET (10000000ULL * 60 * 60 * 24 * \ @@ -811,6 +817,77 @@ done: static GuestPCIAddress *get_pci_info(char *guid, Error **errp) { + HDEVINFO dev_info; + SP_DEVINFO_DATA dev_info_data; + int i; + char dev_name[MAX_PATH]; + char *name = g_strdup(&guid[4]); + char *buffer = NULL; + if (!QueryDosDevice(name, dev_name, sizeof(dev_name)/sizeof(char))) { + error_setg_win32(errp, GetLastError(), "failed to get dos device name"); + g_free(name); + return NULL; + } + g_free(name); + + dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, 0, 0, + DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (dev_info == INVALID_HANDLE_VALUE) { + error_setg_win32(errp, GetLastError(), "failed to get devices tree"); + return NULL; + } + dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); + for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) { + DWORD data, addr, bus, slot, func; + GuestPCIAddress *pci; + DWORD size = 0; + + while (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, + SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, + &data, (PBYTE)buffer, size, &size)) { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + if (buffer) { + g_free(buffer); + } + buffer = g_malloc0(sizeof(char)*(size*2)); + } else { + error_setg_win32(errp, GetLastError(), + "failed to get device name"); + goto out; + } + } + + if (g_strcmp0(buffer, dev_name)) { + continue; + } + + if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, + SPDRP_BUSNUMBER, &data, (PBYTE)&bus, size, &size)) { + goto out; + } + + if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, + SPDRP_ADDRESS, &data, (PBYTE)&addr, size, &size)) { + goto out; + } + + slot = (addr >> 16) & 0xFFFF; + func = addr & 0xFFFF; + pci = g_malloc0(sizeof(*pci)); + pci->domain = addr; + pci->slot = slot; + pci->function = func; + pci->bus = bus; + + if (buffer) { + g_free(buffer); + } + return pci; + } +out: + if (buffer) { + g_free(buffer); + } return NULL; } -- 1.9.1