in sdk/userspace/fpga_libs/fpga_dma/fpga_dma_utils.c [178:287]
int fpga_pci_get_dma_device_num(enum fpga_dma_driver which_driver,
int slot_id, int *device_num)
{
int rc;
char dbdf[16];
char path[64];
int _device_num;
struct dirent *entry;
char real_path[MAX_FD_LEN];
char *possible_dbdf = NULL;
struct fpga_pci_resource_map resource;
char sysfs_path_instance[MAX_FD_LEN + sizeof(entry->d_name) + sizeof(path)];
const struct dma_opts_s *dma_opts = fpga_dma_get_dma_opts(which_driver);
fail_on_with_code(!dma_opts, err, rc, -EINVAL, "invalid DMA driver");
rc = snprintf(path, sizeof(path), "/sys/class/%s", dma_opts->drv_name);
fail_on_with_code(rc < 1, err, rc, FPGA_ERR_SOFTWARE_PROBLEM,
"snprintf failed");
/* This call must be before the lock, because the call holds the lock. */
rc = fpga_pci_get_resource_map(slot_id, FPGA_APP_PF, &resource);
fail_on(rc, err, "Could not get resource map");
rc = snprintf(dbdf,
sizeof(dbdf),
PCI_DEV_FMT,
resource.domain,
resource.bus,
resource.dev,
resource.func);
fail_on_with_code(rc < 1, err, rc, FPGA_ERR_SOFTWARE_PROBLEM,
"Could not record DBDF");
DIR *dirp = opendir(path);
fail_on_with_code(!dirp, err, rc, FPGA_ERR_SOFTWARE_PROBLEM,
"opendir failed for path=%s", path);
#if defined(FPGA_PCI_USE_READDIR_R)
struct dirent entry_stack, *result;
entry = &entry_stack;
memset(entry, 0, sizeof(struct dirent));
#else
/**
* Protect calls to readdir with a mutex because multiple threads may call
* this function, which always reads from the same directory. The man page
* for readdir says the POSIX spec does not require threadsafety.
*/
fpga_acquire_readdir_lock();
#endif
while (true) {
/* reset so that the loop termination detection below works */
_device_num = -1;
#if defined(FPGA_PCI_USE_READDIR_R)
memset(entry, 0, sizeof(struct dirent));
readdir_r(dirp, entry, &result);
if (result == NULL) {
/** No more directories */
break;
}
#else
entry = readdir(dirp);
if (entry == NULL) {
/** No more directories */
break;
}
#endif
rc = (*dma_opts->get_dev_number_f)(entry->d_name, &_device_num);
if (rc != 0) {
continue;
}
rc = snprintf(sysfs_path_instance, sizeof(sysfs_path_instance),
"%s/%s/device", path, entry->d_name);
fail_on_with_code(rc < 2, err_unlock, rc, FPGA_ERR_SOFTWARE_PROBLEM,
"snprintf failed to build sysfs path");
possible_dbdf = realpath(sysfs_path_instance, real_path);
if (possible_dbdf == NULL) {
continue;
}
possible_dbdf = basename(real_path);
if (strncmp(possible_dbdf, dbdf, 12) == 0) {
break; /* found device */
}
/* continue... */
}
#if !defined(FPGA_PCI_USE_READDIR_R)
fpga_release_readdir_lock();
#endif
fail_on_with_code(_device_num == -1, err, rc, FPGA_ERR_PCI_MISSING,
"Unable to find device num");
closedir(dirp);
*device_num = _device_num;
errno = 0;
return 0;
err_unlock:
#if !defined(FPGA_PCI_USE_READDIR_R)
fpga_release_readdir_lock();
#endif
err:
if (dirp) {
closedir(dirp);
}
errno = 0;
return rc;
}