|
1 | 1 | #include "gpu.h" |
2 | | -#include "common/io/io.h" |
3 | | -#include "common/processing.h" |
| 2 | +#include "util/stringUtils.h" |
4 | 3 |
|
5 | | -const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) |
6 | | -{ |
7 | | - // SunOS requires root permission to query PCI device list, except `/usr/bin/scanpci` |
8 | | - // Same behavior can be observed with `cp $(which scanpci) /tmp/ && /tmp/scanpci` |
9 | | - |
10 | | - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); |
11 | | - const char* error = ffProcessAppendStdOut(&buffer, (char* const[]) { |
12 | | - "/usr/bin/scanpci", |
13 | | - "-v", |
14 | | - NULL, |
15 | | - }); |
16 | | - if (error) |
17 | | - return error; |
18 | | - |
19 | | - if (!ffStrbufStartsWithS(&buffer, "\npci ")) |
20 | | - return "Invalid scanpci result"; |
| 4 | +#include <libdevinfo.h> |
21 | 5 |
|
22 | | - // pci bus 0x0000 cardnum 0x00 function 0x00: vendor 0x1414 device 0x008e |
23 | | - // Device unknown |
24 | | - // CardVendor 0x0000 card 0x0000 (Card unknown) |
25 | | - // STATUS 0x0010 COMMAND 0x0007 |
26 | | - // CLASS 0x03 0x02 0x00 REVISION 0x00 |
27 | | - // BIST 0x00 HEADER 0x00 LATENCY 0x00 CACHE 0x00 |
28 | | - // MAX_LAT 0x00 MIN_GNT 0x00 INT_PIN 0x00 INT_LINE 0x00 |
29 | | - |
30 | | - for ( |
31 | | - const char* pclass = strstr(buffer.chars, "\n CLASS 0x03 "); |
32 | | - pclass; |
33 | | - pclass = strstr(pclass, "\n CLASS 0x03 ") |
34 | | - ) |
| 6 | +static int walkDevTree(di_node_t node, FFlist* gpus) |
| 7 | +{ |
| 8 | + if (ffStrEquals(di_node_name(node), "display")) |
35 | 9 | { |
36 | | - // find the start of device entry |
37 | | - const char* pstart = memrchr(buffer.chars, '\n', (size_t) (pclass - buffer.chars)); |
38 | | - if (pstart == NULL) |
39 | | - return "PCI info not found, invalid scanpci result"; |
40 | | - while (pstart[1] != 'p') |
| 10 | + int* vendorId; |
| 11 | + int* deviceId; |
| 12 | + if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "vendor-id", &vendorId) > 0 |
| 13 | + && di_prop_lookup_ints(DDI_DEV_T_ANY, node, "device-id", &deviceId) > 0) |
41 | 14 | { |
42 | | - pstart = memrchr(buffer.chars, '\n', (size_t) (pstart - buffer.chars - 1)); |
43 | | - if (pstart == NULL) |
44 | | - return "PCI info not found, invalid scanpci result"; |
| 15 | + FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); |
| 16 | + ffStrbufInitS(&gpu->vendor, ffGPUGetVendorString((uint16_t) *vendorId)); |
| 17 | + ffStrbufInit(&gpu->name); |
| 18 | + ffStrbufInitS(&gpu->driver, di_driver_name(node)); |
| 19 | + ffStrbufInitStatic(&gpu->platformApi, "libdevinfo"); |
| 20 | + ffStrbufInit(&gpu->memoryType); |
| 21 | + gpu->index = FF_GPU_INDEX_UNSET; |
| 22 | + gpu->temperature = FF_GPU_TEMP_UNSET; |
| 23 | + gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; |
| 24 | + gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; |
| 25 | + gpu->type = FF_GPU_TYPE_UNKNOWN; |
| 26 | + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; |
| 27 | + gpu->deviceId = strtoul(di_bus_addr(node), NULL, 16); |
| 28 | + gpu->frequency = FF_GPU_FREQUENCY_UNSET; |
| 29 | + |
| 30 | + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) |
| 31 | + { |
| 32 | + int* revId; |
| 33 | + if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "revision-id", &revId) > 0) |
| 34 | + ffGPUQueryAmdGpuName((uint16_t) *deviceId, (uint8_t) *revId, gpu); |
| 35 | + } |
| 36 | + |
| 37 | + if (gpu->name.length == 0) |
| 38 | + { |
| 39 | + uint8_t subclass = 0; // assume VGA |
| 40 | + int* classCode; |
| 41 | + if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "class-code", &classCode) > 0) |
| 42 | + subclass = (uint8_t) (*classCode & 0xFFFF); |
| 43 | + ffGPUFillVendorAndName(subclass, (uint16_t) *vendorId, (uint16_t) *deviceId, gpu); |
| 44 | + } |
45 | 45 | } |
46 | | - ++pstart; |
47 | | - |
48 | | - uint32_t vendorId, deviceId; |
49 | | - if (sscanf(pstart, "pci %*[^:]: vendor %x device %x", |
50 | | - &vendorId, &deviceId) != 2) |
51 | | - return "PCI info not found, invalid scanpci result"; |
52 | | - |
53 | | - pclass += strlen("\n CLASS 0x03 "); |
54 | | - uint32_t subclass = (uint32_t) strtoul(pclass, NULL, 16); |
55 | | - pclass += strlen("0x02 0x00 REVISION "); |
56 | | - uint32_t revision = (uint32_t) strtoul(pclass, NULL, 16); |
57 | | - |
58 | | - FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); |
59 | | - ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(vendorId)); |
60 | | - ffStrbufInit(&gpu->memoryType); |
61 | | - ffStrbufInit(&gpu->name); |
62 | | - ffStrbufInit(&gpu->driver); |
63 | | - ffStrbufInitStatic(&gpu->platformApi, "/usr/bin/scanpci"); |
64 | | - gpu->index = FF_GPU_INDEX_UNSET; |
65 | | - gpu->temperature = FF_GPU_TEMP_UNSET; |
66 | | - gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; |
67 | | - gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; |
68 | | - gpu->type = FF_GPU_TYPE_UNKNOWN; |
69 | | - gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; |
70 | | - gpu->deviceId = 0; |
71 | | - gpu->frequency = FF_GPU_FREQUENCY_UNSET; |
| 46 | + } |
72 | 47 |
|
73 | | - if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) |
74 | | - ffGPUQueryAmdGpuName((uint16_t) deviceId, (uint8_t) revision, gpu); |
| 48 | + return DI_WALK_CONTINUE; |
| 49 | +} |
75 | 50 |
|
76 | | - if (gpu->name.length == 0) |
77 | | - { |
78 | | - ffGPUFillVendorAndName((uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu); |
79 | | - } |
80 | | - } |
| 51 | +const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) |
| 52 | +{ |
| 53 | + di_node_t rootNode = di_init("/", DINFOCPYALL); |
| 54 | + if (rootNode == DI_NODE_NIL) |
| 55 | + return "di_init() failed"; |
| 56 | + di_walk_node(rootNode, DI_WALK_CLDFIRST, gpus, (void*) walkDevTree); |
| 57 | + di_fini(rootNode); |
81 | 58 |
|
82 | 59 | return NULL; |
83 | 60 | } |
0 commit comments