Files
rt-thread/components/drivers/virtio/virtio-rng.c
T
GuEe-GUI 8517f2d086 [dm][virtio] support virtio dm
1. version for v1.2
2. support packed queue
1. support MMIO/PCI over bus
2. new virtio queue api with dma/cpu sync
3. update for virtio device drivers:
  - net
  - block
  - console
  - input
  - gpu
4. new virtio device drivers:
  - 9p
  - crypto
  - rng
  - scmi
  - scsi

Signed-off-by: GuEe-GUI <2991707448@qq.com>
2026-06-15 10:00:57 +08:00

192 lines
3.7 KiB
C

/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#define DBG_TAG "virtio.dev.rng"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include <cpuport.h>
struct virtio_rng
{
struct rt_hwcrypto_device parent;
struct rt_virtio_device *vdev;
struct rt_virtqueue *vqs[1];
struct rt_spinlock lock;
};
static rt_uint32_t virtio_rng_rand(struct hwcrypto_rng *ctx)
{
rt_uint32_t rand;
struct rt_virtqueue *vq;
struct virtio_rng *vrng = rt_container_of(ctx->parent.device, struct virtio_rng, parent);
vq = vrng->vqs[0];
rt_virtqueue_wait_prepare(vq, 1);
rt_spin_lock(&vrng->lock);
rt_virtqueue_add_inbuf(vq, &rand, sizeof(rand));
rt_virtqueue_kick(vq);
while (!rt_virtqueue_read_buf(vq, RT_NULL))
{
rt_hw_cpu_relax();
}
rt_spin_unlock(&vrng->lock);
return rand;
}
static const struct hwcrypto_rng_ops rng_ops =
{
.update = virtio_rng_rand,
};
static rt_err_t virtio_rng_create(struct rt_hwcrypto_ctx *ctx)
{
if ((ctx->type & HWCRYPTO_MAIN_TYPE_MASK) == HWCRYPTO_TYPE_RNG)
{
struct hwcrypto_rng *rng;
ctx->contex = RT_NULL;
rng = rt_container_of(ctx, struct hwcrypto_rng, parent);
rng->ops = &rng_ops;
return RT_EOK;
}
return -RT_ENOSYS;
}
static void virtio_rng_destroy(struct rt_hwcrypto_ctx *ctx)
{
}
static rt_err_t virtio_rng_copy(struct rt_hwcrypto_ctx *des,
const struct rt_hwcrypto_ctx *src)
{
if ((src->type & HWCRYPTO_MAIN_TYPE_MASK) == HWCRYPTO_TYPE_RNG)
{
return RT_EOK;
}
return -RT_ENOSYS;
}
static void virtio_rng_reset(struct rt_hwcrypto_ctx *ctx)
{
}
static const struct rt_hwcrypto_ops virtio_rng_ops =
{
.create = virtio_rng_create,
.destroy = virtio_rng_destroy,
.copy = virtio_rng_copy,
.reset = virtio_rng_reset,
};
static void virtio_rng_done(struct rt_virtqueue *vq)
{
}
static rt_err_t virtio_rng_vq_init(struct virtio_rng *vrng)
{
const char *names[] =
{
"req",
};
rt_virtqueue_callback cbs[] =
{
&virtio_rng_done,
};
return rt_virtio_virtqueue_install(vrng->vdev, RT_ARRAY_SIZE(vrng->vqs),
vrng->vqs, names, cbs);
}
static void virtio_rng_vq_finit(struct virtio_rng *vrng)
{
if (vrng->vqs[0])
{
rt_virtio_virtqueue_release(vrng->vdev);
}
}
static rt_err_t virtio_rng_probe(struct rt_virtio_device *vdev)
{
rt_err_t err;
struct virtio_rng *vrng = rt_calloc(1, sizeof(*vrng));
if (!vrng)
{
return -RT_ENOMEM;
}
vdev->priv = vrng;
vrng->vdev = vdev;
vdev->parent.user_data = vrng;
if ((err = virtio_rng_vq_init(vrng)))
{
goto _fail;
}
rt_spin_lock_init(&vrng->lock);
vrng->parent.ops = &virtio_rng_ops;
vrng->parent.id = vdev->id.vendor;
if ((err = rt_hwcrypto_register(&vrng->parent, "hwrng")))
{
goto _fail;
}
return RT_EOK;
_fail:
virtio_rng_vq_finit(vrng);
rt_free(vrng);
return err;
}
static rt_err_t virtio_rng_remove(struct rt_virtio_device *vdev)
{
struct virtio_rng *vrng = vdev->parent.user_data;
rt_device_unregister(&vrng->parent.parent);
virtio_rng_vq_finit(vrng);
rt_free(vrng);
return RT_EOK;
}
static const struct rt_virtio_device_id virtio_rng_ids[] =
{
{ VIRTIO_DEVICE_ID_RNG, VIRTIO_DEVICE_ANY_ID },
{ /* sentinel */ }
};
static struct rt_virtio_driver virtio_rng_driver =
{
.ids = virtio_rng_ids,
.probe = virtio_rng_probe,
.remove = virtio_rng_remove,
};
RT_VIRTIO_DRIVER_EXPORT(virtio_rng_driver);