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