Changeset cbcb34c in mainline for uspace/lib/virtio/virtio-pci.c


Ignore:
Timestamp:
2018-05-22T19:06:50Z (6 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
341df5f
Parents:
1c53d93
git-author:
Jakub Jermar <jakub@…> (2018-05-05 14:43:51)
git-committer:
Jakub Jermar <jakub@…> (2018-05-22 19:06:50)
Message:

Configure the virtqueues

File:
1 edited

Legend:

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

    r1c53d93 rcbcb34c  
    3232#include "virtio-pci.h"
    3333
     34#include <as.h>
     35#include <align.h>
     36#include <macros.h>
     37
    3438#include <ddf/driver.h>
    3539#include <ddf/log.h>
     
    173177
    174178        return EOK;
     179}
     180
     181errno_t virtio_virtq_setup(virtio_dev_t *vdev, uint16_t num, uint16_t size,
     182    size_t buf_size, uint16_t buf_flags)
     183{
     184        virtq_t *q = &vdev->queues[num];
     185        virtio_pci_common_cfg_t *cfg = vdev->common_cfg;
     186
     187        /* Program the queue of our interest */
     188        pio_write_16(&cfg->queue_select, num);
     189
     190        /* Trim the size of the queue as needed */
     191        size = min(pio_read_16(&cfg->queue_size), size);
     192        pio_write_16(&cfg->queue_size, size);
     193        ddf_msg(LVL_NOTE, "Virtq %u: %u buffers", num, (unsigned) size);
     194
     195        /* Allocate array to hold virtual addresses of DMA buffers */
     196        void **buffers = calloc(sizeof(void *), size);
     197        if (!buffers)
     198                return ENOMEM;
     199
     200        size_t avail_offset = 0;
     201        size_t used_offset = 0;
     202        size_t buffers_offset = 0;
     203
     204        /*
     205         * Compute the size of the needed DMA memory and also the offsets of
     206         * the individual components
     207         */
     208        size_t mem_size = sizeof(virtq_desc_t[size]);
     209        mem_size = ALIGN_UP(mem_size, _Alignof(virtq_avail_t));
     210        avail_offset = mem_size;
     211        mem_size += sizeof(virtq_avail_t) + sizeof(ioport16_t[size]) +
     212            sizeof(ioport16_t);
     213        mem_size = ALIGN_UP(mem_size, _Alignof(virtq_used_t));
     214        used_offset = mem_size;
     215        mem_size += sizeof(virtq_used_t) + sizeof(virtq_used_elem_t[size]) +
     216            sizeof(ioport16_t);
     217        buffers_offset = mem_size;
     218        mem_size += size * buf_size;
     219
     220        /*
     221         * Allocate DMA memory for the virtqueues and the buffers
     222         */
     223        q->virt = AS_AREA_ANY;
     224        errno_t rc = dmamem_map_anonymous(mem_size, DMAMEM_4GiB,
     225            AS_AREA_READ | AS_AREA_WRITE, 0, &q->phys, &q->virt);
     226        if (rc != EOK) {
     227                free(buffers);
     228                q->virt = NULL;
     229                return rc;
     230        }
     231
     232        q->size = mem_size;
     233        q->queue_size = size;
     234        q->desc = q->virt;
     235        q->avail = q->virt + avail_offset;
     236        q->used = q->virt + used_offset;
     237        q->buffers = buffers;
     238
     239        memset(q->virt, 0, q->size);
     240
     241        /*
     242         * Initialize the descriptor table and the buffers array
     243         */
     244        for (unsigned i = 0; i < size; i++) {
     245                q->desc[i].addr = q->phys + buffers_offset + i * buf_size;
     246                q->desc[i].len = buf_size;
     247                q->desc[i].flags = buf_flags;
     248
     249                q->buffers[i] = q->virt + buffers_offset + i * buf_size;
     250        }
     251
     252        /*
     253         * Write the configured addresses to device's common config
     254         */
     255        pio_write_64(&cfg->queue_desc, q->phys);
     256        pio_write_64(&cfg->queue_avail, q->phys + avail_offset);
     257        pio_write_64(&cfg->queue_used, q->phys + used_offset);
     258
     259        ddf_msg(LVL_NOTE, "DMA memory for virtq %d: virt=%p, phys=%p, size=%zu",
     260            num, q->virt, (void *) q->phys, q->size);
     261
     262        return rc;
     263}
     264
     265void virtio_virtq_teardown(virtio_dev_t *vdev, uint16_t num)
     266{
     267        virtq_t *q = &vdev->queues[num];
     268        if (q->size)
     269                dmamem_unmap_anonymous(q->virt);
     270        if (q->buffers)
     271                free(q->buffers);
    175272}
    176273
     
    279376errno_t virtio_pci_dev_cleanup(virtio_dev_t *vdev)
    280377{
     378        if (vdev->queues) {
     379                for (unsigned i = 0;
     380                    i < pio_read_16(&vdev->common_cfg->num_queues); i++)
     381                        virtio_virtq_teardown(vdev, i);
     382                free(vdev->queues);
     383        }
    281384        return disable_resources(vdev);
    282385}
Note: See TracChangeset for help on using the changeset viewer.