Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 2d4faf7 in mainline


Ignore:
Timestamp:
2018-05-22T19:06:50Z (3 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
eda41a9
Parents:
341df5f
git-author:
Jakub Jermar <jakub@…> (2018-05-05 20:44:09)
git-committer:
Jakub Jermar <jakub@…> (2018-05-22 19:06:50)
Message:

Split generic and PCI specific virtio code

Location:
uspace/lib/virtio
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/virtio/Makefile

    r341df5f r2d4faf7  
    3232
    3333SOURCES = \
     34        virtio.c \
    3435        virtio-pci.c
    3536
  • uspace/lib/virtio/virtio-pci.c

    r341df5f r2d4faf7  
    3232#include "virtio-pci.h"
    3333
    34 #include <as.h>
    35 #include <align.h>
    36 #include <macros.h>
    37 
    3834#include <ddf/driver.h>
    3935#include <ddf/log.h>
     
    179175}
    180176
    181 errno_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 
    265 void 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);
    272 }
    273 
    274 /**
    275  * Perform device initialization as described in section 3.1.1 of the
    276  * specification, steps 1 - 6.
    277  */
    278 errno_t virtio_device_setup_start(virtio_dev_t *vdev, uint32_t features)
    279 {
    280         virtio_pci_common_cfg_t *cfg = vdev->common_cfg;
    281 
    282         /* 1. Reset the device */
    283         uint8_t status = VIRTIO_DEV_STATUS_RESET;
    284         pio_write_8(&cfg->device_status, status);
    285 
    286         /* 2. Acknowledge we found the device */
    287         status |= VIRTIO_DEV_STATUS_ACKNOWLEDGE;
    288         pio_write_8(&cfg->device_status, status);
    289 
    290         /* 3. We know how to drive the device */
    291         status |= VIRTIO_DEV_STATUS_DRIVER;
    292         pio_write_8(&cfg->device_status, status);
    293 
    294         /* 4. Read the offered feature flags */
    295         pio_write_32(&cfg->device_feature_select, VIRTIO_FEATURES_0_31);
    296         uint32_t device_features = pio_read_32(&cfg->device_feature);
    297 
    298         ddf_msg(LVL_NOTE, "offered features %x", device_features);
    299         features &= device_features;
    300 
    301         if (!features)
    302                 return ENOTSUP;
    303 
    304         /* 4. Write the accepted feature flags */
    305         pio_write_32(&cfg->driver_feature_select, VIRTIO_FEATURES_0_31);
    306         pio_write_32(&cfg->driver_feature, features);
    307 
    308         ddf_msg(LVL_NOTE, "accepted features %x", features);
    309 
    310         /* 5. Set FEATURES_OK */
    311         status |= VIRTIO_DEV_STATUS_FEATURES_OK;
    312         pio_write_8(&cfg->device_status, status);
    313 
    314         /* 6. Test if the device supports our feature subset */
    315         status = pio_read_8(&cfg->device_status);
    316         if (!(status & VIRTIO_DEV_STATUS_FEATURES_OK))
    317                 return ENOTSUP;
    318 
    319         return EOK;
    320 }
    321 
    322 /**
    323  * Perform device initialization as described in section 3.1.1 of the
    324  * specification, step 8 (go live).
    325  */
    326 void virtio_device_setup_finalize(virtio_dev_t *vdev)
    327 {
    328         virtio_pci_common_cfg_t *cfg = vdev->common_cfg;
    329 
    330         /* 8. Go live */
    331         uint8_t status = pio_read_8(&cfg->device_status);
    332         pio_write_8(&cfg->device_status, status | VIRTIO_DEV_STATUS_DRIVER_OK);
    333 }
    334 
    335 void virtio_device_setup_fail(virtio_dev_t *vdev)
    336 {
    337         virtio_pci_common_cfg_t *cfg = vdev->common_cfg;
    338 
    339         uint8_t status = pio_read_8(&cfg->device_status);
    340         pio_write_8(&cfg->device_status, status | VIRTIO_DEV_STATUS_FAILED);
    341 }
    342 
    343177errno_t virtio_pci_dev_initialize(ddf_dev_t *dev, virtio_dev_t *vdev)
    344178{
Note: See TracChangeset for help on using the changeset viewer.