int scan()

in SDAccel/userspace/src/scan.h [243:447]


    int scan(bool print) {
        pci_device device;
        int domain = 0;
        int bus = 0, dev = 0, func = 0;
        std::string dirname;
        dirname = ROOT_DIR;
        dirname += "/devices/";

#ifdef INTERNAL_TESTING
        DIR *dir;
        struct dirent *entry;
        if ( !print_system_info() ) {
            std::cout << "Unable to determine system info " << std::endl;
        }
        std::cout << "--- " << std::endl;
        if ( !print_paths() ) {
            std::cout << "Unable to determine PATH/LD_LIBRARY_PATH info " << std::endl;
        }
        std::cout << "--- " << std::endl;

        dir = opendir(dirname.c_str());
        if ( !dir ) {
            std::cout << "Cannot open " << dirname << std::endl;
            return -1;
        }

        while ((entry = readdir(dir))) {
            if ( entry->d_name[0] == '.')
                continue;

            if ( sscanf(entry->d_name, "%x:%x:%x.%d", &domain, &bus, &dev, &func) < 4) {
                std::cout << "scan: Couldn't parse entry name " << entry->d_name << std::endl;
            }

            std::string subdir = dirname + entry->d_name;
            std::string subdir2 = dirname + entry->d_name;

            //On Pegasus: 0 is userPF & 2 is mgmtPG.
            //On Pegasus & F1: userPF is for Device 1d0f:1042
            //if (func == 0 || func == 2) {
            //}
            //Using device id to only find userPF info
            device.domain = domain;
            device.bus = bus;
            device.dev = dev;
            device.func = func;
            device.vendor_id = get_val_int(subdir, "vendor");
            device.device_id = get_val_int(subdir, "device");
            device.subsystem_id = get_val_int(subdir, "subsystem_device");
            if (device.vendor_id != XILINX_ID)
                continue;
            if (device.device_id != AWS_UserPF_DEVICE_ID && device.device_id != AWS_MgmtPF_DEVICE_ID && device.device_id != AWS_UserPF_DEVICE_ID_SDx)
                continue;
            if ( device.func != 0 && device.func != 2)
                continue;
            //std::cout << "scan: Xilinx AWS device entry name " << entry->d_name << std::endl;

            //Get the driver name.
            char driverName[DRIVER_BUF_SIZE];
            memset(driverName, 0, DRIVER_BUF_SIZE);
            subdir += "/driver";
            int err = readlink(subdir.c_str(), driverName, DRIVER_BUF_SIZE);
            if ( err < 0 ) {
                add_device(device);
                continue;
            }
            if ( err >= DRIVER_BUF_SIZE ) {
                std::cout << "Driver name is too big " << std::endl;
                return -1;
            }

            device.driver_name = driverName;
            size_t found = device.driver_name.find_last_of("/");
            if ( found != std::string::npos ) {
                device.driver_name = device.driver_name.substr(found + 1);
            }

            //Get driver version
            subdir += "/module/";
            std::string version = get_val_string(subdir, "version");
            version.erase(std::remove(version.begin(), version.end(), '\n'), version.end());
            device.driver_version = version;

            if(device.func == 2) {//mgmtPF on Pegasus; mgmtPF not visible on AWS F1
                device.instance = get_val_int(subdir2, "instance");
            } else if (device.func == 0)  {//userPF on Pegasus (AWS)
                std::string drm_dir = subdir2;
                drm_dir += "/drm";
                device.instance = get_render_value(drm_dir);
            }
            device.device_name = entry->d_name;

            if ( !add_device(device) )
                return -1;

        }
        //std::cout << "scan: Create device list" << std::endl;
        add_to_device_list();

        if(print)
            return print_pci_info() ? 0 : -1;
        else
            return 0;
#else
        uint16_t vendor_id = 0, device_id = 0; // only used without INTERNAL_TESTING

        if (fpga_mgmt_init() || fpga_pci_init() ) {
            std::cout << "ERROR: xclProbe-scan failed to initialized fpga libraries" << std::endl;
            return -1;
        }
        fpga_slot_spec spec_array[16];
        std::memset(spec_array, 0, sizeof(fpga_slot_spec) * 16);
        if (fpga_pci_get_all_slot_specs(spec_array, 16)) {
            std::cout << "ERROR: xclProbe-scan failed at fpga_pci_get_all_slot_specs" << std::endl;
            return -1;
        }

        for (unsigned short i = 0; i < 16; i++) {
            if (spec_array[i].map[FPGA_APP_PF].vendor_id == 0)
                break;

            domain = spec_array[i].map[FPGA_APP_PF].domain;
            bus = spec_array[i].map[FPGA_APP_PF].bus;
            dev = spec_array[i].map[FPGA_APP_PF].dev;
            func = spec_array[i].map[FPGA_APP_PF].func;
            vendor_id = spec_array[i].map[FPGA_APP_PF].vendor_id;
            device_id = spec_array[i].map[FPGA_APP_PF].device_id;

            //On Pegasus: func=0 is userPF & func=2 is mgmtPG.
            //On Pegasus & F1: userPF is for Device 1d0f:1042
            if (vendor_id != XILINX_ID)
                continue;
            if (device_id != AWS_UserPF_DEVICE_ID && device_id != AWS_MgmtPF_DEVICE_ID && device_id != AWS_UserPF_DEVICE_ID_SDx)
                continue;
            if (func != 0) //userPF func == 0; mgmtPF not visible on AWS F1
                continue;

            //userPF func == 0; mgmtPF not visible on AWS F1
            std::stringstream domain_str;
            std::stringstream bus_str;
            std::stringstream dev_str;
            //Note: Below works with stringstream only for integers and not for uint8, etc.
            domain_str << std::setw(4) << std::setfill('0') << domain;
            bus_str << std::setw(2) << std::setfill('0') << std::hex << bus;
            dev_str << std::setw(2) << std::setfill('0') << std::hex << dev;
            std::string func_str = std::to_string(func);//stringstream is giving minimum of two chars

            device.device_name = domain_str.str() + ":" + bus_str.str() + ":" + dev_str.str() + "." + func_str + "\0";
            std::string subdir2 = dirname + device.device_name;

            device.domain = domain;
            device.bus = bus;
            device.dev = dev;
            device.func = func;
            device.vendor_id = vendor_id;
            device.device_id = device_id;
            device.subsystem_id = spec_array[i].map[FPGA_APP_PF].subsystem_device_id;

            //Get the driver name.
            char driverName[DRIVER_BUF_SIZE];
            memset(driverName, 0, DRIVER_BUF_SIZE);
            std::string driver_dir = subdir2;
            driver_dir += "/driver";
            int err = readlink(driver_dir.c_str(), driverName, DRIVER_BUF_SIZE);
            if ( err < 0) {
                add_device(device);
                continue;
            }
            if (err >= DRIVER_BUF_SIZE) {
                std::cout << "ERROR: Driver name is too big " << std::endl;
                return -1;
            }

            device.driver_name = driverName;
            size_t found = device.driver_name.find_last_of("/");
            if ( found != std::string::npos) {
                device.driver_name = device.driver_name.substr(found + 1);
            }

            //Get driver version
            std::string module_dir = driver_dir;
            module_dir += "/module/";
            std::string version = get_val_string(module_dir, "version");
            version.erase(std::remove(version.begin(), version.end(), '\n'), version.end());
            device.driver_version = version;

            if (func == 0)  {//userPF on Pegasus & F1
                std::string drm_dir = subdir2;
                drm_dir += "/drm";
                device.instance = get_render_value(drm_dir);
            }

            if (!add_device(device))
                return -1;

        }
        //std::cout << "scan: Create device list" << std::endl;
        add_to_device_list();

        if(print)
            return print_f1_pci_info() ? 0 : -1;
        else
            return 0;
#endif
    }