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