random: add a Virtio RNG module
* The default module is replaced by the Virtio RNG module when found. * This can have the undesired effect of rendering /dev/urandom slow. * Tested with the following QEmu command line option: -device virtio-rng-pci,rng=rng0 -object rng-random,filename=/dev/random,id=rng0 * moved random.h to private/drivers headers.
This commit is contained in:
@@ -23,11 +23,9 @@ typedef struct {
|
|||||||
typedef struct random_module_info {
|
typedef struct random_module_info {
|
||||||
driver_module_info info;
|
driver_module_info info;
|
||||||
|
|
||||||
status_t (*init)();
|
status_t (*read)(void* cookie, void *_buffer, size_t *_numBytes);
|
||||||
void (*uninit)();
|
status_t (*write)(void* cookie, const void *_buffer, size_t *_numBytes);
|
||||||
status_t (*read)(void *_buffer, size_t *_numBytes);
|
} random_module_info;
|
||||||
status_t (*write)(const void *_buffer, size_t *_numBytes);
|
|
||||||
} random_sim_interface;
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _RANDOM_H */
|
#endif /* _RANDOM_H */
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel bus_managers random ;
|
SubDir HAIKU_TOP src add-ons kernel bus_managers random ;
|
||||||
|
|
||||||
|
UsePrivateHeaders drivers ;
|
||||||
UsePrivateKernelHeaders ;
|
UsePrivateKernelHeaders ;
|
||||||
|
|
||||||
KernelAddon random :
|
KernelAddon random :
|
||||||
|
|||||||
@@ -32,7 +32,8 @@
|
|||||||
|
|
||||||
|
|
||||||
static mutex sRandomLock;
|
static mutex sRandomLock;
|
||||||
static random_sim_interface *sRandomModule;
|
static random_module_info *sRandomModule;
|
||||||
|
static void *sRandomCookie;
|
||||||
device_manager_info* gDeviceManager;
|
device_manager_info* gDeviceManager;
|
||||||
|
|
||||||
|
|
||||||
@@ -73,7 +74,7 @@ random_read(void *cookie, off_t position, void *_buffer, size_t *_numBytes)
|
|||||||
TRACE("read(%Ld,, %ld)\n", position, *_numBytes);
|
TRACE("read(%Ld,, %ld)\n", position, *_numBytes);
|
||||||
|
|
||||||
MutexLocker locker(&sRandomLock);
|
MutexLocker locker(&sRandomLock);
|
||||||
return sRandomModule->read(_buffer, _numBytes);
|
return sRandomModule->read(sRandomCookie, _buffer, _numBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -82,7 +83,11 @@ random_write(void *cookie, off_t position, const void *buffer, size_t *_numBytes
|
|||||||
{
|
{
|
||||||
TRACE("write(%Ld,, %ld)\n", position, *_numBytes);
|
TRACE("write(%Ld,, %ld)\n", position, *_numBytes);
|
||||||
MutexLocker locker(&sRandomLock);
|
MutexLocker locker(&sRandomLock);
|
||||||
return sRandomModule->write(buffer, _numBytes);
|
if (sRandomModule->write == NULL) {
|
||||||
|
*_numBytes = 0;
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
return sRandomModule->write(sRandomCookie, buffer, _numBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -244,10 +249,8 @@ random_added_device(device_node *node)
|
|||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
void *cookie;
|
|
||||||
|
|
||||||
status_t status = gDeviceManager->get_driver(node,
|
status_t status = gDeviceManager->get_driver(node,
|
||||||
(driver_module_info **)&sRandomModule, &cookie);
|
(driver_module_info **)&sRandomModule, &sRandomCookie);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -290,24 +290,7 @@ kill_chrand(ch_randgen *randgen)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
yarrow_rng_init()
|
yarrow_rng_read(void* cookie, void *_buffer, size_t *_numBytes)
|
||||||
{
|
|
||||||
sRandomEnv = new_chrand(8);
|
|
||||||
if (sRandomEnv == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
yarrow_rng_uninit()
|
|
||||||
{
|
|
||||||
kill_chrand(sRandomEnv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
yarrow_rng_read(void *_buffer, size_t *_numBytes)
|
|
||||||
{
|
{
|
||||||
sRandomCount += *_numBytes;
|
sRandomCount += *_numBytes;
|
||||||
|
|
||||||
@@ -333,7 +316,7 @@ yarrow_rng_read(void *_buffer, size_t *_numBytes)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
yarrow_rng_write(const void *buffer, size_t *_numBytes)
|
yarrow_rng_write(void* cookie, const void *buffer, size_t *_numBytes)
|
||||||
{
|
{
|
||||||
OCTET* data = (OCTET*)buffer;
|
OCTET* data = (OCTET*)buffer;
|
||||||
for (size_t i = 0; i < *_numBytes / sizeof(OCTET); i++) {
|
for (size_t i = 0; i < *_numBytes / sizeof(OCTET); i++) {
|
||||||
@@ -351,7 +334,10 @@ static status_t
|
|||||||
yarrow_init_bus(device_node* node, void** bus_cookie)
|
yarrow_init_bus(device_node* node, void** bus_cookie)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
return yarrow_rng_init();
|
sRandomEnv = new_chrand(8);
|
||||||
|
if (sRandomEnv == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -359,7 +345,7 @@ static void
|
|||||||
yarrow_uninit_bus(void* bus_cookie)
|
yarrow_uninit_bus(void* bus_cookie)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
yarrow_rng_uninit();
|
kill_chrand(sRandomEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -389,8 +375,6 @@ random_module_info gYarrowRandomModule = {
|
|||||||
NULL, // rescan
|
NULL, // rescan
|
||||||
yarrow_bus_removed,
|
yarrow_bus_removed,
|
||||||
},
|
},
|
||||||
yarrow_rng_init,
|
|
||||||
yarrow_rng_uninit,
|
|
||||||
yarrow_rng_read,
|
yarrow_rng_read,
|
||||||
yarrow_rng_write
|
yarrow_rng_write
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ if $(HAIKU_ATA_STACK) = 1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SubInclude HAIKU_TOP src add-ons kernel busses agp_gart ;
|
SubInclude HAIKU_TOP src add-ons kernel busses agp_gart ;
|
||||||
|
SubInclude HAIKU_TOP src add-ons kernel busses random ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel busses scsi ;
|
SubInclude HAIKU_TOP src add-ons kernel busses scsi ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel busses usb ;
|
SubInclude HAIKU_TOP src add-ons kernel busses usb ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel busses virtio ;
|
SubInclude HAIKU_TOP src add-ons kernel busses virtio ;
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
SubDir HAIKU_TOP src add-ons kernel busses random ;
|
||||||
|
|
||||||
|
UsePrivateHeaders drivers virtio ;
|
||||||
|
UsePrivateKernelHeaders ;
|
||||||
|
|
||||||
|
KernelAddon virtio_rng :
|
||||||
|
virtio_rng.cpp
|
||||||
|
VirtioRNGDevice.cpp
|
||||||
|
;
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Jérôme Duval, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "VirtioRNGPrivate.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
|
|
||||||
|
const char *
|
||||||
|
get_feature_name(uint32 feature)
|
||||||
|
{
|
||||||
|
switch (feature) {
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VirtioRNGDevice::VirtioRNGDevice(device_node *node)
|
||||||
|
:
|
||||||
|
fNode(node),
|
||||||
|
fVirtio(NULL),
|
||||||
|
fVirtioDevice(NULL),
|
||||||
|
fStatus(B_NO_INIT),
|
||||||
|
fOffset(BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
B_INITIALIZE_SPINLOCK(&fInterruptLock);
|
||||||
|
fInterruptCondition.Init(this, "virtio rng transfer");
|
||||||
|
|
||||||
|
get_memory_map(fBuffer, BUFFER_SIZE, &fEntry, 1);
|
||||||
|
|
||||||
|
// get the Virtio device from our parent's parent
|
||||||
|
device_node *parent = gDeviceManager->get_parent_node(node);
|
||||||
|
device_node *virtioParent = gDeviceManager->get_parent_node(parent);
|
||||||
|
gDeviceManager->put_node(parent);
|
||||||
|
|
||||||
|
gDeviceManager->get_driver(virtioParent, (driver_module_info **)&fVirtio,
|
||||||
|
(void **)&fVirtioDevice);
|
||||||
|
gDeviceManager->put_node(virtioParent);
|
||||||
|
|
||||||
|
fVirtio->negociate_features(fVirtioDevice,
|
||||||
|
0, &fFeatures, &get_feature_name);
|
||||||
|
|
||||||
|
fStatus = fVirtio->alloc_queues(fVirtioDevice, 1, &fVirtioQueue);
|
||||||
|
if (fStatus != B_OK) {
|
||||||
|
ERROR("queue allocation failed (%s)\n", strerror(fStatus));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fStatus = fVirtio->setup_interrupt(fVirtioDevice, NULL, this);
|
||||||
|
if (fStatus != B_OK) {
|
||||||
|
ERROR("interrupt setup failed (%s)\n", strerror(fStatus));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VirtioRNGDevice::~VirtioRNGDevice()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
VirtioRNGDevice::InitCheck()
|
||||||
|
{
|
||||||
|
return fStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
VirtioRNGDevice::Read(void* _buffer, size_t* _numBytes)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
if (fOffset >= BUFFER_SIZE) {
|
||||||
|
{
|
||||||
|
InterruptsSpinLocker locker(fInterruptLock);
|
||||||
|
fExpectsInterrupt = true;
|
||||||
|
fInterruptCondition.Add(&fInterruptConditionEntry);
|
||||||
|
}
|
||||||
|
status_t result = fVirtio->queue_request(fVirtioQueue, NULL, &fEntry,
|
||||||
|
_RequestCallback, this);
|
||||||
|
if (result != B_OK) {
|
||||||
|
ERROR("queueing failed (%s)\n", strerror(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = fInterruptConditionEntry.Wait(B_CAN_INTERRUPT);
|
||||||
|
|
||||||
|
{
|
||||||
|
InterruptsSpinLocker locker(fInterruptLock);
|
||||||
|
fExpectsInterrupt = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == B_OK) {
|
||||||
|
fOffset = 0;
|
||||||
|
} else if (result != B_INTERRUPTED) {
|
||||||
|
ERROR("request failed (%s)\n", strerror(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fOffset < BUFFER_SIZE) {
|
||||||
|
size_t size = min_c(BUFFER_SIZE - fOffset, *_numBytes);
|
||||||
|
memcpy(_buffer, fBuffer + fOffset, size);
|
||||||
|
fOffset += size;
|
||||||
|
*_numBytes = size;
|
||||||
|
} else
|
||||||
|
*_numBytes = 0;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VirtioRNGDevice::_RequestCallback(void* driverCookie, void* cookie)
|
||||||
|
{
|
||||||
|
VirtioRNGDevice* device = (VirtioRNGDevice*)driverCookie;
|
||||||
|
device->_RequestInterrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VirtioRNGDevice::_RequestInterrupt()
|
||||||
|
{
|
||||||
|
SpinLocker locker(fInterruptLock);
|
||||||
|
fInterruptCondition.NotifyAll();
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Jérôme Duval, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef VIRTIO_RNG_PRIVATE_H
|
||||||
|
#define VIRTIO_RNG_PRIVATE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <condition_variable.h>
|
||||||
|
#include <lock.h>
|
||||||
|
#include "random.h"
|
||||||
|
#include <virtio.h>
|
||||||
|
|
||||||
|
|
||||||
|
//#define TRACE_VIRTIO_RNG
|
||||||
|
#ifdef TRACE_VIRTIO_RNG
|
||||||
|
# define TRACE(x...) dprintf("virtio_rng: " x)
|
||||||
|
#else
|
||||||
|
# define TRACE(x...) ;
|
||||||
|
#endif
|
||||||
|
#define ERROR(x...) dprintf("\33[33mvirtio_rng:\33[0m " x)
|
||||||
|
#define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
||||||
|
|
||||||
|
|
||||||
|
extern device_manager_info* gDeviceManager;
|
||||||
|
extern random_for_controller_interface *gRandom;
|
||||||
|
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 16
|
||||||
|
|
||||||
|
|
||||||
|
class VirtioRNGDevice {
|
||||||
|
public:
|
||||||
|
VirtioRNGDevice(device_node* node);
|
||||||
|
~VirtioRNGDevice();
|
||||||
|
|
||||||
|
status_t InitCheck();
|
||||||
|
|
||||||
|
status_t Read(void* buffer, size_t* numBytes);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void _RequestCallback(void* driverCookie,
|
||||||
|
void *cookie);
|
||||||
|
void _RequestInterrupt();
|
||||||
|
|
||||||
|
device_node* fNode;
|
||||||
|
|
||||||
|
virtio_device_interface* fVirtio;
|
||||||
|
virtio_device* fVirtioDevice;
|
||||||
|
|
||||||
|
status_t fStatus;
|
||||||
|
uint32 fFeatures;
|
||||||
|
::virtio_queue fVirtioQueue;
|
||||||
|
|
||||||
|
physical_entry fEntry;
|
||||||
|
uint8 fBuffer[BUFFER_SIZE];
|
||||||
|
uint32 fOffset;
|
||||||
|
|
||||||
|
spinlock fInterruptLock;
|
||||||
|
ConditionVariable fInterruptCondition;
|
||||||
|
ConditionVariableEntry fInterruptConditionEntry;
|
||||||
|
bool fExpectsInterrupt;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VIRTIO_RNG_PRIVATE_H
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Jérôme Duval, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "VirtioRNGPrivate.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define VIRTIO_RNG_CONTROLLER_PRETTY_NAME "Virtio RNG Device"
|
||||||
|
|
||||||
|
#define VIRTIO_RNG_DRIVER_MODULE_NAME "busses/random/virtio_rng/driver_v1"
|
||||||
|
#define VIRTIO_RNG_DEVICE_MODULE_NAME "busses/random/virtio_rng/device_v1"
|
||||||
|
|
||||||
|
|
||||||
|
device_manager_info *gDeviceManager;
|
||||||
|
random_for_controller_interface *gRandom;
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Random module interface
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
sim_init_bus(device_node *node, void **_cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
VirtioRNGDevice *device = new(std::nothrow)
|
||||||
|
VirtioRNGDevice(node);
|
||||||
|
if (device == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
status_t status = device->InitCheck();
|
||||||
|
if (status < B_OK) {
|
||||||
|
delete device;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_cookie = device;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
sim_uninit_bus(void *cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
VirtioRNGDevice *device = (VirtioRNGDevice*)cookie;
|
||||||
|
|
||||||
|
delete device;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
sim_read(void* cookie, void *_buffer, size_t *_numBytes)
|
||||||
|
{
|
||||||
|
VirtioRNGDevice *device = (VirtioRNGDevice*)cookie;
|
||||||
|
return device->Read(_buffer, _numBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Driver module interface
|
||||||
|
|
||||||
|
|
||||||
|
static float
|
||||||
|
virtio_rng_supports_device(device_node *parent)
|
||||||
|
{
|
||||||
|
const char *bus;
|
||||||
|
uint16 deviceType;
|
||||||
|
|
||||||
|
// make sure parent is really the Virtio bus manager
|
||||||
|
if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (strcmp(bus, "virtio"))
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
// check whether it's really a Virtio Entropy Device
|
||||||
|
if (gDeviceManager->get_attr_uint16(parent, VIRTIO_DEVICE_TYPE_ITEM,
|
||||||
|
&deviceType, true) != B_OK || deviceType != VIRTIO_DEVICE_ID_ENTROPY)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
TRACE("Virtio RNG device found!\n");
|
||||||
|
|
||||||
|
return 0.6f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
virtio_rng_register_device(device_node *parent)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
device_attr attrs[] = {
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
return gDeviceManager->register_node(parent, VIRTIO_RNG_DRIVER_MODULE_NAME,
|
||||||
|
attrs, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
virtio_rng_init_driver(device_node *node, void **_cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
*_cookie = node;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
virtio_rng_register_child_devices(void *cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
device_node *node = (device_node *)cookie;
|
||||||
|
|
||||||
|
device_attr attrs[] = {
|
||||||
|
{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
|
||||||
|
{ string: RANDOM_FOR_CONTROLLER_MODULE_NAME }},
|
||||||
|
{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
|
||||||
|
{ string: VIRTIO_RNG_CONTROLLER_PRETTY_NAME }},
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
return gDeviceManager->register_node(node,
|
||||||
|
VIRTIO_RNG_DEVICE_MODULE_NAME, attrs, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
std_ops(int32 op, ...)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case B_MODULE_INIT:
|
||||||
|
case B_MODULE_UNINIT:
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static random_module_info sVirtioRNGDeviceInterface = {
|
||||||
|
{
|
||||||
|
{
|
||||||
|
VIRTIO_RNG_DEVICE_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
std_ops
|
||||||
|
},
|
||||||
|
NULL, // supported devices
|
||||||
|
NULL, // register node
|
||||||
|
sim_init_bus,
|
||||||
|
sim_uninit_bus,
|
||||||
|
NULL, // register child devices
|
||||||
|
NULL, // rescan
|
||||||
|
NULL // bus_removed
|
||||||
|
},
|
||||||
|
|
||||||
|
sim_read,
|
||||||
|
NULL // write
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static driver_module_info sVirtioRNGDriver = {
|
||||||
|
{
|
||||||
|
VIRTIO_RNG_DRIVER_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
std_ops
|
||||||
|
},
|
||||||
|
virtio_rng_supports_device,
|
||||||
|
virtio_rng_register_device,
|
||||||
|
virtio_rng_init_driver,
|
||||||
|
NULL, // uninit_driver,
|
||||||
|
virtio_rng_register_child_devices,
|
||||||
|
NULL, // rescan
|
||||||
|
NULL, // device_removed
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module_dependency module_dependencies[] = {
|
||||||
|
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
|
||||||
|
{ RANDOM_FOR_CONTROLLER_MODULE_NAME, (module_info **)&gRandom },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module_info *modules[] = {
|
||||||
|
(module_info *)&sVirtioRNGDriver,
|
||||||
|
(module_info *)&sVirtioRNGDeviceInterface,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user