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