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