Home | History | Annotate | Download | only in emlxs
      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 2010 Emulex.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 
     28 #define	DEF_ICFG	1
     29 
     30 #include <emlxs.h>
     31 #include <emlxs_version.h>
     32 
     33 
     34 char emlxs_revision[] = EMLXS_REVISION;
     35 char emlxs_version[] = EMLXS_VERSION;
     36 char emlxs_name[] = EMLXS_NAME;
     37 char emlxs_label[] = EMLXS_LABEL;
     38 
     39 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
     40 EMLXS_MSG_DEF(EMLXS_SOLARIS_C);
     41 
     42 #ifdef MENLO_SUPPORT
     43 static int32_t  emlxs_send_menlo(emlxs_port_t *port, emlxs_buf_t *sbp);
     44 #endif /* MENLO_SUPPORT */
     45 
     46 static void	emlxs_fca_attach(emlxs_hba_t *hba);
     47 static void	emlxs_fca_detach(emlxs_hba_t *hba);
     48 static void	emlxs_drv_banner(emlxs_hba_t *hba);
     49 
     50 static int32_t	emlxs_get_props(emlxs_hba_t *hba);
     51 static int32_t	emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp);
     52 static int32_t	emlxs_send_fct_status(emlxs_port_t *port, emlxs_buf_t *sbp);
     53 static int32_t	emlxs_send_fct_abort(emlxs_port_t *port, emlxs_buf_t *sbp);
     54 static int32_t	emlxs_send_ip(emlxs_port_t *port, emlxs_buf_t *sbp);
     55 static int32_t	emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp);
     56 static int32_t	emlxs_send_els_rsp(emlxs_port_t *port, emlxs_buf_t *sbp);
     57 static int32_t	emlxs_send_ct(emlxs_port_t *port, emlxs_buf_t *sbp);
     58 static int32_t	emlxs_send_ct_rsp(emlxs_port_t *port, emlxs_buf_t *sbp);
     59 static uint32_t emlxs_add_instance(int32_t ddiinst);
     60 static void	emlxs_iodone(emlxs_buf_t *sbp);
     61 static int	emlxs_pm_lower_power(dev_info_t *dip);
     62 static int	emlxs_pm_raise_power(dev_info_t *dip);
     63 static void	emlxs_driver_remove(dev_info_t *dip, uint32_t init_flag,
     64 		    uint32_t failed);
     65 static void	emlxs_iodone_server(void *arg1, void *arg2, void *arg3);
     66 static uint32_t	emlxs_integrity_check(emlxs_hba_t *hba);
     67 static uint32_t	emlxs_test(emlxs_hba_t *hba, uint32_t test_code,
     68 		    uint32_t args, uint32_t *arg);
     69 
     70 static void	emlxs_read_vport_prop(emlxs_hba_t *hba);
     71 
     72 
     73 
     74 /*
     75  * Driver Entry Routines.
     76  */
     77 static int32_t	emlxs_detach(dev_info_t *, ddi_detach_cmd_t);
     78 static int32_t	emlxs_attach(dev_info_t *, ddi_attach_cmd_t);
     79 static int32_t	emlxs_open(dev_t *, int32_t, int32_t, cred_t *);
     80 static int32_t	emlxs_close(dev_t, int32_t, int32_t, cred_t *);
     81 static int32_t	emlxs_ioctl(dev_t, int32_t, intptr_t, int32_t,
     82 		    cred_t *, int32_t *);
     83 static int32_t	emlxs_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
     84 
     85 
     86 /*
     87  * FC_AL Transport Functions.
     88  */
     89 static opaque_t	emlxs_bind_port(dev_info_t *, fc_fca_port_info_t *,
     90 		    fc_fca_bind_info_t *);
     91 static void	emlxs_unbind_port(opaque_t);
     92 static void	emlxs_initialize_pkt(emlxs_port_t *, emlxs_buf_t *);
     93 static int32_t	emlxs_get_cap(opaque_t, char *, void *);
     94 static int32_t	emlxs_set_cap(opaque_t, char *, void *);
     95 static int32_t	emlxs_get_map(opaque_t, fc_lilpmap_t *);
     96 static int32_t	emlxs_ub_alloc(opaque_t, uint64_t *, uint32_t,
     97 		    uint32_t *, uint32_t);
     98 static int32_t	emlxs_ub_free(opaque_t, uint32_t, uint64_t *);
     99 
    100 static opaque_t	emlxs_get_device(opaque_t, fc_portid_t);
    101 static int32_t	emlxs_notify(opaque_t, uint32_t);
    102 static void	emlxs_ub_els_reject(emlxs_port_t *, fc_unsol_buf_t *);
    103 
    104 /*
    105  * Driver Internal Functions.
    106  */
    107 
    108 static void	emlxs_poll(emlxs_port_t *, emlxs_buf_t *);
    109 static int32_t	emlxs_power(dev_info_t *, int32_t, int32_t);
    110 #ifdef EMLXS_I386
    111 #ifdef S11
    112 static int32_t	emlxs_quiesce(dev_info_t *);
    113 #endif
    114 #endif
    115 static int32_t	emlxs_hba_resume(dev_info_t *);
    116 static int32_t	emlxs_hba_suspend(dev_info_t *);
    117 static int32_t	emlxs_hba_detach(dev_info_t *);
    118 static int32_t	emlxs_hba_attach(dev_info_t *);
    119 static void	emlxs_lock_destroy(emlxs_hba_t *);
    120 static void	emlxs_lock_init(emlxs_hba_t *);
    121 static ULP_BDE64 *emlxs_pkt_to_bpl(ULP_BDE64 *, fc_packet_t *,
    122 			uint32_t, uint8_t);
    123 
    124 char *emlxs_pm_components[] = {
    125 	"NAME=emlxx000",
    126 	"0=Device D3 State",
    127 	"1=Device D0 State"
    128 };
    129 
    130 
    131 /*
    132  * Default emlx dma limits
    133  */
    134 ddi_dma_lim_t emlxs_dma_lim = {
    135 	(uint32_t)0,				/* dlim_addr_lo */
    136 	(uint32_t)0xffffffff,			/* dlim_addr_hi */
    137 	(uint_t)0x00ffffff,			/* dlim_cntr_max */
    138 	DEFAULT_BURSTSIZE | BURST32 | BURST64,	/* dlim_burstsizes */
    139 	1,					/* dlim_minxfer */
    140 	0x00ffffff				/* dlim_dmaspeed */
    141 };
    142 
    143 /*
    144  * Be careful when using these attributes; the defaults listed below are
    145  * (almost) the most general case, permitting allocation in almost any
    146  * way supported by the LightPulse family.  The sole exception is the
    147  * alignment specified as requiring memory allocation on a 4-byte boundary;
    148  * the Lightpulse can DMA memory on any byte boundary.
    149  *
    150  * The LightPulse family currently is limited to 16M transfers;
    151  * this restriction affects the dma_attr_count_max and dma_attr_maxxfer fields.
    152  */
    153 ddi_dma_attr_t emlxs_dma_attr = {
    154 	DMA_ATTR_V0,				/* dma_attr_version */
    155 	(uint64_t)0,				/* dma_attr_addr_lo */
    156 	(uint64_t)0xffffffffffffffff,		/* dma_attr_addr_hi */
    157 	(uint64_t)0x00ffffff,			/* dma_attr_count_max */
    158 	1,					/* dma_attr_align */
    159 	DEFAULT_BURSTSIZE | BURST32 | BURST64,	/* dma_attr_burstsizes */
    160 	1,					/* dma_attr_minxfer */
    161 	(uint64_t)0x00ffffff,			/* dma_attr_maxxfer */
    162 	(uint64_t)0xffffffff,			/* dma_attr_seg */
    163 	EMLXS_SGLLEN,				/* dma_attr_sgllen */
    164 	1,					/* dma_attr_granular */
    165 	0					/* dma_attr_flags */
    166 };
    167 
    168 ddi_dma_attr_t emlxs_dma_attr_ro = {
    169 	DMA_ATTR_V0,				/* dma_attr_version */
    170 	(uint64_t)0,				/* dma_attr_addr_lo */
    171 	(uint64_t)0xffffffffffffffff,		/* dma_attr_addr_hi */
    172 	(uint64_t)0x00ffffff,			/* dma_attr_count_max */
    173 	1,					/* dma_attr_align */
    174 	DEFAULT_BURSTSIZE | BURST32 | BURST64,	/* dma_attr_burstsizes */
    175 	1,					/* dma_attr_minxfer */
    176 	(uint64_t)0x00ffffff,			/* dma_attr_maxxfer */
    177 	(uint64_t)0xffffffff,			/* dma_attr_seg */
    178 	EMLXS_SGLLEN,				/* dma_attr_sgllen */
    179 	1,					/* dma_attr_granular */
    180 	DDI_DMA_RELAXED_ORDERING		/* dma_attr_flags */
    181 };
    182 
    183 ddi_dma_attr_t emlxs_dma_attr_1sg = {
    184 	DMA_ATTR_V0,				/* dma_attr_version */
    185 	(uint64_t)0,				/* dma_attr_addr_lo */
    186 	(uint64_t)0xffffffffffffffff,		/* dma_attr_addr_hi */
    187 	(uint64_t)0x00ffffff,			/* dma_attr_count_max */
    188 	1,					/* dma_attr_align */
    189 	DEFAULT_BURSTSIZE | BURST32 | BURST64,	/* dma_attr_burstsizes */
    190 	1,					/* dma_attr_minxfer */
    191 	(uint64_t)0x00ffffff,			/* dma_attr_maxxfer */
    192 	(uint64_t)0xffffffff,			/* dma_attr_seg */
    193 	1,					/* dma_attr_sgllen */
    194 	1,					/* dma_attr_granular */
    195 	0					/* dma_attr_flags */
    196 };
    197 
    198 #if (EMLXS_MODREV >= EMLXS_MODREV3)
    199 ddi_dma_attr_t emlxs_dma_attr_fcip_rsp = {
    200 	DMA_ATTR_V0,				/* dma_attr_version */
    201 	(uint64_t)0,				/* dma_attr_addr_lo */
    202 	(uint64_t)0xffffffffffffffff,		/* dma_attr_addr_hi */
    203 	(uint64_t)0x00ffffff,			/* dma_attr_count_max */
    204 	1,					/* dma_attr_align */
    205 	DEFAULT_BURSTSIZE | BURST32 | BURST64,	/* dma_attr_burstsizes */
    206 	1,					/* dma_attr_minxfer */
    207 	(uint64_t)0x00ffffff,			/* dma_attr_maxxfer */
    208 	(uint64_t)0xffffffff,			/* dma_attr_seg */
    209 	EMLXS_SGLLEN,				/* dma_attr_sgllen */
    210 	1,					/* dma_attr_granular */
    211 	0					/* dma_attr_flags */
    212 };
    213 #endif	/* >= EMLXS_MODREV3 */
    214 
    215 /*
    216  * DDI access attributes for device
    217  */
    218 ddi_device_acc_attr_t emlxs_dev_acc_attr = {
    219 	DDI_DEVICE_ATTR_V1,	/* devacc_attr_version		*/
    220 	DDI_STRUCTURE_LE_ACC,	/* PCI is Little Endian		*/
    221 	DDI_STRICTORDER_ACC,	/* devacc_attr_dataorder	*/
    222 	DDI_DEFAULT_ACC		/* devacc_attr_access		*/
    223 };
    224 
    225 /*
    226  * DDI access attributes for data
    227  */
    228 ddi_device_acc_attr_t emlxs_data_acc_attr = {
    229 	DDI_DEVICE_ATTR_V1,	/* devacc_attr_version		*/
    230 	DDI_NEVERSWAP_ACC,	/* don't swap for Data		*/
    231 	DDI_STRICTORDER_ACC,	/* devacc_attr_dataorder	*/
    232 	DDI_DEFAULT_ACC		/* devacc_attr_access		*/
    233 };
    234 
    235 /*
    236  * Fill in the FC Transport structure,
    237  * as defined in the Fibre Channel Transport Programmming Guide.
    238  */
    239 #if (EMLXS_MODREV == EMLXS_MODREV5)
    240 	static fc_fca_tran_t emlxs_fca_tran = {
    241 	FCTL_FCA_MODREV_5, 		/* fca_version, with SUN NPIV support */
    242 	MAX_VPORTS,			/* fca numerb of ports */
    243 	sizeof (emlxs_buf_t),		/* fca pkt size */
    244 	2048,				/* fca cmd max */
    245 	&emlxs_dma_lim,			/* fca dma limits */
    246 	0,				/* fca iblock, to be filled in later */
    247 	&emlxs_dma_attr,		/* fca dma attributes */
    248 	&emlxs_dma_attr_1sg,		/* fca dma fcp cmd attributes */
    249 	&emlxs_dma_attr_1sg,		/* fca dma fcp rsp attributes */
    250 	&emlxs_dma_attr_ro,		/* fca dma fcp data attributes */
    251 	&emlxs_dma_attr_1sg,		/* fca dma fcip cmd attributes */
    252 	&emlxs_dma_attr_fcip_rsp,	/* fca dma fcip rsp attributes */
    253 	&emlxs_dma_attr_1sg,		/* fca dma fcsm cmd attributes */
    254 	&emlxs_dma_attr,		/* fca dma fcsm rsp attributes */
    255 	&emlxs_data_acc_attr,   	/* fca access atributes */
    256 	0,				/* fca_num_npivports */
    257 	{0, 0, 0, 0, 0, 0, 0, 0},	/* Physical port WWPN */
    258 	emlxs_bind_port,
    259 	emlxs_unbind_port,
    260 	emlxs_pkt_init,
    261 	emlxs_pkt_uninit,
    262 	emlxs_transport,
    263 	emlxs_get_cap,
    264 	emlxs_set_cap,
    265 	emlxs_get_map,
    266 	emlxs_transport,
    267 	emlxs_ub_alloc,
    268 	emlxs_ub_free,
    269 	emlxs_ub_release,
    270 	emlxs_pkt_abort,
    271 	emlxs_reset,
    272 	emlxs_port_manage,
    273 	emlxs_get_device,
    274 	emlxs_notify
    275 };
    276 #endif	/* EMLXS_MODREV5 */
    277 
    278 
    279 #if (EMLXS_MODREV == EMLXS_MODREV4)
    280 static fc_fca_tran_t emlxs_fca_tran = {
    281 	FCTL_FCA_MODREV_4,		/* fca_version */
    282 	MAX_VPORTS,			/* fca numerb of ports */
    283 	sizeof (emlxs_buf_t),		/* fca pkt size */
    284 	2048,				/* fca cmd max */
    285 	&emlxs_dma_lim,			/* fca dma limits */
    286 	0,				/* fca iblock, to be filled in later */
    287 	&emlxs_dma_attr,		/* fca dma attributes */
    288 	&emlxs_dma_attr_1sg,		/* fca dma fcp cmd attributes */
    289 	&emlxs_dma_attr_1sg,		/* fca dma fcp rsp attributes */
    290 	&emlxs_dma_attr_ro,		/* fca dma fcp data attributes */
    291 	&emlxs_dma_attr_1sg,		/* fca dma fcip cmd attributes */
    292 	&emlxs_dma_attr_fcip_rsp,	/* fca dma fcip rsp attributes */
    293 	&emlxs_dma_attr_1sg,		/* fca dma fcsm cmd attributes */
    294 	&emlxs_dma_attr,		/* fca dma fcsm rsp attributes */
    295 	&emlxs_data_acc_attr,		/* fca access atributes */
    296 	emlxs_bind_port,
    297 	emlxs_unbind_port,
    298 	emlxs_pkt_init,
    299 	emlxs_pkt_uninit,
    300 	emlxs_transport,
    301 	emlxs_get_cap,
    302 	emlxs_set_cap,
    303 	emlxs_get_map,
    304 	emlxs_transport,
    305 	emlxs_ub_alloc,
    306 	emlxs_ub_free,
    307 	emlxs_ub_release,
    308 	emlxs_pkt_abort,
    309 	emlxs_reset,
    310 	emlxs_port_manage,
    311 	emlxs_get_device,
    312 	emlxs_notify
    313 };
    314 #endif	/* EMLXS_MODEREV4 */
    315 
    316 
    317 #if (EMLXS_MODREV == EMLXS_MODREV3)
    318 static fc_fca_tran_t emlxs_fca_tran = {
    319 	FCTL_FCA_MODREV_3,		/* fca_version */
    320 	MAX_VPORTS,			/* fca numerb of ports */
    321 	sizeof (emlxs_buf_t),		/* fca pkt size */
    322 	2048,				/* fca cmd max */
    323 	&emlxs_dma_lim,			/* fca dma limits */
    324 	0,				/* fca iblock, to be filled in later */
    325 	&emlxs_dma_attr,		/* fca dma attributes */
    326 	&emlxs_dma_attr_1sg,		/* fca dma fcp cmd attributes */
    327 	&emlxs_dma_attr_1sg,		/* fca dma fcp rsp attributes */
    328 	&emlxs_dma_attr_ro,		/* fca dma fcp data attributes */
    329 	&emlxs_dma_attr_1sg,		/* fca dma fcip cmd attributes */
    330 	&emlxs_dma_attr_fcip_rsp,	/* fca dma fcip rsp attributes */
    331 	&emlxs_dma_attr_1sg,		/* fca dma fcsm cmd attributes */
    332 	&emlxs_dma_attr,		/* fca dma fcsm rsp attributes */
    333 	&emlxs_data_acc_attr,		/* fca access atributes */
    334 	emlxs_bind_port,
    335 	emlxs_unbind_port,
    336 	emlxs_pkt_init,
    337 	emlxs_pkt_uninit,
    338 	emlxs_transport,
    339 	emlxs_get_cap,
    340 	emlxs_set_cap,
    341 	emlxs_get_map,
    342 	emlxs_transport,
    343 	emlxs_ub_alloc,
    344 	emlxs_ub_free,
    345 	emlxs_ub_release,
    346 	emlxs_pkt_abort,
    347 	emlxs_reset,
    348 	emlxs_port_manage,
    349 	emlxs_get_device,
    350 	emlxs_notify
    351 };
    352 #endif	/* EMLXS_MODREV3 */
    353 
    354 
    355 #if (EMLXS_MODREV == EMLXS_MODREV2)
    356 static fc_fca_tran_t emlxs_fca_tran = {
    357 	FCTL_FCA_MODREV_2,		/* fca_version */
    358 	MAX_VPORTS,			/* number of ports */
    359 	sizeof (emlxs_buf_t),		/* pkt size */
    360 	2048,				/* max cmds */
    361 	&emlxs_dma_lim,			/* DMA limits */
    362 	0,				/* iblock, to be filled in later */
    363 	&emlxs_dma_attr,		/* dma attributes */
    364 	&emlxs_data_acc_attr,		/* access atributes */
    365 	emlxs_bind_port,
    366 	emlxs_unbind_port,
    367 	emlxs_pkt_init,
    368 	emlxs_pkt_uninit,
    369 	emlxs_transport,
    370 	emlxs_get_cap,
    371 	emlxs_set_cap,
    372 	emlxs_get_map,
    373 	emlxs_transport,
    374 	emlxs_ub_alloc,
    375 	emlxs_ub_free,
    376 	emlxs_ub_release,
    377 	emlxs_pkt_abort,
    378 	emlxs_reset,
    379 	emlxs_port_manage,
    380 	emlxs_get_device,
    381 	emlxs_notify
    382 };
    383 #endif	/* EMLXS_MODREV2 */
    384 
    385 /*
    386  * This is needed when the module gets loaded by the kernel
    387  * so ddi library calls get resolved.
    388  */
    389 #ifndef MODSYM_SUPPORT
    390 char   _depends_on[] = "misc/fctl";
    391 #endif /* MODSYM_SUPPORT */
    392 
    393 /*
    394  * state pointer which the implementation uses as a place to
    395  * hang a set of per-driver structures;
    396  *
    397  */
    398 void		*emlxs_soft_state = NULL;
    399 
    400 /*
    401  * Driver Global variables.
    402  */
    403 int32_t		emlxs_scsi_reset_delay = 3000;	/* milliseconds */
    404 
    405 emlxs_device_t  emlxs_device;
    406 
    407 uint32_t	emlxs_instance[MAX_FC_BRDS];	/* uses emlxs_device.lock */
    408 uint32_t	emlxs_instance_count = 0;	/* uses emlxs_device.lock */
    409 
    410 
    411 /*
    412  * Single private "global" lock used to gain access to
    413  * the hba_list and/or any other case where we want need to be
    414  * single-threaded.
    415  */
    416 uint32_t	emlxs_diag_state;
    417 
    418 /*
    419  * CB ops vector.  Used for administration only.
    420  */
    421 static struct cb_ops emlxs_cb_ops = {
    422 	emlxs_open,	/* cb_open	*/
    423 	emlxs_close,	/* cb_close	*/
    424 	nodev,		/* cb_strategy	*/
    425 	nodev,		/* cb_print	*/
    426 	nodev,		/* cb_dump	*/
    427 	nodev,		/* cb_read	*/
    428 	nodev,		/* cb_write	*/
    429 	emlxs_ioctl,	/* cb_ioctl	*/
    430 	nodev,		/* cb_devmap	*/
    431 	nodev,		/* cb_mmap	*/
    432 	nodev,		/* cb_segmap	*/
    433 	nochpoll,	/* cb_chpoll	*/
    434 	ddi_prop_op,	/* cb_prop_op	*/
    435 	0,		/* cb_stream	*/
    436 #ifdef _LP64
    437 	D_64BIT | D_HOTPLUG | D_MP | D_NEW,	/* cb_flag */
    438 #else
    439 	D_HOTPLUG | D_MP | D_NEW,		/* cb_flag */
    440 #endif
    441 	CB_REV,		/* rev		*/
    442 	nodev,		/* cb_aread	*/
    443 	nodev		/* cb_awrite	*/
    444 };
    445 
    446 static struct dev_ops emlxs_ops = {
    447 	DEVO_REV,	/* rev */
    448 	0,	/* refcnt */
    449 	emlxs_info,	/* getinfo	*/
    450 	nulldev,	/* identify	*/
    451 	nulldev,	/* probe	*/
    452 	emlxs_attach,	/* attach	*/
    453 	emlxs_detach,	/* detach	*/
    454 	nodev,		/* reset	*/
    455 	&emlxs_cb_ops,	/* devo_cb_ops	*/
    456 	NULL,		/* devo_bus_ops */
    457 	emlxs_power,	/* power ops	*/
    458 #ifdef EMLXS_I386
    459 #ifdef S11
    460 	emlxs_quiesce,	/* quiesce	*/
    461 #endif
    462 #endif
    463 };
    464 
    465 #include <sys/modctl.h>
    466 extern struct mod_ops mod_driverops;
    467 
    468 #ifdef SAN_DIAG_SUPPORT
    469 extern kmutex_t		sd_bucket_mutex;
    470 extern sd_bucket_info_t	sd_bucket;
    471 #endif /* SAN_DIAG_SUPPORT */
    472 
    473 /*
    474  * Module linkage information for the kernel.
    475  */
    476 static struct modldrv emlxs_modldrv = {
    477 	&mod_driverops,	/* module type - driver */
    478 	emlxs_name,	/* module name */
    479 	&emlxs_ops,	/* driver ops */
    480 };
    481 
    482 
    483 /*
    484  * Driver module linkage structure
    485  */
    486 static struct modlinkage emlxs_modlinkage = {
    487 	MODREV_1,	/* ml_rev - must be MODREV_1 */
    488 	&emlxs_modldrv,	/* ml_linkage */
    489 	NULL	/* end of driver linkage */
    490 };
    491 
    492 
    493 /* We only need to add entries for non-default return codes. */
    494 /* Entries do not need to be in order. */
    495 /* Default:	FC_PKT_TRAN_ERROR,	FC_REASON_ABORTED, */
    496 /*		FC_EXPLN_NONE,		FC_ACTION_RETRYABLE */
    497 
    498 emlxs_xlat_err_t emlxs_iostat_tbl[] = {
    499 /* 	{f/w code, pkt_state, pkt_reason, 	*/
    500 /* 		pkt_expln, pkt_action}		*/
    501 
    502 	/* 0x00 - Do not remove */
    503 	{IOSTAT_SUCCESS, FC_PKT_SUCCESS, FC_REASON_NONE,
    504 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    505 
    506 	/* 0x01 - Do not remove */
    507 	{IOSTAT_FCP_RSP_ERROR, FC_PKT_SUCCESS, FC_REASON_NONE,
    508 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    509 
    510 	/* 0x02 */
    511 	{IOSTAT_REMOTE_STOP, FC_PKT_REMOTE_STOP, FC_REASON_ABTS,
    512 		FC_EXPLN_NONE, FC_ACTION_NON_RETRYABLE},
    513 
    514 	/*
    515 	 * This is a default entry.
    516 	 * The real codes are written dynamically in emlxs_els.c
    517 	 */
    518 	/* 0x09 */
    519 	{IOSTAT_LS_RJT, FC_PKT_LS_RJT, FC_REASON_CMD_UNABLE,
    520 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    521 
    522 	/* Special error code */
    523 	/* 0x10 */
    524 	{IOSTAT_DATA_OVERRUN, FC_PKT_TRAN_ERROR, FC_REASON_OVERRUN,
    525 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    526 
    527 	/* Special error code */
    528 	/* 0x11 */
    529 	{IOSTAT_DATA_UNDERRUN, FC_PKT_TRAN_ERROR, FC_REASON_ABORTED,
    530 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    531 
    532 	/* CLASS 2 only */
    533 	/* 0x04 */
    534 	{IOSTAT_NPORT_RJT, FC_PKT_NPORT_RJT, FC_REASON_PROTOCOL_ERROR,
    535 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    536 
    537 	/* CLASS 2 only */
    538 	/* 0x05 */
    539 	{IOSTAT_FABRIC_RJT, FC_PKT_FABRIC_RJT, FC_REASON_PROTOCOL_ERROR,
    540 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    541 
    542 	/* CLASS 2 only */
    543 	/* 0x06 */
    544 	{IOSTAT_NPORT_BSY, FC_PKT_NPORT_BSY, FC_REASON_PHYSICAL_BUSY,
    545 		FC_EXPLN_NONE, FC_ACTION_SEQ_TERM_RETRY},
    546 
    547 	/* CLASS 2 only */
    548 	/* 0x07 */
    549 	{IOSTAT_FABRIC_BSY, FC_PKT_FABRIC_BSY, FC_REASON_FABRIC_BSY,
    550 		FC_EXPLN_NONE, FC_ACTION_SEQ_TERM_RETRY},
    551 };
    552 
    553 #define	IOSTAT_MAX (sizeof (emlxs_iostat_tbl)/sizeof (emlxs_xlat_err_t))
    554 
    555 
    556 /* We only need to add entries for non-default return codes. */
    557 /* Entries do not need to be in order. */
    558 /* Default:	FC_PKT_TRAN_ERROR,	FC_REASON_ABORTED, */
    559 /*		FC_EXPLN_NONE,		FC_ACTION_RETRYABLE} */
    560 
    561 emlxs_xlat_err_t emlxs_ioerr_tbl[] = {
    562 /*	{f/w code, pkt_state, pkt_reason,	*/
    563 /*		pkt_expln, pkt_action}		*/
    564 
    565 	/* 0x01 */
    566 	{IOERR_MISSING_CONTINUE, FC_PKT_TRAN_ERROR, FC_REASON_OVERRUN,
    567 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    568 
    569 	/* 0x02 */
    570 	{IOERR_SEQUENCE_TIMEOUT, FC_PKT_TIMEOUT, FC_REASON_SEQ_TIMEOUT,
    571 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    572 
    573 	/* 0x04 */
    574 	{IOERR_INVALID_RPI, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE,
    575 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    576 
    577 	/* 0x05 */
    578 	{IOERR_NO_XRI, FC_PKT_LOCAL_RJT, FC_REASON_XCHG_DROPPED,
    579 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    580 
    581 	/* 0x06 */
    582 	{IOERR_ILLEGAL_COMMAND,	FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_REQ,
    583 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    584 
    585 	/* 0x07 */
    586 	{IOERR_XCHG_DROPPED, FC_PKT_LOCAL_RJT,	FC_REASON_XCHG_DROPPED,
    587 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    588 
    589 	/* 0x08 */
    590 	{IOERR_ILLEGAL_FIELD, FC_PKT_LOCAL_RJT,	FC_REASON_ILLEGAL_REQ,
    591 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    592 
    593 	/* 0x0B */
    594 	{IOERR_RCV_BUFFER_WAITING, FC_PKT_LOCAL_RJT, FC_REASON_NOMEM,
    595 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    596 
    597 	/* 0x0D */
    598 	{IOERR_TX_DMA_FAILED, FC_PKT_LOCAL_RJT,	FC_REASON_DMA_ERROR,
    599 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    600 
    601 	/* 0x0E */
    602 	{IOERR_RX_DMA_FAILED, FC_PKT_LOCAL_RJT,	FC_REASON_DMA_ERROR,
    603 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    604 
    605 	/* 0x0F */
    606 	{IOERR_ILLEGAL_FRAME, FC_PKT_LOCAL_RJT,	FC_REASON_ILLEGAL_FRAME,
    607 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    608 
    609 	/* 0x11 */
    610 	{IOERR_NO_RESOURCES, FC_PKT_LOCAL_RJT,	FC_REASON_NOMEM,
    611 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    612 
    613 	/* 0x13 */
    614 	{IOERR_ILLEGAL_LENGTH, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_LENGTH,
    615 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    616 
    617 	/* 0x14 */
    618 	{IOERR_UNSUPPORTED_FEATURE, FC_PKT_LOCAL_RJT, FC_REASON_UNSUPPORTED,
    619 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    620 
    621 	/* 0x15 */
    622 	{IOERR_ABORT_IN_PROGRESS, FC_PKT_LOCAL_RJT, FC_REASON_ABORTED,
    623 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    624 
    625 	/* 0x16 */
    626 	{IOERR_ABORT_REQUESTED, FC_PKT_LOCAL_RJT, FC_REASON_ABORTED,
    627 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    628 
    629 	/* 0x17 */
    630 	{IOERR_RCV_BUFFER_TIMEOUT, FC_PKT_LOCAL_RJT, FC_REASON_RX_BUF_TIMEOUT,
    631 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    632 
    633 	/* 0x18 */
    634 	{IOERR_LOOP_OPEN_FAILURE, FC_PKT_LOCAL_RJT, FC_REASON_FCAL_OPN_FAIL,
    635 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    636 
    637 	/* 0x1A */
    638 	{IOERR_LINK_DOWN, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE,
    639 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    640 
    641 	/* 0x21 */
    642 	{IOERR_BAD_HOST_ADDRESS, FC_PKT_LOCAL_RJT, FC_REASON_BAD_SID,
    643 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    644 
    645 	/* Occurs at link down */
    646 	/* 0x28 */
    647 	{IOERR_BUFFER_SHORTAGE, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE,
    648 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    649 
    650 	/* 0xF0 */
    651 	{IOERR_ABORT_TIMEOUT, FC_PKT_TIMEOUT, FC_REASON_SEQ_TIMEOUT,
    652 		FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
    653 };
    654 
    655 #define	IOERR_MAX    (sizeof (emlxs_ioerr_tbl)/sizeof (emlxs_xlat_err_t))
    656 
    657 
    658 
    659 emlxs_table_t emlxs_error_table[] = {
    660 	{IOERR_SUCCESS, "No error."},
    661 	{IOERR_MISSING_CONTINUE, "Missing continue."},
    662 	{IOERR_SEQUENCE_TIMEOUT, "Sequence timeout."},
    663 	{IOERR_INTERNAL_ERROR, "Internal error."},
    664 	{IOERR_INVALID_RPI, "Invalid RPI."},
    665 	{IOERR_NO_XRI, "No XRI."},
    666 	{IOERR_ILLEGAL_COMMAND, "Illegal command."},
    667 	{IOERR_XCHG_DROPPED, "Exchange dropped."},
    668 	{IOERR_ILLEGAL_FIELD, "Illegal field."},
    669 	{IOERR_RCV_BUFFER_WAITING, "RX buffer waiting."},
    670 	{IOERR_TX_DMA_FAILED, "TX DMA failed."},
    671 	{IOERR_RX_DMA_FAILED, "RX DMA failed."},
    672 	{IOERR_ILLEGAL_FRAME, "Illegal frame."},
    673 	{IOERR_NO_RESOURCES, "No resources."},
    674 	{IOERR_ILLEGAL_LENGTH, "Illegal length."},
    675 	{IOERR_UNSUPPORTED_FEATURE, "Unsupported feature."},
    676 	{IOERR_ABORT_IN_PROGRESS, "Abort in progess."},
    677 	{IOERR_ABORT_REQUESTED, "Abort requested."},
    678 	{IOERR_RCV_BUFFER_TIMEOUT, "RX buffer timeout."},
    679 	{IOERR_LOOP_OPEN_FAILURE, "Loop open failed."},
    680 	{IOERR_RING_RESET, "Ring reset."},
    681 	{IOERR_LINK_DOWN, "Link down."},
    682 	{IOERR_CORRUPTED_DATA, "Corrupted data."},
    683 	{IOERR_CORRUPTED_RPI, "Corrupted RPI."},
    684 	{IOERR_OUT_OF_ORDER_DATA, "Out-of-order data."},
    685 	{IOERR_OUT_OF_ORDER_ACK, "Out-of-order ack."},
    686 	{IOERR_DUP_FRAME, "Duplicate frame."},
    687 	{IOERR_LINK_CONTROL_FRAME, "Link control frame."},
    688 	{IOERR_BAD_HOST_ADDRESS, "Bad host address."},
    689 	{IOERR_RCV_HDRBUF_WAITING, "RX header buffer waiting."},
    690 	{IOERR_MISSING_HDR_BUFFER, "Missing header buffer."},
    691 	{IOERR_MSEQ_CHAIN_CORRUPTED, "MSEQ chain corrupted."},
    692 	{IOERR_ABORTMULT_REQUESTED, "Abort multiple requested."},
    693 	{IOERR_BUFFER_SHORTAGE, "Buffer shortage."},
    694 	{IOERR_XRIBUF_WAITING, "XRI buffer shortage"},
    695 	{IOERR_XRIBUF_MISSING, "XRI buffer missing"},
    696 	{IOERR_ROFFSET_INVAL, "Relative offset invalid."},
    697 	{IOERR_ROFFSET_MISSING, "Relative offset missing."},
    698 	{IOERR_INSUF_BUFFER, "Buffer too small."},
    699 	{IOERR_MISSING_SI, "ELS frame missing SI"},
    700 	{IOERR_MISSING_ES, "Exhausted burst without ES"},
    701 	{IOERR_INCOMP_XFER, "Transfer incomplete."},
    702 	{IOERR_ABORT_TIMEOUT, "Abort timeout."}
    703 
    704 };	/* emlxs_error_table */
    705 
    706 
    707 emlxs_table_t emlxs_state_table[] = {
    708 	{IOSTAT_SUCCESS, "Success."},
    709 	{IOSTAT_FCP_RSP_ERROR, "FCP response error."},
    710 	{IOSTAT_REMOTE_STOP, "Remote stop."},
    711 	{IOSTAT_LOCAL_REJECT, "Local reject."},
    712 	{IOSTAT_NPORT_RJT, "NPort reject."},
    713 	{IOSTAT_FABRIC_RJT, "Fabric reject."},
    714 	{IOSTAT_NPORT_BSY, "Nport busy."},
    715 	{IOSTAT_FABRIC_BSY, "Fabric busy."},
    716 	{IOSTAT_INTERMED_RSP, "Intermediate response."},
    717 	{IOSTAT_LS_RJT, "LS reject."},
    718 	{IOSTAT_CMD_REJECT,		"Cmd reject."},
    719 	{IOSTAT_FCP_TGT_LENCHK, "TGT length check."},
    720 	{IOSTAT_NEED_BUFF_ENTRY, "Need buffer entry."},
    721 	{IOSTAT_DATA_UNDERRUN, "Data underrun."},
    722 	{IOSTAT_DATA_OVERRUN,  "Data overrun."},
    723 
    724 };	/* emlxs_state_table */
    725 
    726 
    727 #ifdef MENLO_SUPPORT
    728 emlxs_table_t emlxs_menlo_cmd_table[] = {
    729 	{MENLO_CMD_INITIALIZE,		"MENLO_INIT"},
    730 	{MENLO_CMD_FW_DOWNLOAD,		"MENLO_FW_DOWNLOAD"},
    731 	{MENLO_CMD_READ_MEMORY,		"MENLO_READ_MEM"},
    732 	{MENLO_CMD_WRITE_MEMORY,	"MENLO_WRITE_MEM"},
    733 	{MENLO_CMD_FTE_INSERT,		"MENLO_FTE_INSERT"},
    734 	{MENLO_CMD_FTE_DELETE,		"MENLO_FTE_DELETE"},
    735 
    736 	{MENLO_CMD_GET_INIT,		"MENLO_GET_INIT"},
    737 	{MENLO_CMD_GET_CONFIG,		"MENLO_GET_CONFIG"},
    738 	{MENLO_CMD_GET_PORT_STATS,	"MENLO_GET_PORT_STATS"},
    739 	{MENLO_CMD_GET_LIF_STATS,	"MENLO_GET_LIF_STATS"},
    740 	{MENLO_CMD_GET_ASIC_STATS,	"MENLO_GET_ASIC_STATS"},
    741 	{MENLO_CMD_GET_LOG_CONFIG,	"MENLO_GET_LOG_CFG"},
    742 	{MENLO_CMD_GET_LOG_DATA,	"MENLO_GET_LOG_DATA"},
    743 	{MENLO_CMD_GET_PANIC_LOG,	"MENLO_GET_PANIC_LOG"},
    744 	{MENLO_CMD_GET_LB_MODE,		"MENLO_GET_LB_MODE"},
    745 
    746 	{MENLO_CMD_SET_PAUSE,		"MENLO_SET_PAUSE"},
    747 	{MENLO_CMD_SET_FCOE_COS,	"MENLO_SET_FCOE_COS"},
    748 	{MENLO_CMD_SET_UIF_PORT_TYPE,	"MENLO_SET_UIF_TYPE"},
    749 
    750 	{MENLO_CMD_DIAGNOSTICS,		"MENLO_DIAGNOSTICS"},
    751 	{MENLO_CMD_LOOPBACK,		"MENLO_LOOPBACK"},
    752 
    753 	{MENLO_CMD_RESET,		"MENLO_RESET"},
    754 	{MENLO_CMD_SET_MODE,		"MENLO_SET_MODE"}
    755 
    756 };	/* emlxs_menlo_cmd_table */
    757 
    758 emlxs_table_t emlxs_menlo_rsp_table[] = {
    759 	{MENLO_RSP_SUCCESS,		"SUCCESS"},
    760 	{MENLO_ERR_FAILED,		"FAILED"},
    761 	{MENLO_ERR_INVALID_CMD,		"INVALID_CMD"},
    762 	{MENLO_ERR_INVALID_CREDIT,	"INVALID_CREDIT"},
    763 	{MENLO_ERR_INVALID_SIZE,	"INVALID_SIZE"},
    764 	{MENLO_ERR_INVALID_ADDRESS,	"INVALID_ADDRESS"},
    765 	{MENLO_ERR_INVALID_CONTEXT,	"INVALID_CONTEXT"},
    766 	{MENLO_ERR_INVALID_LENGTH,	"INVALID_LENGTH"},
    767 	{MENLO_ERR_INVALID_TYPE,	"INVALID_TYPE"},
    768 	{MENLO_ERR_INVALID_DATA,	"INVALID_DATA"},
    769 	{MENLO_ERR_INVALID_VALUE1,	"INVALID_VALUE1"},
    770 	{MENLO_ERR_INVALID_VALUE2,	"INVALID_VALUE2"},
    771 	{MENLO_ERR_INVALID_MASK,	"INVALID_MASK"},
    772 	{MENLO_ERR_CHECKSUM,		"CHECKSUM_ERROR"},
    773 	{MENLO_ERR_UNKNOWN_FCID,	"UNKNOWN_FCID"},
    774 	{MENLO_ERR_UNKNOWN_WWN,		"UNKNOWN_WWN"},
    775 	{MENLO_ERR_BUSY,		"BUSY"},
    776 
    777 };	/* emlxs_menlo_rsp_table */
    778 
    779 #endif /* MENLO_SUPPORT */
    780 
    781 
    782 emlxs_table_t emlxs_mscmd_table[] = {
    783 	{SLI_CT_RESPONSE_FS_ACC, "CT_ACC"},
    784 	{SLI_CT_RESPONSE_FS_RJT, "CT_RJT"},
    785 	{MS_GTIN, "MS_GTIN"},
    786 	{MS_GIEL, "MS_GIEL"},
    787 	{MS_GIET, "MS_GIET"},
    788 	{MS_GDID, "MS_GDID"},
    789 	{MS_GMID, "MS_GMID"},
    790 	{MS_GFN, "MS_GFN"},
    791 	{MS_GIELN, "MS_GIELN"},
    792 	{MS_GMAL, "MS_GMAL"},
    793 	{MS_GIEIL, "MS_GIEIL"},
    794 	{MS_GPL, "MS_GPL"},
    795 	{MS_GPT, "MS_GPT"},
    796 	{MS_GPPN, "MS_GPPN"},
    797 	{MS_GAPNL, "MS_GAPNL"},
    798 	{MS_GPS, "MS_GPS"},
    799 	{MS_GPSC, "MS_GPSC"},
    800 	{MS_GATIN, "MS_GATIN"},
    801 	{MS_GSES, "MS_GSES"},
    802 	{MS_GPLNL, "MS_GPLNL"},
    803 	{MS_GPLT, "MS_GPLT"},
    804 	{MS_GPLML, "MS_GPLML"},
    805 	{MS_GPAB, "MS_GPAB"},
    806 	{MS_GNPL, "MS_GNPL"},
    807 	{MS_GPNL, "MS_GPNL"},
    808 	{MS_GPFCP, "MS_GPFCP"},
    809 	{MS_GPLI, "MS_GPLI"},
    810 	{MS_GNID, "MS_GNID"},
    811 	{MS_RIELN, "MS_RIELN"},
    812 	{MS_RPL, "MS_RPL"},
    813 	{MS_RPLN, "MS_RPLN"},
    814 	{MS_RPLT, "MS_RPLT"},
    815 	{MS_RPLM, "MS_RPLM"},
    816 	{MS_RPAB, "MS_RPAB"},
    817 	{MS_RPFCP, "MS_RPFCP"},
    818 	{MS_RPLI, "MS_RPLI"},
    819 	{MS_DPL, "MS_DPL"},
    820 	{MS_DPLN, "MS_DPLN"},
    821 	{MS_DPLM, "MS_DPLM"},
    822 	{MS_DPLML, "MS_DPLML"},
    823 	{MS_DPLI, "MS_DPLI"},
    824 	{MS_DPAB, "MS_DPAB"},
    825 	{MS_DPALL, "MS_DPALL"}
    826 
    827 };	/* emlxs_mscmd_table */
    828 
    829 
    830 emlxs_table_t emlxs_ctcmd_table[] = {
    831 	{SLI_CT_RESPONSE_FS_ACC, "CT_ACC"},
    832 	{SLI_CT_RESPONSE_FS_RJT, "CT_RJT"},
    833 	{SLI_CTNS_GA_NXT, "GA_NXT"},
    834 	{SLI_CTNS_GPN_ID, "GPN_ID"},
    835 	{SLI_CTNS_GNN_ID, "GNN_ID"},
    836 	{SLI_CTNS_GCS_ID, "GCS_ID"},
    837 	{SLI_CTNS_GFT_ID, "GFT_ID"},
    838 	{SLI_CTNS_GSPN_ID, "GSPN_ID"},
    839 	{SLI_CTNS_GPT_ID, "GPT_ID"},
    840 	{SLI_CTNS_GID_PN, "GID_PN"},
    841 	{SLI_CTNS_GID_NN, "GID_NN"},
    842 	{SLI_CTNS_GIP_NN, "GIP_NN"},
    843 	{SLI_CTNS_GIPA_NN, "GIPA_NN"},
    844 	{SLI_CTNS_GSNN_NN, "GSNN_NN"},
    845 	{SLI_CTNS_GNN_IP, "GNN_IP"},
    846 	{SLI_CTNS_GIPA_IP, "GIPA_IP"},
    847 	{SLI_CTNS_GID_FT, "GID_FT"},
    848 	{SLI_CTNS_GID_PT, "GID_PT"},
    849 	{SLI_CTNS_RPN_ID, "RPN_ID"},
    850 	{SLI_CTNS_RNN_ID, "RNN_ID"},
    851 	{SLI_CTNS_RCS_ID, "RCS_ID"},
    852 	{SLI_CTNS_RFT_ID, "RFT_ID"},
    853 	{SLI_CTNS_RSPN_ID, "RSPN_ID"},
    854 	{SLI_CTNS_RPT_ID, "RPT_ID"},
    855 	{SLI_CTNS_RIP_NN, "RIP_NN"},
    856 	{SLI_CTNS_RIPA_NN, "RIPA_NN"},
    857 	{SLI_CTNS_RSNN_NN, "RSNN_NN"},
    858 	{SLI_CTNS_DA_ID, "DA_ID"},
    859 	{SLI_CT_LOOPBACK, "LOOPBACK"} /* Driver special */
    860 
    861 };	/* emlxs_ctcmd_table */
    862 
    863 
    864 
    865 emlxs_table_t emlxs_rmcmd_table[] = {
    866 	{SLI_CT_RESPONSE_FS_ACC, "CT_ACC"},
    867 	{SLI_CT_RESPONSE_FS_RJT, "CT_RJT"},
    868 	{CT_OP_GSAT, "RM_GSAT"},
    869 	{CT_OP_GHAT, "RM_GHAT"},
    870 	{CT_OP_GPAT, "RM_GPAT"},
    871 	{CT_OP_GDAT, "RM_GDAT"},
    872 	{CT_OP_GPST, "RM_GPST"},
    873 	{CT_OP_GDP, "RM_GDP"},
    874 	{CT_OP_GDPG, "RM_GDPG"},
    875 	{CT_OP_GEPS, "RM_GEPS"},
    876 	{CT_OP_GLAT, "RM_GLAT"},
    877 	{CT_OP_SSAT, "RM_SSAT"},
    878 	{CT_OP_SHAT, "RM_SHAT"},
    879 	{CT_OP_SPAT, "RM_SPAT"},
    880 	{CT_OP_SDAT, "RM_SDAT"},
    881 	{CT_OP_SDP, "RM_SDP"},
    882 	{CT_OP_SBBS, "RM_SBBS"},
    883 	{CT_OP_RPST, "RM_RPST"},
    884 	{CT_OP_VFW, "RM_VFW"},
    885 	{CT_OP_DFW, "RM_DFW"},
    886 	{CT_OP_RES, "RM_RES"},
    887 	{CT_OP_RHD, "RM_RHD"},
    888 	{CT_OP_UFW, "RM_UFW"},
    889 	{CT_OP_RDP, "RM_RDP"},
    890 	{CT_OP_GHDR, "RM_GHDR"},
    891 	{CT_OP_CHD, "RM_CHD"},
    892 	{CT_OP_SSR, "RM_SSR"},
    893 	{CT_OP_RSAT, "RM_RSAT"},
    894 	{CT_OP_WSAT, "RM_WSAT"},
    895 	{CT_OP_RSAH, "RM_RSAH"},
    896 	{CT_OP_WSAH, "RM_WSAH"},
    897 	{CT_OP_RACT, "RM_RACT"},
    898 	{CT_OP_WACT, "RM_WACT"},
    899 	{CT_OP_RKT, "RM_RKT"},
    900 	{CT_OP_WKT, "RM_WKT"},
    901 	{CT_OP_SSC, "RM_SSC"},
    902 	{CT_OP_QHBA, "RM_QHBA"},
    903 	{CT_OP_GST, "RM_GST"},
    904 	{CT_OP_GFTM, "RM_GFTM"},
    905 	{CT_OP_SRL, "RM_SRL"},
    906 	{CT_OP_SI, "RM_SI"},
    907 	{CT_OP_SRC, "RM_SRC"},
    908 	{CT_OP_GPB, "RM_GPB"},
    909 	{CT_OP_SPB, "RM_SPB"},
    910 	{CT_OP_RPB, "RM_RPB"},
    911 	{CT_OP_RAPB, "RM_RAPB"},
    912 	{CT_OP_GBC, "RM_GBC"},
    913 	{CT_OP_GBS, "RM_GBS"},
    914 	{CT_OP_SBS, "RM_SBS"},
    915 	{CT_OP_GANI, "RM_GANI"},
    916 	{CT_OP_GRV, "RM_GRV"},
    917 	{CT_OP_GAPBS, "RM_GAPBS"},
    918 	{CT_OP_APBC, "RM_APBC"},
    919 	{CT_OP_GDT, "RM_GDT"},
    920 	{CT_OP_GDLMI, "RM_GDLMI"},
    921 	{CT_OP_GANA, "RM_GANA"},
    922 	{CT_OP_GDLV, "RM_GDLV"},
    923 	{CT_OP_GWUP, "RM_GWUP"},
    924 	{CT_OP_GLM, "RM_GLM"},
    925 	{CT_OP_GABS, "RM_GABS"},
    926 	{CT_OP_SABS, "RM_SABS"},
    927 	{CT_OP_RPR, "RM_RPR"},
    928 	{SLI_CT_LOOPBACK, "LOOPBACK"} /* Driver special */
    929 
    930 };	/* emlxs_rmcmd_table */
    931 
    932 
    933 emlxs_table_t emlxs_elscmd_table[] = {
    934 	{ELS_CMD_ACC, "ACC"},
    935 	{ELS_CMD_LS_RJT, "LS_RJT"},
    936 	{ELS_CMD_PLOGI, "PLOGI"},
    937 	{ELS_CMD_FLOGI, "FLOGI"},
    938 	{ELS_CMD_LOGO, "LOGO"},
    939 	{ELS_CMD_ABTX, "ABTX"},
    940 	{ELS_CMD_RCS, "RCS"},
    941 	{ELS_CMD_RES, "RES"},
    942 	{ELS_CMD_RSS, "RSS"},
    943 	{ELS_CMD_RSI, "RSI"},
    944 	{ELS_CMD_ESTS, "ESTS"},
    945 	{ELS_CMD_ESTC, "ESTC"},
    946 	{ELS_CMD_ADVC, "ADVC"},
    947 	{ELS_CMD_RTV, "RTV"},
    948 	{ELS_CMD_RLS, "RLS"},
    949 	{ELS_CMD_ECHO, "ECHO"},
    950 	{ELS_CMD_TEST, "TEST"},
    951 	{ELS_CMD_RRQ, "RRQ"},
    952 	{ELS_CMD_PRLI, "PRLI"},
    953 	{ELS_CMD_PRLO, "PRLO"},
    954 	{ELS_CMD_SCN, "SCN"},
    955 	{ELS_CMD_TPLS, "TPLS"},
    956 	{ELS_CMD_GPRLO, "GPRLO"},
    957 	{ELS_CMD_GAID, "GAID"},
    958 	{ELS_CMD_FACT, "FACT"},
    959 	{ELS_CMD_FDACT, "FDACT"},
    960 	{ELS_CMD_NACT, "NACT"},
    961 	{ELS_CMD_NDACT, "NDACT"},
    962 	{ELS_CMD_QoSR, "QoSR"},
    963 	{ELS_CMD_RVCS, "RVCS"},
    964 	{ELS_CMD_PDISC, "PDISC"},
    965 	{ELS_CMD_FDISC, "FDISC"},
    966 	{ELS_CMD_ADISC, "ADISC"},
    967 	{ELS_CMD_FARP, "FARP"},
    968 	{ELS_CMD_FARPR, "FARPR"},
    969 	{ELS_CMD_FAN, "FAN"},
    970 	{ELS_CMD_RSCN, "RSCN"},
    971 	{ELS_CMD_SCR, "SCR"},
    972 	{ELS_CMD_LINIT, "LINIT"},
    973 	{ELS_CMD_RNID, "RNID"},
    974 	{ELS_CMD_AUTH, "AUTH"}
    975 
    976 };	/* emlxs_elscmd_table */
    977 
    978 
    979 /*
    980  *
    981  *	Device Driver Entry Routines
    982  *
    983  */
    984 
    985 #ifdef MODSYM_SUPPORT
    986 static void emlxs_fca_modclose();
    987 static int  emlxs_fca_modopen();
    988 emlxs_modsym_t emlxs_modsym;	/* uses emlxs_device.lock */
    989 
    990 static int
    991 emlxs_fca_modopen()
    992 {
    993 	int err;
    994 
    995 	if (emlxs_modsym.mod_fctl) {
    996 		return (0);
    997 	}
    998 
    999 	/* Leadville (fctl) */
   1000 	err = 0;
   1001 	emlxs_modsym.mod_fctl =
   1002 	    ddi_modopen("misc/fctl", KRTLD_MODE_FIRST, &err);
   1003 	if (!emlxs_modsym.mod_fctl) {
   1004 		cmn_err(CE_WARN,
   1005 		    "?%s: misc/fctl: ddi_modopen misc/fctl failed: error=%d",
   1006 		    DRIVER_NAME, err);
   1007 
   1008 		goto failed;
   1009 	}
   1010 
   1011 	err = 0;
   1012 	/* Check if the fctl fc_fca_attach is present */
   1013 	emlxs_modsym.fc_fca_attach =
   1014 	    (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_attach",
   1015 	    &err);
   1016 	if ((void *)emlxs_modsym.fc_fca_attach == NULL) {
   1017 		cmn_err(CE_WARN,
   1018 		    "?%s: misc/fctl: fc_fca_attach not present", DRIVER_NAME);
   1019 		goto failed;
   1020 	}
   1021 
   1022 	err = 0;
   1023 	/* Check if the fctl fc_fca_detach is present */
   1024 	emlxs_modsym.fc_fca_detach =
   1025 	    (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_detach",
   1026 	    &err);
   1027 	if ((void *)emlxs_modsym.fc_fca_detach == NULL) {
   1028 		cmn_err(CE_WARN,
   1029 		    "?%s: misc/fctl: fc_fca_detach not present", DRIVER_NAME);
   1030 		goto failed;
   1031 	}
   1032 
   1033 	err = 0;
   1034 	/* Check if the fctl fc_fca_init is present */
   1035 	emlxs_modsym.fc_fca_init =
   1036 	    (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_init", &err);
   1037 	if ((void *)emlxs_modsym.fc_fca_init == NULL) {
   1038 		cmn_err(CE_WARN,
   1039 		    "?%s: misc/fctl: fc_fca_init not present", DRIVER_NAME);
   1040 		goto failed;
   1041 	}
   1042 
   1043 	return (0);
   1044 
   1045 failed:
   1046 
   1047 	emlxs_fca_modclose();
   1048 
   1049 	return (1);
   1050 
   1051 
   1052 } /* emlxs_fca_modopen() */
   1053 
   1054 
   1055 static void
   1056 emlxs_fca_modclose()
   1057 {
   1058 	if (emlxs_modsym.mod_fctl) {
   1059 		(void) ddi_modclose(emlxs_modsym.mod_fctl);
   1060 		emlxs_modsym.mod_fctl = 0;
   1061 	}
   1062 
   1063 	emlxs_modsym.fc_fca_attach = NULL;
   1064 	emlxs_modsym.fc_fca_detach = NULL;
   1065 	emlxs_modsym.fc_fca_init   = NULL;
   1066 
   1067 	return;
   1068 
   1069 } /* emlxs_fca_modclose() */
   1070 
   1071 #endif /* MODSYM_SUPPORT */
   1072 
   1073 
   1074 
   1075 /*
   1076  * Global driver initialization, called once when driver is loaded
   1077  */
   1078 int
   1079 _init(void)
   1080 {
   1081 	int ret;
   1082 	char buf[64];
   1083 
   1084 	/*
   1085 	 * First init call for this driver,
   1086 	 * so initialize the emlxs_dev_ctl structure.
   1087 	 */
   1088 	bzero(&emlxs_device, sizeof (emlxs_device));
   1089 
   1090 #ifdef MODSYM_SUPPORT
   1091 	bzero(&emlxs_modsym, sizeof (emlxs_modsym_t));
   1092 #endif /* MODSYM_SUPPORT */
   1093 
   1094 	(void) sprintf(buf, "%s_device mutex", DRIVER_NAME);
   1095 	mutex_init(&emlxs_device.lock, buf, MUTEX_DRIVER, NULL);
   1096 
   1097 	(void) drv_getparm(LBOLT, &emlxs_device.log_timestamp);
   1098 	emlxs_device.drv_timestamp = ddi_get_time();
   1099 
   1100 	for (ret = 0; ret < MAX_FC_BRDS; ret++) {
   1101 		emlxs_instance[ret] = (uint32_t)-1;
   1102 	}
   1103 
   1104 	/*
   1105 	 * Provide for one ddiinst of the emlxs_dev_ctl structure
   1106 	 * for each possible board in the system.
   1107 	 */
   1108 	if ((ret = ddi_soft_state_init(&emlxs_soft_state,
   1109 	    sizeof (emlxs_hba_t), MAX_FC_BRDS)) != 0) {
   1110 		cmn_err(CE_WARN,
   1111 		    "?%s: _init: ddi_soft_state_init failed. rval=%x",
   1112 		    DRIVER_NAME, ret);
   1113 
   1114 		return (ret);
   1115 	}
   1116 
   1117 #ifdef MODSYM_SUPPORT
   1118 	/* Open SFS */
   1119 	(void) emlxs_fca_modopen();
   1120 #endif /* MODSYM_SUPPORT */
   1121 
   1122 	/* Setup devops for SFS */
   1123 	MODSYM(fc_fca_init)(&emlxs_ops);
   1124 
   1125 	if ((ret = mod_install(&emlxs_modlinkage)) != 0) {
   1126 		(void) ddi_soft_state_fini(&emlxs_soft_state);
   1127 #ifdef MODSYM_SUPPORT
   1128 		/* Close SFS */
   1129 		emlxs_fca_modclose();
   1130 #endif /* MODSYM_SUPPORT */
   1131 
   1132 		return (ret);
   1133 	}
   1134 
   1135 #ifdef SAN_DIAG_SUPPORT
   1136 	(void) sprintf(buf, "%s_sd_bucket mutex", DRIVER_NAME);
   1137 	mutex_init(&sd_bucket_mutex, buf, MUTEX_DRIVER, NULL);
   1138 #endif /* SAN_DIAG_SUPPORT */
   1139 
   1140 	return (ret);
   1141 
   1142 } /* _init() */
   1143 
   1144 
   1145 /*
   1146  * Called when driver is unloaded.
   1147  */
   1148 int
   1149 _fini(void)
   1150 {
   1151 	int ret;
   1152 
   1153 	if ((ret = mod_remove(&emlxs_modlinkage)) != 0) {
   1154 		return (ret);
   1155 	}
   1156 #ifdef MODSYM_SUPPORT
   1157 	/* Close SFS */
   1158 	emlxs_fca_modclose();
   1159 #endif /* MODSYM_SUPPORT */
   1160 
   1161 	/*
   1162 	 * Destroy the soft state structure
   1163 	 */
   1164 	(void) ddi_soft_state_fini(&emlxs_soft_state);
   1165 
   1166 	/* Destroy the global device lock */
   1167 	mutex_destroy(&emlxs_device.lock);
   1168 
   1169 #ifdef SAN_DIAG_SUPPORT
   1170 	mutex_destroy(&sd_bucket_mutex);
   1171 #endif /* SAN_DIAG_SUPPORT */
   1172 
   1173 	return (ret);
   1174 
   1175 } /* _fini() */
   1176 
   1177 
   1178 
   1179 int
   1180 _info(struct modinfo *modinfop)
   1181 {
   1182 
   1183 	return (mod_info(&emlxs_modlinkage, modinfop));
   1184 
   1185 } /* _info() */
   1186 
   1187 
   1188 /*
   1189  * Attach an ddiinst of an emlx host adapter.
   1190  * Allocate data structures, initialize the adapter and we're ready to fly.
   1191  */
   1192 static int
   1193 emlxs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
   1194 {
   1195 	emlxs_hba_t *hba;
   1196 	int ddiinst;
   1197 	int emlxinst;
   1198 	int rval;
   1199 
   1200 	switch (cmd) {
   1201 	case DDI_ATTACH:
   1202 		/* If successful this will set EMLXS_PM_IN_ATTACH */
   1203 		rval = emlxs_hba_attach(dip);
   1204 		break;
   1205 
   1206 	case DDI_PM_RESUME:
   1207 		/* This will resume the driver */
   1208 		rval = emlxs_pm_raise_power(dip);
   1209 		break;
   1210 
   1211 	case DDI_RESUME:
   1212 		/* This will resume the driver */
   1213 		rval = emlxs_hba_resume(dip);
   1214 		break;
   1215 
   1216 	default:
   1217 		rval = DDI_FAILURE;
   1218 	}
   1219 
   1220 	if (rval == DDI_SUCCESS) {
   1221 		ddiinst = ddi_get_instance(dip);
   1222 		emlxinst = emlxs_get_instance(ddiinst);
   1223 		hba = emlxs_device.hba[emlxinst];
   1224 
   1225 		if ((hba != NULL) && (hba != (emlxs_hba_t *)-1)) {
   1226 
   1227 			/* Enable driver dump feature */
   1228 			mutex_enter(&EMLXS_PORT_LOCK);
   1229 			hba->flag |= FC_DUMP_SAFE;
   1230 			mutex_exit(&EMLXS_PORT_LOCK);
   1231 		}
   1232 	}
   1233 
   1234 	return (rval);
   1235 
   1236 } /* emlxs_attach() */
   1237 
   1238 
   1239 /*
   1240  * Detach/prepare driver to unload (see detach(9E)).
   1241  */
   1242 static int
   1243 emlxs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
   1244 {
   1245 	emlxs_hba_t *hba;
   1246 	emlxs_port_t *port;
   1247 	int ddiinst;
   1248 	int emlxinst;
   1249 	int rval;
   1250 
   1251 	ddiinst = ddi_get_instance(dip);
   1252 	emlxinst = emlxs_get_instance(ddiinst);
   1253 	hba = emlxs_device.hba[emlxinst];
   1254 
   1255 	if (hba == NULL) {
   1256 		cmn_err(CE_WARN, "?%s: Detach: NULL device.", DRIVER_NAME);
   1257 
   1258 		return (DDI_FAILURE);
   1259 	}
   1260 
   1261 	if (hba == (emlxs_hba_t *)-1) {
   1262 		cmn_err(CE_WARN, "?%s: Detach: Device attach failed.",
   1263 		    DRIVER_NAME);
   1264 
   1265 		return (DDI_FAILURE);
   1266 	}
   1267 
   1268 	port = &PPORT;
   1269 	rval = DDI_SUCCESS;
   1270 
   1271 	/* Check driver dump */
   1272 	mutex_enter(&EMLXS_PORT_LOCK);
   1273 
   1274 	if (hba->flag & FC_DUMP_ACTIVE) {
   1275 		mutex_exit(&EMLXS_PORT_LOCK);
   1276 
   1277 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
   1278 		    "emlxs_detach: Driver busy. Driver dump active.");
   1279 
   1280 		return (DDI_FAILURE);
   1281 	}
   1282 
   1283 #ifdef SFCT_SUPPORT
   1284 	if (port->tgt_mode && ((port->fct_flags & FCT_STATE_PORT_ONLINE) ||
   1285 	    (port->fct_flags & FCT_STATE_NOT_ACKED))) {
   1286 		mutex_exit(&EMLXS_PORT_LOCK);
   1287 
   1288 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
   1289 		    "emlxs_detach: Driver busy. Target mode active.");
   1290 
   1291 		return (DDI_FAILURE);
   1292 	}
   1293 #endif /* SFCT_SUPPORT */
   1294 
   1295 	if (port->ini_mode && (port->flag & EMLXS_PORT_BOUND)) {
   1296 		mutex_exit(&EMLXS_PORT_LOCK);
   1297 
   1298 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
   1299 		    "emlxs_detach: Driver busy. Initiator mode active.");
   1300 
   1301 		return (DDI_FAILURE);
   1302 	}
   1303 
   1304 	hba->flag &= ~FC_DUMP_SAFE;
   1305 
   1306 	mutex_exit(&EMLXS_PORT_LOCK);
   1307 
   1308 	switch (cmd) {
   1309 	case DDI_DETACH:
   1310 
   1311 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg,
   1312 		    "DDI_DETACH");
   1313 
   1314 		rval = emlxs_hba_detach(dip);
   1315 
   1316 		if (rval != DDI_SUCCESS) {
   1317 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
   1318 			    "Unable to detach.");
   1319 		}
   1320 		break;
   1321 
   1322 
   1323 	case DDI_PM_SUSPEND:
   1324 
   1325 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg,
   1326 		    "DDI_PM_SUSPEND");
   1327 
   1328 		/* This will suspend the driver */
   1329 		rval = emlxs_pm_lower_power(dip);
   1330 
   1331 		if (rval != DDI_SUCCESS) {
   1332 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
   1333 			    "Unable to lower power.");
   1334 		}
   1335 
   1336 		break;
   1337 
   1338 
   1339 	case DDI_SUSPEND:
   1340 
   1341 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg,
   1342 		    "DDI_SUSPEND");
   1343 
   1344 		/* Suspend the driver */
   1345 		rval = emlxs_hba_suspend(dip);
   1346 
   1347 		if (rval != DDI_SUCCESS) {
   1348 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
   1349 			    "Unable to suspend driver.");
   1350 		}
   1351 		break;
   1352 
   1353 
   1354 	default:
   1355 		cmn_err(CE_WARN, "?%s: Detach: Unknown cmd received. cmd=%x",
   1356 		    DRIVER_NAME, cmd);
   1357 		rval = DDI_FAILURE;
   1358 	}
   1359 
   1360 	if (rval == DDI_FAILURE) {
   1361 		/* Re-Enable driver dump feature */
   1362 		mutex_enter(&EMLXS_PORT_LOCK);
   1363 		hba->flag |= FC_DUMP_SAFE;
   1364 		mutex_exit(&EMLXS_PORT_LOCK);
   1365 	}
   1366 
   1367 	return (rval);
   1368 
   1369 } /* emlxs_detach() */
   1370 
   1371 
   1372 /* EMLXS_PORT_LOCK must be held when calling this */
   1373 extern void
   1374 emlxs_port_init(emlxs_port_t *port)
   1375 {
   1376 	emlxs_hba_t *hba = HBA;
   1377 
   1378 	/* Initialize the base node */
   1379 	bzero((caddr_t)&port->node_base, sizeof (NODELIST));
   1380 	port->node_base.nlp_Rpi = 0;
   1381 	port->node_base.nlp_DID = 0xffffff;
   1382 	port->node_base.nlp_list_next = NULL;
   1383 	port->node_base.nlp_list_prev = NULL;
   1384 	port->node_base.nlp_active = 1;
   1385 	port->node_base.nlp_base = 1;
   1386 	port->node_count = 0;
   1387 
   1388 	if (!(port->flag & EMLXS_PORT_ENABLE)) {
   1389 		uint8_t dummy_wwn[8] =
   1390 		    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
   1391 
   1392 		bcopy((caddr_t)dummy_wwn, (caddr_t)&port->wwnn,
   1393 		    sizeof (NAME_TYPE));
   1394 		bcopy((caddr_t)dummy_wwn, (caddr_t)&port->wwpn,
   1395 		    sizeof (NAME_TYPE));
   1396 	}
   1397 
   1398 	if (!(port->flag & EMLXS_PORT_CONFIG)) {
   1399 		(void) strncpy((caddr_t)port->snn, (caddr_t)hba->snn, 256);
   1400 		(void) strncpy((caddr_t)port->spn, (caddr_t)hba->spn, 256);
   1401 	}
   1402 
   1403 	bcopy((caddr_t)&hba->sparam, (caddr_t)&port->sparam,
   1404 	    sizeof (SERV_PARM));
   1405 	bcopy((caddr_t)&port->wwnn, (caddr_t)&port->sparam.nodeName,
   1406 	    sizeof (NAME_TYPE));
   1407 	bcopy((caddr_t)&port->wwpn, (caddr_t)&port->sparam.portName,
   1408 	    sizeof (NAME_TYPE));
   1409 
   1410 	return;
   1411 
   1412 } /* emlxs_port_init() */
   1413 
   1414 
   1415 void
   1416 emlxs_disable_pcie_ce_err(emlxs_hba_t *hba)
   1417 {
   1418 #define	NXT_PTR_OFF		PCI_BYTE
   1419 #define	PCIE_DEVCTL_OFF		0x8
   1420 #define	PCIE_CAP_ID		0x10
   1421 
   1422 	uint8_t	cap_ptr;
   1423 	uint8_t	cap_id;
   1424 	uint16_t  tmp16;
   1425 
   1426 	cap_ptr = ddi_get8(hba->pci_acc_handle,
   1427 	    (uint8_t *)(hba->pci_addr + PCI_CAP_POINTER));
   1428 
   1429 	while (cap_ptr) {
   1430 		cap_id = ddi_get8(hba->pci_acc_handle,
   1431 		    (uint8_t *)(hba->pci_addr + cap_ptr));
   1432 
   1433 		if (cap_id == PCIE_CAP_ID) {
   1434 			break;
   1435 		}
   1436 		cap_ptr = ddi_get8(hba->pci_acc_handle,
   1437 		    (uint8_t *)(hba->pci_addr + cap_ptr + NXT_PTR_OFF));
   1438 	}
   1439 
   1440 	/* PCI Express Capability Register Set */
   1441 	/* Turn off the Correctable Error Reporting */
   1442 	/* (the Device Control Register, bit 0). */
   1443 
   1444 	if (cap_id == PCIE_CAP_ID) {
   1445 		tmp16 = ddi_get16(hba->pci_acc_handle,
   1446 		    (uint16_t *)(hba->pci_addr + cap_ptr + PCIE_DEVCTL_OFF));
   1447 		tmp16 &= ~1;
   1448 		(void) ddi_put16(hba->pci_acc_handle,
   1449 		    (uint16_t *)(hba->pci_addr + cap_ptr + PCIE_DEVCTL_OFF),
   1450 		    tmp16);
   1451 	}
   1452 }
   1453 
   1454 /*
   1455  * emlxs_bind_port
   1456  *
   1457  * Arguments:
   1458  *
   1459  * dip: the dev_info pointer for the ddiinst
   1460  * port_info: pointer to info handed back to the transport
   1461  * bind_info: pointer to info from the transport
   1462  *
   1463  * Return values: a port handle for this port, NULL for failure
   1464  *
   1465  */
   1466 static opaque_t
   1467 emlxs_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info,
   1468     fc_fca_bind_info_t *bind_info)
   1469 {
   1470 	emlxs_hba_t *hba;
   1471 	emlxs_port_t *port;
   1472 	emlxs_port_t *vport;
   1473 	int ddiinst;
   1474 	emlxs_vpd_t *vpd;
   1475 	emlxs_config_t *cfg;
   1476 	char *dptr;
   1477 	char buffer[16];
   1478 	uint32_t length;
   1479 	uint32_t len;
   1480 	char topology[32];
   1481 	char linkspeed[32];
   1482 
   1483 	ddiinst = ddi_get_instance(dip);
   1484 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
   1485 	port = &PPORT;
   1486 
   1487 	ddiinst = hba->ddiinst;
   1488 	vpd = &VPD;
   1489 	cfg = &CFG;
   1490 
   1491 	mutex_enter(&EMLXS_PORT_LOCK);
   1492 
   1493 	if (bind_info->port_num > 0) {
   1494 #if (EMLXS_MODREV >= EMLXS_MODREV5)
   1495 		if (!(hba->flag & FC_NPIV_ENABLED) ||
   1496 		    !(bind_info->port_npiv) ||
   1497 		    (bind_info->port_num > hba->vpi_max))
   1498 #elif (EMLXS_MODREV >= EMLXS_MODREV3)
   1499 		if (!(hba->flag & FC_NPIV_ENABLED) ||
   1500 		    (bind_info->port_num > hba->vpi_high))
   1501 #endif
   1502 		{
   1503 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   1504 			    "emlxs_port_bind: Port %d not supported.",
   1505 			    bind_info->port_num);
   1506 
   1507 			mutex_exit(&EMLXS_PORT_LOCK);
   1508 
   1509 			port_info->pi_error = FC_OUTOFBOUNDS;
   1510 			return (NULL);
   1511 		}
   1512 	}
   1513 
   1514 	/* Get true port pointer */
   1515 	port = &VPORT(bind_info->port_num);
   1516 
   1517 	if (port->tgt_mode) {
   1518 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   1519 		    "emlxs_port_bind: Port %d is in target mode.",
   1520 		    bind_info->port_num);
   1521 
   1522 		mutex_exit(&EMLXS_PORT_LOCK);
   1523 
   1524 		port_info->pi_error = FC_OUTOFBOUNDS;
   1525 		return (NULL);
   1526 	}
   1527 
   1528 	if (!port->ini_mode) {
   1529 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   1530 		    "emlxs_port_bind: Port %d is not in initiator mode.",
   1531 		    bind_info->port_num);
   1532 
   1533 		mutex_exit(&EMLXS_PORT_LOCK);
   1534 
   1535 		port_info->pi_error = FC_OUTOFBOUNDS;
   1536 		return (NULL);
   1537 	}
   1538 
   1539 	/* Make sure the port is not already bound to the transport */
   1540 	if (port->flag & EMLXS_PORT_BOUND) {
   1541 
   1542 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   1543 		    "emlxs_port_bind: Port %d already bound. flag=%x",
   1544 		    bind_info->port_num, port->flag);
   1545 
   1546 		mutex_exit(&EMLXS_PORT_LOCK);
   1547 
   1548 		port_info->pi_error = FC_ALREADY;
   1549 		return (NULL);
   1550 	}
   1551 
   1552 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   1553 	    "fca_bind_port: Port %d: port_info=%p bind_info=%p",
   1554 	    bind_info->port_num, port_info, bind_info);
   1555 
   1556 #if (EMLXS_MODREV >= EMLXS_MODREV5)
   1557 	if (bind_info->port_npiv) {
   1558 		bcopy((caddr_t)&bind_info->port_nwwn, (caddr_t)&port->wwnn,
   1559 		    sizeof (NAME_TYPE));
   1560 		bcopy((caddr_t)&bind_info->port_pwwn, (caddr_t)&port->wwpn,
   1561 		    sizeof (NAME_TYPE));
   1562 		if (port->snn[0] == 0) {
   1563 			(void) strncpy((caddr_t)port->snn, (caddr_t)hba->snn,
   1564 			    256);
   1565 		}
   1566 
   1567 		if (port->spn[0] == 0) {
   1568 			(void) sprintf((caddr_t)port->spn, "%s VPort-%d",
   1569 			    (caddr_t)hba->spn, port->vpi);
   1570 		}
   1571 		port->flag |= (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE);
   1572 	}
   1573 #endif /* >= EMLXS_MODREV5 */
   1574 
   1575 	/*
   1576 	 * Restricted login should apply both physical and
   1577 	 * virtual ports.
   1578 	 */
   1579 	if (cfg[CFG_VPORT_RESTRICTED].current) {
   1580 		port->flag |= EMLXS_PORT_RESTRICTED;
   1581 	}
   1582 
   1583 	/* Perform generic port initialization */
   1584 	emlxs_port_init(port);
   1585 
   1586 	/* Perform SFS specific initialization */
   1587 	port->ulp_handle	= bind_info->port_handle;
   1588 	port->ulp_statec_cb	= bind_info->port_statec_cb;
   1589 	port->ulp_unsol_cb	= bind_info->port_unsol_cb;
   1590 	port->ub_count		= EMLXS_UB_TOKEN_OFFSET;
   1591 	port->ub_pool		= NULL;
   1592 
   1593 	/* Update the port info structure */
   1594 
   1595 	/* Set the topology and state */
   1596 	if ((hba->state < FC_LINK_UP) ||
   1597 	    ((port->vpi > 0) && (!(port->flag & EMLXS_PORT_ENABLE) ||
   1598 	    !(hba->flag & FC_NPIV_SUPPORTED)))) {
   1599 		port_info->pi_port_state = FC_STATE_OFFLINE;
   1600 		port_info->pi_topology = FC_TOP_UNKNOWN;
   1601 	}
   1602 #ifdef MENLO_SUPPORT
   1603 	else if (hba->flag & FC_MENLO_MODE) {
   1604 		port_info->pi_port_state = FC_STATE_OFFLINE;
   1605 		port_info->pi_topology = FC_TOP_UNKNOWN;
   1606 	}
   1607 #endif /* MENLO_SUPPORT */
   1608 	else {
   1609 		/* Check for loop topology */
   1610 		if (hba->topology == TOPOLOGY_LOOP) {
   1611 			port_info->pi_port_state = FC_STATE_LOOP;
   1612 			(void) strcpy(topology, ", loop");
   1613 
   1614 			if (hba->flag & FC_FABRIC_ATTACHED) {
   1615 				port_info->pi_topology = FC_TOP_PUBLIC_LOOP;
   1616 			} else {
   1617 				port_info->pi_topology = FC_TOP_PRIVATE_LOOP;
   1618 			}
   1619 		} else {
   1620 			port_info->pi_topology = FC_TOP_FABRIC;
   1621 			port_info->pi_port_state = FC_STATE_ONLINE;
   1622 			(void) strcpy(topology, ", fabric");
   1623 		}
   1624 
   1625 		/* Set the link speed */
   1626 		switch (hba->linkspeed) {
   1627 		case 0:
   1628 			(void) strcpy(linkspeed, "Gb");
   1629 			port_info->pi_port_state |= FC_STATE_1GBIT_SPEED;
   1630 			break;
   1631 
   1632 		case LA_1GHZ_LINK:
   1633 			(void) strcpy(linkspeed, "1Gb");
   1634 			port_info->pi_port_state |= FC_STATE_1GBIT_SPEED;
   1635 			break;
   1636 		case LA_2GHZ_LINK:
   1637 			(void) strcpy(linkspeed, "2Gb");
   1638 			port_info->pi_port_state |= FC_STATE_2GBIT_SPEED;
   1639 			break;
   1640 		case LA_4GHZ_LINK:
   1641 			(void) strcpy(linkspeed, "4Gb");
   1642 			port_info->pi_port_state |= FC_STATE_4GBIT_SPEED;
   1643 			break;
   1644 		case LA_8GHZ_LINK:
   1645 			(void) strcpy(linkspeed, "8Gb");
   1646 			port_info->pi_port_state |= FC_STATE_8GBIT_SPEED;
   1647 			break;
   1648 		case LA_10GHZ_LINK:
   1649 			(void) strcpy(linkspeed, "10Gb");
   1650 			port_info->pi_port_state |= FC_STATE_10GBIT_SPEED;
   1651 			break;
   1652 		default:
   1653 			(void) sprintf(linkspeed, "unknown(0x%x)",
   1654 			    hba->linkspeed);
   1655 			break;
   1656 		}
   1657 
   1658 		/* Adjusting port context for link up messages */
   1659 		vport = port;
   1660 		port = &PPORT;
   1661 		if (vport->vpi == 0) {
   1662 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, "%s%s",
   1663 			    linkspeed, topology);
   1664 		} else if (!(hba->flag & FC_NPIV_LINKUP)) {
   1665 			hba->flag |= FC_NPIV_LINKUP;
   1666 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_npiv_link_up_msg,
   1667 			    "%s%s", linkspeed, topology);
   1668 		}
   1669 		port = vport;
   1670 
   1671 	}
   1672 
   1673 	/* PCIE Correctable Error Reporting workaround */
   1674 	if ((hba->model_info.chip == EMLXS_BE_CHIP) &&
   1675 	    (bind_info->port_num == 0)) {
   1676 		emlxs_disable_pcie_ce_err(hba);
   1677 	}
   1678 
   1679 	/* Save initial state */
   1680 	port->ulp_statec = port_info->pi_port_state;
   1681 
   1682 	/*
   1683 	 * The transport needs a copy of the common service parameters
   1684 	 * for this port. The transport can get any updates through
   1685 	 * the getcap entry point.
   1686 	 */
   1687 	bcopy((void *) &port->sparam,
   1688 	    (void *) &port_info->pi_login_params.common_service,
   1689 	    sizeof (SERV_PARM));
   1690 
   1691 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
   1692 	/* Swap the service parameters for ULP */
   1693 	emlxs_swap_service_params((SERV_PARM *)&port_info->pi_login_params.
   1694 	    common_service);
   1695 #endif /* EMLXS_MODREV2X */
   1696 
   1697 	port_info->pi_login_params.common_service.btob_credit = 0xffff;
   1698 
   1699 	bcopy((void *) &port->wwnn,
   1700 	    (void *) &port_info->pi_login_params.node_ww_name,
   1701 	    sizeof (NAME_TYPE));
   1702 
   1703 	bcopy((void *) &port->wwpn,
   1704 	    (void *) &port_info->pi_login_params.nport_ww_name,
   1705 	    sizeof (NAME_TYPE));
   1706 
   1707 	/*
   1708 	 * We need to turn off CLASS2 support.
   1709 	 * Otherwise, FC transport will use CLASS2 as default class
   1710 	 * and never try with CLASS3.
   1711 	 */
   1712 #if (EMLXS_MODREV >= EMLXS_MODREV3)
   1713 #if (EMLXS_MODREVX >= EMLXS_MODREV3X)
   1714 	if ((port_info->pi_login_params.class_1.class_opt) & 0x0080) {
   1715 		port_info->pi_login_params.class_1.class_opt &= ~0x0080;
   1716 	}
   1717 
   1718 	if ((port_info->pi_login_params.class_2.class_opt) & 0x0080) {
   1719 		port_info->pi_login_params.class_2.class_opt &= ~0x0080;
   1720 	}
   1721 #else	/* EMLXS_SPARC or EMLXS_MODREV2X */
   1722 	if ((port_info->pi_login_params.class_1.class_opt) & 0x8000) {
   1723 		port_info->pi_login_params.class_1.class_opt &= ~0x8000;
   1724 	}
   1725 
   1726 	if ((port_info->pi_login_params.class_2.class_opt) & 0x8000) {
   1727 		port_info->pi_login_params.class_2.class_opt &= ~0x8000;
   1728 	}
   1729 #endif	/* >= EMLXS_MODREV3X */
   1730 #endif	/* >= EMLXS_MODREV3 */
   1731 
   1732 
   1733 #if (EMLXS_MODREV <= EMLXS_MODREV2)
   1734 	if ((port_info->pi_login_params.class_1.data[0]) & 0x80) {
   1735 		port_info->pi_login_params.class_1.data[0] &= ~0x80;
   1736 	}
   1737 
   1738 	if ((port_info->pi_login_params.class_2.data[0]) & 0x80) {
   1739 		port_info->pi_login_params.class_2.data[0] &= ~0x80;
   1740 	}
   1741 #endif	/* <= EMLXS_MODREV2 */
   1742 
   1743 	/* Additional parameters */
   1744 	port_info->pi_s_id.port_id = port->did;
   1745 	port_info->pi_s_id.priv_lilp_posit = 0;
   1746 	port_info->pi_hard_addr.hard_addr = cfg[CFG_ASSIGN_ALPA].current;
   1747 
   1748 	/* Initialize the RNID parameters */
   1749 	bzero(&port_info->pi_rnid_params, sizeof (port_info->pi_rnid_params));
   1750 
   1751 	(void) sprintf((char *)port_info->pi_rnid_params.params.global_id,
   1752 	    "%01x%01x%02x%02x%02x%02x%02x%02x%02x", hba->wwpn.nameType,
   1753 	    hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb, hba->wwpn.IEEE[0],
   1754 	    hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], hba->wwpn.IEEE[3],
   1755 	    hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
   1756 
   1757 	port_info->pi_rnid_params.params.unit_type  = RNID_HBA;
   1758 	port_info->pi_rnid_params.params.port_id    = port->did;
   1759 	port_info->pi_rnid_params.params.ip_version = RNID_IPV4;
   1760 
   1761 	/* Initialize the port attributes */
   1762 	bzero(&port_info->pi_attrs, sizeof (port_info->pi_attrs));
   1763 
   1764 	(void) strcpy(port_info->pi_attrs.manufacturer, "Emulex");
   1765 
   1766 	port_info->pi_rnid_params.status = FC_SUCCESS;
   1767 
   1768 	(void) strcpy(port_info->pi_attrs.serial_number, vpd->serial_num);
   1769 
   1770 	(void) sprintf(port_info->pi_attrs.firmware_version, "%s (%s)",
   1771 	    vpd->fw_version, vpd->fw_label);
   1772 
   1773 #ifdef EMLXS_I386
   1774 	(void) sprintf(port_info->pi_attrs.option_rom_version,
   1775 	    "Boot:%s", vpd->boot_version);
   1776 #else	/* EMLXS_SPARC */
   1777 	(void) sprintf(port_info->pi_attrs.option_rom_version,
   1778 	    "Boot:%s Fcode:%s", vpd->boot_version, vpd->fcode_version);
   1779 #endif	/* EMLXS_I386 */
   1780 
   1781 
   1782 	(void) sprintf(port_info->pi_attrs.driver_version, "%s (%s)",
   1783 	    emlxs_version, emlxs_revision);
   1784 
   1785 	(void) strcpy(port_info->pi_attrs.driver_name, DRIVER_NAME);
   1786 
   1787 	port_info->pi_attrs.vendor_specific_id =
   1788 	    ((hba->model_info.device_id << 16) | PCI_VENDOR_ID_EMULEX);
   1789 
   1790 	port_info->pi_attrs.supported_cos = LE_SWAP32(FC_NS_CLASS3);
   1791 
   1792 	port_info->pi_attrs.max_frame_size = FF_FRAME_SIZE;
   1793 
   1794 #if (EMLXS_MODREV >= EMLXS_MODREV5)
   1795 
   1796 	port_info->pi_rnid_params.params.num_attached = 0;
   1797 
   1798 	/*
   1799 	 * Copy the serial number string (right most 16 chars) into the right
   1800 	 * justified local buffer
   1801 	 */
   1802 	bzero(buffer, sizeof (buffer));
   1803 	length = strlen(vpd->serial_num);
   1804 	len = (length > 16) ? 16 : length;
   1805 	bcopy(&vpd->serial_num[(length - len)],
   1806 	    &buffer[(sizeof (buffer) - len)], len);
   1807 
   1808 	port_info->pi_attrs.hba_fru_details.port_index = vpd->port_index;
   1809 
   1810 #endif /* >= EMLXS_MODREV5 */
   1811 
   1812 #if ((EMLXS_MODREV == EMLXS_MODREV3) || (EMLX_MODREV == EMLXS_MODREV4))
   1813 
   1814 	port_info->pi_rnid_params.params.num_attached = 0;
   1815 
   1816 	if (hba->flag & FC_NPIV_ENABLED) {
   1817 		uint8_t		byte;
   1818 		uint8_t		*wwpn;
   1819 		uint32_t	i;
   1820 		uint32_t	j;
   1821 
   1822 		/* Copy the WWPN as a string into the local buffer */
   1823 		wwpn = (uint8_t *)&hba->wwpn;
   1824 		for (i = 0; i < 16; i++) {
   1825 			byte = *wwpn++;
   1826 			j = ((byte & 0xf0) >> 4);
   1827 			if (j <= 9) {
   1828 				buffer[i] =
   1829 				    (char)((uint8_t)'0' + (uint8_t)j);
   1830 			} else {
   1831 				buffer[i] =
   1832 				    (char)((uint8_t)'A' + (uint8_t)(j -
   1833 				    10));
   1834 			}
   1835 
   1836 			i++;
   1837 			j = (byte & 0xf);
   1838 			if (j <= 9) {
   1839 				buffer[i] =
   1840 				    (char)((uint8_t)'0' + (uint8_t)j);
   1841 			} else {
   1842 				buffer[i] =
   1843 				    (char)((uint8_t)'A' + (uint8_t)(j -
   1844 				    10));
   1845 			}
   1846 			}
   1847 
   1848 		port_info->pi_attrs.hba_fru_details.port_index = port->vpi;
   1849 	} else {
   1850 		/* Copy the serial number string (right most 16 chars) */
   1851 		/* into the right justified local buffer */
   1852 		bzero(buffer, sizeof (buffer));
   1853 		length = strlen(vpd->serial_num);
   1854 		len = (length > 16) ? 16 : length;
   1855 		bcopy(&vpd->serial_num[(length - len)],
   1856 		    &buffer[(sizeof (buffer) - len)], len);
   1857 
   1858 		port_info->pi_attrs.hba_fru_details.port_index =
   1859 		    vpd->port_index;
   1860 	}
   1861 
   1862 #endif /* == EMLXS_MODREV3 || EMLXS_MODREV4 */
   1863 
   1864 #if (EMLXS_MODREV >= EMLXS_MODREV3)
   1865 
   1866 	dptr = (char *)&port_info->pi_attrs.hba_fru_details.high;
   1867 	dptr[0] = buffer[0];
   1868 	dptr[1] = buffer[1];
   1869 	dptr[2] = buffer[2];
   1870 	dptr[3] = buffer[3];
   1871 	dptr[4] = buffer[4];
   1872 	dptr[5] = buffer[5];
   1873 	dptr[6] = buffer[6];
   1874 	dptr[7] = buffer[7];
   1875 	port_info->pi_attrs.hba_fru_details.high =
   1876 	    LE_SWAP64(port_info->pi_attrs.hba_fru_details.high);
   1877 
   1878 	dptr = (char *)&port_info->pi_attrs.hba_fru_details.low;
   1879 	dptr[0] = buffer[8];
   1880 	dptr[1] = buffer[9];
   1881 	dptr[2] = buffer[10];
   1882 	dptr[3] = buffer[11];
   1883 	dptr[4] = buffer[12];
   1884 	dptr[5] = buffer[13];
   1885 	dptr[6] = buffer[14];
   1886 	dptr[7] = buffer[15];
   1887 	port_info->pi_attrs.hba_fru_details.low =
   1888 	    LE_SWAP64(port_info->pi_attrs.hba_fru_details.low);
   1889 
   1890 #endif /* >= EMLXS_MODREV3 */
   1891 
   1892 #if (EMLXS_MODREV >= EMLXS_MODREV4)
   1893 	(void) strncpy((caddr_t)port_info->pi_attrs.sym_node_name,
   1894 	    (caddr_t)port->snn, FCHBA_SYMB_NAME_LEN);
   1895 	(void) strncpy((caddr_t)port_info->pi_attrs.sym_port_name,
   1896 	    (caddr_t)port->spn, FCHBA_SYMB_NAME_LEN);
   1897 #endif	/* >= EMLXS_MODREV4 */
   1898 
   1899 	(void) sprintf(port_info->pi_attrs.hardware_version, "%x", vpd->biuRev);
   1900 
   1901 	/* Set the hba speed limit */
   1902 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
   1903 		port_info->pi_attrs.supported_speed |=
   1904 		    FC_HBA_PORTSPEED_10GBIT;
   1905 	}
   1906 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
   1907 		port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_8GBIT;
   1908 	}
   1909 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
   1910 		port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_4GBIT;
   1911 	}
   1912 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
   1913 		port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_2GBIT;
   1914 	}
   1915 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
   1916 		port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_1GBIT;
   1917 	}
   1918 
   1919 	/* Set the hba model info */
   1920 	(void) strcpy(port_info->pi_attrs.model, hba->model_info.model);
   1921 	(void) strcpy(port_info->pi_attrs.model_description,
   1922 	    hba->model_info.model_desc);
   1923 
   1924 
   1925 	/* Log information */
   1926 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1927 	    "Bind info: port_num           = %d", bind_info->port_num);
   1928 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1929 	    "Bind info: port_handle        = %p", bind_info->port_handle);
   1930 
   1931 #if (EMLXS_MODREV >= EMLXS_MODREV5)
   1932 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1933 	    "Bind info: port_npiv          = %d", bind_info->port_npiv);
   1934 #endif /* >= EMLXS_MODREV5 */
   1935 
   1936 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1937 	    "Port info: pi_topology        = %x", port_info->pi_topology);
   1938 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1939 	    "Port info: pi_error           = %x", port_info->pi_error);
   1940 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1941 	    "Port info: pi_port_state      = %x", port_info->pi_port_state);
   1942 
   1943 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1944 	    "Port info: port_id            = %x", port_info->pi_s_id.port_id);
   1945 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1946 	    "Port info: priv_lilp_posit    = %x",
   1947 	    port_info->pi_s_id.priv_lilp_posit);
   1948 
   1949 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1950 	    "Port info: hard_addr          = %x",
   1951 	    port_info->pi_hard_addr.hard_addr);
   1952 
   1953 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1954 	    "Port info: rnid.status        = %x",
   1955 	    port_info->pi_rnid_params.status);
   1956 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1957 	    "Port info: rnid.global_id     = %16s",
   1958 	    port_info->pi_rnid_params.params.global_id);
   1959 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1960 	    "Port info: rnid.unit_type     = %x",
   1961 	    port_info->pi_rnid_params.params.unit_type);
   1962 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1963 	    "Port info: rnid.port_id       = %x",
   1964 	    port_info->pi_rnid_params.params.port_id);
   1965 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1966 	    "Port info: rnid.num_attached  = %x",
   1967 	    port_info->pi_rnid_params.params.num_attached);
   1968 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1969 	    "Port info: rnid.ip_version    = %x",
   1970 	    port_info->pi_rnid_params.params.ip_version);
   1971 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1972 	    "Port info: rnid.udp_port      = %x",
   1973 	    port_info->pi_rnid_params.params.udp_port);
   1974 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1975 	    "Port info: rnid.ip_addr       = %16s",
   1976 	    port_info->pi_rnid_params.params.ip_addr);
   1977 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1978 	    "Port info: rnid.spec_id_resv  = %x",
   1979 	    port_info->pi_rnid_params.params.specific_id_resv);
   1980 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1981 	    "Port info: rnid.topo_flags    = %x",
   1982 	    port_info->pi_rnid_params.params.topo_flags);
   1983 
   1984 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1985 	    "Port info: manufacturer       = %s",
   1986 	    port_info->pi_attrs.manufacturer);
   1987 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1988 	    "Port info: serial_num         = %s",
   1989 	    port_info->pi_attrs.serial_number);
   1990 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1991 	    "Port info: model              = %s", port_info->pi_attrs.model);
   1992 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1993 	    "Port info: model_description  = %s",
   1994 	    port_info->pi_attrs.model_description);
   1995 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1996 	    "Port info: hardware_version   = %s",
   1997 	    port_info->pi_attrs.hardware_version);
   1998 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   1999 	    "Port info: driver_version     = %s",
   2000 	    port_info->pi_attrs.driver_version);
   2001 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   2002 	    "Port info: option_rom_version = %s",
   2003 	    port_info->pi_attrs.option_rom_version);
   2004 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   2005 	    "Port info: firmware_version   = %s",
   2006 	    port_info->pi_attrs.firmware_version);
   2007 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   2008 	    "Port info: driver_name        = %s",
   2009 	    port_info->pi_attrs.driver_name);
   2010 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   2011 	    "Port info: vendor_specific_id = %x",
   2012 	    port_info->pi_attrs.vendor_specific_id);
   2013 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   2014 	    "Port info: supported_cos      = %x",
   2015 	    port_info->pi_attrs.supported_cos);
   2016 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   2017 	    "Port info: supported_speed    = %x",
   2018 	    port_info->pi_attrs.supported_speed);
   2019 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   2020 	    "Port info: max_frame_size     = %x",
   2021 	    port_info->pi_attrs.max_frame_size);
   2022 
   2023 #if (EMLXS_MODREV >= EMLXS_MODREV3)
   2024 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   2025 	    "Port info: fru_port_index     = %x",
   2026 	    port_info->pi_attrs.hba_fru_details.port_index);
   2027 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   2028 	    "Port info: fru_high           = %llx",
   2029 	    port_info->pi_attrs.hba_fru_details.high);
   2030 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   2031 	    "Port info: fru_low            = %llx",
   2032 	    port_info->pi_attrs.hba_fru_details.low);
   2033 #endif	/* >= EMLXS_MODREV3 */
   2034 
   2035 #if (EMLXS_MODREV >= EMLXS_MODREV4)
   2036 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   2037 	    "Port info: sym_node_name      = %s",
   2038 	    port_info->pi_attrs.sym_node_name);
   2039 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   2040 	    "Port info: sym_port_name      = %s",
   2041 	    port_info->pi_attrs.sym_port_name);
   2042 #endif	/* >= EMLXS_MODREV4 */
   2043 
   2044 	/* Set the bound flag */
   2045 	port->flag |= EMLXS_PORT_BOUND;
   2046 	hba->num_of_ports++;
   2047 
   2048 	mutex_exit(&EMLXS_PORT_LOCK);
   2049 
   2050 	return ((opaque_t)port);
   2051 
   2052 } /* emlxs_bind_port() */
   2053 
   2054 
   2055 static void
   2056 emlxs_unbind_port(opaque_t fca_port_handle)
   2057 {
   2058 	emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
   2059 	emlxs_hba_t *hba = HBA;
   2060 
   2061 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2062 	    "fca_unbind_port: port=%p", port);
   2063 
   2064 	/* Destroy & flush all port nodes, if they exist */
   2065 	if (port->node_count) {
   2066 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
   2067 			(void) emlxs_sli4_unreg_all_rpi_by_port(port);
   2068 		} else {
   2069 			(void) emlxs_mb_unreg_rpi(port, 0xffff, 0, 0, 0);
   2070 		}
   2071 	}
   2072 
   2073 #if (EMLXS_MODREV >= EMLXS_MODREV5)
   2074 	if ((hba->flag & FC_NPIV_ENABLED) &&
   2075 	    (port->flag & (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE))) {
   2076 		(void) emlxs_mb_unreg_vpi(port);
   2077 	}
   2078 #endif
   2079 
   2080 	mutex_enter(&EMLXS_PORT_LOCK);
   2081 
   2082 	if (!(port->flag & EMLXS_PORT_BOUND)) {
   2083 		mutex_exit(&EMLXS_PORT_LOCK);
   2084 		return;
   2085 	}
   2086 
   2087 	port->flag &= ~EMLXS_PORT_BOUND;
   2088 	hba->num_of_ports--;
   2089 
   2090 	port->ulp_handle = 0;
   2091 	port->ulp_statec = FC_STATE_OFFLINE;
   2092 	port->ulp_statec_cb = NULL;
   2093 	port->ulp_unsol_cb = NULL;
   2094 
   2095 	mutex_exit(&EMLXS_PORT_LOCK);
   2096 
   2097 	return;
   2098 
   2099 } /* emlxs_unbind_port() */
   2100 
   2101 
   2102 /*ARGSUSED*/
   2103 extern int
   2104 emlxs_pkt_init(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep)
   2105 {
   2106 	emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
   2107 	emlxs_hba_t  *hba = HBA;
   2108 	emlxs_buf_t  *sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
   2109 
   2110 	if (!sbp) {
   2111 		return (FC_FAILURE);
   2112 	}
   2113 	bzero((void *)sbp, sizeof (emlxs_buf_t));
   2114 
   2115 	mutex_init(&sbp->mtx, NULL, MUTEX_DRIVER, (void *)hba->intr_arg);
   2116 	sbp->pkt_flags =
   2117 	    PACKET_VALID | PACKET_ULP_OWNED;
   2118 	sbp->port = port;
   2119 	sbp->pkt = pkt;
   2120 	sbp->iocbq.sbp = sbp;
   2121 
   2122 	return (FC_SUCCESS);
   2123 
   2124 } /* emlxs_pkt_init() */
   2125 
   2126 
   2127 
   2128 static void
   2129 emlxs_initialize_pkt(emlxs_port_t *port, emlxs_buf_t *sbp)
   2130 {
   2131 	emlxs_hba_t *hba = HBA;
   2132 	emlxs_config_t *cfg = &CFG;
   2133 	fc_packet_t *pkt = PRIV2PKT(sbp);
   2134 	uint32_t *iptr;
   2135 
   2136 	mutex_enter(&sbp->mtx);
   2137 
   2138 	/* Reinitialize */
   2139 	sbp->pkt   = pkt;
   2140 	sbp->port  = port;
   2141 	sbp->bmp   = NULL;
   2142 	sbp->pkt_flags &= (PACKET_VALID | PACKET_ALLOCATED);
   2143 	sbp->iotag = 0;
   2144 	sbp->ticks = 0;
   2145 	sbp->abort_attempts = 0;
   2146 	sbp->fpkt  = NULL;
   2147 	sbp->flush_count = 0;
   2148 	sbp->next  = NULL;
   2149 
   2150 	if (!port->tgt_mode) {
   2151 		sbp->node  = NULL;
   2152 		sbp->did   = 0;
   2153 		sbp->lun   = 0;
   2154 		sbp->class = 0;
   2155 		sbp->class = 0;
   2156 		sbp->channel  = NULL;
   2157 	}
   2158 
   2159 	bzero((void *)&sbp->iocbq, sizeof (IOCBQ));
   2160 	sbp->iocbq.sbp = sbp;
   2161 
   2162 	if ((pkt->pkt_tran_flags & FC_TRAN_NO_INTR) || !pkt->pkt_comp ||
   2163 	    ddi_in_panic()) {
   2164 		sbp->pkt_flags |= PACKET_POLLED;
   2165 	}
   2166 
   2167 	/* Prepare the fc packet */
   2168 	pkt->pkt_state = FC_PKT_SUCCESS;
   2169 	pkt->pkt_reason = 0;
   2170 	pkt->pkt_action = 0;
   2171 	pkt->pkt_expln = 0;
   2172 	pkt->pkt_data_resid = 0;
   2173 	pkt->pkt_resp_resid = 0;
   2174 
   2175 	/* Make sure all pkt's have a proper timeout */
   2176 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
   2177 		/* This disables all IOCB on chip timeouts */
   2178 		pkt->pkt_timeout = 0x80000000;
   2179 	} else if (pkt->pkt_timeout == 0 || pkt->pkt_timeout == 0xffffffff) {
   2180 		pkt->pkt_timeout = 60;
   2181 	}
   2182 
   2183 	/* Clear the response buffer */
   2184 	if (pkt->pkt_rsplen) {
   2185 		/* Check for FCP commands */
   2186 		if ((pkt->pkt_tran_type == FC_PKT_FCP_READ) ||
   2187 		    (pkt->pkt_tran_type == FC_PKT_FCP_WRITE)) {
   2188 			iptr = (uint32_t *)pkt->pkt_resp;
   2189 			iptr[2] = 0;
   2190 			iptr[3] = 0;
   2191 		} else {
   2192 		bzero(pkt->pkt_resp, pkt->pkt_rsplen);
   2193 	}
   2194 	}
   2195 
   2196 	mutex_exit(&sbp->mtx);
   2197 
   2198 	return;
   2199 
   2200 } /* emlxs_initialize_pkt() */
   2201 
   2202 
   2203 
   2204 /*
   2205  * We may not need this routine
   2206  */
   2207 /*ARGSUSED*/
   2208 extern int
   2209 emlxs_pkt_uninit(opaque_t fca_port_handle, fc_packet_t *pkt)
   2210 {
   2211 	emlxs_buf_t  *sbp = PKT2PRIV(pkt);
   2212 
   2213 	if (!sbp) {
   2214 		return (FC_FAILURE);
   2215 	}
   2216 
   2217 	if (!(sbp->pkt_flags & PACKET_VALID)) {
   2218 		return (FC_FAILURE);
   2219 	}
   2220 	sbp->pkt_flags &= ~PACKET_VALID;
   2221 	mutex_destroy(&sbp->mtx);
   2222 
   2223 	return (FC_SUCCESS);
   2224 
   2225 } /* emlxs_pkt_uninit() */
   2226 
   2227 
   2228 static int
   2229 emlxs_get_cap(opaque_t fca_port_handle, char *cap, void *ptr)
   2230 {
   2231 	emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
   2232 	emlxs_hba_t  *hba = HBA;
   2233 	int32_t rval;
   2234 
   2235 	if (!(port->flag & EMLXS_PORT_BOUND)) {
   2236 		return (FC_CAP_ERROR);
   2237 	}
   2238 
   2239 	if (strcmp(cap, FC_NODE_WWN) == 0) {
   2240 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2241 		    "fca_get_cap: FC_NODE_WWN");
   2242 
   2243 		bcopy((void *)&hba->wwnn, (void *)ptr, sizeof (NAME_TYPE));
   2244 		rval = FC_CAP_FOUND;
   2245 
   2246 	} else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) {
   2247 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2248 		    "fca_get_cap: FC_LOGIN_PARAMS");
   2249 
   2250 		/*
   2251 		 * We need to turn off CLASS2 support.
   2252 		 * Otherwise, FC transport will use CLASS2 as default class
   2253 		 * and never try with CLASS3.
   2254 		 */
   2255 		hba->sparam.cls2.classValid = 0;
   2256 
   2257 		bcopy((void *)&hba->sparam, (void *)ptr, sizeof (SERV_PARM));
   2258 
   2259 		rval = FC_CAP_FOUND;
   2260 
   2261 	} else if (strcmp(cap, FC_CAP_UNSOL_BUF) == 0) {
   2262 		int32_t		*num_bufs;
   2263 		emlxs_config_t	*cfg = &CFG;
   2264 
   2265 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2266 		    "fca_get_cap: FC_CAP_UNSOL_BUF (%d)",
   2267 		    cfg[CFG_UB_BUFS].current);
   2268 
   2269 		num_bufs = (int32_t *)ptr;
   2270 
   2271 		/* We multiply by MAX_VPORTS because ULP uses a */
   2272 		/* formula to calculate ub bufs from this */
   2273 		*num_bufs = (cfg[CFG_UB_BUFS].current * MAX_VPORTS);
   2274 
   2275 		rval = FC_CAP_FOUND;
   2276 
   2277 	} else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) {
   2278 		int32_t		*size;
   2279 
   2280 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2281 		    "fca_get_cap: FC_CAP_PAYLOAD_SIZE");
   2282 
   2283 		size = (int32_t *)ptr;
   2284 		*size = -1;
   2285 		rval = FC_CAP_FOUND;
   2286 
   2287 	} else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) {
   2288 		fc_reset_action_t *action;
   2289 
   2290 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2291 		    "fca_get_cap: FC_CAP_POST_RESET_BEHAVIOR");
   2292 
   2293 		action = (fc_reset_action_t *)ptr;
   2294 		*action = FC_RESET_RETURN_ALL;
   2295 		rval = FC_CAP_FOUND;
   2296 
   2297 	} else if (strcmp(cap, FC_CAP_NOSTREAM_ON_UNALIGN_BUF) == 0) {
   2298 		fc_dma_behavior_t *behavior;
   2299 
   2300 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2301 		    "fca_get_cap: FC_CAP_NOSTREAM_ON_UNALIGN_BUF");
   2302 
   2303 		behavior = (fc_dma_behavior_t *)ptr;
   2304 		*behavior = FC_ALLOW_STREAMING;
   2305 		rval = FC_CAP_FOUND;
   2306 
   2307 	} else if (strcmp(cap, FC_CAP_FCP_DMA) == 0) {
   2308 		fc_fcp_dma_t   *fcp_dma;
   2309 
   2310 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2311 		    "fca_get_cap: FC_CAP_FCP_DMA");
   2312 
   2313 		fcp_dma = (fc_fcp_dma_t *)ptr;
   2314 		*fcp_dma = FC_DVMA_SPACE;
   2315 		rval = FC_CAP_FOUND;
   2316 
   2317 	} else {
   2318 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2319 		    "fca_get_cap: Unknown capability. [%s]", cap);
   2320 
   2321 		rval = FC_CAP_ERROR;
   2322 
   2323 	}
   2324 
   2325 	return (rval);
   2326 
   2327 } /* emlxs_get_cap() */
   2328 
   2329 
   2330 
   2331 static int
   2332 emlxs_set_cap(opaque_t fca_port_handle, char *cap, void *ptr)
   2333 {
   2334 	emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
   2335 
   2336 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2337 	    "fca_set_cap: cap=[%s] arg=%p", cap, ptr);
   2338 
   2339 	return (FC_CAP_ERROR);
   2340 
   2341 } /* emlxs_set_cap() */
   2342 
   2343 
   2344 static opaque_t
   2345 emlxs_get_device(opaque_t fca_port_handle, fc_portid_t d_id)
   2346 {
   2347 	emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
   2348 
   2349 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2350 	    "fca_get_device: did=%x", d_id.port_id);
   2351 
   2352 	return (NULL);
   2353 
   2354 } /* emlxs_get_device() */
   2355 
   2356 
   2357 static int32_t
   2358 emlxs_notify(opaque_t fca_port_handle, uint32_t cmd)
   2359 {
   2360 	emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
   2361 
   2362 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, "fca_notify: cmd=%x",
   2363 	    cmd);
   2364 
   2365 	return (FC_SUCCESS);
   2366 
   2367 } /* emlxs_notify */
   2368 
   2369 
   2370 
   2371 static int
   2372 emlxs_get_map(opaque_t fca_port_handle, fc_lilpmap_t *mapbuf)
   2373 {
   2374 	emlxs_port_t	*port = (emlxs_port_t *)fca_port_handle;
   2375 	emlxs_hba_t	*hba = HBA;
   2376 	uint32_t	lilp_length;
   2377 
   2378 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2379 	    "fca_get_map: mapbuf=%p length=%d (%X,%X,%X,%X)", mapbuf,
   2380 	    port->alpa_map[0], port->alpa_map[1], port->alpa_map[2],
   2381 	    port->alpa_map[3], port->alpa_map[4]);
   2382 
   2383 	if (!(port->flag & EMLXS_PORT_BOUND)) {
   2384 		return (FC_NOMAP);
   2385 	}
   2386 
   2387 	if (hba->topology != TOPOLOGY_LOOP) {
   2388 		return (FC_NOMAP);
   2389 	}
   2390 
   2391 	/* Check if alpa map is available */
   2392 	if (port->alpa_map[0] != 0) {
   2393 		mapbuf->lilp_magic  = MAGIC_LILP;
   2394 	} else {	/* No LILP map available */
   2395 
   2396 		/* Set lilp_magic to MAGIC_LISA and this will */
   2397 		/* trigger an ALPA scan in ULP */
   2398 		mapbuf->lilp_magic  = MAGIC_LISA;
   2399 	}
   2400 
   2401 	mapbuf->lilp_myalpa = port->did;
   2402 
   2403 	/* The first byte of the alpa_map is the lilp map length */
   2404 	/* Add one to include the lilp length byte itself */
   2405 	lilp_length = (uint32_t)port->alpa_map[0] + 1;
   2406 
   2407 	/* Make sure the max transfer is 128 bytes */
   2408 	if (lilp_length > 128) {
   2409 		lilp_length = 128;
   2410 	}
   2411 
   2412 	/* We start copying from the lilp_length field */
   2413 	/* in order to get a word aligned address */
   2414 	bcopy((void *)&port->alpa_map, (void *)&mapbuf->lilp_length,
   2415 	    lilp_length);
   2416 
   2417 	return (FC_SUCCESS);
   2418 
   2419 } /* emlxs_get_map() */
   2420 
   2421 
   2422 
   2423 extern int
   2424 emlxs_transport(opaque_t fca_port_handle, fc_packet_t *pkt)
   2425 {
   2426 	emlxs_port_t	*port = (emlxs_port_t *)fca_port_handle;
   2427 	emlxs_hba_t	*hba = HBA;
   2428 	emlxs_buf_t	*sbp;
   2429 	uint32_t	rval;
   2430 	uint32_t	pkt_flags;
   2431 
   2432 	/* Make sure adapter is online */
   2433 	if (!(hba->flag & FC_ONLINE_MODE)) {
   2434 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
   2435 		    "Adapter offline.");
   2436 
   2437 		return (FC_OFFLINE);
   2438 	}
   2439 
   2440 	/* Validate packet */
   2441 	sbp = PKT2PRIV(pkt);
   2442 
   2443 	/* Make sure ULP was told that the port was online */
   2444 	if ((port->ulp_statec == FC_STATE_OFFLINE) &&
   2445 	    !(sbp->pkt_flags & PACKET_ALLOCATED)) {
   2446 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
   2447 		    "Port offline.");
   2448 
   2449 		return (FC_OFFLINE);
   2450 	}
   2451 
   2452 	if (sbp->port != port) {
   2453 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
   2454 		    "Invalid port handle. sbp=%p port=%p flags=%x", sbp,
   2455 		    sbp->port, sbp->pkt_flags);
   2456 		return (FC_BADPACKET);
   2457 	}
   2458 
   2459 	if (!(sbp->pkt_flags & (PACKET_VALID | PACKET_ULP_OWNED))) {
   2460 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
   2461 		    "Invalid packet flags. sbp=%p port=%p flags=%x", sbp,
   2462 		    sbp->port, sbp->pkt_flags);
   2463 		return (FC_BADPACKET);
   2464 	}
   2465 #ifdef SFCT_SUPPORT
   2466 	if (port->tgt_mode && !sbp->fct_cmd &&
   2467 	    !(sbp->pkt_flags & PACKET_ALLOCATED)) {
   2468 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
   2469 		    "Packet blocked. Target mode.");
   2470 		return (FC_TRANSPORT_ERROR);
   2471 	}
   2472 #endif /* SFCT_SUPPORT */
   2473 
   2474 #ifdef IDLE_TIMER
   2475 	emlxs_pm_busy_component(hba);
   2476 #endif	/* IDLE_TIMER */
   2477 
   2478 	/* Prepare the packet for transport */
   2479 	emlxs_initialize_pkt(port, sbp);
   2480 
   2481 	/* Save a copy of the pkt flags. */
   2482 	/* We will check the polling flag later */
   2483 	pkt_flags = sbp->pkt_flags;
   2484 
   2485 	/* Send the packet */
   2486 	switch (pkt->pkt_tran_type) {
   2487 	case FC_PKT_FCP_READ:
   2488 	case FC_PKT_FCP_WRITE:
   2489 		rval = emlxs_send_fcp_cmd(port, sbp);
   2490 		break;
   2491 
   2492 	case FC_PKT_IP_WRITE:
   2493 	case FC_PKT_BROADCAST:
   2494 		rval = emlxs_send_ip(port, sbp);
   2495 		break;
   2496 
   2497 	case FC_PKT_EXCHANGE:
   2498 		switch (pkt->pkt_cmd_fhdr.type) {
   2499 		case FC_TYPE_SCSI_FCP:
   2500 			rval = emlxs_send_fcp_cmd(port, sbp);
   2501 			break;
   2502 
   2503 		case FC_TYPE_FC_SERVICES:
   2504 			rval = emlxs_send_ct(port, sbp);
   2505 			break;
   2506 
   2507 #ifdef MENLO_SUPPORT
   2508 		case EMLXS_MENLO_TYPE:
   2509 			rval = emlxs_send_menlo(port, sbp);
   2510 			break;
   2511 #endif /* MENLO_SUPPORT */
   2512 
   2513 		default:
   2514 			rval = emlxs_send_els(port, sbp);
   2515 		}
   2516 		break;
   2517 
   2518 	case FC_PKT_OUTBOUND:
   2519 		switch (pkt->pkt_cmd_fhdr.type) {
   2520 #ifdef SFCT_SUPPORT
   2521 		case FC_TYPE_SCSI_FCP:
   2522 			rval = emlxs_send_fct_status(port, sbp);
   2523 			break;
   2524 
   2525 		case FC_TYPE_BASIC_LS:
   2526 			rval = emlxs_send_fct_abort(port, sbp);
   2527 			break;
   2528 #endif /* SFCT_SUPPORT */
   2529 
   2530 		case FC_TYPE_FC_SERVICES:
   2531 			rval = emlxs_send_ct_rsp(port, sbp);
   2532 			break;
   2533 #ifdef MENLO_SUPPORT
   2534 		case EMLXS_MENLO_TYPE:
   2535 			rval = emlxs_send_menlo(port, sbp);
   2536 			break;
   2537 #endif /* MENLO_SUPPORT */
   2538 
   2539 		default:
   2540 			rval = emlxs_send_els_rsp(port, sbp);
   2541 		}
   2542 		break;
   2543 
   2544 	default:
   2545 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
   2546 		    "Unsupported pkt_tran_type. type=%x", pkt->pkt_tran_type);
   2547 		rval = FC_TRANSPORT_ERROR;
   2548 		break;
   2549 	}
   2550 
   2551 	/* Check if send was not successful */
   2552 	if (rval != FC_SUCCESS) {
   2553 		/* Return packet to ULP */
   2554 		mutex_enter(&sbp->mtx);
   2555 		sbp->pkt_flags |= PACKET_ULP_OWNED;
   2556 		mutex_exit(&sbp->mtx);
   2557 
   2558 		return (rval);
   2559 	}
   2560 
   2561 	/* Check if this packet should be polled for completion before */
   2562 	/* returning. This check must be done with a saved copy of the */
   2563 	/* pkt_flags because the packet itself could already be freed from */
   2564 	/* memory if it was not polled. */
   2565 	if (pkt_flags & PACKET_POLLED) {
   2566 		emlxs_poll(port, sbp);
   2567 	}
   2568 
   2569 	return (FC_SUCCESS);
   2570 
   2571 } /* emlxs_transport() */
   2572 
   2573 
   2574 
   2575 static void
   2576 emlxs_poll(emlxs_port_t *port, emlxs_buf_t *sbp)
   2577 {
   2578 	emlxs_hba_t	*hba = HBA;
   2579 	fc_packet_t	*pkt = PRIV2PKT(sbp);
   2580 	clock_t		timeout;
   2581 	clock_t		time;
   2582 	uint32_t	att_bit;
   2583 	CHANNEL	*cp;
   2584 	int		in_panic = 0;
   2585 
   2586 	mutex_enter(&EMLXS_PORT_LOCK);
   2587 	hba->io_poll_count++;
   2588 	mutex_exit(&EMLXS_PORT_LOCK);
   2589 
   2590 	/* Check for panic situation */
   2591 	cp = (CHANNEL *)sbp->channel;
   2592 
   2593 	if (ddi_in_panic()) {
   2594 		in_panic = 1;
   2595 		/*
   2596 		 * In panic situations there will be one thread with
   2597 		 * no interrrupts (hard or soft) and no timers
   2598 		 */
   2599 
   2600 		/*
   2601 		 * We must manually poll everything in this thread
   2602 		 * to keep the driver going.
   2603 		 */
   2604 		if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) {
   2605 			switch (cp->channelno) {
   2606 			case FC_FCP_RING:
   2607 				att_bit = HA_R0ATT;
   2608 				break;
   2609 
   2610 			case FC_IP_RING:
   2611 				att_bit = HA_R1ATT;
   2612 				break;
   2613 
   2614 			case FC_ELS_RING:
   2615 				att_bit = HA_R2ATT;
   2616 				break;
   2617 
   2618 			case FC_CT_RING:
   2619 				att_bit = HA_R3ATT;
   2620 				break;
   2621 			}
   2622 		}
   2623 
   2624 		/* Keep polling the chip until our IO is completed */
   2625 		/* Driver's timer will not function during panics. */
   2626 		/* Therefore, timer checks must be performed manually. */
   2627 		(void) drv_getparm(LBOLT, &time);
   2628 		timeout = time + drv_usectohz(1000000);
   2629 		while (!(sbp->pkt_flags & PACKET_COMPLETED)) {
   2630 			if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) {
   2631 				EMLXS_SLI_POLL_INTR(hba, att_bit);
   2632 			} else {
   2633 				EMLXS_SLI_POLL_INTR(hba, 0);
   2634 			}
   2635 			(void) drv_getparm(LBOLT, &time);
   2636 
   2637 			/* Trigger timer checks periodically */
   2638 			if (time >= timeout) {
   2639 				emlxs_timer_checks(hba);
   2640 				timeout = time + drv_usectohz(1000000);
   2641 			}
   2642 		}
   2643 	} else {
   2644 		/* Wait for IO completion */
   2645 		/* The driver's timer will detect */
   2646 		/* any timeout and abort the I/O. */
   2647 		mutex_enter(&EMLXS_PKT_LOCK);
   2648 		while (!(sbp->pkt_flags & PACKET_COMPLETED)) {
   2649 			cv_wait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK);
   2650 		}
   2651 		mutex_exit(&EMLXS_PKT_LOCK);
   2652 	}
   2653 
   2654 	/* Check for fcp reset pkt */
   2655 	if (sbp->pkt_flags & PACKET_FCP_RESET) {
   2656 		if (sbp->pkt_flags & PACKET_FCP_TGT_RESET) {
   2657 			/* Flush the IO's on the chipq */
   2658 			(void) emlxs_chipq_node_flush(port,
   2659 			    &hba->chan[hba->channel_fcp],
   2660 			    sbp->node, sbp);
   2661 		} else {
   2662 			/* Flush the IO's on the chipq for this lun */
   2663 			(void) emlxs_chipq_lun_flush(port,
   2664 			    sbp->node, sbp->lun, sbp);
   2665 		}
   2666 
   2667 		if (sbp->flush_count == 0) {
   2668 			emlxs_node_open(port, sbp->node, hba->channel_fcp);
   2669 			goto done;
   2670 		}
   2671 
   2672 		/* Set the timeout so the flush has time to complete */
   2673 		timeout = emlxs_timeout(hba, 60);
   2674 		(void) drv_getparm(LBOLT, &time);
   2675 		while ((time < timeout) && sbp->flush_count > 0) {
   2676 			delay(drv_usectohz(500000));
   2677 			(void) drv_getparm(LBOLT, &time);
   2678 		}
   2679 
   2680 		if (sbp->flush_count == 0) {
   2681 			emlxs_node_open(port, sbp->node, hba->channel_fcp);
   2682 			goto done;
   2683 		}
   2684 
   2685 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg,
   2686 		    "sbp=%p flush_count=%d. Waiting...", sbp,
   2687 		    sbp->flush_count);
   2688 
   2689 		/* Let's try this one more time */
   2690 
   2691 		if (sbp->pkt_flags & PACKET_FCP_TGT_RESET) {
   2692 			/* Flush the IO's on the chipq */
   2693 			(void) emlxs_chipq_node_flush(port,
   2694 			    &hba->chan[hba->channel_fcp],
   2695 			    sbp->node, sbp);
   2696 		} else {
   2697 			/* Flush the IO's on the chipq for this lun */
   2698 			(void) emlxs_chipq_lun_flush(port,
   2699 			    sbp->node, sbp->lun, sbp);
   2700 		}
   2701 
   2702 		/* Reset the timeout so the flush has time to complete */
   2703 		timeout = emlxs_timeout(hba, 60);
   2704 		(void) drv_getparm(LBOLT, &time);
   2705 		while ((time < timeout) && sbp->flush_count > 0) {
   2706 			delay(drv_usectohz(500000));
   2707 			(void) drv_getparm(LBOLT, &time);
   2708 		}
   2709 
   2710 		if (sbp->flush_count == 0) {
   2711 			emlxs_node_open(port, sbp->node, hba->channel_fcp);
   2712 			goto done;
   2713 		}
   2714 
   2715 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg,
   2716 		    "sbp=%p flush_count=%d. Resetting link.", sbp,
   2717 		    sbp->flush_count);
   2718 
   2719 		/* Let's first try to reset the link */
   2720 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
   2721 
   2722 		if (sbp->flush_count == 0) {
   2723 			goto done;
   2724 		}
   2725 
   2726 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg,
   2727 		    "sbp=%p flush_count=%d. Resetting HBA.", sbp,
   2728 		    sbp->flush_count);
   2729 
   2730 		/* If that doesn't work, reset the adapter */
   2731 		(void) emlxs_reset(port, FC_FCA_RESET);
   2732 
   2733 		if (sbp->flush_count != 0) {
   2734 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg,
   2735 			    "sbp=%p flush_count=%d. Giving up.", sbp,
   2736 			    sbp->flush_count);
   2737 		}
   2738 
   2739 	}
   2740 	/* PACKET_FCP_RESET */
   2741 done:
   2742 
   2743 	/* Packet has been declared completed and is now ready to be returned */
   2744 
   2745 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
   2746 	emlxs_unswap_pkt(sbp);
   2747 #endif	/* EMLXS_MODREV2X */
   2748 
   2749 	mutex_enter(&sbp->mtx);
   2750 	sbp->pkt_flags |= PACKET_ULP_OWNED;
   2751 	mutex_exit(&sbp->mtx);
   2752 
   2753 	mutex_enter(&EMLXS_PORT_LOCK);
   2754 	hba->io_poll_count--;
   2755 	mutex_exit(&EMLXS_PORT_LOCK);
   2756 
   2757 #ifdef FMA_SUPPORT
   2758 	if (!in_panic) {
   2759 		emlxs_check_dma(hba, sbp);
   2760 	}
   2761 #endif
   2762 
   2763 	/* Make ULP completion callback if required */
   2764 	if (pkt->pkt_comp) {
   2765 		cp->ulpCmplCmd++;
   2766 		(*pkt->pkt_comp) (pkt);
   2767 	}
   2768 
   2769 #ifdef FMA_SUPPORT
   2770 	if (hba->flag & FC_DMA_CHECK_ERROR) {
   2771 		emlxs_thread_spawn(hba, emlxs_restart_thread,
   2772 		    NULL, NULL);
   2773 	}
   2774 #endif
   2775 
   2776 	return;
   2777 
   2778 } /* emlxs_poll() */
   2779 
   2780 
   2781 static int
   2782 emlxs_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size,
   2783     uint32_t *count, uint32_t type)
   2784 {
   2785 	emlxs_port_t		*port = (emlxs_port_t *)fca_port_handle;
   2786 	emlxs_hba_t		*hba = HBA;
   2787 
   2788 	char			*err = NULL;
   2789 	emlxs_unsol_buf_t	*pool;
   2790 	emlxs_unsol_buf_t	*new_pool;
   2791 	int32_t			i;
   2792 	int			result;
   2793 	uint32_t		free_resv;
   2794 	uint32_t		free;
   2795 	emlxs_config_t		*cfg = &CFG;
   2796 	fc_unsol_buf_t		*ubp;
   2797 	emlxs_ub_priv_t		*ub_priv;
   2798 	int			rc;
   2799 
   2800 	if (port->tgt_mode) {
   2801 		if (tokens && count) {
   2802 			bzero(tokens, (sizeof (uint64_t) * (*count)));
   2803 		}
   2804 		return (FC_SUCCESS);
   2805 	}
   2806 
   2807 	if (!(port->flag & EMLXS_PORT_BOUND)) {
   2808 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2809 		    "ub_alloc failed: Port not bound!  size=%x count=%d "
   2810 		    "type=%x", size, *count, type);
   2811 
   2812 		return (FC_FAILURE);
   2813 	}
   2814 
   2815 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2816 	    "ub_alloc: size=%x count=%d type=%x", size, *count, type);
   2817 
   2818 	if (count && (*count > EMLXS_MAX_UBUFS)) {
   2819 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
   2820 		    "ub_alloc failed: Too many unsolicted buffers requested. "
   2821 		    "count=%x", *count);
   2822 
   2823 		return (FC_FAILURE);
   2824 
   2825 	}
   2826 
   2827 	if (tokens == NULL) {
   2828 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
   2829 		    "ub_alloc failed: Token array is NULL.");
   2830 
   2831 		return (FC_FAILURE);
   2832 	}
   2833 
   2834 	/* Clear the token array */
   2835 	bzero(tokens, (sizeof (uint64_t) * (*count)));
   2836 
   2837 	free_resv = 0;
   2838 	free = *count;
   2839 	switch (type) {
   2840 	case FC_TYPE_BASIC_LS:
   2841 		err = "BASIC_LS";
   2842 		break;
   2843 	case FC_TYPE_EXTENDED_LS:
   2844 		err = "EXTENDED_LS";
   2845 		free = *count / 2;	/* Hold 50% for normal use */
   2846 		free_resv = *count - free;	/* Reserve 50% for RSCN use */
   2847 		break;
   2848 	case FC_TYPE_IS8802:
   2849 		err = "IS8802";
   2850 		break;
   2851 	case FC_TYPE_IS8802_SNAP:
   2852 		err = "IS8802_SNAP";
   2853 
   2854 		if (cfg[CFG_NETWORK_ON].current == 0) {
   2855 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   2856 			    "ub_alloc failed: IP support is disabled.");
   2857 
   2858 			return (FC_FAILURE);
   2859 		}
   2860 		break;
   2861 	case FC_TYPE_SCSI_FCP:
   2862 		err = "SCSI_FCP";
   2863 		break;
   2864 	case FC_TYPE_SCSI_GPP:
   2865 		err = "SCSI_GPP";
   2866 		break;
   2867 	case FC_TYPE_HIPP_FP:
   2868 		err = "HIPP_FP";
   2869 		break;
   2870 	case FC_TYPE_IPI3_MASTER:
   2871 		err = "IPI3_MASTER";
   2872 		break;
   2873 	case FC_TYPE_IPI3_SLAVE:
   2874 		err = "IPI3_SLAVE";
   2875 		break;
   2876 	case FC_TYPE_IPI3_PEER:
   2877 		err = "IPI3_PEER";
   2878 		break;
   2879 	case FC_TYPE_FC_SERVICES:
   2880 		err = "FC_SERVICES";
   2881 		break;
   2882 	}
   2883 
   2884 	mutex_enter(&EMLXS_UB_LOCK);
   2885 
   2886 	/*
   2887 	 * Walk through the list of the unsolicited buffers
   2888 	 * for this ddiinst of emlx.
   2889 	 */
   2890 
   2891 	pool = port->ub_pool;
   2892 
   2893 	/*
   2894 	 * The emlxs_ub_alloc() can be called more than once with different
   2895 	 * size. We will reject the call if there are
   2896 	 * duplicate size with the same FC-4 type.
   2897 	 */
   2898 	while (pool) {
   2899 		if ((pool->pool_type == type) &&
   2900 		    (pool->pool_buf_size == size)) {
   2901 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
   2902 			    "ub_alloc failed: Unsolicited buffer pool for %s "
   2903 			    "of size 0x%x bytes already exists.", err, size);
   2904 
   2905 			result = FC_FAILURE;
   2906 			goto fail;
   2907 		}
   2908 
   2909 		pool = pool->pool_next;
   2910 	}
   2911 
   2912 	mutex_exit(&EMLXS_UB_LOCK);
   2913 
   2914 	new_pool = (emlxs_unsol_buf_t *)kmem_zalloc(sizeof (emlxs_unsol_buf_t),
   2915 	    KM_SLEEP);
   2916 
   2917 	new_pool->pool_next = NULL;
   2918 	new_pool->pool_type = type;
   2919 	new_pool->pool_buf_size = size;
   2920 	new_pool->pool_nentries = *count;
   2921 	new_pool->pool_available = new_pool->pool_nentries;
   2922 	new_pool->pool_free = free;
   2923 	new_pool->pool_free_resv = free_resv;
   2924 	new_pool->fc_ubufs =
   2925 	    kmem_zalloc((sizeof (fc_unsol_buf_t) * (*count)), KM_SLEEP);
   2926 
   2927 	new_pool->pool_first_token = port->ub_count;
   2928 	new_pool->pool_last_token = port->ub_count + new_pool->pool_nentries;
   2929 
   2930 	for (i = 0; i < new_pool->pool_nentries; i++) {
   2931 		ubp = (fc_unsol_buf_t *)&new_pool->fc_ubufs[i];
   2932 		ubp->ub_port_handle = port->ulp_handle;
   2933 		ubp->ub_token = (uint64_t)((unsigned long)ubp);
   2934 		ubp->ub_bufsize = size;
   2935 		ubp->ub_class = FC_TRAN_CLASS3;
   2936 		ubp->ub_port_private = NULL;
   2937 		ubp->ub_fca_private =
   2938 		    (emlxs_ub_priv_t *)kmem_zalloc(sizeof (emlxs_ub_priv_t),
   2939 		    KM_SLEEP);
   2940 
   2941 		/*
   2942 		 * Initialize emlxs_ub_priv_t
   2943 		 */
   2944 		ub_priv = ubp->ub_fca_private;
   2945 		ub_priv->ubp = ubp;
   2946 		ub_priv->port = port;
   2947 		ub_priv->flags = EMLXS_UB_FREE;
   2948 		ub_priv->available = 1;
   2949 		ub_priv->pool = new_pool;
   2950 		ub_priv->time = 0;
   2951 		ub_priv->timeout = 0;
   2952 		ub_priv->token = port->ub_count;
   2953 		ub_priv->cmd = 0;
   2954 
   2955 		/* Allocate the actual buffer */
   2956 		ubp->ub_buffer = (caddr_t)kmem_zalloc(size, KM_SLEEP);
   2957 
   2958 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
   2959 		    "ub_alloc: buffer=%p token=%x size=%x type=%x ", ubp,
   2960 		    ub_priv->token, ubp->ub_bufsize, type);
   2961 
   2962 		tokens[i] = (uint64_t)((unsigned long)ubp);
   2963 		port->ub_count++;
   2964 	}
   2965 
   2966 	mutex_enter(&EMLXS_UB_LOCK);
   2967 
   2968 	/* Add the pool to the top of the pool list */
   2969 	new_pool->pool_prev = NULL;
   2970 	new_pool->pool_next = port->ub_pool;
   2971 
   2972 	if (port->ub_pool) {
   2973 		port->ub_pool->pool_prev = new_pool;
   2974 	}
   2975 	port->ub_pool = new_pool;
   2976 
   2977 	/* Set the post counts */
   2978 	if (type == FC_TYPE_IS8802_SNAP) {
   2979 		MAILBOXQ	*mbox;
   2980 
   2981 		port->ub_post[hba->channel_ip] += new_pool->pool_nentries;
   2982 
   2983 		if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
   2984 		    MEM_MBOX, 1))) {
   2985 			emlxs_mb_config_farp(hba, mbox);
   2986 			rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba,
   2987 			    mbox, MBX_NOWAIT, 0);
   2988 			if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
   2989 				(void) emlxs_mem_put(hba, MEM_MBOX,
   2990 				    (uint8_t *)mbox);
   2991 			}
   2992 		}
   2993 		port->flag |= EMLXS_PORT_IP_UP;
   2994 	} else if (type == FC_TYPE_EXTENDED_LS) {
   2995 		port->ub_post[hba->channel_els] += new_pool->pool_nentries;
   2996 	} else if (type == FC_TYPE_FC_SERVICES) {
   2997 		port->ub_post[hba->channel_ct] += new_pool->pool_nentries;
   2998 	}
   2999 
   3000 	mutex_exit(&EMLXS_UB_LOCK);
   3001 
   3002 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   3003 	    "%d unsolicited buffers allocated for %s of size 0x%x bytes.",
   3004 	    *count, err, size);
   3005 
   3006 	return (FC_SUCCESS);
   3007 
   3008 fail:
   3009 
   3010 	/* Clean the pool */
   3011 	for (i = 0; tokens[i] != NULL; i++) {
   3012 		/* Get the buffer object */
   3013 		ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]);
   3014 		ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
   3015 
   3016 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
   3017 		    "ub_alloc failed: Freed buffer=%p token=%x size=%x "
   3018 		    "type=%x ", ubp, ub_priv->token, ubp->ub_bufsize, type);
   3019 
   3020 		/* Free the actual buffer */
   3021 		kmem_free(ubp->ub_buffer, ubp->ub_bufsize);
   3022 
   3023 		/* Free the private area of the buffer object */
   3024 		kmem_free(ubp->ub_fca_private, sizeof (emlxs_ub_priv_t));
   3025 
   3026 		tokens[i] = 0;
   3027 		port->ub_count--;
   3028 	}
   3029 
   3030 	/* Free the array of buffer objects in the pool */
   3031 	kmem_free((caddr_t)new_pool->fc_ubufs,
   3032 	    (sizeof (fc_unsol_buf_t) * new_pool->pool_nentries));
   3033 
   3034 	/* Free the pool object */
   3035 	kmem_free((caddr_t)new_pool, sizeof (emlxs_unsol_buf_t));
   3036 
   3037 	mutex_exit(&EMLXS_UB_LOCK);
   3038 
   3039 	return (result);
   3040 
   3041 } /* emlxs_ub_alloc() */
   3042 
   3043 
   3044 static void
   3045 emlxs_ub_els_reject(emlxs_port_t *port, fc_unsol_buf_t *ubp)
   3046 {
   3047 	emlxs_hba_t	*hba = HBA;
   3048 	emlxs_ub_priv_t	*ub_priv;
   3049 	fc_packet_t	*pkt;
   3050 	ELS_PKT		*els;
   3051 	uint32_t	sid;
   3052 
   3053 	ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
   3054 
   3055 	if (hba->state <= FC_LINK_DOWN) {
   3056 		return;
   3057 	}
   3058 
   3059 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) +
   3060 	    sizeof (LS_RJT), 0, 0, KM_NOSLEEP))) {
   3061 		return;
   3062 	}
   3063 
   3064 	sid = LE_SWAP24_LO(ubp->ub_frame.s_id);
   3065 
   3066 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
   3067 	    "%s dropped: sid=%x. Rejecting.",
   3068 	    emlxs_elscmd_xlate(ub_priv->cmd), sid);
   3069 
   3070 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
   3071 	pkt->pkt_timeout = (2 * hba->fc_ratov);
   3072 
   3073 	if ((uint32_t)ubp->ub_class == FC_TRAN_CLASS2) {
   3074 		pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
   3075 		pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
   3076 	}
   3077 
   3078 	/* Build the fc header */
   3079 	pkt->pkt_cmd_fhdr.d_id = ubp->ub_frame.s_id;
   3080 	pkt->pkt_cmd_fhdr.r_ctl =
   3081 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
   3082 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
   3083 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
   3084 	pkt->pkt_cmd_fhdr.f_ctl =
   3085 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
   3086 	pkt->pkt_cmd_fhdr.seq_id = 0;
   3087 	pkt->pkt_cmd_fhdr.df_ctl = 0;
   3088 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
   3089 	pkt->pkt_cmd_fhdr.ox_id = (ub_priv->cmd >> ELS_CMD_SHIFT) & 0xff;
   3090 	pkt->pkt_cmd_fhdr.rx_id = ubp->ub_frame.rx_id;
   3091 	pkt->pkt_cmd_fhdr.ro = 0;
   3092 
   3093 	/* Build the command */
   3094 	els = (ELS_PKT *) pkt->pkt_cmd;
   3095 	els->elsCode = 0x01;
   3096 	els->un.lsRjt.un.b.lsRjtRsvd0 = 0;
   3097 	els->un.lsRjt.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
   3098 	els->un.lsRjt.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
   3099 	els->un.lsRjt.un.b.vendorUnique = 0x02;
   3100 
   3101 	/* Send the pkt later in another thread */
   3102 	(void) emlxs_pkt_send(pkt, 0);
   3103 
   3104 	return;
   3105 
   3106 } /* emlxs_ub_els_reject() */
   3107 
   3108 extern int
   3109 emlxs_ub_release(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[])
   3110 {
   3111 	emlxs_port_t		*port = (emlxs_port_t *)fca_port_handle;
   3112 	emlxs_hba_t		*hba = HBA;
   3113 	fc_unsol_buf_t		*ubp;
   3114 	emlxs_ub_priv_t		*ub_priv;
   3115 	uint32_t		i;
   3116 	uint32_t		time;
   3117 	emlxs_unsol_buf_t	*pool;
   3118 
   3119 	if (count == 0) {
   3120 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3121 		    "ub_release: Nothing to do. count=%d", count);
   3122 
   3123 		return (FC_SUCCESS);
   3124 	}
   3125 
   3126 	if (!(port->flag & EMLXS_PORT_BOUND)) {
   3127 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3128 		    "ub_release failed: Port not bound. count=%d token[0]=%p",
   3129 		    count, tokens[0]);
   3130 
   3131 		return (FC_UNBOUND);
   3132 	}
   3133 
   3134 	mutex_enter(&EMLXS_UB_LOCK);
   3135 
   3136 	if (!port->ub_pool) {
   3137 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3138 		    "ub_release failed: No pools! count=%d token[0]=%p",
   3139 		    count, tokens[0]);
   3140 
   3141 		mutex_exit(&EMLXS_UB_LOCK);
   3142 		return (FC_UB_BADTOKEN);
   3143 	}
   3144 
   3145 	for (i = 0; i < count; i++) {
   3146 		ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]);
   3147 
   3148 		if (!ubp) {
   3149 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3150 			    "ub_release failed: count=%d tokens[%d]=0", count,
   3151 			    i);
   3152 
   3153 			mutex_exit(&EMLXS_UB_LOCK);
   3154 			return (FC_UB_BADTOKEN);
   3155 		}
   3156 
   3157 		ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
   3158 
   3159 		if (!ub_priv || (ub_priv == (emlxs_ub_priv_t *)DEAD_PTR)) {
   3160 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3161 			    "ub_release failed: Dead buffer found. ubp=%p",
   3162 			    ubp);
   3163 
   3164 			mutex_exit(&EMLXS_UB_LOCK);
   3165 			return (FC_UB_BADTOKEN);
   3166 		}
   3167 
   3168 		if (ub_priv->flags == EMLXS_UB_FREE) {
   3169 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3170 			    "ub_release: Buffer already free! ubp=%p token=%x",
   3171 			    ubp, ub_priv->token);
   3172 
   3173 			continue;
   3174 		}
   3175 
   3176 		/* Check for dropped els buffer */
   3177 		/* ULP will do this sometimes without sending a reply */
   3178 		if ((ubp->ub_frame.r_ctl == FC_ELS_REQ) &&
   3179 		    !(ub_priv->flags & EMLXS_UB_REPLY)) {
   3180 			emlxs_ub_els_reject(port, ubp);
   3181 		}
   3182 
   3183 		/* Mark the buffer free */
   3184 		ub_priv->flags = EMLXS_UB_FREE;
   3185 		bzero(ubp->ub_buffer, ubp->ub_bufsize);
   3186 
   3187 		time = hba->timer_tics - ub_priv->time;
   3188 		ub_priv->time = 0;
   3189 		ub_priv->timeout = 0;
   3190 
   3191 		pool = ub_priv->pool;
   3192 
   3193 		if (ub_priv->flags & EMLXS_UB_RESV) {
   3194 			pool->pool_free_resv++;
   3195 		} else {
   3196 			pool->pool_free++;
   3197 		}
   3198 
   3199 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
   3200 		    "ub_release: ubp=%p token=%x time=%d av=%d (%d,%d,%d,%d)",
   3201 		    ubp, ub_priv->token, time, ub_priv->available,
   3202 		    pool->pool_nentries, pool->pool_available,
   3203 		    pool->pool_free, pool->pool_free_resv);
   3204 
   3205 		/* Check if pool can be destroyed now */
   3206 		if ((pool->pool_available == 0) &&
   3207 		    (pool->pool_free + pool->pool_free_resv ==
   3208 		    pool->pool_nentries)) {
   3209 			emlxs_ub_destroy(port, pool);
   3210 		}
   3211 	}
   3212 
   3213 	mutex_exit(&EMLXS_UB_LOCK);
   3214 
   3215 	return (FC_SUCCESS);
   3216 
   3217 } /* emlxs_ub_release() */
   3218 
   3219 
   3220 static int
   3221 emlxs_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[])
   3222 {
   3223 	emlxs_port_t		*port = (emlxs_port_t *)fca_port_handle;
   3224 	emlxs_unsol_buf_t	*pool;
   3225 	fc_unsol_buf_t		*ubp;
   3226 	emlxs_ub_priv_t		*ub_priv;
   3227 	uint32_t		i;
   3228 
   3229 	if (port->tgt_mode) {
   3230 		return (FC_SUCCESS);
   3231 	}
   3232 
   3233 	if (count == 0) {
   3234 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3235 		    "ub_free: Nothing to do. count=%d token[0]=%p", count,
   3236 		    tokens[0]);
   3237 
   3238 		return (FC_SUCCESS);
   3239 	}
   3240 
   3241 	if (!(port->flag & EMLXS_PORT_BOUND)) {
   3242 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3243 		    "ub_free: Port not bound. count=%d token[0]=%p", count,
   3244 		    tokens[0]);
   3245 
   3246 		return (FC_SUCCESS);
   3247 	}
   3248 
   3249 	mutex_enter(&EMLXS_UB_LOCK);
   3250 
   3251 	if (!port->ub_pool) {
   3252 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3253 		    "ub_free failed: No pools! count=%d token[0]=%p", count,
   3254 		    tokens[0]);
   3255 
   3256 		mutex_exit(&EMLXS_UB_LOCK);
   3257 		return (FC_UB_BADTOKEN);
   3258 	}
   3259 
   3260 	/* Process buffer list */
   3261 	for (i = 0; i < count; i++) {
   3262 		ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]);
   3263 
   3264 		if (!ubp) {
   3265 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3266 			    "ub_free failed: count=%d tokens[%d]=0", count,
   3267 			    i);
   3268 
   3269 			mutex_exit(&EMLXS_UB_LOCK);
   3270 			return (FC_UB_BADTOKEN);
   3271 		}
   3272 
   3273 		/* Mark buffer unavailable */
   3274 		ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
   3275 
   3276 		if (!ub_priv || (ub_priv == (emlxs_ub_priv_t *)DEAD_PTR)) {
   3277 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3278 			    "ub_free failed: Dead buffer found. ubp=%p", ubp);
   3279 
   3280 			mutex_exit(&EMLXS_UB_LOCK);
   3281 			return (FC_UB_BADTOKEN);
   3282 		}
   3283 
   3284 		ub_priv->available = 0;
   3285 
   3286 		/* Mark one less buffer available in the parent pool */
   3287 		pool = ub_priv->pool;
   3288 
   3289 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
   3290 		    "ub_free: ubp=%p token=%x (%d,%d,%d,%d)", ubp,
   3291 		    ub_priv->token, pool->pool_nentries,
   3292 		    pool->pool_available - 1, pool->pool_free,
   3293 		    pool->pool_free_resv);
   3294 
   3295 		if (pool->pool_available) {
   3296 			pool->pool_available--;
   3297 
   3298 			/* Check if pool can be destroyed */
   3299 			if ((pool->pool_available == 0) &&
   3300 			    (pool->pool_free + pool->pool_free_resv ==
   3301 			    pool->pool_nentries)) {
   3302 				emlxs_ub_destroy(port, pool);
   3303 			}
   3304 		}
   3305 	}
   3306 
   3307 	mutex_exit(&EMLXS_UB_LOCK);
   3308 
   3309 	return (FC_SUCCESS);
   3310 
   3311 } /* emlxs_ub_free() */
   3312 
   3313 
   3314 /* EMLXS_UB_LOCK must be held when calling this routine */
   3315 extern void
   3316 emlxs_ub_destroy(emlxs_port_t *port, emlxs_unsol_buf_t *pool)
   3317 {
   3318 	emlxs_hba_t		*hba = HBA;
   3319 	emlxs_unsol_buf_t	*next;
   3320 	emlxs_unsol_buf_t	*prev;
   3321 	fc_unsol_buf_t		*ubp;
   3322 	uint32_t		i;
   3323 
   3324 	/* Remove the pool object from the pool list */
   3325 	next = pool->pool_next;
   3326 	prev = pool->pool_prev;
   3327 
   3328 	if (port->ub_pool == pool) {
   3329 		port->ub_pool = next;
   3330 	}
   3331 
   3332 	if (prev) {
   3333 		prev->pool_next = next;
   3334 	}
   3335 
   3336 	if (next) {
   3337 		next->pool_prev = prev;
   3338 	}
   3339 
   3340 	pool->pool_prev = NULL;
   3341 	pool->pool_next = NULL;
   3342 
   3343 	/* Clear the post counts */
   3344 	switch (pool->pool_type) {
   3345 	case FC_TYPE_IS8802_SNAP:
   3346 		port->ub_post[hba->channel_ip] -= pool->pool_nentries;
   3347 		break;
   3348 
   3349 	case FC_TYPE_EXTENDED_LS:
   3350 		port->ub_post[hba->channel_els] -= pool->pool_nentries;
   3351 		break;
   3352 
   3353 	case FC_TYPE_FC_SERVICES:
   3354 		port->ub_post[hba->channel_ct] -= pool->pool_nentries;
   3355 		break;
   3356 	}
   3357 
   3358 	/* Now free the pool memory */
   3359 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3360 	    "ub_destroy: pool=%p type=%d size=%d count=%d", pool,
   3361 	    pool->pool_type, pool->pool_buf_size, pool->pool_nentries);
   3362 
   3363 	/* Process the array of buffer objects in the pool */
   3364 	for (i = 0; i < pool->pool_nentries; i++) {
   3365 		/* Get the buffer object */
   3366 		ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[i];
   3367 
   3368 		/* Free the memory the buffer object represents */
   3369 		kmem_free(ubp->ub_buffer, ubp->ub_bufsize);
   3370 
   3371 		/* Free the private area of the buffer object */
   3372 		kmem_free(ubp->ub_fca_private, sizeof (emlxs_ub_priv_t));
   3373 	}
   3374 
   3375 	/* Free the array of buffer objects in the pool */
   3376 	kmem_free((caddr_t)pool->fc_ubufs,
   3377 	    (sizeof (fc_unsol_buf_t)*pool->pool_nentries));
   3378 
   3379 	/* Free the pool object */
   3380 	kmem_free((caddr_t)pool, sizeof (emlxs_unsol_buf_t));
   3381 
   3382 	return;
   3383 
   3384 } /* emlxs_ub_destroy() */
   3385 
   3386 
   3387 /*ARGSUSED*/
   3388 extern int
   3389 emlxs_pkt_abort(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep)
   3390 {
   3391 	emlxs_port_t	*port = (emlxs_port_t *)fca_port_handle;
   3392 	emlxs_hba_t	*hba = HBA;
   3393 	emlxs_config_t	*cfg = &CFG;
   3394 
   3395 	emlxs_buf_t	*sbp;
   3396 	NODELIST	*nlp;
   3397 	NODELIST	*prev_nlp;
   3398 	uint8_t		channelno;
   3399 	CHANNEL	*cp;
   3400 	clock_t		timeout;
   3401 	clock_t		time;
   3402 	int32_t		pkt_ret;
   3403 	IOCBQ		*iocbq;
   3404 	IOCBQ		*next;
   3405 	IOCBQ		*prev;
   3406 	uint32_t	found;
   3407 	uint32_t	att_bit;
   3408 	uint32_t	pass = 0;
   3409 
   3410 	sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
   3411 	iocbq = &sbp->iocbq;
   3412 	nlp = (NODELIST *)sbp->node;
   3413 	cp = (CHANNEL *)sbp->channel;
   3414 	channelno = (cp) ? cp->channelno : 0;
   3415 
   3416 	if (!(port->flag & EMLXS_PORT_BOUND)) {
   3417 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
   3418 		    "Port not bound.");
   3419 		return (FC_UNBOUND);
   3420 	}
   3421 
   3422 	if (!(hba->flag & FC_ONLINE_MODE)) {
   3423 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
   3424 		    "Adapter offline.");
   3425 		return (FC_OFFLINE);
   3426 	}
   3427 
   3428 	/* ULP requires the aborted pkt to be completed */
   3429 	/* back to ULP before returning from this call. */
   3430 	/* SUN knows of problems with this call so they suggested that we */
   3431 	/* always return a FC_FAILURE for this call, until it is worked out. */
   3432 
   3433 	/* Check if pkt is no good */
   3434 	if (!(sbp->pkt_flags & PACKET_VALID) ||
   3435 	    (sbp->pkt_flags & PACKET_ULP_OWNED)) {
   3436 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
   3437 		    "Bad sbp. flags=%x", sbp->pkt_flags);
   3438 		return (FC_FAILURE);
   3439 	}
   3440 
   3441 	/* Tag this now */
   3442 	/* This will prevent any thread except ours from completing it */
   3443 	mutex_enter(&sbp->mtx);
   3444 
   3445 	/* Check again if we still own this */
   3446 	if (!(sbp->pkt_flags & PACKET_VALID) ||
   3447 	    (sbp->pkt_flags & PACKET_ULP_OWNED)) {
   3448 		mutex_exit(&sbp->mtx);
   3449 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
   3450 		    "Bad sbp. flags=%x", sbp->pkt_flags);
   3451 		return (FC_FAILURE);
   3452 	}
   3453 
   3454 	/* Check if pkt is a real polled command */
   3455 	if (!(sbp->pkt_flags & PACKET_IN_ABORT) &&
   3456 	    (sbp->pkt_flags & PACKET_POLLED)) {
   3457 		mutex_exit(&sbp->mtx);
   3458 
   3459 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
   3460 		    "Attempting to abort a polled I/O. sbp=%p flags=%x", sbp,
   3461 		    sbp->pkt_flags);
   3462 		return (FC_FAILURE);
   3463 	}
   3464 
   3465 	sbp->pkt_flags |= PACKET_POLLED;
   3466 	sbp->pkt_flags |= PACKET_IN_ABORT;
   3467 
   3468 	if (sbp->pkt_flags & (PACKET_IN_COMPLETION | PACKET_IN_FLUSH |
   3469 	    PACKET_IN_TIMEOUT)) {
   3470 		mutex_exit(&sbp->mtx);
   3471 
   3472 		/* Do nothing, pkt already on its way out */
   3473 		goto done;
   3474 	}
   3475 
   3476 	mutex_exit(&sbp->mtx);
   3477 
   3478 begin:
   3479 	pass++;
   3480 
   3481 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
   3482 
   3483 	if (sbp->pkt_flags & PACKET_IN_TXQ) {
   3484 		/* Find it on the queue */
   3485 		found = 0;
   3486 		if (iocbq->flag & IOCB_PRIORITY) {
   3487 			/* Search the priority queue */
   3488 			prev = NULL;
   3489 			next = (IOCBQ *) nlp->nlp_ptx[channelno].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_ptx[channelno].q_last ==
   3499 					    (void *)iocbq) {
   3500 						nlp->nlp_ptx[channelno].q_last =
   3501 						    (void *)prev;
   3502 					}
   3503 
   3504 					if (nlp->nlp_ptx[channelno].q_first ==
   3505 					    (void *)iocbq) {
   3506 						nlp->nlp_ptx[channelno].
   3507 						    q_first =
   3508 						    (void *)iocbq->next;
   3509 					}
   3510 
   3511 					nlp->nlp_ptx[channelno].q_cnt--;
   3512 					iocbq->next = NULL;
   3513 					found = 1;
   3514 					break;
   3515 				}
   3516 
   3517 				prev = next;
   3518 				next = next->next;
   3519 			}
   3520 		} else {
   3521 			/* Search the normal queue */
   3522 			prev = NULL;
   3523 			next = (IOCBQ *) nlp->nlp_tx[channelno].q_first;
   3524 
   3525 			while (next) {
   3526 				if (next == iocbq) {
   3527 					/* Remove it */
   3528 					if (prev) {
   3529 						prev->next = iocbq->next;
   3530 					}
   3531 
   3532 					if (nlp->nlp_tx[channelno].q_last ==
   3533 					    (void *)iocbq) {
   3534 						nlp->nlp_tx[channelno].q_last =
   3535 						    (void *)prev;
   3536 					}
   3537 
   3538 					if (nlp->nlp_tx[channelno].q_first ==
   3539 					    (void *)iocbq) {
   3540 						nlp->nlp_tx[channelno].q_first =
   3541 						    (void *)iocbq->next;
   3542 					}
   3543 
   3544 					nlp->nlp_tx[channelno].q_cnt--;
   3545 					iocbq->next = NULL;
   3546 					found = 1;
   3547 					break;
   3548 				}
   3549 
   3550 				prev = next;
   3551 				next = (IOCBQ *) next->next;
   3552 			}
   3553 		}
   3554 
   3555 		if (!found) {
   3556 			mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
   3557 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
   3558 			    "I/O not found in driver. sbp=%p flags=%x", sbp,
   3559 			    sbp->pkt_flags);
   3560 			goto done;
   3561 		}
   3562 
   3563 		/* Check if node still needs servicing */
   3564 		if ((nlp->nlp_ptx[channelno].q_first) ||
   3565 		    (nlp->nlp_tx[channelno].q_first &&
   3566 		    !(nlp->nlp_flag[channelno] & NLP_CLOSED))) {
   3567 
   3568 			/*
   3569 			 * If this is the base node,
   3570 			 * then don't shift the pointers
   3571 			 */
   3572 			/* We want to drain the base node before moving on */
   3573 			if (!nlp->nlp_base) {
   3574 				/* Just shift channel queue */
   3575 				/* pointers to next node */
   3576 				cp->nodeq.q_last = (void *) nlp;
   3577 				cp->nodeq.q_first = nlp->nlp_next[channelno];
   3578 			}
   3579 		} else {
   3580 			/* Remove node from channel queue */
   3581 
   3582 			/* If this is the only node on list */
   3583 			if (cp->nodeq.q_first == (void *)nlp &&
   3584 			    cp->nodeq.q_last == (void *)nlp) {
   3585 				cp->nodeq.q_last = NULL;
   3586 				cp->nodeq.q_first = NULL;
   3587 				cp->nodeq.q_cnt = 0;
   3588 			} else if (cp->nodeq.q_first == (void *)nlp) {
   3589 				cp->nodeq.q_first = nlp->nlp_next[channelno];
   3590 				((NODELIST *) cp->nodeq.q_last)->
   3591 				    nlp_next[channelno] = cp->nodeq.q_first;
   3592 				cp->nodeq.q_cnt--;
   3593 			} else {
   3594 				/*
   3595 				 * This is a little more difficult find the
   3596 				 * previous node in the circular channel queue
   3597 				 */
   3598 				prev_nlp = nlp;
   3599 				while (prev_nlp->nlp_next[channelno] != nlp) {
   3600 					prev_nlp = prev_nlp->
   3601 					    nlp_next[channelno];
   3602 				}
   3603 
   3604 				prev_nlp->nlp_next[channelno] =
   3605 				    nlp->nlp_next[channelno];
   3606 
   3607 				if (cp->nodeq.q_last == (void *)nlp) {
   3608 					cp->nodeq.q_last = (void *)prev_nlp;
   3609 				}
   3610 				cp->nodeq.q_cnt--;
   3611 
   3612 			}
   3613 
   3614 			/* Clear node */
   3615 			nlp->nlp_next[channelno] = NULL;
   3616 		}
   3617 
   3618 		/* Free the ULPIOTAG and the bmp */
   3619 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
   3620 			hba->fc_table[sbp->iotag] = NULL;
   3621 			emlxs_sli4_free_xri(hba, sbp, sbp->xp);
   3622 		} else {
   3623 			(void) emlxs_unregister_pkt(cp, sbp->iotag, 1);
   3624 		}
   3625 
   3626 
   3627 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
   3628 
   3629 		emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
   3630 		    IOERR_ABORT_REQUESTED, 1);
   3631 
   3632 		goto done;
   3633 	}
   3634 
   3635 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
   3636 
   3637 
   3638 	/* Check the chip queue */
   3639 	mutex_enter(&EMLXS_FCTAB_LOCK);
   3640 
   3641 	if ((sbp->pkt_flags & PACKET_IN_CHIPQ) &&
   3642 	    !(sbp->pkt_flags & PACKET_XRI_CLOSED) &&
   3643 	    (sbp == hba->fc_table[sbp->iotag])) {
   3644 
   3645 		/* Create the abort IOCB */
   3646 		if (hba->state >= FC_LINK_UP) {
   3647 			iocbq =
   3648 			    emlxs_create_abort_xri_cn(port, sbp->node,
   3649 			    sbp->iotag, cp, sbp->class, ABORT_TYPE_ABTS);
   3650 
   3651 			mutex_enter(&sbp->mtx);
   3652 			sbp->pkt_flags |= PACKET_XRI_CLOSED;
   3653 			sbp->ticks =
   3654 			    hba->timer_tics + (4 * hba->fc_ratov) + 10;
   3655 			sbp->abort_attempts++;
   3656 			mutex_exit(&sbp->mtx);
   3657 		} else {
   3658 			iocbq =
   3659 			    emlxs_create_close_xri_cn(port, sbp->node,
   3660 			    sbp->iotag, cp);
   3661 
   3662 			mutex_enter(&sbp->mtx);
   3663 			sbp->pkt_flags |= PACKET_XRI_CLOSED;
   3664 			sbp->ticks = hba->timer_tics + 30;
   3665 			sbp->abort_attempts++;
   3666 			mutex_exit(&sbp->mtx);
   3667 		}
   3668 
   3669 		mutex_exit(&EMLXS_FCTAB_LOCK);
   3670 
   3671 		/* Send this iocbq */
   3672 		if (iocbq) {
   3673 			EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
   3674 			iocbq = NULL;
   3675 		}
   3676 
   3677 		goto done;
   3678 	}
   3679 
   3680 	mutex_exit(&EMLXS_FCTAB_LOCK);
   3681 
   3682 	/* Pkt was not on any queues */
   3683 
   3684 	/* Check again if we still own this */
   3685 	if (!(sbp->pkt_flags & PACKET_VALID) ||
   3686 	    (sbp->pkt_flags &
   3687 	    (PACKET_ULP_OWNED | PACKET_IN_COMPLETION |
   3688 	    PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
   3689 		goto done;
   3690 	}
   3691 
   3692 	if (!sleep) {
   3693 		return (FC_FAILURE);
   3694 	}
   3695 
   3696 	/* Apparently the pkt was not found.  Let's delay and try again */
   3697 	if (pass < 5) {
   3698 		delay(drv_usectohz(5000000));	/* 5 seconds */
   3699 
   3700 		/* Check again if we still own this */
   3701 		if (!(sbp->pkt_flags & PACKET_VALID) ||
   3702 		    (sbp->pkt_flags &
   3703 		    (PACKET_ULP_OWNED | PACKET_IN_COMPLETION |
   3704 		    PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
   3705 			goto done;
   3706 		}
   3707 
   3708 		goto begin;
   3709 	}
   3710 
   3711 force_it:
   3712 
   3713 	/* Force the completion now */
   3714 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3715 	    "Abort: Completing an IO thats not outstanding: %x", sbp->iotag);
   3716 
   3717 	/* Now complete it */
   3718 	emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, IOERR_ABORT_REQUESTED,
   3719 	    1);
   3720 
   3721 done:
   3722 
   3723 	/* Now wait for the pkt to complete */
   3724 	if (!(sbp->pkt_flags & PACKET_COMPLETED)) {
   3725 		/* Set thread timeout */
   3726 		timeout = emlxs_timeout(hba, 30);
   3727 
   3728 		/* Check for panic situation */
   3729 		if (ddi_in_panic()) {
   3730 
   3731 			/*
   3732 			 * In panic situations there will be one thread with no
   3733 			 * interrrupts (hard or soft) and no timers
   3734 			 */
   3735 
   3736 			/*
   3737 			 * We must manually poll everything in this thread
   3738 			 * to keep the driver going.
   3739 			 */
   3740 
   3741 			cp = (CHANNEL *)sbp->channel;
   3742 			switch (cp->channelno) {
   3743 			case FC_FCP_RING:
   3744 				att_bit = HA_R0ATT;
   3745 				break;
   3746 
   3747 			case FC_IP_RING:
   3748 				att_bit = HA_R1ATT;
   3749 				break;
   3750 
   3751 			case FC_ELS_RING:
   3752 				att_bit = HA_R2ATT;
   3753 				break;
   3754 
   3755 			case FC_CT_RING:
   3756 				att_bit = HA_R3ATT;
   3757 				break;
   3758 			}
   3759 
   3760 			/* Keep polling the chip until our IO is completed */
   3761 			(void) drv_getparm(LBOLT, &time);
   3762 			while ((time < timeout) &&
   3763 			    !(sbp->pkt_flags & PACKET_COMPLETED)) {
   3764 				EMLXS_SLI_POLL_INTR(hba, att_bit);
   3765 				(void) drv_getparm(LBOLT, &time);
   3766 			}
   3767 		} else {
   3768 			/* Wait for IO completion or timeout */
   3769 			mutex_enter(&EMLXS_PKT_LOCK);
   3770 			pkt_ret = 0;
   3771 			while ((pkt_ret != -1) &&
   3772 			    !(sbp->pkt_flags & PACKET_COMPLETED)) {
   3773 				pkt_ret =
   3774 				    cv_timedwait(&EMLXS_PKT_CV,
   3775 				    &EMLXS_PKT_LOCK, timeout);
   3776 			}
   3777 			mutex_exit(&EMLXS_PKT_LOCK);
   3778 		}
   3779 
   3780 		/* Check if timeout occured. This is not good. */
   3781 		/* Something happened to our IO. */
   3782 		if (!(sbp->pkt_flags & PACKET_COMPLETED)) {
   3783 			/* Force the completion now */
   3784 			goto force_it;
   3785 		}
   3786 	}
   3787 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
   3788 	emlxs_unswap_pkt(sbp);
   3789 #endif	/* EMLXS_MODREV2X */
   3790 
   3791 	/* Check again if we still own this */
   3792 	if ((sbp->pkt_flags & PACKET_VALID) &&
   3793 	    !(sbp->pkt_flags & PACKET_ULP_OWNED)) {
   3794 		mutex_enter(&sbp->mtx);
   3795 		if ((sbp->pkt_flags & PACKET_VALID) &&
   3796 		    !(sbp->pkt_flags & PACKET_ULP_OWNED)) {
   3797 			sbp->pkt_flags |= PACKET_ULP_OWNED;
   3798 		}
   3799 		mutex_exit(&sbp->mtx);
   3800 	}
   3801 
   3802 #ifdef ULP_PATCH5
   3803 	if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH5) {
   3804 		return (FC_FAILURE);
   3805 	}
   3806 #endif /* ULP_PATCH5 */
   3807 
   3808 	return (FC_SUCCESS);
   3809 
   3810 } /* emlxs_pkt_abort() */
   3811 
   3812 
   3813 static void
   3814 emlxs_abort_all(emlxs_hba_t *hba, uint32_t *tx, uint32_t *chip)
   3815 {
   3816 	emlxs_port_t   *port = &PPORT;
   3817 	fc_packet_t *pkt;
   3818 	emlxs_buf_t *sbp;
   3819 	uint32_t i;
   3820 	uint32_t flg;
   3821 	uint32_t rc;
   3822 	uint32_t txcnt;
   3823 	uint32_t chipcnt;
   3824 
   3825 	txcnt = 0;
   3826 	chipcnt = 0;
   3827 
   3828 	mutex_enter(&EMLXS_FCTAB_LOCK);
   3829 	for (i = 0; i < hba->max_iotag; i++) {
   3830 		sbp = hba->fc_table[i];
   3831 		if (sbp == NULL || sbp == STALE_PACKET) {
   3832 			continue;
   3833 		}
   3834 		flg =  (sbp->pkt_flags & PACKET_IN_CHIPQ);
   3835 		pkt = PRIV2PKT(sbp);
   3836 		mutex_exit(&EMLXS_FCTAB_LOCK);
   3837 		rc = emlxs_pkt_abort(port, pkt, 0);
   3838 		if (rc == FC_SUCCESS) {
   3839 			if (flg) {
   3840 				chipcnt++;
   3841 			} else {
   3842 				txcnt++;
   3843 			}
   3844 		}
   3845 		mutex_enter(&EMLXS_FCTAB_LOCK);
   3846 	}
   3847 	mutex_exit(&EMLXS_FCTAB_LOCK);
   3848 	*tx = txcnt;
   3849 	*chip = chipcnt;
   3850 } /* emlxs_abort_all() */
   3851 
   3852 
   3853 extern int32_t
   3854 emlxs_reset(opaque_t fca_port_handle, uint32_t cmd)
   3855 {
   3856 	emlxs_port_t	*port = (emlxs_port_t *)fca_port_handle;
   3857 	emlxs_hba_t	*hba = HBA;
   3858 	int		rval;
   3859 	int		ret;
   3860 	clock_t		timeout;
   3861 
   3862 	if (!(port->flag & EMLXS_PORT_BOUND)) {
   3863 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3864 		    "fca_reset failed. Port not bound.");
   3865 
   3866 		return (FC_UNBOUND);
   3867 	}
   3868 
   3869 	switch (cmd) {
   3870 	case FC_FCA_LINK_RESET:
   3871 
   3872 		if (!(hba->flag & FC_ONLINE_MODE) ||
   3873 		    (hba->state <= FC_LINK_DOWN)) {
   3874 			return (FC_SUCCESS);
   3875 		}
   3876 
   3877 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3878 		    "fca_reset: Resetting Link.");
   3879 
   3880 		mutex_enter(&EMLXS_LINKUP_LOCK);
   3881 		hba->linkup_wait_flag = TRUE;
   3882 		mutex_exit(&EMLXS_LINKUP_LOCK);
   3883 
   3884 		if (emlxs_reset_link(hba, 1, 1)) {
   3885 			mutex_enter(&EMLXS_LINKUP_LOCK);
   3886 			hba->linkup_wait_flag = FALSE;
   3887 			mutex_exit(&EMLXS_LINKUP_LOCK);
   3888 
   3889 			return (FC_FAILURE);
   3890 		}
   3891 
   3892 		mutex_enter(&EMLXS_LINKUP_LOCK);
   3893 		timeout = emlxs_timeout(hba, 60);
   3894 		ret = 0;
   3895 		while ((ret != -1) && (hba->linkup_wait_flag == TRUE)) {
   3896 			ret =
   3897 			    cv_timedwait(&EMLXS_LINKUP_CV, &EMLXS_LINKUP_LOCK,
   3898 			    timeout);
   3899 		}
   3900 
   3901 		hba->linkup_wait_flag = FALSE;
   3902 		mutex_exit(&EMLXS_LINKUP_LOCK);
   3903 
   3904 		if (ret == -1) {
   3905 			return (FC_FAILURE);
   3906 		}
   3907 
   3908 		return (FC_SUCCESS);
   3909 
   3910 	case FC_FCA_CORE:
   3911 #ifdef DUMP_SUPPORT
   3912 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3913 		    "fca_reset: Core dump.");
   3914 
   3915 		/* Schedule a USER dump */
   3916 		emlxs_dump(hba, EMLXS_USER_DUMP, 0, 0);
   3917 
   3918 		/* Wait for dump to complete */
   3919 		emlxs_dump_wait(hba);
   3920 
   3921 		return (FC_SUCCESS);
   3922 #endif /* DUMP_SUPPORT */
   3923 
   3924 	case FC_FCA_RESET:
   3925 	case FC_FCA_RESET_CORE:
   3926 
   3927 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3928 		    "fca_reset: Resetting Adapter.");
   3929 
   3930 		rval = FC_SUCCESS;
   3931 
   3932 		if (emlxs_offline(hba) == 0) {
   3933 			(void) emlxs_online(hba);
   3934 		} else {
   3935 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3936 			    "fca_reset: Adapter reset failed. Device busy.");
   3937 
   3938 			rval = FC_DEVICE_BUSY;
   3939 		}
   3940 
   3941 		return (rval);
   3942 
   3943 	default:
   3944 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3945 		    "fca_reset: Unknown command. cmd=%x", cmd);
   3946 
   3947 		break;
   3948 	}
   3949 
   3950 	return (FC_FAILURE);
   3951 
   3952 } /* emlxs_reset() */
   3953 
   3954 
   3955 extern int
   3956 emlxs_port_manage(opaque_t fca_port_handle, fc_fca_pm_t *pm)
   3957 {
   3958 	emlxs_port_t	*port = (emlxs_port_t *)fca_port_handle;
   3959 	emlxs_hba_t	*hba = HBA;
   3960 	int32_t		ret;
   3961 	emlxs_vpd_t	*vpd = &VPD;
   3962 
   3963 
   3964 	ret = FC_SUCCESS;
   3965 
   3966 	if (!(port->flag & EMLXS_PORT_BOUND)) {
   3967 		return (FC_UNBOUND);
   3968 	}
   3969 
   3970 
   3971 #ifdef IDLE_TIMER
   3972 	emlxs_pm_busy_component(hba);
   3973 #endif	/* IDLE_TIMER */
   3974 
   3975 	switch (pm->pm_cmd_code) {
   3976 
   3977 	case FC_PORT_GET_FW_REV:
   3978 	{
   3979 		char buffer[128];
   3980 
   3981 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   3982 		    "fca_port_manage: FC_PORT_GET_FW_REV");
   3983 
   3984 		(void) sprintf(buffer, "%s %s", hba->model_info.model,
   3985 		    vpd->fw_version);
   3986 		bzero(pm->pm_data_buf, pm->pm_data_len);
   3987 
   3988 		if (pm->pm_data_len < strlen(buffer) + 1) {
   3989 			ret = FC_NOMEM;
   3990 
   3991 			break;
   3992 		}
   3993 
   3994 		(void) strcpy(pm->pm_data_buf, buffer);
   3995 		break;
   3996 	}
   3997 
   3998 	case FC_PORT_GET_FCODE_REV:
   3999 	{
   4000 		char buffer[128];
   4001 
   4002 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4003 		    "fca_port_manage: FC_PORT_GET_FCODE_REV");
   4004 
   4005 		/* Force update here just to be sure */
   4006 		emlxs_get_fcode_version(hba);
   4007 
   4008 		(void) sprintf(buffer, "%s %s", hba->model_info.model,
   4009 		    vpd->fcode_version);
   4010 		bzero(pm->pm_data_buf, pm->pm_data_len);
   4011 
   4012 		if (pm->pm_data_len < strlen(buffer) + 1) {
   4013 			ret = FC_NOMEM;
   4014 			break;
   4015 		}
   4016 
   4017 		(void) strcpy(pm->pm_data_buf, buffer);
   4018 		break;
   4019 	}
   4020 
   4021 	case FC_PORT_GET_DUMP_SIZE:
   4022 	{
   4023 #ifdef DUMP_SUPPORT
   4024 		uint32_t dump_size = 0;
   4025 
   4026 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4027 		    "fca_port_manage: FC_PORT_GET_DUMP_SIZE");
   4028 
   4029 		if (pm->pm_data_len < sizeof (uint32_t)) {
   4030 			ret = FC_NOMEM;
   4031 			break;
   4032 		}
   4033 
   4034 		(void) emlxs_get_dump(hba, NULL, &dump_size);
   4035 
   4036 		*((uint32_t *)pm->pm_data_buf) = dump_size;
   4037 
   4038 #else
   4039 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4040 		    "fca_port_manage: FC_PORT_GET_DUMP_SIZE unsupported.");
   4041 
   4042 #endif /* DUMP_SUPPORT */
   4043 
   4044 		break;
   4045 	}
   4046 
   4047 	case FC_PORT_GET_DUMP:
   4048 	{
   4049 #ifdef DUMP_SUPPORT
   4050 		uint32_t dump_size = 0;
   4051 
   4052 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4053 		    "fca_port_manage: FC_PORT_GET_DUMP");
   4054 
   4055 		(void) emlxs_get_dump(hba, NULL, &dump_size);
   4056 
   4057 		if (pm->pm_data_len < dump_size) {
   4058 			ret = FC_NOMEM;
   4059 			break;
   4060 		}
   4061 
   4062 		(void) emlxs_get_dump(hba, (uint8_t *)pm->pm_data_buf,
   4063 		    (uint32_t *)&dump_size);
   4064 #else
   4065 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4066 		    "fca_port_manage: FC_PORT_GET_DUMP unsupported.");
   4067 
   4068 #endif /* DUMP_SUPPORT */
   4069 
   4070 		break;
   4071 	}
   4072 
   4073 	case FC_PORT_FORCE_DUMP:
   4074 	{
   4075 #ifdef DUMP_SUPPORT
   4076 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4077 		    "fca_port_manage: FC_PORT_FORCE_DUMP");
   4078 
   4079 		/* Schedule a USER dump */
   4080 		emlxs_dump(hba, EMLXS_USER_DUMP, 0, 0);
   4081 
   4082 		/* Wait for dump to complete */
   4083 		emlxs_dump_wait(hba);
   4084 #else
   4085 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4086 		    "fca_port_manage: FC_PORT_FORCE_DUMP unsupported.");
   4087 
   4088 #endif /* DUMP_SUPPORT */
   4089 		break;
   4090 	}
   4091 
   4092 	case FC_PORT_LINK_STATE:
   4093 	{
   4094 		uint32_t	*link_state;
   4095 
   4096 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4097 		    "fca_port_manage: FC_PORT_LINK_STATE");
   4098 
   4099 		if (pm->pm_stat_len != sizeof (*link_state)) {
   4100 			ret = FC_NOMEM;
   4101 			break;
   4102 		}
   4103 
   4104 		if (pm->pm_cmd_buf != NULL) {
   4105 			/*
   4106 			 * Can't look beyond the FCA port.
   4107 			 */
   4108 			ret = FC_INVALID_REQUEST;
   4109 			break;
   4110 		}
   4111 
   4112 		link_state = (uint32_t *)pm->pm_stat_buf;
   4113 
   4114 		/* Set the state */
   4115 		if (hba->state >= FC_LINK_UP) {
   4116 			/* Check for loop topology */
   4117 			if (hba->topology == TOPOLOGY_LOOP) {
   4118 				*link_state = FC_STATE_LOOP;
   4119 			} else {
   4120 				*link_state = FC_STATE_ONLINE;
   4121 			}
   4122 
   4123 			/* Set the link speed */
   4124 			switch (hba->linkspeed) {
   4125 			case LA_2GHZ_LINK:
   4126 				*link_state |= FC_STATE_2GBIT_SPEED;
   4127 				break;
   4128 			case LA_4GHZ_LINK:
   4129 				*link_state |= FC_STATE_4GBIT_SPEED;
   4130 				break;
   4131 			case LA_8GHZ_LINK:
   4132 				*link_state |= FC_STATE_8GBIT_SPEED;
   4133 				break;
   4134 			case LA_10GHZ_LINK:
   4135 				*link_state |= FC_STATE_10GBIT_SPEED;
   4136 				break;
   4137 			case LA_1GHZ_LINK:
   4138 			default:
   4139 				*link_state |= FC_STATE_1GBIT_SPEED;
   4140 				break;
   4141 			}
   4142 		} else {
   4143 			*link_state = FC_STATE_OFFLINE;
   4144 		}
   4145 
   4146 		break;
   4147 	}
   4148 
   4149 
   4150 	case FC_PORT_ERR_STATS:
   4151 	case FC_PORT_RLS:
   4152 	{
   4153 		MAILBOXQ	*mbq;
   4154 		MAILBOX		*mb;
   4155 		fc_rls_acc_t	*bp;
   4156 
   4157 		if (!(hba->flag & FC_ONLINE_MODE)) {
   4158 			return (FC_OFFLINE);
   4159 		}
   4160 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4161 		    "fca_port_manage: FC_PORT_RLS / FC_PORT_ERR_STATS");
   4162 
   4163 		if (pm->pm_data_len < sizeof (fc_rls_acc_t)) {
   4164 			ret = FC_NOMEM;
   4165 			break;
   4166 		}
   4167 
   4168 		if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba,
   4169 		    MEM_MBOX, 1)) == 0) {
   4170 			ret = FC_NOMEM;
   4171 			break;
   4172 		}
   4173 		mb = (MAILBOX *)mbq;
   4174 
   4175 		emlxs_mb_read_lnk_stat(hba, mbq);
   4176 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0)
   4177 		    != MBX_SUCCESS) {
   4178 			ret = FC_PBUSY;
   4179 		} else {
   4180 			bp = (fc_rls_acc_t *)pm->pm_data_buf;
   4181 
   4182 			bp->rls_link_fail = mb->un.varRdLnk.linkFailureCnt;
   4183 			bp->rls_sync_loss = mb->un.varRdLnk.lossSyncCnt;
   4184 			bp->rls_sig_loss = mb->un.varRdLnk.lossSignalCnt;
   4185 			bp->rls_prim_seq_err = mb->un.varRdLnk.primSeqErrCnt;
   4186 			bp->rls_invalid_word =
   4187 			    mb->un.varRdLnk.invalidXmitWord;
   4188 			bp->rls_invalid_crc = mb->un.varRdLnk.crcCnt;
   4189 		}
   4190 
   4191 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
   4192 		break;
   4193 	}
   4194 
   4195 	case FC_PORT_DOWNLOAD_FW:
   4196 		if (!(hba->flag & FC_ONLINE_MODE)) {
   4197 			return (FC_OFFLINE);
   4198 		}
   4199 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4200 		    "fca_port_manage: FC_PORT_DOWNLOAD_FW");
   4201 		ret = emlxs_fw_download(hba, pm->pm_data_buf,
   4202 		    pm->pm_data_len, 1);
   4203 		break;
   4204 
   4205 	case FC_PORT_DOWNLOAD_FCODE:
   4206 		if (!(hba->flag & FC_ONLINE_MODE)) {
   4207 			return (FC_OFFLINE);
   4208 		}
   4209 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4210 		    "fca_port_manage: FC_PORT_DOWNLOAD_FCODE");
   4211 		ret = emlxs_fw_download(hba, pm->pm_data_buf,
   4212 		    pm->pm_data_len, 1);
   4213 		break;
   4214 
   4215 	case FC_PORT_DIAG:
   4216 	{
   4217 		uint32_t errno = 0;
   4218 		uint32_t did = 0;
   4219 		uint32_t pattern = 0;
   4220 
   4221 		switch (pm->pm_cmd_flags) {
   4222 		case EMLXS_DIAG_BIU:
   4223 
   4224 			if (!(hba->flag & FC_ONLINE_MODE)) {
   4225 				return (FC_OFFLINE);
   4226 			}
   4227 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4228 			    "fca_port_manage: EMLXS_DIAG_BIU");
   4229 
   4230 			if (pm->pm_data_len) {
   4231 				pattern = *((uint32_t *)pm->pm_data_buf);
   4232 			}
   4233 
   4234 			errno = emlxs_diag_biu_run(hba, pattern);
   4235 
   4236 			if (pm->pm_stat_len == sizeof (errno)) {
   4237 				*(int *)pm->pm_stat_buf = errno;
   4238 			}
   4239 
   4240 			break;
   4241 
   4242 
   4243 		case EMLXS_DIAG_POST:
   4244 
   4245 			if (!(hba->flag & FC_ONLINE_MODE)) {
   4246 				return (FC_OFFLINE);
   4247 			}
   4248 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4249 			    "fca_port_manage: EMLXS_DIAG_POST");
   4250 
   4251 			errno = emlxs_diag_post_run(hba);
   4252 
   4253 			if (pm->pm_stat_len == sizeof (errno)) {
   4254 				*(int *)pm->pm_stat_buf = errno;
   4255 			}
   4256 
   4257 			break;
   4258 
   4259 
   4260 		case EMLXS_DIAG_ECHO:
   4261 
   4262 			if (!(hba->flag & FC_ONLINE_MODE)) {
   4263 				return (FC_OFFLINE);
   4264 			}
   4265 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4266 			    "fca_port_manage: EMLXS_DIAG_ECHO");
   4267 
   4268 			if (pm->pm_cmd_len != sizeof (uint32_t)) {
   4269 				ret = FC_INVALID_REQUEST;
   4270 				break;
   4271 			}
   4272 
   4273 			did = *((uint32_t *)pm->pm_cmd_buf);
   4274 
   4275 			if (pm->pm_data_len) {
   4276 				pattern = *((uint32_t *)pm->pm_data_buf);
   4277 			}
   4278 
   4279 			errno = emlxs_diag_echo_run(port, did, pattern);
   4280 
   4281 			if (pm->pm_stat_len == sizeof (errno)) {
   4282 				*(int *)pm->pm_stat_buf = errno;
   4283 			}
   4284 
   4285 			break;
   4286 
   4287 
   4288 		case EMLXS_PARM_GET_NUM:
   4289 		{
   4290 			uint32_t	*num;
   4291 			emlxs_config_t	*cfg;
   4292 			uint32_t	i;
   4293 			uint32_t	count;
   4294 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4295 			    "fca_port_manage: EMLXS_PARM_GET_NUM");
   4296 
   4297 			if (pm->pm_stat_len < sizeof (uint32_t)) {
   4298 				ret = FC_NOMEM;
   4299 				break;
   4300 			}
   4301 
   4302 			num = (uint32_t *)pm->pm_stat_buf;
   4303 			count = 0;
   4304 			cfg = &CFG;
   4305 			for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) {
   4306 				if (!(cfg->flags & PARM_HIDDEN)) {
   4307 					count++;
   4308 				}
   4309 
   4310 			}
   4311 
   4312 			*num = count;
   4313 
   4314 			break;
   4315 		}
   4316 
   4317 		case EMLXS_PARM_GET_LIST:
   4318 		{
   4319 			emlxs_parm_t	*parm;
   4320 			emlxs_config_t	*cfg;
   4321 			uint32_t	i;
   4322 			uint32_t	max_count;
   4323 
   4324 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4325 			    "fca_port_manage: EMLXS_PARM_GET_LIST");
   4326 
   4327 			if (pm->pm_stat_len < sizeof (emlxs_parm_t)) {
   4328 				ret = FC_NOMEM;
   4329 				break;
   4330 			}
   4331 
   4332 			max_count = pm->pm_stat_len / sizeof (emlxs_parm_t);
   4333 
   4334 			parm = (emlxs_parm_t *)pm->pm_stat_buf;
   4335 			cfg = &CFG;
   4336 			for (i = 0; i < NUM_CFG_PARAM && max_count; i++,
   4337 			    cfg++) {
   4338 				if (!(cfg->flags & PARM_HIDDEN)) {
   4339 					(void) strcpy(parm->label, cfg->string);
   4340 					parm->min = cfg->low;
   4341 					parm->max = cfg->hi;
   4342 					parm->def = cfg->def;
   4343 					parm->current = cfg->current;
   4344 					parm->flags = cfg->flags;
   4345 					(void) strcpy(parm->help, cfg->help);
   4346 					parm++;
   4347 					max_count--;
   4348 				}
   4349 			}
   4350 
   4351 			break;
   4352 		}
   4353 
   4354 		case EMLXS_PARM_GET:
   4355 		{
   4356 			emlxs_parm_t	*parm_in;
   4357 			emlxs_parm_t	*parm_out;
   4358 			emlxs_config_t	*cfg;
   4359 			uint32_t	i;
   4360 			uint32_t	len;
   4361 
   4362 			if (pm->pm_cmd_len < sizeof (emlxs_parm_t)) {
   4363 				EMLXS_MSGF(EMLXS_CONTEXT,
   4364 				    &emlxs_sfs_debug_msg,
   4365 				    "fca_port_manage: EMLXS_PARM_GET. "
   4366 				    "inbuf too small.");
   4367 
   4368 				ret = FC_BADCMD;
   4369 				break;
   4370 			}
   4371 
   4372 			if (pm->pm_stat_len < sizeof (emlxs_parm_t)) {
   4373 				EMLXS_MSGF(EMLXS_CONTEXT,
   4374 				    &emlxs_sfs_debug_msg,
   4375 				    "fca_port_manage: EMLXS_PARM_GET. "
   4376 				    "outbuf too small");
   4377 
   4378 				ret = FC_BADCMD;
   4379 				break;
   4380 			}
   4381 
   4382 			parm_in = (emlxs_parm_t *)pm->pm_cmd_buf;
   4383 			parm_out = (emlxs_parm_t *)pm->pm_stat_buf;
   4384 			len = strlen(parm_in->label);
   4385 			cfg = &CFG;
   4386 			ret = FC_BADOBJECT;
   4387 
   4388 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4389 			    "fca_port_manage: EMLXS_PARM_GET: %s",
   4390 			    parm_in->label);
   4391 
   4392 			for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) {
   4393 				if (len == strlen(cfg->string) &&
   4394 				    (strcmp(parm_in->label,
   4395 				    cfg->string) == 0)) {
   4396 					(void) strcpy(parm_out->label,
   4397 					    cfg->string);
   4398 					parm_out->min = cfg->low;
   4399 					parm_out->max = cfg->hi;
   4400 					parm_out->def = cfg->def;
   4401 					parm_out->current = cfg->current;
   4402 					parm_out->flags = cfg->flags;
   4403 					(void) strcpy(parm_out->help,
   4404 					    cfg->help);
   4405 
   4406 					ret = FC_SUCCESS;
   4407 					break;
   4408 				}
   4409 			}
   4410 
   4411 			break;
   4412 		}
   4413 
   4414 		case EMLXS_PARM_SET:
   4415 		{
   4416 			emlxs_parm_t	*parm_in;
   4417 			emlxs_parm_t	*parm_out;
   4418 			emlxs_config_t	*cfg;
   4419 			uint32_t	i;
   4420 			uint32_t	len;
   4421 
   4422 			if (pm->pm_cmd_len < sizeof (emlxs_parm_t)) {
   4423 				EMLXS_MSGF(EMLXS_CONTEXT,
   4424 				    &emlxs_sfs_debug_msg,
   4425 				    "fca_port_manage: EMLXS_PARM_GET. "
   4426 				    "inbuf too small.");
   4427 
   4428 				ret = FC_BADCMD;
   4429 				break;
   4430 			}
   4431 
   4432 			if (pm->pm_stat_len < sizeof (emlxs_parm_t)) {
   4433 				EMLXS_MSGF(EMLXS_CONTEXT,
   4434 				    &emlxs_sfs_debug_msg,
   4435 				    "fca_port_manage: EMLXS_PARM_GET. "
   4436 				    "outbuf too small");
   4437 				ret = FC_BADCMD;
   4438 				break;
   4439 			}
   4440 
   4441 			parm_in = (emlxs_parm_t *)pm->pm_cmd_buf;
   4442 			parm_out = (emlxs_parm_t *)pm->pm_stat_buf;
   4443 			len = strlen(parm_in->label);
   4444 			cfg = &CFG;
   4445 			ret = FC_BADOBJECT;
   4446 
   4447 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4448 			    "fca_port_manage: EMLXS_PARM_SET: %s=0x%x,%d",
   4449 			    parm_in->label, parm_in->current,
   4450 			    parm_in->current);
   4451 
   4452 			for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) {
   4453 				/* Find matching parameter string */
   4454 				if (len == strlen(cfg->string) &&
   4455 				    (strcmp(parm_in->label,
   4456 				    cfg->string) == 0)) {
   4457 					/* Attempt to update parameter */
   4458 					if (emlxs_set_parm(hba, i,
   4459 					    parm_in->current) == FC_SUCCESS) {
   4460 						(void) strcpy(parm_out->label,
   4461 						    cfg->string);
   4462 						parm_out->min = cfg->low;
   4463 						parm_out->max = cfg->hi;
   4464 						parm_out->def = cfg->def;
   4465 						parm_out->current =
   4466 						    cfg->current;
   4467 						parm_out->flags = cfg->flags;
   4468 						(void) strcpy(parm_out->help,
   4469 						    cfg->help);
   4470 
   4471 						ret = FC_SUCCESS;
   4472 					}
   4473 
   4474 					break;
   4475 				}
   4476 			}
   4477 
   4478 			break;
   4479 		}
   4480 
   4481 		case EMLXS_LOG_GET:
   4482 		{
   4483 			emlxs_log_req_t		*req;
   4484 			emlxs_log_resp_t	*resp;
   4485 			uint32_t		len;
   4486 
   4487 			/* Check command size */
   4488 			if (pm->pm_cmd_len < sizeof (emlxs_log_req_t)) {
   4489 				ret = FC_BADCMD;
   4490 				break;
   4491 			}
   4492 
   4493 			/* Get the request */
   4494 			req = (emlxs_log_req_t *)pm->pm_cmd_buf;
   4495 
   4496 			/* Calculate the response length from the request */
   4497 			len = sizeof (emlxs_log_resp_t) +
   4498 			    (req->count * MAX_LOG_MSG_LENGTH);
   4499 
   4500 					/* Check the response buffer length */
   4501 			if (pm->pm_stat_len < len) {
   4502 				ret = FC_BADCMD;
   4503 				break;
   4504 			}
   4505 
   4506 			/* Get the response pointer */
   4507 			resp = (emlxs_log_resp_t *)pm->pm_stat_buf;
   4508 
   4509 			/* Get the request log enties */
   4510 			(void) emlxs_msg_log_get(hba, req, resp);
   4511 
   4512 			ret = FC_SUCCESS;
   4513 			break;
   4514 		}
   4515 
   4516 		case EMLXS_GET_BOOT_REV:
   4517 		{
   4518 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4519 			    "fca_port_manage: EMLXS_GET_BOOT_REV");
   4520 
   4521 			if (pm->pm_stat_len < strlen(vpd->boot_version)) {
   4522 				ret = FC_NOMEM;
   4523 				break;
   4524 			}
   4525 
   4526 			bzero(pm->pm_stat_buf, pm->pm_stat_len);
   4527 			(void) sprintf(pm->pm_stat_buf, "%s %s",
   4528 			    hba->model_info.model, vpd->boot_version);
   4529 
   4530 			break;
   4531 		}
   4532 
   4533 		case EMLXS_DOWNLOAD_BOOT:
   4534 			if (!(hba->flag & FC_ONLINE_MODE)) {
   4535 				return (FC_OFFLINE);
   4536 			}
   4537 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4538 			    "fca_port_manage: EMLXS_DOWNLOAD_BOOT");
   4539 
   4540 			ret = emlxs_fw_download(hba, pm->pm_data_buf,
   4541 			    pm->pm_data_len, 1);
   4542 			break;
   4543 
   4544 		case EMLXS_DOWNLOAD_CFL:
   4545 		{
   4546 			uint32_t *buffer;
   4547 			uint32_t region;
   4548 			uint32_t length;
   4549 
   4550 			if (!(hba->flag & FC_ONLINE_MODE)) {
   4551 				return (FC_OFFLINE);
   4552 			}
   4553 
   4554 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4555 			    "fca_port_manage: EMLXS_DOWNLOAD_CFL");
   4556 
   4557 			/* Extract the region number from the first word. */
   4558 			buffer = (uint32_t *)pm->pm_data_buf;
   4559 			region = *buffer++;
   4560 
   4561 			/* Adjust the image length for the header word */
   4562 			length = pm->pm_data_len - 4;
   4563 
   4564 			ret =
   4565 			    emlxs_cfl_download(hba, region, (caddr_t)buffer,
   4566 			    length);
   4567 			break;
   4568 		}
   4569 
   4570 		case EMLXS_VPD_GET:
   4571 		{
   4572 			emlxs_vpd_desc_t	*vpd_out;
   4573 
   4574 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4575 			    "fca_port_manage: EMLXS_VPD_GET");
   4576 
   4577 			if (pm->pm_stat_len < sizeof (emlxs_vpd_desc_t)) {
   4578 				ret = FC_BADCMD;
   4579 				break;
   4580 			}
   4581 
   4582 			vpd_out = (emlxs_vpd_desc_t *)pm->pm_stat_buf;
   4583 			bzero(vpd_out, sizeof (emlxs_vpd_desc_t));
   4584 
   4585 			(void) strncpy(vpd_out->id, vpd->id,
   4586 			    sizeof (vpd_out->id));
   4587 			(void) strncpy(vpd_out->part_num, vpd->part_num,
   4588 			    sizeof (vpd_out->part_num));
   4589 			(void) strncpy(vpd_out->eng_change, vpd->eng_change,
   4590 			    sizeof (vpd_out->eng_change));
   4591 			(void) strncpy(vpd_out->manufacturer, vpd->manufacturer,
   4592 			    sizeof (vpd_out->manufacturer));
   4593 			(void) strncpy(vpd_out->serial_num, vpd->serial_num,
   4594 			    sizeof (vpd_out->serial_num));
   4595 			(void) strncpy(vpd_out->model, vpd->model,
   4596 			    sizeof (vpd_out->model));
   4597 			(void) strncpy(vpd_out->model_desc, vpd->model_desc,
   4598 			    sizeof (vpd_out->model_desc));
   4599 			(void) strncpy(vpd_out->port_num, vpd->port_num,
   4600 			    sizeof (vpd_out->port_num));
   4601 			(void) strncpy(vpd_out->prog_types, vpd->prog_types,
   4602 			    sizeof (vpd_out->prog_types));
   4603 
   4604 			ret = FC_SUCCESS;
   4605 
   4606 			break;
   4607 		}
   4608 
   4609 		case EMLXS_GET_FCIO_REV:
   4610 		{
   4611 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4612 			    "fca_port_manage: EMLXS_GET_FCIO_REV");
   4613 
   4614 			if (pm->pm_stat_len < sizeof (uint32_t)) {
   4615 				ret = FC_NOMEM;
   4616 				break;
   4617 			}
   4618 
   4619 			bzero(pm->pm_stat_buf, pm->pm_stat_len);
   4620 			*(uint32_t *)pm->pm_stat_buf = FCIO_REV;
   4621 
   4622 			break;
   4623 		}
   4624 
   4625 		case EMLXS_GET_DFC_REV:
   4626 		{
   4627 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4628 			    "fca_port_manage: EMLXS_GET_DFC_REV");
   4629 
   4630 			if (pm->pm_stat_len < sizeof (uint32_t)) {
   4631 				ret = FC_NOMEM;
   4632 				break;
   4633 			}
   4634 
   4635 			bzero(pm->pm_stat_buf, pm->pm_stat_len);
   4636 			*(uint32_t *)pm->pm_stat_buf = DFC_REV;
   4637 
   4638 			break;
   4639 		}
   4640 
   4641 		case EMLXS_SET_BOOT_STATE:
   4642 		case EMLXS_SET_BOOT_STATE_old:
   4643 		{
   4644 			uint32_t	state;
   4645 
   4646 			if (!(hba->flag & FC_ONLINE_MODE)) {
   4647 				return (FC_OFFLINE);
   4648 			}
   4649 			if (pm->pm_cmd_len < sizeof (uint32_t)) {
   4650 				EMLXS_MSGF(EMLXS_CONTEXT,
   4651 				    &emlxs_sfs_debug_msg,
   4652 				    "fca_port_manage: EMLXS_SET_BOOT_STATE");
   4653 				ret = FC_BADCMD;
   4654 				break;
   4655 			}
   4656 
   4657 			state = *(uint32_t *)pm->pm_cmd_buf;
   4658 
   4659 			if (state == 0) {
   4660 				EMLXS_MSGF(EMLXS_CONTEXT,
   4661 				    &emlxs_sfs_debug_msg,
   4662 				    "fca_port_manage: EMLXS_SET_BOOT_STATE: "
   4663 				    "Disable");
   4664 				ret = emlxs_boot_code_disable(hba);
   4665 			} else {
   4666 				EMLXS_MSGF(EMLXS_CONTEXT,
   4667 				    &emlxs_sfs_debug_msg,
   4668 				    "fca_port_manage: EMLXS_SET_BOOT_STATE: "
   4669 				    "Enable");
   4670 				ret = emlxs_boot_code_enable(hba);
   4671 			}
   4672 
   4673 			break;
   4674 		}
   4675 
   4676 		case EMLXS_GET_BOOT_STATE:
   4677 		case EMLXS_GET_BOOT_STATE_old:
   4678 		{
   4679 			if (!(hba->flag & FC_ONLINE_MODE)) {
   4680 				return (FC_OFFLINE);
   4681 			}
   4682 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4683 			    "fca_port_manage: EMLXS_GET_BOOT_STATE");
   4684 
   4685 			if (pm->pm_stat_len < sizeof (uint32_t)) {
   4686 				ret = FC_NOMEM;
   4687 				break;
   4688 			}
   4689 			bzero(pm->pm_stat_buf, pm->pm_stat_len);
   4690 
   4691 			ret = emlxs_boot_code_state(hba);
   4692 
   4693 			if (ret == FC_SUCCESS) {
   4694 				*(uint32_t *)pm->pm_stat_buf = 1;
   4695 				ret = FC_SUCCESS;
   4696 			} else if (ret == FC_FAILURE) {
   4697 				ret = FC_SUCCESS;
   4698 			}
   4699 
   4700 			break;
   4701 		}
   4702 
   4703 		case EMLXS_HW_ERROR_TEST:
   4704 		{
   4705 			if (!(hba->flag & FC_ONLINE_MODE)) {
   4706 				return (FC_OFFLINE);
   4707 			}
   4708 
   4709 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4710 			    "fca_port_manage: EMLXS_HW_ERROR_TEST");
   4711 
   4712 			/* Trigger a mailbox timeout */
   4713 			hba->mbox_timer = hba->timer_tics;
   4714 
   4715 			break;
   4716 		}
   4717 
   4718 		case EMLXS_TEST_CODE:
   4719 		{
   4720 			uint32_t *cmd;
   4721 
   4722 			if (!(hba->flag & FC_ONLINE_MODE)) {
   4723 				return (FC_OFFLINE);
   4724 			}
   4725 
   4726 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4727 			    "fca_port_manage: EMLXS_TEST_CODE");
   4728 
   4729 			if (pm->pm_cmd_len < sizeof (uint32_t)) {
   4730 				EMLXS_MSGF(EMLXS_CONTEXT,
   4731 				    &emlxs_sfs_debug_msg,
   4732 				    "fca_port_manage: EMLXS_TEST_CODE. "
   4733 				    "inbuf to small.");
   4734 
   4735 				ret = FC_BADCMD;
   4736 				break;
   4737 			}
   4738 
   4739 			cmd = (uint32_t *)pm->pm_cmd_buf;
   4740 
   4741 			ret = emlxs_test(hba, cmd[0],
   4742 			    (pm->pm_cmd_len/sizeof (uint32_t)) - 1, &cmd[1]);
   4743 
   4744 			break;
   4745 		}
   4746 
   4747 		case EMLXS_BAR_IO:
   4748 		{
   4749 			uint32_t *cmd;
   4750 			uint32_t *datap;
   4751 			uint32_t offset;
   4752 			caddr_t  addr;
   4753 			uint32_t i;
   4754 			uint32_t tx_cnt;
   4755 			uint32_t chip_cnt;
   4756 
   4757 			cmd = (uint32_t *)pm->pm_cmd_buf;
   4758 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4759 			    "fca_port_manage: EMLXS_BAR_IO %x %x %x",
   4760 			    cmd[0], cmd[1], cmd[2]);
   4761 
   4762 			offset = cmd[1];
   4763 
   4764 			ret = FC_SUCCESS;
   4765 
   4766 			switch (cmd[0]) {
   4767 			case 2: /* bar1read */
   4768 				if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
   4769 					return (FC_BADCMD);
   4770 				}
   4771 
   4772 				/* Registers in this range are invalid */
   4773 				if ((offset >= 0x4C00) && (offset < 0x5000)) {
   4774 					return (FC_BADCMD);
   4775 				}
   4776 				if ((offset >= 0x5800) || (offset & 0x3)) {
   4777 					return (FC_BADCMD);
   4778 				}
   4779 				datap = (uint32_t *)pm->pm_stat_buf;
   4780 
   4781 				for (i = 0; i < pm->pm_stat_len;
   4782 				    i += sizeof (uint32_t)) {
   4783 					if ((offset >= 0x4C00) &&
   4784 					    (offset < 0x5000)) {
   4785 						pm->pm_stat_len = i;
   4786 						break;
   4787 					}
   4788 					if (offset >= 0x5800) {
   4789 						pm->pm_stat_len = i;
   4790 						break;
   4791 					}
   4792 					addr = hba->sli.sli4.bar1_addr + offset;
   4793 					*datap = READ_BAR1_REG(hba, addr);
   4794 					datap++;
   4795 					offset += sizeof (uint32_t);
   4796 				}
   4797 #ifdef FMA_SUPPORT
   4798 				/* Access handle validation */
   4799 				EMLXS_CHK_ACC_HANDLE(hba,
   4800 				    hba->sli.sli4.bar1_acc_handle);
   4801 #endif  /* FMA_SUPPORT */
   4802 				break;
   4803 			case 3: /* bar2read */
   4804 				if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
   4805 					return (FC_BADCMD);
   4806 				}
   4807 				if ((offset >= 0x1000) || (offset & 0x3)) {
   4808 					return (FC_BADCMD);
   4809 				}
   4810 				datap = (uint32_t *)pm->pm_stat_buf;
   4811 
   4812 				for (i = 0; i < pm->pm_stat_len;
   4813 				    i += sizeof (uint32_t)) {
   4814 					*datap = READ_BAR2_REG(hba,
   4815 					    hba->sli.sli4.bar2_addr + offset);
   4816 					datap++;
   4817 					offset += sizeof (uint32_t);
   4818 				}
   4819 #ifdef FMA_SUPPORT
   4820 				/* Access handle validation */
   4821 				EMLXS_CHK_ACC_HANDLE(hba,
   4822 				    hba->sli.sli4.bar2_acc_handle);
   4823 #endif  /* FMA_SUPPORT */
   4824 				break;
   4825 			case 4: /* bar1write */
   4826 				if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
   4827 					return (FC_BADCMD);
   4828 				}
   4829 				WRITE_BAR1_REG(hba, hba->sli.sli4.bar1_addr +
   4830 				    offset, cmd[2]);
   4831 #ifdef FMA_SUPPORT
   4832 				/* Access handle validation */
   4833 				EMLXS_CHK_ACC_HANDLE(hba,
   4834 				    hba->sli.sli4.bar1_acc_handle);
   4835 #endif  /* FMA_SUPPORT */
   4836 				break;
   4837 			case 5: /* bar2write */
   4838 				if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
   4839 					return (FC_BADCMD);
   4840 				}
   4841 				WRITE_BAR2_REG(hba, hba->sli.sli4.bar2_addr +
   4842 				    offset, cmd[2]);
   4843 #ifdef FMA_SUPPORT
   4844 				/* Access handle validation */
   4845 				EMLXS_CHK_ACC_HANDLE(hba,
   4846 				    hba->sli.sli4.bar2_acc_handle);
   4847 #endif  /* FMA_SUPPORT */
   4848 				break;
   4849 			case 6: /* dumpbsmbox */
   4850 				if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
   4851 					return (FC_BADCMD);
   4852 				}
   4853 				if (offset != 0) {
   4854 					return (FC_BADCMD);
   4855 				}
   4856 
   4857 				bcopy((caddr_t)hba->sli.sli4.bootstrapmb.virt,
   4858 				    (caddr_t)pm->pm_stat_buf, 256);
   4859 				break;
   4860 			case 7: /* pciread */
   4861 				if ((offset >= 0x200) || (offset & 0x3)) {
   4862 					return (FC_BADCMD);
   4863 				}
   4864 				datap = (uint32_t *)pm->pm_stat_buf;
   4865 				for (i = 0; i < pm->pm_stat_len;
   4866 				    i += sizeof (uint32_t)) {
   4867 					*datap = ddi_get32(hba->pci_acc_handle,
   4868 					    (uint32_t *)(hba->pci_addr +
   4869 					    offset));
   4870 					datap++;
   4871 					offset += sizeof (uint32_t);
   4872 				}
   4873 #ifdef FMA_SUPPORT
   4874 				/* Access handle validation */
   4875 				EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
   4876 #endif  /* FMA_SUPPORT */
   4877 				break;
   4878 			case 8: /* abortall */
   4879 				if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
   4880 					return (FC_BADCMD);
   4881 				}
   4882 				emlxs_abort_all(hba, &tx_cnt, &chip_cnt);
   4883 				datap = (uint32_t *)pm->pm_stat_buf;
   4884 				*datap++ = tx_cnt;
   4885 				*datap = chip_cnt;
   4886 				break;
   4887 			default:
   4888 				ret = FC_BADCMD;
   4889 				break;
   4890 			}
   4891 			break;
   4892 		}
   4893 
   4894 		default:
   4895 
   4896 			ret = FC_INVALID_REQUEST;
   4897 			break;
   4898 		}
   4899 
   4900 		break;
   4901 
   4902 	}
   4903 
   4904 	case FC_PORT_INITIALIZE:
   4905 		if (!(hba->flag & FC_ONLINE_MODE)) {
   4906 			return (FC_OFFLINE);
   4907 		}
   4908 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4909 		    "fca_port_manage: FC_PORT_INITIALIZE");
   4910 		break;
   4911 
   4912 	case FC_PORT_LOOPBACK:
   4913 		if (!(hba->flag & FC_ONLINE_MODE)) {
   4914 			return (FC_OFFLINE);
   4915 		}
   4916 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4917 		    "fca_port_manage: FC_PORT_LOOPBACK");
   4918 		break;
   4919 
   4920 	case FC_PORT_BYPASS:
   4921 		if (!(hba->flag & FC_ONLINE_MODE)) {
   4922 			return (FC_OFFLINE);
   4923 		}
   4924 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4925 		    "fca_port_manage: FC_PORT_BYPASS");
   4926 		ret = FC_INVALID_REQUEST;
   4927 		break;
   4928 
   4929 	case FC_PORT_UNBYPASS:
   4930 		if (!(hba->flag & FC_ONLINE_MODE)) {
   4931 			return (FC_OFFLINE);
   4932 		}
   4933 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4934 		    "fca_port_manage: FC_PORT_UNBYPASS");
   4935 		ret = FC_INVALID_REQUEST;
   4936 		break;
   4937 
   4938 	case FC_PORT_GET_NODE_ID:
   4939 	{
   4940 		fc_rnid_t *rnid;
   4941 
   4942 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4943 		    "fca_port_manage: FC_PORT_GET_NODE_ID");
   4944 
   4945 		bzero(pm->pm_data_buf, pm->pm_data_len);
   4946 
   4947 		if (pm->pm_data_len < sizeof (fc_rnid_t)) {
   4948 			ret = FC_NOMEM;
   4949 			break;
   4950 		}
   4951 
   4952 		rnid = (fc_rnid_t *)pm->pm_data_buf;
   4953 
   4954 		(void) sprintf((char *)rnid->global_id,
   4955 		    "%01x%01x%02x%02x%02x%02x%02x%02x%02x",
   4956 		    hba->wwpn.nameType, hba->wwpn.IEEEextMsn,
   4957 		    hba->wwpn.IEEEextLsb, hba->wwpn.IEEE[0],
   4958 		    hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], hba->wwpn.IEEE[3],
   4959 		    hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
   4960 
   4961 		rnid->unit_type  = RNID_HBA;
   4962 		rnid->port_id    = port->did;
   4963 		rnid->ip_version = RNID_IPV4;
   4964 
   4965 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4966 		    "GET_NODE_ID: wwpn:       %s", rnid->global_id);
   4967 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4968 		    "GET_NODE_ID: unit_type:  0x%x", rnid->unit_type);
   4969 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4970 		    "GET_NODE_ID: port_id:    0x%x", rnid->port_id);
   4971 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4972 		    "GET_NODE_ID: num_attach: %d", rnid->num_attached);
   4973 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4974 		    "GET_NODE_ID: ip_version: 0x%x", rnid->ip_version);
   4975 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4976 		    "GET_NODE_ID: udp_port:   0x%x", rnid->udp_port);
   4977 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4978 		    "GET_NODE_ID: ip_addr:    %s", rnid->ip_addr);
   4979 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4980 		    "GET_NODE_ID: resv:       0x%x", rnid->specific_id_resv);
   4981 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4982 		    "GET_NODE_ID: topo_flags: 0x%x", rnid->topo_flags);
   4983 
   4984 		ret = FC_SUCCESS;
   4985 		break;
   4986 	}
   4987 
   4988 	case FC_PORT_SET_NODE_ID:
   4989 	{
   4990 		fc_rnid_t *rnid;
   4991 
   4992 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   4993 		    "fca_port_manage: FC_PORT_SET_NODE_ID");
   4994 
   4995 		if (pm->pm_data_len < sizeof (fc_rnid_t)) {
   4996 			ret = FC_NOMEM;
   4997 			break;
   4998 		}
   4999 
   5000 		rnid = (fc_rnid_t *)pm->pm_data_buf;
   5001 
   5002 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5003 		    "SET_NODE_ID: wwpn:       %s", rnid->global_id);
   5004 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5005 		    "SET_NODE_ID: unit_type:  0x%x", rnid->unit_type);
   5006 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5007 		    "SET_NODE_ID: port_id:    0x%x", rnid->port_id);
   5008 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5009 		    "SET_NODE_ID: num_attach: %d", rnid->num_attached);
   5010 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5011 		    "SET_NODE_ID: ip_version: 0x%x", rnid->ip_version);
   5012 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5013 		    "SET_NODE_ID: udp_port:   0x%x", rnid->udp_port);
   5014 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5015 		    "SET_NODE_ID: ip_addr:    %s", rnid->ip_addr);
   5016 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5017 		    "SET_NODE_ID: resv:       0x%x", rnid->specific_id_resv);
   5018 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5019 		    "SET_NODE_ID: topo_flags: 0x%x", rnid->topo_flags);
   5020 
   5021 		ret = FC_SUCCESS;
   5022 		break;
   5023 	}
   5024 
   5025 #ifdef S11
   5026 	case FC_PORT_GET_P2P_INFO:
   5027 	{
   5028 		fc_fca_p2p_info_t	*p2p_info;
   5029 		NODELIST		*ndlp;
   5030 
   5031 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5032 		    "fca_port_manage: FC_PORT_GET_P2P_INFO");
   5033 
   5034 		bzero(pm->pm_data_buf, pm->pm_data_len);
   5035 
   5036 		if (pm->pm_data_len < sizeof (fc_fca_p2p_info_t)) {
   5037 			ret = FC_NOMEM;
   5038 			break;
   5039 		}
   5040 
   5041 		p2p_info = (fc_fca_p2p_info_t *)pm->pm_data_buf;
   5042 
   5043 		if (hba->state >= FC_LINK_UP) {
   5044 			if ((hba->topology == TOPOLOGY_PT_PT) &&
   5045 			    (hba->flag & FC_PT_TO_PT)) {
   5046 				p2p_info->fca_d_id = port->did;
   5047 				p2p_info->d_id = port->rdid;
   5048 
   5049 				ndlp = emlxs_node_find_did(port,
   5050 				    port->rdid);
   5051 
   5052 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5053 				    "FC_PORT_GET_P2P_INFO: fca_d_id: 0x%x, "
   5054 				    "d_id: 0x%x, ndlp: 0x%p", port->did,
   5055 				    port->rdid, ndlp);
   5056 				if (ndlp) {
   5057 					bcopy(&ndlp->nlp_portname,
   5058 					    (caddr_t)&p2p_info->pwwn,
   5059 					    sizeof (la_wwn_t));
   5060 					bcopy(&ndlp->nlp_nodename,
   5061 					    (caddr_t)&p2p_info->nwwn,
   5062 					    sizeof (la_wwn_t));
   5063 
   5064 					ret = FC_SUCCESS;
   5065 					break;
   5066 
   5067 				}
   5068 			}
   5069 		}
   5070 
   5071 		ret = FC_FAILURE;
   5072 		break;
   5073 	}
   5074 #endif
   5075 
   5076 	default:
   5077 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5078 		    "fca_port_manage: code=%x", pm->pm_cmd_code);
   5079 		ret = FC_INVALID_REQUEST;
   5080 		break;
   5081 
   5082 	}
   5083 
   5084 	return (ret);
   5085 
   5086 } /* emlxs_port_manage() */
   5087 
   5088 
   5089 /*ARGSUSED*/
   5090 static uint32_t
   5091 emlxs_test(emlxs_hba_t *hba, uint32_t test_code, uint32_t args,
   5092     uint32_t *arg)
   5093 {
   5094 	uint32_t rval = 0;
   5095 	emlxs_port_t   *port = &PPORT;
   5096 
   5097 	switch (test_code) {
   5098 #ifdef TEST_SUPPORT
   5099 	case 1: /* SCSI underrun */
   5100 	{
   5101 		hba->underrun_counter = (args)? arg[0]:1;
   5102 		break;
   5103 	}
   5104 #endif /* TEST_SUPPORT */
   5105 
   5106 	default:
   5107 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5108 		    "emlxs_test: Unsupported test code. (0x%x)", test_code);
   5109 		rval = FC_INVALID_REQUEST;
   5110 	}
   5111 
   5112 	return (rval);
   5113 
   5114 } /* emlxs_test() */
   5115 
   5116 
   5117 /*
   5118  * Given the device number, return the devinfo pointer or the ddiinst number.
   5119  * Note: this routine must be successful on DDI_INFO_DEVT2INSTANCE even
   5120  * before attach.
   5121  *
   5122  * Translate "dev_t" to a pointer to the associated "dev_info_t".
   5123  */
   5124 /*ARGSUSED*/
   5125 static int
   5126 emlxs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
   5127 {
   5128 	emlxs_hba_t	*hba;
   5129 	int32_t		ddiinst;
   5130 
   5131 	ddiinst = getminor((dev_t)arg);
   5132 
   5133 	switch (infocmd) {
   5134 	case DDI_INFO_DEVT2DEVINFO:
   5135 		hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
   5136 		if (hba)
   5137 			*result = hba->dip;
   5138 		else
   5139 			*result = NULL;
   5140 		break;
   5141 
   5142 	case DDI_INFO_DEVT2INSTANCE:
   5143 		*result = (void *)((unsigned long)ddiinst);
   5144 		break;
   5145 
   5146 	default:
   5147 		return (DDI_FAILURE);
   5148 	}
   5149 
   5150 	return (DDI_SUCCESS);
   5151 
   5152 } /* emlxs_info() */
   5153 
   5154 
   5155 static int32_t
   5156 emlxs_power(dev_info_t *dip, int32_t comp, int32_t level)
   5157 {
   5158 	emlxs_hba_t	*hba;
   5159 	emlxs_port_t	*port;
   5160 	int32_t		ddiinst;
   5161 	int		rval = DDI_SUCCESS;
   5162 
   5163 	ddiinst = ddi_get_instance(dip);
   5164 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
   5165 	port = &PPORT;
   5166 
   5167 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   5168 	    "fca_power: comp=%x level=%x", comp, level);
   5169 
   5170 	if (hba == NULL || comp != EMLXS_PM_ADAPTER) {
   5171 		return (DDI_FAILURE);
   5172 	}
   5173 
   5174 	mutex_enter(&EMLXS_PM_LOCK);
   5175 
   5176 	/* If we are already at the proper level then return success */
   5177 	if (hba->pm_level == level) {
   5178 		mutex_exit(&EMLXS_PM_LOCK);
   5179 		return (DDI_SUCCESS);
   5180 	}
   5181 
   5182 	switch (level) {
   5183 	case EMLXS_PM_ADAPTER_UP:
   5184 
   5185 		/*
   5186 		 * If we are already in emlxs_attach,
   5187 		 * let emlxs_hba_attach take care of things
   5188 		 */
   5189 		if (hba->pm_state & EMLXS_PM_IN_ATTACH) {
   5190 			hba->pm_level = EMLXS_PM_ADAPTER_UP;
   5191 			break;
   5192 		}
   5193 
   5194 		/* Check if adapter is suspended */
   5195 		if (hba->pm_state & EMLXS_PM_SUSPENDED) {
   5196 			hba->pm_level = EMLXS_PM_ADAPTER_UP;
   5197 
   5198 			/* Try to resume the port */
   5199 			rval = emlxs_hba_resume(dip);
   5200 
   5201 			if (rval != DDI_SUCCESS) {
   5202 				hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
   5203 			}
   5204 			break;
   5205 		}
   5206 
   5207 		/* Set adapter up */
   5208 		hba->pm_level = EMLXS_PM_ADAPTER_UP;
   5209 		break;
   5210 
   5211 	case EMLXS_PM_ADAPTER_DOWN:
   5212 
   5213 
   5214 		/*
   5215 		 * If we are already in emlxs_detach,
   5216 		 * let emlxs_hba_detach take care of things
   5217 		 */
   5218 		if (hba->pm_state & EMLXS_PM_IN_DETACH) {
   5219 			hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
   5220 			break;
   5221 		}
   5222 
   5223 		/* Check if adapter is not suspended */
   5224 		if (!(hba->pm_state & EMLXS_PM_SUSPENDED)) {
   5225 			hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
   5226 
   5227 			/* Try to suspend the port */
   5228 			rval = emlxs_hba_suspend(dip);
   5229 
   5230 			if (rval != DDI_SUCCESS) {
   5231 				hba->pm_level = EMLXS_PM_ADAPTER_UP;
   5232 			}
   5233 
   5234 			break;
   5235 		}
   5236 
   5237 		/* Set adapter down */
   5238 		hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
   5239 		break;
   5240 
   5241 	default:
   5242 		rval = DDI_FAILURE;
   5243 		break;
   5244 
   5245 	}
   5246 
   5247 	mutex_exit(&EMLXS_PM_LOCK);
   5248 
   5249 	return (rval);
   5250 
   5251 } /* emlxs_power() */
   5252 
   5253 
   5254 #ifdef EMLXS_I386
   5255 #ifdef S11
   5256 /*
   5257  * quiesce(9E) entry point.
   5258  *
   5259  * This function is called when the system is single-thread at hight PIL
   5260  * with preemption disabled. Therefore, this function must not be blocked.
   5261  *
   5262  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
   5263  * DDI_FAILURE indicates an error condition and should almost never happen.
   5264  */
   5265 static int
   5266 emlxs_quiesce(dev_info_t *dip)
   5267 {
   5268 	emlxs_hba_t	*hba;
   5269 	emlxs_port_t	*port;
   5270 	int32_t		ddiinst;
   5271 	int		rval = DDI_SUCCESS;
   5272 
   5273 	ddiinst = ddi_get_instance(dip);
   5274 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
   5275 	port = &PPORT;
   5276 
   5277 	if (hba == NULL || port == NULL) {
   5278 		return (DDI_FAILURE);
   5279 	}
   5280 
   5281 	/* The fourth arg 1 indicates the call is from quiesce */
   5282 	if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 1) == 0) {
   5283 		return (rval);
   5284 	} else {
   5285 		return (DDI_FAILURE);
   5286 	}
   5287 
   5288 } /* emlxs_quiesce */
   5289 #endif
   5290 #endif /* EMLXS_I386 */
   5291 
   5292 
   5293 static int
   5294 emlxs_open(dev_t *dev_p, int32_t flag, int32_t otype, cred_t *cred_p)
   5295 {
   5296 	emlxs_hba_t	*hba;
   5297 	emlxs_port_t	*port;
   5298 	int		ddiinst;
   5299 
   5300 	ddiinst = getminor(*dev_p);
   5301 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
   5302 
   5303 	if (hba == NULL) {
   5304 		return (ENXIO);
   5305 	}
   5306 
   5307 	port = &PPORT;
   5308 
   5309 	if (hba->pm_state & EMLXS_PM_SUSPENDED) {
   5310 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg,
   5311 		    "open failed: Driver suspended.");
   5312 		return (ENXIO);
   5313 	}
   5314 
   5315 	if (otype != OTYP_CHR) {
   5316 		return (EINVAL);
   5317 	}
   5318 
   5319 	if (drv_priv(cred_p)) {
   5320 		return (EPERM);
   5321 	}
   5322 
   5323 	mutex_enter(&EMLXS_IOCTL_LOCK);
   5324 
   5325 	if (hba->ioctl_flags & EMLXS_OPEN_EXCLUSIVE) {
   5326 		mutex_exit(&EMLXS_IOCTL_LOCK);
   5327 		return (EBUSY);
   5328 	}
   5329 
   5330 	if (flag & FEXCL) {
   5331 		if (hba->ioctl_flags & EMLXS_OPEN) {
   5332 			mutex_exit(&EMLXS_IOCTL_LOCK);
   5333 			return (EBUSY);
   5334 		}
   5335 
   5336 		hba->ioctl_flags |= EMLXS_OPEN_EXCLUSIVE;
   5337 	}
   5338 
   5339 	hba->ioctl_flags |= EMLXS_OPEN;
   5340 
   5341 	mutex_exit(&EMLXS_IOCTL_LOCK);
   5342 
   5343 	return (0);
   5344 
   5345 } /* emlxs_open() */
   5346 
   5347 
   5348 /*ARGSUSED*/
   5349 static int
   5350 emlxs_close(dev_t dev, int32_t flag, int32_t otype, cred_t *cred_p)
   5351 {
   5352 	emlxs_hba_t	*hba;
   5353 	int		ddiinst;
   5354 
   5355 	ddiinst = getminor(dev);
   5356 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
   5357 
   5358 	if (hba == NULL) {
   5359 		return (ENXIO);
   5360 	}
   5361 
   5362 	if (otype != OTYP_CHR) {
   5363 		return (EINVAL);
   5364 	}
   5365 
   5366 	mutex_enter(&EMLXS_IOCTL_LOCK);
   5367 
   5368 	if (!(hba->ioctl_flags & EMLXS_OPEN)) {
   5369 		mutex_exit(&EMLXS_IOCTL_LOCK);
   5370 		return (ENODEV);
   5371 	}
   5372 
   5373 	hba->ioctl_flags &= ~EMLXS_OPEN;
   5374 	hba->ioctl_flags &= ~EMLXS_OPEN_EXCLUSIVE;
   5375 
   5376 	mutex_exit(&EMLXS_IOCTL_LOCK);
   5377 
   5378 	return (0);
   5379 
   5380 } /* emlxs_close() */
   5381 
   5382 
   5383 /*ARGSUSED*/
   5384 static int
   5385 emlxs_ioctl(dev_t dev, int32_t cmd, intptr_t arg, int32_t mode,
   5386     cred_t *cred_p, int32_t *rval_p)
   5387 {
   5388 	emlxs_hba_t	*hba;
   5389 	emlxs_port_t	*port;
   5390 	int		rval = 0;	/* return code */
   5391 	int		ddiinst;
   5392 
   5393 	ddiinst = getminor(dev);
   5394 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
   5395 
   5396 	if (hba == NULL) {
   5397 		return (ENXIO);
   5398 	}
   5399 
   5400 	port = &PPORT;
   5401 
   5402 	if (hba->pm_state & EMLXS_PM_SUSPENDED) {
   5403 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg,
   5404 		    "ioctl failed: Driver suspended.");
   5405 
   5406 		return (ENXIO);
   5407 	}
   5408 
   5409 	mutex_enter(&EMLXS_IOCTL_LOCK);
   5410 	if (!(hba->ioctl_flags & EMLXS_OPEN)) {
   5411 		mutex_exit(&EMLXS_IOCTL_LOCK);
   5412 		return (ENXIO);
   5413 	}
   5414 	mutex_exit(&EMLXS_IOCTL_LOCK);
   5415 
   5416 #ifdef IDLE_TIMER
   5417 	emlxs_pm_busy_component(hba);
   5418 #endif	/* IDLE_TIMER */
   5419 
   5420 	switch (cmd) {
   5421 	case EMLXS_DFC_COMMAND:
   5422 		rval = emlxs_dfc_manage(hba, (void *)arg, mode);
   5423 		break;
   5424 
   5425 	default:
   5426 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg,
   5427 		    "ioctl: Invalid command received. cmd=%x", cmd);
   5428 		rval = EINVAL;
   5429 	}
   5430 
   5431 done:
   5432 	return (rval);
   5433 
   5434 } /* emlxs_ioctl() */
   5435 
   5436 
   5437 
   5438 /*
   5439  *
   5440  *	Device Driver Common Routines
   5441  *
   5442  */
   5443 
   5444 /* EMLXS_PM_LOCK must be held for this call */
   5445 static int
   5446 emlxs_hba_resume(dev_info_t *dip)
   5447 {
   5448 	emlxs_hba_t	*hba;
   5449 	emlxs_port_t	*port;
   5450 	int		ddiinst;
   5451 
   5452 	ddiinst = ddi_get_instance(dip);
   5453 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
   5454 	port = &PPORT;
   5455 
   5456 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_resume_msg, NULL);
   5457 
   5458 	if (!(hba->pm_state & EMLXS_PM_SUSPENDED)) {
   5459 		return (DDI_SUCCESS);
   5460 	}
   5461 
   5462 	hba->pm_state &= ~EMLXS_PM_SUSPENDED;
   5463 
   5464 	/* Take the adapter online */
   5465 	if (emlxs_power_up(hba)) {
   5466 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_resume_failed_msg,
   5467 		    "Unable to take adapter online.");
   5468 
   5469 		hba->pm_state |= EMLXS_PM_SUSPENDED;
   5470 
   5471 		return (DDI_FAILURE);
   5472 	}
   5473 
   5474 	return (DDI_SUCCESS);
   5475 
   5476 } /* emlxs_hba_resume() */
   5477 
   5478 
   5479 /* EMLXS_PM_LOCK must be held for this call */
   5480 static int
   5481 emlxs_hba_suspend(dev_info_t *dip)
   5482 {
   5483 	emlxs_hba_t	*hba;
   5484 	emlxs_port_t	*port;
   5485 	int		ddiinst;
   5486 
   5487 	ddiinst = ddi_get_instance(dip);
   5488 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
   5489 	port = &PPORT;
   5490 
   5491 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_suspend_msg, NULL);
   5492 
   5493 	if (hba->pm_state & EMLXS_PM_SUSPENDED) {
   5494 		return (DDI_SUCCESS);
   5495 	}
   5496 
   5497 	hba->pm_state |= EMLXS_PM_SUSPENDED;
   5498 
   5499 	/* Take the adapter offline */
   5500 	if (emlxs_power_down(hba)) {
   5501 		hba->pm_state &= ~EMLXS_PM_SUSPENDED;
   5502 
   5503 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_suspend_failed_msg,
   5504 		    "Unable to take adapter offline.");
   5505 
   5506 		return (DDI_FAILURE);
   5507 	}
   5508 
   5509 	return (DDI_SUCCESS);
   5510 
   5511 } /* emlxs_hba_suspend() */
   5512 
   5513 
   5514 
   5515 static void
   5516 emlxs_lock_init(emlxs_hba_t *hba)
   5517 {
   5518 	emlxs_port_t	*port = &PPORT;
   5519 	int32_t		ddiinst;
   5520 	char		buf[64];
   5521 	uint32_t	i;
   5522 
   5523 	ddiinst = hba->ddiinst;
   5524 
   5525 	/* Initialize the power management */
   5526 	(void) sprintf(buf, "%s%d_pm_lock mutex", DRIVER_NAME, ddiinst);
   5527 	mutex_init(&EMLXS_PM_LOCK, buf, MUTEX_DRIVER,
   5528 	    (void *)hba->intr_arg);
   5529 
   5530 	(void) sprintf(buf, "%s%d_adap_lock mutex", DRIVER_NAME, ddiinst);
   5531 	mutex_init(&EMLXS_TIMER_LOCK, buf, MUTEX_DRIVER,
   5532 	    (void *)hba->intr_arg);
   5533 
   5534 	(void) sprintf(buf, "%s%d_adap_lock cv", DRIVER_NAME, ddiinst);
   5535 	cv_init(&hba->timer_lock_cv, buf, CV_DRIVER, NULL);
   5536 
   5537 	(void) sprintf(buf, "%s%d_port_lock mutex", DRIVER_NAME, ddiinst);
   5538 	mutex_init(&EMLXS_PORT_LOCK, buf, MUTEX_DRIVER,
   5539 	    (void *)hba->intr_arg);
   5540 
   5541 	(void) sprintf(buf, "%s%d_mbox_lock mutex", DRIVER_NAME, ddiinst);
   5542 	mutex_init(&EMLXS_MBOX_LOCK, buf, MUTEX_DRIVER,
   5543 	    (void *)hba->intr_arg);
   5544 
   5545 	(void) sprintf(buf, "%s%d_mbox_lock cv", DRIVER_NAME, ddiinst);
   5546 	cv_init(&EMLXS_MBOX_CV, buf, CV_DRIVER, NULL);
   5547 
   5548 	(void) sprintf(buf, "%s%d_linkup_lock mutex", DRIVER_NAME, ddiinst);
   5549 	mutex_init(&EMLXS_LINKUP_LOCK, buf, MUTEX_DRIVER,
   5550 	    (void *)hba->intr_arg);
   5551 
   5552 	(void) sprintf(buf, "%s%d_linkup_lock cv", DRIVER_NAME, ddiinst);
   5553 	cv_init(&EMLXS_LINKUP_CV, buf, CV_DRIVER, NULL);
   5554 
   5555 	(void) sprintf(buf, "%s%d_ring_tx_lock mutex", DRIVER_NAME, ddiinst);
   5556 	mutex_init(&EMLXS_TX_CHANNEL_LOCK, buf, MUTEX_DRIVER,
   5557 	    (void *)hba->intr_arg);
   5558 
   5559 	for (i = 0; i < MAX_RINGS; i++) {
   5560 		(void) sprintf(buf, "%s%d_cmd_ring%d_lock mutex", DRIVER_NAME,
   5561 		    ddiinst, i);
   5562 		mutex_init(&EMLXS_CMD_RING_LOCK(i), buf, MUTEX_DRIVER,
   5563 		    (void *)hba->intr_arg);
   5564 	}
   5565 
   5566 	(void) sprintf(buf, "%s%d_fctab_lock mutex", DRIVER_NAME, ddiinst);
   5567 	mutex_init(&EMLXS_FCTAB_LOCK, buf, MUTEX_DRIVER,
   5568 	    (void *)hba->intr_arg);
   5569 
   5570 	(void) sprintf(buf, "%s%d_memget_lock mutex", DRIVER_NAME, ddiinst);
   5571 	mutex_init(&EMLXS_MEMGET_LOCK, buf, MUTEX_DRIVER,
   5572 	    (void *)hba->intr_arg);
   5573 
   5574 	(void) sprintf(buf, "%s%d_memput_lock mutex", DRIVER_NAME, ddiinst);
   5575 	mutex_init(&EMLXS_MEMPUT_LOCK, buf, MUTEX_DRIVER,
   5576 	    (void *)hba->intr_arg);
   5577 
   5578 	(void) sprintf(buf, "%s%d_ioctl_lock mutex", DRIVER_NAME, ddiinst);
   5579 	mutex_init(&EMLXS_IOCTL_LOCK, buf, MUTEX_DRIVER,
   5580 	    (void *)hba->intr_arg);
   5581 
   5582 #ifdef DUMP_SUPPORT
   5583 	(void) sprintf(buf, "%s%d_dump mutex", DRIVER_NAME, ddiinst);
   5584 	mutex_init(&EMLXS_DUMP_LOCK, buf, MUTEX_DRIVER,
   5585 	    (void *)hba->intr_arg);
   5586 #endif /* DUMP_SUPPORT */
   5587 
   5588 	(void) sprintf(buf, "%s%d_thread_lock mutex", DRIVER_NAME, ddiinst);
   5589 	mutex_init(&EMLXS_SPAWN_LOCK, buf, MUTEX_DRIVER,
   5590 	    (void *)hba->intr_arg);
   5591 
   5592 	/* Create per port locks */
   5593 	for (i = 0; i < MAX_VPORTS; i++) {
   5594 		port = &VPORT(i);
   5595 
   5596 		rw_init(&port->node_rwlock, NULL, RW_DRIVER, NULL);
   5597 
   5598 		if (i == 0) {
   5599 			(void) sprintf(buf, "%s%d_pkt_lock mutex", DRIVER_NAME,
   5600 			    ddiinst);
   5601 			mutex_init(&EMLXS_PKT_LOCK, buf, MUTEX_DRIVER,
   5602 			    (void *)hba->intr_arg);
   5603 
   5604 			(void) sprintf(buf, "%s%d_pkt_lock cv", DRIVER_NAME,
   5605 			    ddiinst);
   5606 			cv_init(&EMLXS_PKT_CV, buf, CV_DRIVER, NULL);
   5607 
   5608 			(void) sprintf(buf, "%s%d_ub_lock mutex", DRIVER_NAME,
   5609 			    ddiinst);
   5610 			mutex_init(&EMLXS_UB_LOCK, buf, MUTEX_DRIVER,
   5611 			    (void *)hba->intr_arg);
   5612 		} else {
   5613 			(void) sprintf(buf, "%s%d.%d_pkt_lock mutex",
   5614 			    DRIVER_NAME, ddiinst, port->vpi);
   5615 			mutex_init(&EMLXS_PKT_LOCK, buf, MUTEX_DRIVER,
   5616 			    (void *)hba->intr_arg);
   5617 
   5618 			(void) sprintf(buf, "%s%d.%d_pkt_lock cv", DRIVER_NAME,
   5619 			    ddiinst, port->vpi);
   5620 			cv_init(&EMLXS_PKT_CV, buf, CV_DRIVER, NULL);
   5621 
   5622 			(void) sprintf(buf, "%s%d.%d_ub_lock mutex",
   5623 			    DRIVER_NAME, ddiinst, port->vpi);
   5624 			mutex_init(&EMLXS_UB_LOCK, buf, MUTEX_DRIVER,
   5625 			    (void *)hba->intr_arg);
   5626 		}
   5627 	}
   5628 
   5629 	return;
   5630 
   5631 } /* emlxs_lock_init() */
   5632 
   5633 
   5634 
   5635 static void
   5636 emlxs_lock_destroy(emlxs_hba_t *hba)
   5637 {
   5638 	emlxs_port_t	*port = &PPORT;
   5639 	uint32_t	i;
   5640 
   5641 	mutex_destroy(&EMLXS_TIMER_LOCK);
   5642 	cv_destroy(&hba->timer_lock_cv);
   5643 
   5644 	mutex_destroy(&EMLXS_PORT_LOCK);
   5645 
   5646 	cv_destroy(&EMLXS_MBOX_CV);
   5647 	cv_destroy(&EMLXS_LINKUP_CV);
   5648 
   5649 	mutex_destroy(&EMLXS_LINKUP_LOCK);
   5650 	mutex_destroy(&EMLXS_MBOX_LOCK);
   5651 
   5652 	mutex_destroy(&EMLXS_TX_CHANNEL_LOCK);
   5653 
   5654 	for (i = 0; i < MAX_RINGS; i++) {
   5655 		mutex_destroy(&EMLXS_CMD_RING_LOCK(i));
   5656 	}
   5657 
   5658 	mutex_destroy(&EMLXS_FCTAB_LOCK);
   5659 	mutex_destroy(&EMLXS_MEMGET_LOCK);
   5660 	mutex_destroy(&EMLXS_MEMPUT_LOCK);
   5661 	mutex_destroy(&EMLXS_IOCTL_LOCK);
   5662 	mutex_destroy(&EMLXS_SPAWN_LOCK);
   5663 	mutex_destroy(&EMLXS_PM_LOCK);
   5664 
   5665 #ifdef DUMP_SUPPORT
   5666 	mutex_destroy(&EMLXS_DUMP_LOCK);
   5667 #endif /* DUMP_SUPPORT */
   5668 
   5669 	/* Destroy per port locks */
   5670 	for (i = 0; i < MAX_VPORTS; i++) {
   5671 		port = &VPORT(i);
   5672 		rw_destroy(&port->node_rwlock);
   5673 		mutex_destroy(&EMLXS_PKT_LOCK);
   5674 		cv_destroy(&EMLXS_PKT_CV);
   5675 		mutex_destroy(&EMLXS_UB_LOCK);
   5676 	}
   5677 
   5678 	return;
   5679 
   5680 } /* emlxs_lock_destroy() */
   5681 
   5682 
   5683 /* init_flag values */
   5684 #define	ATTACH_SOFT_STATE	0x00000001
   5685 #define	ATTACH_FCA_TRAN		0x00000002
   5686 #define	ATTACH_HBA		0x00000004
   5687 #define	ATTACH_LOG		0x00000008
   5688 #define	ATTACH_MAP_BUS		0x00000010
   5689 #define	ATTACH_INTR_INIT	0x00000020
   5690 #define	ATTACH_PROP		0x00000040
   5691 #define	ATTACH_LOCK		0x00000080
   5692 #define	ATTACH_THREAD		0x00000100
   5693 #define	ATTACH_INTR_ADD		0x00000200
   5694 #define	ATTACH_ONLINE		0x00000400
   5695 #define	ATTACH_NODE		0x00000800
   5696 #define	ATTACH_FCT		0x00001000
   5697 #define	ATTACH_FCA		0x00002000
   5698 #define	ATTACH_KSTAT		0x00004000
   5699 #define	ATTACH_DHCHAP		0x00008000
   5700 #define	ATTACH_FM		0x00010000
   5701 #define	ATTACH_MAP_SLI		0x00020000
   5702 #define	ATTACH_SPAWN		0x00040000
   5703 #define	ATTACH_EVENTS		0x00080000
   5704 
   5705 static void
   5706 emlxs_driver_remove(dev_info_t *dip, uint32_t init_flag, uint32_t failed)
   5707 {
   5708 	emlxs_hba_t	*hba = NULL;
   5709 	int		ddiinst;
   5710 
   5711 	ddiinst = ddi_get_instance(dip);
   5712 
   5713 	if (init_flag & ATTACH_HBA) {
   5714 		hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
   5715 
   5716 		if (init_flag & ATTACH_SPAWN) {
   5717 			emlxs_thread_spawn_destroy(hba);
   5718 		}
   5719 
   5720 		if (init_flag & ATTACH_EVENTS) {
   5721 			(void) emlxs_event_queue_destroy(hba);
   5722 		}
   5723 
   5724 		if (init_flag & ATTACH_ONLINE) {
   5725 			(void) emlxs_offline(hba);
   5726 		}
   5727 
   5728 		if (init_flag & ATTACH_INTR_ADD) {
   5729 			(void) EMLXS_INTR_REMOVE(hba);
   5730 		}
   5731 #ifdef SFCT_SUPPORT
   5732 		if (init_flag & ATTACH_FCT) {
   5733 			emlxs_fct_detach(hba);
   5734 			emlxs_fct_modclose();
   5735 		}
   5736 #endif /* SFCT_SUPPORT */
   5737 
   5738 #ifdef DHCHAP_SUPPORT
   5739 		if (init_flag & ATTACH_DHCHAP) {
   5740 			emlxs_dhc_detach(hba);
   5741 		}
   5742 #endif /* DHCHAP_SUPPORT */
   5743 
   5744 		if (init_flag & ATTACH_KSTAT) {
   5745 			kstat_delete(hba->kstat);
   5746 		}
   5747 
   5748 		if (init_flag & ATTACH_FCA) {
   5749 			emlxs_fca_detach(hba);
   5750 		}
   5751 
   5752 		if (init_flag & ATTACH_NODE) {
   5753 			(void) ddi_remove_minor_node(hba->dip, "devctl");
   5754 		}
   5755 
   5756 		if (init_flag & ATTACH_THREAD) {
   5757 			emlxs_thread_destroy(&hba->iodone_thread);
   5758 		}
   5759 
   5760 		if (init_flag & ATTACH_PROP) {
   5761 			(void) ddi_prop_remove_all(hba->dip);
   5762 		}
   5763 
   5764 		if (init_flag & ATTACH_LOCK) {
   5765 			emlxs_lock_destroy(hba);
   5766 		}
   5767 
   5768 		if (init_flag & ATTACH_INTR_INIT) {
   5769 			(void) EMLXS_INTR_UNINIT(hba);
   5770 		}
   5771 
   5772 		if (init_flag & ATTACH_MAP_BUS) {
   5773 			emlxs_unmap_bus(hba);
   5774 		}
   5775 
   5776 		if (init_flag & ATTACH_MAP_SLI) {
   5777 			EMLXS_SLI_UNMAP_HDW(hba);
   5778 		}
   5779 
   5780 #ifdef FMA_SUPPORT
   5781 		if (init_flag & ATTACH_FM) {
   5782 			emlxs_fm_fini(hba);
   5783 		}
   5784 #endif	/* FMA_SUPPORT */
   5785 
   5786 		if (init_flag & ATTACH_LOG) {
   5787 			(void) emlxs_msg_log_destroy(hba);
   5788 		}
   5789 
   5790 		if (init_flag & ATTACH_FCA_TRAN) {
   5791 			(void) ddi_set_driver_private(hba->dip, NULL);
   5792 			kmem_free(hba->fca_tran, sizeof (fc_fca_tran_t));
   5793 			hba->fca_tran = NULL;
   5794 		}
   5795 
   5796 		if (init_flag & ATTACH_HBA) {
   5797 			emlxs_device.log[hba->emlxinst] = 0;
   5798 			emlxs_device.hba[hba->emlxinst] =
   5799 			    (emlxs_hba_t *)((unsigned long)((failed) ? -1 : 0));
   5800 #ifdef DUMP_SUPPORT
   5801 			emlxs_device.dump_txtfile[hba->emlxinst] = 0;
   5802 			emlxs_device.dump_dmpfile[hba->emlxinst] = 0;
   5803 			emlxs_device.dump_ceefile[hba->emlxinst] = 0;
   5804 #endif /* DUMP_SUPPORT */
   5805 
   5806 		}
   5807 	}
   5808 
   5809 	if (init_flag & ATTACH_SOFT_STATE) {
   5810 		(void) ddi_soft_state_free(emlxs_soft_state, ddiinst);
   5811 	}
   5812 
   5813 	return;
   5814 
   5815 } /* emlxs_driver_remove() */
   5816 
   5817 
   5818 
   5819 /* This determines which ports will be initiator mode */
   5820 static void
   5821 emlxs_fca_init(emlxs_hba_t *hba)
   5822 {
   5823 	emlxs_port_t	*port = &PPORT;
   5824 	emlxs_port_t	*vport;
   5825 	uint32_t	i;
   5826 
   5827 	if (!hba->ini_mode) {
   5828 		return;
   5829 	}
   5830 	/* Check if SFS present */
   5831 	if (((void *)MODSYM(fc_fca_init) == NULL) ||
   5832 	    ((void *)MODSYM(fc_fca_attach) == NULL)) {
   5833 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   5834 		    "SFS not present. Initiator mode disabled.");
   5835 		goto failed;
   5836 	}
   5837 
   5838 	/* Check if our SFS driver interface matches the current SFS stack */
   5839 	if (MODSYM(fc_fca_attach) (hba->dip, hba->fca_tran) != DDI_SUCCESS) {
   5840 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   5841 		    "SFS/FCA version mismatch. FCA=0x%x",
   5842 		    hba->fca_tran->fca_version);
   5843 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   5844 		    "SFS present. Initiator mode disabled.");
   5845 
   5846 		goto failed;
   5847 	}
   5848 
   5849 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   5850 	    "SFS present. Initiator mode enabled.");
   5851 
   5852 	return;
   5853 
   5854 failed:
   5855 
   5856 	hba->ini_mode = 0;
   5857 	for (i = 0; i < MAX_VPORTS; i++) {
   5858 		vport = &VPORT(i);
   5859 		vport->ini_mode = 0;
   5860 	}
   5861 
   5862 	return;
   5863 
   5864 } /* emlxs_fca_init() */
   5865 
   5866 
   5867 /* This determines which ports will be initiator or target mode */
   5868 static void
   5869 emlxs_set_mode(emlxs_hba_t *hba)
   5870 {
   5871 	emlxs_port_t	*port = &PPORT;
   5872 	emlxs_port_t	*vport;
   5873 	uint32_t	i;
   5874 	uint32_t	tgt_mode = 0;
   5875 
   5876 #ifdef SFCT_SUPPORT
   5877 	emlxs_config_t *cfg;
   5878 
   5879 	cfg = &hba->config[CFG_TARGET_MODE];
   5880 	tgt_mode = cfg->current;
   5881 
   5882 	if (tgt_mode) {
   5883 		if (emlxs_fct_modopen() != 0) {
   5884 			tgt_mode = 0;
   5885 		}
   5886 	}
   5887 
   5888 	port->fct_flags = 0;
   5889 #endif /* SFCT_SUPPORT */
   5890 
   5891 	/* Initialize physical port  */
   5892 	if (tgt_mode) {
   5893 		hba->tgt_mode  = 1;
   5894 		hba->ini_mode  = 0;
   5895 
   5896 		port->tgt_mode = 1;
   5897 		port->ini_mode = 0;
   5898 	} else {
   5899 		hba->tgt_mode  = 0;
   5900 		hba->ini_mode  = 1;
   5901 
   5902 		port->tgt_mode = 0;
   5903 		port->ini_mode = 1;
   5904 	}
   5905 
   5906 	/* Initialize virtual ports */
   5907 	/* Virtual ports take on the mode of the parent physical port */
   5908 	for (i = 1; i < MAX_VPORTS; i++) {
   5909 		vport = &VPORT(i);
   5910 
   5911 #ifdef SFCT_SUPPORT
   5912 		vport->fct_flags = 0;
   5913 #endif /* SFCT_SUPPORT */
   5914 
   5915 		vport->ini_mode = port->ini_mode;
   5916 		vport->tgt_mode = port->tgt_mode;
   5917 	}
   5918 
   5919 	/* Check if initiator mode is requested */
   5920 	if (hba->ini_mode) {
   5921 		emlxs_fca_init(hba);
   5922 	} else {
   5923 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   5924 		    "Initiator mode not enabled.");
   5925 	}
   5926 
   5927 #ifdef SFCT_SUPPORT
   5928 	/* Check if target mode is requested */
   5929 	if (hba->tgt_mode) {
   5930 		emlxs_fct_init(hba);
   5931 	} else {
   5932 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   5933 		    "Target mode not enabled.");
   5934 	}
   5935 #endif /* SFCT_SUPPORT */
   5936 
   5937 	return;
   5938 
   5939 } /* emlxs_set_mode() */
   5940 
   5941 
   5942 
   5943 static void
   5944 emlxs_fca_attach(emlxs_hba_t *hba)
   5945 {
   5946 	/* Update our transport structure */
   5947 	hba->fca_tran->fca_iblock  = (ddi_iblock_cookie_t *)&hba->intr_arg;
   5948 	hba->fca_tran->fca_cmd_max = hba->io_throttle;
   5949 
   5950 #if (EMLXS_MODREV >= EMLXS_MODREV5)
   5951 	bcopy((caddr_t)&hba->wwpn, (caddr_t)&hba->fca_tran->fca_perm_pwwn,
   5952 	    sizeof (NAME_TYPE));
   5953 #endif /* >= EMLXS_MODREV5 */
   5954 
   5955 	return;
   5956 
   5957 } /* emlxs_fca_attach() */
   5958 
   5959 
   5960 static void
   5961 emlxs_fca_detach(emlxs_hba_t *hba)
   5962 {
   5963 	uint32_t	i;
   5964 	emlxs_port_t	*vport;
   5965 
   5966 	if (hba->ini_mode) {
   5967 		if ((void *)MODSYM(fc_fca_detach) != NULL) {
   5968 			MODSYM(fc_fca_detach)(hba->dip);
   5969 		}
   5970 
   5971 		hba->ini_mode = 0;
   5972 
   5973 		for (i = 0; i < MAX_VPORTS; i++) {
   5974 			vport = &VPORT(i);
   5975 			vport->ini_mode  = 0;
   5976 		}
   5977 	}
   5978 
   5979 	return;
   5980 
   5981 } /* emlxs_fca_detach() */
   5982 
   5983 
   5984 
   5985 static void
   5986 emlxs_drv_banner(emlxs_hba_t *hba)
   5987 {
   5988 	emlxs_port_t	*port = &PPORT;
   5989 	uint32_t	i;
   5990 	char		sli_mode[16];
   5991 	char		msi_mode[16];
   5992 	char		npiv_mode[16];
   5993 	emlxs_vpd_t	*vpd = &VPD;
   5994 	emlxs_config_t	*cfg = &CFG;
   5995 	uint8_t		*wwpn;
   5996 	uint8_t		*wwnn;
   5997 
   5998 	/* Display firmware library one time */
   5999 	if (emlxs_instance_count == 1) {
   6000 		emlxs_fw_show(hba);
   6001 	}
   6002 
   6003 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s (%s)", emlxs_label,
   6004 	    emlxs_revision);
   6005 
   6006 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
   6007 	    "%s Dev_id:%x Sub_id:%x Id:%d", hba->model_info.model,
   6008 	    hba->model_info.device_id, hba->model_info.ssdid,
   6009 	    hba->model_info.id);
   6010 
   6011 #ifdef EMLXS_I386
   6012 
   6013 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
   6014 	    "Firmware:%s (%s) Boot:%s", vpd->fw_version, vpd->fw_label,
   6015 	    vpd->boot_version);
   6016 
   6017 #else	/* EMLXS_SPARC */
   6018 
   6019 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
   6020 	    "Firmware:%s (%s) Boot:%s Fcode:%s", vpd->fw_version,
   6021 	    vpd->fw_label, vpd->boot_version, vpd->fcode_version);
   6022 
   6023 #endif	/* EMLXS_I386 */
   6024 
   6025 	if (hba->sli_mode > 3) {
   6026 		(void) sprintf(sli_mode, "SLI:%d(%s)", hba->sli_mode,
   6027 		    ((hba->flag & FC_FIP_SUPPORTED) ? "FIP" : "nonFIP"));
   6028 	} else {
   6029 		(void) sprintf(sli_mode, "SLI:%d", hba->sli_mode);
   6030 	}
   6031 
   6032 	(void) strcpy(msi_mode, " INTX:1");
   6033 
   6034 #ifdef MSI_SUPPORT
   6035 	if (hba->intr_flags & EMLXS_MSI_ENABLED) {
   6036 		switch (hba->intr_type) {
   6037 		case DDI_INTR_TYPE_FIXED:
   6038 			(void) strcpy(msi_mode, " MSI:0");
   6039 			break;
   6040 
   6041 		case DDI_INTR_TYPE_MSI:
   6042 			(void) sprintf(msi_mode, " MSI:%d", hba->intr_count);
   6043 			break;
   6044 
   6045 		case DDI_INTR_TYPE_MSIX:
   6046 			(void) sprintf(msi_mode, " MSIX:%d", hba->intr_count);
   6047 			break;
   6048 		}
   6049 	}
   6050 #endif
   6051 
   6052 	(void) strcpy(npiv_mode, "");
   6053 
   6054 	if (hba->flag & FC_NPIV_ENABLED) {
   6055 		(void) sprintf(npiv_mode, " NPIV:%d", hba->vpi_max+1);
   6056 	} else {
   6057 		(void) strcpy(npiv_mode, " NPIV:0");
   6058 	}
   6059 
   6060 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s%s%s%s%s",
   6061 	    sli_mode, msi_mode, npiv_mode,
   6062 	    ((hba->ini_mode)? " FCA":""), ((hba->tgt_mode)? " FCT":""));
   6063 
   6064 	wwpn = (uint8_t *)&hba->wwpn;
   6065 	wwnn = (uint8_t *)&hba->wwnn;
   6066 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
   6067 	    "WWPN:%02X%02X%02X%02X%02X%02X%02X%02X "
   6068 	    "WWNN:%02X%02X%02X%02X%02X%02X%02X%02X",
   6069 	    wwpn[0], wwpn[1], wwpn[2], wwpn[3], wwpn[4], wwpn[5], wwpn[6],
   6070 	    wwpn[7], wwnn[0], wwnn[1], wwnn[2], wwnn[3], wwnn[4], wwnn[5],
   6071 	    wwnn[6], wwnn[7]);
   6072 
   6073 	for (i = 0; i < MAX_VPORTS; i++) {
   6074 		port = &VPORT(i);
   6075 
   6076 		if (!(port->flag & EMLXS_PORT_CONFIG)) {
   6077 			continue;
   6078 		}
   6079 
   6080 		wwpn = (uint8_t *)&port->wwpn;
   6081 		wwnn = (uint8_t *)&port->wwnn;
   6082 
   6083 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
   6084 		    "WWPN:%02X%02X%02X%02X%02X%02X%02X%02X "
   6085 		    "WWNN:%02X%02X%02X%02X%02X%02X%02X%02X",
   6086 		    wwpn[0], wwpn[1], wwpn[2], wwpn[3], wwpn[4], wwpn[5],
   6087 		    wwpn[6], wwpn[7], wwnn[0], wwnn[1], wwnn[2], wwnn[3],
   6088 		    wwnn[4], wwnn[5], wwnn[6], wwnn[7]);
   6089 	}
   6090 	port = &PPORT;
   6091 
   6092 	/*
   6093 	 * No dependency for Restricted login parameter.
   6094 	 */
   6095 	if ((cfg[CFG_VPORT_RESTRICTED].current) && (port->ini_mode)) {
   6096 		port->flag |= EMLXS_PORT_RESTRICTED;
   6097 	} else {
   6098 		port->flag &= ~EMLXS_PORT_RESTRICTED;
   6099 	}
   6100 
   6101 	/*
   6102 	 * Announce the device: ddi_report_dev() prints a banner at boot time,
   6103 	 * announcing the device pointed to by dip.
   6104 	 */
   6105 	(void) ddi_report_dev(hba->dip);
   6106 
   6107 	return;
   6108 
   6109 } /* emlxs_drv_banner() */
   6110 
   6111 
   6112 extern void
   6113 emlxs_get_fcode_version(emlxs_hba_t *hba)
   6114 {
   6115 	emlxs_vpd_t	*vpd = &VPD;
   6116 	char		*prop_str;
   6117 	int		status;
   6118 
   6119 	/* Setup fcode version property */
   6120 	prop_str = NULL;
   6121 	status =
   6122 	    ddi_prop_lookup_string(DDI_DEV_T_ANY, (dev_info_t *)hba->dip, 0,
   6123 	    "fcode-version", (char **)&prop_str);
   6124 
   6125 	if (status == DDI_PROP_SUCCESS) {
   6126 		bcopy(prop_str, vpd->fcode_version, strlen(prop_str));
   6127 		(void) ddi_prop_free((void *)prop_str);
   6128 	} else {
   6129 		(void) strcpy(vpd->fcode_version, "none");
   6130 	}
   6131 
   6132 	return;
   6133 
   6134 } /* emlxs_get_fcode_version() */
   6135 
   6136 
   6137 static int
   6138 emlxs_hba_attach(dev_info_t *dip)
   6139 {
   6140 	emlxs_hba_t	*hba;
   6141 	emlxs_port_t	*port;
   6142 	emlxs_config_t	*cfg;
   6143 	char		*prop_str;
   6144 	int		ddiinst;
   6145 	int32_t		emlxinst;
   6146 	int		status;
   6147 	uint32_t	rval;
   6148 	uint32_t	init_flag = 0;
   6149 	char		local_pm_components[32];
   6150 #ifdef EMLXS_I386
   6151 	uint32_t	i;
   6152 #endif	/* EMLXS_I386 */
   6153 
   6154 	ddiinst = ddi_get_instance(dip);
   6155 	emlxinst = emlxs_add_instance(ddiinst);
   6156 
   6157 	if (emlxinst >= MAX_FC_BRDS) {
   6158 		cmn_err(CE_WARN,
   6159 		    "?%s: fca_hba_attach failed. Too many driver ddiinsts. "
   6160 		    "inst=%x", DRIVER_NAME, ddiinst);
   6161 		return (DDI_FAILURE);
   6162 	}
   6163 
   6164 	if (emlxs_device.hba[emlxinst] == (emlxs_hba_t *)-1) {
   6165 		return (DDI_FAILURE);
   6166 	}
   6167 
   6168 	if (emlxs_device.hba[emlxinst]) {
   6169 		return (DDI_SUCCESS);
   6170 	}
   6171 
   6172 	/* An adapter can accidentally be plugged into a slave-only PCI slot */
   6173 	if (ddi_slaveonly(dip) == DDI_SUCCESS) {
   6174 		cmn_err(CE_WARN,
   6175 		    "?%s%d: fca_hba_attach failed. Device in slave-only slot.",
   6176 		    DRIVER_NAME, ddiinst);
   6177 		return (DDI_FAILURE);
   6178 	}
   6179 
   6180 	/* Allocate emlxs_dev_ctl structure. */
   6181 	if (ddi_soft_state_zalloc(emlxs_soft_state, ddiinst) != DDI_SUCCESS) {
   6182 		cmn_err(CE_WARN,
   6183 		    "?%s%d: fca_hba_attach failed. Unable to allocate soft "
   6184 		    "state.", DRIVER_NAME, ddiinst);
   6185 		return (DDI_FAILURE);
   6186 	}
   6187 	init_flag |= ATTACH_SOFT_STATE;
   6188 
   6189 	if ((hba = (emlxs_hba_t *)ddi_get_soft_state(emlxs_soft_state,
   6190 	    ddiinst)) == NULL) {
   6191 		cmn_err(CE_WARN,
   6192 		    "?%s%d: fca_hba_attach failed. Unable to get soft state.",
   6193 		    DRIVER_NAME, ddiinst);
   6194 		goto failed;
   6195 	}
   6196 	bzero((char *)hba, sizeof (emlxs_hba_t));
   6197 
   6198 	emlxs_device.hba[emlxinst] = hba;
   6199 	emlxs_device.log[emlxinst] = &hba->log;
   6200 
   6201 #ifdef DUMP_SUPPORT
   6202 	emlxs_device.dump_txtfile[emlxinst] = &hba->dump_txtfile;
   6203 	emlxs_device.dump_dmpfile[emlxinst] = &hba->dump_dmpfile;
   6204 	emlxs_device.dump_ceefile[emlxinst] = &hba->dump_ceefile;
   6205 #endif /* DUMP_SUPPORT */
   6206 
   6207 	hba->dip = dip;
   6208 	hba->emlxinst = emlxinst;
   6209 	hba->ddiinst = ddiinst;
   6210 	hba->ini_mode = 0;
   6211 	hba->tgt_mode = 0;
   6212 
   6213 	init_flag |= ATTACH_HBA;
   6214 
   6215 	/* Enable the physical port on this HBA */
   6216 	port = &PPORT;
   6217 	port->hba = hba;
   6218 	port->vpi = 0;
   6219 	port->flag |= EMLXS_PORT_ENABLE;
   6220 
   6221 	/* Allocate a transport structure */
   6222 	hba->fca_tran =
   6223 	    (fc_fca_tran_t *)kmem_zalloc(sizeof (fc_fca_tran_t), KM_NOSLEEP);
   6224 	if (hba->fca_tran == NULL) {
   6225 		cmn_err(CE_WARN,
   6226 		    "?%s%d: fca_hba_attach failed. Unable to allocate fca_tran "
   6227 		    "memory.", DRIVER_NAME, ddiinst);
   6228 		goto failed;
   6229 	}
   6230 	bcopy((caddr_t)&emlxs_fca_tran, (caddr_t)hba->fca_tran,
   6231 	    sizeof (fc_fca_tran_t));
   6232 
   6233 	/*
   6234 	 * Copy the global ddi_dma_attr to the local hba fields
   6235 	 */
   6236 	bcopy((caddr_t)&emlxs_dma_attr, (caddr_t)&hba->dma_attr,
   6237 	    sizeof (ddi_dma_attr_t));
   6238 	bcopy((caddr_t)&emlxs_dma_attr_ro, (caddr_t)&hba->dma_attr_ro,
   6239 	    sizeof (ddi_dma_attr_t));
   6240 	bcopy((caddr_t)&emlxs_dma_attr_1sg, (caddr_t)&hba->dma_attr_1sg,
   6241 	    sizeof (ddi_dma_attr_t));
   6242 	bcopy((caddr_t)&emlxs_dma_attr_fcip_rsp,
   6243 	    (caddr_t)&hba->dma_attr_fcip_rsp, sizeof (ddi_dma_attr_t));
   6244 
   6245 	/* Reset the fca_tran dma_attr fields to the per-hba copies */
   6246 	hba->fca_tran->fca_dma_attr = &hba->dma_attr;
   6247 	hba->fca_tran->fca_dma_fcp_cmd_attr = &hba->dma_attr_1sg;
   6248 	hba->fca_tran->fca_dma_fcp_rsp_attr = &hba->dma_attr_1sg;
   6249 	hba->fca_tran->fca_dma_fcp_data_attr = &hba->dma_attr_ro;
   6250 	hba->fca_tran->fca_dma_fcip_cmd_attr = &hba->dma_attr_1sg;
   6251 	hba->fca_tran->fca_dma_fcip_rsp_attr = &hba->dma_attr_fcip_rsp;
   6252 	hba->fca_tran->fca_dma_fcsm_cmd_attr = &hba->dma_attr_1sg;
   6253 	hba->fca_tran->fca_dma_fcsm_rsp_attr = &hba->dma_attr;
   6254 
   6255 	/* Set the transport structure pointer in our dip */
   6256 	/* SFS may panic if we are in target only mode    */
   6257 	/* We will update the transport structure later   */
   6258 	(void) ddi_set_driver_private(dip, (caddr_t)&emlxs_fca_tran);
   6259 	init_flag |= ATTACH_FCA_TRAN;
   6260 
   6261 	/* Perform driver integrity check */
   6262 	rval = emlxs_integrity_check(hba);
   6263 	if (rval) {
   6264 		cmn_err(CE_WARN,
   6265 		    "?%s%d: fca_hba_attach failed. Driver integrity check "
   6266 		    "failed. %d error(s) found.", DRIVER_NAME, ddiinst, rval);
   6267 		goto failed;
   6268 	}
   6269 
   6270 	cfg = &CFG;
   6271 
   6272 	bcopy((uint8_t *)&emlxs_cfg, (uint8_t *)cfg, sizeof (emlxs_cfg));
   6273 #ifdef MSI_SUPPORT
   6274 	if ((void *)&ddi_intr_get_supported_types != NULL) {
   6275 		hba->intr_flags |= EMLXS_MSI_ENABLED;
   6276 	}
   6277 #endif	/* MSI_SUPPORT */
   6278 
   6279 
   6280 	/* Create the msg log file */
   6281 	if (emlxs_msg_log_create(hba) == 0) {
   6282 		cmn_err(CE_WARN,
   6283 		    "?%s%d: fca_hba_attach failed. Unable to create message "
   6284 		    "log", DRIVER_NAME, ddiinst);
   6285 		goto failed;
   6286 
   6287 	}
   6288 	init_flag |= ATTACH_LOG;
   6289 
   6290 	/* We can begin to use EMLXS_MSGF from this point on */
   6291 
   6292 	/* Create the event queue */
   6293 	if (emlxs_event_queue_create(hba) == 0) {
   6294 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
   6295 		    "Unable to create event queue");
   6296 
   6297 		goto failed;
   6298 
   6299 	}
   6300 	init_flag |= ATTACH_EVENTS;
   6301 
   6302 	/*
   6303 	 * Find the I/O bus type If it is not a SBUS card,
   6304 	 * then it is a PCI card. Default is PCI_FC (0).
   6305 	 */
   6306 	prop_str = NULL;
   6307 	status = ddi_prop_lookup_string(DDI_DEV_T_ANY,
   6308 	    (dev_info_t *)dip, 0, "name", (char **)&prop_str);
   6309 
   6310 	if (status == DDI_PROP_SUCCESS) {
   6311 		if (strncmp(prop_str, "lpfs", 4) == 0) {
   6312 			hba->bus_type = SBUS_FC;
   6313 		}
   6314 
   6315 		(void) ddi_prop_free((void *)prop_str);
   6316 	}
   6317 
   6318 	/*
   6319 	 * Copy DDS from the config method and update configuration parameters
   6320 	 */
   6321 	(void) emlxs_get_props(hba);
   6322 
   6323 #ifdef FMA_SUPPORT
   6324 	hba->fm_caps = cfg[CFG_FM_CAPS].current;
   6325 
   6326 	emlxs_fm_init(hba);
   6327 
   6328 	init_flag |= ATTACH_FM;
   6329 #endif	/* FMA_SUPPORT */
   6330 
   6331 	if (emlxs_map_bus(hba)) {
   6332 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
   6333 		    "Unable to map memory");
   6334 		goto failed;
   6335 
   6336 	}
   6337 	init_flag |= ATTACH_MAP_BUS;
   6338 
   6339 	/* Attempt to identify the adapter */
   6340 	rval = emlxs_init_adapter_info(hba);
   6341 
   6342 	if (rval == 0) {
   6343 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
   6344 		    "Unable to get adapter info. Id:%d  Device id:0x%x "
   6345 		    "Model:%s", hba->model_info.id,
   6346 		    hba->model_info.device_id, hba->model_info.model);
   6347 		goto failed;
   6348 	}
   6349 
   6350 	/* Check if adapter is not supported */
   6351 	if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
   6352 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
   6353 		    "Unsupported adapter found. Id:%d  Device id:0x%x "
   6354 		    "SSDID:0x%x  Model:%s", hba->model_info.id,
   6355 		    hba->model_info.device_id,
   6356 		    hba->model_info.ssdid, hba->model_info.model);
   6357 		goto failed;
   6358 	}
   6359 	if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
   6360 		hba->sli.sli4.mem_sgl_size = MEM_SGL_SIZE;
   6361 #ifdef EMLXS_I386
   6362 		/*
   6363 		 * TigerShark has 64K limit for SG element size
   6364 		 * Do this for x86 alone. For SPARC, the driver
   6365 		 * breaks up the single SGE later on.
   6366 		 */
   6367 		hba->dma_attr_ro.dma_attr_count_max = 0xffff;
   6368 
   6369 		i = cfg[CFG_MAX_XFER_SIZE].current;
   6370 		/* Update SGL size based on max_xfer_size */
   6371 		if (i > 688128) {
   6372 			/* 688128 = (((2048 / 12) - 2) * 4096) */
   6373 			hba->sli.sli4.mem_sgl_size = 4096;
   6374 		} else if (i > 339968) {
   6375 			/* 339968 = (((1024 / 12) - 2) * 4096) */
   6376 			hba->sli.sli4.mem_sgl_size = 2048;
   6377 		} else {
   6378 			hba->sli.sli4.mem_sgl_size = 1024;
   6379 		}
   6380 		i = SGL_TO_SGLLEN(hba->sli.sli4.mem_sgl_size);
   6381 #endif /* EMLXS_I386 */
   6382 	} else {
   6383 		hba->sli.sli3.mem_bpl_size = MEM_BPL_SIZE;
   6384 #ifdef EMLXS_I386
   6385 		i = cfg[CFG_MAX_XFER_SIZE].current;
   6386 		/* Update BPL size based on max_xfer_size */
   6387 		if (i > 688128) {
   6388 			/* 688128 = (((2048 / 12) - 2) * 4096) */
   6389 			hba->sli.sli3.mem_bpl_size = 4096;
   6390 		} else if (i > 339968) {
   6391 			/* 339968 = (((1024 / 12) - 2) * 4096) */
   6392 			hba->sli.sli3.mem_bpl_size = 2048;
   6393 		} else {
   6394 			hba->sli.sli3.mem_bpl_size = 1024;
   6395 		}
   6396 		i = BPL_TO_SGLLEN(hba->sli.sli3.mem_bpl_size);
   6397 #endif /* EMLXS_I386 */
   6398 	}
   6399 
   6400 #ifdef EMLXS_I386
   6401 	/* Update dma_attr_sgllen based on BPL size */
   6402 	hba->dma_attr.dma_attr_sgllen = i;
   6403 	hba->dma_attr_ro.dma_attr_sgllen = i;
   6404 	hba->dma_attr_fcip_rsp.dma_attr_sgllen = i;
   6405 #endif /* EMLXS_I386 */
   6406 
   6407 	if (EMLXS_SLI_MAP_HDW(hba)) {
   6408 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
   6409 		    "Unable to map memory");
   6410 		goto failed;
   6411 
   6412 	}
   6413 	init_flag |= ATTACH_MAP_SLI;
   6414 
   6415 	/* Initialize the interrupts. But don't add them yet */
   6416 	status = EMLXS_INTR_INIT(hba, 0);
   6417 	if (status != DDI_SUCCESS) {
   6418 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
   6419 		    "Unable to initalize interrupt(s).");
   6420 		goto failed;
   6421 
   6422 	}
   6423 	init_flag |= ATTACH_INTR_INIT;
   6424 
   6425 	/* Initialize LOCKs */
   6426 	emlxs_lock_init(hba);
   6427 	init_flag |= ATTACH_LOCK;
   6428 
   6429 	/* Initialize the power management */
   6430 	mutex_enter(&EMLXS_PM_LOCK);
   6431 	hba->pm_state = EMLXS_PM_IN_ATTACH;
   6432 	hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
   6433 	hba->pm_busy = 0;
   6434 #ifdef IDLE_TIMER
   6435 	hba->pm_active = 1;
   6436 	hba->pm_idle_timer = 0;
   6437 #endif	/* IDLE_TIMER */
   6438 	mutex_exit(&EMLXS_PM_LOCK);
   6439 
   6440 	/* Set the pm component name */
   6441 	(void) sprintf(local_pm_components, "NAME=%s%d", DRIVER_NAME,
   6442 	    ddiinst);
   6443 	emlxs_pm_components[0] = local_pm_components;
   6444 
   6445 	/* Check if power management support is enabled */
   6446 	if (cfg[CFG_PM_SUPPORT].current) {
   6447 		if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
   6448 		    "pm-components", emlxs_pm_components,
   6449 		    sizeof (emlxs_pm_components) /
   6450 		    sizeof (emlxs_pm_components[0])) !=
   6451 		    DDI_PROP_SUCCESS) {
   6452 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
   6453 			    "Unable to create pm components.");
   6454 			goto failed;
   6455 		}
   6456 	}
   6457 
   6458 	/* Needed for suspend and resume support */
   6459 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, "pm-hardware-state",
   6460 	    "needs-suspend-resume");
   6461 	init_flag |= ATTACH_PROP;
   6462 
   6463 	emlxs_thread_spawn_create(hba);
   6464 	init_flag |= ATTACH_SPAWN;
   6465 
   6466 	emlxs_thread_create(hba, &hba->iodone_thread);
   6467 
   6468 	init_flag |= ATTACH_THREAD;
   6469 
   6470 	/* Setup initiator / target ports */
   6471 	emlxs_set_mode(hba);
   6472 
   6473 	/* If driver did not attach to either stack, */
   6474 	/* then driver attach failed */
   6475 	if (!hba->tgt_mode && !hba->ini_mode) {
   6476 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
   6477 		    "Driver interfaces not enabled.");
   6478 		goto failed;
   6479 	}
   6480 
   6481 	/*
   6482 	 * Initialize HBA
   6483 	 */
   6484 
   6485 	/* Set initial state */
   6486 	mutex_enter(&EMLXS_PORT_LOCK);
   6487 	emlxs_diag_state = DDI_OFFDI;
   6488 	hba->flag |= FC_OFFLINE_MODE;
   6489 	hba->flag &= ~(FC_ONLINE_MODE | FC_ONLINING_MODE | FC_OFFLINING_MODE);
   6490 	mutex_exit(&EMLXS_PORT_LOCK);
   6491 
   6492 	if (status = emlxs_online(hba)) {
   6493 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
   6494 		    "Unable to initialize adapter.");
   6495 		goto failed;
   6496 	}
   6497 	init_flag |= ATTACH_ONLINE;
   6498 
   6499 	/* This is to ensure that the model property is properly set */
   6500 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, "model",
   6501 	    hba->model_info.model);
   6502 
   6503 	/* Create the device node. */
   6504 	if (ddi_create_minor_node(dip, "devctl", S_IFCHR, ddiinst, NULL, 0) ==
   6505 	    DDI_FAILURE) {
   6506 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
   6507 		    "Unable to create device node.");
   6508 		goto failed;
   6509 	}
   6510 	init_flag |= ATTACH_NODE;
   6511 
   6512 	/* Attach initiator now */
   6513 	/* This must come after emlxs_online() */
   6514 	emlxs_fca_attach(hba);
   6515 	init_flag |= ATTACH_FCA;
   6516 
   6517 	/* Initialize kstat information */
   6518 	hba->kstat = kstat_create(DRIVER_NAME,
   6519 	    ddiinst, "statistics", "controller",
   6520 	    KSTAT_TYPE_RAW, sizeof (emlxs_stats_t),
   6521 	    KSTAT_FLAG_VIRTUAL);
   6522 
   6523 	if (hba->kstat == NULL) {
   6524 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
   6525 		    "kstat_create failed.");
   6526 	} else {
   6527 		hba->kstat->ks_data = (void *)&hba->stats;
   6528 		kstat_install(hba->kstat);
   6529 		init_flag |= ATTACH_KSTAT;
   6530 	}
   6531 
   6532 #if (EMLXS_MODREV >= EMLXS_MODREV3) && (EMLXS_MODREV <= EMLXS_MODREV4)
   6533 	/* Setup virtual port properties */
   6534 	emlxs_read_vport_prop(hba);
   6535 #endif	/* EMLXS_MODREV3 || EMLXS_MODREV4 */
   6536 
   6537 
   6538 #ifdef DHCHAP_SUPPORT
   6539 	emlxs_dhc_attach(hba);
   6540 	init_flag |= ATTACH_DHCHAP;
   6541 #endif	/* DHCHAP_SUPPORT */
   6542 
   6543 	/* Display the driver banner now */
   6544 	emlxs_drv_banner(hba);
   6545 
   6546 	/* Raise the power level */
   6547 
   6548 	/*
   6549 	 * This will not execute emlxs_hba_resume because
   6550 	 * EMLXS_PM_IN_ATTACH is set
   6551 	 */
   6552 	if (emlxs_pm_raise_power(dip) != DDI_SUCCESS) {
   6553 		/* Set power up anyway. This should not happen! */
   6554 		mutex_enter(&EMLXS_PM_LOCK);
   6555 		hba->pm_level = EMLXS_PM_ADAPTER_UP;
   6556 		hba->pm_state &= ~EMLXS_PM_IN_ATTACH;
   6557 		mutex_exit(&EMLXS_PM_LOCK);
   6558 	} else {
   6559 		mutex_enter(&EMLXS_PM_LOCK);
   6560 		hba->pm_state &= ~EMLXS_PM_IN_ATTACH;
   6561 		mutex_exit(&EMLXS_PM_LOCK);
   6562 	}
   6563 
   6564 #ifdef SFCT_SUPPORT
   6565 	/* Do this last */
   6566 	emlxs_fct_attach(hba);
   6567 	init_flag |= ATTACH_FCT;
   6568 #endif /* SFCT_SUPPORT */
   6569 
   6570 	return (DDI_SUCCESS);
   6571 
   6572 failed:
   6573 
   6574 	emlxs_driver_remove(dip, init_flag, 1);
   6575 
   6576 	return (DDI_FAILURE);
   6577 
   6578 } /* emlxs_hba_attach() */
   6579 
   6580 
   6581 static int
   6582 emlxs_hba_detach(dev_info_t *dip)
   6583 {
   6584 	emlxs_hba_t	*hba;
   6585 	emlxs_port_t	*port;
   6586 	int		ddiinst;
   6587 	int		count;
   6588 	uint32_t	init_flag = (uint32_t)-1;
   6589 
   6590 	ddiinst = ddi_get_instance(dip);
   6591 	hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
   6592 	port = &PPORT;
   6593 
   6594 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg, NULL);
   6595 
   6596 	mutex_enter(&EMLXS_PM_LOCK);
   6597 	hba->pm_state |= EMLXS_PM_IN_DETACH;
   6598 	mutex_exit(&EMLXS_PM_LOCK);
   6599 
   6600 	/* Lower the power level */
   6601 	/*
   6602 	 * This will not suspend the driver since the
   6603 	 * EMLXS_PM_IN_DETACH has been set
   6604 	 */
   6605 	if (emlxs_pm_lower_power(dip) != DDI_SUCCESS) {
   6606 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
   6607 		    "Unable to lower power.");
   6608 
   6609 		mutex_enter(&EMLXS_PM_LOCK);
   6610 		hba->pm_state &= ~EMLXS_PM_IN_DETACH;
   6611 		mutex_exit(&EMLXS_PM_LOCK);
   6612 
   6613 		return (DDI_FAILURE);
   6614 	}
   6615 
   6616 	/* Take the adapter offline first, if not already */
   6617 	if (emlxs_offline(hba) != 0) {
   6618 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
   6619 		    "Unable to take adapter offline.");
   6620 
   6621 		mutex_enter(&EMLXS_PM_LOCK);
   6622 		hba->pm_state &= ~EMLXS_PM_IN_DETACH;
   6623 		mutex_exit(&EMLXS_PM_LOCK);
   6624 
   6625 		(void) emlxs_pm_raise_power(dip);
   6626 
   6627 		return (DDI_FAILURE);
   6628 	}
   6629 	/* Check ub buffer pools */
   6630 	if (port->ub_pool) {
   6631 		mutex_enter(&EMLXS_UB_LOCK);
   6632 
   6633 		/* Wait up to 10 seconds for all ub pools to be freed */
   6634 		count = 10 * 2;
   6635 		while (port->ub_pool && count) {
   6636 			mutex_exit(&EMLXS_UB_LOCK);
   6637 			delay(drv_usectohz(500000));	/* half second wait */
   6638 			count--;
   6639 			mutex_enter(&EMLXS_UB_LOCK);
   6640 		}
   6641 
   6642 		if (port->ub_pool) {
   6643 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   6644 			    "fca_unbind_port: Unsolicited buffers still "
   6645 			    "active. port=%p. Destroying...", port);
   6646 
   6647 			/* Destroy all pools */
   6648 			while (port->ub_pool) {
   6649 				emlxs_ub_destroy(port, port->ub_pool);
   6650 			}
   6651 		}
   6652 
   6653 		mutex_exit(&EMLXS_UB_LOCK);
   6654 	}
   6655 	init_flag &= ~ATTACH_ONLINE;
   6656 
   6657 	/* Remove the driver instance */
   6658 	emlxs_driver_remove(dip, init_flag, 0);
   6659 
   6660 	return (DDI_SUCCESS);
   6661 
   6662 } /* emlxs_hba_detach() */
   6663 
   6664 
   6665 extern int
   6666 emlxs_map_bus(emlxs_hba_t *hba)
   6667 {
   6668 	emlxs_port_t		*port = &PPORT;
   6669 	dev_info_t		*dip;
   6670 	ddi_device_acc_attr_t	dev_attr;
   6671 	int			status;
   6672 
   6673 	dip = (dev_info_t *)hba->dip;
   6674 	dev_attr = emlxs_dev_acc_attr;
   6675 
   6676 	if (hba->bus_type == SBUS_FC) {
   6677 		if (hba->pci_acc_handle == 0) {
   6678 			status = ddi_regs_map_setup(dip,
   6679 			    SBUS_DFLY_PCI_CFG_RINDEX,
   6680 			    (caddr_t *)&hba->pci_addr,
   6681 			    0, 0, &emlxs_dev_acc_attr, &hba->pci_acc_handle);
   6682 			if (status != DDI_SUCCESS) {
   6683 				EMLXS_MSGF(EMLXS_CONTEXT,
   6684 				    &emlxs_attach_failed_msg,
   6685 				    "(SBUS) ddi_regs_map_setup PCI failed. "
   6686 				    "status=%x", status);
   6687 				goto failed;
   6688 			}
   6689 		}
   6690 
   6691 		if (hba->sbus_pci_handle == 0) {
   6692 			status = ddi_regs_map_setup(dip,
   6693 			    SBUS_TITAN_PCI_CFG_RINDEX,
   6694 			    (caddr_t *)&hba->sbus_pci_addr,
   6695 			    0, 0, &dev_attr, &hba->sbus_pci_handle);
   6696 			if (status != DDI_SUCCESS) {
   6697 				EMLXS_MSGF(EMLXS_CONTEXT,
   6698 				    &emlxs_attach_failed_msg,
   6699 				    "(SBUS) ddi_regs_map_setup TITAN PCI "
   6700 				    "failed. status=%x", status);
   6701 				goto failed;
   6702 			}
   6703 		}
   6704 
   6705 	} else {	/* ****** PCI ****** */
   6706 
   6707 		if (hba->pci_acc_handle == 0) {
   6708 			status = ddi_regs_map_setup(dip,
   6709 			    PCI_CFG_RINDEX,
   6710 			    (caddr_t *)&hba->pci_addr,
   6711 			    0, 0, &emlxs_dev_acc_attr, &hba->pci_acc_handle);
   6712 			if (status != DDI_SUCCESS) {
   6713 				EMLXS_MSGF(EMLXS_CONTEXT,
   6714 				    &emlxs_attach_failed_msg,
   6715 				    "(PCI) ddi_regs_map_setup PCI failed. "
   6716 				    "status=%x", status);
   6717 				goto failed;
   6718 			}
   6719 		}
   6720 #ifdef EMLXS_I386
   6721 		/* Setting up PCI configure space */
   6722 		(void) ddi_put16(hba->pci_acc_handle,
   6723 		    (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER),
   6724 		    CMD_CFG_VALUE | CMD_IO_ENBL);
   6725 
   6726 #ifdef FMA_SUPPORT
   6727 		if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
   6728 		    != DDI_FM_OK) {
   6729 			EMLXS_MSGF(EMLXS_CONTEXT,
   6730 			    &emlxs_invalid_access_handle_msg, NULL);
   6731 			goto failed;
   6732 		}
   6733 #endif  /* FMA_SUPPORT */
   6734 
   6735 #endif	/* EMLXS_I386 */
   6736 
   6737 	}
   6738 	return (0);
   6739 
   6740 failed:
   6741 
   6742 	emlxs_unmap_bus(hba);
   6743 	return (ENOMEM);
   6744 
   6745 } /* emlxs_map_bus() */
   6746 
   6747 
   6748 extern void
   6749 emlxs_unmap_bus(emlxs_hba_t *hba)
   6750 {
   6751 	if (hba->pci_acc_handle) {
   6752 		(void) ddi_regs_map_free(&hba->pci_acc_handle);
   6753 		hba->pci_acc_handle = 0;
   6754 	}
   6755 
   6756 	if (hba->sbus_pci_handle) {
   6757 		(void) ddi_regs_map_free(&hba->sbus_pci_handle);
   6758 		hba->sbus_pci_handle = 0;
   6759 	}
   6760 
   6761 	return;
   6762 
   6763 } /* emlxs_unmap_bus() */
   6764 
   6765 
   6766 static int
   6767 emlxs_get_props(emlxs_hba_t *hba)
   6768 {
   6769 	emlxs_config_t	*cfg;
   6770 	uint32_t	i;
   6771 	char		string[256];
   6772 	uint32_t	new_value;
   6773 
   6774 	/* Initialize each parameter */
   6775 	for (i = 0; i < NUM_CFG_PARAM; i++) {
   6776 		cfg = &hba->config[i];
   6777 
   6778 		/* Ensure strings are terminated */
   6779 		cfg->string[(EMLXS_CFG_STR_SIZE-1)] = 0;
   6780 		cfg->help[(EMLXS_CFG_HELP_SIZE-1)]  = 0;
   6781 
   6782 		/* Set the current value to the default value */
   6783 		new_value = cfg->def;
   6784 
   6785 		/* First check for the global setting */
   6786 		new_value = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY,
   6787 		    (void *)hba->dip, DDI_PROP_DONTPASS,
   6788 		    cfg->string, new_value);
   6789 
   6790 		/* Now check for the per adapter ddiinst setting */
   6791 		(void) sprintf(string, "%s%d-%s", DRIVER_NAME, hba->ddiinst,
   6792 		    cfg->string);
   6793 
   6794 		new_value = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY,
   6795 		    (void *)hba->dip, DDI_PROP_DONTPASS, string, new_value);
   6796 
   6797 		/* Now check the parameter */
   6798 		cfg->current = emlxs_check_parm(hba, i, new_value);
   6799 	}
   6800 
   6801 	return (0);
   6802 
   6803 } /* emlxs_get_props() */
   6804 
   6805 
   6806 extern uint32_t
   6807 emlxs_check_parm(emlxs_hba_t *hba, uint32_t index, uint32_t new_value)
   6808 {
   6809 	emlxs_port_t	*port = &PPORT;
   6810 	uint32_t	i;
   6811 	emlxs_config_t	*cfg;
   6812 	emlxs_vpd_t	*vpd = &VPD;
   6813 
   6814 	if (index > NUM_CFG_PARAM) {
   6815 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   6816 		    "emlxs_check_parm failed. Invalid index = %d", index);
   6817 
   6818 		return (new_value);
   6819 	}
   6820 
   6821 	cfg = &hba->config[index];
   6822 
   6823 	if (new_value > cfg->hi) {
   6824 		new_value = cfg->def;
   6825 	} else if (new_value < cfg->low) {
   6826 		new_value = cfg->def;
   6827 	}
   6828 
   6829 	/* Perform additional checks */
   6830 	switch (index) {
   6831 	case CFG_NPIV_ENABLE:
   6832 		if (hba->tgt_mode) {
   6833 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
   6834 			    "enable-npiv: Not supported in target mode. "
   6835 			    "Disabling.");
   6836 
   6837 			new_value = 0;
   6838 		}
   6839 		break;
   6840 
   6841 #ifdef DHCHAP_SUPPORT
   6842 	case CFG_AUTH_ENABLE:
   6843 		if (hba->tgt_mode) {
   6844 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
   6845 			    "enable-auth: Not supported in target mode. "
   6846 			    "Disabling.");
   6847 
   6848 			new_value = 0;
   6849 		}
   6850 		break;
   6851 #endif /* DHCHAP_SUPPORT */
   6852 
   6853 	case CFG_NUM_NODES:
   6854 		switch (new_value) {
   6855 		case 1:
   6856 		case 2:
   6857 			/* Must have at least 3 if not 0 */
   6858 			return (3);
   6859 
   6860 		default:
   6861 			break;
   6862 		}
   6863 		break;
   6864 
   6865 	case CFG_LINK_SPEED:
   6866 		if (vpd->link_speed) {
   6867 			switch (new_value) {
   6868 			case 0:
   6869 				break;
   6870 
   6871 			case 1:
   6872 				if (!(vpd->link_speed & LMT_1GB_CAPABLE)) {
   6873 					new_value = 0;
   6874 
   6875 					EMLXS_MSGF(EMLXS_CONTEXT,
   6876 					    &emlxs_init_msg,
   6877 					    "link-speed: 1Gb not supported "
   6878 					    "by adapter. Switching to auto "
   6879 					    "detect.");
   6880 				}
   6881 				break;
   6882 
   6883 			case 2:
   6884 				if (!(vpd->link_speed & LMT_2GB_CAPABLE)) {
   6885 					new_value = 0;
   6886 
   6887 					EMLXS_MSGF(EMLXS_CONTEXT,
   6888 					    &emlxs_init_msg,
   6889 					    "link-speed: 2Gb not supported "
   6890 					    "by adapter. Switching to auto "
   6891 					    "detect.");
   6892 				}
   6893 				break;
   6894 			case 4:
   6895 				if (!(vpd->link_speed & LMT_4GB_CAPABLE)) {
   6896 					new_value = 0;
   6897 
   6898 					EMLXS_MSGF(EMLXS_CONTEXT,
   6899 					    &emlxs_init_msg,
   6900 					    "link-speed: 4Gb not supported "
   6901 					    "by adapter. Switching to auto "
   6902 					    "detect.");
   6903 				}
   6904 				break;
   6905 
   6906 			case 8:
   6907 				if (!(vpd->link_speed & LMT_8GB_CAPABLE)) {
   6908 					new_value = 0;
   6909 
   6910 					EMLXS_MSGF(EMLXS_CONTEXT,
   6911 					    &emlxs_init_msg,
   6912 					    "link-speed: 8Gb not supported "
   6913 					    "by adapter. Switching to auto "
   6914 					    "detect.");
   6915 				}
   6916 				break;
   6917 
   6918 			case 10:
   6919 				if (!(vpd->link_speed & LMT_10GB_CAPABLE)) {
   6920 					new_value = 0;
   6921 
   6922 					EMLXS_MSGF(EMLXS_CONTEXT,
   6923 					    &emlxs_init_msg,
   6924 					    "link-speed: 10Gb not supported "
   6925 					    "by adapter. Switching to auto "
   6926 					    "detect.");
   6927 				}
   6928 				break;
   6929 
   6930 			default:
   6931 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
   6932 				    "link-speed: Invalid value=%d provided. "
   6933 				    "Switching to auto detect.",
   6934 				    new_value);
   6935 
   6936 				new_value = 0;
   6937 			}
   6938 		} else {	/* Perform basic validity check */
   6939 
   6940 			/* Perform additional check on link speed */
   6941 			switch (new_value) {
   6942 			case 0:
   6943 			case 1:
   6944 			case 2:
   6945 			case 4:
   6946 			case 8:
   6947 			case 10:
   6948 				/* link-speed is a valid choice */
   6949 				break;
   6950 
   6951 			default:
   6952 				new_value = cfg->def;
   6953 			}
   6954 		}
   6955 		break;
   6956 
   6957 	case CFG_TOPOLOGY:
   6958 		/* Perform additional check on topology */
   6959 		switch (new_value) {
   6960 		case 0:
   6961 		case 2:
   6962 		case 4:
   6963 		case 6:
   6964 			/* topology is a valid choice */
   6965 			break;
   6966 
   6967 		default:
   6968 			return (cfg->def);
   6969 		}
   6970 		break;
   6971 
   6972 #ifdef DHCHAP_SUPPORT
   6973 	case CFG_AUTH_TYPE:
   6974 	{
   6975 		uint32_t shift;
   6976 		uint32_t mask;
   6977 
   6978 		/* Perform additional check on auth type */
   6979 		shift = 12;
   6980 		mask  = 0xF000;
   6981 		for (i = 0; i < 4; i++) {
   6982 			if (((new_value & mask) >> shift) > DFC_AUTH_TYPE_MAX) {
   6983 				return (cfg->def);
   6984 			}
   6985 
   6986 			shift -= 4;
   6987 			mask >>= 4;
   6988 		}
   6989 		break;
   6990 	}
   6991 
   6992 	case CFG_AUTH_HASH:
   6993 	{
   6994 		uint32_t shift;
   6995 		uint32_t mask;
   6996 
   6997 		/* Perform additional check on auth hash */
   6998 		shift = 12;
   6999 		mask  = 0xF000;
   7000 		for (i = 0; i < 4; i++) {
   7001 			if (((new_value & mask) >> shift) > DFC_AUTH_HASH_MAX) {
   7002 				return (cfg->def);
   7003 			}
   7004 
   7005 			shift -= 4;
   7006 			mask >>= 4;
   7007 		}
   7008 		break;
   7009 	}
   7010 
   7011 	case CFG_AUTH_GROUP:
   7012 	{
   7013 		uint32_t shift;
   7014 		uint32_t mask;
   7015 
   7016 		/* Perform additional check on auth group */
   7017 		shift = 28;
   7018 		mask  = 0xF0000000;
   7019 		for (i = 0; i < 8; i++) {
   7020 			if (((new_value & mask) >> shift) >
   7021 			    DFC_AUTH_GROUP_MAX) {
   7022 				return (cfg->def);
   7023 			}
   7024 
   7025 			shift -= 4;
   7026 			mask >>= 4;
   7027 		}
   7028 		break;
   7029 	}
   7030 
   7031 	case CFG_AUTH_INTERVAL:
   7032 		if (new_value < 10) {
   7033 			return (10);
   7034 		}
   7035 		break;
   7036 
   7037 
   7038 #endif /* DHCHAP_SUPPORT */
   7039 
   7040 	} /* switch */
   7041 
   7042 	return (new_value);
   7043 
   7044 } /* emlxs_check_parm() */
   7045 
   7046 
   7047 extern uint32_t
   7048 emlxs_set_parm(emlxs_hba_t *hba, uint32_t index, uint32_t new_value)
   7049 {
   7050 	emlxs_port_t	*port = &PPORT;
   7051 	emlxs_port_t	*vport;
   7052 	uint32_t	vpi;
   7053 	emlxs_config_t	*cfg;
   7054 	uint32_t	old_value;
   7055 
   7056 	if (index > NUM_CFG_PARAM) {
   7057 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   7058 		    "emlxs_set_parm failed. Invalid index = %d", index);
   7059 
   7060 		return ((uint32_t)FC_FAILURE);
   7061 	}
   7062 
   7063 	cfg = &hba->config[index];
   7064 
   7065 	if (!(cfg->flags & PARM_DYNAMIC)) {
   7066 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   7067 		    "emlxs_set_parm failed. %s is not dynamic.", cfg->string);
   7068 
   7069 		return ((uint32_t)FC_FAILURE);
   7070 	}
   7071 
   7072 	/* Check new value */
   7073 	old_value = new_value;
   7074 	new_value = emlxs_check_parm(hba, index, new_value);
   7075 
   7076 	if (old_value != new_value) {
   7077 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   7078 		    "emlxs_set_parm: %s invalid. 0x%x --> 0x%x",
   7079 		    cfg->string, old_value, new_value);
   7080 	}
   7081 
   7082 	/* Return now if no actual change */
   7083 	if (new_value == cfg->current) {
   7084 		return (FC_SUCCESS);
   7085 	}
   7086 
   7087 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
   7088 	    "emlxs_set_parm: %s changing. 0x%x --> 0x%x",
   7089 	    cfg->string, cfg->current, new_value);
   7090 
   7091 	old_value = cfg->current;
   7092 	cfg->current = new_value;
   7093 
   7094 	/* React to change if needed */
   7095 	switch (index) {
   7096 
   7097 	case CFG_PCI_MAX_READ:
   7098 		/* Update MXR */
   7099 		emlxs_pcix_mxr_update(hba, 1);
   7100 		break;
   7101 
   7102 	case CFG_SLI_MODE:
   7103 		/* Check SLI mode */
   7104 		if ((hba->sli_mode == 3) && (new_value == 2)) {
   7105 			/* All vports must be disabled first */
   7106 			for (vpi = 1; vpi < MAX_VPORTS; vpi++) {
   7107 				vport = &VPORT(vpi);
   7108 
   7109 				if (vport->flag & EMLXS_PORT_ENABLE) {
   7110 					/* Reset current value */
   7111 					cfg->current = old_value;
   7112 
   7113 					EMLXS_MSGF(EMLXS_CONTEXT,
   7114 					    &emlxs_sfs_debug_msg,
   7115 					    "emlxs_set_parm failed. %s: vpi=%d "
   7116 					    "still enabled. Value restored to "
   7117 					    "0x%x.", cfg->string, vpi,
   7118 					    old_value);
   7119 
   7120 					return (2);
   7121 				}
   7122 			}
   7123 		}
   7124 		break;
   7125 
   7126 	case CFG_NPIV_ENABLE:
   7127 		/* Check if NPIV is being disabled */
   7128 		if ((old_value == 1) && (new_value == 0)) {
   7129 			/* All vports must be disabled first */
   7130 			for (vpi = 1; vpi < MAX_VPORTS; vpi++) {
   7131 				vport = &VPORT(vpi);
   7132 
   7133 				if (vport->flag & EMLXS_PORT_ENABLE) {
   7134 					/* Reset current value */
   7135 					cfg->current = old_value;
   7136 
   7137 					EMLXS_MSGF(EMLXS_CONTEXT,
   7138 					    &emlxs_sfs_debug_msg,
   7139 					    "emlxs_set_parm failed. %s: vpi=%d "
   7140 					    "still enabled. Value restored to "
   7141 					    "0x%x.", cfg->string, vpi,
   7142 					    old_value);
   7143 
   7144 					return (2);
   7145 				}
   7146 			}
   7147 		}
   7148 
   7149 		/* Trigger adapter reset */
   7150 		/* (void) emlxs_reset(port, FC_FCA_RESET); */
   7151 
   7152 		break;
   7153 
   7154 
   7155 	case CFG_VPORT_RESTRICTED:
   7156 		for (vpi = 0; vpi < MAX_VPORTS; vpi++) {
   7157 			vport = &VPORT(vpi);
   7158 
   7159 			if (!(vport->flag & EMLXS_PORT_CONFIG)) {
   7160 				continue;
   7161 			}
   7162 
   7163 			if (vport->options & EMLXS_OPT_RESTRICT_MASK) {
   7164 				continue;
   7165 			}
   7166 
   7167 			if (new_value) {
   7168 				vport->flag |= EMLXS_PORT_RESTRICTED;
   7169 			} else {
   7170 				vport->flag &= ~EMLXS_PORT_RESTRICTED;
   7171 			}
   7172 		}
   7173 
   7174 		break;
   7175 
   7176 #ifdef DHCHAP_SUPPORT
   7177 	case CFG_AUTH_ENABLE:
   7178 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
   7179 		break;
   7180 
   7181 	case CFG_AUTH_TMO:
   7182 		hba->auth_cfg.authentication_timeout = cfg->current;
   7183 		break;
   7184 
   7185 	case CFG_AUTH_MODE:
   7186 		hba->auth_cfg.authentication_mode = cfg->current;
   7187 		break;
   7188 
   7189 	case CFG_AUTH_BIDIR:
   7190 		hba->auth_cfg.bidirectional = cfg->current;
   7191 		break;
   7192 
   7193 	case CFG_AUTH_TYPE:
   7194 		hba->auth_cfg.authentication_type_priority[0] =
   7195 		    (cfg->current & 0xF000) >> 12;
   7196 		hba->auth_cfg.authentication_type_priority[1] =
   7197 		    (cfg->current & 0x0F00) >> 8;
   7198 		hba->auth_cfg.authentication_type_priority[2] =
   7199 		    (cfg->current & 0x00F0) >> 4;
   7200 		hba->auth_cfg.authentication_type_priority[3] =
   7201 		    (cfg->current & 0x000F);
   7202 		break;
   7203 
   7204 	case CFG_AUTH_HASH:
   7205 		hba->auth_cfg.hash_priority[0] =
   7206 		    (cfg->current & 0xF000) >> 12;
   7207 		hba->auth_cfg.hash_priority[1] = (cfg->current & 0x0F00)>>8;
   7208 		hba->auth_cfg.hash_priority[2] = (cfg->current & 0x00F0)>>4;
   7209 		hba->auth_cfg.hash_priority[3] = (cfg->current & 0x000F);
   7210 		break;
   7211 
   7212 	case CFG_AUTH_GROUP:
   7213 		hba->auth_cfg.dh_group_priority[0] =
   7214 		    (cfg->current & 0xF0000000) >> 28;
   7215 		hba->auth_cfg.dh_group_priority[1] =
   7216 		    (cfg->current & 0x0F000000) >> 24;
   7217 		hba->auth_cfg.dh_group_priority[2] =
   7218 		    (cfg->current & 0x00F00000) >> 20;
   7219 		hba->auth_cfg.dh_group_priority[3] =
   7220 		    (cfg->current & 0x000F0000) >> 16;
   7221 		hba->auth_cfg.dh_group_priority[4] =
   7222 		    (cfg->current & 0x0000F000) >> 12;
   7223 		hba->auth_cfg.dh_group_priority[5] =
   7224 		    (cfg->current & 0x00000F00) >> 8;
   7225 		hba->auth_cfg.dh_group_priority[6] =
   7226 		    (cfg->current & 0x000000F0) >> 4;
   7227 		hba->auth_cfg.dh_group_priority[7] =
   7228 		    (cfg->current & 0x0000000F);
   7229 		break;
   7230 
   7231 	case CFG_AUTH_INTERVAL:
   7232 		hba->auth_cfg.reauthenticate_time_interval = cfg->current;
   7233 		break;
   7234 #endif /* DHCHAP_SUPPORT */
   7235 
   7236 	}
   7237 
   7238 	return (FC_SUCCESS);
   7239 
   7240 } /* emlxs_set_parm() */
   7241 
   7242 
   7243 /*
   7244  * emlxs_mem_alloc  OS specific routine for memory allocation / mapping
   7245  *
   7246  * The buf_info->flags field describes the memory operation requested.
   7247  *
   7248  * FC_MBUF_PHYSONLY set  requests a supplied virtual address be mapped for DMA
   7249  * Virtual address is supplied in buf_info->virt
   7250  * DMA mapping flag is in buf_info->align
   7251  * (DMA_READ_ONLY, DMA_WRITE_ONLY, DMA_READ_WRITE)
   7252  * The mapped physical address is returned buf_info->phys
   7253  *
   7254  * FC_MBUF_PHYSONLY cleared requests memory be allocated for driver use and
   7255  * if FC_MBUF_DMA is set the memory is also mapped for DMA
   7256  * The byte alignment of the memory request is supplied in buf_info->align
   7257  * The byte size of the memory request is supplied in buf_info->size
   7258  * The virtual address is returned buf_info->virt
   7259  * The mapped physical address is returned buf_info->phys (for FC_MBUF_DMA)
   7260  */
   7261 extern uint8_t *
   7262 emlxs_mem_alloc(emlxs_hba_t *hba, MBUF_INFO *buf_info)
   7263 {
   7264 	emlxs_port_t		*port = &PPORT;
   7265 	ddi_dma_attr_t		dma_attr;
   7266 	ddi_device_acc_attr_t	dev_attr;
   7267 	uint_t			cookie_count;
   7268 	size_t			dma_reallen;
   7269 	ddi_dma_cookie_t	dma_cookie;
   7270 	uint_t			dma_flag;
   7271 	int			status;
   7272 
   7273 	dma_attr = hba->dma_attr_1sg;
   7274 	dev_attr = emlxs_data_acc_attr;
   7275 
   7276 	if (buf_info->flags & FC_MBUF_SNGLSG) {
   7277 		dma_attr.dma_attr_sgllen = 1;
   7278 	}
   7279 
   7280 	if (buf_info->flags & FC_MBUF_DMA32) {
   7281 		dma_attr.dma_attr_addr_hi = (uint64_t)0xffffffff;
   7282 	}
   7283 
   7284 	if (buf_info->flags & FC_MBUF_PHYSONLY) {
   7285 
   7286 		if (buf_info->virt == 0) {
   7287 			goto done;
   7288 		}
   7289 
   7290 		/*
   7291 		 * Allocate the DMA handle for this DMA object
   7292 		 */
   7293 		status = ddi_dma_alloc_handle((void *)hba->dip,
   7294 		    &dma_attr, DDI_DMA_DONTWAIT,
   7295 		    NULL, (ddi_dma_handle_t *)&buf_info->dma_handle);
   7296 		if (status != DDI_SUCCESS) {
   7297 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
   7298 			    "ddi_dma_alloc_handle failed: size=%x align=%x "
   7299 			    "flags=%x", buf_info->size, buf_info->align,
   7300 			    buf_info->flags);
   7301 
   7302 			buf_info->phys = 0;
   7303 			buf_info->dma_handle = 0;
   7304 			goto done;
   7305 		}
   7306 
   7307 		switch (buf_info->align) {
   7308 		case DMA_READ_WRITE:
   7309 			dma_flag = (DDI_DMA_RDWR | DDI_DMA_CONSISTENT);
   7310 			break;
   7311 		case DMA_READ_ONLY:
   7312 			dma_flag = (DDI_DMA_READ | DDI_DMA_CONSISTENT);
   7313 			break;
   7314 		case DMA_WRITE_ONLY:
   7315 			dma_flag = (DDI_DMA_WRITE | DDI_DMA_CONSISTENT);
   7316 			break;
   7317 		}
   7318 
   7319 		/* Map this page of memory */
   7320 		status = ddi_dma_addr_bind_handle(
   7321 		    (ddi_dma_handle_t)buf_info->dma_handle, NULL,
   7322 		    (caddr_t)buf_info->virt, (size_t)buf_info->size,
   7323 		    dma_flag, DDI_DMA_DONTWAIT, NULL, &dma_cookie,
   7324 		    &cookie_count);
   7325 
   7326 		if (status != DDI_DMA_MAPPED || (cookie_count > 1)) {
   7327 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
   7328 			    "ddi_dma_addr_bind_handle failed: status=%x "
   7329 			    "count=%x flags=%x", status, cookie_count,
   7330 			    buf_info->flags);
   7331 
   7332 			(void) ddi_dma_free_handle(
   7333 			    (ddi_dma_handle_t *)&buf_info->dma_handle);
   7334 			buf_info->phys = 0;
   7335 			buf_info->dma_handle = 0;
   7336 			goto done;
   7337 		}
   7338 
   7339 		if (hba->bus_type == SBUS_FC) {
   7340 
   7341 			int32_t burstsizes_limit = 0xff;
   7342 			int32_t ret_burst;
   7343 
   7344 			ret_burst = ddi_dma_burstsizes(
   7345 			    buf_info->dma_handle) & burstsizes_limit;
   7346 			if (ddi_dma_set_sbus64(buf_info->dma_handle,
   7347 			    ret_burst) == DDI_FAILURE) {
   7348 				EMLXS_MSGF(EMLXS_CONTEXT,
   7349 				    &emlxs_mem_alloc_failed_msg,
   7350 				    "ddi_dma_set_sbus64 failed.");
   7351 			}
   7352 		}
   7353 
   7354 		/* Save Physical address */
   7355 		buf_info->phys = dma_cookie.dmac_laddress;
   7356 
   7357 		/*
   7358 		 * Just to be sure, let's add this
   7359 		 */
   7360 		EMLXS_MPDATA_SYNC((ddi_dma_handle_t)buf_info->dma_handle,
   7361 		    (off_t)0, (size_t)buf_info->size, DDI_DMA_SYNC_FORDEV);
   7362 
   7363 	} else if (buf_info->flags & (FC_MBUF_DMA|FC_MBUF_DMA32)) {
   7364 
   7365 		dma_attr.dma_attr_align = buf_info->align;
   7366 
   7367 		/*
   7368 		 * Allocate the DMA handle for this DMA object
   7369 		 */
   7370 		status = ddi_dma_alloc_handle((void *)hba->dip, &dma_attr,
   7371 		    DDI_DMA_DONTWAIT, NULL,
   7372 		    (ddi_dma_handle_t *)&buf_info->dma_handle);
   7373 		if (status != DDI_SUCCESS) {
   7374 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
   7375 			    "ddi_dma_alloc_handle failed: size=%x align=%x "
   7376 			    "flags=%x", buf_info->size, buf_info->align,
   7377 			    buf_info->flags);
   7378 
   7379 			buf_info->virt = 0;
   7380 			buf_info->phys = 0;
   7381 			buf_info->data_handle = 0;
   7382 			buf_info->dma_handle = 0;
   7383 			goto done;
   7384 		}
   7385 
   7386 		status = ddi_dma_mem_alloc(
   7387 		    (ddi_dma_handle_t)buf_info->dma_handle,
   7388 		    (size_t)buf_info->size, &dev_attr, DDI_DMA_CONSISTENT,
   7389 		    DDI_DMA_DONTWAIT, NULL, (caddr_t *)&buf_info->virt,
   7390 		    &dma_reallen, (ddi_acc_handle_t *)&buf_info->data_handle);
   7391 
   7392 		if ((status != DDI_SUCCESS) || (buf_info->size > dma_reallen)) {
   7393 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
   7394 			    "ddi_dma_mem_alloc failed: size=%x align=%x "
   7395 			    "flags=%x", buf_info->size, buf_info->align,
   7396 			    buf_info->flags);
   7397 
   7398 			(void) ddi_dma_free_handle(
   7399 			    (ddi_dma_handle_t *)&buf_info->dma_handle);
   7400 
   7401 			buf_info->virt = 0;
   7402 			buf_info->phys = 0;
   7403 			buf_info->data_handle = 0;
   7404 			buf_info->dma_handle = 0;
   7405 			goto done;
   7406 		}
   7407 
   7408 		/* Map this page of memory */
   7409 		status = ddi_dma_addr_bind_handle(
   7410 		    (ddi_dma_handle_t)buf_info->dma_handle, NULL,
   7411 		    (caddr_t)buf_info->virt, (size_t)buf_info->size,
   7412 		    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
   7413 		    &dma_cookie, &cookie_count);
   7414 
   7415 		if (status != DDI_DMA_MAPPED || (cookie_count > 1)) {
   7416 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
   7417 			    "ddi_dma_addr_bind_handle failed: status=%x "
   7418 			    "count=%d size=%x align=%x flags=%x", status,
   7419 			    cookie_count, buf_info->size, buf_info->align,
   7420 			    buf_info->flags);
   7421 
   7422 			(void) ddi_dma_mem_free(
   7423 			    (ddi_acc_handle_t *)&buf_info->data_handle);
   7424 			(void) ddi_dma_free_handle(
   7425 			    (ddi_dma_handle_t *)&buf_info->dma_handle);
   7426 
   7427 			buf_info->virt = 0;
   7428 			buf_info->phys = 0;
   7429 			buf_info->dma_handle = 0;
   7430 			buf_info->data_handle = 0;
   7431 			goto done;
   7432 		}
   7433 
   7434 		if (hba->bus_type == SBUS_FC) {
   7435 			int32_t burstsizes_limit = 0xff;
   7436 			int32_t ret_burst;
   7437 
   7438 			ret_burst =
   7439 			    ddi_dma_burstsizes(buf_info->
   7440 			    dma_handle) & burstsizes_limit;
   7441 			if (ddi_dma_set_sbus64(buf_info->dma_handle,
   7442 			    ret_burst) == DDI_FAILURE) {
   7443 				EMLXS_MSGF(EMLXS_CONTEXT,
   7444 				    &emlxs_mem_alloc_failed_msg,
   7445 				    "ddi_dma_set_sbus64 failed.");
   7446 			}
   7447 		}
   7448 
   7449 		/* Save Physical address */
   7450 		buf_info->phys = dma_cookie.dmac_laddress;
   7451 
   7452 		/* Just to be sure, let's add this */
   7453 		EMLXS_MPDATA_SYNC((ddi_dma_handle_t)buf_info->dma_handle,
   7454 		    (off_t)0, (size_t)buf_info->size, DDI_DMA_SYNC_FORDEV);
   7455 
   7456 	} else {	/* allocate virtual memory */
   7457 
   7458 		buf_info->virt =
   7459 		    (uint32_t *)kmem_zalloc((size_t)buf_info->size,
   7460 		    KM_NOSLEEP);
   7461 		buf_info->phys = 0;
   7462 		buf_info->data_handle = 0;
   7463 		buf_info->dma_handle = 0;
   7464 
   7465 		if (buf_info->virt == (uint32_t *)0) {
   7466 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
   7467 			    "size=%x flags=%x", buf_info->size,
   7468 			    buf_info->flags);
   7469 		}
   7470 
   7471 	}
   7472 
   7473 done:
   7474 
   7475 	return ((uint8_t *)buf_info->virt);
   7476 
   7477 } /* emlxs_mem_alloc() */
   7478 
   7479 
   7480 
   7481 /*
   7482  * emlxs_mem_free:
   7483  *
   7484  * OS specific routine for memory de-allocation / unmapping
   7485  *
   7486  * The buf_info->flags field describes the memory operation requested.
   7487  *
   7488  * FC_MBUF_PHYSONLY set  requests a supplied virtual address be unmapped
   7489  * for DMA, but not freed. The mapped physical address to be unmapped is in
   7490  * buf_info->phys
   7491  *
   7492  * FC_MBUF_PHYSONLY cleared requests memory be freed and unmapped for DMA only
   7493  * if FC_MBUF_DMA is set. The mapped physical address to be unmapped is in
   7494  * buf_info->phys. The virtual address to be freed is in buf_info->virt
   7495  */
   7496 /*ARGSUSED*/
   7497 extern void
   7498 emlxs_mem_free(emlxs_hba_t *hba, MBUF_INFO *buf_info)
   7499 {
   7500 	if (buf_info->flags & FC_MBUF_PHYSONLY) {
   7501 
   7502 		if (buf_info->dma_handle) {
   7503 			(void) ddi_dma_unbind_handle(buf_info->dma_handle);
   7504 			(void) ddi_dma_free_handle(
   7505 			    (ddi_dma_handle_t *)&buf_info->dma_handle);
   7506 			buf_info->dma_handle = NULL;
   7507 		}
   7508 
   7509 	} else if (buf_info->flags & (FC_MBUF_DMA|FC_MBUF_DMA32)) {
   7510 
   7511 		if (buf_info->dma_handle) {
   7512 			(void) ddi_dma_unbind_handle(buf_info->dma_handle);
   7513 			(void) ddi_dma_mem_free(
   7514 			    (ddi_acc_handle_t *)&buf_info->data_handle);
   7515 			(void) ddi_dma_free_handle(
   7516 			    (ddi_dma_handle_t *)&buf_info->dma_handle);
   7517 			buf_info->dma_handle = NULL;
   7518 			buf_info->data_handle = NULL;
   7519 		}
   7520 
   7521 	} else {	/* allocate virtual memory */
   7522 
   7523 		if (buf_info->virt) {
   7524 			kmem_free(buf_info->virt, (size_t)buf_info->size);
   7525 			buf_info->virt = NULL;
   7526 		}
   7527 	}
   7528 
   7529 } /* emlxs_mem_free() */
   7530 
   7531 
   7532 /*
   7533  * A channel has a association with a msi id.
   7534  * One msi id could be associated with multiple channels.
   7535  */
   7536 static int
   7537 emlxs_next_chan(emlxs_hba_t *hba, int msi_id)
   7538 {
   7539 	emlxs_config_t *cfg = &CFG;
   7540 	EQ_DESC_t *eqp;
   7541 	int chan;
   7542 	int num_wq;
   7543 
   7544 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
   7545 		/* For SLI4 round robin all WQs associated with the msi_id */
   7546 		eqp = &hba->sli.sli4.eq[msi_id];
   7547 		num_wq = cfg[CFG_NUM_WQ].current;
   7548 
   7549 		mutex_enter(&eqp->lastwq_lock);
   7550 		chan = eqp->lastwq;
   7551 		eqp->lastwq++;
   7552 		if (eqp->lastwq >= ((msi_id + 1) * num_wq)) {
   7553 			eqp->lastwq -= num_wq;
   7554 		}
   7555 		mutex_exit(&eqp->lastwq_lock);
   7556 
   7557 	} else {
   7558 		chan = hba->channel_fcp;
   7559 	}
   7560 	return (chan);
   7561 }
   7562 
   7563 
   7564 static int
   7565 emlxs_select_fcp_channel(emlxs_hba_t *hba, NODELIST *ndlp, int reset)
   7566 {
   7567 	int		channel;
   7568 
   7569 
   7570 	/* IO to FCP2 device or a device reset always use fcp channel */
   7571 	if ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) || reset) {
   7572 		return (hba->channel_fcp);
   7573 	}
   7574 
   7575 	channel = emlxs_next_chan(hba, 0);
   7576 
   7577 
   7578 	/* If channel is closed, then try fcp channel */
   7579 	if (ndlp->nlp_flag[channel] & NLP_CLOSED) {
   7580 		channel = hba->channel_fcp;
   7581 	}
   7582 	return (channel);
   7583 
   7584 }
   7585 
   7586 static int32_t
   7587 emlxs_fast_target_reset(emlxs_port_t *port, emlxs_buf_t *sbp, NODELIST *ndlp)
   7588 {
   7589 	emlxs_hba_t	*hba = HBA;
   7590 	fc_packet_t	*pkt;
   7591 	emlxs_config_t	*cfg;
   7592 	MAILBOXQ	*mbq;
   7593 	MAILBOX		*mb;
   7594 	uint32_t	rc;
   7595 
   7596 	/*
   7597 	 * This routine provides a alternative target reset provessing
   7598 	 * method. Instead of sending an actual target reset to the
   7599 	 * NPort, we will first unreg the login to that NPort. This
   7600 	 * will cause all the outstanding IOs the quickly complete with
   7601 	 * a NO RPI local error. Next we will force the ULP to relogin
   7602 	 * to the NPort by sending an RSCN (for that NPort) to the
   7603 	 * upper layer. This method should result in a fast target
   7604 	 * reset, as far as IOs completing; however, since an actual
   7605 	 * target reset is not sent to the NPort, it is not 100%
   7606 	 * compatable. Things like reservations will not be broken.
   7607 	 * By default this option is DISABLED, and its only enabled thru
   7608 	 * a hidden configuration parameter (fast-tgt-reset).
   7609 	 */
   7610 	rc = FC_TRAN_BUSY;
   7611 	pkt = PRIV2PKT(sbp);
   7612 	cfg = &CFG;
   7613 
   7614 	if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
   7615 		/* issue the mbox cmd to the sli */
   7616 		mb = (MAILBOX *) mbq->mbox;
   7617 		bzero((void *) mb, MAILBOX_CMD_BSIZE);
   7618 		mb->un.varUnregLogin.rpi = (uint16_t)ndlp->nlp_Rpi;
   7619 #ifdef SLI3_SUPPORT
   7620 		mb->un.varUnregLogin.vpi = port->vpi;
   7621 #endif	/* SLI3_SUPPORT */
   7622 		mb->mbxCommand = MBX_UNREG_LOGIN;
   7623 		mb->mbxOwner = OWN_HOST;
   7624 
   7625 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
   7626 		    "Fast Target Reset: unreg rpi=x%x tmr %d", ndlp->nlp_Rpi,
   7627 		    cfg[CFG_FAST_TGT_RESET_TMR].current);
   7628 
   7629 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0)
   7630 		    == MBX_SUCCESS) {
   7631 
   7632 			ndlp->nlp_Rpi = 0;
   7633 
   7634 			mutex_enter(&sbp->mtx);
   7635 			sbp->node = (void *)ndlp;
   7636 			sbp->did = ndlp->nlp_DID;
   7637 			mutex_exit(&sbp->mtx);
   7638 
   7639 			if (pkt->pkt_rsplen) {
   7640 				bzero((uint8_t *)pkt->pkt_resp,
   7641 				    pkt->pkt_rsplen);
   7642 			}
   7643 			if (cfg[CFG_FAST_TGT_RESET_TMR].current) {
   7644 				ndlp->nlp_force_rscn = hba->timer_tics +
   7645 				    cfg[CFG_FAST_TGT_RESET_TMR].current;
   7646 			}
   7647 
   7648 			emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 0);
   7649 		}
   7650 
   7651 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
   7652 		rc = FC_SUCCESS;
   7653 	}
   7654 	return (rc);
   7655 }
   7656 
   7657 static int32_t
   7658 emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp)
   7659 {
   7660 	emlxs_hba_t	*hba = HBA;
   7661 	fc_packet_t	*pkt;
   7662 	emlxs_config_t	*cfg;
   7663 	IOCBQ		*iocbq;
   7664 	IOCB		*iocb;
   7665 	CHANNEL		*cp;
   7666 	NODELIST	*ndlp;
   7667 	char		*cmd;
   7668 	uint16_t	lun;
   7669 	FCP_CMND	*fcp_cmd;
   7670 	uint32_t	did;
   7671 	uint32_t	reset = 0;
   7672 	int		channel;
   7673 	int32_t		rval;
   7674 
   7675 	pkt = PRIV2PKT(sbp);
   7676 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
   7677 
   7678 	/* Find target node object */
   7679 	ndlp = emlxs_node_find_did(port, did);
   7680 
   7681 	if (!ndlp || !ndlp->nlp_active) {
   7682 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
   7683 		    "Node not found. did=%x", did);
   7684 
   7685 		return (FC_BADPACKET);
   7686 	}
   7687 
   7688 	/* When the fcp channel is closed we stop accepting any FCP cmd */
   7689 	if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) {
   7690 		return (FC_TRAN_BUSY);
   7691 	}
   7692 
   7693 	/* Snoop for target or lun reset first */
   7694 	/* We always use FCP channel to send out target/lun reset fcp cmds */
   7695 	/* interrupt affinity only applies to non tgt lun reset fcp cmd */
   7696 
   7697 	cmd = (char *)pkt->pkt_cmd;
   7698 	lun = *((uint16_t *)cmd);
   7699 	lun = LE_SWAP16(lun);
   7700 
   7701 	iocbq = &sbp->iocbq;
   7702 	iocb = &iocbq->iocb;
   7703 	iocbq->node = (void *) ndlp;
   7704 
   7705 	/* Check for target reset */
   7706 	if (cmd[10] & 0x20) {
   7707 		/* prepare iocb */
   7708 		if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp,
   7709 		    hba->channel_fcp)) != FC_SUCCESS) {
   7710 
   7711 			if (rval == 0xff) {
   7712 				emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
   7713 				    0, 1);
   7714 				rval = FC_SUCCESS;
   7715 			}
   7716 
   7717 			return (rval);
   7718 		}
   7719 
   7720 		mutex_enter(&sbp->mtx);
   7721 		sbp->pkt_flags |= PACKET_FCP_TGT_RESET;
   7722 		sbp->pkt_flags |= PACKET_POLLED;
   7723 		mutex_exit(&sbp->mtx);
   7724 
   7725 #ifdef SAN_DIAG_SUPPORT
   7726 		emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_TGTRESET,
   7727 		    (HBA_WWN *)&ndlp->nlp_portname, -1);
   7728 #endif	/* SAN_DIAG_SUPPORT */
   7729 
   7730 		iocbq->flag |= IOCB_PRIORITY;
   7731 
   7732 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
   7733 		    "Target Reset: did=%x", did);
   7734 
   7735 		cfg = &CFG;
   7736 		if (cfg[CFG_FAST_TGT_RESET].current) {
   7737 			if (emlxs_fast_target_reset(port, sbp, ndlp) ==
   7738 			    FC_SUCCESS) {
   7739 				return (FC_SUCCESS);
   7740 			}
   7741 		}
   7742 
   7743 		/* Close the node for any further normal IO */
   7744 		emlxs_node_close(port, ndlp, hba->channel_fcp,
   7745 		    pkt->pkt_timeout);
   7746 
   7747 		/* Flush the IO's on the tx queues */
   7748 		(void) emlxs_tx_node_flush(port, ndlp,
   7749 		    &hba->chan[hba->channel_fcp], 0, sbp);
   7750 
   7751 		/* This is the target reset fcp cmd */
   7752 		reset = 1;
   7753 	}
   7754 
   7755 	/* Check for lun reset */
   7756 	else if (cmd[10] & 0x10) {
   7757 		/* prepare iocb */
   7758 		if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp,
   7759 		    hba->channel_fcp)) != FC_SUCCESS) {
   7760 
   7761 			if (rval == 0xff) {
   7762 				emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
   7763 				    0, 1);
   7764 				rval = FC_SUCCESS;
   7765 			}
   7766 
   7767 			return (rval);
   7768 		}
   7769 
   7770 		mutex_enter(&sbp->mtx);
   7771 		sbp->pkt_flags |= PACKET_FCP_LUN_RESET;
   7772 		sbp->pkt_flags |= PACKET_POLLED;
   7773 		mutex_exit(&sbp->mtx);
   7774 
   7775 #ifdef SAN_DIAG_SUPPORT
   7776 		emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_LUNRESET,
   7777 		    (HBA_WWN *)&ndlp->nlp_portname, lun);
   7778 #endif	/* SAN_DIAG_SUPPORT */
   7779 
   7780 		iocbq->flag |= IOCB_PRIORITY;
   7781 
   7782 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
   7783 		    "LUN Reset: did=%x LUN=%02x02x", did, cmd[0], cmd[1]);
   7784 
   7785 		/* Flush the IO's on the tx queues for this lun */
   7786 		(void) emlxs_tx_lun_flush(port, ndlp, lun, sbp);
   7787 
   7788 		/* This is the lun reset fcp cmd */
   7789 		reset = 1;
   7790 	}
   7791 
   7792 	channel = emlxs_select_fcp_channel(hba, ndlp, reset);
   7793 
   7794 #ifdef SAN_DIAG_SUPPORT
   7795 	sbp->sd_start_time = gethrtime();
   7796 #endif /* SAN_DIAG_SUPPORT */
   7797 
   7798 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
   7799 	emlxs_swap_fcp_pkt(sbp);
   7800 #endif	/* EMLXS_MODREV2X */
   7801 
   7802 	fcp_cmd = (FCP_CMND *) pkt->pkt_cmd;
   7803 
   7804 	if (fcp_cmd->fcpCntl1 == FCP_QTYPE_UNTAGGED) {
   7805 		fcp_cmd->fcpCntl1 = FCP_QTYPE_SIMPLE;
   7806 	}
   7807 
   7808 	if (reset == 0) {
   7809 		/*
   7810 		 * tgt lun reset fcp cmd has been prepared
   7811 		 * separately in the beginning
   7812 		 */
   7813 		if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp,
   7814 		    channel)) != FC_SUCCESS) {
   7815 
   7816 			if (rval == 0xff) {
   7817 				emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
   7818 				    0, 1);
   7819 				rval = FC_SUCCESS;
   7820 			}
   7821 
   7822 			return (rval);
   7823 		}
   7824 	}
   7825 
   7826 	cp = &hba->chan[channel];
   7827 	cp->ulpSendCmd++;
   7828 
   7829 	/* Initalize sbp */
   7830 	mutex_enter(&sbp->mtx);
   7831 	sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
   7832 	    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
   7833 	sbp->node = (void *)ndlp;
   7834 	sbp->lun = lun;
   7835 	sbp->class = iocb->ULPCLASS;
   7836 	sbp->did = ndlp->nlp_DID;
   7837 	mutex_exit(&sbp->mtx);
   7838 
   7839 	if (pkt->pkt_cmdlen) {
   7840 		EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
   7841 		    DDI_DMA_SYNC_FORDEV);
   7842 	}
   7843 
   7844 	if (pkt->pkt_datalen && pkt->pkt_tran_type == FC_PKT_FCP_WRITE) {
   7845 		EMLXS_MPDATA_SYNC(pkt->pkt_data_dma, 0, pkt->pkt_datalen,
   7846 		    DDI_DMA_SYNC_FORDEV);
   7847 	}
   7848 
   7849 	HBASTATS.FcpIssued++;
   7850 
   7851 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
   7852 	return (FC_SUCCESS);
   7853 
   7854 } /* emlxs_send_fcp_cmd() */
   7855 
   7856 
   7857 
   7858 
   7859 #ifdef SFCT_SUPPORT
   7860 static int32_t
   7861 emlxs_send_fct_status(emlxs_port_t *port, emlxs_buf_t *sbp)
   7862 {
   7863 	emlxs_hba_t		*hba = HBA;
   7864 	fc_packet_t		*pkt;
   7865 	IOCBQ			*iocbq;
   7866 	IOCB			*iocb;
   7867 	NODELIST		*ndlp;
   7868 	CHANNEL			*cp;
   7869 	uint16_t		iotag;
   7870 	uint32_t		did;
   7871 	ddi_dma_cookie_t	*cp_cmd;
   7872 
   7873 	pkt = PRIV2PKT(sbp);
   7874 
   7875 	did = sbp->did;
   7876 	ndlp = sbp->node;
   7877 
   7878 	iocbq = &sbp->iocbq;
   7879 	iocb = &iocbq->iocb;
   7880 
   7881 	/* Make sure node is still active */
   7882 	if (!ndlp->nlp_active) {
   7883 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
   7884 		    "*Node not found. did=%x", did);
   7885 
   7886 		return (FC_BADPACKET);
   7887 	}
   7888 
   7889 	/* If gate is closed */
   7890 	if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) {
   7891 		return (FC_TRAN_BUSY);
   7892 	}
   7893 
   7894 	/* Get the iotag by registering the packet */
   7895 	iotag = emlxs_register_pkt(sbp->channel, sbp);
   7896 
   7897 	if (!iotag) {
   7898 		/* No more command slots available, retry later */
   7899 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
   7900 		    "*Adapter Busy. Unable to allocate iotag: did=0x%x", did);
   7901 
   7902 		return (FC_TRAN_BUSY);
   7903 	}
   7904 
   7905 	/* Point of no return */
   7906 
   7907 	cp = sbp->channel;
   7908 	cp->ulpSendCmd++;
   7909 
   7910 #if (EMLXS_MODREV >= EMLXS_MODREV3)
   7911 	cp_cmd = pkt->pkt_cmd_cookie;
   7912 #else
   7913 	cp_cmd  = &pkt->pkt_cmd_cookie;
   7914 #endif	/* >= EMLXS_MODREV3 */
   7915 
   7916 	iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(cp_cmd->dmac_laddress);
   7917 	iocb->un.fcpt64.bdl.addrLow = PADDR_LO(cp_cmd->dmac_laddress);
   7918 	iocb->un.fcpt64.bdl.bdeSize = pkt->pkt_cmdlen;
   7919 	iocb->un.fcpt64.bdl.bdeFlags = 0;
   7920 
   7921 	if (hba->sli_mode < 3) {
   7922 		iocb->ULPBDECOUNT = 1;
   7923 		iocb->ULPLE = 1;
   7924 	} else {	/* SLI3 */
   7925 
   7926 		iocb->ULPBDECOUNT = 0;
   7927 		iocb->ULPLE = 0;
   7928 		iocb->unsli3.ext_iocb.ebde_count = 0;
   7929 	}
   7930 
   7931 	/* Initalize iocbq */
   7932 	iocbq->port = (void *)port;
   7933 	iocbq->node = (void *)ndlp;
   7934 	iocbq->channel = (void *)cp;
   7935 
   7936 	/* Initalize iocb */
   7937 	iocb->ULPCONTEXT = (uint16_t)pkt->pkt_cmd_fhdr.rx_id;
   7938 	iocb->ULPIOTAG = iotag;
   7939 	iocb->ULPRSVDBYTE =
   7940 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
   7941 	iocb->ULPOWNER = OWN_CHIP;
   7942 	iocb->ULPCLASS = sbp->class;
   7943 	iocb->