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