LCOV - code coverage report
Current view: top level - zephyr/drivers/virtio - virtqueue.h Coverage Total Hit
Test: new.info Lines: 97.6 % 41 40
Test Date: 2025-09-05 20:47:19

            Line data    Source code
       1            0 : /*
       2              :  * Copyright (c) 2024 Antmicro <www.antmicro.com>
       3              :  *
       4              :  * SPDX-License-Identifier: Apache-2.0
       5              :  */
       6              : 
       7              : #ifndef ZEPHYR_VIRTIO_VIRTQUEUE_H_
       8              : #define ZEPHYR_VIRTIO_VIRTQUEUE_H_
       9              : #include <stdint.h>
      10              : #include <stddef.h>
      11              : #include <zephyr/kernel.h>
      12              : 
      13              : #ifdef __cplusplus
      14              : extern "C" {
      15              : #endif
      16              : 
      17              : /*
      18              :  * Based on Virtual I/O Device (VIRTIO) Version 1.3 specification:
      19              :  * https://docs.oasis-open.org/virtio/virtio/v1.3/csd01/virtio-v1.3-csd01.pdf
      20              :  */
      21              : 
      22              : /**
      23              :  * @brief Virtqueue Interface
      24              :  * @defgroup virtqueue_interface Virtqueue Interface
      25              :  * @ingroup virtio_interface
      26              :  * @{
      27              :  */
      28              : 
      29              : /**
      30              :  * used in virtq_desc::flags, enables chaining descriptor via virtq_desc::next
      31              :  */
      32            1 : #define VIRTQ_DESC_F_NEXT 1
      33              : /**
      34              :  * used in virtq_desc::flags, makes descriptor device writeable
      35              :  */
      36            1 : #define VIRTQ_DESC_F_WRITE 2
      37              : 
      38              : /**
      39              :  * @brief virtqueue descriptor
      40              :  *
      41              :  * Describes a single buffer
      42              :  */
      43            1 : struct virtq_desc {
      44              :         /**
      45              :          * physical address of the buffer
      46              :          */
      47            1 :         uint64_t addr;
      48              :         /**
      49              :          * length of the buffer
      50              :          */
      51            1 :         uint32_t len;
      52              :         /**
      53              :          * buffer flags
      54              :          */
      55            1 :         uint16_t flags;
      56              :         /**
      57              :          * chaining next descriptor, valid if flags & VIRTQ_DESC_F_NEXT
      58              :          */
      59            1 :         uint16_t next;
      60              : };
      61              : 
      62              : /**
      63              :  * @brief virtqueue available ring
      64              :  *
      65              :  * Used to pass descriptors to the virtio device. Driver writeable, device readable
      66              :  */
      67            1 : struct virtq_avail {
      68              :         /**
      69              :          * ring flags, e.g. VIRTQ_AVAIL_F_NO_INTERRUPT, currently unused
      70              :          */
      71            1 :         uint16_t flags;
      72              :         /**
      73              :          * head of the ring, by increasing it newly added descriptors are committed
      74              :          */
      75            1 :         uint16_t idx;
      76              :         /**
      77              :          * ring with indexes of descriptors
      78              :          */
      79            1 :         uint16_t ring[];
      80              : };
      81              : 
      82              : /**
      83              :  * @brief used descriptor chain
      84              :  *
      85              :  * Describes a single descriptor chain returned by the virtio device
      86              :  */
      87            1 : struct virtq_used_elem {
      88              :         /**
      89              :          * index of the head of descriptor chain
      90              :          */
      91            1 :         uint32_t id;
      92              :         /**
      93              :          * total amount of bytes written to descriptor chain by the virtio device
      94              :          */
      95            1 :         uint32_t len;
      96              : };
      97              : 
      98              : /**
      99              :  * @brief virtqueue used ring
     100              :  *
     101              :  * Used to receive descriptors from the virtio device. Driver readable, device writeable
     102              :  */
     103            1 : struct virtq_used {
     104              :         /**
     105              :          * ring flags, e.g. VIRTQ_USED_F_NO_NOTIFY, currently unused
     106              :          */
     107            1 :         uint16_t flags;
     108              :         /**
     109              :          * head of the ring
     110              :          */
     111            1 :         uint16_t idx;
     112              :         /**
     113              :          * ring of struct virtq_used_elem
     114              :          */
     115            1 :         struct virtq_used_elem ring[];
     116              : };
     117              : 
     118              : /**
     119              :  * @brief receive callback function type
     120              :  *
     121              :  * @param opaque argument passed to the callback
     122              :  * @param used_len total amount of bytes written to the descriptor chain by the virtio device
     123              :  */
     124            1 : typedef void (*virtq_receive_callback)(void *opaque, uint32_t used_len);
     125              : 
     126              : /**
     127              :  * @brief callback descriptor
     128              :  *
     129              :  * contains callback function ad its argument, invoked after virtio device return
     130              :  * descriptor chain its associated with
     131              :  */
     132            1 : struct virtq_receive_callback_entry {
     133              :         /**
     134              :          * callback function pointer
     135              :          */
     136            1 :         virtq_receive_callback cb;
     137              :         /**
     138              :          * argument passed to the callback function
     139              :          */
     140            1 :         void *opaque;
     141              : };
     142              : 
     143              : /**
     144              :  * @brief virtqueue
     145              :  *
     146              :  * contains structures required for virtqueue operation
     147              :  */
     148            1 : struct virtq {
     149              :         /**
     150              :          * lock used to synchronize operations on virtqueue
     151              :          */
     152            1 :         struct k_spinlock lock;
     153              : 
     154              :         /**
     155              :          * size of virtqueue
     156              :          */
     157            1 :         uint16_t num;
     158              :         /**
     159              :          * array with descriptors
     160              :          */
     161            1 :         struct virtq_desc *desc;
     162              :         /**
     163              :          * available ring
     164              :          */
     165            1 :         struct virtq_avail *avail;
     166              :         /**
     167              :          * used ring
     168              :          */
     169            1 :         struct virtq_used *used;
     170              : 
     171              :         /**
     172              :          * last seen idx in used ring, used to determine first descriptor to process
     173              :          * after receiving virtqueue interrupt
     174              :          */
     175            1 :         uint16_t last_used_idx;
     176              :         /**
     177              :          * Stack containing indexes of free descriptors. Because virtio devices are
     178              :          * not required to use received descriptors in order (see 2.7.9) unless
     179              :          * VIRTIO_F_IN_ORDER was offered, we can't use array with descriptors as another
     180              :          * ring buffer, always taking next descriptor. This is an auxilary structure to
     181              :          * easily determine next free descriptor
     182              :          */
     183            1 :         struct k_stack free_desc_stack;
     184              : 
     185              :         /**
     186              :          * amount of free descriptors in the free_desc_stack
     187              :          */
     188            1 :         uint16_t free_desc_n;
     189              : 
     190              :         /**
     191              :          * array with callbacks invoked after receiving buffers back from the device
     192              :          */
     193            1 :         struct virtq_receive_callback_entry *recv_cbs;
     194              : };
     195              : 
     196              : 
     197              : /**
     198              :  * @brief creates virtqueue
     199              :  *
     200              :  * @param v virtqueue to be created
     201              :  * @param size size of the virtqueue
     202              :  * @return 0 or error code on failure
     203              :  */
     204            1 : int virtq_create(struct virtq *v, size_t size);
     205              : 
     206              : /**
     207              :  * @brief frees virtqueue
     208              :  *
     209              :  * @param v virtqueue to be freed
     210              :  */
     211            1 : void virtq_free(struct virtq *v);
     212              : 
     213              : /**
     214              :  * @brief single buffer passed to virtq_add_buffer_chain
     215              :  */
     216            1 : struct virtq_buf {
     217              :         /**
     218              :          * virtual address of the buffer
     219              :          */
     220            1 :         void *addr;
     221              :         /**
     222              :          * length of the buffer
     223              :          */
     224            1 :         uint32_t len;
     225              : };
     226              : 
     227              : /**
     228              :  * @brief adds chain of buffers to the virtqueue
     229              :  *
     230              :  * Note that according to spec 2.7.13.3 the device may access the buffers as soon
     231              :  * as the avail->idx is increased, which is done at the end of this function, so
     232              :  * the device may access the buffers without notifying it with virtio_notify_virtqueue
     233              :  *
     234              :  * @param v virtqueue it operates on
     235              :  * @param bufs array of buffers to be added to the virtqueue
     236              :  * @param bufs_size amount of buffers
     237              :  * @param device_readable_count amount of bufferes readable by the device, the first
     238              :  * device_readable_count buffers will be set as device readable
     239              :  * @param cb callback to be invoked after device returns the buffer chain, can be NULL
     240              :  * @param cb_opaque opaque value that will be passed to the cb
     241              :  * @param timeout amount of time it will wait for free descriptors, with K_NO_WAIT it
     242              :  * can be called from isr
     243              :  * @return 0 or error code on failure
     244              :  */
     245            1 : int virtq_add_buffer_chain(
     246              :         struct virtq *v, struct virtq_buf *bufs, uint16_t bufs_size,
     247              :         uint16_t device_readable_count, virtq_receive_callback cb, void *cb_opaque,
     248              :         k_timeout_t timeout
     249              : );
     250              : 
     251              : /**
     252              :  * @brief adds free descriptor back
     253              :  *
     254              :  * @param v virtqueue it operates on
     255              :  * @param desc_idx index of returned descriptor
     256              :  */
     257            1 : void virtq_add_free_desc(struct virtq *v, uint16_t desc_idx);
     258              : 
     259              : /**
     260              :  * @brief gets next free descriptor
     261              :  *
     262              :  * @param v virtqueue it operates on
     263              :  * @param desc_idx address where index of descriptor will be stored
     264              :  * @param timeout amount of time it will wait for free descriptor, with K_NO_WAIT it
     265              :  * can be called from isr
     266              :  * @return 0 or error code on failure
     267              :  */
     268            1 : int virtq_get_free_desc(struct virtq *v, uint16_t *desc_idx, k_timeout_t timeout);
     269              : 
     270              : /**
     271              :  * @}
     272              :  */
     273              : 
     274              : #ifdef __cplusplus
     275              : }
     276              : #endif
     277              : 
     278              : #endif /* ZEPHYR_VIRTIO_VIRTQUEUE_H_ */
        

Generated by: LCOV version 2.0-1