2 * Copyright 2013, Jérôme Duval, korli@users.berlios.de.
3 * Distributed under the terms of the MIT License.
7 #include "VirtioRNGPrivate.h"
13 #include <util/AutoLock.h>
17 get_feature_name(uint32 feature
)
25 VirtioRNGDevice::VirtioRNGDevice(device_node
*node
)
32 fExpectsInterrupt(false)
36 B_INITIALIZE_SPINLOCK(&fInterruptLock
);
37 fInterruptCondition
.Init(this, "virtio rng transfer");
39 get_memory_map(fBuffer
, BUFFER_SIZE
, &fEntry
, 1);
41 // get the Virtio device from our parent's parent
42 device_node
*parent
= gDeviceManager
->get_parent_node(node
);
43 device_node
*virtioParent
= gDeviceManager
->get_parent_node(parent
);
44 gDeviceManager
->put_node(parent
);
46 gDeviceManager
->get_driver(virtioParent
, (driver_module_info
**)&fVirtio
,
47 (void **)&fVirtioDevice
);
48 gDeviceManager
->put_node(virtioParent
);
50 fVirtio
->negociate_features(fVirtioDevice
,
51 0, &fFeatures
, &get_feature_name
);
53 fStatus
= fVirtio
->alloc_queues(fVirtioDevice
, 1, &fVirtioQueue
);
54 if (fStatus
!= B_OK
) {
55 ERROR("queue allocation failed (%s)\n", strerror(fStatus
));
59 fStatus
= fVirtio
->setup_interrupt(fVirtioDevice
, NULL
, this);
60 if (fStatus
!= B_OK
) {
61 ERROR("interrupt setup failed (%s)\n", strerror(fStatus
));
67 VirtioRNGDevice::~VirtioRNGDevice()
73 VirtioRNGDevice::InitCheck()
80 VirtioRNGDevice::Read(void* _buffer
, size_t* _numBytes
)
84 if (fOffset
>= BUFFER_SIZE
) {
86 InterruptsSpinLocker
locker(fInterruptLock
);
87 fExpectsInterrupt
= true;
88 fInterruptCondition
.Add(&fInterruptConditionEntry
);
90 status_t result
= fVirtio
->queue_request(fVirtioQueue
, NULL
, &fEntry
,
91 _RequestCallback
, this);
93 ERROR("queueing failed (%s)\n", strerror(result
));
97 result
= fInterruptConditionEntry
.Wait(B_CAN_INTERRUPT
);
100 InterruptsSpinLocker
locker(fInterruptLock
);
101 fExpectsInterrupt
= false;
104 if (result
== B_OK
) {
106 } else if (result
!= B_INTERRUPTED
) {
107 ERROR("request failed (%s)\n", strerror(result
));
111 if (fOffset
< BUFFER_SIZE
) {
112 size_t size
= min_c(BUFFER_SIZE
- fOffset
, *_numBytes
);
113 memcpy(_buffer
, fBuffer
+ fOffset
, size
);
123 VirtioRNGDevice::_RequestCallback(void* driverCookie
, void* cookie
)
125 VirtioRNGDevice
* device
= (VirtioRNGDevice
*)driverCookie
;
126 device
->_RequestInterrupt();
131 VirtioRNGDevice::_RequestInterrupt()
133 SpinLocker
locker(fInterruptLock
);
134 fInterruptCondition
.NotifyAll();