1/*
2 * Copyright 2021, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _VIRTIODEVICE_H_
6#define _VIRTIODEVICE_H_
7
8
9#include <virtio.h>
10#include <virtio_defs.h>
11#include <AutoDeleter.h>
12#include <AutoDeleterOS.h>
13#include <Referenceable.h>
14#include <util/AutoLock.h>
15#include <util/Bitmap.h>
16
17
18//#define TRACE_VIRTIO
19#ifdef TRACE_VIRTIO
20#	define TRACE(x...) dprintf("virtio_mmio: " x)
21#else
22#	define TRACE(x...) ;
23#endif
24
25#define TRACE_ALWAYS(x...) dprintf("virtio_mmio: " x)
26#define ERROR(x...) dprintf("virtio_mmio: " x)
27
28
29struct VirtioIrqHandler;
30struct VirtioDevice;
31
32struct VirtioQueue {
33	VirtioDevice *fDev;
34	int32 fId;
35	size_t fQueueLen;
36	size_t fDescCount;
37	AreaDeleter fArea;
38	volatile VirtioDesc  *fDescs;
39	volatile VirtioAvail *fAvail;
40	volatile VirtioUsed  *fUsed;
41	Bitmap fAllocatedDescs;
42	uint16 fLastUsed;
43	ArrayDeleter<void*> fCookies;
44
45	BReference<VirtioIrqHandler> fQueueHandlerRef;
46	virtio_callback_func fQueueHandler;
47	void *fQueueHandlerCookie;
48
49	VirtioQueue(VirtioDevice *dev, int32 id);
50	~VirtioQueue();
51	status_t Init();
52
53	int32 AllocDesc();
54	void FreeDesc(int32 idx);
55
56	status_t Enqueue(
57		const physical_entry* vector,
58		size_t readVectorCount, size_t writtenVectorCount,
59		void* cookie
60	);
61
62	bool Dequeue(void** _cookie, uint32* _usedLength);
63};
64
65
66struct VirtioIrqHandler: public BReferenceable
67{
68	VirtioDevice* fDev;
69
70	VirtioIrqHandler(VirtioDevice* dev);
71
72	virtual void FirstReferenceAcquired();
73	virtual void LastReferenceReleased();
74
75	static int32 Handle(void* data);
76};
77
78
79struct VirtioDevice
80{
81	AreaDeleter fRegsArea;
82	volatile VirtioRegs *fRegs;
83	int32 fIrq;
84	int32 fQueueCnt;
85	ArrayDeleter<ObjectDeleter<VirtioQueue> > fQueues;
86
87	VirtioIrqHandler fIrqHandler;
88
89	BReference<VirtioIrqHandler> fConfigHandlerRef;
90	virtio_intr_func fConfigHandler;
91	void* fConfigHandlerCookie;
92
93	VirtioDevice();
94	status_t Init(phys_addr_t regs, size_t regsLen, int32 irq, int32 queueCnt);
95};
96
97
98#endif	// _VIRTIODEVICE_H_
99