Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/virtio/virtio.c

    r417aaafb r1e472ee  
    3939#include <libarch/barrier.h>
    4040
     41/** Allocate DMA buffers
     42 *
     43 * @param buffers[in]  Number of buffers to allocate.
     44 * @param size[in]     Size of each buffer.
     45 * @param write[in]    True if the buffers are writable by the driver, false
     46 *                     otherwise.
     47 * @param buf[out]     Output array holding virtual addresses of the allocated
     48 *                     buffers.
     49 * @param buf_p[out]   Output array holding physical addresses of the allocated
     50 *                     buffers.
     51 *
     52 * The buffers can be deallocated by virtio_net_teardown_bufs().
     53 *
     54 * @return  EOK on success or error code.
     55 */
     56errno_t virtio_setup_dma_bufs(unsigned int buffers, size_t size,
     57    bool write, void *buf[], uintptr_t buf_p[])
     58{
     59        /*
     60         * Allocate all buffers at once in one large chunk.
     61         */
     62        void *virt = AS_AREA_ANY;
     63        uintptr_t phys;
     64        errno_t rc = dmamem_map_anonymous(buffers * size, 0,
     65            write ? AS_AREA_WRITE : AS_AREA_READ, 0, &phys, &virt);
     66        if (rc != EOK)
     67                return rc;
     68
     69        ddf_msg(LVL_NOTE, "DMA buffers: %p-%p", virt, virt + buffers * size);
     70
     71        /*
     72         * Calculate addresses of the individual buffers for easy access.
     73         */
     74        for (unsigned i = 0; i < buffers; i++) {
     75                buf[i] = virt + i * size;
     76                buf_p[i] = phys + i * size;
     77        }
     78
     79        return EOK;
     80}
     81
     82/** Deallocate DMA buffers
     83 *
     84 * @param buf[in]  Array holding the virtual addresses of the DMA buffers
     85 *                 previously allocated by virtio_net_setup_bufs().
     86 */
     87extern void virtio_teardown_dma_bufs(void *buf[])
     88{
     89        if (buf[0]) {
     90                dmamem_unmap_anonymous(buf[0]);
     91                buf[0] = NULL;
     92        }
     93}
     94
    4195void virtio_virtq_desc_set(virtio_dev_t *vdev, uint16_t num, uint16_t descno,
    4296    uint64_t addr, uint32_t len, uint16_t flags, uint16_t next)
     
    57111        return pio_read_le16(&d->next);
    58112}
     113
     114/** Create free descriptor list from the unused VIRTIO descriptors
     115 *
     116 * @param vdev[in]   VIRTIO device for which the free list will be created.
     117 * @param num[in]    Index of the virtqueue for which the free list will be
     118 *                   created.
     119 * @param size[in]   Number of descriptors on the free list. The free list will
     120 *                   contain descriptors starting from 0 to \a size - 1.
     121 * @param head[out]  Variable that will hold the VIRTIO descriptor at the head
     122 *                   of the free list.
     123 */
     124void virtio_create_desc_free_list(virtio_dev_t *vdev, uint16_t num,
     125    uint16_t size, uint16_t *head)
     126{
     127        for (unsigned i = 0; i < size; i++) {
     128                virtio_virtq_desc_set(vdev, num, i, 0, 0,
     129                    VIRTQ_DESC_F_NEXT, (i + 1 == size) ? -1U : i + 1);
     130        }
     131        *head = 0;
     132}
     133
     134/** Allocate a descriptor from the free list
     135 *
     136 * @param vdev[in]      VIRTIO device with the free list.
     137 * @param num[in]       Index of the virtqueue with free list.
     138 * @param head[in,out]  Head of the free list.
     139 *
     140 * @return  Allocated descriptor or 0xFFFF if the list is empty.
     141 */
     142uint16_t virtio_alloc_desc(virtio_dev_t *vdev, uint16_t num, uint16_t *head)
     143{
     144        virtq_t *q = &vdev->queues[num];
     145        fibril_mutex_lock(&q->lock);
     146        uint16_t descno = *head;
     147        if (descno != (uint16_t) -1U)
     148                *head = virtio_virtq_desc_get_next(vdev, num, descno);
     149        fibril_mutex_unlock(&q->lock);
     150        return descno;
     151}
     152
     153/** Free a descriptor into the free list
     154 *
     155 * @param vdev[in]      VIRTIO device with the free list.
     156 * @param num[in]       Index of the virtqueue with free list.
     157 * @param head[in,out]  Head of the free list.
     158 * @param descno[in]    The freed descriptor.
     159 */
     160void virtio_free_desc(virtio_dev_t *vdev, uint16_t num, uint16_t *head,
     161    uint16_t descno)
     162{
     163        virtq_t *q = &vdev->queues[num];
     164        fibril_mutex_lock(&q->lock);
     165        virtio_virtq_desc_set(vdev, num, descno, 0, 0, VIRTQ_DESC_F_NEXT,
     166            *head);
     167        *head = descno;
     168        fibril_mutex_unlock(&q->lock);
     169}
     170
    59171
    60172void virtio_virtq_produce_available(virtio_dev_t *vdev, uint16_t num,
Note: See TracChangeset for help on using the changeset viewer.