2cd010a09bb71a512eb246f3a90f5d722fa8fd11
[dpdk.git] / drivers / bus / pci / windows / pci.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2020 Mellanox Technologies, Ltd
3  */
4 #include <rte_windows.h>
5 #include <rte_errno.h>
6 #include <rte_log.h>
7 #include <rte_eal_memconfig.h>
8 #include <rte_eal.h>
9
10 #include "private.h"
11
12 #include <devpkey.h>
13
14 #ifdef RTE_TOOLCHAIN_GCC
15 #include <devpropdef.h>
16 DEFINE_DEVPROPKEY(DEVPKEY_Device_Numa_Node, 0x540b947e, 0x8b40, 0x45bc,
17         0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 3);
18 #endif
19
20 /*
21  * This code is used to simulate a PCI probe by parsing information in
22  * the registry hive for PCI devices.
23  */
24
25 /* The functions below are not implemented on Windows,
26  * but need to be defined for compilation purposes
27  */
28
29 /* Map pci device */
30 int
31 rte_pci_map_device(struct rte_pci_device *dev __rte_unused)
32 {
33         /* This function is not implemented on Windows.
34          * We really should short-circuit the call to these functions by
35          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
36          * in the rte_pci_driver flags.
37          */
38         return 0;
39 }
40
41 /* Unmap pci device */
42 void
43 rte_pci_unmap_device(struct rte_pci_device *dev __rte_unused)
44 {
45         /* This function is not implemented on Windows.
46          * We really should short-circuit the call to these functions by
47          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
48          * in the rte_pci_driver flags.
49          */
50 }
51
52 int
53 pci_update_device(const struct rte_pci_addr *addr __rte_unused)
54 {
55         /* This function is not implemented on Windows.
56          * We really should short-circuit the call to these functions by
57          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
58          * in the rte_pci_driver flags.
59          */
60         return 0;
61 }
62
63 /* Read PCI config space. */
64 int
65 rte_pci_read_config(const struct rte_pci_device *dev __rte_unused,
66         void *buf __rte_unused, size_t len __rte_unused,
67         off_t offset __rte_unused)
68 {
69         /* This function is not implemented on Windows.
70          * We really should short-circuit the call to these functions by
71          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
72          * in the rte_pci_driver flags.
73          */
74         return 0;
75 }
76
77 /* Write PCI config space. */
78 int
79 rte_pci_write_config(const struct rte_pci_device *dev __rte_unused,
80         const void *buf __rte_unused, size_t len __rte_unused,
81         off_t offset __rte_unused)
82 {
83         /* This function is not implemented on Windows.
84          * We really should short-circuit the call to these functions by
85          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
86          * in the rte_pci_driver flags.
87          */
88         return 0;
89 }
90
91 enum rte_iova_mode
92 pci_device_iova_mode(const struct rte_pci_driver *pdrv __rte_unused,
93                 const struct rte_pci_device *pdev __rte_unused)
94 {
95         /* This function is not implemented on Windows.
96          * We really should short-circuit the call to these functions by
97          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
98          * in the rte_pci_driver flags.
99          */
100         return RTE_IOVA_DC;
101 }
102
103 int
104 rte_pci_ioport_map(struct rte_pci_device *dev __rte_unused,
105         int bar __rte_unused, struct rte_pci_ioport *p __rte_unused)
106 {
107         /* This function is not implemented on Windows.
108          * We really should short-circuit the call to these functions by
109          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
110          * in the rte_pci_driver flags.
111          */
112         return -1;
113 }
114
115
116 void
117 rte_pci_ioport_read(struct rte_pci_ioport *p __rte_unused,
118         void *data __rte_unused, size_t len __rte_unused,
119         off_t offset __rte_unused)
120 {
121         /* This function is not implemented on Windows.
122          * We really should short-circuit the call to these functions by
123          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
124          * in the rte_pci_driver flags.
125          */
126 }
127
128 int
129 rte_pci_ioport_unmap(struct rte_pci_ioport *p __rte_unused)
130 {
131         /* This function is not implemented on Windows.
132          * We really should short-circuit the call to these functions by
133          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
134          * in the rte_pci_driver flags.
135          */
136         return -1;
137 }
138
139 bool
140 pci_device_iommu_support_va(const struct rte_pci_device *dev __rte_unused)
141 {
142         /* This function is not implemented on Windows.
143          * We really should short-circuit the call to these functions by
144          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
145          * in the rte_pci_driver flags.
146          */
147         return false;
148 }
149
150 void
151 rte_pci_ioport_write(struct rte_pci_ioport *p __rte_unused,
152                 const void *data __rte_unused, size_t len __rte_unused,
153                 off_t offset __rte_unused)
154 {
155         /* This function is not implemented on Windows.
156          * We really should short-circuit the call to these functions by
157          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
158          * in the rte_pci_driver flags.
159          */
160 }
161
162 /* remap the PCI resource of a PCI device in anonymous virtual memory */
163 int
164 pci_uio_remap_resource(struct rte_pci_device *dev __rte_unused)
165 {
166         /* This function is not implemented on Windows.
167          * We really should short-circuit the call to these functions by
168          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
169          * in the rte_pci_driver flags.
170          */
171         return -1;
172 }
173
174 static int
175 get_device_pci_address(HDEVINFO dev_info,
176         PSP_DEVINFO_DATA device_info_data, struct rte_pci_addr *addr)
177 {
178         BOOL  res;
179         ULONG bus_num, dev_and_func;
180
181         res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
182                 SPDRP_BUSNUMBER, NULL, (PBYTE)&bus_num, sizeof(bus_num), NULL);
183         if (!res) {
184                 RTE_LOG_WIN32_ERR(
185                         "SetupDiGetDeviceRegistryProperty(SPDRP_BUSNUMBER)");
186                 return -1;
187         }
188
189         res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
190                 SPDRP_ADDRESS, NULL, (PBYTE)&dev_and_func, sizeof(dev_and_func),
191                 NULL);
192         if (!res) {
193                 RTE_LOG_WIN32_ERR(
194                         "SetupDiGetDeviceRegistryProperty(SPDRP_ADDRESS)");
195                 return -1;
196         }
197
198         addr->domain = bus_num >> 8;
199         addr->bus = bus_num & 0xff;
200         addr->devid = dev_and_func >> 16;
201         addr->function = dev_and_func & 0xffff;
202         return 0;
203 }
204
205 static int
206 get_device_resource_info(HDEVINFO dev_info,
207         PSP_DEVINFO_DATA dev_info_data, struct rte_pci_device *dev)
208 {
209         DEVPROPTYPE property_type;
210         DWORD numa_node;
211         BOOL  res;
212
213         switch (dev->kdrv) {
214         case RTE_PCI_KDRV_NONE:
215                 /* Get NUMA node using DEVPKEY_Device_Numa_Node */
216                 res = SetupDiGetDevicePropertyW(dev_info, dev_info_data,
217                         &DEVPKEY_Device_Numa_Node, &property_type,
218                         (BYTE *)&numa_node, sizeof(numa_node), NULL, 0);
219                 if (!res) {
220                         RTE_LOG_WIN32_ERR(
221                                 "SetupDiGetDevicePropertyW"
222                                 "(DEVPKEY_Device_Numa_Node)");
223                         return -1;
224                 }
225                 dev->device.numa_node = numa_node;
226                 /* mem_resource - Unneeded for RTE_PCI_KDRV_NONE */
227                 dev->mem_resource[0].phys_addr = 0;
228                 dev->mem_resource[0].len = 0;
229                 dev->mem_resource[0].addr = NULL;
230                 break;
231         default:
232                 /* kernel driver type is unsupported */
233                 RTE_LOG(DEBUG, EAL,
234                         "Kernel driver type for PCI device " PCI_PRI_FMT ","
235                         " is unsupported",
236                         dev->addr.domain, dev->addr.bus,
237                         dev->addr.devid, dev->addr.function);
238                 return -1;
239         }
240
241         return ERROR_SUCCESS;
242 }
243
244 /*
245  * get string that contains the list of hardware IDs for a device
246  */
247 static int
248 get_pci_hardware_id(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data,
249         char *pci_device_info, size_t pci_device_info_len)
250 {
251         BOOL  res;
252
253         /* Retrieve PCI device IDs */
254         res = SetupDiGetDeviceRegistryPropertyA(dev_info, device_info_data,
255                         SPDRP_HARDWAREID, NULL, (BYTE *)pci_device_info,
256                         pci_device_info_len, NULL);
257         if (!res) {
258                 RTE_LOG_WIN32_ERR(
259                         "SetupDiGetDeviceRegistryPropertyA(SPDRP_HARDWAREID)");
260                 return -1;
261         }
262
263         return 0;
264 }
265
266 /*
267  * parse the SPDRP_HARDWAREID output and assign to rte_pci_id
268  */
269 static int
270 parse_pci_hardware_id(const char *buf, struct rte_pci_id *pci_id)
271 {
272         int ids = 0;
273         uint16_t vendor_id, device_id;
274         uint32_t subvendor_id = 0;
275
276         ids = sscanf_s(buf, "PCI\\VEN_%" PRIx16 "&DEV_%" PRIx16 "&SUBSYS_%"
277                 PRIx32, &vendor_id, &device_id, &subvendor_id);
278         if (ids != 3)
279                 return -1;
280
281         pci_id->vendor_id = vendor_id;
282         pci_id->device_id = device_id;
283         pci_id->subsystem_device_id = subvendor_id >> 16;
284         pci_id->subsystem_vendor_id = subvendor_id & 0xffff;
285         return 0;
286 }
287
288 static void
289 get_kernel_driver_type(struct rte_pci_device *dev)
290 {
291         /*
292          * If another kernel driver is supported the relevant checking
293          * functions should be here
294          */
295         dev->kdrv = RTE_PCI_KDRV_NONE;
296 }
297
298 static int
299 pci_scan_one(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data)
300 {
301         struct rte_pci_device *dev;
302         int ret = -1;
303         char  pci_device_info[PATH_MAX];
304         struct rte_pci_addr addr;
305         struct rte_pci_id pci_id;
306
307         dev = malloc(sizeof(*dev));
308         if (dev == NULL)
309                 goto end;
310
311         memset(dev, 0, sizeof(*dev));
312
313         ret = get_pci_hardware_id(dev_info, device_info_data,
314                 pci_device_info, PATH_MAX);
315         if (ret != 0)
316                 goto end;
317
318         ret = parse_pci_hardware_id((const char *)&pci_device_info, &pci_id);
319         if (ret != 0) {
320                 /*
321                  * We won't add this device, but we want to continue
322                  * looking for supported devices
323                  */
324                 ret = ERROR_CONTINUE;
325                 goto end;
326         }
327
328         ret = get_device_pci_address(dev_info, device_info_data, &addr);
329         if (ret != 0)
330                 goto end;
331
332         dev->addr = addr;
333         dev->id = pci_id;
334         dev->max_vfs = 0; /* TODO: get max_vfs */
335
336         pci_name_set(dev);
337
338         get_kernel_driver_type(dev);
339
340         /* get resources */
341         if (get_device_resource_info(dev_info, device_info_data, dev)
342                         != ERROR_SUCCESS) {
343                 goto end;
344         }
345
346         /* device is valid, add in list (sorted) */
347         if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
348                 rte_pci_add_device(dev);
349         } else {
350                 struct rte_pci_device *dev2 = NULL;
351                 int ret;
352
353                 TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
354                         ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
355                         if (ret > 0) {
356                                 continue;
357                         } else if (ret < 0) {
358                                 rte_pci_insert_device(dev2, dev);
359                         } else { /* already registered */
360                                 dev2->kdrv = dev->kdrv;
361                                 dev2->max_vfs = dev->max_vfs;
362                                 memmove(dev2->mem_resource, dev->mem_resource,
363                                         sizeof(dev->mem_resource));
364                                 free(dev);
365                         }
366                         return 0;
367                 }
368                 rte_pci_add_device(dev);
369         }
370
371         return 0;
372 end:
373         if (dev)
374                 free(dev);
375         return ret;
376 }
377
378 /*
379  * Scan the contents of the PCI bus
380  * and add all network class devices into the devices list.
381  */
382 int
383 rte_pci_scan(void)
384 {
385         int   ret = -1;
386         DWORD device_index = 0, found_device = 0;
387         HDEVINFO dev_info;
388         SP_DEVINFO_DATA device_info_data;
389
390         /* for debug purposes, PCI can be disabled */
391         if (!rte_eal_has_pci())
392                 return 0;
393
394         dev_info = SetupDiGetClassDevs(&GUID_DEVCLASS_NET, TEXT("PCI"), NULL,
395                                 DIGCF_PRESENT);
396         if (dev_info == INVALID_HANDLE_VALUE) {
397                 RTE_LOG_WIN32_ERR("SetupDiGetClassDevs(pci_scan)");
398                 RTE_LOG(ERR, EAL, "Unable to enumerate PCI devices.\n");
399                 goto end;
400         }
401
402         device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
403         device_index = 0;
404
405         while (SetupDiEnumDeviceInfo(dev_info, device_index,
406             &device_info_data)) {
407                 device_index++;
408                 ret = pci_scan_one(dev_info, &device_info_data);
409                 if (ret == ERROR_SUCCESS)
410                         found_device++;
411                 else if (ret != ERROR_CONTINUE)
412                         goto end;
413
414                 memset(&device_info_data, 0, sizeof(SP_DEVINFO_DATA));
415                 device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
416         }
417
418         RTE_LOG(DEBUG, EAL, "PCI scan found %lu devices\n", found_device);
419         ret = 0;
420 end:
421         if (dev_info != INVALID_HANDLE_VALUE)
422                 SetupDiDestroyDeviceInfoList(dev_info);
423
424         return ret;
425 }