* Copyright 2013, JΓ©rΓ΄me Duval, korli@users.berlios.de.
* Distributed under the terms of the MIT License.
*/
#ifndef VIRTIO_PRIVATE_H
#define VIRTIO_PRIVATE_H
#include <new>
#include <stdio.h>
#include <string.h>
#include <lock.h>
#include <util/AutoLock.h>
#include <virtio.h>
#include "virtio_ring.h"
#ifdef VIRTIO_TRACE
# define TRACE(x...) dprintf("\33[33mvirtio:\33[0m " x)
#else
# define TRACE(x...)
#endif
#define TRACE_ALWAYS(x...) dprintf("\33[33mvirtio:\33[0m " x)
#define ERROR(x...) TRACE_ALWAYS(x)
#define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
#define VIRTIO_SIM_MODULE_NAME "bus_managers/virtio/sim/driver_v1"
class VirtioDevice;
class VirtioQueue;
extern device_manager_info *gDeviceManager;
class VirtioDevice {
public:
VirtioDevice(device_node *node);
~VirtioDevice();
status_t InitCheck();
uint32 ID() const { return fID; }
status_t NegotiateFeatures(uint64 supported,
uint64* negotiated,
const char* (*get_feature_name)(uint64));
status_t ClearFeature(uint64 feature);
status_t ReadDeviceConfig(uint8 offset, void* buffer,
size_t bufferSize);
status_t WriteDeviceConfig(uint8 offset,
const void* buffer, size_t bufferSize);
status_t AllocateQueues(size_t count,
virtio_queue *queues,
uint16 *requestedSizes);
void FreeQueues();
status_t SetupInterrupt(virtio_intr_func config_handler,
void *driverCookie);
status_t FreeInterrupts();
uint16 Alignment() const { return fAlignment; }
uint64 Features() const { return fFeatures; }
void* DriverCookie() { return fDriverCookie; }
status_t SetupQueue(uint16 queueNumber,
phys_addr_t physAddr, phys_addr_t phyAvail,
phys_addr_t phyUsed);
void NotifyQueue(uint16 queueNumber);
status_t QueueInterrupt(uint16 queueNumber);
status_t ConfigInterrupt();
private:
void _DumpFeatures(const char* title,
uint64 features,
const char* (*get_feature_name)(uint64));
void _DestroyQueues(size_t count);
device_node * fNode;
uint32 fID;
virtio_sim_interface *fController;
void * fCookie;
status_t fStatus;
VirtioQueue** fQueues;
size_t fQueueCount;
uint64 fFeatures;
uint16 fAlignment;
bool fVirtio1;
virtio_intr_func fConfigHandler;
void* fDriverCookie;
};
class TransferDescriptor;
class VirtioQueue {
public:
VirtioQueue(VirtioDevice *device,
uint16 queueNumber, uint16 ringSize);
~VirtioQueue();
status_t InitCheck() { return fStatus; }
void NotifyHost();
status_t Interrupt();
bool IsFull() const { return fRingFree == 0; }
bool IsEmpty() const { return fRingFree == fRingSize; }
uint16 Size() const { return fRingSize; }
VirtioDevice* Device() { return fDevice; }
status_t QueueRequest(const physical_entry* vector,
size_t readVectorCount,
size_t writtenVectorCount,
void *cookie);
status_t QueueRequestIndirect(
const physical_entry* vector,
size_t readVectorCount,
size_t writtenVectorCount,
void *cookie);
status_t SetupInterrupt(virtio_callback_func handler,
void *cookie);
void EnableInterrupt();
void DisableInterrupt();
bool Dequeue(void** _cookie = NULL,
uint32* _usedLength = NULL);
private:
void UpdateAvailable(uint16 index);
uint16 QueueVector(uint16 insertIndex,
struct vring_desc *desc,
const physical_entry* vector,
size_t readVectorCount,
size_t writtenVectorCount);
VirtioDevice* fDevice;
uint16 fQueueNumber;
uint16 fRingSize;
uint16 fRingFree;
struct vring fRing;
uint16 fRingHeadIndex;
uint16 fRingUsedIndex;
status_t fStatus;
size_t fAreaSize;
area_id fArea;
uint16 fIndirectMaxSize;
TransferDescriptor** fDescriptors;
virtio_callback_func fCallback;
void* fCookie;
};
#endif