mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-02-06 09:02:20 +08:00
[virtio] Add modern VirtIO (v1.2.0) support with backward compatibility
- Updated Kconfig to support both legacy and modern versions - Added version field to virtio_device structure - Implemented 64-bit feature negotiation for modern virtio - Updated queue initialization for modern virtio (separate desc/driver/device areas) - Added FEATURES_OK check for modern virtio - Updated all device drivers (blk, net, console, gpu, input) to use new APIs - Updated BSP drivers to accept both version 1 (legacy) and version 2 (modern) Co-authored-by: BernardXiong <1241087+BernardXiong@users.noreply.github.com>
This commit is contained in:
@@ -74,12 +74,17 @@ int rt_virtio_devices_init(void)
|
||||
mmio_config = (struct virtio_mmio_config *)mmio_base;
|
||||
|
||||
if (mmio_config->magic != VIRTIO_MAGIC_VALUE ||
|
||||
mmio_config->version != RT_USING_VIRTIO_VERSION ||
|
||||
mmio_config->vendor_id != VIRTIO_VENDOR_ID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Support both legacy (0x1) and modern (0x2) versions */
|
||||
if (mmio_config->version != 1 && mmio_config->version != 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
init_handler = virtio_device_init_handlers[mmio_config->device_id];
|
||||
|
||||
if (init_handler != RT_NULL)
|
||||
|
||||
@@ -80,12 +80,17 @@ int rt_virtio_devices_init(void)
|
||||
mmio_config = (struct virtio_mmio_config *)mmio_base;
|
||||
|
||||
if (mmio_config->magic != VIRTIO_MAGIC_VALUE ||
|
||||
mmio_config->version != RT_USING_VIRTIO_VERSION ||
|
||||
mmio_config->vendor_id != VIRTIO_VENDOR_ID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Support both legacy (0x1) and modern (0x2) versions */
|
||||
if (mmio_config->version != 1 && mmio_config->version != 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
init_handler = virtio_device_init_handlers[mmio_config->device_id];
|
||||
|
||||
if (init_handler != RT_NULL)
|
||||
|
||||
@@ -5,10 +5,20 @@ menuconfig RT_USING_VIRTIO
|
||||
if RT_USING_VIRTIO
|
||||
choice RT_USING_VIRTIO_VERSION
|
||||
prompt "VirtIO Version"
|
||||
default RT_USING_VIRTIO10
|
||||
default RT_USING_VIRTIO_LEGACY
|
||||
|
||||
config RT_USING_VIRTIO10
|
||||
bool "VirtIO v1.0"
|
||||
config RT_USING_VIRTIO_LEGACY
|
||||
bool "VirtIO Legacy (v0.95)"
|
||||
help
|
||||
Support for VirtIO legacy interface (version 0x1).
|
||||
This is the older version compatible with most existing QEMU versions.
|
||||
|
||||
config RT_USING_VIRTIO_MODERN
|
||||
bool "VirtIO Modern (v1.0+)"
|
||||
help
|
||||
Support for VirtIO modern interface (version 0x2).
|
||||
This version supports VirtIO 1.0, 1.1, and 1.2 specifications.
|
||||
Requires QEMU 2.4+ or compatible hypervisor.
|
||||
endchoice
|
||||
|
||||
config RT_USING_VIRTIO_MMIO_ALIGN
|
||||
|
||||
@@ -38,7 +38,27 @@ void virtio_status_driver_ok(struct virtio_device *dev)
|
||||
{
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
dev->mmio_config->status |= VIRTIO_STATUS_FEATURES_OK | VIRTIO_STATUS_DRIVER_OK;
|
||||
if (dev->version == 1)
|
||||
{
|
||||
/* Legacy virtio */
|
||||
dev->mmio_config->status |= VIRTIO_STATUS_FEATURES_OK | VIRTIO_STATUS_DRIVER_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Modern virtio: set FEATURES_OK and verify it */
|
||||
dev->mmio_config->status |= VIRTIO_STATUS_FEATURES_OK;
|
||||
|
||||
/* Verify that device accepted the features */
|
||||
if (!(dev->mmio_config->status & VIRTIO_STATUS_FEATURES_OK))
|
||||
{
|
||||
/* Device doesn't support our feature subset */
|
||||
dev->mmio_config->status |= VIRTIO_STATUS_FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now set DRIVER_OK */
|
||||
dev->mmio_config->status |= VIRTIO_STATUS_DRIVER_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void virtio_interrupt_ack(struct virtio_device *dev)
|
||||
@@ -59,7 +79,66 @@ rt_bool_t virtio_has_feature(struct virtio_device *dev, rt_uint32_t feature_bit)
|
||||
{
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
return !!(dev->mmio_config->device_features & (1UL << feature_bit));
|
||||
if (dev->version == 1)
|
||||
{
|
||||
/* Legacy: 32-bit feature bits only */
|
||||
return !!(dev->mmio_config->device_features & (1UL << feature_bit));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Modern: Use 64-bit feature access */
|
||||
rt_uint64_t features = virtio_get_features(dev);
|
||||
return !!(features & (1ULL << feature_bit));
|
||||
}
|
||||
}
|
||||
|
||||
rt_uint64_t virtio_get_features(struct virtio_device *dev)
|
||||
{
|
||||
rt_uint64_t features = 0;
|
||||
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
if (dev->version == 1)
|
||||
{
|
||||
/* Legacy: only lower 32 bits */
|
||||
features = dev->mmio_config->device_features;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Modern: read both 32-bit halves */
|
||||
dev->mmio_config->device_features_sel = 0;
|
||||
features = dev->mmio_config->device_features;
|
||||
|
||||
dev->mmio_config->device_features_sel = 1;
|
||||
features |= ((rt_uint64_t)dev->mmio_config->device_features) << 32;
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
void virtio_set_features(struct virtio_device *dev, rt_uint64_t features)
|
||||
{
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
if (dev->version == 1)
|
||||
{
|
||||
/* Legacy: only lower 32 bits */
|
||||
dev->mmio_config->driver_features = (rt_uint32_t)features;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Modern: write both 32-bit halves */
|
||||
dev->mmio_config->driver_features_sel = 0;
|
||||
dev->mmio_config->driver_features = (rt_uint32_t)features;
|
||||
|
||||
dev->mmio_config->driver_features_sel = 1;
|
||||
dev->mmio_config->driver_features = (rt_uint32_t)(features >> 32);
|
||||
}
|
||||
}
|
||||
|
||||
rt_bool_t virtio_has_feature_64(struct virtio_device *dev, rt_uint64_t features, rt_uint32_t feature_bit)
|
||||
{
|
||||
return !!(features & (1ULL << feature_bit));
|
||||
}
|
||||
|
||||
rt_err_t virtio_queues_alloc(struct virtio_device *dev, rt_size_t queues_num)
|
||||
@@ -93,6 +172,7 @@ rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, r
|
||||
void *pages;
|
||||
rt_size_t pages_total_size;
|
||||
struct virtq *queue;
|
||||
rt_uint64_t desc_addr, avail_addr, used_addr;
|
||||
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
@@ -123,18 +203,44 @@ rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, r
|
||||
|
||||
rt_memset(pages, 0, pages_total_size);
|
||||
|
||||
dev->mmio_config->guest_page_size = VIRTIO_PAGE_SIZE;
|
||||
/* Set queue selector */
|
||||
dev->mmio_config->queue_sel = queue_index;
|
||||
dev->mmio_config->queue_num = ring_size;
|
||||
dev->mmio_config->queue_align = VIRTIO_PAGE_SIZE;
|
||||
dev->mmio_config->queue_pfn = VIRTIO_VA2PA(pages) >> VIRTIO_PAGE_SHIFT;
|
||||
|
||||
/* Calculate queue area addresses */
|
||||
queue->num = ring_size;
|
||||
queue->desc = (struct virtq_desc *)((rt_ubase_t)pages);
|
||||
queue->avail = (struct virtq_avail *)(((rt_ubase_t)pages) + VIRTQ_DESC_TOTAL_SIZE(ring_size));
|
||||
queue->used = (struct virtq_used *)VIRTIO_PAGE_ALIGN(
|
||||
(rt_ubase_t)&queue->avail->ring[ring_size] + VIRTQ_AVAIL_RES_SIZE);
|
||||
|
||||
desc_addr = VIRTIO_VA2PA(queue->desc);
|
||||
avail_addr = VIRTIO_VA2PA(queue->avail);
|
||||
used_addr = VIRTIO_VA2PA(queue->used);
|
||||
|
||||
if (dev->version == 1)
|
||||
{
|
||||
/* Legacy virtio: use queue_pfn */
|
||||
dev->mmio_config->guest_page_size = VIRTIO_PAGE_SIZE;
|
||||
dev->mmio_config->queue_align = VIRTIO_PAGE_SIZE;
|
||||
dev->mmio_config->queue_pfn = desc_addr >> VIRTIO_PAGE_SHIFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Modern virtio: use separate descriptor/driver/device registers */
|
||||
dev->mmio_config->queue_desc_low = (rt_uint32_t)desc_addr;
|
||||
dev->mmio_config->queue_desc_high = (rt_uint32_t)(desc_addr >> 32);
|
||||
|
||||
dev->mmio_config->queue_driver_low = (rt_uint32_t)avail_addr;
|
||||
dev->mmio_config->queue_driver_high = (rt_uint32_t)(avail_addr >> 32);
|
||||
|
||||
dev->mmio_config->queue_device_low = (rt_uint32_t)used_addr;
|
||||
dev->mmio_config->queue_device_high = (rt_uint32_t)(used_addr >> 32);
|
||||
|
||||
/* Enable the queue */
|
||||
dev->mmio_config->queue_ready = 1;
|
||||
}
|
||||
|
||||
queue->used_idx = 0;
|
||||
|
||||
/* All descriptors start out unused */
|
||||
@@ -165,7 +271,17 @@ void virtio_queue_destroy(struct virtio_device *dev, rt_uint32_t queue_index)
|
||||
rt_free_align((void *)queue->desc);
|
||||
|
||||
dev->mmio_config->queue_sel = queue_index;
|
||||
dev->mmio_config->queue_pfn = RT_NULL;
|
||||
|
||||
if (dev->version == 1)
|
||||
{
|
||||
/* Legacy virtio */
|
||||
dev->mmio_config->queue_pfn = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Modern virtio */
|
||||
dev->mmio_config->queue_ready = 0;
|
||||
}
|
||||
|
||||
queue->num = 0;
|
||||
queue->desc = RT_NULL;
|
||||
|
||||
@@ -24,8 +24,13 @@
|
||||
#error "Please set RT_NAME_MAX to at lest 16"
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_VIRTIO10
|
||||
#define RT_USING_VIRTIO_VERSION 0x1
|
||||
/* VirtIO version configuration */
|
||||
#ifdef RT_USING_VIRTIO_LEGACY
|
||||
#define RT_USING_VIRTIO_VERSION 0x1 /* Legacy interface */
|
||||
#elif defined(RT_USING_VIRTIO_MODERN)
|
||||
#define RT_USING_VIRTIO_VERSION 0x2 /* Modern interface (1.0+) */
|
||||
#else
|
||||
#define RT_USING_VIRTIO_VERSION 0x1 /* Default to legacy */
|
||||
#endif
|
||||
|
||||
#include <virtio_mmio.h>
|
||||
@@ -111,6 +116,7 @@ enum
|
||||
struct virtio_device
|
||||
{
|
||||
rt_uint32_t irq;
|
||||
rt_uint32_t version; /* VirtIO version from MMIO config */
|
||||
|
||||
struct virtq *queues;
|
||||
rt_size_t queues_num;
|
||||
@@ -136,6 +142,11 @@ void virtio_status_driver_ok(struct virtio_device *dev);
|
||||
void virtio_interrupt_ack(struct virtio_device *dev);
|
||||
rt_bool_t virtio_has_feature(struct virtio_device *dev, rt_uint32_t feature_bit);
|
||||
|
||||
/* Modern VirtIO feature negotiation (64-bit features) */
|
||||
rt_uint64_t virtio_get_features(struct virtio_device *dev);
|
||||
void virtio_set_features(struct virtio_device *dev, rt_uint64_t features);
|
||||
rt_bool_t virtio_has_feature_64(struct virtio_device *dev, rt_uint64_t features, rt_uint32_t feature_bit);
|
||||
|
||||
rt_err_t virtio_queues_alloc(struct virtio_device *dev, rt_size_t queues_num);
|
||||
void virtio_queues_free(struct virtio_device *dev);
|
||||
rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, rt_size_t ring_size);
|
||||
|
||||
@@ -178,6 +178,7 @@ rt_err_t rt_virtio_blk_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
char dev_name[RT_NAME_MAX];
|
||||
struct virtio_device *virtio_dev;
|
||||
struct virtio_blk_device *virtio_blk_dev;
|
||||
rt_uint64_t device_features, driver_features;
|
||||
|
||||
virtio_blk_dev = rt_malloc(sizeof(struct virtio_blk_device));
|
||||
|
||||
@@ -189,6 +190,7 @@ rt_err_t rt_virtio_blk_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
virtio_dev = &virtio_blk_dev->virtio_dev;
|
||||
virtio_dev->irq = irq;
|
||||
virtio_dev->mmio_base = mmio_base;
|
||||
virtio_dev->version = virtio_dev->mmio_config->version;
|
||||
|
||||
virtio_blk_dev->config = (struct virtio_blk_config *)virtio_dev->mmio_config->config;
|
||||
|
||||
@@ -200,14 +202,23 @@ rt_err_t rt_virtio_blk_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
virtio_status_acknowledge_driver(virtio_dev);
|
||||
|
||||
/* Negotiate features */
|
||||
virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~(
|
||||
(1 << VIRTIO_BLK_F_RO) |
|
||||
(1 << VIRTIO_BLK_F_MQ) |
|
||||
(1 << VIRTIO_BLK_F_SCSI) |
|
||||
(1 << VIRTIO_BLK_F_CONFIG_WCE) |
|
||||
(1 << VIRTIO_F_ANY_LAYOUT) |
|
||||
(1 << VIRTIO_F_RING_EVENT_IDX) |
|
||||
(1 << VIRTIO_F_RING_INDIRECT_DESC));
|
||||
device_features = virtio_get_features(virtio_dev);
|
||||
driver_features = device_features & ~(
|
||||
(1ULL << VIRTIO_BLK_F_RO) |
|
||||
(1ULL << VIRTIO_BLK_F_MQ) |
|
||||
(1ULL << VIRTIO_BLK_F_SCSI) |
|
||||
(1ULL << VIRTIO_BLK_F_CONFIG_WCE) |
|
||||
(1ULL << VIRTIO_F_ANY_LAYOUT) |
|
||||
(1ULL << VIRTIO_F_RING_EVENT_IDX) |
|
||||
(1ULL << VIRTIO_F_RING_INDIRECT_DESC));
|
||||
|
||||
/* For modern virtio, we must support VERSION_1 */
|
||||
if (virtio_dev->version == 2)
|
||||
{
|
||||
driver_features |= (1ULL << VIRTIO_F_VERSION_1);
|
||||
}
|
||||
|
||||
virtio_set_features(virtio_dev, driver_features);
|
||||
|
||||
/* Tell device that feature negotiation is complete and we're completely ready */
|
||||
virtio_status_driver_ok(virtio_dev);
|
||||
|
||||
@@ -674,6 +674,7 @@ rt_err_t rt_virtio_console_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
char dev_name[RT_NAME_MAX];
|
||||
struct virtio_device *virtio_dev;
|
||||
struct virtio_console_device *virtio_console_dev;
|
||||
rt_uint64_t device_features, driver_features;
|
||||
|
||||
RT_ASSERT(RT_USING_VIRTIO_CONSOLE_PORT_MAX_NR > 0);
|
||||
|
||||
@@ -687,6 +688,7 @@ rt_err_t rt_virtio_console_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
virtio_dev = &virtio_console_dev->virtio_dev;
|
||||
virtio_dev->irq = irq;
|
||||
virtio_dev->mmio_base = mmio_base;
|
||||
virtio_dev->version = virtio_dev->mmio_config->version;
|
||||
|
||||
virtio_console_dev->config = (struct virtio_console_config *)virtio_dev->mmio_config->config;
|
||||
|
||||
@@ -697,9 +699,19 @@ rt_err_t rt_virtio_console_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
virtio_reset_device(virtio_dev);
|
||||
virtio_status_acknowledge_driver(virtio_dev);
|
||||
|
||||
virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~(
|
||||
(1 << VIRTIO_F_RING_EVENT_IDX) |
|
||||
(1 << VIRTIO_F_RING_INDIRECT_DESC));
|
||||
/* Negotiate features */
|
||||
device_features = virtio_get_features(virtio_dev);
|
||||
driver_features = device_features & ~(
|
||||
(1ULL << VIRTIO_F_RING_EVENT_IDX) |
|
||||
(1ULL << VIRTIO_F_RING_INDIRECT_DESC));
|
||||
|
||||
/* For modern virtio, we must support VERSION_1 */
|
||||
if (virtio_dev->version == 2)
|
||||
{
|
||||
driver_features |= (1ULL << VIRTIO_F_VERSION_1);
|
||||
}
|
||||
|
||||
virtio_set_features(virtio_dev, driver_features);
|
||||
|
||||
virtio_status_driver_ok(virtio_dev);
|
||||
|
||||
|
||||
@@ -850,6 +850,7 @@ rt_err_t rt_virtio_gpu_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
char dev_name[RT_NAME_MAX];
|
||||
struct virtio_device *virtio_dev;
|
||||
struct virtio_gpu_device *virtio_gpu_dev;
|
||||
rt_uint64_t device_features, driver_features;
|
||||
|
||||
virtio_gpu_dev = rt_malloc(sizeof(struct virtio_gpu_device));
|
||||
|
||||
@@ -861,6 +862,7 @@ rt_err_t rt_virtio_gpu_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
virtio_dev = &virtio_gpu_dev->virtio_dev;
|
||||
virtio_dev->irq = irq;
|
||||
virtio_dev->mmio_base = mmio_base;
|
||||
virtio_dev->version = virtio_dev->mmio_config->version;
|
||||
|
||||
virtio_gpu_dev->pmode_id = VIRTIO_GPU_INVALID_PMODE_ID;
|
||||
virtio_gpu_dev->display_resource_id = 0;
|
||||
@@ -877,9 +879,19 @@ rt_err_t rt_virtio_gpu_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
virtio_reset_device(virtio_dev);
|
||||
virtio_status_acknowledge_driver(virtio_dev);
|
||||
|
||||
virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~(
|
||||
(1 << VIRTIO_F_RING_EVENT_IDX) |
|
||||
(1 << VIRTIO_F_RING_INDIRECT_DESC));
|
||||
/* Negotiate features */
|
||||
device_features = virtio_get_features(virtio_dev);
|
||||
driver_features = device_features & ~(
|
||||
(1ULL << VIRTIO_F_RING_EVENT_IDX) |
|
||||
(1ULL << VIRTIO_F_RING_INDIRECT_DESC));
|
||||
|
||||
/* For modern virtio, we must support VERSION_1 */
|
||||
if (virtio_dev->version == 2)
|
||||
{
|
||||
driver_features |= (1ULL << VIRTIO_F_VERSION_1);
|
||||
}
|
||||
|
||||
virtio_set_features(virtio_dev, driver_features);
|
||||
|
||||
virtio_status_driver_ok(virtio_dev);
|
||||
|
||||
|
||||
@@ -346,6 +346,7 @@ rt_err_t rt_virtio_input_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
char dev_name[RT_NAME_MAX];
|
||||
struct virtio_device *virtio_dev;
|
||||
struct virtio_input_device *virtio_input_dev;
|
||||
rt_uint64_t device_features, driver_features;
|
||||
|
||||
virtio_input_dev = rt_malloc(sizeof(struct virtio_input_device));
|
||||
|
||||
@@ -357,6 +358,7 @@ rt_err_t rt_virtio_input_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
virtio_dev = &virtio_input_dev->virtio_dev;
|
||||
virtio_dev->irq = irq;
|
||||
virtio_dev->mmio_base = mmio_base;
|
||||
virtio_dev->version = virtio_dev->mmio_config->version;
|
||||
|
||||
virtio_input_dev->config = (struct virtio_input_config *)virtio_dev->mmio_config->config;
|
||||
virtio_input_dev->bsct_handler = RT_NULL;
|
||||
@@ -368,9 +370,19 @@ rt_err_t rt_virtio_input_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
virtio_reset_device(virtio_dev);
|
||||
virtio_status_acknowledge_driver(virtio_dev);
|
||||
|
||||
virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~(
|
||||
(1 << VIRTIO_F_RING_EVENT_IDX) |
|
||||
(1 << VIRTIO_F_RING_INDIRECT_DESC));
|
||||
/* Negotiate features */
|
||||
device_features = virtio_get_features(virtio_dev);
|
||||
driver_features = device_features & ~(
|
||||
(1ULL << VIRTIO_F_RING_EVENT_IDX) |
|
||||
(1ULL << VIRTIO_F_RING_INDIRECT_DESC));
|
||||
|
||||
/* For modern virtio, we must support VERSION_1 */
|
||||
if (virtio_dev->version == 2)
|
||||
{
|
||||
driver_features |= (1ULL << VIRTIO_F_VERSION_1);
|
||||
}
|
||||
|
||||
virtio_set_features(virtio_dev, driver_features);
|
||||
|
||||
virtio_status_driver_ok(virtio_dev);
|
||||
|
||||
|
||||
@@ -195,6 +195,7 @@ rt_err_t rt_virtio_net_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
char dev_name[RT_NAME_MAX];
|
||||
struct virtio_device *virtio_dev;
|
||||
struct virtio_net_device *virtio_net_dev;
|
||||
rt_uint64_t device_features, driver_features;
|
||||
|
||||
virtio_net_dev = rt_malloc(sizeof(struct virtio_net_device));
|
||||
|
||||
@@ -206,15 +207,26 @@ rt_err_t rt_virtio_net_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
virtio_dev = &virtio_net_dev->virtio_dev;
|
||||
virtio_dev->irq = irq;
|
||||
virtio_dev->mmio_base = mmio_base;
|
||||
virtio_dev->version = virtio_dev->mmio_config->version;
|
||||
|
||||
virtio_net_dev->config = (struct virtio_net_config *)virtio_dev->mmio_config->config;
|
||||
|
||||
virtio_reset_device(virtio_dev);
|
||||
virtio_status_acknowledge_driver(virtio_dev);
|
||||
|
||||
virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~(
|
||||
(1 << VIRTIO_NET_F_CTRL_VQ) |
|
||||
(1 << VIRTIO_F_RING_EVENT_IDX));
|
||||
/* Negotiate features */
|
||||
device_features = virtio_get_features(virtio_dev);
|
||||
driver_features = device_features & ~(
|
||||
(1ULL << VIRTIO_NET_F_CTRL_VQ) |
|
||||
(1ULL << VIRTIO_F_RING_EVENT_IDX));
|
||||
|
||||
/* For modern virtio, we must support VERSION_1 */
|
||||
if (virtio_dev->version == 2)
|
||||
{
|
||||
driver_features |= (1ULL << VIRTIO_F_VERSION_1);
|
||||
}
|
||||
|
||||
virtio_set_features(virtio_dev, driver_features);
|
||||
|
||||
virtio_status_driver_ok(virtio_dev);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user