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