xref: /illumos-gate/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fct.c (revision a73c0fe4e90b82a478f821ef3adb5cf34f6a9346)
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 /*
23  * Copyright 2008 Emulex.  All rights reserved.
24  * Use is subject to License terms.
25  */
26 
27 
28 #include "emlxs.h"
29 
30 #ifdef SFCT_SUPPORT
31 
32 /* #define	FCT_API_TRACE		Extra debug */
33 
34 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
35 EMLXS_MSG_DEF(EMLXS_FCT_C);
36 
37 #ifndef PORT_SPEED_10G
38 #define	PORT_SPEED_10G			0x10
39 #endif	/* PORT_SPEED_10G */
40 
41 static uint32_t emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp);
42 static uint32_t emlxs_fct_sli2_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp);
43 static uint32_t emlxs_fct_sli3_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp);
44 static void emlxs_fct_handle_acc(emlxs_port_t *port, emlxs_buf_t *sbp,
45     IOCBQ *iocbq);
46 static void emlxs_fct_handle_reject(emlxs_port_t *port, emlxs_buf_t *sbp,
47     IOCBQ *iocbq);
48 static emlxs_buf_t *emlxs_fct_cmd_init(emlxs_port_t *port, fct_cmd_t *fct_cmd);
49 static int emlxs_fct_cmd_uninit(emlxs_port_t *port, fct_cmd_t *fct_cmd);
50 
51 static fct_status_t emlxs_flogi_xchg(struct fct_local_port *fct_port,
52     struct fct_flogi_xchg *fx);
53 static fct_status_t emlxs_fct_get_link_info(fct_local_port_t *fct_port,
54     fct_link_info_t *link);
55 static fct_status_t emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port,
56     fct_remote_port_t *port_handle);
57 static fct_status_t emlxs_fct_send_cmd(fct_cmd_t *fct_cmd);
58 static fct_status_t emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd,
59     stmf_data_buf_t *dbuf, uint32_t ioflags);
60 static fct_status_t emlxs_fct_send_cmd_rsp(fct_cmd_t *fct_cmd,
61     uint32_t ioflags);
62 static fct_status_t emlxs_fct_abort(fct_local_port_t *fct_port, fct_cmd_t *cmd,
63     uint32_t flags);
64 static void emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg);
65 static fct_status_t emlxs_fct_register_remote_port(fct_local_port_t *fct_port,
66     fct_remote_port_t *port_handle, fct_cmd_t *plogi);
67 static fct_status_t emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd);
68 static fct_status_t emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd);
69 static fct_status_t emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd);
70 static fct_status_t emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd);
71 static fct_status_t emlxs_fct_send_abts_rsp(fct_cmd_t *fct_cmd);
72 static void emlxs_fct_pkt_comp(fc_packet_t *pkt);
73 static void emlxs_populate_hba_details(fct_local_port_t *fct_port,
74     fct_port_attrs_t *port_attrs);
75 
76 static fct_status_t emlxs_fct_dmem_init(emlxs_port_t *port);
77 static void emlxs_fct_dmem_fini(emlxs_port_t *port);
78 
79 static stmf_data_buf_t *emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port,
80     uint32_t size, uint32_t *pminsize, uint32_t flags);
81 static void emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *dbuf);
82 
83 static void emlxs_fct_dbuf_dma_sync(stmf_data_buf_t *dbuf, uint_t sync_type);
84 static emlxs_buf_t *emlxs_fct_pkt_init(emlxs_port_t *port, fct_cmd_t *fct_cmd,
85     fc_packet_t *pkt);
86 
87 static void emlxs_fct_unsol_flush(emlxs_port_t *port);
88 static uint32_t emlxs_fct_process_unsol_flogi(emlxs_port_t *port, RING *rp,
89     IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
90 static uint32_t emlxs_fct_process_unsol_plogi(emlxs_port_t *port, RING *rp,
91     IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
92 static void emlxs_fct_handle_rcvd_flogi(emlxs_port_t *port, fct_cmd_t *fct_cmd);
93 static fct_status_t emlxs_fct_pkt_abort(emlxs_port_t *port, emlxs_buf_t *sbp);
94 static fct_status_t emlxs_fct_send_qfull_reply(emlxs_port_t *port,
95     emlxs_node_t *ndlp, uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd);
96 
97 #ifdef MODSYM_SUPPORT
98 
99 static int
100 emlxs_fct_modopen()
101 {
102 	int err;
103 
104 	if (emlxs_modsym.mod_fct) {
105 		return (1);
106 	}
107 	/* Comstar (fct) */
108 	err = 0;
109 	emlxs_modsym.mod_fct = ddi_modopen("drv/fct", KRTLD_MODE_FIRST, &err);
110 	if (!emlxs_modsym.mod_fct) {
111 
112 		cmn_err(CE_WARN, "?%s: ddi_modopen drv/fct failed: err %d",
113 		    DRIVER_NAME, err);
114 		goto failed;
115 	}
116 	/* Comstar (stmf) */
117 	err = 0;
118 	emlxs_modsym.mod_stmf = ddi_modopen("drv/stmf", KRTLD_MODE_FIRST, &err);
119 	if (!emlxs_modsym.mod_stmf) {
120 
121 		cmn_err(CE_WARN, "?%s: ddi_modopen drv/stmf failed: err %d",
122 		    DRIVER_NAME, err);
123 		goto failed;
124 	}
125 	err = 0;
126 	/* Check if the fct fct_alloc is present */
127 	emlxs_modsym.fct_alloc = (void *(*) ()) ddi_modsym(emlxs_modsym.mod_fct,
128 	    "fct_alloc", &err);
129 	if ((void *)emlxs_modsym.fct_alloc == NULL) {
130 		cmn_err(CE_WARN,
131 		    "?%s: drv/fct: fct_alloc not present", DRIVER_NAME);
132 		goto failed;
133 	}
134 	err = 0;
135 	/* Check if the fct fct_free is present */
136 	emlxs_modsym.fct_free = (void (*) ())ddi_modsym(emlxs_modsym.mod_fct,
137 	    "fct_free", &err);
138 	if ((void *)emlxs_modsym.fct_free == NULL) {
139 		cmn_err(CE_WARN,
140 		    "?%s: drv/fct: fct_free not present", DRIVER_NAME);
141 		goto failed;
142 	}
143 	err = 0;
144 	/* Check if the fct fct_scsi_task_alloc is present */
145 	emlxs_modsym.fct_scsi_task_alloc = (void *(*) ())
146 	    ddi_modsym(emlxs_modsym.mod_fct, "fct_scsi_task_alloc", &err);
147 	if ((void *)emlxs_modsym.fct_scsi_task_alloc == NULL) {
148 		cmn_err(CE_WARN,
149 		    "?%s: drv/fct: fct_scsi_task_alloc not present",
150 		    DRIVER_NAME);
151 		goto failed;
152 	}
153 	err = 0;
154 	/* Check if the fct fct_register_local_port is present */
155 	emlxs_modsym.fct_register_local_port = (int (*) ())
156 	    ddi_modsym(emlxs_modsym.mod_fct, "fct_register_local_port", &err);
157 	if ((void *)emlxs_modsym.fct_register_local_port == NULL) {
158 		cmn_err(CE_WARN,
159 		    "?%s: drv/fct: fct_register_local_port not present",
160 		    DRIVER_NAME);
161 		goto failed;
162 	}
163 	err = 0;
164 	/* Check if the fct fct_deregister_local_port is present */
165 	emlxs_modsym.fct_deregister_local_port = (void (*) ())
166 	    ddi_modsym(emlxs_modsym.mod_fct, "fct_deregister_local_port", &err);
167 	if ((void *)emlxs_modsym.fct_deregister_local_port == NULL) {
168 		cmn_err(CE_WARN,
169 		    "?%s: drv/fct: fct_deregister_local_port not present",
170 		    DRIVER_NAME);
171 		goto failed;
172 	}
173 	err = 0;
174 	/* Check if the fct fct_handle_event is present */
175 	emlxs_modsym.fct_handle_event = (void (*) ())
176 	    ddi_modsym(emlxs_modsym.mod_fct, "fct_handle_event", &err);
177 	if ((void *)emlxs_modsym.fct_handle_event == NULL) {
178 		cmn_err(CE_WARN,
179 		    "?%s: drv/fct: fct_handle_event not present", DRIVER_NAME);
180 		goto failed;
181 	}
182 	err = 0;
183 	/* Check if the fct fct_post_rcvd_cmd is present */
184 	emlxs_modsym.fct_post_rcvd_cmd = (void (*) ())
185 	    ddi_modsym(emlxs_modsym.mod_fct, "fct_post_rcvd_cmd", &err);
186 	if ((void *)emlxs_modsym.fct_post_rcvd_cmd == NULL) {
187 		cmn_err(CE_WARN,
188 		    "?%s: drv/fct: fct_post_rcvd_cmd not present", DRIVER_NAME);
189 		goto failed;
190 	}
191 	err = 0;
192 	/* Check if the fct fct_alloc is present */
193 	emlxs_modsym.fct_ctl = (void (*) ())ddi_modsym(emlxs_modsym.mod_fct,
194 	    "fct_ctl", &err);
195 	if ((void *)emlxs_modsym.fct_ctl == NULL) {
196 		cmn_err(CE_WARN,
197 		    "?%s: drv/fct: fct_ctl not present", DRIVER_NAME);
198 		goto failed;
199 	}
200 	err = 0;
201 	/* Check if the fct fct_send_response_done is present */
202 	emlxs_modsym.fct_send_response_done = (void (*) ())
203 	    ddi_modsym(emlxs_modsym.mod_fct, "fct_send_response_done", &err);
204 	if ((void *)emlxs_modsym.fct_send_response_done == NULL) {
205 		cmn_err(CE_WARN,
206 		    "?%s: drv/fct: fct_send_response_done not present",
207 		    DRIVER_NAME);
208 		goto failed;
209 	}
210 	err = 0;
211 	/* Check if the fct fct_send_cmd_done is present */
212 	emlxs_modsym.fct_send_cmd_done = (void (*) ())
213 	    ddi_modsym(emlxs_modsym.mod_fct, "fct_send_cmd_done", &err);
214 	if ((void *)emlxs_modsym.fct_send_cmd_done == NULL) {
215 		cmn_err(CE_WARN,
216 		    "?%s: drv/fct: fct_send_cmd_done not present", DRIVER_NAME);
217 		goto failed;
218 	}
219 	err = 0;
220 	/* Check if the fct fct_scsi_xfer_data_done is present */
221 	emlxs_modsym.fct_scsi_data_xfer_done = (void (*) ())
222 	    ddi_modsym(emlxs_modsym.mod_fct, "fct_scsi_data_xfer_done", &err);
223 	if ((void *)emlxs_modsym.fct_scsi_data_xfer_done == NULL) {
224 		cmn_err(CE_WARN,
225 		    "?%s: drv/fct: fct_scsi_data_xfer_done not present",
226 		    DRIVER_NAME);
227 		goto failed;
228 	}
229 	err = 0;
230 	/* Check if the fct fct_port_shutdown is present */
231 	emlxs_modsym.fct_port_shutdown = (fct_status_t(*) ())
232 	    ddi_modsym(emlxs_modsym.mod_fct, "fct_port_shutdown", &err);
233 	if ((void *)emlxs_modsym.fct_port_shutdown == NULL) {
234 		cmn_err(CE_WARN,
235 		    "?%s: drv/fct: fct_port_shutdown not present", DRIVER_NAME);
236 		goto failed;
237 	}
238 	err = 0;
239 	/* Check if the fct fct_port_initialize is present */
240 	emlxs_modsym.fct_port_initialize = (fct_status_t(*) ())
241 	    ddi_modsym(emlxs_modsym.mod_fct, "fct_port_initialize", &err);
242 	if ((void *)emlxs_modsym.fct_port_initialize == NULL) {
243 		cmn_err(CE_WARN,
244 		    "?%s: drv/fct: fct_port_initialize not present",
245 		    DRIVER_NAME);
246 		goto failed;
247 	}
248 	err = 0;
249 	/* Check if the fct fct_handle_rcvd_flogi is present */
250 	emlxs_modsym.fct_handle_rcvd_flogi = (fct_status_t(*) ())
251 	    ddi_modsym(emlxs_modsym.mod_fct, "fct_handle_rcvd_flogi", &err);
252 	if ((void *)emlxs_modsym.fct_handle_rcvd_flogi == NULL) {
253 		cmn_err(CE_WARN,
254 		    "?%s: drv/fct: fct_handle_rcvd_flogi not present",
255 		    DRIVER_NAME);
256 		goto failed;
257 	}
258 	/* Comstar (stmf) */
259 	err = 0;
260 	/* Check if the stmf stmf_alloc is present */
261 	emlxs_modsym.stmf_alloc = (void *(*) ())
262 	    ddi_modsym(emlxs_modsym.mod_stmf, "stmf_alloc", &err);
263 	if ((void *)emlxs_modsym.stmf_alloc == NULL) {
264 		cmn_err(CE_WARN,
265 		    "?%s: drv/stmf: stmf_alloc not present", DRIVER_NAME);
266 		goto failed;
267 	}
268 	err = 0;
269 	/* Check if the stmf stmf_free is present */
270 	emlxs_modsym.stmf_free = (void (*) ())ddi_modsym(emlxs_modsym.mod_stmf,
271 	    "stmf_free", &err);
272 	if ((void *)emlxs_modsym.stmf_free == NULL) {
273 		cmn_err(CE_WARN,
274 		    "?%s: drv/stmf: stmf_free not present", DRIVER_NAME);
275 		goto failed;
276 	}
277 	err = 0;
278 	/* Check if the stmf stmf_deregister_port_provider is present */
279 	emlxs_modsym.stmf_deregister_port_provider =
280 	    (void (*) ())ddi_modsym(emlxs_modsym.mod_stmf,
281 	    "stmf_deregister_port_provider", &err);
282 	if ((void *)emlxs_modsym.stmf_deregister_port_provider == NULL) {
283 		cmn_err(CE_WARN,
284 		    "?%s: drv/stmf: stmf_deregister_port_provider not present",
285 		    DRIVER_NAME);
286 		goto failed;
287 	}
288 	err = 0;
289 	/* Check if the stmf stmf_register_port_provider is present */
290 	emlxs_modsym.stmf_register_port_provider =
291 	    (int (*) ())ddi_modsym(emlxs_modsym.mod_stmf,
292 	    "stmf_register_port_provider", &err);
293 	if ((void *)emlxs_modsym.stmf_register_port_provider == NULL) {
294 		cmn_err(CE_WARN,
295 		    "?%s: drv/stmf: stmf_register_port_provider not present",
296 		    DRIVER_NAME);
297 		goto failed;
298 	}
299 	return (1);
300 
301 failed:
302 
303 	emlxs_fct_modclose();
304 
305 	return (0);
306 
307 } /* emlxs_fct_modopen() */
308 
309 
310 extern void
311 emlxs_fct_modclose()
312 {
313 
314 	if (emlxs_modsym.mod_fct) {
315 		(void) ddi_modclose(emlxs_modsym.mod_fct);
316 		emlxs_modsym.mod_fct = 0;
317 	}
318 	if (emlxs_modsym.mod_stmf) {
319 		(void) ddi_modclose(emlxs_modsym.mod_stmf);
320 		emlxs_modsym.mod_stmf = 0;
321 	}
322 	emlxs_modsym.fct_alloc = NULL;
323 	emlxs_modsym.fct_free = NULL;
324 	emlxs_modsym.fct_scsi_task_alloc = NULL;
325 	emlxs_modsym.fct_register_local_port = NULL;
326 	emlxs_modsym.fct_deregister_local_port = NULL;
327 	emlxs_modsym.fct_handle_event = NULL;
328 	emlxs_modsym.fct_ctl = NULL;
329 	emlxs_modsym.fct_send_response_done = NULL;
330 	emlxs_modsym.fct_send_cmd_done = NULL;
331 	emlxs_modsym.fct_scsi_data_xfer_done = NULL;
332 	emlxs_modsym.fct_port_shutdown = NULL;
333 	emlxs_modsym.fct_port_initialize = NULL;
334 	emlxs_modsym.fct_handle_rcvd_flogi = NULL;
335 
336 	emlxs_modsym.stmf_alloc = NULL;
337 	emlxs_modsym.stmf_free = NULL;
338 	emlxs_modsym.stmf_deregister_port_provider = NULL;
339 	emlxs_modsym.stmf_register_port_provider = NULL;
340 
341 } /* emlxs_fct_modclose() */
342 
343 #endif	/* MODSYM_SUPPORT */
344 
345 
346 
347 extern void
348 emlxs_fct_unsol_callback(emlxs_port_t *port, fct_cmd_t *fct_cmd)
349 {
350 	emlxs_hba_t *hba = HBA;
351 	emlxs_buf_t *cmd_sbp;
352 
353 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
354 
355 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
356 		mutex_enter(&cmd_sbp->mtx);
357 		/* mutex_exit(&cmd_sbp->mtx); */
358 		(void) emlxs_fct_cmd_uninit(port, fct_cmd);
359 
360 #ifdef FCT_API_TRACE
361 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
362 		    "fct_free:1 %p", cmd_sbp->fct_cmd);
363 #endif	/* FCT_API_TRACE */
364 		MODSYM(fct_free) (cmd_sbp->fct_cmd);
365 	}
366 	/* Online & Link up */
367 	else if (port->fct_flags & FCT_STATE_LINK_UP) {
368 		if (cmd_sbp->fct_flags & EMLXS_FCT_FLOGI) {
369 
370 			emlxs_fct_handle_rcvd_flogi(port, fct_cmd);
371 		} else {
372 			mutex_enter(&cmd_sbp->mtx);
373 			cmd_sbp->pkt_flags |= PACKET_RETURNED;
374 			mutex_exit(&cmd_sbp->mtx);
375 
376 #ifdef FCT_API_TRACE
377 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
378 			    "fct_post_rcvd_cmd:1 %p: portid x%x",
379 			    fct_cmd, fct_cmd->cmd_lportid);
380 #endif	/* FCT_API_TRACE */
381 			MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
382 		}
383 	} else {	/* Online & Link down */
384 		/* Add buffer to queue tail */
385 		mutex_enter(&EMLXS_PORT_LOCK);
386 
387 		if (port->fct_wait_tail) {
388 			port->fct_wait_tail->next = cmd_sbp;
389 		}
390 		port->fct_wait_tail = cmd_sbp;
391 
392 		if (!port->fct_wait_head) {
393 			port->fct_wait_head = cmd_sbp;
394 		}
395 		mutex_exit(&EMLXS_PORT_LOCK);
396 	}
397 
398 	return;
399 
400 } /* emlxs_fct_unsol_callback() */
401 
402 
403 /* This is called at port online and offline */
404 static void
405 emlxs_fct_unsol_flush(emlxs_port_t *port)
406 {
407 	emlxs_hba_t *hba = HBA;
408 	emlxs_buf_t *cmd_sbp;
409 	emlxs_buf_t *next;
410 	fct_cmd_t *fct_cmd;
411 
412 	if (!port->fct_port) {
413 		return;
414 	}
415 	/* Return if nothing to do */
416 	if (!port->fct_wait_head) {
417 		return;
418 	}
419 	mutex_enter(&EMLXS_PORT_LOCK);
420 	cmd_sbp = port->fct_wait_head;
421 	port->fct_wait_head = NULL;
422 	port->fct_wait_tail = NULL;
423 	mutex_exit(&EMLXS_PORT_LOCK);
424 
425 	while (cmd_sbp) {
426 		next = cmd_sbp->next;
427 		fct_cmd = cmd_sbp->fct_cmd;
428 
429 		if (port->fct_flags & FCT_STATE_LINK_UP) {
430 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
431 			    "Completing fct_cmd: %p", fct_cmd);
432 
433 			if (cmd_sbp->fct_flags & EMLXS_FCT_FLOGI) {
434 				emlxs_fct_handle_rcvd_flogi(port, fct_cmd);
435 			} else {
436 				mutex_enter(&cmd_sbp->mtx);
437 				cmd_sbp->pkt_flags |= PACKET_RETURNED;
438 				mutex_exit(&cmd_sbp->mtx);
439 
440 #ifdef FCT_API_TRACE
441 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
442 				    "fct_post_rcvd_cmd:2 %p: portid x%x",
443 				    fct_cmd, fct_cmd->cmd_lportid);
444 #endif	/* FCT_API_TRACE */
445 				MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
446 			}
447 		} else {	/* Drop the cmd */
448 			mutex_enter(&cmd_sbp->mtx);
449 			/* mutex_exit(&cmd_sbp->mtx); */
450 			(void) emlxs_fct_cmd_uninit(port, fct_cmd);
451 
452 #ifdef FCT_API_TRACE
453 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
454 			    "fct_free:2 %p", fct_cmd);
455 #endif	/* FCT_API_TRACE */
456 			MODSYM(fct_free) (fct_cmd);
457 		}
458 
459 		cmd_sbp = next;
460 
461 	}	/* while() */
462 
463 	return;
464 
465 } /* emlxs_fct_unsol_flush() */
466 
467 
468 int
469 emlxs_is_digit(uint8_t chr)
470 {
471 	if ((chr >= '0') && (chr <= '9')) {
472 		return (1);
473 	}
474 	return (0);
475 
476 } /* emlxs_is_digit */
477 
478 
479 /*
480  *   Convert an ASCII decimal numeric string to integer.
481  *   Negation character '-' is not handled.
482  */
483 uint32_t
484 emlxs_str_atoi(uint8_t *string)
485 {
486 	uint32_t num = 0;
487 	int i = 0;
488 
489 	while (string[i]) {
490 		if (!emlxs_is_digit(string[i])) {
491 			return (num);
492 		}
493 		num = num * 10 + (string[i++] - '0');
494 	}
495 
496 	return (num);
497 
498 } /* emlxs_str_atoi() */
499 
500 
501 static void
502 emlxs_init_fct_bufpool(emlxs_hba_t *hba, char **arrayp, uint32_t cnt)
503 {
504 	emlxs_port_t *port = &PPORT;
505 	uint8_t *datap;
506 	int i;
507 
508 	bzero((uint8_t *)port->dmem_bucket, sizeof (port->dmem_bucket));
509 	for (i = 0; i < cnt; i++) {
510 		datap = (uint8_t *)arrayp[i];
511 		if (datap == 0)
512 			break;
513 
514 		while (*datap == ' ')	/* Skip spaces */
515 			datap++;
516 
517 		port->dmem_bucket[i].dmem_buf_size = emlxs_str_atoi(datap);
518 
519 		while ((*datap != ':') && (*datap != 0))
520 			datap++;
521 		if (*datap == ':')	/* Skip past delimeter */
522 			datap++;
523 		while (*datap == ' ')	/* Skip spaces */
524 			datap++;
525 
526 		port->dmem_bucket[i].dmem_nbufs = emlxs_str_atoi(datap);
527 
528 		/* Check for a bad entry */
529 		if (!port->dmem_bucket[i].dmem_buf_size ||
530 		    !port->dmem_bucket[i].dmem_nbufs) {
531 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
532 			    "Bad fct-bufpool entry %d %d",
533 			    port->dmem_bucket[i].dmem_buf_size,
534 			    port->dmem_bucket[i].dmem_nbufs);
535 
536 			port->dmem_bucket[i].dmem_buf_size = 0;
537 			port->dmem_bucket[i].dmem_nbufs = 0;
538 		}
539 		if (i >= FCT_MAX_BUCKETS)
540 			break;
541 	}
542 }
543 
544 
545 static void
546 emlxs_fct_cfg_init(emlxs_hba_t *hba)
547 {
548 	emlxs_port_t *port = &PPORT;
549 	char **arrayp;
550 	uint32_t cnt;
551 	char buf[32];
552 	int status;
553 
554 	bzero((void *) buf, 32);
555 	cnt = 0;
556 	arrayp = NULL;
557 
558 	(void) sprintf(buf, "emlxs%d-fct-bufpool", ddi_get_instance(hba->dip));
559 	status = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
560 	    (DDI_PROP_DONTPASS), buf, &arrayp, &cnt);
561 
562 	if ((status == DDI_PROP_SUCCESS) && cnt && arrayp) {
563 		emlxs_init_fct_bufpool(hba, arrayp, cnt);
564 	} else {
565 		status = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
566 		    (DDI_PROP_DONTPASS), "fct-bufpool", &arrayp, &cnt);
567 
568 		if ((status == DDI_PROP_SUCCESS) && cnt && arrayp) {
569 			emlxs_init_fct_bufpool(hba, arrayp, cnt);
570 		} else {
571 			bzero((uint8_t *)port->dmem_bucket,
572 			    sizeof (port->dmem_bucket));
573 			port->dmem_bucket[0].dmem_buf_size = 512;
574 			port->dmem_bucket[0].dmem_nbufs = FCT_BUF_COUNT_512;
575 			port->dmem_bucket[1].dmem_buf_size = 8192;
576 			port->dmem_bucket[1].dmem_nbufs = FCT_BUF_COUNT_8K;
577 			port->dmem_bucket[2].dmem_buf_size = 65536;
578 			port->dmem_bucket[2].dmem_nbufs = FCT_BUF_COUNT_64K;
579 			port->dmem_bucket[3].dmem_buf_size = (2 * 65536);
580 			port->dmem_bucket[3].dmem_nbufs = FCT_BUF_COUNT_128K;
581 		}
582 	}
583 
584 	bzero((void *)buf, 32);
585 	cnt = 0;
586 
587 	(void) sprintf(buf, "emlxs%d-fct-queue-depth",
588 	    ddi_get_instance(hba->dip));
589 	cnt = ddi_prop_get_int(DDI_DEV_T_ANY, hba->dip,
590 	    (DDI_PROP_DONTPASS), buf, 0);
591 
592 	if ((cnt == DDI_PROP_NOT_FOUND) || (cnt == 0)) {
593 		cnt = ddi_prop_get_int(DDI_DEV_T_ANY, hba->dip,
594 		    (DDI_PROP_DONTPASS), "fct-queue-depth", 0);
595 
596 		if (cnt == DDI_PROP_NOT_FOUND) {
597 			cnt = 64;
598 		}
599 	}
600 	port->fct_queue_depth = cnt;
601 	return;
602 
603 } /* emlxs_fct_cfg_init() */
604 
605 
606 extern void
607 emlxs_fct_init(emlxs_hba_t *hba)
608 {
609 	emlxs_port_t *port = &PPORT;
610 	emlxs_config_t *cfg = &CFG;
611 	emlxs_port_t *vport;
612 	uint32_t i;
613 
614 	if (!hba->tgt_mode) {
615 		return;
616 	}
617 #ifdef MODSYM_SUPPORT
618 	/* Open COMSTAR */
619 	(void) emlxs_fct_modopen();
620 #endif	/* MODSYM_SUPPORT */
621 
622 	/* Check if COMSTAR is present */
623 	if (((void *)MODSYM(stmf_alloc) == NULL) ||
624 	    ((void *) MODSYM(fct_alloc) == NULL)) {
625 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
626 		    "Comstar not present. Target mode disabled.");
627 		goto failed;
628 	}
629 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
630 	    "Comstar present. Target mode enabled.");
631 
632 #ifdef NPIV_SUPPORT
633 	if (cfg[CFG_NPIV_ENABLE].current) {
634 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
635 		    "enable-npiv: Not supported in target mode. Disabling.");
636 
637 		/* Temporary patch to disable npiv */
638 		cfg[CFG_NPIV_ENABLE].current = 0;
639 	}
640 #endif	/* NPIV_SUPPORT */
641 
642 #ifdef DHCHAP_SUPPORT
643 	if (cfg[CFG_AUTH_ENABLE].current) {
644 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
645 		    "enable-auth: Not supported in target mode. Disabling.");
646 
647 		/* Temporary patch to disable auth */
648 		cfg[CFG_AUTH_ENABLE].current = 0;
649 	}
650 #endif	/* DHCHAP_SUPPORT */
651 
652 	emlxs_fct_cfg_init(hba);
653 	return;
654 
655 failed:
656 
657 	hba->tgt_mode = 0;
658 	for (i = 0; i < MAX_VPORTS; i++) {
659 		vport = &VPORT(i);
660 		vport->tgt_mode = 0;
661 		vport->fct_flags = 0;
662 	}
663 } /* emlxs_fct_init() */
664 
665 
666 extern void
667 emlxs_fct_attach(emlxs_hba_t *hba)
668 {
669 	emlxs_port_t *port = &PPORT;
670 	uint32_t vpi;
671 
672 	if (!hba->tgt_mode) {
673 		return;
674 	}
675 	/* Bind the physical port */
676 	emlxs_fct_bind_port(port);
677 
678 	/* Bind virtual ports */
679 	if (hba->flag & FC_NPIV_ENABLED) {
680 		for (vpi = 1; vpi < hba->vpi_high; vpi++) {
681 			port = &VPORT(vpi);
682 
683 			if (!(port->flag & EMLXS_PORT_ENABLE)) {
684 				continue;
685 			}
686 			emlxs_fct_bind_port(port);
687 		}
688 	}
689 	return;
690 
691 } /* emlxs_fct_attach() */
692 
693 
694 extern void
695 emlxs_fct_detach(emlxs_hba_t *hba)
696 {
697 	uint32_t i;
698 	emlxs_port_t *vport;
699 
700 	if (hba->tgt_mode) {
701 		for (i = 0; i < MAX_VPORTS; i++) {
702 			vport = &VPORT(i);
703 
704 			if (!vport->tgt_mode) {
705 				continue;
706 			}
707 			emlxs_fct_unbind_port(vport);
708 			vport->tgt_mode = 0;
709 		}
710 
711 
712 		hba->tgt_mode = 0;
713 	}
714 	return;
715 
716 } /* emlxs_fct_detach() */
717 
718 
719 extern void
720 emlxs_fct_unbind_port(emlxs_port_t *port)
721 {
722 	emlxs_hba_t *hba = HBA;
723 	char node_name[32];
724 
725 	if (!port->tgt_mode) {
726 		return;
727 	}
728 	mutex_enter(&EMLXS_PORT_LOCK);
729 	if (!(port->flag & EMLXS_PORT_BOUND)) {
730 		mutex_exit(&EMLXS_PORT_LOCK);
731 		return;
732 	}
733 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
734 	    "emlxs_fct_unbind_port: port=%d", port->vpi);
735 
736 	/* Destroy & flush all port nodes, if they exist */
737 	if (port->node_count) {
738 		(void) emlxs_mb_unreg_rpi(port, 0xffff, 0, 0, 0);
739 	}
740 	port->flag &= ~EMLXS_PORT_BOUND;
741 	hba->num_of_ports--;
742 	mutex_exit(&EMLXS_PORT_LOCK);
743 
744 	if (port->fct_port) {
745 		emlxs_fct_link_down(port);
746 		emlxs_fct_unsol_flush(port);
747 
748 #ifdef FCT_API_TRACE
749 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
750 		    "fct_deregister_local_port %p", port->fct_port);
751 #endif	/* FCT_API_TRACE */
752 		MODSYM(fct_deregister_local_port) (port->fct_port);
753 
754 		if (port->fct_port->port_fds) {
755 #ifdef FCT_API_TRACE
756 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
757 			    "fct_free:3 %p", port->fct_port->port_fds);
758 #endif	/* FCT_API_TRACE */
759 			MODSYM(fct_free) (port->fct_port->port_fds);
760 			port->fct_port->port_fds = NULL;
761 		}
762 #ifdef FCT_API_TRACE
763 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
764 		    "fct_free:4 %p", port->fct_port);
765 #endif	/* FCT_API_TRACE */
766 		MODSYM(fct_free) (port->fct_port);
767 		port->fct_port = NULL;
768 		port->fct_flags = 0;
769 	}
770 	if (port->port_provider) {
771 #ifdef FCT_API_TRACE
772 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
773 		    "stmf_deregister_port_provider:1 %p", port->port_provider);
774 #endif	/* FCT_API_TRACE */
775 		MODSYM(stmf_deregister_port_provider) (port->port_provider);
776 
777 #ifdef FCT_API_TRACE
778 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
779 		    "stmf_free:1 %p", port->port_provider);
780 #endif	/* FCT_API_TRACE */
781 		MODSYM(stmf_free) (port->port_provider);
782 		port->port_provider = NULL;
783 	}
784 	if (port->dmem_bucket) {
785 		emlxs_fct_dmem_fini(port);
786 	}
787 	(void) sprintf(node_name, "%d,%d:SFCT", hba->ddiinst, port->vpi);
788 	(void) ddi_remove_minor_node(hba->dip, node_name);
789 
790 	return;
791 
792 } /* emlxs_fct_unbind_port() */
793 
794 
795 extern void
796 emlxs_fct_bind_port(emlxs_port_t *port)
797 {
798 	emlxs_hba_t *hba = HBA;
799 	fct_local_port_t *fct_port;
800 	uint32_t flag = 0;
801 	emlxs_config_t *cfg = &CFG;
802 	fct_dbuf_store_t *fds;
803 	char node_name[32];
804 
805 	mutex_enter(&EMLXS_PORT_LOCK);
806 
807 	if (!hba->tgt_mode || !port->tgt_mode) {
808 		mutex_exit(&EMLXS_PORT_LOCK);
809 		return;
810 	}
811 	if (port->flag & EMLXS_PORT_BOUND) {
812 		mutex_exit(&EMLXS_PORT_LOCK);
813 		return;
814 	}
815 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
816 	    "emlxs_fct_bind_port: port=%d", port->vpi);
817 
818 	/* Perform generic port initialization */
819 	emlxs_port_init(port);
820 
821 	if (port->vpi == 0) {
822 		(void) sprintf(port->cfd_name, "%s%d", DRIVER_NAME,
823 		    hba->ddiinst);
824 	} else {
825 		(void) sprintf(port->cfd_name, "%s%d.%d", DRIVER_NAME,
826 		    hba->ddiinst, port->vpi);
827 	}
828 
829 	if (emlxs_fct_dmem_init(port) != FCT_SUCCESS) {
830 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
831 		    "emlxs_fct_bind_port: Unable to allocate fct memory.");
832 		goto failed;
833 	}
834 	flag |= 0x00000001;
835 
836 	port->port_provider = (stmf_port_provider_t *)
837 	    MODSYM(stmf_alloc) (STMF_STRUCT_PORT_PROVIDER, 0, 0);
838 #ifdef FCT_API_TRACE
839 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
840 	    "stmf_alloc port_provider %p", port->port_provider);
841 #endif	/* FCT_API_TRACE */
842 
843 	if (port->port_provider == NULL) {
844 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
845 		    "emlxs_fct_bind_port: Unable to allocate "
846 		    "fct port provider.");
847 		goto failed;
848 	}
849 	flag |= 0x00000002;
850 
851 	port->port_provider->pp_portif_rev = PORTIF_REV_1;
852 	port->port_provider->pp_name = port->cfd_name;
853 	port->port_provider->pp_provider_private = port;
854 
855 #ifdef FCT_API_TRACE
856 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
857 	    "stmf_register_port_provider %p", port->port_provider);
858 #endif	/* FCT_API_TRACE */
859 	/* register port provider with framework */
860 	if (MODSYM(stmf_register_port_provider) (port->port_provider)
861 	    != STMF_SUCCESS) {
862 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
863 		    "emlxs_fct_bind_port: Unable to register "
864 		    "fct port provider.");
865 		goto failed;
866 	}
867 	flag |= 0x00000004;
868 
869 	port->fct_port = (fct_local_port_t *)
870 	    MODSYM(fct_alloc) (FCT_STRUCT_LOCAL_PORT, 0, 0);
871 #ifdef FCT_API_TRACE
872 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
873 	    "fct_alloc fct_port %p", port->fct_port);
874 #endif	/* FCT_API_TRACE */
875 
876 	if (port->fct_port == NULL) {
877 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
878 		    "emlxs_fct_bind_port: Unable to allocate fct port.");
879 		goto failed;
880 	}
881 	flag |= 0x00000008;
882 
883 	port->fct_port->port_fds = (fct_dbuf_store_t *)
884 	    MODSYM(fct_alloc) (FCT_STRUCT_DBUF_STORE, 0, 0);
885 #ifdef FCT_API_TRACE
886 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
887 	    "fct_alloc port_fds %p", port->fct_port->port_fds);
888 #endif	/* FCT_API_TRACE */
889 
890 	if (port->fct_port->port_fds == NULL) {
891 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
892 		    "emlxs_fct_bind_port: Unable to allocate dbuf store.");
893 		goto failed;
894 	}
895 	flag |= 0x00000010;
896 
897 	(void) sprintf(node_name, "%d,%d:SFCT", hba->ddiinst, port->vpi);
898 	if (ddi_create_minor_node(hba->dip, node_name, S_IFCHR,
899 	    hba->ddiinst, NULL, 0) == DDI_FAILURE) {
900 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
901 		    "Unable to create SFCT device node.");
902 		goto failed;
903 	}
904 	flag |= 0x00000020;
905 
906 	/* Intialize */
907 	fct_port = port->fct_port;
908 	fct_port->port_fca_private = port;
909 	fct_port->port_fca_abort_timeout = 30 * 1000;	/* 30 seconds */
910 
911 	bcopy((uint8_t *)&port->wwpn, (uint8_t *)fct_port->port_pwwn, 8);
912 	bcopy((uint8_t *)&port->wwnn, (uint8_t *)fct_port->port_nwwn, 8);
913 
914 	fct_port->port_sym_node_name = port->snn;
915 	fct_port->port_sym_port_name = port->spn;
916 	fct_port->port_hard_address = cfg[CFG_ASSIGN_ALPA].current;
917 	fct_port->port_default_alias = port->cfd_name;
918 	fct_port->port_pp = port->port_provider;
919 	fct_port->port_max_logins = hba->max_nodes;
920 
921 	if ((port->fct_queue_depth) && (port->fct_queue_depth
922 	    < hba->io_throttle)) {
923 		fct_port->port_max_xchges = port->fct_queue_depth;
924 	} else {
925 		fct_port->port_max_xchges = hba->io_throttle;
926 	}
927 
928 	fct_port->port_fca_fcp_cmd_size = sizeof (emlxs_buf_t);
929 	fct_port->port_fca_rp_private_size = sizeof (uintptr_t);
930 	fct_port->port_fca_sol_els_private_size = sizeof (emlxs_buf_t);
931 	fct_port->port_fca_sol_ct_private_size = sizeof (emlxs_buf_t);
932 	fct_port->port_get_link_info = emlxs_fct_get_link_info;
933 	fct_port->port_register_remote_port = emlxs_fct_register_remote_port;
934 	fct_port->port_deregister_remote_port =
935 	    emlxs_fct_deregister_remote_port;
936 	fct_port->port_send_cmd = emlxs_fct_send_cmd;
937 	fct_port->port_xfer_scsi_data = emlxs_fct_send_fcp_data;
938 	fct_port->port_send_cmd_response = emlxs_fct_send_cmd_rsp;
939 	fct_port->port_abort_cmd = emlxs_fct_abort;
940 	fct_port->port_ctl = emlxs_fct_ctl;
941 	fct_port->port_flogi_xchg = emlxs_flogi_xchg;
942 	fct_port->port_populate_hba_details = emlxs_populate_hba_details;
943 
944 	fds = port->fct_port->port_fds;
945 	fds->fds_fca_private = port;
946 	fds->fds_alloc_data_buf = emlxs_fct_dbuf_alloc;
947 	fds->fds_free_data_buf = emlxs_fct_dbuf_free;
948 
949 #ifdef FCT_API_TRACE
950 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
951 	    "fct_register_local_port %p", fct_port);
952 #endif	/* FCT_API_TRACE */
953 	/* register this local port with the fct module */
954 	if (MODSYM(fct_register_local_port) (fct_port) != FCT_SUCCESS) {
955 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
956 		    "emlxs_fct_bind_port: Unable to register fct port.");
957 		goto failed;
958 	}
959 	/* Set the bound flag */
960 	port->flag |= EMLXS_PORT_BOUND;
961 	hba->num_of_ports++;
962 
963 	mutex_exit(&EMLXS_PORT_LOCK);
964 
965 	return;
966 
967 failed:
968 
969 	if (flag & 0x20) {
970 		(void) ddi_remove_minor_node(hba->dip, node_name);
971 	}
972 	if (flag & 0x10) {
973 #ifdef FCT_API_TRACE
974 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
975 		    "fct_free:5 %p", port->fct_port->port_fds);
976 #endif	/* FCT_API_TRACE */
977 		MODSYM(fct_free) (port->fct_port->port_fds);
978 		port->fct_port->port_fds = NULL;
979 	}
980 	if (flag & 0x8) {
981 #ifdef FCT_API_TRACE
982 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
983 		    "fct_free:6 %p", port->fct_port);
984 #endif	/* FCT_API_TRACE */
985 		MODSYM(fct_free) (port->fct_port);
986 		port->fct_port = NULL;
987 		port->fct_flags = 0;
988 	}
989 	if (flag & 0x4) {
990 #ifdef FCT_API_TRACE
991 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
992 		    "stmf_deregister_port_provider:2 %p", port->port_provider);
993 #endif	/* FCT_API_TRACE */
994 		MODSYM(stmf_deregister_port_provider) (port->port_provider);
995 	}
996 	if (flag & 0x2) {
997 #ifdef FCT_API_TRACE
998 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
999 		    "stmf_free:2 %p", port->port_provider);
1000 #endif	/* FCT_API_TRACE */
1001 		MODSYM(stmf_free) (port->port_provider);
1002 		port->port_provider = NULL;
1003 	}
1004 	if (flag & 0x1) {
1005 		emlxs_fct_dmem_fini(port);
1006 	}
1007 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1008 	    "Target mode disabled.");
1009 
1010 	mutex_exit(&EMLXS_PORT_LOCK);
1011 
1012 	return;
1013 
1014 } /* emlxs_fct_bind_port() */
1015 
1016 
1017 static void
1018 emlxs_populate_hba_details(fct_local_port_t *fct_port,
1019     fct_port_attrs_t *port_attrs)
1020 {
1021 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1022 	emlxs_hba_t *hba = HBA;
1023 	emlxs_vpd_t *vpd = &VPD;
1024 
1025 	(void) strcpy(port_attrs->manufacturer, "Emulex");
1026 	(void) strcpy(port_attrs->serial_number, vpd->serial_num);
1027 	(void) strcpy(port_attrs->model, hba->model_info.model);
1028 	(void) strcpy(port_attrs->model_description,
1029 	    hba->model_info.model_desc);
1030 	(void) sprintf(port_attrs->hardware_version, "%x", vpd->biuRev);
1031 	(void) sprintf(port_attrs->driver_version, "%s (%s)", emlxs_version,
1032 	    emlxs_revision);
1033 	(void) strcpy(port_attrs->option_rom_version, vpd->fcode_version);
1034 	(void) sprintf(port_attrs->firmware_version, "%s (%s)", vpd->fw_version,
1035 	    vpd->fw_label);
1036 	(void) strcpy(port_attrs->driver_name, DRIVER_NAME);
1037 	port_attrs->vendor_specific_id =
1038 	    ((hba->model_info.device_id << 16) | PCI_VENDOR_ID_EMULEX);
1039 	port_attrs->supported_cos = SWAP_DATA32(FC_NS_CLASS3);
1040 
1041 	port_attrs->max_frame_size = FF_FRAME_SIZE;
1042 
1043 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
1044 		port_attrs->supported_speed |= FC_HBA_PORTSPEED_10GBIT;
1045 	}
1046 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
1047 		port_attrs->supported_speed |= FC_HBA_PORTSPEED_8GBIT;
1048 	}
1049 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
1050 		port_attrs->supported_speed |= FC_HBA_PORTSPEED_4GBIT;
1051 	}
1052 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
1053 		port_attrs->supported_speed |= FC_HBA_PORTSPEED_2GBIT;
1054 	}
1055 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
1056 		port_attrs->supported_speed |= FC_HBA_PORTSPEED_1GBIT;
1057 	}
1058 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1059 	    "Port attr: manufacturer       = %s", port_attrs->manufacturer);
1060 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1061 	    "Port attr: serial_num         = %s", port_attrs->serial_number);
1062 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1063 	    "Port attr: model              = %s", port_attrs->model);
1064 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1065 	    "Port attr: model_description  = %s",
1066 	    port_attrs->model_description);
1067 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1068 	    "Port attr: hardware_version   = %s", port_attrs->hardware_version);
1069 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1070 	    "Port attr: driver_version     = %s", port_attrs->driver_version);
1071 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1072 	    "Port attr: option_rom_version = %s",
1073 	    port_attrs->option_rom_version);
1074 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1075 	    "Port attr: firmware_version   = %s", port_attrs->firmware_version);
1076 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1077 	    "Port attr: driver_name        = %s", port_attrs->driver_name);
1078 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1079 	    "Port attr: vendor_specific_id = 0x%x",
1080 	    port_attrs->vendor_specific_id);
1081 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1082 	    "Port attr: supported_cos      = 0x%x", port_attrs->supported_cos);
1083 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1084 	    "Port attr: supported_speed    = 0x%x",
1085 	    port_attrs->supported_speed);
1086 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1087 	    "Port attr: max_frame_size     = 0x%x", port_attrs->max_frame_size);
1088 
1089 	return;
1090 
1091 } /* emlxs_populate_hba_details() */
1092 
1093 
1094 /* ARGSUSED */
1095 static void
1096 emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg)
1097 {
1098 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1099 	emlxs_hba_t *hba = HBA;
1100 	stmf_change_status_t st;
1101 
1102 	st.st_completion_status = FCT_SUCCESS;
1103 	st.st_additional_info = NULL;
1104 
1105 	switch (cmd) {
1106 	case FCT_CMD_PORT_ONLINE:
1107 		/* If the HBA is offline, we cannot bring the tgtport online */
1108 		if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) {
1109 			st.st_completion_status = FCT_FAILURE;
1110 			MODSYM(fct_ctl) (fct_port->port_lport,
1111 			    FCT_CMD_PORT_ONLINE_COMPLETE, &st);
1112 			break;
1113 		}
1114 		if (port->fct_flags & FCT_STATE_PORT_ONLINE) {
1115 			st.st_completion_status = STMF_ALREADY;
1116 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1117 			    "STATE: ONLINE chk");
1118 		} else {
1119 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1120 			    "STATE: OFFLINE --> ONLINE");
1121 
1122 			port->fct_flags |= FCT_STATE_NOT_ACKED;
1123 			port->fct_flags |= FCT_STATE_PORT_ONLINE;
1124 
1125 			if (hba->state <= FC_LINK_DOWN) {
1126 				/* Try to bring the link up */
1127 				(void) emlxs_reset_link(hba, 1);
1128 			}
1129 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1130 			    "STATE: ONLINE");
1131 		}
1132 
1133 		MODSYM(fct_ctl) (fct_port->port_lport,
1134 		    FCT_CMD_PORT_ONLINE_COMPLETE, &st);
1135 		break;
1136 
1137 	case FCT_CMD_PORT_OFFLINE:
1138 		if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
1139 			st.st_completion_status = STMF_ALREADY;
1140 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1141 			    "STATE: OFFLINE chk");
1142 
1143 		} else {
1144 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1145 			    "STATE: ONLINE --> OFFLINE");
1146 
1147 			/* Take link down and flush */
1148 			emlxs_fct_link_down(port);
1149 			emlxs_fct_unsol_flush(port);
1150 
1151 			/* Declare this port offline now */
1152 			port->fct_flags |= FCT_STATE_NOT_ACKED;
1153 			port->fct_flags &= ~FCT_STATE_PORT_ONLINE;
1154 
1155 			/* Take link down and hold it down */
1156 			(void) emlxs_reset_link(hba, 0);
1157 
1158 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1159 			    "STATE: OFFLINE");
1160 		}
1161 
1162 		MODSYM(fct_ctl) (fct_port->port_lport,
1163 		    FCT_CMD_PORT_OFFLINE_COMPLETE, &st);
1164 
1165 		break;
1166 
1167 	case FCT_ACK_PORT_OFFLINE_COMPLETE:
1168 		port->fct_flags &= ~FCT_STATE_NOT_ACKED;
1169 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1170 		    "STATE: OFFLINE ack");
1171 		break;
1172 
1173 	case FCT_ACK_PORT_ONLINE_COMPLETE:
1174 		port->fct_flags &= ~FCT_STATE_NOT_ACKED;
1175 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1176 		    "STATE: ONLINE ack");
1177 		break;
1178 
1179 	}
1180 
1181 	return;
1182 
1183 } /* emlxs_fct_ctl() */
1184 
1185 extern int
1186 emlxs_fct_port_shutdown(emlxs_port_t *port)
1187 {
1188 	fct_local_port_t *fct_port;
1189 	int i;
1190 
1191 	fct_port = port->fct_port;
1192 	if (!fct_port) {
1193 		return (0);
1194 	}
1195 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1196 	    "fct_port_shutdown");
1197 	MODSYM(fct_port_shutdown) (fct_port, STMF_RFLAG_STAY_OFFLINED,
1198 	    "emlxs shutdown");
1199 
1200 	i = 0;
1201 	while (port->fct_flags & FCT_STATE_NOT_ACKED) {
1202 		i++;
1203 		if (i > 300) {	/* 30 seconds */
1204 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1205 			    "fct_port_shutdown failed to ACK");
1206 			break;
1207 		}
1208 		delay(drv_usectohz(100000));	/* 100 msec */
1209 	}
1210 	return (1);
1211 }
1212 
1213 
1214 extern int
1215 emlxs_fct_port_initialize(emlxs_port_t *port)
1216 {
1217 	fct_local_port_t *fct_port;
1218 	int i;
1219 
1220 	fct_port = port->fct_port;
1221 	if (!fct_port) {
1222 		return (0);
1223 	}
1224 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1225 	    "fct_port_initialize");
1226 	MODSYM(fct_port_initialize) (fct_port, STMF_RFLAG_STAY_OFFLINED,
1227 	    "emlxs initialize");
1228 
1229 	i = 0;
1230 	while (port->fct_flags & FCT_STATE_NOT_ACKED) {
1231 		i++;
1232 		if (i > 300) {	/* 30 seconds */
1233 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1234 			    "fct_port_initialize failed to ACK");
1235 			break;
1236 		}
1237 		delay(drv_usectohz(100000));	/* 100 msec */
1238 	}
1239 	return (1);
1240 }
1241 
1242 static fct_status_t
1243 emlxs_fct_send_cmd(fct_cmd_t *fct_cmd)
1244 {
1245 	emlxs_port_t *port;
1246 
1247 	port = (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
1248 
1249 #ifdef FCT_API_TRACE
1250 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1251 	    "emlxs_fct_send_cmd %p: x%x", fct_cmd, fct_cmd->cmd_type);
1252 #endif	/* FCT_API_TRACE */
1253 
1254 	switch (fct_cmd->cmd_type) {
1255 	case FCT_CMD_SOL_ELS:
1256 
1257 		return (emlxs_fct_send_els_cmd(fct_cmd));
1258 
1259 	case FCT_CMD_SOL_CT:
1260 
1261 		return (emlxs_fct_send_ct_cmd(fct_cmd));
1262 
1263 	default:
1264 
1265 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1266 		    "emlxs_fct_send_cmd: Invalid cmd type found. type=%x",
1267 		    fct_cmd->cmd_type);
1268 
1269 		return (FCT_FAILURE);
1270 	}
1271 
1272 } /* emlxs_fct_send_cmd() */
1273 
1274 
1275 
1276 static fct_status_t
1277 emlxs_fct_send_cmd_rsp(fct_cmd_t *fct_cmd, uint32_t ioflags)
1278 {
1279 	emlxs_port_t *port;
1280 
1281 	port = (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
1282 
1283 #ifdef FCT_API_TRACE
1284 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1285 	    "emlxs_fct_send_cmd_rsp %p: x%x", fct_cmd, fct_cmd->cmd_type);
1286 #endif	/* FCT_API_TRACE */
1287 
1288 	switch (fct_cmd->cmd_type) {
1289 	case FCT_CMD_FCP_XCHG:
1290 
1291 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1292 			goto failure;
1293 		}
1294 		return (emlxs_fct_send_fcp_status(fct_cmd));
1295 
1296 	case FCT_CMD_RCVD_ELS:
1297 
1298 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1299 			goto failure;
1300 		}
1301 		return (emlxs_fct_send_els_rsp(fct_cmd));
1302 
1303 	case FCT_CMD_RCVD_ABTS:
1304 
1305 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1306 			fct_cmd->cmd_handle = 0;
1307 		}
1308 		return (emlxs_fct_send_abts_rsp(fct_cmd));
1309 
1310 	default:
1311 
1312 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1313 			fct_cmd->cmd_handle = 0;
1314 		}
1315 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1316 		    "emlxs_fct_send_cmd_rsp: Invalid cmd type found. type=%x",
1317 		    fct_cmd->cmd_type);
1318 
1319 		return (FCT_FAILURE);
1320 	}
1321 
1322 failure:
1323 
1324 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1325 	    "emlxs_fct_send_cmd_rsp: Unable to handle FCT_IOF_FORCE_FCA_DONE. "
1326 	    "type=%x", fct_cmd->cmd_type);
1327 
1328 	return (FCT_FAILURE);
1329 
1330 } /* emlxs_fct_send_cmd_rsp() */
1331 
1332 
1333 
1334 static fct_status_t
1335 emlxs_flogi_xchg(struct fct_local_port *fct_port, struct fct_flogi_xchg *fx)
1336 {
1337 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1338 	emlxs_hba_t *hba = HBA;
1339 	uint32_t size;
1340 	fc_packet_t *pkt;
1341 	ELS_PKT *els;
1342 
1343 #ifdef FCT_API_TRACE
1344 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1345 	    "emlxs_flogi_xchg: Sending FLOGI: %p", fct_port);
1346 #else
1347 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1348 	    "emlxs_flogi_xchg: Sending FLOGI.");
1349 #endif	/* FCT_API_TRACE */
1350 
1351 	if (hba->state <= FC_LINK_DOWN) {
1352 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1353 		    "emlxs_flogi_xchg: FLOGI failed. Link down.");
1354 		return (FCT_FAILURE);
1355 	}
1356 	size = sizeof (SERV_PARM) + 4;
1357 
1358 	if (!(pkt = emlxs_pkt_alloc(port, size, size, 0, KM_NOSLEEP))) {
1359 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1360 		    "emlxs_flogi_xchg: FLOGI failed. Unable allocate packet.");
1361 		return (FCT_FAILURE);
1362 	}
1363 	/* Make this a polled IO */
1364 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
1365 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
1366 	pkt->pkt_comp = NULL;
1367 
1368 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
1369 	pkt->pkt_timeout = fx->fx_sec_timeout;
1370 
1371 	/* Build the fc header */
1372 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(fx->fx_did);
1373 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
1374 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(fx->fx_sid);
1375 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
1376 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE;
1377 	pkt->pkt_cmd_fhdr.seq_id = 0;
1378 	pkt->pkt_cmd_fhdr.df_ctl = 0;
1379 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
1380 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
1381 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
1382 	pkt->pkt_cmd_fhdr.ro = 0;
1383 
1384 	/* Build the command */
1385 	/*
1386 	 * Service paramters will be added automatically later by the driver
1387 	 * (See emlxs_send_els())
1388 	 */
1389 	els = (ELS_PKT *)pkt->pkt_cmd;
1390 	els->elsCode = 0x04;	/* FLOGI */
1391 
1392 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
1393 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1394 		    "emlxs_flogi_xchg: FLOGI failed. Unable to send packet.");
1395 
1396 		emlxs_pkt_free(pkt);
1397 		return (FCT_FAILURE);
1398 	}
1399 	if ((pkt->pkt_state != FC_PKT_SUCCESS) &&
1400 	    (pkt->pkt_state != FC_PKT_LS_RJT)) {
1401 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
1402 			return (FCT_TIMEOUT);
1403 		} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
1404 		    (pkt->pkt_reason == FC_REASON_FCAL_OPN_FAIL)) {
1405 			return (FCT_NOT_FOUND);
1406 		}
1407 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1408 		    "emlxs_flogi_xchg: FLOGI failed. state=%x reason=%x",
1409 		    pkt->pkt_state, pkt->pkt_reason);
1410 
1411 		return (FCT_FAILURE);
1412 	}
1413 	if (pkt->pkt_state == FC_PKT_LS_RJT) {
1414 		fx->fx_op = ELS_OP_LSRJT;
1415 		fx->fx_rjt_reason = pkt->pkt_reason;
1416 		fx->fx_rjt_expl = pkt->pkt_expln;
1417 	} else {	/* FC_PKT_SUCCESS */
1418 		fx->fx_op = ELS_OP_ACC;
1419 		fx->fx_sid = Fabric_DID;
1420 		fx->fx_did = port->did;
1421 
1422 		els = (ELS_PKT *) pkt->pkt_resp;
1423 		bcopy((caddr_t)&els->un.logi.nodeName,
1424 		    (caddr_t)fx->fx_nwwn, 8);
1425 		bcopy((caddr_t)&els->un.logi.portName,
1426 		    (caddr_t)fx->fx_pwwn, 8);
1427 		fx->fx_fport = els->un.logi.cmn.fPort;
1428 	}
1429 
1430 	return (FCT_SUCCESS);
1431 
1432 } /* emlxs_flogi_xchg() */
1433 
1434 
1435 
1436 /* This is called right after we report that link has come online */
1437 static fct_status_t
1438 emlxs_fct_get_link_info(fct_local_port_t *fct_port, fct_link_info_t *link)
1439 {
1440 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1441 	emlxs_hba_t *hba = HBA;
1442 
1443 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1444 	    "emlxs_fct_get_link_info %p", fct_port);
1445 
1446 	mutex_enter(&EMLXS_PORT_LOCK);
1447 
1448 	if (!(port->fct_flags & FCT_STATE_LINK_UP) ||
1449 	    (hba->state < FC_LINK_UP) ||
1450 	    (hba->flag & FC_LOOPBACK_MODE)) {
1451 		link->port_topology = PORT_TOPOLOGY_UNKNOWN;
1452 		link->port_speed = PORT_SPEED_UNKNOWN;
1453 		link->portid = 0;
1454 
1455 		mutex_exit(&EMLXS_PORT_LOCK);
1456 
1457 		return (FCT_SUCCESS);
1458 	}
1459 	if (hba->topology == TOPOLOGY_LOOP) {
1460 		link->port_topology = PORT_TOPOLOGY_PRIVATE_LOOP;
1461 	} else {
1462 		link->port_topology = PORT_TOPOLOGY_PT_TO_PT;
1463 	}
1464 
1465 	switch (hba->linkspeed) {
1466 	case LA_1GHZ_LINK:
1467 		link->port_speed = PORT_SPEED_1G;
1468 		break;
1469 	case LA_2GHZ_LINK:
1470 		link->port_speed = PORT_SPEED_2G;
1471 		break;
1472 	case LA_4GHZ_LINK:
1473 		link->port_speed = PORT_SPEED_4G;
1474 		break;
1475 	case LA_8GHZ_LINK:
1476 		link->port_speed = PORT_SPEED_8G;
1477 		break;
1478 	case LA_10GHZ_LINK:
1479 		link->port_speed = PORT_SPEED_10G;
1480 		break;
1481 	default:
1482 		link->port_speed = PORT_SPEED_UNKNOWN;
1483 		break;
1484 	}
1485 
1486 	link->portid = port->did;
1487 	link->port_no_fct_flogi = 0;
1488 	link->port_fca_flogi_done = 0;
1489 	link->port_fct_flogi_done = 0;
1490 
1491 
1492 	mutex_exit(&EMLXS_PORT_LOCK);
1493 
1494 	return (FCT_SUCCESS);
1495 
1496 } /* emlxs_fct_get_link_info() */
1497 
1498 
1499 
1500 static fct_status_t
1501 emlxs_fct_register_remote_port(fct_local_port_t *fct_port,
1502     fct_remote_port_t *remote_port, fct_cmd_t *fct_cmd)
1503 {
1504 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1505 	emlxs_hba_t *hba = HBA;
1506 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
1507 	clock_t timeout;
1508 	int32_t pkt_ret;
1509 	fct_els_t *els;
1510 	SERV_PARM *sp;
1511 	emlxs_node_t *ndlp;
1512 	SERV_PARM sparam;
1513 	uint32_t *iptr;
1514 
1515 #ifdef FCT_API_TRACE
1516 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1517 	    "emlxs_fct_register_remote_port %p", fct_port);
1518 #endif	/* FCT_API_TRACE */
1519 
1520 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
1521 		(void) emlxs_fct_cmd_init(port, fct_cmd);
1522 		/* mutex_enter(&cmd_sbp->mtx); */
1523 
1524 		cmd_sbp->ring = &hba->ring[FC_ELS_RING];
1525 		cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD;
1526 		cmd_sbp->fct_state = EMLXS_FCT_REQ_CREATED;
1527 	} else {
1528 		mutex_enter(&cmd_sbp->mtx);
1529 	}
1530 
1531 	cmd_sbp->pkt_flags &= ~PACKET_RETURNED;
1532 
1533 	if (!cmd_sbp->node) {
1534 		cmd_sbp->node = emlxs_node_find_did(port, fct_cmd->cmd_rportid);
1535 	}
1536 	if (!cmd_sbp->node) {
1537 		els = (fct_els_t *)fct_cmd->cmd_specific;
1538 
1539 		/* Check for unsolicited PLOGI */
1540 		if (cmd_sbp->fct_state == EMLXS_FCT_CMD_RECEIVED) {
1541 			sp = (SERV_PARM *)
1542 			    ((caddr_t)els->els_req_payload + sizeof (uint32_t));
1543 		} else {	/* Solicited PLOGI */
1544 			sp = &sparam;
1545 			bcopy((caddr_t)&port->sparam, (caddr_t)sp,
1546 			    sizeof (SERV_PARM));
1547 
1548 			/* Create temporary WWN's from fct_cmd address */
1549 			/*
1550 			 * This simply allows us to get an RPI from the
1551 			 * adapter until we get real service params
1552 			 */
1553 			/*
1554 			 * The PLOGI ACC reply will trigger a REG_LOGIN
1555 			 * update later
1556 			 */
1557 			iptr = (uint32_t *)&sp->portName;
1558 			iptr[0] =
1559 			    (uint32_t)putPaddrHigh((unsigned long)fct_cmd);
1560 			iptr[1] =
1561 			    (uint32_t)putPaddrLow((unsigned long)fct_cmd);
1562 			iptr = (uint32_t *)&sp->nodeName;
1563 			iptr[0] =
1564 			    (uint32_t)putPaddrHigh((unsigned long)fct_cmd);
1565 			iptr[1] =
1566 			    (uint32_t)putPaddrLow((unsigned long)fct_cmd);
1567 		}
1568 
1569 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1570 		    "emlxs_fct_register_remote_port: Registering did=%x. "
1571 		    "(%x,%p)", fct_cmd->cmd_rportid, cmd_sbp->fct_state,
1572 		    fct_cmd);
1573 
1574 		cmd_sbp->fct_state = EMLXS_FCT_REG_PENDING;
1575 
1576 		/* Create a new node */
1577 		if (emlxs_mb_reg_did(port, fct_cmd->cmd_rportid, sp, cmd_sbp,
1578 		    NULL, NULL) != 0) {
1579 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
1580 			    "emlxs_fct_register_remote_port: Reg login failed. "
1581 			    "did=%x", fct_cmd->cmd_rportid);
1582 			goto done;
1583 		}
1584 		mutex_exit(&cmd_sbp->mtx);
1585 
1586 		/* Wait for completion */
1587 		mutex_enter(&EMLXS_PKT_LOCK);
1588 		timeout = emlxs_timeout(hba, 30);
1589 		pkt_ret = 0;
1590 		while ((pkt_ret != -1) &&
1591 		    (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING)) {
1592 			pkt_ret = cv_timedwait(&EMLXS_PKT_CV,
1593 			    &EMLXS_PKT_LOCK, timeout);
1594 		}
1595 		mutex_exit(&EMLXS_PKT_LOCK);
1596 
1597 		mutex_enter(&cmd_sbp->mtx);
1598 	}
1599 done:
1600 
1601 	ndlp = (emlxs_node_t *)cmd_sbp->node;
1602 
1603 	if (ndlp) {
1604 		*((emlxs_node_t **)remote_port->rp_fca_private) = cmd_sbp->node;
1605 		remote_port->rp_handle = ndlp->nlp_Rpi;
1606 
1607 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1608 		    "emlxs_fct_register_remote_port: did=%x hdl=%x",
1609 		    fct_cmd->cmd_rportid, remote_port->rp_handle);
1610 
1611 		remote_port->rp_handle = ndlp->nlp_Rpi;
1612 
1613 		cmd_sbp->pkt_flags |= PACKET_RETURNED;
1614 		mutex_exit(&cmd_sbp->mtx);
1615 
1616 		TGTPORTSTAT.FctPortRegister++;
1617 		return (FCT_SUCCESS);
1618 	} else {
1619 		*((emlxs_node_t **)remote_port->rp_fca_private) = NULL;
1620 
1621 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1622 		    "emlxs_fct_register_remote_port: failed. did=%x hdl=%x",
1623 		    fct_cmd->cmd_rportid, remote_port->rp_handle);
1624 
1625 		remote_port->rp_handle = FCT_HANDLE_NONE;
1626 
1627 		cmd_sbp->pkt_flags |= PACKET_RETURNED;
1628 		cmd_sbp->fct_state = EMLXS_FCT_REQ_CREATED;
1629 
1630 		mutex_exit(&cmd_sbp->mtx);
1631 
1632 		TGTPORTSTAT.FctFailedPortRegister++;
1633 		return (FCT_FAILURE);
1634 	}
1635 
1636 
1637 } /* emlxs_fct_register_remote_port() */
1638 
1639 
1640 static fct_status_t
1641 emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port,
1642     fct_remote_port_t *remote_port)
1643 {
1644 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1645 
1646 #ifdef FCT_API_TRACE
1647 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1648 	    "emlxs_fct_deregister_remote_port: did=%x hdl=%x",
1649 	    remote_port->rp_id, remote_port->rp_handle);
1650 #else
1651 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1652 	    "emlxs_fct_deregister_remote_port: did=%x hdl=%x",
1653 	    remote_port->rp_id, remote_port->rp_handle);
1654 #endif	/* FCT_API_TRACE */
1655 
1656 	*((emlxs_node_t **)remote_port->rp_fca_private) = NULL;
1657 	(void) emlxs_mb_unreg_did(port, remote_port->rp_id, NULL, NULL, NULL);
1658 
1659 	TGTPORTSTAT.FctPortDeregister++;
1660 	return (FCT_SUCCESS);
1661 
1662 } /* emlxs_fct_deregister_remote_port() */
1663 
1664 
1665 /* ARGSUSED */
1666 extern int
1667 emlxs_fct_handle_unsol_req(emlxs_port_t *port, RING *rp, IOCBQ *iocbq,
1668     MATCHMAP *mp, uint32_t size)
1669 {
1670 	IOCB *iocb;
1671 	fct_cmd_t *fct_cmd;
1672 	emlxs_buf_t *cmd_sbp;
1673 	emlxs_fcp_cmd_t *fcp_cmd;
1674 	emlxs_node_t *ndlp;
1675 	uint32_t cnt;
1676 	uint32_t tm;
1677 	scsi_task_t *fct_task;
1678 	uint8_t lun[8];
1679 	uint32_t sid = 0;
1680 
1681 	iocb = &iocbq->iocb;
1682 	ndlp = emlxs_node_find_rpi(port, iocb->ulpIoTag);
1683 	if (!ndlp) {
1684 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1685 		    "FCP rcvd: Unknown RPI. rpi=%x rxid=%x. Dropping...",
1686 		    iocb->ulpIoTag, iocb->ulpContext);
1687 
1688 		goto dropped;
1689 	}
1690 	sid = ndlp->nlp_DID;
1691 
1692 	fcp_cmd = (emlxs_fcp_cmd_t *)mp->virt;
1693 
1694 	if (!port->fct_port) {
1695 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1696 		    "FCP rcvd: Target unbound. rpi=%x rxid=%x. Dropping...",
1697 		    iocb->ulpIoTag, iocb->ulpContext);
1698 
1699 		emlxs_send_logo(port, sid);
1700 
1701 		goto dropped;
1702 	}
1703 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
1704 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1705 		    "FCP rcvd: Target offline. rpi=%x rxid=%x. Dropping...",
1706 		    iocb->ulpIoTag, iocb->ulpContext);
1707 
1708 		emlxs_send_logo(port, sid);
1709 
1710 		goto dropped;
1711 	}
1712 	/* Get lun id */
1713 	bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8);
1714 
1715 	if (TGTPORTSTAT.FctOutstandingIO >= port->fct_port->port_max_xchges) {
1716 		TGTPORTSTAT.FctOverQDepth++;
1717 	}
1718 	fct_cmd = MODSYM(fct_scsi_task_alloc)
1719 	    (port->fct_port, iocb->ulpIoTag, sid, lun, 16, 0);
1720 #ifdef FCT_API_TRACE
1721 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1722 	    "fct_scsi_task_alloc %p: FCP rcvd: cmd=%x sid=%x rxid=%x "
1723 	    "lun=%02x%02x dl=%d", fct_cmd, fcp_cmd->fcpCdb[0], sid,
1724 	    iocb->ulpContext, lun[0], lun[1], SWAP_DATA32(fcp_cmd->fcpDl));
1725 #endif	/* FCT_API_TRACE */
1726 
1727 	if (fct_cmd == NULL) {
1728 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1729 		    "FCP rcvd: sid=%x xid=%x. Unable to allocate scsi task. "
1730 		    "Returning QFULL.", sid, iocb->ulpContext);
1731 
1732 		(void) emlxs_fct_send_qfull_reply(port, ndlp, iocb->ulpContext,
1733 		    iocb->ulpClass, fcp_cmd);
1734 
1735 		goto dropped;
1736 	}
1737 	/* Initialize fct_cmd */
1738 	fct_cmd->cmd_oxid = 0xFFFF;
1739 	fct_cmd->cmd_rxid = iocb->ulpContext;
1740 	fct_cmd->cmd_rportid = sid;
1741 	fct_cmd->cmd_lportid = port->did;
1742 	fct_cmd->cmd_rp_handle = iocb->ulpIoTag;	/* RPI */
1743 	fct_cmd->cmd_port = port->fct_port;
1744 
1745 	/* Initialize cmd_sbp */
1746 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd);
1747 	/* mutex_enter(&cmd_sbp->mtx); */
1748 
1749 	cmd_sbp->ring = rp;
1750 	cmd_sbp->class = iocb->ulpClass;
1751 	cmd_sbp->lun = (lun[0] << 8) | lun[1];
1752 	cmd_sbp->fct_type = EMLXS_FCT_FCP_CMD;
1753 	cmd_sbp->fct_state = EMLXS_FCT_CMD_RECEIVED;
1754 	/*
1755 	 * bcopy((uint8_t*)iocb, (uint8_t*)&cmd_sbp->iocbq,
1756 	 * sizeof(emlxs_iocb_t));
1757 	 */
1758 
1759 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
1760 
1761 	/* Set task_flags */
1762 	switch (fcp_cmd->fcpCntl2) {
1763 	case 0:
1764 		fct_task->task_flags = TF_ATTR_SIMPLE_QUEUE;
1765 		break;
1766 
1767 	case 1:
1768 		fct_task->task_flags = TF_ATTR_HEAD_OF_QUEUE;
1769 		break;
1770 
1771 	case 2:
1772 		fct_task->task_flags = TF_ATTR_ORDERED_QUEUE;
1773 		break;
1774 
1775 	case 4:
1776 		fct_task->task_flags = TF_ATTR_ACA;
1777 		break;
1778 
1779 	case 5:
1780 		fct_task->task_flags = TF_ATTR_UNTAGGED;
1781 		break;
1782 	}
1783 
1784 	cnt = SWAP_DATA32(fcp_cmd->fcpDl);
1785 	switch (fcp_cmd->fcpCntl3) {
1786 	case 0:
1787 		TGTPORTSTAT.FctIOCmdCnt++;
1788 		break;
1789 	case 1:
1790 		emlxs_bump_wrioctr(port, cnt);
1791 		TGTPORTSTAT.FctWriteBytes += cnt;
1792 		fct_task->task_flags |= TF_WRITE_DATA;
1793 		break;
1794 
1795 	case 2:
1796 		emlxs_bump_rdioctr(port, cnt);
1797 		TGTPORTSTAT.FctReadBytes += cnt;
1798 		fct_task->task_flags |= TF_READ_DATA;
1799 		break;
1800 	}
1801 
1802 	fct_task->task_priority = 0;
1803 
1804 	/* task_mgmt_function */
1805 	tm = fcp_cmd->fcpCntl2;
1806 	if (tm) {
1807 		if (tm & BIT_1) {
1808 			fct_task->task_mgmt_function = TM_ABORT_TASK_SET;
1809 		} else if (tm & BIT_2) {
1810 			fct_task->task_mgmt_function = TM_CLEAR_TASK_SET;
1811 		} else if (tm & BIT_4) {
1812 			fct_task->task_mgmt_function = TM_LUN_RESET;
1813 		} else if (tm & BIT_5) {
1814 			fct_task->task_mgmt_function = TM_TARGET_COLD_RESET;
1815 		} else if (tm & BIT_6) {
1816 			fct_task->task_mgmt_function = TM_CLEAR_ACA;
1817 		} else {
1818 			fct_task->task_mgmt_function = TM_ABORT_TASK;
1819 		}
1820 	}
1821 	/* Parallel buffers support - future */
1822 	fct_task->task_max_nbufs = 1;
1823 
1824 	fct_task->task_additional_flags = 0;
1825 	fct_task->task_cur_nbufs = 0;
1826 	fct_task->task_csn_size = 8;
1827 	fct_task->task_cmd_seq_no = 0;
1828 	fct_task->task_expected_xfer_length = cnt;
1829 	bcopy((void *)&fcp_cmd->fcpCdb, fct_task->task_cdb, 16);
1830 
1831 	TGTPORTSTAT.FctCmdReceived++;
1832 
1833 	TGTPORTSTAT.FctOutstandingIO++;
1834 
1835 	cmd_sbp->pkt_flags |= PACKET_RETURNED;
1836 	mutex_exit(&cmd_sbp->mtx);
1837 
1838 	emlxs_fct_unsol_callback(port, fct_cmd);
1839 
1840 	return (0);
1841 
1842 dropped:
1843 
1844 	TGTPORTSTAT.FctRcvDropped++;
1845 	return (1);
1846 
1847 } /* emlxs_fct_handle_unsol_req() */
1848 
1849 
1850 /* ARGSUSED */
1851 static fct_status_t
1852 emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd, stmf_data_buf_t *dbuf,
1853     uint32_t ioflags)
1854 {
1855 	emlxs_port_t *port =
1856 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
1857 	emlxs_hba_t *hba = HBA;
1858 	emlxs_config_t *cfg = &CFG;
1859 	emlxs_buf_t *cmd_sbp;
1860 	scsi_task_t *fct_task;
1861 	uint32_t did;
1862 	IOCBQ *iocbq;
1863 	IOCB *iocb;
1864 	uint32_t timeout;
1865 	uint32_t iotag;
1866 	emlxs_node_t *ndlp;
1867 
1868 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
1869 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
1870 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
1871 	did = fct_cmd->cmd_rportid;
1872 
1873 	/* Initialize cmd_sbp */
1874 	mutex_enter(&cmd_sbp->mtx);
1875 
1876 	/*
1877 	 * This check is here because task_max_nbufs is set to 1. This
1878 	 * ensures we will only have 1 outstanding call to this routine.
1879 	 */
1880 	if (!(cmd_sbp->pkt_flags & PACKET_RETURNED)) {
1881 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
1882 		    "Adapter Busy. Processing IO. did=0x%x", did);
1883 		mutex_exit(&cmd_sbp->mtx);
1884 		return (FCT_BUSY);
1885 	}
1886 	cmd_sbp->pkt_flags &= ~PACKET_RETURNED;
1887 	cmd_sbp->node = ndlp;
1888 	cmd_sbp->fct_buf = dbuf;
1889 
1890 	iocbq = &cmd_sbp->iocbq;
1891 	iocb = &iocbq->iocb;
1892 
1893 	if (cfg[CFG_TIMEOUT_ENABLE].current) {
1894 		timeout = ((2 * hba->fc_ratov) < 60) ? 60 : (2 * hba->fc_ratov);
1895 	} else {
1896 		timeout = 0x80000000;
1897 	}
1898 
1899 #ifdef FCT_API_TRACE
1900 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1901 	    "emlxs_fct_send_fcp_data %p: flgs=%x ioflags=%x dl=%d,%d,%d",
1902 	    fct_cmd, dbuf->db_flags, ioflags, fct_task->task_cmd_xfer_length,
1903 	    fct_task->task_nbytes_transferred, dbuf->db_data_size);
1904 #endif	/* FCT_API_TRACE */
1905 
1906 	/* Get the iotag by registering the packet */
1907 	iotag = emlxs_register_pkt(cmd_sbp->ring, cmd_sbp);
1908 
1909 	if (!iotag) {
1910 		/* No more command slots available, retry later */
1911 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
1912 		    "Adapter Busy. Unable to allocate iotag. did=0x%x", did);
1913 
1914 		cmd_sbp->pkt_flags |= PACKET_RETURNED;
1915 		mutex_exit(&cmd_sbp->mtx);
1916 		return (FCT_BUSY);
1917 	}
1918 	if (emlxs_fct_bde_setup(port, cmd_sbp)) {
1919 		/* Unregister the packet */
1920 		(void) emlxs_unregister_pkt(cmd_sbp->ring, iotag, 0);
1921 
1922 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
1923 		    "Adapter Busy. Unable to setup buffer list. did=%x", did);
1924 
1925 		cmd_sbp->pkt_flags |= PACKET_RETURNED;
1926 		mutex_exit(&cmd_sbp->mtx);
1927 		return (FCT_BUSY);
1928 	}
1929 	/* Point of no return */
1930 	cmd_sbp->fct_type = EMLXS_FCT_FCP_DATA;
1931 	cmd_sbp->fct_state = EMLXS_FCT_DATA_PENDING;
1932 
1933 	if (dbuf->db_flags & DB_SEND_STATUS_GOOD) {
1934 		cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
1935 	}
1936 	cmd_sbp->ticks = hba->timer_tics + timeout +
1937 	    ((timeout > 0xff) ? 0 : 10);
1938 
1939 	/* Initalize iocbq */
1940 	iocbq->port = (void *)port;
1941 	iocbq->node = (void *)ndlp;
1942 	iocbq->ring = (void *)cmd_sbp->ring;
1943 
1944 	/* Initalize iocb */
1945 	iocb->ulpContext = (uint16_t)fct_cmd->cmd_rxid;
1946 	iocb->ulpIoTag = iotag;
1947 	iocb->ulpRsvdByte = ((timeout > 0xff) ? 0 : timeout);
1948 	iocb->ulpOwner = OWN_CHIP;
1949 	iocb->ulpClass = cmd_sbp->class;
1950 
1951 	iocb->ulpPU = 1;	/* Wd4 is relative offset */
1952 	iocb->un.fcpt64.fcpt_Offset = dbuf->db_relative_offset;
1953 
1954 	if (fct_task->task_flags & TF_WRITE_DATA) {
1955 		iocb->ulpCommand = CMD_FCP_TRECEIVE64_CX;
1956 	} else {	/* TF_READ_DATA */
1957 		iocb->ulpCommand = CMD_FCP_TSEND64_CX;
1958 	}
1959 
1960 #if 0
1961 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1962 	    "FCT reply: icmd=%x did=%x oxid=%x rxid=%x sbp=%p",
1963 	    iocb->ulpCommand, did, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid,
1964 	    cmd_sbp);
1965 #endif
1966 
1967 	if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
1968 		emlxs_fct_dbuf_dma_sync(dbuf, DDI_DMA_SYNC_FORDEV);
1969 	}
1970 	mutex_exit(&cmd_sbp->mtx);
1971 	emlxs_issue_iocb_cmd(hba, cmd_sbp->ring, iocbq);
1972 
1973 	return (FCT_SUCCESS);
1974 
1975 } /* emlxs_fct_send_fcp_data() */
1976 
1977 
1978 static fct_status_t
1979 emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd)
1980 {
1981 	emlxs_port_t *port =
1982 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
1983 	emlxs_hba_t *hba = HBA;
1984 	emlxs_buf_t *cmd_sbp;
1985 	scsi_task_t *fct_task;
1986 	fc_packet_t *pkt;
1987 	uint32_t did;
1988 	emlxs_fcp_rsp *fcp_rsp;
1989 	uint32_t size;
1990 	emlxs_node_t *ndlp;
1991 
1992 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
1993 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
1994 	did = fct_cmd->cmd_rportid;
1995 
1996 	/* Initialize cmd_sbp */
1997 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
1998 
1999 	mutex_enter(&cmd_sbp->mtx);
2000 	cmd_sbp->pkt_flags &= ~PACKET_RETURNED;
2001 	cmd_sbp->node = ndlp;
2002 
2003 	size = 24;
2004 	if (fct_task->task_sense_length) {
2005 		size += fct_task->task_sense_length;
2006 	}
2007 #ifdef FCT_API_TRACE
2008 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2009 	    "emlxs_fct_send_fcp_status %p: stat=%d resid=%d size=%d rx=%x",
2010 	    fct_cmd, fct_task->task_scsi_status,
2011 	    fct_task->task_resid, size, fct_cmd->cmd_rxid);
2012 #endif	/* FCT_API_TRACE */
2013 
2014 	if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) {
2015 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2016 		    "emlxs_fct_send_fcp_status: Unable to allocate packet.");
2017 
2018 		cmd_sbp->pkt_flags |= PACKET_RETURNED;
2019 		mutex_exit(&cmd_sbp->mtx);
2020 
2021 		return (FCT_FAILURE);
2022 	}
2023 	cmd_sbp->fct_type = EMLXS_FCT_FCP_STATUS;
2024 	cmd_sbp->fct_state = EMLXS_FCT_STATUS_PENDING;
2025 
2026 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
2027 
2028 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2029 	pkt->pkt_timeout =
2030 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
2031 	pkt->pkt_comp = emlxs_fct_pkt_comp;
2032 
2033 	/* Build the fc header */
2034 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(did);
2035 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
2036 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
2037 	pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP;
2038 	pkt->pkt_cmd_fhdr.f_ctl =
2039 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2040 	pkt->pkt_cmd_fhdr.seq_id = 0;
2041 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2042 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2043 	pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
2044 	pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
2045 	pkt->pkt_cmd_fhdr.ro = 0;
2046 
2047 	/* Build the status payload */
2048 	fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd;
2049 
2050 	if (fct_task->task_resid) {
2051 		if (fct_task->task_status_ctrl & TASK_SCTRL_OVER) {
2052 			TGTPORTSTAT.FctScsiResidOver++;
2053 			fcp_rsp->rspStatus2 |= RESID_OVER;
2054 			fcp_rsp->rspResId = SWAP_DATA32(fct_task->task_resid);
2055 
2056 		} else if (fct_task->task_status_ctrl & TASK_SCTRL_UNDER) {
2057 			TGTPORTSTAT.FctScsiResidUnder++;
2058 			fcp_rsp->rspStatus2 |= RESID_UNDER;
2059 			fcp_rsp->rspResId = SWAP_DATA32(fct_task->task_resid);
2060 
2061 		}
2062 	}
2063 	if (fct_task->task_scsi_status) {
2064 		if (fct_task->task_scsi_status == SCSI_STAT_QUE_FULL) {
2065 			TGTPORTSTAT.FctScsiQfullErr++;
2066 		} else {
2067 			TGTPORTSTAT.FctScsiStatusErr++;
2068 		}
2069 
2070 		/*
2071 		 * Make sure a residual is reported on non-SCSI_GOOD READ
2072 		 * status
2073 		 */
2074 		if ((fct_task->task_flags & TF_READ_DATA) &&
2075 		    (fcp_rsp->rspResId == 0)) {
2076 			fcp_rsp->rspStatus2 |= RESID_UNDER;
2077 			fcp_rsp->rspResId = fct_task->task_expected_xfer_length;
2078 		}
2079 	}
2080 	if (fct_task->task_sense_length) {
2081 		TGTPORTSTAT.FctScsiSenseErr++;
2082 		fcp_rsp->rspStatus2 |= SNS_LEN_VALID;
2083 		fcp_rsp->rspSnsLen = SWAP_DATA32(fct_task->task_sense_length);
2084 
2085 		bcopy((uint8_t *)fct_task->task_sense_data,
2086 		    (uint8_t *)&fcp_rsp->rspInfo0, fct_task->task_sense_length);
2087 	}
2088 	fcp_rsp->rspStatus3 = fct_task->task_scsi_status;
2089 	fcp_rsp->rspRspLen = 0;
2090 
2091 	mutex_exit(&cmd_sbp->mtx);
2092 
2093 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2094 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2095 		    "emlxs_fct_send_fcp_status: Unable to send packet.");
2096 
2097 		if (cmd_sbp->pkt_flags & PACKET_VALID) {
2098 			mutex_enter(&cmd_sbp->mtx);
2099 			cmd_sbp->fct_pkt = NULL;
2100 			cmd_sbp->fct_state = EMLXS_FCT_STATUS_COMPLETE;
2101 			cmd_sbp->pkt_flags |= PACKET_RETURNED;
2102 			mutex_exit(&cmd_sbp->mtx);
2103 		}
2104 		emlxs_pkt_free(pkt);
2105 		return (FCT_FAILURE);
2106 	}
2107 	return (FCT_SUCCESS);
2108 
2109 } /* emlxs_fct_send_fcp_status() */
2110 
2111 
2112 static fct_status_t
2113 emlxs_fct_send_qfull_reply(emlxs_port_t *port, emlxs_node_t *ndlp, uint16_t xid,
2114     uint32_t class, emlxs_fcp_cmd_t *fcp_cmd)
2115 {
2116 	emlxs_hba_t *hba = HBA;
2117 	emlxs_buf_t *sbp;
2118 	fc_packet_t *pkt;
2119 	emlxs_fcp_rsp *fcp_rsp;
2120 	uint32_t size;
2121 	RING *rp = &hba->ring[FC_FCP_RING];
2122 	uint8_t lun[8];
2123 
2124 	bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8);
2125 	size = 24;
2126 
2127 	if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) {
2128 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2129 		    "emlxs_fct_send_qfull_reply: Unable to allocate packet.");
2130 		return (FCT_FAILURE);
2131 	}
2132 	sbp = PKT2PRIV(pkt);
2133 	sbp->node = ndlp;
2134 	sbp->ring = rp;
2135 	sbp->did = ndlp->nlp_DID;
2136 	sbp->lun = (lun[0] << 8) | lun[1];
2137 	sbp->class = class;
2138 
2139 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2140 	pkt->pkt_timeout =
2141 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
2142 
2143 	/* Build the fc header */
2144 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(ndlp->nlp_DID);
2145 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
2146 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
2147 	pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP;
2148 	pkt->pkt_cmd_fhdr.f_ctl =
2149 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2150 	pkt->pkt_cmd_fhdr.seq_id = 0;
2151 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2152 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2153 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
2154 	pkt->pkt_cmd_fhdr.rx_id = xid;
2155 	pkt->pkt_cmd_fhdr.ro = 0;
2156 
2157 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2158 	    "emlxs_fct_send_qfull_reply: Sending QFULL: x%x lun x%x: %d %d",
2159 	    xid, sbp->lun, TGTPORTSTAT.FctOutstandingIO,
2160 	    port->fct_port->port_max_xchges);
2161 
2162 	/* Build the status payload */
2163 	fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd;
2164 
2165 	TGTPORTSTAT.FctScsiQfullErr++;
2166 	fcp_rsp->rspStatus3 = SCSI_STAT_QUE_FULL;
2167 	fcp_rsp->rspStatus2 |= RESID_UNDER;
2168 	fcp_rsp->rspResId = SWAP_DATA32(fcp_cmd->fcpDl);
2169 
2170 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2171 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2172 		    "emlxs_fct_send_qfull_reply: Unable to send packet.");
2173 		emlxs_pkt_free(pkt);
2174 		return (FCT_FAILURE);
2175 	}
2176 	return (FCT_SUCCESS);
2177 
2178 } /* emlxs_fct_send_qfull_reply() */
2179 
2180 
2181 
2182 
2183 /* ARGSUSED */
2184 extern int
2185 emlxs_fct_handle_fcp_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq)
2186 {
2187 	emlxs_port_t *port = &PPORT;
2188 	IOCB *iocb;
2189 	emlxs_buf_t *sbp;
2190 	emlxs_buf_t *cmd_sbp;
2191 	uint32_t status;
2192 	fct_cmd_t *fct_cmd;
2193 	stmf_data_buf_t *dbuf;
2194 	scsi_task_t *fct_task;
2195 
2196 	iocb = &iocbq->iocb;
2197 	sbp = (emlxs_buf_t *)iocbq->sbp;
2198 
2199 
2200 	TGTPORTSTAT.FctEvent++;
2201 
2202 	if (!sbp) {
2203 		/* completion with missing xmit command */
2204 		TGTPORTSTAT.FctStray++;
2205 
2206 		/* emlxs_stray_fcp_completion_msg */
2207 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2208 		    "cmd=%x status=%x error=%x iotag=%x", iocb->ulpCommand,
2209 		    iocb->ulpStatus, iocb->un.grsp.perr.statLocalError,
2210 		    iocb->ulpIoTag);
2211 
2212 		return (1);
2213 	}
2214 	TGTPORTSTAT.FctCompleted++;
2215 
2216 	port = sbp->iocbq.port;
2217 	fct_cmd = sbp->fct_cmd;
2218 	status = iocb->ulpStatus;
2219 
2220 #ifdef FCT_API_TRACE
2221 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2222 	    "emlxs_fct_handle_fcp_event: %p: cmd=%x status=%x",
2223 	    fct_cmd, iocb->ulpCommand, status);
2224 #endif	/* FCT_API_TRACE */
2225 
2226 	if (fct_cmd == NULL) {
2227 		if ((iocb->ulpCommand == CMD_FCP_TRSP_CX) ||
2228 		    (iocb->ulpCommand == CMD_FCP_TRSP64_CX)) {
2229 			emlxs_pkt_free(sbp->pkt);
2230 		}
2231 		return (0);
2232 	}
2233 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2234 	dbuf = sbp->fct_buf;
2235 	fct_cmd->cmd_comp_status = (status) ? FCT_FAILURE : FCT_SUCCESS;
2236 
2237 
2238 	switch (iocb->ulpCommand) {
2239 
2240 		/*
2241 		 * FCP Data completion
2242 		 */
2243 	case CMD_FCP_TSEND_CX:
2244 	case CMD_FCP_TSEND64_CX:
2245 	case CMD_FCP_TRECEIVE_CX:
2246 	case CMD_FCP_TRECEIVE64_CX:
2247 
2248 		mutex_enter(&cmd_sbp->mtx);
2249 		cmd_sbp->pkt_flags &= ~PACKET_RETURNED;
2250 		cmd_sbp->fct_state = EMLXS_FCT_DATA_COMPLETE;
2251 
2252 		if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT) {
2253 			cmd_sbp->fct_flags |= EMLXS_FCT_ABORT_COMPLETE;
2254 			mutex_exit(&cmd_sbp->mtx);
2255 
2256 			/* Wake up sleeping thread */
2257 			mutex_enter(&EMLXS_PKT_LOCK);
2258 			cv_broadcast(&EMLXS_PKT_CV);
2259 			mutex_exit(&EMLXS_PKT_LOCK);
2260 
2261 			break;
2262 		}
2263 		if (status == 0) {
2264 			if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) {
2265 				emlxs_fct_dbuf_dma_sync(dbuf,
2266 				    DDI_DMA_SYNC_FORCPU);
2267 			}
2268 			if (cmd_sbp->fct_flags & EMLXS_FCT_SEND_STATUS) {
2269 				dbuf->db_flags |= DB_STATUS_GOOD_SENT;
2270 
2271 				fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
2272 				fct_task->task_scsi_status = 0;
2273 
2274 				mutex_exit(&cmd_sbp->mtx);
2275 				(void) emlxs_fct_send_fcp_status(fct_cmd);
2276 
2277 				break;
2278 			}
2279 		}
2280 		cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
2281 		cmd_sbp->pkt_flags |= PACKET_RETURNED;
2282 		mutex_exit(&cmd_sbp->mtx);
2283 
2284 #ifdef FCT_API_TRACE
2285 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2286 		    "fct_scsi_data_xfer_done:1 %p %p", fct_cmd, dbuf);
2287 #endif	/* FCT_API_TRACE */
2288 		MODSYM(fct_scsi_data_xfer_done) (fct_cmd, dbuf, 0);
2289 
2290 		break;
2291 
2292 		/* FCP Status completion */
2293 	case CMD_FCP_TRSP_CX:
2294 	case CMD_FCP_TRSP64_CX:
2295 
2296 		mutex_enter(&cmd_sbp->mtx);
2297 		cmd_sbp->pkt_flags &= ~PACKET_RETURNED;
2298 		cmd_sbp->fct_state = EMLXS_FCT_STATUS_COMPLETE;
2299 
2300 		if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT) {
2301 			cmd_sbp->fct_flags |= EMLXS_FCT_ABORT_COMPLETE;
2302 			mutex_exit(&cmd_sbp->mtx);
2303 
2304 			/* Wake up sleeping thread */
2305 			mutex_enter(&EMLXS_PKT_LOCK);
2306 			cv_broadcast(&EMLXS_PKT_CV);
2307 			mutex_exit(&EMLXS_PKT_LOCK);
2308 		} else if (cmd_sbp->fct_flags & EMLXS_FCT_SEND_STATUS) {
2309 
2310 			/* mutex_exit(&cmd_sbp->mtx); */
2311 			(void) emlxs_fct_cmd_uninit(port, fct_cmd);
2312 			TGTPORTSTAT.FctOutstandingIO--;
2313 
2314 #ifdef FCT_API_TRACE
2315 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2316 			    "fct_scsi_data_xfer_done:2 %p %p",
2317 			    fct_cmd, cmd_sbp->fct_buf);
2318 #endif	/* FCT_API_TRACE */
2319 			MODSYM(fct_scsi_data_xfer_done) (fct_cmd,
2320 			    cmd_sbp->fct_buf, FCT_IOF_FCA_DONE);
2321 		} else {
2322 			/* mutex_exit(&cmd_sbp->mtx); */
2323 			(void) emlxs_fct_cmd_uninit(port, fct_cmd);
2324 			TGTPORTSTAT.FctOutstandingIO--;
2325 
2326 #ifdef FCT_API_TRACE
2327 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2328 			    "fct_send_response_done:1 %p: x%x",
2329 			    fct_cmd, fct_cmd->cmd_comp_status);
2330 #endif	/* FCT_API_TRACE */
2331 			MODSYM(fct_send_response_done) (fct_cmd,
2332 			    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
2333 		}
2334 
2335 		emlxs_pkt_free(sbp->pkt);
2336 
2337 		break;
2338 
2339 	default:
2340 
2341 		TGTPORTSTAT.FctStray++;
2342 
2343 		TGTPORTSTAT.FctCompleted--;
2344 
2345 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2346 		    "Invalid iocb: cmd=0x%x", iocb->ulpCommand);
2347 
2348 		emlxs_pkt_complete(sbp, status,
2349 		    iocb->un.grsp.perr.statLocalError, 1);
2350 
2351 		return (1);
2352 	}	/* switch(iocb->ulpCommand) */
2353 
2354 
2355 	if (status == IOSTAT_SUCCESS) {
2356 		TGTPORTSTAT.FctCmplGood++;
2357 	} else {
2358 		TGTPORTSTAT.FctCmplError++;
2359 	}
2360 
2361 	return (0);
2362 
2363 
2364 } /* emlxs_fct_handle_fcp_event() */
2365 
2366 
2367 extern int
2368 emlxs_fct_handle_unsol_els(emlxs_port_t *port, RING *rp, IOCBQ *iocbq,
2369     MATCHMAP *mp, uint32_t size)
2370 {
2371 	emlxs_hba_t *hba = HBA;
2372 	IOCB *iocb;
2373 	uint32_t cmd_code;
2374 	fct_cmd_t *fct_cmd;
2375 	fct_els_t *els;
2376 	uint32_t sid;
2377 	uint32_t padding;
2378 	uint8_t *bp;
2379 	emlxs_buf_t *cmd_sbp;
2380 	uint32_t rval;
2381 
2382 	HBASTATS.ElsCmdReceived++;
2383 
2384 	bp = mp->virt;
2385 	cmd_code = (*(uint32_t *)bp) & ELS_CMD_MASK;
2386 	iocb = &iocbq->iocb;
2387 	sid = iocb->un.elsreq.remoteID;
2388 
2389 	if (!port->fct_port) {
2390 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2391 		    "%s: sid=%x. Target unbound. Rejecting...",
2392 		    emlxs_elscmd_xlate(cmd_code), sid);
2393 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
2394 		    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
2395 
2396 		goto done;
2397 	}
2398 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
2399 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2400 		    "%s: sid=%x. Target offline. Rejecting...",
2401 		    emlxs_elscmd_xlate(cmd_code), sid);
2402 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
2403 		    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
2404 
2405 		goto done;
2406 	}
2407 	/* Process the request */
2408 	switch (cmd_code) {
2409 	case ELS_CMD_FLOGI:
2410 		rval = emlxs_fct_process_unsol_flogi(port, rp, iocbq, mp, size);
2411 		break;
2412 
2413 	case ELS_CMD_PLOGI:
2414 		rval = emlxs_fct_process_unsol_plogi(port, rp, iocbq, mp, size);
2415 		break;
2416 
2417 	default:
2418 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2419 		    "%s: sid=0x%x", emlxs_elscmd_xlate(cmd_code), sid);
2420 		rval = 0;
2421 		break;
2422 	}
2423 
2424 	if (rval) {
2425 		goto done;
2426 	}
2427 	padding = (8 - (size & 7)) & 7;
2428 
2429 	fct_cmd = (fct_cmd_t *)MODSYM(fct_alloc) (FCT_STRUCT_CMD_RCVD_ELS,
2430 	    (size + padding + GET_STRUCT_SIZE(emlxs_buf_t)), AF_FORCE_NOSLEEP);
2431 
2432 #ifdef FCT_API_TRACE
2433 	{
2434 		uint32_t *ptr = (uint32_t *)bp;
2435 
2436 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2437 		    "fct_alloc %p: ELS rcvd: rxid=%x payload: x%x x%x",
2438 		    fct_cmd, iocb->ulpContext, *ptr, *(ptr + 1));
2439 	}
2440 #endif	/* FCT_API_TRACE */
2441 
2442 	if (fct_cmd == NULL) {
2443 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2444 		    "%s: sid=%x. Out of memory. Rejecting...",
2445 		    emlxs_elscmd_xlate(cmd_code), sid);
2446 
2447 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
2448 		    LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
2449 		goto done;
2450 	}
2451 	/* Initialize fct_cmd */
2452 	fct_cmd->cmd_oxid = (cmd_code >> ELS_CMD_SHIFT) & 0xff;
2453 	fct_cmd->cmd_rxid = iocb->ulpContext;
2454 	fct_cmd->cmd_rportid = sid;
2455 	fct_cmd->cmd_lportid = port->did;
2456 	fct_cmd->cmd_rp_handle = iocb->ulpIoTag;	/* RPI */
2457 	fct_cmd->cmd_port = port->fct_port;
2458 
2459 	/* Initialize cmd_sbp */
2460 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd);
2461 	/* mutex_enter(&cmd_sbp->mtx); */
2462 
2463 	cmd_sbp->ring = rp;
2464 	cmd_sbp->class = iocb->ulpClass;
2465 	cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD;
2466 	cmd_sbp->fct_state = EMLXS_FCT_CMD_RECEIVED;
2467 	bcopy((uint8_t *)iocb, (uint8_t *)&cmd_sbp->iocbq,
2468 	    sizeof (emlxs_iocb_t));
2469 
2470 	if (cmd_code == ELS_CMD_FLOGI) {
2471 		cmd_sbp->fct_flags |= EMLXS_FCT_FLOGI;
2472 	}
2473 	els = (fct_els_t *)fct_cmd->cmd_specific;
2474 	els->els_req_size = size;
2475 	els->els_req_payload = GET_BYTE_OFFSET(fct_cmd->cmd_fca_private,
2476 	    GET_STRUCT_SIZE(emlxs_buf_t));
2477 	bcopy(bp, els->els_req_payload, size);
2478 
2479 	cmd_sbp->pkt_flags |= PACKET_RETURNED;
2480 	mutex_exit(&cmd_sbp->mtx);
2481 
2482 	emlxs_fct_unsol_callback(port, fct_cmd);
2483 
2484 done:
2485 
2486 	return (0);
2487 
2488 } /* emlxs_fct_handle_unsol_els() */
2489 
2490 
2491 static void
2492 emlxs_fct_handle_rcvd_flogi(emlxs_port_t *port, fct_cmd_t *fct_cmd)
2493 {
2494 	fct_els_t *fct_els;
2495 	ELS_PKT *els;
2496 	fct_flogi_xchg_t fx;
2497 	fct_status_t status;
2498 	emlxs_buf_t *cmd_sbp;
2499 
2500 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2501 
2502 	mutex_enter(&cmd_sbp->mtx);
2503 	cmd_sbp->pkt_flags &= ~PACKET_RETURNED;
2504 
2505 	fct_els = (fct_els_t *)fct_cmd->cmd_specific;
2506 	els = (ELS_PKT *)fct_els->els_req_payload;
2507 
2508 	/* Init the xchg object */
2509 	bzero((uint8_t *)&fx, sizeof (fct_flogi_xchg_t));
2510 	bcopy((caddr_t)&els->un.logi.nodeName, (caddr_t)fx.fx_nwwn, 8);
2511 	bcopy((caddr_t)&els->un.logi.portName, (caddr_t)fx.fx_pwwn, 8);
2512 	fx.fx_sid = fct_cmd->cmd_rportid;
2513 	fx.fx_did = fct_cmd->cmd_lportid;
2514 	fx.fx_fport = els->un.logi.cmn.fPort;
2515 	fx.fx_op = ELS_OP_FLOGI;
2516 
2517 	status = MODSYM(fct_handle_rcvd_flogi) (port->fct_port, &fx);
2518 #ifdef FCT_API_TRACE
2519 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2520 	    "fct_handle_rcvd_flogi %p: x%x", port->fct_port, status);
2521 #endif	/* FCT_API_TRACE */
2522 
2523 	if (status == FCT_SUCCESS) {
2524 		if (fx.fx_op == ELS_OP_ACC) {
2525 			(void) emlxs_els_reply(port, &cmd_sbp->iocbq,
2526 			    ELS_CMD_ACC, ELS_CMD_FLOGI, 0, 0);
2527 		} else {	/* ELS_OP_LSRJT */
2528 			(void) emlxs_els_reply(port, &cmd_sbp->iocbq,
2529 			    ELS_CMD_LS_RJT, ELS_CMD_FLOGI, fx.fx_rjt_reason,
2530 			    fx.fx_rjt_expl);
2531 		}
2532 	} else {
2533 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2534 		    "FLOGI: sid=%x. fct_handle_rcvd_flogi failed. Rejecting.",
2535 		    fct_cmd->cmd_rportid);
2536 
2537 		(void) emlxs_els_reply(port, &cmd_sbp->iocbq, ELS_CMD_LS_RJT,
2538 		    ELS_CMD_FLOGI, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
2539 	}
2540 
2541 	/* mutex_exit(&cmd_sbp->mtx); */
2542 	(void) emlxs_fct_cmd_uninit(port, fct_cmd);
2543 
2544 #ifdef FCT_API_TRACE
2545 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2546 	    "fct_free:7 %p", fct_cmd);
2547 #endif	/* FCT_API_TRACE */
2548 	MODSYM(fct_free) (fct_cmd);
2549 
2550 	return;
2551 
2552 } /* emlxs_fct_handle_rcvd_flogi() */
2553 
2554 
2555 /* ARGSUSED */
2556 static uint32_t
2557 emlxs_fct_process_unsol_flogi(emlxs_port_t *port, RING *rp, IOCBQ *iocbq,
2558     MATCHMAP *mp, uint32_t size)
2559 {
2560 	IOCB *iocb;
2561 	char buffer[64];
2562 
2563 	buffer[0] = 0;
2564 
2565 	iocb = &iocbq->iocb;
2566 
2567 	/* Perform processing of FLOGI payload */
2568 	if (emlxs_process_unsol_flogi(port, iocbq, mp, size, buffer)) {
2569 		return (1);
2570 	}
2571 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, "FLOGI: sid=0x%x %s",
2572 	    iocb->un.elsreq.remoteID, buffer);
2573 
2574 	return (0);
2575 
2576 } /* emlxs_fct_process_unsol_flogi() */
2577 
2578 
2579 /* ARGSUSED */
2580 static uint32_t
2581 emlxs_fct_process_unsol_plogi(emlxs_port_t *port, RING *rp, IOCBQ *iocbq,
2582     MATCHMAP *mp, uint32_t size)
2583 {
2584 	IOCB *iocb;
2585 	char buffer[64];
2586 
2587 	buffer[0] = 0;
2588 
2589 	iocb = &iocbq->iocb;
2590 
2591 	/* Perform processing of PLOGI payload */
2592 	if (emlxs_process_unsol_plogi(port, iocbq, mp, size, buffer)) {
2593 		return (1);
2594 	}
2595 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, "PLOGI: sid=0x%x %s",
2596 	    iocb->un.elsreq.remoteID, buffer);
2597 
2598 	return (0);
2599 
2600 } /* emlxs_fct_process_unsol_plogi() */
2601 
2602 
2603 /* ARGSUSED */
2604 static emlxs_buf_t *
2605 emlxs_fct_pkt_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, fc_packet_t *pkt)
2606 {
2607 	emlxs_buf_t *cmd_sbp;
2608 	emlxs_buf_t *sbp;
2609 
2610 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2611 	cmd_sbp->fct_pkt = pkt;
2612 
2613 	sbp = PKT2PRIV(pkt);
2614 	sbp->fct_cmd = cmd_sbp->fct_cmd;
2615 	sbp->node = cmd_sbp->node;
2616 	sbp->ring = cmd_sbp->ring;
2617 	sbp->did = cmd_sbp->did;
2618 	sbp->lun = cmd_sbp->lun;
2619 	sbp->class = cmd_sbp->class;
2620 	sbp->fct_type = cmd_sbp->fct_type;
2621 	sbp->fct_state = cmd_sbp->fct_state;
2622 
2623 	return (sbp);
2624 
2625 } /* emlxs_fct_pkt_init() */
2626 
2627 
2628 /* Mutex will be acquired */
2629 static emlxs_buf_t *
2630 emlxs_fct_cmd_init(emlxs_port_t *port, fct_cmd_t *fct_cmd)
2631 {
2632 	emlxs_hba_t *hba = HBA;
2633 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2634 
2635 	bzero((void *)cmd_sbp, sizeof (emlxs_buf_t));
2636 
2637 	mutex_init(&cmd_sbp->mtx, NULL, MUTEX_DRIVER, (void *)hba->intr_arg);
2638 
2639 	mutex_enter(&cmd_sbp->mtx);
2640 	cmd_sbp->pkt_flags = PACKET_VALID;
2641 	cmd_sbp->port = port;
2642 	cmd_sbp->fct_cmd = fct_cmd;
2643 	cmd_sbp->node = (fct_cmd->cmd_rp) ?
2644 	    *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private : NULL;
2645 	cmd_sbp->did = fct_cmd->cmd_rportid;
2646 	cmd_sbp->iocbq.sbp = cmd_sbp;
2647 
2648 	return (cmd_sbp);
2649 
2650 } /* emlxs_fct_cmd_init() */
2651 
2652 
2653 /* Mutex must be held */
2654 static int
2655 emlxs_fct_cmd_uninit(emlxs_port_t *port, fct_cmd_t *fct_cmd)
2656 {
2657 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2658 
2659 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
2660 		return (FC_FAILURE);
2661 	}
2662 	if (cmd_sbp->iotag != 0) {
2663 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2664 		    "Pkt still registered! ringo=%d iotag=%d sbp=%p",
2665 		    cmd_sbp->ring, cmd_sbp->iotag, cmd_sbp);
2666 
2667 		if (cmd_sbp->ring) {
2668 			(void) emlxs_unregister_pkt(cmd_sbp->ring,
2669 			    cmd_sbp->iotag, 1);
2670 		}
2671 	}
2672 	cmd_sbp->pkt_flags |= PACKET_RETURNED;
2673 	cmd_sbp->pkt_flags &= ~PACKET_VALID;
2674 
2675 	mutex_exit(&cmd_sbp->mtx);
2676 	mutex_destroy(&cmd_sbp->mtx);
2677 
2678 	return (FC_SUCCESS);
2679 
2680 } /* emlxs_fct_cmd_uninit() */
2681 
2682 
2683 static void
2684 emlxs_fct_pkt_comp(fc_packet_t *pkt)
2685 {
2686 	emlxs_port_t *port;
2687 	emlxs_buf_t *sbp;
2688 	emlxs_buf_t *cmd_sbp;
2689 	fct_cmd_t *fct_cmd;
2690 	fct_els_t *fct_els;
2691 	fct_sol_ct_t *fct_ct;
2692 
2693 	sbp = PKT2PRIV(pkt);
2694 	port = sbp->port;
2695 	fct_cmd = sbp->fct_cmd;
2696 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2697 
2698 	mutex_enter(&cmd_sbp->mtx);
2699 	cmd_sbp->pkt_flags &= ~PACKET_RETURNED;
2700 	cmd_sbp->fct_pkt = NULL;
2701 
2702 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT) {
2703 		cmd_sbp->fct_flags |= EMLXS_FCT_ABORT_COMPLETE;
2704 		mutex_exit(&cmd_sbp->mtx);
2705 
2706 		/* Wake up sleeping thread */
2707 		mutex_enter(&EMLXS_PKT_LOCK);
2708 		cv_broadcast(&EMLXS_PKT_CV);
2709 		mutex_exit(&EMLXS_PKT_LOCK);
2710 
2711 		goto done;
2712 	}
2713 	fct_cmd->cmd_comp_status = (pkt->pkt_state) ? FCT_FAILURE : FCT_SUCCESS;
2714 
2715 	switch (fct_cmd->cmd_type) {
2716 	case FCT_CMD_FCP_XCHG:
2717 		cmd_sbp->fct_state = EMLXS_FCT_STATUS_COMPLETE;
2718 
2719 		/* mutex_exit(&cmd_sbp->mtx); */
2720 		(void) emlxs_fct_cmd_uninit(port, fct_cmd);
2721 
2722 #ifdef FCT_API_TRACE
2723 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2724 		    "fct_send_response_done:2 %p: x%x",
2725 		    fct_cmd, fct_cmd->cmd_comp_status);
2726 #else
2727 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2728 		    "emlxs_fct_pkt_comp: fct_send_response_done. dbuf=%p",
2729 		    sbp->fct_buf);
2730 #endif	/* FCT_API_TRACE */
2731 
2732 		MODSYM(fct_send_response_done) (fct_cmd,
2733 		    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
2734 
2735 		break;
2736 
2737 	case FCT_CMD_RCVD_ELS:
2738 		cmd_sbp->fct_state = EMLXS_FCT_RSP_COMPLETE;
2739 
2740 		/* mutex_exit(&cmd_sbp->mtx); */
2741 		(void) emlxs_fct_cmd_uninit(port, fct_cmd);
2742 
2743 #ifdef FCT_API_TRACE
2744 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2745 		    "fct_send_response_done:3 %p: x%x",
2746 		    fct_cmd, fct_cmd->cmd_comp_status);
2747 #endif	/* FCT_API_TRACE */
2748 		MODSYM(fct_send_response_done) (fct_cmd,
2749 		    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
2750 
2751 		break;
2752 
2753 	case FCT_CMD_SOL_ELS:
2754 		cmd_sbp->fct_state = EMLXS_FCT_REQ_COMPLETE;
2755 
2756 		fct_els = (fct_els_t *)fct_cmd->cmd_specific;
2757 
2758 		if (fct_els->els_resp_payload) {
2759 			emlxs_mpdata_sync(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen,
2760 			    DDI_DMA_SYNC_FORKERNEL);
2761 
2762 			bcopy((uint8_t *)pkt->pkt_resp,
2763 			    (uint8_t *)fct_els->els_resp_payload,
2764 			    fct_els->els_resp_size);
2765 		}
2766 		/* mutex_exit(&cmd_sbp->mtx); */
2767 		(void) emlxs_fct_cmd_uninit(port, fct_cmd);
2768 
2769 #ifdef FCT_API_TRACE
2770 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2771 		    "fct_send_cmd_done:1 %p: x%x",
2772 		    fct_cmd, fct_cmd->cmd_comp_status);
2773 #endif	/* FCT_API_TRACE */
2774 		MODSYM(fct_send_cmd_done) (fct_cmd,
2775 		    FCT_SUCCESS, FCT_IOF_FCA_DONE);
2776 
2777 		break;
2778 
2779 	case FCT_CMD_SOL_CT:
2780 		cmd_sbp->fct_state = EMLXS_FCT_REQ_COMPLETE;
2781 
2782 		fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific;
2783 
2784 		if (fct_ct->ct_resp_payload) {
2785 			emlxs_mpdata_sync(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen,
2786 			    DDI_DMA_SYNC_FORKERNEL);
2787 
2788 			bcopy((uint8_t *)pkt->pkt_resp,
2789 			    (uint8_t *)fct_ct->ct_resp_payload,
2790 			    fct_ct->ct_resp_size);
2791 		}
2792 		/* mutex_exit(&cmd_sbp->mtx); */
2793 		(void) emlxs_fct_cmd_uninit(port, fct_cmd);
2794 
2795 #ifdef FCT_API_TRACE
2796 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2797 		    "fct_send_cmd_done:2 %p: x%x",
2798 		    fct_cmd, fct_cmd->cmd_comp_status);
2799 #endif	/* FCT_API_TRACE */
2800 		MODSYM(fct_send_cmd_done) (fct_cmd,
2801 		    FCT_SUCCESS, FCT_IOF_FCA_DONE);
2802 		break;
2803 
2804 	default:
2805 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2806 		    "emlxs_fct_pkt_comp: Invalid cmd type found. type=%x",
2807 		    fct_cmd->cmd_type);
2808 
2809 		/* mutex_exit(&cmd_sbp->mtx); */
2810 		(void) emlxs_fct_cmd_uninit(port, fct_cmd);
2811 	}
2812 
2813 done:
2814 
2815 	emlxs_pkt_free(pkt);
2816 
2817 	return;
2818 
2819 } /* emlxs_fct_pkt_comp() */
2820 
2821 
2822 
2823 static fct_status_t
2824 emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd)
2825 {
2826 	emlxs_port_t *port =
2827 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
2828 	emlxs_hba_t *hba = HBA;
2829 	uint32_t did;
2830 	fct_els_t *fct_els;
2831 	fc_packet_t *pkt;
2832 	emlxs_buf_t *cmd_sbp;
2833 
2834 #if 0
2835 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2836 	    "emlxs_fct_send_els_cmd() called.");
2837 #endif
2838 
2839 	did = fct_cmd->cmd_rportid;
2840 	fct_els = (fct_els_t *)fct_cmd->cmd_specific;
2841 
2842 	if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_req_size,
2843 	    fct_els->els_resp_size, 0, KM_NOSLEEP))) {
2844 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2845 		    "emlxs_fct_send_els_cmd: Unable to allocate packet.");
2846 		return (FCT_FAILURE);
2847 	}
2848 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd);
2849 	/* mutex_enter(&cmd_sbp->mtx); */
2850 
2851 	cmd_sbp->ring = &hba->ring[FC_ELS_RING];
2852 	cmd_sbp->fct_type = EMLXS_FCT_ELS_REQ;
2853 	cmd_sbp->fct_state = EMLXS_FCT_REQ_PENDING;
2854 
2855 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
2856 
2857 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
2858 	pkt->pkt_timeout =
2859 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
2860 	pkt->pkt_comp = emlxs_fct_pkt_comp;
2861 
2862 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2863 	    "emlxs_fct_send_els_cmd: pkt_timeout=%d ratov=%d",
2864 	    pkt->pkt_timeout, hba->fc_ratov);
2865 
2866 
2867 	/* Build the fc header */
2868 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(did);
2869 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
2870 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
2871 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2872 	pkt->pkt_cmd_fhdr.f_ctl =
2873 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
2874 	pkt->pkt_cmd_fhdr.seq_id = 0;
2875 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2876 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2877 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
2878 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
2879 	pkt->pkt_cmd_fhdr.ro = 0;
2880 
2881 	/* Copy the cmd payload */
2882 	bcopy((uint8_t *)fct_els->els_req_payload, (uint8_t *)pkt->pkt_cmd,
2883 	    fct_els->els_req_size);
2884 
2885 	mutex_exit(&cmd_sbp->mtx);
2886 
2887 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2888 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2889 		    "emlxs_fct_send_els_cmd: Unable to send packet.");
2890 
2891 		if (cmd_sbp->pkt_flags & PACKET_VALID) {
2892 			mutex_enter(&cmd_sbp->mtx);
2893 			cmd_sbp->fct_pkt = NULL;
2894 			cmd_sbp->fct_state = EMLXS_FCT_REQ_COMPLETE;
2895 			cmd_sbp->pkt_flags |= PACKET_RETURNED;
2896 			mutex_exit(&cmd_sbp->mtx);
2897 		}
2898 		emlxs_pkt_free(pkt);
2899 		return (FCT_FAILURE);
2900 	}
2901 	return (FCT_SUCCESS);
2902 
2903 } /* emlxs_fct_send_els_cmd() */
2904 
2905 
2906 static fct_status_t
2907 emlxs_fct_send_abts_rsp(fct_cmd_t *fct_cmd)
2908 {
2909 	emlxs_port_t *port =
2910 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
2911 	emlxs_hba_t *hba = HBA;
2912 	emlxs_buf_t *cmd_sbp;
2913 	IOCBQ *iocbq;
2914 
2915 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2916 	    "emlxs_fct_send_abts_rsp: cmd=%p", fct_cmd);
2917 
2918 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2919 
2920 	mutex_enter(&cmd_sbp->mtx);
2921 	cmd_sbp->pkt_flags &= ~PACKET_RETURNED;
2922 
2923 	cmd_sbp->fct_flags |= (EMLXS_FCT_ABORT | EMLXS_FCT_ABORT_COMPLETE);
2924 
2925 	/* Create the abort IOCB */
2926 	if (hba->state >= FC_LINK_UP) {
2927 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2928 		    "emlxs_fct_send_abts_rsp: Aborting xid=%x. sbp=%p "
2929 		    "state=%d flags=%x,%x", fct_cmd->cmd_rxid, cmd_sbp,
2930 		    cmd_sbp->fct_state, cmd_sbp->fct_flags, cmd_sbp->pkt_flags);
2931 
2932 		iocbq = emlxs_create_abort_xri_cx(port, cmd_sbp->node,
2933 		    fct_cmd->cmd_rxid, cmd_sbp->ring, cmd_sbp->class,
2934 		    ABORT_TYPE_ABTS);
2935 	} else {
2936 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2937 		    "emlxs_fct_send_abts_rsp: Closing xid=%x. sbp=%p state=%d "
2938 		    "flags=%x,%x", fct_cmd->cmd_rxid, cmd_sbp,
2939 		    cmd_sbp->fct_state, cmd_sbp->fct_flags, cmd_sbp->pkt_flags);
2940 
2941 		iocbq = emlxs_create_close_xri_cx(port, cmd_sbp->node,
2942 		    fct_cmd->cmd_rxid, cmd_sbp->ring);
2943 	}
2944 
2945 	cmd_sbp->abort_attempts++;
2946 	emlxs_issue_iocb_cmd(hba, cmd_sbp->ring, iocbq);
2947 
2948 	/* mutex_exit(&cmd_sbp->mtx); */
2949 	(void) emlxs_fct_cmd_uninit(port, fct_cmd);
2950 
2951 	fct_cmd->cmd_comp_status = FCT_SUCCESS;
2952 #ifdef FCT_API_TRACE
2953 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2954 	    "fct_send_response_done:4 %p: x%x",
2955 	    fct_cmd, fct_cmd->cmd_comp_status);
2956 #endif	/* FCT_API_TRACE */
2957 	MODSYM(fct_send_response_done) (fct_cmd,
2958 	    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
2959 
2960 	return (FCT_SUCCESS);
2961 
2962 } /* emlxs_fct_send_abts_rsp() */
2963 
2964 
2965 static fct_status_t
2966 emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd)
2967 {
2968 	emlxs_port_t *port =
2969 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
2970 	emlxs_hba_t *hba = HBA;
2971 	uint32_t did;
2972 	fct_els_t *fct_els;
2973 	fc_packet_t *pkt;
2974 	emlxs_buf_t *cmd_sbp;
2975 
2976 #if 0
2977 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2978 	    "emlxs_fct_send_els_rsp: cmd=%p", fct_cmd);
2979 #endif
2980 
2981 	fct_els = (fct_els_t *)fct_cmd->cmd_specific;
2982 	did = fct_cmd->cmd_rportid;
2983 
2984 	if (!(pkt =
2985 	    emlxs_pkt_alloc(port, fct_els->els_resp_size, 0, 0, KM_NOSLEEP))) {
2986 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2987 		    "emlxs_fct_send_els_rsp: Unable to allocate packet.");
2988 		return (FCT_FAILURE);
2989 	}
2990 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2991 
2992 	mutex_enter(&cmd_sbp->mtx);
2993 	cmd_sbp->pkt_flags &= ~PACKET_RETURNED;
2994 
2995 	cmd_sbp->fct_type = EMLXS_FCT_ELS_RSP;
2996 	cmd_sbp->fct_state = EMLXS_FCT_RSP_PENDING;
2997 
2998 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
2999 
3000 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
3001 	pkt->pkt_timeout =
3002 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
3003 	pkt->pkt_comp = emlxs_fct_pkt_comp;
3004 
3005 	/* Build the fc header */
3006 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(did);
3007 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_RSP;
3008 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
3009 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3010 	pkt->pkt_cmd_fhdr.f_ctl =
3011 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
3012 	pkt->pkt_cmd_fhdr.seq_id = 0;
3013 	pkt->pkt_cmd_fhdr.df_ctl = 0;
3014 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
3015 	pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
3016 	pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
3017 	pkt->pkt_cmd_fhdr.ro = 0;
3018 
3019 	/* Copy the resp payload to pkt_cmd buffer */
3020 	bcopy((uint8_t *)fct_els->els_resp_payload, (uint8_t *)pkt->pkt_cmd,
3021 	    fct_els->els_resp_size);
3022 
3023 	mutex_exit(&cmd_sbp->mtx);
3024 
3025 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
3026 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
3027 		    "emlxs_fct_send_els_rsp: Unable to send packet.");
3028 
3029 		if (cmd_sbp->pkt_flags & PACKET_VALID) {
3030 			mutex_enter(&cmd_sbp->mtx);
3031 			cmd_sbp->fct_pkt = NULL;
3032 			cmd_sbp->fct_state = EMLXS_FCT_RSP_COMPLETE;
3033 			cmd_sbp->pkt_flags |= PACKET_RETURNED;
3034 			mutex_exit(&cmd_sbp->mtx);
3035 		}
3036 		emlxs_pkt_free(pkt);
3037 		return (FCT_FAILURE);
3038 	}
3039 	return (FCT_SUCCESS);
3040 
3041 } /* emlxs_fct_send_els_rsp() */
3042 
3043 
3044 
3045 static fct_status_t
3046 emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd)
3047 {
3048 	emlxs_port_t *port =
3049 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
3050 	emlxs_hba_t *hba = HBA;
3051 	uint32_t did;
3052 	fct_sol_ct_t *fct_ct;
3053 	fc_packet_t *pkt;
3054 	emlxs_buf_t *cmd_sbp;
3055 
3056 #if 0
3057 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3058 	    "emlxs_fct_send_ct_cmd() called.");
3059 #endif
3060 
3061 	did = fct_cmd->cmd_rportid;
3062 	fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific;
3063 
3064 	if (!(pkt = emlxs_pkt_alloc(port, fct_ct->ct_req_size,
3065 	    fct_ct->ct_resp_size, 0, KM_NOSLEEP))) {
3066 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
3067 		    "emlxs_fct_send_ct_cmd: Unable to allocate packet.");
3068 		return (FCT_FAILURE);
3069 	}
3070 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd);
3071 	/* mutex_enter(&cmd_sbp->mtx); */
3072 
3073 	cmd_sbp->ring = &hba->ring[FC_CT_RING];
3074 	cmd_sbp->fct_type = EMLXS_FCT_CT_REQ;
3075 	cmd_sbp->fct_state = EMLXS_FCT_REQ_PENDING;
3076 
3077 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
3078 
3079 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
3080 	pkt->pkt_timeout =
3081 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
3082 	pkt->pkt_comp = emlxs_fct_pkt_comp;
3083 
3084 	/* Build the fc header */
3085 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(did);
3086 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL;
3087 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
3088 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
3089 	pkt->pkt_cmd_fhdr.f_ctl =
3090 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
3091 	pkt->pkt_cmd_fhdr.seq_id = 0;
3092 	pkt->pkt_cmd_fhdr.df_ctl = 0;
3093 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
3094 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
3095 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
3096 	pkt->pkt_cmd_fhdr.ro = 0;
3097 
3098 	/* Copy the cmd payload */
3099 	bcopy((uint8_t *)fct_ct->ct_req_payload, (uint8_t *)pkt->pkt_cmd,
3100 	    fct_ct->ct_req_size);
3101 
3102 	mutex_exit(&cmd_sbp->mtx);
3103 
3104 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
3105 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
3106 		    "emlxs_fct_send_ct_cmd: Unable to send packet.");
3107 
3108 		if (cmd_sbp->pkt_flags & PACKET_VALID) {
3109 			mutex_enter(&cmd_sbp->mtx);
3110 			cmd_sbp->fct_pkt = NULL;
3111 			cmd_sbp->fct_state = EMLXS_FCT_REQ_COMPLETE;
3112 			cmd_sbp->pkt_flags |= PACKET_RETURNED;
3113 			mutex_exit(&cmd_sbp->mtx);
3114 		}
3115 		emlxs_pkt_free(pkt);
3116 		return (FCT_FAILURE);
3117 	}
3118 	return (FCT_SUCCESS);
3119 
3120 } /* emlxs_fct_send_ct_cmd() */
3121 
3122 
3123 /* FCT_NOT_FOUND & FCT_ABORT_SUCCESS indicates IO is done */
3124 /* FCT_SUCCESS indicates abort will occur asyncronously */
3125 static fct_status_t
3126 emlxs_fct_abort(fct_local_port_t *fct_port, fct_cmd_t *fct_cmd, uint32_t flags)
3127 {
3128 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
3129 	emlxs_hba_t *hba = HBA;
3130 	emlxs_buf_t *cmd_sbp;
3131 	uint32_t pkt_flags = 0;
3132 	emlxs_buf_t *sbp = NULL;
3133 	IOCBQ *iocbq;
3134 	fct_status_t rval;
3135 
3136 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3137 
3138 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
3139 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3140 		    "emlxs_fct_abort: Invalid cmd_sbp=%p.", cmd_sbp);
3141 
3142 		return (FCT_NOT_FOUND);
3143 	}
3144 	mutex_enter(&cmd_sbp->mtx);
3145 
3146 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
3147 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3148 		    "emlxs_fct_abort: Invalid cmd_sbp=%p.", cmd_sbp);
3149 
3150 		mutex_exit(&cmd_sbp->mtx);
3151 		return (FCT_NOT_FOUND);
3152 	}
3153 	if (flags & FCT_IOF_FORCE_FCA_DONE) {
3154 		fct_cmd->cmd_handle = 0;
3155 	}
3156 	TGTPORTSTAT.FctAbortSent++;
3157 	TGTPORTSTAT.FctOutstandingIO--;
3158 
3159 	switch (cmd_sbp->fct_state) {
3160 	case 0:
3161 	case EMLXS_FCT_REQ_CREATED:
3162 	case EMLXS_FCT_REG_PENDING:
3163 
3164 	case EMLXS_FCT_REG_COMPLETE:
3165 	case EMLXS_FCT_REQ_COMPLETE:
3166 	case EMLXS_FCT_DATA_COMPLETE:
3167 	case EMLXS_FCT_STATUS_COMPLETE:
3168 	case EMLXS_FCT_RSP_COMPLETE:
3169 
3170 		cmd_sbp->fct_flags |=
3171 		    (EMLXS_FCT_ABORT | EMLXS_FCT_ABORT_COMPLETE);
3172 
3173 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3174 		    "emlxs_fct_abort: Aborted. cmd_sbp=%p state=%d "
3175 		    "flags=%x,%x,%x,%x", cmd_sbp, cmd_sbp->fct_state,
3176 		    flags, cmd_sbp->fct_flags, cmd_sbp->pkt_flags, pkt_flags);
3177 
3178 		/* mutex_exit(&cmd_sbp->mtx); */
3179 		(void) emlxs_fct_cmd_uninit(port, fct_cmd);
3180 
3181 		fct_cmd->cmd_comp_status = FCT_ABORT_SUCCESS;
3182 		return (FCT_ABORT_SUCCESS);
3183 
3184 
3185 	case EMLXS_FCT_CMD_RECEIVED:
3186 
3187 		cmd_sbp->fct_flags |=
3188 		    (EMLXS_FCT_ABORT | EMLXS_FCT_ABORT_COMPLETE);
3189 
3190 		/* Create the abort IOCB */
3191 		if (hba->state >= FC_LINK_UP) {
3192 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3193 			    "emlxs_fct_abort: Aborted. xid=%x. cmd_sbp=%p "
3194 			    "state=%d flags=%x,%x,%x", fct_cmd->cmd_rxid,
3195 			    cmd_sbp, cmd_sbp->fct_state, flags,
3196 			    cmd_sbp->fct_flags, cmd_sbp->pkt_flags);
3197 
3198 			iocbq = emlxs_create_abort_xri_cx(port, cmd_sbp->node,
3199 			    fct_cmd->cmd_rxid, cmd_sbp->ring, cmd_sbp->class,
3200 			    ABORT_TYPE_ABTS);
3201 		} else {
3202 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3203 			    "emlxs_fct_abort: Closed. xid=%x. cmd_sbp=%p "
3204 			    "state=%d flags=%x,%x,%x", fct_cmd->cmd_rxid,
3205 			    cmd_sbp, cmd_sbp->fct_state, flags,
3206 			    cmd_sbp->fct_flags, cmd_sbp->pkt_flags);
3207 
3208 			iocbq = emlxs_create_close_xri_cx(port, cmd_sbp->node,
3209 			    fct_cmd->cmd_rxid, cmd_sbp->ring);
3210 		}
3211 
3212 		cmd_sbp->abort_attempts++;
3213 		emlxs_issue_iocb_cmd(hba, cmd_sbp->ring, iocbq);
3214 
3215 		/* mutex_exit(&cmd_sbp->mtx); */
3216 		(void) emlxs_fct_cmd_uninit(port, fct_cmd);
3217 
3218 		fct_cmd->cmd_comp_status = FCT_ABORT_SUCCESS;
3219 		return (FCT_ABORT_SUCCESS);
3220 
3221 
3222 	case EMLXS_FCT_REQ_PENDING:
3223 	case EMLXS_FCT_STATUS_PENDING:
3224 	case EMLXS_FCT_RSP_PENDING:
3225 
3226 		sbp = (emlxs_buf_t *)cmd_sbp->fct_pkt->pkt_fca_private;
3227 		cmd_sbp->fct_flags |= EMLXS_FCT_ABORT;
3228 		mutex_exit(&cmd_sbp->mtx);
3229 
3230 		(void) emlxs_fct_pkt_abort(port, sbp);
3231 
3232 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3233 		    "emlxs_fct_abort: Aborted. cmd_sbp=%p state=%d "
3234 		    "flags=%x,%x,%x", cmd_sbp, cmd_sbp->fct_state, flags,
3235 		    cmd_sbp->fct_flags, cmd_sbp->pkt_flags);
3236 
3237 		if (cmd_sbp->pkt_flags & PACKET_VALID) {
3238 			mutex_enter(&cmd_sbp->mtx);
3239 			/* mutex_exit(&cmd_sbp->mtx); */
3240 			(void) emlxs_fct_cmd_uninit(port, fct_cmd);
3241 		}
3242 		fct_cmd->cmd_comp_status = FCT_ABORT_SUCCESS;
3243 		return (FCT_ABORT_SUCCESS);
3244 
3245 	case EMLXS_FCT_DATA_PENDING:
3246 
3247 		if ((cmd_sbp->pkt_flags & (PACKET_IN_COMPLETION |
3248 		    PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
3249 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3250 			    "emlxs_fct_abort: Completing. cmd_sbp=%p state=%d "
3251 			    "flags=%x,%x,%x", cmd_sbp, cmd_sbp->fct_state,
3252 			    flags, cmd_sbp->fct_flags, cmd_sbp->pkt_flags);
3253 
3254 			mutex_exit(&cmd_sbp->mtx);
3255 			return (FCT_NOT_FOUND);
3256 		}
3257 		cmd_sbp->fct_flags |= EMLXS_FCT_ABORT;
3258 		mutex_exit(&cmd_sbp->mtx);
3259 
3260 		rval = emlxs_fct_pkt_abort(port, cmd_sbp);
3261 
3262 		if (rval == FCT_ABORT_SUCCESS) {
3263 			fct_cmd->cmd_comp_status = FCT_ABORT_SUCCESS;
3264 
3265 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3266 			    "emlxs_fct_abort: Aborted. cmd_sbp=%p state=%d "
3267 			    "flags=%x,%x,%x", cmd_sbp, cmd_sbp->fct_state,
3268 			    flags, cmd_sbp->fct_flags, cmd_sbp->pkt_flags);
3269 
3270 			if (cmd_sbp->pkt_flags & PACKET_VALID) {
3271 				mutex_enter(&cmd_sbp->mtx);
3272 				/* mutex_exit(&cmd_sbp->mtx); */
3273 				(void) emlxs_fct_cmd_uninit(port, fct_cmd);
3274 			}
3275 		} else {
3276 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3277 			    "emlxs_fct_abort: Not found. cmd_sbp=%p state=%d "
3278 			    "flags=%x,%x,%x", cmd_sbp, cmd_sbp->fct_state,
3279 			    flags, cmd_sbp->fct_flags, cmd_sbp->pkt_flags);
3280 		}
3281 
3282 		return (rval);
3283 
3284 	}	/* switch */
3285 
3286 	return (FCT_SUCCESS);
3287 
3288 } /* emlxs_fct_abort() */
3289 
3290 
3291 /* Returns FCT_ABORT_SUCCESS or FCT_NOT_FOUND */
3292 static fct_status_t
3293 emlxs_fct_pkt_abort(emlxs_port_t *port, emlxs_buf_t *sbp)
3294 {
3295 	emlxs_hba_t *hba = HBA;
3296 
3297 	NODELIST *nlp;
3298 	uint8_t ringno;
3299 	RING *rp;
3300 	clock_t timeout;
3301 	clock_t time;
3302 	int32_t pkt_ret;
3303 	IOCBQ *iocbq;
3304 	IOCBQ *next;
3305 	IOCBQ *prev;
3306 	uint32_t found;
3307 	uint32_t att_bit;
3308 	uint32_t pass = 0;
3309 	fct_cmd_t *fct_cmd;
3310 	emlxs_buf_t *cmd_sbp;
3311 
3312 	fct_cmd = sbp->fct_cmd;
3313 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3314 
3315 	iocbq = &sbp->iocbq;
3316 	nlp = (NODELIST *)sbp->node;
3317 	rp = (RING *)sbp->ring;
3318 	ringno = (rp) ? rp->ringno : 0;
3319 
3320 	/* Check packet */
3321 	if (!(sbp->pkt_flags & PACKET_VALID) ||
3322 	    (sbp->pkt_flags & PACKET_RETURNED)) {
3323 		/*
3324 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3325 		 * "emlxs_fct_pkt_abort: 1. sbp=%p flags=%x,%x", sbp,
3326 		 * cmd_sbp->fct_flags, sbp->pkt_flags);
3327 		 */
3328 
3329 		return (FCT_NOT_FOUND);
3330 	}
3331 	mutex_enter(&sbp->mtx);
3332 
3333 	/* Check again if we still own this */
3334 	if (!(sbp->pkt_flags & PACKET_VALID) ||
3335 	    (sbp->pkt_flags & PACKET_RETURNED)) {
3336 		/*
3337 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3338 		 * "emlxs_fct_pkt_abort: 2. sbp=%p flags=%x,%x", sbp,
3339 		 * cmd_sbp->fct_flags, sbp->pkt_flags);
3340 		 */
3341 
3342 		mutex_exit(&sbp->mtx);
3343 		return (FCT_NOT_FOUND);
3344 	}
3345 	sbp->pkt_flags |= PACKET_IN_ABORT;
3346 
3347 	/* Check again if we still own this */
3348 	if (sbp->pkt_flags &
3349 	    (PACKET_IN_COMPLETION | PACKET_IN_FLUSH | PACKET_IN_TIMEOUT)) {
3350 		/*
3351 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3352 		 * "emlxs_fct_pkt_abort: 3. sbp=%p flags=%x,%x", sbp,
3353 		 * cmd_sbp->fct_flags, sbp->pkt_flags);
3354 		 */
3355 
3356 		mutex_exit(&sbp->mtx);
3357 		goto done;
3358 	}
3359 	mutex_exit(&sbp->mtx);
3360 
3361 begin:
3362 	pass++;
3363 
3364 	/* Check the transmit queue */
3365 	mutex_enter(&EMLXS_RINGTX_LOCK);
3366 
3367 	if (sbp->pkt_flags & PACKET_IN_TXQ) {
3368 		/* Find it on the queue */
3369 		found = 0;
3370 		if (iocbq->flag & IOCB_PRIORITY) {
3371 			/* Search the priority queue */
3372 			prev = NULL;
3373 			next = (IOCBQ *)nlp->nlp_ptx[ringno].q_first;
3374 
3375 			while (next) {
3376 				if (next == iocbq) {
3377 					/* Remove it */
3378 					if (prev) {
3379 						prev->next = iocbq->next;
3380 					}
3381 					if (nlp->nlp_ptx[ringno].q_last ==
3382 					    (void *)iocbq) {
3383 						nlp->nlp_ptx[ringno].q_last =
3384 						    (void *)prev;
3385 					}
3386 					if (nlp->nlp_ptx[ringno].q_first ==
3387 					    (void *)iocbq) {
3388 						nlp->nlp_ptx[ringno].q_first =
3389 						    (void *)iocbq->next;
3390 					}
3391 					nlp->nlp_ptx[ringno].q_cnt--;
3392 					iocbq->next = NULL;
3393 					found = 1;
3394 					break;
3395 				}
3396 				prev = next;
3397 				next = next->next;
3398 			}
3399 		} else {
3400 			/* Search the normal queue */
3401 			prev = NULL;
3402 			next = (IOCBQ *)nlp->nlp_tx[ringno].q_first;
3403 
3404 			while (next) {
3405 				if (next == iocbq) {
3406 					/* Remove it */
3407 					if (prev) {
3408 						prev->next = iocbq->next;
3409 					}
3410 					if (nlp->nlp_tx[ringno].q_last ==
3411 					    (void *)iocbq) {
3412 						nlp->nlp_tx[ringno].q_last =
3413 						    (void *)prev;
3414 					}
3415 					if (nlp->nlp_tx[ringno].q_first ==
3416 					    (void *)iocbq) {
3417 						nlp->nlp_tx[ringno].q_first =
3418 						    (void *)iocbq->next;
3419 					}
3420 					nlp->nlp_tx[ringno].q_cnt--;
3421 					iocbq->next = NULL;
3422 					found = 1;
3423 					break;
3424 				}
3425 				prev = next;
3426 				next = (IOCBQ *)next->next;
3427 			}
3428 		}
3429 
3430 		if (!found) {
3431 			/*
3432 			 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3433 			 * "emlxs_fct_pkt_abort: 4. sbp=%p flags=%x,%x", sbp,
3434 			 * cmd_sbp->fct_flags, sbp->pkt_flags);
3435 			 */
3436 
3437 			goto done;
3438 		}
3439 		/* Check if node still needs servicing */
3440 		if ((nlp->nlp_ptx[ringno].q_first) ||
3441 		    (nlp->nlp_tx[ringno].q_first &&
3442 		    !(nlp->nlp_flag[ringno] & NLP_CLOSED))) {
3443 
3444 			/*
3445 			 * If this is the base node, then don't shift the
3446 			 * pointers
3447 			 */
3448 			/* We want to drain the base node before moving on */
3449 			if (!nlp->nlp_base) {
3450 				/*
3451 				 * Just shift ring queue pointers to next
3452 				 * node
3453 				 */
3454 				rp->nodeq.q_last = (void *)nlp;
3455 				rp->nodeq.q_first = nlp->nlp_next[ringno];
3456 			}
3457 		} else {
3458 			/* Remove node from ring queue */
3459 
3460 			/* If this is the last node on list */
3461 			if (rp->nodeq.q_last == (void *)nlp) {
3462 				rp->nodeq.q_last = NULL;
3463 				rp->nodeq.q_first = NULL;
3464 				rp->nodeq.q_cnt = 0;
3465 			} else {
3466 				/* Remove node from head */
3467 				rp->nodeq.q_first = nlp->nlp_next[ringno];
3468 				((NODELIST *)rp->nodeq.q_last)->
3469 				    nlp_next[ringno] = rp->nodeq.q_first;
3470 				rp->nodeq.q_cnt--;
3471 			}
3472 
3473 			/* Clear node */
3474 			nlp->nlp_next[ringno] = NULL;
3475 		}
3476 
3477 		mutex_enter(&sbp->mtx);
3478 
3479 		if (sbp->pkt_flags & PACKET_IN_TXQ) {
3480 			sbp->pkt_flags &= ~PACKET_IN_TXQ;
3481 			hba->ring_tx_count[ringno]--;
3482 		}
3483 		mutex_exit(&sbp->mtx);
3484 
3485 		(void) emlxs_unregister_pkt(rp, sbp->iotag, 0);
3486 
3487 		mutex_exit(&EMLXS_RINGTX_LOCK);
3488 
3489 		/*
3490 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3491 		 * "emlxs_fct_pkt_abort: 5. sbp=%p flags=%x,%x", sbp,
3492 		 * cmd_sbp->fct_flags, sbp->pkt_flags);
3493 		 */
3494 
3495 		/* Now complete it */
3496 		if (sbp->pkt) {
3497 			emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
3498 			    IOERR_ABORT_REQUESTED, 1);
3499 		}
3500 		goto done;
3501 	}
3502 	mutex_exit(&EMLXS_RINGTX_LOCK);
3503 
3504 
3505 	/* Check the chip queue */
3506 	mutex_enter(&EMLXS_FCTAB_LOCK(ringno));
3507 
3508 	if ((sbp->pkt_flags & PACKET_IN_CHIPQ) &&
3509 	    !(sbp->pkt_flags & PACKET_XRI_CLOSED) &&
3510 	    (sbp == rp->fc_table[sbp->iotag])) {
3511 		/* Create the abort IOCB */
3512 		if (hba->state >= FC_LINK_UP) {
3513 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3514 			    "emlxs_fct_pkt_abort: Aborting. sbp=%p "
3515 			    "flags=%x,%x", sbp, cmd_sbp->fct_flags,
3516 			    sbp->pkt_flags);
3517 
3518 			iocbq = emlxs_create_abort_xri_cn(port, sbp->node,
3519 			    sbp->iotag, rp, sbp->class, ABORT_TYPE_ABTS);
3520 
3521 			mutex_enter(&sbp->mtx);
3522 			sbp->pkt_flags |= PACKET_XRI_CLOSED;
3523 			sbp->ticks = hba->timer_tics + (4 * hba->fc_ratov) + 10;
3524 			sbp->abort_attempts++;
3525 			mutex_exit(&sbp->mtx);
3526 		} else {
3527 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3528 			    "emlxs_fct_pkt_abort: Closing. sbp=%p flags=%x,%x",
3529 			    sbp, cmd_sbp->fct_flags, sbp->pkt_flags);
3530 
3531 			iocbq = emlxs_create_close_xri_cn(port, sbp->node,
3532 			    sbp->iotag, rp);
3533 
3534 			mutex_enter(&sbp->mtx);
3535 			sbp->pkt_flags |= PACKET_XRI_CLOSED;
3536 			sbp->ticks = hba->timer_tics + 30;
3537 			sbp->abort_attempts++;
3538 			mutex_exit(&sbp->mtx);
3539 		}
3540 
3541 		mutex_exit(&EMLXS_FCTAB_LOCK(ringno));
3542 
3543 		/* Send this iocbq */
3544 		if (iocbq) {
3545 			emlxs_issue_iocb_cmd(hba, rp, iocbq);
3546 			iocbq = NULL;
3547 		}
3548 		goto done;
3549 	}
3550 	mutex_exit(&EMLXS_FCTAB_LOCK(ringno));
3551 
3552 
3553 	/* Pkt was not on any queues */
3554 
3555 	/* Check again if we still own this */
3556 	if (!(sbp->pkt_flags & PACKET_VALID) ||
3557 	    (sbp->pkt_flags & (PACKET_RETURNED | PACKET_IN_COMPLETION |
3558 	    PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
3559 		/*
3560 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3561 		 * "emlxs_fct_pkt_abort: 9. sbp=%p flags=%x,%x", sbp,
3562 		 * cmd_sbp->fct_flags, sbp->pkt_flags);
3563 		 */
3564 
3565 		goto done;
3566 	}
3567 	/* Apparently the pkt was not found.  Let's delay and try again */
3568 	if (pass < 5) {
3569 		delay(drv_usectohz(5000000));	/* 5 seconds */
3570 
3571 		/* Check packet */
3572 		if (!(sbp->pkt_flags & PACKET_VALID) ||
3573 		    (sbp->pkt_flags & (PACKET_RETURNED | PACKET_IN_COMPLETION |
3574 		    PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
3575 
3576 			/*
3577 			 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3578 			 * "emlxs_fct_pkt_abort: 10. sbp=%p flags=%x,%x",
3579 			 * sbp, cmd_sbp->fct_flags, sbp->pkt_flags);
3580 			 */
3581 
3582 			goto done;
3583 		}
3584 		goto begin;
3585 	}
3586 force_it:
3587 
3588 	/* Force the completion now */
3589 	/*
3590 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3591 	 * "emlxs_fct_pkt_abort: 11. sbp=%p flags=%x,%x", sbp,
3592 	 * cmd_sbp->fct_flags, sbp->pkt_flags);
3593 	 */
3594 
3595 	/* Unregister the pkt */
3596 	(void) emlxs_unregister_pkt(rp, sbp->iotag, 1);
3597 
3598 	/* Now complete it */
3599 	if (sbp->pkt) {
3600 		emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
3601 		    IOERR_ABORT_REQUESTED, 1);
3602 	}
3603 done:
3604 
3605 	/* Now wait for the pkt to complete */
3606 	if (!(cmd_sbp->fct_flags & EMLXS_FCT_ABORT_COMPLETE)) {
3607 		/* Set thread timeout */
3608 		timeout = emlxs_timeout(hba, 30);
3609 
3610 		/* Check for panic situation */
3611 		if (ddi_in_panic()) {
3612 			/*
3613 			 * In panic situations there will be one thread with
3614 			 * no interrrupts (hard or soft) and no timers
3615 			 */
3616 
3617 			/*
3618 			 * We must manually poll everything in this thread to
3619 			 * keep the driver going.
3620 			 */
3621 
3622 			rp = (emlxs_ring_t *)sbp->ring;
3623 			switch (rp->ringno) {
3624 			case FC_FCP_RING:
3625 				att_bit = HA_R0ATT;
3626 				break;
3627 
3628 			case FC_IP_RING:
3629 				att_bit = HA_R1ATT;
3630 				break;
3631 
3632 			case FC_ELS_RING:
3633 				att_bit = HA_R2ATT;
3634 				break;
3635 
3636 			case FC_CT_RING:
3637 				att_bit = HA_R3ATT;
3638 				break;
3639 			}
3640 
3641 			/* Keep polling the chip until our IO is completed */
3642 			(void) drv_getparm(LBOLT, &time);
3643 			while ((time < timeout) &&
3644 			    !(cmd_sbp->fct_flags & EMLXS_FCT_ABORT_COMPLETE)) {
3645 				emlxs_poll_intr(hba, att_bit);
3646 				(void) drv_getparm(LBOLT, &time);
3647 			}
3648 		} else {
3649 			/* Wait for IO completion or timeout */
3650 			mutex_enter(&EMLXS_PKT_LOCK);
3651 			pkt_ret = 0;
3652 			while ((pkt_ret != -1) &&
3653 			    !(cmd_sbp->fct_flags & EMLXS_FCT_ABORT_COMPLETE)) {
3654 				pkt_ret = cv_timedwait(&EMLXS_PKT_CV,
3655 				    &EMLXS_PKT_LOCK, timeout);
3656 			}
3657 			mutex_exit(&EMLXS_PKT_LOCK);
3658 		}
3659 
3660 		/*
3661 		 * Check if timeout occured.  This is not good.  Something
3662 		 * happened to our IO.
3663 		 */
3664 		if (!(cmd_sbp->fct_flags & EMLXS_FCT_ABORT_COMPLETE)) {
3665 			/* Force the completion now */
3666 			goto force_it;
3667 		}
3668 	}
3669 	/*
3670 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3671 	 * "emlxs_fct_pkt_abort: 12. sbp=%p flags=%x,%x", sbp,
3672 	 * cmd_sbp->fct_flags, sbp->pkt_flags);
3673 	 */
3674 
3675 	return (FCT_ABORT_SUCCESS);
3676 
3677 } /* emlxs_fct_pkt_abort() */
3678 
3679 
3680 
3681 static uint32_t
3682 emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
3683 {
3684 	emlxs_hba_t *hba = HBA;
3685 	uint32_t sgllen = 1;
3686 	uint32_t rval;
3687 	uint32_t size;
3688 	uint32_t count;
3689 	uint32_t resid;
3690 	struct stmf_sglist_ent *sgl;
3691 
3692 	size = sbp->fct_buf->db_data_size;
3693 	count = sbp->fct_buf->db_sglist_length;
3694 	sgl = sbp->fct_buf->db_sglist;
3695 	resid = size;
3696 
3697 	for (sgllen = 0; sgllen < count && resid > 0; sgllen++) {
3698 		resid -= MIN(resid, sgl->seg_length);
3699 		sgl++;
3700 	}
3701 
3702 	if (resid > 0) {
3703 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
3704 		    "emlxs_fct_bde_setup: Not enough scatter gather buffers "
3705 		    "provided. size=%d resid=%d count=%d", size, resid, count);
3706 		return (1);
3707 	}
3708 #ifdef SLI3_SUPPORT
3709 	if ((hba->sli_mode < 3) || (sgllen > SLI3_MAX_BDE)) {
3710 		rval = emlxs_fct_sli2_bde_setup(port, sbp);
3711 	} else {
3712 		rval = emlxs_fct_sli3_bde_setup(port, sbp);
3713 	}
3714 #else	/* !SLI3_SUPPORT */
3715 	rval = emlxs_fct_sli2_bde_setup(port, sbp);
3716 #endif	/* SLI3_SUPPORT */
3717 
3718 	return (rval);
3719 
3720 } /* emlxs_fct_bde_setup() */
3721 
3722 
3723 
3724 /* Only used for FCP Data xfers */
3725 static uint32_t
3726 emlxs_fct_sli2_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
3727 {
3728 	emlxs_hba_t *hba = HBA;
3729 	scsi_task_t *fct_task;
3730 	MATCHMAP *bmp;
3731 	ULP_BDE64 *bpl;
3732 	uint64_t bp;
3733 	uint8_t bdeFlags;
3734 	IOCB *iocb;
3735 	uint32_t resid;
3736 	uint32_t count;
3737 	uint32_t size;
3738 	uint32_t sgllen;
3739 	struct stmf_sglist_ent *sgl;
3740 	emlxs_fct_dmem_bctl_t *bctl;
3741 
3742 	iocb = (IOCB *)&sbp->iocbq;
3743 	sbp->bmp = NULL;
3744 
3745 	if (!sbp->fct_buf) {
3746 		iocb->un.fcpt64.bdl.addrHigh = 0;
3747 		iocb->un.fcpt64.bdl.addrLow = 0;
3748 		iocb->un.fcpt64.bdl.bdeSize = 0;
3749 		iocb->un.fcpt64.bdl.bdeFlags = 0;
3750 		iocb->un.fcpt64.fcpt_Offset = 0;
3751 		iocb->un.fcpt64.fcpt_Length = 0;
3752 		iocb->ulpBdeCount = 0;
3753 		iocb->ulpLe = 1;
3754 		return (0);
3755 	}
3756 #ifdef EMLXS_SPARC
3757 	/* Use FCP MEM_BPL table to get BPL buffer */
3758 	bmp = &hba->fcp_bpl_table[sbp->iotag];
3759 #else
3760 	/* Use MEM_BPL pool to get BPL buffer */
3761 	bmp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BPL);
3762 #endif	/* EMLXS_SPARC */
3763 
3764 	if (!bmp) {
3765 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
3766 		    "emlxs_fct_sli2_bde_setup: Unable to BPL buffer. iotag=%x",
3767 		    sbp->iotag);
3768 
3769 		iocb->un.fcpt64.bdl.addrHigh = 0;
3770 		iocb->un.fcpt64.bdl.addrLow = 0;
3771 		iocb->un.fcpt64.bdl.bdeSize = 0;
3772 		iocb->un.fcpt64.bdl.bdeFlags = 0;
3773 		iocb->un.fcpt64.fcpt_Offset = 0;
3774 		iocb->un.fcpt64.fcpt_Length = 0;
3775 		iocb->ulpBdeCount = 0;
3776 		iocb->ulpLe = 1;
3777 		return (1);
3778 	}
3779 	bpl = (ULP_BDE64 *) bmp->virt;
3780 	bp = bmp->phys;
3781 
3782 	fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific;
3783 
3784 	/* size = fct_task->task_cmd_xfer_length; */
3785 	size = sbp->fct_buf->db_data_size;
3786 	count = sbp->fct_buf->db_sglist_length;
3787 	bctl = (emlxs_fct_dmem_bctl_t *)sbp->fct_buf->db_port_private;
3788 
3789 	bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0;
3790 	sgl = sbp->fct_buf->db_sglist;
3791 	resid = size;
3792 
3793 	/* Init the buffer list */
3794 	for (sgllen = 0; sgllen < count && resid > 0; sgllen++) {
3795 		bpl->addrHigh =
3796 		    PCIMEM_LONG((uint32_t)putPaddrHigh(bctl->bctl_dev_addr));
3797 		bpl->addrLow =
3798 		    PCIMEM_LONG((uint32_t)putPaddrLow(bctl->bctl_dev_addr));
3799 		bpl->tus.f.bdeSize = MIN(resid, sgl->seg_length);
3800 		bpl->tus.f.bdeFlags = bdeFlags;
3801 		bpl->tus.w = PCIMEM_LONG(bpl->tus.w);
3802 		bpl++;
3803 
3804 		resid -= MIN(resid, sgl->seg_length);
3805 		sgl++;
3806 	}
3807 
3808 	/* Init the IOCB */
3809 	iocb->un.fcpt64.bdl.addrHigh = (uint32_t)putPaddrHigh(bp);
3810 	iocb->un.fcpt64.bdl.addrLow = (uint32_t)putPaddrLow(bp);
3811 	iocb->un.fcpt64.bdl.bdeSize = sgllen * sizeof (ULP_BDE64);
3812 	iocb->un.fcpt64.bdl.bdeFlags = BUFF_TYPE_BDL;
3813 
3814 	iocb->un.fcpt64.fcpt_Length =
3815 	    (fct_task->task_flags & TF_WRITE_DATA) ? size : 0;
3816 	iocb->un.fcpt64.fcpt_Offset = 0;
3817 
3818 	iocb->ulpBdeCount = 1;
3819 	iocb->ulpLe = 1;
3820 	sbp->bmp = bmp;
3821 
3822 	return (0);
3823 
3824 } /* emlxs_fct_sli2_bde_setup */
3825 
3826 
3827 
3828 #ifdef SLI3_SUPPORT
3829 
3830 /* ARGSUSED */
3831 static uint32_t
3832 emlxs_fct_sli3_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
3833 {
3834 	scsi_task_t *fct_task;
3835 	ULP_BDE64 *bde;
3836 	IOCB *iocb;
3837 	uint32_t size;
3838 	uint32_t count;
3839 	uint32_t sgllen;
3840 	int32_t resid;
3841 	struct stmf_sglist_ent *sgl;
3842 	uint32_t bdeFlags;
3843 	emlxs_fct_dmem_bctl_t *bctl;
3844 
3845 	iocb = (IOCB *)&sbp->iocbq;
3846 
3847 	if (!sbp->fct_buf) {
3848 		iocb->un.fcpt64.bdl.addrHigh = 0;
3849 		iocb->un.fcpt64.bdl.addrLow = 0;
3850 		iocb->un.fcpt64.bdl.bdeSize = 0;
3851 		iocb->un.fcpt64.bdl.bdeFlags = 0;
3852 		iocb->un.fcpt64.fcpt_Offset = 0;
3853 		iocb->un.fcpt64.fcpt_Length = 0;
3854 		iocb->ulpBdeCount = 0;
3855 		iocb->ulpLe = 0;
3856 		iocb->unsli3.ext_iocb.ebde_count = 0;
3857 		return (0);
3858 	}
3859 	fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific;
3860 
3861 	size = sbp->fct_buf->db_data_size;
3862 	count = sbp->fct_buf->db_sglist_length;
3863 	bctl = (emlxs_fct_dmem_bctl_t *)sbp->fct_buf->db_port_private;
3864 
3865 	bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0;
3866 	sgl = sbp->fct_buf->db_sglist;
3867 	resid = size;
3868 
3869 	/* Init first BDE */
3870 	iocb->un.fcpt64.bdl.addrHigh = putPaddrHigh(bctl->bctl_dev_addr);
3871 	iocb->un.fcpt64.bdl.addrLow = putPaddrLow(bctl->bctl_dev_addr);
3872 	iocb->un.fcpt64.bdl.bdeSize = MIN(resid, sgl->seg_length);
3873 	iocb->un.fcpt64.bdl.bdeFlags = bdeFlags;
3874 	resid -= MIN(resid, sgl->seg_length);
3875 	sgl++;
3876 
3877 	/* Init remaining BDE's */
3878 	bde = (ULP_BDE64 *) & iocb->unsli3.ext_iocb.ebde1;
3879 	for (sgllen = 1; sgllen < count && resid > 0; sgllen++) {
3880 		bde->addrHigh = putPaddrHigh(bctl->bctl_dev_addr);
3881 		bde->addrLow = putPaddrLow(bctl->bctl_dev_addr);
3882 		bde->tus.f.bdeSize = MIN(resid, sgl->seg_length);
3883 		bde->tus.f.bdeFlags = bdeFlags;
3884 		bde++;
3885 
3886 		resid -= MIN(resid, sgl->seg_length);
3887 		sgl++;
3888 	}
3889 
3890 	iocb->unsli3.ext_iocb.ebde_count = sgllen - 1;
3891 	iocb->un.fcpt64.fcpt_Length =
3892 	    (fct_task->task_flags & TF_WRITE_DATA) ? size : 0;
3893 	iocb->un.fcpt64.fcpt_Offset = 0;
3894 
3895 	iocb->ulpBdeCount = 0;
3896 	iocb->ulpLe = 0;
3897 
3898 	return (0);
3899 
3900 } /* emlxs_fct_sli3_bde_setup */
3901 
3902 #endif	/* SLI3_SUPPORT */
3903 
3904 
3905 extern void
3906 emlxs_fct_link_up(emlxs_port_t *port)
3907 {
3908 	emlxs_hba_t *hba = HBA;
3909 
3910 	mutex_enter(&EMLXS_PORT_LOCK);
3911 
3912 	if (port->fct_port &&
3913 	    (port->fct_flags & FCT_STATE_PORT_ONLINE) &&
3914 	    !(port->fct_flags & FCT_STATE_LINK_UP)) {
3915 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3916 		    "emlxs_fct_link_up event.");
3917 
3918 		port->fct_flags |= FCT_STATE_LINK_UP;
3919 
3920 		mutex_exit(&EMLXS_PORT_LOCK);
3921 
3922 #ifdef FCT_API_TRACE
3923 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3924 		    "fct_handle_event LINK_UP");
3925 #endif	/* FCT_API_TRACE */
3926 		MODSYM(fct_handle_event) (port->fct_port,
3927 		    FCT_EVENT_LINK_UP, 0, 0);
3928 
3929 		emlxs_fct_unsol_flush(port);
3930 	} else {
3931 		if (!hba->ini_mode &&
3932 		    !(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
3933 			mutex_exit(&EMLXS_PORT_LOCK);
3934 
3935 			/* Take link down and hold it down */
3936 			(void) emlxs_reset_link(hba, 0);
3937 		} else {
3938 			mutex_exit(&EMLXS_PORT_LOCK);
3939 		}
3940 	}
3941 
3942 	return;
3943 
3944 } /* emlxs_fct_link_up() */
3945 
3946 extern void
3947 emlxs_fct_link_down(emlxs_port_t *port)
3948 {
3949 	emlxs_hba_t *hba = HBA;
3950 
3951 	mutex_enter(&EMLXS_PORT_LOCK);
3952 
3953 	if (port->fct_port &&
3954 	    (port->fct_flags & FCT_STATE_PORT_ONLINE) &&
3955 	    (port->fct_flags & FCT_STATE_LINK_UP)) {
3956 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3957 		    "emlxs_fct_link_down event.");
3958 
3959 		port->fct_flags &= ~FCT_STATE_LINK_UP;
3960 
3961 		mutex_exit(&EMLXS_PORT_LOCK);
3962 
3963 #ifdef FCT_API_TRACE
3964 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3965 		    "fct_handle_event LINK_DOWN");
3966 #endif	/* FCT_API_TRACE */
3967 		MODSYM(fct_handle_event) (port->fct_port,
3968 		    FCT_EVENT_LINK_DOWN, 0, 0);
3969 	} else {
3970 		mutex_exit(&EMLXS_PORT_LOCK);
3971 	}
3972 
3973 	return;
3974 
3975 } /* emlxs_fct_link_down() */
3976 
3977 
3978 
3979 /*
3980  * DMA FUNCTIONS
3981  */
3982 
3983 
3984 fct_status_t
3985 emlxs_fct_dmem_init(emlxs_port_t *port)
3986 {
3987 	emlxs_hba_t *hba = HBA;
3988 	emlxs_fct_dmem_bucket_t *p;
3989 	emlxs_fct_dmem_bctl_t *bctl;
3990 	emlxs_fct_dmem_bctl_t *bc;
3991 	emlxs_fct_dmem_bctl_t *prev;
3992 	int32_t j;
3993 	int32_t i;
3994 	uint32_t total_mem;
3995 	uint8_t *addr;
3996 	uint8_t *host_addr;
3997 	uint64_t dev_addr;
3998 	ddi_dma_cookie_t cookie;
3999 	uint32_t ncookie;
4000 	uint32_t bsize;
4001 	size_t len;
4002 	char buf[64];
4003 	ddi_device_acc_attr_t acc;
4004 
4005 	bzero(&acc, sizeof (acc));
4006 	acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
4007 	acc.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
4008 	acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
4009 
4010 	p = port->dmem_bucket;
4011 	for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) {
4012 		if (!p->dmem_nbufs) {
4013 			continue;
4014 		}
4015 		bctl = (emlxs_fct_dmem_bctl_t *)kmem_zalloc(p->dmem_nbufs *
4016 		    sizeof (emlxs_fct_dmem_bctl_t), KM_NOSLEEP);
4017 
4018 		if (bctl == NULL) {
4019 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4020 			    "emlxs_fct_dmem_init: Unable to allocate bctl.");
4021 			goto alloc_bctl_failed;
4022 		}
4023 		p->dmem_bctls_mem = bctl;
4024 
4025 		if (ddi_dma_alloc_handle(hba->dip, &emlxs_dma_attr_1sg,
4026 		    DDI_DMA_SLEEP, 0, &p->dmem_dma_handle) != DDI_SUCCESS) {
4027 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4028 			    "emlxs_fct_dmem_init: Unable to allocate handle.");
4029 			goto alloc_handle_failed;
4030 		}
4031 
4032 		total_mem = p->dmem_buf_size * p->dmem_nbufs;
4033 
4034 		if (ddi_dma_mem_alloc(p->dmem_dma_handle, total_mem, &acc,
4035 		    DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0, (caddr_t *)&addr,
4036 		    &len, &p->dmem_acc_handle) != DDI_SUCCESS) {
4037 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4038 			    "emlxs_fct_dmem_init: Unable to allocate memory.");
4039 			goto mem_alloc_failed;
4040 		}
4041 
4042 		if (ddi_dma_addr_bind_handle(p->dmem_dma_handle, NULL,
4043 		    (caddr_t)addr, total_mem, DDI_DMA_RDWR | DDI_DMA_STREAMING,
4044 		    DDI_DMA_DONTWAIT, 0, &cookie, &ncookie) != DDI_SUCCESS) {
4045 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4046 			    "emlxs_fct_dmem_init: Unable to bind handle.");
4047 			goto addr_bind_handle_failed;
4048 		}
4049 
4050 		if (ncookie != 1) {
4051 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4052 			    "emlxs_fct_dmem_init: DMEM init failed.");
4053 			goto dmem_init_failed;
4054 		}
4055 		(void) sprintf(buf, "%s%d_bucket%d mutex", DRIVER_NAME,
4056 		    hba->ddiinst, i);
4057 		mutex_init(&p->dmem_lock, buf, MUTEX_DRIVER,
4058 		    (void *)hba->intr_arg);
4059 
4060 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4061 		    "bufsize=%d cnt=%d", p->dmem_buf_size, p->dmem_nbufs);
4062 
4063 		host_addr = addr;
4064 		dev_addr = (uint64_t)cookie.dmac_laddress;
4065 
4066 		p->dmem_host_addr = addr;
4067 		p->dmem_dev_addr = dev_addr;
4068 		p->dmem_bctl_free_list = bctl;
4069 		p->dmem_nbufs_free = p->dmem_nbufs;
4070 		bsize = p->dmem_buf_size;
4071 
4072 		for (j = 0; j < p->dmem_nbufs; j++) {
4073 			stmf_data_buf_t *db;
4074 
4075 			db = MODSYM(stmf_alloc) (STMF_STRUCT_DATA_BUF, 0, 0);
4076 #ifdef FCT_API_TRACE
4077 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4078 			    "stmf_alloc data_buf %p", db);
4079 #endif	/* FCT_API_TRACE */
4080 			if (db == NULL) {
4081 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4082 				    "emlxs_fct_dmem_init: DMEM init: "
4083 				    "alloc failed.");
4084 				goto dmem_init_failed;
4085 			}
4086 			db->db_port_private = bctl;
4087 			db->db_sglist[0].seg_addr = host_addr;
4088 			db->db_sglist[0].seg_length = bsize;
4089 			db->db_buf_size = bsize;
4090 			db->db_sglist_length = 1;
4091 
4092 			bctl->bctl_bucket = p;
4093 			bctl->bctl_buf = db;
4094 			bctl->bctl_dev_addr = dev_addr;
4095 
4096 			host_addr += bsize;
4097 			dev_addr += bsize;
4098 
4099 			prev = bctl;
4100 			bctl++;
4101 			prev->bctl_next = bctl;
4102 		}
4103 
4104 		prev->bctl_next = NULL;
4105 	}
4106 
4107 	return (FCT_SUCCESS);
4108 
4109 dmem_failure_loop:
4110 	mutex_destroy(&p->dmem_lock);
4111 	bc = bctl;
4112 	while (bc) {
4113 #ifdef FCT_API_TRACE
4114 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4115 		    "stmf_free:3 %p", bctl->bctl_buf);
4116 #endif	/* FCT_API_TRACE */
4117 		MODSYM(stmf_free) (bc->bctl_buf);
4118 		bc = bc->bctl_next;
4119 	}
4120 
4121 dmem_init_failed:
4122 	(void) ddi_dma_unbind_handle(p->dmem_dma_handle);
4123 
4124 addr_bind_handle_failed:
4125 	(void) ddi_dma_mem_free(&p->dmem_acc_handle);
4126 
4127 mem_alloc_failed:
4128 	(void) ddi_dma_free_handle(&p->dmem_dma_handle);
4129 
4130 alloc_handle_failed:
4131 	kmem_free(p->dmem_bctls_mem,
4132 	    p->dmem_nbufs * sizeof (emlxs_fct_dmem_bctl_t));
4133 
4134 alloc_bctl_failed:
4135 	if (--i >= 0) {
4136 		p = &port->dmem_bucket[i];
4137 		bctl = p->dmem_bctl_free_list;
4138 		goto dmem_failure_loop;
4139 	}
4140 	return (FCT_FAILURE);
4141 
4142 } /* emlxs_fct_dmem_init() */
4143 
4144 
4145 
4146 void
4147 emlxs_fct_dmem_fini(emlxs_port_t *port)
4148 {
4149 	emlxs_fct_dmem_bucket_t *p;
4150 	emlxs_fct_dmem_bctl_t *bctl;
4151 	uint32_t i;
4152 
4153 	p = port->dmem_bucket;
4154 	for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) {
4155 		if (!p->dmem_nbufs) {
4156 			continue;
4157 		}
4158 		bctl = p->dmem_bctl_free_list;
4159 
4160 		while (bctl) {
4161 #ifdef FCT_API_TRACE
4162 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4163 			    "stmf_free:4 %p", bctl->bctl_buf);
4164 #endif	/* FCT_API_TRACE */
4165 			MODSYM(stmf_free) (bctl->bctl_buf);
4166 			bctl = bctl->bctl_next;
4167 		}
4168 
4169 		bctl = p->dmem_bctl_free_list;
4170 
4171 		(void) ddi_dma_unbind_handle(p->dmem_dma_handle);
4172 		(void) ddi_dma_mem_free(&p->dmem_acc_handle);
4173 		(void) ddi_dma_free_handle(&p->dmem_dma_handle);
4174 
4175 		kmem_free(p->dmem_bctls_mem,
4176 		    (p->dmem_nbufs * sizeof (emlxs_fct_dmem_bctl_t)));
4177 		mutex_destroy(&p->dmem_lock);
4178 	}
4179 
4180 	bzero((uint8_t *)port->dmem_bucket, sizeof (port->dmem_bucket));
4181 
4182 	return;
4183 
4184 } /* emlxs_fct_dmem_fini() */
4185 
4186 
4187 /* ARGSUSED */
4188 static stmf_data_buf_t *
4189 emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port, uint32_t size,
4190     uint32_t *pminsize, uint32_t flags)
4191 {
4192 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
4193 	emlxs_fct_dmem_bucket_t *p;
4194 	emlxs_fct_dmem_bctl_t *bctl;
4195 	uint32_t i;
4196 
4197 /*
4198  *	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4199  *	    "emlxs_fct_dbuf_alloc: size=%d min=%d", size, *pminsize);
4200  */
4201 
4202 	if (size > FCT_DMEM_MAX_BUF_SIZE) {
4203 		size = FCT_DMEM_MAX_BUF_SIZE;
4204 	}
4205 	p = port->dmem_bucket;
4206 	for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) {
4207 		if (!p->dmem_nbufs) {
4208 			continue;
4209 		}
4210 		if (p->dmem_buf_size >= size) {
4211 			mutex_enter(&p->dmem_lock);
4212 			if (p->dmem_nbufs_free) {
4213 				if (p->dmem_buf_size < *pminsize) {
4214 					*pminsize = p->dmem_buf_size;
4215 					TGTPORTSTAT.FctNoBuffer++;
4216 
4217 					EMLXS_MSGF(EMLXS_CONTEXT,
4218 					    &emlxs_fct_api_msg,
4219 					    "emlxs_fct_dbuf_alloc: Failed(1).");
4220 					mutex_exit(&p->dmem_lock);
4221 					return (NULL);
4222 				}
4223 				bctl = p->dmem_bctl_free_list;
4224 				if (bctl == NULL) {
4225 					mutex_exit(&p->dmem_lock);
4226 					continue;
4227 				}
4228 				p->dmem_bctl_free_list = bctl->bctl_next;
4229 				p->dmem_nbufs_free--;
4230 				bctl->bctl_buf->db_data_size = size;
4231 				mutex_exit(&p->dmem_lock);
4232 
4233 #ifdef FCT_API_TRACE
4234 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4235 				    "emlx_fct_buf_alloc size %p: %d",
4236 				    bctl->bctl_buf, size);
4237 #endif	/* FCT_API_TRACE */
4238 
4239 				return (bctl->bctl_buf);
4240 			}
4241 			mutex_exit(&p->dmem_lock);
4242 
4243 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4244 			    "emlx_fct_buf_alloc size %d Nothing free bck %d",
4245 			    size, i);
4246 		}
4247 	}
4248 
4249 	*pminsize = 0;
4250 	TGTPORTSTAT.FctNoBuffer++;
4251 
4252 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4253 	    "emlxs_fct_dbuf_alloc: Failed(2).");
4254 
4255 	return (NULL);
4256 
4257 } /* emlxs_fct_dbuf_alloc() */
4258 
4259 
4260 /* ARGSUSED */
4261 static void
4262 emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *dbuf)
4263 {
4264 	emlxs_fct_dmem_bctl_t *bctl =
4265 	    (emlxs_fct_dmem_bctl_t *)dbuf->db_port_private;
4266 	emlxs_fct_dmem_bucket_t *p = bctl->bctl_bucket;
4267 
4268 #ifdef FCT_API_TRACE
4269 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4270 	    "emlx_fct_buf_free %p", dbuf);
4271 #endif	/* FCT_API_TRACE */
4272 
4273 	mutex_enter(&p->dmem_lock);
4274 	bctl->bctl_next = p->dmem_bctl_free_list;
4275 	p->dmem_bctl_free_list = bctl;
4276 	p->dmem_nbufs_free++;
4277 	mutex_exit(&p->dmem_lock);
4278 
4279 } /* emlxs_fct_dbuf_free() */
4280 
4281 
4282 void
4283 emlxs_fct_dbuf_dma_sync(stmf_data_buf_t *dbuf, uint_t sync_type)
4284 {
4285 	emlxs_fct_dmem_bctl_t *bctl =
4286 	    (emlxs_fct_dmem_bctl_t *)dbuf->db_port_private;
4287 	emlxs_fct_dmem_bucket_t *p = bctl->bctl_bucket;
4288 
4289 	(void) ddi_dma_sync(p->dmem_dma_handle,
4290 	    (unsigned long)(bctl->bctl_dev_addr - p->dmem_dev_addr),
4291 	    dbuf->db_data_size, sync_type);
4292 
4293 } /* emlxs_fct_dbuf_dma_sync() */
4294 
4295 
4296 #endif	/* SFCT_SUPPORT */
4297