xref: /titanic_51/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_els.c (revision 8f23e9fa8abcb5857661066b954e63400d589b65)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at
9  * http://www.opensource.org/licenses/cddl1.txt.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2004-2012 Emulex. All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <emlxs.h>
28 
29 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
30 EMLXS_MSG_DEF(EMLXS_ELS_C);
31 
32 static void	emlxs_handle_sol_flogi(emlxs_port_t *port, emlxs_buf_t *sbp);
33 static void	emlxs_handle_sol_fdisc(emlxs_port_t *port, emlxs_buf_t *sbp);
34 static void	emlxs_handle_sol_plogi(emlxs_port_t *port, emlxs_buf_t *sbp);
35 static void	emlxs_handle_sol_adisc(emlxs_port_t *port, emlxs_buf_t *sbp);
36 static void	emlxs_handle_sol_logo(emlxs_port_t *port, emlxs_buf_t *sbp);
37 static void	emlxs_handle_sol_prli(emlxs_port_t *port, emlxs_buf_t *sbp);
38 
39 static void	emlxs_handle_unsol_rscn(emlxs_port_t *port, CHANNEL *cp,
40 			IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
41 static void	emlxs_handle_unsol_flogi(emlxs_port_t *port, CHANNEL *cp,
42 			IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
43 static void	emlxs_handle_unsol_plogi(emlxs_port_t *port, CHANNEL *cp,
44 			IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
45 static void	emlxs_handle_unsol_logo(emlxs_port_t *port, CHANNEL *cp,
46 			IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
47 static void	emlxs_handle_unsol_adisc(emlxs_port_t *port, CHANNEL *cp,
48 			IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
49 static void	emlxs_handle_unsol_prli(emlxs_port_t *port, CHANNEL *cp,
50 			IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
51 static void	emlxs_handle_unsol_prlo(emlxs_port_t *port, CHANNEL *cp,
52 			IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
53 static void	emlxs_handle_unsol_auth(emlxs_port_t *port, CHANNEL *cp,
54 			IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
55 static void	emlxs_handle_unsol_gen_cmd(emlxs_port_t *port, CHANNEL *cp,
56 			IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
57 static void	emlxs_handle_unsol_echo(emlxs_port_t *port, CHANNEL *cp,
58 			IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
59 static void	emlxs_handle_unsol_rtv(emlxs_port_t *port, CHANNEL *cp,
60 			IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
61 static void	emlxs_handle_unsol_rls(emlxs_port_t *port, CHANNEL *cp,
62 			IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
63 static void	emlxs_handle_acc(emlxs_port_t *port, emlxs_buf_t *sbp,
64 			IOCBQ *iocbq, uint32_t flag);
65 static void	emlxs_handle_reject(emlxs_port_t *port, emlxs_buf_t *sbp,
66 			IOCBQ *iocbq, uint32_t flag);
67 
68 #if (EMLXS_MODREV < EMLXS_MODREV4)
69 static void	emlxs_send_rsnn(emlxs_port_t *port);
70 
71 #endif /* < EMLXS_MODREV4 */
72 
73 
74 
75 /* Routine Declaration - Local */
76 /* End Routine Declaration - Local */
77 
78 /*
79  *  emlxs_els_handle_event
80  *
81  *  Description: Process an ELS Response Ring cmpl
82  *
83  */
84 extern int
85 emlxs_els_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
86 {
87 	emlxs_port_t *port = &PPORT;
88 	IOCB *iocb;
89 	emlxs_buf_t *sbp;
90 	fc_packet_t *pkt;
91 	uint32_t *lp0;
92 	uint32_t command;
93 	NODELIST *ndlp;
94 	uint32_t did;
95 	ELS_PKT *els;
96 
97 	iocb = &iocbq->iocb;
98 
99 	HBASTATS.ElsEvent++;
100 
101 	sbp = (emlxs_buf_t *)iocbq->sbp;
102 
103 	if (!sbp) {
104 		/*
105 		 * completion with missing xmit command
106 		 */
107 		HBASTATS.ElsStray++;
108 
109 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_els_completion_msg,
110 		    "iocbq=%p cmd=0x%x iotag=0x%x status=0x%x perr=0x%x",
111 		    iocbq, (uint32_t)iocb->ULPCOMMAND,
112 		    (uint32_t)iocb->ULPIOTAG, iocb->ULPSTATUS,
113 		    iocb->un.ulpWord[4]);
114 
115 		return (1);
116 	}
117 
118 	if (cp->channelno != hba->channel_els) {
119 		HBASTATS.ElsStray++;
120 
121 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_els_completion_msg,
122 		    "Not ELS channel: channel=%d iocbq=%p cmd=0x%x iotag=0x%x "
123 		    "status=0x%x perr=0x%x", cp->channelno, iocbq,
124 		    (uint32_t)iocb->ULPCOMMAND, (uint32_t)iocb->ULPIOTAG,
125 		    iocb->ULPSTATUS, iocb->un.ulpWord[4]);
126 
127 		return (1);
128 	}
129 
130 	port = sbp->iocbq.port;
131 	pkt = PRIV2PKT(sbp);
132 	lp0 = (uint32_t *)pkt->pkt_cmd;
133 	command = *lp0 & ELS_CMD_MASK;
134 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
135 
136 	/* Check if a response buffer was provided */
137 	if (pkt->pkt_rsplen) {
138 		EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen,
139 		    DDI_DMA_SYNC_FORKERNEL);
140 	}
141 
142 	switch (iocb->ULPCOMMAND) {
143 		/*
144 		 * ELS Reply completion
145 		 */
146 	case CMD_XMIT_ELS_RSP_CX:
147 	case CMD_XMIT_ELS_RSP64_CX:
148 
149 		HBASTATS.ElsRspCompleted++;
150 
151 		if (command == ELS_CMD_ACC) {
152 			emlxs_handle_acc(port, sbp, iocbq, 1);
153 		} else {
154 			emlxs_handle_reject(port, sbp, iocbq, 1);
155 		}
156 
157 		break;
158 
159 		/*
160 		 * ELS command completion
161 		 */
162 	case CMD_ELS_REQUEST_CR:
163 	case CMD_ELS_REQUEST64_CR:
164 	case CMD_ELS_REQUEST_CX:
165 	case CMD_ELS_REQUEST64_CX:
166 
167 		HBASTATS.ElsCmdCompleted++;
168 
169 		sbp->pkt_flags |= PACKET_ELS_RSP_VALID;
170 
171 		els = (ELS_PKT *)pkt->pkt_resp;
172 
173 		pkt->pkt_resp_resid =
174 		    pkt->pkt_rsplen - iocb->un.elsreq64.bdl.bdeSize;
175 		pkt->pkt_data_resid = pkt->pkt_datalen;
176 
177 		pkt->pkt_resp_fhdr.d_id = pkt->pkt_cmd_fhdr.s_id;
178 		pkt->pkt_resp_fhdr.s_id = pkt->pkt_cmd_fhdr.d_id;
179 
180 		if ((iocb->ULPSTATUS == 0) && (els->elsCode == 0x02)) {
181 			HBASTATS.ElsCmdGood++;
182 
183 			if (!(sbp->pkt_flags & PACKET_ALLOCATED)) {
184 				/*
185 				 * ULP patch - ULP expects
186 				 * resp_resid = 0 on success
187 				 */
188 				pkt->pkt_resp_resid = 0;
189 			}
190 
191 			switch (command) {
192 			case ELS_CMD_FDISC:	/* Fabric login */
193 				emlxs_handle_sol_fdisc(port, sbp);
194 
195 				break;
196 
197 			case ELS_CMD_FLOGI:	/* Fabric login */
198 				emlxs_handle_sol_flogi(port, sbp);
199 
200 				break;
201 
202 			case ELS_CMD_PLOGI:	/* NPort login */
203 				emlxs_handle_sol_plogi(port, sbp);
204 
205 				break;
206 
207 			case ELS_CMD_ADISC:	/* Adisc */
208 				emlxs_handle_sol_adisc(port, sbp);
209 
210 				break;
211 
212 			case ELS_CMD_LOGO:	/* Logout */
213 				emlxs_handle_sol_logo(port, sbp);
214 
215 				break;
216 
217 			case ELS_CMD_PRLI:	/* Process Log In */
218 				emlxs_handle_sol_prli(port, sbp);
219 
220 				break;
221 
222 			default:
223 				EMLXS_MSGF(EMLXS_CONTEXT,
224 				    &emlxs_els_completion_msg, "%s: did=%x",
225 				    emlxs_elscmd_xlate(command), did);
226 
227 				emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
228 
229 				break;
230 			}
231 
232 		} else {
233 			HBASTATS.ElsCmdError++;
234 
235 			/* Look for LS_REJECT */
236 			if (iocb->ULPSTATUS == IOSTAT_LS_RJT) {
237 				pkt->pkt_state = FC_PKT_LS_RJT;
238 				pkt->pkt_action = FC_ACTION_RETRYABLE;
239 				pkt->pkt_reason = iocb->un.grsp.perr.statRsn;
240 				pkt->pkt_expln = iocb->un.grsp.perr.statBaExp;
241 				sbp->pkt_flags |= PACKET_STATE_VALID;
242 
243 #ifdef SAN_DIAG_SUPPORT
244 				ndlp = emlxs_node_find_did(port, did, 1);
245 				if (ndlp) {
246 					emlxs_log_sd_lsrjt_event(port,
247 					    (HBA_WWN *)&ndlp->nlp_portname,
248 					    command, pkt->pkt_reason,
249 					    pkt->pkt_expln);
250 				}
251 #endif
252 
253 				EMLXS_MSGF(EMLXS_CONTEXT,
254 				    &emlxs_els_completion_msg,
255 				    "%s Rejected: did=%x rsn=%x exp=%x",
256 				    emlxs_elscmd_xlate(command), did,
257 				    pkt->pkt_reason, pkt->pkt_expln);
258 			} else if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) {
259 				EMLXS_MSGF(EMLXS_CONTEXT,
260 				    &emlxs_bad_els_completion_msg,
261 				    "%s: did=%x Local Reject. %s",
262 				    emlxs_elscmd_xlate(command), did,
263 				    emlxs_error_xlate(iocb->un.grsp.perr.
264 				    statLocalError));
265 			} else {
266 				EMLXS_MSGF(EMLXS_CONTEXT,
267 				    &emlxs_bad_els_completion_msg,
268 				    "%s: did=%x %s (%02x%02x%02x%02x)",
269 				    emlxs_elscmd_xlate(command), did,
270 				    emlxs_state_xlate(iocb->ULPSTATUS),
271 				    iocb->un.grsp.perr.statAction,
272 				    iocb->un.grsp.perr.statRsn,
273 				    iocb->un.grsp.perr.statBaExp,
274 				    iocb->un.grsp.perr.statLocalError);
275 			}
276 
277 			switch (command) {
278 			case ELS_CMD_PLOGI:	/* NPort login failed */
279 				ndlp = emlxs_node_find_did(port, did, 1);
280 
281 				if (ndlp && ndlp->nlp_active) {
282 					/* Open the node again */
283 					emlxs_node_open(port, ndlp,
284 					    hba->channel_fcp);
285 					emlxs_node_open(port, ndlp,
286 					    hba->channel_ip);
287 #ifdef DHCHAP_SUPPORT
288 					if (pkt->pkt_state == FC_PKT_LS_RJT) {
289 						emlxs_dhc_state(port, ndlp,
290 						    NODE_STATE_NOCHANGE,
291 						    pkt->pkt_reason,
292 						    pkt->pkt_expln);
293 					}
294 #endif /*  DHCHAP_SUPPORT */
295 				}
296 
297 				break;
298 
299 
300 			case ELS_CMD_PRLI:	/* Process Log In failed */
301 				ndlp = emlxs_node_find_did(port, did, 1);
302 
303 				if (ndlp && ndlp->nlp_active) {
304 					/* Open the node again */
305 					emlxs_node_open(port, ndlp,
306 					    hba->channel_fcp);
307 				}
308 
309 				break;
310 
311 			case ELS_CMD_FDISC:	/* Fabric login */
312 			case ELS_CMD_FLOGI:	/* Fabric login */
313 				if (pkt->pkt_state == FC_PKT_LS_RJT) {
314 					/* This will cause ULP to retry */
315 					/* FLOGI requests */
316 					pkt->pkt_reason = FC_REASON_QFULL;
317 					pkt->pkt_expln = 0;
318 
319 #ifdef DHCHAP_SUPPORT
320 					ndlp = emlxs_node_find_did(port,
321 					    did, 1);
322 					if (ndlp && ndlp->nlp_active) {
323 						emlxs_dhc_state(port, ndlp,
324 						    NODE_STATE_NOCHANGE,
325 						    pkt->pkt_reason,
326 						    pkt->pkt_expln);
327 					}
328 #endif /*  DHCHAP_SUPPORT */
329 				}
330 
331 				if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
332 					/* Preset the state for deferred cmpl */
333 					emlxs_set_pkt_state(sbp,
334 					    iocb->ULPSTATUS,
335 					    iocb->un.grsp.perr.statLocalError,
336 					    1);
337 
338 					if (emlxs_vpi_logi_failed_notify(
339 					    sbp->port, sbp) == 0) {
340 						/* Defer completion */
341 						return (0);
342 					}
343 				}
344 
345 				break;
346 
347 			default:
348 				break;
349 			}
350 
351 			emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
352 			    iocb->un.grsp.perr.statLocalError, 1);
353 		}
354 
355 		break;
356 
357 	default:
358 
359 		HBASTATS.ElsStray++;
360 
361 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_invalid_els_msg,
362 		    "Invalid iocb: cmd=0x%x", iocb->ULPCOMMAND);
363 
364 		emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
365 		    iocb->un.grsp.perr.statLocalError, 1);
366 
367 		break;
368 	}	/* switch(iocb->ULPCOMMAND) */
369 
370 	return (0);
371 
372 } /* emlxs_els_handle_event() */
373 
374 
375 extern int
376 emlxs_els_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
377     MATCHMAP *mp, uint32_t size)
378 {
379 	emlxs_hba_t *hba = HBA;
380 	uint32_t cmd_code;
381 	IOCB *iocb;
382 
383 	HBASTATS.ElsCmdReceived++;
384 
385 	iocb = &iocbq->iocb;
386 	cmd_code = *((uint32_t *)mp->virt) & ELS_CMD_MASK;
387 
388 	if (!(port->flag & EMLXS_PORT_BOUND)) {
389 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
390 		    "%s: sid=%x. Port not bound: Rejecting.",
391 		    emlxs_elscmd_xlate(cmd_code),
392 		    iocbq->iocb.un.elsreq.remoteID);
393 
394 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
395 		    cmd_code, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
396 
397 		return (0);
398 	}
399 
400 	switch (cmd_code) {
401 	case ELS_CMD_RSCN:
402 		HBASTATS.ElsRscnReceived++;
403 		emlxs_handle_unsol_rscn(port, cp, iocbq, mp, size);
404 		break;
405 
406 	case ELS_CMD_FLOGI:
407 		HBASTATS.ElsFlogiReceived++;
408 		emlxs_handle_unsol_flogi(port, cp, iocbq, mp, size);
409 		break;
410 
411 	case ELS_CMD_PLOGI:
412 		HBASTATS.ElsPlogiReceived++;
413 		emlxs_handle_unsol_plogi(port, cp, iocbq, mp, size);
414 		break;
415 
416 	case ELS_CMD_PRLI:
417 		HBASTATS.ElsPrliReceived++;
418 		emlxs_handle_unsol_prli(port, cp, iocbq, mp, size);
419 		break;
420 
421 	case ELS_CMD_PRLO:
422 		HBASTATS.ElsPrloReceived++;
423 		emlxs_handle_unsol_prlo(port, cp, iocbq, mp, size);
424 		break;
425 
426 	case ELS_CMD_LOGO:
427 		HBASTATS.ElsLogoReceived++;
428 		emlxs_handle_unsol_logo(port, cp, iocbq, mp, size);
429 		break;
430 
431 	case ELS_CMD_ADISC:
432 		HBASTATS.ElsAdiscReceived++;
433 		emlxs_handle_unsol_adisc(port, cp, iocbq, mp, size);
434 		break;
435 
436 	case ELS_CMD_AUTH:
437 		HBASTATS.ElsAuthReceived++;
438 		emlxs_handle_unsol_auth(port, cp, iocbq, mp, size);
439 		break;
440 
441 	case ELS_CMD_TEST:
442 		HBASTATS.ElsTestReceived++;
443 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
444 		    "%s: sid=%x. Dropping.",
445 		    emlxs_elscmd_xlate(cmd_code),
446 		    iocbq->iocb.un.elsreq.remoteID);
447 
448 		/* drop it */
449 		emlxs_close_els_exchange(hba, port, iocb->ULPCONTEXT);
450 		break;
451 
452 	case ELS_CMD_ESTC:
453 		HBASTATS.ElsEstcReceived++;
454 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
455 		    "%s: sid=%x. Dropping.",
456 		    emlxs_elscmd_xlate(cmd_code),
457 		    iocbq->iocb.un.elsreq.remoteID);
458 
459 		/* drop it */
460 		emlxs_close_els_exchange(hba, port, iocb->ULPCONTEXT);
461 		break;
462 
463 	case ELS_CMD_FARPR:
464 		HBASTATS.ElsFarprReceived++;
465 
466 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
467 		    "%s: sid=%x. Dropping.",
468 		    emlxs_elscmd_xlate(cmd_code),
469 		    iocbq->iocb.un.elsreq.remoteID);
470 
471 		/* drop it */
472 		emlxs_close_els_exchange(hba, port, iocb->ULPCONTEXT);
473 		break;
474 
475 	case ELS_CMD_ECHO:
476 		HBASTATS.ElsEchoReceived++;
477 		emlxs_handle_unsol_echo(port, cp, iocbq, mp, size);
478 		break;
479 
480 	case ELS_CMD_RLS:
481 		HBASTATS.ElsRlsReceived++;
482 		emlxs_handle_unsol_rls(port, cp, iocbq, mp, size);
483 		break;
484 
485 	case ELS_CMD_RTV:
486 		HBASTATS.ElsRtvReceived++;
487 		emlxs_handle_unsol_rtv(port, cp, iocbq, mp, size);
488 		break;
489 
490 	case ELS_CMD_ABTX:
491 	case ELS_CMD_RCS:
492 	case ELS_CMD_RES:
493 	case ELS_CMD_RSS:
494 	case ELS_CMD_RSI:
495 	case ELS_CMD_ESTS:
496 	case ELS_CMD_RRQ:
497 	case ELS_CMD_REC:
498 		HBASTATS.ElsGenReceived++;
499 
500 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
501 		    "%s: sid=%x. Rejecting.",
502 		    emlxs_elscmd_xlate(cmd_code),
503 		    iocbq->iocb.un.elsreq.remoteID);
504 
505 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
506 		    LSRJT_CMD_UNSUPPORTED, LSEXP_NOTHING_MORE);
507 		break;
508 
509 	default:
510 		HBASTATS.ElsGenReceived++;
511 		emlxs_handle_unsol_gen_cmd(port, cp, iocbq, mp, size);
512 		break;
513 	}
514 
515 	return (0);
516 
517 } /* emlxs_els_handle_unsol_req() */
518 
519 
520 static uint32_t
521 emlxs_els_delay_discovery(emlxs_port_t *port, emlxs_buf_t *sbp)
522 {
523 	emlxs_hba_t	*hba = HBA;
524 	emlxs_config_t	*cfg;
525 	SERV_PARM	*parm;
526 
527 	cfg = &CFG;
528 	if (!cfg[CFG_DELAY_DISCOVERY].current) {
529 		return (0);
530 	}
531 
532 	parm = &port->fabric_sparam;
533 	if (((port->prev_did != port->did) ||
534 	    bcmp(&port->prev_fabric_sparam.portName,
535 	    &port->fabric_sparam.portName, 8)) &&
536 	    !(parm->cmn.CLEAN_ADDRESS_BIT)) {
537 
538 		/* If this is the first time, check config parameter */
539 		if (port->prev_did || cfg[CFG_DELAY_DISCOVERY].current == 2) {
540 
541 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
542 			    "Clean Address delay: sid=%x prev=%x RATOV %d",
543 			    port->did, port->prev_did, hba->fc_ratov);
544 
545 			port->clean_address_sbp = sbp;
546 			port->clean_address_timer =
547 			    hba->timer_tics + hba->fc_ratov;
548 
549 			return (1);
550 		}
551 	}
552 	return (0);
553 
554 } /* emlxs_els_delay_discovery() */
555 
556 
557 static void
558 emlxs_handle_sol_flogi(emlxs_port_t *port, emlxs_buf_t *sbp)
559 {
560 	emlxs_hba_t *hba = HBA;
561 	emlxs_config_t *cfg = &CFG;
562 	emlxs_port_t *vport;
563 	SERV_PARM *sp;
564 	fc_packet_t *pkt;
565 	MAILBOXQ *mbox;
566 	uint32_t did;
567 	IOCBQ *iocbq;
568 	IOCB *iocb;
569 	char buffer[64];
570 	uint32_t i;
571 	int rc;
572 	uint16_t altBbCredit;
573 
574 	pkt = PRIV2PKT(sbp);
575 	sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t));
576 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
577 	iocbq = &sbp->iocbq;
578 	iocb = &iocbq->iocb;
579 
580 	mutex_enter(&EMLXS_PORT_LOCK);
581 
582 	/* Save the fabric service parameters and did */
583 	bcopy((void *)sp, (void *)&port->fabric_sparam, sizeof (SERV_PARM));
584 
585 	/* Save E_D_TOV ticks in nanoseconds */
586 	if (sp->cmn.edtovResolution) {
587 		hba->fc_edtov = (LE_SWAP32(sp->cmn.e_d_tov) + 999999) / 1000000;
588 	} else {
589 		hba->fc_edtov = LE_SWAP32(sp->cmn.e_d_tov);
590 	}
591 
592 	/* Save R_A_TOV ticks */
593 	hba->fc_ratov = (LE_SWAP32(sp->cmn.w2.r_a_tov) + 999) / 1000;
594 
595 	if (sp->cmn.fPort) {
596 		hba->flag |= FC_FABRIC_ATTACHED;
597 		hba->flag &= ~FC_PT_TO_PT;
598 
599 		port->did = iocb->un.elsreq.myID;
600 		pkt->pkt_resp_fhdr.s_id = LE_SWAP24_LO(FABRIC_DID);
601 		pkt->pkt_resp_fhdr.d_id = LE_SWAP24_LO(port->did);
602 
603 		/*
604 		 * If we are a N-port connected to a Fabric,
605 		 * fixup sparam's so logins to devices on remote
606 		 * loops work.
607 		 */
608 		altBbCredit = (hba->topology != TOPOLOGY_LOOP)? 1:0;
609 		hba->sparam.cmn.altBbCredit = altBbCredit;
610 
611 		/* Set this bit in all the port sparam copies */
612 		for (i = 0; i < MAX_VPORTS; i++) {
613 			vport = &VPORT(i);
614 
615 			if (!(vport->flag & EMLXS_PORT_BOUND)) {
616 				continue;
617 			}
618 
619 			vport->sparam.cmn.altBbCredit = altBbCredit;
620 		}
621 
622 		if (sp->cmn.rspMultipleNPort) {
623 			hba->flag |= FC_NPIV_SUPPORTED;
624 
625 			if (cfg[CFG_NPIV_DELAY].current) {
626 				/*
627 				 * PATCH: for NPIV support on
628 				 * Brocade switch firmware 5.10b
629 				 */
630 				if ((hba->flag & FC_NPIV_ENABLED) &&
631 				    ((sp->nodeName.IEEE[0] == 0x00) &&
632 				    (sp->nodeName.IEEE[1] == 0x05) &&
633 				    (sp->nodeName.IEEE[2] == 0x1e))) {
634 					hba->flag |= FC_NPIV_DELAY_REQUIRED;
635 				}
636 			}
637 		} else {
638 			hba->flag |= FC_NPIV_UNSUPPORTED;
639 		}
640 
641 		if (!(hba->flag & FC_NPIV_ENABLED)) {
642 			(void) strlcpy(buffer, "npiv:Disabled ",
643 			    sizeof (buffer));
644 		} else if (hba->flag & FC_NPIV_SUPPORTED) {
645 			(void) strlcpy(buffer, "npiv:Supported ",
646 			    sizeof (buffer));
647 		} else {
648 			(void) strlcpy(buffer, "npiv:Unsupported ",
649 			    sizeof (buffer));
650 		}
651 
652 #ifdef DHCHAP_SUPPORT
653 		if (!sp->cmn.fcsp_support) {
654 			(void) strlcat(buffer, "fcsp:Unsupported",
655 			    sizeof (buffer));
656 		} else if (cfg[CFG_AUTH_ENABLE].current &&
657 		    (port->vpi == 0 || cfg[CFG_AUTH_NPIV].current)) {
658 			(void) strlcat(buffer, "fcsp:Supported",
659 			    sizeof (buffer));
660 		} else {
661 			(void) strlcat(buffer, "fcsp:Disabled",
662 			    sizeof (buffer));
663 		}
664 #endif /* DHCHAP_SUPPORT */
665 
666 		mutex_exit(&EMLXS_PORT_LOCK);
667 
668 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
669 		    "FLOGI: did=%x sid=%x prev=%x %s",
670 		    did, port->did, port->prev_did, buffer);
671 
672 		/* Update our service parms */
673 		if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
674 			/* Update our service parms */
675 			if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
676 			    MEM_MBOX))) {
677 				emlxs_mb_config_link(hba, mbox);
678 
679 				rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox,
680 				    MBX_NOWAIT, 0);
681 				if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
682 					emlxs_mem_put(hba, MEM_MBOX,
683 					    (void *)mbox);
684 				}
685 			}
686 		}
687 
688 		/* Preset the state for the reg_did */
689 		emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1);
690 
691 		if (emlxs_els_delay_discovery(port, sbp)) {
692 			/* Deferred registration of this pkt until */
693 			/* Clean Address timeout */
694 			return;
695 		}
696 
697 		if (EMLXS_SLI_REG_DID(port, FABRIC_DID, &port->fabric_sparam,
698 		    sbp, NULL, NULL) == 0) {
699 			/* Deferred completion of this pkt until */
700 			/* login is complete */
701 			return;
702 		}
703 
704 		emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
705 		    IOERR_NO_RESOURCES, 1);
706 
707 	} else {	/* No switch */
708 
709 		hba->flag &= ~FC_FABRIC_ATTACHED;
710 		hba->flag |= FC_PT_TO_PT;
711 
712 		hba->flag &= ~FC_NPIV_SUPPORTED;
713 		(void) strlcpy(buffer, "npiv:Disabled.", sizeof (buffer));
714 
715 		if (emlxs_wwn_cmp((uint8_t *)&sp->portName,
716 		    (uint8_t *)&port->wwpn) > 0) {
717 			(void) strlcat(buffer, " P2P Master.",
718 			    sizeof (buffer));
719 		} else {
720 			(void) strlcat(buffer, " P2P Slave.",
721 			    sizeof (buffer));
722 		}
723 
724 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
725 		    "FLOGI: did=%x sid=%x %s", did, port->did, buffer);
726 
727 		mutex_exit(&EMLXS_PORT_LOCK);
728 
729 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
730 			/* Preset the state for the reg_did */
731 			emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1);
732 
733 			if (EMLXS_SLI_REG_DID(port, FABRIC_DID,
734 			    &port->fabric_sparam, sbp, NULL, NULL) == 0) {
735 				/* Deferred completion of this pkt until */
736 				/* login is complete */
737 				return;
738 			}
739 
740 			emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
741 			    IOERR_NO_RESOURCES, 1);
742 
743 		} else {
744 			emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
745 		}
746 	}
747 
748 	return;
749 
750 } /* emlxs_handle_sol_flogi() */
751 
752 
753 static void
754 emlxs_handle_sol_fdisc(emlxs_port_t *port, emlxs_buf_t *sbp)
755 {
756 	emlxs_hba_t *hba = HBA;
757 	emlxs_config_t *cfg = &CFG;
758 	SERV_PARM *sp;
759 	fc_packet_t *pkt;
760 	uint32_t did;
761 	IOCBQ *iocbq;
762 	IOCB *iocb;
763 	char buffer[64];
764 
765 	pkt = PRIV2PKT(sbp);
766 	sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t));
767 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
768 	iocbq = &sbp->iocbq;
769 	iocb = &iocbq->iocb;
770 
771 	mutex_enter(&EMLXS_PORT_LOCK);
772 
773 	/* Save the fabric service parameters and did */
774 	port->did = iocb->un.elsreq.myID;
775 	bcopy((void *)sp, (void *)&port->fabric_sparam, sizeof (SERV_PARM));
776 
777 	pkt->pkt_resp_fhdr.d_id = LE_SWAP24_LO(port->did);
778 
779 	mutex_exit(&EMLXS_PORT_LOCK);
780 
781 	buffer[0] = 0;
782 
783 #ifdef DHCHAP_SUPPORT
784 	if (!sp->cmn.fcsp_support) {
785 		(void) strlcat(buffer, "fcsp:Unsupported",
786 		    sizeof (buffer));
787 	} else if (cfg[CFG_AUTH_ENABLE].current && cfg[CFG_AUTH_NPIV].current) {
788 		(void) strlcat(buffer, "fcsp:Supported",
789 		    sizeof (buffer));
790 	} else {
791 		(void) strlcat(buffer, "fcsp:Disabled",
792 		    sizeof (buffer));
793 	}
794 #endif /* DHCHAP_SUPPORT */
795 
796 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
797 	    "FDISC: did=%x sid=%x %s", did, port->did, buffer);
798 
799 	/* Preset the state for the reg_did */
800 	emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1);
801 
802 	if (emlxs_els_delay_discovery(port, sbp)) {
803 		/* Deferred registration of this pkt until */
804 		/* Clean Address timeout */
805 		return;
806 	}
807 
808 	if (EMLXS_SLI_REG_DID(port, FABRIC_DID, &port->fabric_sparam, sbp,
809 	    NULL, NULL) == 0) {
810 		/*
811 		 * Deferred completion of this pkt until login is complete
812 		 */
813 		return;
814 	}
815 
816 	emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, IOERR_NO_RESOURCES, 1);
817 
818 	return;
819 
820 } /* emlxs_handle_sol_fdisc() */
821 
822 
823 static void
824 emlxs_handle_sol_plogi(emlxs_port_t *port, emlxs_buf_t *sbp)
825 {
826 	emlxs_hba_t *hba = HBA;
827 	emlxs_config_t *cfg = &CFG;
828 	SERV_PARM *sp;
829 	fc_packet_t *pkt;
830 	uint32_t did;
831 	uint32_t sid;
832 	NODELIST *ndlp;
833 	char buffer[64];
834 
835 	pkt = PRIV2PKT(sbp);
836 	sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t));
837 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
838 	sid = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.s_id);
839 
840 	buffer[0] = 0;
841 
842 #ifdef DHCHAP_SUPPORT
843 	if (!sp->cmn.fcsp_support) {
844 		(void) strlcat(buffer, "fcsp:Unsupported",
845 		    sizeof (buffer));
846 	} else if (cfg[CFG_AUTH_ENABLE].current && cfg[CFG_AUTH_E2E].current &&
847 	    (port->vpi == 0 || cfg[CFG_AUTH_NPIV].current)) {
848 		(void) strlcat(buffer, "fcsp:Supported",
849 		    sizeof (buffer));
850 	} else {
851 		(void) strlcat(buffer, "fcsp:Disabled",
852 		    sizeof (buffer));
853 	}
854 #endif /* DHCHAP_SUPPORT */
855 
856 	if (hba->flag & FC_PT_TO_PT) {
857 		mutex_enter(&EMLXS_PORT_LOCK);
858 
859 		port->did = sid;
860 		port->rdid = did;
861 
862 		/* Save E_D_TOV ticks in nanoseconds */
863 		if (sp->cmn.edtovResolution) {
864 			hba->fc_edtov =
865 			    (LE_SWAP32(sp->cmn.e_d_tov) + 999999) / 1000000;
866 		} else {
867 			hba->fc_edtov = LE_SWAP32(sp->cmn.e_d_tov);
868 		}
869 
870 		/* Only E_D_TOV is valid for PLOGI in pt2pt mode */
871 
872 		mutex_exit(&EMLXS_PORT_LOCK);
873 	}
874 
875 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
876 	    "PLOGI: sid=%x did=%x %s", sid, did, buffer);
877 
878 	/* Preset the pkt state for reg_did */
879 	emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1);
880 
881 	/*
882 	 * Do register login to Firmware before calling packet completion
883 	 */
884 	if (EMLXS_SLI_REG_DID(port, did, sp, sbp, NULL, NULL) == 0) {
885 		/*
886 		 * Deferred completion of this pkt until login is complete
887 		 */
888 		return;
889 	}
890 
891 	ndlp = emlxs_node_find_did(port, did, 1);
892 
893 	if (ndlp && ndlp->nlp_active) {
894 		/* Open the node again */
895 		emlxs_node_open(port, ndlp, hba->channel_fcp);
896 		emlxs_node_open(port, ndlp, hba->channel_ip);
897 	}
898 
899 	emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, IOERR_NO_RESOURCES, 1);
900 
901 	return;
902 
903 } /* emlxs_handle_sol_plogi() */
904 
905 
906 static void
907 emlxs_handle_sol_adisc(emlxs_port_t *port, emlxs_buf_t *sbp)
908 {
909 	emlxs_hba_t *hba = HBA;
910 	fc_packet_t *pkt;
911 	uint32_t did;
912 	NODELIST *ndlp;
913 
914 	pkt = PRIV2PKT(sbp);
915 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
916 
917 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg, "ADISC: did=%x",
918 	    did);
919 
920 	ndlp = emlxs_node_find_did(port, did, 1);
921 
922 	if (ndlp && ndlp->nlp_active) {
923 		/* Open the node again */
924 		emlxs_node_open(port, ndlp, hba->channel_fcp);
925 		emlxs_node_open(port, ndlp, hba->channel_ip);
926 
927 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
928 
929 			emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1);
930 
931 			if (emlxs_rpi_resume_notify(port,
932 			    ndlp->rpip, sbp) == 0) {
933 				/*
934 				 * Delay ADISC cmpl to ULP till
935 				 * after RESUME_RPI
936 				 */
937 				return;
938 			}
939 		}
940 	}
941 
942 	emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
943 
944 	return;
945 
946 } /* emlxs_handle_sol_adisc() */
947 
948 
949 static void
950 emlxs_handle_sol_prli(emlxs_port_t *port, emlxs_buf_t *sbp)
951 {
952 	emlxs_hba_t *hba = HBA;
953 	emlxs_config_t *cfg = &CFG;
954 	fc_packet_t *pkt;
955 	NODELIST *ndlp;
956 	uint32_t did;
957 	PRLI *npr;
958 	uint32_t task_retry_id;
959 
960 	pkt = PRIV2PKT(sbp);
961 	npr = (PRLI *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t));
962 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
963 
964 	ndlp = emlxs_node_find_did(port, did, 1);
965 
966 	if (ndlp && ndlp->nlp_active) {
967 		/* Check for FCP support */
968 		if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) &&
969 		    (npr->prliType == PRLI_FCP_TYPE)) {
970 			/* Clear FCP2 support if no ADISC support requested */
971 			if (cfg[CFG_ADISC_SUPPORT].current == 0) {
972 				npr->ConfmComplAllowed = 0;
973 				npr->TaskRetryIdReq = 0;
974 				npr->Retry = 0;
975 			}
976 
977 			/* Check for target */
978 			if (npr->targetFunc) {
979 				ndlp->nlp_fcp_info |= NLP_FCP_TGT_DEVICE;
980 			} else {
981 				ndlp->nlp_fcp_info &= ~NLP_FCP_TGT_DEVICE;
982 			}
983 #ifdef NODE_THROTTLE_SUPPORT
984 			emlxs_node_throttle_set(port, ndlp);
985 #endif /* NODE_THROTTLE_SUPPORT */
986 
987 			/* Check for initiator */
988 			if (npr->initiatorFunc) {
989 				ndlp->nlp_fcp_info |= NLP_FCP_INI_DEVICE;
990 			} else {
991 				ndlp->nlp_fcp_info &= ~NLP_FCP_INI_DEVICE;
992 			}
993 
994 			/* If TRI support is not required then force */
995 			/* the task_retry_id value to one */
996 			if (cfg[CFG_TRI_REQUIRED].current == 0) {
997 				task_retry_id = 1;
998 			} else {
999 				task_retry_id = npr->TaskRetryIdReq;
1000 			}
1001 
1002 			/* Check for FCP2 target support */
1003 			/* Retry and TaskRetryId bits are both required here */
1004 			if (npr->targetFunc && npr->Retry && task_retry_id) {
1005 				ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
1006 			} else {
1007 				ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
1008 			}
1009 		}
1010 
1011 		/* Open the node again */
1012 		emlxs_node_open(port, ndlp, hba->channel_fcp);
1013 
1014 		EMLXS_SET_DFC_STATE(ndlp, NODE_ALLOC);
1015 
1016 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
1017 		    "PRLI: did=%x info=%02x", did, ndlp->nlp_fcp_info);
1018 
1019 		/*
1020 		 * Report PRLI completion
1021 		 */
1022 		emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
1023 
1024 	} else {
1025 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
1026 		    "PRLI: did=%x: Node not found. Failing.", did);
1027 
1028 		/*
1029 		 * Report PRLI failed
1030 		 */
1031 		emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
1032 		    IOERR_INVALID_RPI, 1);
1033 	}
1034 	return;
1035 
1036 } /* emlxs_handle_sol_prli() */
1037 
1038 
1039 static void
1040 emlxs_handle_sol_logo(emlxs_port_t *port, emlxs_buf_t *sbp)
1041 {
1042 	emlxs_hba_t *hba = HBA;
1043 	fc_packet_t *pkt;
1044 	uint32_t did;
1045 	NODELIST *ndlp;
1046 
1047 	pkt = PRIV2PKT(sbp);
1048 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
1049 
1050 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg, "LOGO: did=%x",
1051 	    did);
1052 
1053 	ndlp = emlxs_node_find_did(port, did, 1);
1054 
1055 	if (ndlp && ndlp->nlp_active) {
1056 		EMLXS_SET_DFC_STATE(ndlp, NODE_LOGOUT);
1057 
1058 		if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) &&
1059 		    (ndlp->nlp_DID == FABRIC_DID)) {
1060 			(void) emlxs_vpi_logo_cmpl_notify(port);
1061 		} else {
1062 			/* Close the node for any further normal IO */
1063 			emlxs_node_close(port, ndlp, hba->channel_fcp, 60);
1064 			emlxs_node_close(port, ndlp, hba->channel_ip, 60);
1065 
1066 			/* Flush tx queues */
1067 			(void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0);
1068 
1069 			/* Flush chip queues */
1070 			(void) emlxs_chipq_node_flush(port, 0, ndlp, 0);
1071 		}
1072 	}
1073 
1074 	emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
1075 
1076 	if ((hba->sli_mode == EMLXS_HBA_SLI3_MODE) &&
1077 	    (ndlp->nlp_DID == FABRIC_DID)) {
1078 		port->flag &= ~EMLXS_PORT_FLOGI_CMPL;
1079 	}
1080 
1081 	return;
1082 
1083 } /* emlxs_handle_sol_logo() */
1084 
1085 
1086 /* ARGSUSED */
1087 static void
1088 emlxs_handle_unsol_rscn(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1089     MATCHMAP *mp, uint32_t size)
1090 {
1091 	uint32_t *lp;
1092 	fc_unsol_buf_t *ubp;
1093 	uint8_t *bp;
1094 	IOCB *iocb;
1095 	uint32_t count;
1096 	uint32_t sid;
1097 	emlxs_ub_priv_t *ub_priv;
1098 
1099 	iocb = &iocbq->iocb;
1100 	bp = mp->virt;
1101 	lp = (uint32_t *)bp + 1;
1102 	sid = iocb->un.elsreq.remoteID;
1103 
1104 	/* Log the legacy rscn event for physical port only */
1105 	if (port->vpi == 0) {
1106 		emlxs_log_rscn_event(port, bp, size);
1107 	}
1108 
1109 	/* Log the vport rscn event for all ports */
1110 	emlxs_log_vportrscn_event(port, bp, size);
1111 
1112 	count = ((size - 4) / 4);
1113 
1114 	ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
1115 	    FC_TYPE_EXTENDED_LS, 1);
1116 
1117 	if (ubp == NULL) {
1118 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
1119 		    "RSCN rcvd: sid=%x  %d page(s): %08X, %08X. Rejecting.",
1120 		    sid, count, LE_SWAP32(*lp),
1121 		    ((count > 1) ? LE_SWAP32(*(lp + 1)) : 0));
1122 
1123 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1124 		    ELS_CMD_RSCN, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
1125 
1126 		goto drop_it;
1127 	}
1128 
1129 	bcopy(bp, ubp->ub_buffer, size);
1130 	ub_priv = ubp->ub_fca_private;
1131 	ub_priv->cmd = ELS_CMD_RSCN;
1132 
1133 	/*
1134 	 * Setup frame header
1135 	 */
1136 	ubp->ub_frame.r_ctl = FC_ELS_REQ;
1137 	ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
1138 	ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
1139 	ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
1140 	ubp->ub_frame.ox_id = ub_priv->token;
1141 	ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
1142 	ubp->ub_class = FC_TRAN_CLASS3;
1143 
1144 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1145 	    "RSCN: sid=%x  %d page(s): %08X, %08X  buffer=%p token=%x.", sid,
1146 	    count, LE_SWAP32(*lp),
1147 	    ((count > 1) ? LE_SWAP32(*(lp + 1)) : 0), ubp, ub_priv->token);
1148 
1149 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
1150 	emlxs_swap_els_ub(ubp);
1151 #endif /* EMLXS_MODREV2X */
1152 
1153 	emlxs_ub_callback(port, ubp);
1154 
1155 drop_it:
1156 
1157 	return;
1158 
1159 } /* emlxs_handle_unsol_rscn() */
1160 
1161 
1162 /* This is shared by FCT driver */
1163 extern uint32_t
1164 emlxs_process_unsol_flogi(emlxs_port_t *port, IOCBQ *iocbq, MATCHMAP *mp,
1165     uint32_t size, char *buffer, size_t len)
1166 {
1167 	emlxs_hba_t *hba = HBA;
1168 	emlxs_config_t *cfg = &CFG;
1169 	uint8_t *bp;
1170 	IOCB *iocb;
1171 	uint32_t sid;
1172 	SERV_PARM *sp;
1173 
1174 	iocb = &iocbq->iocb;
1175 	sid = iocb->un.elsreq.remoteID;
1176 
1177 	/* Check payload size */
1178 	if (size < (sizeof (SERV_PARM) + 4)) {
1179 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1180 		    "FLOGI: sid=%x. Payload too small. %d<%d Rejecting.", sid,
1181 		    size, (sizeof (SERV_PARM) + 4));
1182 
1183 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1184 		    ELS_CMD_FLOGI, LSRJT_PROTOCOL_ERR, LSEXP_NOTHING_MORE);
1185 
1186 		return (1);
1187 	}
1188 
1189 	bp = mp->virt;
1190 	sp = (SERV_PARM *)(bp + sizeof (uint32_t));
1191 
1192 	mutex_enter(&EMLXS_PORT_LOCK);
1193 
1194 	hba->flag &= ~FC_FABRIC_ATTACHED;
1195 	hba->flag |= FC_PT_TO_PT;
1196 
1197 	bcopy((void *)sp, (void *)&port->fabric_sparam, sizeof (SERV_PARM));
1198 
1199 	/* Save E_D_TOV ticks in nanoseconds */
1200 	if (sp->cmn.edtovResolution) {
1201 		hba->fc_edtov =
1202 		    (LE_SWAP32(sp->cmn.e_d_tov) + 999999) / 1000000;
1203 	} else {
1204 		hba->fc_edtov = LE_SWAP32(sp->cmn.e_d_tov);
1205 	}
1206 
1207 	/* Typically the FLOGI ACC rsp has the R_A_TOV value both sides use */
1208 
1209 	hba->flag &= ~FC_NPIV_SUPPORTED;
1210 	(void) strlcpy(buffer, "npiv:Disabled.", len);
1211 
1212 	if (emlxs_wwn_cmp((uint8_t *)&sp->portName,
1213 	    (uint8_t *)&port->wwpn) > 0) {
1214 		(void) strlcat(buffer, " P2P Master.", len);
1215 	} else {
1216 		(void) strlcat(buffer, " P2P Slave.", len);
1217 	}
1218 
1219 #ifdef DHCHAP_SUPPORT
1220 	if (!sp->cmn.fcsp_support) {
1221 		(void) strlcat(buffer, " fcsp:Unsupported", len);
1222 	} else if (cfg[CFG_AUTH_ENABLE].current &&
1223 	    (port->vpi == 0 || cfg[CFG_AUTH_NPIV].current)) {
1224 		(void) strlcat(buffer, " fcsp:Supported", len);
1225 	} else {
1226 		(void) strlcat(buffer, " fcsp:Disabled", len);
1227 	}
1228 #endif /* DHCHAP_SUPPORT */
1229 
1230 	mutex_exit(&EMLXS_PORT_LOCK);
1231 
1232 	return (0);
1233 
1234 } /* emlxs_process_unsol_flogi() */
1235 
1236 
1237 /* ARGSUSED */
1238 static void
1239 emlxs_handle_unsol_flogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1240     MATCHMAP *mp, uint32_t size)
1241 {
1242 	uint8_t *bp;
1243 	fc_unsol_buf_t *ubp;
1244 	IOCB *iocb;
1245 	uint32_t sid;
1246 	emlxs_ub_priv_t *ub_priv;
1247 	char buffer[64];
1248 
1249 	buffer[0] = 0;
1250 
1251 	/* Perform processing of FLOGI payload */
1252 	if (emlxs_process_unsol_flogi(port, iocbq, mp, size, buffer,
1253 	    sizeof (buffer))) {
1254 		return;
1255 	}
1256 
1257 	iocb = &iocbq->iocb;
1258 	sid = iocb->un.elsreq.remoteID;
1259 	bp = mp->virt;
1260 	size = sizeof (SERV_PARM) + 4;
1261 
1262 	ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
1263 	    FC_TYPE_EXTENDED_LS, 0);
1264 
1265 	if (ubp == NULL) {
1266 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
1267 		    "FLOGI rcvd: sid=%x. Rejecting.", sid);
1268 
1269 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1270 		    ELS_CMD_FLOGI, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
1271 
1272 		goto drop_it;
1273 	}
1274 
1275 	/*
1276 	 * Setup unsolicited buffer and pass it up
1277 	 */
1278 	bcopy(bp, ubp->ub_buffer, size);
1279 	ub_priv = ubp->ub_fca_private;
1280 	ub_priv->cmd = ELS_CMD_FLOGI;
1281 
1282 	/*
1283 	 * Setup frame header
1284 	 */
1285 	ubp->ub_frame.r_ctl = FC_ELS_REQ;
1286 	ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
1287 	ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
1288 	ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
1289 	ubp->ub_frame.ox_id = ub_priv->token;
1290 	ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
1291 	ubp->ub_class = FC_TRAN_CLASS3;
1292 
1293 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1294 	    "FLOGI: sid=%x buffer=%p token=%x %s", sid, ubp, ub_priv->token,
1295 	    buffer);
1296 
1297 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
1298 	emlxs_swap_els_ub(ubp);
1299 #endif /* EMLXS_MODREV2X */
1300 
1301 	emlxs_ub_callback(port, ubp);
1302 
1303 drop_it:
1304 
1305 	return;
1306 
1307 } /* emlxs_handle_unsol_flogi() */
1308 
1309 
1310 
1311 /* This is shared by FCT driver */
1312 extern uint32_t
1313 emlxs_process_unsol_plogi(emlxs_port_t *port, IOCBQ *iocbq, MATCHMAP *mp,
1314     uint32_t size, char *buffer, size_t len)
1315 {
1316 	emlxs_hba_t *hba = HBA;
1317 	emlxs_config_t *cfg = &CFG;
1318 	uint8_t *bp;
1319 	IOCB *iocb;
1320 	uint32_t sid;
1321 	uint32_t did;
1322 	SERV_PARM *sp;
1323 	MAILBOXQ *mbox;
1324 	emlxs_vvl_fmt_t vvl;
1325 	int rc;
1326 
1327 	iocb = &iocbq->iocb;
1328 	did = iocb->un.elsreq.myID;
1329 	sid = iocb->un.elsreq.remoteID;
1330 
1331 	if (size < (sizeof (SERV_PARM) + 4)) {
1332 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1333 		    "PLOGI: sid=%x. Payload too small. %d<%d Rejecting.", sid,
1334 		    size, (sizeof (SERV_PARM) + 4));
1335 
1336 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1337 		    ELS_CMD_PLOGI, LSRJT_PROTOCOL_ERR, LSEXP_NOTHING_MORE);
1338 
1339 		return (1);
1340 	}
1341 
1342 	bp = mp->virt;
1343 	sp = (SERV_PARM *)(bp + sizeof (uint32_t));
1344 
1345 	bzero((char *)&vvl, sizeof (emlxs_vvl_fmt_t));
1346 
1347 	if (sp->VALID_VENDOR_VERSION) {
1348 
1349 		bcopy((caddr_t *)&sp->vendorVersion[0],
1350 		    (caddr_t *)&vvl, sizeof (emlxs_vvl_fmt_t));
1351 		vvl.un0.word0 = LE_SWAP32(vvl.un0.word0);
1352 		vvl.un1.word1 = LE_SWAP32(vvl.un1.word1);
1353 	}
1354 
1355 	if ((port->mode == MODE_INITIATOR) &&
1356 	    (port->flag & EMLXS_PORT_RESTRICTED)) {
1357 		uint32_t reject_it = 0;
1358 
1359 		/* If remote port is the virtual port, then reject it */
1360 		if ((vvl.un0.w0.oui == 0x0000C9) && (vvl.un1.w1.vport)) {
1361 			reject_it = 1;
1362 		}
1363 
1364 		/* If we are a virtual port and the remote device */
1365 		/* is not a switch, then reject it */
1366 		else if (port->vpi && ((sid & FABRIC_DID_MASK) !=
1367 		    FABRIC_DID_MASK)) {
1368 			reject_it = 1;
1369 		}
1370 
1371 		if (reject_it) {
1372 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1373 			    "PLOGI rcvd: sid=%x. Restricted. Rejecting.",
1374 			    sid);
1375 
1376 			(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1377 			    ELS_CMD_PLOGI, LSRJT_UNABLE_TPC,
1378 			    LSEXP_NOTHING_MORE);
1379 
1380 			/* Clear temporary RPI in firmware */
1381 			if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
1382 				(void) EMLXS_SLI_REG_DID(port, sid, sp,
1383 				    NULL, NULL, (IOCBQ *)1);
1384 			}
1385 
1386 			return (1);
1387 		}
1388 	}
1389 
1390 #ifdef DHCHAP_SUPPORT
1391 	if (emlxs_dhc_verify_login(port, sid, sp)) {
1392 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1393 		    "PLOGI: sid=%x. FCSP disabled. Rejecting.", sid);
1394 
1395 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1396 		    ELS_CMD_PLOGI, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
1397 
1398 		return (1);
1399 	}
1400 
1401 	if (!sp->cmn.fcsp_support) {
1402 		(void) strlcat(buffer, "fcsp:Unsupported", len);
1403 	} else if (cfg[CFG_AUTH_ENABLE].current && cfg[CFG_AUTH_E2E].current &&
1404 	    (port->vpi == 0 || cfg[CFG_AUTH_NPIV].current)) {
1405 		(void) strlcat(buffer, "fcsp:Supported", len);
1406 	} else {
1407 		(void) strlcat(buffer, "fcsp:Disabled", len);
1408 	}
1409 #endif /* DHCHAP_SUPPORT */
1410 
1411 	/* Check if this was a point to point Plogi */
1412 	if (hba->flag & FC_PT_TO_PT) {
1413 		mutex_enter(&EMLXS_PORT_LOCK);
1414 
1415 		port->did = did;
1416 		port->rdid = sid;
1417 
1418 		/* Save E_D_TOV ticks in nanoseconds */
1419 		if (sp->cmn.edtovResolution) {
1420 			hba->fc_edtov =
1421 			    (LE_SWAP32(sp->cmn.e_d_tov) + 999999) / 1000000;
1422 		} else {
1423 			hba->fc_edtov = LE_SWAP32(sp->cmn.e_d_tov);
1424 		}
1425 
1426 		/* Only E_D_TOV is valid for PLOGI in pt2pt mode */
1427 
1428 		mutex_exit(&EMLXS_PORT_LOCK);
1429 
1430 		if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
1431 			/* Update our service parms */
1432 			if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
1433 			    MEM_MBOX))) {
1434 				emlxs_mb_config_link(hba, mbox);
1435 
1436 				rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox,
1437 				    MBX_NOWAIT, 0);
1438 				if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
1439 					emlxs_mem_put(hba, MEM_MBOX,
1440 					    (void *)mbox);
1441 				}
1442 
1443 			}
1444 		}
1445 	}
1446 
1447 	return (0);
1448 
1449 } /* emlxs_process_unsol_plogi() */
1450 
1451 
1452 /* ARGSUSED */
1453 static void
1454 emlxs_handle_unsol_plogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1455     MATCHMAP *mp, uint32_t size)
1456 {
1457 	emlxs_hba_t *hba = HBA;
1458 	fc_unsol_buf_t *ubp;
1459 	uint8_t *bp;
1460 	IOCB *iocb;
1461 	uint32_t sid;
1462 	uint32_t did;
1463 	emlxs_ub_priv_t *ub_priv;
1464 	SERV_PARM *sp;
1465 	char buffer[64];
1466 
1467 	buffer[0] = 0;
1468 
1469 	/* Perform processing of PLOGI payload */
1470 	if (emlxs_process_unsol_plogi(port, iocbq, mp, size, buffer,
1471 	    sizeof (buffer))) {
1472 		return;
1473 	}
1474 
1475 	iocb = &iocbq->iocb;
1476 	sid = iocb->un.elsreq.remoteID;
1477 	did = iocb->un.elsreq.myID;
1478 	bp = mp->virt;
1479 	sp = (SERV_PARM *)(bp + sizeof (uint32_t));
1480 	size = sizeof (SERV_PARM) + 4;
1481 
1482 #ifdef SAN_DIAG_SUPPORT
1483 	emlxs_log_sd_basic_els_event(port, SD_ELS_SUBCATEGORY_PLOGI_RCV,
1484 	    (HBA_WWN *)&sp->portName, (HBA_WWN *)&sp->nodeName);
1485 #endif
1486 
1487 	ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
1488 	    FC_TYPE_EXTENDED_LS, 0);
1489 
1490 	if (ubp == NULL) {
1491 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
1492 		    "PLOGI rcvd: sid=%x. Rejecting.", sid);
1493 
1494 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1495 		    ELS_CMD_PLOGI, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
1496 
1497 		goto drop_it;
1498 	}
1499 
1500 	/*
1501 	 * Setup unsolicited buffer and pass it up
1502 	 */
1503 	bcopy(bp, ubp->ub_buffer, size);
1504 	ub_priv = ubp->ub_fca_private;
1505 	ub_priv->cmd = ELS_CMD_PLOGI;
1506 
1507 	/*
1508 	 * Setup frame header
1509 	 */
1510 	ubp->ub_frame.r_ctl = FC_ELS_REQ;
1511 	ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
1512 	ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
1513 	ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
1514 	ubp->ub_frame.ox_id = ub_priv->token;
1515 	ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
1516 	ubp->ub_class = FC_TRAN_CLASS3;
1517 
1518 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1519 	    "PLOGI: sid=%x did=%x buffer=%p token=%x %s", sid, did, ubp,
1520 	    ub_priv->token, buffer);
1521 
1522 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
1523 	emlxs_swap_els_ub(ubp);
1524 #endif /* EMLXS_MODREV2X */
1525 
1526 	/* Create a new node and defer callback */
1527 	if (EMLXS_SLI_REG_DID(port, sid, sp, NULL, ubp, NULL) == 0) {
1528 		/*
1529 		 * Defer completion of this pkt until login is complete
1530 		 */
1531 		goto drop_it;
1532 	}
1533 
1534 	emlxs_ub_callback(port, ubp);
1535 
1536 drop_it:
1537 
1538 	return;
1539 
1540 } /* emlxs_handle_unsol_plogi() */
1541 
1542 
1543 /* ARGSUSED */
1544 static void
1545 emlxs_handle_unsol_prli(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1546     MATCHMAP *mp, uint32_t size)
1547 {
1548 	emlxs_hba_t	*hba = HBA;
1549 	emlxs_config_t	*cfg = &CFG;
1550 	IOCB *iocb;
1551 	uint32_t sid;
1552 	NODELIST *ndlp;
1553 	PRLI *npr;
1554 	fc_unsol_buf_t *ubp;
1555 	emlxs_ub_priv_t *ub_priv;
1556 	uint32_t task_retry_id;
1557 
1558 	iocb = &iocbq->iocb;
1559 	sid = iocb->un.elsreq.remoteID;
1560 	ndlp = emlxs_node_find_did(port, sid, 1);
1561 
1562 	if (!ndlp || !ndlp->nlp_active) {
1563 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1564 		    "PRLI: sid=%x: Node not found. Rejecting.", sid);
1565 
1566 		/* Auto reply to PRLI's */
1567 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1568 		    ELS_CMD_PRLI, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
1569 
1570 		goto drop_it;
1571 	}
1572 
1573 	/* If node exists then save FCP2 support */
1574 	npr = (PRLI *)((caddr_t)mp->virt + sizeof (uint32_t));
1575 
1576 	/* Check for FCP2 support */
1577 	if ((npr->prliType == PRLI_FCP_TYPE) && npr->targetFunc) {
1578 		/* Clear FCP2 support if no ADISC support is requested */
1579 		if (cfg[CFG_ADISC_SUPPORT].current == 0) {
1580 			npr->ConfmComplAllowed = 0;
1581 			npr->TaskRetryIdReq = 0;
1582 			npr->Retry = 0;
1583 		}
1584 
1585 		/* Check for target */
1586 		if (npr->targetFunc) {
1587 			ndlp->nlp_fcp_info |= NLP_FCP_TGT_DEVICE;
1588 		} else {
1589 			ndlp->nlp_fcp_info &= ~NLP_FCP_TGT_DEVICE;
1590 		}
1591 #ifdef NODE_THROTTLE_SUPPORT
1592 		emlxs_node_throttle_set(port, ndlp);
1593 #endif /* NODE_THROTTLE_SUPPORT */
1594 
1595 		/* Check for initiator */
1596 		if (npr->initiatorFunc) {
1597 			ndlp->nlp_fcp_info |= NLP_FCP_INI_DEVICE;
1598 		} else {
1599 			ndlp->nlp_fcp_info &= ~NLP_FCP_INI_DEVICE;
1600 		}
1601 
1602 		/* If TRI support is not required then force */
1603 		/* the task_retry_id value to one */
1604 		if (cfg[CFG_TRI_REQUIRED].current == 0) {
1605 			task_retry_id = 1;
1606 		} else {
1607 			task_retry_id = npr->TaskRetryIdReq;
1608 		}
1609 
1610 		/* Check for FCP2 target support */
1611 		/* Retry and TaskRetryId bits are both required here */
1612 		if (npr->targetFunc && npr->Retry && task_retry_id) {
1613 			ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
1614 		} else {
1615 			ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
1616 		}
1617 	}
1618 
1619 #ifdef ULP_PATCH3
1620 	if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH3) {
1621 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1622 		    "PRLI: sid=%x. Accepting.", sid);
1623 
1624 		/* Auto reply to PRLI's */
1625 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC,
1626 		    ELS_CMD_PRLI, 0, 0);
1627 		goto drop_it;
1628 	}
1629 #endif /* ULP_PATCH3 */
1630 
1631 	/* Tell ULP about it */
1632 	ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
1633 	    FC_TYPE_EXTENDED_LS, 0);
1634 
1635 	if (ubp == NULL) {
1636 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
1637 		    "PRLI rcvd: sid=%x. Rejecting.", sid);
1638 
1639 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1640 		    ELS_CMD_PRLI, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
1641 
1642 		goto drop_it;
1643 	}
1644 
1645 	/*
1646 	 * Setup unsolicited buffer and pass it up
1647 	 */
1648 	bcopy(mp->virt, ubp->ub_buffer, size);
1649 	ub_priv = ubp->ub_fca_private;
1650 	ub_priv->cmd = ELS_CMD_PRLI;
1651 
1652 	/*
1653 	 * Setup frame header
1654 	 */
1655 	ubp->ub_frame.r_ctl = FC_ELS_REQ;
1656 	ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
1657 	ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
1658 	ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
1659 	ubp->ub_frame.ox_id = ub_priv->token;
1660 	ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
1661 	ubp->ub_class = FC_TRAN_CLASS3;
1662 
1663 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1664 	    "PRLI: sid=%x buffer=%p token=%x info=%02x", sid, ubp,
1665 	    ub_priv->token, ndlp->nlp_fcp_info);
1666 
1667 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
1668 	emlxs_swap_els_ub(ubp);
1669 #endif /* EMLXS_MODREV2X */
1670 
1671 	emlxs_ub_callback(port, ubp);
1672 
1673 drop_it:
1674 
1675 	return;
1676 
1677 } /* emlxs_handle_unsol_prli() */
1678 
1679 
1680 /* ARGSUSED */
1681 static void
1682 emlxs_handle_unsol_auth(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1683     MATCHMAP *mp, uint32_t size)
1684 {
1685 	IOCB *iocb;
1686 	uint32_t sid;
1687 	NODELIST *ndlp;
1688 
1689 	iocb = &iocbq->iocb;
1690 	sid = iocb->un.elsreq.remoteID;
1691 
1692 #ifdef DHCHAP_SUPPORT
1693 	ndlp = emlxs_node_find_did(port, sid, 1);
1694 
1695 	if (!ndlp || !ndlp->nlp_active) {
1696 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1697 		    "AUTH: sid=%x: Node not found. Rejecting.", sid);
1698 
1699 		/* Auto reply to AUTH_ELS's */
1700 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1701 		    ELS_CMD_AUTH, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
1702 
1703 		goto drop_it;
1704 	}
1705 
1706 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, "AUTH: sid=%x", sid);
1707 
1708 	(void) emlxs_dhchap_state_machine(port, cp, iocbq, mp, ndlp,
1709 	    NODE_EVENT_RCV_AUTH_MSG);
1710 #else
1711 
1712 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1713 	    "AUTH: sid=%x: Rejecting.", sid);
1714 	(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, ELS_CMD_AUTH,
1715 	    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
1716 
1717 #endif /* DHCAHP_SUPPORT */
1718 
1719 drop_it:
1720 
1721 	return;
1722 
1723 } /* emlxs_handle_unsol_auth() */
1724 
1725 
1726 /* ARGSUSED */
1727 static void
1728 emlxs_handle_unsol_adisc(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1729     MATCHMAP *mp, uint32_t size)
1730 {
1731 	IOCB		*iocb;
1732 #ifdef SAN_DIAG_SUPPORT
1733 	NODELIST	*ndlp;
1734 #endif
1735 	uint32_t	sid;
1736 
1737 	iocb = &iocbq->iocb;
1738 	sid = iocb->un.elsreq.remoteID;
1739 
1740 #ifdef SAN_DIAG_SUPPORT
1741 	ndlp = emlxs_node_find_did(port, sid, 1);
1742 
1743 	if (ndlp) {
1744 		emlxs_log_sd_basic_els_event(port, SD_ELS_SUBCATEGORY_ADISC_RCV,
1745 		    (HBA_WWN *)&ndlp->nlp_portname,
1746 		    (HBA_WWN *)&ndlp->nlp_nodename);
1747 	}
1748 #endif
1749 
1750 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1751 	    "ADISC: sid=%x: Accepting.", sid);
1752 	(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_ADISC, 0, 0);
1753 
1754 	return;
1755 
1756 } /* emlxs_handle_unsol_adisc() */
1757 
1758 
1759 /* ARGSUSED */
1760 static void
1761 emlxs_handle_unsol_prlo(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1762     MATCHMAP *mp, uint32_t size)
1763 {
1764 	emlxs_hba_t	*hba = HBA;
1765 	emlxs_config_t	*cfg = &CFG;
1766 	IOCB *iocb;
1767 	uint32_t sid;
1768 	fc_unsol_buf_t *ubp;
1769 	emlxs_ub_priv_t *ub_priv;
1770 	NODELIST *ndlp;
1771 
1772 	iocb = &iocbq->iocb;
1773 	sid = iocb->un.elsreq.remoteID;
1774 
1775 	/* Get the node */
1776 	ndlp = emlxs_node_find_did(port, sid, 1);
1777 
1778 #ifdef SAN_DIAG_SUPPORT
1779 	if (ndlp) {
1780 		emlxs_log_sd_prlo_event(port, (HBA_WWN *)&ndlp->nlp_portname);
1781 	}
1782 #endif
1783 
1784 #ifdef ULP_PATCH4
1785 	if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH4) {
1786 #ifdef ULP_PATCH6
1787 		if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH6) {
1788 			/* Check if this is a SCSI target */
1789 			if (ndlp && (ndlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE)) {
1790 				/* This is a SCSI target */
1791 
1792 				/* If only one node is present, then we can */
1793 				/* conclude that we are direct attached */
1794 				/* to a target */
1795 				if (port->node_count == 1) {
1796 					EMLXS_MSGF(EMLXS_CONTEXT,
1797 					    &emlxs_unsol_els_msg,
1798 					    "PRLO: sid=%x. Accepting and " \
1799 					    "reseting link.",
1800 					    sid);
1801 
1802 					/* Send Acc */
1803 					(void) emlxs_els_reply(port, iocbq,
1804 					    ELS_CMD_ACC, ELS_CMD_PRLO, 0, 0);
1805 
1806 					/* Spawn a thread to reset the link */
1807 					emlxs_thread_spawn(hba,
1808 					    emlxs_reset_link_thread,
1809 					    NULL, NULL);
1810 
1811 					goto drop_it;
1812 
1813 				}
1814 				/* Check if fabric is present */
1815 				else if (hba->flag & FC_FABRIC_ATTACHED) {
1816 					/* Auto reply to PRLO */
1817 					EMLXS_MSGF(EMLXS_CONTEXT,
1818 					    &emlxs_unsol_els_msg,
1819 					    "PRLO: sid=%x. Accepting and " \
1820 					    "generating RSCN.",
1821 					    sid);
1822 
1823 					/* Send Acc */
1824 					(void) emlxs_els_reply(port, iocbq,
1825 					    ELS_CMD_ACC, ELS_CMD_PRLO, 0, 0);
1826 
1827 					/* Generate an RSCN to wakeup ULP */
1828 					(void) emlxs_generate_rscn(port, sid);
1829 
1830 					goto drop_it;
1831 				}
1832 			}
1833 		}
1834 #endif /* ULP_PATCH6 */
1835 
1836 		/* Auto reply to PRLO */
1837 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1838 		    "PRLO: sid=%x. Accepting.", sid);
1839 
1840 		/* Send Acc */
1841 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC,
1842 		    ELS_CMD_PRLO, 0, 0);
1843 
1844 		goto drop_it;
1845 	}
1846 #endif /* ULP_PATCH4 */
1847 
1848 	/* Tell ULP about it */
1849 
1850 	ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
1851 	    FC_TYPE_EXTENDED_LS, 0);
1852 
1853 	if (ubp == NULL) {
1854 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
1855 		    "PRLO recvd: sid=%x. Rejecting.", sid);
1856 
1857 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1858 		    ELS_CMD_PRLO, LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
1859 
1860 		goto drop_it;
1861 	}
1862 
1863 	/*
1864 	 * Setup unsolicited buffer and pass it up
1865 	 */
1866 	bcopy(mp->virt, ubp->ub_buffer, size);
1867 	ub_priv = ubp->ub_fca_private;
1868 	ub_priv->cmd = ELS_CMD_PRLO;
1869 
1870 	/*
1871 	 * Setup frame header
1872 	 */
1873 	ubp->ub_frame.r_ctl = FC_ELS_REQ;
1874 	ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
1875 	ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
1876 	ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
1877 	ubp->ub_frame.ox_id = ub_priv->token;
1878 	ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
1879 	ubp->ub_class = FC_TRAN_CLASS3;
1880 
1881 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1882 	    "PRLO: sid=%x buffeiocbr=%p token=%x.", sid, ubp, ub_priv->token);
1883 
1884 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
1885 	emlxs_swap_els_ub(ubp);
1886 #endif /* EMLXS_MODREV2X */
1887 
1888 	emlxs_ub_callback(port, ubp);
1889 
1890 drop_it:
1891 
1892 	return;
1893 
1894 } /* emlxs_handle_unsol_prlo() */
1895 
1896 
1897 /* ARGSUSED */
1898 static void
1899 emlxs_handle_unsol_logo(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
1900     MATCHMAP *mp, uint32_t size)
1901 {
1902 	emlxs_hba_t *hba = HBA;
1903 	emlxs_config_t	*cfg = &CFG;
1904 	fc_unsol_buf_t *ubp;
1905 	IOCB *iocb;
1906 	uint32_t sid;
1907 	emlxs_ub_priv_t *ub_priv;
1908 	uint32_t reply_sent = 0;
1909 	NODELIST *ndlp;
1910 
1911 	iocb = &iocbq->iocb;
1912 	sid = iocb->un.elsreq.remoteID;
1913 
1914 	ndlp = emlxs_node_find_did(port, sid, 1);
1915 
1916 #ifdef SAN_DIAG_SUPPORT
1917 	if (ndlp) {
1918 		emlxs_log_sd_basic_els_event(port,  SD_ELS_SUBCATEGORY_LOGO_RCV,
1919 		    (HBA_WWN *)&ndlp->nlp_portname,
1920 		    (HBA_WWN *)((uint32_t *)mp->virt + 2));
1921 	}
1922 #endif
1923 
1924 	EMLXS_SET_DFC_STATE(ndlp, NODE_LOGOUT);
1925 
1926 #ifdef ULP_PATCH6
1927 	if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH6) {
1928 		/* Check if this is a SCSI target */
1929 		if (ndlp && (ndlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE)) {
1930 			/* This is a SCSI target */
1931 
1932 			/* If only one node is present, then we can */
1933 			/* conclude that we are direct attached to a target */
1934 			if (port->node_count == 1) {
1935 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1936 				    "LOGO: sid=%x. Accepting and "\
1937 				    "reseting link.", sid);
1938 
1939 				(void) emlxs_els_reply(port, iocbq,
1940 				    ELS_CMD_ACC, ELS_CMD_LOGO, 0, 0);
1941 
1942 				/* Spawn a thread to reset the link */
1943 				emlxs_thread_spawn(hba, emlxs_reset_link_thread,
1944 				    NULL, NULL);
1945 
1946 				goto drop_it;
1947 			}
1948 			/* Check if fabric node is present */
1949 			else if (hba->flag & FC_FABRIC_ATTACHED) {
1950 				/* Send reply ourselves */
1951 				/* We will block all attempts */
1952 				/* for ULP to reply to a LOGO */
1953 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
1954 				    "LOGO: sid=%x. Accepting and " \
1955 				    "generating RSCN.", sid);
1956 
1957 				(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC,
1958 				    ELS_CMD_LOGO, 0, 0);
1959 
1960 				/* Generate an RSCN to wakeup ULP */
1961 				if (emlxs_generate_rscn(port, sid)
1962 				    == FC_SUCCESS) {
1963 					goto drop_it;
1964 				}
1965 
1966 				reply_sent = 1;
1967 			}
1968 		}
1969 	}
1970 #endif /* ULP_PATCH6 */
1971 
1972 	ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
1973 	    FC_TYPE_EXTENDED_LS, 1);
1974 
1975 	if (ubp == NULL) {
1976 		if (!reply_sent) {
1977 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
1978 			    "LOGO rcvd: sid=%x. Rejecting.", sid);
1979 
1980 			(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
1981 			    ELS_CMD_LOGO, LSRJT_LOGICAL_BSY,
1982 			    LSEXP_OUT_OF_RESOURCE);
1983 		}
1984 
1985 		goto drop_it;
1986 
1987 	}
1988 
1989 	/* Setup unsolicited buffer and pass it up */
1990 	bcopy(mp->virt, ubp->ub_buffer, size);
1991 	ub_priv = ubp->ub_fca_private;
1992 	ub_priv->cmd = ELS_CMD_LOGO;
1993 
1994 	/* Setup frame header */
1995 	ubp->ub_frame.r_ctl = FC_ELS_REQ;
1996 	ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
1997 	ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
1998 	ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
1999 	ubp->ub_frame.ox_id = ub_priv->token;
2000 	ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
2001 	ubp->ub_class = FC_TRAN_CLASS3;
2002 
2003 #ifdef ULP_PATCH2
2004 	if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH2) {
2005 		if (!reply_sent) {
2006 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2007 			    "LOGO: sid=%x buffer=%p token=%x. Accepting.",
2008 			    sid, ubp, ub_priv->token);
2009 
2010 			ub_priv->flags |= EMLXS_UB_REPLY;
2011 
2012 			/* Send Acc */
2013 			/* Send reply ourselves because ULP */
2014 			/* doesn't always reply to these */
2015 			/* We ll block attempts for ULP to reply to a LOGO */
2016 			(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC,
2017 			    ELS_CMD_LOGO, 0, 0);
2018 			reply_sent = 1;
2019 		}
2020 	}
2021 #endif /* ULP_PATCH2 */
2022 
2023 	if (!reply_sent) {
2024 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2025 		    "LOGO: sid=%x buffer=%p token=%x.", sid, ubp,
2026 		    ub_priv->token);
2027 	}
2028 
2029 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
2030 	emlxs_swap_els_ub(ubp);
2031 #endif /* EMLXS_MODREV2X */
2032 
2033 	/* Unregister the node */
2034 	if ((sid & FABRIC_DID_MASK) == FABRIC_DID_MASK) {
2035 		if (ndlp) {
2036 			if (EMLXS_SLI_UNREG_NODE(port, ndlp, NULL,
2037 			    ubp, NULL) == 0) {
2038 				/*
2039 				 * Deferred completion of this ubp
2040 				 * until unreg login is complete
2041 				 */
2042 				return;
2043 			}
2044 		}
2045 	}
2046 
2047 	emlxs_ub_callback(port, ubp);
2048 
2049 drop_it:
2050 
2051 	return;
2052 
2053 } /* emlxs_handle_unsol_logo() */
2054 
2055 
2056 
2057 /* ARGSUSED */
2058 static void
2059 emlxs_handle_unsol_gen_cmd(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
2060     MATCHMAP *mp, uint32_t size)
2061 {
2062 	uint8_t *bp;
2063 	fc_unsol_buf_t *ubp;
2064 	IOCB *iocb;
2065 	uint32_t *lp;
2066 	uint32_t cmd;
2067 	uint32_t sid;
2068 	emlxs_ub_priv_t *ub_priv;
2069 
2070 	iocb = &iocbq->iocb;
2071 	sid = iocb->un.elsreq.remoteID;
2072 
2073 	bp = mp->virt;
2074 	lp = (uint32_t *)bp;
2075 	cmd = *lp & ELS_CMD_MASK;
2076 
2077 	ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, size,
2078 	    FC_TYPE_EXTENDED_LS, 0);
2079 
2080 	if (ubp == NULL) {
2081 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
2082 		    "%s rcvd: sid=%x: Rejecting.", emlxs_elscmd_xlate(cmd),
2083 		    sid);
2084 
2085 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd,
2086 		    LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
2087 
2088 		goto drop_it;
2089 	}
2090 
2091 	bcopy(bp, ubp->ub_buffer, size);
2092 	ub_priv = ubp->ub_fca_private;
2093 	ub_priv->cmd = cmd;
2094 
2095 	/* Setup frame header */
2096 	ubp->ub_frame.r_ctl = FC_ELS_REQ;
2097 	ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
2098 	ubp->ub_frame.s_id = LE_SWAP24_LO(iocb->un.elsreq.remoteID);
2099 	ubp->ub_frame.d_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
2100 	ubp->ub_frame.ox_id = ub_priv->token;
2101 	ubp->ub_frame.rx_id = iocb->ULPCONTEXT;
2102 	ubp->ub_class = FC_TRAN_CLASS3;
2103 
2104 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2105 	    "%s: sid=%x buffer=%p token=%x.", emlxs_elscmd_xlate(cmd), sid,
2106 	    ubp, ub_priv->token);
2107 
2108 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
2109 	emlxs_swap_els_ub(ubp);
2110 #endif /* EMLXS_MODREV2X */
2111 
2112 	emlxs_ub_callback(port, ubp);
2113 
2114 drop_it:
2115 
2116 	return;
2117 
2118 } /* emlxs_handle_unsol_gen_cmd() */
2119 
2120 
2121 /* ARGSUSED */
2122 static void
2123 emlxs_handle_unsol_echo(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
2124     MATCHMAP *mp, uint32_t size)
2125 {
2126 	emlxs_hba_t *hba = HBA;
2127 	uint8_t *bp;
2128 	IOCB *iocb;
2129 	uint32_t *lp;
2130 	uint32_t sid;
2131 	fc_packet_t *pkt;
2132 	uint32_t cmd;
2133 
2134 	iocb = &iocbq->iocb;
2135 	sid = iocb->un.elsreq.remoteID;
2136 
2137 	bp = mp->virt;
2138 	lp = (uint32_t *)bp;
2139 	cmd = *lp & ELS_CMD_MASK;
2140 
2141 	if (!(pkt = emlxs_pkt_alloc(port,
2142 	    size, 0, 0, KM_NOSLEEP))) {
2143 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2144 		    "ECHO: sid=%x. Unable to allocate pkt. Rejecting.",
2145 		    sid);
2146 
2147 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
2148 		    ELS_CMD_ECHO, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
2149 		return;
2150 	}
2151 
2152 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2153 	    "ECHO: sid=%x. Accepting.",
2154 	    sid);
2155 
2156 	/* Common initialization */
2157 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2158 	pkt->pkt_timeout = (2 * hba->fc_ratov);
2159 
2160 	if ((uint32_t)iocb->ULPCLASS == CLASS2) {
2161 		pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
2162 		pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
2163 	}
2164 
2165 	/* Build the fc header */
2166 	pkt->pkt_cmd_fhdr.d_id =
2167 	    LE_SWAP24_LO(iocb->un.elsreq.remoteID);
2168 	pkt->pkt_cmd_fhdr.r_ctl =
2169 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
2170 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
2171 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2172 	pkt->pkt_cmd_fhdr.f_ctl =
2173 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2174 	pkt->pkt_cmd_fhdr.seq_id = 0;
2175 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2176 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2177 	pkt->pkt_cmd_fhdr.ox_id = (cmd >> ELS_CMD_SHIFT) & 0xff;
2178 	pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT;
2179 	pkt->pkt_cmd_fhdr.ro = 0;
2180 
2181 	/* Build the response */
2182 	*lp = ELS_CMD_ACC;
2183 	bcopy(lp, pkt->pkt_cmd, size);
2184 
2185 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2186 		/* Free the pkt */
2187 		emlxs_pkt_free(pkt);
2188 		emlxs_abort_els_exchange(hba, port, iocb->ULPCONTEXT);
2189 	}
2190 
2191 	return;
2192 
2193 } /* emlxs_handle_unsol_echo() */
2194 
2195 
2196 /* ARGSUSED */
2197 static void
2198 emlxs_handle_unsol_rtv(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
2199     MATCHMAP *mp, uint32_t size)
2200 {
2201 	emlxs_hba_t *hba = HBA;
2202 	uint8_t *bp;
2203 	IOCB *iocb;
2204 	uint32_t *lp;
2205 	uint32_t sid;
2206 	fc_packet_t *pkt;
2207 	uint32_t cmd;
2208 	SERV_PARM *sp;
2209 
2210 	iocb = &iocbq->iocb;
2211 	sid = iocb->un.elsreq.remoteID;
2212 
2213 	bp = mp->virt;
2214 	lp = (uint32_t *)bp;
2215 	cmd = *lp & ELS_CMD_MASK;
2216 
2217 	if (!(pkt = emlxs_pkt_alloc(port,
2218 	    (4 * sizeof (uint32_t)), 0, 0, KM_NOSLEEP))) {
2219 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2220 		    "RTV: sid=%x. Unable to allocate pkt. Rejecting.",
2221 		    sid);
2222 
2223 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
2224 		    ELS_CMD_RTV, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
2225 		return;
2226 	}
2227 
2228 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2229 	    "RTV: sid=%x. Accepting.",
2230 	    emlxs_elscmd_xlate(cmd),
2231 	    sid);
2232 
2233 	/* Common initialization */
2234 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2235 	pkt->pkt_timeout = (2 * hba->fc_ratov);
2236 
2237 	if ((uint32_t)iocb->ULPCLASS == CLASS2) {
2238 		pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
2239 		pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
2240 	}
2241 
2242 	/* Build the fc header */
2243 	pkt->pkt_cmd_fhdr.d_id =
2244 	    LE_SWAP24_LO(iocb->un.elsreq.remoteID);
2245 	pkt->pkt_cmd_fhdr.r_ctl =
2246 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
2247 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
2248 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2249 	pkt->pkt_cmd_fhdr.f_ctl =
2250 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2251 	pkt->pkt_cmd_fhdr.seq_id = 0;
2252 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2253 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2254 	pkt->pkt_cmd_fhdr.ox_id = (cmd >> ELS_CMD_SHIFT) & 0xff;
2255 	pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT;
2256 	pkt->pkt_cmd_fhdr.ro = 0;
2257 
2258 	/* Build the response */
2259 	sp = (SERV_PARM *)&port->fabric_sparam;
2260 	lp = (uint32_t *)pkt->pkt_cmd;
2261 	lp[0] = ELS_CMD_ACC;
2262 	lp[1] = LE_SWAP32(sp->cmn.w2.r_a_tov);
2263 	lp[2] = LE_SWAP32(sp->cmn.e_d_tov);
2264 	lp[3] = sp->cmn.edtovResolution << 26;
2265 
2266 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2267 		/* Free the pkt */
2268 		emlxs_pkt_free(pkt);
2269 		emlxs_abort_els_exchange(hba, port, iocb->ULPCONTEXT);
2270 	}
2271 
2272 	return;
2273 
2274 } /* emlxs_handle_unsol_rtv() */
2275 
2276 
2277 /* ARGSUSED */
2278 static void
2279 emlxs_rls_rsp_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2280 {
2281 	emlxs_port_t *port = (emlxs_port_t *)arg1;
2282 	fc_packet_t *pkt = (fc_packet_t *)arg2;
2283 	MAILBOXQ	*mbq = NULL;
2284 	MAILBOX		*mb;
2285 	la_els_rls_acc_t *rls;
2286 	uint32_t rval;
2287 
2288 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2289 	    "RLS: sid=%x. Accepting.",
2290 	    LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id));
2291 
2292 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
2293 		goto dropit;
2294 	}
2295 	mb = (MAILBOX *)mbq;
2296 
2297 	/* Read current link status */
2298 	emlxs_mb_read_lnk_stat(hba, mbq);
2299 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
2300 
2301 	if (rval != MBX_SUCCESS) {
2302 		goto dropit;
2303 	}
2304 
2305 	/* Build the response */
2306 	rls = (la_els_rls_acc_t *)pkt->pkt_cmd;
2307 	rls->ls_code.ls_code = 0x02;
2308 	rls->rls_link_params.rls_link_fail =
2309 	    mb->un.varRdLnk.linkFailureCnt;
2310 	rls->rls_link_params.rls_sync_loss =
2311 	    mb->un.varRdLnk.lossSyncCnt;
2312 	rls->rls_link_params.rls_sig_loss =
2313 	    mb->un.varRdLnk.lossSignalCnt;
2314 	rls->rls_link_params.rls_prim_seq_err =
2315 	    mb->un.varRdLnk.primSeqErrCnt;
2316 	rls->rls_link_params.rls_invalid_word =
2317 	    mb->un.varRdLnk.invalidXmitWord;
2318 	rls->rls_link_params.rls_invalid_crc =
2319 	    mb->un.varRdLnk.crcCnt;
2320 
2321 	LE_SWAP32_BUFFER((uint8_t *)rls, sizeof (la_els_rls_acc_t));
2322 
2323 	emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
2324 	mbq = NULL;
2325 
2326 	if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) {
2327 		goto dropit;
2328 	}
2329 
2330 	return;
2331 
2332 dropit:
2333 
2334 	emlxs_abort_els_exchange(hba, port, pkt->pkt_cmd_fhdr.rx_id);
2335 
2336 	emlxs_pkt_free(pkt);
2337 
2338 	if (mbq) {
2339 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
2340 	}
2341 
2342 	return;
2343 
2344 } /* emlxs_rls_rsp_thread() */
2345 
2346 
2347 /* ARGSUSED */
2348 static void
2349 emlxs_handle_unsol_rls(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
2350     MATCHMAP *mp, uint32_t size)
2351 {
2352 	emlxs_hba_t *hba = HBA;
2353 	uint8_t *bp;
2354 	IOCB *iocb;
2355 	uint32_t *lp;
2356 	uint32_t sid;
2357 	fc_packet_t *pkt;
2358 	uint32_t cmd;
2359 
2360 	iocb = &iocbq->iocb;
2361 	sid = iocb->un.elsreq.remoteID;
2362 
2363 	bp = mp->virt;
2364 	lp = (uint32_t *)bp;
2365 	cmd = *lp++ & ELS_CMD_MASK;
2366 
2367 	if (!(pkt = emlxs_pkt_alloc(port,
2368 	    sizeof (la_els_rls_acc_t), 0, 0, KM_NOSLEEP))) {
2369 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2370 		    "RLS: sid=%x. Unable to allocate pkt.  Rejecting.",
2371 		    sid);
2372 
2373 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
2374 		    ELS_CMD_RLS, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
2375 		return;
2376 	}
2377 
2378 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2379 	    "RLS: sid=%x. Scheduling response.",
2380 	    sid);
2381 
2382 	/* Common initialization */
2383 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2384 	pkt->pkt_timeout = (2 * hba->fc_ratov);
2385 
2386 	if ((uint32_t)iocb->ULPCLASS == CLASS2) {
2387 		pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
2388 		pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
2389 	}
2390 
2391 	/* Build the fc header */
2392 	pkt->pkt_cmd_fhdr.d_id =
2393 	    LE_SWAP24_LO(iocb->un.elsreq.remoteID);
2394 	pkt->pkt_cmd_fhdr.r_ctl =
2395 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
2396 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
2397 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2398 	pkt->pkt_cmd_fhdr.f_ctl =
2399 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2400 	pkt->pkt_cmd_fhdr.seq_id = 0;
2401 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2402 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2403 	pkt->pkt_cmd_fhdr.ox_id = (cmd >> ELS_CMD_SHIFT) & 0xff;
2404 	pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT;
2405 	pkt->pkt_cmd_fhdr.ro = 0;
2406 
2407 	/* We must spawn a separate thread to send the */
2408 	/* read link status mailbox command becasue we are */
2409 	/* normally in a hardware interrupt context here. */
2410 	emlxs_thread_spawn(hba, emlxs_rls_rsp_thread,
2411 	    (void *)port, (void *)pkt);
2412 
2413 	return;
2414 
2415 } /* emlxs_handle_unsol_rls() */
2416 
2417 
2418 /* This handles the reply completions to unsolicited cmds */
2419 /* ARGSUSED */
2420 static void
2421 emlxs_handle_acc(emlxs_port_t *port, emlxs_buf_t *sbp, IOCBQ *iocbq,
2422     uint32_t flag)
2423 {
2424 	emlxs_hba_t *hba = HBA;
2425 	fc_packet_t *pkt;
2426 	IOCB *iocb;
2427 	uint32_t did;
2428 	NODELIST *ndlp;
2429 	uint32_t ucmd;
2430 	uint32_t cmd;
2431 	uint32_t *lp;
2432 
2433 	iocb = &iocbq->iocb;
2434 	pkt = PRIV2PKT(sbp);
2435 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
2436 	ucmd = pkt->pkt_cmd_fhdr.ox_id << ELS_CMD_SHIFT;
2437 	lp = (uint32_t *)pkt->pkt_cmd;
2438 	cmd = *lp & ELS_CMD_MASK;
2439 
2440 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
2441 	    "%s %s: did=%x %s %s", emlxs_elscmd_xlate(ucmd),
2442 	    emlxs_elscmd_xlate(cmd), did, emlxs_state_xlate(iocb->ULPSTATUS),
2443 	    emlxs_error_xlate(iocb->un.grsp.perr.statLocalError));
2444 
2445 	switch (ucmd) {
2446 	case ELS_CMD_PLOGI:
2447 	case ELS_CMD_ADISC:
2448 
2449 		ndlp = emlxs_node_find_did(port, did, 1);
2450 
2451 		if (ndlp && ndlp->nlp_active) {
2452 			/* Open the node again */
2453 			emlxs_node_open(port, ndlp, hba->channel_fcp);
2454 			emlxs_node_open(port, ndlp, hba->channel_ip);
2455 		}
2456 
2457 		break;
2458 
2459 	case ELS_CMD_PRLI:
2460 
2461 		ndlp = emlxs_node_find_did(port, did, 1);
2462 
2463 		if (ndlp && ndlp->nlp_active) {
2464 			EMLXS_SET_DFC_STATE(ndlp, NODE_ALLOC);
2465 
2466 			/* Open the node again */
2467 			emlxs_node_open(port, ndlp, hba->channel_fcp);
2468 		}
2469 
2470 		break;
2471 	}
2472 
2473 	emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
2474 	    iocb->un.grsp.perr.statLocalError, 1);
2475 
2476 	return;
2477 
2478 } /* emlxs_handle_acc() */
2479 
2480 
2481 /* This handles the reply completions to unsolicited cmds */
2482 /* ARGSUSED */
2483 static void
2484 emlxs_handle_reject(emlxs_port_t *port, emlxs_buf_t *sbp, IOCBQ *iocbq,
2485     uint32_t flag)
2486 {
2487 	emlxs_hba_t *hba = HBA;
2488 	fc_packet_t	*pkt;
2489 	NODELIST	*ndlp;
2490 	IOCB		*iocb;
2491 	uint32_t	did;
2492 	uint32_t	ucmd;
2493 	uint32_t	cmd;
2494 	uint32_t	*lp;
2495 
2496 	iocb = &iocbq->iocb;
2497 	pkt = PRIV2PKT(sbp);
2498 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
2499 	ucmd = pkt->pkt_cmd_fhdr.ox_id << ELS_CMD_SHIFT;
2500 	lp = (uint32_t *)pkt->pkt_cmd;
2501 	cmd = *lp & ELS_CMD_MASK;
2502 
2503 	ndlp = emlxs_node_find_did(port, did, 1);
2504 
2505 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
2506 	    "%s %s: did=%x %s %s", emlxs_elscmd_xlate(ucmd),
2507 	    emlxs_elscmd_xlate(cmd), did, emlxs_state_xlate(iocb->ULPSTATUS),
2508 	    emlxs_error_xlate(iocb->un.grsp.perr.statLocalError));
2509 
2510 	switch (ucmd) {
2511 	case ELS_CMD_PLOGI:
2512 
2513 		if (ndlp && ndlp->nlp_active) {
2514 			/* Open the node again */
2515 			emlxs_node_open(port, ndlp, hba->channel_fcp);
2516 			emlxs_node_open(port, ndlp, hba->channel_ip);
2517 		}
2518 
2519 		break;
2520 
2521 	case ELS_CMD_PRLI:
2522 
2523 		if (ndlp && ndlp->nlp_active) {
2524 			/* Open the node again */
2525 			emlxs_node_open(port, ndlp, hba->channel_fcp);
2526 		}
2527 
2528 		break;
2529 	}
2530 
2531 	emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
2532 	    iocb->un.grsp.perr.statLocalError, 1);
2533 
2534 	return;
2535 
2536 } /* emlxs_handle_reject() */
2537 
2538 
2539 /* ARGSUSED */
2540 extern int32_t
2541 emlxs_els_reply(emlxs_port_t *port, IOCBQ *iocbq, uint32_t type,
2542     uint32_t type2, uint32_t reason, uint32_t explain)
2543 {
2544 	emlxs_hba_t *hba = HBA;
2545 	emlxs_config_t *cfg = &CFG;
2546 	fc_packet_t *pkt;
2547 	ELS_PKT *els;
2548 	IOCB *iocb;
2549 
2550 	iocb = &iocbq->iocb;
2551 
2552 	switch (type) {
2553 	case ELS_CMD_ACC:	/* Accept Response */
2554 
2555 		/* Allocate the pkt */
2556 		switch (type2) {
2557 		case ELS_CMD_FLOGI:
2558 			pkt = emlxs_pkt_alloc(port,
2559 			    sizeof (uint32_t) + sizeof (SERV_PARM), 0,
2560 			    0, KM_NOSLEEP);
2561 			break;
2562 
2563 		case ELS_CMD_ADISC:
2564 			pkt = emlxs_pkt_alloc(port,
2565 			    sizeof (uint32_t) + sizeof (ADISC), 0, 0,
2566 			    KM_NOSLEEP);
2567 			break;
2568 
2569 		case ELS_CMD_PRLI:
2570 			pkt = emlxs_pkt_alloc(port,
2571 			    sizeof (uint32_t) + sizeof (PRLI), 0, 0,
2572 			    KM_NOSLEEP);
2573 			break;
2574 
2575 		case ELS_CMD_PRLO:
2576 			pkt = emlxs_pkt_alloc(port,
2577 			    sizeof (uint32_t) + sizeof (PRLO), 0, 0,
2578 			    KM_NOSLEEP);
2579 			break;
2580 
2581 		case ELS_CMD_AUTH:
2582 		default:
2583 			pkt = emlxs_pkt_alloc(port, sizeof (uint32_t),
2584 			    0, 0, KM_NOSLEEP);
2585 			break;
2586 		}
2587 
2588 		if (!pkt) {
2589 			goto dropit;
2590 		}
2591 
2592 		/* Common initialization */
2593 		pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2594 		pkt->pkt_timeout = (2 * hba->fc_ratov);
2595 
2596 		if ((uint32_t)iocb->ULPCLASS == CLASS2) {
2597 			pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
2598 			pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
2599 		}
2600 
2601 		/* Build the fc header */
2602 		pkt->pkt_cmd_fhdr.d_id =
2603 		    LE_SWAP24_LO(iocb->un.elsreq.remoteID);
2604 		pkt->pkt_cmd_fhdr.r_ctl =
2605 		    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
2606 		pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
2607 		pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2608 		pkt->pkt_cmd_fhdr.f_ctl =
2609 		    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2610 		pkt->pkt_cmd_fhdr.seq_id = 0;
2611 		pkt->pkt_cmd_fhdr.df_ctl = 0;
2612 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
2613 		pkt->pkt_cmd_fhdr.ox_id = (type2 >> ELS_CMD_SHIFT) & 0xff;
2614 		pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT;
2615 		pkt->pkt_cmd_fhdr.ro = 0;
2616 
2617 		/*
2618 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2619 		 * "%s ACC send. oxid=%x", emlxs_elscmd_xlate(type2),
2620 		 * pkt->pkt_cmd_fhdr.ox_id);
2621 		 */
2622 
2623 		/* Build the command */
2624 		els = (ELS_PKT *)pkt->pkt_cmd;
2625 		els->elsCode = 0x02;
2626 
2627 		/* Build the payload */
2628 		switch (type2) {
2629 		case ELS_CMD_ADISC:
2630 
2631 			els->un.adisc.hardAL_PA =
2632 			    (uint8_t)cfg[CFG_ASSIGN_ALPA].current;
2633 			bcopy(&port->wwnn, &els->un.adisc.nodeName,
2634 			    sizeof (NAME_TYPE));
2635 			bcopy(&port->wwpn, &els->un.adisc.portName,
2636 			    sizeof (NAME_TYPE));
2637 			els->un.adisc.DID = LE_SWAP24_LO(port->did);
2638 
2639 			break;
2640 
2641 		case ELS_CMD_PRLI:
2642 
2643 			els->elsByte1 = 0x10;
2644 			els->elsByte2 = 0;
2645 			els->elsByte3 = 0x14;
2646 
2647 			els->un.prli.prliType = PRLI_FCP_TYPE;
2648 			els->un.prli.estabImagePair = 1;
2649 			els->un.prli.acceptRspCode = PRLI_REQ_EXECUTED;
2650 
2651 			if (port->mode == MODE_INITIATOR) {
2652 				els->un.prli.initiatorFunc = 1;
2653 			}
2654 
2655 			if (port->mode == MODE_TARGET) {
2656 				els->un.prli.targetFunc = 1;
2657 			}
2658 
2659 			els->un.prli.readXferRdyDis = 1;
2660 
2661 			if ((hba->vpd.feaLevelHigh >= 0x02) &&
2662 			    (cfg[CFG_ADISC_SUPPORT].current != 0)) {
2663 				els->un.prli.ConfmComplAllowed = 1;
2664 				els->un.prli.Retry = 1;
2665 				els->un.prli.TaskRetryIdReq = 1;
2666 			} else {
2667 				els->un.prli.ConfmComplAllowed = 0;
2668 				els->un.prli.Retry = 0;
2669 				els->un.prli.TaskRetryIdReq = 0;
2670 			}
2671 
2672 			break;
2673 
2674 		case ELS_CMD_PRLO:
2675 
2676 			els->elsByte1 = 0x10;
2677 			els->elsByte2 = 0;
2678 			els->elsByte3 = 0x14;
2679 
2680 			els->un.prlo.prloType = PRLO_FCP_TYPE;
2681 			els->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
2682 
2683 			break;
2684 
2685 
2686 		}	/* switch(type2) */
2687 		break;
2688 
2689 	case ELS_CMD_LS_RJT:	/* reject response */
2690 
2691 		if (!(pkt = emlxs_pkt_alloc(port,
2692 		    sizeof (uint32_t) + sizeof (LS_RJT), 0, 0, KM_NOSLEEP))) {
2693 			goto dropit;
2694 		}
2695 
2696 		pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2697 		pkt->pkt_timeout = (2 * hba->fc_ratov);
2698 
2699 		if ((uint32_t)iocb->ULPCLASS == CLASS2) {
2700 			pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
2701 			pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
2702 		}
2703 
2704 		/* Build the fc header */
2705 		pkt->pkt_cmd_fhdr.d_id =
2706 		    LE_SWAP24_LO(iocb->un.elsreq.remoteID);
2707 		pkt->pkt_cmd_fhdr.r_ctl =
2708 		    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
2709 		pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID);
2710 		pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2711 		pkt->pkt_cmd_fhdr.f_ctl =
2712 		    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2713 		pkt->pkt_cmd_fhdr.seq_id = 0;
2714 		pkt->pkt_cmd_fhdr.df_ctl = 0;
2715 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
2716 		pkt->pkt_cmd_fhdr.ox_id = (type2 >> ELS_CMD_SHIFT) & 0xff;
2717 		pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT;
2718 		pkt->pkt_cmd_fhdr.ro = 0;
2719 
2720 		/*
2721 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2722 		 * "%s LS_RJT send. oxid=%x", emlxs_elscmd_xlate(type2),
2723 		 * pkt->pkt_cmd_fhdr.ox_id);
2724 		 */
2725 
2726 		/* Build the command */
2727 		els = (ELS_PKT *)pkt->pkt_cmd;
2728 		els->elsCode = 0x01;
2729 		els->un.lsRjt.un.b.lsRjtRsvd0 = 0;
2730 		els->un.lsRjt.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2731 		els->un.lsRjt.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
2732 		els->un.lsRjt.un.b.vendorUnique = 0x01;
2733 
2734 		break;
2735 
2736 	default:
2737 		return (1);
2738 	}
2739 
2740 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2741 		/* Free the pkt */
2742 		emlxs_pkt_free(pkt);
2743 		goto dropit;
2744 	}
2745 
2746 	return (0);
2747 
2748 dropit:
2749 
2750 	emlxs_abort_els_exchange(hba, port, iocb->ULPCONTEXT);
2751 	return (1);
2752 
2753 } /* emlxs_els_reply() */
2754 
2755 
2756 #ifdef ULP_PATCH6
2757 
2758 extern uint32_t
2759 emlxs_generate_rscn(emlxs_port_t *port, uint32_t d_id)
2760 {
2761 	fc_unsol_buf_t *ubp;
2762 	fc_rscn_t *rscn;
2763 	emlxs_ub_priv_t *ub_priv;
2764 	uint32_t *page;
2765 
2766 	ubp = (fc_unsol_buf_t *)emlxs_ub_get(port, 8, FC_TYPE_EXTENDED_LS, 1);
2767 
2768 	if (ubp == NULL) {
2769 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_no_unsol_buf_msg,
2770 		    "RSCN create: sid=0xfffffd  1 page(s): %08X, 00000000. "
2771 		    "Creation failed.", d_id);
2772 
2773 		return ((uint32_t)FC_FAILURE);
2774 	}
2775 
2776 	/* Simulate an RSCN payload */
2777 	rscn = (fc_rscn_t *)ubp->ub_buffer;
2778 	rscn->rscn_code = 0x61;
2779 	rscn->rscn_len = 0x04;
2780 	rscn->rscn_payload_len = 0x0008;
2781 	page = ((uint32_t *)rscn);
2782 	page++;
2783 	*page = d_id;
2784 
2785 #ifdef EMLXS_I386
2786 	/* Put payload in BE format */
2787 	rscn->rscn_payload_len = LE_SWAP16(rscn->rscn_payload_len);
2788 	*page = LE_SWAP32(d_id);
2789 #endif /* EMLXS_I386 */
2790 
2791 	ub_priv = ubp->ub_fca_private;
2792 	ub_priv->cmd = ELS_CMD_RSCN;
2793 	ub_priv->flags |= EMLXS_UB_INTERCEPT;
2794 
2795 	ubp->ub_frame.r_ctl = FC_ELS_REQ;
2796 	ubp->ub_frame.type = FC_TYPE_EXTENDED_LS;
2797 	ubp->ub_frame.s_id = 0xfffffd;
2798 	ubp->ub_frame.d_id = LE_SWAP24_LO(port->did);
2799 	ubp->ub_frame.ox_id = ub_priv->token;
2800 	ubp->ub_frame.rx_id = 0xffff;
2801 	ubp->ub_class = FC_TRAN_CLASS3;
2802 
2803 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
2804 	    "RSCN: sid=fffffd  1 page(s): %08X, 00000000  buffer=%p "
2805 	    "token=%x. Created.", d_id, ubp, ub_priv->token);
2806 
2807 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
2808 	emlxs_swap_els_ub(ubp);
2809 #endif /* EMLXS_MODREV2X */
2810 
2811 	emlxs_ub_callback(port, ubp);
2812 
2813 	return (FC_SUCCESS);
2814 
2815 } /* emlxs_generate_rscn() */
2816 
2817 #endif /* ULP_PATCH6 */
2818 
2819 
2820 #ifdef MENLO_SUPPORT
2821 extern int
2822 emlxs_menlo_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2823 {
2824 	emlxs_port_t *port = &PPORT;
2825 	IOCB *iocb;
2826 	emlxs_buf_t *sbp;
2827 	fc_packet_t *pkt;
2828 	uint32_t cmd_code = 0;
2829 	uint32_t rsp_code = 0;
2830 	menlo_cmd_t *cmd;
2831 	uint32_t *rsp;
2832 
2833 	iocb = &iocbq->iocb;
2834 
2835 	HBASTATS.CtEvent++;
2836 
2837 	sbp = (emlxs_buf_t *)iocbq->sbp;
2838 
2839 	if (!sbp) {
2840 		/*
2841 		 * completion with missing xmit command
2842 		 */
2843 		HBASTATS.CtStray++;
2844 
2845 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ct_completion_msg,
2846 		    "iocbq=%p cmd=0x%x iotag=0x%x status=0x%x perr=0x%x",
2847 		    iocbq, (uint32_t)iocb->ULPCOMMAND,
2848 		    (uint32_t)iocb->ULPIOTAG, iocb->ULPSTATUS,
2849 		    iocb->un.ulpWord[4]);
2850 
2851 		return (1);
2852 	}
2853 
2854 	if (cp->channelno != hba->channel_ct) {
2855 		HBASTATS.CtStray++;
2856 
2857 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ct_completion_msg,
2858 		    "Invalid IO channel:%d iocbq=%p", cp->channelno, iocbq);
2859 
2860 		return (1);
2861 	}
2862 
2863 	port = sbp->iocbq.port;
2864 	pkt = PRIV2PKT(sbp);
2865 
2866 	cmd = (menlo_cmd_t *)pkt->pkt_cmd;
2867 	cmd_code = BE_SWAP32(cmd->code);
2868 
2869 	/* Check if a response buffer was provided */
2870 	if (pkt->pkt_rsplen) {
2871 		EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen,
2872 		    DDI_DMA_SYNC_FORKERNEL);
2873 	}
2874 
2875 	switch (iocb->ULPCOMMAND) {
2876 	/*
2877 	 * MENLO Command completion
2878 	 */
2879 	case CMD_GEN_REQUEST64_CR:
2880 	case CMD_GEN_REQUEST64_CX:
2881 
2882 		HBASTATS.CtCmdCompleted++;
2883 
2884 		sbp->pkt_flags |= PACKET_CT_RSP_VALID;
2885 
2886 		rsp = (uint32_t *)pkt->pkt_resp;
2887 		rsp_code = *rsp;
2888 		rsp_code = BE_SWAP32(rsp_code);
2889 
2890 		if (hba->sli_mode >= EMLXS_HBA_SLI3_MODE) {
2891 			pkt->pkt_resp_resid =
2892 			    pkt->pkt_rsplen - iocb->unsli3.ext_iocb.rsplen;
2893 		} else {
2894 			pkt->pkt_resp_resid =
2895 			    pkt->pkt_rsplen - iocb->un.genreq64.bdl.bdeSize;
2896 		}
2897 
2898 		pkt->pkt_data_resid = pkt->pkt_datalen;
2899 		pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT;
2900 
2901 		if ((iocb->ULPSTATUS == 0) && (rsp_code == MENLO_RSP_SUCCESS)) {
2902 			HBASTATS.CtCmdGood++;
2903 
2904 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
2905 			    "%s: %s rxid=0x%x",
2906 			    emlxs_menlo_cmd_xlate(cmd_code),
2907 			    emlxs_menlo_rsp_xlate(rsp_code),
2908 			    iocb->ULPCONTEXT);
2909 
2910 		} else {
2911 			HBASTATS.CtCmdError++;
2912 
2913 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
2914 			    "%s: %s %s %s rxid=0x%x",
2915 			    emlxs_menlo_cmd_xlate(cmd_code),
2916 			    emlxs_menlo_rsp_xlate(rsp_code),
2917 			    emlxs_state_xlate(iocb->ULPSTATUS),
2918 			    emlxs_error_xlate(iocb->un.grsp.perr.
2919 			    statLocalError), iocb->ULPCONTEXT);
2920 		}
2921 
2922 		emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
2923 		    iocb->un.grsp.perr.statLocalError, 1);
2924 
2925 		break;
2926 
2927 	default:
2928 
2929 		HBASTATS.CtStray++;
2930 
2931 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_invalid_ct_msg,
2932 		    "Invalid iocb: cmd=0x%x", iocb->ULPCOMMAND);
2933 
2934 		emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
2935 		    iocb->un.grsp.perr.statLocalError, 1);
2936 
2937 		break;
2938 
2939 	}	/* switch(iocb->ULPCOMMAND) */
2940 
2941 	return (0);
2942 
2943 } /* emlxs_menlo_handle_event() */
2944 
2945 #endif /* MENLO_SUPPORT */
2946 
2947 
2948 extern int
2949 emlxs_ct_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2950 {
2951 	emlxs_port_t *port = &PPORT;
2952 	IOCB *iocb;
2953 	emlxs_buf_t *sbp;
2954 	fc_packet_t *pkt;
2955 	uint32_t *rsp;
2956 	SLI_CT_REQUEST *CtRsp;
2957 	SLI_CT_REQUEST *CtCmd;
2958 	uint32_t cmd_code = 0;
2959 	uint32_t rsp_code = 0;
2960 
2961 	iocb = &iocbq->iocb;
2962 
2963 	HBASTATS.CtEvent++;
2964 
2965 	sbp = (emlxs_buf_t *)iocbq->sbp;
2966 
2967 	if (!sbp) {
2968 		/*
2969 		 * completion with missing xmit command
2970 		 */
2971 		HBASTATS.CtStray++;
2972 
2973 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ct_completion_msg,
2974 		    "iocbq=%p cmd=0x%x iotag=0x%x status=0x%x perr=0x%x",
2975 		    iocbq, (uint32_t)iocb->ULPCOMMAND,
2976 		    (uint32_t)iocb->ULPIOTAG, iocb->ULPSTATUS,
2977 		    iocb->un.ulpWord[4]);
2978 
2979 		return (1);
2980 	}
2981 
2982 	if (cp->channelno != hba->channel_ct) {
2983 		HBASTATS.CtStray++;
2984 
2985 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_ct_completion_msg,
2986 		    "Invalid channel: channel=%d iocbq=%p", cp->channelno,
2987 		    iocbq);
2988 
2989 		return (1);
2990 	}
2991 
2992 	pkt = PRIV2PKT(sbp);
2993 	port = sbp->iocbq.port;
2994 	CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd;
2995 	cmd_code = LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp);
2996 
2997 	if (cmd_code == SLI_CT_LOOPBACK) {
2998 		HBASTATS.CtEvent--;
2999 		return (emlxs_dfc_handle_event(hba, cp, iocbq));
3000 	}
3001 
3002 	/* Check if a response buffer was provided */
3003 	if (pkt->pkt_rsplen) {
3004 		EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen,
3005 		    DDI_DMA_SYNC_FORKERNEL);
3006 	}
3007 
3008 	switch (iocb->ULPCOMMAND) {
3009 		/*
3010 		 * CT Reply completion
3011 		 */
3012 	case CMD_XMIT_SEQUENCE_CX:
3013 	case CMD_XMIT_SEQUENCE64_CX:
3014 
3015 		HBASTATS.CtRspCompleted++;
3016 
3017 		switch (CtCmd->FsType) {
3018 		case 0xFC:	/* Name server */
3019 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
3020 			    "%s: %s %s", emlxs_ctcmd_xlate(cmd_code),
3021 			    emlxs_state_xlate(iocb->ULPSTATUS),
3022 			    emlxs_error_xlate(iocb->un.grsp.perr.
3023 			    statLocalError));
3024 			break;
3025 
3026 		case 0xFA:	/* Managment server */
3027 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
3028 			    "%s: %s %s", emlxs_mscmd_xlate(cmd_code),
3029 			    emlxs_state_xlate(iocb->ULPSTATUS),
3030 			    emlxs_error_xlate(iocb->un.grsp.perr.
3031 			    statLocalError));
3032 			break;
3033 
3034 		case 0x0A:	/* Emulex Remote server */
3035 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
3036 			    "%s: %s %s", emlxs_rmcmd_xlate(cmd_code),
3037 			    emlxs_state_xlate(iocb->ULPSTATUS),
3038 			    emlxs_error_xlate(iocb->un.grsp.perr.
3039 			    statLocalError));
3040 			break;
3041 
3042 		default:
3043 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
3044 			    "%s: %s %s", emlxs_ctcmd_xlate(cmd_code),
3045 			    emlxs_state_xlate(iocb->ULPSTATUS),
3046 			    emlxs_error_xlate(iocb->un.grsp.perr.
3047 			    statLocalError));
3048 		}
3049 
3050 		emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
3051 		    iocb->un.grsp.perr.statLocalError, 1);
3052 
3053 		break;
3054 
3055 		/*
3056 		 * CT Command completion
3057 		 */
3058 	case CMD_GEN_REQUEST64_CR:
3059 	case CMD_GEN_REQUEST64_CX:
3060 
3061 		HBASTATS.CtCmdCompleted++;
3062 
3063 		sbp->pkt_flags |= PACKET_CT_RSP_VALID;
3064 
3065 		rsp = (uint32_t *)pkt->pkt_resp;
3066 		CtRsp = (SLI_CT_REQUEST *)pkt->pkt_resp;
3067 		rsp_code = LE_SWAP16(CtRsp->CommandResponse.bits.CmdRsp);
3068 
3069 		if (hba->sli_mode >= EMLXS_HBA_SLI3_MODE) {
3070 			pkt->pkt_resp_resid =
3071 			    pkt->pkt_rsplen - iocb->unsli3.ext_iocb.rsplen;
3072 		} else {
3073 			pkt->pkt_resp_resid =
3074 			    pkt->pkt_rsplen - iocb->un.genreq64.bdl.bdeSize;
3075 		}
3076 
3077 		pkt->pkt_data_resid = pkt->pkt_datalen;
3078 
3079 		/*
3080 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_completion_msg,
3081 		 * "INFO: pkt_resid=%d  %d  %d  %x", pkt->pkt_resp_resid,
3082 		 * pkt->pkt_rsplen, iocb->un.genreq64.bdl.bdeSize,
3083 		 * iocb->un.genreq64.bdl.bdeFlags);
3084 		 */
3085 
3086 		if ((iocb->ULPSTATUS == 0) &&
3087 		    (rsp_code == SLI_CT_RESPONSE_FS_ACC)) {
3088 			HBASTATS.CtCmdGood++;
3089 
3090 			if (!(sbp->pkt_flags & PACKET_ALLOCATED)) {
3091 				/* ULP patch - ULP expects */
3092 				/* resp_resid = 0 on success */
3093 				pkt->pkt_resp_resid = 0;
3094 			}
3095 
3096 			switch (CtCmd->FsType) {
3097 			case 0xFC:	/* Name server */
3098 				EMLXS_MSGF(EMLXS_CONTEXT,
3099 				    &emlxs_ct_completion_msg,
3100 				    "%s: %s: Rsn=%x Exp=%x [%08x,%08x]",
3101 				    emlxs_ctcmd_xlate(cmd_code),
3102 				    emlxs_ctcmd_xlate(rsp_code),
3103 				    CtRsp->ReasonCode, CtRsp->Explanation,
3104 				    LE_SWAP32(rsp[4]), LE_SWAP32(rsp[5]));
3105 
3106 #if (EMLXS_MODREV < EMLXS_MODREV4)
3107 				if (cmd_code == SLI_CTNS_RNN_ID) {
3108 					emlxs_send_rsnn(port);
3109 				}
3110 #endif /* < EMLXS_MODREV4 */
3111 
3112 				break;
3113 
3114 			case 0xFA:	/* Managment server */
3115 				EMLXS_MSGF(EMLXS_CONTEXT,
3116 				    &emlxs_ct_completion_msg,
3117 				    "%s: %s: Rsn=%x Exp=%x [%08x,%08x]",
3118 				    emlxs_mscmd_xlate(cmd_code),
3119 				    emlxs_mscmd_xlate(rsp_code),
3120 				    CtRsp->ReasonCode, CtRsp->Explanation,
3121 				    LE_SWAP32(rsp[4]), LE_SWAP32(rsp[5]));
3122 				break;
3123 
3124 			case 0x0A:	/* Emulex Remote server */
3125 				EMLXS_MSGF(EMLXS_CONTEXT,
3126 				    &emlxs_ct_completion_msg,
3127 				    "%s: %s: Rsn=%x Exp=%x [%08x,%08x]",
3128 				    emlxs_rmcmd_xlate(cmd_code),
3129 				    emlxs_rmcmd_xlate(rsp_code),
3130 				    CtRsp->ReasonCode, CtRsp->Explanation,
3131 				    LE_SWAP32(rsp[4]), LE_SWAP32(rsp[5]));
3132 				break;
3133 
3134 			default:
3135 				EMLXS_MSGF(EMLXS_CONTEXT,
3136 				    &emlxs_ct_completion_msg,
3137 				    "%s: %s: Rsn=%x Exp=%x [%08x,%08x]",
3138 				    emlxs_ctcmd_xlate(cmd_code),
3139 				    emlxs_ctcmd_xlate(rsp_code),
3140 				    CtRsp->ReasonCode, CtRsp->Explanation,
3141 				    LE_SWAP32(rsp[4]), LE_SWAP32(rsp[5]));
3142 			}
3143 		} else {
3144 			HBASTATS.CtCmdError++;
3145 
3146 			if (rsp_code == SLI_CT_RESPONSE_FS_RJT) {
3147 				pkt->pkt_state = FC_PKT_FS_RJT;
3148 				pkt->pkt_action = FC_ACTION_RETRYABLE;
3149 				pkt->pkt_reason = CtRsp->ReasonCode;
3150 				pkt->pkt_expln = CtRsp->Explanation;
3151 				sbp->pkt_flags |= PACKET_STATE_VALID;
3152 
3153 				EMLXS_MSGF(EMLXS_CONTEXT,
3154 				    &emlxs_ct_completion_msg,
3155 				    "%s: Rejected. rsn=%x exp=%x",
3156 				    emlxs_ctcmd_xlate(cmd_code),
3157 				    pkt->pkt_reason, pkt->pkt_expln);
3158 			} else if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) {
3159 				switch (CtCmd->FsType) {
3160 				case 0xFC:	/* Name server */
3161 					EMLXS_MSGF(EMLXS_CONTEXT,
3162 					    &emlxs_ct_completion_msg,
3163 					    "%s: %s %s",
3164 					    emlxs_ctcmd_xlate(cmd_code),
3165 					    emlxs_state_xlate(iocb->
3166 					    ULPSTATUS),
3167 					    emlxs_error_xlate(iocb->un.grsp.
3168 					    perr.statLocalError));
3169 					break;
3170 
3171 				case 0xFA:	/* Managment server */
3172 					EMLXS_MSGF(EMLXS_CONTEXT,
3173 					    &emlxs_ct_completion_msg,
3174 					    "%s: %s %s",
3175 					    emlxs_mscmd_xlate(cmd_code),
3176 					    emlxs_state_xlate(iocb->
3177 					    ULPSTATUS),
3178 					    emlxs_error_xlate(iocb->un.grsp.
3179 					    perr.statLocalError));
3180 					break;
3181 
3182 				case 0x0A:	/* Emulex Remote server */
3183 					EMLXS_MSGF(EMLXS_CONTEXT,
3184 					    &emlxs_ct_completion_msg,
3185 					    "%s: %s %s",
3186 					    emlxs_rmcmd_xlate(cmd_code),
3187 					    emlxs_state_xlate(iocb->
3188 					    ULPSTATUS),
3189 					    emlxs_error_xlate(iocb->un.grsp.
3190 					    perr.statLocalError));
3191 					break;
3192 
3193 				default:
3194 					EMLXS_MSGF(EMLXS_CONTEXT,
3195 					    &emlxs_ct_completion_msg,
3196 					    "%s: %s %s",
3197 					    emlxs_ctcmd_xlate(cmd_code),
3198 					    emlxs_state_xlate(iocb->
3199 					    ULPSTATUS),
3200 					    emlxs_error_xlate(iocb->un.grsp.
3201 					    perr.statLocalError));
3202 				}
3203 			} else {
3204 				switch (CtCmd->FsType) {
3205 				case 0xFC:	/* Name server */
3206 					EMLXS_MSGF(EMLXS_CONTEXT,
3207 					    &emlxs_ct_completion_msg,
3208 					    "%s: %s (%02x%02x%02x%02x)",
3209 					    emlxs_ctcmd_xlate(cmd_code),
3210 					    emlxs_state_xlate(iocb->
3211 					    ULPSTATUS),
3212 					    iocb->un.grsp.perr.statAction,
3213 					    iocb->un.grsp.perr.statRsn,
3214 					    iocb->un.grsp.perr.statBaExp,
3215 					    iocb->un.grsp.perr.
3216 					    statLocalError);
3217 					break;
3218 
3219 				case 0xFA:	/* Managment server */
3220 					EMLXS_MSGF(EMLXS_CONTEXT,
3221 					    &emlxs_ct_completion_msg,
3222 					    "%s: %s (%02x%02x%02x%02x)",
3223 					    emlxs_mscmd_xlate(cmd_code),
3224 					    emlxs_state_xlate(iocb->
3225 					    ULPSTATUS),
3226 					    iocb->un.grsp.perr.statAction,
3227 					    iocb->un.grsp.perr.statRsn,
3228 					    iocb->un.grsp.perr.statBaExp,
3229 					    iocb->un.grsp.perr.
3230 					    statLocalError);
3231 					break;
3232 
3233 				case 0x0A:	/* Emulex Remote server */
3234 					EMLXS_MSGF(EMLXS_CONTEXT,
3235 					    &emlxs_ct_completion_msg,
3236 					    "%s: %s (%02x%02x%02x%02x)",
3237 					    emlxs_rmcmd_xlate(cmd_code),
3238 					    emlxs_state_xlate(iocb->
3239 					    ULPSTATUS),
3240 					    iocb->un.grsp.perr.statAction,
3241 					    iocb->un.grsp.perr.statRsn,
3242 					    iocb->un.grsp.perr.statBaExp,
3243 					    iocb->un.grsp.perr.
3244 					    statLocalError);
3245 					break;
3246 
3247 				default:
3248 					EMLXS_MSGF(EMLXS_CONTEXT,
3249 					    &emlxs_ct_completion_msg,
3250 					    "%s: %s (%02x%02x%02x%02x)",
3251 					    emlxs_ctcmd_xlate(cmd_code),
3252 					    emlxs_state_xlate(iocb->
3253 					    ULPSTATUS),
3254 					    iocb->un.grsp.perr.statAction,
3255 					    iocb->un.grsp.perr.statRsn,
3256 					    iocb->un.grsp.perr.statBaExp,
3257 					    iocb->un.grsp.perr.
3258 					    statLocalError);
3259 				}
3260 			}
3261 		}
3262 
3263 		emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
3264 		    iocb->un.grsp.perr.statLocalError, 1);
3265 
3266 		break;
3267 
3268 	default:
3269 
3270 		HBASTATS.CtStray++;
3271 
3272 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_invalid_ct_msg,
3273 		    "Invalid iocb: cmd=0x%x", iocb->ULPCOMMAND);
3274 
3275 		emlxs_pkt_complete(sbp, iocb->ULPSTATUS,
3276 		    iocb->un.grsp.perr.statLocalError, 1);
3277 
3278 		break;
3279 	}	/* switch(iocb->ULPCOMMAND) */
3280 
3281 	return (0);
3282 
3283 } /* emlxs_ct_handle_event() */
3284 
3285 
3286 extern int
3287 emlxs_ct_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3288     MATCHMAP *mp, uint32_t size)
3289 {
3290 	emlxs_hba_t *hba = HBA;
3291 	IOCB *iocb;
3292 	SLI_CT_REQUEST *CtCmd;
3293 	uint32_t cmd_code;
3294 
3295 	iocb = &iocbq->iocb;
3296 
3297 	CtCmd = (SLI_CT_REQUEST *)mp->virt;
3298 	cmd_code = LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp);
3299 
3300 	if (cmd_code == SLI_CT_LOOPBACK) {
3301 		int rval;
3302 
3303 		rval = emlxs_dfc_handle_unsol_req(port, cp, iocbq, mp, size);
3304 
3305 		return (rval);
3306 	}
3307 
3308 	HBASTATS.CtCmdReceived++;
3309 
3310 	switch (CtCmd->FsType) {
3311 	case 0xFC:	/* Name server */
3312 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg,
3313 		    "%s: pl=%p size=%d rxid=%x", emlxs_ctcmd_xlate(cmd_code),
3314 		    CtCmd, size, iocb->ULPCONTEXT);
3315 		break;
3316 
3317 	case 0xFA:	/* Managment server */
3318 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg,
3319 		    "%s: pl=%p size=%d rxid=%x", emlxs_mscmd_xlate(cmd_code),
3320 		    CtCmd, size, iocb->ULPCONTEXT);
3321 		break;
3322 
3323 	case 0x0A:	/* Emulex Remote server */
3324 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg,
3325 		    "%s: pl=%p size=%d rxid=%x", emlxs_rmcmd_xlate(cmd_code),
3326 		    CtCmd, size, iocb->ULPCONTEXT);
3327 		break;
3328 
3329 	default:
3330 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg,
3331 		    "%s: pl=%p size=%d rxid=%x", emlxs_ctcmd_xlate(cmd_code),
3332 		    CtCmd, size, iocb->ULPCONTEXT);
3333 	}
3334 
3335 	if (emlxs_log_ct_event(port, (uint8_t *)mp->virt, size,
3336 	    iocb->ULPCONTEXT)) {
3337 		/* Abort the exchange */
3338 		emlxs_abort_ct_exchange(hba, port, iocb->ULPCONTEXT);
3339 	}
3340 
3341 	return (0);
3342 
3343 } /* emlxs_ct_handle_unsol_req() */
3344 
3345 
3346 #if (EMLXS_MODREV < EMLXS_MODREV4)
3347 static void
3348 emlxs_send_rsnn(emlxs_port_t *port)
3349 {
3350 	emlxs_hba_t *hba = HBA;
3351 	fc_packet_t *pkt;
3352 	SLI_CT_REQUEST *ct;
3353 
3354 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (SLI_CT_REQUEST),
3355 	    sizeof (SLI_CT_REQUEST), 0, KM_NOSLEEP))) {
3356 		return;
3357 	}
3358 
3359 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
3360 	pkt->pkt_timeout = (2 * hba->fc_ratov);
3361 
3362 	/* Build the fc header */
3363 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(NAMESERVER_DID);
3364 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL;
3365 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
3366 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
3367 	pkt->pkt_cmd_fhdr.f_ctl =
3368 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
3369 	pkt->pkt_cmd_fhdr.seq_id = 0;
3370 	pkt->pkt_cmd_fhdr.df_ctl = 0;
3371 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
3372 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
3373 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
3374 	pkt->pkt_cmd_fhdr.ro = 0;
3375 
3376 	/* Build the command */
3377 	ct = (SLI_CT_REQUEST *)pkt->pkt_cmd;
3378 
3379 	ct->RevisionId.bits.Revision = SLI_CT_REVISION;
3380 	ct->RevisionId.bits.InId = 0;
3381 
3382 	ct->FsType = SLI_CT_DIRECTORY_SERVICE;
3383 	ct->FsSubType = SLI_CT_DIRECTORY_NAME_SERVER;
3384 
3385 	ct->CommandResponse.bits.Size = 0;
3386 	ct->CommandResponse.bits.CmdRsp = LE_SWAP16(SLI_CTNS_RSNN_NN);
3387 
3388 	bcopy((uint8_t *)&hba->wwnn, (char *)ct->un.rsnn.wwnn, 8);
3389 
3390 	ct->un.rsnn.snn_len = strlen(port->snn);
3391 	bcopy(port->snn, (char *)ct->un.rsnn.snn, ct->un.rsnn.snn_len);
3392 
3393 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, "Sending RSNN_NN. [%s]",
3394 	    port->snn);
3395 
3396 	/* Send the pkt later in another thread */
3397 	if (emlxs_pkt_send(pkt, 0) != FC_SUCCESS) {
3398 		/* Free the pkt */
3399 		emlxs_pkt_free(pkt);
3400 	}
3401 
3402 	return;
3403 
3404 } /* emlxs_send_rsnn() */
3405 #endif /* < EMLXS_MODREV4 */
3406 
3407 
3408 
3409 
3410 extern uint32_t
3411 emlxs_ub_send_login_acc(emlxs_port_t *port, fc_unsol_buf_t *ubp)
3412 {
3413 	emlxs_hba_t *hba = HBA;
3414 	fc_packet_t *pkt;
3415 	ELS_PKT *els;
3416 	uint32_t rval;
3417 	emlxs_ub_priv_t *ub_priv;
3418 
3419 	ub_priv = ubp->ub_fca_private;
3420 
3421 	if (!(pkt = emlxs_pkt_alloc(port,
3422 	    sizeof (uint32_t) + sizeof (SERV_PARM), 0, 0, KM_NOSLEEP))) {
3423 		return (1);
3424 	}
3425 
3426 	/* Common initialization */
3427 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
3428 	pkt->pkt_timeout = (2 * hba->fc_ratov);
3429 
3430 	if ((uint32_t)ubp->ub_class == FC_TRAN_CLASS2) {
3431 		pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
3432 		pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
3433 	}
3434 
3435 	/* Build the fc header */
3436 	pkt->pkt_cmd_fhdr.d_id = ubp->ub_frame.s_id;
3437 	pkt->pkt_cmd_fhdr.r_ctl =
3438 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
3439 	pkt->pkt_cmd_fhdr.s_id = ubp->ub_frame.d_id;
3440 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3441 	pkt->pkt_cmd_fhdr.f_ctl =
3442 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
3443 	pkt->pkt_cmd_fhdr.seq_id = 0;
3444 	pkt->pkt_cmd_fhdr.df_ctl = 0;
3445 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
3446 	pkt->pkt_cmd_fhdr.ox_id = (ub_priv->cmd >> ELS_CMD_SHIFT) & 0xff;
3447 	pkt->pkt_cmd_fhdr.rx_id = ubp->ub_frame.rx_id;
3448 	pkt->pkt_cmd_fhdr.ro = 0;
3449 
3450 	/* Build the command */
3451 	els = (ELS_PKT *)pkt->pkt_cmd;
3452 	els->elsCode = 0x02;
3453 	bcopy((void *)&port->sparam, (void *)&els->un.logi,
3454 	    sizeof (SERV_PARM));
3455 
3456 	if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) {
3457 		/* Free the pkt */
3458 		emlxs_pkt_free(pkt);
3459 	} else {
3460 		ub_priv->flags |= EMLXS_UB_INTERCEPT;
3461 	}
3462 
3463 	return (rval);
3464 
3465 } /* emlxs_ub_send_login_acc */
3466 
3467 
3468 extern void
3469 emlxs_send_logo(emlxs_port_t *port, uint32_t d_id)
3470 {
3471 	emlxs_hba_t *hba = HBA;
3472 	fc_packet_t *pkt;
3473 	ELS_PKT *els;
3474 
3475 	if (!(hba->flag & FC_ONLINE_MODE)) {
3476 		return;
3477 	}
3478 
3479 	if (hba->state <= FC_LINK_DOWN) {
3480 		return;
3481 	}
3482 
3483 	if (!(pkt = emlxs_pkt_alloc(port,
3484 	    sizeof (uint32_t) + sizeof (LOGO),
3485 	    sizeof (uint32_t) + sizeof (LOGO), 0, KM_NOSLEEP))) {
3486 		return;
3487 	}
3488 
3489 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
3490 	pkt->pkt_timeout = (2 * hba->fc_ratov);
3491 
3492 	/* Build the fc header */
3493 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(d_id);
3494 	pkt->pkt_cmd_fhdr.r_ctl =
3495 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
3496 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
3497 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3498 	pkt->pkt_cmd_fhdr.f_ctl =
3499 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
3500 	pkt->pkt_cmd_fhdr.seq_id = 0;
3501 	pkt->pkt_cmd_fhdr.df_ctl = 0;
3502 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
3503 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
3504 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
3505 	pkt->pkt_cmd_fhdr.ro = 0;
3506 
3507 	/* Build the command */
3508 	els = (ELS_PKT *)pkt->pkt_cmd;
3509 	els->elsCode = 0x05;
3510 	els->un.logo.un.nPortId32 = pkt->pkt_cmd_fhdr.s_id;
3511 	bcopy((uint8_t *)&port->wwpn, (uint8_t *)&els->un.logo.portName,
3512 	    8);
3513 
3514 	/* Send the pkt now */
3515 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
3516 		/* Free the pkt */
3517 		emlxs_pkt_free(pkt);
3518 	}
3519 
3520 	return;
3521 
3522 } /* emlxs_send_logo() */
3523