| 88 | } |
| 89 | |
| 90 | rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, rt_size_t ring_size) |
| 91 | { |
| 92 | int i; |
| 93 | void *pages; |
| 94 | rt_size_t pages_total_size; |
| 95 | struct virtq *queue; |
| 96 | |
| 97 | _virtio_dev_check(dev); |
| 98 | |
| 99 | RT_ASSERT(dev->mmio_config->queue_num_max > 0); |
| 100 | RT_ASSERT(dev->mmio_config->queue_num_max > queue_index); |
| 101 | /* ring_size is power of 2 */ |
| 102 | RT_ASSERT(ring_size > 0); |
| 103 | RT_ASSERT(((ring_size - 1) & ring_size) == 0); |
| 104 | |
| 105 | queue = &dev->queues[queue_index]; |
| 106 | pages_total_size = VIRTIO_PAGE_ALIGN( |
| 107 | VIRTQ_DESC_TOTAL_SIZE(ring_size) + VIRTQ_AVAIL_TOTAL_SIZE(ring_size)) + VIRTQ_USED_TOTAL_SIZE(ring_size); |
| 108 | |
| 109 | pages = rt_malloc_align(pages_total_size, VIRTIO_PAGE_SIZE); |
| 110 | |
| 111 | if (pages == RT_NULL) |
| 112 | { |
| 113 | return -RT_ENOMEM; |
| 114 | } |
| 115 | |
| 116 | queue->free = rt_malloc(sizeof(rt_bool_t) * ring_size); |
| 117 | |
| 118 | if (queue->free == RT_NULL) |
| 119 | { |
| 120 | rt_free_align(pages); |
| 121 | return -RT_ENOMEM; |
| 122 | } |
| 123 | |
| 124 | rt_memset(pages, 0, pages_total_size); |
| 125 | |
| 126 | dev->mmio_config->guest_page_size = VIRTIO_PAGE_SIZE; |
| 127 | dev->mmio_config->queue_sel = queue_index; |
| 128 | dev->mmio_config->queue_num = ring_size; |
| 129 | dev->mmio_config->queue_align = VIRTIO_PAGE_SIZE; |
| 130 | dev->mmio_config->queue_pfn = VIRTIO_VA2PA(pages) >> VIRTIO_PAGE_SHIFT; |
| 131 | |
| 132 | queue->num = ring_size; |
| 133 | queue->desc = (struct virtq_desc *)((rt_ubase_t)pages); |
| 134 | queue->avail = (struct virtq_avail *)(((rt_ubase_t)pages) + VIRTQ_DESC_TOTAL_SIZE(ring_size)); |
| 135 | queue->used = (struct virtq_used *)VIRTIO_PAGE_ALIGN( |
| 136 | (rt_ubase_t)&queue->avail->ring[ring_size] + VIRTQ_AVAIL_RES_SIZE); |
| 137 | |
| 138 | queue->used_idx = 0; |
| 139 | |
| 140 | /* All descriptors start out unused */ |
| 141 | for (i = 0; i < ring_size; ++i) |
| 142 | { |
| 143 | queue->free[i] = RT_TRUE; |
| 144 | } |
| 145 | |
| 146 | queue->free_count = ring_size; |
| 147 |
no test coverage detected