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