1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
88f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
98f23e9faSHans Rosenfeld  * http://www.opensource.org/licenses/cddl1.txt.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22fcf3ce44SJohn Forte /*
238f23e9faSHans Rosenfeld  * Copyright (c) 2004-2012 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25a988c0caSRick McNeal  * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
26a3170057SPaul Winder  * Copyright 2020 RackTop Systems, Inc.
27fcf3ce44SJohn Forte  */
28fcf3ce44SJohn Forte 
29291a2b48SSukumar Swaminathan #include <emlxs.h>
30fcf3ce44SJohn Forte 
31fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
32fcf3ce44SJohn Forte 
33fcf3ce44SJohn Forte 
34fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
35fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_FCT_C);
36fcf3ce44SJohn Forte 
378f23e9faSHans Rosenfeld static void emlxs_fct_memseg_init(emlxs_hba_t *hba);
388f23e9faSHans Rosenfeld 
3982527734SSukumar Swaminathan static fct_status_t emlxs_fct_cmd_acquire(emlxs_port_t *port,
4082527734SSukumar Swaminathan 	fct_cmd_t *fct_cmd, uint16_t fct_state);
4182527734SSukumar Swaminathan static fct_status_t emlxs_fct_cmd_accept(emlxs_port_t *port,
4282527734SSukumar Swaminathan 	fct_cmd_t *fct_cmd, uint16_t fct_state);
4382527734SSukumar Swaminathan static void emlxs_fct_cmd_release(emlxs_port_t *port, fct_cmd_t *fct_cmd,
4482527734SSukumar Swaminathan 	uint16_t fct_state);
45fcf3ce44SJohn Forte 
46291a2b48SSukumar Swaminathan static emlxs_buf_t *emlxs_fct_cmd_init(emlxs_port_t *port,
47a9800bebSGarrett D'Amore     fct_cmd_t *fct_cmd, uint16_t fct_state);
4882527734SSukumar Swaminathan static void emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd,
4982527734SSukumar Swaminathan 	uint16_t fct_state);
5082527734SSukumar Swaminathan static void emlxs_fct_cmd_post(emlxs_port_t *port, fct_cmd_t *fct_cmd,
5182527734SSukumar Swaminathan 	uint16_t fct_state);
52fcf3ce44SJohn Forte 
5382527734SSukumar Swaminathan static fct_status_t emlxs_fct_flogi_xchg(struct fct_local_port *fct_port,
54fcf3ce44SJohn Forte     struct fct_flogi_xchg *fx);
55fcf3ce44SJohn Forte static fct_status_t emlxs_fct_get_link_info(fct_local_port_t *fct_port,
56fcf3ce44SJohn Forte     fct_link_info_t *link);
57fcf3ce44SJohn Forte static fct_status_t emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port,
58fcf3ce44SJohn Forte     fct_remote_port_t *port_handle);
59fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_cmd(fct_cmd_t *fct_cmd);
60fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd,
61fcf3ce44SJohn Forte     stmf_data_buf_t *dbuf, uint32_t ioflags);
62291a2b48SSukumar Swaminathan static fct_status_t emlxs_fct_send_cmd_rsp(fct_cmd_t *fct_cmd, uint32_t flags);
63291a2b48SSukumar Swaminathan static fct_status_t emlxs_fct_abort(fct_local_port_t *fct_port,
64291a2b48SSukumar Swaminathan     fct_cmd_t *cmd, uint32_t flags);
65fcf3ce44SJohn Forte static void emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg);
66fcf3ce44SJohn Forte static fct_status_t emlxs_fct_register_remote_port(fct_local_port_t *fct_port,
67fcf3ce44SJohn Forte     fct_remote_port_t *port_handle, fct_cmd_t *plogi);
68fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd);
69fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd);
70fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd);
71fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd);
72fcf3ce44SJohn Forte static void emlxs_fct_pkt_comp(fc_packet_t *pkt);
7382527734SSukumar Swaminathan static void emlxs_fct_populate_hba_details(fct_local_port_t *fct_port,
74fcf3ce44SJohn Forte     fct_port_attrs_t *port_attrs);
7582527734SSukumar Swaminathan static fct_status_t emlxs_fct_port_info(uint32_t cmd,
7682527734SSukumar Swaminathan     fct_local_port_t *fct_port, void *arg, uint8_t *buffer, uint32_t *size);
77fcf3ce44SJohn Forte 
78fcf3ce44SJohn Forte static fct_status_t emlxs_fct_dmem_init(emlxs_port_t *port);
79fcf3ce44SJohn Forte static void emlxs_fct_dmem_fini(emlxs_port_t *port);
80fcf3ce44SJohn Forte 
81fcf3ce44SJohn Forte static stmf_data_buf_t *emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port,
82fcf3ce44SJohn Forte     uint32_t size, uint32_t *pminsize, uint32_t flags);
83fcf3ce44SJohn Forte static void emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *dbuf);
84fcf3ce44SJohn Forte 
85b3660a96SSukumar Swaminathan static int emlxs_fct_dbuf_dma_sync(emlxs_hba_t *hba, stmf_data_buf_t *dbuf,
86b3660a96SSukumar Swaminathan     uint_t sync_type);
87291a2b48SSukumar Swaminathan static emlxs_buf_t *emlxs_fct_pkt_init(emlxs_port_t *port,
88291a2b48SSukumar Swaminathan     fct_cmd_t *fct_cmd, fc_packet_t *pkt);
89fcf3ce44SJohn Forte 
908f23e9faSHans Rosenfeld static void emlxs_fct_unsol_flush_thread(emlxs_hba_t *hba, void *arg1,
918f23e9faSHans Rosenfeld     void *arg2);
92fcf3ce44SJohn Forte static void emlxs_fct_unsol_flush(emlxs_port_t *port);
9382527734SSukumar Swaminathan static uint32_t emlxs_fct_process_unsol_flogi(emlxs_port_t *port,
9482527734SSukumar Swaminathan     CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
9582527734SSukumar Swaminathan static uint32_t emlxs_fct_process_unsol_plogi(emlxs_port_t *port,
9682527734SSukumar Swaminathan     CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
97fe199829SSukumar Swaminathan static uint32_t emlxs_fct_pkt_abort_txq(emlxs_port_t *port,
98fe199829SSukumar Swaminathan     emlxs_buf_t *cmd_sbp);
99fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_qfull_reply(emlxs_port_t *port,
100fcf3ce44SJohn Forte     emlxs_node_t *ndlp, uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd);
101291a2b48SSukumar Swaminathan 
102291a2b48SSukumar Swaminathan #ifdef FCT_IO_TRACE
103291a2b48SSukumar Swaminathan uint8_t *emlxs_iotrace = 0;	/* global for mdb */
104291a2b48SSukumar Swaminathan int emlxs_iotrace_cnt = 0;
105291a2b48SSukumar Swaminathan 
10682527734SSukumar Swaminathan /*
10782527734SSukumar Swaminathan  *
10882527734SSukumar Swaminathan  * FCT_CMD  (cmd_sbp->fct_state)
10982527734SSukumar Swaminathan  *
11082527734SSukumar Swaminathan  * STATE				LOCK STATUS			OWNER
11182527734SSukumar Swaminathan  * -----------------------------------------------------------------------------
11282527734SSukumar Swaminathan  * EMLXS_FCT_ABORT_DONE			Lock Destroyed			COMSTAR
11382527734SSukumar Swaminathan  * EMLXS_FCT_IO_DONE			Lock Destroyed			COMSTAR
11482527734SSukumar Swaminathan  *
11582527734SSukumar Swaminathan  * EMLXS_FCT_CMD_POSTED			Lock Released			COMSTAR
11682527734SSukumar Swaminathan  * EMLXS_FCT_OWNED			Lock Released			COMSTAR
11782527734SSukumar Swaminathan  *
11882527734SSukumar Swaminathan  * EMLXS_FCT_CMD_WAITQ			Lock Released			DRIVER
11982527734SSukumar Swaminathan  * EMLXS_FCT_RSP_PENDING		Lock Released			DRIVER
12082527734SSukumar Swaminathan  * EMLXS_FCT_REQ_PENDING		Lock Released			DRIVER
12182527734SSukumar Swaminathan  * EMLXS_FCT_REG_PENDING		Lock Released			DRIVER
12282527734SSukumar Swaminathan  * EMLXS_FCT_DATA_PENDING		Lock Released			DRIVER
12382527734SSukumar Swaminathan  * EMLXS_FCT_STATUS_PENDING		Lock Released			DRIVER
12482527734SSukumar Swaminathan  * EMLXS_FCT_CLOSE_PENDING		Lock Released			DRIVER
12582527734SSukumar Swaminathan  * EMLXS_FCT_ABORT_PENDING		Lock Released			DRIVER
12682527734SSukumar Swaminathan  *
12782527734SSukumar Swaminathan  * EMLXS_FCT_FCP_CMD_RECEIVED		Transistional, lock held	DRIVER
12882527734SSukumar Swaminathan  * EMLXS_FCT_ELS_CMD_RECEIVED		Transistional, lock held	DRIVER
12982527734SSukumar Swaminathan  * EMLXS_FCT_SEND_CMD_RSP		Transistional, lock held	DRIVER
13082527734SSukumar Swaminathan  * EMLXS_FCT_SEND_ELS_RSP		Transistional, lock held	DRIVER
13182527734SSukumar Swaminathan  * EMLXS_FCT_SEND_ELS_REQ		Transistional, lock held	DRIVER
13282527734SSukumar Swaminathan  * EMLXS_FCT_SEND_CT_REQ		Transistional, lock held	DRIVER
13382527734SSukumar Swaminathan  * EMLXS_FCT_REG_COMPLETE		Transistional, lock held	DRIVER
13482527734SSukumar Swaminathan  * EMLXS_FCT_SEND_FCP_DATA		Transistional, lock held	DRIVER
13582527734SSukumar Swaminathan  * EMLXS_FCT_SEND_FCP_STATUS		Transistional, lock held	DRIVER
13682527734SSukumar Swaminathan  * EMLXS_FCT_PKT_COMPLETE		Transistional, lock held	DRIVER
13782527734SSukumar Swaminathan  * EMLXS_FCT_PKT_FCPRSP_COMPLETE	Transistional, lock held	DRIVER
13882527734SSukumar Swaminathan  * EMLXS_FCT_PKT_ELSRSP_COMPLETE	Transistional, lock held	DRIVER
13982527734SSukumar Swaminathan  * EMLXS_FCT_PKT_ELSCMD_COMPLETE	Transistional, lock held	DRIVER
14082527734SSukumar Swaminathan  * EMLXS_FCT_PKT_CTCMD_COMPLETE		Transistional, lock held	DRIVER
14182527734SSukumar Swaminathan  * EMLXS_FCT_REQ_COMPLETE		Transistional, lock held	DRIVER
14282527734SSukumar Swaminathan  *
14382527734SSukumar Swaminathan  *
14482527734SSukumar Swaminathan  * 	COMSTAR OWNED	DRIVER OWNED
14582527734SSukumar Swaminathan  * 	-------------	---------------------------------------------------
14682527734SSukumar Swaminathan  * 	------- >	@	   Accept---- >Release  @   Acquire--- >+
14782527734SSukumar Swaminathan  *									|
14882527734SSukumar Swaminathan  *	< -------	@	Post/Done< ----Acquire  @   Release< ---+
14982527734SSukumar Swaminathan  *
15082527734SSukumar Swaminathan  * 	@  :Indicates COMSTAR use of emlxs_fct_abort()
15182527734SSukumar Swaminathan  *	    Abort requests set the EMLXS_FCT_ABORT_INP flag.
15282527734SSukumar Swaminathan  *
15382527734SSukumar Swaminathan  * 	Accept		:Indicates use of emlxs_fct_cmd_accept()
15482527734SSukumar Swaminathan  * 	Acquire		:Indicates use of emlxs_fct_cmd_acquire()
15582527734SSukumar Swaminathan  * 	Post		:Indicates use of emlxs_fct_cmd_post()
15682527734SSukumar Swaminathan  * 	Done		:Indicates use of emlxs_fct_cmd_done()
15782527734SSukumar Swaminathan  */
15882527734SSukumar Swaminathan 
159291a2b48SSukumar Swaminathan void
emlxs_fct_io_trace(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint32_t data)160291a2b48SSukumar Swaminathan emlxs_fct_io_trace(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint32_t data)
161291a2b48SSukumar Swaminathan {
162291a2b48SSukumar Swaminathan 	emlxs_iotrace_t *iop = port->iotrace;
163291a2b48SSukumar Swaminathan 	uint16_t iotrace_cnt;
164291a2b48SSukumar Swaminathan 	uint16_t iotrace_index;
165291a2b48SSukumar Swaminathan 	int i;
166291a2b48SSukumar Swaminathan 
167291a2b48SSukumar Swaminathan 	if (!iop) {
168291a2b48SSukumar Swaminathan 		return;
169291a2b48SSukumar Swaminathan 	}
170291a2b48SSukumar Swaminathan 
171291a2b48SSukumar Swaminathan 	mutex_enter(&port->iotrace_mtx);
172291a2b48SSukumar Swaminathan 	iotrace_cnt = port->iotrace_cnt;
173291a2b48SSukumar Swaminathan 	iotrace_index = port->iotrace_index;
174291a2b48SSukumar Swaminathan 
175291a2b48SSukumar Swaminathan 	switch (data) {
176291a2b48SSukumar Swaminathan 
177291a2b48SSukumar Swaminathan 		/* New entry */
178291a2b48SSukumar Swaminathan 	case EMLXS_FCT_ELS_CMD_RECEIVED:
179291a2b48SSukumar Swaminathan 	case EMLXS_FCT_FCP_CMD_RECEIVED:
180291a2b48SSukumar Swaminathan 	case EMLXS_FCT_SEND_ELS_REQ:
181291a2b48SSukumar Swaminathan 	case EMLXS_FCT_SEND_CT_REQ:
182291a2b48SSukumar Swaminathan 		for (i = 0; i < iotrace_cnt; i++) {
183291a2b48SSukumar Swaminathan 			if ((iop->fct_cmd == fct_cmd) &&
184291a2b48SSukumar Swaminathan 			    (iop->trc[0] != (uint8_t)(0)))
185291a2b48SSukumar Swaminathan 				break;
186291a2b48SSukumar Swaminathan 			iop++;
187291a2b48SSukumar Swaminathan 		}
188291a2b48SSukumar Swaminathan 		if (i < iotrace_cnt) {
189291a2b48SSukumar Swaminathan 			/* New entry already exists */
190291a2b48SSukumar Swaminathan 			mutex_exit(&port->iotrace_mtx);
191291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
192291a2b48SSukumar Swaminathan 			    "IOTRACE: New entry already exists: fct_cmd: %p",
193291a2b48SSukumar Swaminathan 			    fct_cmd);
194291a2b48SSukumar Swaminathan 			return;
195291a2b48SSukumar Swaminathan 		}
196291a2b48SSukumar Swaminathan 		iop = port->iotrace + iotrace_index;
197291a2b48SSukumar Swaminathan 		for (i = 0; i < iotrace_cnt; i++) {
198291a2b48SSukumar Swaminathan 			if (iop->trc[0] == (uint8_t)(0))
199291a2b48SSukumar Swaminathan 				break;
200291a2b48SSukumar Swaminathan 
201291a2b48SSukumar Swaminathan 			iop++;
202291a2b48SSukumar Swaminathan 			if (iop == (port->iotrace + iotrace_cnt))
203291a2b48SSukumar Swaminathan 				iop = port->iotrace;
204291a2b48SSukumar Swaminathan 		}
205291a2b48SSukumar Swaminathan 		if (i >= iotrace_cnt) {
206291a2b48SSukumar Swaminathan 			/* No new slots available */
207291a2b48SSukumar Swaminathan 			mutex_exit(&port->iotrace_mtx);
208291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
209291a2b48SSukumar Swaminathan 			    "IOTRACE: No new slots: fct_cmd: %p data: %d",
210291a2b48SSukumar Swaminathan 			    fct_cmd, data);
211291a2b48SSukumar Swaminathan 			return;
212291a2b48SSukumar Swaminathan 		}
213291a2b48SSukumar Swaminathan 		port->iotrace_index++;
214291a2b48SSukumar Swaminathan 		if (port->iotrace_index >= iotrace_cnt)
215291a2b48SSukumar Swaminathan 			port->iotrace_index = 0;
216291a2b48SSukumar Swaminathan 
217291a2b48SSukumar Swaminathan 		bzero((uint8_t *)iop, sizeof (emlxs_iotrace_t));
218291a2b48SSukumar Swaminathan 		iop->fct_cmd = fct_cmd;
219291a2b48SSukumar Swaminathan 		iop->xri = fct_cmd->cmd_rxid;
220291a2b48SSukumar Swaminathan 		iop->marker = 0xff;
221291a2b48SSukumar Swaminathan 		iop->trc[0] = 2;
222291a2b48SSukumar Swaminathan 		iop->trc[1] = data;
223291a2b48SSukumar Swaminathan 		mutex_exit(&port->iotrace_mtx);
224291a2b48SSukumar Swaminathan 		return;
225291a2b48SSukumar Swaminathan 	}
226291a2b48SSukumar Swaminathan 
227291a2b48SSukumar Swaminathan 	for (i = 0; i < iotrace_cnt; i++) {
228291a2b48SSukumar Swaminathan 		if ((iop->fct_cmd == fct_cmd) &&
229291a2b48SSukumar Swaminathan 		    (iop->trc[0] != (uint8_t)(0)))
230291a2b48SSukumar Swaminathan 			break;
231291a2b48SSukumar Swaminathan 		iop++;
232291a2b48SSukumar Swaminathan 	}
233291a2b48SSukumar Swaminathan 	if (i >= iotrace_cnt) {
234291a2b48SSukumar Swaminathan 		/* Cannot find existing slot for fct_cmd */
235291a2b48SSukumar Swaminathan 		mutex_exit(&port->iotrace_mtx);
236291a2b48SSukumar Swaminathan 
237291a2b48SSukumar Swaminathan 		if ((data != EMLXS_FCT_REG_PENDING) &&
238291a2b48SSukumar Swaminathan 		    (data != EMLXS_FCT_REG_COMPLETE)) {
239291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
240291a2b48SSukumar Swaminathan 			    "IOTRACE: Missing slot: fct_cmd: %p data: %d",
241291a2b48SSukumar Swaminathan 			    fct_cmd, data);
242291a2b48SSukumar Swaminathan 		}
243291a2b48SSukumar Swaminathan 		return;
244291a2b48SSukumar Swaminathan 	}
245291a2b48SSukumar Swaminathan 
246291a2b48SSukumar Swaminathan 	if (iop->trc[0] >= MAX_IO_TRACE) {
247291a2b48SSukumar Swaminathan 		/* trc overrun for fct_cmd */
248291a2b48SSukumar Swaminathan 		mutex_exit(&port->iotrace_mtx);
249291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
250291a2b48SSukumar Swaminathan 		    "IOTRACE: trc overrun slot: fct_cmd: %p data: %d",
251291a2b48SSukumar Swaminathan 		    fct_cmd, data);
252291a2b48SSukumar Swaminathan 		return;
253291a2b48SSukumar Swaminathan 	}
254291a2b48SSukumar Swaminathan 
255291a2b48SSukumar Swaminathan 	if (iop->xri != fct_cmd->cmd_rxid) {
256291a2b48SSukumar Swaminathan 		/* xri mismatch for fct_cmd */
257291a2b48SSukumar Swaminathan 		mutex_exit(&port->iotrace_mtx);
258291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
259291a2b48SSukumar Swaminathan 		    "IOTRACE: xri mismatch %x != %x: fct_cmd: %p data: %d",
260291a2b48SSukumar Swaminathan 		    iop->xri, fct_cmd->cmd_rxid, fct_cmd, data);
261291a2b48SSukumar Swaminathan 		return;
262291a2b48SSukumar Swaminathan 	}
263291a2b48SSukumar Swaminathan 
264291a2b48SSukumar Swaminathan 	iop->trc[iop->trc[0]] = data;
265291a2b48SSukumar Swaminathan 	if ((data == EMLXS_FCT_IO_DONE) || (data == EMLXS_FCT_ABORT_DONE)) {
26682527734SSukumar Swaminathan 		/* IOCB ULPCOMMAND is saved after EMLXS_FCT_IOCB_ISSUED */
26782527734SSukumar Swaminathan 		if (iop->trc[iop->trc[0]-1] == EMLXS_FCT_IOCB_ISSUED) {
268291a2b48SSukumar Swaminathan 			iop->trc[0]++;
26982527734SSukumar Swaminathan 		} else {
270291a2b48SSukumar Swaminathan 			iop->trc[0] = 0;
271*e2d1a434SCarsten Grzemba 		}
27282527734SSukumar Swaminathan 	} else {
273291a2b48SSukumar Swaminathan 		iop->trc[0]++;
27482527734SSukumar Swaminathan 	}
275291a2b48SSukumar Swaminathan 	mutex_exit(&port->iotrace_mtx);
27682527734SSukumar Swaminathan 
27782527734SSukumar Swaminathan 	return;
27882527734SSukumar Swaminathan 
27982527734SSukumar Swaminathan } /* emlxs_fct_io_trace() */
280291a2b48SSukumar Swaminathan #endif /* FCT_IO_TRACE */
281fcf3ce44SJohn Forte 
282fcf3ce44SJohn Forte #ifdef MODSYM_SUPPORT
283fcf3ce44SJohn Forte 
284e51761e0SSukumar Swaminathan extern int
emlxs_fct_modopen()285fcf3ce44SJohn Forte emlxs_fct_modopen()
286fcf3ce44SJohn Forte {
287fcf3ce44SJohn Forte 	int err;
288fcf3ce44SJohn Forte 
28982527734SSukumar Swaminathan 	mutex_enter(&emlxs_device.lock);
29082527734SSukumar Swaminathan 
29182527734SSukumar Swaminathan 	if (emlxs_modsym.fct_modopen) {
29282527734SSukumar Swaminathan 		mutex_exit(&emlxs_device.lock);
29382527734SSukumar Swaminathan 		return (0);
294fcf3ce44SJohn Forte 	}
295291a2b48SSukumar Swaminathan 
29682527734SSukumar Swaminathan 	emlxs_modsym.fct_modopen++;
29782527734SSukumar Swaminathan 
298fcf3ce44SJohn Forte 	/* Comstar (fct) */
299fcf3ce44SJohn Forte 	err = 0;
300fcf3ce44SJohn Forte 	emlxs_modsym.mod_fct = ddi_modopen("drv/fct", KRTLD_MODE_FIRST, &err);
301fcf3ce44SJohn Forte 	if (!emlxs_modsym.mod_fct) {
302fcf3ce44SJohn Forte 
303fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "?%s: ddi_modopen drv/fct failed: err %d",
304fcf3ce44SJohn Forte 		    DRIVER_NAME, err);
305fcf3ce44SJohn Forte 		goto failed;
306fcf3ce44SJohn Forte 	}
307291a2b48SSukumar Swaminathan 
308fcf3ce44SJohn Forte 	/* Comstar (stmf) */
309fcf3ce44SJohn Forte 	err = 0;
310291a2b48SSukumar Swaminathan 	emlxs_modsym.mod_stmf =
311291a2b48SSukumar Swaminathan 	    ddi_modopen("drv/stmf", KRTLD_MODE_FIRST, &err);
312fcf3ce44SJohn Forte 	if (!emlxs_modsym.mod_stmf) {
313fcf3ce44SJohn Forte 
314fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "?%s: ddi_modopen drv/stmf failed: err %d",
315fcf3ce44SJohn Forte 		    DRIVER_NAME, err);
316fcf3ce44SJohn Forte 		goto failed;
317fcf3ce44SJohn Forte 	}
318291a2b48SSukumar Swaminathan 
319fcf3ce44SJohn Forte 	err = 0;
320fcf3ce44SJohn Forte 	/* Check if the fct fct_alloc is present */
321291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_alloc = (void *(*)())ddi_modsym(emlxs_modsym.mod_fct,
322fcf3ce44SJohn Forte 	    "fct_alloc", &err);
323fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_alloc == NULL) {
324fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
325fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_alloc not present", DRIVER_NAME);
326fcf3ce44SJohn Forte 		goto failed;
327fcf3ce44SJohn Forte 	}
328291a2b48SSukumar Swaminathan 
329fcf3ce44SJohn Forte 	err = 0;
330fcf3ce44SJohn Forte 	/* Check if the fct fct_free is present */
331291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_free = (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
332fcf3ce44SJohn Forte 	    "fct_free", &err);
333fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_free == NULL) {
334fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
335fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_free not present", DRIVER_NAME);
336fcf3ce44SJohn Forte 		goto failed;
337fcf3ce44SJohn Forte 	}
338291a2b48SSukumar Swaminathan 
339fcf3ce44SJohn Forte 	err = 0;
340fcf3ce44SJohn Forte 	/* Check if the fct fct_scsi_task_alloc is present */
341291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_scsi_task_alloc =
342291a2b48SSukumar Swaminathan 	    (void *(*)(void *, uint16_t, uint32_t, uint8_t *,
343291a2b48SSukumar Swaminathan 	    uint16_t, uint16_t))ddi_modsym(emlxs_modsym.mod_fct,
344291a2b48SSukumar Swaminathan 	    "fct_scsi_task_alloc", &err);
345fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_scsi_task_alloc == NULL) {
346fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
347fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_scsi_task_alloc not present",
348fcf3ce44SJohn Forte 		    DRIVER_NAME);
349fcf3ce44SJohn Forte 		goto failed;
350fcf3ce44SJohn Forte 	}
351291a2b48SSukumar Swaminathan 
352fcf3ce44SJohn Forte 	err = 0;
353fcf3ce44SJohn Forte 	/* Check if the fct fct_register_local_port is present */
354291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_register_local_port =
355291a2b48SSukumar Swaminathan 	    (int (*)())ddi_modsym(emlxs_modsym.mod_fct,
356291a2b48SSukumar Swaminathan 	    "fct_register_local_port", &err);
357fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_register_local_port == NULL) {
358fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
359fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_register_local_port not present",
360fcf3ce44SJohn Forte 		    DRIVER_NAME);
361fcf3ce44SJohn Forte 		goto failed;
362fcf3ce44SJohn Forte 	}
363291a2b48SSukumar Swaminathan 
364fcf3ce44SJohn Forte 	err = 0;
365fcf3ce44SJohn Forte 	/* Check if the fct fct_deregister_local_port is present */
366291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_deregister_local_port =
367291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
368291a2b48SSukumar Swaminathan 	    "fct_deregister_local_port", &err);
369fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_deregister_local_port == NULL) {
370fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
371fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_deregister_local_port not present",
372fcf3ce44SJohn Forte 		    DRIVER_NAME);
373fcf3ce44SJohn Forte 		goto failed;
374fcf3ce44SJohn Forte 	}
375291a2b48SSukumar Swaminathan 
376fcf3ce44SJohn Forte 	err = 0;
377fcf3ce44SJohn Forte 	/* Check if the fct fct_handle_event is present */
378291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_handle_event =
379291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_handle_event",
380291a2b48SSukumar Swaminathan 	    &err);
381fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_handle_event == NULL) {
382fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
383291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_handle_event not present",
384291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
385fcf3ce44SJohn Forte 		goto failed;
386fcf3ce44SJohn Forte 	}
387291a2b48SSukumar Swaminathan 
388fcf3ce44SJohn Forte 	err = 0;
389fcf3ce44SJohn Forte 	/* Check if the fct fct_post_rcvd_cmd is present */
390291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_post_rcvd_cmd =
391291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_post_rcvd_cmd",
392291a2b48SSukumar Swaminathan 	    &err);
393fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_post_rcvd_cmd == NULL) {
394fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
395291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_post_rcvd_cmd not present",
396291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
397fcf3ce44SJohn Forte 		goto failed;
398fcf3ce44SJohn Forte 	}
399fcf3ce44SJohn Forte 	err = 0;
400fcf3ce44SJohn Forte 	/* Check if the fct fct_alloc is present */
401291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_ctl = (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
402fcf3ce44SJohn Forte 	    "fct_ctl", &err);
403fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_ctl == NULL) {
404fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
405fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_ctl not present", DRIVER_NAME);
406fcf3ce44SJohn Forte 		goto failed;
407fcf3ce44SJohn Forte 	}
408fcf3ce44SJohn Forte 	err = 0;
409291a2b48SSukumar Swaminathan 	/* Check if the fct fct_queue_cmd_for_termination is present */
410291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_queue_cmd_for_termination =
411291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
412291a2b48SSukumar Swaminathan 	    "fct_queue_cmd_for_termination", &err);
413291a2b48SSukumar Swaminathan 	if ((void *)emlxs_modsym.fct_queue_cmd_for_termination == NULL) {
414291a2b48SSukumar Swaminathan 		cmn_err(CE_WARN,
415291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_queue_cmd_for_termination not present",
416291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
417291a2b48SSukumar Swaminathan 		goto failed;
418291a2b48SSukumar Swaminathan 	}
419291a2b48SSukumar Swaminathan 	err = 0;
420fcf3ce44SJohn Forte 	/* Check if the fct fct_send_response_done is present */
421291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_send_response_done =
422291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
423291a2b48SSukumar Swaminathan 	    "fct_send_response_done", &err);
424fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_send_response_done == NULL) {
425fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
426fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_send_response_done not present",
427fcf3ce44SJohn Forte 		    DRIVER_NAME);
428fcf3ce44SJohn Forte 		goto failed;
429fcf3ce44SJohn Forte 	}
430fcf3ce44SJohn Forte 	err = 0;
431fcf3ce44SJohn Forte 	/* Check if the fct fct_send_cmd_done is present */
432291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_send_cmd_done =
433291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_send_cmd_done",
434291a2b48SSukumar Swaminathan 	    &err);
435fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_send_cmd_done == NULL) {
436fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
437291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_send_cmd_done not present",
438291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
439fcf3ce44SJohn Forte 		goto failed;
440fcf3ce44SJohn Forte 	}
441fcf3ce44SJohn Forte 	err = 0;
442fcf3ce44SJohn Forte 	/* Check if the fct fct_scsi_xfer_data_done is present */
443291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_scsi_data_xfer_done =
444291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
445291a2b48SSukumar Swaminathan 	    "fct_scsi_data_xfer_done", &err);
446fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_scsi_data_xfer_done == NULL) {
447fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
448fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_scsi_data_xfer_done not present",
449fcf3ce44SJohn Forte 		    DRIVER_NAME);
450fcf3ce44SJohn Forte 		goto failed;
451fcf3ce44SJohn Forte 	}
452fcf3ce44SJohn Forte 	err = 0;
453fcf3ce44SJohn Forte 	/* Check if the fct fct_port_shutdown is present */
454291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_port_shutdown =
455291a2b48SSukumar Swaminathan 	    (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct,
456291a2b48SSukumar Swaminathan 	    "fct_port_shutdown", &err);
457fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_port_shutdown == NULL) {
458fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
459291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_port_shutdown not present",
460291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
461fcf3ce44SJohn Forte 		goto failed;
462fcf3ce44SJohn Forte 	}
463291a2b48SSukumar Swaminathan 
464fcf3ce44SJohn Forte 	err = 0;
465fcf3ce44SJohn Forte 	/* Check if the fct fct_port_initialize is present */
466291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_port_initialize =
467291a2b48SSukumar Swaminathan 	    (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct,
468291a2b48SSukumar Swaminathan 	    "fct_port_initialize", &err);
469fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_port_initialize == NULL) {
470fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
471fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_port_initialize not present",
472fcf3ce44SJohn Forte 		    DRIVER_NAME);
473fcf3ce44SJohn Forte 		goto failed;
474fcf3ce44SJohn Forte 	}
475291a2b48SSukumar Swaminathan 
476291a2b48SSukumar Swaminathan 	err = 0;
477291a2b48SSukumar Swaminathan 	/* Check if the fct fct_cmd_fca_aborted is present */
478291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_cmd_fca_aborted =
479291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
480291a2b48SSukumar Swaminathan 	    "fct_cmd_fca_aborted", &err);
481291a2b48SSukumar Swaminathan 	if ((void *)emlxs_modsym.fct_cmd_fca_aborted == NULL) {
482291a2b48SSukumar Swaminathan 		cmn_err(CE_WARN,
483291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_cmd_fca_aborted not present",
484291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
485291a2b48SSukumar Swaminathan 		goto failed;
486291a2b48SSukumar Swaminathan 	}
487291a2b48SSukumar Swaminathan 
488fcf3ce44SJohn Forte 	err = 0;
489fcf3ce44SJohn Forte 	/* Check if the fct fct_handle_rcvd_flogi is present */
490291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_handle_rcvd_flogi =
491291a2b48SSukumar Swaminathan 	    (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct,
492291a2b48SSukumar Swaminathan 	    "fct_handle_rcvd_flogi", &err);
493fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_handle_rcvd_flogi == NULL) {
494fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
495fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_handle_rcvd_flogi not present",
496fcf3ce44SJohn Forte 		    DRIVER_NAME);
497fcf3ce44SJohn Forte 		goto failed;
498fcf3ce44SJohn Forte 	}
499291a2b48SSukumar Swaminathan 
500fcf3ce44SJohn Forte 	/* Comstar (stmf) */
501fcf3ce44SJohn Forte 	err = 0;
502fcf3ce44SJohn Forte 	/* Check if the stmf stmf_alloc is present */
503291a2b48SSukumar Swaminathan 	emlxs_modsym.stmf_alloc =
504291a2b48SSukumar Swaminathan 	    (void *(*)())ddi_modsym(emlxs_modsym.mod_stmf, "stmf_alloc",
505291a2b48SSukumar Swaminathan 	    &err);
506fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.stmf_alloc == NULL) {
507fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
508fcf3ce44SJohn Forte 		    "?%s: drv/stmf: stmf_alloc not present", DRIVER_NAME);
509fcf3ce44SJohn Forte 		goto failed;
510fcf3ce44SJohn Forte 	}
511291a2b48SSukumar Swaminathan 
512fcf3ce44SJohn Forte 	err = 0;
513fcf3ce44SJohn Forte 	/* Check if the stmf stmf_free is present */
514291a2b48SSukumar Swaminathan 	emlxs_modsym.stmf_free = (void (*)())ddi_modsym(emlxs_modsym.mod_stmf,
515fcf3ce44SJohn Forte 	    "stmf_free", &err);
516fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.stmf_free == NULL) {
517fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
518fcf3ce44SJohn Forte 		    "?%s: drv/stmf: stmf_free not present", DRIVER_NAME);
519fcf3ce44SJohn Forte 		goto failed;
520fcf3ce44SJohn Forte 	}
521291a2b48SSukumar Swaminathan 
522fcf3ce44SJohn Forte 	err = 0;
523fcf3ce44SJohn Forte 	/* Check if the stmf stmf_deregister_port_provider is present */
524fcf3ce44SJohn Forte 	emlxs_modsym.stmf_deregister_port_provider =
525291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_stmf,
526fcf3ce44SJohn Forte 	    "stmf_deregister_port_provider", &err);
527fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.stmf_deregister_port_provider == NULL) {
528fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
529fcf3ce44SJohn Forte 		    "?%s: drv/stmf: stmf_deregister_port_provider not present",
530fcf3ce44SJohn Forte 		    DRIVER_NAME);
531fcf3ce44SJohn Forte 		goto failed;
532fcf3ce44SJohn Forte 	}
533291a2b48SSukumar Swaminathan 
534fcf3ce44SJohn Forte 	err = 0;
535fcf3ce44SJohn Forte 	/* Check if the stmf stmf_register_port_provider is present */
536fcf3ce44SJohn Forte 	emlxs_modsym.stmf_register_port_provider =
537291a2b48SSukumar Swaminathan 	    (int (*)())ddi_modsym(emlxs_modsym.mod_stmf,
538fcf3ce44SJohn Forte 	    "stmf_register_port_provider", &err);
539fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.stmf_register_port_provider == NULL) {
540fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
541fcf3ce44SJohn Forte 		    "?%s: drv/stmf: stmf_register_port_provider not present",
542fcf3ce44SJohn Forte 		    DRIVER_NAME);
543fcf3ce44SJohn Forte 		goto failed;
544fcf3ce44SJohn Forte 	}
54582527734SSukumar Swaminathan 
54682527734SSukumar Swaminathan 	mutex_exit(&emlxs_device.lock);
54782527734SSukumar Swaminathan 	return (0);
548fcf3ce44SJohn Forte 
549fcf3ce44SJohn Forte failed:
55082527734SSukumar Swaminathan 
55182527734SSukumar Swaminathan 	mutex_exit(&emlxs_device.lock);
552fcf3ce44SJohn Forte 	emlxs_fct_modclose();
55382527734SSukumar Swaminathan 	return (1);
554fcf3ce44SJohn Forte 
55582527734SSukumar Swaminathan } /* emlxs_fct_modopen() */
556fcf3ce44SJohn Forte 
557fcf3ce44SJohn Forte 
558fcf3ce44SJohn Forte extern void
emlxs_fct_modclose()559fcf3ce44SJohn Forte emlxs_fct_modclose()
560fcf3ce44SJohn Forte {
56182527734SSukumar Swaminathan 	mutex_enter(&emlxs_device.lock);
56282527734SSukumar Swaminathan 
56382527734SSukumar Swaminathan 	if (emlxs_modsym.fct_modopen == 0) {
56482527734SSukumar Swaminathan 		mutex_exit(&emlxs_device.lock);
56582527734SSukumar Swaminathan 		return;
56682527734SSukumar Swaminathan 	}
56782527734SSukumar Swaminathan 
56882527734SSukumar Swaminathan 	emlxs_modsym.fct_modopen--;
56982527734SSukumar Swaminathan 
57082527734SSukumar Swaminathan 	if (emlxs_modsym.fct_modopen) {
57182527734SSukumar Swaminathan 		mutex_exit(&emlxs_device.lock);
57282527734SSukumar Swaminathan 		return;
57382527734SSukumar Swaminathan 	}
574fcf3ce44SJohn Forte 
575fcf3ce44SJohn Forte 	if (emlxs_modsym.mod_fct) {
576fcf3ce44SJohn Forte 		(void) ddi_modclose(emlxs_modsym.mod_fct);
577fcf3ce44SJohn Forte 		emlxs_modsym.mod_fct = 0;
578fcf3ce44SJohn Forte 	}
579291a2b48SSukumar Swaminathan 
580fcf3ce44SJohn Forte 	if (emlxs_modsym.mod_stmf) {
581fcf3ce44SJohn Forte 		(void) ddi_modclose(emlxs_modsym.mod_stmf);
582fcf3ce44SJohn Forte 		emlxs_modsym.mod_stmf = 0;
583fcf3ce44SJohn Forte 	}
584291a2b48SSukumar Swaminathan 
585fcf3ce44SJohn Forte 	emlxs_modsym.fct_alloc = NULL;
586fcf3ce44SJohn Forte 	emlxs_modsym.fct_free = NULL;
587fcf3ce44SJohn Forte 	emlxs_modsym.fct_scsi_task_alloc = NULL;
588fcf3ce44SJohn Forte 	emlxs_modsym.fct_register_local_port = NULL;
589fcf3ce44SJohn Forte 	emlxs_modsym.fct_deregister_local_port = NULL;
590fcf3ce44SJohn Forte 	emlxs_modsym.fct_handle_event = NULL;
591fcf3ce44SJohn Forte 	emlxs_modsym.fct_ctl = NULL;
592291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_queue_cmd_for_termination = NULL;
593fcf3ce44SJohn Forte 	emlxs_modsym.fct_send_response_done = NULL;
594fcf3ce44SJohn Forte 	emlxs_modsym.fct_send_cmd_done = NULL;
595fcf3ce44SJohn Forte 	emlxs_modsym.fct_scsi_data_xfer_done = NULL;
596fcf3ce44SJohn Forte 	emlxs_modsym.fct_port_shutdown = NULL;
597fcf3ce44SJohn Forte 	emlxs_modsym.fct_port_initialize = NULL;
598291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_cmd_fca_aborted = NULL;
599fcf3ce44SJohn Forte 	emlxs_modsym.fct_handle_rcvd_flogi = NULL;
600fcf3ce44SJohn Forte 
601fcf3ce44SJohn Forte 	emlxs_modsym.stmf_alloc = NULL;
602fcf3ce44SJohn Forte 	emlxs_modsym.stmf_free = NULL;
603fcf3ce44SJohn Forte 	emlxs_modsym.stmf_deregister_port_provider = NULL;
604fcf3ce44SJohn Forte 	emlxs_modsym.stmf_register_port_provider = NULL;
605fcf3ce44SJohn Forte 
60682527734SSukumar Swaminathan 	mutex_exit(&emlxs_device.lock);
60782527734SSukumar Swaminathan 
60882527734SSukumar Swaminathan } /* emlxs_fct_modclose() */
609291a2b48SSukumar Swaminathan 
610291a2b48SSukumar Swaminathan #endif /* MODSYM_SUPPORT */
611291a2b48SSukumar Swaminathan 
612e2ca2865SSukumar Swaminathan /*
613e2ca2865SSukumar Swaminathan  * This routine is called to handle an unsol FLOGI exchange
614e2ca2865SSukumar Swaminathan  *	fx	save
615e2ca2865SSukumar Swaminathan  *	0	1	Process or save port->fx
616e2ca2865SSukumar Swaminathan  *	0	0	Process or reject port->fx
617e2ca2865SSukumar Swaminathan  *	1	1	Process port->fx, Process or save fx
618e2ca2865SSukumar Swaminathan  *	1	0	Process or reject port->fx, Process or reject fx
619e2ca2865SSukumar Swaminathan  */
620291a2b48SSukumar Swaminathan static void
emlxs_fct_handle_unsol_flogi(emlxs_port_t * port,fct_flogi_xchg_t * fx,uint32_t save)621e2ca2865SSukumar Swaminathan emlxs_fct_handle_unsol_flogi(emlxs_port_t *port, fct_flogi_xchg_t *fx,
622e2ca2865SSukumar Swaminathan     uint32_t save)
623291a2b48SSukumar Swaminathan {
624e2ca2865SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
625291a2b48SSukumar Swaminathan 	fct_status_t status;
626291a2b48SSukumar Swaminathan 	IOCBQ iocbq;
627e2ca2865SSukumar Swaminathan 	fct_flogi_xchg_t fxchg;
628e2ca2865SSukumar Swaminathan 
629e2ca2865SSukumar Swaminathan begin:
630e2ca2865SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
631e2ca2865SSukumar Swaminathan 
632e2ca2865SSukumar Swaminathan 	/* Check if there is an old saved FLOGI */
633e2ca2865SSukumar Swaminathan 	if (port->fx.fx_op) {
634e2ca2865SSukumar Swaminathan 		/* Get it now */
635e2ca2865SSukumar Swaminathan 		bcopy(&port->fx, &fxchg, sizeof (fct_flogi_xchg_t));
636e2ca2865SSukumar Swaminathan 
637e2ca2865SSukumar Swaminathan 		if (fx) {
638e2ca2865SSukumar Swaminathan 			/* Save new FLOGI */
639e2ca2865SSukumar Swaminathan 			bcopy(fx, &port->fx, sizeof (fct_flogi_xchg_t));
640e2ca2865SSukumar Swaminathan 
641e2ca2865SSukumar Swaminathan 			/* Reject old stale FLOGI */
642e2ca2865SSukumar Swaminathan 			fx = &fxchg;
643e2ca2865SSukumar Swaminathan 			goto reject_it;
644e2ca2865SSukumar Swaminathan 
645e2ca2865SSukumar Swaminathan 		} else {
646e2ca2865SSukumar Swaminathan 			bzero(&port->fx, sizeof (fct_flogi_xchg_t));
647e2ca2865SSukumar Swaminathan 			fx = &fxchg;
648e2ca2865SSukumar Swaminathan 		}
649e2ca2865SSukumar Swaminathan 
650e2ca2865SSukumar Swaminathan 	} else if (!fx) {
651e2ca2865SSukumar Swaminathan 		/* Nothing to do, just return */
652e2ca2865SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
653e2ca2865SSukumar Swaminathan 		return;
654e2ca2865SSukumar Swaminathan 	}
655e2ca2865SSukumar Swaminathan 
656e2ca2865SSukumar Swaminathan 	/* We have a valid FLOGI here */
657e2ca2865SSukumar Swaminathan 	/* There is no saved FLOGI at this point either */
658e2ca2865SSukumar Swaminathan 
659e2ca2865SSukumar Swaminathan 	/* Check if COMSTAR is ready to accept it */
660e2ca2865SSukumar Swaminathan 	if (port->fct_flags & FCT_STATE_LINK_UP_ACKED) {
661e2ca2865SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
662291a2b48SSukumar Swaminathan 
663291a2b48SSukumar Swaminathan 		bzero((uint8_t *)&iocbq, sizeof (IOCBQ));
664e2ca2865SSukumar Swaminathan 		iocbq.iocb.un.elsreq.remoteID = fx->fx_sid;
665e2ca2865SSukumar Swaminathan 		iocbq.iocb.un.elsreq.myID = fx->fx_did;
666e2ca2865SSukumar Swaminathan 		iocbq.iocb.ULPCONTEXT = (uint16_t)fx->rsvd2;
667e2ca2865SSukumar Swaminathan 		fx->rsvd2 = 0; /* Clear the reserved field now */
668291a2b48SSukumar Swaminathan 
669e2ca2865SSukumar Swaminathan 		status = MODSYM(fct_handle_rcvd_flogi) (port->fct_port, fx);
670291a2b48SSukumar Swaminathan 
671291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
672291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
673e2ca2865SSukumar Swaminathan 		    "fct_handle_rcvd_flogi %p: status=%x",
674e2ca2865SSukumar Swaminathan 		    port->fct_port, status);
675291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
676291a2b48SSukumar Swaminathan 
677291a2b48SSukumar Swaminathan 		if (status == FCT_SUCCESS) {
678e2ca2865SSukumar Swaminathan 			if (fx->fx_op == ELS_OP_ACC) {
679291a2b48SSukumar Swaminathan 				(void) emlxs_els_reply(port, &iocbq,
680291a2b48SSukumar Swaminathan 				    ELS_CMD_ACC, ELS_CMD_FLOGI, 0, 0);
681291a2b48SSukumar Swaminathan 
682e2ca2865SSukumar Swaminathan 			} else {	/* ELS_OP_LSRJT */
683291a2b48SSukumar Swaminathan 				(void) emlxs_els_reply(port, &iocbq,
684e2ca2865SSukumar Swaminathan 				    ELS_CMD_LS_RJT, ELS_CMD_FLOGI,
685e2ca2865SSukumar Swaminathan 				    fx->fx_rjt_reason, fx->fx_rjt_expl);
686291a2b48SSukumar Swaminathan 			}
687291a2b48SSukumar Swaminathan 		} else {
688291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
689e2ca2865SSukumar Swaminathan 			    "FLOGI: sid=%x xid=%x. "
690e2ca2865SSukumar Swaminathan 			    "fct_handle_rcvd_flogi failed. Rejecting.",
691e2ca2865SSukumar Swaminathan 			    fx->fx_sid, iocbq.iocb.ULPCONTEXT);
692291a2b48SSukumar Swaminathan 
693e2ca2865SSukumar Swaminathan 			(void) emlxs_els_reply(port, &iocbq,
694e2ca2865SSukumar Swaminathan 			    ELS_CMD_LS_RJT, ELS_CMD_FLOGI,
695e2ca2865SSukumar Swaminathan 			    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
696291a2b48SSukumar Swaminathan 		}
697291a2b48SSukumar Swaminathan 
698e2ca2865SSukumar Swaminathan 		return;
699291a2b48SSukumar Swaminathan 	}
700fcf3ce44SJohn Forte 
701e2ca2865SSukumar Swaminathan 	if (save) {
702e2ca2865SSukumar Swaminathan 		/* Save FLOGI for later */
703e2ca2865SSukumar Swaminathan 		bcopy(fx, &port->fx, sizeof (fct_flogi_xchg_t));
704e2ca2865SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
705291a2b48SSukumar Swaminathan 		return;
706fcf3ce44SJohn Forte 	}
707291a2b48SSukumar Swaminathan 
708e2ca2865SSukumar Swaminathan reject_it:
709291a2b48SSukumar Swaminathan 
710e2ca2865SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
711fcf3ce44SJohn Forte 
712e2ca2865SSukumar Swaminathan 	if (port->fct_flags & FCT_STATE_LINK_UP) {
713e2ca2865SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
714e2ca2865SSukumar Swaminathan 		    "FLOGI: sid=%x xid=%x. Stale. Rejecting.",
715e2ca2865SSukumar Swaminathan 		    fx->fx_sid, fx->rsvd2);
716fcf3ce44SJohn Forte 
717e2ca2865SSukumar Swaminathan 		bzero((uint8_t *)&iocbq, sizeof (IOCBQ));
718e2ca2865SSukumar Swaminathan 		iocbq.iocb.un.elsreq.remoteID = fx->fx_sid;
719e2ca2865SSukumar Swaminathan 		iocbq.iocb.un.elsreq.myID = fx->fx_did;
720e2ca2865SSukumar Swaminathan 		iocbq.iocb.ULPCONTEXT = fx->rsvd2;
721291a2b48SSukumar Swaminathan 
722e2ca2865SSukumar Swaminathan 		(void) emlxs_els_reply(port, &iocbq,
723e2ca2865SSukumar Swaminathan 		    ELS_CMD_LS_RJT, ELS_CMD_FLOGI,
724e2ca2865SSukumar Swaminathan 		    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
725fcf3ce44SJohn Forte 
726e2ca2865SSukumar Swaminathan 		/* If we have an FLOGI saved, try sending it now */
727e2ca2865SSukumar Swaminathan 		if (port->fx.fx_op) {
728e2ca2865SSukumar Swaminathan 			fx = NULL;
729e2ca2865SSukumar Swaminathan 			goto begin;
730e2ca2865SSukumar Swaminathan 		}
731291a2b48SSukumar Swaminathan 
732e2ca2865SSukumar Swaminathan 	} else {
733e2ca2865SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
734e2ca2865SSukumar Swaminathan 		    "FLOGI: sid=%x xid=%x. Link down. "
735e2ca2865SSukumar Swaminathan 		    "Dropping.",
736e2ca2865SSukumar Swaminathan 		    fx->fx_sid, fx->rsvd2);
737291a2b48SSukumar Swaminathan 	}
73882527734SSukumar Swaminathan 
739fcf3ce44SJohn Forte 	return;
740fcf3ce44SJohn Forte 
741e2ca2865SSukumar Swaminathan } /* emlxs_fct_handle_unsol_flogi() */
742fcf3ce44SJohn Forte 
743fcf3ce44SJohn Forte 
7448f23e9faSHans Rosenfeld /* ARGSUSED */
7458f23e9faSHans Rosenfeld static void
emlxs_fct_unsol_flush_thread(emlxs_hba_t * hba,void * arg1,void * arg2)7468f23e9faSHans Rosenfeld emlxs_fct_unsol_flush_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
7478f23e9faSHans Rosenfeld {
7488f23e9faSHans Rosenfeld 	emlxs_port_t *port = (emlxs_port_t *)arg1;
7498f23e9faSHans Rosenfeld 
7508f23e9faSHans Rosenfeld 	emlxs_fct_unsol_flush(port);
7518f23e9faSHans Rosenfeld 	return;
7528f23e9faSHans Rosenfeld 
7538f23e9faSHans Rosenfeld } /* emlxs_fct_unsol_flush_thread() */
7548f23e9faSHans Rosenfeld 
7558f23e9faSHans Rosenfeld 
756fcf3ce44SJohn Forte /* This is called at port online and offline */
757fcf3ce44SJohn Forte static void
emlxs_fct_unsol_flush(emlxs_port_t * port)758fcf3ce44SJohn Forte emlxs_fct_unsol_flush(emlxs_port_t *port)
759fcf3ce44SJohn Forte {
760fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
761fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
762fcf3ce44SJohn Forte 	emlxs_buf_t *next;
763fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
76482527734SSukumar Swaminathan 	fct_status_t rval;
765e2ca2865SSukumar Swaminathan 	uint32_t cmd_code;
766fcf3ce44SJohn Forte 
767fcf3ce44SJohn Forte 	if (!port->fct_port) {
768fcf3ce44SJohn Forte 		return;
769fcf3ce44SJohn Forte 	}
770291a2b48SSukumar Swaminathan 
771e2ca2865SSukumar Swaminathan 	/* First handle any pending FLOGI */
772e2ca2865SSukumar Swaminathan 	emlxs_fct_handle_unsol_flogi(port, NULL, 0);
773291a2b48SSukumar Swaminathan 
7748f23e9faSHans Rosenfeld 	if ((port->fct_flags & FCT_STATE_LINK_UP_ACKED) &&
7758f23e9faSHans Rosenfeld 	    !(port->fct_flags & FCT_STATE_FLOGI_CMPL)) {
7768f23e9faSHans Rosenfeld 		return;
7778f23e9faSHans Rosenfeld 	}
7788f23e9faSHans Rosenfeld 
779e2ca2865SSukumar Swaminathan 	/* Wait queue */
780fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
781fcf3ce44SJohn Forte 	cmd_sbp = port->fct_wait_head;
782fcf3ce44SJohn Forte 	port->fct_wait_head = NULL;
783fcf3ce44SJohn Forte 	port->fct_wait_tail = NULL;
784fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
785fcf3ce44SJohn Forte 
786291a2b48SSukumar Swaminathan 	/*
787291a2b48SSukumar Swaminathan 	 * Next process any outstanding ELS commands. It doesn't
788291a2b48SSukumar Swaminathan 	 * matter if the Link is up or not, always post them to FCT.
789291a2b48SSukumar Swaminathan 	 */
790fcf3ce44SJohn Forte 	while (cmd_sbp) {
791fcf3ce44SJohn Forte 		next = cmd_sbp->next;
792fcf3ce44SJohn Forte 		fct_cmd = cmd_sbp->fct_cmd;
793fcf3ce44SJohn Forte 
794e2ca2865SSukumar Swaminathan 		cmd_code = (fct_cmd->cmd_oxid << ELS_CMD_SHIFT);
795e2ca2865SSukumar Swaminathan 
79682527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
79782527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
79882527734SSukumar Swaminathan 		if (rval) {
79982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
8008f23e9faSHans Rosenfeld 			    "fct_unsol_flush: %s: sid=%x xid=%x "
801e2ca2865SSukumar Swaminathan 			    "Unable to reacquire fct_cmd.",
802e2ca2865SSukumar Swaminathan 			    emlxs_elscmd_xlate(cmd_code),
803e2ca2865SSukumar Swaminathan 			    fct_cmd->cmd_rxid, fct_cmd->cmd_rportid);
80482527734SSukumar Swaminathan 
80582527734SSukumar Swaminathan 			cmd_sbp = next;
80682527734SSukumar Swaminathan 			continue;
80782527734SSukumar Swaminathan 		}
80882527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
80982527734SSukumar Swaminathan 
810291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
8118f23e9faSHans Rosenfeld 		    "Posting %s: sid=%x xid=%x %p",
812e2ca2865SSukumar Swaminathan 		    emlxs_elscmd_xlate(cmd_code),
813e2ca2865SSukumar Swaminathan 		    fct_cmd->cmd_rportid, fct_cmd->cmd_rxid,
814e2ca2865SSukumar Swaminathan 		    fct_cmd);
815fcf3ce44SJohn Forte 
81682527734SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
81782527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
818fcf3ce44SJohn Forte 
819fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
820291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
8218f23e9faSHans Rosenfeld 		    "fct_post_rcvd_cmd:2 %p:%p portid x%x", fct_cmd, cmd_sbp,
822291a2b48SSukumar Swaminathan 		    fct_cmd->cmd_lportid);
823291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
82482527734SSukumar Swaminathan 
825291a2b48SSukumar Swaminathan 		MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
826fcf3ce44SJohn Forte 
827fcf3ce44SJohn Forte 		cmd_sbp = next;
828fcf3ce44SJohn Forte 
82982527734SSukumar Swaminathan 	}	/* while () */
830fcf3ce44SJohn Forte 
831fcf3ce44SJohn Forte 	return;
832fcf3ce44SJohn Forte 
83382527734SSukumar Swaminathan } /* emlxs_fct_unsol_flush() */
834fcf3ce44SJohn Forte 
835fcf3ce44SJohn Forte 
836fcf3ce44SJohn Forte int
emlxs_is_digit(uint8_t chr)837fcf3ce44SJohn Forte emlxs_is_digit(uint8_t chr)
838fcf3ce44SJohn Forte {
839fcf3ce44SJohn Forte 	if ((chr >= '0') && (chr <= '9')) {
840fcf3ce44SJohn Forte 		return (1);
841fcf3ce44SJohn Forte 	}
842291a2b48SSukumar Swaminathan 
843fcf3ce44SJohn Forte 	return (0);
844fcf3ce44SJohn Forte 
84582527734SSukumar Swaminathan } /* emlxs_is_digit */
846fcf3ce44SJohn Forte 
847fcf3ce44SJohn Forte 
848fcf3ce44SJohn Forte /*
849fcf3ce44SJohn Forte  *   Convert an ASCII decimal numeric string to integer.
850fcf3ce44SJohn Forte  *   Negation character '-' is not handled.
851fcf3ce44SJohn Forte  */
8528f23e9faSHans Rosenfeld static uint32_t
emlxs_str_atoi(uint8_t * string)853fcf3ce44SJohn Forte emlxs_str_atoi(uint8_t *string)
854fcf3ce44SJohn Forte {
855fcf3ce44SJohn Forte 	uint32_t num = 0;
856fcf3ce44SJohn Forte 	int i = 0;
857fcf3ce44SJohn Forte 
858fcf3ce44SJohn Forte 	while (string[i]) {
859fcf3ce44SJohn Forte 		if (!emlxs_is_digit(string[i])) {
860fcf3ce44SJohn Forte 			return (num);
861fcf3ce44SJohn Forte 		}
862291a2b48SSukumar Swaminathan 
863fcf3ce44SJohn Forte 		num = num * 10 + (string[i++] - '0');
864fcf3ce44SJohn Forte 	}
865fcf3ce44SJohn Forte 
866fcf3ce44SJohn Forte 	return (num);
867fcf3ce44SJohn Forte 
86882527734SSukumar Swaminathan } /* emlxs_str_atoi() */
869fcf3ce44SJohn Forte 
870fcf3ce44SJohn Forte 
8718f23e9faSHans Rosenfeld extern uint32_t
emlxs_fct_init(emlxs_hba_t * hba)872fcf3ce44SJohn Forte emlxs_fct_init(emlxs_hba_t *hba)
873fcf3ce44SJohn Forte {
874fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
875fcf3ce44SJohn Forte 
876fcf3ce44SJohn Forte 	/* Check if COMSTAR is present */
877fcf3ce44SJohn Forte 	if (((void *)MODSYM(stmf_alloc) == NULL) ||
878291a2b48SSukumar Swaminathan 	    ((void *)MODSYM(fct_alloc) == NULL)) {
879fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
8808f23e9faSHans Rosenfeld 		    "Comstar not present.");
8818f23e9faSHans Rosenfeld 		return (1);
882fcf3ce44SJohn Forte 	}
883291a2b48SSukumar Swaminathan 
8848f23e9faSHans Rosenfeld 	return (0);
885291a2b48SSukumar Swaminathan 
88682527734SSukumar Swaminathan } /* emlxs_fct_init() */
887fcf3ce44SJohn Forte 
888fcf3ce44SJohn Forte 
889fcf3ce44SJohn Forte extern void
emlxs_fct_attach(emlxs_hba_t * hba)890fcf3ce44SJohn Forte emlxs_fct_attach(emlxs_hba_t *hba)
891fcf3ce44SJohn Forte {
892fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
893fcf3ce44SJohn Forte 	uint32_t vpi;
894fcf3ce44SJohn Forte 
8958f23e9faSHans Rosenfeld 	if (!(port->flag & EMLXS_TGT_ENABLED)) {
896fcf3ce44SJohn Forte 		return;
897fcf3ce44SJohn Forte 	}
898291a2b48SSukumar Swaminathan 
899fcf3ce44SJohn Forte 	/* Bind the physical port */
900fcf3ce44SJohn Forte 	emlxs_fct_bind_port(port);
901fcf3ce44SJohn Forte 
902fcf3ce44SJohn Forte 	/* Bind virtual ports */
903fcf3ce44SJohn Forte 	if (hba->flag & FC_NPIV_ENABLED) {
90482527734SSukumar Swaminathan 		for (vpi = 1; vpi <= hba->vpi_high; vpi++) {
905fcf3ce44SJohn Forte 			port = &VPORT(vpi);
906fcf3ce44SJohn Forte 
9078f23e9faSHans Rosenfeld 			if (!(port->flag & EMLXS_PORT_ENABLED)) {
908fcf3ce44SJohn Forte 				continue;
909fcf3ce44SJohn Forte 			}
910291a2b48SSukumar Swaminathan 
911fcf3ce44SJohn Forte 			emlxs_fct_bind_port(port);
912fcf3ce44SJohn Forte 		}
913fcf3ce44SJohn Forte 	}
914291a2b48SSukumar Swaminathan 
915fcf3ce44SJohn Forte 	return;
916fcf3ce44SJohn Forte 
91782527734SSukumar Swaminathan } /* emlxs_fct_attach() */
918fcf3ce44SJohn Forte 
919fcf3ce44SJohn Forte 
920fcf3ce44SJohn Forte extern void
emlxs_fct_detach(emlxs_hba_t * hba)921fcf3ce44SJohn Forte emlxs_fct_detach(emlxs_hba_t *hba)
922fcf3ce44SJohn Forte {
923fcf3ce44SJohn Forte 	uint32_t i;
924fcf3ce44SJohn Forte 	emlxs_port_t *vport;
925fcf3ce44SJohn Forte 
9268f23e9faSHans Rosenfeld 	for (i = 0; i < MAX_VPORTS; i++) {
9278f23e9faSHans Rosenfeld 		vport = &VPORT(i);
928291a2b48SSukumar Swaminathan 
9298f23e9faSHans Rosenfeld 		if (!(vport->flag & EMLXS_PORT_ENABLED)) {
9308f23e9faSHans Rosenfeld 			continue;
931fcf3ce44SJohn Forte 		}
932fcf3ce44SJohn Forte 
9338f23e9faSHans Rosenfeld 		emlxs_fct_unbind_port(vport);
934fcf3ce44SJohn Forte 	}
9358f23e9faSHans Rosenfeld 
936291a2b48SSukumar Swaminathan #ifdef FCT_IO_TRACE
9378f23e9faSHans Rosenfeld {
9388f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
939291a2b48SSukumar Swaminathan 
9408f23e9faSHans Rosenfeld 	mutex_destroy(&port->iotrace_mtx);
9418f23e9faSHans Rosenfeld 	if (port->iotrace) {
9428f23e9faSHans Rosenfeld 		kmem_free(port->iotrace,
9438f23e9faSHans Rosenfeld 		    (port->iotrace_cnt * sizeof (emlxs_iotrace_t)));
944291a2b48SSukumar Swaminathan 	}
9458f23e9faSHans Rosenfeld 	port->iotrace = NULL;
9468f23e9faSHans Rosenfeld }
947291a2b48SSukumar Swaminathan #endif /* FCT_IO_TRACE */
948291a2b48SSukumar Swaminathan 
949fcf3ce44SJohn Forte 	return;
950fcf3ce44SJohn Forte 
95182527734SSukumar Swaminathan } /* emlxs_fct_detach() */
952fcf3ce44SJohn Forte 
953fcf3ce44SJohn Forte 
954fcf3ce44SJohn Forte extern void
emlxs_fct_unbind_port(emlxs_port_t * port)955fcf3ce44SJohn Forte emlxs_fct_unbind_port(emlxs_port_t *port)
956fcf3ce44SJohn Forte {
957fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
958fcf3ce44SJohn Forte 	char node_name[32];
959fcf3ce44SJohn Forte 
960fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
9618f23e9faSHans Rosenfeld 
9628f23e9faSHans Rosenfeld 	if (!(port->flag & EMLXS_TGT_BOUND)) {
963fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
964fcf3ce44SJohn Forte 		return;
965fcf3ce44SJohn Forte 	}
966291a2b48SSukumar Swaminathan 
967fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
9688f23e9faSHans Rosenfeld 	    "fct_unbind_port: port=%d", port->vpi);
969fcf3ce44SJohn Forte 
970fcf3ce44SJohn Forte 	/* Destroy & flush all port nodes, if they exist */
971fcf3ce44SJohn Forte 	if (port->node_count) {
9728f23e9faSHans Rosenfeld 		(void) EMLXS_SLI_UNREG_NODE(port, NULL, NULL, NULL, NULL);
973fcf3ce44SJohn Forte 	}
974291a2b48SSukumar Swaminathan 
9758f23e9faSHans Rosenfeld 	port->flag &= ~EMLXS_TGT_BOUND;
9768f23e9faSHans Rosenfeld 	port->flag &= ~EMLXS_TGT_ENABLED;
977fcf3ce44SJohn Forte 	hba->num_of_ports--;
978fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
979fcf3ce44SJohn Forte 
980fcf3ce44SJohn Forte 	if (port->fct_port) {
981fcf3ce44SJohn Forte 		emlxs_fct_link_down(port);
982fcf3ce44SJohn Forte 		emlxs_fct_unsol_flush(port);
983fcf3ce44SJohn Forte 
984fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
985fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
986fcf3ce44SJohn Forte 		    "fct_deregister_local_port %p", port->fct_port);
987291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
988fcf3ce44SJohn Forte 		MODSYM(fct_deregister_local_port) (port->fct_port);
989fcf3ce44SJohn Forte 
990fcf3ce44SJohn Forte 		if (port->fct_port->port_fds) {
991fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
992fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
993fcf3ce44SJohn Forte 			    "fct_free:3 %p", port->fct_port->port_fds);
994291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
995fcf3ce44SJohn Forte 			MODSYM(fct_free) (port->fct_port->port_fds);
996fcf3ce44SJohn Forte 			port->fct_port->port_fds = NULL;
997fcf3ce44SJohn Forte 		}
998fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
999fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1000fcf3ce44SJohn Forte 		    "fct_free:4 %p", port->fct_port);
1001291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1002fcf3ce44SJohn Forte 		MODSYM(fct_free) (port->fct_port);
1003fcf3ce44SJohn Forte 		port->fct_port = NULL;
1004fcf3ce44SJohn Forte 		port->fct_flags = 0;
1005fcf3ce44SJohn Forte 	}
1006291a2b48SSukumar Swaminathan 
1007fcf3ce44SJohn Forte 	if (port->port_provider) {
1008fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1009fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1010291a2b48SSukumar Swaminathan 		    "stmf_deregister_port_provider:1 %p",
1011291a2b48SSukumar Swaminathan 		    port->port_provider);
1012291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1013fcf3ce44SJohn Forte 		MODSYM(stmf_deregister_port_provider) (port->port_provider);
1014fcf3ce44SJohn Forte 
1015fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1016fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1017fcf3ce44SJohn Forte 		    "stmf_free:1 %p", port->port_provider);
1018291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1019fcf3ce44SJohn Forte 		MODSYM(stmf_free) (port->port_provider);
1020fcf3ce44SJohn Forte 		port->port_provider = NULL;
1021fcf3ce44SJohn Forte 	}
1022291a2b48SSukumar Swaminathan 
10238f23e9faSHans Rosenfeld 	if (port->fct_memseg) {
1024fcf3ce44SJohn Forte 		emlxs_fct_dmem_fini(port);
1025fcf3ce44SJohn Forte 	}
1026291a2b48SSukumar Swaminathan 
10278f23e9faSHans Rosenfeld 	(void) snprintf(node_name, sizeof (node_name), "%d,%d:SFCT",
10288f23e9faSHans Rosenfeld 	    hba->ddiinst, port->vpi);
1029fcf3ce44SJohn Forte 	(void) ddi_remove_minor_node(hba->dip, node_name);
1030fcf3ce44SJohn Forte 
1031fcf3ce44SJohn Forte 	return;
1032fcf3ce44SJohn Forte 
103382527734SSukumar Swaminathan } /* emlxs_fct_unbind_port() */
1034fcf3ce44SJohn Forte 
1035fcf3ce44SJohn Forte 
1036fcf3ce44SJohn Forte extern void
emlxs_fct_bind_port(emlxs_port_t * port)1037fcf3ce44SJohn Forte emlxs_fct_bind_port(emlxs_port_t *port)
1038fcf3ce44SJohn Forte {
1039fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1040fcf3ce44SJohn Forte 	fct_local_port_t *fct_port;
1041fcf3ce44SJohn Forte 	uint32_t flag = 0;
1042fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
1043fcf3ce44SJohn Forte 	fct_dbuf_store_t *fds;
1044fcf3ce44SJohn Forte 	char node_name[32];
104582527734SSukumar Swaminathan 	uint8_t *bptr;
1046fcf3ce44SJohn Forte 
10478f23e9faSHans Rosenfeld 	if (!(port->flag & EMLXS_TGT_ENABLED)) {
1048fcf3ce44SJohn Forte 		return;
1049fcf3ce44SJohn Forte 	}
1050291a2b48SSukumar Swaminathan 
10518f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_PORT_LOCK);
10528f23e9faSHans Rosenfeld 
10538f23e9faSHans Rosenfeld 	if (port->flag & EMLXS_TGT_BOUND) {
1054fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1055fcf3ce44SJohn Forte 		return;
1056fcf3ce44SJohn Forte 	}
1057291a2b48SSukumar Swaminathan 
1058fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
10598f23e9faSHans Rosenfeld 	    "fct_bind_port: port=%d", port->vpi);
1060fcf3ce44SJohn Forte 
1061fcf3ce44SJohn Forte 	/* Perform generic port initialization */
1062fcf3ce44SJohn Forte 	emlxs_port_init(port);
1063fcf3ce44SJohn Forte 
1064fcf3ce44SJohn Forte 	if (port->vpi == 0) {
10658f23e9faSHans Rosenfeld 		(void) snprintf(port->cfd_name, sizeof (port->cfd_name),
10668f23e9faSHans Rosenfeld 		    "%s%d", DRIVER_NAME, hba->ddiinst);
1067fcf3ce44SJohn Forte 	} else {
10688f23e9faSHans Rosenfeld 		(void) snprintf(port->cfd_name, sizeof (port->cfd_name),
10698f23e9faSHans Rosenfeld 		    "%s%d.%d", DRIVER_NAME, hba->ddiinst, port->vpi);
1070fcf3ce44SJohn Forte 	}
1071fcf3ce44SJohn Forte 
1072fcf3ce44SJohn Forte 	if (emlxs_fct_dmem_init(port) != FCT_SUCCESS) {
1073fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
10748f23e9faSHans Rosenfeld 		    "fct_bind_port: Unable to allocate fct memory.");
1075fcf3ce44SJohn Forte 		goto failed;
1076fcf3ce44SJohn Forte 	}
1077fcf3ce44SJohn Forte 	flag |= 0x00000001;
1078fcf3ce44SJohn Forte 
1079291a2b48SSukumar Swaminathan 	port->port_provider =
1080291a2b48SSukumar Swaminathan 	    (stmf_port_provider_t *)
1081fcf3ce44SJohn Forte 	    MODSYM(stmf_alloc) (STMF_STRUCT_PORT_PROVIDER, 0, 0);
1082fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1083fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1084fcf3ce44SJohn Forte 	    "stmf_alloc port_provider %p", port->port_provider);
1085291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1086fcf3ce44SJohn Forte 
1087fcf3ce44SJohn Forte 	if (port->port_provider == NULL) {
1088fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
10898f23e9faSHans Rosenfeld 		    "fct_bind_port: Unable to allocate port provider.");
1090fcf3ce44SJohn Forte 		goto failed;
1091fcf3ce44SJohn Forte 	}
1092fcf3ce44SJohn Forte 	flag |= 0x00000002;
1093fcf3ce44SJohn Forte 
1094fcf3ce44SJohn Forte 	port->port_provider->pp_portif_rev = PORTIF_REV_1;
1095fcf3ce44SJohn Forte 	port->port_provider->pp_name = port->cfd_name;
1096fcf3ce44SJohn Forte 	port->port_provider->pp_provider_private = port;
1097fcf3ce44SJohn Forte 
1098fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1099fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1100fcf3ce44SJohn Forte 	    "stmf_register_port_provider %p", port->port_provider);
1101291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1102fcf3ce44SJohn Forte 	/* register port provider with framework */
1103291a2b48SSukumar Swaminathan 	if (MODSYM(stmf_register_port_provider) (port->port_provider) !=
1104291a2b48SSukumar Swaminathan 	    STMF_SUCCESS) {
1105fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
11068f23e9faSHans Rosenfeld 		    "fct_bind_port: Unable to register port provider.");
1107fcf3ce44SJohn Forte 		goto failed;
1108fcf3ce44SJohn Forte 	}
1109fcf3ce44SJohn Forte 	flag |= 0x00000004;
1110fcf3ce44SJohn Forte 
1111291a2b48SSukumar Swaminathan 	port->fct_port =
1112291a2b48SSukumar Swaminathan 	    (fct_local_port_t *)MODSYM(fct_alloc) (FCT_STRUCT_LOCAL_PORT, 0,
1113291a2b48SSukumar Swaminathan 	    0);
1114fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1115fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1116fcf3ce44SJohn Forte 	    "fct_alloc fct_port %p", port->fct_port);
1117291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1118fcf3ce44SJohn Forte 
1119fcf3ce44SJohn Forte 	if (port->fct_port == NULL) {
1120fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
11218f23e9faSHans Rosenfeld 		    "fct_bind_port: Unable to allocate fct port.");
1122fcf3ce44SJohn Forte 		goto failed;
1123fcf3ce44SJohn Forte 	}
1124fcf3ce44SJohn Forte 	flag |= 0x00000008;
1125fcf3ce44SJohn Forte 
1126291a2b48SSukumar Swaminathan 	port->fct_port->port_fds =
1127291a2b48SSukumar Swaminathan 	    (fct_dbuf_store_t *)MODSYM(fct_alloc) (FCT_STRUCT_DBUF_STORE, 0,
1128291a2b48SSukumar Swaminathan 	    0);
1129fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1130fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1131fcf3ce44SJohn Forte 	    "fct_alloc port_fds %p", port->fct_port->port_fds);
1132291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1133fcf3ce44SJohn Forte 
1134fcf3ce44SJohn Forte 	if (port->fct_port->port_fds == NULL) {
1135fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
11368f23e9faSHans Rosenfeld 		    "fct_bind_port: Unable to allocate dbuf store.");
1137fcf3ce44SJohn Forte 		goto failed;
1138fcf3ce44SJohn Forte 	}
1139fcf3ce44SJohn Forte 	flag |= 0x00000010;
1140fcf3ce44SJohn Forte 
11418f23e9faSHans Rosenfeld 	(void) snprintf(node_name, sizeof (node_name), "%d,%d:SFCT",
11428f23e9faSHans Rosenfeld 	    hba->ddiinst, port->vpi);
1143291a2b48SSukumar Swaminathan 	if (ddi_create_minor_node(hba->dip, node_name, S_IFCHR, hba->ddiinst,
1144291a2b48SSukumar Swaminathan 	    NULL, 0) == DDI_FAILURE) {
1145fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1146fcf3ce44SJohn Forte 		    "Unable to create SFCT device node.");
1147fcf3ce44SJohn Forte 		goto failed;
1148fcf3ce44SJohn Forte 	}
1149fcf3ce44SJohn Forte 	flag |= 0x00000020;
1150fcf3ce44SJohn Forte 
1151fcf3ce44SJohn Forte 	/* Intialize */
1152fcf3ce44SJohn Forte 	fct_port = port->fct_port;
1153162fafd3Sallan 	fct_port->port_fca_version = FCT_FCA_MODREV_1;
1154fcf3ce44SJohn Forte 	fct_port->port_fca_private = port;
1155fcf3ce44SJohn Forte 	fct_port->port_fca_abort_timeout = 30 * 1000;	/* 30 seconds */
1156fcf3ce44SJohn Forte 
1157fcf3ce44SJohn Forte 	bcopy((uint8_t *)&port->wwpn, (uint8_t *)fct_port->port_pwwn, 8);
1158fcf3ce44SJohn Forte 	bcopy((uint8_t *)&port->wwnn, (uint8_t *)fct_port->port_nwwn, 8);
1159fcf3ce44SJohn Forte 
116082527734SSukumar Swaminathan 	bptr = (uint8_t *)&port->wwnn;
11618f23e9faSHans Rosenfeld 	(void) snprintf(fct_port->port_nwwn_str, FC_WWN_BUFLEN,
116282527734SSukumar Swaminathan 	    "%02x%02x%02x%02x%02x%02x%02x%02x",
116382527734SSukumar Swaminathan 	    bptr[0], bptr[1], bptr[2], bptr[3],
116482527734SSukumar Swaminathan 	    bptr[4], bptr[5], bptr[6], bptr[7]);
116582527734SSukumar Swaminathan 
116682527734SSukumar Swaminathan 	bptr = (uint8_t *)&port->wwpn;
11678f23e9faSHans Rosenfeld 	(void) snprintf(fct_port->port_pwwn_str, FC_WWN_BUFLEN,
116882527734SSukumar Swaminathan 	    "%02x%02x%02x%02x%02x%02x%02x%02x",
116982527734SSukumar Swaminathan 	    bptr[0], bptr[1], bptr[2], bptr[3],
117082527734SSukumar Swaminathan 	    bptr[4], bptr[5], bptr[6], bptr[7]);
117182527734SSukumar Swaminathan 
1172fcf3ce44SJohn Forte 	fct_port->port_sym_node_name = port->snn;
1173fcf3ce44SJohn Forte 	fct_port->port_sym_port_name = port->spn;
1174fcf3ce44SJohn Forte 	fct_port->port_hard_address = cfg[CFG_ASSIGN_ALPA].current;
1175fcf3ce44SJohn Forte 	fct_port->port_default_alias = port->cfd_name;
1176fcf3ce44SJohn Forte 	fct_port->port_pp = port->port_provider;
11778f23e9faSHans Rosenfeld 	fct_port->port_max_logins = hba->max_nodes + EMLXS_FCT_NUM_ELS_ONLY;
1178fcf3ce44SJohn Forte 
1179bce54adfSSukumar Swaminathan 	if (cfg[CFG_FCT_QDEPTH].current &&
1180bce54adfSSukumar Swaminathan 	    (cfg[CFG_FCT_QDEPTH].current < hba->io_throttle)) {
1181bce54adfSSukumar Swaminathan 		fct_port->port_max_xchges = cfg[CFG_FCT_QDEPTH].current;
1182fcf3ce44SJohn Forte 	} else {
1183fcf3ce44SJohn Forte 		fct_port->port_max_xchges = hba->io_throttle;
1184fcf3ce44SJohn Forte 	}
1185fcf3ce44SJohn Forte 
1186fcf3ce44SJohn Forte 	fct_port->port_fca_fcp_cmd_size = sizeof (emlxs_buf_t);
1187fcf3ce44SJohn Forte 	fct_port->port_fca_rp_private_size = sizeof (uintptr_t);
1188fcf3ce44SJohn Forte 	fct_port->port_fca_sol_els_private_size = sizeof (emlxs_buf_t);
1189fcf3ce44SJohn Forte 	fct_port->port_fca_sol_ct_private_size = sizeof (emlxs_buf_t);
1190fcf3ce44SJohn Forte 	fct_port->port_get_link_info = emlxs_fct_get_link_info;
1191fcf3ce44SJohn Forte 	fct_port->port_register_remote_port = emlxs_fct_register_remote_port;
1192fcf3ce44SJohn Forte 	fct_port->port_deregister_remote_port =
1193fcf3ce44SJohn Forte 	    emlxs_fct_deregister_remote_port;
1194fcf3ce44SJohn Forte 	fct_port->port_send_cmd = emlxs_fct_send_cmd;
1195fcf3ce44SJohn Forte 	fct_port->port_xfer_scsi_data = emlxs_fct_send_fcp_data;
1196fcf3ce44SJohn Forte 	fct_port->port_send_cmd_response = emlxs_fct_send_cmd_rsp;
1197fcf3ce44SJohn Forte 	fct_port->port_abort_cmd = emlxs_fct_abort;
1198fcf3ce44SJohn Forte 	fct_port->port_ctl = emlxs_fct_ctl;
119982527734SSukumar Swaminathan 	fct_port->port_flogi_xchg = emlxs_fct_flogi_xchg;
120082527734SSukumar Swaminathan 	fct_port->port_populate_hba_details = emlxs_fct_populate_hba_details;
120182527734SSukumar Swaminathan 	fct_port->port_info = emlxs_fct_port_info;
1202fcf3ce44SJohn Forte 
1203fcf3ce44SJohn Forte 	fds = port->fct_port->port_fds;
1204fcf3ce44SJohn Forte 	fds->fds_fca_private = port;
1205fcf3ce44SJohn Forte 	fds->fds_alloc_data_buf = emlxs_fct_dbuf_alloc;
1206fcf3ce44SJohn Forte 	fds->fds_free_data_buf = emlxs_fct_dbuf_free;
1207fcf3ce44SJohn Forte 
12088f23e9faSHans Rosenfeld 	/* Scatter gather list support */
12098f23e9faSHans Rosenfeld /*	fds->fds_setup_dbuf = ; */
12108f23e9faSHans Rosenfeld /*	fds->fds_teardown_dbuf = ; */
12118f23e9faSHans Rosenfeld /*	fds->fds_max_sgl_xfer_len = ; */
12128f23e9faSHans Rosenfeld /*	fds->fds_copy_threshold = ; */
12138f23e9faSHans Rosenfeld 
1214fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1215fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1216fcf3ce44SJohn Forte 	    "fct_register_local_port %p", fct_port);
1217291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1218fcf3ce44SJohn Forte 	/* register this local port with the fct module */
1219fcf3ce44SJohn Forte 	if (MODSYM(fct_register_local_port) (fct_port) != FCT_SUCCESS) {
1220fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
12218f23e9faSHans Rosenfeld 		    "fct_bind_port: Unable to register fct port.");
1222fcf3ce44SJohn Forte 		goto failed;
1223fcf3ce44SJohn Forte 	}
1224291a2b48SSukumar Swaminathan 
1225fcf3ce44SJohn Forte 	/* Set the bound flag */
12268f23e9faSHans Rosenfeld 	port->flag |= EMLXS_TGT_BOUND;
1227fcf3ce44SJohn Forte 	hba->num_of_ports++;
1228fcf3ce44SJohn Forte 
1229fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
1230fcf3ce44SJohn Forte 
1231fcf3ce44SJohn Forte 	return;
1232fcf3ce44SJohn Forte 
1233fcf3ce44SJohn Forte failed:
1234fcf3ce44SJohn Forte 
1235fcf3ce44SJohn Forte 	if (flag & 0x20) {
1236fcf3ce44SJohn Forte 		(void) ddi_remove_minor_node(hba->dip, node_name);
1237fcf3ce44SJohn Forte 	}
1238291a2b48SSukumar Swaminathan 
1239fcf3ce44SJohn Forte 	if (flag & 0x10) {
1240fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1241fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1242fcf3ce44SJohn Forte 		    "fct_free:5 %p", port->fct_port->port_fds);
1243291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1244fcf3ce44SJohn Forte 		MODSYM(fct_free) (port->fct_port->port_fds);
1245fcf3ce44SJohn Forte 		port->fct_port->port_fds = NULL;
1246fcf3ce44SJohn Forte 	}
1247291a2b48SSukumar Swaminathan 
1248fcf3ce44SJohn Forte 	if (flag & 0x8) {
1249fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1250fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1251fcf3ce44SJohn Forte 		    "fct_free:6 %p", port->fct_port);
1252291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1253fcf3ce44SJohn Forte 		MODSYM(fct_free) (port->fct_port);
1254fcf3ce44SJohn Forte 		port->fct_port = NULL;
1255fcf3ce44SJohn Forte 		port->fct_flags = 0;
1256fcf3ce44SJohn Forte 	}
1257291a2b48SSukumar Swaminathan 
1258fcf3ce44SJohn Forte 	if (flag & 0x4) {
1259fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1260fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1261291a2b48SSukumar Swaminathan 		    "stmf_deregister_port_provider:2 %p",
1262291a2b48SSukumar Swaminathan 		    port->port_provider);
1263291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1264fcf3ce44SJohn Forte 		MODSYM(stmf_deregister_port_provider) (port->port_provider);
1265fcf3ce44SJohn Forte 	}
1266291a2b48SSukumar Swaminathan 
1267fcf3ce44SJohn Forte 	if (flag & 0x2) {
1268fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1269fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1270fcf3ce44SJohn Forte 		    "stmf_free:2 %p", port->port_provider);
1271291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1272fcf3ce44SJohn Forte 		MODSYM(stmf_free) (port->port_provider);
1273fcf3ce44SJohn Forte 		port->port_provider = NULL;
1274fcf3ce44SJohn Forte 	}
1275291a2b48SSukumar Swaminathan 
1276fcf3ce44SJohn Forte 	if (flag & 0x1) {
1277fcf3ce44SJohn Forte 		emlxs_fct_dmem_fini(port);
1278fcf3ce44SJohn Forte 	}
1279291a2b48SSukumar Swaminathan 
12808f23e9faSHans Rosenfeld 	port->flag &= ~EMLXS_TGT_ENABLED;
12818f23e9faSHans Rosenfeld 
1282fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1283fcf3ce44SJohn Forte 	    "Target mode disabled.");
1284fcf3ce44SJohn Forte 
1285fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
1286fcf3ce44SJohn Forte 
1287fcf3ce44SJohn Forte 	return;
1288fcf3ce44SJohn Forte 
128982527734SSukumar Swaminathan } /* emlxs_fct_bind_port() */
129082527734SSukumar Swaminathan 
129182527734SSukumar Swaminathan 
129282527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
129382527734SSukumar Swaminathan /*ARGSUSED*/
129482527734SSukumar Swaminathan static fct_status_t
emlxs_fct_port_info(uint32_t cmd,fct_local_port_t * fct_port,void * arg,uint8_t * buffer,uint32_t * size)129582527734SSukumar Swaminathan emlxs_fct_port_info(uint32_t cmd, fct_local_port_t *fct_port, void *arg,
129682527734SSukumar Swaminathan     uint8_t *buffer, uint32_t *size)
129782527734SSukumar Swaminathan {
129882527734SSukumar Swaminathan 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
129982527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
130082527734SSukumar Swaminathan 	fct_status_t rval = FCT_SUCCESS;
130182527734SSukumar Swaminathan 	fct_port_link_status_t *link_status;
130282527734SSukumar Swaminathan 	MAILBOX *mb;
130382527734SSukumar Swaminathan 	MAILBOXQ *mbq;
130482527734SSukumar Swaminathan 
130582527734SSukumar Swaminathan 	switch (cmd) {
130682527734SSukumar Swaminathan 	case FC_TGT_PORT_RLS:
130782527734SSukumar Swaminathan 		bzero(buffer, *size);
130882527734SSukumar Swaminathan 
130982527734SSukumar Swaminathan 		if ((*size) < sizeof (fct_port_link_status_t)) {
131082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
131182527734SSukumar Swaminathan 			    "FC_TGT_PORT_RLS: Buffer too small. %d < %d",
131282527734SSukumar Swaminathan 			    *size, sizeof (fct_port_link_status_t));
131382527734SSukumar Swaminathan 
131482527734SSukumar Swaminathan 			rval = FCT_FAILURE;
131582527734SSukumar Swaminathan 			break;
131682527734SSukumar Swaminathan 		}
131782527734SSukumar Swaminathan 
13188f23e9faSHans Rosenfeld 		if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) == 0) {
131982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
132082527734SSukumar Swaminathan 			    "FC_TGT_PORT_RLS: Unable to allocate mailbox.");
132182527734SSukumar Swaminathan 
132282527734SSukumar Swaminathan 			rval = FCT_ALLOC_FAILURE;
132382527734SSukumar Swaminathan 			break;
132482527734SSukumar Swaminathan 		}
132582527734SSukumar Swaminathan 		mb = (MAILBOX *)mbq;
132682527734SSukumar Swaminathan 
132782527734SSukumar Swaminathan 		emlxs_mb_read_lnk_stat(hba, mbq);
132882527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0)
132982527734SSukumar Swaminathan 		    != MBX_SUCCESS) {
133082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
133182527734SSukumar Swaminathan 			    "FC_TGT_PORT_RLS: Unable to send request.");
133282527734SSukumar Swaminathan 
133382527734SSukumar Swaminathan 			rval = FCT_BUSY;
133482527734SSukumar Swaminathan 		} else {
133582527734SSukumar Swaminathan 			link_status = (fct_port_link_status_t *)buffer;
133682527734SSukumar Swaminathan 			link_status->LinkFailureCount =
133782527734SSukumar Swaminathan 			    mb->un.varRdLnk.linkFailureCnt;
133882527734SSukumar Swaminathan 			link_status->LossOfSyncCount =
133982527734SSukumar Swaminathan 			    mb->un.varRdLnk.lossSyncCnt;
134082527734SSukumar Swaminathan 			link_status->LossOfSignalsCount =
134182527734SSukumar Swaminathan 			    mb->un.varRdLnk.lossSignalCnt;
134282527734SSukumar Swaminathan 			link_status->PrimitiveSeqProtocolErrorCount =
134382527734SSukumar Swaminathan 			    mb->un.varRdLnk.primSeqErrCnt;
134482527734SSukumar Swaminathan 			link_status->InvalidTransmissionWordCount =
134582527734SSukumar Swaminathan 			    mb->un.varRdLnk.invalidXmitWord;
134682527734SSukumar Swaminathan 			link_status->InvalidCRCCount =
134782527734SSukumar Swaminathan 			    mb->un.varRdLnk.crcCnt;
134882527734SSukumar Swaminathan 		}
134982527734SSukumar Swaminathan 
1350a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
135182527734SSukumar Swaminathan 		break;
135282527734SSukumar Swaminathan 
135382527734SSukumar Swaminathan 	default:
135482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
13558f23e9faSHans Rosenfeld 		    "fct_port_info: Invalid request. cmd=%x",
135682527734SSukumar Swaminathan 		    cmd);
135782527734SSukumar Swaminathan 
135882527734SSukumar Swaminathan 		rval = FCT_FAILURE;
135982527734SSukumar Swaminathan 		break;
136082527734SSukumar Swaminathan 
136182527734SSukumar Swaminathan 	}
1362fcf3ce44SJohn Forte 
136382527734SSukumar Swaminathan 	return (rval);
136482527734SSukumar Swaminathan 
136582527734SSukumar Swaminathan } /* emlxs_fct_port_info() */
1366fcf3ce44SJohn Forte 
136782527734SSukumar Swaminathan 
136882527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1369fcf3ce44SJohn Forte static void
emlxs_fct_populate_hba_details(fct_local_port_t * fct_port,fct_port_attrs_t * port_attrs)137082527734SSukumar Swaminathan emlxs_fct_populate_hba_details(fct_local_port_t *fct_port,
1371fcf3ce44SJohn Forte     fct_port_attrs_t *port_attrs)
1372fcf3ce44SJohn Forte {
1373fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1374fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1375fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd = &VPD;
1376fcf3ce44SJohn Forte 
1377a3170057SPaul Winder 	(void) strncpy(port_attrs->manufacturer,
1378a3170057SPaul Winder 	    hba->model_info.manufacturer,
13798f23e9faSHans Rosenfeld 	    (sizeof (port_attrs->manufacturer)-1));
13808f23e9faSHans Rosenfeld 	(void) strncpy(port_attrs->serial_number, vpd->serial_num,
13818f23e9faSHans Rosenfeld 	    (sizeof (port_attrs->serial_number)-1));
13828f23e9faSHans Rosenfeld 	(void) strncpy(port_attrs->model, hba->model_info.model,
13838f23e9faSHans Rosenfeld 	    (sizeof (port_attrs->model)-1));
13848f23e9faSHans Rosenfeld 	(void) strncpy(port_attrs->model_description,
13858f23e9faSHans Rosenfeld 	    hba->model_info.model_desc,
13868f23e9faSHans Rosenfeld 	    (sizeof (port_attrs->model_description)-1));
13878f23e9faSHans Rosenfeld 	(void) snprintf(port_attrs->hardware_version,
13888f23e9faSHans Rosenfeld 	    (sizeof (port_attrs->hardware_version)-1),
13898f23e9faSHans Rosenfeld 	    "%x", vpd->biuRev);
13908f23e9faSHans Rosenfeld 	(void) snprintf(port_attrs->driver_version,
13918f23e9faSHans Rosenfeld 	    (sizeof (port_attrs->driver_version)-1),
13928f23e9faSHans Rosenfeld 	    "%s (%s)", emlxs_version,
1393fcf3ce44SJohn Forte 	    emlxs_revision);
13948f23e9faSHans Rosenfeld 	(void) strncpy(port_attrs->option_rom_version, vpd->fcode_version,
13958f23e9faSHans Rosenfeld 	    (sizeof (port_attrs->option_rom_version)-1));
13968f23e9faSHans Rosenfeld 	(void) snprintf(port_attrs->firmware_version,
13978f23e9faSHans Rosenfeld 	    (sizeof (port_attrs->firmware_version)-1),
13988f23e9faSHans Rosenfeld 	    "%s (%s)", vpd->fw_version,
1399fcf3ce44SJohn Forte 	    vpd->fw_label);
14008f23e9faSHans Rosenfeld 	(void) strncpy(port_attrs->driver_name, DRIVER_NAME,
14018f23e9faSHans Rosenfeld 	    (sizeof (port_attrs->driver_name)-1));
1402a3170057SPaul Winder 	port_attrs->vendor_specific_id = (hba->model_info.device_id << 16) |
1403a3170057SPaul Winder 	    hba->model_info.vendor_id;
140482527734SSukumar Swaminathan 	port_attrs->supported_cos = LE_SWAP32(FC_NS_CLASS3);
1405fcf3ce44SJohn Forte 
1406fcf3ce44SJohn Forte 	port_attrs->max_frame_size = FF_FRAME_SIZE;
1407fcf3ce44SJohn Forte 
1408a3170057SPaul Winder 	if (vpd->link_speed & LMT_32GB_CAPABLE) {
1409a3170057SPaul Winder 		port_attrs->supported_speed |= PORT_SPEED_32G;
1410a3170057SPaul Winder 	}
14118f23e9faSHans Rosenfeld 	if (vpd->link_speed & LMT_16GB_CAPABLE) {
14128f23e9faSHans Rosenfeld 		port_attrs->supported_speed |= PORT_SPEED_16G;
14138f23e9faSHans Rosenfeld 	}
1414fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
1415291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_10G;
1416fcf3ce44SJohn Forte 	}
1417fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
1418291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_8G;
1419fcf3ce44SJohn Forte 	}
1420fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
1421291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_4G;
1422fcf3ce44SJohn Forte 	}
1423fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
1424291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_2G;
1425fcf3ce44SJohn Forte 	}
1426fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
1427291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_1G;
1428fcf3ce44SJohn Forte 	}
1429291a2b48SSukumar Swaminathan 
1430fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1431fcf3ce44SJohn Forte 	    "Port attr: manufacturer       = %s", port_attrs->manufacturer);
1432fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1433fcf3ce44SJohn Forte 	    "Port attr: serial_num         = %s", port_attrs->serial_number);
1434fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1435fcf3ce44SJohn Forte 	    "Port attr: model              = %s", port_attrs->model);
1436fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1437fcf3ce44SJohn Forte 	    "Port attr: model_description  = %s",
1438fcf3ce44SJohn Forte 	    port_attrs->model_description);
1439fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1440291a2b48SSukumar Swaminathan 	    "Port attr: hardware_version   = %s",
1441291a2b48SSukumar Swaminathan 	    port_attrs->hardware_version);
1442fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1443fcf3ce44SJohn Forte 	    "Port attr: driver_version     = %s", port_attrs->driver_version);
1444fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1445fcf3ce44SJohn Forte 	    "Port attr: option_rom_version = %s",
1446fcf3ce44SJohn Forte 	    port_attrs->option_rom_version);
1447fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1448291a2b48SSukumar Swaminathan 	    "Port attr: firmware_version   = %s",
1449291a2b48SSukumar Swaminathan 	    port_attrs->firmware_version);
1450fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1451fcf3ce44SJohn Forte 	    "Port attr: driver_name        = %s", port_attrs->driver_name);
1452fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1453fcf3ce44SJohn Forte 	    "Port attr: vendor_specific_id = 0x%x",
1454fcf3ce44SJohn Forte 	    port_attrs->vendor_specific_id);
1455fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1456291a2b48SSukumar Swaminathan 	    "Port attr: supported_cos      = 0x%x",
1457291a2b48SSukumar Swaminathan 	    port_attrs->supported_cos);
1458fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1459fcf3ce44SJohn Forte 	    "Port attr: supported_speed    = 0x%x",
1460fcf3ce44SJohn Forte 	    port_attrs->supported_speed);
1461fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1462291a2b48SSukumar Swaminathan 	    "Port attr: max_frame_size     = 0x%x",
1463291a2b48SSukumar Swaminathan 	    port_attrs->max_frame_size);
1464fcf3ce44SJohn Forte 
1465fcf3ce44SJohn Forte 	return;
1466fcf3ce44SJohn Forte 
146782527734SSukumar Swaminathan } /* emlxs_fct_populate_hba_details() */
1468fcf3ce44SJohn Forte 
1469fcf3ce44SJohn Forte 
147082527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1471fcf3ce44SJohn Forte /* ARGSUSED */
1472fcf3ce44SJohn Forte static void
emlxs_fct_ctl(fct_local_port_t * fct_port,int cmd,void * arg)1473fcf3ce44SJohn Forte emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg)
1474fcf3ce44SJohn Forte {
1475fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1476fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1477fcf3ce44SJohn Forte 	stmf_change_status_t st;
1478a988c0caSRick McNeal 	int32_t rval;
1479fcf3ce44SJohn Forte 
1480fcf3ce44SJohn Forte 	st.st_completion_status = FCT_SUCCESS;
1481fcf3ce44SJohn Forte 	st.st_additional_info = NULL;
1482fcf3ce44SJohn Forte 
1483fcf3ce44SJohn Forte 	switch (cmd) {
1484fcf3ce44SJohn Forte 	case FCT_CMD_PORT_ONLINE:
1485fcf3ce44SJohn Forte 		/* If the HBA is offline, we cannot bring the tgtport online */
1486fcf3ce44SJohn Forte 		if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) {
1487fcf3ce44SJohn Forte 			st.st_completion_status = FCT_FAILURE;
1488fcf3ce44SJohn Forte 			MODSYM(fct_ctl) (fct_port->port_lport,
1489fcf3ce44SJohn Forte 			    FCT_CMD_PORT_ONLINE_COMPLETE, &st);
1490fcf3ce44SJohn Forte 			break;
1491fcf3ce44SJohn Forte 		}
1492291a2b48SSukumar Swaminathan 
1493fcf3ce44SJohn Forte 		if (port->fct_flags & FCT_STATE_PORT_ONLINE) {
1494fcf3ce44SJohn Forte 			st.st_completion_status = STMF_ALREADY;
1495fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1496fcf3ce44SJohn Forte 			    "STATE: ONLINE chk");
1497fcf3ce44SJohn Forte 		} else {
1498fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1499fcf3ce44SJohn Forte 			    "STATE: OFFLINE --> ONLINE");
1500fcf3ce44SJohn Forte 
1501fcf3ce44SJohn Forte 			port->fct_flags |= FCT_STATE_NOT_ACKED;
1502fcf3ce44SJohn Forte 			port->fct_flags |= FCT_STATE_PORT_ONLINE;
1503fcf3ce44SJohn Forte 
15048f23e9faSHans Rosenfeld 			if ((port->vpi == 0) &&
15058f23e9faSHans Rosenfeld 			    (port->mode == MODE_TARGET) &&
15068f23e9faSHans Rosenfeld 			    (hba->state <= FC_LINK_DOWN)) {
1507fcf3ce44SJohn Forte 				/* Try to bring the link up */
150882527734SSukumar Swaminathan 				(void) emlxs_reset_link(hba, 1, 1);
1509fcf3ce44SJohn Forte 			}
1510291a2b48SSukumar Swaminathan 
1511fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1512fcf3ce44SJohn Forte 			    "STATE: ONLINE");
1513fcf3ce44SJohn Forte 		}
1514fcf3ce44SJohn Forte 
1515fcf3ce44SJohn Forte 		MODSYM(fct_ctl) (fct_port->port_lport,
1516fcf3ce44SJohn Forte 		    FCT_CMD_PORT_ONLINE_COMPLETE, &st);
1517fcf3ce44SJohn Forte 		break;
1518fcf3ce44SJohn Forte 
1519fcf3ce44SJohn Forte 	case FCT_CMD_PORT_OFFLINE:
1520fcf3ce44SJohn Forte 		if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
1521fcf3ce44SJohn Forte 			st.st_completion_status = STMF_ALREADY;
1522fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1523fcf3ce44SJohn Forte 			    "STATE: OFFLINE chk");
1524fcf3ce44SJohn Forte 
1525fcf3ce44SJohn Forte 		} else {
1526fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1527fcf3ce44SJohn Forte 			    "STATE: ONLINE --> OFFLINE");
1528fcf3ce44SJohn Forte 
1529fcf3ce44SJohn Forte 			/* Take link down and flush */
1530fcf3ce44SJohn Forte 			emlxs_fct_link_down(port);
1531fcf3ce44SJohn Forte 			emlxs_fct_unsol_flush(port);
1532fcf3ce44SJohn Forte 
1533fcf3ce44SJohn Forte 			/* Declare this port offline now */
1534fcf3ce44SJohn Forte 			port->fct_flags |= FCT_STATE_NOT_ACKED;
1535fcf3ce44SJohn Forte 			port->fct_flags &= ~FCT_STATE_PORT_ONLINE;
1536fcf3ce44SJohn Forte 
15378f23e9faSHans Rosenfeld 			if ((port->vpi == 0) &&
15388f23e9faSHans Rosenfeld 			    (port->mode == MODE_TARGET) &&
15398f23e9faSHans Rosenfeld 			    !(port->flag & EMLXS_INI_ENABLED)) {
15408f23e9faSHans Rosenfeld 				/* Take link down and hold it down */
15418f23e9faSHans Rosenfeld 				(void) emlxs_reset_link(hba, 0, 1);
15428f23e9faSHans Rosenfeld 			}
1543fcf3ce44SJohn Forte 
1544fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1545fcf3ce44SJohn Forte 			    "STATE: OFFLINE");
1546fcf3ce44SJohn Forte 		}
1547fcf3ce44SJohn Forte 
1548fcf3ce44SJohn Forte 		MODSYM(fct_ctl) (fct_port->port_lport,
1549fcf3ce44SJohn Forte 		    FCT_CMD_PORT_OFFLINE_COMPLETE, &st);
1550fcf3ce44SJohn Forte 
1551fcf3ce44SJohn Forte 		break;
1552fcf3ce44SJohn Forte 
1553fcf3ce44SJohn Forte 	case FCT_ACK_PORT_OFFLINE_COMPLETE:
1554fcf3ce44SJohn Forte 		port->fct_flags &= ~FCT_STATE_NOT_ACKED;
1555fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1556fcf3ce44SJohn Forte 		    "STATE: OFFLINE ack");
1557fcf3ce44SJohn Forte 		break;
1558fcf3ce44SJohn Forte 
1559fcf3ce44SJohn Forte 	case FCT_ACK_PORT_ONLINE_COMPLETE:
1560fcf3ce44SJohn Forte 		port->fct_flags &= ~FCT_STATE_NOT_ACKED;
1561fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1562fcf3ce44SJohn Forte 		    "STATE: ONLINE ack");
1563fcf3ce44SJohn Forte 		break;
1564fcf3ce44SJohn Forte 
156582527734SSukumar Swaminathan 	case FCT_CMD_FORCE_LIP:
15668f23e9faSHans Rosenfeld 		if (port->mode == MODE_INITIATOR) {
15678f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
15688f23e9faSHans Rosenfeld 			    "fct_ctl: FCT_CMD_FORCE_LIP.");
1569a988c0caSRick McNeal 			*((fct_status_t *)arg) = FCT_FAILURE;
15708f23e9faSHans Rosenfeld 			break;
15718f23e9faSHans Rosenfeld 		}
15728f23e9faSHans Rosenfeld 
1573a9800bebSGarrett D'Amore 		if (hba->fw_flag & FW_UPDATE_NEEDED) {
1574a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
15758f23e9faSHans Rosenfeld 			    "fct_ctl: FCT_CMD_FORCE_LIP -> "
1576a9800bebSGarrett D'Amore 			    "FCT_CMD_RESET");
1577a9800bebSGarrett D'Amore 
1578a9800bebSGarrett D'Amore 			hba->fw_flag |= FW_UPDATE_KERNEL;
15798f23e9faSHans Rosenfeld 
1580a9800bebSGarrett D'Amore 			/* Reset the adapter */
1581a988c0caSRick McNeal 			rval = emlxs_reset(port, FC_FCA_RESET);
1582a9800bebSGarrett D'Amore 		} else {
1583a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
15848f23e9faSHans Rosenfeld 			    "fct_ctl: FCT_CMD_FORCE_LIP");
158582527734SSukumar Swaminathan 
1586a9800bebSGarrett D'Amore 			/* Reset the link */
1587a988c0caSRick McNeal 			rval = emlxs_reset(port, FC_FCA_LINK_RESET);
1588a9800bebSGarrett D'Amore 		}
1589a988c0caSRick McNeal 		*((fct_status_t *)arg) = (rval == FC_SUCCESS) ? FCT_SUCCESS:
1590a988c0caSRick McNeal 		    FCT_FAILURE;
159182527734SSukumar Swaminathan 		break;
1592fcf3ce44SJohn Forte 	}
1593fcf3ce44SJohn Forte 
1594fcf3ce44SJohn Forte 	return;
1595fcf3ce44SJohn Forte 
159682527734SSukumar Swaminathan } /* emlxs_fct_ctl() */
1597291a2b48SSukumar Swaminathan 
1598fcf3ce44SJohn Forte 
1599fcf3ce44SJohn Forte extern int
emlxs_fct_port_shutdown(emlxs_port_t * port)1600fcf3ce44SJohn Forte emlxs_fct_port_shutdown(emlxs_port_t *port)
1601fcf3ce44SJohn Forte {
1602fcf3ce44SJohn Forte 	fct_local_port_t *fct_port;
160382527734SSukumar Swaminathan 	int i;
1604fcf3ce44SJohn Forte 
1605fcf3ce44SJohn Forte 	fct_port = port->fct_port;
1606fcf3ce44SJohn Forte 	if (!fct_port) {
1607fcf3ce44SJohn Forte 		return (0);
1608fcf3ce44SJohn Forte 	}
16093be114edSSukumar Swaminathan 
16103be114edSSukumar Swaminathan 	port->fct_flags |= FCT_STATE_NOT_ACKED;
16113be114edSSukumar Swaminathan 
1612291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, "fct_port_shutdown");
1613fcf3ce44SJohn Forte 	MODSYM(fct_port_shutdown) (fct_port, STMF_RFLAG_STAY_OFFLINED,
16148f23e9faSHans Rosenfeld 	    DRIVER_NAME" shutdown");
1615fcf3ce44SJohn Forte 
161682527734SSukumar Swaminathan 	i = 0;
1617fcf3ce44SJohn Forte 	while (port->fct_flags & FCT_STATE_NOT_ACKED) {
1618fcf3ce44SJohn Forte 		i++;
1619fcf3ce44SJohn Forte 		if (i > 300) {	/* 30 seconds */
1620fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1621fcf3ce44SJohn Forte 			    "fct_port_shutdown failed to ACK");
1622fcf3ce44SJohn Forte 			break;
1623fcf3ce44SJohn Forte 		}
1624fcf3ce44SJohn Forte 		delay(drv_usectohz(100000));	/* 100 msec */
1625fcf3ce44SJohn Forte 	}
1626fcf3ce44SJohn Forte 	return (1);
1627fcf3ce44SJohn Forte }
1628fcf3ce44SJohn Forte 
1629fcf3ce44SJohn Forte 
1630fcf3ce44SJohn Forte extern int
emlxs_fct_port_initialize(emlxs_port_t * port)1631fcf3ce44SJohn Forte emlxs_fct_port_initialize(emlxs_port_t *port)
1632fcf3ce44SJohn Forte {
1633fcf3ce44SJohn Forte 	fct_local_port_t *fct_port;
163482527734SSukumar Swaminathan 	int i;
1635fcf3ce44SJohn Forte 
1636fcf3ce44SJohn Forte 	fct_port = port->fct_port;
1637fcf3ce44SJohn Forte 	if (!fct_port) {
1638fcf3ce44SJohn Forte 		return (0);
1639fcf3ce44SJohn Forte 	}
16403be114edSSukumar Swaminathan 
16413be114edSSukumar Swaminathan 	port->fct_flags |= FCT_STATE_NOT_ACKED;
16423be114edSSukumar Swaminathan 
1643fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1644fcf3ce44SJohn Forte 	    "fct_port_initialize");
1645fcf3ce44SJohn Forte 	MODSYM(fct_port_initialize) (fct_port, STMF_RFLAG_STAY_OFFLINED,
16468f23e9faSHans Rosenfeld 	    DRIVER_NAME" initialize");
1647fcf3ce44SJohn Forte 
164882527734SSukumar Swaminathan 	i = 0;
1649fcf3ce44SJohn Forte 	while (port->fct_flags & FCT_STATE_NOT_ACKED) {
1650fcf3ce44SJohn Forte 		i++;
1651fcf3ce44SJohn Forte 		if (i > 300) {	/* 30 seconds */
1652fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1653fcf3ce44SJohn Forte 			    "fct_port_initialize failed to ACK");
1654fcf3ce44SJohn Forte 			break;
1655fcf3ce44SJohn Forte 		}
1656fcf3ce44SJohn Forte 		delay(drv_usectohz(100000));	/* 100 msec */
1657fcf3ce44SJohn Forte 	}
1658fcf3ce44SJohn Forte 	return (1);
1659fcf3ce44SJohn Forte }
1660fcf3ce44SJohn Forte 
1661291a2b48SSukumar Swaminathan 
166282527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1663fcf3ce44SJohn Forte static fct_status_t
emlxs_fct_send_cmd(fct_cmd_t * fct_cmd)1664fcf3ce44SJohn Forte emlxs_fct_send_cmd(fct_cmd_t *fct_cmd)
1665fcf3ce44SJohn Forte {
1666fcf3ce44SJohn Forte 	emlxs_port_t *port;
1667fcf3ce44SJohn Forte 
1668fcf3ce44SJohn Forte 	port = (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
1669fcf3ce44SJohn Forte 
1670fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1671fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
16728f23e9faSHans Rosenfeld 	    "fct_send_cmd %p:%p  x%x", fct_cmd,
16738f23e9faSHans Rosenfeld 	    fct_cmd->cmd_fca_private, fct_cmd->cmd_type);
1674291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1675fcf3ce44SJohn Forte 
1676fcf3ce44SJohn Forte 	switch (fct_cmd->cmd_type) {
1677fcf3ce44SJohn Forte 	case FCT_CMD_SOL_ELS:
1678fcf3ce44SJohn Forte 
1679fcf3ce44SJohn Forte 		return (emlxs_fct_send_els_cmd(fct_cmd));
1680fcf3ce44SJohn Forte 
1681fcf3ce44SJohn Forte 	case FCT_CMD_SOL_CT:
1682fcf3ce44SJohn Forte 
1683fcf3ce44SJohn Forte 		return (emlxs_fct_send_ct_cmd(fct_cmd));
1684fcf3ce44SJohn Forte 
1685fcf3ce44SJohn Forte 	default:
1686fcf3ce44SJohn Forte 
1687fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
16888f23e9faSHans Rosenfeld 		    "fct_send_cmd: Invalid cmd type found. type=%x",
1689fcf3ce44SJohn Forte 		    fct_cmd->cmd_type);
1690fcf3ce44SJohn Forte 
1691fcf3ce44SJohn Forte 		return (FCT_FAILURE);
1692fcf3ce44SJohn Forte 	}
1693fcf3ce44SJohn Forte 
169482527734SSukumar Swaminathan } /* emlxs_fct_send_cmd() */
1695fcf3ce44SJohn Forte 
1696fcf3ce44SJohn Forte 
169782527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1698fcf3ce44SJohn Forte static fct_status_t
emlxs_fct_send_cmd_rsp(fct_cmd_t * fct_cmd,uint32_t ioflags)1699fcf3ce44SJohn Forte emlxs_fct_send_cmd_rsp(fct_cmd_t *fct_cmd, uint32_t ioflags)
1700fcf3ce44SJohn Forte {
1701fcf3ce44SJohn Forte 	emlxs_port_t *port;
1702291a2b48SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp;
1703291a2b48SSukumar Swaminathan 	fct_status_t rval;
170482527734SSukumar Swaminathan 	IOCBQ *iocbq;
170582527734SSukumar Swaminathan 	IOCB *iocb;
170682527734SSukumar Swaminathan 	uint32_t status;
1707fcf3ce44SJohn Forte 
1708fcf3ce44SJohn Forte 	port = (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
170982527734SSukumar Swaminathan 
171082527734SSukumar Swaminathan 	rval = emlxs_fct_cmd_accept(port, fct_cmd, EMLXS_FCT_SEND_CMD_RSP);
171182527734SSukumar Swaminathan 	if (rval) {
171282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
17138f23e9faSHans Rosenfeld 		    "fct_send_cmd_rsp: "
171482527734SSukumar Swaminathan 		    "Unable to accept fct_cmd. type=%x",
171582527734SSukumar Swaminathan 		    fct_cmd->cmd_type);
171682527734SSukumar Swaminathan 
171782527734SSukumar Swaminathan 		return (rval);
171882527734SSukumar Swaminathan 	}
171982527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
172082527734SSukumar Swaminathan 
1721291a2b48SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
172282527734SSukumar Swaminathan 	iocbq = &cmd_sbp->iocbq;
17238f23e9faSHans Rosenfeld 	iocbq->sbp = cmd_sbp;
172482527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
172582527734SSukumar Swaminathan 	status = iocb->ULPSTATUS;
1726fcf3ce44SJohn Forte 
1727fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1728fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
17298f23e9faSHans Rosenfeld 	    "fct_send_cmd_rsp %p:%p x%x, %x, %x",
17308f23e9faSHans Rosenfeld 	    fct_cmd, cmd_sbp, fct_cmd->cmd_type, iocb->ULPCT, status);
1731291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1732fcf3ce44SJohn Forte 
1733fcf3ce44SJohn Forte 	switch (fct_cmd->cmd_type) {
1734fcf3ce44SJohn Forte 	case FCT_CMD_FCP_XCHG:
1735fcf3ce44SJohn Forte 
1736fcf3ce44SJohn Forte 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1737fcf3ce44SJohn Forte 			goto failure;
1738fcf3ce44SJohn Forte 		}
1739291a2b48SSukumar Swaminathan 
174082527734SSukumar Swaminathan 		if ((iocb->ULPCT == 0x1) && (status == 0)) {
174182527734SSukumar Swaminathan 
174282527734SSukumar Swaminathan 			/* Firmware already sent out resp */
174382527734SSukumar Swaminathan 			cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
174482527734SSukumar Swaminathan 
17458f23e9faSHans Rosenfeld 			TGTPORTSTAT.FctOutstandingIO--;
17468f23e9faSHans Rosenfeld 
174782527734SSukumar Swaminathan 			emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
174882527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
174982527734SSukumar Swaminathan 
175082527734SSukumar Swaminathan #ifdef FCT_API_TRACE
175182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
175282527734SSukumar Swaminathan 			    "fct_send_response_done:4 %p: x%x",
175382527734SSukumar Swaminathan 			    fct_cmd, fct_cmd->cmd_comp_status);
175482527734SSukumar Swaminathan 
175582527734SSukumar Swaminathan #endif /* FCT_API_TRACE */
175682527734SSukumar Swaminathan 
175782527734SSukumar Swaminathan 			MODSYM(fct_send_response_done) (fct_cmd,
175882527734SSukumar Swaminathan 			    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
175982527734SSukumar Swaminathan 
176082527734SSukumar Swaminathan 			return (FCT_SUCCESS);
176182527734SSukumar Swaminathan 		}
176282527734SSukumar Swaminathan 
1763291a2b48SSukumar Swaminathan 		rval =  emlxs_fct_send_fcp_status(fct_cmd);
17648f23e9faSHans Rosenfeld 		if (rval == FCT_NOT_FOUND) {
17658f23e9faSHans Rosenfeld 			goto failure;
17668f23e9faSHans Rosenfeld 		}
176782527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
176882527734SSukumar Swaminathan 
1769291a2b48SSukumar Swaminathan 		return (rval);
1770fcf3ce44SJohn Forte 
1771fcf3ce44SJohn Forte 	case FCT_CMD_RCVD_ELS:
1772fcf3ce44SJohn Forte 
1773fcf3ce44SJohn Forte 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1774fcf3ce44SJohn Forte 			goto failure;
1775fcf3ce44SJohn Forte 		}
1776fcf3ce44SJohn Forte 
177782527734SSukumar Swaminathan 		rval =  emlxs_fct_send_els_rsp(fct_cmd);
177882527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
177982527734SSukumar Swaminathan 
178082527734SSukumar Swaminathan 		return (rval);
1781fcf3ce44SJohn Forte 
1782fcf3ce44SJohn Forte 	default:
1783fcf3ce44SJohn Forte 
1784fcf3ce44SJohn Forte 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1785fcf3ce44SJohn Forte 			fct_cmd->cmd_handle = 0;
1786fcf3ce44SJohn Forte 		}
1787291a2b48SSukumar Swaminathan 
1788fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
17898f23e9faSHans Rosenfeld 		    "fct_send_cmd_rsp: Invalid cmd type found. type=%x",
1790fcf3ce44SJohn Forte 		    fct_cmd->cmd_type);
1791fcf3ce44SJohn Forte 
1792fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
179382527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
179482527734SSukumar Swaminathan 
1795fcf3ce44SJohn Forte 		return (FCT_FAILURE);
1796fcf3ce44SJohn Forte 	}
1797fcf3ce44SJohn Forte 
1798fcf3ce44SJohn Forte failure:
1799fcf3ce44SJohn Forte 
1800fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
18018f23e9faSHans Rosenfeld 	    "fct_send_cmd_rsp: "
1802291a2b48SSukumar Swaminathan 	    "Unable to handle FCT_IOF_FORCE_FCA_DONE. type=%x",
1803291a2b48SSukumar Swaminathan 	    fct_cmd->cmd_type);
1804fcf3ce44SJohn Forte 
1805fe199829SSukumar Swaminathan 	emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
180682527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
180782527734SSukumar Swaminathan 
1808fcf3ce44SJohn Forte 	return (FCT_FAILURE);
1809fcf3ce44SJohn Forte 
181082527734SSukumar Swaminathan } /* emlxs_fct_send_cmd_rsp() */
1811fcf3ce44SJohn Forte 
1812fcf3ce44SJohn Forte 
181382527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1814fcf3ce44SJohn Forte static fct_status_t
emlxs_fct_flogi_xchg(struct fct_local_port * fct_port,struct fct_flogi_xchg * fx)181582527734SSukumar Swaminathan emlxs_fct_flogi_xchg(struct fct_local_port *fct_port, struct fct_flogi_xchg *fx)
1816fcf3ce44SJohn Forte {
1817fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1818fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1819fcf3ce44SJohn Forte 	uint32_t size;
182082527734SSukumar Swaminathan 	fc_packet_t *pkt = NULL;
1821fcf3ce44SJohn Forte 	ELS_PKT *els;
182282527734SSukumar Swaminathan 	fct_status_t rval = FCT_SUCCESS;
1823fcf3ce44SJohn Forte 
1824fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1825fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
18268f23e9faSHans Rosenfeld 	    "fct_flogi_xchg: Sending FLOGI: %p", fct_port);
1827fcf3ce44SJohn Forte #else
1828fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
18298f23e9faSHans Rosenfeld 	    "fct_flogi_xchg: Sending FLOGI.");
1830291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1831fcf3ce44SJohn Forte 
1832fcf3ce44SJohn Forte 	if (hba->state <= FC_LINK_DOWN) {
1833fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
18348f23e9faSHans Rosenfeld 		    "fct_flogi_xchg: FLOGI failed. Link down.");
183582527734SSukumar Swaminathan 		rval = FCT_FAILURE;
183682527734SSukumar Swaminathan 		goto done;
1837fcf3ce44SJohn Forte 	}
1838291a2b48SSukumar Swaminathan 
18398f23e9faSHans Rosenfeld 	/* Use this entry point as the link up acknowledgment */
1840e2ca2865SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
1841e2ca2865SSukumar Swaminathan 	port->fct_flags |= FCT_STATE_LINK_UP_ACKED;
1842e2ca2865SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
18438f23e9faSHans Rosenfeld 	    "fct_link_up acked.");
1844e2ca2865SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
1845e2ca2865SSukumar Swaminathan 
18468f23e9faSHans Rosenfeld 	/* First handle any pending FLOGI's */
18478f23e9faSHans Rosenfeld 	emlxs_fct_handle_unsol_flogi(port, NULL, 0);
1848e2ca2865SSukumar Swaminathan 
1849fcf3ce44SJohn Forte 	size = sizeof (SERV_PARM) + 4;
1850fcf3ce44SJohn Forte 
1851fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, size, size, 0, KM_NOSLEEP))) {
1852fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
18538f23e9faSHans Rosenfeld 		    "fct_flogi_xchg: FLOGI failed. "
185482527734SSukumar Swaminathan 		    "Unable allocate packet.");
185582527734SSukumar Swaminathan 		rval = FCT_FAILURE;
185682527734SSukumar Swaminathan 		goto done;
1857fcf3ce44SJohn Forte 	}
1858291a2b48SSukumar Swaminathan 
1859fcf3ce44SJohn Forte 	/* Make this a polled IO */
1860fcf3ce44SJohn Forte 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
1861fcf3ce44SJohn Forte 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
1862fcf3ce44SJohn Forte 	pkt->pkt_comp = NULL;
1863fcf3ce44SJohn Forte 
1864fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
1865fcf3ce44SJohn Forte 	pkt->pkt_timeout = fx->fx_sec_timeout;
1866fcf3ce44SJohn Forte 
1867fcf3ce44SJohn Forte 	/* Build the fc header */
186882527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(fx->fx_did);
1869291a2b48SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.r_ctl =
1870291a2b48SSukumar Swaminathan 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
187182527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(fx->fx_sid);
1872fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
1873fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE;
1874fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
1875fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
1876fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
1877fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
1878fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
1879fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
1880fcf3ce44SJohn Forte 
1881fcf3ce44SJohn Forte 	/* Build the command */
1882291a2b48SSukumar Swaminathan 	/* Service paramters will be added automatically later by the driver */
1883fcf3ce44SJohn Forte 	els = (ELS_PKT *)pkt->pkt_cmd;
1884fcf3ce44SJohn Forte 	els->elsCode = 0x04;	/* FLOGI */
1885fcf3ce44SJohn Forte 
1886fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
1887fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
18888f23e9faSHans Rosenfeld 		    "fct_flogi_xchg: FLOGI failed. "
188982527734SSukumar Swaminathan 		    "Unable to send packet.");
1890fcf3ce44SJohn Forte 
189182527734SSukumar Swaminathan 		rval = FCT_FAILURE;
189282527734SSukumar Swaminathan 		goto done;
1893fcf3ce44SJohn Forte 	}
1894291a2b48SSukumar Swaminathan 
1895fcf3ce44SJohn Forte 	if ((pkt->pkt_state != FC_PKT_SUCCESS) &&
1896fcf3ce44SJohn Forte 	    (pkt->pkt_state != FC_PKT_LS_RJT)) {
1897fcf3ce44SJohn Forte 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
189882527734SSukumar Swaminathan 			rval = FCT_TIMEOUT;
1899fcf3ce44SJohn Forte 		} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
1900fcf3ce44SJohn Forte 		    (pkt->pkt_reason == FC_REASON_FCAL_OPN_FAIL)) {
190182527734SSukumar Swaminathan 			rval = FCT_NOT_FOUND;
190282527734SSukumar Swaminathan 		} else {
190382527734SSukumar Swaminathan 			rval = FCT_FAILURE;
1904fcf3ce44SJohn Forte 		}
1905291a2b48SSukumar Swaminathan 
1906fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
19078f23e9faSHans Rosenfeld 		    "fct_flogi_xchg: FLOGI failed. state=%x reason=%x "
19088f23e9faSHans Rosenfeld 		    "rval=%llx", pkt->pkt_state, pkt->pkt_reason, rval);
1909fcf3ce44SJohn Forte 
191082527734SSukumar Swaminathan 		goto done;
1911fcf3ce44SJohn Forte 	}
1912291a2b48SSukumar Swaminathan 
1913fcf3ce44SJohn Forte 	if (pkt->pkt_state == FC_PKT_LS_RJT) {
1914fcf3ce44SJohn Forte 		fx->fx_op = ELS_OP_LSRJT;
1915fcf3ce44SJohn Forte 		fx->fx_rjt_reason = pkt->pkt_reason;
1916fcf3ce44SJohn Forte 		fx->fx_rjt_expl = pkt->pkt_expln;
1917fcf3ce44SJohn Forte 	} else {	/* FC_PKT_SUCCESS */
1918291a2b48SSukumar Swaminathan 
1919fcf3ce44SJohn Forte 		fx->fx_op = ELS_OP_ACC;
192082527734SSukumar Swaminathan 		fx->fx_sid = FABRIC_DID;
1921fcf3ce44SJohn Forte 		fx->fx_did = port->did;
1922fcf3ce44SJohn Forte 
1923291a2b48SSukumar Swaminathan 		els = (ELS_PKT *)pkt->pkt_resp;
1924fcf3ce44SJohn Forte 		bcopy((caddr_t)&els->un.logi.nodeName,
1925fcf3ce44SJohn Forte 		    (caddr_t)fx->fx_nwwn, 8);
1926fcf3ce44SJohn Forte 		bcopy((caddr_t)&els->un.logi.portName,
1927fcf3ce44SJohn Forte 		    (caddr_t)fx->fx_pwwn, 8);
1928fcf3ce44SJohn Forte 		fx->fx_fport = els->un.logi.cmn.fPort;
1929fcf3ce44SJohn Forte 	}
1930fcf3ce44SJohn Forte 
193182527734SSukumar Swaminathan done:
193282527734SSukumar Swaminathan 	if (pkt) {
193382527734SSukumar Swaminathan 		emlxs_pkt_free(pkt);
193482527734SSukumar Swaminathan 	}
193582527734SSukumar Swaminathan 
19368f23e9faSHans Rosenfeld 	if ((rval == FCT_SUCCESS) || (rval == FCT_NOT_FOUND)) {
19378f23e9faSHans Rosenfeld 
19388f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
19398f23e9faSHans Rosenfeld 		    "fct_flogi_xchg: FCT_STATE_FLOGI_CMPL.  rval=%s",
19408f23e9faSHans Rosenfeld 		    ((rval == FCT_SUCCESS)? "FCT_SUCCESS":"FCT_NOT_FOUND"));
19418f23e9faSHans Rosenfeld 
19428f23e9faSHans Rosenfeld 		mutex_enter(&EMLXS_PORT_LOCK);
19438f23e9faSHans Rosenfeld 		port->fct_flags |= FCT_STATE_FLOGI_CMPL;
19448f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PORT_LOCK);
19458f23e9faSHans Rosenfeld 
19468f23e9faSHans Rosenfeld 		/*
19478f23e9faSHans Rosenfeld 		 * Flush all unsolicited commands
19488f23e9faSHans Rosenfeld 		 * Must use separate thread since
19498f23e9faSHans Rosenfeld 		 * this thread must complete first
19508f23e9faSHans Rosenfeld 		 */
19518f23e9faSHans Rosenfeld 		emlxs_thread_spawn(hba, emlxs_fct_unsol_flush_thread,
19528f23e9faSHans Rosenfeld 		    (void *)port, 0);
19538f23e9faSHans Rosenfeld 	}
19548f23e9faSHans Rosenfeld 
195582527734SSukumar Swaminathan 	return (rval);
1956fcf3ce44SJohn Forte 
195782527734SSukumar Swaminathan } /* emlxs_fct_flogi_xchg() */
1958fcf3ce44SJohn Forte 
1959fcf3ce44SJohn Forte 
196082527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1961fcf3ce44SJohn Forte /* This is called right after we report that link has come online */
1962fcf3ce44SJohn Forte static fct_status_t
emlxs_fct_get_link_info(fct_local_port_t * fct_port,fct_link_info_t * link)1963fcf3ce44SJohn Forte emlxs_fct_get_link_info(fct_local_port_t *fct_port, fct_link_info_t *link)
1964fcf3ce44SJohn Forte {
1965fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1966fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1967fcf3ce44SJohn Forte 
1968fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
19698f23e9faSHans Rosenfeld 	    "fct_get_link_info %p: FCT: flg x%x  HBA: ste x%x flg x%x topo x%x",
19708f23e9faSHans Rosenfeld 	    fct_port, port->fct_flags, hba->state, hba->flag, hba->topology);
1971fcf3ce44SJohn Forte 
1972fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
1973fcf3ce44SJohn Forte 
19748f23e9faSHans Rosenfeld 	if (port->mode == MODE_INITIATOR) {
19758f23e9faSHans Rosenfeld 		link->port_topology = PORT_TOPOLOGY_UNKNOWN;
19768f23e9faSHans Rosenfeld 		link->port_speed = PORT_SPEED_UNKNOWN;
19778f23e9faSHans Rosenfeld 		link->portid = 0;
19788f23e9faSHans Rosenfeld 
19798f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PORT_LOCK);
19808f23e9faSHans Rosenfeld 
19818f23e9faSHans Rosenfeld 		return (FCT_SUCCESS);
19828f23e9faSHans Rosenfeld 	}
19838f23e9faSHans Rosenfeld 
1984fcf3ce44SJohn Forte 	if (!(port->fct_flags & FCT_STATE_LINK_UP) ||
1985291a2b48SSukumar Swaminathan 	    (hba->state < FC_LINK_UP) || (hba->flag & FC_LOOPBACK_MODE)) {
1986fcf3ce44SJohn Forte 		link->port_topology = PORT_TOPOLOGY_UNKNOWN;
1987fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_UNKNOWN;
1988fcf3ce44SJohn Forte 		link->portid = 0;
1989fcf3ce44SJohn Forte 
1990fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1991fcf3ce44SJohn Forte 
1992fcf3ce44SJohn Forte 		return (FCT_SUCCESS);
1993fcf3ce44SJohn Forte 	}
1994291a2b48SSukumar Swaminathan 
1995fcf3ce44SJohn Forte 	if (hba->topology == TOPOLOGY_LOOP) {
1996fcf3ce44SJohn Forte 		link->port_topology = PORT_TOPOLOGY_PRIVATE_LOOP;
1997fcf3ce44SJohn Forte 	} else {
1998fcf3ce44SJohn Forte 		link->port_topology = PORT_TOPOLOGY_PT_TO_PT;
1999fcf3ce44SJohn Forte 	}
2000fcf3ce44SJohn Forte 
2001fcf3ce44SJohn Forte 	switch (hba->linkspeed) {
2002fcf3ce44SJohn Forte 	case LA_1GHZ_LINK:
2003fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_1G;
2004fcf3ce44SJohn Forte 		break;
2005fcf3ce44SJohn Forte 	case LA_2GHZ_LINK:
2006fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_2G;
2007fcf3ce44SJohn Forte 		break;
2008fcf3ce44SJohn Forte 	case LA_4GHZ_LINK:
2009fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_4G;
2010fcf3ce44SJohn Forte 		break;
2011fcf3ce44SJohn Forte 	case LA_8GHZ_LINK:
2012fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_8G;
2013fcf3ce44SJohn Forte 		break;
2014fcf3ce44SJohn Forte 	case LA_10GHZ_LINK:
2015fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_10G;
2016fcf3ce44SJohn Forte 		break;
20178f23e9faSHans Rosenfeld 	case LA_16GHZ_LINK:
20188f23e9faSHans Rosenfeld 		link->port_speed = PORT_SPEED_16G;
20198f23e9faSHans Rosenfeld 		break;
2020a3170057SPaul Winder 	case LA_32GHZ_LINK:
2021a3170057SPaul Winder 		link->port_speed = PORT_SPEED_32G;
2022a3170057SPaul Winder 		break;
2023fcf3ce44SJohn Forte 	default:
2024fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_UNKNOWN;
2025fcf3ce44SJohn Forte 		break;
2026fcf3ce44SJohn Forte 	}
2027fcf3ce44SJohn Forte 
2028fcf3ce44SJohn Forte 	link->portid = port->did;
2029fcf3ce44SJohn Forte 	link->port_no_fct_flogi = 0;
2030fcf3ce44SJohn Forte 	link->port_fca_flogi_done = 0;
2031fcf3ce44SJohn Forte 	link->port_fct_flogi_done = 0;
2032fcf3ce44SJohn Forte 
2033fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
2034fcf3ce44SJohn Forte 
2035fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
2036fcf3ce44SJohn Forte 
203782527734SSukumar Swaminathan } /* emlxs_fct_get_link_info() */
2038fcf3ce44SJohn Forte 
2039fcf3ce44SJohn Forte 
204082527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
2041fcf3ce44SJohn Forte static fct_status_t
emlxs_fct_register_remote_port(fct_local_port_t * fct_port,fct_remote_port_t * remote_port,fct_cmd_t * fct_cmd)2042fcf3ce44SJohn Forte emlxs_fct_register_remote_port(fct_local_port_t *fct_port,
2043fcf3ce44SJohn Forte     fct_remote_port_t *remote_port, fct_cmd_t *fct_cmd)
2044fcf3ce44SJohn Forte {
2045fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
2046fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2047fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2048fcf3ce44SJohn Forte 	clock_t timeout;
2049fcf3ce44SJohn Forte 	int32_t pkt_ret;
2050fcf3ce44SJohn Forte 	fct_els_t *els;
2051fcf3ce44SJohn Forte 	SERV_PARM *sp;
2052fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
2053fcf3ce44SJohn Forte 	SERV_PARM sparam;
2054fcf3ce44SJohn Forte 	uint32_t *iptr;
20558f23e9faSHans Rosenfeld 	uint16_t hdl;
20563be114edSSukumar Swaminathan 	uint64_t addr;
205782527734SSukumar Swaminathan 	fct_status_t rval;
205882527734SSukumar Swaminathan 	fct_status_t rval2;
20598f23e9faSHans Rosenfeld 	uint32_t i;
2060fcf3ce44SJohn Forte 
2061fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2062fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
20638f23e9faSHans Rosenfeld 	    "fct_register_remote_port %p", fct_port);
2064291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2065fcf3ce44SJohn Forte 
2066fcf3ce44SJohn Forte 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
206782527734SSukumar Swaminathan 
206882527734SSukumar Swaminathan 		cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd,
206982527734SSukumar Swaminathan 		    EMLXS_FCT_REG_PENDING);
2070291a2b48SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
2071fcf3ce44SJohn Forte 
207282527734SSukumar Swaminathan 		cmd_sbp->channel = &hba->chan[hba->channel_els];
2073fcf3ce44SJohn Forte 		cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD;
207482527734SSukumar Swaminathan 
2075fcf3ce44SJohn Forte 	} else {
2076fcf3ce44SJohn Forte 
207782527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_accept(port, fct_cmd,
207882527734SSukumar Swaminathan 		    EMLXS_FCT_REG_PENDING);
207982527734SSukumar Swaminathan 		if (rval) {
208082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
20818f23e9faSHans Rosenfeld 			    "fct_register_remote_port: "
20828f23e9faSHans Rosenfeld 			    "Unable to accept fct_cmd. lid=%x rid=%x",
20838f23e9faSHans Rosenfeld 			    fct_cmd->cmd_lportid, fct_cmd->cmd_rportid);
2084291a2b48SSukumar Swaminathan 
208582527734SSukumar Swaminathan 			return (rval);
208682527734SSukumar Swaminathan 		}
208782527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
208882527734SSukumar Swaminathan 	}
2089fcf3ce44SJohn Forte 
2090a9800bebSGarrett D'Amore 	cmd_sbp->fct_flags &= ~EMLXS_FCT_REGISTERED;
20918f23e9faSHans Rosenfeld 	cmd_sbp->node = emlxs_node_find_did(port, fct_cmd->cmd_rportid, 1);
2092a9800bebSGarrett D'Amore 
20938f23e9faSHans Rosenfeld 	/* Check for unsolicited PLOGI */
20948f23e9faSHans Rosenfeld 	if (cmd_sbp->fct_flags & EMLXS_FCT_PLOGI_RECEIVED) {
2095fcf3ce44SJohn Forte 		els = (fct_els_t *)fct_cmd->cmd_specific;
20968f23e9faSHans Rosenfeld 		sp = (SERV_PARM *)((caddr_t)els->els_req_payload +
20978f23e9faSHans Rosenfeld 		    sizeof (uint32_t));
20988f23e9faSHans Rosenfeld 
20998f23e9faSHans Rosenfeld 	} else {	/* Solicited PLOGI */
21008f23e9faSHans Rosenfeld 
21018f23e9faSHans Rosenfeld 		sp = &sparam;
21028f23e9faSHans Rosenfeld 		bcopy((caddr_t)&port->sparam, (caddr_t)sp,
21038f23e9faSHans Rosenfeld 		    sizeof (SERV_PARM));
21048f23e9faSHans Rosenfeld 
21058f23e9faSHans Rosenfeld 		/*
21068f23e9faSHans Rosenfeld 		 * Create temporary WWN's from fct_cmd address
21078f23e9faSHans Rosenfeld 		 * This simply allows us to get an RPI from the
21088f23e9faSHans Rosenfeld 		 * adapter until we get real service params.
21098f23e9faSHans Rosenfeld 		 * The PLOGI ACC reply will trigger a REG_LOGIN
21108f23e9faSHans Rosenfeld 		 * update later
21118f23e9faSHans Rosenfeld 		 */
21128f23e9faSHans Rosenfeld 		addr = (uint64_t)((unsigned long)fct_cmd);
21138f23e9faSHans Rosenfeld 
21148f23e9faSHans Rosenfeld 		iptr = (uint32_t *)&sp->portName;
21158f23e9faSHans Rosenfeld 		iptr[0] = PADDR_HI(addr);
21168f23e9faSHans Rosenfeld 		iptr[1] = PADDR_LO(addr);
2117fcf3ce44SJohn Forte 
21188f23e9faSHans Rosenfeld 		iptr = (uint32_t *)&sp->nodeName;
21198f23e9faSHans Rosenfeld 		iptr[0] = PADDR_HI(addr);
21208f23e9faSHans Rosenfeld 		iptr[1] = PADDR_LO(addr);
21218f23e9faSHans Rosenfeld 	}
21228f23e9faSHans Rosenfeld 
21238f23e9faSHans Rosenfeld 	if (hba->flag & FC_PT_TO_PT) {
21248f23e9faSHans Rosenfeld 		mutex_enter(&EMLXS_PORT_LOCK);
21258f23e9faSHans Rosenfeld 		port->did = fct_cmd->cmd_lportid;
21268f23e9faSHans Rosenfeld 		port->rdid = fct_cmd->cmd_rportid;
21278f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PORT_LOCK);
2128291a2b48SSukumar Swaminathan 
21298f23e9faSHans Rosenfeld 		/*
21308f23e9faSHans Rosenfeld 		 * We already received the remote port's
21318f23e9faSHans Rosenfeld 		 * parameters in the FLOGI exchange
21328f23e9faSHans Rosenfeld 		 */
21338f23e9faSHans Rosenfeld 		if (!(cmd_sbp->fct_flags & EMLXS_FCT_PLOGI_RECEIVED)) {
2134fcf3ce44SJohn Forte 			sp = &sparam;
21358f23e9faSHans Rosenfeld 			bcopy((caddr_t)&port->fabric_sparam, (caddr_t)sp,
2136fcf3ce44SJohn Forte 			    sizeof (SERV_PARM));
2137fcf3ce44SJohn Forte 
2138fcf3ce44SJohn Forte 			/*
21398f23e9faSHans Rosenfeld 			 * Since this is a PLOGI, not a FLOGI, we need
21408f23e9faSHans Rosenfeld 			 * to fix up word2 of the CSP accordingly.
2141fcf3ce44SJohn Forte 			 */
21428f23e9faSHans Rosenfeld 			sp->cmn.w2.r_a_tov = port->sparam.cmn.w2.r_a_tov;
2143fcf3ce44SJohn Forte 		}
21448f23e9faSHans Rosenfeld 	}
2145fcf3ce44SJohn Forte 
21468f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
21478f23e9faSHans Rosenfeld 	    "fct_register_remote_port: Register lid=%x rid=%x. (%x,%x,%p)",
21488f23e9faSHans Rosenfeld 	    fct_cmd->cmd_lportid, fct_cmd->cmd_rportid, cmd_sbp->fct_state,
21498f23e9faSHans Rosenfeld 	    hba->flag, fct_cmd);
2150fcf3ce44SJohn Forte 
21518f23e9faSHans Rosenfeld 	emlxs_fct_cmd_release(port, fct_cmd, 0);
21528f23e9faSHans Rosenfeld 	/* mutex_exit(&cmd_sbp->fct_mtx); */
215382527734SSukumar Swaminathan 
21548f23e9faSHans Rosenfeld 	/* Create a new node */
21558f23e9faSHans Rosenfeld 	if (EMLXS_SLI_REG_DID(port, fct_cmd->cmd_rportid, sp, cmd_sbp,
21568f23e9faSHans Rosenfeld 	    NULL, NULL) != 0) {
21578f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
21588f23e9faSHans Rosenfeld 		    "fct_register_remote_port: "
21598f23e9faSHans Rosenfeld 		    "Reg login failed. lid=%x rid=%x",
21608f23e9faSHans Rosenfeld 		    fct_cmd->cmd_lportid, fct_cmd->cmd_rportid);
21618f23e9faSHans Rosenfeld 	} else {
2162fcf3ce44SJohn Forte 
21638f23e9faSHans Rosenfeld 		/* Wait for completion */
21648f23e9faSHans Rosenfeld 		mutex_enter(&EMLXS_PKT_LOCK);
21658f23e9faSHans Rosenfeld 		timeout = emlxs_timeout(hba, 30);
21668f23e9faSHans Rosenfeld 		pkt_ret = 0;
21678f23e9faSHans Rosenfeld 		while ((pkt_ret != -1) &&
21688f23e9faSHans Rosenfeld 		    (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) &&
21698f23e9faSHans Rosenfeld 		    !(cmd_sbp->fct_flags & EMLXS_FCT_REGISTERED)) {
21708f23e9faSHans Rosenfeld 			pkt_ret = cv_timedwait(&EMLXS_PKT_CV,
21718f23e9faSHans Rosenfeld 			    &EMLXS_PKT_LOCK, timeout);
2172fcf3ce44SJohn Forte 		}
21738f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PKT_LOCK);
21748f23e9faSHans Rosenfeld 	}
2175fcf3ce44SJohn Forte 
21768f23e9faSHans Rosenfeld 	/* Reacquire ownership of the fct_cmd */
21778f23e9faSHans Rosenfeld 	rval2 = emlxs_fct_cmd_acquire(port, fct_cmd,
21788f23e9faSHans Rosenfeld 	    EMLXS_FCT_REG_COMPLETE);
21798f23e9faSHans Rosenfeld 	if (rval2) {
21808f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
21818f23e9faSHans Rosenfeld 		    "fct_register_remote_port: "
21828f23e9faSHans Rosenfeld 		    "Unable to reacquire fct_cmd. lid=%x rid=%x",
21838f23e9faSHans Rosenfeld 		    fct_cmd->cmd_lportid, fct_cmd->cmd_rportid);
218482527734SSukumar Swaminathan 
21858f23e9faSHans Rosenfeld 		return (rval2);
2186fcf3ce44SJohn Forte 	}
21878f23e9faSHans Rosenfeld 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2188291a2b48SSukumar Swaminathan 
21898f23e9faSHans Rosenfeld 	/* Prepare response */
2190fcf3ce44SJohn Forte 
2191fcf3ce44SJohn Forte 	ndlp = (emlxs_node_t *)cmd_sbp->node;
2192fcf3ce44SJohn Forte 
2193fcf3ce44SJohn Forte 	if (ndlp) {
2194a9800bebSGarrett D'Amore 		cmd_sbp->fct_flags |= EMLXS_FCT_REGISTERED;
2195a9800bebSGarrett D'Amore 
2196291a2b48SSukumar Swaminathan 		*((emlxs_node_t **)remote_port->rp_fca_private) =
2197291a2b48SSukumar Swaminathan 		    cmd_sbp->node;
2198fcf3ce44SJohn Forte 
21998f23e9faSHans Rosenfeld 		hdl = ndlp->nlp_Rpi;
22008f23e9faSHans Rosenfeld 		if (hdl == FABRIC_RPI) {
22018f23e9faSHans Rosenfeld 			if (fct_cmd->cmd_rportid == SCR_DID) {
22028f23e9faSHans Rosenfeld 				/* The SCR handle is hardcoded */
22038f23e9faSHans Rosenfeld 				remote_port->rp_handle = hba->max_nodes;
22048f23e9faSHans Rosenfeld 				port->fct_els_only_bmap |= 1;
22058f23e9faSHans Rosenfeld 
22068f23e9faSHans Rosenfeld 			} else {
22078f23e9faSHans Rosenfeld 				for (i = 1; i < EMLXS_FCT_NUM_ELS_ONLY; i++) {
22088f23e9faSHans Rosenfeld 					if (port->fct_els_only_bmap & (1 << i))
22098f23e9faSHans Rosenfeld 						continue;
22108f23e9faSHans Rosenfeld 					/*
22118f23e9faSHans Rosenfeld 					 * Bit is not set, so use this
22128f23e9faSHans Rosenfeld 					 * for the handle
22138f23e9faSHans Rosenfeld 					 */
22148f23e9faSHans Rosenfeld 					remote_port->rp_handle =
22158f23e9faSHans Rosenfeld 					    hba->max_nodes + i;
22168f23e9faSHans Rosenfeld 					port->fct_els_only_bmap |= (1 << i);
22178f23e9faSHans Rosenfeld 					break;
22188f23e9faSHans Rosenfeld 				}
22198f23e9faSHans Rosenfeld 				if (i >= EMLXS_FCT_NUM_ELS_ONLY) {
22208f23e9faSHans Rosenfeld 					remote_port->rp_handle =
22218f23e9faSHans Rosenfeld 					    FCT_HANDLE_NONE;
22228f23e9faSHans Rosenfeld 				}
22238f23e9faSHans Rosenfeld 			}
22248f23e9faSHans Rosenfeld 		} else {
22258f23e9faSHans Rosenfeld 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
22268f23e9faSHans Rosenfeld 				hdl = emlxs_sli4_rpi_to_index(hba, hdl);
22278f23e9faSHans Rosenfeld 			}
22288f23e9faSHans Rosenfeld 			remote_port->rp_handle = hdl;
22298f23e9faSHans Rosenfeld 		}
2230fcf3ce44SJohn Forte 
22318f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
22328f23e9faSHans Rosenfeld 		    "fct_register_remote_port: lid=%x rid=%x hdl=%x",
22338f23e9faSHans Rosenfeld 		    fct_cmd->cmd_lportid, fct_cmd->cmd_rportid,
22348f23e9faSHans Rosenfeld 		    remote_port->rp_handle);
2235fcf3ce44SJohn Forte 
2236fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
223782527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2238291a2b48SSukumar Swaminathan 
2239fcf3ce44SJohn Forte 		TGTPORTSTAT.FctPortRegister++;
2240fcf3ce44SJohn Forte 		return (FCT_SUCCESS);
2241fcf3ce44SJohn Forte 	} else {
2242fcf3ce44SJohn Forte 		*((emlxs_node_t **)remote_port->rp_fca_private) = NULL;
2243fcf3ce44SJohn Forte 
2244fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
22458f23e9faSHans Rosenfeld 		    "fct_register_remote_port: failed. lid=%x rid=%x hdl=%x",
22468f23e9faSHans Rosenfeld 		    fct_cmd->cmd_lportid, fct_cmd->cmd_rportid,
22478f23e9faSHans Rosenfeld 		    remote_port->rp_handle);
2248fcf3ce44SJohn Forte 
2249fcf3ce44SJohn Forte 		remote_port->rp_handle = FCT_HANDLE_NONE;
2250fcf3ce44SJohn Forte 
2251fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
225282527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2253291a2b48SSukumar Swaminathan 
2254fcf3ce44SJohn Forte 		TGTPORTSTAT.FctFailedPortRegister++;
2255fcf3ce44SJohn Forte 		return (FCT_FAILURE);
2256fcf3ce44SJohn Forte 	}
2257fcf3ce44SJohn Forte 
225882527734SSukumar Swaminathan } /* emlxs_fct_register_remote_port() */
2259fcf3ce44SJohn Forte 
2260fcf3ce44SJohn Forte 
226182527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
2262fcf3ce44SJohn Forte static fct_status_t
emlxs_fct_deregister_remote_port(fct_local_port_t * fct_port,fct_remote_port_t * remote_port)2263fcf3ce44SJohn Forte emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port,
2264fcf3ce44SJohn Forte     fct_remote_port_t *remote_port)
2265fcf3ce44SJohn Forte {
2266fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
22678f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
2268a9800bebSGarrett D'Amore 	emlxs_node_t *ndlp;
22698f23e9faSHans Rosenfeld 	uint32_t i;
2270fcf3ce44SJohn Forte 
2271fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2272fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
22738f23e9faSHans Rosenfeld 	    "fct_deregister_remote_port: did=%x hdl=%x",
2274fcf3ce44SJohn Forte 	    remote_port->rp_id, remote_port->rp_handle);
2275fcf3ce44SJohn Forte #else
2276fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
22778f23e9faSHans Rosenfeld 	    "fct_deregister_remote_port: did=%x hdl=%x",
2278fcf3ce44SJohn Forte 	    remote_port->rp_id, remote_port->rp_handle);
2279291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2280fcf3ce44SJohn Forte 
22818f23e9faSHans Rosenfeld 	if (remote_port->rp_handle >= hba->max_nodes) {
22828f23e9faSHans Rosenfeld 		i = remote_port->rp_handle - hba->max_nodes;
22838f23e9faSHans Rosenfeld 		if ((i < EMLXS_FCT_NUM_ELS_ONLY) &&
22848f23e9faSHans Rosenfeld 		    (port->fct_els_only_bmap & (1 << i))) {
22858f23e9faSHans Rosenfeld 			port->fct_els_only_bmap &= ~(1 << i);
22868f23e9faSHans Rosenfeld 		}
22878f23e9faSHans Rosenfeld 	}
22888f23e9faSHans Rosenfeld 
2289a9800bebSGarrett D'Amore 	ndlp = *((emlxs_node_t **)remote_port->rp_fca_private);
2290fcf3ce44SJohn Forte 	*((emlxs_node_t **)remote_port->rp_fca_private) = NULL;
2291a9800bebSGarrett D'Amore 
2292a9800bebSGarrett D'Amore 	if (ndlp) {
22938f23e9faSHans Rosenfeld 		(void) EMLXS_SLI_UNREG_NODE(port, ndlp, NULL,
2294a9800bebSGarrett D'Amore 		    NULL, NULL);
2295a9800bebSGarrett D'Amore 	}
2296fcf3ce44SJohn Forte 
2297fcf3ce44SJohn Forte 	TGTPORTSTAT.FctPortDeregister++;
2298fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
2299fcf3ce44SJohn Forte 
230082527734SSukumar Swaminathan } /* emlxs_fct_deregister_remote_port() */
2301fcf3ce44SJohn Forte 
2302fcf3ce44SJohn Forte 
2303fcf3ce44SJohn Forte /* ARGSUSED */
2304fcf3ce44SJohn Forte extern int
emlxs_fct_handle_unsol_req(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)230582527734SSukumar Swaminathan emlxs_fct_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
2306fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
2307fcf3ce44SJohn Forte {
23088f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
2309fcf3ce44SJohn Forte 	IOCB *iocb;
2310fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
2311fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
2312fcf3ce44SJohn Forte 	emlxs_fcp_cmd_t *fcp_cmd;
2313fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
2314fcf3ce44SJohn Forte 	uint32_t cnt;
2315fcf3ce44SJohn Forte 	uint32_t tm;
23168f23e9faSHans Rosenfeld 	uint16_t hdl;
2317fcf3ce44SJohn Forte 	scsi_task_t *fct_task;
2318fcf3ce44SJohn Forte 	uint8_t lun[8];
2319fcf3ce44SJohn Forte 	uint32_t sid = 0;
2320fcf3ce44SJohn Forte 
2321fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
232282527734SSukumar Swaminathan 	ndlp = emlxs_node_find_rpi(port, iocb->ULPIOTAG);
2323fcf3ce44SJohn Forte 	if (!ndlp) {
2324fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
23258f23e9faSHans Rosenfeld 		    "FCP rcvd: Unknown RPI. rpi=%d rxid=%x. Dropping...",
232682527734SSukumar Swaminathan 		    iocb->ULPIOTAG, iocb->ULPCONTEXT);
2327fcf3ce44SJohn Forte 
2328fcf3ce44SJohn Forte 		goto dropped;
2329fcf3ce44SJohn Forte 	}
2330fcf3ce44SJohn Forte 	sid = ndlp->nlp_DID;
2331fcf3ce44SJohn Forte 
2332fcf3ce44SJohn Forte 	fcp_cmd = (emlxs_fcp_cmd_t *)mp->virt;
2333fcf3ce44SJohn Forte 
2334fcf3ce44SJohn Forte 	if (!port->fct_port) {
2335fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
23368f23e9faSHans Rosenfeld 		    "FCP rcvd: Target unbound. rpi=%d rxid=%x. Dropping...",
233782527734SSukumar Swaminathan 		    iocb->ULPIOTAG, iocb->ULPCONTEXT);
2338fcf3ce44SJohn Forte 
2339fcf3ce44SJohn Forte 		emlxs_send_logo(port, sid);
2340fcf3ce44SJohn Forte 
2341fcf3ce44SJohn Forte 		goto dropped;
2342fcf3ce44SJohn Forte 	}
2343291a2b48SSukumar Swaminathan 
2344fcf3ce44SJohn Forte 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
2345fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
23468f23e9faSHans Rosenfeld 		    "FCP rcvd: Target offline. rpi=%d rxid=%x. Dropping...",
234782527734SSukumar Swaminathan 		    iocb->ULPIOTAG, iocb->ULPCONTEXT);
2348fcf3ce44SJohn Forte 
2349fcf3ce44SJohn Forte 		emlxs_send_logo(port, sid);
2350fcf3ce44SJohn Forte 
2351fcf3ce44SJohn Forte 		goto dropped;
2352fcf3ce44SJohn Forte 	}
2353291a2b48SSukumar Swaminathan 
2354fcf3ce44SJohn Forte 	/* Get lun id */
2355fcf3ce44SJohn Forte 	bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8);
2356fcf3ce44SJohn Forte 
2357fcf3ce44SJohn Forte 	if (TGTPORTSTAT.FctOutstandingIO >= port->fct_port->port_max_xchges) {
2358fcf3ce44SJohn Forte 		TGTPORTSTAT.FctOverQDepth++;
2359fcf3ce44SJohn Forte 	}
2360291a2b48SSukumar Swaminathan 
23618f23e9faSHans Rosenfeld 	hdl = ndlp->nlp_Rpi;
23628f23e9faSHans Rosenfeld 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
23638f23e9faSHans Rosenfeld 		hdl = emlxs_sli4_rpi_to_index(hba, hdl);
23648f23e9faSHans Rosenfeld 	}
2365291a2b48SSukumar Swaminathan 	fct_cmd =
23668f23e9faSHans Rosenfeld 	    MODSYM(fct_scsi_task_alloc) (port->fct_port, hdl, sid, lun, 16, 0);
2367fcf3ce44SJohn Forte 
2368fcf3ce44SJohn Forte 	if (fct_cmd == NULL) {
2369fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2370291a2b48SSukumar Swaminathan 		    "FCP rcvd: sid=%x xid=%x. "
2371291a2b48SSukumar Swaminathan 		    "Unable to allocate scsi task. Returning QFULL.",
237282527734SSukumar Swaminathan 		    sid, iocb->ULPCONTEXT);
2373fcf3ce44SJohn Forte 
237482527734SSukumar Swaminathan 		(void) emlxs_fct_send_qfull_reply(port, ndlp, iocb->ULPCONTEXT,
237582527734SSukumar Swaminathan 		    iocb->ULPCLASS, fcp_cmd);
2376fcf3ce44SJohn Forte 
2377fcf3ce44SJohn Forte 		goto dropped;
2378fcf3ce44SJohn Forte 	}
2379291a2b48SSukumar Swaminathan 
2380fcf3ce44SJohn Forte 	/* Initialize fct_cmd */
2381fcf3ce44SJohn Forte 	fct_cmd->cmd_rportid = sid;
2382fcf3ce44SJohn Forte 	fct_cmd->cmd_lportid = port->did;
23838f23e9faSHans Rosenfeld 	fct_cmd->cmd_rp_handle = hdl;
2384fcf3ce44SJohn Forte 	fct_cmd->cmd_port = port->fct_port;
2385fcf3ce44SJohn Forte 
238682527734SSukumar Swaminathan 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_FCP_CMD_RECEIVED);
238782527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2388fcf3ce44SJohn Forte 
23898f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
23908f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
23918f23e9faSHans Rosenfeld 	    "fct_scsi_task_alloc %p:%p FCP rcvd: "
23928f23e9faSHans Rosenfeld 	    "cmd=%x sid=%x rxid=%x oxid=%x lun=%02x%02x dl=%d",
23938f23e9faSHans Rosenfeld 	    fct_cmd, cmd_sbp, fcp_cmd->fcpCdb[0], sid, iocb->ULPCONTEXT,
23948f23e9faSHans Rosenfeld 	    iocb->unsli3.ext_rcv.oxid, lun[0], lun[1],
23958f23e9faSHans Rosenfeld 	    LE_SWAP32(fcp_cmd->fcpDl));
23968f23e9faSHans Rosenfeld #endif /* FCT_API_TRACE */
23978f23e9faSHans Rosenfeld 
2398291a2b48SSukumar Swaminathan 	/* Initialize cmd_sbp */
239982527734SSukumar Swaminathan 	cmd_sbp->channel = cp;
240082527734SSukumar Swaminathan 	cmd_sbp->class = iocb->ULPCLASS;
2401fcf3ce44SJohn Forte 	cmd_sbp->lun = (lun[0] << 8) | lun[1];
2402fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_FCP_CMD;
24038f23e9faSHans Rosenfeld 	cmd_sbp->ticks = hba->timer_tics + (2 * hba->fc_ratov);
2404fcf3ce44SJohn Forte 
24058f23e9faSHans Rosenfeld 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
24068f23e9faSHans Rosenfeld 		/* xrip was setup / passed in from the SLI layer */
24078f23e9faSHans Rosenfeld 		cmd_sbp->xrip = iocbq->sbp;
24088f23e9faSHans Rosenfeld 		cmd_sbp->node = iocbq->node;
24098f23e9faSHans Rosenfeld 		iocbq->sbp = 0;
2410fcf3ce44SJohn Forte 
24118f23e9faSHans Rosenfeld 		fct_cmd->cmd_oxid = cmd_sbp->xrip->rx_id;
24128f23e9faSHans Rosenfeld 		fct_cmd->cmd_rxid = cmd_sbp->xrip->XRI;
24138f23e9faSHans Rosenfeld 
24148f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
24158f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
24168f23e9faSHans Rosenfeld 		    "FCP rcvd: oxid=%x rxid=%x iotag=%d %p ",
24178f23e9faSHans Rosenfeld 		    fct_cmd->cmd_oxid, fct_cmd->cmd_rxid, cmd_sbp->xrip->iotag,
24188f23e9faSHans Rosenfeld 		    hba->fc_table[cmd_sbp->xrip->iotag]);
24198f23e9faSHans Rosenfeld #endif /* FCT_API_TRACE */
24208f23e9faSHans Rosenfeld 
24218f23e9faSHans Rosenfeld 	} else {
24228f23e9faSHans Rosenfeld 		fct_cmd->cmd_oxid = iocb->unsli3.ext_rcv.oxid;
24238f23e9faSHans Rosenfeld 		if (!fct_cmd->cmd_oxid) {
24248f23e9faSHans Rosenfeld 			fct_cmd->cmd_oxid = 0xFFFF;
24258f23e9faSHans Rosenfeld 		}
24268f23e9faSHans Rosenfeld 		fct_cmd->cmd_rxid = iocb->ULPCONTEXT;
24278f23e9faSHans Rosenfeld 	}
24288f23e9faSHans Rosenfeld 
24298f23e9faSHans Rosenfeld 
24308f23e9faSHans Rosenfeld 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
24318f23e9faSHans Rosenfeld 
24328f23e9faSHans Rosenfeld 	/* Set task_flags */
2433291a2b48SSukumar Swaminathan 	switch (fcp_cmd->fcpCntl1) {
2434291a2b48SSukumar Swaminathan 	case SIMPLE_Q:
2435fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_SIMPLE_QUEUE;
2436fcf3ce44SJohn Forte 		break;
2437fcf3ce44SJohn Forte 
2438291a2b48SSukumar Swaminathan 	case HEAD_OF_Q:
2439fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_HEAD_OF_QUEUE;
2440fcf3ce44SJohn Forte 		break;
2441fcf3ce44SJohn Forte 
2442291a2b48SSukumar Swaminathan 	case ORDERED_Q:
2443fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_ORDERED_QUEUE;
2444fcf3ce44SJohn Forte 		break;
2445fcf3ce44SJohn Forte 
2446291a2b48SSukumar Swaminathan 	case ACA_Q:
2447fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_ACA;
2448fcf3ce44SJohn Forte 		break;
2449fcf3ce44SJohn Forte 
2450291a2b48SSukumar Swaminathan 	case UNTAGGED:
2451fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_UNTAGGED;
2452fcf3ce44SJohn Forte 		break;
2453fcf3ce44SJohn Forte 	}
2454fcf3ce44SJohn Forte 
245582527734SSukumar Swaminathan 	cnt = LE_SWAP32(fcp_cmd->fcpDl);
2456fcf3ce44SJohn Forte 	switch (fcp_cmd->fcpCntl3) {
2457fcf3ce44SJohn Forte 	case 0:
2458fcf3ce44SJohn Forte 		TGTPORTSTAT.FctIOCmdCnt++;
2459fcf3ce44SJohn Forte 		break;
2460fcf3ce44SJohn Forte 	case 1:
246182527734SSukumar Swaminathan 		EMLXS_BUMP_WRIOCTR(port, cnt);
2462fcf3ce44SJohn Forte 		TGTPORTSTAT.FctWriteBytes += cnt;
2463fcf3ce44SJohn Forte 		fct_task->task_flags |= TF_WRITE_DATA;
2464fcf3ce44SJohn Forte 		break;
2465fcf3ce44SJohn Forte 
2466fcf3ce44SJohn Forte 	case 2:
246782527734SSukumar Swaminathan 		EMLXS_BUMP_RDIOCTR(port, cnt);
2468fcf3ce44SJohn Forte 		TGTPORTSTAT.FctReadBytes += cnt;
2469fcf3ce44SJohn Forte 		fct_task->task_flags |= TF_READ_DATA;
2470fcf3ce44SJohn Forte 		break;
2471fcf3ce44SJohn Forte 	}
2472fcf3ce44SJohn Forte 
2473fcf3ce44SJohn Forte 	fct_task->task_priority = 0;
2474fcf3ce44SJohn Forte 
2475fcf3ce44SJohn Forte 	/* task_mgmt_function */
2476fcf3ce44SJohn Forte 	tm = fcp_cmd->fcpCntl2;
2477fcf3ce44SJohn Forte 	if (tm) {
2478fcf3ce44SJohn Forte 		if (tm & BIT_1) {
2479fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_ABORT_TASK_SET;
2480fcf3ce44SJohn Forte 		} else if (tm & BIT_2) {
2481fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_CLEAR_TASK_SET;
2482fcf3ce44SJohn Forte 		} else if (tm & BIT_4) {
2483fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_LUN_RESET;
2484fcf3ce44SJohn Forte 		} else if (tm & BIT_5) {
2485fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_TARGET_COLD_RESET;
2486fcf3ce44SJohn Forte 		} else if (tm & BIT_6) {
2487fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_CLEAR_ACA;
2488fcf3ce44SJohn Forte 		} else {
2489fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_ABORT_TASK;
2490fcf3ce44SJohn Forte 		}
2491fcf3ce44SJohn Forte 	}
2492291a2b48SSukumar Swaminathan 
2493fcf3ce44SJohn Forte 	/* Parallel buffers support - future */
2494fcf3ce44SJohn Forte 	fct_task->task_max_nbufs = 1;
2495fcf3ce44SJohn Forte 
2496fcf3ce44SJohn Forte 	fct_task->task_additional_flags = 0;
2497fcf3ce44SJohn Forte 	fct_task->task_cur_nbufs = 0;
2498fcf3ce44SJohn Forte 	fct_task->task_csn_size = 8;
2499fcf3ce44SJohn Forte 	fct_task->task_cmd_seq_no = 0;
2500fcf3ce44SJohn Forte 	fct_task->task_expected_xfer_length = cnt;
2501fcf3ce44SJohn Forte 	bcopy((void *)&fcp_cmd->fcpCdb, fct_task->task_cdb, 16);
2502fcf3ce44SJohn Forte 
2503fcf3ce44SJohn Forte 	TGTPORTSTAT.FctCmdReceived++;
2504fcf3ce44SJohn Forte 	TGTPORTSTAT.FctOutstandingIO++;
2505fcf3ce44SJohn Forte 
250682527734SSukumar Swaminathan 	emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
250782527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
2508fcf3ce44SJohn Forte 
2509291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
2510291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
25118f23e9faSHans Rosenfeld 	    "fct_post_rcvd_cmd:3 %p:%p portid x%x, %d outio %d",
25128f23e9faSHans Rosenfeld 	    fct_cmd, cmd_sbp, fct_cmd->cmd_lportid,
25138f23e9faSHans Rosenfeld 	    fct_task->task_expected_xfer_length,
25148f23e9faSHans Rosenfeld 	    TGTPORTSTAT.FctOutstandingIO);
2515291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
251682527734SSukumar Swaminathan 
2517291a2b48SSukumar Swaminathan 	MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
2518fcf3ce44SJohn Forte 
2519fcf3ce44SJohn Forte 	return (0);
2520fcf3ce44SJohn Forte 
2521fcf3ce44SJohn Forte dropped:
2522fcf3ce44SJohn Forte 
2523fcf3ce44SJohn Forte 	TGTPORTSTAT.FctRcvDropped++;
2524fcf3ce44SJohn Forte 	return (1);
2525fcf3ce44SJohn Forte 
252682527734SSukumar Swaminathan } /* emlxs_fct_handle_unsol_req() */
2527fcf3ce44SJohn Forte 
2528fcf3ce44SJohn Forte 
252982527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
2530fcf3ce44SJohn Forte /* ARGSUSED */
2531fcf3ce44SJohn Forte static fct_status_t
emlxs_fct_send_fcp_data(fct_cmd_t * fct_cmd,stmf_data_buf_t * dbuf,uint32_t ioflags)2532fcf3ce44SJohn Forte emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd, stmf_data_buf_t *dbuf,
2533fcf3ce44SJohn Forte     uint32_t ioflags)
2534fcf3ce44SJohn Forte {
2535fcf3ce44SJohn Forte 	emlxs_port_t *port =
2536fcf3ce44SJohn Forte 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
2537fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2538fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
2539291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
2540fcf3ce44SJohn Forte 	scsi_task_t *fct_task;
2541291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2542fcf3ce44SJohn Forte 	IOCBQ *iocbq;
2543fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
2544fcf3ce44SJohn Forte 
254582527734SSukumar Swaminathan 	int	channel;
254682527734SSukumar Swaminathan 	int	channelno;
2547b3660a96SSukumar Swaminathan 	fct_status_t rval = 0;
2548fcf3ce44SJohn Forte 
254982527734SSukumar Swaminathan 	rval = emlxs_fct_cmd_accept(port, fct_cmd, EMLXS_FCT_SEND_FCP_DATA);
255082527734SSukumar Swaminathan 	if (rval) {
255182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
25528f23e9faSHans Rosenfeld 		    "fct_send_fcp_data: "
255382527734SSukumar Swaminathan 		    "Unable to accept fct_cmd. did=%x",
255482527734SSukumar Swaminathan 		    fct_cmd->cmd_rportid);
2555fcf3ce44SJohn Forte 
255682527734SSukumar Swaminathan 		return (rval);
2557fcf3ce44SJohn Forte 	}
255882527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2559291a2b48SSukumar Swaminathan 
256082527734SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
256182527734SSukumar Swaminathan #ifdef FCT_API_TRACE
256282527734SSukumar Swaminathan 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
256382527734SSukumar Swaminathan #endif /* FCT_API_TRACE */
256482527734SSukumar Swaminathan 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
2565291a2b48SSukumar Swaminathan 
2566fcf3ce44SJohn Forte 	cmd_sbp->node = ndlp;
2567fcf3ce44SJohn Forte 	cmd_sbp->fct_buf = dbuf;
2568fcf3ce44SJohn Forte 
256982527734SSukumar Swaminathan 	channelno = ((CHANNEL *)cmd_sbp->channel)->channelno;
257082527734SSukumar Swaminathan 
257182527734SSukumar Swaminathan 	channel = channelno;
257282527734SSukumar Swaminathan 
257382527734SSukumar Swaminathan 
257482527734SSukumar Swaminathan 
2575fcf3ce44SJohn Forte 	iocbq = &cmd_sbp->iocbq;
25768f23e9faSHans Rosenfeld 	iocbq->sbp = cmd_sbp;
2577fcf3ce44SJohn Forte 
2578fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2579fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
25808f23e9faSHans Rosenfeld 	    "fct_send_fcp_data %p:%p flgs=%x ioflags=%x dl=%d,%d,%d,%d",
25818f23e9faSHans Rosenfeld 	    fct_cmd, cmd_sbp, dbuf->db_flags, ioflags,
25828f23e9faSHans Rosenfeld 	    fct_task->task_cmd_xfer_length,
258382527734SSukumar Swaminathan 	    fct_task->task_nbytes_transferred, dbuf->db_data_size,
258482527734SSukumar Swaminathan 	    fct_task->task_expected_xfer_length);
2585291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2586fcf3ce44SJohn Forte 
25878f23e9faSHans Rosenfeld 	/* Setup for I/O prep routine */
25888f23e9faSHans Rosenfeld 	iocbq->iocb.ULPCOMMAND = 0;
25898f23e9faSHans Rosenfeld 
259082527734SSukumar Swaminathan 	if (EMLXS_SLI_PREP_FCT_IOCB(port, cmd_sbp, channel) != IOERR_SUCCESS) {
259182527734SSukumar Swaminathan 
2592fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
259382527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2594fcf3ce44SJohn Forte 
2595fcf3ce44SJohn Forte 		return (FCT_BUSY);
2596fcf3ce44SJohn Forte 	}
2597291a2b48SSukumar Swaminathan 
2598fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_FCP_DATA;
2599fcf3ce44SJohn Forte 
2600fcf3ce44SJohn Forte 	if (dbuf->db_flags & DB_SEND_STATUS_GOOD) {
2601fcf3ce44SJohn Forte 		cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
2602fcf3ce44SJohn Forte 	}
2603fcf3ce44SJohn Forte 
2604fcf3ce44SJohn Forte 	if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
2605b3660a96SSukumar Swaminathan 		if (emlxs_fct_dbuf_dma_sync(hba, dbuf, DDI_DMA_SYNC_FORDEV)) {
2606b3660a96SSukumar Swaminathan 			emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
2607b3660a96SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
2608b3660a96SSukumar Swaminathan 
26098f23e9faSHans Rosenfeld 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
26108f23e9faSHans Rosenfeld 				emlxs_sli4_free_xri(port, cmd_sbp, 0, 0);
26118f23e9faSHans Rosenfeld 			}
2612b3660a96SSukumar Swaminathan 			return (FCT_BUSY);
2613b3660a96SSukumar Swaminathan 		}
2614fcf3ce44SJohn Forte 	}
2615291a2b48SSukumar Swaminathan 
2616291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
261782527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_DATA_PENDING);
261882527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
261982527734SSukumar Swaminathan 
262082527734SSukumar Swaminathan 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cmd_sbp->channel, iocbq);
2621fcf3ce44SJohn Forte 
2622fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
2623fcf3ce44SJohn Forte 
262482527734SSukumar Swaminathan } /* emlxs_fct_send_fcp_data() */
2625fcf3ce44SJohn Forte 
2626fcf3ce44SJohn Forte 
262782527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
262882527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be released before exiting */
2629fcf3ce44SJohn Forte static fct_status_t
emlxs_fct_send_fcp_status(fct_cmd_t * fct_cmd)2630fcf3ce44SJohn Forte emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd)
2631fcf3ce44SJohn Forte {
2632fcf3ce44SJohn Forte 	emlxs_port_t *port =
2633fcf3ce44SJohn Forte 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
2634fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2635fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
2636fcf3ce44SJohn Forte 	scsi_task_t *fct_task;
2637fcf3ce44SJohn Forte 	fc_packet_t *pkt;
26388f23e9faSHans Rosenfeld 	emlxs_buf_t *sbp = NULL;
2639fcf3ce44SJohn Forte 	emlxs_fcp_rsp *fcp_rsp;
2640fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
264182527734SSukumar Swaminathan 	fct_status_t rval;
26428f23e9faSHans Rosenfeld 	uint32_t did;
26438f23e9faSHans Rosenfeld 	uint32_t size;
2644fcf3ce44SJohn Forte 
2645fcf3ce44SJohn Forte 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
2646fcf3ce44SJohn Forte 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
2647fcf3ce44SJohn Forte 	did = fct_cmd->cmd_rportid;
2648fcf3ce44SJohn Forte 
2649fcf3ce44SJohn Forte 	/* Initialize cmd_sbp */
2650fcf3ce44SJohn Forte 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2651fcf3ce44SJohn Forte 
265282527734SSukumar Swaminathan 	EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_SEND_FCP_STATUS);
2653291a2b48SSukumar Swaminathan 
2654fcf3ce44SJohn Forte 	cmd_sbp->node = ndlp;
2655fcf3ce44SJohn Forte 
2656fcf3ce44SJohn Forte 	size = 24;
2657fcf3ce44SJohn Forte 	if (fct_task->task_sense_length) {
2658fcf3ce44SJohn Forte 		size += fct_task->task_sense_length;
2659fcf3ce44SJohn Forte 	}
2660fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2661fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
26628f23e9faSHans Rosenfeld 	    "fct_send_fcp_status %p:%p stat=%d resid=%d size=%d rx=%x ox=%x",
26638f23e9faSHans Rosenfeld 	    fct_cmd, cmd_sbp, fct_task->task_scsi_status,
26648f23e9faSHans Rosenfeld 	    fct_task->task_resid, size, fct_cmd->cmd_rxid, fct_cmd->cmd_oxid);
2665291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2666fcf3ce44SJohn Forte 
2667fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) {
2668fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
26698f23e9faSHans Rosenfeld 		    "fct_send_fcp_status: Unable to allocate packet.");
2670fcf3ce44SJohn Forte 
2671fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
267282527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2673fcf3ce44SJohn Forte 
2674291a2b48SSukumar Swaminathan 		return (FCT_BUSY);
2675fcf3ce44SJohn Forte 	}
2676291a2b48SSukumar Swaminathan 
2677fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_FCP_STATUS;
2678fcf3ce44SJohn Forte 
26798f23e9faSHans Rosenfeld 	sbp =  emlxs_fct_pkt_init(port, fct_cmd, pkt);
2680291a2b48SSukumar Swaminathan 	cmd_sbp->fct_pkt = pkt;
2681fcf3ce44SJohn Forte 
2682fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2683fcf3ce44SJohn Forte 	pkt->pkt_timeout =
2684fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
26858f23e9faSHans Rosenfeld 	pkt->pkt_timeout = (pkt->pkt_timeout > 60)? 60: pkt->pkt_timeout;
2686fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_fct_pkt_comp;
2687fcf3ce44SJohn Forte 
2688fcf3ce44SJohn Forte 	/* Build the fc header */
268982527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
2690fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
269182527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
2692fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP;
2693fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
2694fcf3ce44SJohn Forte 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2695fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
2696fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2697fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2698fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
2699fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
2700fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
2701fcf3ce44SJohn Forte 
2702fcf3ce44SJohn Forte 	/* Build the status payload */
2703fcf3ce44SJohn Forte 	fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd;
2704fcf3ce44SJohn Forte 
2705fcf3ce44SJohn Forte 	if (fct_task->task_resid) {
2706fcf3ce44SJohn Forte 		if (fct_task->task_status_ctrl & TASK_SCTRL_OVER) {
2707fcf3ce44SJohn Forte 			TGTPORTSTAT.FctScsiResidOver++;
2708fcf3ce44SJohn Forte 			fcp_rsp->rspStatus2 |= RESID_OVER;
270982527734SSukumar Swaminathan 			fcp_rsp->rspResId = LE_SWAP32(fct_task->task_resid);
2710fcf3ce44SJohn Forte 
2711fcf3ce44SJohn Forte 		} else if (fct_task->task_status_ctrl & TASK_SCTRL_UNDER) {
2712fcf3ce44SJohn Forte 			TGTPORTSTAT.FctScsiResidUnder++;
2713fcf3ce44SJohn Forte 			fcp_rsp->rspStatus2 |= RESID_UNDER;
271482527734SSukumar Swaminathan 			fcp_rsp->rspResId = LE_SWAP32(fct_task->task_resid);
2715fcf3ce44SJohn Forte 
2716fcf3ce44SJohn Forte 		}
2717fcf3ce44SJohn Forte 	}
2718291a2b48SSukumar Swaminathan 
2719fcf3ce44SJohn Forte 	if (fct_task->task_scsi_status) {
2720fcf3ce44SJohn Forte 		if (fct_task->task_scsi_status == SCSI_STAT_QUE_FULL) {
2721fcf3ce44SJohn Forte 			TGTPORTSTAT.FctScsiQfullErr++;
2722fcf3ce44SJohn Forte 		} else {
2723fcf3ce44SJohn Forte 			TGTPORTSTAT.FctScsiStatusErr++;
2724fcf3ce44SJohn Forte 		}
2725fcf3ce44SJohn Forte 
2726291a2b48SSukumar Swaminathan 		/* Make sure residual reported on non-SCSI_GOOD READ status */
2727fcf3ce44SJohn Forte 		if ((fct_task->task_flags & TF_READ_DATA) &&
2728fcf3ce44SJohn Forte 		    (fcp_rsp->rspResId == 0)) {
2729fcf3ce44SJohn Forte 			fcp_rsp->rspStatus2 |= RESID_UNDER;
2730291a2b48SSukumar Swaminathan 			fcp_rsp->rspResId =
2731291a2b48SSukumar Swaminathan 			    fct_task->task_expected_xfer_length;
2732fcf3ce44SJohn Forte 		}
2733fcf3ce44SJohn Forte 	}
2734291a2b48SSukumar Swaminathan 
2735291a2b48SSukumar Swaminathan 
2736fcf3ce44SJohn Forte 	if (fct_task->task_sense_length) {
2737fcf3ce44SJohn Forte 		TGTPORTSTAT.FctScsiSenseErr++;
2738fcf3ce44SJohn Forte 		fcp_rsp->rspStatus2 |= SNS_LEN_VALID;
273982527734SSukumar Swaminathan 		fcp_rsp->rspSnsLen = LE_SWAP32(fct_task->task_sense_length);
2740fcf3ce44SJohn Forte 
2741fcf3ce44SJohn Forte 		bcopy((uint8_t *)fct_task->task_sense_data,
2742291a2b48SSukumar Swaminathan 		    (uint8_t *)&fcp_rsp->rspInfo0,
2743291a2b48SSukumar Swaminathan 		    fct_task->task_sense_length);
2744fcf3ce44SJohn Forte 	}
2745291a2b48SSukumar Swaminathan 
2746fcf3ce44SJohn Forte 	fcp_rsp->rspStatus3 = fct_task->task_scsi_status;
2747fcf3ce44SJohn Forte 	fcp_rsp->rspRspLen = 0;
274882527734SSukumar Swaminathan 
27498f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
27508f23e9faSHans Rosenfeld 	emlxs_data_dump(port, "RESP", (uint32_t *)fcp_rsp, 36, 0);
27518f23e9faSHans Rosenfeld #endif /* FCT_API_TRACE */
27528f23e9faSHans Rosenfeld 
2753291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
275482527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_STATUS_PENDING);
275582527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
2756fcf3ce44SJohn Forte 
2757fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
275882527734SSukumar Swaminathan 
2759fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
27608f23e9faSHans Rosenfeld 		    "fct_send_fcp_status: Unable to send packet.");
27618f23e9faSHans Rosenfeld 
27628f23e9faSHans Rosenfeld 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
27638f23e9faSHans Rosenfeld 			emlxs_sli4_free_xri(port, sbp, 0, 0);
27648f23e9faSHans Rosenfeld 		}
2765fcf3ce44SJohn Forte 
276682527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
276782527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
276882527734SSukumar Swaminathan 		if (rval) {
276982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
27708f23e9faSHans Rosenfeld 			    "fct_send_fcp_status: "
277182527734SSukumar Swaminathan 			    "Unable to acquire fct_cmd.");
277282527734SSukumar Swaminathan 			return (rval);
2773fcf3ce44SJohn Forte 		}
277482527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
2775291a2b48SSukumar Swaminathan 
2776fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
277782527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2778291a2b48SSukumar Swaminathan 
2779291a2b48SSukumar Swaminathan 		return (FCT_BUSY);
2780fcf3ce44SJohn Forte 	}
2781291a2b48SSukumar Swaminathan 
2782fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
2783fcf3ce44SJohn Forte 
278482527734SSukumar Swaminathan } /* emlxs_fct_send_fcp_status() */
2785fcf3ce44SJohn Forte 
2786fcf3ce44SJohn Forte 
2787fcf3ce44SJohn Forte static fct_status_t
emlxs_fct_send_qfull_reply(emlxs_port_t * port,emlxs_node_t * ndlp,uint16_t xid,uint32_t class,emlxs_fcp_cmd_t * fcp_cmd)2788291a2b48SSukumar Swaminathan emlxs_fct_send_qfull_reply(emlxs_port_t *port, emlxs_node_t *ndlp,
2789291a2b48SSukumar Swaminathan     uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd)
2790fcf3ce44SJohn Forte {
2791fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2792fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
2793fcf3ce44SJohn Forte 	fc_packet_t *pkt;
2794fcf3ce44SJohn Forte 	emlxs_fcp_rsp *fcp_rsp;
2795fcf3ce44SJohn Forte 	uint32_t size;
279682527734SSukumar Swaminathan 	CHANNEL *cp = &hba->chan[hba->CHANNEL_FCT];
2797fcf3ce44SJohn Forte 	uint8_t lun[8];
2798fcf3ce44SJohn Forte 
2799fcf3ce44SJohn Forte 	bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8);
2800fcf3ce44SJohn Forte 	size = 24;
2801fcf3ce44SJohn Forte 
2802fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) {
2803fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
28048f23e9faSHans Rosenfeld 		    "fct_send_qfull_reply: Unable to allocate packet.");
2805fcf3ce44SJohn Forte 		return (FCT_FAILURE);
2806fcf3ce44SJohn Forte 	}
2807291a2b48SSukumar Swaminathan 
2808fcf3ce44SJohn Forte 	sbp = PKT2PRIV(pkt);
2809fcf3ce44SJohn Forte 	sbp->node = ndlp;
281082527734SSukumar Swaminathan 	sbp->channel = cp;
2811fcf3ce44SJohn Forte 	sbp->did = ndlp->nlp_DID;
2812fcf3ce44SJohn Forte 	sbp->lun = (lun[0] << 8) | lun[1];
2813fcf3ce44SJohn Forte 	sbp->class = class;
2814fcf3ce44SJohn Forte 
2815fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2816fcf3ce44SJohn Forte 	pkt->pkt_timeout =
2817fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
2818fcf3ce44SJohn Forte 
2819fcf3ce44SJohn Forte 	/* Build the fc header */
282082527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(ndlp->nlp_DID);
2821fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
282282527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
2823fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP;
2824fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
2825fcf3ce44SJohn Forte 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2826fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
2827fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2828fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2829fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
2830fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = xid;
2831fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
2832fcf3ce44SJohn Forte 
2833fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
28348f23e9faSHans Rosenfeld 	    "fct_send_qfull_reply: Sending QFULL: x%x lun x%x: %d %d",
2835fcf3ce44SJohn Forte 	    xid, sbp->lun, TGTPORTSTAT.FctOutstandingIO,
2836fcf3ce44SJohn Forte 	    port->fct_port->port_max_xchges);
2837fcf3ce44SJohn Forte 
2838fcf3ce44SJohn Forte 	/* Build the status payload */
2839fcf3ce44SJohn Forte 	fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd;
2840fcf3ce44SJohn Forte 
2841fcf3ce44SJohn Forte 	TGTPORTSTAT.FctScsiQfullErr++;
2842fcf3ce44SJohn Forte 	fcp_rsp->rspStatus3 = SCSI_STAT_QUE_FULL;
2843fcf3ce44SJohn Forte 	fcp_rsp->rspStatus2 |= RESID_UNDER;
284482527734SSukumar Swaminathan 	fcp_rsp->rspResId = LE_SWAP32(fcp_cmd->fcpDl);
2845fcf3ce44SJohn Forte 
2846fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
28478f23e9faSHans Rosenfeld 
28488f23e9faSHans Rosenfeld 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
28498f23e9faSHans Rosenfeld 			emlxs_sli4_free_xri(port, sbp, 0, 0);
28508f23e9faSHans Rosenfeld 		}
28518f23e9faSHans Rosenfeld 
2852fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
28538f23e9faSHans Rosenfeld 		    "fct_send_qfull_reply: Unable to send packet.");
2854fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
2855fcf3ce44SJohn Forte 		return (FCT_FAILURE);
2856fcf3ce44SJohn Forte 	}
2857fcf3ce44SJohn Forte 
2858291a2b48SSukumar Swaminathan 	return (FCT_SUCCESS);
2859fcf3ce44SJohn Forte 
286082527734SSukumar Swaminathan } /* emlxs_fct_send_qfull_reply() */
2861fcf3ce44SJohn Forte 
2862fcf3ce44SJohn Forte 
2863fcf3ce44SJohn Forte /* ARGSUSED */
2864fcf3ce44SJohn Forte extern int
emlxs_fct_handle_fcp_event(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)286582527734SSukumar Swaminathan emlxs_fct_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2866fcf3ce44SJohn Forte {
2867fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2868fcf3ce44SJohn Forte 	IOCB *iocb;
2869fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
2870fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
2871fcf3ce44SJohn Forte 	uint32_t status;
2872fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
2873fcf3ce44SJohn Forte 	stmf_data_buf_t *dbuf;
2874fcf3ce44SJohn Forte 	scsi_task_t *fct_task;
2875291a2b48SSukumar Swaminathan 	fc_packet_t *pkt;
287682527734SSukumar Swaminathan 	uint32_t fct_flags;
287782527734SSukumar Swaminathan 	stmf_data_buf_t *fct_buf;
287882527734SSukumar Swaminathan 	fct_status_t rval;
2879fcf3ce44SJohn Forte 
2880fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
2881fcf3ce44SJohn Forte 	sbp = (emlxs_buf_t *)iocbq->sbp;
2882fcf3ce44SJohn Forte 
2883fcf3ce44SJohn Forte 	TGTPORTSTAT.FctEvent++;
2884fcf3ce44SJohn Forte 
2885fcf3ce44SJohn Forte 	if (!sbp) {
2886fcf3ce44SJohn Forte 		/* completion with missing xmit command */
2887fcf3ce44SJohn Forte 		TGTPORTSTAT.FctStray++;
2888fcf3ce44SJohn Forte 
2889fcf3ce44SJohn Forte 		/* emlxs_stray_fcp_completion_msg */
2890fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
28918f23e9faSHans Rosenfeld 		    "FCP event cmd=%x status=%x error=%x iotag=%d",
289282527734SSukumar Swaminathan 		    iocb->ULPCOMMAND, iocb->ULPSTATUS,
289382527734SSukumar Swaminathan 		    iocb->un.grsp.perr.statLocalError, iocb->ULPIOTAG);
2894fcf3ce44SJohn Forte 
2895fcf3ce44SJohn Forte 		return (1);
2896fcf3ce44SJohn Forte 	}
2897291a2b48SSukumar Swaminathan 
2898fcf3ce44SJohn Forte 	TGTPORTSTAT.FctCompleted++;
2899fcf3ce44SJohn Forte 
2900fcf3ce44SJohn Forte 	port = sbp->iocbq.port;
2901fcf3ce44SJohn Forte 	fct_cmd = sbp->fct_cmd;
290282527734SSukumar Swaminathan 	status = iocb->ULPSTATUS;
2903fcf3ce44SJohn Forte 
2904fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2905fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
29068f23e9faSHans Rosenfeld 	    "fct_handle_fcp_event: %p:%p cmd=%x status=%x, %x",
29078f23e9faSHans Rosenfeld 	    fct_cmd, sbp, iocb->ULPCOMMAND, status, iocb->ULPCT);
2908291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2909fcf3ce44SJohn Forte 
2910fcf3ce44SJohn Forte 	if (fct_cmd == NULL) {
2911291a2b48SSukumar Swaminathan 		/* For driver generated QFULL response */
291282527734SSukumar Swaminathan 		if (((iocb->ULPCOMMAND == CMD_FCP_TRSP_CX) ||
291382527734SSukumar Swaminathan 		    (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX)) && sbp->pkt) {
2914fcf3ce44SJohn Forte 			emlxs_pkt_free(sbp->pkt);
2915fcf3ce44SJohn Forte 		}
2916fcf3ce44SJohn Forte 		return (0);
2917fcf3ce44SJohn Forte 	}
2918291a2b48SSukumar Swaminathan 
291982527734SSukumar Swaminathan 	rval = emlxs_fct_cmd_acquire(port, fct_cmd, EMLXS_FCT_REQ_COMPLETE);
292082527734SSukumar Swaminathan 	if (rval) {
292182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
29228f23e9faSHans Rosenfeld 		    "fct_handle_fcp_event: "
292382527734SSukumar Swaminathan 		    "Unable to reacquire fct_cmd. type=%x",
292482527734SSukumar Swaminathan 		    fct_cmd->cmd_type);
292582527734SSukumar Swaminathan 
292682527734SSukumar Swaminathan 		return (1);
2927291a2b48SSukumar Swaminathan 	}
292882527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2929291a2b48SSukumar Swaminathan 
2930fcf3ce44SJohn Forte 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
293182527734SSukumar Swaminathan 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
2932291a2b48SSukumar Swaminathan 
2933291a2b48SSukumar Swaminathan 	pkt = cmd_sbp->fct_pkt;
293482527734SSukumar Swaminathan 	cmd_sbp->fct_pkt = NULL;
2935fcf3ce44SJohn Forte 
293682527734SSukumar Swaminathan 	dbuf = sbp->fct_buf;
2937fcf3ce44SJohn Forte 
2938291a2b48SSukumar Swaminathan 	fct_cmd->cmd_comp_status = FCT_SUCCESS;
2939291a2b48SSukumar Swaminathan 
2940291a2b48SSukumar Swaminathan 	if (status) {
2941b3660a96SSukumar Swaminathan emlxs_dma_error:
2942fcf3ce44SJohn Forte 		/*
2943291a2b48SSukumar Swaminathan 		 * The error indicates this IO should be terminated
2944291a2b48SSukumar Swaminathan 		 * immediately.
2945fcf3ce44SJohn Forte 		 */
2946291a2b48SSukumar Swaminathan 		cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
294782527734SSukumar Swaminathan 		fct_cmd->cmd_comp_status = FCT_FAILURE;
2948291a2b48SSukumar Swaminathan 
294982527734SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
295082527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2951291a2b48SSukumar Swaminathan 
2952291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
2953291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2954291a2b48SSukumar Swaminathan 		    "fct_queue_cmd_for_termination:1 %p: x%x",
2955291a2b48SSukumar Swaminathan 		    fct_cmd, fct_cmd->cmd_comp_status);
2956291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
295782527734SSukumar Swaminathan 
2958291a2b48SSukumar Swaminathan 		MODSYM(fct_queue_cmd_for_termination) (fct_cmd,
2959291a2b48SSukumar Swaminathan 		    FCT_ABTS_RECEIVED);
296082527734SSukumar Swaminathan 
2961291a2b48SSukumar Swaminathan 		goto done;
2962291a2b48SSukumar Swaminathan 	}
2963291a2b48SSukumar Swaminathan 
296482527734SSukumar Swaminathan 	switch (iocb->ULPCOMMAND) {
2965291a2b48SSukumar Swaminathan 
2966291a2b48SSukumar Swaminathan 	/*
2967291a2b48SSukumar Swaminathan 	 *  FCP Data completion
2968291a2b48SSukumar Swaminathan 	 */
2969fcf3ce44SJohn Forte 	case CMD_FCP_TSEND_CX:
2970fcf3ce44SJohn Forte 	case CMD_FCP_TSEND64_CX:
2971fcf3ce44SJohn Forte 	case CMD_FCP_TRECEIVE_CX:
2972fcf3ce44SJohn Forte 	case CMD_FCP_TRECEIVE64_CX:
2973fcf3ce44SJohn Forte 
297482527734SSukumar Swaminathan 		if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) {
2975b3660a96SSukumar Swaminathan 			if (emlxs_fct_dbuf_dma_sync(hba, dbuf,
2976b3660a96SSukumar Swaminathan 			    DDI_DMA_SYNC_FORCPU)) {
2977b3660a96SSukumar Swaminathan 				goto emlxs_dma_error;
2978b3660a96SSukumar Swaminathan 			}
297982527734SSukumar Swaminathan 		}
2980fcf3ce44SJohn Forte 
298182527734SSukumar Swaminathan 		if ((cmd_sbp->fct_flags & EMLXS_FCT_SEND_STATUS) &&
298282527734SSukumar Swaminathan 		    (iocb->ULPCT != 1)) {
2983291a2b48SSukumar Swaminathan 
298482527734SSukumar Swaminathan 			dbuf->db_flags |= DB_STATUS_GOOD_SENT;
2985fcf3ce44SJohn Forte 
298682527734SSukumar Swaminathan 			fct_task =
298782527734SSukumar Swaminathan 			    (scsi_task_t *)fct_cmd->cmd_specific;
298882527734SSukumar Swaminathan 			fct_task->task_scsi_status = 0;
2989fcf3ce44SJohn Forte 
299082527734SSukumar Swaminathan 			(void) emlxs_fct_send_fcp_status(fct_cmd);
299182527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
2992fcf3ce44SJohn Forte 
299382527734SSukumar Swaminathan 			break;
299482527734SSukumar Swaminathan 
299582527734SSukumar Swaminathan 		} else if ((cmd_sbp->fct_flags &
299682527734SSukumar Swaminathan 		    EMLXS_FCT_SEND_STATUS) &&
299782527734SSukumar Swaminathan 		    (iocb->ULPCT == 1)) {
299882527734SSukumar Swaminathan 			/* Auto-resp has been sent out by firmware */
299982527734SSukumar Swaminathan 			/* We can assume this is really a FC_TRSP_CX */
300082527734SSukumar Swaminathan 
300182527734SSukumar Swaminathan 			dbuf->db_flags |= DB_STATUS_GOOD_SENT;
300282527734SSukumar Swaminathan 			fct_task =
300382527734SSukumar Swaminathan 			    (scsi_task_t *)fct_cmd->cmd_specific;
300482527734SSukumar Swaminathan 			fct_task->task_scsi_status = 0;
300582527734SSukumar Swaminathan 
300682527734SSukumar Swaminathan 			cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
300782527734SSukumar Swaminathan 
300882527734SSukumar Swaminathan 			goto auto_resp;
3009fcf3ce44SJohn Forte 		}
3010291a2b48SSukumar Swaminathan 
3011fcf3ce44SJohn Forte 		cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
3012fcf3ce44SJohn Forte 
3013fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
301482527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
301582527734SSukumar Swaminathan 
3016fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3017fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3018fcf3ce44SJohn Forte 		    "fct_scsi_data_xfer_done:1 %p %p", fct_cmd, dbuf);
3019291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
302082527734SSukumar Swaminathan 
3021fcf3ce44SJohn Forte 		MODSYM(fct_scsi_data_xfer_done) (fct_cmd, dbuf, 0);
3022fcf3ce44SJohn Forte 
3023fcf3ce44SJohn Forte 		break;
3024fcf3ce44SJohn Forte 
3025fcf3ce44SJohn Forte 		/* FCP Status completion */
3026fcf3ce44SJohn Forte 	case CMD_FCP_TRSP_CX:
3027fcf3ce44SJohn Forte 	case CMD_FCP_TRSP64_CX:
3028fcf3ce44SJohn Forte 
302982527734SSukumar Swaminathan auto_resp:
303082527734SSukumar Swaminathan 		/* Copy these before calling emlxs_fct_cmd_done */
303182527734SSukumar Swaminathan 		fct_flags = cmd_sbp->fct_flags;
303282527734SSukumar Swaminathan 		fct_buf = cmd_sbp->fct_buf;
3033fcf3ce44SJohn Forte 
303482527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
303582527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3036fcf3ce44SJohn Forte 
303782527734SSukumar Swaminathan 		TGTPORTSTAT.FctOutstandingIO--;
3038fcf3ce44SJohn Forte 
303982527734SSukumar Swaminathan 		if (fct_flags & EMLXS_FCT_SEND_STATUS) {
3040fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3041fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
30428f23e9faSHans Rosenfeld 			    "fct_scsi_data_xfer_done:2 %p %p outio %d",
30438f23e9faSHans Rosenfeld 			    fct_cmd, fct_buf, TGTPORTSTAT.FctOutstandingIO);
3044291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
304582527734SSukumar Swaminathan 
3046fcf3ce44SJohn Forte 			MODSYM(fct_scsi_data_xfer_done) (fct_cmd,
304782527734SSukumar Swaminathan 			    fct_buf, FCT_IOF_FCA_DONE);
3048fcf3ce44SJohn Forte 		} else {
3049fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3050fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
30518f23e9faSHans Rosenfeld 			    "fct_send_response_done:1 %p: x%x outio %d",
30528f23e9faSHans Rosenfeld 			    fct_cmd, fct_cmd->cmd_comp_status,
30538f23e9faSHans Rosenfeld 			    TGTPORTSTAT.FctOutstandingIO);
3054291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
305582527734SSukumar Swaminathan 
3056fcf3ce44SJohn Forte 			MODSYM(fct_send_response_done) (fct_cmd,
3057fcf3ce44SJohn Forte 			    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
3058fcf3ce44SJohn Forte 		}
3059fcf3ce44SJohn Forte 		break;
3060fcf3ce44SJohn Forte 
3061fcf3ce44SJohn Forte 	default:
306282527734SSukumar Swaminathan 		emlxs_fct_cmd_release(port, fct_cmd, 0);
306382527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3064291a2b48SSukumar Swaminathan 
3065fcf3ce44SJohn Forte 		TGTPORTSTAT.FctStray++;
3066fcf3ce44SJohn Forte 		TGTPORTSTAT.FctCompleted--;
3067fcf3ce44SJohn Forte 
3068fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
306982527734SSukumar Swaminathan 		    "Invalid iocb: cmd=0x%x", iocb->ULPCOMMAND);
3070fcf3ce44SJohn Forte 
3071291a2b48SSukumar Swaminathan 		if (pkt) {
3072291a2b48SSukumar Swaminathan 			emlxs_pkt_complete(sbp, status,
3073291a2b48SSukumar Swaminathan 			    iocb->un.grsp.perr.statLocalError, 1);
3074291a2b48SSukumar Swaminathan 		}
3075fcf3ce44SJohn Forte 
307682527734SSukumar Swaminathan 	}	/* switch(iocb->ULPCOMMAND) */
3077fcf3ce44SJohn Forte 
3078fcf3ce44SJohn Forte 
3079291a2b48SSukumar Swaminathan done:
3080291a2b48SSukumar Swaminathan 	if (pkt) {
3081291a2b48SSukumar Swaminathan 		emlxs_pkt_free(pkt);
3082291a2b48SSukumar Swaminathan 	}
3083291a2b48SSukumar Swaminathan 
3084fcf3ce44SJohn Forte 	if (status == IOSTAT_SUCCESS) {
3085fcf3ce44SJohn Forte 		TGTPORTSTAT.FctCmplGood++;
3086fcf3ce44SJohn Forte 	} else {
3087fcf3ce44SJohn Forte 		TGTPORTSTAT.FctCmplError++;
3088fcf3ce44SJohn Forte 	}
3089fcf3ce44SJohn Forte 
3090fcf3ce44SJohn Forte 	return (0);
3091fcf3ce44SJohn Forte 
309282527734SSukumar Swaminathan } /* emlxs_fct_handle_fcp_event() */
3093291a2b48SSukumar Swaminathan 
3094291a2b48SSukumar Swaminathan 
3095291a2b48SSukumar Swaminathan /* ARGSUSED */
3096291a2b48SSukumar Swaminathan extern int
emlxs_fct_handle_abort(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)309782527734SSukumar Swaminathan emlxs_fct_handle_abort(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
3098291a2b48SSukumar Swaminathan {
3099291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3100291a2b48SSukumar Swaminathan 	IOCB *iocb;
3101291a2b48SSukumar Swaminathan 	emlxs_buf_t *sbp;
3102291a2b48SSukumar Swaminathan 	fc_packet_t *pkt;
3103291a2b48SSukumar Swaminathan 
3104291a2b48SSukumar Swaminathan 	iocb = &iocbq->iocb;
3105291a2b48SSukumar Swaminathan 	sbp = (emlxs_buf_t *)iocbq->sbp;
3106291a2b48SSukumar Swaminathan 
3107291a2b48SSukumar Swaminathan 	TGTPORTSTAT.FctEvent++;
3108291a2b48SSukumar Swaminathan 
3109291a2b48SSukumar Swaminathan 	if (!sbp) {
3110291a2b48SSukumar Swaminathan 		/* completion with missing xmit command */
3111291a2b48SSukumar Swaminathan 		TGTPORTSTAT.FctStray++;
3112291a2b48SSukumar Swaminathan 
3113291a2b48SSukumar Swaminathan 		/* emlxs_stray_fcp_completion_msg */
3114291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
31158f23e9faSHans Rosenfeld 		    "ABORT event cmd=%x status=%x error=%x iotag=%d",
311682527734SSukumar Swaminathan 		    iocb->ULPCOMMAND, iocb->ULPSTATUS,
311782527734SSukumar Swaminathan 		    iocb->un.grsp.perr.statLocalError, iocb->ULPIOTAG);
3118291a2b48SSukumar Swaminathan 
3119291a2b48SSukumar Swaminathan 		return (1);
3120291a2b48SSukumar Swaminathan 	}
3121291a2b48SSukumar Swaminathan 
3122291a2b48SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
3123291a2b48SSukumar Swaminathan 
3124291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
3125291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
31268f23e9faSHans Rosenfeld 	    "fct_handle_abort: %p:%p xri=%d cmd=%x status=%x",
31278f23e9faSHans Rosenfeld 	    sbp->fct_cmd, sbp,
31288f23e9faSHans Rosenfeld 	    iocb->ULPCONTEXT, iocb->ULPCOMMAND, iocb->ULPSTATUS);
3129291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
3130291a2b48SSukumar Swaminathan 
31318f23e9faSHans Rosenfeld 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
31328f23e9faSHans Rosenfeld 		XRIobj_t	*xrip;
31338f23e9faSHans Rosenfeld 
31348f23e9faSHans Rosenfeld 		emlxs_sli4_free_xri(port, NULL, sbp->xrip, 1);
31358f23e9faSHans Rosenfeld 		xrip = emlxs_sli4_find_xri(port, iocb->ULPCONTEXT);
31368f23e9faSHans Rosenfeld 		if (!xrip || xrip->state == XRI_STATE_FREE) {
31378f23e9faSHans Rosenfeld 			goto exit;
31388f23e9faSHans Rosenfeld 		}
31398f23e9faSHans Rosenfeld 
31408f23e9faSHans Rosenfeld 		if ((hba->fc_table[xrip->iotag]) &&
31418f23e9faSHans Rosenfeld 		    (hba->fc_table[xrip->iotag] != STALE_PACKET)) {
31428f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
31438f23e9faSHans Rosenfeld 			    "Cmd not aborted, retrying: xri=%d iotag=%d sbp=%p",
31448f23e9faSHans Rosenfeld 			    xrip->XRI, xrip->iotag, hba->fc_table[xrip->iotag]);
31458f23e9faSHans Rosenfeld 
31468f23e9faSHans Rosenfeld 			/* Abort retry */
31478f23e9faSHans Rosenfeld 			if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
31488f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
31498f23e9faSHans Rosenfeld 				    "Abort retry failed xri=%x", xrip->XRI);
31508f23e9faSHans Rosenfeld 			} else {
31518f23e9faSHans Rosenfeld 				return (0);
31528f23e9faSHans Rosenfeld 			}
31538f23e9faSHans Rosenfeld 		}
31548f23e9faSHans Rosenfeld 	}
3155291a2b48SSukumar Swaminathan 
31568f23e9faSHans Rosenfeld exit:
3157291a2b48SSukumar Swaminathan 	if (pkt) {
3158291a2b48SSukumar Swaminathan 		emlxs_pkt_free(pkt);
3159291a2b48SSukumar Swaminathan 	}
3160291a2b48SSukumar Swaminathan 	return (0);
3161fcf3ce44SJohn Forte 
316282527734SSukumar Swaminathan } /* emlxs_fct_handle_abort() */
3163fcf3ce44SJohn Forte 
3164fcf3ce44SJohn Forte 
3165fcf3ce44SJohn Forte extern int
emlxs_fct_handle_unsol_els(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)316682527734SSukumar Swaminathan emlxs_fct_handle_unsol_els(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3167fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
3168fcf3ce44SJohn Forte {
3169fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
3170fcf3ce44SJohn Forte 	IOCB *iocb;
3171fcf3ce44SJohn Forte 	uint32_t cmd_code;
3172fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
3173fcf3ce44SJohn Forte 	fct_els_t *els;
3174fcf3ce44SJohn Forte 	uint32_t sid;
3175fcf3ce44SJohn Forte 	uint32_t padding;
3176fcf3ce44SJohn Forte 	uint8_t *bp;
3177fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
3178fcf3ce44SJohn Forte 	uint32_t rval;
3179fcf3ce44SJohn Forte 
3180fcf3ce44SJohn Forte 	HBASTATS.ElsCmdReceived++;
3181fcf3ce44SJohn Forte 
3182fcf3ce44SJohn Forte 	bp = mp->virt;
3183fcf3ce44SJohn Forte 	cmd_code = (*(uint32_t *)bp) & ELS_CMD_MASK;
3184fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
3185fcf3ce44SJohn Forte 	sid = iocb->un.elsreq.remoteID;
3186fcf3ce44SJohn Forte 
3187fcf3ce44SJohn Forte 	if (!port->fct_port) {
31888f23e9faSHans Rosenfeld 		if (!(hba->flag & FC_ONLINE_MODE)) {
31898f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
31908f23e9faSHans Rosenfeld 			    "%s: sid=%x. Adapter offline. Dropping...",
31918f23e9faSHans Rosenfeld 			    emlxs_elscmd_xlate(cmd_code), sid);
31928f23e9faSHans Rosenfeld 			goto done;
31938f23e9faSHans Rosenfeld 		}
3194fcf3ce44SJohn Forte 
31958f23e9faSHans Rosenfeld 		switch (cmd_code) {
31968f23e9faSHans Rosenfeld 		case ELS_CMD_LOGO:
31978f23e9faSHans Rosenfeld 		case ELS_CMD_PRLO:
31988f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
31998f23e9faSHans Rosenfeld 			    "%s: sid=%x. Target unbound. Accepting...",
32008f23e9faSHans Rosenfeld 			    emlxs_elscmd_xlate(cmd_code), sid);
32018f23e9faSHans Rosenfeld 			(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC,
32028f23e9faSHans Rosenfeld 			    ELS_CMD_LOGO, 0, 0);
32038f23e9faSHans Rosenfeld 			break;
32048f23e9faSHans Rosenfeld 		default:
32058f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
32068f23e9faSHans Rosenfeld 			    "%s: sid=%x. Target unbound. Rejecting...",
32078f23e9faSHans Rosenfeld 			    emlxs_elscmd_xlate(cmd_code), sid);
32088f23e9faSHans Rosenfeld 			(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
32098f23e9faSHans Rosenfeld 			    cmd_code, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
32108f23e9faSHans Rosenfeld 			break;
32118f23e9faSHans Rosenfeld 		}
3212fcf3ce44SJohn Forte 		goto done;
3213fcf3ce44SJohn Forte 	}
3214291a2b48SSukumar Swaminathan 
3215fcf3ce44SJohn Forte 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
3216fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3217fcf3ce44SJohn Forte 		    "%s: sid=%x. Target offline. Rejecting...",
3218fcf3ce44SJohn Forte 		    emlxs_elscmd_xlate(cmd_code), sid);
3219fcf3ce44SJohn Forte 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
3220fcf3ce44SJohn Forte 		    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
3221fcf3ce44SJohn Forte 
3222fcf3ce44SJohn Forte 		goto done;
3223fcf3ce44SJohn Forte 	}
3224291a2b48SSukumar Swaminathan 
32258f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
32268f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
32278f23e9faSHans Rosenfeld 	    "%s: sid=%x cnt=%d. Target rcv. ",
32288f23e9faSHans Rosenfeld 	    emlxs_elscmd_xlate(cmd_code), sid, size);
32298f23e9faSHans Rosenfeld #endif /* FCT_API_TRACE */
32308f23e9faSHans Rosenfeld 
3231fcf3ce44SJohn Forte 	/* Process the request */
3232fcf3ce44SJohn Forte 	switch (cmd_code) {
3233fcf3ce44SJohn Forte 	case ELS_CMD_FLOGI:
3234e2ca2865SSukumar Swaminathan 		rval = emlxs_fct_process_unsol_flogi(port, cp, iocbq, mp, size);
3235291a2b48SSukumar Swaminathan 
3236291a2b48SSukumar Swaminathan 		if (!rval) {
3237291a2b48SSukumar Swaminathan 			ELS_PKT *els_pkt = (ELS_PKT *)bp;
3238e2ca2865SSukumar Swaminathan 			fct_flogi_xchg_t fx;
3239e2ca2865SSukumar Swaminathan 
3240e2ca2865SSukumar Swaminathan 			bzero((uint8_t *)&fx, sizeof (fct_flogi_xchg_t));
3241291a2b48SSukumar Swaminathan 
3242291a2b48SSukumar Swaminathan 			/* Save the FLOGI exchange information */
3243e2ca2865SSukumar Swaminathan 			fx.rsvd2 = iocb->ULPCONTEXT;
3244291a2b48SSukumar Swaminathan 			bcopy((caddr_t)&els_pkt->un.logi.nodeName,
3245e2ca2865SSukumar Swaminathan 			    (caddr_t)fx.fx_nwwn, 8);
3246291a2b48SSukumar Swaminathan 			bcopy((caddr_t)&els_pkt->un.logi.portName,
3247e2ca2865SSukumar Swaminathan 			    (caddr_t)fx.fx_pwwn, 8);
3248e2ca2865SSukumar Swaminathan 			fx.fx_sid = sid;
3249e2ca2865SSukumar Swaminathan 			fx.fx_did = iocb->un.elsreq.myID;
3250e2ca2865SSukumar Swaminathan 			fx.fx_fport = els_pkt->un.logi.cmn.fPort;
3251e2ca2865SSukumar Swaminathan 			fx.fx_op = ELS_OP_FLOGI;
3252e2ca2865SSukumar Swaminathan 
3253e2ca2865SSukumar Swaminathan 			emlxs_fct_handle_unsol_flogi(port, &fx, 1);
3254291a2b48SSukumar Swaminathan 		}
3255e2ca2865SSukumar Swaminathan 
3256291a2b48SSukumar Swaminathan 		goto done;
3257fcf3ce44SJohn Forte 
3258fcf3ce44SJohn Forte 	case ELS_CMD_PLOGI:
3259291a2b48SSukumar Swaminathan 		rval =
326082527734SSukumar Swaminathan 		    emlxs_fct_process_unsol_plogi(port, cp, iocbq, mp, size);
3261fcf3ce44SJohn Forte 		break;
3262fcf3ce44SJohn Forte 
3263fcf3ce44SJohn Forte 	default:
3264fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3265fcf3ce44SJohn Forte 		    "%s: sid=0x%x", emlxs_elscmd_xlate(cmd_code), sid);
3266fcf3ce44SJohn Forte 		rval = 0;
3267fcf3ce44SJohn Forte 		break;
3268fcf3ce44SJohn Forte 	}
3269fcf3ce44SJohn Forte 
3270fcf3ce44SJohn Forte 	if (rval) {
3271fcf3ce44SJohn Forte 		goto done;
3272fcf3ce44SJohn Forte 	}
3273291a2b48SSukumar Swaminathan 
3274fcf3ce44SJohn Forte 	padding = (8 - (size & 7)) & 7;
3275fcf3ce44SJohn Forte 
3276fcf3ce44SJohn Forte 	fct_cmd = (fct_cmd_t *)MODSYM(fct_alloc) (FCT_STRUCT_CMD_RCVD_ELS,
3277291a2b48SSukumar Swaminathan 	    (size + padding + GET_STRUCT_SIZE(emlxs_buf_t)),
3278291a2b48SSukumar Swaminathan 	    AF_FORCE_NOSLEEP);
3279fcf3ce44SJohn Forte 
3280fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3281fcf3ce44SJohn Forte 	{
3282fcf3ce44SJohn Forte 		uint32_t *ptr = (uint32_t *)bp;
3283fcf3ce44SJohn Forte 
3284fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3285fcf3ce44SJohn Forte 		    "fct_alloc %p: ELS rcvd: rxid=%x payload: x%x x%x",
328682527734SSukumar Swaminathan 		    fct_cmd, iocb->ULPCONTEXT, *ptr, *(ptr + 1));
3287fcf3ce44SJohn Forte 	}
3288291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
3289fcf3ce44SJohn Forte 
3290fcf3ce44SJohn Forte 	if (fct_cmd == NULL) {
3291fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3292fcf3ce44SJohn Forte 		    "%s: sid=%x. Out of memory. Rejecting...",
3293fcf3ce44SJohn Forte 		    emlxs_elscmd_xlate(cmd_code), sid);
3294fcf3ce44SJohn Forte 
3295fcf3ce44SJohn Forte 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
3296fcf3ce44SJohn Forte 		    LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
3297fcf3ce44SJohn Forte 		goto done;
3298fcf3ce44SJohn Forte 	}
3299291a2b48SSukumar Swaminathan 
3300fcf3ce44SJohn Forte 	/* Initialize fct_cmd */
3301fcf3ce44SJohn Forte 	fct_cmd->cmd_oxid = (cmd_code >> ELS_CMD_SHIFT) & 0xff;
330282527734SSukumar Swaminathan 	fct_cmd->cmd_rxid = iocb->ULPCONTEXT;
3303fcf3ce44SJohn Forte 	fct_cmd->cmd_rportid = sid;
3304fcf3ce44SJohn Forte 	fct_cmd->cmd_lportid = port->did;
33058f23e9faSHans Rosenfeld 	fct_cmd->cmd_rp_handle = FCT_HANDLE_NONE;
3306fcf3ce44SJohn Forte 	fct_cmd->cmd_port = port->fct_port;
3307fcf3ce44SJohn Forte 
330882527734SSukumar Swaminathan 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_ELS_CMD_RECEIVED);
330982527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
3310fcf3ce44SJohn Forte 
3311291a2b48SSukumar Swaminathan 	/* Initialize cmd_sbp */
331282527734SSukumar Swaminathan 	cmd_sbp->channel = cp;
331382527734SSukumar Swaminathan 	cmd_sbp->class = iocb->ULPCLASS;
3314fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD;
3315291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_PLOGI_RECEIVED;
3316291a2b48SSukumar Swaminathan 
3317fcf3ce44SJohn Forte 	bcopy((uint8_t *)iocb, (uint8_t *)&cmd_sbp->iocbq,
3318fcf3ce44SJohn Forte 	    sizeof (emlxs_iocb_t));
3319fcf3ce44SJohn Forte 
3320fcf3ce44SJohn Forte 	els = (fct_els_t *)fct_cmd->cmd_specific;
3321a9800bebSGarrett D'Amore 	els->els_req_size = (uint16_t)size;
3322291a2b48SSukumar Swaminathan 	els->els_req_payload =
3323291a2b48SSukumar Swaminathan 	    GET_BYTE_OFFSET(fct_cmd->cmd_fca_private,
3324fcf3ce44SJohn Forte 	    GET_STRUCT_SIZE(emlxs_buf_t));
3325fcf3ce44SJohn Forte 	bcopy(bp, els->els_req_payload, size);
3326fcf3ce44SJohn Forte 
3327e2ca2865SSukumar Swaminathan 
3328e2ca2865SSukumar Swaminathan 	/* Check if Offline */
3329e2ca2865SSukumar Swaminathan 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
3330e2ca2865SSukumar Swaminathan 
3331e2ca2865SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
3332e2ca2865SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3333e2ca2865SSukumar Swaminathan 
3334e2ca2865SSukumar Swaminathan #ifdef FCT_API_TRACE
3335e2ca2865SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3336e2ca2865SSukumar Swaminathan 		    "fct_post_rcvd_cmd:4 %p: portid x%x", fct_cmd,
3337e2ca2865SSukumar Swaminathan 		    fct_cmd->cmd_lportid);
3338e2ca2865SSukumar Swaminathan #endif /* FCT_API_TRACE */
3339e2ca2865SSukumar Swaminathan 
3340e2ca2865SSukumar Swaminathan 		MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
3341e2ca2865SSukumar Swaminathan 
3342e2ca2865SSukumar Swaminathan 		goto done;
3343e2ca2865SSukumar Swaminathan 	}
3344e2ca2865SSukumar Swaminathan 
3345e2ca2865SSukumar Swaminathan 	/* Online */
33468f23e9faSHans Rosenfeld 
3347e2ca2865SSukumar Swaminathan 	/* Check if Link up is acked */
33488f23e9faSHans Rosenfeld 	if (!(port->fct_flags & FCT_STATE_LINK_UP_ACKED)) {
33498f23e9faSHans Rosenfeld 		goto defer;
33508f23e9faSHans Rosenfeld 	}
3351e2ca2865SSukumar Swaminathan 
33528f23e9faSHans Rosenfeld 	if ((cmd_code != ELS_CMD_FLOGI) &&
33538f23e9faSHans Rosenfeld 	    !(port->fct_flags & FCT_STATE_FLOGI_CMPL)) {
33548f23e9faSHans Rosenfeld 		goto defer;
33558f23e9faSHans Rosenfeld 	}
33568f23e9faSHans Rosenfeld 
33578f23e9faSHans Rosenfeld 	/* Post it to COMSTAR */
33588f23e9faSHans Rosenfeld 	emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
33598f23e9faSHans Rosenfeld 	/* mutex_exit(&cmd_sbp->fct_mtx); */
3360e2ca2865SSukumar Swaminathan 
3361e2ca2865SSukumar Swaminathan #ifdef FCT_API_TRACE
33628f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
33638f23e9faSHans Rosenfeld 	    "fct_post_rcvd_cmd:1 %p: portid x%x", fct_cmd,
33648f23e9faSHans Rosenfeld 	    fct_cmd->cmd_lportid);
3365e2ca2865SSukumar Swaminathan #endif /* FCT_API_TRACE */
3366e2ca2865SSukumar Swaminathan 
33678f23e9faSHans Rosenfeld 	MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
3368e2ca2865SSukumar Swaminathan 
33698f23e9faSHans Rosenfeld 	goto done;
3370e2ca2865SSukumar Swaminathan 
33718f23e9faSHans Rosenfeld defer:
3372e2ca2865SSukumar Swaminathan 	/* Defer processing of fct_cmd till later (after link up ack). */
3373e2ca2865SSukumar Swaminathan 
33748f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
33758f23e9faSHans Rosenfeld 	    "%s: sid=%x. Defer Processing x%x.",
33768f23e9faSHans Rosenfeld 	    emlxs_elscmd_xlate(cmd_code), sid, port->fct_flags);
33778f23e9faSHans Rosenfeld 
3378e2ca2865SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_CMD_WAITQ);
3379e2ca2865SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
3380e2ca2865SSukumar Swaminathan 
3381e2ca2865SSukumar Swaminathan 	/* Add cmd_sbp to queue tail */
3382e2ca2865SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
3383e2ca2865SSukumar Swaminathan 
3384e2ca2865SSukumar Swaminathan 	if (port->fct_wait_tail) {
3385e2ca2865SSukumar Swaminathan 		port->fct_wait_tail->next = cmd_sbp;
3386e2ca2865SSukumar Swaminathan 	}
3387e2ca2865SSukumar Swaminathan 	port->fct_wait_tail = cmd_sbp;
3388e2ca2865SSukumar Swaminathan 
3389e2ca2865SSukumar Swaminathan 	if (!port->fct_wait_head) {
3390e2ca2865SSukumar Swaminathan 		port->fct_wait_head = cmd_sbp;
3391e2ca2865SSukumar Swaminathan 	}
3392e2ca2865SSukumar Swaminathan 
3393e2ca2865SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
3394fcf3ce44SJohn Forte 
3395fcf3ce44SJohn Forte done:
3396fcf3ce44SJohn Forte 
3397fcf3ce44SJohn Forte 	return (0);
3398fcf3ce44SJohn Forte 
339982527734SSukumar Swaminathan } /* emlxs_fct_handle_unsol_els() */
3400fcf3ce44SJohn Forte 
3401fcf3ce44SJohn Forte 
3402fcf3ce44SJohn Forte /* ARGSUSED */
3403fcf3ce44SJohn Forte static uint32_t
emlxs_fct_process_unsol_flogi(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)340482527734SSukumar Swaminathan emlxs_fct_process_unsol_flogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3405fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
3406fcf3ce44SJohn Forte {
3407fcf3ce44SJohn Forte 	IOCB *iocb;
3408fcf3ce44SJohn Forte 	char buffer[64];
3409fcf3ce44SJohn Forte 
3410fcf3ce44SJohn Forte 	buffer[0] = 0;
3411fcf3ce44SJohn Forte 
3412fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
3413fcf3ce44SJohn Forte 
3414fcf3ce44SJohn Forte 	/* Perform processing of FLOGI payload */
34158f23e9faSHans Rosenfeld 	if (emlxs_process_unsol_flogi(port, iocbq, mp, size, buffer,
34168f23e9faSHans Rosenfeld 	    sizeof (buffer))) {
3417fcf3ce44SJohn Forte 		return (1);
3418fcf3ce44SJohn Forte 	}
3419291a2b48SSukumar Swaminathan 
3420fe199829SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3421fe199829SSukumar Swaminathan 	    "FLOGI: sid=0x%x xid=%x %s",
3422fe199829SSukumar Swaminathan 	    iocb->un.elsreq.remoteID, iocb->ULPIOTAG, buffer);
3423fcf3ce44SJohn Forte 
3424fcf3ce44SJohn Forte 	return (0);
3425fcf3ce44SJohn Forte 
342682527734SSukumar Swaminathan } /* emlxs_fct_process_unsol_flogi() */
3427fcf3ce44SJohn Forte 
3428fcf3ce44SJohn Forte 
3429fcf3ce44SJohn Forte /* ARGSUSED */
3430fcf3ce44SJohn Forte static uint32_t
emlxs_fct_process_unsol_plogi(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)343182527734SSukumar Swaminathan emlxs_fct_process_unsol_plogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3432fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
3433fcf3ce44SJohn Forte {
3434fcf3ce44SJohn Forte 	IOCB *iocb;
3435fcf3ce44SJohn Forte 	char buffer[64];
3436fcf3ce44SJohn Forte 
3437fcf3ce44SJohn Forte 	buffer[0] = 0;
3438fcf3ce44SJohn Forte 
3439fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
3440fcf3ce44SJohn Forte 
3441fcf3ce44SJohn Forte 	/* Perform processing of PLOGI payload */
34428f23e9faSHans Rosenfeld 	if (emlxs_process_unsol_plogi(port, iocbq, mp, size, buffer,
34438f23e9faSHans Rosenfeld 	    sizeof (buffer))) {
3444fcf3ce44SJohn Forte 		return (1);
3445fcf3ce44SJohn Forte 	}
3446291a2b48SSukumar Swaminathan 
3447fe199829SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3448fe199829SSukumar Swaminathan 	    "PLOGI: sid=0x%x xid=%x %s",
3449fe199829SSukumar Swaminathan 	    iocb->un.elsreq.remoteID, iocb->ULPIOTAG, buffer);
3450fcf3ce44SJohn Forte 
3451fcf3ce44SJohn Forte 	return (0);
3452fcf3ce44SJohn Forte 
345382527734SSukumar Swaminathan } /* emlxs_fct_process_unsol_plogi() */
3454fcf3ce44SJohn Forte 
3455fcf3ce44SJohn Forte 
3456fcf3ce44SJohn Forte /* ARGSUSED */
3457fcf3ce44SJohn Forte static emlxs_buf_t *
emlxs_fct_pkt_init(emlxs_port_t * port,fct_cmd_t * fct_cmd,fc_packet_t * pkt)3458291a2b48SSukumar Swaminathan emlxs_fct_pkt_init(emlxs_port_t *port, fct_cmd_t *fct_cmd,
3459291a2b48SSukumar Swaminathan     fc_packet_t *pkt)
3460fcf3ce44SJohn Forte {
3461fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
3462fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
3463fcf3ce44SJohn Forte 
3464fcf3ce44SJohn Forte 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3465fcf3ce44SJohn Forte 
3466fcf3ce44SJohn Forte 	sbp = PKT2PRIV(pkt);
3467fcf3ce44SJohn Forte 	sbp->fct_cmd = cmd_sbp->fct_cmd;
3468fcf3ce44SJohn Forte 	sbp->node = cmd_sbp->node;
346982527734SSukumar Swaminathan 	sbp->channel = cmd_sbp->channel;
3470fcf3ce44SJohn Forte 	sbp->did = cmd_sbp->did;
3471fcf3ce44SJohn Forte 	sbp->lun = cmd_sbp->lun;
3472fcf3ce44SJohn Forte 	sbp->class = cmd_sbp->class;
3473fcf3ce44SJohn Forte 	sbp->fct_type = cmd_sbp->fct_type;
3474fcf3ce44SJohn Forte 	sbp->fct_state = cmd_sbp->fct_state;
34758f23e9faSHans Rosenfeld 	sbp->xrip = cmd_sbp->xrip;
34768f23e9faSHans Rosenfeld 	sbp->iotag = cmd_sbp->iotag;
3477fcf3ce44SJohn Forte 
3478fcf3ce44SJohn Forte 	return (sbp);
3479fcf3ce44SJohn Forte 
348082527734SSukumar Swaminathan } /* emlxs_fct_pkt_init() */
3481fcf3ce44SJohn Forte 
3482fcf3ce44SJohn Forte 
3483fcf3ce44SJohn Forte /* Mutex will be acquired */
3484fcf3ce44SJohn Forte static emlxs_buf_t *
emlxs_fct_cmd_init(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint16_t fct_state)3485a9800bebSGarrett D'Amore emlxs_fct_cmd_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state)
3486fcf3ce44SJohn Forte {
3487fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
3488fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3489fcf3ce44SJohn Forte 
3490fcf3ce44SJohn Forte 	bzero((void *)cmd_sbp, sizeof (emlxs_buf_t));
3491291a2b48SSukumar Swaminathan 	mutex_init(&cmd_sbp->fct_mtx, NULL, MUTEX_DRIVER,
3492a9800bebSGarrett D'Amore 	    DDI_INTR_PRI(hba->intr_arg));
3493a9800bebSGarrett D'Amore 	mutex_init(&cmd_sbp->mtx, NULL, MUTEX_DRIVER,
3494a9800bebSGarrett D'Amore 	    DDI_INTR_PRI(hba->intr_arg));
3495fcf3ce44SJohn Forte 
3496291a2b48SSukumar Swaminathan 	mutex_enter(&cmd_sbp->fct_mtx);
3497fcf3ce44SJohn Forte 	cmd_sbp->pkt_flags = PACKET_VALID;
3498fcf3ce44SJohn Forte 	cmd_sbp->port = port;
3499fcf3ce44SJohn Forte 	cmd_sbp->fct_cmd = fct_cmd;
3500fcf3ce44SJohn Forte 	cmd_sbp->node = (fct_cmd->cmd_rp) ?
3501fcf3ce44SJohn Forte 	    *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private : NULL;
3502fcf3ce44SJohn Forte 	cmd_sbp->iocbq.sbp = cmd_sbp;
3503291a2b48SSukumar Swaminathan 	cmd_sbp->iocbq.port = port;
350482527734SSukumar Swaminathan 	cmd_sbp->did = fct_cmd->cmd_rportid;
350582527734SSukumar Swaminathan 
350682527734SSukumar Swaminathan 	/* Flags fct_cmd as inuse */
350782527734SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
350882527734SSukumar Swaminathan 		fct_cmd->cmd_oxid = 0xffff;
350982527734SSukumar Swaminathan 		fct_cmd->cmd_rxid = 0xffff;
351082527734SSukumar Swaminathan 	}
351182527734SSukumar Swaminathan 
351282527734SSukumar Swaminathan 	if (fct_state) {
351382527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
351482527734SSukumar Swaminathan 	}
3515fcf3ce44SJohn Forte 
3516fcf3ce44SJohn Forte 	return (cmd_sbp);
3517fcf3ce44SJohn Forte 
351882527734SSukumar Swaminathan } /* emlxs_fct_cmd_init() */
3519fcf3ce44SJohn Forte 
3520fcf3ce44SJohn Forte 
352182527734SSukumar Swaminathan /* Called after receiving fct_cmd from COMSTAR */
352282527734SSukumar Swaminathan static fct_status_t
emlxs_fct_cmd_accept(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint16_t fct_state)352382527734SSukumar Swaminathan emlxs_fct_cmd_accept(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state)
3524fcf3ce44SJohn Forte {
3525fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3526fcf3ce44SJohn Forte 
352782527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
352882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
35298f23e9faSHans Rosenfeld 		    "fct_cmd_accept: "
353082527734SSukumar Swaminathan 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
353182527734SSukumar Swaminathan 		    fct_cmd, fct_state);
353282527734SSukumar Swaminathan 
353382527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
353482527734SSukumar Swaminathan 	}
353582527734SSukumar Swaminathan 
353682527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->fct_mtx);
353782527734SSukumar Swaminathan 
353882527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
353982527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
354082527734SSukumar Swaminathan 
354182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
35428f23e9faSHans Rosenfeld 		    "fct_cmd_accept:2 "
354382527734SSukumar Swaminathan 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
354482527734SSukumar Swaminathan 		    fct_cmd, fct_state);
354582527734SSukumar Swaminathan 
354682527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
354782527734SSukumar Swaminathan 	}
354882527734SSukumar Swaminathan 
354982527734SSukumar Swaminathan 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) {
355082527734SSukumar Swaminathan 
355182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
35528f23e9faSHans Rosenfeld 		    "fct_cmd_accept: "
355382527734SSukumar Swaminathan 		    "Aborted fct_cmd found! fct_cmd=%p state=%x",
355482527734SSukumar Swaminathan 		    fct_cmd, fct_state);
355582527734SSukumar Swaminathan 
355682527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_ABORT_DONE);
355782527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
355882527734SSukumar Swaminathan 
355982527734SSukumar Swaminathan 		MODSYM(fct_cmd_fca_aborted) (fct_cmd,
356082527734SSukumar Swaminathan 		    FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
356182527734SSukumar Swaminathan 
356282527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
356382527734SSukumar Swaminathan 	}
356482527734SSukumar Swaminathan 
356582527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->mtx);
356682527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) {
356782527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->mtx);
356882527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
356982527734SSukumar Swaminathan 
357082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
35718f23e9faSHans Rosenfeld 		    "fct_cmd_accept: "
357282527734SSukumar Swaminathan 		    "Busy fct_cmd found! fct_cmd=%p state=%x",
357382527734SSukumar Swaminathan 		    fct_cmd, fct_state);
357482527734SSukumar Swaminathan 
357582527734SSukumar Swaminathan 		return (FCT_BUSY);
357682527734SSukumar Swaminathan 	}
357782527734SSukumar Swaminathan 	cmd_sbp->pkt_flags &= ~PACKET_ULP_OWNED;
357882527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->mtx);
357982527734SSukumar Swaminathan 
358082527734SSukumar Swaminathan 	if (fct_state) {
358182527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
358282527734SSukumar Swaminathan 	}
358382527734SSukumar Swaminathan 
358482527734SSukumar Swaminathan 	return (FCT_SUCCESS);
358582527734SSukumar Swaminathan 
358682527734SSukumar Swaminathan } /* emlxs_fct_cmd_accept() */
358782527734SSukumar Swaminathan 
358882527734SSukumar Swaminathan 
358982527734SSukumar Swaminathan /* Called after receiving fct_cmd from driver */
359082527734SSukumar Swaminathan static fct_status_t
emlxs_fct_cmd_acquire(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint16_t fct_state)359182527734SSukumar Swaminathan emlxs_fct_cmd_acquire(emlxs_port_t *port, fct_cmd_t *fct_cmd,
359282527734SSukumar Swaminathan     uint16_t fct_state)
359382527734SSukumar Swaminathan {
359482527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
359582527734SSukumar Swaminathan 
359682527734SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
359782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
35988f23e9faSHans Rosenfeld 		    "fct_cmd_acquire: "
359982527734SSukumar Swaminathan 		    "Bad fct_cmd found! fct_cmd=%p state=%x",
360082527734SSukumar Swaminathan 		    fct_cmd, fct_state);
360182527734SSukumar Swaminathan 
360282527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
360382527734SSukumar Swaminathan 	}
360482527734SSukumar Swaminathan 
360582527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
360682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
36078f23e9faSHans Rosenfeld 		    "fct_cmd_acquire: "
360882527734SSukumar Swaminathan 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
360982527734SSukumar Swaminathan 		    fct_cmd, fct_state);
361082527734SSukumar Swaminathan 
361182527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
361282527734SSukumar Swaminathan 	}
361382527734SSukumar Swaminathan 
361482527734SSukumar Swaminathan 	if ((cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) {
361582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
36168f23e9faSHans Rosenfeld 		    "fct_cmd_acquire: "
361782527734SSukumar Swaminathan 		    "Returned fct_cmd found! fct_cmd=%p state=%x",
361882527734SSukumar Swaminathan 		    fct_cmd, fct_state);
361982527734SSukumar Swaminathan 
362082527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
362182527734SSukumar Swaminathan 	}
362282527734SSukumar Swaminathan 
362382527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->fct_mtx);
362482527734SSukumar Swaminathan 
362582527734SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
362682527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
362782527734SSukumar Swaminathan 
362882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
36298f23e9faSHans Rosenfeld 		    "fct_cmd_acquire:2 "
363082527734SSukumar Swaminathan 		    "Bad fct_cmd found! fct_cmd=%p state=%x",
363182527734SSukumar Swaminathan 		    fct_cmd, fct_state);
3632291a2b48SSukumar Swaminathan 
363382527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
363482527734SSukumar Swaminathan 	}
3635291a2b48SSukumar Swaminathan 
3636fcf3ce44SJohn Forte 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
363782527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
363882527734SSukumar Swaminathan 
363982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
36408f23e9faSHans Rosenfeld 		    "fct_cmd_acquire:2 "
364182527734SSukumar Swaminathan 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
364282527734SSukumar Swaminathan 		    fct_cmd, fct_state);
364382527734SSukumar Swaminathan 
364482527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
364582527734SSukumar Swaminathan 	}
364682527734SSukumar Swaminathan 
364782527734SSukumar Swaminathan 	if ((cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) {
364882527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
364982527734SSukumar Swaminathan 
365082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
36518f23e9faSHans Rosenfeld 		    "fct_cmd_acquire:2 "
365282527734SSukumar Swaminathan 		    "Returned fct_cmd found! fct_cmd=%p state=%x",
365382527734SSukumar Swaminathan 		    fct_cmd, fct_state);
365482527734SSukumar Swaminathan 
365582527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
365682527734SSukumar Swaminathan 	}
365782527734SSukumar Swaminathan 
365882527734SSukumar Swaminathan 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) {
365982527734SSukumar Swaminathan 
366082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
36618f23e9faSHans Rosenfeld 		    "fct_cmd_acquire: "
366282527734SSukumar Swaminathan 		    "Aborting cmd. fct_cmd=%p state=%x",
366382527734SSukumar Swaminathan 		    fct_cmd, fct_state);
366482527734SSukumar Swaminathan 
366582527734SSukumar Swaminathan 		if (fct_cmd->cmd_type == FCT_CMD_FCP_XCHG) {
366682527734SSukumar Swaminathan 			TGTPORTSTAT.FctOutstandingIO--;
366782527734SSukumar Swaminathan 		}
366882527734SSukumar Swaminathan 
366982527734SSukumar Swaminathan 		fct_cmd->cmd_comp_status = FCT_FAILURE;
367082527734SSukumar Swaminathan 
367182527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_ABORT_DONE);
367282527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
367382527734SSukumar Swaminathan 
367482527734SSukumar Swaminathan 		MODSYM(fct_cmd_fca_aborted) (fct_cmd,
367582527734SSukumar Swaminathan 		    FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
367682527734SSukumar Swaminathan 
367782527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
367882527734SSukumar Swaminathan 	}
367982527734SSukumar Swaminathan 
368082527734SSukumar Swaminathan 	if (fct_state) {
368182527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
368282527734SSukumar Swaminathan 	}
368382527734SSukumar Swaminathan 
368482527734SSukumar Swaminathan 	return (FCT_SUCCESS);
368582527734SSukumar Swaminathan 
368682527734SSukumar Swaminathan } /* emlxs_fct_cmd_acquire() */
368782527734SSukumar Swaminathan 
368882527734SSukumar Swaminathan 
368982527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
369082527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be released before exiting */
369182527734SSukumar Swaminathan /* Called before transitionally sending fct_cmd to driver */
369282527734SSukumar Swaminathan /*ARGSUSED*/
369382527734SSukumar Swaminathan static void
emlxs_fct_cmd_release(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint16_t fct_state)369482527734SSukumar Swaminathan emlxs_fct_cmd_release(emlxs_port_t *port, fct_cmd_t *fct_cmd,
369582527734SSukumar Swaminathan     uint16_t fct_state)
369682527734SSukumar Swaminathan {
369782527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
369882527734SSukumar Swaminathan 
369982527734SSukumar Swaminathan 	if (fct_state) {
370082527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
3701fcf3ce44SJohn Forte 	}
3702291a2b48SSukumar Swaminathan 
370382527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->fct_mtx);
370482527734SSukumar Swaminathan 
370582527734SSukumar Swaminathan 	return;
370682527734SSukumar Swaminathan 
370782527734SSukumar Swaminathan } /* emlxs_fct_cmd_release() */
370882527734SSukumar Swaminathan 
370982527734SSukumar Swaminathan 
371082527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
371182527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be released before exiting */
371282527734SSukumar Swaminathan /* Called before posting fct_cmd back to COMSTAR */
371382527734SSukumar Swaminathan /*ARGSUSED*/
371482527734SSukumar Swaminathan static void
emlxs_fct_cmd_post(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint16_t fct_state)371582527734SSukumar Swaminathan emlxs_fct_cmd_post(emlxs_port_t *port, fct_cmd_t *fct_cmd,
371682527734SSukumar Swaminathan     uint16_t fct_state)
371782527734SSukumar Swaminathan {
371882527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
371982527734SSukumar Swaminathan 	fc_packet_t *pkt;
372082527734SSukumar Swaminathan 
372182527734SSukumar Swaminathan 	pkt = cmd_sbp->fct_pkt;
372282527734SSukumar Swaminathan 	cmd_sbp->fct_pkt = NULL;
372382527734SSukumar Swaminathan 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
372482527734SSukumar Swaminathan 
372582527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->mtx);
372682527734SSukumar Swaminathan 	cmd_sbp->pkt_flags |= PACKET_ULP_OWNED;
372782527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->mtx);
372882527734SSukumar Swaminathan 
372982527734SSukumar Swaminathan 	if (fct_state) {
373082527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
373182527734SSukumar Swaminathan 	}
373282527734SSukumar Swaminathan 
373382527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->fct_mtx);
373482527734SSukumar Swaminathan 
373582527734SSukumar Swaminathan 	if (pkt) {
373682527734SSukumar Swaminathan 		emlxs_pkt_free(pkt);
373782527734SSukumar Swaminathan 	}
373882527734SSukumar Swaminathan 
373982527734SSukumar Swaminathan 	return;
374082527734SSukumar Swaminathan 
374182527734SSukumar Swaminathan } /* emlxs_fct_cmd_post() */
374282527734SSukumar Swaminathan 
374382527734SSukumar Swaminathan 
374482527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
374582527734SSukumar Swaminathan /* Called before completing fct_cmd back to COMSTAR */
374682527734SSukumar Swaminathan static void
emlxs_fct_cmd_done(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint16_t fct_state)374782527734SSukumar Swaminathan emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state)
374882527734SSukumar Swaminathan {
374982527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
375082527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
375182527734SSukumar Swaminathan 	fc_packet_t *pkt;
375282527734SSukumar Swaminathan 
375382527734SSukumar Swaminathan 	/* Flags fct_cmd is no longer used */
375482527734SSukumar Swaminathan 	fct_cmd->cmd_oxid = 0;
375582527734SSukumar Swaminathan 	fct_cmd->cmd_rxid = 0;
375682527734SSukumar Swaminathan 
3757fcf3ce44SJohn Forte 	if (cmd_sbp->iotag != 0) {
3758fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
37598f23e9faSHans Rosenfeld 		    "Pkt still registered! channel=%p iotag=%d sbp=%p",
376082527734SSukumar Swaminathan 		    cmd_sbp->channel, cmd_sbp->iotag, cmd_sbp);
376182527734SSukumar Swaminathan 
376282527734SSukumar Swaminathan 		if (cmd_sbp->channel) {
376382527734SSukumar Swaminathan 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
37648f23e9faSHans Rosenfeld 				emlxs_sli4_free_xri(port, cmd_sbp,
37658f23e9faSHans Rosenfeld 				    cmd_sbp->xrip, 1);
376682527734SSukumar Swaminathan 			} else {
376782527734SSukumar Swaminathan 				(void) emlxs_unregister_pkt(cmd_sbp->channel,
376882527734SSukumar Swaminathan 				    cmd_sbp->iotag, 0);
376982527734SSukumar Swaminathan 			}
3770fcf3ce44SJohn Forte 
3771fcf3ce44SJohn Forte 		}
3772fcf3ce44SJohn Forte 	}
3773291a2b48SSukumar Swaminathan 
377482527734SSukumar Swaminathan 	pkt = cmd_sbp->fct_pkt;
377582527734SSukumar Swaminathan 	cmd_sbp->fct_pkt = NULL;
377682527734SSukumar Swaminathan 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
377782527734SSukumar Swaminathan 
377882527734SSukumar Swaminathan 	if (fct_state) {
377982527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
378082527734SSukumar Swaminathan 	}
3781fcf3ce44SJohn Forte 
378282527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->mtx);
378382527734SSukumar Swaminathan 	cmd_sbp->pkt_flags |= PACKET_ULP_OWNED;
378482527734SSukumar Swaminathan 	cmd_sbp->pkt_flags &= ~PACKET_VALID;
378582527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->mtx);
3786291a2b48SSukumar Swaminathan 	mutex_exit(&cmd_sbp->fct_mtx);
378782527734SSukumar Swaminathan 
378882527734SSukumar Swaminathan 
3789291a2b48SSukumar Swaminathan 	mutex_destroy(&cmd_sbp->fct_mtx);
379082527734SSukumar Swaminathan 	mutex_destroy(&cmd_sbp->mtx);
379182527734SSukumar Swaminathan 
379282527734SSukumar Swaminathan 	if (pkt) {
379382527734SSukumar Swaminathan 		emlxs_pkt_free(pkt);
379482527734SSukumar Swaminathan 	}
3795fcf3ce44SJohn Forte 
379682527734SSukumar Swaminathan 	return;
3797fcf3ce44SJohn Forte 
379882527734SSukumar Swaminathan } /* emlxs_fct_cmd_done() */
3799fcf3ce44SJohn Forte 
3800fcf3ce44SJohn Forte 
3801fcf3ce44SJohn Forte static void
emlxs_fct_pkt_comp(fc_packet_t * pkt)3802fcf3ce44SJohn Forte emlxs_fct_pkt_comp(fc_packet_t *pkt)
3803fcf3ce44SJohn Forte {
3804fcf3ce44SJohn Forte 	emlxs_port_t *port;
3805291a2b48SSukumar Swaminathan #ifdef FMA_SUPPORT
3806291a2b48SSukumar Swaminathan 	emlxs_hba_t *hba;
3807291a2b48SSukumar Swaminathan #endif	/* FMA_SUPPORT */
3808fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
3809fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
3810fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
3811fcf3ce44SJohn Forte 	fct_els_t *fct_els;
3812fcf3ce44SJohn Forte 	fct_sol_ct_t *fct_ct;
381382527734SSukumar Swaminathan 	fct_status_t rval;
3814fcf3ce44SJohn Forte 
3815fcf3ce44SJohn Forte 	sbp = PKT2PRIV(pkt);
3816fcf3ce44SJohn Forte 	port = sbp->port;
3817291a2b48SSukumar Swaminathan #ifdef FMA_SUPPORT
3818291a2b48SSukumar Swaminathan 	hba = HBA;
3819291a2b48SSukumar Swaminathan #endif	/* FMA_SUPPORT */
3820fcf3ce44SJohn Forte 	fct_cmd = sbp->fct_cmd;
3821291a2b48SSukumar Swaminathan 
382282527734SSukumar Swaminathan 	rval = emlxs_fct_cmd_acquire(port, fct_cmd, EMLXS_FCT_PKT_COMPLETE);
382382527734SSukumar Swaminathan 	if (rval) {
382482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
38258f23e9faSHans Rosenfeld 		    "fct_pkt_comp: "
382682527734SSukumar Swaminathan 		    "Unable to reacquire fct_cmd.");
382782527734SSukumar Swaminathan 		return;
3828291a2b48SSukumar Swaminathan 	}
382982527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
3830fcf3ce44SJohn Forte 
383182527734SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
383282527734SSukumar Swaminathan 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
3833fcf3ce44SJohn Forte 	cmd_sbp->fct_pkt = NULL;
3834fcf3ce44SJohn Forte 
3835291a2b48SSukumar Swaminathan 	switch (fct_cmd->cmd_type) {
3836291a2b48SSukumar Swaminathan 	case FCT_CMD_FCP_XCHG:
3837291a2b48SSukumar Swaminathan 		if ((pkt->pkt_reason == FC_REASON_ABORTED) ||
3838291a2b48SSukumar Swaminathan 		    (pkt->pkt_reason == FC_REASON_XCHG_DROPPED) ||
3839291a2b48SSukumar Swaminathan 		    (pkt->pkt_reason == FC_REASON_OFFLINE)) {
3840291a2b48SSukumar Swaminathan 			/*
3841291a2b48SSukumar Swaminathan 			 * The error indicates this IO should be terminated
3842291a2b48SSukumar Swaminathan 			 * immediately.
3843291a2b48SSukumar Swaminathan 			 */
3844291a2b48SSukumar Swaminathan 			cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
3845fcf3ce44SJohn Forte 
384682527734SSukumar Swaminathan 			emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
384782527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
3848fcf3ce44SJohn Forte 
3849291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
3850291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
38518f23e9faSHans Rosenfeld 			    "fct_queue_cmd_for_termination:2 %p:%p x%x",
38528f23e9faSHans Rosenfeld 			    fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status);
3853291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
385482527734SSukumar Swaminathan 
3855291a2b48SSukumar Swaminathan 			MODSYM(fct_queue_cmd_for_termination) (fct_cmd,
3856291a2b48SSukumar Swaminathan 			    FCT_ABTS_RECEIVED);
385782527734SSukumar Swaminathan 
385882527734SSukumar Swaminathan 			break;
3859291a2b48SSukumar Swaminathan 		}
3860fcf3ce44SJohn Forte 
386182527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3862291a2b48SSukumar Swaminathan 		    EMLXS_FCT_PKT_FCPRSP_COMPLETE);
3863291a2b48SSukumar Swaminathan 
386482527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3865291a2b48SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3866fcf3ce44SJohn Forte 
3867fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3868fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
38698f23e9faSHans Rosenfeld 		    "fct_send_response_done:2 %p:%p x%x outio %d",
38708f23e9faSHans Rosenfeld 		    fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status,
38718f23e9faSHans Rosenfeld 		    TGTPORTSTAT.FctOutstandingIO);
3872fcf3ce44SJohn Forte #else
3873fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
38748f23e9faSHans Rosenfeld 		    "fct_pkt_comp: fct_send_response_done. dbuf=%p",
3875fcf3ce44SJohn Forte 		    sbp->fct_buf);
3876291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
3877291a2b48SSukumar Swaminathan 
3878291a2b48SSukumar Swaminathan 		TGTPORTSTAT.FctOutstandingIO--;
3879fcf3ce44SJohn Forte 
3880fcf3ce44SJohn Forte 		MODSYM(fct_send_response_done) (fct_cmd,
3881fcf3ce44SJohn Forte 		    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
3882fcf3ce44SJohn Forte 
3883fcf3ce44SJohn Forte 		break;
3884fcf3ce44SJohn Forte 
3885fcf3ce44SJohn Forte 	case FCT_CMD_RCVD_ELS:
3886fcf3ce44SJohn Forte 
388782527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3888291a2b48SSukumar Swaminathan 		    EMLXS_FCT_PKT_ELSRSP_COMPLETE);
3889291a2b48SSukumar Swaminathan 
389082527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3891291a2b48SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3892fcf3ce44SJohn Forte 
3893fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3894fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
38958f23e9faSHans Rosenfeld 		    "fct_send_response_done:3 %p:%p x%x",
38968f23e9faSHans Rosenfeld 		    fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status);
3897291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
389882527734SSukumar Swaminathan 
3899fcf3ce44SJohn Forte 		MODSYM(fct_send_response_done) (fct_cmd,
3900fcf3ce44SJohn Forte 		    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
3901fcf3ce44SJohn Forte 
3902fcf3ce44SJohn Forte 		break;
3903fcf3ce44SJohn Forte 
3904fcf3ce44SJohn Forte 	case FCT_CMD_SOL_ELS:
3905291a2b48SSukumar Swaminathan 
390682527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3907291a2b48SSukumar Swaminathan 		    EMLXS_FCT_PKT_ELSCMD_COMPLETE);
3908291a2b48SSukumar Swaminathan 
3909fcf3ce44SJohn Forte 		fct_els = (fct_els_t *)fct_cmd->cmd_specific;
3910fcf3ce44SJohn Forte 
3911fcf3ce44SJohn Forte 		if (fct_els->els_resp_payload) {
391282527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0,
3913291a2b48SSukumar Swaminathan 			    pkt->pkt_rsplen, DDI_DMA_SYNC_FORKERNEL);
3914fcf3ce44SJohn Forte 
3915fcf3ce44SJohn Forte 			bcopy((uint8_t *)pkt->pkt_resp,
3916fcf3ce44SJohn Forte 			    (uint8_t *)fct_els->els_resp_payload,
3917fcf3ce44SJohn Forte 			    fct_els->els_resp_size);
3918fcf3ce44SJohn Forte 		}
3919291a2b48SSukumar Swaminathan 
392082527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3921291a2b48SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3922fcf3ce44SJohn Forte 
3923fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3924fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
39258f23e9faSHans Rosenfeld 		    "fct_send_cmd_done:1 %p:%p x%x",
39268f23e9faSHans Rosenfeld 		    fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status);
3927291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
392882527734SSukumar Swaminathan 
3929b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3930b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma)
3931b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
3932b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3933b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
39348f23e9faSHans Rosenfeld 			    "fct_pkt_comp: hdl=%p",
3935b3660a96SSukumar Swaminathan 			    pkt->pkt_resp_dma);
3936b3660a96SSukumar Swaminathan 			MODSYM(fct_send_cmd_done) (fct_cmd, FCT_FAILURE,
3937b3660a96SSukumar Swaminathan 			    FCT_IOF_FCA_DONE);
3938b3660a96SSukumar Swaminathan 
3939b3660a96SSukumar Swaminathan 			break;
3940b3660a96SSukumar Swaminathan 		}
3941b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */
3942b3660a96SSukumar Swaminathan 
3943291a2b48SSukumar Swaminathan 		MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS,
3944291a2b48SSukumar Swaminathan 		    FCT_IOF_FCA_DONE);
3945fcf3ce44SJohn Forte 
3946fcf3ce44SJohn Forte 		break;
3947fcf3ce44SJohn Forte 
3948fcf3ce44SJohn Forte 	case FCT_CMD_SOL_CT:
3949291a2b48SSukumar Swaminathan 
395082527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3951291a2b48SSukumar Swaminathan 		    EMLXS_FCT_PKT_CTCMD_COMPLETE);
3952291a2b48SSukumar Swaminathan 
3953fcf3ce44SJohn Forte 		fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific;
3954fcf3ce44SJohn Forte 
3955fcf3ce44SJohn Forte 		if (fct_ct->ct_resp_payload) {
395682527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0,
3957291a2b48SSukumar Swaminathan 			    pkt->pkt_rsplen, DDI_DMA_SYNC_FORKERNEL);
3958fcf3ce44SJohn Forte 
3959fcf3ce44SJohn Forte 			bcopy((uint8_t *)pkt->pkt_resp,
3960fcf3ce44SJohn Forte 			    (uint8_t *)fct_ct->ct_resp_payload,
3961fcf3ce44SJohn Forte 			    fct_ct->ct_resp_size);
3962fcf3ce44SJohn Forte 		}
3963291a2b48SSukumar Swaminathan 
396482527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3965291a2b48SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3966fcf3ce44SJohn Forte 
3967fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3968fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
39698f23e9faSHans Rosenfeld 		    "fct_send_cmd_done:2 %p:%p x%x",
39708f23e9faSHans Rosenfeld 		    fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status);
3971291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
397282527734SSukumar Swaminathan 
3973b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3974b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma)
3975b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
3976b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3977b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
39788f23e9faSHans Rosenfeld 			    "fct_pkt_comp: hdl=%p",
3979b3660a96SSukumar Swaminathan 			    pkt->pkt_resp_dma);
3980b3660a96SSukumar Swaminathan 			MODSYM(fct_send_cmd_done) (fct_cmd, FCT_FAILURE,
3981b3660a96SSukumar Swaminathan 			    FCT_IOF_FCA_DONE);
3982b3660a96SSukumar Swaminathan 
3983b3660a96SSukumar Swaminathan 			break;
3984b3660a96SSukumar Swaminathan 		}
3985b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */
3986291a2b48SSukumar Swaminathan 		MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS,
3987291a2b48SSukumar Swaminathan 		    FCT_IOF_FCA_DONE);
398882527734SSukumar Swaminathan 
3989fcf3ce44SJohn Forte 		break;
3990fcf3ce44SJohn Forte 
3991fcf3ce44SJohn Forte 	default:
3992fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
39938f23e9faSHans Rosenfeld 		    "fct_pkt_comp: Invalid cmd type found. type=%x",
3994fcf3ce44SJohn Forte 		    fct_cmd->cmd_type);
3995fcf3ce44SJohn Forte 
399682527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
399782527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
399882527734SSukumar Swaminathan 
399982527734SSukumar Swaminathan 		break;
4000fcf3ce44SJohn Forte 	}
4001fcf3ce44SJohn Forte 
4002fcf3ce44SJohn Forte 	emlxs_pkt_free(pkt);
4003fcf3ce44SJohn Forte 	return;
4004fcf3ce44SJohn Forte 
400582527734SSukumar Swaminathan } /* emlxs_fct_pkt_comp() */
4006fcf3ce44SJohn Forte 
4007fcf3ce44SJohn Forte 
4008291a2b48SSukumar Swaminathan static void
emlxs_fct_abort_pkt_comp(fc_packet_t * pkt)4009291a2b48SSukumar Swaminathan emlxs_fct_abort_pkt_comp(fc_packet_t *pkt)
4010fcf3ce44SJohn Forte {
40118f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
4012291a2b48SSukumar Swaminathan 	emlxs_buf_t *sbp;
4013291a2b48SSukumar Swaminathan 	IOCBQ *iocbq;
4014291a2b48SSukumar Swaminathan 	IOCB *iocb;
40158f23e9faSHans Rosenfeld 	emlxs_port_t *port;
4016291a2b48SSukumar Swaminathan 
4017291a2b48SSukumar Swaminathan 	sbp = PKT2PRIV(pkt);
40188f23e9faSHans Rosenfeld 	port = sbp->port;
4019291a2b48SSukumar Swaminathan 	iocbq = &sbp->iocbq;
4020291a2b48SSukumar Swaminathan 	iocb = &iocbq->iocb;
4021291a2b48SSukumar Swaminathan 
4022291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
40238f23e9faSHans Rosenfeld 	    "fct_abort_pkt_comp: %p: xri=%d cmd=%x status=%x",
40248f23e9faSHans Rosenfeld 	    sbp->fct_cmd, sbp,
40258f23e9faSHans Rosenfeld 	    iocb->ULPCONTEXT, iocb->ULPCOMMAND, iocb->ULPSTATUS);
4026291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
4027291a2b48SSukumar Swaminathan 
4028291a2b48SSukumar Swaminathan 	emlxs_pkt_free(pkt);
4029291a2b48SSukumar Swaminathan 	return;
4030291a2b48SSukumar Swaminathan 
403182527734SSukumar Swaminathan } /* emlxs_fct_abort_pkt_comp() */
4032291a2b48SSukumar Swaminathan 
4033291a2b48SSukumar Swaminathan 
403482527734SSukumar Swaminathan /* COMSTAR ENTER POINT (INDIRECT) */
4035291a2b48SSukumar Swaminathan static fct_status_t
emlxs_fct_send_els_cmd(fct_cmd_t * fct_cmd)4036291a2b48SSukumar Swaminathan emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd)
4037291a2b48SSukumar Swaminathan {
4038291a2b48SSukumar Swaminathan 	emlxs_port_t *port =
4039291a2b48SSukumar Swaminathan 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
4040fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4041fcf3ce44SJohn Forte 	uint32_t did;
40428f23e9faSHans Rosenfeld 	uint32_t sid;
4043fcf3ce44SJohn Forte 	fct_els_t *fct_els;
4044fcf3ce44SJohn Forte 	fc_packet_t *pkt;
4045fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
404682527734SSukumar Swaminathan 	fct_status_t rval;
4047fcf3ce44SJohn Forte 
4048fcf3ce44SJohn Forte 	did = fct_cmd->cmd_rportid;
40498f23e9faSHans Rosenfeld 	sid = fct_cmd->cmd_lportid;
4050fcf3ce44SJohn Forte 	fct_els = (fct_els_t *)fct_cmd->cmd_specific;
4051fcf3ce44SJohn Forte 
4052fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_req_size,
4053fcf3ce44SJohn Forte 	    fct_els->els_resp_size, 0, KM_NOSLEEP))) {
4054fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
40558f23e9faSHans Rosenfeld 		    "fct_send_els_cmd: Unable to allocate packet.");
405682527734SSukumar Swaminathan 
405782527734SSukumar Swaminathan 		return (FCT_BUSY);
4058fcf3ce44SJohn Forte 	}
4059291a2b48SSukumar Swaminathan 
406082527734SSukumar Swaminathan 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_SEND_ELS_REQ);
4061291a2b48SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
4062291a2b48SSukumar Swaminathan 
406382527734SSukumar Swaminathan 	cmd_sbp->channel = &hba->chan[hba->channel_els];
4064fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_ELS_REQ;
4065fcf3ce44SJohn Forte 
4066fcf3ce44SJohn Forte 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
4067291a2b48SSukumar Swaminathan 	cmd_sbp->fct_pkt = pkt;
4068fcf3ce44SJohn Forte 
4069fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
4070fcf3ce44SJohn Forte 	pkt->pkt_timeout =
4071fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
40728f23e9faSHans Rosenfeld 	pkt->pkt_timeout = (pkt->pkt_timeout > 60)? 60: pkt->pkt_timeout;
4073fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_fct_pkt_comp;
4074fcf3ce44SJohn Forte 
4075fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
40768f23e9faSHans Rosenfeld 	    "fct_send_els_cmd: pkt_timeout=%d ratov=%d",
4077fcf3ce44SJohn Forte 	    pkt->pkt_timeout, hba->fc_ratov);
4078fcf3ce44SJohn Forte 
4079fcf3ce44SJohn Forte 	/* Build the fc header */
408082527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
4081fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
40828f23e9faSHans Rosenfeld 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(sid);
4083fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
4084fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
4085fcf3ce44SJohn Forte 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
4086fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
4087fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4088fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4089fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
4090fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
4091fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
4092fcf3ce44SJohn Forte 
4093fcf3ce44SJohn Forte 	/* Copy the cmd payload */
4094fcf3ce44SJohn Forte 	bcopy((uint8_t *)fct_els->els_req_payload, (uint8_t *)pkt->pkt_cmd,
4095fcf3ce44SJohn Forte 	    fct_els->els_req_size);
409682527734SSukumar Swaminathan 
4097291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
409882527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_REQ_PENDING);
409982527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
4100fcf3ce44SJohn Forte 
4101fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
410282527734SSukumar Swaminathan 
4103fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
41048f23e9faSHans Rosenfeld 		    "fct_send_els_cmd: Unable to send packet.");
4105fcf3ce44SJohn Forte 
410682527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
410782527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
410882527734SSukumar Swaminathan 		if (rval) {
410982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
41108f23e9faSHans Rosenfeld 			    "fct_send_els_cmd: "
411182527734SSukumar Swaminathan 			    "Unable to reacquire fct_cmd.");
411282527734SSukumar Swaminathan 			return (rval);
4113fcf3ce44SJohn Forte 		}
411482527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
4115fcf3ce44SJohn Forte 
411682527734SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
411782527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4118fcf3ce44SJohn Forte 
411982527734SSukumar Swaminathan 		return (FCT_BUSY);
4120fcf3ce44SJohn Forte 	}
4121fcf3ce44SJohn Forte 
4122fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
4123fcf3ce44SJohn Forte 
412482527734SSukumar Swaminathan } /* emlxs_fct_send_els_cmd() */
4125fcf3ce44SJohn Forte 
4126fcf3ce44SJohn Forte 
412782527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
412882527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be released before exiting */
4129fcf3ce44SJohn Forte static fct_status_t
emlxs_fct_send_els_rsp(fct_cmd_t * fct_cmd)4130fcf3ce44SJohn Forte emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd)
4131fcf3ce44SJohn Forte {
4132fcf3ce44SJohn Forte 	emlxs_port_t *port =
4133fcf3ce44SJohn Forte 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
4134fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4135fcf3ce44SJohn Forte 	uint32_t did;
41368f23e9faSHans Rosenfeld 	uint32_t sid;
4137fcf3ce44SJohn Forte 	fct_els_t *fct_els;
4138fcf3ce44SJohn Forte 	fc_packet_t *pkt;
4139fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
414082527734SSukumar Swaminathan 	fct_status_t rval;
4141fcf3ce44SJohn Forte 
4142fcf3ce44SJohn Forte 	fct_els = (fct_els_t *)fct_cmd->cmd_specific;
4143fcf3ce44SJohn Forte 	did = fct_cmd->cmd_rportid;
41448f23e9faSHans Rosenfeld 	sid = fct_cmd->cmd_lportid;
414582527734SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
4146fcf3ce44SJohn Forte 
4147291a2b48SSukumar Swaminathan 	if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_resp_size, 0, 0,
4148291a2b48SSukumar Swaminathan 	    KM_NOSLEEP))) {
4149fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
41508f23e9faSHans Rosenfeld 		    "fct_send_els_rsp: Unable to allocate packet.");
4151291a2b48SSukumar Swaminathan 
4152fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
415382527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4154fcf3ce44SJohn Forte 
415582527734SSukumar Swaminathan 		return (FCT_FAILURE);
415682527734SSukumar Swaminathan 	}
4157291a2b48SSukumar Swaminathan 
415882527734SSukumar Swaminathan 	EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_SEND_ELS_RSP);
4159fcf3ce44SJohn Forte 
4160fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_ELS_RSP;
4161fcf3ce44SJohn Forte 
4162fcf3ce44SJohn Forte 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
4163291a2b48SSukumar Swaminathan 	cmd_sbp->fct_pkt = pkt;
4164fcf3ce44SJohn Forte 
4165fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
4166fcf3ce44SJohn Forte 	pkt->pkt_timeout =
4167fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
41688f23e9faSHans Rosenfeld 	pkt->pkt_timeout = (pkt->pkt_timeout > 60)? 60: pkt->pkt_timeout;
4169fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_fct_pkt_comp;
4170fcf3ce44SJohn Forte 
4171fcf3ce44SJohn Forte 	/* Build the fc header */
417282527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
4173fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_RSP;
41748f23e9faSHans Rosenfeld 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(sid);
4175fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
4176fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
4177fcf3ce44SJohn Forte 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
4178fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
4179fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4180fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4181fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
4182fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
4183fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
4184fcf3ce44SJohn Forte 
4185fcf3ce44SJohn Forte 	/* Copy the resp payload to pkt_cmd buffer */
4186fcf3ce44SJohn Forte 	bcopy((uint8_t *)fct_els->els_resp_payload, (uint8_t *)pkt->pkt_cmd,
4187fcf3ce44SJohn Forte 	    fct_els->els_resp_size);
418882527734SSukumar Swaminathan 
4189291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
419082527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_RSP_PENDING);
419182527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
4192fcf3ce44SJohn Forte 
4193fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
419482527734SSukumar Swaminathan 
4195fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
41968f23e9faSHans Rosenfeld 		    "fct_send_els_rsp: Unable to send packet.");
4197fcf3ce44SJohn Forte 
419882527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
419982527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
420082527734SSukumar Swaminathan 		if (rval) {
420182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
42028f23e9faSHans Rosenfeld 			    "fct_send_els_rsp: "
420382527734SSukumar Swaminathan 			    "Unable to reacquire fct_cmd.");
420482527734SSukumar Swaminathan 			return (rval);
4205fcf3ce44SJohn Forte 		}
420682527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
4207291a2b48SSukumar Swaminathan 
4208fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
420982527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4210291a2b48SSukumar Swaminathan 
4211fcf3ce44SJohn Forte 		return (FCT_FAILURE);
4212fcf3ce44SJohn Forte 	}
4213fcf3ce44SJohn Forte 
4214291a2b48SSukumar Swaminathan 	return (FCT_SUCCESS);
4215fcf3ce44SJohn Forte 
421682527734SSukumar Swaminathan } /* emlxs_fct_send_els_rsp() */
4217fcf3ce44SJohn Forte 
4218fcf3ce44SJohn Forte 
421982527734SSukumar Swaminathan /* COMSTAR ENTER POINT (INDIRECT) */
4220fcf3ce44SJohn Forte static fct_status_t
emlxs_fct_send_ct_cmd(fct_cmd_t * fct_cmd)4221fcf3ce44SJohn Forte emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd)
4222fcf3ce44SJohn Forte {
4223fcf3ce44SJohn Forte 	emlxs_port_t *port =
4224fcf3ce44SJohn Forte 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
4225fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4226fcf3ce44SJohn Forte 	uint32_t did;
4227fcf3ce44SJohn Forte 	fct_sol_ct_t *fct_ct;
4228fcf3ce44SJohn Forte 	fc_packet_t *pkt;
4229fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
423082527734SSukumar Swaminathan 	fct_status_t rval;
4231fcf3ce44SJohn Forte 
4232fcf3ce44SJohn Forte 	did = fct_cmd->cmd_rportid;
4233fcf3ce44SJohn Forte 	fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific;
4234fcf3ce44SJohn Forte 
4235fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, fct_ct->ct_req_size,
4236fcf3ce44SJohn Forte 	    fct_ct->ct_resp_size, 0, KM_NOSLEEP))) {
4237fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
42388f23e9faSHans Rosenfeld 		    "fct_send_ct_cmd: Unable to allocate packet.");
423982527734SSukumar Swaminathan 		return (FCT_BUSY);
4240fcf3ce44SJohn Forte 	}
4241291a2b48SSukumar Swaminathan 
424282527734SSukumar Swaminathan 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_SEND_CT_REQ);
4243291a2b48SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
4244fcf3ce44SJohn Forte 
424582527734SSukumar Swaminathan 	cmd_sbp->channel = &hba->chan[hba->channel_ct];
4246fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_CT_REQ;
4247fcf3ce44SJohn Forte 
4248fcf3ce44SJohn Forte 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
4249291a2b48SSukumar Swaminathan 	cmd_sbp->fct_pkt = pkt;
4250fcf3ce44SJohn Forte 
4251fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
4252fcf3ce44SJohn Forte 	pkt->pkt_timeout =
4253fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
42548f23e9faSHans Rosenfeld 	pkt->pkt_timeout = (pkt->pkt_timeout > 60)? 60: pkt->pkt_timeout;
4255fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_fct_pkt_comp;
4256fcf3ce44SJohn Forte 
4257fcf3ce44SJohn Forte 	/* Build the fc header */
425882527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
4259fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL;
426082527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
4261fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
4262fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
4263fcf3ce44SJohn Forte 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
4264fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
4265fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4266fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4267fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
4268fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
4269fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
4270fcf3ce44SJohn Forte 
4271fcf3ce44SJohn Forte 	/* Copy the cmd payload */
4272fcf3ce44SJohn Forte 	bcopy((uint8_t *)fct_ct->ct_req_payload, (uint8_t *)pkt->pkt_cmd,
4273fcf3ce44SJohn Forte 	    fct_ct->ct_req_size);
427482527734SSukumar Swaminathan 
4275291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
427682527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_REQ_PENDING);
427782527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
4278fcf3ce44SJohn Forte 
4279fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
428082527734SSukumar Swaminathan 
4281fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
42828f23e9faSHans Rosenfeld 		    "fct_send_ct_cmd: Unable to send packet.");
4283fcf3ce44SJohn Forte 
428482527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
428582527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
428682527734SSukumar Swaminathan 		if (rval) {
428782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
42888f23e9faSHans Rosenfeld 			    "fct_send_ct_cmd: "
428982527734SSukumar Swaminathan 			    "Unable to reacquire fct_cmd.");
429082527734SSukumar Swaminathan 
429182527734SSukumar Swaminathan 			return (rval);
4292fcf3ce44SJohn Forte 		}
429382527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
4294fcf3ce44SJohn Forte 
429582527734SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
429682527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4297fcf3ce44SJohn Forte 
429882527734SSukumar Swaminathan 		return (FCT_BUSY);
4299fcf3ce44SJohn Forte 	}
4300fcf3ce44SJohn Forte 
4301fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
4302fcf3ce44SJohn Forte 
430382527734SSukumar Swaminathan } /* emlxs_fct_send_ct_cmd() */
4304fcf3ce44SJohn Forte 
4305fcf3ce44SJohn Forte 
430682527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
4307fe199829SSukumar Swaminathan static uint32_t
emlxs_fct_pkt_abort_txq(emlxs_port_t * port,emlxs_buf_t * cmd_sbp)4308291a2b48SSukumar Swaminathan emlxs_fct_pkt_abort_txq(emlxs_port_t *port, emlxs_buf_t *cmd_sbp)
4309fcf3ce44SJohn Forte {
4310fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4311fcf3ce44SJohn Forte 	NODELIST *nlp;
4312291a2b48SSukumar Swaminathan 	fc_packet_t *pkt;
4313291a2b48SSukumar Swaminathan 	emlxs_buf_t *sbp;
4314291a2b48SSukumar Swaminathan 	emlxs_buf_t *iocb_sbp;
431582527734SSukumar Swaminathan 	uint8_t channelno;
431682527734SSukumar Swaminathan 	CHANNEL *cp;
4317fcf3ce44SJohn Forte 	IOCBQ *iocbq;
4318fcf3ce44SJohn Forte 	IOCBQ *next;
4319fcf3ce44SJohn Forte 	IOCBQ *prev;
4320fcf3ce44SJohn Forte 	uint32_t found;
4321291a2b48SSukumar Swaminathan 	uint32_t pkt_flags;
4322fcf3ce44SJohn Forte 
4323291a2b48SSukumar Swaminathan 	/* Check the transmit queue */
432482527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
4325fcf3ce44SJohn Forte 
4326291a2b48SSukumar Swaminathan 	/* The IOCB could point to a cmd_sbp (no packet) or a sbp (packet) */
4327291a2b48SSukumar Swaminathan 	pkt = cmd_sbp->fct_pkt;
4328291a2b48SSukumar Swaminathan 	if (pkt) {
4329291a2b48SSukumar Swaminathan 		sbp = PKT2PRIV(pkt);
4330291a2b48SSukumar Swaminathan 		if (sbp == NULL) {
4331291a2b48SSukumar Swaminathan 			goto done;
4332291a2b48SSukumar Swaminathan 		}
4333291a2b48SSukumar Swaminathan 		iocb_sbp = sbp;
4334291a2b48SSukumar Swaminathan 		iocbq = &sbp->iocbq;
4335291a2b48SSukumar Swaminathan 		pkt_flags = sbp->pkt_flags;
4336291a2b48SSukumar Swaminathan 	} else {
4337291a2b48SSukumar Swaminathan 		sbp = NULL;
4338291a2b48SSukumar Swaminathan 		iocb_sbp = cmd_sbp;
4339291a2b48SSukumar Swaminathan 		iocbq = &cmd_sbp->iocbq;
4340291a2b48SSukumar Swaminathan 		pkt_flags = cmd_sbp->pkt_flags;
4341fcf3ce44SJohn Forte 	}
4342fcf3ce44SJohn Forte 
4343291a2b48SSukumar Swaminathan 	nlp = (NODELIST *)cmd_sbp->node;
434482527734SSukumar Swaminathan 	cp = (CHANNEL *)cmd_sbp->channel;
434582527734SSukumar Swaminathan 	channelno = (cp) ? cp->channelno : 0;
4346fcf3ce44SJohn Forte 
4347291a2b48SSukumar Swaminathan 	if (pkt_flags & PACKET_IN_TXQ) {
4348fcf3ce44SJohn Forte 		/* Find it on the queue */
4349fcf3ce44SJohn Forte 		found = 0;
4350fcf3ce44SJohn Forte 		if (iocbq->flag & IOCB_PRIORITY) {
4351fcf3ce44SJohn Forte 			/* Search the priority queue */
4352fcf3ce44SJohn Forte 			prev = NULL;
435382527734SSukumar Swaminathan 			next = (IOCBQ *)nlp->nlp_ptx[channelno].q_first;
4354fcf3ce44SJohn Forte 
4355fcf3ce44SJohn Forte 			while (next) {
4356fcf3ce44SJohn Forte 				if (next == iocbq) {
4357fcf3ce44SJohn Forte 					/* Remove it */
4358fcf3ce44SJohn Forte 					if (prev) {
4359fcf3ce44SJohn Forte 						prev->next = iocbq->next;
4360fcf3ce44SJohn Forte 					}
4361291a2b48SSukumar Swaminathan 
436282527734SSukumar Swaminathan 					if (nlp->nlp_ptx[channelno].q_last ==
4363fcf3ce44SJohn Forte 					    (void *)iocbq) {
436482527734SSukumar Swaminathan 						nlp->nlp_ptx[channelno].q_last =
4365fcf3ce44SJohn Forte 						    (void *)prev;
4366fcf3ce44SJohn Forte 					}
4367291a2b48SSukumar Swaminathan 
436882527734SSukumar Swaminathan 					if (nlp->nlp_ptx[channelno].q_first ==
4369fcf3ce44SJohn Forte 					    (void *)iocbq) {
437082527734SSukumar Swaminathan 						nlp->nlp_ptx[channelno].
437182527734SSukumar Swaminathan 						    q_first =
4372fcf3ce44SJohn Forte 						    (void *)iocbq->next;
4373fcf3ce44SJohn Forte 					}
4374291a2b48SSukumar Swaminathan 
437582527734SSukumar Swaminathan 					nlp->nlp_ptx[channelno].q_cnt--;
4376fcf3ce44SJohn Forte 					iocbq->next = NULL;
4377fcf3ce44SJohn Forte 					found = 1;
4378fcf3ce44SJohn Forte 					break;
4379fcf3ce44SJohn Forte 				}
4380291a2b48SSukumar Swaminathan 
4381fcf3ce44SJohn Forte 				prev = next;
4382fcf3ce44SJohn Forte 				next = next->next;
4383fcf3ce44SJohn Forte 			}
4384fcf3ce44SJohn Forte 		} else {
4385fcf3ce44SJohn Forte 			/* Search the normal queue */
4386fcf3ce44SJohn Forte 			prev = NULL;
438782527734SSukumar Swaminathan 			next = (IOCBQ *)nlp->nlp_tx[channelno].q_first;
4388fcf3ce44SJohn Forte 
4389fcf3ce44SJohn Forte 			while (next) {
4390fcf3ce44SJohn Forte 				if (next == iocbq) {
4391fcf3ce44SJohn Forte 					/* Remove it */
4392fcf3ce44SJohn Forte 					if (prev) {
4393fcf3ce44SJohn Forte 						prev->next = iocbq->next;
4394fcf3ce44SJohn Forte 					}
4395291a2b48SSukumar Swaminathan 
439682527734SSukumar Swaminathan 					if (nlp->nlp_tx[channelno].q_last ==
4397fcf3ce44SJohn Forte 					    (void *)iocbq) {
439882527734SSukumar Swaminathan 						nlp->nlp_tx[channelno].q_last =
4399fcf3ce44SJohn Forte 						    (void *)prev;
4400fcf3ce44SJohn Forte 					}
4401291a2b48SSukumar Swaminathan 
440282527734SSukumar Swaminathan 					if (nlp->nlp_tx[channelno].q_first ==
4403fcf3ce44SJohn Forte 					    (void *)iocbq) {
440482527734SSukumar Swaminathan 						nlp->nlp_tx[channelno].q_first =
4405fcf3ce44SJohn Forte 						    (void *)iocbq->next;
4406fcf3ce44SJohn Forte 					}
4407291a2b48SSukumar Swaminathan 
440882527734SSukumar Swaminathan 					nlp->nlp_tx[channelno].q_cnt--;
4409fcf3ce44SJohn Forte 					iocbq->next = NULL;
4410fcf3ce44SJohn Forte 					found = 1;
4411fcf3ce44SJohn Forte 					break;
4412fcf3ce44SJohn Forte 				}
4413291a2b48SSukumar Swaminathan 
4414fcf3ce44SJohn Forte 				prev = next;
4415fcf3ce44SJohn Forte 				next = (IOCBQ *)next->next;
4416fcf3ce44SJohn Forte 			}
4417fcf3ce44SJohn Forte 		}
4418fcf3ce44SJohn Forte 
4419fcf3ce44SJohn Forte 		if (!found) {
4420fcf3ce44SJohn Forte 			goto done;
4421fcf3ce44SJohn Forte 		}
4422291a2b48SSukumar Swaminathan 
4423fcf3ce44SJohn Forte 		/* Check if node still needs servicing */
442482527734SSukumar Swaminathan 		if ((nlp->nlp_ptx[channelno].q_first) ||
442582527734SSukumar Swaminathan 		    (nlp->nlp_tx[channelno].q_first &&
442682527734SSukumar Swaminathan 		    !(nlp->nlp_flag[channelno] & NLP_CLOSED))) {
4427fcf3ce44SJohn Forte 
4428fcf3ce44SJohn Forte 			/*
4429291a2b48SSukumar Swaminathan 			 * If this is the base node, don't shift the pointers
4430fcf3ce44SJohn Forte 			 */
4431fcf3ce44SJohn Forte 			/* We want to drain the base node before moving on */
4432fcf3ce44SJohn Forte 			if (!nlp->nlp_base) {
443382527734SSukumar Swaminathan 				/* Shift channel queue pointers to next node */
443482527734SSukumar Swaminathan 				cp->nodeq.q_last = (void *)nlp;
443582527734SSukumar Swaminathan 				cp->nodeq.q_first = nlp->nlp_next[channelno];
4436fcf3ce44SJohn Forte 			}
4437fcf3ce44SJohn Forte 		} else {
443882527734SSukumar Swaminathan 			/* Remove node from channel queue */
4439fcf3ce44SJohn Forte 
4440fcf3ce44SJohn Forte 			/* If this is the last node on list */
444182527734SSukumar Swaminathan 			if (cp->nodeq.q_last == (void *)nlp) {
444282527734SSukumar Swaminathan 				cp->nodeq.q_last = NULL;
444382527734SSukumar Swaminathan 				cp->nodeq.q_first = NULL;
444482527734SSukumar Swaminathan 				cp->nodeq.q_cnt = 0;
4445fcf3ce44SJohn Forte 			} else {
4446fcf3ce44SJohn Forte 				/* Remove node from head */
444782527734SSukumar Swaminathan 				cp->nodeq.q_first = nlp->nlp_next[channelno];
444882527734SSukumar Swaminathan 				((NODELIST *)cp->nodeq.q_last)->
444982527734SSukumar Swaminathan 				    nlp_next[channelno] = cp->nodeq.q_first;
445082527734SSukumar Swaminathan 				cp->nodeq.q_cnt--;
4451fcf3ce44SJohn Forte 			}
4452fcf3ce44SJohn Forte 
4453fcf3ce44SJohn Forte 			/* Clear node */
445482527734SSukumar Swaminathan 			nlp->nlp_next[channelno] = NULL;
4455fcf3ce44SJohn Forte 		}
4456fcf3ce44SJohn Forte 
445782527734SSukumar Swaminathan 		/* The IOCB points to iocb_sbp (no packet) or a sbp (packet) */
445882527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
44598f23e9faSHans Rosenfeld 			emlxs_sli4_free_xri(port, iocb_sbp, iocb_sbp->xrip, 1);
446082527734SSukumar Swaminathan 		} else {
446182527734SSukumar Swaminathan 			(void) emlxs_unregister_pkt(cp, iocb_sbp->iotag, 0);
4462fcf3ce44SJohn Forte 		}
4463fcf3ce44SJohn Forte 
446482527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
4465fcf3ce44SJohn Forte 
4466291a2b48SSukumar Swaminathan 		if (pkt) {
4467291a2b48SSukumar Swaminathan 			emlxs_pkt_free(pkt);
4468291a2b48SSukumar Swaminathan 			cmd_sbp->fct_pkt = NULL;
4469fcf3ce44SJohn Forte 		}
447082527734SSukumar Swaminathan 		return (1);
4471fcf3ce44SJohn Forte 	}
4472291a2b48SSukumar Swaminathan done:
447382527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
447482527734SSukumar Swaminathan 	return (0);
447582527734SSukumar Swaminathan 
447682527734SSukumar Swaminathan } /* emlxs_fct_pkt_abort_txq() */
4477fcf3ce44SJohn Forte 
4478fcf3ce44SJohn Forte 
447982527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
4480291a2b48SSukumar Swaminathan /* FCT_NOT_FOUND & FCT_ABORT_SUCCESS indicates IO is done */
4481291a2b48SSukumar Swaminathan /* FCT_SUCCESS indicates abort will occur asyncronously */
4482291a2b48SSukumar Swaminathan static fct_status_t
emlxs_fct_abort(fct_local_port_t * fct_port,fct_cmd_t * fct_cmd,uint32_t flags)4483291a2b48SSukumar Swaminathan emlxs_fct_abort(fct_local_port_t *fct_port, fct_cmd_t *fct_cmd,
4484291a2b48SSukumar Swaminathan     uint32_t flags)
4485291a2b48SSukumar Swaminathan {
4486291a2b48SSukumar Swaminathan 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
4487291a2b48SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
4488291a2b48SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp;
448982527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp2;
449082527734SSukumar Swaminathan 	emlxs_buf_t *prev;
4491291a2b48SSukumar Swaminathan 	fc_packet_t *pkt;
4492291a2b48SSukumar Swaminathan 	emlxs_buf_t *sbp = NULL;
449382527734SSukumar Swaminathan 	kmutex_t *fct_mtx;
449482527734SSukumar Swaminathan 	uint32_t fct_state;
449582527734SSukumar Swaminathan 
449682527734SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
449782527734SSukumar Swaminathan 	fct_mtx = &cmd_sbp->fct_mtx;
4498fcf3ce44SJohn Forte 
4499291a2b48SSukumar Swaminathan top:
450082527734SSukumar Swaminathan 
4501291a2b48SSukumar Swaminathan 	/* Sanity check */
4502291a2b48SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
4503291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
45048f23e9faSHans Rosenfeld 		    "fct_abort: Bad fct_cmd=%p.", fct_cmd);
4505fcf3ce44SJohn Forte 
4506291a2b48SSukumar Swaminathan 		return (FCT_NOT_FOUND);
4507291a2b48SSukumar Swaminathan 	}
4508fcf3ce44SJohn Forte 
4509291a2b48SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
4510291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
45118f23e9faSHans Rosenfeld 		    "fct_abort: Pkt invalid. cmd_sbp=%p",
451282527734SSukumar Swaminathan 		    cmd_sbp);
4513fcf3ce44SJohn Forte 
4514291a2b48SSukumar Swaminathan 		return (FCT_NOT_FOUND);
4515fcf3ce44SJohn Forte 	}
4516fcf3ce44SJohn Forte 
451782527734SSukumar Swaminathan 	if (mutex_tryenter(fct_mtx) == 0) {
4518fcf3ce44SJohn Forte 		/*
4519291a2b48SSukumar Swaminathan 		 * This code path handles a race condition if
4520291a2b48SSukumar Swaminathan 		 * an IO completes, in emlxs_fct_handle_fcp_event(),
4521291a2b48SSukumar Swaminathan 		 * and we get an abort at the same time.
4522fcf3ce44SJohn Forte 		 */
4523291a2b48SSukumar Swaminathan 		delay(drv_usectohz(100000));	/* 100 msec */
4524291a2b48SSukumar Swaminathan 		goto top;
4525fcf3ce44SJohn Forte 	}
4526291a2b48SSukumar Swaminathan 	/* At this point, we have entered the mutex */
4527fcf3ce44SJohn Forte 
452882527734SSukumar Swaminathan 	/* Sanity check */
452982527734SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
4530291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
45318f23e9faSHans Rosenfeld 		    "fct_abort: Bad fct_cmd=%p.", fct_cmd);
4532fcf3ce44SJohn Forte 
453382527734SSukumar Swaminathan 		mutex_exit(fct_mtx);
4534291a2b48SSukumar Swaminathan 		return (FCT_NOT_FOUND);
4535fcf3ce44SJohn Forte 	}
4536fcf3ce44SJohn Forte 
453782527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
453882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
45398f23e9faSHans Rosenfeld 		    "fct_abort: Pkt invalid. cmd_sbp=%p",
454082527734SSukumar Swaminathan 		    cmd_sbp);
454182527734SSukumar Swaminathan 
454282527734SSukumar Swaminathan 		mutex_exit(fct_mtx);
454382527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
4544fcf3ce44SJohn Forte 	}
4545fcf3ce44SJohn Forte 
4546291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
45478f23e9faSHans Rosenfeld 	    "fct_abort: hbastate=%x. "
4548fe199829SSukumar Swaminathan 	    "xid=%x,%x cmd_sbp=%p fctstate=%d flags=%x,%x,%x",
4549fe199829SSukumar Swaminathan 	    hba->state, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid, cmd_sbp,
4550fe199829SSukumar Swaminathan 	    cmd_sbp->fct_state, flags, cmd_sbp->fct_flags, cmd_sbp->pkt_flags);
4551291a2b48SSukumar Swaminathan 
4552291a2b48SSukumar Swaminathan 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) {
455382527734SSukumar Swaminathan 		EMLXS_SLI_ISSUE_IOCB_CMD(hba, cmd_sbp->channel, 0);
455482527734SSukumar Swaminathan 
4555291a2b48SSukumar Swaminathan 		/* If Abort is already in progress */
455682527734SSukumar Swaminathan 		mutex_exit(fct_mtx);
455782527734SSukumar Swaminathan 		return (FCT_SUCCESS);
455882527734SSukumar Swaminathan 	}
455982527734SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_ABORT_INP;
456082527734SSukumar Swaminathan 
456182527734SSukumar Swaminathan 	if (flags & FCT_IOF_FORCE_FCA_DONE) {
456282527734SSukumar Swaminathan 		fct_cmd->cmd_handle = 0;
4563291a2b48SSukumar Swaminathan 	}
4564fcf3ce44SJohn Forte 
4565291a2b48SSukumar Swaminathan 	TGTPORTSTAT.FctAbortSent++;
4566fcf3ce44SJohn Forte 
456782527734SSukumar Swaminathan 	switch (cmd_sbp->fct_state) {
456882527734SSukumar Swaminathan 	/* These are currently owned by COMSTAR. */
456982527734SSukumar Swaminathan 	/* They were last processed by emlxs_fct_cmd_post() */
4570fe199829SSukumar Swaminathan 	/* We have NO exchange resources associated with this IO. */
457182527734SSukumar Swaminathan 	case EMLXS_FCT_OWNED:
4572fe199829SSukumar Swaminathan 		goto abort_done;
457382527734SSukumar Swaminathan 
457482527734SSukumar Swaminathan 	/* These are on the unsol waitQ in the driver */
457582527734SSukumar Swaminathan 	case EMLXS_FCT_CMD_WAITQ:
457682527734SSukumar Swaminathan 		/* Find and remove it */
457782527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
457882527734SSukumar Swaminathan 		cmd_sbp2 = port->fct_wait_head;
457982527734SSukumar Swaminathan 		prev = NULL;
458082527734SSukumar Swaminathan 		while (cmd_sbp2) {
458182527734SSukumar Swaminathan 			if (cmd_sbp2 == cmd_sbp) {
458282527734SSukumar Swaminathan 				/* Remove it */
458382527734SSukumar Swaminathan 				if (prev) {
458482527734SSukumar Swaminathan 					prev->next = cmd_sbp2->next;
458582527734SSukumar Swaminathan 				}
458682527734SSukumar Swaminathan 
458782527734SSukumar Swaminathan 				if (port->fct_wait_head == cmd_sbp2) {
458882527734SSukumar Swaminathan 					port->fct_wait_head = cmd_sbp2->next;
458982527734SSukumar Swaminathan 				}
459082527734SSukumar Swaminathan 
459182527734SSukumar Swaminathan 				if (port->fct_wait_tail == cmd_sbp2) {
459282527734SSukumar Swaminathan 					port->fct_wait_tail = prev;
459382527734SSukumar Swaminathan 				}
459482527734SSukumar Swaminathan 
459582527734SSukumar Swaminathan 				cmd_sbp2->next = NULL;
459682527734SSukumar Swaminathan 				break;
459782527734SSukumar Swaminathan 			}
459882527734SSukumar Swaminathan 			prev = cmd_sbp2;
459982527734SSukumar Swaminathan 			cmd_sbp2 = cmd_sbp2->next;
460082527734SSukumar Swaminathan 		}
460182527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
460282527734SSukumar Swaminathan 
4603fe199829SSukumar Swaminathan 		/*FALLTHROUGH*/
4604fe199829SSukumar Swaminathan 
4605fe199829SSukumar Swaminathan 	/* These are currently owned by COMSTAR. */
4606fe199829SSukumar Swaminathan 	/* They were last processed by emlxs_fct_cmd_post() */
4607fe199829SSukumar Swaminathan 	/* We have residual exchange resources associated with this IO */
4608fe199829SSukumar Swaminathan 	case EMLXS_FCT_CMD_POSTED:
4609fe199829SSukumar Swaminathan 		switch (fct_cmd->cmd_type) {
4610fe199829SSukumar Swaminathan 		case FCT_CMD_FCP_XCHG: /* Unsol */
4611fe199829SSukumar Swaminathan 			TGTPORTSTAT.FctOutstandingIO--;
4612fe199829SSukumar Swaminathan 			emlxs_abort_fct_exchange(hba, port, fct_cmd->cmd_rxid);
4613fe199829SSukumar Swaminathan 			break;
4614fe199829SSukumar Swaminathan 
4615fe199829SSukumar Swaminathan 		case FCT_CMD_RCVD_ELS: /* Unsol */
4616fe199829SSukumar Swaminathan 			emlxs_abort_els_exchange(hba, port, fct_cmd->cmd_rxid);
4617fe199829SSukumar Swaminathan 			break;
4618fe199829SSukumar Swaminathan 		}
4619fe199829SSukumar Swaminathan 
4620fe199829SSukumar Swaminathan 		goto abort_done;
462182527734SSukumar Swaminathan 
462282527734SSukumar Swaminathan 	/* These are active in the driver */
462382527734SSukumar Swaminathan 	/* They were last processed by emlxs_fct_cmd_release() */
4624291a2b48SSukumar Swaminathan 	case EMLXS_FCT_RSP_PENDING:
4625291a2b48SSukumar Swaminathan 	case EMLXS_FCT_REQ_PENDING:
4626291a2b48SSukumar Swaminathan 	case EMLXS_FCT_REG_PENDING:
4627291a2b48SSukumar Swaminathan 	case EMLXS_FCT_DATA_PENDING:
4628291a2b48SSukumar Swaminathan 	case EMLXS_FCT_STATUS_PENDING:
462982527734SSukumar Swaminathan 
463082527734SSukumar Swaminathan 		/* Abort anything pending */
4631291a2b48SSukumar Swaminathan 		if (emlxs_fct_pkt_abort_txq(port, cmd_sbp)) {
4632fcf3ce44SJohn Forte 
4633291a2b48SSukumar Swaminathan 			if (fct_cmd->cmd_type == FCT_CMD_FCP_XCHG) {
4634291a2b48SSukumar Swaminathan 				TGTPORTSTAT.FctOutstandingIO--;
4635fcf3ce44SJohn Forte 			}
463682527734SSukumar Swaminathan 
4637fe199829SSukumar Swaminathan 			goto abort_done;
4638291a2b48SSukumar Swaminathan 		}
4639fcf3ce44SJohn Forte 
464082527734SSukumar Swaminathan 		/* If we're not online, then all IO will be flushed anyway */
4641291a2b48SSukumar Swaminathan 		if (!(hba->flag & FC_ONLINE_MODE)) {
464282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
46438f23e9faSHans Rosenfeld 			    "fct_abort: Not online. fct_cmd=%p.",
464482527734SSukumar Swaminathan 			    fct_cmd);
4645291a2b48SSukumar Swaminathan 
464682527734SSukumar Swaminathan 			emlxs_fct_cmd_release(port, fct_cmd, 0);
464782527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
464882527734SSukumar Swaminathan 
464982527734SSukumar Swaminathan 			/* The cmd will be aborted on the */
465082527734SSukumar Swaminathan 			/* next emlxs_fct_cmd_acquire */
465182527734SSukumar Swaminathan 			/* because EMLXS_FCT_ABORT_INP is set. */
465282527734SSukumar Swaminathan 			break;
4653fcf3ce44SJohn Forte 		}
4654fcf3ce44SJohn Forte 
465582527734SSukumar Swaminathan 		/* Try to send abort request */
4656291a2b48SSukumar Swaminathan 		if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) {
4657291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
46588f23e9faSHans Rosenfeld 			    "fct_abort: Unable to allocate packet. "
465982527734SSukumar Swaminathan 			    "fct_cmd=%p",
466082527734SSukumar Swaminathan 			    fct_cmd);
466182527734SSukumar Swaminathan 
466282527734SSukumar Swaminathan 			emlxs_fct_cmd_release(port, fct_cmd, 0);
466382527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
466482527734SSukumar Swaminathan 
466582527734SSukumar Swaminathan 			/* The cmd will be aborted on the */
466682527734SSukumar Swaminathan 			/* next emlxs_fct_cmd_acquire anyway */
466782527734SSukumar Swaminathan 			/* because EMLXS_FCT_ABORT_INP is set. */
466882527734SSukumar Swaminathan 			break;
4669fcf3ce44SJohn Forte 		}
4670fcf3ce44SJohn Forte 
4671291a2b48SSukumar Swaminathan 		sbp = emlxs_fct_pkt_init(port, fct_cmd, pkt);
4672291a2b48SSukumar Swaminathan 
4673291a2b48SSukumar Swaminathan 		pkt->pkt_tran_type = FC_PKT_OUTBOUND;
4674291a2b48SSukumar Swaminathan 		pkt->pkt_timeout =
4675291a2b48SSukumar Swaminathan 		    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
4676291a2b48SSukumar Swaminathan 		pkt->pkt_comp = emlxs_fct_abort_pkt_comp;
4677291a2b48SSukumar Swaminathan 
4678291a2b48SSukumar Swaminathan 		/* Build the fc header */
467982527734SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(fct_cmd->cmd_rportid);
4680291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
468182527734SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
4682291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.type = FC_TYPE_BASIC_LS;
4683291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.f_ctl =
4684291a2b48SSukumar Swaminathan 		    (F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ);
4685291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.seq_id = 0;
4686291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.df_ctl = 0;
4687291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
4688291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
4689291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
4690291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.ro = 0;
4691291a2b48SSukumar Swaminathan 
46928f23e9faSHans Rosenfeld 		/* Make sure xrip is setup */
46938f23e9faSHans Rosenfeld 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
46948f23e9faSHans Rosenfeld 			if (!sbp->xrip || sbp->xrip->state == XRI_STATE_FREE) {
46958f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
46968f23e9faSHans Rosenfeld 				    "fct_abort: "
46978f23e9faSHans Rosenfeld 				    "Unable to acquire xri. (xid:%x,%x)",
46988f23e9faSHans Rosenfeld 				    fct_cmd->cmd_oxid, fct_cmd->cmd_rxid);
46998f23e9faSHans Rosenfeld 
47008f23e9faSHans Rosenfeld 				emlxs_pkt_free(pkt);
47018f23e9faSHans Rosenfeld 				return (FCT_NOT_FOUND);
47028f23e9faSHans Rosenfeld 			}
47038f23e9faSHans Rosenfeld 		}
47048f23e9faSHans Rosenfeld 
4705291a2b48SSukumar Swaminathan 		cmd_sbp->fct_cmd = fct_cmd;
4706291a2b48SSukumar Swaminathan 		cmd_sbp->abort_attempts++;
4707fcf3ce44SJohn Forte 
4708291a2b48SSukumar Swaminathan 		/* Now disassociate the sbp / pkt from the fct_cmd */
4709291a2b48SSukumar Swaminathan 		sbp->fct_cmd = NULL;
4710fcf3ce44SJohn Forte 
471182527734SSukumar Swaminathan 		if (hba->state >= FC_LINK_UP) {
4712291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
47138f23e9faSHans Rosenfeld 			    "fct_abort: ABORT: %p xid:%x,%x",
47148f23e9faSHans Rosenfeld 			    fct_cmd, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid);
4715fcf3ce44SJohn Forte 
471682527734SSukumar Swaminathan 			fct_state = EMLXS_FCT_ABORT_PENDING;
471782527734SSukumar Swaminathan 
471882527734SSukumar Swaminathan 		} else {
4719291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
47208f23e9faSHans Rosenfeld 			    "fct_abort: CLOSE: %p xid:%x,%x",
47218f23e9faSHans Rosenfeld 			    fct_cmd, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid);
4722fcf3ce44SJohn Forte 
472382527734SSukumar Swaminathan 			fct_state = EMLXS_FCT_CLOSE_PENDING;
4724291a2b48SSukumar Swaminathan 		}
4725fcf3ce44SJohn Forte 
472682527734SSukumar Swaminathan 		emlxs_fct_cmd_release(port, fct_cmd, fct_state);
472782527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
472882527734SSukumar Swaminathan 
4729291a2b48SSukumar Swaminathan 		if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
4730291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
47318f23e9faSHans Rosenfeld 			    "fct_abort: Unable to send abort packet.");
4732fcf3ce44SJohn Forte 
4733291a2b48SSukumar Swaminathan 			emlxs_pkt_free(pkt);
4734fcf3ce44SJohn Forte 
473582527734SSukumar Swaminathan 			/* The cmd will be aborted on the */
473682527734SSukumar Swaminathan 			/* next emlxs_fct_cmd_acquire anyway */
473782527734SSukumar Swaminathan 			/* because EMLXS_FCT_ABORT_INP is set. */
4738291a2b48SSukumar Swaminathan 		}
473982527734SSukumar Swaminathan 
4740291a2b48SSukumar Swaminathan 		break;
4741fcf3ce44SJohn Forte 
4742291a2b48SSukumar Swaminathan 	default:
474382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
47448f23e9faSHans Rosenfeld 		    "fct_abort: Unexpected fct_state. "
47458f23e9faSHans Rosenfeld 		    "fct_cmd=%p state=%d",
474682527734SSukumar Swaminathan 		    fct_cmd, cmd_sbp->fct_state);
474782527734SSukumar Swaminathan 
474882527734SSukumar Swaminathan 		emlxs_fct_cmd_release(port, fct_cmd, 0);
474982527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
475082527734SSukumar Swaminathan 
475182527734SSukumar Swaminathan 		/* The cmd will be aborted on the */
475282527734SSukumar Swaminathan 		/* next emlxs_fct_cmd_acquire anyway */
475382527734SSukumar Swaminathan 		/* because EMLXS_FCT_ABORT_INP is set. */
4754fcf3ce44SJohn Forte 
4755291a2b48SSukumar Swaminathan 	}	/* switch */
4756fcf3ce44SJohn Forte 
475782527734SSukumar Swaminathan 	return (FCT_SUCCESS);
4758fcf3ce44SJohn Forte 
4759fe199829SSukumar Swaminathan abort_done:
476082527734SSukumar Swaminathan 
476182527734SSukumar Swaminathan 	emlxs_fct_cmd_done(port, fct_cmd,
476282527734SSukumar Swaminathan 	    EMLXS_FCT_ABORT_DONE);
476382527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
476482527734SSukumar Swaminathan 
476582527734SSukumar Swaminathan 	return (FCT_ABORT_SUCCESS);
476682527734SSukumar Swaminathan 
476782527734SSukumar Swaminathan } /* emlxs_fct_abort() */
4768fcf3ce44SJohn Forte 
4769fcf3ce44SJohn Forte 
4770fcf3ce44SJohn Forte extern void
emlxs_fct_link_up(emlxs_port_t * port)4771fcf3ce44SJohn Forte emlxs_fct_link_up(emlxs_port_t *port)
4772fcf3ce44SJohn Forte {
4773fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4774fcf3ce44SJohn Forte 
4775fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
47768f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
47778f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
47788f23e9faSHans Rosenfeld 	    "fct_link_up port %p fct flags x%x",
47798f23e9faSHans Rosenfeld 	    port->fct_port, port->fct_flags);
47808f23e9faSHans Rosenfeld #endif /* FCT_API_TRACE */
4781fcf3ce44SJohn Forte 
4782fcf3ce44SJohn Forte 	if (port->fct_port &&
4783fcf3ce44SJohn Forte 	    (port->fct_flags & FCT_STATE_PORT_ONLINE) &&
4784fcf3ce44SJohn Forte 	    !(port->fct_flags & FCT_STATE_LINK_UP)) {
4785fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
47868f23e9faSHans Rosenfeld 		    "fct_link_up event.");
4787fcf3ce44SJohn Forte 
4788e2ca2865SSukumar Swaminathan 		port->fct_flags &= ~FCT_STATE_LINK_UP_ACKED;
47898f23e9faSHans Rosenfeld 		port->fct_flags &= ~FCT_STATE_FLOGI_CMPL;
4790fcf3ce44SJohn Forte 		port->fct_flags |= FCT_STATE_LINK_UP;
4791fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
4792fcf3ce44SJohn Forte 
4793fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4794fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4795fcf3ce44SJohn Forte 		    "fct_handle_event LINK_UP");
4796291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
4797291a2b48SSukumar Swaminathan 		MODSYM(fct_handle_event) (port->fct_port, FCT_EVENT_LINK_UP,
4798291a2b48SSukumar Swaminathan 		    0, 0);
47998f23e9faSHans Rosenfeld 	} else if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
48008f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PORT_LOCK);
48018f23e9faSHans Rosenfeld 
48028f23e9faSHans Rosenfeld 		if (port->vpi == 0) {
48038f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
48048f23e9faSHans Rosenfeld 			    "fct_link_up event. FCT port offline (%x). "
48058f23e9faSHans Rosenfeld 			    "Disable link.",
48068f23e9faSHans Rosenfeld 			    port->fct_flags);
4807fcf3ce44SJohn Forte 
4808fcf3ce44SJohn Forte 			/* Take link down and hold it down */
480982527734SSukumar Swaminathan 			(void) emlxs_reset_link(hba, 0, 1);
4810fcf3ce44SJohn Forte 		} else {
48118f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
48128f23e9faSHans Rosenfeld 			    "fct_link_up event. FCT port offline (%x).",
48138f23e9faSHans Rosenfeld 			    port->fct_flags);
4814fcf3ce44SJohn Forte 		}
48158f23e9faSHans Rosenfeld 	} else {
48168f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PORT_LOCK);
4817fcf3ce44SJohn Forte 	}
4818fcf3ce44SJohn Forte 
4819fcf3ce44SJohn Forte 	return;
4820fcf3ce44SJohn Forte 
482182527734SSukumar Swaminathan } /* emlxs_fct_link_up() */
4822291a2b48SSukumar Swaminathan 
4823fcf3ce44SJohn Forte 
4824fcf3ce44SJohn Forte extern void
emlxs_fct_link_down(emlxs_port_t * port)4825fcf3ce44SJohn Forte emlxs_fct_link_down(emlxs_port_t *port)
4826fcf3ce44SJohn Forte {
4827fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4828fcf3ce44SJohn Forte 
4829fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
48308f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
48318f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
48328f23e9faSHans Rosenfeld 	    "fct_link_down port %p fct flags x%x",
48338f23e9faSHans Rosenfeld 	    port->fct_port, port->fct_flags);
48348f23e9faSHans Rosenfeld #endif /* FCT_API_TRACE */
4835fcf3ce44SJohn Forte 
4836fcf3ce44SJohn Forte 	if (port->fct_port &&
4837fcf3ce44SJohn Forte 	    (port->fct_flags & FCT_STATE_PORT_ONLINE) &&
4838fcf3ce44SJohn Forte 	    (port->fct_flags & FCT_STATE_LINK_UP)) {
4839fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
48408f23e9faSHans Rosenfeld 		    "fct_link_down event.");
4841fcf3ce44SJohn Forte 
4842e2ca2865SSukumar Swaminathan 		port->fct_flags &= ~FCT_STATE_LINK_UP_ACKED;
48438f23e9faSHans Rosenfeld 		port->fct_flags &= ~FCT_STATE_FLOGI_CMPL;
4844fcf3ce44SJohn Forte 		port->fct_flags &= ~FCT_STATE_LINK_UP;
4845fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
4846fcf3ce44SJohn Forte 
4847fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4848fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4849fcf3ce44SJohn Forte 		    "fct_handle_event LINK_DOWN");
4850291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
485182527734SSukumar Swaminathan 
4852291a2b48SSukumar Swaminathan 		MODSYM(fct_handle_event) (port->fct_port, FCT_EVENT_LINK_DOWN,
4853291a2b48SSukumar Swaminathan 		    0, 0);
4854fcf3ce44SJohn Forte 	} else {
4855fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
4856fcf3ce44SJohn Forte 	}
4857fcf3ce44SJohn Forte 
4858fcf3ce44SJohn Forte 	return;
4859fcf3ce44SJohn Forte 
486082527734SSukumar Swaminathan } /* emlxs_fct_link_down() */
4861fcf3ce44SJohn Forte 
4862fcf3ce44SJohn Forte 
48638f23e9faSHans Rosenfeld void
emlxs_abort_fct_exchange(emlxs_hba_t * hba,emlxs_port_t * port,uint32_t rxid)48648f23e9faSHans Rosenfeld emlxs_abort_fct_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid)
4865fcf3ce44SJohn Forte {
48668f23e9faSHans Rosenfeld 	CHANNEL *cp;
48678f23e9faSHans Rosenfeld 	IOCBQ *iocbq;
48688f23e9faSHans Rosenfeld 	IOCB *iocb;
48698f23e9faSHans Rosenfeld 
48708f23e9faSHans Rosenfeld 	if (rxid == 0 || rxid == 0xFFFF) {
48718f23e9faSHans Rosenfeld 		return;
48728f23e9faSHans Rosenfeld 	}
48738f23e9faSHans Rosenfeld 
48748f23e9faSHans Rosenfeld 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
48758f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
48768f23e9faSHans Rosenfeld 		    "Aborting FCT exchange: xid=%x", rxid);
48778f23e9faSHans Rosenfeld 
48788f23e9faSHans Rosenfeld 		if (emlxs_sli4_unreserve_xri(port, rxid, 1) == 0) {
48798f23e9faSHans Rosenfeld 			/* We have no way to abort unsolicited exchanges */
48808f23e9faSHans Rosenfeld 			/* that we have not responded to at this time */
48818f23e9faSHans Rosenfeld 			/* So we will return for now */
48828f23e9faSHans Rosenfeld 			return;
4883fcf3ce44SJohn Forte 		}
48848f23e9faSHans Rosenfeld 	}
4885291a2b48SSukumar Swaminathan 
48868f23e9faSHans Rosenfeld 	cp = &hba->chan[hba->channel_fcp];
4887fcf3ce44SJohn Forte 
48888f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_FCTAB_LOCK);
48898f23e9faSHans Rosenfeld 
48908f23e9faSHans Rosenfeld 	/* Create the abort IOCB */
48918f23e9faSHans Rosenfeld 	if (hba->state >= FC_LINK_UP) {
48928f23e9faSHans Rosenfeld 		iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp,
48938f23e9faSHans Rosenfeld 		    CLASS3, ABORT_TYPE_ABTS);
48948f23e9faSHans Rosenfeld 	} else {
48958f23e9faSHans Rosenfeld 		iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp);
48968f23e9faSHans Rosenfeld 	}
48978f23e9faSHans Rosenfeld 
48988f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_FCTAB_LOCK);
48998f23e9faSHans Rosenfeld 
49008f23e9faSHans Rosenfeld 	if (iocbq) {
49018f23e9faSHans Rosenfeld 		iocb = &iocbq->iocb;
49028f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
49038f23e9faSHans Rosenfeld 		    "Aborting FCT exchange: xid=%x iotag=%d", rxid,
49048f23e9faSHans Rosenfeld 		    iocb->ULPIOTAG);
49058f23e9faSHans Rosenfeld 
49068f23e9faSHans Rosenfeld 		EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
49078f23e9faSHans Rosenfeld 	}
49088f23e9faSHans Rosenfeld 
49098f23e9faSHans Rosenfeld } /* emlxs_abort_fct_exchange() */
49108f23e9faSHans Rosenfeld 
49118f23e9faSHans Rosenfeld 
49128f23e9faSHans Rosenfeld extern uint32_t
emlxs_fct_stmf_alloc(emlxs_hba_t * hba,MATCHMAP * mp)49138f23e9faSHans Rosenfeld emlxs_fct_stmf_alloc(emlxs_hba_t *hba, MATCHMAP *mp)
49148f23e9faSHans Rosenfeld {
49158f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
49168f23e9faSHans Rosenfeld 	stmf_data_buf_t *db;
49178f23e9faSHans Rosenfeld 
49188f23e9faSHans Rosenfeld 	if (mp->tag < MEM_FCTSEG) {
49198f23e9faSHans Rosenfeld 		return (0);
49208f23e9faSHans Rosenfeld 	}
49218f23e9faSHans Rosenfeld 
49228f23e9faSHans Rosenfeld 	db = MODSYM(stmf_alloc) (STMF_STRUCT_DATA_BUF, 0, 0);
49238f23e9faSHans Rosenfeld 
49248f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
49258f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
49268f23e9faSHans Rosenfeld 	    "stmf_alloc:%p iotag=%d phys %p virt %p sz %d",
49278f23e9faSHans Rosenfeld 	    db, mp->tag, mp->phys, mp->virt, mp->size);
49288f23e9faSHans Rosenfeld #endif /* FCT_API_TRACE */
49298f23e9faSHans Rosenfeld 
49308f23e9faSHans Rosenfeld 	if (db == NULL) {
49318f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
49328f23e9faSHans Rosenfeld 		    "emlxs_fct_stmf_alloc: alloc failed.");
49338f23e9faSHans Rosenfeld 		return (1);
49348f23e9faSHans Rosenfeld 	}
49358f23e9faSHans Rosenfeld 
49368f23e9faSHans Rosenfeld 	db->db_port_private = (void*)mp;
49378f23e9faSHans Rosenfeld 	db->db_sglist[0].seg_addr = mp->virt;
49388f23e9faSHans Rosenfeld 	db->db_sglist[0].seg_length = mp->size;
49398f23e9faSHans Rosenfeld 	db->db_buf_size = mp->size;
49408f23e9faSHans Rosenfeld 	db->db_sglist_length = 1;
49418f23e9faSHans Rosenfeld 
49428f23e9faSHans Rosenfeld 	mp->fct_private = (void*)db;
49438f23e9faSHans Rosenfeld 
49448f23e9faSHans Rosenfeld 	return (0);
49458f23e9faSHans Rosenfeld 
49468f23e9faSHans Rosenfeld } /* emlxs_fct_stmf_alloc() */
49478f23e9faSHans Rosenfeld 
49488f23e9faSHans Rosenfeld 
49498f23e9faSHans Rosenfeld /* ARGSUSED */
49508f23e9faSHans Rosenfeld extern void
emlxs_fct_stmf_free(emlxs_hba_t * hba,MATCHMAP * mp)49518f23e9faSHans Rosenfeld emlxs_fct_stmf_free(emlxs_hba_t *hba, MATCHMAP *mp)
49528f23e9faSHans Rosenfeld {
49538f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
49548f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
49558f23e9faSHans Rosenfeld #endif /* FCT_API_TRACE */
49568f23e9faSHans Rosenfeld 	stmf_data_buf_t *db;
49578f23e9faSHans Rosenfeld 
49588f23e9faSHans Rosenfeld 	if (mp->tag < MEM_FCTSEG) {
49598f23e9faSHans Rosenfeld 		return;
49608f23e9faSHans Rosenfeld 	}
49618f23e9faSHans Rosenfeld 
49628f23e9faSHans Rosenfeld 	db = (stmf_data_buf_t *)mp->fct_private;
49638f23e9faSHans Rosenfeld 	mp->fct_private = NULL;
49648f23e9faSHans Rosenfeld 
49658f23e9faSHans Rosenfeld 	if (db == NULL) {
49668f23e9faSHans Rosenfeld 		return;
49678f23e9faSHans Rosenfeld 	}
49688f23e9faSHans Rosenfeld 
49698f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
49708f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
49718f23e9faSHans Rosenfeld 	    "stmf_free:%p iotag=%d",
49728f23e9faSHans Rosenfeld 	    db, mp->tag);
49738f23e9faSHans Rosenfeld #endif /* FCT_API_TRACE */
49748f23e9faSHans Rosenfeld 
49758f23e9faSHans Rosenfeld 	MODSYM(stmf_free) (db);
49768f23e9faSHans Rosenfeld 
49778f23e9faSHans Rosenfeld 	return;
49788f23e9faSHans Rosenfeld 
49798f23e9faSHans Rosenfeld } /* emlxs_fct_stmf_free() */
49808f23e9faSHans Rosenfeld 
49818f23e9faSHans Rosenfeld 
49828f23e9faSHans Rosenfeld static void
emlxs_fct_memseg_init(emlxs_hba_t * hba)49838f23e9faSHans Rosenfeld emlxs_fct_memseg_init(emlxs_hba_t *hba)
49848f23e9faSHans Rosenfeld {
49858f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
49868f23e9faSHans Rosenfeld 	char **arrayp = NULL;
49878f23e9faSHans Rosenfeld 	uint32_t cnt = 0;
49888f23e9faSHans Rosenfeld 	char buf[32];
49898f23e9faSHans Rosenfeld 	uint32_t rval;
49908f23e9faSHans Rosenfeld 	uint8_t *datap;
49918f23e9faSHans Rosenfeld 	int i;
49928f23e9faSHans Rosenfeld 	int j;
49938f23e9faSHans Rosenfeld 	int fct_memseg_cnt = 0;
49948f23e9faSHans Rosenfeld 	int numblks;
49958f23e9faSHans Rosenfeld 	int memsize;
49968f23e9faSHans Rosenfeld 	emlxs_memseg_t *fct_memseg = NULL;
49978f23e9faSHans Rosenfeld 	uint32_t fct_memseg_size = 0;
49988f23e9faSHans Rosenfeld 	emlxs_memseg_t *current;
49998f23e9faSHans Rosenfeld 	emlxs_memseg_t *next;
50008f23e9faSHans Rosenfeld 	emlxs_memseg_t *seg;
50018f23e9faSHans Rosenfeld 
50028f23e9faSHans Rosenfeld 	port->fct_memseg = NULL;
50038f23e9faSHans Rosenfeld 	port->fct_memseg_cnt = 0;
50048f23e9faSHans Rosenfeld 
50058f23e9faSHans Rosenfeld 	/* Check for the per adapter setting */
50068f23e9faSHans Rosenfeld 	(void) snprintf(buf, sizeof (buf), "%s%d-fct-bufpool", DRIVER_NAME,
50078f23e9faSHans Rosenfeld 	    hba->ddiinst);
50088f23e9faSHans Rosenfeld 	rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
50098f23e9faSHans Rosenfeld 	    (DDI_PROP_DONTPASS), buf, &arrayp, &cnt);
50108f23e9faSHans Rosenfeld 
50118f23e9faSHans Rosenfeld 	if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
50128f23e9faSHans Rosenfeld 		/* Check for the global setting */
50138f23e9faSHans Rosenfeld 		cnt = 0;
50148f23e9faSHans Rosenfeld 		arrayp = NULL;
50158f23e9faSHans Rosenfeld 		rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
50168f23e9faSHans Rosenfeld 		    (DDI_PROP_DONTPASS), "fct-bufpool", &arrayp, &cnt);
50178f23e9faSHans Rosenfeld 	}
50188f23e9faSHans Rosenfeld 
50198f23e9faSHans Rosenfeld 	if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
50208f23e9faSHans Rosenfeld 		goto default_config;
50218f23e9faSHans Rosenfeld 	}
50228f23e9faSHans Rosenfeld 
50238f23e9faSHans Rosenfeld 	fct_memseg_size = cnt * sizeof (emlxs_memseg_t);
50248f23e9faSHans Rosenfeld 	fct_memseg = kmem_zalloc(fct_memseg_size, KM_SLEEP);
50258f23e9faSHans Rosenfeld 
50268f23e9faSHans Rosenfeld 	if (!fct_memseg) {
50278f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
50288f23e9faSHans Rosenfeld 		    "Unable to alloc fct_memseg. cnt=%d. "
50298f23e9faSHans Rosenfeld 		    "Trying default config.",
50308f23e9faSHans Rosenfeld 		    cnt);
50318f23e9faSHans Rosenfeld 		goto default_config;
50328f23e9faSHans Rosenfeld 	}
50338f23e9faSHans Rosenfeld 
50348f23e9faSHans Rosenfeld 	for (i = 0; i < cnt; i++) {
50358f23e9faSHans Rosenfeld 		datap = (uint8_t *)arrayp[i];
50368f23e9faSHans Rosenfeld 		if (datap == 0) {
50378f23e9faSHans Rosenfeld 			break;
5038fcf3ce44SJohn Forte 		}
5039291a2b48SSukumar Swaminathan 
50408f23e9faSHans Rosenfeld 		while (*datap == ' ') {	/* Skip spaces */
50418f23e9faSHans Rosenfeld 			datap++;
50428f23e9faSHans Rosenfeld 		}
5043fcf3ce44SJohn Forte 
50448f23e9faSHans Rosenfeld 		memsize = emlxs_str_atoi(datap);
50458f23e9faSHans Rosenfeld 
50468f23e9faSHans Rosenfeld 		while ((*datap != ':') && (*datap != 0)) {
50478f23e9faSHans Rosenfeld 			datap++;
50488f23e9faSHans Rosenfeld 		}
50498f23e9faSHans Rosenfeld 		if (*datap == ':') { /* Skip past delimeter */
50508f23e9faSHans Rosenfeld 			datap++;
50518f23e9faSHans Rosenfeld 		}
50528f23e9faSHans Rosenfeld 		while (*datap == ' ') { /* Skip spaces */
50538f23e9faSHans Rosenfeld 			datap++;
5054fcf3ce44SJohn Forte 		}
5055fcf3ce44SJohn Forte 
50568f23e9faSHans Rosenfeld 		numblks = emlxs_str_atoi(datap);
5057fcf3ce44SJohn Forte 
50588f23e9faSHans Rosenfeld 		/* Check for a bad entry */
50598f23e9faSHans Rosenfeld 		if (!memsize || !numblks) {
5060fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
50618f23e9faSHans Rosenfeld 			    "fct-bufpool: Entry %d:%d. Invalid.",
50628f23e9faSHans Rosenfeld 			    memsize, numblks);
50638f23e9faSHans Rosenfeld 			continue;
5064fcf3ce44SJohn Forte 		}
5065fcf3ce44SJohn Forte 
50668f23e9faSHans Rosenfeld 		fct_memseg[fct_memseg_cnt].fc_memsize = memsize;
50678f23e9faSHans Rosenfeld 		fct_memseg[fct_memseg_cnt].fc_numblks = numblks;
50688f23e9faSHans Rosenfeld 		fct_memseg_cnt++;
50698f23e9faSHans Rosenfeld 
50708f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
50718f23e9faSHans Rosenfeld 		    "fct-bufpool: Entry:%d  %d:%d",
50728f23e9faSHans Rosenfeld 		    fct_memseg_cnt, memsize, numblks);
50738f23e9faSHans Rosenfeld 	}
50748f23e9faSHans Rosenfeld 
50758f23e9faSHans Rosenfeld 	if (!fct_memseg_cnt) {
50768f23e9faSHans Rosenfeld 		kmem_free(fct_memseg, fct_memseg_size);
50778f23e9faSHans Rosenfeld 		fct_memseg_size = 0;
50788f23e9faSHans Rosenfeld 		fct_memseg = NULL;
50798f23e9faSHans Rosenfeld 	}
50808f23e9faSHans Rosenfeld 
50818f23e9faSHans Rosenfeld default_config:
50828f23e9faSHans Rosenfeld 	/* If buffer list is empty, setup defaults */
50838f23e9faSHans Rosenfeld 	if (!fct_memseg) {
50848f23e9faSHans Rosenfeld 
50858f23e9faSHans Rosenfeld 		fct_memseg_size = 8 * sizeof (emlxs_memseg_t);
50868f23e9faSHans Rosenfeld 		fct_memseg = kmem_zalloc(fct_memseg_size, KM_SLEEP);
50878f23e9faSHans Rosenfeld 
50888f23e9faSHans Rosenfeld 		if (!fct_memseg) {
5089fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
50908f23e9faSHans Rosenfeld 			    "Unable to alloc default port buffer pool. "
50918f23e9faSHans Rosenfeld 			    "fct_memseg_cnt=%d",
50928f23e9faSHans Rosenfeld 			    cnt);
50938f23e9faSHans Rosenfeld 			return;
5094fcf3ce44SJohn Forte 		}
5095fcf3ce44SJohn Forte 
50968f23e9faSHans Rosenfeld 		i = 0;
50978f23e9faSHans Rosenfeld 		numblks = FCT_BUF_COUNT_2K;
50988f23e9faSHans Rosenfeld 		if (numblks) {
50998f23e9faSHans Rosenfeld 			fct_memseg[i].fc_memsize = 2 * 1024;
51008f23e9faSHans Rosenfeld 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_2K;
51018f23e9faSHans Rosenfeld 		}
51028f23e9faSHans Rosenfeld 		numblks = FCT_BUF_COUNT_4K;
51038f23e9faSHans Rosenfeld 		if (numblks) {
51048f23e9faSHans Rosenfeld 			fct_memseg[i].fc_memsize = 4 * 1024;
51058f23e9faSHans Rosenfeld 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_4K;
51068f23e9faSHans Rosenfeld 		}
51078f23e9faSHans Rosenfeld 		numblks = FCT_BUF_COUNT_8K;
51088f23e9faSHans Rosenfeld 		if (numblks) {
51098f23e9faSHans Rosenfeld 			fct_memseg[i].fc_memsize = 8 * 1024;
51108f23e9faSHans Rosenfeld 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_8K;
51118f23e9faSHans Rosenfeld 		}
51128f23e9faSHans Rosenfeld 		numblks = FCT_BUF_COUNT_16K;
51138f23e9faSHans Rosenfeld 		if (numblks) {
51148f23e9faSHans Rosenfeld 			fct_memseg[i].fc_memsize = 16 * 1024;
51158f23e9faSHans Rosenfeld 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_16K;
51168f23e9faSHans Rosenfeld 		}
51178f23e9faSHans Rosenfeld 		numblks = FCT_BUF_COUNT_32K;
51188f23e9faSHans Rosenfeld 		if (numblks) {
51198f23e9faSHans Rosenfeld 			fct_memseg[i].fc_memsize = 32 * 1024;
51208f23e9faSHans Rosenfeld 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_32K;
5121fcf3ce44SJohn Forte 		}
51228f23e9faSHans Rosenfeld 		numblks = FCT_BUF_COUNT_64K;
51238f23e9faSHans Rosenfeld 		if (numblks) {
51248f23e9faSHans Rosenfeld 			fct_memseg[i].fc_memsize = 64 * 1024;
51258f23e9faSHans Rosenfeld 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_64K;
51268f23e9faSHans Rosenfeld 		}
51278f23e9faSHans Rosenfeld 		numblks = FCT_BUF_COUNT_128K;
51288f23e9faSHans Rosenfeld 		if (numblks) {
51298f23e9faSHans Rosenfeld 			fct_memseg[i].fc_memsize = 128 * 1024;
51308f23e9faSHans Rosenfeld 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_128K;
51318f23e9faSHans Rosenfeld 		}
51328f23e9faSHans Rosenfeld 		numblks = FCT_BUF_COUNT_256K;
51338f23e9faSHans Rosenfeld 		if (numblks) {
51348f23e9faSHans Rosenfeld 			fct_memseg[i].fc_memsize = 256 * 1024;
51358f23e9faSHans Rosenfeld 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_256K;
51368f23e9faSHans Rosenfeld 		}
51378f23e9faSHans Rosenfeld 		fct_memseg_cnt = i;
51388f23e9faSHans Rosenfeld 	}
51398f23e9faSHans Rosenfeld 
51408f23e9faSHans Rosenfeld 	port->fct_memseg = kmem_zalloc((fct_memseg_cnt *
51418f23e9faSHans Rosenfeld 	    sizeof (emlxs_memseg_t)), KM_SLEEP);
5142fcf3ce44SJohn Forte 
51438f23e9faSHans Rosenfeld 	if (!port->fct_memseg) {
5144fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
51458f23e9faSHans Rosenfeld 		    "Unable to alloc port buffer pool. fct_memseg_cnt=%d",
51468f23e9faSHans Rosenfeld 		    fct_memseg_cnt);
51478f23e9faSHans Rosenfeld 		kmem_free(fct_memseg, fct_memseg_size);
51488f23e9faSHans Rosenfeld 		return;
51498f23e9faSHans Rosenfeld 	}
5150fcf3ce44SJohn Forte 
51518f23e9faSHans Rosenfeld 	/* Initalize port bucket list */
51528f23e9faSHans Rosenfeld 	port->fct_memseg_cnt = fct_memseg_cnt;
5153fcf3ce44SJohn Forte 
51548f23e9faSHans Rosenfeld 	/* Sort the entries smallest to largest */
51558f23e9faSHans Rosenfeld 	seg = port->fct_memseg;
51568f23e9faSHans Rosenfeld 	for (i = 0; i < fct_memseg_cnt; i++, seg++) {
5157fcf3ce44SJohn Forte 
51588f23e9faSHans Rosenfeld 		/* Find next smallest buffer */
51598f23e9faSHans Rosenfeld 		current = fct_memseg;
51608f23e9faSHans Rosenfeld 		next = NULL;
51618f23e9faSHans Rosenfeld 		for (j = 0; j < fct_memseg_cnt; j++, current++) {
51628f23e9faSHans Rosenfeld 			if (current->fc_memsize == 0) {
51638f23e9faSHans Rosenfeld 				continue;
51648f23e9faSHans Rosenfeld 			}
5165fcf3ce44SJohn Forte 
51668f23e9faSHans Rosenfeld 			if (next == NULL) {
51678f23e9faSHans Rosenfeld 				next = current;
51688f23e9faSHans Rosenfeld 				continue;
51698f23e9faSHans Rosenfeld 			}
51708f23e9faSHans Rosenfeld 
51718f23e9faSHans Rosenfeld 			if (current->fc_memsize < next->fc_memsize) {
51728f23e9faSHans Rosenfeld 				next = current;
5173fcf3ce44SJohn Forte 			}
5174fcf3ce44SJohn Forte 		}
5175fcf3ce44SJohn Forte 
51768f23e9faSHans Rosenfeld 		/* Save next entry */
51778f23e9faSHans Rosenfeld 		seg->fc_memsize = next->fc_memsize;
51788f23e9faSHans Rosenfeld 		seg->fc_numblks = next->fc_numblks;
51798f23e9faSHans Rosenfeld 		next->fc_memsize = 0;
51808f23e9faSHans Rosenfeld 		next->fc_numblks = 0;
5181fcf3ce44SJohn Forte 	}
5182fcf3ce44SJohn Forte 
51838f23e9faSHans Rosenfeld 	kmem_free(fct_memseg, fct_memseg_size);
5184fcf3ce44SJohn Forte 
51858f23e9faSHans Rosenfeld 	/* Complete the initialization */
51868f23e9faSHans Rosenfeld 	seg = port->fct_memseg;
51878f23e9faSHans Rosenfeld 	for (i = 0; i < port->fct_memseg_cnt; i++, seg++) {
51888f23e9faSHans Rosenfeld /*		seg->fc_memsize = ; Already setup */
51898f23e9faSHans Rosenfeld /*		seg->fc_numblks = ; Already setup */
5190fcf3ce44SJohn Forte 
51918f23e9faSHans Rosenfeld 		(void) snprintf(seg->fc_label, sizeof (seg->fc_label),
51928f23e9faSHans Rosenfeld 		    "FCT_DMEM_%d", seg->fc_memsize);
5193fcf3ce44SJohn Forte 
51948f23e9faSHans Rosenfeld 		seg->fc_memtag   = MEM_FCTSEG + i;
51958f23e9faSHans Rosenfeld 		seg->fc_memflag  = FC_MBUF_DMA | FC_MBUF_SNGLSG;
51968f23e9faSHans Rosenfeld 		seg->fc_memalign = 32;
51978f23e9faSHans Rosenfeld 		seg->fc_hi_water = 0xFFFF;
51988f23e9faSHans Rosenfeld 		seg->fc_lo_water = seg->fc_numblks;
51998f23e9faSHans Rosenfeld 		seg->fc_numblks  = 0;
52008f23e9faSHans Rosenfeld 		seg->fc_step = 1;
52018f23e9faSHans Rosenfeld 	}
5202fcf3ce44SJohn Forte 
52038f23e9faSHans Rosenfeld 	return;
5204fcf3ce44SJohn Forte 
52058f23e9faSHans Rosenfeld } /* emlxs_fct_memseg_init() */
5206fcf3ce44SJohn Forte 
5207fcf3ce44SJohn Forte 
52088f23e9faSHans Rosenfeld fct_status_t
emlxs_fct_dmem_init(emlxs_port_t * port)52098f23e9faSHans Rosenfeld emlxs_fct_dmem_init(emlxs_port_t *port)
52108f23e9faSHans Rosenfeld {
52118f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
52128f23e9faSHans Rosenfeld 	emlxs_memseg_t *seg;
52138f23e9faSHans Rosenfeld 	int32_t i;
5214fcf3ce44SJohn Forte 
52158f23e9faSHans Rosenfeld 	/* Initialize the fct memseg list */
52168f23e9faSHans Rosenfeld 	emlxs_fct_memseg_init(hba);
5217fcf3ce44SJohn Forte 
52188f23e9faSHans Rosenfeld 	if (!port->fct_memseg || !port->fct_memseg_cnt) {
52198f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
52208f23e9faSHans Rosenfeld 		    "fct_dmem_init: fct_memseg list is empty.");
52218f23e9faSHans Rosenfeld 		return (FCT_FAILURE);
52228f23e9faSHans Rosenfeld 	}
5223fcf3ce44SJohn Forte 
52248f23e9faSHans Rosenfeld 	/* Create the DMA buffer pools */
52258f23e9faSHans Rosenfeld 	seg = port->fct_memseg;
52268f23e9faSHans Rosenfeld 	for (i = 0; i < port->fct_memseg_cnt; i++, seg++) {
5227fcf3ce44SJohn Forte 
52288f23e9faSHans Rosenfeld 		(void) emlxs_mem_pool_create(hba, seg);
52298f23e9faSHans Rosenfeld 
52308f23e9faSHans Rosenfeld 		if (seg->fc_numblks < seg->fc_lo_water) {
52318f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
52328f23e9faSHans Rosenfeld 			    "%s: count=%d size=%d flags=%x lo=%d hi=%d",
52338f23e9faSHans Rosenfeld 			    seg->fc_label, seg->fc_numblks,
52348f23e9faSHans Rosenfeld 			    seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
52358f23e9faSHans Rosenfeld 			    seg->fc_hi_water);
5236fcf3ce44SJohn Forte 		}
52378f23e9faSHans Rosenfeld 	}
5238291a2b48SSukumar Swaminathan 
52398f23e9faSHans Rosenfeld 	return (FCT_SUCCESS);
5240fcf3ce44SJohn Forte 
52418f23e9faSHans Rosenfeld } /* emlxs_fct_dmem_init */
5242fcf3ce44SJohn Forte 
5243fcf3ce44SJohn Forte 
52448f23e9faSHans Rosenfeld void
emlxs_fct_dmem_fini(emlxs_port_t * port)52458f23e9faSHans Rosenfeld emlxs_fct_dmem_fini(emlxs_port_t *port)
52468f23e9faSHans Rosenfeld {
52478f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
52488f23e9faSHans Rosenfeld 	emlxs_memseg_t *seg;
52498f23e9faSHans Rosenfeld 	int32_t i;
52508f23e9faSHans Rosenfeld 
52518f23e9faSHans Rosenfeld 	if (!port->fct_memseg || !port->fct_memseg_cnt) {
52528f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
52538f23e9faSHans Rosenfeld 		    "fct_dmem_fini: fct_memseg list is empty.");
52548f23e9faSHans Rosenfeld 		return;
52558f23e9faSHans Rosenfeld 	}
5256fcf3ce44SJohn Forte 
52578f23e9faSHans Rosenfeld 	/* Destroy the dmem buffer pools */
52588f23e9faSHans Rosenfeld 	seg = port->fct_memseg;
52598f23e9faSHans Rosenfeld 	for (i = 0; i < port->fct_memseg_cnt; i++, seg++) {
52608f23e9faSHans Rosenfeld 		(void) emlxs_mem_pool_destroy(hba, seg);
5261fcf3ce44SJohn Forte 	}
5262fcf3ce44SJohn Forte 
52638f23e9faSHans Rosenfeld 	/* Clear the segment space */
52648f23e9faSHans Rosenfeld 	kmem_free(port->fct_memseg,
52658f23e9faSHans Rosenfeld 	    (port->fct_memseg_cnt * sizeof (emlxs_memseg_t)));
52668f23e9faSHans Rosenfeld 
52678f23e9faSHans Rosenfeld 	port->fct_memseg = 0;
52688f23e9faSHans Rosenfeld 	port->fct_memseg_cnt = 0;
5269fcf3ce44SJohn Forte 
5270fcf3ce44SJohn Forte 	return;
5271fcf3ce44SJohn Forte 
52728f23e9faSHans Rosenfeld } /* emlxs_fct_dmem_fini */
5273fcf3ce44SJohn Forte 
5274fcf3ce44SJohn Forte 
527582527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
52768f23e9faSHans Rosenfeld /*ARGSUSED*/
5277fcf3ce44SJohn Forte static stmf_data_buf_t *
emlxs_fct_dbuf_alloc(fct_local_port_t * fct_port,uint32_t size,uint32_t * pminsize,uint32_t flags)5278fcf3ce44SJohn Forte emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port, uint32_t size,
5279fcf3ce44SJohn Forte     uint32_t *pminsize, uint32_t flags)
5280fcf3ce44SJohn Forte {
5281fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
52828f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
52838f23e9faSHans Rosenfeld 	emlxs_memseg_t *seg;
52848f23e9faSHans Rosenfeld 	stmf_data_buf_t *db;
52858f23e9faSHans Rosenfeld 	MATCHMAP *mp;
52868f23e9faSHans Rosenfeld 	int i;
52878f23e9faSHans Rosenfeld 	uint32_t minsize = 0;
52888f23e9faSHans Rosenfeld 
52898f23e9faSHans Rosenfeld 	if (!port->fct_memseg || !port->fct_memseg_cnt) {
52908f23e9faSHans Rosenfeld 		goto failed;
52918f23e9faSHans Rosenfeld 	}
5292fcf3ce44SJohn Forte 
52938f23e9faSHans Rosenfeld 	/* Check if our largest buffer is too small */
52948f23e9faSHans Rosenfeld 	seg = &port->fct_memseg[port->fct_memseg_cnt-1];
52958f23e9faSHans Rosenfeld 	if (size > seg->fc_memsize) {
52968f23e9faSHans Rosenfeld 		goto partial_alloc;
5297fcf3ce44SJohn Forte 	}
5298291a2b48SSukumar Swaminathan 
52998f23e9faSHans Rosenfeld 	/* Find smallest available buffer >= size */
53008f23e9faSHans Rosenfeld 	seg = port->fct_memseg;
53018f23e9faSHans Rosenfeld 	for (i = 0; i < port->fct_memseg_cnt; i++, seg++) {
53028f23e9faSHans Rosenfeld 		if (seg->fc_memsize < size) {
5303fcf3ce44SJohn Forte 			continue;
5304fcf3ce44SJohn Forte 		}
5305291a2b48SSukumar Swaminathan 
53068f23e9faSHans Rosenfeld 		mp = (MATCHMAP*)emlxs_mem_pool_get(hba, seg);
5307291a2b48SSukumar Swaminathan 
53088f23e9faSHans Rosenfeld 		if (mp) {
53098f23e9faSHans Rosenfeld 			goto success;
53108f23e9faSHans Rosenfeld 		}
53118f23e9faSHans Rosenfeld 	}
5312291a2b48SSukumar Swaminathan 
53138f23e9faSHans Rosenfeld 	seg = &port->fct_memseg[port->fct_memseg_cnt-1];
5314fcf3ce44SJohn Forte 
53158f23e9faSHans Rosenfeld partial_alloc:
53168f23e9faSHans Rosenfeld 	/* Find largest available buffer >= *pminsize */
53178f23e9faSHans Rosenfeld 	for (i = port->fct_memseg_cnt-1; i >= 0; i--, seg--) {
53188f23e9faSHans Rosenfeld 		if (seg->fc_memsize < *pminsize) {
53198f23e9faSHans Rosenfeld 			minsize = seg->fc_memsize;
53208f23e9faSHans Rosenfeld 			goto failed;
53218f23e9faSHans Rosenfeld 		}
5322fcf3ce44SJohn Forte 
53238f23e9faSHans Rosenfeld 		mp = (MATCHMAP*)emlxs_mem_pool_get(hba, seg);
5324fcf3ce44SJohn Forte 
53258f23e9faSHans Rosenfeld 		if (mp) {
53268f23e9faSHans Rosenfeld 			goto success;
5327fcf3ce44SJohn Forte 		}
5328fcf3ce44SJohn Forte 	}
5329fcf3ce44SJohn Forte 
53308f23e9faSHans Rosenfeld failed:
53318f23e9faSHans Rosenfeld 	*pminsize = minsize;
5332fcf3ce44SJohn Forte 	TGTPORTSTAT.FctNoBuffer++;
5333fcf3ce44SJohn Forte 
5334fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
53358f23e9faSHans Rosenfeld 	    "fct_dbuf_alloc:Failed. size=%d minsize=%d",
53368f23e9faSHans Rosenfeld 	    size, *pminsize);
5337fcf3ce44SJohn Forte 
5338fcf3ce44SJohn Forte 	return (NULL);
5339fcf3ce44SJohn Forte 
53408f23e9faSHans Rosenfeld success:
53418f23e9faSHans Rosenfeld 	/* Setup the data buffer */
53428f23e9faSHans Rosenfeld 	db = (stmf_data_buf_t *)mp->fct_private;
53438f23e9faSHans Rosenfeld 	db->db_data_size = min(size, mp->size);
53448f23e9faSHans Rosenfeld 
53458f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
53468f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
53478f23e9faSHans Rosenfeld 	    "fct_dbuf_alloc:%p iotag=%d size=%d,%d",
53488f23e9faSHans Rosenfeld 	    db, mp->tag, size,  mp->size);
53498f23e9faSHans Rosenfeld #endif /* FCT_API_TRACE */
53508f23e9faSHans Rosenfeld 
53518f23e9faSHans Rosenfeld 	return (db);
53528f23e9faSHans Rosenfeld 
535382527734SSukumar Swaminathan } /* emlxs_fct_dbuf_alloc() */
5354fcf3ce44SJohn Forte 
5355fcf3ce44SJohn Forte 
535682527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
5357291a2b48SSukumar Swaminathan /*ARGSUSED*/
5358fcf3ce44SJohn Forte static void
emlxs_fct_dbuf_free(fct_dbuf_store_t * fds,stmf_data_buf_t * db)53598f23e9faSHans Rosenfeld emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *db)
5360fcf3ce44SJohn Forte {
53618f23e9faSHans Rosenfeld 	emlxs_port_t *port = (emlxs_port_t *)fds->fds_fca_private;
53628f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
53638f23e9faSHans Rosenfeld 	MATCHMAP *mp = (MATCHMAP *)db->db_port_private;
53648f23e9faSHans Rosenfeld 
53658f23e9faSHans Rosenfeld 	if (!mp) {
53668f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
53678f23e9faSHans Rosenfeld 		    "fct_dbuf_free:%p  NULL mp found!",
53688f23e9faSHans Rosenfeld 		    db);
53698f23e9faSHans Rosenfeld 		return;
53708f23e9faSHans Rosenfeld 	}
5371fcf3ce44SJohn Forte 
53728f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
5373fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
53748f23e9faSHans Rosenfeld 	    "fct_dbuf_free:%p iotag=%d",
53758f23e9faSHans Rosenfeld 	    db, mp->tag);
5376291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
5377fcf3ce44SJohn Forte 
53788f23e9faSHans Rosenfeld 	emlxs_mem_pool_put(hba, mp->segment, (void *)mp);
5379fcf3ce44SJohn Forte 
538082527734SSukumar Swaminathan } /* emlxs_fct_dbuf_free() */
5381fcf3ce44SJohn Forte 
5382fcf3ce44SJohn Forte 
5383b3660a96SSukumar Swaminathan static int
emlxs_fct_dbuf_dma_sync(emlxs_hba_t * hba,stmf_data_buf_t * db,uint_t sync_type)53848f23e9faSHans Rosenfeld emlxs_fct_dbuf_dma_sync(emlxs_hba_t *hba, stmf_data_buf_t *db,
5385b3660a96SSukumar Swaminathan     uint_t sync_type)
5386fcf3ce44SJohn Forte {
5387b3660a96SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
53888f23e9faSHans Rosenfeld 	MATCHMAP *mp = (MATCHMAP *)db->db_port_private;
5389fcf3ce44SJohn Forte 
53908f23e9faSHans Rosenfeld 	if (!mp) {
53918f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
53928f23e9faSHans Rosenfeld 		    "fct_dbuf_dma_sync:%p  NULL mp found!",
53938f23e9faSHans Rosenfeld 		    db);
53948f23e9faSHans Rosenfeld 		return (0);
53958f23e9faSHans Rosenfeld 	}
53968f23e9faSHans Rosenfeld 
53978f23e9faSHans Rosenfeld #ifdef FCT_API_TRACE
53988f23e9faSHans Rosenfeld {
53998f23e9faSHans Rosenfeld 	char buf[16];
54008f23e9faSHans Rosenfeld 
54018f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
54028f23e9faSHans Rosenfeld 	    "fct_dbuf_dma_sync:%p iotag=%d size=%d",
54038f23e9faSHans Rosenfeld 	    db, mp->tag, db->db_data_size);
54048f23e9faSHans Rosenfeld 
54058f23e9faSHans Rosenfeld 	(void) snprintf(buf, sizeof (buf), "TAG%d:", mp->tag);
54068f23e9faSHans Rosenfeld 	emlxs_data_dump(port, buf, (uint32_t *)db->db_sglist[0].seg_addr,
54078f23e9faSHans Rosenfeld 	    36, 0);
54088f23e9faSHans Rosenfeld }
54098f23e9faSHans Rosenfeld #endif /* FCT_API_TRACE */
54108f23e9faSHans Rosenfeld 
54118f23e9faSHans Rosenfeld 	EMLXS_MPDATA_SYNC(mp->dma_handle, 0, db->db_data_size, sync_type);
5412fcf3ce44SJohn Forte 
5413b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
54148f23e9faSHans Rosenfeld 	if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
5415b3660a96SSukumar Swaminathan 	    != DDI_FM_OK) {
5416b3660a96SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
5417b3660a96SSukumar Swaminathan 		    &emlxs_invalid_dma_handle_msg,
54188f23e9faSHans Rosenfeld 		    "fct_dbuf_dma_sync:%p iotag=%d",
54198f23e9faSHans Rosenfeld 		    db, mp->tag);
54208f23e9faSHans Rosenfeld 		return (1);
5421b3660a96SSukumar Swaminathan 	}
5422b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
5423b3660a96SSukumar Swaminathan 
54248f23e9faSHans Rosenfeld 	return (0);
5425b3660a96SSukumar Swaminathan 
542682527734SSukumar Swaminathan } /* emlxs_fct_dbuf_dma_sync() */
5427fcf3ce44SJohn Forte 
5428291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
5429