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