1f8296c60SJoshua M. Clulow /*
2f8296c60SJoshua M. Clulow  * This file and its contents are supplied under the terms of the
3f8296c60SJoshua M. Clulow  * Common Development and Distribution License ("CDDL"), version 1.0.
4f8296c60SJoshua M. Clulow  * You may only use this file in accordance with the terms of version
5f8296c60SJoshua M. Clulow  * 1.0 of the CDDL.
6f8296c60SJoshua M. Clulow  *
7f8296c60SJoshua M. Clulow  * A full copy of the text of the CDDL should have accompanied this
8f8296c60SJoshua M. Clulow  * source.  A copy of the CDDL is also available via the Internet at
9f8296c60SJoshua M. Clulow  * http://www.illumos.org/license/CDDL.
10f8296c60SJoshua M. Clulow  */
11f8296c60SJoshua M. Clulow 
12f8296c60SJoshua M. Clulow /*
13f8296c60SJoshua M. Clulow  * Copyright 2019 Joyent, Inc.
14*501bc5c0SAndy Fiddaman  * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
15f8296c60SJoshua M. Clulow  */
16f8296c60SJoshua M. Clulow 
17f8296c60SJoshua M. Clulow #ifndef _VIRTIO_IMPL_H
18f8296c60SJoshua M. Clulow #define	_VIRTIO_IMPL_H
19f8296c60SJoshua M. Clulow 
20f8296c60SJoshua M. Clulow /*
21f8296c60SJoshua M. Clulow  * VIRTIO FRAMEWORK: FRAMEWORK-PRIVATE DEFINITIONS
22f8296c60SJoshua M. Clulow  *
23f8296c60SJoshua M. Clulow  * For design and usage documentation, see the comments in "virtio.h".
24f8296c60SJoshua M. Clulow  *
25f8296c60SJoshua M. Clulow  * NOTE: Client drivers should not use definitions from this file.
26f8296c60SJoshua M. Clulow  */
27f8296c60SJoshua M. Clulow 
28f8296c60SJoshua M. Clulow #include <sys/types.h>
29f8296c60SJoshua M. Clulow #include <sys/dditypes.h>
30f8296c60SJoshua M. Clulow #include <sys/list.h>
31f8296c60SJoshua M. Clulow #include <sys/ccompile.h>
32f8296c60SJoshua M. Clulow 
33f8296c60SJoshua M. Clulow #include "virtio.h"
34f8296c60SJoshua M. Clulow 
35f8296c60SJoshua M. Clulow #ifdef __cplusplus
36f8296c60SJoshua M. Clulow extern "C" {
37f8296c60SJoshua M. Clulow #endif
38f8296c60SJoshua M. Clulow 
39f8296c60SJoshua M. Clulow extern ddi_device_acc_attr_t virtio_acc_attr;
40f8296c60SJoshua M. Clulow extern ddi_dma_attr_t virtio_dma_attr;
41f8296c60SJoshua M. Clulow 
42f8296c60SJoshua M. Clulow typedef struct virtio_vq_desc virtio_vq_desc_t;
43f8296c60SJoshua M. Clulow typedef struct virtio_vq_driver virtio_vq_driver_t;
44f8296c60SJoshua M. Clulow typedef struct virtio_vq_device virtio_vq_device_t;
45f8296c60SJoshua M. Clulow typedef struct virtio_vq_elem virtio_vq_elem_t;
46f8296c60SJoshua M. Clulow 
47f8296c60SJoshua M. Clulow int virtio_dma_init(virtio_t *, virtio_dma_t *, size_t, const ddi_dma_attr_t *,
48f8296c60SJoshua M. Clulow     int, int);
49f8296c60SJoshua M. Clulow void virtio_dma_fini(virtio_dma_t *);
50f8296c60SJoshua M. Clulow 
51f8296c60SJoshua M. Clulow 
52f8296c60SJoshua M. Clulow 
53f8296c60SJoshua M. Clulow typedef enum virtio_dma_level {
54f8296c60SJoshua M. Clulow 	VIRTIO_DMALEVEL_HANDLE_ALLOC =	(1ULL << 0),
55f8296c60SJoshua M. Clulow 	VIRTIO_DMALEVEL_MEMORY_ALLOC =	(1ULL << 1),
56f8296c60SJoshua M. Clulow 	VIRTIO_DMALEVEL_HANDLE_BOUND =	(1ULL << 2),
57f8296c60SJoshua M. Clulow 	VIRTIO_DMALEVEL_COOKIE_ARRAY =	(1ULL << 3),
58f8296c60SJoshua M. Clulow } virtio_dma_level_t;
59f8296c60SJoshua M. Clulow 
60f8296c60SJoshua M. Clulow struct virtio_dma {
61f8296c60SJoshua M. Clulow 	virtio_dma_level_t		vidma_level;
62f8296c60SJoshua M. Clulow 	virtio_t			*vidma_virtio;
63f8296c60SJoshua M. Clulow 	caddr_t				vidma_va;
64f8296c60SJoshua M. Clulow 	size_t				vidma_size;
65f8296c60SJoshua M. Clulow 	size_t				vidma_real_size;
66f8296c60SJoshua M. Clulow 	ddi_dma_handle_t		vidma_dma_handle;
67f8296c60SJoshua M. Clulow 	ddi_acc_handle_t		vidma_acc_handle;
68f8296c60SJoshua M. Clulow 	uint_t				vidma_dma_ncookies;
69f8296c60SJoshua M. Clulow 	ddi_dma_cookie_t		*vidma_dma_cookies;
70f8296c60SJoshua M. Clulow };
71f8296c60SJoshua M. Clulow 
72f8296c60SJoshua M. Clulow typedef enum virtio_initlevel {
73f8296c60SJoshua M. Clulow 	VIRTIO_INITLEVEL_REGS =		(1ULL << 0),
74f8296c60SJoshua M. Clulow 	VIRTIO_INITLEVEL_PROVIDER =	(1ULL << 1),
75f8296c60SJoshua M. Clulow 	VIRTIO_INITLEVEL_INT_ALLOC =	(1ULL << 2),
76f8296c60SJoshua M. Clulow 	VIRTIO_INITLEVEL_INT_ADDED =	(1ULL << 3),
77f8296c60SJoshua M. Clulow 	VIRTIO_INITLEVEL_INT_ENABLED =	(1ULL << 4),
78f8296c60SJoshua M. Clulow 	VIRTIO_INITLEVEL_SHUTDOWN =	(1ULL << 5),
79f8296c60SJoshua M. Clulow } virtio_initlevel_t;
80f8296c60SJoshua M. Clulow 
81f8296c60SJoshua M. Clulow struct virtio {
82f8296c60SJoshua M. Clulow 	dev_info_t			*vio_dip;
83f8296c60SJoshua M. Clulow 
84f8296c60SJoshua M. Clulow 	kmutex_t			vio_mutex;
85f8296c60SJoshua M. Clulow 
86f8296c60SJoshua M. Clulow 	virtio_initlevel_t		vio_initlevel;
87f8296c60SJoshua M. Clulow 
88f8296c60SJoshua M. Clulow 	list_t				vio_queues;
89f8296c60SJoshua M. Clulow 
90f8296c60SJoshua M. Clulow 	ddi_acc_handle_t		vio_barh;
91f8296c60SJoshua M. Clulow 	caddr_t				vio_bar;
92f8296c60SJoshua M. Clulow 	uint_t				vio_config_offset;
93f8296c60SJoshua M. Clulow 
94f8296c60SJoshua M. Clulow 	uint32_t			vio_features;
95f8296c60SJoshua M. Clulow 	uint32_t			vio_features_device;
96f8296c60SJoshua M. Clulow 
97f8296c60SJoshua M. Clulow 	ddi_intr_handle_t		*vio_interrupts;
98f8296c60SJoshua M. Clulow 	int				vio_ninterrupts;
99f8296c60SJoshua M. Clulow 	int				vio_interrupt_type;
100f8296c60SJoshua M. Clulow 	int				vio_interrupt_cap;
101f8296c60SJoshua M. Clulow 	uint_t				vio_interrupt_priority;
102*501bc5c0SAndy Fiddaman 
103*501bc5c0SAndy Fiddaman 	ddi_intr_handler_t		*vio_cfgchange_handler;
104*501bc5c0SAndy Fiddaman 	void				*vio_cfgchange_handlerarg;
105*501bc5c0SAndy Fiddaman 	boolean_t			vio_cfgchange_handler_added;
106*501bc5c0SAndy Fiddaman 	uint_t				vio_cfgchange_handler_index;
107f8296c60SJoshua M. Clulow };
108f8296c60SJoshua M. Clulow 
109f8296c60SJoshua M. Clulow struct virtio_queue {
110f8296c60SJoshua M. Clulow 	virtio_t			*viq_virtio;
111f8296c60SJoshua M. Clulow 	kmutex_t			viq_mutex;
112f8296c60SJoshua M. Clulow 	const char			*viq_name;
113f8296c60SJoshua M. Clulow 	list_node_t			viq_link;
114f8296c60SJoshua M. Clulow 
115f8296c60SJoshua M. Clulow 	boolean_t			viq_shutdown;
116f8296c60SJoshua M. Clulow 	boolean_t			viq_indirect;
117f8296c60SJoshua M. Clulow 	uint_t				viq_max_segs;
118f8296c60SJoshua M. Clulow 
119f8296c60SJoshua M. Clulow 	/*
120f8296c60SJoshua M. Clulow 	 * Each Virtio device type has some set of queues for data transfer to
121f8296c60SJoshua M. Clulow 	 * and from the host.  This index is described in the specification for
122f8296c60SJoshua M. Clulow 	 * the particular device and queue type, and written to QUEUE_SELECT to
123f8296c60SJoshua M. Clulow 	 * allow interaction with the queue.  For example, a network device has
124f8296c60SJoshua M. Clulow 	 * at least a receive queue with index 0, and a transmit queue with
125f8296c60SJoshua M. Clulow 	 * index 1.
126f8296c60SJoshua M. Clulow 	 */
127f8296c60SJoshua M. Clulow 	uint16_t			viq_index;
128f8296c60SJoshua M. Clulow 
129f8296c60SJoshua M. Clulow 	/*
130f8296c60SJoshua M. Clulow 	 * For legacy Virtio devices, the size and shape of the queue is
131f8296c60SJoshua M. Clulow 	 * determined entirely by the number of queue entries.
132f8296c60SJoshua M. Clulow 	 */
133f8296c60SJoshua M. Clulow 	uint16_t			viq_size;
134f8296c60SJoshua M. Clulow 	id_space_t			*viq_descmap;
135f8296c60SJoshua M. Clulow 
136f8296c60SJoshua M. Clulow 	/*
137f8296c60SJoshua M. Clulow 	 * The memory shared between the device and the driver is allocated as
138f8296c60SJoshua M. Clulow 	 * a large phyisically contiguous chunk.  Access to this area is
139f8296c60SJoshua M. Clulow 	 * through three pointers to packed structures.
140f8296c60SJoshua M. Clulow 	 */
141f8296c60SJoshua M. Clulow 	virtio_dma_t			viq_dma;
142f8296c60SJoshua M. Clulow 	virtio_vq_desc_t		*viq_dma_descs;
143f8296c60SJoshua M. Clulow 	virtio_vq_driver_t		*viq_dma_driver;
144f8296c60SJoshua M. Clulow 	virtio_vq_device_t		*viq_dma_device;
145f8296c60SJoshua M. Clulow 
146f8296c60SJoshua M. Clulow 	uint16_t			viq_device_index;
147f8296c60SJoshua M. Clulow 	uint16_t			viq_driver_index;
148f8296c60SJoshua M. Clulow 
149f8296c60SJoshua M. Clulow 	/*
150f8296c60SJoshua M. Clulow 	 * Interrupt handler function, or NULL if not provided.
151f8296c60SJoshua M. Clulow 	 */
152f8296c60SJoshua M. Clulow 	ddi_intr_handler_t		*viq_func;
153f8296c60SJoshua M. Clulow 	void				*viq_funcarg;
154f8296c60SJoshua M. Clulow 	boolean_t			viq_handler_added;
155f8296c60SJoshua M. Clulow 	uint_t				viq_handler_index;
156f8296c60SJoshua M. Clulow 
157f8296c60SJoshua M. Clulow 	/*
158f8296c60SJoshua M. Clulow 	 * When a chain is submitted to the queue, it is also stored in this
159f8296c60SJoshua M. Clulow 	 * AVL tree keyed by the index of the first descriptor in the chain.
160f8296c60SJoshua M. Clulow 	 */
161f8296c60SJoshua M. Clulow 	avl_tree_t			viq_inflight;
162f8296c60SJoshua M. Clulow };
163f8296c60SJoshua M. Clulow 
164f8296c60SJoshua M. Clulow struct virtio_chain {
165f8296c60SJoshua M. Clulow 	virtio_queue_t			*vic_vq;
166f8296c60SJoshua M. Clulow 	avl_node_t			vic_node;
167f8296c60SJoshua M. Clulow 
168f8296c60SJoshua M. Clulow 	void				*vic_data;
169f8296c60SJoshua M. Clulow 
170f8296c60SJoshua M. Clulow 	uint16_t			vic_head;
171f8296c60SJoshua M. Clulow 	uint32_t			vic_received_length;
172f8296c60SJoshua M. Clulow 
173f8296c60SJoshua M. Clulow 	virtio_dma_t			vic_indirect_dma;
174f8296c60SJoshua M. Clulow 	uint_t				vic_indirect_capacity;
175f8296c60SJoshua M. Clulow 	uint_t				vic_indirect_used;
176f8296c60SJoshua M. Clulow 
177f8296c60SJoshua M. Clulow 	uint_t				vic_direct_capacity;
178f8296c60SJoshua M. Clulow 	uint_t				vic_direct_used;
179f8296c60SJoshua M. Clulow 	uint16_t			vic_direct[];
180f8296c60SJoshua M. Clulow };
181f8296c60SJoshua M. Clulow 
182f8296c60SJoshua M. Clulow /*
183f8296c60SJoshua M. Clulow  * PACKED STRUCTS FOR DEVICE ACCESS
184f8296c60SJoshua M. Clulow  */
185f8296c60SJoshua M. Clulow 
186f8296c60SJoshua M. Clulow struct virtio_vq_desc {
187f8296c60SJoshua M. Clulow 	/*
188f8296c60SJoshua M. Clulow 	 * Buffer physical address and length.
189f8296c60SJoshua M. Clulow 	 */
190f8296c60SJoshua M. Clulow 	uint64_t			vqd_addr;
191f8296c60SJoshua M. Clulow 	uint32_t			vqd_len;
192f8296c60SJoshua M. Clulow 
193f8296c60SJoshua M. Clulow 	/*
194f8296c60SJoshua M. Clulow 	 * Flags.  Use with the VIRTQ_DESC_F_* family of constants.  See below.
195f8296c60SJoshua M. Clulow 	 */
196f8296c60SJoshua M. Clulow 	uint16_t			vqd_flags;
197f8296c60SJoshua M. Clulow 
198f8296c60SJoshua M. Clulow 	/*
199f8296c60SJoshua M. Clulow 	 * If VIRTQ_DESC_F_NEXT is set in flags, this refers to the next
200f8296c60SJoshua M. Clulow 	 * descriptor in the chain by table index.
201f8296c60SJoshua M. Clulow 	 */
202f8296c60SJoshua M. Clulow 	uint16_t			vqd_next;
203f8296c60SJoshua M. Clulow } __packed;
204f8296c60SJoshua M. Clulow 
205f8296c60SJoshua M. Clulow /*
206f8296c60SJoshua M. Clulow  * VIRTIO DESCRIPTOR FLAGS (vqd_flags)
207f8296c60SJoshua M. Clulow  */
208f8296c60SJoshua M. Clulow 
209f8296c60SJoshua M. Clulow /*
210f8296c60SJoshua M. Clulow  * NEXT:
211f8296c60SJoshua M. Clulow  *	Signals that this descriptor (direct or indirect) is part of a chain.
212f8296c60SJoshua M. Clulow  *	If populated, "vqd_next" names the next descriptor in the chain by its
213f8296c60SJoshua M. Clulow  *	table index.
214f8296c60SJoshua M. Clulow  */
215f8296c60SJoshua M. Clulow #define	VIRTQ_DESC_F_NEXT		(1 << 0)
216f8296c60SJoshua M. Clulow 
217f8296c60SJoshua M. Clulow /*
218f8296c60SJoshua M. Clulow  * WRITE:
219f8296c60SJoshua M. Clulow  *	Determines whether this buffer is to be written by the device (WRITE is
220f8296c60SJoshua M. Clulow  *	set) or by the driver (WRITE is not set).
221f8296c60SJoshua M. Clulow  */
222f8296c60SJoshua M. Clulow #define	VIRTQ_DESC_F_WRITE		(1 << 1)
223f8296c60SJoshua M. Clulow 
224f8296c60SJoshua M. Clulow /*
225f8296c60SJoshua M. Clulow  * INDIRECT:
226f8296c60SJoshua M. Clulow  *	This bit signals that a direct descriptor refers to an indirect
227f8296c60SJoshua M. Clulow  *	descriptor list, rather than directly to a buffer.  This bit may only
228f8296c60SJoshua M. Clulow  *	be used in a direct descriptor; indirect descriptors are not allowed to
229f8296c60SJoshua M. Clulow  *	refer to additional layers of indirect tables.  If this bit is set,
230f8296c60SJoshua M. Clulow  *	NEXT must be clear; indirect descriptors may not be chained.
231f8296c60SJoshua M. Clulow  */
232f8296c60SJoshua M. Clulow #define	VIRTQ_DESC_F_INDIRECT		(1 << 2)
233f8296c60SJoshua M. Clulow 
234f8296c60SJoshua M. Clulow /*
235f8296c60SJoshua M. Clulow  * This structure is variously known as the "available" or "avail" ring, or the
236f8296c60SJoshua M. Clulow  * driver-owned portion of the queue structure.  It is used by the driver to
237f8296c60SJoshua M. Clulow  * submit descriptor chains to the device.
238f8296c60SJoshua M. Clulow  */
239f8296c60SJoshua M. Clulow struct virtio_vq_driver {
240f8296c60SJoshua M. Clulow 	uint16_t			vqdr_flags;
241f8296c60SJoshua M. Clulow 	uint16_t			vqdr_index;
242f8296c60SJoshua M. Clulow 	uint16_t			vqdr_ring[];
243f8296c60SJoshua M. Clulow } __packed;
244f8296c60SJoshua M. Clulow 
245f8296c60SJoshua M. Clulow #define	VIRTQ_AVAIL_F_NO_INTERRUPT	(1 << 0)
246f8296c60SJoshua M. Clulow 
247f8296c60SJoshua M. Clulow /*
248f8296c60SJoshua M. Clulow  * We use the sizeof operator on this packed struct to calculate the offset of
249f8296c60SJoshua M. Clulow  * subsequent structs.  Ensure the compiler is not adding any padding to the
250f8296c60SJoshua M. Clulow  * end of the struct.
251f8296c60SJoshua M. Clulow  */
252f8296c60SJoshua M. Clulow CTASSERT(sizeof (virtio_vq_driver_t) ==
253f8296c60SJoshua M. Clulow     offsetof(virtio_vq_driver_t, vqdr_ring));
254f8296c60SJoshua M. Clulow 
255f8296c60SJoshua M. Clulow struct virtio_vq_elem {
256f8296c60SJoshua M. Clulow 	/*
257f8296c60SJoshua M. Clulow 	 * The device returns chains of descriptors by specifying the table
258f8296c60SJoshua M. Clulow 	 * index of the first descriptor in the chain.
259f8296c60SJoshua M. Clulow 	 */
260f8296c60SJoshua M. Clulow 	uint32_t			vqe_start;
261f8296c60SJoshua M. Clulow 	uint32_t			vqe_len;
262f8296c60SJoshua M. Clulow } __packed;
263f8296c60SJoshua M. Clulow 
264f8296c60SJoshua M. Clulow /*
265f8296c60SJoshua M. Clulow  * This structure is variously known as the "used" ring, or the device-owned
266f8296c60SJoshua M. Clulow  * portion of the queue structure.  It is used by the device to return
267c00b0288SJoshua M. Clulow  * completed descriptor chains to the driver.
268f8296c60SJoshua M. Clulow  */
269f8296c60SJoshua M. Clulow struct virtio_vq_device {
270f8296c60SJoshua M. Clulow 	uint16_t			vqde_flags;
271f8296c60SJoshua M. Clulow 	uint16_t			vqde_index;
272f8296c60SJoshua M. Clulow 	virtio_vq_elem_t		vqde_ring[];
273f8296c60SJoshua M. Clulow } __packed;
274f8296c60SJoshua M. Clulow 
275f8296c60SJoshua M. Clulow #define	VIRTQ_USED_F_NO_NOTIFY		(1 << 0)
276f8296c60SJoshua M. Clulow 
277f8296c60SJoshua M. Clulow /*
278f8296c60SJoshua M. Clulow  * BASIC CONFIGURATION
279f8296c60SJoshua M. Clulow  *
280f8296c60SJoshua M. Clulow  * Legacy devices expose both their generic and their device-specific
281f8296c60SJoshua M. Clulow  * configuration through PCI BAR0.  This is the second entry in the register
282f8296c60SJoshua M. Clulow  * address space set for these devices.
283f8296c60SJoshua M. Clulow  */
284f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_PCI_BAR0		1
285f8296c60SJoshua M. Clulow 
286f8296c60SJoshua M. Clulow /*
287f8296c60SJoshua M. Clulow  * These are offsets into the base configuration space available through the
288f8296c60SJoshua M. Clulow  * virtio_get*() and virtio_put*() family of functions.  These offsets are for
289f8296c60SJoshua M. Clulow  * what the specification describes as the "legacy" mode of device operation.
290f8296c60SJoshua M. Clulow  */
291f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_FEATURES_DEVICE	0x00	/* 32 R   */
292f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_FEATURES_DRIVER	0x04	/* 32 R/W */
293f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_QUEUE_ADDRESS	0x08	/* 32 R/W */
294f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_QUEUE_SIZE	0x0C	/* 16 R   */
295f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_QUEUE_SELECT	0x0E	/* 16 R/W */
296f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_QUEUE_NOTIFY	0x10	/* 16 R/W */
297f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_DEVICE_STATUS	0x12	/* 8  R/W */
298f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_ISR_STATUS	0x13	/* 8  R   */
299f8296c60SJoshua M. Clulow 
300f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_MSIX_CONFIG	0x14	/* 16 R/W */
301f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_MSIX_QUEUE	0x16	/* 16 R/W */
302f8296c60SJoshua M. Clulow 
303f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_CFG_OFFSET	(VIRTIO_LEGACY_ISR_STATUS + 1)
304f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_CFG_OFFSET_MSIX	(VIRTIO_LEGACY_MSIX_QUEUE + 2)
305f8296c60SJoshua M. Clulow 
306f8296c60SJoshua M. Clulow #define	VIRTIO_LEGACY_MSI_NO_VECTOR	0xFFFF
307f8296c60SJoshua M. Clulow 
308f8296c60SJoshua M. Clulow /*
309f8296c60SJoshua M. Clulow  * Bits in the Device Status byte (VIRTIO_LEGACY_DEVICE_STATUS):
310f8296c60SJoshua M. Clulow  */
311f8296c60SJoshua M. Clulow #define	VIRTIO_STATUS_RESET		0
312f8296c60SJoshua M. Clulow #define	VIRTIO_STATUS_ACKNOWLEDGE	(1 << 0)
313f8296c60SJoshua M. Clulow #define	VIRTIO_STATUS_DRIVER		(1 << 1)
314f8296c60SJoshua M. Clulow #define	VIRTIO_STATUS_DRIVER_OK		(1 << 2)
315f8296c60SJoshua M. Clulow #define	VIRTIO_STATUS_FAILED		(1 << 7)
316f8296c60SJoshua M. Clulow 
317f8296c60SJoshua M. Clulow /*
318f8296c60SJoshua M. Clulow  * Bits in the Interrupt Service Routine Status byte
319f8296c60SJoshua M. Clulow  * (VIRTIO_LEGACY_ISR_STATUS):
320f8296c60SJoshua M. Clulow  */
321f8296c60SJoshua M. Clulow #define	VIRTIO_ISR_CHECK_QUEUES		(1 << 0)
322f8296c60SJoshua M. Clulow #define	VIRTIO_ISR_CHECK_CONFIG		(1 << 1)
323f8296c60SJoshua M. Clulow 
324f8296c60SJoshua M. Clulow /*
325f8296c60SJoshua M. Clulow  * Bits in the Features fields (VIRTIO_LEGACY_FEATURES_DEVICE,
326f8296c60SJoshua M. Clulow  * VIRTIO_LEGACY_FEATURES_DRIVER):
327f8296c60SJoshua M. Clulow  */
328f8296c60SJoshua M. Clulow #define	VIRTIO_F_RING_INDIRECT_DESC	(1ULL << 28)
329f8296c60SJoshua M. Clulow 
330f8296c60SJoshua M. Clulow /*
331f8296c60SJoshua M. Clulow  * For devices operating in the legacy mode, virtqueues must be aligned on a
332f8296c60SJoshua M. Clulow  * "page size" of 4096 bytes; this is also called the "Queue Align" value in
333f8296c60SJoshua M. Clulow  * newer versions of the specification.
334f8296c60SJoshua M. Clulow  */
335f8296c60SJoshua M. Clulow #define	VIRTIO_PAGE_SHIFT		12
336f8296c60SJoshua M. Clulow #define	VIRTIO_PAGE_SIZE		(1 << VIRTIO_PAGE_SHIFT)
337f8296c60SJoshua M. Clulow CTASSERT(VIRTIO_PAGE_SIZE == 4096);
338f8296c60SJoshua M. Clulow CTASSERT(ISP2(VIRTIO_PAGE_SIZE));
339f8296c60SJoshua M. Clulow 
340f8296c60SJoshua M. Clulow /*
341f8296c60SJoshua M. Clulow  * DMA SYNCHRONISATION WRAPPERS
342f8296c60SJoshua M. Clulow  */
343f8296c60SJoshua M. Clulow 
344f8296c60SJoshua M. Clulow /*
345f8296c60SJoshua M. Clulow  * Synchronise the driver-owned portion of the queue so that the device can see
346f8296c60SJoshua M. Clulow  * our writes.  This covers the memory accessed via the "viq_dma_descs" and
347f8296c60SJoshua M. Clulow  * "viq_dma_device" members.
348f8296c60SJoshua M. Clulow  */
349f8296c60SJoshua M. Clulow #define	VIRTQ_DMA_SYNC_FORDEV(viq)	VERIFY0(ddi_dma_sync( \
350f8296c60SJoshua M. Clulow 					    (viq)->viq_dma.vidma_dma_handle, \
351f8296c60SJoshua M. Clulow 					    0, \
352f8296c60SJoshua M. Clulow 					    (uintptr_t)(viq)->viq_dma_device - \
353f8296c60SJoshua M. Clulow 					    (uintptr_t)(viq)->viq_dma_descs, \
354f8296c60SJoshua M. Clulow 					    DDI_DMA_SYNC_FORDEV))
355f8296c60SJoshua M. Clulow 
356f8296c60SJoshua M. Clulow /*
357f8296c60SJoshua M. Clulow  * Synchronise the device-owned portion of the queue so that we can see any
358f8296c60SJoshua M. Clulow  * writes from the device.  This covers the memory accessed via the
359f8296c60SJoshua M. Clulow  * "viq_dma_device" member.
360f8296c60SJoshua M. Clulow  */
361f8296c60SJoshua M. Clulow #define	VIRTQ_DMA_SYNC_FORKERNEL(viq)	VERIFY0(ddi_dma_sync( \
362f8296c60SJoshua M. Clulow 					    (viq)->viq_dma.vidma_dma_handle, \
363f8296c60SJoshua M. Clulow 					    (uintptr_t)(viq)->viq_dma_device - \
364f8296c60SJoshua M. Clulow 					    (uintptr_t)(viq)->viq_dma_descs, \
365f8296c60SJoshua M. Clulow 					    (viq)->viq_dma.vidma_size - \
366f8296c60SJoshua M. Clulow 					    (uintptr_t)(viq)->viq_dma_device - \
367f8296c60SJoshua M. Clulow 					    (uintptr_t)(viq)->viq_dma_descs, \
368f8296c60SJoshua M. Clulow 					    DDI_DMA_SYNC_FORKERNEL))
369f8296c60SJoshua M. Clulow 
370f8296c60SJoshua M. Clulow #ifdef __cplusplus
371f8296c60SJoshua M. Clulow }
372f8296c60SJoshua M. Clulow #endif
373f8296c60SJoshua M. Clulow 
374f8296c60SJoshua M. Clulow #endif /* _VIRTIO_IMPL_H */
375