xref: /illumos-gate/usr/src/uts/common/io/vioscsi/vioscsi.h (revision 7a6d80f1660abd4755c68cbd094d4a914681d26e)
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 Nexenta by DDN, Inc. All rights reserved.
14  * Copyright 2022 RackTop Systems, Inc.
15  */
16 
17 #ifndef _VIOSCSI_H_
18 #define	_VIOSCSI_H_
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 #include <sys/types.h>
25 #include <sys/atomic.h>
26 #include <sys/kmem.h>
27 #include <sys/conf.h>
28 #include <sys/devops.h>
29 #include <sys/ksynch.h>
30 #include <sys/modctl.h>
31 #include <sys/debug.h>
32 #include <sys/list.h>
33 #include <sys/stddef.h>
34 
35 #include <sys/scsi/scsi.h>
36 #include <sys/ddi.h>
37 #include <sys/sunddi.h>
38 
39 #include <virtio.h>
40 
41 #define	VIRTIO_SCSI_CDB_SIZE	32
42 #define	VIRTIO_SCSI_SENSE_SIZE	96
43 
44 /*
45  * Feature bits:
46  */
47 #define	VIRTIO_SCSI_F_INOUT		(0x1 << 0)
48 #define	VIRTIO_SCSI_F_HOTPLUG		(0x1 << 1)
49 #define	VIRTIO_SCSI_F_CHANGE		(0x1 << 2)
50 #define	VIRTIO_SCSI_F_T10_PI		(0x1 << 3)
51 
52 /*
53  * Register offset in bytes:
54  */
55 #define	VIRTIO_SCSI_CFG_NUM_QUEUES	0
56 #define	VIRTIO_SCSI_CFG_SEG_MAX		4
57 #define	VIRTIO_SCSI_CFG_MAX_SECTORS	8
58 #define	VIRTIO_SCSI_CFG_CMD_PER_LUN	12
59 #define	VIRTIO_SCSI_CFG_EVI_SIZE	16
60 #define	VIRTIO_SCSI_CFG_SENSE_SIZE	20
61 #define	VIRTIO_SCSI_CFG_CDB_SIZE	24
62 #define	VIRTIO_SCSI_CFG_MAX_CHANNEL	28
63 #define	VIRTIO_SCSI_CFG_MAX_TARGET	30
64 #define	VIRTIO_SCSI_CFG_MAX_LUN		32
65 
66 /*
67  * Response codes:
68  */
69 #define	VIRTIO_SCSI_S_OK			0
70 #define	VIRTIO_SCSI_S_FUNCTION_COMPLETED	0
71 #define	VIRTIO_SCSI_S_OVERRUN			1
72 #define	VIRTIO_SCSI_S_ABORTED			2
73 #define	VIRTIO_SCSI_S_BAD_TARGET		3
74 #define	VIRTIO_SCSI_S_RESET			4
75 #define	VIRTIO_SCSI_S_BUSY			5
76 #define	VIRTIO_SCSI_S_TRANSPORT_FAILURE		6
77 #define	VIRTIO_SCSI_S_TARGET_FAILURE		7
78 #define	VIRTIO_SCSI_S_NEXUS_FAILURE		8
79 #define	VIRTIO_SCSI_S_FAILURE			9
80 #define	VIRTIO_SCSI_S_FUNCTION_SUCCEEDED	10
81 #define	VIRTIO_SCSI_S_FUNCTION_REJECTED		11
82 #define	VIRTIO_SCSI_S_INCORRECT_LUN		12
83 
84 /*
85  * Control queue type codes:
86  */
87 #define	VIRTIO_SCSI_T_TMF			0
88 #define	VIRTIO_SCSI_T_AN_QUERY			1
89 #define	VIRTIO_SCSI_T_AN_SUBSCRIBE		2
90 
91 /*
92  * Task management codes:
93  */
94 #define	VIRTIO_SCSI_T_TMF_ABORT_TASK		0
95 #define	VIRTIO_SCSI_T_TMF_ABORT_TASK_SET	1
96 #define	VIRTIO_SCSI_T_TMF_CLEAR_ACA		2
97 #define	VIRTIO_SCSI_T_TMF_CLEAR_ACA_TASK_SET	3
98 #define	VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET	4
99 #define	VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET	5
100 #define	VIRTIO_SCSI_T_TMF_QUERY_TASK		6
101 #define	VIRTIO_SCSI_T_TMF_QUERY_TASK_SET	7
102 
103 /*
104  * Events:
105  */
106 #define	VIRTIO_SCSI_T_EVENTS_MISSED		0x80000000
107 #define	VIRTIO_SCSI_T_NO_EVENT			0
108 #define	VIRTIO_SCSI_T_TRANSPORT_RESET		1
109 #define	VIRTIO_SCSI_T_ASYNC_NOTIFY		2
110 
111 /*
112  * Task attributes:
113  */
114 #define	VIRTIO_SCSI_S_SIMPLE			0
115 #define	VIRTIO_SCSI_S_ORDERED			1
116 #define	VIRTIO_SCSI_S_HEAD			2
117 #define	VIRTIO_SCSI_S_ACA			3
118 
119 /*
120  * Reasons of reset event:
121  */
122 #define	VIRTIO_SCSI_EVT_RESET_HARD		0
123 #define	VIRTIO_SCSI_EVT_RESET_RESCAN		1
124 #define	VIRTIO_SCSI_EVT_RESET_REMOVED		2
125 
126 /*
127  * We need to support INOUT, and we want hotplug notifications:
128  */
129 #define	VIOSCSI_WANTED_FEATURES	(VIRTIO_SCSI_F_INOUT | VIRTIO_SCSI_F_HOTPLUG)
130 
131 #define	VIOSCSI_MAX_TARGET			256
132 #define	VIOSCSI_MIN_SEGS			3
133 #define	VIOSCSI_NUM_EVENTS			16
134 
135 /*
136  * Data structures:
137  */
138 
139 #pragma pack(1)
140 
141 /*
142  * virtio SCSI command request:
143  */
144 struct virtio_scsi_cmd_req {
145 	uint8_t		lun[8];
146 	uint64_t	tag;
147 	uint8_t		task_attr;
148 	uint8_t		prio;
149 	uint8_t		crn;
150 	uint8_t		cdb[VIRTIO_SCSI_CDB_SIZE];
151 };
152 
153 /*
154  * Virtio SCSI response:
155  */
156 struct virtio_scsi_cmd_resp {
157 	uint32_t	sense_len;
158 	uint32_t	res_id;
159 	uint16_t	status_qualifier;
160 	uint8_t		status;
161 	uint8_t		response;
162 	uint8_t		sense[VIRTIO_SCSI_SENSE_SIZE];
163 };
164 
165 /*
166  * Task management request:
167  */
168 struct virtio_scsi_ctrl_tmf_req {
169 	uint32_t	type;
170 	uint32_t	subtype;
171 	uint8_t		lun[8];
172 	uint64_t	tag;
173 };
174 
175 /*
176  * Task management response:
177  */
178 struct virtio_scsi_ctrl_tmf_resp {
179 	uint8_t		response;
180 };
181 
182 /*
183  * Asynchronous notification request:
184  */
185 struct virtio_scsi_ctrl_an_req {
186 	uint32_t	type;
187 	uint8_t		lun[8];
188 	uint32_t	event_requested;
189 };
190 
191 /*
192  * Asynchronous notification response:
193  */
194 struct virtio_scsi_ctrl_an_resp {
195 	uint32_t	event_actual;
196 	uint8_t		response;
197 };
198 
199 /*
200  * Events delivered on the event queue:
201  */
202 struct virtio_scsi_event {
203 	uint32_t	event;
204 	uint8_t		lun[8];
205 	uint32_t	reason;
206 };
207 
208 #pragma pack()
209 
210 typedef union {
211 	struct virtio_scsi_cmd_req		cmd;
212 	struct virtio_scsi_ctrl_tmf_req		tmf;
213 	struct virtio_scsi_ctrl_an_req		anr;
214 } vioscsi_req_t;
215 
216 typedef union {
217 	struct virtio_scsi_cmd_resp		cmd;
218 	struct virtio_scsi_ctrl_tmf_resp	tmf;
219 	struct virtio_scsi_ctrl_an_resp		anr;
220 } vioscsi_res_t;
221 
222 struct virtio_scsi_op {
223 	vioscsi_req_t	req;
224 	vioscsi_res_t	res;
225 };
226 
227 #define	VIOSCSI_REQ_OFFSET	offsetof(struct virtio_scsi_op, req)
228 #define	VIOSCSI_RES_OFFSET	offsetof(struct virtio_scsi_op, res)
229 
230 typedef struct vioscsi_request vioscsi_request_t;
231 typedef	struct vioscsi_event vioscsi_event_t;
232 typedef struct vioscsi_softc vioscsi_softc_t;
233 typedef struct vioscsi_dev vioscsi_dev_t;
234 typedef struct virtio_scsi_event vioscsi_evt_t;
235 typedef struct virtio_scsi_ctrl_tmf_req vioscsi_tmf_req_t;
236 typedef struct virtio_scsi_ctrl_tmf_resp vioscsi_tmf_res_t;
237 typedef struct virtio_scsi_cmd_req vioscsi_cmd_req_t;
238 typedef struct virtio_scsi_cmd_resp vioscsi_cmd_res_t;
239 typedef struct virtio_scsi_op vioscsi_op_t;
240 
241 struct vioscsi_request {
242 	list_node_t		vr_node;
243 	struct scsi_pkt		*vr_pkt;
244 	virtio_queue_t		*vr_vq;
245 	virtio_dma_t		*vr_dma;
246 	virtio_chain_t		*vr_vic;
247 	vioscsi_dev_t		*vr_dev;
248 	vioscsi_req_t		*vr_req;
249 	vioscsi_res_t		*vr_res;
250 	uint64_t		vr_req_pa;
251 	uint64_t		vr_res_pa;
252 	boolean_t		vr_poll;
253 	uint8_t			vr_expired;	/* access using atomics */
254 	uint8_t			vr_done;	/* access using atomics */
255 	uint8_t			vr_task_attr;
256 	uint8_t			vr_target;
257 	uint16_t		vr_lun;
258 	clock_t			vr_time;	/* seconds */
259 	clock_t			vr_start;	/* ticks */
260 	clock_t			vr_expire;	/* ticks */
261 };
262 
263 struct vioscsi_dev {
264 	list_node_t		vd_node;
265 	uint8_t			vd_target;
266 	uint16_t		vd_lun;
267 	struct scsi_device	*vd_sd;
268 	vioscsi_softc_t		*vd_sc;
269 	int			vd_num_cmd;
270 	int			vd_max_cmd;
271 	boolean_t		vd_rescan;
272 	list_t			vd_reqs;
273 	timeout_id_t		vd_timeout;
274 	kmutex_t		vd_lock;
275 };
276 
277 struct vioscsi_event {
278 	virtio_chain_t		*ve_vic;
279 	virtio_dma_t		*ve_dma;
280 	vioscsi_evt_t		*ve_evt;
281 };
282 
283 struct vioscsi_softc {
284 	dev_info_t		*vs_dip;
285 	virtio_t		*vs_virtio;
286 	uint64_t		vs_features;
287 
288 	virtio_queue_t		*vs_ctl_vq;
289 	virtio_queue_t		*vs_evt_vq;
290 	virtio_queue_t		*vs_cmd_vq;
291 
292 	scsi_hba_tran_t		*vs_tran;
293 	scsi_hba_tgtmap_t	*vs_tgtmap;
294 	ddi_taskq_t		*vs_tq;
295 
296 	uint32_t		vs_max_target;
297 	uint32_t		vs_max_lun;
298 	uint32_t		vs_cdb_size;
299 	uint32_t		vs_max_seg;
300 	uint32_t		vs_cmd_per_lun;
301 
302 	vioscsi_event_t		vs_events[VIOSCSI_NUM_EVENTS];
303 
304 	void			*vs_intr_pri;
305 	kmutex_t		vs_lock;
306 	list_t			vs_devs;
307 };
308 
309 #ifdef __cplusplus
310 }
311 #endif
312 
313 #endif /* _VIOSCSI_H_ */
314