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