[haiku-commits] haiku: hrev45998 - src/add-ons/kernel/busses/random src/add-ons/kernel/bus_managers/random headers/private/drivers

  • From: korli@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 29 Aug 2013 18:48:01 +0200 (CEST)

hrev45998 adds 4 changesets to branch 'master'
old head: 8f7f28a7c3db28711920ad5d15df401fae90bcf1
new head: 86af5f159bbd93b977407e8df5ac5f5fe04c2b05
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=86af5f1+%5E8f7f28a

----------------------------------------------------------------------------

f73fb10: random: added a bus interface for RNG modules.
  
  * Yarrow RNG is the default RNG module.

eb5639c: device_manager: tune the search paths
  
  * the Virtio RNG PCI device has the class 0, so can't be found using usual
  paths. Add 0 to _AlwaysRegisterDynamic() and "busses/virtio" in 
_GetNextDriverPath()
  for non generic drivers to help finding virtio_pci.
  * The RNG Virtio device is generic and needs "busses/random" to find 
virtio_rng.

8d2bf69: 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.

86af5f1: VirtioRNG: add to the image

                                   [ Jérôme Duval <jerome.duval@xxxxxxxxx> ]

----------------------------------------------------------------------------

13 files changed, 575 insertions(+), 59 deletions(-)
build/jam/HaikuImage                             |   2 +
headers/private/drivers/random.h                 |  31 +++
src/add-ons/kernel/bus_managers/random/Jamfile   |   1 +
.../kernel/bus_managers/random/driver.cpp        |  76 ++++++-
src/add-ons/kernel/bus_managers/random/random.h  |  20 --
.../kernel/bus_managers/random/yarrow_rng.cpp    |  84 +++++---
.../kernel/bus_managers/random/yarrow_rng.h      |   5 +-
src/add-ons/kernel/busses/Jamfile                |   1 +
src/add-ons/kernel/busses/random/Jamfile         |   9 +
.../kernel/busses/random/VirtioRNGDevice.cpp     | 134 +++++++++++++
.../kernel/busses/random/VirtioRNGPrivate.h      |  67 +++++++
src/add-ons/kernel/busses/random/virtio_rng.cpp  | 197 +++++++++++++++++++
.../kernel/device_manager/device_manager.cpp     |   7 +-

############################################################################

Commit:      f73fb1051dbdebede4a6ecec5b37674237f0b528
URL:         http://cgit.haiku-os.org/haiku/commit/?id=f73fb10
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Tue Aug 27 22:07:17 2013 UTC

random: added a bus interface for RNG modules.

* Yarrow RNG is the default RNG module.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/bus_managers/random/driver.cpp 
b/src/add-ons/kernel/bus_managers/random/driver.cpp
index 151a178..715f1691 100644
--- a/src/add-ons/kernel/bus_managers/random/driver.cpp
+++ b/src/add-ons/kernel/bus_managers/random/driver.cpp
@@ -32,7 +32,8 @@
 
 
 static mutex sRandomLock;
-static device_manager_info* sDeviceManager;
+static random_sim_interface *sRandomModule;
+device_manager_info* gDeviceManager;
 
 
 typedef struct {
@@ -47,14 +48,13 @@ static status_t
 random_init_device(void* _info, void** _cookie)
 {
        mutex_init(&sRandomLock, "/dev/random lock");
-       return gYarrowRandomModule->init();
+       return B_OK;
 }
 
 
 static void
 random_uninit_device(void* _cookie)
 {
-       gYarrowRandomModule->uninit();
        mutex_destroy(&sRandomLock);
 }
 
@@ -73,7 +73,7 @@ random_read(void *cookie, off_t position, void *_buffer, 
size_t *_numBytes)
        TRACE("read(%Ld,, %ld)\n", position, *_numBytes);
 
        MutexLocker locker(&sRandomLock);
-       return gYarrowRandomModule->read(_buffer, _numBytes);
+       return sRandomModule->read(_buffer, _numBytes);
 }
 
 
@@ -82,7 +82,7 @@ random_write(void *cookie, off_t position, const void 
*buffer, size_t *_numBytes
 {
        TRACE("write(%Ld,, %ld)\n", position, *_numBytes);
        MutexLocker locker(&sRandomLock);
-       return gYarrowRandomModule->write(buffer, _numBytes);
+       return sRandomModule->write(buffer, _numBytes);
 }
 
 
@@ -152,7 +152,7 @@ random_supports_device(device_node *parent)
        const char *bus;
 
        // make sure parent is really device root
-       if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
+       if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
                return -1;
 
        if (strcmp(bus, "root"))
@@ -174,7 +174,7 @@ random_register_device(device_node *node)
                { NULL }
        };
 
-       return sDeviceManager->register_node(node, RANDOM_DRIVER_MODULE_NAME,
+       return gDeviceManager->register_node(node, RANDOM_DRIVER_MODULE_NAME,
                attrs, NULL, NULL);
 }
 
@@ -212,25 +212,57 @@ random_register_child_devices(void* _cookie)
 {
        CALLED();
        random_driver_info* info = (random_driver_info*)_cookie;
-       status_t status = sDeviceManager->publish_device(info->node, "random",
+       status_t status = gDeviceManager->publish_device(info->node, "random",
                RANDOM_DEVICE_MODULE_NAME);
        if (status == B_OK) {
-               sDeviceManager->publish_device(info->node, "urandom",
+               gDeviceManager->publish_device(info->node, "urandom",
                        RANDOM_DEVICE_MODULE_NAME);
        }
 
+       // add the default Yarrow RNG
+       device_attr attrs[] = {
+               { B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
+                       { string: "Yarrow RNG" }},
+               { B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
+                       { string: RANDOM_FOR_CONTROLLER_MODULE_NAME }},
+               { NULL }
+       };
+
+       device_node* node;
+       return gDeviceManager->register_node(info->node,
+               YARROW_RNG_SIM_MODULE_NAME, attrs, NULL, &node);
+
+       return status;
+}
+
+
+//     #pragma mark -
+
+
+status_t
+random_added_device(device_node *node)
+{
+       CALLED();
+
+       void *cookie;
+
+       status_t status = gDeviceManager->get_driver(node,
+               (driver_module_info **)&sRandomModule, &cookie);
+
        return status;
 }
 
 
+
 //     #pragma mark -
 
 
 module_dependency module_dependencies[] = {
-       {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager},
+       {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager},
        {}
 };
 
+
 struct device_module_info sRandomDevice = {
        {
                RANDOM_DEVICE_MODULE_NAME,
@@ -254,6 +286,7 @@ struct device_module_info sRandomDevice = {
        random_deselect,
 };
 
+
 struct driver_module_info sRandomDriver = {
        {
                RANDOM_DRIVER_MODULE_NAME,
@@ -270,8 +303,28 @@ struct driver_module_info sRandomDriver = {
        NULL,   // removed
 };
 
+
+random_for_controller_interface sRandomForControllerModule = {
+       {
+               {
+                       RANDOM_FOR_CONTROLLER_MODULE_NAME,
+                       0,
+                       NULL
+               },
+
+               NULL, // supported devices
+               random_added_device,
+               NULL,
+               NULL,
+               NULL
+       }
+};
+
+
 module_info* modules[] = {
        (module_info*)&sRandomDriver,
        (module_info*)&sRandomDevice,
+       (module_info*)&sRandomForControllerModule,
+       (module_info*)&gYarrowRandomModule,
        NULL
 };
diff --git a/src/add-ons/kernel/bus_managers/random/random.h 
b/src/add-ons/kernel/bus_managers/random/random.h
index 743305f..23c9d10 100644
--- a/src/add-ons/kernel/bus_managers/random/random.h
+++ b/src/add-ons/kernel/bus_managers/random/random.h
@@ -9,12 +9,25 @@
 #define _RANDOM_H
 
 
+#include <device_manager.h>
+
+
+typedef struct {
+       driver_module_info info;
+} random_for_controller_interface;
+
+
+#define RANDOM_FOR_CONTROLLER_MODULE_NAME 
"bus_managers/random/controller/driver_v1"
+
+// Bus manager interface used by Random controller drivers.
 typedef struct random_module_info {
+       driver_module_info info;
+
        status_t (*init)();
        void (*uninit)();
        status_t (*read)(void *_buffer, size_t *_numBytes);
        status_t (*write)(const void *_buffer, size_t *_numBytes);
-} random_module_info;
+} random_sim_interface;
 
 
 #endif /* _RANDOM_H */
diff --git a/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp 
b/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp
index d144d34..6be1acb 100644
--- a/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp
+++ b/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp
@@ -12,6 +12,15 @@
 #include <thread.h>
 
 
+//#define TRACE_DRIVER
+#ifdef TRACE_DRIVER
+#      define TRACE(x...) dprintf("random: " x)
+#else
+#      define TRACE(x...) ;
+#endif
+#define CALLED()                       TRACE("CALLED %s\n", 
__PRETTY_FUNCTION__)
+
+
 #define rotr32(x, n) ((((uint32)(x)) >> ((int) ((n) & 31))) | (((uint32)(x)) 
<< ((int) ((32 - ((n) & 31))))))
 #define rotl32(x, n) ((((uint32)(x)) << ((int) ((n) & 31))) | (((uint32)(x)) 
>> ((int) ((32 - ((n) & 31))))))
 
@@ -335,12 +344,53 @@ yarrow_rng_write(const void *buffer, size_t *_numBytes)
 }
 
 
-random_module_info sYarrowRandomModule = {
+//     #pragma mark -
+
+
+static status_t
+yarrow_init_bus(device_node* node, void** bus_cookie)
+{
+       CALLED();
+       return yarrow_rng_init();
+}
+
+
+static void
+yarrow_uninit_bus(void* bus_cookie)
+{
+       CALLED();
+       yarrow_rng_uninit();
+}
+
+
+static void
+yarrow_bus_removed(void* bus_cookie)
+{
+       return;
+}
+
+
+//     #pragma mark -
+
+
+random_module_info gYarrowRandomModule = {
+       {
+               {
+                       YARROW_RNG_SIM_MODULE_NAME,
+                       0,
+                       NULL
+               },
+
+               NULL, // supports_device,
+               NULL, // register_device,
+               yarrow_init_bus,
+               yarrow_uninit_bus,
+               NULL,   // register child devices
+               NULL,   // rescan
+               yarrow_bus_removed,
+       },
        yarrow_rng_init,
        yarrow_rng_uninit,
        yarrow_rng_read,
        yarrow_rng_write
 };
-
-
-random_module_info *gYarrowRandomModule = &sYarrowRandomModule;
diff --git a/src/add-ons/kernel/bus_managers/random/yarrow_rng.h 
b/src/add-ons/kernel/bus_managers/random/yarrow_rng.h
index 9f73719..b76f314 100644
--- a/src/add-ons/kernel/bus_managers/random/yarrow_rng.h
+++ b/src/add-ons/kernel/bus_managers/random/yarrow_rng.h
@@ -14,12 +14,15 @@
 #include "random.h"
 
 
+#define YARROW_RNG_SIM_MODULE_NAME "bus_managers/random/yarrow_rng/device/v1"
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 
-extern random_module_info* gYarrowRandomModule;
+extern random_module_info gYarrowRandomModule;
 
 
 #ifdef __cplusplus

############################################################################

Commit:      eb5639c43ec74cf0fd714685a6add1c54a2388ac
URL:         http://cgit.haiku-os.org/haiku/commit/?id=eb5639c
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Thu Aug 29 16:30:48 2013 UTC

device_manager: tune the search paths

* the Virtio RNG PCI device has the class 0, so can't be found using usual
paths. Add 0 to _AlwaysRegisterDynamic() and "busses/virtio" in 
_GetNextDriverPath()
for non generic drivers to help finding virtio_pci.
* The RNG Virtio device is generic and needs "busses/random" to find virtio_rng.

----------------------------------------------------------------------------

diff --git a/src/system/kernel/device_manager/device_manager.cpp 
b/src/system/kernel/device_manager/device_manager.cpp
index fff9626..e73c025 100644
--- a/src/system/kernel/device_manager/device_manager.cpp
+++ b/src/system/kernel/device_manager/device_manager.cpp
@@ -1608,6 +1608,7 @@ device_node::_GetNextDriverPath(void*& cookie, KPath& 
_path)
                                        _AddPath(*stack, "busses/pci");
                                        _AddPath(*stack, "bus_managers");
                                } else if (!generic) {
+                                       _AddPath(*stack, "busses", "virtio");
                                        _AddPath(*stack, "drivers");
                                } else {
                                        // For generic drivers, we only allow 
busses when the
@@ -1619,7 +1620,8 @@ device_node::_GetNextDriverPath(void*& cookie, KPath& 
_path)
                                                _AddPath(*stack, "busses");
                                        }
                                        _AddPath(*stack, "drivers", 
sGenericContextPath);
-                                       _AddPath(*stack, "busses/scsi");        
                                
+                                       _AddPath(*stack, "busses/scsi");
+                                       _AddPath(*stack, "busses/random");
                                }
                                break;
                }
@@ -1736,7 +1738,7 @@ device_node::_AlwaysRegisterDynamic()
        get_attr_uint16(this, B_DEVICE_TYPE, &type, false);
        get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false);
 
-       return type == PCI_serial_bus || type == PCI_bridge;
+       return type == PCI_serial_bus || type == PCI_bridge || type == 0;
                // TODO: we may want to be a bit more specific in the future
 }
 
@@ -2308,4 +2310,3 @@ device_manager_init_post_modules(struct kernel_args* args)
        RecursiveLocker _(sLock);
        return sRootNode->Reprobe();
 }
-

############################################################################

Commit:      8d2bf6953e851d431fc67de1bc970c40afa79e9f
URL:         http://cgit.haiku-os.org/haiku/commit/?id=8d2bf69
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Thu Aug 29 16:38:46 2013 UTC

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.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/bus_managers/random/random.h 
b/headers/private/drivers/random.h
similarity index 75%
rename from src/add-ons/kernel/bus_managers/random/random.h
rename to headers/private/drivers/random.h
index 23c9d10..cc4d1d5 100644
--- a/src/add-ons/kernel/bus_managers/random/random.h
+++ b/headers/private/drivers/random.h
@@ -23,11 +23,9 @@ typedef struct {
 typedef struct random_module_info {
        driver_module_info info;
 
-       status_t (*init)();
-       void (*uninit)();
-       status_t (*read)(void *_buffer, size_t *_numBytes);
-       status_t (*write)(const void *_buffer, size_t *_numBytes);
-} random_sim_interface;
+       status_t (*read)(void* cookie, void *_buffer, size_t *_numBytes);
+       status_t (*write)(void* cookie, const void *_buffer, size_t *_numBytes);
+} random_module_info;
 
 
 #endif /* _RANDOM_H */
diff --git a/src/add-ons/kernel/bus_managers/random/Jamfile 
b/src/add-ons/kernel/bus_managers/random/Jamfile
index f5a33f9..8772580 100644
--- a/src/add-ons/kernel/bus_managers/random/Jamfile
+++ b/src/add-ons/kernel/bus_managers/random/Jamfile
@@ -1,5 +1,6 @@
 SubDir HAIKU_TOP src add-ons kernel bus_managers random ;
 
+UsePrivateHeaders drivers ;
 UsePrivateKernelHeaders ;
 
 KernelAddon random :
diff --git a/src/add-ons/kernel/bus_managers/random/driver.cpp 
b/src/add-ons/kernel/bus_managers/random/driver.cpp
index 715f1691..deb937a 100644
--- a/src/add-ons/kernel/bus_managers/random/driver.cpp
+++ b/src/add-ons/kernel/bus_managers/random/driver.cpp
@@ -32,7 +32,8 @@
 
 
 static mutex sRandomLock;
-static random_sim_interface *sRandomModule;
+static random_module_info *sRandomModule;
+static void *sRandomCookie;
 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);
 
        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);
        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();
 
-       void *cookie;
-
        status_t status = gDeviceManager->get_driver(node,
-               (driver_module_info **)&sRandomModule, &cookie);
+               (driver_module_info **)&sRandomModule, &sRandomCookie);
 
        return status;
 }
diff --git a/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp 
b/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp
index 6be1acb..bab1123 100644
--- a/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp
+++ b/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp
@@ -290,24 +290,7 @@ kill_chrand(ch_randgen *randgen)
 
 
 static status_t
-yarrow_rng_init()
-{
-       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)
+yarrow_rng_read(void* cookie, void *_buffer, size_t *_numBytes)
 {
        sRandomCount += *_numBytes;
 
@@ -333,7 +316,7 @@ yarrow_rng_read(void *_buffer, size_t *_numBytes)
 
 
 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;
        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)
 {
        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)
 {
        CALLED();
-       yarrow_rng_uninit();
+       kill_chrand(sRandomEnv);
 }
 
 
@@ -389,8 +375,6 @@ random_module_info gYarrowRandomModule = {
                NULL,   // rescan
                yarrow_bus_removed,
        },
-       yarrow_rng_init,
-       yarrow_rng_uninit,
        yarrow_rng_read,
        yarrow_rng_write
 };
diff --git a/src/add-ons/kernel/busses/Jamfile 
b/src/add-ons/kernel/busses/Jamfile
index 2c9ee48..74adc1b 100644
--- a/src/add-ons/kernel/busses/Jamfile
+++ b/src/add-ons/kernel/busses/Jamfile
@@ -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 random ;
 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 virtio ;
diff --git a/src/add-ons/kernel/busses/random/Jamfile 
b/src/add-ons/kernel/busses/random/Jamfile
new file mode 100644
index 0000000..d1d610b
--- /dev/null
+++ b/src/add-ons/kernel/busses/random/Jamfile
@@ -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
+;
diff --git a/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp 
b/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp
new file mode 100644
index 0000000..7aa9ae0
--- /dev/null
+++ b/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * 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();
+}
diff --git a/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h 
b/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h
new file mode 100644
index 0000000..60a4921
--- /dev/null
+++ b/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * 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
diff --git a/src/add-ons/kernel/busses/random/virtio_rng.cpp 
b/src/add-ons/kernel/busses/random/virtio_rng.cpp
new file mode 100644
index 0000000..951c4eb
--- /dev/null
+++ b/src/add-ons/kernel/busses/random/virtio_rng.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * 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
+};

############################################################################

Revision:    hrev45998
Commit:      86af5f159bbd93b977407e8df5ac5f5fe04c2b05
URL:         http://cgit.haiku-os.org/haiku/commit/?id=86af5f1
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Thu Aug 29 16:43:51 2013 UTC

VirtioRNG: add to the image

----------------------------------------------------------------------------

diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage
index 88da45e..84b2500 100644
--- a/build/jam/HaikuImage
+++ b/build/jam/HaikuImage
@@ -226,6 +226,8 @@ if $(HAIKU_ATA_STACK) = 1 {
                : generic_ide_pci it8211 legacy_sata silicon_image_3112 
ide_isa@x86 ;
 }
 
+AddFilesToHaikuImage system add-ons kernel busses random
+       : virtio_rng ;
 AddFilesToHaikuImage system add-ons kernel busses scsi
        : ahci virtio_scsi ;
 AddFilesToHaikuImage system add-ons kernel busses usb


Other related posts:

  • » [haiku-commits] haiku: hrev45998 - src/add-ons/kernel/busses/random src/add-ons/kernel/bus_managers/random headers/private/drivers - korli