Skip to content

Commit

Permalink
gqa-win: get_pci_info: Split logic to separate functions
Browse files Browse the repository at this point in the history
Signed-off-by: Kostiantyn Kostiuk <konstantin@daynix.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Kostiantyn Kostiuk <kkostiuk@redhat.com>
  • Loading branch information
kostyanf14 committed Jan 10, 2022
1 parent c49ca88 commit 7cc3546
Showing 1 changed file with 87 additions and 74 deletions.
161 changes: 87 additions & 74 deletions qga/commands-win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,92 @@ DEFINE_GUID(GUID_DEVINTERFACE_STORAGEPORT,
0x2accfe60L, 0xc130, 0x11d2, 0xb0, 0x82,
0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);

static void get_pci_address_for_device(GuestPCIAddress *pci,
HDEVINFO dev_info)
{
SP_DEVINFO_DATA dev_info_data;
DWORD j;
DWORD size;
bool partial_pci = false;

dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);

for (j = 0;
SetupDiEnumDeviceInfo(dev_info, j, &dev_info_data);
j++) {
DWORD addr, bus, ui_slot, type;
int func, slot;
size = sizeof(DWORD);

/*
* There is no need to allocate buffer in the next functions. The
* size is known and ULONG according to
* https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
*/
if (!SetupDiGetDeviceRegistryProperty(
dev_info, &dev_info_data, SPDRP_BUSNUMBER,
&type, (PBYTE)&bus, size, NULL)) {
debug_error("failed to get PCI bus");
bus = -1;
partial_pci = true;
}

/*
* The function retrieves the device's address. This value will be
* transformed into device function and number
*/
if (!SetupDiGetDeviceRegistryProperty(
dev_info, &dev_info_data, SPDRP_ADDRESS,
&type, (PBYTE)&addr, size, NULL)) {
debug_error("failed to get PCI address");
addr = -1;
partial_pci = true;
}

/*
* This call returns UINumber of DEVICE_CAPABILITIES structure.
* This number is typically a user-perceived slot number.
*/
if (!SetupDiGetDeviceRegistryProperty(
dev_info, &dev_info_data, SPDRP_UI_NUMBER,
&type, (PBYTE)&ui_slot, size, NULL)) {
debug_error("failed to get PCI slot");
ui_slot = -1;
partial_pci = true;
}

/*
* SetupApi gives us the same information as driver with
* IoGetDeviceProperty. According to Microsoft:
*
* FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF)
* DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF)
* SPDRP_ADDRESS is propertyAddress, so we do the same.
*
* https://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya
*/
if (partial_pci) {
pci->domain = -1;
pci->slot = -1;
pci->function = -1;
pci->bus = -1;
continue;
} else {
func = ((int)addr == -1) ? -1 : addr & 0x0000FFFF;
slot = ((int)addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF;
if ((int)ui_slot != slot) {
g_debug("mismatch with reported slot values: %d vs %d",
(int)ui_slot, slot);
}
pci->domain = 0;
pci->slot = (int)ui_slot;
pci->function = func;
pci->bus = (int)bus;
return;
}
}
}

static GuestPCIAddress *get_pci_info(int number, Error **errp)
{
HDEVINFO dev_info = INVALID_HANDLE_VALUE;
Expand All @@ -522,7 +608,6 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp)
HANDLE dev_file;
int i;
GuestPCIAddress *pci = NULL;
bool partial_pci = false;

pci = g_malloc0(sizeof(*pci));
pci->domain = -1;
Expand All @@ -545,7 +630,6 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp)
STORAGE_DEVICE_NUMBER sdn;
char *parent_dev_id = NULL;
SP_DEVINFO_DATA parent_dev_info_data;
DWORD j;
DWORD size = 0;

g_debug("getting device path");
Expand Down Expand Up @@ -672,79 +756,8 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp)
goto end;
}

for (j = 0;
SetupDiEnumDeviceInfo(parent_dev_info, j, &parent_dev_info_data);
j++) {
DWORD addr, bus, ui_slot, type;
int func, slot;
get_pci_address_for_device(pci, parent_dev_info);

/*
* There is no need to allocate buffer in the next functions. The
* size is known and ULONG according to
* https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
*/
if (!SetupDiGetDeviceRegistryProperty(
parent_dev_info, &parent_dev_info_data, SPDRP_BUSNUMBER,
&type, (PBYTE)&bus, size, NULL)) {
debug_error("failed to get PCI bus");
bus = -1;
partial_pci = true;
}

/*
* The function retrieves the device's address. This value will be
* transformed into device function and number
*/
if (!SetupDiGetDeviceRegistryProperty(
parent_dev_info, &parent_dev_info_data, SPDRP_ADDRESS,
&type, (PBYTE)&addr, size, NULL)) {
debug_error("failed to get PCI address");
addr = -1;
partial_pci = true;
}

/*
* This call returns UINumber of DEVICE_CAPABILITIES structure.
* This number is typically a user-perceived slot number.
*/
if (!SetupDiGetDeviceRegistryProperty(
parent_dev_info, &parent_dev_info_data, SPDRP_UI_NUMBER,
&type, (PBYTE)&ui_slot, size, NULL)) {
debug_error("failed to get PCI slot");
ui_slot = -1;
partial_pci = true;
}

/*
* SetupApi gives us the same information as driver with
* IoGetDeviceProperty. According to Microsoft:
*
* FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF)
* DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF)
* SPDRP_ADDRESS is propertyAddress, so we do the same.
*
* https://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya
*/
if (partial_pci) {
pci->domain = -1;
pci->slot = -1;
pci->function = -1;
pci->bus = -1;
continue;
} else {
func = ((int)addr == -1) ? -1 : addr & 0x0000FFFF;
slot = ((int)addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF;
if ((int)ui_slot != slot) {
g_debug("mismatch with reported slot values: %d vs %d",
(int)ui_slot, slot);
}
pci->domain = 0;
pci->slot = (int)ui_slot;
pci->function = func;
pci->bus = (int)bus;
break;
}
}
break;
}

Expand Down

0 comments on commit 7cc3546

Please sign in to comment.