#include "gpu.h" #include "common/io/io.h" #include "common/processing.h" const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) { // SunOS requires root permission to query PCI device list, except `/usr/bin/scanpci` // Same behavior can be observed with `cp $(which scanpci) /tmp/ && /tmp/scanpci` FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); const char* error = ffProcessAppendStdOut(&buffer, (char* const[]) { "/usr/bin/scanpci", "-v", NULL, }); if (error) return error; if (!ffStrbufStartsWithS(&buffer, "\npci ")) return "Invalid scanpci result"; // pci bus 0x0000 cardnum 0x00 function 0x00: vendor 0x1414 device 0x008e // Device unknown // CardVendor 0x0000 card 0x0000 (Card unknown) // STATUS 0x0010 COMMAND 0x0007 // CLASS 0x03 0x02 0x00 REVISION 0x00 // BIST 0x00 HEADER 0x00 LATENCY 0x00 CACHE 0x00 // MAX_LAT 0x00 MIN_GNT 0x00 INT_PIN 0x00 INT_LINE 0x00 for ( const char* pclass = strstr(buffer.chars, "\n CLASS 0x03 "); pclass; pclass = strstr(pclass, "\n CLASS 0x03 ") ) { // find the start of device entry const char* pstart = memrchr(buffer.chars, '\n', (size_t) (pclass - buffer.chars)); if (pstart == NULL) return "PCI info not found, invalid scanpci result"; while (pstart[1] != 'p') { pstart = memrchr(buffer.chars, '\n', (size_t) (pstart - buffer.chars - 1)); if (pstart == NULL) return "PCI info not found, invalid scanpci result"; } ++pstart; uint32_t vendorId, deviceId; if (sscanf(pstart, "pci %*[^:]: vendor %x device %x", &vendorId, &deviceId) != 2) return "PCI info not found, invalid scanpci result"; pclass += strlen("\n CLASS 0x03 "); uint32_t subclass = (uint32_t) strtoul(pclass, NULL, 16); pclass += strlen("0x02 0x00 REVISION "); uint32_t revision = (uint32_t) strtoul(pclass, NULL, 16); FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(vendorId)); ffStrbufInit(&gpu->memoryType); ffStrbufInit(&gpu->name); ffStrbufInit(&gpu->driver); ffStrbufInitStatic(&gpu->platformApi, "/usr/bin/scanpci"); gpu->index = FF_GPU_INDEX_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->deviceId = 0; gpu->frequency = FF_GPU_FREQUENCY_UNSET; if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) ffGPUQueryAmdGpuName((uint16_t) deviceId, (uint8_t) revision, gpu); if (gpu->name.length == 0) { ffGPUFillVendorAndName((uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu); } } return NULL; }