1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 #ifndef	_FCOE_COMMON_H_
26 #define	_FCOE_COMMON_H_
27 
28 #ifdef	__cplusplus
29 extern "C" {
30 #endif
31 
32 #ifdef	_KERNEL
33 
34 /*
35  * Interface return value
36  */
37 #define	FCOE_SUCCESS		 0
38 #define	FCOE_FAILURE		-1
39 #define	FCOE_BUSY		-2
40 #define	FCOE_NOT_SUPPORTED	-3
41 #define	FCOE_BAD_FRAME		-4
42 
43 /*
44  * FCOE port speed
45  */
46 #define	FCOE_PORT_SPEED_1G	1000000000
47 #define	FCOE_PORT_SPEED_10G	10000000000
48 
49 /*
50  * FC Frame header size: 24 bytes
51  */
52 #define	FCFH_SIZE		(sizeof (fcoe_fc_frame_header_t))
53 
54 /*
55  * FLOGI
56  */
57 #define	FLOGI_REQ_PAYLOAD_SIZE	116
58 #define	FLOGI_ACC_PAYLOAD_SIZE	116
59 
60 #define	FCOE_MIN_MTU_SIZE	2500
61 #define	FCOE_MAX_FC_FRAME_SIZE	2136
62 
63 /*
64  * 24 byte FC frame header
65  * For all data structures that have endian problems, we will use only
66  * one type: uint8_t. We need associate the data structure pointer with
67  * one buffer directly.
68  */
69 typedef struct fcoe_fc_frame_header {
70 	uint8_t hdr_r_ctl[1];
71 	uint8_t hdr_d_id[3];
72 
73 	uint8_t hdr_cs_ctl[1];
74 	uint8_t hdr_s_id[3];
75 
76 	uint8_t hdr_type[1];
77 	uint8_t hdr_f_ctl[3];
78 
79 	uint8_t hdr_seq_id[1];
80 	uint8_t hdr_df_ctl[1];
81 	uint8_t hdr_seq_cnt[2];
82 
83 	uint8_t hdr_oxid[2];
84 	uint8_t hdr_rxid[2];
85 
86 	uint8_t hdr_param[4];
87 } fcoe_fc_frame_header_t;
88 
89 /*
90  * Solicited frame:   allocted by FCOET/FOCEI,  free-ed by FCOE
91  * Unsolicited frame: allocated by FCOE,        free-ed by FCOET/FCOEI
92  */
93 struct fcoe_port;
94 typedef struct fcoe_frame {
95 	uint32_t		 frm_flags;
96 	void			*frm_netb;
97 
98 	/*
99 	 * frm_hdr will be cleared by fcoe explicitly
100 	 */
101 	fcoe_fc_frame_header_t	*frm_hdr;
102 	uint8_t			*frm_ofh1;
103 	uint8_t			*frm_ofh2;
104 	uint8_t			*frm_fc_frame;
105 
106 	/*
107 	 * fcoe client need clear FC payload explicitly,
108 	 * except for RD/WR data frames
109 	 */
110 	uint8_t			*frm_payload;
111 	uint32_t		 frm_fc_frame_size;
112 	uint32_t		 frm_payload_size;
113 	uint32_t		 frm_alloc_size;
114 	struct fcoe_port	*frm_eport;
115 	void			*frm_fcoe_private;
116 	void			*frm_client_private;
117 	clock_t			 frm_clock;
118 } fcoe_frame_t;
119 
120 /*
121  * FCOE HBA
122  */
123 typedef struct fcoe_port {
124 	uint32_t	   eport_flags;
125 	void		  *eport_fcoe_private;
126 	void		  *eport_client_private;
127 	uint8_t		   eport_portwwn[8];
128 	uint8_t		   eport_nodewwn[8];
129 	uint32_t	   eport_max_fc_frame_size;
130 	uint32_t	   eport_mtu;
131 	uint64_t	   eport_link_speed;
132 	uint8_t		   eport_efh_dst[ETHERADDRL];
133 
134 	void		 (*eport_tx_frame)(fcoe_frame_t *frame);
135 	fcoe_frame_t	*(*eport_alloc_frame)(struct fcoe_port *eport,
136 	    uint32_t this_fc_frame_size, void *netb);
137 	void		 (*eport_release_frame)(fcoe_frame_t *frame);
138 	void		*(*eport_alloc_netb)(struct fcoe_port *eport,
139 	    uint32_t this_fc_frame_size, uint8_t **ppfc);
140 	void		 (*eport_free_netb)(void *netb);
141 	void		 (*eport_deregister_client)(struct fcoe_port *eport);
142 	int		 (*eport_ctl)(struct fcoe_port *eport,
143 	    int cmd, void *arg);
144 	int		 (*eport_set_mac_address)(struct fcoe_port *eport,
145 	    uint8_t *addr, boolean_t fc_assigned);
146 } fcoe_port_t;
147 
148 /*
149  * FCOE only supports two kinds of topology: direct P2P, fabric P2P.
150  */
151 #define	EPORT_FLAG_IS_DIRECT_P2P	0x01
152 #define	EPORT_FLAG_TGT_MODE		0x02
153 #define	EPORT_FLAG_INI_MODE		0x04
154 #define	EPORT_FLAG_MAC_IN_USE		0x08
155 
156 #define	FCOE_NOTIFY_EPORT_LINK_UP	0x01
157 #define	FCOE_NOTIFY_EPORT_LINK_DOWN	0x02
158 #define	FCOE_NOTIFY_EPORT_ADDR_CHG	0x03
159 
160 #define	FCOE_PORT_CTL_CMDS		0x3000
161 #define	FCOE_CMD_PORT_ONLINE		(FCOE_PORT_CTL_CMDS | 0x01)
162 #define	FCOE_CMD_PORT_OFFLINE		(FCOE_PORT_CTL_CMDS | 0x02)
163 
164 /*
165  * FCoE version control
166  */
167 typedef enum fcoe_ver
168 {
169 	FCOE_VER_1 = 0xAA01,
170 	FCOE_VER_2,
171 	FCOE_VER_3,
172 	FCOE_VER_4,
173 	FCOE_VER_5
174 } fcoe_ver_e;
175 
176 #define	FCOE_VER_NOW FCOE_VER_1
177 extern const fcoe_ver_e fcoe_ver_now;
178 
179 typedef struct fcoe_client {
180 	fcoe_ver_e	 ect_fcoe_ver;
181 	uint32_t	 ect_eport_flags;
182 	uint32_t	 ect_max_fc_frame_size;
183 	uint32_t	 ect_private_frame_struct_size;
184 	uint32_t	 ect_channelid;
185 	void		*ect_client_port_struct;
186 	void		 (*ect_rx_frame)(fcoe_frame_t *frame);
187 	void		 (*ect_port_event)(fcoe_port_t *eport, uint32_t event);
188 	void		 (*ect_release_sol_frame)(fcoe_frame_t *frame);
189 } fcoe_client_t;
190 
191 /*
192  * Define common-used conversion or calculation macros
193  */
194 #define	FCOE_V2B_1(x_v, x_b)				\
195 	{						\
196 		((uint8_t *)(x_b))[0] = 0xFF & (x_v);	\
197 	}
198 
199 #define	FCOE_V2B_2(x_v, x_b)					\
200 	{							\
201 		((uint8_t *)(x_b))[1] = 0xFF & (x_v);		\
202 		((uint8_t *)(x_b))[0] = 0xFF & ((x_v) >> 8);	\
203 	}
204 
205 #define	FCOE_V2B_3(x_v, x_b)					\
206 	{							\
207 		((uint8_t *)(x_b))[2] = 0xFF & (x_v);		\
208 		((uint8_t *)(x_b))[1] = 0xFF & ((x_v) >> 8);	\
209 		((uint8_t *)(x_b))[0] = 0xFF & ((x_v) >> 16);	\
210 	}
211 
212 #define	FCOE_V2B_4(x_v, x_b)					\
213 	{							\
214 		((uint8_t *)(x_b))[3] = 0xFF & (x_v);		\
215 		((uint8_t *)(x_b))[2] = 0xFF & ((x_v) >> 8);	\
216 		((uint8_t *)(x_b))[1] = 0xFF & ((x_v) >> 16);	\
217 		((uint8_t *)(x_b))[0] = 0xFF & ((x_v) >> 24);	\
218 	}
219 
220 #define	FCOE_V2B_8(x_v, x_b)					\
221 	{							\
222 		((uint8_t *)(x_b))[7] = 0xFF & (x_v);		\
223 		((uint8_t *)(x_b))[6] = 0xFF & ((x_v) >> 8);	\
224 		((uint8_t *)(x_b))[5] = 0xFF & ((x_v) >> 16);	\
225 		((uint8_t *)(x_b))[4] = 0xFF & ((x_v) >> 24);	\
226 		((uint8_t *)(x_b))[3] = 0xFF & ((x_v) >> 32);	\
227 		((uint8_t *)(x_b))[2] = 0xFF & ((x_v) >> 40);	\
228 		((uint8_t *)(x_b))[1] = 0xFF & ((x_v) >> 48);	\
229 		((uint8_t *)(x_b))[0] = 0xFF & ((x_v) >> 56);	\
230 	}
231 
232 #define	FCOE_B2V_1(x_b)				\
233 	((((uint8_t *)(x_b))[0]) & 0xFF)
234 
235 #define	FCOE_B2V_2(x_b)						\
236 	((((uint8_t *)(x_b))[1] | ((uint8_t *)(x_b))[0] << 8) & 0xFFFF)
237 
238 #define	FCOE_B2V_3(x_b)						\
239 	((((uint8_t *)(x_b))[2] | ((uint8_t *)(x_b))[1] << 8 |	\
240 	((uint8_t *)(x_b))[0] << 16) & 0xFFFFFF)
241 
242 #define	FCOE_B2V_4(x_b)						\
243 	((((uint8_t *)(x_b))[3] | ((uint8_t *)(x_b))[2] << 8 |	\
244 	((uint8_t *)(x_b))[1] << 16 |				\
245 	((uint8_t *)(x_b))[0] << 24) & 0xFFFFFFFF)
246 
247 #define	FCOE_B2V_8(x_b)						\
248 	((((uint8_t *)(x_b))[7] | ((uint8_t *)(x_b))[6] << 8 |	\
249 	((uint8_t *)(x_b))[5] << 16 |				\
250 	((uint8_t *)(x_b))[4] << 24 |				\
251 	((uint8_t *)(x_b))[3] << 32 |				\
252 	((uint8_t *)(x_b))[2] << 40 |				\
253 	((uint8_t *)(x_b))[1] << 48 |				\
254 	((uint8_t *)(x_b))[0] << 56) & 0xFFFFFFFFFFFFFFFF)
255 
256 /*
257  * Get FC frame header's element
258  */
259 #define	FRM_R_CTL(x_frm)	(FCOE_B2V_1((x_frm)->frm_hdr->hdr_r_ctl))
260 #define	FRM_D_ID(x_frm)		(FCOE_B2V_3((x_frm)->frm_hdr->hdr_d_id))
261 #define	FRM_S_ID(x_frm)		(FCOE_B2V_3((x_frm)->frm_hdr->hdr_s_id))
262 #define	FRM_TYPE(x_frm)		(FCOE_B2V_1((x_frm)->frm_hdr->hdr_type))
263 #define	FRM_F_CTL(x_frm)	(FCOE_B2V_3((x_frm)->frm_hdr->hdr_f_ctl))
264 #define	FRM_SEQ_ID(x_frm)	(FCOE_B2V_1((x_frm)->frm_hdr->hdr_seq_id))
265 #define	FRM_DF_CTL(x_frm)	(FCOE_B2V_1((x_frm)->frm_hdr->hdr_df_ctl))
266 #define	FRM_SEQ_CNT(x_frm)	(FCOE_B2V_2((x_frm)->frm_hdr->hdr_seq_cnt))
267 #define	FRM_OXID(x_frm)		(FCOE_B2V_2((x_frm)->frm_hdr->hdr_oxid))
268 #define	FRM_RXID(x_frm)		(FCOE_B2V_2((x_frm)->frm_hdr->hdr_rxid))
269 #define	FRM_PARAM(x_frm)	(FCOE_B2V_4((x_frm)->frm_hdr->hdr_param))
270 
271 /*
272  * Set FC frame header's element
273  */
274 #define	FFM_R_CTL(x_v, x_frm)	FCOE_V2B_1((x_v), (x_frm)->frm_hdr->hdr_r_ctl)
275 #define	FFM_D_ID(x_v, x_frm)	FCOE_V2B_3((x_v), (x_frm)->frm_hdr->hdr_d_id)
276 #define	FFM_S_ID(x_v, x_frm)	FCOE_V2B_3((x_v), (x_frm)->frm_hdr->hdr_s_id)
277 #define	FFM_TYPE(x_v, x_frm)	FCOE_V2B_1((x_v), (x_frm)->frm_hdr->hdr_type)
278 #define	FFM_F_CTL(x_v, x_frm)	FCOE_V2B_3((x_v), (x_frm)->frm_hdr->hdr_f_ctl)
279 #define	FFM_SEQ_ID(x_v, x_frm)	FCOE_V2B_1((x_v), (x_frm)->frm_hdr->hdr_seq_id)
280 #define	FFM_DF_CTL(x_v, x_frm)	FCOE_V2B_1((x_v), (x_frm)->frm_hdr->hdr_df_ctl)
281 #define	FFM_SEQ_CNT(x_v, x_frm)	FCOE_V2B_2((x_v), (x_frm)->frm_hdr->hdr_seq_cnt)
282 #define	FFM_OXID(x_v, x_frm)	FCOE_V2B_2((x_v), (x_frm)->frm_hdr->hdr_oxid)
283 #define	FFM_RXID(x_v, x_frm)	FCOE_V2B_2((x_v), (x_frm)->frm_hdr->hdr_rxid)
284 #define	FFM_PARAM(x_v, x_frm)	FCOE_V2B_4((x_v), (x_frm)->frm_hdr->hdr_param)
285 
286 /*
287  * frame header checking
288  */
289 #define	FRM_IS_LAST_FRAME(x_frm)		(FRM_F_CTL(x_frm) & (1 << 19))
290 #define	FRM_SENDER_IS_XCH_RESPONDER(x_frm)	(FRM_F_CTL(x_frm) & (1 << 23))
291 
292 /*
293  * FCOET/FCOEI will only call this fcoe function explicitly, all others
294  * should be called through vectors in struct fcoe_port.
295  * FCOE client call this to register one port to FCOE, FCOE need initialize
296  * and return the corresponding fcoe_port.
297  */
298 extern fcoe_port_t *fcoe_register_client(fcoe_client_t *client);
299 
300 #define	EPORT_CLT_TYPE(eport)				\
301 	(((eport)->eport_flags & EPORT_FLAG_INI_MODE) ? \
302 	FCOE_CLIENT_INITIATOR : FCOE_CLIENT_TARGET)
303 
304 #define	FCOE_SET_DEFAULT_OUI(x_oui)	\
305 	(x_oui)[0] = 0x0e; (x_oui)[1] = 0xfc; (x_oui)[2] = 0x00;
306 #define	FCOE_SET_DEFAULT_FPORT_ADDR(x_addr)	\
307 	FCOE_SET_DEFAULT_OUI(x_addr)		\
308 	(x_addr)[3] = 0xff; (x_addr)[4] = 0xff; (x_addr)[5] = 0xfe;
309 
310 /*
311  * FC payload size
312  */
313 #define	FCOE_DEFAULT_FCP_DATA_PAYLOAD_SIZE	2048
314 #define	FCOE_MIN_FCP_DATA_PAYLOAD_SIZE		1024
315 
316 typedef struct fcoe_fcp_cmnd {
317 	uint8_t ffc_lun[8];
318 	uint8_t ffc_ref_num[1];
319 
320 	/*
321 	 * least 3 bits
322 	 */
323 	uint8_t ffc_attribute[1];
324 
325 	/*
326 	 * Magnagement flags
327 	 */
328 	uint8_t ffc_management_flags[1];
329 
330 	/*
331 	 * additional cdb len and read/write flag
332 	 */
333 	uint8_t ffc_addlen_rdwr[1];
334 
335 	uint8_t ffc_cdb[16];
336 	uint8_t ffc_fcp_dl[4];
337 } fcoe_fcp_cmnd_t;
338 
339 typedef struct fcoe_fcp_rsp {
340 	uint8_t ffr_rsvd[8];
341 
342 	/*
343 	 * see SAM-4
344 	 */
345 	uint8_t ffr_retry_delay_timer[2];
346 	uint8_t ffr_flags[1];
347 	uint8_t ffr_scsi_status[1];
348 	uint8_t ffr_resid[4];
349 	uint8_t ffr_sns_len[4];
350 	uint8_t ffr_rsp_len[4];
351 	/*
352 	 * Followed by sense data when available
353 	 */
354 } fcoe_fcp_rsp_t;
355 
356 typedef struct fcoe_fcp_xfer_rdy {
357 	uint8_t fxr_data_ro[4];
358 	uint8_t fxr_burst_len[4];
359 	uint8_t fxr_rsvd[4];
360 } fcoe_fcp_xfer_rdy_t;
361 
362 /*
363  * FCOE project global functions
364  */
365 #if !defined(__FUNCTION__)
366 #define	__FUNCTION__ ((caddr_t)__func__)
367 #endif
368 
369 #define	FCOE_STR_LEN 32
370 
371 /*
372  * timestamp (golbal variable in sys/systm.h)
373  */
374 #define	CURRENT_CLOCK		(ddi_get_lbolt())
375 #define	FCOE_SEC2TICK(x_sec)	(drv_usectohz((x_sec) * 1000000))
376 
377 /*
378  * Form/convert mod_hash_key from/to xch ID
379  */
380 #define	FMHK(x_xid)		(mod_hash_key_t)(uintptr_t)(x_xid)
381 #define	CMHK(x_key)		(uint16_t)(uintptr_t)(x_key)
382 
383 typedef void (*TQ_FUNC_P)(void *);
384 extern void fcoe_trace(caddr_t ident, const char *fmt, ...);
385 
386 #endif
387 
388 #ifdef	__cplusplus
389 }
390 #endif
391 
392 #endif	/* _FCOE_COMMON_H_ */
393