xref: /illumos-gate/usr/src/uts/common/io/vioblk/vioblk.h (revision 069e6b7e31ba5dcbc5441b98af272714d9a5455c)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2019 Joyent, Inc.
14  */
15 
16 /*
17  * VIRTIO BLOCK DRIVER
18  */
19 
20 #ifndef _VIOBLK_H
21 #define	_VIOBLK_H
22 
23 #include "virtio.h"
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 /*
30  * VIRTIO BLOCK CONFIGURATION REGISTERS
31  *
32  * These are offsets into the device-specific configuration space available
33  * through the virtio_dev_*() family of functions.
34  */
35 #define	VIRTIO_BLK_CONFIG_CAPACITY	0x00	/* 64 R   */
36 #define	VIRTIO_BLK_CONFIG_SIZE_MAX	0x08	/* 32 R   */
37 #define	VIRTIO_BLK_CONFIG_SEG_MAX	0x0C	/* 32 R   */
38 #define	VIRTIO_BLK_CONFIG_GEOMETRY_C	0x10	/* 16 R   */
39 #define	VIRTIO_BLK_CONFIG_GEOMETRY_H	0x12	/*  8 R   */
40 #define	VIRTIO_BLK_CONFIG_GEOMETRY_S	0x13	/*  8 R   */
41 #define	VIRTIO_BLK_CONFIG_BLK_SIZE	0x14	/* 32 R   */
42 #define	VIRTIO_BLK_CONFIG_TOPO_PBEXP	0x18	/*  8 R   */
43 #define	VIRTIO_BLK_CONFIG_TOPO_ALIGN	0x19	/*  8 R   */
44 #define	VIRTIO_BLK_CONFIG_TOPO_MIN_SZ	0x1A	/* 16 R   */
45 #define	VIRTIO_BLK_CONFIG_TOPO_OPT_SZ	0x1C	/* 32 R   */
46 
47 /*
48  * VIRTIO BLOCK VIRTQUEUES
49  *
50  * Virtio block devices have just one queue which is used to make the various
51  * supported I/O requests.
52  */
53 #define	VIRTIO_BLK_VIRTQ_IO		0
54 
55 /*
56  * VIRTIO BLOCK FEATURE BITS
57  */
58 #define	VIRTIO_BLK_F_BARRIER		(1ULL << 0)
59 #define	VIRTIO_BLK_F_SIZE_MAX		(1ULL << 1)
60 #define	VIRTIO_BLK_F_SEG_MAX		(1ULL << 2)
61 #define	VIRTIO_BLK_F_GEOMETRY		(1ULL << 4)
62 #define	VIRTIO_BLK_F_RO			(1ULL << 5)
63 #define	VIRTIO_BLK_F_BLK_SIZE		(1ULL << 6)
64 #define	VIRTIO_BLK_F_SCSI		(1ULL << 7)
65 #define	VIRTIO_BLK_F_FLUSH		(1ULL << 9)
66 #define	VIRTIO_BLK_F_TOPOLOGY		(1ULL << 10)
67 
68 /*
69  * These features are supported by the driver and we will request them from the
70  * device.
71  */
72 #define	VIRTIO_BLK_WANTED_FEATURES	(VIRTIO_BLK_F_RO |		\
73 					VIRTIO_BLK_F_BLK_SIZE |		\
74 					VIRTIO_BLK_F_FLUSH |		\
75 					VIRTIO_BLK_F_TOPOLOGY |		\
76 					VIRTIO_BLK_F_SEG_MAX |		\
77 					VIRTIO_BLK_F_SIZE_MAX)
78 
79 /*
80  * VIRTIO BLOCK REQUEST HEADER
81  *
82  * This structure appears at the start of each I/O request buffer.  Note that
83  * neither the data payload nor the status byte appear in this structure as
84  * both are handled in separate descriptor entries.
85  */
86 struct vioblk_req_hdr {
87 	uint32_t			vbh_type;
88 	uint32_t			vbh_ioprio;
89 	uint64_t			vbh_sector;
90 } __packed;
91 
92 /*
93  * VIRTIO BLOCK REQUEST HEADER: COMMANDS (vbh_type)
94  *
95  * Each of these is a command type, except for BARRIER which is logically
96  * OR-ed with one of the other types.
97  */
98 #define	VIRTIO_BLK_T_IN			0
99 #define	VIRTIO_BLK_T_OUT		1
100 #define	VIRTIO_BLK_T_SCSI_CMD		2
101 #define	VIRTIO_BLK_T_SCSI_CMD_OUT	3
102 #define	VIRTIO_BLK_T_FLUSH		4
103 #define	VIRTIO_BLK_T_FLUSH_OUT		5
104 #define	VIRTIO_BLK_T_GET_ID		8
105 #define	VIRTIO_BLK_T_BARRIER		0x80000000
106 
107 /*
108  * The GET_ID command type does not appear in the specification, but
109  * implementations in the wild use a 20 byte buffer into which the device will
110  * write an ASCII string.  The string should not be assumed to be
111  * NUL-terminated.
112  */
113 #define	VIRTIO_BLK_ID_BYTES		20
114 
115 /*
116  * VIRTIO BLOCK REQUEST HEADER: STATUS CODES
117  *
118  * These are returned in the writeable status byte descriptor included at the
119  * end of each request passed to the device.
120  */
121 #define	VIRTIO_BLK_S_OK			0
122 #define	VIRTIO_BLK_S_IOERR		1
123 #define	VIRTIO_BLK_S_UNSUPP		2
124 
125 /*
126  * DRIVER PARAMETERS
127  */
128 
129 /*
130  * In the event that the device does not negotiate DMA parameters, we have to
131  * make a best guess.
132  */
133 #define	VIRTIO_BLK_DEFAULT_MAX_SEG	128
134 #define	VIRTIO_BLK_DEFAULT_MAX_SIZE	4096
135 
136 /*
137  * We allocate a fixed number of request buffers in advance and place them in a
138  * per-instance free list.
139  */
140 #define	VIRTIO_BLK_REQ_BUFS		256
141 
142 /*
143  * TYPE DEFINITIONS
144  */
145 
146 typedef enum vioblk_req_status {
147 	VIOBLK_REQSTAT_ALLOCATED =	(0x1 << 0),
148 	VIOBLK_REQSTAT_INFLIGHT =	(0x1 << 1),
149 	VIOBLK_REQSTAT_COMPLETE =	(0x1 << 2),
150 	VIOBLK_REQSTAT_POLLED =		(0x1 << 3),
151 	VIOBLK_REQSTAT_POLL_COMPLETE =	(0x1 << 4),
152 } vioblk_req_status_t;
153 
154 typedef struct vioblk_req {
155 	vioblk_req_status_t		vbr_status;
156 	uint64_t			vbr_seqno;
157 	int				vbr_type;
158 	int				vbr_error;
159 	virtio_dma_t			*vbr_dma;
160 	bd_xfer_t			*vbr_xfer;
161 	list_node_t			vbr_link;
162 } vioblk_req_t;
163 
164 typedef struct vioblk_stats {
165 	struct kstat_named		vbs_rw_outofmemory;
166 	struct kstat_named		vbs_rw_badoffset;
167 	struct kstat_named		vbs_rw_queuemax;
168 	struct kstat_named		vbs_rw_cookiesmax;
169 	struct kstat_named		vbs_rw_cacheflush;
170 	struct kstat_named		vbs_intr_queuemax;
171 	struct kstat_named		vbs_intr_total;
172 	struct kstat_named		vbs_io_errors;
173 	struct kstat_named		vbs_unsupp_errors;
174 	struct kstat_named		vbs_nxio_errors;
175 } vioblk_stats_t;
176 
177 typedef struct vioblk {
178 	dev_info_t			*vib_dip;
179 	virtio_t			*vib_virtio;
180 	virtio_queue_t			*vib_vq;
181 
182 	kmutex_t			vib_mutex;
183 	kcondvar_t			vib_cv;
184 
185 	bd_handle_t			vib_bd_h;
186 	ddi_dma_attr_t			vib_bd_dma_attr;
187 
188 	list_t				vib_reqs;
189 	uint_t				vib_nreqs_alloc;
190 	uint_t				vib_reqs_capacity;
191 	vioblk_req_t			*vib_reqs_mem;
192 
193 	kstat_t				*vib_kstat;
194 	vioblk_stats_t			*vib_stats;
195 
196 	uint64_t			vib_nblks;
197 	boolean_t			vib_readonly;
198 	uint_t				vib_blk_size;
199 	uint_t				vib_pblk_size;
200 	uint_t				vib_seg_max;
201 	uint_t				vib_seg_size_max;
202 
203 	boolean_t			vib_devid_fetched;
204 	char				vib_devid[VIRTIO_BLK_ID_BYTES + 1];
205 	uint8_t				vib_rawid[VIRTIO_BLK_ID_BYTES];
206 } vioblk_t;
207 
208 #ifdef __cplusplus
209 }
210 #endif
211 
212 #endif /* _VIOBLK_H */
213