xref: /illumos-gate/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_solaris.c (revision 825277341c15b6b0d2c4b8b622ae7b1d2bdc0390)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Emulex.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #define	DEF_ICFG	1
29 
30 #include <emlxs.h>
31 #include <emlxs_version.h>
32 
33 
34 char emlxs_revision[] = EMLXS_REVISION;
35 char emlxs_version[] = EMLXS_VERSION;
36 char emlxs_name[] = EMLXS_NAME;
37 char emlxs_label[] = EMLXS_LABEL;
38 
39 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
40 EMLXS_MSG_DEF(EMLXS_SOLARIS_C);
41 
42 #ifdef MENLO_SUPPORT
43 static int32_t  emlxs_send_menlo(emlxs_port_t *port, emlxs_buf_t *sbp);
44 #endif /* MENLO_SUPPORT */
45 
46 static void	emlxs_fca_attach(emlxs_hba_t *hba);
47 static void	emlxs_fca_detach(emlxs_hba_t *hba);
48 static void	emlxs_drv_banner(emlxs_hba_t *hba);
49 
50 static int32_t	emlxs_get_props(emlxs_hba_t *hba);
51 static int32_t	emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp);
52 static int32_t	emlxs_send_fct_status(emlxs_port_t *port, emlxs_buf_t *sbp);
53 static int32_t	emlxs_send_fct_abort(emlxs_port_t *port, emlxs_buf_t *sbp);
54 static int32_t	emlxs_send_ip(emlxs_port_t *port, emlxs_buf_t *sbp);
55 static int32_t	emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp);
56 static int32_t	emlxs_send_els_rsp(emlxs_port_t *port, emlxs_buf_t *sbp);
57 static int32_t	emlxs_send_ct(emlxs_port_t *port, emlxs_buf_t *sbp);
58 static int32_t	emlxs_send_ct_rsp(emlxs_port_t *port, emlxs_buf_t *sbp);
59 static uint32_t emlxs_add_instance(int32_t ddiinst);
60 static void	emlxs_iodone(emlxs_buf_t *sbp);
61 static int	emlxs_pm_lower_power(dev_info_t *dip);
62 static int	emlxs_pm_raise_power(dev_info_t *dip);
63 static void	emlxs_driver_remove(dev_info_t *dip, uint32_t init_flag,
64 		    uint32_t failed);
65 static void	emlxs_iodone_server(void *arg1, void *arg2, void *arg3);
66 static uint32_t	emlxs_integrity_check(emlxs_hba_t *hba);
67 static uint32_t	emlxs_test(emlxs_hba_t *hba, uint32_t test_code,
68 		    uint32_t args, uint32_t *arg);
69 
70 static void	emlxs_read_vport_prop(emlxs_hba_t *hba);
71 
72 
73 
74 /*
75  * Driver Entry Routines.
76  */
77 static int32_t	emlxs_detach(dev_info_t *, ddi_detach_cmd_t);
78 static int32_t	emlxs_attach(dev_info_t *, ddi_attach_cmd_t);
79 static int32_t	emlxs_open(dev_t *, int32_t, int32_t, cred_t *);
80 static int32_t	emlxs_close(dev_t, int32_t, int32_t, cred_t *);
81 static int32_t	emlxs_ioctl(dev_t, int32_t, intptr_t, int32_t,
82 		    cred_t *, int32_t *);
83 static int32_t	emlxs_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
84 
85 
86 /*
87  * FC_AL Transport Functions.
88  */
89 static opaque_t	emlxs_bind_port(dev_info_t *, fc_fca_port_info_t *,
90 		    fc_fca_bind_info_t *);
91 static void	emlxs_unbind_port(opaque_t);
92 static void	emlxs_initialize_pkt(emlxs_port_t *, emlxs_buf_t *);
93 static int32_t	emlxs_get_cap(opaque_t, char *, void *);
94 static int32_t	emlxs_set_cap(opaque_t, char *, void *);
95 static int32_t	emlxs_get_map(opaque_t, fc_lilpmap_t *);
96 static int32_t	emlxs_ub_alloc(opaque_t, uint64_t *, uint32_t,
97 		    uint32_t *, uint32_t);
98 static int32_t	emlxs_ub_free(opaque_t, uint32_t, uint64_t *);
99 
100 static opaque_t	emlxs_get_device(opaque_t, fc_portid_t);
101 static int32_t	emlxs_notify(opaque_t, uint32_t);
102 static void	emlxs_ub_els_reject(emlxs_port_t *, fc_unsol_buf_t *);
103 
104 /*
105  * Driver Internal Functions.
106  */
107 
108 static void	emlxs_poll(emlxs_port_t *, emlxs_buf_t *);
109 static int32_t	emlxs_power(dev_info_t *, int32_t, int32_t);
110 #ifdef EMLXS_I386
111 #ifdef S11
112 static int32_t	emlxs_quiesce(dev_info_t *);
113 #endif
114 #endif
115 static int32_t	emlxs_hba_resume(dev_info_t *);
116 static int32_t	emlxs_hba_suspend(dev_info_t *);
117 static int32_t	emlxs_hba_detach(dev_info_t *);
118 static int32_t	emlxs_hba_attach(dev_info_t *);
119 static void	emlxs_lock_destroy(emlxs_hba_t *);
120 static void	emlxs_lock_init(emlxs_hba_t *);
121 static ULP_BDE64 *emlxs_pkt_to_bpl(ULP_BDE64 *, fc_packet_t *,
122 			uint32_t, uint8_t);
123 
124 char *emlxs_pm_components[] = {
125 	"NAME=emlxx000",
126 	"0=Device D3 State",
127 	"1=Device D0 State"
128 };
129 
130 
131 /*
132  * Default emlx dma limits
133  */
134 ddi_dma_lim_t emlxs_dma_lim = {
135 	(uint32_t)0,				/* dlim_addr_lo */
136 	(uint32_t)0xffffffff,			/* dlim_addr_hi */
137 	(uint_t)0x00ffffff,			/* dlim_cntr_max */
138 	DEFAULT_BURSTSIZE | BURST32 | BURST64,	/* dlim_burstsizes */
139 	1,					/* dlim_minxfer */
140 	0x00ffffff				/* dlim_dmaspeed */
141 };
142 
143 /*
144  * Be careful when using these attributes; the defaults listed below are
145  * (almost) the most general case, permitting allocation in almost any
146  * way supported by the LightPulse family.  The sole exception is the
147  * alignment specified as requiring memory allocation on a 4-byte boundary;
148  * the Lightpulse can DMA memory on any byte boundary.
149  *
150  * The LightPulse family currently is limited to 16M transfers;
151  * this restriction affects the dma_attr_count_max and dma_attr_maxxfer fields.
152  */
153 ddi_dma_attr_t emlxs_dma_attr = {
154 	DMA_ATTR_V0,				/* dma_attr_version */
155 	(uint64_t)0,				/* dma_attr_addr_lo */
156 	(uint64_t)0xffffffffffffffff,		/* dma_attr_addr_hi */
157 	(uint64_t)0x00ffffff,			/* dma_attr_count_max */
158 	1,					/* dma_attr_align */
159 	DEFAULT_BURSTSIZE | BURST32 | BURST64,	/* dma_attr_burstsizes */
160 	1,					/* dma_attr_minxfer */
161 	(uint64_t)0x00ffffff,			/* dma_attr_maxxfer */
162 	(uint64_t)0xffffffff,			/* dma_attr_seg */
163 	EMLXS_SGLLEN,				/* dma_attr_sgllen */
164 	1,					/* dma_attr_granular */
165 	0					/* dma_attr_flags */
166 };
167 
168 ddi_dma_attr_t emlxs_dma_attr_ro = {
169 	DMA_ATTR_V0,				/* dma_attr_version */
170 	(uint64_t)0,				/* dma_attr_addr_lo */
171 	(uint64_t)0xffffffffffffffff,		/* dma_attr_addr_hi */
172 	(uint64_t)0x00ffffff,			/* dma_attr_count_max */
173 	1,					/* dma_attr_align */
174 	DEFAULT_BURSTSIZE | BURST32 | BURST64,	/* dma_attr_burstsizes */
175 	1,					/* dma_attr_minxfer */
176 	(uint64_t)0x00ffffff,			/* dma_attr_maxxfer */
177 	(uint64_t)0xffffffff,			/* dma_attr_seg */
178 	EMLXS_SGLLEN,				/* dma_attr_sgllen */
179 	1,					/* dma_attr_granular */
180 	DDI_DMA_RELAXED_ORDERING		/* dma_attr_flags */
181 };
182 
183 ddi_dma_attr_t emlxs_dma_attr_1sg = {
184 	DMA_ATTR_V0,				/* dma_attr_version */
185 	(uint64_t)0,				/* dma_attr_addr_lo */
186 	(uint64_t)0xffffffffffffffff,		/* dma_attr_addr_hi */
187 	(uint64_t)0x00ffffff,			/* dma_attr_count_max */
188 	1,					/* dma_attr_align */
189 	DEFAULT_BURSTSIZE | BURST32 | BURST64,	/* dma_attr_burstsizes */
190 	1,					/* dma_attr_minxfer */
191 	(uint64_t)0x00ffffff,			/* dma_attr_maxxfer */
192 	(uint64_t)0xffffffff,			/* dma_attr_seg */
193 	1,					/* dma_attr_sgllen */
194 	1,					/* dma_attr_granular */
195 	0					/* dma_attr_flags */
196 };
197 
198 #if (EMLXS_MODREV >= EMLXS_MODREV3)
199 ddi_dma_attr_t emlxs_dma_attr_fcip_rsp = {
200 	DMA_ATTR_V0,				/* dma_attr_version */
201 	(uint64_t)0,				/* dma_attr_addr_lo */
202 	(uint64_t)0xffffffffffffffff,		/* dma_attr_addr_hi */
203 	(uint64_t)0x00ffffff,			/* dma_attr_count_max */
204 	1,					/* dma_attr_align */
205 	DEFAULT_BURSTSIZE | BURST32 | BURST64,	/* dma_attr_burstsizes */
206 	1,					/* dma_attr_minxfer */
207 	(uint64_t)0x00ffffff,			/* dma_attr_maxxfer */
208 	(uint64_t)0xffffffff,			/* dma_attr_seg */
209 	EMLXS_SGLLEN,				/* dma_attr_sgllen */
210 	1,					/* dma_attr_granular */
211 	0					/* dma_attr_flags */
212 };
213 #endif	/* >= EMLXS_MODREV3 */
214 
215 /*
216  * DDI access attributes for device
217  */
218 ddi_device_acc_attr_t emlxs_dev_acc_attr = {
219 	DDI_DEVICE_ATTR_V1,	/* devacc_attr_version		*/
220 	DDI_STRUCTURE_LE_ACC,	/* PCI is Little Endian		*/
221 	DDI_STRICTORDER_ACC,	/* devacc_attr_dataorder	*/
222 	DDI_DEFAULT_ACC		/* devacc_attr_access		*/
223 };
224 
225 /*
226  * DDI access attributes for data
227  */
228 ddi_device_acc_attr_t emlxs_data_acc_attr = {
229 	DDI_DEVICE_ATTR_V1,	/* devacc_attr_version		*/
230 	DDI_NEVERSWAP_ACC,	/* don't swap for Data		*/
231 	DDI_STRICTORDER_ACC,	/* devacc_attr_dataorder	*/
232 	DDI_DEFAULT_ACC		/* devacc_attr_access		*/
233 };
234 
235 /*
236  * Fill in the FC Transport structure,
237  * as defined in the Fibre Channel Transport Programmming Guide.
238  */
239 #if (EMLXS_MODREV == EMLXS_MODREV5)
240 	static fc_fca_tran_t emlxs_fca_tran = {
241 	FCTL_FCA_MODREV_5, 		/* fca_version, with SUN NPIV support */
242 	MAX_VPORTS,			/* fca numerb of ports */
243 	sizeof (emlxs_buf_t),		/* fca pkt size */
244 	2048,				/* fca cmd max */
245 	&emlxs_dma_lim,			/* fca dma limits */
246 	0,				/* fca iblock, to be filled in later */
247 	&emlxs_dma_attr,		/* fca dma attributes */
248 	&emlxs_dma_attr_1sg,		/* fca dma fcp cmd attributes */
249 	&emlxs_dma_attr_1sg,		/* fca dma fcp rsp attributes */
250 	&emlxs_dma_attr_ro,		/* fca dma fcp data attributes */
251 	&emlxs_dma_attr_1sg,		/* fca dma fcip cmd attributes */
252 	&emlxs_dma_attr_fcip_rsp,	/* fca dma fcip rsp attributes */
253 	&emlxs_dma_attr_1sg,		/* fca dma fcsm cmd attributes */
254 	&emlxs_dma_attr,		/* fca dma fcsm rsp attributes */
255 	&emlxs_data_acc_attr,   	/* fca access atributes */
256 	0,				/* fca_num_npivports */
257 	{0, 0, 0, 0, 0, 0, 0, 0},	/* Physical port WWPN */
258 	emlxs_bind_port,
259 	emlxs_unbind_port,
260 	emlxs_pkt_init,
261 	emlxs_pkt_uninit,
262 	emlxs_transport,
263 	emlxs_get_cap,
264 	emlxs_set_cap,
265 	emlxs_get_map,
266 	emlxs_transport,
267 	emlxs_ub_alloc,
268 	emlxs_ub_free,
269 	emlxs_ub_release,
270 	emlxs_pkt_abort,
271 	emlxs_reset,
272 	emlxs_port_manage,
273 	emlxs_get_device,
274 	emlxs_notify
275 };
276 #endif	/* EMLXS_MODREV5 */
277 
278 
279 #if (EMLXS_MODREV == EMLXS_MODREV4)
280 static fc_fca_tran_t emlxs_fca_tran = {
281 	FCTL_FCA_MODREV_4,		/* fca_version */
282 	MAX_VPORTS,			/* fca numerb of ports */
283 	sizeof (emlxs_buf_t),		/* fca pkt size */
284 	2048,				/* fca cmd max */
285 	&emlxs_dma_lim,			/* fca dma limits */
286 	0,				/* fca iblock, to be filled in later */
287 	&emlxs_dma_attr,		/* fca dma attributes */
288 	&emlxs_dma_attr_1sg,		/* fca dma fcp cmd attributes */
289 	&emlxs_dma_attr_1sg,		/* fca dma fcp rsp attributes */
290 	&emlxs_dma_attr_ro,		/* fca dma fcp data attributes */
291 	&emlxs_dma_attr_1sg,		/* fca dma fcip cmd attributes */
292 	&emlxs_dma_attr_fcip_rsp,	/* fca dma fcip rsp attributes */
293 	&emlxs_dma_attr_1sg,		/* fca dma fcsm cmd attributes */
294 	&emlxs_dma_attr,		/* fca dma fcsm rsp attributes */
295 	&emlxs_data_acc_attr,		/* fca access atributes */
296 	emlxs_bind_port,
297 	emlxs_unbind_port,
298 	emlxs_pkt_init,
299 	emlxs_pkt_uninit,
300 	emlxs_transport,
301 	emlxs_get_cap,
302 	emlxs_set_cap,
303 	emlxs_get_map,
304 	emlxs_transport,
305 	emlxs_ub_alloc,
306 	emlxs_ub_free,
307 	emlxs_ub_release,
308 	emlxs_pkt_abort,
309 	emlxs_reset,
310 	emlxs_port_manage,
311 	emlxs_get_device,
312 	emlxs_notify
313 };
314 #endif	/* EMLXS_MODEREV4 */
315 
316 
317 #if (EMLXS_MODREV == EMLXS_MODREV3)
318 static fc_fca_tran_t emlxs_fca_tran = {
319 	FCTL_FCA_MODREV_3,		/* fca_version */
320 	MAX_VPORTS,			/* fca numerb of ports */
321 	sizeof (emlxs_buf_t),		/* fca pkt size */
322 	2048,				/* fca cmd max */
323 	&emlxs_dma_lim,			/* fca dma limits */
324 	0,				/* fca iblock, to be filled in later */
325 	&emlxs_dma_attr,		/* fca dma attributes */
326 	&emlxs_dma_attr_1sg,		/* fca dma fcp cmd attributes */
327 	&emlxs_dma_attr_1sg,		/* fca dma fcp rsp attributes */
328 	&emlxs_dma_attr_ro,		/* fca dma fcp data attributes */
329 	&emlxs_dma_attr_1sg,		/* fca dma fcip cmd attributes */
330 	&emlxs_dma_attr_fcip_rsp,	/* fca dma fcip rsp attributes */
331 	&emlxs_dma_attr_1sg,		/* fca dma fcsm cmd attributes */
332 	&emlxs_dma_attr,		/* fca dma fcsm rsp attributes */
333 	&emlxs_data_acc_attr,		/* fca access atributes */
334 	emlxs_bind_port,
335 	emlxs_unbind_port,
336 	emlxs_pkt_init,
337 	emlxs_pkt_uninit,
338 	emlxs_transport,
339 	emlxs_get_cap,
340 	emlxs_set_cap,
341 	emlxs_get_map,
342 	emlxs_transport,
343 	emlxs_ub_alloc,
344 	emlxs_ub_free,
345 	emlxs_ub_release,
346 	emlxs_pkt_abort,
347 	emlxs_reset,
348 	emlxs_port_manage,
349 	emlxs_get_device,
350 	emlxs_notify
351 };
352 #endif	/* EMLXS_MODREV3 */
353 
354 
355 #if (EMLXS_MODREV == EMLXS_MODREV2)
356 static fc_fca_tran_t emlxs_fca_tran = {
357 	FCTL_FCA_MODREV_2,		/* fca_version */
358 	MAX_VPORTS,			/* number of ports */
359 	sizeof (emlxs_buf_t),		/* pkt size */
360 	2048,				/* max cmds */
361 	&emlxs_dma_lim,			/* DMA limits */
362 	0,				/* iblock, to be filled in later */
363 	&emlxs_dma_attr,		/* dma attributes */
364 	&emlxs_data_acc_attr,		/* access atributes */
365 	emlxs_bind_port,
366 	emlxs_unbind_port,
367 	emlxs_pkt_init,
368 	emlxs_pkt_uninit,
369 	emlxs_transport,
370 	emlxs_get_cap,
371 	emlxs_set_cap,
372 	emlxs_get_map,
373 	emlxs_transport,
374 	emlxs_ub_alloc,
375 	emlxs_ub_free,
376 	emlxs_ub_release,
377 	emlxs_pkt_abort,
378 	emlxs_reset,
379 	emlxs_port_manage,
380 	emlxs_get_device,
381 	emlxs_notify
382 };
383 #endif	/* EMLXS_MODREV2 */
384 
385 /*
386  * This is needed when the module gets loaded by the kernel
387  * so ddi library calls get resolved.
388  */
389 #ifndef MODSYM_SUPPORT
390 char   _depends_on[] = "misc/fctl";
391 #endif /* MODSYM_SUPPORT */
392 
393 /*
394  * state pointer which the implementation uses as a place to
395  * hang a set of per-driver structures;
396  *
397  */
398 void		*emlxs_soft_state = NULL;
399 
400 /*
401  * Driver Global variables.
402  */
403 int32_t		emlxs_scsi_reset_delay = 3000;	/* milliseconds */
404 
405 emlxs_device_t  emlxs_device;
406 
407 uint32_t	emlxs_instance[MAX_FC_BRDS];	/* uses emlxs_device.lock */
408 uint32_t	emlxs_instance_count = 0;	/* uses emlxs_device.lock */
409 
410 
411 /*
412  * Single private "global" lock used to gain access to
413  * the hba_list and/or any other case where we want need to be
414  * single-threaded.
415  */
416 uint32_t	emlxs_diag_state;
417 
418 /*
419  * CB ops vector.  Used for administration only.
420  */
421 static struct cb_ops emlxs_cb_ops = {
422 	emlxs_open,	/* cb_open	*/
423 	emlxs_close,	/* cb_close	*/
424 	nodev,		/* cb_strategy	*/
425 	nodev,		/* cb_print	*/
426 	nodev,		/* cb_dump	*/
427 	nodev,		/* cb_read	*/
428 	nodev,		/* cb_write	*/
429 	emlxs_ioctl,	/* cb_ioctl	*/
430 	nodev,		/* cb_devmap	*/
431 	nodev,		/* cb_mmap	*/
432 	nodev,		/* cb_segmap	*/
433 	nochpoll,	/* cb_chpoll	*/
434 	ddi_prop_op,	/* cb_prop_op	*/
435 	0,		/* cb_stream	*/
436 #ifdef _LP64
437 	D_64BIT | D_HOTPLUG | D_MP | D_NEW,	/* cb_flag */
438 #else
439 	D_HOTPLUG | D_MP | D_NEW,		/* cb_flag */
440 #endif
441 	CB_REV,		/* rev		*/
442 	nodev,		/* cb_aread	*/
443 	nodev		/* cb_awrite	*/
444 };
445 
446 static struct dev_ops emlxs_ops = {
447 	DEVO_REV,	/* rev */
448 	0,	/* refcnt */
449 	emlxs_info,	/* getinfo	*/
450 	nulldev,	/* identify	*/
451 	nulldev,	/* probe	*/
452 	emlxs_attach,	/* attach	*/
453 	emlxs_detach,	/* detach	*/
454 	nodev,		/* reset	*/
455 	&emlxs_cb_ops,	/* devo_cb_ops	*/
456 	NULL,		/* devo_bus_ops */
457 	emlxs_power,	/* power ops	*/
458 #ifdef EMLXS_I386
459 #ifdef S11
460 	emlxs_quiesce,	/* quiesce	*/
461 #endif
462 #endif
463 };
464 
465 #include <sys/modctl.h>
466 extern struct mod_ops mod_driverops;
467 
468 #ifdef SAN_DIAG_SUPPORT
469 extern kmutex_t		sd_bucket_mutex;
470 extern sd_bucket_info_t	sd_bucket;
471 #endif /* SAN_DIAG_SUPPORT */
472 
473 /*
474  * Module linkage information for the kernel.
475  */
476 static struct modldrv emlxs_modldrv = {
477 	&mod_driverops,	/* module type - driver */
478 	emlxs_name,	/* module name */
479 	&emlxs_ops,	/* driver ops */
480 };
481 
482 
483 /*
484  * Driver module linkage structure
485  */
486 static struct modlinkage emlxs_modlinkage = {
487 	MODREV_1,	/* ml_rev - must be MODREV_1 */
488 	&emlxs_modldrv,	/* ml_linkage */
489 	NULL	/* end of driver linkage */
490 };
491 
492 
493 /* We only need to add entries for non-default return codes. */
494 /* Entries do not need to be in order. */
495 /* Default:	FC_PKT_TRAN_ERROR,	FC_REASON_ABORTED, */
496 /*		FC_EXPLN_NONE,		FC_ACTION_RETRYABLE */
497 
498 emlxs_xlat_err_t emlxs_iostat_tbl[] = {
499 /* 	{f/w code, pkt_state, pkt_reason, 	*/
500 /* 		pkt_expln, pkt_action}		*/
501 
502 	/* 0x00 - Do not remove */
503 	{IOSTAT_SUCCESS, FC_PKT_SUCCESS, FC_REASON_NONE,
504 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
505 
506 	/* 0x01 - Do not remove */
507 	{IOSTAT_FCP_RSP_ERROR, FC_PKT_SUCCESS, FC_REASON_NONE,
508 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
509 
510 	/* 0x02 */
511 	{IOSTAT_REMOTE_STOP, FC_PKT_REMOTE_STOP, FC_REASON_ABTS,
512 		FC_EXPLN_NONE, FC_ACTION_NON_RETRYABLE},
513 
514 	/*
515 	 * This is a default entry.
516 	 * The real codes are written dynamically in emlxs_els.c
517 	 */
518 	/* 0x09 */
519 	{IOSTAT_LS_RJT, FC_PKT_LS_RJT, FC_REASON_CMD_UNABLE,
520 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
521 
522 	/* Special error code */
523 	/* 0x10 */
524 	{IOSTAT_DATA_OVERRUN, FC_PKT_TRAN_ERROR, FC_REASON_OVERRUN,
525 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
526 
527 	/* Special error code */
528 	/* 0x11 */
529 	{IOSTAT_DATA_UNDERRUN, FC_PKT_TRAN_ERROR, FC_REASON_ABORTED,
530 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
531 
532 	/* CLASS 2 only */
533 	/* 0x04 */
534 	{IOSTAT_NPORT_RJT, FC_PKT_NPORT_RJT, FC_REASON_PROTOCOL_ERROR,
535 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
536 
537 	/* CLASS 2 only */
538 	/* 0x05 */
539 	{IOSTAT_FABRIC_RJT, FC_PKT_FABRIC_RJT, FC_REASON_PROTOCOL_ERROR,
540 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
541 
542 	/* CLASS 2 only */
543 	/* 0x06 */
544 	{IOSTAT_NPORT_BSY, FC_PKT_NPORT_BSY, FC_REASON_PHYSICAL_BUSY,
545 		FC_EXPLN_NONE, FC_ACTION_SEQ_TERM_RETRY},
546 
547 	/* CLASS 2 only */
548 	/* 0x07 */
549 	{IOSTAT_FABRIC_BSY, FC_PKT_FABRIC_BSY, FC_REASON_FABRIC_BSY,
550 		FC_EXPLN_NONE, FC_ACTION_SEQ_TERM_RETRY},
551 };
552 
553 #define	IOSTAT_MAX (sizeof (emlxs_iostat_tbl)/sizeof (emlxs_xlat_err_t))
554 
555 
556 /* We only need to add entries for non-default return codes. */
557 /* Entries do not need to be in order. */
558 /* Default:	FC_PKT_TRAN_ERROR,	FC_REASON_ABORTED, */
559 /*		FC_EXPLN_NONE,		FC_ACTION_RETRYABLE} */
560 
561 emlxs_xlat_err_t emlxs_ioerr_tbl[] = {
562 /*	{f/w code, pkt_state, pkt_reason,	*/
563 /*		pkt_expln, pkt_action}		*/
564 
565 	/* 0x01 */
566 	{IOERR_MISSING_CONTINUE, FC_PKT_TRAN_ERROR, FC_REASON_OVERRUN,
567 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
568 
569 	/* 0x02 */
570 	{IOERR_SEQUENCE_TIMEOUT, FC_PKT_TIMEOUT, FC_REASON_SEQ_TIMEOUT,
571 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
572 
573 	/* 0x04 */
574 	{IOERR_INVALID_RPI, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE,
575 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
576 
577 	/* 0x05 */
578 	{IOERR_NO_XRI, FC_PKT_LOCAL_RJT, FC_REASON_XCHG_DROPPED,
579 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
580 
581 	/* 0x06 */
582 	{IOERR_ILLEGAL_COMMAND,	FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_REQ,
583 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
584 
585 	/* 0x07 */
586 	{IOERR_XCHG_DROPPED, FC_PKT_LOCAL_RJT,	FC_REASON_XCHG_DROPPED,
587 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
588 
589 	/* 0x08 */
590 	{IOERR_ILLEGAL_FIELD, FC_PKT_LOCAL_RJT,	FC_REASON_ILLEGAL_REQ,
591 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
592 
593 	/* 0x0B */
594 	{IOERR_RCV_BUFFER_WAITING, FC_PKT_LOCAL_RJT, FC_REASON_NOMEM,
595 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
596 
597 	/* 0x0D */
598 	{IOERR_TX_DMA_FAILED, FC_PKT_LOCAL_RJT,	FC_REASON_DMA_ERROR,
599 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
600 
601 	/* 0x0E */
602 	{IOERR_RX_DMA_FAILED, FC_PKT_LOCAL_RJT,	FC_REASON_DMA_ERROR,
603 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
604 
605 	/* 0x0F */
606 	{IOERR_ILLEGAL_FRAME, FC_PKT_LOCAL_RJT,	FC_REASON_ILLEGAL_FRAME,
607 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
608 
609 	/* 0x11 */
610 	{IOERR_NO_RESOURCES, FC_PKT_LOCAL_RJT,	FC_REASON_NOMEM,
611 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
612 
613 	/* 0x13 */
614 	{IOERR_ILLEGAL_LENGTH, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_LENGTH,
615 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
616 
617 	/* 0x14 */
618 	{IOERR_UNSUPPORTED_FEATURE, FC_PKT_LOCAL_RJT, FC_REASON_UNSUPPORTED,
619 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
620 
621 	/* 0x15 */
622 	{IOERR_ABORT_IN_PROGRESS, FC_PKT_LOCAL_RJT, FC_REASON_ABORTED,
623 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
624 
625 	/* 0x16 */
626 	{IOERR_ABORT_REQUESTED, FC_PKT_LOCAL_RJT, FC_REASON_ABORTED,
627 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
628 
629 	/* 0x17 */
630 	{IOERR_RCV_BUFFER_TIMEOUT, FC_PKT_LOCAL_RJT, FC_REASON_RX_BUF_TIMEOUT,
631 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
632 
633 	/* 0x18 */
634 	{IOERR_LOOP_OPEN_FAILURE, FC_PKT_LOCAL_RJT, FC_REASON_FCAL_OPN_FAIL,
635 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
636 
637 	/* 0x1A */
638 	{IOERR_LINK_DOWN, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE,
639 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
640 
641 	/* 0x21 */
642 	{IOERR_BAD_HOST_ADDRESS, FC_PKT_LOCAL_RJT, FC_REASON_BAD_SID,
643 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
644 
645 	/* Occurs at link down */
646 	/* 0x28 */
647 	{IOERR_BUFFER_SHORTAGE, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE,
648 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
649 
650 	/* 0xF0 */
651 	{IOERR_ABORT_TIMEOUT, FC_PKT_TIMEOUT, FC_REASON_SEQ_TIMEOUT,
652 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
653 };
654 
655 #define	IOERR_MAX    (sizeof (emlxs_ioerr_tbl)/sizeof (emlxs_xlat_err_t))
656 
657 
658 
659 emlxs_table_t emlxs_error_table[] = {
660 	{IOERR_SUCCESS, "No error."},
661 	{IOERR_MISSING_CONTINUE, "Missing continue."},
662 	{IOERR_SEQUENCE_TIMEOUT, "Sequence timeout."},
663 	{IOERR_INTERNAL_ERROR, "Internal error."},
664 	{IOERR_INVALID_RPI, "Invalid RPI."},
665 	{IOERR_NO_XRI, "No XRI."},
666 	{IOERR_ILLEGAL_COMMAND, "Illegal command."},
667 	{IOERR_XCHG_DROPPED, "Exchange dropped."},
668 	{IOERR_ILLEGAL_FIELD, "Illegal field."},
669 	{IOERR_RCV_BUFFER_WAITING, "RX buffer waiting."},
670 	{IOERR_TX_DMA_FAILED, "TX DMA failed."},
671 	{IOERR_RX_DMA_FAILED, "RX DMA failed."},
672 	{IOERR_ILLEGAL_FRAME, "Illegal frame."},
673 	{IOERR_NO_RESOURCES, "No resources."},
674 	{IOERR_ILLEGAL_LENGTH, "Illegal length."},
675 	{IOERR_UNSUPPORTED_FEATURE, "Unsupported feature."},
676 	{IOERR_ABORT_IN_PROGRESS, "Abort in progess."},
677 	{IOERR_ABORT_REQUESTED, "Abort requested."},
678 	{IOERR_RCV_BUFFER_TIMEOUT, "RX buffer timeout."},
679 	{IOERR_LOOP_OPEN_FAILURE, "Loop open failed."},
680 	{IOERR_RING_RESET, "Ring reset."},
681 	{IOERR_LINK_DOWN, "Link down."},
682 	{IOERR_CORRUPTED_DATA, "Corrupted data."},
683 	{IOERR_CORRUPTED_RPI, "Corrupted RPI."},
684 	{IOERR_OUT_OF_ORDER_DATA, "Out-of-order data."},
685 	{IOERR_OUT_OF_ORDER_ACK, "Out-of-order ack."},
686 	{IOERR_DUP_FRAME, "Duplicate frame."},
687 	{IOERR_LINK_CONTROL_FRAME, "Link control frame."},
688 	{IOERR_BAD_HOST_ADDRESS, "Bad host address."},
689 	{IOERR_RCV_HDRBUF_WAITING, "RX header buffer waiting."},
690 	{IOERR_MISSING_HDR_BUFFER, "Missing header buffer."},
691 	{IOERR_MSEQ_CHAIN_CORRUPTED, "MSEQ chain corrupted."},
692 	{IOERR_ABORTMULT_REQUESTED, "Abort multiple requested."},
693 	{IOERR_BUFFER_SHORTAGE, "Buffer shortage."},
694 	{IOERR_XRIBUF_WAITING, "XRI buffer shortage"},
695 	{IOERR_XRIBUF_MISSING, "XRI buffer missing"},
696 	{IOERR_ROFFSET_INVAL, "Relative offset invalid."},
697 	{IOERR_ROFFSET_MISSING, "Relative offset missing."},
698 	{IOERR_INSUF_BUFFER, "Buffer too small."},
699 	{IOERR_MISSING_SI, "ELS frame missing SI"},
700 	{IOERR_MISSING_ES, "Exhausted burst without ES"},
701 	{IOERR_INCOMP_XFER, "Transfer incomplete."},
702 	{IOERR_ABORT_TIMEOUT, "Abort timeout."}
703 
704 };	/* emlxs_error_table */
705 
706 
707 emlxs_table_t emlxs_state_table[] = {
708 	{IOSTAT_SUCCESS, "Success."},
709 	{IOSTAT_FCP_RSP_ERROR, "FCP response error."},
710 	{IOSTAT_REMOTE_STOP, "Remote stop."},
711 	{IOSTAT_LOCAL_REJECT, "Local reject."},
712 	{IOSTAT_NPORT_RJT, "NPort reject."},
713 	{IOSTAT_FABRIC_RJT, "Fabric reject."},
714 	{IOSTAT_NPORT_BSY, "Nport busy."},
715 	{IOSTAT_FABRIC_BSY, "Fabric busy."},
716 	{IOSTAT_INTERMED_RSP, "Intermediate response."},
717 	{IOSTAT_LS_RJT, "LS reject."},
718 	{IOSTAT_CMD_REJECT,		"Cmd reject."},
719 	{IOSTAT_FCP_TGT_LENCHK, "TGT length check."},
720 	{IOSTAT_NEED_BUFF_ENTRY, "Need buffer entry."},
721 	{IOSTAT_DATA_UNDERRUN, "Data underrun."},
722 	{IOSTAT_DATA_OVERRUN,  "Data overrun."},
723 
724 };	/* emlxs_state_table */
725 
726 
727 #ifdef MENLO_SUPPORT
728 emlxs_table_t emlxs_menlo_cmd_table[] = {
729 	{MENLO_CMD_INITIALIZE,		"MENLO_INIT"},
730 	{MENLO_CMD_FW_DOWNLOAD,		"MENLO_FW_DOWNLOAD"},
731 	{MENLO_CMD_READ_MEMORY,		"MENLO_READ_MEM"},
732 	{MENLO_CMD_WRITE_MEMORY,	"MENLO_WRITE_MEM"},
733 	{MENLO_CMD_FTE_INSERT,		"MENLO_FTE_INSERT"},
734 	{MENLO_CMD_FTE_DELETE,		"MENLO_FTE_DELETE"},
735 
736 	{MENLO_CMD_GET_INIT,		"MENLO_GET_INIT"},
737 	{MENLO_CMD_GET_CONFIG,		"MENLO_GET_CONFIG"},
738 	{MENLO_CMD_GET_PORT_STATS,	"MENLO_GET_PORT_STATS"},
739 	{MENLO_CMD_GET_LIF_STATS,	"MENLO_GET_LIF_STATS"},
740 	{MENLO_CMD_GET_ASIC_STATS,	"MENLO_GET_ASIC_STATS"},
741 	{MENLO_CMD_GET_LOG_CONFIG,	"MENLO_GET_LOG_CFG"},
742 	{MENLO_CMD_GET_LOG_DATA,	"MENLO_GET_LOG_DATA"},
743 	{MENLO_CMD_GET_PANIC_LOG,	"MENLO_GET_PANIC_LOG"},
744 	{MENLO_CMD_GET_LB_MODE,		"MENLO_GET_LB_MODE"},
745 
746 	{MENLO_CMD_SET_PAUSE,		"MENLO_SET_PAUSE"},
747 	{MENLO_CMD_SET_FCOE_COS,	"MENLO_SET_FCOE_COS"},
748 	{MENLO_CMD_SET_UIF_PORT_TYPE,	"MENLO_SET_UIF_TYPE"},
749 
750 	{MENLO_CMD_DIAGNOSTICS,		"MENLO_DIAGNOSTICS"},
751 	{MENLO_CMD_LOOPBACK,		"MENLO_LOOPBACK"},
752 
753 	{MENLO_CMD_RESET,		"MENLO_RESET"},
754 	{MENLO_CMD_SET_MODE,		"MENLO_SET_MODE"}
755 
756 };	/* emlxs_menlo_cmd_table */
757 
758 emlxs_table_t emlxs_menlo_rsp_table[] = {
759 	{MENLO_RSP_SUCCESS,		"SUCCESS"},
760 	{MENLO_ERR_FAILED,		"FAILED"},
761 	{MENLO_ERR_INVALID_CMD,		"INVALID_CMD"},
762 	{MENLO_ERR_INVALID_CREDIT,	"INVALID_CREDIT"},
763 	{MENLO_ERR_INVALID_SIZE,	"INVALID_SIZE"},
764 	{MENLO_ERR_INVALID_ADDRESS,	"INVALID_ADDRESS"},
765 	{MENLO_ERR_INVALID_CONTEXT,	"INVALID_CONTEXT"},
766 	{MENLO_ERR_INVALID_LENGTH,	"INVALID_LENGTH"},
767 	{MENLO_ERR_INVALID_TYPE,	"INVALID_TYPE"},
768 	{MENLO_ERR_INVALID_DATA,	"INVALID_DATA"},
769 	{MENLO_ERR_INVALID_VALUE1,	"INVALID_VALUE1"},
770 	{MENLO_ERR_INVALID_VALUE2,	"INVALID_VALUE2"},
771 	{MENLO_ERR_INVALID_MASK,	"INVALID_MASK"},
772 	{MENLO_ERR_CHECKSUM,		"CHECKSUM_ERROR"},
773 	{MENLO_ERR_UNKNOWN_FCID,	"UNKNOWN_FCID"},
774 	{MENLO_ERR_UNKNOWN_WWN,		"UNKNOWN_WWN"},
775 	{MENLO_ERR_BUSY,		"BUSY"},
776 
777 };	/* emlxs_menlo_rsp_table */
778 
779 #endif /* MENLO_SUPPORT */
780 
781 
782 emlxs_table_t emlxs_mscmd_table[] = {
783 	{SLI_CT_RESPONSE_FS_ACC, "CT_ACC"},
784 	{SLI_CT_RESPONSE_FS_RJT, "CT_RJT"},
785 	{MS_GTIN, "MS_GTIN"},
786 	{MS_GIEL, "MS_GIEL"},
787 	{MS_GIET, "MS_GIET"},
788 	{MS_GDID, "MS_GDID"},
789 	{MS_GMID, "MS_GMID"},
790 	{MS_GFN, "MS_GFN"},
791 	{MS_GIELN, "MS_GIELN"},
792 	{MS_GMAL, "MS_GMAL"},
793 	{MS_GIEIL, "MS_GIEIL"},
794 	{MS_GPL, "MS_GPL"},
795 	{MS_GPT, "MS_GPT"},
796 	{MS_GPPN, "MS_GPPN"},
797 	{MS_GAPNL, "MS_GAPNL"},
798 	{MS_GPS, "MS_GPS"},
799 	{MS_GPSC, "MS_GPSC"},
800 	{MS_GATIN, "MS_GATIN"},
801 	{MS_GSES, "MS_GSES"},
802 	{MS_GPLNL, "MS_GPLNL"},
803 	{MS_GPLT, "MS_GPLT"},
804 	{MS_GPLML, "MS_GPLML"},
805 	{MS_GPAB, "MS_GPAB"},
806 	{MS_GNPL, "MS_GNPL"},
807 	{MS_GPNL, "MS_GPNL"},
808 	{MS_GPFCP, "MS_GPFCP"},
809 	{MS_GPLI, "MS_GPLI"},
810 	{MS_GNID, "MS_GNID"},
811 	{MS_RIELN, "MS_RIELN"},
812 	{MS_RPL, "MS_RPL"},
813 	{MS_RPLN, "MS_RPLN"},
814 	{MS_RPLT, "MS_RPLT"},
815 	{MS_RPLM, "MS_RPLM"},
816 	{MS_RPAB, "MS_RPAB"},
817 	{MS_RPFCP, "MS_RPFCP"},
818 	{MS_RPLI, "MS_RPLI"},
819 	{MS_DPL, "MS_DPL"},
820 	{MS_DPLN, "MS_DPLN"},
821 	{MS_DPLM, "MS_DPLM"},
822 	{MS_DPLML, "MS_DPLML"},
823 	{MS_DPLI, "MS_DPLI"},
824 	{MS_DPAB, "MS_DPAB"},
825 	{MS_DPALL, "MS_DPALL"}
826 
827 };	/* emlxs_mscmd_table */
828 
829 
830 emlxs_table_t emlxs_ctcmd_table[] = {
831 	{SLI_CT_RESPONSE_FS_ACC, "CT_ACC"},
832 	{SLI_CT_RESPONSE_FS_RJT, "CT_RJT"},
833 	{SLI_CTNS_GA_NXT, "GA_NXT"},
834 	{SLI_CTNS_GPN_ID, "GPN_ID"},
835 	{SLI_CTNS_GNN_ID, "GNN_ID"},
836 	{SLI_CTNS_GCS_ID, "GCS_ID"},
837 	{SLI_CTNS_GFT_ID, "GFT_ID"},
838 	{SLI_CTNS_GSPN_ID, "GSPN_ID"},
839 	{SLI_CTNS_GPT_ID, "GPT_ID"},
840 	{SLI_CTNS_GID_PN, "GID_PN"},
841 	{SLI_CTNS_GID_NN, "GID_NN"},
842 	{SLI_CTNS_GIP_NN, "GIP_NN"},
843 	{SLI_CTNS_GIPA_NN, "GIPA_NN"},
844 	{SLI_CTNS_GSNN_NN, "GSNN_NN"},
845 	{SLI_CTNS_GNN_IP, "GNN_IP"},
846 	{SLI_CTNS_GIPA_IP, "GIPA_IP"},
847 	{SLI_CTNS_GID_FT, "GID_FT"},
848 	{SLI_CTNS_GID_PT, "GID_PT"},
849 	{SLI_CTNS_RPN_ID, "RPN_ID"},
850 	{SLI_CTNS_RNN_ID, "RNN_ID"},
851 	{SLI_CTNS_RCS_ID, "RCS_ID"},
852 	{SLI_CTNS_RFT_ID, "RFT_ID"},
853 	{SLI_CTNS_RSPN_ID, "RSPN_ID"},
854 	{SLI_CTNS_RPT_ID, "RPT_ID"},
855 	{SLI_CTNS_RIP_NN, "RIP_NN"},
856 	{SLI_CTNS_RIPA_NN, "RIPA_NN"},
857 	{SLI_CTNS_RSNN_NN, "RSNN_NN"},
858 	{SLI_CTNS_DA_ID, "DA_ID"},
859 	{SLI_CT_LOOPBACK, "LOOPBACK"} /* Driver special */
860 
861 };	/* emlxs_ctcmd_table */
862 
863 
864 
865 emlxs_table_t emlxs_rmcmd_table[] = {
866 	{SLI_CT_RESPONSE_FS_ACC, "CT_ACC"},
867 	{SLI_CT_RESPONSE_FS_RJT, "CT_RJT"},
868 	{CT_OP_GSAT, "RM_GSAT"},
869 	{CT_OP_GHAT, "RM_GHAT"},
870 	{CT_OP_GPAT, "RM_GPAT"},
871 	{CT_OP_GDAT, "RM_GDAT"},
872 	{CT_OP_GPST, "RM_GPST"},
873 	{CT_OP_GDP, "RM_GDP"},
874 	{CT_OP_GDPG, "RM_GDPG"},
875 	{CT_OP_GEPS, "RM_GEPS"},
876 	{CT_OP_GLAT, "RM_GLAT"},
877 	{CT_OP_SSAT, "RM_SSAT"},
878 	{CT_OP_SHAT, "RM_SHAT"},
879 	{CT_OP_SPAT, "RM_SPAT"},
880 	{CT_OP_SDAT, "RM_SDAT"},
881 	{CT_OP_SDP, "RM_SDP"},
882 	{CT_OP_SBBS, "RM_SBBS"},
883 	{CT_OP_RPST, "RM_RPST"},
884 	{CT_OP_VFW, "RM_VFW"},
885 	{CT_OP_DFW, "RM_DFW"},
886 	{CT_OP_RES, "RM_RES"},
887 	{CT_OP_RHD, "RM_RHD"},
888 	{CT_OP_UFW, "RM_UFW"},
889 	{CT_OP_RDP, "RM_RDP"},
890 	{CT_OP_GHDR, "RM_GHDR"},
891 	{CT_OP_CHD, "RM_CHD"},
892 	{CT_OP_SSR, "RM_SSR"},
893 	{CT_OP_RSAT, "RM_RSAT"},
894 	{CT_OP_WSAT, "RM_WSAT"},
895 	{CT_OP_RSAH, "RM_RSAH"},
896 	{CT_OP_WSAH, "RM_WSAH"},
897 	{CT_OP_RACT, "RM_RACT"},
898 	{CT_OP_WACT, "RM_WACT"},
899 	{CT_OP_RKT, "RM_RKT"},
900 	{CT_OP_WKT, "RM_WKT"},
901 	{CT_OP_SSC, "RM_SSC"},
902 	{CT_OP_QHBA, "RM_QHBA"},
903 	{CT_OP_GST, "RM_GST"},
904 	{CT_OP_GFTM, "RM_GFTM"},
905 	{CT_OP_SRL, "RM_SRL"},
906 	{CT_OP_SI, "RM_SI"},
907 	{CT_OP_SRC, "RM_SRC"},
908 	{CT_OP_GPB, "RM_GPB"},
909 	{CT_OP_SPB, "RM_SPB"},
910 	{CT_OP_RPB, "RM_RPB"},
911 	{CT_OP_RAPB, "RM_RAPB"},
912 	{CT_OP_GBC, "RM_GBC"},
913 	{CT_OP_GBS, "RM_GBS"},
914 	{CT_OP_SBS, "RM_SBS"},
915 	{CT_OP_GANI, "RM_GANI"},
916 	{CT_OP_GRV, "RM_GRV"},
917 	{CT_OP_GAPBS, "RM_GAPBS"},
918 	{CT_OP_APBC, "RM_APBC"},
919 	{CT_OP_GDT, "RM_GDT"},
920 	{CT_OP_GDLMI, "RM_GDLMI"},
921 	{CT_OP_GANA, "RM_GANA"},
922 	{CT_OP_GDLV, "RM_GDLV"},
923 	{CT_OP_GWUP, "RM_GWUP"},
924 	{CT_OP_GLM, "RM_GLM"},
925 	{CT_OP_GABS, "RM_GABS"},
926 	{CT_OP_SABS, "RM_SABS"},
927 	{CT_OP_RPR, "RM_RPR"},
928 	{SLI_CT_LOOPBACK, "LOOPBACK"} /* Driver special */
929 
930 };	/* emlxs_rmcmd_table */
931 
932 
933 emlxs_table_t emlxs_elscmd_table[] = {
934 	{ELS_CMD_ACC, "ACC"},
935 	{ELS_CMD_LS_RJT, "LS_RJT"},
936 	{ELS_CMD_PLOGI, "PLOGI"},
937 	{ELS_CMD_FLOGI, "FLOGI"},
938 	{ELS_CMD_LOGO, "LOGO"},
939 	{ELS_CMD_ABTX, "ABTX"},
940 	{ELS_CMD_RCS, "RCS"},
941 	{ELS_CMD_RES, "RES"},
942 	{ELS_CMD_RSS, "RSS"},
943 	{ELS_CMD_RSI, "RSI"},
944 	{ELS_CMD_ESTS, "ESTS"},
945 	{ELS_CMD_ESTC, "ESTC"},
946 	{ELS_CMD_ADVC, "ADVC"},
947 	{ELS_CMD_RTV, "RTV"},
948 	{ELS_CMD_RLS, "RLS"},
949 	{ELS_CMD_ECHO, "ECHO"},
950 	{ELS_CMD_TEST, "TEST"},
951 	{ELS_CMD_RRQ, "RRQ"},
952 	{ELS_CMD_PRLI, "PRLI"},
953 	{ELS_CMD_PRLO, "PRLO"},
954 	{ELS_CMD_SCN, "SCN"},
955 	{ELS_CMD_TPLS, "TPLS"},
956 	{ELS_CMD_GPRLO, "GPRLO"},
957 	{ELS_CMD_GAID, "GAID"},
958 	{ELS_CMD_FACT, "FACT"},
959 	{ELS_CMD_FDACT, "FDACT"},
960 	{ELS_CMD_NACT, "NACT"},
961 	{ELS_CMD_NDACT, "NDACT"},
962 	{ELS_CMD_QoSR, "QoSR"},
963 	{ELS_CMD_RVCS, "RVCS"},
964 	{ELS_CMD_PDISC, "PDISC"},
965 	{ELS_CMD_FDISC, "FDISC"},
966 	{ELS_CMD_ADISC, "ADISC"},
967 	{ELS_CMD_FARP, "FARP"},
968 	{ELS_CMD_FARPR, "FARPR"},
969 	{ELS_CMD_FAN, "FAN"},
970 	{ELS_CMD_RSCN, "RSCN"},
971 	{ELS_CMD_SCR, "SCR"},
972 	{ELS_CMD_LINIT, "LINIT"},
973 	{ELS_CMD_RNID, "RNID"},
974 	{ELS_CMD_AUTH, "AUTH"}
975 
976 };	/* emlxs_elscmd_table */
977 
978 
979 /*
980  *
981  *	Device Driver Entry Routines
982  *
983  */
984 
985 #ifdef MODSYM_SUPPORT
986 static void emlxs_fca_modclose();
987 static int  emlxs_fca_modopen();
988 emlxs_modsym_t emlxs_modsym;	/* uses emlxs_device.lock */
989 
990 static int
991 emlxs_fca_modopen()
992 {
993 	int err;
994 
995 	if (emlxs_modsym.mod_fctl) {
996 		return (0);
997 	}
998 
999 	/* Leadville (fctl) */
1000 	err = 0;
1001 	emlxs_modsym.mod_fctl =
1002 	    ddi_modopen("misc/fctl", KRTLD_MODE_FIRST, &err);
1003 	if (!emlxs_modsym.mod_fctl) {
1004 		cmn_err(CE_WARN,
1005 		    "?%s: misc/fctl: ddi_modopen misc/fctl failed: error=%d",
1006 		    DRIVER_NAME, err);
1007 
1008 		goto failed;
1009 	}
1010 
1011 	err = 0;
1012 	/* Check if the fctl fc_fca_attach is present */
1013 	emlxs_modsym.fc_fca_attach =
1014 	    (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_attach",
1015 	    &err);
1016 	if ((void *)emlxs_modsym.fc_fca_attach == NULL) {
1017 		cmn_err(CE_WARN,
1018 		    "?%s: misc/fctl: fc_fca_attach not present", DRIVER_NAME);
1019 		goto failed;
1020 	}
1021 
1022 	err = 0;
1023 	/* Check if the fctl fc_fca_detach is present */
1024 	emlxs_modsym.fc_fca_detach =
1025 	    (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_detach",
1026 	    &err);
1027 	if ((void *)emlxs_modsym.fc_fca_detach == NULL) {
1028 		cmn_err(CE_WARN,
1029 		    "?%s: misc/fctl: fc_fca_detach not present", DRIVER_NAME);
1030 		goto failed;
1031 	}
1032 
1033 	err = 0;
1034 	/* Check if the fctl fc_fca_init is present */
1035 	emlxs_modsym.fc_fca_init =
1036 	    (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_init", &err);
1037 	if ((void *)emlxs_modsym.fc_fca_init == NULL) {
1038 		cmn_err(CE_WARN,
1039 		    "?%s: misc/fctl: fc_fca_init not present", DRIVER_NAME);
1040 		goto failed;
1041 	}
1042 
1043 	return (0);
1044 
1045 failed:
1046 
1047 	emlxs_fca_modclose();
1048 
1049 	return (1);
1050 
1051 
1052 } /* emlxs_fca_modopen() */
1053 
1054 
1055 static void
1056 emlxs_fca_modclose()
1057 {
1058 	if (emlxs_modsym.mod_fctl) {
1059 		(void) ddi_modclose(emlxs_modsym.mod_fctl);
1060 		emlxs_modsym.mod_fctl = 0;
1061 	}
1062 
1063 	emlxs_modsym.fc_fca_attach = NULL;
1064 	emlxs_modsym.fc_fca_detach = NULL;
1065 	emlxs_modsym.fc_fca_init   = NULL;
1066 
1067 	return;
1068 
1069 } /* emlxs_fca_modclose() */
1070 
1071 #endif /* MODSYM_SUPPORT */
1072 
1073 
1074 
1075 /*
1076  * Global driver initialization, called once when driver is loaded
1077  */
1078 int
1079 _init(void)
1080 {
1081 	int ret;
1082 	char buf[64];
1083 
1084 	/*
1085 	 * First init call for this driver,
1086 	 * so initialize the emlxs_dev_ctl structure.
1087 	 */
1088 	bzero(&emlxs_device, sizeof (emlxs_device));
1089 
1090 #ifdef MODSYM_SUPPORT
1091 	bzero(&emlxs_modsym, sizeof (emlxs_modsym_t));
1092 #endif /* MODSYM_SUPPORT */
1093 
1094 	(void) sprintf(buf, "%s_device mutex", DRIVER_NAME);
1095 	mutex_init(&emlxs_device.lock, buf, MUTEX_DRIVER, NULL);
1096 
1097 	(void) drv_getparm(LBOLT, &emlxs_device.log_timestamp);
1098 	emlxs_device.drv_timestamp = ddi_get_time();
1099 
1100 	for (ret = 0; ret < MAX_FC_BRDS; ret++) {
1101 		emlxs_instance[ret] = (uint32_t)-1;
1102 	}
1103 
1104 	/*
1105 	 * Provide for one ddiinst of the emlxs_dev_ctl structure
1106 	 * for each possible board in the system.
1107 	 */
1108 	if ((ret = ddi_soft_state_init(&emlxs_soft_state,
1109 	    sizeof (emlxs_hba_t), MAX_FC_BRDS)) != 0) {
1110 		cmn_err(CE_WARN,
1111 		    "?%s: _init: ddi_soft_state_init failed. rval=%x",
1112 		    DRIVER_NAME, ret);
1113 
1114 		return (ret);
1115 	}
1116 
1117 #ifdef MODSYM_SUPPORT
1118 	/* Open SFS */
1119 	(void) emlxs_fca_modopen();
1120 #endif /* MODSYM_SUPPORT */
1121 
1122 	/* Setup devops for SFS */
1123 	MODSYM(fc_fca_init)(&emlxs_ops);
1124 
1125 	if ((ret = mod_install(&emlxs_modlinkage)) != 0) {
1126 		(void) ddi_soft_state_fini(&emlxs_soft_state);
1127 #ifdef MODSYM_SUPPORT
1128 		/* Close SFS */
1129 		emlxs_fca_modclose();
1130 #endif /* MODSYM_SUPPORT */
1131 
1132 		return (ret);
1133 	}
1134 
1135 #ifdef SAN_DIAG_SUPPORT
1136 	(void) sprintf(buf, "%s_sd_bucket mutex", DRIVER_NAME);
1137 	mutex_init(&sd_bucket_mutex, buf, MUTEX_DRIVER, NULL);
1138 #endif /* SAN_DIAG_SUPPORT */
1139 
1140 	return (ret);
1141 
1142 } /* _init() */
1143 
1144 
1145 /*
1146  * Called when driver is unloaded.
1147  */
1148 int
1149 _fini(void)
1150 {
1151 	int ret;
1152 
1153 	if ((ret = mod_remove(&emlxs_modlinkage)) != 0) {
1154 		return (ret);
1155 	}
1156 #ifdef MODSYM_SUPPORT
1157 	/* Close SFS */
1158 	emlxs_fca_modclose();
1159 #endif /* MODSYM_SUPPORT */
1160 
1161 	/*
1162 	 * Destroy the soft state structure
1163 	 */
1164 	(void) ddi_soft_state_fini(&emlxs_soft_state);
1165 
1166 	/* Destroy the global device lock */
1167 	mutex_destroy(&emlxs_device.lock);
1168 
1169 #ifdef SAN_DIAG_SUPPORT
1170 	mutex_destroy(&sd_bucket_mutex);
1171 #endif /* SAN_DIAG_SUPPORT */
1172 
1173 	return (ret);
1174 
1175 } /* _fini() */
1176 
1177 
1178 
1179 int
1180 _info(struct modinfo *modinfop)
1181 {
1182 
1183 	return (mod_info(&emlxs_modlinkage, modinfop));
1184 
1185 } /* _info() */
1186 
1187 
1188 /*
1189  * Attach an ddiinst of an emlx host adapter.
1190  * Allocate data structures, initialize the adapter and we're ready to fly.
1191  */
1192 static int
1193 emlxs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1194 {
1195 	emlxs_hba_t *hba;
1196 	int ddiinst;
1197 	int emlxinst;
1198 	int rval;
1199 
1200 	switch (cmd) {
1201 	case DDI_ATTACH:
1202 		/* If successful this will set EMLXS_PM_IN_ATTACH */
1203 		rval = emlxs_hba_attach(dip);
1204 		break;
1205 
1206 	case DDI_PM_RESUME:
1207 		/* This will resume the driver */
1208 		rval = emlxs_pm_raise_power(dip);
1209 		break;
1210 
1211 	case DDI_RESUME:
1212 		/* This will resume the driver */
1213 		rval = emlxs_hba_resume(dip);
1214 		break;
1215 
1216 	default:
1217 		rval = DDI_FAILURE;
1218 	}
1219 
1220 	if (rval == DDI_SUCCESS) {
1221 		ddiinst = ddi_get_instance(dip);
1222 		emlxinst = emlxs_get_instance(ddiinst);
1223 		hba = emlxs_device.hba[emlxinst];
1224 
1225 		if ((hba != NULL) && (hba != (emlxs_hba_t *)-1)) {
1226 
1227 			/* Enable driver dump feature */
1228 			mutex_enter(&EMLXS_PORT_LOCK);
1229 			hba->flag |= FC_DUMP_SAFE;
1230 			mutex_exit(&EMLXS_PORT_LOCK);
1231 		}
1232 	}
1233 
1234 	return (rval);
1235 
1236 } /* emlxs_attach() */
1237 
1238 
1239 /*
1240  * Detach/prepare driver to unload (see detach(9E)).
1241  */
1242 static int
1243 emlxs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1244 {
1245 	emlxs_hba_t *hba;
1246 	emlxs_port_t *port;
1247 	int ddiinst;
1248 	int emlxinst;
1249 	int rval;
1250 
1251 	ddiinst = ddi_get_instance(dip);
1252 	emlxinst = emlxs_get_instance(ddiinst);
1253 	hba = emlxs_device.hba[emlxinst];
1254 
1255 	if (hba == NULL) {
1256 		cmn_err(CE_WARN, "?%s: Detach: NULL device.", DRIVER_NAME);
1257 
1258 		return (DDI_FAILURE);
1259 	}
1260 
1261 	if (hba == (emlxs_hba_t *)-1) {
1262 		cmn_err(CE_WARN, "?%s: Detach: Device attach failed.",
1263 		    DRIVER_NAME);
1264 
1265 		return (DDI_FAILURE);
1266 	}
1267 
1268 	port = &PPORT;
1269 	rval = DDI_SUCCESS;
1270 
1271 	/* Check driver dump */
1272 	mutex_enter(&EMLXS_PORT_LOCK);
1273 
1274 	if (hba->flag & FC_DUMP_ACTIVE) {
1275 		mutex_exit(&EMLXS_PORT_LOCK);
1276 
1277 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
1278 		    "emlxs_detach: Driver busy. Driver dump active.");
1279 
1280 		return (DDI_FAILURE);
1281 	}
1282 
1283 #ifdef SFCT_SUPPORT
1284 	if (port->tgt_mode && ((port->fct_flags & FCT_STATE_PORT_ONLINE) ||
1285 	    (port->fct_flags & FCT_STATE_NOT_ACKED))) {
1286 		mutex_exit(&EMLXS_PORT_LOCK);
1287 
1288 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
1289 		    "emlxs_detach: Driver busy. Target mode active.");
1290 
1291 		return (DDI_FAILURE);
1292 	}
1293 #endif /* SFCT_SUPPORT */
1294 
1295 	if (port->ini_mode && (port->flag & EMLXS_PORT_BOUND)) {
1296 		mutex_exit(&EMLXS_PORT_LOCK);
1297 
1298 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
1299 		    "emlxs_detach: Driver busy. Initiator mode active.");
1300 
1301 		return (DDI_FAILURE);
1302 	}
1303 
1304 	hba->flag &= ~FC_DUMP_SAFE;
1305 
1306 	mutex_exit(&EMLXS_PORT_LOCK);
1307 
1308 	switch (cmd) {
1309 	case DDI_DETACH:
1310 
1311 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg,
1312 		    "DDI_DETACH");
1313 
1314 		rval = emlxs_hba_detach(dip);
1315 
1316 		if (rval != DDI_SUCCESS) {
1317 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
1318 			    "Unable to detach.");
1319 		}
1320 		break;
1321 
1322 
1323 	case DDI_PM_SUSPEND:
1324 
1325 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg,
1326 		    "DDI_PM_SUSPEND");
1327 
1328 		/* This will suspend the driver */
1329 		rval = emlxs_pm_lower_power(dip);
1330 
1331 		if (rval != DDI_SUCCESS) {
1332 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
1333 			    "Unable to lower power.");
1334 		}
1335 
1336 		break;
1337 
1338 
1339 	case DDI_SUSPEND:
1340 
1341 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg,
1342 		    "DDI_SUSPEND");
1343 
1344 		/* Suspend the driver */
1345 		rval = emlxs_hba_suspend(dip);
1346 
1347 		if (rval != DDI_SUCCESS) {
1348 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
1349 			    "Unable to suspend driver.");
1350 		}
1351 		break;
1352 
1353 
1354 	default:
1355 		cmn_err(CE_WARN, "?%s: Detach: Unknown cmd received. cmd=%x",
1356 		    DRIVER_NAME, cmd);
1357 		rval = DDI_FAILURE;
1358 	}
1359 
1360 	if (rval == DDI_FAILURE) {
1361 		/* Re-Enable driver dump feature */
1362 		mutex_enter(&EMLXS_PORT_LOCK);
1363 		hba->flag |= FC_DUMP_SAFE;
1364 		mutex_exit(&EMLXS_PORT_LOCK);
1365 	}
1366 
1367 	return (rval);
1368 
1369 } /* emlxs_detach() */
1370 
1371 
1372 /* EMLXS_PORT_LOCK must be held when calling this */
1373 extern void
1374 emlxs_port_init(emlxs_port_t *port)
1375 {
1376 	emlxs_hba_t *hba = HBA;
1377 
1378 	/* Initialize the base node */
1379 	bzero((caddr_t)&port->node_base, sizeof (NODELIST));
1380 	port->node_base.nlp_Rpi = 0;
1381 	port->node_base.nlp_DID = 0xffffff;
1382 	port->node_base.nlp_list_next = NULL;
1383 	port->node_base.nlp_list_prev = NULL;
1384 	port->node_base.nlp_active = 1;
1385 	port->node_base.nlp_base = 1;
1386 	port->node_count = 0;
1387 
1388 	if (!(port->flag & EMLXS_PORT_ENABLE)) {
1389 		uint8_t dummy_wwn[8] =
1390 		    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
1391 
1392 		bcopy((caddr_t)dummy_wwn, (caddr_t)&port->wwnn,
1393 		    sizeof (NAME_TYPE));
1394 		bcopy((caddr_t)dummy_wwn, (caddr_t)&port->wwpn,
1395 		    sizeof (NAME_TYPE));
1396 	}
1397 
1398 	if (!(port->flag & EMLXS_PORT_CONFIG)) {
1399 		(void) strncpy((caddr_t)port->snn, (caddr_t)hba->snn, 256);
1400 		(void) strncpy((caddr_t)port->spn, (caddr_t)hba->spn, 256);
1401 	}
1402 
1403 	bcopy((caddr_t)&hba->sparam, (caddr_t)&port->sparam,
1404 	    sizeof (SERV_PARM));
1405 	bcopy((caddr_t)&port->wwnn, (caddr_t)&port->sparam.nodeName,
1406 	    sizeof (NAME_TYPE));
1407 	bcopy((caddr_t)&port->wwpn, (caddr_t)&port->sparam.portName,
1408 	    sizeof (NAME_TYPE));
1409 
1410 	return;
1411 
1412 } /* emlxs_port_init() */
1413 
1414 
1415 
1416 /*
1417  * emlxs_bind_port
1418  *
1419  * Arguments:
1420  *
1421  * dip: the dev_info pointer for the ddiinst
1422  * port_info: pointer to info handed back to the transport
1423  * bind_info: pointer to info from the transport
1424  *
1425  * Return values: a port handle for this port, NULL for failure
1426  *
1427  */
1428 static opaque_t
1429 emlxs_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info,
1430     fc_fca_bind_info_t *bind_info)
1431 {
1432 	emlxs_hba_t *hba;
1433 	emlxs_port_t *port;
1434 	emlxs_port_t *vport;
1435 	int ddiinst;
1436 	emlxs_vpd_t *vpd;
1437 	emlxs_config_t *cfg;
1438 	char *dptr;
1439 	char buffer[16];
1440 	uint32_t length;
1441 	uint32_t len;
1442 	char topology[32];
1443 	char linkspeed[32];
1444 
1445 	ddiinst = ddi_get_instance(dip);
1446 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
1447 	port = &PPORT;
1448 
1449 	ddiinst = hba->ddiinst;
1450 	vpd = &VPD;
1451 	cfg = &CFG;
1452 
1453 	mutex_enter(&EMLXS_PORT_LOCK);
1454 
1455 	if (bind_info->port_num > 0) {
1456 #if (EMLXS_MODREV >= EMLXS_MODREV5)
1457 		if (!(hba->flag & FC_NPIV_ENABLED) ||
1458 		    !(bind_info->port_npiv) ||
1459 		    (bind_info->port_num > hba->vpi_max))
1460 #elif (EMLXS_MODREV >= EMLXS_MODREV3)
1461 		if (!(hba->flag & FC_NPIV_ENABLED) ||
1462 		    (bind_info->port_num > hba->vpi_high))
1463 #endif
1464 		{
1465 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1466 			    "emlxs_port_bind: Port %d not supported.",
1467 			    bind_info->port_num);
1468 
1469 			mutex_exit(&EMLXS_PORT_LOCK);
1470 
1471 			port_info->pi_error = FC_OUTOFBOUNDS;
1472 			return (NULL);
1473 		}
1474 	}
1475 
1476 	/* Get true port pointer */
1477 	port = &VPORT(bind_info->port_num);
1478 
1479 	if (port->tgt_mode) {
1480 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1481 		    "emlxs_port_bind: Port %d is in target mode.",
1482 		    bind_info->port_num);
1483 
1484 		mutex_exit(&EMLXS_PORT_LOCK);
1485 
1486 		port_info->pi_error = FC_OUTOFBOUNDS;
1487 		return (NULL);
1488 	}
1489 
1490 	if (!port->ini_mode) {
1491 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1492 		    "emlxs_port_bind: Port %d is not in initiator mode.",
1493 		    bind_info->port_num);
1494 
1495 		mutex_exit(&EMLXS_PORT_LOCK);
1496 
1497 		port_info->pi_error = FC_OUTOFBOUNDS;
1498 		return (NULL);
1499 	}
1500 
1501 	/* Make sure the port is not already bound to the transport */
1502 	if (port->flag & EMLXS_PORT_BOUND) {
1503 
1504 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1505 		    "emlxs_port_bind: Port %d already bound. flag=%x",
1506 		    bind_info->port_num, port->flag);
1507 
1508 		mutex_exit(&EMLXS_PORT_LOCK);
1509 
1510 		port_info->pi_error = FC_ALREADY;
1511 		return (NULL);
1512 	}
1513 
1514 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1515 	    "fca_bind_port: Port %d: port_info=%p bind_info=%p",
1516 	    bind_info->port_num, port_info, bind_info);
1517 
1518 #if (EMLXS_MODREV >= EMLXS_MODREV5)
1519 	if (bind_info->port_npiv) {
1520 		bcopy((caddr_t)&bind_info->port_nwwn, (caddr_t)&port->wwnn,
1521 		    sizeof (NAME_TYPE));
1522 		bcopy((caddr_t)&bind_info->port_pwwn, (caddr_t)&port->wwpn,
1523 		    sizeof (NAME_TYPE));
1524 		if (port->snn[0] == 0) {
1525 			(void) strncpy((caddr_t)port->snn, (caddr_t)hba->snn,
1526 			    256);
1527 		}
1528 
1529 		if (port->spn[0] == 0) {
1530 			(void) sprintf((caddr_t)port->spn, "%s VPort-%d",
1531 			    (caddr_t)hba->spn, port->vpi);
1532 		}
1533 		port->flag |= (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE);
1534 	}
1535 #endif /* >= EMLXS_MODREV5 */
1536 
1537 	/*
1538 	 * Restricted login should apply both physical and
1539 	 * virtual ports.
1540 	 */
1541 	if (cfg[CFG_VPORT_RESTRICTED].current) {
1542 		port->flag |= EMLXS_PORT_RESTRICTED;
1543 	}
1544 
1545 	/* Perform generic port initialization */
1546 	emlxs_port_init(port);
1547 
1548 	/* Perform SFS specific initialization */
1549 	port->ulp_handle	= bind_info->port_handle;
1550 	port->ulp_statec_cb	= bind_info->port_statec_cb;
1551 	port->ulp_unsol_cb	= bind_info->port_unsol_cb;
1552 	port->ub_count		= EMLXS_UB_TOKEN_OFFSET;
1553 	port->ub_pool		= NULL;
1554 
1555 	/* Update the port info structure */
1556 
1557 	/* Set the topology and state */
1558 	if ((hba->state < FC_LINK_UP) ||
1559 	    ((port->vpi > 0) && (!(port->flag & EMLXS_PORT_ENABLE) ||
1560 	    !(hba->flag & FC_NPIV_SUPPORTED)))) {
1561 		port_info->pi_port_state = FC_STATE_OFFLINE;
1562 		port_info->pi_topology = FC_TOP_UNKNOWN;
1563 	}
1564 #ifdef MENLO_SUPPORT
1565 	else if (hba->flag & FC_MENLO_MODE) {
1566 		port_info->pi_port_state = FC_STATE_OFFLINE;
1567 		port_info->pi_topology = FC_TOP_UNKNOWN;
1568 	}
1569 #endif /* MENLO_SUPPORT */
1570 	else {
1571 		/* Check for loop topology */
1572 		if (hba->topology == TOPOLOGY_LOOP) {
1573 			port_info->pi_port_state = FC_STATE_LOOP;
1574 			(void) strcpy(topology, ", loop");
1575 
1576 			if (hba->flag & FC_FABRIC_ATTACHED) {
1577 				port_info->pi_topology = FC_TOP_PUBLIC_LOOP;
1578 			} else {
1579 				port_info->pi_topology = FC_TOP_PRIVATE_LOOP;
1580 			}
1581 		} else {
1582 			port_info->pi_topology = FC_TOP_FABRIC;
1583 			port_info->pi_port_state = FC_STATE_ONLINE;
1584 			(void) strcpy(topology, ", fabric");
1585 		}
1586 
1587 		/* Set the link speed */
1588 		switch (hba->linkspeed) {
1589 		case 0:
1590 			(void) strcpy(linkspeed, "Gb");
1591 			port_info->pi_port_state |= FC_STATE_1GBIT_SPEED;
1592 			break;
1593 
1594 		case LA_1GHZ_LINK:
1595 			(void) strcpy(linkspeed, "1Gb");
1596 			port_info->pi_port_state |= FC_STATE_1GBIT_SPEED;
1597 			break;
1598 		case LA_2GHZ_LINK:
1599 			(void) strcpy(linkspeed, "2Gb");
1600 			port_info->pi_port_state |= FC_STATE_2GBIT_SPEED;
1601 			break;
1602 		case LA_4GHZ_LINK:
1603 			(void) strcpy(linkspeed, "4Gb");
1604 			port_info->pi_port_state |= FC_STATE_4GBIT_SPEED;
1605 			break;
1606 		case LA_8GHZ_LINK:
1607 			(void) strcpy(linkspeed, "8Gb");
1608 			port_info->pi_port_state |= FC_STATE_8GBIT_SPEED;
1609 			break;
1610 		case LA_10GHZ_LINK:
1611 			(void) strcpy(linkspeed, "10Gb");
1612 			port_info->pi_port_state |= FC_STATE_10GBIT_SPEED;
1613 			break;
1614 		default:
1615 			(void) sprintf(linkspeed, "unknown(0x%x)",
1616 			    hba->linkspeed);
1617 			break;
1618 		}
1619 
1620 		/* Adjusting port context for link up messages */
1621 		vport = port;
1622 		port = &PPORT;
1623 		if (vport->vpi == 0) {
1624 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, "%s%s",
1625 			    linkspeed, topology);
1626 		} else if (!(hba->flag & FC_NPIV_LINKUP)) {
1627 			hba->flag |= FC_NPIV_LINKUP;
1628 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_npiv_link_up_msg,
1629 			    "%s%s", linkspeed, topology);
1630 		}
1631 		port = vport;
1632 
1633 	}
1634 
1635 	/* Save initial state */
1636 	port->ulp_statec = port_info->pi_port_state;
1637 
1638 	/*
1639 	 * The transport needs a copy of the common service parameters
1640 	 * for this port. The transport can get any updates through
1641 	 * the getcap entry point.
1642 	 */
1643 	bcopy((void *) &port->sparam,
1644 	    (void *) &port_info->pi_login_params.common_service,
1645 	    sizeof (SERV_PARM));
1646 
1647 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
1648 	/* Swap the service parameters for ULP */
1649 	emlxs_swap_service_params((SERV_PARM *)&port_info->pi_login_params.
1650 	    common_service);
1651 #endif /* EMLXS_MODREV2X */
1652 
1653 	port_info->pi_login_params.common_service.btob_credit = 0xffff;
1654 
1655 	bcopy((void *) &port->wwnn,
1656 	    (void *) &port_info->pi_login_params.node_ww_name,
1657 	    sizeof (NAME_TYPE));
1658 
1659 	bcopy((void *) &port->wwpn,
1660 	    (void *) &port_info->pi_login_params.nport_ww_name,
1661 	    sizeof (NAME_TYPE));
1662 
1663 	/*
1664 	 * We need to turn off CLASS2 support.
1665 	 * Otherwise, FC transport will use CLASS2 as default class
1666 	 * and never try with CLASS3.
1667 	 */
1668 #if (EMLXS_MODREV >= EMLXS_MODREV3)
1669 #if (EMLXS_MODREVX >= EMLXS_MODREV3X)
1670 	if ((port_info->pi_login_params.class_1.class_opt) & 0x0080) {
1671 		port_info->pi_login_params.class_1.class_opt &= ~0x0080;
1672 	}
1673 
1674 	if ((port_info->pi_login_params.class_2.class_opt) & 0x0080) {
1675 		port_info->pi_login_params.class_2.class_opt &= ~0x0080;
1676 	}
1677 #else	/* EMLXS_SPARC or EMLXS_MODREV2X */
1678 	if ((port_info->pi_login_params.class_1.class_opt) & 0x8000) {
1679 		port_info->pi_login_params.class_1.class_opt &= ~0x8000;
1680 	}
1681 
1682 	if ((port_info->pi_login_params.class_2.class_opt) & 0x8000) {
1683 		port_info->pi_login_params.class_2.class_opt &= ~0x8000;
1684 	}
1685 #endif	/* >= EMLXS_MODREV3X */
1686 #endif	/* >= EMLXS_MODREV3 */
1687 
1688 
1689 #if (EMLXS_MODREV <= EMLXS_MODREV2)
1690 	if ((port_info->pi_login_params.class_1.data[0]) & 0x80) {
1691 		port_info->pi_login_params.class_1.data[0] &= ~0x80;
1692 	}
1693 
1694 	if ((port_info->pi_login_params.class_2.data[0]) & 0x80) {
1695 		port_info->pi_login_params.class_2.data[0] &= ~0x80;
1696 	}
1697 #endif	/* <= EMLXS_MODREV2 */
1698 
1699 	/* Additional parameters */
1700 	port_info->pi_s_id.port_id = port->did;
1701 	port_info->pi_s_id.priv_lilp_posit = 0;
1702 	port_info->pi_hard_addr.hard_addr = cfg[CFG_ASSIGN_ALPA].current;
1703 
1704 	/* Initialize the RNID parameters */
1705 	bzero(&port_info->pi_rnid_params, sizeof (port_info->pi_rnid_params));
1706 
1707 	(void) sprintf((char *)port_info->pi_rnid_params.params.global_id,
1708 	    "%01x%01x%02x%02x%02x%02x%02x%02x%02x", hba->wwpn.nameType,
1709 	    hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb, hba->wwpn.IEEE[0],
1710 	    hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], hba->wwpn.IEEE[3],
1711 	    hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
1712 
1713 	port_info->pi_rnid_params.params.unit_type  = RNID_HBA;
1714 	port_info->pi_rnid_params.params.port_id    = port->did;
1715 	port_info->pi_rnid_params.params.ip_version = RNID_IPV4;
1716 
1717 	/* Initialize the port attributes */
1718 	bzero(&port_info->pi_attrs, sizeof (port_info->pi_attrs));
1719 
1720 	(void) strcpy(port_info->pi_attrs.manufacturer, "Emulex");
1721 
1722 	port_info->pi_rnid_params.status = FC_SUCCESS;
1723 
1724 	(void) strcpy(port_info->pi_attrs.serial_number, vpd->serial_num);
1725 
1726 	(void) sprintf(port_info->pi_attrs.firmware_version, "%s (%s)",
1727 	    vpd->fw_version, vpd->fw_label);
1728 
1729 #ifdef EMLXS_I386
1730 	(void) sprintf(port_info->pi_attrs.option_rom_version,
1731 	    "Boot:%s", vpd->boot_version);
1732 #else	/* EMLXS_SPARC */
1733 	(void) sprintf(port_info->pi_attrs.option_rom_version,
1734 	    "Boot:%s Fcode:%s", vpd->boot_version, vpd->fcode_version);
1735 #endif	/* EMLXS_I386 */
1736 
1737 
1738 	(void) sprintf(port_info->pi_attrs.driver_version, "%s (%s)",
1739 	    emlxs_version, emlxs_revision);
1740 
1741 	(void) strcpy(port_info->pi_attrs.driver_name, DRIVER_NAME);
1742 
1743 	port_info->pi_attrs.vendor_specific_id =
1744 	    ((hba->model_info.device_id << 16) | PCI_VENDOR_ID_EMULEX);
1745 
1746 	port_info->pi_attrs.supported_cos = LE_SWAP32(FC_NS_CLASS3);
1747 
1748 	port_info->pi_attrs.max_frame_size = FF_FRAME_SIZE;
1749 
1750 #if (EMLXS_MODREV >= EMLXS_MODREV5)
1751 
1752 	port_info->pi_rnid_params.params.num_attached = 0;
1753 
1754 	/*
1755 	 * Copy the serial number string (right most 16 chars) into the right
1756 	 * justified local buffer
1757 	 */
1758 	bzero(buffer, sizeof (buffer));
1759 	length = strlen(vpd->serial_num);
1760 	len = (length > 16) ? 16 : length;
1761 	bcopy(&vpd->serial_num[(length - len)],
1762 	    &buffer[(sizeof (buffer) - len)], len);
1763 
1764 	port_info->pi_attrs.hba_fru_details.port_index = vpd->port_index;
1765 
1766 #endif /* >= EMLXS_MODREV5 */
1767 
1768 #if ((EMLXS_MODREV == EMLXS_MODREV3) || (EMLX_MODREV == EMLXS_MODREV4))
1769 
1770 	port_info->pi_rnid_params.params.num_attached = 0;
1771 
1772 	if (hba->flag & FC_NPIV_ENABLED) {
1773 		uint8_t		byte;
1774 		uint8_t		*wwpn;
1775 		uint32_t	i;
1776 		uint32_t	j;
1777 
1778 		/* Copy the WWPN as a string into the local buffer */
1779 		wwpn = (uint8_t *)&hba->wwpn;
1780 		for (i = 0; i < 16; i++) {
1781 			byte = *wwpn++;
1782 			j = ((byte & 0xf0) >> 4);
1783 			if (j <= 9) {
1784 				buffer[i] =
1785 				    (char)((uint8_t)'0' + (uint8_t)j);
1786 			} else {
1787 				buffer[i] =
1788 				    (char)((uint8_t)'A' + (uint8_t)(j -
1789 				    10));
1790 			}
1791 
1792 			i++;
1793 			j = (byte & 0xf);
1794 			if (j <= 9) {
1795 				buffer[i] =
1796 				    (char)((uint8_t)'0' + (uint8_t)j);
1797 			} else {
1798 				buffer[i] =
1799 				    (char)((uint8_t)'A' + (uint8_t)(j -
1800 				    10));
1801 			}
1802 			}
1803 
1804 		port_info->pi_attrs.hba_fru_details.port_index = port->vpi;
1805 	} else {
1806 		/* Copy the serial number string (right most 16 chars) */
1807 		/* into the right justified local buffer */
1808 		bzero(buffer, sizeof (buffer));
1809 		length = strlen(vpd->serial_num);
1810 		len = (length > 16) ? 16 : length;
1811 		bcopy(&vpd->serial_num[(length - len)],
1812 		    &buffer[(sizeof (buffer) - len)], len);
1813 
1814 		port_info->pi_attrs.hba_fru_details.port_index =
1815 		    vpd->port_index;
1816 	}
1817 
1818 #endif /* == EMLXS_MODREV3 || EMLXS_MODREV4 */
1819 
1820 #if (EMLXS_MODREV >= EMLXS_MODREV3)
1821 
1822 	dptr = (char *)&port_info->pi_attrs.hba_fru_details.high;
1823 	dptr[0] = buffer[0];
1824 	dptr[1] = buffer[1];
1825 	dptr[2] = buffer[2];
1826 	dptr[3] = buffer[3];
1827 	dptr[4] = buffer[4];
1828 	dptr[5] = buffer[5];
1829 	dptr[6] = buffer[6];
1830 	dptr[7] = buffer[7];
1831 	port_info->pi_attrs.hba_fru_details.high =
1832 	    LE_SWAP64(port_info->pi_attrs.hba_fru_details.high);
1833 
1834 	dptr = (char *)&port_info->pi_attrs.hba_fru_details.low;
1835 	dptr[0] = buffer[8];
1836 	dptr[1] = buffer[9];
1837 	dptr[2] = buffer[10];
1838 	dptr[3] = buffer[11];
1839 	dptr[4] = buffer[12];
1840 	dptr[5] = buffer[13];
1841 	dptr[6] = buffer[14];
1842 	dptr[7] = buffer[15];
1843 	port_info->pi_attrs.hba_fru_details.low =
1844 	    LE_SWAP64(port_info->pi_attrs.hba_fru_details.low);
1845 
1846 #endif /* >= EMLXS_MODREV3 */
1847 
1848 #if (EMLXS_MODREV >= EMLXS_MODREV4)
1849 	(void) strncpy((caddr_t)port_info->pi_attrs.sym_node_name,
1850 	    (caddr_t)port->snn, FCHBA_SYMB_NAME_LEN);
1851 	(void) strncpy((caddr_t)port_info->pi_attrs.sym_port_name,
1852 	    (caddr_t)port->spn, FCHBA_SYMB_NAME_LEN);
1853 #endif	/* >= EMLXS_MODREV4 */
1854 
1855 	(void) sprintf(port_info->pi_attrs.hardware_version, "%x", vpd->biuRev);
1856 
1857 	/* Set the hba speed limit */
1858 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
1859 		port_info->pi_attrs.supported_speed |=
1860 		    FC_HBA_PORTSPEED_10GBIT;
1861 	}
1862 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
1863 		port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_8GBIT;
1864 	}
1865 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
1866 		port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_4GBIT;
1867 	}
1868 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
1869 		port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_2GBIT;
1870 	}
1871 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
1872 		port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_1GBIT;
1873 	}
1874 
1875 	/* Set the hba model info */
1876 	(void) strcpy(port_info->pi_attrs.model, hba->model_info.model);
1877 	(void) strcpy(port_info->pi_attrs.model_description,
1878 	    hba->model_info.model_desc);
1879 
1880 
1881 	/* Log information */
1882 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1883 	    "Bind info: port_num           = %d", bind_info->port_num);
1884 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1885 	    "Bind info: port_handle        = %p", bind_info->port_handle);
1886 
1887 #if (EMLXS_MODREV >= EMLXS_MODREV5)
1888 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1889 	    "Bind info: port_npiv          = %d", bind_info->port_npiv);
1890 #endif /* >= EMLXS_MODREV5 */
1891 
1892 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1893 	    "Port info: pi_topology        = %x", port_info->pi_topology);
1894 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1895 	    "Port info: pi_error           = %x", port_info->pi_error);
1896 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1897 	    "Port info: pi_port_state      = %x", port_info->pi_port_state);
1898 
1899 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1900 	    "Port info: port_id            = %x", port_info->pi_s_id.port_id);
1901 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1902 	    "Port info: priv_lilp_posit    = %x",
1903 	    port_info->pi_s_id.priv_lilp_posit);
1904 
1905 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1906 	    "Port info: hard_addr          = %x",
1907 	    port_info->pi_hard_addr.hard_addr);
1908 
1909 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1910 	    "Port info: rnid.status        = %x",
1911 	    port_info->pi_rnid_params.status);
1912 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1913 	    "Port info: rnid.global_id     = %16s",
1914 	    port_info->pi_rnid_params.params.global_id);
1915 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1916 	    "Port info: rnid.unit_type     = %x",
1917 	    port_info->pi_rnid_params.params.unit_type);
1918 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1919 	    "Port info: rnid.port_id       = %x",
1920 	    port_info->pi_rnid_params.params.port_id);
1921 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1922 	    "Port info: rnid.num_attached  = %x",
1923 	    port_info->pi_rnid_params.params.num_attached);
1924 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1925 	    "Port info: rnid.ip_version    = %x",
1926 	    port_info->pi_rnid_params.params.ip_version);
1927 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1928 	    "Port info: rnid.udp_port      = %x",
1929 	    port_info->pi_rnid_params.params.udp_port);
1930 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1931 	    "Port info: rnid.ip_addr       = %16s",
1932 	    port_info->pi_rnid_params.params.ip_addr);
1933 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1934 	    "Port info: rnid.spec_id_resv  = %x",
1935 	    port_info->pi_rnid_params.params.specific_id_resv);
1936 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1937 	    "Port info: rnid.topo_flags    = %x",
1938 	    port_info->pi_rnid_params.params.topo_flags);
1939 
1940 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1941 	    "Port info: manufacturer       = %s",
1942 	    port_info->pi_attrs.manufacturer);
1943 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1944 	    "Port info: serial_num         = %s",
1945 	    port_info->pi_attrs.serial_number);
1946 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1947 	    "Port info: model              = %s", port_info->pi_attrs.model);
1948 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1949 	    "Port info: model_description  = %s",
1950 	    port_info->pi_attrs.model_description);
1951 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1952 	    "Port info: hardware_version   = %s",
1953 	    port_info->pi_attrs.hardware_version);
1954 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1955 	    "Port info: driver_version     = %s",
1956 	    port_info->pi_attrs.driver_version);
1957 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1958 	    "Port info: option_rom_version = %s",
1959 	    port_info->pi_attrs.option_rom_version);
1960 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1961 	    "Port info: firmware_version   = %s",
1962 	    port_info->pi_attrs.firmware_version);
1963 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1964 	    "Port info: driver_name        = %s",
1965 	    port_info->pi_attrs.driver_name);
1966 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1967 	    "Port info: vendor_specific_id = %x",
1968 	    port_info->pi_attrs.vendor_specific_id);
1969 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1970 	    "Port info: supported_cos      = %x",
1971 	    port_info->pi_attrs.supported_cos);
1972 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1973 	    "Port info: supported_speed    = %x",
1974 	    port_info->pi_attrs.supported_speed);
1975 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1976 	    "Port info: max_frame_size     = %x",
1977 	    port_info->pi_attrs.max_frame_size);
1978 
1979 #if (EMLXS_MODREV >= EMLXS_MODREV3)
1980 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1981 	    "Port info: fru_port_index     = %x",
1982 	    port_info->pi_attrs.hba_fru_details.port_index);
1983 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1984 	    "Port info: fru_high           = %llx",
1985 	    port_info->pi_attrs.hba_fru_details.high);
1986 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1987 	    "Port info: fru_low            = %llx",
1988 	    port_info->pi_attrs.hba_fru_details.low);
1989 #endif	/* >= EMLXS_MODREV3 */
1990 
1991 #if (EMLXS_MODREV >= EMLXS_MODREV4)
1992 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1993 	    "Port info: sym_node_name      = %s",
1994 	    port_info->pi_attrs.sym_node_name);
1995 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1996 	    "Port info: sym_port_name      = %s",
1997 	    port_info->pi_attrs.sym_port_name);
1998 #endif	/* >= EMLXS_MODREV4 */
1999 
2000 	/* Set the bound flag */
2001 	port->flag |= EMLXS_PORT_BOUND;
2002 	hba->num_of_ports++;
2003 
2004 	mutex_exit(&EMLXS_PORT_LOCK);
2005 
2006 	return ((opaque_t)port);
2007 
2008 } /* emlxs_bind_port() */
2009 
2010 
2011 static void
2012 emlxs_unbind_port(opaque_t fca_port_handle)
2013 {
2014 	emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2015 	emlxs_hba_t *hba = HBA;
2016 
2017 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2018 	    "fca_unbind_port: port=%p", port);
2019 
2020 	/* Destroy & flush all port nodes, if they exist */
2021 	if (port->node_count) {
2022 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2023 			(void) emlxs_sli4_unreg_all_rpi_by_port(port);
2024 		} else {
2025 			(void) emlxs_mb_unreg_rpi(port, 0xffff, 0, 0, 0);
2026 		}
2027 	}
2028 
2029 #if (EMLXS_MODREV >= EMLXS_MODREV5)
2030 	if ((hba->flag & FC_NPIV_ENABLED) &&
2031 	    (port->flag & (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE))) {
2032 		(void) emlxs_mb_unreg_vpi(port);
2033 	}
2034 #endif
2035 
2036 	mutex_enter(&EMLXS_PORT_LOCK);
2037 
2038 	if (!(port->flag & EMLXS_PORT_BOUND)) {
2039 		mutex_exit(&EMLXS_PORT_LOCK);
2040 		return;
2041 	}
2042 
2043 	port->flag &= ~EMLXS_PORT_BOUND;
2044 	hba->num_of_ports--;
2045 
2046 	port->ulp_handle = 0;
2047 	port->ulp_statec = FC_STATE_OFFLINE;
2048 	port->ulp_statec_cb = NULL;
2049 	port->ulp_unsol_cb = NULL;
2050 
2051 	mutex_exit(&EMLXS_PORT_LOCK);
2052 
2053 	return;
2054 
2055 } /* emlxs_unbind_port() */
2056 
2057 
2058 /*ARGSUSED*/
2059 extern int
2060 emlxs_pkt_init(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep)
2061 {
2062 	emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2063 	emlxs_hba_t  *hba = HBA;
2064 	emlxs_buf_t  *sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
2065 
2066 	if (!sbp) {
2067 		return (FC_FAILURE);
2068 	}
2069 	bzero((void *)sbp, sizeof (emlxs_buf_t));
2070 
2071 	mutex_init(&sbp->mtx, NULL, MUTEX_DRIVER, (void *)hba->intr_arg);
2072 	sbp->pkt_flags =
2073 	    PACKET_VALID | PACKET_ULP_OWNED;
2074 	sbp->port = port;
2075 	sbp->pkt = pkt;
2076 	sbp->iocbq.sbp = sbp;
2077 
2078 	return (FC_SUCCESS);
2079 
2080 } /* emlxs_pkt_init() */
2081 
2082 
2083 
2084 static void
2085 emlxs_initialize_pkt(emlxs_port_t *port, emlxs_buf_t *sbp)
2086 {
2087 	emlxs_hba_t *hba = HBA;
2088 	emlxs_config_t *cfg = &CFG;
2089 	fc_packet_t *pkt = PRIV2PKT(sbp);
2090 	uint32_t *iptr;
2091 
2092 	mutex_enter(&sbp->mtx);
2093 
2094 	/* Reinitialize */
2095 	sbp->pkt   = pkt;
2096 	sbp->port  = port;
2097 	sbp->bmp   = NULL;
2098 	sbp->pkt_flags &= (PACKET_VALID | PACKET_ALLOCATED);
2099 	sbp->iotag = 0;
2100 	sbp->ticks = 0;
2101 	sbp->abort_attempts = 0;
2102 	sbp->fpkt  = NULL;
2103 	sbp->flush_count = 0;
2104 	sbp->next  = NULL;
2105 
2106 	if (!port->tgt_mode) {
2107 		sbp->node  = NULL;
2108 		sbp->did   = 0;
2109 		sbp->lun   = 0;
2110 		sbp->class = 0;
2111 		sbp->class = 0;
2112 		sbp->channel  = NULL;
2113 	}
2114 
2115 	bzero((void *)&sbp->iocbq, sizeof (IOCBQ));
2116 	sbp->iocbq.sbp = sbp;
2117 
2118 	if ((pkt->pkt_tran_flags & FC_TRAN_NO_INTR) || !pkt->pkt_comp ||
2119 	    ddi_in_panic()) {
2120 		sbp->pkt_flags |= PACKET_POLLED;
2121 	}
2122 
2123 	/* Prepare the fc packet */
2124 	pkt->pkt_state = FC_PKT_SUCCESS;
2125 	pkt->pkt_reason = 0;
2126 	pkt->pkt_action = 0;
2127 	pkt->pkt_expln = 0;
2128 	pkt->pkt_data_resid = 0;
2129 	pkt->pkt_resp_resid = 0;
2130 
2131 	/* Make sure all pkt's have a proper timeout */
2132 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
2133 		/* This disables all IOCB on chip timeouts */
2134 		pkt->pkt_timeout = 0x80000000;
2135 	} else if (pkt->pkt_timeout == 0 || pkt->pkt_timeout == 0xffffffff) {
2136 		pkt->pkt_timeout = 60;
2137 	}
2138 
2139 	/* Clear the response buffer */
2140 	if (pkt->pkt_rsplen) {
2141 		/* Check for FCP commands */
2142 		if ((pkt->pkt_tran_type == FC_PKT_FCP_READ) ||
2143 		    (pkt->pkt_tran_type == FC_PKT_FCP_WRITE)) {
2144 			iptr = (uint32_t *)pkt->pkt_resp;
2145 			iptr[2] = 0;
2146 			iptr[3] = 0;
2147 		} else {
2148 		bzero(pkt->pkt_resp, pkt->pkt_rsplen);
2149 	}
2150 	}
2151 
2152 	mutex_exit(&sbp->mtx);
2153 
2154 	return;
2155 
2156 } /* emlxs_initialize_pkt() */
2157 
2158 
2159 
2160 /*
2161  * We may not need this routine
2162  */
2163 /*ARGSUSED*/
2164 extern int
2165 emlxs_pkt_uninit(opaque_t fca_port_handle, fc_packet_t *pkt)
2166 {
2167 	emlxs_buf_t  *sbp = PKT2PRIV(pkt);
2168 
2169 	if (!sbp) {
2170 		return (FC_FAILURE);
2171 	}
2172 
2173 	if (!(sbp->pkt_flags & PACKET_VALID)) {
2174 		return (FC_FAILURE);
2175 	}
2176 	sbp->pkt_flags &= ~PACKET_VALID;
2177 	mutex_destroy(&sbp->mtx);
2178 
2179 	return (FC_SUCCESS);
2180 
2181 } /* emlxs_pkt_uninit() */
2182 
2183 
2184 static int
2185 emlxs_get_cap(opaque_t fca_port_handle, char *cap, void *ptr)
2186 {
2187 	emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2188 	emlxs_hba_t  *hba = HBA;
2189 	int32_t rval;
2190 
2191 	if (!(port->flag & EMLXS_PORT_BOUND)) {
2192 		return (FC_CAP_ERROR);
2193 	}
2194 
2195 	if (strcmp(cap, FC_NODE_WWN) == 0) {
2196 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2197 		    "fca_get_cap: FC_NODE_WWN");
2198 
2199 		bcopy((void *)&hba->wwnn, (void *)ptr, sizeof (NAME_TYPE));
2200 		rval = FC_CAP_FOUND;
2201 
2202 	} else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) {
2203 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2204 		    "fca_get_cap: FC_LOGIN_PARAMS");
2205 
2206 		/*
2207 		 * We need to turn off CLASS2 support.
2208 		 * Otherwise, FC transport will use CLASS2 as default class
2209 		 * and never try with CLASS3.
2210 		 */
2211 		hba->sparam.cls2.classValid = 0;
2212 
2213 		bcopy((void *)&hba->sparam, (void *)ptr, sizeof (SERV_PARM));
2214 
2215 		rval = FC_CAP_FOUND;
2216 
2217 	} else if (strcmp(cap, FC_CAP_UNSOL_BUF) == 0) {
2218 		int32_t		*num_bufs;
2219 		emlxs_config_t	*cfg = &CFG;
2220 
2221 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2222 		    "fca_get_cap: FC_CAP_UNSOL_BUF (%d)",
2223 		    cfg[CFG_UB_BUFS].current);
2224 
2225 		num_bufs = (int32_t *)ptr;
2226 
2227 		/* We multiply by MAX_VPORTS because ULP uses a */
2228 		/* formula to calculate ub bufs from this */
2229 		*num_bufs = (cfg[CFG_UB_BUFS].current * MAX_VPORTS);
2230 
2231 		rval = FC_CAP_FOUND;
2232 
2233 	} else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) {
2234 		int32_t		*size;
2235 
2236 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2237 		    "fca_get_cap: FC_CAP_PAYLOAD_SIZE");
2238 
2239 		size = (int32_t *)ptr;
2240 		*size = -1;
2241 		rval = FC_CAP_FOUND;
2242 
2243 	} else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) {
2244 		fc_reset_action_t *action;
2245 
2246 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2247 		    "fca_get_cap: FC_CAP_POST_RESET_BEHAVIOR");
2248 
2249 		action = (fc_reset_action_t *)ptr;
2250 		*action = FC_RESET_RETURN_ALL;
2251 		rval = FC_CAP_FOUND;
2252 
2253 	} else if (strcmp(cap, FC_CAP_NOSTREAM_ON_UNALIGN_BUF) == 0) {
2254 		fc_dma_behavior_t *behavior;
2255 
2256 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2257 		    "fca_get_cap: FC_CAP_NOSTREAM_ON_UNALIGN_BUF");
2258 
2259 		behavior = (fc_dma_behavior_t *)ptr;
2260 		*behavior = FC_ALLOW_STREAMING;
2261 		rval = FC_CAP_FOUND;
2262 
2263 	} else if (strcmp(cap, FC_CAP_FCP_DMA) == 0) {
2264 		fc_fcp_dma_t   *fcp_dma;
2265 
2266 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2267 		    "fca_get_cap: FC_CAP_FCP_DMA");
2268 
2269 		fcp_dma = (fc_fcp_dma_t *)ptr;
2270 		*fcp_dma = FC_DVMA_SPACE;
2271 		rval = FC_CAP_FOUND;
2272 
2273 	} else {
2274 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2275 		    "fca_get_cap: Unknown capability. [%s]", cap);
2276 
2277 		rval = FC_CAP_ERROR;
2278 
2279 	}
2280 
2281 	return (rval);
2282 
2283 } /* emlxs_get_cap() */
2284 
2285 
2286 
2287 static int
2288 emlxs_set_cap(opaque_t fca_port_handle, char *cap, void *ptr)
2289 {
2290 	emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2291 
2292 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2293 	    "fca_set_cap: cap=[%s] arg=%p", cap, ptr);
2294 
2295 	return (FC_CAP_ERROR);
2296 
2297 } /* emlxs_set_cap() */
2298 
2299 
2300 static opaque_t
2301 emlxs_get_device(opaque_t fca_port_handle, fc_portid_t d_id)
2302 {
2303 	emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2304 
2305 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2306 	    "fca_get_device: did=%x", d_id.port_id);
2307 
2308 	return (NULL);
2309 
2310 } /* emlxs_get_device() */
2311 
2312 
2313 static int32_t
2314 emlxs_notify(opaque_t fca_port_handle, uint32_t cmd)
2315 {
2316 	emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2317 
2318 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, "fca_notify: cmd=%x",
2319 	    cmd);
2320 
2321 	return (FC_SUCCESS);
2322 
2323 } /* emlxs_notify */
2324 
2325 
2326 
2327 static int
2328 emlxs_get_map(opaque_t fca_port_handle, fc_lilpmap_t *mapbuf)
2329 {
2330 	emlxs_port_t	*port = (emlxs_port_t *)fca_port_handle;
2331 	emlxs_hba_t	*hba = HBA;
2332 	uint32_t	lilp_length;
2333 
2334 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2335 	    "fca_get_map: mapbuf=%p length=%d (%X,%X,%X,%X)", mapbuf,
2336 	    port->alpa_map[0], port->alpa_map[1], port->alpa_map[2],
2337 	    port->alpa_map[3], port->alpa_map[4]);
2338 
2339 	if (!(port->flag & EMLXS_PORT_BOUND)) {
2340 		return (FC_NOMAP);
2341 	}
2342 
2343 	if (hba->topology != TOPOLOGY_LOOP) {
2344 		return (FC_NOMAP);
2345 	}
2346 
2347 	/* Check if alpa map is available */
2348 	if (port->alpa_map[0] != 0) {
2349 		mapbuf->lilp_magic  = MAGIC_LILP;
2350 	} else {	/* No LILP map available */
2351 
2352 		/* Set lilp_magic to MAGIC_LISA and this will */
2353 		/* trigger an ALPA scan in ULP */
2354 		mapbuf->lilp_magic  = MAGIC_LISA;
2355 	}
2356 
2357 	mapbuf->lilp_myalpa = port->did;
2358 
2359 	/* The first byte of the alpa_map is the lilp map length */
2360 	/* Add one to include the lilp length byte itself */
2361 	lilp_length = (uint32_t)port->alpa_map[0] + 1;
2362 
2363 	/* Make sure the max transfer is 128 bytes */
2364 	if (lilp_length > 128) {
2365 		lilp_length = 128;
2366 	}
2367 
2368 	/* We start copying from the lilp_length field */
2369 	/* in order to get a word aligned address */
2370 	bcopy((void *)&port->alpa_map, (void *)&mapbuf->lilp_length,
2371 	    lilp_length);
2372 
2373 	return (FC_SUCCESS);
2374 
2375 } /* emlxs_get_map() */
2376 
2377 
2378 
2379 extern int
2380 emlxs_transport(opaque_t fca_port_handle, fc_packet_t *pkt)
2381 {
2382 	emlxs_port_t	*port = (emlxs_port_t *)fca_port_handle;
2383 	emlxs_hba_t	*hba = HBA;
2384 	emlxs_buf_t	*sbp;
2385 	uint32_t	rval;
2386 	uint32_t	pkt_flags;
2387 
2388 	/* Make sure adapter is online */
2389 	if (!(hba->flag & FC_ONLINE_MODE)) {
2390 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
2391 		    "Adapter offline.");
2392 
2393 		return (FC_OFFLINE);
2394 	}
2395 
2396 	/* Validate packet */
2397 	sbp = PKT2PRIV(pkt);
2398 
2399 	/* Make sure ULP was told that the port was online */
2400 	if ((port->ulp_statec == FC_STATE_OFFLINE) &&
2401 	    !(sbp->pkt_flags & PACKET_ALLOCATED)) {
2402 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
2403 		    "Port offline.");
2404 
2405 		return (FC_OFFLINE);
2406 	}
2407 
2408 	if (sbp->port != port) {
2409 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
2410 		    "Invalid port handle. sbp=%p port=%p flags=%x", sbp,
2411 		    sbp->port, sbp->pkt_flags);
2412 		return (FC_BADPACKET);
2413 	}
2414 
2415 	if (!(sbp->pkt_flags & (PACKET_VALID | PACKET_ULP_OWNED))) {
2416 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
2417 		    "Invalid packet flags. sbp=%p port=%p flags=%x", sbp,
2418 		    sbp->port, sbp->pkt_flags);
2419 		return (FC_BADPACKET);
2420 	}
2421 #ifdef SFCT_SUPPORT
2422 	if (port->tgt_mode && !sbp->fct_cmd &&
2423 	    !(sbp->pkt_flags & PACKET_ALLOCATED)) {
2424 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
2425 		    "Packet blocked. Target mode.");
2426 		return (FC_TRANSPORT_ERROR);
2427 	}
2428 #endif /* SFCT_SUPPORT */
2429 
2430 #ifdef IDLE_TIMER
2431 	emlxs_pm_busy_component(hba);
2432 #endif	/* IDLE_TIMER */
2433 
2434 	/* Prepare the packet for transport */
2435 	emlxs_initialize_pkt(port, sbp);
2436 
2437 	/* Save a copy of the pkt flags. */
2438 	/* We will check the polling flag later */
2439 	pkt_flags = sbp->pkt_flags;
2440 
2441 	/* Send the packet */
2442 	switch (pkt->pkt_tran_type) {
2443 	case FC_PKT_FCP_READ:
2444 	case FC_PKT_FCP_WRITE:
2445 		rval = emlxs_send_fcp_cmd(port, sbp);
2446 		break;
2447 
2448 	case FC_PKT_IP_WRITE:
2449 	case FC_PKT_BROADCAST:
2450 		rval = emlxs_send_ip(port, sbp);
2451 		break;
2452 
2453 	case FC_PKT_EXCHANGE:
2454 		switch (pkt->pkt_cmd_fhdr.type) {
2455 		case FC_TYPE_SCSI_FCP:
2456 			rval = emlxs_send_fcp_cmd(port, sbp);
2457 			break;
2458 
2459 		case FC_TYPE_FC_SERVICES:
2460 			rval = emlxs_send_ct(port, sbp);
2461 			break;
2462 
2463 #ifdef MENLO_SUPPORT
2464 		case EMLXS_MENLO_TYPE:
2465 			rval = emlxs_send_menlo(port, sbp);
2466 			break;
2467 #endif /* MENLO_SUPPORT */
2468 
2469 		default:
2470 			rval = emlxs_send_els(port, sbp);
2471 		}
2472 		break;
2473 
2474 	case FC_PKT_OUTBOUND:
2475 		switch (pkt->pkt_cmd_fhdr.type) {
2476 #ifdef SFCT_SUPPORT
2477 		case FC_TYPE_SCSI_FCP:
2478 			rval = emlxs_send_fct_status(port, sbp);
2479 			break;
2480 
2481 		case FC_TYPE_BASIC_LS:
2482 			rval = emlxs_send_fct_abort(port, sbp);
2483 			break;
2484 #endif /* SFCT_SUPPORT */
2485 
2486 		case FC_TYPE_FC_SERVICES:
2487 			rval = emlxs_send_ct_rsp(port, sbp);
2488 			break;
2489 #ifdef MENLO_SUPPORT
2490 		case EMLXS_MENLO_TYPE:
2491 			rval = emlxs_send_menlo(port, sbp);
2492 			break;
2493 #endif /* MENLO_SUPPORT */
2494 
2495 		default:
2496 			rval = emlxs_send_els_rsp(port, sbp);
2497 		}
2498 		break;
2499 
2500 	default:
2501 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
2502 		    "Unsupported pkt_tran_type. type=%x", pkt->pkt_tran_type);
2503 		rval = FC_TRANSPORT_ERROR;
2504 		break;
2505 	}
2506 
2507 	/* Check if send was not successful */
2508 	if (rval != FC_SUCCESS) {
2509 		/* Return packet to ULP */
2510 		mutex_enter(&sbp->mtx);
2511 		sbp->pkt_flags |= PACKET_ULP_OWNED;
2512 		mutex_exit(&sbp->mtx);
2513 
2514 		return (rval);
2515 	}
2516 
2517 	/* Check if this packet should be polled for completion before */
2518 	/* returning. This check must be done with a saved copy of the */
2519 	/* pkt_flags because the packet itself could already be freed from */
2520 	/* memory if it was not polled. */
2521 	if (pkt_flags & PACKET_POLLED) {
2522 		emlxs_poll(port, sbp);
2523 	}
2524 
2525 	return (FC_SUCCESS);
2526 
2527 } /* emlxs_transport() */
2528 
2529 
2530 
2531 static void
2532 emlxs_poll(emlxs_port_t *port, emlxs_buf_t *sbp)
2533 {
2534 	emlxs_hba_t	*hba = HBA;
2535 	fc_packet_t	*pkt = PRIV2PKT(sbp);
2536 	clock_t		timeout;
2537 	clock_t		time;
2538 	uint32_t	att_bit;
2539 	CHANNEL	*cp;
2540 
2541 	mutex_enter(&EMLXS_PORT_LOCK);
2542 	hba->io_poll_count++;
2543 	mutex_exit(&EMLXS_PORT_LOCK);
2544 
2545 	/* Check for panic situation */
2546 	cp = (CHANNEL *)sbp->channel;
2547 
2548 	if (ddi_in_panic()) {
2549 		/*
2550 		 * In panic situations there will be one thread with
2551 		 * no interrrupts (hard or soft) and no timers
2552 		 */
2553 
2554 		/*
2555 		 * We must manually poll everything in this thread
2556 		 * to keep the driver going.
2557 		 */
2558 		if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) {
2559 			switch (cp->channelno) {
2560 			case FC_FCP_RING:
2561 				att_bit = HA_R0ATT;
2562 				break;
2563 
2564 			case FC_IP_RING:
2565 				att_bit = HA_R1ATT;
2566 				break;
2567 
2568 			case FC_ELS_RING:
2569 				att_bit = HA_R2ATT;
2570 				break;
2571 
2572 			case FC_CT_RING:
2573 				att_bit = HA_R3ATT;
2574 				break;
2575 			}
2576 		}
2577 
2578 		/* Keep polling the chip until our IO is completed */
2579 		/* Driver's timer will not function during panics. */
2580 		/* Therefore, timer checks must be performed manually. */
2581 		(void) drv_getparm(LBOLT, &time);
2582 		timeout = time + drv_usectohz(1000000);
2583 		while (!(sbp->pkt_flags & PACKET_COMPLETED)) {
2584 			if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) {
2585 				EMLXS_SLI_POLL_INTR(hba, att_bit);
2586 			} else {
2587 				EMLXS_SLI_POLL_INTR(hba, 0);
2588 			}
2589 			(void) drv_getparm(LBOLT, &time);
2590 
2591 			/* Trigger timer checks periodically */
2592 			if (time >= timeout) {
2593 				emlxs_timer_checks(hba);
2594 				timeout = time + drv_usectohz(1000000);
2595 			}
2596 		}
2597 	} else {
2598 		/* Wait for IO completion */
2599 		/* The driver's timer will detect */
2600 		/* any timeout and abort the I/O. */
2601 		mutex_enter(&EMLXS_PKT_LOCK);
2602 		while (!(sbp->pkt_flags & PACKET_COMPLETED)) {
2603 			cv_wait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK);
2604 		}
2605 		mutex_exit(&EMLXS_PKT_LOCK);
2606 	}
2607 
2608 	/* Check for fcp reset pkt */
2609 	if (sbp->pkt_flags & PACKET_FCP_RESET) {
2610 		if (sbp->pkt_flags & PACKET_FCP_TGT_RESET) {
2611 			/* Flush the IO's on the chipq */
2612 			(void) emlxs_chipq_node_flush(port,
2613 			    &hba->chan[hba->channel_fcp],
2614 			    sbp->node, sbp);
2615 		} else {
2616 			/* Flush the IO's on the chipq for this lun */
2617 			(void) emlxs_chipq_lun_flush(port,
2618 			    sbp->node, sbp->lun, sbp);
2619 		}
2620 
2621 		if (sbp->flush_count == 0) {
2622 			emlxs_node_open(port, sbp->node, hba->channel_fcp);
2623 			goto done;
2624 		}
2625 
2626 		/* Set the timeout so the flush has time to complete */
2627 		timeout = emlxs_timeout(hba, 60);
2628 		(void) drv_getparm(LBOLT, &time);
2629 		while ((time < timeout) && sbp->flush_count > 0) {
2630 			delay(drv_usectohz(500000));
2631 			(void) drv_getparm(LBOLT, &time);
2632 		}
2633 
2634 		if (sbp->flush_count == 0) {
2635 			emlxs_node_open(port, sbp->node, hba->channel_fcp);
2636 			goto done;
2637 		}
2638 
2639 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg,
2640 		    "sbp=%p flush_count=%d. Waiting...", sbp,
2641 		    sbp->flush_count);
2642 
2643 		/* Let's try this one more time */
2644 
2645 		if (sbp->pkt_flags & PACKET_FCP_TGT_RESET) {
2646 			/* Flush the IO's on the chipq */
2647 			(void) emlxs_chipq_node_flush(port,
2648 			    &hba->chan[hba->channel_fcp],
2649 			    sbp->node, sbp);
2650 		} else {
2651 			/* Flush the IO's on the chipq for this lun */
2652 			(void) emlxs_chipq_lun_flush(port,
2653 			    sbp->node, sbp->lun, sbp);
2654 		}
2655 
2656 		/* Reset the timeout so the flush has time to complete */
2657 		timeout = emlxs_timeout(hba, 60);
2658 		(void) drv_getparm(LBOLT, &time);
2659 		while ((time < timeout) && sbp->flush_count > 0) {
2660 			delay(drv_usectohz(500000));
2661 			(void) drv_getparm(LBOLT, &time);
2662 		}
2663 
2664 		if (sbp->flush_count == 0) {
2665 			emlxs_node_open(port, sbp->node, hba->channel_fcp);
2666 			goto done;
2667 		}
2668 
2669 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg,
2670 		    "sbp=%p flush_count=%d. Resetting link.", sbp,
2671 		    sbp->flush_count);
2672 
2673 		/* Let's first try to reset the link */
2674 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
2675 
2676 		if (sbp->flush_count == 0) {
2677 			goto done;
2678 		}
2679 
2680 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg,
2681 		    "sbp=%p flush_count=%d. Resetting HBA.", sbp,
2682 		    sbp->flush_count);
2683 
2684 		/* If that doesn't work, reset the adapter */
2685 		(void) emlxs_reset(port, FC_FCA_RESET);
2686 
2687 		if (sbp->flush_count != 0) {
2688 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg,
2689 			    "sbp=%p flush_count=%d. Giving up.", sbp,
2690 			    sbp->flush_count);
2691 		}
2692 
2693 	}
2694 	/* PACKET_FCP_RESET */
2695 done:
2696 
2697 	/* Packet has been declared completed and is now ready to be returned */
2698 
2699 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
2700 	emlxs_unswap_pkt(sbp);
2701 #endif	/* EMLXS_MODREV2X */
2702 
2703 	mutex_enter(&sbp->mtx);
2704 	sbp->pkt_flags |= PACKET_ULP_OWNED;
2705 	mutex_exit(&sbp->mtx);
2706 
2707 	mutex_enter(&EMLXS_PORT_LOCK);
2708 	hba->io_poll_count--;
2709 	mutex_exit(&EMLXS_PORT_LOCK);
2710 
2711 	/* Make ULP completion callback if required */
2712 	if (pkt->pkt_comp) {
2713 		cp->ulpCmplCmd++;
2714 		(*pkt->pkt_comp) (pkt);
2715 	}
2716 
2717 	return;
2718 
2719 } /* emlxs_poll() */
2720 
2721 
2722 static int
2723 emlxs_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size,
2724     uint32_t *count, uint32_t type)
2725 {
2726 	emlxs_port_t		*port = (emlxs_port_t *)fca_port_handle;
2727 	emlxs_hba_t		*hba = HBA;
2728 
2729 	char			*err = NULL;
2730 	emlxs_unsol_buf_t	*pool;
2731 	emlxs_unsol_buf_t	*new_pool;
2732 	int32_t			i;
2733 	int			result;
2734 	uint32_t		free_resv;
2735 	uint32_t		free;
2736 	emlxs_config_t		*cfg = &CFG;
2737 	fc_unsol_buf_t		*ubp;
2738 	emlxs_ub_priv_t		*ub_priv;
2739 	int			rc;
2740 
2741 	if (port->tgt_mode) {
2742 		if (tokens && count) {
2743 			bzero(tokens, (sizeof (uint64_t) * (*count)));
2744 		}
2745 		return (FC_SUCCESS);
2746 	}
2747 
2748 	if (!(port->flag & EMLXS_PORT_BOUND)) {
2749 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2750 		    "ub_alloc failed: Port not bound!  size=%x count=%d "
2751 		    "type=%x", size, *count, type);
2752 
2753 		return (FC_FAILURE);
2754 	}
2755 
2756 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2757 	    "ub_alloc: size=%x count=%d type=%x", size, *count, type);
2758 
2759 	if (count && (*count > EMLXS_MAX_UBUFS)) {
2760 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
2761 		    "ub_alloc failed: Too many unsolicted buffers requested. "
2762 		    "count=%x", *count);
2763 
2764 		return (FC_FAILURE);
2765 
2766 	}
2767 
2768 	if (tokens == NULL) {
2769 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
2770 		    "ub_alloc failed: Token array is NULL.");
2771 
2772 		return (FC_FAILURE);
2773 	}
2774 
2775 	/* Clear the token array */
2776 	bzero(tokens, (sizeof (uint64_t) * (*count)));
2777 
2778 	free_resv = 0;
2779 	free = *count;
2780 	switch (type) {
2781 	case FC_TYPE_BASIC_LS:
2782 		err = "BASIC_LS";
2783 		break;
2784 	case FC_TYPE_EXTENDED_LS:
2785 		err = "EXTENDED_LS";
2786 		free = *count / 2;	/* Hold 50% for normal use */
2787 		free_resv = *count - free;	/* Reserve 50% for RSCN use */
2788 		break;
2789 	case FC_TYPE_IS8802:
2790 		err = "IS8802";
2791 		break;
2792 	case FC_TYPE_IS8802_SNAP:
2793 		err = "IS8802_SNAP";
2794 
2795 		if (cfg[CFG_NETWORK_ON].current == 0) {
2796 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
2797 			    "ub_alloc failed: IP support is disabled.");
2798 
2799 			return (FC_FAILURE);
2800 		}
2801 		break;
2802 	case FC_TYPE_SCSI_FCP:
2803 		err = "SCSI_FCP";
2804 		break;
2805 	case FC_TYPE_SCSI_GPP:
2806 		err = "SCSI_GPP";
2807 		break;
2808 	case FC_TYPE_HIPP_FP:
2809 		err = "HIPP_FP";
2810 		break;
2811 	case FC_TYPE_IPI3_MASTER:
2812 		err = "IPI3_MASTER";
2813 		break;
2814 	case FC_TYPE_IPI3_SLAVE:
2815 		err = "IPI3_SLAVE";
2816 		break;
2817 	case FC_TYPE_IPI3_PEER:
2818 		err = "IPI3_PEER";
2819 		break;
2820 	case FC_TYPE_FC_SERVICES:
2821 		err = "FC_SERVICES";
2822 		break;
2823 	}
2824 
2825 	mutex_enter(&EMLXS_UB_LOCK);
2826 
2827 	/*
2828 	 * Walk through the list of the unsolicited buffers
2829 	 * for this ddiinst of emlx.
2830 	 */
2831 
2832 	pool = port->ub_pool;
2833 
2834 	/*
2835 	 * The emlxs_ub_alloc() can be called more than once with different
2836 	 * size. We will reject the call if there are
2837 	 * duplicate size with the same FC-4 type.
2838 	 */
2839 	while (pool) {
2840 		if ((pool->pool_type == type) &&
2841 		    (pool->pool_buf_size == size)) {
2842 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
2843 			    "ub_alloc failed: Unsolicited buffer pool for %s "
2844 			    "of size 0x%x bytes already exists.", err, size);
2845 
2846 			result = FC_FAILURE;
2847 			goto fail;
2848 		}
2849 
2850 		pool = pool->pool_next;
2851 	}
2852 
2853 	mutex_exit(&EMLXS_UB_LOCK);
2854 
2855 	new_pool = (emlxs_unsol_buf_t *)kmem_zalloc(sizeof (emlxs_unsol_buf_t),
2856 	    KM_SLEEP);
2857 
2858 	new_pool->pool_next = NULL;
2859 	new_pool->pool_type = type;
2860 	new_pool->pool_buf_size = size;
2861 	new_pool->pool_nentries = *count;
2862 	new_pool->pool_available = new_pool->pool_nentries;
2863 	new_pool->pool_free = free;
2864 	new_pool->pool_free_resv = free_resv;
2865 	new_pool->fc_ubufs =
2866 	    kmem_zalloc((sizeof (fc_unsol_buf_t) * (*count)), KM_SLEEP);
2867 
2868 	new_pool->pool_first_token = port->ub_count;
2869 	new_pool->pool_last_token = port->ub_count + new_pool->pool_nentries;
2870 
2871 	for (i = 0; i < new_pool->pool_nentries; i++) {
2872 		ubp = (fc_unsol_buf_t *)&new_pool->fc_ubufs[i];
2873 		ubp->ub_port_handle = port->ulp_handle;
2874 		ubp->ub_token = (uint64_t)((unsigned long)ubp);
2875 		ubp->ub_bufsize = size;
2876 		ubp->ub_class = FC_TRAN_CLASS3;
2877 		ubp->ub_port_private = NULL;
2878 		ubp->ub_fca_private =
2879 		    (emlxs_ub_priv_t *)kmem_zalloc(sizeof (emlxs_ub_priv_t),
2880 		    KM_SLEEP);
2881 
2882 		/*
2883 		 * Initialize emlxs_ub_priv_t
2884 		 */
2885 		ub_priv = ubp->ub_fca_private;
2886 		ub_priv->ubp = ubp;
2887 		ub_priv->port = port;
2888 		ub_priv->flags = EMLXS_UB_FREE;
2889 		ub_priv->available = 1;
2890 		ub_priv->pool = new_pool;
2891 		ub_priv->time = 0;
2892 		ub_priv->timeout = 0;
2893 		ub_priv->token = port->ub_count;
2894 		ub_priv->cmd = 0;
2895 
2896 		/* Allocate the actual buffer */
2897 		ubp->ub_buffer = (caddr_t)kmem_zalloc(size, KM_SLEEP);
2898 
2899 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
2900 		    "ub_alloc: buffer=%p token=%x size=%x type=%x ", ubp,
2901 		    ub_priv->token, ubp->ub_bufsize, type);
2902 
2903 		tokens[i] = (uint64_t)((unsigned long)ubp);
2904 		port->ub_count++;
2905 	}
2906 
2907 	mutex_enter(&EMLXS_UB_LOCK);
2908 
2909 	/* Add the pool to the top of the pool list */
2910 	new_pool->pool_prev = NULL;
2911 	new_pool->pool_next = port->ub_pool;
2912 
2913 	if (port->ub_pool) {
2914 		port->ub_pool->pool_prev = new_pool;
2915 	}
2916 	port->ub_pool = new_pool;
2917 
2918 	/* Set the post counts */
2919 	if (type == FC_TYPE_IS8802_SNAP) {
2920 		MAILBOXQ	*mbox;
2921 
2922 		port->ub_post[hba->channel_ip] += new_pool->pool_nentries;
2923 
2924 		if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
2925 		    MEM_MBOX, 1))) {
2926 			emlxs_mb_config_farp(hba, mbox);
2927 			rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba,
2928 			    mbox, MBX_NOWAIT, 0);
2929 			if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
2930 				(void) emlxs_mem_put(hba, MEM_MBOX,
2931 				    (uint8_t *)mbox);
2932 			}
2933 		}
2934 		port->flag |= EMLXS_PORT_IP_UP;
2935 	} else if (type == FC_TYPE_EXTENDED_LS) {
2936 		port->ub_post[hba->channel_els] += new_pool->pool_nentries;
2937 	} else if (type == FC_TYPE_FC_SERVICES) {
2938 		port->ub_post[hba->channel_ct] += new_pool->pool_nentries;
2939 	}
2940 
2941 	mutex_exit(&EMLXS_UB_LOCK);
2942 
2943 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2944 	    "%d unsolicited buffers allocated for %s of size 0x%x bytes.",
2945 	    *count, err, size);
2946 
2947 	return (FC_SUCCESS);
2948 
2949 fail:
2950 
2951 	/* Clean the pool */
2952 	for (i = 0; tokens[i] != NULL; i++) {
2953 		/* Get the buffer object */
2954 		ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]);
2955 		ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
2956 
2957 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
2958 		    "ub_alloc failed: Freed buffer=%p token=%x size=%x "
2959 		    "type=%x ", ubp, ub_priv->token, ubp->ub_bufsize, type);
2960 
2961 		/* Free the actual buffer */
2962 		kmem_free(ubp->ub_buffer, ubp->ub_bufsize);
2963 
2964 		/* Free the private area of the buffer object */
2965 		kmem_free(ubp->ub_fca_private, sizeof (emlxs_ub_priv_t));
2966 
2967 		tokens[i] = 0;
2968 		port->ub_count--;
2969 	}
2970 
2971 	/* Free the array of buffer objects in the pool */
2972 	kmem_free((caddr_t)new_pool->fc_ubufs,
2973 	    (sizeof (fc_unsol_buf_t) * new_pool->pool_nentries));
2974 
2975 	/* Free the pool object */
2976 	kmem_free((caddr_t)new_pool, sizeof (emlxs_unsol_buf_t));
2977 
2978 	mutex_exit(&EMLXS_UB_LOCK);
2979 
2980 	return (result);
2981 
2982 } /* emlxs_ub_alloc() */
2983 
2984 
2985 static void
2986 emlxs_ub_els_reject(emlxs_port_t *port, fc_unsol_buf_t *ubp)
2987 {
2988 	emlxs_hba_t	*hba = HBA;
2989 	emlxs_ub_priv_t	*ub_priv;
2990 	fc_packet_t	*pkt;
2991 	ELS_PKT		*els;
2992 	uint32_t	sid;
2993 
2994 	ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
2995 
2996 	if (hba->state <= FC_LINK_DOWN) {
2997 		return;
2998 	}
2999 
3000 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) +
3001 	    sizeof (LS_RJT), 0, 0, KM_NOSLEEP))) {
3002 		return;
3003 	}
3004 
3005 	sid = LE_SWAP24_LO(ubp->ub_frame.s_id);
3006 
3007 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3008 	    "%s dropped: sid=%x. Rejecting.",
3009 	    emlxs_elscmd_xlate(ub_priv->cmd), sid);
3010 
3011 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
3012 	pkt->pkt_timeout = (2 * hba->fc_ratov);
3013 
3014 	if ((uint32_t)ubp->ub_class == FC_TRAN_CLASS2) {
3015 		pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
3016 		pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
3017 	}
3018 
3019 	/* Build the fc header */
3020 	pkt->pkt_cmd_fhdr.d_id = ubp->ub_frame.s_id;
3021 	pkt->pkt_cmd_fhdr.r_ctl =
3022 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
3023 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
3024 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3025 	pkt->pkt_cmd_fhdr.f_ctl =
3026 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
3027 	pkt->pkt_cmd_fhdr.seq_id = 0;
3028 	pkt->pkt_cmd_fhdr.df_ctl = 0;
3029 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
3030 	pkt->pkt_cmd_fhdr.ox_id = (ub_priv->cmd >> ELS_CMD_SHIFT) & 0xff;
3031 	pkt->pkt_cmd_fhdr.rx_id = ubp->ub_frame.rx_id;
3032 	pkt->pkt_cmd_fhdr.ro = 0;
3033 
3034 	/* Build the command */
3035 	els = (ELS_PKT *) pkt->pkt_cmd;
3036 	els->elsCode = 0x01;
3037 	els->un.lsRjt.un.b.lsRjtRsvd0 = 0;
3038 	els->un.lsRjt.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
3039 	els->un.lsRjt.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
3040 	els->un.lsRjt.un.b.vendorUnique = 0x02;
3041 
3042 	/* Send the pkt later in another thread */
3043 	(void) emlxs_pkt_send(pkt, 0);
3044 
3045 	return;
3046 
3047 } /* emlxs_ub_els_reject() */
3048 
3049 extern int
3050 emlxs_ub_release(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[])
3051 {
3052 	emlxs_port_t		*port = (emlxs_port_t *)fca_port_handle;
3053 	emlxs_hba_t		*hba = HBA;
3054 	fc_unsol_buf_t		*ubp;
3055 	emlxs_ub_priv_t		*ub_priv;
3056 	uint32_t		i;
3057 	uint32_t		time;
3058 	emlxs_unsol_buf_t	*pool;
3059 
3060 	if (count == 0) {
3061 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3062 		    "ub_release: Nothing to do. count=%d", count);
3063 
3064 		return (FC_SUCCESS);
3065 	}
3066 
3067 	if (!(port->flag & EMLXS_PORT_BOUND)) {
3068 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3069 		    "ub_release failed: Port not bound. count=%d token[0]=%p",
3070 		    count, tokens[0]);
3071 
3072 		return (FC_UNBOUND);
3073 	}
3074 
3075 	mutex_enter(&EMLXS_UB_LOCK);
3076 
3077 	if (!port->ub_pool) {
3078 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3079 		    "ub_release failed: No pools! count=%d token[0]=%p",
3080 		    count, tokens[0]);
3081 
3082 		mutex_exit(&EMLXS_UB_LOCK);
3083 		return (FC_UB_BADTOKEN);
3084 	}
3085 
3086 	for (i = 0; i < count; i++) {
3087 		ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]);
3088 
3089 		if (!ubp) {
3090 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3091 			    "ub_release failed: count=%d tokens[%d]=0", count,
3092 			    i);
3093 
3094 			mutex_exit(&EMLXS_UB_LOCK);
3095 			return (FC_UB_BADTOKEN);
3096 		}
3097 
3098 		ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
3099 
3100 		if (!ub_priv || (ub_priv == (emlxs_ub_priv_t *)DEAD_PTR)) {
3101 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3102 			    "ub_release failed: Dead buffer found. ubp=%p",
3103 			    ubp);
3104 
3105 			mutex_exit(&EMLXS_UB_LOCK);
3106 			return (FC_UB_BADTOKEN);
3107 		}
3108 
3109 		if (ub_priv->flags == EMLXS_UB_FREE) {
3110 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3111 			    "ub_release: Buffer already free! ubp=%p token=%x",
3112 			    ubp, ub_priv->token);
3113 
3114 			continue;
3115 		}
3116 
3117 		/* Check for dropped els buffer */
3118 		/* ULP will do this sometimes without sending a reply */
3119 		if ((ubp->ub_frame.r_ctl == FC_ELS_REQ) &&
3120 		    !(ub_priv->flags & EMLXS_UB_REPLY)) {
3121 			emlxs_ub_els_reject(port, ubp);
3122 		}
3123 
3124 		/* Mark the buffer free */
3125 		ub_priv->flags = EMLXS_UB_FREE;
3126 		bzero(ubp->ub_buffer, ubp->ub_bufsize);
3127 
3128 		time = hba->timer_tics - ub_priv->time;
3129 		ub_priv->time = 0;
3130 		ub_priv->timeout = 0;
3131 
3132 		pool = ub_priv->pool;
3133 
3134 		if (ub_priv->flags & EMLXS_UB_RESV) {
3135 			pool->pool_free_resv++;
3136 		} else {
3137 			pool->pool_free++;
3138 		}
3139 
3140 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
3141 		    "ub_release: ubp=%p token=%x time=%d av=%d (%d,%d,%d,%d)",
3142 		    ubp, ub_priv->token, time, ub_priv->available,
3143 		    pool->pool_nentries, pool->pool_available,
3144 		    pool->pool_free, pool->pool_free_resv);
3145 
3146 		/* Check if pool can be destroyed now */
3147 		if ((pool->pool_available == 0) &&
3148 		    (pool->pool_free + pool->pool_free_resv ==
3149 		    pool->pool_nentries)) {
3150 			emlxs_ub_destroy(port, pool);
3151 		}
3152 	}
3153 
3154 	mutex_exit(&EMLXS_UB_LOCK);
3155 
3156 	return (FC_SUCCESS);
3157 
3158 } /* emlxs_ub_release() */
3159 
3160 
3161 static int
3162 emlxs_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[])
3163 {
3164 	emlxs_port_t		*port = (emlxs_port_t *)fca_port_handle;
3165 	emlxs_unsol_buf_t	*pool;
3166 	fc_unsol_buf_t		*ubp;
3167 	emlxs_ub_priv_t		*ub_priv;
3168 	uint32_t		i;
3169 
3170 	if (port->tgt_mode) {
3171 		return (FC_SUCCESS);
3172 	}
3173 
3174 	if (count == 0) {
3175 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3176 		    "ub_free: Nothing to do. count=%d token[0]=%p", count,
3177 		    tokens[0]);
3178 
3179 		return (FC_SUCCESS);
3180 	}
3181 
3182 	if (!(port->flag & EMLXS_PORT_BOUND)) {
3183 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3184 		    "ub_free: Port not bound. count=%d token[0]=%p", count,
3185 		    tokens[0]);
3186 
3187 		return (FC_SUCCESS);
3188 	}
3189 
3190 	mutex_enter(&EMLXS_UB_LOCK);
3191 
3192 	if (!port->ub_pool) {
3193 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3194 		    "ub_free failed: No pools! count=%d token[0]=%p", count,
3195 		    tokens[0]);
3196 
3197 		mutex_exit(&EMLXS_UB_LOCK);
3198 		return (FC_UB_BADTOKEN);
3199 	}
3200 
3201 	/* Process buffer list */
3202 	for (i = 0; i < count; i++) {
3203 		ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]);
3204 
3205 		if (!ubp) {
3206 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3207 			    "ub_free failed: count=%d tokens[%d]=0", count,
3208 			    i);
3209 
3210 			mutex_exit(&EMLXS_UB_LOCK);
3211 			return (FC_UB_BADTOKEN);
3212 		}
3213 
3214 		/* Mark buffer unavailable */
3215 		ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
3216 
3217 		if (!ub_priv || (ub_priv == (emlxs_ub_priv_t *)DEAD_PTR)) {
3218 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3219 			    "ub_free failed: Dead buffer found. ubp=%p", ubp);
3220 
3221 			mutex_exit(&EMLXS_UB_LOCK);
3222 			return (FC_UB_BADTOKEN);
3223 		}
3224 
3225 		ub_priv->available = 0;
3226 
3227 		/* Mark one less buffer available in the parent pool */
3228 		pool = ub_priv->pool;
3229 
3230 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
3231 		    "ub_free: ubp=%p token=%x (%d,%d,%d,%d)", ubp,
3232 		    ub_priv->token, pool->pool_nentries,
3233 		    pool->pool_available - 1, pool->pool_free,
3234 		    pool->pool_free_resv);
3235 
3236 		if (pool->pool_available) {
3237 			pool->pool_available--;
3238 
3239 			/* Check if pool can be destroyed */
3240 			if ((pool->pool_available == 0) &&
3241 			    (pool->pool_free + pool->pool_free_resv ==
3242 			    pool->pool_nentries)) {
3243 				emlxs_ub_destroy(port, pool);
3244 			}
3245 		}
3246 	}
3247 
3248 	mutex_exit(&EMLXS_UB_LOCK);
3249 
3250 	return (FC_SUCCESS);
3251 
3252 } /* emlxs_ub_free() */
3253 
3254 
3255 /* EMLXS_UB_LOCK must be held when calling this routine */
3256 extern void
3257 emlxs_ub_destroy(emlxs_port_t *port, emlxs_unsol_buf_t *pool)
3258 {
3259 	emlxs_hba_t		*hba = HBA;
3260 	emlxs_unsol_buf_t	*next;
3261 	emlxs_unsol_buf_t	*prev;
3262 	fc_unsol_buf_t		*ubp;
3263 	uint32_t		i;
3264 
3265 	/* Remove the pool object from the pool list */
3266 	next = pool->pool_next;
3267 	prev = pool->pool_prev;
3268 
3269 	if (port->ub_pool == pool) {
3270 		port->ub_pool = next;
3271 	}
3272 
3273 	if (prev) {
3274 		prev->pool_next = next;
3275 	}
3276 
3277 	if (next) {
3278 		next->pool_prev = prev;
3279 	}
3280 
3281 	pool->pool_prev = NULL;
3282 	pool->pool_next = NULL;
3283 
3284 	/* Clear the post counts */
3285 	switch (pool->pool_type) {
3286 	case FC_TYPE_IS8802_SNAP:
3287 		port->ub_post[hba->channel_ip] -= pool->pool_nentries;
3288 		break;
3289 
3290 	case FC_TYPE_EXTENDED_LS:
3291 		port->ub_post[hba->channel_els] -= pool->pool_nentries;
3292 		break;
3293 
3294 	case FC_TYPE_FC_SERVICES:
3295 		port->ub_post[hba->channel_ct] -= pool->pool_nentries;
3296 		break;
3297 	}
3298 
3299 	/* Now free the pool memory */
3300 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3301 	    "ub_destroy: pool=%p type=%d size=%d count=%d", pool,
3302 	    pool->pool_type, pool->pool_buf_size, pool->pool_nentries);
3303 
3304 	/* Process the array of buffer objects in the pool */
3305 	for (i = 0; i < pool->pool_nentries; i++) {
3306 		/* Get the buffer object */
3307 		ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[i];
3308 
3309 		/* Free the memory the buffer object represents */
3310 		kmem_free(ubp->ub_buffer, ubp->ub_bufsize);
3311 
3312 		/* Free the private area of the buffer object */
3313 		kmem_free(ubp->ub_fca_private, sizeof (emlxs_ub_priv_t));
3314 	}
3315 
3316 	/* Free the array of buffer objects in the pool */
3317 	kmem_free((caddr_t)pool->fc_ubufs,
3318 	    (sizeof (fc_unsol_buf_t)*pool->pool_nentries));
3319 
3320 	/* Free the pool object */
3321 	kmem_free((caddr_t)pool, sizeof (emlxs_unsol_buf_t));
3322 
3323 	return;
3324 
3325 } /* emlxs_ub_destroy() */
3326 
3327 
3328 /*ARGSUSED*/
3329 extern int
3330 emlxs_pkt_abort(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep)
3331 {
3332 	emlxs_port_t	*port = (emlxs_port_t *)fca_port_handle;
3333 	emlxs_hba_t	*hba = HBA;
3334 	emlxs_config_t	*cfg = &CFG;
3335 
3336 	emlxs_buf_t	*sbp;
3337 	NODELIST	*nlp;
3338 	NODELIST	*prev_nlp;
3339 	uint8_t		channelno;
3340 	CHANNEL	*cp;
3341 	clock_t		timeout;
3342 	clock_t		time;
3343 	int32_t		pkt_ret;
3344 	IOCBQ		*iocbq;
3345 	IOCBQ		*next;
3346 	IOCBQ		*prev;
3347 	uint32_t	found;
3348 	uint32_t	att_bit;
3349 	uint32_t	pass = 0;
3350 
3351 	sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
3352 	iocbq = &sbp->iocbq;
3353 	nlp = (NODELIST *)sbp->node;
3354 	cp = (CHANNEL *)sbp->channel;
3355 	channelno = (cp) ? cp->channelno : 0;
3356 
3357 	if (!(port->flag & EMLXS_PORT_BOUND)) {
3358 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
3359 		    "Port not bound.");
3360 		return (FC_UNBOUND);
3361 	}
3362 
3363 	if (!(hba->flag & FC_ONLINE_MODE)) {
3364 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
3365 		    "Adapter offline.");
3366 		return (FC_OFFLINE);
3367 	}
3368 
3369 	/* ULP requires the aborted pkt to be completed */
3370 	/* back to ULP before returning from this call. */
3371 	/* SUN knows of problems with this call so they suggested that we */
3372 	/* always return a FC_FAILURE for this call, until it is worked out. */
3373 
3374 	/* Check if pkt is no good */
3375 	if (!(sbp->pkt_flags & PACKET_VALID) ||
3376 	    (sbp->pkt_flags & PACKET_ULP_OWNED)) {
3377 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
3378 		    "Bad sbp. flags=%x", sbp->pkt_flags);
3379 		return (FC_FAILURE);
3380 	}
3381 
3382 	/* Tag this now */
3383 	/* This will prevent any thread except ours from completing it */
3384 	mutex_enter(&sbp->mtx);
3385 
3386 	/* Check again if we still own this */
3387 	if (!(sbp->pkt_flags & PACKET_VALID) ||
3388 	    (sbp->pkt_flags & PACKET_ULP_OWNED)) {
3389 		mutex_exit(&sbp->mtx);
3390 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
3391 		    "Bad sbp. flags=%x", sbp->pkt_flags);
3392 		return (FC_FAILURE);
3393 	}
3394 
3395 	/* Check if pkt is a real polled command */
3396 	if (!(sbp->pkt_flags & PACKET_IN_ABORT) &&
3397 	    (sbp->pkt_flags & PACKET_POLLED)) {
3398 		mutex_exit(&sbp->mtx);
3399 
3400 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
3401 		    "Attempting to abort a polled I/O. sbp=%p flags=%x", sbp,
3402 		    sbp->pkt_flags);
3403 		return (FC_FAILURE);
3404 	}
3405 
3406 	sbp->pkt_flags |= PACKET_POLLED;
3407 	sbp->pkt_flags |= PACKET_IN_ABORT;
3408 
3409 	if (sbp->pkt_flags & (PACKET_IN_COMPLETION | PACKET_IN_FLUSH |
3410 	    PACKET_IN_TIMEOUT)) {
3411 		mutex_exit(&sbp->mtx);
3412 
3413 		/* Do nothing, pkt already on its way out */
3414 		goto done;
3415 	}
3416 
3417 	mutex_exit(&sbp->mtx);
3418 
3419 begin:
3420 	pass++;
3421 
3422 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
3423 
3424 	if (sbp->pkt_flags & PACKET_IN_TXQ) {
3425 		/* Find it on the queue */
3426 		found = 0;
3427 		if (iocbq->flag & IOCB_PRIORITY) {
3428 			/* Search the priority queue */
3429 			prev = NULL;
3430 			next = (IOCBQ *) nlp->nlp_ptx[channelno].q_first;
3431 
3432 			while (next) {
3433 				if (next == iocbq) {
3434 					/* Remove it */
3435 					if (prev) {
3436 						prev->next = iocbq->next;
3437 					}
3438 
3439 					if (nlp->nlp_ptx[channelno].q_last ==
3440 					    (void *)iocbq) {
3441 						nlp->nlp_ptx[channelno].q_last =
3442 						    (void *)prev;
3443 					}
3444 
3445 					if (nlp->nlp_ptx[channelno].q_first ==
3446 					    (void *)iocbq) {
3447 						nlp->nlp_ptx[channelno].
3448 						    q_first =
3449 						    (void *)iocbq->next;
3450 					}
3451 
3452 					nlp->nlp_ptx[channelno].q_cnt--;
3453 					iocbq->next = NULL;
3454 					found = 1;
3455 					break;
3456 				}
3457 
3458 				prev = next;
3459 				next = next->next;
3460 			}
3461 		} else {
3462 			/* Search the normal queue */
3463 			prev = NULL;
3464 			next = (IOCBQ *) nlp->nlp_tx[channelno].q_first;
3465 
3466 			while (next) {
3467 				if (next == iocbq) {
3468 					/* Remove it */
3469 					if (prev) {
3470 						prev->next = iocbq->next;
3471 					}
3472 
3473 					if (nlp->nlp_tx[channelno].q_last ==
3474 					    (void *)iocbq) {
3475 						nlp->nlp_tx[channelno].q_last =
3476 						    (void *)prev;
3477 					}
3478 
3479 					if (nlp->nlp_tx[channelno].q_first ==
3480 					    (void *)iocbq) {
3481 						nlp->nlp_tx[channelno].q_first =
3482 						    (void *)iocbq->next;
3483 					}
3484 
3485 					nlp->nlp_tx[channelno].q_cnt--;
3486 					iocbq->next = NULL;
3487 					found = 1;
3488 					break;
3489 				}
3490 
3491 				prev = next;
3492 				next = (IOCBQ *) next->next;
3493 			}
3494 		}
3495 
3496 		if (!found) {
3497 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
3498 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
3499 			    "I/O not found in driver. sbp=%p flags=%x", sbp,
3500 			    sbp->pkt_flags);
3501 			goto done;
3502 		}
3503 
3504 		/* Check if node still needs servicing */
3505 		if ((nlp->nlp_ptx[channelno].q_first) ||
3506 		    (nlp->nlp_tx[channelno].q_first &&
3507 		    !(nlp->nlp_flag[channelno] & NLP_CLOSED))) {
3508 
3509 			/*
3510 			 * If this is the base node,
3511 			 * then don't shift the pointers
3512 			 */
3513 			/* We want to drain the base node before moving on */
3514 			if (!nlp->nlp_base) {
3515 				/* Just shift channel queue */
3516 				/* pointers to next node */
3517 				cp->nodeq.q_last = (void *) nlp;
3518 				cp->nodeq.q_first = nlp->nlp_next[channelno];
3519 			}
3520 		} else {
3521 			/* Remove node from channel queue */
3522 
3523 			/* If this is the only node on list */
3524 			if (cp->nodeq.q_first == (void *)nlp &&
3525 			    cp->nodeq.q_last == (void *)nlp) {
3526 				cp->nodeq.q_last = NULL;
3527 				cp->nodeq.q_first = NULL;
3528 				cp->nodeq.q_cnt = 0;
3529 			} else if (cp->nodeq.q_first == (void *)nlp) {
3530 				cp->nodeq.q_first = nlp->nlp_next[channelno];
3531 				((NODELIST *) cp->nodeq.q_last)->
3532 				    nlp_next[channelno] = cp->nodeq.q_first;
3533 				cp->nodeq.q_cnt--;
3534 			} else {
3535 				/*
3536 				 * This is a little more difficult find the
3537 				 * previous node in the circular channel queue
3538 				 */
3539 				prev_nlp = nlp;
3540 				while (prev_nlp->nlp_next[channelno] != nlp) {
3541 					prev_nlp = prev_nlp->
3542 					    nlp_next[channelno];
3543 				}
3544 
3545 				prev_nlp->nlp_next[channelno] =
3546 				    nlp->nlp_next[channelno];
3547 
3548 				if (cp->nodeq.q_last == (void *)nlp) {
3549 					cp->nodeq.q_last = (void *)prev_nlp;
3550 				}
3551 				cp->nodeq.q_cnt--;
3552 
3553 			}
3554 
3555 			/* Clear node */
3556 			nlp->nlp_next[channelno] = NULL;
3557 		}
3558 
3559 		/* Free the ULPIOTAG and the bmp */
3560 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3561 			hba->fc_table[sbp->iotag] = NULL;
3562 			emlxs_sli4_free_xri(hba, sbp, sbp->xp);
3563 		} else {
3564 			(void) emlxs_unregister_pkt(cp, sbp->iotag, 1);
3565 		}
3566 
3567 
3568 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
3569 
3570 		emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
3571 		    IOERR_ABORT_REQUESTED, 1);
3572 
3573 		goto done;
3574 	}
3575 
3576 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
3577 
3578 
3579 	/* Check the chip queue */
3580 	mutex_enter(&EMLXS_FCTAB_LOCK);
3581 
3582 	if ((sbp->pkt_flags & PACKET_IN_CHIPQ) &&
3583 	    !(sbp->pkt_flags & PACKET_XRI_CLOSED) &&
3584 	    (sbp == hba->fc_table[sbp->iotag])) {
3585 
3586 		/* Create the abort IOCB */
3587 		if (hba->state >= FC_LINK_UP) {
3588 			iocbq =
3589 			    emlxs_create_abort_xri_cn(port, sbp->node,
3590 			    sbp->iotag, cp, sbp->class, ABORT_TYPE_ABTS);
3591 
3592 			mutex_enter(&sbp->mtx);
3593 			sbp->pkt_flags |= PACKET_XRI_CLOSED;
3594 			sbp->ticks =
3595 			    hba->timer_tics + (4 * hba->fc_ratov) + 10;
3596 			sbp->abort_attempts++;
3597 			mutex_exit(&sbp->mtx);
3598 		} else {
3599 			iocbq =
3600 			    emlxs_create_close_xri_cn(port, sbp->node,
3601 			    sbp->iotag, cp);
3602 
3603 			mutex_enter(&sbp->mtx);
3604 			sbp->pkt_flags |= PACKET_XRI_CLOSED;
3605 			sbp->ticks = hba->timer_tics + 30;
3606 			sbp->abort_attempts++;
3607 			mutex_exit(&sbp->mtx);
3608 		}
3609 
3610 		mutex_exit(&EMLXS_FCTAB_LOCK);
3611 
3612 		/* Send this iocbq */
3613 		if (iocbq) {
3614 			EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
3615 			iocbq = NULL;
3616 		}
3617 
3618 		goto done;
3619 	}
3620 
3621 	mutex_exit(&EMLXS_FCTAB_LOCK);
3622 
3623 	/* Pkt was not on any queues */
3624 
3625 	/* Check again if we still own this */
3626 	if (!(sbp->pkt_flags & PACKET_VALID) ||
3627 	    (sbp->pkt_flags &
3628 	    (PACKET_ULP_OWNED | PACKET_IN_COMPLETION |
3629 	    PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
3630 		goto done;
3631 	}
3632 
3633 	if (!sleep) {
3634 		return (FC_FAILURE);
3635 	}
3636 
3637 	/* Apparently the pkt was not found.  Let's delay and try again */
3638 	if (pass < 5) {
3639 		delay(drv_usectohz(5000000));	/* 5 seconds */
3640 
3641 		/* Check again if we still own this */
3642 		if (!(sbp->pkt_flags & PACKET_VALID) ||
3643 		    (sbp->pkt_flags &
3644 		    (PACKET_ULP_OWNED | PACKET_IN_COMPLETION |
3645 		    PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
3646 			goto done;
3647 		}
3648 
3649 		goto begin;
3650 	}
3651 
3652 force_it:
3653 
3654 	/* Force the completion now */
3655 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3656 	    "Abort: Completing an IO thats not outstanding: %x", sbp->iotag);
3657 
3658 	/* Now complete it */
3659 	emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, IOERR_ABORT_REQUESTED,
3660 	    1);
3661 
3662 done:
3663 
3664 	/* Now wait for the pkt to complete */
3665 	if (!(sbp->pkt_flags & PACKET_COMPLETED)) {
3666 		/* Set thread timeout */
3667 		timeout = emlxs_timeout(hba, 30);
3668 
3669 		/* Check for panic situation */
3670 		if (ddi_in_panic()) {
3671 
3672 			/*
3673 			 * In panic situations there will be one thread with no
3674 			 * interrrupts (hard or soft) and no timers
3675 			 */
3676 
3677 			/*
3678 			 * We must manually poll everything in this thread
3679 			 * to keep the driver going.
3680 			 */
3681 
3682 			cp = (CHANNEL *)sbp->channel;
3683 			switch (cp->channelno) {
3684 			case FC_FCP_RING:
3685 				att_bit = HA_R0ATT;
3686 				break;
3687 
3688 			case FC_IP_RING:
3689 				att_bit = HA_R1ATT;
3690 				break;
3691 
3692 			case FC_ELS_RING:
3693 				att_bit = HA_R2ATT;
3694 				break;
3695 
3696 			case FC_CT_RING:
3697 				att_bit = HA_R3ATT;
3698 				break;
3699 			}
3700 
3701 			/* Keep polling the chip until our IO is completed */
3702 			(void) drv_getparm(LBOLT, &time);
3703 			while ((time < timeout) &&
3704 			    !(sbp->pkt_flags & PACKET_COMPLETED)) {
3705 				EMLXS_SLI_POLL_INTR(hba, att_bit);
3706 				(void) drv_getparm(LBOLT, &time);
3707 			}
3708 		} else {
3709 			/* Wait for IO completion or timeout */
3710 			mutex_enter(&EMLXS_PKT_LOCK);
3711 			pkt_ret = 0;
3712 			while ((pkt_ret != -1) &&
3713 			    !(sbp->pkt_flags & PACKET_COMPLETED)) {
3714 				pkt_ret =
3715 				    cv_timedwait(&EMLXS_PKT_CV,
3716 				    &EMLXS_PKT_LOCK, timeout);
3717 			}
3718 			mutex_exit(&EMLXS_PKT_LOCK);
3719 		}
3720 
3721 		/* Check if timeout occured. This is not good. */
3722 		/* Something happened to our IO. */
3723 		if (!(sbp->pkt_flags & PACKET_COMPLETED)) {
3724 			/* Force the completion now */
3725 			goto force_it;
3726 		}
3727 	}
3728 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
3729 	emlxs_unswap_pkt(sbp);
3730 #endif	/* EMLXS_MODREV2X */
3731 
3732 	/* Check again if we still own this */
3733 	if ((sbp->pkt_flags & PACKET_VALID) &&
3734 	    !(sbp->pkt_flags & PACKET_ULP_OWNED)) {
3735 		mutex_enter(&sbp->mtx);
3736 		if ((sbp->pkt_flags & PACKET_VALID) &&
3737 		    !(sbp->pkt_flags & PACKET_ULP_OWNED)) {
3738 			sbp->pkt_flags |= PACKET_ULP_OWNED;
3739 		}
3740 		mutex_exit(&sbp->mtx);
3741 	}
3742 
3743 #ifdef ULP_PATCH5
3744 	if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH5) {
3745 		return (FC_FAILURE);
3746 	}
3747 #endif /* ULP_PATCH5 */
3748 
3749 	return (FC_SUCCESS);
3750 
3751 } /* emlxs_pkt_abort() */
3752 
3753 
3754 static void
3755 emlxs_abort_all(emlxs_hba_t *hba, uint32_t *tx, uint32_t *chip)
3756 {
3757 	emlxs_port_t   *port = &PPORT;
3758 	fc_packet_t *pkt;
3759 	emlxs_buf_t *sbp;
3760 	uint32_t i;
3761 	uint32_t flg;
3762 	uint32_t rc;
3763 	uint32_t txcnt;
3764 	uint32_t chipcnt;
3765 
3766 	txcnt = 0;
3767 	chipcnt = 0;
3768 
3769 	mutex_enter(&EMLXS_FCTAB_LOCK);
3770 	for (i = 0; i < hba->max_iotag; i++) {
3771 		sbp = hba->fc_table[i];
3772 		if (sbp == NULL || sbp == STALE_PACKET) {
3773 			continue;
3774 		}
3775 		flg =  (sbp->pkt_flags & PACKET_IN_CHIPQ);
3776 		pkt = PRIV2PKT(sbp);
3777 		mutex_exit(&EMLXS_FCTAB_LOCK);
3778 		rc = emlxs_pkt_abort(port, pkt, 0);
3779 		if (rc == FC_SUCCESS) {
3780 			if (flg) {
3781 				chipcnt++;
3782 			} else {
3783 				txcnt++;
3784 			}
3785 		}
3786 		mutex_enter(&EMLXS_FCTAB_LOCK);
3787 	}
3788 	mutex_exit(&EMLXS_FCTAB_LOCK);
3789 	*tx = txcnt;
3790 	*chip = chipcnt;
3791 } /* emlxs_abort_all() */
3792 
3793 
3794 extern int32_t
3795 emlxs_reset(opaque_t fca_port_handle, uint32_t cmd)
3796 {
3797 	emlxs_port_t	*port = (emlxs_port_t *)fca_port_handle;
3798 	emlxs_hba_t	*hba = HBA;
3799 	int		rval;
3800 	int		ret;
3801 	clock_t		timeout;
3802 
3803 	if (!(port->flag & EMLXS_PORT_BOUND)) {
3804 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3805 		    "fca_reset failed. Port not bound.");
3806 
3807 		return (FC_UNBOUND);
3808 	}
3809 
3810 	switch (cmd) {
3811 	case FC_FCA_LINK_RESET:
3812 
3813 		if (!(hba->flag & FC_ONLINE_MODE) ||
3814 		    (hba->state <= FC_LINK_DOWN)) {
3815 			return (FC_SUCCESS);
3816 		}
3817 
3818 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3819 		    "fca_reset: Resetting Link.");
3820 
3821 		mutex_enter(&EMLXS_LINKUP_LOCK);
3822 		hba->linkup_wait_flag = TRUE;
3823 		mutex_exit(&EMLXS_LINKUP_LOCK);
3824 
3825 		if (emlxs_reset_link(hba, 1, 1)) {
3826 			mutex_enter(&EMLXS_LINKUP_LOCK);
3827 			hba->linkup_wait_flag = FALSE;
3828 			mutex_exit(&EMLXS_LINKUP_LOCK);
3829 
3830 			return (FC_FAILURE);
3831 		}
3832 
3833 		mutex_enter(&EMLXS_LINKUP_LOCK);
3834 		timeout = emlxs_timeout(hba, 60);
3835 		ret = 0;
3836 		while ((ret != -1) && (hba->linkup_wait_flag == TRUE)) {
3837 			ret =
3838 			    cv_timedwait(&EMLXS_LINKUP_CV, &EMLXS_LINKUP_LOCK,
3839 			    timeout);
3840 		}
3841 
3842 		hba->linkup_wait_flag = FALSE;
3843 		mutex_exit(&EMLXS_LINKUP_LOCK);
3844 
3845 		if (ret == -1) {
3846 			return (FC_FAILURE);
3847 		}
3848 
3849 		return (FC_SUCCESS);
3850 
3851 	case FC_FCA_CORE:
3852 #ifdef DUMP_SUPPORT
3853 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3854 		    "fca_reset: Core dump.");
3855 
3856 		/* Schedule a USER dump */
3857 		emlxs_dump(hba, EMLXS_USER_DUMP, 0, 0);
3858 
3859 		/* Wait for dump to complete */
3860 		emlxs_dump_wait(hba);
3861 
3862 		return (FC_SUCCESS);
3863 #endif /* DUMP_SUPPORT */
3864 
3865 	case FC_FCA_RESET:
3866 	case FC_FCA_RESET_CORE:
3867 
3868 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3869 		    "fca_reset: Resetting Adapter.");
3870 
3871 		rval = FC_SUCCESS;
3872 
3873 		if (emlxs_offline(hba) == 0) {
3874 			(void) emlxs_online(hba);
3875 		} else {
3876 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3877 			    "fca_reset: Adapter reset failed. Device busy.");
3878 
3879 			rval = FC_DEVICE_BUSY;
3880 		}
3881 
3882 		return (rval);
3883 
3884 	default:
3885 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3886 		    "fca_reset: Unknown command. cmd=%x", cmd);
3887 
3888 		break;
3889 	}
3890 
3891 	return (FC_FAILURE);
3892 
3893 } /* emlxs_reset() */
3894 
3895 
3896 extern int
3897 emlxs_port_manage(opaque_t fca_port_handle, fc_fca_pm_t *pm)
3898 {
3899 	emlxs_port_t	*port = (emlxs_port_t *)fca_port_handle;
3900 	emlxs_hba_t	*hba = HBA;
3901 	int32_t		ret;
3902 	emlxs_vpd_t	*vpd = &VPD;
3903 
3904 
3905 	ret = FC_SUCCESS;
3906 
3907 	if (!(port->flag & EMLXS_PORT_BOUND)) {
3908 		return (FC_UNBOUND);
3909 	}
3910 
3911 
3912 #ifdef IDLE_TIMER
3913 	emlxs_pm_busy_component(hba);
3914 #endif	/* IDLE_TIMER */
3915 
3916 	switch (pm->pm_cmd_code) {
3917 
3918 	case FC_PORT_GET_FW_REV:
3919 	{
3920 		char buffer[128];
3921 
3922 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3923 		    "fca_port_manage: FC_PORT_GET_FW_REV");
3924 
3925 		(void) sprintf(buffer, "%s %s", hba->model_info.model,
3926 		    vpd->fw_version);
3927 		bzero(pm->pm_data_buf, pm->pm_data_len);
3928 
3929 		if (pm->pm_data_len < strlen(buffer) + 1) {
3930 			ret = FC_NOMEM;
3931 
3932 			break;
3933 		}
3934 
3935 		(void) strcpy(pm->pm_data_buf, buffer);
3936 		break;
3937 	}
3938 
3939 	case FC_PORT_GET_FCODE_REV:
3940 	{
3941 		char buffer[128];
3942 
3943 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3944 		    "fca_port_manage: FC_PORT_GET_FCODE_REV");
3945 
3946 		/* Force update here just to be sure */
3947 		emlxs_get_fcode_version(hba);
3948 
3949 		(void) sprintf(buffer, "%s %s", hba->model_info.model,
3950 		    vpd->fcode_version);
3951 		bzero(pm->pm_data_buf, pm->pm_data_len);
3952 
3953 		if (pm->pm_data_len < strlen(buffer) + 1) {
3954 			ret = FC_NOMEM;
3955 			break;
3956 		}
3957 
3958 		(void) strcpy(pm->pm_data_buf, buffer);
3959 		break;
3960 	}
3961 
3962 	case FC_PORT_GET_DUMP_SIZE:
3963 	{
3964 #ifdef DUMP_SUPPORT
3965 		uint32_t dump_size = 0;
3966 
3967 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3968 		    "fca_port_manage: FC_PORT_GET_DUMP_SIZE");
3969 
3970 		if (pm->pm_data_len < sizeof (uint32_t)) {
3971 			ret = FC_NOMEM;
3972 			break;
3973 		}
3974 
3975 		(void) emlxs_get_dump(hba, NULL, &dump_size);
3976 
3977 		*((uint32_t *)pm->pm_data_buf) = dump_size;
3978 
3979 #else
3980 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3981 		    "fca_port_manage: FC_PORT_GET_DUMP_SIZE unsupported.");
3982 
3983 #endif /* DUMP_SUPPORT */
3984 
3985 		break;
3986 	}
3987 
3988 	case FC_PORT_GET_DUMP:
3989 	{
3990 #ifdef DUMP_SUPPORT
3991 		uint32_t dump_size = 0;
3992 
3993 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3994 		    "fca_port_manage: FC_PORT_GET_DUMP");
3995 
3996 		(void) emlxs_get_dump(hba, NULL, &dump_size);
3997 
3998 		if (pm->pm_data_len < dump_size) {
3999 			ret = FC_NOMEM;
4000 			break;
4001 		}
4002 
4003 		(void) emlxs_get_dump(hba, (uint8_t *)pm->pm_data_buf,
4004 		    (uint32_t *)&dump_size);
4005 #else
4006 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4007 		    "fca_port_manage: FC_PORT_GET_DUMP unsupported.");
4008 
4009 #endif /* DUMP_SUPPORT */
4010 
4011 		break;
4012 	}
4013 
4014 	case FC_PORT_FORCE_DUMP:
4015 	{
4016 #ifdef DUMP_SUPPORT
4017 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4018 		    "fca_port_manage: FC_PORT_FORCE_DUMP");
4019 
4020 		/* Schedule a USER dump */
4021 		emlxs_dump(hba, EMLXS_USER_DUMP, 0, 0);
4022 
4023 		/* Wait for dump to complete */
4024 		emlxs_dump_wait(hba);
4025 #else
4026 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4027 		    "fca_port_manage: FC_PORT_FORCE_DUMP unsupported.");
4028 
4029 #endif /* DUMP_SUPPORT */
4030 		break;
4031 	}
4032 
4033 	case FC_PORT_LINK_STATE:
4034 	{
4035 		uint32_t	*link_state;
4036 
4037 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4038 		    "fca_port_manage: FC_PORT_LINK_STATE");
4039 
4040 		if (pm->pm_stat_len != sizeof (*link_state)) {
4041 			ret = FC_NOMEM;
4042 			break;
4043 		}
4044 
4045 		if (pm->pm_cmd_buf != NULL) {
4046 			/*
4047 			 * Can't look beyond the FCA port.
4048 			 */
4049 			ret = FC_INVALID_REQUEST;
4050 			break;
4051 		}
4052 
4053 		link_state = (uint32_t *)pm->pm_stat_buf;
4054 
4055 		/* Set the state */
4056 		if (hba->state >= FC_LINK_UP) {
4057 			/* Check for loop topology */
4058 			if (hba->topology == TOPOLOGY_LOOP) {
4059 				*link_state = FC_STATE_LOOP;
4060 			} else {
4061 				*link_state = FC_STATE_ONLINE;
4062 			}
4063 
4064 			/* Set the link speed */
4065 			switch (hba->linkspeed) {
4066 			case LA_2GHZ_LINK:
4067 				*link_state |= FC_STATE_2GBIT_SPEED;
4068 				break;
4069 			case LA_4GHZ_LINK:
4070 				*link_state |= FC_STATE_4GBIT_SPEED;
4071 				break;
4072 			case LA_8GHZ_LINK:
4073 				*link_state |= FC_STATE_8GBIT_SPEED;
4074 				break;
4075 			case LA_10GHZ_LINK:
4076 				*link_state |= FC_STATE_10GBIT_SPEED;
4077 				break;
4078 			case LA_1GHZ_LINK:
4079 			default:
4080 				*link_state |= FC_STATE_1GBIT_SPEED;
4081 				break;
4082 			}
4083 		} else {
4084 			*link_state = FC_STATE_OFFLINE;
4085 		}
4086 
4087 		break;
4088 	}
4089 
4090 
4091 	case FC_PORT_ERR_STATS:
4092 	case FC_PORT_RLS:
4093 	{
4094 		MAILBOXQ	*mbq;
4095 		MAILBOX		*mb;
4096 		fc_rls_acc_t	*bp;
4097 
4098 		if (!(hba->flag & FC_ONLINE_MODE)) {
4099 			return (FC_OFFLINE);
4100 		}
4101 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4102 		    "fca_port_manage: FC_PORT_RLS / FC_PORT_ERR_STATS");
4103 
4104 		if (pm->pm_data_len < sizeof (fc_rls_acc_t)) {
4105 			ret = FC_NOMEM;
4106 			break;
4107 		}
4108 
4109 		if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba,
4110 		    MEM_MBOX, 1)) == 0) {
4111 			ret = FC_NOMEM;
4112 			break;
4113 		}
4114 		mb = (MAILBOX *)mbq;
4115 
4116 		emlxs_mb_read_lnk_stat(hba, mbq);
4117 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0)
4118 		    != MBX_SUCCESS) {
4119 			ret = FC_PBUSY;
4120 		} else {
4121 			bp = (fc_rls_acc_t *)pm->pm_data_buf;
4122 
4123 			bp->rls_link_fail = mb->un.varRdLnk.linkFailureCnt;
4124 			bp->rls_sync_loss = mb->un.varRdLnk.lossSyncCnt;
4125 			bp->rls_sig_loss = mb->un.varRdLnk.lossSignalCnt;
4126 			bp->rls_prim_seq_err = mb->un.varRdLnk.primSeqErrCnt;
4127 			bp->rls_invalid_word =
4128 			    mb->un.varRdLnk.invalidXmitWord;
4129 			bp->rls_invalid_crc = mb->un.varRdLnk.crcCnt;
4130 		}
4131 
4132 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
4133 		break;
4134 	}
4135 
4136 	case FC_PORT_DOWNLOAD_FW:
4137 		if (!(hba->flag & FC_ONLINE_MODE)) {
4138 			return (FC_OFFLINE);
4139 		}
4140 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4141 		    "fca_port_manage: FC_PORT_DOWNLOAD_FW");
4142 		ret = emlxs_fw_download(hba, pm->pm_data_buf,
4143 		    pm->pm_data_len, 1);
4144 		break;
4145 
4146 	case FC_PORT_DOWNLOAD_FCODE:
4147 		if (!(hba->flag & FC_ONLINE_MODE)) {
4148 			return (FC_OFFLINE);
4149 		}
4150 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4151 		    "fca_port_manage: FC_PORT_DOWNLOAD_FCODE");
4152 		ret = emlxs_fw_download(hba, pm->pm_data_buf,
4153 		    pm->pm_data_len, 1);
4154 		break;
4155 
4156 	case FC_PORT_DIAG:
4157 	{
4158 		uint32_t errno = 0;
4159 		uint32_t did = 0;
4160 		uint32_t pattern = 0;
4161 
4162 		switch (pm->pm_cmd_flags) {
4163 		case EMLXS_DIAG_BIU:
4164 
4165 			if (!(hba->flag & FC_ONLINE_MODE)) {
4166 				return (FC_OFFLINE);
4167 			}
4168 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4169 			    "fca_port_manage: EMLXS_DIAG_BIU");
4170 
4171 			if (pm->pm_data_len) {
4172 				pattern = *((uint32_t *)pm->pm_data_buf);
4173 			}
4174 
4175 			errno = emlxs_diag_biu_run(hba, pattern);
4176 
4177 			if (pm->pm_stat_len == sizeof (errno)) {
4178 				*(int *)pm->pm_stat_buf = errno;
4179 			}
4180 
4181 			break;
4182 
4183 
4184 		case EMLXS_DIAG_POST:
4185 
4186 			if (!(hba->flag & FC_ONLINE_MODE)) {
4187 				return (FC_OFFLINE);
4188 			}
4189 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4190 			    "fca_port_manage: EMLXS_DIAG_POST");
4191 
4192 			errno = emlxs_diag_post_run(hba);
4193 
4194 			if (pm->pm_stat_len == sizeof (errno)) {
4195 				*(int *)pm->pm_stat_buf = errno;
4196 			}
4197 
4198 			break;
4199 
4200 
4201 		case EMLXS_DIAG_ECHO:
4202 
4203 			if (!(hba->flag & FC_ONLINE_MODE)) {
4204 				return (FC_OFFLINE);
4205 			}
4206 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4207 			    "fca_port_manage: EMLXS_DIAG_ECHO");
4208 
4209 			if (pm->pm_cmd_len != sizeof (uint32_t)) {
4210 				ret = FC_INVALID_REQUEST;
4211 				break;
4212 			}
4213 
4214 			did = *((uint32_t *)pm->pm_cmd_buf);
4215 
4216 			if (pm->pm_data_len) {
4217 				pattern = *((uint32_t *)pm->pm_data_buf);
4218 			}
4219 
4220 			errno = emlxs_diag_echo_run(port, did, pattern);
4221 
4222 			if (pm->pm_stat_len == sizeof (errno)) {
4223 				*(int *)pm->pm_stat_buf = errno;
4224 			}
4225 
4226 			break;
4227 
4228 
4229 		case EMLXS_PARM_GET_NUM:
4230 		{
4231 			uint32_t	*num;
4232 			emlxs_config_t	*cfg;
4233 			uint32_t	i;
4234 			uint32_t	count;
4235 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4236 			    "fca_port_manage: EMLXS_PARM_GET_NUM");
4237 
4238 			if (pm->pm_stat_len < sizeof (uint32_t)) {
4239 				ret = FC_NOMEM;
4240 				break;
4241 			}
4242 
4243 			num = (uint32_t *)pm->pm_stat_buf;
4244 			count = 0;
4245 			cfg = &CFG;
4246 			for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) {
4247 				if (!(cfg->flags & PARM_HIDDEN)) {
4248 					count++;
4249 				}
4250 
4251 			}
4252 
4253 			*num = count;
4254 
4255 			break;
4256 		}
4257 
4258 		case EMLXS_PARM_GET_LIST:
4259 		{
4260 			emlxs_parm_t	*parm;
4261 			emlxs_config_t	*cfg;
4262 			uint32_t	i;
4263 			uint32_t	max_count;
4264 
4265 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4266 			    "fca_port_manage: EMLXS_PARM_GET_LIST");
4267 
4268 			if (pm->pm_stat_len < sizeof (emlxs_parm_t)) {
4269 				ret = FC_NOMEM;
4270 				break;
4271 			}
4272 
4273 			max_count = pm->pm_stat_len / sizeof (emlxs_parm_t);
4274 
4275 			parm = (emlxs_parm_t *)pm->pm_stat_buf;
4276 			cfg = &CFG;
4277 			for (i = 0; i < NUM_CFG_PARAM && max_count; i++,
4278 			    cfg++) {
4279 				if (!(cfg->flags & PARM_HIDDEN)) {
4280 					(void) strcpy(parm->label, cfg->string);
4281 					parm->min = cfg->low;
4282 					parm->max = cfg->hi;
4283 					parm->def = cfg->def;
4284 					parm->current = cfg->current;
4285 					parm->flags = cfg->flags;
4286 					(void) strcpy(parm->help, cfg->help);
4287 					parm++;
4288 					max_count--;
4289 				}
4290 			}
4291 
4292 			break;
4293 		}
4294 
4295 		case EMLXS_PARM_GET:
4296 		{
4297 			emlxs_parm_t	*parm_in;
4298 			emlxs_parm_t	*parm_out;
4299 			emlxs_config_t	*cfg;
4300 			uint32_t	i;
4301 			uint32_t	len;
4302 
4303 			if (pm->pm_cmd_len < sizeof (emlxs_parm_t)) {
4304 				EMLXS_MSGF(EMLXS_CONTEXT,
4305 				    &emlxs_sfs_debug_msg,
4306 				    "fca_port_manage: EMLXS_PARM_GET. "
4307 				    "inbuf too small.");
4308 
4309 				ret = FC_BADCMD;
4310 				break;
4311 			}
4312 
4313 			if (pm->pm_stat_len < sizeof (emlxs_parm_t)) {
4314 				EMLXS_MSGF(EMLXS_CONTEXT,
4315 				    &emlxs_sfs_debug_msg,
4316 				    "fca_port_manage: EMLXS_PARM_GET. "
4317 				    "outbuf too small");
4318 
4319 				ret = FC_BADCMD;
4320 				break;
4321 			}
4322 
4323 			parm_in = (emlxs_parm_t *)pm->pm_cmd_buf;
4324 			parm_out = (emlxs_parm_t *)pm->pm_stat_buf;
4325 			len = strlen(parm_in->label);
4326 			cfg = &CFG;
4327 			ret = FC_BADOBJECT;
4328 
4329 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4330 			    "fca_port_manage: EMLXS_PARM_GET: %s",
4331 			    parm_in->label);
4332 
4333 			for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) {
4334 				if (len == strlen(cfg->string) &&
4335 				    (strcmp(parm_in->label,
4336 				    cfg->string) == 0)) {
4337 					(void) strcpy(parm_out->label,
4338 					    cfg->string);
4339 					parm_out->min = cfg->low;
4340 					parm_out->max = cfg->hi;
4341 					parm_out->def = cfg->def;
4342 					parm_out->current = cfg->current;
4343 					parm_out->flags = cfg->flags;
4344 					(void) strcpy(parm_out->help,
4345 					    cfg->help);
4346 
4347 					ret = FC_SUCCESS;
4348 					break;
4349 				}
4350 			}
4351 
4352 			break;
4353 		}
4354 
4355 		case EMLXS_PARM_SET:
4356 		{
4357 			emlxs_parm_t	*parm_in;
4358 			emlxs_parm_t	*parm_out;
4359 			emlxs_config_t	*cfg;
4360 			uint32_t	i;
4361 			uint32_t	len;
4362 
4363 			if (pm->pm_cmd_len < sizeof (emlxs_parm_t)) {
4364 				EMLXS_MSGF(EMLXS_CONTEXT,
4365 				    &emlxs_sfs_debug_msg,
4366 				    "fca_port_manage: EMLXS_PARM_GET. "
4367 				    "inbuf too small.");
4368 
4369 				ret = FC_BADCMD;
4370 				break;
4371 			}
4372 
4373 			if (pm->pm_stat_len < sizeof (emlxs_parm_t)) {
4374 				EMLXS_MSGF(EMLXS_CONTEXT,
4375 				    &emlxs_sfs_debug_msg,
4376 				    "fca_port_manage: EMLXS_PARM_GET. "
4377 				    "outbuf too small");
4378 				ret = FC_BADCMD;
4379 				break;
4380 			}
4381 
4382 			parm_in = (emlxs_parm_t *)pm->pm_cmd_buf;
4383 			parm_out = (emlxs_parm_t *)pm->pm_stat_buf;
4384 			len = strlen(parm_in->label);
4385 			cfg = &CFG;
4386 			ret = FC_BADOBJECT;
4387 
4388 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4389 			    "fca_port_manage: EMLXS_PARM_SET: %s=0x%x,%d",
4390 			    parm_in->label, parm_in->current,
4391 			    parm_in->current);
4392 
4393 			for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) {
4394 				/* Find matching parameter string */
4395 				if (len == strlen(cfg->string) &&
4396 				    (strcmp(parm_in->label,
4397 				    cfg->string) == 0)) {
4398 					/* Attempt to update parameter */
4399 					if (emlxs_set_parm(hba, i,
4400 					    parm_in->current) == FC_SUCCESS) {
4401 						(void) strcpy(parm_out->label,
4402 						    cfg->string);
4403 						parm_out->min = cfg->low;
4404 						parm_out->max = cfg->hi;
4405 						parm_out->def = cfg->def;
4406 						parm_out->current =
4407 						    cfg->current;
4408 						parm_out->flags = cfg->flags;
4409 						(void) strcpy(parm_out->help,
4410 						    cfg->help);
4411 
4412 						ret = FC_SUCCESS;
4413 					}
4414 
4415 					break;
4416 				}
4417 			}
4418 
4419 			break;
4420 		}
4421 
4422 		case EMLXS_LOG_GET:
4423 		{
4424 			emlxs_log_req_t		*req;
4425 			emlxs_log_resp_t	*resp;
4426 			uint32_t		len;
4427 
4428 			/* Check command size */
4429 			if (pm->pm_cmd_len < sizeof (emlxs_log_req_t)) {
4430 				ret = FC_BADCMD;
4431 				break;
4432 			}
4433 
4434 			/* Get the request */
4435 			req = (emlxs_log_req_t *)pm->pm_cmd_buf;
4436 
4437 			/* Calculate the response length from the request */
4438 			len = sizeof (emlxs_log_resp_t) +
4439 			    (req->count * MAX_LOG_MSG_LENGTH);
4440 
4441 					/* Check the response buffer length */
4442 			if (pm->pm_stat_len < len) {
4443 				ret = FC_BADCMD;
4444 				break;
4445 			}
4446 
4447 			/* Get the response pointer */
4448 			resp = (emlxs_log_resp_t *)pm->pm_stat_buf;
4449 
4450 			/* Get the request log enties */
4451 			(void) emlxs_msg_log_get(hba, req, resp);
4452 
4453 			ret = FC_SUCCESS;
4454 			break;
4455 		}
4456 
4457 		case EMLXS_GET_BOOT_REV:
4458 		{
4459 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4460 			    "fca_port_manage: EMLXS_GET_BOOT_REV");
4461 
4462 			if (pm->pm_stat_len < strlen(vpd->boot_version)) {
4463 				ret = FC_NOMEM;
4464 				break;
4465 			}
4466 
4467 			bzero(pm->pm_stat_buf, pm->pm_stat_len);
4468 			(void) sprintf(pm->pm_stat_buf, "%s %s",
4469 			    hba->model_info.model, vpd->boot_version);
4470 
4471 			break;
4472 		}
4473 
4474 		case EMLXS_DOWNLOAD_BOOT:
4475 			if (!(hba->flag & FC_ONLINE_MODE)) {
4476 				return (FC_OFFLINE);
4477 			}
4478 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4479 			    "fca_port_manage: EMLXS_DOWNLOAD_BOOT");
4480 
4481 			ret = emlxs_fw_download(hba, pm->pm_data_buf,
4482 			    pm->pm_data_len, 1);
4483 			break;
4484 
4485 		case EMLXS_DOWNLOAD_CFL:
4486 		{
4487 			uint32_t *buffer;
4488 			uint32_t region;
4489 			uint32_t length;
4490 
4491 			if (!(hba->flag & FC_ONLINE_MODE)) {
4492 				return (FC_OFFLINE);
4493 			}
4494 
4495 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4496 			    "fca_port_manage: EMLXS_DOWNLOAD_CFL");
4497 
4498 			/* Extract the region number from the first word. */
4499 			buffer = (uint32_t *)pm->pm_data_buf;
4500 			region = *buffer++;
4501 
4502 			/* Adjust the image length for the header word */
4503 			length = pm->pm_data_len - 4;
4504 
4505 			ret =
4506 			    emlxs_cfl_download(hba, region, (caddr_t)buffer,
4507 			    length);
4508 			break;
4509 		}
4510 
4511 		case EMLXS_VPD_GET:
4512 		{
4513 			emlxs_vpd_desc_t	*vpd_out;
4514 
4515 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4516 			    "fca_port_manage: EMLXS_VPD_GET");
4517 
4518 			if (pm->pm_stat_len < sizeof (emlxs_vpd_desc_t)) {
4519 				ret = FC_BADCMD;
4520 				break;
4521 			}
4522 
4523 			vpd_out = (emlxs_vpd_desc_t *)pm->pm_stat_buf;
4524 			bzero(vpd_out, sizeof (emlxs_vpd_desc_t));
4525 
4526 			(void) strncpy(vpd_out->id, vpd->id,
4527 			    sizeof (vpd_out->id));
4528 			(void) strncpy(vpd_out->part_num, vpd->part_num,
4529 			    sizeof (vpd_out->part_num));
4530 			(void) strncpy(vpd_out->eng_change, vpd->eng_change,
4531 			    sizeof (vpd_out->eng_change));
4532 			(void) strncpy(vpd_out->manufacturer, vpd->manufacturer,
4533 			    sizeof (vpd_out->manufacturer));
4534 			(void) strncpy(vpd_out->serial_num, vpd->serial_num,
4535 			    sizeof (vpd_out->serial_num));
4536 			(void) strncpy(vpd_out->model, vpd->model,
4537 			    sizeof (vpd_out->model));
4538 			(void) strncpy(vpd_out->model_desc, vpd->model_desc,
4539 			    sizeof (vpd_out->model_desc));
4540 			(void) strncpy(vpd_out->port_num, vpd->port_num,
4541 			    sizeof (vpd_out->port_num));
4542 			(void) strncpy(vpd_out->prog_types, vpd->prog_types,
4543 			    sizeof (vpd_out->prog_types));
4544 
4545 			ret = FC_SUCCESS;
4546 
4547 			break;
4548 		}
4549 
4550 		case EMLXS_GET_FCIO_REV:
4551 		{
4552 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4553 			    "fca_port_manage: EMLXS_GET_FCIO_REV");
4554 
4555 			if (pm->pm_stat_len < sizeof (uint32_t)) {
4556 				ret = FC_NOMEM;
4557 				break;
4558 			}
4559 
4560 			bzero(pm->pm_stat_buf, pm->pm_stat_len);
4561 			*(uint32_t *)pm->pm_stat_buf = FCIO_REV;
4562 
4563 			break;
4564 		}
4565 
4566 		case EMLXS_GET_DFC_REV:
4567 		{
4568 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4569 			    "fca_port_manage: EMLXS_GET_DFC_REV");
4570 
4571 			if (pm->pm_stat_len < sizeof (uint32_t)) {
4572 				ret = FC_NOMEM;
4573 				break;
4574 			}
4575 
4576 			bzero(pm->pm_stat_buf, pm->pm_stat_len);
4577 			*(uint32_t *)pm->pm_stat_buf = DFC_REV;
4578 
4579 			break;
4580 		}
4581 
4582 		case EMLXS_SET_BOOT_STATE:
4583 		case EMLXS_SET_BOOT_STATE_old:
4584 		{
4585 			uint32_t	state;
4586 
4587 			if (!(hba->flag & FC_ONLINE_MODE)) {
4588 				return (FC_OFFLINE);
4589 			}
4590 			if (pm->pm_cmd_len < sizeof (uint32_t)) {
4591 				EMLXS_MSGF(EMLXS_CONTEXT,
4592 				    &emlxs_sfs_debug_msg,
4593 				    "fca_port_manage: EMLXS_SET_BOOT_STATE");
4594 				ret = FC_BADCMD;
4595 				break;
4596 			}
4597 
4598 			state = *(uint32_t *)pm->pm_cmd_buf;
4599 
4600 			if (state == 0) {
4601 				EMLXS_MSGF(EMLXS_CONTEXT,
4602 				    &emlxs_sfs_debug_msg,
4603 				    "fca_port_manage: EMLXS_SET_BOOT_STATE: "
4604 				    "Disable");
4605 				ret = emlxs_boot_code_disable(hba);
4606 			} else {
4607 				EMLXS_MSGF(EMLXS_CONTEXT,
4608 				    &emlxs_sfs_debug_msg,
4609 				    "fca_port_manage: EMLXS_SET_BOOT_STATE: "
4610 				    "Enable");
4611 				ret = emlxs_boot_code_enable(hba);
4612 			}
4613 
4614 			break;
4615 		}
4616 
4617 		case EMLXS_GET_BOOT_STATE:
4618 		case EMLXS_GET_BOOT_STATE_old:
4619 		{
4620 			if (!(hba->flag & FC_ONLINE_MODE)) {
4621 				return (FC_OFFLINE);
4622 			}
4623 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4624 			    "fca_port_manage: EMLXS_GET_BOOT_STATE");
4625 
4626 			if (pm->pm_stat_len < sizeof (uint32_t)) {
4627 				ret = FC_NOMEM;
4628 				break;
4629 			}
4630 			bzero(pm->pm_stat_buf, pm->pm_stat_len);
4631 
4632 			ret = emlxs_boot_code_state(hba);
4633 
4634 			if (ret == FC_SUCCESS) {
4635 				*(uint32_t *)pm->pm_stat_buf = 1;
4636 				ret = FC_SUCCESS;
4637 			} else if (ret == FC_FAILURE) {
4638 				ret = FC_SUCCESS;
4639 			}
4640 
4641 			break;
4642 		}
4643 
4644 		case EMLXS_HW_ERROR_TEST:
4645 		{
4646 			if (!(hba->flag & FC_ONLINE_MODE)) {
4647 				return (FC_OFFLINE);
4648 			}
4649 
4650 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4651 			    "fca_port_manage: EMLXS_HW_ERROR_TEST");
4652 
4653 			/* Trigger a mailbox timeout */
4654 			hba->mbox_timer = hba->timer_tics;
4655 
4656 			break;
4657 		}
4658 
4659 		case EMLXS_TEST_CODE:
4660 		{
4661 			uint32_t *cmd;
4662 
4663 			if (!(hba->flag & FC_ONLINE_MODE)) {
4664 				return (FC_OFFLINE);
4665 			}
4666 
4667 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4668 			    "fca_port_manage: EMLXS_TEST_CODE");
4669 
4670 			if (pm->pm_cmd_len < sizeof (uint32_t)) {
4671 				EMLXS_MSGF(EMLXS_CONTEXT,
4672 				    &emlxs_sfs_debug_msg,
4673 				    "fca_port_manage: EMLXS_TEST_CODE. "
4674 				    "inbuf to small.");
4675 
4676 				ret = FC_BADCMD;
4677 				break;
4678 			}
4679 
4680 			cmd = (uint32_t *)pm->pm_cmd_buf;
4681 
4682 			ret = emlxs_test(hba, cmd[0],
4683 			    (pm->pm_cmd_len/sizeof (uint32_t)) - 1, &cmd[1]);
4684 
4685 			break;
4686 		}
4687 
4688 		case EMLXS_BAR_IO:
4689 		{
4690 			uint32_t *cmd;
4691 			uint32_t *datap;
4692 			uint32_t offset;
4693 			caddr_t  addr;
4694 			uint32_t i;
4695 			uint32_t tx_cnt;
4696 			uint32_t chip_cnt;
4697 
4698 			cmd = (uint32_t *)pm->pm_cmd_buf;
4699 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4700 			    "fca_port_manage: EMLXS_BAR_IO %x %x %x",
4701 			    cmd[0], cmd[1], cmd[2]);
4702 
4703 			offset = cmd[1];
4704 
4705 			ret = FC_SUCCESS;
4706 
4707 			switch (cmd[0]) {
4708 			case 2: /* bar1read */
4709 				if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
4710 					return (FC_BADCMD);
4711 				}
4712 
4713 				/* Registers in this range are invalid */
4714 				if ((offset >= 0x4C00) && (offset < 0x5000)) {
4715 					return (FC_BADCMD);
4716 				}
4717 				if ((offset >= 0x5800) || (offset & 0x3)) {
4718 					return (FC_BADCMD);
4719 				}
4720 				datap = (uint32_t *)pm->pm_stat_buf;
4721 
4722 				for (i = 0; i < pm->pm_stat_len;
4723 				    i += sizeof (uint32_t)) {
4724 					if ((offset >= 0x4C00) &&
4725 					    (offset < 0x5000)) {
4726 						pm->pm_stat_len = i;
4727 						break;
4728 					}
4729 					if (offset >= 0x5800) {
4730 						pm->pm_stat_len = i;
4731 						break;
4732 					}
4733 					addr = hba->sli.sli4.bar1_addr + offset;
4734 					*datap = READ_BAR1_REG(hba, addr);
4735 					datap++;
4736 					offset += sizeof (uint32_t);
4737 				}
4738 #ifdef FMA_SUPPORT
4739 				/* Access handle validation */
4740 				EMLXS_CHK_ACC_HANDLE(hba,
4741 				    hba->sli.sli4.bar1_acc_handle);
4742 #endif  /* FMA_SUPPORT */
4743 				break;
4744 			case 3: /* bar2read */
4745 				if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
4746 					return (FC_BADCMD);
4747 				}
4748 				if ((offset >= 0x1000) || (offset & 0x3)) {
4749 					return (FC_BADCMD);
4750 				}
4751 				datap = (uint32_t *)pm->pm_stat_buf;
4752 
4753 				for (i = 0; i < pm->pm_stat_len;
4754 				    i += sizeof (uint32_t)) {
4755 					*datap = READ_BAR2_REG(hba,
4756 					    hba->sli.sli4.bar2_addr + offset);
4757 					datap++;
4758 					offset += sizeof (uint32_t);
4759 				}
4760 #ifdef FMA_SUPPORT
4761 				/* Access handle validation */
4762 				EMLXS_CHK_ACC_HANDLE(hba,
4763 				    hba->sli.sli4.bar2_acc_handle);
4764 #endif  /* FMA_SUPPORT */
4765 				break;
4766 			case 4: /* bar1write */
4767 				if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
4768 					return (FC_BADCMD);
4769 				}
4770 				WRITE_BAR1_REG(hba, hba->sli.sli4.bar1_addr +
4771 				    offset, cmd[2]);
4772 #ifdef FMA_SUPPORT
4773 				/* Access handle validation */
4774 				EMLXS_CHK_ACC_HANDLE(hba,
4775 				    hba->sli.sli4.bar1_acc_handle);
4776 #endif  /* FMA_SUPPORT */
4777 				break;
4778 			case 5: /* bar2write */
4779 				if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
4780 					return (FC_BADCMD);
4781 				}
4782 				WRITE_BAR2_REG(hba, hba->sli.sli4.bar2_addr +
4783 				    offset, cmd[2]);
4784 #ifdef FMA_SUPPORT
4785 				/* Access handle validation */
4786 				EMLXS_CHK_ACC_HANDLE(hba,
4787 				    hba->sli.sli4.bar2_acc_handle);
4788 #endif  /* FMA_SUPPORT */
4789 				break;
4790 			case 6: /* dumpbsmbox */
4791 				if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
4792 					return (FC_BADCMD);
4793 				}
4794 				if (offset != 0) {
4795 					return (FC_BADCMD);
4796 				}
4797 
4798 				bcopy((caddr_t)hba->sli.sli4.bootstrapmb.virt,
4799 				    (caddr_t)pm->pm_stat_buf, 256);
4800 				break;
4801 			case 7: /* pciread */
4802 				if ((offset >= 0x200) || (offset & 0x3)) {
4803 					return (FC_BADCMD);
4804 				}
4805 				datap = (uint32_t *)pm->pm_stat_buf;
4806 				for (i = 0; i < pm->pm_stat_len;
4807 				    i += sizeof (uint32_t)) {
4808 					*datap = ddi_get32(hba->pci_acc_handle,
4809 					    (uint32_t *)(hba->pci_addr +
4810 					    offset));
4811 					datap++;
4812 					offset += sizeof (uint32_t);
4813 				}
4814 #ifdef FMA_SUPPORT
4815 				/* Access handle validation */
4816 				EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
4817 #endif  /* FMA_SUPPORT */
4818 				break;
4819 			case 8: /* abortall */
4820 				if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
4821 					return (FC_BADCMD);
4822 				}
4823 				emlxs_abort_all(hba, &tx_cnt, &chip_cnt);
4824 				datap = (uint32_t *)pm->pm_stat_buf;
4825 				*datap++ = tx_cnt;
4826 				*datap = chip_cnt;
4827 				break;
4828 			default:
4829 				ret = FC_BADCMD;
4830 				break;
4831 			}
4832 			break;
4833 		}
4834 
4835 		default:
4836 
4837 			ret = FC_INVALID_REQUEST;
4838 			break;
4839 		}
4840 
4841 		break;
4842 
4843 	}
4844 
4845 	case FC_PORT_INITIALIZE:
4846 		if (!(hba->flag & FC_ONLINE_MODE)) {
4847 			return (FC_OFFLINE);
4848 		}
4849 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4850 		    "fca_port_manage: FC_PORT_INITIALIZE");
4851 		break;
4852 
4853 	case FC_PORT_LOOPBACK:
4854 		if (!(hba->flag & FC_ONLINE_MODE)) {
4855 			return (FC_OFFLINE);
4856 		}
4857 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4858 		    "fca_port_manage: FC_PORT_LOOPBACK");
4859 		break;
4860 
4861 	case FC_PORT_BYPASS:
4862 		if (!(hba->flag & FC_ONLINE_MODE)) {
4863 			return (FC_OFFLINE);
4864 		}
4865 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4866 		    "fca_port_manage: FC_PORT_BYPASS");
4867 		ret = FC_INVALID_REQUEST;
4868 		break;
4869 
4870 	case FC_PORT_UNBYPASS:
4871 		if (!(hba->flag & FC_ONLINE_MODE)) {
4872 			return (FC_OFFLINE);
4873 		}
4874 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4875 		    "fca_port_manage: FC_PORT_UNBYPASS");
4876 		ret = FC_INVALID_REQUEST;
4877 		break;
4878 
4879 	case FC_PORT_GET_NODE_ID:
4880 	{
4881 		fc_rnid_t *rnid;
4882 
4883 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4884 		    "fca_port_manage: FC_PORT_GET_NODE_ID");
4885 
4886 		bzero(pm->pm_data_buf, pm->pm_data_len);
4887 
4888 		if (pm->pm_data_len < sizeof (fc_rnid_t)) {
4889 			ret = FC_NOMEM;
4890 			break;
4891 		}
4892 
4893 		rnid = (fc_rnid_t *)pm->pm_data_buf;
4894 
4895 		(void) sprintf((char *)rnid->global_id,
4896 		    "%01x%01x%02x%02x%02x%02x%02x%02x%02x",
4897 		    hba->wwpn.nameType, hba->wwpn.IEEEextMsn,
4898 		    hba->wwpn.IEEEextLsb, hba->wwpn.IEEE[0],
4899 		    hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], hba->wwpn.IEEE[3],
4900 		    hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
4901 
4902 		rnid->unit_type  = RNID_HBA;
4903 		rnid->port_id    = port->did;
4904 		rnid->ip_version = RNID_IPV4;
4905 
4906 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4907 		    "GET_NODE_ID: wwpn:       %s", rnid->global_id);
4908 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4909 		    "GET_NODE_ID: unit_type:  0x%x", rnid->unit_type);
4910 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4911 		    "GET_NODE_ID: port_id:    0x%x", rnid->port_id);
4912 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4913 		    "GET_NODE_ID: num_attach: %d", rnid->num_attached);
4914 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4915 		    "GET_NODE_ID: ip_version: 0x%x", rnid->ip_version);
4916 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4917 		    "GET_NODE_ID: udp_port:   0x%x", rnid->udp_port);
4918 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4919 		    "GET_NODE_ID: ip_addr:    %s", rnid->ip_addr);
4920 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4921 		    "GET_NODE_ID: resv:       0x%x", rnid->specific_id_resv);
4922 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4923 		    "GET_NODE_ID: topo_flags: 0x%x", rnid->topo_flags);
4924 
4925 		ret = FC_SUCCESS;
4926 		break;
4927 	}
4928 
4929 	case FC_PORT_SET_NODE_ID:
4930 	{
4931 		fc_rnid_t *rnid;
4932 
4933 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4934 		    "fca_port_manage: FC_PORT_SET_NODE_ID");
4935 
4936 		if (pm->pm_data_len < sizeof (fc_rnid_t)) {
4937 			ret = FC_NOMEM;
4938 			break;
4939 		}
4940 
4941 		rnid = (fc_rnid_t *)pm->pm_data_buf;
4942 
4943 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4944 		    "SET_NODE_ID: wwpn:       %s", rnid->global_id);
4945 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4946 		    "SET_NODE_ID: unit_type:  0x%x", rnid->unit_type);
4947 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4948 		    "SET_NODE_ID: port_id:    0x%x", rnid->port_id);
4949 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4950 		    "SET_NODE_ID: num_attach: %d", rnid->num_attached);
4951 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4952 		    "SET_NODE_ID: ip_version: 0x%x", rnid->ip_version);
4953 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4954 		    "SET_NODE_ID: udp_port:   0x%x", rnid->udp_port);
4955 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4956 		    "SET_NODE_ID: ip_addr:    %s", rnid->ip_addr);
4957 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4958 		    "SET_NODE_ID: resv:       0x%x", rnid->specific_id_resv);
4959 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4960 		    "SET_NODE_ID: topo_flags: 0x%x", rnid->topo_flags);
4961 
4962 		ret = FC_SUCCESS;
4963 		break;
4964 	}
4965 
4966 #ifdef S11
4967 	case FC_PORT_GET_P2P_INFO:
4968 	{
4969 		fc_fca_p2p_info_t	*p2p_info;
4970 		NODELIST		*ndlp;
4971 
4972 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4973 		    "fca_port_manage: FC_PORT_GET_P2P_INFO");
4974 
4975 		bzero(pm->pm_data_buf, pm->pm_data_len);
4976 
4977 		if (pm->pm_data_len < sizeof (fc_fca_p2p_info_t)) {
4978 			ret = FC_NOMEM;
4979 			break;
4980 		}
4981 
4982 		p2p_info = (fc_fca_p2p_info_t *)pm->pm_data_buf;
4983 
4984 		if (hba->state >= FC_LINK_UP) {
4985 			if ((hba->topology == TOPOLOGY_PT_PT) &&
4986 			    (hba->flag & FC_PT_TO_PT)) {
4987 				p2p_info->fca_d_id = port->did;
4988 				p2p_info->d_id = port->rdid;
4989 
4990 				ndlp = emlxs_node_find_did(port,
4991 				    port->rdid);
4992 
4993 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4994 				    "FC_PORT_GET_P2P_INFO: fca_d_id: 0x%x, "
4995 				    "d_id: 0x%x, ndlp: 0x%p", port->did,
4996 				    port->rdid, ndlp);
4997 				if (ndlp) {
4998 					bcopy(&ndlp->nlp_portname,
4999 					    (caddr_t)&p2p_info->pwwn,
5000 					    sizeof (la_wwn_t));
5001 					bcopy(&ndlp->nlp_nodename,
5002 					    (caddr_t)&p2p_info->nwwn,
5003 					    sizeof (la_wwn_t));
5004 
5005 					ret = FC_SUCCESS;
5006 					break;
5007 
5008 				}
5009 			}
5010 		}
5011 
5012 		ret = FC_FAILURE;
5013 		break;
5014 	}
5015 #endif
5016 
5017 	default:
5018 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5019 		    "fca_port_manage: code=%x", pm->pm_cmd_code);
5020 		ret = FC_INVALID_REQUEST;
5021 		break;
5022 
5023 	}
5024 
5025 	return (ret);
5026 
5027 } /* emlxs_port_manage() */
5028 
5029 
5030 /*ARGSUSED*/
5031 static uint32_t
5032 emlxs_test(emlxs_hba_t *hba, uint32_t test_code, uint32_t args,
5033     uint32_t *arg)
5034 {
5035 	uint32_t rval = 0;
5036 	emlxs_port_t   *port = &PPORT;
5037 
5038 	switch (test_code) {
5039 #ifdef TEST_SUPPORT
5040 	case 1: /* SCSI underrun */
5041 	{
5042 		hba->underrun_counter = (args)? arg[0]:1;
5043 		break;
5044 	}
5045 #endif /* TEST_SUPPORT */
5046 
5047 	default:
5048 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5049 		    "emlxs_test: Unsupported test code. (0x%x)", test_code);
5050 		rval = FC_INVALID_REQUEST;
5051 	}
5052 
5053 	return (rval);
5054 
5055 } /* emlxs_test() */
5056 
5057 
5058 /*
5059  * Given the device number, return the devinfo pointer or the ddiinst number.
5060  * Note: this routine must be successful on DDI_INFO_DEVT2INSTANCE even
5061  * before attach.
5062  *
5063  * Translate "dev_t" to a pointer to the associated "dev_info_t".
5064  */
5065 /*ARGSUSED*/
5066 static int
5067 emlxs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
5068 {
5069 	emlxs_hba_t	*hba;
5070 	int32_t		ddiinst;
5071 
5072 	ddiinst = getminor((dev_t)arg);
5073 
5074 	switch (infocmd) {
5075 	case DDI_INFO_DEVT2DEVINFO:
5076 		hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5077 		if (hba)
5078 			*result = hba->dip;
5079 		else
5080 			*result = NULL;
5081 		break;
5082 
5083 	case DDI_INFO_DEVT2INSTANCE:
5084 		*result = (void *)((unsigned long)ddiinst);
5085 		break;
5086 
5087 	default:
5088 		return (DDI_FAILURE);
5089 	}
5090 
5091 	return (DDI_SUCCESS);
5092 
5093 } /* emlxs_info() */
5094 
5095 
5096 static int32_t
5097 emlxs_power(dev_info_t *dip, int32_t comp, int32_t level)
5098 {
5099 	emlxs_hba_t	*hba;
5100 	emlxs_port_t	*port;
5101 	int32_t		ddiinst;
5102 	int		rval = DDI_SUCCESS;
5103 
5104 	ddiinst = ddi_get_instance(dip);
5105 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5106 	port = &PPORT;
5107 
5108 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5109 	    "fca_power: comp=%x level=%x", comp, level);
5110 
5111 	if (hba == NULL || comp != EMLXS_PM_ADAPTER) {
5112 		return (DDI_FAILURE);
5113 	}
5114 
5115 	mutex_enter(&hba->pm_lock);
5116 
5117 	/* If we are already at the proper level then return success */
5118 	if (hba->pm_level == level) {
5119 		mutex_exit(&hba->pm_lock);
5120 		return (DDI_SUCCESS);
5121 	}
5122 
5123 	switch (level) {
5124 	case EMLXS_PM_ADAPTER_UP:
5125 
5126 		/*
5127 		 * If we are already in emlxs_attach,
5128 		 * let emlxs_hba_attach take care of things
5129 		 */
5130 		if (hba->pm_state & EMLXS_PM_IN_ATTACH) {
5131 			hba->pm_level = EMLXS_PM_ADAPTER_UP;
5132 			break;
5133 		}
5134 
5135 		/* Check if adapter is suspended */
5136 		if (hba->pm_state & EMLXS_PM_SUSPENDED) {
5137 			hba->pm_level = EMLXS_PM_ADAPTER_UP;
5138 
5139 			/* Try to resume the port */
5140 			rval = emlxs_hba_resume(dip);
5141 
5142 			if (rval != DDI_SUCCESS) {
5143 				hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
5144 			}
5145 			break;
5146 		}
5147 
5148 		/* Set adapter up */
5149 		hba->pm_level = EMLXS_PM_ADAPTER_UP;
5150 		break;
5151 
5152 	case EMLXS_PM_ADAPTER_DOWN:
5153 
5154 
5155 		/*
5156 		 * If we are already in emlxs_detach,
5157 		 * let emlxs_hba_detach take care of things
5158 		 */
5159 		if (hba->pm_state & EMLXS_PM_IN_DETACH) {
5160 			hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
5161 			break;
5162 		}
5163 
5164 		/* Check if adapter is not suspended */
5165 		if (!(hba->pm_state & EMLXS_PM_SUSPENDED)) {
5166 			hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
5167 
5168 			/* Try to suspend the port */
5169 			rval = emlxs_hba_suspend(dip);
5170 
5171 			if (rval != DDI_SUCCESS) {
5172 				hba->pm_level = EMLXS_PM_ADAPTER_UP;
5173 			}
5174 
5175 			break;
5176 		}
5177 
5178 		/* Set adapter down */
5179 		hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
5180 		break;
5181 
5182 	default:
5183 		rval = DDI_FAILURE;
5184 		break;
5185 
5186 	}
5187 
5188 	mutex_exit(&hba->pm_lock);
5189 
5190 	return (rval);
5191 
5192 } /* emlxs_power() */
5193 
5194 
5195 #ifdef EMLXS_I386
5196 #ifdef S11
5197 /*
5198  * quiesce(9E) entry point.
5199  *
5200  * This function is called when the system is single-thread at hight PIL
5201  * with preemption disabled. Therefore, this function must not be blocked.
5202  *
5203  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
5204  * DDI_FAILURE indicates an error condition and should almost never happen.
5205  */
5206 static int
5207 emlxs_quiesce(dev_info_t *dip)
5208 {
5209 	emlxs_hba_t	*hba;
5210 	emlxs_port_t	*port;
5211 	int32_t		ddiinst;
5212 	int		rval = DDI_SUCCESS;
5213 
5214 	ddiinst = ddi_get_instance(dip);
5215 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5216 	port = &PPORT;
5217 
5218 	if (hba == NULL || port == NULL) {
5219 		return (DDI_FAILURE);
5220 	}
5221 
5222 	/* The fourth arg 1 indicates the call is from quiesce */
5223 	if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 1) == 0) {
5224 		return (rval);
5225 	} else {
5226 		return (DDI_FAILURE);
5227 	}
5228 
5229 } /* emlxs_quiesce */
5230 #endif
5231 #endif /* EMLXS_I386 */
5232 
5233 
5234 static int
5235 emlxs_open(dev_t *dev_p, int32_t flag, int32_t otype, cred_t *cred_p)
5236 {
5237 	emlxs_hba_t	*hba;
5238 	emlxs_port_t	*port;
5239 	int		ddiinst;
5240 
5241 	ddiinst = getminor(*dev_p);
5242 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5243 
5244 	if (hba == NULL) {
5245 		return (ENXIO);
5246 	}
5247 
5248 	port = &PPORT;
5249 
5250 	if (hba->pm_state & EMLXS_PM_SUSPENDED) {
5251 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg,
5252 		    "open failed: Driver suspended.");
5253 		return (ENXIO);
5254 	}
5255 
5256 	if (otype != OTYP_CHR) {
5257 		return (EINVAL);
5258 	}
5259 
5260 	if (drv_priv(cred_p)) {
5261 		return (EPERM);
5262 	}
5263 
5264 	mutex_enter(&EMLXS_IOCTL_LOCK);
5265 
5266 	if (hba->ioctl_flags & EMLXS_OPEN_EXCLUSIVE) {
5267 		mutex_exit(&EMLXS_IOCTL_LOCK);
5268 		return (EBUSY);
5269 	}
5270 
5271 	if (flag & FEXCL) {
5272 		if (hba->ioctl_flags & EMLXS_OPEN) {
5273 			mutex_exit(&EMLXS_IOCTL_LOCK);
5274 			return (EBUSY);
5275 		}
5276 
5277 		hba->ioctl_flags |= EMLXS_OPEN_EXCLUSIVE;
5278 	}
5279 
5280 	hba->ioctl_flags |= EMLXS_OPEN;
5281 
5282 	mutex_exit(&EMLXS_IOCTL_LOCK);
5283 
5284 	return (0);
5285 
5286 } /* emlxs_open() */
5287 
5288 
5289 /*ARGSUSED*/
5290 static int
5291 emlxs_close(dev_t dev, int32_t flag, int32_t otype, cred_t *cred_p)
5292 {
5293 	emlxs_hba_t	*hba;
5294 	int		ddiinst;
5295 
5296 	ddiinst = getminor(dev);
5297 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5298 
5299 	if (hba == NULL) {
5300 		return (ENXIO);
5301 	}
5302 
5303 	if (otype != OTYP_CHR) {
5304 		return (EINVAL);
5305 	}
5306 
5307 	mutex_enter(&EMLXS_IOCTL_LOCK);
5308 
5309 	if (!(hba->ioctl_flags & EMLXS_OPEN)) {
5310 		mutex_exit(&EMLXS_IOCTL_LOCK);
5311 		return (ENODEV);
5312 	}
5313 
5314 	hba->ioctl_flags &= ~EMLXS_OPEN;
5315 	hba->ioctl_flags &= ~EMLXS_OPEN_EXCLUSIVE;
5316 
5317 	mutex_exit(&EMLXS_IOCTL_LOCK);
5318 
5319 	return (0);
5320 
5321 } /* emlxs_close() */
5322 
5323 
5324 /*ARGSUSED*/
5325 static int
5326 emlxs_ioctl(dev_t dev, int32_t cmd, intptr_t arg, int32_t mode,
5327     cred_t *cred_p, int32_t *rval_p)
5328 {
5329 	emlxs_hba_t	*hba;
5330 	emlxs_port_t	*port;
5331 	int		rval = 0;	/* return code */
5332 	int		ddiinst;
5333 
5334 	ddiinst = getminor(dev);
5335 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5336 
5337 	if (hba == NULL) {
5338 		return (ENXIO);
5339 	}
5340 
5341 	port = &PPORT;
5342 
5343 	if (hba->pm_state & EMLXS_PM_SUSPENDED) {
5344 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg,
5345 		    "ioctl failed: Driver suspended.");
5346 
5347 		return (ENXIO);
5348 	}
5349 
5350 	mutex_enter(&EMLXS_IOCTL_LOCK);
5351 	if (!(hba->ioctl_flags & EMLXS_OPEN)) {
5352 		mutex_exit(&EMLXS_IOCTL_LOCK);
5353 		return (ENXIO);
5354 	}
5355 	mutex_exit(&EMLXS_IOCTL_LOCK);
5356 
5357 #ifdef IDLE_TIMER
5358 	emlxs_pm_busy_component(hba);
5359 #endif	/* IDLE_TIMER */
5360 
5361 	switch (cmd) {
5362 	case EMLXS_DFC_COMMAND:
5363 		rval = emlxs_dfc_manage(hba, (void *)arg, mode);
5364 		break;
5365 
5366 	default:
5367 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg,
5368 		    "ioctl: Invalid command received. cmd=%x", cmd);
5369 		rval = EINVAL;
5370 	}
5371 
5372 done:
5373 	return (rval);
5374 
5375 } /* emlxs_ioctl() */
5376 
5377 
5378 
5379 /*
5380  *
5381  *	Device Driver Common Routines
5382  *
5383  */
5384 
5385 /* emlxs_pm_lock must be held for this call */
5386 static int
5387 emlxs_hba_resume(dev_info_t *dip)
5388 {
5389 	emlxs_hba_t	*hba;
5390 	emlxs_port_t	*port;
5391 	int		ddiinst;
5392 
5393 	ddiinst = ddi_get_instance(dip);
5394 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5395 	port = &PPORT;
5396 
5397 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_resume_msg, NULL);
5398 
5399 	if (!(hba->pm_state & EMLXS_PM_SUSPENDED)) {
5400 		return (DDI_SUCCESS);
5401 	}
5402 
5403 	hba->pm_state &= ~EMLXS_PM_SUSPENDED;
5404 
5405 	/* Take the adapter online */
5406 	if (emlxs_power_up(hba)) {
5407 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_resume_failed_msg,
5408 		    "Unable to take adapter online.");
5409 
5410 		hba->pm_state |= EMLXS_PM_SUSPENDED;
5411 
5412 		return (DDI_FAILURE);
5413 	}
5414 
5415 	return (DDI_SUCCESS);
5416 
5417 } /* emlxs_hba_resume() */
5418 
5419 
5420 /* emlxs_pm_lock must be held for this call */
5421 static int
5422 emlxs_hba_suspend(dev_info_t *dip)
5423 {
5424 	emlxs_hba_t	*hba;
5425 	emlxs_port_t	*port;
5426 	int		ddiinst;
5427 
5428 	ddiinst = ddi_get_instance(dip);
5429 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5430 	port = &PPORT;
5431 
5432 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_suspend_msg, NULL);
5433 
5434 	if (hba->pm_state & EMLXS_PM_SUSPENDED) {
5435 		return (DDI_SUCCESS);
5436 	}
5437 
5438 	hba->pm_state |= EMLXS_PM_SUSPENDED;
5439 
5440 	/* Take the adapter offline */
5441 	if (emlxs_power_down(hba)) {
5442 		hba->pm_state &= ~EMLXS_PM_SUSPENDED;
5443 
5444 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_suspend_failed_msg,
5445 		    "Unable to take adapter offline.");
5446 
5447 		return (DDI_FAILURE);
5448 	}
5449 
5450 	return (DDI_SUCCESS);
5451 
5452 } /* emlxs_hba_suspend() */
5453 
5454 
5455 
5456 static void
5457 emlxs_lock_init(emlxs_hba_t *hba)
5458 {
5459 	emlxs_port_t	*port = &PPORT;
5460 	int32_t		ddiinst;
5461 	char		buf[64];
5462 	uint32_t	i;
5463 
5464 	ddiinst = hba->ddiinst;
5465 
5466 	/* Initialize the power management */
5467 	(void) sprintf(buf, "%s%d_pm_lock mutex", DRIVER_NAME, ddiinst);
5468 	mutex_init(&hba->pm_lock, buf, MUTEX_DRIVER, (void *)hba->intr_arg);
5469 
5470 	(void) sprintf(buf, "%s%d_adap_lock mutex", DRIVER_NAME, ddiinst);
5471 	mutex_init(&EMLXS_TIMER_LOCK, buf, MUTEX_DRIVER,
5472 	    (void *)hba->intr_arg);
5473 
5474 	(void) sprintf(buf, "%s%d_adap_lock cv", DRIVER_NAME, ddiinst);
5475 	cv_init(&hba->timer_lock_cv, buf, CV_DRIVER, NULL);
5476 
5477 	(void) sprintf(buf, "%s%d_port_lock mutex", DRIVER_NAME, ddiinst);
5478 	mutex_init(&EMLXS_PORT_LOCK, buf, MUTEX_DRIVER,
5479 	    (void *)hba->intr_arg);
5480 
5481 	(void) sprintf(buf, "%s%d_mbox_lock mutex", DRIVER_NAME, ddiinst);
5482 	mutex_init(&EMLXS_MBOX_LOCK, buf, MUTEX_DRIVER,
5483 	    (void *)hba->intr_arg);
5484 
5485 	(void) sprintf(buf, "%s%d_mbox_lock cv", DRIVER_NAME, ddiinst);
5486 	cv_init(&EMLXS_MBOX_CV, buf, CV_DRIVER, NULL);
5487 
5488 	(void) sprintf(buf, "%s%d_linkup_lock mutex", DRIVER_NAME, ddiinst);
5489 	mutex_init(&EMLXS_LINKUP_LOCK, buf, MUTEX_DRIVER,
5490 	    (void *)hba->intr_arg);
5491 
5492 	(void) sprintf(buf, "%s%d_linkup_lock cv", DRIVER_NAME, ddiinst);
5493 	cv_init(&EMLXS_LINKUP_CV, buf, CV_DRIVER, NULL);
5494 
5495 	(void) sprintf(buf, "%s%d_ring_tx_lock mutex", DRIVER_NAME, ddiinst);
5496 	mutex_init(&EMLXS_TX_CHANNEL_LOCK, buf, MUTEX_DRIVER,
5497 	    (void *)hba->intr_arg);
5498 
5499 	for (i = 0; i < MAX_RINGS; i++) {
5500 		(void) sprintf(buf, "%s%d_cmd_ring%d_lock mutex", DRIVER_NAME,
5501 		    ddiinst, i);
5502 		mutex_init(&EMLXS_CMD_RING_LOCK(i), buf, MUTEX_DRIVER,
5503 		    (void *)hba->intr_arg);
5504 	}
5505 
5506 	(void) sprintf(buf, "%s%d_fctab_lock mutex", DRIVER_NAME, ddiinst);
5507 	mutex_init(&EMLXS_FCTAB_LOCK, buf, MUTEX_DRIVER,
5508 	    (void *)hba->intr_arg);
5509 
5510 	(void) sprintf(buf, "%s%d_memget_lock mutex", DRIVER_NAME, ddiinst);
5511 	mutex_init(&EMLXS_MEMGET_LOCK, buf, MUTEX_DRIVER,
5512 	    (void *)hba->intr_arg);
5513 
5514 	(void) sprintf(buf, "%s%d_memput_lock mutex", DRIVER_NAME, ddiinst);
5515 	mutex_init(&EMLXS_MEMPUT_LOCK, buf, MUTEX_DRIVER,
5516 	    (void *)hba->intr_arg);
5517 
5518 	(void) sprintf(buf, "%s%d_ioctl_lock mutex", DRIVER_NAME, ddiinst);
5519 	mutex_init(&EMLXS_IOCTL_LOCK, buf, MUTEX_DRIVER,
5520 	    (void *)hba->intr_arg);
5521 
5522 #ifdef DUMP_SUPPORT
5523 	(void) sprintf(buf, "%s%d_dump mutex", DRIVER_NAME, ddiinst);
5524 	mutex_init(&EMLXS_DUMP_LOCK, buf, MUTEX_DRIVER,
5525 	    (void *)hba->intr_arg);
5526 #endif /* DUMP_SUPPORT */
5527 
5528 	/* Create per port locks */
5529 	for (i = 0; i < MAX_VPORTS; i++) {
5530 		port = &VPORT(i);
5531 
5532 		rw_init(&port->node_rwlock, NULL, RW_DRIVER, NULL);
5533 
5534 		if (i == 0) {
5535 			(void) sprintf(buf, "%s%d_pkt_lock mutex", DRIVER_NAME,
5536 			    ddiinst);
5537 			mutex_init(&EMLXS_PKT_LOCK, buf, MUTEX_DRIVER,
5538 			    (void *)hba->intr_arg);
5539 
5540 			(void) sprintf(buf, "%s%d_pkt_lock cv", DRIVER_NAME,
5541 			    ddiinst);
5542 			cv_init(&EMLXS_PKT_CV, buf, CV_DRIVER, NULL);
5543 
5544 			(void) sprintf(buf, "%s%d_ub_lock mutex", DRIVER_NAME,
5545 			    ddiinst);
5546 			mutex_init(&EMLXS_UB_LOCK, buf, MUTEX_DRIVER,
5547 			    (void *)hba->intr_arg);
5548 		} else {
5549 			(void) sprintf(buf, "%s%d.%d_pkt_lock mutex",
5550 			    DRIVER_NAME, ddiinst, port->vpi);
5551 			mutex_init(&EMLXS_PKT_LOCK, buf, MUTEX_DRIVER,
5552 			    (void *)hba->intr_arg);
5553 
5554 			(void) sprintf(buf, "%s%d.%d_pkt_lock cv", DRIVER_NAME,
5555 			    ddiinst, port->vpi);
5556 			cv_init(&EMLXS_PKT_CV, buf, CV_DRIVER, NULL);
5557 
5558 			(void) sprintf(buf, "%s%d.%d_ub_lock mutex",
5559 			    DRIVER_NAME, ddiinst, port->vpi);
5560 			mutex_init(&EMLXS_UB_LOCK, buf, MUTEX_DRIVER,
5561 			    (void *)hba->intr_arg);
5562 		}
5563 	}
5564 
5565 	return;
5566 
5567 } /* emlxs_lock_init() */
5568 
5569 
5570 
5571 static void
5572 emlxs_lock_destroy(emlxs_hba_t *hba)
5573 {
5574 	emlxs_port_t	*port = &PPORT;
5575 	uint32_t	i;
5576 
5577 	mutex_destroy(&EMLXS_TIMER_LOCK);
5578 	cv_destroy(&hba->timer_lock_cv);
5579 
5580 	mutex_destroy(&EMLXS_PORT_LOCK);
5581 
5582 	cv_destroy(&EMLXS_MBOX_CV);
5583 	cv_destroy(&EMLXS_LINKUP_CV);
5584 
5585 	mutex_destroy(&EMLXS_LINKUP_LOCK);
5586 	mutex_destroy(&EMLXS_MBOX_LOCK);
5587 
5588 	mutex_destroy(&EMLXS_TX_CHANNEL_LOCK);
5589 
5590 	for (i = 0; i < MAX_RINGS; i++) {
5591 		mutex_destroy(&EMLXS_CMD_RING_LOCK(i));
5592 	}
5593 
5594 	mutex_destroy(&EMLXS_FCTAB_LOCK);
5595 	mutex_destroy(&EMLXS_MEMGET_LOCK);
5596 	mutex_destroy(&EMLXS_MEMPUT_LOCK);
5597 	mutex_destroy(&EMLXS_IOCTL_LOCK);
5598 	mutex_destroy(&hba->pm_lock);
5599 
5600 #ifdef DUMP_SUPPORT
5601 	mutex_destroy(&EMLXS_DUMP_LOCK);
5602 #endif /* DUMP_SUPPORT */
5603 
5604 	/* Destroy per port locks */
5605 	for (i = 0; i < MAX_VPORTS; i++) {
5606 		port = &VPORT(i);
5607 		rw_destroy(&port->node_rwlock);
5608 		mutex_destroy(&EMLXS_PKT_LOCK);
5609 		cv_destroy(&EMLXS_PKT_CV);
5610 		mutex_destroy(&EMLXS_UB_LOCK);
5611 	}
5612 
5613 	return;
5614 
5615 } /* emlxs_lock_destroy() */
5616 
5617 
5618 /* init_flag values */
5619 #define	ATTACH_SOFT_STATE	0x00000001
5620 #define	ATTACH_FCA_TRAN		0x00000002
5621 #define	ATTACH_HBA		0x00000004
5622 #define	ATTACH_LOG		0x00000008
5623 #define	ATTACH_MAP_BUS		0x00000010
5624 #define	ATTACH_INTR_INIT	0x00000020
5625 #define	ATTACH_PROP		0x00000040
5626 #define	ATTACH_LOCK		0x00000080
5627 #define	ATTACH_THREAD		0x00000100
5628 #define	ATTACH_INTR_ADD		0x00000200
5629 #define	ATTACH_ONLINE		0x00000400
5630 #define	ATTACH_NODE		0x00000800
5631 #define	ATTACH_FCT		0x00001000
5632 #define	ATTACH_FCA		0x00002000
5633 #define	ATTACH_KSTAT		0x00004000
5634 #define	ATTACH_DHCHAP		0x00008000
5635 #define	ATTACH_FM		0x00010000
5636 #define	ATTACH_MAP_SLI		0x00020000
5637 #define	ATTACH_SPAWN		0x00040000
5638 #define	ATTACH_EVENTS		0x00080000
5639 
5640 static void
5641 emlxs_driver_remove(dev_info_t *dip, uint32_t init_flag, uint32_t failed)
5642 {
5643 	emlxs_hba_t	*hba = NULL;
5644 	int		ddiinst;
5645 
5646 	ddiinst = ddi_get_instance(dip);
5647 
5648 	if (init_flag & ATTACH_HBA) {
5649 		hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5650 
5651 		if (init_flag & ATTACH_SPAWN) {
5652 			emlxs_thread_spawn_destroy(hba);
5653 		}
5654 
5655 		if (init_flag & ATTACH_ONLINE) {
5656 			(void) emlxs_offline(hba);
5657 		}
5658 
5659 		if (init_flag & ATTACH_INTR_ADD) {
5660 			(void) EMLXS_INTR_REMOVE(hba);
5661 		}
5662 #ifdef SFCT_SUPPORT
5663 		if (init_flag & ATTACH_FCT) {
5664 			emlxs_fct_detach(hba);
5665 			emlxs_fct_modclose();
5666 		}
5667 #endif /* SFCT_SUPPORT */
5668 
5669 #ifdef DHCHAP_SUPPORT
5670 		if (init_flag & ATTACH_DHCHAP) {
5671 			emlxs_dhc_detach(hba);
5672 		}
5673 #endif /* DHCHAP_SUPPORT */
5674 
5675 		if (init_flag & ATTACH_KSTAT) {
5676 			kstat_delete(hba->kstat);
5677 		}
5678 
5679 		if (init_flag & ATTACH_FCA) {
5680 			emlxs_fca_detach(hba);
5681 		}
5682 
5683 		if (init_flag & ATTACH_NODE) {
5684 			(void) ddi_remove_minor_node(hba->dip, "devctl");
5685 		}
5686 
5687 		if (init_flag & ATTACH_THREAD) {
5688 			emlxs_thread_destroy(&hba->iodone_thread);
5689 		}
5690 
5691 		if (init_flag & ATTACH_PROP) {
5692 			(void) ddi_prop_remove_all(hba->dip);
5693 		}
5694 
5695 		if (init_flag & ATTACH_LOCK) {
5696 			emlxs_lock_destroy(hba);
5697 		}
5698 
5699 		if (init_flag & ATTACH_INTR_INIT) {
5700 			(void) EMLXS_INTR_UNINIT(hba);
5701 		}
5702 
5703 		if (init_flag & ATTACH_MAP_BUS) {
5704 			emlxs_unmap_bus(hba);
5705 		}
5706 
5707 		if (init_flag & ATTACH_MAP_SLI) {
5708 			EMLXS_SLI_UNMAP_HDW(hba);
5709 		}
5710 
5711 #ifdef FMA_SUPPORT
5712 		if (init_flag & ATTACH_FM) {
5713 			emlxs_fm_fini(hba);
5714 		}
5715 #endif	/* FMA_SUPPORT */
5716 
5717 		if (init_flag & ATTACH_EVENTS) {
5718 			(void) emlxs_event_queue_destroy(hba);
5719 		}
5720 
5721 		if (init_flag & ATTACH_LOG) {
5722 			(void) emlxs_msg_log_destroy(hba);
5723 		}
5724 
5725 		if (init_flag & ATTACH_FCA_TRAN) {
5726 			(void) ddi_set_driver_private(hba->dip, NULL);
5727 			kmem_free(hba->fca_tran, sizeof (fc_fca_tran_t));
5728 			hba->fca_tran = NULL;
5729 		}
5730 
5731 		if (init_flag & ATTACH_HBA) {
5732 			emlxs_device.log[hba->emlxinst] = 0;
5733 			emlxs_device.hba[hba->emlxinst] =
5734 			    (emlxs_hba_t *)((unsigned long)((failed) ? -1 : 0));
5735 #ifdef DUMP_SUPPORT
5736 			emlxs_device.dump_txtfile[hba->emlxinst] = 0;
5737 			emlxs_device.dump_dmpfile[hba->emlxinst] = 0;
5738 			emlxs_device.dump_ceefile[hba->emlxinst] = 0;
5739 #endif /* DUMP_SUPPORT */
5740 
5741 		}
5742 	}
5743 
5744 	if (init_flag & ATTACH_SOFT_STATE) {
5745 		(void) ddi_soft_state_free(emlxs_soft_state, ddiinst);
5746 	}
5747 
5748 	return;
5749 
5750 } /* emlxs_driver_remove() */
5751 
5752 
5753 
5754 /* This determines which ports will be initiator mode */
5755 static void
5756 emlxs_fca_init(emlxs_hba_t *hba)
5757 {
5758 	emlxs_port_t	*port = &PPORT;
5759 	emlxs_port_t	*vport;
5760 	uint32_t	i;
5761 
5762 	if (!hba->ini_mode) {
5763 		return;
5764 	}
5765 	/* Check if SFS present */
5766 	if (((void *)MODSYM(fc_fca_init) == NULL) ||
5767 	    ((void *)MODSYM(fc_fca_attach) == NULL)) {
5768 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
5769 		    "SFS not present. Initiator mode disabled.");
5770 		goto failed;
5771 	}
5772 
5773 	/* Check if our SFS driver interface matches the current SFS stack */
5774 	if (MODSYM(fc_fca_attach) (hba->dip, hba->fca_tran) != DDI_SUCCESS) {
5775 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
5776 		    "SFS/FCA version mismatch. FCA=0x%x",
5777 		    hba->fca_tran->fca_version);
5778 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
5779 		    "SFS present. Initiator mode disabled.");
5780 
5781 		goto failed;
5782 	}
5783 
5784 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
5785 	    "SFS present. Initiator mode enabled.");
5786 
5787 	return;
5788 
5789 failed:
5790 
5791 	hba->ini_mode = 0;
5792 	for (i = 0; i < MAX_VPORTS; i++) {
5793 		vport = &VPORT(i);
5794 		vport->ini_mode = 0;
5795 	}
5796 
5797 	return;
5798 
5799 } /* emlxs_fca_init() */
5800 
5801 
5802 /* This determines which ports will be initiator or target mode */
5803 static void
5804 emlxs_set_mode(emlxs_hba_t *hba)
5805 {
5806 	emlxs_port_t	*port = &PPORT;
5807 	emlxs_port_t	*vport;
5808 	uint32_t	i;
5809 	uint32_t	tgt_mode = 0;
5810 
5811 #ifdef SFCT_SUPPORT
5812 	emlxs_config_t *cfg;
5813 
5814 	cfg = &hba->config[CFG_TARGET_MODE];
5815 	tgt_mode = cfg->current;
5816 
5817 	if (tgt_mode) {
5818 		if (emlxs_fct_modopen() != 0) {
5819 			tgt_mode = 0;
5820 		}
5821 	}
5822 
5823 	port->fct_flags = 0;
5824 #endif /* SFCT_SUPPORT */
5825 
5826 	/* Initialize physical port  */
5827 	if (tgt_mode) {
5828 		hba->tgt_mode  = 1;
5829 		hba->ini_mode  = 0;
5830 
5831 		port->tgt_mode = 1;
5832 		port->ini_mode = 0;
5833 	} else {
5834 		hba->tgt_mode  = 0;
5835 		hba->ini_mode  = 1;
5836 
5837 		port->tgt_mode = 0;
5838 		port->ini_mode = 1;
5839 	}
5840 
5841 	/* Initialize virtual ports */
5842 	/* Virtual ports take on the mode of the parent physical port */
5843 	for (i = 1; i < MAX_VPORTS; i++) {
5844 		vport = &VPORT(i);
5845 
5846 #ifdef SFCT_SUPPORT
5847 		vport->fct_flags = 0;
5848 #endif /* SFCT_SUPPORT */
5849 
5850 		vport->ini_mode = port->ini_mode;
5851 		vport->tgt_mode = port->tgt_mode;
5852 	}
5853 
5854 	/* Check if initiator mode is requested */
5855 	if (hba->ini_mode) {
5856 		emlxs_fca_init(hba);
5857 	} else {
5858 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
5859 		    "Initiator mode not enabled.");
5860 	}
5861 
5862 #ifdef SFCT_SUPPORT
5863 	/* Check if target mode is requested */
5864 	if (hba->tgt_mode) {
5865 		emlxs_fct_init(hba);
5866 	} else {
5867 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
5868 		    "Target mode not enabled.");
5869 	}
5870 #endif /* SFCT_SUPPORT */
5871 
5872 	return;
5873 
5874 } /* emlxs_set_mode() */
5875 
5876 
5877 
5878 static void
5879 emlxs_fca_attach(emlxs_hba_t *hba)
5880 {
5881 	/* Update our transport structure */
5882 	hba->fca_tran->fca_iblock  = (ddi_iblock_cookie_t *)&hba->intr_arg;
5883 	hba->fca_tran->fca_cmd_max = hba->io_throttle;
5884 
5885 #if (EMLXS_MODREV >= EMLXS_MODREV5)
5886 	bcopy((caddr_t)&hba->wwpn, (caddr_t)&hba->fca_tran->fca_perm_pwwn,
5887 	    sizeof (NAME_TYPE));
5888 #endif /* >= EMLXS_MODREV5 */
5889 
5890 	return;
5891 
5892 } /* emlxs_fca_attach() */
5893 
5894 
5895 static void
5896 emlxs_fca_detach(emlxs_hba_t *hba)
5897 {
5898 	uint32_t	i;
5899 	emlxs_port_t	*vport;
5900 
5901 	if (hba->ini_mode) {
5902 		if ((void *)MODSYM(fc_fca_detach) != NULL) {
5903 			MODSYM(fc_fca_detach)(hba->dip);
5904 		}
5905 
5906 		hba->ini_mode = 0;
5907 
5908 		for (i = 0; i < MAX_VPORTS; i++) {
5909 			vport = &VPORT(i);
5910 			vport->ini_mode  = 0;
5911 		}
5912 	}
5913 
5914 	return;
5915 
5916 } /* emlxs_fca_detach() */
5917 
5918 
5919 
5920 static void
5921 emlxs_drv_banner(emlxs_hba_t *hba)
5922 {
5923 	emlxs_port_t	*port = &PPORT;
5924 	uint32_t	i;
5925 	char		sli_mode[16];
5926 	char		msi_mode[16];
5927 	char		npiv_mode[16];
5928 	emlxs_vpd_t	*vpd = &VPD;
5929 	emlxs_config_t	*cfg = &CFG;
5930 	uint8_t		*wwpn;
5931 	uint8_t		*wwnn;
5932 
5933 	/* Display firmware library one time */
5934 	if (emlxs_instance_count == 1) {
5935 		emlxs_fw_show(hba);
5936 	}
5937 
5938 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s (%s)", emlxs_label,
5939 	    emlxs_revision);
5940 
5941 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
5942 	    "%s Dev_id:%x Sub_id:%x Id:%d", hba->model_info.model,
5943 	    hba->model_info.device_id, hba->model_info.ssdid,
5944 	    hba->model_info.id);
5945 
5946 #ifdef EMLXS_I386
5947 
5948 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
5949 	    "Firmware:%s (%s) Boot:%s", vpd->fw_version, vpd->fw_label,
5950 	    vpd->boot_version);
5951 
5952 #else	/* EMLXS_SPARC */
5953 
5954 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
5955 	    "Firmware:%s (%s) Boot:%s Fcode:%s", vpd->fw_version,
5956 	    vpd->fw_label, vpd->boot_version, vpd->fcode_version);
5957 
5958 #endif	/* EMLXS_I386 */
5959 
5960 	if (hba->sli_mode > 3) {
5961 		(void) sprintf(sli_mode, "SLI:%d(%s)", hba->sli_mode,
5962 		    ((hba->flag & FC_FIP_SUPPORTED) ? "FIP" : "nonFIP"));
5963 	} else {
5964 		(void) sprintf(sli_mode, "SLI:%d", hba->sli_mode);
5965 	}
5966 
5967 	(void) strcpy(msi_mode, " INTX:1");
5968 
5969 #ifdef MSI_SUPPORT
5970 	if (hba->intr_flags & EMLXS_MSI_ENABLED) {
5971 		switch (hba->intr_type) {
5972 		case DDI_INTR_TYPE_FIXED:
5973 			(void) strcpy(msi_mode, " MSI:0");
5974 			break;
5975 
5976 		case DDI_INTR_TYPE_MSI:
5977 			(void) sprintf(msi_mode, " MSI:%d", hba->intr_count);
5978 			break;
5979 
5980 		case DDI_INTR_TYPE_MSIX:
5981 			(void) sprintf(msi_mode, " MSIX:%d", hba->intr_count);
5982 			break;
5983 		}
5984 	}
5985 #endif
5986 
5987 	(void) strcpy(npiv_mode, "");
5988 
5989 	if (hba->flag & FC_NPIV_ENABLED) {
5990 		(void) sprintf(npiv_mode, " NPIV:%d", hba->vpi_max+1);
5991 	} else {
5992 		(void) strcpy(npiv_mode, " NPIV:0");
5993 	}
5994 
5995 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s%s%s%s%s",
5996 	    sli_mode, msi_mode, npiv_mode,
5997 	    ((hba->ini_mode)? " FCA":""), ((hba->tgt_mode)? " FCT":""));
5998 
5999 	wwpn = (uint8_t *)&hba->wwpn;
6000 	wwnn = (uint8_t *)&hba->wwnn;
6001 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
6002 	    "WWPN:%02X%02X%02X%02X%02X%02X%02X%02X "
6003 	    "WWNN:%02X%02X%02X%02X%02X%02X%02X%02X",
6004 	    wwpn[0], wwpn[1], wwpn[2], wwpn[3], wwpn[4], wwpn[5], wwpn[6],
6005 	    wwpn[7], wwnn[0], wwnn[1], wwnn[2], wwnn[3], wwnn[4], wwnn[5],
6006 	    wwnn[6], wwnn[7]);
6007 
6008 	for (i = 0; i < MAX_VPORTS; i++) {
6009 		port = &VPORT(i);
6010 
6011 		if (!(port->flag & EMLXS_PORT_CONFIG)) {
6012 			continue;
6013 		}
6014 
6015 		wwpn = (uint8_t *)&port->wwpn;
6016 		wwnn = (uint8_t *)&port->wwnn;
6017 
6018 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
6019 		    "WWPN:%02X%02X%02X%02X%02X%02X%02X%02X "
6020 		    "WWNN:%02X%02X%02X%02X%02X%02X%02X%02X",
6021 		    wwpn[0], wwpn[1], wwpn[2], wwpn[3], wwpn[4], wwpn[5],
6022 		    wwpn[6], wwpn[7], wwnn[0], wwnn[1], wwnn[2], wwnn[3],
6023 		    wwnn[4], wwnn[5], wwnn[6], wwnn[7]);
6024 	}
6025 	port = &PPORT;
6026 
6027 	/*
6028 	 * No dependency for Restricted login parameter.
6029 	 */
6030 	if ((cfg[CFG_VPORT_RESTRICTED].current) && (port->ini_mode)) {
6031 		port->flag |= EMLXS_PORT_RESTRICTED;
6032 	} else {
6033 		port->flag &= ~EMLXS_PORT_RESTRICTED;
6034 	}
6035 
6036 	/*
6037 	 * Announce the device: ddi_report_dev() prints a banner at boot time,
6038 	 * announcing the device pointed to by dip.
6039 	 */
6040 	(void) ddi_report_dev(hba->dip);
6041 
6042 	return;
6043 
6044 } /* emlxs_drv_banner() */
6045 
6046 
6047 extern void
6048 emlxs_get_fcode_version(emlxs_hba_t *hba)
6049 {
6050 	emlxs_vpd_t	*vpd = &VPD;
6051 	char		*prop_str;
6052 	int		status;
6053 
6054 	/* Setup fcode version property */
6055 	prop_str = NULL;
6056 	status =
6057 	    ddi_prop_lookup_string(DDI_DEV_T_ANY, (dev_info_t *)hba->dip, 0,
6058 	    "fcode-version", (char **)&prop_str);
6059 
6060 	if (status == DDI_PROP_SUCCESS) {
6061 		bcopy(prop_str, vpd->fcode_version, strlen(prop_str));
6062 		(void) ddi_prop_free((void *)prop_str);
6063 	} else {
6064 		(void) strcpy(vpd->fcode_version, "none");
6065 	}
6066 
6067 	return;
6068 
6069 } /* emlxs_get_fcode_version() */
6070 
6071 
6072 static int
6073 emlxs_hba_attach(dev_info_t *dip)
6074 {
6075 	emlxs_hba_t	*hba;
6076 	emlxs_port_t	*port;
6077 	emlxs_config_t	*cfg;
6078 	char		*prop_str;
6079 	int		ddiinst;
6080 	int32_t		emlxinst;
6081 	int		status;
6082 	uint32_t	rval;
6083 	uint32_t	init_flag = 0;
6084 	char		local_pm_components[32];
6085 #ifdef EMLXS_I386
6086 	uint32_t	i;
6087 #endif	/* EMLXS_I386 */
6088 
6089 	ddiinst = ddi_get_instance(dip);
6090 	emlxinst = emlxs_add_instance(ddiinst);
6091 
6092 	if (emlxinst >= MAX_FC_BRDS) {
6093 		cmn_err(CE_WARN,
6094 		    "?%s: fca_hba_attach failed. Too many driver ddiinsts. "
6095 		    "inst=%x", DRIVER_NAME, ddiinst);
6096 		return (DDI_FAILURE);
6097 	}
6098 
6099 	if (emlxs_device.hba[emlxinst] == (emlxs_hba_t *)-1) {
6100 		return (DDI_FAILURE);
6101 	}
6102 
6103 	if (emlxs_device.hba[emlxinst]) {
6104 		return (DDI_SUCCESS);
6105 	}
6106 
6107 	/* An adapter can accidentally be plugged into a slave-only PCI slot */
6108 	if (ddi_slaveonly(dip) == DDI_SUCCESS) {
6109 		cmn_err(CE_WARN,
6110 		    "?%s%d: fca_hba_attach failed. Device in slave-only slot.",
6111 		    DRIVER_NAME, ddiinst);
6112 		return (DDI_FAILURE);
6113 	}
6114 
6115 	/* Allocate emlxs_dev_ctl structure. */
6116 	if (ddi_soft_state_zalloc(emlxs_soft_state, ddiinst) != DDI_SUCCESS) {
6117 		cmn_err(CE_WARN,
6118 		    "?%s%d: fca_hba_attach failed. Unable to allocate soft "
6119 		    "state.", DRIVER_NAME, ddiinst);
6120 		return (DDI_FAILURE);
6121 	}
6122 	init_flag |= ATTACH_SOFT_STATE;
6123 
6124 	if ((hba = (emlxs_hba_t *)ddi_get_soft_state(emlxs_soft_state,
6125 	    ddiinst)) == NULL) {
6126 		cmn_err(CE_WARN,
6127 		    "?%s%d: fca_hba_attach failed. Unable to get soft state.",
6128 		    DRIVER_NAME, ddiinst);
6129 		goto failed;
6130 	}
6131 	bzero((char *)hba, sizeof (emlxs_hba_t));
6132 
6133 	emlxs_device.hba[emlxinst] = hba;
6134 	emlxs_device.log[emlxinst] = &hba->log;
6135 
6136 #ifdef DUMP_SUPPORT
6137 	emlxs_device.dump_txtfile[emlxinst] = &hba->dump_txtfile;
6138 	emlxs_device.dump_dmpfile[emlxinst] = &hba->dump_dmpfile;
6139 	emlxs_device.dump_ceefile[emlxinst] = &hba->dump_ceefile;
6140 #endif /* DUMP_SUPPORT */
6141 
6142 	hba->dip = dip;
6143 	hba->emlxinst = emlxinst;
6144 	hba->ddiinst = ddiinst;
6145 	hba->ini_mode = 0;
6146 	hba->tgt_mode = 0;
6147 
6148 	init_flag |= ATTACH_HBA;
6149 
6150 	/* Enable the physical port on this HBA */
6151 	port = &PPORT;
6152 	port->hba = hba;
6153 	port->vpi = 0;
6154 	port->flag |= EMLXS_PORT_ENABLE;
6155 
6156 	/* Allocate a transport structure */
6157 	hba->fca_tran =
6158 	    (fc_fca_tran_t *)kmem_zalloc(sizeof (fc_fca_tran_t), KM_NOSLEEP);
6159 	if (hba->fca_tran == NULL) {
6160 		cmn_err(CE_WARN,
6161 		    "?%s%d: fca_hba_attach failed. Unable to allocate fca_tran "
6162 		    "memory.", DRIVER_NAME, ddiinst);
6163 		goto failed;
6164 	}
6165 	bcopy((caddr_t)&emlxs_fca_tran, (caddr_t)hba->fca_tran,
6166 	    sizeof (fc_fca_tran_t));
6167 
6168 	/* Set the transport structure pointer in our dip */
6169 	/* SFS may panic if we are in target only mode    */
6170 	/* We will update the transport structure later   */
6171 	(void) ddi_set_driver_private(dip, (caddr_t)&emlxs_fca_tran);
6172 	init_flag |= ATTACH_FCA_TRAN;
6173 
6174 	/* Perform driver integrity check */
6175 	rval = emlxs_integrity_check(hba);
6176 	if (rval) {
6177 		cmn_err(CE_WARN,
6178 		    "?%s%d: fca_hba_attach failed. Driver integrity check "
6179 		    "failed. %d error(s) found.", DRIVER_NAME, ddiinst, rval);
6180 		goto failed;
6181 	}
6182 
6183 	cfg = &CFG;
6184 
6185 	bcopy((uint8_t *)&emlxs_cfg, (uint8_t *)cfg, sizeof (emlxs_cfg));
6186 #ifdef MSI_SUPPORT
6187 	if ((void *)&ddi_intr_get_supported_types != NULL) {
6188 		hba->intr_flags |= EMLXS_MSI_ENABLED;
6189 	}
6190 #endif	/* MSI_SUPPORT */
6191 
6192 
6193 	/* Create the msg log file */
6194 	if (emlxs_msg_log_create(hba) == 0) {
6195 		cmn_err(CE_WARN,
6196 		    "?%s%d: fca_hba_attach failed. Unable to create message "
6197 		    "log", DRIVER_NAME, ddiinst);
6198 		goto failed;
6199 
6200 	}
6201 	init_flag |= ATTACH_LOG;
6202 
6203 	/* We can begin to use EMLXS_MSGF from this point on */
6204 
6205 	/* Create the event queue */
6206 	if (emlxs_event_queue_create(hba) == 0) {
6207 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
6208 		    "Unable to create event queue");
6209 
6210 		goto failed;
6211 
6212 	}
6213 	init_flag |= ATTACH_EVENTS;
6214 
6215 	/*
6216 	 * Find the I/O bus type If it is not a SBUS card,
6217 	 * then it is a PCI card. Default is PCI_FC (0).
6218 	 */
6219 	prop_str = NULL;
6220 	status = ddi_prop_lookup_string(DDI_DEV_T_ANY,
6221 	    (dev_info_t *)dip, 0, "name", (char **)&prop_str);
6222 
6223 	if (status == DDI_PROP_SUCCESS) {
6224 		if (strncmp(prop_str, "lpfs", 4) == 0) {
6225 			hba->bus_type = SBUS_FC;
6226 		}
6227 
6228 		(void) ddi_prop_free((void *)prop_str);
6229 	}
6230 
6231 	/*
6232 	 * Copy DDS from the config method and update configuration parameters
6233 	 */
6234 	(void) emlxs_get_props(hba);
6235 
6236 #ifdef FMA_SUPPORT
6237 	hba->fm_caps = cfg[CFG_FM_CAPS].current;
6238 
6239 	emlxs_fm_init(hba);
6240 
6241 	init_flag |= ATTACH_FM;
6242 #endif	/* FMA_SUPPORT */
6243 
6244 	if (emlxs_map_bus(hba)) {
6245 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
6246 		    "Unable to map memory");
6247 		goto failed;
6248 
6249 	}
6250 	init_flag |= ATTACH_MAP_BUS;
6251 
6252 	/* Attempt to identify the adapter */
6253 	rval = emlxs_init_adapter_info(hba);
6254 
6255 	if (rval == 0) {
6256 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
6257 		    "Unable to get adapter info. Id:%d  Device id:0x%x "
6258 		    "Model:%s", hba->model_info.id,
6259 		    hba->model_info.device_id, hba->model_info.model);
6260 		goto failed;
6261 	}
6262 
6263 	/* Check if adapter is not supported */
6264 	if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
6265 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
6266 		    "Unsupported adapter found. Id:%d  Device id:0x%x "
6267 		    "SSDID:0x%x  Model:%s", hba->model_info.id,
6268 		    hba->model_info.device_id,
6269 		    hba->model_info.ssdid, hba->model_info.model);
6270 		goto failed;
6271 	}
6272 	if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
6273 		hba->sli.sli4.mem_sgl_size = MEM_SGL_SIZE;
6274 #ifdef EMLXS_I386
6275 		i = cfg[CFG_MAX_XFER_SIZE].current;
6276 		/* Update SGL size based on max_xfer_size */
6277 		if (i > 516096) {
6278 			/* 516096 = (((2048 / 16) - 2) * 4096) */
6279 			hba->sli.sli4.mem_sgl_size = 4096;
6280 		} else if (i > 253953) {
6281 			/* 253953 = (((1024 / 16) - 2) * 4096) */
6282 			hba->sli.sli4.mem_sgl_size = 2048;
6283 		} else {
6284 			hba->sli.sli4.mem_sgl_size = 1024;
6285 		}
6286 		i = SGL_TO_SGLLEN(hba->sli.sli4.mem_sgl_size);
6287 #endif /* EMLXS_I386 */
6288 	} else {
6289 		hba->sli.sli3.mem_bpl_size = MEM_BPL_SIZE;
6290 #ifdef EMLXS_I386
6291 		i = cfg[CFG_MAX_XFER_SIZE].current;
6292 		/* Update BPL size based on max_xfer_size */
6293 		if (i > 688128) {
6294 			/* 688128 = (((2048 / 12) - 2) * 4096) */
6295 			hba->sli.sli3.mem_bpl_size = 4096;
6296 		} else if (i > 339968) {
6297 			/* 339968 = (((1024 / 12) - 2) * 4096) */
6298 			hba->sli.sli3.mem_bpl_size = 2048;
6299 		} else {
6300 			hba->sli.sli3.mem_bpl_size = 1024;
6301 		}
6302 		i = BPL_TO_SGLLEN(hba->sli.sli3.mem_bpl_size);
6303 #endif /* EMLXS_I386 */
6304 	}
6305 
6306 #ifdef EMLXS_I386
6307 	/* Update dma_attr_sgllen based on BPL size */
6308 	emlxs_dma_attr.dma_attr_sgllen = i;
6309 	emlxs_dma_attr_ro.dma_attr_sgllen = i;
6310 	emlxs_dma_attr_fcip_rsp.dma_attr_sgllen = i;
6311 #endif /* EMLXS_I386 */
6312 
6313 	if (EMLXS_SLI_MAP_HDW(hba)) {
6314 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
6315 		    "Unable to map memory");
6316 		goto failed;
6317 
6318 	}
6319 	init_flag |= ATTACH_MAP_SLI;
6320 
6321 	/* Initialize the interrupts. But don't add them yet */
6322 	status = EMLXS_INTR_INIT(hba, 0);
6323 	if (status != DDI_SUCCESS) {
6324 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
6325 		    "Unable to initalize interrupt(s).");
6326 		goto failed;
6327 
6328 	}
6329 	init_flag |= ATTACH_INTR_INIT;
6330 
6331 	/* Initialize LOCKs */
6332 	emlxs_lock_init(hba);
6333 	init_flag |= ATTACH_LOCK;
6334 
6335 	/* Initialize the power management */
6336 	mutex_enter(&hba->pm_lock);
6337 	hba->pm_state = EMLXS_PM_IN_ATTACH;
6338 	hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
6339 	hba->pm_busy = 0;
6340 #ifdef IDLE_TIMER
6341 	hba->pm_active = 1;
6342 	hba->pm_idle_timer = 0;
6343 #endif	/* IDLE_TIMER */
6344 	mutex_exit(&hba->pm_lock);
6345 
6346 	/* Set the pm component name */
6347 	(void) sprintf(local_pm_components, "NAME=%s%d", DRIVER_NAME,
6348 	    ddiinst);
6349 	emlxs_pm_components[0] = local_pm_components;
6350 
6351 	/* Check if power management support is enabled */
6352 	if (cfg[CFG_PM_SUPPORT].current) {
6353 		if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
6354 		    "pm-components", emlxs_pm_components,
6355 		    sizeof (emlxs_pm_components) /
6356 		    sizeof (emlxs_pm_components[0])) !=
6357 		    DDI_PROP_SUCCESS) {
6358 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
6359 			    "Unable to create pm components.");
6360 			goto failed;
6361 		}
6362 	}
6363 
6364 	/* Needed for suspend and resume support */
6365 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, "pm-hardware-state",
6366 	    "needs-suspend-resume");
6367 	init_flag |= ATTACH_PROP;
6368 
6369 	emlxs_thread_spawn_create(hba);
6370 	init_flag |= ATTACH_SPAWN;
6371 
6372 	emlxs_thread_create(hba, &hba->iodone_thread);
6373 
6374 	init_flag |= ATTACH_THREAD;
6375 
6376 	/* Setup initiator / target ports */
6377 	emlxs_set_mode(hba);
6378 
6379 	/* If driver did not attach to either stack, */
6380 	/* then driver attach failed */
6381 	if (!hba->tgt_mode && !hba->ini_mode) {
6382 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
6383 		    "Driver interfaces not enabled.");
6384 		goto failed;
6385 	}
6386 
6387 	/*
6388 	 * Initialize HBA
6389 	 */
6390 
6391 	/* Set initial state */
6392 	mutex_enter(&EMLXS_PORT_LOCK);
6393 	emlxs_diag_state = DDI_OFFDI;
6394 	hba->flag |= FC_OFFLINE_MODE;
6395 	hba->flag &= ~(FC_ONLINE_MODE | FC_ONLINING_MODE | FC_OFFLINING_MODE);
6396 	mutex_exit(&EMLXS_PORT_LOCK);
6397 
6398 	if (status = emlxs_online(hba)) {
6399 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
6400 		    "Unable to initialize adapter.");
6401 		goto failed;
6402 	}
6403 	init_flag |= ATTACH_ONLINE;
6404 
6405 	/* This is to ensure that the model property is properly set */
6406 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, "model",
6407 	    hba->model_info.model);
6408 
6409 	/* Create the device node. */
6410 	if (ddi_create_minor_node(dip, "devctl", S_IFCHR, ddiinst, NULL, 0) ==
6411 	    DDI_FAILURE) {
6412 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
6413 		    "Unable to create device node.");
6414 		goto failed;
6415 	}
6416 	init_flag |= ATTACH_NODE;
6417 
6418 	/* Attach initiator now */
6419 	/* This must come after emlxs_online() */
6420 	emlxs_fca_attach(hba);
6421 	init_flag |= ATTACH_FCA;
6422 
6423 	/* Initialize kstat information */
6424 	hba->kstat = kstat_create(DRIVER_NAME,
6425 	    ddiinst, "statistics", "controller",
6426 	    KSTAT_TYPE_RAW, sizeof (emlxs_stats_t),
6427 	    KSTAT_FLAG_VIRTUAL);
6428 
6429 	if (hba->kstat == NULL) {
6430 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6431 		    "kstat_create failed.");
6432 	} else {
6433 		hba->kstat->ks_data = (void *)&hba->stats;
6434 		kstat_install(hba->kstat);
6435 		init_flag |= ATTACH_KSTAT;
6436 	}
6437 
6438 #if (EMLXS_MODREV >= EMLXS_MODREV3) && (EMLXS_MODREV <= EMLXS_MODREV4)
6439 	/* Setup virtual port properties */
6440 	emlxs_read_vport_prop(hba);
6441 #endif	/* EMLXS_MODREV3 || EMLXS_MODREV4 */
6442 
6443 
6444 #ifdef DHCHAP_SUPPORT
6445 	emlxs_dhc_attach(hba);
6446 	init_flag |= ATTACH_DHCHAP;
6447 #endif	/* DHCHAP_SUPPORT */
6448 
6449 	/* Display the driver banner now */
6450 	emlxs_drv_banner(hba);
6451 
6452 	/* Raise the power level */
6453 
6454 	/*
6455 	 * This will not execute emlxs_hba_resume because
6456 	 * EMLXS_PM_IN_ATTACH is set
6457 	 */
6458 	if (emlxs_pm_raise_power(dip) != DDI_SUCCESS) {
6459 		/* Set power up anyway. This should not happen! */
6460 		mutex_enter(&hba->pm_lock);
6461 		hba->pm_level = EMLXS_PM_ADAPTER_UP;
6462 		hba->pm_state &= ~EMLXS_PM_IN_ATTACH;
6463 		mutex_exit(&hba->pm_lock);
6464 	} else {
6465 		mutex_enter(&hba->pm_lock);
6466 		hba->pm_state &= ~EMLXS_PM_IN_ATTACH;
6467 		mutex_exit(&hba->pm_lock);
6468 	}
6469 
6470 #ifdef SFCT_SUPPORT
6471 	/* Do this last */
6472 	emlxs_fct_attach(hba);
6473 	init_flag |= ATTACH_FCT;
6474 #endif /* SFCT_SUPPORT */
6475 
6476 	return (DDI_SUCCESS);
6477 
6478 failed:
6479 
6480 	emlxs_driver_remove(dip, init_flag, 1);
6481 
6482 	return (DDI_FAILURE);
6483 
6484 } /* emlxs_hba_attach() */
6485 
6486 
6487 static int
6488 emlxs_hba_detach(dev_info_t *dip)
6489 {
6490 	emlxs_hba_t	*hba;
6491 	emlxs_port_t	*port;
6492 	int		ddiinst;
6493 	int		count;
6494 	uint32_t	init_flag = (uint32_t)-1;
6495 
6496 	ddiinst = ddi_get_instance(dip);
6497 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
6498 	port = &PPORT;
6499 
6500 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg, NULL);
6501 
6502 	mutex_enter(&hba->pm_lock);
6503 	hba->pm_state |= EMLXS_PM_IN_DETACH;
6504 	mutex_exit(&hba->pm_lock);
6505 
6506 	/* Lower the power level */
6507 	/*
6508 	 * This will not suspend the driver since the
6509 	 * EMLXS_PM_IN_DETACH has been set
6510 	 */
6511 	if (emlxs_pm_lower_power(dip) != DDI_SUCCESS) {
6512 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
6513 		    "Unable to lower power.");
6514 
6515 		mutex_enter(&hba->pm_lock);
6516 		hba->pm_state &= ~EMLXS_PM_IN_DETACH;
6517 		mutex_exit(&hba->pm_lock);
6518 
6519 		return (DDI_FAILURE);
6520 	}
6521 
6522 	/* Take the adapter offline first, if not already */
6523 	if (emlxs_offline(hba) != 0) {
6524 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
6525 		    "Unable to take adapter offline.");
6526 
6527 		mutex_enter(&hba->pm_lock);
6528 		hba->pm_state &= ~EMLXS_PM_IN_DETACH;
6529 		mutex_exit(&hba->pm_lock);
6530 
6531 		(void) emlxs_pm_raise_power(dip);
6532 
6533 		return (DDI_FAILURE);
6534 	}
6535 	/* Check ub buffer pools */
6536 	if (port->ub_pool) {
6537 		mutex_enter(&EMLXS_UB_LOCK);
6538 
6539 		/* Wait up to 10 seconds for all ub pools to be freed */
6540 		count = 10 * 2;
6541 		while (port->ub_pool && count) {
6542 			mutex_exit(&EMLXS_UB_LOCK);
6543 			delay(drv_usectohz(500000));	/* half second wait */
6544 			count--;
6545 			mutex_enter(&EMLXS_UB_LOCK);
6546 		}
6547 
6548 		if (port->ub_pool) {
6549 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
6550 			    "fca_unbind_port: Unsolicited buffers still "
6551 			    "active. port=%p. Destroying...", port);
6552 
6553 			/* Destroy all pools */
6554 			while (port->ub_pool) {
6555 				emlxs_ub_destroy(port, port->ub_pool);
6556 			}
6557 		}
6558 
6559 		mutex_exit(&EMLXS_UB_LOCK);
6560 	}
6561 	init_flag &= ~ATTACH_ONLINE;
6562 
6563 	/* Remove the driver instance */
6564 	emlxs_driver_remove(dip, init_flag, 0);
6565 
6566 	return (DDI_SUCCESS);
6567 
6568 } /* emlxs_hba_detach() */
6569 
6570 
6571 extern int
6572 emlxs_map_bus(emlxs_hba_t *hba)
6573 {
6574 	emlxs_port_t		*port = &PPORT;
6575 	dev_info_t		*dip;
6576 	ddi_device_acc_attr_t	dev_attr;
6577 	int			status;
6578 
6579 	dip = (dev_info_t *)hba->dip;
6580 	dev_attr = emlxs_dev_acc_attr;
6581 
6582 	if (hba->bus_type == SBUS_FC) {
6583 		if (hba->pci_acc_handle == 0) {
6584 			status = ddi_regs_map_setup(dip,
6585 			    SBUS_DFLY_PCI_CFG_RINDEX,
6586 			    (caddr_t *)&hba->pci_addr,
6587 			    0, 0, &emlxs_dev_acc_attr, &hba->pci_acc_handle);
6588 			if (status != DDI_SUCCESS) {
6589 				EMLXS_MSGF(EMLXS_CONTEXT,
6590 				    &emlxs_attach_failed_msg,
6591 				    "(SBUS) ddi_regs_map_setup PCI failed. "
6592 				    "status=%x", status);
6593 				goto failed;
6594 			}
6595 		}
6596 
6597 		if (hba->sbus_pci_handle == 0) {
6598 			status = ddi_regs_map_setup(dip,
6599 			    SBUS_TITAN_PCI_CFG_RINDEX,
6600 			    (caddr_t *)&hba->sbus_pci_addr,
6601 			    0, 0, &dev_attr, &hba->sbus_pci_handle);
6602 			if (status != DDI_SUCCESS) {
6603 				EMLXS_MSGF(EMLXS_CONTEXT,
6604 				    &emlxs_attach_failed_msg,
6605 				    "(SBUS) ddi_regs_map_setup TITAN PCI "
6606 				    "failed. status=%x", status);
6607 				goto failed;
6608 			}
6609 		}
6610 
6611 	} else {	/* ****** PCI ****** */
6612 
6613 		if (hba->pci_acc_handle == 0) {
6614 			status = ddi_regs_map_setup(dip,
6615 			    PCI_CFG_RINDEX,
6616 			    (caddr_t *)&hba->pci_addr,
6617 			    0, 0, &emlxs_dev_acc_attr, &hba->pci_acc_handle);
6618 			if (status != DDI_SUCCESS) {
6619 				EMLXS_MSGF(EMLXS_CONTEXT,
6620 				    &emlxs_attach_failed_msg,
6621 				    "(PCI) ddi_regs_map_setup PCI failed. "
6622 				    "status=%x", status);
6623 				goto failed;
6624 			}
6625 		}
6626 #ifdef EMLXS_I386
6627 		/* Setting up PCI configure space */
6628 		(void) ddi_put16(hba->pci_acc_handle,
6629 		    (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER),
6630 		    CMD_CFG_VALUE | CMD_IO_ENBL);
6631 
6632 #ifdef FMA_SUPPORT
6633 		if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
6634 		    != DDI_FM_OK) {
6635 			EMLXS_MSGF(EMLXS_CONTEXT,
6636 			    &emlxs_invalid_access_handle_msg, NULL);
6637 			goto failed;
6638 		}
6639 #endif  /* FMA_SUPPORT */
6640 
6641 #endif	/* EMLXS_I386 */
6642 
6643 	}
6644 	return (0);
6645 
6646 failed:
6647 
6648 	emlxs_unmap_bus(hba);
6649 	return (ENOMEM);
6650 
6651 } /* emlxs_map_bus() */
6652 
6653 
6654 extern void
6655 emlxs_unmap_bus(emlxs_hba_t *hba)
6656 {
6657 	if (hba->pci_acc_handle) {
6658 		(void) ddi_regs_map_free(&hba->pci_acc_handle);
6659 		hba->pci_acc_handle = 0;
6660 	}
6661 
6662 	if (hba->sbus_pci_handle) {
6663 		(void) ddi_regs_map_free(&hba->sbus_pci_handle);
6664 		hba->sbus_pci_handle = 0;
6665 	}
6666 
6667 	return;
6668 
6669 } /* emlxs_unmap_bus() */
6670 
6671 
6672 static int
6673 emlxs_get_props(emlxs_hba_t *hba)
6674 {
6675 	emlxs_config_t	*cfg;
6676 	uint32_t	i;
6677 	char		string[256];
6678 	uint32_t	new_value;
6679 
6680 	/* Initialize each parameter */
6681 	for (i = 0; i < NUM_CFG_PARAM; i++) {
6682 		cfg = &hba->config[i];
6683 
6684 		/* Ensure strings are terminated */
6685 		cfg->string[(EMLXS_CFG_STR_SIZE-1)] = 0;
6686 		cfg->help[(EMLXS_CFG_HELP_SIZE-1)]  = 0;
6687 
6688 		/* Set the current value to the default value */
6689 		new_value = cfg->def;
6690 
6691 		/* First check for the global setting */
6692 		new_value = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY,
6693 		    (void *)hba->dip, DDI_PROP_DONTPASS,
6694 		    cfg->string, new_value);
6695 
6696 		/* Now check for the per adapter ddiinst setting */
6697 		(void) sprintf(string, "%s%d-%s", DRIVER_NAME, hba->ddiinst,
6698 		    cfg->string);
6699 
6700 		new_value = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY,
6701 		    (void *)hba->dip, DDI_PROP_DONTPASS, string, new_value);
6702 
6703 		/* Now check the parameter */
6704 		cfg->current = emlxs_check_parm(hba, i, new_value);
6705 	}
6706 
6707 	return (0);
6708 
6709 } /* emlxs_get_props() */
6710 
6711 
6712 extern uint32_t
6713 emlxs_check_parm(emlxs_hba_t *hba, uint32_t index, uint32_t new_value)
6714 {
6715 	emlxs_port_t	*port = &PPORT;
6716 	uint32_t	i;
6717 	emlxs_config_t	*cfg;
6718 	emlxs_vpd_t	*vpd = &VPD;
6719 
6720 	if (index > NUM_CFG_PARAM) {
6721 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
6722 		    "emlxs_check_parm failed. Invalid index = %d", index);
6723 
6724 		return (new_value);
6725 	}
6726 
6727 	cfg = &hba->config[index];
6728 
6729 	if (new_value > cfg->hi) {
6730 		new_value = cfg->def;
6731 	} else if (new_value < cfg->low) {
6732 		new_value = cfg->def;
6733 	}
6734 
6735 	/* Perform additional checks */
6736 	switch (index) {
6737 	case CFG_NPIV_ENABLE:
6738 		if (hba->tgt_mode) {
6739 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
6740 			    "enable-npiv: Not supported in target mode. "
6741 			    "Disabling.");
6742 
6743 			new_value = 0;
6744 		}
6745 		break;
6746 
6747 #ifdef DHCHAP_SUPPORT
6748 	case CFG_AUTH_ENABLE:
6749 		if (hba->tgt_mode) {
6750 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
6751 			    "enable-auth: Not supported in target mode. "
6752 			    "Disabling.");
6753 
6754 			new_value = 0;
6755 		}
6756 		break;
6757 #endif /* DHCHAP_SUPPORT */
6758 
6759 	case CFG_NUM_NODES:
6760 		switch (new_value) {
6761 		case 1:
6762 		case 2:
6763 			/* Must have at least 3 if not 0 */
6764 			return (3);
6765 
6766 		default:
6767 			break;
6768 		}
6769 		break;
6770 
6771 	case CFG_LINK_SPEED:
6772 		if (vpd->link_speed) {
6773 			switch (new_value) {
6774 			case 0:
6775 				break;
6776 
6777 			case 1:
6778 				if (!(vpd->link_speed & LMT_1GB_CAPABLE)) {
6779 					new_value = 0;
6780 
6781 					EMLXS_MSGF(EMLXS_CONTEXT,
6782 					    &emlxs_init_msg,
6783 					    "link-speed: 1Gb not supported "
6784 					    "by adapter. Switching to auto "
6785 					    "detect.");
6786 				}
6787 				break;
6788 
6789 			case 2:
6790 				if (!(vpd->link_speed & LMT_2GB_CAPABLE)) {
6791 					new_value = 0;
6792 
6793 					EMLXS_MSGF(EMLXS_CONTEXT,
6794 					    &emlxs_init_msg,
6795 					    "link-speed: 2Gb not supported "
6796 					    "by adapter. Switching to auto "
6797 					    "detect.");
6798 				}
6799 				break;
6800 			case 4:
6801 				if (!(vpd->link_speed & LMT_4GB_CAPABLE)) {
6802 					new_value = 0;
6803 
6804 					EMLXS_MSGF(EMLXS_CONTEXT,
6805 					    &emlxs_init_msg,
6806 					    "link-speed: 4Gb not supported "
6807 					    "by adapter. Switching to auto "
6808 					    "detect.");
6809 				}
6810 				break;
6811 
6812 			case 8:
6813 				if (!(vpd->link_speed & LMT_8GB_CAPABLE)) {
6814 					new_value = 0;
6815 
6816 					EMLXS_MSGF(EMLXS_CONTEXT,
6817 					    &emlxs_init_msg,
6818 					    "link-speed: 8Gb not supported "
6819 					    "by adapter. Switching to auto "
6820 					    "detect.");
6821 				}
6822 				break;
6823 
6824 			case 10:
6825 				if (!(vpd->link_speed & LMT_10GB_CAPABLE)) {
6826 					new_value = 0;
6827 
6828 					EMLXS_MSGF(EMLXS_CONTEXT,
6829 					    &emlxs_init_msg,
6830 					    "link-speed: 10Gb not supported "
6831 					    "by adapter. Switching to auto "
6832 					    "detect.");
6833 				}
6834 				break;
6835 
6836 			default:
6837 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
6838 				    "link-speed: Invalid value=%d provided. "
6839 				    "Switching to auto detect.",
6840 				    new_value);
6841 
6842 				new_value = 0;
6843 			}
6844 		} else {	/* Perform basic validity check */
6845 
6846 			/* Perform additional check on link speed */
6847 			switch (new_value) {
6848 			case 0:
6849 			case 1:
6850 			case 2:
6851 			case 4:
6852 			case 8:
6853 			case 10:
6854 				/* link-speed is a valid choice */
6855 				break;
6856 
6857 			default:
6858 				new_value = cfg->def;
6859 			}
6860 		}
6861 		break;
6862 
6863 	case CFG_TOPOLOGY:
6864 		/* Perform additional check on topology */
6865 		switch (new_value) {
6866 		case 0:
6867 		case 2:
6868 		case 4:
6869 		case 6:
6870 			/* topology is a valid choice */
6871 			break;
6872 
6873 		default:
6874 			return (cfg->def);
6875 		}
6876 		break;
6877 
6878 #ifdef DHCHAP_SUPPORT
6879 	case CFG_AUTH_TYPE:
6880 	{
6881 		uint32_t shift;
6882 		uint32_t mask;
6883 
6884 		/* Perform additional check on auth type */
6885 		shift = 12;
6886 		mask  = 0xF000;
6887 		for (i = 0; i < 4; i++) {
6888 			if (((new_value & mask) >> shift) > DFC_AUTH_TYPE_MAX) {
6889 				return (cfg->def);
6890 			}
6891 
6892 			shift -= 4;
6893 			mask >>= 4;
6894 		}
6895 		break;
6896 	}
6897 
6898 	case CFG_AUTH_HASH:
6899 	{
6900 		uint32_t shift;
6901 		uint32_t mask;
6902 
6903 		/* Perform additional check on auth hash */
6904 		shift = 12;
6905 		mask  = 0xF000;
6906 		for (i = 0; i < 4; i++) {
6907 			if (((new_value & mask) >> shift) > DFC_AUTH_HASH_MAX) {
6908 				return (cfg->def);
6909 			}
6910 
6911 			shift -= 4;
6912 			mask >>= 4;
6913 		}
6914 		break;
6915 	}
6916 
6917 	case CFG_AUTH_GROUP:
6918 	{
6919 		uint32_t shift;
6920 		uint32_t mask;
6921 
6922 		/* Perform additional check on auth group */
6923 		shift = 28;
6924 		mask  = 0xF0000000;
6925 		for (i = 0; i < 8; i++) {
6926 			if (((new_value & mask) >> shift) >
6927 			    DFC_AUTH_GROUP_MAX) {
6928 				return (cfg->def);
6929 			}
6930 
6931 			shift -= 4;
6932 			mask >>= 4;
6933 		}
6934 		break;
6935 	}
6936 
6937 	case CFG_AUTH_INTERVAL:
6938 		if (new_value < 10) {
6939 			return (10);
6940 		}
6941 		break;
6942 
6943 
6944 #endif /* DHCHAP_SUPPORT */
6945 
6946 	} /* switch */
6947 
6948 	return (new_value);
6949 
6950 } /* emlxs_check_parm() */
6951 
6952 
6953 extern uint32_t
6954 emlxs_set_parm(emlxs_hba_t *hba, uint32_t index, uint32_t new_value)
6955 {
6956 	emlxs_port_t	*port = &PPORT;
6957 	emlxs_port_t	*vport;
6958 	uint32_t	vpi;
6959 	emlxs_config_t	*cfg;
6960 	uint32_t	old_value;
6961 
6962 	if (index > NUM_CFG_PARAM) {
6963 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
6964 		    "emlxs_set_parm failed. Invalid index = %d", index);
6965 
6966 		return ((uint32_t)FC_FAILURE);
6967 	}
6968 
6969 	cfg = &hba->config[index];
6970 
6971 	if (!(cfg->flags & PARM_DYNAMIC)) {
6972 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
6973 		    "emlxs_set_parm failed. %s is not dynamic.", cfg->string);
6974 
6975 		return ((uint32_t)FC_FAILURE);
6976 	}
6977 
6978 	/* Check new value */
6979 	old_value = new_value;
6980 	new_value = emlxs_check_parm(hba, index, new_value);
6981 
6982 	if (old_value != new_value) {
6983 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
6984 		    "emlxs_set_parm: %s invalid. 0x%x --> 0x%x",
6985 		    cfg->string, old_value, new_value);
6986 	}
6987 
6988 	/* Return now if no actual change */
6989 	if (new_value == cfg->current) {
6990 		return (FC_SUCCESS);
6991 	}
6992 
6993 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
6994 	    "emlxs_set_parm: %s changing. 0x%x --> 0x%x",
6995 	    cfg->string, cfg->current, new_value);
6996 
6997 	old_value = cfg->current;
6998 	cfg->current = new_value;
6999 
7000 	/* React to change if needed */
7001 	switch (index) {
7002 
7003 	case CFG_PCI_MAX_READ:
7004 		/* Update MXR */
7005 		emlxs_pcix_mxr_update(hba, 1);
7006 		break;
7007 
7008 	case CFG_SLI_MODE:
7009 		/* Check SLI mode */
7010 		if ((hba->sli_mode == 3) && (new_value == 2)) {
7011 			/* All vports must be disabled first */
7012 			for (vpi = 1; vpi < MAX_VPORTS; vpi++) {
7013 				vport = &VPORT(vpi);
7014 
7015 				if (vport->flag & EMLXS_PORT_ENABLE) {
7016 					/* Reset current value */
7017 					cfg->current = old_value;
7018 
7019 					EMLXS_MSGF(EMLXS_CONTEXT,
7020 					    &emlxs_sfs_debug_msg,
7021 					    "emlxs_set_parm failed. %s: vpi=%d "
7022 					    "still enabled. Value restored to "
7023 					    "0x%x.", cfg->string, vpi,
7024 					    old_value);
7025 
7026 					return (2);
7027 				}
7028 			}
7029 		}
7030 		break;
7031 
7032 	case CFG_NPIV_ENABLE:
7033 		/* Check if NPIV is being disabled */
7034 		if ((old_value == 1) && (new_value == 0)) {
7035 			/* All vports must be disabled first */
7036 			for (vpi = 1; vpi < MAX_VPORTS; vpi++) {
7037 				vport = &VPORT(vpi);
7038 
7039 				if (vport->flag & EMLXS_PORT_ENABLE) {
7040 					/* Reset current value */
7041 					cfg->current = old_value;
7042 
7043 					EMLXS_MSGF(EMLXS_CONTEXT,
7044 					    &emlxs_sfs_debug_msg,
7045 					    "emlxs_set_parm failed. %s: vpi=%d "
7046 					    "still enabled. Value restored to "
7047 					    "0x%x.", cfg->string, vpi,
7048 					    old_value);
7049 
7050 					return (2);
7051 				}
7052 			}
7053 		}
7054 
7055 		/* Trigger adapter reset */
7056 		/* (void) emlxs_reset(port, FC_FCA_RESET); */
7057 
7058 		break;
7059 
7060 
7061 	case CFG_VPORT_RESTRICTED:
7062 		for (vpi = 0; vpi < MAX_VPORTS; vpi++) {
7063 			vport = &VPORT(vpi);
7064 
7065 			if (!(vport->flag & EMLXS_PORT_CONFIG)) {
7066 				continue;
7067 			}
7068 
7069 			if (vport->options & EMLXS_OPT_RESTRICT_MASK) {
7070 				continue;
7071 			}
7072 
7073 			if (new_value) {
7074 				vport->flag |= EMLXS_PORT_RESTRICTED;
7075 			} else {
7076 				vport->flag &= ~EMLXS_PORT_RESTRICTED;
7077 			}
7078 		}
7079 
7080 		break;
7081 
7082 #ifdef DHCHAP_SUPPORT
7083 	case CFG_AUTH_ENABLE:
7084 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
7085 		break;
7086 
7087 	case CFG_AUTH_TMO:
7088 		hba->auth_cfg.authentication_timeout = cfg->current;
7089 		break;
7090 
7091 	case CFG_AUTH_MODE:
7092 		hba->auth_cfg.authentication_mode = cfg->current;
7093 		break;
7094 
7095 	case CFG_AUTH_BIDIR:
7096 		hba->auth_cfg.bidirectional = cfg->current;
7097 		break;
7098 
7099 	case CFG_AUTH_TYPE:
7100 		hba->auth_cfg.authentication_type_priority[0] =
7101 		    (cfg->current & 0xF000) >> 12;
7102 		hba->auth_cfg.authentication_type_priority[1] =
7103 		    (cfg->current & 0x0F00) >> 8;
7104 		hba->auth_cfg.authentication_type_priority[2] =
7105 		    (cfg->current & 0x00F0) >> 4;
7106 		hba->auth_cfg.authentication_type_priority[3] =
7107 		    (cfg->current & 0x000F);
7108 		break;
7109 
7110 	case CFG_AUTH_HASH:
7111 		hba->auth_cfg.hash_priority[0] =
7112 		    (cfg->current & 0xF000) >> 12;
7113 		hba->auth_cfg.hash_priority[1] = (cfg->current & 0x0F00)>>8;
7114 		hba->auth_cfg.hash_priority[2] = (cfg->current & 0x00F0)>>4;
7115 		hba->auth_cfg.hash_priority[3] = (cfg->current & 0x000F);
7116 		break;
7117 
7118 	case CFG_AUTH_GROUP:
7119 		hba->auth_cfg.dh_group_priority[0] =
7120 		    (cfg->current & 0xF0000000) >> 28;
7121 		hba->auth_cfg.dh_group_priority[1] =
7122 		    (cfg->current & 0x0F000000) >> 24;
7123 		hba->auth_cfg.dh_group_priority[2] =
7124 		    (cfg->current & 0x00F00000) >> 20;
7125 		hba->auth_cfg.dh_group_priority[3] =
7126 		    (cfg->current & 0x000F0000) >> 16;
7127 		hba->auth_cfg.dh_group_priority[4] =
7128 		    (cfg->current & 0x0000F000) >> 12;
7129 		hba->auth_cfg.dh_group_priority[5] =
7130 		    (cfg->current & 0x00000F00) >> 8;
7131 		hba->auth_cfg.dh_group_priority[6] =
7132 		    (cfg->current & 0x000000F0) >> 4;
7133 		hba->auth_cfg.dh_group_priority[7] =
7134 		    (cfg->current & 0x0000000F);
7135 		break;
7136 
7137 	case CFG_AUTH_INTERVAL:
7138 		hba->auth_cfg.reauthenticate_time_interval = cfg->current;
7139 		break;
7140 #endif /* DHCHAP_SUPPORT */
7141 
7142 	}
7143 
7144 	return (FC_SUCCESS);
7145 
7146 } /* emlxs_set_parm() */
7147 
7148 
7149 /*
7150  * emlxs_mem_alloc  OS specific routine for memory allocation / mapping
7151  *
7152  * The buf_info->flags field describes the memory operation requested.
7153  *
7154  * FC_MBUF_PHYSONLY set  requests a supplied virtual address be mapped for DMA
7155  * Virtual address is supplied in buf_info->virt
7156  * DMA mapping flag is in buf_info->align
7157  * (DMA_READ_ONLY, DMA_WRITE_ONLY, DMA_READ_WRITE)
7158  * The mapped physical address is returned buf_info->phys
7159  *
7160  * FC_MBUF_PHYSONLY cleared requests memory be allocated for driver use and
7161  * if FC_MBUF_DMA is set the memory is also mapped for DMA
7162  * The byte alignment of the memory request is supplied in buf_info->align
7163  * The byte size of the memory request is supplied in buf_info->size
7164  * The virtual address is returned buf_info->virt
7165  * The mapped physical address is returned buf_info->phys (for FC_MBUF_DMA)
7166  */
7167 extern uint8_t *
7168 emlxs_mem_alloc(emlxs_hba_t *hba, MBUF_INFO *buf_info)
7169 {
7170 	emlxs_port_t		*port = &PPORT;
7171 	ddi_dma_attr_t		dma_attr;
7172 	ddi_device_acc_attr_t	dev_attr;
7173 	uint_t			cookie_count;
7174 	size_t			dma_reallen;
7175 	ddi_dma_cookie_t	dma_cookie;
7176 	uint_t			dma_flag;
7177 	int			status;
7178 
7179 	dma_attr = emlxs_dma_attr_1sg;
7180 	dev_attr = emlxs_data_acc_attr;
7181 
7182 	if (buf_info->flags & FC_MBUF_SNGLSG) {
7183 		dma_attr.dma_attr_sgllen = 1;
7184 	}
7185 
7186 	if (buf_info->flags & FC_MBUF_DMA32) {
7187 		dma_attr.dma_attr_addr_hi = (uint64_t)0xffffffff;
7188 	}
7189 
7190 	if (buf_info->flags & FC_MBUF_PHYSONLY) {
7191 
7192 		if (buf_info->virt == 0) {
7193 			goto done;
7194 		}
7195 
7196 		/*
7197 		 * Allocate the DMA handle for this DMA object
7198 		 */
7199 		status = ddi_dma_alloc_handle((void *)hba->dip,
7200 		    &dma_attr, DDI_DMA_DONTWAIT,
7201 		    NULL, (ddi_dma_handle_t *)&buf_info->dma_handle);
7202 		if (status != DDI_SUCCESS) {
7203 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
7204 			    "ddi_dma_alloc_handle failed: size=%x align=%x "
7205 			    "flags=%x", buf_info->size, buf_info->align,
7206 			    buf_info->flags);
7207 
7208 			buf_info->phys = 0;
7209 			buf_info->dma_handle = 0;
7210 			goto done;
7211 		}
7212 
7213 		switch (buf_info->align) {
7214 		case DMA_READ_WRITE:
7215 			dma_flag = (DDI_DMA_RDWR | DDI_DMA_CONSISTENT);
7216 			break;
7217 		case DMA_READ_ONLY:
7218 			dma_flag = (DDI_DMA_READ | DDI_DMA_CONSISTENT);
7219 			break;
7220 		case DMA_WRITE_ONLY:
7221 			dma_flag = (DDI_DMA_WRITE | DDI_DMA_CONSISTENT);
7222 			break;
7223 		}
7224 
7225 		/* Map this page of memory */
7226 		status = ddi_dma_addr_bind_handle(
7227 		    (ddi_dma_handle_t)buf_info->dma_handle, NULL,
7228 		    (caddr_t)buf_info->virt, (size_t)buf_info->size,
7229 		    dma_flag, DDI_DMA_DONTWAIT, NULL, &dma_cookie,
7230 		    &cookie_count);
7231 
7232 		if (status != DDI_DMA_MAPPED || (cookie_count > 1)) {
7233 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
7234 			    "ddi_dma_addr_bind_handle failed: status=%x "
7235 			    "count=%x flags=%x", status, cookie_count,
7236 			    buf_info->flags);
7237 
7238 			(void) ddi_dma_free_handle(
7239 			    (ddi_dma_handle_t *)&buf_info->dma_handle);
7240 			buf_info->phys = 0;
7241 			buf_info->dma_handle = 0;
7242 			goto done;
7243 		}
7244 
7245 		if (hba->bus_type == SBUS_FC) {
7246 
7247 			int32_t burstsizes_limit = 0xff;
7248 			int32_t ret_burst;
7249 
7250 			ret_burst = ddi_dma_burstsizes(
7251 			    buf_info->dma_handle) & burstsizes_limit;
7252 			if (ddi_dma_set_sbus64(buf_info->dma_handle,
7253 			    ret_burst) == DDI_FAILURE) {
7254 				EMLXS_MSGF(EMLXS_CONTEXT,
7255 				    &emlxs_mem_alloc_failed_msg,
7256 				    "ddi_dma_set_sbus64 failed.");
7257 			}
7258 		}
7259 
7260 		/* Save Physical address */
7261 		buf_info->phys = dma_cookie.dmac_laddress;
7262 
7263 		/*
7264 		 * Just to be sure, let's add this
7265 		 */
7266 		EMLXS_MPDATA_SYNC((ddi_dma_handle_t)buf_info->dma_handle,
7267 		    (off_t)0, (size_t)buf_info->size, DDI_DMA_SYNC_FORDEV);
7268 
7269 	} else if (buf_info->flags & (FC_MBUF_DMA|FC_MBUF_DMA32)) {
7270 
7271 		dma_attr.dma_attr_align = buf_info->align;
7272 
7273 		/*
7274 		 * Allocate the DMA handle for this DMA object
7275 		 */
7276 		status = ddi_dma_alloc_handle((void *)hba->dip, &dma_attr,
7277 		    DDI_DMA_DONTWAIT, NULL,
7278 		    (ddi_dma_handle_t *)&buf_info->dma_handle);
7279 		if (status != DDI_SUCCESS) {
7280 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
7281 			    "ddi_dma_alloc_handle failed: size=%x align=%x "
7282 			    "flags=%x", buf_info->size, buf_info->align,
7283 			    buf_info->flags);
7284 
7285 			buf_info->virt = 0;
7286 			buf_info->phys = 0;
7287 			buf_info->data_handle = 0;
7288 			buf_info->dma_handle = 0;
7289 			goto done;
7290 		}
7291 
7292 		status = ddi_dma_mem_alloc(
7293 		    (ddi_dma_handle_t)buf_info->dma_handle,
7294 		    (size_t)buf_info->size, &dev_attr, DDI_DMA_CONSISTENT,
7295 		    DDI_DMA_DONTWAIT, NULL, (caddr_t *)&buf_info->virt,
7296 		    &dma_reallen, (ddi_acc_handle_t *)&buf_info->data_handle);
7297 
7298 		if ((status != DDI_SUCCESS) || (buf_info->size > dma_reallen)) {
7299 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
7300 			    "ddi_dma_mem_alloc failed: size=%x align=%x "
7301 			    "flags=%x", buf_info->size, buf_info->align,
7302 			    buf_info->flags);
7303 
7304 			(void) ddi_dma_free_handle(
7305 			    (ddi_dma_handle_t *)&buf_info->dma_handle);
7306 
7307 			buf_info->virt = 0;
7308 			buf_info->phys = 0;
7309 			buf_info->data_handle = 0;
7310 			buf_info->dma_handle = 0;
7311 			goto done;
7312 		}
7313 
7314 		/* Map this page of memory */
7315 		status = ddi_dma_addr_bind_handle(
7316 		    (ddi_dma_handle_t)buf_info->dma_handle, NULL,
7317 		    (caddr_t)buf_info->virt, (size_t)buf_info->size,
7318 		    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
7319 		    &dma_cookie, &cookie_count);
7320 
7321 		if (status != DDI_DMA_MAPPED || (cookie_count > 1)) {
7322 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
7323 			    "ddi_dma_addr_bind_handle failed: status=%x "
7324 			    "count=%d size=%x align=%x flags=%x", status,
7325 			    cookie_count, buf_info->size, buf_info->align,
7326 			    buf_info->flags);
7327 
7328 			(void) ddi_dma_mem_free(
7329 			    (ddi_acc_handle_t *)&buf_info->data_handle);
7330 			(void) ddi_dma_free_handle(
7331 			    (ddi_dma_handle_t *)&buf_info->dma_handle);
7332 
7333 			buf_info->virt = 0;
7334 			buf_info->phys = 0;
7335 			buf_info->dma_handle = 0;
7336 			buf_info->data_handle = 0;
7337 			goto done;
7338 		}
7339 
7340 		if (hba->bus_type == SBUS_FC) {
7341 			int32_t burstsizes_limit = 0xff;
7342 			int32_t ret_burst;
7343 
7344 			ret_burst =
7345 			    ddi_dma_burstsizes(buf_info->
7346 			    dma_handle) & burstsizes_limit;
7347 			if (ddi_dma_set_sbus64(buf_info->dma_handle,
7348 			    ret_burst) == DDI_FAILURE) {
7349 				EMLXS_MSGF(EMLXS_CONTEXT,
7350 				    &emlxs_mem_alloc_failed_msg,
7351 				    "ddi_dma_set_sbus64 failed.");
7352 			}
7353 		}
7354 
7355 		/* Save Physical address */
7356 		buf_info->phys = dma_cookie.dmac_laddress;
7357 
7358 		/* Just to be sure, let's add this */
7359 		EMLXS_MPDATA_SYNC((ddi_dma_handle_t)buf_info->dma_handle,
7360 		    (off_t)0, (size_t)buf_info->size, DDI_DMA_SYNC_FORDEV);
7361 
7362 	} else {	/* allocate virtual memory */
7363 
7364 		buf_info->virt =
7365 		    (uint32_t *)kmem_zalloc((size_t)buf_info->size,
7366 		    KM_NOSLEEP);
7367 		buf_info->phys = 0;
7368 		buf_info->data_handle = 0;
7369 		buf_info->dma_handle = 0;
7370 
7371 		if (buf_info->virt == (uint32_t *)0) {
7372 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
7373 			    "size=%x flags=%x", buf_info->size,
7374 			    buf_info->flags);
7375 		}
7376 
7377 	}
7378 
7379 done:
7380 
7381 	return ((uint8_t *)buf_info->virt);
7382 
7383 } /* emlxs_mem_alloc() */
7384 
7385 
7386 
7387 /*
7388  * emlxs_mem_free:
7389  *
7390  * OS specific routine for memory de-allocation / unmapping
7391  *
7392  * The buf_info->flags field describes the memory operation requested.
7393  *
7394  * FC_MBUF_PHYSONLY set  requests a supplied virtual address be unmapped
7395  * for DMA, but not freed. The mapped physical address to be unmapped is in
7396  * buf_info->phys
7397  *
7398  * FC_MBUF_PHYSONLY cleared requests memory be freed and unmapped for DMA only
7399  * if FC_MBUF_DMA is set. The mapped physical address to be unmapped is in
7400  * buf_info->phys. The virtual address to be freed is in buf_info->virt
7401  */
7402 /*ARGSUSED*/
7403 extern void
7404 emlxs_mem_free(emlxs_hba_t *hba, MBUF_INFO *buf_info)
7405 {
7406 	if (buf_info->flags & FC_MBUF_PHYSONLY) {
7407 
7408 		if (buf_info->dma_handle) {
7409 			(void) ddi_dma_unbind_handle(buf_info->dma_handle);
7410 			(void) ddi_dma_free_handle(
7411 			    (ddi_dma_handle_t *)&buf_info->dma_handle);
7412 			buf_info->dma_handle = NULL;
7413 		}
7414 
7415 	} else if (buf_info->flags & (FC_MBUF_DMA|FC_MBUF_DMA32)) {
7416 
7417 		if (buf_info->dma_handle) {
7418 			(void) ddi_dma_unbind_handle(buf_info->dma_handle);
7419 			(void) ddi_dma_mem_free(
7420 			    (ddi_acc_handle_t *)&buf_info->data_handle);
7421 			(void) ddi_dma_free_handle(
7422 			    (ddi_dma_handle_t *)&buf_info->dma_handle);
7423 			buf_info->dma_handle = NULL;
7424 			buf_info->data_handle = NULL;
7425 		}
7426 
7427 	} else {	/* allocate virtual memory */
7428 
7429 		if (buf_info->virt) {
7430 			kmem_free(buf_info->virt, (size_t)buf_info->size);
7431 			buf_info->virt = NULL;
7432 		}
7433 	}
7434 
7435 } /* emlxs_mem_free() */
7436 
7437 
7438 /*
7439  * A channel has a association with a msi id.
7440  * One msi id could be associated with multiple channels.
7441  */
7442 static int
7443 emlxs_next_chan(emlxs_hba_t *hba, int msi_id)
7444 {
7445 	emlxs_config_t *cfg = &CFG;
7446 	EQ_DESC_t *eqp;
7447 	int chan;
7448 	int num_wq;
7449 
7450 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
7451 		/* For SLI4 round robin all WQs associated with the msi_id */
7452 		eqp = &hba->sli.sli4.eq[msi_id];
7453 		num_wq = cfg[CFG_NUM_WQ].current;
7454 
7455 		mutex_enter(&eqp->lastwq_lock);
7456 		chan = eqp->lastwq;
7457 		eqp->lastwq++;
7458 		if (eqp->lastwq >= ((msi_id + 1) * num_wq)) {
7459 			eqp->lastwq -= num_wq;
7460 		}
7461 		mutex_exit(&eqp->lastwq_lock);
7462 
7463 	} else {
7464 		chan = hba->channel_fcp;
7465 	}
7466 	return (chan);
7467 }
7468 
7469 
7470 static int
7471 emlxs_select_fcp_channel(emlxs_hba_t *hba, NODELIST *ndlp, int reset)
7472 {
7473 	int		channel;
7474 
7475 
7476 	/* IO to FCP2 device or a device reset always use fcp channel */
7477 	if ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) || reset) {
7478 		return (hba->channel_fcp);
7479 	}
7480 
7481 	channel = emlxs_next_chan(hba, 0);
7482 
7483 
7484 	/* If channel is closed, then try fcp channel */
7485 	if (ndlp->nlp_flag[channel] & NLP_CLOSED) {
7486 		channel = hba->channel_fcp;
7487 	}
7488 	return (channel);
7489 
7490 }
7491 
7492 static int32_t
7493 emlxs_fast_target_reset(emlxs_port_t *port, emlxs_buf_t *sbp, NODELIST *ndlp)
7494 {
7495 	emlxs_hba_t	*hba = HBA;
7496 	fc_packet_t	*pkt;
7497 	emlxs_config_t	*cfg;
7498 	MAILBOXQ	*mbq;
7499 	MAILBOX		*mb;
7500 	uint32_t	rc;
7501 
7502 	/*
7503 	 * This routine provides a alternative target reset provessing
7504 	 * method. Instead of sending an actual target reset to the
7505 	 * NPort, we will first unreg the login to that NPort. This
7506 	 * will cause all the outstanding IOs the quickly complete with
7507 	 * a NO RPI local error. Next we will force the ULP to relogin
7508 	 * to the NPort by sending an RSCN (for that NPort) to the
7509 	 * upper layer. This method should result in a fast target
7510 	 * reset, as far as IOs completing; however, since an actual
7511 	 * target reset is not sent to the NPort, it is not 100%
7512 	 * compatable. Things like reservations will not be broken.
7513 	 * By default this option is DISABLED, and its only enabled thru
7514 	 * a hidden configuration parameter (fast-tgt-reset).
7515 	 */
7516 	rc = FC_TRAN_BUSY;
7517 	pkt = PRIV2PKT(sbp);
7518 	cfg = &CFG;
7519 
7520 	if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
7521 		/* issue the mbox cmd to the sli */
7522 		mb = (MAILBOX *) mbq->mbox;
7523 		bzero((void *) mb, MAILBOX_CMD_BSIZE);
7524 		mb->un.varUnregLogin.rpi = (uint16_t)ndlp->nlp_Rpi;
7525 #ifdef SLI3_SUPPORT
7526 		mb->un.varUnregLogin.vpi = port->vpi;
7527 #endif	/* SLI3_SUPPORT */
7528 		mb->mbxCommand = MBX_UNREG_LOGIN;
7529 		mb->mbxOwner = OWN_HOST;
7530 
7531 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7532 		    "Fast Target Reset: unreg rpi=x%x tmr %d", ndlp->nlp_Rpi,
7533 		    cfg[CFG_FAST_TGT_RESET_TMR].current);
7534 
7535 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0)
7536 		    == MBX_SUCCESS) {
7537 
7538 			ndlp->nlp_Rpi = 0;
7539 
7540 			mutex_enter(&sbp->mtx);
7541 			sbp->node = (void *)ndlp;
7542 			sbp->did = ndlp->nlp_DID;
7543 			mutex_exit(&sbp->mtx);
7544 
7545 			if (pkt->pkt_rsplen) {
7546 				bzero((uint8_t *)pkt->pkt_resp,
7547 				    pkt->pkt_rsplen);
7548 			}
7549 			if (cfg[CFG_FAST_TGT_RESET_TMR].current) {
7550 				ndlp->nlp_force_rscn = hba->timer_tics +
7551 				    cfg[CFG_FAST_TGT_RESET_TMR].current;
7552 			}
7553 
7554 			emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 0);
7555 		}
7556 
7557 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
7558 		rc = FC_SUCCESS;
7559 	}
7560 	return (rc);
7561 }
7562 
7563 static int32_t
7564 emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp)
7565 {
7566 	emlxs_hba_t	*hba = HBA;
7567 	fc_packet_t	*pkt;
7568 	emlxs_config_t	*cfg;
7569 	IOCBQ		*iocbq;
7570 	IOCB		*iocb;
7571 	CHANNEL		*cp;
7572 	NODELIST	*ndlp;
7573 	char		*cmd;
7574 	uint16_t	lun;
7575 	FCP_CMND	*fcp_cmd;
7576 	uint32_t	did;
7577 	uint32_t	reset = 0;
7578 	int		channel;
7579 	int32_t		rval;
7580 
7581 	pkt = PRIV2PKT(sbp);
7582 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
7583 
7584 	/* Find target node object */
7585 	ndlp = emlxs_node_find_did(port, did);
7586 
7587 	if (!ndlp || !ndlp->nlp_active) {
7588 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
7589 		    "Node not found. did=%x", did);
7590 
7591 		return (FC_BADPACKET);
7592 	}
7593 
7594 	/* When the fcp channel is closed we stop accepting any FCP cmd */
7595 	if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) {
7596 		return (FC_TRAN_BUSY);
7597 	}
7598 
7599 	/* Snoop for target or lun reset first */
7600 	/* We always use FCP channel to send out target/lun reset fcp cmds */
7601 	/* interrupt affinity only applies to non tgt lun reset fcp cmd */
7602 
7603 	cmd = (char *)pkt->pkt_cmd;
7604 	lun = *((uint16_t *)cmd);
7605 	lun = LE_SWAP16(lun);
7606 
7607 	iocbq = &sbp->iocbq;
7608 	iocb = &iocbq->iocb;
7609 	iocbq->node = (void *) ndlp;
7610 
7611 	/* Check for target reset */
7612 	if (cmd[10] & 0x20) {
7613 		/* prepare iocb */
7614 		if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp,
7615 		    hba->channel_fcp)) != FC_SUCCESS) {
7616 
7617 			if (rval == 0xff) {
7618 				emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
7619 				    0, 1);
7620 				rval = FC_SUCCESS;
7621 			}
7622 
7623 			return (rval);
7624 		}
7625 
7626 		mutex_enter(&sbp->mtx);
7627 		sbp->pkt_flags |= PACKET_FCP_TGT_RESET;
7628 		sbp->pkt_flags |= PACKET_POLLED;
7629 		mutex_exit(&sbp->mtx);
7630 
7631 #ifdef SAN_DIAG_SUPPORT
7632 		emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_TGTRESET,
7633 		    (HBA_WWN *)&ndlp->nlp_portname, -1);
7634 #endif	/* SAN_DIAG_SUPPORT */
7635 
7636 		iocbq->flag |= IOCB_PRIORITY;
7637 
7638 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7639 		    "Target Reset: did=%x", did);
7640 
7641 		cfg = &CFG;
7642 		if (cfg[CFG_FAST_TGT_RESET].current) {
7643 			if (emlxs_fast_target_reset(port, sbp, ndlp) ==
7644 			    FC_SUCCESS) {
7645 				return (FC_SUCCESS);
7646 			}
7647 		}
7648 
7649 		/* Close the node for any further normal IO */
7650 		emlxs_node_close(port, ndlp, hba->channel_fcp,
7651 		    pkt->pkt_timeout);
7652 
7653 		/* Flush the IO's on the tx queues */
7654 		(void) emlxs_tx_node_flush(port, ndlp,
7655 		    &hba->chan[hba->channel_fcp], 0, sbp);
7656 
7657 		/* This is the target reset fcp cmd */
7658 		reset = 1;
7659 	}
7660 
7661 	/* Check for lun reset */
7662 	else if (cmd[10] & 0x10) {
7663 		/* prepare iocb */
7664 		if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp,
7665 		    hba->channel_fcp)) != FC_SUCCESS) {
7666 
7667 			if (rval == 0xff) {
7668 				emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
7669 				    0, 1);
7670 				rval = FC_SUCCESS;
7671 			}
7672 
7673 			return (rval);
7674 		}
7675 
7676 		mutex_enter(&sbp->mtx);
7677 		sbp->pkt_flags |= PACKET_FCP_LUN_RESET;
7678 		sbp->pkt_flags |= PACKET_POLLED;
7679 		mutex_exit(&sbp->mtx);
7680 
7681 #ifdef SAN_DIAG_SUPPORT
7682 		emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_LUNRESET,
7683 		    (HBA_WWN *)&ndlp->nlp_portname, lun);
7684 #endif	/* SAN_DIAG_SUPPORT */
7685 
7686 		iocbq->flag |= IOCB_PRIORITY;
7687 
7688 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7689 		    "LUN Reset: did=%x LUN=%02x02x", did, cmd[0], cmd[1]);
7690 
7691 		/* Flush the IO's on the tx queues for this lun */
7692 		(void) emlxs_tx_lun_flush(port, ndlp, lun, sbp);
7693 
7694 		/* This is the lun reset fcp cmd */
7695 		reset = 1;
7696 	}
7697 
7698 	channel = emlxs_select_fcp_channel(hba, ndlp, reset);
7699 
7700 #ifdef SAN_DIAG_SUPPORT
7701 	sbp->sd_start_time = gethrtime();
7702 #endif /* SAN_DIAG_SUPPORT */
7703 
7704 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
7705 	emlxs_swap_fcp_pkt(sbp);
7706 #endif	/* EMLXS_MODREV2X */
7707 
7708 	fcp_cmd = (FCP_CMND *) pkt->pkt_cmd;
7709 
7710 	if (fcp_cmd->fcpCntl1 == FCP_QTYPE_UNTAGGED) {
7711 		fcp_cmd->fcpCntl1 = FCP_QTYPE_SIMPLE;
7712 	}
7713 
7714 	if (reset == 0) {
7715 		/*
7716 		 * tgt lun reset fcp cmd has been prepared
7717 		 * separately in the beginning
7718 		 */
7719 		if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp,
7720 		    channel)) != FC_SUCCESS) {
7721 
7722 			if (rval == 0xff) {
7723 				emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
7724 				    0, 1);
7725 				rval = FC_SUCCESS;
7726 			}
7727 
7728 			return (rval);
7729 		}
7730 	}
7731 
7732 	cp = &hba->chan[channel];
7733 	cp->ulpSendCmd++;
7734 
7735 	/* Initalize sbp */
7736 	mutex_enter(&sbp->mtx);
7737 	sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
7738 	    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
7739 	sbp->node = (void *)ndlp;
7740 	sbp->lun = lun;
7741 	sbp->class = iocb->ULPCLASS;
7742 	sbp->did = ndlp->nlp_DID;
7743 	mutex_exit(&sbp->mtx);
7744 
7745 	if (pkt->pkt_cmdlen) {
7746 		EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
7747 		    DDI_DMA_SYNC_FORDEV);
7748 	}
7749 
7750 	if (pkt->pkt_datalen && pkt->pkt_tran_type == FC_PKT_FCP_WRITE) {
7751 		EMLXS_MPDATA_SYNC(pkt->pkt_data_dma, 0, pkt->pkt_datalen,
7752 		    DDI_DMA_SYNC_FORDEV);
7753 	}
7754 
7755 	HBASTATS.FcpIssued++;
7756 
7757 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
7758 	return (FC_SUCCESS);
7759 
7760 } /* emlxs_send_fcp_cmd() */
7761 
7762 
7763 
7764 
7765 #ifdef SFCT_SUPPORT
7766 static int32_t
7767 emlxs_send_fct_status(emlxs_port_t *port, emlxs_buf_t *sbp)
7768 {
7769 	emlxs_hba_t		*hba = HBA;
7770 	fc_packet_t		*pkt;
7771 	IOCBQ			*iocbq;
7772 	IOCB			*iocb;
7773 	NODELIST		*ndlp;
7774 	CHANNEL			*cp;
7775 	uint16_t		iotag;
7776 	uint32_t		did;
7777 	ddi_dma_cookie_t	*cp_cmd;
7778 
7779 	pkt = PRIV2PKT(sbp);
7780 
7781 	did = sbp->did;
7782 	ndlp = sbp->node;
7783 
7784 	iocbq = &sbp->iocbq;
7785 	iocb = &iocbq->iocb;
7786 
7787 	/* Make sure node is still active */
7788 	if (!ndlp->nlp_active) {
7789 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
7790 		    "*Node not found. did=%x", did);
7791 
7792 		return (FC_BADPACKET);
7793 	}
7794 
7795 	/* If gate is closed */
7796 	if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) {
7797 		return (FC_TRAN_BUSY);
7798 	}
7799 
7800 	/* Get the iotag by registering the packet */
7801 	iotag = emlxs_register_pkt(sbp->channel, sbp);
7802 
7803 	if (!iotag) {
7804 		/* No more command slots available, retry later */
7805 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7806 		    "*Adapter Busy. Unable to allocate iotag: did=0x%x", did);
7807 
7808 		return (FC_TRAN_BUSY);
7809 	}
7810 
7811 	/* Point of no return */
7812 
7813 	cp = sbp->channel;
7814 	cp->ulpSendCmd++;
7815 
7816 #if (EMLXS_MODREV >= EMLXS_MODREV3)
7817 	cp_cmd = pkt->pkt_cmd_cookie;
7818 #else
7819 	cp_cmd  = &pkt->pkt_cmd_cookie;
7820 #endif	/* >= EMLXS_MODREV3 */
7821 
7822 	iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(cp_cmd->dmac_laddress);
7823 	iocb->un.fcpt64.bdl.addrLow = PADDR_LO(cp_cmd->dmac_laddress);
7824 	iocb->un.fcpt64.bdl.bdeSize = pkt->pkt_cmdlen;
7825 	iocb->un.fcpt64.bdl.bdeFlags = 0;
7826 
7827 	if (hba->sli_mode < 3) {
7828 		iocb->ULPBDECOUNT = 1;
7829 		iocb->ULPLE = 1;
7830 	} else {	/* SLI3 */
7831 
7832 		iocb->ULPBDECOUNT = 0;
7833 		iocb->ULPLE = 0;
7834 		iocb->unsli3.ext_iocb.ebde_count = 0;
7835 	}
7836 
7837 	/* Initalize iocbq */
7838 	iocbq->port = (void *)port;
7839 	iocbq->node = (void *)ndlp;
7840 	iocbq->channel = (void *)cp;
7841 
7842 	/* Initalize iocb */
7843 	iocb->ULPCONTEXT = (uint16_t)pkt->pkt_cmd_fhdr.rx_id;
7844 	iocb->ULPIOTAG = iotag;
7845 	iocb->ULPRSVDBYTE =
7846 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
7847 	iocb->ULPOWNER = OWN_CHIP;
7848 	iocb->ULPCLASS = sbp->class;
7849 	iocb->ULPCOMMAND = CMD_FCP_TRSP64_CX;
7850 
7851 	/* Set the pkt timer */
7852 	sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
7853 	    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
7854 
7855 	if (pkt->pkt_cmdlen) {
7856 		EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
7857 		    DDI_DMA_SYNC_FORDEV);
7858 	}
7859 
7860 	HBASTATS.FcpIssued++;
7861 
7862 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
7863 
7864 	return (FC_SUCCESS);
7865 
7866 } /* emlxs_send_fct_status() */
7867 
7868 
7869 static int32_t
7870 emlxs_send_fct_abort(emlxs_port_t *port, emlxs_buf_t *sbp)
7871 {
7872 	emlxs_hba_t	*hba = HBA;
7873 	fc_packet_t	*pkt;
7874 	IOCBQ		*iocbq;
7875 	IOCB		*iocb;
7876 	NODELIST	*ndlp;
7877 	uint16_t	iotag;
7878 	uint32_t	did;
7879 
7880 	pkt = PRIV2PKT(sbp);
7881 
7882 	did = sbp->did;
7883 	ndlp = sbp->node;
7884 
7885 
7886 	iocbq = &sbp->iocbq;
7887 	iocb = &iocbq->iocb;
7888 
7889 	/* Make sure node is still active */
7890 	if ((ndlp == NULL) || (!ndlp->nlp_active)) {
7891 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
7892 		    "*Node not found. did=%x", did);
7893 
7894 		return (FC_BADPACKET);
7895 	}
7896 
7897 	/* If gate is closed */
7898 	if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) {
7899 		return (FC_TRAN_BUSY);
7900 	}
7901 
7902 	/* Get the iotag by registering the packet */
7903 	iotag = emlxs_register_pkt(sbp->channel, sbp);
7904 
7905 	if (!iotag) {
7906 		/* No more command slots available, retry later */
7907 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7908 		    "*Adapter Busy. Unable to allocate iotag: did=0x%x", did);
7909 
7910 		return (FC_TRAN_BUSY);
7911 	}
7912 
7913 	/* Point of no return */
7914 	iocbq->port = (void *)port;
7915 	iocbq->node = (void *)ndlp;
7916 	iocbq->channel = (void *)sbp->channel;
7917 	((CHANNEL *)sbp->channel)->ulpSendCmd++;
7918 
7919 	/*
7920 	 * Don't give the abort priority, we want the IOCB
7921 	 * we are aborting to be processed first.
7922 	 */
7923 	iocbq->flag |= IOCB_SPECIAL;
7924 
7925 	iocb->ULPCONTEXT = pkt->pkt_cmd_fhdr.rx_id;
7926 	iocb->ULPIOTAG = iotag;
7927 	iocb->ULPLE = 1;
7928 	iocb->ULPCLASS = sbp->class;
7929 	iocb->ULPOWNER = OWN_CHIP;
7930 
7931 	if (hba->state >= FC_LINK_UP) {
7932 		/* Create the abort IOCB */
7933 		iocb->un.acxri.abortType = ABORT_TYPE_ABTS;
7934 		iocb->ULPCOMMAND = CMD_ABORT_XRI_CX;
7935 
7936 	} else {
7937 		/* Create the close IOCB */
7938 		iocb->ULPCOMMAND = CMD_CLOSE_XRI_CX;
7939 
7940 	}
7941 
7942 	iocb->ULPRSVDBYTE =
7943 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
7944 	/* Set the pkt timer */
7945 	sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
7946 	    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
7947 
7948 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, sbp->channel, iocbq);
7949 
7950 	return (FC_SUCCESS);
7951 
7952 } /* emlxs_send_fct_abort() */
7953 
7954 #endif /* SFCT_SUPPORT */
7955 
7956 
7957 static int32_t
7958 emlxs_send_ip(emlxs_port_t *port, emlxs_buf_t *sbp)
7959 {
7960 	emlxs_hba_t	*hba = HBA;
7961 	fc_packet_t	*pkt;
7962 	IOCBQ		*iocbq;
7963 	IOCB		*iocb;
7964 	CHANNEL		*cp;
7965 	uint32_t	i;
7966 	NODELIST	*ndlp;
7967 	uint32_t	did;
7968 	int32_t 	rval;
7969 
7970 	pkt = PRIV2PKT(sbp);
7971 	cp = &hba->chan[hba->channel_ip];
7972 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
7973 
7974 	/* Check if node exists */
7975 	/* Broadcast did is always a success */
7976 	ndlp = emlxs_node_find_did(port, did);
7977 
7978 	if (!ndlp || !ndlp->nlp_active) {
7979 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
7980 		    "Node not found. did=0x%x", did);
7981 
7982 		return (FC_BADPACKET);
7983 	}
7984 
7985 	/* Check if gate is temporarily closed */
7986 	if (ndlp->nlp_flag[hba->channel_ip] & NLP_CLOSED) {
7987 		return (FC_TRAN_BUSY);
7988 	}
7989 
7990 	/* Check if an exchange has been created */
7991 	if ((ndlp->nlp_Xri == 0) && (did != BCAST_DID)) {
7992 		/* No exchange.  Try creating one */
7993 		(void) emlxs_create_xri(port, cp, ndlp);
7994 
7995 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7996 		    "Adapter Busy. Exchange not found. did=0x%x", did);
7997 
7998 		return (FC_TRAN_BUSY);
7999 	}
8000 
8001 	/* ULP PATCH: pkt_cmdlen was found to be set to zero */
8002 	/* on BROADCAST commands */
8003 	if (pkt->pkt_cmdlen == 0) {
8004 		/* Set the pkt_cmdlen to the cookie size */
8005 #if (EMLXS_MODREV >= EMLXS_MODREV3)
8006 		for (i = 0; i < pkt->pkt_cmd_cookie_cnt; i++) {
8007 			pkt->pkt_cmdlen += pkt->pkt_cmd_cookie[i].dmac_size;
8008 		}
8009 #else
8010 		pkt->pkt_cmdlen = pkt->pkt_cmd_cookie.dmac_size;
8011 #endif	/* >= EMLXS_MODREV3 */
8012 
8013 	}
8014 
8015 	iocbq = &sbp->iocbq;
8016 	iocb = &iocbq->iocb;
8017 
8018 	iocbq->node = (void *)ndlp;
8019 	if ((rval = EMLXS_SLI_PREP_IP_IOCB(port, sbp)) != FC_SUCCESS) {
8020 
8021 		if (rval == 0xff) {
8022 			emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
8023 			rval = FC_SUCCESS;
8024 		}
8025 
8026 		return (rval);
8027 	}
8028 
8029 	cp->ulpSendCmd++;
8030 
8031 	/* Initalize sbp */
8032 	mutex_enter(&sbp->mtx);
8033 	sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
8034 	    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
8035 	sbp->node = (void *)ndlp;
8036 	sbp->lun = 0;
8037 	sbp->class = iocb->ULPCLASS;
8038 	sbp->did = did;
8039 	mutex_exit(&sbp->mtx);
8040 
8041 	if (pkt->pkt_cmdlen) {
8042 		EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
8043 		    DDI_DMA_SYNC_FORDEV);
8044 	}
8045 
8046 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
8047 
8048 	return (FC_SUCCESS);
8049 
8050 } /* emlxs_send_ip() */
8051 
8052 
8053 static int32_t
8054 emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp)
8055 {
8056 	emlxs_hba_t	*hba = HBA;
8057 	emlxs_port_t	*vport;
8058 	fc_packet_t	*pkt;
8059 	IOCBQ		*iocbq;
8060 	CHANNEL		*cp;
8061 	uint32_t	cmd;
8062 	int		i;
8063 	ELS_PKT		*els_pkt;
8064 	NODELIST	*ndlp;
8065 	uint32_t	did;
8066 	char		fcsp_msg[32];
8067 	int		rc;
8068 	int32_t 	rval;
8069 
8070 	fcsp_msg[0] = 0;
8071 	pkt = PRIV2PKT(sbp);
8072 	els_pkt = (ELS_PKT *)pkt->pkt_cmd;
8073 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
8074 
8075 	iocbq = &sbp->iocbq;
8076 
8077 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
8078 	emlxs_swap_els_pkt(sbp);
8079 #endif	/* EMLXS_MODREV2X */
8080 
8081 	cmd = *((uint32_t *)pkt->pkt_cmd);
8082 	cmd &= ELS_CMD_MASK;
8083 
8084 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8085 	    "Send ELS cmd: %x", cmd);
8086 
8087 	/* Point of no return, except for ADISC & PLOGI */
8088 
8089 	/* Check node */
8090 	switch (cmd) {
8091 	case ELS_CMD_FLOGI:
8092 		if (port->vpi > 0) {
8093 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
8094 				if (!(port->flag & EMLXS_PORT_INIT_VPI_CMPL)) {
8095 					(void) emlxs_mb_init_vpi(port);
8096 					if (!(port->flag &
8097 					    EMLXS_PORT_INIT_VPI_CMPL)) {
8098 						pkt->pkt_state =
8099 						    FC_PKT_LOCAL_RJT;
8100 
8101 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
8102 						emlxs_unswap_pkt(sbp);
8103 #endif  /* EMLXS_MODREV2X */
8104 
8105 						return (FC_FAILURE);
8106 					}
8107 				}
8108 			}
8109 			cmd = ELS_CMD_FDISC;
8110 			*((uint32_t *)pkt->pkt_cmd) = cmd;
8111 		}
8112 		ndlp = NULL;
8113 
8114 		if (hba->flag & FC_NPIV_DELAY_REQUIRED) {
8115 			sbp->pkt_flags |= PACKET_DELAY_REQUIRED;
8116 		}
8117 
8118 		/* We will process these cmds at the bottom of this routine */
8119 		break;
8120 
8121 	case ELS_CMD_PLOGI:
8122 		/* Make sure we don't log into ourself */
8123 		for (i = 0; i < MAX_VPORTS; i++) {
8124 			vport = &VPORT(i);
8125 
8126 			if (!(vport->flag & EMLXS_PORT_BOUND)) {
8127 				continue;
8128 			}
8129 
8130 			if (did == vport->did) {
8131 				pkt->pkt_state = FC_PKT_NPORT_RJT;
8132 
8133 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
8134 				emlxs_unswap_pkt(sbp);
8135 #endif	/* EMLXS_MODREV2X */
8136 
8137 				return (FC_FAILURE);
8138 			}
8139 		}
8140 
8141 		ndlp = NULL;
8142 
8143 		/* Check if this is the first PLOGI */
8144 		/* after a PT_TO_PT connection */
8145 		if ((hba->flag & FC_PT_TO_PT) && (port->did == 0)) {
8146 			MAILBOXQ	*mbox;
8147 
8148 			/* ULP bug fix */
8149 			if (pkt->pkt_cmd_fhdr.s_id == 0) {
8150 				pkt->pkt_cmd_fhdr.s_id =
8151 				    pkt->pkt_cmd_fhdr.d_id - FP_DEFAULT_DID +
8152 				    FP_DEFAULT_SID;
8153 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_send_msg,
8154 				    "PLOGI: P2P Fix. sid=0-->%x did=%x",
8155 				    pkt->pkt_cmd_fhdr.s_id,
8156 				    pkt->pkt_cmd_fhdr.d_id);
8157 			}
8158 
8159 			mutex_enter(&EMLXS_PORT_LOCK);
8160 			port->did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.s_id);
8161 			mutex_exit(&EMLXS_PORT_LOCK);
8162 
8163 			/* Update our service parms */
8164 			if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
8165 			    MEM_MBOX, 1))) {
8166 				emlxs_mb_config_link(hba, mbox);
8167 
8168 				rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba,
8169 				    mbox, MBX_NOWAIT, 0);
8170 				if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
8171 					(void) emlxs_mem_put(hba, MEM_MBOX,
8172 					    (uint8_t *)mbox);
8173 				}
8174 
8175 			}
8176 		}
8177 
8178 		/* We will process these cmds at the bottom of this routine */
8179 		break;
8180 
8181 	default:
8182 		ndlp = emlxs_node_find_did(port, did);
8183 
8184 		/* If an ADISC is being sent and we have no node, */
8185 		/* then we must fail the ADISC now */
8186 		if (!ndlp && (cmd == ELS_CMD_ADISC) && !port->tgt_mode) {
8187 
8188 			/* Build the LS_RJT response */
8189 			els_pkt = (ELS_PKT *)pkt->pkt_resp;
8190 			els_pkt->elsCode = 0x01;
8191 			els_pkt->un.lsRjt.un.b.lsRjtRsvd0 = 0;
8192 			els_pkt->un.lsRjt.un.b.lsRjtRsnCode =
8193 			    LSRJT_LOGICAL_ERR;
8194 			els_pkt->un.lsRjt.un.b.lsRjtRsnCodeExp =
8195 			    LSEXP_NOTHING_MORE;
8196 			els_pkt->un.lsRjt.un.b.vendorUnique = 0x03;
8197 
8198 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
8199 			    "ADISC Rejected. Node not found. did=0x%x", did);
8200 
8201 			if (sbp->channel == NULL) {
8202 				if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
8203 					sbp->channel =
8204 					    &hba->chan[hba->channel_els];
8205 				} else {
8206 					sbp->channel =
8207 					    &hba->chan[FC_ELS_RING];
8208 				}
8209 			}
8210 
8211 			/* Return this as rejected by the target */
8212 			emlxs_pkt_complete(sbp, IOSTAT_LS_RJT, 0, 1);
8213 
8214 			return (FC_SUCCESS);
8215 		}
8216 	}
8217 
8218 	/* DID == BCAST_DID is special case to indicate that */
8219 	/* RPI is being passed in seq_id field */
8220 	/* This is used by emlxs_send_logo() for target mode */
8221 
8222 	/* Initalize iocbq */
8223 	iocbq->node = (void *)ndlp;
8224 	if ((rval = EMLXS_SLI_PREP_ELS_IOCB(port, sbp)) != FC_SUCCESS) {
8225 
8226 		if (rval == 0xff) {
8227 			emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
8228 			rval = FC_SUCCESS;
8229 		}
8230 
8231 		return (rval);
8232 	}
8233 
8234 	cp = &hba->chan[hba->channel_els];
8235 	cp->ulpSendCmd++;
8236 
8237 	/* Check cmd */
8238 	switch (cmd) {
8239 	case ELS_CMD_PRLI:
8240 		{
8241 		/*
8242 		 * if our firmware version is 3.20 or later,
8243 		 * set the following bits for FC-TAPE support.
8244 		 */
8245 
8246 		if (port->ini_mode && hba->vpd.feaLevelHigh >= 0x02) {
8247 				els_pkt->un.prli.ConfmComplAllowed = 1;
8248 				els_pkt->un.prli.Retry = 1;
8249 				els_pkt->un.prli.TaskRetryIdReq = 1;
8250 		} else {
8251 				els_pkt->un.prli.ConfmComplAllowed = 0;
8252 				els_pkt->un.prli.Retry = 0;
8253 				els_pkt->un.prli.TaskRetryIdReq = 0;
8254 			}
8255 
8256 			break;
8257 		}
8258 
8259 		/* This is a patch for the ULP stack. */
8260 
8261 		/*
8262 		 * ULP only reads our service paramters once during bind_port,
8263 		 * but the service parameters change due to topology.
8264 		 */
8265 	case ELS_CMD_FLOGI:
8266 	case ELS_CMD_FDISC:
8267 	case ELS_CMD_PLOGI:
8268 	case ELS_CMD_PDISC:
8269 		{
8270 		/* Copy latest service parameters to payload */
8271 		bcopy((void *) &port->sparam,
8272 		    (void *)&els_pkt->un.logi, sizeof (SERV_PARM));
8273 
8274 		if ((hba->flag & FC_NPIV_ENABLED) &&
8275 		    (hba->flag & FC_NPIV_SUPPORTED) &&
8276 		    (cmd == ELS_CMD_PLOGI)) {
8277 				SERV_PARM	*sp;
8278 				emlxs_vvl_fmt_t	*vvl;
8279 
8280 				sp = (SERV_PARM *)&els_pkt->un.logi;
8281 				sp->VALID_VENDOR_VERSION = 1;
8282 				vvl = (emlxs_vvl_fmt_t *)&sp->vendorVersion[0];
8283 				vvl->un0.w0.oui = 0x0000C9;
8284 				vvl->un0.word0 = LE_SWAP32(vvl->un0.word0);
8285 				vvl->un1.w1.vport =  (port->vpi > 0) ? 1 : 0;
8286 				vvl->un1.word1 = LE_SWAP32(vvl->un1.word1);
8287 			}
8288 
8289 #ifdef DHCHAP_SUPPORT
8290 			emlxs_dhc_init_sp(port, did,
8291 			    (SERV_PARM *)&els_pkt->un.logi, (char **)&fcsp_msg);
8292 #endif	/* DHCHAP_SUPPORT */
8293 
8294 			break;
8295 		}
8296 
8297 	}
8298 
8299 	/* Initialize the sbp */
8300 	mutex_enter(&sbp->mtx);
8301 	sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
8302 	    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
8303 	sbp->node = (void *)ndlp;
8304 	sbp->lun = 0;
8305 	sbp->did = did;
8306 	mutex_exit(&sbp->mtx);
8307 
8308 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_send_msg, "%s: sid=%x did=%x %s",
8309 	    emlxs_elscmd_xlate(cmd), port->did, did, fcsp_msg);
8310 
8311 	if (pkt->pkt_cmdlen) {
8312 		EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
8313 		    DDI_DMA_SYNC_FORDEV);
8314 	}
8315 
8316 	/* Check node */
8317 	switch (cmd) {
8318 	case ELS_CMD_FLOGI:
8319 		if (port->ini_mode) {
8320 			/* Make sure fabric node is destroyed */
8321 			/* It should already have been destroyed at link down */
8322 			/* Unregister the fabric did and attempt a deferred */
8323 			/* iocb send */
8324 			if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
8325 				if (emlxs_mb_unreg_did(port, FABRIC_DID, NULL,
8326 				    NULL, iocbq) == 0) {
8327 					/* Deferring iocb tx until */
8328 					/* completion of unreg */
8329 					return (FC_SUCCESS);
8330 				}
8331 			}
8332 		}
8333 		break;
8334 
8335 	case ELS_CMD_PLOGI:
8336 
8337 		ndlp = emlxs_node_find_did(port, did);
8338 
8339 		if (ndlp && ndlp->nlp_active) {
8340 			/* Close the node for any further normal IO */
8341 			emlxs_node_close(port, ndlp, hba->channel_fcp,
8342 			    pkt->pkt_timeout + 10);
8343 			emlxs_node_close(port, ndlp, hba->channel_ip,
8344 			    pkt->pkt_timeout + 10);
8345 
8346 			/* Flush tx queues */
8347 			(void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0);
8348 
8349 			/* Flush chip queues */
8350 			(void) emlxs_chipq_node_flush(port, 0, ndlp, 0);
8351 		}
8352 
8353 		break;
8354 
8355 	case ELS_CMD_PRLI:
8356 
8357 		ndlp = emlxs_node_find_did(port, did);
8358 
8359 		if (ndlp && ndlp->nlp_active) {
8360 			/*
8361 			 * Close the node for any further FCP IO;
8362 			 * Flush all outstanding I/O only if
8363 			 * "Establish Image Pair" bit is set.
8364 			 */
8365 			emlxs_node_close(port, ndlp, hba->channel_fcp,
8366 			    pkt->pkt_timeout + 10);
8367 
8368 			if (els_pkt->un.prli.estabImagePair) {
8369 				/* Flush tx queues */
8370 				(void) emlxs_tx_node_flush(port, ndlp,
8371 				    &hba->chan[hba->channel_fcp], 0, 0);
8372 
8373 				/* Flush chip queues */
8374 				(void) emlxs_chipq_node_flush(port,
8375 				    &hba->chan[hba->channel_fcp], ndlp, 0);
8376 			}
8377 		}
8378 
8379 		break;
8380 
8381 	}
8382 
8383 	HBASTATS.ElsCmdIssued++;
8384 
8385 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
8386 
8387 	return (FC_SUCCESS);
8388 
8389 } /* emlxs_send_els() */
8390 
8391 
8392 
8393 
8394 static int32_t
8395 emlxs_send_els_rsp(emlxs_port_t *port, emlxs_buf_t *sbp)
8396 {
8397 	emlxs_hba_t	*hba = HBA;
8398 	emlxs_config_t  *cfg = &CFG;
8399 	fc_packet_t	*pkt;
8400 	IOCBQ		*iocbq;
8401 	IOCB		*iocb;
8402 	NODELIST	*ndlp;
8403 	CHANNEL		*cp;
8404 	int		i;
8405 	uint32_t	cmd;
8406 	uint32_t	ucmd;
8407 	ELS_PKT		*els_pkt;
8408 	fc_unsol_buf_t	*ubp;
8409 	emlxs_ub_priv_t	*ub_priv;
8410 	uint32_t	did;
8411 	char		fcsp_msg[32];
8412 	uint8_t		*ub_buffer;
8413 	int32_t		rval;
8414 
8415 	fcsp_msg[0] = 0;
8416 	pkt = PRIV2PKT(sbp);
8417 	els_pkt = (ELS_PKT *)pkt->pkt_cmd;
8418 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
8419 
8420 	iocbq = &sbp->iocbq;
8421 	iocb = &iocbq->iocb;
8422 
8423 	/* Acquire the unsolicited command this pkt is replying to */
8424 	if (pkt->pkt_cmd_fhdr.ox_id < EMLXS_UB_TOKEN_OFFSET) {
8425 		/* This is for auto replies when no ub's are used */
8426 		ucmd = pkt->pkt_cmd_fhdr.ox_id << ELS_CMD_SHIFT;
8427 		ubp = NULL;
8428 		ub_priv = NULL;
8429 		ub_buffer = NULL;
8430 
8431 #ifdef SFCT_SUPPORT
8432 		if (sbp->fct_cmd) {
8433 			fct_els_t *els =
8434 			    (fct_els_t *)sbp->fct_cmd->cmd_specific;
8435 			ub_buffer = (uint8_t *)els->els_req_payload;
8436 		}
8437 #endif /* SFCT_SUPPORT */
8438 
8439 	} else {
8440 		/* Find the ub buffer that goes with this reply */
8441 		if (!(ubp = emlxs_ub_find(port, pkt->pkt_cmd_fhdr.ox_id))) {
8442 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
8443 			    "ELS reply: Invalid oxid=%x",
8444 			    pkt->pkt_cmd_fhdr.ox_id);
8445 			return (FC_BADPACKET);
8446 		}
8447 
8448 		ub_buffer = (uint8_t *)ubp->ub_buffer;
8449 		ub_priv = ubp->ub_fca_private;
8450 		ucmd = ub_priv->cmd;
8451 
8452 		ub_priv->flags |= EMLXS_UB_REPLY;
8453 
8454 		/* Reset oxid to ELS command */
8455 		/* We do this because the ub is only valid */
8456 		/* until we return from this thread */
8457 		pkt->pkt_cmd_fhdr.ox_id = (ucmd >> ELS_CMD_SHIFT) & 0xff;
8458 	}
8459 
8460 	/* Save the result */
8461 	sbp->ucmd = ucmd;
8462 
8463 	if (sbp->channel == NULL) {
8464 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
8465 			sbp->channel = &hba->chan[hba->channel_els];
8466 		} else {
8467 			sbp->channel = &hba->chan[FC_ELS_RING];
8468 		}
8469 	}
8470 
8471 	/* Check for interceptions */
8472 	switch (ucmd) {
8473 
8474 #ifdef ULP_PATCH2
8475 	case ELS_CMD_LOGO:
8476 		if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH2)) {
8477 			break;
8478 		}
8479 
8480 		/* Check if this was generated by ULP and not us */
8481 		if (!(sbp->pkt_flags & PACKET_ALLOCATED)) {
8482 
8483 			/*
8484 			 * Since we replied to this already,
8485 			 * we won't need to send this now
8486 			 */
8487 			emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
8488 
8489 			return (FC_SUCCESS);
8490 		}
8491 
8492 		break;
8493 #endif /* ULP_PATCH2 */
8494 
8495 #ifdef ULP_PATCH3
8496 	case ELS_CMD_PRLI:
8497 		if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH3)) {
8498 			break;
8499 		}
8500 
8501 		/* Check if this was generated by ULP and not us */
8502 		if (!(sbp->pkt_flags & PACKET_ALLOCATED)) {
8503 
8504 			/*
8505 			 * Since we replied to this already,
8506 			 * we won't need to send this now
8507 			 */
8508 			emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
8509 
8510 			return (FC_SUCCESS);
8511 		}
8512 
8513 		break;
8514 #endif /* ULP_PATCH3 */
8515 
8516 
8517 #ifdef ULP_PATCH4
8518 	case ELS_CMD_PRLO:
8519 		if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH4)) {
8520 			break;
8521 		}
8522 
8523 		/* Check if this was generated by ULP and not us */
8524 		if (!(sbp->pkt_flags & PACKET_ALLOCATED)) {
8525 			/*
8526 			 * Since we replied to this already,
8527 			 * we won't need to send this now
8528 			 */
8529 			emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
8530 
8531 			return (FC_SUCCESS);
8532 		}
8533 
8534 		break;
8535 #endif /* ULP_PATCH4 */
8536 
8537 #ifdef ULP_PATCH6
8538 	case ELS_CMD_RSCN:
8539 		if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH6)) {
8540 			break;
8541 		}
8542 
8543 		/* Check if this RSCN was generated by us */
8544 		if (ub_priv && (ub_priv->flags & EMLXS_UB_INTERCEPT)) {
8545 			cmd = *((uint32_t *)pkt->pkt_cmd);
8546 			cmd = LE_SWAP32(cmd);
8547 			cmd &= ELS_CMD_MASK;
8548 
8549 			/*
8550 			 * If ULP is accepting this,
8551 			 * then close affected node
8552 			 */
8553 			if (port->ini_mode && ub_buffer && cmd
8554 			    == ELS_CMD_ACC) {
8555 				fc_rscn_t	*rscn;
8556 				uint32_t	count;
8557 				uint32_t	*lp;
8558 
8559 				/*
8560 				 * Only the Leadville code path will
8561 				 * come thru here. The RSCN data is NOT
8562 				 * swapped properly for the Comstar code
8563 				 * path.
8564 				 */
8565 				lp = (uint32_t *)ub_buffer;
8566 				rscn = (fc_rscn_t *)lp++;
8567 				count =
8568 				    ((rscn->rscn_payload_len - 4) / 4);
8569 
8570 				/* Close affected ports */
8571 				for (i = 0; i < count; i++, lp++) {
8572 					(void) emlxs_port_offline(port,
8573 					    *lp);
8574 				}
8575 			}
8576 
8577 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_reply_msg,
8578 			    "RSCN %s: did=%x oxid=%x rxid=%x. "
8579 			    "Intercepted.", emlxs_elscmd_xlate(cmd),
8580 			    did, pkt->pkt_cmd_fhdr.ox_id,
8581 			    pkt->pkt_cmd_fhdr.rx_id);
8582 
8583 			/*
8584 			 * Since we generated this RSCN,
8585 			 * we won't need to send this reply
8586 			 */
8587 			emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
8588 
8589 			return (FC_SUCCESS);
8590 		}
8591 
8592 		break;
8593 #endif /* ULP_PATCH6 */
8594 
8595 	case ELS_CMD_PLOGI:
8596 		/* Check if this PLOGI was generated by us */
8597 		if (ub_priv && (ub_priv->flags & EMLXS_UB_INTERCEPT)) {
8598 			cmd = *((uint32_t *)pkt->pkt_cmd);
8599 			cmd = LE_SWAP32(cmd);
8600 			cmd &= ELS_CMD_MASK;
8601 
8602 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_reply_msg,
8603 			    "PLOGI %s: did=%x oxid=%x rxid=%x. "
8604 			    "Intercepted.", emlxs_elscmd_xlate(cmd),
8605 			    did, pkt->pkt_cmd_fhdr.ox_id,
8606 			    pkt->pkt_cmd_fhdr.rx_id);
8607 
8608 			/*
8609 			 * Since we generated this PLOGI,
8610 			 * we won't need to send this reply
8611 			 */
8612 			emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
8613 
8614 			return (FC_SUCCESS);
8615 		}
8616 
8617 		break;
8618 	}
8619 
8620 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
8621 	emlxs_swap_els_pkt(sbp);
8622 #endif	/* EMLXS_MODREV2X */
8623 
8624 
8625 	cmd = *((uint32_t *)pkt->pkt_cmd);
8626 	cmd &= ELS_CMD_MASK;
8627 
8628 	/* Check if modifications are needed */
8629 	switch (ucmd) {
8630 	case (ELS_CMD_PRLI):
8631 
8632 		if (cmd == ELS_CMD_ACC) {
8633 			/* This is a patch for the ULP stack. */
8634 			/* ULP does not keep track of FCP2 support */
8635 
8636 			if (port->ini_mode && hba->vpd.feaLevelHigh >= 0x02) {
8637 				els_pkt->un.prli.ConfmComplAllowed = 1;
8638 				els_pkt->un.prli.Retry = 1;
8639 				els_pkt->un.prli.TaskRetryIdReq = 1;
8640 			} else {
8641 				els_pkt->un.prli.ConfmComplAllowed = 0;
8642 				els_pkt->un.prli.Retry = 0;
8643 				els_pkt->un.prli.TaskRetryIdReq = 0;
8644 			}
8645 		}
8646 
8647 		break;
8648 
8649 	case ELS_CMD_FLOGI:
8650 	case ELS_CMD_PLOGI:
8651 	case ELS_CMD_FDISC:
8652 	case ELS_CMD_PDISC:
8653 
8654 		if (cmd == ELS_CMD_ACC) {
8655 			/* This is a patch for the ULP stack. */
8656 
8657 			/*
8658 			 * ULP only reads our service parameters
8659 			 * once during bind_port, but the service
8660 			 * parameters change due to topology.
8661 			 */
8662 
8663 			/* Copy latest service parameters to payload */
8664 			bcopy((void *)&port->sparam,
8665 			    (void *)&els_pkt->un.logi, sizeof (SERV_PARM));
8666 
8667 #ifdef DHCHAP_SUPPORT
8668 			emlxs_dhc_init_sp(port, did,
8669 			    (SERV_PARM *)&els_pkt->un.logi, (char **)&fcsp_msg);
8670 #endif	/* DHCHAP_SUPPORT */
8671 
8672 		}
8673 
8674 		break;
8675 
8676 	}
8677 
8678 	/* Initalize iocbq */
8679 	iocbq->node = (void *)NULL;
8680 	if ((rval = EMLXS_SLI_PREP_ELS_IOCB(port, sbp)) != FC_SUCCESS) {
8681 
8682 		if (rval == 0xff) {
8683 			emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
8684 			rval = FC_SUCCESS;
8685 		}
8686 
8687 		return (rval);
8688 	}
8689 
8690 	cp = &hba->chan[hba->channel_els];
8691 	cp->ulpSendCmd++;
8692 
8693 	/* Initalize sbp */
8694 	mutex_enter(&sbp->mtx);
8695 	sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
8696 	    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
8697 	sbp->node = (void *) NULL;
8698 	sbp->lun = 0;
8699 	sbp->class = iocb->ULPCLASS;
8700 	sbp->did = did;
8701 	mutex_exit(&sbp->mtx);
8702 
8703 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_reply_msg,
8704 	    "%s %s: did=%x oxid=%x rxid=%x %s", emlxs_elscmd_xlate(ucmd),
8705 	    emlxs_elscmd_xlate(cmd), did, pkt->pkt_cmd_fhdr.ox_id,
8706 	    pkt->pkt_cmd_fhdr.rx_id, fcsp_msg);
8707 
8708 	/* Process nodes */
8709 	switch (ucmd) {
8710 	case ELS_CMD_RSCN:
8711 		{
8712 		if (port->ini_mode && ub_buffer && cmd == ELS_CMD_ACC) {
8713 			fc_rscn_t	*rscn;
8714 			uint32_t	count;
8715 			uint32_t	*lp = NULL;
8716 
8717 			/*
8718 			 * Only the Leadville code path will come thru
8719 			 * here. The RSCN data is NOT swapped properly
8720 			 * for the Comstar code path.
8721 			 */
8722 			lp = (uint32_t *)ub_buffer;
8723 			rscn = (fc_rscn_t *)lp++;
8724 			count = ((rscn->rscn_payload_len - 4) / 4);
8725 
8726 			/* Close affected ports */
8727 			for (i = 0; i < count; i++, lp++) {
8728 				(void) emlxs_port_offline(port, *lp);
8729 			}
8730 		}
8731 			break;
8732 		}
8733 	case ELS_CMD_PLOGI:
8734 
8735 		if (cmd == ELS_CMD_ACC) {
8736 			ndlp = emlxs_node_find_did(port, did);
8737 
8738 			if (ndlp && ndlp->nlp_active) {
8739 				/* Close the node for any further normal IO */
8740 				emlxs_node_close(port, ndlp, hba->channel_fcp,
8741 				    pkt->pkt_timeout + 10);
8742 				emlxs_node_close(port, ndlp, hba->channel_ip,
8743 				    pkt->pkt_timeout + 10);
8744 
8745 				/* Flush tx queue */
8746 				(void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0);
8747 
8748 				/* Flush chip queue */
8749 				(void) emlxs_chipq_node_flush(port, 0, ndlp, 0);
8750 			}
8751 		}
8752 
8753 		break;
8754 
8755 	case ELS_CMD_PRLI:
8756 
8757 		if (cmd == ELS_CMD_ACC) {
8758 			ndlp = emlxs_node_find_did(port, did);
8759 
8760 			if (ndlp && ndlp->nlp_active) {
8761 				/* Close the node for any further normal IO */
8762 				emlxs_node_close(port, ndlp, hba->channel_fcp,
8763 				    pkt->pkt_timeout + 10);
8764 
8765 				/* Flush tx queues */
8766 				(void) emlxs_tx_node_flush(port, ndlp,
8767 				    &hba->chan[hba->channel_fcp], 0, 0);
8768 
8769 				/* Flush chip queues */
8770 				(void) emlxs_chipq_node_flush(port,
8771 				    &hba->chan[hba->channel_fcp], ndlp, 0);
8772 			}
8773 		}
8774 
8775 		break;
8776 
8777 	case ELS_CMD_PRLO:
8778 
8779 		if (cmd == ELS_CMD_ACC) {
8780 			ndlp = emlxs_node_find_did(port, did);
8781 
8782 			if (ndlp && ndlp->nlp_active) {
8783 				/* Close the node for any further normal IO */
8784 				emlxs_node_close(port, ndlp,
8785 				    hba->channel_fcp, 60);
8786 
8787 				/* Flush tx queues */
8788 				(void) emlxs_tx_node_flush(port, ndlp,
8789 				    &hba->chan[hba->channel_fcp], 0, 0);
8790 
8791 				/* Flush chip queues */
8792 				(void) emlxs_chipq_node_flush(port,
8793 				    &hba->chan[hba->channel_fcp], ndlp, 0);
8794 			}
8795 		}
8796 
8797 		break;
8798 
8799 	case ELS_CMD_LOGO:
8800 
8801 		if (cmd == ELS_CMD_ACC) {
8802 			ndlp = emlxs_node_find_did(port, did);
8803 
8804 			if (ndlp && ndlp->nlp_active) {
8805 				/* Close the node for any further normal IO */
8806 				emlxs_node_close(port, ndlp,
8807 				    hba->channel_fcp, 60);
8808 				emlxs_node_close(port, ndlp,
8809 				    hba->channel_ip, 60);
8810 
8811 				/* Flush tx queues */
8812 				(void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0);
8813 
8814 				/* Flush chip queues */
8815 				(void) emlxs_chipq_node_flush(port, 0, ndlp, 0);
8816 			}
8817 		}
8818 
8819 		break;
8820 	}
8821 
8822 	if (pkt->pkt_cmdlen) {
8823 		EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
8824 		    DDI_DMA_SYNC_FORDEV);
8825 	}
8826 
8827 	HBASTATS.ElsRspIssued++;
8828 
8829 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
8830 
8831 	return (FC_SUCCESS);
8832 
8833 } /* emlxs_send_els_rsp() */
8834 
8835 
8836 #ifdef MENLO_SUPPORT
8837 static int32_t
8838 emlxs_send_menlo(emlxs_port_t *port, emlxs_buf_t *sbp)
8839 {
8840 	emlxs_hba_t	*hba = HBA;
8841 	fc_packet_t	*pkt;
8842 	IOCBQ		*iocbq;
8843 	IOCB		*iocb;
8844 	CHANNEL		*cp;
8845 	NODELIST	*ndlp;
8846 	uint32_t	did;
8847 	uint32_t	*lp;
8848 	int32_t		rval;
8849 
8850 	pkt = PRIV2PKT(sbp);
8851 	did = EMLXS_MENLO_DID;
8852 	lp = (uint32_t *)pkt->pkt_cmd;
8853 
8854 	iocbq = &sbp->iocbq;
8855 	iocb = &iocbq->iocb;
8856 
8857 	ndlp = emlxs_node_find_did(port, did);
8858 
8859 	if (!ndlp || !ndlp->nlp_active) {
8860 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
8861 		    "Node not found. did=0x%x", did);
8862 
8863 		return (FC_BADPACKET);
8864 	}
8865 
8866 	iocbq->node = (void *) ndlp;
8867 	if ((rval = EMLXS_SLI_PREP_CT_IOCB(port, sbp)) != FC_SUCCESS) {
8868 
8869 		if (rval == 0xff) {
8870 			emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
8871 			rval = FC_SUCCESS;
8872 		}
8873 
8874 		return (rval);
8875 	}
8876 
8877 	cp = &hba->chan[hba->channel_ct];
8878 	cp->ulpSendCmd++;
8879 
8880 	if (pkt->pkt_tran_type == FC_PKT_EXCHANGE) {
8881 		/* Cmd phase */
8882 
8883 		/* Initalize iocb */
8884 		iocb->un.genreq64.param = pkt->pkt_cmd_fhdr.d_id;
8885 		iocb->ULPCONTEXT = 0;
8886 		iocb->ULPPU = 3;
8887 
8888 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg,
8889 		    "%s: [%08x,%08x,%08x,%08x]",
8890 		    emlxs_menlo_cmd_xlate(BE_SWAP32(lp[0])), BE_SWAP32(lp[1]),
8891 		    BE_SWAP32(lp[2]), BE_SWAP32(lp[3]), BE_SWAP32(lp[4]));
8892 
8893 	} else {	/* FC_PKT_OUTBOUND */
8894 
8895 		/* MENLO_CMD_FW_DOWNLOAD Data Phase */
8896 		iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CX;
8897 
8898 		/* Initalize iocb */
8899 		iocb->un.genreq64.param = 0;
8900 		iocb->ULPCONTEXT = pkt->pkt_cmd_fhdr.rx_id;
8901 		iocb->ULPPU = 1;
8902 
8903 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg,
8904 		    "%s: Data: rxid=0x%x size=%d",
8905 		    emlxs_menlo_cmd_xlate(MENLO_CMD_FW_DOWNLOAD),
8906 		    pkt->pkt_cmd_fhdr.rx_id, pkt->pkt_cmdlen);
8907 	}
8908 
8909 	/* Initalize sbp */
8910 	mutex_enter(&sbp->mtx);
8911 	sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
8912 	    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
8913 	sbp->node = (void *) ndlp;
8914 	sbp->lun = 0;
8915 	sbp->class = iocb->ULPCLASS;
8916 	sbp->did = did;
8917 	mutex_exit(&sbp->mtx);
8918 
8919 	EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
8920 	    DDI_DMA_SYNC_FORDEV);
8921 
8922 	HBASTATS.CtCmdIssued++;
8923 
8924 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
8925 
8926 	return (FC_SUCCESS);
8927 
8928 } /* emlxs_send_menlo() */
8929 #endif /* MENLO_SUPPORT */
8930 
8931 
8932 static int32_t
8933 emlxs_send_ct(emlxs_port_t *port, emlxs_buf_t *sbp)
8934 {
8935 	emlxs_hba_t	*hba = HBA;
8936 	fc_packet_t	*pkt;
8937 	IOCBQ		*iocbq;
8938 	IOCB		*iocb;
8939 	NODELIST	*ndlp;
8940 	uint32_t	did;
8941 	CHANNEL		*cp;
8942 	int32_t 	rval;
8943 
8944 	pkt = PRIV2PKT(sbp);
8945 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
8946 
8947 	iocbq = &sbp->iocbq;
8948 	iocb = &iocbq->iocb;
8949 
8950 	ndlp = emlxs_node_find_did(port, did);
8951 
8952 	if (!ndlp || !ndlp->nlp_active) {
8953 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
8954 		    "Node not found. did=0x%x", did);
8955 
8956 		return (FC_BADPACKET);
8957 	}
8958 
8959 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
8960 	emlxs_swap_ct_pkt(sbp);
8961 #endif	/* EMLXS_MODREV2X */
8962 
8963 	iocbq->node = (void *)ndlp;
8964 	if ((rval = EMLXS_SLI_PREP_CT_IOCB(port, sbp)) != FC_SUCCESS) {
8965 
8966 		if (rval == 0xff) {
8967 			emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
8968 			rval = FC_SUCCESS;
8969 		}
8970 
8971 		return (rval);
8972 	}
8973 
8974 	cp = &hba->chan[hba->channel_ct];
8975 	cp->ulpSendCmd++;
8976 
8977 	/* Initalize sbp */
8978 	mutex_enter(&sbp->mtx);
8979 	sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
8980 	    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
8981 	sbp->node = (void *)ndlp;
8982 	sbp->lun = 0;
8983 	sbp->class = iocb->ULPCLASS;
8984 	sbp->did = did;
8985 	mutex_exit(&sbp->mtx);
8986 
8987 	if (did == NAMESERVER_DID) {
8988 		SLI_CT_REQUEST	*CtCmd;
8989 		uint32_t	*lp0;
8990 
8991 		CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd;
8992 		lp0 = (uint32_t *)pkt->pkt_cmd;
8993 
8994 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg,
8995 		    "%s: did=%x [%08x,%08x]",
8996 		    emlxs_ctcmd_xlate(
8997 		    LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp)),
8998 		    did, LE_SWAP32(lp0[4]), LE_SWAP32(lp0[5]));
8999 
9000 		if (hba->flag & FC_NPIV_DELAY_REQUIRED) {
9001 			sbp->pkt_flags |= PACKET_DELAY_REQUIRED;
9002 		}
9003 
9004 	} else if (did == FDMI_DID) {
9005 		SLI_CT_REQUEST	*CtCmd;
9006 		uint32_t	*lp0;
9007 
9008 		CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd;
9009 		lp0 = (uint32_t *)pkt->pkt_cmd;
9010 
9011 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg,
9012 		    "%s: did=%x [%08x,%08x]",
9013 		    emlxs_mscmd_xlate(
9014 		    LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp)),
9015 		    did, LE_SWAP32(lp0[4]), LE_SWAP32(lp0[5]));
9016 	} else {
9017 		SLI_CT_REQUEST	*CtCmd;
9018 		uint32_t	*lp0;
9019 
9020 		CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd;
9021 		lp0 = (uint32_t *)pkt->pkt_cmd;
9022 
9023 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg,
9024 		    "%s: did=%x [%08x,%08x]",
9025 		    emlxs_rmcmd_xlate(
9026 		    LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp)),
9027 		    did, LE_SWAP32(lp0[4]), LE_SWAP32(lp0[5]));
9028 	}
9029 
9030 	if (pkt->pkt_cmdlen) {
9031 		EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
9032 		    DDI_DMA_SYNC_FORDEV);
9033 	}
9034 
9035 	HBASTATS.CtCmdIssued++;
9036 
9037 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
9038 
9039 	return (FC_SUCCESS);
9040 
9041 } /* emlxs_send_ct() */
9042 
9043 
9044 static int32_t
9045 emlxs_send_ct_rsp(emlxs_port_t *port, emlxs_buf_t *sbp)
9046 {
9047 	emlxs_hba_t	*hba = HBA;
9048 	fc_packet_t	*pkt;
9049 	CHANNEL		*cp;
9050 	IOCBQ		*iocbq;
9051 	IOCB		*iocb;
9052 	uint32_t	*cmd;
9053 	SLI_CT_REQUEST	*CtCmd;
9054 	int32_t 	rval;
9055 
9056 	pkt = PRIV2PKT(sbp);
9057 	CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd;
9058 	cmd = (uint32_t *)pkt->pkt_cmd;
9059 
9060 	iocbq = &sbp->iocbq;
9061 	iocb = &iocbq->iocb;
9062 
9063 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
9064 	emlxs_swap_ct_pkt(sbp);
9065 #endif	/* EMLXS_MODREV2X */
9066 
9067 	if ((rval = EMLXS_SLI_PREP_CT_IOCB(port, sbp)) != FC_SUCCESS) {
9068 
9069 		if (rval == 0xff) {
9070 			emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
9071 			rval = FC_SUCCESS;
9072 		}
9073 
9074 		return (rval);
9075 	}
9076 
9077 	cp = &hba->chan[hba->channel_ct];
9078 	cp->ulpSendCmd++;
9079 
9080 	/* Initalize sbp */
9081 	mutex_enter(&sbp->mtx);
9082 	sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
9083 	    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
9084 	sbp->node = NULL;
9085 	sbp->lun = 0;
9086 	sbp->class = iocb->ULPCLASS;
9087 	mutex_exit(&sbp->mtx);
9088 
9089 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_reply_msg,
9090 	    "%s: Rsn=%x Exp=%x [%08x,%08x] rxid=%x ",
9091 	    emlxs_rmcmd_xlate(LE_SWAP16(
9092 	    CtCmd->CommandResponse.bits.CmdRsp)),
9093 	    CtCmd->ReasonCode, CtCmd->Explanation,
9094 	    LE_SWAP32(cmd[4]), LE_SWAP32(cmd[5]),
9095 	    pkt->pkt_cmd_fhdr.rx_id);
9096 
9097 	if (pkt->pkt_cmdlen) {
9098 		EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
9099 		    DDI_DMA_SYNC_FORDEV);
9100 	}
9101 
9102 	HBASTATS.CtRspIssued++;
9103 
9104 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
9105 
9106 	return (FC_SUCCESS);
9107 
9108 } /* emlxs_send_ct_rsp() */
9109 
9110 
9111 /*
9112  * emlxs_get_instance()
9113  * Given a ddi ddiinst, return a Fibre Channel (emlx) ddiinst.
9114  */
9115 extern uint32_t
9116 emlxs_get_instance(int32_t ddiinst)
9117 {
9118 	uint32_t i;
9119 	uint32_t inst;
9120 
9121 	mutex_enter(&emlxs_device.lock);
9122 
9123 	inst = MAX_FC_BRDS;
9124 	for (i = 0; i < emlxs_instance_count; i++) {
9125 		if (emlxs_instance[i] == ddiinst) {
9126 			inst = i;
9127 			break;
9128 		}
9129 	}
9130 
9131 	mutex_exit(&emlxs_device.lock);
9132 
9133 	return (inst);
9134 
9135 } /* emlxs_get_instance() */
9136 
9137 
9138 /*
9139  * emlxs_add_instance()
9140  * Given a ddi ddiinst, create a Fibre Channel (emlx) ddiinst.
9141  * emlx ddiinsts are the order that emlxs_attach gets called, starting at 0.
9142  */
9143 static uint32_t
9144 emlxs_add_instance(int32_t ddiinst)
9145 {
9146 	uint32_t i;
9147 
9148 	mutex_enter(&emlxs_device.lock);
9149 
9150 	/* First see if the ddiinst already exists */
9151 	for (i = 0; i < emlxs_instance_count; i++) {
9152 		if (emlxs_instance[i] == ddiinst) {
9153 			break;
9154 		}
9155 	}
9156 
9157 	/* If it doesn't already exist, add it */
9158 	if (i >= emlxs_instance_count) {
9159 		if ((i = emlxs_instance_count) < MAX_FC_BRDS) {
9160 			emlxs_instance[i] = ddiinst;
9161 			emlxs_instance_count++;
9162 			emlxs_device.hba_count = emlxs_instance_count;
9163 		}
9164 	}
9165 
9166 	mutex_exit(&emlxs_device.lock);
9167 
9168 	return (i);
9169 
9170 } /* emlxs_add_instance() */
9171 
9172 
9173 /*ARGSUSED*/
9174 extern void
9175 emlxs_pkt_complete(emlxs_buf_t *sbp, uint32_t iostat, uint8_t localstat,
9176     uint32_t doneq)
9177 {
9178 	emlxs_hba_t	*hba;
9179 	emlxs_port_t	*port;
9180 	emlxs_buf_t	*fpkt;
9181 
9182 	port = sbp->port;
9183 
9184 	if (!port) {
9185 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_completion_error_msg,
9186 		    "NULL port found. sbp=%p flags=%x", sbp, sbp->pkt_flags);
9187 
9188 		return;
9189 	}
9190 
9191 	hba = HBA;
9192 
9193 	mutex_enter(&sbp->mtx);
9194 
9195 	/* Check for error conditions */
9196 	if (sbp->pkt_flags & (PACKET_ULP_OWNED | PACKET_COMPLETED |
9197 	    PACKET_IN_DONEQ | PACKET_IN_COMPLETION |
9198 	    PACKET_IN_TXQ | PACKET_IN_CHIPQ)) {
9199 		if (sbp->pkt_flags & PACKET_ULP_OWNED) {
9200 			EMLXS_MSGF(EMLXS_CONTEXT,
9201 			    &emlxs_pkt_completion_error_msg,
9202 			    "Packet already returned. sbp=%p flags=%x", sbp,
9203 			    sbp->pkt_flags);
9204 		}
9205 
9206 		else if (sbp->pkt_flags & PACKET_COMPLETED) {
9207 			EMLXS_MSGF(EMLXS_CONTEXT,
9208 			    &emlxs_pkt_completion_error_msg,
9209 			    "Packet already completed. sbp=%p flags=%x", sbp,
9210 			    sbp->pkt_flags);
9211 		}
9212 
9213 		else if (sbp->pkt_flags & PACKET_IN_DONEQ) {
9214 			EMLXS_MSGF(EMLXS_CONTEXT,
9215 			    &emlxs_pkt_completion_error_msg,
9216 			    "Pkt already on done queue. sbp=%p flags=%x", sbp,
9217 			    sbp->pkt_flags);
9218 		}
9219 
9220 		else if (sbp->pkt_flags & PACKET_IN_COMPLETION) {
9221 			EMLXS_MSGF(EMLXS_CONTEXT,
9222 			    &emlxs_pkt_completion_error_msg,
9223 			    "Packet already in completion. sbp=%p flags=%x",
9224 			    sbp, sbp->pkt_flags);
9225 		}
9226 
9227 		else if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
9228 			EMLXS_MSGF(EMLXS_CONTEXT,
9229 			    &emlxs_pkt_completion_error_msg,
9230 			    "Packet still on chip queue. sbp=%p flags=%x",
9231 			    sbp, sbp->pkt_flags);
9232 		}
9233 
9234 		else if (sbp->pkt_flags & PACKET_IN_TXQ) {
9235 			EMLXS_MSGF(EMLXS_CONTEXT,
9236 			    &emlxs_pkt_completion_error_msg,
9237 			    "Packet still on tx queue. sbp=%p flags=%x", sbp,
9238 			    sbp->pkt_flags);
9239 		}
9240 
9241 		mutex_exit(&sbp->mtx);
9242 		return;
9243 	}
9244 
9245 	/* Packet is now in completion */
9246 	sbp->pkt_flags |= PACKET_IN_COMPLETION;
9247 
9248 	/* Set the state if not already set */
9249 	if (!(sbp->pkt_flags & PACKET_STATE_VALID)) {
9250 		emlxs_set_pkt_state(sbp, iostat, localstat, 0);
9251 	}
9252 
9253 	/* Check for parent flush packet */
9254 	/* If pkt has a parent flush packet then adjust its count now */
9255 	fpkt = sbp->fpkt;
9256 	if (fpkt) {
9257 		/*
9258 		 * We will try to NULL sbp->fpkt inside the
9259 		 * fpkt's mutex if possible
9260 		 */
9261 
9262 		if (!(fpkt->pkt_flags & PACKET_ULP_OWNED)) {
9263 			mutex_enter(&fpkt->mtx);
9264 			if (fpkt->flush_count) {
9265 				fpkt->flush_count--;
9266 			}
9267 			sbp->fpkt = NULL;
9268 			mutex_exit(&fpkt->mtx);
9269 		} else {	/* fpkt has been returned already */
9270 
9271 			sbp->fpkt = NULL;
9272 		}
9273 	}
9274 
9275 	/* If pkt is polled, then wake up sleeping thread */
9276 	if (sbp->pkt_flags & PACKET_POLLED) {
9277 		/* Don't set the PACKET_ULP_OWNED flag here */
9278 		/* because the polling thread will do it */
9279 		sbp->pkt_flags |= PACKET_COMPLETED;
9280 		mutex_exit(&sbp->mtx);
9281 
9282 		/* Wake up sleeping thread */
9283 		mutex_enter(&EMLXS_PKT_LOCK);
9284 		cv_broadcast(&EMLXS_PKT_CV);
9285 		mutex_exit(&EMLXS_PKT_LOCK);
9286 	}
9287 
9288 	/* If packet was generated by our driver, */
9289 	/* then complete it immediately */
9290 	else if (sbp->pkt_flags & PACKET_ALLOCATED) {
9291 		mutex_exit(&sbp->mtx);
9292 
9293 		emlxs_iodone(sbp);
9294 	}
9295 
9296 	/* Put the pkt on the done queue for callback */
9297 	/* completion in another thread */
9298 	else {
9299 		sbp->pkt_flags |= PACKET_IN_DONEQ;
9300 		sbp->next = NULL;
9301 		mutex_exit(&sbp->mtx);
9302 
9303 		/* Put pkt on doneq, so I/O's will be completed in order */
9304 		mutex_enter(&EMLXS_PORT_LOCK);
9305 		if (hba->iodone_tail == NULL) {
9306 			hba->iodone_list = sbp;
9307 			hba->iodone_count = 1;
9308 		} else {
9309 			hba->iodone_tail->next = sbp;
9310 			hba->iodone_count++;
9311 		}
9312 		hba->iodone_tail = sbp;
9313 		mutex_exit(&EMLXS_PORT_LOCK);
9314 
9315 		/* Trigger a thread to service the doneq */
9316 		emlxs_thread_trigger1(&hba->iodone_thread,
9317 		    emlxs_iodone_server);
9318 	}
9319 
9320 	return;
9321 
9322 } /* emlxs_pkt_complete() */
9323 
9324 
9325 #ifdef SAN_DIAG_SUPPORT
9326 /*
9327  * This routine is called with EMLXS_PORT_LOCK held so we can just increment
9328  * normally. Don't have to use atomic operations.
9329  */
9330 extern void
9331 emlxs_update_sd_bucket(emlxs_buf_t *sbp)
9332 {
9333 	emlxs_port_t	*vport;
9334 	fc_packet_t	*pkt;
9335 	uint32_t	did;
9336 	hrtime_t	t;
9337 	hrtime_t	delta_time;
9338 	int		i;
9339 	NODELIST	*ndlp;
9340 
9341 	vport = sbp->port;
9342 
9343 	if ((sd_bucket.search_type == 0) ||
9344 	    (vport->sd_io_latency_state != SD_COLLECTING))
9345 		return;
9346 
9347 	/* Compute the iolatency time in microseconds */
9348 	t = gethrtime();
9349 	delta_time = t - sbp->sd_start_time;
9350 	pkt = PRIV2PKT(sbp);
9351 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
9352 	ndlp = emlxs_node_find_did(vport, did);
9353 
9354 	if (ndlp) {
9355 		if (delta_time >=
9356 		    sd_bucket.values[SD_IO_LATENCY_MAX_BUCKETS - 1])
9357 			ndlp->sd_dev_bucket[SD_IO_LATENCY_MAX_BUCKETS - 1].
9358 			    count++;
9359 		else if (delta_time <= sd_bucket.values[0])
9360 			ndlp->sd_dev_bucket[0].count++;
9361 		else {
9362 			for (i = 1; i < SD_IO_LATENCY_MAX_BUCKETS; i++) {
9363 				if ((delta_time > sd_bucket.values[i-1]) &&
9364 				    (delta_time <= sd_bucket.values[i])) {
9365 					ndlp->sd_dev_bucket[i].count++;
9366 					break;
9367 				}
9368 			}
9369 		}
9370 	}
9371 }
9372 #endif /* SAN_DIAG_SUPPORT */
9373 
9374 /*ARGSUSED*/
9375 static void
9376 emlxs_iodone_server(void *arg1, void *arg2, void *arg3)
9377 {
9378 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
9379 	emlxs_buf_t *sbp;
9380 
9381 	mutex_enter(&EMLXS_PORT_LOCK);
9382 
9383 	/* Remove one pkt from the doneq head and complete it */
9384 	while ((sbp = hba->iodone_list) != NULL) {
9385 		if ((hba->iodone_list = sbp->next) == NULL) {
9386 			hba->iodone_tail = NULL;
9387 			hba->iodone_count = 0;
9388 		} else {
9389 			hba->iodone_count--;
9390 		}
9391 
9392 		mutex_exit(&EMLXS_PORT_LOCK);
9393 
9394 		/* Prepare the pkt for completion */
9395 		mutex_enter(&sbp->mtx);
9396 		sbp->next = NULL;
9397 		sbp->pkt_flags &= ~PACKET_IN_DONEQ;
9398 		mutex_exit(&sbp->mtx);
9399 
9400 		/* Complete the IO now */
9401 		emlxs_iodone(sbp);
9402 
9403 		/* Reacquire lock and check if more work is to be done */
9404 		mutex_enter(&EMLXS_PORT_LOCK);
9405 	}
9406 
9407 	mutex_exit(&EMLXS_PORT_LOCK);
9408 
9409 	return;
9410 
9411 } /* End emlxs_iodone_server */
9412 
9413 
9414 static void
9415 emlxs_iodone(emlxs_buf_t *sbp)
9416 {
9417 	fc_packet_t	*pkt;
9418 	CHANNEL		*cp;
9419 
9420 	pkt = PRIV2PKT(sbp);
9421 
9422 	/* Check one more time that the  pkt has not already been returned */
9423 	if (sbp->pkt_flags & PACKET_ULP_OWNED) {
9424 		return;
9425 	}
9426 	cp = (CHANNEL *)sbp->channel;
9427 
9428 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
9429 	emlxs_unswap_pkt(sbp);
9430 #endif	/* EMLXS_MODREV2X */
9431 
9432 	mutex_enter(&sbp->mtx);
9433 	sbp->pkt_flags |= (PACKET_COMPLETED | PACKET_ULP_OWNED);
9434 	mutex_exit(&sbp->mtx);
9435 
9436 	if (pkt->pkt_comp) {
9437 		cp->ulpCmplCmd++;
9438 		(*pkt->pkt_comp) (pkt);
9439 	}
9440 
9441 	return;
9442 
9443 } /* emlxs_iodone() */
9444 
9445 
9446 
9447 extern fc_unsol_buf_t *
9448 emlxs_ub_find(emlxs_port_t *port, uint32_t token)
9449 {
9450 	emlxs_unsol_buf_t	*pool;
9451 	fc_unsol_buf_t		*ubp;
9452 	emlxs_ub_priv_t		*ub_priv;
9453 
9454 	/* Check if this is a valid ub token */
9455 	if (token < EMLXS_UB_TOKEN_OFFSET) {
9456 		return (NULL);
9457 	}
9458 
9459 	mutex_enter(&EMLXS_UB_LOCK);
9460 
9461 	pool = port->ub_pool;
9462 	while (pool) {
9463 		/* Find a pool with the proper token range */
9464 		if (token >= pool->pool_first_token &&
9465 		    token <= pool->pool_last_token) {
9466 			ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[(token -
9467 			    pool->pool_first_token)];
9468 			ub_priv = ubp->ub_fca_private;
9469 
9470 			if (ub_priv->token != token) {
9471 				EMLXS_MSGF(EMLXS_CONTEXT,
9472 				    &emlxs_sfs_debug_msg,
9473 				    "ub_find: Invalid token=%x", ubp, token,
9474 				    ub_priv->token);
9475 
9476 				ubp = NULL;
9477 			}
9478 
9479 			else if (!(ub_priv->flags & EMLXS_UB_IN_USE)) {
9480 				EMLXS_MSGF(EMLXS_CONTEXT,
9481 				    &emlxs_sfs_debug_msg,
9482 				    "ub_find: Buffer not in use. buffer=%p "
9483 				    "token=%x", ubp, token);
9484 
9485 				ubp = NULL;
9486 			}
9487 
9488 			mutex_exit(&EMLXS_UB_LOCK);
9489 
9490 			return (ubp);
9491 		}
9492 
9493 		pool = pool->pool_next;
9494 	}
9495 
9496 	mutex_exit(&EMLXS_UB_LOCK);
9497 
9498 	return (NULL);
9499 
9500 } /* emlxs_ub_find() */
9501 
9502 
9503 
9504 extern fc_unsol_buf_t *
9505 emlxs_ub_get(emlxs_port_t *port, uint32_t size, uint32_t type,
9506     uint32_t reserve)
9507 {
9508 	emlxs_hba_t		*hba = HBA;
9509 	emlxs_unsol_buf_t	*pool;
9510 	fc_unsol_buf_t		*ubp;
9511 	emlxs_ub_priv_t		*ub_priv;
9512 	uint32_t		i;
9513 	uint32_t		resv_flag;
9514 	uint32_t		pool_free;
9515 	uint32_t		pool_free_resv;
9516 
9517 	mutex_enter(&EMLXS_UB_LOCK);
9518 
9519 	pool = port->ub_pool;
9520 	while (pool) {
9521 		/* Find a pool of the appropriate type and size */
9522 		if ((pool->pool_available == 0) ||
9523 		    (pool->pool_type != type) ||
9524 		    (pool->pool_buf_size < size)) {
9525 			goto next_pool;
9526 		}
9527 
9528 
9529 		/* Adjust free counts based on availablity    */
9530 		/* The free reserve count gets first priority */
9531 		pool_free_resv =
9532 		    min(pool->pool_free_resv, pool->pool_available);
9533 		pool_free =
9534 		    min(pool->pool_free,
9535 		    (pool->pool_available - pool_free_resv));
9536 
9537 		/* Initialize reserve flag */
9538 		resv_flag = reserve;
9539 
9540 		if (resv_flag) {
9541 			if (pool_free_resv == 0) {
9542 				if (pool_free == 0) {
9543 					goto next_pool;
9544 				}
9545 				resv_flag = 0;
9546 			}
9547 		} else if (pool_free == 0) {
9548 			goto next_pool;
9549 		}
9550 
9551 		/* Find next available free buffer in this pool */
9552 		for (i = 0; i < pool->pool_nentries; i++) {
9553 			ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[i];
9554 			ub_priv = ubp->ub_fca_private;
9555 
9556 			if (!ub_priv->available ||
9557 			    ub_priv->flags != EMLXS_UB_FREE) {
9558 				continue;
9559 			}
9560 
9561 			ub_priv->time = hba->timer_tics;
9562 
9563 			/* Timeout in 5 minutes */
9564 			ub_priv->timeout = (5 * 60);
9565 
9566 			ub_priv->flags = EMLXS_UB_IN_USE;
9567 
9568 			/* Alloc the buffer from the pool */
9569 			if (resv_flag) {
9570 				ub_priv->flags |= EMLXS_UB_RESV;
9571 				pool->pool_free_resv--;
9572 			} else {
9573 				pool->pool_free--;
9574 			}
9575 
9576 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
9577 			    "ub_get: ubp=%p token=%x (%d,%d,%d,%d)", ubp,
9578 			    ub_priv->token, pool->pool_nentries,
9579 			    pool->pool_available, pool->pool_free,
9580 			    pool->pool_free_resv);
9581 
9582 			mutex_exit(&EMLXS_UB_LOCK);
9583 
9584 			return (ubp);
9585 		}
9586 next_pool:
9587 
9588 		pool = pool->pool_next;
9589 	}
9590 
9591 	mutex_exit(&EMLXS_UB_LOCK);
9592 
9593 	return (NULL);
9594 
9595 } /* emlxs_ub_get() */
9596 
9597 
9598 
9599 extern void
9600 emlxs_set_pkt_state(emlxs_buf_t *sbp, uint32_t iostat, uint8_t localstat,
9601     uint32_t lock)
9602 {
9603 	fc_packet_t		*pkt;
9604 	fcp_rsp_t		*fcp_rsp;
9605 	uint32_t		i;
9606 	emlxs_xlat_err_t	*tptr;
9607 	emlxs_xlat_err_t	*entry;
9608 
9609 
9610 	pkt = PRIV2PKT(sbp);
9611 
9612 	if (lock) {
9613 		mutex_enter(&sbp->mtx);
9614 	}
9615 
9616 	if (!(sbp->pkt_flags & PACKET_STATE_VALID)) {
9617 		sbp->pkt_flags |= PACKET_STATE_VALID;
9618 
9619 		/* Perform table lookup */
9620 		entry = NULL;
9621 		if (iostat != IOSTAT_LOCAL_REJECT) {
9622 			tptr = emlxs_iostat_tbl;
9623 			for (i = 0; i < IOSTAT_MAX; i++, tptr++) {
9624 				if (iostat == tptr->emlxs_status) {
9625 					entry = tptr;
9626 					break;
9627 		}
9628 			}
9629 		} else {	/* iostate == IOSTAT_LOCAL_REJECT */
9630 
9631 			tptr = emlxs_ioerr_tbl;
9632 			for (i = 0; i < IOERR_MAX; i++, tptr++) {
9633 				if (localstat == tptr->emlxs_status) {
9634 					entry = tptr;
9635 					break;
9636 		}
9637 			}
9638 		}
9639 
9640 		if (entry) {
9641 			pkt->pkt_state  = entry->pkt_state;
9642 			pkt->pkt_reason = entry->pkt_reason;
9643 			pkt->pkt_expln  = entry->pkt_expln;
9644 			pkt->pkt_action = entry->pkt_action;
9645 		} else {
9646 			/* Set defaults */
9647 			pkt->pkt_state  = FC_PKT_TRAN_ERROR;
9648 			pkt->pkt_reason = FC_REASON_ABORTED;
9649 			pkt->pkt_expln  = FC_EXPLN_NONE;
9650 			pkt->pkt_action = FC_ACTION_RETRYABLE;
9651 		}
9652 
9653 
9654 		/* Set the residual counts and response frame */
9655 		/* Check if response frame was received from the chip */
9656 		/* If so, then the residual counts will already be set */
9657 		if (!(sbp->pkt_flags & (PACKET_FCP_RSP_VALID |
9658 		    PACKET_CT_RSP_VALID | PACKET_ELS_RSP_VALID))) {
9659 			/* We have to create the response frame */
9660 			if (iostat == IOSTAT_SUCCESS) {
9661 				pkt->pkt_resp_resid = 0;
9662 				pkt->pkt_data_resid = 0;
9663 
9664 				if ((pkt->pkt_cmd_fhdr.type ==
9665 				    FC_TYPE_SCSI_FCP) && pkt->pkt_rsplen &&
9666 				    pkt->pkt_resp) {
9667 					fcp_rsp = (fcp_rsp_t *)pkt->pkt_resp;
9668 
9669 					fcp_rsp->fcp_u.fcp_status.
9670 					    rsp_len_set = 1;
9671 					fcp_rsp->fcp_response_len = 8;
9672 				}
9673 			} else {
9674 				/* Otherwise assume no data */
9675 				/* and no response received */
9676 				pkt->pkt_data_resid = pkt->pkt_datalen;
9677 				pkt->pkt_resp_resid = pkt->pkt_rsplen;
9678 			}
9679 		}
9680 	}
9681 
9682 	if (lock) {
9683 		mutex_exit(&sbp->mtx);
9684 	}
9685 
9686 	return;
9687 
9688 } /* emlxs_set_pkt_state() */
9689 
9690 
9691 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
9692 
9693 extern void
9694 emlxs_swap_service_params(SERV_PARM *sp)
9695 {
9696 	uint16_t	*p;
9697 	int		size;
9698 	int		i;
9699 
9700 	size = (sizeof (CSP) - 4) / 2;
9701 	p = (uint16_t *)&sp->cmn;
9702 	for (i = 0; i < size; i++) {
9703 		p[i] = LE_SWAP16(p[i]);
9704 	}
9705 	sp->cmn.e_d_tov = LE_SWAP32(sp->cmn.e_d_tov);
9706 
9707 	size = sizeof (CLASS_PARMS) / 2;
9708 	p = (uint16_t *)&sp->cls1;
9709 	for (i = 0; i < size; i++, p++) {
9710 		*p = LE_SWAP16(*p);
9711 	}
9712 
9713 	size = sizeof (CLASS_PARMS) / 2;
9714 	p = (uint16_t *)&sp->cls2;
9715 	for (i = 0; i < size; i++, p++) {
9716 		*p = LE_SWAP16(*p);
9717 	}
9718 
9719 	size = sizeof (CLASS_PARMS) / 2;
9720 	p = (uint16_t *)&sp->cls3;
9721 	for (i = 0; i < size; i++, p++) {
9722 		*p = LE_SWAP16(*p);
9723 	}
9724 
9725 	size = sizeof (CLASS_PARMS) / 2;
9726 	p = (uint16_t *)&sp->cls4;
9727 	for (i = 0; i < size; i++, p++) {
9728 		*p = LE_SWAP16(*p);
9729 	}
9730 
9731 	return;
9732 
9733 } /* emlxs_swap_service_params() */
9734 
9735 extern void
9736 emlxs_unswap_pkt(emlxs_buf_t *sbp)
9737 {
9738 	if (sbp->pkt_flags & PACKET_FCP_SWAPPED) {
9739 		emlxs_swap_fcp_pkt(sbp);
9740 	}
9741 
9742 	else if (sbp->pkt_flags & PACKET_ELS_SWAPPED) {
9743 		emlxs_swap_els_pkt(sbp);
9744 	}
9745 
9746 	else if (sbp->pkt_flags & PACKET_CT_SWAPPED) {
9747 		emlxs_swap_ct_pkt(sbp);
9748 	}
9749 
9750 } /* emlxs_unswap_pkt() */
9751 
9752 
9753 extern void
9754 emlxs_swap_fcp_pkt(emlxs_buf_t *sbp)
9755 {
9756 	fc_packet_t	*pkt;
9757 	FCP_CMND	*cmd;
9758 	fcp_rsp_t	*rsp;
9759 	uint16_t	*lunp;
9760 	uint32_t	i;
9761 
9762 	mutex_enter(&sbp->mtx);
9763 
9764 	if (sbp->pkt_flags & PACKET_ALLOCATED) {
9765 		mutex_exit(&sbp->mtx);
9766 		return;
9767 	}
9768 
9769 	if (sbp->pkt_flags & PACKET_FCP_SWAPPED) {
9770 		sbp->pkt_flags &= ~PACKET_FCP_SWAPPED;
9771 	} else {
9772 		sbp->pkt_flags |= PACKET_FCP_SWAPPED;
9773 	}
9774 
9775 	mutex_exit(&sbp->mtx);
9776 
9777 	pkt = PRIV2PKT(sbp);
9778 
9779 	cmd = (FCP_CMND *)pkt->pkt_cmd;
9780 	rsp = (pkt->pkt_rsplen &&
9781 	    (sbp->pkt_flags & PACKET_FCP_RSP_VALID)) ?
9782 	    (fcp_rsp_t *)pkt->pkt_resp : NULL;
9783 
9784 	/* The size of data buffer needs to be swapped. */
9785 	cmd->fcpDl = LE_SWAP32(cmd->fcpDl);
9786 
9787 	/*
9788 	 * Swap first 2 words of FCP CMND payload.
9789 	 */
9790 	lunp = (uint16_t *)&cmd->fcpLunMsl;
9791 	for (i = 0; i < 4; i++) {
9792 		lunp[i] = LE_SWAP16(lunp[i]);
9793 	}
9794 
9795 	if (rsp) {
9796 		rsp->fcp_resid = LE_SWAP32(rsp->fcp_resid);
9797 		rsp->fcp_sense_len = LE_SWAP32(rsp->fcp_sense_len);
9798 		rsp->fcp_response_len = LE_SWAP32(rsp->fcp_response_len);
9799 	}
9800 
9801 	return;
9802 
9803 } /* emlxs_swap_fcp_pkt() */
9804 
9805 
9806 extern void
9807 emlxs_swap_els_pkt(emlxs_buf_t *sbp)
9808 {
9809 	fc_packet_t	*pkt;
9810 	uint32_t	*cmd;
9811 	uint32_t	*rsp;
9812 	uint32_t	command;
9813 	uint16_t	*c;
9814 	uint32_t	i;
9815 	uint32_t	swapped;
9816 
9817 	mutex_enter(&sbp->mtx);
9818 
9819 	if (sbp->pkt_flags & PACKET_ALLOCATED) {
9820 		mutex_exit(&sbp->mtx);
9821 		return;
9822 	}
9823 
9824 	if (sbp->pkt_flags & PACKET_ELS_SWAPPED) {
9825 		sbp->pkt_flags &= ~PACKET_ELS_SWAPPED;
9826 		swapped = 1;
9827 	} else {
9828 		sbp->pkt_flags |= PACKET_ELS_SWAPPED;
9829 		swapped = 0;
9830 	}
9831 
9832 	mutex_exit(&sbp->mtx);
9833 
9834 	pkt = PRIV2PKT(sbp);
9835 
9836 	cmd = (uint32_t *)pkt->pkt_cmd;
9837 	rsp = (pkt->pkt_rsplen &&
9838 	    (sbp->pkt_flags & PACKET_ELS_RSP_VALID)) ?
9839 	    (uint32_t *)pkt->pkt_resp : NULL;
9840 
9841 	if (!swapped) {
9842 		cmd[0] = LE_SWAP32(cmd[0]);
9843 		command = cmd[0] & ELS_CMD_MASK;
9844 	} else {
9845 		command = cmd[0] & ELS_CMD_MASK;
9846 		cmd[0] = LE_SWAP32(cmd[0]);
9847 	}
9848 
9849 	if (rsp) {
9850 		rsp[0] = LE_SWAP32(rsp[0]);
9851 	}
9852 
9853 	switch (command) {
9854 	case ELS_CMD_ACC:
9855 		if (sbp->ucmd == ELS_CMD_ADISC) {
9856 			/* Hard address of originator */
9857 			cmd[1] = LE_SWAP32(cmd[1]);
9858 
9859 			/* N_Port ID of originator */
9860 			cmd[6] = LE_SWAP32(cmd[6]);
9861 		}
9862 		break;
9863 
9864 	case ELS_CMD_PLOGI:
9865 	case ELS_CMD_FLOGI:
9866 	case ELS_CMD_FDISC:
9867 		if (rsp) {
9868 			emlxs_swap_service_params((SERV_PARM *) & rsp[1]);
9869 		}
9870 		break;
9871 
9872 	case ELS_CMD_RLS:
9873 		cmd[1] = LE_SWAP32(cmd[1]);
9874 
9875 		if (rsp) {
9876 			for (i = 0; i < 6; i++) {
9877 				rsp[1 + i] = LE_SWAP32(rsp[1 + i]);
9878 			}
9879 		}
9880 		break;
9881 
9882 	case ELS_CMD_ADISC:
9883 		cmd[1] = LE_SWAP32(cmd[1]);	/* Hard address of originator */
9884 		cmd[6] = LE_SWAP32(cmd[6]);	/* N_Port ID of originator */
9885 		break;
9886 
9887 	case ELS_CMD_PRLI:
9888 		c = (uint16_t *)&cmd[1];
9889 		c[1] = LE_SWAP16(c[1]);
9890 
9891 		cmd[4] = LE_SWAP32(cmd[4]);
9892 
9893 		if (rsp) {
9894 			rsp[4] = LE_SWAP32(rsp[4]);
9895 		}
9896 		break;
9897 
9898 	case ELS_CMD_SCR:
9899 		cmd[1] = LE_SWAP32(cmd[1]);
9900 		break;
9901 
9902 	case ELS_CMD_LINIT:
9903 		if (rsp) {
9904 			rsp[1] = LE_SWAP32(rsp[1]);
9905 		}
9906 		break;
9907 
9908 	default:
9909 		break;
9910 	}
9911 
9912 	return;
9913 
9914 } /* emlxs_swap_els_pkt() */
9915 
9916 
9917 extern void
9918 emlxs_swap_ct_pkt(emlxs_buf_t *sbp)
9919 {
9920 	fc_packet_t	*pkt;
9921 	uint32_t	*cmd;
9922 	uint32_t	*rsp;
9923 	uint32_t	command;
9924 	uint32_t	i;
9925 	uint32_t	swapped;
9926 
9927 	mutex_enter(&sbp->mtx);
9928 
9929 	if (sbp->pkt_flags & PACKET_ALLOCATED) {
9930 		mutex_exit(&sbp->mtx);
9931 		return;
9932 	}
9933 
9934 	if (sbp->pkt_flags & PACKET_CT_SWAPPED) {
9935 		sbp->pkt_flags &= ~PACKET_CT_SWAPPED;
9936 		swapped = 1;
9937 	} else {
9938 		sbp->pkt_flags |= PACKET_CT_SWAPPED;
9939 		swapped = 0;
9940 	}
9941 
9942 	mutex_exit(&sbp->mtx);
9943 
9944 	pkt = PRIV2PKT(sbp);
9945 
9946 	cmd = (uint32_t *)pkt->pkt_cmd;
9947 	rsp = (pkt->pkt_rsplen &&
9948 	    (sbp->pkt_flags & PACKET_CT_RSP_VALID)) ?
9949 	    (uint32_t *)pkt->pkt_resp : NULL;
9950 
9951 	if (!swapped) {
9952 		cmd[0] = 0x01000000;
9953 		command = cmd[2];
9954 	}
9955 
9956 	cmd[0] = LE_SWAP32(cmd[0]);
9957 	cmd[1] = LE_SWAP32(cmd[1]);
9958 	cmd[2] = LE_SWAP32(cmd[2]);
9959 	cmd[3] = LE_SWAP32(cmd[3]);
9960 
9961 	if (swapped) {
9962 		command = cmd[2];
9963 	}
9964 
9965 	switch ((command >> 16)) {
9966 	case SLI_CTNS_GA_NXT:
9967 		cmd[4] = LE_SWAP32(cmd[4]);
9968 		break;
9969 
9970 	case SLI_CTNS_GPN_ID:
9971 	case SLI_CTNS_GNN_ID:
9972 	case SLI_CTNS_RPN_ID:
9973 	case SLI_CTNS_RNN_ID:
9974 	case SLI_CTNS_RSPN_ID:
9975 		cmd[4] = LE_SWAP32(cmd[4]);
9976 		break;
9977 
9978 	case SLI_CTNS_RCS_ID:
9979 	case SLI_CTNS_RPT_ID:
9980 		cmd[4] = LE_SWAP32(cmd[4]);
9981 		cmd[5] = LE_SWAP32(cmd[5]);
9982 		break;
9983 
9984 	case SLI_CTNS_RFT_ID:
9985 		cmd[4] = LE_SWAP32(cmd[4]);
9986 
9987 		/* Swap FC4 types */
9988 		for (i = 0; i < 8; i++) {
9989 			cmd[5 + i] = LE_SWAP32(cmd[5 + i]);
9990 		}
9991 		break;
9992 
9993 	case SLI_CTNS_GFT_ID:
9994 		if (rsp) {
9995 			/* Swap FC4 types */
9996 			for (i = 0; i < 8; i++) {
9997 				rsp[4 + i] = LE_SWAP32(rsp[4 + i]);
9998 			}
9999 		}
10000 		break;
10001 
10002 	case SLI_CTNS_GCS_ID:
10003 	case SLI_CTNS_GSPN_ID:
10004 	case SLI_CTNS_GSNN_NN:
10005 	case SLI_CTNS_GIP_NN:
10006 	case SLI_CTNS_GIPA_NN:
10007 
10008 	case SLI_CTNS_GPT_ID:
10009 	case SLI_CTNS_GID_NN:
10010 	case SLI_CTNS_GNN_IP:
10011 	case SLI_CTNS_GIPA_IP:
10012 	case SLI_CTNS_GID_FT:
10013 	case SLI_CTNS_GID_PT:
10014 	case SLI_CTNS_GID_PN:
10015 	case SLI_CTNS_RIP_NN:
10016 	case SLI_CTNS_RIPA_NN:
10017 	case SLI_CTNS_RSNN_NN:
10018 	case SLI_CTNS_DA_ID:
10019 	case SLI_CT_RESPONSE_FS_RJT:
10020 	case SLI_CT_RESPONSE_FS_ACC:
10021 
10022 	default:
10023 		break;
10024 	}
10025 	return;
10026 
10027 } /* emlxs_swap_ct_pkt() */
10028 
10029 
10030 extern void
10031 emlxs_swap_els_ub(fc_unsol_buf_t *ubp)
10032 {
10033 	emlxs_ub_priv_t	*ub_priv;
10034 	fc_rscn_t	*rscn;
10035 	uint32_t	count;
10036 	uint32_t	i;
10037 	uint32_t	*lp;
10038 	la_els_logi_t	*logi;
10039 
10040 	ub_priv = ubp->ub_fca_private;
10041 
10042 	switch (ub_priv->cmd) {
10043 	case ELS_CMD_RSCN:
10044 		rscn = (fc_rscn_t *)ubp->ub_buffer;
10045 
10046 		rscn->rscn_payload_len = LE_SWAP16(rscn->rscn_payload_len);
10047 
10048 		count = ((rscn->rscn_payload_len - 4) / 4);
10049 		lp = (uint32_t *)ubp->ub_buffer + 1;
10050 		for (i = 0; i < count; i++, lp++) {
10051 			*lp = LE_SWAP32(*lp);
10052 		}
10053 
10054 		break;
10055 
10056 	case ELS_CMD_FLOGI:
10057 	case ELS_CMD_PLOGI:
10058 	case ELS_CMD_FDISC:
10059 	case ELS_CMD_PDISC:
10060 		logi = (la_els_logi_t *)ubp->ub_buffer;
10061 		emlxs_swap_service_params(
10062 		    (SERV_PARM *)&logi->common_service);
10063 		break;
10064 
10065 		/* ULP handles this */
10066 	case ELS_CMD_LOGO:
10067 	case ELS_CMD_PRLI:
10068 	case ELS_CMD_PRLO:
10069 	case ELS_CMD_ADISC:
10070 	default:
10071 		break;
10072 	}
10073 
10074 	return;
10075 
10076 } /* emlxs_swap_els_ub() */
10077 
10078 
10079 #endif	/* EMLXS_MODREV2X */
10080 
10081 
10082 extern char *
10083 emlxs_elscmd_xlate(uint32_t elscmd)
10084 {
10085 	static char	buffer[32];
10086 	uint32_t	i;
10087 	uint32_t	count;
10088 
10089 	count = sizeof (emlxs_elscmd_table) / sizeof (emlxs_table_t);
10090 	for (i = 0; i < count; i++) {
10091 		if (elscmd == emlxs_elscmd_table[i].code) {
10092 			return (emlxs_elscmd_table[i].string);
10093 		}
10094 	}
10095 
10096 	(void) sprintf(buffer, "ELS=0x%x", elscmd);
10097 	return (buffer);
10098 
10099 } /* emlxs_elscmd_xlate() */
10100 
10101 
10102 extern char *
10103 emlxs_ctcmd_xlate(uint32_t ctcmd)
10104 {
10105 	static char	buffer[32];
10106 	uint32_t	i;
10107 	uint32_t	count;
10108 
10109 	count = sizeof (emlxs_ctcmd_table) / sizeof (emlxs_table_t);
10110 	for (i = 0; i < count; i++) {
10111 		if (ctcmd == emlxs_ctcmd_table[i].code) {
10112 			return (emlxs_ctcmd_table[i].string);
10113 		}
10114 	}
10115 
10116 	(void) sprintf(buffer, "cmd=0x%x", ctcmd);
10117 	return (buffer);
10118 
10119 } /* emlxs_ctcmd_xlate() */
10120 
10121 
10122 #ifdef MENLO_SUPPORT
10123 extern char *
10124 emlxs_menlo_cmd_xlate(uint32_t cmd)
10125 {
10126 	static char	buffer[32];
10127 	uint32_t	i;
10128 	uint32_t	count;
10129 
10130 	count = sizeof (emlxs_menlo_cmd_table) / sizeof (emlxs_table_t);
10131 	for (i = 0; i < count; i++) {
10132 		if (cmd == emlxs_menlo_cmd_table[i].code) {
10133 			return (emlxs_menlo_cmd_table[i].string);
10134 		}
10135 	}
10136 
10137 	(void) sprintf(buffer, "Cmd=0x%x", cmd);
10138 	return (buffer);
10139 
10140 } /* emlxs_menlo_cmd_xlate() */
10141 
10142 extern char *
10143 emlxs_menlo_rsp_xlate(uint32_t rsp)
10144 {
10145 	static char	buffer[32];
10146 	uint32_t	i;
10147 	uint32_t	count;
10148 
10149 	count = sizeof (emlxs_menlo_rsp_table) / sizeof (emlxs_table_t);
10150 	for (i = 0; i < count; i++) {
10151 		if (rsp == emlxs_menlo_rsp_table[i].code) {
10152 			return (emlxs_menlo_rsp_table[i].string);
10153 		}
10154 	}
10155 
10156 	(void) sprintf(buffer, "Rsp=0x%x", rsp);
10157 	return (buffer);
10158 
10159 } /* emlxs_menlo_rsp_xlate() */
10160 
10161 #endif /* MENLO_SUPPORT */
10162 
10163 
10164 extern char *
10165 emlxs_rmcmd_xlate(uint32_t rmcmd)
10166 {
10167 	static char	buffer[32];
10168 	uint32_t	i;
10169 	uint32_t	count;
10170 
10171 	count = sizeof (emlxs_rmcmd_table) / sizeof (emlxs_table_t);
10172 	for (i = 0; i < count; i++) {
10173 		if (rmcmd == emlxs_rmcmd_table[i].code) {
10174 			return (emlxs_rmcmd_table[i].string);
10175 		}
10176 	}
10177 
10178 	(void) sprintf(buffer, "RM=0x%x", rmcmd);
10179 	return (buffer);
10180 
10181 } /* emlxs_rmcmd_xlate() */
10182 
10183 
10184 
10185 extern char *
10186 emlxs_mscmd_xlate(uint16_t mscmd)
10187 {
10188 	static char	buffer[32];
10189 	uint32_t	i;
10190 	uint32_t	count;
10191 
10192 	count = sizeof (emlxs_mscmd_table) / sizeof (emlxs_table_t);
10193 	for (i = 0; i < count; i++) {
10194 		if (mscmd == emlxs_mscmd_table[i].code) {
10195 			return (emlxs_mscmd_table[i].string);
10196 		}
10197 	}
10198 
10199 	(void) sprintf(buffer, "Cmd=0x%x", mscmd);
10200 	return (buffer);
10201 
10202 } /* emlxs_mscmd_xlate() */
10203 
10204 
10205 extern char *
10206 emlxs_state_xlate(uint8_t state)
10207 {
10208 	static char	buffer[32];
10209 	uint32_t	i;
10210 	uint32_t	count;
10211 
10212 	count = sizeof (emlxs_state_table) / sizeof (emlxs_table_t);
10213 	for (i = 0; i < count; i++) {
10214 		if (state == emlxs_state_table[i].code) {
10215 			return (emlxs_state_table[i].string);
10216 		}
10217 	}
10218 
10219 	(void) sprintf(buffer, "State=0x%x", state);
10220 	return (buffer);
10221 
10222 } /* emlxs_state_xlate() */
10223 
10224 
10225 extern char *
10226 emlxs_error_xlate(uint8_t errno)
10227 {
10228 	static char	buffer[32];
10229 	uint32_t	i;
10230 	uint32_t	count;
10231 
10232 	count = sizeof (emlxs_error_table) / sizeof (emlxs_table_t);
10233 	for (i = 0; i < count; i++) {
10234 		if (errno == emlxs_error_table[i].code) {
10235 			return (emlxs_error_table[i].string);
10236 		}
10237 	}
10238 
10239 	(void) sprintf(buffer, "Errno=0x%x", errno);
10240 	return (buffer);
10241 
10242 } /* emlxs_error_xlate() */
10243 
10244 
10245 static int
10246 emlxs_pm_lower_power(dev_info_t *dip)
10247 {
10248 	int		ddiinst;
10249 	int		emlxinst;
10250 	emlxs_config_t	*cfg;
10251 	int32_t		rval;
10252 	emlxs_hba_t	*hba;
10253 
10254 	ddiinst = ddi_get_instance(dip);
10255 	emlxinst = emlxs_get_instance(ddiinst);
10256 	hba = emlxs_device.hba[emlxinst];
10257 	cfg = &CFG;
10258 
10259 	rval = DDI_SUCCESS;
10260 
10261 	/* Lower the power level */
10262 	if (cfg[CFG_PM_SUPPORT].current) {
10263 		rval =
10264 		    pm_lower_power(dip, EMLXS_PM_ADAPTER,
10265 		    EMLXS_PM_ADAPTER_DOWN);
10266 	} else {
10267 		/* We do not have kernel support of power management enabled */
10268 		/* therefore, call our power management routine directly */
10269 		rval =
10270 		    emlxs_power(dip, EMLXS_PM_ADAPTER, EMLXS_PM_ADAPTER_DOWN);
10271 	}
10272 
10273 	return (rval);
10274 
10275 } /* emlxs_pm_lower_power() */
10276 
10277 
10278 static int
10279 emlxs_pm_raise_power(dev_info_t *dip)
10280 {
10281 	int		ddiinst;
10282 	int		emlxinst;
10283 	emlxs_config_t	*cfg;
10284 	int32_t		rval;
10285 	emlxs_hba_t	*hba;
10286 
10287 	ddiinst = ddi_get_instance(dip);
10288 	emlxinst = emlxs_get_instance(ddiinst);
10289 	hba = emlxs_device.hba[emlxinst];
10290 	cfg = &CFG;
10291 
10292 	/* Raise the power level */
10293 	if (cfg[CFG_PM_SUPPORT].current) {
10294 		rval =
10295 		    pm_raise_power(dip, EMLXS_PM_ADAPTER,
10296 		    EMLXS_PM_ADAPTER_UP);
10297 	} else {
10298 		/* We do not have kernel support of power management enabled */
10299 		/* therefore, call our power management routine directly */
10300 		rval =
10301 		    emlxs_power(dip, EMLXS_PM_ADAPTER, EMLXS_PM_ADAPTER_UP);
10302 	}
10303 
10304 	return (rval);
10305 
10306 } /* emlxs_pm_raise_power() */
10307 
10308 
10309 #ifdef IDLE_TIMER
10310 
10311 extern int
10312 emlxs_pm_busy_component(emlxs_hba_t *hba)
10313 {
10314 	emlxs_config_t	*cfg = &CFG;
10315 	int		rval;
10316 
10317 	hba->pm_active = 1;
10318 
10319 	if (hba->pm_busy) {
10320 		return (DDI_SUCCESS);
10321 	}
10322 
10323 	mutex_enter(&hba->pm_lock);
10324 
10325 	if (hba->pm_busy) {
10326 		mutex_exit(&hba->pm_lock);
10327 		return (DDI_SUCCESS);
10328 	}
10329 	hba->pm_busy = 1;
10330 
10331 	mutex_exit(&hba->pm_lock);
10332 
10333 	/* Attempt to notify system that we are busy */
10334 	if (cfg[CFG_PM_SUPPORT].current) {
10335 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
10336 		    "pm_busy_component.");
10337 
10338 		rval = pm_busy_component(dip, EMLXS_PM_ADAPTER);
10339 
10340 		if (rval != DDI_SUCCESS) {
10341 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
10342 			    "pm_busy_component failed. ret=%d", rval);
10343 
10344 			/* If this attempt failed then clear our flags */
10345 			mutex_enter(&hba->pm_lock);
10346 			hba->pm_busy = 0;
10347 			mutex_exit(&hba->pm_lock);
10348 
10349 			return (rval);
10350 		}
10351 	}
10352 
10353 	return (DDI_SUCCESS);
10354 
10355 } /* emlxs_pm_busy_component() */
10356 
10357 
10358 extern int
10359 emlxs_pm_idle_component(emlxs_hba_t *hba)
10360 {
10361 	emlxs_config_t	*cfg = &CFG;
10362 	int		rval;
10363 
10364 	if (!hba->pm_busy) {
10365 		return (DDI_SUCCESS);
10366 	}
10367 
10368 	mutex_enter(&hba->pm_lock);
10369 
10370 	if (!hba->pm_busy) {
10371 		mutex_exit(&hba->pm_lock);
10372 		return (DDI_SUCCESS);
10373 	}
10374 	hba->pm_busy = 0;
10375 
10376 	mutex_exit(&hba->pm_lock);
10377 
10378 	if (cfg[CFG_PM_SUPPORT].current) {
10379 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
10380 		    "pm_idle_component.");
10381 
10382 		rval = pm_idle_component(dip, EMLXS_PM_ADAPTER);
10383 
10384 		if (rval != DDI_SUCCESS) {
10385 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
10386 			    "pm_idle_component failed. ret=%d", rval);
10387 
10388 			/* If this attempt failed then */
10389 			/* reset our flags for another attempt */
10390 			mutex_enter(&hba->pm_lock);
10391 			hba->pm_busy = 1;
10392 			mutex_exit(&hba->pm_lock);
10393 
10394 			return (rval);
10395 		}
10396 	}
10397 
10398 	return (DDI_SUCCESS);
10399 
10400 } /* emlxs_pm_idle_component() */
10401 
10402 
10403 extern void
10404 emlxs_pm_idle_timer(emlxs_hba_t *hba)
10405 {
10406 	emlxs_config_t *cfg = &CFG;
10407 
10408 	if (hba->pm_active) {
10409 		/* Clear active flag and reset idle timer */
10410 		mutex_enter(&hba->pm_lock);
10411 		hba->pm_active = 0;
10412 		hba->pm_idle_timer =
10413 		    hba->timer_tics + cfg[CFG_PM_IDLE].current;
10414 		mutex_exit(&hba->pm_lock);
10415 	}
10416 
10417 	/* Check for idle timeout */
10418 	else if (hba->timer_tics >= hba->pm_idle_timer) {
10419 		if (emlxs_pm_idle_component(hba) == DDI_SUCCESS) {
10420 			mutex_enter(&hba->pm_lock);
10421 			hba->pm_idle_timer =
10422 			    hba->timer_tics + cfg[CFG_PM_IDLE].current;
10423 			mutex_exit(&hba->pm_lock);
10424 		}
10425 	}
10426 
10427 	return;
10428 
10429 } /* emlxs_pm_idle_timer() */
10430 
10431 #endif	/* IDLE_TIMER */
10432 
10433 
10434 static void
10435 emlxs_read_vport_prop(emlxs_hba_t *hba)
10436 {
10437 	emlxs_port_t	*port = &PPORT;
10438 	emlxs_config_t	*cfg = &CFG;
10439 	char		**arrayp;
10440 	uint8_t		*s;
10441 	uint8_t		*np;
10442 	NAME_TYPE	pwwpn;
10443 	NAME_TYPE	wwnn;
10444 	NAME_TYPE	wwpn;
10445 	uint32_t	vpi;
10446 	uint32_t	cnt;
10447 	uint32_t	rval;
10448 	uint32_t	i;
10449 	uint32_t	j;
10450 	uint32_t	c1;
10451 	uint32_t	sum;
10452 	uint32_t	errors;
10453 	char		buffer[64];
10454 
10455 	/* Check for the per adapter vport setting */
10456 	(void) sprintf(buffer, "%s%d-vport", DRIVER_NAME, hba->ddiinst);
10457 	cnt = 0;
10458 	arrayp = NULL;
10459 	rval =
10460 	    ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
10461 	    (DDI_PROP_DONTPASS), buffer, &arrayp, &cnt);
10462 
10463 	if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
10464 		/* Check for the global vport setting */
10465 		cnt = 0;
10466 		arrayp = NULL;
10467 		rval =
10468 		    ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
10469 		    (DDI_PROP_DONTPASS), "vport", &arrayp, &cnt);
10470 	}
10471 
10472 	if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
10473 		return;
10474 	}
10475 
10476 	for (i = 0; i < cnt; i++) {
10477 		errors = 0;
10478 		s = (uint8_t *)arrayp[i];
10479 
10480 		if (!s) {
10481 			break;
10482 		}
10483 
10484 		np = (uint8_t *)&pwwpn;
10485 		for (j = 0; j < sizeof (NAME_TYPE); j++) {
10486 			c1 = *s++;
10487 			if ((c1 >= '0') && (c1 <= '9')) {
10488 				sum = ((c1 - '0') << 4);
10489 			} else if ((c1 >= 'a') && (c1 <= 'f')) {
10490 				sum = ((c1 - 'a' + 10) << 4);
10491 			} else if ((c1 >= 'A') && (c1 <= 'F')) {
10492 				sum = ((c1 - 'A' + 10) << 4);
10493 			} else {
10494 				EMLXS_MSGF(EMLXS_CONTEXT,
10495 				    &emlxs_attach_debug_msg,
10496 				    "Config error: Invalid PWWPN found. "
10497 				    "entry=%d byte=%d hi_nibble=%c",
10498 				    i, j, c1);
10499 				errors++;
10500 			}
10501 
10502 			c1 = *s++;
10503 			if ((c1 >= '0') && (c1 <= '9')) {
10504 				sum |= (c1 - '0');
10505 			} else if ((c1 >= 'a') && (c1 <= 'f')) {
10506 				sum |= (c1 - 'a' + 10);
10507 			} else if ((c1 >= 'A') && (c1 <= 'F')) {
10508 				sum |= (c1 - 'A' + 10);
10509 			} else {
10510 				EMLXS_MSGF(EMLXS_CONTEXT,
10511 				    &emlxs_attach_debug_msg,
10512 				    "Config error: Invalid PWWPN found. "
10513 				    "entry=%d byte=%d lo_nibble=%c",
10514 				    i, j, c1);
10515 				errors++;
10516 			}
10517 
10518 			*np++ = sum;
10519 		}
10520 
10521 		if (*s++ != ':') {
10522 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
10523 			    "Config error: Invalid delimiter after PWWPN. "
10524 			    "entry=%d", i);
10525 			goto out;
10526 		}
10527 
10528 		np = (uint8_t *)&wwnn;
10529 		for (j = 0; j < sizeof (NAME_TYPE); j++) {
10530 			c1 = *s++;
10531 			if ((c1 >= '0') && (c1 <= '9')) {
10532 				sum = ((c1 - '0') << 4);
10533 			} else if ((c1 >= 'a') && (c1 <= 'f')) {
10534 				sum = ((c1 - 'a' + 10) << 4);
10535 			} else if ((c1 >= 'A') && (c1 <= 'F')) {
10536 				sum = ((c1 - 'A' + 10) << 4);
10537 			} else {
10538 				EMLXS_MSGF(EMLXS_CONTEXT,
10539 				    &emlxs_attach_debug_msg,
10540 				    "Config error: Invalid WWNN found. "
10541 				    "entry=%d byte=%d hi_nibble=%c",
10542 				    i, j, c1);
10543 				errors++;
10544 			}
10545 
10546 			c1 = *s++;
10547 			if ((c1 >= '0') && (c1 <= '9')) {
10548 				sum |= (c1 - '0');
10549 			} else if ((c1 >= 'a') && (c1 <= 'f')) {
10550 				sum |= (c1 - 'a' + 10);
10551 			} else if ((c1 >= 'A') && (c1 <= 'F')) {
10552 				sum |= (c1 - 'A' + 10);
10553 			} else {
10554 				EMLXS_MSGF(EMLXS_CONTEXT,
10555 				    &emlxs_attach_debug_msg,
10556 				    "Config error: Invalid WWNN found. "
10557 				    "entry=%d byte=%d lo_nibble=%c",
10558 				    i, j, c1);
10559 				errors++;
10560 			}
10561 
10562 			*np++ = sum;
10563 		}
10564 
10565 		if (*s++ != ':') {
10566 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
10567 			    "Config error: Invalid delimiter after WWNN. "
10568 			    "entry=%d", i);
10569 			goto out;
10570 		}
10571 
10572 		np = (uint8_t *)&wwpn;
10573 		for (j = 0; j < sizeof (NAME_TYPE); j++) {
10574 			c1 = *s++;
10575 			if ((c1 >= '0') && (c1 <= '9')) {
10576 				sum = ((c1 - '0') << 4);
10577 			} else if ((c1 >= 'a') && (c1 <= 'f')) {
10578 				sum = ((c1 - 'a' + 10) << 4);
10579 			} else if ((c1 >= 'A') && (c1 <= 'F')) {
10580 				sum = ((c1 - 'A' + 10) << 4);
10581 			} else {
10582 				EMLXS_MSGF(EMLXS_CONTEXT,
10583 				    &emlxs_attach_debug_msg,
10584 				    "Config error: Invalid WWPN found. "
10585 				    "entry=%d byte=%d hi_nibble=%c",
10586 				    i, j, c1);
10587 
10588 				errors++;
10589 			}
10590 
10591 			c1 = *s++;
10592 			if ((c1 >= '0') && (c1 <= '9')) {
10593 				sum |= (c1 - '0');
10594 			} else if ((c1 >= 'a') && (c1 <= 'f')) {
10595 				sum |= (c1 - 'a' + 10);
10596 			} else if ((c1 >= 'A') && (c1 <= 'F')) {
10597 				sum |= (c1 - 'A' + 10);
10598 			} else {
10599 				EMLXS_MSGF(EMLXS_CONTEXT,
10600 				    &emlxs_attach_debug_msg,
10601 				    "Config error: Invalid WWPN found. "
10602 				    "entry=%d byte=%d lo_nibble=%c",
10603 				    i, j, c1);
10604 
10605 				errors++;
10606 			}
10607 
10608 			*np++ = sum;
10609 		}
10610 
10611 		if (*s++ != ':') {
10612 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
10613 			    "Config error: Invalid delimiter after WWPN. "
10614 			    "entry=%d", i);
10615 
10616 			goto out;
10617 		}
10618 
10619 		sum = 0;
10620 		do {
10621 			c1 = *s++;
10622 			if ((c1 < '0') || (c1 > '9')) {
10623 				EMLXS_MSGF(EMLXS_CONTEXT,
10624 				    &emlxs_attach_debug_msg,
10625 				    "Config error: Invalid VPI found. "
10626 				    "entry=%d c=%c vpi=%d", i, c1, sum);
10627 
10628 				goto out;
10629 			}
10630 
10631 			sum = (sum * 10) + (c1 - '0');
10632 
10633 		} while (*s != 0);
10634 
10635 		vpi = sum;
10636 
10637 		if (errors) {
10638 			continue;
10639 		}
10640 
10641 		/* Entry has been read */
10642 
10643 		/* Check if the physical port wwpn */
10644 		/* matches our physical port wwpn */
10645 		if (bcmp((caddr_t)&hba->wwpn, (caddr_t)&pwwpn, 8)) {
10646 			continue;
10647 		}
10648 
10649 		/* Check vpi range */
10650 		if ((vpi == 0) || (vpi >= MAX_VPORTS)) {
10651 			continue;
10652 		}
10653 
10654 		/* Check if port has already been configured */
10655 		if (hba->port[vpi].flag & EMLXS_PORT_CONFIG) {
10656 			continue;
10657 		}
10658 
10659 		/* Set the highest configured vpi */
10660 		if (vpi > hba->vpi_high) {
10661 			hba->vpi_high = vpi;
10662 		}
10663 
10664 		bcopy((caddr_t)&wwnn, (caddr_t)&hba->port[vpi].wwnn,
10665 		    sizeof (NAME_TYPE));
10666 		bcopy((caddr_t)&wwpn, (caddr_t)&hba->port[vpi].wwpn,
10667 		    sizeof (NAME_TYPE));
10668 
10669 		if (hba->port[vpi].snn[0] == 0) {
10670 			(void) strncpy((caddr_t)hba->port[vpi].snn,
10671 			    (caddr_t)hba->snn, 256);
10672 		}
10673 
10674 		if (hba->port[vpi].spn[0] == 0) {
10675 			(void) sprintf((caddr_t)hba->port[vpi].spn,
10676 			    "%s VPort-%d",
10677 			    (caddr_t)hba->spn, vpi);
10678 		}
10679 
10680 		hba->port[vpi].flag |=
10681 		    (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE);
10682 
10683 		if (cfg[CFG_VPORT_RESTRICTED].current) {
10684 			hba->port[vpi].flag |= EMLXS_PORT_RESTRICTED;
10685 		}
10686 	}
10687 
10688 out:
10689 
10690 	(void) ddi_prop_free((void *) arrayp);
10691 	return;
10692 
10693 } /* emlxs_read_vport_prop() */
10694 
10695 
10696 extern char *
10697 emlxs_wwn_xlate(char *buffer, uint8_t *wwn)
10698 {
10699 	(void) sprintf(buffer, "%02x%02x%02x%02x%02x%02x%02x%02x",
10700 	    wwn[0] & 0xff, wwn[1] & 0xff, wwn[2] & 0xff, wwn[3] & 0xff,
10701 	    wwn[4] & 0xff, wwn[5] & 0xff, wwn[6] & 0xff, wwn[7] & 0xff);
10702 
10703 	return (buffer);
10704 
10705 } /* emlxs_wwn_xlate() */
10706 
10707 
10708 /* This is called at port online and offline */
10709 extern void
10710 emlxs_ub_flush(emlxs_port_t *port)
10711 {
10712 	emlxs_hba_t	*hba = HBA;
10713 	fc_unsol_buf_t	*ubp;
10714 	emlxs_ub_priv_t	*ub_priv;
10715 	emlxs_ub_priv_t	*next;
10716 
10717 	/* Return if nothing to do */
10718 	if (!port->ub_wait_head) {
10719 		return;
10720 	}
10721 
10722 	mutex_enter(&EMLXS_PORT_LOCK);
10723 	ub_priv = port->ub_wait_head;
10724 	port->ub_wait_head = NULL;
10725 	port->ub_wait_tail = NULL;
10726 	mutex_exit(&EMLXS_PORT_LOCK);
10727 
10728 	while (ub_priv) {
10729 		next = ub_priv->next;
10730 		ubp = ub_priv->ubp;
10731 
10732 		/* Check if ULP is online and we have a callback function */
10733 		if ((port->ulp_statec != FC_STATE_OFFLINE) &&
10734 		    port->ulp_unsol_cb) {
10735 			/* Send ULP the ub buffer */
10736 			port->ulp_unsol_cb(port->ulp_handle, ubp,
10737 			    ubp->ub_frame.type);
10738 		} else {	/* Drop the buffer */
10739 
10740 			(void) emlxs_ub_release(port, 1, &ubp->ub_token);
10741 		}
10742 
10743 		ub_priv = next;
10744 
10745 	}	/* while () */
10746 
10747 	return;
10748 
10749 } /* emlxs_ub_flush() */
10750 
10751 
10752 extern void
10753 emlxs_ub_callback(emlxs_port_t *port, fc_unsol_buf_t *ubp)
10754 {
10755 	emlxs_hba_t	*hba = HBA;
10756 	emlxs_ub_priv_t	*ub_priv;
10757 
10758 	ub_priv = ubp->ub_fca_private;
10759 
10760 	/* Check if ULP is online */
10761 	if (port->ulp_statec != FC_STATE_OFFLINE) {
10762 		if (port->ulp_unsol_cb) {
10763 			port->ulp_unsol_cb(port->ulp_handle, ubp,
10764 			    ubp->ub_frame.type);
10765 		} else {
10766 			(void) emlxs_ub_release(port, 1, &ubp->ub_token);
10767 		}
10768 
10769 		return;
10770 	} else {	/* ULP offline */
10771 
10772 		if (hba->state >= FC_LINK_UP) {
10773 			/* Add buffer to queue tail */
10774 			mutex_enter(&EMLXS_PORT_LOCK);
10775 
10776 			if (port->ub_wait_tail) {
10777 				port->ub_wait_tail->next = ub_priv;
10778 			}
10779 			port->ub_wait_tail = ub_priv;
10780 
10781 			if (!port->ub_wait_head) {
10782 				port->ub_wait_head = ub_priv;
10783 			}
10784 
10785 			mutex_exit(&EMLXS_PORT_LOCK);
10786 		} else {
10787 			(void) emlxs_ub_release(port, 1, &ubp->ub_token);
10788 		}
10789 	}
10790 
10791 	return;
10792 
10793 } /* emlxs_ub_callback() */
10794 
10795 
10796 static uint32_t
10797 emlxs_integrity_check(emlxs_hba_t *hba)
10798 {
10799 	uint32_t size;
10800 	uint32_t errors = 0;
10801 	int ddiinst = hba->ddiinst;
10802 
10803 	size = 16;
10804 	if (sizeof (ULP_BDL) != size) {
10805 		cmn_err(CE_WARN, "?%s%d: ULP_BDL size incorrect.  %d != 16",
10806 		    DRIVER_NAME, ddiinst, (int)sizeof (ULP_BDL));
10807 
10808 		errors++;
10809 	}
10810 	size = 8;
10811 	if (sizeof (ULP_BDE) != size) {
10812 		cmn_err(CE_WARN, "?%s%d: ULP_BDE size incorrect.  %d != 8",
10813 		    DRIVER_NAME, ddiinst, (int)sizeof (ULP_BDE));
10814 
10815 		errors++;
10816 	}
10817 	size = 12;
10818 	if (sizeof (ULP_BDE64) != size) {
10819 		cmn_err(CE_WARN, "?%s%d: ULP_BDE64 size incorrect.  %d != 12",
10820 		    DRIVER_NAME, ddiinst, (int)sizeof (ULP_BDE64));
10821 
10822 		errors++;
10823 	}
10824 	size = 16;
10825 	if (sizeof (HBQE_t) != size) {
10826 		cmn_err(CE_WARN, "?%s%d: HBQE size incorrect.  %d != 16",
10827 		    DRIVER_NAME, ddiinst, (int)sizeof (HBQE_t));
10828 
10829 		errors++;
10830 	}
10831 	size = 8;
10832 	if (sizeof (HGP) != size) {
10833 		cmn_err(CE_WARN, "?%s%d: HGP size incorrect.  %d != 8",
10834 		    DRIVER_NAME, ddiinst, (int)sizeof (HGP));
10835 
10836 		errors++;
10837 	}
10838 	if (sizeof (PGP) != size) {
10839 		cmn_err(CE_WARN, "?%s%d: PGP size incorrect.  %d != 8",
10840 		    DRIVER_NAME, ddiinst, (int)sizeof (PGP));
10841 
10842 		errors++;
10843 	}
10844 	size = 4;
10845 	if (sizeof (WORD5) != size) {
10846 		cmn_err(CE_WARN, "?%s%d: WORD5 size incorrect.  %d != 4",
10847 		    DRIVER_NAME, ddiinst, (int)sizeof (WORD5));
10848 
10849 		errors++;
10850 	}
10851 	size = 124;
10852 	if (sizeof (MAILVARIANTS) != size) {
10853 		cmn_err(CE_WARN, "?%s%d: MAILVARIANTS size incorrect.  "
10854 		    "%d != 124", DRIVER_NAME, ddiinst,
10855 		    (int)sizeof (MAILVARIANTS));
10856 
10857 		errors++;
10858 	}
10859 	size = 128;
10860 	if (sizeof (SLI1_DESC) != size) {
10861 		cmn_err(CE_WARN, "?%s%d: SLI1_DESC size incorrect.  %d != 128",
10862 		    DRIVER_NAME, ddiinst, (int)sizeof (SLI1_DESC));
10863 
10864 		errors++;
10865 	}
10866 	if (sizeof (SLI2_DESC) != size) {
10867 		cmn_err(CE_WARN, "?%s%d: SLI2_DESC size incorrect.  %d != 128",
10868 		    DRIVER_NAME, ddiinst, (int)sizeof (SLI2_DESC));
10869 
10870 		errors++;
10871 	}
10872 	size = MBOX_SIZE;
10873 	if (sizeof (MAILBOX) != size) {
10874 		cmn_err(CE_WARN, "?%s%d: MAILBOX size incorrect.  %d != %d",
10875 		    DRIVER_NAME, ddiinst, (int)sizeof (MAILBOX), MBOX_SIZE);
10876 
10877 		errors++;
10878 	}
10879 	size = PCB_SIZE;
10880 	if (sizeof (PCB) != size) {
10881 		cmn_err(CE_WARN, "?%s%d: PCB size incorrect.  %d != %d",
10882 		    DRIVER_NAME, ddiinst, (int)sizeof (PCB), PCB_SIZE);
10883 
10884 		errors++;
10885 	}
10886 	size = 260;
10887 	if (sizeof (ATTRIBUTE_ENTRY) != size) {
10888 		cmn_err(CE_WARN, "?%s%d: ATTRIBUTE_ENTRY size incorrect.  "
10889 		    "%d != 260", DRIVER_NAME, ddiinst,
10890 		    (int)sizeof (ATTRIBUTE_ENTRY));
10891 
10892 		errors++;
10893 	}
10894 	size = SLI_SLIM1_SIZE;
10895 	if (sizeof (SLIM1) != size) {
10896 		cmn_err(CE_WARN, "?%s%d: SLIM1 size incorrect.  %d != %d",
10897 		    DRIVER_NAME, ddiinst, (int)sizeof (SLIM1), SLI_SLIM1_SIZE);
10898 
10899 		errors++;
10900 	}
10901 	size = SLI3_IOCB_CMD_SIZE;
10902 	if (sizeof (IOCB) != size) {
10903 		cmn_err(CE_WARN, "?%s%d: IOCB size incorrect.  %d != %d",
10904 		    DRIVER_NAME, ddiinst, (int)sizeof (IOCB),
10905 		    SLI3_IOCB_CMD_SIZE);
10906 
10907 		errors++;
10908 	}
10909 
10910 	size = SLI_SLIM2_SIZE;
10911 	if (sizeof (SLIM2) != size) {
10912 		cmn_err(CE_WARN, "?%s%d: SLIM2 size incorrect.  %d != %d",
10913 		    DRIVER_NAME, ddiinst, (int)sizeof (SLIM2),
10914 		    SLI_SLIM2_SIZE);
10915 
10916 		errors++;
10917 	}
10918 	return (errors);
10919 
10920 } /* emlxs_integrity_check() */
10921 
10922 
10923 #ifdef FMA_SUPPORT
10924 /*
10925  * FMA support
10926  */
10927 
10928 extern void
10929 emlxs_fm_init(emlxs_hba_t *hba)
10930 {
10931 	ddi_iblock_cookie_t iblk;
10932 
10933 	if (hba->fm_caps == DDI_FM_NOT_CAPABLE) {
10934 		return;
10935 	}
10936 
10937 	if (DDI_FM_ACC_ERR_CAP(hba->fm_caps)) {
10938 		emlxs_dev_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
10939 		emlxs_data_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
10940 	} else {
10941 		emlxs_dev_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
10942 		emlxs_data_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
10943 	}
10944 
10945 	if (DDI_FM_DMA_ERR_CAP(hba->fm_caps)) {
10946 		emlxs_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
10947 		emlxs_dma_attr_ro.dma_attr_flags |= DDI_DMA_FLAGERR;
10948 		emlxs_dma_attr_1sg.dma_attr_flags |= DDI_DMA_FLAGERR;
10949 		emlxs_dma_attr_fcip_rsp.dma_attr_flags |= DDI_DMA_FLAGERR;
10950 	} else {
10951 		emlxs_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
10952 		emlxs_dma_attr_ro.dma_attr_flags &= ~DDI_DMA_FLAGERR;
10953 		emlxs_dma_attr_1sg.dma_attr_flags &= ~DDI_DMA_FLAGERR;
10954 		emlxs_dma_attr_fcip_rsp.dma_attr_flags &= ~DDI_DMA_FLAGERR;
10955 	}
10956 
10957 	ddi_fm_init(hba->dip, &hba->fm_caps, &iblk);
10958 
10959 	if (DDI_FM_EREPORT_CAP(hba->fm_caps) ||
10960 	    DDI_FM_ERRCB_CAP(hba->fm_caps)) {
10961 		pci_ereport_setup(hba->dip);
10962 	}
10963 
10964 	if (DDI_FM_ERRCB_CAP(hba->fm_caps)) {
10965 		ddi_fm_handler_register(hba->dip, emlxs_fm_error_cb,
10966 		    (void *)hba);
10967 	}
10968 
10969 } /* emlxs_fm_init() */
10970 
10971 
10972 extern void
10973 emlxs_fm_fini(emlxs_hba_t *hba)
10974 {
10975 	if (hba->fm_caps == DDI_FM_NOT_CAPABLE) {
10976 		return;
10977 	}
10978 
10979 	if (DDI_FM_EREPORT_CAP(hba->fm_caps) ||
10980 	    DDI_FM_ERRCB_CAP(hba->fm_caps)) {
10981 		pci_ereport_teardown(hba->dip);
10982 	}
10983 
10984 	if (DDI_FM_ERRCB_CAP(hba->fm_caps)) {
10985 		ddi_fm_handler_unregister(hba->dip);
10986 	}
10987 
10988 	(void) ddi_fm_fini(hba->dip);
10989 
10990 } /* emlxs_fm_fini() */
10991 
10992 
10993 extern int
10994 emlxs_fm_check_acc_handle(emlxs_hba_t *hba, ddi_acc_handle_t handle)
10995 {
10996 	ddi_fm_error_t err;
10997 
10998 	if (!DDI_FM_ACC_ERR_CAP(hba->fm_caps)) {
10999 		return (DDI_FM_OK);
11000 	}
11001 
11002 	/* Some S10 versions do not define the ahi_err structure */
11003 	if (((ddi_acc_impl_t *)handle)->ahi_err == NULL) {
11004 		return (DDI_FM_OK);
11005 	}
11006 
11007 	err.fme_status = DDI_FM_OK;
11008 	(void) ddi_fm_acc_err_get(handle, &err, DDI_FME_VERSION);
11009 
11010 	/* Some S10 versions do not define the ddi_fm_acc_err_clear function */
11011 	if ((void *)&ddi_fm_acc_err_clear != NULL) {
11012 		(void) ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
11013 	}
11014 
11015 	return (err.fme_status);
11016 
11017 } /* emlxs_fm_check_acc_handle() */
11018 
11019 
11020 extern int
11021 emlxs_fm_check_dma_handle(emlxs_hba_t *hba, ddi_dma_handle_t handle)
11022 {
11023 	ddi_fm_error_t err;
11024 
11025 	if (!DDI_FM_ACC_ERR_CAP(hba->fm_caps)) {
11026 		return (DDI_FM_OK);
11027 	}
11028 
11029 	err.fme_status = DDI_FM_OK;
11030 	(void) ddi_fm_dma_err_get(handle, &err, DDI_FME_VERSION);
11031 
11032 	return (err.fme_status);
11033 
11034 } /* emlxs_fm_check_dma_handle() */
11035 
11036 
11037 extern void
11038 emlxs_fm_ereport(emlxs_hba_t *hba, char *detail)
11039 {
11040 	uint64_t ena;
11041 	char buf[FM_MAX_CLASS];
11042 
11043 	if (!DDI_FM_EREPORT_CAP(hba->fm_caps)) {
11044 		return;
11045 	}
11046 
11047 	if (detail == NULL) {
11048 		return;
11049 	}
11050 
11051 	(void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
11052 	ena = fm_ena_generate(0, FM_ENA_FMT1);
11053 
11054 	ddi_fm_ereport_post(hba->dip, buf, ena, DDI_NOSLEEP,
11055 	    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
11056 
11057 } /* emlxs_fm_ereport() */
11058 
11059 
11060 extern void
11061 emlxs_fm_service_impact(emlxs_hba_t *hba, int impact)
11062 {
11063 	if (!DDI_FM_EREPORT_CAP(hba->fm_caps)) {
11064 		return;
11065 	}
11066 
11067 	if (impact == NULL) {
11068 		return;
11069 	}
11070 
11071 	if ((hba->pm_state & EMLXS_PM_IN_DETACH) &&
11072 	    (impact == DDI_SERVICE_DEGRADED)) {
11073 		impact = DDI_SERVICE_UNAFFECTED;
11074 	}
11075 
11076 	ddi_fm_service_impact(hba->dip, impact);
11077 
11078 } /* emlxs_fm_service_impact() */
11079 
11080 
11081 /*
11082  * The I/O fault service error handling callback function
11083  */
11084 /*ARGSUSED*/
11085 extern int
11086 emlxs_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err,
11087     const void *impl_data)
11088 {
11089 	/*
11090 	 * as the driver can always deal with an error
11091 	 * in any dma or access handle, we can just return
11092 	 * the fme_status value.
11093 	 */
11094 	pci_ereport_post(dip, err, NULL);
11095 	return (err->fme_status);
11096 
11097 } /* emlxs_fm_error_cb() */
11098 #endif	/* FMA_SUPPORT */
11099 
11100 
11101 extern void
11102 emlxs_swap32_buffer(uint8_t *buffer, uint32_t size)
11103 {
11104 	uint32_t word;
11105 	uint32_t *wptr;
11106 	uint32_t i;
11107 
11108 	wptr = (uint32_t *)buffer;
11109 
11110 	size += (size%4)? (4-(size%4)):0;
11111 	for (i = 0; i < size / 4; i++) {
11112 		word = *wptr;
11113 		*wptr++ = SWAP32(word);
11114 	}
11115 
11116 	return;
11117 
11118 }  /* emlxs_swap32_buffer() */
11119 
11120 
11121 extern void
11122 emlxs_swap32_bcopy(uint8_t *src, uint8_t *dst, uint32_t size)
11123 {
11124 	uint32_t word;
11125 	uint32_t *sptr;
11126 	uint32_t *dptr;
11127 	uint32_t i;
11128 
11129 	sptr = (uint32_t *)src;
11130 	dptr = (uint32_t *)dst;
11131 
11132 	size += (size%4)? (4-(size%4)):0;
11133 	for (i = 0; i < size / 4; i++) {
11134 		word = *sptr++;
11135 		*dptr++ = SWAP32(word);
11136 	}
11137 
11138 	return;
11139 
11140 }  /* emlxs_swap32_buffer() */
11141