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 /*
23bce54adfSSukumar Swaminathan  * Copyright 2010 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 
43291a2b48SSukumar Swaminathan static emlxs_buf_t *emlxs_fct_cmd_init(emlxs_port_t *port,
44*a9800bebSGarrett D'Amore     fct_cmd_t *fct_cmd, uint16_t fct_state);
4582527734SSukumar Swaminathan static void emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd,
4682527734SSukumar Swaminathan 	uint16_t fct_state);
4782527734SSukumar Swaminathan static void emlxs_fct_cmd_post(emlxs_port_t *port, fct_cmd_t *fct_cmd,
4882527734SSukumar Swaminathan 	uint16_t fct_state);
49fcf3ce44SJohn Forte 
5082527734SSukumar Swaminathan static fct_status_t emlxs_fct_flogi_xchg(struct fct_local_port *fct_port,
51fcf3ce44SJohn Forte     struct fct_flogi_xchg *fx);
52fcf3ce44SJohn Forte static fct_status_t emlxs_fct_get_link_info(fct_local_port_t *fct_port,
53fcf3ce44SJohn Forte     fct_link_info_t *link);
54fcf3ce44SJohn Forte static fct_status_t emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port,
55fcf3ce44SJohn Forte     fct_remote_port_t *port_handle);
56fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_cmd(fct_cmd_t *fct_cmd);
57fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd,
58fcf3ce44SJohn Forte     stmf_data_buf_t *dbuf, uint32_t ioflags);
59291a2b48SSukumar Swaminathan static fct_status_t emlxs_fct_send_cmd_rsp(fct_cmd_t *fct_cmd, uint32_t flags);
60291a2b48SSukumar Swaminathan static fct_status_t emlxs_fct_abort(fct_local_port_t *fct_port,
61291a2b48SSukumar Swaminathan     fct_cmd_t *cmd, uint32_t flags);
62fcf3ce44SJohn Forte static void emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg);
63fcf3ce44SJohn Forte static fct_status_t emlxs_fct_register_remote_port(fct_local_port_t *fct_port,
64fcf3ce44SJohn Forte     fct_remote_port_t *port_handle, fct_cmd_t *plogi);
65fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd);
66fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd);
67fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd);
68fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd);
69fcf3ce44SJohn Forte static void emlxs_fct_pkt_comp(fc_packet_t *pkt);
7082527734SSukumar Swaminathan static void emlxs_fct_populate_hba_details(fct_local_port_t *fct_port,
71fcf3ce44SJohn Forte     fct_port_attrs_t *port_attrs);
7282527734SSukumar Swaminathan static fct_status_t emlxs_fct_port_info(uint32_t cmd,
7382527734SSukumar Swaminathan     fct_local_port_t *fct_port, void *arg, uint8_t *buffer, uint32_t *size);
74fcf3ce44SJohn Forte 
75fcf3ce44SJohn Forte static fct_status_t emlxs_fct_dmem_init(emlxs_port_t *port);
76fcf3ce44SJohn Forte static void emlxs_fct_dmem_fini(emlxs_port_t *port);
77fcf3ce44SJohn Forte 
78fcf3ce44SJohn Forte static stmf_data_buf_t *emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port,
79fcf3ce44SJohn Forte     uint32_t size, uint32_t *pminsize, uint32_t flags);
80fcf3ce44SJohn Forte static void emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *dbuf);
81fcf3ce44SJohn Forte 
82b3660a96SSukumar Swaminathan static int emlxs_fct_dbuf_dma_sync(emlxs_hba_t *hba, stmf_data_buf_t *dbuf,
83b3660a96SSukumar Swaminathan     uint_t sync_type);
84291a2b48SSukumar Swaminathan static emlxs_buf_t *emlxs_fct_pkt_init(emlxs_port_t *port,
85291a2b48SSukumar Swaminathan     fct_cmd_t *fct_cmd, fc_packet_t *pkt);
86fcf3ce44SJohn Forte 
87fcf3ce44SJohn Forte static void emlxs_fct_unsol_flush(emlxs_port_t *port);
8882527734SSukumar Swaminathan static uint32_t emlxs_fct_process_unsol_flogi(emlxs_port_t *port,
8982527734SSukumar Swaminathan     CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
9082527734SSukumar Swaminathan static uint32_t emlxs_fct_process_unsol_plogi(emlxs_port_t *port,
9182527734SSukumar Swaminathan     CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
92fe199829SSukumar Swaminathan static uint32_t emlxs_fct_pkt_abort_txq(emlxs_port_t *port,
93fe199829SSukumar Swaminathan     emlxs_buf_t *cmd_sbp);
94fcf3ce44SJohn Forte static fct_status_t emlxs_fct_send_qfull_reply(emlxs_port_t *port,
95fcf3ce44SJohn Forte     emlxs_node_t *ndlp, uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd);
96291a2b48SSukumar Swaminathan 
97291a2b48SSukumar Swaminathan #ifdef FCT_IO_TRACE
98291a2b48SSukumar Swaminathan uint8_t *emlxs_iotrace = 0;	/* global for mdb */
99291a2b48SSukumar Swaminathan int emlxs_iotrace_cnt = 0;
100291a2b48SSukumar Swaminathan 
10182527734SSukumar Swaminathan /*
10282527734SSukumar Swaminathan  *
10382527734SSukumar Swaminathan  * FCT_CMD  (cmd_sbp->fct_state)
10482527734SSukumar Swaminathan  *
10582527734SSukumar Swaminathan  * STATE				LOCK STATUS			OWNER
10682527734SSukumar Swaminathan  * -----------------------------------------------------------------------------
10782527734SSukumar Swaminathan  * EMLXS_FCT_ABORT_DONE			Lock Destroyed			COMSTAR
10882527734SSukumar Swaminathan  * EMLXS_FCT_IO_DONE			Lock Destroyed			COMSTAR
10982527734SSukumar Swaminathan  *
11082527734SSukumar Swaminathan  * EMLXS_FCT_CMD_POSTED			Lock Released			COMSTAR
11182527734SSukumar Swaminathan  * EMLXS_FCT_OWNED			Lock Released			COMSTAR
11282527734SSukumar Swaminathan  *
11382527734SSukumar Swaminathan  * EMLXS_FCT_CMD_WAITQ			Lock Released			DRIVER
11482527734SSukumar Swaminathan  * EMLXS_FCT_RSP_PENDING		Lock Released			DRIVER
11582527734SSukumar Swaminathan  * EMLXS_FCT_REQ_PENDING		Lock Released			DRIVER
11682527734SSukumar Swaminathan  * EMLXS_FCT_REG_PENDING		Lock Released			DRIVER
11782527734SSukumar Swaminathan  * EMLXS_FCT_DATA_PENDING		Lock Released			DRIVER
11882527734SSukumar Swaminathan  * EMLXS_FCT_STATUS_PENDING		Lock Released			DRIVER
11982527734SSukumar Swaminathan  * EMLXS_FCT_CLOSE_PENDING		Lock Released			DRIVER
12082527734SSukumar Swaminathan  * EMLXS_FCT_ABORT_PENDING		Lock Released			DRIVER
12182527734SSukumar Swaminathan  *
12282527734SSukumar Swaminathan  * EMLXS_FCT_FCP_CMD_RECEIVED		Transistional, lock held	DRIVER
12382527734SSukumar Swaminathan  * EMLXS_FCT_ELS_CMD_RECEIVED		Transistional, lock held	DRIVER
12482527734SSukumar Swaminathan  * EMLXS_FCT_SEND_CMD_RSP		Transistional, lock held	DRIVER
12582527734SSukumar Swaminathan  * EMLXS_FCT_SEND_ELS_RSP		Transistional, lock held	DRIVER
12682527734SSukumar Swaminathan  * EMLXS_FCT_SEND_ELS_REQ		Transistional, lock held	DRIVER
12782527734SSukumar Swaminathan  * EMLXS_FCT_SEND_CT_REQ		Transistional, lock held	DRIVER
12882527734SSukumar Swaminathan  * EMLXS_FCT_REG_COMPLETE		Transistional, lock held	DRIVER
12982527734SSukumar Swaminathan  * EMLXS_FCT_SEND_FCP_DATA		Transistional, lock held	DRIVER
13082527734SSukumar Swaminathan  * EMLXS_FCT_SEND_FCP_STATUS		Transistional, lock held	DRIVER
13182527734SSukumar Swaminathan  * EMLXS_FCT_PKT_COMPLETE		Transistional, lock held	DRIVER
13282527734SSukumar Swaminathan  * EMLXS_FCT_PKT_FCPRSP_COMPLETE	Transistional, lock held	DRIVER
13382527734SSukumar Swaminathan  * EMLXS_FCT_PKT_ELSRSP_COMPLETE	Transistional, lock held	DRIVER
13482527734SSukumar Swaminathan  * EMLXS_FCT_PKT_ELSCMD_COMPLETE	Transistional, lock held	DRIVER
13582527734SSukumar Swaminathan  * EMLXS_FCT_PKT_CTCMD_COMPLETE		Transistional, lock held	DRIVER
13682527734SSukumar Swaminathan  * EMLXS_FCT_REQ_COMPLETE		Transistional, lock held	DRIVER
13782527734SSukumar Swaminathan  *
13882527734SSukumar Swaminathan  *
13982527734SSukumar Swaminathan  * 	COMSTAR OWNED	DRIVER OWNED
14082527734SSukumar Swaminathan  * 	-------------	---------------------------------------------------
14182527734SSukumar Swaminathan  * 	------- >	@	   Accept---- >Release  @   Acquire--- >+
14282527734SSukumar Swaminathan  *									|
14382527734SSukumar Swaminathan  *	< -------	@	Post/Done< ----Acquire  @   Release< ---+
14482527734SSukumar Swaminathan  *
14582527734SSukumar Swaminathan  * 	@  :Indicates COMSTAR use of emlxs_fct_abort()
14682527734SSukumar Swaminathan  *	    Abort requests set the EMLXS_FCT_ABORT_INP flag.
14782527734SSukumar Swaminathan  *
14882527734SSukumar Swaminathan  * 	Accept		:Indicates use of emlxs_fct_cmd_accept()
14982527734SSukumar Swaminathan  * 	Acquire		:Indicates use of emlxs_fct_cmd_acquire()
15082527734SSukumar Swaminathan  * 	Post		:Indicates use of emlxs_fct_cmd_post()
15182527734SSukumar Swaminathan  * 	Done		:Indicates use of emlxs_fct_cmd_done()
15282527734SSukumar Swaminathan  */
15382527734SSukumar Swaminathan 
154291a2b48SSukumar Swaminathan void
155291a2b48SSukumar Swaminathan emlxs_fct_io_trace(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint32_t data)
156291a2b48SSukumar Swaminathan {
157291a2b48SSukumar Swaminathan 	emlxs_iotrace_t *iop = port->iotrace;
158291a2b48SSukumar Swaminathan 	uint16_t iotrace_cnt;
159291a2b48SSukumar Swaminathan 	uint16_t iotrace_index;
160291a2b48SSukumar Swaminathan 	int i;
161291a2b48SSukumar Swaminathan 
162291a2b48SSukumar Swaminathan 	if (!iop) {
163291a2b48SSukumar Swaminathan 		return;
164291a2b48SSukumar Swaminathan 	}
165291a2b48SSukumar Swaminathan 
166291a2b48SSukumar Swaminathan 	mutex_enter(&port->iotrace_mtx);
167291a2b48SSukumar Swaminathan 	iotrace_cnt = port->iotrace_cnt;
168291a2b48SSukumar Swaminathan 	iotrace_index = port->iotrace_index;
169291a2b48SSukumar Swaminathan 
170291a2b48SSukumar Swaminathan 	switch (data) {
171291a2b48SSukumar Swaminathan 
172291a2b48SSukumar Swaminathan 		/* New entry */
173291a2b48SSukumar Swaminathan 	case EMLXS_FCT_ELS_CMD_RECEIVED:
174291a2b48SSukumar Swaminathan 	case EMLXS_FCT_FCP_CMD_RECEIVED:
175291a2b48SSukumar Swaminathan 	case EMLXS_FCT_SEND_ELS_REQ:
176291a2b48SSukumar Swaminathan 	case EMLXS_FCT_SEND_CT_REQ:
177291a2b48SSukumar Swaminathan 		for (i = 0; i < iotrace_cnt; i++) {
178291a2b48SSukumar Swaminathan 			if ((iop->fct_cmd == fct_cmd) &&
179291a2b48SSukumar Swaminathan 			    (iop->trc[0] != (uint8_t)(0)))
180291a2b48SSukumar Swaminathan 				break;
181291a2b48SSukumar Swaminathan 			iop++;
182291a2b48SSukumar Swaminathan 		}
183291a2b48SSukumar Swaminathan 		if (i < iotrace_cnt) {
184291a2b48SSukumar Swaminathan 			/* New entry already exists */
185291a2b48SSukumar Swaminathan 			mutex_exit(&port->iotrace_mtx);
186291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
187291a2b48SSukumar Swaminathan 			    "IOTRACE: New entry already exists: fct_cmd: %p",
188291a2b48SSukumar Swaminathan 			    fct_cmd);
189291a2b48SSukumar Swaminathan 			return;
190291a2b48SSukumar Swaminathan 		}
191291a2b48SSukumar Swaminathan 		iop = port->iotrace + iotrace_index;
192291a2b48SSukumar Swaminathan 		for (i = 0; i < iotrace_cnt; i++) {
193291a2b48SSukumar Swaminathan 			if (iop->trc[0] == (uint8_t)(0))
194291a2b48SSukumar Swaminathan 				break;
195291a2b48SSukumar Swaminathan 
196291a2b48SSukumar Swaminathan 			iop++;
197291a2b48SSukumar Swaminathan 			if (iop == (port->iotrace + iotrace_cnt))
198291a2b48SSukumar Swaminathan 				iop = port->iotrace;
199291a2b48SSukumar Swaminathan 		}
200291a2b48SSukumar Swaminathan 		if (i >= iotrace_cnt) {
201291a2b48SSukumar Swaminathan 			/* No new slots available */
202291a2b48SSukumar Swaminathan 			mutex_exit(&port->iotrace_mtx);
203291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
204291a2b48SSukumar Swaminathan 			    "IOTRACE: No new slots: fct_cmd: %p data: %d",
205291a2b48SSukumar Swaminathan 			    fct_cmd, data);
206291a2b48SSukumar Swaminathan 			return;
207291a2b48SSukumar Swaminathan 		}
208291a2b48SSukumar Swaminathan 		port->iotrace_index++;
209291a2b48SSukumar Swaminathan 		if (port->iotrace_index >= iotrace_cnt)
210291a2b48SSukumar Swaminathan 			port->iotrace_index = 0;
211291a2b48SSukumar Swaminathan 
212291a2b48SSukumar Swaminathan 		bzero((uint8_t *)iop, sizeof (emlxs_iotrace_t));
213291a2b48SSukumar Swaminathan 		iop->fct_cmd = fct_cmd;
214291a2b48SSukumar Swaminathan 		iop->xri = fct_cmd->cmd_rxid;
215291a2b48SSukumar Swaminathan 		iop->marker = 0xff;
216291a2b48SSukumar Swaminathan 		iop->trc[0] = 2;
217291a2b48SSukumar Swaminathan 		iop->trc[1] = data;
218291a2b48SSukumar Swaminathan 		mutex_exit(&port->iotrace_mtx);
219291a2b48SSukumar Swaminathan 		return;
220291a2b48SSukumar Swaminathan 	}
221291a2b48SSukumar Swaminathan 
222291a2b48SSukumar Swaminathan 	for (i = 0; i < iotrace_cnt; i++) {
223291a2b48SSukumar Swaminathan 		if ((iop->fct_cmd == fct_cmd) &&
224291a2b48SSukumar Swaminathan 		    (iop->trc[0] != (uint8_t)(0)))
225291a2b48SSukumar Swaminathan 			break;
226291a2b48SSukumar Swaminathan 		iop++;
227291a2b48SSukumar Swaminathan 	}
228291a2b48SSukumar Swaminathan 	if (i >= iotrace_cnt) {
229291a2b48SSukumar Swaminathan 		/* Cannot find existing slot for fct_cmd */
230291a2b48SSukumar Swaminathan 		mutex_exit(&port->iotrace_mtx);
231291a2b48SSukumar Swaminathan 
232291a2b48SSukumar Swaminathan 		if ((data != EMLXS_FCT_REG_PENDING) &&
233291a2b48SSukumar Swaminathan 		    (data != EMLXS_FCT_REG_COMPLETE)) {
234291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
235291a2b48SSukumar Swaminathan 			    "IOTRACE: Missing slot: fct_cmd: %p data: %d",
236291a2b48SSukumar Swaminathan 			    fct_cmd, data);
237291a2b48SSukumar Swaminathan 		}
238291a2b48SSukumar Swaminathan 		return;
239291a2b48SSukumar Swaminathan 	}
240291a2b48SSukumar Swaminathan 
241291a2b48SSukumar Swaminathan 	if (iop->trc[0] >= MAX_IO_TRACE) {
242291a2b48SSukumar Swaminathan 		/* trc overrun for fct_cmd */
243291a2b48SSukumar Swaminathan 		mutex_exit(&port->iotrace_mtx);
244291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
245291a2b48SSukumar Swaminathan 		    "IOTRACE: trc overrun slot: fct_cmd: %p data: %d",
246291a2b48SSukumar Swaminathan 		    fct_cmd, data);
247291a2b48SSukumar Swaminathan 		return;
248291a2b48SSukumar Swaminathan 	}
249291a2b48SSukumar Swaminathan 
250291a2b48SSukumar Swaminathan 	if (iop->xri != fct_cmd->cmd_rxid) {
251291a2b48SSukumar Swaminathan 		/* xri mismatch for fct_cmd */
252291a2b48SSukumar Swaminathan 		mutex_exit(&port->iotrace_mtx);
253291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
254291a2b48SSukumar Swaminathan 		    "IOTRACE: xri mismatch %x != %x: fct_cmd: %p data: %d",
255291a2b48SSukumar Swaminathan 		    iop->xri, fct_cmd->cmd_rxid, fct_cmd, data);
256291a2b48SSukumar Swaminathan 		return;
257291a2b48SSukumar Swaminathan 	}
258291a2b48SSukumar Swaminathan 
259291a2b48SSukumar Swaminathan 	iop->trc[iop->trc[0]] = data;
260291a2b48SSukumar Swaminathan 	if ((data == EMLXS_FCT_IO_DONE) || (data == EMLXS_FCT_ABORT_DONE)) {
26182527734SSukumar Swaminathan 		/* IOCB ULPCOMMAND is saved after EMLXS_FCT_IOCB_ISSUED */
26282527734SSukumar Swaminathan 		if (iop->trc[iop->trc[0]-1] == EMLXS_FCT_IOCB_ISSUED) {
263291a2b48SSukumar Swaminathan 			iop->trc[0]++;
26482527734SSukumar Swaminathan 		} else {
265291a2b48SSukumar Swaminathan 			iop->trc[0] = 0;
26682527734SSukumar Swaminathan 	} else {
267291a2b48SSukumar Swaminathan 		iop->trc[0]++;
26882527734SSukumar Swaminathan 	}
269291a2b48SSukumar Swaminathan 	mutex_exit(&port->iotrace_mtx);
27082527734SSukumar Swaminathan 
27182527734SSukumar Swaminathan 	return;
27282527734SSukumar Swaminathan 
27382527734SSukumar Swaminathan } /* emlxs_fct_io_trace() */
274291a2b48SSukumar Swaminathan #endif /* FCT_IO_TRACE */
275fcf3ce44SJohn Forte 
276fcf3ce44SJohn Forte #ifdef MODSYM_SUPPORT
277fcf3ce44SJohn Forte 
278e51761e0SSukumar Swaminathan extern int
279fcf3ce44SJohn Forte emlxs_fct_modopen()
280fcf3ce44SJohn Forte {
281fcf3ce44SJohn Forte 	int err;
282fcf3ce44SJohn Forte 
28382527734SSukumar Swaminathan 	mutex_enter(&emlxs_device.lock);
28482527734SSukumar Swaminathan 
28582527734SSukumar Swaminathan 	if (emlxs_modsym.fct_modopen) {
28682527734SSukumar Swaminathan 		mutex_exit(&emlxs_device.lock);
28782527734SSukumar Swaminathan 		return (0);
288fcf3ce44SJohn Forte 	}
289291a2b48SSukumar Swaminathan 
29082527734SSukumar Swaminathan 	emlxs_modsym.fct_modopen++;
29182527734SSukumar Swaminathan 
292fcf3ce44SJohn Forte 	/* Comstar (fct) */
293fcf3ce44SJohn Forte 	err = 0;
294fcf3ce44SJohn Forte 	emlxs_modsym.mod_fct = ddi_modopen("drv/fct", KRTLD_MODE_FIRST, &err);
295fcf3ce44SJohn Forte 	if (!emlxs_modsym.mod_fct) {
296fcf3ce44SJohn Forte 
297fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "?%s: ddi_modopen drv/fct failed: err %d",
298fcf3ce44SJohn Forte 		    DRIVER_NAME, err);
299fcf3ce44SJohn Forte 		goto failed;
300fcf3ce44SJohn Forte 	}
301291a2b48SSukumar Swaminathan 
302fcf3ce44SJohn Forte 	/* Comstar (stmf) */
303fcf3ce44SJohn Forte 	err = 0;
304291a2b48SSukumar Swaminathan 	emlxs_modsym.mod_stmf =
305291a2b48SSukumar Swaminathan 	    ddi_modopen("drv/stmf", KRTLD_MODE_FIRST, &err);
306fcf3ce44SJohn Forte 	if (!emlxs_modsym.mod_stmf) {
307fcf3ce44SJohn Forte 
308fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "?%s: ddi_modopen drv/stmf failed: err %d",
309fcf3ce44SJohn Forte 		    DRIVER_NAME, err);
310fcf3ce44SJohn Forte 		goto failed;
311fcf3ce44SJohn Forte 	}
312291a2b48SSukumar Swaminathan 
313fcf3ce44SJohn Forte 	err = 0;
314fcf3ce44SJohn Forte 	/* Check if the fct fct_alloc is present */
315291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_alloc = (void *(*)())ddi_modsym(emlxs_modsym.mod_fct,
316fcf3ce44SJohn Forte 	    "fct_alloc", &err);
317fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_alloc == NULL) {
318fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
319fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_alloc not present", DRIVER_NAME);
320fcf3ce44SJohn Forte 		goto failed;
321fcf3ce44SJohn Forte 	}
322291a2b48SSukumar Swaminathan 
323fcf3ce44SJohn Forte 	err = 0;
324fcf3ce44SJohn Forte 	/* Check if the fct fct_free is present */
325291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_free = (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
326fcf3ce44SJohn Forte 	    "fct_free", &err);
327fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_free == NULL) {
328fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
329fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_free not present", DRIVER_NAME);
330fcf3ce44SJohn Forte 		goto failed;
331fcf3ce44SJohn Forte 	}
332291a2b48SSukumar Swaminathan 
333fcf3ce44SJohn Forte 	err = 0;
334fcf3ce44SJohn Forte 	/* Check if the fct fct_scsi_task_alloc is present */
335291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_scsi_task_alloc =
336291a2b48SSukumar Swaminathan 	    (void *(*)(void *, uint16_t, uint32_t, uint8_t *,
337291a2b48SSukumar Swaminathan 	    uint16_t, uint16_t))ddi_modsym(emlxs_modsym.mod_fct,
338291a2b48SSukumar Swaminathan 	    "fct_scsi_task_alloc", &err);
339fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_scsi_task_alloc == NULL) {
340fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
341fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_scsi_task_alloc not present",
342fcf3ce44SJohn Forte 		    DRIVER_NAME);
343fcf3ce44SJohn Forte 		goto failed;
344fcf3ce44SJohn Forte 	}
345291a2b48SSukumar Swaminathan 
346fcf3ce44SJohn Forte 	err = 0;
347fcf3ce44SJohn Forte 	/* Check if the fct fct_register_local_port is present */
348291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_register_local_port =
349291a2b48SSukumar Swaminathan 	    (int (*)())ddi_modsym(emlxs_modsym.mod_fct,
350291a2b48SSukumar Swaminathan 	    "fct_register_local_port", &err);
351fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_register_local_port == NULL) {
352fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
353fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_register_local_port not present",
354fcf3ce44SJohn Forte 		    DRIVER_NAME);
355fcf3ce44SJohn Forte 		goto failed;
356fcf3ce44SJohn Forte 	}
357291a2b48SSukumar Swaminathan 
358fcf3ce44SJohn Forte 	err = 0;
359fcf3ce44SJohn Forte 	/* Check if the fct fct_deregister_local_port is present */
360291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_deregister_local_port =
361291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
362291a2b48SSukumar Swaminathan 	    "fct_deregister_local_port", &err);
363fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_deregister_local_port == NULL) {
364fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
365fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_deregister_local_port not present",
366fcf3ce44SJohn Forte 		    DRIVER_NAME);
367fcf3ce44SJohn Forte 		goto failed;
368fcf3ce44SJohn Forte 	}
369291a2b48SSukumar Swaminathan 
370fcf3ce44SJohn Forte 	err = 0;
371fcf3ce44SJohn Forte 	/* Check if the fct fct_handle_event is present */
372291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_handle_event =
373291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_handle_event",
374291a2b48SSukumar Swaminathan 	    &err);
375fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_handle_event == NULL) {
376fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
377291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_handle_event not present",
378291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
379fcf3ce44SJohn Forte 		goto failed;
380fcf3ce44SJohn Forte 	}
381291a2b48SSukumar Swaminathan 
382fcf3ce44SJohn Forte 	err = 0;
383fcf3ce44SJohn Forte 	/* Check if the fct fct_post_rcvd_cmd is present */
384291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_post_rcvd_cmd =
385291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_post_rcvd_cmd",
386291a2b48SSukumar Swaminathan 	    &err);
387fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_post_rcvd_cmd == NULL) {
388fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
389291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_post_rcvd_cmd not present",
390291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
391fcf3ce44SJohn Forte 		goto failed;
392fcf3ce44SJohn Forte 	}
393fcf3ce44SJohn Forte 	err = 0;
394fcf3ce44SJohn Forte 	/* Check if the fct fct_alloc is present */
395291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_ctl = (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
396fcf3ce44SJohn Forte 	    "fct_ctl", &err);
397fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_ctl == NULL) {
398fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
399fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_ctl not present", DRIVER_NAME);
400fcf3ce44SJohn Forte 		goto failed;
401fcf3ce44SJohn Forte 	}
402fcf3ce44SJohn Forte 	err = 0;
403291a2b48SSukumar Swaminathan 	/* Check if the fct fct_queue_cmd_for_termination is present */
404291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_queue_cmd_for_termination =
405291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
406291a2b48SSukumar Swaminathan 	    "fct_queue_cmd_for_termination", &err);
407291a2b48SSukumar Swaminathan 	if ((void *)emlxs_modsym.fct_queue_cmd_for_termination == NULL) {
408291a2b48SSukumar Swaminathan 		cmn_err(CE_WARN,
409291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_queue_cmd_for_termination not present",
410291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
411291a2b48SSukumar Swaminathan 		goto failed;
412291a2b48SSukumar Swaminathan 	}
413291a2b48SSukumar Swaminathan 	err = 0;
414fcf3ce44SJohn Forte 	/* Check if the fct fct_send_response_done is present */
415291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_send_response_done =
416291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
417291a2b48SSukumar Swaminathan 	    "fct_send_response_done", &err);
418fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_send_response_done == NULL) {
419fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
420fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_send_response_done not present",
421fcf3ce44SJohn Forte 		    DRIVER_NAME);
422fcf3ce44SJohn Forte 		goto failed;
423fcf3ce44SJohn Forte 	}
424fcf3ce44SJohn Forte 	err = 0;
425fcf3ce44SJohn Forte 	/* Check if the fct fct_send_cmd_done is present */
426291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_send_cmd_done =
427291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_send_cmd_done",
428291a2b48SSukumar Swaminathan 	    &err);
429fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_send_cmd_done == NULL) {
430fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
431291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_send_cmd_done not present",
432291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
433fcf3ce44SJohn Forte 		goto failed;
434fcf3ce44SJohn Forte 	}
435fcf3ce44SJohn Forte 	err = 0;
436fcf3ce44SJohn Forte 	/* Check if the fct fct_scsi_xfer_data_done is present */
437291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_scsi_data_xfer_done =
438291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
439291a2b48SSukumar Swaminathan 	    "fct_scsi_data_xfer_done", &err);
440fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_scsi_data_xfer_done == NULL) {
441fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
442fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_scsi_data_xfer_done not present",
443fcf3ce44SJohn Forte 		    DRIVER_NAME);
444fcf3ce44SJohn Forte 		goto failed;
445fcf3ce44SJohn Forte 	}
446fcf3ce44SJohn Forte 	err = 0;
447fcf3ce44SJohn Forte 	/* Check if the fct fct_port_shutdown is present */
448291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_port_shutdown =
449291a2b48SSukumar Swaminathan 	    (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct,
450291a2b48SSukumar Swaminathan 	    "fct_port_shutdown", &err);
451fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_port_shutdown == NULL) {
452fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
453291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_port_shutdown not present",
454291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
455fcf3ce44SJohn Forte 		goto failed;
456fcf3ce44SJohn Forte 	}
457291a2b48SSukumar Swaminathan 
458fcf3ce44SJohn Forte 	err = 0;
459fcf3ce44SJohn Forte 	/* Check if the fct fct_port_initialize is present */
460291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_port_initialize =
461291a2b48SSukumar Swaminathan 	    (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct,
462291a2b48SSukumar Swaminathan 	    "fct_port_initialize", &err);
463fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_port_initialize == NULL) {
464fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
465fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_port_initialize not present",
466fcf3ce44SJohn Forte 		    DRIVER_NAME);
467fcf3ce44SJohn Forte 		goto failed;
468fcf3ce44SJohn Forte 	}
469291a2b48SSukumar Swaminathan 
470291a2b48SSukumar Swaminathan 	err = 0;
471291a2b48SSukumar Swaminathan 	/* Check if the fct fct_cmd_fca_aborted is present */
472291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_cmd_fca_aborted =
473291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
474291a2b48SSukumar Swaminathan 	    "fct_cmd_fca_aborted", &err);
475291a2b48SSukumar Swaminathan 	if ((void *)emlxs_modsym.fct_cmd_fca_aborted == NULL) {
476291a2b48SSukumar Swaminathan 		cmn_err(CE_WARN,
477291a2b48SSukumar Swaminathan 		    "?%s: drv/fct: fct_cmd_fca_aborted not present",
478291a2b48SSukumar Swaminathan 		    DRIVER_NAME);
479291a2b48SSukumar Swaminathan 		goto failed;
480291a2b48SSukumar Swaminathan 	}
481291a2b48SSukumar Swaminathan 
482fcf3ce44SJohn Forte 	err = 0;
483fcf3ce44SJohn Forte 	/* Check if the fct fct_handle_rcvd_flogi is present */
484291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_handle_rcvd_flogi =
485291a2b48SSukumar Swaminathan 	    (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct,
486291a2b48SSukumar Swaminathan 	    "fct_handle_rcvd_flogi", &err);
487fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.fct_handle_rcvd_flogi == NULL) {
488fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
489fcf3ce44SJohn Forte 		    "?%s: drv/fct: fct_handle_rcvd_flogi not present",
490fcf3ce44SJohn Forte 		    DRIVER_NAME);
491fcf3ce44SJohn Forte 		goto failed;
492fcf3ce44SJohn Forte 	}
493291a2b48SSukumar Swaminathan 
494fcf3ce44SJohn Forte 	/* Comstar (stmf) */
495fcf3ce44SJohn Forte 	err = 0;
496fcf3ce44SJohn Forte 	/* Check if the stmf stmf_alloc is present */
497291a2b48SSukumar Swaminathan 	emlxs_modsym.stmf_alloc =
498291a2b48SSukumar Swaminathan 	    (void *(*)())ddi_modsym(emlxs_modsym.mod_stmf, "stmf_alloc",
499291a2b48SSukumar Swaminathan 	    &err);
500fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.stmf_alloc == NULL) {
501fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
502fcf3ce44SJohn Forte 		    "?%s: drv/stmf: stmf_alloc not present", DRIVER_NAME);
503fcf3ce44SJohn Forte 		goto failed;
504fcf3ce44SJohn Forte 	}
505291a2b48SSukumar Swaminathan 
506fcf3ce44SJohn Forte 	err = 0;
507fcf3ce44SJohn Forte 	/* Check if the stmf stmf_free is present */
508291a2b48SSukumar Swaminathan 	emlxs_modsym.stmf_free = (void (*)())ddi_modsym(emlxs_modsym.mod_stmf,
509fcf3ce44SJohn Forte 	    "stmf_free", &err);
510fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.stmf_free == NULL) {
511fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
512fcf3ce44SJohn Forte 		    "?%s: drv/stmf: stmf_free not present", DRIVER_NAME);
513fcf3ce44SJohn Forte 		goto failed;
514fcf3ce44SJohn Forte 	}
515291a2b48SSukumar Swaminathan 
516fcf3ce44SJohn Forte 	err = 0;
517fcf3ce44SJohn Forte 	/* Check if the stmf stmf_deregister_port_provider is present */
518fcf3ce44SJohn Forte 	emlxs_modsym.stmf_deregister_port_provider =
519291a2b48SSukumar Swaminathan 	    (void (*)())ddi_modsym(emlxs_modsym.mod_stmf,
520fcf3ce44SJohn Forte 	    "stmf_deregister_port_provider", &err);
521fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.stmf_deregister_port_provider == NULL) {
522fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
523fcf3ce44SJohn Forte 		    "?%s: drv/stmf: stmf_deregister_port_provider not present",
524fcf3ce44SJohn Forte 		    DRIVER_NAME);
525fcf3ce44SJohn Forte 		goto failed;
526fcf3ce44SJohn Forte 	}
527291a2b48SSukumar Swaminathan 
528fcf3ce44SJohn Forte 	err = 0;
529fcf3ce44SJohn Forte 	/* Check if the stmf stmf_register_port_provider is present */
530fcf3ce44SJohn Forte 	emlxs_modsym.stmf_register_port_provider =
531291a2b48SSukumar Swaminathan 	    (int (*)())ddi_modsym(emlxs_modsym.mod_stmf,
532fcf3ce44SJohn Forte 	    "stmf_register_port_provider", &err);
533fcf3ce44SJohn Forte 	if ((void *)emlxs_modsym.stmf_register_port_provider == NULL) {
534fcf3ce44SJohn Forte 		cmn_err(CE_WARN,
535fcf3ce44SJohn Forte 		    "?%s: drv/stmf: stmf_register_port_provider not present",
536fcf3ce44SJohn Forte 		    DRIVER_NAME);
537fcf3ce44SJohn Forte 		goto failed;
538fcf3ce44SJohn Forte 	}
53982527734SSukumar Swaminathan 
54082527734SSukumar Swaminathan 	mutex_exit(&emlxs_device.lock);
54182527734SSukumar Swaminathan 	return (0);
542fcf3ce44SJohn Forte 
543fcf3ce44SJohn Forte failed:
54482527734SSukumar Swaminathan 
54582527734SSukumar Swaminathan 	mutex_exit(&emlxs_device.lock);
546fcf3ce44SJohn Forte 	emlxs_fct_modclose();
54782527734SSukumar Swaminathan 	return (1);
548fcf3ce44SJohn Forte 
54982527734SSukumar Swaminathan } /* emlxs_fct_modopen() */
550fcf3ce44SJohn Forte 
551fcf3ce44SJohn Forte 
552fcf3ce44SJohn Forte extern void
553fcf3ce44SJohn Forte emlxs_fct_modclose()
554fcf3ce44SJohn Forte {
55582527734SSukumar Swaminathan 	mutex_enter(&emlxs_device.lock);
55682527734SSukumar Swaminathan 
55782527734SSukumar Swaminathan 	if (emlxs_modsym.fct_modopen == 0) {
55882527734SSukumar Swaminathan 		mutex_exit(&emlxs_device.lock);
55982527734SSukumar Swaminathan 		return;
56082527734SSukumar Swaminathan 	}
56182527734SSukumar Swaminathan 
56282527734SSukumar Swaminathan 	emlxs_modsym.fct_modopen--;
56382527734SSukumar Swaminathan 
56482527734SSukumar Swaminathan 	if (emlxs_modsym.fct_modopen) {
56582527734SSukumar Swaminathan 		mutex_exit(&emlxs_device.lock);
56682527734SSukumar Swaminathan 		return;
56782527734SSukumar Swaminathan 	}
568fcf3ce44SJohn Forte 
569fcf3ce44SJohn Forte 	if (emlxs_modsym.mod_fct) {
570fcf3ce44SJohn Forte 		(void) ddi_modclose(emlxs_modsym.mod_fct);
571fcf3ce44SJohn Forte 		emlxs_modsym.mod_fct = 0;
572fcf3ce44SJohn Forte 	}
573291a2b48SSukumar Swaminathan 
574fcf3ce44SJohn Forte 	if (emlxs_modsym.mod_stmf) {
575fcf3ce44SJohn Forte 		(void) ddi_modclose(emlxs_modsym.mod_stmf);
576fcf3ce44SJohn Forte 		emlxs_modsym.mod_stmf = 0;
577fcf3ce44SJohn Forte 	}
578291a2b48SSukumar Swaminathan 
579fcf3ce44SJohn Forte 	emlxs_modsym.fct_alloc = NULL;
580fcf3ce44SJohn Forte 	emlxs_modsym.fct_free = NULL;
581fcf3ce44SJohn Forte 	emlxs_modsym.fct_scsi_task_alloc = NULL;
582fcf3ce44SJohn Forte 	emlxs_modsym.fct_register_local_port = NULL;
583fcf3ce44SJohn Forte 	emlxs_modsym.fct_deregister_local_port = NULL;
584fcf3ce44SJohn Forte 	emlxs_modsym.fct_handle_event = NULL;
585fcf3ce44SJohn Forte 	emlxs_modsym.fct_ctl = NULL;
586291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_queue_cmd_for_termination = NULL;
587fcf3ce44SJohn Forte 	emlxs_modsym.fct_send_response_done = NULL;
588fcf3ce44SJohn Forte 	emlxs_modsym.fct_send_cmd_done = NULL;
589fcf3ce44SJohn Forte 	emlxs_modsym.fct_scsi_data_xfer_done = NULL;
590fcf3ce44SJohn Forte 	emlxs_modsym.fct_port_shutdown = NULL;
591fcf3ce44SJohn Forte 	emlxs_modsym.fct_port_initialize = NULL;
592291a2b48SSukumar Swaminathan 	emlxs_modsym.fct_cmd_fca_aborted = NULL;
593fcf3ce44SJohn Forte 	emlxs_modsym.fct_handle_rcvd_flogi = NULL;
594fcf3ce44SJohn Forte 
595fcf3ce44SJohn Forte 	emlxs_modsym.stmf_alloc = NULL;
596fcf3ce44SJohn Forte 	emlxs_modsym.stmf_free = NULL;
597fcf3ce44SJohn Forte 	emlxs_modsym.stmf_deregister_port_provider = NULL;
598fcf3ce44SJohn Forte 	emlxs_modsym.stmf_register_port_provider = NULL;
599fcf3ce44SJohn Forte 
60082527734SSukumar Swaminathan 	mutex_exit(&emlxs_device.lock);
60182527734SSukumar Swaminathan 
60282527734SSukumar Swaminathan } /* emlxs_fct_modclose() */
603291a2b48SSukumar Swaminathan 
604291a2b48SSukumar Swaminathan #endif /* MODSYM_SUPPORT */
605291a2b48SSukumar Swaminathan 
606e2ca2865SSukumar Swaminathan /*
607e2ca2865SSukumar Swaminathan  * This routine is called to handle an unsol FLOGI exchange
608e2ca2865SSukumar Swaminathan  *	fx	save
609e2ca2865SSukumar Swaminathan  *	0	1	Process or save port->fx
610e2ca2865SSukumar Swaminathan  *	0	0	Process or reject port->fx
611e2ca2865SSukumar Swaminathan  *	1	1	Process port->fx, Process or save fx
612e2ca2865SSukumar Swaminathan  *	1	0	Process or reject port->fx, Process or reject fx
613e2ca2865SSukumar Swaminathan  */
614291a2b48SSukumar Swaminathan static void
615e2ca2865SSukumar Swaminathan emlxs_fct_handle_unsol_flogi(emlxs_port_t *port, fct_flogi_xchg_t *fx,
616e2ca2865SSukumar Swaminathan     uint32_t save)
617291a2b48SSukumar Swaminathan {
618e2ca2865SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
619291a2b48SSukumar Swaminathan 	fct_status_t status;
620291a2b48SSukumar Swaminathan 	IOCBQ iocbq;
621e2ca2865SSukumar Swaminathan 	fct_flogi_xchg_t fxchg;
622e2ca2865SSukumar Swaminathan 
623e2ca2865SSukumar Swaminathan begin:
624e2ca2865SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
625e2ca2865SSukumar Swaminathan 
626e2ca2865SSukumar Swaminathan 	/* Check if there is an old saved FLOGI */
627e2ca2865SSukumar Swaminathan 	if (port->fx.fx_op) {
628e2ca2865SSukumar Swaminathan 		/* Get it now */
629e2ca2865SSukumar Swaminathan 		bcopy(&port->fx, &fxchg, sizeof (fct_flogi_xchg_t));
630e2ca2865SSukumar Swaminathan 
631e2ca2865SSukumar Swaminathan 		if (fx) {
632e2ca2865SSukumar Swaminathan 			/* Save new FLOGI */
633e2ca2865SSukumar Swaminathan 			bcopy(fx, &port->fx, sizeof (fct_flogi_xchg_t));
634e2ca2865SSukumar Swaminathan 
635e2ca2865SSukumar Swaminathan 			/* Reject old stale FLOGI */
636e2ca2865SSukumar Swaminathan 			fx = &fxchg;
637e2ca2865SSukumar Swaminathan 			goto reject_it;
638e2ca2865SSukumar Swaminathan 
639e2ca2865SSukumar Swaminathan 		} else {
640e2ca2865SSukumar Swaminathan 			bzero(&port->fx, sizeof (fct_flogi_xchg_t));
641e2ca2865SSukumar Swaminathan 			fx = &fxchg;
642e2ca2865SSukumar Swaminathan 		}
643e2ca2865SSukumar Swaminathan 
644e2ca2865SSukumar Swaminathan 	} else if (!fx) {
645e2ca2865SSukumar Swaminathan 		/* Nothing to do, just return */
646e2ca2865SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
647e2ca2865SSukumar Swaminathan 		return;
648e2ca2865SSukumar Swaminathan 	}
649e2ca2865SSukumar Swaminathan 
650e2ca2865SSukumar Swaminathan 	/* We have a valid FLOGI here */
651e2ca2865SSukumar Swaminathan 	/* There is no saved FLOGI at this point either */
652e2ca2865SSukumar Swaminathan 
653e2ca2865SSukumar Swaminathan 	/* Check if COMSTAR is ready to accept it */
654e2ca2865SSukumar Swaminathan 	if (port->fct_flags & FCT_STATE_LINK_UP_ACKED) {
655e2ca2865SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
656291a2b48SSukumar Swaminathan 
657291a2b48SSukumar Swaminathan 		bzero((uint8_t *)&iocbq, sizeof (IOCBQ));
658e2ca2865SSukumar Swaminathan 		iocbq.iocb.un.elsreq.remoteID = fx->fx_sid;
659e2ca2865SSukumar Swaminathan 		iocbq.iocb.un.elsreq.myID = fx->fx_did;
660e2ca2865SSukumar Swaminathan 		iocbq.iocb.ULPCONTEXT = (uint16_t)fx->rsvd2;
661e2ca2865SSukumar Swaminathan 		fx->rsvd2 = 0; /* Clear the reserved field now */
662291a2b48SSukumar Swaminathan 
663e2ca2865SSukumar Swaminathan 		status = MODSYM(fct_handle_rcvd_flogi) (port->fct_port, fx);
664291a2b48SSukumar Swaminathan 
665291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
666291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
667e2ca2865SSukumar Swaminathan 		    "fct_handle_rcvd_flogi %p: status=%x",
668e2ca2865SSukumar Swaminathan 		    port->fct_port, status);
669291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
670291a2b48SSukumar Swaminathan 
671291a2b48SSukumar Swaminathan 		if (status == FCT_SUCCESS) {
672e2ca2865SSukumar Swaminathan 			if (fx->fx_op == ELS_OP_ACC) {
673291a2b48SSukumar Swaminathan 				(void) emlxs_els_reply(port, &iocbq,
674291a2b48SSukumar Swaminathan 				    ELS_CMD_ACC, ELS_CMD_FLOGI, 0, 0);
675291a2b48SSukumar Swaminathan 
676e2ca2865SSukumar Swaminathan 			} else {	/* ELS_OP_LSRJT */
677291a2b48SSukumar Swaminathan 				(void) emlxs_els_reply(port, &iocbq,
678e2ca2865SSukumar Swaminathan 				    ELS_CMD_LS_RJT, ELS_CMD_FLOGI,
679e2ca2865SSukumar Swaminathan 				    fx->fx_rjt_reason, fx->fx_rjt_expl);
680291a2b48SSukumar Swaminathan 			}
681291a2b48SSukumar Swaminathan 		} else {
682291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
683e2ca2865SSukumar Swaminathan 			    "FLOGI: sid=%x xid=%x. "
684e2ca2865SSukumar Swaminathan 			    "fct_handle_rcvd_flogi failed. Rejecting.",
685e2ca2865SSukumar Swaminathan 			    fx->fx_sid, iocbq.iocb.ULPCONTEXT);
686291a2b48SSukumar Swaminathan 
687e2ca2865SSukumar Swaminathan 			(void) emlxs_els_reply(port, &iocbq,
688e2ca2865SSukumar Swaminathan 			    ELS_CMD_LS_RJT, ELS_CMD_FLOGI,
689e2ca2865SSukumar Swaminathan 			    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
690291a2b48SSukumar Swaminathan 		}
691291a2b48SSukumar Swaminathan 
692e2ca2865SSukumar Swaminathan 		return;
693291a2b48SSukumar Swaminathan 	}
694fcf3ce44SJohn Forte 
695e2ca2865SSukumar Swaminathan 	if (save) {
696e2ca2865SSukumar Swaminathan 		/* Save FLOGI for later */
697e2ca2865SSukumar Swaminathan 		bcopy(fx, &port->fx, sizeof (fct_flogi_xchg_t));
698e2ca2865SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
699291a2b48SSukumar Swaminathan 		return;
700fcf3ce44SJohn Forte 	}
701291a2b48SSukumar Swaminathan 
702e2ca2865SSukumar Swaminathan reject_it:
703291a2b48SSukumar Swaminathan 
704e2ca2865SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
705fcf3ce44SJohn Forte 
706e2ca2865SSukumar Swaminathan 	if (port->fct_flags & FCT_STATE_LINK_UP) {
707e2ca2865SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
708e2ca2865SSukumar Swaminathan 		    "FLOGI: sid=%x xid=%x. Stale. Rejecting.",
709e2ca2865SSukumar Swaminathan 		    fx->fx_sid, fx->rsvd2);
710fcf3ce44SJohn Forte 
711e2ca2865SSukumar Swaminathan 		bzero((uint8_t *)&iocbq, sizeof (IOCBQ));
712e2ca2865SSukumar Swaminathan 		iocbq.iocb.un.elsreq.remoteID = fx->fx_sid;
713e2ca2865SSukumar Swaminathan 		iocbq.iocb.un.elsreq.myID = fx->fx_did;
714e2ca2865SSukumar Swaminathan 		iocbq.iocb.ULPCONTEXT = fx->rsvd2;
715291a2b48SSukumar Swaminathan 
716e2ca2865SSukumar Swaminathan 		(void) emlxs_els_reply(port, &iocbq,
717e2ca2865SSukumar Swaminathan 		    ELS_CMD_LS_RJT, ELS_CMD_FLOGI,
718e2ca2865SSukumar Swaminathan 		    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
719fcf3ce44SJohn Forte 
720e2ca2865SSukumar Swaminathan 		/* If we have an FLOGI saved, try sending it now */
721e2ca2865SSukumar Swaminathan 		if (port->fx.fx_op) {
722e2ca2865SSukumar Swaminathan 			fx = NULL;
723e2ca2865SSukumar Swaminathan 			goto begin;
724e2ca2865SSukumar Swaminathan 		}
725291a2b48SSukumar Swaminathan 
726e2ca2865SSukumar Swaminathan 	} else {
727e2ca2865SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
728e2ca2865SSukumar Swaminathan 		    "FLOGI: sid=%x xid=%x. Link down. "
729e2ca2865SSukumar Swaminathan 		    "Dropping.",
730e2ca2865SSukumar Swaminathan 		    fx->fx_sid, fx->rsvd2);
731291a2b48SSukumar Swaminathan 	}
73282527734SSukumar Swaminathan 
733fcf3ce44SJohn Forte 	return;
734fcf3ce44SJohn Forte 
735e2ca2865SSukumar Swaminathan } /* emlxs_fct_handle_unsol_flogi() */
736fcf3ce44SJohn Forte 
737fcf3ce44SJohn Forte 
738fcf3ce44SJohn Forte /* This is called at port online and offline */
739fcf3ce44SJohn Forte static void
740fcf3ce44SJohn Forte emlxs_fct_unsol_flush(emlxs_port_t *port)
741fcf3ce44SJohn Forte {
742fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
743fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
744fcf3ce44SJohn Forte 	emlxs_buf_t *next;
745fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
74682527734SSukumar Swaminathan 	fct_status_t rval;
747e2ca2865SSukumar Swaminathan 	uint32_t cmd_code;
748fcf3ce44SJohn Forte 
749fcf3ce44SJohn Forte 	if (!port->fct_port) {
750fcf3ce44SJohn Forte 		return;
751fcf3ce44SJohn Forte 	}
752291a2b48SSukumar Swaminathan 
753e2ca2865SSukumar Swaminathan 	/* First handle any pending FLOGI */
754e2ca2865SSukumar Swaminathan 	emlxs_fct_handle_unsol_flogi(port, NULL, 0);
755291a2b48SSukumar Swaminathan 
756e2ca2865SSukumar Swaminathan 	/* Wait queue */
757fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
758fcf3ce44SJohn Forte 	cmd_sbp = port->fct_wait_head;
759fcf3ce44SJohn Forte 	port->fct_wait_head = NULL;
760fcf3ce44SJohn Forte 	port->fct_wait_tail = NULL;
761fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
762fcf3ce44SJohn Forte 
763291a2b48SSukumar Swaminathan 	/*
764291a2b48SSukumar Swaminathan 	 * Next process any outstanding ELS commands. It doesn't
765291a2b48SSukumar Swaminathan 	 * matter if the Link is up or not, always post them to FCT.
766291a2b48SSukumar Swaminathan 	 */
767fcf3ce44SJohn Forte 	while (cmd_sbp) {
768fcf3ce44SJohn Forte 		next = cmd_sbp->next;
769fcf3ce44SJohn Forte 		fct_cmd = cmd_sbp->fct_cmd;
770fcf3ce44SJohn Forte 
771e2ca2865SSukumar Swaminathan 		cmd_code = (fct_cmd->cmd_oxid << ELS_CMD_SHIFT);
772e2ca2865SSukumar Swaminathan 
77382527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
77482527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
77582527734SSukumar Swaminathan 		if (rval) {
77682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
777e2ca2865SSukumar Swaminathan 			    "emlxs_fct_unsol_flush: %s: sid=%x xid=%x "
778e2ca2865SSukumar Swaminathan 			    "Unable to reacquire fct_cmd.",
779e2ca2865SSukumar Swaminathan 			    emlxs_elscmd_xlate(cmd_code),
780e2ca2865SSukumar Swaminathan 			    fct_cmd->cmd_rxid, fct_cmd->cmd_rportid);
78182527734SSukumar Swaminathan 
78282527734SSukumar Swaminathan 			cmd_sbp = next;
78382527734SSukumar Swaminathan 			continue;
78482527734SSukumar Swaminathan 		}
78582527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
78682527734SSukumar Swaminathan 
787291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
788e2ca2865SSukumar Swaminathan 		    "Completing %s: sid=%x xid=%x %p",
789e2ca2865SSukumar Swaminathan 		    emlxs_elscmd_xlate(cmd_code),
790e2ca2865SSukumar Swaminathan 		    fct_cmd->cmd_rportid, fct_cmd->cmd_rxid,
791e2ca2865SSukumar Swaminathan 		    fct_cmd);
792fcf3ce44SJohn Forte 
79382527734SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
79482527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
795fcf3ce44SJohn Forte 
796fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
797291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
798291a2b48SSukumar Swaminathan 		    "fct_post_rcvd_cmd:2 %p: portid x%x", fct_cmd,
799291a2b48SSukumar Swaminathan 		    fct_cmd->cmd_lportid);
800291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
80182527734SSukumar Swaminathan 
802291a2b48SSukumar Swaminathan 		MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
803fcf3ce44SJohn Forte 
804fcf3ce44SJohn Forte 		cmd_sbp = next;
805fcf3ce44SJohn Forte 
80682527734SSukumar Swaminathan 	}	/* while () */
807fcf3ce44SJohn Forte 
808fcf3ce44SJohn Forte 	return;
809fcf3ce44SJohn Forte 
81082527734SSukumar Swaminathan } /* emlxs_fct_unsol_flush() */
811fcf3ce44SJohn Forte 
812fcf3ce44SJohn Forte 
813fcf3ce44SJohn Forte int
814fcf3ce44SJohn Forte emlxs_is_digit(uint8_t chr)
815fcf3ce44SJohn Forte {
816fcf3ce44SJohn Forte 	if ((chr >= '0') && (chr <= '9')) {
817fcf3ce44SJohn Forte 		return (1);
818fcf3ce44SJohn Forte 	}
819291a2b48SSukumar Swaminathan 
820fcf3ce44SJohn Forte 	return (0);
821fcf3ce44SJohn Forte 
82282527734SSukumar Swaminathan } /* emlxs_is_digit */
823fcf3ce44SJohn Forte 
824fcf3ce44SJohn Forte 
825fcf3ce44SJohn Forte /*
826fcf3ce44SJohn Forte  *   Convert an ASCII decimal numeric string to integer.
827fcf3ce44SJohn Forte  *   Negation character '-' is not handled.
828fcf3ce44SJohn Forte  */
829fcf3ce44SJohn Forte uint32_t
830fcf3ce44SJohn Forte emlxs_str_atoi(uint8_t *string)
831fcf3ce44SJohn Forte {
832fcf3ce44SJohn Forte 	uint32_t num = 0;
833fcf3ce44SJohn Forte 	int i = 0;
834fcf3ce44SJohn Forte 
835fcf3ce44SJohn Forte 	while (string[i]) {
836fcf3ce44SJohn Forte 		if (!emlxs_is_digit(string[i])) {
837fcf3ce44SJohn Forte 			return (num);
838fcf3ce44SJohn Forte 		}
839291a2b48SSukumar Swaminathan 
840fcf3ce44SJohn Forte 		num = num * 10 + (string[i++] - '0');
841fcf3ce44SJohn Forte 	}
842fcf3ce44SJohn Forte 
843fcf3ce44SJohn Forte 	return (num);
844fcf3ce44SJohn Forte 
84582527734SSukumar Swaminathan } /* emlxs_str_atoi() */
846fcf3ce44SJohn Forte 
847fcf3ce44SJohn Forte 
848fcf3ce44SJohn Forte static void
849fcf3ce44SJohn Forte emlxs_init_fct_bufpool(emlxs_hba_t *hba, char **arrayp, uint32_t cnt)
850fcf3ce44SJohn Forte {
851fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
852fcf3ce44SJohn Forte 	uint8_t *datap;
853fcf3ce44SJohn Forte 	int i;
854291a2b48SSukumar Swaminathan 	int bck;
855291a2b48SSukumar Swaminathan 	int nbufs;
856291a2b48SSukumar Swaminathan 	int maxbufs;
857291a2b48SSukumar Swaminathan 	int size;
858fcf3ce44SJohn Forte 
859fcf3ce44SJohn Forte 	bzero((uint8_t *)port->dmem_bucket, sizeof (port->dmem_bucket));
860291a2b48SSukumar Swaminathan 	bck = 0;
861bce54adfSSukumar Swaminathan 
862bce54adfSSukumar Swaminathan 	if (!cnt || !arrayp) {
863bce54adfSSukumar Swaminathan 		goto done;
864bce54adfSSukumar Swaminathan 	}
865bce54adfSSukumar Swaminathan 
866fcf3ce44SJohn Forte 	for (i = 0; i < cnt; i++) {
867fcf3ce44SJohn Forte 		datap = (uint8_t *)arrayp[i];
868bce54adfSSukumar Swaminathan 		if (datap == 0) {
869fcf3ce44SJohn Forte 			break;
870bce54adfSSukumar Swaminathan 		}
871fcf3ce44SJohn Forte 
872bce54adfSSukumar Swaminathan 		while (*datap == ' ') {	/* Skip spaces */
873fcf3ce44SJohn Forte 			datap++;
874bce54adfSSukumar Swaminathan 		}
875fcf3ce44SJohn Forte 
876291a2b48SSukumar Swaminathan 		size = emlxs_str_atoi(datap);
877fcf3ce44SJohn Forte 
878bce54adfSSukumar Swaminathan 		while ((*datap != ':') && (*datap != 0)) {
879fcf3ce44SJohn Forte 			datap++;
880bce54adfSSukumar Swaminathan 		}
881bce54adfSSukumar Swaminathan 		if (*datap == ':') {	/* Skip past delimeter */
882fcf3ce44SJohn Forte 			datap++;
883bce54adfSSukumar Swaminathan 		}
884bce54adfSSukumar Swaminathan 		while (*datap == ' ') {	/* Skip spaces */
885fcf3ce44SJohn Forte 			datap++;
886bce54adfSSukumar Swaminathan 		}
887fcf3ce44SJohn Forte 
888291a2b48SSukumar Swaminathan 		nbufs = emlxs_str_atoi(datap);
889fcf3ce44SJohn Forte 
890fcf3ce44SJohn Forte 		/* Check for a bad entry */
891291a2b48SSukumar Swaminathan 		if (!size || !nbufs) {
892fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
893291a2b48SSukumar Swaminathan 			    "Bad fct-bufpool entry %d %d", size, nbufs);
894291a2b48SSukumar Swaminathan 
895291a2b48SSukumar Swaminathan 			port->dmem_bucket[bck].dmem_buf_size = 0;
896291a2b48SSukumar Swaminathan 			port->dmem_bucket[bck].dmem_nbufs = 0;
897291a2b48SSukumar Swaminathan 			size = 0;
898291a2b48SSukumar Swaminathan 			nbufs = 0;
899291a2b48SSukumar Swaminathan 		}
900291a2b48SSukumar Swaminathan 
901291a2b48SSukumar Swaminathan 		while (nbufs) {
902291a2b48SSukumar Swaminathan 			port->dmem_bucket[bck].dmem_buf_size = size;
903291a2b48SSukumar Swaminathan 			port->dmem_bucket[bck].dmem_nbufs = nbufs;
904291a2b48SSukumar Swaminathan 
905291a2b48SSukumar Swaminathan 			/*
906291a2b48SSukumar Swaminathan 			 * We are not going to try to allocate a chunk
907291a2b48SSukumar Swaminathan 			 * of memory > FCT_DMEM_MAX_BUF_SEGMENT
908291a2b48SSukumar Swaminathan 			 * to accomidate the buffer pool of the
909291a2b48SSukumar Swaminathan 			 * requested size.
910291a2b48SSukumar Swaminathan 			 */
911291a2b48SSukumar Swaminathan 			maxbufs = (FCT_DMEM_MAX_BUF_SEGMENT / size);
912fcf3ce44SJohn Forte 
913291a2b48SSukumar Swaminathan 			if (nbufs > maxbufs) {
914291a2b48SSukumar Swaminathan 				port->dmem_bucket[bck].dmem_nbufs = maxbufs;
915291a2b48SSukumar Swaminathan 				nbufs -= maxbufs;
916291a2b48SSukumar Swaminathan 				bck++;
917291a2b48SSukumar Swaminathan 				if (bck >= FCT_MAX_BUCKETS)
918291a2b48SSukumar Swaminathan 					break;
919291a2b48SSukumar Swaminathan 			} else {
920291a2b48SSukumar Swaminathan 				bck++;
921291a2b48SSukumar Swaminathan 				nbufs = 0;
922291a2b48SSukumar Swaminathan 			}
923fcf3ce44SJohn Forte 		}
924291a2b48SSukumar Swaminathan 
925291a2b48SSukumar Swaminathan 		if (bck >= FCT_MAX_BUCKETS) {
926291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
927291a2b48SSukumar Swaminathan 			    "fct-bufpool entry %d %d Exceeds available buckets",
928291a2b48SSukumar Swaminathan 			    size, nbufs);
929fcf3ce44SJohn Forte 			break;
930291a2b48SSukumar Swaminathan 		}
931fcf3ce44SJohn Forte 	}
932bce54adfSSukumar Swaminathan 
933bce54adfSSukumar Swaminathan done:
934bce54adfSSukumar Swaminathan 	/* If no entries found then use defaults */
935bce54adfSSukumar Swaminathan 	if (bck == 0) {
936bce54adfSSukumar Swaminathan 		port->dmem_bucket[0].dmem_buf_size = 512;
937bce54adfSSukumar Swaminathan 		port->dmem_bucket[0].dmem_nbufs = FCT_BUF_COUNT_512;
938bce54adfSSukumar Swaminathan 		port->dmem_bucket[1].dmem_buf_size = 8192;
939bce54adfSSukumar Swaminathan 		port->dmem_bucket[1].dmem_nbufs = FCT_BUF_COUNT_8K;
940bce54adfSSukumar Swaminathan 		port->dmem_bucket[2].dmem_buf_size = 65536;
941bce54adfSSukumar Swaminathan 		port->dmem_bucket[2].dmem_nbufs = FCT_BUF_COUNT_64K;
942bce54adfSSukumar Swaminathan 		port->dmem_bucket[3].dmem_buf_size = 131072;
943bce54adfSSukumar Swaminathan 		port->dmem_bucket[3].dmem_nbufs = FCT_BUF_COUNT_128K;
944bce54adfSSukumar Swaminathan 	}
945bce54adfSSukumar Swaminathan 
946bce54adfSSukumar Swaminathan } /* emlxs_init_fct_bufpool() */
947fcf3ce44SJohn Forte 
948fcf3ce44SJohn Forte 
949fcf3ce44SJohn Forte static void
950fcf3ce44SJohn Forte emlxs_fct_cfg_init(emlxs_hba_t *hba)
951fcf3ce44SJohn Forte {
952bce54adfSSukumar Swaminathan #ifdef FCT_IO_TRACE
953fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
954bce54adfSSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
955bce54adfSSukumar Swaminathan #endif /* FCT_IO_TRACE */
956fcf3ce44SJohn Forte 	char **arrayp;
957fcf3ce44SJohn Forte 	uint32_t cnt;
958fcf3ce44SJohn Forte 	char buf[32];
959bce54adfSSukumar Swaminathan 	uint32_t rval;
960fcf3ce44SJohn Forte 
961bce54adfSSukumar Swaminathan 	/* Check for the per adapter setting */
962bce54adfSSukumar Swaminathan 	(void) sprintf(buf, "%s%d-fct-bufpool", DRIVER_NAME, hba->ddiinst);
963fcf3ce44SJohn Forte 	cnt = 0;
964fcf3ce44SJohn Forte 	arrayp = NULL;
965bce54adfSSukumar Swaminathan 	rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
966fcf3ce44SJohn Forte 	    (DDI_PROP_DONTPASS), buf, &arrayp, &cnt);
967fcf3ce44SJohn Forte 
968bce54adfSSukumar Swaminathan 	if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
969bce54adfSSukumar Swaminathan 		/* Check for the global setting */
970bce54adfSSukumar Swaminathan 		cnt = 0;
971bce54adfSSukumar Swaminathan 		arrayp = NULL;
972bce54adfSSukumar Swaminathan 		rval =
973bce54adfSSukumar Swaminathan 		    ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
974fcf3ce44SJohn Forte 		    (DDI_PROP_DONTPASS), "fct-bufpool", &arrayp, &cnt);
975fcf3ce44SJohn Forte 
976bce54adfSSukumar Swaminathan 		if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
977bce54adfSSukumar Swaminathan 			cnt = 0;
978bce54adfSSukumar Swaminathan 			arrayp = NULL;
979fcf3ce44SJohn Forte 		}
980fcf3ce44SJohn Forte 	}
981291a2b48SSukumar Swaminathan 
982bce54adfSSukumar Swaminathan 	emlxs_init_fct_bufpool(hba, arrayp, cnt);
983291a2b48SSukumar Swaminathan 
984291a2b48SSukumar Swaminathan #ifdef FCT_IO_TRACE
985291a2b48SSukumar Swaminathan 	port->iotrace_cnt = 1024;
986291a2b48SSukumar Swaminathan 	port->iotrace_index = 0;
987bce54adfSSukumar Swaminathan 	if (cfg[CFG_FCT_QDEPTH].current) {
988bce54adfSSukumar Swaminathan 		port->iotrace_cnt = (2 * cfg[CFG_FCT_QDEPTH].current);
989bce54adfSSukumar Swaminathan 	}
990291a2b48SSukumar Swaminathan 	port->iotrace =
991291a2b48SSukumar Swaminathan 	    kmem_zalloc(port->iotrace_cnt * sizeof (emlxs_iotrace_t),
992291a2b48SSukumar Swaminathan 	    KM_SLEEP);
99382527734SSukumar Swaminathan 
994291a2b48SSukumar Swaminathan 	mutex_init(&port->iotrace_mtx, NULL, MUTEX_DRIVER,
995*a9800bebSGarrett D'Amore 	    DDI_INTR_PRI(hba->intr_arg));
996291a2b48SSukumar Swaminathan 	emlxs_iotrace = (uint8_t *)port->iotrace;
997291a2b48SSukumar Swaminathan 	emlxs_iotrace_cnt = port->iotrace_cnt;
998291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
999291a2b48SSukumar Swaminathan 	    "IOTRACE: init:%p cnt:%d", emlxs_iotrace, emlxs_iotrace_cnt);
1000291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1001291a2b48SSukumar Swaminathan 	    "FCT_ABORT_SUCCESS:%lx FCT_SUCCESS:%lx", FCT_ABORT_SUCCESS,
1002291a2b48SSukumar Swaminathan 	    FCT_SUCCESS);
1003291a2b48SSukumar Swaminathan #endif /* FCT_IO_TRACE */
1004bce54adfSSukumar Swaminathan 
1005fcf3ce44SJohn Forte 	return;
1006fcf3ce44SJohn Forte 
100782527734SSukumar Swaminathan } /* emlxs_fct_cfg_init() */
1008fcf3ce44SJohn Forte 
1009fcf3ce44SJohn Forte 
1010fcf3ce44SJohn Forte extern void
1011fcf3ce44SJohn Forte emlxs_fct_init(emlxs_hba_t *hba)
1012fcf3ce44SJohn Forte {
1013fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1014fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
1015fcf3ce44SJohn Forte 	emlxs_port_t *vport;
1016fcf3ce44SJohn Forte 	uint32_t i;
1017fcf3ce44SJohn Forte 
1018fcf3ce44SJohn Forte 	if (!hba->tgt_mode) {
1019fcf3ce44SJohn Forte 		return;
1020fcf3ce44SJohn Forte 	}
1021fcf3ce44SJohn Forte 
1022fcf3ce44SJohn Forte 	/* Check if COMSTAR is present */
1023fcf3ce44SJohn Forte 	if (((void *)MODSYM(stmf_alloc) == NULL) ||
1024291a2b48SSukumar Swaminathan 	    ((void *)MODSYM(fct_alloc) == NULL)) {
1025fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1026fcf3ce44SJohn Forte 		    "Comstar not present. Target mode disabled.");
1027fcf3ce44SJohn Forte 		goto failed;
1028fcf3ce44SJohn Forte 	}
1029291a2b48SSukumar Swaminathan 
1030fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1031fcf3ce44SJohn Forte 	    "Comstar present. Target mode enabled.");
1032fcf3ce44SJohn Forte 
1033fcf3ce44SJohn Forte 	if (cfg[CFG_NPIV_ENABLE].current) {
1034fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
1035fcf3ce44SJohn Forte 		    "enable-npiv: Not supported in target mode. Disabling.");
1036fcf3ce44SJohn Forte 
1037fcf3ce44SJohn Forte 		/* Temporary patch to disable npiv */
1038fcf3ce44SJohn Forte 		cfg[CFG_NPIV_ENABLE].current = 0;
1039fcf3ce44SJohn Forte 	}
1040fcf3ce44SJohn Forte 
1041fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
1042fcf3ce44SJohn Forte 	if (cfg[CFG_AUTH_ENABLE].current) {
1043fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
1044fcf3ce44SJohn Forte 		    "enable-auth: Not supported in target mode. Disabling.");
1045fcf3ce44SJohn Forte 
1046fcf3ce44SJohn Forte 		/* Temporary patch to disable auth */
1047fcf3ce44SJohn Forte 		cfg[CFG_AUTH_ENABLE].current = 0;
1048fcf3ce44SJohn Forte 	}
1049291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */
1050fcf3ce44SJohn Forte 
1051fcf3ce44SJohn Forte 	emlxs_fct_cfg_init(hba);
1052fcf3ce44SJohn Forte 	return;
1053fcf3ce44SJohn Forte 
1054fcf3ce44SJohn Forte failed:
1055fcf3ce44SJohn Forte 
1056fcf3ce44SJohn Forte 	hba->tgt_mode = 0;
1057fcf3ce44SJohn Forte 	for (i = 0; i < MAX_VPORTS; i++) {
1058fcf3ce44SJohn Forte 		vport = &VPORT(i);
1059fcf3ce44SJohn Forte 		vport->tgt_mode = 0;
1060fcf3ce44SJohn Forte 		vport->fct_flags = 0;
1061fcf3ce44SJohn Forte 	}
1062291a2b48SSukumar Swaminathan 
1063291a2b48SSukumar Swaminathan 	return;
1064291a2b48SSukumar Swaminathan 
106582527734SSukumar Swaminathan } /* emlxs_fct_init() */
1066fcf3ce44SJohn Forte 
1067fcf3ce44SJohn Forte 
1068fcf3ce44SJohn Forte extern void
1069fcf3ce44SJohn Forte emlxs_fct_attach(emlxs_hba_t *hba)
1070fcf3ce44SJohn Forte {
1071fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1072fcf3ce44SJohn Forte 	uint32_t vpi;
1073fcf3ce44SJohn Forte 
1074fcf3ce44SJohn Forte 	if (!hba->tgt_mode) {
1075fcf3ce44SJohn Forte 		return;
1076fcf3ce44SJohn Forte 	}
1077291a2b48SSukumar Swaminathan 
1078fcf3ce44SJohn Forte 	/* Bind the physical port */
1079fcf3ce44SJohn Forte 	emlxs_fct_bind_port(port);
1080fcf3ce44SJohn Forte 
1081fcf3ce44SJohn Forte 	/* Bind virtual ports */
1082fcf3ce44SJohn Forte 	if (hba->flag & FC_NPIV_ENABLED) {
108382527734SSukumar Swaminathan 		for (vpi = 1; vpi <= hba->vpi_high; vpi++) {
1084fcf3ce44SJohn Forte 			port = &VPORT(vpi);
1085fcf3ce44SJohn Forte 
1086fcf3ce44SJohn Forte 			if (!(port->flag & EMLXS_PORT_ENABLE)) {
1087fcf3ce44SJohn Forte 				continue;
1088fcf3ce44SJohn Forte 			}
1089291a2b48SSukumar Swaminathan 
1090fcf3ce44SJohn Forte 			emlxs_fct_bind_port(port);
1091fcf3ce44SJohn Forte 		}
1092fcf3ce44SJohn Forte 	}
1093291a2b48SSukumar Swaminathan 
1094fcf3ce44SJohn Forte 	return;
1095fcf3ce44SJohn Forte 
109682527734SSukumar Swaminathan } /* emlxs_fct_attach() */
1097fcf3ce44SJohn Forte 
1098fcf3ce44SJohn Forte 
1099fcf3ce44SJohn Forte extern void
1100fcf3ce44SJohn Forte emlxs_fct_detach(emlxs_hba_t *hba)
1101fcf3ce44SJohn Forte {
1102fcf3ce44SJohn Forte 	uint32_t i;
1103fcf3ce44SJohn Forte 	emlxs_port_t *vport;
1104fcf3ce44SJohn Forte 
1105fcf3ce44SJohn Forte 	if (hba->tgt_mode) {
1106fcf3ce44SJohn Forte 		for (i = 0; i < MAX_VPORTS; i++) {
1107fcf3ce44SJohn Forte 			vport = &VPORT(i);
1108fcf3ce44SJohn Forte 
1109fcf3ce44SJohn Forte 			if (!vport->tgt_mode) {
1110fcf3ce44SJohn Forte 				continue;
1111fcf3ce44SJohn Forte 			}
1112291a2b48SSukumar Swaminathan 
1113fcf3ce44SJohn Forte 			emlxs_fct_unbind_port(vport);
1114fcf3ce44SJohn Forte 			vport->tgt_mode = 0;
1115fcf3ce44SJohn Forte 		}
1116fcf3ce44SJohn Forte 
1117fcf3ce44SJohn Forte 
1118fcf3ce44SJohn Forte 		hba->tgt_mode = 0;
1119fcf3ce44SJohn Forte 	}
1120291a2b48SSukumar Swaminathan #ifdef FCT_IO_TRACE
1121291a2b48SSukumar Swaminathan 	{
1122291a2b48SSukumar Swaminathan 		emlxs_port_t *port = &PPORT;
1123291a2b48SSukumar Swaminathan 
1124291a2b48SSukumar Swaminathan 		mutex_destroy(&port->iotrace_mtx);
1125291a2b48SSukumar Swaminathan 		if (port->iotrace)
1126291a2b48SSukumar Swaminathan 			kmem_free(port->iotrace,
1127291a2b48SSukumar Swaminathan 			    (port->iotrace_cnt * sizeof (emlxs_iotrace_t)));
1128291a2b48SSukumar Swaminathan 		port->iotrace = NULL;
1129291a2b48SSukumar Swaminathan 	}
1130291a2b48SSukumar Swaminathan #endif /* FCT_IO_TRACE */
1131291a2b48SSukumar Swaminathan 
1132fcf3ce44SJohn Forte 	return;
1133fcf3ce44SJohn Forte 
113482527734SSukumar Swaminathan } /* emlxs_fct_detach() */
1135fcf3ce44SJohn Forte 
1136fcf3ce44SJohn Forte 
1137fcf3ce44SJohn Forte extern void
1138fcf3ce44SJohn Forte emlxs_fct_unbind_port(emlxs_port_t *port)
1139fcf3ce44SJohn Forte {
1140fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1141fcf3ce44SJohn Forte 	char node_name[32];
1142fcf3ce44SJohn Forte 
1143fcf3ce44SJohn Forte 	if (!port->tgt_mode) {
1144fcf3ce44SJohn Forte 		return;
1145fcf3ce44SJohn Forte 	}
1146291a2b48SSukumar Swaminathan 
1147fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
1148fcf3ce44SJohn Forte 	if (!(port->flag & EMLXS_PORT_BOUND)) {
1149fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1150fcf3ce44SJohn Forte 		return;
1151fcf3ce44SJohn Forte 	}
1152291a2b48SSukumar Swaminathan 
1153fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1154fcf3ce44SJohn Forte 	    "emlxs_fct_unbind_port: port=%d", port->vpi);
1155fcf3ce44SJohn Forte 
1156fcf3ce44SJohn Forte 	/* Destroy & flush all port nodes, if they exist */
1157fcf3ce44SJohn Forte 	if (port->node_count) {
1158*a9800bebSGarrett D'Amore 		(void) emlxs_mb_unreg_node(port, NULL, NULL, NULL, NULL);
1159fcf3ce44SJohn Forte 	}
1160291a2b48SSukumar Swaminathan 
1161fcf3ce44SJohn Forte 	port->flag &= ~EMLXS_PORT_BOUND;
1162fcf3ce44SJohn Forte 	hba->num_of_ports--;
1163fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
1164fcf3ce44SJohn Forte 
1165fcf3ce44SJohn Forte 	if (port->fct_port) {
1166fcf3ce44SJohn Forte 		emlxs_fct_link_down(port);
1167fcf3ce44SJohn Forte 		emlxs_fct_unsol_flush(port);
1168fcf3ce44SJohn Forte 
1169fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1170fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1171fcf3ce44SJohn Forte 		    "fct_deregister_local_port %p", port->fct_port);
1172291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1173fcf3ce44SJohn Forte 		MODSYM(fct_deregister_local_port) (port->fct_port);
1174fcf3ce44SJohn Forte 
1175fcf3ce44SJohn Forte 		if (port->fct_port->port_fds) {
1176fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1177fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1178fcf3ce44SJohn Forte 			    "fct_free:3 %p", port->fct_port->port_fds);
1179291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1180fcf3ce44SJohn Forte 			MODSYM(fct_free) (port->fct_port->port_fds);
1181fcf3ce44SJohn Forte 			port->fct_port->port_fds = NULL;
1182fcf3ce44SJohn Forte 		}
1183fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1184fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1185fcf3ce44SJohn Forte 		    "fct_free:4 %p", port->fct_port);
1186291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1187fcf3ce44SJohn Forte 		MODSYM(fct_free) (port->fct_port);
1188fcf3ce44SJohn Forte 		port->fct_port = NULL;
1189fcf3ce44SJohn Forte 		port->fct_flags = 0;
1190fcf3ce44SJohn Forte 	}
1191291a2b48SSukumar Swaminathan 
1192fcf3ce44SJohn Forte 	if (port->port_provider) {
1193fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1194fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1195291a2b48SSukumar Swaminathan 		    "stmf_deregister_port_provider:1 %p",
1196291a2b48SSukumar Swaminathan 		    port->port_provider);
1197291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1198fcf3ce44SJohn Forte 		MODSYM(stmf_deregister_port_provider) (port->port_provider);
1199fcf3ce44SJohn Forte 
1200fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1201fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1202fcf3ce44SJohn Forte 		    "stmf_free:1 %p", port->port_provider);
1203291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1204fcf3ce44SJohn Forte 		MODSYM(stmf_free) (port->port_provider);
1205fcf3ce44SJohn Forte 		port->port_provider = NULL;
1206fcf3ce44SJohn Forte 	}
1207291a2b48SSukumar Swaminathan 
1208fcf3ce44SJohn Forte 	if (port->dmem_bucket) {
1209fcf3ce44SJohn Forte 		emlxs_fct_dmem_fini(port);
1210fcf3ce44SJohn Forte 	}
1211291a2b48SSukumar Swaminathan 
1212fcf3ce44SJohn Forte 	(void) sprintf(node_name, "%d,%d:SFCT", hba->ddiinst, port->vpi);
1213fcf3ce44SJohn Forte 	(void) ddi_remove_minor_node(hba->dip, node_name);
1214fcf3ce44SJohn Forte 
1215fcf3ce44SJohn Forte 	return;
1216fcf3ce44SJohn Forte 
121782527734SSukumar Swaminathan } /* emlxs_fct_unbind_port() */
1218fcf3ce44SJohn Forte 
1219fcf3ce44SJohn Forte 
1220fcf3ce44SJohn Forte extern void
1221fcf3ce44SJohn Forte emlxs_fct_bind_port(emlxs_port_t *port)
1222fcf3ce44SJohn Forte {
1223fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1224fcf3ce44SJohn Forte 	fct_local_port_t *fct_port;
1225fcf3ce44SJohn Forte 	uint32_t flag = 0;
1226fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
1227fcf3ce44SJohn Forte 	fct_dbuf_store_t *fds;
1228fcf3ce44SJohn Forte 	char node_name[32];
122982527734SSukumar Swaminathan 	uint8_t *bptr;
1230fcf3ce44SJohn Forte 
1231fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
1232fcf3ce44SJohn Forte 
1233fcf3ce44SJohn Forte 	if (!hba->tgt_mode || !port->tgt_mode) {
1234fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1235fcf3ce44SJohn Forte 		return;
1236fcf3ce44SJohn Forte 	}
1237291a2b48SSukumar Swaminathan 
1238fcf3ce44SJohn Forte 	if (port->flag & EMLXS_PORT_BOUND) {
1239fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1240fcf3ce44SJohn Forte 		return;
1241fcf3ce44SJohn Forte 	}
1242291a2b48SSukumar Swaminathan 
1243fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1244fcf3ce44SJohn Forte 	    "emlxs_fct_bind_port: port=%d", port->vpi);
1245fcf3ce44SJohn Forte 
1246fcf3ce44SJohn Forte 	/* Perform generic port initialization */
1247fcf3ce44SJohn Forte 	emlxs_port_init(port);
1248fcf3ce44SJohn Forte 
1249fcf3ce44SJohn Forte 	if (port->vpi == 0) {
1250fcf3ce44SJohn Forte 		(void) sprintf(port->cfd_name, "%s%d", DRIVER_NAME,
1251fcf3ce44SJohn Forte 		    hba->ddiinst);
1252fcf3ce44SJohn Forte 	} else {
1253fcf3ce44SJohn Forte 		(void) sprintf(port->cfd_name, "%s%d.%d", DRIVER_NAME,
1254fcf3ce44SJohn Forte 		    hba->ddiinst, port->vpi);
1255fcf3ce44SJohn Forte 	}
1256fcf3ce44SJohn Forte 
1257fcf3ce44SJohn Forte 	if (emlxs_fct_dmem_init(port) != FCT_SUCCESS) {
1258fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1259fcf3ce44SJohn Forte 		    "emlxs_fct_bind_port: Unable to allocate fct memory.");
1260fcf3ce44SJohn Forte 		goto failed;
1261fcf3ce44SJohn Forte 	}
1262fcf3ce44SJohn Forte 	flag |= 0x00000001;
1263fcf3ce44SJohn Forte 
1264291a2b48SSukumar Swaminathan 	port->port_provider =
1265291a2b48SSukumar Swaminathan 	    (stmf_port_provider_t *)
1266fcf3ce44SJohn Forte 	    MODSYM(stmf_alloc) (STMF_STRUCT_PORT_PROVIDER, 0, 0);
1267fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1268fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1269fcf3ce44SJohn Forte 	    "stmf_alloc port_provider %p", port->port_provider);
1270291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1271fcf3ce44SJohn Forte 
1272fcf3ce44SJohn Forte 	if (port->port_provider == NULL) {
1273fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1274291a2b48SSukumar Swaminathan 		    "emlxs_fct_bind_port: Unable to allocate port provider.");
1275fcf3ce44SJohn Forte 		goto failed;
1276fcf3ce44SJohn Forte 	}
1277fcf3ce44SJohn Forte 	flag |= 0x00000002;
1278fcf3ce44SJohn Forte 
1279fcf3ce44SJohn Forte 	port->port_provider->pp_portif_rev = PORTIF_REV_1;
1280fcf3ce44SJohn Forte 	port->port_provider->pp_name = port->cfd_name;
1281fcf3ce44SJohn Forte 	port->port_provider->pp_provider_private = port;
1282fcf3ce44SJohn Forte 
1283fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1284fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1285fcf3ce44SJohn Forte 	    "stmf_register_port_provider %p", port->port_provider);
1286291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1287fcf3ce44SJohn Forte 	/* register port provider with framework */
1288291a2b48SSukumar Swaminathan 	if (MODSYM(stmf_register_port_provider) (port->port_provider) !=
1289291a2b48SSukumar Swaminathan 	    STMF_SUCCESS) {
1290fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1291291a2b48SSukumar Swaminathan 		    "emlxs_fct_bind_port: Unable to register port provider.");
1292fcf3ce44SJohn Forte 		goto failed;
1293fcf3ce44SJohn Forte 	}
1294fcf3ce44SJohn Forte 	flag |= 0x00000004;
1295fcf3ce44SJohn Forte 
1296291a2b48SSukumar Swaminathan 	port->fct_port =
1297291a2b48SSukumar Swaminathan 	    (fct_local_port_t *)MODSYM(fct_alloc) (FCT_STRUCT_LOCAL_PORT, 0,
1298291a2b48SSukumar Swaminathan 	    0);
1299fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1300fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1301fcf3ce44SJohn Forte 	    "fct_alloc fct_port %p", port->fct_port);
1302291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1303fcf3ce44SJohn Forte 
1304fcf3ce44SJohn Forte 	if (port->fct_port == NULL) {
1305fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1306fcf3ce44SJohn Forte 		    "emlxs_fct_bind_port: Unable to allocate fct port.");
1307fcf3ce44SJohn Forte 		goto failed;
1308fcf3ce44SJohn Forte 	}
1309fcf3ce44SJohn Forte 	flag |= 0x00000008;
1310fcf3ce44SJohn Forte 
1311291a2b48SSukumar Swaminathan 	port->fct_port->port_fds =
1312291a2b48SSukumar Swaminathan 	    (fct_dbuf_store_t *)MODSYM(fct_alloc) (FCT_STRUCT_DBUF_STORE, 0,
1313291a2b48SSukumar Swaminathan 	    0);
1314fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1315fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1316fcf3ce44SJohn Forte 	    "fct_alloc port_fds %p", port->fct_port->port_fds);
1317291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1318fcf3ce44SJohn Forte 
1319fcf3ce44SJohn Forte 	if (port->fct_port->port_fds == NULL) {
1320fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1321fcf3ce44SJohn Forte 		    "emlxs_fct_bind_port: Unable to allocate dbuf store.");
1322fcf3ce44SJohn Forte 		goto failed;
1323fcf3ce44SJohn Forte 	}
1324fcf3ce44SJohn Forte 	flag |= 0x00000010;
1325fcf3ce44SJohn Forte 
1326fcf3ce44SJohn Forte 	(void) sprintf(node_name, "%d,%d:SFCT", hba->ddiinst, port->vpi);
1327291a2b48SSukumar Swaminathan 	if (ddi_create_minor_node(hba->dip, node_name, S_IFCHR, hba->ddiinst,
1328291a2b48SSukumar Swaminathan 	    NULL, 0) == DDI_FAILURE) {
1329fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1330fcf3ce44SJohn Forte 		    "Unable to create SFCT device node.");
1331fcf3ce44SJohn Forte 		goto failed;
1332fcf3ce44SJohn Forte 	}
1333fcf3ce44SJohn Forte 	flag |= 0x00000020;
1334fcf3ce44SJohn Forte 
1335fcf3ce44SJohn Forte 	/* Intialize */
1336fcf3ce44SJohn Forte 	fct_port = port->fct_port;
1337162fafd3Sallan 	fct_port->port_fca_version = FCT_FCA_MODREV_1;
1338fcf3ce44SJohn Forte 	fct_port->port_fca_private = port;
1339fcf3ce44SJohn Forte 	fct_port->port_fca_abort_timeout = 30 * 1000;	/* 30 seconds */
1340fcf3ce44SJohn Forte 
1341fcf3ce44SJohn Forte 	bcopy((uint8_t *)&port->wwpn, (uint8_t *)fct_port->port_pwwn, 8);
1342fcf3ce44SJohn Forte 	bcopy((uint8_t *)&port->wwnn, (uint8_t *)fct_port->port_nwwn, 8);
1343fcf3ce44SJohn Forte 
134482527734SSukumar Swaminathan 	bptr = (uint8_t *)&port->wwnn;
134582527734SSukumar Swaminathan 	(void) sprintf(fct_port->port_nwwn_str,
134682527734SSukumar Swaminathan 	    "%02x%02x%02x%02x%02x%02x%02x%02x",
134782527734SSukumar Swaminathan 	    bptr[0], bptr[1], bptr[2], bptr[3],
134882527734SSukumar Swaminathan 	    bptr[4], bptr[5], bptr[6], bptr[7]);
134982527734SSukumar Swaminathan 
135082527734SSukumar Swaminathan 	bptr = (uint8_t *)&port->wwpn;
135182527734SSukumar Swaminathan 	(void) sprintf(fct_port->port_pwwn_str,
135282527734SSukumar Swaminathan 	    "%02x%02x%02x%02x%02x%02x%02x%02x",
135382527734SSukumar Swaminathan 	    bptr[0], bptr[1], bptr[2], bptr[3],
135482527734SSukumar Swaminathan 	    bptr[4], bptr[5], bptr[6], bptr[7]);
135582527734SSukumar Swaminathan 
1356fcf3ce44SJohn Forte 	fct_port->port_sym_node_name = port->snn;
1357fcf3ce44SJohn Forte 	fct_port->port_sym_port_name = port->spn;
1358fcf3ce44SJohn Forte 	fct_port->port_hard_address = cfg[CFG_ASSIGN_ALPA].current;
1359fcf3ce44SJohn Forte 	fct_port->port_default_alias = port->cfd_name;
1360fcf3ce44SJohn Forte 	fct_port->port_pp = port->port_provider;
1361fcf3ce44SJohn Forte 	fct_port->port_max_logins = hba->max_nodes;
1362fcf3ce44SJohn Forte 
1363bce54adfSSukumar Swaminathan 	if (cfg[CFG_FCT_QDEPTH].current &&
1364bce54adfSSukumar Swaminathan 	    (cfg[CFG_FCT_QDEPTH].current < hba->io_throttle)) {
1365bce54adfSSukumar Swaminathan 		fct_port->port_max_xchges = cfg[CFG_FCT_QDEPTH].current;
1366fcf3ce44SJohn Forte 	} else {
1367fcf3ce44SJohn Forte 		fct_port->port_max_xchges = hba->io_throttle;
1368fcf3ce44SJohn Forte 	}
1369fcf3ce44SJohn Forte 
1370fcf3ce44SJohn Forte 	fct_port->port_fca_fcp_cmd_size = sizeof (emlxs_buf_t);
1371fcf3ce44SJohn Forte 	fct_port->port_fca_rp_private_size = sizeof (uintptr_t);
1372fcf3ce44SJohn Forte 	fct_port->port_fca_sol_els_private_size = sizeof (emlxs_buf_t);
1373fcf3ce44SJohn Forte 	fct_port->port_fca_sol_ct_private_size = sizeof (emlxs_buf_t);
1374fcf3ce44SJohn Forte 	fct_port->port_get_link_info = emlxs_fct_get_link_info;
1375fcf3ce44SJohn Forte 	fct_port->port_register_remote_port = emlxs_fct_register_remote_port;
1376fcf3ce44SJohn Forte 	fct_port->port_deregister_remote_port =
1377fcf3ce44SJohn Forte 	    emlxs_fct_deregister_remote_port;
1378fcf3ce44SJohn Forte 	fct_port->port_send_cmd = emlxs_fct_send_cmd;
1379fcf3ce44SJohn Forte 	fct_port->port_xfer_scsi_data = emlxs_fct_send_fcp_data;
1380fcf3ce44SJohn Forte 	fct_port->port_send_cmd_response = emlxs_fct_send_cmd_rsp;
1381fcf3ce44SJohn Forte 	fct_port->port_abort_cmd = emlxs_fct_abort;
1382fcf3ce44SJohn Forte 	fct_port->port_ctl = emlxs_fct_ctl;
138382527734SSukumar Swaminathan 	fct_port->port_flogi_xchg = emlxs_fct_flogi_xchg;
138482527734SSukumar Swaminathan 	fct_port->port_populate_hba_details = emlxs_fct_populate_hba_details;
138582527734SSukumar Swaminathan 	fct_port->port_info = emlxs_fct_port_info;
1386fcf3ce44SJohn Forte 
1387fcf3ce44SJohn Forte 	fds = port->fct_port->port_fds;
1388fcf3ce44SJohn Forte 	fds->fds_fca_private = port;
1389fcf3ce44SJohn Forte 	fds->fds_alloc_data_buf = emlxs_fct_dbuf_alloc;
1390fcf3ce44SJohn Forte 	fds->fds_free_data_buf = emlxs_fct_dbuf_free;
1391fcf3ce44SJohn Forte 
1392fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1393fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1394fcf3ce44SJohn Forte 	    "fct_register_local_port %p", fct_port);
1395291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1396fcf3ce44SJohn Forte 	/* register this local port with the fct module */
1397fcf3ce44SJohn Forte 	if (MODSYM(fct_register_local_port) (fct_port) != FCT_SUCCESS) {
1398fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1399fcf3ce44SJohn Forte 		    "emlxs_fct_bind_port: Unable to register fct port.");
1400fcf3ce44SJohn Forte 		goto failed;
1401fcf3ce44SJohn Forte 	}
1402291a2b48SSukumar Swaminathan 
1403fcf3ce44SJohn Forte 	/* Set the bound flag */
1404fcf3ce44SJohn Forte 	port->flag |= EMLXS_PORT_BOUND;
1405fcf3ce44SJohn Forte 	hba->num_of_ports++;
1406fcf3ce44SJohn Forte 
1407fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
1408fcf3ce44SJohn Forte 
1409fcf3ce44SJohn Forte 	return;
1410fcf3ce44SJohn Forte 
1411fcf3ce44SJohn Forte failed:
1412fcf3ce44SJohn Forte 
1413fcf3ce44SJohn Forte 	if (flag & 0x20) {
1414fcf3ce44SJohn Forte 		(void) ddi_remove_minor_node(hba->dip, node_name);
1415fcf3ce44SJohn Forte 	}
1416291a2b48SSukumar Swaminathan 
1417fcf3ce44SJohn Forte 	if (flag & 0x10) {
1418fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1419fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1420fcf3ce44SJohn Forte 		    "fct_free:5 %p", port->fct_port->port_fds);
1421291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1422fcf3ce44SJohn Forte 		MODSYM(fct_free) (port->fct_port->port_fds);
1423fcf3ce44SJohn Forte 		port->fct_port->port_fds = NULL;
1424fcf3ce44SJohn Forte 	}
1425291a2b48SSukumar Swaminathan 
1426fcf3ce44SJohn Forte 	if (flag & 0x8) {
1427fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1428fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1429fcf3ce44SJohn Forte 		    "fct_free:6 %p", port->fct_port);
1430291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1431fcf3ce44SJohn Forte 		MODSYM(fct_free) (port->fct_port);
1432fcf3ce44SJohn Forte 		port->fct_port = NULL;
1433fcf3ce44SJohn Forte 		port->fct_flags = 0;
1434fcf3ce44SJohn Forte 	}
1435291a2b48SSukumar Swaminathan 
1436fcf3ce44SJohn Forte 	if (flag & 0x4) {
1437fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1438fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1439291a2b48SSukumar Swaminathan 		    "stmf_deregister_port_provider:2 %p",
1440291a2b48SSukumar Swaminathan 		    port->port_provider);
1441291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1442fcf3ce44SJohn Forte 		MODSYM(stmf_deregister_port_provider) (port->port_provider);
1443fcf3ce44SJohn Forte 	}
1444291a2b48SSukumar Swaminathan 
1445fcf3ce44SJohn Forte 	if (flag & 0x2) {
1446fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1447fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1448fcf3ce44SJohn Forte 		    "stmf_free:2 %p", port->port_provider);
1449291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1450fcf3ce44SJohn Forte 		MODSYM(stmf_free) (port->port_provider);
1451fcf3ce44SJohn Forte 		port->port_provider = NULL;
1452fcf3ce44SJohn Forte 	}
1453291a2b48SSukumar Swaminathan 
1454fcf3ce44SJohn Forte 	if (flag & 0x1) {
1455fcf3ce44SJohn Forte 		emlxs_fct_dmem_fini(port);
1456fcf3ce44SJohn Forte 	}
1457291a2b48SSukumar Swaminathan 
1458fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1459fcf3ce44SJohn Forte 	    "Target mode disabled.");
1460fcf3ce44SJohn Forte 
1461fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
1462fcf3ce44SJohn Forte 
1463fcf3ce44SJohn Forte 	return;
1464fcf3ce44SJohn Forte 
146582527734SSukumar Swaminathan } /* emlxs_fct_bind_port() */
146682527734SSukumar Swaminathan 
146782527734SSukumar Swaminathan 
146882527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
146982527734SSukumar Swaminathan /*ARGSUSED*/
147082527734SSukumar Swaminathan static fct_status_t
147182527734SSukumar Swaminathan emlxs_fct_port_info(uint32_t cmd, fct_local_port_t *fct_port, void *arg,
147282527734SSukumar Swaminathan     uint8_t *buffer, uint32_t *size)
147382527734SSukumar Swaminathan {
147482527734SSukumar Swaminathan 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
147582527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
147682527734SSukumar Swaminathan 	fct_status_t rval = FCT_SUCCESS;
147782527734SSukumar Swaminathan 	fct_port_link_status_t *link_status;
147882527734SSukumar Swaminathan 	MAILBOX *mb;
147982527734SSukumar Swaminathan 	MAILBOXQ *mbq;
148082527734SSukumar Swaminathan 
148182527734SSukumar Swaminathan 	switch (cmd) {
148282527734SSukumar Swaminathan 	case FC_TGT_PORT_RLS:
148382527734SSukumar Swaminathan 		bzero(buffer, *size);
148482527734SSukumar Swaminathan 
148582527734SSukumar Swaminathan 		if ((*size) < sizeof (fct_port_link_status_t)) {
148682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
148782527734SSukumar Swaminathan 			    "FC_TGT_PORT_RLS: Buffer too small. %d < %d",
148882527734SSukumar Swaminathan 			    *size, sizeof (fct_port_link_status_t));
148982527734SSukumar Swaminathan 
149082527734SSukumar Swaminathan 			rval = FCT_FAILURE;
149182527734SSukumar Swaminathan 			break;
149282527734SSukumar Swaminathan 		}
149382527734SSukumar Swaminathan 
149482527734SSukumar Swaminathan 		if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) {
149582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
149682527734SSukumar Swaminathan 			    "FC_TGT_PORT_RLS: Unable to allocate mailbox.");
149782527734SSukumar Swaminathan 
149882527734SSukumar Swaminathan 			rval = FCT_ALLOC_FAILURE;
149982527734SSukumar Swaminathan 			break;
150082527734SSukumar Swaminathan 		}
150182527734SSukumar Swaminathan 		mb = (MAILBOX *)mbq;
150282527734SSukumar Swaminathan 
150382527734SSukumar Swaminathan 		emlxs_mb_read_lnk_stat(hba, mbq);
150482527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0)
150582527734SSukumar Swaminathan 		    != MBX_SUCCESS) {
150682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
150782527734SSukumar Swaminathan 			    "FC_TGT_PORT_RLS: Unable to send request.");
150882527734SSukumar Swaminathan 
150982527734SSukumar Swaminathan 			rval = FCT_BUSY;
151082527734SSukumar Swaminathan 		} else {
151182527734SSukumar Swaminathan 			link_status = (fct_port_link_status_t *)buffer;
151282527734SSukumar Swaminathan 			link_status->LinkFailureCount =
151382527734SSukumar Swaminathan 			    mb->un.varRdLnk.linkFailureCnt;
151482527734SSukumar Swaminathan 			link_status->LossOfSyncCount =
151582527734SSukumar Swaminathan 			    mb->un.varRdLnk.lossSyncCnt;
151682527734SSukumar Swaminathan 			link_status->LossOfSignalsCount =
151782527734SSukumar Swaminathan 			    mb->un.varRdLnk.lossSignalCnt;
151882527734SSukumar Swaminathan 			link_status->PrimitiveSeqProtocolErrorCount =
151982527734SSukumar Swaminathan 			    mb->un.varRdLnk.primSeqErrCnt;
152082527734SSukumar Swaminathan 			link_status->InvalidTransmissionWordCount =
152182527734SSukumar Swaminathan 			    mb->un.varRdLnk.invalidXmitWord;
152282527734SSukumar Swaminathan 			link_status->InvalidCRCCount =
152382527734SSukumar Swaminathan 			    mb->un.varRdLnk.crcCnt;
152482527734SSukumar Swaminathan 		}
152582527734SSukumar Swaminathan 
1526*a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
152782527734SSukumar Swaminathan 		break;
152882527734SSukumar Swaminathan 
152982527734SSukumar Swaminathan 	default:
153082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
153182527734SSukumar Swaminathan 		    "emlxs_fct_port_info: Invalid request. cmd=%x",
153282527734SSukumar Swaminathan 		    cmd);
153382527734SSukumar Swaminathan 
153482527734SSukumar Swaminathan 		rval = FCT_FAILURE;
153582527734SSukumar Swaminathan 		break;
153682527734SSukumar Swaminathan 
153782527734SSukumar Swaminathan 	}
1538fcf3ce44SJohn Forte 
153982527734SSukumar Swaminathan 	return (rval);
154082527734SSukumar Swaminathan 
154182527734SSukumar Swaminathan } /* emlxs_fct_port_info() */
1542fcf3ce44SJohn Forte 
154382527734SSukumar Swaminathan 
154482527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1545fcf3ce44SJohn Forte static void
154682527734SSukumar Swaminathan emlxs_fct_populate_hba_details(fct_local_port_t *fct_port,
1547fcf3ce44SJohn Forte     fct_port_attrs_t *port_attrs)
1548fcf3ce44SJohn Forte {
1549fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1550fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1551fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd = &VPD;
1552fcf3ce44SJohn Forte 
1553fcf3ce44SJohn Forte 	(void) strcpy(port_attrs->manufacturer, "Emulex");
1554fcf3ce44SJohn Forte 	(void) strcpy(port_attrs->serial_number, vpd->serial_num);
1555fcf3ce44SJohn Forte 	(void) strcpy(port_attrs->model, hba->model_info.model);
1556fcf3ce44SJohn Forte 	(void) strcpy(port_attrs->model_description,
1557fcf3ce44SJohn Forte 	    hba->model_info.model_desc);
1558fcf3ce44SJohn Forte 	(void) sprintf(port_attrs->hardware_version, "%x", vpd->biuRev);
1559fcf3ce44SJohn Forte 	(void) sprintf(port_attrs->driver_version, "%s (%s)", emlxs_version,
1560fcf3ce44SJohn Forte 	    emlxs_revision);
1561fcf3ce44SJohn Forte 	(void) strcpy(port_attrs->option_rom_version, vpd->fcode_version);
1562fcf3ce44SJohn Forte 	(void) sprintf(port_attrs->firmware_version, "%s (%s)", vpd->fw_version,
1563fcf3ce44SJohn Forte 	    vpd->fw_label);
1564fcf3ce44SJohn Forte 	(void) strcpy(port_attrs->driver_name, DRIVER_NAME);
1565fcf3ce44SJohn Forte 	port_attrs->vendor_specific_id =
1566fcf3ce44SJohn Forte 	    ((hba->model_info.device_id << 16) | PCI_VENDOR_ID_EMULEX);
156782527734SSukumar Swaminathan 	port_attrs->supported_cos = LE_SWAP32(FC_NS_CLASS3);
1568fcf3ce44SJohn Forte 
1569fcf3ce44SJohn Forte 	port_attrs->max_frame_size = FF_FRAME_SIZE;
1570fcf3ce44SJohn Forte 
1571fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
1572291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_10G;
1573fcf3ce44SJohn Forte 	}
1574fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
1575291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_8G;
1576fcf3ce44SJohn Forte 	}
1577fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
1578291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_4G;
1579fcf3ce44SJohn Forte 	}
1580fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
1581291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_2G;
1582fcf3ce44SJohn Forte 	}
1583fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
1584291a2b48SSukumar Swaminathan 		port_attrs->supported_speed |= PORT_SPEED_1G;
1585fcf3ce44SJohn Forte 	}
1586291a2b48SSukumar Swaminathan 
1587fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1588fcf3ce44SJohn Forte 	    "Port attr: manufacturer       = %s", port_attrs->manufacturer);
1589fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1590fcf3ce44SJohn Forte 	    "Port attr: serial_num         = %s", port_attrs->serial_number);
1591fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1592fcf3ce44SJohn Forte 	    "Port attr: model              = %s", port_attrs->model);
1593fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1594fcf3ce44SJohn Forte 	    "Port attr: model_description  = %s",
1595fcf3ce44SJohn Forte 	    port_attrs->model_description);
1596fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1597291a2b48SSukumar Swaminathan 	    "Port attr: hardware_version   = %s",
1598291a2b48SSukumar Swaminathan 	    port_attrs->hardware_version);
1599fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1600fcf3ce44SJohn Forte 	    "Port attr: driver_version     = %s", port_attrs->driver_version);
1601fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1602fcf3ce44SJohn Forte 	    "Port attr: option_rom_version = %s",
1603fcf3ce44SJohn Forte 	    port_attrs->option_rom_version);
1604fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1605291a2b48SSukumar Swaminathan 	    "Port attr: firmware_version   = %s",
1606291a2b48SSukumar Swaminathan 	    port_attrs->firmware_version);
1607fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1608fcf3ce44SJohn Forte 	    "Port attr: driver_name        = %s", port_attrs->driver_name);
1609fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1610fcf3ce44SJohn Forte 	    "Port attr: vendor_specific_id = 0x%x",
1611fcf3ce44SJohn Forte 	    port_attrs->vendor_specific_id);
1612fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1613291a2b48SSukumar Swaminathan 	    "Port attr: supported_cos      = 0x%x",
1614291a2b48SSukumar Swaminathan 	    port_attrs->supported_cos);
1615fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1616fcf3ce44SJohn Forte 	    "Port attr: supported_speed    = 0x%x",
1617fcf3ce44SJohn Forte 	    port_attrs->supported_speed);
1618fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1619291a2b48SSukumar Swaminathan 	    "Port attr: max_frame_size     = 0x%x",
1620291a2b48SSukumar Swaminathan 	    port_attrs->max_frame_size);
1621fcf3ce44SJohn Forte 
1622fcf3ce44SJohn Forte 	return;
1623fcf3ce44SJohn Forte 
162482527734SSukumar Swaminathan } /* emlxs_fct_populate_hba_details() */
1625fcf3ce44SJohn Forte 
1626fcf3ce44SJohn Forte 
162782527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1628fcf3ce44SJohn Forte /* ARGSUSED */
1629fcf3ce44SJohn Forte static void
1630fcf3ce44SJohn Forte emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg)
1631fcf3ce44SJohn Forte {
1632fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1633fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1634fcf3ce44SJohn Forte 	stmf_change_status_t st;
1635fcf3ce44SJohn Forte 
1636fcf3ce44SJohn Forte 	st.st_completion_status = FCT_SUCCESS;
1637fcf3ce44SJohn Forte 	st.st_additional_info = NULL;
1638fcf3ce44SJohn Forte 
1639fcf3ce44SJohn Forte 	switch (cmd) {
1640fcf3ce44SJohn Forte 	case FCT_CMD_PORT_ONLINE:
1641fcf3ce44SJohn Forte 		/* If the HBA is offline, we cannot bring the tgtport online */
1642fcf3ce44SJohn Forte 		if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) {
1643fcf3ce44SJohn Forte 			st.st_completion_status = FCT_FAILURE;
1644fcf3ce44SJohn Forte 			MODSYM(fct_ctl) (fct_port->port_lport,
1645fcf3ce44SJohn Forte 			    FCT_CMD_PORT_ONLINE_COMPLETE, &st);
1646fcf3ce44SJohn Forte 			break;
1647fcf3ce44SJohn Forte 		}
1648291a2b48SSukumar Swaminathan 
1649fcf3ce44SJohn Forte 		if (port->fct_flags & FCT_STATE_PORT_ONLINE) {
1650fcf3ce44SJohn Forte 			st.st_completion_status = STMF_ALREADY;
1651fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1652fcf3ce44SJohn Forte 			    "STATE: ONLINE chk");
1653fcf3ce44SJohn Forte 		} else {
1654fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1655fcf3ce44SJohn Forte 			    "STATE: OFFLINE --> ONLINE");
1656fcf3ce44SJohn Forte 
1657fcf3ce44SJohn Forte 			port->fct_flags |= FCT_STATE_NOT_ACKED;
1658fcf3ce44SJohn Forte 			port->fct_flags |= FCT_STATE_PORT_ONLINE;
1659fcf3ce44SJohn Forte 
1660fcf3ce44SJohn Forte 			if (hba->state <= FC_LINK_DOWN) {
1661fcf3ce44SJohn Forte 				/* Try to bring the link up */
166282527734SSukumar Swaminathan 				(void) emlxs_reset_link(hba, 1, 1);
1663fcf3ce44SJohn Forte 			}
1664291a2b48SSukumar Swaminathan 
1665fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1666fcf3ce44SJohn Forte 			    "STATE: ONLINE");
1667fcf3ce44SJohn Forte 		}
1668fcf3ce44SJohn Forte 
1669fcf3ce44SJohn Forte 		MODSYM(fct_ctl) (fct_port->port_lport,
1670fcf3ce44SJohn Forte 		    FCT_CMD_PORT_ONLINE_COMPLETE, &st);
1671fcf3ce44SJohn Forte 		break;
1672fcf3ce44SJohn Forte 
1673fcf3ce44SJohn Forte 	case FCT_CMD_PORT_OFFLINE:
1674fcf3ce44SJohn Forte 		if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
1675fcf3ce44SJohn Forte 			st.st_completion_status = STMF_ALREADY;
1676fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1677fcf3ce44SJohn Forte 			    "STATE: OFFLINE chk");
1678fcf3ce44SJohn Forte 
1679fcf3ce44SJohn Forte 		} else {
1680fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1681fcf3ce44SJohn Forte 			    "STATE: ONLINE --> OFFLINE");
1682fcf3ce44SJohn Forte 
1683fcf3ce44SJohn Forte 			/* Take link down and flush */
1684fcf3ce44SJohn Forte 			emlxs_fct_link_down(port);
1685fcf3ce44SJohn Forte 			emlxs_fct_unsol_flush(port);
1686fcf3ce44SJohn Forte 
1687fcf3ce44SJohn Forte 			/* Declare this port offline now */
1688fcf3ce44SJohn Forte 			port->fct_flags |= FCT_STATE_NOT_ACKED;
1689fcf3ce44SJohn Forte 			port->fct_flags &= ~FCT_STATE_PORT_ONLINE;
1690fcf3ce44SJohn Forte 
1691fcf3ce44SJohn Forte 			/* Take link down and hold it down */
169282527734SSukumar Swaminathan 			(void) emlxs_reset_link(hba, 0, 1);
1693fcf3ce44SJohn Forte 
1694fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1695fcf3ce44SJohn Forte 			    "STATE: OFFLINE");
1696fcf3ce44SJohn Forte 		}
1697fcf3ce44SJohn Forte 
1698fcf3ce44SJohn Forte 		MODSYM(fct_ctl) (fct_port->port_lport,
1699fcf3ce44SJohn Forte 		    FCT_CMD_PORT_OFFLINE_COMPLETE, &st);
1700fcf3ce44SJohn Forte 
1701fcf3ce44SJohn Forte 		break;
1702fcf3ce44SJohn Forte 
1703fcf3ce44SJohn Forte 	case FCT_ACK_PORT_OFFLINE_COMPLETE:
1704fcf3ce44SJohn Forte 		port->fct_flags &= ~FCT_STATE_NOT_ACKED;
1705fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1706fcf3ce44SJohn Forte 		    "STATE: OFFLINE ack");
1707fcf3ce44SJohn Forte 		break;
1708fcf3ce44SJohn Forte 
1709fcf3ce44SJohn Forte 	case FCT_ACK_PORT_ONLINE_COMPLETE:
1710fcf3ce44SJohn Forte 		port->fct_flags &= ~FCT_STATE_NOT_ACKED;
1711fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1712fcf3ce44SJohn Forte 		    "STATE: ONLINE ack");
1713fcf3ce44SJohn Forte 		break;
1714fcf3ce44SJohn Forte 
171582527734SSukumar Swaminathan 	case FCT_CMD_FORCE_LIP:
1716*a9800bebSGarrett D'Amore 		if (hba->fw_flag & FW_UPDATE_NEEDED) {
1717*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1718*a9800bebSGarrett D'Amore 			    "emlxs_fct_ctl: FCT_CMD_FORCE_LIP -> "
1719*a9800bebSGarrett D'Amore 			    "FCT_CMD_RESET");
1720*a9800bebSGarrett D'Amore 
1721*a9800bebSGarrett D'Amore 			hba->fw_flag |= FW_UPDATE_KERNEL;
1722*a9800bebSGarrett D'Amore 			/* Reset the adapter */
1723*a9800bebSGarrett D'Amore 			(void) emlxs_reset(port, FC_FCA_RESET);
1724*a9800bebSGarrett D'Amore 		} else {
1725*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1726*a9800bebSGarrett D'Amore 			    "emlxs_fct_ctl: FCT_CMD_FORCE_LIP");
172782527734SSukumar Swaminathan 
1728*a9800bebSGarrett D'Amore 			/* Reset the link */
1729*a9800bebSGarrett D'Amore 			(void) emlxs_reset(port, FC_FCA_LINK_RESET);
1730*a9800bebSGarrett D'Amore 		}
173182527734SSukumar Swaminathan 		break;
1732fcf3ce44SJohn Forte 	}
1733fcf3ce44SJohn Forte 
1734fcf3ce44SJohn Forte 	return;
1735fcf3ce44SJohn Forte 
173682527734SSukumar Swaminathan } /* emlxs_fct_ctl() */
1737291a2b48SSukumar Swaminathan 
1738fcf3ce44SJohn Forte 
1739fcf3ce44SJohn Forte extern int
1740fcf3ce44SJohn Forte emlxs_fct_port_shutdown(emlxs_port_t *port)
1741fcf3ce44SJohn Forte {
1742fcf3ce44SJohn Forte 	fct_local_port_t *fct_port;
174382527734SSukumar Swaminathan 	int i;
1744fcf3ce44SJohn Forte 
1745fcf3ce44SJohn Forte 	fct_port = port->fct_port;
1746fcf3ce44SJohn Forte 	if (!fct_port) {
1747fcf3ce44SJohn Forte 		return (0);
1748fcf3ce44SJohn Forte 	}
17493be114edSSukumar Swaminathan 
17503be114edSSukumar Swaminathan 	port->fct_flags |= FCT_STATE_NOT_ACKED;
17513be114edSSukumar Swaminathan 
1752291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, "fct_port_shutdown");
1753fcf3ce44SJohn Forte 	MODSYM(fct_port_shutdown) (fct_port, STMF_RFLAG_STAY_OFFLINED,
1754fcf3ce44SJohn Forte 	    "emlxs shutdown");
1755fcf3ce44SJohn Forte 
175682527734SSukumar Swaminathan 	i = 0;
1757fcf3ce44SJohn Forte 	while (port->fct_flags & FCT_STATE_NOT_ACKED) {
1758fcf3ce44SJohn Forte 		i++;
1759fcf3ce44SJohn Forte 		if (i > 300) {	/* 30 seconds */
1760fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1761fcf3ce44SJohn Forte 			    "fct_port_shutdown failed to ACK");
1762fcf3ce44SJohn Forte 			break;
1763fcf3ce44SJohn Forte 		}
1764fcf3ce44SJohn Forte 		delay(drv_usectohz(100000));	/* 100 msec */
1765fcf3ce44SJohn Forte 	}
1766fcf3ce44SJohn Forte 	return (1);
1767fcf3ce44SJohn Forte }
1768fcf3ce44SJohn Forte 
1769fcf3ce44SJohn Forte 
1770fcf3ce44SJohn Forte extern int
1771fcf3ce44SJohn Forte emlxs_fct_port_initialize(emlxs_port_t *port)
1772fcf3ce44SJohn Forte {
1773fcf3ce44SJohn Forte 	fct_local_port_t *fct_port;
177482527734SSukumar Swaminathan 	int i;
1775fcf3ce44SJohn Forte 
1776fcf3ce44SJohn Forte 	fct_port = port->fct_port;
1777fcf3ce44SJohn Forte 	if (!fct_port) {
1778fcf3ce44SJohn Forte 		return (0);
1779fcf3ce44SJohn Forte 	}
17803be114edSSukumar Swaminathan 
17813be114edSSukumar Swaminathan 	port->fct_flags |= FCT_STATE_NOT_ACKED;
17823be114edSSukumar Swaminathan 
1783fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1784fcf3ce44SJohn Forte 	    "fct_port_initialize");
1785fcf3ce44SJohn Forte 	MODSYM(fct_port_initialize) (fct_port, STMF_RFLAG_STAY_OFFLINED,
1786fcf3ce44SJohn Forte 	    "emlxs initialize");
1787fcf3ce44SJohn Forte 
178882527734SSukumar Swaminathan 	i = 0;
1789fcf3ce44SJohn Forte 	while (port->fct_flags & FCT_STATE_NOT_ACKED) {
1790fcf3ce44SJohn Forte 		i++;
1791fcf3ce44SJohn Forte 		if (i > 300) {	/* 30 seconds */
1792fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1793fcf3ce44SJohn Forte 			    "fct_port_initialize failed to ACK");
1794fcf3ce44SJohn Forte 			break;
1795fcf3ce44SJohn Forte 		}
1796fcf3ce44SJohn Forte 		delay(drv_usectohz(100000));	/* 100 msec */
1797fcf3ce44SJohn Forte 	}
1798fcf3ce44SJohn Forte 	return (1);
1799fcf3ce44SJohn Forte }
1800fcf3ce44SJohn Forte 
1801291a2b48SSukumar Swaminathan 
180282527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1803fcf3ce44SJohn Forte static fct_status_t
1804fcf3ce44SJohn Forte emlxs_fct_send_cmd(fct_cmd_t *fct_cmd)
1805fcf3ce44SJohn Forte {
1806fcf3ce44SJohn Forte 	emlxs_port_t *port;
1807fcf3ce44SJohn Forte 
1808fcf3ce44SJohn Forte 	port = (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
1809fcf3ce44SJohn Forte 
1810fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1811fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1812fcf3ce44SJohn Forte 	    "emlxs_fct_send_cmd %p: x%x", fct_cmd, fct_cmd->cmd_type);
1813291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1814fcf3ce44SJohn Forte 
1815fcf3ce44SJohn Forte 	switch (fct_cmd->cmd_type) {
1816fcf3ce44SJohn Forte 	case FCT_CMD_SOL_ELS:
1817fcf3ce44SJohn Forte 
1818fcf3ce44SJohn Forte 		return (emlxs_fct_send_els_cmd(fct_cmd));
1819fcf3ce44SJohn Forte 
1820fcf3ce44SJohn Forte 	case FCT_CMD_SOL_CT:
1821fcf3ce44SJohn Forte 
1822fcf3ce44SJohn Forte 		return (emlxs_fct_send_ct_cmd(fct_cmd));
1823fcf3ce44SJohn Forte 
1824fcf3ce44SJohn Forte 	default:
1825fcf3ce44SJohn Forte 
1826fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1827fcf3ce44SJohn Forte 		    "emlxs_fct_send_cmd: Invalid cmd type found. type=%x",
1828fcf3ce44SJohn Forte 		    fct_cmd->cmd_type);
1829fcf3ce44SJohn Forte 
1830fcf3ce44SJohn Forte 		return (FCT_FAILURE);
1831fcf3ce44SJohn Forte 	}
1832fcf3ce44SJohn Forte 
183382527734SSukumar Swaminathan } /* emlxs_fct_send_cmd() */
1834fcf3ce44SJohn Forte 
1835fcf3ce44SJohn Forte 
183682527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1837fcf3ce44SJohn Forte static fct_status_t
1838fcf3ce44SJohn Forte emlxs_fct_send_cmd_rsp(fct_cmd_t *fct_cmd, uint32_t ioflags)
1839fcf3ce44SJohn Forte {
1840fcf3ce44SJohn Forte 	emlxs_port_t *port;
1841291a2b48SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp;
1842291a2b48SSukumar Swaminathan 	fct_status_t rval;
184382527734SSukumar Swaminathan 	IOCBQ *iocbq;
184482527734SSukumar Swaminathan 	IOCB *iocb;
184582527734SSukumar Swaminathan 	uint32_t status;
1846fcf3ce44SJohn Forte 
1847fcf3ce44SJohn Forte 	port = (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
184882527734SSukumar Swaminathan 
184982527734SSukumar Swaminathan 	rval = emlxs_fct_cmd_accept(port, fct_cmd, EMLXS_FCT_SEND_CMD_RSP);
185082527734SSukumar Swaminathan 	if (rval) {
185182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
185282527734SSukumar Swaminathan 		    "emlxs_fct_send_cmd_rsp: "
185382527734SSukumar Swaminathan 		    "Unable to accept fct_cmd. type=%x",
185482527734SSukumar Swaminathan 		    fct_cmd->cmd_type);
185582527734SSukumar Swaminathan 
185682527734SSukumar Swaminathan 		return (rval);
185782527734SSukumar Swaminathan 	}
185882527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
185982527734SSukumar Swaminathan 
1860291a2b48SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
186182527734SSukumar Swaminathan 	iocbq = &cmd_sbp->iocbq;
186282527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
186382527734SSukumar Swaminathan 	status = iocb->ULPSTATUS;
1864fcf3ce44SJohn Forte 
1865fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1866fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
186782527734SSukumar Swaminathan 	    "emlxs_fct_send_cmd_rsp %p: x%x, %x, %x",
186882527734SSukumar Swaminathan 	    fct_cmd, fct_cmd->cmd_type, iocb->ULPCT, status);
1869291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1870fcf3ce44SJohn Forte 
1871fcf3ce44SJohn Forte 	switch (fct_cmd->cmd_type) {
1872fcf3ce44SJohn Forte 	case FCT_CMD_FCP_XCHG:
1873fcf3ce44SJohn Forte 
1874fcf3ce44SJohn Forte 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1875fcf3ce44SJohn Forte 			goto failure;
1876fcf3ce44SJohn Forte 		}
1877291a2b48SSukumar Swaminathan 
187882527734SSukumar Swaminathan 		if ((iocb->ULPCT == 0x1) && (status == 0)) {
187982527734SSukumar Swaminathan 
188082527734SSukumar Swaminathan 			/* Firmware already sent out resp */
188182527734SSukumar Swaminathan 			cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
188282527734SSukumar Swaminathan 
188382527734SSukumar Swaminathan 			emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
188482527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
188582527734SSukumar Swaminathan 
188682527734SSukumar Swaminathan #ifdef FCT_API_TRACE
188782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
188882527734SSukumar Swaminathan 			    "fct_send_response_done:4 %p: x%x",
188982527734SSukumar Swaminathan 			    fct_cmd, fct_cmd->cmd_comp_status);
189082527734SSukumar Swaminathan 
189182527734SSukumar Swaminathan #endif /* FCT_API_TRACE */
189282527734SSukumar Swaminathan 
189382527734SSukumar Swaminathan 			MODSYM(fct_send_response_done) (fct_cmd,
189482527734SSukumar Swaminathan 			    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
189582527734SSukumar Swaminathan 
189682527734SSukumar Swaminathan 			return (FCT_SUCCESS);
189782527734SSukumar Swaminathan 		}
189882527734SSukumar Swaminathan 
1899291a2b48SSukumar Swaminathan 		rval =  emlxs_fct_send_fcp_status(fct_cmd);
190082527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
190182527734SSukumar Swaminathan 
1902291a2b48SSukumar Swaminathan 		return (rval);
1903fcf3ce44SJohn Forte 
1904fcf3ce44SJohn Forte 	case FCT_CMD_RCVD_ELS:
1905fcf3ce44SJohn Forte 
1906fcf3ce44SJohn Forte 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1907fcf3ce44SJohn Forte 			goto failure;
1908fcf3ce44SJohn Forte 		}
1909fcf3ce44SJohn Forte 
191082527734SSukumar Swaminathan 		rval =  emlxs_fct_send_els_rsp(fct_cmd);
191182527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
191282527734SSukumar Swaminathan 
191382527734SSukumar Swaminathan 		return (rval);
1914fcf3ce44SJohn Forte 
1915fcf3ce44SJohn Forte 	default:
1916fcf3ce44SJohn Forte 
1917fcf3ce44SJohn Forte 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1918fcf3ce44SJohn Forte 			fct_cmd->cmd_handle = 0;
1919fcf3ce44SJohn Forte 		}
1920291a2b48SSukumar Swaminathan 
1921fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1922fcf3ce44SJohn Forte 		    "emlxs_fct_send_cmd_rsp: Invalid cmd type found. type=%x",
1923fcf3ce44SJohn Forte 		    fct_cmd->cmd_type);
1924fcf3ce44SJohn Forte 
1925fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
192682527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
192782527734SSukumar Swaminathan 
1928fcf3ce44SJohn Forte 		return (FCT_FAILURE);
1929fcf3ce44SJohn Forte 	}
1930fcf3ce44SJohn Forte 
1931fcf3ce44SJohn Forte failure:
1932fcf3ce44SJohn Forte 
1933fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1934291a2b48SSukumar Swaminathan 	    "emlxs_fct_send_cmd_rsp: "
1935291a2b48SSukumar Swaminathan 	    "Unable to handle FCT_IOF_FORCE_FCA_DONE. type=%x",
1936291a2b48SSukumar Swaminathan 	    fct_cmd->cmd_type);
1937fcf3ce44SJohn Forte 
1938fe199829SSukumar Swaminathan 	emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
193982527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
194082527734SSukumar Swaminathan 
1941fcf3ce44SJohn Forte 	return (FCT_FAILURE);
1942fcf3ce44SJohn Forte 
194382527734SSukumar Swaminathan } /* emlxs_fct_send_cmd_rsp() */
1944fcf3ce44SJohn Forte 
1945fcf3ce44SJohn Forte 
194682527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
1947fcf3ce44SJohn Forte static fct_status_t
194882527734SSukumar Swaminathan emlxs_fct_flogi_xchg(struct fct_local_port *fct_port, struct fct_flogi_xchg *fx)
1949fcf3ce44SJohn Forte {
1950fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1951fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1952fcf3ce44SJohn Forte 	uint32_t size;
195382527734SSukumar Swaminathan 	fc_packet_t *pkt = NULL;
1954fcf3ce44SJohn Forte 	ELS_PKT *els;
195582527734SSukumar Swaminathan 	fct_status_t rval = FCT_SUCCESS;
1956fcf3ce44SJohn Forte 
1957fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
1958fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
195982527734SSukumar Swaminathan 	    "emlxs_fct_flogi_xchg: Sending FLOGI: %p", fct_port);
1960fcf3ce44SJohn Forte #else
1961fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
196282527734SSukumar Swaminathan 	    "emlxs_fct_flogi_xchg: Sending FLOGI.");
1963291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
1964fcf3ce44SJohn Forte 
1965fcf3ce44SJohn Forte 	if (hba->state <= FC_LINK_DOWN) {
1966fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
196782527734SSukumar Swaminathan 		    "emlxs_fct_flogi_xchg: FLOGI failed. Link down.");
196882527734SSukumar Swaminathan 		rval = FCT_FAILURE;
196982527734SSukumar Swaminathan 		goto done;
1970fcf3ce44SJohn Forte 	}
1971291a2b48SSukumar Swaminathan 
1972e2ca2865SSukumar Swaminathan 	/* Use this entyr point as the link up acknowlegment */
1973e2ca2865SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
1974e2ca2865SSukumar Swaminathan 	port->fct_flags |= FCT_STATE_LINK_UP_ACKED;
1975e2ca2865SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1976e2ca2865SSukumar Swaminathan 	    "emlxs_fct_link_up acked.");
1977e2ca2865SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
1978e2ca2865SSukumar Swaminathan 
1979e2ca2865SSukumar Swaminathan 	/* Now flush any pending unsolicited requests */
1980e2ca2865SSukumar Swaminathan 	emlxs_fct_unsol_flush(port);
1981e2ca2865SSukumar Swaminathan 
1982fcf3ce44SJohn Forte 	size = sizeof (SERV_PARM) + 4;
1983fcf3ce44SJohn Forte 
1984fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, size, size, 0, KM_NOSLEEP))) {
1985fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
198682527734SSukumar Swaminathan 		    "emlxs_fct_flogi_xchg: FLOGI failed. "
198782527734SSukumar Swaminathan 		    "Unable allocate packet.");
198882527734SSukumar Swaminathan 		rval = FCT_FAILURE;
198982527734SSukumar Swaminathan 		goto done;
1990fcf3ce44SJohn Forte 	}
1991291a2b48SSukumar Swaminathan 
1992fcf3ce44SJohn Forte 	/* Make this a polled IO */
1993fcf3ce44SJohn Forte 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
1994fcf3ce44SJohn Forte 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
1995fcf3ce44SJohn Forte 	pkt->pkt_comp = NULL;
1996fcf3ce44SJohn Forte 
1997fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
1998fcf3ce44SJohn Forte 	pkt->pkt_timeout = fx->fx_sec_timeout;
1999fcf3ce44SJohn Forte 
2000fcf3ce44SJohn Forte 	/* Build the fc header */
200182527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(fx->fx_did);
2002291a2b48SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.r_ctl =
2003291a2b48SSukumar Swaminathan 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
200482527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(fx->fx_sid);
2005fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2006fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE;
2007fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
2008fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2009fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2010fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
2011fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
2012fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
2013fcf3ce44SJohn Forte 
2014fcf3ce44SJohn Forte 	/* Build the command */
2015291a2b48SSukumar Swaminathan 	/* Service paramters will be added automatically later by the driver */
2016fcf3ce44SJohn Forte 	els = (ELS_PKT *)pkt->pkt_cmd;
2017fcf3ce44SJohn Forte 	els->elsCode = 0x04;	/* FLOGI */
2018fcf3ce44SJohn Forte 
2019fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2020fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
202182527734SSukumar Swaminathan 		    "emlxs_fct_flogi_xchg: FLOGI failed. "
202282527734SSukumar Swaminathan 		    "Unable to send packet.");
2023fcf3ce44SJohn Forte 
202482527734SSukumar Swaminathan 		rval = FCT_FAILURE;
202582527734SSukumar Swaminathan 		goto done;
2026fcf3ce44SJohn Forte 	}
2027291a2b48SSukumar Swaminathan 
2028fcf3ce44SJohn Forte 	if ((pkt->pkt_state != FC_PKT_SUCCESS) &&
2029fcf3ce44SJohn Forte 	    (pkt->pkt_state != FC_PKT_LS_RJT)) {
2030fcf3ce44SJohn Forte 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
203182527734SSukumar Swaminathan 			rval = FCT_TIMEOUT;
2032fcf3ce44SJohn Forte 		} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
2033fcf3ce44SJohn Forte 		    (pkt->pkt_reason == FC_REASON_FCAL_OPN_FAIL)) {
203482527734SSukumar Swaminathan 			rval = FCT_NOT_FOUND;
203582527734SSukumar Swaminathan 		} else {
203682527734SSukumar Swaminathan 			rval = FCT_FAILURE;
2037fcf3ce44SJohn Forte 		}
2038291a2b48SSukumar Swaminathan 
2039fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
204082527734SSukumar Swaminathan 		    "emlxs_fct_flogi_xchg: FLOGI failed. state=%x reason=%x",
2041fcf3ce44SJohn Forte 		    pkt->pkt_state, pkt->pkt_reason);
2042fcf3ce44SJohn Forte 
204382527734SSukumar Swaminathan 		goto done;
2044fcf3ce44SJohn Forte 	}
2045291a2b48SSukumar Swaminathan 
2046fcf3ce44SJohn Forte 	if (pkt->pkt_state == FC_PKT_LS_RJT) {
2047fcf3ce44SJohn Forte 		fx->fx_op = ELS_OP_LSRJT;
2048fcf3ce44SJohn Forte 		fx->fx_rjt_reason = pkt->pkt_reason;
2049fcf3ce44SJohn Forte 		fx->fx_rjt_expl = pkt->pkt_expln;
2050fcf3ce44SJohn Forte 	} else {	/* FC_PKT_SUCCESS */
2051291a2b48SSukumar Swaminathan 
2052fcf3ce44SJohn Forte 		fx->fx_op = ELS_OP_ACC;
205382527734SSukumar Swaminathan 		fx->fx_sid = FABRIC_DID;
2054fcf3ce44SJohn Forte 		fx->fx_did = port->did;
2055fcf3ce44SJohn Forte 
2056291a2b48SSukumar Swaminathan 		els = (ELS_PKT *)pkt->pkt_resp;
2057fcf3ce44SJohn Forte 		bcopy((caddr_t)&els->un.logi.nodeName,
2058fcf3ce44SJohn Forte 		    (caddr_t)fx->fx_nwwn, 8);
2059fcf3ce44SJohn Forte 		bcopy((caddr_t)&els->un.logi.portName,
2060fcf3ce44SJohn Forte 		    (caddr_t)fx->fx_pwwn, 8);
2061fcf3ce44SJohn Forte 		fx->fx_fport = els->un.logi.cmn.fPort;
2062fcf3ce44SJohn Forte 	}
2063fcf3ce44SJohn Forte 
206482527734SSukumar Swaminathan done:
206582527734SSukumar Swaminathan 	if (pkt) {
206682527734SSukumar Swaminathan 		emlxs_pkt_free(pkt);
206782527734SSukumar Swaminathan 	}
206882527734SSukumar Swaminathan 
206982527734SSukumar Swaminathan 	return (rval);
2070fcf3ce44SJohn Forte 
207182527734SSukumar Swaminathan } /* emlxs_fct_flogi_xchg() */
2072fcf3ce44SJohn Forte 
2073fcf3ce44SJohn Forte 
207482527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
2075fcf3ce44SJohn Forte /* This is called right after we report that link has come online */
2076fcf3ce44SJohn Forte static fct_status_t
2077fcf3ce44SJohn Forte emlxs_fct_get_link_info(fct_local_port_t *fct_port, fct_link_info_t *link)
2078fcf3ce44SJohn Forte {
2079fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
2080fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2081fcf3ce44SJohn Forte 
2082fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2083fcf3ce44SJohn Forte 	    "emlxs_fct_get_link_info %p", fct_port);
2084fcf3ce44SJohn Forte 
2085fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
2086fcf3ce44SJohn Forte 
2087fcf3ce44SJohn Forte 	if (!(port->fct_flags & FCT_STATE_LINK_UP) ||
2088291a2b48SSukumar Swaminathan 	    (hba->state < FC_LINK_UP) || (hba->flag & FC_LOOPBACK_MODE)) {
2089fcf3ce44SJohn Forte 		link->port_topology = PORT_TOPOLOGY_UNKNOWN;
2090fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_UNKNOWN;
2091fcf3ce44SJohn Forte 		link->portid = 0;
2092fcf3ce44SJohn Forte 
2093fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
2094fcf3ce44SJohn Forte 
2095fcf3ce44SJohn Forte 		return (FCT_SUCCESS);
2096fcf3ce44SJohn Forte 	}
2097291a2b48SSukumar Swaminathan 
2098fcf3ce44SJohn Forte 	if (hba->topology == TOPOLOGY_LOOP) {
2099fcf3ce44SJohn Forte 		link->port_topology = PORT_TOPOLOGY_PRIVATE_LOOP;
2100fcf3ce44SJohn Forte 	} else {
2101fcf3ce44SJohn Forte 		link->port_topology = PORT_TOPOLOGY_PT_TO_PT;
2102fcf3ce44SJohn Forte 	}
2103fcf3ce44SJohn Forte 
2104fcf3ce44SJohn Forte 	switch (hba->linkspeed) {
2105fcf3ce44SJohn Forte 	case LA_1GHZ_LINK:
2106fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_1G;
2107fcf3ce44SJohn Forte 		break;
2108fcf3ce44SJohn Forte 	case LA_2GHZ_LINK:
2109fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_2G;
2110fcf3ce44SJohn Forte 		break;
2111fcf3ce44SJohn Forte 	case LA_4GHZ_LINK:
2112fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_4G;
2113fcf3ce44SJohn Forte 		break;
2114fcf3ce44SJohn Forte 	case LA_8GHZ_LINK:
2115fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_8G;
2116fcf3ce44SJohn Forte 		break;
2117fcf3ce44SJohn Forte 	case LA_10GHZ_LINK:
2118fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_10G;
2119fcf3ce44SJohn Forte 		break;
2120fcf3ce44SJohn Forte 	default:
2121fcf3ce44SJohn Forte 		link->port_speed = PORT_SPEED_UNKNOWN;
2122fcf3ce44SJohn Forte 		break;
2123fcf3ce44SJohn Forte 	}
2124fcf3ce44SJohn Forte 
2125fcf3ce44SJohn Forte 	link->portid = port->did;
2126fcf3ce44SJohn Forte 	link->port_no_fct_flogi = 0;
2127fcf3ce44SJohn Forte 	link->port_fca_flogi_done = 0;
2128fcf3ce44SJohn Forte 	link->port_fct_flogi_done = 0;
2129fcf3ce44SJohn Forte 
2130fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
2131fcf3ce44SJohn Forte 
2132fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
2133fcf3ce44SJohn Forte 
213482527734SSukumar Swaminathan } /* emlxs_fct_get_link_info() */
2135fcf3ce44SJohn Forte 
2136fcf3ce44SJohn Forte 
213782527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
2138fcf3ce44SJohn Forte static fct_status_t
2139fcf3ce44SJohn Forte emlxs_fct_register_remote_port(fct_local_port_t *fct_port,
2140fcf3ce44SJohn Forte     fct_remote_port_t *remote_port, fct_cmd_t *fct_cmd)
2141fcf3ce44SJohn Forte {
2142fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
2143fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2144fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2145fcf3ce44SJohn Forte 	clock_t timeout;
2146fcf3ce44SJohn Forte 	int32_t pkt_ret;
2147fcf3ce44SJohn Forte 	fct_els_t *els;
2148fcf3ce44SJohn Forte 	SERV_PARM *sp;
2149fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
2150fcf3ce44SJohn Forte 	SERV_PARM sparam;
2151fcf3ce44SJohn Forte 	uint32_t *iptr;
21523be114edSSukumar Swaminathan 	uint64_t addr;
215382527734SSukumar Swaminathan 	fct_status_t rval;
215482527734SSukumar Swaminathan 	fct_status_t rval2;
2155fcf3ce44SJohn Forte 
2156fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2157fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2158fcf3ce44SJohn Forte 	    "emlxs_fct_register_remote_port %p", fct_port);
2159291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2160fcf3ce44SJohn Forte 
2161fcf3ce44SJohn Forte 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
216282527734SSukumar Swaminathan 
216382527734SSukumar Swaminathan 		cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd,
216482527734SSukumar Swaminathan 		    EMLXS_FCT_REG_PENDING);
2165291a2b48SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
2166fcf3ce44SJohn Forte 
216782527734SSukumar Swaminathan 		cmd_sbp->channel = &hba->chan[hba->channel_els];
2168fcf3ce44SJohn Forte 		cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD;
216982527734SSukumar Swaminathan 
2170fcf3ce44SJohn Forte 	} else {
2171fcf3ce44SJohn Forte 
217282527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_accept(port, fct_cmd,
217382527734SSukumar Swaminathan 		    EMLXS_FCT_REG_PENDING);
217482527734SSukumar Swaminathan 		if (rval) {
217582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
217682527734SSukumar Swaminathan 			    "emlxs_fct_register_remote_port: "
217782527734SSukumar Swaminathan 			    "Unable to accept fct_cmd. did=%x",
217882527734SSukumar Swaminathan 			    fct_cmd->cmd_rportid);
2179291a2b48SSukumar Swaminathan 
218082527734SSukumar Swaminathan 			return (rval);
218182527734SSukumar Swaminathan 		}
218282527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
218382527734SSukumar Swaminathan 	}
2184fcf3ce44SJohn Forte 
2185*a9800bebSGarrett D'Amore 	cmd_sbp->fct_flags &= ~EMLXS_FCT_REGISTERED;
2186*a9800bebSGarrett D'Amore 
2187fcf3ce44SJohn Forte 	if (!cmd_sbp->node) {
2188291a2b48SSukumar Swaminathan 		cmd_sbp->node =
2189291a2b48SSukumar Swaminathan 		    emlxs_node_find_did(port, fct_cmd->cmd_rportid);
2190fcf3ce44SJohn Forte 	}
2191291a2b48SSukumar Swaminathan 
2192fcf3ce44SJohn Forte 	if (!cmd_sbp->node) {
2193fcf3ce44SJohn Forte 		els = (fct_els_t *)fct_cmd->cmd_specific;
2194fcf3ce44SJohn Forte 
2195fcf3ce44SJohn Forte 		/* Check for unsolicited PLOGI */
2196291a2b48SSukumar Swaminathan 		if (cmd_sbp->fct_flags & EMLXS_FCT_PLOGI_RECEIVED) {
2197291a2b48SSukumar Swaminathan 			sp = (SERV_PARM *)((caddr_t)els->els_req_payload +
2198291a2b48SSukumar Swaminathan 			    sizeof (uint32_t));
2199fcf3ce44SJohn Forte 		} else {	/* Solicited PLOGI */
2200291a2b48SSukumar Swaminathan 
2201fcf3ce44SJohn Forte 			sp = &sparam;
2202fcf3ce44SJohn Forte 			bcopy((caddr_t)&port->sparam, (caddr_t)sp,
2203fcf3ce44SJohn Forte 			    sizeof (SERV_PARM));
2204fcf3ce44SJohn Forte 
2205fcf3ce44SJohn Forte 			/*
2206291a2b48SSukumar Swaminathan 			 * Create temporary WWN's from fct_cmd address
2207fcf3ce44SJohn Forte 			 * This simply allows us to get an RPI from the
2208291a2b48SSukumar Swaminathan 			 * adapter until we get real service params.
2209fcf3ce44SJohn Forte 			 * The PLOGI ACC reply will trigger a REG_LOGIN
2210fcf3ce44SJohn Forte 			 * update later
2211fcf3ce44SJohn Forte 			 */
22123be114edSSukumar Swaminathan 			addr = (uint64_t)((unsigned long)fct_cmd);
22133be114edSSukumar Swaminathan 
2214fcf3ce44SJohn Forte 			iptr = (uint32_t *)&sp->portName;
221582527734SSukumar Swaminathan 			iptr[0] = PADDR_HI(addr);
221682527734SSukumar Swaminathan 			iptr[1] = PADDR_LO(addr);
2217291a2b48SSukumar Swaminathan 
2218fcf3ce44SJohn Forte 			iptr = (uint32_t *)&sp->nodeName;
221982527734SSukumar Swaminathan 			iptr[0] = PADDR_HI(addr);
222082527734SSukumar Swaminathan 			iptr[1] = PADDR_LO(addr);
2221fcf3ce44SJohn Forte 		}
2222fcf3ce44SJohn Forte 
2223fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
2224291a2b48SSukumar Swaminathan 		    "emlxs_fct_register_remote_port: Register did=%x. (%x,%p)",
2225291a2b48SSukumar Swaminathan 		    fct_cmd->cmd_rportid, cmd_sbp->fct_state, fct_cmd);
2226fcf3ce44SJohn Forte 
222782527734SSukumar Swaminathan 		emlxs_fct_cmd_release(port, fct_cmd, 0);
222882527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
222982527734SSukumar Swaminathan 
2230fcf3ce44SJohn Forte 		/* Create a new node */
2231fcf3ce44SJohn Forte 		if (emlxs_mb_reg_did(port, fct_cmd->cmd_rportid, sp, cmd_sbp,
2232fcf3ce44SJohn Forte 		    NULL, NULL) != 0) {
2233fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2234291a2b48SSukumar Swaminathan 			    "emlxs_fct_register_remote_port: "
2235291a2b48SSukumar Swaminathan 			    "Reg login failed. did=%x",
2236291a2b48SSukumar Swaminathan 			    fct_cmd->cmd_rportid);
223782527734SSukumar Swaminathan 		} else {
2238fcf3ce44SJohn Forte 
223982527734SSukumar Swaminathan 			/* Wait for completion */
224082527734SSukumar Swaminathan 			mutex_enter(&EMLXS_PKT_LOCK);
224182527734SSukumar Swaminathan 			timeout = emlxs_timeout(hba, 30);
224282527734SSukumar Swaminathan 			pkt_ret = 0;
224382527734SSukumar Swaminathan 			while ((pkt_ret != -1) &&
224482527734SSukumar Swaminathan 			    (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) &&
2245*a9800bebSGarrett D'Amore 			    !(cmd_sbp->fct_flags & EMLXS_FCT_REGISTERED)) {
224682527734SSukumar Swaminathan 				pkt_ret = cv_timedwait(&EMLXS_PKT_CV,
224782527734SSukumar Swaminathan 				    &EMLXS_PKT_LOCK, timeout);
224882527734SSukumar Swaminathan 			}
224982527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PKT_LOCK);
2250fcf3ce44SJohn Forte 		}
2251fcf3ce44SJohn Forte 
225282527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
225382527734SSukumar Swaminathan 		rval2 = emlxs_fct_cmd_acquire(port, fct_cmd,
225482527734SSukumar Swaminathan 		    EMLXS_FCT_REG_COMPLETE);
225582527734SSukumar Swaminathan 		if (rval2) {
225682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
225782527734SSukumar Swaminathan 			    "emlxs_fct_register_remote_port: "
225882527734SSukumar Swaminathan 			    "Unable to reacquire fct_cmd. did=%x",
225982527734SSukumar Swaminathan 			    fct_cmd->cmd_rportid);
226082527734SSukumar Swaminathan 
226182527734SSukumar Swaminathan 			return (rval2);
2262291a2b48SSukumar Swaminathan 		}
226382527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
2264fcf3ce44SJohn Forte 	}
2265291a2b48SSukumar Swaminathan 
2266fcf3ce44SJohn Forte done:
2267fcf3ce44SJohn Forte 
2268fcf3ce44SJohn Forte 	ndlp = (emlxs_node_t *)cmd_sbp->node;
2269fcf3ce44SJohn Forte 
2270fcf3ce44SJohn Forte 	if (ndlp) {
2271*a9800bebSGarrett D'Amore 		cmd_sbp->fct_flags |= EMLXS_FCT_REGISTERED;
2272*a9800bebSGarrett D'Amore 
2273291a2b48SSukumar Swaminathan 		*((emlxs_node_t **)remote_port->rp_fca_private) =
2274291a2b48SSukumar Swaminathan 		    cmd_sbp->node;
2275fcf3ce44SJohn Forte 		remote_port->rp_handle = ndlp->nlp_Rpi;
2276fcf3ce44SJohn Forte 
2277fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2278fcf3ce44SJohn Forte 		    "emlxs_fct_register_remote_port: did=%x hdl=%x",
2279fcf3ce44SJohn Forte 		    fct_cmd->cmd_rportid, remote_port->rp_handle);
2280fcf3ce44SJohn Forte 
2281fcf3ce44SJohn Forte 		remote_port->rp_handle = ndlp->nlp_Rpi;
2282fcf3ce44SJohn Forte 
2283fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
228482527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2285291a2b48SSukumar Swaminathan 
2286fcf3ce44SJohn Forte 		TGTPORTSTAT.FctPortRegister++;
2287fcf3ce44SJohn Forte 		return (FCT_SUCCESS);
2288fcf3ce44SJohn Forte 	} else {
2289fcf3ce44SJohn Forte 		*((emlxs_node_t **)remote_port->rp_fca_private) = NULL;
2290fcf3ce44SJohn Forte 
2291fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2292fcf3ce44SJohn Forte 		    "emlxs_fct_register_remote_port: failed. did=%x hdl=%x",
2293fcf3ce44SJohn Forte 		    fct_cmd->cmd_rportid, remote_port->rp_handle);
2294fcf3ce44SJohn Forte 
2295fcf3ce44SJohn Forte 		remote_port->rp_handle = FCT_HANDLE_NONE;
2296fcf3ce44SJohn Forte 
2297fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
229882527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2299291a2b48SSukumar Swaminathan 
2300fcf3ce44SJohn Forte 		TGTPORTSTAT.FctFailedPortRegister++;
2301fcf3ce44SJohn Forte 		return (FCT_FAILURE);
2302fcf3ce44SJohn Forte 	}
2303fcf3ce44SJohn Forte 
230482527734SSukumar Swaminathan } /* emlxs_fct_register_remote_port() */
2305fcf3ce44SJohn Forte 
2306fcf3ce44SJohn Forte 
230782527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
2308fcf3ce44SJohn Forte static fct_status_t
2309fcf3ce44SJohn Forte emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port,
2310fcf3ce44SJohn Forte     fct_remote_port_t *remote_port)
2311fcf3ce44SJohn Forte {
2312fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
2313*a9800bebSGarrett D'Amore 	emlxs_node_t *ndlp;
2314fcf3ce44SJohn Forte 
2315fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2316fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2317fcf3ce44SJohn Forte 	    "emlxs_fct_deregister_remote_port: did=%x hdl=%x",
2318fcf3ce44SJohn Forte 	    remote_port->rp_id, remote_port->rp_handle);
2319fcf3ce44SJohn Forte #else
2320fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2321fcf3ce44SJohn Forte 	    "emlxs_fct_deregister_remote_port: did=%x hdl=%x",
2322fcf3ce44SJohn Forte 	    remote_port->rp_id, remote_port->rp_handle);
2323291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2324fcf3ce44SJohn Forte 
2325*a9800bebSGarrett D'Amore 	ndlp = *((emlxs_node_t **)remote_port->rp_fca_private);
2326fcf3ce44SJohn Forte 	*((emlxs_node_t **)remote_port->rp_fca_private) = NULL;
2327*a9800bebSGarrett D'Amore 
2328*a9800bebSGarrett D'Amore 	if (ndlp) {
2329*a9800bebSGarrett D'Amore 		(void) emlxs_mb_unreg_node(port, ndlp, NULL,
2330*a9800bebSGarrett D'Amore 		    NULL, NULL);
2331*a9800bebSGarrett D'Amore 	}
2332fcf3ce44SJohn Forte 
2333fcf3ce44SJohn Forte 	TGTPORTSTAT.FctPortDeregister++;
2334fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
2335fcf3ce44SJohn Forte 
233682527734SSukumar Swaminathan } /* emlxs_fct_deregister_remote_port() */
2337fcf3ce44SJohn Forte 
2338fcf3ce44SJohn Forte 
2339fcf3ce44SJohn Forte /* ARGSUSED */
2340fcf3ce44SJohn Forte extern int
234182527734SSukumar Swaminathan emlxs_fct_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
2342fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
2343fcf3ce44SJohn Forte {
2344fcf3ce44SJohn Forte 	IOCB *iocb;
2345fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
2346fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
2347fcf3ce44SJohn Forte 	emlxs_fcp_cmd_t *fcp_cmd;
2348fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
2349fcf3ce44SJohn Forte 	uint32_t cnt;
2350fcf3ce44SJohn Forte 	uint32_t tm;
2351fcf3ce44SJohn Forte 	scsi_task_t *fct_task;
2352fcf3ce44SJohn Forte 	uint8_t lun[8];
2353fcf3ce44SJohn Forte 	uint32_t sid = 0;
2354fcf3ce44SJohn Forte 
2355fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
235682527734SSukumar Swaminathan 	ndlp = emlxs_node_find_rpi(port, iocb->ULPIOTAG);
2357fcf3ce44SJohn Forte 	if (!ndlp) {
2358fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2359fcf3ce44SJohn Forte 		    "FCP rcvd: Unknown RPI. rpi=%x rxid=%x. Dropping...",
236082527734SSukumar Swaminathan 		    iocb->ULPIOTAG, iocb->ULPCONTEXT);
2361fcf3ce44SJohn Forte 
2362fcf3ce44SJohn Forte 		goto dropped;
2363fcf3ce44SJohn Forte 	}
2364fcf3ce44SJohn Forte 	sid = ndlp->nlp_DID;
2365fcf3ce44SJohn Forte 
2366fcf3ce44SJohn Forte 	fcp_cmd = (emlxs_fcp_cmd_t *)mp->virt;
2367fcf3ce44SJohn Forte 
2368fcf3ce44SJohn Forte 	if (!port->fct_port) {
2369fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2370fcf3ce44SJohn Forte 		    "FCP rcvd: Target unbound. rpi=%x rxid=%x. Dropping...",
237182527734SSukumar Swaminathan 		    iocb->ULPIOTAG, iocb->ULPCONTEXT);
2372fcf3ce44SJohn Forte 
2373fcf3ce44SJohn Forte 		emlxs_send_logo(port, sid);
2374fcf3ce44SJohn Forte 
2375fcf3ce44SJohn Forte 		goto dropped;
2376fcf3ce44SJohn Forte 	}
2377291a2b48SSukumar Swaminathan 
2378fcf3ce44SJohn Forte 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
2379fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2380fcf3ce44SJohn Forte 		    "FCP rcvd: Target offline. rpi=%x rxid=%x. Dropping...",
238182527734SSukumar Swaminathan 		    iocb->ULPIOTAG, iocb->ULPCONTEXT);
2382fcf3ce44SJohn Forte 
2383fcf3ce44SJohn Forte 		emlxs_send_logo(port, sid);
2384fcf3ce44SJohn Forte 
2385fcf3ce44SJohn Forte 		goto dropped;
2386fcf3ce44SJohn Forte 	}
2387291a2b48SSukumar Swaminathan 
2388fcf3ce44SJohn Forte 	/* Get lun id */
2389fcf3ce44SJohn Forte 	bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8);
2390fcf3ce44SJohn Forte 
2391fcf3ce44SJohn Forte 	if (TGTPORTSTAT.FctOutstandingIO >= port->fct_port->port_max_xchges) {
2392fcf3ce44SJohn Forte 		TGTPORTSTAT.FctOverQDepth++;
2393fcf3ce44SJohn Forte 	}
2394291a2b48SSukumar Swaminathan 
2395291a2b48SSukumar Swaminathan 	fct_cmd =
239682527734SSukumar Swaminathan 	    MODSYM(fct_scsi_task_alloc) (port->fct_port, iocb->ULPIOTAG, sid,
2397291a2b48SSukumar Swaminathan 	    lun, 16, 0);
2398fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2399fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2400291a2b48SSukumar Swaminathan 	    "fct_scsi_task_alloc %p: FCP rcvd: "
2401291a2b48SSukumar Swaminathan 	    "cmd=%x sid=%x rxid=%x lun=%02x%02x dl=%d",
240282527734SSukumar Swaminathan 	    fct_cmd, fcp_cmd->fcpCdb[0], sid, iocb->ULPCONTEXT,
240382527734SSukumar Swaminathan 	    lun[0], lun[1], LE_SWAP32(fcp_cmd->fcpDl));
2404291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2405fcf3ce44SJohn Forte 
2406fcf3ce44SJohn Forte 	if (fct_cmd == NULL) {
2407fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2408291a2b48SSukumar Swaminathan 		    "FCP rcvd: sid=%x xid=%x. "
2409291a2b48SSukumar Swaminathan 		    "Unable to allocate scsi task. Returning QFULL.",
241082527734SSukumar Swaminathan 		    sid, iocb->ULPCONTEXT);
2411fcf3ce44SJohn Forte 
241282527734SSukumar Swaminathan 		(void) emlxs_fct_send_qfull_reply(port, ndlp, iocb->ULPCONTEXT,
241382527734SSukumar Swaminathan 		    iocb->ULPCLASS, fcp_cmd);
2414fcf3ce44SJohn Forte 
2415fcf3ce44SJohn Forte 		goto dropped;
2416fcf3ce44SJohn Forte 	}
2417291a2b48SSukumar Swaminathan 
2418fcf3ce44SJohn Forte 	/* Initialize fct_cmd */
2419fcf3ce44SJohn Forte 	fct_cmd->cmd_oxid = 0xFFFF;
242082527734SSukumar Swaminathan 	fct_cmd->cmd_rxid = iocb->ULPCONTEXT;
2421fcf3ce44SJohn Forte 	fct_cmd->cmd_rportid = sid;
2422fcf3ce44SJohn Forte 	fct_cmd->cmd_lportid = port->did;
242382527734SSukumar Swaminathan 	fct_cmd->cmd_rp_handle = iocb->ULPIOTAG;	/* RPI */
2424fcf3ce44SJohn Forte 	fct_cmd->cmd_port = port->fct_port;
2425fcf3ce44SJohn Forte 
242682527734SSukumar Swaminathan 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_FCP_CMD_RECEIVED);
242782527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2428fcf3ce44SJohn Forte 
2429291a2b48SSukumar Swaminathan 	/* Initialize cmd_sbp */
243082527734SSukumar Swaminathan 	cmd_sbp->channel = cp;
243182527734SSukumar Swaminathan 	cmd_sbp->class = iocb->ULPCLASS;
2432fcf3ce44SJohn Forte 	cmd_sbp->lun = (lun[0] << 8) | lun[1];
2433fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_FCP_CMD;
2434fcf3ce44SJohn Forte 
2435fcf3ce44SJohn Forte 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
2436fcf3ce44SJohn Forte 
2437fcf3ce44SJohn Forte 	/* Set task_flags */
2438291a2b48SSukumar Swaminathan 	switch (fcp_cmd->fcpCntl1) {
2439291a2b48SSukumar Swaminathan 	case SIMPLE_Q:
2440fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_SIMPLE_QUEUE;
2441fcf3ce44SJohn Forte 		break;
2442fcf3ce44SJohn Forte 
2443291a2b48SSukumar Swaminathan 	case HEAD_OF_Q:
2444fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_HEAD_OF_QUEUE;
2445fcf3ce44SJohn Forte 		break;
2446fcf3ce44SJohn Forte 
2447291a2b48SSukumar Swaminathan 	case ORDERED_Q:
2448fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_ORDERED_QUEUE;
2449fcf3ce44SJohn Forte 		break;
2450fcf3ce44SJohn Forte 
2451291a2b48SSukumar Swaminathan 	case ACA_Q:
2452fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_ACA;
2453fcf3ce44SJohn Forte 		break;
2454fcf3ce44SJohn Forte 
2455291a2b48SSukumar Swaminathan 	case UNTAGGED:
2456fcf3ce44SJohn Forte 		fct_task->task_flags = TF_ATTR_UNTAGGED;
2457fcf3ce44SJohn Forte 		break;
2458fcf3ce44SJohn Forte 	}
2459fcf3ce44SJohn Forte 
246082527734SSukumar Swaminathan 	cnt = LE_SWAP32(fcp_cmd->fcpDl);
2461fcf3ce44SJohn Forte 	switch (fcp_cmd->fcpCntl3) {
2462fcf3ce44SJohn Forte 	case 0:
2463fcf3ce44SJohn Forte 		TGTPORTSTAT.FctIOCmdCnt++;
2464fcf3ce44SJohn Forte 		break;
2465fcf3ce44SJohn Forte 	case 1:
246682527734SSukumar Swaminathan 		EMLXS_BUMP_WRIOCTR(port, cnt);
2467fcf3ce44SJohn Forte 		TGTPORTSTAT.FctWriteBytes += cnt;
2468fcf3ce44SJohn Forte 		fct_task->task_flags |= TF_WRITE_DATA;
2469fcf3ce44SJohn Forte 		break;
2470fcf3ce44SJohn Forte 
2471fcf3ce44SJohn Forte 	case 2:
247282527734SSukumar Swaminathan 		EMLXS_BUMP_RDIOCTR(port, cnt);
2473fcf3ce44SJohn Forte 		TGTPORTSTAT.FctReadBytes += cnt;
2474fcf3ce44SJohn Forte 		fct_task->task_flags |= TF_READ_DATA;
2475fcf3ce44SJohn Forte 		break;
2476fcf3ce44SJohn Forte 	}
2477fcf3ce44SJohn Forte 
2478fcf3ce44SJohn Forte 	fct_task->task_priority = 0;
2479fcf3ce44SJohn Forte 
2480fcf3ce44SJohn Forte 	/* task_mgmt_function */
2481fcf3ce44SJohn Forte 	tm = fcp_cmd->fcpCntl2;
2482fcf3ce44SJohn Forte 	if (tm) {
2483fcf3ce44SJohn Forte 		if (tm & BIT_1) {
2484fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_ABORT_TASK_SET;
2485fcf3ce44SJohn Forte 		} else if (tm & BIT_2) {
2486fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_CLEAR_TASK_SET;
2487fcf3ce44SJohn Forte 		} else if (tm & BIT_4) {
2488fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_LUN_RESET;
2489fcf3ce44SJohn Forte 		} else if (tm & BIT_5) {
2490fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_TARGET_COLD_RESET;
2491fcf3ce44SJohn Forte 		} else if (tm & BIT_6) {
2492fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_CLEAR_ACA;
2493fcf3ce44SJohn Forte 		} else {
2494fcf3ce44SJohn Forte 			fct_task->task_mgmt_function = TM_ABORT_TASK;
2495fcf3ce44SJohn Forte 		}
2496fcf3ce44SJohn Forte 	}
2497291a2b48SSukumar Swaminathan 
2498fcf3ce44SJohn Forte 	/* Parallel buffers support - future */
2499fcf3ce44SJohn Forte 	fct_task->task_max_nbufs = 1;
2500fcf3ce44SJohn Forte 
2501fcf3ce44SJohn Forte 	fct_task->task_additional_flags = 0;
2502fcf3ce44SJohn Forte 	fct_task->task_cur_nbufs = 0;
2503fcf3ce44SJohn Forte 	fct_task->task_csn_size = 8;
2504fcf3ce44SJohn Forte 	fct_task->task_cmd_seq_no = 0;
2505fcf3ce44SJohn Forte 	fct_task->task_expected_xfer_length = cnt;
2506fcf3ce44SJohn Forte 	bcopy((void *)&fcp_cmd->fcpCdb, fct_task->task_cdb, 16);
2507fcf3ce44SJohn Forte 
2508fcf3ce44SJohn Forte 	TGTPORTSTAT.FctCmdReceived++;
2509fcf3ce44SJohn Forte 	TGTPORTSTAT.FctOutstandingIO++;
2510fcf3ce44SJohn Forte 
251182527734SSukumar Swaminathan 	emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
251282527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
2513fcf3ce44SJohn Forte 
2514291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
2515291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
251682527734SSukumar Swaminathan 	    "fct_post_rcvd_cmd:3 %p: portid x%x, %d", fct_cmd,
251782527734SSukumar Swaminathan 	    fct_cmd->cmd_lportid, fct_task->task_expected_xfer_length);
2518291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
251982527734SSukumar Swaminathan 
2520291a2b48SSukumar Swaminathan 	MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
2521fcf3ce44SJohn Forte 
2522fcf3ce44SJohn Forte 	return (0);
2523fcf3ce44SJohn Forte 
2524fcf3ce44SJohn Forte dropped:
2525fcf3ce44SJohn Forte 
2526fcf3ce44SJohn Forte 	TGTPORTSTAT.FctRcvDropped++;
2527fcf3ce44SJohn Forte 	return (1);
2528fcf3ce44SJohn Forte 
252982527734SSukumar Swaminathan } /* emlxs_fct_handle_unsol_req() */
2530fcf3ce44SJohn Forte 
2531fcf3ce44SJohn Forte 
253282527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
2533fcf3ce44SJohn Forte /* ARGSUSED */
2534fcf3ce44SJohn Forte static fct_status_t
2535fcf3ce44SJohn Forte emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd, stmf_data_buf_t *dbuf,
2536fcf3ce44SJohn Forte     uint32_t ioflags)
2537fcf3ce44SJohn Forte {
2538fcf3ce44SJohn Forte 	emlxs_port_t *port =
2539fcf3ce44SJohn Forte 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
2540fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2541fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
2542291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
2543fcf3ce44SJohn Forte 	scsi_task_t *fct_task;
2544291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2545fcf3ce44SJohn Forte 	IOCBQ *iocbq;
2546fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
2547fcf3ce44SJohn Forte 
254882527734SSukumar Swaminathan 	int	channel;
254982527734SSukumar Swaminathan 	int	channelno;
2550b3660a96SSukumar Swaminathan 	fct_status_t rval = 0;
2551fcf3ce44SJohn Forte 
255282527734SSukumar Swaminathan 	rval = emlxs_fct_cmd_accept(port, fct_cmd, EMLXS_FCT_SEND_FCP_DATA);
255382527734SSukumar Swaminathan 	if (rval) {
255482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
255582527734SSukumar Swaminathan 		    "emlxs_fct_send_fcp_data: "
255682527734SSukumar Swaminathan 		    "Unable to accept fct_cmd. did=%x",
255782527734SSukumar Swaminathan 		    fct_cmd->cmd_rportid);
2558fcf3ce44SJohn Forte 
255982527734SSukumar Swaminathan 		return (rval);
2560fcf3ce44SJohn Forte 	}
256182527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2562291a2b48SSukumar Swaminathan 
256382527734SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
256482527734SSukumar Swaminathan #ifdef FCT_API_TRACE
256582527734SSukumar Swaminathan 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
256682527734SSukumar Swaminathan #endif /* FCT_API_TRACE */
256782527734SSukumar Swaminathan 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
2568291a2b48SSukumar Swaminathan 
2569fcf3ce44SJohn Forte 	cmd_sbp->node = ndlp;
2570fcf3ce44SJohn Forte 	cmd_sbp->fct_buf = dbuf;
2571fcf3ce44SJohn Forte 
257282527734SSukumar Swaminathan 	channelno = ((CHANNEL *)cmd_sbp->channel)->channelno;
257382527734SSukumar Swaminathan 
257482527734SSukumar Swaminathan 	channel = channelno;
257582527734SSukumar Swaminathan 
257682527734SSukumar Swaminathan 
257782527734SSukumar Swaminathan 
2578fcf3ce44SJohn Forte 	iocbq = &cmd_sbp->iocbq;
2579fcf3ce44SJohn Forte 
2580fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2581fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
258282527734SSukumar Swaminathan 	    "emlxs_fct_send_fcp_data %p: flgs=%x ioflags=%x dl=%d,%d,%d, %d",
2583fcf3ce44SJohn Forte 	    fct_cmd, dbuf->db_flags, ioflags, fct_task->task_cmd_xfer_length,
258482527734SSukumar Swaminathan 	    fct_task->task_nbytes_transferred, dbuf->db_data_size,
258582527734SSukumar Swaminathan 	    fct_task->task_expected_xfer_length);
2586291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2587fcf3ce44SJohn Forte 
258882527734SSukumar Swaminathan 	if (EMLXS_SLI_PREP_FCT_IOCB(port, cmd_sbp, channel) != IOERR_SUCCESS) {
258982527734SSukumar Swaminathan 
2590fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
259182527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2592fcf3ce44SJohn Forte 
2593fcf3ce44SJohn Forte 		return (FCT_BUSY);
2594fcf3ce44SJohn Forte 	}
2595291a2b48SSukumar Swaminathan 
2596fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_FCP_DATA;
2597fcf3ce44SJohn Forte 
2598fcf3ce44SJohn Forte 	if (dbuf->db_flags & DB_SEND_STATUS_GOOD) {
2599fcf3ce44SJohn Forte 		cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
2600fcf3ce44SJohn Forte 	}
2601fcf3ce44SJohn Forte 
2602fcf3ce44SJohn Forte 	if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
2603b3660a96SSukumar Swaminathan 		if (emlxs_fct_dbuf_dma_sync(hba, dbuf, DDI_DMA_SYNC_FORDEV)) {
2604b3660a96SSukumar Swaminathan 			emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
2605b3660a96SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
2606b3660a96SSukumar Swaminathan 
2607b3660a96SSukumar Swaminathan 			return (FCT_BUSY);
2608b3660a96SSukumar Swaminathan 		}
2609fcf3ce44SJohn Forte 	}
2610291a2b48SSukumar Swaminathan 
2611291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
261282527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_DATA_PENDING);
261382527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
261482527734SSukumar Swaminathan 
261582527734SSukumar Swaminathan 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cmd_sbp->channel, iocbq);
2616fcf3ce44SJohn Forte 
2617fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
2618fcf3ce44SJohn Forte 
261982527734SSukumar Swaminathan } /* emlxs_fct_send_fcp_data() */
2620fcf3ce44SJohn Forte 
2621fcf3ce44SJohn Forte 
262282527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
262382527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be released before exiting */
2624fcf3ce44SJohn Forte static fct_status_t
2625fcf3ce44SJohn Forte emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd)
2626fcf3ce44SJohn Forte {
2627fcf3ce44SJohn Forte 	emlxs_port_t *port =
2628fcf3ce44SJohn Forte 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
2629fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2630fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
2631fcf3ce44SJohn Forte 	scsi_task_t *fct_task;
2632fcf3ce44SJohn Forte 	fc_packet_t *pkt;
2633fcf3ce44SJohn Forte 	uint32_t did;
2634fcf3ce44SJohn Forte 	emlxs_fcp_rsp *fcp_rsp;
2635fcf3ce44SJohn Forte 	uint32_t size;
2636fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
263782527734SSukumar Swaminathan 	fct_status_t rval;
2638fcf3ce44SJohn Forte 
2639fcf3ce44SJohn Forte 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
2640fcf3ce44SJohn Forte 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
2641fcf3ce44SJohn Forte 	did = fct_cmd->cmd_rportid;
2642fcf3ce44SJohn Forte 
2643fcf3ce44SJohn Forte 	/* Initialize cmd_sbp */
2644fcf3ce44SJohn Forte 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2645fcf3ce44SJohn Forte 
264682527734SSukumar Swaminathan 	EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_SEND_FCP_STATUS);
2647291a2b48SSukumar Swaminathan 
2648fcf3ce44SJohn Forte 	cmd_sbp->node = ndlp;
2649fcf3ce44SJohn Forte 
2650fcf3ce44SJohn Forte 	size = 24;
2651fcf3ce44SJohn Forte 	if (fct_task->task_sense_length) {
2652fcf3ce44SJohn Forte 		size += fct_task->task_sense_length;
2653fcf3ce44SJohn Forte 	}
2654fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2655fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2656fcf3ce44SJohn Forte 	    "emlxs_fct_send_fcp_status %p: stat=%d resid=%d size=%d rx=%x",
2657fcf3ce44SJohn Forte 	    fct_cmd, fct_task->task_scsi_status,
2658fcf3ce44SJohn Forte 	    fct_task->task_resid, size, fct_cmd->cmd_rxid);
2659291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2660fcf3ce44SJohn Forte 
2661fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) {
2662fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2663fcf3ce44SJohn Forte 		    "emlxs_fct_send_fcp_status: Unable to allocate packet.");
2664fcf3ce44SJohn Forte 
2665fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
266682527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2667fcf3ce44SJohn Forte 
2668291a2b48SSukumar Swaminathan 		return (FCT_BUSY);
2669fcf3ce44SJohn Forte 	}
2670291a2b48SSukumar Swaminathan 
2671fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_FCP_STATUS;
2672fcf3ce44SJohn Forte 
2673fcf3ce44SJohn Forte 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
2674291a2b48SSukumar Swaminathan 	cmd_sbp->fct_pkt = pkt;
2675fcf3ce44SJohn Forte 
2676fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2677fcf3ce44SJohn Forte 	pkt->pkt_timeout =
2678fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
2679fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_fct_pkt_comp;
2680fcf3ce44SJohn Forte 
2681fcf3ce44SJohn Forte 	/* Build the fc header */
268282527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
2683fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
268482527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
2685fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP;
2686fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
2687fcf3ce44SJohn Forte 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2688fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
2689fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2690fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2691fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
2692fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
2693fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
2694fcf3ce44SJohn Forte 
2695fcf3ce44SJohn Forte 	/* Build the status payload */
2696fcf3ce44SJohn Forte 	fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd;
2697fcf3ce44SJohn Forte 
2698fcf3ce44SJohn Forte 	if (fct_task->task_resid) {
2699fcf3ce44SJohn Forte 		if (fct_task->task_status_ctrl & TASK_SCTRL_OVER) {
2700fcf3ce44SJohn Forte 			TGTPORTSTAT.FctScsiResidOver++;
2701fcf3ce44SJohn Forte 			fcp_rsp->rspStatus2 |= RESID_OVER;
270282527734SSukumar Swaminathan 			fcp_rsp->rspResId = LE_SWAP32(fct_task->task_resid);
2703fcf3ce44SJohn Forte 
2704fcf3ce44SJohn Forte 		} else if (fct_task->task_status_ctrl & TASK_SCTRL_UNDER) {
2705fcf3ce44SJohn Forte 			TGTPORTSTAT.FctScsiResidUnder++;
2706fcf3ce44SJohn Forte 			fcp_rsp->rspStatus2 |= RESID_UNDER;
270782527734SSukumar Swaminathan 			fcp_rsp->rspResId = LE_SWAP32(fct_task->task_resid);
2708fcf3ce44SJohn Forte 
2709fcf3ce44SJohn Forte 		}
2710fcf3ce44SJohn Forte 	}
2711291a2b48SSukumar Swaminathan 
2712fcf3ce44SJohn Forte 	if (fct_task->task_scsi_status) {
2713fcf3ce44SJohn Forte 		if (fct_task->task_scsi_status == SCSI_STAT_QUE_FULL) {
2714fcf3ce44SJohn Forte 			TGTPORTSTAT.FctScsiQfullErr++;
2715fcf3ce44SJohn Forte 		} else {
2716fcf3ce44SJohn Forte 			TGTPORTSTAT.FctScsiStatusErr++;
2717fcf3ce44SJohn Forte 		}
2718fcf3ce44SJohn Forte 
2719291a2b48SSukumar Swaminathan 		/* Make sure residual reported on non-SCSI_GOOD READ status */
2720fcf3ce44SJohn Forte 		if ((fct_task->task_flags & TF_READ_DATA) &&
2721fcf3ce44SJohn Forte 		    (fcp_rsp->rspResId == 0)) {
2722fcf3ce44SJohn Forte 			fcp_rsp->rspStatus2 |= RESID_UNDER;
2723291a2b48SSukumar Swaminathan 			fcp_rsp->rspResId =
2724291a2b48SSukumar Swaminathan 			    fct_task->task_expected_xfer_length;
2725fcf3ce44SJohn Forte 		}
2726fcf3ce44SJohn Forte 	}
2727291a2b48SSukumar Swaminathan 
2728291a2b48SSukumar Swaminathan 
2729fcf3ce44SJohn Forte 	if (fct_task->task_sense_length) {
2730fcf3ce44SJohn Forte 		TGTPORTSTAT.FctScsiSenseErr++;
2731fcf3ce44SJohn Forte 		fcp_rsp->rspStatus2 |= SNS_LEN_VALID;
273282527734SSukumar Swaminathan 		fcp_rsp->rspSnsLen = LE_SWAP32(fct_task->task_sense_length);
2733fcf3ce44SJohn Forte 
2734fcf3ce44SJohn Forte 		bcopy((uint8_t *)fct_task->task_sense_data,
2735291a2b48SSukumar Swaminathan 		    (uint8_t *)&fcp_rsp->rspInfo0,
2736291a2b48SSukumar Swaminathan 		    fct_task->task_sense_length);
2737fcf3ce44SJohn Forte 	}
2738291a2b48SSukumar Swaminathan 
2739fcf3ce44SJohn Forte 	fcp_rsp->rspStatus3 = fct_task->task_scsi_status;
2740fcf3ce44SJohn Forte 	fcp_rsp->rspRspLen = 0;
274182527734SSukumar Swaminathan 
2742291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
274382527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_STATUS_PENDING);
274482527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
2745fcf3ce44SJohn Forte 
2746fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
274782527734SSukumar Swaminathan 
2748fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2749fcf3ce44SJohn Forte 		    "emlxs_fct_send_fcp_status: Unable to send packet.");
2750fcf3ce44SJohn Forte 
275182527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
275282527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
275382527734SSukumar Swaminathan 		if (rval) {
275482527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
275582527734SSukumar Swaminathan 			    "emlxs_fct_send_fcp_status: "
275682527734SSukumar Swaminathan 			    "Unable to acquire fct_cmd.");
275782527734SSukumar Swaminathan 			return (rval);
2758fcf3ce44SJohn Forte 		}
275982527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
2760291a2b48SSukumar Swaminathan 
2761fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
276282527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2763291a2b48SSukumar Swaminathan 
2764291a2b48SSukumar Swaminathan 		return (FCT_BUSY);
2765fcf3ce44SJohn Forte 	}
2766291a2b48SSukumar Swaminathan 
2767fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
2768fcf3ce44SJohn Forte 
276982527734SSukumar Swaminathan } /* emlxs_fct_send_fcp_status() */
2770fcf3ce44SJohn Forte 
2771fcf3ce44SJohn Forte 
2772fcf3ce44SJohn Forte static fct_status_t
2773291a2b48SSukumar Swaminathan emlxs_fct_send_qfull_reply(emlxs_port_t *port, emlxs_node_t *ndlp,
2774291a2b48SSukumar Swaminathan     uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd)
2775fcf3ce44SJohn Forte {
2776fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
2777fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
2778fcf3ce44SJohn Forte 	fc_packet_t *pkt;
2779fcf3ce44SJohn Forte 	emlxs_fcp_rsp *fcp_rsp;
2780fcf3ce44SJohn Forte 	uint32_t size;
278182527734SSukumar Swaminathan 	CHANNEL *cp = &hba->chan[hba->CHANNEL_FCT];
2782fcf3ce44SJohn Forte 	uint8_t lun[8];
2783fcf3ce44SJohn Forte 
2784fcf3ce44SJohn Forte 	bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8);
2785fcf3ce44SJohn Forte 	size = 24;
2786fcf3ce44SJohn Forte 
2787fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) {
2788fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2789fcf3ce44SJohn Forte 		    "emlxs_fct_send_qfull_reply: Unable to allocate packet.");
2790fcf3ce44SJohn Forte 		return (FCT_FAILURE);
2791fcf3ce44SJohn Forte 	}
2792291a2b48SSukumar Swaminathan 
2793291a2b48SSukumar Swaminathan 
2794fcf3ce44SJohn Forte 	sbp = PKT2PRIV(pkt);
2795fcf3ce44SJohn Forte 	sbp->node = ndlp;
279682527734SSukumar Swaminathan 	sbp->channel = cp;
2797fcf3ce44SJohn Forte 	sbp->did = ndlp->nlp_DID;
2798fcf3ce44SJohn Forte 	sbp->lun = (lun[0] << 8) | lun[1];
2799fcf3ce44SJohn Forte 	sbp->class = class;
2800fcf3ce44SJohn Forte 
2801fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2802fcf3ce44SJohn Forte 	pkt->pkt_timeout =
2803fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
2804fcf3ce44SJohn Forte 
2805fcf3ce44SJohn Forte 	/* Build the fc header */
280682527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(ndlp->nlp_DID);
2807fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
280882527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
2809fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP;
2810fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
2811fcf3ce44SJohn Forte 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2812fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
2813fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2814fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2815fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
2816fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = xid;
2817fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
2818fcf3ce44SJohn Forte 
2819fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2820fcf3ce44SJohn Forte 	    "emlxs_fct_send_qfull_reply: Sending QFULL: x%x lun x%x: %d %d",
2821fcf3ce44SJohn Forte 	    xid, sbp->lun, TGTPORTSTAT.FctOutstandingIO,
2822fcf3ce44SJohn Forte 	    port->fct_port->port_max_xchges);
2823fcf3ce44SJohn Forte 
2824fcf3ce44SJohn Forte 	/* Build the status payload */
2825fcf3ce44SJohn Forte 	fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd;
2826fcf3ce44SJohn Forte 
2827fcf3ce44SJohn Forte 	TGTPORTSTAT.FctScsiQfullErr++;
2828fcf3ce44SJohn Forte 	fcp_rsp->rspStatus3 = SCSI_STAT_QUE_FULL;
2829fcf3ce44SJohn Forte 	fcp_rsp->rspStatus2 |= RESID_UNDER;
283082527734SSukumar Swaminathan 	fcp_rsp->rspResId = LE_SWAP32(fcp_cmd->fcpDl);
2831fcf3ce44SJohn Forte 
2832fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2833fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2834fcf3ce44SJohn Forte 		    "emlxs_fct_send_qfull_reply: Unable to send packet.");
2835fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
2836fcf3ce44SJohn Forte 		return (FCT_FAILURE);
2837fcf3ce44SJohn Forte 	}
2838fcf3ce44SJohn Forte 
2839291a2b48SSukumar Swaminathan 	return (FCT_SUCCESS);
2840fcf3ce44SJohn Forte 
284182527734SSukumar Swaminathan } /* emlxs_fct_send_qfull_reply() */
2842fcf3ce44SJohn Forte 
2843fcf3ce44SJohn Forte 
2844fcf3ce44SJohn Forte /* ARGSUSED */
2845fcf3ce44SJohn Forte extern int
284682527734SSukumar Swaminathan emlxs_fct_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2847fcf3ce44SJohn Forte {
2848fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2849fcf3ce44SJohn Forte 	IOCB *iocb;
2850fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
2851fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
2852fcf3ce44SJohn Forte 	uint32_t status;
2853fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
2854fcf3ce44SJohn Forte 	stmf_data_buf_t *dbuf;
2855fcf3ce44SJohn Forte 	scsi_task_t *fct_task;
2856291a2b48SSukumar Swaminathan 	fc_packet_t *pkt;
285782527734SSukumar Swaminathan 	uint32_t fct_flags;
285882527734SSukumar Swaminathan 	stmf_data_buf_t *fct_buf;
285982527734SSukumar Swaminathan 	fct_status_t rval;
2860fcf3ce44SJohn Forte 
2861fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
2862fcf3ce44SJohn Forte 	sbp = (emlxs_buf_t *)iocbq->sbp;
2863fcf3ce44SJohn Forte 
2864fcf3ce44SJohn Forte 	TGTPORTSTAT.FctEvent++;
2865fcf3ce44SJohn Forte 
2866fcf3ce44SJohn Forte 	if (!sbp) {
2867fcf3ce44SJohn Forte 		/* completion with missing xmit command */
2868fcf3ce44SJohn Forte 		TGTPORTSTAT.FctStray++;
2869fcf3ce44SJohn Forte 
2870fcf3ce44SJohn Forte 		/* emlxs_stray_fcp_completion_msg */
2871fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2872291a2b48SSukumar Swaminathan 		    "FCP event cmd=%x status=%x error=%x iotag=%x",
287382527734SSukumar Swaminathan 		    iocb->ULPCOMMAND, iocb->ULPSTATUS,
287482527734SSukumar Swaminathan 		    iocb->un.grsp.perr.statLocalError, iocb->ULPIOTAG);
2875fcf3ce44SJohn Forte 
2876fcf3ce44SJohn Forte 		return (1);
2877fcf3ce44SJohn Forte 	}
2878291a2b48SSukumar Swaminathan 
2879fcf3ce44SJohn Forte 	TGTPORTSTAT.FctCompleted++;
2880fcf3ce44SJohn Forte 
2881fcf3ce44SJohn Forte 	port = sbp->iocbq.port;
2882fcf3ce44SJohn Forte 	fct_cmd = sbp->fct_cmd;
288382527734SSukumar Swaminathan 	status = iocb->ULPSTATUS;
2884fcf3ce44SJohn Forte 
2885fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2886fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
288782527734SSukumar Swaminathan 	    "emlxs_fct_handle_fcp_event: %p: cmd=%x status=%x, %x",
288882527734SSukumar Swaminathan 	    fct_cmd, iocb->ULPCOMMAND, status, iocb->ULPCT);
2889291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
2890fcf3ce44SJohn Forte 
2891fcf3ce44SJohn Forte 	if (fct_cmd == NULL) {
2892291a2b48SSukumar Swaminathan 		/* For driver generated QFULL response */
289382527734SSukumar Swaminathan 		if (((iocb->ULPCOMMAND == CMD_FCP_TRSP_CX) ||
289482527734SSukumar Swaminathan 		    (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX)) && sbp->pkt) {
2895fcf3ce44SJohn Forte 			emlxs_pkt_free(sbp->pkt);
2896fcf3ce44SJohn Forte 		}
2897fcf3ce44SJohn Forte 		return (0);
2898fcf3ce44SJohn Forte 	}
2899291a2b48SSukumar Swaminathan 
290082527734SSukumar Swaminathan 	rval = emlxs_fct_cmd_acquire(port, fct_cmd, EMLXS_FCT_REQ_COMPLETE);
290182527734SSukumar Swaminathan 	if (rval) {
290282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
290382527734SSukumar Swaminathan 		    "emlxs_fct_handle_fcp_event: "
290482527734SSukumar Swaminathan 		    "Unable to reacquire fct_cmd. type=%x",
290582527734SSukumar Swaminathan 		    fct_cmd->cmd_type);
290682527734SSukumar Swaminathan 
290782527734SSukumar Swaminathan 		return (1);
2908291a2b48SSukumar Swaminathan 	}
290982527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2910291a2b48SSukumar Swaminathan 
2911fcf3ce44SJohn Forte 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
291282527734SSukumar Swaminathan 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
2913291a2b48SSukumar Swaminathan 
2914291a2b48SSukumar Swaminathan 	pkt = cmd_sbp->fct_pkt;
291582527734SSukumar Swaminathan 	cmd_sbp->fct_pkt = NULL;
2916fcf3ce44SJohn Forte 
291782527734SSukumar Swaminathan 	dbuf = sbp->fct_buf;
2918fcf3ce44SJohn Forte 
2919291a2b48SSukumar Swaminathan 	fct_cmd->cmd_comp_status = FCT_SUCCESS;
2920291a2b48SSukumar Swaminathan 
2921291a2b48SSukumar Swaminathan 	if (status) {
2922b3660a96SSukumar Swaminathan emlxs_dma_error:
2923fcf3ce44SJohn Forte 		/*
2924291a2b48SSukumar Swaminathan 		 * The error indicates this IO should be terminated
2925291a2b48SSukumar Swaminathan 		 * immediately.
2926fcf3ce44SJohn Forte 		 */
2927291a2b48SSukumar Swaminathan 		cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
292882527734SSukumar Swaminathan 		fct_cmd->cmd_comp_status = FCT_FAILURE;
2929291a2b48SSukumar Swaminathan 
293082527734SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
293182527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2932291a2b48SSukumar Swaminathan 
2933291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
2934291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2935291a2b48SSukumar Swaminathan 		    "fct_queue_cmd_for_termination:1 %p: x%x",
2936291a2b48SSukumar Swaminathan 		    fct_cmd, fct_cmd->cmd_comp_status);
2937291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
293882527734SSukumar Swaminathan 
2939291a2b48SSukumar Swaminathan 		MODSYM(fct_queue_cmd_for_termination) (fct_cmd,
2940291a2b48SSukumar Swaminathan 		    FCT_ABTS_RECEIVED);
294182527734SSukumar Swaminathan 
2942291a2b48SSukumar Swaminathan 		goto done;
2943291a2b48SSukumar Swaminathan 	}
2944291a2b48SSukumar Swaminathan 
294582527734SSukumar Swaminathan 	switch (iocb->ULPCOMMAND) {
2946291a2b48SSukumar Swaminathan 
2947291a2b48SSukumar Swaminathan 	/*
2948291a2b48SSukumar Swaminathan 	 *  FCP Data completion
2949291a2b48SSukumar Swaminathan 	 */
2950fcf3ce44SJohn Forte 	case CMD_FCP_TSEND_CX:
2951fcf3ce44SJohn Forte 	case CMD_FCP_TSEND64_CX:
2952fcf3ce44SJohn Forte 	case CMD_FCP_TRECEIVE_CX:
2953fcf3ce44SJohn Forte 	case CMD_FCP_TRECEIVE64_CX:
2954fcf3ce44SJohn Forte 
295582527734SSukumar Swaminathan 		if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) {
2956b3660a96SSukumar Swaminathan 			if (emlxs_fct_dbuf_dma_sync(hba, dbuf,
2957b3660a96SSukumar Swaminathan 			    DDI_DMA_SYNC_FORCPU)) {
2958b3660a96SSukumar Swaminathan 				goto emlxs_dma_error;
2959b3660a96SSukumar Swaminathan 			}
296082527734SSukumar Swaminathan 		}
2961fcf3ce44SJohn Forte 
296282527734SSukumar Swaminathan 		if ((cmd_sbp->fct_flags & EMLXS_FCT_SEND_STATUS) &&
296382527734SSukumar Swaminathan 		    (iocb->ULPCT != 1)) {
2964291a2b48SSukumar Swaminathan 
296582527734SSukumar Swaminathan 			dbuf->db_flags |= DB_STATUS_GOOD_SENT;
2966fcf3ce44SJohn Forte 
296782527734SSukumar Swaminathan 			fct_task =
296882527734SSukumar Swaminathan 			    (scsi_task_t *)fct_cmd->cmd_specific;
296982527734SSukumar Swaminathan 			fct_task->task_scsi_status = 0;
2970fcf3ce44SJohn Forte 
297182527734SSukumar Swaminathan 			(void) emlxs_fct_send_fcp_status(fct_cmd);
297282527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
2973fcf3ce44SJohn Forte 
297482527734SSukumar Swaminathan 			break;
297582527734SSukumar Swaminathan 
297682527734SSukumar Swaminathan 		} else if ((cmd_sbp->fct_flags &
297782527734SSukumar Swaminathan 		    EMLXS_FCT_SEND_STATUS) &&
297882527734SSukumar Swaminathan 		    (iocb->ULPCT == 1)) {
297982527734SSukumar Swaminathan 			/* Auto-resp has been sent out by firmware */
298082527734SSukumar Swaminathan 			/* We can assume this is really a FC_TRSP_CX */
298182527734SSukumar Swaminathan 
298282527734SSukumar Swaminathan 			dbuf->db_flags |= DB_STATUS_GOOD_SENT;
298382527734SSukumar Swaminathan 			fct_task =
298482527734SSukumar Swaminathan 			    (scsi_task_t *)fct_cmd->cmd_specific;
298582527734SSukumar Swaminathan 			fct_task->task_scsi_status = 0;
298682527734SSukumar Swaminathan 
298782527734SSukumar Swaminathan 			cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
298882527734SSukumar Swaminathan 
298982527734SSukumar Swaminathan 			goto auto_resp;
2990fcf3ce44SJohn Forte 		}
2991291a2b48SSukumar Swaminathan 
2992fcf3ce44SJohn Forte 		cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
2993fcf3ce44SJohn Forte 
2994fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
299582527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
299682527734SSukumar Swaminathan 
2997fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
2998fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2999fcf3ce44SJohn Forte 		    "fct_scsi_data_xfer_done:1 %p %p", fct_cmd, dbuf);
3000291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
300182527734SSukumar Swaminathan 
3002fcf3ce44SJohn Forte 		MODSYM(fct_scsi_data_xfer_done) (fct_cmd, dbuf, 0);
3003fcf3ce44SJohn Forte 
3004fcf3ce44SJohn Forte 		break;
3005fcf3ce44SJohn Forte 
3006fcf3ce44SJohn Forte 		/* FCP Status completion */
3007fcf3ce44SJohn Forte 	case CMD_FCP_TRSP_CX:
3008fcf3ce44SJohn Forte 	case CMD_FCP_TRSP64_CX:
3009fcf3ce44SJohn Forte 
301082527734SSukumar Swaminathan auto_resp:
301182527734SSukumar Swaminathan 		/* Copy these before calling emlxs_fct_cmd_done */
301282527734SSukumar Swaminathan 		fct_flags = cmd_sbp->fct_flags;
301382527734SSukumar Swaminathan 		fct_buf = cmd_sbp->fct_buf;
3014fcf3ce44SJohn Forte 
301582527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
301682527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3017fcf3ce44SJohn Forte 
301882527734SSukumar Swaminathan 		TGTPORTSTAT.FctOutstandingIO--;
3019fcf3ce44SJohn Forte 
302082527734SSukumar Swaminathan 		if (fct_flags & EMLXS_FCT_SEND_STATUS) {
3021fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3022fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3023fcf3ce44SJohn Forte 			    "fct_scsi_data_xfer_done:2 %p %p",
302482527734SSukumar Swaminathan 			    fct_cmd, fct_buf);
3025291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
302682527734SSukumar Swaminathan 
3027fcf3ce44SJohn Forte 			MODSYM(fct_scsi_data_xfer_done) (fct_cmd,
302882527734SSukumar Swaminathan 			    fct_buf, FCT_IOF_FCA_DONE);
3029fcf3ce44SJohn Forte 		} else {
3030fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3031fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3032fcf3ce44SJohn Forte 			    "fct_send_response_done:1 %p: x%x",
3033fcf3ce44SJohn Forte 			    fct_cmd, fct_cmd->cmd_comp_status);
3034291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
303582527734SSukumar Swaminathan 
3036fcf3ce44SJohn Forte 			MODSYM(fct_send_response_done) (fct_cmd,
3037fcf3ce44SJohn Forte 			    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
3038fcf3ce44SJohn Forte 		}
3039fcf3ce44SJohn Forte 		break;
3040fcf3ce44SJohn Forte 
3041fcf3ce44SJohn Forte 	default:
304282527734SSukumar Swaminathan 		emlxs_fct_cmd_release(port, fct_cmd, 0);
304382527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3044291a2b48SSukumar Swaminathan 
3045fcf3ce44SJohn Forte 		TGTPORTSTAT.FctStray++;
3046fcf3ce44SJohn Forte 		TGTPORTSTAT.FctCompleted--;
3047fcf3ce44SJohn Forte 
3048fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
304982527734SSukumar Swaminathan 		    "Invalid iocb: cmd=0x%x", iocb->ULPCOMMAND);
3050fcf3ce44SJohn Forte 
3051291a2b48SSukumar Swaminathan 		if (pkt) {
3052291a2b48SSukumar Swaminathan 			emlxs_pkt_complete(sbp, status,
3053291a2b48SSukumar Swaminathan 			    iocb->un.grsp.perr.statLocalError, 1);
3054291a2b48SSukumar Swaminathan 		}
3055fcf3ce44SJohn Forte 
305682527734SSukumar Swaminathan 	}	/* switch(iocb->ULPCOMMAND) */
3057fcf3ce44SJohn Forte 
3058fcf3ce44SJohn Forte 
3059291a2b48SSukumar Swaminathan done:
3060291a2b48SSukumar Swaminathan 	if (pkt) {
3061291a2b48SSukumar Swaminathan 		emlxs_pkt_free(pkt);
3062291a2b48SSukumar Swaminathan 	}
3063291a2b48SSukumar Swaminathan 
3064fcf3ce44SJohn Forte 	if (status == IOSTAT_SUCCESS) {
3065fcf3ce44SJohn Forte 		TGTPORTSTAT.FctCmplGood++;
3066fcf3ce44SJohn Forte 	} else {
3067fcf3ce44SJohn Forte 		TGTPORTSTAT.FctCmplError++;
3068fcf3ce44SJohn Forte 	}
3069fcf3ce44SJohn Forte 
3070fcf3ce44SJohn Forte 	return (0);
3071fcf3ce44SJohn Forte 
307282527734SSukumar Swaminathan } /* emlxs_fct_handle_fcp_event() */
3073291a2b48SSukumar Swaminathan 
3074291a2b48SSukumar Swaminathan 
3075291a2b48SSukumar Swaminathan /* ARGSUSED */
3076291a2b48SSukumar Swaminathan extern int
307782527734SSukumar Swaminathan emlxs_fct_handle_abort(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
3078291a2b48SSukumar Swaminathan {
3079291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3080291a2b48SSukumar Swaminathan 	IOCB *iocb;
3081291a2b48SSukumar Swaminathan 	emlxs_buf_t *sbp;
3082291a2b48SSukumar Swaminathan 	fc_packet_t *pkt;
3083291a2b48SSukumar Swaminathan 
3084291a2b48SSukumar Swaminathan 	iocb = &iocbq->iocb;
3085291a2b48SSukumar Swaminathan 	sbp = (emlxs_buf_t *)iocbq->sbp;
3086291a2b48SSukumar Swaminathan 
3087291a2b48SSukumar Swaminathan 	TGTPORTSTAT.FctEvent++;
3088291a2b48SSukumar Swaminathan 
3089291a2b48SSukumar Swaminathan 	if (!sbp) {
3090291a2b48SSukumar Swaminathan 		/* completion with missing xmit command */
3091291a2b48SSukumar Swaminathan 		TGTPORTSTAT.FctStray++;
3092291a2b48SSukumar Swaminathan 
3093291a2b48SSukumar Swaminathan 		/* emlxs_stray_fcp_completion_msg */
3094291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3095291a2b48SSukumar Swaminathan 		    "ABORT event cmd=%x status=%x error=%x iotag=%x",
309682527734SSukumar Swaminathan 		    iocb->ULPCOMMAND, iocb->ULPSTATUS,
309782527734SSukumar Swaminathan 		    iocb->un.grsp.perr.statLocalError, iocb->ULPIOTAG);
3098291a2b48SSukumar Swaminathan 
3099291a2b48SSukumar Swaminathan 		return (1);
3100291a2b48SSukumar Swaminathan 	}
3101291a2b48SSukumar Swaminathan 
3102291a2b48SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
3103291a2b48SSukumar Swaminathan 
3104291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
3105291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
310682527734SSukumar Swaminathan 	    "emlxs_fct_handle_abort: %p: xri=%x status=%x", iocb->ULPCONTEXT,
310782527734SSukumar Swaminathan 	    iocb->ULPCOMMAND, iocb->ULPSTATUS);
3108291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
3109291a2b48SSukumar Swaminathan 
3110291a2b48SSukumar Swaminathan 
3111291a2b48SSukumar Swaminathan 	if (pkt) {
3112291a2b48SSukumar Swaminathan 		emlxs_pkt_free(pkt);
3113291a2b48SSukumar Swaminathan 	}
3114291a2b48SSukumar Swaminathan 	return (0);
3115fcf3ce44SJohn Forte 
311682527734SSukumar Swaminathan } /* emlxs_fct_handle_abort() */
3117fcf3ce44SJohn Forte 
3118fcf3ce44SJohn Forte 
3119fcf3ce44SJohn Forte extern int
312082527734SSukumar Swaminathan emlxs_fct_handle_unsol_els(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3121fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
3122fcf3ce44SJohn Forte {
3123fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
3124fcf3ce44SJohn Forte 	IOCB *iocb;
3125fcf3ce44SJohn Forte 	uint32_t cmd_code;
3126fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
3127fcf3ce44SJohn Forte 	fct_els_t *els;
3128fcf3ce44SJohn Forte 	uint32_t sid;
3129fcf3ce44SJohn Forte 	uint32_t padding;
3130fcf3ce44SJohn Forte 	uint8_t *bp;
3131fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
3132fcf3ce44SJohn Forte 	uint32_t rval;
3133fcf3ce44SJohn Forte 
3134fcf3ce44SJohn Forte 	HBASTATS.ElsCmdReceived++;
3135fcf3ce44SJohn Forte 
3136fcf3ce44SJohn Forte 	bp = mp->virt;
3137fcf3ce44SJohn Forte 	cmd_code = (*(uint32_t *)bp) & ELS_CMD_MASK;
3138fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
3139fcf3ce44SJohn Forte 	sid = iocb->un.elsreq.remoteID;
3140fcf3ce44SJohn Forte 
3141fcf3ce44SJohn Forte 	if (!port->fct_port) {
3142fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3143fcf3ce44SJohn Forte 		    "%s: sid=%x. Target unbound. Rejecting...",
3144fcf3ce44SJohn Forte 		    emlxs_elscmd_xlate(cmd_code), sid);
3145fcf3ce44SJohn Forte 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
3146fcf3ce44SJohn Forte 		    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
3147fcf3ce44SJohn Forte 
3148fcf3ce44SJohn Forte 		goto done;
3149fcf3ce44SJohn Forte 	}
3150291a2b48SSukumar Swaminathan 
3151fcf3ce44SJohn Forte 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
3152fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3153fcf3ce44SJohn Forte 		    "%s: sid=%x. Target offline. Rejecting...",
3154fcf3ce44SJohn Forte 		    emlxs_elscmd_xlate(cmd_code), sid);
3155fcf3ce44SJohn Forte 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
3156fcf3ce44SJohn Forte 		    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
3157fcf3ce44SJohn Forte 
3158fcf3ce44SJohn Forte 		goto done;
3159fcf3ce44SJohn Forte 	}
3160291a2b48SSukumar Swaminathan 
3161fcf3ce44SJohn Forte 	/* Process the request */
3162fcf3ce44SJohn Forte 	switch (cmd_code) {
3163fcf3ce44SJohn Forte 	case ELS_CMD_FLOGI:
3164e2ca2865SSukumar Swaminathan 		rval = emlxs_fct_process_unsol_flogi(port, cp, iocbq, mp, size);
3165291a2b48SSukumar Swaminathan 
3166291a2b48SSukumar Swaminathan 		if (!rval) {
3167291a2b48SSukumar Swaminathan 			ELS_PKT *els_pkt = (ELS_PKT *)bp;
3168e2ca2865SSukumar Swaminathan 			fct_flogi_xchg_t fx;
3169e2ca2865SSukumar Swaminathan 
3170e2ca2865SSukumar Swaminathan 			bzero((uint8_t *)&fx, sizeof (fct_flogi_xchg_t));
3171291a2b48SSukumar Swaminathan 
3172291a2b48SSukumar Swaminathan 			/* Save the FLOGI exchange information */
3173e2ca2865SSukumar Swaminathan 			fx.rsvd2 = iocb->ULPCONTEXT;
3174291a2b48SSukumar Swaminathan 			bcopy((caddr_t)&els_pkt->un.logi.nodeName,
3175e2ca2865SSukumar Swaminathan 			    (caddr_t)fx.fx_nwwn, 8);
3176291a2b48SSukumar Swaminathan 			bcopy((caddr_t)&els_pkt->un.logi.portName,
3177e2ca2865SSukumar Swaminathan 			    (caddr_t)fx.fx_pwwn, 8);
3178e2ca2865SSukumar Swaminathan 			fx.fx_sid = sid;
3179e2ca2865SSukumar Swaminathan 			fx.fx_did = iocb->un.elsreq.myID;
3180e2ca2865SSukumar Swaminathan 			fx.fx_fport = els_pkt->un.logi.cmn.fPort;
3181e2ca2865SSukumar Swaminathan 			fx.fx_op = ELS_OP_FLOGI;
3182e2ca2865SSukumar Swaminathan 
3183e2ca2865SSukumar Swaminathan 			emlxs_fct_handle_unsol_flogi(port, &fx, 1);
3184291a2b48SSukumar Swaminathan 		}
3185e2ca2865SSukumar Swaminathan 
3186291a2b48SSukumar Swaminathan 		goto done;
3187fcf3ce44SJohn Forte 
3188fcf3ce44SJohn Forte 	case ELS_CMD_PLOGI:
3189291a2b48SSukumar Swaminathan 		rval =
319082527734SSukumar Swaminathan 		    emlxs_fct_process_unsol_plogi(port, cp, iocbq, mp, size);
3191fcf3ce44SJohn Forte 		break;
3192fcf3ce44SJohn Forte 
3193fcf3ce44SJohn Forte 	default:
3194fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3195fcf3ce44SJohn Forte 		    "%s: sid=0x%x", emlxs_elscmd_xlate(cmd_code), sid);
3196fcf3ce44SJohn Forte 		rval = 0;
3197fcf3ce44SJohn Forte 		break;
3198fcf3ce44SJohn Forte 	}
3199fcf3ce44SJohn Forte 
3200fcf3ce44SJohn Forte 	if (rval) {
3201fcf3ce44SJohn Forte 		goto done;
3202fcf3ce44SJohn Forte 	}
3203291a2b48SSukumar Swaminathan 
3204fcf3ce44SJohn Forte 	padding = (8 - (size & 7)) & 7;
3205fcf3ce44SJohn Forte 
3206fcf3ce44SJohn Forte 	fct_cmd = (fct_cmd_t *)MODSYM(fct_alloc) (FCT_STRUCT_CMD_RCVD_ELS,
3207291a2b48SSukumar Swaminathan 	    (size + padding + GET_STRUCT_SIZE(emlxs_buf_t)),
3208291a2b48SSukumar Swaminathan 	    AF_FORCE_NOSLEEP);
3209fcf3ce44SJohn Forte 
3210fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3211fcf3ce44SJohn Forte 	{
3212fcf3ce44SJohn Forte 		uint32_t *ptr = (uint32_t *)bp;
3213fcf3ce44SJohn Forte 
3214fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3215fcf3ce44SJohn Forte 		    "fct_alloc %p: ELS rcvd: rxid=%x payload: x%x x%x",
321682527734SSukumar Swaminathan 		    fct_cmd, iocb->ULPCONTEXT, *ptr, *(ptr + 1));
3217fcf3ce44SJohn Forte 	}
3218291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
3219fcf3ce44SJohn Forte 
3220fcf3ce44SJohn Forte 	if (fct_cmd == NULL) {
3221fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3222fcf3ce44SJohn Forte 		    "%s: sid=%x. Out of memory. Rejecting...",
3223fcf3ce44SJohn Forte 		    emlxs_elscmd_xlate(cmd_code), sid);
3224fcf3ce44SJohn Forte 
3225fcf3ce44SJohn Forte 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
3226fcf3ce44SJohn Forte 		    LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
3227fcf3ce44SJohn Forte 		goto done;
3228fcf3ce44SJohn Forte 	}
3229291a2b48SSukumar Swaminathan 
3230fcf3ce44SJohn Forte 	/* Initialize fct_cmd */
3231fcf3ce44SJohn Forte 	fct_cmd->cmd_oxid = (cmd_code >> ELS_CMD_SHIFT) & 0xff;
323282527734SSukumar Swaminathan 	fct_cmd->cmd_rxid = iocb->ULPCONTEXT;
3233fcf3ce44SJohn Forte 	fct_cmd->cmd_rportid = sid;
3234fcf3ce44SJohn Forte 	fct_cmd->cmd_lportid = port->did;
323582527734SSukumar Swaminathan 	fct_cmd->cmd_rp_handle = iocb->ULPIOTAG;	/* RPI */
3236fcf3ce44SJohn Forte 	fct_cmd->cmd_port = port->fct_port;
3237fcf3ce44SJohn Forte 
323882527734SSukumar Swaminathan 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_ELS_CMD_RECEIVED);
323982527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
3240fcf3ce44SJohn Forte 
3241291a2b48SSukumar Swaminathan 	/* Initialize cmd_sbp */
324282527734SSukumar Swaminathan 	cmd_sbp->channel = cp;
324382527734SSukumar Swaminathan 	cmd_sbp->class = iocb->ULPCLASS;
3244fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD;
3245291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_PLOGI_RECEIVED;
3246291a2b48SSukumar Swaminathan 
3247fcf3ce44SJohn Forte 	bcopy((uint8_t *)iocb, (uint8_t *)&cmd_sbp->iocbq,
3248fcf3ce44SJohn Forte 	    sizeof (emlxs_iocb_t));
3249fcf3ce44SJohn Forte 
3250fcf3ce44SJohn Forte 	els = (fct_els_t *)fct_cmd->cmd_specific;
3251*a9800bebSGarrett D'Amore 	els->els_req_size = (uint16_t)size;
3252291a2b48SSukumar Swaminathan 	els->els_req_payload =
3253291a2b48SSukumar Swaminathan 	    GET_BYTE_OFFSET(fct_cmd->cmd_fca_private,
3254fcf3ce44SJohn Forte 	    GET_STRUCT_SIZE(emlxs_buf_t));
3255fcf3ce44SJohn Forte 	bcopy(bp, els->els_req_payload, size);
3256fcf3ce44SJohn Forte 
3257e2ca2865SSukumar Swaminathan 
3258e2ca2865SSukumar Swaminathan 	/* Check if Offline */
3259e2ca2865SSukumar Swaminathan 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
3260e2ca2865SSukumar Swaminathan 
3261e2ca2865SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
3262e2ca2865SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3263e2ca2865SSukumar Swaminathan 
3264e2ca2865SSukumar Swaminathan #ifdef FCT_API_TRACE
3265e2ca2865SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3266e2ca2865SSukumar Swaminathan 		    "fct_post_rcvd_cmd:4 %p: portid x%x", fct_cmd,
3267e2ca2865SSukumar Swaminathan 		    fct_cmd->cmd_lportid);
3268e2ca2865SSukumar Swaminathan #endif /* FCT_API_TRACE */
3269e2ca2865SSukumar Swaminathan 
3270e2ca2865SSukumar Swaminathan 		MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
3271e2ca2865SSukumar Swaminathan 
3272e2ca2865SSukumar Swaminathan 		goto done;
3273e2ca2865SSukumar Swaminathan 	}
3274e2ca2865SSukumar Swaminathan 
3275e2ca2865SSukumar Swaminathan 	/* Online */
3276e2ca2865SSukumar Swaminathan 	/* Check if Link up is acked */
3277e2ca2865SSukumar Swaminathan 	if (port->fct_flags & FCT_STATE_LINK_UP_ACKED) {
3278e2ca2865SSukumar Swaminathan 
3279e2ca2865SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
3280e2ca2865SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3281e2ca2865SSukumar Swaminathan 
3282e2ca2865SSukumar Swaminathan #ifdef FCT_API_TRACE
3283e2ca2865SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3284e2ca2865SSukumar Swaminathan 		    "fct_post_rcvd_cmd:1 %p: portid x%x", fct_cmd,
3285e2ca2865SSukumar Swaminathan 		    fct_cmd->cmd_lportid);
3286e2ca2865SSukumar Swaminathan #endif /* FCT_API_TRACE */
3287e2ca2865SSukumar Swaminathan 
3288e2ca2865SSukumar Swaminathan 		MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
3289e2ca2865SSukumar Swaminathan 
3290e2ca2865SSukumar Swaminathan 		goto done;
3291e2ca2865SSukumar Swaminathan 
3292e2ca2865SSukumar Swaminathan 	}
3293e2ca2865SSukumar Swaminathan 
3294e2ca2865SSukumar Swaminathan 	/* Defer processing of fct_cmd till later (after link up ack). */
3295e2ca2865SSukumar Swaminathan 
3296e2ca2865SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_CMD_WAITQ);
3297e2ca2865SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
3298e2ca2865SSukumar Swaminathan 
3299e2ca2865SSukumar Swaminathan 	/* Add cmd_sbp to queue tail */
3300e2ca2865SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
3301e2ca2865SSukumar Swaminathan 
3302e2ca2865SSukumar Swaminathan 	if (port->fct_wait_tail) {
3303e2ca2865SSukumar Swaminathan 		port->fct_wait_tail->next = cmd_sbp;
3304e2ca2865SSukumar Swaminathan 	}
3305e2ca2865SSukumar Swaminathan 	port->fct_wait_tail = cmd_sbp;
3306e2ca2865SSukumar Swaminathan 
3307e2ca2865SSukumar Swaminathan 	if (!port->fct_wait_head) {
3308e2ca2865SSukumar Swaminathan 		port->fct_wait_head = cmd_sbp;
3309e2ca2865SSukumar Swaminathan 	}
3310e2ca2865SSukumar Swaminathan 
3311e2ca2865SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
3312fcf3ce44SJohn Forte 
3313fcf3ce44SJohn Forte done:
3314fcf3ce44SJohn Forte 
3315fcf3ce44SJohn Forte 	return (0);
3316fcf3ce44SJohn Forte 
331782527734SSukumar Swaminathan } /* emlxs_fct_handle_unsol_els() */
3318fcf3ce44SJohn Forte 
3319fcf3ce44SJohn Forte 
3320fcf3ce44SJohn Forte /* ARGSUSED */
3321fcf3ce44SJohn Forte static uint32_t
332282527734SSukumar Swaminathan emlxs_fct_process_unsol_flogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3323fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
3324fcf3ce44SJohn Forte {
3325fcf3ce44SJohn Forte 	IOCB *iocb;
3326fcf3ce44SJohn Forte 	char buffer[64];
3327fcf3ce44SJohn Forte 
3328fcf3ce44SJohn Forte 	buffer[0] = 0;
3329fcf3ce44SJohn Forte 
3330fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
3331fcf3ce44SJohn Forte 
3332fcf3ce44SJohn Forte 	/* Perform processing of FLOGI payload */
3333fcf3ce44SJohn Forte 	if (emlxs_process_unsol_flogi(port, iocbq, mp, size, buffer)) {
3334fcf3ce44SJohn Forte 		return (1);
3335fcf3ce44SJohn Forte 	}
3336291a2b48SSukumar Swaminathan 
3337fe199829SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3338fe199829SSukumar Swaminathan 	    "FLOGI: sid=0x%x xid=%x %s",
3339fe199829SSukumar Swaminathan 	    iocb->un.elsreq.remoteID, iocb->ULPIOTAG, buffer);
3340fcf3ce44SJohn Forte 
3341fcf3ce44SJohn Forte 	return (0);
3342fcf3ce44SJohn Forte 
334382527734SSukumar Swaminathan } /* emlxs_fct_process_unsol_flogi() */
3344fcf3ce44SJohn Forte 
3345fcf3ce44SJohn Forte 
3346fcf3ce44SJohn Forte /* ARGSUSED */
3347fcf3ce44SJohn Forte static uint32_t
334882527734SSukumar Swaminathan emlxs_fct_process_unsol_plogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3349fcf3ce44SJohn Forte     MATCHMAP *mp, uint32_t size)
3350fcf3ce44SJohn Forte {
3351fcf3ce44SJohn Forte 	IOCB *iocb;
3352fcf3ce44SJohn Forte 	char buffer[64];
3353fcf3ce44SJohn Forte 
3354fcf3ce44SJohn Forte 	buffer[0] = 0;
3355fcf3ce44SJohn Forte 
3356fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
3357fcf3ce44SJohn Forte 
3358fcf3ce44SJohn Forte 	/* Perform processing of PLOGI payload */
3359fcf3ce44SJohn Forte 	if (emlxs_process_unsol_plogi(port, iocbq, mp, size, buffer)) {
3360fcf3ce44SJohn Forte 		return (1);
3361fcf3ce44SJohn Forte 	}
3362291a2b48SSukumar Swaminathan 
3363fe199829SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3364fe199829SSukumar Swaminathan 	    "PLOGI: sid=0x%x xid=%x %s",
3365fe199829SSukumar Swaminathan 	    iocb->un.elsreq.remoteID, iocb->ULPIOTAG, buffer);
3366fcf3ce44SJohn Forte 
3367fcf3ce44SJohn Forte 	return (0);
3368fcf3ce44SJohn Forte 
336982527734SSukumar Swaminathan } /* emlxs_fct_process_unsol_plogi() */
3370fcf3ce44SJohn Forte 
3371fcf3ce44SJohn Forte 
3372fcf3ce44SJohn Forte /* ARGSUSED */
3373fcf3ce44SJohn Forte static emlxs_buf_t *
3374291a2b48SSukumar Swaminathan emlxs_fct_pkt_init(emlxs_port_t *port, fct_cmd_t *fct_cmd,
3375291a2b48SSukumar Swaminathan     fc_packet_t *pkt)
3376fcf3ce44SJohn Forte {
3377fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
3378fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
3379fcf3ce44SJohn Forte 
3380fcf3ce44SJohn Forte 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3381fcf3ce44SJohn Forte 
3382fcf3ce44SJohn Forte 	sbp = PKT2PRIV(pkt);
3383fcf3ce44SJohn Forte 	sbp->fct_cmd = cmd_sbp->fct_cmd;
3384fcf3ce44SJohn Forte 	sbp->node = cmd_sbp->node;
338582527734SSukumar Swaminathan 	sbp->channel = cmd_sbp->channel;
3386fcf3ce44SJohn Forte 	sbp->did = cmd_sbp->did;
3387fcf3ce44SJohn Forte 	sbp->lun = cmd_sbp->lun;
3388fcf3ce44SJohn Forte 	sbp->class = cmd_sbp->class;
3389fcf3ce44SJohn Forte 	sbp->fct_type = cmd_sbp->fct_type;
3390fcf3ce44SJohn Forte 	sbp->fct_state = cmd_sbp->fct_state;
3391fcf3ce44SJohn Forte 
3392fcf3ce44SJohn Forte 	return (sbp);
3393fcf3ce44SJohn Forte 
339482527734SSukumar Swaminathan } /* emlxs_fct_pkt_init() */
3395fcf3ce44SJohn Forte 
3396fcf3ce44SJohn Forte 
3397fcf3ce44SJohn Forte /* Mutex will be acquired */
3398fcf3ce44SJohn Forte static emlxs_buf_t *
3399*a9800bebSGarrett D'Amore emlxs_fct_cmd_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state)
3400fcf3ce44SJohn Forte {
3401fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
3402fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3403fcf3ce44SJohn Forte 
3404fcf3ce44SJohn Forte 	bzero((void *)cmd_sbp, sizeof (emlxs_buf_t));
3405291a2b48SSukumar Swaminathan 	mutex_init(&cmd_sbp->fct_mtx, NULL, MUTEX_DRIVER,
3406*a9800bebSGarrett D'Amore 	    DDI_INTR_PRI(hba->intr_arg));
3407*a9800bebSGarrett D'Amore 	mutex_init(&cmd_sbp->mtx, NULL, MUTEX_DRIVER,
3408*a9800bebSGarrett D'Amore 	    DDI_INTR_PRI(hba->intr_arg));
3409fcf3ce44SJohn Forte 
3410291a2b48SSukumar Swaminathan 	mutex_enter(&cmd_sbp->fct_mtx);
3411fcf3ce44SJohn Forte 	cmd_sbp->pkt_flags = PACKET_VALID;
3412fcf3ce44SJohn Forte 	cmd_sbp->port = port;
3413fcf3ce44SJohn Forte 	cmd_sbp->fct_cmd = fct_cmd;
3414fcf3ce44SJohn Forte 	cmd_sbp->node = (fct_cmd->cmd_rp) ?
3415fcf3ce44SJohn Forte 	    *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private : NULL;
3416fcf3ce44SJohn Forte 	cmd_sbp->iocbq.sbp = cmd_sbp;
3417291a2b48SSukumar Swaminathan 	cmd_sbp->iocbq.port = port;
341882527734SSukumar Swaminathan 	cmd_sbp->did = fct_cmd->cmd_rportid;
341982527734SSukumar Swaminathan 
342082527734SSukumar Swaminathan 	/* Flags fct_cmd as inuse */
342182527734SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
342282527734SSukumar Swaminathan 		fct_cmd->cmd_oxid = 0xffff;
342382527734SSukumar Swaminathan 		fct_cmd->cmd_rxid = 0xffff;
342482527734SSukumar Swaminathan 	}
342582527734SSukumar Swaminathan 
342682527734SSukumar Swaminathan 	if (fct_state) {
342782527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
342882527734SSukumar Swaminathan 	}
3429fcf3ce44SJohn Forte 
3430fcf3ce44SJohn Forte 	return (cmd_sbp);
3431fcf3ce44SJohn Forte 
343282527734SSukumar Swaminathan } /* emlxs_fct_cmd_init() */
3433fcf3ce44SJohn Forte 
3434fcf3ce44SJohn Forte 
343582527734SSukumar Swaminathan /* Called after receiving fct_cmd from COMSTAR */
343682527734SSukumar Swaminathan static fct_status_t
343782527734SSukumar Swaminathan emlxs_fct_cmd_accept(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state)
3438fcf3ce44SJohn Forte {
3439fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3440fcf3ce44SJohn Forte 
344182527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
344282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
344382527734SSukumar Swaminathan 		    "emlxs_fct_cmd_accept: "
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 	mutex_enter(&cmd_sbp->fct_mtx);
345182527734SSukumar Swaminathan 
345282527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
345382527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
345482527734SSukumar Swaminathan 
345582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
345682527734SSukumar Swaminathan 		    "emlxs_fct_cmd_accept:2 "
345782527734SSukumar Swaminathan 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
345882527734SSukumar Swaminathan 		    fct_cmd, fct_state);
345982527734SSukumar Swaminathan 
346082527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
346182527734SSukumar Swaminathan 	}
346282527734SSukumar Swaminathan 
346382527734SSukumar Swaminathan 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) {
346482527734SSukumar Swaminathan 
346582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
346682527734SSukumar Swaminathan 		    "emlxs_fct_cmd_accept: "
346782527734SSukumar Swaminathan 		    "Aborted fct_cmd found! fct_cmd=%p state=%x",
346882527734SSukumar Swaminathan 		    fct_cmd, fct_state);
346982527734SSukumar Swaminathan 
347082527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_ABORT_DONE);
347182527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
347282527734SSukumar Swaminathan 
347382527734SSukumar Swaminathan 		MODSYM(fct_cmd_fca_aborted) (fct_cmd,
347482527734SSukumar Swaminathan 		    FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
347582527734SSukumar Swaminathan 
347682527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
347782527734SSukumar Swaminathan 	}
347882527734SSukumar Swaminathan 
347982527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->mtx);
348082527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) {
348182527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->mtx);
348282527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
348382527734SSukumar Swaminathan 
348482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
348582527734SSukumar Swaminathan 		    "emlxs_fct_cmd_accept: "
348682527734SSukumar Swaminathan 		    "Busy fct_cmd found! fct_cmd=%p state=%x",
348782527734SSukumar Swaminathan 		    fct_cmd, fct_state);
348882527734SSukumar Swaminathan 
348982527734SSukumar Swaminathan 		return (FCT_BUSY);
349082527734SSukumar Swaminathan 	}
349182527734SSukumar Swaminathan 	cmd_sbp->pkt_flags &= ~PACKET_ULP_OWNED;
349282527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->mtx);
349382527734SSukumar Swaminathan 
349482527734SSukumar Swaminathan 	if (fct_state) {
349582527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
349682527734SSukumar Swaminathan 	}
349782527734SSukumar Swaminathan 
349882527734SSukumar Swaminathan 	return (FCT_SUCCESS);
349982527734SSukumar Swaminathan 
350082527734SSukumar Swaminathan } /* emlxs_fct_cmd_accept() */
350182527734SSukumar Swaminathan 
350282527734SSukumar Swaminathan 
350382527734SSukumar Swaminathan /* Called after receiving fct_cmd from driver */
350482527734SSukumar Swaminathan static fct_status_t
350582527734SSukumar Swaminathan emlxs_fct_cmd_acquire(emlxs_port_t *port, fct_cmd_t *fct_cmd,
350682527734SSukumar Swaminathan     uint16_t fct_state)
350782527734SSukumar Swaminathan {
350882527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
350982527734SSukumar Swaminathan 
351082527734SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
351182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
351282527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire: "
351382527734SSukumar Swaminathan 		    "Bad fct_cmd found! fct_cmd=%p state=%x",
351482527734SSukumar Swaminathan 		    fct_cmd, fct_state);
351582527734SSukumar Swaminathan 
351682527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
351782527734SSukumar Swaminathan 	}
351882527734SSukumar Swaminathan 
351982527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
352082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
352182527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire: "
352282527734SSukumar Swaminathan 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
352382527734SSukumar Swaminathan 		    fct_cmd, fct_state);
352482527734SSukumar Swaminathan 
352582527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
352682527734SSukumar Swaminathan 	}
352782527734SSukumar Swaminathan 
352882527734SSukumar Swaminathan 	if ((cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) {
352982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
353082527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire: "
353182527734SSukumar Swaminathan 		    "Returned fct_cmd found! fct_cmd=%p state=%x",
353282527734SSukumar Swaminathan 		    fct_cmd, fct_state);
353382527734SSukumar Swaminathan 
353482527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
353582527734SSukumar Swaminathan 	}
353682527734SSukumar Swaminathan 
353782527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->fct_mtx);
353882527734SSukumar Swaminathan 
353982527734SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
354082527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
354182527734SSukumar Swaminathan 
354282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
354382527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire:2 "
354482527734SSukumar Swaminathan 		    "Bad fct_cmd found! fct_cmd=%p state=%x",
354582527734SSukumar Swaminathan 		    fct_cmd, fct_state);
3546291a2b48SSukumar Swaminathan 
354782527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
354882527734SSukumar Swaminathan 	}
3549291a2b48SSukumar Swaminathan 
3550fcf3ce44SJohn Forte 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
355182527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
355282527734SSukumar Swaminathan 
355382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
355482527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire:2 "
355582527734SSukumar Swaminathan 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
355682527734SSukumar Swaminathan 		    fct_cmd, fct_state);
355782527734SSukumar Swaminathan 
355882527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
355982527734SSukumar Swaminathan 	}
356082527734SSukumar Swaminathan 
356182527734SSukumar Swaminathan 	if ((cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) {
356282527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
356382527734SSukumar Swaminathan 
356482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
356582527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire:2 "
356682527734SSukumar Swaminathan 		    "Returned fct_cmd found! fct_cmd=%p state=%x",
356782527734SSukumar Swaminathan 		    fct_cmd, fct_state);
356882527734SSukumar Swaminathan 
356982527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
357082527734SSukumar Swaminathan 	}
357182527734SSukumar Swaminathan 
357282527734SSukumar Swaminathan 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) {
357382527734SSukumar Swaminathan 
357482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
357582527734SSukumar Swaminathan 		    "emlxs_fct_cmd_acquire: "
357682527734SSukumar Swaminathan 		    "Aborting cmd. fct_cmd=%p state=%x",
357782527734SSukumar Swaminathan 		    fct_cmd, fct_state);
357882527734SSukumar Swaminathan 
357982527734SSukumar Swaminathan 		if (fct_cmd->cmd_type == FCT_CMD_FCP_XCHG) {
358082527734SSukumar Swaminathan 			TGTPORTSTAT.FctOutstandingIO--;
358182527734SSukumar Swaminathan 		}
358282527734SSukumar Swaminathan 
358382527734SSukumar Swaminathan 		fct_cmd->cmd_comp_status = FCT_FAILURE;
358482527734SSukumar Swaminathan 
358582527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_ABORT_DONE);
358682527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
358782527734SSukumar Swaminathan 
358882527734SSukumar Swaminathan 		MODSYM(fct_cmd_fca_aborted) (fct_cmd,
358982527734SSukumar Swaminathan 		    FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
359082527734SSukumar Swaminathan 
359182527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
359282527734SSukumar Swaminathan 	}
359382527734SSukumar Swaminathan 
359482527734SSukumar Swaminathan 	if (fct_state) {
359582527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
359682527734SSukumar Swaminathan 	}
359782527734SSukumar Swaminathan 
359882527734SSukumar Swaminathan 	return (FCT_SUCCESS);
359982527734SSukumar Swaminathan 
360082527734SSukumar Swaminathan } /* emlxs_fct_cmd_acquire() */
360182527734SSukumar Swaminathan 
360282527734SSukumar Swaminathan 
360382527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
360482527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be released before exiting */
360582527734SSukumar Swaminathan /* Called before transitionally sending fct_cmd to driver */
360682527734SSukumar Swaminathan /*ARGSUSED*/
360782527734SSukumar Swaminathan static void
360882527734SSukumar Swaminathan emlxs_fct_cmd_release(emlxs_port_t *port, fct_cmd_t *fct_cmd,
360982527734SSukumar Swaminathan     uint16_t fct_state)
361082527734SSukumar Swaminathan {
361182527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
361282527734SSukumar Swaminathan 
361382527734SSukumar Swaminathan 	if (fct_state) {
361482527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
3615fcf3ce44SJohn Forte 	}
3616291a2b48SSukumar Swaminathan 
361782527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->fct_mtx);
361882527734SSukumar Swaminathan 
361982527734SSukumar Swaminathan 	return;
362082527734SSukumar Swaminathan 
362182527734SSukumar Swaminathan } /* emlxs_fct_cmd_release() */
362282527734SSukumar Swaminathan 
362382527734SSukumar Swaminathan 
362482527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
362582527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be released before exiting */
362682527734SSukumar Swaminathan /* Called before posting fct_cmd back to COMSTAR */
362782527734SSukumar Swaminathan /*ARGSUSED*/
362882527734SSukumar Swaminathan static void
362982527734SSukumar Swaminathan emlxs_fct_cmd_post(emlxs_port_t *port, fct_cmd_t *fct_cmd,
363082527734SSukumar Swaminathan     uint16_t fct_state)
363182527734SSukumar Swaminathan {
363282527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
363382527734SSukumar Swaminathan 	fc_packet_t *pkt;
363482527734SSukumar Swaminathan 
363582527734SSukumar Swaminathan 	pkt = cmd_sbp->fct_pkt;
363682527734SSukumar Swaminathan 	cmd_sbp->fct_pkt = NULL;
363782527734SSukumar Swaminathan 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
363882527734SSukumar Swaminathan 
363982527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->mtx);
364082527734SSukumar Swaminathan 	cmd_sbp->pkt_flags |= PACKET_ULP_OWNED;
364182527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->mtx);
364282527734SSukumar Swaminathan 
364382527734SSukumar Swaminathan 	if (fct_state) {
364482527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
364582527734SSukumar Swaminathan 	}
364682527734SSukumar Swaminathan 
364782527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->fct_mtx);
364882527734SSukumar Swaminathan 
364982527734SSukumar Swaminathan 	if (pkt) {
365082527734SSukumar Swaminathan 		emlxs_pkt_free(pkt);
365182527734SSukumar Swaminathan 	}
365282527734SSukumar Swaminathan 
365382527734SSukumar Swaminathan 	return;
365482527734SSukumar Swaminathan 
365582527734SSukumar Swaminathan } /* emlxs_fct_cmd_post() */
365682527734SSukumar Swaminathan 
365782527734SSukumar Swaminathan 
365882527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
365982527734SSukumar Swaminathan /* Called before completing fct_cmd back to COMSTAR */
366082527734SSukumar Swaminathan static void
366182527734SSukumar Swaminathan emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state)
366282527734SSukumar Swaminathan {
366382527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
366482527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
366582527734SSukumar Swaminathan 	fc_packet_t *pkt;
366682527734SSukumar Swaminathan 
366782527734SSukumar Swaminathan 	/* Flags fct_cmd is no longer used */
366882527734SSukumar Swaminathan 	fct_cmd->cmd_oxid = 0;
366982527734SSukumar Swaminathan 	fct_cmd->cmd_rxid = 0;
367082527734SSukumar Swaminathan 
3671fcf3ce44SJohn Forte 	if (cmd_sbp->iotag != 0) {
3672fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
367382527734SSukumar Swaminathan 		    "Pkt still registered! channel=%d iotag=%d sbp=%p",
367482527734SSukumar Swaminathan 		    cmd_sbp->channel, cmd_sbp->iotag, cmd_sbp);
367582527734SSukumar Swaminathan 
367682527734SSukumar Swaminathan 		if (cmd_sbp->channel) {
367782527734SSukumar Swaminathan 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3678*a9800bebSGarrett D'Amore 				emlxs_sli4_free_xri(hba, cmd_sbp, cmd_sbp->xrip,
3679*a9800bebSGarrett D'Amore 				    1);
368082527734SSukumar Swaminathan 			} else {
368182527734SSukumar Swaminathan 				(void) emlxs_unregister_pkt(cmd_sbp->channel,
368282527734SSukumar Swaminathan 				    cmd_sbp->iotag, 0);
368382527734SSukumar Swaminathan 			}
3684fcf3ce44SJohn Forte 
3685fcf3ce44SJohn Forte 		}
3686fcf3ce44SJohn Forte 	}
3687291a2b48SSukumar Swaminathan 
368882527734SSukumar Swaminathan 	pkt = cmd_sbp->fct_pkt;
368982527734SSukumar Swaminathan 	cmd_sbp->fct_pkt = NULL;
369082527734SSukumar Swaminathan 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
369182527734SSukumar Swaminathan 
369282527734SSukumar Swaminathan 	if (fct_state) {
369382527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
369482527734SSukumar Swaminathan 	}
3695fcf3ce44SJohn Forte 
369682527734SSukumar Swaminathan 	mutex_enter(&cmd_sbp->mtx);
369782527734SSukumar Swaminathan 	cmd_sbp->pkt_flags |= PACKET_ULP_OWNED;
369882527734SSukumar Swaminathan 	cmd_sbp->pkt_flags &= ~PACKET_VALID;
369982527734SSukumar Swaminathan 	mutex_exit(&cmd_sbp->mtx);
3700291a2b48SSukumar Swaminathan 	mutex_exit(&cmd_sbp->fct_mtx);
370182527734SSukumar Swaminathan 
370282527734SSukumar Swaminathan 
3703291a2b48SSukumar Swaminathan 	mutex_destroy(&cmd_sbp->fct_mtx);
370482527734SSukumar Swaminathan 	mutex_destroy(&cmd_sbp->mtx);
370582527734SSukumar Swaminathan 
370682527734SSukumar Swaminathan 	if (pkt) {
370782527734SSukumar Swaminathan 		emlxs_pkt_free(pkt);
370882527734SSukumar Swaminathan 	}
3709fcf3ce44SJohn Forte 
371082527734SSukumar Swaminathan 	return;
3711fcf3ce44SJohn Forte 
371282527734SSukumar Swaminathan } /* emlxs_fct_cmd_done() */
3713fcf3ce44SJohn Forte 
3714fcf3ce44SJohn Forte 
3715fcf3ce44SJohn Forte static void
3716fcf3ce44SJohn Forte emlxs_fct_pkt_comp(fc_packet_t *pkt)
3717fcf3ce44SJohn Forte {
3718fcf3ce44SJohn Forte 	emlxs_port_t *port;
3719291a2b48SSukumar Swaminathan #ifdef FMA_SUPPORT
3720291a2b48SSukumar Swaminathan 	emlxs_hba_t *hba;
3721291a2b48SSukumar Swaminathan #endif	/* FMA_SUPPORT */
3722fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
3723fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
3724fcf3ce44SJohn Forte 	fct_cmd_t *fct_cmd;
3725fcf3ce44SJohn Forte 	fct_els_t *fct_els;
3726fcf3ce44SJohn Forte 	fct_sol_ct_t *fct_ct;
372782527734SSukumar Swaminathan 	fct_status_t rval;
3728fcf3ce44SJohn Forte 
3729fcf3ce44SJohn Forte 	sbp = PKT2PRIV(pkt);
3730fcf3ce44SJohn Forte 	port = sbp->port;
3731291a2b48SSukumar Swaminathan #ifdef FMA_SUPPORT
3732291a2b48SSukumar Swaminathan 	hba = HBA;
3733291a2b48SSukumar Swaminathan #endif	/* FMA_SUPPORT */
3734fcf3ce44SJohn Forte 	fct_cmd = sbp->fct_cmd;
3735291a2b48SSukumar Swaminathan 
373682527734SSukumar Swaminathan 	rval = emlxs_fct_cmd_acquire(port, fct_cmd, EMLXS_FCT_PKT_COMPLETE);
373782527734SSukumar Swaminathan 	if (rval) {
373882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
373982527734SSukumar Swaminathan 		    "emlxs_fct_pkt_comp: "
374082527734SSukumar Swaminathan 		    "Unable to reacquire fct_cmd.");
374182527734SSukumar Swaminathan 		return;
3742291a2b48SSukumar Swaminathan 	}
374382527734SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
3744fcf3ce44SJohn Forte 
374582527734SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
374682527734SSukumar Swaminathan 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
3747fcf3ce44SJohn Forte 	cmd_sbp->fct_pkt = NULL;
3748fcf3ce44SJohn Forte 
3749291a2b48SSukumar Swaminathan 	switch (fct_cmd->cmd_type) {
3750291a2b48SSukumar Swaminathan 	case FCT_CMD_FCP_XCHG:
3751291a2b48SSukumar Swaminathan 		if ((pkt->pkt_reason == FC_REASON_ABORTED) ||
3752291a2b48SSukumar Swaminathan 		    (pkt->pkt_reason == FC_REASON_XCHG_DROPPED) ||
3753291a2b48SSukumar Swaminathan 		    (pkt->pkt_reason == FC_REASON_OFFLINE)) {
3754291a2b48SSukumar Swaminathan 			/*
3755291a2b48SSukumar Swaminathan 			 * The error indicates this IO should be terminated
3756291a2b48SSukumar Swaminathan 			 * immediately.
3757291a2b48SSukumar Swaminathan 			 */
3758291a2b48SSukumar Swaminathan 			cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
3759fcf3ce44SJohn Forte 
376082527734SSukumar Swaminathan 			emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
376182527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
3762fcf3ce44SJohn Forte 
3763291a2b48SSukumar Swaminathan #ifdef FCT_API_TRACE
3764291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3765291a2b48SSukumar Swaminathan 			    "fct_queue_cmd_for_termination:2 %p: x%x",
3766291a2b48SSukumar Swaminathan 			    fct_cmd, fct_cmd->cmd_comp_status);
3767291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
376882527734SSukumar Swaminathan 
3769291a2b48SSukumar Swaminathan 			MODSYM(fct_queue_cmd_for_termination) (fct_cmd,
3770291a2b48SSukumar Swaminathan 			    FCT_ABTS_RECEIVED);
377182527734SSukumar Swaminathan 
377282527734SSukumar Swaminathan 			break;
3773291a2b48SSukumar Swaminathan 		}
3774fcf3ce44SJohn Forte 
377582527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3776291a2b48SSukumar Swaminathan 		    EMLXS_FCT_PKT_FCPRSP_COMPLETE);
3777291a2b48SSukumar Swaminathan 
377882527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3779291a2b48SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3780fcf3ce44SJohn Forte 
3781fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3782fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3783fcf3ce44SJohn Forte 		    "fct_send_response_done:2 %p: x%x",
3784fcf3ce44SJohn Forte 		    fct_cmd, fct_cmd->cmd_comp_status);
3785fcf3ce44SJohn Forte #else
3786fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3787fcf3ce44SJohn Forte 		    "emlxs_fct_pkt_comp: fct_send_response_done. dbuf=%p",
3788fcf3ce44SJohn Forte 		    sbp->fct_buf);
3789291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
3790291a2b48SSukumar Swaminathan 
3791291a2b48SSukumar Swaminathan 		TGTPORTSTAT.FctOutstandingIO--;
3792fcf3ce44SJohn Forte 
3793fcf3ce44SJohn Forte 		MODSYM(fct_send_response_done) (fct_cmd,
3794fcf3ce44SJohn Forte 		    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
3795fcf3ce44SJohn Forte 
3796fcf3ce44SJohn Forte 		break;
3797fcf3ce44SJohn Forte 
3798fcf3ce44SJohn Forte 	case FCT_CMD_RCVD_ELS:
3799fcf3ce44SJohn Forte 
380082527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3801291a2b48SSukumar Swaminathan 		    EMLXS_FCT_PKT_ELSRSP_COMPLETE);
3802291a2b48SSukumar Swaminathan 
380382527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3804291a2b48SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3805fcf3ce44SJohn Forte 
3806fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3807fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3808fcf3ce44SJohn Forte 		    "fct_send_response_done:3 %p: x%x",
3809fcf3ce44SJohn Forte 		    fct_cmd, fct_cmd->cmd_comp_status);
3810291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
381182527734SSukumar Swaminathan 
3812fcf3ce44SJohn Forte 		MODSYM(fct_send_response_done) (fct_cmd,
3813fcf3ce44SJohn Forte 		    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
3814fcf3ce44SJohn Forte 
3815fcf3ce44SJohn Forte 		break;
3816fcf3ce44SJohn Forte 
3817fcf3ce44SJohn Forte 	case FCT_CMD_SOL_ELS:
3818291a2b48SSukumar Swaminathan 
381982527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3820291a2b48SSukumar Swaminathan 		    EMLXS_FCT_PKT_ELSCMD_COMPLETE);
3821291a2b48SSukumar Swaminathan 
3822fcf3ce44SJohn Forte 		fct_els = (fct_els_t *)fct_cmd->cmd_specific;
3823fcf3ce44SJohn Forte 
3824fcf3ce44SJohn Forte 		if (fct_els->els_resp_payload) {
382582527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0,
3826291a2b48SSukumar Swaminathan 			    pkt->pkt_rsplen, DDI_DMA_SYNC_FORKERNEL);
3827fcf3ce44SJohn Forte 
3828fcf3ce44SJohn Forte 			bcopy((uint8_t *)pkt->pkt_resp,
3829fcf3ce44SJohn Forte 			    (uint8_t *)fct_els->els_resp_payload,
3830fcf3ce44SJohn Forte 			    fct_els->els_resp_size);
3831fcf3ce44SJohn Forte 		}
3832291a2b48SSukumar Swaminathan 
383382527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3834291a2b48SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3835fcf3ce44SJohn Forte 
3836fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3837fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3838fcf3ce44SJohn Forte 		    "fct_send_cmd_done:1 %p: x%x",
3839fcf3ce44SJohn Forte 		    fct_cmd, fct_cmd->cmd_comp_status);
3840291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
384182527734SSukumar Swaminathan 
3842b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3843b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma)
3844b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
3845b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3846b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
3847b3660a96SSukumar Swaminathan 			    "emlxs_fct_pkt_comp: hdl=%p",
3848b3660a96SSukumar Swaminathan 			    pkt->pkt_resp_dma);
3849b3660a96SSukumar Swaminathan 			MODSYM(fct_send_cmd_done) (fct_cmd, FCT_FAILURE,
3850b3660a96SSukumar Swaminathan 			    FCT_IOF_FCA_DONE);
3851b3660a96SSukumar Swaminathan 
3852b3660a96SSukumar Swaminathan 			break;
3853b3660a96SSukumar Swaminathan 		}
3854b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */
3855b3660a96SSukumar Swaminathan 
3856291a2b48SSukumar Swaminathan 		MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS,
3857291a2b48SSukumar Swaminathan 		    FCT_IOF_FCA_DONE);
3858fcf3ce44SJohn Forte 
3859fcf3ce44SJohn Forte 		break;
3860fcf3ce44SJohn Forte 
3861fcf3ce44SJohn Forte 	case FCT_CMD_SOL_CT:
3862291a2b48SSukumar Swaminathan 
386382527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3864291a2b48SSukumar Swaminathan 		    EMLXS_FCT_PKT_CTCMD_COMPLETE);
3865291a2b48SSukumar Swaminathan 
3866fcf3ce44SJohn Forte 		fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific;
3867fcf3ce44SJohn Forte 
3868fcf3ce44SJohn Forte 		if (fct_ct->ct_resp_payload) {
386982527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0,
3870291a2b48SSukumar Swaminathan 			    pkt->pkt_rsplen, DDI_DMA_SYNC_FORKERNEL);
3871fcf3ce44SJohn Forte 
3872fcf3ce44SJohn Forte 			bcopy((uint8_t *)pkt->pkt_resp,
3873fcf3ce44SJohn Forte 			    (uint8_t *)fct_ct->ct_resp_payload,
3874fcf3ce44SJohn Forte 			    fct_ct->ct_resp_size);
3875fcf3ce44SJohn Forte 		}
3876291a2b48SSukumar Swaminathan 
387782527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3878291a2b48SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3879fcf3ce44SJohn Forte 
3880fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
3881fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3882fcf3ce44SJohn Forte 		    "fct_send_cmd_done:2 %p: x%x",
3883fcf3ce44SJohn Forte 		    fct_cmd, fct_cmd->cmd_comp_status);
3884291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
388582527734SSukumar Swaminathan 
3886b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3887b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma)
3888b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
3889b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3890b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
3891b3660a96SSukumar Swaminathan 			    "emlxs_fct_pkt_comp: hdl=%p",
3892b3660a96SSukumar Swaminathan 			    pkt->pkt_resp_dma);
3893b3660a96SSukumar Swaminathan 			MODSYM(fct_send_cmd_done) (fct_cmd, FCT_FAILURE,
3894b3660a96SSukumar Swaminathan 			    FCT_IOF_FCA_DONE);
3895b3660a96SSukumar Swaminathan 
3896b3660a96SSukumar Swaminathan 			break;
3897b3660a96SSukumar Swaminathan 		}
3898b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */
3899291a2b48SSukumar Swaminathan 		MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS,
3900291a2b48SSukumar Swaminathan 		    FCT_IOF_FCA_DONE);
390182527734SSukumar Swaminathan 
3902fcf3ce44SJohn Forte 		break;
3903fcf3ce44SJohn Forte 
3904fcf3ce44SJohn Forte 	default:
3905fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3906fcf3ce44SJohn Forte 		    "emlxs_fct_pkt_comp: Invalid cmd type found. type=%x",
3907fcf3ce44SJohn Forte 		    fct_cmd->cmd_type);
3908fcf3ce44SJohn Forte 
390982527734SSukumar Swaminathan 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
391082527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
391182527734SSukumar Swaminathan 
391282527734SSukumar Swaminathan 		break;
3913fcf3ce44SJohn Forte 	}
3914fcf3ce44SJohn Forte 
3915fcf3ce44SJohn Forte 	emlxs_pkt_free(pkt);
3916fcf3ce44SJohn Forte 	return;
3917fcf3ce44SJohn Forte 
391882527734SSukumar Swaminathan } /* emlxs_fct_pkt_comp() */
3919fcf3ce44SJohn Forte 
3920fcf3ce44SJohn Forte 
3921291a2b48SSukumar Swaminathan static void
3922291a2b48SSukumar Swaminathan emlxs_fct_abort_pkt_comp(fc_packet_t *pkt)
3923fcf3ce44SJohn Forte {
392482527734SSukumar Swaminathan #ifdef FCT_API_TRACE_11
3925291a2b48SSukumar Swaminathan 	emlxs_buf_t *sbp;
3926291a2b48SSukumar Swaminathan 	IOCBQ *iocbq;
3927291a2b48SSukumar Swaminathan 	IOCB *iocb;
3928291a2b48SSukumar Swaminathan 
3929291a2b48SSukumar Swaminathan 	sbp = PKT2PRIV(pkt);
3930291a2b48SSukumar Swaminathan 	iocbq = &sbp->iocbq;
3931291a2b48SSukumar Swaminathan 	iocb = &iocbq->iocb;
3932291a2b48SSukumar Swaminathan 
3933291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3934bce54adfSSukumar Swaminathan 	    "emlxs_fct_abort_pkt_comp: %p: xri=%x status=%x", iocb->ULPCONTEXT,
393582527734SSukumar Swaminathan 	    iocb->ULPCOMMAND, iocb->ULPSTATUS);
3936291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
3937291a2b48SSukumar Swaminathan 
3938291a2b48SSukumar Swaminathan 	emlxs_pkt_free(pkt);
3939291a2b48SSukumar Swaminathan 	return;
3940291a2b48SSukumar Swaminathan 
394182527734SSukumar Swaminathan } /* emlxs_fct_abort_pkt_comp() */
3942291a2b48SSukumar Swaminathan 
3943291a2b48SSukumar Swaminathan 
394482527734SSukumar Swaminathan /* COMSTAR ENTER POINT (INDIRECT) */
3945291a2b48SSukumar Swaminathan static fct_status_t
3946291a2b48SSukumar Swaminathan emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd)
3947291a2b48SSukumar Swaminathan {
3948291a2b48SSukumar Swaminathan 	emlxs_port_t *port =
3949291a2b48SSukumar Swaminathan 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
3950fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
3951fcf3ce44SJohn Forte 	uint32_t did;
3952fcf3ce44SJohn Forte 	fct_els_t *fct_els;
3953fcf3ce44SJohn Forte 	fc_packet_t *pkt;
3954fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
395582527734SSukumar Swaminathan 	fct_status_t rval;
3956fcf3ce44SJohn Forte 
3957fcf3ce44SJohn Forte 	did = fct_cmd->cmd_rportid;
3958fcf3ce44SJohn Forte 	fct_els = (fct_els_t *)fct_cmd->cmd_specific;
3959fcf3ce44SJohn Forte 
3960fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_req_size,
3961fcf3ce44SJohn Forte 	    fct_els->els_resp_size, 0, KM_NOSLEEP))) {
3962fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
3963fcf3ce44SJohn Forte 		    "emlxs_fct_send_els_cmd: Unable to allocate packet.");
396482527734SSukumar Swaminathan 
396582527734SSukumar Swaminathan 		return (FCT_BUSY);
3966fcf3ce44SJohn Forte 	}
3967291a2b48SSukumar Swaminathan 
396882527734SSukumar Swaminathan 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_SEND_ELS_REQ);
3969291a2b48SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
3970291a2b48SSukumar Swaminathan 
397182527734SSukumar Swaminathan 	cmd_sbp->channel = &hba->chan[hba->channel_els];
3972fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_ELS_REQ;
3973fcf3ce44SJohn Forte 
3974fcf3ce44SJohn Forte 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
3975291a2b48SSukumar Swaminathan 	cmd_sbp->fct_pkt = pkt;
3976fcf3ce44SJohn Forte 
3977fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
3978fcf3ce44SJohn Forte 	pkt->pkt_timeout =
3979fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
3980fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_fct_pkt_comp;
3981fcf3ce44SJohn Forte 
3982fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3983fcf3ce44SJohn Forte 	    "emlxs_fct_send_els_cmd: pkt_timeout=%d ratov=%d",
3984fcf3ce44SJohn Forte 	    pkt->pkt_timeout, hba->fc_ratov);
3985fcf3ce44SJohn Forte 
3986fcf3ce44SJohn Forte 	/* Build the fc header */
398782527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
3988fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
398982527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
3990fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3991fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
3992fcf3ce44SJohn Forte 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
3993fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
3994fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
3995fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
3996fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
3997fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
3998fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
3999fcf3ce44SJohn Forte 
4000fcf3ce44SJohn Forte 	/* Copy the cmd payload */
4001fcf3ce44SJohn Forte 	bcopy((uint8_t *)fct_els->els_req_payload, (uint8_t *)pkt->pkt_cmd,
4002fcf3ce44SJohn Forte 	    fct_els->els_req_size);
400382527734SSukumar Swaminathan 
4004291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
400582527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_REQ_PENDING);
400682527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
4007fcf3ce44SJohn Forte 
4008fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
400982527734SSukumar Swaminathan 
4010fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4011fcf3ce44SJohn Forte 		    "emlxs_fct_send_els_cmd: Unable to send packet.");
4012fcf3ce44SJohn Forte 
401382527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
401482527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
401582527734SSukumar Swaminathan 		if (rval) {
401682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
401782527734SSukumar Swaminathan 			    "emlxs_fct_send_els_cmd: "
401882527734SSukumar Swaminathan 			    "Unable to reacquire fct_cmd.");
401982527734SSukumar Swaminathan 			return (rval);
4020fcf3ce44SJohn Forte 		}
402182527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
4022fcf3ce44SJohn Forte 
402382527734SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
402482527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4025fcf3ce44SJohn Forte 
402682527734SSukumar Swaminathan 		return (FCT_BUSY);
4027fcf3ce44SJohn Forte 	}
4028fcf3ce44SJohn Forte 
4029fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
4030fcf3ce44SJohn Forte 
403182527734SSukumar Swaminathan } /* emlxs_fct_send_els_cmd() */
4032fcf3ce44SJohn Forte 
4033fcf3ce44SJohn Forte 
403482527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
403582527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be released before exiting */
4036fcf3ce44SJohn Forte static fct_status_t
4037fcf3ce44SJohn Forte emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd)
4038fcf3ce44SJohn Forte {
4039fcf3ce44SJohn Forte 	emlxs_port_t *port =
4040fcf3ce44SJohn Forte 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
4041fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4042fcf3ce44SJohn Forte 	uint32_t did;
4043fcf3ce44SJohn Forte 	fct_els_t *fct_els;
4044fcf3ce44SJohn Forte 	fc_packet_t *pkt;
4045fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
404682527734SSukumar Swaminathan 	fct_status_t rval;
4047fcf3ce44SJohn Forte 
4048fcf3ce44SJohn Forte 	fct_els = (fct_els_t *)fct_cmd->cmd_specific;
4049fcf3ce44SJohn Forte 	did = fct_cmd->cmd_rportid;
405082527734SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
4051fcf3ce44SJohn Forte 
4052291a2b48SSukumar Swaminathan 	if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_resp_size, 0, 0,
4053291a2b48SSukumar Swaminathan 	    KM_NOSLEEP))) {
4054fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4055fcf3ce44SJohn Forte 		    "emlxs_fct_send_els_rsp: Unable to allocate packet.");
4056291a2b48SSukumar Swaminathan 
4057fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
405882527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4059fcf3ce44SJohn Forte 
406082527734SSukumar Swaminathan 		return (FCT_FAILURE);
406182527734SSukumar Swaminathan 	}
4062291a2b48SSukumar Swaminathan 
406382527734SSukumar Swaminathan 	EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_SEND_ELS_RSP);
4064fcf3ce44SJohn Forte 
4065fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_ELS_RSP;
4066fcf3ce44SJohn Forte 
4067fcf3ce44SJohn Forte 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
4068291a2b48SSukumar Swaminathan 	cmd_sbp->fct_pkt = pkt;
4069fcf3ce44SJohn Forte 
4070fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
4071fcf3ce44SJohn Forte 	pkt->pkt_timeout =
4072fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
4073fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_fct_pkt_comp;
4074fcf3ce44SJohn Forte 
4075fcf3ce44SJohn Forte 	/* Build the fc header */
407682527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
4077fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_RSP;
407882527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
4079fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
4080fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
4081fcf3ce44SJohn Forte 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
4082fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
4083fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4084fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4085fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
4086fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
4087fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
4088fcf3ce44SJohn Forte 
4089fcf3ce44SJohn Forte 	/* Copy the resp payload to pkt_cmd buffer */
4090fcf3ce44SJohn Forte 	bcopy((uint8_t *)fct_els->els_resp_payload, (uint8_t *)pkt->pkt_cmd,
4091fcf3ce44SJohn Forte 	    fct_els->els_resp_size);
409282527734SSukumar Swaminathan 
4093291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
409482527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_RSP_PENDING);
409582527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
4096fcf3ce44SJohn Forte 
4097fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
409882527734SSukumar Swaminathan 
4099fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4100fcf3ce44SJohn Forte 		    "emlxs_fct_send_els_rsp: Unable to send packet.");
4101fcf3ce44SJohn Forte 
410282527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
410382527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
410482527734SSukumar Swaminathan 		if (rval) {
410582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
410682527734SSukumar Swaminathan 			    "emlxs_fct_send_els_rsp: "
410782527734SSukumar Swaminathan 			    "Unable to reacquire fct_cmd.");
410882527734SSukumar Swaminathan 			return (rval);
4109fcf3ce44SJohn Forte 		}
411082527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
4111291a2b48SSukumar Swaminathan 
4112fe199829SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
411382527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4114291a2b48SSukumar Swaminathan 
4115fcf3ce44SJohn Forte 		return (FCT_FAILURE);
4116fcf3ce44SJohn Forte 	}
4117fcf3ce44SJohn Forte 
4118291a2b48SSukumar Swaminathan 	return (FCT_SUCCESS);
4119fcf3ce44SJohn Forte 
412082527734SSukumar Swaminathan } /* emlxs_fct_send_els_rsp() */
4121fcf3ce44SJohn Forte 
4122fcf3ce44SJohn Forte 
412382527734SSukumar Swaminathan /* COMSTAR ENTER POINT (INDIRECT) */
4124fcf3ce44SJohn Forte static fct_status_t
4125fcf3ce44SJohn Forte emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd)
4126fcf3ce44SJohn Forte {
4127fcf3ce44SJohn Forte 	emlxs_port_t *port =
4128fcf3ce44SJohn Forte 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
4129fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4130fcf3ce44SJohn Forte 	uint32_t did;
4131fcf3ce44SJohn Forte 	fct_sol_ct_t *fct_ct;
4132fcf3ce44SJohn Forte 	fc_packet_t *pkt;
4133fcf3ce44SJohn Forte 	emlxs_buf_t *cmd_sbp;
413482527734SSukumar Swaminathan 	fct_status_t rval;
4135fcf3ce44SJohn Forte 
4136fcf3ce44SJohn Forte 	did = fct_cmd->cmd_rportid;
4137fcf3ce44SJohn Forte 	fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific;
4138fcf3ce44SJohn Forte 
4139fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, fct_ct->ct_req_size,
4140fcf3ce44SJohn Forte 	    fct_ct->ct_resp_size, 0, KM_NOSLEEP))) {
4141fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4142fcf3ce44SJohn Forte 		    "emlxs_fct_send_ct_cmd: Unable to allocate packet.");
414382527734SSukumar Swaminathan 		return (FCT_BUSY);
4144fcf3ce44SJohn Forte 	}
4145291a2b48SSukumar Swaminathan 
414682527734SSukumar Swaminathan 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_SEND_CT_REQ);
4147291a2b48SSukumar Swaminathan 	/* mutex_enter(&cmd_sbp->fct_mtx); */
4148fcf3ce44SJohn Forte 
414982527734SSukumar Swaminathan 	cmd_sbp->channel = &hba->chan[hba->channel_ct];
4150fcf3ce44SJohn Forte 	cmd_sbp->fct_type = EMLXS_FCT_CT_REQ;
4151fcf3ce44SJohn Forte 
4152fcf3ce44SJohn Forte 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
4153291a2b48SSukumar Swaminathan 	cmd_sbp->fct_pkt = pkt;
4154fcf3ce44SJohn Forte 
4155fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
4156fcf3ce44SJohn Forte 	pkt->pkt_timeout =
4157fcf3ce44SJohn Forte 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
4158fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_fct_pkt_comp;
4159fcf3ce44SJohn Forte 
4160fcf3ce44SJohn Forte 	/* Build the fc header */
416182527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
4162fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL;
416382527734SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
4164fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
4165fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl =
4166fcf3ce44SJohn Forte 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
4167fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
4168fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4169fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4170fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
4171fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
4172fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
4173fcf3ce44SJohn Forte 
4174fcf3ce44SJohn Forte 	/* Copy the cmd payload */
4175fcf3ce44SJohn Forte 	bcopy((uint8_t *)fct_ct->ct_req_payload, (uint8_t *)pkt->pkt_cmd,
4176fcf3ce44SJohn Forte 	    fct_ct->ct_req_size);
417782527734SSukumar Swaminathan 
4178291a2b48SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
417982527734SSukumar Swaminathan 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_REQ_PENDING);
418082527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
4181fcf3ce44SJohn Forte 
4182fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
418382527734SSukumar Swaminathan 
4184fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4185fcf3ce44SJohn Forte 		    "emlxs_fct_send_ct_cmd: Unable to send packet.");
4186fcf3ce44SJohn Forte 
418782527734SSukumar Swaminathan 		/* Reacquire ownership of the fct_cmd */
418882527734SSukumar Swaminathan 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
418982527734SSukumar Swaminathan 		if (rval) {
419082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
419182527734SSukumar Swaminathan 			    "emlxs_fct_send_ct_cmd: "
419282527734SSukumar Swaminathan 			    "Unable to reacquire fct_cmd.");
419382527734SSukumar Swaminathan 
419482527734SSukumar Swaminathan 			return (rval);
4195fcf3ce44SJohn Forte 		}
419682527734SSukumar Swaminathan 		/* mutex_enter(&cmd_sbp->fct_mtx); */
4197fcf3ce44SJohn Forte 
419882527734SSukumar Swaminathan 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
419982527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4200fcf3ce44SJohn Forte 
420182527734SSukumar Swaminathan 		return (FCT_BUSY);
4202fcf3ce44SJohn Forte 	}
4203fcf3ce44SJohn Forte 
4204fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
4205fcf3ce44SJohn Forte 
420682527734SSukumar Swaminathan } /* emlxs_fct_send_ct_cmd() */
4207fcf3ce44SJohn Forte 
4208fcf3ce44SJohn Forte 
420982527734SSukumar Swaminathan /* cmd_sbp->fct_mtx must be held to enter */
4210fe199829SSukumar Swaminathan static uint32_t
4211291a2b48SSukumar Swaminathan emlxs_fct_pkt_abort_txq(emlxs_port_t *port, emlxs_buf_t *cmd_sbp)
4212fcf3ce44SJohn Forte {
4213fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4214fcf3ce44SJohn Forte 	NODELIST *nlp;
4215291a2b48SSukumar Swaminathan 	fc_packet_t *pkt;
4216291a2b48SSukumar Swaminathan 	emlxs_buf_t *sbp;
4217291a2b48SSukumar Swaminathan 	emlxs_buf_t *iocb_sbp;
421882527734SSukumar Swaminathan 	uint8_t channelno;
421982527734SSukumar Swaminathan 	CHANNEL *cp;
4220fcf3ce44SJohn Forte 	IOCBQ *iocbq;
4221fcf3ce44SJohn Forte 	IOCBQ *next;
4222fcf3ce44SJohn Forte 	IOCBQ *prev;
4223fcf3ce44SJohn Forte 	uint32_t found;
4224291a2b48SSukumar Swaminathan 	uint32_t pkt_flags;
4225fcf3ce44SJohn Forte 
4226291a2b48SSukumar Swaminathan 	/* Check the transmit queue */
422782527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
4228fcf3ce44SJohn Forte 
4229291a2b48SSukumar Swaminathan 	/* The IOCB could point to a cmd_sbp (no packet) or a sbp (packet) */
4230291a2b48SSukumar Swaminathan 	pkt = cmd_sbp->fct_pkt;
4231291a2b48SSukumar Swaminathan 	if (pkt) {
4232291a2b48SSukumar Swaminathan 		sbp = PKT2PRIV(pkt);
4233291a2b48SSukumar Swaminathan 		if (sbp == NULL) {
4234291a2b48SSukumar Swaminathan 			goto done;
4235291a2b48SSukumar Swaminathan 		}
4236291a2b48SSukumar Swaminathan 		iocb_sbp = sbp;
4237291a2b48SSukumar Swaminathan 		iocbq = &sbp->iocbq;
4238291a2b48SSukumar Swaminathan 		pkt_flags = sbp->pkt_flags;
4239291a2b48SSukumar Swaminathan 	} else {
4240291a2b48SSukumar Swaminathan 		sbp = NULL;
4241291a2b48SSukumar Swaminathan 		iocb_sbp = cmd_sbp;
4242291a2b48SSukumar Swaminathan 		iocbq = &cmd_sbp->iocbq;
4243291a2b48SSukumar Swaminathan 		pkt_flags = cmd_sbp->pkt_flags;
4244fcf3ce44SJohn Forte 	}
4245fcf3ce44SJohn Forte 
4246291a2b48SSukumar Swaminathan 	nlp = (NODELIST *)cmd_sbp->node;
424782527734SSukumar Swaminathan 	cp = (CHANNEL *)cmd_sbp->channel;
424882527734SSukumar Swaminathan 	channelno = (cp) ? cp->channelno : 0;
4249fcf3ce44SJohn Forte 
4250291a2b48SSukumar Swaminathan 	if (pkt_flags & PACKET_IN_TXQ) {
4251fcf3ce44SJohn Forte 		/* Find it on the queue */
4252fcf3ce44SJohn Forte 		found = 0;
4253fcf3ce44SJohn Forte 		if (iocbq->flag & IOCB_PRIORITY) {
4254fcf3ce44SJohn Forte 			/* Search the priority queue */
4255fcf3ce44SJohn Forte 			prev = NULL;
425682527734SSukumar Swaminathan 			next = (IOCBQ *)nlp->nlp_ptx[channelno].q_first;
4257fcf3ce44SJohn Forte 
4258fcf3ce44SJohn Forte 			while (next) {
4259fcf3ce44SJohn Forte 				if (next == iocbq) {
4260fcf3ce44SJohn Forte 					/* Remove it */
4261fcf3ce44SJohn Forte 					if (prev) {
4262fcf3ce44SJohn Forte 						prev->next = iocbq->next;
4263fcf3ce44SJohn Forte 					}
4264291a2b48SSukumar Swaminathan 
426582527734SSukumar Swaminathan 					if (nlp->nlp_ptx[channelno].q_last ==
4266fcf3ce44SJohn Forte 					    (void *)iocbq) {
426782527734SSukumar Swaminathan 						nlp->nlp_ptx[channelno].q_last =
4268fcf3ce44SJohn Forte 						    (void *)prev;
4269fcf3ce44SJohn Forte 					}
4270291a2b48SSukumar Swaminathan 
427182527734SSukumar Swaminathan 					if (nlp->nlp_ptx[channelno].q_first ==
4272fcf3ce44SJohn Forte 					    (void *)iocbq) {
427382527734SSukumar Swaminathan 						nlp->nlp_ptx[channelno].
427482527734SSukumar Swaminathan 						    q_first =
4275fcf3ce44SJohn Forte 						    (void *)iocbq->next;
4276fcf3ce44SJohn Forte 					}
4277291a2b48SSukumar Swaminathan 
427882527734SSukumar Swaminathan 					nlp->nlp_ptx[channelno].q_cnt--;
4279fcf3ce44SJohn Forte 					iocbq->next = NULL;
4280fcf3ce44SJohn Forte 					found = 1;
4281fcf3ce44SJohn Forte 					break;
4282fcf3ce44SJohn Forte 				}
4283291a2b48SSukumar Swaminathan 
4284fcf3ce44SJohn Forte 				prev = next;
4285fcf3ce44SJohn Forte 				next = next->next;
4286fcf3ce44SJohn Forte 			}
4287fcf3ce44SJohn Forte 		} else {
4288fcf3ce44SJohn Forte 			/* Search the normal queue */
4289fcf3ce44SJohn Forte 			prev = NULL;
429082527734SSukumar Swaminathan 			next = (IOCBQ *)nlp->nlp_tx[channelno].q_first;
4291fcf3ce44SJohn Forte 
4292fcf3ce44SJohn Forte 			while (next) {
4293fcf3ce44SJohn Forte 				if (next == iocbq) {
4294fcf3ce44SJohn Forte 					/* Remove it */
4295fcf3ce44SJohn Forte 					if (prev) {
4296fcf3ce44SJohn Forte 						prev->next = iocbq->next;
4297fcf3ce44SJohn Forte 					}
4298291a2b48SSukumar Swaminathan 
429982527734SSukumar Swaminathan 					if (nlp->nlp_tx[channelno].q_last ==
4300fcf3ce44SJohn Forte 					    (void *)iocbq) {
430182527734SSukumar Swaminathan 						nlp->nlp_tx[channelno].q_last =
4302fcf3ce44SJohn Forte 						    (void *)prev;
4303fcf3ce44SJohn Forte 					}
4304291a2b48SSukumar Swaminathan 
430582527734SSukumar Swaminathan 					if (nlp->nlp_tx[channelno].q_first ==
4306fcf3ce44SJohn Forte 					    (void *)iocbq) {
430782527734SSukumar Swaminathan 						nlp->nlp_tx[channelno].q_first =
4308fcf3ce44SJohn Forte 						    (void *)iocbq->next;
4309fcf3ce44SJohn Forte 					}
4310291a2b48SSukumar Swaminathan 
431182527734SSukumar Swaminathan 					nlp->nlp_tx[channelno].q_cnt--;
4312fcf3ce44SJohn Forte 					iocbq->next = NULL;
4313fcf3ce44SJohn Forte 					found = 1;
4314fcf3ce44SJohn Forte 					break;
4315fcf3ce44SJohn Forte 				}
4316291a2b48SSukumar Swaminathan 
4317fcf3ce44SJohn Forte 				prev = next;
4318fcf3ce44SJohn Forte 				next = (IOCBQ *)next->next;
4319fcf3ce44SJohn Forte 			}
4320fcf3ce44SJohn Forte 		}
4321fcf3ce44SJohn Forte 
4322fcf3ce44SJohn Forte 		if (!found) {
4323fcf3ce44SJohn Forte 			goto done;
4324fcf3ce44SJohn Forte 		}
4325291a2b48SSukumar Swaminathan 
4326fcf3ce44SJohn Forte 		/* Check if node still needs servicing */
432782527734SSukumar Swaminathan 		if ((nlp->nlp_ptx[channelno].q_first) ||
432882527734SSukumar Swaminathan 		    (nlp->nlp_tx[channelno].q_first &&
432982527734SSukumar Swaminathan 		    !(nlp->nlp_flag[channelno] & NLP_CLOSED))) {
4330fcf3ce44SJohn Forte 
4331fcf3ce44SJohn Forte 			/*
4332291a2b48SSukumar Swaminathan 			 * If this is the base node, don't shift the pointers
4333fcf3ce44SJohn Forte 			 */
4334fcf3ce44SJohn Forte 			/* We want to drain the base node before moving on */
4335fcf3ce44SJohn Forte 			if (!nlp->nlp_base) {
433682527734SSukumar Swaminathan 				/* Shift channel queue pointers to next node */
433782527734SSukumar Swaminathan 				cp->nodeq.q_last = (void *)nlp;
433882527734SSukumar Swaminathan 				cp->nodeq.q_first = nlp->nlp_next[channelno];
4339fcf3ce44SJohn Forte 			}
4340fcf3ce44SJohn Forte 		} else {
434182527734SSukumar Swaminathan 			/* Remove node from channel queue */
4342fcf3ce44SJohn Forte 
4343fcf3ce44SJohn Forte 			/* If this is the last node on list */
434482527734SSukumar Swaminathan 			if (cp->nodeq.q_last == (void *)nlp) {
434582527734SSukumar Swaminathan 				cp->nodeq.q_last = NULL;
434682527734SSukumar Swaminathan 				cp->nodeq.q_first = NULL;
434782527734SSukumar Swaminathan 				cp->nodeq.q_cnt = 0;
4348fcf3ce44SJohn Forte 			} else {
4349fcf3ce44SJohn Forte 				/* Remove node from head */
435082527734SSukumar Swaminathan 				cp->nodeq.q_first = nlp->nlp_next[channelno];
435182527734SSukumar Swaminathan 				((NODELIST *)cp->nodeq.q_last)->
435282527734SSukumar Swaminathan 				    nlp_next[channelno] = cp->nodeq.q_first;
435382527734SSukumar Swaminathan 				cp->nodeq.q_cnt--;
4354fcf3ce44SJohn Forte 			}
4355fcf3ce44SJohn Forte 
4356fcf3ce44SJohn Forte 			/* Clear node */
435782527734SSukumar Swaminathan 			nlp->nlp_next[channelno] = NULL;
4358fcf3ce44SJohn Forte 		}
4359fcf3ce44SJohn Forte 
436082527734SSukumar Swaminathan 		/* The IOCB points to iocb_sbp (no packet) or a sbp (packet) */
436182527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4362*a9800bebSGarrett D'Amore 			emlxs_sli4_free_xri(hba, iocb_sbp, iocb_sbp->xrip, 1);
436382527734SSukumar Swaminathan 		} else {
436482527734SSukumar Swaminathan 			(void) emlxs_unregister_pkt(cp, iocb_sbp->iotag, 0);
4365fcf3ce44SJohn Forte 		}
4366fcf3ce44SJohn Forte 
436782527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
4368fcf3ce44SJohn Forte 
4369291a2b48SSukumar Swaminathan 		if (pkt) {
4370291a2b48SSukumar Swaminathan 			emlxs_pkt_free(pkt);
4371291a2b48SSukumar Swaminathan 			cmd_sbp->fct_pkt = NULL;
4372fcf3ce44SJohn Forte 		}
437382527734SSukumar Swaminathan 		return (1);
4374fcf3ce44SJohn Forte 	}
4375291a2b48SSukumar Swaminathan done:
437682527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
437782527734SSukumar Swaminathan 	return (0);
437882527734SSukumar Swaminathan 
437982527734SSukumar Swaminathan } /* emlxs_fct_pkt_abort_txq() */
4380fcf3ce44SJohn Forte 
4381fcf3ce44SJohn Forte 
438282527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
4383291a2b48SSukumar Swaminathan /* FCT_NOT_FOUND & FCT_ABORT_SUCCESS indicates IO is done */
4384291a2b48SSukumar Swaminathan /* FCT_SUCCESS indicates abort will occur asyncronously */
4385291a2b48SSukumar Swaminathan static fct_status_t
4386291a2b48SSukumar Swaminathan emlxs_fct_abort(fct_local_port_t *fct_port, fct_cmd_t *fct_cmd,
4387291a2b48SSukumar Swaminathan     uint32_t flags)
4388291a2b48SSukumar Swaminathan {
4389291a2b48SSukumar Swaminathan 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
4390291a2b48SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
4391291a2b48SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp;
439282527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp2;
439382527734SSukumar Swaminathan 	emlxs_buf_t *prev;
4394291a2b48SSukumar Swaminathan 	fc_packet_t *pkt;
4395291a2b48SSukumar Swaminathan 	emlxs_buf_t *sbp = NULL;
439682527734SSukumar Swaminathan 	kmutex_t *fct_mtx;
439782527734SSukumar Swaminathan 	uint32_t fct_state;
439882527734SSukumar Swaminathan 
439982527734SSukumar Swaminathan 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
440082527734SSukumar Swaminathan 	fct_mtx = &cmd_sbp->fct_mtx;
4401fcf3ce44SJohn Forte 
4402291a2b48SSukumar Swaminathan top:
440382527734SSukumar Swaminathan 
4404291a2b48SSukumar Swaminathan 	/* Sanity check */
4405291a2b48SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
4406291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
440782527734SSukumar Swaminathan 		    "emlxs_fct_abort: Bad fct_cmd=%p.", fct_cmd);
4408fcf3ce44SJohn Forte 
4409291a2b48SSukumar Swaminathan 		return (FCT_NOT_FOUND);
4410291a2b48SSukumar Swaminathan 	}
4411fcf3ce44SJohn Forte 
4412291a2b48SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
4413291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
441482527734SSukumar Swaminathan 		    "emlxs_fct_abort: Pkt invalid. cmd_sbp=%p",
441582527734SSukumar Swaminathan 		    cmd_sbp);
4416fcf3ce44SJohn Forte 
4417291a2b48SSukumar Swaminathan 		return (FCT_NOT_FOUND);
4418fcf3ce44SJohn Forte 	}
4419fcf3ce44SJohn Forte 
442082527734SSukumar Swaminathan 	if (mutex_tryenter(fct_mtx) == 0) {
4421fcf3ce44SJohn Forte 		/*
4422291a2b48SSukumar Swaminathan 		 * This code path handles a race condition if
4423291a2b48SSukumar Swaminathan 		 * an IO completes, in emlxs_fct_handle_fcp_event(),
4424291a2b48SSukumar Swaminathan 		 * and we get an abort at the same time.
4425fcf3ce44SJohn Forte 		 */
4426291a2b48SSukumar Swaminathan 		delay(drv_usectohz(100000));	/* 100 msec */
4427291a2b48SSukumar Swaminathan 		goto top;
4428fcf3ce44SJohn Forte 	}
4429291a2b48SSukumar Swaminathan 	/* At this point, we have entered the mutex */
4430fcf3ce44SJohn Forte 
443182527734SSukumar Swaminathan 	/* Sanity check */
443282527734SSukumar Swaminathan 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
4433291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
443482527734SSukumar Swaminathan 		    "emlxs_fct_abort: Bad fct_cmd=%p.", fct_cmd);
4435fcf3ce44SJohn Forte 
443682527734SSukumar Swaminathan 		mutex_exit(fct_mtx);
4437291a2b48SSukumar Swaminathan 		return (FCT_NOT_FOUND);
4438fcf3ce44SJohn Forte 	}
4439fcf3ce44SJohn Forte 
444082527734SSukumar Swaminathan 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
444182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
444282527734SSukumar Swaminathan 		    "emlxs_fct_abort: Pkt invalid. cmd_sbp=%p",
444382527734SSukumar Swaminathan 		    cmd_sbp);
444482527734SSukumar Swaminathan 
444582527734SSukumar Swaminathan 		mutex_exit(fct_mtx);
444682527734SSukumar Swaminathan 		return (FCT_NOT_FOUND);
4447fcf3ce44SJohn Forte 	}
4448fcf3ce44SJohn Forte 
4449291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4450fe199829SSukumar Swaminathan 	    "emlxs_fct_abort: hbastate=%x. "
4451fe199829SSukumar Swaminathan 	    "xid=%x,%x cmd_sbp=%p fctstate=%d flags=%x,%x,%x",
4452fe199829SSukumar Swaminathan 	    hba->state, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid, cmd_sbp,
4453fe199829SSukumar Swaminathan 	    cmd_sbp->fct_state, flags, cmd_sbp->fct_flags, cmd_sbp->pkt_flags);
4454291a2b48SSukumar Swaminathan 
4455291a2b48SSukumar Swaminathan 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) {
445682527734SSukumar Swaminathan 		EMLXS_SLI_ISSUE_IOCB_CMD(hba, cmd_sbp->channel, 0);
445782527734SSukumar Swaminathan 
4458291a2b48SSukumar Swaminathan 		/* If Abort is already in progress */
445982527734SSukumar Swaminathan 		mutex_exit(fct_mtx);
446082527734SSukumar Swaminathan 		return (FCT_SUCCESS);
446182527734SSukumar Swaminathan 	}
446282527734SSukumar Swaminathan 	cmd_sbp->fct_flags |= EMLXS_FCT_ABORT_INP;
446382527734SSukumar Swaminathan 
446482527734SSukumar Swaminathan 	if (flags & FCT_IOF_FORCE_FCA_DONE) {
446582527734SSukumar Swaminathan 		fct_cmd->cmd_handle = 0;
4466291a2b48SSukumar Swaminathan 	}
4467fcf3ce44SJohn Forte 
4468291a2b48SSukumar Swaminathan 	TGTPORTSTAT.FctAbortSent++;
4469fcf3ce44SJohn Forte 
447082527734SSukumar Swaminathan 	switch (cmd_sbp->fct_state) {
447182527734SSukumar Swaminathan 	/* These are currently owned by COMSTAR. */
447282527734SSukumar Swaminathan 	/* They were last processed by emlxs_fct_cmd_post() */
4473fe199829SSukumar Swaminathan 	/* We have NO exchange resources associated with this IO. */
447482527734SSukumar Swaminathan 	case EMLXS_FCT_OWNED:
4475fe199829SSukumar Swaminathan 		goto abort_done;
447682527734SSukumar Swaminathan 
447782527734SSukumar Swaminathan 	/* These are on the unsol waitQ in the driver */
447882527734SSukumar Swaminathan 	case EMLXS_FCT_CMD_WAITQ:
447982527734SSukumar Swaminathan 		/* Find and remove it */
448082527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
448182527734SSukumar Swaminathan 		cmd_sbp2 = port->fct_wait_head;
448282527734SSukumar Swaminathan 		prev = NULL;
448382527734SSukumar Swaminathan 		while (cmd_sbp2) {
448482527734SSukumar Swaminathan 			if (cmd_sbp2 == cmd_sbp) {
448582527734SSukumar Swaminathan 				/* Remove it */
448682527734SSukumar Swaminathan 				if (prev) {
448782527734SSukumar Swaminathan 					prev->next = cmd_sbp2->next;
448882527734SSukumar Swaminathan 				}
448982527734SSukumar Swaminathan 
449082527734SSukumar Swaminathan 				if (port->fct_wait_head == cmd_sbp2) {
449182527734SSukumar Swaminathan 					port->fct_wait_head = cmd_sbp2->next;
449282527734SSukumar Swaminathan 				}
449382527734SSukumar Swaminathan 
449482527734SSukumar Swaminathan 				if (port->fct_wait_tail == cmd_sbp2) {
449582527734SSukumar Swaminathan 					port->fct_wait_tail = prev;
449682527734SSukumar Swaminathan 				}
449782527734SSukumar Swaminathan 
449882527734SSukumar Swaminathan 				cmd_sbp2->next = NULL;
449982527734SSukumar Swaminathan 				break;
450082527734SSukumar Swaminathan 			}
450182527734SSukumar Swaminathan 			prev = cmd_sbp2;
450282527734SSukumar Swaminathan 			cmd_sbp2 = cmd_sbp2->next;
450382527734SSukumar Swaminathan 		}
450482527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
450582527734SSukumar Swaminathan 
4506fe199829SSukumar Swaminathan 		/*FALLTHROUGH*/
4507fe199829SSukumar Swaminathan 
4508fe199829SSukumar Swaminathan 	/* These are currently owned by COMSTAR. */
4509fe199829SSukumar Swaminathan 	/* They were last processed by emlxs_fct_cmd_post() */
4510fe199829SSukumar Swaminathan 	/* We have residual exchange resources associated with this IO */
4511fe199829SSukumar Swaminathan 	case EMLXS_FCT_CMD_POSTED:
4512fe199829SSukumar Swaminathan 		switch (fct_cmd->cmd_type) {
4513fe199829SSukumar Swaminathan 		case FCT_CMD_FCP_XCHG: /* Unsol */
4514fe199829SSukumar Swaminathan 			TGTPORTSTAT.FctOutstandingIO--;
4515fe199829SSukumar Swaminathan 			emlxs_abort_fct_exchange(hba, port, fct_cmd->cmd_rxid);
4516fe199829SSukumar Swaminathan 			break;
4517fe199829SSukumar Swaminathan 
4518fe199829SSukumar Swaminathan 		case FCT_CMD_RCVD_ELS: /* Unsol */
4519fe199829SSukumar Swaminathan 			emlxs_abort_els_exchange(hba, port, fct_cmd->cmd_rxid);
4520fe199829SSukumar Swaminathan 			break;
4521fe199829SSukumar Swaminathan 		}
4522fe199829SSukumar Swaminathan 
4523fe199829SSukumar Swaminathan 		goto abort_done;
452482527734SSukumar Swaminathan 
452582527734SSukumar Swaminathan 	/* These are active in the driver */
452682527734SSukumar Swaminathan 	/* They were last processed by emlxs_fct_cmd_release() */
4527291a2b48SSukumar Swaminathan 	case EMLXS_FCT_RSP_PENDING:
4528291a2b48SSukumar Swaminathan 	case EMLXS_FCT_REQ_PENDING:
4529291a2b48SSukumar Swaminathan 	case EMLXS_FCT_REG_PENDING:
4530291a2b48SSukumar Swaminathan 	case EMLXS_FCT_DATA_PENDING:
4531291a2b48SSukumar Swaminathan 	case EMLXS_FCT_STATUS_PENDING:
453282527734SSukumar Swaminathan 
453382527734SSukumar Swaminathan 		/* Abort anything pending */
4534291a2b48SSukumar Swaminathan 		if (emlxs_fct_pkt_abort_txq(port, cmd_sbp)) {
4535fcf3ce44SJohn Forte 
4536291a2b48SSukumar Swaminathan 			if (fct_cmd->cmd_type == FCT_CMD_FCP_XCHG) {
4537291a2b48SSukumar Swaminathan 				TGTPORTSTAT.FctOutstandingIO--;
4538fcf3ce44SJohn Forte 			}
453982527734SSukumar Swaminathan 
4540fe199829SSukumar Swaminathan 			goto abort_done;
4541291a2b48SSukumar Swaminathan 		}
4542fcf3ce44SJohn Forte 
454382527734SSukumar Swaminathan 		/* If we're not online, then all IO will be flushed anyway */
4544291a2b48SSukumar Swaminathan 		if (!(hba->flag & FC_ONLINE_MODE)) {
454582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
454682527734SSukumar Swaminathan 			    "emlxs_fct_abort: Not online. fct_cmd=%p.",
454782527734SSukumar Swaminathan 			    fct_cmd);
4548291a2b48SSukumar Swaminathan 
454982527734SSukumar Swaminathan 			emlxs_fct_cmd_release(port, fct_cmd, 0);
455082527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
455182527734SSukumar Swaminathan 
455282527734SSukumar Swaminathan 			/* The cmd will be aborted on the */
455382527734SSukumar Swaminathan 			/* next emlxs_fct_cmd_acquire */
455482527734SSukumar Swaminathan 			/* because EMLXS_FCT_ABORT_INP is set. */
455582527734SSukumar Swaminathan 			break;
4556fcf3ce44SJohn Forte 		}
4557fcf3ce44SJohn Forte 
455882527734SSukumar Swaminathan 		/* Try to send abort request */
4559291a2b48SSukumar Swaminathan 		if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) {
4560291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
456182527734SSukumar Swaminathan 			    "emlxs_fct_abort: Unable to allocate packet. "
456282527734SSukumar Swaminathan 			    "fct_cmd=%p",
456382527734SSukumar Swaminathan 			    fct_cmd);
456482527734SSukumar Swaminathan 
456582527734SSukumar Swaminathan 			emlxs_fct_cmd_release(port, fct_cmd, 0);
456682527734SSukumar Swaminathan 			/* mutex_exit(&cmd_sbp->fct_mtx); */
456782527734SSukumar Swaminathan 
456882527734SSukumar Swaminathan 			/* The cmd will be aborted on the */
456982527734SSukumar Swaminathan 			/* next emlxs_fct_cmd_acquire anyway */
457082527734SSukumar Swaminathan 			/* because EMLXS_FCT_ABORT_INP is set. */
457182527734SSukumar Swaminathan 			break;
4572fcf3ce44SJohn Forte 		}
4573fcf3ce44SJohn Forte 
4574291a2b48SSukumar Swaminathan 		sbp = emlxs_fct_pkt_init(port, fct_cmd, pkt);
4575291a2b48SSukumar Swaminathan 
4576291a2b48SSukumar Swaminathan 		pkt->pkt_tran_type = FC_PKT_OUTBOUND;
4577291a2b48SSukumar Swaminathan 		pkt->pkt_timeout =
4578291a2b48SSukumar Swaminathan 		    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
4579291a2b48SSukumar Swaminathan 		pkt->pkt_comp = emlxs_fct_abort_pkt_comp;
4580291a2b48SSukumar Swaminathan 
4581291a2b48SSukumar Swaminathan 		/* Build the fc header */
458282527734SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(fct_cmd->cmd_rportid);
4583291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
458482527734SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
4585291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.type = FC_TYPE_BASIC_LS;
4586291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.f_ctl =
4587291a2b48SSukumar Swaminathan 		    (F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ);
4588291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.seq_id = 0;
4589291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.df_ctl = 0;
4590291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
4591291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
4592291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
4593291a2b48SSukumar Swaminathan 		pkt->pkt_cmd_fhdr.ro = 0;
4594291a2b48SSukumar Swaminathan 
4595291a2b48SSukumar Swaminathan 		cmd_sbp->fct_cmd = fct_cmd;
4596291a2b48SSukumar Swaminathan 		cmd_sbp->abort_attempts++;
4597fcf3ce44SJohn Forte 
4598291a2b48SSukumar Swaminathan 		/* Now disassociate the sbp / pkt from the fct_cmd */
4599291a2b48SSukumar Swaminathan 		sbp->fct_cmd = NULL;
4600fcf3ce44SJohn Forte 
460182527734SSukumar Swaminathan 		if (hba->state >= FC_LINK_UP) {
4602291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4603291a2b48SSukumar Swaminathan 			    "emlxs_fct_abort: ABORT: %p xri x%x",
4604291a2b48SSukumar Swaminathan 			    fct_cmd, fct_cmd->cmd_rxid);
4605fcf3ce44SJohn Forte 
460682527734SSukumar Swaminathan 			fct_state = EMLXS_FCT_ABORT_PENDING;
460782527734SSukumar Swaminathan 
460882527734SSukumar Swaminathan 		} else {
4609291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4610291a2b48SSukumar Swaminathan 			    "emlxs_fct_abort: CLOSE: %p xri x%x",
4611291a2b48SSukumar Swaminathan 			    fct_cmd, fct_cmd->cmd_rxid);
4612fcf3ce44SJohn Forte 
461382527734SSukumar Swaminathan 			fct_state = EMLXS_FCT_CLOSE_PENDING;
4614291a2b48SSukumar Swaminathan 		}
4615fcf3ce44SJohn Forte 
461682527734SSukumar Swaminathan 		emlxs_fct_cmd_release(port, fct_cmd, fct_state);
461782527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
461882527734SSukumar Swaminathan 
4619291a2b48SSukumar Swaminathan 		if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
4620291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
462182527734SSukumar Swaminathan 			    "emlxs_fct_abort: Unable to send abort packet.");
4622fcf3ce44SJohn Forte 
4623291a2b48SSukumar Swaminathan 			emlxs_pkt_free(pkt);
4624fcf3ce44SJohn Forte 
462582527734SSukumar Swaminathan 			/* The cmd will be aborted on the */
462682527734SSukumar Swaminathan 			/* next emlxs_fct_cmd_acquire anyway */
462782527734SSukumar Swaminathan 			/* because EMLXS_FCT_ABORT_INP is set. */
4628291a2b48SSukumar Swaminathan 		}
462982527734SSukumar Swaminathan 
4630291a2b48SSukumar Swaminathan 		break;
4631fcf3ce44SJohn Forte 
4632291a2b48SSukumar Swaminathan 	default:
463382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
463482527734SSukumar Swaminathan 		    "emlxs_fct_abort: Unexpected fct_state. "
463582527734SSukumar Swaminathan 		    "fct_cmd=%p state=%x",
463682527734SSukumar Swaminathan 		    fct_cmd, cmd_sbp->fct_state);
463782527734SSukumar Swaminathan 
463882527734SSukumar Swaminathan 		emlxs_fct_cmd_release(port, fct_cmd, 0);
463982527734SSukumar Swaminathan 		/* mutex_exit(&cmd_sbp->fct_mtx); */
464082527734SSukumar Swaminathan 
464182527734SSukumar Swaminathan 		/* The cmd will be aborted on the */
464282527734SSukumar Swaminathan 		/* next emlxs_fct_cmd_acquire anyway */
464382527734SSukumar Swaminathan 		/* because EMLXS_FCT_ABORT_INP is set. */
4644fcf3ce44SJohn Forte 
4645291a2b48SSukumar Swaminathan 	}	/* switch */
4646fcf3ce44SJohn Forte 
464782527734SSukumar Swaminathan 	return (FCT_SUCCESS);
4648fcf3ce44SJohn Forte 
4649fe199829SSukumar Swaminathan abort_done:
465082527734SSukumar Swaminathan 
465182527734SSukumar Swaminathan 	emlxs_fct_cmd_done(port, fct_cmd,
465282527734SSukumar Swaminathan 	    EMLXS_FCT_ABORT_DONE);
465382527734SSukumar Swaminathan 	/* mutex_exit(&cmd_sbp->fct_mtx); */
465482527734SSukumar Swaminathan 
465582527734SSukumar Swaminathan 	return (FCT_ABORT_SUCCESS);
465682527734SSukumar Swaminathan 
465782527734SSukumar Swaminathan } /* emlxs_fct_abort() */
4658fcf3ce44SJohn Forte 
4659fcf3ce44SJohn Forte 
4660fcf3ce44SJohn Forte extern void
4661fcf3ce44SJohn Forte emlxs_fct_link_up(emlxs_port_t *port)
4662fcf3ce44SJohn Forte {
4663fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4664fcf3ce44SJohn Forte 
4665fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
4666fcf3ce44SJohn Forte 
4667fcf3ce44SJohn Forte 	if (port->fct_port &&
4668fcf3ce44SJohn Forte 	    (port->fct_flags & FCT_STATE_PORT_ONLINE) &&
4669fcf3ce44SJohn Forte 	    !(port->fct_flags & FCT_STATE_LINK_UP)) {
4670fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4671fcf3ce44SJohn Forte 		    "emlxs_fct_link_up event.");
4672fcf3ce44SJohn Forte 
4673e2ca2865SSukumar Swaminathan 		port->fct_flags &= ~FCT_STATE_LINK_UP_ACKED;
4674fcf3ce44SJohn Forte 		port->fct_flags |= FCT_STATE_LINK_UP;
4675fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
4676fcf3ce44SJohn Forte 
4677fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4678fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4679fcf3ce44SJohn Forte 		    "fct_handle_event LINK_UP");
4680291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
4681291a2b48SSukumar Swaminathan 		MODSYM(fct_handle_event) (port->fct_port, FCT_EVENT_LINK_UP,
4682291a2b48SSukumar Swaminathan 		    0, 0);
4683fcf3ce44SJohn Forte 	} else {
4684fcf3ce44SJohn Forte 		if (!hba->ini_mode &&
4685fcf3ce44SJohn Forte 		    !(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
4686fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
4687fcf3ce44SJohn Forte 
4688fcf3ce44SJohn Forte 			/* Take link down and hold it down */
468982527734SSukumar Swaminathan 			(void) emlxs_reset_link(hba, 0, 1);
4690fcf3ce44SJohn Forte 		} else {
4691fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
4692fcf3ce44SJohn Forte 		}
4693fcf3ce44SJohn Forte 	}
4694fcf3ce44SJohn Forte 
4695fcf3ce44SJohn Forte 	return;
4696fcf3ce44SJohn Forte 
469782527734SSukumar Swaminathan } /* emlxs_fct_link_up() */
4698291a2b48SSukumar Swaminathan 
4699fcf3ce44SJohn Forte 
4700fcf3ce44SJohn Forte extern void
4701fcf3ce44SJohn Forte emlxs_fct_link_down(emlxs_port_t *port)
4702fcf3ce44SJohn Forte {
4703fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4704fcf3ce44SJohn Forte 
4705fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
4706fcf3ce44SJohn Forte 
4707fcf3ce44SJohn Forte 	if (port->fct_port &&
4708fcf3ce44SJohn Forte 	    (port->fct_flags & FCT_STATE_PORT_ONLINE) &&
4709fcf3ce44SJohn Forte 	    (port->fct_flags & FCT_STATE_LINK_UP)) {
4710fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4711fcf3ce44SJohn Forte 		    "emlxs_fct_link_down event.");
4712fcf3ce44SJohn Forte 
4713e2ca2865SSukumar Swaminathan 		port->fct_flags &= ~FCT_STATE_LINK_UP_ACKED;
4714fcf3ce44SJohn Forte 		port->fct_flags &= ~FCT_STATE_LINK_UP;
4715fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
4716fcf3ce44SJohn Forte 
4717fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4718fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4719fcf3ce44SJohn Forte 		    "fct_handle_event LINK_DOWN");
4720291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
472182527734SSukumar Swaminathan 
4722291a2b48SSukumar Swaminathan 		MODSYM(fct_handle_event) (port->fct_port, FCT_EVENT_LINK_DOWN,
4723291a2b48SSukumar Swaminathan 		    0, 0);
4724fcf3ce44SJohn Forte 	} else {
4725fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
4726fcf3ce44SJohn Forte 	}
4727fcf3ce44SJohn Forte 
4728fcf3ce44SJohn Forte 	return;
4729fcf3ce44SJohn Forte 
473082527734SSukumar Swaminathan } /* emlxs_fct_link_down() */
4731fcf3ce44SJohn Forte 
4732fcf3ce44SJohn Forte 
4733291a2b48SSukumar Swaminathan /* DMA FUNCTIONS */
4734fcf3ce44SJohn Forte 
4735fcf3ce44SJohn Forte fct_status_t
4736fcf3ce44SJohn Forte emlxs_fct_dmem_init(emlxs_port_t *port)
4737fcf3ce44SJohn Forte {
4738fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
4739fcf3ce44SJohn Forte 	emlxs_fct_dmem_bucket_t *p;
4740fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *bctl;
4741fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *bc;
4742fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *prev;
4743fcf3ce44SJohn Forte 	int32_t j;
4744fcf3ce44SJohn Forte 	int32_t i;
4745fcf3ce44SJohn Forte 	uint32_t total_mem;
4746fcf3ce44SJohn Forte 	uint8_t *addr;
4747fcf3ce44SJohn Forte 	uint8_t *host_addr;
4748fcf3ce44SJohn Forte 	uint64_t dev_addr;
4749fcf3ce44SJohn Forte 	ddi_dma_cookie_t cookie;
4750fcf3ce44SJohn Forte 	uint32_t ncookie;
4751fcf3ce44SJohn Forte 	uint32_t bsize;
4752fcf3ce44SJohn Forte 	size_t len;
4753fcf3ce44SJohn Forte 	char buf[64];
4754fcf3ce44SJohn Forte 	ddi_device_acc_attr_t acc;
4755fcf3ce44SJohn Forte 
4756fcf3ce44SJohn Forte 	bzero(&acc, sizeof (acc));
4757fcf3ce44SJohn Forte 	acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
4758fcf3ce44SJohn Forte 	acc.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
4759fcf3ce44SJohn Forte 	acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
4760fcf3ce44SJohn Forte 
4761fcf3ce44SJohn Forte 	p = port->dmem_bucket;
4762fcf3ce44SJohn Forte 	for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) {
4763fcf3ce44SJohn Forte 		if (!p->dmem_nbufs) {
4764fcf3ce44SJohn Forte 			continue;
4765fcf3ce44SJohn Forte 		}
4766291a2b48SSukumar Swaminathan 
4767fcf3ce44SJohn Forte 		bctl = (emlxs_fct_dmem_bctl_t *)kmem_zalloc(p->dmem_nbufs *
476882527734SSukumar Swaminathan 		    sizeof (emlxs_fct_dmem_bctl_t), KM_NOSLEEP);
4769fcf3ce44SJohn Forte 
4770fcf3ce44SJohn Forte 		if (bctl == NULL) {
4771fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4772fcf3ce44SJohn Forte 			    "emlxs_fct_dmem_init: Unable to allocate bctl.");
4773fcf3ce44SJohn Forte 			goto alloc_bctl_failed;
4774fcf3ce44SJohn Forte 		}
4775291a2b48SSukumar Swaminathan 
4776fcf3ce44SJohn Forte 		p->dmem_bctls_mem = bctl;
4777fcf3ce44SJohn Forte 
477862379b58SSukumar Swaminathan 		if (ddi_dma_alloc_handle(hba->dip, &hba->dma_attr_1sg,
4779fcf3ce44SJohn Forte 		    DDI_DMA_SLEEP, 0, &p->dmem_dma_handle) != DDI_SUCCESS) {
4780fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4781fcf3ce44SJohn Forte 			    "emlxs_fct_dmem_init: Unable to allocate handle.");
4782fcf3ce44SJohn Forte 			goto alloc_handle_failed;
4783fcf3ce44SJohn Forte 		}
4784fcf3ce44SJohn Forte 
4785fcf3ce44SJohn Forte 		total_mem = p->dmem_buf_size * p->dmem_nbufs;
4786fcf3ce44SJohn Forte 
4787fcf3ce44SJohn Forte 		if (ddi_dma_mem_alloc(p->dmem_dma_handle, total_mem, &acc,
478882527734SSukumar Swaminathan 		    DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0,
4789291a2b48SSukumar Swaminathan 		    (caddr_t *)&addr, &len,
4790291a2b48SSukumar Swaminathan 		    &p->dmem_acc_handle) != DDI_SUCCESS) {
4791fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4792fcf3ce44SJohn Forte 			    "emlxs_fct_dmem_init: Unable to allocate memory.");
4793fcf3ce44SJohn Forte 			goto mem_alloc_failed;
4794fcf3ce44SJohn Forte 		}
4795fcf3ce44SJohn Forte 
4796fcf3ce44SJohn Forte 		if (ddi_dma_addr_bind_handle(p->dmem_dma_handle, NULL,
4797291a2b48SSukumar Swaminathan 		    (caddr_t)addr, total_mem,
479882527734SSukumar Swaminathan 		    DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0,
4799291a2b48SSukumar Swaminathan 		    &cookie, &ncookie) != DDI_SUCCESS) {
4800fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4801fcf3ce44SJohn Forte 			    "emlxs_fct_dmem_init: Unable to bind handle.");
4802fcf3ce44SJohn Forte 			goto addr_bind_handle_failed;
4803fcf3ce44SJohn Forte 		}
4804fcf3ce44SJohn Forte 
4805fcf3ce44SJohn Forte 		if (ncookie != 1) {
4806fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4807fcf3ce44SJohn Forte 			    "emlxs_fct_dmem_init: DMEM init failed.");
4808fcf3ce44SJohn Forte 			goto dmem_init_failed;
4809fcf3ce44SJohn Forte 		}
4810fcf3ce44SJohn Forte 		(void) sprintf(buf, "%s%d_bucket%d mutex", DRIVER_NAME,
4811fcf3ce44SJohn Forte 		    hba->ddiinst, i);
4812fcf3ce44SJohn Forte 		mutex_init(&p->dmem_lock, buf, MUTEX_DRIVER,
4813*a9800bebSGarrett D'Amore 		    DDI_INTR_PRI(hba->intr_arg));
4814fcf3ce44SJohn Forte 
4815fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4816fcf3ce44SJohn Forte 		    "bufsize=%d cnt=%d", p->dmem_buf_size, p->dmem_nbufs);
4817fcf3ce44SJohn Forte 
4818fcf3ce44SJohn Forte 		host_addr = addr;
4819fcf3ce44SJohn Forte 		dev_addr = (uint64_t)cookie.dmac_laddress;
4820fcf3ce44SJohn Forte 
4821fcf3ce44SJohn Forte 		p->dmem_host_addr = addr;
4822fcf3ce44SJohn Forte 		p->dmem_dev_addr = dev_addr;
4823fcf3ce44SJohn Forte 		p->dmem_bctl_free_list = bctl;
4824fcf3ce44SJohn Forte 		p->dmem_nbufs_free = p->dmem_nbufs;
4825fcf3ce44SJohn Forte 		bsize = p->dmem_buf_size;
4826fcf3ce44SJohn Forte 
4827fcf3ce44SJohn Forte 		for (j = 0; j < p->dmem_nbufs; j++) {
4828fcf3ce44SJohn Forte 			stmf_data_buf_t *db;
4829fcf3ce44SJohn Forte 
4830fcf3ce44SJohn Forte 			db = MODSYM(stmf_alloc) (STMF_STRUCT_DATA_BUF, 0, 0);
4831fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4832fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4833fcf3ce44SJohn Forte 			    "stmf_alloc data_buf %p", db);
4834291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
4835fcf3ce44SJohn Forte 			if (db == NULL) {
4836fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4837291a2b48SSukumar Swaminathan 				    "emlxs_fct_dmem_init: alloc failed.");
4838fcf3ce44SJohn Forte 				goto dmem_init_failed;
4839fcf3ce44SJohn Forte 			}
4840fcf3ce44SJohn Forte 			db->db_port_private = bctl;
4841fcf3ce44SJohn Forte 			db->db_sglist[0].seg_addr = host_addr;
4842fcf3ce44SJohn Forte 			db->db_sglist[0].seg_length = bsize;
4843fcf3ce44SJohn Forte 			db->db_buf_size = bsize;
4844fcf3ce44SJohn Forte 			db->db_sglist_length = 1;
4845fcf3ce44SJohn Forte 
4846fcf3ce44SJohn Forte 			bctl->bctl_bucket = p;
4847fcf3ce44SJohn Forte 			bctl->bctl_buf = db;
4848fcf3ce44SJohn Forte 			bctl->bctl_dev_addr = dev_addr;
4849fcf3ce44SJohn Forte 
4850fcf3ce44SJohn Forte 			host_addr += bsize;
4851fcf3ce44SJohn Forte 			dev_addr += bsize;
4852fcf3ce44SJohn Forte 
4853fcf3ce44SJohn Forte 			prev = bctl;
4854fcf3ce44SJohn Forte 			bctl++;
4855fcf3ce44SJohn Forte 			prev->bctl_next = bctl;
4856fcf3ce44SJohn Forte 		}
4857fcf3ce44SJohn Forte 
4858fcf3ce44SJohn Forte 		prev->bctl_next = NULL;
4859fcf3ce44SJohn Forte 	}
4860fcf3ce44SJohn Forte 
4861fcf3ce44SJohn Forte 	return (FCT_SUCCESS);
4862fcf3ce44SJohn Forte 
4863fcf3ce44SJohn Forte dmem_failure_loop:
4864fcf3ce44SJohn Forte 	mutex_destroy(&p->dmem_lock);
4865fcf3ce44SJohn Forte 	bc = bctl;
4866fcf3ce44SJohn Forte 	while (bc) {
4867fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4868fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4869fcf3ce44SJohn Forte 		    "stmf_free:3 %p", bctl->bctl_buf);
4870291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
4871fcf3ce44SJohn Forte 		MODSYM(stmf_free) (bc->bctl_buf);
4872fcf3ce44SJohn Forte 		bc = bc->bctl_next;
4873fcf3ce44SJohn Forte 	}
4874fcf3ce44SJohn Forte 
4875fcf3ce44SJohn Forte dmem_init_failed:
4876fcf3ce44SJohn Forte 	(void) ddi_dma_unbind_handle(p->dmem_dma_handle);
4877fcf3ce44SJohn Forte 
4878fcf3ce44SJohn Forte addr_bind_handle_failed:
4879fcf3ce44SJohn Forte 	(void) ddi_dma_mem_free(&p->dmem_acc_handle);
4880fcf3ce44SJohn Forte 
4881fcf3ce44SJohn Forte mem_alloc_failed:
4882fcf3ce44SJohn Forte 	(void) ddi_dma_free_handle(&p->dmem_dma_handle);
4883fcf3ce44SJohn Forte 
4884fcf3ce44SJohn Forte alloc_handle_failed:
4885fcf3ce44SJohn Forte 	kmem_free(p->dmem_bctls_mem,
4886fcf3ce44SJohn Forte 	    p->dmem_nbufs * sizeof (emlxs_fct_dmem_bctl_t));
4887fcf3ce44SJohn Forte 
4888fcf3ce44SJohn Forte alloc_bctl_failed:
4889fcf3ce44SJohn Forte 	if (--i >= 0) {
4890fcf3ce44SJohn Forte 		p = &port->dmem_bucket[i];
4891fcf3ce44SJohn Forte 		bctl = p->dmem_bctl_free_list;
4892fcf3ce44SJohn Forte 		goto dmem_failure_loop;
4893fcf3ce44SJohn Forte 	}
4894fcf3ce44SJohn Forte 
4895291a2b48SSukumar Swaminathan 	return (FCT_FAILURE);
4896fcf3ce44SJohn Forte 
489782527734SSukumar Swaminathan } /* emlxs_fct_dmem_init() */
4898fcf3ce44SJohn Forte 
4899fcf3ce44SJohn Forte 
4900fcf3ce44SJohn Forte void
4901fcf3ce44SJohn Forte emlxs_fct_dmem_fini(emlxs_port_t *port)
4902fcf3ce44SJohn Forte {
4903fcf3ce44SJohn Forte 	emlxs_fct_dmem_bucket_t *p;
4904fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *bctl;
4905fcf3ce44SJohn Forte 	uint32_t i;
4906fcf3ce44SJohn Forte 
4907fcf3ce44SJohn Forte 	p = port->dmem_bucket;
4908fcf3ce44SJohn Forte 	for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) {
4909fcf3ce44SJohn Forte 		if (!p->dmem_nbufs) {
4910fcf3ce44SJohn Forte 			continue;
4911fcf3ce44SJohn Forte 		}
4912291a2b48SSukumar Swaminathan 
4913fcf3ce44SJohn Forte 		bctl = p->dmem_bctl_free_list;
4914fcf3ce44SJohn Forte 
4915fcf3ce44SJohn Forte 		while (bctl) {
4916fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4917fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4918fcf3ce44SJohn Forte 			    "stmf_free:4 %p", bctl->bctl_buf);
4919291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
4920fcf3ce44SJohn Forte 			MODSYM(stmf_free) (bctl->bctl_buf);
4921fcf3ce44SJohn Forte 			bctl = bctl->bctl_next;
4922fcf3ce44SJohn Forte 		}
4923fcf3ce44SJohn Forte 
4924fcf3ce44SJohn Forte 		bctl = p->dmem_bctl_free_list;
4925fcf3ce44SJohn Forte 
4926fcf3ce44SJohn Forte 		(void) ddi_dma_unbind_handle(p->dmem_dma_handle);
4927fcf3ce44SJohn Forte 		(void) ddi_dma_mem_free(&p->dmem_acc_handle);
4928fcf3ce44SJohn Forte 		(void) ddi_dma_free_handle(&p->dmem_dma_handle);
4929fcf3ce44SJohn Forte 
4930fcf3ce44SJohn Forte 		kmem_free(p->dmem_bctls_mem,
4931fcf3ce44SJohn Forte 		    (p->dmem_nbufs * sizeof (emlxs_fct_dmem_bctl_t)));
4932fcf3ce44SJohn Forte 		mutex_destroy(&p->dmem_lock);
4933fcf3ce44SJohn Forte 	}
4934fcf3ce44SJohn Forte 
4935fcf3ce44SJohn Forte 	bzero((uint8_t *)port->dmem_bucket, sizeof (port->dmem_bucket));
4936fcf3ce44SJohn Forte 
4937fcf3ce44SJohn Forte 	return;
4938fcf3ce44SJohn Forte 
493982527734SSukumar Swaminathan } /* emlxs_fct_dmem_fini() */
4940fcf3ce44SJohn Forte 
4941fcf3ce44SJohn Forte 
494282527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
4943fcf3ce44SJohn Forte /* ARGSUSED */
4944fcf3ce44SJohn Forte static stmf_data_buf_t *
4945fcf3ce44SJohn Forte emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port, uint32_t size,
4946fcf3ce44SJohn Forte     uint32_t *pminsize, uint32_t flags)
4947fcf3ce44SJohn Forte {
4948fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
4949fcf3ce44SJohn Forte 	emlxs_fct_dmem_bucket_t *p;
4950fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *bctl;
4951fcf3ce44SJohn Forte 	uint32_t i;
4952fcf3ce44SJohn Forte 
4953fcf3ce44SJohn Forte 	if (size > FCT_DMEM_MAX_BUF_SIZE) {
4954fcf3ce44SJohn Forte 		size = FCT_DMEM_MAX_BUF_SIZE;
4955fcf3ce44SJohn Forte 	}
4956291a2b48SSukumar Swaminathan 
4957fcf3ce44SJohn Forte 	p = port->dmem_bucket;
4958fcf3ce44SJohn Forte 	for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) {
4959fcf3ce44SJohn Forte 		if (!p->dmem_nbufs) {
4960fcf3ce44SJohn Forte 			continue;
4961fcf3ce44SJohn Forte 		}
4962291a2b48SSukumar Swaminathan 
4963fcf3ce44SJohn Forte 		if (p->dmem_buf_size >= size) {
4964fcf3ce44SJohn Forte 			mutex_enter(&p->dmem_lock);
4965fcf3ce44SJohn Forte 			if (p->dmem_nbufs_free) {
4966fcf3ce44SJohn Forte 				if (p->dmem_buf_size < *pminsize) {
4967fcf3ce44SJohn Forte 					*pminsize = p->dmem_buf_size;
4968fcf3ce44SJohn Forte 					TGTPORTSTAT.FctNoBuffer++;
4969fcf3ce44SJohn Forte 
4970fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
4971fcf3ce44SJohn Forte 					    &emlxs_fct_api_msg,
4972fcf3ce44SJohn Forte 					    "emlxs_fct_dbuf_alloc: Failed(1).");
4973fcf3ce44SJohn Forte 					mutex_exit(&p->dmem_lock);
4974fcf3ce44SJohn Forte 					return (NULL);
4975fcf3ce44SJohn Forte 				}
4976291a2b48SSukumar Swaminathan 
4977fcf3ce44SJohn Forte 				bctl = p->dmem_bctl_free_list;
4978fcf3ce44SJohn Forte 				if (bctl == NULL) {
4979fcf3ce44SJohn Forte 					mutex_exit(&p->dmem_lock);
4980fcf3ce44SJohn Forte 					continue;
4981fcf3ce44SJohn Forte 				}
4982291a2b48SSukumar Swaminathan 
4983fcf3ce44SJohn Forte 				p->dmem_bctl_free_list = bctl->bctl_next;
4984fcf3ce44SJohn Forte 				p->dmem_nbufs_free--;
4985fcf3ce44SJohn Forte 				bctl->bctl_buf->db_data_size = size;
4986fcf3ce44SJohn Forte 				mutex_exit(&p->dmem_lock);
4987fcf3ce44SJohn Forte 
4988fcf3ce44SJohn Forte #ifdef FCT_API_TRACE
4989fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
499082527734SSukumar Swaminathan 				    "emlx_fct_buf_alloc: bctl_buf %p: size %d",
4991fcf3ce44SJohn Forte 				    bctl->bctl_buf, size);
4992291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
4993fcf3ce44SJohn Forte 
4994fcf3ce44SJohn Forte 				return (bctl->bctl_buf);
4995fcf3ce44SJohn Forte 			}
4996fcf3ce44SJohn Forte 			mutex_exit(&p->dmem_lock);
4997fcf3ce44SJohn Forte 
4998fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4999fcf3ce44SJohn Forte 			    "emlx_fct_buf_alloc size %d Nothing free bck %d",
5000fcf3ce44SJohn Forte 			    size, i);
5001fcf3ce44SJohn Forte 		}
5002fcf3ce44SJohn Forte 	}
5003fcf3ce44SJohn Forte 
5004fcf3ce44SJohn Forte 	*pminsize = 0;
5005fcf3ce44SJohn Forte 	TGTPORTSTAT.FctNoBuffer++;
5006fcf3ce44SJohn Forte 
5007fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
5008fcf3ce44SJohn Forte 	    "emlxs_fct_dbuf_alloc: Failed(2).");
5009fcf3ce44SJohn Forte 
5010fcf3ce44SJohn Forte 	return (NULL);
5011fcf3ce44SJohn Forte 
501282527734SSukumar Swaminathan } /* emlxs_fct_dbuf_alloc() */
5013fcf3ce44SJohn Forte 
5014fcf3ce44SJohn Forte 
501582527734SSukumar Swaminathan /* COMSTAR ENTER POINT */
5016291a2b48SSukumar Swaminathan /*ARGSUSED*/
5017fcf3ce44SJohn Forte static void
5018fcf3ce44SJohn Forte emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *dbuf)
5019fcf3ce44SJohn Forte {
5020fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *bctl =
5021fcf3ce44SJohn Forte 	    (emlxs_fct_dmem_bctl_t *)dbuf->db_port_private;
5022fcf3ce44SJohn Forte 	emlxs_fct_dmem_bucket_t *p = bctl->bctl_bucket;
5023fcf3ce44SJohn Forte 
502482527734SSukumar Swaminathan #ifdef FCT_API_TRACE_1
5025fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
5026fcf3ce44SJohn Forte 	    "emlx_fct_buf_free %p", dbuf);
5027291a2b48SSukumar Swaminathan #endif /* FCT_API_TRACE */
5028fcf3ce44SJohn Forte 
5029fcf3ce44SJohn Forte 	mutex_enter(&p->dmem_lock);
5030fcf3ce44SJohn Forte 	bctl->bctl_next = p->dmem_bctl_free_list;
5031fcf3ce44SJohn Forte 	p->dmem_bctl_free_list = bctl;
5032fcf3ce44SJohn Forte 	p->dmem_nbufs_free++;
5033fcf3ce44SJohn Forte 	mutex_exit(&p->dmem_lock);
5034fcf3ce44SJohn Forte 
503582527734SSukumar Swaminathan } /* emlxs_fct_dbuf_free() */
5036fcf3ce44SJohn Forte 
5037fcf3ce44SJohn Forte 
5038b3660a96SSukumar Swaminathan static int
5039b3660a96SSukumar Swaminathan emlxs_fct_dbuf_dma_sync(emlxs_hba_t *hba, stmf_data_buf_t *dbuf,
5040b3660a96SSukumar Swaminathan     uint_t sync_type)
5041fcf3ce44SJohn Forte {
5042fcf3ce44SJohn Forte 	emlxs_fct_dmem_bctl_t *bctl =
5043fcf3ce44SJohn Forte 	    (emlxs_fct_dmem_bctl_t *)dbuf->db_port_private;
5044fcf3ce44SJohn Forte 	emlxs_fct_dmem_bucket_t *p = bctl->bctl_bucket;
5045b3660a96SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
5046b3660a96SSukumar Swaminathan 	int retval = 0;
5047fcf3ce44SJohn Forte 
5048fcf3ce44SJohn Forte 	(void) ddi_dma_sync(p->dmem_dma_handle,
5049fcf3ce44SJohn Forte 	    (unsigned long)(bctl->bctl_dev_addr - p->dmem_dev_addr),
5050fcf3ce44SJohn Forte 	    dbuf->db_data_size, sync_type);
5051fcf3ce44SJohn Forte 
5052b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
5053b3660a96SSukumar Swaminathan 	if (emlxs_fm_check_dma_handle(hba, p->dmem_dma_handle)
5054b3660a96SSukumar Swaminathan 	    != DDI_FM_OK) {
5055b3660a96SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
5056b3660a96SSukumar Swaminathan 		    &emlxs_invalid_dma_handle_msg,
5057b3660a96SSukumar Swaminathan 		    "emlxs_fct_dbuf_dma_sync: hdl=%p",
5058b3660a96SSukumar Swaminathan 		    p->dmem_dma_handle);
5059b3660a96SSukumar Swaminathan 		retval = 1;
5060b3660a96SSukumar Swaminathan 	}
5061b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
5062b3660a96SSukumar Swaminathan 
5063b3660a96SSukumar Swaminathan 	return (retval);
5064b3660a96SSukumar Swaminathan 
506582527734SSukumar Swaminathan } /* emlxs_fct_dbuf_dma_sync() */
5066fcf3ce44SJohn Forte 
5067fcf3ce44SJohn Forte 
5068291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
5069