Changeset 2d4faf7 in mainline
- Timestamp:
- 2018-05-22T19:06:50Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- eda41a9e
- Parents:
- 341df5f
- git-author:
- Jakub Jermar <jakub@…> (2018-05-05 20:44:09)
- git-committer:
- Jakub Jermar <jakub@…> (2018-05-22 19:06:50)
- Location:
- uspace/lib/virtio
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/virtio/Makefile
r341df5f r2d4faf7 32 32 33 33 SOURCES = \ 34 virtio.c \ 34 35 virtio-pci.c 35 36 -
uspace/lib/virtio/virtio-pci.c
r341df5f r2d4faf7 32 32 #include "virtio-pci.h" 33 33 34 #include <as.h>35 #include <align.h>36 #include <macros.h>37 38 34 #include <ddf/driver.h> 39 35 #include <ddf/log.h> … … 179 175 } 180 176 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 of206 * the individual components207 */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 buffers222 */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 array243 */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 config254 */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 the276 * 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 the324 * 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 343 177 errno_t virtio_pci_dev_initialize(ddf_dev_t *dev, virtio_dev_t *vdev) 344 178 {
Note:
See TracChangeset
for help on using the changeset viewer.