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  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
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 /*
23291a2b48SSukumar Swaminathan  * Copyright 2009 Emulex.  All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
2782527734SSukumar Swaminathan 
28291a2b48SSukumar Swaminathan #include <emlxs.h>
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
31fcf3ce44SJohn Forte 
32fcf3ce44SJohn Forte 
33fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
34fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_FCT_C);
35fcf3ce44SJohn Forte 
3682527734SSukumar Swaminathan static fct_status_t emlxs_fct_cmd_acquire(emlxs_port_t *port,
3782527734SSukumar Swaminathan 	fct_cmd_t *fct_cmd, uint16_t fct_state);
3882527734SSukumar Swaminathan static fct_status_t emlxs_fct_cmd_accept(emlxs_port_t *port,
3982527734SSukumar Swaminathan 	fct_cmd_t *fct_cmd, uint16_t fct_state);
4082527734SSukumar Swaminathan static void emlxs_fct_cmd_release(emlxs_port_t *port, fct_cmd_t *fct_cmd,
4182527734SSukumar Swaminathan 	uint16_t fct_state);
42fcf3ce44SJohn Forte 
43fcf3ce44SJohn Forte static void emlxs_fct_handle_acc(emlxs_port_t *port, emlxs_buf_t *sbp,
44fcf3ce44SJohn Forte     IOCBQ *iocbq);
45fcf3ce44SJohn Forte static void emlxs_fct_handle_reject(emlxs_port_t *port, emlxs_buf_t *sbp,
46fcf3ce44SJohn Forte     IOCBQ *iocbq);
47291a2b48SSukumar Swaminathan static emlxs_buf_t *emlxs_fct_cmd_init(emlxs_port_t *port,
4882527734SSukumar Swaminathan     fct_cmd_t *fct_cmd, uint32_t fct_state);
4982527734SSukumar Swaminathan static void emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd,
5082527734SSukumar Swaminathan 	uint16_t fct_state);
5182527734SSukumar Swaminathan static void emlxs_fct_cmd_post(emlxs_port_t *port, fct_cmd_t *fct_cmd,
5282527734SSukumar Swaminathan 	uint16_t fct_state);
53fcf3ce44SJohn Forte 
5482527734SSukumar Swaminathan static fct_status_t emlxs_fct_flogi_xchg(struct fct_local_port *fct_port,
55fcf3ce44SJohn Forte     struct fct_flogi_xchg *fx);
56fcf3ce44SJohn Forte static fct_status_t emlxs_fct_get_link_info(fct_local_port_t *fct_port,
57fcf3ce44SJohn Forte     fct_link_info_t *link);
58fcf3ce44SJohn Forte static fct_status_t emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port,
59fcf3ce44SJohn Forte     fct_remote_port_t *port_handle);
60fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_cmd(fct_cmd_t *fct_cmd);
61fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd,
62fcf3ce44SJohn Forte     stmf_data_buf_t *dbuf, uint32_t ioflags);
63291a2b48SSukumar Swaminathan static fct_status_t emlxs_fct_send_cmd_rsp(fct_cmd_t *fct_cmd, uint32_t flags);
64291a2b48SSukumar Swaminathan static fct_status_t emlxs_fct_abort(fct_local_port_t *fct_port,
65291a2b48SSukumar Swaminathan     fct_cmd_t *cmd, uint32_t flags);
66fcf3ce44SJohn Forte static void emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg);
67fcf3ce44SJohn Forte static fct_status_t emlxs_fct_register_remote_port(fct_local_port_t *fct_port,
68fcf3ce44SJohn Forte     fct_remote_port_t *port_handle, fct_cmd_t *plogi);
69fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd);
70fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd);
71fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd);
72fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd);
73fcf3ce44SJohn Forte static void emlxs_fct_pkt_comp(fc_packet_t *pkt);
7482527734SSukumar Swaminathan static void emlxs_fct_populate_hba_details(fct_local_port_t *fct_port,
75fcf3ce44SJohn Forte     fct_port_attrs_t *port_attrs);
7682527734SSukumar Swaminathan static fct_status_t emlxs_fct_port_info(uint32_t cmd,
7782527734SSukumar Swaminathan     fct_local_port_t *fct_port, void *arg, uint8_t *buffer, uint32_t *size);
78fcf3ce44SJohn Forte 
79fcf3ce44SJohn Forte static fct_status_t emlxs_fct_dmem_init(emlxs_port_t *port);
80fcf3ce44SJohn Forte static void emlxs_fct_dmem_fini(emlxs_port_t *port);
81fcf3ce44SJohn Forte 
82fcf3ce44SJohn Forte static stmf_data_buf_t *emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port,
83fcf3ce44SJohn Forte     uint32_t size, uint32_t *pminsize, uint32_t flags);
84fcf3ce44SJohn Forte static void emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *dbuf);
85fcf3ce44SJohn Forte 
86*b3660a96SSukumar Swaminathan static int emlxs_fct_dbuf_dma_sync(emlxs_hba_t *hba, stmf_data_buf_t *dbuf,
87*b3660a96SSukumar Swaminathan     uint_t sync_type);
88291a2b48SSukumar Swaminathan static emlxs_buf_t *emlxs_fct_pkt_init(emlxs_port_t *port,
89291a2b48SSukumar Swaminathan     fct_cmd_t *fct_cmd, fc_packet_t *pkt);
90fcf3ce44SJohn Forte 
91fcf3ce44SJohn Forte static void emlxs_fct_unsol_flush(emlxs_port_t *port);
9282527734SSukumar Swaminathan static uint32_t emlxs_fct_process_unsol_flogi(emlxs_port_t *port,
9382527734SSukumar Swaminathan     CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
9482527734SSukumar Swaminathan static uint32_t emlxs_fct_process_unsol_plogi(emlxs_port_t *port,
9582527734SSukumar Swaminathan     CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
96fe199829SSukumar Swaminathan static uint32_t emlxs_fct_pkt_abort_txq(emlxs_port_t *port,
97fe199829SSukumar Swaminathan     emlxs_buf_t *cmd_sbp);
98fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_qfull_reply(emlxs_port_t *port,
99fcf3ce44SJohn Forte     emlxs_node_t *ndlp, uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd);
100291a2b48SSukumar Swaminathan 
101291a2b48SSukumar Swaminathan #ifdef FCT_IO_TRACE
102291a2b48SSukumar Swaminathan uint8_t *emlxs_iotrace = 0;	/* global for mdb */
103291a2b48SSukumar Swaminathan int emlxs_iotrace_cnt = 0;
104291a2b48SSukumar Swaminathan 
10582527734SSukumar Swaminathan /*
10682527734SSukumar Swaminathan  *
10782527734SSukumar Swaminathan  * FCT_CMD  (cmd_sbp->fct_state)
10882527734SSukumar Swaminathan  *
10982527734SSukumar Swaminathan  * STATE				LOCK STATUS			OWNER
11082527734SSukumar Swaminathan  * -----------------------------------------------------------------------------
11182527734SSukumar Swaminathan  * EMLXS_FCT_ABORT_DONE			Lock Destroyed			COMSTAR
11282527734SSukumar Swaminathan  * EMLXS_FCT_IO_DONE			Lock Destroyed			COMSTAR
11382527734SSukumar Swaminathan  *
11482527734SSukumar Swaminathan  * EMLXS_FCT_CMD_POSTED			Lock Released			COMSTAR
11582527734SSukumar Swaminathan  * EMLXS_FCT_OWNED			Lock Released			COMSTAR
11682527734SSukumar Swaminathan  *
11782527734SSukumar Swaminathan  * EMLXS_FCT_CMD_WAITQ			Lock Released			DRIVER
11882527734SSukumar Swaminathan  * EMLXS_FCT_RSP_PENDING		Lock Released			DRIVER
11982527734SSukumar Swaminathan  * EMLXS_FCT_REQ_PENDING		Lock Released			DRIVER
12082527734SSukumar Swaminathan  * EMLXS_FCT_REG_PENDING		Lock Released			DRIVER
12182527734SSukumar Swaminathan  * EMLXS_FCT_DATA_PENDING		Lock Released			DRIVER
12282527734SSukumar Swaminathan  * EMLXS_FCT_STATUS_PENDING		Lock Released			DRIVER
12382527734SSukumar Swaminathan  * EMLXS_FCT_CLOSE_PENDING		Lock Released			DRIVER
12482527734SSukumar Swaminathan  * EMLXS_FCT_ABORT_PENDING		Lock Released			DRIVER
12582527734SSukumar Swaminathan  *
12682527734SSukumar Swaminathan  * EMLXS_FCT_FCP_CMD_RECEIVED		Transistional, lock held	DRIVER
12782527734SSukumar Swaminathan  * EMLXS_FCT_ELS_CMD_RECEIVED		Transistional, lock held	DRIVER
12882527734SSukumar Swaminathan  * EMLXS_FCT_SEND_CMD_RSP		Transistional, lock held	DRIVER
12982527734SSukumar Swaminathan  * EMLXS_FCT_SEND_ELS_RSP		Transistional, lock held	DRIVER
13082527734SSukumar Swaminathan  * EMLXS_FCT_SEND_ELS_REQ		Transistional, lock held	DRIVER
13182527734SSukumar Swaminathan  * EMLXS_FCT_SEND_CT_REQ		Transistional, lock held	DRIVER
13282527734SSukumar Swaminathan  * EMLXS_FCT_REG_COMPLETE		Transistional, lock held	DRIVER
13382527734SSukumar Swaminathan  * EMLXS_FCT_SEND_FCP_DATA		Transistional, lock held	DRIVER
13482527734SSukumar Swaminathan  * EMLXS_FCT_SEND_FCP_STATUS		Transistional, lock held	DRIVER
13582527734SSukumar Swaminathan  * EMLXS_FCT_PKT_COMPLETE		Transistional, lock held	DRIVER
13682527734SSukumar Swaminathan  * EMLXS_FCT_PKT_FCPRSP_COMPLETE	Transistional, lock held	DRIVER
13782527734SSukumar Swaminathan  * EMLXS_FCT_PKT_ELSRSP_COMPLETE	Transistional, lock held	DRIVER
13882527734SSukumar Swaminathan  * EMLXS_FCT_PKT_ELSCMD_COMPLETE	Transistional, lock held	DRIVER
13982527734SSukumar Swaminathan  * EMLXS_FCT_PKT_CTCMD_COMPLETE		Transistional, lock held	DRIVER
14082527734SSukumar Swaminathan  * EMLXS_FCT_REQ_COMPLETE		Transistional, lock held	DRIVER
14182527734SSukumar Swaminathan  *
14282527734SSukumar Swaminathan  *
14382527734SSukumar Swaminathan  * 	COMSTAR OWNED	DRIVER OWNED
14482527734SSukumar Swaminathan  * 	-------------	---------------------------------------------------
14582527734SSukumar Swaminathan  * 	------- >	@	   Accept---- >Release  @   Acquire--- >+
14682527734SSukumar Swaminathan  *									|
14782527734SSukumar Swaminathan  *	< -------	@	Post/Done< ----Acquire  @   Release< ---+
14882527734SSukumar Swaminathan  *
14982527734SSukumar Swaminathan  * 	@  :Indicates COMSTAR use of emlxs_fct_abort()
15082527734SSukumar Swaminathan  *	    Abort requests set the EMLXS_FCT_ABORT_INP flag.
15182527734SSukumar Swaminathan  *
15282527734SSukumar Swaminathan  * 	Accept		:Indicates use of emlxs_fct_cmd_accept()
15382527734SSukumar Swaminathan  * 	Acquire		:Indicates use of emlxs_fct_cmd_acquire()
15482527734SSukumar Swaminathan  * 	Post		:Indicates use of emlxs_fct_cmd_post()
15582527734SSukumar Swaminathan  * 	Done		:Indicates use of emlxs_fct_cmd_done()
15682527734SSukumar Swaminathan  */
15782527734SSukumar Swaminathan 
158291a2b48SSukumar Swaminathan void
159291a2b48SSukumar Swaminathan emlxs_fct_io_trace(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint32_t data)
160291a2b48SSukumar Swaminathan {
161291a2b48SSukumar Swaminathan 	emlxs_iotrace_t *iop = port->iotrace;
162291a2b48SSukumar Swaminathan 	uint16_t iotrace_cnt;
163291a2b48SSukumar Swaminathan 	uint16_t iotrace_index;
164291a2b48SSukumar Swaminathan 	int i;
165291a2b48SSukumar Swaminathan 
166291a2b48SSukumar Swaminathan 	if (!iop) {
167291a2b48SSukumar Swaminathan 		return;
168291a2b48SSukumar Swaminathan 	}
169291a2b48SSukumar Swaminathan 
170291a2b48SSukumar Swaminathan 	mutex_enter(&port->iotrace_mtx);
171291a2b48SSukumar Swaminathan 	iotrace_cnt = port->iotrace_cnt;
172291a2b48SSukumar Swaminathan 	iotrace_index = port->iotrace_index;
173291a2b48SSukumar Swaminathan 
174291a2b48SSukumar Swaminathan 	switch (data) {
175291a2b48SSukumar Swaminathan 
176291a2b48SSukumar Swaminathan 		/* New entry */
177291a2b48SSukumar Swaminathan 	case EMLXS_FCT_ELS_CMD_RECEIVED:
178291a2b48SSukumar Swaminathan 	case EMLXS_FCT_FCP_CMD_RECEIVED:
179291a2b48SSukumar Swaminathan 	case EMLXS_FCT_SEND_ELS_REQ:
180291a2b48SSukumar Swaminathan 	case EMLXS_FCT_SEND_CT_REQ:
181291a2b48SSukumar Swaminathan 		for (i = 0; i < iotrace_cnt; i++) {
182291a2b48SSukumar Swaminathan 			if ((iop->fct_cmd == fct_cmd) &&
183291a2b48SSukumar Swaminathan 			    (iop->trc[0] != (uint8_t)(0)))
184291a2b48SSukumar Swaminathan 				break;
185291a2b48SSukumar Swaminathan 			iop++;
186291a2b48SSukumar Swaminathan 		}
187291a2b48SSukumar Swaminathan 		if (i < iotrace_cnt) {
188291a2b48SSukumar Swaminathan 			/* New entry already exists */
189291a2b48SSukumar Swaminathan 			mutex_exit(&port->iotrace_mtx);
190291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
191291a2b48SSukumar Swaminathan 			    "IOTRACE: New entry already exists: fct_cmd: %p",
192291a2b48SSukumar Swaminathan 			    fct_cmd);
193291a2b48SSukumar Swaminathan 			return;
194291a2b48SSukumar Swaminathan 		}
195291a2b48SSukumar Swaminathan 		iop = port->iotrace + iotrace_index;
196291a2b48SSukumar Swaminathan 		for (i = 0; i < iotrace_cnt; i++) {
197291a2b48SSukumar Swaminathan 			if (iop->trc[0] == (uint8_t)(0))
198291a2b48SSukumar Swaminathan 				break;
199291a2b48SSukumar Swaminathan 
200291a2b48SSukumar Swaminathan 			iop++;
201291a2b48SSukumar Swaminathan 			if (iop == (port->iotrace + iotrace_cnt))
202291a2b48SSukumar Swaminathan 				iop = port->iotrace;
203291a2b48SSukumar Swaminathan 		}
204291a2b48SSukumar Swaminathan 		if (i >= iotrace_cnt) {
205291a2b48SSukumar Swaminathan 			/* No new slots available */
206291a2b48SSukumar Swaminathan 			mutex_exit(&port->iotrace_mtx);
207291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
208291a2b48SSukumar Swaminathan 			    "IOTRACE: No new slots: fct_cmd: %p data: %d",
209291a2b48SSukumar Swaminathan 			    fct_cmd, data);
210291a2b48SSukumar Swaminathan 			return;
211291a2b48SSukumar Swaminathan 		}
212291a2b48SSukumar Swaminathan 		port->iotrace_index++;
213291a2b48SSukumar Swaminathan 		if (port->iotrace_index >= iotrace_cnt)
214291a2b48SSukumar Swaminathan 			port->iotrace_index = 0;
215291a2b48SSukumar Swaminathan 
216291a2b48SSukumar Swaminathan 		bzero((uint8_t *)iop, sizeof (emlxs_iotrace_t));
217291a2b48SSukumar Swaminathan 		iop->fct_cmd = fct_cmd;
218291a2b48SSukumar Swaminathan 		iop->xri = fct_cmd->cmd_rxid;
219291a2b48SSukumar Swaminathan 		iop->marker = 0xff;
220291a2b48SSukumar Swaminathan 		iop->trc[0] = 2;
221291a2b48SSukumar Swaminathan 		iop->trc[1] = data;
222291a2b48SSukumar Swaminathan 		mutex_exit(&port->iotrace_mtx);
223291a2b48SSukumar Swaminathan 		return;
224291a2b48SSukumar Swaminathan 	}
225291a2b48SSukumar Swaminathan 
226291a2b48SSukumar Swaminathan 	for (i = 0; i < iotrace_cnt; i++) {
227291a2b48SSukumar Swaminathan 		if ((iop->fct_cmd == fct_cmd) &&
228291a2b48SSukumar Swaminathan 		    (iop->trc[0] != (uint8_t)(0)))
229291a2b48SSukumar Swaminathan 			break;
230291a2b48SSukumar Swaminathan 		iop++;
231291a2b48SSukumar Swaminathan 	}
232291a2b48SSukumar Swaminathan 	if (i >= iotrace_cnt) {
233291a2b48SSukumar Swaminathan 		/* Cannot find existing slot for fct_cmd */
234291a2b48SSukumar Swaminathan 		mutex_exit(&port->iotrace_mtx);
235291a2b48SSukumar Swaminathan 
236291a2b48SSukumar Swaminathan 		if ((data != EMLXS_FCT_REG_PENDING) &&
237291a2b48SSukumar Swaminathan 		    (data != EMLXS_FCT_REG_COMPLETE)) {
238291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
239291a2b48SSukumar Swaminathan 			    "IOTRACE: Missing slot: fct_cmd: %p data: %d",
240291a2b48SSukumar Swaminathan 			    fct_cmd, data);
241291a2b48SSukumar Swaminathan 		}
242291a2b48SSukumar Swaminathan 		return;
243291a2b48SSukumar Swaminathan 	}
244291a2b48SSukumar Swaminathan 
245291a2b48SSukumar Swaminathan 	if (iop->trc[0] >= MAX_IO_TRACE) {
246291a2b48SSukumar Swaminathan 		/* trc overrun for fct_cmd */
247291a2b48SSukumar Swaminathan 		mutex_exit(&port->iotrace_mtx);
248291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
249291a2b48SSukumar Swaminathan 		    "IOTRACE: trc overrun slot: fct_cmd: %p data: %d",
250291a2b48SSukumar Swaminathan 		    fct_cmd, data);
251291a2b48SSukumar Swaminathan 		return;
252291a2b48SSukumar Swaminathan 	}
253291a2b48SSukumar Swaminathan 
254291a2b48SSukumar Swaminathan 	if (iop->xri != fct_cmd->cmd_rxid) {
255291a2b48SSukumar Swaminathan 		/* xri mismatch for fct_cmd */
256291a2b48SSukumar Swaminathan 		mutex_exit(&port->iotrace_mtx);
257291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
258291a2b48SSukumar Swaminathan 		    "IOTRACE: xri mismatch %x != %x: fct_cmd: %p data: %d",
259291a2b48SSukumar Swaminathan 		    iop->xri, fct_cmd->cmd_rxid, fct_cmd, data);
260291a2b48SSukumar Swaminathan 		return;
261291a2b48SSukumar Swaminathan 	}
262291a2b48SSukumar Swaminathan 
263291a2b48SSukumar Swaminathan 	iop->trc[iop->trc[0]] = data;
264291a2b48SSukumar Swaminathan 	if ((data == EMLXS_FCT_IO_DONE) || (data == EMLXS_FCT_ABORT_DONE)) {
26582527734SSukumar Swaminathan 		/* IOCB ULPCOMMAND is saved after EMLXS_FCT_IOCB_ISSUED */
26682527734SSukumar Swaminathan 		if (iop->trc[iop->trc[0]-1] == EMLXS_FCT_IOCB_ISSUED) {
267291a2b48SSukumar Swaminathan 			iop->trc[0]++;
26882527734SSukumar Swaminathan 		} else {
269291a2b48SSukumar Swaminathan 			iop->trc[0] = 0;
27082527734SSukumar Swaminathan 	} else {
271291a2b48SSukumar Swaminathan 		iop->trc[0]++;
27282527734SSukumar Swaminathan 	}
273291a2b48SSukumar Swaminathan 	mutex_exit(&port->iotrace_mtx);
27482527734SSukumar Swaminathan 
27582527734SSukumar Swaminathan 	return;
27682527734SSukumar Swaminathan 
27782527734SSukumar Swaminathan } /* emlxs_fct_io_trace() */
278291a2b48SSukumar Swaminathan #endif /* FCT_IO_TRACE */
279fcf3ce44SJohn Forte 
280fcf3ce44SJohn Forte #ifdef MODSYM_SUPPORT
281fcf3ce44SJohn Forte 
282e51761e0SSukumar Swaminathan extern int
283fcf3ce44SJohn Forte emlxs_fct_modopen()
284fcf3ce44SJohn Forte {
285fcf3ce44SJohn Forte 	int err;
286fcf3ce44SJohn Forte 
28782527734SSukumar Swaminathan 	mutex_enter(&emlxs_device.lock);
28882527734SSukumar Swaminathan 
28982527734SSukumar Swaminathan 	if (emlxs_modsym.fct_modopen) {
29082527734SSukumar Swaminathan 		mutex_exit(&emlxs_device.lock);
29182527734SSukumar Swaminathan 		return (0);
292fcf3ce44SJohn Forte 	}
293291a2b48SSukumar Swaminathan 
29482527734SSukumar Swaminathan 	emlxs_modsym.fct_modopen++;
29582527734SSukumar Swaminathan 
296fcf3ce44SJohn Forte 	/* Comstar (fct) */
297fcf3ce44SJohn Forte 	err = 0;
298fcf3ce44SJohn Forte 	emlxs_modsym.mod_fct = ddi_modopen("drv/fct", KRTLD_MODE_FIRST, &err);
299fcf3ce44SJohn Forte 	if (!emlxs_modsym.mod_fct) {
300fcf3ce44SJohn Forte 
301fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "?%s: ddi_modopen drv/fct failed: err %d",
302fcf3ce44SJohn Forte 		    DRIVER_NAME, err);
303fcf3ce44SJohn Forte 		goto failed;
304fcf3ce44SJohn Forte 	}
305291a2b48SSukumar Swaminathan 
306fcf3ce44SJohn Forte 	/* Comstar (stmf) */
307fcf3ce44SJohn Forte 	err = 0;
308291a2b48SSukumar Swaminathan 	emlxs_modsym.mod_stmf =
309291a2b48SSukumar Swaminathan 	    ddi_modopen("drv/stmf", KRTLD_MODE_FIRST, &err);
310fcf3ce44SJohn Forte 	if (!emlxs_modsym.mod_stmf) {
311fcf3ce44SJohn Forte 
312fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "?%s: ddi_modopen drv/stmf failed: err %d",
313fcf3ce44SJohn Forte 		    DRIVER_NAME, err);
314fcf3ce44SJohn Forte 		goto failed;
315fcf3ce44SJohn Forte 	}
316291a2b48SSukumar Swaminathan 
317fcf3ce44SJohn Forte 	err = 0;
318fcf3ce44SJohn Forte 	/* Check if the fct fct_alloc is present */
319291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_alloc = (void *(*)())ddi_modsym(emlxs_modsym.mod_fct,
320fcf3ce44SJohn Forte 	    "fct_alloc", &err);
321fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_alloc == NULL) {
322fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
323fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_alloc not present", DRIVER_NAME);
324fcf3ce44SJohn Forte 		goto failed;
325fcf3ce44SJohn Forte 	}
326291a2b48SSukumar Swaminathan 
327fcf3ce44SJohn Forte 	err = 0;
328fcf3ce44SJohn Forte 	/* Check if the fct fct_free is present */
329291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_free = (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
330fcf3ce44SJohn Forte 	    "fct_free", &err);
331fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_free == NULL) {
332fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
333fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_free not present", DRIVER_NAME);
334fcf3ce44SJohn Forte 		goto failed;
335fcf3ce44SJohn Forte 	}
336291a2b48SSukumar Swaminathan 
337fcf3ce44SJohn Forte 	err = 0;
338fcf3ce44SJohn Forte 	/* Check if the fct fct_scsi_task_alloc is present */
339291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_scsi_task_alloc =
340291a2b48SSukumar Swaminathan 	    (void *(*)(void *, uint16_t, uint32_t, uint8_t *,
341291a2b48SSukumar Swaminathan 	    uint16_t, uint16_t))ddi_modsym(emlxs_modsym.mod_fct,
342291a2b48SSukumar Swaminathan 	    "fct_scsi_task_alloc", &err);
343fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_scsi_task_alloc == NULL) {
344fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
345fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_scsi_task_alloc not present",
346fcf3ce44SJohn Forte 		    DRIVER_NAME);
347fcf3ce44SJohn Forte 		goto failed;
348fcf3ce44SJohn Forte 	}
349291a2b48SSukumar Swaminathan 
350fcf3ce44SJohn Forte 	err = 0;
351fcf3ce44SJohn Forte 	/* Check if the fct fct_register_local_port is present */
352291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_register_local_port =
353291a2b48SSukumar Swaminathan 	    (int (*)())ddi_modsym(emlxs_modsym.mod_fct,
354291a2b48SSukumar Swaminathan 	    "fct_register_local_port", &err);
355fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_register_local_port == NULL) {
356fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
357fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_register_local_port not present",
358fcf3ce44SJohn Forte 		    DRIVER_NAME);
359fcf3ce44SJohn Forte 		goto failed;
360fcf3ce44SJohn Forte 	}
361291a2b48SSukumar Swaminathan 
362fcf3ce44SJohn Forte 	err = 0;
363fcf3ce44SJohn Forte 	/* Check if the fct fct_deregister_local_port is present */
364291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_deregister_local_port =
365291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
366291a2b48SSukumar Swaminathan 	    "fct_deregister_local_port", &err);
367fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_deregister_local_port == NULL) {
368fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
369fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_deregister_local_port not present",
370fcf3ce44SJohn Forte 		    DRIVER_NAME);
371fcf3ce44SJohn Forte 		goto failed;
372fcf3ce44SJohn Forte 	}
373291a2b48SSukumar Swaminathan 
374fcf3ce44SJohn Forte 	err = 0;
375fcf3ce44SJohn Forte 	/* Check if the fct fct_handle_event is present */
376291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_handle_event =
377291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_handle_event",
378291a2b48SSukumar Swaminathan 	    &err);
379fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_handle_event == NULL) {
380fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
381291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_handle_event not present",
382291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
383fcf3ce44SJohn Forte 		goto failed;
384fcf3ce44SJohn Forte 	}
385291a2b48SSukumar Swaminathan 
386fcf3ce44SJohn Forte 	err = 0;
387fcf3ce44SJohn Forte 	/* Check if the fct fct_post_rcvd_cmd is present */
388291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_post_rcvd_cmd =
389291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_post_rcvd_cmd",
390291a2b48SSukumar Swaminathan 	    &err);
391fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_post_rcvd_cmd == NULL) {
392fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
393291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_post_rcvd_cmd not present",
394291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
395fcf3ce44SJohn Forte 		goto failed;
396fcf3ce44SJohn Forte 	}
397fcf3ce44SJohn Forte 	err = 0;
398fcf3ce44SJohn Forte 	/* Check if the fct fct_alloc is present */
399291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_ctl = (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
400fcf3ce44SJohn Forte 	    "fct_ctl", &err);
401fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_ctl == NULL) {
402fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
403fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_ctl not present", DRIVER_NAME);
404fcf3ce44SJohn Forte 		goto failed;
405fcf3ce44SJohn Forte 	}
406fcf3ce44SJohn Forte 	err = 0;
407291a2b48SSukumar Swaminathan 	/* Check if the fct fct_queue_cmd_for_termination is present */
408291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_queue_cmd_for_termination =
409291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
410291a2b48SSukumar Swaminathan 	    "fct_queue_cmd_for_termination", &err);
411291a2b48SSukumar Swaminathan 	if ((void *)emlxs_modsym.fct_queue_cmd_for_termination == NULL) {
412291a2b48SSukumar Swaminathan 		cmn_err(CE_WARN,
413291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_queue_cmd_for_termination not present",
414291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
415291a2b48SSukumar Swaminathan 		goto failed;
416291a2b48SSukumar Swaminathan 	}
417291a2b48SSukumar Swaminathan 	err = 0;
418fcf3ce44SJohn Forte 	/* Check if the fct fct_send_response_done is present */
419291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_send_response_done =
420291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
421291a2b48SSukumar Swaminathan 	    "fct_send_response_done", &err);
422fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_send_response_done == NULL) {
423fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
424fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_send_response_done not present",
425fcf3ce44SJohn Forte 		    DRIVER_NAME);
426fcf3ce44SJohn Forte 		goto failed;
427fcf3ce44SJohn Forte 	}
428fcf3ce44SJohn Forte 	err = 0;
429fcf3ce44SJohn Forte 	/* Check if the fct fct_send_cmd_done is present */
430291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_send_cmd_done =
431291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_send_cmd_done",
432291a2b48SSukumar Swaminathan 	    &err);
433fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_send_cmd_done == NULL) {
434fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
435291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_send_cmd_done not present",
436291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
437fcf3ce44SJohn Forte 		goto failed;
438fcf3ce44SJohn Forte 	}
439fcf3ce44SJohn Forte 	err = 0;
440fcf3ce44SJohn Forte 	/* Check if the fct fct_scsi_xfer_data_done is present */
441291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_scsi_data_xfer_done =
442291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
443291a2b48SSukumar Swaminathan 	    "fct_scsi_data_xfer_done", &err);
444fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_scsi_data_xfer_done == NULL) {
445fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
446fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_scsi_data_xfer_done not present",
447fcf3ce44SJohn Forte 		    DRIVER_NAME);
448fcf3ce44SJohn Forte 		goto failed;
449fcf3ce44SJohn Forte 	}
450fcf3ce44SJohn Forte 	err = 0;
451fcf3ce44SJohn Forte 	/* Check if the fct fct_port_shutdown is present */
452291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_port_shutdown =
453291a2b48SSukumar Swaminathan 	    (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct,
454291a2b48SSukumar Swaminathan 	    "fct_port_shutdown", &err);
455fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_port_shutdown == NULL) {
456fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
457291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_port_shutdown not present",
458291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
459fcf3ce44SJohn Forte 		goto failed;
460fcf3ce44SJohn Forte 	}
461291a2b48SSukumar Swaminathan 
462fcf3ce44SJohn Forte 	err = 0;
463fcf3ce44SJohn Forte 	/* Check if the fct fct_port_initialize is present */
464291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_port_initialize =
465291a2b48SSukumar Swaminathan 	    (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct,
466291a2b48SSukumar Swaminathan 	    "fct_port_initialize", &err);
467fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_port_initialize == NULL) {
468fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
469fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_port_initialize not present",
470fcf3ce44SJohn Forte 		    DRIVER_NAME);
471fcf3ce44SJohn Forte 		goto failed;
472fcf3ce44SJohn Forte 	}
473291a2b48SSukumar Swaminathan 
474291a2b48SSukumar Swaminathan 	err = 0;
475291a2b48SSukumar Swaminathan 	/* Check if the fct fct_cmd_fca_aborted is present */
476291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_cmd_fca_aborted =
477291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
478291a2b48SSukumar Swaminathan 	    "fct_cmd_fca_aborted", &err);
479291a2b48SSukumar Swaminathan 	if ((void *)emlxs_modsym.fct_cmd_fca_aborted == NULL) {
480291a2b48SSukumar Swaminathan 		cmn_err(CE_WARN,
481291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_cmd_fca_aborted not present",
482291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
483291a2b48SSukumar Swaminathan 		goto failed;
484291a2b48SSukumar Swaminathan 	}
485291a2b48SSukumar Swaminathan 
486fcf3ce44SJohn Forte 	err = 0;
487fcf3ce44SJohn Forte 	/* Check if the fct fct_handle_rcvd_flogi is present */
488291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_handle_rcvd_flogi =
489291a2b48SSukumar Swaminathan 	    (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct,
490291a2b48SSukumar Swaminathan 	    "fct_handle_rcvd_flogi", &err);
491fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_handle_rcvd_flogi == NULL) {
492fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
493fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_handle_rcvd_flogi not present",
494fcf3ce44SJohn Forte 		    DRIVER_NAME);
495fcf3ce44SJohn Forte 		goto failed;
496fcf3ce44SJohn Forte 	}
497291a2b48SSukumar Swaminathan 
498fcf3ce44SJohn Forte 	/* Comstar (stmf) */
499fcf3ce44SJohn Forte 	err = 0;
500fcf3ce44SJohn Forte 	/* Check if the stmf stmf_alloc is present */
501291a2b48SSukumar Swaminathan 	emlxs_modsym.stmf_alloc =
502291a2b48SSukumar Swaminathan 	    (void *(*)())ddi_modsym(emlxs_modsym.mod_stmf, "stmf_alloc",
503291a2b48SSukumar Swaminathan 	    &err);
504fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.stmf_alloc == NULL) {
505fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
506fcf3ce44SJohn Forte 		    "?%s: drv/stmf: stmf_alloc not present", DRIVER_NAME);
507fcf3ce44SJohn Forte 		goto failed;
508fcf3ce44SJohn Forte 	}
509291a2b48SSukumar Swaminathan 
510fcf3ce44SJohn Forte 	err = 0;
511fcf3ce44SJohn Forte 	/* Check if the stmf stmf_free is present */
512291a2b48SSukumar Swaminathan 	emlxs_modsym.stmf_free = (void (*)())ddi_modsym(emlxs_modsym.mod_stmf,
513fcf3ce44SJohn Forte 	    "stmf_free", &err);
514fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.stmf_free == NULL) {
515fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
516fcf3ce44SJohn Forte 		    "?%s: drv/stmf: stmf_free not present", DRIVER_NAME);
517fcf3ce44SJohn Forte 		goto failed;
518fcf3ce44SJohn Forte 	}
519291a2b48SSukumar Swaminathan 
520fcf3ce44SJohn Forte 	err = 0;
521fcf3ce44SJohn Forte 	/* Check if the stmf stmf_deregister_port_provider is present */
522fcf3ce44SJohn Forte 	emlxs_modsym.stmf_deregister_port_provider =
523291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_stmf,
524fcf3ce44SJohn Forte 	    "stmf_deregister_port_provider", &err);
525fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.stmf_deregister_port_provider == NULL) {
526fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
527fcf3ce44SJohn Forte 		    "?%s: drv/stmf: stmf_deregister_port_provider not present",
528fcf3ce44SJohn Forte 		    DRIVER_NAME);
529fcf3ce44SJohn Forte 		goto failed;
530fcf3ce44SJohn Forte 	}
531291a2b48SSukumar Swaminathan 
532fcf3ce44SJohn Forte 	err = 0;
533fcf3ce44SJohn Forte 	/* Check if the stmf stmf_register_port_provider is present */
534fcf3ce44SJohn Forte 	emlxs_modsym.stmf_register_port_provider =
535291a2b48SSukumar Swaminathan 	    (int (*)())ddi_modsym(emlxs_modsym.mod_stmf,
536fcf3ce44SJohn Forte 	    "stmf_register_port_provider", &err);
537fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.stmf_register_port_provider == NULL) {
538fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
539fcf3ce44SJohn Forte 		    "?%s: drv/stmf: stmf_register_port_provider not present",
540fcf3ce44SJohn Forte 		    DRIVER_NAME);
541fcf3ce44SJohn Forte 		goto failed;
542fcf3ce44SJohn Forte 	}
54382527734SSukumar Swaminathan 
54482527734SSukumar Swaminathan 	mutex_exit(&emlxs_device.lock);
54582527734SSukumar Swaminathan 	return (0);
546fcf3ce44SJohn Forte 
547fcf3ce44SJohn Forte failed:
54882527734SSukumar Swaminathan 
54982527734SSukumar Swaminathan 	mutex_exit(&emlxs_device.lock);
550fcf3ce44SJohn Forte 	emlxs_fct_modclose();
55182527734SSukumar Swaminathan 	return (1);
552fcf3ce44SJohn Forte 
55382527734SSukumar Swaminathan } /* emlxs_fct_modopen() */
554fcf3ce44SJohn Forte 
555fcf3ce44SJohn Forte 
556fcf3ce44SJohn Forte extern void
557fcf3ce44SJohn Forte emlxs_fct_modclose()
558fcf3ce44SJohn Forte {
55982527734SSukumar Swaminathan 	mutex_enter(&emlxs_device.lock);
56082527734SSukumar Swaminathan 
56182527734SSukumar Swaminathan 	if (emlxs_modsym.fct_modopen == 0) {
56282527734SSukumar Swaminathan 		mutex_exit(&emlxs_device.lock);
56382527734SSukumar Swaminathan 		return;
56482527734SSukumar Swaminathan 	}
56582527734SSukumar Swaminathan 
56682527734SSukumar Swaminathan 	emlxs_modsym.fct_modopen--;
56782527734SSukumar Swaminathan 
56882527734SSukumar Swaminathan 	if (emlxs_modsym.fct_modopen) {
56982527734SSukumar Swaminathan 		mutex_exit(&emlxs_device.lock);
57082527734SSukumar Swaminathan 		return;
57182527734SSukumar Swaminathan 	}
572fcf3ce44SJohn Forte 
573fcf3ce44SJohn Forte 	if (emlxs_modsym.mod_fct) {
574fcf3ce44SJohn Forte 		(void) ddi_modclose(emlxs_modsym.mod_fct);
575fcf3ce44SJohn Forte 		emlxs_modsym.mod_fct = 0;
576fcf3ce44SJohn Forte 	}
577291a2b48SSukumar Swaminathan 
578fcf3ce44SJohn Forte 	if (emlxs_modsym.mod_stmf) {
579fcf3ce44SJohn Forte 		(void) ddi_modclose(emlxs_modsym.mod_stmf);
580fcf3ce44SJohn Forte 		emlxs_modsym.mod_stmf = 0;
581fcf3ce44SJohn Forte 	}
582291a2b48SSukumar Swaminathan 
583fcf3ce44SJohn Forte 	emlxs_modsym.fct_alloc = NULL;
584fcf3ce44SJohn Forte 	emlxs_modsym.fct_free = NULL;
585fcf3ce44SJohn Forte 	emlxs_modsym.fct_scsi_task_alloc = NULL;
586fcf3ce44SJohn Forte 	emlxs_modsym.fct_register_local_port = NULL;
587fcf3ce44SJohn Forte 	emlxs_modsym.fct_deregister_local_port = NULL;
588fcf3ce44SJohn Forte 	emlxs_modsym.fct_handle_event = NULL;
589fcf3ce44SJohn Forte 	emlxs_modsym.fct_ctl = NULL;
590291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_queue_cmd_for_termination = NULL;
591fcf3ce44SJohn Forte 	emlxs_modsym.fct_send_response_done = NULL;
592fcf3ce44SJohn Forte 	emlxs_modsym.fct_send_cmd_done = NULL;
593fcf3ce44SJohn Forte 	emlxs_modsym.fct_scsi_data_xfer_done = NULL;
594fcf3ce44SJohn Forte 	emlxs_modsym.fct_port_shutdown = NULL;
595fcf3ce44SJohn Forte 	emlxs_modsym.fct_port_initialize = NULL;
596291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_cmd_fca_aborted = NULL;
597fcf3ce44SJohn Forte 	emlxs_modsym.fct_handle_rcvd_flogi = NULL;
598fcf3ce44SJohn Forte 
599fcf3ce44SJohn Forte 	emlxs_modsym.stmf_alloc = NULL;
600fcf3ce44SJohn Forte 	emlxs_modsym.stmf_free = NULL;
601fcf3ce44SJohn Forte 	emlxs_modsym.stmf_deregister_port_provider = NULL;
602fcf3ce44SJohn Forte 	emlxs_modsym.stmf_register_port_provider = NULL;
603fcf3ce44SJohn Forte 
60482527734SSukumar Swaminathan 	mutex_exit(&emlxs_device.lock);
60582527734SSukumar Swaminathan 
60682527734SSukumar Swaminathan } /* emlxs_fct_modclose() */
607291a2b48SSukumar Swaminathan 
608291a2b48SSukumar Swaminathan #endif /* MODSYM_SUPPORT */
609291a2b48SSukumar Swaminathan 
610e2ca2865SSukumar Swaminathan /*
611e2ca2865SSukumar Swaminathan  * This routine is called to handle an unsol FLOGI exchange
612e2ca2865SSukumar Swaminathan  *	fx	save
613e2ca2865SSukumar Swaminathan  *	0	1	Process or save port->fx
614e2ca2865SSukumar Swaminathan  *	0	0	Process or reject port->fx
615e2ca2865SSukumar Swaminathan  *	1	1	Process port->fx, Process or save fx
616e2ca2865SSukumar Swaminathan  *	1	0	Process or reject port->fx, Process or reject fx
617e2ca2865SSukumar Swaminathan  */
618291a2b48SSukumar Swaminathan static void
619e2ca2865SSukumar Swaminathan emlxs_fct_handle_unsol_flogi(emlxs_port_t *port, fct_flogi_xchg_t *fx,
620e2ca2865SSukumar Swaminathan     uint32_t save)
621291a2b48SSukumar Swaminathan {
622e2ca2865SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
623291a2b48SSukumar Swaminathan 	fct_status_t status;
624291a2b48SSukumar Swaminathan 	IOCBQ iocbq;
625e2ca2865SSukumar Swaminathan 	fct_flogi_xchg_t fxchg;
626e2ca2865SSukumar Swaminathan 
627e2ca2865SSukumar Swaminathan begin:
628e2ca2865SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
629e2ca2865SSukumar Swaminathan 
630e2ca2865SSukumar Swaminathan 	/* Check if there is an old saved FLOGI */
631e2ca2865SSukumar Swaminathan 	if (port->fx.fx_op) {
632e2ca2865SSukumar Swaminathan 		/* Get it now */
633e2ca2865SSukumar Swaminathan 		bcopy(&port->fx, &fxchg, sizeof (fct_flogi_xchg_t));
634e2ca2865SSukumar Swaminathan 
635e2ca2865SSukumar Swaminathan 		if (fx) {
636e2ca2865SSukumar Swaminathan 			/* Save new FLOGI */
637e2ca2865SSukumar Swaminathan 			bcopy(fx, &port->fx, sizeof (fct_flogi_xchg_t));
638e2ca2865SSukumar Swaminathan 
639e2ca2865SSukumar Swaminathan 			/* Reject old stale FLOGI */
640e2ca2865SSukumar Swaminathan 			fx = &fxchg;
641e2ca2865SSukumar Swaminathan 			goto reject_it;
642e2ca2865SSukumar Swaminathan 
643e2ca2865SSukumar Swaminathan 		} else {
644e2ca2865SSukumar Swaminathan 			bzero(&port->fx, sizeof (fct_flogi_xchg_t));
645e2ca2865SSukumar Swaminathan 			fx = &fxchg;
646e2ca2865SSukumar Swaminathan 		}
647e2ca2865SSukumar Swaminathan 
648e2ca2865SSukumar Swaminathan 	} else if (!fx) {
649e2ca2865SSukumar Swaminathan 		/* Nothing to do, just return */
650e2ca2865SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
651e2ca2865SSukumar Swaminathan 		return;
652e2ca2865SSukumar Swaminathan 	}
653e2ca2865SSukumar Swaminathan 
654e2ca2865SSukumar Swaminathan 	/* We have a valid FLOGI here */
655e2ca2865SSukumar Swaminathan 	/* There is no saved FLOGI at this point either */
656e2ca2865SSukumar Swaminathan 
657e2ca2865SSukumar Swaminathan 	/* Check if COMSTAR is ready to accept it */
658e2ca2865SSukumar Swaminathan 	if (port->fct_flags & FCT_STATE_LINK_UP_ACKED) {
659e2ca2865SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
660291a2b48SSukumar Swaminathan 
661291a2b48SSukumar Swaminathan 		bzero((uint8_t *)&iocbq, sizeof (IOCBQ));
662e2ca2865SSukumar Swaminathan 		iocbq.iocb.un.elsreq.remoteID = fx->fx_sid;
663e2ca2865SSukumar Swaminathan 		iocbq.iocb.un.elsreq.myID = fx->fx_did;
664e2ca2865SSukumar Swaminathan 		iocbq.iocb.ULPCONTEXT = (uint16_t)fx->rsvd2;
665e2ca2865SSukumar Swaminathan 		fx->rsvd2 = 0; /* Clear the reserved field now */
666291a2b48SSukumar Swaminathan 
667e2ca2865SSukumar Swaminathan 		status = MODSYM(fct_handle_rcvd_flogi) (port->fct_port, fx);
668291a2b48SSukumar Swaminathan 
669291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
670291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
671e2ca2865SSukumar Swaminathan 		    "fct_handle_rcvd_flogi %p: status=%x",
672e2ca2865SSukumar Swaminathan 		    port->fct_port, status);
673291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
674291a2b48SSukumar Swaminathan 
675291a2b48SSukumar Swaminathan 		if (status == FCT_SUCCESS) {
676e2ca2865SSukumar Swaminathan 			if (fx->fx_op == ELS_OP_ACC) {
677291a2b48SSukumar Swaminathan 				(void) emlxs_els_reply(port, &iocbq,
678291a2b48SSukumar Swaminathan 				    ELS_CMD_ACC, ELS_CMD_FLOGI, 0, 0);
679291a2b48SSukumar Swaminathan 
680e2ca2865SSukumar Swaminathan 			} else {	/* ELS_OP_LSRJT */
681291a2b48SSukumar Swaminathan 				(void) emlxs_els_reply(port, &iocbq,
682e2ca2865SSukumar Swaminathan 				    ELS_CMD_LS_RJT, ELS_CMD_FLOGI,
683e2ca2865SSukumar Swaminathan 				    fx->fx_rjt_reason, fx->fx_rjt_expl);
684291a2b48SSukumar Swaminathan 			}
685291a2b48SSukumar Swaminathan 		} else {
686291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
687e2ca2865SSukumar Swaminathan 			    "FLOGI: sid=%x xid=%x. "
688e2ca2865SSukumar Swaminathan 			    "fct_handle_rcvd_flogi failed. Rejecting.",
689e2ca2865SSukumar Swaminathan 			    fx->fx_sid, iocbq.iocb.ULPCONTEXT);
690291a2b48SSukumar Swaminathan 
691e2ca2865SSukumar Swaminathan 			(void) emlxs_els_reply(port, &iocbq,
692e2ca2865SSukumar Swaminathan 			    ELS_CMD_LS_RJT, ELS_CMD_FLOGI,
693e2ca2865SSukumar Swaminathan 			    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
694291a2b48SSukumar Swaminathan 		}
695291a2b48SSukumar Swaminathan 
696e2ca2865SSukumar Swaminathan 		return;
697291a2b48SSukumar Swaminathan 	}
698fcf3ce44SJohn Forte 
699e2ca2865SSukumar Swaminathan 	if (save) {
700e2ca2865SSukumar Swaminathan 		/* Save FLOGI for later */
701e2ca2865SSukumar Swaminathan 		bcopy(fx, &port->fx, sizeof (fct_flogi_xchg_t));
702e2ca2865SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
703291a2b48SSukumar Swaminathan 		return;
704fcf3ce44SJohn Forte 	}
705291a2b48SSukumar Swaminathan 
706e2ca2865SSukumar Swaminathan reject_it:
707291a2b48SSukumar Swaminathan 
708e2ca2865SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
709fcf3ce44SJohn Forte 
710e2ca2865SSukumar Swaminathan 	if (port->fct_flags & FCT_STATE_LINK_UP) {
711e2ca2865SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
712e2ca2865SSukumar Swaminathan 		    "FLOGI: sid=%x xid=%x. Stale. Rejecting.",
713e2ca2865SSukumar Swaminathan 		    fx->fx_sid, fx->rsvd2);
714fcf3ce44SJohn Forte 
715e2ca2865SSukumar Swaminathan 		bzero((uint8_t *)&iocbq, sizeof (IOCBQ));
716e2ca2865SSukumar Swaminathan 		iocbq.iocb.un.elsreq.remoteID = fx->fx_sid;
717e2ca2865SSukumar Swaminathan 		iocbq.iocb.un.elsreq.myID = fx->fx_did;
718e2ca2865SSukumar Swaminathan 		iocbq.iocb.ULPCONTEXT = fx->rsvd2;
719291a2b48SSukumar Swaminathan 
720e2ca2865SSukumar Swaminathan 		(void) emlxs_els_reply(port, &iocbq,
721e2ca2865SSukumar Swaminathan 		    ELS_CMD_LS_RJT, ELS_CMD_FLOGI,
722e2ca2865SSukumar Swaminathan 		    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
723fcf3ce44SJohn Forte 
724e2ca2865SSukumar Swaminathan 		/* If we have an FLOGI saved, try sending it now */
725e2ca2865SSukumar Swaminathan 		if (port->fx.fx_op) {
726e2ca2865SSukumar Swaminathan 			fx = NULL;
727e2ca2865SSukumar Swaminathan 			goto begin;
728e2ca2865SSukumar Swaminathan 		}
729291a2b48SSukumar Swaminathan 
730e2ca2865SSukumar Swaminathan 	} else {
731e2ca2865SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
732e2ca2865SSukumar Swaminathan 		    "FLOGI: sid=%x xid=%x. Link down. "
733e2ca2865SSukumar Swaminathan 		    "Dropping.",
734e2ca2865SSukumar Swaminathan 		    fx->fx_sid, fx->rsvd2);
735291a2b48SSukumar Swaminathan 	}
73682527734SSukumar Swaminathan 
737fcf3ce44SJohn Forte 	return;
738fcf3ce44SJohn Forte 
739e2ca2865SSukumar Swaminathan } /* emlxs_fct_handle_unsol_flogi() */
740fcf3ce44SJohn Forte 
741fcf3ce44SJohn Forte 
742fcf3ce44SJohn Forte /* This is called at port online and offline */
743fcf3ce44SJohn Forte static void
744fcf3ce44SJohn Forte emlxs_fct_unsol_flush(emlxs_port_t *port)
745fcf3ce44SJohn Forte {
746fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
747fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
748fcf3ce44SJohn Forte 	emlxs_buf_t *next;
749fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
75082527734SSukumar Swaminathan 	fct_status_t rval;
751e2ca2865SSukumar Swaminathan 	uint32_t cmd_code;
752fcf3ce44SJohn Forte 
753fcf3ce44SJohn Forte 	if (!port->fct_port) {
754fcf3ce44SJohn Forte 		return;
755fcf3ce44SJohn Forte 	}
756291a2b48SSukumar Swaminathan 
757e2ca2865SSukumar Swaminathan 	/* First handle any pending FLOGI */
758e2ca2865SSukumar Swaminathan 	emlxs_fct_handle_unsol_flogi(port, NULL, 0);
759291a2b48SSukumar Swaminathan 
760e2ca2865SSukumar Swaminathan 	/* Wait queue */
761fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
762fcf3ce44SJohn Forte 	cmd_sbp = port->fct_wait_head;
763fcf3ce44SJohn Forte 	port->fct_wait_head = NULL;
764fcf3ce44SJohn Forte 	port->fct_wait_tail = NULL;
765fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
766fcf3ce44SJohn Forte 
767291a2b48SSukumar Swaminathan 	/*
768291a2b48SSukumar Swaminathan 	 * Next process any outstanding ELS commands. It doesn't
769291a2b48SSukumar Swaminathan 	 * matter if the Link is up or not, always post them to FCT.
770291a2b48SSukumar Swaminathan 	 */
771fcf3ce44SJohn Forte 	while (cmd_sbp) {
772fcf3ce44SJohn Forte 		next = cmd_sbp->next;
773fcf3ce44SJohn Forte 		fct_cmd = cmd_sbp->fct_cmd;
774fcf3ce44SJohn Forte 
775e2ca2865SSukumar Swaminathan 		cmd_code = (fct_cmd->cmd_oxid << ELS_CMD_SHIFT);
776e2ca2865SSukumar Swaminathan 
77782527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
77882527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
77982527734SSukumar Swaminathan 		if (rval) {
78082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
781e2ca2865SSukumar Swaminathan 			    "emlxs_fct_unsol_flush: %s: sid=%x xid=%x "
782e2ca2865SSukumar Swaminathan 			    "Unable to reacquire fct_cmd.",
783e2ca2865SSukumar Swaminathan 			    emlxs_elscmd_xlate(cmd_code),
784e2ca2865SSukumar Swaminathan 			    fct_cmd->cmd_rxid, fct_cmd->cmd_rportid);
78582527734SSukumar Swaminathan 
78682527734SSukumar Swaminathan 			cmd_sbp = next;
78782527734SSukumar Swaminathan 			continue;
78882527734SSukumar Swaminathan 		}
78982527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
79082527734SSukumar Swaminathan 
791291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
792e2ca2865SSukumar Swaminathan 		    "Completing %s: sid=%x xid=%x %p",
793e2ca2865SSukumar Swaminathan 		    emlxs_elscmd_xlate(cmd_code),
794e2ca2865SSukumar Swaminathan 		    fct_cmd->cmd_rportid, fct_cmd->cmd_rxid,
795e2ca2865SSukumar Swaminathan 		    fct_cmd);
796fcf3ce44SJohn Forte 
79782527734SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
79882527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
799fcf3ce44SJohn Forte 
800fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
801291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
802291a2b48SSukumar Swaminathan 		    "fct_post_rcvd_cmd:2 %p: portid x%x", fct_cmd,
803291a2b48SSukumar Swaminathan 		    fct_cmd->cmd_lportid);
804291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
80582527734SSukumar Swaminathan 
806291a2b48SSukumar Swaminathan 		MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
807fcf3ce44SJohn Forte 
808fcf3ce44SJohn Forte 		cmd_sbp = next;
809fcf3ce44SJohn Forte 
81082527734SSukumar Swaminathan 	}	/* while () */
811fcf3ce44SJohn Forte 
812fcf3ce44SJohn Forte 	return;
813fcf3ce44SJohn Forte 
81482527734SSukumar Swaminathan } /* emlxs_fct_unsol_flush() */
815fcf3ce44SJohn Forte 
816fcf3ce44SJohn Forte 
817fcf3ce44SJohn Forte int
818fcf3ce44SJohn Forte emlxs_is_digit(uint8_t chr)
819fcf3ce44SJohn Forte {
820fcf3ce44SJohn Forte 	if ((chr >= '0') && (chr <= '9')) {
821fcf3ce44SJohn Forte 		return (1);
822fcf3ce44SJohn Forte 	}
823291a2b48SSukumar Swaminathan 
824fcf3ce44SJohn Forte 	return (0);
825fcf3ce44SJohn Forte 
82682527734SSukumar Swaminathan } /* emlxs_is_digit */
827fcf3ce44SJohn Forte 
828fcf3ce44SJohn Forte 
829fcf3ce44SJohn Forte /*
830fcf3ce44SJohn Forte  *   Convert an ASCII decimal numeric string to integer.
831fcf3ce44SJohn Forte  *   Negation character '-' is not handled.
832fcf3ce44SJohn Forte  */
833fcf3ce44SJohn Forte uint32_t
834fcf3ce44SJohn Forte emlxs_str_atoi(uint8_t *string)
835fcf3ce44SJohn Forte {
836fcf3ce44SJohn Forte 	uint32_t num = 0;
837fcf3ce44SJohn Forte 	int i = 0;
838fcf3ce44SJohn Forte 
839fcf3ce44SJohn Forte 	while (string[i]) {
840fcf3ce44SJohn Forte 		if (!emlxs_is_digit(string[i])) {
841fcf3ce44SJohn Forte 			return (num);
842fcf3ce44SJohn Forte 		}
843291a2b48SSukumar Swaminathan 
844fcf3ce44SJohn Forte 		num = num * 10 + (string[i++] - '0');
845fcf3ce44SJohn Forte 	}
846fcf3ce44SJohn Forte 
847fcf3ce44SJohn Forte 	return (num);
848fcf3ce44SJohn Forte 
84982527734SSukumar Swaminathan } /* emlxs_str_atoi() */
850fcf3ce44SJohn Forte 
851fcf3ce44SJohn Forte 
852fcf3ce44SJohn Forte static void
853fcf3ce44SJohn Forte emlxs_init_fct_bufpool(emlxs_hba_t *hba, char **arrayp, uint32_t cnt)
854fcf3ce44SJohn Forte {
855fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
856fcf3ce44SJohn Forte 	uint8_t *datap;
857fcf3ce44SJohn Forte 	int i;
858291a2b48SSukumar Swaminathan 	int bck;
859291a2b48SSukumar Swaminathan 	int nbufs;
860291a2b48SSukumar Swaminathan 	int maxbufs;
861291a2b48SSukumar Swaminathan 	int size;
862fcf3ce44SJohn Forte 
863fcf3ce44SJohn Forte 	bzero((uint8_t *)port->dmem_bucket, sizeof (port->dmem_bucket));
864291a2b48SSukumar Swaminathan 	bck = 0;
865fcf3ce44SJohn Forte 	for (i = 0; i < cnt; i++) {
866fcf3ce44SJohn Forte 		datap = (uint8_t *)arrayp[i];
867fcf3ce44SJohn Forte 		if (datap == 0)
868fcf3ce44SJohn Forte 			break;
869fcf3ce44SJohn Forte 
870fcf3ce44SJohn Forte 		while (*datap == ' ')	/* Skip spaces */
871fcf3ce44SJohn Forte 			datap++;
872fcf3ce44SJohn Forte 
873291a2b48SSukumar Swaminathan 		size = emlxs_str_atoi(datap);
874fcf3ce44SJohn Forte 
875fcf3ce44SJohn Forte 		while ((*datap != ':') && (*datap != 0))
876fcf3ce44SJohn Forte 			datap++;
877fcf3ce44SJohn Forte 		if (*datap == ':')	/* Skip past delimeter */
878fcf3ce44SJohn Forte 			datap++;
879fcf3ce44SJohn Forte 		while (*datap == ' ')	/* Skip spaces */
880fcf3ce44SJohn Forte 			datap++;
881fcf3ce44SJohn Forte 
882291a2b48SSukumar Swaminathan 		nbufs = emlxs_str_atoi(datap);
883fcf3ce44SJohn Forte 
884fcf3ce44SJohn Forte 		/* Check for a bad entry */
885291a2b48SSukumar Swaminathan 		if (!size || !nbufs) {
886fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
887291a2b48SSukumar Swaminathan 			    "Bad fct-bufpool entry %d %d", size, nbufs);
888291a2b48SSukumar Swaminathan 
889291a2b48SSukumar Swaminathan 			port->dmem_bucket[bck].dmem_buf_size = 0;
890291a2b48SSukumar Swaminathan 			port->dmem_bucket[bck].dmem_nbufs = 0;
891291a2b48SSukumar Swaminathan 			size = 0;
892291a2b48SSukumar Swaminathan 			nbufs = 0;
893291a2b48SSukumar Swaminathan 		}
894291a2b48SSukumar Swaminathan 
895291a2b48SSukumar Swaminathan 		while (nbufs) {
896291a2b48SSukumar Swaminathan 			port->dmem_bucket[bck].dmem_buf_size = size;
897291a2b48SSukumar Swaminathan 			port->dmem_bucket[bck].dmem_nbufs = nbufs;
898291a2b48SSukumar Swaminathan 
899291a2b48SSukumar Swaminathan 			/*
900291a2b48SSukumar Swaminathan 			 * We are not going to try to allocate a chunk
901291a2b48SSukumar Swaminathan 			 * of memory > FCT_DMEM_MAX_BUF_SEGMENT
902291a2b48SSukumar Swaminathan 			 * to accomidate the buffer pool of the
903291a2b48SSukumar Swaminathan 			 * requested size.
904291a2b48SSukumar Swaminathan 			 */
905291a2b48SSukumar Swaminathan 			maxbufs = (FCT_DMEM_MAX_BUF_SEGMENT / size);
906fcf3ce44SJohn Forte 
907291a2b48SSukumar Swaminathan 			if (nbufs > maxbufs) {
908291a2b48SSukumar Swaminathan 				port->dmem_bucket[bck].dmem_nbufs = maxbufs;
909291a2b48SSukumar Swaminathan 				nbufs -= maxbufs;
910291a2b48SSukumar Swaminathan 				bck++;
911291a2b48SSukumar Swaminathan 				if (bck >= FCT_MAX_BUCKETS)
912291a2b48SSukumar Swaminathan 					break;
913291a2b48SSukumar Swaminathan 			} else {
914291a2b48SSukumar Swaminathan 				bck++;
915291a2b48SSukumar Swaminathan 				nbufs = 0;
916291a2b48SSukumar Swaminathan 			}
917fcf3ce44SJohn Forte 		}
918291a2b48SSukumar Swaminathan 
919291a2b48SSukumar Swaminathan 		if (bck >= FCT_MAX_BUCKETS) {
920291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
921291a2b48SSukumar Swaminathan 			    "fct-bufpool entry %d %d Exceeds available buckets",
922291a2b48SSukumar Swaminathan 			    size, nbufs);
923fcf3ce44SJohn Forte 			break;
924291a2b48SSukumar Swaminathan 		}
925fcf3ce44SJohn Forte 	}
926fcf3ce44SJohn Forte }
927fcf3ce44SJohn Forte 
928fcf3ce44SJohn Forte 
929fcf3ce44SJohn Forte static void
930fcf3ce44SJohn Forte emlxs_fct_cfg_init(emlxs_hba_t *hba)
931fcf3ce44SJohn Forte {
932fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
933fcf3ce44SJohn Forte 	char **arrayp;
934fcf3ce44SJohn Forte 	uint32_t cnt;
935fcf3ce44SJohn Forte 	char buf[32];
936fcf3ce44SJohn Forte 	int status;
937fcf3ce44SJohn Forte 
938291a2b48SSukumar Swaminathan 	bzero((void *)buf, 32);
939fcf3ce44SJohn Forte 	cnt = 0;
940fcf3ce44SJohn Forte 	arrayp = NULL;
941fcf3ce44SJohn Forte 
942fcf3ce44SJohn Forte 	(void) sprintf(buf, "emlxs%d-fct-bufpool", ddi_get_instance(hba->dip));
943fcf3ce44SJohn Forte 	status = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
944fcf3ce44SJohn Forte 	    (DDI_PROP_DONTPASS), buf, &arrayp, &cnt);
945fcf3ce44SJohn Forte 
946fcf3ce44SJohn Forte 	if ((status == DDI_PROP_SUCCESS) && cnt && arrayp) {
947fcf3ce44SJohn Forte 		emlxs_init_fct_bufpool(hba, arrayp, cnt);
948fcf3ce44SJohn Forte 	} else {
949fcf3ce44SJohn Forte 		status = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
950fcf3ce44SJohn Forte 		    (DDI_PROP_DONTPASS), "fct-bufpool", &arrayp, &cnt);
951fcf3ce44SJohn Forte 
952fcf3ce44SJohn Forte 		if ((status == DDI_PROP_SUCCESS) && cnt && arrayp) {
953fcf3ce44SJohn Forte 			emlxs_init_fct_bufpool(hba, arrayp, cnt);
954fcf3ce44SJohn Forte 		} else {
955fcf3ce44SJohn Forte 			bzero((uint8_t *)port->dmem_bucket,
956fcf3ce44SJohn Forte 			    sizeof (port->dmem_bucket));
957fcf3ce44SJohn Forte 			port->dmem_bucket[0].dmem_buf_size = 512;
958fcf3ce44SJohn Forte 			port->dmem_bucket[0].dmem_nbufs = FCT_BUF_COUNT_512;
959291a2b48SSukumar Swaminathan 			port->dmem_bucket[1].dmem_buf_size = (2 * 65536);
960291a2b48SSukumar Swaminathan 			port->dmem_bucket[1].dmem_nbufs = FCT_BUF_COUNT_128K;
961fcf3ce44SJohn Forte 		}
962fcf3ce44SJohn Forte 	}
963fcf3ce44SJohn Forte 
964fcf3ce44SJohn Forte 	bzero((void *)buf, 32);
965fcf3ce44SJohn Forte 	cnt = 0;
966fcf3ce44SJohn Forte 
967291a2b48SSukumar Swaminathan 	/*
968291a2b48SSukumar Swaminathan 	 * 0 means use HBA throttle for target queue depth,
969291a2b48SSukumar Swaminathan 	 * non-0 value is the actual target queue depth,
970291a2b48SSukumar Swaminathan 	 * default is EMLXS_FCT_DFLT_QDEPTH.
971291a2b48SSukumar Swaminathan 	 */
972fcf3ce44SJohn Forte 	(void) sprintf(buf, "emlxs%d-fct-queue-depth",
973fcf3ce44SJohn Forte 	    ddi_get_instance(hba->dip));
974fcf3ce44SJohn Forte 	cnt = ddi_prop_get_int(DDI_DEV_T_ANY, hba->dip,
975291a2b48SSukumar Swaminathan 	    (DDI_PROP_DONTPASS), buf, EMLXS_FCT_DFLT_QDEPTH);
976fcf3ce44SJohn Forte 
977291a2b48SSukumar Swaminathan 	if ((cnt == DDI_PROP_NOT_FOUND) || (cnt == EMLXS_FCT_DFLT_QDEPTH)) {
978fcf3ce44SJohn Forte 		cnt = ddi_prop_get_int(DDI_DEV_T_ANY, hba->dip,
979291a2b48SSukumar Swaminathan 		    (DDI_PROP_DONTPASS), "fct-queue-depth",
980291a2b48SSukumar Swaminathan 		    EMLXS_FCT_DFLT_QDEPTH);
981fcf3ce44SJohn Forte 
982fcf3ce44SJohn Forte 		if (cnt == DDI_PROP_NOT_FOUND) {
983291a2b48SSukumar Swaminathan 			cnt = EMLXS_FCT_DFLT_QDEPTH;
984fcf3ce44SJohn Forte 		}
985fcf3ce44SJohn Forte 	}
986291a2b48SSukumar Swaminathan 
987fcf3ce44SJohn Forte 	port->fct_queue_depth = cnt;
988291a2b48SSukumar Swaminathan 
989291a2b48SSukumar Swaminathan #ifdef FCT_IO_TRACE
990291a2b48SSukumar Swaminathan 	port->iotrace_cnt = 1024;
991291a2b48SSukumar Swaminathan 	port->iotrace_index = 0;
992291a2b48SSukumar Swaminathan 	if (cnt)
993291a2b48SSukumar Swaminathan 		port->iotrace_cnt = (2 * cnt);
994291a2b48SSukumar Swaminathan 	port->iotrace =
995291a2b48SSukumar Swaminathan 	    kmem_zalloc(port->iotrace_cnt * sizeof (emlxs_iotrace_t),
996291a2b48SSukumar Swaminathan 	    KM_SLEEP);
99782527734SSukumar Swaminathan 
998291a2b48SSukumar Swaminathan 	mutex_init(&port->iotrace_mtx, NULL, MUTEX_DRIVER,
999291a2b48SSukumar Swaminathan 	    (void *)hba->intr_arg);
1000291a2b48SSukumar Swaminathan 	emlxs_iotrace = (uint8_t *)port->iotrace;
1001291a2b48SSukumar Swaminathan 	emlxs_iotrace_cnt = port->iotrace_cnt;
1002291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1003291a2b48SSukumar Swaminathan 	    "IOTRACE: init:%p cnt:%d", emlxs_iotrace, emlxs_iotrace_cnt);
1004291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1005291a2b48SSukumar Swaminathan 	    "FCT_ABORT_SUCCESS:%lx FCT_SUCCESS:%lx", FCT_ABORT_SUCCESS,
1006291a2b48SSukumar Swaminathan 	    FCT_SUCCESS);
1007291a2b48SSukumar Swaminathan #endif /* FCT_IO_TRACE */
1008fcf3ce44SJohn Forte 	return;
1009fcf3ce44SJohn Forte 
101082527734SSukumar Swaminathan } /* emlxs_fct_cfg_init() */
1011fcf3ce44SJohn Forte 
1012fcf3ce44SJohn Forte 
1013fcf3ce44SJohn Forte extern void
1014fcf3ce44SJohn Forte emlxs_fct_init(emlxs_hba_t *hba)
1015fcf3ce44SJohn Forte {
1016fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1017fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
1018fcf3ce44SJohn Forte 	emlxs_port_t *vport;
1019fcf3ce44SJohn Forte 	uint32_t i;
1020fcf3ce44SJohn Forte 
1021fcf3ce44SJohn Forte 	if (!hba->tgt_mode) {
1022fcf3ce44SJohn Forte 		return;
1023fcf3ce44SJohn Forte 	}
1024fcf3ce44SJohn Forte 
1025fcf3ce44SJohn Forte 	/* Check if COMSTAR is present */
1026fcf3ce44SJohn Forte 	if (((void *)MODSYM(stmf_alloc) == NULL) ||
1027291a2b48SSukumar Swaminathan 	    ((void *)MODSYM(fct_alloc) == NULL)) {
1028fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1029fcf3ce44SJohn Forte 		    "Comstar not present. Target mode disabled.");
1030fcf3ce44SJohn Forte 		goto failed;
1031fcf3ce44SJohn Forte 	}
1032291a2b48SSukumar Swaminathan 
1033fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1034fcf3ce44SJohn Forte 	    "Comstar present. Target mode enabled.");
1035fcf3ce44SJohn Forte 
1036fcf3ce44SJohn Forte 	if (cfg[CFG_NPIV_ENABLE].current) {
1037fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
1038fcf3ce44SJohn Forte 		    "enable-npiv: Not supported in target mode. Disabling.");
1039fcf3ce44SJohn Forte 
1040fcf3ce44SJohn Forte 		/* Temporary patch to disable npiv */
1041fcf3ce44SJohn Forte 		cfg[CFG_NPIV_ENABLE].current = 0;
1042fcf3ce44SJohn Forte 	}
1043fcf3ce44SJohn Forte 
1044fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
1045fcf3ce44SJohn Forte 	if (cfg[CFG_AUTH_ENABLE].current) {
1046fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
1047fcf3ce44SJohn Forte 		    "enable-auth: Not supported in target mode. Disabling.");
1048fcf3ce44SJohn Forte 
1049fcf3ce44SJohn Forte 		/* Temporary patch to disable auth */
1050fcf3ce44SJohn Forte 		cfg[CFG_AUTH_ENABLE].current = 0;
1051fcf3ce44SJohn Forte 	}
1052291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */
1053fcf3ce44SJohn Forte 
1054fcf3ce44SJohn Forte 	emlxs_fct_cfg_init(hba);
1055fcf3ce44SJohn Forte 	return;
1056fcf3ce44SJohn Forte 
1057fcf3ce44SJohn Forte failed:
1058fcf3ce44SJohn Forte 
1059fcf3ce44SJohn Forte 	hba->tgt_mode = 0;
1060fcf3ce44SJohn Forte 	for (i = 0; i < MAX_VPORTS; i++) {
1061fcf3ce44SJohn Forte 		vport = &VPORT(i);
1062fcf3ce44SJohn Forte 		vport->tgt_mode = 0;
1063fcf3ce44SJohn Forte 		vport->fct_flags = 0;
1064fcf3ce44SJohn Forte 	}
1065291a2b48SSukumar Swaminathan 
1066291a2b48SSukumar Swaminathan 	return;
1067291a2b48SSukumar Swaminathan 
106882527734SSukumar Swaminathan } /* emlxs_fct_init() */
1069fcf3ce44SJohn Forte 
1070fcf3ce44SJohn Forte 
1071fcf3ce44SJohn Forte extern void
1072fcf3ce44SJohn Forte emlxs_fct_attach(emlxs_hba_t *hba)
1073fcf3ce44SJohn Forte {
1074fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1075fcf3ce44SJohn Forte 	uint32_t vpi;
1076fcf3ce44SJohn Forte 
1077fcf3ce44SJohn Forte 	if (!hba->tgt_mode) {
1078fcf3ce44SJohn Forte 		return;
1079fcf3ce44SJohn Forte 	}
1080291a2b48SSukumar Swaminathan 
1081fcf3ce44SJohn Forte 	/* Bind the physical port */
1082fcf3ce44SJohn Forte 	emlxs_fct_bind_port(port);
1083fcf3ce44SJohn Forte 
1084fcf3ce44SJohn Forte 	/* Bind virtual ports */
1085fcf3ce44SJohn Forte 	if (hba->flag & FC_NPIV_ENABLED) {
108682527734SSukumar Swaminathan 		for (vpi = 1; vpi <= hba->vpi_high; vpi++) {
1087fcf3ce44SJohn Forte 			port = &VPORT(vpi);
1088fcf3ce44SJohn Forte 
1089fcf3ce44SJohn Forte 			if (!(port->flag & EMLXS_PORT_ENABLE)) {
1090fcf3ce44SJohn Forte 				continue;
1091fcf3ce44SJohn Forte 			}
1092291a2b48SSukumar Swaminathan 
1093fcf3ce44SJohn Forte 			emlxs_fct_bind_port(port);
1094fcf3ce44SJohn Forte 		}
1095fcf3ce44SJohn Forte 	}
1096291a2b48SSukumar Swaminathan 
1097fcf3ce44SJohn Forte 	return;
1098fcf3ce44SJohn Forte 
109982527734SSukumar Swaminathan } /* emlxs_fct_attach() */
1100fcf3ce44SJohn Forte 
1101fcf3ce44SJohn Forte 
1102fcf3ce44SJohn Forte extern void
1103fcf3ce44SJohn Forte emlxs_fct_detach(emlxs_hba_t *hba)
1104fcf3ce44SJohn Forte {
1105fcf3ce44SJohn Forte 	uint32_t i;
1106fcf3ce44SJohn Forte 	emlxs_port_t *vport;
1107fcf3ce44SJohn Forte 
1108fcf3ce44SJohn Forte 	if (hba->tgt_mode) {
1109fcf3ce44SJohn Forte 		for (i = 0; i < MAX_VPORTS; i++) {
1110fcf3ce44SJohn Forte 			vport = &VPORT(i);
1111fcf3ce44SJohn Forte 
1112fcf3ce44SJohn Forte 			if (!vport->tgt_mode) {
1113fcf3ce44SJohn Forte 				continue;
1114fcf3ce44SJohn Forte 			}
1115291a2b48SSukumar Swaminathan 
1116fcf3ce44SJohn Forte 			emlxs_fct_unbind_port(vport);
1117fcf3ce44SJohn Forte 			vport->tgt_mode = 0;
1118fcf3ce44SJohn Forte 		}
1119fcf3ce44SJohn Forte 
1120fcf3ce44SJohn Forte 
1121fcf3ce44SJohn Forte 		hba->tgt_mode = 0;
1122fcf3ce44SJohn Forte 	}
1123291a2b48SSukumar Swaminathan #ifdef FCT_IO_TRACE
1124291a2b48SSukumar Swaminathan 	{
1125291a2b48SSukumar Swaminathan 		emlxs_port_t *port = &PPORT;
1126291a2b48SSukumar Swaminathan 
1127291a2b48SSukumar Swaminathan 		mutex_destroy(&port->iotrace_mtx);
1128291a2b48SSukumar Swaminathan 		if (port->iotrace)
1129291a2b48SSukumar Swaminathan 			kmem_free(port->iotrace,
1130291a2b48SSukumar Swaminathan 			    (port->iotrace_cnt * sizeof (emlxs_iotrace_t)));
1131291a2b48SSukumar Swaminathan 		port->iotrace = NULL;
1132291a2b48SSukumar Swaminathan 	}
1133291a2b48SSukumar Swaminathan #endif /* FCT_IO_TRACE */
1134291a2b48SSukumar Swaminathan 
1135fcf3ce44SJohn Forte 	return;
1136fcf3ce44SJohn Forte 
113782527734SSukumar Swaminathan } /* emlxs_fct_detach() */
1138fcf3ce44SJohn Forte 
1139fcf3ce44SJohn Forte 
1140fcf3ce44SJohn Forte extern void
1141fcf3ce44SJohn Forte emlxs_fct_unbind_port(emlxs_port_t *port)
1142fcf3ce44SJohn Forte {
1143fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1144fcf3ce44SJohn Forte 	char node_name[32];
1145fcf3ce44SJohn Forte 
1146fcf3ce44SJohn Forte 	if (!port->tgt_mode) {
1147fcf3ce44SJohn Forte 		return;
1148fcf3ce44SJohn Forte 	}
1149291a2b48SSukumar Swaminathan 
1150fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
1151fcf3ce44SJohn Forte 	if (!(port->flag & EMLXS_PORT_BOUND)) {
1152fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1153fcf3ce44SJohn Forte 		return;
1154fcf3ce44SJohn Forte 	}
1155291a2b48SSukumar Swaminathan 
1156fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1157fcf3ce44SJohn Forte 	    "emlxs_fct_unbind_port: port=%d", port->vpi);
1158fcf3ce44SJohn Forte 
1159fcf3ce44SJohn Forte 	/* Destroy & flush all port nodes, if they exist */
1160fcf3ce44SJohn Forte 	if (port->node_count) {
116182527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
116282527734SSukumar Swaminathan 			(void) emlxs_sli4_unreg_all_rpi_by_port(port);
116382527734SSukumar Swaminathan 		} else {
116482527734SSukumar Swaminathan 			(void) emlxs_mb_unreg_rpi(port, 0xffff, 0, 0,
116582527734SSukumar Swaminathan 			    0);
116682527734SSukumar Swaminathan 		}
1167fcf3ce44SJohn Forte 	}
1168291a2b48SSukumar Swaminathan 
1169fcf3ce44SJohn Forte 	port->flag &= ~EMLXS_PORT_BOUND;
1170fcf3ce44SJohn Forte 	hba->num_of_ports--;
1171fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
1172fcf3ce44SJohn Forte 
1173fcf3ce44SJohn Forte 	if (port->fct_port) {
1174fcf3ce44SJohn Forte 		emlxs_fct_link_down(port);
1175fcf3ce44SJohn Forte 		emlxs_fct_unsol_flush(port);
1176fcf3ce44SJohn Forte 
1177fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1178fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1179fcf3ce44SJohn Forte 		    "fct_deregister_local_port %p", port->fct_port);
1180291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1181fcf3ce44SJohn Forte 		MODSYM(fct_deregister_local_port) (port->fct_port);
1182fcf3ce44SJohn Forte 
1183fcf3ce44SJohn Forte 		if (port->fct_port->port_fds) {
1184fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1185fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1186fcf3ce44SJohn Forte 			    "fct_free:3 %p", port->fct_port->port_fds);
1187291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1188fcf3ce44SJohn Forte 			MODSYM(fct_free) (port->fct_port->port_fds);
1189fcf3ce44SJohn Forte 			port->fct_port->port_fds = NULL;
1190fcf3ce44SJohn Forte 		}
1191fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1192fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1193fcf3ce44SJohn Forte 		    "fct_free:4 %p", port->fct_port);
1194291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1195fcf3ce44SJohn Forte 		MODSYM(fct_free) (port->fct_port);
1196fcf3ce44SJohn Forte 		port->fct_port = NULL;
1197fcf3ce44SJohn Forte 		port->fct_flags = 0;
1198fcf3ce44SJohn Forte 	}
1199291a2b48SSukumar Swaminathan 
1200fcf3ce44SJohn Forte 	if (port->port_provider) {
1201fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1202fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1203291a2b48SSukumar Swaminathan 		    "stmf_deregister_port_provider:1 %p",
1204291a2b48SSukumar Swaminathan 		    port->port_provider);
1205291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1206fcf3ce44SJohn Forte 		MODSYM(stmf_deregister_port_provider) (port->port_provider);
1207fcf3ce44SJohn Forte 
1208fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1209fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1210fcf3ce44SJohn Forte 		    "stmf_free:1 %p", port->port_provider);
1211291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1212fcf3ce44SJohn Forte 		MODSYM(stmf_free) (port->port_provider);
1213fcf3ce44SJohn Forte 		port->port_provider = NULL;
1214fcf3ce44SJohn Forte 	}
1215291a2b48SSukumar Swaminathan 
1216fcf3ce44SJohn Forte 	if (port->dmem_bucket) {
1217fcf3ce44SJohn Forte 		emlxs_fct_dmem_fini(port);
1218fcf3ce44SJohn Forte 	}
1219291a2b48SSukumar Swaminathan 
1220fcf3ce44SJohn Forte 	(void) sprintf(node_name, "%d,%d:SFCT", hba->ddiinst, port->vpi);
1221fcf3ce44SJohn Forte 	(void) ddi_remove_minor_node(hba->dip, node_name);
1222fcf3ce44SJohn Forte 
1223fcf3ce44SJohn Forte 	return;
1224fcf3ce44SJohn Forte 
122582527734SSukumar Swaminathan } /* emlxs_fct_unbind_port() */
1226fcf3ce44SJohn Forte 
1227fcf3ce44SJohn Forte 
1228fcf3ce44SJohn Forte extern void
1229fcf3ce44SJohn Forte emlxs_fct_bind_port(emlxs_port_t *port)
1230fcf3ce44SJohn Forte {
1231fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1232fcf3ce44SJohn Forte 	fct_local_port_t *fct_port;
1233fcf3ce44SJohn Forte 	uint32_t flag = 0;
1234fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
1235fcf3ce44SJohn Forte 	fct_dbuf_store_t *fds;
1236fcf3ce44SJohn Forte 	char node_name[32];
123782527734SSukumar Swaminathan 	uint8_t *bptr;
1238fcf3ce44SJohn Forte 
1239fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
1240fcf3ce44SJohn Forte 
1241fcf3ce44SJohn Forte 	if (!hba->tgt_mode || !port->tgt_mode) {
1242fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1243fcf3ce44SJohn Forte 		return;
1244fcf3ce44SJohn Forte 	}
1245291a2b48SSukumar Swaminathan 
1246fcf3ce44SJohn Forte 	if (port->flag & EMLXS_PORT_BOUND) {
1247fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1248fcf3ce44SJohn Forte 		return;
1249fcf3ce44SJohn Forte 	}
1250291a2b48SSukumar Swaminathan 
1251fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1252fcf3ce44SJohn Forte 	    "emlxs_fct_bind_port: port=%d", port->vpi);
1253fcf3ce44SJohn Forte 
1254fcf3ce44SJohn Forte 	/* Perform generic port initialization */
1255fcf3ce44SJohn Forte 	emlxs_port_init(port);
1256fcf3ce44SJohn Forte 
1257fcf3ce44SJohn Forte 	if (port->vpi == 0) {
1258fcf3ce44SJohn Forte 		(void) sprintf(port->cfd_name, "%s%d", DRIVER_NAME,
1259fcf3ce44SJohn Forte 		    hba->ddiinst);
1260fcf3ce44SJohn Forte 	} else {
1261fcf3ce44SJohn Forte 		(void) sprintf(port->cfd_name, "%s%d.%d", DRIVER_NAME,
1262fcf3ce44SJohn Forte 		    hba->ddiinst, port->vpi);
1263fcf3ce44SJohn Forte 	}
1264fcf3ce44SJohn Forte 
1265fcf3ce44SJohn Forte 	if (emlxs_fct_dmem_init(port) != FCT_SUCCESS) {
1266fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1267fcf3ce44SJohn Forte 		    "emlxs_fct_bind_port: Unable to allocate fct memory.");
1268fcf3ce44SJohn Forte 		goto failed;
1269fcf3ce44SJohn Forte 	}
1270fcf3ce44SJohn Forte 	flag |= 0x00000001;
1271fcf3ce44SJohn Forte 
1272291a2b48SSukumar Swaminathan 	port->port_provider =
1273291a2b48SSukumar Swaminathan 	    (stmf_port_provider_t *)
1274fcf3ce44SJohn Forte 	    MODSYM(stmf_alloc) (STMF_STRUCT_PORT_PROVIDER, 0, 0);
1275fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1276fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1277fcf3ce44SJohn Forte 	    "stmf_alloc port_provider %p", port->port_provider);
1278291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1279fcf3ce44SJohn Forte 
1280fcf3ce44SJohn Forte 	if (port->port_provider == NULL) {
1281fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1282291a2b48SSukumar Swaminathan 		    "emlxs_fct_bind_port: Unable to allocate port provider.");
1283fcf3ce44SJohn Forte 		goto failed;
1284fcf3ce44SJohn Forte 	}
1285fcf3ce44SJohn Forte 	flag |= 0x00000002;
1286fcf3ce44SJohn Forte 
1287fcf3ce44SJohn Forte 	port->port_provider->pp_portif_rev = PORTIF_REV_1;
1288fcf3ce44SJohn Forte 	port->port_provider->pp_name = port->cfd_name;
1289fcf3ce44SJohn Forte 	port->port_provider->pp_provider_private = port;
1290fcf3ce44SJohn Forte 
1291fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1292fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1293fcf3ce44SJohn Forte 	    "stmf_register_port_provider %p", port->port_provider);
1294291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1295fcf3ce44SJohn Forte 	/* register port provider with framework */
1296291a2b48SSukumar Swaminathan 	if (MODSYM(stmf_register_port_provider) (port->port_provider) !=
1297291a2b48SSukumar Swaminathan 	    STMF_SUCCESS) {
1298fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1299291a2b48SSukumar Swaminathan 		    "emlxs_fct_bind_port: Unable to register port provider.");
1300fcf3ce44SJohn Forte 		goto failed;
1301fcf3ce44SJohn Forte 	}
1302fcf3ce44SJohn Forte 	flag |= 0x00000004;
1303fcf3ce44SJohn Forte 
1304291a2b48SSukumar Swaminathan 	port->fct_port =
1305291a2b48SSukumar Swaminathan 	    (fct_local_port_t *)MODSYM(fct_alloc) (FCT_STRUCT_LOCAL_PORT, 0,
1306291a2b48SSukumar Swaminathan 	    0);
1307fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1308fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1309fcf3ce44SJohn Forte 	    "fct_alloc fct_port %p", port->fct_port);
1310291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1311fcf3ce44SJohn Forte 
1312fcf3ce44SJohn Forte 	if (port->fct_port == NULL) {
1313fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1314fcf3ce44SJohn Forte 		    "emlxs_fct_bind_port: Unable to allocate fct port.");
1315fcf3ce44SJohn Forte 		goto failed;
1316fcf3ce44SJohn Forte 	}
1317fcf3ce44SJohn Forte 	flag |= 0x00000008;
1318fcf3ce44SJohn Forte 
1319291a2b48SSukumar Swaminathan 	port->fct_port->port_fds =
1320291a2b48SSukumar Swaminathan 	    (fct_dbuf_store_t *)MODSYM(fct_alloc) (FCT_STRUCT_DBUF_STORE, 0,
1321291a2b48SSukumar Swaminathan 	    0);
1322fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1323fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1324fcf3ce44SJohn Forte 	    "fct_alloc port_fds %p", port->fct_port->port_fds);
1325291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1326fcf3ce44SJohn Forte 
1327fcf3ce44SJohn Forte 	if (port->fct_port->port_fds == NULL) {
1328fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1329fcf3ce44SJohn Forte 		    "emlxs_fct_bind_port: Unable to allocate dbuf store.");
1330fcf3ce44SJohn Forte 		goto failed;
1331fcf3ce44SJohn Forte 	}
1332fcf3ce44SJohn Forte 	flag |= 0x00000010;
1333fcf3ce44SJohn Forte 
1334fcf3ce44SJohn Forte 	(void) sprintf(node_name, "%d,%d:SFCT", hba->ddiinst, port->vpi);
1335291a2b48SSukumar Swaminathan 	if (ddi_create_minor_node(hba->dip, node_name, S_IFCHR, hba->ddiinst,
1336291a2b48SSukumar Swaminathan 	    NULL, 0) == DDI_FAILURE) {
1337fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1338fcf3ce44SJohn Forte 		    "Unable to create SFCT device node.");
1339fcf3ce44SJohn Forte 		goto failed;
1340fcf3ce44SJohn Forte 	}
1341fcf3ce44SJohn Forte 	flag |= 0x00000020;
1342fcf3ce44SJohn Forte 
1343fcf3ce44SJohn Forte 	/* Intialize */
1344fcf3ce44SJohn Forte 	fct_port = port->fct_port;
1345162fafd3Sallan 	fct_port->port_fca_version = FCT_FCA_MODREV_1;
1346fcf3ce44SJohn Forte 	fct_port->port_fca_private = port;
1347fcf3ce44SJohn Forte 	fct_port->port_fca_abort_timeout = 30 * 1000;	/* 30 seconds */
1348fcf3ce44SJohn Forte 
1349fcf3ce44SJohn Forte 	bcopy((uint8_t *)&port->wwpn, (uint8_t *)fct_port->port_pwwn, 8);
1350fcf3ce44SJohn Forte 	bcopy((uint8_t *)&port->wwnn, (uint8_t *)fct_port->port_nwwn, 8);
1351fcf3ce44SJohn Forte 
135282527734SSukumar Swaminathan 	bptr = (uint8_t *)&port->wwnn;
135382527734SSukumar Swaminathan 	(void) sprintf(fct_port->port_nwwn_str,
135482527734SSukumar Swaminathan 	    "%02x%02x%02x%02x%02x%02x%02x%02x",
135582527734SSukumar Swaminathan 	    bptr[0], bptr[1], bptr[2], bptr[3],
135682527734SSukumar Swaminathan 	    bptr[4], bptr[5], bptr[6], bptr[7]);
135782527734SSukumar Swaminathan 
135882527734SSukumar Swaminathan 	bptr = (uint8_t *)&port->wwpn;
135982527734SSukumar Swaminathan 	(void) sprintf(fct_port->port_pwwn_str,
136082527734SSukumar Swaminathan 	    "%02x%02x%02x%02x%02x%02x%02x%02x",
136182527734SSukumar Swaminathan 	    bptr[0], bptr[1], bptr[2], bptr[3],
136282527734SSukumar Swaminathan 	    bptr[4], bptr[5], bptr[6], bptr[7]);
136382527734SSukumar Swaminathan 
1364fcf3ce44SJohn Forte 	fct_port->port_sym_node_name = port->snn;
1365fcf3ce44SJohn Forte 	fct_port->port_sym_port_name = port->spn;
1366fcf3ce44SJohn Forte 	fct_port->port_hard_address = cfg[CFG_ASSIGN_ALPA].current;
1367fcf3ce44SJohn Forte 	fct_port->port_default_alias = port->cfd_name;
1368fcf3ce44SJohn Forte 	fct_port->port_pp = port->port_provider;
1369fcf3ce44SJohn Forte 	fct_port->port_max_logins = hba->max_nodes;
1370fcf3ce44SJohn Forte 
1371291a2b48SSukumar Swaminathan 	if ((port->fct_queue_depth) &&
1372291a2b48SSukumar Swaminathan 	    (port->fct_queue_depth < hba->io_throttle)) {
1373fcf3ce44SJohn Forte 		fct_port->port_max_xchges = port->fct_queue_depth;
1374fcf3ce44SJohn Forte 	} else {
1375fcf3ce44SJohn Forte 		fct_port->port_max_xchges = hba->io_throttle;
1376fcf3ce44SJohn Forte 	}
1377fcf3ce44SJohn Forte 
1378fcf3ce44SJohn Forte 	fct_port->port_fca_fcp_cmd_size = sizeof (emlxs_buf_t);
1379fcf3ce44SJohn Forte 	fct_port->port_fca_rp_private_size = sizeof (uintptr_t);
1380fcf3ce44SJohn Forte 	fct_port->port_fca_sol_els_private_size = sizeof (emlxs_buf_t);
1381fcf3ce44SJohn Forte 	fct_port->port_fca_sol_ct_private_size = sizeof (emlxs_buf_t);
1382fcf3ce44SJohn Forte 	fct_port->port_get_link_info = emlxs_fct_get_link_info;
1383fcf3ce44SJohn Forte 	fct_port->port_register_remote_port = emlxs_fct_register_remote_port;
1384fcf3ce44SJohn Forte 	fct_port->port_deregister_remote_port =
1385fcf3ce44SJohn Forte 	    emlxs_fct_deregister_remote_port;
1386fcf3ce44SJohn Forte 	fct_port->port_send_cmd = emlxs_fct_send_cmd;
1387fcf3ce44SJohn Forte 	fct_port->port_xfer_scsi_data = emlxs_fct_send_fcp_data;
1388fcf3ce44SJohn Forte 	fct_port->port_send_cmd_response = emlxs_fct_send_cmd_rsp;
1389fcf3ce44SJohn Forte 	fct_port->port_abort_cmd = emlxs_fct_abort;
1390fcf3ce44SJohn Forte 	fct_port->port_ctl = emlxs_fct_ctl;
139182527734SSukumar Swaminathan 	fct_port->port_flogi_xchg = emlxs_fct_flogi_xchg;
139282527734SSukumar Swaminathan 	fct_port->port_populate_hba_details = emlxs_fct_populate_hba_details;
139382527734SSukumar Swaminathan 	fct_port->port_info = emlxs_fct_port_info;
1394fcf3ce44SJohn Forte 
1395fcf3ce44SJohn Forte 	fds = port->fct_port->port_fds;
1396fcf3ce44SJohn Forte 	fds->fds_fca_private = port;
1397fcf3ce44SJohn Forte 	fds->fds_alloc_data_buf = emlxs_fct_dbuf_alloc;
1398fcf3ce44SJohn Forte 	fds->fds_free_data_buf = emlxs_fct_dbuf_free;
1399fcf3ce44SJohn Forte 
1400fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1401fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1402fcf3ce44SJohn Forte 	    "fct_register_local_port %p", fct_port);
1403291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1404fcf3ce44SJohn Forte 	/* register this local port with the fct module */
1405fcf3ce44SJohn Forte 	if (MODSYM(fct_register_local_port) (fct_port) != FCT_SUCCESS) {
1406fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1407fcf3ce44SJohn Forte 		    "emlxs_fct_bind_port: Unable to register fct port.");
1408fcf3ce44SJohn Forte 		goto failed;
1409fcf3ce44SJohn Forte 	}
1410291a2b48SSukumar Swaminathan 
1411fcf3ce44SJohn Forte 	/* Set the bound flag */
1412fcf3ce44SJohn Forte 	port->flag |= EMLXS_PORT_BOUND;
1413fcf3ce44SJohn Forte 	hba->num_of_ports++;
1414fcf3ce44SJohn Forte 
1415fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
1416fcf3ce44SJohn Forte 
1417fcf3ce44SJohn Forte 	return;
1418fcf3ce44SJohn Forte 
1419fcf3ce44SJohn Forte failed:
1420fcf3ce44SJohn Forte 
1421fcf3ce44SJohn Forte 	if (flag & 0x20) {
1422fcf3ce44SJohn Forte 		(void) ddi_remove_minor_node(hba->dip, node_name);
1423fcf3ce44SJohn Forte 	}
1424291a2b48SSukumar Swaminathan 
1425fcf3ce44SJohn Forte 	if (flag & 0x10) {
1426fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1427fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1428fcf3ce44SJohn Forte 		    "fct_free:5 %p", port->fct_port->port_fds);
1429291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1430fcf3ce44SJohn Forte 		MODSYM(fct_free) (port->fct_port->port_fds);
1431fcf3ce44SJohn Forte 		port->fct_port->port_fds = NULL;
1432fcf3ce44SJohn Forte 	}
1433291a2b48SSukumar Swaminathan 
1434fcf3ce44SJohn Forte 	if (flag & 0x8) {
1435fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1436fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1437fcf3ce44SJohn Forte 		    "fct_free:6 %p", port->fct_port);
1438291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1439fcf3ce44SJohn Forte 		MODSYM(fct_free) (port->fct_port);
1440fcf3ce44SJohn Forte 		port->fct_port = NULL;
1441fcf3ce44SJohn Forte 		port->fct_flags = 0;
1442fcf3ce44SJohn Forte 	}
1443291a2b48SSukumar Swaminathan 
1444fcf3ce44SJohn Forte 	if (flag & 0x4) {
1445fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1446fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1447291a2b48SSukumar Swaminathan 		    "stmf_deregister_port_provider:2 %p",
1448291a2b48SSukumar Swaminathan 		    port->port_provider);
1449291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1450fcf3ce44SJohn Forte 		MODSYM(stmf_deregister_port_provider) (port->port_provider);
1451fcf3ce44SJohn Forte 	}
1452291a2b48SSukumar Swaminathan 
1453fcf3ce44SJohn Forte 	if (flag & 0x2) {
1454fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1455fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1456fcf3ce44SJohn Forte 		    "stmf_free:2 %p", port->port_provider);
1457291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1458fcf3ce44SJohn Forte 		MODSYM(stmf_free) (port->port_provider);
1459fcf3ce44SJohn Forte 		port->port_provider = NULL;
1460fcf3ce44SJohn Forte 	}
1461291a2b48SSukumar Swaminathan 
1462fcf3ce44SJohn Forte 	if (flag & 0x1) {
1463fcf3ce44SJohn Forte 		emlxs_fct_dmem_fini(port);
1464fcf3ce44SJohn Forte 	}
1465291a2b48SSukumar Swaminathan 
1466fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1467fcf3ce44SJohn Forte 	    "Target mode disabled.");
1468fcf3ce44SJohn Forte 
1469fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
1470fcf3ce44SJohn Forte 
1471fcf3ce44SJohn Forte 	return;
1472fcf3ce44SJohn Forte 
147382527734SSukumar Swaminathan } /* emlxs_fct_bind_port() */
147482527734SSukumar Swaminathan 
147582527734SSukumar Swaminathan 
147682527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
147782527734SSukumar Swaminathan /*ARGSUSED*/
147882527734SSukumar Swaminathan static fct_status_t
147982527734SSukumar Swaminathan emlxs_fct_port_info(uint32_t cmd, fct_local_port_t *fct_port, void *arg,
148082527734SSukumar Swaminathan     uint8_t *buffer, uint32_t *size)
148182527734SSukumar Swaminathan {
148282527734SSukumar Swaminathan 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
148382527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
148482527734SSukumar Swaminathan 	fct_status_t rval = FCT_SUCCESS;
148582527734SSukumar Swaminathan 	fct_port_link_status_t *link_status;
148682527734SSukumar Swaminathan 	MAILBOX *mb;
148782527734SSukumar Swaminathan 	MAILBOXQ *mbq;
148882527734SSukumar Swaminathan 
148982527734SSukumar Swaminathan 	switch (cmd) {
149082527734SSukumar Swaminathan 	case FC_TGT_PORT_RLS:
149182527734SSukumar Swaminathan 		bzero(buffer, *size);
149282527734SSukumar Swaminathan 
149382527734SSukumar Swaminathan 		if ((*size) < sizeof (fct_port_link_status_t)) {
149482527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
149582527734SSukumar Swaminathan 			    "FC_TGT_PORT_RLS: Buffer too small. %d < %d",
149682527734SSukumar Swaminathan 			    *size, sizeof (fct_port_link_status_t));
149782527734SSukumar Swaminathan 
149882527734SSukumar Swaminathan 			rval = FCT_FAILURE;
149982527734SSukumar Swaminathan 			break;
150082527734SSukumar Swaminathan 		}
150182527734SSukumar Swaminathan 
150282527734SSukumar Swaminathan 		if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) {
150382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
150482527734SSukumar Swaminathan 			    "FC_TGT_PORT_RLS: Unable to allocate mailbox.");
150582527734SSukumar Swaminathan 
150682527734SSukumar Swaminathan 			rval = FCT_ALLOC_FAILURE;
150782527734SSukumar Swaminathan 			break;
150882527734SSukumar Swaminathan 		}
150982527734SSukumar Swaminathan 		mb = (MAILBOX *)mbq;
151082527734SSukumar Swaminathan 
151182527734SSukumar Swaminathan 		emlxs_mb_read_lnk_stat(hba, mbq);
151282527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0)
151382527734SSukumar Swaminathan 		    != MBX_SUCCESS) {
151482527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
151582527734SSukumar Swaminathan 			    "FC_TGT_PORT_RLS: Unable to send request.");
151682527734SSukumar Swaminathan 
151782527734SSukumar Swaminathan 			rval = FCT_BUSY;
151882527734SSukumar Swaminathan 		} else {
151982527734SSukumar Swaminathan 			link_status = (fct_port_link_status_t *)buffer;
152082527734SSukumar Swaminathan 			link_status->LinkFailureCount =
152182527734SSukumar Swaminathan 			    mb->un.varRdLnk.linkFailureCnt;
152282527734SSukumar Swaminathan 			link_status->LossOfSyncCount =
152382527734SSukumar Swaminathan 			    mb->un.varRdLnk.lossSyncCnt;
152482527734SSukumar Swaminathan 			link_status->LossOfSignalsCount =
152582527734SSukumar Swaminathan 			    mb->un.varRdLnk.lossSignalCnt;
152682527734SSukumar Swaminathan 			link_status->PrimitiveSeqProtocolErrorCount =
152782527734SSukumar Swaminathan 			    mb->un.varRdLnk.primSeqErrCnt;
152882527734SSukumar Swaminathan 			link_status->InvalidTransmissionWordCount =
152982527734SSukumar Swaminathan 			    mb->un.varRdLnk.invalidXmitWord;
153082527734SSukumar Swaminathan 			link_status->InvalidCRCCount =
153182527734SSukumar Swaminathan 			    mb->un.varRdLnk.crcCnt;
153282527734SSukumar Swaminathan 		}
153382527734SSukumar Swaminathan 
153482527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
153582527734SSukumar Swaminathan 		break;
153682527734SSukumar Swaminathan 
153782527734SSukumar Swaminathan 	default:
153882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
153982527734SSukumar Swaminathan 		    "emlxs_fct_port_info: Invalid request. cmd=%x",
154082527734SSukumar Swaminathan 		    cmd);
154182527734SSukumar Swaminathan 
154282527734SSukumar Swaminathan 		rval = FCT_FAILURE;
154382527734SSukumar Swaminathan 		break;
154482527734SSukumar Swaminathan 
154582527734SSukumar Swaminathan 	}
1546fcf3ce44SJohn Forte 
154782527734SSukumar Swaminathan 	return (rval);
154882527734SSukumar Swaminathan 
154982527734SSukumar Swaminathan } /* emlxs_fct_port_info() */
1550fcf3ce44SJohn Forte 
155182527734SSukumar Swaminathan 
155282527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1553fcf3ce44SJohn Forte static void
155482527734SSukumar Swaminathan emlxs_fct_populate_hba_details(fct_local_port_t *fct_port,
1555fcf3ce44SJohn Forte     fct_port_attrs_t *port_attrs)
1556fcf3ce44SJohn Forte {
1557fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1558fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1559fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd = &VPD;
1560fcf3ce44SJohn Forte 
1561fcf3ce44SJohn Forte 	(void) strcpy(port_attrs->manufacturer, "Emulex");
1562fcf3ce44SJohn Forte 	(void) strcpy(port_attrs->serial_number, vpd->serial_num);
1563fcf3ce44SJohn Forte 	(void) strcpy(port_attrs->model, hba->model_info.model);
1564fcf3ce44SJohn Forte 	(void) strcpy(port_attrs->model_description,
1565fcf3ce44SJohn Forte 	    hba->model_info.model_desc);
1566fcf3ce44SJohn Forte 	(void) sprintf(port_attrs->hardware_version, "%x", vpd->biuRev);
1567fcf3ce44SJohn Forte 	(void) sprintf(port_attrs->driver_version, "%s (%s)", emlxs_version,
1568fcf3ce44SJohn Forte 	    emlxs_revision);
1569fcf3ce44SJohn Forte 	(void) strcpy(port_attrs->option_rom_version, vpd->fcode_version);
1570fcf3ce44SJohn Forte 	(void) sprintf(port_attrs->firmware_version, "%s (%s)", vpd->fw_version,
1571fcf3ce44SJohn Forte 	    vpd->fw_label);
1572fcf3ce44SJohn Forte 	(void) strcpy(port_attrs->driver_name, DRIVER_NAME);
1573fcf3ce44SJohn Forte 	port_attrs->vendor_specific_id =
1574fcf3ce44SJohn Forte 	    ((hba->model_info.device_id << 16) | PCI_VENDOR_ID_EMULEX);
157582527734SSukumar Swaminathan 	port_attrs->supported_cos = LE_SWAP32(FC_NS_CLASS3);
1576fcf3ce44SJohn Forte 
1577fcf3ce44SJohn Forte 	port_attrs->max_frame_size = FF_FRAME_SIZE;
1578fcf3ce44SJohn Forte 
1579fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
1580291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_10G;
1581fcf3ce44SJohn Forte 	}
1582fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
1583291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_8G;
1584fcf3ce44SJohn Forte 	}
1585fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
1586291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_4G;
1587fcf3ce44SJohn Forte 	}
1588fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
1589291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_2G;
1590fcf3ce44SJohn Forte 	}
1591fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
1592291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_1G;
1593fcf3ce44SJohn Forte 	}
1594291a2b48SSukumar Swaminathan 
1595fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1596fcf3ce44SJohn Forte 	    "Port attr: manufacturer       = %s", port_attrs->manufacturer);
1597fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1598fcf3ce44SJohn Forte 	    "Port attr: serial_num         = %s", port_attrs->serial_number);
1599fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1600fcf3ce44SJohn Forte 	    "Port attr: model              = %s", port_attrs->model);
1601fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1602fcf3ce44SJohn Forte 	    "Port attr: model_description  = %s",
1603fcf3ce44SJohn Forte 	    port_attrs->model_description);
1604fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1605291a2b48SSukumar Swaminathan 	    "Port attr: hardware_version   = %s",
1606291a2b48SSukumar Swaminathan 	    port_attrs->hardware_version);
1607fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1608fcf3ce44SJohn Forte 	    "Port attr: driver_version     = %s", port_attrs->driver_version);
1609fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1610fcf3ce44SJohn Forte 	    "Port attr: option_rom_version = %s",
1611fcf3ce44SJohn Forte 	    port_attrs->option_rom_version);
1612fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1613291a2b48SSukumar Swaminathan 	    "Port attr: firmware_version   = %s",
1614291a2b48SSukumar Swaminathan 	    port_attrs->firmware_version);
1615fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1616fcf3ce44SJohn Forte 	    "Port attr: driver_name        = %s", port_attrs->driver_name);
1617fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1618fcf3ce44SJohn Forte 	    "Port attr: vendor_specific_id = 0x%x",
1619fcf3ce44SJohn Forte 	    port_attrs->vendor_specific_id);
1620fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1621291a2b48SSukumar Swaminathan 	    "Port attr: supported_cos      = 0x%x",
1622291a2b48SSukumar Swaminathan 	    port_attrs->supported_cos);
1623fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1624fcf3ce44SJohn Forte 	    "Port attr: supported_speed    = 0x%x",
1625fcf3ce44SJohn Forte 	    port_attrs->supported_speed);
1626fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1627291a2b48SSukumar Swaminathan 	    "Port attr: max_frame_size     = 0x%x",
1628291a2b48SSukumar Swaminathan 	    port_attrs->max_frame_size);
1629fcf3ce44SJohn Forte 
1630fcf3ce44SJohn Forte 	return;
1631fcf3ce44SJohn Forte 
163282527734SSukumar Swaminathan } /* emlxs_fct_populate_hba_details() */
1633fcf3ce44SJohn Forte 
1634fcf3ce44SJohn Forte 
163582527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1636fcf3ce44SJohn Forte /* ARGSUSED */
1637fcf3ce44SJohn Forte static void
1638fcf3ce44SJohn Forte emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg)
1639fcf3ce44SJohn Forte {
1640fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1641fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1642fcf3ce44SJohn Forte 	stmf_change_status_t st;
1643fcf3ce44SJohn Forte 
1644fcf3ce44SJohn Forte 	st.st_completion_status = FCT_SUCCESS;
1645fcf3ce44SJohn Forte 	st.st_additional_info = NULL;
1646fcf3ce44SJohn Forte 
1647fcf3ce44SJohn Forte 	switch (cmd) {
1648fcf3ce44SJohn Forte 	case FCT_CMD_PORT_ONLINE:
1649fcf3ce44SJohn Forte 		/* If the HBA is offline, we cannot bring the tgtport online */
1650fcf3ce44SJohn Forte 		if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) {
1651fcf3ce44SJohn Forte 			st.st_completion_status = FCT_FAILURE;
1652fcf3ce44SJohn Forte 			MODSYM(fct_ctl) (fct_port->port_lport,
1653fcf3ce44SJohn Forte 			    FCT_CMD_PORT_ONLINE_COMPLETE, &st);
1654fcf3ce44SJohn Forte 			break;
1655fcf3ce44SJohn Forte 		}
1656291a2b48SSukumar Swaminathan 
1657fcf3ce44SJohn Forte 		if (port->fct_flags & FCT_STATE_PORT_ONLINE) {
1658fcf3ce44SJohn Forte 			st.st_completion_status = STMF_ALREADY;
1659fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1660fcf3ce44SJohn Forte 			    "STATE: ONLINE chk");
1661fcf3ce44SJohn Forte 		} else {
1662fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1663fcf3ce44SJohn Forte 			    "STATE: OFFLINE --> ONLINE");
1664fcf3ce44SJohn Forte 
1665fcf3ce44SJohn Forte 			port->fct_flags |= FCT_STATE_NOT_ACKED;
1666fcf3ce44SJohn Forte 			port->fct_flags |= FCT_STATE_PORT_ONLINE;
1667fcf3ce44SJohn Forte 
1668fcf3ce44SJohn Forte 			if (hba->state <= FC_LINK_DOWN) {
1669fcf3ce44SJohn Forte 				/* Try to bring the link up */
167082527734SSukumar Swaminathan 				(void) emlxs_reset_link(hba, 1, 1);
1671fcf3ce44SJohn Forte 			}
1672291a2b48SSukumar Swaminathan 
1673fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1674fcf3ce44SJohn Forte 			    "STATE: ONLINE");
1675fcf3ce44SJohn Forte 		}
1676fcf3ce44SJohn Forte 
1677fcf3ce44SJohn Forte 		MODSYM(fct_ctl) (fct_port->port_lport,
1678fcf3ce44SJohn Forte 		    FCT_CMD_PORT_ONLINE_COMPLETE, &st);
1679fcf3ce44SJohn Forte 		break;
1680fcf3ce44SJohn Forte 
1681fcf3ce44SJohn Forte 	case FCT_CMD_PORT_OFFLINE:
1682fcf3ce44SJohn Forte 		if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
1683fcf3ce44SJohn Forte 			st.st_completion_status = STMF_ALREADY;
1684fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1685fcf3ce44SJohn Forte 			    "STATE: OFFLINE chk");
1686fcf3ce44SJohn Forte 
1687fcf3ce44SJohn Forte 		} else {
1688fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1689fcf3ce44SJohn Forte 			    "STATE: ONLINE --> OFFLINE");
1690fcf3ce44SJohn Forte 
1691fcf3ce44SJohn Forte 			/* Take link down and flush */
1692fcf3ce44SJohn Forte 			emlxs_fct_link_down(port);
1693fcf3ce44SJohn Forte 			emlxs_fct_unsol_flush(port);
1694fcf3ce44SJohn Forte 
1695fcf3ce44SJohn Forte 			/* Declare this port offline now */
1696fcf3ce44SJohn Forte 			port->fct_flags |= FCT_STATE_NOT_ACKED;
1697fcf3ce44SJohn Forte 			port->fct_flags &= ~FCT_STATE_PORT_ONLINE;
1698fcf3ce44SJohn Forte 
1699fcf3ce44SJohn Forte 			/* Take link down and hold it down */
170082527734SSukumar Swaminathan 			(void) emlxs_reset_link(hba, 0, 1);
1701fcf3ce44SJohn Forte 
1702fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1703fcf3ce44SJohn Forte 			    "STATE: OFFLINE");
1704fcf3ce44SJohn Forte 		}
1705fcf3ce44SJohn Forte 
1706fcf3ce44SJohn Forte 		MODSYM(fct_ctl) (fct_port->port_lport,
1707fcf3ce44SJohn Forte 		    FCT_CMD_PORT_OFFLINE_COMPLETE, &st);
1708fcf3ce44SJohn Forte 
1709fcf3ce44SJohn Forte 		break;
1710fcf3ce44SJohn Forte 
1711fcf3ce44SJohn Forte 	case FCT_ACK_PORT_OFFLINE_COMPLETE:
1712fcf3ce44SJohn Forte 		port->fct_flags &= ~FCT_STATE_NOT_ACKED;
1713fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1714fcf3ce44SJohn Forte 		    "STATE: OFFLINE ack");
1715fcf3ce44SJohn Forte 		break;
1716fcf3ce44SJohn Forte 
1717fcf3ce44SJohn Forte 	case FCT_ACK_PORT_ONLINE_COMPLETE:
1718fcf3ce44SJohn Forte 		port->fct_flags &= ~FCT_STATE_NOT_ACKED;
1719fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1720fcf3ce44SJohn Forte 		    "STATE: ONLINE ack");
1721fcf3ce44SJohn Forte 		break;
1722fcf3ce44SJohn Forte 
172382527734SSukumar Swaminathan 	case FCT_CMD_FORCE_LIP:
172482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
172582527734SSukumar Swaminathan 		    "emlxs_fct_ctl: FCT_CMD_FORCE_LIP");
172682527734SSukumar Swaminathan 
172782527734SSukumar Swaminathan 		/* Reset the link */
172882527734SSukumar Swaminathan 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
172982527734SSukumar Swaminathan 		break;
1730fcf3ce44SJohn Forte 	}
1731fcf3ce44SJohn Forte 
1732fcf3ce44SJohn Forte 	return;
1733fcf3ce44SJohn Forte 
173482527734SSukumar Swaminathan } /* emlxs_fct_ctl() */
1735291a2b48SSukumar Swaminathan 
1736fcf3ce44SJohn Forte 
1737fcf3ce44SJohn Forte extern int
1738fcf3ce44SJohn Forte emlxs_fct_port_shutdown(emlxs_port_t *port)
1739fcf3ce44SJohn Forte {
1740fcf3ce44SJohn Forte 	fct_local_port_t *fct_port;
174182527734SSukumar Swaminathan 	int i;
1742fcf3ce44SJohn Forte 
1743fcf3ce44SJohn Forte 	fct_port = port->fct_port;
1744fcf3ce44SJohn Forte 	if (!fct_port) {
1745fcf3ce44SJohn Forte 		return (0);
1746fcf3ce44SJohn Forte 	}
17473be114edSSukumar Swaminathan 
17483be114edSSukumar Swaminathan 	port->fct_flags |= FCT_STATE_NOT_ACKED;
17493be114edSSukumar Swaminathan 
1750291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, "fct_port_shutdown");
1751fcf3ce44SJohn Forte 	MODSYM(fct_port_shutdown) (fct_port, STMF_RFLAG_STAY_OFFLINED,
1752fcf3ce44SJohn Forte 	    "emlxs shutdown");
1753fcf3ce44SJohn Forte 
175482527734SSukumar Swaminathan 	i = 0;
1755fcf3ce44SJohn Forte 	while (port->fct_flags & FCT_STATE_NOT_ACKED) {
1756fcf3ce44SJohn Forte 		i++;
1757fcf3ce44SJohn Forte 		if (i > 300) {	/* 30 seconds */
1758fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1759fcf3ce44SJohn Forte 			    "fct_port_shutdown failed to ACK");
1760fcf3ce44SJohn Forte 			break;
1761fcf3ce44SJohn Forte 		}
1762fcf3ce44SJohn Forte 		delay(drv_usectohz(100000));	/* 100 msec */
1763fcf3ce44SJohn Forte 	}
1764fcf3ce44SJohn Forte 	return (1);
1765fcf3ce44SJohn Forte }
1766fcf3ce44SJohn Forte 
1767fcf3ce44SJohn Forte 
1768fcf3ce44SJohn Forte extern int
1769fcf3ce44SJohn Forte emlxs_fct_port_initialize(emlxs_port_t *port)
1770fcf3ce44SJohn Forte {
1771fcf3ce44SJohn Forte 	fct_local_port_t *fct_port;
177282527734SSukumar Swaminathan 	int i;
1773fcf3ce44SJohn Forte 
1774fcf3ce44SJohn Forte 	fct_port = port->fct_port;
1775fcf3ce44SJohn Forte 	if (!fct_port) {
1776fcf3ce44SJohn Forte 		return (0);
1777fcf3ce44SJohn Forte 	}
17783be114edSSukumar Swaminathan 
17793be114edSSukumar Swaminathan 	port->fct_flags |= FCT_STATE_NOT_ACKED;
17803be114edSSukumar Swaminathan 
1781fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1782fcf3ce44SJohn Forte 	    "fct_port_initialize");
1783fcf3ce44SJohn Forte 	MODSYM(fct_port_initialize) (fct_port, STMF_RFLAG_STAY_OFFLINED,
1784fcf3ce44SJohn Forte 	    "emlxs initialize");
1785fcf3ce44SJohn Forte 
178682527734SSukumar Swaminathan 	i = 0;
1787fcf3ce44SJohn Forte 	while (port->fct_flags & FCT_STATE_NOT_ACKED) {
1788fcf3ce44SJohn Forte 		i++;
1789fcf3ce44SJohn Forte 		if (i > 300) {	/* 30 seconds */
1790fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1791fcf3ce44SJohn Forte 			    "fct_port_initialize failed to ACK");
1792fcf3ce44SJohn Forte 			break;
1793fcf3ce44SJohn Forte 		}
1794fcf3ce44SJohn Forte 		delay(drv_usectohz(100000));	/* 100 msec */
1795fcf3ce44SJohn Forte 	}
1796fcf3ce44SJohn Forte 	return (1);
1797fcf3ce44SJohn Forte }
1798fcf3ce44SJohn Forte 
1799291a2b48SSukumar Swaminathan 
180082527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1801fcf3ce44SJohn Forte static fct_status_t
1802fcf3ce44SJohn Forte emlxs_fct_send_cmd(fct_cmd_t *fct_cmd)
1803fcf3ce44SJohn Forte {
1804fcf3ce44SJohn Forte 	emlxs_port_t *port;
1805fcf3ce44SJohn Forte 
1806fcf3ce44SJohn Forte 	port = (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
1807fcf3ce44SJohn Forte 
1808fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1809fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1810fcf3ce44SJohn Forte 	    "emlxs_fct_send_cmd %p: x%x", fct_cmd, fct_cmd->cmd_type);
1811291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1812fcf3ce44SJohn Forte 
1813fcf3ce44SJohn Forte 	switch (fct_cmd->cmd_type) {
1814fcf3ce44SJohn Forte 	case FCT_CMD_SOL_ELS:
1815fcf3ce44SJohn Forte 
1816fcf3ce44SJohn Forte 		return (emlxs_fct_send_els_cmd(fct_cmd));
1817fcf3ce44SJohn Forte 
1818fcf3ce44SJohn Forte 	case FCT_CMD_SOL_CT:
1819fcf3ce44SJohn Forte 
1820fcf3ce44SJohn Forte 		return (emlxs_fct_send_ct_cmd(fct_cmd));
1821fcf3ce44SJohn Forte 
1822fcf3ce44SJohn Forte 	default:
1823fcf3ce44SJohn Forte 
1824fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1825fcf3ce44SJohn Forte 		    "emlxs_fct_send_cmd: Invalid cmd type found. type=%x",
1826fcf3ce44SJohn Forte 		    fct_cmd->cmd_type);
1827fcf3ce44SJohn Forte 
1828fcf3ce44SJohn Forte 		return (FCT_FAILURE);
1829fcf3ce44SJohn Forte 	}
1830fcf3ce44SJohn Forte 
183182527734SSukumar Swaminathan } /* emlxs_fct_send_cmd() */
1832fcf3ce44SJohn Forte 
1833fcf3ce44SJohn Forte 
183482527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1835fcf3ce44SJohn Forte static fct_status_t
1836fcf3ce44SJohn Forte emlxs_fct_send_cmd_rsp(fct_cmd_t *fct_cmd, uint32_t ioflags)
1837fcf3ce44SJohn Forte {
1838fcf3ce44SJohn Forte 	emlxs_port_t *port;
1839291a2b48SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp;
1840291a2b48SSukumar Swaminathan 	fct_status_t rval;
184182527734SSukumar Swaminathan 	IOCBQ *iocbq;
184282527734SSukumar Swaminathan 	IOCB *iocb;
184382527734SSukumar Swaminathan 	uint32_t status;
1844fcf3ce44SJohn Forte 
1845fcf3ce44SJohn Forte 	port = (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
184682527734SSukumar Swaminathan 
184782527734SSukumar Swaminathan 	rval = emlxs_fct_cmd_accept(port, fct_cmd, EMLXS_FCT_SEND_CMD_RSP);
184882527734SSukumar Swaminathan 	if (rval) {
184982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
185082527734SSukumar Swaminathan 		    "emlxs_fct_send_cmd_rsp: "
185182527734SSukumar Swaminathan 		    "Unable to accept fct_cmd. type=%x",
185282527734SSukumar Swaminathan 		    fct_cmd->cmd_type);
185382527734SSukumar Swaminathan 
185482527734SSukumar Swaminathan 		return (rval);
185582527734SSukumar Swaminathan 	}
185682527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
185782527734SSukumar Swaminathan 
1858291a2b48SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
185982527734SSukumar Swaminathan 	iocbq = &cmd_sbp->iocbq;
186082527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
186182527734SSukumar Swaminathan 	status = iocb->ULPSTATUS;
1862fcf3ce44SJohn Forte 
1863fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1864fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
186582527734SSukumar Swaminathan 	    "emlxs_fct_send_cmd_rsp %p: x%x, %x, %x",
186682527734SSukumar Swaminathan 	    fct_cmd, fct_cmd->cmd_type, iocb->ULPCT, status);
1867291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1868fcf3ce44SJohn Forte 
1869fcf3ce44SJohn Forte 	switch (fct_cmd->cmd_type) {
1870fcf3ce44SJohn Forte 	case FCT_CMD_FCP_XCHG:
1871fcf3ce44SJohn Forte 
1872fcf3ce44SJohn Forte 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1873fcf3ce44SJohn Forte 			goto failure;
1874fcf3ce44SJohn Forte 		}
1875291a2b48SSukumar Swaminathan 
187682527734SSukumar Swaminathan 		if ((iocb->ULPCT == 0x1) && (status == 0)) {
187782527734SSukumar Swaminathan 
187882527734SSukumar Swaminathan 			/* Firmware already sent out resp */
187982527734SSukumar Swaminathan 			cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
188082527734SSukumar Swaminathan 
188182527734SSukumar Swaminathan 			emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
188282527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
188382527734SSukumar Swaminathan 
188482527734SSukumar Swaminathan #ifdef FCT_API_TRACE
188582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
188682527734SSukumar Swaminathan 			    "fct_send_response_done:4 %p: x%x",
188782527734SSukumar Swaminathan 			    fct_cmd, fct_cmd->cmd_comp_status);
188882527734SSukumar Swaminathan 
188982527734SSukumar Swaminathan #endif /* FCT_API_TRACE */
189082527734SSukumar Swaminathan 
189182527734SSukumar Swaminathan 			MODSYM(fct_send_response_done) (fct_cmd,
189282527734SSukumar Swaminathan 			    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
189382527734SSukumar Swaminathan 
189482527734SSukumar Swaminathan 			return (FCT_SUCCESS);
189582527734SSukumar Swaminathan 		}
189682527734SSukumar Swaminathan 
1897291a2b48SSukumar Swaminathan 		rval =  emlxs_fct_send_fcp_status(fct_cmd);
189882527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
189982527734SSukumar Swaminathan 
1900291a2b48SSukumar Swaminathan 		return (rval);
1901fcf3ce44SJohn Forte 
1902fcf3ce44SJohn Forte 	case FCT_CMD_RCVD_ELS:
1903fcf3ce44SJohn Forte 
1904fcf3ce44SJohn Forte 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1905fcf3ce44SJohn Forte 			goto failure;
1906fcf3ce44SJohn Forte 		}
1907fcf3ce44SJohn Forte 
190882527734SSukumar Swaminathan 		rval =  emlxs_fct_send_els_rsp(fct_cmd);
190982527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
191082527734SSukumar Swaminathan 
191182527734SSukumar Swaminathan 		return (rval);
1912fcf3ce44SJohn Forte 
1913fcf3ce44SJohn Forte 	default:
1914fcf3ce44SJohn Forte 
1915fcf3ce44SJohn Forte 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1916fcf3ce44SJohn Forte 			fct_cmd->cmd_handle = 0;
1917fcf3ce44SJohn Forte 		}
1918291a2b48SSukumar Swaminathan 
1919fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1920fcf3ce44SJohn Forte 		    "emlxs_fct_send_cmd_rsp: Invalid cmd type found. type=%x",
1921fcf3ce44SJohn Forte 		    fct_cmd->cmd_type);
1922fcf3ce44SJohn Forte 
1923fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
192482527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
192582527734SSukumar Swaminathan 
1926fcf3ce44SJohn Forte 		return (FCT_FAILURE);
1927fcf3ce44SJohn Forte 	}
1928fcf3ce44SJohn Forte 
1929fcf3ce44SJohn Forte failure:
1930fcf3ce44SJohn Forte 
1931fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1932291a2b48SSukumar Swaminathan 	    "emlxs_fct_send_cmd_rsp: "
1933291a2b48SSukumar Swaminathan 	    "Unable to handle FCT_IOF_FORCE_FCA_DONE. type=%x",
1934291a2b48SSukumar Swaminathan 	    fct_cmd->cmd_type);
1935fcf3ce44SJohn Forte 
1936fe199829SSukumar Swaminathan 	emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
193782527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
193882527734SSukumar Swaminathan 
1939fcf3ce44SJohn Forte 	return (FCT_FAILURE);
1940fcf3ce44SJohn Forte 
194182527734SSukumar Swaminathan } /* emlxs_fct_send_cmd_rsp() */
1942fcf3ce44SJohn Forte 
1943fcf3ce44SJohn Forte 
194482527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1945fcf3ce44SJohn Forte static fct_status_t
194682527734SSukumar Swaminathan emlxs_fct_flogi_xchg(struct fct_local_port *fct_port, struct fct_flogi_xchg *fx)
1947fcf3ce44SJohn Forte {
1948fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1949fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1950fcf3ce44SJohn Forte 	uint32_t size;
195182527734SSukumar Swaminathan 	fc_packet_t *pkt = NULL;
1952fcf3ce44SJohn Forte 	ELS_PKT *els;
195382527734SSukumar Swaminathan 	fct_status_t rval = FCT_SUCCESS;
1954fcf3ce44SJohn Forte 
1955fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1956fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
195782527734SSukumar Swaminathan 	    "emlxs_fct_flogi_xchg: Sending FLOGI: %p", fct_port);
1958fcf3ce44SJohn Forte #else
1959fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
196082527734SSukumar Swaminathan 	    "emlxs_fct_flogi_xchg: Sending FLOGI.");
1961291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1962fcf3ce44SJohn Forte 
1963fcf3ce44SJohn Forte 	if (hba->state <= FC_LINK_DOWN) {
1964fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
196582527734SSukumar Swaminathan 		    "emlxs_fct_flogi_xchg: FLOGI failed. Link down.");
196682527734SSukumar Swaminathan 		rval = FCT_FAILURE;
196782527734SSukumar Swaminathan 		goto done;
1968fcf3ce44SJohn Forte 	}
1969291a2b48SSukumar Swaminathan 
1970e2ca2865SSukumar Swaminathan 	/* Use this entyr point as the link up acknowlegment */
1971e2ca2865SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
1972e2ca2865SSukumar Swaminathan 	port->fct_flags |= FCT_STATE_LINK_UP_ACKED;
1973e2ca2865SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1974e2ca2865SSukumar Swaminathan 	    "emlxs_fct_link_up acked.");
1975e2ca2865SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
1976e2ca2865SSukumar Swaminathan 
1977e2ca2865SSukumar Swaminathan 	/* Now flush any pending unsolicited requests */
1978e2ca2865SSukumar Swaminathan 	emlxs_fct_unsol_flush(port);
1979e2ca2865SSukumar Swaminathan 
1980fcf3ce44SJohn Forte 	size = sizeof (SERV_PARM) + 4;
1981fcf3ce44SJohn Forte 
1982fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, size, size, 0, KM_NOSLEEP))) {
1983fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
198482527734SSukumar Swaminathan 		    "emlxs_fct_flogi_xchg: FLOGI failed. "
198582527734SSukumar Swaminathan 		    "Unable allocate packet.");
198682527734SSukumar Swaminathan 		rval = FCT_FAILURE;
198782527734SSukumar Swaminathan 		goto done;
1988fcf3ce44SJohn Forte 	}
1989291a2b48SSukumar Swaminathan 
1990fcf3ce44SJohn Forte 	/* Make this a polled IO */
1991fcf3ce44SJohn Forte 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
1992fcf3ce44SJohn Forte 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
1993fcf3ce44SJohn Forte 	pkt->pkt_comp = NULL;
1994fcf3ce44SJohn Forte 
1995fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
1996fcf3ce44SJohn Forte 	pkt->pkt_timeout = fx->fx_sec_timeout;
1997fcf3ce44SJohn Forte 
1998fcf3ce44SJohn Forte 	/* Build the fc header */
199982527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(fx->fx_did);
2000291a2b48SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.r_ctl =
2001291a2b48SSukumar Swaminathan 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
200282527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(fx->fx_sid);
2003fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2004fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE;
2005fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
2006fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2007fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2008fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
2009fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
2010fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
2011fcf3ce44SJohn Forte 
2012fcf3ce44SJohn Forte 	/* Build the command */
2013291a2b48SSukumar Swaminathan 	/* Service paramters will be added automatically later by the driver */
2014fcf3ce44SJohn Forte 	els = (ELS_PKT *)pkt->pkt_cmd;
2015fcf3ce44SJohn Forte 	els->elsCode = 0x04;	/* FLOGI */
2016fcf3ce44SJohn Forte 
2017fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2018fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
201982527734SSukumar Swaminathan 		    "emlxs_fct_flogi_xchg: FLOGI failed. "
202082527734SSukumar Swaminathan 		    "Unable to send packet.");
2021fcf3ce44SJohn Forte 
202282527734SSukumar Swaminathan 		rval = FCT_FAILURE;
202382527734SSukumar Swaminathan 		goto done;
2024fcf3ce44SJohn Forte 	}
2025291a2b48SSukumar Swaminathan 
2026fcf3ce44SJohn Forte 	if ((pkt->pkt_state != FC_PKT_SUCCESS) &&
2027fcf3ce44SJohn Forte 	    (pkt->pkt_state != FC_PKT_LS_RJT)) {
2028fcf3ce44SJohn Forte 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
202982527734SSukumar Swaminathan 			rval = FCT_TIMEOUT;
2030fcf3ce44SJohn Forte 		} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
2031fcf3ce44SJohn Forte 		    (pkt->pkt_reason == FC_REASON_FCAL_OPN_FAIL)) {
203282527734SSukumar Swaminathan 			rval = FCT_NOT_FOUND;
203382527734SSukumar Swaminathan 		} else {
203482527734SSukumar Swaminathan 			rval = FCT_FAILURE;
2035fcf3ce44SJohn Forte 		}
2036291a2b48SSukumar Swaminathan 
2037fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
203882527734SSukumar Swaminathan 		    "emlxs_fct_flogi_xchg: FLOGI failed. state=%x reason=%x",
2039fcf3ce44SJohn Forte 		    pkt->pkt_state, pkt->pkt_reason);
2040fcf3ce44SJohn Forte 
204182527734SSukumar Swaminathan 		goto done;
2042fcf3ce44SJohn Forte 	}
2043291a2b48SSukumar Swaminathan 
2044fcf3ce44SJohn Forte 	if (pkt->pkt_state == FC_PKT_LS_RJT) {
2045fcf3ce44SJohn Forte 		fx->fx_op = ELS_OP_LSRJT;
2046fcf3ce44SJohn Forte 		fx->fx_rjt_reason = pkt->pkt_reason;
2047fcf3ce44SJohn Forte 		fx->fx_rjt_expl = pkt->pkt_expln;
2048fcf3ce44SJohn Forte 	} else {	/* FC_PKT_SUCCESS */
2049291a2b48SSukumar Swaminathan 
2050fcf3ce44SJohn Forte 		fx->fx_op = ELS_OP_ACC;
205182527734SSukumar Swaminathan 		fx->fx_sid = FABRIC_DID;
2052fcf3ce44SJohn Forte 		fx->fx_did = port->did;
2053fcf3ce44SJohn Forte 
2054291a2b48SSukumar Swaminathan 		els = (ELS_PKT *)pkt->pkt_resp;
2055fcf3ce44SJohn Forte 		bcopy((caddr_t)&els->un.logi.nodeName,
2056fcf3ce44SJohn Forte 		    (caddr_t)fx->fx_nwwn, 8);
2057fcf3ce44SJohn Forte 		bcopy((caddr_t)&els->un.logi.portName,
2058fcf3ce44SJohn Forte 		    (caddr_t)fx->fx_pwwn, 8);
2059fcf3ce44SJohn Forte 		fx->fx_fport = els->un.logi.cmn.fPort;
2060fcf3ce44SJohn Forte 	}
2061fcf3ce44SJohn Forte 
206282527734SSukumar Swaminathan done:
206382527734SSukumar Swaminathan 	if (pkt) {
206482527734SSukumar Swaminathan 		emlxs_pkt_free(pkt);
206582527734SSukumar Swaminathan 	}
206682527734SSukumar Swaminathan 
206782527734SSukumar Swaminathan 	return (rval);
2068fcf3ce44SJohn Forte 
206982527734SSukumar Swaminathan } /* emlxs_fct_flogi_xchg() */
2070fcf3ce44SJohn Forte 
2071fcf3ce44SJohn Forte 
207282527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
2073fcf3ce44SJohn Forte /* This is called right after we report that link has come online */
2074fcf3ce44SJohn Forte static fct_status_t
2075fcf3ce44SJohn Forte emlxs_fct_get_link_info(fct_local_port_t *fct_port, fct_link_info_t *link)
2076fcf3ce44SJohn Forte {
2077fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
2078fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2079fcf3ce44SJohn Forte 
2080fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2081fcf3ce44SJohn Forte 	    "emlxs_fct_get_link_info %p", fct_port);
2082fcf3ce44SJohn Forte 
2083fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
2084fcf3ce44SJohn Forte 
2085fcf3ce44SJohn Forte 	if (!(port->fct_flags & FCT_STATE_LINK_UP) ||
2086291a2b48SSukumar Swaminathan 	    (hba->state < FC_LINK_UP) || (hba->flag & FC_LOOPBACK_MODE)) {
2087fcf3ce44SJohn Forte 		link->port_topology = PORT_TOPOLOGY_UNKNOWN;
2088fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_UNKNOWN;
2089fcf3ce44SJohn Forte 		link->portid = 0;
2090fcf3ce44SJohn Forte 
2091fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
2092fcf3ce44SJohn Forte 
2093fcf3ce44SJohn Forte 		return (FCT_SUCCESS);
2094fcf3ce44SJohn Forte 	}
2095291a2b48SSukumar Swaminathan 
2096fcf3ce44SJohn Forte 	if (hba->topology == TOPOLOGY_LOOP) {
2097fcf3ce44SJohn Forte 		link->port_topology = PORT_TOPOLOGY_PRIVATE_LOOP;
2098fcf3ce44SJohn Forte 	} else {
2099fcf3ce44SJohn Forte 		link->port_topology = PORT_TOPOLOGY_PT_TO_PT;
2100fcf3ce44SJohn Forte 	}
2101fcf3ce44SJohn Forte 
2102fcf3ce44SJohn Forte 	switch (hba->linkspeed) {
2103fcf3ce44SJohn Forte 	case LA_1GHZ_LINK:
2104fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_1G;
2105fcf3ce44SJohn Forte 		break;
2106fcf3ce44SJohn Forte 	case LA_2GHZ_LINK:
2107fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_2G;
2108fcf3ce44SJohn Forte 		break;
2109fcf3ce44SJohn Forte 	case LA_4GHZ_LINK:
2110fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_4G;
2111fcf3ce44SJohn Forte 		break;
2112fcf3ce44SJohn Forte 	case LA_8GHZ_LINK:
2113fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_8G;
2114fcf3ce44SJohn Forte 		break;
2115fcf3ce44SJohn Forte 	case LA_10GHZ_LINK:
2116fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_10G;
2117fcf3ce44SJohn Forte 		break;
2118fcf3ce44SJohn Forte 	default:
2119fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_UNKNOWN;
2120fcf3ce44SJohn Forte 		break;
2121fcf3ce44SJohn Forte 	}
2122fcf3ce44SJohn Forte 
2123fcf3ce44SJohn Forte 	link->portid = port->did;
2124fcf3ce44SJohn Forte 	link->port_no_fct_flogi = 0;
2125fcf3ce44SJohn Forte 	link->port_fca_flogi_done = 0;
2126fcf3ce44SJohn Forte 	link->port_fct_flogi_done = 0;
2127fcf3ce44SJohn Forte 
2128fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
2129fcf3ce44SJohn Forte 
2130fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
2131fcf3ce44SJohn Forte 
213282527734SSukumar Swaminathan } /* emlxs_fct_get_link_info() */
2133fcf3ce44SJohn Forte 
2134fcf3ce44SJohn Forte 
213582527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
2136fcf3ce44SJohn Forte static fct_status_t
2137fcf3ce44SJohn Forte emlxs_fct_register_remote_port(fct_local_port_t *fct_port,
2138fcf3ce44SJohn Forte     fct_remote_port_t *remote_port, fct_cmd_t *fct_cmd)
2139fcf3ce44SJohn Forte {
2140fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
2141fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2142fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2143fcf3ce44SJohn Forte 	clock_t timeout;
2144fcf3ce44SJohn Forte 	int32_t pkt_ret;
2145fcf3ce44SJohn Forte 	fct_els_t *els;
2146fcf3ce44SJohn Forte 	SERV_PARM *sp;
2147fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
2148fcf3ce44SJohn Forte 	SERV_PARM sparam;
2149fcf3ce44SJohn Forte 	uint32_t *iptr;
21503be114edSSukumar Swaminathan 	uint64_t addr;
215182527734SSukumar Swaminathan 	fct_status_t rval;
215282527734SSukumar Swaminathan 	fct_status_t rval2;
2153fcf3ce44SJohn Forte 
2154fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2155fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2156fcf3ce44SJohn Forte 	    "emlxs_fct_register_remote_port %p", fct_port);
2157291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2158fcf3ce44SJohn Forte 
2159fcf3ce44SJohn Forte 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
216082527734SSukumar Swaminathan 
216182527734SSukumar Swaminathan 		cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd,
216282527734SSukumar Swaminathan 		    EMLXS_FCT_REG_PENDING);
2163291a2b48SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
2164fcf3ce44SJohn Forte 
216582527734SSukumar Swaminathan 		cmd_sbp->channel = &hba->chan[hba->channel_els];
2166fcf3ce44SJohn Forte 		cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD;
216782527734SSukumar Swaminathan 
2168fcf3ce44SJohn Forte 	} else {
2169fcf3ce44SJohn Forte 
217082527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_accept(port, fct_cmd,
217182527734SSukumar Swaminathan 		    EMLXS_FCT_REG_PENDING);
217282527734SSukumar Swaminathan 		if (rval) {
217382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
217482527734SSukumar Swaminathan 			    "emlxs_fct_register_remote_port: "
217582527734SSukumar Swaminathan 			    "Unable to accept fct_cmd. did=%x",
217682527734SSukumar Swaminathan 			    fct_cmd->cmd_rportid);
2177291a2b48SSukumar Swaminathan 
217882527734SSukumar Swaminathan 			return (rval);
217982527734SSukumar Swaminathan 		}
218082527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
218182527734SSukumar Swaminathan 	}
2182fcf3ce44SJohn Forte 
2183fcf3ce44SJohn Forte 	if (!cmd_sbp->node) {
2184291a2b48SSukumar Swaminathan 		cmd_sbp->node =
2185291a2b48SSukumar Swaminathan 		    emlxs_node_find_did(port, fct_cmd->cmd_rportid);
2186fcf3ce44SJohn Forte 	}
2187291a2b48SSukumar Swaminathan 
2188fcf3ce44SJohn Forte 	if (!cmd_sbp->node) {
2189fcf3ce44SJohn Forte 		els = (fct_els_t *)fct_cmd->cmd_specific;
2190fcf3ce44SJohn Forte 
2191fcf3ce44SJohn Forte 		/* Check for unsolicited PLOGI */
2192291a2b48SSukumar Swaminathan 		if (cmd_sbp->fct_flags & EMLXS_FCT_PLOGI_RECEIVED) {
2193291a2b48SSukumar Swaminathan 			sp = (SERV_PARM *)((caddr_t)els->els_req_payload +
2194291a2b48SSukumar Swaminathan 			    sizeof (uint32_t));
2195fcf3ce44SJohn Forte 		} else {	/* Solicited PLOGI */
2196291a2b48SSukumar Swaminathan 
2197fcf3ce44SJohn Forte 			sp = &sparam;
2198fcf3ce44SJohn Forte 			bcopy((caddr_t)&port->sparam, (caddr_t)sp,
2199fcf3ce44SJohn Forte 			    sizeof (SERV_PARM));
2200fcf3ce44SJohn Forte 
2201fcf3ce44SJohn Forte 			/*
2202291a2b48SSukumar Swaminathan 			 * Create temporary WWN's from fct_cmd address
2203fcf3ce44SJohn Forte 			 * This simply allows us to get an RPI from the
2204291a2b48SSukumar Swaminathan 			 * adapter until we get real service params.
2205fcf3ce44SJohn Forte 			 * The PLOGI ACC reply will trigger a REG_LOGIN
2206fcf3ce44SJohn Forte 			 * update later
2207fcf3ce44SJohn Forte 			 */
22083be114edSSukumar Swaminathan 			addr = (uint64_t)((unsigned long)fct_cmd);
22093be114edSSukumar Swaminathan 
2210fcf3ce44SJohn Forte 			iptr = (uint32_t *)&sp->portName;
221182527734SSukumar Swaminathan 			iptr[0] = PADDR_HI(addr);
221282527734SSukumar Swaminathan 			iptr[1] = PADDR_LO(addr);
2213291a2b48SSukumar Swaminathan 
2214fcf3ce44SJohn Forte 			iptr = (uint32_t *)&sp->nodeName;
221582527734SSukumar Swaminathan 			iptr[0] = PADDR_HI(addr);
221682527734SSukumar Swaminathan 			iptr[1] = PADDR_LO(addr);
2217fcf3ce44SJohn Forte 		}
2218fcf3ce44SJohn Forte 
2219fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
2220291a2b48SSukumar Swaminathan 		    "emlxs_fct_register_remote_port: Register did=%x. (%x,%p)",
2221291a2b48SSukumar Swaminathan 		    fct_cmd->cmd_rportid, cmd_sbp->fct_state, fct_cmd);
2222fcf3ce44SJohn Forte 
222382527734SSukumar Swaminathan 		emlxs_fct_cmd_release(port, fct_cmd, 0);
222482527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
222582527734SSukumar Swaminathan 
2226fcf3ce44SJohn Forte 		/* Create a new node */
2227fcf3ce44SJohn Forte 		if (emlxs_mb_reg_did(port, fct_cmd->cmd_rportid, sp, cmd_sbp,
2228fcf3ce44SJohn Forte 		    NULL, NULL) != 0) {
2229fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2230291a2b48SSukumar Swaminathan 			    "emlxs_fct_register_remote_port: "
2231291a2b48SSukumar Swaminathan 			    "Reg login failed. did=%x",
2232291a2b48SSukumar Swaminathan 			    fct_cmd->cmd_rportid);
223382527734SSukumar Swaminathan 		} else {
2234fcf3ce44SJohn Forte 
223582527734SSukumar Swaminathan 			/* Wait for completion */
223682527734SSukumar Swaminathan 			mutex_enter(&EMLXS_PKT_LOCK);
223782527734SSukumar Swaminathan 			timeout = emlxs_timeout(hba, 30);
223882527734SSukumar Swaminathan 			pkt_ret = 0;
223982527734SSukumar Swaminathan 			while ((pkt_ret != -1) &&
224082527734SSukumar Swaminathan 			    (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) &&
224182527734SSukumar Swaminathan 			    (cmd_sbp->node == NULL)) {
224282527734SSukumar Swaminathan 				pkt_ret = cv_timedwait(&EMLXS_PKT_CV,
224382527734SSukumar Swaminathan 				    &EMLXS_PKT_LOCK, timeout);
224482527734SSukumar Swaminathan 			}
224582527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PKT_LOCK);
2246fcf3ce44SJohn Forte 		}
2247fcf3ce44SJohn Forte 
224882527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
224982527734SSukumar Swaminathan 		rval2 = emlxs_fct_cmd_acquire(port, fct_cmd,
225082527734SSukumar Swaminathan 		    EMLXS_FCT_REG_COMPLETE);
225182527734SSukumar Swaminathan 		if (rval2) {
225282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
225382527734SSukumar Swaminathan 			    "emlxs_fct_register_remote_port: "
225482527734SSukumar Swaminathan 			    "Unable to reacquire fct_cmd. did=%x",
225582527734SSukumar Swaminathan 			    fct_cmd->cmd_rportid);
225682527734SSukumar Swaminathan 
225782527734SSukumar Swaminathan 			return (rval2);
2258291a2b48SSukumar Swaminathan 		}
225982527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
2260fcf3ce44SJohn Forte 	}
2261291a2b48SSukumar Swaminathan 
2262fcf3ce44SJohn Forte done:
2263fcf3ce44SJohn Forte 
2264fcf3ce44SJohn Forte 	ndlp = (emlxs_node_t *)cmd_sbp->node;
2265fcf3ce44SJohn Forte 
2266fcf3ce44SJohn Forte 	if (ndlp) {
2267291a2b48SSukumar Swaminathan 		*((emlxs_node_t **)remote_port->rp_fca_private) =
2268291a2b48SSukumar Swaminathan 		    cmd_sbp->node;
2269fcf3ce44SJohn Forte 		remote_port->rp_handle = ndlp->nlp_Rpi;
2270fcf3ce44SJohn Forte 
2271fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2272fcf3ce44SJohn Forte 		    "emlxs_fct_register_remote_port: did=%x hdl=%x",
2273fcf3ce44SJohn Forte 		    fct_cmd->cmd_rportid, remote_port->rp_handle);
2274fcf3ce44SJohn Forte 
2275fcf3ce44SJohn Forte 		remote_port->rp_handle = ndlp->nlp_Rpi;
2276fcf3ce44SJohn Forte 
2277fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
227882527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2279291a2b48SSukumar Swaminathan 
2280fcf3ce44SJohn Forte 		TGTPORTSTAT.FctPortRegister++;
2281fcf3ce44SJohn Forte 		return (FCT_SUCCESS);
2282fcf3ce44SJohn Forte 	} else {
2283fcf3ce44SJohn Forte 		*((emlxs_node_t **)remote_port->rp_fca_private) = NULL;
2284fcf3ce44SJohn Forte 
2285fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2286fcf3ce44SJohn Forte 		    "emlxs_fct_register_remote_port: failed. did=%x hdl=%x",
2287fcf3ce44SJohn Forte 		    fct_cmd->cmd_rportid, remote_port->rp_handle);
2288fcf3ce44SJohn Forte 
2289fcf3ce44SJohn Forte 		remote_port->rp_handle = FCT_HANDLE_NONE;
2290fcf3ce44SJohn Forte 
2291fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
229282527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2293291a2b48SSukumar Swaminathan 
2294fcf3ce44SJohn Forte 		TGTPORTSTAT.FctFailedPortRegister++;
2295fcf3ce44SJohn Forte 		return (FCT_FAILURE);
2296fcf3ce44SJohn Forte 	}
2297fcf3ce44SJohn Forte 
229882527734SSukumar Swaminathan } /* emlxs_fct_register_remote_port() */
2299fcf3ce44SJohn Forte 
2300fcf3ce44SJohn Forte 
230182527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
2302fcf3ce44SJohn Forte static fct_status_t
2303fcf3ce44SJohn Forte emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port,
2304fcf3ce44SJohn Forte     fct_remote_port_t *remote_port)
2305fcf3ce44SJohn Forte {
2306fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
2307fcf3ce44SJohn Forte 
2308fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2309fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2310fcf3ce44SJohn Forte 	    "emlxs_fct_deregister_remote_port: did=%x hdl=%x",
2311fcf3ce44SJohn Forte 	    remote_port->rp_id, remote_port->rp_handle);
2312fcf3ce44SJohn Forte #else
2313fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2314fcf3ce44SJohn Forte 	    "emlxs_fct_deregister_remote_port: did=%x hdl=%x",
2315fcf3ce44SJohn Forte 	    remote_port->rp_id, remote_port->rp_handle);
2316291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2317fcf3ce44SJohn Forte 
2318fcf3ce44SJohn Forte 	*((emlxs_node_t **)remote_port->rp_fca_private) = NULL;
2319fcf3ce44SJohn Forte 	(void) emlxs_mb_unreg_did(port, remote_port->rp_id, NULL, NULL, NULL);
2320fcf3ce44SJohn Forte 
2321fcf3ce44SJohn Forte 	TGTPORTSTAT.FctPortDeregister++;
2322fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
2323fcf3ce44SJohn Forte 
232482527734SSukumar Swaminathan } /* emlxs_fct_deregister_remote_port() */
2325fcf3ce44SJohn Forte 
2326fcf3ce44SJohn Forte 
2327fcf3ce44SJohn Forte /* ARGSUSED */
2328fcf3ce44SJohn Forte extern int
232982527734SSukumar Swaminathan emlxs_fct_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
2330fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
2331fcf3ce44SJohn Forte {
2332fcf3ce44SJohn Forte 	IOCB *iocb;
2333fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
2334fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
2335fcf3ce44SJohn Forte 	emlxs_fcp_cmd_t *fcp_cmd;
2336fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
2337fcf3ce44SJohn Forte 	uint32_t cnt;
2338fcf3ce44SJohn Forte 	uint32_t tm;
2339fcf3ce44SJohn Forte 	scsi_task_t *fct_task;
2340fcf3ce44SJohn Forte 	uint8_t lun[8];
2341fcf3ce44SJohn Forte 	uint32_t sid = 0;
2342fcf3ce44SJohn Forte 
2343fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
234482527734SSukumar Swaminathan 	ndlp = emlxs_node_find_rpi(port, iocb->ULPIOTAG);
2345fcf3ce44SJohn Forte 	if (!ndlp) {
2346fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2347fcf3ce44SJohn Forte 		    "FCP rcvd: Unknown RPI. rpi=%x rxid=%x. Dropping...",
234882527734SSukumar Swaminathan 		    iocb->ULPIOTAG, iocb->ULPCONTEXT);
2349fcf3ce44SJohn Forte 
2350fcf3ce44SJohn Forte 		goto dropped;
2351fcf3ce44SJohn Forte 	}
2352fcf3ce44SJohn Forte 	sid = ndlp->nlp_DID;
2353fcf3ce44SJohn Forte 
2354fcf3ce44SJohn Forte 	fcp_cmd = (emlxs_fcp_cmd_t *)mp->virt;
2355fcf3ce44SJohn Forte 
2356fcf3ce44SJohn Forte 	if (!port->fct_port) {
2357fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2358fcf3ce44SJohn Forte 		    "FCP rcvd: Target unbound. rpi=%x rxid=%x. Dropping...",
235982527734SSukumar Swaminathan 		    iocb->ULPIOTAG, iocb->ULPCONTEXT);
2360fcf3ce44SJohn Forte 
2361fcf3ce44SJohn Forte 		emlxs_send_logo(port, sid);
2362fcf3ce44SJohn Forte 
2363fcf3ce44SJohn Forte 		goto dropped;
2364fcf3ce44SJohn Forte 	}
2365291a2b48SSukumar Swaminathan 
2366fcf3ce44SJohn Forte 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
2367fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2368fcf3ce44SJohn Forte 		    "FCP rcvd: Target offline. rpi=%x rxid=%x. Dropping...",
236982527734SSukumar Swaminathan 		    iocb->ULPIOTAG, iocb->ULPCONTEXT);
2370fcf3ce44SJohn Forte 
2371fcf3ce44SJohn Forte 		emlxs_send_logo(port, sid);
2372fcf3ce44SJohn Forte 
2373fcf3ce44SJohn Forte 		goto dropped;
2374fcf3ce44SJohn Forte 	}
2375291a2b48SSukumar Swaminathan 
2376fcf3ce44SJohn Forte 	/* Get lun id */
2377fcf3ce44SJohn Forte 	bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8);
2378fcf3ce44SJohn Forte 
2379fcf3ce44SJohn Forte 	if (TGTPORTSTAT.FctOutstandingIO >= port->fct_port->port_max_xchges) {
2380fcf3ce44SJohn Forte 		TGTPORTSTAT.FctOverQDepth++;
2381fcf3ce44SJohn Forte 	}
2382291a2b48SSukumar Swaminathan 
2383291a2b48SSukumar Swaminathan 	fct_cmd =
238482527734SSukumar Swaminathan 	    MODSYM(fct_scsi_task_alloc) (port->fct_port, iocb->ULPIOTAG, sid,
2385291a2b48SSukumar Swaminathan 	    lun, 16, 0);
2386fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2387fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2388291a2b48SSukumar Swaminathan 	    "fct_scsi_task_alloc %p: FCP rcvd: "
2389291a2b48SSukumar Swaminathan 	    "cmd=%x sid=%x rxid=%x lun=%02x%02x dl=%d",
239082527734SSukumar Swaminathan 	    fct_cmd, fcp_cmd->fcpCdb[0], sid, iocb->ULPCONTEXT,
239182527734SSukumar Swaminathan 	    lun[0], lun[1], LE_SWAP32(fcp_cmd->fcpDl));
2392291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2393fcf3ce44SJohn Forte 
2394fcf3ce44SJohn Forte 	if (fct_cmd == NULL) {
2395fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2396291a2b48SSukumar Swaminathan 		    "FCP rcvd: sid=%x xid=%x. "
2397291a2b48SSukumar Swaminathan 		    "Unable to allocate scsi task. Returning QFULL.",
239882527734SSukumar Swaminathan 		    sid, iocb->ULPCONTEXT);
2399fcf3ce44SJohn Forte 
240082527734SSukumar Swaminathan 		(void) emlxs_fct_send_qfull_reply(port, ndlp, iocb->ULPCONTEXT,
240182527734SSukumar Swaminathan 		    iocb->ULPCLASS, fcp_cmd);
2402fcf3ce44SJohn Forte 
2403fcf3ce44SJohn Forte 		goto dropped;
2404fcf3ce44SJohn Forte 	}
2405291a2b48SSukumar Swaminathan 
2406fcf3ce44SJohn Forte 	/* Initialize fct_cmd */
2407fcf3ce44SJohn Forte 	fct_cmd->cmd_oxid = 0xFFFF;
240882527734SSukumar Swaminathan 	fct_cmd->cmd_rxid = iocb->ULPCONTEXT;
2409fcf3ce44SJohn Forte 	fct_cmd->cmd_rportid = sid;
2410fcf3ce44SJohn Forte 	fct_cmd->cmd_lportid = port->did;
241182527734SSukumar Swaminathan 	fct_cmd->cmd_rp_handle = iocb->ULPIOTAG;	/* RPI */
2412fcf3ce44SJohn Forte 	fct_cmd->cmd_port = port->fct_port;
2413fcf3ce44SJohn Forte 
241482527734SSukumar Swaminathan 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_FCP_CMD_RECEIVED);
241582527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2416fcf3ce44SJohn Forte 
2417291a2b48SSukumar Swaminathan 	/* Initialize cmd_sbp */
241882527734SSukumar Swaminathan 	cmd_sbp->channel = cp;
241982527734SSukumar Swaminathan 	cmd_sbp->class = iocb->ULPCLASS;
2420fcf3ce44SJohn Forte 	cmd_sbp->lun = (lun[0] << 8) | lun[1];
2421fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_FCP_CMD;
2422fcf3ce44SJohn Forte 
2423fcf3ce44SJohn Forte 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
2424fcf3ce44SJohn Forte 
2425fcf3ce44SJohn Forte 	/* Set task_flags */
2426291a2b48SSukumar Swaminathan 	switch (fcp_cmd->fcpCntl1) {
2427291a2b48SSukumar Swaminathan 	case SIMPLE_Q:
2428fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_SIMPLE_QUEUE;
2429fcf3ce44SJohn Forte 		break;
2430fcf3ce44SJohn Forte 
2431291a2b48SSukumar Swaminathan 	case HEAD_OF_Q:
2432fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_HEAD_OF_QUEUE;
2433fcf3ce44SJohn Forte 		break;
2434fcf3ce44SJohn Forte 
2435291a2b48SSukumar Swaminathan 	case ORDERED_Q:
2436fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_ORDERED_QUEUE;
2437fcf3ce44SJohn Forte 		break;
2438fcf3ce44SJohn Forte 
2439291a2b48SSukumar Swaminathan 	case ACA_Q:
2440fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_ACA;
2441fcf3ce44SJohn Forte 		break;
2442fcf3ce44SJohn Forte 
2443291a2b48SSukumar Swaminathan 	case UNTAGGED:
2444fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_UNTAGGED;
2445fcf3ce44SJohn Forte 		break;
2446fcf3ce44SJohn Forte 	}
2447fcf3ce44SJohn Forte 
244882527734SSukumar Swaminathan 	cnt = LE_SWAP32(fcp_cmd->fcpDl);
2449fcf3ce44SJohn Forte 	switch (fcp_cmd->fcpCntl3) {
2450fcf3ce44SJohn Forte 	case 0:
2451fcf3ce44SJohn Forte 		TGTPORTSTAT.FctIOCmdCnt++;
2452fcf3ce44SJohn Forte 		break;
2453fcf3ce44SJohn Forte 	case 1:
245482527734SSukumar Swaminathan 		EMLXS_BUMP_WRIOCTR(port, cnt);
2455fcf3ce44SJohn Forte 		TGTPORTSTAT.FctWriteBytes += cnt;
2456fcf3ce44SJohn Forte 		fct_task->task_flags |= TF_WRITE_DATA;
2457fcf3ce44SJohn Forte 		break;
2458fcf3ce44SJohn Forte 
2459fcf3ce44SJohn Forte 	case 2:
246082527734SSukumar Swaminathan 		EMLXS_BUMP_RDIOCTR(port, cnt);
2461fcf3ce44SJohn Forte 		TGTPORTSTAT.FctReadBytes += cnt;
2462fcf3ce44SJohn Forte 		fct_task->task_flags |= TF_READ_DATA;
2463fcf3ce44SJohn Forte 		break;
2464fcf3ce44SJohn Forte 	}
2465fcf3ce44SJohn Forte 
2466fcf3ce44SJohn Forte 	fct_task->task_priority = 0;
2467fcf3ce44SJohn Forte 
2468fcf3ce44SJohn Forte 	/* task_mgmt_function */
2469fcf3ce44SJohn Forte 	tm = fcp_cmd->fcpCntl2;
2470fcf3ce44SJohn Forte 	if (tm) {
2471fcf3ce44SJohn Forte 		if (tm & BIT_1) {
2472fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_ABORT_TASK_SET;
2473fcf3ce44SJohn Forte 		} else if (tm & BIT_2) {
2474fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_CLEAR_TASK_SET;
2475fcf3ce44SJohn Forte 		} else if (tm & BIT_4) {
2476fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_LUN_RESET;
2477fcf3ce44SJohn Forte 		} else if (tm & BIT_5) {
2478fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_TARGET_COLD_RESET;
2479fcf3ce44SJohn Forte 		} else if (tm & BIT_6) {
2480fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_CLEAR_ACA;
2481fcf3ce44SJohn Forte 		} else {
2482fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_ABORT_TASK;
2483fcf3ce44SJohn Forte 		}
2484fcf3ce44SJohn Forte 	}
2485291a2b48SSukumar Swaminathan 
2486fcf3ce44SJohn Forte 	/* Parallel buffers support - future */
2487fcf3ce44SJohn Forte 	fct_task->task_max_nbufs = 1;
2488fcf3ce44SJohn Forte 
2489fcf3ce44SJohn Forte 	fct_task->task_additional_flags = 0;
2490fcf3ce44SJohn Forte 	fct_task->task_cur_nbufs = 0;
2491fcf3ce44SJohn Forte 	fct_task->task_csn_size = 8;
2492fcf3ce44SJohn Forte 	fct_task->task_cmd_seq_no = 0;
2493fcf3ce44SJohn Forte 	fct_task->task_expected_xfer_length = cnt;
2494fcf3ce44SJohn Forte 	bcopy((void *)&fcp_cmd->fcpCdb, fct_task->task_cdb, 16);
2495fcf3ce44SJohn Forte 
2496fcf3ce44SJohn Forte 	TGTPORTSTAT.FctCmdReceived++;
2497fcf3ce44SJohn Forte 	TGTPORTSTAT.FctOutstandingIO++;
2498fcf3ce44SJohn Forte 
249982527734SSukumar Swaminathan 	emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
250082527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
2501fcf3ce44SJohn Forte 
2502291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
2503291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
250482527734SSukumar Swaminathan 	    "fct_post_rcvd_cmd:3 %p: portid x%x, %d", fct_cmd,
250582527734SSukumar Swaminathan 	    fct_cmd->cmd_lportid, fct_task->task_expected_xfer_length);
2506291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
250782527734SSukumar Swaminathan 
2508291a2b48SSukumar Swaminathan 	MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
2509fcf3ce44SJohn Forte 
2510fcf3ce44SJohn Forte 	return (0);
2511fcf3ce44SJohn Forte 
2512fcf3ce44SJohn Forte dropped:
2513fcf3ce44SJohn Forte 
2514fcf3ce44SJohn Forte 	TGTPORTSTAT.FctRcvDropped++;
2515fcf3ce44SJohn Forte 	return (1);
2516fcf3ce44SJohn Forte 
251782527734SSukumar Swaminathan } /* emlxs_fct_handle_unsol_req() */
2518fcf3ce44SJohn Forte 
2519fcf3ce44SJohn Forte 
252082527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
2521fcf3ce44SJohn Forte /* ARGSUSED */
2522fcf3ce44SJohn Forte static fct_status_t
2523fcf3ce44SJohn Forte emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd, stmf_data_buf_t *dbuf,
2524fcf3ce44SJohn Forte     uint32_t ioflags)
2525fcf3ce44SJohn Forte {
2526fcf3ce44SJohn Forte 	emlxs_port_t *port =
2527fcf3ce44SJohn Forte 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
2528fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2529fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
2530291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
2531fcf3ce44SJohn Forte 	scsi_task_t *fct_task;
2532291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2533fcf3ce44SJohn Forte 	IOCBQ *iocbq;
2534fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
2535fcf3ce44SJohn Forte 
253682527734SSukumar Swaminathan 	int	channel;
253782527734SSukumar Swaminathan 	int	channelno;
2538*b3660a96SSukumar Swaminathan 	fct_status_t rval = 0;
2539fcf3ce44SJohn Forte 
254082527734SSukumar Swaminathan 	rval = emlxs_fct_cmd_accept(port, fct_cmd, EMLXS_FCT_SEND_FCP_DATA);
254182527734SSukumar Swaminathan 	if (rval) {
254282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
254382527734SSukumar Swaminathan 		    "emlxs_fct_send_fcp_data: "
254482527734SSukumar Swaminathan 		    "Unable to accept fct_cmd. did=%x",
254582527734SSukumar Swaminathan 		    fct_cmd->cmd_rportid);
2546fcf3ce44SJohn Forte 
254782527734SSukumar Swaminathan 		return (rval);
2548fcf3ce44SJohn Forte 	}
254982527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2550291a2b48SSukumar Swaminathan 
255182527734SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
255282527734SSukumar Swaminathan #ifdef FCT_API_TRACE
255382527734SSukumar Swaminathan 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
255482527734SSukumar Swaminathan #endif /* FCT_API_TRACE */
255582527734SSukumar Swaminathan 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
2556291a2b48SSukumar Swaminathan 
2557fcf3ce44SJohn Forte 	cmd_sbp->node = ndlp;
2558fcf3ce44SJohn Forte 	cmd_sbp->fct_buf = dbuf;
2559fcf3ce44SJohn Forte 
256082527734SSukumar Swaminathan 	channelno = ((CHANNEL *)cmd_sbp->channel)->channelno;
256182527734SSukumar Swaminathan 
256282527734SSukumar Swaminathan 	channel = channelno;
256382527734SSukumar Swaminathan 
256482527734SSukumar Swaminathan 
256582527734SSukumar Swaminathan 
2566fcf3ce44SJohn Forte 	iocbq = &cmd_sbp->iocbq;
2567fcf3ce44SJohn Forte 
2568fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2569fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
257082527734SSukumar Swaminathan 	    "emlxs_fct_send_fcp_data %p: flgs=%x ioflags=%x dl=%d,%d,%d, %d",
2571fcf3ce44SJohn Forte 	    fct_cmd, dbuf->db_flags, ioflags, fct_task->task_cmd_xfer_length,
257282527734SSukumar Swaminathan 	    fct_task->task_nbytes_transferred, dbuf->db_data_size,
257382527734SSukumar Swaminathan 	    fct_task->task_expected_xfer_length);
2574291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2575fcf3ce44SJohn Forte 
257682527734SSukumar Swaminathan 	if (EMLXS_SLI_PREP_FCT_IOCB(port, cmd_sbp, channel) != IOERR_SUCCESS) {
257782527734SSukumar Swaminathan 
2578fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
257982527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2580fcf3ce44SJohn Forte 
2581fcf3ce44SJohn Forte 		return (FCT_BUSY);
2582fcf3ce44SJohn Forte 	}
2583291a2b48SSukumar Swaminathan 
2584fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_FCP_DATA;
2585fcf3ce44SJohn Forte 
2586fcf3ce44SJohn Forte 	if (dbuf->db_flags & DB_SEND_STATUS_GOOD) {
2587fcf3ce44SJohn Forte 		cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
2588fcf3ce44SJohn Forte 	}
2589fcf3ce44SJohn Forte 
2590fcf3ce44SJohn Forte 	if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
2591*b3660a96SSukumar Swaminathan 		if (emlxs_fct_dbuf_dma_sync(hba, dbuf, DDI_DMA_SYNC_FORDEV)) {
2592*b3660a96SSukumar Swaminathan 			emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
2593*b3660a96SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
2594*b3660a96SSukumar Swaminathan 
2595*b3660a96SSukumar Swaminathan 			return (FCT_BUSY);
2596*b3660a96SSukumar Swaminathan 		}
2597fcf3ce44SJohn Forte 	}
2598291a2b48SSukumar Swaminathan 
2599291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
260082527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_DATA_PENDING);
260182527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
260282527734SSukumar Swaminathan 
260382527734SSukumar Swaminathan 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cmd_sbp->channel, iocbq);
2604fcf3ce44SJohn Forte 
2605fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
2606fcf3ce44SJohn Forte 
260782527734SSukumar Swaminathan } /* emlxs_fct_send_fcp_data() */
2608fcf3ce44SJohn Forte 
2609fcf3ce44SJohn Forte 
261082527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
261182527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be released before exiting */
2612fcf3ce44SJohn Forte static fct_status_t
2613fcf3ce44SJohn Forte emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd)
2614fcf3ce44SJohn Forte {
2615fcf3ce44SJohn Forte 	emlxs_port_t *port =
2616fcf3ce44SJohn Forte 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
2617fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2618fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
2619fcf3ce44SJohn Forte 	scsi_task_t *fct_task;
2620fcf3ce44SJohn Forte 	fc_packet_t *pkt;
2621fcf3ce44SJohn Forte 	uint32_t did;
2622fcf3ce44SJohn Forte 	emlxs_fcp_rsp *fcp_rsp;
2623fcf3ce44SJohn Forte 	uint32_t size;
2624fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
262582527734SSukumar Swaminathan 	fct_status_t rval;
2626fcf3ce44SJohn Forte 
2627fcf3ce44SJohn Forte 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
2628fcf3ce44SJohn Forte 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
2629fcf3ce44SJohn Forte 	did = fct_cmd->cmd_rportid;
2630fcf3ce44SJohn Forte 
2631fcf3ce44SJohn Forte 	/* Initialize cmd_sbp */
2632fcf3ce44SJohn Forte 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2633fcf3ce44SJohn Forte 
263482527734SSukumar Swaminathan 	EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_SEND_FCP_STATUS);
2635291a2b48SSukumar Swaminathan 
2636fcf3ce44SJohn Forte 	cmd_sbp->node = ndlp;
2637fcf3ce44SJohn Forte 
2638fcf3ce44SJohn Forte 	size = 24;
2639fcf3ce44SJohn Forte 	if (fct_task->task_sense_length) {
2640fcf3ce44SJohn Forte 		size += fct_task->task_sense_length;
2641fcf3ce44SJohn Forte 	}
2642fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2643fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2644fcf3ce44SJohn Forte 	    "emlxs_fct_send_fcp_status %p: stat=%d resid=%d size=%d rx=%x",
2645fcf3ce44SJohn Forte 	    fct_cmd, fct_task->task_scsi_status,
2646fcf3ce44SJohn Forte 	    fct_task->task_resid, size, fct_cmd->cmd_rxid);
2647291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2648fcf3ce44SJohn Forte 
2649fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) {
2650fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2651fcf3ce44SJohn Forte 		    "emlxs_fct_send_fcp_status: Unable to allocate packet.");
2652fcf3ce44SJohn Forte 
2653fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
265482527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2655fcf3ce44SJohn Forte 
2656291a2b48SSukumar Swaminathan 		return (FCT_BUSY);
2657fcf3ce44SJohn Forte 	}
2658291a2b48SSukumar Swaminathan 
2659fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_FCP_STATUS;
2660fcf3ce44SJohn Forte 
2661fcf3ce44SJohn Forte 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
2662291a2b48SSukumar Swaminathan 	cmd_sbp->fct_pkt = pkt;
2663fcf3ce44SJohn Forte 
2664fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2665fcf3ce44SJohn Forte 	pkt->pkt_timeout =
2666fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
2667fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_fct_pkt_comp;
2668fcf3ce44SJohn Forte 
2669fcf3ce44SJohn Forte 	/* Build the fc header */
267082527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
2671fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
267282527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
2673fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP;
2674fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
2675fcf3ce44SJohn Forte 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2676fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
2677fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2678fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2679fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
2680fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
2681fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
2682fcf3ce44SJohn Forte 
2683fcf3ce44SJohn Forte 	/* Build the status payload */
2684fcf3ce44SJohn Forte 	fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd;
2685fcf3ce44SJohn Forte 
2686fcf3ce44SJohn Forte 	if (fct_task->task_resid) {
2687fcf3ce44SJohn Forte 		if (fct_task->task_status_ctrl & TASK_SCTRL_OVER) {
2688fcf3ce44SJohn Forte 			TGTPORTSTAT.FctScsiResidOver++;
2689fcf3ce44SJohn Forte 			fcp_rsp->rspStatus2 |= RESID_OVER;
269082527734SSukumar Swaminathan 			fcp_rsp->rspResId = LE_SWAP32(fct_task->task_resid);
2691fcf3ce44SJohn Forte 
2692fcf3ce44SJohn Forte 		} else if (fct_task->task_status_ctrl & TASK_SCTRL_UNDER) {
2693fcf3ce44SJohn Forte 			TGTPORTSTAT.FctScsiResidUnder++;
2694fcf3ce44SJohn Forte 			fcp_rsp->rspStatus2 |= RESID_UNDER;
269582527734SSukumar Swaminathan 			fcp_rsp->rspResId = LE_SWAP32(fct_task->task_resid);
2696fcf3ce44SJohn Forte 
2697fcf3ce44SJohn Forte 		}
2698fcf3ce44SJohn Forte 	}
2699291a2b48SSukumar Swaminathan 
2700fcf3ce44SJohn Forte 	if (fct_task->task_scsi_status) {
2701fcf3ce44SJohn Forte 		if (fct_task->task_scsi_status == SCSI_STAT_QUE_FULL) {
2702fcf3ce44SJohn Forte 			TGTPORTSTAT.FctScsiQfullErr++;
2703fcf3ce44SJohn Forte 		} else {
2704fcf3ce44SJohn Forte 			TGTPORTSTAT.FctScsiStatusErr++;
2705fcf3ce44SJohn Forte 		}
2706fcf3ce44SJohn Forte 
2707291a2b48SSukumar Swaminathan 		/* Make sure residual reported on non-SCSI_GOOD READ status */
2708fcf3ce44SJohn Forte 		if ((fct_task->task_flags & TF_READ_DATA) &&
2709fcf3ce44SJohn Forte 		    (fcp_rsp->rspResId == 0)) {
2710fcf3ce44SJohn Forte 			fcp_rsp->rspStatus2 |= RESID_UNDER;
2711291a2b48SSukumar Swaminathan 			fcp_rsp->rspResId =
2712291a2b48SSukumar Swaminathan 			    fct_task->task_expected_xfer_length;
2713fcf3ce44SJohn Forte 		}
2714fcf3ce44SJohn Forte 	}
2715291a2b48SSukumar Swaminathan 
2716291a2b48SSukumar Swaminathan 
2717fcf3ce44SJohn Forte 	if (fct_task->task_sense_length) {
2718fcf3ce44SJohn Forte 		TGTPORTSTAT.FctScsiSenseErr++;
2719fcf3ce44SJohn Forte 		fcp_rsp->rspStatus2 |= SNS_LEN_VALID;
272082527734SSukumar Swaminathan 		fcp_rsp->rspSnsLen = LE_SWAP32(fct_task->task_sense_length);
2721fcf3ce44SJohn Forte 
2722fcf3ce44SJohn Forte 		bcopy((uint8_t *)fct_task->task_sense_data,
2723291a2b48SSukumar Swaminathan 		    (uint8_t *)&fcp_rsp->rspInfo0,
2724291a2b48SSukumar Swaminathan 		    fct_task->task_sense_length);
2725fcf3ce44SJohn Forte 	}
2726291a2b48SSukumar Swaminathan 
2727fcf3ce44SJohn Forte 	fcp_rsp->rspStatus3 = fct_task->task_scsi_status;
2728fcf3ce44SJohn Forte 	fcp_rsp->rspRspLen = 0;
272982527734SSukumar Swaminathan 
2730291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
273182527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_STATUS_PENDING);
273282527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
2733fcf3ce44SJohn Forte 
2734fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
273582527734SSukumar Swaminathan 
2736fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2737fcf3ce44SJohn Forte 		    "emlxs_fct_send_fcp_status: Unable to send packet.");
2738fcf3ce44SJohn Forte 
273982527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
274082527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
274182527734SSukumar Swaminathan 		if (rval) {
274282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
274382527734SSukumar Swaminathan 			    "emlxs_fct_send_fcp_status: "
274482527734SSukumar Swaminathan 			    "Unable to acquire fct_cmd.");
274582527734SSukumar Swaminathan 			return (rval);
2746fcf3ce44SJohn Forte 		}
274782527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
2748291a2b48SSukumar Swaminathan 
2749fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
275082527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2751291a2b48SSukumar Swaminathan 
2752291a2b48SSukumar Swaminathan 		return (FCT_BUSY);
2753fcf3ce44SJohn Forte 	}
2754291a2b48SSukumar Swaminathan 
2755fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
2756fcf3ce44SJohn Forte 
275782527734SSukumar Swaminathan } /* emlxs_fct_send_fcp_status() */
2758fcf3ce44SJohn Forte 
2759fcf3ce44SJohn Forte 
2760fcf3ce44SJohn Forte static fct_status_t
2761291a2b48SSukumar Swaminathan emlxs_fct_send_qfull_reply(emlxs_port_t *port, emlxs_node_t *ndlp,
2762291a2b48SSukumar Swaminathan     uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd)
2763fcf3ce44SJohn Forte {
2764fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2765fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
2766fcf3ce44SJohn Forte 	fc_packet_t *pkt;
2767fcf3ce44SJohn Forte 	emlxs_fcp_rsp *fcp_rsp;
2768fcf3ce44SJohn Forte 	uint32_t size;
276982527734SSukumar Swaminathan 	CHANNEL *cp = &hba->chan[hba->CHANNEL_FCT];
2770fcf3ce44SJohn Forte 	uint8_t lun[8];
2771fcf3ce44SJohn Forte 
2772fcf3ce44SJohn Forte 	bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8);
2773fcf3ce44SJohn Forte 	size = 24;
2774fcf3ce44SJohn Forte 
2775fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) {
2776fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2777fcf3ce44SJohn Forte 		    "emlxs_fct_send_qfull_reply: Unable to allocate packet.");
2778fcf3ce44SJohn Forte 		return (FCT_FAILURE);
2779fcf3ce44SJohn Forte 	}
2780291a2b48SSukumar Swaminathan 
2781291a2b48SSukumar Swaminathan 
2782fcf3ce44SJohn Forte 	sbp = PKT2PRIV(pkt);
2783fcf3ce44SJohn Forte 	sbp->node = ndlp;
278482527734SSukumar Swaminathan 	sbp->channel = cp;
2785fcf3ce44SJohn Forte 	sbp->did = ndlp->nlp_DID;
2786fcf3ce44SJohn Forte 	sbp->lun = (lun[0] << 8) | lun[1];
2787fcf3ce44SJohn Forte 	sbp->class = class;
2788fcf3ce44SJohn Forte 
2789fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2790fcf3ce44SJohn Forte 	pkt->pkt_timeout =
2791fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
2792fcf3ce44SJohn Forte 
2793fcf3ce44SJohn Forte 	/* Build the fc header */
279482527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(ndlp->nlp_DID);
2795fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
279682527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
2797fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP;
2798fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
2799fcf3ce44SJohn Forte 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2800fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
2801fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2802fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2803fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
2804fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = xid;
2805fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
2806fcf3ce44SJohn Forte 
2807fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2808fcf3ce44SJohn Forte 	    "emlxs_fct_send_qfull_reply: Sending QFULL: x%x lun x%x: %d %d",
2809fcf3ce44SJohn Forte 	    xid, sbp->lun, TGTPORTSTAT.FctOutstandingIO,
2810fcf3ce44SJohn Forte 	    port->fct_port->port_max_xchges);
2811fcf3ce44SJohn Forte 
2812fcf3ce44SJohn Forte 	/* Build the status payload */
2813fcf3ce44SJohn Forte 	fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd;
2814fcf3ce44SJohn Forte 
2815fcf3ce44SJohn Forte 	TGTPORTSTAT.FctScsiQfullErr++;
2816fcf3ce44SJohn Forte 	fcp_rsp->rspStatus3 = SCSI_STAT_QUE_FULL;
2817fcf3ce44SJohn Forte 	fcp_rsp->rspStatus2 |= RESID_UNDER;
281882527734SSukumar Swaminathan 	fcp_rsp->rspResId = LE_SWAP32(fcp_cmd->fcpDl);
2819fcf3ce44SJohn Forte 
2820fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2821fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2822fcf3ce44SJohn Forte 		    "emlxs_fct_send_qfull_reply: Unable to send packet.");
2823fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
2824fcf3ce44SJohn Forte 		return (FCT_FAILURE);
2825fcf3ce44SJohn Forte 	}
2826fcf3ce44SJohn Forte 
2827291a2b48SSukumar Swaminathan 	return (FCT_SUCCESS);
2828fcf3ce44SJohn Forte 
282982527734SSukumar Swaminathan } /* emlxs_fct_send_qfull_reply() */
2830fcf3ce44SJohn Forte 
2831fcf3ce44SJohn Forte 
2832fcf3ce44SJohn Forte /* ARGSUSED */
2833fcf3ce44SJohn Forte extern int
283482527734SSukumar Swaminathan emlxs_fct_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2835fcf3ce44SJohn Forte {
2836fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2837fcf3ce44SJohn Forte 	IOCB *iocb;
2838fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
2839fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
2840fcf3ce44SJohn Forte 	uint32_t status;
2841fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
2842fcf3ce44SJohn Forte 	stmf_data_buf_t *dbuf;
2843fcf3ce44SJohn Forte 	scsi_task_t *fct_task;
2844291a2b48SSukumar Swaminathan 	fc_packet_t *pkt;
284582527734SSukumar Swaminathan 	uint32_t fct_flags;
284682527734SSukumar Swaminathan 	stmf_data_buf_t *fct_buf;
284782527734SSukumar Swaminathan 	fct_status_t rval;
2848fcf3ce44SJohn Forte 
2849fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
2850fcf3ce44SJohn Forte 	sbp = (emlxs_buf_t *)iocbq->sbp;
2851fcf3ce44SJohn Forte 
2852fcf3ce44SJohn Forte 	TGTPORTSTAT.FctEvent++;
2853fcf3ce44SJohn Forte 
2854fcf3ce44SJohn Forte 	if (!sbp) {
2855fcf3ce44SJohn Forte 		/* completion with missing xmit command */
2856fcf3ce44SJohn Forte 		TGTPORTSTAT.FctStray++;
2857fcf3ce44SJohn Forte 
2858fcf3ce44SJohn Forte 		/* emlxs_stray_fcp_completion_msg */
2859fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2860291a2b48SSukumar Swaminathan 		    "FCP event cmd=%x status=%x error=%x iotag=%x",
286182527734SSukumar Swaminathan 		    iocb->ULPCOMMAND, iocb->ULPSTATUS,
286282527734SSukumar Swaminathan 		    iocb->un.grsp.perr.statLocalError, iocb->ULPIOTAG);
2863fcf3ce44SJohn Forte 
2864fcf3ce44SJohn Forte 		return (1);
2865fcf3ce44SJohn Forte 	}
2866291a2b48SSukumar Swaminathan 
2867fcf3ce44SJohn Forte 	TGTPORTSTAT.FctCompleted++;
2868fcf3ce44SJohn Forte 
2869fcf3ce44SJohn Forte 	port = sbp->iocbq.port;
2870fcf3ce44SJohn Forte 	fct_cmd = sbp->fct_cmd;
287182527734SSukumar Swaminathan 	status = iocb->ULPSTATUS;
2872fcf3ce44SJohn Forte 
2873fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2874fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
287582527734SSukumar Swaminathan 	    "emlxs_fct_handle_fcp_event: %p: cmd=%x status=%x, %x",
287682527734SSukumar Swaminathan 	    fct_cmd, iocb->ULPCOMMAND, status, iocb->ULPCT);
2877291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2878fcf3ce44SJohn Forte 
2879fcf3ce44SJohn Forte 	if (fct_cmd == NULL) {
2880291a2b48SSukumar Swaminathan 		/* For driver generated QFULL response */
288182527734SSukumar Swaminathan 		if (((iocb->ULPCOMMAND == CMD_FCP_TRSP_CX) ||
288282527734SSukumar Swaminathan 		    (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX)) && sbp->pkt) {
2883fcf3ce44SJohn Forte 			emlxs_pkt_free(sbp->pkt);
2884fcf3ce44SJohn Forte 		}
2885fcf3ce44SJohn Forte 		return (0);
2886fcf3ce44SJohn Forte 	}
2887291a2b48SSukumar Swaminathan 
288882527734SSukumar Swaminathan 	rval = emlxs_fct_cmd_acquire(port, fct_cmd, EMLXS_FCT_REQ_COMPLETE);
288982527734SSukumar Swaminathan 	if (rval) {
289082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
289182527734SSukumar Swaminathan 		    "emlxs_fct_handle_fcp_event: "
289282527734SSukumar Swaminathan 		    "Unable to reacquire fct_cmd. type=%x",
289382527734SSukumar Swaminathan 		    fct_cmd->cmd_type);
289482527734SSukumar Swaminathan 
289582527734SSukumar Swaminathan 		return (1);
2896291a2b48SSukumar Swaminathan 	}
289782527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2898291a2b48SSukumar Swaminathan 
2899fcf3ce44SJohn Forte 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
290082527734SSukumar Swaminathan 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
2901291a2b48SSukumar Swaminathan 
2902291a2b48SSukumar Swaminathan 	pkt = cmd_sbp->fct_pkt;
290382527734SSukumar Swaminathan 	cmd_sbp->fct_pkt = NULL;
2904fcf3ce44SJohn Forte 
290582527734SSukumar Swaminathan 	dbuf = sbp->fct_buf;
2906fcf3ce44SJohn Forte 
2907291a2b48SSukumar Swaminathan 	fct_cmd->cmd_comp_status = FCT_SUCCESS;
2908291a2b48SSukumar Swaminathan 
2909291a2b48SSukumar Swaminathan 	if (status) {
2910*b3660a96SSukumar Swaminathan emlxs_dma_error:
2911fcf3ce44SJohn Forte 		/*
2912291a2b48SSukumar Swaminathan 		 * The error indicates this IO should be terminated
2913291a2b48SSukumar Swaminathan 		 * immediately.
2914fcf3ce44SJohn Forte 		 */
2915291a2b48SSukumar Swaminathan 		cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
291682527734SSukumar Swaminathan 		fct_cmd->cmd_comp_status = FCT_FAILURE;
2917291a2b48SSukumar Swaminathan 
291882527734SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
291982527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2920291a2b48SSukumar Swaminathan 
2921291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
2922291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2923291a2b48SSukumar Swaminathan 		    "fct_queue_cmd_for_termination:1 %p: x%x",
2924291a2b48SSukumar Swaminathan 		    fct_cmd, fct_cmd->cmd_comp_status);
2925291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
292682527734SSukumar Swaminathan 
2927291a2b48SSukumar Swaminathan 		MODSYM(fct_queue_cmd_for_termination) (fct_cmd,
2928291a2b48SSukumar Swaminathan 		    FCT_ABTS_RECEIVED);
292982527734SSukumar Swaminathan 
2930291a2b48SSukumar Swaminathan 		goto done;
2931291a2b48SSukumar Swaminathan 	}
2932291a2b48SSukumar Swaminathan 
293382527734SSukumar Swaminathan 	switch (iocb->ULPCOMMAND) {
2934291a2b48SSukumar Swaminathan 
2935291a2b48SSukumar Swaminathan 	/*
2936291a2b48SSukumar Swaminathan 	 *  FCP Data completion
2937291a2b48SSukumar Swaminathan 	 */
2938fcf3ce44SJohn Forte 	case CMD_FCP_TSEND_CX:
2939fcf3ce44SJohn Forte 	case CMD_FCP_TSEND64_CX:
2940fcf3ce44SJohn Forte 	case CMD_FCP_TRECEIVE_CX:
2941fcf3ce44SJohn Forte 	case CMD_FCP_TRECEIVE64_CX:
2942fcf3ce44SJohn Forte 
294382527734SSukumar Swaminathan 		if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) {
2944*b3660a96SSukumar Swaminathan 			if (emlxs_fct_dbuf_dma_sync(hba, dbuf,
2945*b3660a96SSukumar Swaminathan 			    DDI_DMA_SYNC_FORCPU)) {
2946*b3660a96SSukumar Swaminathan 				goto emlxs_dma_error;
2947*b3660a96SSukumar Swaminathan 			}
294882527734SSukumar Swaminathan 		}
2949fcf3ce44SJohn Forte 
295082527734SSukumar Swaminathan 		if ((cmd_sbp->fct_flags & EMLXS_FCT_SEND_STATUS) &&
295182527734SSukumar Swaminathan 		    (iocb->ULPCT != 1)) {
2952291a2b48SSukumar Swaminathan 
295382527734SSukumar Swaminathan 			dbuf->db_flags |= DB_STATUS_GOOD_SENT;
2954fcf3ce44SJohn Forte 
295582527734SSukumar Swaminathan 			fct_task =
295682527734SSukumar Swaminathan 			    (scsi_task_t *)fct_cmd->cmd_specific;
295782527734SSukumar Swaminathan 			fct_task->task_scsi_status = 0;
2958fcf3ce44SJohn Forte 
295982527734SSukumar Swaminathan 			(void) emlxs_fct_send_fcp_status(fct_cmd);
296082527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
2961fcf3ce44SJohn Forte 
296282527734SSukumar Swaminathan 			break;
296382527734SSukumar Swaminathan 
296482527734SSukumar Swaminathan 		} else if ((cmd_sbp->fct_flags &
296582527734SSukumar Swaminathan 		    EMLXS_FCT_SEND_STATUS) &&
296682527734SSukumar Swaminathan 		    (iocb->ULPCT == 1)) {
296782527734SSukumar Swaminathan 			/* Auto-resp has been sent out by firmware */
296882527734SSukumar Swaminathan 			/* We can assume this is really a FC_TRSP_CX */
296982527734SSukumar Swaminathan 
297082527734SSukumar Swaminathan 			dbuf->db_flags |= DB_STATUS_GOOD_SENT;
297182527734SSukumar Swaminathan 			fct_task =
297282527734SSukumar Swaminathan 			    (scsi_task_t *)fct_cmd->cmd_specific;
297382527734SSukumar Swaminathan 			fct_task->task_scsi_status = 0;
297482527734SSukumar Swaminathan 
297582527734SSukumar Swaminathan 			cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
297682527734SSukumar Swaminathan 
297782527734SSukumar Swaminathan 			goto auto_resp;
2978fcf3ce44SJohn Forte 		}
2979291a2b48SSukumar Swaminathan 
2980fcf3ce44SJohn Forte 		cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
2981fcf3ce44SJohn Forte 
2982fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
298382527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
298482527734SSukumar Swaminathan 
2985fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2986fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2987fcf3ce44SJohn Forte 		    "fct_scsi_data_xfer_done:1 %p %p", fct_cmd, dbuf);
2988291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
298982527734SSukumar Swaminathan 
2990fcf3ce44SJohn Forte 		MODSYM(fct_scsi_data_xfer_done) (fct_cmd, dbuf, 0);
2991fcf3ce44SJohn Forte 
2992fcf3ce44SJohn Forte 		break;
2993fcf3ce44SJohn Forte 
2994fcf3ce44SJohn Forte 		/* FCP Status completion */
2995fcf3ce44SJohn Forte 	case CMD_FCP_TRSP_CX:
2996fcf3ce44SJohn Forte 	case CMD_FCP_TRSP64_CX:
2997fcf3ce44SJohn Forte 
299882527734SSukumar Swaminathan auto_resp:
299982527734SSukumar Swaminathan 		/* Copy these before calling emlxs_fct_cmd_done */
300082527734SSukumar Swaminathan 		fct_flags = cmd_sbp->fct_flags;
300182527734SSukumar Swaminathan 		fct_buf = cmd_sbp->fct_buf;
3002fcf3ce44SJohn Forte 
300382527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
300482527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3005fcf3ce44SJohn Forte 
300682527734SSukumar Swaminathan 		TGTPORTSTAT.FctOutstandingIO--;
3007fcf3ce44SJohn Forte 
300882527734SSukumar Swaminathan 		if (fct_flags & EMLXS_FCT_SEND_STATUS) {
3009fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3010fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3011fcf3ce44SJohn Forte 			    "fct_scsi_data_xfer_done:2 %p %p",
301282527734SSukumar Swaminathan 			    fct_cmd, fct_buf);
3013291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
301482527734SSukumar Swaminathan 
3015fcf3ce44SJohn Forte 			MODSYM(fct_scsi_data_xfer_done) (fct_cmd,
301682527734SSukumar Swaminathan 			    fct_buf, FCT_IOF_FCA_DONE);
3017fcf3ce44SJohn Forte 		} else {
3018fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3019fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3020fcf3ce44SJohn Forte 			    "fct_send_response_done:1 %p: x%x",
3021fcf3ce44SJohn Forte 			    fct_cmd, fct_cmd->cmd_comp_status);
3022291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
302382527734SSukumar Swaminathan 
3024fcf3ce44SJohn Forte 			MODSYM(fct_send_response_done) (fct_cmd,
3025fcf3ce44SJohn Forte 			    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
3026fcf3ce44SJohn Forte 		}
3027fcf3ce44SJohn Forte 		break;
3028fcf3ce44SJohn Forte 
3029fcf3ce44SJohn Forte 	default:
303082527734SSukumar Swaminathan 		emlxs_fct_cmd_release(port, fct_cmd, 0);
303182527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3032291a2b48SSukumar Swaminathan 
3033fcf3ce44SJohn Forte 		TGTPORTSTAT.FctStray++;
3034fcf3ce44SJohn Forte 		TGTPORTSTAT.FctCompleted--;
3035fcf3ce44SJohn Forte 
3036fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
303782527734SSukumar Swaminathan 		    "Invalid iocb: cmd=0x%x", iocb->ULPCOMMAND);
3038fcf3ce44SJohn Forte 
3039291a2b48SSukumar Swaminathan 		if (pkt) {
3040291a2b48SSukumar Swaminathan 			emlxs_pkt_complete(sbp, status,
3041291a2b48SSukumar Swaminathan 			    iocb->un.grsp.perr.statLocalError, 1);
3042291a2b48SSukumar Swaminathan 		}
3043fcf3ce44SJohn Forte 
304482527734SSukumar Swaminathan 	}	/* switch(iocb->ULPCOMMAND) */
3045fcf3ce44SJohn Forte 
3046fcf3ce44SJohn Forte 
3047291a2b48SSukumar Swaminathan done:
3048291a2b48SSukumar Swaminathan 	if (pkt) {
3049291a2b48SSukumar Swaminathan 		emlxs_pkt_free(pkt);
3050291a2b48SSukumar Swaminathan 	}
3051291a2b48SSukumar Swaminathan 
3052fcf3ce44SJohn Forte 	if (status == IOSTAT_SUCCESS) {
3053fcf3ce44SJohn Forte 		TGTPORTSTAT.FctCmplGood++;
3054fcf3ce44SJohn Forte 	} else {
3055fcf3ce44SJohn Forte 		TGTPORTSTAT.FctCmplError++;
3056fcf3ce44SJohn Forte 	}
3057fcf3ce44SJohn Forte 
3058fcf3ce44SJohn Forte 	return (0);
3059fcf3ce44SJohn Forte 
306082527734SSukumar Swaminathan } /* emlxs_fct_handle_fcp_event() */
3061291a2b48SSukumar Swaminathan 
3062291a2b48SSukumar Swaminathan 
3063291a2b48SSukumar Swaminathan /* ARGSUSED */
3064291a2b48SSukumar Swaminathan extern int
306582527734SSukumar Swaminathan emlxs_fct_handle_abort(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
3066291a2b48SSukumar Swaminathan {
3067291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3068291a2b48SSukumar Swaminathan 	IOCB *iocb;
3069291a2b48SSukumar Swaminathan 	emlxs_buf_t *sbp;
3070291a2b48SSukumar Swaminathan 	fc_packet_t *pkt;
3071291a2b48SSukumar Swaminathan 
3072291a2b48SSukumar Swaminathan 	iocb = &iocbq->iocb;
3073291a2b48SSukumar Swaminathan 	sbp = (emlxs_buf_t *)iocbq->sbp;
3074291a2b48SSukumar Swaminathan 
3075291a2b48SSukumar Swaminathan 	TGTPORTSTAT.FctEvent++;
3076291a2b48SSukumar Swaminathan 
3077291a2b48SSukumar Swaminathan 	if (!sbp) {
3078291a2b48SSukumar Swaminathan 		/* completion with missing xmit command */
3079291a2b48SSukumar Swaminathan 		TGTPORTSTAT.FctStray++;
3080291a2b48SSukumar Swaminathan 
3081291a2b48SSukumar Swaminathan 		/* emlxs_stray_fcp_completion_msg */
3082291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3083291a2b48SSukumar Swaminathan 		    "ABORT event cmd=%x status=%x error=%x iotag=%x",
308482527734SSukumar Swaminathan 		    iocb->ULPCOMMAND, iocb->ULPSTATUS,
308582527734SSukumar Swaminathan 		    iocb->un.grsp.perr.statLocalError, iocb->ULPIOTAG);
3086291a2b48SSukumar Swaminathan 
3087291a2b48SSukumar Swaminathan 		return (1);
3088291a2b48SSukumar Swaminathan 	}
3089291a2b48SSukumar Swaminathan 
3090291a2b48SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
3091291a2b48SSukumar Swaminathan 
3092291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
3093291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
309482527734SSukumar Swaminathan 	    "emlxs_fct_handle_abort: %p: xri=%x status=%x", iocb->ULPCONTEXT,
309582527734SSukumar Swaminathan 	    iocb->ULPCOMMAND, iocb->ULPSTATUS);
3096291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
3097291a2b48SSukumar Swaminathan 
3098291a2b48SSukumar Swaminathan 
3099291a2b48SSukumar Swaminathan 	if (pkt) {
3100291a2b48SSukumar Swaminathan 		emlxs_pkt_free(pkt);
3101291a2b48SSukumar Swaminathan 	}
3102291a2b48SSukumar Swaminathan 	return (0);
3103fcf3ce44SJohn Forte 
310482527734SSukumar Swaminathan } /* emlxs_fct_handle_abort() */
3105fcf3ce44SJohn Forte 
3106fcf3ce44SJohn Forte 
3107fcf3ce44SJohn Forte extern int
310882527734SSukumar Swaminathan emlxs_fct_handle_unsol_els(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3109fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
3110fcf3ce44SJohn Forte {
3111fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
3112fcf3ce44SJohn Forte 	IOCB *iocb;
3113fcf3ce44SJohn Forte 	uint32_t cmd_code;
3114fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
3115fcf3ce44SJohn Forte 	fct_els_t *els;
3116fcf3ce44SJohn Forte 	uint32_t sid;
3117fcf3ce44SJohn Forte 	uint32_t padding;
3118fcf3ce44SJohn Forte 	uint8_t *bp;
3119fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
3120fcf3ce44SJohn Forte 	uint32_t rval;
3121fcf3ce44SJohn Forte 
3122fcf3ce44SJohn Forte 	HBASTATS.ElsCmdReceived++;
3123fcf3ce44SJohn Forte 
3124fcf3ce44SJohn Forte 	bp = mp->virt;
3125fcf3ce44SJohn Forte 	cmd_code = (*(uint32_t *)bp) & ELS_CMD_MASK;
3126fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
3127fcf3ce44SJohn Forte 	sid = iocb->un.elsreq.remoteID;
3128fcf3ce44SJohn Forte 
3129fcf3ce44SJohn Forte 	if (!port->fct_port) {
3130fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3131fcf3ce44SJohn Forte 		    "%s: sid=%x. Target unbound. Rejecting...",
3132fcf3ce44SJohn Forte 		    emlxs_elscmd_xlate(cmd_code), sid);
3133fcf3ce44SJohn Forte 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
3134fcf3ce44SJohn Forte 		    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
3135fcf3ce44SJohn Forte 
3136fcf3ce44SJohn Forte 		goto done;
3137fcf3ce44SJohn Forte 	}
3138291a2b48SSukumar Swaminathan 
3139fcf3ce44SJohn Forte 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
3140fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3141fcf3ce44SJohn Forte 		    "%s: sid=%x. Target offline. Rejecting...",
3142fcf3ce44SJohn Forte 		    emlxs_elscmd_xlate(cmd_code), sid);
3143fcf3ce44SJohn Forte 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
3144fcf3ce44SJohn Forte 		    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
3145fcf3ce44SJohn Forte 
3146fcf3ce44SJohn Forte 		goto done;
3147fcf3ce44SJohn Forte 	}
3148291a2b48SSukumar Swaminathan 
3149fcf3ce44SJohn Forte 	/* Process the request */
3150fcf3ce44SJohn Forte 	switch (cmd_code) {
3151fcf3ce44SJohn Forte 	case ELS_CMD_FLOGI:
3152e2ca2865SSukumar Swaminathan 		rval = emlxs_fct_process_unsol_flogi(port, cp, iocbq, mp, size);
3153291a2b48SSukumar Swaminathan 
3154291a2b48SSukumar Swaminathan 		if (!rval) {
3155291a2b48SSukumar Swaminathan 			ELS_PKT *els_pkt = (ELS_PKT *)bp;
3156e2ca2865SSukumar Swaminathan 			fct_flogi_xchg_t fx;
3157e2ca2865SSukumar Swaminathan 
3158e2ca2865SSukumar Swaminathan 			bzero((uint8_t *)&fx, sizeof (fct_flogi_xchg_t));
3159291a2b48SSukumar Swaminathan 
3160291a2b48SSukumar Swaminathan 			/* Save the FLOGI exchange information */
3161e2ca2865SSukumar Swaminathan 			fx.rsvd2 = iocb->ULPCONTEXT;
3162291a2b48SSukumar Swaminathan 			bcopy((caddr_t)&els_pkt->un.logi.nodeName,
3163e2ca2865SSukumar Swaminathan 			    (caddr_t)fx.fx_nwwn, 8);
3164291a2b48SSukumar Swaminathan 			bcopy((caddr_t)&els_pkt->un.logi.portName,
3165e2ca2865SSukumar Swaminathan 			    (caddr_t)fx.fx_pwwn, 8);
3166e2ca2865SSukumar Swaminathan 			fx.fx_sid = sid;
3167e2ca2865SSukumar Swaminathan 			fx.fx_did = iocb->un.elsreq.myID;
3168e2ca2865SSukumar Swaminathan 			fx.fx_fport = els_pkt->un.logi.cmn.fPort;
3169e2ca2865SSukumar Swaminathan 			fx.fx_op = ELS_OP_FLOGI;
3170e2ca2865SSukumar Swaminathan 
3171e2ca2865SSukumar Swaminathan 			emlxs_fct_handle_unsol_flogi(port, &fx, 1);
3172291a2b48SSukumar Swaminathan 		}
3173e2ca2865SSukumar Swaminathan 
3174291a2b48SSukumar Swaminathan 		goto done;
3175fcf3ce44SJohn Forte 
3176fcf3ce44SJohn Forte 	case ELS_CMD_PLOGI:
3177291a2b48SSukumar Swaminathan 		rval =
317882527734SSukumar Swaminathan 		    emlxs_fct_process_unsol_plogi(port, cp, iocbq, mp, size);
3179fcf3ce44SJohn Forte 		break;
3180fcf3ce44SJohn Forte 
3181fcf3ce44SJohn Forte 	default:
3182fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3183fcf3ce44SJohn Forte 		    "%s: sid=0x%x", emlxs_elscmd_xlate(cmd_code), sid);
3184fcf3ce44SJohn Forte 		rval = 0;
3185fcf3ce44SJohn Forte 		break;
3186fcf3ce44SJohn Forte 	}
3187fcf3ce44SJohn Forte 
3188fcf3ce44SJohn Forte 	if (rval) {
3189fcf3ce44SJohn Forte 		goto done;
3190fcf3ce44SJohn Forte 	}
3191291a2b48SSukumar Swaminathan 
3192fcf3ce44SJohn Forte 	padding = (8 - (size & 7)) & 7;
3193fcf3ce44SJohn Forte 
3194fcf3ce44SJohn Forte 	fct_cmd = (fct_cmd_t *)MODSYM(fct_alloc) (FCT_STRUCT_CMD_RCVD_ELS,
3195291a2b48SSukumar Swaminathan 	    (size + padding + GET_STRUCT_SIZE(emlxs_buf_t)),
3196291a2b48SSukumar Swaminathan 	    AF_FORCE_NOSLEEP);
3197fcf3ce44SJohn Forte 
3198fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3199fcf3ce44SJohn Forte 	{
3200fcf3ce44SJohn Forte 		uint32_t *ptr = (uint32_t *)bp;
3201fcf3ce44SJohn Forte 
3202fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3203fcf3ce44SJohn Forte 		    "fct_alloc %p: ELS rcvd: rxid=%x payload: x%x x%x",
320482527734SSukumar Swaminathan 		    fct_cmd, iocb->ULPCONTEXT, *ptr, *(ptr + 1));
3205fcf3ce44SJohn Forte 	}
3206291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
3207fcf3ce44SJohn Forte 
3208fcf3ce44SJohn Forte 	if (fct_cmd == NULL) {
3209fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3210fcf3ce44SJohn Forte 		    "%s: sid=%x. Out of memory. Rejecting...",
3211fcf3ce44SJohn Forte 		    emlxs_elscmd_xlate(cmd_code), sid);
3212fcf3ce44SJohn Forte 
3213fcf3ce44SJohn Forte 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
3214fcf3ce44SJohn Forte 		    LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
3215fcf3ce44SJohn Forte 		goto done;
3216fcf3ce44SJohn Forte 	}
3217291a2b48SSukumar Swaminathan 
3218fcf3ce44SJohn Forte 	/* Initialize fct_cmd */
3219fcf3ce44SJohn Forte 	fct_cmd->cmd_oxid = (cmd_code >> ELS_CMD_SHIFT) & 0xff;
322082527734SSukumar Swaminathan 	fct_cmd->cmd_rxid = iocb->ULPCONTEXT;
3221fcf3ce44SJohn Forte 	fct_cmd->cmd_rportid = sid;
3222fcf3ce44SJohn Forte 	fct_cmd->cmd_lportid = port->did;
322382527734SSukumar Swaminathan 	fct_cmd->cmd_rp_handle = iocb->ULPIOTAG;	/* RPI */
3224fcf3ce44SJohn Forte 	fct_cmd->cmd_port = port->fct_port;
3225fcf3ce44SJohn Forte 
322682527734SSukumar Swaminathan 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_ELS_CMD_RECEIVED);
322782527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
3228fcf3ce44SJohn Forte 
3229291a2b48SSukumar Swaminathan 	/* Initialize cmd_sbp */
323082527734SSukumar Swaminathan 	cmd_sbp->channel = cp;
323182527734SSukumar Swaminathan 	cmd_sbp->class = iocb->ULPCLASS;
3232fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD;
3233291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_PLOGI_RECEIVED;
3234291a2b48SSukumar Swaminathan 
3235fcf3ce44SJohn Forte 	bcopy((uint8_t *)iocb, (uint8_t *)&cmd_sbp->iocbq,
3236fcf3ce44SJohn Forte 	    sizeof (emlxs_iocb_t));
3237fcf3ce44SJohn Forte 
3238fcf3ce44SJohn Forte 	els = (fct_els_t *)fct_cmd->cmd_specific;
3239fcf3ce44SJohn Forte 	els->els_req_size = size;
3240291a2b48SSukumar Swaminathan 	els->els_req_payload =
3241291a2b48SSukumar Swaminathan 	    GET_BYTE_OFFSET(fct_cmd->cmd_fca_private,
3242fcf3ce44SJohn Forte 	    GET_STRUCT_SIZE(emlxs_buf_t));
3243fcf3ce44SJohn Forte 	bcopy(bp, els->els_req_payload, size);
3244fcf3ce44SJohn Forte 
3245e2ca2865SSukumar Swaminathan 
3246e2ca2865SSukumar Swaminathan 	/* Check if Offline */
3247e2ca2865SSukumar Swaminathan 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
3248e2ca2865SSukumar Swaminathan 
3249e2ca2865SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
3250e2ca2865SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3251e2ca2865SSukumar Swaminathan 
3252e2ca2865SSukumar Swaminathan #ifdef FCT_API_TRACE
3253e2ca2865SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3254e2ca2865SSukumar Swaminathan 		    "fct_post_rcvd_cmd:4 %p: portid x%x", fct_cmd,
3255e2ca2865SSukumar Swaminathan 		    fct_cmd->cmd_lportid);
3256e2ca2865SSukumar Swaminathan #endif /* FCT_API_TRACE */
3257e2ca2865SSukumar Swaminathan 
3258e2ca2865SSukumar Swaminathan 		MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
3259e2ca2865SSukumar Swaminathan 
3260e2ca2865SSukumar Swaminathan 		goto done;
3261e2ca2865SSukumar Swaminathan 	}
3262e2ca2865SSukumar Swaminathan 
3263e2ca2865SSukumar Swaminathan 	/* Online */
3264e2ca2865SSukumar Swaminathan 	/* Check if Link up is acked */
3265e2ca2865SSukumar Swaminathan 	if (port->fct_flags & FCT_STATE_LINK_UP_ACKED) {
3266e2ca2865SSukumar Swaminathan 
3267e2ca2865SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
3268e2ca2865SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3269e2ca2865SSukumar Swaminathan 
3270e2ca2865SSukumar Swaminathan #ifdef FCT_API_TRACE
3271e2ca2865SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3272e2ca2865SSukumar Swaminathan 		    "fct_post_rcvd_cmd:1 %p: portid x%x", fct_cmd,
3273e2ca2865SSukumar Swaminathan 		    fct_cmd->cmd_lportid);
3274e2ca2865SSukumar Swaminathan #endif /* FCT_API_TRACE */
3275e2ca2865SSukumar Swaminathan 
3276e2ca2865SSukumar Swaminathan 		MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
3277e2ca2865SSukumar Swaminathan 
3278e2ca2865SSukumar Swaminathan 		goto done;
3279e2ca2865SSukumar Swaminathan 
3280e2ca2865SSukumar Swaminathan 	}
3281e2ca2865SSukumar Swaminathan 
3282e2ca2865SSukumar Swaminathan 	/* Defer processing of fct_cmd till later (after link up ack). */
3283e2ca2865SSukumar Swaminathan 
3284e2ca2865SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_CMD_WAITQ);
3285e2ca2865SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
3286e2ca2865SSukumar Swaminathan 
3287e2ca2865SSukumar Swaminathan 	/* Add cmd_sbp to queue tail */
3288e2ca2865SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
3289e2ca2865SSukumar Swaminathan 
3290e2ca2865SSukumar Swaminathan 	if (port->fct_wait_tail) {
3291e2ca2865SSukumar Swaminathan 		port->fct_wait_tail->next = cmd_sbp;
3292e2ca2865SSukumar Swaminathan 	}
3293e2ca2865SSukumar Swaminathan 	port->fct_wait_tail = cmd_sbp;
3294e2ca2865SSukumar Swaminathan 
3295e2ca2865SSukumar Swaminathan 	if (!port->fct_wait_head) {
3296e2ca2865SSukumar Swaminathan 		port->fct_wait_head = cmd_sbp;
3297e2ca2865SSukumar Swaminathan 	}
3298e2ca2865SSukumar Swaminathan 
3299e2ca2865SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
3300fcf3ce44SJohn Forte 
3301fcf3ce44SJohn Forte done:
3302fcf3ce44SJohn Forte 
3303fcf3ce44SJohn Forte 	return (0);
3304fcf3ce44SJohn Forte 
330582527734SSukumar Swaminathan } /* emlxs_fct_handle_unsol_els() */
3306fcf3ce44SJohn Forte 
3307fcf3ce44SJohn Forte 
3308fcf3ce44SJohn Forte /* ARGSUSED */
3309fcf3ce44SJohn Forte static uint32_t
331082527734SSukumar Swaminathan emlxs_fct_process_unsol_flogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3311fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
3312fcf3ce44SJohn Forte {
3313fcf3ce44SJohn Forte 	IOCB *iocb;
3314fcf3ce44SJohn Forte 	char buffer[64];
3315fcf3ce44SJohn Forte 
3316fcf3ce44SJohn Forte 	buffer[0] = 0;
3317fcf3ce44SJohn Forte 
3318fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
3319fcf3ce44SJohn Forte 
3320fcf3ce44SJohn Forte 	/* Perform processing of FLOGI payload */
3321fcf3ce44SJohn Forte 	if (emlxs_process_unsol_flogi(port, iocbq, mp, size, buffer)) {
3322fcf3ce44SJohn Forte 		return (1);
3323fcf3ce44SJohn Forte 	}
3324291a2b48SSukumar Swaminathan 
3325fe199829SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3326fe199829SSukumar Swaminathan 	    "FLOGI: sid=0x%x xid=%x %s",
3327fe199829SSukumar Swaminathan 	    iocb->un.elsreq.remoteID, iocb->ULPIOTAG, buffer);
3328fcf3ce44SJohn Forte 
3329fcf3ce44SJohn Forte 	return (0);
3330fcf3ce44SJohn Forte 
333182527734SSukumar Swaminathan } /* emlxs_fct_process_unsol_flogi() */
3332fcf3ce44SJohn Forte 
3333fcf3ce44SJohn Forte 
3334fcf3ce44SJohn Forte /* ARGSUSED */
3335fcf3ce44SJohn Forte static uint32_t
333682527734SSukumar Swaminathan emlxs_fct_process_unsol_plogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3337fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
3338fcf3ce44SJohn Forte {
3339fcf3ce44SJohn Forte 	IOCB *iocb;
3340fcf3ce44SJohn Forte 	char buffer[64];
3341fcf3ce44SJohn Forte 
3342fcf3ce44SJohn Forte 	buffer[0] = 0;
3343fcf3ce44SJohn Forte 
3344fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
3345fcf3ce44SJohn Forte 
3346fcf3ce44SJohn Forte 	/* Perform processing of PLOGI payload */
3347fcf3ce44SJohn Forte 	if (emlxs_process_unsol_plogi(port, iocbq, mp, size, buffer)) {
3348fcf3ce44SJohn Forte 		return (1);
3349fcf3ce44SJohn Forte 	}
3350291a2b48SSukumar Swaminathan 
3351fe199829SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3352fe199829SSukumar Swaminathan 	    "PLOGI: sid=0x%x xid=%x %s",
3353fe199829SSukumar Swaminathan 	    iocb->un.elsreq.remoteID, iocb->ULPIOTAG, buffer);
3354fcf3ce44SJohn Forte 
3355fcf3ce44SJohn Forte 	return (0);
3356fcf3ce44SJohn Forte 
335782527734SSukumar Swaminathan } /* emlxs_fct_process_unsol_plogi() */
3358fcf3ce44SJohn Forte 
3359fcf3ce44SJohn Forte 
3360fcf3ce44SJohn Forte /* ARGSUSED */
3361fcf3ce44SJohn Forte static emlxs_buf_t *
3362291a2b48SSukumar Swaminathan emlxs_fct_pkt_init(emlxs_port_t *port, fct_cmd_t *fct_cmd,
3363291a2b48SSukumar Swaminathan     fc_packet_t *pkt)
3364fcf3ce44SJohn Forte {
3365fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
3366fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
3367fcf3ce44SJohn Forte 
3368fcf3ce44SJohn Forte 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3369fcf3ce44SJohn Forte 
3370fcf3ce44SJohn Forte 	sbp = PKT2PRIV(pkt);
3371fcf3ce44SJohn Forte 	sbp->fct_cmd = cmd_sbp->fct_cmd;
3372fcf3ce44SJohn Forte 	sbp->node = cmd_sbp->node;
337382527734SSukumar Swaminathan 	sbp->channel = cmd_sbp->channel;
3374fcf3ce44SJohn Forte 	sbp->did = cmd_sbp->did;
3375fcf3ce44SJohn Forte 	sbp->lun = cmd_sbp->lun;
3376fcf3ce44SJohn Forte 	sbp->class = cmd_sbp->class;
3377fcf3ce44SJohn Forte 	sbp->fct_type = cmd_sbp->fct_type;
3378fcf3ce44SJohn Forte 	sbp->fct_state = cmd_sbp->fct_state;
3379fcf3ce44SJohn Forte 
3380fcf3ce44SJohn Forte 	return (sbp);
3381fcf3ce44SJohn Forte 
338282527734SSukumar Swaminathan } /* emlxs_fct_pkt_init() */
3383fcf3ce44SJohn Forte 
3384fcf3ce44SJohn Forte 
3385fcf3ce44SJohn Forte /* Mutex will be acquired */
3386fcf3ce44SJohn Forte static emlxs_buf_t *
338782527734SSukumar Swaminathan emlxs_fct_cmd_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint32_t fct_state)
3388fcf3ce44SJohn Forte {
3389fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
3390fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3391fcf3ce44SJohn Forte 
3392fcf3ce44SJohn Forte 	bzero((void *)cmd_sbp, sizeof (emlxs_buf_t));
3393291a2b48SSukumar Swaminathan 	mutex_init(&cmd_sbp->fct_mtx, NULL, MUTEX_DRIVER,
3394291a2b48SSukumar Swaminathan 	    (void *)hba->intr_arg);
3395fcf3ce44SJohn Forte 	mutex_init(&cmd_sbp->mtx, NULL, MUTEX_DRIVER, (void *)hba->intr_arg);
3396fcf3ce44SJohn Forte 
3397291a2b48SSukumar Swaminathan 	mutex_enter(&cmd_sbp->fct_mtx);
3398fcf3ce44SJohn Forte 	cmd_sbp->pkt_flags = PACKET_VALID;
3399fcf3ce44SJohn Forte 	cmd_sbp->port = port;
3400fcf3ce44SJohn Forte 	cmd_sbp->fct_cmd = fct_cmd;
3401fcf3ce44SJohn Forte 	cmd_sbp->node = (fct_cmd->cmd_rp) ?
3402fcf3ce44SJohn Forte 	    *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private : NULL;
3403fcf3ce44SJohn Forte 	cmd_sbp->iocbq.sbp = cmd_sbp;
3404291a2b48SSukumar Swaminathan 	cmd_sbp->iocbq.port = port;
340582527734SSukumar Swaminathan 	cmd_sbp->did = fct_cmd->cmd_rportid;
340682527734SSukumar Swaminathan 
340782527734SSukumar Swaminathan 	/* Flags fct_cmd as inuse */
340882527734SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
340982527734SSukumar Swaminathan 		fct_cmd->cmd_oxid = 0xffff;
341082527734SSukumar Swaminathan 		fct_cmd->cmd_rxid = 0xffff;
341182527734SSukumar Swaminathan 	}
341282527734SSukumar Swaminathan 
341382527734SSukumar Swaminathan 	if (fct_state) {
341482527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
341582527734SSukumar Swaminathan 	}
3416fcf3ce44SJohn Forte 
3417fcf3ce44SJohn Forte 	return (cmd_sbp);
3418fcf3ce44SJohn Forte 
341982527734SSukumar Swaminathan } /* emlxs_fct_cmd_init() */
3420fcf3ce44SJohn Forte 
3421fcf3ce44SJohn Forte 
342282527734SSukumar Swaminathan /* Called after receiving fct_cmd from COMSTAR */
342382527734SSukumar Swaminathan static fct_status_t
342482527734SSukumar Swaminathan emlxs_fct_cmd_accept(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state)
3425fcf3ce44SJohn Forte {
3426fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3427fcf3ce44SJohn Forte 
342882527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
342982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
343082527734SSukumar Swaminathan 		    "emlxs_fct_cmd_accept: "
343182527734SSukumar Swaminathan 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
343282527734SSukumar Swaminathan 		    fct_cmd, fct_state);
343382527734SSukumar Swaminathan 
343482527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
343582527734SSukumar Swaminathan 	}
343682527734SSukumar Swaminathan 
343782527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->fct_mtx);
343882527734SSukumar Swaminathan 
343982527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
344082527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
344182527734SSukumar Swaminathan 
344282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
344382527734SSukumar Swaminathan 		    "emlxs_fct_cmd_accept:2 "
344482527734SSukumar Swaminathan 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
344582527734SSukumar Swaminathan 		    fct_cmd, fct_state);
344682527734SSukumar Swaminathan 
344782527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
344882527734SSukumar Swaminathan 	}
344982527734SSukumar Swaminathan 
345082527734SSukumar Swaminathan 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) {
345182527734SSukumar Swaminathan 
345282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
345382527734SSukumar Swaminathan 		    "emlxs_fct_cmd_accept: "
345482527734SSukumar Swaminathan 		    "Aborted fct_cmd found! fct_cmd=%p state=%x",
345582527734SSukumar Swaminathan 		    fct_cmd, fct_state);
345682527734SSukumar Swaminathan 
345782527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_ABORT_DONE);
345882527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
345982527734SSukumar Swaminathan 
346082527734SSukumar Swaminathan 		MODSYM(fct_cmd_fca_aborted) (fct_cmd,
346182527734SSukumar Swaminathan 		    FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
346282527734SSukumar Swaminathan 
346382527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
346482527734SSukumar Swaminathan 	}
346582527734SSukumar Swaminathan 
346682527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->mtx);
346782527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) {
346882527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->mtx);
346982527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
347082527734SSukumar Swaminathan 
347182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
347282527734SSukumar Swaminathan 		    "emlxs_fct_cmd_accept: "
347382527734SSukumar Swaminathan 		    "Busy fct_cmd found! fct_cmd=%p state=%x",
347482527734SSukumar Swaminathan 		    fct_cmd, fct_state);
347582527734SSukumar Swaminathan 
347682527734SSukumar Swaminathan 		return (FCT_BUSY);
347782527734SSukumar Swaminathan 	}
347882527734SSukumar Swaminathan 	cmd_sbp->pkt_flags &= ~PACKET_ULP_OWNED;
347982527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->mtx);
348082527734SSukumar Swaminathan 
348182527734SSukumar Swaminathan 	if (fct_state) {
348282527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
348382527734SSukumar Swaminathan 	}
348482527734SSukumar Swaminathan 
348582527734SSukumar Swaminathan 	return (FCT_SUCCESS);
348682527734SSukumar Swaminathan 
348782527734SSukumar Swaminathan } /* emlxs_fct_cmd_accept() */
348882527734SSukumar Swaminathan 
348982527734SSukumar Swaminathan 
349082527734SSukumar Swaminathan /* Called after receiving fct_cmd from driver */
349182527734SSukumar Swaminathan static fct_status_t
349282527734SSukumar Swaminathan emlxs_fct_cmd_acquire(emlxs_port_t *port, fct_cmd_t *fct_cmd,
349382527734SSukumar Swaminathan     uint16_t fct_state)
349482527734SSukumar Swaminathan {
349582527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
349682527734SSukumar Swaminathan 
349782527734SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
349882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
349982527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire: "
350082527734SSukumar Swaminathan 		    "Bad fct_cmd found! fct_cmd=%p state=%x",
350182527734SSukumar Swaminathan 		    fct_cmd, fct_state);
350282527734SSukumar Swaminathan 
350382527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
350482527734SSukumar Swaminathan 	}
350582527734SSukumar Swaminathan 
350682527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
350782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
350882527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire: "
350982527734SSukumar Swaminathan 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
351082527734SSukumar Swaminathan 		    fct_cmd, fct_state);
351182527734SSukumar Swaminathan 
351282527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
351382527734SSukumar Swaminathan 	}
351482527734SSukumar Swaminathan 
351582527734SSukumar Swaminathan 	if ((cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) {
351682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
351782527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire: "
351882527734SSukumar Swaminathan 		    "Returned fct_cmd found! fct_cmd=%p state=%x",
351982527734SSukumar Swaminathan 		    fct_cmd, fct_state);
352082527734SSukumar Swaminathan 
352182527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
352282527734SSukumar Swaminathan 	}
352382527734SSukumar Swaminathan 
352482527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->fct_mtx);
352582527734SSukumar Swaminathan 
352682527734SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
352782527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
352882527734SSukumar Swaminathan 
352982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
353082527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire:2 "
353182527734SSukumar Swaminathan 		    "Bad fct_cmd found! fct_cmd=%p state=%x",
353282527734SSukumar Swaminathan 		    fct_cmd, fct_state);
3533291a2b48SSukumar Swaminathan 
353482527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
353582527734SSukumar Swaminathan 	}
3536291a2b48SSukumar Swaminathan 
3537fcf3ce44SJohn Forte 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
353882527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
353982527734SSukumar Swaminathan 
354082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
354182527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire:2 "
354282527734SSukumar Swaminathan 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
354382527734SSukumar Swaminathan 		    fct_cmd, fct_state);
354482527734SSukumar Swaminathan 
354582527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
354682527734SSukumar Swaminathan 	}
354782527734SSukumar Swaminathan 
354882527734SSukumar Swaminathan 	if ((cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) {
354982527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
355082527734SSukumar Swaminathan 
355182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
355282527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire:2 "
355382527734SSukumar Swaminathan 		    "Returned fct_cmd found! fct_cmd=%p state=%x",
355482527734SSukumar Swaminathan 		    fct_cmd, fct_state);
355582527734SSukumar Swaminathan 
355682527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
355782527734SSukumar Swaminathan 	}
355882527734SSukumar Swaminathan 
355982527734SSukumar Swaminathan 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) {
356082527734SSukumar Swaminathan 
356182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
356282527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire: "
356382527734SSukumar Swaminathan 		    "Aborting cmd. fct_cmd=%p state=%x",
356482527734SSukumar Swaminathan 		    fct_cmd, fct_state);
356582527734SSukumar Swaminathan 
356682527734SSukumar Swaminathan 		if (fct_cmd->cmd_type == FCT_CMD_FCP_XCHG) {
356782527734SSukumar Swaminathan 			TGTPORTSTAT.FctOutstandingIO--;
356882527734SSukumar Swaminathan 		}
356982527734SSukumar Swaminathan 
357082527734SSukumar Swaminathan 		fct_cmd->cmd_comp_status = FCT_FAILURE;
357182527734SSukumar Swaminathan 
357282527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_ABORT_DONE);
357382527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
357482527734SSukumar Swaminathan 
357582527734SSukumar Swaminathan 		MODSYM(fct_cmd_fca_aborted) (fct_cmd,
357682527734SSukumar Swaminathan 		    FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
357782527734SSukumar Swaminathan 
357882527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
357982527734SSukumar Swaminathan 	}
358082527734SSukumar Swaminathan 
358182527734SSukumar Swaminathan 	if (fct_state) {
358282527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
358382527734SSukumar Swaminathan 	}
358482527734SSukumar Swaminathan 
358582527734SSukumar Swaminathan 	return (FCT_SUCCESS);
358682527734SSukumar Swaminathan 
358782527734SSukumar Swaminathan } /* emlxs_fct_cmd_acquire() */
358882527734SSukumar Swaminathan 
358982527734SSukumar Swaminathan 
359082527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
359182527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be released before exiting */
359282527734SSukumar Swaminathan /* Called before transitionally sending fct_cmd to driver */
359382527734SSukumar Swaminathan /*ARGSUSED*/
359482527734SSukumar Swaminathan static void
359582527734SSukumar Swaminathan emlxs_fct_cmd_release(emlxs_port_t *port, fct_cmd_t *fct_cmd,
359682527734SSukumar Swaminathan     uint16_t fct_state)
359782527734SSukumar Swaminathan {
359882527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
359982527734SSukumar Swaminathan 
360082527734SSukumar Swaminathan 	if (fct_state) {
360182527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
3602fcf3ce44SJohn Forte 	}
3603291a2b48SSukumar Swaminathan 
360482527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->fct_mtx);
360582527734SSukumar Swaminathan 
360682527734SSukumar Swaminathan 	return;
360782527734SSukumar Swaminathan 
360882527734SSukumar Swaminathan } /* emlxs_fct_cmd_release() */
360982527734SSukumar Swaminathan 
361082527734SSukumar Swaminathan 
361182527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
361282527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be released before exiting */
361382527734SSukumar Swaminathan /* Called before posting fct_cmd back to COMSTAR */
361482527734SSukumar Swaminathan /*ARGSUSED*/
361582527734SSukumar Swaminathan static void
361682527734SSukumar Swaminathan emlxs_fct_cmd_post(emlxs_port_t *port, fct_cmd_t *fct_cmd,
361782527734SSukumar Swaminathan     uint16_t fct_state)
361882527734SSukumar Swaminathan {
361982527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
362082527734SSukumar Swaminathan 	fc_packet_t *pkt;
362182527734SSukumar Swaminathan 
362282527734SSukumar Swaminathan 	pkt = cmd_sbp->fct_pkt;
362382527734SSukumar Swaminathan 	cmd_sbp->fct_pkt = NULL;
362482527734SSukumar Swaminathan 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
362582527734SSukumar Swaminathan 
362682527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->mtx);
362782527734SSukumar Swaminathan 	cmd_sbp->pkt_flags |= PACKET_ULP_OWNED;
362882527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->mtx);
362982527734SSukumar Swaminathan 
363082527734SSukumar Swaminathan 	if (fct_state) {
363182527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
363282527734SSukumar Swaminathan 	}
363382527734SSukumar Swaminathan 
363482527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->fct_mtx);
363582527734SSukumar Swaminathan 
363682527734SSukumar Swaminathan 	if (pkt) {
363782527734SSukumar Swaminathan 		emlxs_pkt_free(pkt);
363882527734SSukumar Swaminathan 	}
363982527734SSukumar Swaminathan 
364082527734SSukumar Swaminathan 	return;
364182527734SSukumar Swaminathan 
364282527734SSukumar Swaminathan } /* emlxs_fct_cmd_post() */
364382527734SSukumar Swaminathan 
364482527734SSukumar Swaminathan 
364582527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
364682527734SSukumar Swaminathan /* Called before completing fct_cmd back to COMSTAR */
364782527734SSukumar Swaminathan static void
364882527734SSukumar Swaminathan emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state)
364982527734SSukumar Swaminathan {
365082527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
365182527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
365282527734SSukumar Swaminathan 	fc_packet_t *pkt;
365382527734SSukumar Swaminathan 
365482527734SSukumar Swaminathan 	/* Flags fct_cmd is no longer used */
365582527734SSukumar Swaminathan 	fct_cmd->cmd_oxid = 0;
365682527734SSukumar Swaminathan 	fct_cmd->cmd_rxid = 0;
365782527734SSukumar Swaminathan 
3658fcf3ce44SJohn Forte 	if (cmd_sbp->iotag != 0) {
3659fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
366082527734SSukumar Swaminathan 		    "Pkt still registered! channel=%d iotag=%d sbp=%p",
366182527734SSukumar Swaminathan 		    cmd_sbp->channel, cmd_sbp->iotag, cmd_sbp);
366282527734SSukumar Swaminathan 
366382527734SSukumar Swaminathan 		if (cmd_sbp->channel) {
366482527734SSukumar Swaminathan 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
366582527734SSukumar Swaminathan 				hba->fc_table[cmd_sbp->iotag] = NULL;
366682527734SSukumar Swaminathan 				emlxs_sli4_free_xri(hba, cmd_sbp, cmd_sbp->xp);
366782527734SSukumar Swaminathan 			} else {
366882527734SSukumar Swaminathan 				(void) emlxs_unregister_pkt(cmd_sbp->channel,
366982527734SSukumar Swaminathan 				    cmd_sbp->iotag, 0);
367082527734SSukumar Swaminathan 			}
3671fcf3ce44SJohn Forte 
3672fcf3ce44SJohn Forte 		}
3673fcf3ce44SJohn Forte 	}
3674291a2b48SSukumar Swaminathan 
367582527734SSukumar Swaminathan 	pkt = cmd_sbp->fct_pkt;
367682527734SSukumar Swaminathan 	cmd_sbp->fct_pkt = NULL;
367782527734SSukumar Swaminathan 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
367882527734SSukumar Swaminathan 
367982527734SSukumar Swaminathan 	if (fct_state) {
368082527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
368182527734SSukumar Swaminathan 	}
3682fcf3ce44SJohn Forte 
368382527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->mtx);
368482527734SSukumar Swaminathan 	cmd_sbp->pkt_flags |= PACKET_ULP_OWNED;
368582527734SSukumar Swaminathan 	cmd_sbp->pkt_flags &= ~PACKET_VALID;
368682527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->mtx);
3687291a2b48SSukumar Swaminathan 	mutex_exit(&cmd_sbp->fct_mtx);
368882527734SSukumar Swaminathan 
368982527734SSukumar Swaminathan 
3690291a2b48SSukumar Swaminathan 	mutex_destroy(&cmd_sbp->fct_mtx);
369182527734SSukumar Swaminathan 	mutex_destroy(&cmd_sbp->mtx);
369282527734SSukumar Swaminathan 
369382527734SSukumar Swaminathan 	if (pkt) {
369482527734SSukumar Swaminathan 		emlxs_pkt_free(pkt);
369582527734SSukumar Swaminathan 	}
3696fcf3ce44SJohn Forte 
369782527734SSukumar Swaminathan 	return;
3698fcf3ce44SJohn Forte 
369982527734SSukumar Swaminathan } /* emlxs_fct_cmd_done() */
3700fcf3ce44SJohn Forte 
3701fcf3ce44SJohn Forte 
3702fcf3ce44SJohn Forte static void
3703fcf3ce44SJohn Forte emlxs_fct_pkt_comp(fc_packet_t *pkt)
3704fcf3ce44SJohn Forte {
3705fcf3ce44SJohn Forte 	emlxs_port_t *port;
3706291a2b48SSukumar Swaminathan #ifdef FMA_SUPPORT
3707291a2b48SSukumar Swaminathan 	emlxs_hba_t *hba;
3708291a2b48SSukumar Swaminathan #endif	/* FMA_SUPPORT */
3709fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
3710fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
3711fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
3712fcf3ce44SJohn Forte 	fct_els_t *fct_els;
3713fcf3ce44SJohn Forte 	fct_sol_ct_t *fct_ct;
371482527734SSukumar Swaminathan 	fct_status_t rval;
3715fcf3ce44SJohn Forte 
3716fcf3ce44SJohn Forte 	sbp = PKT2PRIV(pkt);
3717fcf3ce44SJohn Forte 	port = sbp->port;
3718291a2b48SSukumar Swaminathan #ifdef FMA_SUPPORT
3719291a2b48SSukumar Swaminathan 	hba = HBA;
3720291a2b48SSukumar Swaminathan #endif	/* FMA_SUPPORT */
3721fcf3ce44SJohn Forte 	fct_cmd = sbp->fct_cmd;
3722291a2b48SSukumar Swaminathan 
372382527734SSukumar Swaminathan 	rval = emlxs_fct_cmd_acquire(port, fct_cmd, EMLXS_FCT_PKT_COMPLETE);
372482527734SSukumar Swaminathan 	if (rval) {
372582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
372682527734SSukumar Swaminathan 		    "emlxs_fct_pkt_comp: "
372782527734SSukumar Swaminathan 		    "Unable to reacquire fct_cmd.");
372882527734SSukumar Swaminathan 		return;
3729291a2b48SSukumar Swaminathan 	}
373082527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
3731fcf3ce44SJohn Forte 
373282527734SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
373382527734SSukumar Swaminathan 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
3734fcf3ce44SJohn Forte 	cmd_sbp->fct_pkt = NULL;
3735fcf3ce44SJohn Forte 
3736291a2b48SSukumar Swaminathan 	switch (fct_cmd->cmd_type) {
3737291a2b48SSukumar Swaminathan 	case FCT_CMD_FCP_XCHG:
3738291a2b48SSukumar Swaminathan 		if ((pkt->pkt_reason == FC_REASON_ABORTED) ||
3739291a2b48SSukumar Swaminathan 		    (pkt->pkt_reason == FC_REASON_XCHG_DROPPED) ||
3740291a2b48SSukumar Swaminathan 		    (pkt->pkt_reason == FC_REASON_OFFLINE)) {
3741291a2b48SSukumar Swaminathan 			/*
3742291a2b48SSukumar Swaminathan 			 * The error indicates this IO should be terminated
3743291a2b48SSukumar Swaminathan 			 * immediately.
3744291a2b48SSukumar Swaminathan 			 */
3745291a2b48SSukumar Swaminathan 			cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
3746fcf3ce44SJohn Forte 
374782527734SSukumar Swaminathan 			emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
374882527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
3749fcf3ce44SJohn Forte 
3750291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
3751291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3752291a2b48SSukumar Swaminathan 			    "fct_queue_cmd_for_termination:2 %p: x%x",
3753291a2b48SSukumar Swaminathan 			    fct_cmd, fct_cmd->cmd_comp_status);
3754291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
375582527734SSukumar Swaminathan 
3756291a2b48SSukumar Swaminathan 			MODSYM(fct_queue_cmd_for_termination) (fct_cmd,
3757291a2b48SSukumar Swaminathan 			    FCT_ABTS_RECEIVED);
375882527734SSukumar Swaminathan 
375982527734SSukumar Swaminathan 			break;
3760291a2b48SSukumar Swaminathan 		}
3761fcf3ce44SJohn Forte 
376282527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3763291a2b48SSukumar Swaminathan 		    EMLXS_FCT_PKT_FCPRSP_COMPLETE);
3764291a2b48SSukumar Swaminathan 
376582527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3766291a2b48SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3767fcf3ce44SJohn Forte 
3768fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3769fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3770fcf3ce44SJohn Forte 		    "fct_send_response_done:2 %p: x%x",
3771fcf3ce44SJohn Forte 		    fct_cmd, fct_cmd->cmd_comp_status);
3772fcf3ce44SJohn Forte #else
3773fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3774fcf3ce44SJohn Forte 		    "emlxs_fct_pkt_comp: fct_send_response_done. dbuf=%p",
3775fcf3ce44SJohn Forte 		    sbp->fct_buf);
3776291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
3777291a2b48SSukumar Swaminathan 
3778291a2b48SSukumar Swaminathan 		TGTPORTSTAT.FctOutstandingIO--;
3779fcf3ce44SJohn Forte 
3780fcf3ce44SJohn Forte 		MODSYM(fct_send_response_done) (fct_cmd,
3781fcf3ce44SJohn Forte 		    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
3782fcf3ce44SJohn Forte 
3783fcf3ce44SJohn Forte 		break;
3784fcf3ce44SJohn Forte 
3785fcf3ce44SJohn Forte 	case FCT_CMD_RCVD_ELS:
3786fcf3ce44SJohn Forte 
378782527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3788291a2b48SSukumar Swaminathan 		    EMLXS_FCT_PKT_ELSRSP_COMPLETE);
3789291a2b48SSukumar Swaminathan 
379082527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3791291a2b48SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3792fcf3ce44SJohn Forte 
3793fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3794fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3795fcf3ce44SJohn Forte 		    "fct_send_response_done:3 %p: x%x",
3796fcf3ce44SJohn Forte 		    fct_cmd, fct_cmd->cmd_comp_status);
3797291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
379882527734SSukumar Swaminathan 
3799fcf3ce44SJohn Forte 		MODSYM(fct_send_response_done) (fct_cmd,
3800fcf3ce44SJohn Forte 		    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
3801fcf3ce44SJohn Forte 
3802fcf3ce44SJohn Forte 		break;
3803fcf3ce44SJohn Forte 
3804fcf3ce44SJohn Forte 	case FCT_CMD_SOL_ELS:
3805291a2b48SSukumar Swaminathan 
380682527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3807291a2b48SSukumar Swaminathan 		    EMLXS_FCT_PKT_ELSCMD_COMPLETE);
3808291a2b48SSukumar Swaminathan 
3809fcf3ce44SJohn Forte 		fct_els = (fct_els_t *)fct_cmd->cmd_specific;
3810fcf3ce44SJohn Forte 
3811fcf3ce44SJohn Forte 		if (fct_els->els_resp_payload) {
381282527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0,
3813291a2b48SSukumar Swaminathan 			    pkt->pkt_rsplen, DDI_DMA_SYNC_FORKERNEL);
3814fcf3ce44SJohn Forte 
3815fcf3ce44SJohn Forte 			bcopy((uint8_t *)pkt->pkt_resp,
3816fcf3ce44SJohn Forte 			    (uint8_t *)fct_els->els_resp_payload,
3817fcf3ce44SJohn Forte 			    fct_els->els_resp_size);
3818fcf3ce44SJohn Forte 		}
3819291a2b48SSukumar Swaminathan 
382082527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3821291a2b48SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3822fcf3ce44SJohn Forte 
3823fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3824fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3825fcf3ce44SJohn Forte 		    "fct_send_cmd_done:1 %p: x%x",
3826fcf3ce44SJohn Forte 		    fct_cmd, fct_cmd->cmd_comp_status);
3827291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
382882527734SSukumar Swaminathan 
3829*b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3830*b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma)
3831*b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
3832*b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3833*b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
3834*b3660a96SSukumar Swaminathan 			    "emlxs_fct_pkt_comp: hdl=%p",
3835*b3660a96SSukumar Swaminathan 			    pkt->pkt_resp_dma);
3836*b3660a96SSukumar Swaminathan 			MODSYM(fct_send_cmd_done) (fct_cmd, FCT_FAILURE,
3837*b3660a96SSukumar Swaminathan 			    FCT_IOF_FCA_DONE);
3838*b3660a96SSukumar Swaminathan 
3839*b3660a96SSukumar Swaminathan 			break;
3840*b3660a96SSukumar Swaminathan 		}
3841*b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */
3842*b3660a96SSukumar Swaminathan 
3843291a2b48SSukumar Swaminathan 		MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS,
3844291a2b48SSukumar Swaminathan 		    FCT_IOF_FCA_DONE);
3845fcf3ce44SJohn Forte 
3846fcf3ce44SJohn Forte 		break;
3847fcf3ce44SJohn Forte 
3848fcf3ce44SJohn Forte 	case FCT_CMD_SOL_CT:
3849291a2b48SSukumar Swaminathan 
385082527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3851291a2b48SSukumar Swaminathan 		    EMLXS_FCT_PKT_CTCMD_COMPLETE);
3852291a2b48SSukumar Swaminathan 
3853fcf3ce44SJohn Forte 		fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific;
3854fcf3ce44SJohn Forte 
3855fcf3ce44SJohn Forte 		if (fct_ct->ct_resp_payload) {
385682527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0,
3857291a2b48SSukumar Swaminathan 			    pkt->pkt_rsplen, DDI_DMA_SYNC_FORKERNEL);
3858fcf3ce44SJohn Forte 
3859fcf3ce44SJohn Forte 			bcopy((uint8_t *)pkt->pkt_resp,
3860fcf3ce44SJohn Forte 			    (uint8_t *)fct_ct->ct_resp_payload,
3861fcf3ce44SJohn Forte 			    fct_ct->ct_resp_size);
3862fcf3ce44SJohn Forte 		}
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,
3869fcf3ce44SJohn Forte 		    "fct_send_cmd_done:2 %p: x%x",
3870fcf3ce44SJohn Forte 		    fct_cmd, fct_cmd->cmd_comp_status);
3871291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
387282527734SSukumar Swaminathan 
3873*b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3874*b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma)
3875*b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
3876*b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3877*b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
3878*b3660a96SSukumar Swaminathan 			    "emlxs_fct_pkt_comp: hdl=%p",
3879*b3660a96SSukumar Swaminathan 			    pkt->pkt_resp_dma);
3880*b3660a96SSukumar Swaminathan 			MODSYM(fct_send_cmd_done) (fct_cmd, FCT_FAILURE,
3881*b3660a96SSukumar Swaminathan 			    FCT_IOF_FCA_DONE);
3882*b3660a96SSukumar Swaminathan 
3883*b3660a96SSukumar Swaminathan 			break;
3884*b3660a96SSukumar Swaminathan 		}
3885*b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */
3886291a2b48SSukumar Swaminathan 		MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS,
3887291a2b48SSukumar Swaminathan 		    FCT_IOF_FCA_DONE);
388882527734SSukumar Swaminathan 
3889fcf3ce44SJohn Forte 		break;
3890fcf3ce44SJohn Forte 
3891fcf3ce44SJohn Forte 	default:
3892fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3893fcf3ce44SJohn Forte 		    "emlxs_fct_pkt_comp: Invalid cmd type found. type=%x",
3894fcf3ce44SJohn Forte 		    fct_cmd->cmd_type);
3895fcf3ce44SJohn Forte 
389682527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
389782527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
389882527734SSukumar Swaminathan 
389982527734SSukumar Swaminathan 		break;
3900fcf3ce44SJohn Forte 	}
3901fcf3ce44SJohn Forte 
3902fcf3ce44SJohn Forte 	emlxs_pkt_free(pkt);
3903fcf3ce44SJohn Forte 	return;
3904fcf3ce44SJohn Forte 
390582527734SSukumar Swaminathan } /* emlxs_fct_pkt_comp() */
3906fcf3ce44SJohn Forte 
3907fcf3ce44SJohn Forte 
3908291a2b48SSukumar Swaminathan static void
3909291a2b48SSukumar Swaminathan emlxs_fct_abort_pkt_comp(fc_packet_t *pkt)
3910fcf3ce44SJohn Forte {
391182527734SSukumar Swaminathan #ifdef FCT_API_TRACE_11
3912291a2b48SSukumar Swaminathan 	emlxs_buf_t *sbp;
3913291a2b48SSukumar Swaminathan 	IOCBQ *iocbq;
3914291a2b48SSukumar Swaminathan 	IOCB *iocb;
3915291a2b48SSukumar Swaminathan 
3916291a2b48SSukumar Swaminathan 	sbp = PKT2PRIV(pkt);
3917291a2b48SSukumar Swaminathan 	iocbq = &sbp->iocbq;
3918291a2b48SSukumar Swaminathan 	iocb = &iocbq->iocb;
3919291a2b48SSukumar Swaminathan 
3920291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
392182527734SSukumar Swaminathan 	    "emlxs_fct_handle_abort: %p: xri=%x status=%x", iocb->ULPCONTEXT,
392282527734SSukumar Swaminathan 	    iocb->ULPCOMMAND, iocb->ULPSTATUS);
3923291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
3924291a2b48SSukumar Swaminathan 
3925291a2b48SSukumar Swaminathan 	emlxs_pkt_free(pkt);
3926291a2b48SSukumar Swaminathan 	return;
3927291a2b48SSukumar Swaminathan 
392882527734SSukumar Swaminathan } /* emlxs_fct_abort_pkt_comp() */
3929291a2b48SSukumar Swaminathan 
3930291a2b48SSukumar Swaminathan 
393182527734SSukumar Swaminathan /* COMSTAR ENTER POINT (INDIRECT) */
3932291a2b48SSukumar Swaminathan static fct_status_t
3933291a2b48SSukumar Swaminathan emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd)
3934291a2b48SSukumar Swaminathan {
3935291a2b48SSukumar Swaminathan 	emlxs_port_t *port =
3936291a2b48SSukumar Swaminathan 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
3937fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
3938fcf3ce44SJohn Forte 	uint32_t did;
3939fcf3ce44SJohn Forte 	fct_els_t *fct_els;
3940fcf3ce44SJohn Forte 	fc_packet_t *pkt;
3941fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
394282527734SSukumar Swaminathan 	fct_status_t rval;
3943fcf3ce44SJohn Forte 
3944fcf3ce44SJohn Forte 	did = fct_cmd->cmd_rportid;
3945fcf3ce44SJohn Forte 	fct_els = (fct_els_t *)fct_cmd->cmd_specific;
3946fcf3ce44SJohn Forte 
3947fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_req_size,
3948fcf3ce44SJohn Forte 	    fct_els->els_resp_size, 0, KM_NOSLEEP))) {
3949fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
3950fcf3ce44SJohn Forte 		    "emlxs_fct_send_els_cmd: Unable to allocate packet.");
395182527734SSukumar Swaminathan 
395282527734SSukumar Swaminathan 		return (FCT_BUSY);
3953fcf3ce44SJohn Forte 	}
3954291a2b48SSukumar Swaminathan 
395582527734SSukumar Swaminathan 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_SEND_ELS_REQ);
3956291a2b48SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
3957291a2b48SSukumar Swaminathan 
395882527734SSukumar Swaminathan 	cmd_sbp->channel = &hba->chan[hba->channel_els];
3959fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_ELS_REQ;
3960fcf3ce44SJohn Forte 
3961fcf3ce44SJohn Forte 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
3962291a2b48SSukumar Swaminathan 	cmd_sbp->fct_pkt = pkt;
3963fcf3ce44SJohn Forte 
3964fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
3965fcf3ce44SJohn Forte 	pkt->pkt_timeout =
3966fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
3967fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_fct_pkt_comp;
3968fcf3ce44SJohn Forte 
3969fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3970fcf3ce44SJohn Forte 	    "emlxs_fct_send_els_cmd: pkt_timeout=%d ratov=%d",
3971fcf3ce44SJohn Forte 	    pkt->pkt_timeout, hba->fc_ratov);
3972fcf3ce44SJohn Forte 
3973fcf3ce44SJohn Forte 	/* Build the fc header */
397482527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
3975fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
397682527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
3977fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3978fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
3979fcf3ce44SJohn Forte 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
3980fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
3981fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
3982fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
3983fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
3984fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
3985fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
3986fcf3ce44SJohn Forte 
3987fcf3ce44SJohn Forte 	/* Copy the cmd payload */
3988fcf3ce44SJohn Forte 	bcopy((uint8_t *)fct_els->els_req_payload, (uint8_t *)pkt->pkt_cmd,
3989fcf3ce44SJohn Forte 	    fct_els->els_req_size);
399082527734SSukumar Swaminathan 
3991291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
399282527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_REQ_PENDING);
399382527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
3994fcf3ce44SJohn Forte 
3995fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
399682527734SSukumar Swaminathan 
3997fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
3998fcf3ce44SJohn Forte 		    "emlxs_fct_send_els_cmd: Unable to send packet.");
3999fcf3ce44SJohn Forte 
400082527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
400182527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
400282527734SSukumar Swaminathan 		if (rval) {
400382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
400482527734SSukumar Swaminathan 			    "emlxs_fct_send_els_cmd: "
400582527734SSukumar Swaminathan 			    "Unable to reacquire fct_cmd.");
400682527734SSukumar Swaminathan 			return (rval);
4007fcf3ce44SJohn Forte 		}
400882527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
4009fcf3ce44SJohn Forte 
401082527734SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
401182527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4012fcf3ce44SJohn Forte 
401382527734SSukumar Swaminathan 		return (FCT_BUSY);
4014fcf3ce44SJohn Forte 	}
4015fcf3ce44SJohn Forte 
4016fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
4017fcf3ce44SJohn Forte 
401882527734SSukumar Swaminathan } /* emlxs_fct_send_els_cmd() */
4019fcf3ce44SJohn Forte 
4020fcf3ce44SJohn Forte 
402182527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
402282527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be released before exiting */
4023fcf3ce44SJohn Forte static fct_status_t
4024fcf3ce44SJohn Forte emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd)
4025fcf3ce44SJohn Forte {
4026fcf3ce44SJohn Forte 	emlxs_port_t *port =
4027fcf3ce44SJohn Forte 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
4028fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4029fcf3ce44SJohn Forte 	uint32_t did;
4030fcf3ce44SJohn Forte 	fct_els_t *fct_els;
4031fcf3ce44SJohn Forte 	fc_packet_t *pkt;
4032fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
403382527734SSukumar Swaminathan 	fct_status_t rval;
4034fcf3ce44SJohn Forte 
4035fcf3ce44SJohn Forte 	fct_els = (fct_els_t *)fct_cmd->cmd_specific;
4036fcf3ce44SJohn Forte 	did = fct_cmd->cmd_rportid;
403782527734SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
4038fcf3ce44SJohn Forte 
4039291a2b48SSukumar Swaminathan 	if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_resp_size, 0, 0,
4040291a2b48SSukumar Swaminathan 	    KM_NOSLEEP))) {
4041fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4042fcf3ce44SJohn Forte 		    "emlxs_fct_send_els_rsp: Unable to allocate packet.");
4043291a2b48SSukumar Swaminathan 
4044fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
404582527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4046fcf3ce44SJohn Forte 
404782527734SSukumar Swaminathan 		return (FCT_FAILURE);
404882527734SSukumar Swaminathan 	}
4049291a2b48SSukumar Swaminathan 
405082527734SSukumar Swaminathan 	EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_SEND_ELS_RSP);
4051fcf3ce44SJohn Forte 
4052fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_ELS_RSP;
4053fcf3ce44SJohn Forte 
4054fcf3ce44SJohn Forte 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
4055291a2b48SSukumar Swaminathan 	cmd_sbp->fct_pkt = pkt;
4056fcf3ce44SJohn Forte 
4057fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
4058fcf3ce44SJohn Forte 	pkt->pkt_timeout =
4059fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
4060fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_fct_pkt_comp;
4061fcf3ce44SJohn Forte 
4062fcf3ce44SJohn Forte 	/* Build the fc header */
406382527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
4064fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_RSP;
406582527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
4066fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
4067fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
4068fcf3ce44SJohn Forte 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
4069fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
4070fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4071fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4072fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
4073fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
4074fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
4075fcf3ce44SJohn Forte 
4076fcf3ce44SJohn Forte 	/* Copy the resp payload to pkt_cmd buffer */
4077fcf3ce44SJohn Forte 	bcopy((uint8_t *)fct_els->els_resp_payload, (uint8_t *)pkt->pkt_cmd,
4078fcf3ce44SJohn Forte 	    fct_els->els_resp_size);
407982527734SSukumar Swaminathan 
4080291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
408182527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_RSP_PENDING);
408282527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
4083fcf3ce44SJohn Forte 
4084fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
408582527734SSukumar Swaminathan 
4086fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4087fcf3ce44SJohn Forte 		    "emlxs_fct_send_els_rsp: Unable to send packet.");
4088fcf3ce44SJohn Forte 
408982527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
409082527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
409182527734SSukumar Swaminathan 		if (rval) {
409282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
409382527734SSukumar Swaminathan 			    "emlxs_fct_send_els_rsp: "
409482527734SSukumar Swaminathan 			    "Unable to reacquire fct_cmd.");
409582527734SSukumar Swaminathan 			return (rval);
4096fcf3ce44SJohn Forte 		}
409782527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
4098291a2b48SSukumar Swaminathan 
4099fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
410082527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4101291a2b48SSukumar Swaminathan 
4102fcf3ce44SJohn Forte 		return (FCT_FAILURE);
4103fcf3ce44SJohn Forte 	}
4104fcf3ce44SJohn Forte 
4105291a2b48SSukumar Swaminathan 	return (FCT_SUCCESS);
4106fcf3ce44SJohn Forte 
410782527734SSukumar Swaminathan } /* emlxs_fct_send_els_rsp() */
4108fcf3ce44SJohn Forte 
4109fcf3ce44SJohn Forte 
411082527734SSukumar Swaminathan /* COMSTAR ENTER POINT (INDIRECT) */
4111fcf3ce44SJohn Forte static fct_status_t
4112fcf3ce44SJohn Forte emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd)
4113fcf3ce44SJohn Forte {
4114fcf3ce44SJohn Forte 	emlxs_port_t *port =
4115fcf3ce44SJohn Forte 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
4116fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4117fcf3ce44SJohn Forte 	uint32_t did;
4118fcf3ce44SJohn Forte 	fct_sol_ct_t *fct_ct;
4119fcf3ce44SJohn Forte 	fc_packet_t *pkt;
4120fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
412182527734SSukumar Swaminathan 	fct_status_t rval;
4122fcf3ce44SJohn Forte 
4123fcf3ce44SJohn Forte 	did = fct_cmd->cmd_rportid;
4124fcf3ce44SJohn Forte 	fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific;
4125fcf3ce44SJohn Forte 
4126fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, fct_ct->ct_req_size,
4127fcf3ce44SJohn Forte 	    fct_ct->ct_resp_size, 0, KM_NOSLEEP))) {
4128fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4129fcf3ce44SJohn Forte 		    "emlxs_fct_send_ct_cmd: Unable to allocate packet.");
413082527734SSukumar Swaminathan 		return (FCT_BUSY);
4131fcf3ce44SJohn Forte 	}
4132291a2b48SSukumar Swaminathan 
413382527734SSukumar Swaminathan 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_SEND_CT_REQ);
4134291a2b48SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
4135fcf3ce44SJohn Forte 
413682527734SSukumar Swaminathan 	cmd_sbp->channel = &hba->chan[hba->channel_ct];
4137fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_CT_REQ;
4138fcf3ce44SJohn Forte 
4139fcf3ce44SJohn Forte 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
4140291a2b48SSukumar Swaminathan 	cmd_sbp->fct_pkt = pkt;
4141fcf3ce44SJohn Forte 
4142fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
4143fcf3ce44SJohn Forte 	pkt->pkt_timeout =
4144fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
4145fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_fct_pkt_comp;
4146fcf3ce44SJohn Forte 
4147fcf3ce44SJohn Forte 	/* Build the fc header */
414882527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
4149fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL;
415082527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
4151fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
4152fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
4153fcf3ce44SJohn Forte 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
4154fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
4155fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4156fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4157fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
4158fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
4159fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
4160fcf3ce44SJohn Forte 
4161fcf3ce44SJohn Forte 	/* Copy the cmd payload */
4162fcf3ce44SJohn Forte 	bcopy((uint8_t *)fct_ct->ct_req_payload, (uint8_t *)pkt->pkt_cmd,
4163fcf3ce44SJohn Forte 	    fct_ct->ct_req_size);
416482527734SSukumar Swaminathan 
4165291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
416682527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_REQ_PENDING);
416782527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
4168fcf3ce44SJohn Forte 
4169fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
417082527734SSukumar Swaminathan 
4171fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4172fcf3ce44SJohn Forte 		    "emlxs_fct_send_ct_cmd: Unable to send packet.");
4173fcf3ce44SJohn Forte 
417482527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
417582527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
417682527734SSukumar Swaminathan 		if (rval) {
417782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
417882527734SSukumar Swaminathan 			    "emlxs_fct_send_ct_cmd: "
417982527734SSukumar Swaminathan 			    "Unable to reacquire fct_cmd.");
418082527734SSukumar Swaminathan 
418182527734SSukumar Swaminathan 			return (rval);
4182fcf3ce44SJohn Forte 		}
418382527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
4184fcf3ce44SJohn Forte 
418582527734SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
418682527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4187fcf3ce44SJohn Forte 
418882527734SSukumar Swaminathan 		return (FCT_BUSY);
4189fcf3ce44SJohn Forte 	}
4190fcf3ce44SJohn Forte 
4191fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
4192fcf3ce44SJohn Forte 
419382527734SSukumar Swaminathan } /* emlxs_fct_send_ct_cmd() */
4194fcf3ce44SJohn Forte 
4195fcf3ce44SJohn Forte 
419682527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
4197fe199829SSukumar Swaminathan static uint32_t
4198291a2b48SSukumar Swaminathan emlxs_fct_pkt_abort_txq(emlxs_port_t *port, emlxs_buf_t *cmd_sbp)
4199fcf3ce44SJohn Forte {
4200fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4201fcf3ce44SJohn Forte 	NODELIST *nlp;
4202291a2b48SSukumar Swaminathan 	fc_packet_t *pkt;
4203291a2b48SSukumar Swaminathan 	emlxs_buf_t *sbp;
4204291a2b48SSukumar Swaminathan 	emlxs_buf_t *iocb_sbp;
420582527734SSukumar Swaminathan 	uint8_t channelno;
420682527734SSukumar Swaminathan 	CHANNEL *cp;
4207fcf3ce44SJohn Forte 	IOCBQ *iocbq;
4208fcf3ce44SJohn Forte 	IOCBQ *next;
4209fcf3ce44SJohn Forte 	IOCBQ *prev;
4210fcf3ce44SJohn Forte 	uint32_t found;
4211291a2b48SSukumar Swaminathan 	uint32_t pkt_flags;
4212fcf3ce44SJohn Forte 
4213291a2b48SSukumar Swaminathan 	/* Check the transmit queue */
421482527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
4215fcf3ce44SJohn Forte 
4216291a2b48SSukumar Swaminathan 	/* The IOCB could point to a cmd_sbp (no packet) or a sbp (packet) */
4217291a2b48SSukumar Swaminathan 	pkt = cmd_sbp->fct_pkt;
4218291a2b48SSukumar Swaminathan 	if (pkt) {
4219291a2b48SSukumar Swaminathan 		sbp = PKT2PRIV(pkt);
4220291a2b48SSukumar Swaminathan 		if (sbp == NULL) {
4221291a2b48SSukumar Swaminathan 			goto done;
4222291a2b48SSukumar Swaminathan 		}
4223291a2b48SSukumar Swaminathan 		iocb_sbp = sbp;
4224291a2b48SSukumar Swaminathan 		iocbq = &sbp->iocbq;
4225291a2b48SSukumar Swaminathan 		pkt_flags = sbp->pkt_flags;
4226291a2b48SSukumar Swaminathan 	} else {
4227291a2b48SSukumar Swaminathan 		sbp = NULL;
4228291a2b48SSukumar Swaminathan 		iocb_sbp = cmd_sbp;
4229291a2b48SSukumar Swaminathan 		iocbq = &cmd_sbp->iocbq;
4230291a2b48SSukumar Swaminathan 		pkt_flags = cmd_sbp->pkt_flags;
4231fcf3ce44SJohn Forte 	}
4232fcf3ce44SJohn Forte 
4233291a2b48SSukumar Swaminathan 	nlp = (NODELIST *)cmd_sbp->node;
423482527734SSukumar Swaminathan 	cp = (CHANNEL *)cmd_sbp->channel;
423582527734SSukumar Swaminathan 	channelno = (cp) ? cp->channelno : 0;
4236fcf3ce44SJohn Forte 
4237291a2b48SSukumar Swaminathan 	if (pkt_flags & PACKET_IN_TXQ) {
4238fcf3ce44SJohn Forte 		/* Find it on the queue */
4239fcf3ce44SJohn Forte 		found = 0;
4240fcf3ce44SJohn Forte 		if (iocbq->flag & IOCB_PRIORITY) {
4241fcf3ce44SJohn Forte 			/* Search the priority queue */
4242fcf3ce44SJohn Forte 			prev = NULL;
424382527734SSukumar Swaminathan 			next = (IOCBQ *)nlp->nlp_ptx[channelno].q_first;
4244fcf3ce44SJohn Forte 
4245fcf3ce44SJohn Forte 			while (next) {
4246fcf3ce44SJohn Forte 				if (next == iocbq) {
4247fcf3ce44SJohn Forte 					/* Remove it */
4248fcf3ce44SJohn Forte 					if (prev) {
4249fcf3ce44SJohn Forte 						prev->next = iocbq->next;
4250fcf3ce44SJohn Forte 					}
4251291a2b48SSukumar Swaminathan 
425282527734SSukumar Swaminathan 					if (nlp->nlp_ptx[channelno].q_last ==
4253fcf3ce44SJohn Forte 					    (void *)iocbq) {
425482527734SSukumar Swaminathan 						nlp->nlp_ptx[channelno].q_last =
4255fcf3ce44SJohn Forte 						    (void *)prev;
4256fcf3ce44SJohn Forte 					}
4257291a2b48SSukumar Swaminathan 
425882527734SSukumar Swaminathan 					if (nlp->nlp_ptx[channelno].q_first ==
4259fcf3ce44SJohn Forte 					    (void *)iocbq) {
426082527734SSukumar Swaminathan 						nlp->nlp_ptx[channelno].
426182527734SSukumar Swaminathan 						    q_first =
4262fcf3ce44SJohn Forte 						    (void *)iocbq->next;
4263fcf3ce44SJohn Forte 					}
4264291a2b48SSukumar Swaminathan 
426582527734SSukumar Swaminathan 					nlp->nlp_ptx[channelno].q_cnt--;
4266fcf3ce44SJohn Forte 					iocbq->next = NULL;
4267fcf3ce44SJohn Forte 					found = 1;
4268fcf3ce44SJohn Forte 					break;
4269fcf3ce44SJohn Forte 				}
4270291a2b48SSukumar Swaminathan 
4271fcf3ce44SJohn Forte 				prev = next;
4272fcf3ce44SJohn Forte 				next = next->next;
4273fcf3ce44SJohn Forte 			}
4274fcf3ce44SJohn Forte 		} else {
4275fcf3ce44SJohn Forte 			/* Search the normal queue */
4276fcf3ce44SJohn Forte 			prev = NULL;
427782527734SSukumar Swaminathan 			next = (IOCBQ *)nlp->nlp_tx[channelno].q_first;
4278fcf3ce44SJohn Forte 
4279fcf3ce44SJohn Forte 			while (next) {
4280fcf3ce44SJohn Forte 				if (next == iocbq) {
4281fcf3ce44SJohn Forte 					/* Remove it */
4282fcf3ce44SJohn Forte 					if (prev) {
4283fcf3ce44SJohn Forte 						prev->next = iocbq->next;
4284fcf3ce44SJohn Forte 					}
4285291a2b48SSukumar Swaminathan 
428682527734SSukumar Swaminathan 					if (nlp->nlp_tx[channelno].q_last ==
4287fcf3ce44SJohn Forte 					    (void *)iocbq) {
428882527734SSukumar Swaminathan 						nlp->nlp_tx[channelno].q_last =
4289fcf3ce44SJohn Forte 						    (void *)prev;
4290fcf3ce44SJohn Forte 					}
4291291a2b48SSukumar Swaminathan 
429282527734SSukumar Swaminathan 					if (nlp->nlp_tx[channelno].q_first ==
4293fcf3ce44SJohn Forte 					    (void *)iocbq) {
429482527734SSukumar Swaminathan 						nlp->nlp_tx[channelno].q_first =
4295fcf3ce44SJohn Forte 						    (void *)iocbq->next;
4296fcf3ce44SJohn Forte 					}
4297291a2b48SSukumar Swaminathan 
429882527734SSukumar Swaminathan 					nlp->nlp_tx[channelno].q_cnt--;
4299fcf3ce44SJohn Forte 					iocbq->next = NULL;
4300fcf3ce44SJohn Forte 					found = 1;
4301fcf3ce44SJohn Forte 					break;
4302fcf3ce44SJohn Forte 				}
4303291a2b48SSukumar Swaminathan 
4304fcf3ce44SJohn Forte 				prev = next;
4305fcf3ce44SJohn Forte 				next = (IOCBQ *)next->next;
4306fcf3ce44SJohn Forte 			}
4307fcf3ce44SJohn Forte 		}
4308fcf3ce44SJohn Forte 
4309fcf3ce44SJohn Forte 		if (!found) {
4310fcf3ce44SJohn Forte 			goto done;
4311fcf3ce44SJohn Forte 		}
4312291a2b48SSukumar Swaminathan 
4313fcf3ce44SJohn Forte 		/* Check if node still needs servicing */
431482527734SSukumar Swaminathan 		if ((nlp->nlp_ptx[channelno].q_first) ||
431582527734SSukumar Swaminathan 		    (nlp->nlp_tx[channelno].q_first &&
431682527734SSukumar Swaminathan 		    !(nlp->nlp_flag[channelno] & NLP_CLOSED))) {
4317fcf3ce44SJohn Forte 
4318fcf3ce44SJohn Forte 			/*
4319291a2b48SSukumar Swaminathan 			 * If this is the base node, don't shift the pointers
4320fcf3ce44SJohn Forte 			 */
4321fcf3ce44SJohn Forte 			/* We want to drain the base node before moving on */
4322fcf3ce44SJohn Forte 			if (!nlp->nlp_base) {
432382527734SSukumar Swaminathan 				/* Shift channel queue pointers to next node */
432482527734SSukumar Swaminathan 				cp->nodeq.q_last = (void *)nlp;
432582527734SSukumar Swaminathan 				cp->nodeq.q_first = nlp->nlp_next[channelno];
4326fcf3ce44SJohn Forte 			}
4327fcf3ce44SJohn Forte 		} else {
432882527734SSukumar Swaminathan 			/* Remove node from channel queue */
4329fcf3ce44SJohn Forte 
4330fcf3ce44SJohn Forte 			/* If this is the last node on list */
433182527734SSukumar Swaminathan 			if (cp->nodeq.q_last == (void *)nlp) {
433282527734SSukumar Swaminathan 				cp->nodeq.q_last = NULL;
433382527734SSukumar Swaminathan 				cp->nodeq.q_first = NULL;
433482527734SSukumar Swaminathan 				cp->nodeq.q_cnt = 0;
4335fcf3ce44SJohn Forte 			} else {
4336fcf3ce44SJohn Forte 				/* Remove node from head */
433782527734SSukumar Swaminathan 				cp->nodeq.q_first = nlp->nlp_next[channelno];
433882527734SSukumar Swaminathan 				((NODELIST *)cp->nodeq.q_last)->
433982527734SSukumar Swaminathan 				    nlp_next[channelno] = cp->nodeq.q_first;
434082527734SSukumar Swaminathan 				cp->nodeq.q_cnt--;
4341fcf3ce44SJohn Forte 			}
4342fcf3ce44SJohn Forte 
4343fcf3ce44SJohn Forte 			/* Clear node */
434482527734SSukumar Swaminathan 			nlp->nlp_next[channelno] = NULL;
4345fcf3ce44SJohn Forte 		}
4346fcf3ce44SJohn Forte 
434782527734SSukumar Swaminathan 		/* The IOCB points to iocb_sbp (no packet) or a sbp (packet) */
434882527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
434982527734SSukumar Swaminathan 			hba->fc_table[iocb_sbp->iotag] = NULL;
435082527734SSukumar Swaminathan 			emlxs_sli4_free_xri(hba, iocb_sbp, iocb_sbp->xp);
435182527734SSukumar Swaminathan 		} else {
435282527734SSukumar Swaminathan 			(void) emlxs_unregister_pkt(cp, iocb_sbp->iotag, 0);
4353fcf3ce44SJohn Forte 		}
4354fcf3ce44SJohn Forte 
435582527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
4356fcf3ce44SJohn Forte 
4357291a2b48SSukumar Swaminathan 		if (pkt) {
4358291a2b48SSukumar Swaminathan 			emlxs_pkt_free(pkt);
4359291a2b48SSukumar Swaminathan 			cmd_sbp->fct_pkt = NULL;
4360fcf3ce44SJohn Forte 		}
436182527734SSukumar Swaminathan 		return (1);
4362fcf3ce44SJohn Forte 	}
4363291a2b48SSukumar Swaminathan done:
436482527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
436582527734SSukumar Swaminathan 	return (0);
436682527734SSukumar Swaminathan 
436782527734SSukumar Swaminathan } /* emlxs_fct_pkt_abort_txq() */
4368fcf3ce44SJohn Forte 
4369fcf3ce44SJohn Forte 
437082527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
4371291a2b48SSukumar Swaminathan /* FCT_NOT_FOUND & FCT_ABORT_SUCCESS indicates IO is done */
4372291a2b48SSukumar Swaminathan /* FCT_SUCCESS indicates abort will occur asyncronously */
4373291a2b48SSukumar Swaminathan static fct_status_t
4374291a2b48SSukumar Swaminathan emlxs_fct_abort(fct_local_port_t *fct_port, fct_cmd_t *fct_cmd,
4375291a2b48SSukumar Swaminathan     uint32_t flags)
4376291a2b48SSukumar Swaminathan {
4377291a2b48SSukumar Swaminathan 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
4378291a2b48SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
4379291a2b48SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp;
438082527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp2;
438182527734SSukumar Swaminathan 	emlxs_buf_t *prev;
4382291a2b48SSukumar Swaminathan 	fc_packet_t *pkt;
4383291a2b48SSukumar Swaminathan 	emlxs_buf_t *sbp = NULL;
438482527734SSukumar Swaminathan 	kmutex_t *fct_mtx;
438582527734SSukumar Swaminathan 	uint32_t fct_state;
438682527734SSukumar Swaminathan 
438782527734SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
438882527734SSukumar Swaminathan 	fct_mtx = &cmd_sbp->fct_mtx;
4389fcf3ce44SJohn Forte 
4390291a2b48SSukumar Swaminathan top:
439182527734SSukumar Swaminathan 
4392291a2b48SSukumar Swaminathan 	/* Sanity check */
4393291a2b48SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
4394291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
439582527734SSukumar Swaminathan 		    "emlxs_fct_abort: Bad fct_cmd=%p.", fct_cmd);
4396fcf3ce44SJohn Forte 
4397291a2b48SSukumar Swaminathan 		return (FCT_NOT_FOUND);
4398291a2b48SSukumar Swaminathan 	}
4399fcf3ce44SJohn Forte 
4400291a2b48SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
4401291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
440282527734SSukumar Swaminathan 		    "emlxs_fct_abort: Pkt invalid. cmd_sbp=%p",
440382527734SSukumar Swaminathan 		    cmd_sbp);
4404fcf3ce44SJohn Forte 
4405291a2b48SSukumar Swaminathan 		return (FCT_NOT_FOUND);
4406fcf3ce44SJohn Forte 	}
4407fcf3ce44SJohn Forte 
440882527734SSukumar Swaminathan 	if (mutex_tryenter(fct_mtx) == 0) {
4409fcf3ce44SJohn Forte 		/*
4410291a2b48SSukumar Swaminathan 		 * This code path handles a race condition if
4411291a2b48SSukumar Swaminathan 		 * an IO completes, in emlxs_fct_handle_fcp_event(),
4412291a2b48SSukumar Swaminathan 		 * and we get an abort at the same time.
4413fcf3ce44SJohn Forte 		 */
4414291a2b48SSukumar Swaminathan 		delay(drv_usectohz(100000));	/* 100 msec */
4415291a2b48SSukumar Swaminathan 		goto top;
4416fcf3ce44SJohn Forte 	}
4417291a2b48SSukumar Swaminathan 	/* At this point, we have entered the mutex */
4418fcf3ce44SJohn Forte 
441982527734SSukumar Swaminathan 	/* Sanity check */
442082527734SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
4421291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
442282527734SSukumar Swaminathan 		    "emlxs_fct_abort: Bad fct_cmd=%p.", fct_cmd);
4423fcf3ce44SJohn Forte 
442482527734SSukumar Swaminathan 		mutex_exit(fct_mtx);
4425291a2b48SSukumar Swaminathan 		return (FCT_NOT_FOUND);
4426fcf3ce44SJohn Forte 	}
4427fcf3ce44SJohn Forte 
442882527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
442982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
443082527734SSukumar Swaminathan 		    "emlxs_fct_abort: Pkt invalid. cmd_sbp=%p",
443182527734SSukumar Swaminathan 		    cmd_sbp);
443282527734SSukumar Swaminathan 
443382527734SSukumar Swaminathan 		mutex_exit(fct_mtx);
443482527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
4435fcf3ce44SJohn Forte 	}
4436fcf3ce44SJohn Forte 
4437291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4438fe199829SSukumar Swaminathan 	    "emlxs_fct_abort: hbastate=%x. "
4439fe199829SSukumar Swaminathan 	    "xid=%x,%x cmd_sbp=%p fctstate=%d flags=%x,%x,%x",
4440fe199829SSukumar Swaminathan 	    hba->state, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid, cmd_sbp,
4441fe199829SSukumar Swaminathan 	    cmd_sbp->fct_state, flags, cmd_sbp->fct_flags, cmd_sbp->pkt_flags);
4442291a2b48SSukumar Swaminathan 
4443291a2b48SSukumar Swaminathan 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) {
444482527734SSukumar Swaminathan 		EMLXS_SLI_ISSUE_IOCB_CMD(hba, cmd_sbp->channel, 0);
444582527734SSukumar Swaminathan 
4446291a2b48SSukumar Swaminathan 		/* If Abort is already in progress */
444782527734SSukumar Swaminathan 		mutex_exit(fct_mtx);
444882527734SSukumar Swaminathan 		return (FCT_SUCCESS);
444982527734SSukumar Swaminathan 	}
445082527734SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_ABORT_INP;
445182527734SSukumar Swaminathan 
445282527734SSukumar Swaminathan 	if (flags & FCT_IOF_FORCE_FCA_DONE) {
445382527734SSukumar Swaminathan 		fct_cmd->cmd_handle = 0;
4454291a2b48SSukumar Swaminathan 	}
4455fcf3ce44SJohn Forte 
4456291a2b48SSukumar Swaminathan 	TGTPORTSTAT.FctAbortSent++;
4457fcf3ce44SJohn Forte 
445882527734SSukumar Swaminathan 	switch (cmd_sbp->fct_state) {
445982527734SSukumar Swaminathan 	/* These are currently owned by COMSTAR. */
446082527734SSukumar Swaminathan 	/* They were last processed by emlxs_fct_cmd_post() */
4461fe199829SSukumar Swaminathan 	/* We have NO exchange resources associated with this IO. */
446282527734SSukumar Swaminathan 	case EMLXS_FCT_OWNED:
4463fe199829SSukumar Swaminathan 		goto abort_done;
446482527734SSukumar Swaminathan 
446582527734SSukumar Swaminathan 	/* These are on the unsol waitQ in the driver */
446682527734SSukumar Swaminathan 	case EMLXS_FCT_CMD_WAITQ:
446782527734SSukumar Swaminathan 		/* Find and remove it */
446882527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
446982527734SSukumar Swaminathan 		cmd_sbp2 = port->fct_wait_head;
447082527734SSukumar Swaminathan 		prev = NULL;
447182527734SSukumar Swaminathan 		while (cmd_sbp2) {
447282527734SSukumar Swaminathan 			if (cmd_sbp2 == cmd_sbp) {
447382527734SSukumar Swaminathan 				/* Remove it */
447482527734SSukumar Swaminathan 				if (prev) {
447582527734SSukumar Swaminathan 					prev->next = cmd_sbp2->next;
447682527734SSukumar Swaminathan 				}
447782527734SSukumar Swaminathan 
447882527734SSukumar Swaminathan 				if (port->fct_wait_head == cmd_sbp2) {
447982527734SSukumar Swaminathan 					port->fct_wait_head = cmd_sbp2->next;
448082527734SSukumar Swaminathan 				}
448182527734SSukumar Swaminathan 
448282527734SSukumar Swaminathan 				if (port->fct_wait_tail == cmd_sbp2) {
448382527734SSukumar Swaminathan 					port->fct_wait_tail = prev;
448482527734SSukumar Swaminathan 				}
448582527734SSukumar Swaminathan 
448682527734SSukumar Swaminathan 				cmd_sbp2->next = NULL;
448782527734SSukumar Swaminathan 				break;
448882527734SSukumar Swaminathan 			}
448982527734SSukumar Swaminathan 			prev = cmd_sbp2;
449082527734SSukumar Swaminathan 			cmd_sbp2 = cmd_sbp2->next;
449182527734SSukumar Swaminathan 		}
449282527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
449382527734SSukumar Swaminathan 
4494fe199829SSukumar Swaminathan 		/*FALLTHROUGH*/
4495fe199829SSukumar Swaminathan 
4496fe199829SSukumar Swaminathan 	/* These are currently owned by COMSTAR. */
4497fe199829SSukumar Swaminathan 	/* They were last processed by emlxs_fct_cmd_post() */
4498fe199829SSukumar Swaminathan 	/* We have residual exchange resources associated with this IO */
4499fe199829SSukumar Swaminathan 	case EMLXS_FCT_CMD_POSTED:
4500fe199829SSukumar Swaminathan 		switch (fct_cmd->cmd_type) {
4501fe199829SSukumar Swaminathan 		case FCT_CMD_FCP_XCHG: /* Unsol */
4502fe199829SSukumar Swaminathan 			TGTPORTSTAT.FctOutstandingIO--;
4503fe199829SSukumar Swaminathan 			emlxs_abort_fct_exchange(hba, port, fct_cmd->cmd_rxid);
4504fe199829SSukumar Swaminathan 			break;
4505fe199829SSukumar Swaminathan 
4506fe199829SSukumar Swaminathan 		case FCT_CMD_RCVD_ELS: /* Unsol */
4507fe199829SSukumar Swaminathan 			emlxs_abort_els_exchange(hba, port, fct_cmd->cmd_rxid);
4508fe199829SSukumar Swaminathan 			break;
4509fe199829SSukumar Swaminathan 		}
4510fe199829SSukumar Swaminathan 
4511fe199829SSukumar Swaminathan 		goto abort_done;
451282527734SSukumar Swaminathan 
451382527734SSukumar Swaminathan 	/* These are active in the driver */
451482527734SSukumar Swaminathan 	/* They were last processed by emlxs_fct_cmd_release() */
4515291a2b48SSukumar Swaminathan 	case EMLXS_FCT_RSP_PENDING:
4516291a2b48SSukumar Swaminathan 	case EMLXS_FCT_REQ_PENDING:
4517291a2b48SSukumar Swaminathan 	case EMLXS_FCT_REG_PENDING:
4518291a2b48SSukumar Swaminathan 	case EMLXS_FCT_DATA_PENDING:
4519291a2b48SSukumar Swaminathan 	case EMLXS_FCT_STATUS_PENDING:
452082527734SSukumar Swaminathan 
452182527734SSukumar Swaminathan 		/* Abort anything pending */
4522291a2b48SSukumar Swaminathan 		if (emlxs_fct_pkt_abort_txq(port, cmd_sbp)) {
4523fcf3ce44SJohn Forte 
4524291a2b48SSukumar Swaminathan 			if (fct_cmd->cmd_type == FCT_CMD_FCP_XCHG) {
4525291a2b48SSukumar Swaminathan 				TGTPORTSTAT.FctOutstandingIO--;
4526fcf3ce44SJohn Forte 			}
452782527734SSukumar Swaminathan 
4528fe199829SSukumar Swaminathan 			goto abort_done;
4529291a2b48SSukumar Swaminathan 		}
4530fcf3ce44SJohn Forte 
453182527734SSukumar Swaminathan 		/* If we're not online, then all IO will be flushed anyway */
4532291a2b48SSukumar Swaminathan 		if (!(hba->flag & FC_ONLINE_MODE)) {
453382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
453482527734SSukumar Swaminathan 			    "emlxs_fct_abort: Not online. fct_cmd=%p.",
453582527734SSukumar Swaminathan 			    fct_cmd);
4536291a2b48SSukumar Swaminathan 
453782527734SSukumar Swaminathan 			emlxs_fct_cmd_release(port, fct_cmd, 0);
453882527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
453982527734SSukumar Swaminathan 
454082527734SSukumar Swaminathan 			/* The cmd will be aborted on the */
454182527734SSukumar Swaminathan 			/* next emlxs_fct_cmd_acquire */
454282527734SSukumar Swaminathan 			/* because EMLXS_FCT_ABORT_INP is set. */
454382527734SSukumar Swaminathan 			break;
4544fcf3ce44SJohn Forte 		}
4545fcf3ce44SJohn Forte 
454682527734SSukumar Swaminathan 		/* Try to send abort request */
4547291a2b48SSukumar Swaminathan 		if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) {
4548291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
454982527734SSukumar Swaminathan 			    "emlxs_fct_abort: Unable to allocate packet. "
455082527734SSukumar Swaminathan 			    "fct_cmd=%p",
455182527734SSukumar Swaminathan 			    fct_cmd);
455282527734SSukumar Swaminathan 
455382527734SSukumar Swaminathan 			emlxs_fct_cmd_release(port, fct_cmd, 0);
455482527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
455582527734SSukumar Swaminathan 
455682527734SSukumar Swaminathan 			/* The cmd will be aborted on the */
455782527734SSukumar Swaminathan 			/* next emlxs_fct_cmd_acquire anyway */
455882527734SSukumar Swaminathan 			/* because EMLXS_FCT_ABORT_INP is set. */
455982527734SSukumar Swaminathan 			break;
4560fcf3ce44SJohn Forte 		}
4561fcf3ce44SJohn Forte 
4562291a2b48SSukumar Swaminathan 		sbp = emlxs_fct_pkt_init(port, fct_cmd, pkt);
4563291a2b48SSukumar Swaminathan 
4564291a2b48SSukumar Swaminathan 		pkt->pkt_tran_type = FC_PKT_OUTBOUND;
4565291a2b48SSukumar Swaminathan 		pkt->pkt_timeout =
4566291a2b48SSukumar Swaminathan 		    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
4567291a2b48SSukumar Swaminathan 		pkt->pkt_comp = emlxs_fct_abort_pkt_comp;
4568291a2b48SSukumar Swaminathan 
4569291a2b48SSukumar Swaminathan 		/* Build the fc header */
457082527734SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(fct_cmd->cmd_rportid);
4571291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
457282527734SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
4573291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.type = FC_TYPE_BASIC_LS;
4574291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.f_ctl =
4575291a2b48SSukumar Swaminathan 		    (F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ);
4576291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.seq_id = 0;
4577291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.df_ctl = 0;
4578291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
4579291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
4580291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
4581291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.ro = 0;
4582291a2b48SSukumar Swaminathan 
4583291a2b48SSukumar Swaminathan 		cmd_sbp->fct_cmd = fct_cmd;
4584291a2b48SSukumar Swaminathan 		cmd_sbp->abort_attempts++;
4585fcf3ce44SJohn Forte 
4586291a2b48SSukumar Swaminathan 		/* Now disassociate the sbp / pkt from the fct_cmd */
4587291a2b48SSukumar Swaminathan 		sbp->fct_cmd = NULL;
4588fcf3ce44SJohn Forte 
458982527734SSukumar Swaminathan 		if (hba->state >= FC_LINK_UP) {
4590291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4591291a2b48SSukumar Swaminathan 			    "emlxs_fct_abort: ABORT: %p xri x%x",
4592291a2b48SSukumar Swaminathan 			    fct_cmd, fct_cmd->cmd_rxid);
4593fcf3ce44SJohn Forte 
459482527734SSukumar Swaminathan 			fct_state = EMLXS_FCT_ABORT_PENDING;
459582527734SSukumar Swaminathan 
459682527734SSukumar Swaminathan 		} else {
4597291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4598291a2b48SSukumar Swaminathan 			    "emlxs_fct_abort: CLOSE: %p xri x%x",
4599291a2b48SSukumar Swaminathan 			    fct_cmd, fct_cmd->cmd_rxid);
4600fcf3ce44SJohn Forte 
460182527734SSukumar Swaminathan 			fct_state = EMLXS_FCT_CLOSE_PENDING;
4602291a2b48SSukumar Swaminathan 		}
4603fcf3ce44SJohn Forte 
460482527734SSukumar Swaminathan 		emlxs_fct_cmd_release(port, fct_cmd, fct_state);
460582527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
460682527734SSukumar Swaminathan 
4607291a2b48SSukumar Swaminathan 		if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
4608291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
460982527734SSukumar Swaminathan 			    "emlxs_fct_abort: Unable to send abort packet.");
4610fcf3ce44SJohn Forte 
4611291a2b48SSukumar Swaminathan 			emlxs_pkt_free(pkt);
4612fcf3ce44SJohn Forte 
461382527734SSukumar Swaminathan 			/* The cmd will be aborted on the */
461482527734SSukumar Swaminathan 			/* next emlxs_fct_cmd_acquire anyway */
461582527734SSukumar Swaminathan 			/* because EMLXS_FCT_ABORT_INP is set. */
4616291a2b48SSukumar Swaminathan 		}
461782527734SSukumar Swaminathan 
4618291a2b48SSukumar Swaminathan 		break;
4619fcf3ce44SJohn Forte 
4620291a2b48SSukumar Swaminathan 	default:
462182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
462282527734SSukumar Swaminathan 		    "emlxs_fct_abort: Unexpected fct_state. "
462382527734SSukumar Swaminathan 		    "fct_cmd=%p state=%x",
462482527734SSukumar Swaminathan 		    fct_cmd, cmd_sbp->fct_state);
462582527734SSukumar Swaminathan 
462682527734SSukumar Swaminathan 		emlxs_fct_cmd_release(port, fct_cmd, 0);
462782527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
462882527734SSukumar Swaminathan 
462982527734SSukumar Swaminathan 		/* The cmd will be aborted on the */
463082527734SSukumar Swaminathan 		/* next emlxs_fct_cmd_acquire anyway */
463182527734SSukumar Swaminathan 		/* because EMLXS_FCT_ABORT_INP is set. */
4632fcf3ce44SJohn Forte 
4633291a2b48SSukumar Swaminathan 	}	/* switch */
4634fcf3ce44SJohn Forte 
463582527734SSukumar Swaminathan 	return (FCT_SUCCESS);
4636fcf3ce44SJohn Forte 
4637fe199829SSukumar Swaminathan abort_done:
463882527734SSukumar Swaminathan 
463982527734SSukumar Swaminathan 	emlxs_fct_cmd_done(port, fct_cmd,
464082527734SSukumar Swaminathan 	    EMLXS_FCT_ABORT_DONE);
464182527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
464282527734SSukumar Swaminathan 
464382527734SSukumar Swaminathan 	return (FCT_ABORT_SUCCESS);
464482527734SSukumar Swaminathan 
464582527734SSukumar Swaminathan } /* emlxs_fct_abort() */
4646fcf3ce44SJohn Forte 
4647fcf3ce44SJohn Forte 
4648fcf3ce44SJohn Forte extern void
4649fcf3ce44SJohn Forte emlxs_fct_link_up(emlxs_port_t *port)
4650fcf3ce44SJohn Forte {
4651fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4652fcf3ce44SJohn Forte 
4653fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
4654fcf3ce44SJohn Forte 
4655fcf3ce44SJohn Forte 	if (port->fct_port &&
4656fcf3ce44SJohn Forte 	    (port->fct_flags & FCT_STATE_PORT_ONLINE) &&
4657fcf3ce44SJohn Forte 	    !(port->fct_flags & FCT_STATE_LINK_UP)) {
4658fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4659fcf3ce44SJohn Forte 		    "emlxs_fct_link_up event.");
4660fcf3ce44SJohn Forte 
4661e2ca2865SSukumar Swaminathan 		port->fct_flags &= ~FCT_STATE_LINK_UP_ACKED;
4662fcf3ce44SJohn Forte 		port->fct_flags |= FCT_STATE_LINK_UP;
4663fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
4664fcf3ce44SJohn Forte 
4665fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4666fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4667fcf3ce44SJohn Forte 		    "fct_handle_event LINK_UP");
4668291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
4669291a2b48SSukumar Swaminathan 		MODSYM(fct_handle_event) (port->fct_port, FCT_EVENT_LINK_UP,
4670291a2b48SSukumar Swaminathan 		    0, 0);
4671fcf3ce44SJohn Forte 	} else {
4672fcf3ce44SJohn Forte 		if (!hba->ini_mode &&
4673fcf3ce44SJohn Forte 		    !(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
4674fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
4675fcf3ce44SJohn Forte 
4676fcf3ce44SJohn Forte 			/* Take link down and hold it down */
467782527734SSukumar Swaminathan 			(void) emlxs_reset_link(hba, 0, 1);
4678fcf3ce44SJohn Forte 		} else {
4679fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
4680fcf3ce44SJohn Forte 		}
4681fcf3ce44SJohn Forte 	}
4682fcf3ce44SJohn Forte 
4683fcf3ce44SJohn Forte 	return;
4684fcf3ce44SJohn Forte 
468582527734SSukumar Swaminathan } /* emlxs_fct_link_up() */
4686291a2b48SSukumar Swaminathan 
4687fcf3ce44SJohn Forte 
4688fcf3ce44SJohn Forte extern void
4689fcf3ce44SJohn Forte emlxs_fct_link_down(emlxs_port_t *port)
4690fcf3ce44SJohn Forte {
4691fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4692fcf3ce44SJohn Forte 
4693fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
4694fcf3ce44SJohn Forte 
4695fcf3ce44SJohn Forte 	if (port->fct_port &&
4696fcf3ce44SJohn Forte 	    (port->fct_flags & FCT_STATE_PORT_ONLINE) &&
4697fcf3ce44SJohn Forte 	    (port->fct_flags & FCT_STATE_LINK_UP)) {
4698fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4699fcf3ce44SJohn Forte 		    "emlxs_fct_link_down event.");
4700fcf3ce44SJohn Forte 
4701e2ca2865SSukumar Swaminathan 		port->fct_flags &= ~FCT_STATE_LINK_UP_ACKED;
4702fcf3ce44SJohn Forte 		port->fct_flags &= ~FCT_STATE_LINK_UP;
4703fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
4704fcf3ce44SJohn Forte 
4705fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4706fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4707fcf3ce44SJohn Forte 		    "fct_handle_event LINK_DOWN");
4708291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
470982527734SSukumar Swaminathan 
4710291a2b48SSukumar Swaminathan 		MODSYM(fct_handle_event) (port->fct_port, FCT_EVENT_LINK_DOWN,
4711291a2b48SSukumar Swaminathan 		    0, 0);
4712fcf3ce44SJohn Forte 	} else {
4713fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
4714fcf3ce44SJohn Forte 	}
4715fcf3ce44SJohn Forte 
4716fcf3ce44SJohn Forte 	return;
4717fcf3ce44SJohn Forte 
471882527734SSukumar Swaminathan } /* emlxs_fct_link_down() */
4719fcf3ce44SJohn Forte 
4720fcf3ce44SJohn Forte 
4721291a2b48SSukumar Swaminathan /* DMA FUNCTIONS */
4722fcf3ce44SJohn Forte 
4723fcf3ce44SJohn Forte fct_status_t
4724fcf3ce44SJohn Forte emlxs_fct_dmem_init(emlxs_port_t *port)
4725fcf3ce44SJohn Forte {
4726fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4727fcf3ce44SJohn Forte 	emlxs_fct_dmem_bucket_t *p;
4728fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *bctl;
4729fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *bc;
4730fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *prev;
4731fcf3ce44SJohn Forte 	int32_t j;
4732fcf3ce44SJohn Forte 	int32_t i;
4733fcf3ce44SJohn Forte 	uint32_t total_mem;
4734fcf3ce44SJohn Forte 	uint8_t *addr;
4735fcf3ce44SJohn Forte 	uint8_t *host_addr;
4736fcf3ce44SJohn Forte 	uint64_t dev_addr;
4737fcf3ce44SJohn Forte 	ddi_dma_cookie_t cookie;
4738fcf3ce44SJohn Forte 	uint32_t ncookie;
4739fcf3ce44SJohn Forte 	uint32_t bsize;
4740fcf3ce44SJohn Forte 	size_t len;
4741fcf3ce44SJohn Forte 	char buf[64];
4742fcf3ce44SJohn Forte 	ddi_device_acc_attr_t acc;
4743fcf3ce44SJohn Forte 
4744fcf3ce44SJohn Forte 	bzero(&acc, sizeof (acc));
4745fcf3ce44SJohn Forte 	acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
4746fcf3ce44SJohn Forte 	acc.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
4747fcf3ce44SJohn Forte 	acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
4748fcf3ce44SJohn Forte 
4749fcf3ce44SJohn Forte 	p = port->dmem_bucket;
4750fcf3ce44SJohn Forte 	for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) {
4751fcf3ce44SJohn Forte 		if (!p->dmem_nbufs) {
4752fcf3ce44SJohn Forte 			continue;
4753fcf3ce44SJohn Forte 		}
4754291a2b48SSukumar Swaminathan 
4755fcf3ce44SJohn Forte 		bctl = (emlxs_fct_dmem_bctl_t *)kmem_zalloc(p->dmem_nbufs *
475682527734SSukumar Swaminathan 		    sizeof (emlxs_fct_dmem_bctl_t), KM_NOSLEEP);
4757fcf3ce44SJohn Forte 
4758fcf3ce44SJohn Forte 		if (bctl == NULL) {
4759fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4760fcf3ce44SJohn Forte 			    "emlxs_fct_dmem_init: Unable to allocate bctl.");
4761fcf3ce44SJohn Forte 			goto alloc_bctl_failed;
4762fcf3ce44SJohn Forte 		}
4763291a2b48SSukumar Swaminathan 
4764fcf3ce44SJohn Forte 		p->dmem_bctls_mem = bctl;
4765fcf3ce44SJohn Forte 
476662379b58SSukumar Swaminathan 		if (ddi_dma_alloc_handle(hba->dip, &hba->dma_attr_1sg,
4767fcf3ce44SJohn Forte 		    DDI_DMA_SLEEP, 0, &p->dmem_dma_handle) != DDI_SUCCESS) {
4768fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4769fcf3ce44SJohn Forte 			    "emlxs_fct_dmem_init: Unable to allocate handle.");
4770fcf3ce44SJohn Forte 			goto alloc_handle_failed;
4771fcf3ce44SJohn Forte 		}
4772fcf3ce44SJohn Forte 
4773fcf3ce44SJohn Forte 		total_mem = p->dmem_buf_size * p->dmem_nbufs;
4774fcf3ce44SJohn Forte 
4775fcf3ce44SJohn Forte 		if (ddi_dma_mem_alloc(p->dmem_dma_handle, total_mem, &acc,
477682527734SSukumar Swaminathan 		    DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0,
4777291a2b48SSukumar Swaminathan 		    (caddr_t *)&addr, &len,
4778291a2b48SSukumar Swaminathan 		    &p->dmem_acc_handle) != DDI_SUCCESS) {
4779fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4780fcf3ce44SJohn Forte 			    "emlxs_fct_dmem_init: Unable to allocate memory.");
4781fcf3ce44SJohn Forte 			goto mem_alloc_failed;
4782fcf3ce44SJohn Forte 		}
4783fcf3ce44SJohn Forte 
4784fcf3ce44SJohn Forte 		if (ddi_dma_addr_bind_handle(p->dmem_dma_handle, NULL,
4785291a2b48SSukumar Swaminathan 		    (caddr_t)addr, total_mem,
478682527734SSukumar Swaminathan 		    DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0,
4787291a2b48SSukumar Swaminathan 		    &cookie, &ncookie) != DDI_SUCCESS) {
4788fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4789fcf3ce44SJohn Forte 			    "emlxs_fct_dmem_init: Unable to bind handle.");
4790fcf3ce44SJohn Forte 			goto addr_bind_handle_failed;
4791fcf3ce44SJohn Forte 		}
4792fcf3ce44SJohn Forte 
4793fcf3ce44SJohn Forte 		if (ncookie != 1) {
4794fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4795fcf3ce44SJohn Forte 			    "emlxs_fct_dmem_init: DMEM init failed.");
4796fcf3ce44SJohn Forte 			goto dmem_init_failed;
4797fcf3ce44SJohn Forte 		}
4798fcf3ce44SJohn Forte 		(void) sprintf(buf, "%s%d_bucket%d mutex", DRIVER_NAME,
4799fcf3ce44SJohn Forte 		    hba->ddiinst, i);
4800fcf3ce44SJohn Forte 		mutex_init(&p->dmem_lock, buf, MUTEX_DRIVER,
4801fcf3ce44SJohn Forte 		    (void *)hba->intr_arg);
4802fcf3ce44SJohn Forte 
4803fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4804fcf3ce44SJohn Forte 		    "bufsize=%d cnt=%d", p->dmem_buf_size, p->dmem_nbufs);
4805fcf3ce44SJohn Forte 
4806fcf3ce44SJohn Forte 		host_addr = addr;
4807fcf3ce44SJohn Forte 		dev_addr = (uint64_t)cookie.dmac_laddress;
4808fcf3ce44SJohn Forte 
4809fcf3ce44SJohn Forte 		p->dmem_host_addr = addr;
4810fcf3ce44SJohn Forte 		p->dmem_dev_addr = dev_addr;
4811fcf3ce44SJohn Forte 		p->dmem_bctl_free_list = bctl;
4812fcf3ce44SJohn Forte 		p->dmem_nbufs_free = p->dmem_nbufs;
4813fcf3ce44SJohn Forte 		bsize = p->dmem_buf_size;
4814fcf3ce44SJohn Forte 
4815fcf3ce44SJohn Forte 		for (j = 0; j < p->dmem_nbufs; j++) {
4816fcf3ce44SJohn Forte 			stmf_data_buf_t *db;
4817fcf3ce44SJohn Forte 
4818fcf3ce44SJohn Forte 			db = MODSYM(stmf_alloc) (STMF_STRUCT_DATA_BUF, 0, 0);
4819fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4820fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4821fcf3ce44SJohn Forte 			    "stmf_alloc data_buf %p", db);
4822291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
4823fcf3ce44SJohn Forte 			if (db == NULL) {
4824fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4825291a2b48SSukumar Swaminathan 				    "emlxs_fct_dmem_init: alloc failed.");
4826fcf3ce44SJohn Forte 				goto dmem_init_failed;
4827fcf3ce44SJohn Forte 			}
4828fcf3ce44SJohn Forte 			db->db_port_private = bctl;
4829fcf3ce44SJohn Forte 			db->db_sglist[0].seg_addr = host_addr;
4830fcf3ce44SJohn Forte 			db->db_sglist[0].seg_length = bsize;
4831fcf3ce44SJohn Forte 			db->db_buf_size = bsize;
4832fcf3ce44SJohn Forte 			db->db_sglist_length = 1;
4833fcf3ce44SJohn Forte 
4834fcf3ce44SJohn Forte 			bctl->bctl_bucket = p;
4835fcf3ce44SJohn Forte 			bctl->bctl_buf = db;
4836fcf3ce44SJohn Forte 			bctl->bctl_dev_addr = dev_addr;
4837fcf3ce44SJohn Forte 
4838fcf3ce44SJohn Forte 			host_addr += bsize;
4839fcf3ce44SJohn Forte 			dev_addr += bsize;
4840fcf3ce44SJohn Forte 
4841fcf3ce44SJohn Forte 			prev = bctl;
4842fcf3ce44SJohn Forte 			bctl++;
4843fcf3ce44SJohn Forte 			prev->bctl_next = bctl;
4844fcf3ce44SJohn Forte 		}
4845fcf3ce44SJohn Forte 
4846fcf3ce44SJohn Forte 		prev->bctl_next = NULL;
4847fcf3ce44SJohn Forte 	}
4848fcf3ce44SJohn Forte 
4849fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
4850fcf3ce44SJohn Forte 
4851fcf3ce44SJohn Forte dmem_failure_loop:
4852fcf3ce44SJohn Forte 	mutex_destroy(&p->dmem_lock);
4853fcf3ce44SJohn Forte 	bc = bctl;
4854fcf3ce44SJohn Forte 	while (bc) {
4855fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4856fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4857fcf3ce44SJohn Forte 		    "stmf_free:3 %p", bctl->bctl_buf);
4858291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
4859fcf3ce44SJohn Forte 		MODSYM(stmf_free) (bc->bctl_buf);
4860fcf3ce44SJohn Forte 		bc = bc->bctl_next;
4861fcf3ce44SJohn Forte 	}
4862fcf3ce44SJohn Forte 
4863fcf3ce44SJohn Forte dmem_init_failed:
4864fcf3ce44SJohn Forte 	(void) ddi_dma_unbind_handle(p->dmem_dma_handle);
4865fcf3ce44SJohn Forte 
4866fcf3ce44SJohn Forte addr_bind_handle_failed:
4867fcf3ce44SJohn Forte 	(void) ddi_dma_mem_free(&p->dmem_acc_handle);
4868fcf3ce44SJohn Forte 
4869fcf3ce44SJohn Forte mem_alloc_failed:
4870fcf3ce44SJohn Forte 	(void) ddi_dma_free_handle(&p->dmem_dma_handle);
4871fcf3ce44SJohn Forte 
4872fcf3ce44SJohn Forte alloc_handle_failed:
4873fcf3ce44SJohn Forte 	kmem_free(p->dmem_bctls_mem,
4874fcf3ce44SJohn Forte 	    p->dmem_nbufs * sizeof (emlxs_fct_dmem_bctl_t));
4875fcf3ce44SJohn Forte 
4876fcf3ce44SJohn Forte alloc_bctl_failed:
4877fcf3ce44SJohn Forte 	if (--i >= 0) {
4878fcf3ce44SJohn Forte 		p = &port->dmem_bucket[i];
4879fcf3ce44SJohn Forte 		bctl = p->dmem_bctl_free_list;
4880fcf3ce44SJohn Forte 		goto dmem_failure_loop;
4881fcf3ce44SJohn Forte 	}
4882fcf3ce44SJohn Forte 
4883291a2b48SSukumar Swaminathan 	return (FCT_FAILURE);
4884fcf3ce44SJohn Forte 
488582527734SSukumar Swaminathan } /* emlxs_fct_dmem_init() */
4886fcf3ce44SJohn Forte 
4887fcf3ce44SJohn Forte 
4888fcf3ce44SJohn Forte void
4889fcf3ce44SJohn Forte emlxs_fct_dmem_fini(emlxs_port_t *port)
4890fcf3ce44SJohn Forte {
4891fcf3ce44SJohn Forte 	emlxs_fct_dmem_bucket_t *p;
4892fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *bctl;
4893fcf3ce44SJohn Forte 	uint32_t i;
4894fcf3ce44SJohn Forte 
4895fcf3ce44SJohn Forte 	p = port->dmem_bucket;
4896fcf3ce44SJohn Forte 	for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) {
4897fcf3ce44SJohn Forte 		if (!p->dmem_nbufs) {
4898fcf3ce44SJohn Forte 			continue;
4899fcf3ce44SJohn Forte 		}
4900291a2b48SSukumar Swaminathan 
4901fcf3ce44SJohn Forte 		bctl = p->dmem_bctl_free_list;
4902fcf3ce44SJohn Forte 
4903fcf3ce44SJohn Forte 		while (bctl) {
4904fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4905fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4906fcf3ce44SJohn Forte 			    "stmf_free:4 %p", bctl->bctl_buf);
4907291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
4908fcf3ce44SJohn Forte 			MODSYM(stmf_free) (bctl->bctl_buf);
4909fcf3ce44SJohn Forte 			bctl = bctl->bctl_next;
4910fcf3ce44SJohn Forte 		}
4911fcf3ce44SJohn Forte 
4912fcf3ce44SJohn Forte 		bctl = p->dmem_bctl_free_list;
4913fcf3ce44SJohn Forte 
4914fcf3ce44SJohn Forte 		(void) ddi_dma_unbind_handle(p->dmem_dma_handle);
4915fcf3ce44SJohn Forte 		(void) ddi_dma_mem_free(&p->dmem_acc_handle);
4916fcf3ce44SJohn Forte 		(void) ddi_dma_free_handle(&p->dmem_dma_handle);
4917fcf3ce44SJohn Forte 
4918fcf3ce44SJohn Forte 		kmem_free(p->dmem_bctls_mem,
4919fcf3ce44SJohn Forte 		    (p->dmem_nbufs * sizeof (emlxs_fct_dmem_bctl_t)));
4920fcf3ce44SJohn Forte 		mutex_destroy(&p->dmem_lock);
4921fcf3ce44SJohn Forte 	}
4922fcf3ce44SJohn Forte 
4923fcf3ce44SJohn Forte 	bzero((uint8_t *)port->dmem_bucket, sizeof (port->dmem_bucket));
4924fcf3ce44SJohn Forte 
4925fcf3ce44SJohn Forte 	return;
4926fcf3ce44SJohn Forte 
492782527734SSukumar Swaminathan } /* emlxs_fct_dmem_fini() */
4928fcf3ce44SJohn Forte 
4929fcf3ce44SJohn Forte 
493082527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
4931fcf3ce44SJohn Forte /* ARGSUSED */
4932fcf3ce44SJohn Forte static stmf_data_buf_t *
4933fcf3ce44SJohn Forte emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port, uint32_t size,
4934fcf3ce44SJohn Forte     uint32_t *pminsize, uint32_t flags)
4935fcf3ce44SJohn Forte {
4936fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
4937fcf3ce44SJohn Forte 	emlxs_fct_dmem_bucket_t *p;
4938fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *bctl;
4939fcf3ce44SJohn Forte 	uint32_t i;
4940fcf3ce44SJohn Forte 
4941fcf3ce44SJohn Forte 	if (size > FCT_DMEM_MAX_BUF_SIZE) {
4942fcf3ce44SJohn Forte 		size = FCT_DMEM_MAX_BUF_SIZE;
4943fcf3ce44SJohn Forte 	}
4944291a2b48SSukumar Swaminathan 
4945fcf3ce44SJohn Forte 	p = port->dmem_bucket;
4946fcf3ce44SJohn Forte 	for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) {
4947fcf3ce44SJohn Forte 		if (!p->dmem_nbufs) {
4948fcf3ce44SJohn Forte 			continue;
4949fcf3ce44SJohn Forte 		}
4950291a2b48SSukumar Swaminathan 
4951fcf3ce44SJohn Forte 		if (p->dmem_buf_size >= size) {
4952fcf3ce44SJohn Forte 			mutex_enter(&p->dmem_lock);
4953fcf3ce44SJohn Forte 			if (p->dmem_nbufs_free) {
4954fcf3ce44SJohn Forte 				if (p->dmem_buf_size < *pminsize) {
4955fcf3ce44SJohn Forte 					*pminsize = p->dmem_buf_size;
4956fcf3ce44SJohn Forte 					TGTPORTSTAT.FctNoBuffer++;
4957fcf3ce44SJohn Forte 
4958fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
4959fcf3ce44SJohn Forte 					    &emlxs_fct_api_msg,
4960fcf3ce44SJohn Forte 					    "emlxs_fct_dbuf_alloc: Failed(1).");
4961fcf3ce44SJohn Forte 					mutex_exit(&p->dmem_lock);
4962fcf3ce44SJohn Forte 					return (NULL);
4963fcf3ce44SJohn Forte 				}
4964291a2b48SSukumar Swaminathan 
4965fcf3ce44SJohn Forte 				bctl = p->dmem_bctl_free_list;
4966fcf3ce44SJohn Forte 				if (bctl == NULL) {
4967fcf3ce44SJohn Forte 					mutex_exit(&p->dmem_lock);
4968fcf3ce44SJohn Forte 					continue;
4969fcf3ce44SJohn Forte 				}
4970291a2b48SSukumar Swaminathan 
4971fcf3ce44SJohn Forte 				p->dmem_bctl_free_list = bctl->bctl_next;
4972fcf3ce44SJohn Forte 				p->dmem_nbufs_free--;
4973fcf3ce44SJohn Forte 				bctl->bctl_buf->db_data_size = size;
4974fcf3ce44SJohn Forte 				mutex_exit(&p->dmem_lock);
4975fcf3ce44SJohn Forte 
4976fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4977fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
497882527734SSukumar Swaminathan 				    "emlx_fct_buf_alloc: bctl_buf %p: size %d",
4979fcf3ce44SJohn Forte 				    bctl->bctl_buf, size);
4980291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
4981fcf3ce44SJohn Forte 
4982fcf3ce44SJohn Forte 				return (bctl->bctl_buf);
4983fcf3ce44SJohn Forte 			}
4984fcf3ce44SJohn Forte 			mutex_exit(&p->dmem_lock);
4985fcf3ce44SJohn Forte 
4986fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4987fcf3ce44SJohn Forte 			    "emlx_fct_buf_alloc size %d Nothing free bck %d",
4988fcf3ce44SJohn Forte 			    size, i);
4989fcf3ce44SJohn Forte 		}
4990fcf3ce44SJohn Forte 	}
4991fcf3ce44SJohn Forte 
4992fcf3ce44SJohn Forte 	*pminsize = 0;
4993fcf3ce44SJohn Forte 	TGTPORTSTAT.FctNoBuffer++;
4994fcf3ce44SJohn Forte 
4995fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4996fcf3ce44SJohn Forte 	    "emlxs_fct_dbuf_alloc: Failed(2).");
4997fcf3ce44SJohn Forte 
4998fcf3ce44SJohn Forte 	return (NULL);
4999fcf3ce44SJohn Forte 
500082527734SSukumar Swaminathan } /* emlxs_fct_dbuf_alloc() */
5001fcf3ce44SJohn Forte 
5002fcf3ce44SJohn Forte 
500382527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
5004291a2b48SSukumar Swaminathan /*ARGSUSED*/
5005fcf3ce44SJohn Forte static void
5006fcf3ce44SJohn Forte emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *dbuf)
5007fcf3ce44SJohn Forte {
5008fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *bctl =
5009fcf3ce44SJohn Forte 	    (emlxs_fct_dmem_bctl_t *)dbuf->db_port_private;
5010fcf3ce44SJohn Forte 	emlxs_fct_dmem_bucket_t *p = bctl->bctl_bucket;
5011fcf3ce44SJohn Forte 
501282527734SSukumar Swaminathan #ifdef FCT_API_TRACE_1
5013fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
5014fcf3ce44SJohn Forte 	    "emlx_fct_buf_free %p", dbuf);
5015291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
5016fcf3ce44SJohn Forte 
5017fcf3ce44SJohn Forte 	mutex_enter(&p->dmem_lock);
5018fcf3ce44SJohn Forte 	bctl->bctl_next = p->dmem_bctl_free_list;
5019fcf3ce44SJohn Forte 	p->dmem_bctl_free_list = bctl;
5020fcf3ce44SJohn Forte 	p->dmem_nbufs_free++;
5021fcf3ce44SJohn Forte 	mutex_exit(&p->dmem_lock);
5022fcf3ce44SJohn Forte 
502382527734SSukumar Swaminathan } /* emlxs_fct_dbuf_free() */
5024fcf3ce44SJohn Forte 
5025fcf3ce44SJohn Forte 
5026*b3660a96SSukumar Swaminathan static int
5027*b3660a96SSukumar Swaminathan emlxs_fct_dbuf_dma_sync(emlxs_hba_t *hba, stmf_data_buf_t *dbuf,
5028*b3660a96SSukumar Swaminathan     uint_t sync_type)
5029fcf3ce44SJohn Forte {
5030fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *bctl =
5031fcf3ce44SJohn Forte 	    (emlxs_fct_dmem_bctl_t *)dbuf->db_port_private;
5032fcf3ce44SJohn Forte 	emlxs_fct_dmem_bucket_t *p = bctl->bctl_bucket;
5033*b3660a96SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
5034*b3660a96SSukumar Swaminathan 	int retval = 0;
5035fcf3ce44SJohn Forte 
5036fcf3ce44SJohn Forte 	(void) ddi_dma_sync(p->dmem_dma_handle,
5037fcf3ce44SJohn Forte 	    (unsigned long)(bctl->bctl_dev_addr - p->dmem_dev_addr),
5038fcf3ce44SJohn Forte 	    dbuf->db_data_size, sync_type);
5039fcf3ce44SJohn Forte 
5040*b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
5041*b3660a96SSukumar Swaminathan 	if (emlxs_fm_check_dma_handle(hba, p->dmem_dma_handle)
5042*b3660a96SSukumar Swaminathan 	    != DDI_FM_OK) {
5043*b3660a96SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
5044*b3660a96SSukumar Swaminathan 		    &emlxs_invalid_dma_handle_msg,
5045*b3660a96SSukumar Swaminathan 		    "emlxs_fct_dbuf_dma_sync: hdl=%p",
5046*b3660a96SSukumar Swaminathan 		    p->dmem_dma_handle);
5047*b3660a96SSukumar Swaminathan 		retval = 1;
5048*b3660a96SSukumar Swaminathan 	}
5049*b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
5050*b3660a96SSukumar Swaminathan 
5051*b3660a96SSukumar Swaminathan 	return (retval);
5052*b3660a96SSukumar Swaminathan 
505382527734SSukumar Swaminathan } /* emlxs_fct_dbuf_dma_sync() */
5054fcf3ce44SJohn Forte 
5055fcf3ce44SJohn Forte 
5056291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
5057