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
29extern "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 */
69typedef 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 */
93struct fcoe_port;
94typedef 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 */
123typedef 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 */
167typedef 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
177extern const fcoe_ver_e fcoe_ver_now;
178
179typedef 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 */
298extern 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
316typedef 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
339typedef 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
356typedef 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
383typedef void (*TQ_FUNC_P)(void *);
384extern 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