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
|
/*
* 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 2020 RackTop Systems, Inc.
*/
#ifndef _FCT_H
#define _FCT_H
/*
* Definitions for common FC Target.
*/
#include <sys/note.h>
#include <sys/stmf_defines.h>
#include <sys/fct_defines.h>
#include <sys/portif.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum fct_struct_id {
FCT_STRUCT_LOCAL_PORT = 1,
FCT_STRUCT_REMOTE_PORT,
FCT_STRUCT_CMD_RCVD_ELS,
FCT_STRUCT_CMD_SOL_ELS,
FCT_STRUCT_CMD_SOL_CT,
FCT_STRUCT_CMD_RCVD_ABTS,
FCT_STRUCT_CMD_FCP_XCHG,
FCT_STRUCT_DBUF_STORE,
FCT_MAX_STRUCT_IDS
} fct_struct_id_t;
typedef struct fct_remote_port {
void *rp_fct_private;
void *rp_fca_private;
struct fct_local_port *rp_port;
char rp_nwwn_str[FC_WWN_BUFLEN];
char rp_pwwn_str[FC_WWN_BUFLEN];
uint8_t rp_nwwn[FC_WWN_LEN];
uint8_t rp_pwwn[FC_WWN_LEN];
uint32_t rp_id; /* 8 or 24 bit */
uint32_t rp_hard_address;
uint16_t rp_handle;
} fct_remote_port_t;
#define FCT_HANDLE_NONE 0xffff
typedef struct fct_cmd {
void *cmd_fct_private;
void *cmd_fca_private;
void *cmd_specific;
struct fct_local_port *cmd_port;
/* During cmd porting this can be set to NULL */
struct fct_remote_port *cmd_rp;
/* To link cmds together for handling things like ABTS. */
struct fct_cmd *cmd_link;
uint8_t cmd_type;
uint8_t cmd_rsvd1;
/* During cmd posting this can be set to FCT_HANDLE_NONE */
uint16_t cmd_rp_handle;
uint32_t cmd_handle;
uint32_t cmd_rportid;
uint32_t cmd_lportid;
uint32_t cmd_rsvd2;
uint16_t cmd_oxid;
uint16_t cmd_rxid;
fct_status_t cmd_comp_status;
} fct_cmd_t;
/*
* fcmd_cmd_handle: Bit definitions.
* 31 23 15 7 0
* +--------------+------------+------------+------------+
* | V |uniq_cntr |fca specific| cmd slot index |
* +--------------+------------+------------+------------+
* V = handle valid.
*/
#define CMD_HANDLE_SLOT_INDEX(x) ((x) & 0xffff)
#define CMD_HANDLE_VALID(x) ((x) & 0x80000000)
enum fct_cmd_types {
FCT_CMD_FCP_XCHG = 0x0001,
FCT_CMD_RCVD_ELS = 0x0002,
FCT_CMD_SOL_ELS = 0x0004,
FCT_CMD_RCVD_ABTS = 0x0008,
FCT_CMD_SOL_CT = 0x0010,
FCT_CMD_TYPE_ALL = 0xffff
};
typedef struct fct_els {
uint16_t els_req_size;
uint16_t els_resp_size;
uint16_t els_req_alloc_size;
uint16_t els_resp_alloc_size;
uint8_t *els_req_payload;
uint8_t *els_resp_payload;
} fct_els_t;
typedef struct fct_sol_ct {
uint16_t ct_req_size;
uint16_t ct_resp_size;
uint16_t ct_req_alloc_size;
uint16_t ct_resp_alloc_size;
uint8_t *ct_req_payload;
uint8_t *ct_resp_payload;
} fct_sol_ct_t;
typedef struct fct_rcvd_abts {
uint8_t abts_resp_rctl; /* Can be BA_ACC or BA_RJT */
uint8_t abts_state;
uint16_t rsvd;
uint8_t abts_resp_payload[12];
} fct_rcvd_abts_t;
/*
* abts state
*/
#define ABTS_STATE_RECEIVED 0
#define ABTS_STATE_RESPONDED 1
#define ABTS_STATE_COMPLETED 2
#define ABTS_STATE_ABORT_REQUESTED 3
#define ABTS_STATE_ABORT_COMPLETED 4
#define FCHBA_MANUFACTURER_LEN 64
#define FCHBA_SERIAL_NUMBER_LEN 64
#define FCHBA_MODEL_LEN 256
#define FCHBA_MODEL_DESCRIPTION_LEN 256
#define FCHBA_HARDWARE_VERSION_LEN 256
#define FCHBA_DRIVER_VERSION_LEN 256
#define FCHBA_OPTION_ROM_VERSION_LEN 256
#define FCHBA_FIRMWARE_VERSION_LEN 256
#define FCHBA_DRIVER_NAME_LEN 256
#define FCHBA_SYMB_NAME_LEN 255
#define FCT_INFO_LEN 160
#define FCT_TASKQ_NAME_LEN 24
#define FC_TGT_PORT_INFO_CMD (((uint32_t)'I') << 24)
#define FC_TGT_PORT_RLS FC_TGT_PORT_INFO_CMD + 0x1
typedef struct fct_port_attrs {
char manufacturer[FCHBA_MANUFACTURER_LEN];
char serial_number[FCHBA_SERIAL_NUMBER_LEN];
char model[FCHBA_MODEL_LEN];
char model_description[FCHBA_MODEL_DESCRIPTION_LEN];
char hardware_version[FCHBA_HARDWARE_VERSION_LEN];
char driver_version[FCHBA_DRIVER_VERSION_LEN];
char option_rom_version[FCHBA_OPTION_ROM_VERSION_LEN];
char firmware_version[FCHBA_FIRMWARE_VERSION_LEN];
char driver_name[FCHBA_DRIVER_NAME_LEN];
uint32_t vendor_specific_id;
uint32_t supported_cos;
uint32_t supported_speed;
uint32_t max_frame_size;
} fct_port_attrs_t;
typedef struct fct_port_link_status {
uint32_t LinkFailureCount;
uint32_t LossOfSyncCount;
uint32_t LossOfSignalsCount;
uint32_t PrimitiveSeqProtocolErrorCount;
uint32_t InvalidTransmissionWordCount;
uint32_t InvalidCRCCount;
} fct_port_link_status_t;
typedef struct fct_dbuf_store {
void *fds_fct_private;
void *fds_fca_private;
struct stmf_dbuf_store *fds_ds;
stmf_data_buf_t *(*fds_alloc_data_buf)(struct fct_local_port *port,
uint32_t size, uint32_t *pminsize, uint32_t flags);
void (*fds_free_data_buf)(struct fct_dbuf_store *fds,
stmf_data_buf_t *dbuf);
stmf_status_t (*fds_setup_dbuf)(struct fct_local_port *port,
stmf_data_buf_t *dbuf, uint32_t flags);
void (*fds_teardown_dbuf)(struct fct_dbuf_store *fds,
stmf_data_buf_t *dbuf);
uint32_t fds_max_sgl_xfer_len;
uint32_t fds_copy_threshold;
} fct_dbuf_store_t;
#define FCT_FCA_MODREV_1 1
typedef struct fct_local_port {
void *port_fct_private;
void *port_fca_private;
stmf_local_port_t *port_lport;
char port_nwwn_str[FC_WWN_BUFLEN];
char port_pwwn_str[FC_WWN_BUFLEN];
uint8_t port_nwwn[FC_WWN_LEN];
uint8_t port_pwwn[FC_WWN_LEN];
char *port_default_alias;
char *port_sym_node_name;
char *port_sym_port_name;
stmf_port_provider_t *port_pp;
uint32_t port_hard_address;
uint16_t port_max_logins;
uint16_t port_max_xchges;
uint32_t port_fca_fcp_cmd_size;
uint32_t port_fca_rp_private_size;
uint32_t port_fca_sol_els_private_size;
uint32_t port_fca_sol_ct_private_size;
/* in milliseconds */
uint32_t port_fca_abort_timeout;
fct_dbuf_store_t *port_fds;
fct_status_t (*port_get_link_info)(
struct fct_local_port *port, struct fct_link_info *li);
fct_status_t (*port_register_remote_port)(
struct fct_local_port *port, struct fct_remote_port *rp,
struct fct_cmd *login_els);
fct_status_t (*port_deregister_remote_port)(
struct fct_local_port *port, struct fct_remote_port *rp);
fct_status_t (*port_send_cmd)(fct_cmd_t *cmd);
fct_status_t (*port_xfer_scsi_data)(fct_cmd_t *cmd,
stmf_data_buf_t *dbuf, uint32_t flags);
fct_status_t (*port_send_cmd_response)(fct_cmd_t *cmd,
uint32_t ioflags);
fct_status_t (*port_abort_cmd)(struct fct_local_port *port,
fct_cmd_t *cmd, uint32_t flags);
void (*port_ctl)(struct fct_local_port *port,
int cmd, void *arg);
fct_status_t (*port_flogi_xchg)(struct fct_local_port *port,
struct fct_flogi_xchg *fx);
void (*port_populate_hba_details)(
struct fct_local_port *port, struct fct_port_attrs *port_attrs);
fct_status_t (*port_info)(uint32_t cmd,
struct fct_local_port *port, void *arg, uint8_t *buf,
uint32_t *bufsizep);
int port_fca_version;
} fct_local_port_t;
/*
* Common struct used during FLOGI exchange.
*/
typedef struct fct_flogi_xchg {
uint8_t fx_op; /* ELS_OP_FLOGI or ELS_OP_ACC/RJT */
uint8_t fx_rjt_reason;
uint8_t fx_rjt_expl;
uint8_t fx_sec_timeout; /* Timeout in seconds */
uint32_t fx_fport:1, /* 0=N_port, 1=F_port */
rsvd2:31;
uint32_t fx_sid; /* 24 bit SID to use */
uint32_t fx_did; /* 24 bit DID to use */
uint8_t fx_pwwn[8];
uint8_t fx_nwwn[8];
} fct_flogi_xchg_t;
typedef struct fct_link_info {
uint32_t portid;
uint8_t port_topology;
uint8_t port_speed;
uint8_t rsvd:5,
/*
* FCA sets this bit to indicate that fct does not need to do FLOGI
* because either FCA did the FLOGI or it determined that its a private
* loop. Setting this bit by FCA is optional.
*/
port_no_fct_flogi:1,
/* FCA sets this bit to indicate that it did FLOGI */
port_fca_flogi_done:1,
/* FCT sets this bit to indicate that it did FLOGI */
port_fct_flogi_done:1;
uint8_t rsvd1;
/* The fields below are only valid if someone did a successful flogi */
uint8_t port_rnwwn[8];
uint8_t port_rpwwn[8];
} fct_link_info_t;
typedef struct fct_port_stat {
kstat_named_t link_failure_cnt;
kstat_named_t loss_of_sync_cnt;
kstat_named_t loss_of_signals_cnt;
kstat_named_t prim_seq_protocol_err_cnt;
kstat_named_t invalid_tx_word_cnt;
kstat_named_t invalid_crc_cnt;
} fct_port_stat_t;
/*
* port topology
*/
#define PORT_TOPOLOGY_UNKNOWN 0
#define PORT_TOPOLOGY_PT_TO_PT 1
#define PORT_TOPOLOGY_PRIVATE_LOOP 2
#define PORT_TOPOLOGY_PUBLIC_LOOP 6
#define PORT_TOPOLOGY_FABRIC_PT_TO_PT 5
#define PORT_TOPOLOGY_FABRIC_BIT 4
#define PORT_FLOGI_DONE(li) (((li)->port_fca_flogi_done) || \
((li)->port_fct_flogi_done))
/*
* port speed
*/
#define PORT_SPEED_UNKNOWN 0
#define PORT_SPEED_1G 1
#define PORT_SPEED_2G 2
#define PORT_SPEED_4G 4
#define PORT_SPEED_8G 8
#define PORT_SPEED_10G 16
#define PORT_SPEED_16G 32
#define PORT_SPEED_32G 64
/*
* Abort commands
*/
#define FCT_TERMINATE_CMD 1
/*
* FCT port states.
*/
#define FCT_STATE_OFFLINE 0
#define FCT_STATE_ONLINING 1
#define FCT_STATE_ONLINE 2
#define FCT_STATE_OFFLINING 3
/*
* fct ctl commands. These should not conflict with stmf ctl commands
*/
#define FCT_CMD_PORT_ONLINE (STMF_LPORT_CTL_CMDS | 0x01)
#define FCT_CMD_PORT_ONLINE_COMPLETE (STMF_LPORT_CTL_CMDS | 0x02)
#define FCT_CMD_PORT_OFFLINE (STMF_LPORT_CTL_CMDS | 0x03)
#define FCT_CMD_PORT_OFFLINE_COMPLETE (STMF_LPORT_CTL_CMDS | 0x04)
#define FCT_ACK_PORT_ONLINE_COMPLETE (STMF_LPORT_CTL_CMDS | 0x05)
#define FCT_ACK_PORT_OFFLINE_COMPLETE (STMF_LPORT_CTL_CMDS | 0x06)
#define FCT_CMD_FORCE_LIP (STMF_LPORT_CTL_CMDS | 0x07)
/*
* IO flags for cmd flow.
*/
#define FCT_IOF_FCA_DONE 0x10000
#define FCT_IOF_FORCE_FCA_DONE 0x20000
/*
* Fill CTIU preamble
*/
#ifdef lint
#define FCT_FILL_CTIU_PREAMBLE(x_payload, x_ctop) _NOTE(EMPTY)
#else
#define FCT_FILL_CTIU_PREAMBLE(x_payload, x_ctop) \
do { \
x_payload[0] = 0x01; \
x_payload[4] = 0xFC; \
x_payload[5] = 0x02; \
x_payload[8] = 0xFF & (x_ctop >> 8); \
x_payload[9] = 0xFF & (x_ctop); \
} while (0)
#endif
uint64_t fct_netbuf_to_value(uint8_t *buf, uint8_t nbytes);
void fct_value_to_netbuf(uint64_t value, uint8_t *buf, uint8_t nbytes);
void *fct_alloc(fct_struct_id_t struct_id, int additional_size, int flags);
void fct_free(void *ptr);
fct_cmd_t *fct_scsi_task_alloc(struct fct_local_port *port,
uint16_t rp_handle, uint32_t rportid, uint8_t *lun,
uint16_t cdb_length, uint16_t task_ext);
fct_status_t fct_register_local_port(fct_local_port_t *port);
fct_status_t fct_deregister_local_port(fct_local_port_t *port);
void fct_handle_event(fct_local_port_t *port, int event_id,
uint32_t event_flags, caddr_t arg);
void fct_post_rcvd_cmd(fct_cmd_t *cmd, stmf_data_buf_t *dbuf);
void fct_queue_cmd_for_termination(fct_cmd_t *cmd, fct_status_t s);
void fct_queue_scsi_task_for_termination(fct_cmd_t *cmd, fct_status_t s);
fct_cmd_t *fct_handle_to_cmd(fct_local_port_t *port, uint32_t fct_handle);
void fct_ctl(struct stmf_local_port *lport, int cmd, void *arg);
void fct_cmd_fca_aborted(fct_cmd_t *cmd, fct_status_t s, uint32_t ioflags);
uint16_t fct_get_rp_handle(fct_local_port_t *port, uint32_t rportid);
void fct_send_response_done(fct_cmd_t *cmd, fct_status_t s, uint32_t ioflags);
void fct_send_cmd_done(fct_cmd_t *cmd, fct_status_t s, uint32_t ioflags);
void fct_scsi_data_xfer_done(fct_cmd_t *cmd, stmf_data_buf_t *dbuf,
uint32_t ioflags);
fct_status_t fct_port_initialize(fct_local_port_t *port, uint32_t rflags,
char *additional_info);
fct_status_t fct_port_shutdown(fct_local_port_t *port, uint32_t rflags,
char *additional_info);
fct_status_t fct_handle_rcvd_flogi(fct_local_port_t *port,
fct_flogi_xchg_t *fx);
void fct_log_local_port_event(fct_local_port_t *port, char *subclass);
void fct_log_remote_port_event(fct_local_port_t *port, char *subclass,
uint8_t *rp_pwwn, uint32_t rp_id);
void fct_wwn_to_str(char *to_ptr, const uint8_t *from_ptr);
#ifdef __cplusplus
}
#endif
#endif /* _FCT_H */
|