⛏️ index : haiku.git

/*
 * 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"


//#define VIRTIO_TRACE
#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 // VIRTIO_PRIVATE_H