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
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
#ifndef _STMF_H
#define _STMF_H
#include <sys/stmf_defines.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum stmf_struct_id {
STMF_STRUCT_LU_PROVIDER = 1,
STMF_STRUCT_PORT_PROVIDER,
STMF_STRUCT_STMF_LOCAL_PORT,
STMF_STRUCT_STMF_LU,
STMF_STRUCT_SCSI_SESSION,
STMF_STRUCT_SCSI_TASK,
STMF_STRUCT_DATA_BUF,
STMF_STRUCT_DBUF_STORE,
STMF_MAX_STRUCT_IDS
} stmf_struct_id_t;
/*
* Provider callback commands
*/
#define STMF_PROVIDER_DATA_UPDATED 0x01
/*
* Provider callback flags
*/
#define STMF_PCB_STMF_ONLINING 0x0001
#define STMF_PCB_PREG_COMPLETE 0x0002
typedef void *data_seg_handle_t;
#define STMF_MAX_LU_CACHE_NTASKS 16
#define STMF_NO_HANDLE 0xffffffff
#define COMPANY_ID_NONE 0xFFFFFFFF
#define COMPANY_ID_SUN 0x00144F
/*
* The scatter/gather list buffer format is used in 2 different
* contexts within stmf:
* 1) supplied by the port provider that the LU provider uses to exchange
* data with the backing store.
* 2) supplied by the LU provider that the port provider uses exchange
* data with the host initiator.
* The second format is optionally supported by the port provided as
* indicated by the command task flags.
*/
typedef struct stmf_sglist_ent {
uint32_t seg_length;
uint8_t *seg_addr;
} stmf_sglist_ent_t;
typedef struct stmf_data_buf {
void *db_stmf_private;
void *db_port_private;
void *db_lu_private;
uint32_t db_buf_size; /* Total size of this buffer */
uint32_t db_data_size; /* Intended xfer size of this buffer */
uint32_t db_relative_offset;
uint16_t db_sglist_length;
uint16_t db_flags; /* Direction, auto status etc */
stmf_status_t db_xfer_status;
uint8_t db_handle; /* To track parallel buffers */
hrtime_t db_xfer_start_timestamp;
stmf_sglist_ent_t db_sglist[1]; /* PP scatter/gather list */
} stmf_data_buf_t;
/*
* db_flags
*/
#define DB_DIRECTION_TO_RPORT 0x0001
#define DB_DIRECTION_FROM_RPORT 0x0002
#define DB_SEND_STATUS_GOOD 0x0004
#define DB_STATUS_GOOD_SENT 0x0008
#define DB_DONT_CACHE 0x0010
#define DB_DONT_REUSE 0x0020
#define DB_LU_DATA_BUF 0x0040
#define DB_LPORT_XFER_ACTIVE 0x8000
typedef struct scsi_task {
void *task_stmf_private;
void *task_port_private;
void *task_lu_private;
struct stmf_scsi_session *task_session;
struct stmf_local_port *task_lport;
struct stmf_lu *task_lu;
void *task_lu_itl_handle; /* Assigned by LU */
/* CMD information from initiator */
uint8_t task_lun_no[8];
uint8_t task_flags; /* See def. for task flags */
uint8_t task_priority; /* As per SAM-3 */
uint8_t task_mgmt_function; /* If this is a TM request */
uint8_t task_max_nbufs;
uint8_t task_cur_nbufs;
uint8_t task_csn_size; /* cmd seq no size in bits */
uint16_t task_additional_flags;
uint32_t task_cmd_seq_no;
uint32_t task_expected_xfer_length;
uint32_t task_timeout; /* In seconds */
uint16_t task_ext_id;
uint16_t task_cdb_length;
uint8_t *task_cdb;
/* Fields to manage data phase */
uint32_t task_cmd_xfer_length; /* xfer len based on CDB */
uint32_t task_nbytes_transferred;
uint32_t task_max_xfer_len; /* largest xfer allowed */
uint32_t task_1st_xfer_len; /* 1st xfer hint */
uint32_t task_copy_threshold; /* copy reduction threshold */
/* Status Phase */
stmf_status_t task_completion_status;
uint32_t task_resid;
uint8_t task_status_ctrl; /* See def. for status ctrl */
uint8_t task_scsi_status;
uint16_t task_sense_length;
uint8_t *task_sense_data;
/* Misc. task data */
void *task_extended_cmd;
} scsi_task_t;
/*
* Maximum expected transfer length. Can also be used when the transfer
* length is unknown when the task is allocated (e.g. SAS)
*/
#define TASK_MAX_XFER_LENGTH 0xFFFFFFFF
/*
* task_flags definitions.
*/
/*
* If TF_INITIAL_BURST is set, the dbuf passed with new_task() contains
* data from initial burst. Otherwise its just a buffer which the port
* passed to the LU.
*/
#define TF_INITIAL_BURST 0x80
/* Both READ_DATA and WRITE_DATA can be set for bidirectional xfers */
#define TF_READ_DATA 0x40
#define TF_WRITE_DATA 0x20
#define TF_ATTR_MASK 0x07
#define TF_ATTR_UNTAGGED 0x0
#define TF_ATTR_SIMPLE_QUEUE 0x1
#define TF_ATTR_ORDERED_QUEUE 0x2
#define TF_ATTR_HEAD_OF_QUEUE 0x3
#define TF_ATTR_ACA 0x4
/*
* Task Management flags.
*/
#define TM_NONE 0x00
#define TM_ABORT_TASK 0x01
#define TM_ABORT_TASK_SET 0x02
#define TM_CLEAR_ACA 0x03
#define TM_CLEAR_TASK_SET 0x04
#define TM_LUN_RESET 0x05
#define TM_TARGET_WARM_RESET 0x06
#define TM_TARGET_COLD_RESET 0x07
#define TM_TASK_REASSIGN 0x08
#define TM_TARGET_RESET 0x09
#define TM_QUERY_TASK 0x0A
/*
* additional flags
*/
#define TASK_AF_ENABLE_COMP_CONF 0x01
#define TASK_AF_PORT_LOAD_HIGH 0x02
#define TASK_AF_NO_EXPECTED_XFER_LENGTH 0x04
/*
* PP sets this flag if it can process dbufs created by the LU.
*/
#define TASK_AF_ACCEPT_LU_DBUF 0x08
/*
* Indicating a PPPT task
*/
#define TASK_AF_PPPT_TASK 0x10
/*
* scsi_task_t extension identifiers
*/
#define STMF_TASK_EXT_NONE 0
/*
* max_nbufs
*/
#define STMF_BUFS_MAX 255
/*
* Task status ctrl
*/
#define TASK_SCTRL_OVER 1
#define TASK_SCTRL_UNDER 2
/*
* The flags used by I/O flow.
*/
#define STMF_IOF_LU_DONE 0x0001
#define STMF_IOF_LPORT_DONE 0x0002
#define STMF_IOF_STATS_ONLY 0x0004
/*
* struct allocation flags
*/
#define AF_FORCE_NOSLEEP 0x0001
#define AF_DONTZERO 0x0002
typedef struct stmf_state_change_info {
uint64_t st_rflags; /* Reason behind this change */
char *st_additional_info;
} stmf_state_change_info_t;
typedef struct stmf_change_status {
stmf_status_t st_completion_status;
char *st_additional_info;
} stmf_change_status_t;
/*
* conditions causing or affecting the change.
*/
#define STMF_RFLAG_USER_REQUEST 0x0001
#define STMF_RFLAG_FATAL_ERROR 0x0002
#define STMF_RFLAG_STAY_OFFLINED 0x0004
#define STMF_RFLAG_RESET 0x0008
#define STMF_RFLAG_COLLECT_DEBUG_DUMP 0x0010
#define STMF_RFLAG_LU_ABORT 0x0020
#define STMF_RFLAG_LPORT_ABORT 0x0040
#define STMF_CHANGE_INFO_LEN 160
/*
* cmds to stmf_abort entry point
*/
#define STMF_QUEUE_TASK_ABORT 1
#define STMF_REQUEUE_TASK_ABORT_LPORT 2
#define STMF_REQUEUE_TASK_ABORT_LU 3
#define STMF_QUEUE_ABORT_LU 4
/*
* cmds to be used by stmf ctl
*/
#define STMF_CMD_LU_OP 0x0100
#define STMF_CMD_LPORT_OP 0x0200
#define STMF_CMD_MASK 0x00ff
#define STMF_CMD_ONLINE 0x0001
#define STMF_CMD_OFFLINE 0x0002
#define STMF_CMD_GET_STATUS 0x0003
#define STMF_CMD_ONLINE_COMPLETE 0x0004
#define STMF_CMD_OFFLINE_COMPLETE 0x0005
#define STMF_ACK_ONLINE_COMPLETE 0x0006
#define STMF_ACK_OFFLINE_COMPLETE 0x0007
#define STMF_CMD_LU_ONLINE (STMF_CMD_LU_OP | STMF_CMD_ONLINE)
#define STMF_CMD_LU_OFFLINE (STMF_CMD_LU_OP | STMF_CMD_OFFLINE)
#define STMF_CMD_LPORT_ONLINE (STMF_CMD_LPORT_OP | STMF_CMD_ONLINE)
#define STMF_CMD_LPORT_OFFLINE (STMF_CMD_LPORT_OP | STMF_CMD_OFFLINE)
#define STMF_CMD_GET_LU_STATUS (STMF_CMD_LU_OP | STMF_CMD_GET_STATUS)
#define STMF_CMD_GET_LPORT_STATUS \
(STMF_CMD_LPORT_OP | STMF_CMD_GET_STATUS)
#define STMF_CMD_LU_ONLINE_COMPLETE \
(STMF_CMD_LU_OP | STMF_CMD_ONLINE_COMPLETE)
#define STMF_CMD_LPORT_ONLINE_COMPLETE \
(STMF_CMD_LPORT_OP | STMF_CMD_ONLINE_COMPLETE)
#define STMF_ACK_LU_ONLINE_COMPLETE \
(STMF_CMD_LU_OP | STMF_ACK_ONLINE_COMPLETE)
#define STMF_ACK_LPORT_ONLINE_COMPLETE \
(STMF_CMD_LPORT_OP | STMF_ACK_ONLINE_COMPLETE)
#define STMF_CMD_LU_OFFLINE_COMPLETE \
(STMF_CMD_LU_OP | STMF_CMD_OFFLINE_COMPLETE)
#define STMF_CMD_LPORT_OFFLINE_COMPLETE \
(STMF_CMD_LPORT_OP | STMF_CMD_OFFLINE_COMPLETE)
#define STMF_ACK_LU_OFFLINE_COMPLETE \
(STMF_CMD_LU_OP | STMF_ACK_OFFLINE_COMPLETE)
#define STMF_ACK_LPORT_OFFLINE_COMPLETE \
(STMF_CMD_LPORT_OP | STMF_ACK_OFFLINE_COMPLETE)
/*
* For LPORTs and LUs to create their own ctl cmds which dont
* conflict with stmf ctl cmds.
*/
#define STMF_LPORT_CTL_CMDS 0x1000
#define STMF_LU_CTL_CMDS 0x2000
/*
* Commands for various info routines.
*/
/* Command classifiers */
#define SI_LPORT 0x1000000
#define SI_STMF 0x2000000
#define SI_LU 0x4000000
#define SI_LPORT_FC 0x0000000
#define SI_LPORT_ISCSI 0x0010000
#define SI_LPORT_SAS 0x0020000
#define SI_STMF_LU 0x0010000
#define SI_STMF_LPORT 0x0020000
#define SI_GET_CLASS(v) ((v) & 0xFF000000)
#define SI_GET_SUBCLASS(v) ((v) & 0x00FF0000)
/* Commands for LPORT info routines */
/* XXX - Implement these. */
#if 0
#define SI_LPORT_FC_PORTINFO (SI_LPORT | SI_LPORT_FC | 1)
#define SI_RPORT_FC_PORTINFO (SI_LPORT | SI_LPORT_FC | 2)
#endif
/*
* Events
*/
#define STMF_EVENT_ALL ((int)-1)
#define LPORT_EVENT_INITIAL_LUN_MAPPED 0
/*
* This needs to go into common/ddi/sunddi.h
*/
#define DDI_NT_STMF "ddi_scsi_target:framework"
#define DDI_NT_STMF_LP "ddi_scsi_target:lu_provider"
#define DDI_NT_STMF_PP "ddi_scsi_target:port_provider"
/*
* VPD page bits.
*/
#define STMF_VPD_LU_ID 0x01
#define STMF_VPD_TARGET_ID 0x02
#define STMF_VPD_TP_GROUP 0x04
#define STMF_VPD_RELATIVE_TP_ID 0x08
/*
* Common macros to simplify coding
*/
#define STMF_SEC2TICK(x_sec) (drv_usectohz((x_sec) * 1000000))
void stmf_trace(caddr_t ident, const char *fmt, ...);
void *stmf_alloc(stmf_struct_id_t sid, int additional_size, int alloc_flags);
void stmf_free(void *struct_ptr);
struct scsi_task *stmf_task_alloc(struct stmf_local_port *lport,
struct stmf_scsi_session *ss, uint8_t *lun, uint16_t cdb_length,
uint16_t ext_id);
void stmf_post_task(scsi_task_t *task, stmf_data_buf_t *dbuf);
stmf_data_buf_t *stmf_alloc_dbuf(scsi_task_t *task, uint32_t size,
uint32_t *pminsize, uint32_t flags);
void stmf_free_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf);
stmf_status_t stmf_setup_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf,
uint32_t flags);
void stmf_teardown_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf);
stmf_status_t stmf_xfer_data(scsi_task_t *task, stmf_data_buf_t *dbuf,
uint32_t ioflags);
stmf_status_t stmf_send_scsi_status(scsi_task_t *task, uint32_t ioflags);
void stmf_data_xfer_done(scsi_task_t *task, stmf_data_buf_t *dbuf,
uint32_t iof);
void stmf_send_status_done(scsi_task_t *task, stmf_status_t s, uint32_t iof);
void stmf_task_lu_done(scsi_task_t *task);
void stmf_abort(int abort_cmd, scsi_task_t *task, stmf_status_t s, void *arg);
void stmf_task_lu_aborted(scsi_task_t *task, stmf_status_t s, uint32_t iof);
void stmf_task_lport_aborted_unlocked(scsi_task_t *task, stmf_status_t s,
uint32_t iof);
stmf_status_t stmf_task_poll_lu(scsi_task_t *task, uint32_t timeout);
stmf_status_t stmf_task_poll_lport(scsi_task_t *task, uint32_t timeout);
stmf_status_t stmf_ctl(int cmd, void *obj, void *arg);
stmf_status_t stmf_register_itl_handle(struct stmf_lu *lu, uint8_t *lun,
struct stmf_scsi_session *ss, uint64_t session_id, void *itl_handle);
stmf_status_t stmf_deregister_all_lu_itl_handles(struct stmf_lu *lu);
stmf_status_t stmf_get_itl_handle(struct stmf_lu *lu, uint8_t *lun,
struct stmf_scsi_session *ss, uint64_t session_id, void **itl_handle_retp);
stmf_data_buf_t *stmf_handle_to_buf(scsi_task_t *task, uint8_t h);
stmf_status_t stmf_lu_add_event(struct stmf_lu *lu, int eventid);
stmf_status_t stmf_lu_remove_event(struct stmf_lu *lu, int eventid);
stmf_status_t stmf_lport_add_event(struct stmf_local_port *lport, int eventid);
stmf_status_t stmf_lport_remove_event(struct stmf_local_port *lport,
int eventid);
void stmf_wwn_to_devid_desc(struct scsi_devid_desc *sdid, uint8_t *wwn,
uint8_t protocol_id);
stmf_status_t stmf_scsilib_uniq_lu_id(uint32_t company_id,
struct scsi_devid_desc *lu_id);
stmf_status_t stmf_scsilib_uniq_lu_id2(uint32_t company_id, uint32_t host_id,
struct scsi_devid_desc *lu_id);
void stmf_scsilib_send_status(scsi_task_t *task, uint8_t st, uint32_t saa);
uint32_t stmf_scsilib_prepare_vpd_page83(scsi_task_t *task, uint8_t *page,
uint32_t page_len, uint8_t byte0, uint32_t vpd_mask);
uint16_t stmf_scsilib_get_lport_rtid(struct scsi_devid_desc *devid);
struct scsi_devid_desc *stmf_scsilib_get_devid_desc(uint16_t rtpid);
void stmf_scsilib_handle_report_tpgs(scsi_task_t *task, stmf_data_buf_t *dbuf);
void stmf_scsilib_handle_task_mgmt(scsi_task_t *task);
struct stmf_remote_port *stmf_scsilib_devid_to_remote_port(
struct scsi_devid_desc *);
boolean_t stmf_scsilib_tptid_validate(struct scsi_transport_id *,
uint32_t, uint16_t *);
boolean_t stmf_scsilib_tptid_compare(struct scsi_transport_id *,
struct scsi_transport_id *);
struct stmf_remote_port *stmf_remote_port_alloc(uint16_t);
void stmf_remote_port_free(struct stmf_remote_port *);
struct stmf_lu *stmf_check_and_hold_lu(struct scsi_task *task, uint8_t *guid);
void stmf_release_lu(struct stmf_lu *lu);
int stmf_is_task_being_aborted(struct scsi_task *task);
#ifdef __cplusplus
}
#endif
#endif /* _STMF_H */
|