virtio: support specification 1.0
[dpdk.git] / drivers / net / virtio / virtio_pci.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 #include <stdint.h>
34
35 #ifdef RTE_EXEC_ENV_LINUXAPP
36  #include <dirent.h>
37  #include <fcntl.h>
38 #endif
39
40 #include "virtio_pci.h"
41 #include "virtio_logs.h"
42 #include "virtqueue.h"
43
44 /*
45  * Following macros are derived from linux/pci_regs.h, however,
46  * we can't simply include that header here, as there is no such
47  * file for non-Linux platform.
48  */
49 #define PCI_CAPABILITY_LIST     0x34
50 #define PCI_CAP_ID_VNDR         0x09
51
52 static void
53 legacy_read_dev_config(struct virtio_hw *hw, size_t offset,
54                        void *dst, int length)
55 {
56         uint64_t off;
57         uint8_t *d;
58         int size;
59
60         off = VIRTIO_PCI_CONFIG(hw) + offset;
61         for (d = dst; length > 0; d += size, off += size, length -= size) {
62                 if (length >= 4) {
63                         size = 4;
64                         *(uint32_t *)d = VIRTIO_READ_REG_4(hw, off);
65                 } else if (length >= 2) {
66                         size = 2;
67                         *(uint16_t *)d = VIRTIO_READ_REG_2(hw, off);
68                 } else {
69                         size = 1;
70                         *d = VIRTIO_READ_REG_1(hw, off);
71                 }
72         }
73 }
74
75 static void
76 legacy_write_dev_config(struct virtio_hw *hw, size_t offset,
77                         const void *src, int length)
78 {
79         uint64_t off;
80         const uint8_t *s;
81         int size;
82
83         off = VIRTIO_PCI_CONFIG(hw) + offset;
84         for (s = src; length > 0; s += size, off += size, length -= size) {
85                 if (length >= 4) {
86                         size = 4;
87                         VIRTIO_WRITE_REG_4(hw, off, *(const uint32_t *)s);
88                 } else if (length >= 2) {
89                         size = 2;
90                         VIRTIO_WRITE_REG_2(hw, off, *(const uint16_t *)s);
91                 } else {
92                         size = 1;
93                         VIRTIO_WRITE_REG_1(hw, off, *s);
94                 }
95         }
96 }
97
98 static uint64_t
99 legacy_get_features(struct virtio_hw *hw)
100 {
101         return VIRTIO_READ_REG_4(hw, VIRTIO_PCI_HOST_FEATURES);
102 }
103
104 static void
105 legacy_set_features(struct virtio_hw *hw, uint64_t features)
106 {
107         if ((features >> 32) != 0) {
108                 PMD_DRV_LOG(ERR,
109                         "only 32 bit features are allowed for legacy virtio!");
110                 return;
111         }
112         VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_GUEST_FEATURES, features);
113 }
114
115 static uint8_t
116 legacy_get_status(struct virtio_hw *hw)
117 {
118         return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS);
119 }
120
121 static void
122 legacy_set_status(struct virtio_hw *hw, uint8_t status)
123 {
124         VIRTIO_WRITE_REG_1(hw, VIRTIO_PCI_STATUS, status);
125 }
126
127 static void
128 legacy_reset(struct virtio_hw *hw)
129 {
130         legacy_set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
131 }
132
133 static uint8_t
134 legacy_get_isr(struct virtio_hw *hw)
135 {
136         return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_ISR);
137 }
138
139 /* Enable one vector (0) for Link State Intrerrupt */
140 static uint16_t
141 legacy_set_config_irq(struct virtio_hw *hw, uint16_t vec)
142 {
143         VIRTIO_WRITE_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR, vec);
144         return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR);
145 }
146
147 static uint16_t
148 legacy_get_queue_num(struct virtio_hw *hw, uint16_t queue_id)
149 {
150         VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, queue_id);
151         return VIRTIO_READ_REG_2(hw, VIRTIO_PCI_QUEUE_NUM);
152 }
153
154 static void
155 legacy_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
156 {
157         VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index);
158
159         VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN,
160                 vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT);
161 }
162
163 static void
164 legacy_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
165 {
166         VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index);
167
168         VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, 0);
169 }
170
171 static void
172 legacy_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
173 {
174         VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_NOTIFY, vq->vq_queue_index);
175 }
176
177 #ifdef RTE_EXEC_ENV_LINUXAPP
178 static int
179 parse_sysfs_value(const char *filename, unsigned long *val)
180 {
181         FILE *f;
182         char buf[BUFSIZ];
183         char *end = NULL;
184
185         f = fopen(filename, "r");
186         if (f == NULL) {
187                 PMD_INIT_LOG(ERR, "%s(): cannot open sysfs value %s",
188                              __func__, filename);
189                 return -1;
190         }
191
192         if (fgets(buf, sizeof(buf), f) == NULL) {
193                 PMD_INIT_LOG(ERR, "%s(): cannot read sysfs value %s",
194                              __func__, filename);
195                 fclose(f);
196                 return -1;
197         }
198         *val = strtoul(buf, &end, 0);
199         if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
200                 PMD_INIT_LOG(ERR, "%s(): cannot parse sysfs value %s",
201                              __func__, filename);
202                 fclose(f);
203                 return -1;
204         }
205         fclose(f);
206         return 0;
207 }
208
209 static int
210 get_uio_dev(struct rte_pci_addr *loc, char *buf, unsigned int buflen,
211                         unsigned int *uio_num)
212 {
213         struct dirent *e;
214         DIR *dir;
215         char dirname[PATH_MAX];
216
217         /*
218          * depending on kernel version, uio can be located in uio/uioX
219          * or uio:uioX
220          */
221         snprintf(dirname, sizeof(dirname),
222                      SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/uio",
223                      loc->domain, loc->bus, loc->devid, loc->function);
224         dir = opendir(dirname);
225         if (dir == NULL) {
226                 /* retry with the parent directory */
227                 snprintf(dirname, sizeof(dirname),
228                              SYSFS_PCI_DEVICES "/" PCI_PRI_FMT,
229                              loc->domain, loc->bus, loc->devid, loc->function);
230                 dir = opendir(dirname);
231
232                 if (dir == NULL) {
233                         PMD_INIT_LOG(ERR, "Cannot opendir %s", dirname);
234                         return -1;
235                 }
236         }
237
238         /* take the first file starting with "uio" */
239         while ((e = readdir(dir)) != NULL) {
240                 /* format could be uio%d ...*/
241                 int shortprefix_len = sizeof("uio") - 1;
242                 /* ... or uio:uio%d */
243                 int longprefix_len = sizeof("uio:uio") - 1;
244                 char *endptr;
245
246                 if (strncmp(e->d_name, "uio", 3) != 0)
247                         continue;
248
249                 /* first try uio%d */
250                 errno = 0;
251                 *uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10);
252                 if (errno == 0 && endptr != (e->d_name + shortprefix_len)) {
253                         snprintf(buf, buflen, "%s/uio%u", dirname, *uio_num);
254                         break;
255                 }
256
257                 /* then try uio:uio%d */
258                 errno = 0;
259                 *uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10);
260                 if (errno == 0 && endptr != (e->d_name + longprefix_len)) {
261                         snprintf(buf, buflen, "%s/uio:uio%u", dirname,
262                                      *uio_num);
263                         break;
264                 }
265         }
266         closedir(dir);
267
268         /* No uio resource found */
269         if (e == NULL) {
270                 PMD_INIT_LOG(ERR, "Could not find uio resource");
271                 return -1;
272         }
273
274         return 0;
275 }
276
277 static int
278 legacy_virtio_has_msix(const struct rte_pci_addr *loc)
279 {
280         DIR *d;
281         char dirname[PATH_MAX];
282
283         snprintf(dirname, sizeof(dirname),
284                      SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/msi_irqs",
285                      loc->domain, loc->bus, loc->devid, loc->function);
286
287         d = opendir(dirname);
288         if (d)
289                 closedir(d);
290
291         return (d != NULL);
292 }
293
294 /* Extract I/O port numbers from sysfs */
295 static int
296 virtio_resource_init_by_uio(struct rte_pci_device *pci_dev)
297 {
298         char dirname[PATH_MAX];
299         char filename[PATH_MAX];
300         unsigned long start, size;
301         unsigned int uio_num;
302
303         if (get_uio_dev(&pci_dev->addr, dirname, sizeof(dirname), &uio_num) < 0)
304                 return -1;
305
306         /* get portio size */
307         snprintf(filename, sizeof(filename),
308                      "%s/portio/port0/size", dirname);
309         if (parse_sysfs_value(filename, &size) < 0) {
310                 PMD_INIT_LOG(ERR, "%s(): cannot parse size",
311                              __func__);
312                 return -1;
313         }
314
315         /* get portio start */
316         snprintf(filename, sizeof(filename),
317                  "%s/portio/port0/start", dirname);
318         if (parse_sysfs_value(filename, &start) < 0) {
319                 PMD_INIT_LOG(ERR, "%s(): cannot parse portio start",
320                              __func__);
321                 return -1;
322         }
323         pci_dev->mem_resource[0].addr = (void *)(uintptr_t)start;
324         pci_dev->mem_resource[0].len =  (uint64_t)size;
325         PMD_INIT_LOG(DEBUG,
326                      "PCI Port IO found start=0x%lx with size=0x%lx",
327                      start, size);
328
329         /* save fd */
330         memset(dirname, 0, sizeof(dirname));
331         snprintf(dirname, sizeof(dirname), "/dev/uio%u", uio_num);
332         pci_dev->intr_handle.fd = open(dirname, O_RDWR);
333         if (pci_dev->intr_handle.fd < 0) {
334                 PMD_INIT_LOG(ERR, "Cannot open %s: %s\n",
335                         dirname, strerror(errno));
336                 return -1;
337         }
338
339         pci_dev->intr_handle.type = RTE_INTR_HANDLE_UIO;
340         pci_dev->driver->drv_flags |= RTE_PCI_DRV_INTR_LSC;
341
342         return 0;
343 }
344
345 /* Extract port I/O numbers from proc/ioports */
346 static int
347 virtio_resource_init_by_ioports(struct rte_pci_device *pci_dev)
348 {
349         uint16_t start, end;
350         int size;
351         FILE *fp;
352         char *line = NULL;
353         char pci_id[16];
354         int found = 0;
355         size_t linesz;
356
357         snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT,
358                  pci_dev->addr.domain,
359                  pci_dev->addr.bus,
360                  pci_dev->addr.devid,
361                  pci_dev->addr.function);
362
363         fp = fopen("/proc/ioports", "r");
364         if (fp == NULL) {
365                 PMD_INIT_LOG(ERR, "%s(): can't open ioports", __func__);
366                 return -1;
367         }
368
369         while (getdelim(&line, &linesz, '\n', fp) > 0) {
370                 char *ptr = line;
371                 char *left;
372                 int n;
373
374                 n = strcspn(ptr, ":");
375                 ptr[n] = 0;
376                 left = &ptr[n + 1];
377
378                 while (*left && isspace(*left))
379                         left++;
380
381                 if (!strncmp(left, pci_id, strlen(pci_id))) {
382                         found = 1;
383
384                         while (*ptr && isspace(*ptr))
385                                 ptr++;
386
387                         sscanf(ptr, "%04hx-%04hx", &start, &end);
388                         size = end - start + 1;
389
390                         break;
391                 }
392         }
393
394         free(line);
395         fclose(fp);
396
397         if (!found)
398                 return -1;
399
400         pci_dev->mem_resource[0].addr = (void *)(uintptr_t)(uint32_t)start;
401         pci_dev->mem_resource[0].len =  (uint64_t)size;
402         PMD_INIT_LOG(DEBUG,
403                 "PCI Port IO found start=0x%x with size=0x%x",
404                 start, size);
405
406         /* can't support lsc interrupt without uio */
407         pci_dev->driver->drv_flags &= ~RTE_PCI_DRV_INTR_LSC;
408
409         return 0;
410 }
411
412 /* Extract I/O port numbers from sysfs */
413 static int
414 legacy_virtio_resource_init(struct rte_pci_device *pci_dev)
415 {
416         if (virtio_resource_init_by_uio(pci_dev) == 0)
417                 return 0;
418         else
419                 return virtio_resource_init_by_ioports(pci_dev);
420 }
421
422 #else
423 static int
424 legayc_virtio_has_msix(const struct rte_pci_addr *loc __rte_unused)
425 {
426         /* nic_uio does not enable interrupts, return 0 (false). */
427         return 0;
428 }
429
430 static int
431 legacy_virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused)
432 {
433         /* no setup required */
434         return 0;
435 }
436 #endif
437
438 static const struct virtio_pci_ops legacy_ops = {
439         .read_dev_cfg   = legacy_read_dev_config,
440         .write_dev_cfg  = legacy_write_dev_config,
441         .reset          = legacy_reset,
442         .get_status     = legacy_get_status,
443         .set_status     = legacy_set_status,
444         .get_features   = legacy_get_features,
445         .set_features   = legacy_set_features,
446         .get_isr        = legacy_get_isr,
447         .set_config_irq = legacy_set_config_irq,
448         .get_queue_num  = legacy_get_queue_num,
449         .setup_queue    = legacy_setup_queue,
450         .del_queue      = legacy_del_queue,
451         .notify_queue   = legacy_notify_queue,
452 };
453
454
455 static inline uint8_t
456 io_read8(uint8_t *addr)
457 {
458         return *(volatile uint8_t *)addr;
459 }
460
461 static inline void
462 io_write8(uint8_t val, uint8_t *addr)
463 {
464         *(volatile uint8_t *)addr = val;
465 }
466
467 static inline uint16_t
468 io_read16(uint16_t *addr)
469 {
470         return *(volatile uint16_t *)addr;
471 }
472
473 static inline void
474 io_write16(uint16_t val, uint16_t *addr)
475 {
476         *(volatile uint16_t *)addr = val;
477 }
478
479 static inline uint32_t
480 io_read32(uint32_t *addr)
481 {
482         return *(volatile uint32_t *)addr;
483 }
484
485 static inline void
486 io_write32(uint32_t val, uint32_t *addr)
487 {
488         *(volatile uint32_t *)addr = val;
489 }
490
491 static inline void
492 io_write64_twopart(uint64_t val, uint32_t *lo, uint32_t *hi)
493 {
494         io_write32(val & ((1ULL << 32) - 1), lo);
495         io_write32(val >> 32,                hi);
496 }
497
498 static void
499 modern_read_dev_config(struct virtio_hw *hw, size_t offset,
500                        void *dst, int length)
501 {
502         int i;
503         uint8_t *p;
504         uint8_t old_gen, new_gen;
505
506         do {
507                 old_gen = io_read8(&hw->common_cfg->config_generation);
508
509                 p = dst;
510                 for (i = 0;  i < length; i++)
511                         *p++ = io_read8((uint8_t *)hw->dev_cfg + offset + i);
512
513                 new_gen = io_read8(&hw->common_cfg->config_generation);
514         } while (old_gen != new_gen);
515 }
516
517 static void
518 modern_write_dev_config(struct virtio_hw *hw, size_t offset,
519                         const void *src, int length)
520 {
521         int i;
522         const uint8_t *p = src;
523
524         for (i = 0;  i < length; i++)
525                 io_write8(*p++, (uint8_t *)hw->dev_cfg + offset + i);
526 }
527
528 static uint64_t
529 modern_get_features(struct virtio_hw *hw)
530 {
531         uint32_t features_lo, features_hi;
532
533         io_write32(0, &hw->common_cfg->device_feature_select);
534         features_lo = io_read32(&hw->common_cfg->device_feature);
535
536         io_write32(1, &hw->common_cfg->device_feature_select);
537         features_hi = io_read32(&hw->common_cfg->device_feature);
538
539         return ((uint64_t)features_hi << 32) | features_lo;
540 }
541
542 static void
543 modern_set_features(struct virtio_hw *hw, uint64_t features)
544 {
545         io_write32(0, &hw->common_cfg->guest_feature_select);
546         io_write32(features & ((1ULL << 32) - 1),
547                 &hw->common_cfg->guest_feature);
548
549         io_write32(1, &hw->common_cfg->guest_feature_select);
550         io_write32(features >> 32,
551                 &hw->common_cfg->guest_feature);
552 }
553
554 static uint8_t
555 modern_get_status(struct virtio_hw *hw)
556 {
557         return io_read8(&hw->common_cfg->device_status);
558 }
559
560 static void
561 modern_set_status(struct virtio_hw *hw, uint8_t status)
562 {
563         io_write8(status, &hw->common_cfg->device_status);
564 }
565
566 static void
567 modern_reset(struct virtio_hw *hw)
568 {
569         modern_set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
570         modern_get_status(hw);
571 }
572
573 static uint8_t
574 modern_get_isr(struct virtio_hw *hw)
575 {
576         return io_read8(hw->isr);
577 }
578
579 static uint16_t
580 modern_set_config_irq(struct virtio_hw *hw, uint16_t vec)
581 {
582         io_write16(vec, &hw->common_cfg->msix_config);
583         return io_read16(&hw->common_cfg->msix_config);
584 }
585
586 static uint16_t
587 modern_get_queue_num(struct virtio_hw *hw, uint16_t queue_id)
588 {
589         io_write16(queue_id, &hw->common_cfg->queue_select);
590         return io_read16(&hw->common_cfg->queue_size);
591 }
592
593 static void
594 modern_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
595 {
596         uint64_t desc_addr, avail_addr, used_addr;
597         uint16_t notify_off;
598
599         desc_addr = vq->mz->phys_addr;
600         avail_addr = desc_addr + vq->vq_nentries * sizeof(struct vring_desc);
601         used_addr = RTE_ALIGN_CEIL(avail_addr + offsetof(struct vring_avail,
602                                                          ring[vq->vq_nentries]),
603                                    VIRTIO_PCI_VRING_ALIGN);
604
605         io_write16(vq->vq_queue_index, &hw->common_cfg->queue_select);
606
607         io_write64_twopart(desc_addr, &hw->common_cfg->queue_desc_lo,
608                                       &hw->common_cfg->queue_desc_hi);
609         io_write64_twopart(avail_addr, &hw->common_cfg->queue_avail_lo,
610                                        &hw->common_cfg->queue_avail_hi);
611         io_write64_twopart(used_addr, &hw->common_cfg->queue_used_lo,
612                                       &hw->common_cfg->queue_used_hi);
613
614         notify_off = io_read16(&hw->common_cfg->queue_notify_off);
615         vq->notify_addr = (void *)((uint8_t *)hw->notify_base +
616                                 notify_off * hw->notify_off_multiplier);
617
618         io_write16(1, &hw->common_cfg->queue_enable);
619
620         PMD_INIT_LOG(DEBUG, "queue %u addresses:", vq->vq_queue_index);
621         PMD_INIT_LOG(DEBUG, "\t desc_addr: %" PRIx64, desc_addr);
622         PMD_INIT_LOG(DEBUG, "\t aval_addr: %" PRIx64, avail_addr);
623         PMD_INIT_LOG(DEBUG, "\t used_addr: %" PRIx64, used_addr);
624         PMD_INIT_LOG(DEBUG, "\t notify addr: %p (notify offset: %u)",
625                 vq->notify_addr, notify_off);
626 }
627
628 static void
629 modern_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
630 {
631         io_write16(vq->vq_queue_index, &hw->common_cfg->queue_select);
632
633         io_write64_twopart(0, &hw->common_cfg->queue_desc_lo,
634                                   &hw->common_cfg->queue_desc_hi);
635         io_write64_twopart(0, &hw->common_cfg->queue_avail_lo,
636                                   &hw->common_cfg->queue_avail_hi);
637         io_write64_twopart(0, &hw->common_cfg->queue_used_lo,
638                                   &hw->common_cfg->queue_used_hi);
639
640         io_write16(0, &hw->common_cfg->queue_enable);
641 }
642
643 static void
644 modern_notify_queue(struct virtio_hw *hw __rte_unused, struct virtqueue *vq)
645 {
646         io_write16(1, vq->notify_addr);
647 }
648
649 static const struct virtio_pci_ops modern_ops = {
650         .read_dev_cfg   = modern_read_dev_config,
651         .write_dev_cfg  = modern_write_dev_config,
652         .reset          = modern_reset,
653         .get_status     = modern_get_status,
654         .set_status     = modern_set_status,
655         .get_features   = modern_get_features,
656         .set_features   = modern_set_features,
657         .get_isr        = modern_get_isr,
658         .set_config_irq = modern_set_config_irq,
659         .get_queue_num  = modern_get_queue_num,
660         .setup_queue    = modern_setup_queue,
661         .del_queue      = modern_del_queue,
662         .notify_queue   = modern_notify_queue,
663 };
664
665
666 void
667 vtpci_read_dev_config(struct virtio_hw *hw, size_t offset,
668                       void *dst, int length)
669 {
670         hw->vtpci_ops->read_dev_cfg(hw, offset, dst, length);
671 }
672
673 void
674 vtpci_write_dev_config(struct virtio_hw *hw, size_t offset,
675                        const void *src, int length)
676 {
677         hw->vtpci_ops->write_dev_cfg(hw, offset, src, length);
678 }
679
680 uint64_t
681 vtpci_negotiate_features(struct virtio_hw *hw, uint64_t host_features)
682 {
683         uint64_t features;
684
685         /*
686          * Limit negotiated features to what the driver, virtqueue, and
687          * host all support.
688          */
689         features = host_features & hw->guest_features;
690         hw->vtpci_ops->set_features(hw, features);
691
692         return features;
693 }
694
695 void
696 vtpci_reset(struct virtio_hw *hw)
697 {
698         hw->vtpci_ops->set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
699         /* flush status write */
700         hw->vtpci_ops->get_status(hw);
701 }
702
703 void
704 vtpci_reinit_complete(struct virtio_hw *hw)
705 {
706         vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK);
707 }
708
709 void
710 vtpci_set_status(struct virtio_hw *hw, uint8_t status)
711 {
712         if (status != VIRTIO_CONFIG_STATUS_RESET)
713                 status |= hw->vtpci_ops->get_status(hw);
714
715         hw->vtpci_ops->set_status(hw, status);
716 }
717
718 uint8_t
719 vtpci_get_status(struct virtio_hw *hw)
720 {
721         return hw->vtpci_ops->get_status(hw);
722 }
723
724 uint8_t
725 vtpci_isr(struct virtio_hw *hw)
726 {
727         return hw->vtpci_ops->get_isr(hw);
728 }
729
730
731 /* Enable one vector (0) for Link State Intrerrupt */
732 uint16_t
733 vtpci_irq_config(struct virtio_hw *hw, uint16_t vec)
734 {
735         return hw->vtpci_ops->set_config_irq(hw, vec);
736 }
737
738 static void *
739 get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap)
740 {
741         uint8_t  bar    = cap->bar;
742         uint32_t length = cap->length;
743         uint32_t offset = cap->offset;
744         uint8_t *base;
745
746         if (bar > 5) {
747                 PMD_INIT_LOG(ERR, "invalid bar: %u", bar);
748                 return NULL;
749         }
750
751         if (offset + length < offset) {
752                 PMD_INIT_LOG(ERR, "offset(%u) + length(%u) overflows",
753                         offset, length);
754                 return NULL;
755         }
756
757         if (offset + length > dev->mem_resource[bar].len) {
758                 PMD_INIT_LOG(ERR,
759                         "invalid cap: overflows bar space: %u > %" PRIu64,
760                         offset + length, dev->mem_resource[bar].len);
761                 return NULL;
762         }
763
764         base = dev->mem_resource[bar].addr;
765         if (base == NULL) {
766                 PMD_INIT_LOG(ERR, "bar %u base addr is NULL", bar);
767                 return NULL;
768         }
769
770         return base + offset;
771 }
772
773 static int
774 virtio_read_caps(struct rte_pci_device *dev, struct virtio_hw *hw)
775 {
776         uint8_t pos;
777         struct virtio_pci_cap cap;
778         int ret;
779
780         if (rte_eal_pci_map_device(dev) < 0) {
781                 PMD_INIT_LOG(DEBUG, "failed to map pci device!");
782                 return -1;
783         }
784
785         ret = rte_eal_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST);
786         if (ret < 0) {
787                 PMD_INIT_LOG(DEBUG, "failed to read pci capability list");
788                 return -1;
789         }
790
791         while (pos) {
792                 ret = rte_eal_pci_read_config(dev, &cap, sizeof(cap), pos);
793                 if (ret < 0) {
794                         PMD_INIT_LOG(ERR,
795                                 "failed to read pci cap at pos: %x", pos);
796                         break;
797                 }
798
799                 if (cap.cap_vndr != PCI_CAP_ID_VNDR) {
800                         PMD_INIT_LOG(DEBUG,
801                                 "[%2x] skipping non VNDR cap id: %02x",
802                                 pos, cap.cap_vndr);
803                         goto next;
804                 }
805
806                 PMD_INIT_LOG(DEBUG,
807                         "[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u",
808                         pos, cap.cfg_type, cap.bar, cap.offset, cap.length);
809
810                 switch (cap.cfg_type) {
811                 case VIRTIO_PCI_CAP_COMMON_CFG:
812                         hw->common_cfg = get_cfg_addr(dev, &cap);
813                         break;
814                 case VIRTIO_PCI_CAP_NOTIFY_CFG:
815                         rte_eal_pci_read_config(dev, &hw->notify_off_multiplier,
816                                                 4, pos + sizeof(cap));
817                         hw->notify_base = get_cfg_addr(dev, &cap);
818                         break;
819                 case VIRTIO_PCI_CAP_DEVICE_CFG:
820                         hw->dev_cfg = get_cfg_addr(dev, &cap);
821                         break;
822                 case VIRTIO_PCI_CAP_ISR_CFG:
823                         hw->isr = get_cfg_addr(dev, &cap);
824                         break;
825                 }
826
827 next:
828                 pos = cap.cap_next;
829         }
830
831         if (hw->common_cfg == NULL || hw->notify_base == NULL ||
832             hw->dev_cfg == NULL    || hw->isr == NULL) {
833                 PMD_INIT_LOG(INFO, "no modern virtio pci device found.");
834                 return -1;
835         }
836
837         PMD_INIT_LOG(INFO, "found modern virtio pci device.");
838
839         PMD_INIT_LOG(DEBUG, "common cfg mapped at: %p", hw->common_cfg);
840         PMD_INIT_LOG(DEBUG, "device cfg mapped at: %p", hw->dev_cfg);
841         PMD_INIT_LOG(DEBUG, "isr cfg mapped at: %p", hw->isr);
842         PMD_INIT_LOG(DEBUG, "notify base: %p, notify off multiplier: %u",
843                 hw->notify_base, hw->notify_off_multiplier);
844
845         return 0;
846 }
847
848 int
849 vtpci_init(struct rte_pci_device *dev, struct virtio_hw *hw)
850 {
851         hw->dev = dev;
852
853         /*
854          * Try if we can succeed reading virtio pci caps, which exists
855          * only on modern pci device. If failed, we fallback to legacy
856          * virtio handling.
857          */
858         if (virtio_read_caps(dev, hw) == 0) {
859                 PMD_INIT_LOG(INFO, "modern virtio pci detected.");
860                 hw->vtpci_ops = &modern_ops;
861                 hw->modern    = 1;
862                 dev->driver->drv_flags |= RTE_PCI_DRV_INTR_LSC;
863                 return 0;
864         }
865
866         PMD_INIT_LOG(INFO, "trying with legacy virtio pci.");
867         if (legacy_virtio_resource_init(dev) < 0)
868                 return -1;
869
870         hw->vtpci_ops = &legacy_ops;
871         hw->use_msix = legacy_virtio_has_msix(&dev->addr);
872         hw->io_base  = (uint32_t)(uintptr_t)dev->mem_resource[0].addr;
873         hw->modern   = 0;
874
875         return 0;
876 }