1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte 
22*fcf3ce44SJohn Forte /*
23*fcf3ce44SJohn Forte  * Copyright 2008 Emulex.  All rights reserved.
24*fcf3ce44SJohn Forte  * Use is subject to License terms.
25*fcf3ce44SJohn Forte  */
26*fcf3ce44SJohn Forte 
27*fcf3ce44SJohn Forte 
28*fcf3ce44SJohn Forte #include "emlxs.h"
29*fcf3ce44SJohn Forte 
30*fcf3ce44SJohn Forte #define	PRIV_LILP_POSIT(port_dev)	port_dev->dev_did.priv_lilp_posit
31*fcf3ce44SJohn Forte #define	HARD_ADDR(port_dev)		port_dev->dev_hard_addr.hard_addr
32*fcf3ce44SJohn Forte #define	HBA_10GBIT	HBA_PORTSPEED_10GBIT
33*fcf3ce44SJohn Forte 
34*fcf3ce44SJohn Forte #ifdef DFC_SUPPORT
35*fcf3ce44SJohn Forte 
36*fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
37*fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_DFC_C);
38*fcf3ce44SJohn Forte 
39*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_rev(emlxs_hba_t *hba,
40*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
41*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_hbainfo(emlxs_hba_t *hba,
42*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
43*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_hbastats(emlxs_hba_t *hba,
44*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
45*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_drvstats(emlxs_hba_t *hba,
46*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
47*fcf3ce44SJohn Forte static int32_t emlxs_dfc_set_diag(emlxs_hba_t *hba,
48*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
49*fcf3ce44SJohn Forte static int32_t emlxs_dfc_send_mbox(emlxs_hba_t *hba,
50*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
51*fcf3ce44SJohn Forte static int32_t emlxs_dfc_read_pci(emlxs_hba_t *hba,
52*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
53*fcf3ce44SJohn Forte static int32_t emlxs_dfc_write_pci(emlxs_hba_t *hba,
54*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
55*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_cfg(emlxs_hba_t *hba,
56*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
57*fcf3ce44SJohn Forte static int32_t emlxs_dfc_set_cfg(emlxs_hba_t *hba,
58*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
59*fcf3ce44SJohn Forte static int32_t emlxs_dfc_send_menlo(emlxs_hba_t *hba,
60*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
61*fcf3ce44SJohn Forte static int32_t emlxs_dfc_send_ct(emlxs_hba_t *hba,
62*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
63*fcf3ce44SJohn Forte static int32_t emlxs_dfc_send_ct_rsp(emlxs_hba_t *hba,
64*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
65*fcf3ce44SJohn Forte static int32_t emlxs_dfc_write_flash(emlxs_hba_t *hba,
66*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
67*fcf3ce44SJohn Forte static int32_t emlxs_dfc_read_flash(emlxs_hba_t *hba,
68*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
69*fcf3ce44SJohn Forte static int32_t emlxs_dfc_send_els(emlxs_hba_t *hba,
70*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
71*fcf3ce44SJohn Forte static int32_t emlxs_dfc_loopback_test(emlxs_hba_t *hba,
72*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
73*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_dump_region(emlxs_hba_t *hba,
74*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
75*fcf3ce44SJohn Forte static int32_t emlxs_dfc_loopback_mode(emlxs_hba_t *hba,
76*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
77*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_ioinfo(emlxs_hba_t *hba,
78*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
79*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_linkinfo(emlxs_hba_t *hba,
80*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
81*fcf3ce44SJohn Forte static int32_t emlxs_dfc_read_mem(emlxs_hba_t *hba,
82*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
83*fcf3ce44SJohn Forte static int32_t emlxs_dfc_write_mem(emlxs_hba_t *hba,
84*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
85*fcf3ce44SJohn Forte static int32_t emlxs_dfc_write_ctlreg(emlxs_hba_t *hba,
86*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
87*fcf3ce44SJohn Forte static int32_t emlxs_dfc_read_ctlreg(emlxs_hba_t *hba,
88*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
89*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_event(emlxs_hba_t *hba,
90*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
91*fcf3ce44SJohn Forte static int32_t emlxs_dfc_set_event(emlxs_hba_t *hba,
92*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
93*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_eventinfo(emlxs_hba_t *hba,
94*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
95*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_nodeinfo(emlxs_hba_t *hba,
96*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
97*fcf3ce44SJohn Forte 
98*fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
99*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_fctstat(emlxs_hba_t *hba,
100*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
101*fcf3ce44SJohn Forte #endif	/* SFCT_SUPPORT */
102*fcf3ce44SJohn Forte #ifdef NPIV_SUPPORT
103*fcf3ce44SJohn Forte static int32_t emlxs_dfc_create_vport(emlxs_hba_t *hba,
104*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
105*fcf3ce44SJohn Forte static int32_t emlxs_dfc_destroy_vport(emlxs_hba_t *hba,
106*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
107*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_vportinfo(emlxs_hba_t *hba,
108*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
109*fcf3ce44SJohn Forte static int32_t emlxs_dfc_npiv_resource(emlxs_hba_t *hba,
110*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
111*fcf3ce44SJohn Forte static int32_t emlxs_dfc_npiv_test(emlxs_hba_t *hba,
112*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
113*fcf3ce44SJohn Forte static emlxs_port_t *emlxs_vport_find_wwpn(emlxs_hba_t *hba,
114*fcf3ce44SJohn Forte 	uint8_t *wwpn);
115*fcf3ce44SJohn Forte #endif	/* NPIV_SUPPORT */
116*fcf3ce44SJohn Forte 
117*fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
118*fcf3ce44SJohn Forte static int32_t emlxs_dfc_init_auth(emlxs_hba_t *hba,
119*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
120*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_auth_cfg(emlxs_hba_t *hba,
121*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
122*fcf3ce44SJohn Forte static int32_t emlxs_dfc_set_auth_cfg(emlxs_hba_t *hba,
123*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
124*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_auth_pwd(emlxs_hba_t *hba,
125*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
126*fcf3ce44SJohn Forte static int32_t emlxs_dfc_set_auth_pwd(emlxs_hba_t *hba,
127*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
128*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_auth_status(emlxs_hba_t *hba,
129*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
130*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_auth_cfg_table(emlxs_hba_t *hba,
131*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
132*fcf3ce44SJohn Forte static int32_t emlxs_dfc_get_auth_key_table(emlxs_hba_t *hba,
133*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
134*fcf3ce44SJohn Forte #endif	/* DHCHAP_SUPPORT */
135*fcf3ce44SJohn Forte 
136*fcf3ce44SJohn Forte static int32_t emlxs_dfc_send_scsi_fcp(emlxs_hba_t *hba,
137*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
138*fcf3ce44SJohn Forte #ifdef FCIO_SUPPORT
139*fcf3ce44SJohn Forte static int32_t emlxs_fcio_manage(emlxs_hba_t *hba,
140*fcf3ce44SJohn Forte 	dfc_t *dfc, int32_t mode);
141*fcf3ce44SJohn Forte #endif	/* FCIO_SUPPORT */
142*fcf3ce44SJohn Forte 
143*fcf3ce44SJohn Forte 
144*fcf3ce44SJohn Forte uint32_t emlxs_loopback_tmo = 60;
145*fcf3ce44SJohn Forte 
146*fcf3ce44SJohn Forte emlxs_table_t emlxs_dfc_table[] =
147*fcf3ce44SJohn Forte {
148*fcf3ce44SJohn Forte 	{EMLXS_GET_HBAINFO, "GET_HBAINFO"},
149*fcf3ce44SJohn Forte 	{EMLXS_GET_REV, "GET_REV"},
150*fcf3ce44SJohn Forte 	{EMLXS_SET_DIAG, "SET_DIAG"},
151*fcf3ce44SJohn Forte 	{EMLXS_SEND_MBOX, "SEND_MBOX"},
152*fcf3ce44SJohn Forte 	{EMLXS_READ_PCI, "READ_PCI"},
153*fcf3ce44SJohn Forte 	{EMLXS_WRITE_PCI, "WRITE_PCI"},
154*fcf3ce44SJohn Forte 	{EMLXS_GET_CFG, "GET_CFG"},
155*fcf3ce44SJohn Forte 	{EMLXS_SET_CFG, "SET_CFG"},
156*fcf3ce44SJohn Forte 	{EMLXS_SEND_CT, "SEND_CT"},
157*fcf3ce44SJohn Forte 	{EMLXS_SEND_CT_RSP, "SEND_CT_RSP"},
158*fcf3ce44SJohn Forte 	{EMLXS_SEND_MENLO, "SEND_MENLO"},
159*fcf3ce44SJohn Forte 	{EMLXS_WRITE_FLASH, "WRITE_FLASH"},
160*fcf3ce44SJohn Forte 	{EMLXS_READ_FLASH, "READ_FLASH"},
161*fcf3ce44SJohn Forte 	{EMLXS_SEND_ELS, "SEND_ELS"},
162*fcf3ce44SJohn Forte 	{EMLXS_LOOPBACK_TEST, "LOOPBACK_TEST"},
163*fcf3ce44SJohn Forte 	{EMLXS_GET_DUMPREGION, "GET_DUMPREGION"},
164*fcf3ce44SJohn Forte 	{EMLXS_LOOPBACK_MODE, "LOOPBACK_MODE"},
165*fcf3ce44SJohn Forte 	{EMLXS_GET_IOINFO, "GET_IOINFO"},
166*fcf3ce44SJohn Forte 	{EMLXS_GET_LINKINFO, "GET_LINKINFO"},
167*fcf3ce44SJohn Forte 	{EMLXS_GET_NODEINFO, "GET_NODEINFO"},
168*fcf3ce44SJohn Forte 	{EMLXS_READ_MEM, "READ_MEM"},
169*fcf3ce44SJohn Forte 	{EMLXS_WRITE_MEM, "WRITE_MEM"},
170*fcf3ce44SJohn Forte 	{EMLXS_WRITE_CTLREG, "WRITE_CTLREG"},
171*fcf3ce44SJohn Forte 	{EMLXS_READ_CTLREG, "READ_CTLREG"},
172*fcf3ce44SJohn Forte 	{EMLXS_SEND_SCSI, "SEND_SCSI"},
173*fcf3ce44SJohn Forte 	{EMLXS_GET_EVENT, "GET_EVENT"},
174*fcf3ce44SJohn Forte 	{EMLXS_SET_EVENT, "SET_EVENT"},
175*fcf3ce44SJohn Forte 	{EMLXS_GET_EVENTINFO, "GET_EVENTINFO"},
176*fcf3ce44SJohn Forte 	{EMLXS_GET_HBASTATS, "GET_HBASTATS"},
177*fcf3ce44SJohn Forte 	{EMLXS_GET_DRVSTATS, "GET_DRVSTATS"},
178*fcf3ce44SJohn Forte 	{EMLXS_CREATE_VPORT, "CREATE_VPORT"},
179*fcf3ce44SJohn Forte 	{EMLXS_DESTROY_VPORT, "DESTROY_VPORT"},
180*fcf3ce44SJohn Forte 	{EMLXS_GET_VPORTINFO, "GET_VPORTINFO"},
181*fcf3ce44SJohn Forte 	{EMLXS_NPIV_RESOURCE, "NPIV_RESOURCE"},
182*fcf3ce44SJohn Forte 	{EMLXS_NPIV_TEST, "NPIV_TEST"},
183*fcf3ce44SJohn Forte 	{EMLXS_INIT_AUTH, "INIT_AUTH"},
184*fcf3ce44SJohn Forte 	{EMLXS_GET_AUTH_CFG, "GET_AUTH_CFG"},
185*fcf3ce44SJohn Forte 	{EMLXS_SET_AUTH_CFG, "SET_AUTH_CFG"},
186*fcf3ce44SJohn Forte 	{EMLXS_GET_AUTH_PASSWORD, "GET_AUTH_PASSWORD"},
187*fcf3ce44SJohn Forte 	{EMLXS_SET_AUTH_PASSWORD, "SET_AUTH_PASSWORD"},
188*fcf3ce44SJohn Forte 	{EMLXS_GET_AUTH_STATUS, "GET_AUTH_STATUS"},
189*fcf3ce44SJohn Forte 	{EMLXS_GET_AUTH_CFG_TABLE, "GET_AUTH_CFG_TABLE"},
190*fcf3ce44SJohn Forte 	{EMLXS_GET_AUTH_KEY_TABLE, "GET_AUTH_KEY_TABLE"},
191*fcf3ce44SJohn Forte 	{EMLXS_FCIO_CMD, "FCIO_CMD"},
192*fcf3ce44SJohn Forte 	{EMLXS_GET_FCTSTAT, "GET_FCTSTAT"},
193*fcf3ce44SJohn Forte 
194*fcf3ce44SJohn Forte };	/* emlxs_dfc_table */
195*fcf3ce44SJohn Forte 
196*fcf3ce44SJohn Forte 
197*fcf3ce44SJohn Forte emlxs_table_t emlxs_dfc_event_table[] =
198*fcf3ce44SJohn Forte {
199*fcf3ce44SJohn Forte 	{FC_REG_LINK_EVENT, "LINK_EVENT"},
200*fcf3ce44SJohn Forte 	{FC_REG_RSCN_EVENT, "RSCN_EVENT"},
201*fcf3ce44SJohn Forte 	{FC_REG_CT_EVENT, "CT_EVENT"},
202*fcf3ce44SJohn Forte 	{FC_REG_DUMP_EVENT, "DUMP_EVENT"},
203*fcf3ce44SJohn Forte 	{FC_REG_TEMP_EVENT, "TEMP_EVENT"},
204*fcf3ce44SJohn Forte 	{FC_REG_FCOE_EVENT, "FCOE_EVENT"},
205*fcf3ce44SJohn Forte 
206*fcf3ce44SJohn Forte };	/* emlxs_dfc_event_table */
207*fcf3ce44SJohn Forte 
208*fcf3ce44SJohn Forte 
209*fcf3ce44SJohn Forte extern char *
210*fcf3ce44SJohn Forte emlxs_dfc_xlate(uint16_t cmd)
211*fcf3ce44SJohn Forte {
212*fcf3ce44SJohn Forte 	static char buffer[32];
213*fcf3ce44SJohn Forte 	uint32_t i;
214*fcf3ce44SJohn Forte 	uint32_t count;
215*fcf3ce44SJohn Forte 
216*fcf3ce44SJohn Forte 	count = sizeof (emlxs_dfc_table) / sizeof (emlxs_table_t);
217*fcf3ce44SJohn Forte 	for (i = 0; i < count; i++) {
218*fcf3ce44SJohn Forte 		if (cmd == emlxs_dfc_table[i].code) {
219*fcf3ce44SJohn Forte 			return (emlxs_dfc_table[i].string);
220*fcf3ce44SJohn Forte 		}
221*fcf3ce44SJohn Forte 	}
222*fcf3ce44SJohn Forte 
223*fcf3ce44SJohn Forte 	(void) sprintf(buffer, "Cmd=0x%x", cmd);
224*fcf3ce44SJohn Forte 	return (buffer);
225*fcf3ce44SJohn Forte 
226*fcf3ce44SJohn Forte } /* emlxs_dfc_xlate() */
227*fcf3ce44SJohn Forte 
228*fcf3ce44SJohn Forte 
229*fcf3ce44SJohn Forte extern char *
230*fcf3ce44SJohn Forte emlxs_dfc_event_xlate(uint32_t event)
231*fcf3ce44SJohn Forte {
232*fcf3ce44SJohn Forte 	static char buffer[32];
233*fcf3ce44SJohn Forte 	uint32_t i;
234*fcf3ce44SJohn Forte 	uint32_t count;
235*fcf3ce44SJohn Forte 
236*fcf3ce44SJohn Forte 	count = sizeof (emlxs_dfc_event_table) / sizeof (emlxs_table_t);
237*fcf3ce44SJohn Forte 	for (i = 0; i < count; i++) {
238*fcf3ce44SJohn Forte 		if (event == emlxs_dfc_event_table[i].code) {
239*fcf3ce44SJohn Forte 			return (emlxs_dfc_event_table[i].string);
240*fcf3ce44SJohn Forte 		}
241*fcf3ce44SJohn Forte 	}
242*fcf3ce44SJohn Forte 
243*fcf3ce44SJohn Forte 	(void) sprintf(buffer, "Event=0x%x", event);
244*fcf3ce44SJohn Forte 	return (buffer);
245*fcf3ce44SJohn Forte 
246*fcf3ce44SJohn Forte } /* emlxs_dfc_event_xlate() */
247*fcf3ce44SJohn Forte 
248*fcf3ce44SJohn Forte 
249*fcf3ce44SJohn Forte 
250*fcf3ce44SJohn Forte extern int32_t
251*fcf3ce44SJohn Forte emlxs_dfc_manage(emlxs_hba_t *hba, void *arg, int32_t mode)
252*fcf3ce44SJohn Forte {
253*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
254*fcf3ce44SJohn Forte 	int rval = 0;
255*fcf3ce44SJohn Forte 	dfc_t *dfc;
256*fcf3ce44SJohn Forte 
257*fcf3ce44SJohn Forte 	if (!(dfc = (dfc_t *)kmem_zalloc(sizeof (dfc_t), KM_SLEEP))) {
258*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
259*fcf3ce44SJohn Forte 		    "%s: Unable to allocate dfc buffer.",
260*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
261*fcf3ce44SJohn Forte 
262*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
263*fcf3ce44SJohn Forte 	}
264*fcf3ce44SJohn Forte #ifdef	_MULTI_DATAMODEL
265*fcf3ce44SJohn Forte 	switch (ddi_model_convert_from(mode & FMODELS)) {
266*fcf3ce44SJohn Forte 	case DDI_MODEL_ILP32:
267*fcf3ce44SJohn Forte 		{
268*fcf3ce44SJohn Forte 			dfc32_t dfc32;
269*fcf3ce44SJohn Forte 
270*fcf3ce44SJohn Forte 			if (ddi_copyin((void *)arg, (void *)&dfc32,
271*fcf3ce44SJohn Forte 			    sizeof (dfc32_t), mode)) {
272*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
273*fcf3ce44SJohn Forte 				    "%s: ddi_copyin failed.",
274*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
275*fcf3ce44SJohn Forte 
276*fcf3ce44SJohn Forte 				rval = DFC_COPYIN_ERROR;
277*fcf3ce44SJohn Forte 				break;
278*fcf3ce44SJohn Forte 			}
279*fcf3ce44SJohn Forte 			dfc->cmd = dfc32.cmd;
280*fcf3ce44SJohn Forte 			dfc->flag = dfc32.flag;
281*fcf3ce44SJohn Forte 			dfc->buf1 = (void *)(unsigned long)dfc32.buf1;
282*fcf3ce44SJohn Forte 			dfc->buf1_size = dfc32.buf1_size;
283*fcf3ce44SJohn Forte 			dfc->data1 = dfc32.data1;
284*fcf3ce44SJohn Forte 			dfc->buf2 = (void *)(unsigned long)dfc32.buf2;
285*fcf3ce44SJohn Forte 			dfc->buf2_size = dfc32.buf2_size;
286*fcf3ce44SJohn Forte 			dfc->data2 = dfc32.data2;
287*fcf3ce44SJohn Forte 			dfc->buf3 = (void *)(unsigned long)dfc32.buf3;
288*fcf3ce44SJohn Forte 			dfc->buf3_size = dfc32.buf3_size;
289*fcf3ce44SJohn Forte 			dfc->data3 = dfc32.data3;
290*fcf3ce44SJohn Forte 			dfc->buf4 = (void *)(unsigned long)dfc32.buf4;
291*fcf3ce44SJohn Forte 			dfc->buf4_size = dfc32.buf4_size;
292*fcf3ce44SJohn Forte 			dfc->data4 = dfc32.data4;
293*fcf3ce44SJohn Forte 
294*fcf3ce44SJohn Forte 			break;
295*fcf3ce44SJohn Forte 		}
296*fcf3ce44SJohn Forte 
297*fcf3ce44SJohn Forte 	case DDI_MODEL_NONE:
298*fcf3ce44SJohn Forte 		if (ddi_copyin((void *)arg, (void *)dfc,
299*fcf3ce44SJohn Forte 		    sizeof (dfc_t), mode)) {
300*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
301*fcf3ce44SJohn Forte 			    "%s: ddi_copyin failed.",
302*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
303*fcf3ce44SJohn Forte 
304*fcf3ce44SJohn Forte 			rval = DFC_COPYIN_ERROR;
305*fcf3ce44SJohn Forte 		}
306*fcf3ce44SJohn Forte 		break;
307*fcf3ce44SJohn Forte 	}
308*fcf3ce44SJohn Forte #else	/* _MULTI_DATAMODEL */
309*fcf3ce44SJohn Forte 	if (ddi_copyin((void *) arg, (void *) dfc, sizeof (dfc_t), mode)) {
310*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
311*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
312*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
313*fcf3ce44SJohn Forte 
314*fcf3ce44SJohn Forte 		rval = DFC_COPYIN_ERROR;
315*fcf3ce44SJohn Forte 	}
316*fcf3ce44SJohn Forte #endif	/* _MULTI_DATAMODEL */
317*fcf3ce44SJohn Forte 
318*fcf3ce44SJohn Forte 
319*fcf3ce44SJohn Forte 	switch (dfc->cmd) {
320*fcf3ce44SJohn Forte 	case EMLXS_GET_HBAINFO:
321*fcf3ce44SJohn Forte 		{
322*fcf3ce44SJohn Forte 
323*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_hbainfo(hba, dfc, mode);
324*fcf3ce44SJohn Forte 
325*fcf3ce44SJohn Forte 			break;
326*fcf3ce44SJohn Forte 		}
327*fcf3ce44SJohn Forte 
328*fcf3ce44SJohn Forte 	case EMLXS_GET_HBASTATS:
329*fcf3ce44SJohn Forte 		{
330*fcf3ce44SJohn Forte 
331*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_hbastats(hba, dfc, mode);
332*fcf3ce44SJohn Forte 
333*fcf3ce44SJohn Forte 			break;
334*fcf3ce44SJohn Forte 		}
335*fcf3ce44SJohn Forte 
336*fcf3ce44SJohn Forte 	case EMLXS_GET_DRVSTATS:
337*fcf3ce44SJohn Forte 		{
338*fcf3ce44SJohn Forte 
339*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_drvstats(hba, dfc, mode);
340*fcf3ce44SJohn Forte 
341*fcf3ce44SJohn Forte 			break;
342*fcf3ce44SJohn Forte 		}
343*fcf3ce44SJohn Forte 
344*fcf3ce44SJohn Forte 	case EMLXS_GET_NODEINFO:
345*fcf3ce44SJohn Forte 		{
346*fcf3ce44SJohn Forte 
347*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_nodeinfo(hba, dfc, mode);
348*fcf3ce44SJohn Forte 
349*fcf3ce44SJohn Forte 			break;
350*fcf3ce44SJohn Forte 		}
351*fcf3ce44SJohn Forte 
352*fcf3ce44SJohn Forte 	case EMLXS_SET_DIAG:
353*fcf3ce44SJohn Forte 		{
354*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
355*fcf3ce44SJohn Forte 			    "%s requested.",
356*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
357*fcf3ce44SJohn Forte 
358*fcf3ce44SJohn Forte 			rval = emlxs_dfc_set_diag(hba, dfc, mode);
359*fcf3ce44SJohn Forte 
360*fcf3ce44SJohn Forte 			break;
361*fcf3ce44SJohn Forte 		}
362*fcf3ce44SJohn Forte 
363*fcf3ce44SJohn Forte 	case EMLXS_SEND_MBOX:
364*fcf3ce44SJohn Forte 		{
365*fcf3ce44SJohn Forte 			rval = emlxs_dfc_send_mbox(hba, dfc, mode);
366*fcf3ce44SJohn Forte 
367*fcf3ce44SJohn Forte 			break;
368*fcf3ce44SJohn Forte 		}
369*fcf3ce44SJohn Forte 
370*fcf3ce44SJohn Forte 	case EMLXS_READ_PCI:
371*fcf3ce44SJohn Forte 		{
372*fcf3ce44SJohn Forte 			rval = emlxs_dfc_read_pci(hba, dfc, mode);
373*fcf3ce44SJohn Forte 
374*fcf3ce44SJohn Forte 			break;
375*fcf3ce44SJohn Forte 		}
376*fcf3ce44SJohn Forte 
377*fcf3ce44SJohn Forte 	case EMLXS_WRITE_PCI:
378*fcf3ce44SJohn Forte 		{
379*fcf3ce44SJohn Forte 			rval = emlxs_dfc_write_pci(hba, dfc, mode);
380*fcf3ce44SJohn Forte 
381*fcf3ce44SJohn Forte 			break;
382*fcf3ce44SJohn Forte 		}
383*fcf3ce44SJohn Forte 
384*fcf3ce44SJohn Forte 	case EMLXS_GET_CFG:
385*fcf3ce44SJohn Forte 		{
386*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
387*fcf3ce44SJohn Forte 			    "%s requested.",
388*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
389*fcf3ce44SJohn Forte 
390*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_cfg(hba, dfc, mode);
391*fcf3ce44SJohn Forte 
392*fcf3ce44SJohn Forte 			break;
393*fcf3ce44SJohn Forte 		}
394*fcf3ce44SJohn Forte 
395*fcf3ce44SJohn Forte 	case EMLXS_SET_CFG:
396*fcf3ce44SJohn Forte 		{
397*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
398*fcf3ce44SJohn Forte 			    "%s requested.",
399*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
400*fcf3ce44SJohn Forte 
401*fcf3ce44SJohn Forte 			rval = emlxs_dfc_set_cfg(hba, dfc, mode);
402*fcf3ce44SJohn Forte 
403*fcf3ce44SJohn Forte 			break;
404*fcf3ce44SJohn Forte 		}
405*fcf3ce44SJohn Forte 
406*fcf3ce44SJohn Forte 	case EMLXS_SEND_CT:
407*fcf3ce44SJohn Forte 		{
408*fcf3ce44SJohn Forte 			rval = emlxs_dfc_send_ct(hba, dfc, mode);
409*fcf3ce44SJohn Forte 
410*fcf3ce44SJohn Forte 			break;
411*fcf3ce44SJohn Forte 		}
412*fcf3ce44SJohn Forte 
413*fcf3ce44SJohn Forte 	case EMLXS_SEND_CT_RSP:
414*fcf3ce44SJohn Forte 		{
415*fcf3ce44SJohn Forte 			rval = emlxs_dfc_send_ct_rsp(hba, dfc, mode);
416*fcf3ce44SJohn Forte 
417*fcf3ce44SJohn Forte 			break;
418*fcf3ce44SJohn Forte 		}
419*fcf3ce44SJohn Forte 
420*fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
421*fcf3ce44SJohn Forte 	case EMLXS_SEND_MENLO:
422*fcf3ce44SJohn Forte 		{
423*fcf3ce44SJohn Forte 			rval = emlxs_dfc_send_menlo(hba, dfc, mode);
424*fcf3ce44SJohn Forte 
425*fcf3ce44SJohn Forte 			break;
426*fcf3ce44SJohn Forte 		}
427*fcf3ce44SJohn Forte #endif	/* MENLO_SUPPORT */
428*fcf3ce44SJohn Forte 
429*fcf3ce44SJohn Forte 	case EMLXS_WRITE_FLASH:
430*fcf3ce44SJohn Forte 		{
431*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
432*fcf3ce44SJohn Forte 			    "%s requested.",
433*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
434*fcf3ce44SJohn Forte 
435*fcf3ce44SJohn Forte 			rval = emlxs_dfc_write_flash(hba, dfc, mode);
436*fcf3ce44SJohn Forte 
437*fcf3ce44SJohn Forte 			break;
438*fcf3ce44SJohn Forte 		}
439*fcf3ce44SJohn Forte 
440*fcf3ce44SJohn Forte 	case EMLXS_READ_FLASH:
441*fcf3ce44SJohn Forte 		{
442*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
443*fcf3ce44SJohn Forte 			    "%s requested.",
444*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
445*fcf3ce44SJohn Forte 
446*fcf3ce44SJohn Forte 			rval = emlxs_dfc_read_flash(hba, dfc, mode);
447*fcf3ce44SJohn Forte 
448*fcf3ce44SJohn Forte 			break;
449*fcf3ce44SJohn Forte 		}
450*fcf3ce44SJohn Forte 
451*fcf3ce44SJohn Forte 	case EMLXS_SEND_ELS:
452*fcf3ce44SJohn Forte 		{
453*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
454*fcf3ce44SJohn Forte 			    "%s requested.",
455*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
456*fcf3ce44SJohn Forte 
457*fcf3ce44SJohn Forte 			rval = emlxs_dfc_send_els(hba, dfc, mode);
458*fcf3ce44SJohn Forte 
459*fcf3ce44SJohn Forte 			break;
460*fcf3ce44SJohn Forte 		}
461*fcf3ce44SJohn Forte 
462*fcf3ce44SJohn Forte 	case EMLXS_LOOPBACK_TEST:
463*fcf3ce44SJohn Forte 		{
464*fcf3ce44SJohn Forte 			rval = emlxs_dfc_loopback_test(hba, dfc, mode);
465*fcf3ce44SJohn Forte 
466*fcf3ce44SJohn Forte 			break;
467*fcf3ce44SJohn Forte 		}
468*fcf3ce44SJohn Forte 
469*fcf3ce44SJohn Forte 	case EMLXS_GET_DUMPREGION:
470*fcf3ce44SJohn Forte 		{
471*fcf3ce44SJohn Forte 
472*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_dump_region(hba, dfc, mode);
473*fcf3ce44SJohn Forte 
474*fcf3ce44SJohn Forte 			break;
475*fcf3ce44SJohn Forte 		}
476*fcf3ce44SJohn Forte 
477*fcf3ce44SJohn Forte 	case EMLXS_LOOPBACK_MODE:
478*fcf3ce44SJohn Forte 		{
479*fcf3ce44SJohn Forte 			rval = emlxs_dfc_loopback_mode(hba, dfc, mode);
480*fcf3ce44SJohn Forte 
481*fcf3ce44SJohn Forte 			break;
482*fcf3ce44SJohn Forte 		}
483*fcf3ce44SJohn Forte 
484*fcf3ce44SJohn Forte 	case EMLXS_GET_IOINFO:
485*fcf3ce44SJohn Forte 		{
486*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
487*fcf3ce44SJohn Forte 			    "%s requested.",
488*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
489*fcf3ce44SJohn Forte 
490*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_ioinfo(hba, dfc, mode);
491*fcf3ce44SJohn Forte 
492*fcf3ce44SJohn Forte 			break;
493*fcf3ce44SJohn Forte 		}
494*fcf3ce44SJohn Forte 
495*fcf3ce44SJohn Forte 	case EMLXS_GET_LINKINFO:
496*fcf3ce44SJohn Forte 		{
497*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
498*fcf3ce44SJohn Forte 			    "%s requested.",
499*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
500*fcf3ce44SJohn Forte 
501*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_linkinfo(hba, dfc, mode);
502*fcf3ce44SJohn Forte 
503*fcf3ce44SJohn Forte 			break;
504*fcf3ce44SJohn Forte 		}
505*fcf3ce44SJohn Forte 
506*fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
507*fcf3ce44SJohn Forte 	case EMLXS_GET_FCTSTAT:
508*fcf3ce44SJohn Forte 		{
509*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
510*fcf3ce44SJohn Forte 			    "%s requested.",
511*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
512*fcf3ce44SJohn Forte 
513*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_fctstat(hba, dfc, mode);
514*fcf3ce44SJohn Forte 
515*fcf3ce44SJohn Forte 			break;
516*fcf3ce44SJohn Forte 		}
517*fcf3ce44SJohn Forte #endif	/* SFCT_SUPPORT */
518*fcf3ce44SJohn Forte 
519*fcf3ce44SJohn Forte 	case EMLXS_READ_MEM:
520*fcf3ce44SJohn Forte 		{
521*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
522*fcf3ce44SJohn Forte 			    "%s requested.",
523*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
524*fcf3ce44SJohn Forte 
525*fcf3ce44SJohn Forte 			rval = emlxs_dfc_read_mem(hba, dfc, mode);
526*fcf3ce44SJohn Forte 
527*fcf3ce44SJohn Forte 			break;
528*fcf3ce44SJohn Forte 		}
529*fcf3ce44SJohn Forte 
530*fcf3ce44SJohn Forte 	case EMLXS_WRITE_MEM:
531*fcf3ce44SJohn Forte 		{
532*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
533*fcf3ce44SJohn Forte 			    "%s requested.",
534*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
535*fcf3ce44SJohn Forte 
536*fcf3ce44SJohn Forte 			rval = emlxs_dfc_write_mem(hba, dfc, mode);
537*fcf3ce44SJohn Forte 
538*fcf3ce44SJohn Forte 			break;
539*fcf3ce44SJohn Forte 		}
540*fcf3ce44SJohn Forte 
541*fcf3ce44SJohn Forte 	case EMLXS_WRITE_CTLREG:
542*fcf3ce44SJohn Forte 		{
543*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
544*fcf3ce44SJohn Forte 			    "%s requested.",
545*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
546*fcf3ce44SJohn Forte 
547*fcf3ce44SJohn Forte 			rval = emlxs_dfc_write_ctlreg(hba, dfc, mode);
548*fcf3ce44SJohn Forte 
549*fcf3ce44SJohn Forte 			break;
550*fcf3ce44SJohn Forte 		}
551*fcf3ce44SJohn Forte 
552*fcf3ce44SJohn Forte 	case EMLXS_READ_CTLREG:
553*fcf3ce44SJohn Forte 		{
554*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
555*fcf3ce44SJohn Forte 			    "%s requested.",
556*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
557*fcf3ce44SJohn Forte 
558*fcf3ce44SJohn Forte 			rval = emlxs_dfc_read_ctlreg(hba, dfc, mode);
559*fcf3ce44SJohn Forte 
560*fcf3ce44SJohn Forte 			break;
561*fcf3ce44SJohn Forte 		}
562*fcf3ce44SJohn Forte 
563*fcf3ce44SJohn Forte 
564*fcf3ce44SJohn Forte 	case EMLXS_GET_EVENTINFO:
565*fcf3ce44SJohn Forte 		{
566*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_eventinfo(hba, dfc, mode);
567*fcf3ce44SJohn Forte 
568*fcf3ce44SJohn Forte 			break;
569*fcf3ce44SJohn Forte 		}
570*fcf3ce44SJohn Forte 
571*fcf3ce44SJohn Forte 	case EMLXS_GET_EVENT:
572*fcf3ce44SJohn Forte 		{
573*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_event(hba, dfc, mode);
574*fcf3ce44SJohn Forte 
575*fcf3ce44SJohn Forte 			break;
576*fcf3ce44SJohn Forte 		}
577*fcf3ce44SJohn Forte 
578*fcf3ce44SJohn Forte 	case EMLXS_SET_EVENT:
579*fcf3ce44SJohn Forte 		{
580*fcf3ce44SJohn Forte 			rval = emlxs_dfc_set_event(hba, dfc, mode);
581*fcf3ce44SJohn Forte 
582*fcf3ce44SJohn Forte 			break;
583*fcf3ce44SJohn Forte 		}
584*fcf3ce44SJohn Forte 
585*fcf3ce44SJohn Forte 	case EMLXS_GET_REV:
586*fcf3ce44SJohn Forte 		{
587*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_rev(hba, dfc, mode);
588*fcf3ce44SJohn Forte 
589*fcf3ce44SJohn Forte 			break;
590*fcf3ce44SJohn Forte 		}
591*fcf3ce44SJohn Forte 
592*fcf3ce44SJohn Forte 	case EMLXS_SEND_SCSI:
593*fcf3ce44SJohn Forte 		{
594*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
595*fcf3ce44SJohn Forte 			    "%s requested.",
596*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
597*fcf3ce44SJohn Forte 
598*fcf3ce44SJohn Forte 			rval = emlxs_dfc_send_scsi_fcp(hba, dfc, mode);
599*fcf3ce44SJohn Forte 			break;
600*fcf3ce44SJohn Forte 		}
601*fcf3ce44SJohn Forte 
602*fcf3ce44SJohn Forte #ifdef NPIV_SUPPORT
603*fcf3ce44SJohn Forte 	case EMLXS_CREATE_VPORT:
604*fcf3ce44SJohn Forte 		{
605*fcf3ce44SJohn Forte 
606*fcf3ce44SJohn Forte 			rval = emlxs_dfc_create_vport(hba, dfc, mode);
607*fcf3ce44SJohn Forte 
608*fcf3ce44SJohn Forte 			break;
609*fcf3ce44SJohn Forte 		}
610*fcf3ce44SJohn Forte 
611*fcf3ce44SJohn Forte 	case EMLXS_DESTROY_VPORT:
612*fcf3ce44SJohn Forte 		{
613*fcf3ce44SJohn Forte 
614*fcf3ce44SJohn Forte 			rval = emlxs_dfc_destroy_vport(hba, dfc, mode);
615*fcf3ce44SJohn Forte 
616*fcf3ce44SJohn Forte 			break;
617*fcf3ce44SJohn Forte 		}
618*fcf3ce44SJohn Forte 
619*fcf3ce44SJohn Forte 	case EMLXS_GET_VPORTINFO:
620*fcf3ce44SJohn Forte 		{
621*fcf3ce44SJohn Forte 
622*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_vportinfo(hba, dfc, mode);
623*fcf3ce44SJohn Forte 
624*fcf3ce44SJohn Forte 			break;
625*fcf3ce44SJohn Forte 		}
626*fcf3ce44SJohn Forte 
627*fcf3ce44SJohn Forte 	case EMLXS_NPIV_RESOURCE:
628*fcf3ce44SJohn Forte 		{
629*fcf3ce44SJohn Forte 			rval = emlxs_dfc_npiv_resource(hba, dfc, mode);
630*fcf3ce44SJohn Forte 
631*fcf3ce44SJohn Forte 			break;
632*fcf3ce44SJohn Forte 		}
633*fcf3ce44SJohn Forte 
634*fcf3ce44SJohn Forte 	case EMLXS_NPIV_TEST:
635*fcf3ce44SJohn Forte 		{
636*fcf3ce44SJohn Forte 			rval = emlxs_dfc_npiv_test(hba, dfc, mode);
637*fcf3ce44SJohn Forte 
638*fcf3ce44SJohn Forte 			break;
639*fcf3ce44SJohn Forte 		}
640*fcf3ce44SJohn Forte #endif	/* NPIV_SUPPORT */
641*fcf3ce44SJohn Forte 
642*fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
643*fcf3ce44SJohn Forte 	case EMLXS_INIT_AUTH:
644*fcf3ce44SJohn Forte 		{
645*fcf3ce44SJohn Forte 			rval = emlxs_dfc_init_auth(hba, dfc, mode);
646*fcf3ce44SJohn Forte 
647*fcf3ce44SJohn Forte 			break;
648*fcf3ce44SJohn Forte 		}
649*fcf3ce44SJohn Forte 
650*fcf3ce44SJohn Forte 	case EMLXS_GET_AUTH_CFG:
651*fcf3ce44SJohn Forte 		{
652*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_auth_cfg(hba, dfc, mode);
653*fcf3ce44SJohn Forte 
654*fcf3ce44SJohn Forte 			break;
655*fcf3ce44SJohn Forte 		}
656*fcf3ce44SJohn Forte 
657*fcf3ce44SJohn Forte 	case EMLXS_SET_AUTH_CFG:
658*fcf3ce44SJohn Forte 		{
659*fcf3ce44SJohn Forte 			rval = emlxs_dfc_set_auth_cfg(hba, dfc, mode);
660*fcf3ce44SJohn Forte 
661*fcf3ce44SJohn Forte 			break;
662*fcf3ce44SJohn Forte 		}
663*fcf3ce44SJohn Forte 
664*fcf3ce44SJohn Forte 	case EMLXS_GET_AUTH_PASSWORD:
665*fcf3ce44SJohn Forte 		{
666*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_auth_pwd(hba, dfc, mode);
667*fcf3ce44SJohn Forte 
668*fcf3ce44SJohn Forte 			break;
669*fcf3ce44SJohn Forte 		}
670*fcf3ce44SJohn Forte 
671*fcf3ce44SJohn Forte 	case EMLXS_SET_AUTH_PASSWORD:
672*fcf3ce44SJohn Forte 		{
673*fcf3ce44SJohn Forte 			rval = emlxs_dfc_set_auth_pwd(hba, dfc, mode);
674*fcf3ce44SJohn Forte 
675*fcf3ce44SJohn Forte 			break;
676*fcf3ce44SJohn Forte 		}
677*fcf3ce44SJohn Forte 
678*fcf3ce44SJohn Forte 	case EMLXS_GET_AUTH_STATUS:
679*fcf3ce44SJohn Forte 		{
680*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_auth_status(hba, dfc, mode);
681*fcf3ce44SJohn Forte 
682*fcf3ce44SJohn Forte 			break;
683*fcf3ce44SJohn Forte 		}
684*fcf3ce44SJohn Forte 
685*fcf3ce44SJohn Forte 	case EMLXS_GET_AUTH_CFG_TABLE:
686*fcf3ce44SJohn Forte 		{
687*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_auth_cfg_table(hba, dfc, mode);
688*fcf3ce44SJohn Forte 			break;
689*fcf3ce44SJohn Forte 		}
690*fcf3ce44SJohn Forte 
691*fcf3ce44SJohn Forte 	case EMLXS_GET_AUTH_KEY_TABLE:
692*fcf3ce44SJohn Forte 		{
693*fcf3ce44SJohn Forte 			rval = emlxs_dfc_get_auth_key_table(hba, dfc, mode);
694*fcf3ce44SJohn Forte 			break;
695*fcf3ce44SJohn Forte 		}
696*fcf3ce44SJohn Forte 
697*fcf3ce44SJohn Forte #endif	/* DHCHAP_SUPPORT */
698*fcf3ce44SJohn Forte 
699*fcf3ce44SJohn Forte #ifdef FCIO_SUPPORT
700*fcf3ce44SJohn Forte 	case EMLXS_FCIO_CMD:
701*fcf3ce44SJohn Forte 		rval = emlxs_fcio_manage(hba, dfc, mode);
702*fcf3ce44SJohn Forte 		break;
703*fcf3ce44SJohn Forte #endif	/* FCIO_SUPPORT */
704*fcf3ce44SJohn Forte 
705*fcf3ce44SJohn Forte 	default:
706*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
707*fcf3ce44SJohn Forte 		    "Unknown command received. (0x%x)",
708*fcf3ce44SJohn Forte 		    dfc->cmd);
709*fcf3ce44SJohn Forte 		rval = DFC_ARG_INVALID;
710*fcf3ce44SJohn Forte 
711*fcf3ce44SJohn Forte 	}	/* switch() */
712*fcf3ce44SJohn Forte 
713*fcf3ce44SJohn Forte 	kmem_free(dfc, sizeof (dfc_t));
714*fcf3ce44SJohn Forte 	return (rval);
715*fcf3ce44SJohn Forte 
716*fcf3ce44SJohn Forte } /* emlxs_dfc_manage() */
717*fcf3ce44SJohn Forte 
718*fcf3ce44SJohn Forte 
719*fcf3ce44SJohn Forte #ifdef FCIO_SUPPORT
720*fcf3ce44SJohn Forte 
721*fcf3ce44SJohn Forte emlxs_table_t emlxs_fcio_table[] =
722*fcf3ce44SJohn Forte {
723*fcf3ce44SJohn Forte 	{FCIO_GET_NUM_DEVS, "GET_NUM_DEVS"},
724*fcf3ce44SJohn Forte 	{FCIO_GET_DEV_LIST, "GET_DEV_LIST"},
725*fcf3ce44SJohn Forte 	{FCIO_GET_SYM_PNAME, "GET_SYM_PNAME"},
726*fcf3ce44SJohn Forte 	{FCIO_GET_SYM_NNAME, "GET_SYM_NNAME"},
727*fcf3ce44SJohn Forte 	{FCIO_SET_SYM_PNAME, "SET_SYM_PNAME"},
728*fcf3ce44SJohn Forte 	{FCIO_SET_SYM_NNAME, "SET_SYM_NNAME"},
729*fcf3ce44SJohn Forte 	{FCIO_GET_LOGI_PARAMS, "GET_LOGI_PARAMS"},
730*fcf3ce44SJohn Forte 	{FCIO_DEV_LOGIN, "DEV_LOGIN"},
731*fcf3ce44SJohn Forte 	{FCIO_DEV_LOGOUT, "DEV_LOGOUT"},
732*fcf3ce44SJohn Forte 	{FCIO_GET_STATE, "GET_STATE"},
733*fcf3ce44SJohn Forte 	{FCIO_DEV_REMOVE, "DEV_REMOVE"},
734*fcf3ce44SJohn Forte 	{FCIO_GET_FCODE_REV, "GET_FCODE_REV"},
735*fcf3ce44SJohn Forte 	{FCIO_GET_FW_REV, "GET_FW_REV"},
736*fcf3ce44SJohn Forte 	{FCIO_GET_DUMP_SIZE, "GET_DUMP_SIZE"},
737*fcf3ce44SJohn Forte 	{FCIO_FORCE_DUMP, "FORCE_DUMP"},
738*fcf3ce44SJohn Forte 	{FCIO_GET_DUMP, "GET_DUMP"},
739*fcf3ce44SJohn Forte 	{FCIO_GET_TOPOLOGY, "GET_TOPOLOGY"},
740*fcf3ce44SJohn Forte 	{FCIO_RESET_LINK, "RESET_LINK"},
741*fcf3ce44SJohn Forte 	{FCIO_RESET_HARD, "RESET_HARD"},
742*fcf3ce44SJohn Forte 	{FCIO_RESET_HARD_CORE, "RESET_HARD_CORE"},
743*fcf3ce44SJohn Forte 	{FCIO_DIAG, "DIAG"},
744*fcf3ce44SJohn Forte 	{FCIO_NS, "NS"},
745*fcf3ce44SJohn Forte 	{FCIO_DOWNLOAD_FW, "DOWNLOAD_FW"},
746*fcf3ce44SJohn Forte 	{FCIO_GET_HOST_PARAMS, "GET_HOST_PARAMS"},
747*fcf3ce44SJohn Forte 	{FCIO_LINK_STATUS, "LINK_STATUS"},
748*fcf3ce44SJohn Forte 	{FCIO_DOWNLOAD_FCODE, "DOWNLOAD_FCODE"},
749*fcf3ce44SJohn Forte 	{FCIO_GET_NODE_ID, "GET_NODE_ID"},
750*fcf3ce44SJohn Forte 	{FCIO_SET_NODE_ID, "SET_NODE_ID"},
751*fcf3ce44SJohn Forte 	{FCIO_SEND_NODE_ID, "SEND_NODE_ID"},
752*fcf3ce44SJohn Forte 	{FCIO_GET_ADAPTER_ATTRIBUTES, "GET_ADAPTER_ATTRIBUTES"},
753*fcf3ce44SJohn Forte 	{FCIO_GET_OTHER_ADAPTER_PORTS, "GET_OTHER_ADAPTER_PORTS"},
754*fcf3ce44SJohn Forte 	{FCIO_GET_ADAPTER_PORT_ATTRIBUTES, "GET_ADAPTER_PORT_ATTRIBUTES"},
755*fcf3ce44SJohn Forte 	{FCIO_GET_DISCOVERED_PORT_ATTRIBUTES, "GET_DISCOVERED_PORT_ATTRIBUTES"},
756*fcf3ce44SJohn Forte 	{FCIO_GET_PORT_ATTRIBUTES, "GET_PORT_ATTRIBUTES"},
757*fcf3ce44SJohn Forte 	{FCIO_GET_ADAPTER_PORT_STATS, "GET_ADAPTER_PORT_STATS"},
758*fcf3ce44SJohn Forte 
759*fcf3ce44SJohn Forte };	/* emlxs_fcio_table */
760*fcf3ce44SJohn Forte 
761*fcf3ce44SJohn Forte 
762*fcf3ce44SJohn Forte extern char *
763*fcf3ce44SJohn Forte emlxs_fcio_xlate(uint16_t cmd)
764*fcf3ce44SJohn Forte {
765*fcf3ce44SJohn Forte 	static char buffer[32];
766*fcf3ce44SJohn Forte 	uint32_t i;
767*fcf3ce44SJohn Forte 	uint32_t count;
768*fcf3ce44SJohn Forte 
769*fcf3ce44SJohn Forte 	count = sizeof (emlxs_fcio_table) / sizeof (emlxs_table_t);
770*fcf3ce44SJohn Forte 	for (i = 0; i < count; i++) {
771*fcf3ce44SJohn Forte 		if (cmd == emlxs_fcio_table[i].code) {
772*fcf3ce44SJohn Forte 			return (emlxs_fcio_table[i].string);
773*fcf3ce44SJohn Forte 		}
774*fcf3ce44SJohn Forte 	}
775*fcf3ce44SJohn Forte 
776*fcf3ce44SJohn Forte 	(void) sprintf(buffer, "Cmd=0x%x", cmd);
777*fcf3ce44SJohn Forte 	return (buffer);
778*fcf3ce44SJohn Forte 
779*fcf3ce44SJohn Forte } /* emlxs_fcio_xlate() */
780*fcf3ce44SJohn Forte 
781*fcf3ce44SJohn Forte 
782*fcf3ce44SJohn Forte static int32_t
783*fcf3ce44SJohn Forte emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
784*fcf3ce44SJohn Forte {
785*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
786*fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
787*fcf3ce44SJohn Forte 	int rval = 0;
788*fcf3ce44SJohn Forte 	fcio_t local_fcio;
789*fcf3ce44SJohn Forte 	fcio_t *fcio = &local_fcio;
790*fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd = &VPD;
791*fcf3ce44SJohn Forte 	fc_hba_port_attributes_t *port_attrs;
792*fcf3ce44SJohn Forte 	emlxs_node_t *ndlp;
793*fcf3ce44SJohn Forte 	uint8_t *wwpn;
794*fcf3ce44SJohn Forte 
795*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
796*fcf3ce44SJohn Forte 	    "%s: %s: requested.",
797*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd), emlxs_fcio_xlate(dfc->data1));
798*fcf3ce44SJohn Forte 
799*fcf3ce44SJohn Forte 	if (!dfc->buf4 || !dfc->buf4_size) {
800*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
801*fcf3ce44SJohn Forte 		    "%s: %s: Null buffer4 found.",
802*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
803*fcf3ce44SJohn Forte 		    emlxs_fcio_xlate(dfc->data1));
804*fcf3ce44SJohn Forte 
805*fcf3ce44SJohn Forte 		return (EFAULT);
806*fcf3ce44SJohn Forte 	}
807*fcf3ce44SJohn Forte 	if (dfc->buf4_size < sizeof (uint32_t)) {
808*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
809*fcf3ce44SJohn Forte 		    "%s: %s: Buffer4 too small. (size=%d)",
810*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), emlxs_fcio_xlate(dfc->data1),
811*fcf3ce44SJohn Forte 		    dfc->buf4_size);
812*fcf3ce44SJohn Forte 
813*fcf3ce44SJohn Forte 		return (EFAULT);
814*fcf3ce44SJohn Forte 	}
815*fcf3ce44SJohn Forte 	/* Map DFC to FCIO */
816*fcf3ce44SJohn Forte 	bzero(fcio, sizeof (fcio_t));
817*fcf3ce44SJohn Forte 	fcio->fcio_flags = dfc->flag;
818*fcf3ce44SJohn Forte 	fcio->fcio_cmd = dfc->data1;
819*fcf3ce44SJohn Forte 	fcio->fcio_cmd_flags = dfc->data2;
820*fcf3ce44SJohn Forte 	fcio->fcio_xfer = dfc->data3;
821*fcf3ce44SJohn Forte 	fcio->fcio_errno = FC_FAILURE;	/* dfc->buf4 on return */
822*fcf3ce44SJohn Forte 
823*fcf3ce44SJohn Forte 	if (dfc->buf1_size && dfc->buf1) {
824*fcf3ce44SJohn Forte 		fcio->fcio_ilen = dfc->buf1_size;
825*fcf3ce44SJohn Forte 		fcio->fcio_ibuf = kmem_zalloc(dfc->buf1_size, KM_SLEEP);
826*fcf3ce44SJohn Forte 
827*fcf3ce44SJohn Forte 		if (!fcio->fcio_ibuf) {
828*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
829*fcf3ce44SJohn Forte 			    "%s: %s: Unable to allocate ibuf. (size=%d)",
830*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
831*fcf3ce44SJohn Forte 			    emlxs_fcio_xlate(dfc->data1),
832*fcf3ce44SJohn Forte 			    fcio->fcio_ilen);
833*fcf3ce44SJohn Forte 
834*fcf3ce44SJohn Forte 			rval = EFAULT;
835*fcf3ce44SJohn Forte 			goto done;
836*fcf3ce44SJohn Forte 		}
837*fcf3ce44SJohn Forte 		if (ddi_copyin(dfc->buf1, fcio->fcio_ibuf,
838*fcf3ce44SJohn Forte 		    fcio->fcio_ilen, mode)) {
839*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
840*fcf3ce44SJohn Forte 			    "%s: %s: ddi_copyin failed. (size=%d)",
841*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
842*fcf3ce44SJohn Forte 			    emlxs_fcio_xlate(dfc->data1),
843*fcf3ce44SJohn Forte 			    fcio->fcio_ilen);
844*fcf3ce44SJohn Forte 
845*fcf3ce44SJohn Forte 			rval = EFAULT;
846*fcf3ce44SJohn Forte 			goto done;
847*fcf3ce44SJohn Forte 		}
848*fcf3ce44SJohn Forte 	}
849*fcf3ce44SJohn Forte 	if (dfc->buf2_size && dfc->buf2) {
850*fcf3ce44SJohn Forte 		fcio->fcio_olen = dfc->buf2_size;
851*fcf3ce44SJohn Forte 		fcio->fcio_obuf = kmem_zalloc(dfc->buf2_size, KM_SLEEP);
852*fcf3ce44SJohn Forte 
853*fcf3ce44SJohn Forte 		if (!fcio->fcio_obuf) {
854*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
855*fcf3ce44SJohn Forte 			    "%s: %s: Unable to allocate obuf. (size=%d)",
856*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
857*fcf3ce44SJohn Forte 			    emlxs_fcio_xlate(dfc->data1),
858*fcf3ce44SJohn Forte 			    fcio->fcio_olen);
859*fcf3ce44SJohn Forte 
860*fcf3ce44SJohn Forte 			rval = EFAULT;
861*fcf3ce44SJohn Forte 			goto done;
862*fcf3ce44SJohn Forte 		}
863*fcf3ce44SJohn Forte 		if (ddi_copyin(dfc->buf2, fcio->fcio_obuf,
864*fcf3ce44SJohn Forte 		    fcio->fcio_olen, mode)) {
865*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
866*fcf3ce44SJohn Forte 			    "%s: %s: ddi_copyin failed. (size=%d)",
867*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
868*fcf3ce44SJohn Forte 			    emlxs_fcio_xlate(dfc->data1),
869*fcf3ce44SJohn Forte 			    fcio->fcio_olen);
870*fcf3ce44SJohn Forte 
871*fcf3ce44SJohn Forte 			rval = EFAULT;
872*fcf3ce44SJohn Forte 			goto done;
873*fcf3ce44SJohn Forte 		}
874*fcf3ce44SJohn Forte 	}
875*fcf3ce44SJohn Forte 	if (dfc->buf3_size && dfc->buf3) {
876*fcf3ce44SJohn Forte 		fcio->fcio_alen = dfc->buf3_size;
877*fcf3ce44SJohn Forte 		fcio->fcio_abuf = kmem_zalloc(dfc->buf3_size, KM_SLEEP);
878*fcf3ce44SJohn Forte 
879*fcf3ce44SJohn Forte 		if (!fcio->fcio_abuf) {
880*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
881*fcf3ce44SJohn Forte 			    "%s: %s: Unable to allocate abuf. (size=%d)",
882*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
883*fcf3ce44SJohn Forte 			    emlxs_fcio_xlate(dfc->data1),
884*fcf3ce44SJohn Forte 			    fcio->fcio_alen);
885*fcf3ce44SJohn Forte 
886*fcf3ce44SJohn Forte 			rval = EFAULT;
887*fcf3ce44SJohn Forte 			goto done;
888*fcf3ce44SJohn Forte 		}
889*fcf3ce44SJohn Forte 		if (ddi_copyin(dfc->buf3, fcio->fcio_abuf,
890*fcf3ce44SJohn Forte 		    fcio->fcio_alen, mode)) {
891*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
892*fcf3ce44SJohn Forte 			    "%s: %s: ddi_copyin failed. (size=%d)",
893*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
894*fcf3ce44SJohn Forte 			    emlxs_fcio_xlate(dfc->data1),
895*fcf3ce44SJohn Forte 			    fcio->fcio_alen);
896*fcf3ce44SJohn Forte 
897*fcf3ce44SJohn Forte 			rval = EFAULT;
898*fcf3ce44SJohn Forte 			goto done;
899*fcf3ce44SJohn Forte 		}
900*fcf3ce44SJohn Forte 	}
901*fcf3ce44SJohn Forte 	/* FCIO command */
902*fcf3ce44SJohn Forte 	switch (fcio->fcio_cmd) {
903*fcf3ce44SJohn Forte 	case FCIO_DIAG:
904*fcf3ce44SJohn Forte 		{
905*fcf3ce44SJohn Forte 			fc_fca_pm_t pm;
906*fcf3ce44SJohn Forte 			/* uint32_t ret; */
907*fcf3ce44SJohn Forte 
908*fcf3ce44SJohn Forte 			bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
909*fcf3ce44SJohn Forte 
910*fcf3ce44SJohn Forte 			pm.pm_cmd_len = fcio->fcio_ilen;
911*fcf3ce44SJohn Forte 			pm.pm_cmd_buf = fcio->fcio_ibuf;
912*fcf3ce44SJohn Forte 			pm.pm_data_len = fcio->fcio_alen;
913*fcf3ce44SJohn Forte 			pm.pm_data_buf = fcio->fcio_abuf;
914*fcf3ce44SJohn Forte 			pm.pm_stat_len = fcio->fcio_olen;
915*fcf3ce44SJohn Forte 			pm.pm_stat_buf = fcio->fcio_obuf;
916*fcf3ce44SJohn Forte 			pm.pm_cmd_code = FC_PORT_DIAG;
917*fcf3ce44SJohn Forte 			pm.pm_cmd_flags = fcio->fcio_cmd_flags;
918*fcf3ce44SJohn Forte 
919*fcf3ce44SJohn Forte 			rval = emlxs_port_manage(port, &pm);
920*fcf3ce44SJohn Forte 
921*fcf3ce44SJohn Forte 			if (rval != FC_SUCCESS) {
922*fcf3ce44SJohn Forte 				fcio->fcio_errno = rval;
923*fcf3ce44SJohn Forte 
924*fcf3ce44SJohn Forte 				if (rval == FC_INVALID_REQUEST) {
925*fcf3ce44SJohn Forte 					rval = ENOTTY;
926*fcf3ce44SJohn Forte 				} else {
927*fcf3ce44SJohn Forte 					rval = EIO;
928*fcf3ce44SJohn Forte 				}
929*fcf3ce44SJohn Forte 			}
930*fcf3ce44SJohn Forte 			break;
931*fcf3ce44SJohn Forte 		}
932*fcf3ce44SJohn Forte 
933*fcf3ce44SJohn Forte 	case FCIO_GET_HOST_PARAMS:
934*fcf3ce44SJohn Forte 		{
935*fcf3ce44SJohn Forte 			fc_port_dev_t *port_dev;
936*fcf3ce44SJohn Forte 			uint32_t i;
937*fcf3ce44SJohn Forte 
938*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
939*fcf3ce44SJohn Forte 			    fcio->fcio_olen != sizeof (fc_port_dev_t)) {
940*fcf3ce44SJohn Forte 				rval = EINVAL;
941*fcf3ce44SJohn Forte 				break;
942*fcf3ce44SJohn Forte 			}
943*fcf3ce44SJohn Forte 			port_dev = (fc_port_dev_t *)fcio->fcio_obuf;
944*fcf3ce44SJohn Forte 			port_dev->dev_did.port_id = port->did;
945*fcf3ce44SJohn Forte 			port_dev->dev_hard_addr.hard_addr =
946*fcf3ce44SJohn Forte 			    cfg[CFG_ASSIGN_ALPA].current;
947*fcf3ce44SJohn Forte 			port_dev->dev_state = port->ulp_statec;
948*fcf3ce44SJohn Forte 			bcopy((caddr_t)&port->wwpn,
949*fcf3ce44SJohn Forte 			    (caddr_t)&port_dev->dev_pwwn, 8);
950*fcf3ce44SJohn Forte 			bcopy((caddr_t)&port->wwnn,
951*fcf3ce44SJohn Forte 			    (caddr_t)&port_dev->dev_nwwn, 8);
952*fcf3ce44SJohn Forte 
953*fcf3ce44SJohn Forte 			if (hba->topology == TOPOLOGY_LOOP) {
954*fcf3ce44SJohn Forte 				for (i = 0; i < port->alpa_map[0]; i++) {
955*fcf3ce44SJohn Forte 					if (port->alpa_map[i+1] == port->did) {
956*fcf3ce44SJohn Forte 						PRIV_LILP_POSIT(port_dev) =
957*fcf3ce44SJohn Forte 						    (uint8_t)(i & 0xff);
958*fcf3ce44SJohn Forte 						break;
959*fcf3ce44SJohn Forte 					}
960*fcf3ce44SJohn Forte 				}
961*fcf3ce44SJohn Forte 			}
962*fcf3ce44SJohn Forte 			port_dev->dev_type[0] = SWAP_DATA32(0x00000120);
963*fcf3ce44SJohn Forte 			port_dev->dev_type[1] = SWAP_DATA32(0x00000001);
964*fcf3ce44SJohn Forte 
965*fcf3ce44SJohn Forte 			break;
966*fcf3ce44SJohn Forte 		}
967*fcf3ce44SJohn Forte 
968*fcf3ce44SJohn Forte 	case FCIO_RESET_LINK:
969*fcf3ce44SJohn Forte 		{
970*fcf3ce44SJohn Forte 			uint8_t null_wwn[8];
971*fcf3ce44SJohn Forte 
972*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
973*fcf3ce44SJohn Forte 			    fcio->fcio_ilen != 8) {
974*fcf3ce44SJohn Forte 				rval = EINVAL;
975*fcf3ce44SJohn Forte 				break;
976*fcf3ce44SJohn Forte 			}
977*fcf3ce44SJohn Forte 			bzero(null_wwn, 8);
978*fcf3ce44SJohn Forte 
979*fcf3ce44SJohn Forte 			if (bcmp((uint8_t *)fcio->fcio_ibuf,
980*fcf3ce44SJohn Forte 			    null_wwn, 8) == 0) {
981*fcf3ce44SJohn Forte 				rval = emlxs_reset(port, FC_FCA_LINK_RESET);
982*fcf3ce44SJohn Forte 
983*fcf3ce44SJohn Forte 				if (rval != FC_SUCCESS) {
984*fcf3ce44SJohn Forte 					fcio->fcio_errno = rval;
985*fcf3ce44SJohn Forte 					rval = EIO;
986*fcf3ce44SJohn Forte 				}
987*fcf3ce44SJohn Forte 			} else {
988*fcf3ce44SJohn Forte 				rval = ENOTSUP;
989*fcf3ce44SJohn Forte 			}
990*fcf3ce44SJohn Forte 			break;
991*fcf3ce44SJohn Forte 		}
992*fcf3ce44SJohn Forte 
993*fcf3ce44SJohn Forte 	case FCIO_RESET_HARD:
994*fcf3ce44SJohn Forte 	case FCIO_RESET_HARD_CORE:
995*fcf3ce44SJohn Forte 		{
996*fcf3ce44SJohn Forte 			rval = emlxs_reset(port, FC_FCA_RESET);
997*fcf3ce44SJohn Forte 
998*fcf3ce44SJohn Forte 			if (rval != FC_SUCCESS) {
999*fcf3ce44SJohn Forte 				fcio->fcio_errno = rval;
1000*fcf3ce44SJohn Forte 				rval = EIO;
1001*fcf3ce44SJohn Forte 			}
1002*fcf3ce44SJohn Forte 			break;
1003*fcf3ce44SJohn Forte 		}
1004*fcf3ce44SJohn Forte 
1005*fcf3ce44SJohn Forte 	case FCIO_DOWNLOAD_FW:
1006*fcf3ce44SJohn Forte 		{
1007*fcf3ce44SJohn Forte 			fc_fca_pm_t pm;
1008*fcf3ce44SJohn Forte 
1009*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1010*fcf3ce44SJohn Forte 			    fcio->fcio_ilen <= 0) {
1011*fcf3ce44SJohn Forte 				rval = EINVAL;
1012*fcf3ce44SJohn Forte 				break;
1013*fcf3ce44SJohn Forte 			}
1014*fcf3ce44SJohn Forte 			bzero((caddr_t)&pm, sizeof (pm));
1015*fcf3ce44SJohn Forte 
1016*fcf3ce44SJohn Forte 			pm.pm_cmd_flags = FC_FCA_PM_WRITE;
1017*fcf3ce44SJohn Forte 			pm.pm_cmd_code = FC_PORT_DOWNLOAD_FW;
1018*fcf3ce44SJohn Forte 			pm.pm_data_len = fcio->fcio_ilen;
1019*fcf3ce44SJohn Forte 			pm.pm_data_buf = fcio->fcio_ibuf;
1020*fcf3ce44SJohn Forte 
1021*fcf3ce44SJohn Forte 			rval = emlxs_port_manage(port, &pm);
1022*fcf3ce44SJohn Forte 
1023*fcf3ce44SJohn Forte 			if (rval != FC_SUCCESS) {
1024*fcf3ce44SJohn Forte 				fcio->fcio_errno = rval;
1025*fcf3ce44SJohn Forte 				rval = EIO;
1026*fcf3ce44SJohn Forte 			}
1027*fcf3ce44SJohn Forte 			break;
1028*fcf3ce44SJohn Forte 		}
1029*fcf3ce44SJohn Forte 
1030*fcf3ce44SJohn Forte 	case FCIO_GET_FW_REV:
1031*fcf3ce44SJohn Forte 		{
1032*fcf3ce44SJohn Forte 			fc_fca_pm_t pm;
1033*fcf3ce44SJohn Forte 
1034*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1035*fcf3ce44SJohn Forte 			    fcio->fcio_olen < FC_FW_REV_SIZE) {
1036*fcf3ce44SJohn Forte 				rval = EINVAL;
1037*fcf3ce44SJohn Forte 				break;
1038*fcf3ce44SJohn Forte 			}
1039*fcf3ce44SJohn Forte 			bzero((caddr_t)&pm, sizeof (pm));
1040*fcf3ce44SJohn Forte 
1041*fcf3ce44SJohn Forte 			pm.pm_cmd_flags = FC_FCA_PM_READ;
1042*fcf3ce44SJohn Forte 			pm.pm_cmd_code = FC_PORT_GET_FW_REV;
1043*fcf3ce44SJohn Forte 			pm.pm_data_len = fcio->fcio_olen;
1044*fcf3ce44SJohn Forte 			pm.pm_data_buf = fcio->fcio_obuf;
1045*fcf3ce44SJohn Forte 
1046*fcf3ce44SJohn Forte 			rval = emlxs_port_manage(port, &pm);
1047*fcf3ce44SJohn Forte 
1048*fcf3ce44SJohn Forte 			if (rval != FC_SUCCESS) {
1049*fcf3ce44SJohn Forte 				fcio->fcio_errno = rval;
1050*fcf3ce44SJohn Forte 				rval = EIO;
1051*fcf3ce44SJohn Forte 			}
1052*fcf3ce44SJohn Forte 			break;
1053*fcf3ce44SJohn Forte 		}
1054*fcf3ce44SJohn Forte 
1055*fcf3ce44SJohn Forte 	case FCIO_GET_FCODE_REV:
1056*fcf3ce44SJohn Forte 		{
1057*fcf3ce44SJohn Forte 			fc_fca_pm_t pm;
1058*fcf3ce44SJohn Forte 
1059*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1060*fcf3ce44SJohn Forte 			    fcio->fcio_olen < FC_FCODE_REV_SIZE) {
1061*fcf3ce44SJohn Forte 				rval = EINVAL;
1062*fcf3ce44SJohn Forte 				break;
1063*fcf3ce44SJohn Forte 			}
1064*fcf3ce44SJohn Forte 			bzero((caddr_t)&pm, sizeof (pm));
1065*fcf3ce44SJohn Forte 
1066*fcf3ce44SJohn Forte 			pm.pm_cmd_flags = FC_FCA_PM_READ;
1067*fcf3ce44SJohn Forte 			pm.pm_cmd_code = FC_PORT_GET_FCODE_REV;
1068*fcf3ce44SJohn Forte 			pm.pm_data_len = fcio->fcio_olen;
1069*fcf3ce44SJohn Forte 			pm.pm_data_buf = fcio->fcio_obuf;
1070*fcf3ce44SJohn Forte 
1071*fcf3ce44SJohn Forte 			rval = emlxs_port_manage(port, &pm);
1072*fcf3ce44SJohn Forte 
1073*fcf3ce44SJohn Forte 			if (rval != FC_SUCCESS) {
1074*fcf3ce44SJohn Forte 				fcio->fcio_errno = rval;
1075*fcf3ce44SJohn Forte 				rval = EIO;
1076*fcf3ce44SJohn Forte 			}
1077*fcf3ce44SJohn Forte 			break;
1078*fcf3ce44SJohn Forte 		}
1079*fcf3ce44SJohn Forte 
1080*fcf3ce44SJohn Forte 	case FCIO_DOWNLOAD_FCODE:
1081*fcf3ce44SJohn Forte 		{
1082*fcf3ce44SJohn Forte 			fc_fca_pm_t pm;
1083*fcf3ce44SJohn Forte 
1084*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1085*fcf3ce44SJohn Forte 			    fcio->fcio_ilen <= 0) {
1086*fcf3ce44SJohn Forte 				rval = EINVAL;
1087*fcf3ce44SJohn Forte 				break;
1088*fcf3ce44SJohn Forte 			}
1089*fcf3ce44SJohn Forte 			bzero((caddr_t)&pm, sizeof (pm));
1090*fcf3ce44SJohn Forte 
1091*fcf3ce44SJohn Forte 			pm.pm_cmd_flags = FC_FCA_PM_WRITE;
1092*fcf3ce44SJohn Forte 			pm.pm_cmd_code = FC_PORT_DOWNLOAD_FCODE;
1093*fcf3ce44SJohn Forte 			pm.pm_data_len = fcio->fcio_ilen;
1094*fcf3ce44SJohn Forte 			pm.pm_data_buf = fcio->fcio_ibuf;
1095*fcf3ce44SJohn Forte 
1096*fcf3ce44SJohn Forte 			rval = emlxs_port_manage(port, &pm);
1097*fcf3ce44SJohn Forte 
1098*fcf3ce44SJohn Forte 			if (rval != FC_SUCCESS) {
1099*fcf3ce44SJohn Forte 				fcio->fcio_errno = rval;
1100*fcf3ce44SJohn Forte 				rval = EIO;
1101*fcf3ce44SJohn Forte 			}
1102*fcf3ce44SJohn Forte 			break;
1103*fcf3ce44SJohn Forte 		}
1104*fcf3ce44SJohn Forte 
1105*fcf3ce44SJohn Forte 	case FCIO_GET_ADAPTER_ATTRIBUTES:
1106*fcf3ce44SJohn Forte 		{
1107*fcf3ce44SJohn Forte 			fc_hba_adapter_attributes_t *hba_attrs;
1108*fcf3ce44SJohn Forte 
1109*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1110*fcf3ce44SJohn Forte 			    fcio->fcio_olen <
1111*fcf3ce44SJohn Forte 			    sizeof (fc_hba_adapter_attributes_t)) {
1112*fcf3ce44SJohn Forte 				rval = EINVAL;
1113*fcf3ce44SJohn Forte 				break;
1114*fcf3ce44SJohn Forte 			}
1115*fcf3ce44SJohn Forte 			hba_attrs =
1116*fcf3ce44SJohn Forte 			    (fc_hba_adapter_attributes_t *)fcio->fcio_obuf;
1117*fcf3ce44SJohn Forte 
1118*fcf3ce44SJohn Forte 			hba_attrs->version = FC_HBA_ADAPTER_ATTRIBUTES_VERSION;
1119*fcf3ce44SJohn Forte 			(void) strncpy(hba_attrs->Manufacturer,
1120*fcf3ce44SJohn Forte 			    "Emulex", sizeof (hba_attrs->Manufacturer));
1121*fcf3ce44SJohn Forte 			(void) strncpy(hba_attrs->SerialNumber, vpd->serial_num,
1122*fcf3ce44SJohn Forte 			    sizeof (hba_attrs->SerialNumber));
1123*fcf3ce44SJohn Forte 			(void) strncpy(hba_attrs->Model, hba->model_info.model,
1124*fcf3ce44SJohn Forte 			    sizeof (hba_attrs->Model));
1125*fcf3ce44SJohn Forte 			(void) strncpy(hba_attrs->ModelDescription,
1126*fcf3ce44SJohn Forte 			    hba->model_info.model_desc,
1127*fcf3ce44SJohn Forte 			    sizeof (hba_attrs->ModelDescription));
1128*fcf3ce44SJohn Forte 			bcopy((caddr_t)&port->wwnn,
1129*fcf3ce44SJohn Forte 			    (caddr_t)&hba_attrs->NodeWWN, 8);
1130*fcf3ce44SJohn Forte 			(void) strncpy((caddr_t)hba_attrs->NodeSymbolicName,
1131*fcf3ce44SJohn Forte 			    (caddr_t)port->snn,
1132*fcf3ce44SJohn Forte 			    sizeof (hba_attrs->NodeSymbolicName));
1133*fcf3ce44SJohn Forte 			(void) sprintf(hba_attrs->HardwareVersion, "%x",
1134*fcf3ce44SJohn Forte 			    vpd->biuRev);
1135*fcf3ce44SJohn Forte 			(void) sprintf(hba_attrs->DriverVersion, "%s (%s)",
1136*fcf3ce44SJohn Forte 			    emlxs_version, emlxs_revision);
1137*fcf3ce44SJohn Forte 			(void) strncpy(hba_attrs->OptionROMVersion,
1138*fcf3ce44SJohn Forte 			    vpd->fcode_version,
1139*fcf3ce44SJohn Forte 			    sizeof (hba_attrs->OptionROMVersion));
1140*fcf3ce44SJohn Forte 			(void) sprintf(hba_attrs->FirmwareVersion, "%s (%s)",
1141*fcf3ce44SJohn Forte 			    vpd->fw_version, vpd->fw_label);
1142*fcf3ce44SJohn Forte 			(void) strncpy(hba_attrs->DriverName, DRIVER_NAME,
1143*fcf3ce44SJohn Forte 			    sizeof (hba_attrs->DriverName));
1144*fcf3ce44SJohn Forte 			hba_attrs->VendorSpecificID =
1145*fcf3ce44SJohn Forte 			    ((hba->model_info.device_id << 16) |
1146*fcf3ce44SJohn Forte 			    PCI_VENDOR_ID_EMULEX);
1147*fcf3ce44SJohn Forte 			hba_attrs->NumberOfPorts = hba->num_of_ports;
1148*fcf3ce44SJohn Forte 
1149*fcf3ce44SJohn Forte 			break;
1150*fcf3ce44SJohn Forte 		}
1151*fcf3ce44SJohn Forte 
1152*fcf3ce44SJohn Forte 	case FCIO_GET_ADAPTER_PORT_ATTRIBUTES:
1153*fcf3ce44SJohn Forte 		{
1154*fcf3ce44SJohn Forte 			fc_hba_port_attributes_t *port_attrs;
1155*fcf3ce44SJohn Forte 			uint32_t value1;
1156*fcf3ce44SJohn Forte 			uint32_t value2;
1157*fcf3ce44SJohn Forte 
1158*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1159*fcf3ce44SJohn Forte 			    fcio->fcio_olen <
1160*fcf3ce44SJohn Forte 			    sizeof (fc_hba_port_attributes_t)) {
1161*fcf3ce44SJohn Forte 				rval = EINVAL;
1162*fcf3ce44SJohn Forte 				break;
1163*fcf3ce44SJohn Forte 			}
1164*fcf3ce44SJohn Forte 			port_attrs =
1165*fcf3ce44SJohn Forte 			    (fc_hba_port_attributes_t *)fcio->fcio_obuf;
1166*fcf3ce44SJohn Forte 
1167*fcf3ce44SJohn Forte 			port_attrs->version = FC_HBA_PORT_ATTRIBUTES_VERSION;
1168*fcf3ce44SJohn Forte 			port_attrs->lastChange = 0;
1169*fcf3ce44SJohn Forte 			port_attrs->fp_minor = 0;
1170*fcf3ce44SJohn Forte 			bcopy((caddr_t)&port->wwnn,
1171*fcf3ce44SJohn Forte 			    (caddr_t)&port_attrs->NodeWWN, 8);
1172*fcf3ce44SJohn Forte 			bcopy((caddr_t)&port->wwpn,
1173*fcf3ce44SJohn Forte 			    (caddr_t)&port_attrs->PortWWN, 8);
1174*fcf3ce44SJohn Forte 
1175*fcf3ce44SJohn Forte 			if (hba->state <= FC_LINK_DOWN) {
1176*fcf3ce44SJohn Forte 				/* port_attrs->PortFcId   */
1177*fcf3ce44SJohn Forte 				/* port_attrs->PortType   */
1178*fcf3ce44SJohn Forte 				/* port_attrs->PortSpeed  */
1179*fcf3ce44SJohn Forte 				/* port_attrs->FabricName */
1180*fcf3ce44SJohn Forte 				port_attrs->PortState =
1181*fcf3ce44SJohn Forte 				    FC_HBA_PORTSTATE_OFFLINE;
1182*fcf3ce44SJohn Forte 			} else {
1183*fcf3ce44SJohn Forte 				port_attrs->PortFcId = port->did;
1184*fcf3ce44SJohn Forte 				port_attrs->PortState =
1185*fcf3ce44SJohn Forte 				    FC_HBA_PORTSTATE_ONLINE;
1186*fcf3ce44SJohn Forte 
1187*fcf3ce44SJohn Forte 				if (hba->topology == TOPOLOGY_LOOP) {
1188*fcf3ce44SJohn Forte 					port_attrs->PortType =
1189*fcf3ce44SJohn Forte 					    FC_HBA_PORTTYPE_LPORT;
1190*fcf3ce44SJohn Forte 				} else {
1191*fcf3ce44SJohn Forte 					port_attrs->PortType =
1192*fcf3ce44SJohn Forte 					    FC_HBA_PORTTYPE_NPORT;
1193*fcf3ce44SJohn Forte 				}
1194*fcf3ce44SJohn Forte 
1195*fcf3ce44SJohn Forte 				ndlp = emlxs_node_find_did(port, Fabric_DID);
1196*fcf3ce44SJohn Forte 
1197*fcf3ce44SJohn Forte 				if (ndlp) {
1198*fcf3ce44SJohn Forte 					bcopy(&ndlp->nlp_portname, (caddr_t)
1199*fcf3ce44SJohn Forte 					    &port_attrs->FabricName,
1200*fcf3ce44SJohn Forte 					    sizeof (port_attrs->FabricName));
1201*fcf3ce44SJohn Forte 				}
1202*fcf3ce44SJohn Forte 				switch (hba->linkspeed) {
1203*fcf3ce44SJohn Forte 				case 0:
1204*fcf3ce44SJohn Forte 					port_attrs->PortSpeed =
1205*fcf3ce44SJohn Forte 					    HBA_PORTSPEED_1GBIT;
1206*fcf3ce44SJohn Forte 					break;
1207*fcf3ce44SJohn Forte 				case LA_1GHZ_LINK:
1208*fcf3ce44SJohn Forte 					port_attrs->PortSpeed =
1209*fcf3ce44SJohn Forte 					    HBA_PORTSPEED_1GBIT;
1210*fcf3ce44SJohn Forte 					break;
1211*fcf3ce44SJohn Forte 				case LA_2GHZ_LINK:
1212*fcf3ce44SJohn Forte 					port_attrs->PortSpeed =
1213*fcf3ce44SJohn Forte 					    HBA_PORTSPEED_2GBIT;
1214*fcf3ce44SJohn Forte 					break;
1215*fcf3ce44SJohn Forte 				case LA_4GHZ_LINK:
1216*fcf3ce44SJohn Forte 					port_attrs->PortSpeed =
1217*fcf3ce44SJohn Forte 					    HBA_PORTSPEED_4GBIT;
1218*fcf3ce44SJohn Forte 					break;
1219*fcf3ce44SJohn Forte 				case LA_8GHZ_LINK:
1220*fcf3ce44SJohn Forte 					port_attrs->PortSpeed =
1221*fcf3ce44SJohn Forte 					    HBA_PORTSPEED_8GBIT;
1222*fcf3ce44SJohn Forte 					break;
1223*fcf3ce44SJohn Forte 				case LA_10GHZ_LINK:
1224*fcf3ce44SJohn Forte 					port_attrs->PortSpeed =
1225*fcf3ce44SJohn Forte 					    HBA_PORTSPEED_10GBIT;
1226*fcf3ce44SJohn Forte 					break;
1227*fcf3ce44SJohn Forte 				default:
1228*fcf3ce44SJohn Forte 					port_attrs->PortSpeed =
1229*fcf3ce44SJohn Forte 					    HBA_PORTSPEED_UNKNOWN;
1230*fcf3ce44SJohn Forte 
1231*fcf3ce44SJohn Forte 				}
1232*fcf3ce44SJohn Forte 			}
1233*fcf3ce44SJohn Forte 
1234*fcf3ce44SJohn Forte 			port_attrs->PortSupportedClassofService =
1235*fcf3ce44SJohn Forte 			    SWAP_DATA32(FC_NS_CLASS3);
1236*fcf3ce44SJohn Forte 			(void) strncpy((caddr_t)port_attrs->PortSymbolicName,
1237*fcf3ce44SJohn Forte 			    (caddr_t)port->spn,
1238*fcf3ce44SJohn Forte 			    sizeof (port_attrs->PortSymbolicName));
1239*fcf3ce44SJohn Forte 
1240*fcf3ce44SJohn Forte 			/* Set the hba speed limit */
1241*fcf3ce44SJohn Forte 			if (vpd->link_speed & LMT_10GB_CAPABLE) {
1242*fcf3ce44SJohn Forte 				port_attrs->PortSupportedSpeed |=
1243*fcf3ce44SJohn Forte 				    FC_HBA_PORTSPEED_10GBIT;
1244*fcf3ce44SJohn Forte 			}
1245*fcf3ce44SJohn Forte 			if (vpd->link_speed & LMT_8GB_CAPABLE) {
1246*fcf3ce44SJohn Forte 				port_attrs->PortSupportedSpeed |=
1247*fcf3ce44SJohn Forte 				    FC_HBA_PORTSPEED_8GBIT;
1248*fcf3ce44SJohn Forte 			}
1249*fcf3ce44SJohn Forte 			if (vpd->link_speed & LMT_4GB_CAPABLE) {
1250*fcf3ce44SJohn Forte 				port_attrs->PortSupportedSpeed |=
1251*fcf3ce44SJohn Forte 				    FC_HBA_PORTSPEED_4GBIT;
1252*fcf3ce44SJohn Forte 			}
1253*fcf3ce44SJohn Forte 			if (vpd->link_speed & LMT_2GB_CAPABLE) {
1254*fcf3ce44SJohn Forte 				port_attrs->PortSupportedSpeed |=
1255*fcf3ce44SJohn Forte 				    FC_HBA_PORTSPEED_2GBIT;
1256*fcf3ce44SJohn Forte 			}
1257*fcf3ce44SJohn Forte 			if (vpd->link_speed & LMT_1GB_CAPABLE) {
1258*fcf3ce44SJohn Forte 				port_attrs->PortSupportedSpeed |=
1259*fcf3ce44SJohn Forte 				    FC_HBA_PORTSPEED_1GBIT;
1260*fcf3ce44SJohn Forte 			}
1261*fcf3ce44SJohn Forte 			value1 = 0x00000120;
1262*fcf3ce44SJohn Forte 			value2 = 0x00000001;
1263*fcf3ce44SJohn Forte 
1264*fcf3ce44SJohn Forte 			bcopy((caddr_t)&value1,
1265*fcf3ce44SJohn Forte 			    (caddr_t)&port_attrs->PortSupportedFc4Types[0],
1266*fcf3ce44SJohn Forte 			    4);
1267*fcf3ce44SJohn Forte 			bcopy((caddr_t)&value2,
1268*fcf3ce44SJohn Forte 			    (caddr_t)&port_attrs->PortSupportedFc4Types[4],
1269*fcf3ce44SJohn Forte 			    4);
1270*fcf3ce44SJohn Forte 
1271*fcf3ce44SJohn Forte 			bcopy((caddr_t)&value1,
1272*fcf3ce44SJohn Forte 			    (caddr_t)&port_attrs->PortActiveFc4Types[0], 4);
1273*fcf3ce44SJohn Forte 			bcopy((caddr_t)&value2,
1274*fcf3ce44SJohn Forte 			    (caddr_t)&port_attrs->PortActiveFc4Types[4], 4);
1275*fcf3ce44SJohn Forte 
1276*fcf3ce44SJohn Forte 			port_attrs->PortMaxFrameSize = FF_FRAME_SIZE;
1277*fcf3ce44SJohn Forte 			port_attrs->NumberofDiscoveredPorts =
1278*fcf3ce44SJohn Forte 			    emlxs_nport_count(port);
1279*fcf3ce44SJohn Forte 
1280*fcf3ce44SJohn Forte 			break;
1281*fcf3ce44SJohn Forte 		}
1282*fcf3ce44SJohn Forte 
1283*fcf3ce44SJohn Forte 	case FCIO_GET_NODE_ID:
1284*fcf3ce44SJohn Forte 		{
1285*fcf3ce44SJohn Forte 			fc_fca_pm_t pm;
1286*fcf3ce44SJohn Forte 
1287*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1288*fcf3ce44SJohn Forte 			    fcio->fcio_olen < sizeof (fc_rnid_t)) {
1289*fcf3ce44SJohn Forte 				rval = EINVAL;
1290*fcf3ce44SJohn Forte 				break;
1291*fcf3ce44SJohn Forte 			}
1292*fcf3ce44SJohn Forte 			bzero((caddr_t)&pm, sizeof (pm));
1293*fcf3ce44SJohn Forte 
1294*fcf3ce44SJohn Forte 			pm.pm_cmd_flags = FC_FCA_PM_READ;
1295*fcf3ce44SJohn Forte 			pm.pm_cmd_code = FC_PORT_GET_NODE_ID;
1296*fcf3ce44SJohn Forte 			pm.pm_data_len = fcio->fcio_olen;
1297*fcf3ce44SJohn Forte 			pm.pm_data_buf = fcio->fcio_obuf;
1298*fcf3ce44SJohn Forte 
1299*fcf3ce44SJohn Forte 			rval = emlxs_port_manage(port, &pm);
1300*fcf3ce44SJohn Forte 
1301*fcf3ce44SJohn Forte 			if (rval != FC_SUCCESS) {
1302*fcf3ce44SJohn Forte 				fcio->fcio_errno = rval;
1303*fcf3ce44SJohn Forte 				rval = EIO;
1304*fcf3ce44SJohn Forte 			}
1305*fcf3ce44SJohn Forte 			break;
1306*fcf3ce44SJohn Forte 		}
1307*fcf3ce44SJohn Forte 
1308*fcf3ce44SJohn Forte 	case FCIO_SET_NODE_ID:
1309*fcf3ce44SJohn Forte 		{
1310*fcf3ce44SJohn Forte 			fc_fca_pm_t pm;
1311*fcf3ce44SJohn Forte 
1312*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1313*fcf3ce44SJohn Forte 			    fcio->fcio_ilen < sizeof (fc_rnid_t)) {
1314*fcf3ce44SJohn Forte 				rval = EINVAL;
1315*fcf3ce44SJohn Forte 				break;
1316*fcf3ce44SJohn Forte 			}
1317*fcf3ce44SJohn Forte 			bzero((caddr_t)&pm, sizeof (pm));
1318*fcf3ce44SJohn Forte 
1319*fcf3ce44SJohn Forte 			pm.pm_cmd_flags = FC_FCA_PM_READ;
1320*fcf3ce44SJohn Forte 			pm.pm_cmd_code = FC_PORT_SET_NODE_ID;
1321*fcf3ce44SJohn Forte 			pm.pm_data_len = fcio->fcio_ilen;
1322*fcf3ce44SJohn Forte 			pm.pm_data_buf = fcio->fcio_ibuf;
1323*fcf3ce44SJohn Forte 
1324*fcf3ce44SJohn Forte 			rval = emlxs_port_manage(port, &pm);
1325*fcf3ce44SJohn Forte 
1326*fcf3ce44SJohn Forte 			if (rval != FC_SUCCESS) {
1327*fcf3ce44SJohn Forte 				fcio->fcio_errno = rval;
1328*fcf3ce44SJohn Forte 				rval = EIO;
1329*fcf3ce44SJohn Forte 			}
1330*fcf3ce44SJohn Forte 			break;
1331*fcf3ce44SJohn Forte 		}
1332*fcf3ce44SJohn Forte 
1333*fcf3ce44SJohn Forte 	case FCIO_GET_NUM_DEVS:
1334*fcf3ce44SJohn Forte 		{
1335*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1336*fcf3ce44SJohn Forte 			    fcio->fcio_olen < sizeof (uint32_t)) {
1337*fcf3ce44SJohn Forte 				rval = EINVAL;
1338*fcf3ce44SJohn Forte 				break;
1339*fcf3ce44SJohn Forte 			}
1340*fcf3ce44SJohn Forte 			*(uint32_t *)fcio->fcio_obuf = emlxs_nport_count(port);
1341*fcf3ce44SJohn Forte 
1342*fcf3ce44SJohn Forte 			break;
1343*fcf3ce44SJohn Forte 		}
1344*fcf3ce44SJohn Forte 
1345*fcf3ce44SJohn Forte 	case FCIO_GET_DEV_LIST:
1346*fcf3ce44SJohn Forte 		{
1347*fcf3ce44SJohn Forte 			fc_port_dev_t *port_dev;
1348*fcf3ce44SJohn Forte 			uint32_t max_count;
1349*fcf3ce44SJohn Forte 			uint32_t i;
1350*fcf3ce44SJohn Forte 			uint32_t j;
1351*fcf3ce44SJohn Forte 			emlxs_node_t *nlp;
1352*fcf3ce44SJohn Forte 			uint32_t nport_count;
1353*fcf3ce44SJohn Forte 			caddr_t np;
1354*fcf3ce44SJohn Forte 			caddr_t wp;
1355*fcf3ce44SJohn Forte 
1356*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1357*fcf3ce44SJohn Forte 			    fcio->fcio_alen < sizeof (uint32_t)) {
1358*fcf3ce44SJohn Forte 				rval = EINVAL;
1359*fcf3ce44SJohn Forte 				break;
1360*fcf3ce44SJohn Forte 			}
1361*fcf3ce44SJohn Forte 			port_dev = (fc_port_dev_t *)fcio->fcio_obuf;
1362*fcf3ce44SJohn Forte 			max_count = fcio->fcio_olen / sizeof (fc_port_dev_t);
1363*fcf3ce44SJohn Forte 
1364*fcf3ce44SJohn Forte 			rw_enter(&port->node_rwlock, RW_READER);
1365*fcf3ce44SJohn Forte 
1366*fcf3ce44SJohn Forte 			nport_count = emlxs_nport_count(port);
1367*fcf3ce44SJohn Forte 			*(uint32_t *)fcio->fcio_abuf = nport_count;
1368*fcf3ce44SJohn Forte 
1369*fcf3ce44SJohn Forte 			if (nport_count == 0) {
1370*fcf3ce44SJohn Forte 				rw_exit(&port->node_rwlock);
1371*fcf3ce44SJohn Forte 
1372*fcf3ce44SJohn Forte 				fcio->fcio_errno = FC_NO_MAP;
1373*fcf3ce44SJohn Forte 				rval = EIO;
1374*fcf3ce44SJohn Forte 				break;
1375*fcf3ce44SJohn Forte 			}
1376*fcf3ce44SJohn Forte 			if (nport_count > max_count) {
1377*fcf3ce44SJohn Forte 				rw_exit(&port->node_rwlock);
1378*fcf3ce44SJohn Forte 
1379*fcf3ce44SJohn Forte 				fcio->fcio_errno = FC_TOOMANY;
1380*fcf3ce44SJohn Forte 				rval = EIO;
1381*fcf3ce44SJohn Forte 				break;
1382*fcf3ce44SJohn Forte 			}
1383*fcf3ce44SJohn Forte 
1384*fcf3ce44SJohn Forte #define	TOP_LOOP()	for (j = 1; j < port->alpa_map[0]; j++) { \
1385*fcf3ce44SJohn Forte 				if (nlp->nlp_DID == port->alpa_map[j]) { \
1386*fcf3ce44SJohn Forte 					PRIV_LILP_POSIT(port_dev) = j - 1; \
1387*fcf3ce44SJohn Forte 					break; \
1388*fcf3ce44SJohn Forte 				} \
1389*fcf3ce44SJohn Forte 			}
1390*fcf3ce44SJohn Forte 
1391*fcf3ce44SJohn Forte 
1392*fcf3ce44SJohn Forte 			for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
1393*fcf3ce44SJohn Forte 				nlp = port->node_table[i];
1394*fcf3ce44SJohn Forte 				while (nlp != NULL) {
1395*fcf3ce44SJohn Forte 					if ((nlp->nlp_DID & 0xFFF000) !=
1396*fcf3ce44SJohn Forte 					    0xFFF000) {
1397*fcf3ce44SJohn Forte 						port_dev->dev_dtype = 0;
1398*fcf3ce44SJohn Forte 						port_dev->dev_type[0] =
1399*fcf3ce44SJohn Forte 						    SWAP_LONG(0x00000100);
1400*fcf3ce44SJohn Forte 						port_dev->dev_state =
1401*fcf3ce44SJohn Forte 						    PORT_DEVICE_LOGGED_IN;
1402*fcf3ce44SJohn Forte 						port_dev->dev_did.port_id =
1403*fcf3ce44SJohn Forte 						    nlp->nlp_DID;
1404*fcf3ce44SJohn Forte 						PRIV_LILP_POSIT(port_dev) = 0;
1405*fcf3ce44SJohn Forte 						HARD_ADDR(port_dev) = 0;
1406*fcf3ce44SJohn Forte 
1407*fcf3ce44SJohn Forte 						if (hba->topology ==
1408*fcf3ce44SJohn Forte 						    TOPOLOGY_LOOP) {
1409*fcf3ce44SJohn Forte 
1410*fcf3ce44SJohn Forte 	for (j = 1; j < port->alpa_map[0]; j++) {
1411*fcf3ce44SJohn Forte 		if (nlp->nlp_DID == port->alpa_map[j]) {
1412*fcf3ce44SJohn Forte 			PRIV_LILP_POSIT(port_dev) = j - 1;
1413*fcf3ce44SJohn Forte 			break;
1414*fcf3ce44SJohn Forte 		}
1415*fcf3ce44SJohn Forte 	}
1416*fcf3ce44SJohn Forte 							HARD_ADDR(port_dev) =
1417*fcf3ce44SJohn Forte 							    nlp->nlp_DID;
1418*fcf3ce44SJohn Forte 
1419*fcf3ce44SJohn Forte 						}
1420*fcf3ce44SJohn Forte 
1421*fcf3ce44SJohn Forte 						np = (caddr_t)
1422*fcf3ce44SJohn Forte 						    &nlp->nlp_portname;
1423*fcf3ce44SJohn Forte 						wp = (caddr_t)
1424*fcf3ce44SJohn Forte 						    &port_dev->dev_pwwn;
1425*fcf3ce44SJohn Forte 						bcopy(np, wp, 8);
1426*fcf3ce44SJohn Forte 
1427*fcf3ce44SJohn Forte 						np = (caddr_t)
1428*fcf3ce44SJohn Forte 						    &nlp->nlp_nodename;
1429*fcf3ce44SJohn Forte 						wp = (caddr_t)
1430*fcf3ce44SJohn Forte 						    &port_dev->dev_nwwn;
1431*fcf3ce44SJohn Forte 						bcopy(np, wp, 8);
1432*fcf3ce44SJohn Forte 						port_dev++;
1433*fcf3ce44SJohn Forte 					}
1434*fcf3ce44SJohn Forte 					nlp = (NODELIST *) nlp->nlp_list_next;
1435*fcf3ce44SJohn Forte 				}
1436*fcf3ce44SJohn Forte 			}
1437*fcf3ce44SJohn Forte 			rw_exit(&port->node_rwlock);
1438*fcf3ce44SJohn Forte 
1439*fcf3ce44SJohn Forte 			break;
1440*fcf3ce44SJohn Forte 		}
1441*fcf3ce44SJohn Forte 
1442*fcf3ce44SJohn Forte 	case FCIO_GET_LOGI_PARAMS:
1443*fcf3ce44SJohn Forte 		{
1444*fcf3ce44SJohn Forte 			uint8_t null_wwn[8];
1445*fcf3ce44SJohn Forte 
1446*fcf3ce44SJohn Forte 			if (fcio->fcio_ilen != sizeof (la_wwn_t) ||
1447*fcf3ce44SJohn Forte 			    (fcio->fcio_xfer & FCIO_XFER_READ) == 0 ||
1448*fcf3ce44SJohn Forte 			    (fcio->fcio_xfer & FCIO_XFER_WRITE) == 0) {
1449*fcf3ce44SJohn Forte 				rval = EINVAL;
1450*fcf3ce44SJohn Forte 				break;
1451*fcf3ce44SJohn Forte 			}
1452*fcf3ce44SJohn Forte 			bzero(null_wwn, 8);
1453*fcf3ce44SJohn Forte 			wwpn = (uint8_t *)fcio->fcio_ibuf;
1454*fcf3ce44SJohn Forte 
1455*fcf3ce44SJohn Forte 			if ((bcmp((caddr_t)wwpn, (caddr_t)null_wwn, 8) == 0) ||
1456*fcf3ce44SJohn Forte 			    (bcmp((caddr_t)wwpn,
1457*fcf3ce44SJohn Forte 			    (caddr_t)&port->wwpn, 8) == 0)) {
1458*fcf3ce44SJohn Forte 				bcopy((caddr_t)&port->sparam,
1459*fcf3ce44SJohn Forte 				    (caddr_t)fcio->fcio_obuf, fcio->fcio_olen);
1460*fcf3ce44SJohn Forte 			} else {
1461*fcf3ce44SJohn Forte 				ndlp = emlxs_node_find_wwpn(port, wwpn);
1462*fcf3ce44SJohn Forte 
1463*fcf3ce44SJohn Forte 				if (ndlp) {
1464*fcf3ce44SJohn Forte 					bcopy((caddr_t)&ndlp->sparm,
1465*fcf3ce44SJohn Forte 					    (caddr_t)fcio->fcio_obuf,
1466*fcf3ce44SJohn Forte 					    fcio->fcio_olen);
1467*fcf3ce44SJohn Forte 				} else {
1468*fcf3ce44SJohn Forte 					rval = ENXIO;
1469*fcf3ce44SJohn Forte 				}
1470*fcf3ce44SJohn Forte 			}
1471*fcf3ce44SJohn Forte 
1472*fcf3ce44SJohn Forte 			break;
1473*fcf3ce44SJohn Forte 		}
1474*fcf3ce44SJohn Forte 
1475*fcf3ce44SJohn Forte 	case FCIO_GET_STATE:
1476*fcf3ce44SJohn Forte 		{
1477*fcf3ce44SJohn Forte 			uint8_t null_wwn[8];
1478*fcf3ce44SJohn Forte 			uint32_t *statep;
1479*fcf3ce44SJohn Forte 
1480*fcf3ce44SJohn Forte 			if (fcio->fcio_ilen != 8 ||
1481*fcf3ce44SJohn Forte 			    fcio->fcio_olen != 4 ||
1482*fcf3ce44SJohn Forte 			    (fcio->fcio_xfer & FCIO_XFER_WRITE) == 0 ||
1483*fcf3ce44SJohn Forte 			    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
1484*fcf3ce44SJohn Forte 				rval = EINVAL;
1485*fcf3ce44SJohn Forte 				break;
1486*fcf3ce44SJohn Forte 			}
1487*fcf3ce44SJohn Forte 			bzero(null_wwn, 8);
1488*fcf3ce44SJohn Forte 			wwpn = (uint8_t *)fcio->fcio_ibuf;
1489*fcf3ce44SJohn Forte 			statep = (uint32_t *)fcio->fcio_obuf;
1490*fcf3ce44SJohn Forte 
1491*fcf3ce44SJohn Forte 			if ((bcmp((caddr_t)wwpn, (caddr_t)null_wwn, 8) == 0) ||
1492*fcf3ce44SJohn Forte 			    (bcmp((caddr_t)wwpn,
1493*fcf3ce44SJohn Forte 			    (caddr_t)&port->wwpn, 8) == 0)) {
1494*fcf3ce44SJohn Forte 				*statep = PORT_DEVICE_VALID;
1495*fcf3ce44SJohn Forte 			} else {
1496*fcf3ce44SJohn Forte 				ndlp = emlxs_node_find_wwpn(port, wwpn);
1497*fcf3ce44SJohn Forte 
1498*fcf3ce44SJohn Forte 				if (ndlp) {
1499*fcf3ce44SJohn Forte 					*statep = PORT_DEVICE_VALID;
1500*fcf3ce44SJohn Forte 				} else {
1501*fcf3ce44SJohn Forte 					*statep = PORT_DEVICE_INVALID;
1502*fcf3ce44SJohn Forte 				}
1503*fcf3ce44SJohn Forte 			}
1504*fcf3ce44SJohn Forte 
1505*fcf3ce44SJohn Forte 			break;
1506*fcf3ce44SJohn Forte 		}
1507*fcf3ce44SJohn Forte 
1508*fcf3ce44SJohn Forte 	case FCIO_GET_TOPOLOGY:
1509*fcf3ce44SJohn Forte 		{
1510*fcf3ce44SJohn Forte 			uint32_t *tp;
1511*fcf3ce44SJohn Forte 
1512*fcf3ce44SJohn Forte 			if (fcio->fcio_olen != 4 ||
1513*fcf3ce44SJohn Forte 			    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
1514*fcf3ce44SJohn Forte 				rval = EINVAL;
1515*fcf3ce44SJohn Forte 				break;
1516*fcf3ce44SJohn Forte 			}
1517*fcf3ce44SJohn Forte 			tp = (uint32_t *)fcio->fcio_obuf;
1518*fcf3ce44SJohn Forte 
1519*fcf3ce44SJohn Forte 			if (hba->state <= FC_LINK_DOWN) {
1520*fcf3ce44SJohn Forte 				*tp = FC_TOP_UNKNOWN;
1521*fcf3ce44SJohn Forte 			} else {
1522*fcf3ce44SJohn Forte 				ndlp = emlxs_node_find_did(port, Fabric_DID);
1523*fcf3ce44SJohn Forte 
1524*fcf3ce44SJohn Forte 				if (hba->topology == TOPOLOGY_LOOP) {
1525*fcf3ce44SJohn Forte 					if (ndlp) {
1526*fcf3ce44SJohn Forte 						*tp = FC_TOP_PUBLIC_LOOP;
1527*fcf3ce44SJohn Forte 					} else {
1528*fcf3ce44SJohn Forte 						*tp = FC_TOP_PRIVATE_LOOP;
1529*fcf3ce44SJohn Forte 					}
1530*fcf3ce44SJohn Forte 				} else {
1531*fcf3ce44SJohn Forte 					if (ndlp) {
1532*fcf3ce44SJohn Forte 						*tp = FC_TOP_FABRIC;
1533*fcf3ce44SJohn Forte 					} else {
1534*fcf3ce44SJohn Forte 						*tp = FC_TOP_PT_PT;
1535*fcf3ce44SJohn Forte 					}
1536*fcf3ce44SJohn Forte 				}
1537*fcf3ce44SJohn Forte 			}
1538*fcf3ce44SJohn Forte 
1539*fcf3ce44SJohn Forte 			break;
1540*fcf3ce44SJohn Forte 		}
1541*fcf3ce44SJohn Forte 
1542*fcf3ce44SJohn Forte 	case FCIO_LINK_STATUS:
1543*fcf3ce44SJohn Forte 		{
1544*fcf3ce44SJohn Forte 			fc_portid_t *portid;
1545*fcf3ce44SJohn Forte 			fc_rls_acc_t *rls;
1546*fcf3ce44SJohn Forte 			fc_fca_pm_t pm;
1547*fcf3ce44SJohn Forte 
1548*fcf3ce44SJohn Forte 			if (fcio->fcio_ilen != sizeof (fc_portid_t) ||
1549*fcf3ce44SJohn Forte 			    fcio->fcio_olen != sizeof (fc_rls_acc_t) ||
1550*fcf3ce44SJohn Forte 			    fcio->fcio_xfer != FCIO_XFER_RW) {
1551*fcf3ce44SJohn Forte 				rval = EINVAL;
1552*fcf3ce44SJohn Forte 				break;
1553*fcf3ce44SJohn Forte 			}
1554*fcf3ce44SJohn Forte 			if ((fcio->fcio_cmd_flags !=
1555*fcf3ce44SJohn Forte 			    FCIO_CFLAGS_RLS_DEST_FPORT) &&
1556*fcf3ce44SJohn Forte 			    (fcio->fcio_cmd_flags !=
1557*fcf3ce44SJohn Forte 			    FCIO_CFLAGS_RLS_DEST_NPORT)) {
1558*fcf3ce44SJohn Forte 				rval = EINVAL;
1559*fcf3ce44SJohn Forte 				break;
1560*fcf3ce44SJohn Forte 			}
1561*fcf3ce44SJohn Forte 			portid = (fc_portid_t *)fcio->fcio_ibuf;
1562*fcf3ce44SJohn Forte 			rls = (fc_rls_acc_t *)fcio->fcio_obuf;
1563*fcf3ce44SJohn Forte 
1564*fcf3ce44SJohn Forte 			if (portid->port_id == 0 ||
1565*fcf3ce44SJohn Forte 			    portid->port_id == port->did) {
1566*fcf3ce44SJohn Forte 				bzero((caddr_t)&pm, sizeof (pm));
1567*fcf3ce44SJohn Forte 
1568*fcf3ce44SJohn Forte 				pm.pm_cmd_flags = FC_FCA_PM_READ;
1569*fcf3ce44SJohn Forte 				pm.pm_cmd_code = FC_PORT_RLS;
1570*fcf3ce44SJohn Forte 				pm.pm_data_len = sizeof (fc_rls_acc_t);
1571*fcf3ce44SJohn Forte 				pm.pm_data_buf = (caddr_t)rls;
1572*fcf3ce44SJohn Forte 
1573*fcf3ce44SJohn Forte 				rval = emlxs_port_manage(port, &pm);
1574*fcf3ce44SJohn Forte 
1575*fcf3ce44SJohn Forte 				if (rval != FC_SUCCESS) {
1576*fcf3ce44SJohn Forte 					fcio->fcio_errno = rval;
1577*fcf3ce44SJohn Forte 					rval = EIO;
1578*fcf3ce44SJohn Forte 				}
1579*fcf3ce44SJohn Forte 			} else {
1580*fcf3ce44SJohn Forte 				rval = ENOTSUP;
1581*fcf3ce44SJohn Forte 			}
1582*fcf3ce44SJohn Forte 			break;
1583*fcf3ce44SJohn Forte 		}
1584*fcf3ce44SJohn Forte 
1585*fcf3ce44SJohn Forte 	case FCIO_GET_OTHER_ADAPTER_PORTS:
1586*fcf3ce44SJohn Forte 		{
1587*fcf3ce44SJohn Forte 			uint32_t index;
1588*fcf3ce44SJohn Forte 			char *path;
1589*fcf3ce44SJohn Forte 
1590*fcf3ce44SJohn Forte 			if (fcio->fcio_olen < MAXPATHLEN ||
1591*fcf3ce44SJohn Forte 			    fcio->fcio_ilen != sizeof (uint32_t)) {
1592*fcf3ce44SJohn Forte 				rval = EINVAL;
1593*fcf3ce44SJohn Forte 				break;
1594*fcf3ce44SJohn Forte 			}
1595*fcf3ce44SJohn Forte 			index = *(uint32_t *)fcio->fcio_ibuf;
1596*fcf3ce44SJohn Forte 			path = (char *)fcio->fcio_obuf;
1597*fcf3ce44SJohn Forte 
1598*fcf3ce44SJohn Forte 			if (index > hba->vpi_max - 1) {
1599*fcf3ce44SJohn Forte 				fcio->fcio_errno = FC_BADPORT;
1600*fcf3ce44SJohn Forte 				rval = EFAULT;
1601*fcf3ce44SJohn Forte 				break;
1602*fcf3ce44SJohn Forte 			}
1603*fcf3ce44SJohn Forte 			(void) ddi_pathname(hba->dip, path);
1604*fcf3ce44SJohn Forte 
1605*fcf3ce44SJohn Forte 			break;
1606*fcf3ce44SJohn Forte 		}
1607*fcf3ce44SJohn Forte 
1608*fcf3ce44SJohn Forte 	case FCIO_GET_DISCOVERED_PORT_ATTRIBUTES:
1609*fcf3ce44SJohn Forte 		{
1610*fcf3ce44SJohn Forte 			uint32_t index;
1611*fcf3ce44SJohn Forte 
1612*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1613*fcf3ce44SJohn Forte 			    fcio->fcio_ilen < sizeof (uint32_t) ||
1614*fcf3ce44SJohn Forte 			    fcio->fcio_olen <
1615*fcf3ce44SJohn Forte 			    sizeof (fc_hba_port_attributes_t)) {
1616*fcf3ce44SJohn Forte 				rval = EINVAL;
1617*fcf3ce44SJohn Forte 				break;
1618*fcf3ce44SJohn Forte 			}
1619*fcf3ce44SJohn Forte 			index = *(uint32_t *)fcio->fcio_ibuf;
1620*fcf3ce44SJohn Forte 			ndlp = emlxs_node_find_index(port, index, 1);
1621*fcf3ce44SJohn Forte 
1622*fcf3ce44SJohn Forte 			if (!ndlp) {
1623*fcf3ce44SJohn Forte 				fcio->fcio_errno = FC_OUTOFBOUNDS;
1624*fcf3ce44SJohn Forte 				rval = EINVAL;
1625*fcf3ce44SJohn Forte 				break;
1626*fcf3ce44SJohn Forte 			}
1627*fcf3ce44SJohn Forte 			goto get_node_attrs;
1628*fcf3ce44SJohn Forte 		}
1629*fcf3ce44SJohn Forte 
1630*fcf3ce44SJohn Forte 		/* Same as FCIO_GET_DISCOVERED_PORT_ATTRIBUTES */
1631*fcf3ce44SJohn Forte 		/* except WWPN is used instead of index */
1632*fcf3ce44SJohn Forte 	case FCIO_GET_PORT_ATTRIBUTES:
1633*fcf3ce44SJohn Forte 		{
1634*fcf3ce44SJohn Forte 			emlxs_node_t *ndlp2;
1635*fcf3ce44SJohn Forte 			/* uint32_t value1; */
1636*fcf3ce44SJohn Forte 
1637*fcf3ce44SJohn Forte 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1638*fcf3ce44SJohn Forte 			    fcio->fcio_ilen < 8 ||
1639*fcf3ce44SJohn Forte 			    fcio->fcio_olen <
1640*fcf3ce44SJohn Forte 			    sizeof (fc_hba_port_attributes_t)) {
1641*fcf3ce44SJohn Forte 				rval = EINVAL;
1642*fcf3ce44SJohn Forte 				break;
1643*fcf3ce44SJohn Forte 			}
1644*fcf3ce44SJohn Forte 			wwpn = (uint8_t *)fcio->fcio_ibuf;
1645*fcf3ce44SJohn Forte 			ndlp = emlxs_node_find_wwpn(port, wwpn);
1646*fcf3ce44SJohn Forte 
1647*fcf3ce44SJohn Forte 			if (!ndlp) {
1648*fcf3ce44SJohn Forte 				fcio->fcio_errno = FC_NOMAP;
1649*fcf3ce44SJohn Forte 				rval = EINVAL;
1650*fcf3ce44SJohn Forte 				break;
1651*fcf3ce44SJohn Forte 			}
1652*fcf3ce44SJohn Forte 			/* Filter fabric ports */
1653*fcf3ce44SJohn Forte 			if ((ndlp->nlp_DID & 0xFFF000) == 0xFFF000) {
1654*fcf3ce44SJohn Forte 				fcio->fcio_errno = FC_NOMAP;
1655*fcf3ce44SJohn Forte 				rval = EINVAL;
1656*fcf3ce44SJohn Forte 				break;
1657*fcf3ce44SJohn Forte 			}
1658*fcf3ce44SJohn Forte 	get_node_attrs:
1659*fcf3ce44SJohn Forte 
1660*fcf3ce44SJohn Forte 			port_attrs =
1661*fcf3ce44SJohn Forte 			    (fc_hba_port_attributes_t *)fcio->fcio_obuf;
1662*fcf3ce44SJohn Forte 
1663*fcf3ce44SJohn Forte 			port_attrs->version = FC_HBA_PORT_ATTRIBUTES_VERSION;
1664*fcf3ce44SJohn Forte 			/* port_attrs->lastChange */
1665*fcf3ce44SJohn Forte 			/* port_attrs->fp_minor   */
1666*fcf3ce44SJohn Forte 			bcopy((caddr_t)&ndlp->nlp_nodename,
1667*fcf3ce44SJohn Forte 			    (caddr_t)&port_attrs->NodeWWN, 8);
1668*fcf3ce44SJohn Forte 			bcopy((caddr_t)&ndlp->nlp_portname,
1669*fcf3ce44SJohn Forte 			    (caddr_t)&port_attrs->PortWWN, 8);
1670*fcf3ce44SJohn Forte 
1671*fcf3ce44SJohn Forte 			port_attrs->PortSpeed = HBA_PORTSPEED_UNKNOWN;
1672*fcf3ce44SJohn Forte 			port_attrs->PortType = FC_HBA_PORTTYPE_UNKNOWN;
1673*fcf3ce44SJohn Forte 			port_attrs->PortState = FC_HBA_PORTSTATE_OFFLINE;
1674*fcf3ce44SJohn Forte 
1675*fcf3ce44SJohn Forte 			if (hba->state > FC_LINK_UP) {
1676*fcf3ce44SJohn Forte 				ndlp2 = emlxs_node_find_did(port, Fabric_DID);
1677*fcf3ce44SJohn Forte 
1678*fcf3ce44SJohn Forte 				port_attrs->PortFcId = ndlp->nlp_DID;
1679*fcf3ce44SJohn Forte 				port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
1680*fcf3ce44SJohn Forte 
1681*fcf3ce44SJohn Forte 				/* no switch */
1682*fcf3ce44SJohn Forte 				if (!ndlp2) {
1683*fcf3ce44SJohn Forte 					if (hba->topology == TOPOLOGY_LOOP) {
1684*fcf3ce44SJohn Forte 						port_attrs->PortType =
1685*fcf3ce44SJohn Forte 						    FC_HBA_PORTTYPE_LPORT;
1686*fcf3ce44SJohn Forte 					} else {
1687*fcf3ce44SJohn Forte 						port_attrs->PortType =
1688*fcf3ce44SJohn Forte 						    FC_HBA_PORTTYPE_PTP;
1689*fcf3ce44SJohn Forte 					}
1690*fcf3ce44SJohn Forte 
1691*fcf3ce44SJohn Forte 					/* We share a common speed */
1692*fcf3ce44SJohn Forte 					switch (hba->linkspeed) {
1693*fcf3ce44SJohn Forte 					case 0:
1694*fcf3ce44SJohn Forte 						port_attrs->PortSpeed =
1695*fcf3ce44SJohn Forte 						    HBA_PORTSPEED_1GBIT;
1696*fcf3ce44SJohn Forte 						break;
1697*fcf3ce44SJohn Forte 					case LA_1GHZ_LINK:
1698*fcf3ce44SJohn Forte 						port_attrs->PortSpeed =
1699*fcf3ce44SJohn Forte 						    HBA_PORTSPEED_1GBIT;
1700*fcf3ce44SJohn Forte 						break;
1701*fcf3ce44SJohn Forte 					case LA_2GHZ_LINK:
1702*fcf3ce44SJohn Forte 						port_attrs->PortSpeed =
1703*fcf3ce44SJohn Forte 						    HBA_PORTSPEED_2GBIT;
1704*fcf3ce44SJohn Forte 						break;
1705*fcf3ce44SJohn Forte 					case LA_4GHZ_LINK:
1706*fcf3ce44SJohn Forte 						port_attrs->PortSpeed =
1707*fcf3ce44SJohn Forte 						    HBA_PORTSPEED_4GBIT;
1708*fcf3ce44SJohn Forte 						break;
1709*fcf3ce44SJohn Forte 					case LA_8GHZ_LINK:
1710*fcf3ce44SJohn Forte 						port_attrs->PortSpeed =
1711*fcf3ce44SJohn Forte 						    HBA_PORTSPEED_8GBIT;
1712*fcf3ce44SJohn Forte 						break;
1713*fcf3ce44SJohn Forte 					case LA_10GHZ_LINK:
1714*fcf3ce44SJohn Forte 						port_attrs->PortSpeed =
1715*fcf3ce44SJohn Forte 						    HBA_PORTSPEED_10GBIT;
1716*fcf3ce44SJohn Forte 						break;
1717*fcf3ce44SJohn Forte 					}
1718*fcf3ce44SJohn Forte 				}
1719*fcf3ce44SJohn Forte 				/* public loop */
1720*fcf3ce44SJohn Forte 				else if (hba->topology == TOPOLOGY_LOOP) {
1721*fcf3ce44SJohn Forte 					/* Check for common area and domain */
1722*fcf3ce44SJohn Forte 					if ((ndlp->nlp_DID & 0xFFFF00) ==
1723*fcf3ce44SJohn Forte 					    (port->did & 0xFFFF00)) {
1724*fcf3ce44SJohn Forte 						port_attrs->PortType =
1725*fcf3ce44SJohn Forte 						    FC_HBA_PORTTYPE_NLPORT;
1726*fcf3ce44SJohn Forte 
1727*fcf3ce44SJohn Forte 						/* We share a common speed */
1728*fcf3ce44SJohn Forte 						switch (hba->linkspeed) {
1729*fcf3ce44SJohn Forte 						case 0:
1730*fcf3ce44SJohn Forte 							port_attrs->PortSpeed =
1731*fcf3ce44SJohn Forte 							    HBA_PORTSPEED_1GBIT;
1732*fcf3ce44SJohn Forte 							break;
1733*fcf3ce44SJohn Forte 						case LA_1GHZ_LINK:
1734*fcf3ce44SJohn Forte 							port_attrs->PortSpeed =
1735*fcf3ce44SJohn Forte 							    HBA_PORTSPEED_1GBIT;
1736*fcf3ce44SJohn Forte 							break;
1737*fcf3ce44SJohn Forte 						case LA_2GHZ_LINK:
1738*fcf3ce44SJohn Forte 							port_attrs->PortSpeed =
1739*fcf3ce44SJohn Forte 							    HBA_PORTSPEED_2GBIT;
1740*fcf3ce44SJohn Forte 							break;
1741*fcf3ce44SJohn Forte 						case LA_4GHZ_LINK:
1742*fcf3ce44SJohn Forte 							port_attrs->PortSpeed =
1743*fcf3ce44SJohn Forte 							    HBA_PORTSPEED_4GBIT;
1744*fcf3ce44SJohn Forte 							break;
1745*fcf3ce44SJohn Forte 						case LA_8GHZ_LINK:
1746*fcf3ce44SJohn Forte 							port_attrs->PortSpeed =
1747*fcf3ce44SJohn Forte 							    HBA_PORTSPEED_8GBIT;
1748*fcf3ce44SJohn Forte 							break;
1749*fcf3ce44SJohn Forte 						case LA_10GHZ_LINK:
1750*fcf3ce44SJohn Forte 							port_attrs->PortSpeed =
1751*fcf3ce44SJohn Forte 							    HBA_10GBIT;
1752*fcf3ce44SJohn Forte 							break;
1753*fcf3ce44SJohn Forte 						}
1754*fcf3ce44SJohn Forte 					}
1755*fcf3ce44SJohn Forte 				}
1756*fcf3ce44SJohn Forte 			}
1757*fcf3ce44SJohn Forte 			port_attrs->PortSupportedClassofService =
1758*fcf3ce44SJohn Forte 			    SWAP_DATA32(FC_NS_CLASS3);
1759*fcf3ce44SJohn Forte 			/* port_attrs->PortSymbolicName		*/
1760*fcf3ce44SJohn Forte 			/* port_attrs->PortSupportedSpeed	*/
1761*fcf3ce44SJohn Forte 			/* port_attrs->PortSupportedFc4Types	*/
1762*fcf3ce44SJohn Forte 			/* port_attrs->PortActiveFc4Types	*/
1763*fcf3ce44SJohn Forte 			/* port_attrs->PortMaxFrameSize		*/
1764*fcf3ce44SJohn Forte 			/* port_attrs->NumberofDiscoveredPorts	*/
1765*fcf3ce44SJohn Forte 
1766*fcf3ce44SJohn Forte 			break;
1767*fcf3ce44SJohn Forte 		}
1768*fcf3ce44SJohn Forte 
1769*fcf3ce44SJohn Forte 	case FCIO_GET_SYM_PNAME:
1770*fcf3ce44SJohn Forte 		{
1771*fcf3ce44SJohn Forte 			if (fcio->fcio_olen < (strlen(port->spn) + 1) ||
1772*fcf3ce44SJohn Forte 			    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
1773*fcf3ce44SJohn Forte 				rval = EINVAL;
1774*fcf3ce44SJohn Forte 				break;
1775*fcf3ce44SJohn Forte 			}
1776*fcf3ce44SJohn Forte 			(void) strcpy((caddr_t)fcio->fcio_obuf,
1777*fcf3ce44SJohn Forte 			    (caddr_t)port->spn);
1778*fcf3ce44SJohn Forte 
1779*fcf3ce44SJohn Forte 			break;
1780*fcf3ce44SJohn Forte 		}
1781*fcf3ce44SJohn Forte 
1782*fcf3ce44SJohn Forte 	case FCIO_GET_SYM_NNAME:
1783*fcf3ce44SJohn Forte 		{
1784*fcf3ce44SJohn Forte 			if (fcio->fcio_olen < (strlen(port->snn) + 1) ||
1785*fcf3ce44SJohn Forte 			    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
1786*fcf3ce44SJohn Forte 				rval = EINVAL;
1787*fcf3ce44SJohn Forte 				break;
1788*fcf3ce44SJohn Forte 			}
1789*fcf3ce44SJohn Forte 			(void) strcpy((caddr_t)fcio->fcio_obuf,
1790*fcf3ce44SJohn Forte 			    (caddr_t)port->snn);
1791*fcf3ce44SJohn Forte 
1792*fcf3ce44SJohn Forte 			break;
1793*fcf3ce44SJohn Forte 		}
1794*fcf3ce44SJohn Forte 
1795*fcf3ce44SJohn Forte 	case FCIO_SET_SYM_PNAME:
1796*fcf3ce44SJohn Forte 	case FCIO_SET_SYM_NNAME:
1797*fcf3ce44SJohn Forte 	case FCIO_DEV_LOGIN:
1798*fcf3ce44SJohn Forte 	case FCIO_DEV_LOGOUT:
1799*fcf3ce44SJohn Forte 	case FCIO_DEV_REMOVE:
1800*fcf3ce44SJohn Forte 	case FCIO_GET_DUMP_SIZE:
1801*fcf3ce44SJohn Forte 	case FCIO_FORCE_DUMP:
1802*fcf3ce44SJohn Forte 	case FCIO_GET_DUMP:
1803*fcf3ce44SJohn Forte 	case FCIO_NS:
1804*fcf3ce44SJohn Forte 	case FCIO_SEND_NODE_ID:
1805*fcf3ce44SJohn Forte 	case FCIO_GET_ADAPTER_PORT_STATS:
1806*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
1807*fcf3ce44SJohn Forte 		    "%s: Unsupported FCIO command.",
1808*fcf3ce44SJohn Forte 		    emlxs_fcio_xlate(fcio->fcio_cmd));
1809*fcf3ce44SJohn Forte 		rval = ENOTSUP;
1810*fcf3ce44SJohn Forte 		break;
1811*fcf3ce44SJohn Forte 
1812*fcf3ce44SJohn Forte 	default:
1813*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
1814*fcf3ce44SJohn Forte 		    "Unknown FCIO command. (0x%x)",
1815*fcf3ce44SJohn Forte 		    fcio->fcio_cmd);
1816*fcf3ce44SJohn Forte 		rval = EFAULT;
1817*fcf3ce44SJohn Forte 
1818*fcf3ce44SJohn Forte 	}	/* switch() */
1819*fcf3ce44SJohn Forte 
1820*fcf3ce44SJohn Forte done:
1821*fcf3ce44SJohn Forte 
1822*fcf3ce44SJohn Forte 	if (rval == 0) {
1823*fcf3ce44SJohn Forte 		fcio->fcio_errno = 0;
1824*fcf3ce44SJohn Forte 	}
1825*fcf3ce44SJohn Forte 	if (fcio->fcio_ibuf) {
1826*fcf3ce44SJohn Forte 		if (ddi_copyout(fcio->fcio_ibuf, dfc->buf1,
1827*fcf3ce44SJohn Forte 		    fcio->fcio_ilen, mode)) {
1828*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1829*fcf3ce44SJohn Forte 			    "%s: %s: ddi_copyout failed. (size=%d)",
1830*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
1831*fcf3ce44SJohn Forte 			    emlxs_fcio_xlate(dfc->data1),
1832*fcf3ce44SJohn Forte 			    fcio->fcio_ilen);
1833*fcf3ce44SJohn Forte 
1834*fcf3ce44SJohn Forte 			rval = EFAULT;
1835*fcf3ce44SJohn Forte 		}
1836*fcf3ce44SJohn Forte 		kmem_free(fcio->fcio_ibuf, fcio->fcio_ilen);
1837*fcf3ce44SJohn Forte 	}
1838*fcf3ce44SJohn Forte 	if (fcio->fcio_obuf) {
1839*fcf3ce44SJohn Forte 		if (ddi_copyout(fcio->fcio_obuf, dfc->buf2,
1840*fcf3ce44SJohn Forte 		    fcio->fcio_olen, mode)) {
1841*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1842*fcf3ce44SJohn Forte 			    "%s: %s: ddi_copyout failed. (size=%d)",
1843*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
1844*fcf3ce44SJohn Forte 			    emlxs_fcio_xlate(dfc->data1),
1845*fcf3ce44SJohn Forte 			    fcio->fcio_olen);
1846*fcf3ce44SJohn Forte 
1847*fcf3ce44SJohn Forte 			rval = EFAULT;
1848*fcf3ce44SJohn Forte 		}
1849*fcf3ce44SJohn Forte 		kmem_free(fcio->fcio_obuf, fcio->fcio_olen);
1850*fcf3ce44SJohn Forte 	}
1851*fcf3ce44SJohn Forte 	if (fcio->fcio_abuf) {
1852*fcf3ce44SJohn Forte 		if (ddi_copyout(fcio->fcio_abuf, dfc->buf3,
1853*fcf3ce44SJohn Forte 		    fcio->fcio_alen, mode)) {
1854*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1855*fcf3ce44SJohn Forte 			    "%s: %s: ddi_copyout failed. (size=%d)",
1856*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
1857*fcf3ce44SJohn Forte 			    emlxs_fcio_xlate(dfc->data1),
1858*fcf3ce44SJohn Forte 			    fcio->fcio_alen);
1859*fcf3ce44SJohn Forte 
1860*fcf3ce44SJohn Forte 			rval = EFAULT;
1861*fcf3ce44SJohn Forte 		}
1862*fcf3ce44SJohn Forte 		kmem_free(fcio->fcio_abuf, fcio->fcio_alen);
1863*fcf3ce44SJohn Forte 	}
1864*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&fcio->fcio_errno, (void *)dfc->buf4,
1865*fcf3ce44SJohn Forte 	    dfc->buf4_size, mode) != 0) {
1866*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1867*fcf3ce44SJohn Forte 		    "%s: %s: ddi_copyout failed. (size=%d)",
1868*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
1869*fcf3ce44SJohn Forte 		    emlxs_fcio_xlate(dfc->data1),
1870*fcf3ce44SJohn Forte 		    dfc->buf4_size);
1871*fcf3ce44SJohn Forte 
1872*fcf3ce44SJohn Forte 		rval = EFAULT;
1873*fcf3ce44SJohn Forte 	}
1874*fcf3ce44SJohn Forte 	return (rval);
1875*fcf3ce44SJohn Forte 
1876*fcf3ce44SJohn Forte } /* emlxs_fcio_manage() */
1877*fcf3ce44SJohn Forte 
1878*fcf3ce44SJohn Forte #endif	/* FCIO_SUPPORT */
1879*fcf3ce44SJohn Forte 
1880*fcf3ce44SJohn Forte 
1881*fcf3ce44SJohn Forte 
1882*fcf3ce44SJohn Forte #ifdef NPIV_SUPPORT
1883*fcf3ce44SJohn Forte 
1884*fcf3ce44SJohn Forte static int32_t
1885*fcf3ce44SJohn Forte emlxs_dfc_create_vport(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
1886*fcf3ce44SJohn Forte {
1887*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1888*fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
1889*fcf3ce44SJohn Forte 	emlxs_port_t *vport;
1890*fcf3ce44SJohn Forte 	dfc_vportinfo_t dfc_vport;
1891*fcf3ce44SJohn Forte 	uint32_t vpi;
1892*fcf3ce44SJohn Forte 	uint32_t options;
1893*fcf3ce44SJohn Forte 	char name[256];
1894*fcf3ce44SJohn Forte 	uint8_t wwn[8];
1895*fcf3ce44SJohn Forte 
1896*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
1897*fcf3ce44SJohn Forte 	    "%s requested.",
1898*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
1899*fcf3ce44SJohn Forte 
1900*fcf3ce44SJohn Forte 	options = dfc->data1;
1901*fcf3ce44SJohn Forte 
1902*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
1903*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1904*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
1905*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
1906*fcf3ce44SJohn Forte 
1907*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
1908*fcf3ce44SJohn Forte 	}
1909*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (dfc_vportinfo_t)) {
1910*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1911*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
1912*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
1913*fcf3ce44SJohn Forte 
1914*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
1915*fcf3ce44SJohn Forte 	}
1916*fcf3ce44SJohn Forte 	/* Read the dfc_vport object */
1917*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)&dfc_vport,
1918*fcf3ce44SJohn Forte 	    sizeof (dfc_vportinfo_t), mode) != 0) {
1919*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1920*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
1921*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
1922*fcf3ce44SJohn Forte 
1923*fcf3ce44SJohn Forte 		return (DFC_COPYIN_ERROR);
1924*fcf3ce44SJohn Forte 	}
1925*fcf3ce44SJohn Forte 	if (!(options & VPORT_OPT_AUTORETRY)) {
1926*fcf3ce44SJohn Forte 		if (!(hba->flag & FC_NPIV_ENABLED)) {
1927*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1928*fcf3ce44SJohn Forte 			    "%s: NPIV currently not enabled.",
1929*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
1930*fcf3ce44SJohn Forte 
1931*fcf3ce44SJohn Forte 			return (DFC_NPIV_DISABLED);
1932*fcf3ce44SJohn Forte 		}
1933*fcf3ce44SJohn Forte 		if (!(hba->flag & FC_NPIV_SUPPORTED)) {
1934*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1935*fcf3ce44SJohn Forte 			    "%s: NPIV currently not supported.",
1936*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
1937*fcf3ce44SJohn Forte 
1938*fcf3ce44SJohn Forte 			return (DFC_NPIV_UNSUPPORTED);
1939*fcf3ce44SJohn Forte 		}
1940*fcf3ce44SJohn Forte 	}
1941*fcf3ce44SJohn Forte 	/*
1942*fcf3ce44SJohn Forte 	 * Only the same WWNN and WWPN can be re-created
1943*fcf3ce44SJohn Forte 	 */
1944*fcf3ce44SJohn Forte 	bzero(wwn, 8);
1945*fcf3ce44SJohn Forte 	if (bcmp(wwn, dfc_vport.wwpn, 8) || bcmp(wwn, dfc_vport.wwnn, 0)) {
1946*fcf3ce44SJohn Forte 		for (vpi = 1; vpi <= hba->vpi_max; vpi++) {
1947*fcf3ce44SJohn Forte 			vport = &VPORT(vpi);
1948*fcf3ce44SJohn Forte 
1949*fcf3ce44SJohn Forte 			if ((bcmp((caddr_t)&vport->wwnn,
1950*fcf3ce44SJohn Forte 			    (caddr_t)dfc_vport.wwnn, 8) == 0) &&
1951*fcf3ce44SJohn Forte 			    (bcmp((caddr_t)&vport->wwpn,
1952*fcf3ce44SJohn Forte 			    (caddr_t)dfc_vport.wwpn, 8) == 0)) {
1953*fcf3ce44SJohn Forte 				if (!(vport->flag & EMLXS_PORT_CONFIG) &&
1954*fcf3ce44SJohn Forte 				    (vport->flag & EMLXS_PORT_BOUND)) {
1955*fcf3ce44SJohn Forte 					dfc_vport.vpi = vpi;
1956*fcf3ce44SJohn Forte 					break;
1957*fcf3ce44SJohn Forte 				} else {
1958*fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1959*fcf3ce44SJohn Forte 					    &emlxs_dfc_error_msg,
1960*fcf3ce44SJohn Forte 					    "%s: VPI already in use.",
1961*fcf3ce44SJohn Forte 					    emlxs_dfc_xlate(dfc->cmd));
1962*fcf3ce44SJohn Forte 
1963*fcf3ce44SJohn Forte 					return (DFC_ARG_INVALID);
1964*fcf3ce44SJohn Forte 				}
1965*fcf3ce44SJohn Forte 			}
1966*fcf3ce44SJohn Forte 		}
1967*fcf3ce44SJohn Forte 	}	/* else auto assign */
1968*fcf3ce44SJohn Forte 	/* Acquire a VPI */
1969*fcf3ce44SJohn Forte 	if (dfc_vport.vpi == 0) {
1970*fcf3ce44SJohn Forte 		/* Auto Assign VPI */
1971*fcf3ce44SJohn Forte 		for (vpi = 1; vpi <= hba->vpi_max; vpi++) {
1972*fcf3ce44SJohn Forte 			vport = &VPORT(vpi);
1973*fcf3ce44SJohn Forte 
1974*fcf3ce44SJohn Forte 			if (!(vport->flag & EMLXS_PORT_CONFIG)) {
1975*fcf3ce44SJohn Forte 				break;
1976*fcf3ce44SJohn Forte 			}
1977*fcf3ce44SJohn Forte 		}
1978*fcf3ce44SJohn Forte 
1979*fcf3ce44SJohn Forte 		if (vpi > hba->vpi_max) {
1980*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1981*fcf3ce44SJohn Forte 			    "%s: Out of resources.",
1982*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
1983*fcf3ce44SJohn Forte 
1984*fcf3ce44SJohn Forte 			return (DFC_DRVRES_ERROR);
1985*fcf3ce44SJohn Forte 		}
1986*fcf3ce44SJohn Forte 		dfc_vport.vpi = vpi;
1987*fcf3ce44SJohn Forte 	}
1988*fcf3ce44SJohn Forte 	/* Establish a WWPN */
1989*fcf3ce44SJohn Forte 	bzero(wwn, 8);
1990*fcf3ce44SJohn Forte 	if (bcmp(wwn, dfc_vport.wwpn, 8) == 0) {
1991*fcf3ce44SJohn Forte 		/* Generate new WWPN */
1992*fcf3ce44SJohn Forte 		bcopy((caddr_t)&hba->wwpn, (caddr_t)dfc_vport.wwpn, 8);
1993*fcf3ce44SJohn Forte 		dfc_vport.wwpn[0] = 0x20;
1994*fcf3ce44SJohn Forte 		dfc_vport.wwpn[1] = vpi;
1995*fcf3ce44SJohn Forte 	} else {	/* use one provided */
1996*fcf3ce44SJohn Forte 		/* Make sure WWPN is unique */
1997*fcf3ce44SJohn Forte 		if (emlxs_vport_find_wwpn(hba, dfc_vport.wwpn)) {
1998*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1999*fcf3ce44SJohn Forte 			    "%s: WWPN already exists. vpi=%d",
2000*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), vpi);
2001*fcf3ce44SJohn Forte 
2002*fcf3ce44SJohn Forte 			return (DFC_ARG_INVALID);
2003*fcf3ce44SJohn Forte 		}
2004*fcf3ce44SJohn Forte 	}
2005*fcf3ce44SJohn Forte 
2006*fcf3ce44SJohn Forte 	/* Establish a WWNN */
2007*fcf3ce44SJohn Forte 	bzero(wwn, 8);
2008*fcf3ce44SJohn Forte 	if (bcmp(wwn, dfc_vport.wwnn, 8) == 0) {
2009*fcf3ce44SJohn Forte 		/* Generate new WWNN */
2010*fcf3ce44SJohn Forte 		bcopy((caddr_t)&hba->wwnn, (caddr_t)dfc_vport.wwnn, 8);
2011*fcf3ce44SJohn Forte 		dfc_vport.wwnn[0] = 0x28;
2012*fcf3ce44SJohn Forte 		dfc_vport.wwnn[1] = vpi;
2013*fcf3ce44SJohn Forte 	}
2014*fcf3ce44SJohn Forte 	/* else use WWNN provided */
2015*fcf3ce44SJohn Forte 
2016*fcf3ce44SJohn Forte 	/* Generate the symbolic node name */
2017*fcf3ce44SJohn Forte 	if (dfc_vport.snn[0]) {
2018*fcf3ce44SJohn Forte 		(void) strcpy(name, dfc_vport.snn);
2019*fcf3ce44SJohn Forte 		(void) sprintf(dfc_vport.snn, "%s %s", hba->snn, name);
2020*fcf3ce44SJohn Forte 	} else {
2021*fcf3ce44SJohn Forte 		(void) strcpy(dfc_vport.snn, hba->snn);
2022*fcf3ce44SJohn Forte 	}
2023*fcf3ce44SJohn Forte 
2024*fcf3ce44SJohn Forte 	/* Generate the symbolic port name */
2025*fcf3ce44SJohn Forte 	if (dfc_vport.spn[0]) {
2026*fcf3ce44SJohn Forte 		(void) strcpy(name, dfc_vport.spn);
2027*fcf3ce44SJohn Forte 		(void) sprintf(dfc_vport.spn, "%s VPort-%d VName-%s",
2028*fcf3ce44SJohn Forte 		    hba->spn, vpi, name);
2029*fcf3ce44SJohn Forte 	} else {
2030*fcf3ce44SJohn Forte 		(void) sprintf(dfc_vport.spn, "%s VPort-%d", hba->spn, vpi);
2031*fcf3ce44SJohn Forte 	}
2032*fcf3ce44SJohn Forte 
2033*fcf3ce44SJohn Forte 	dfc_vport.port_id = 0;
2034*fcf3ce44SJohn Forte 	dfc_vport.ulp_statec = FC_STATE_OFFLINE;
2035*fcf3ce44SJohn Forte 	dfc_vport.flags = VPORT_CONFIG;
2036*fcf3ce44SJohn Forte 
2037*fcf3ce44SJohn Forte 	/* Set the highest configured vpi */
2038*fcf3ce44SJohn Forte 	if (dfc_vport.vpi >= hba->vpi_high) {
2039*fcf3ce44SJohn Forte 		hba->vpi_high = dfc_vport.vpi;
2040*fcf3ce44SJohn Forte 	}
2041*fcf3ce44SJohn Forte 	/* Configure the port object */
2042*fcf3ce44SJohn Forte 	bcopy((caddr_t)dfc_vport.wwnn, (caddr_t)&vport->wwnn, 8);
2043*fcf3ce44SJohn Forte 	bcopy((caddr_t)dfc_vport.wwpn, (caddr_t)&vport->wwpn, 8);
2044*fcf3ce44SJohn Forte 	(void) strncpy((caddr_t)vport->snn, (caddr_t)dfc_vport.snn, 256);
2045*fcf3ce44SJohn Forte 	(void) strncpy((caddr_t)vport->spn, (caddr_t)dfc_vport.spn, 256);
2046*fcf3ce44SJohn Forte 	vport->flag |= (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE);
2047*fcf3ce44SJohn Forte 
2048*fcf3ce44SJohn Forte 	/* Adjust restricted flags */
2049*fcf3ce44SJohn Forte 	vport->options &= ~EMLXS_OPT_RESTRICT_MASK;
2050*fcf3ce44SJohn Forte 	vport->flag &= ~EMLXS_PORT_RESTRICTED;
2051*fcf3ce44SJohn Forte 	if (options & VPORT_OPT_RESTRICT) {
2052*fcf3ce44SJohn Forte 		vport->options |= EMLXS_OPT_RESTRICT;
2053*fcf3ce44SJohn Forte 		vport->flag |= EMLXS_PORT_RESTRICTED;
2054*fcf3ce44SJohn Forte 		dfc_vport.flags |= VPORT_RESTRICTED;
2055*fcf3ce44SJohn Forte 	} else if (options & VPORT_OPT_UNRESTRICT) {
2056*fcf3ce44SJohn Forte 		vport->options |= EMLXS_OPT_UNRESTRICT;
2057*fcf3ce44SJohn Forte 	} else if (cfg[CFG_VPORT_RESTRICTED].current) {
2058*fcf3ce44SJohn Forte 		vport->flag |= EMLXS_PORT_RESTRICTED;
2059*fcf3ce44SJohn Forte 		dfc_vport.flags |= VPORT_RESTRICTED;
2060*fcf3ce44SJohn Forte 	}
2061*fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
2062*fcf3ce44SJohn Forte 	if (vport->tgt_mode) {
2063*fcf3ce44SJohn Forte 		emlxs_fct_bind_port(vport);
2064*fcf3ce44SJohn Forte 	}
2065*fcf3ce44SJohn Forte #endif	/* SFCT_SUPPORT */
2066*fcf3ce44SJohn Forte 
2067*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&dfc_vport, (void *)dfc->buf1,
2068*fcf3ce44SJohn Forte 	    sizeof (dfc_vportinfo_t), mode) != 0) {
2069*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2070*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
2071*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2072*fcf3ce44SJohn Forte 
2073*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
2074*fcf3ce44SJohn Forte 	}
2075*fcf3ce44SJohn Forte 	if (vport->flag & EMLXS_PORT_BOUND) {
2076*fcf3ce44SJohn Forte 		/*
2077*fcf3ce44SJohn Forte 		 * The same WWNN, WWPN and VPI has been re-created. Bring up
2078*fcf3ce44SJohn Forte 		 * the vport now!
2079*fcf3ce44SJohn Forte 		 */
2080*fcf3ce44SJohn Forte 		emlxs_port_online(vport);
2081*fcf3ce44SJohn Forte 	}
2082*fcf3ce44SJohn Forte 	return (0);
2083*fcf3ce44SJohn Forte 
2084*fcf3ce44SJohn Forte } /* emlxs_dfc_create_vport() */
2085*fcf3ce44SJohn Forte 
2086*fcf3ce44SJohn Forte 
2087*fcf3ce44SJohn Forte static int32_t
2088*fcf3ce44SJohn Forte emlxs_dfc_destroy_vport(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2089*fcf3ce44SJohn Forte {
2090*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2091*fcf3ce44SJohn Forte 	emlxs_port_t *vport;
2092*fcf3ce44SJohn Forte 	uint8_t wwpn[8];
2093*fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
2094*fcf3ce44SJohn Forte 	uint32_t rval = 0;
2095*fcf3ce44SJohn Forte 	ELS_PKT *els;
2096*fcf3ce44SJohn Forte 	char buffer[256];
2097*fcf3ce44SJohn Forte 
2098*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
2099*fcf3ce44SJohn Forte 	    "%s requested.",
2100*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
2101*fcf3ce44SJohn Forte 
2102*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
2103*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2104*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
2105*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2106*fcf3ce44SJohn Forte 
2107*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
2108*fcf3ce44SJohn Forte 		goto done;
2109*fcf3ce44SJohn Forte 	}
2110*fcf3ce44SJohn Forte 	if (dfc->buf1_size < 8) {
2111*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2112*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
2113*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2114*fcf3ce44SJohn Forte 
2115*fcf3ce44SJohn Forte 		rval = DFC_ARG_TOOSMALL;
2116*fcf3ce44SJohn Forte 		goto done;
2117*fcf3ce44SJohn Forte 	}
2118*fcf3ce44SJohn Forte 	/* Read the wwn object */
2119*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)wwpn, 8, mode) != 0) {
2120*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2121*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
2122*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2123*fcf3ce44SJohn Forte 
2124*fcf3ce44SJohn Forte 		rval = DFC_COPYIN_ERROR;
2125*fcf3ce44SJohn Forte 		goto done;
2126*fcf3ce44SJohn Forte 	}
2127*fcf3ce44SJohn Forte 	/* Make sure WWPN is unique */
2128*fcf3ce44SJohn Forte 	vport = emlxs_vport_find_wwpn(hba, wwpn);
2129*fcf3ce44SJohn Forte 
2130*fcf3ce44SJohn Forte 	if (!vport) {
2131*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2132*fcf3ce44SJohn Forte 		    "%s: WWPN does not exists. %s",
2133*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
2134*fcf3ce44SJohn Forte 		    emlxs_wwn_xlate(buffer, wwpn));
2135*fcf3ce44SJohn Forte 
2136*fcf3ce44SJohn Forte 		rval = DFC_ARG_INVALID;
2137*fcf3ce44SJohn Forte 		goto done;
2138*fcf3ce44SJohn Forte 	}
2139*fcf3ce44SJohn Forte 	if (vport->did) {
2140*fcf3ce44SJohn Forte 		/* Fabric Logout */
2141*fcf3ce44SJohn Forte 		if (!(pkt = emlxs_pkt_alloc(vport,
2142*fcf3ce44SJohn Forte 		    sizeof (uint32_t) + sizeof (LOGO),
2143*fcf3ce44SJohn Forte 		    sizeof (FCP_RSP), 0, KM_NOSLEEP))) {
2144*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2145*fcf3ce44SJohn Forte 			    "%s: Unable to allocate packet.",
2146*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
2147*fcf3ce44SJohn Forte 
2148*fcf3ce44SJohn Forte 			rval = DFC_SYSRES_ERROR;
2149*fcf3ce44SJohn Forte 			goto done;
2150*fcf3ce44SJohn Forte 		}
2151*fcf3ce44SJohn Forte 		/* Make this a polled IO */
2152*fcf3ce44SJohn Forte 		pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
2153*fcf3ce44SJohn Forte 		pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
2154*fcf3ce44SJohn Forte 		pkt->pkt_comp = NULL;
2155*fcf3ce44SJohn Forte 
2156*fcf3ce44SJohn Forte 		pkt->pkt_tran_type = FC_PKT_EXCHANGE;
2157*fcf3ce44SJohn Forte 		pkt->pkt_timeout = 60;
2158*fcf3ce44SJohn Forte 
2159*fcf3ce44SJohn Forte 		/* Build the fc header */
2160*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(Fabric_DID);
2161*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
2162*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(vport->did);
2163*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2164*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
2165*fcf3ce44SJohn Forte 		    F_CTL_SEQ_INITIATIVE;
2166*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.seq_id = 0;
2167*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.df_ctl = 0;
2168*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
2169*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
2170*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
2171*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.ro = 0;
2172*fcf3ce44SJohn Forte 
2173*fcf3ce44SJohn Forte 		/* Build the command */
2174*fcf3ce44SJohn Forte 		els = (ELS_PKT *) pkt->pkt_cmd;
2175*fcf3ce44SJohn Forte 		els->elsCode = 0x05;	/* LOGO */
2176*fcf3ce44SJohn Forte 		els->un.logo.un.nPortId32 = SWAP_DATA32(vport->did);
2177*fcf3ce44SJohn Forte 		bcopy(&vport->wwpn, &els->un.logo.portName, 8);
2178*fcf3ce44SJohn Forte 
2179*fcf3ce44SJohn Forte 		/*
2180*fcf3ce44SJohn Forte 		 * Just send LOGO. Don't worry about result. This is just a
2181*fcf3ce44SJohn Forte 		 * courtesy anyway.
2182*fcf3ce44SJohn Forte 		 */
2183*fcf3ce44SJohn Forte 		(void) emlxs_pkt_send(pkt, 1);
2184*fcf3ce44SJohn Forte 
2185*fcf3ce44SJohn Forte 
2186*fcf3ce44SJohn Forte 		/* Take the port offline */
2187*fcf3ce44SJohn Forte 		(void) emlxs_port_offline(vport, 0xffffffff);
2188*fcf3ce44SJohn Forte 	}
2189*fcf3ce44SJohn Forte 	vport->flag &= ~(EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE);
2190*fcf3ce44SJohn Forte 
2191*fcf3ce44SJohn Forte 	rval = 0;
2192*fcf3ce44SJohn Forte 
2193*fcf3ce44SJohn Forte done:
2194*fcf3ce44SJohn Forte 
2195*fcf3ce44SJohn Forte 	if (pkt) {
2196*fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
2197*fcf3ce44SJohn Forte 	}
2198*fcf3ce44SJohn Forte 	return (rval);
2199*fcf3ce44SJohn Forte 
2200*fcf3ce44SJohn Forte } /* emlxs_dfc_destroy_vport() */
2201*fcf3ce44SJohn Forte 
2202*fcf3ce44SJohn Forte 
2203*fcf3ce44SJohn Forte static int32_t
2204*fcf3ce44SJohn Forte emlxs_dfc_get_vportinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2205*fcf3ce44SJohn Forte {
2206*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2207*fcf3ce44SJohn Forte 	emlxs_port_t *vport;
2208*fcf3ce44SJohn Forte 	dfc_vportinfo_t *dfc_vport;
2209*fcf3ce44SJohn Forte 	dfc_vportinfo_t *dfc_vport_list = NULL;
2210*fcf3ce44SJohn Forte 	uint32_t i;
2211*fcf3ce44SJohn Forte 	/* uint32_t j; */
2212*fcf3ce44SJohn Forte 	uint32_t size;
2213*fcf3ce44SJohn Forte 	uint32_t max_count;
2214*fcf3ce44SJohn Forte 	uint32_t rval = DFC_SUCCESS;
2215*fcf3ce44SJohn Forte 
2216*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
2217*fcf3ce44SJohn Forte 	    "%s requested.",
2218*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
2219*fcf3ce44SJohn Forte 
2220*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
2221*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2222*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
2223*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2224*fcf3ce44SJohn Forte 
2225*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
2226*fcf3ce44SJohn Forte 	}
2227*fcf3ce44SJohn Forte 	size = (sizeof (dfc_vportinfo_t) * MAX_VPORTS);
2228*fcf3ce44SJohn Forte 
2229*fcf3ce44SJohn Forte 	if (!(dfc_vport_list = (dfc_vportinfo_t *)
2230*fcf3ce44SJohn Forte 	    kmem_zalloc(size, KM_NOSLEEP))) {
2231*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2232*fcf3ce44SJohn Forte 		    "%s: Unable to allocate memory.",
2233*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2234*fcf3ce44SJohn Forte 
2235*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
2236*fcf3ce44SJohn Forte 	}
2237*fcf3ce44SJohn Forte 	max_count = 0;
2238*fcf3ce44SJohn Forte 	for (i = 0; i <= hba->vpi_max; i++) {
2239*fcf3ce44SJohn Forte 		vport = &VPORT(i);
2240*fcf3ce44SJohn Forte 		dfc_vport = &dfc_vport_list[i];
2241*fcf3ce44SJohn Forte 
2242*fcf3ce44SJohn Forte 		if (!(vport->flag & EMLXS_PORT_CONFIG)) {
2243*fcf3ce44SJohn Forte 			continue;
2244*fcf3ce44SJohn Forte 		}
2245*fcf3ce44SJohn Forte 		bcopy(vport->snn, dfc_vport->snn, 256);
2246*fcf3ce44SJohn Forte 		bcopy(vport->spn, dfc_vport->spn, 256);
2247*fcf3ce44SJohn Forte 		bcopy(&vport->wwpn, dfc_vport->wwpn, 8);
2248*fcf3ce44SJohn Forte 		bcopy(&vport->wwnn, dfc_vport->wwnn, 8);
2249*fcf3ce44SJohn Forte 		dfc_vport->port_id = vport->did;
2250*fcf3ce44SJohn Forte 		dfc_vport->vpi = vport->vpi;
2251*fcf3ce44SJohn Forte 		dfc_vport->ulp_statec = vport->ulp_statec;
2252*fcf3ce44SJohn Forte 		dfc_vport->flags = VPORT_CONFIG;
2253*fcf3ce44SJohn Forte 
2254*fcf3ce44SJohn Forte 		if (vport->flag & EMLXS_PORT_ENABLE) {
2255*fcf3ce44SJohn Forte 			dfc_vport->flags |= VPORT_ENABLED;
2256*fcf3ce44SJohn Forte 		}
2257*fcf3ce44SJohn Forte 		if (vport->flag & EMLXS_PORT_BOUND) {
2258*fcf3ce44SJohn Forte 			dfc_vport->flags |= VPORT_BOUND;
2259*fcf3ce44SJohn Forte 		}
2260*fcf3ce44SJohn Forte 		if (vport->flag & EMLXS_PORT_IP_UP) {
2261*fcf3ce44SJohn Forte 			dfc_vport->flags |= VPORT_IP;
2262*fcf3ce44SJohn Forte 		}
2263*fcf3ce44SJohn Forte 		if (vport->flag & EMLXS_PORT_RESTRICTED) {
2264*fcf3ce44SJohn Forte 			dfc_vport->flags |= VPORT_RESTRICTED;
2265*fcf3ce44SJohn Forte 		}
2266*fcf3ce44SJohn Forte 		max_count++;
2267*fcf3ce44SJohn Forte 	}
2268*fcf3ce44SJohn Forte 
2269*fcf3ce44SJohn Forte 	max_count *= sizeof (dfc_vportinfo_t);
2270*fcf3ce44SJohn Forte 
2271*fcf3ce44SJohn Forte 	if (max_count > dfc->buf1_size) {
2272*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2273*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (%d > %d)",
2274*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), max_count,
2275*fcf3ce44SJohn Forte 		    dfc->buf1_size);
2276*fcf3ce44SJohn Forte 
2277*fcf3ce44SJohn Forte 		rval = DFC_ARG_TOOSMALL;
2278*fcf3ce44SJohn Forte 		goto done;
2279*fcf3ce44SJohn Forte 	}
2280*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)dfc_vport_list, (void *)dfc->buf1,
2281*fcf3ce44SJohn Forte 	    dfc->buf1_size, mode) != 0) {
2282*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2283*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
2284*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2285*fcf3ce44SJohn Forte 
2286*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
2287*fcf3ce44SJohn Forte 		goto done;
2288*fcf3ce44SJohn Forte 	}
2289*fcf3ce44SJohn Forte done:
2290*fcf3ce44SJohn Forte 
2291*fcf3ce44SJohn Forte 	if (dfc_vport_list) {
2292*fcf3ce44SJohn Forte 		kmem_free(dfc_vport_list, size);
2293*fcf3ce44SJohn Forte 	}
2294*fcf3ce44SJohn Forte 	return (rval);
2295*fcf3ce44SJohn Forte 
2296*fcf3ce44SJohn Forte } /* emlxs_dfc_get_vportinfo() */
2297*fcf3ce44SJohn Forte 
2298*fcf3ce44SJohn Forte 
2299*fcf3ce44SJohn Forte static emlxs_port_t *
2300*fcf3ce44SJohn Forte emlxs_vport_find_wwpn(emlxs_hba_t *hba, uint8_t *wwpn)
2301*fcf3ce44SJohn Forte {
2302*fcf3ce44SJohn Forte 	emlxs_port_t *port;
2303*fcf3ce44SJohn Forte 	NODELIST *nlp;
2304*fcf3ce44SJohn Forte 	int i, j;
2305*fcf3ce44SJohn Forte 
2306*fcf3ce44SJohn Forte 	for (i = 0; i <= hba->vpi_max; i++) {
2307*fcf3ce44SJohn Forte 		port = &VPORT(i);
2308*fcf3ce44SJohn Forte 
2309*fcf3ce44SJohn Forte 		if (!(port->flag & EMLXS_PORT_CONFIG)) {
2310*fcf3ce44SJohn Forte 			continue;
2311*fcf3ce44SJohn Forte 		}
2312*fcf3ce44SJohn Forte 		/* Check Local N-port */
2313*fcf3ce44SJohn Forte 		if (bcmp(&port->wwpn, wwpn, 8) == 0) {
2314*fcf3ce44SJohn Forte 			return (port);
2315*fcf3ce44SJohn Forte 		}
2316*fcf3ce44SJohn Forte 		/* Check Remote N-port */
2317*fcf3ce44SJohn Forte 		rw_enter(&port->node_rwlock, RW_READER);
2318*fcf3ce44SJohn Forte 		for (j = 0; j < EMLXS_NUM_HASH_QUES; j++) {
2319*fcf3ce44SJohn Forte 			nlp = port->node_table[j];
2320*fcf3ce44SJohn Forte 			while (nlp != NULL) {
2321*fcf3ce44SJohn Forte 				/* Check Local N-port */
2322*fcf3ce44SJohn Forte 				if (bcmp(&nlp->nlp_portname, wwpn, 8) == 0) {
2323*fcf3ce44SJohn Forte 					rw_exit(&port->node_rwlock);
2324*fcf3ce44SJohn Forte 					return (port);
2325*fcf3ce44SJohn Forte 				}
2326*fcf3ce44SJohn Forte 				nlp = nlp->nlp_list_next;
2327*fcf3ce44SJohn Forte 			}
2328*fcf3ce44SJohn Forte 		}
2329*fcf3ce44SJohn Forte 
2330*fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
2331*fcf3ce44SJohn Forte 	}
2332*fcf3ce44SJohn Forte 
2333*fcf3ce44SJohn Forte 	return (0);
2334*fcf3ce44SJohn Forte 
2335*fcf3ce44SJohn Forte } /* emlxs_vport_find_wwpn() */
2336*fcf3ce44SJohn Forte 
2337*fcf3ce44SJohn Forte 
2338*fcf3ce44SJohn Forte static int32_t
2339*fcf3ce44SJohn Forte emlxs_dfc_npiv_resource(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2340*fcf3ce44SJohn Forte {
2341*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2342*fcf3ce44SJohn Forte 	dfc_vport_resource_t vres;
2343*fcf3ce44SJohn Forte 	MAILBOXQ *mbq = NULL;
2344*fcf3ce44SJohn Forte 	MAILBOX *mb;
2345*fcf3ce44SJohn Forte 	uint32_t rval = DFC_SUCCESS;
2346*fcf3ce44SJohn Forte 
2347*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
2348*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2349*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
2350*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2351*fcf3ce44SJohn Forte 
2352*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
2353*fcf3ce44SJohn Forte 	}
2354*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (dfc_vport_resource_t)) {
2355*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2356*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
2357*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2358*fcf3ce44SJohn Forte 
2359*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
2360*fcf3ce44SJohn Forte 	}
2361*fcf3ce44SJohn Forte 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP)) == 0) {
2362*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2363*fcf3ce44SJohn Forte 		    "%s: Unable to allocate mailbox buffer.",
2364*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2365*fcf3ce44SJohn Forte 
2366*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
2367*fcf3ce44SJohn Forte 	}
2368*fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbq;
2369*fcf3ce44SJohn Forte 
2370*fcf3ce44SJohn Forte 	emlxs_mb_read_config(hba, mb);
2371*fcf3ce44SJohn Forte 
2372*fcf3ce44SJohn Forte 	rval = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
2373*fcf3ce44SJohn Forte 
2374*fcf3ce44SJohn Forte 	if (rval == MBX_TIMEOUT) {
2375*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2376*fcf3ce44SJohn Forte 		    "%s: Mailbox timed out. cmd=%x",
2377*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
2378*fcf3ce44SJohn Forte 
2379*fcf3ce44SJohn Forte 		rval = DFC_TIMEOUT;
2380*fcf3ce44SJohn Forte 		goto done;
2381*fcf3ce44SJohn Forte 	}
2382*fcf3ce44SJohn Forte 	if (rval) {
2383*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2384*fcf3ce44SJohn Forte 		    "%s: %s failed. status=%x",
2385*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
2386*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
2387*fcf3ce44SJohn Forte 
2388*fcf3ce44SJohn Forte 		rval = DFC_IO_ERROR;
2389*fcf3ce44SJohn Forte 		goto done;
2390*fcf3ce44SJohn Forte 	}
2391*fcf3ce44SJohn Forte 	bzero(&vres, sizeof (dfc_vport_resource_t));
2392*fcf3ce44SJohn Forte 	vres.vpi_max = mb->un.varRdConfig.max_vpi;
2393*fcf3ce44SJohn Forte 	vres.vpi_inuse = (mb->un.varRdConfig.max_vpi <=
2394*fcf3ce44SJohn Forte 	    mb->un.varRdConfig.avail_vpi) ? 0 :
2395*fcf3ce44SJohn Forte 	    mb->un.varRdConfig.max_vpi -
2396*fcf3ce44SJohn Forte 	    mb->un.varRdConfig.avail_vpi;
2397*fcf3ce44SJohn Forte 
2398*fcf3ce44SJohn Forte 	vres.rpi_max = mb->un.varRdConfig.max_rpi;
2399*fcf3ce44SJohn Forte 	vres.rpi_inuse = (mb->un.varRdConfig.max_rpi <=
2400*fcf3ce44SJohn Forte 	    mb->un.varRdConfig.avail_rpi) ? 0 :
2401*fcf3ce44SJohn Forte 	    mb->un.varRdConfig.max_rpi -
2402*fcf3ce44SJohn Forte 	    mb->un.varRdConfig.avail_rpi;
2403*fcf3ce44SJohn Forte 
2404*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&vres, (void *)dfc->buf1,
2405*fcf3ce44SJohn Forte 	    sizeof (dfc_vport_resource_t), mode) != 0) {
2406*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2407*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
2408*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2409*fcf3ce44SJohn Forte 
2410*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
2411*fcf3ce44SJohn Forte 	}
2412*fcf3ce44SJohn Forte done:
2413*fcf3ce44SJohn Forte 
2414*fcf3ce44SJohn Forte 	/* Free allocated mbox memory */
2415*fcf3ce44SJohn Forte 	if (mbq) {
2416*fcf3ce44SJohn Forte 		kmem_free(mbq, sizeof (MAILBOXQ));
2417*fcf3ce44SJohn Forte 	}
2418*fcf3ce44SJohn Forte 	return (rval);
2419*fcf3ce44SJohn Forte 
2420*fcf3ce44SJohn Forte } /* emlxs_dfc_npiv_resource() */
2421*fcf3ce44SJohn Forte 
2422*fcf3ce44SJohn Forte 
2423*fcf3ce44SJohn Forte static int32_t
2424*fcf3ce44SJohn Forte emlxs_dfc_npiv_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2425*fcf3ce44SJohn Forte {
2426*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2427*fcf3ce44SJohn Forte 	emlxs_port_t *vport = &VPORT(hba->vpi_max);
2428*fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
2429*fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
2430*fcf3ce44SJohn Forte 	fc_packet_t *pkt1 = NULL;
2431*fcf3ce44SJohn Forte 	ELS_PKT *els;
2432*fcf3ce44SJohn Forte 	/* SERV_PARM *sp; */
2433*fcf3ce44SJohn Forte 	LS_RJT *lsrjt;
2434*fcf3ce44SJohn Forte 	uint32_t checklist = 0;
2435*fcf3ce44SJohn Forte 	uint32_t rval = DFC_SUCCESS;
2436*fcf3ce44SJohn Forte 	uint8_t wwn[8];
2437*fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd = &VPD;
2438*fcf3ce44SJohn Forte 	int i;
2439*fcf3ce44SJohn Forte 
2440*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
2441*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2442*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
2443*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2444*fcf3ce44SJohn Forte 
2445*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
2446*fcf3ce44SJohn Forte 	}
2447*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (uint32_t)) {
2448*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2449*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
2450*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2451*fcf3ce44SJohn Forte 
2452*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
2453*fcf3ce44SJohn Forte 	}
2454*fcf3ce44SJohn Forte 	if (cfg[CFG_NPIV_ENABLE].current) {
2455*fcf3ce44SJohn Forte 		checklist |= CL_NPIV_PARM_ENABLE;
2456*fcf3ce44SJohn Forte 	}
2457*fcf3ce44SJohn Forte 	if (hba->sli_mode >= 3) {
2458*fcf3ce44SJohn Forte 		checklist |= CL_SLI3_ENABLE;
2459*fcf3ce44SJohn Forte 	}
2460*fcf3ce44SJohn Forte 	if (vpd->feaLevelHigh >= 0x09) {
2461*fcf3ce44SJohn Forte 		checklist |= CL_HBA_SUPPORT_NPIV;
2462*fcf3ce44SJohn Forte 	}
2463*fcf3ce44SJohn Forte 	if (hba->num_of_ports <= hba->vpi_max) {
2464*fcf3ce44SJohn Forte 		checklist |= CL_HBA_HAS_RESOURCES;
2465*fcf3ce44SJohn Forte 	}
2466*fcf3ce44SJohn Forte 	if (hba->state < FC_LINK_UP) {
2467*fcf3ce44SJohn Forte 		goto done;
2468*fcf3ce44SJohn Forte 	}
2469*fcf3ce44SJohn Forte 	checklist |= CL_HBA_LINKUP;
2470*fcf3ce44SJohn Forte 
2471*fcf3ce44SJohn Forte 	if (hba->topology == TOPOLOGY_LOOP) {
2472*fcf3ce44SJohn Forte 		goto done;
2473*fcf3ce44SJohn Forte 	}
2474*fcf3ce44SJohn Forte 	if (!(hba->flag & FC_FABRIC_ATTACHED)) {
2475*fcf3ce44SJohn Forte 		goto done;
2476*fcf3ce44SJohn Forte 	}
2477*fcf3ce44SJohn Forte 	checklist |= CL_P2P_TOPOLOGY;
2478*fcf3ce44SJohn Forte 
2479*fcf3ce44SJohn Forte 	if (!(hba->flag & FC_NPIV_SUPPORTED)) {
2480*fcf3ce44SJohn Forte 		goto done;
2481*fcf3ce44SJohn Forte 	}
2482*fcf3ce44SJohn Forte 	checklist |= CL_FABRIC_SUPPORTS_NPIV;
2483*fcf3ce44SJohn Forte 
2484*fcf3ce44SJohn Forte 	/* Does fabric have resources? */
2485*fcf3ce44SJohn Forte 
2486*fcf3ce44SJohn Forte 	/* Check if we have resources */
2487*fcf3ce44SJohn Forte 	if (!(checklist & CL_HBA_HAS_RESOURCES)) {
2488*fcf3ce44SJohn Forte 		/*
2489*fcf3ce44SJohn Forte 		 * If we're out of resources then it doesn't matter if fabric
2490*fcf3ce44SJohn Forte 		 * has resources
2491*fcf3ce44SJohn Forte 		 */
2492*fcf3ce44SJohn Forte 		goto done;
2493*fcf3ce44SJohn Forte 	} else {
2494*fcf3ce44SJohn Forte 		/* Now check if fabric have resources */
2495*fcf3ce44SJohn Forte 		for (i = 1; i <= hba->vpi_max; i++) {
2496*fcf3ce44SJohn Forte 			vport = &VPORT(i);
2497*fcf3ce44SJohn Forte 			if (vport->did) {
2498*fcf3ce44SJohn Forte 				checklist |= CL_FABRIC_HAS_RESOURCES;
2499*fcf3ce44SJohn Forte 				goto done;
2500*fcf3ce44SJohn Forte 			}
2501*fcf3ce44SJohn Forte 		}
2502*fcf3ce44SJohn Forte 	}
2503*fcf3ce44SJohn Forte 
2504*fcf3ce44SJohn Forte 	vport->vpi = hba->vpi_max;
2505*fcf3ce44SJohn Forte 	vport->hba = hba;
2506*fcf3ce44SJohn Forte 
2507*fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(vport,
2508*fcf3ce44SJohn Forte 	    sizeof (uint32_t) + sizeof (SERV_PARM),
2509*fcf3ce44SJohn Forte 	    sizeof (FCP_RSP), 0, KM_NOSLEEP))) {
2510*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2511*fcf3ce44SJohn Forte 		    "Unable to allocate packet.");
2512*fcf3ce44SJohn Forte 		goto done;
2513*fcf3ce44SJohn Forte 	}
2514*fcf3ce44SJohn Forte 	/* Build (FDISC) the fc header */
2515*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(Fabric_DID);
2516*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_EXTENDED_SVC | R_CTL_UNSOL_CONTROL;
2517*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.s_id = 0;
2518*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2519*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE;
2520*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
2521*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2522*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2523*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
2524*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
2525*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
2526*fcf3ce44SJohn Forte 
2527*fcf3ce44SJohn Forte 	/* Build the command (FDISC) */
2528*fcf3ce44SJohn Forte 	els = (ELS_PKT *)pkt->pkt_cmd;
2529*fcf3ce44SJohn Forte 	els->elsCode = 0x04;	/* FLOGI - This will be changed automatically */
2530*fcf3ce44SJohn Forte 				/* by the drive (See emlxs_send_els()) */
2531*fcf3ce44SJohn Forte 
2532*fcf3ce44SJohn Forte 	els->un.logi.cmn.fcphHigh = 0x09;
2533*fcf3ce44SJohn Forte 	els->un.logi.cmn.fcphLow = 0x08;
2534*fcf3ce44SJohn Forte 	els->un.logi.cmn.bbCreditMsb = 0xff;
2535*fcf3ce44SJohn Forte 	els->un.logi.cmn.bbCreditlsb = 0xff;
2536*fcf3ce44SJohn Forte 	els->un.logi.cmn.reqMultipleNPort = 1;
2537*fcf3ce44SJohn Forte 	els->un.logi.cmn.bbRcvSizeMsb = 0x08;
2538*fcf3ce44SJohn Forte 	els->un.logi.cmn.bbRcvSizeLsb = 0x00;
2539*fcf3ce44SJohn Forte 	els->un.logi.cmn.w2.nPort.totalConcurrSeq = 0xff;
2540*fcf3ce44SJohn Forte 	els->un.logi.cmn.w2.nPort.roByCategoryMsb = 0xff;
2541*fcf3ce44SJohn Forte 	els->un.logi.cmn.w2.nPort.roByCategoryLsb = 0xff;
2542*fcf3ce44SJohn Forte 	els->un.logi.cmn.e_d_tov = 0x7d0;
2543*fcf3ce44SJohn Forte 
2544*fcf3ce44SJohn Forte 	bcopy((caddr_t)&hba->wwnn, (caddr_t)wwn, 8);
2545*fcf3ce44SJohn Forte 	wwn[0] = 0x28;
2546*fcf3ce44SJohn Forte 	wwn[1] = hba->vpi_max;
2547*fcf3ce44SJohn Forte 	bcopy((caddr_t)wwn, (caddr_t)&els->un.logi.nodeName, 8);
2548*fcf3ce44SJohn Forte 
2549*fcf3ce44SJohn Forte 	bcopy((caddr_t)&hba->wwpn, (caddr_t)wwn, 8);
2550*fcf3ce44SJohn Forte 	wwn[0] = 0x20;
2551*fcf3ce44SJohn Forte 	wwn[1] = hba->vpi_max;
2552*fcf3ce44SJohn Forte 	bcopy((caddr_t)wwn, (caddr_t)&els->un.logi.portName, 8);
2553*fcf3ce44SJohn Forte 
2554*fcf3ce44SJohn Forte 	els->un.logi.cls1.openSeqPerXchgMsb = 0x00;
2555*fcf3ce44SJohn Forte 	els->un.logi.cls1.openSeqPerXchgLsb = 0x01;
2556*fcf3ce44SJohn Forte 
2557*fcf3ce44SJohn Forte 	els->un.logi.cls2.classValid = 1;
2558*fcf3ce44SJohn Forte 	els->un.logi.cls2.rcvDataSizeMsb = 0x08;
2559*fcf3ce44SJohn Forte 	els->un.logi.cls2.rcvDataSizeLsb = 0x00;
2560*fcf3ce44SJohn Forte 	els->un.logi.cls2.concurrentSeqMsb = 0x00;
2561*fcf3ce44SJohn Forte 	els->un.logi.cls2.concurrentSeqLsb = 0xff;
2562*fcf3ce44SJohn Forte 	els->un.logi.cls2.EeCreditSeqMsb = 0x00;
2563*fcf3ce44SJohn Forte 	els->un.logi.cls2.EeCreditSeqLsb = 0x0c;
2564*fcf3ce44SJohn Forte 	els->un.logi.cls2.openSeqPerXchgMsb = 0x00;
2565*fcf3ce44SJohn Forte 	els->un.logi.cls2.openSeqPerXchgLsb = 0x01;
2566*fcf3ce44SJohn Forte 
2567*fcf3ce44SJohn Forte 	els->un.logi.cls3.classValid = 1;
2568*fcf3ce44SJohn Forte 	els->un.logi.cls3.rcvDataSizeMsb = 0x08;
2569*fcf3ce44SJohn Forte 	els->un.logi.cls3.rcvDataSizeLsb = 0x00;
2570*fcf3ce44SJohn Forte 	els->un.logi.cls3.concurrentSeqMsb = 0x00;
2571*fcf3ce44SJohn Forte 	els->un.logi.cls3.concurrentSeqLsb = 0xff;
2572*fcf3ce44SJohn Forte 	els->un.logi.cls3.openSeqPerXchgMsb = 0x00;
2573*fcf3ce44SJohn Forte 	els->un.logi.cls3.openSeqPerXchgLsb = 0x01;
2574*fcf3ce44SJohn Forte 
2575*fcf3ce44SJohn Forte 	bcopy((void *)&els->un.logi, (void *)&vport->sparam,
2576*fcf3ce44SJohn Forte 	    sizeof (SERV_PARM));
2577*fcf3ce44SJohn Forte 
2578*fcf3ce44SJohn Forte 	/* Make this a polled IO */
2579*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
2580*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
2581*fcf3ce44SJohn Forte 	pkt->pkt_comp = NULL;
2582*fcf3ce44SJohn Forte 
2583*fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
2584*fcf3ce44SJohn Forte 	pkt->pkt_timeout = 60;
2585*fcf3ce44SJohn Forte 
2586*fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2587*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2588*fcf3ce44SJohn Forte 		    "%s: Unable to send packet.",
2589*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2590*fcf3ce44SJohn Forte 
2591*fcf3ce44SJohn Forte 		goto done;
2592*fcf3ce44SJohn Forte 	}
2593*fcf3ce44SJohn Forte 	if (pkt->pkt_state == FC_PKT_SUCCESS) {
2594*fcf3ce44SJohn Forte 		if (!(pkt1 = emlxs_pkt_alloc(vport,
2595*fcf3ce44SJohn Forte 		    sizeof (uint32_t) + sizeof (LOGO),
2596*fcf3ce44SJohn Forte 		    sizeof (FCP_RSP), 0, KM_NOSLEEP))) {
2597*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2598*fcf3ce44SJohn Forte 			    "Unable to allocate LOGO packet.");
2599*fcf3ce44SJohn Forte 			goto free_resc;
2600*fcf3ce44SJohn Forte 		}
2601*fcf3ce44SJohn Forte 		/* Make this a polled IO */
2602*fcf3ce44SJohn Forte 		pkt1->pkt_tran_flags &= ~FC_TRAN_INTR;
2603*fcf3ce44SJohn Forte 		pkt1->pkt_tran_flags |= FC_TRAN_NO_INTR;
2604*fcf3ce44SJohn Forte 		pkt1->pkt_comp = NULL;
2605*fcf3ce44SJohn Forte 
2606*fcf3ce44SJohn Forte 		pkt1->pkt_tran_type = FC_PKT_EXCHANGE;
2607*fcf3ce44SJohn Forte 		pkt1->pkt_timeout = 60;
2608*fcf3ce44SJohn Forte 
2609*fcf3ce44SJohn Forte 		/* Build (LOGO) the fc header */
2610*fcf3ce44SJohn Forte 		pkt1->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(Fabric_DID);
2611*fcf3ce44SJohn Forte 		pkt1->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
2612*fcf3ce44SJohn Forte 		pkt1->pkt_cmd_fhdr.s_id =
2613*fcf3ce44SJohn Forte 		    SWAP_DATA24_LO(pkt->pkt_resp_fhdr.d_id);
2614*fcf3ce44SJohn Forte 		pkt1->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2615*fcf3ce44SJohn Forte 		pkt1->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
2616*fcf3ce44SJohn Forte 		    F_CTL_SEQ_INITIATIVE;
2617*fcf3ce44SJohn Forte 		pkt1->pkt_cmd_fhdr.seq_id = 0;
2618*fcf3ce44SJohn Forte 		pkt1->pkt_cmd_fhdr.df_ctl = 0;
2619*fcf3ce44SJohn Forte 		pkt1->pkt_cmd_fhdr.seq_cnt = 0;
2620*fcf3ce44SJohn Forte 		pkt1->pkt_cmd_fhdr.ox_id = 0xFFFF;
2621*fcf3ce44SJohn Forte 		pkt1->pkt_cmd_fhdr.rx_id = 0xFFFF;
2622*fcf3ce44SJohn Forte 		pkt1->pkt_cmd_fhdr.ro = 0;
2623*fcf3ce44SJohn Forte 
2624*fcf3ce44SJohn Forte 		/* Build the command (LOGO) */
2625*fcf3ce44SJohn Forte 		els = (ELS_PKT *)pkt1->pkt_cmd;
2626*fcf3ce44SJohn Forte 		els->elsCode = 0x05;	/* LOGO */
2627*fcf3ce44SJohn Forte 		els->un.logo.un.nPortId32 =
2628*fcf3ce44SJohn Forte 		    SWAP_DATA32(pkt->pkt_resp_fhdr.d_id);
2629*fcf3ce44SJohn Forte 		bcopy((caddr_t)&hba->wwpn, (caddr_t)wwn, 8);
2630*fcf3ce44SJohn Forte 		wwn[0] = 0x20;
2631*fcf3ce44SJohn Forte 		wwn[1] = hba->vpi_max;
2632*fcf3ce44SJohn Forte 		bcopy(wwn, &els->un.logo.portName, 8);
2633*fcf3ce44SJohn Forte 
2634*fcf3ce44SJohn Forte 		if (emlxs_pkt_send(pkt1, 1) != FC_SUCCESS) {
2635*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2636*fcf3ce44SJohn Forte 			    "%s: Unable to send packet.",
2637*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
2638*fcf3ce44SJohn Forte 
2639*fcf3ce44SJohn Forte 			goto free_resc;
2640*fcf3ce44SJohn Forte 		}
2641*fcf3ce44SJohn Forte 		if (pkt1->pkt_state != FC_PKT_SUCCESS) {
2642*fcf3ce44SJohn Forte 			if (pkt1->pkt_state == FC_PKT_TIMEOUT) {
2643*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2644*fcf3ce44SJohn Forte 				    "%s: Pkt Transport error. Pkt Timeout.",
2645*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
2646*fcf3ce44SJohn Forte 			} else {
2647*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2648*fcf3ce44SJohn Forte 				    "%s: Pkt Transport error. state=%x",
2649*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd),
2650*fcf3ce44SJohn Forte 				    pkt1->pkt_state);
2651*fcf3ce44SJohn Forte 			}
2652*fcf3ce44SJohn Forte 			goto free_resc;
2653*fcf3ce44SJohn Forte 		}
2654*fcf3ce44SJohn Forte 		checklist |= CL_FABRIC_HAS_RESOURCES;
2655*fcf3ce44SJohn Forte 	} else if (pkt->pkt_state == FC_PKT_LS_RJT) {
2656*fcf3ce44SJohn Forte 		lsrjt = (LS_RJT *) pkt->pkt_resp;
2657*fcf3ce44SJohn Forte 		if (lsrjt->un.b.lsRjtRsnCodeExp != LSEXP_OUT_OF_RESOURCE) {
2658*fcf3ce44SJohn Forte 			checklist |= CL_FABRIC_HAS_RESOURCES;
2659*fcf3ce44SJohn Forte 		}
2660*fcf3ce44SJohn Forte 	}
2661*fcf3ce44SJohn Forte 	/*
2662*fcf3ce44SJohn Forte 	 * Free up default RPIs and VPI
2663*fcf3ce44SJohn Forte 	 */
2664*fcf3ce44SJohn Forte free_resc:
2665*fcf3ce44SJohn Forte 	(void) emlxs_mb_unreg_rpi(vport, 0xffff, 0, 0, 0);
2666*fcf3ce44SJohn Forte 	(void) emlxs_mb_unreg_vpi(vport);
2667*fcf3ce44SJohn Forte 
2668*fcf3ce44SJohn Forte done:
2669*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&checklist, (void *)dfc->buf1,
2670*fcf3ce44SJohn Forte 	    sizeof (uint32_t), mode) != 0) {
2671*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2672*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
2673*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2674*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
2675*fcf3ce44SJohn Forte 	}
2676*fcf3ce44SJohn Forte 	if (pkt) {
2677*fcf3ce44SJohn Forte 		/* Free the pkt */
2678*fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
2679*fcf3ce44SJohn Forte 	}
2680*fcf3ce44SJohn Forte 	if (pkt1) {
2681*fcf3ce44SJohn Forte 		/* Free the pkt */
2682*fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt1);
2683*fcf3ce44SJohn Forte 	}
2684*fcf3ce44SJohn Forte 	return (rval);
2685*fcf3ce44SJohn Forte 
2686*fcf3ce44SJohn Forte } /* emlxs_dfc_npiv_test() */
2687*fcf3ce44SJohn Forte 
2688*fcf3ce44SJohn Forte #endif	/* NPIV_SUPPORT */
2689*fcf3ce44SJohn Forte 
2690*fcf3ce44SJohn Forte 
2691*fcf3ce44SJohn Forte 
2692*fcf3ce44SJohn Forte static int32_t
2693*fcf3ce44SJohn Forte emlxs_dfc_get_rev(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2694*fcf3ce44SJohn Forte {
2695*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2696*fcf3ce44SJohn Forte 	uint32_t rev;
2697*fcf3ce44SJohn Forte 
2698*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
2699*fcf3ce44SJohn Forte 	    "%s requested.",
2700*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
2701*fcf3ce44SJohn Forte 
2702*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
2703*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2704*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
2705*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2706*fcf3ce44SJohn Forte 
2707*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
2708*fcf3ce44SJohn Forte 	}
2709*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (uint32_t)) {
2710*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2711*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
2712*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2713*fcf3ce44SJohn Forte 
2714*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
2715*fcf3ce44SJohn Forte 	}
2716*fcf3ce44SJohn Forte 	rev = DFC_REV;
2717*fcf3ce44SJohn Forte 
2718*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&rev, (void *)dfc->buf1,
2719*fcf3ce44SJohn Forte 	    sizeof (uint32_t), mode) != 0) {
2720*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2721*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
2722*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2723*fcf3ce44SJohn Forte 
2724*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
2725*fcf3ce44SJohn Forte 	}
2726*fcf3ce44SJohn Forte 	return (0);
2727*fcf3ce44SJohn Forte 
2728*fcf3ce44SJohn Forte } /* emlxs_dfc_get_rev() */
2729*fcf3ce44SJohn Forte 
2730*fcf3ce44SJohn Forte 
2731*fcf3ce44SJohn Forte static int32_t
2732*fcf3ce44SJohn Forte emlxs_dfc_get_hbainfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2733*fcf3ce44SJohn Forte {
2734*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2735*fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd = &VPD;
2736*fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
2737*fcf3ce44SJohn Forte 	dfc_hbainfo_t hbainfo;
2738*fcf3ce44SJohn Forte 	NODELIST *ndlp;
2739*fcf3ce44SJohn Forte 	char pathname[256];
2740*fcf3ce44SJohn Forte 
2741*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
2742*fcf3ce44SJohn Forte 	    "%s requested.",
2743*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
2744*fcf3ce44SJohn Forte 
2745*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
2746*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2747*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
2748*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2749*fcf3ce44SJohn Forte 
2750*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
2751*fcf3ce44SJohn Forte 	}
2752*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (dfc_hbainfo_t)) {
2753*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2754*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size = %d)",
2755*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2756*fcf3ce44SJohn Forte 
2757*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
2758*fcf3ce44SJohn Forte 	}
2759*fcf3ce44SJohn Forte 	bzero((void *)&hbainfo, sizeof (dfc_hbainfo_t));
2760*fcf3ce44SJohn Forte 
2761*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.vpd_serial_num, vpd->serial_num,
2762*fcf3ce44SJohn Forte 	    sizeof (hbainfo.vpd_serial_num));
2763*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.vpd_part_num, vpd->part_num,
2764*fcf3ce44SJohn Forte 	    sizeof (hbainfo.vpd_part_num));
2765*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.vpd_port_num, vpd->port_num,
2766*fcf3ce44SJohn Forte 	    sizeof (hbainfo.vpd_port_num));
2767*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.vpd_eng_change, vpd->eng_change,
2768*fcf3ce44SJohn Forte 	    sizeof (hbainfo.vpd_eng_change));
2769*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.vpd_manufacturer, vpd->manufacturer,
2770*fcf3ce44SJohn Forte 	    sizeof (hbainfo.vpd_manufacturer));
2771*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.vpd_model, vpd->model,
2772*fcf3ce44SJohn Forte 	    sizeof (hbainfo.vpd_model));
2773*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.vpd_model_desc, vpd->model_desc,
2774*fcf3ce44SJohn Forte 	    sizeof (hbainfo.vpd_model_desc));
2775*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.vpd_prog_types, vpd->prog_types,
2776*fcf3ce44SJohn Forte 	    sizeof (hbainfo.vpd_prog_types));
2777*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.vpd_id, vpd->id, sizeof (hbainfo.vpd_id));
2778*fcf3ce44SJohn Forte 
2779*fcf3ce44SJohn Forte 	hbainfo.device_id = hba->model_info.device_id;
2780*fcf3ce44SJohn Forte 	hbainfo.vendor_id = ddi_get32(hba->pci_acc_handle,
2781*fcf3ce44SJohn Forte 	    (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER)) & 0xffff;
2782*fcf3ce44SJohn Forte 
2783*fcf3ce44SJohn Forte 	hbainfo.ports = hba->num_of_ports;
2784*fcf3ce44SJohn Forte 	hbainfo.port_index = vpd->port_index;
2785*fcf3ce44SJohn Forte 
2786*fcf3ce44SJohn Forte 	bcopy(&hba->wwnn, hbainfo.wwnn, sizeof (hbainfo.wwnn));
2787*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.snn, port->snn, sizeof (hbainfo.snn));
2788*fcf3ce44SJohn Forte 
2789*fcf3ce44SJohn Forte 	bcopy(&hba->wwpn, hbainfo.wwpn, sizeof (hbainfo.wwpn));
2790*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.spn, port->spn, sizeof (hbainfo.spn));
2791*fcf3ce44SJohn Forte 
2792*fcf3ce44SJohn Forte 	hbainfo.biuRev = vpd->biuRev;
2793*fcf3ce44SJohn Forte 	hbainfo.smRev = vpd->smRev;
2794*fcf3ce44SJohn Forte 	hbainfo.smFwRev = vpd->smFwRev;
2795*fcf3ce44SJohn Forte 	hbainfo.endecRev = vpd->endecRev;
2796*fcf3ce44SJohn Forte 	hbainfo.rBit = vpd->rBit;
2797*fcf3ce44SJohn Forte 	hbainfo.fcphHigh = vpd->fcphHigh;
2798*fcf3ce44SJohn Forte 	hbainfo.fcphLow = vpd->fcphLow;
2799*fcf3ce44SJohn Forte 	hbainfo.feaLevelHigh = vpd->feaLevelHigh;
2800*fcf3ce44SJohn Forte 	hbainfo.feaLevelLow = vpd->feaLevelLow;
2801*fcf3ce44SJohn Forte 
2802*fcf3ce44SJohn Forte 	hbainfo.kern_rev = vpd->postKernRev;
2803*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.kern_name, vpd->postKernName,
2804*fcf3ce44SJohn Forte 	    sizeof (hbainfo.kern_name));
2805*fcf3ce44SJohn Forte 
2806*fcf3ce44SJohn Forte 	hbainfo.stub_rev = vpd->opFwRev;
2807*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.stub_name, vpd->opFwName,
2808*fcf3ce44SJohn Forte 	    sizeof (hbainfo.stub_name));
2809*fcf3ce44SJohn Forte 
2810*fcf3ce44SJohn Forte 	hbainfo.sli1_rev = vpd->sli1FwRev;
2811*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.sli1_name, vpd->sli1FwName,
2812*fcf3ce44SJohn Forte 	    sizeof (hbainfo.sli1_name));
2813*fcf3ce44SJohn Forte 
2814*fcf3ce44SJohn Forte 	hbainfo.sli2_rev = vpd->sli2FwRev;
2815*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.sli2_name, vpd->sli2FwName,
2816*fcf3ce44SJohn Forte 	    sizeof (hbainfo.sli2_name));
2817*fcf3ce44SJohn Forte 
2818*fcf3ce44SJohn Forte 	hbainfo.sli3_rev = vpd->sli3FwRev;
2819*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.sli3_name, vpd->sli3FwName,
2820*fcf3ce44SJohn Forte 	    sizeof (hbainfo.sli3_name));
2821*fcf3ce44SJohn Forte 
2822*fcf3ce44SJohn Forte 	hbainfo.sli4_rev = vpd->sli4FwRev;
2823*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.sli4_name, vpd->sli4FwName,
2824*fcf3ce44SJohn Forte 	    sizeof (hbainfo.sli4_name));
2825*fcf3ce44SJohn Forte 
2826*fcf3ce44SJohn Forte 	hbainfo.sli_mode = hba->sli_mode;
2827*fcf3ce44SJohn Forte 	hbainfo.vpi_max = hba->vpi_max;
2828*fcf3ce44SJohn Forte 	hbainfo.vpi_high = hba->vpi_high;
2829*fcf3ce44SJohn Forte 	hbainfo.flags = 0;
2830*fcf3ce44SJohn Forte 
2831*fcf3ce44SJohn Forte 	/* Set support flags */
2832*fcf3ce44SJohn Forte 	hbainfo.flags = HBA_FLAG_DYN_WWN;
2833*fcf3ce44SJohn Forte 
2834*fcf3ce44SJohn Forte #ifdef NPIV_SUPPORT
2835*fcf3ce44SJohn Forte 	hbainfo.flags |= HBA_FLAG_NPIV;
2836*fcf3ce44SJohn Forte #endif	/* NPIV_SUPPORT */
2837*fcf3ce44SJohn Forte 
2838*fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
2839*fcf3ce44SJohn Forte 	hbainfo.flags |= HBA_FLAG_DHCHAP;
2840*fcf3ce44SJohn Forte 
2841*fcf3ce44SJohn Forte 	if (cfg[CFG_AUTH_E2E].current) {
2842*fcf3ce44SJohn Forte 		hbainfo.flags |= HBA_FLAG_E2E_AUTH;
2843*fcf3ce44SJohn Forte 	}
2844*fcf3ce44SJohn Forte #endif	/* DHCHAP_SUPPORT */
2845*fcf3ce44SJohn Forte 
2846*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.fcode_version, vpd->fcode_version,
2847*fcf3ce44SJohn Forte 	    sizeof (hbainfo.fcode_version));
2848*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.boot_version, vpd->boot_version,
2849*fcf3ce44SJohn Forte 	    sizeof (hbainfo.boot_version));
2850*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.fw_version, vpd->fw_version,
2851*fcf3ce44SJohn Forte 	    sizeof (hbainfo.fw_version));
2852*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.drv_label, emlxs_label,
2853*fcf3ce44SJohn Forte 	    sizeof (hbainfo.drv_label));
2854*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.drv_module, emlxs_name,
2855*fcf3ce44SJohn Forte 	    sizeof (hbainfo.drv_module));
2856*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.drv_name, DRIVER_NAME,
2857*fcf3ce44SJohn Forte 	    sizeof (hbainfo.drv_name));
2858*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.drv_version, emlxs_version,
2859*fcf3ce44SJohn Forte 	    sizeof (hbainfo.drv_version));
2860*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.drv_revision, emlxs_revision,
2861*fcf3ce44SJohn Forte 	    sizeof (hbainfo.drv_revision));
2862*fcf3ce44SJohn Forte 	(void) strncpy(hbainfo.hostname, (char *)utsname.nodename,
2863*fcf3ce44SJohn Forte 	    sizeof (hbainfo.hostname));
2864*fcf3ce44SJohn Forte 
2865*fcf3ce44SJohn Forte 	(void) ddi_pathname(hba->dip, pathname);
2866*fcf3ce44SJohn Forte 	(void) sprintf(hbainfo.os_devname, "/devices%s", pathname);
2867*fcf3ce44SJohn Forte 
2868*fcf3ce44SJohn Forte 	if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) {
2869*fcf3ce44SJohn Forte 		hbainfo.flags |= HBA_FLAG_OFFLINE;
2870*fcf3ce44SJohn Forte 	}
2871*fcf3ce44SJohn Forte 	hbainfo.drv_instance = hba->ddiinst;
2872*fcf3ce44SJohn Forte 	hbainfo.port_id = port->did;
2873*fcf3ce44SJohn Forte 	hbainfo.port_type = HBA_PORTTYPE_UNKNOWN;
2874*fcf3ce44SJohn Forte 
2875*fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
2876*fcf3ce44SJohn Forte 	if (hba->flag & FC_MENLO_MODE) {
2877*fcf3ce44SJohn Forte 		hbainfo.topology = LNK_MENLO_MAINTENANCE;
2878*fcf3ce44SJohn Forte 	} else
2879*fcf3ce44SJohn Forte #endif	/* MENLO_SUPPORT */
2880*fcf3ce44SJohn Forte 
2881*fcf3ce44SJohn Forte 	if (hba->state >= FC_LINK_UP) {
2882*fcf3ce44SJohn Forte 		ndlp = emlxs_node_find_did(port, Fabric_DID);
2883*fcf3ce44SJohn Forte 
2884*fcf3ce44SJohn Forte 		if (hba->topology == TOPOLOGY_LOOP) {
2885*fcf3ce44SJohn Forte 			if (ndlp) {
2886*fcf3ce44SJohn Forte 				hbainfo.port_type = HBA_PORTTYPE_NLPORT;
2887*fcf3ce44SJohn Forte 				hbainfo.topology = LNK_PUBLIC_LOOP;
2888*fcf3ce44SJohn Forte 			} else {
2889*fcf3ce44SJohn Forte 				hbainfo.port_type = HBA_PORTTYPE_LPORT;
2890*fcf3ce44SJohn Forte 				hbainfo.topology = LNK_LOOP;
2891*fcf3ce44SJohn Forte 			}
2892*fcf3ce44SJohn Forte 
2893*fcf3ce44SJohn Forte 			hbainfo.alpa_count = port->alpa_map[0];
2894*fcf3ce44SJohn Forte 			bcopy((void *)&port->alpa_map[1], hbainfo.alpa_map,
2895*fcf3ce44SJohn Forte 			    hbainfo.alpa_count);
2896*fcf3ce44SJohn Forte 		} else {
2897*fcf3ce44SJohn Forte 			if (ndlp) {
2898*fcf3ce44SJohn Forte 				hbainfo.port_type = HBA_PORTTYPE_NPORT;
2899*fcf3ce44SJohn Forte 				hbainfo.topology = LNK_FABRIC;
2900*fcf3ce44SJohn Forte 			} else {
2901*fcf3ce44SJohn Forte 				hbainfo.port_type = HBA_PORTTYPE_PTP;
2902*fcf3ce44SJohn Forte 				hbainfo.topology = LNK_PT2PT;
2903*fcf3ce44SJohn Forte 			}
2904*fcf3ce44SJohn Forte 		}
2905*fcf3ce44SJohn Forte 
2906*fcf3ce44SJohn Forte 		if (ndlp) {
2907*fcf3ce44SJohn Forte 			bcopy(&ndlp->nlp_nodename, hbainfo.fabric_wwnn,
2908*fcf3ce44SJohn Forte 			    sizeof (hbainfo.fabric_wwnn));
2909*fcf3ce44SJohn Forte 			bcopy(&ndlp->nlp_portname, hbainfo.fabric_wwpn,
2910*fcf3ce44SJohn Forte 			    sizeof (hbainfo.fabric_wwpn));
2911*fcf3ce44SJohn Forte 		}
2912*fcf3ce44SJohn Forte 		if (hba->linkspeed == LA_2GHZ_LINK) {
2913*fcf3ce44SJohn Forte 			hbainfo.port_speed = HBA_PORTSPEED_2GBIT;
2914*fcf3ce44SJohn Forte 		} else if (hba->linkspeed == LA_4GHZ_LINK) {
2915*fcf3ce44SJohn Forte 			hbainfo.port_speed = HBA_PORTSPEED_4GBIT;
2916*fcf3ce44SJohn Forte 		} else if (hba->linkspeed == LA_8GHZ_LINK) {
2917*fcf3ce44SJohn Forte 			hbainfo.port_speed = HBA_PORTSPEED_8GBIT;
2918*fcf3ce44SJohn Forte 		} else if (hba->linkspeed == LA_10GHZ_LINK) {
2919*fcf3ce44SJohn Forte 			hbainfo.port_speed = HBA_PORTSPEED_10GBIT;
2920*fcf3ce44SJohn Forte 		} else {
2921*fcf3ce44SJohn Forte 			hbainfo.port_speed = HBA_PORTSPEED_1GBIT;
2922*fcf3ce44SJohn Forte 		}
2923*fcf3ce44SJohn Forte 
2924*fcf3ce44SJohn Forte 		hbainfo.node_count = port->node_count;
2925*fcf3ce44SJohn Forte 	}
2926*fcf3ce44SJohn Forte 	hbainfo.hard_alpa = cfg[CFG_ASSIGN_ALPA].current;
2927*fcf3ce44SJohn Forte 	hbainfo.supported_cos = SWAP_DATA32((FC_NS_CLASS3 | FC_NS_CLASS2));
2928*fcf3ce44SJohn Forte 
2929*fcf3ce44SJohn Forte 	hbainfo.supported_types[0] = SWAP_DATA32(0x00000120);
2930*fcf3ce44SJohn Forte 	hbainfo.supported_types[1] = SWAP_DATA32(0x00000001);
2931*fcf3ce44SJohn Forte 
2932*fcf3ce44SJohn Forte 	hbainfo.active_types[0] = SWAP_DATA32(0x00000120);
2933*fcf3ce44SJohn Forte 	hbainfo.active_types[1] = SWAP_DATA32(0x00000001);
2934*fcf3ce44SJohn Forte 
2935*fcf3ce44SJohn Forte 	if (!cfg[CFG_NETWORK_ON].current) {
2936*fcf3ce44SJohn Forte 		hbainfo.active_types[0] &= ~(SWAP_DATA32(0x00000020));
2937*fcf3ce44SJohn Forte 	}
2938*fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
2939*fcf3ce44SJohn Forte 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_10GBIT;
2940*fcf3ce44SJohn Forte 	}
2941*fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
2942*fcf3ce44SJohn Forte 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_8GBIT;
2943*fcf3ce44SJohn Forte 	}
2944*fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
2945*fcf3ce44SJohn Forte 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_4GBIT;
2946*fcf3ce44SJohn Forte 	}
2947*fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
2948*fcf3ce44SJohn Forte 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_2GBIT;
2949*fcf3ce44SJohn Forte 	}
2950*fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
2951*fcf3ce44SJohn Forte 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_1GBIT;
2952*fcf3ce44SJohn Forte 	}
2953*fcf3ce44SJohn Forte 	hbainfo.max_frame_size = FF_FRAME_SIZE;
2954*fcf3ce44SJohn Forte 
2955*fcf3ce44SJohn Forte 	if (hba->bus_type == SBUS_FC) {
2956*fcf3ce44SJohn Forte 		hbainfo.flags |= HBA_FLAG_SBUS;
2957*fcf3ce44SJohn Forte 	}
2958*fcf3ce44SJohn Forte 	if (hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE)) {
2959*fcf3ce44SJohn Forte 		hbainfo.flags |= HBA_FLAG_OFFLINE;
2960*fcf3ce44SJohn Forte 		hbainfo.port_state = HBA_PORTSTATE_UNKNOWN;
2961*fcf3ce44SJohn Forte 	} else if (hba->flag & FC_ONLINE_MODE) {
2962*fcf3ce44SJohn Forte 		if (hba->flag & FC_LOOPBACK_MODE) {
2963*fcf3ce44SJohn Forte 			hbainfo.port_state = HBA_PORTSTATE_LOOPBACK;
2964*fcf3ce44SJohn Forte 		} else if (hba->state <= FC_LINK_DOWN) {
2965*fcf3ce44SJohn Forte 			hbainfo.port_state = HBA_PORTSTATE_LINKDOWN;
2966*fcf3ce44SJohn Forte 		}
2967*fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
2968*fcf3ce44SJohn Forte 		else if (hba->flag & FC_MENLO_MODE) {
2969*fcf3ce44SJohn Forte 			hbainfo.port_state = HBA_PORTSTATE_LINKDOWN;
2970*fcf3ce44SJohn Forte 		}
2971*fcf3ce44SJohn Forte #endif	/* MENLO_SUPPORT */
2972*fcf3ce44SJohn Forte 		else {
2973*fcf3ce44SJohn Forte 			hbainfo.port_state = HBA_PORTSTATE_ONLINE;
2974*fcf3ce44SJohn Forte 		}
2975*fcf3ce44SJohn Forte 	} else {
2976*fcf3ce44SJohn Forte 		hbainfo.flags |= HBA_FLAG_OFFLINE;
2977*fcf3ce44SJohn Forte 
2978*fcf3ce44SJohn Forte 		if (hba->state == FC_ERROR) {
2979*fcf3ce44SJohn Forte 			hbainfo.port_state = HBA_PORTSTATE_ERROR;
2980*fcf3ce44SJohn Forte 		} else {
2981*fcf3ce44SJohn Forte 			hbainfo.port_state = HBA_PORTSTATE_OFFLINE;
2982*fcf3ce44SJohn Forte 		}
2983*fcf3ce44SJohn Forte 	}
2984*fcf3ce44SJohn Forte 
2985*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&hbainfo, (void *)dfc->buf1,
2986*fcf3ce44SJohn Forte 	    sizeof (dfc_hbainfo_t), mode) != 0) {
2987*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2988*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
2989*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
2990*fcf3ce44SJohn Forte 
2991*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
2992*fcf3ce44SJohn Forte 	}
2993*fcf3ce44SJohn Forte 	return (0);
2994*fcf3ce44SJohn Forte 
2995*fcf3ce44SJohn Forte } /* emlxs_dfc_get_hbainfo() */
2996*fcf3ce44SJohn Forte 
2997*fcf3ce44SJohn Forte 
2998*fcf3ce44SJohn Forte 
2999*fcf3ce44SJohn Forte static int32_t
3000*fcf3ce44SJohn Forte emlxs_dfc_get_hbastats(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3001*fcf3ce44SJohn Forte {
3002*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3003*fcf3ce44SJohn Forte 	dfc_hbastats_t stats;
3004*fcf3ce44SJohn Forte 	MAILBOX *mb = NULL;
3005*fcf3ce44SJohn Forte 	MAILBOXQ *mbq = NULL;
3006*fcf3ce44SJohn Forte 	uint32_t rval = 0;
3007*fcf3ce44SJohn Forte 
3008*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
3009*fcf3ce44SJohn Forte 	    "%s requested.",
3010*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
3011*fcf3ce44SJohn Forte 
3012*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
3013*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3014*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
3015*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
3016*fcf3ce44SJohn Forte 
3017*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
3018*fcf3ce44SJohn Forte 	}
3019*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (dfc_hbastats_t)) {
3020*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3021*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
3022*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3023*fcf3ce44SJohn Forte 
3024*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
3025*fcf3ce44SJohn Forte 	}
3026*fcf3ce44SJohn Forte 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP)) == 0) {
3027*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3028*fcf3ce44SJohn Forte 		    "%s: Unable to allocate mailbox buffer.",
3029*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
3030*fcf3ce44SJohn Forte 
3031*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
3032*fcf3ce44SJohn Forte 	}
3033*fcf3ce44SJohn Forte 	mb = (MAILBOX *) mbq;
3034*fcf3ce44SJohn Forte 
3035*fcf3ce44SJohn Forte 	emlxs_mb_read_status(hba, mb);
3036*fcf3ce44SJohn Forte 
3037*fcf3ce44SJohn Forte 	rval = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
3038*fcf3ce44SJohn Forte 
3039*fcf3ce44SJohn Forte 	if (rval == MBX_TIMEOUT) {
3040*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3041*fcf3ce44SJohn Forte 		    "%s: Mailbox timed out. cmd=%x",
3042*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3043*fcf3ce44SJohn Forte 
3044*fcf3ce44SJohn Forte 		rval = DFC_TIMEOUT;
3045*fcf3ce44SJohn Forte 		goto done;
3046*fcf3ce44SJohn Forte 	}
3047*fcf3ce44SJohn Forte 	if (rval) {
3048*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3049*fcf3ce44SJohn Forte 		    "%s: %s failed. status=%x",
3050*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
3051*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand),
3052*fcf3ce44SJohn Forte 		    rval);
3053*fcf3ce44SJohn Forte 
3054*fcf3ce44SJohn Forte 		rval = DFC_IO_ERROR;
3055*fcf3ce44SJohn Forte 		goto done;
3056*fcf3ce44SJohn Forte 	}
3057*fcf3ce44SJohn Forte 	bzero((void *)&stats, sizeof (dfc_hbastats_t));
3058*fcf3ce44SJohn Forte 
3059*fcf3ce44SJohn Forte 	stats.tx_frame_cnt = mb->un.varRdStatus.xmitFrameCnt;
3060*fcf3ce44SJohn Forte 	stats.rx_frame_cnt = mb->un.varRdStatus.rcvFrameCnt;
3061*fcf3ce44SJohn Forte 	stats.tx_kbyte_cnt = mb->un.varRdStatus.xmitByteCnt;
3062*fcf3ce44SJohn Forte 	stats.rx_kbyte_cnt = mb->un.varRdStatus.rcvByteCnt;
3063*fcf3ce44SJohn Forte 	stats.tx_seq_cnt = mb->un.varRdStatus.xmitSeqCnt;
3064*fcf3ce44SJohn Forte 	stats.rx_seq_cnt = mb->un.varRdStatus.rcvSeqCnt;
3065*fcf3ce44SJohn Forte 	stats.orig_exch_cnt = mb->un.varRdStatus.totalOrigExchanges;
3066*fcf3ce44SJohn Forte 	stats.resp_exch_cnt = mb->un.varRdStatus.totalRespExchanges;
3067*fcf3ce44SJohn Forte 	stats.pbsy_cnt = mb->un.varRdStatus.rcvPbsyCnt;
3068*fcf3ce44SJohn Forte 	stats.fbsy_cnt = mb->un.varRdStatus.rcvFbsyCnt;
3069*fcf3ce44SJohn Forte 
3070*fcf3ce44SJohn Forte 	emlxs_mb_read_lnk_stat(hba, mb);
3071*fcf3ce44SJohn Forte 
3072*fcf3ce44SJohn Forte 	rval = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
3073*fcf3ce44SJohn Forte 
3074*fcf3ce44SJohn Forte 	if (rval == MBX_TIMEOUT) {
3075*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3076*fcf3ce44SJohn Forte 		    "%s: Mailbox timed out. cmd=%x",
3077*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3078*fcf3ce44SJohn Forte 
3079*fcf3ce44SJohn Forte 		rval = DFC_TIMEOUT;
3080*fcf3ce44SJohn Forte 		goto done;
3081*fcf3ce44SJohn Forte 	}
3082*fcf3ce44SJohn Forte 	if (rval) {
3083*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3084*fcf3ce44SJohn Forte 		    "%s: %s failed. status=%x",
3085*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
3086*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand),
3087*fcf3ce44SJohn Forte 		    rval);
3088*fcf3ce44SJohn Forte 
3089*fcf3ce44SJohn Forte 		rval = DFC_IO_ERROR;
3090*fcf3ce44SJohn Forte 		goto done;
3091*fcf3ce44SJohn Forte 	}
3092*fcf3ce44SJohn Forte 	stats.link_failure_cnt = mb->un.varRdLnk.linkFailureCnt;
3093*fcf3ce44SJohn Forte 	stats.loss_sync_cnt = mb->un.varRdLnk.lossSyncCnt;
3094*fcf3ce44SJohn Forte 	stats.loss_signal_cnt = mb->un.varRdLnk.lossSignalCnt;
3095*fcf3ce44SJohn Forte 	stats.seq_error_cnt = mb->un.varRdLnk.primSeqErrCnt;
3096*fcf3ce44SJohn Forte 	stats.inval_tx_word_cnt = mb->un.varRdLnk.invalidXmitWord;
3097*fcf3ce44SJohn Forte 	stats.crc_error_cnt = mb->un.varRdLnk.crcCnt;
3098*fcf3ce44SJohn Forte 	stats.seq_timeout_cnt = mb->un.varRdLnk.primSeqTimeout;
3099*fcf3ce44SJohn Forte 	stats.elastic_overrun_cnt = mb->un.varRdLnk.elasticOverrun;
3100*fcf3ce44SJohn Forte 	stats.arb_timeout_cnt = mb->un.varRdLnk.arbTimeout;
3101*fcf3ce44SJohn Forte 	stats.rx_buf_credit = mb->un.varRdLnk.rxBufCredit;
3102*fcf3ce44SJohn Forte 	stats.rx_buf_cnt = mb->un.varRdLnk.rxBufCreditCur;
3103*fcf3ce44SJohn Forte 	stats.tx_buf_credit = mb->un.varRdLnk.txBufCredit;
3104*fcf3ce44SJohn Forte 	stats.tx_buf_cnt = mb->un.varRdLnk.txBufCreditCur;
3105*fcf3ce44SJohn Forte 	stats.EOFa_cnt = mb->un.varRdLnk.EOFaCnt;
3106*fcf3ce44SJohn Forte 	stats.EOFdti_cnt = mb->un.varRdLnk.EOFdtiCnt;
3107*fcf3ce44SJohn Forte 	stats.EOFni_cnt = mb->un.varRdLnk.EOFniCnt;
3108*fcf3ce44SJohn Forte 	stats.SOFf_cnt = mb->un.varRdLnk.SOFfCnt;
3109*fcf3ce44SJohn Forte 	stats.link_event_tag = hba->link_event_tag;
3110*fcf3ce44SJohn Forte 	stats.last_reset_time = hba->timer_tics - hba->stats.ResetTime;
3111*fcf3ce44SJohn Forte 	stats.port_type = HBA_PORTTYPE_UNKNOWN;
3112*fcf3ce44SJohn Forte 
3113*fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
3114*fcf3ce44SJohn Forte 	if (hba->flag & FC_MENLO_MODE) {
3115*fcf3ce44SJohn Forte 		stats.topology = LNK_MENLO_MAINTENANCE;
3116*fcf3ce44SJohn Forte 	} else
3117*fcf3ce44SJohn Forte #endif	/* MENLO_SUPPORT */
3118*fcf3ce44SJohn Forte 
3119*fcf3ce44SJohn Forte 	if (hba->state >= FC_LINK_UP) {
3120*fcf3ce44SJohn Forte 		if (hba->topology == TOPOLOGY_LOOP) {
3121*fcf3ce44SJohn Forte 			if (hba->flag & FC_FABRIC_ATTACHED) {
3122*fcf3ce44SJohn Forte 				stats.port_type = HBA_PORTTYPE_NLPORT;
3123*fcf3ce44SJohn Forte 				stats.topology = LNK_PUBLIC_LOOP;
3124*fcf3ce44SJohn Forte 			} else {
3125*fcf3ce44SJohn Forte 				stats.port_type = HBA_PORTTYPE_LPORT;
3126*fcf3ce44SJohn Forte 				stats.topology = LNK_LOOP;
3127*fcf3ce44SJohn Forte 			}
3128*fcf3ce44SJohn Forte 		} else {
3129*fcf3ce44SJohn Forte 			if (hba->flag & FC_FABRIC_ATTACHED) {
3130*fcf3ce44SJohn Forte 				stats.port_type = HBA_PORTTYPE_NPORT;
3131*fcf3ce44SJohn Forte 				stats.topology = LNK_FABRIC;
3132*fcf3ce44SJohn Forte 			} else {
3133*fcf3ce44SJohn Forte 				stats.port_type = HBA_PORTTYPE_PTP;
3134*fcf3ce44SJohn Forte 				stats.topology = LNK_PT2PT;
3135*fcf3ce44SJohn Forte 			}
3136*fcf3ce44SJohn Forte 		}
3137*fcf3ce44SJohn Forte 
3138*fcf3ce44SJohn Forte 		if (hba->linkspeed == LA_2GHZ_LINK) {
3139*fcf3ce44SJohn Forte 			stats.link_speed = HBA_PORTSPEED_2GBIT;
3140*fcf3ce44SJohn Forte 		} else if (hba->linkspeed == LA_4GHZ_LINK) {
3141*fcf3ce44SJohn Forte 			stats.link_speed = HBA_PORTSPEED_4GBIT;
3142*fcf3ce44SJohn Forte 		} else if (hba->linkspeed == LA_8GHZ_LINK) {
3143*fcf3ce44SJohn Forte 			stats.link_speed = HBA_PORTSPEED_8GBIT;
3144*fcf3ce44SJohn Forte 		} else if (hba->linkspeed == LA_10GHZ_LINK) {
3145*fcf3ce44SJohn Forte 			stats.link_speed = HBA_PORTSPEED_10GBIT;
3146*fcf3ce44SJohn Forte 		} else {
3147*fcf3ce44SJohn Forte 			stats.link_speed = HBA_PORTSPEED_1GBIT;
3148*fcf3ce44SJohn Forte 		}
3149*fcf3ce44SJohn Forte 	}
3150*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&stats, (void *)dfc->buf1,
3151*fcf3ce44SJohn Forte 	    sizeof (dfc_hbastats_t), mode) != 0) {
3152*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3153*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
3154*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
3155*fcf3ce44SJohn Forte 
3156*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
3157*fcf3ce44SJohn Forte 	}
3158*fcf3ce44SJohn Forte done:
3159*fcf3ce44SJohn Forte 
3160*fcf3ce44SJohn Forte 	/* Free allocated mbox memory */
3161*fcf3ce44SJohn Forte 	if (mbq) {
3162*fcf3ce44SJohn Forte 		kmem_free(mbq, sizeof (MAILBOXQ));
3163*fcf3ce44SJohn Forte 	}
3164*fcf3ce44SJohn Forte 	return (rval);
3165*fcf3ce44SJohn Forte 
3166*fcf3ce44SJohn Forte } /* emlxs_dfc_get_hbastats() */
3167*fcf3ce44SJohn Forte 
3168*fcf3ce44SJohn Forte 
3169*fcf3ce44SJohn Forte 
3170*fcf3ce44SJohn Forte static int32_t
3171*fcf3ce44SJohn Forte emlxs_dfc_get_drvstats(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3172*fcf3ce44SJohn Forte {
3173*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3174*fcf3ce44SJohn Forte 	dfc_drvstats_t stats;
3175*fcf3ce44SJohn Forte 	uint32_t rval = 0;
3176*fcf3ce44SJohn Forte 
3177*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
3178*fcf3ce44SJohn Forte 	    "%s requested.",
3179*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
3180*fcf3ce44SJohn Forte 
3181*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
3182*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3183*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
3184*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
3185*fcf3ce44SJohn Forte 
3186*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
3187*fcf3ce44SJohn Forte 	}
3188*fcf3ce44SJohn Forte 	bzero((void *)&stats, sizeof (dfc_drvstats_t));
3189*fcf3ce44SJohn Forte 
3190*fcf3ce44SJohn Forte 	stats.LinkUp = hba->stats.LinkUp;
3191*fcf3ce44SJohn Forte 	stats.LinkDown = hba->stats.LinkDown;
3192*fcf3ce44SJohn Forte 	stats.LinkEvent = hba->stats.LinkEvent;
3193*fcf3ce44SJohn Forte 	stats.LinkMultiEvent = hba->stats.LinkMultiEvent;
3194*fcf3ce44SJohn Forte 
3195*fcf3ce44SJohn Forte 	stats.MboxIssued = hba->stats.MboxIssued;
3196*fcf3ce44SJohn Forte 	stats.MboxCompleted = hba->stats.MboxCompleted;
3197*fcf3ce44SJohn Forte 	stats.MboxGood = hba->stats.MboxGood;
3198*fcf3ce44SJohn Forte 	stats.MboxError = hba->stats.MboxError;
3199*fcf3ce44SJohn Forte 	stats.MboxBusy = hba->stats.MboxBusy;
3200*fcf3ce44SJohn Forte 	stats.MboxInvalid = hba->stats.MboxInvalid;
3201*fcf3ce44SJohn Forte 
3202*fcf3ce44SJohn Forte 	stats.IocbIssued[0] = hba->stats.IocbIssued[0];
3203*fcf3ce44SJohn Forte 	stats.IocbIssued[1] = hba->stats.IocbIssued[1];
3204*fcf3ce44SJohn Forte 	stats.IocbIssued[2] = hba->stats.IocbIssued[2];
3205*fcf3ce44SJohn Forte 	stats.IocbIssued[3] = hba->stats.IocbIssued[3];
3206*fcf3ce44SJohn Forte 	stats.IocbReceived[0] = hba->stats.IocbReceived[0];
3207*fcf3ce44SJohn Forte 	stats.IocbReceived[1] = hba->stats.IocbReceived[1];
3208*fcf3ce44SJohn Forte 	stats.IocbReceived[2] = hba->stats.IocbReceived[2];
3209*fcf3ce44SJohn Forte 	stats.IocbReceived[3] = hba->stats.IocbReceived[3];
3210*fcf3ce44SJohn Forte 	stats.IocbTxPut[0] = hba->stats.IocbTxPut[0];
3211*fcf3ce44SJohn Forte 	stats.IocbTxPut[1] = hba->stats.IocbTxPut[1];
3212*fcf3ce44SJohn Forte 	stats.IocbTxPut[2] = hba->stats.IocbTxPut[2];
3213*fcf3ce44SJohn Forte 	stats.IocbTxPut[3] = hba->stats.IocbTxPut[3];
3214*fcf3ce44SJohn Forte 	stats.IocbTxGet[0] = hba->stats.IocbTxGet[0];
3215*fcf3ce44SJohn Forte 	stats.IocbTxGet[1] = hba->stats.IocbTxGet[1];
3216*fcf3ce44SJohn Forte 	stats.IocbTxGet[2] = hba->stats.IocbTxGet[2];
3217*fcf3ce44SJohn Forte 	stats.IocbTxGet[3] = hba->stats.IocbTxGet[3];
3218*fcf3ce44SJohn Forte 	stats.IocbRingFull[0] = hba->stats.IocbRingFull[0];
3219*fcf3ce44SJohn Forte 	stats.IocbRingFull[1] = hba->stats.IocbRingFull[1];
3220*fcf3ce44SJohn Forte 	stats.IocbRingFull[2] = hba->stats.IocbRingFull[2];
3221*fcf3ce44SJohn Forte 	stats.IocbRingFull[3] = hba->stats.IocbRingFull[3];
3222*fcf3ce44SJohn Forte 
3223*fcf3ce44SJohn Forte 	stats.IntrEvent[0] = hba->stats.IntrEvent[0];
3224*fcf3ce44SJohn Forte 	stats.IntrEvent[1] = hba->stats.IntrEvent[1];
3225*fcf3ce44SJohn Forte 	stats.IntrEvent[2] = hba->stats.IntrEvent[2];
3226*fcf3ce44SJohn Forte 	stats.IntrEvent[3] = hba->stats.IntrEvent[3];
3227*fcf3ce44SJohn Forte 	stats.IntrEvent[4] = hba->stats.IntrEvent[4];
3228*fcf3ce44SJohn Forte 	stats.IntrEvent[5] = hba->stats.IntrEvent[5];
3229*fcf3ce44SJohn Forte 	stats.IntrEvent[6] = hba->stats.IntrEvent[6];
3230*fcf3ce44SJohn Forte 	stats.IntrEvent[7] = hba->stats.IntrEvent[7];
3231*fcf3ce44SJohn Forte 
3232*fcf3ce44SJohn Forte 	stats.FcpIssued = hba->stats.FcpIssued;
3233*fcf3ce44SJohn Forte 	stats.FcpCompleted = hba->stats.FcpCompleted;
3234*fcf3ce44SJohn Forte 	stats.FcpGood = hba->stats.FcpGood;
3235*fcf3ce44SJohn Forte 	stats.FcpError = hba->stats.FcpError;
3236*fcf3ce44SJohn Forte 
3237*fcf3ce44SJohn Forte 	stats.FcpEvent = hba->stats.FcpEvent;
3238*fcf3ce44SJohn Forte 	stats.FcpStray = hba->stats.FcpStray;
3239*fcf3ce44SJohn Forte 
3240*fcf3ce44SJohn Forte 	stats.ElsEvent = hba->stats.ElsEvent;
3241*fcf3ce44SJohn Forte 	stats.ElsStray = hba->stats.ElsStray;
3242*fcf3ce44SJohn Forte 
3243*fcf3ce44SJohn Forte 	stats.ElsCmdIssued = hba->stats.ElsCmdIssued;
3244*fcf3ce44SJohn Forte 	stats.ElsCmdCompleted = hba->stats.ElsCmdCompleted;
3245*fcf3ce44SJohn Forte 	stats.ElsCmdGood = hba->stats.ElsCmdGood;
3246*fcf3ce44SJohn Forte 	stats.ElsCmdError = hba->stats.ElsCmdError;
3247*fcf3ce44SJohn Forte 
3248*fcf3ce44SJohn Forte 	stats.ElsRspIssued = hba->stats.ElsRspIssued;
3249*fcf3ce44SJohn Forte 	stats.ElsRspCompleted = hba->stats.ElsRspCompleted;
3250*fcf3ce44SJohn Forte 
3251*fcf3ce44SJohn Forte 	stats.ElsRcvEvent = hba->stats.ElsRcvEvent;
3252*fcf3ce44SJohn Forte 	stats.ElsRcvError = hba->stats.ElsRcvError;
3253*fcf3ce44SJohn Forte 	stats.ElsRcvDropped = hba->stats.ElsRcvDropped;
3254*fcf3ce44SJohn Forte 	stats.ElsCmdReceived = hba->stats.ElsCmdReceived;
3255*fcf3ce44SJohn Forte 	stats.ElsRscnReceived = hba->stats.ElsRscnReceived;
3256*fcf3ce44SJohn Forte 	stats.ElsPlogiReceived = hba->stats.ElsPlogiReceived;
3257*fcf3ce44SJohn Forte 	stats.ElsPrliReceived = hba->stats.ElsPrliReceived;
3258*fcf3ce44SJohn Forte 	stats.ElsPrloReceived = hba->stats.ElsPrloReceived;
3259*fcf3ce44SJohn Forte 	stats.ElsLogoReceived = hba->stats.ElsLogoReceived;
3260*fcf3ce44SJohn Forte 	stats.ElsAdiscReceived = hba->stats.ElsAdiscReceived;
3261*fcf3ce44SJohn Forte 	stats.ElsGenReceived = hba->stats.ElsGenReceived;
3262*fcf3ce44SJohn Forte 
3263*fcf3ce44SJohn Forte 	stats.CtEvent = hba->stats.CtEvent;
3264*fcf3ce44SJohn Forte 	stats.CtStray = hba->stats.CtStray;
3265*fcf3ce44SJohn Forte 
3266*fcf3ce44SJohn Forte 	stats.CtCmdIssued = hba->stats.CtCmdIssued;
3267*fcf3ce44SJohn Forte 	stats.CtCmdCompleted = hba->stats.CtCmdCompleted;
3268*fcf3ce44SJohn Forte 	stats.CtCmdGood = hba->stats.CtCmdGood;
3269*fcf3ce44SJohn Forte 	stats.CtCmdError = hba->stats.CtCmdError;
3270*fcf3ce44SJohn Forte 
3271*fcf3ce44SJohn Forte 	stats.CtRspIssued = hba->stats.CtRspIssued;
3272*fcf3ce44SJohn Forte 	stats.CtRspCompleted = hba->stats.CtRspCompleted;
3273*fcf3ce44SJohn Forte 
3274*fcf3ce44SJohn Forte 	stats.CtRcvEvent = hba->stats.CtRcvEvent;
3275*fcf3ce44SJohn Forte 	stats.CtRcvError = hba->stats.CtRcvError;
3276*fcf3ce44SJohn Forte 	stats.CtRcvDropped = hba->stats.CtRcvDropped;
3277*fcf3ce44SJohn Forte 	stats.CtCmdReceived = hba->stats.CtCmdReceived;
3278*fcf3ce44SJohn Forte 
3279*fcf3ce44SJohn Forte 	stats.IpEvent = hba->stats.IpEvent;
3280*fcf3ce44SJohn Forte 	stats.IpStray = hba->stats.IpStray;
3281*fcf3ce44SJohn Forte 
3282*fcf3ce44SJohn Forte 	stats.IpSeqIssued = hba->stats.IpSeqIssued;
3283*fcf3ce44SJohn Forte 	stats.IpSeqCompleted = hba->stats.IpSeqCompleted;
3284*fcf3ce44SJohn Forte 	stats.IpSeqGood = hba->stats.IpSeqGood;
3285*fcf3ce44SJohn Forte 	stats.IpSeqError = hba->stats.IpSeqError;
3286*fcf3ce44SJohn Forte 
3287*fcf3ce44SJohn Forte 	stats.IpBcastIssued = hba->stats.IpBcastIssued;
3288*fcf3ce44SJohn Forte 	stats.IpBcastCompleted = hba->stats.IpBcastCompleted;
3289*fcf3ce44SJohn Forte 	stats.IpBcastGood = hba->stats.IpBcastGood;
3290*fcf3ce44SJohn Forte 	stats.IpBcastError = hba->stats.IpBcastError;
3291*fcf3ce44SJohn Forte 
3292*fcf3ce44SJohn Forte 	stats.IpRcvEvent = hba->stats.IpRcvEvent;
3293*fcf3ce44SJohn Forte 	stats.IpDropped = hba->stats.IpDropped;
3294*fcf3ce44SJohn Forte 	stats.IpSeqReceived = hba->stats.IpSeqReceived;
3295*fcf3ce44SJohn Forte 	stats.IpBcastReceived = hba->stats.IpBcastReceived;
3296*fcf3ce44SJohn Forte 
3297*fcf3ce44SJohn Forte 	stats.IpUbPosted = hba->stats.IpUbPosted;
3298*fcf3ce44SJohn Forte 	stats.ElsUbPosted = hba->stats.ElsUbPosted;
3299*fcf3ce44SJohn Forte 	stats.CtUbPosted = hba->stats.CtUbPosted;
3300*fcf3ce44SJohn Forte 
3301*fcf3ce44SJohn Forte #if (DFC_REV >= 2)
3302*fcf3ce44SJohn Forte 	stats.IocbThrottled = hba->stats.IocbThrottled;
3303*fcf3ce44SJohn Forte 	stats.ElsAuthReceived = hba->stats.ElsAuthReceived;
3304*fcf3ce44SJohn Forte #endif
3305*fcf3ce44SJohn Forte 
3306*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&stats, (void *)dfc->buf1,
3307*fcf3ce44SJohn Forte 	    dfc->buf1_size, mode) != 0) {
3308*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3309*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
3310*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
3311*fcf3ce44SJohn Forte 
3312*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
3313*fcf3ce44SJohn Forte 	}
3314*fcf3ce44SJohn Forte 	return (rval);
3315*fcf3ce44SJohn Forte 
3316*fcf3ce44SJohn Forte } /* emlxs_dfc_get_drvstats() */
3317*fcf3ce44SJohn Forte 
3318*fcf3ce44SJohn Forte 
3319*fcf3ce44SJohn Forte static int32_t
3320*fcf3ce44SJohn Forte emlxs_dfc_set_diag(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3321*fcf3ce44SJohn Forte {
3322*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3323*fcf3ce44SJohn Forte 	int32_t rval = 0;
3324*fcf3ce44SJohn Forte 	uint32_t flag;
3325*fcf3ce44SJohn Forte 	uint32_t i;
3326*fcf3ce44SJohn Forte 
3327*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
3328*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3329*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
3330*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
3331*fcf3ce44SJohn Forte 
3332*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
3333*fcf3ce44SJohn Forte 	}
3334*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (uint32_t)) {
3335*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3336*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
3337*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3338*fcf3ce44SJohn Forte 
3339*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
3340*fcf3ce44SJohn Forte 	}
3341*fcf3ce44SJohn Forte 	flag = (uint32_t)dfc->flag;
3342*fcf3ce44SJohn Forte 
3343*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
3344*fcf3ce44SJohn Forte 
3345*fcf3ce44SJohn Forte 	/* Wait if adapter is in transition */
3346*fcf3ce44SJohn Forte 	i = 0;
3347*fcf3ce44SJohn Forte 	while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) {
3348*fcf3ce44SJohn Forte 		if (i++ > 30) {
3349*fcf3ce44SJohn Forte 			break;
3350*fcf3ce44SJohn Forte 		}
3351*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
3352*fcf3ce44SJohn Forte 		delay(drv_usectohz(1000000));
3353*fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PORT_LOCK);
3354*fcf3ce44SJohn Forte 	}
3355*fcf3ce44SJohn Forte 
3356*fcf3ce44SJohn Forte 	switch (flag) {
3357*fcf3ce44SJohn Forte 	case DDI_SHOW:
3358*fcf3ce44SJohn Forte 		break;
3359*fcf3ce44SJohn Forte 
3360*fcf3ce44SJohn Forte 	case DDI_ONDI:
3361*fcf3ce44SJohn Forte 		if (hba->flag & FC_OFFLINE_MODE) {
3362*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
3363*fcf3ce44SJohn Forte 			(void) emlxs_online(hba);
3364*fcf3ce44SJohn Forte 			mutex_enter(&EMLXS_PORT_LOCK);
3365*fcf3ce44SJohn Forte 		}
3366*fcf3ce44SJohn Forte 		break;
3367*fcf3ce44SJohn Forte 
3368*fcf3ce44SJohn Forte 
3369*fcf3ce44SJohn Forte 		/* Killed + Restart state */
3370*fcf3ce44SJohn Forte 	case DDI_OFFDI:
3371*fcf3ce44SJohn Forte 		if (hba->flag & FC_ONLINE_MODE) {
3372*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
3373*fcf3ce44SJohn Forte 
3374*fcf3ce44SJohn Forte 			(void) emlxs_offline(hba);
3375*fcf3ce44SJohn Forte 
3376*fcf3ce44SJohn Forte 			/* Reset with restart */
3377*fcf3ce44SJohn Forte 			(void) emlxs_hba_reset(hba, 1, 1);
3378*fcf3ce44SJohn Forte 
3379*fcf3ce44SJohn Forte 			mutex_enter(&EMLXS_PORT_LOCK);
3380*fcf3ce44SJohn Forte 		} else if (hba->state < FC_INIT_START) {
3381*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
3382*fcf3ce44SJohn Forte 
3383*fcf3ce44SJohn Forte 			/* Reset with restart */
3384*fcf3ce44SJohn Forte 			(void) emlxs_hba_reset(hba, 1, 1);
3385*fcf3ce44SJohn Forte 
3386*fcf3ce44SJohn Forte 			mutex_enter(&EMLXS_PORT_LOCK);
3387*fcf3ce44SJohn Forte 		}
3388*fcf3ce44SJohn Forte 		break;
3389*fcf3ce44SJohn Forte 
3390*fcf3ce44SJohn Forte 		/* Killed + Reset state */
3391*fcf3ce44SJohn Forte 	case DDI_WARMDI:
3392*fcf3ce44SJohn Forte 		if (hba->flag & FC_ONLINE_MODE) {
3393*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
3394*fcf3ce44SJohn Forte 
3395*fcf3ce44SJohn Forte 			(void) emlxs_offline(hba);
3396*fcf3ce44SJohn Forte 
3397*fcf3ce44SJohn Forte 			/* Reset with no restart */
3398*fcf3ce44SJohn Forte 			(void) emlxs_hba_reset(hba, 0, 0);
3399*fcf3ce44SJohn Forte 
3400*fcf3ce44SJohn Forte 			mutex_enter(&EMLXS_PORT_LOCK);
3401*fcf3ce44SJohn Forte 		} else if (hba->state != FC_WARM_START) {
3402*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
3403*fcf3ce44SJohn Forte 
3404*fcf3ce44SJohn Forte 			/* Reset with no restart */
3405*fcf3ce44SJohn Forte 			(void) emlxs_hba_reset(hba, 0, 0);
3406*fcf3ce44SJohn Forte 
3407*fcf3ce44SJohn Forte 			mutex_enter(&EMLXS_PORT_LOCK);
3408*fcf3ce44SJohn Forte 		}
3409*fcf3ce44SJohn Forte 		break;
3410*fcf3ce44SJohn Forte 
3411*fcf3ce44SJohn Forte 		/* Killed */
3412*fcf3ce44SJohn Forte 	case DDI_DIAGDI:
3413*fcf3ce44SJohn Forte 		if (hba->flag & FC_ONLINE_MODE) {
3414*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
3415*fcf3ce44SJohn Forte 
3416*fcf3ce44SJohn Forte 			(void) emlxs_offline(hba);
3417*fcf3ce44SJohn Forte 
3418*fcf3ce44SJohn Forte 			mutex_enter(&EMLXS_PORT_LOCK);
3419*fcf3ce44SJohn Forte 		} else if (hba->state != FC_KILLED) {
3420*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
3421*fcf3ce44SJohn Forte 
3422*fcf3ce44SJohn Forte 			(void) emlxs_interlock(hba);
3423*fcf3ce44SJohn Forte 
3424*fcf3ce44SJohn Forte 			mutex_enter(&EMLXS_PORT_LOCK);
3425*fcf3ce44SJohn Forte 		}
3426*fcf3ce44SJohn Forte 		break;
3427*fcf3ce44SJohn Forte 
3428*fcf3ce44SJohn Forte 	default:
3429*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3430*fcf3ce44SJohn Forte 		    "%s: Invalid flag. flag=%x",
3431*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), flag);
3432*fcf3ce44SJohn Forte 
3433*fcf3ce44SJohn Forte 		rval = DFC_ARG_INVALID;
3434*fcf3ce44SJohn Forte 	}
3435*fcf3ce44SJohn Forte 
3436*fcf3ce44SJohn Forte 	/* Wait if adapter is in transition */
3437*fcf3ce44SJohn Forte 	i = 0;
3438*fcf3ce44SJohn Forte 	while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) {
3439*fcf3ce44SJohn Forte 		if (i++ > 30) {
3440*fcf3ce44SJohn Forte 			break;
3441*fcf3ce44SJohn Forte 		}
3442*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
3443*fcf3ce44SJohn Forte 		delay(drv_usectohz(1000000));
3444*fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PORT_LOCK);
3445*fcf3ce44SJohn Forte 	}
3446*fcf3ce44SJohn Forte 
3447*fcf3ce44SJohn Forte 	/* Return current state */
3448*fcf3ce44SJohn Forte 	if (hba->flag & FC_ONLINE_MODE) {
3449*fcf3ce44SJohn Forte 		flag = DDI_ONDI;
3450*fcf3ce44SJohn Forte 	} else if (hba->state == FC_KILLED) {
3451*fcf3ce44SJohn Forte 		flag = DDI_DIAGDI;
3452*fcf3ce44SJohn Forte 	} else if (hba->state == FC_WARM_START) {
3453*fcf3ce44SJohn Forte 		flag = DDI_WARMDI;
3454*fcf3ce44SJohn Forte 	} else {
3455*fcf3ce44SJohn Forte 		flag = DDI_OFFDI;
3456*fcf3ce44SJohn Forte 	}
3457*fcf3ce44SJohn Forte 
3458*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
3459*fcf3ce44SJohn Forte 
3460*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&flag, (void *)dfc->buf1,
3461*fcf3ce44SJohn Forte 	    sizeof (uint32_t), mode) != 0) {
3462*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3463*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
3464*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
3465*fcf3ce44SJohn Forte 
3466*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
3467*fcf3ce44SJohn Forte 	}
3468*fcf3ce44SJohn Forte 	return (rval);
3469*fcf3ce44SJohn Forte 
3470*fcf3ce44SJohn Forte } /* emlxs_dfc_set_diag() */
3471*fcf3ce44SJohn Forte 
3472*fcf3ce44SJohn Forte 
3473*fcf3ce44SJohn Forte 
3474*fcf3ce44SJohn Forte static int32_t
3475*fcf3ce44SJohn Forte emlxs_dfc_send_mbox(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3476*fcf3ce44SJohn Forte {
3477*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3478*fcf3ce44SJohn Forte 	MAILBOX *mb = NULL;
3479*fcf3ce44SJohn Forte 	MAILBOXQ *mbq = NULL;
3480*fcf3ce44SJohn Forte 	uint32_t size = 0;
3481*fcf3ce44SJohn Forte 	MATCHMAP *rx_mp = NULL;
3482*fcf3ce44SJohn Forte 	MATCHMAP *tx_mp = NULL;
3483*fcf3ce44SJohn Forte 	uintptr_t lptr;
3484*fcf3ce44SJohn Forte 	int32_t rval = 0;
3485*fcf3ce44SJohn Forte 	int32_t mbxstatus = 0;
3486*fcf3ce44SJohn Forte 	NODELIST *ndlp;
3487*fcf3ce44SJohn Forte 	uint32_t did;
3488*fcf3ce44SJohn Forte 	uint32_t extsize = 0;
3489*fcf3ce44SJohn Forte 	uint8_t *extbuf = NULL;
3490*fcf3ce44SJohn Forte 
3491*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
3492*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3493*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
3494*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
3495*fcf3ce44SJohn Forte 
3496*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
3497*fcf3ce44SJohn Forte 	}
3498*fcf3ce44SJohn Forte 	if (!dfc->buf2 || !dfc->buf2_size) {
3499*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3500*fcf3ce44SJohn Forte 		    "%s: Null buffer2 found.",
3501*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
3502*fcf3ce44SJohn Forte 
3503*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
3504*fcf3ce44SJohn Forte 	}
3505*fcf3ce44SJohn Forte 	if (dfc->buf1_size > MAILBOX_CMD_BSIZE) {
3506*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3507*fcf3ce44SJohn Forte 		    "%s: Buffer1 too large. (size=%d)",
3508*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3509*fcf3ce44SJohn Forte 
3510*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
3511*fcf3ce44SJohn Forte 	}
3512*fcf3ce44SJohn Forte #ifdef MBOX_EXT_SUPPORT
3513*fcf3ce44SJohn Forte 	if (dfc->buf3_size || dfc->buf4_size) {
3514*fcf3ce44SJohn Forte 		if (dfc->buf3_size && !dfc->buf3) {
3515*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3516*fcf3ce44SJohn Forte 			    "%s: Null buffer3 found.",
3517*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
3518*fcf3ce44SJohn Forte 
3519*fcf3ce44SJohn Forte 			return (DFC_ARG_NULL);
3520*fcf3ce44SJohn Forte 		}
3521*fcf3ce44SJohn Forte 		if (dfc->buf3_size > MBOX_EXTENSION_SIZE) {
3522*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3523*fcf3ce44SJohn Forte 			    "%s: buffer3 too large. (size=%d)",
3524*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
3525*fcf3ce44SJohn Forte 
3526*fcf3ce44SJohn Forte 			return (DFC_ARG_TOOBIG);
3527*fcf3ce44SJohn Forte 		}
3528*fcf3ce44SJohn Forte 		if (dfc->buf4_size && !dfc->buf4) {
3529*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3530*fcf3ce44SJohn Forte 			    "%s: Null buffer4 found.",
3531*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
3532*fcf3ce44SJohn Forte 
3533*fcf3ce44SJohn Forte 			return (DFC_ARG_NULL);
3534*fcf3ce44SJohn Forte 		}
3535*fcf3ce44SJohn Forte 		if (dfc->buf4_size > MBOX_EXTENSION_SIZE) {
3536*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3537*fcf3ce44SJohn Forte 			    "%s: buffer4 too large. (size=%d)",
3538*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
3539*fcf3ce44SJohn Forte 
3540*fcf3ce44SJohn Forte 			return (DFC_ARG_TOOBIG);
3541*fcf3ce44SJohn Forte 		}
3542*fcf3ce44SJohn Forte 		extsize = (dfc->buf3_size > dfc->buf4_size)
3543*fcf3ce44SJohn Forte 		    ? dfc->buf3_size : dfc->buf4_size;
3544*fcf3ce44SJohn Forte 		if ((extbuf = (uint8_t *)
3545*fcf3ce44SJohn Forte 		    kmem_zalloc(extsize, KM_SLEEP)) == 0) {
3546*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3547*fcf3ce44SJohn Forte 			    "%s: Unable to allocate mailbox"
3548*fcf3ce44SJohn Forte 			    " extension buffer.",
3549*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
3550*fcf3ce44SJohn Forte 
3551*fcf3ce44SJohn Forte 			return (DFC_SYSRES_ERROR);
3552*fcf3ce44SJohn Forte 		}
3553*fcf3ce44SJohn Forte 		if (dfc->buf3_size) {
3554*fcf3ce44SJohn Forte 			if (ddi_copyin((void *)dfc->buf3, (void *)extbuf,
3555*fcf3ce44SJohn Forte 			    dfc->buf3_size, mode) != 0) {
3556*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3557*fcf3ce44SJohn Forte 				    "%s: ddi_copyin mbox extension"
3558*fcf3ce44SJohn Forte 				    " data failed.",
3559*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
3560*fcf3ce44SJohn Forte 
3561*fcf3ce44SJohn Forte 				rval = DFC_COPYIN_ERROR;
3562*fcf3ce44SJohn Forte 				goto done;
3563*fcf3ce44SJohn Forte 			}
3564*fcf3ce44SJohn Forte 		}
3565*fcf3ce44SJohn Forte 	}
3566*fcf3ce44SJohn Forte #endif	/* MBOX_EXT_SUPPORT */
3567*fcf3ce44SJohn Forte 
3568*fcf3ce44SJohn Forte 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP)) == 0) {
3569*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3570*fcf3ce44SJohn Forte 		    "%s: Unable to allocate mailbox buffer.",
3571*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
3572*fcf3ce44SJohn Forte 
3573*fcf3ce44SJohn Forte 		rval = DFC_SYSRES_ERROR;
3574*fcf3ce44SJohn Forte 		goto done;
3575*fcf3ce44SJohn Forte 	}
3576*fcf3ce44SJohn Forte 	mb = (MAILBOX *) mbq;
3577*fcf3ce44SJohn Forte 
3578*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
3579*fcf3ce44SJohn Forte 
3580*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)mb,
3581*fcf3ce44SJohn Forte 	    dfc->buf1_size, mode) != 0) {
3582*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3583*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
3584*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
3585*fcf3ce44SJohn Forte 
3586*fcf3ce44SJohn Forte 		rval = DFC_COPYIN_ERROR;
3587*fcf3ce44SJohn Forte 		goto done;
3588*fcf3ce44SJohn Forte 	}
3589*fcf3ce44SJohn Forte #ifdef _LP64
3590*fcf3ce44SJohn Forte 	if ((mb->mbxCommand == MBX_READ_SPARM) ||
3591*fcf3ce44SJohn Forte 	    (mb->mbxCommand == MBX_READ_RPI) ||
3592*fcf3ce44SJohn Forte 	    (mb->mbxCommand == MBX_REG_LOGIN) ||
3593*fcf3ce44SJohn Forte 	    (mb->mbxCommand == MBX_READ_LA) ||
3594*fcf3ce44SJohn Forte 	    (mb->mbxCommand == MBX_RUN_BIU_DIAG)) {
3595*fcf3ce44SJohn Forte 
3596*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3597*fcf3ce44SJohn Forte 		    "%s: Invalid mailbox command."
3598*fcf3ce44SJohn Forte 		    " Must use 64bit version. cmd = %x",
3599*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3600*fcf3ce44SJohn Forte 
3601*fcf3ce44SJohn Forte 		/* Must use 64 bit versions of these mbox cmds */
3602*fcf3ce44SJohn Forte 		rval = DFC_ARG_INVALID;
3603*fcf3ce44SJohn Forte 		goto done;
3604*fcf3ce44SJohn Forte 	}
3605*fcf3ce44SJohn Forte #endif
3606*fcf3ce44SJohn Forte 
3607*fcf3ce44SJohn Forte 	lptr = 0;
3608*fcf3ce44SJohn Forte 	size = 0;
3609*fcf3ce44SJohn Forte 	switch (mb->mbxCommand) {
3610*fcf3ce44SJohn Forte 		/* Offline only */
3611*fcf3ce44SJohn Forte 	case MBX_CONFIG_LINK:	/* 0x07 */
3612*fcf3ce44SJohn Forte 	case MBX_PART_SLIM:	/* 0x08 */
3613*fcf3ce44SJohn Forte 	case MBX_CONFIG_RING:	/* 0x09 */
3614*fcf3ce44SJohn Forte 	case MBX_DUMP_CONTEXT:	/* 0x18 */
3615*fcf3ce44SJohn Forte 	case MBX_RUN_DIAGS:	/* 0x19 */
3616*fcf3ce44SJohn Forte 	case MBX_RESTART:	/* 0x1A */
3617*fcf3ce44SJohn Forte 	case MBX_SET_MASK:	/* 0x20 */
3618*fcf3ce44SJohn Forte 	case MBX_FLASH_WR_ULA:	/* 0x98 */
3619*fcf3ce44SJohn Forte 		if (!(hba->flag & FC_OFFLINE_MODE)) {
3620*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3621*fcf3ce44SJohn Forte 			    "%s: Adapter not offline. cmd=%x",
3622*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3623*fcf3ce44SJohn Forte 
3624*fcf3ce44SJohn Forte 			rval = DFC_ONLINE_ERROR;
3625*fcf3ce44SJohn Forte 			goto done;
3626*fcf3ce44SJohn Forte 		}
3627*fcf3ce44SJohn Forte 		break;
3628*fcf3ce44SJohn Forte 
3629*fcf3ce44SJohn Forte 		/* Online / Offline */
3630*fcf3ce44SJohn Forte 	case MBX_UNREG_LOGIN:	/* 0x14 */
3631*fcf3ce44SJohn Forte 		ndlp = emlxs_node_find_rpi(port, mb->un.varUnregLogin.rpi);
3632*fcf3ce44SJohn Forte 
3633*fcf3ce44SJohn Forte 		if (ndlp) {
3634*fcf3ce44SJohn Forte 			did = ndlp->nlp_DID;
3635*fcf3ce44SJohn Forte 
3636*fcf3ce44SJohn Forte 			/* remove it */
3637*fcf3ce44SJohn Forte 			emlxs_node_rm(port, ndlp);
3638*fcf3ce44SJohn Forte 
3639*fcf3ce44SJohn Forte 			/*
3640*fcf3ce44SJohn Forte 			 * If we just unregistered the host node then clear
3641*fcf3ce44SJohn Forte 			 * the host DID
3642*fcf3ce44SJohn Forte 			 */
3643*fcf3ce44SJohn Forte 			if (did == port->did) {
3644*fcf3ce44SJohn Forte 				port->did = 0;
3645*fcf3ce44SJohn Forte 			}
3646*fcf3ce44SJohn Forte 		} else {
3647*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3648*fcf3ce44SJohn Forte 			    "%s: Node not found. cmd=%x rpi=%x",
3649*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand,
3650*fcf3ce44SJohn Forte 			    mb->un.varUnregLogin.rpi);
3651*fcf3ce44SJohn Forte 
3652*fcf3ce44SJohn Forte 			/* Node does not exist */
3653*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
3654*fcf3ce44SJohn Forte 			goto done;
3655*fcf3ce44SJohn Forte 		}
3656*fcf3ce44SJohn Forte 
3657*fcf3ce44SJohn Forte 		/* Send it */
3658*fcf3ce44SJohn Forte 		break;
3659*fcf3ce44SJohn Forte 
3660*fcf3ce44SJohn Forte 	case MBX_UNREG_D_ID:	/* 0x23 */
3661*fcf3ce44SJohn Forte 
3662*fcf3ce44SJohn Forte 		did = mb->un.varRegLogin.did;
3663*fcf3ce44SJohn Forte 
3664*fcf3ce44SJohn Forte 		if (did == 0) {
3665*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3666*fcf3ce44SJohn Forte 			    "%s: Node not found. cmd=%x did=%x",
3667*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
3668*fcf3ce44SJohn Forte 
3669*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
3670*fcf3ce44SJohn Forte 			goto done;
3671*fcf3ce44SJohn Forte 		}
3672*fcf3ce44SJohn Forte 		if (did == 0xffffffff) {
3673*fcf3ce44SJohn Forte 			emlxs_node_destroy_all(port);
3674*fcf3ce44SJohn Forte 			break;
3675*fcf3ce44SJohn Forte 		}
3676*fcf3ce44SJohn Forte 		/* Check for base node */
3677*fcf3ce44SJohn Forte 		if (did == Bcast_DID) {
3678*fcf3ce44SJohn Forte 			/* just flush base node */
3679*fcf3ce44SJohn Forte 			(void) emlxs_tx_node_flush(port, &port->node_base,
3680*fcf3ce44SJohn Forte 			    0, 0, 0);
3681*fcf3ce44SJohn Forte 			(void) emlxs_chipq_node_flush(port, 0, &port->node_base,
3682*fcf3ce44SJohn Forte 			    0);
3683*fcf3ce44SJohn Forte 
3684*fcf3ce44SJohn Forte 			/* Return now */
3685*fcf3ce44SJohn Forte 			rval = 0;
3686*fcf3ce44SJohn Forte 			goto done;
3687*fcf3ce44SJohn Forte 		}
3688*fcf3ce44SJohn Forte 		/* Make sure the node does already exist */
3689*fcf3ce44SJohn Forte 		ndlp = emlxs_node_find_did(port, did);
3690*fcf3ce44SJohn Forte 
3691*fcf3ce44SJohn Forte 		if (ndlp) {
3692*fcf3ce44SJohn Forte 			/* remove it */
3693*fcf3ce44SJohn Forte 			emlxs_node_rm(port, ndlp);
3694*fcf3ce44SJohn Forte 
3695*fcf3ce44SJohn Forte 			/*
3696*fcf3ce44SJohn Forte 			 * If we just unregistered the host node then clear
3697*fcf3ce44SJohn Forte 			 * the host DID
3698*fcf3ce44SJohn Forte 			 */
3699*fcf3ce44SJohn Forte 			if (did == port->did) {
3700*fcf3ce44SJohn Forte 				port->did = 0;
3701*fcf3ce44SJohn Forte 			}
3702*fcf3ce44SJohn Forte 		} else {
3703*fcf3ce44SJohn Forte 
3704*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3705*fcf3ce44SJohn Forte 			    "%s: Node not found. cmd=%x did=%x",
3706*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
3707*fcf3ce44SJohn Forte 
3708*fcf3ce44SJohn Forte 			/* Node does not exist */
3709*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
3710*fcf3ce44SJohn Forte 			goto done;
3711*fcf3ce44SJohn Forte 		}
3712*fcf3ce44SJohn Forte 
3713*fcf3ce44SJohn Forte 		/* Send it */
3714*fcf3ce44SJohn Forte 		break;
3715*fcf3ce44SJohn Forte 
3716*fcf3ce44SJohn Forte 		/* Online / Offline - with DMA */
3717*fcf3ce44SJohn Forte 	case MBX_READ_EVENT_LOG:	/* 0x38 */
3718*fcf3ce44SJohn Forte 		lptr = (uintptr_t)getPaddr(mb->un.varRdEvtLog.un.sp64.addrHigh,
3719*fcf3ce44SJohn Forte 		    mb->un.varRdEvtLog.un.sp64.addrLow);
3720*fcf3ce44SJohn Forte 		size = (int)mb->un.varRdEvtLog.un.sp64.tus.f.bdeSize;
3721*fcf3ce44SJohn Forte 
3722*fcf3ce44SJohn Forte 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
3723*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3724*fcf3ce44SJohn Forte 			    "%s: Invalid BDE. cmd=%x",
3725*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3726*fcf3ce44SJohn Forte 
3727*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
3728*fcf3ce44SJohn Forte 			goto done;
3729*fcf3ce44SJohn Forte 		}
3730*fcf3ce44SJohn Forte 		/* Allocate receive buffer */
3731*fcf3ce44SJohn Forte 		if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3732*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3733*fcf3ce44SJohn Forte 			    "%s: Unable to allocate receive buffer. cmd=%x",
3734*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3735*fcf3ce44SJohn Forte 
3736*fcf3ce44SJohn Forte 			rval = DFC_DRVRES_ERROR;
3737*fcf3ce44SJohn Forte 			goto done;
3738*fcf3ce44SJohn Forte 		}
3739*fcf3ce44SJohn Forte 		mb->un.varRdEvtLog.un.sp64.addrHigh =
3740*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrHigh(rx_mp->phys);
3741*fcf3ce44SJohn Forte 		mb->un.varRdEvtLog.un.sp64.addrLow =
3742*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrLow(rx_mp->phys);
3743*fcf3ce44SJohn Forte 		mb->un.varRdEvtLog.un.sp64.tus.f.bdeFlags = 0;
3744*fcf3ce44SJohn Forte 
3745*fcf3ce44SJohn Forte 		break;
3746*fcf3ce44SJohn Forte 
3747*fcf3ce44SJohn Forte 	case MBX_READ_SPARM:	/* 0x0D */
3748*fcf3ce44SJohn Forte 	case MBX_READ_SPARM64:	/* 0x8D */
3749*fcf3ce44SJohn Forte 		lptr = (uintptr_t)getPaddr(mb->un.varRdSparm.un.sp64.addrHigh,
3750*fcf3ce44SJohn Forte 		    mb->un.varRdSparm.un.sp64.addrLow);
3751*fcf3ce44SJohn Forte 		size = (int)mb->un.varRdSparm.un.sp64.tus.f.bdeSize;
3752*fcf3ce44SJohn Forte 
3753*fcf3ce44SJohn Forte 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
3754*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3755*fcf3ce44SJohn Forte 			    "%s: Invalid BDE. cmd=%x",
3756*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3757*fcf3ce44SJohn Forte 
3758*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
3759*fcf3ce44SJohn Forte 			goto done;
3760*fcf3ce44SJohn Forte 		}
3761*fcf3ce44SJohn Forte 		/* Allocate receive buffer */
3762*fcf3ce44SJohn Forte 		if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3763*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3764*fcf3ce44SJohn Forte 			    "%s: Unable to allocate receive buffer. cmd=%x",
3765*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3766*fcf3ce44SJohn Forte 
3767*fcf3ce44SJohn Forte 			rval = DFC_DRVRES_ERROR;
3768*fcf3ce44SJohn Forte 			goto done;
3769*fcf3ce44SJohn Forte 		}
3770*fcf3ce44SJohn Forte 		mb->un.varRdSparm.un.sp64.addrHigh =
3771*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrHigh(rx_mp->phys);
3772*fcf3ce44SJohn Forte 		mb->un.varRdSparm.un.sp64.addrLow =
3773*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrLow(rx_mp->phys);
3774*fcf3ce44SJohn Forte 		mb->un.varRdSparm.un.sp64.tus.f.bdeFlags = 0;
3775*fcf3ce44SJohn Forte 
3776*fcf3ce44SJohn Forte 		break;
3777*fcf3ce44SJohn Forte 
3778*fcf3ce44SJohn Forte 	case MBX_READ_RPI:	/* 0x0F */
3779*fcf3ce44SJohn Forte 	case MBX_READ_RPI64:	/* 0x8F */
3780*fcf3ce44SJohn Forte 		lptr = (uintptr_t)getPaddr(mb->un.varRdRPI.un.sp64.addrHigh,
3781*fcf3ce44SJohn Forte 		    mb->un.varRdRPI.un.sp64.addrLow);
3782*fcf3ce44SJohn Forte 		size = (int)mb->un.varRdRPI.un.sp64.tus.f.bdeSize;
3783*fcf3ce44SJohn Forte 
3784*fcf3ce44SJohn Forte 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
3785*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3786*fcf3ce44SJohn Forte 			    "%s: Invalid BDE. cmd=%x",
3787*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3788*fcf3ce44SJohn Forte 
3789*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
3790*fcf3ce44SJohn Forte 			goto done;
3791*fcf3ce44SJohn Forte 		}
3792*fcf3ce44SJohn Forte 		/* Allocate receive buffer */
3793*fcf3ce44SJohn Forte 		if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3794*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3795*fcf3ce44SJohn Forte 			    "%s: Unable to allocate receive buffer. cmd=%x",
3796*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3797*fcf3ce44SJohn Forte 
3798*fcf3ce44SJohn Forte 			rval = DFC_DRVRES_ERROR;
3799*fcf3ce44SJohn Forte 			goto done;
3800*fcf3ce44SJohn Forte 		}
3801*fcf3ce44SJohn Forte 		mb->un.varRdRPI.un.sp64.addrHigh =
3802*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrHigh(rx_mp->phys);
3803*fcf3ce44SJohn Forte 		mb->un.varRdRPI.un.sp64.addrLow =
3804*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrLow(rx_mp->phys);
3805*fcf3ce44SJohn Forte 		mb->un.varRdRPI.un.sp64.tus.f.bdeFlags = 0;
3806*fcf3ce44SJohn Forte 
3807*fcf3ce44SJohn Forte 		break;
3808*fcf3ce44SJohn Forte 
3809*fcf3ce44SJohn Forte 	case MBX_RUN_BIU_DIAG:	/* 0x04 */
3810*fcf3ce44SJohn Forte 	case MBX_RUN_BIU_DIAG64:	/* 0x84 */
3811*fcf3ce44SJohn Forte 		lptr = (uintptr_t)
3812*fcf3ce44SJohn Forte 		    getPaddr(mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh,
3813*fcf3ce44SJohn Forte 		    mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow);
3814*fcf3ce44SJohn Forte 		size = (int)mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize;
3815*fcf3ce44SJohn Forte 
3816*fcf3ce44SJohn Forte 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
3817*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3818*fcf3ce44SJohn Forte 			    "%s: Invalid xmit BDE. cmd=%x",
3819*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3820*fcf3ce44SJohn Forte 
3821*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
3822*fcf3ce44SJohn Forte 			goto done;
3823*fcf3ce44SJohn Forte 		}
3824*fcf3ce44SJohn Forte 		/* Allocate xmit buffer */
3825*fcf3ce44SJohn Forte 		if ((tx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3826*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3827*fcf3ce44SJohn Forte 			    "%s: Unable to allocate xmit buffer. cmd=%x",
3828*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3829*fcf3ce44SJohn Forte 
3830*fcf3ce44SJohn Forte 			rval = DFC_DRVRES_ERROR;
3831*fcf3ce44SJohn Forte 			goto done;
3832*fcf3ce44SJohn Forte 		}
3833*fcf3ce44SJohn Forte 		/* Initialize the xmit buffer */
3834*fcf3ce44SJohn Forte 		if (ddi_copyin((void *)lptr, (void *)tx_mp->virt,
3835*fcf3ce44SJohn Forte 		    size, mode) != 0) {
3836*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3837*fcf3ce44SJohn Forte 			    "%s: ddi_copyin failed. cmd=%x",
3838*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3839*fcf3ce44SJohn Forte 
3840*fcf3ce44SJohn Forte 			rval = DFC_COPYIN_ERROR;
3841*fcf3ce44SJohn Forte 			goto done;
3842*fcf3ce44SJohn Forte 		}
3843*fcf3ce44SJohn Forte 		emlxs_mpdata_sync(tx_mp->dma_handle, 0,
3844*fcf3ce44SJohn Forte 		    size, DDI_DMA_SYNC_FORDEV);
3845*fcf3ce44SJohn Forte 
3846*fcf3ce44SJohn Forte 		mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh =
3847*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrHigh(tx_mp->phys);
3848*fcf3ce44SJohn Forte 		mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow =
3849*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrLow(tx_mp->phys);
3850*fcf3ce44SJohn Forte 		mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeFlags = 0;
3851*fcf3ce44SJohn Forte 
3852*fcf3ce44SJohn Forte 		/* Initialize the receive buffer */
3853*fcf3ce44SJohn Forte 		lptr = (uintptr_t)
3854*fcf3ce44SJohn Forte 		    getPaddr(mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh,
3855*fcf3ce44SJohn Forte 		    mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow);
3856*fcf3ce44SJohn Forte 		size = (int)mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize;
3857*fcf3ce44SJohn Forte 
3858*fcf3ce44SJohn Forte 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
3859*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3860*fcf3ce44SJohn Forte 			    "%s: Invalid rcv BDE. cmd=%x",
3861*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3862*fcf3ce44SJohn Forte 
3863*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
3864*fcf3ce44SJohn Forte 			goto done;
3865*fcf3ce44SJohn Forte 		}
3866*fcf3ce44SJohn Forte 		/* Allocate receive buffer */
3867*fcf3ce44SJohn Forte 		if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3868*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3869*fcf3ce44SJohn Forte 			    "%s: Unable to allocate receive buffer. cmd=%x",
3870*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3871*fcf3ce44SJohn Forte 
3872*fcf3ce44SJohn Forte 			rval = DFC_DRVRES_ERROR;
3873*fcf3ce44SJohn Forte 			goto done;
3874*fcf3ce44SJohn Forte 		}
3875*fcf3ce44SJohn Forte 		mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh =
3876*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrHigh(rx_mp->phys);
3877*fcf3ce44SJohn Forte 		mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow =
3878*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrLow(rx_mp->phys);
3879*fcf3ce44SJohn Forte 		mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeFlags = 0;
3880*fcf3ce44SJohn Forte 
3881*fcf3ce44SJohn Forte 		break;
3882*fcf3ce44SJohn Forte 
3883*fcf3ce44SJohn Forte 	case MBX_REG_LOGIN:	/* 0x13 */
3884*fcf3ce44SJohn Forte 	case MBX_REG_LOGIN64:	/* 0x93 */
3885*fcf3ce44SJohn Forte 
3886*fcf3ce44SJohn Forte 		did = mb->un.varRegLogin.did;
3887*fcf3ce44SJohn Forte 
3888*fcf3ce44SJohn Forte 		/* Check for invalid node ids to register */
3889*fcf3ce44SJohn Forte 		if (did == 0 || (did & 0xff000000)) {
3890*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3891*fcf3ce44SJohn Forte 			    "%s: Invalid node id. cmd=%x did=%x",
3892*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
3893*fcf3ce44SJohn Forte 
3894*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
3895*fcf3ce44SJohn Forte 			goto done;
3896*fcf3ce44SJohn Forte 		}
3897*fcf3ce44SJohn Forte 		/* Check if the node limit has been reached */
3898*fcf3ce44SJohn Forte 		if (port->node_count >= hba->max_nodes) {
3899*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3900*fcf3ce44SJohn Forte 			    "%s: Too many nodes. cmd=%x",
3901*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3902*fcf3ce44SJohn Forte 
3903*fcf3ce44SJohn Forte 			rval = DFC_HBARES_ERROR;
3904*fcf3ce44SJohn Forte 			goto done;
3905*fcf3ce44SJohn Forte 		}
3906*fcf3ce44SJohn Forte 		lptr = (uintptr_t)getPaddr(mb->un.varRegLogin.un.sp64.addrHigh,
3907*fcf3ce44SJohn Forte 		    mb->un.varRegLogin.un.sp64.addrLow);
3908*fcf3ce44SJohn Forte 		size = (int)mb->un.varRegLogin.un.sp64.tus.f.bdeSize;
3909*fcf3ce44SJohn Forte 
3910*fcf3ce44SJohn Forte 		if (!lptr || (size > MEM_BUF_SIZE)) {
3911*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3912*fcf3ce44SJohn Forte 			    "%s: Invalid BDE. cmd=%x",
3913*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3914*fcf3ce44SJohn Forte 
3915*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
3916*fcf3ce44SJohn Forte 			goto done;
3917*fcf3ce44SJohn Forte 		}
3918*fcf3ce44SJohn Forte 		/* Allocate xmit buffer */
3919*fcf3ce44SJohn Forte 		if ((tx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3920*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3921*fcf3ce44SJohn Forte 			    "%s: Unable to allocate xmit buffer. cmd=%x",
3922*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3923*fcf3ce44SJohn Forte 
3924*fcf3ce44SJohn Forte 			rval = DFC_DRVRES_ERROR;
3925*fcf3ce44SJohn Forte 			goto done;
3926*fcf3ce44SJohn Forte 		}
3927*fcf3ce44SJohn Forte 		/* Initialize the xmit buffer */
3928*fcf3ce44SJohn Forte 		if (ddi_copyin((void *)lptr, (void *)tx_mp->virt,
3929*fcf3ce44SJohn Forte 		    size, mode) != 0) {
3930*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3931*fcf3ce44SJohn Forte 			    "%s: Unable to allocate xmit buffer. cmd=%x",
3932*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3933*fcf3ce44SJohn Forte 
3934*fcf3ce44SJohn Forte 			rval = DFC_COPYIN_ERROR;
3935*fcf3ce44SJohn Forte 			goto done;
3936*fcf3ce44SJohn Forte 		}
3937*fcf3ce44SJohn Forte 		emlxs_mpdata_sync(tx_mp->dma_handle, 0,
3938*fcf3ce44SJohn Forte 		    size, DDI_DMA_SYNC_FORDEV);
3939*fcf3ce44SJohn Forte 
3940*fcf3ce44SJohn Forte 		mb->un.varRegLogin.un.sp64.addrHigh =
3941*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrHigh(tx_mp->phys);
3942*fcf3ce44SJohn Forte 		mb->un.varRegLogin.un.sp64.addrLow =
3943*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrLow(tx_mp->phys);
3944*fcf3ce44SJohn Forte 		mb->un.varRegLogin.un.sp64.tus.f.bdeFlags = 0;
3945*fcf3ce44SJohn Forte 
3946*fcf3ce44SJohn Forte 		break;
3947*fcf3ce44SJohn Forte 
3948*fcf3ce44SJohn Forte 	case MBX_READ_LA:	/* 0x15 */
3949*fcf3ce44SJohn Forte 	case MBX_READ_LA64:	/* 0x95 */
3950*fcf3ce44SJohn Forte 		lptr = (uintptr_t)
3951*fcf3ce44SJohn Forte 		    getPaddr(mb->un.varReadLA.un.lilpBde64.addrHigh,
3952*fcf3ce44SJohn Forte 		    mb->un.varReadLA.un.lilpBde64.addrLow);
3953*fcf3ce44SJohn Forte 		size = (int)mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize;
3954*fcf3ce44SJohn Forte 
3955*fcf3ce44SJohn Forte 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
3956*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3957*fcf3ce44SJohn Forte 			    "%s: Invalid BDE. cmd=%x",
3958*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3959*fcf3ce44SJohn Forte 
3960*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
3961*fcf3ce44SJohn Forte 			goto done;
3962*fcf3ce44SJohn Forte 		}
3963*fcf3ce44SJohn Forte 		/* Allocate receive buffer */
3964*fcf3ce44SJohn Forte 		if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3965*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3966*fcf3ce44SJohn Forte 			    "%s: Unable to allocate receive buffer. cmd=%x",
3967*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3968*fcf3ce44SJohn Forte 
3969*fcf3ce44SJohn Forte 			rval = DFC_DRVRES_ERROR;
3970*fcf3ce44SJohn Forte 			goto done;
3971*fcf3ce44SJohn Forte 		}
3972*fcf3ce44SJohn Forte 		mb->un.varReadLA.un.lilpBde64.addrHigh =
3973*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrHigh(rx_mp->phys);
3974*fcf3ce44SJohn Forte 		mb->un.varReadLA.un.lilpBde64.addrLow =
3975*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrLow(rx_mp->phys);
3976*fcf3ce44SJohn Forte 		mb->un.varReadLA.un.lilpBde64.tus.f.bdeFlags = 0;
3977*fcf3ce44SJohn Forte 
3978*fcf3ce44SJohn Forte 		break;
3979*fcf3ce44SJohn Forte 
3980*fcf3ce44SJohn Forte 
3981*fcf3ce44SJohn Forte 		/* Do not allow these commands */
3982*fcf3ce44SJohn Forte 	case MBX_CONFIG_PORT:	/* 0x88 */
3983*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3984*fcf3ce44SJohn Forte 		    "%s: Command not allowed. cmd=%x",
3985*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3986*fcf3ce44SJohn Forte 
3987*fcf3ce44SJohn Forte 		rval = DFC_ARG_INVALID;
3988*fcf3ce44SJohn Forte 		goto done;
3989*fcf3ce44SJohn Forte 
3990*fcf3ce44SJohn Forte 
3991*fcf3ce44SJohn Forte 		/* Online / Offline */
3992*fcf3ce44SJohn Forte 	default:
3993*fcf3ce44SJohn Forte 		break;
3994*fcf3ce44SJohn Forte 
3995*fcf3ce44SJohn Forte 	}	/* switch() */
3996*fcf3ce44SJohn Forte 
3997*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
3998*fcf3ce44SJohn Forte 
3999*fcf3ce44SJohn Forte 	/* Set or don't set the PASSTHRU bit. */
4000*fcf3ce44SJohn Forte 	/* Setting will prevent the driver from processing it as its own */
4001*fcf3ce44SJohn Forte 	switch (mb->mbxCommand) {
4002*fcf3ce44SJohn Forte 	case MBX_REG_LOGIN:	/* 0x13 */
4003*fcf3ce44SJohn Forte 	case MBX_REG_LOGIN64:	/* 0x93 */
4004*fcf3ce44SJohn Forte 		break;
4005*fcf3ce44SJohn Forte 
4006*fcf3ce44SJohn Forte 	default:
4007*fcf3ce44SJohn Forte 		mbq->flag |= MBQ_PASSTHRU;
4008*fcf3ce44SJohn Forte 	}
4009*fcf3ce44SJohn Forte 
4010*fcf3ce44SJohn Forte #ifdef MBOX_EXT_SUPPORT
4011*fcf3ce44SJohn Forte 	if (extbuf) {
4012*fcf3ce44SJohn Forte 		mbq->extbuf = extbuf;
4013*fcf3ce44SJohn Forte 		mbq->extsize = extsize;
4014*fcf3ce44SJohn Forte 	}
4015*fcf3ce44SJohn Forte #endif	/* MBOX_EXT_SUPPORT */
4016*fcf3ce44SJohn Forte 
4017*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4018*fcf3ce44SJohn Forte 	    "%s: %s sent.  (%x %x %x %x)",
4019*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd),
4020*fcf3ce44SJohn Forte 	    emlxs_mb_cmd_xlate(mb->mbxCommand),
4021*fcf3ce44SJohn Forte 	    mb->un.varWords[0],
4022*fcf3ce44SJohn Forte 	    mb->un.varWords[1],
4023*fcf3ce44SJohn Forte 	    mb->un.varWords[2],
4024*fcf3ce44SJohn Forte 	    mb->un.varWords[3]);
4025*fcf3ce44SJohn Forte 
4026*fcf3ce44SJohn Forte 	/* issue the mbox cmd to the sli */
4027*fcf3ce44SJohn Forte 	mbxstatus = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
4028*fcf3ce44SJohn Forte 
4029*fcf3ce44SJohn Forte 	if (mbxstatus) {
4030*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4031*fcf3ce44SJohn Forte 		    "%s: %s failed. mbxstatus=0x%x",
4032*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
4033*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand),
4034*fcf3ce44SJohn Forte 		    mbxstatus);
4035*fcf3ce44SJohn Forte 
4036*fcf3ce44SJohn Forte 	}
4037*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)mb, (void *)dfc->buf2,
4038*fcf3ce44SJohn Forte 	    dfc->buf2_size, mode) != 0) {
4039*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4040*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed. cmd=%x",
4041*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4042*fcf3ce44SJohn Forte 
4043*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
4044*fcf3ce44SJohn Forte 		goto done;
4045*fcf3ce44SJohn Forte 	}
4046*fcf3ce44SJohn Forte 	if (rx_mp) {
4047*fcf3ce44SJohn Forte 		emlxs_mpdata_sync(rx_mp->dma_handle, 0, size,
4048*fcf3ce44SJohn Forte 		    DDI_DMA_SYNC_FORKERNEL);
4049*fcf3ce44SJohn Forte 
4050*fcf3ce44SJohn Forte 		if (ddi_copyout((void *)rx_mp->virt, (void *)lptr,
4051*fcf3ce44SJohn Forte 		    size, mode) != 0) {
4052*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4053*fcf3ce44SJohn Forte 			    "%s: ddi_copyout failed for receive buffer."
4054*fcf3ce44SJohn Forte 			    " cmd = %x",
4055*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
4056*fcf3ce44SJohn Forte 			    mb->mbxCommand);
4057*fcf3ce44SJohn Forte 
4058*fcf3ce44SJohn Forte 			rval = DFC_COPYOUT_ERROR;
4059*fcf3ce44SJohn Forte 			goto done;
4060*fcf3ce44SJohn Forte 		}
4061*fcf3ce44SJohn Forte 	}
4062*fcf3ce44SJohn Forte #ifdef MBOX_EXT_SUPPORT
4063*fcf3ce44SJohn Forte 	/* Any data needs to copy to mbox extension area */
4064*fcf3ce44SJohn Forte 	if (dfc->buf4_size) {
4065*fcf3ce44SJohn Forte 		if (ddi_copyout((void *)extbuf, (void *)dfc->buf4,
4066*fcf3ce44SJohn Forte 		    dfc->buf4_size, mode) != 0) {
4067*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4068*fcf3ce44SJohn Forte 			    "%s: ddi_copyout failed for mbox"
4069*fcf3ce44SJohn Forte 			    " extension data.",
4070*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
4071*fcf3ce44SJohn Forte 
4072*fcf3ce44SJohn Forte 			rval = DFC_COPYIN_ERROR;
4073*fcf3ce44SJohn Forte 			goto done;
4074*fcf3ce44SJohn Forte 		}
4075*fcf3ce44SJohn Forte 	}
4076*fcf3ce44SJohn Forte #endif	/* MBOX_EXT_SUPPORT */
4077*fcf3ce44SJohn Forte 
4078*fcf3ce44SJohn Forte 	rval = 0;
4079*fcf3ce44SJohn Forte 
4080*fcf3ce44SJohn Forte done:
4081*fcf3ce44SJohn Forte 
4082*fcf3ce44SJohn Forte 	/* Free allocated mbox memory */
4083*fcf3ce44SJohn Forte 	if (extbuf) {
4084*fcf3ce44SJohn Forte 		kmem_free(extbuf, extsize);
4085*fcf3ce44SJohn Forte 	}
4086*fcf3ce44SJohn Forte 	/* Free allocated mbox memory */
4087*fcf3ce44SJohn Forte 	if (mbq) {
4088*fcf3ce44SJohn Forte 		kmem_free(mbq, sizeof (MAILBOXQ));
4089*fcf3ce44SJohn Forte 	}
4090*fcf3ce44SJohn Forte 	/* Free allocated mbuf memory */
4091*fcf3ce44SJohn Forte 	if (rx_mp) {
4092*fcf3ce44SJohn Forte 		(void) emlxs_mem_buf_free(hba, (uint8_t *)rx_mp);
4093*fcf3ce44SJohn Forte 	}
4094*fcf3ce44SJohn Forte 	if (tx_mp) {
4095*fcf3ce44SJohn Forte 		(void) emlxs_mem_buf_free(hba, (uint8_t *)tx_mp);
4096*fcf3ce44SJohn Forte 	}
4097*fcf3ce44SJohn Forte 	return (rval);
4098*fcf3ce44SJohn Forte 
4099*fcf3ce44SJohn Forte } /* emlxs_dfc_send_mbox() */
4100*fcf3ce44SJohn Forte 
4101*fcf3ce44SJohn Forte 
4102*fcf3ce44SJohn Forte static int32_t
4103*fcf3ce44SJohn Forte emlxs_dfc_read_pci(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4104*fcf3ce44SJohn Forte {
4105*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4106*fcf3ce44SJohn Forte 	uint32_t offset;
4107*fcf3ce44SJohn Forte 	uint32_t cnt;
4108*fcf3ce44SJohn Forte 	uint32_t outsz;
4109*fcf3ce44SJohn Forte 	uint32_t i;
4110*fcf3ce44SJohn Forte 	uint32_t *buffer;
4111*fcf3ce44SJohn Forte 	uint32_t *bptr;
4112*fcf3ce44SJohn Forte 	uint32_t value;
4113*fcf3ce44SJohn Forte 	uint32_t size;
4114*fcf3ce44SJohn Forte 	uint32_t max = 4096;
4115*fcf3ce44SJohn Forte 
4116*fcf3ce44SJohn Forte 	offset = dfc->data1;
4117*fcf3ce44SJohn Forte 	cnt = dfc->data2;
4118*fcf3ce44SJohn Forte 	outsz = dfc->buf1_size;
4119*fcf3ce44SJohn Forte 
4120*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4121*fcf3ce44SJohn Forte 	    "%s: offset=%x count=%d",
4122*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd), offset, cnt);
4123*fcf3ce44SJohn Forte 
4124*fcf3ce44SJohn Forte 	if (!dfc->buf1_size || !dfc->buf1) {
4125*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4126*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
4127*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4128*fcf3ce44SJohn Forte 
4129*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
4130*fcf3ce44SJohn Forte 	}
4131*fcf3ce44SJohn Forte 	if (offset & 0x3) {
4132*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4133*fcf3ce44SJohn Forte 		    "%s: Offset misaligned. (offset=%d)",
4134*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset);
4135*fcf3ce44SJohn Forte 
4136*fcf3ce44SJohn Forte 		return (DFC_ARG_MISALIGNED);
4137*fcf3ce44SJohn Forte 	}
4138*fcf3ce44SJohn Forte 	if (cnt & 0x3) {
4139*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4140*fcf3ce44SJohn Forte 		    "%s: Count misaligned. (count=%d)",
4141*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), cnt);
4142*fcf3ce44SJohn Forte 
4143*fcf3ce44SJohn Forte 		return (DFC_ARG_MISALIGNED);
4144*fcf3ce44SJohn Forte 	}
4145*fcf3ce44SJohn Forte 	if (outsz & 0x3) {
4146*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4147*fcf3ce44SJohn Forte 		    "%s: Output size misaligned. (size=%d)",
4148*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), outsz);
4149*fcf3ce44SJohn Forte 
4150*fcf3ce44SJohn Forte 		return (DFC_ARG_MISALIGNED);
4151*fcf3ce44SJohn Forte 	}
4152*fcf3ce44SJohn Forte 	/* Get max PCI config range */
4153*fcf3ce44SJohn Forte 	if (hba->model_info.chip <= EMLXS_HELIOS_CHIP) {
4154*fcf3ce44SJohn Forte 		max = 256;
4155*fcf3ce44SJohn Forte 	} else {
4156*fcf3ce44SJohn Forte 		max = 4096;
4157*fcf3ce44SJohn Forte 	}
4158*fcf3ce44SJohn Forte 
4159*fcf3ce44SJohn Forte 	if ((cnt + offset) > max) {
4160*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4161*fcf3ce44SJohn Forte 		    "%s: Offset+Count too large."
4162*fcf3ce44SJohn Forte 		    " (offset=%d count=%d max=%d)",
4163*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset,
4164*fcf3ce44SJohn Forte 		    cnt, max);
4165*fcf3ce44SJohn Forte 
4166*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
4167*fcf3ce44SJohn Forte 	}
4168*fcf3ce44SJohn Forte 	if (outsz > max) {
4169*fcf3ce44SJohn Forte 		outsz = max;
4170*fcf3ce44SJohn Forte 	}
4171*fcf3ce44SJohn Forte 	if (cnt > outsz) {
4172*fcf3ce44SJohn Forte 		cnt = outsz;
4173*fcf3ce44SJohn Forte 	}
4174*fcf3ce44SJohn Forte 	size = cnt;
4175*fcf3ce44SJohn Forte 
4176*fcf3ce44SJohn Forte 	if (!(buffer = (uint32_t *)kmem_zalloc(size, KM_NOSLEEP))) {
4177*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4178*fcf3ce44SJohn Forte 		    "%s: Unable to allocate buffer.",
4179*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4180*fcf3ce44SJohn Forte 
4181*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
4182*fcf3ce44SJohn Forte 	}
4183*fcf3ce44SJohn Forte 	bptr = buffer;
4184*fcf3ce44SJohn Forte 	for (i = offset; i < (offset + cnt); i += 4) {
4185*fcf3ce44SJohn Forte 		value = ddi_get32(hba->pci_acc_handle,
4186*fcf3ce44SJohn Forte 		    (uint32_t *)(hba->pci_addr + i));
4187*fcf3ce44SJohn Forte 		*bptr++ = PCIMEM_LONG(value);
4188*fcf3ce44SJohn Forte 	}
4189*fcf3ce44SJohn Forte 
4190*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)buffer, (void *)dfc->buf1,
4191*fcf3ce44SJohn Forte 	    outsz, mode) != 0) {
4192*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4193*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
4194*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4195*fcf3ce44SJohn Forte 
4196*fcf3ce44SJohn Forte 		kmem_free(buffer, size);
4197*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
4198*fcf3ce44SJohn Forte 	}
4199*fcf3ce44SJohn Forte 	kmem_free(buffer, size);
4200*fcf3ce44SJohn Forte 	return (0);
4201*fcf3ce44SJohn Forte 
4202*fcf3ce44SJohn Forte } /* emlxs_dfc_read_pci() */
4203*fcf3ce44SJohn Forte 
4204*fcf3ce44SJohn Forte 
4205*fcf3ce44SJohn Forte static int32_t
4206*fcf3ce44SJohn Forte emlxs_dfc_write_pci(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4207*fcf3ce44SJohn Forte {
4208*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4209*fcf3ce44SJohn Forte 	uint32_t offset;
4210*fcf3ce44SJohn Forte 	uint32_t cnt;
4211*fcf3ce44SJohn Forte 	/* uint32_t outsz; */
4212*fcf3ce44SJohn Forte 	uint32_t value;
4213*fcf3ce44SJohn Forte 	uint32_t i;
4214*fcf3ce44SJohn Forte 	uint32_t max;
4215*fcf3ce44SJohn Forte 	uint8_t buffer[256];
4216*fcf3ce44SJohn Forte 	uint32_t *bptr;
4217*fcf3ce44SJohn Forte 	uint16_t word0;
4218*fcf3ce44SJohn Forte 	uint16_t word1;
4219*fcf3ce44SJohn Forte 
4220*fcf3ce44SJohn Forte 	offset = dfc->data1;
4221*fcf3ce44SJohn Forte 	cnt = dfc->data2;
4222*fcf3ce44SJohn Forte 
4223*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4224*fcf3ce44SJohn Forte 	    "%s: offset = %x count = %d",
4225*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd), offset, cnt);
4226*fcf3ce44SJohn Forte 
4227*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
4228*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4229*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
4230*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4231*fcf3ce44SJohn Forte 
4232*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
4233*fcf3ce44SJohn Forte 	}
4234*fcf3ce44SJohn Forte 	if (offset & 0x3) {
4235*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4236*fcf3ce44SJohn Forte 		    "%s: Offset misaligned. (offset = %d)",
4237*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset);
4238*fcf3ce44SJohn Forte 
4239*fcf3ce44SJohn Forte 		return (DFC_ARG_MISALIGNED);
4240*fcf3ce44SJohn Forte 	}
4241*fcf3ce44SJohn Forte 	if (cnt > dfc->buf1_size) {
4242*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4243*fcf3ce44SJohn Forte 		    "%s: Count too large. (count=%d)",
4244*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), cnt);
4245*fcf3ce44SJohn Forte 
4246*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
4247*fcf3ce44SJohn Forte 	}
4248*fcf3ce44SJohn Forte 	if (cnt & 0x3) {
4249*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4250*fcf3ce44SJohn Forte 		    "%s: Count misaligned. (count = %d)",
4251*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), cnt);
4252*fcf3ce44SJohn Forte 
4253*fcf3ce44SJohn Forte 		return (DFC_ARG_MISALIGNED);
4254*fcf3ce44SJohn Forte 	}
4255*fcf3ce44SJohn Forte 	/* Get max PCI config range */
4256*fcf3ce44SJohn Forte 	if (hba->model_info.chip <= EMLXS_HELIOS_CHIP) {
4257*fcf3ce44SJohn Forte 		max = 256;
4258*fcf3ce44SJohn Forte 	} else {
4259*fcf3ce44SJohn Forte 		max = 4096;
4260*fcf3ce44SJohn Forte 	}
4261*fcf3ce44SJohn Forte 
4262*fcf3ce44SJohn Forte 	if ((cnt + offset) > max) {
4263*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4264*fcf3ce44SJohn Forte 		    "%s: Count+Offset too large."
4265*fcf3ce44SJohn Forte 		    " (offset = %d count = %d max = %d)",
4266*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset, cnt, max);
4267*fcf3ce44SJohn Forte 
4268*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
4269*fcf3ce44SJohn Forte 	}
4270*fcf3ce44SJohn Forte 	bzero(buffer, sizeof (buffer));
4271*fcf3ce44SJohn Forte 
4272*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)buffer, cnt, mode) != 0) {
4273*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4274*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
4275*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4276*fcf3ce44SJohn Forte 
4277*fcf3ce44SJohn Forte 		return (DFC_COPYIN_ERROR);
4278*fcf3ce44SJohn Forte 	}
4279*fcf3ce44SJohn Forte 	bptr = (uint32_t *)buffer;
4280*fcf3ce44SJohn Forte 	for (i = offset; i < (offset + cnt); i += 4) {
4281*fcf3ce44SJohn Forte 		value = *bptr++;
4282*fcf3ce44SJohn Forte 		value = PCIMEM_LONG(value);
4283*fcf3ce44SJohn Forte 
4284*fcf3ce44SJohn Forte 		word0 = value & 0xFFFF;
4285*fcf3ce44SJohn Forte 		word1 = value >> 16;
4286*fcf3ce44SJohn Forte 
4287*fcf3ce44SJohn Forte 		/*
4288*fcf3ce44SJohn Forte 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, "%s:
4289*fcf3ce44SJohn Forte 		 * Writing. offset=%x cnt=%d value=%08x %04x %04x",
4290*fcf3ce44SJohn Forte 		 * emlxs_dfc_xlate(dfc->cmd), i, value, word0, word1);
4291*fcf3ce44SJohn Forte 		 */
4292*fcf3ce44SJohn Forte 
4293*fcf3ce44SJohn Forte 		/* word0 = PCIMEM_SHORT(word0); */
4294*fcf3ce44SJohn Forte 		(void) ddi_put16(hba->pci_acc_handle,
4295*fcf3ce44SJohn Forte 		    (uint16_t *)(hba->pci_addr + i),
4296*fcf3ce44SJohn Forte 		    (uint16_t)word0);
4297*fcf3ce44SJohn Forte 
4298*fcf3ce44SJohn Forte 		/* word1 = PCIMEM_SHORT(word1); */
4299*fcf3ce44SJohn Forte 		(void) ddi_put16(hba->pci_acc_handle,
4300*fcf3ce44SJohn Forte 		    (uint16_t *)(hba->pci_addr + i + 2), (uint16_t)word1);
4301*fcf3ce44SJohn Forte 	}
4302*fcf3ce44SJohn Forte 
4303*fcf3ce44SJohn Forte 	return (0);
4304*fcf3ce44SJohn Forte 
4305*fcf3ce44SJohn Forte } /* emlxs_dfc_write_pci() */
4306*fcf3ce44SJohn Forte 
4307*fcf3ce44SJohn Forte 
4308*fcf3ce44SJohn Forte static int32_t
4309*fcf3ce44SJohn Forte emlxs_dfc_get_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4310*fcf3ce44SJohn Forte {
4311*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4312*fcf3ce44SJohn Forte 	dfc_cfgparam_t *cfgparam;
4313*fcf3ce44SJohn Forte 	uint32_t size;
4314*fcf3ce44SJohn Forte 	uint32_t count;
4315*fcf3ce44SJohn Forte 	uint32_t i;
4316*fcf3ce44SJohn Forte 	int32_t rval = 0;
4317*fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
4318*fcf3ce44SJohn Forte 
4319*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
4320*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4321*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
4322*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4323*fcf3ce44SJohn Forte 
4324*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
4325*fcf3ce44SJohn Forte 	}
4326*fcf3ce44SJohn Forte 	count = dfc->buf1_size / sizeof (dfc_cfgparam_t);
4327*fcf3ce44SJohn Forte 
4328*fcf3ce44SJohn Forte 	if (count > MAX_CFG_PARAM) {
4329*fcf3ce44SJohn Forte 		count = MAX_CFG_PARAM;
4330*fcf3ce44SJohn Forte 	}
4331*fcf3ce44SJohn Forte 	if (count > NUM_CFG_PARAM) {
4332*fcf3ce44SJohn Forte 		count = NUM_CFG_PARAM;
4333*fcf3ce44SJohn Forte 	}
4334*fcf3ce44SJohn Forte 	size = count * sizeof (dfc_cfgparam_t);
4335*fcf3ce44SJohn Forte 
4336*fcf3ce44SJohn Forte 	if (!(cfgparam = (dfc_cfgparam_t *)kmem_zalloc(size, KM_NOSLEEP))) {
4337*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4338*fcf3ce44SJohn Forte 		    "%s: Unable to allocate cfgparm buffer.",
4339*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4340*fcf3ce44SJohn Forte 
4341*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
4342*fcf3ce44SJohn Forte 	}
4343*fcf3ce44SJohn Forte 	cfg = &CFG;
4344*fcf3ce44SJohn Forte 	for (i = 0; i < count; i++) {
4345*fcf3ce44SJohn Forte 		(void) strncpy(cfgparam[i].a_string, cfg[i].string,
4346*fcf3ce44SJohn Forte 		    sizeof (cfgparam[i].a_string));
4347*fcf3ce44SJohn Forte 		cfgparam[i].a_low = cfg[i].low;
4348*fcf3ce44SJohn Forte 		cfgparam[i].a_hi = cfg[i].hi;
4349*fcf3ce44SJohn Forte 		cfgparam[i].a_default = cfg[i].def;
4350*fcf3ce44SJohn Forte 		cfgparam[i].a_current = cfg[i].current;
4351*fcf3ce44SJohn Forte 
4352*fcf3ce44SJohn Forte 		if (!(cfg[i].flags & PARM_HIDDEN)) {
4353*fcf3ce44SJohn Forte 			cfgparam[i].a_flag |= CFG_EXPORT;
4354*fcf3ce44SJohn Forte 		}
4355*fcf3ce44SJohn Forte 		if ((cfg[i].flags & PARM_DYNAMIC)) {
4356*fcf3ce44SJohn Forte 			if ((cfg[i].flags & PARM_DYNAMIC_RESET) ==
4357*fcf3ce44SJohn Forte 			    PARM_DYNAMIC_RESET) {
4358*fcf3ce44SJohn Forte 				cfgparam[i].a_changestate = CFG_RESTART;
4359*fcf3ce44SJohn Forte 			} else {
4360*fcf3ce44SJohn Forte 				cfgparam[i].a_changestate = CFG_DYMANIC;
4361*fcf3ce44SJohn Forte 			}
4362*fcf3ce44SJohn Forte 		} else {
4363*fcf3ce44SJohn Forte 			cfgparam[i].a_changestate = CFG_REBOOT;
4364*fcf3ce44SJohn Forte 		}
4365*fcf3ce44SJohn Forte 
4366*fcf3ce44SJohn Forte 		(void) strncpy(cfgparam[i].a_help, cfg[i].help,
4367*fcf3ce44SJohn Forte 		    sizeof (cfgparam[i].a_help));
4368*fcf3ce44SJohn Forte 	}
4369*fcf3ce44SJohn Forte 
4370*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)cfgparam, (void *)dfc->buf1,
4371*fcf3ce44SJohn Forte 	    size, mode) != 0) {
4372*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4373*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
4374*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4375*fcf3ce44SJohn Forte 
4376*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
4377*fcf3ce44SJohn Forte 	}
4378*fcf3ce44SJohn Forte 	rval = 0;
4379*fcf3ce44SJohn Forte 
4380*fcf3ce44SJohn Forte 	kmem_free(cfgparam, size);
4381*fcf3ce44SJohn Forte 
4382*fcf3ce44SJohn Forte 	return (rval);
4383*fcf3ce44SJohn Forte 
4384*fcf3ce44SJohn Forte } /* emlxs_dfc_get_cfg() */
4385*fcf3ce44SJohn Forte 
4386*fcf3ce44SJohn Forte 
4387*fcf3ce44SJohn Forte /*ARGSUSED*/
4388*fcf3ce44SJohn Forte static int32_t
4389*fcf3ce44SJohn Forte emlxs_dfc_set_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4390*fcf3ce44SJohn Forte {
4391*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4392*fcf3ce44SJohn Forte 	uint32_t index;
4393*fcf3ce44SJohn Forte 	uint32_t new_value;
4394*fcf3ce44SJohn Forte 	uint32_t rc;
4395*fcf3ce44SJohn Forte 
4396*fcf3ce44SJohn Forte 	index = dfc->data1;
4397*fcf3ce44SJohn Forte 	new_value = dfc->data2;
4398*fcf3ce44SJohn Forte 
4399*fcf3ce44SJohn Forte 	rc = emlxs_set_parm(hba, index, new_value);
4400*fcf3ce44SJohn Forte 
4401*fcf3ce44SJohn Forte 	if (rc) {
4402*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4403*fcf3ce44SJohn Forte 		    "%s: Unable to set parameter. code=%d",
4404*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), rc);
4405*fcf3ce44SJohn Forte 
4406*fcf3ce44SJohn Forte 		switch (rc) {
4407*fcf3ce44SJohn Forte 		case 2:
4408*fcf3ce44SJohn Forte 			return (DFC_NPIV_ACTIVE);
4409*fcf3ce44SJohn Forte 
4410*fcf3ce44SJohn Forte 		default:
4411*fcf3ce44SJohn Forte 			return (DFC_ARG_INVALID);
4412*fcf3ce44SJohn Forte 		}
4413*fcf3ce44SJohn Forte 	}
4414*fcf3ce44SJohn Forte 	return (0);
4415*fcf3ce44SJohn Forte 
4416*fcf3ce44SJohn Forte } /* emlxs_dfc_set_cfg() */
4417*fcf3ce44SJohn Forte 
4418*fcf3ce44SJohn Forte 
4419*fcf3ce44SJohn Forte static int32_t
4420*fcf3ce44SJohn Forte emlxs_dfc_send_ct(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4421*fcf3ce44SJohn Forte {
4422*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4423*fcf3ce44SJohn Forte 	uint8_t *rsp_buf;
4424*fcf3ce44SJohn Forte 	uint8_t *cmd_buf;
4425*fcf3ce44SJohn Forte 	uint32_t did;
4426*fcf3ce44SJohn Forte 	uint32_t rsp_size;
4427*fcf3ce44SJohn Forte 	uint32_t cmd_size;
4428*fcf3ce44SJohn Forte 	uint32_t timeout;
4429*fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
4430*fcf3ce44SJohn Forte 	uint32_t rval = 0;
4431*fcf3ce44SJohn Forte 	dfc_destid_t destid;
4432*fcf3ce44SJohn Forte 	NODELIST *nlp;
4433*fcf3ce44SJohn Forte 	char buffer[128];
4434*fcf3ce44SJohn Forte 
4435*fcf3ce44SJohn Forte 	cmd_buf = dfc->buf1;
4436*fcf3ce44SJohn Forte 	cmd_size = dfc->buf1_size;
4437*fcf3ce44SJohn Forte 	rsp_buf = dfc->buf2;
4438*fcf3ce44SJohn Forte 	rsp_size = dfc->buf2_size;
4439*fcf3ce44SJohn Forte 	timeout = dfc->data1;
4440*fcf3ce44SJohn Forte 
4441*fcf3ce44SJohn Forte 	if (timeout < (2 * hba->fc_ratov)) {
4442*fcf3ce44SJohn Forte 		timeout = 2 * hba->fc_ratov;
4443*fcf3ce44SJohn Forte 	}
4444*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4445*fcf3ce44SJohn Forte 	    "%s: csize=%d rsize=%d",
4446*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd), cmd_size, rsp_size);
4447*fcf3ce44SJohn Forte 
4448*fcf3ce44SJohn Forte 
4449*fcf3ce44SJohn Forte 	if (!cmd_size || !cmd_buf) {
4450*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4451*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
4452*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4453*fcf3ce44SJohn Forte 
4454*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
4455*fcf3ce44SJohn Forte 		goto done;
4456*fcf3ce44SJohn Forte 	}
4457*fcf3ce44SJohn Forte 	if (!rsp_size || !rsp_buf) {
4458*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4459*fcf3ce44SJohn Forte 		    "%s: Null buffer2 found.",
4460*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4461*fcf3ce44SJohn Forte 
4462*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
4463*fcf3ce44SJohn Forte 		goto done;
4464*fcf3ce44SJohn Forte 	}
4465*fcf3ce44SJohn Forte 	if (!dfc->buf3 || !dfc->buf3_size) {
4466*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4467*fcf3ce44SJohn Forte 		    "%s: Null buffer3 found.",
4468*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4469*fcf3ce44SJohn Forte 
4470*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
4471*fcf3ce44SJohn Forte 		goto done;
4472*fcf3ce44SJohn Forte 	}
4473*fcf3ce44SJohn Forte 	if (!dfc->buf4 || !dfc->buf4_size) {
4474*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4475*fcf3ce44SJohn Forte 		    "%s: Null buffer4 found.",
4476*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4477*fcf3ce44SJohn Forte 
4478*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
4479*fcf3ce44SJohn Forte 		goto done;
4480*fcf3ce44SJohn Forte 	}
4481*fcf3ce44SJohn Forte 	if (rsp_size > MAX_CT_PAYLOAD) {
4482*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4483*fcf3ce44SJohn Forte 		    "%s: Buffer2 too large. size=%d",
4484*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), rsp_size);
4485*fcf3ce44SJohn Forte 
4486*fcf3ce44SJohn Forte 		rval = DFC_ARG_TOOBIG;
4487*fcf3ce44SJohn Forte 		goto done;
4488*fcf3ce44SJohn Forte 	}
4489*fcf3ce44SJohn Forte 	if (cmd_size > MAX_CT_PAYLOAD) {
4490*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4491*fcf3ce44SJohn Forte 		    "%s: Buffer1 too large. size=%d",
4492*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), cmd_size);
4493*fcf3ce44SJohn Forte 
4494*fcf3ce44SJohn Forte 		rval = DFC_ARG_TOOBIG;
4495*fcf3ce44SJohn Forte 		goto done;
4496*fcf3ce44SJohn Forte 	}
4497*fcf3ce44SJohn Forte 	if (dfc->buf3_size < sizeof (dfc_destid_t)) {
4498*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4499*fcf3ce44SJohn Forte 		    "%s: Buffer3 too small. (size=%d)",
4500*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
4501*fcf3ce44SJohn Forte 
4502*fcf3ce44SJohn Forte 		rval = DFC_ARG_TOOSMALL;
4503*fcf3ce44SJohn Forte 		goto done;
4504*fcf3ce44SJohn Forte 	}
4505*fcf3ce44SJohn Forte 	if (dfc->buf4_size < sizeof (uint32_t)) {
4506*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4507*fcf3ce44SJohn Forte 		    "%s: Buffer4 too small. (size=%d)",
4508*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf4_size);
4509*fcf3ce44SJohn Forte 
4510*fcf3ce44SJohn Forte 		rval = DFC_ARG_TOOSMALL;
4511*fcf3ce44SJohn Forte 		goto done;
4512*fcf3ce44SJohn Forte 	}
4513*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf3, (void *)&destid,
4514*fcf3ce44SJohn Forte 	    sizeof (dfc_destid_t), mode) != 0) {
4515*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4516*fcf3ce44SJohn Forte 		    "%s: Unable to read destination id.",
4517*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4518*fcf3ce44SJohn Forte 
4519*fcf3ce44SJohn Forte 		rval = DFC_COPYIN_ERROR;
4520*fcf3ce44SJohn Forte 		goto done;
4521*fcf3ce44SJohn Forte 	}
4522*fcf3ce44SJohn Forte 	if (destid.idType == 0) {
4523*fcf3ce44SJohn Forte 		if ((nlp = emlxs_node_find_wwpn(port, destid.wwpn)) == NULL) {
4524*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4525*fcf3ce44SJohn Forte 			    "%s: WWPN does not exists. %s",
4526*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
4527*fcf3ce44SJohn Forte 			    emlxs_wwn_xlate(buffer, destid.wwpn));
4528*fcf3ce44SJohn Forte 
4529*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
4530*fcf3ce44SJohn Forte 			goto done;
4531*fcf3ce44SJohn Forte 		}
4532*fcf3ce44SJohn Forte 		did = nlp->nlp_DID;
4533*fcf3ce44SJohn Forte 	} else {
4534*fcf3ce44SJohn Forte 		if (emlxs_node_find_did(port, destid.d_id) == NULL) {
4535*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4536*fcf3ce44SJohn Forte 			    "%s: DID does not exist. did=%x",
4537*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), destid.d_id);
4538*fcf3ce44SJohn Forte 
4539*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
4540*fcf3ce44SJohn Forte 			goto done;
4541*fcf3ce44SJohn Forte 		}
4542*fcf3ce44SJohn Forte 		did = destid.d_id;
4543*fcf3ce44SJohn Forte 	}
4544*fcf3ce44SJohn Forte 
4545*fcf3ce44SJohn Forte 	if (did == 0) {
4546*fcf3ce44SJohn Forte 		did = port->did;
4547*fcf3ce44SJohn Forte 	}
4548*fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size, 0, KM_NOSLEEP))) {
4549*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4550*fcf3ce44SJohn Forte 		    "%s: Unable to allocate packet.",
4551*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4552*fcf3ce44SJohn Forte 
4553*fcf3ce44SJohn Forte 		rval = DFC_SYSRES_ERROR;
4554*fcf3ce44SJohn Forte 		goto done;
4555*fcf3ce44SJohn Forte 	}
4556*fcf3ce44SJohn Forte 	/* Make this a polled IO */
4557*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
4558*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
4559*fcf3ce44SJohn Forte 	pkt->pkt_comp = NULL;
4560*fcf3ce44SJohn Forte 
4561*fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
4562*fcf3ce44SJohn Forte 	pkt->pkt_timeout = (timeout) ? timeout : 30;
4563*fcf3ce44SJohn Forte 
4564*fcf3ce44SJohn Forte 	/* Build the fc header */
4565*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(did);
4566*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL;
4567*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
4568*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
4569*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
4570*fcf3ce44SJohn Forte 	    F_CTL_SEQ_INITIATIVE;
4571*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
4572*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4573*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4574*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
4575*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
4576*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
4577*fcf3ce44SJohn Forte 
4578*fcf3ce44SJohn Forte 	/* Copy in the command buffer */
4579*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd,
4580*fcf3ce44SJohn Forte 	    cmd_size, mode) != 0) {
4581*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4582*fcf3ce44SJohn Forte 		    "%s: Unable to read command buffer.",
4583*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4584*fcf3ce44SJohn Forte 
4585*fcf3ce44SJohn Forte 		rval = DFC_COPYIN_ERROR;
4586*fcf3ce44SJohn Forte 		goto done;
4587*fcf3ce44SJohn Forte 	}
4588*fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
4589*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4590*fcf3ce44SJohn Forte 		    "%s: Unable to send packet.",
4591*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4592*fcf3ce44SJohn Forte 
4593*fcf3ce44SJohn Forte 		rval = DFC_IO_ERROR;
4594*fcf3ce44SJohn Forte 		goto done;
4595*fcf3ce44SJohn Forte 	}
4596*fcf3ce44SJohn Forte 	if ((pkt->pkt_state != FC_PKT_SUCCESS) &&
4597*fcf3ce44SJohn Forte 	    (pkt->pkt_state != FC_PKT_FS_RJT)) {
4598*fcf3ce44SJohn Forte 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
4599*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4600*fcf3ce44SJohn Forte 			    "Pkt Transport error. Pkt Timeout.");
4601*fcf3ce44SJohn Forte 			rval = DFC_TIMEOUT;
4602*fcf3ce44SJohn Forte 		} else {
4603*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4604*fcf3ce44SJohn Forte 			    "Pkt Transport error. state=%x",
4605*fcf3ce44SJohn Forte 			    pkt->pkt_state);
4606*fcf3ce44SJohn Forte 			rval = DFC_IO_ERROR;
4607*fcf3ce44SJohn Forte 		}
4608*fcf3ce44SJohn Forte 		goto done;
4609*fcf3ce44SJohn Forte 	}
4610*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)pkt->pkt_resp, (void *)rsp_buf,
4611*fcf3ce44SJohn Forte 	    rsp_size, mode) != 0) {
4612*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4613*fcf3ce44SJohn Forte 		    "%s: Unable to read response.",
4614*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4615*fcf3ce44SJohn Forte 
4616*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
4617*fcf3ce44SJohn Forte 		goto done;
4618*fcf3ce44SJohn Forte 	}
4619*fcf3ce44SJohn Forte 	rsp_size -= pkt->pkt_resp_resid;
4620*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf4,
4621*fcf3ce44SJohn Forte 	    dfc->buf4_size, mode) != 0) {
4622*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4623*fcf3ce44SJohn Forte 		    "%s: Unable to write response.",
4624*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4625*fcf3ce44SJohn Forte 
4626*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
4627*fcf3ce44SJohn Forte 		goto done;
4628*fcf3ce44SJohn Forte 	}
4629*fcf3ce44SJohn Forte 	rval = 0;
4630*fcf3ce44SJohn Forte 
4631*fcf3ce44SJohn Forte done:
4632*fcf3ce44SJohn Forte 
4633*fcf3ce44SJohn Forte 	if (pkt) {
4634*fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
4635*fcf3ce44SJohn Forte 	}
4636*fcf3ce44SJohn Forte 	return (rval);
4637*fcf3ce44SJohn Forte 
4638*fcf3ce44SJohn Forte } /* emlxs_dfc_send_ct() */
4639*fcf3ce44SJohn Forte 
4640*fcf3ce44SJohn Forte 
4641*fcf3ce44SJohn Forte static int32_t
4642*fcf3ce44SJohn Forte emlxs_dfc_send_ct_rsp(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4643*fcf3ce44SJohn Forte {
4644*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4645*fcf3ce44SJohn Forte 	uint8_t *cmd_buf;
4646*fcf3ce44SJohn Forte 	uint32_t rx_id;
4647*fcf3ce44SJohn Forte 	uint32_t cmd_size;
4648*fcf3ce44SJohn Forte 	uint32_t timeout;
4649*fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
4650*fcf3ce44SJohn Forte 	uint32_t rval = 0;
4651*fcf3ce44SJohn Forte 	/* dfc_destid_t destid; */
4652*fcf3ce44SJohn Forte 
4653*fcf3ce44SJohn Forte 	cmd_buf = dfc->buf1;
4654*fcf3ce44SJohn Forte 	cmd_size = dfc->buf1_size;
4655*fcf3ce44SJohn Forte 	rx_id = dfc->flag;
4656*fcf3ce44SJohn Forte 	timeout = 2 * hba->fc_ratov;
4657*fcf3ce44SJohn Forte 
4658*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4659*fcf3ce44SJohn Forte 	    "%s: csize=%d",
4660*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd), cmd_size);
4661*fcf3ce44SJohn Forte 
4662*fcf3ce44SJohn Forte 	if (!cmd_size || !cmd_buf) {
4663*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4664*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
4665*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4666*fcf3ce44SJohn Forte 
4667*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
4668*fcf3ce44SJohn Forte 		goto done;
4669*fcf3ce44SJohn Forte 	}
4670*fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, 0, 0, KM_NOSLEEP))) {
4671*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4672*fcf3ce44SJohn Forte 		    "%s: Unable to allocate packet.",
4673*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4674*fcf3ce44SJohn Forte 
4675*fcf3ce44SJohn Forte 		rval = DFC_SYSRES_ERROR;
4676*fcf3ce44SJohn Forte 		goto done;
4677*fcf3ce44SJohn Forte 	}
4678*fcf3ce44SJohn Forte 	/* Make this a polled IO */
4679*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
4680*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
4681*fcf3ce44SJohn Forte 	pkt->pkt_comp = NULL;
4682*fcf3ce44SJohn Forte 
4683*fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
4684*fcf3ce44SJohn Forte 	pkt->pkt_timeout = (timeout) ? timeout : 30;
4685*fcf3ce44SJohn Forte 
4686*fcf3ce44SJohn Forte 	/* Build the fc header */
4687*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(0);
4688*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_SOLICITED_CONTROL;
4689*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
4690*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
4691*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_END_SEQ |
4692*fcf3ce44SJohn Forte 	    F_CTL_XCHG_CONTEXT;
4693*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
4694*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4695*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4696*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
4697*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = rx_id;
4698*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
4699*fcf3ce44SJohn Forte 
4700*fcf3ce44SJohn Forte 	/* Copy in the command buffer */
4701*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd,
4702*fcf3ce44SJohn Forte 	    cmd_size, mode) != 0) {
4703*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4704*fcf3ce44SJohn Forte 		    "%s: Unable to read command buffer.",
4705*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4706*fcf3ce44SJohn Forte 
4707*fcf3ce44SJohn Forte 		rval = DFC_COPYIN_ERROR;
4708*fcf3ce44SJohn Forte 		goto done;
4709*fcf3ce44SJohn Forte 	}
4710*fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
4711*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4712*fcf3ce44SJohn Forte 		    "%s: Unable to send packet.",
4713*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4714*fcf3ce44SJohn Forte 
4715*fcf3ce44SJohn Forte 		rval = DFC_IO_ERROR;
4716*fcf3ce44SJohn Forte 		goto done;
4717*fcf3ce44SJohn Forte 	}
4718*fcf3ce44SJohn Forte 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
4719*fcf3ce44SJohn Forte 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
4720*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4721*fcf3ce44SJohn Forte 			    "Pkt Transport error. Pkt Timeout.");
4722*fcf3ce44SJohn Forte 			rval = DFC_TIMEOUT;
4723*fcf3ce44SJohn Forte 		} else {
4724*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4725*fcf3ce44SJohn Forte 			    "Pkt Transport error. state=%x",
4726*fcf3ce44SJohn Forte 			    pkt->pkt_state);
4727*fcf3ce44SJohn Forte 			rval = DFC_IO_ERROR;
4728*fcf3ce44SJohn Forte 		}
4729*fcf3ce44SJohn Forte 		goto done;
4730*fcf3ce44SJohn Forte 	}
4731*fcf3ce44SJohn Forte 	rval = 0;
4732*fcf3ce44SJohn Forte 
4733*fcf3ce44SJohn Forte done:
4734*fcf3ce44SJohn Forte 
4735*fcf3ce44SJohn Forte 	if (pkt) {
4736*fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
4737*fcf3ce44SJohn Forte 	}
4738*fcf3ce44SJohn Forte 	return (rval);
4739*fcf3ce44SJohn Forte 
4740*fcf3ce44SJohn Forte } /* emlxs_dfc_send_ct_rsp() */
4741*fcf3ce44SJohn Forte 
4742*fcf3ce44SJohn Forte 
4743*fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
4744*fcf3ce44SJohn Forte 
4745*fcf3ce44SJohn Forte static int32_t
4746*fcf3ce44SJohn Forte emlxs_dfc_send_menlo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4747*fcf3ce44SJohn Forte {
4748*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4749*fcf3ce44SJohn Forte 	uint8_t *rsp_buf;
4750*fcf3ce44SJohn Forte 	uint8_t *cmd_buf;
4751*fcf3ce44SJohn Forte 	uint8_t *data_buf;
4752*fcf3ce44SJohn Forte 	/* uint32_t did; */
4753*fcf3ce44SJohn Forte 	uint32_t rsp_size;
4754*fcf3ce44SJohn Forte 	uint32_t cmd_size;
4755*fcf3ce44SJohn Forte 	uint32_t data_size;
4756*fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
4757*fcf3ce44SJohn Forte 	uint32_t rval = 0;
4758*fcf3ce44SJohn Forte 	/* char buffer[128]; */
4759*fcf3ce44SJohn Forte 	menlo_set_cmd_t set_cmd;
4760*fcf3ce44SJohn Forte 	menlo_reset_cmd_t reset_cmd;
4761*fcf3ce44SJohn Forte 	uint32_t rsp_code;
4762*fcf3ce44SJohn Forte 	uint32_t mm_mode;
4763*fcf3ce44SJohn Forte 	uint32_t cmd_code;
4764*fcf3ce44SJohn Forte 	clock_t timeout;
4765*fcf3ce44SJohn Forte 	MAILBOXQ *mbq = NULL;
4766*fcf3ce44SJohn Forte 	MAILBOX *mb;
4767*fcf3ce44SJohn Forte 	uint32_t addr;
4768*fcf3ce44SJohn Forte 	uint32_t value;
4769*fcf3ce44SJohn Forte 	uint32_t mbxstatus;
4770*fcf3ce44SJohn Forte 
4771*fcf3ce44SJohn Forte 	cmd_buf = dfc->buf1;
4772*fcf3ce44SJohn Forte 	cmd_size = dfc->buf1_size;
4773*fcf3ce44SJohn Forte 	rsp_buf = dfc->buf2;
4774*fcf3ce44SJohn Forte 	rsp_size = dfc->buf2_size;
4775*fcf3ce44SJohn Forte 	data_buf = NULL;
4776*fcf3ce44SJohn Forte 	data_size = 0;
4777*fcf3ce44SJohn Forte 	mm_mode = 0;
4778*fcf3ce44SJohn Forte 
4779*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4780*fcf3ce44SJohn Forte 	    "%s: csize=%d rsize=%d",
4781*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd), cmd_size, rsp_size);
4782*fcf3ce44SJohn Forte 
4783*fcf3ce44SJohn Forte 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
4784*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4785*fcf3ce44SJohn Forte 		    "%s: Menlo device not present. device=%x,%x",
4786*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), hba->model_info.device_id,
4787*fcf3ce44SJohn Forte 		    hba->model_info.ssdid);
4788*fcf3ce44SJohn Forte 
4789*fcf3ce44SJohn Forte 		rval = DFC_INVALID_ADAPTER;
4790*fcf3ce44SJohn Forte 		goto done;
4791*fcf3ce44SJohn Forte 	}
4792*fcf3ce44SJohn Forte 	if (!cmd_size || !cmd_buf) {
4793*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4794*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
4795*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4796*fcf3ce44SJohn Forte 
4797*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
4798*fcf3ce44SJohn Forte 		goto done;
4799*fcf3ce44SJohn Forte 	}
4800*fcf3ce44SJohn Forte 	if (!rsp_size || !rsp_buf) {
4801*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4802*fcf3ce44SJohn Forte 		    "%s: Null buffer2 found.",
4803*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4804*fcf3ce44SJohn Forte 
4805*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
4806*fcf3ce44SJohn Forte 		goto done;
4807*fcf3ce44SJohn Forte 	}
4808*fcf3ce44SJohn Forte 	if (!dfc->buf3 || !dfc->buf3_size) {
4809*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4810*fcf3ce44SJohn Forte 		    "%s: Null buffer3 found.",
4811*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4812*fcf3ce44SJohn Forte 
4813*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
4814*fcf3ce44SJohn Forte 		goto done;
4815*fcf3ce44SJohn Forte 	}
4816*fcf3ce44SJohn Forte 	if (dfc->buf3_size < sizeof (uint32_t)) {
4817*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4818*fcf3ce44SJohn Forte 		    "%s: Buffer3 too small. %d < %d",
4819*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size,
4820*fcf3ce44SJohn Forte 		    sizeof (uint32_t));
4821*fcf3ce44SJohn Forte 
4822*fcf3ce44SJohn Forte 		rval = DFC_ARG_TOOSMALL;
4823*fcf3ce44SJohn Forte 		goto done;
4824*fcf3ce44SJohn Forte 	}
4825*fcf3ce44SJohn Forte 	/* Read the command code first */
4826*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)cmd_buf, (void *)&cmd_code,
4827*fcf3ce44SJohn Forte 	    sizeof (uint32_t), mode) != 0) {
4828*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4829*fcf3ce44SJohn Forte 		    "%s: Unable to read command code.",
4830*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
4831*fcf3ce44SJohn Forte 
4832*fcf3ce44SJohn Forte 		rval = DFC_COPYIN_ERROR;
4833*fcf3ce44SJohn Forte 		goto done;
4834*fcf3ce44SJohn Forte 	}
4835*fcf3ce44SJohn Forte 	cmd_code = SWAP_LONG(cmd_code);
4836*fcf3ce44SJohn Forte 
4837*fcf3ce44SJohn Forte 	/* Look for Zephyr specific commands */
4838*fcf3ce44SJohn Forte 	if (cmd_code & 0x80000000) {
4839*fcf3ce44SJohn Forte 		bzero((uint8_t *)&reset_cmd, sizeof (menlo_reset_cmd_t));
4840*fcf3ce44SJohn Forte 		bzero((uint8_t *)&set_cmd, sizeof (menlo_set_cmd_t));
4841*fcf3ce44SJohn Forte 		bzero((uint8_t *)&rsp_code, sizeof (uint32_t));
4842*fcf3ce44SJohn Forte 
4843*fcf3ce44SJohn Forte 		/* Validate response buffer */
4844*fcf3ce44SJohn Forte 		if (rsp_size < sizeof (uint32_t)) {
4845*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4846*fcf3ce44SJohn Forte 			    "%s: Response overrun.",
4847*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
4848*fcf3ce44SJohn Forte 			rval = DFC_RSP_BUF_OVERRUN;
4849*fcf3ce44SJohn Forte 			goto done;
4850*fcf3ce44SJohn Forte 		}
4851*fcf3ce44SJohn Forte 		/* All of these responses will be 4 bytes only */
4852*fcf3ce44SJohn Forte 		rsp_size = sizeof (uint32_t);
4853*fcf3ce44SJohn Forte 		rsp_code = 0;
4854*fcf3ce44SJohn Forte 
4855*fcf3ce44SJohn Forte 		/* Validate command buffer */
4856*fcf3ce44SJohn Forte 		switch (cmd_code) {
4857*fcf3ce44SJohn Forte 		case MENLO_CMD_RESET:
4858*fcf3ce44SJohn Forte 			if (cmd_size < sizeof (menlo_reset_cmd_t)) {
4859*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4860*fcf3ce44SJohn Forte 				    "%s: Invalid command size. %d < %d",
4861*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd), cmd_size,
4862*fcf3ce44SJohn Forte 				    sizeof (menlo_reset_cmd_t));
4863*fcf3ce44SJohn Forte 				rval = DFC_ARG_INVALID;
4864*fcf3ce44SJohn Forte 				goto done;
4865*fcf3ce44SJohn Forte 			}
4866*fcf3ce44SJohn Forte 			cmd_size = sizeof (menlo_reset_cmd_t);
4867*fcf3ce44SJohn Forte 
4868*fcf3ce44SJohn Forte 			/* Read the command buffer */
4869*fcf3ce44SJohn Forte 			if (ddi_copyin((void *)cmd_buf, (void *)&reset_cmd,
4870*fcf3ce44SJohn Forte 			    cmd_size, mode) != 0) {
4871*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4872*fcf3ce44SJohn Forte 				    "%s: Unable to read command buffer.",
4873*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
4874*fcf3ce44SJohn Forte 
4875*fcf3ce44SJohn Forte 				rval = DFC_COPYIN_ERROR;
4876*fcf3ce44SJohn Forte 				goto done;
4877*fcf3ce44SJohn Forte 			}
4878*fcf3ce44SJohn Forte 			if (reset_cmd.firmware) {
4879*fcf3ce44SJohn Forte 				/* MENLO_FW_GOLDEN */
4880*fcf3ce44SJohn Forte 				value = 1;
4881*fcf3ce44SJohn Forte 
4882*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4883*fcf3ce44SJohn Forte 				    "%s: Reset with Golden"
4884*fcf3ce44SJohn Forte 				    " firmware requested.",
4885*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
4886*fcf3ce44SJohn Forte 
4887*fcf3ce44SJohn Forte 			} else {
4888*fcf3ce44SJohn Forte 				/* MENLO_FW_OPERATIONAL */
4889*fcf3ce44SJohn Forte 				value = 0;
4890*fcf3ce44SJohn Forte 
4891*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4892*fcf3ce44SJohn Forte 				    "%s: Reset with Operational"
4893*fcf3ce44SJohn Forte 				    " firmware requested.",
4894*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
4895*fcf3ce44SJohn Forte 			}
4896*fcf3ce44SJohn Forte 
4897*fcf3ce44SJohn Forte 			addr = 0x103007;
4898*fcf3ce44SJohn Forte 
4899*fcf3ce44SJohn Forte 			break;
4900*fcf3ce44SJohn Forte 
4901*fcf3ce44SJohn Forte 		case MENLO_CMD_SET_MODE:
4902*fcf3ce44SJohn Forte 			if (cmd_size < sizeof (menlo_set_cmd_t)) {
4903*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4904*fcf3ce44SJohn Forte 				    "%s: Invalid command size. %d < %d",
4905*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd), cmd_size,
4906*fcf3ce44SJohn Forte 				    sizeof (menlo_set_cmd_t));
4907*fcf3ce44SJohn Forte 				rval = DFC_ARG_INVALID;
4908*fcf3ce44SJohn Forte 				goto done;
4909*fcf3ce44SJohn Forte 			}
4910*fcf3ce44SJohn Forte 			cmd_size = sizeof (menlo_set_cmd_t);
4911*fcf3ce44SJohn Forte 
4912*fcf3ce44SJohn Forte 			/* Read the command buffer */
4913*fcf3ce44SJohn Forte 			if (ddi_copyin((void *)cmd_buf, (void *)&set_cmd,
4914*fcf3ce44SJohn Forte 			    cmd_size, mode) != 0) {
4915*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4916*fcf3ce44SJohn Forte 				    "%s: Unable to read command buffer.",
4917*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
4918*fcf3ce44SJohn Forte 
4919*fcf3ce44SJohn Forte 				rval = DFC_COPYIN_ERROR;
4920*fcf3ce44SJohn Forte 				goto done;
4921*fcf3ce44SJohn Forte 			}
4922*fcf3ce44SJohn Forte 			if (set_cmd.value1) {
4923*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4924*fcf3ce44SJohn Forte 				    "%s: Maintenance mode"
4925*fcf3ce44SJohn Forte 				    " enable requested.",
4926*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
4927*fcf3ce44SJohn Forte 
4928*fcf3ce44SJohn Forte 				/* Make sure the mode flag is cleared */
4929*fcf3ce44SJohn Forte 				if (hba->flag & FC_MENLO_MODE) {
4930*fcf3ce44SJohn Forte 					mutex_enter(&EMLXS_PORT_LOCK);
4931*fcf3ce44SJohn Forte 					hba->flag &= ~FC_MENLO_MODE;
4932*fcf3ce44SJohn Forte 					mutex_exit(&EMLXS_PORT_LOCK);
4933*fcf3ce44SJohn Forte 				}
4934*fcf3ce44SJohn Forte 				mm_mode = 1;
4935*fcf3ce44SJohn Forte 			} else {
4936*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4937*fcf3ce44SJohn Forte 				    "%s: Maintenance mode"
4938*fcf3ce44SJohn Forte 				    " disable requested.",
4939*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
4940*fcf3ce44SJohn Forte 			}
4941*fcf3ce44SJohn Forte 
4942*fcf3ce44SJohn Forte 			addr = 0x103107;
4943*fcf3ce44SJohn Forte 			value = mm_mode;
4944*fcf3ce44SJohn Forte 
4945*fcf3ce44SJohn Forte 			break;
4946*fcf3ce44SJohn Forte 
4947*fcf3ce44SJohn Forte 		default:
4948*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4949*fcf3ce44SJohn Forte 			    "%s: Invalid command. cmd=%x",
4950*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), cmd_code);
4951*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
4952*fcf3ce44SJohn Forte 			goto done;
4953*fcf3ce44SJohn Forte 		}
4954*fcf3ce44SJohn Forte 
4955*fcf3ce44SJohn Forte 		if ((mbq = (MAILBOXQ *)
4956*fcf3ce44SJohn Forte 		    kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP)) == 0) {
4957*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4958*fcf3ce44SJohn Forte 			    "%s: Unable to allocate mailbox buffer.",
4959*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
4960*fcf3ce44SJohn Forte 
4961*fcf3ce44SJohn Forte 			rval = DFC_SYSRES_ERROR;
4962*fcf3ce44SJohn Forte 			goto done;
4963*fcf3ce44SJohn Forte 		}
4964*fcf3ce44SJohn Forte 		mb = (MAILBOX *)mbq;
4965*fcf3ce44SJohn Forte 
4966*fcf3ce44SJohn Forte 		/* Create the set_variable mailbox request */
4967*fcf3ce44SJohn Forte 		emlxs_mb_set_var(hba, mb, addr, value);
4968*fcf3ce44SJohn Forte 
4969*fcf3ce44SJohn Forte 		mbq->flag |= MBQ_PASSTHRU;
4970*fcf3ce44SJohn Forte 
4971*fcf3ce44SJohn Forte 		/* issue the mbox cmd to the sli */
4972*fcf3ce44SJohn Forte 		mbxstatus = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
4973*fcf3ce44SJohn Forte 
4974*fcf3ce44SJohn Forte 		if (mbxstatus) {
4975*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4976*fcf3ce44SJohn Forte 			    "%s: %s failed. mbxstatus=0x%x",
4977*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
4978*fcf3ce44SJohn Forte 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
4979*fcf3ce44SJohn Forte 			    mbxstatus);
4980*fcf3ce44SJohn Forte 
4981*fcf3ce44SJohn Forte 			if (mbxstatus == MBX_TIMEOUT) {
4982*fcf3ce44SJohn Forte 				rval = DFC_TIMEOUT;
4983*fcf3ce44SJohn Forte 			} else {
4984*fcf3ce44SJohn Forte 				rval = DFC_IO_ERROR;
4985*fcf3ce44SJohn Forte 			}
4986*fcf3ce44SJohn Forte 			goto done;
4987*fcf3ce44SJohn Forte 		}
4988*fcf3ce44SJohn Forte 		if (ddi_copyout((void *)&rsp_code, (void *)rsp_buf,
4989*fcf3ce44SJohn Forte 		    rsp_size, mode) != 0) {
4990*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4991*fcf3ce44SJohn Forte 			    "%s: Unable to write response.",
4992*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
4993*fcf3ce44SJohn Forte 
4994*fcf3ce44SJohn Forte 			rval = DFC_COPYOUT_ERROR;
4995*fcf3ce44SJohn Forte 			goto done;
4996*fcf3ce44SJohn Forte 		}
4997*fcf3ce44SJohn Forte 		if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf3,
4998*fcf3ce44SJohn Forte 		    dfc->buf3_size, mode) != 0) {
4999*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5000*fcf3ce44SJohn Forte 			    "%s: Unable to write response size.",
5001*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
5002*fcf3ce44SJohn Forte 
5003*fcf3ce44SJohn Forte 			rval = DFC_COPYOUT_ERROR;
5004*fcf3ce44SJohn Forte 			goto done;
5005*fcf3ce44SJohn Forte 		}
5006*fcf3ce44SJohn Forte 		/* Check if we need to wait for maintenance mode */
5007*fcf3ce44SJohn Forte 		if (mm_mode && !(hba->flag & FC_MENLO_MODE)) {
5008*fcf3ce44SJohn Forte 			/* Wait for link to come up in maintenance mode */
5009*fcf3ce44SJohn Forte 			mutex_enter(&EMLXS_LINKUP_LOCK);
5010*fcf3ce44SJohn Forte 
5011*fcf3ce44SJohn Forte 			timeout = emlxs_timeout(hba, 30);
5012*fcf3ce44SJohn Forte 
5013*fcf3ce44SJohn Forte 			rval = 0;
5014*fcf3ce44SJohn Forte 			while ((rval != -1) && !(hba->flag & FC_MENLO_MODE)) {
5015*fcf3ce44SJohn Forte 				rval = cv_timedwait(&EMLXS_LINKUP_CV,
5016*fcf3ce44SJohn Forte 				    &EMLXS_LINKUP_LOCK, timeout);
5017*fcf3ce44SJohn Forte 			}
5018*fcf3ce44SJohn Forte 
5019*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_LINKUP_LOCK);
5020*fcf3ce44SJohn Forte 
5021*fcf3ce44SJohn Forte 			if (rval == -1) {
5022*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5023*fcf3ce44SJohn Forte 				    "%s: Menlo maintenance mode"
5024*fcf3ce44SJohn Forte 				    " error. Timeout.",
5025*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
5026*fcf3ce44SJohn Forte 
5027*fcf3ce44SJohn Forte 				rval = DFC_TIMEOUT;
5028*fcf3ce44SJohn Forte 				goto done;
5029*fcf3ce44SJohn Forte 			}
5030*fcf3ce44SJohn Forte 		}
5031*fcf3ce44SJohn Forte 	} else {	/* Standard commands */
5032*fcf3ce44SJohn Forte 		if (hba->state <= FC_LINK_DOWN) {
5033*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5034*fcf3ce44SJohn Forte 			    "%s: Adapter link down.",
5035*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
5036*fcf3ce44SJohn Forte 
5037*fcf3ce44SJohn Forte 			rval = DFC_LINKDOWN_ERROR;
5038*fcf3ce44SJohn Forte 			goto done;
5039*fcf3ce44SJohn Forte 		}
5040*fcf3ce44SJohn Forte 		if (cmd_code == MENLO_CMD_FW_DOWNLOAD) {
5041*fcf3ce44SJohn Forte 			/* Check cmd size */
5042*fcf3ce44SJohn Forte 			/*
5043*fcf3ce44SJohn Forte 			 * Must be at least 12 bytes of command plus 4 bytes
5044*fcf3ce44SJohn Forte 			 * of data
5045*fcf3ce44SJohn Forte 			 */
5046*fcf3ce44SJohn Forte 			if (cmd_size < (12 + 4)) {
5047*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5048*fcf3ce44SJohn Forte 				    "%s: Invalid command size. %d < %d",
5049*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd), cmd_size,
5050*fcf3ce44SJohn Forte 				    (12 + 4));
5051*fcf3ce44SJohn Forte 
5052*fcf3ce44SJohn Forte 				rval = DFC_ARG_INVALID;
5053*fcf3ce44SJohn Forte 				goto done;
5054*fcf3ce44SJohn Forte 			}
5055*fcf3ce44SJohn Forte 			/* Extract data buffer from command buffer */
5056*fcf3ce44SJohn Forte 			data_buf = cmd_buf + 12;
5057*fcf3ce44SJohn Forte 			data_size = cmd_size - 12;
5058*fcf3ce44SJohn Forte 			cmd_size = 12;
5059*fcf3ce44SJohn Forte 		}
5060*fcf3ce44SJohn Forte 		if (!(pkt = emlxs_pkt_alloc(port, cmd_size,
5061*fcf3ce44SJohn Forte 		    rsp_size, 0, KM_NOSLEEP))) {
5062*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5063*fcf3ce44SJohn Forte 			    "%s: Unable to allocate packet.",
5064*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
5065*fcf3ce44SJohn Forte 
5066*fcf3ce44SJohn Forte 			rval = DFC_SYSRES_ERROR;
5067*fcf3ce44SJohn Forte 			goto done;
5068*fcf3ce44SJohn Forte 		}
5069*fcf3ce44SJohn Forte 		/* Make this a polled IO */
5070*fcf3ce44SJohn Forte 		pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5071*fcf3ce44SJohn Forte 		pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5072*fcf3ce44SJohn Forte 		pkt->pkt_comp = NULL;
5073*fcf3ce44SJohn Forte 		pkt->pkt_tran_type = FC_PKT_EXCHANGE;
5074*fcf3ce44SJohn Forte 		pkt->pkt_timeout = 30;
5075*fcf3ce44SJohn Forte 
5076*fcf3ce44SJohn Forte 		/* Build the fc header */
5077*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(EMLXS_MENLO_DID);
5078*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
5079*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
5080*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
5081*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
5082*fcf3ce44SJohn Forte 		    F_CTL_SEQ_INITIATIVE;
5083*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.seq_id = 0;
5084*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.df_ctl = 0;
5085*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
5086*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5087*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
5088*fcf3ce44SJohn Forte 		pkt->pkt_cmd_fhdr.ro = 0;
5089*fcf3ce44SJohn Forte 
5090*fcf3ce44SJohn Forte 		/* Copy in the command buffer */
5091*fcf3ce44SJohn Forte 		if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd,
5092*fcf3ce44SJohn Forte 		    cmd_size, mode) != 0) {
5093*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5094*fcf3ce44SJohn Forte 			    "%s: Unable to read command buffer.",
5095*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
5096*fcf3ce44SJohn Forte 
5097*fcf3ce44SJohn Forte 			rval = DFC_COPYIN_ERROR;
5098*fcf3ce44SJohn Forte 			goto done;
5099*fcf3ce44SJohn Forte 		}
5100*fcf3ce44SJohn Forte 		if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5101*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5102*fcf3ce44SJohn Forte 			    "%s: Unable to send packet.",
5103*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
5104*fcf3ce44SJohn Forte 
5105*fcf3ce44SJohn Forte 			rval = DFC_IO_ERROR;
5106*fcf3ce44SJohn Forte 			goto done;
5107*fcf3ce44SJohn Forte 		}
5108*fcf3ce44SJohn Forte 		if (pkt->pkt_state != FC_PKT_SUCCESS) {
5109*fcf3ce44SJohn Forte 			if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5110*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5111*fcf3ce44SJohn Forte 				    "%s: Pkt Transport error. Pkt Timeout.",
5112*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
5113*fcf3ce44SJohn Forte 				rval = DFC_TIMEOUT;
5114*fcf3ce44SJohn Forte 			} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
5115*fcf3ce44SJohn Forte 			    (pkt->pkt_reason == FC_REASON_OVERRUN)) {
5116*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5117*fcf3ce44SJohn Forte 				    "%s: Pkt Transport error."
5118*fcf3ce44SJohn Forte 				    " Response overrun.",
5119*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
5120*fcf3ce44SJohn Forte 				rval = DFC_RSP_BUF_OVERRUN;
5121*fcf3ce44SJohn Forte 			} else {
5122*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5123*fcf3ce44SJohn Forte 				    "%s: Pkt Transport error. state=%x",
5124*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd),
5125*fcf3ce44SJohn Forte 				    pkt->pkt_state);
5126*fcf3ce44SJohn Forte 				rval = DFC_IO_ERROR;
5127*fcf3ce44SJohn Forte 			}
5128*fcf3ce44SJohn Forte 			goto done;
5129*fcf3ce44SJohn Forte 		}
5130*fcf3ce44SJohn Forte 		if (cmd_code == MENLO_CMD_FW_DOWNLOAD) {
5131*fcf3ce44SJohn Forte 			uint32_t *rsp;
5132*fcf3ce44SJohn Forte 
5133*fcf3ce44SJohn Forte 			/* Check response code */
5134*fcf3ce44SJohn Forte 			rsp = (uint32_t *)pkt->pkt_resp;
5135*fcf3ce44SJohn Forte 			rsp_code = *rsp;
5136*fcf3ce44SJohn Forte 			rsp_code = SWAP_LONG(rsp_code);
5137*fcf3ce44SJohn Forte 
5138*fcf3ce44SJohn Forte 			if (rsp_code == MENLO_RSP_SUCCESS) {
5139*fcf3ce44SJohn Forte 				/* Now transmit the data phase */
5140*fcf3ce44SJohn Forte 
5141*fcf3ce44SJohn Forte 				/* Save last rx_id */
5142*fcf3ce44SJohn Forte 				uint32_t rx_id = pkt->pkt_cmd_fhdr.rx_id;
5143*fcf3ce44SJohn Forte 
5144*fcf3ce44SJohn Forte 				/* Free old pkt */
5145*fcf3ce44SJohn Forte 				emlxs_pkt_free(pkt);
5146*fcf3ce44SJohn Forte 
5147*fcf3ce44SJohn Forte 				/* Allocate data pkt */
5148*fcf3ce44SJohn Forte 				if (!(pkt = emlxs_pkt_alloc(port, data_size,
5149*fcf3ce44SJohn Forte 				    rsp_size, 0, KM_NOSLEEP))) {
5150*fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
5151*fcf3ce44SJohn Forte 					    &emlxs_dfc_error_msg,
5152*fcf3ce44SJohn Forte 					    "%s: Unable to allocate"
5153*fcf3ce44SJohn Forte 					    " data packet.",
5154*fcf3ce44SJohn Forte 					    emlxs_dfc_xlate(dfc->cmd));
5155*fcf3ce44SJohn Forte 
5156*fcf3ce44SJohn Forte 					rval = DFC_SYSRES_ERROR;
5157*fcf3ce44SJohn Forte 					goto done;
5158*fcf3ce44SJohn Forte 				}
5159*fcf3ce44SJohn Forte 				/* Make this a polled IO */
5160*fcf3ce44SJohn Forte 				pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5161*fcf3ce44SJohn Forte 				pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5162*fcf3ce44SJohn Forte 				pkt->pkt_comp = NULL;
5163*fcf3ce44SJohn Forte 				pkt->pkt_tran_type = FC_PKT_OUTBOUND;
5164*fcf3ce44SJohn Forte 				pkt->pkt_timeout = 30;
5165*fcf3ce44SJohn Forte 
5166*fcf3ce44SJohn Forte 				/* Build the fc header */
5167*fcf3ce44SJohn Forte 				pkt->pkt_cmd_fhdr.d_id =
5168*fcf3ce44SJohn Forte 				    SWAP_DATA24_LO(EMLXS_MENLO_DID);
5169*fcf3ce44SJohn Forte 				pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
5170*fcf3ce44SJohn Forte 				pkt->pkt_cmd_fhdr.s_id =
5171*fcf3ce44SJohn Forte 				    SWAP_DATA24_LO(port->did);
5172*fcf3ce44SJohn Forte 				pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
5173*fcf3ce44SJohn Forte 				pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ |
5174*fcf3ce44SJohn Forte 				    F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
5175*fcf3ce44SJohn Forte 				pkt->pkt_cmd_fhdr.seq_id = 0;
5176*fcf3ce44SJohn Forte 				pkt->pkt_cmd_fhdr.df_ctl = 0;
5177*fcf3ce44SJohn Forte 				pkt->pkt_cmd_fhdr.seq_cnt = 0;
5178*fcf3ce44SJohn Forte 				pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5179*fcf3ce44SJohn Forte 				pkt->pkt_cmd_fhdr.rx_id = rx_id;
5180*fcf3ce44SJohn Forte 				pkt->pkt_cmd_fhdr.ro = 0;
5181*fcf3ce44SJohn Forte 
5182*fcf3ce44SJohn Forte 				/* Copy in the data buffer */
5183*fcf3ce44SJohn Forte 				if (ddi_copyin((void *)data_buf,
5184*fcf3ce44SJohn Forte 				    (void *)pkt->pkt_cmd, data_size,
5185*fcf3ce44SJohn Forte 				    mode) != 0) {
5186*fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
5187*fcf3ce44SJohn Forte 					    &emlxs_dfc_error_msg,
5188*fcf3ce44SJohn Forte 					    "%s: Unable to read data buffer.",
5189*fcf3ce44SJohn Forte 					    emlxs_dfc_xlate(dfc->cmd));
5190*fcf3ce44SJohn Forte 
5191*fcf3ce44SJohn Forte 					rval = DFC_COPYIN_ERROR;
5192*fcf3ce44SJohn Forte 					goto done;
5193*fcf3ce44SJohn Forte 				}
5194*fcf3ce44SJohn Forte 				if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5195*fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
5196*fcf3ce44SJohn Forte 					    &emlxs_dfc_error_msg,
5197*fcf3ce44SJohn Forte 					    "%s: Unable to send data packet.",
5198*fcf3ce44SJohn Forte 					    emlxs_dfc_xlate(dfc->cmd));
5199*fcf3ce44SJohn Forte 
5200*fcf3ce44SJohn Forte 					rval = DFC_IO_ERROR;
5201*fcf3ce44SJohn Forte 					goto done;
5202*fcf3ce44SJohn Forte 				}
5203*fcf3ce44SJohn Forte 				if (pkt->pkt_state != FC_PKT_SUCCESS) {
5204*fcf3ce44SJohn Forte 					if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5205*fcf3ce44SJohn Forte 						EMLXS_MSGF(EMLXS_CONTEXT,
5206*fcf3ce44SJohn Forte 						    &emlxs_dfc_error_msg,
5207*fcf3ce44SJohn Forte 						    "%s: Data Pkt Transport"
5208*fcf3ce44SJohn Forte 						    " error. Pkt Timeout.",
5209*fcf3ce44SJohn Forte 						    emlxs_dfc_xlate(dfc->cmd));
5210*fcf3ce44SJohn Forte 						rval = DFC_TIMEOUT;
5211*fcf3ce44SJohn Forte 					} else if ((pkt->pkt_state ==
5212*fcf3ce44SJohn Forte 					    FC_PKT_LOCAL_RJT) &&
5213*fcf3ce44SJohn Forte 					    (pkt->pkt_reason ==
5214*fcf3ce44SJohn Forte 					    FC_REASON_OVERRUN)) {
5215*fcf3ce44SJohn Forte 						EMLXS_MSGF(EMLXS_CONTEXT,
5216*fcf3ce44SJohn Forte 						    &emlxs_dfc_error_msg,
5217*fcf3ce44SJohn Forte 						    "%s: Data Pkt Transport "
5218*fcf3ce44SJohn Forte 						    "error. Response overrun.",
5219*fcf3ce44SJohn Forte 						    emlxs_dfc_xlate(dfc->cmd));
5220*fcf3ce44SJohn Forte 						rval = DFC_RSP_BUF_OVERRUN;
5221*fcf3ce44SJohn Forte 					} else {
5222*fcf3ce44SJohn Forte 						EMLXS_MSGF(EMLXS_CONTEXT,
5223*fcf3ce44SJohn Forte 						    &emlxs_dfc_error_msg,
5224*fcf3ce44SJohn Forte 						    "%s: Data Pkt Transport "
5225*fcf3ce44SJohn Forte 						    "error. state=%x",
5226*fcf3ce44SJohn Forte 						    emlxs_dfc_xlate(dfc->cmd),
5227*fcf3ce44SJohn Forte 						    pkt->pkt_state);
5228*fcf3ce44SJohn Forte 						rval = DFC_IO_ERROR;
5229*fcf3ce44SJohn Forte 					}
5230*fcf3ce44SJohn Forte 					goto done;
5231*fcf3ce44SJohn Forte 				}
5232*fcf3ce44SJohn Forte 			}
5233*fcf3ce44SJohn Forte 		}
5234*fcf3ce44SJohn Forte 		if (ddi_copyout((void *)pkt->pkt_resp, (void *)rsp_buf,
5235*fcf3ce44SJohn Forte 		    rsp_size, mode) != 0) {
5236*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5237*fcf3ce44SJohn Forte 			    "%s: Unable to write response.",
5238*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
5239*fcf3ce44SJohn Forte 
5240*fcf3ce44SJohn Forte 			rval = DFC_COPYOUT_ERROR;
5241*fcf3ce44SJohn Forte 			goto done;
5242*fcf3ce44SJohn Forte 		}
5243*fcf3ce44SJohn Forte 		rsp_size -= pkt->pkt_resp_resid;
5244*fcf3ce44SJohn Forte 		if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf3,
5245*fcf3ce44SJohn Forte 		    dfc->buf3_size, mode) != 0) {
5246*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5247*fcf3ce44SJohn Forte 			    "%s: Unable to write response size.",
5248*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
5249*fcf3ce44SJohn Forte 
5250*fcf3ce44SJohn Forte 			rval = DFC_COPYOUT_ERROR;
5251*fcf3ce44SJohn Forte 			goto done;
5252*fcf3ce44SJohn Forte 		}
5253*fcf3ce44SJohn Forte 	}
5254*fcf3ce44SJohn Forte 
5255*fcf3ce44SJohn Forte 	rval = 0;
5256*fcf3ce44SJohn Forte 
5257*fcf3ce44SJohn Forte done:
5258*fcf3ce44SJohn Forte 
5259*fcf3ce44SJohn Forte 	if (pkt) {
5260*fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
5261*fcf3ce44SJohn Forte 	}
5262*fcf3ce44SJohn Forte 	if (mbq) {
5263*fcf3ce44SJohn Forte 		kmem_free(mbq, sizeof (MAILBOXQ));
5264*fcf3ce44SJohn Forte 	}
5265*fcf3ce44SJohn Forte 	return (rval);
5266*fcf3ce44SJohn Forte 
5267*fcf3ce44SJohn Forte } /* emlxs_dfc_send_menlo() */
5268*fcf3ce44SJohn Forte 
5269*fcf3ce44SJohn Forte 
5270*fcf3ce44SJohn Forte 
5271*fcf3ce44SJohn Forte extern void
5272*fcf3ce44SJohn Forte emlxs_fcoe_attention_thread(void *arg)
5273*fcf3ce44SJohn Forte {
5274*fcf3ce44SJohn Forte 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
5275*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5276*fcf3ce44SJohn Forte 	menlo_init_rsp_t *rsp;
5277*fcf3ce44SJohn Forte 	menlo_get_cmd_t *cmd;
5278*fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
5279*fcf3ce44SJohn Forte 
5280*fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_get_cmd_t),
5281*fcf3ce44SJohn Forte 	    sizeof (menlo_init_rsp_t), 0, KM_NOSLEEP))) {
5282*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5283*fcf3ce44SJohn Forte 		    "FCoE attention: Unable to allocate packet.");
5284*fcf3ce44SJohn Forte 
5285*fcf3ce44SJohn Forte 		return;
5286*fcf3ce44SJohn Forte 	}
5287*fcf3ce44SJohn Forte 	/* Make this a polled IO */
5288*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5289*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5290*fcf3ce44SJohn Forte 	pkt->pkt_comp = NULL;
5291*fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
5292*fcf3ce44SJohn Forte 	pkt->pkt_timeout = 30;
5293*fcf3ce44SJohn Forte 
5294*fcf3ce44SJohn Forte 	/* Build the fc header */
5295*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(EMLXS_MENLO_DID);
5296*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
5297*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
5298*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
5299*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
5300*fcf3ce44SJohn Forte 	    F_CTL_SEQ_INITIATIVE;
5301*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
5302*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
5303*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
5304*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5305*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
5306*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
5307*fcf3ce44SJohn Forte 
5308*fcf3ce44SJohn Forte 	cmd = (menlo_get_cmd_t *)pkt->pkt_cmd;
5309*fcf3ce44SJohn Forte 	cmd->code = MENLO_CMD_GET_INIT;
5310*fcf3ce44SJohn Forte 	cmd->context = 0;
5311*fcf3ce44SJohn Forte 	cmd->length = sizeof (menlo_init_rsp_t);
5312*fcf3ce44SJohn Forte 
5313*fcf3ce44SJohn Forte 	/* Little Endian Swap */
5314*fcf3ce44SJohn Forte 	cmd->code = SWAP_LONG(cmd->code);
5315*fcf3ce44SJohn Forte 	cmd->length = SWAP_LONG(cmd->length);
5316*fcf3ce44SJohn Forte 
5317*fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5318*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5319*fcf3ce44SJohn Forte 		    "FCoE attention: Unable to send packet.");
5320*fcf3ce44SJohn Forte 
5321*fcf3ce44SJohn Forte 		goto done;
5322*fcf3ce44SJohn Forte 	}
5323*fcf3ce44SJohn Forte 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
5324*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5325*fcf3ce44SJohn Forte 		    "FCoE attention: Pkt Transport error. state=%x",
5326*fcf3ce44SJohn Forte 		    pkt->pkt_state);
5327*fcf3ce44SJohn Forte 
5328*fcf3ce44SJohn Forte 		goto done;
5329*fcf3ce44SJohn Forte 	}
5330*fcf3ce44SJohn Forte 	/* Check response code */
5331*fcf3ce44SJohn Forte 	rsp = (menlo_init_rsp_t *)pkt->pkt_resp;
5332*fcf3ce44SJohn Forte 	rsp->code = SWAP_LONG(rsp->code);
5333*fcf3ce44SJohn Forte 
5334*fcf3ce44SJohn Forte 	if (rsp->code != MENLO_RSP_SUCCESS) {
5335*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5336*fcf3ce44SJohn Forte 		    "FCoE attention: FCOE Response error =%x",
5337*fcf3ce44SJohn Forte 		    rsp->code);
5338*fcf3ce44SJohn Forte 
5339*fcf3ce44SJohn Forte 		goto done;
5340*fcf3ce44SJohn Forte 	}
5341*fcf3ce44SJohn Forte 	/* Little Endian Swap */
5342*fcf3ce44SJohn Forte 	rsp->bb_credit = SWAP_LONG(rsp->bb_credit);
5343*fcf3ce44SJohn Forte 	rsp->frame_size = SWAP_LONG(rsp->frame_size);
5344*fcf3ce44SJohn Forte 	rsp->fw_version = SWAP_LONG(rsp->fw_version);
5345*fcf3ce44SJohn Forte 	rsp->reset_status = SWAP_LONG(rsp->reset_status);
5346*fcf3ce44SJohn Forte 	rsp->maint_status = SWAP_LONG(rsp->maint_status);
5347*fcf3ce44SJohn Forte 	rsp->fw_type = SWAP_LONG(rsp->fw_type);
5348*fcf3ce44SJohn Forte 	rsp->fru_data_valid = SWAP_LONG(rsp->fru_data_valid);
5349*fcf3ce44SJohn Forte 
5350*fcf3ce44SJohn Forte 	/* Log the event */
5351*fcf3ce44SJohn Forte 	emlxs_log_fcoe_event(port, rsp);
5352*fcf3ce44SJohn Forte 
5353*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5354*fcf3ce44SJohn Forte 	    "MENLO_INIT: bb_credit      = 0x%x", rsp->bb_credit);
5355*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5356*fcf3ce44SJohn Forte 	    "MENLO_INIT: frame_size     = 0x%x", rsp->frame_size);
5357*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5358*fcf3ce44SJohn Forte 	    "MENLO_INIT: fw_version     = 0x%x", rsp->fw_version);
5359*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5360*fcf3ce44SJohn Forte 	    "MENLO_INIT: reset_status   = 0x%x", rsp->reset_status);
5361*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5362*fcf3ce44SJohn Forte 	    "MENLO_INIT: maint_status   = 0x%x", rsp->maint_status);
5363*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5364*fcf3ce44SJohn Forte 	    "MENLO_INIT: fw_type        = 0x%x", rsp->fw_type);
5365*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5366*fcf3ce44SJohn Forte 	    "MENLO_INIT: fru_data_valid = 0x%x", rsp->fru_data_valid);
5367*fcf3ce44SJohn Forte 
5368*fcf3ce44SJohn Forte 	/* Perform attention checks */
5369*fcf3ce44SJohn Forte 	if (rsp->fru_data_valid == 0) {
5370*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_error_msg,
5371*fcf3ce44SJohn Forte 		    "Invalid FRU data found on adapter."
5372*fcf3ce44SJohn Forte 		    " Return adapter to Emulex for repair.");
5373*fcf3ce44SJohn Forte 	}
5374*fcf3ce44SJohn Forte 	switch (rsp->fw_type) {
5375*fcf3ce44SJohn Forte 	case MENLO_FW_TYPE_GOLDEN:
5376*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_warning_msg,
5377*fcf3ce44SJohn Forte 		    "FCoE chip is running Golden firmware."
5378*fcf3ce44SJohn Forte 		    " Update FCoE firmware immediately.");
5379*fcf3ce44SJohn Forte 		break;
5380*fcf3ce44SJohn Forte 
5381*fcf3ce44SJohn Forte 	case MENLO_FW_TYPE_DIAG:
5382*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_notice_msg,
5383*fcf3ce44SJohn Forte 		    "FCoE chip is running Diagnostic firmware."
5384*fcf3ce44SJohn Forte 		    " Operational use of the adapter is suspended.");
5385*fcf3ce44SJohn Forte 		break;
5386*fcf3ce44SJohn Forte 	}
5387*fcf3ce44SJohn Forte 
5388*fcf3ce44SJohn Forte done:
5389*fcf3ce44SJohn Forte 
5390*fcf3ce44SJohn Forte 	if (pkt) {
5391*fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
5392*fcf3ce44SJohn Forte 	}
5393*fcf3ce44SJohn Forte 	return;
5394*fcf3ce44SJohn Forte 
5395*fcf3ce44SJohn Forte } /* emlxs_fcoe_attention_thread() */
5396*fcf3ce44SJohn Forte 
5397*fcf3ce44SJohn Forte #endif	/* MENLO_SUPPORT */
5398*fcf3ce44SJohn Forte 
5399*fcf3ce44SJohn Forte 
5400*fcf3ce44SJohn Forte static int32_t
5401*fcf3ce44SJohn Forte emlxs_dfc_write_flash(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5402*fcf3ce44SJohn Forte {
5403*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5404*fcf3ce44SJohn Forte 	uint32_t offset;
5405*fcf3ce44SJohn Forte 	uint32_t cnt;
5406*fcf3ce44SJohn Forte 	uint8_t *buffer;
5407*fcf3ce44SJohn Forte 	uint8_t *bptr;
5408*fcf3ce44SJohn Forte 	uint32_t i;
5409*fcf3ce44SJohn Forte 
5410*fcf3ce44SJohn Forte 	if (hba->bus_type != SBUS_FC) {
5411*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5412*fcf3ce44SJohn Forte 		    "%s: Invalid bus_type. (bus_type=%x)",
5413*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), hba->bus_type);
5414*fcf3ce44SJohn Forte 
5415*fcf3ce44SJohn Forte 		return (DFC_ARG_INVALID);
5416*fcf3ce44SJohn Forte 	}
5417*fcf3ce44SJohn Forte 	if (!(hba->flag & FC_OFFLINE_MODE)) {
5418*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5419*fcf3ce44SJohn Forte 		    "%s: Adapter not offline.",
5420*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5421*fcf3ce44SJohn Forte 
5422*fcf3ce44SJohn Forte 		return (DFC_ONLINE_ERROR);
5423*fcf3ce44SJohn Forte 	}
5424*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
5425*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5426*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
5427*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5428*fcf3ce44SJohn Forte 
5429*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
5430*fcf3ce44SJohn Forte 	}
5431*fcf3ce44SJohn Forte 	offset = dfc->data1;
5432*fcf3ce44SJohn Forte 	cnt = dfc->data2;
5433*fcf3ce44SJohn Forte 
5434*fcf3ce44SJohn Forte 	if (offset > (64 * 1024)) {
5435*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5436*fcf3ce44SJohn Forte 		    "%s: Offset too large. (offset=%d)",
5437*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset);
5438*fcf3ce44SJohn Forte 
5439*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
5440*fcf3ce44SJohn Forte 	}
5441*fcf3ce44SJohn Forte 	if (cnt > dfc->buf1_size) {
5442*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5443*fcf3ce44SJohn Forte 		    "%s: Count too large. (count=%d)",
5444*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), cnt);
5445*fcf3ce44SJohn Forte 
5446*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
5447*fcf3ce44SJohn Forte 	}
5448*fcf3ce44SJohn Forte 	if ((cnt + offset) > (64 * 1024)) {
5449*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5450*fcf3ce44SJohn Forte 		    "%s: Count+Offset too large. (count=%d offset=%d)",
5451*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), cnt, offset);
5452*fcf3ce44SJohn Forte 
5453*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
5454*fcf3ce44SJohn Forte 	}
5455*fcf3ce44SJohn Forte 	if (cnt == 0) {
5456*fcf3ce44SJohn Forte 		return (0);
5457*fcf3ce44SJohn Forte 	}
5458*fcf3ce44SJohn Forte 	if ((buffer = (uint8_t *)kmem_zalloc(cnt, KM_NOSLEEP)) == NULL) {
5459*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5460*fcf3ce44SJohn Forte 		    "%s: Unable to allocate buffer.",
5461*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5462*fcf3ce44SJohn Forte 
5463*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
5464*fcf3ce44SJohn Forte 	}
5465*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)buffer,
5466*fcf3ce44SJohn Forte 	    cnt, mode) != 0) {
5467*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5468*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
5469*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5470*fcf3ce44SJohn Forte 
5471*fcf3ce44SJohn Forte 		kmem_free(buffer, cnt);
5472*fcf3ce44SJohn Forte 		return (DFC_COPYIN_ERROR);
5473*fcf3ce44SJohn Forte 	}
5474*fcf3ce44SJohn Forte 	bptr = buffer;
5475*fcf3ce44SJohn Forte 	for (i = 0; i < cnt; i++) {
5476*fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, offset++, (unsigned long)bptr++);
5477*fcf3ce44SJohn Forte 	}
5478*fcf3ce44SJohn Forte 
5479*fcf3ce44SJohn Forte 	kmem_free(buffer, cnt);
5480*fcf3ce44SJohn Forte 
5481*fcf3ce44SJohn Forte 	return (0);
5482*fcf3ce44SJohn Forte 
5483*fcf3ce44SJohn Forte } /* emlxs_dfc_write_flash() */
5484*fcf3ce44SJohn Forte 
5485*fcf3ce44SJohn Forte 
5486*fcf3ce44SJohn Forte static int32_t
5487*fcf3ce44SJohn Forte emlxs_dfc_read_flash(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5488*fcf3ce44SJohn Forte {
5489*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5490*fcf3ce44SJohn Forte 	uint32_t offset;
5491*fcf3ce44SJohn Forte 	uint32_t count;
5492*fcf3ce44SJohn Forte 	uint32_t outsz;
5493*fcf3ce44SJohn Forte 	uint8_t *buffer;
5494*fcf3ce44SJohn Forte 	uint8_t *bptr;
5495*fcf3ce44SJohn Forte 	uint32_t i;
5496*fcf3ce44SJohn Forte 
5497*fcf3ce44SJohn Forte 	if (hba->bus_type != SBUS_FC) {
5498*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5499*fcf3ce44SJohn Forte 		    "%s: Invalid bus_type. (bus_type=%x)",
5500*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), hba->bus_type);
5501*fcf3ce44SJohn Forte 
5502*fcf3ce44SJohn Forte 		return (DFC_ARG_INVALID);
5503*fcf3ce44SJohn Forte 	}
5504*fcf3ce44SJohn Forte 	if (!(hba->flag & FC_OFFLINE_MODE)) {
5505*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5506*fcf3ce44SJohn Forte 		    "%s: Adapter not offline.",
5507*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5508*fcf3ce44SJohn Forte 
5509*fcf3ce44SJohn Forte 		return (DFC_ONLINE_ERROR);
5510*fcf3ce44SJohn Forte 	}
5511*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
5512*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5513*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
5514*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5515*fcf3ce44SJohn Forte 
5516*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
5517*fcf3ce44SJohn Forte 	}
5518*fcf3ce44SJohn Forte 	offset = dfc->data1;
5519*fcf3ce44SJohn Forte 	count = dfc->data2;
5520*fcf3ce44SJohn Forte 	outsz = dfc->buf1_size;
5521*fcf3ce44SJohn Forte 
5522*fcf3ce44SJohn Forte 	if (offset > (64 * 1024)) {
5523*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5524*fcf3ce44SJohn Forte 		    "%s: Offset too large. (offset=%d)",
5525*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset);
5526*fcf3ce44SJohn Forte 
5527*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
5528*fcf3ce44SJohn Forte 	}
5529*fcf3ce44SJohn Forte 	if ((count + offset) > (64 * 1024)) {
5530*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5531*fcf3ce44SJohn Forte 		    "%s: Count+Offset too large. (count = %d offset = %d)",
5532*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), count, offset);
5533*fcf3ce44SJohn Forte 
5534*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
5535*fcf3ce44SJohn Forte 	}
5536*fcf3ce44SJohn Forte 	if (count < outsz) {
5537*fcf3ce44SJohn Forte 		outsz = count;
5538*fcf3ce44SJohn Forte 	}
5539*fcf3ce44SJohn Forte 	if ((buffer = (uint8_t *)kmem_zalloc(outsz, KM_NOSLEEP)) == NULL) {
5540*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5541*fcf3ce44SJohn Forte 		    "%s: Unable to allocate buffer.",
5542*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5543*fcf3ce44SJohn Forte 
5544*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
5545*fcf3ce44SJohn Forte 	}
5546*fcf3ce44SJohn Forte 	bptr = buffer;
5547*fcf3ce44SJohn Forte 	for (i = 0; i < outsz; i++) {
5548*fcf3ce44SJohn Forte 		*bptr++ = SBUS_READ_FLASH_COPY(hba, offset++);
5549*fcf3ce44SJohn Forte 	}
5550*fcf3ce44SJohn Forte 
5551*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)buffer, (void *)dfc->buf1,
5552*fcf3ce44SJohn Forte 	    outsz, mode) != 0) {
5553*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5554*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
5555*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5556*fcf3ce44SJohn Forte 
5557*fcf3ce44SJohn Forte 		kmem_free(buffer, outsz);
5558*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
5559*fcf3ce44SJohn Forte 	}
5560*fcf3ce44SJohn Forte 	kmem_free(buffer, outsz);
5561*fcf3ce44SJohn Forte 
5562*fcf3ce44SJohn Forte 	return (0);
5563*fcf3ce44SJohn Forte 
5564*fcf3ce44SJohn Forte } /* emlxs_dfc_read_flash() */
5565*fcf3ce44SJohn Forte 
5566*fcf3ce44SJohn Forte 
5567*fcf3ce44SJohn Forte static int32_t
5568*fcf3ce44SJohn Forte emlxs_dfc_send_els(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5569*fcf3ce44SJohn Forte {
5570*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5571*fcf3ce44SJohn Forte 	uint8_t *rsp_buf;
5572*fcf3ce44SJohn Forte 	uint8_t *cmd_buf;
5573*fcf3ce44SJohn Forte 	dfc_destid_t destid;
5574*fcf3ce44SJohn Forte 	uint32_t rsp_size;
5575*fcf3ce44SJohn Forte 	uint32_t cmd_size;
5576*fcf3ce44SJohn Forte 	uint32_t timeout;
5577*fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
5578*fcf3ce44SJohn Forte 	NODELIST *ndlp;
5579*fcf3ce44SJohn Forte 	uint32_t did;
5580*fcf3ce44SJohn Forte 	uint32_t rval = 0;
5581*fcf3ce44SJohn Forte 	char buffer[128];
5582*fcf3ce44SJohn Forte 
5583*fcf3ce44SJohn Forte 	cmd_buf = dfc->buf1;
5584*fcf3ce44SJohn Forte 	cmd_size = dfc->buf1_size;
5585*fcf3ce44SJohn Forte 	rsp_buf = dfc->buf2;
5586*fcf3ce44SJohn Forte 	rsp_size = dfc->buf2_size;
5587*fcf3ce44SJohn Forte 
5588*fcf3ce44SJohn Forte 	timeout = 2 * hba->fc_ratov;
5589*fcf3ce44SJohn Forte 
5590*fcf3ce44SJohn Forte 	if (!cmd_size || !cmd_buf) {
5591*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5592*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
5593*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5594*fcf3ce44SJohn Forte 
5595*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
5596*fcf3ce44SJohn Forte 		goto done;
5597*fcf3ce44SJohn Forte 	}
5598*fcf3ce44SJohn Forte 	if (!rsp_buf || !rsp_size) {
5599*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5600*fcf3ce44SJohn Forte 		    "%s: Null buffer2 found.",
5601*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5602*fcf3ce44SJohn Forte 
5603*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
5604*fcf3ce44SJohn Forte 		goto done;
5605*fcf3ce44SJohn Forte 	}
5606*fcf3ce44SJohn Forte 	if (!dfc->buf3 || !dfc->buf3_size) {
5607*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5608*fcf3ce44SJohn Forte 		    "%s: Null buffer3 found.",
5609*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5610*fcf3ce44SJohn Forte 
5611*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
5612*fcf3ce44SJohn Forte 		goto done;
5613*fcf3ce44SJohn Forte 	}
5614*fcf3ce44SJohn Forte 	if (dfc->buf3_size < sizeof (dfc_destid_t)) {
5615*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5616*fcf3ce44SJohn Forte 		    "%s: Buffer3 too small. (size=%d)",
5617*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
5618*fcf3ce44SJohn Forte 
5619*fcf3ce44SJohn Forte 		rval = DFC_ARG_TOOSMALL;
5620*fcf3ce44SJohn Forte 		goto done;
5621*fcf3ce44SJohn Forte 	}
5622*fcf3ce44SJohn Forte 	if (!dfc->buf4 || !dfc->buf4_size) {
5623*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5624*fcf3ce44SJohn Forte 		    "%s: Null buffer4 found.",
5625*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5626*fcf3ce44SJohn Forte 
5627*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
5628*fcf3ce44SJohn Forte 		goto done;
5629*fcf3ce44SJohn Forte 	}
5630*fcf3ce44SJohn Forte 	if (dfc->buf4_size < sizeof (uint32_t)) {
5631*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5632*fcf3ce44SJohn Forte 		    "%s: Buffer4 too small. (size=%d)",
5633*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf4_size);
5634*fcf3ce44SJohn Forte 
5635*fcf3ce44SJohn Forte 		rval = DFC_ARG_TOOSMALL;
5636*fcf3ce44SJohn Forte 		goto done;
5637*fcf3ce44SJohn Forte 	}
5638*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf3, (void *)&destid,
5639*fcf3ce44SJohn Forte 	    sizeof (dfc_destid_t), mode) != 0) {
5640*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5641*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
5642*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5643*fcf3ce44SJohn Forte 
5644*fcf3ce44SJohn Forte 		rval = DFC_COPYIN_ERROR;
5645*fcf3ce44SJohn Forte 		goto done;
5646*fcf3ce44SJohn Forte 	}
5647*fcf3ce44SJohn Forte 	if (destid.idType == 0) {
5648*fcf3ce44SJohn Forte 		if ((ndlp = emlxs_node_find_wwpn(port, destid.wwpn)) == NULL) {
5649*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5650*fcf3ce44SJohn Forte 			    "%s: WWPN does not exists. %s",
5651*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
5652*fcf3ce44SJohn Forte 			    emlxs_wwn_xlate(buffer, destid.wwpn));
5653*fcf3ce44SJohn Forte 
5654*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
5655*fcf3ce44SJohn Forte 			goto done;
5656*fcf3ce44SJohn Forte 		}
5657*fcf3ce44SJohn Forte 		did = ndlp->nlp_DID;
5658*fcf3ce44SJohn Forte 	} else {
5659*fcf3ce44SJohn Forte 		if (emlxs_node_find_did(port, destid.d_id) == NULL) {
5660*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5661*fcf3ce44SJohn Forte 			    "%s: DID does not exist. did=%x",
5662*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), destid.d_id);
5663*fcf3ce44SJohn Forte 
5664*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
5665*fcf3ce44SJohn Forte 			goto done;
5666*fcf3ce44SJohn Forte 		}
5667*fcf3ce44SJohn Forte 		did = destid.d_id;
5668*fcf3ce44SJohn Forte 	}
5669*fcf3ce44SJohn Forte 
5670*fcf3ce44SJohn Forte 	if (did == 0) {
5671*fcf3ce44SJohn Forte 		did = port->did;
5672*fcf3ce44SJohn Forte 	}
5673*fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size, 0, KM_NOSLEEP))) {
5674*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5675*fcf3ce44SJohn Forte 		    "%s: Unable to allocate packet.",
5676*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5677*fcf3ce44SJohn Forte 
5678*fcf3ce44SJohn Forte 		rval = DFC_SYSRES_ERROR;
5679*fcf3ce44SJohn Forte 		goto done;
5680*fcf3ce44SJohn Forte 	}
5681*fcf3ce44SJohn Forte 	/* Make this a polled IO */
5682*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5683*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5684*fcf3ce44SJohn Forte 	pkt->pkt_comp = NULL;
5685*fcf3ce44SJohn Forte 
5686*fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
5687*fcf3ce44SJohn Forte 	pkt->pkt_timeout = (timeout) ? timeout : 30;
5688*fcf3ce44SJohn Forte 
5689*fcf3ce44SJohn Forte 	/* Build the fc header */
5690*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(did);
5691*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
5692*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
5693*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
5694*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
5695*fcf3ce44SJohn Forte 	    F_CTL_SEQ_INITIATIVE;
5696*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
5697*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
5698*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
5699*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5700*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
5701*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
5702*fcf3ce44SJohn Forte 
5703*fcf3ce44SJohn Forte 	/* Copy in the command buffer */
5704*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd,
5705*fcf3ce44SJohn Forte 	    cmd_size, mode) != 0) {
5706*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5707*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
5708*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5709*fcf3ce44SJohn Forte 
5710*fcf3ce44SJohn Forte 		rval = DFC_COPYIN_ERROR;
5711*fcf3ce44SJohn Forte 		goto done;
5712*fcf3ce44SJohn Forte 	}
5713*fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5714*fcf3ce44SJohn Forte 		rval = DFC_IO_ERROR;
5715*fcf3ce44SJohn Forte 		goto done;
5716*fcf3ce44SJohn Forte 	}
5717*fcf3ce44SJohn Forte 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
5718*fcf3ce44SJohn Forte 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5719*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5720*fcf3ce44SJohn Forte 			    "Pkt Transport error. Pkt Timeout.");
5721*fcf3ce44SJohn Forte 			rval = DFC_TIMEOUT;
5722*fcf3ce44SJohn Forte 		} else {
5723*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5724*fcf3ce44SJohn Forte 			    "Pkt Transport error. state=%x",
5725*fcf3ce44SJohn Forte 			    pkt->pkt_state);
5726*fcf3ce44SJohn Forte 			rval = DFC_IO_ERROR;
5727*fcf3ce44SJohn Forte 		}
5728*fcf3ce44SJohn Forte 		goto done;
5729*fcf3ce44SJohn Forte 	}
5730*fcf3ce44SJohn Forte 	rsp_size -= pkt->pkt_resp_resid;
5731*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)pkt->pkt_resp, (void *)rsp_buf,
5732*fcf3ce44SJohn Forte 	    rsp_size, mode) != 0) {
5733*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5734*fcf3ce44SJohn Forte 		    "%s: rsp_buf ddi_copyout failed.",
5735*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5736*fcf3ce44SJohn Forte 
5737*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
5738*fcf3ce44SJohn Forte 		goto done;
5739*fcf3ce44SJohn Forte 	}
5740*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf4,
5741*fcf3ce44SJohn Forte 	    sizeof (uint32_t), mode) != 0) {
5742*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5743*fcf3ce44SJohn Forte 		    "%s: rsp_size ddi_copyout failed.",
5744*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5745*fcf3ce44SJohn Forte 
5746*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
5747*fcf3ce44SJohn Forte 		goto done;
5748*fcf3ce44SJohn Forte 	}
5749*fcf3ce44SJohn Forte 	rval = 0;
5750*fcf3ce44SJohn Forte 
5751*fcf3ce44SJohn Forte done:
5752*fcf3ce44SJohn Forte 	if (pkt) {
5753*fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
5754*fcf3ce44SJohn Forte 	}
5755*fcf3ce44SJohn Forte 	return (rval);
5756*fcf3ce44SJohn Forte 
5757*fcf3ce44SJohn Forte } /* emlxs_dfc_send_els() */
5758*fcf3ce44SJohn Forte 
5759*fcf3ce44SJohn Forte 
5760*fcf3ce44SJohn Forte static int32_t
5761*fcf3ce44SJohn Forte emlxs_dfc_get_ioinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5762*fcf3ce44SJohn Forte {
5763*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5764*fcf3ce44SJohn Forte 	dfc_ioinfo_t ioinfo;
5765*fcf3ce44SJohn Forte 	uint32_t i;
5766*fcf3ce44SJohn Forte 
5767*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
5768*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5769*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
5770*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5771*fcf3ce44SJohn Forte 
5772*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
5773*fcf3ce44SJohn Forte 	}
5774*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (dfc_ioinfo_t)) {
5775*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5776*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
5777*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
5778*fcf3ce44SJohn Forte 
5779*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
5780*fcf3ce44SJohn Forte 	}
5781*fcf3ce44SJohn Forte 	bzero(&ioinfo, sizeof (dfc_ioinfo_t));
5782*fcf3ce44SJohn Forte 
5783*fcf3ce44SJohn Forte 	ioinfo.a_mboxCmd = HBASTATS.MboxIssued;
5784*fcf3ce44SJohn Forte 	ioinfo.a_mboxCmpl = HBASTATS.MboxCompleted;
5785*fcf3ce44SJohn Forte 	ioinfo.a_mboxErr = HBASTATS.MboxError;
5786*fcf3ce44SJohn Forte 
5787*fcf3ce44SJohn Forte 	for (i = 0; i < MAX_RINGS; i++) {
5788*fcf3ce44SJohn Forte 		ioinfo.a_iocbCmd += HBASTATS.IocbIssued[i];
5789*fcf3ce44SJohn Forte 		ioinfo.a_iocbRsp += HBASTATS.IocbReceived[i];
5790*fcf3ce44SJohn Forte 	}
5791*fcf3ce44SJohn Forte 
5792*fcf3ce44SJohn Forte 	ioinfo.a_adapterIntr =
5793*fcf3ce44SJohn Forte 	    HBASTATS.IntrEvent[0] + HBASTATS.IntrEvent[1] +
5794*fcf3ce44SJohn Forte 	    HBASTATS.IntrEvent[2] + HBASTATS.IntrEvent[3] +
5795*fcf3ce44SJohn Forte 	    HBASTATS.IntrEvent[4] + HBASTATS.IntrEvent[5] +
5796*fcf3ce44SJohn Forte 	    HBASTATS.IntrEvent[6] + HBASTATS.IntrEvent[7];
5797*fcf3ce44SJohn Forte 
5798*fcf3ce44SJohn Forte 	ioinfo.a_fcpCmd = HBASTATS.FcpIssued;
5799*fcf3ce44SJohn Forte 	ioinfo.a_fcpCmpl = HBASTATS.FcpCompleted;
5800*fcf3ce44SJohn Forte 	ioinfo.a_fcpErr =
5801*fcf3ce44SJohn Forte 	    HBASTATS.FcpCompleted - HBASTATS.FcpGood;
5802*fcf3ce44SJohn Forte 
5803*fcf3ce44SJohn Forte 	ioinfo.a_seqXmit = HBASTATS.IpSeqIssued;
5804*fcf3ce44SJohn Forte 	ioinfo.a_seqRcv = HBASTATS.IpSeqReceived;
5805*fcf3ce44SJohn Forte 	ioinfo.a_seqXmitErr =
5806*fcf3ce44SJohn Forte 	    HBASTATS.IpSeqCompleted - HBASTATS.IpSeqGood;
5807*fcf3ce44SJohn Forte 
5808*fcf3ce44SJohn Forte 	ioinfo.a_bcastXmit = HBASTATS.IpBcastIssued;
5809*fcf3ce44SJohn Forte 	ioinfo.a_bcastRcv = HBASTATS.IpBcastReceived;
5810*fcf3ce44SJohn Forte 
5811*fcf3ce44SJohn Forte 	ioinfo.a_elsXmit = HBASTATS.ElsCmdIssued;
5812*fcf3ce44SJohn Forte 	ioinfo.a_elsRcv = HBASTATS.ElsCmdReceived;
5813*fcf3ce44SJohn Forte 	ioinfo.a_elsXmitErr =
5814*fcf3ce44SJohn Forte 	    HBASTATS.ElsCmdCompleted - HBASTATS.ElsCmdGood;
5815*fcf3ce44SJohn Forte 
5816*fcf3ce44SJohn Forte 	ioinfo.a_RSCNRcv = HBASTATS.ElsRscnReceived;
5817*fcf3ce44SJohn Forte 
5818*fcf3ce44SJohn Forte 	ioinfo.a_elsBufPost = HBASTATS.ElsUbPosted;
5819*fcf3ce44SJohn Forte 	ioinfo.a_ipBufPost = HBASTATS.IpUbPosted;
5820*fcf3ce44SJohn Forte 
5821*fcf3ce44SJohn Forte 	ioinfo.a_cnt1 = 0;
5822*fcf3ce44SJohn Forte 	ioinfo.a_cnt2 = 0;
5823*fcf3ce44SJohn Forte 	ioinfo.a_cnt3 = 0;
5824*fcf3ce44SJohn Forte 	ioinfo.a_cnt4 = 0;
5825*fcf3ce44SJohn Forte 
5826*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&ioinfo, (void *)dfc->buf1,
5827*fcf3ce44SJohn Forte 	    sizeof (dfc_ioinfo_t), mode) != 0) {
5828*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5829*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
5830*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5831*fcf3ce44SJohn Forte 
5832*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
5833*fcf3ce44SJohn Forte 	}
5834*fcf3ce44SJohn Forte 	return (0);
5835*fcf3ce44SJohn Forte 
5836*fcf3ce44SJohn Forte } /* emlxs_dfc_get_ioinfo() */
5837*fcf3ce44SJohn Forte 
5838*fcf3ce44SJohn Forte 
5839*fcf3ce44SJohn Forte static int32_t
5840*fcf3ce44SJohn Forte emlxs_dfc_get_linkinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5841*fcf3ce44SJohn Forte {
5842*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5843*fcf3ce44SJohn Forte 	dfc_linkinfo_t linkinfo;
5844*fcf3ce44SJohn Forte 
5845*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
5846*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5847*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
5848*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5849*fcf3ce44SJohn Forte 
5850*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
5851*fcf3ce44SJohn Forte 	}
5852*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (dfc_linkinfo_t)) {
5853*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5854*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
5855*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
5856*fcf3ce44SJohn Forte 
5857*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
5858*fcf3ce44SJohn Forte 	}
5859*fcf3ce44SJohn Forte 	bzero(&linkinfo, sizeof (dfc_linkinfo_t));
5860*fcf3ce44SJohn Forte 
5861*fcf3ce44SJohn Forte 	linkinfo.a_linkEventTag = hba->link_event_tag;
5862*fcf3ce44SJohn Forte 	linkinfo.a_linkUp = HBASTATS.LinkUp;
5863*fcf3ce44SJohn Forte 	linkinfo.a_linkDown = HBASTATS.LinkDown;
5864*fcf3ce44SJohn Forte 	linkinfo.a_linkMulti = HBASTATS.LinkMultiEvent;
5865*fcf3ce44SJohn Forte 	linkinfo.a_DID = port->did;
5866*fcf3ce44SJohn Forte 	linkinfo.a_topology = 0;
5867*fcf3ce44SJohn Forte 
5868*fcf3ce44SJohn Forte 	if (hba->state <= FC_LINK_DOWN) {
5869*fcf3ce44SJohn Forte 		linkinfo.a_linkState = LNK_DOWN;
5870*fcf3ce44SJohn Forte 	}
5871*fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
5872*fcf3ce44SJohn Forte 	else if (hba->flag & FC_MENLO_MODE) {
5873*fcf3ce44SJohn Forte 		linkinfo.a_linkState = LNK_DOWN;
5874*fcf3ce44SJohn Forte 		linkinfo.a_topology = LNK_MENLO_MAINTENANCE;
5875*fcf3ce44SJohn Forte 
5876*fcf3ce44SJohn Forte 	}
5877*fcf3ce44SJohn Forte #endif	/* MENLO_SUPPORT */
5878*fcf3ce44SJohn Forte 	else if (hba->state < FC_READY) {
5879*fcf3ce44SJohn Forte 		linkinfo.a_linkState = LNK_DISCOVERY;
5880*fcf3ce44SJohn Forte 	} else {
5881*fcf3ce44SJohn Forte 		linkinfo.a_linkState = LNK_READY;
5882*fcf3ce44SJohn Forte 	}
5883*fcf3ce44SJohn Forte 
5884*fcf3ce44SJohn Forte 	if (linkinfo.a_linkState != LNK_DOWN) {
5885*fcf3ce44SJohn Forte 		if (hba->topology == TOPOLOGY_LOOP) {
5886*fcf3ce44SJohn Forte 			if (hba->flag & FC_FABRIC_ATTACHED) {
5887*fcf3ce44SJohn Forte 				linkinfo.a_topology = LNK_PUBLIC_LOOP;
5888*fcf3ce44SJohn Forte 			} else {
5889*fcf3ce44SJohn Forte 				linkinfo.a_topology = LNK_LOOP;
5890*fcf3ce44SJohn Forte 			}
5891*fcf3ce44SJohn Forte 
5892*fcf3ce44SJohn Forte 			linkinfo.a_alpa = port->did & 0xff;
5893*fcf3ce44SJohn Forte 			linkinfo.a_alpaCnt = port->alpa_map[0];
5894*fcf3ce44SJohn Forte 
5895*fcf3ce44SJohn Forte 			if (linkinfo.a_alpaCnt > 127) {
5896*fcf3ce44SJohn Forte 				linkinfo.a_alpaCnt = 127;
5897*fcf3ce44SJohn Forte 			}
5898*fcf3ce44SJohn Forte 			bcopy((void *)&port->alpa_map[1], linkinfo.a_alpaMap,
5899*fcf3ce44SJohn Forte 			    linkinfo.a_alpaCnt);
5900*fcf3ce44SJohn Forte 		} else {
5901*fcf3ce44SJohn Forte 			if (hba->flag & FC_FABRIC_ATTACHED) {
5902*fcf3ce44SJohn Forte 				linkinfo.a_topology = LNK_FABRIC;
5903*fcf3ce44SJohn Forte 			} else {
5904*fcf3ce44SJohn Forte 				linkinfo.a_topology = LNK_PT2PT;
5905*fcf3ce44SJohn Forte 			}
5906*fcf3ce44SJohn Forte 		}
5907*fcf3ce44SJohn Forte 	}
5908*fcf3ce44SJohn Forte 	bcopy(&hba->wwpn, linkinfo.a_wwpName, 8);
5909*fcf3ce44SJohn Forte 	bcopy(&hba->wwnn, linkinfo.a_wwnName, 8);
5910*fcf3ce44SJohn Forte 
5911*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&linkinfo, (void *)dfc->buf1,
5912*fcf3ce44SJohn Forte 	    sizeof (dfc_linkinfo_t), mode) != 0) {
5913*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5914*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
5915*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5916*fcf3ce44SJohn Forte 
5917*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
5918*fcf3ce44SJohn Forte 	}
5919*fcf3ce44SJohn Forte 	return (0);
5920*fcf3ce44SJohn Forte 
5921*fcf3ce44SJohn Forte } /* emlxs_dfc_get_linkinfo() */
5922*fcf3ce44SJohn Forte 
5923*fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
5924*fcf3ce44SJohn Forte static int32_t
5925*fcf3ce44SJohn Forte emlxs_dfc_get_fctstat(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5926*fcf3ce44SJohn Forte {
5927*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5928*fcf3ce44SJohn Forte 	emlxs_tgtport_stat_t *statp = &TGTPORTSTAT;
5929*fcf3ce44SJohn Forte 	dfc_tgtport_stat_t dfcstat;
5930*fcf3ce44SJohn Forte 
5931*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
5932*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5933*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
5934*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
5935*fcf3ce44SJohn Forte 
5936*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
5937*fcf3ce44SJohn Forte 	}
5938*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (emlxs_tgtport_stat_t)) {
5939*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5940*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
5941*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
5942*fcf3ce44SJohn Forte 
5943*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
5944*fcf3ce44SJohn Forte 	}
5945*fcf3ce44SJohn Forte 	bzero(&dfcstat, sizeof (dfcstat));
5946*fcf3ce44SJohn Forte 
5947*fcf3ce44SJohn Forte 	dfcstat.FctRcvDropped = statp->FctRcvDropped;
5948*fcf3ce44SJohn Forte 	dfcstat.FctOverQDepth = statp->FctOverQDepth;
5949*fcf3ce44SJohn Forte 	dfcstat.FctOutstandingIO = statp->FctOutstandingIO;
5950*fcf3ce44SJohn Forte 	dfcstat.FctFailedPortRegister =
5951*fcf3ce44SJohn Forte 	    statp->FctFailedPortRegister;
5952*fcf3ce44SJohn Forte 	dfcstat.FctPortRegister = statp->FctPortRegister;
5953*fcf3ce44SJohn Forte 	dfcstat.FctPortDeregister = statp->FctPortDeregister;
5954*fcf3ce44SJohn Forte 
5955*fcf3ce44SJohn Forte 	dfcstat.FctAbortSent = statp->FctAbortSent;
5956*fcf3ce44SJohn Forte 	dfcstat.FctNoBuffer = statp->FctNoBuffer;
5957*fcf3ce44SJohn Forte 	dfcstat.FctScsiStatusErr = statp->FctScsiStatusErr;
5958*fcf3ce44SJohn Forte 	dfcstat.FctScsiQfullErr = statp->FctScsiQfullErr;
5959*fcf3ce44SJohn Forte 	dfcstat.FctScsiResidOver = statp->FctScsiResidOver;
5960*fcf3ce44SJohn Forte 	dfcstat.FctScsiResidUnder = statp->FctScsiResidUnder;
5961*fcf3ce44SJohn Forte 	dfcstat.FctScsiSenseErr = statp->FctScsiSenseErr;
5962*fcf3ce44SJohn Forte 
5963*fcf3ce44SJohn Forte 	dfcstat.FctEvent = statp->FctEvent;
5964*fcf3ce44SJohn Forte 	dfcstat.FctCompleted = statp->FctCompleted;
5965*fcf3ce44SJohn Forte 	dfcstat.FctCmplGood = statp->FctCmplGood;
5966*fcf3ce44SJohn Forte 	dfcstat.FctCmplError = statp->FctCmplError;
5967*fcf3ce44SJohn Forte 	dfcstat.FctStray = statp->FctStray;
5968*fcf3ce44SJohn Forte 
5969*fcf3ce44SJohn Forte 	bcopy(&statp->FctP2IOWcnt[0], &dfcstat.FctP2IOWcnt[0],
5970*fcf3ce44SJohn Forte 	    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
5971*fcf3ce44SJohn Forte 	bcopy(&statp->FctP2IORcnt[0], &dfcstat.FctP2IORcnt[0],
5972*fcf3ce44SJohn Forte 	    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
5973*fcf3ce44SJohn Forte 	dfcstat.FctIOCmdCnt = statp->FctIOCmdCnt;
5974*fcf3ce44SJohn Forte 	dfcstat.FctReadBytes = statp->FctReadBytes;
5975*fcf3ce44SJohn Forte 	dfcstat.FctWriteBytes = statp->FctWriteBytes;
5976*fcf3ce44SJohn Forte 	dfcstat.FctCmdReceived = statp->FctCmdReceived;
5977*fcf3ce44SJohn Forte 
5978*fcf3ce44SJohn Forte 	if (dfc->flag) {	/* Clear counters after read */
5979*fcf3ce44SJohn Forte 		bzero(&statp->FctP2IOWcnt[0],
5980*fcf3ce44SJohn Forte 		    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
5981*fcf3ce44SJohn Forte 		bzero(&statp->FctP2IORcnt[0],
5982*fcf3ce44SJohn Forte 		    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
5983*fcf3ce44SJohn Forte 		statp->FctIOCmdCnt = 0;
5984*fcf3ce44SJohn Forte 		statp->FctReadBytes = 0;
5985*fcf3ce44SJohn Forte 		statp->FctWriteBytes = 0;
5986*fcf3ce44SJohn Forte 		statp->FctCmdReceived = 0;
5987*fcf3ce44SJohn Forte 	}
5988*fcf3ce44SJohn Forte 	if (hba->state <= FC_LINK_DOWN) {
5989*fcf3ce44SJohn Forte 		dfcstat.FctLinkState = LNK_DOWN;
5990*fcf3ce44SJohn Forte 	}
5991*fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
5992*fcf3ce44SJohn Forte 	else if (hba->flag & FC_MENLO_MODE) {
5993*fcf3ce44SJohn Forte 		dfcstat.FctLinkState = LNK_DOWN;
5994*fcf3ce44SJohn Forte 	}
5995*fcf3ce44SJohn Forte #endif	/* MENLO_SUPPORT */
5996*fcf3ce44SJohn Forte 	else if (hba->state < FC_READY) {
5997*fcf3ce44SJohn Forte 		dfcstat.FctLinkState = LNK_DISCOVERY;
5998*fcf3ce44SJohn Forte 	} else {
5999*fcf3ce44SJohn Forte 		dfcstat.FctLinkState = LNK_READY;
6000*fcf3ce44SJohn Forte 	}
6001*fcf3ce44SJohn Forte 
6002*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&dfcstat, (void *)dfc->buf1,
6003*fcf3ce44SJohn Forte 	    sizeof (dfc_tgtport_stat_t), mode) != 0) {
6004*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6005*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
6006*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6007*fcf3ce44SJohn Forte 
6008*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
6009*fcf3ce44SJohn Forte 	}
6010*fcf3ce44SJohn Forte 	return (0);
6011*fcf3ce44SJohn Forte 
6012*fcf3ce44SJohn Forte } /* emlxs_dfc_get_fctstat() */
6013*fcf3ce44SJohn Forte #endif	/* SFCT_SUPPORT */
6014*fcf3ce44SJohn Forte 
6015*fcf3ce44SJohn Forte static int32_t
6016*fcf3ce44SJohn Forte emlxs_dfc_get_nodeinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6017*fcf3ce44SJohn Forte {
6018*fcf3ce44SJohn Forte 	emlxs_port_t *port;
6019*fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
6020*fcf3ce44SJohn Forte 	dfc_node_t *dfc_node;
6021*fcf3ce44SJohn Forte 	dfc_node_t *dnp;
6022*fcf3ce44SJohn Forte 	uint32_t node_count;
6023*fcf3ce44SJohn Forte 	NODELIST *nlp;
6024*fcf3ce44SJohn Forte 	uint32_t size;
6025*fcf3ce44SJohn Forte 	uint32_t i;
6026*fcf3ce44SJohn Forte 
6027*fcf3ce44SJohn Forte 	port = &VPORT(dfc->data1);
6028*fcf3ce44SJohn Forte 
6029*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6030*fcf3ce44SJohn Forte 	    "%s requested.",
6031*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
6032*fcf3ce44SJohn Forte 
6033*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
6034*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6035*fcf3ce44SJohn Forte 		    "%s: NULL buffer1 found.",
6036*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6037*fcf3ce44SJohn Forte 
6038*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
6039*fcf3ce44SJohn Forte 	}
6040*fcf3ce44SJohn Forte 	if (dfc->buf1_size < (sizeof (dfc_node_t) * MAX_NODES)) {
6041*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6042*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
6043*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6044*fcf3ce44SJohn Forte 
6045*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
6046*fcf3ce44SJohn Forte 	}
6047*fcf3ce44SJohn Forte 	if (!dfc->buf2 || !dfc->buf2_size) {
6048*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6049*fcf3ce44SJohn Forte 		    "%s: NULL buffer2 found.",
6050*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6051*fcf3ce44SJohn Forte 
6052*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
6053*fcf3ce44SJohn Forte 	}
6054*fcf3ce44SJohn Forte 	if (dfc->buf2_size < sizeof (uint32_t)) {
6055*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6056*fcf3ce44SJohn Forte 		    "%s: Buffer2 too small. (size=%d)",
6057*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
6058*fcf3ce44SJohn Forte 
6059*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
6060*fcf3ce44SJohn Forte 	}
6061*fcf3ce44SJohn Forte 	node_count = port->node_count;
6062*fcf3ce44SJohn Forte 
6063*fcf3ce44SJohn Forte 	if (node_count == 0) {
6064*fcf3ce44SJohn Forte 		return (0);
6065*fcf3ce44SJohn Forte 	}
6066*fcf3ce44SJohn Forte 	if (node_count > MAX_NODES) {
6067*fcf3ce44SJohn Forte 		node_count = MAX_NODES;
6068*fcf3ce44SJohn Forte 	}
6069*fcf3ce44SJohn Forte 	size = node_count * sizeof (dfc_node_t);
6070*fcf3ce44SJohn Forte 
6071*fcf3ce44SJohn Forte 	if (!(dfc_node = (dfc_node_t *)kmem_zalloc(size, KM_NOSLEEP))) {
6072*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6073*fcf3ce44SJohn Forte 		    "%s: Unable to allocate dfc_node.",
6074*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6075*fcf3ce44SJohn Forte 
6076*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
6077*fcf3ce44SJohn Forte 	}
6078*fcf3ce44SJohn Forte 	dnp = dfc_node;
6079*fcf3ce44SJohn Forte 
6080*fcf3ce44SJohn Forte 	rw_enter(&port->node_rwlock, RW_READER);
6081*fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
6082*fcf3ce44SJohn Forte 		nlp = port->node_table[i];
6083*fcf3ce44SJohn Forte 		while (nlp != NULL) {
6084*fcf3ce44SJohn Forte 			dnp->port_id = nlp->nlp_DID;
6085*fcf3ce44SJohn Forte 			dnp->rpi = nlp->nlp_Rpi;
6086*fcf3ce44SJohn Forte 			dnp->xri = nlp->nlp_Xri;
6087*fcf3ce44SJohn Forte 
6088*fcf3ce44SJohn Forte 			bcopy((char *)&nlp->sparm, (char *)&dnp->sparm,
6089*fcf3ce44SJohn Forte 			    sizeof (dnp->sparm));
6090*fcf3ce44SJohn Forte 
6091*fcf3ce44SJohn Forte 			if (nlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE) {
6092*fcf3ce44SJohn Forte 				dnp->flags |= PORT_FLAG_FCP_TARGET;
6093*fcf3ce44SJohn Forte 			}
6094*fcf3ce44SJohn Forte 			if (nlp->nlp_fcp_info & NLP_FCP_INI_DEVICE) {
6095*fcf3ce44SJohn Forte 				dnp->flags |= PORT_FLAG_FCP_INI;
6096*fcf3ce44SJohn Forte 
6097*fcf3ce44SJohn Forte 			}
6098*fcf3ce44SJohn Forte 			if (nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
6099*fcf3ce44SJohn Forte 				dnp->flags |= PORT_FLAG_FCP2;
6100*fcf3ce44SJohn Forte 			}
6101*fcf3ce44SJohn Forte 			if (cfg[CFG_NETWORK_ON].current && nlp->nlp_Xri) {
6102*fcf3ce44SJohn Forte 				dnp->flags |= PORT_FLAG_IP;
6103*fcf3ce44SJohn Forte 			}
6104*fcf3ce44SJohn Forte 			dnp++;
6105*fcf3ce44SJohn Forte 			nlp = (NODELIST *) nlp->nlp_list_next;
6106*fcf3ce44SJohn Forte 		}
6107*fcf3ce44SJohn Forte 	}
6108*fcf3ce44SJohn Forte 	rw_exit(&port->node_rwlock);
6109*fcf3ce44SJohn Forte 
6110*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)dfc_node, (void *)dfc->buf1,
6111*fcf3ce44SJohn Forte 	    size, mode) != 0) {
6112*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6113*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
6114*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6115*fcf3ce44SJohn Forte 
6116*fcf3ce44SJohn Forte 		kmem_free(dfc_node, size);
6117*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
6118*fcf3ce44SJohn Forte 	}
6119*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&node_count, (void *)dfc->buf2,
6120*fcf3ce44SJohn Forte 	    sizeof (uint32_t), mode) != 0) {
6121*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6122*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
6123*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6124*fcf3ce44SJohn Forte 
6125*fcf3ce44SJohn Forte 		kmem_free(dfc_node, size);
6126*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
6127*fcf3ce44SJohn Forte 	}
6128*fcf3ce44SJohn Forte 	kmem_free(dfc_node, size);
6129*fcf3ce44SJohn Forte 
6130*fcf3ce44SJohn Forte 	return (0);
6131*fcf3ce44SJohn Forte 
6132*fcf3ce44SJohn Forte } /* emlxs_dfc_get_nodeinfo() */
6133*fcf3ce44SJohn Forte 
6134*fcf3ce44SJohn Forte 
6135*fcf3ce44SJohn Forte static int32_t
6136*fcf3ce44SJohn Forte emlxs_dfc_read_mem(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6137*fcf3ce44SJohn Forte {
6138*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
6139*fcf3ce44SJohn Forte 	uint32_t offset;
6140*fcf3ce44SJohn Forte 	uint32_t size;
6141*fcf3ce44SJohn Forte 	uint32_t max_size;
6142*fcf3ce44SJohn Forte 	uint8_t *buffer;
6143*fcf3ce44SJohn Forte 	uint8_t *slim;
6144*fcf3ce44SJohn Forte 
6145*fcf3ce44SJohn Forte 	offset = dfc->data1;
6146*fcf3ce44SJohn Forte 	size = dfc->data2;
6147*fcf3ce44SJohn Forte 
6148*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
6149*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6150*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
6151*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6152*fcf3ce44SJohn Forte 
6153*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
6154*fcf3ce44SJohn Forte 	}
6155*fcf3ce44SJohn Forte 	if (size > dfc->buf1_size) {
6156*fcf3ce44SJohn Forte 		size = dfc->buf1_size;
6157*fcf3ce44SJohn Forte 	}
6158*fcf3ce44SJohn Forte 	if (offset % 4) {
6159*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6160*fcf3ce44SJohn Forte 		    "%s: Offset misaligned. (offset=%d)",
6161*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset);
6162*fcf3ce44SJohn Forte 
6163*fcf3ce44SJohn Forte 		return (DFC_ARG_MISALIGNED);
6164*fcf3ce44SJohn Forte 	}
6165*fcf3ce44SJohn Forte 	if (size % 4) {
6166*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6167*fcf3ce44SJohn Forte 		    "%s: Size misaligned. (size=%d)",
6168*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), size);
6169*fcf3ce44SJohn Forte 
6170*fcf3ce44SJohn Forte 		return (DFC_ARG_MISALIGNED);
6171*fcf3ce44SJohn Forte 	}
6172*fcf3ce44SJohn Forte 	if (hba->flag & FC_SLIM2_MODE) {
6173*fcf3ce44SJohn Forte 		max_size = SLI2_SLIM2_SIZE;
6174*fcf3ce44SJohn Forte 	} else {
6175*fcf3ce44SJohn Forte 		max_size = 4096;
6176*fcf3ce44SJohn Forte 	}
6177*fcf3ce44SJohn Forte 
6178*fcf3ce44SJohn Forte 	if (offset >= max_size) {
6179*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6180*fcf3ce44SJohn Forte 		    "%s: Offset too large. (offset=%d)",
6181*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset);
6182*fcf3ce44SJohn Forte 
6183*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
6184*fcf3ce44SJohn Forte 	}
6185*fcf3ce44SJohn Forte 	if ((size + offset) > max_size) {
6186*fcf3ce44SJohn Forte 		size = (max_size - offset);
6187*fcf3ce44SJohn Forte 	}
6188*fcf3ce44SJohn Forte 	if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_NOSLEEP))) {
6189*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6190*fcf3ce44SJohn Forte 		    "%s: Unable to allocate buffer.",
6191*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6192*fcf3ce44SJohn Forte 
6193*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
6194*fcf3ce44SJohn Forte 	}
6195*fcf3ce44SJohn Forte 	if (hba->flag & FC_SLIM2_MODE) {
6196*fcf3ce44SJohn Forte 		slim = (uint8_t *)hba->slim2.virt + offset;
6197*fcf3ce44SJohn Forte 		emlxs_pcimem_bcopy((uint32_t *)slim, (uint32_t *)buffer,
6198*fcf3ce44SJohn Forte 		    size);
6199*fcf3ce44SJohn Forte 	} else {
6200*fcf3ce44SJohn Forte 		slim = (uint8_t *)hba->slim_addr + offset;
6201*fcf3ce44SJohn Forte 		READ_SLIM_COPY(hba, (uint32_t *)buffer,
6202*fcf3ce44SJohn Forte 		    (uint32_t *)slim, (size / 4));
6203*fcf3ce44SJohn Forte 	}
6204*fcf3ce44SJohn Forte 
6205*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)buffer, (void *)dfc->buf1,
6206*fcf3ce44SJohn Forte 	    size, mode) != 0) {
6207*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6208*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
6209*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6210*fcf3ce44SJohn Forte 
6211*fcf3ce44SJohn Forte 		kmem_free(buffer, size);
6212*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
6213*fcf3ce44SJohn Forte 	}
6214*fcf3ce44SJohn Forte 	kmem_free(buffer, size);
6215*fcf3ce44SJohn Forte 
6216*fcf3ce44SJohn Forte 	return (0);
6217*fcf3ce44SJohn Forte 
6218*fcf3ce44SJohn Forte } /* emlxs_dfc_read_mem() */
6219*fcf3ce44SJohn Forte 
6220*fcf3ce44SJohn Forte 
6221*fcf3ce44SJohn Forte static int32_t
6222*fcf3ce44SJohn Forte emlxs_dfc_write_mem(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6223*fcf3ce44SJohn Forte {
6224*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
6225*fcf3ce44SJohn Forte 	uint32_t offset;
6226*fcf3ce44SJohn Forte 	uint32_t size;
6227*fcf3ce44SJohn Forte 	uint32_t max_size;
6228*fcf3ce44SJohn Forte 	uint8_t *buffer;
6229*fcf3ce44SJohn Forte 	uint8_t *slim;
6230*fcf3ce44SJohn Forte 
6231*fcf3ce44SJohn Forte 	offset = dfc->data1;
6232*fcf3ce44SJohn Forte 	size = dfc->data2;
6233*fcf3ce44SJohn Forte 
6234*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
6235*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6236*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
6237*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6238*fcf3ce44SJohn Forte 
6239*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
6240*fcf3ce44SJohn Forte 	}
6241*fcf3ce44SJohn Forte 	if (size > dfc->buf1_size) {
6242*fcf3ce44SJohn Forte 		size = dfc->buf1_size;
6243*fcf3ce44SJohn Forte 	}
6244*fcf3ce44SJohn Forte 	if (offset % 4) {
6245*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6246*fcf3ce44SJohn Forte 		    "%s: Offset misaligned. (offset=%d)",
6247*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset);
6248*fcf3ce44SJohn Forte 
6249*fcf3ce44SJohn Forte 		return (DFC_ARG_MISALIGNED);
6250*fcf3ce44SJohn Forte 	}
6251*fcf3ce44SJohn Forte 	if (size % 4) {
6252*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6253*fcf3ce44SJohn Forte 		    "%s: Size misaligned. (szie=%d)",
6254*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), size);
6255*fcf3ce44SJohn Forte 
6256*fcf3ce44SJohn Forte 		return (DFC_ARG_MISALIGNED);
6257*fcf3ce44SJohn Forte 	}
6258*fcf3ce44SJohn Forte 	if (hba->flag & FC_SLIM2_MODE) {
6259*fcf3ce44SJohn Forte 		max_size = SLI2_SLIM2_SIZE;
6260*fcf3ce44SJohn Forte 	} else {
6261*fcf3ce44SJohn Forte 		max_size = 4096;
6262*fcf3ce44SJohn Forte 	}
6263*fcf3ce44SJohn Forte 
6264*fcf3ce44SJohn Forte 	if (offset >= max_size) {
6265*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6266*fcf3ce44SJohn Forte 		    "%s: Offset too large. (offset=%d)",
6267*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset);
6268*fcf3ce44SJohn Forte 
6269*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
6270*fcf3ce44SJohn Forte 	}
6271*fcf3ce44SJohn Forte 	if ((size + offset) > max_size) {
6272*fcf3ce44SJohn Forte 		size = (max_size - offset);
6273*fcf3ce44SJohn Forte 	}
6274*fcf3ce44SJohn Forte 	if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_NOSLEEP))) {
6275*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6276*fcf3ce44SJohn Forte 		    "%s: Unable to allocate buffer.",
6277*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6278*fcf3ce44SJohn Forte 
6279*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
6280*fcf3ce44SJohn Forte 	}
6281*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)buffer,
6282*fcf3ce44SJohn Forte 	    size, mode) != 0) {
6283*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6284*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
6285*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6286*fcf3ce44SJohn Forte 
6287*fcf3ce44SJohn Forte 		kmem_free(buffer, size);
6288*fcf3ce44SJohn Forte 		return (DFC_COPYIN_ERROR);
6289*fcf3ce44SJohn Forte 	}
6290*fcf3ce44SJohn Forte 	if (hba->flag & FC_SLIM2_MODE) {
6291*fcf3ce44SJohn Forte 		slim = (uint8_t *)hba->slim2.virt + offset;
6292*fcf3ce44SJohn Forte 		emlxs_pcimem_bcopy((uint32_t *)buffer, (uint32_t *)slim,
6293*fcf3ce44SJohn Forte 		    size);
6294*fcf3ce44SJohn Forte 	} else {
6295*fcf3ce44SJohn Forte 		slim = (uint8_t *)hba->slim_addr + offset;
6296*fcf3ce44SJohn Forte 		WRITE_SLIM_COPY(hba, (uint32_t *)buffer, (uint32_t *)slim,
6297*fcf3ce44SJohn Forte 		    (size / 4));
6298*fcf3ce44SJohn Forte 	}
6299*fcf3ce44SJohn Forte 
6300*fcf3ce44SJohn Forte 	kmem_free(buffer, size);
6301*fcf3ce44SJohn Forte 
6302*fcf3ce44SJohn Forte 	return (0);
6303*fcf3ce44SJohn Forte 
6304*fcf3ce44SJohn Forte } /* emlxs_dfc_write_mem() */
6305*fcf3ce44SJohn Forte 
6306*fcf3ce44SJohn Forte 
6307*fcf3ce44SJohn Forte /*ARGSUSED*/
6308*fcf3ce44SJohn Forte static int32_t
6309*fcf3ce44SJohn Forte emlxs_dfc_write_ctlreg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6310*fcf3ce44SJohn Forte {
6311*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
6312*fcf3ce44SJohn Forte 	uint32_t offset;
6313*fcf3ce44SJohn Forte 	uint32_t value;
6314*fcf3ce44SJohn Forte 
6315*fcf3ce44SJohn Forte 	offset = dfc->data1;
6316*fcf3ce44SJohn Forte 	value = dfc->data2;
6317*fcf3ce44SJohn Forte 
6318*fcf3ce44SJohn Forte 	if (!(hba->flag & FC_OFFLINE_MODE)) {
6319*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6320*fcf3ce44SJohn Forte 		    "%s: Adapter not offline.",
6321*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6322*fcf3ce44SJohn Forte 
6323*fcf3ce44SJohn Forte 		return (DFC_ONLINE_ERROR);
6324*fcf3ce44SJohn Forte 	}
6325*fcf3ce44SJohn Forte 	if (offset % 4) {
6326*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6327*fcf3ce44SJohn Forte 		    "%s: Offset misaligned. (offset=%d)",
6328*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset);
6329*fcf3ce44SJohn Forte 
6330*fcf3ce44SJohn Forte 		return (DFC_ARG_MISALIGNED);
6331*fcf3ce44SJohn Forte 	}
6332*fcf3ce44SJohn Forte 	if (offset > 255) {
6333*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6334*fcf3ce44SJohn Forte 		    "%s: Offset too large. (offset=%d)",
6335*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset);
6336*fcf3ce44SJohn Forte 
6337*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
6338*fcf3ce44SJohn Forte 	}
6339*fcf3ce44SJohn Forte 	WRITE_CSR_REG(hba, (hba->csr_addr + offset), value);
6340*fcf3ce44SJohn Forte 
6341*fcf3ce44SJohn Forte 	return (0);
6342*fcf3ce44SJohn Forte 
6343*fcf3ce44SJohn Forte } /* emlxs_dfc_write_ctlreg() */
6344*fcf3ce44SJohn Forte 
6345*fcf3ce44SJohn Forte 
6346*fcf3ce44SJohn Forte static int32_t
6347*fcf3ce44SJohn Forte emlxs_dfc_read_ctlreg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6348*fcf3ce44SJohn Forte {
6349*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
6350*fcf3ce44SJohn Forte 	uint32_t offset;
6351*fcf3ce44SJohn Forte 	uint32_t value;
6352*fcf3ce44SJohn Forte 
6353*fcf3ce44SJohn Forte 	offset = dfc->data1;
6354*fcf3ce44SJohn Forte 
6355*fcf3ce44SJohn Forte 	if (offset % 4) {
6356*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6357*fcf3ce44SJohn Forte 		    "%s: Offset misaligned. (offset=%d)",
6358*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset);
6359*fcf3ce44SJohn Forte 
6360*fcf3ce44SJohn Forte 		return (DFC_ARG_MISALIGNED);
6361*fcf3ce44SJohn Forte 	}
6362*fcf3ce44SJohn Forte 	if (offset > 255) {
6363*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6364*fcf3ce44SJohn Forte 		    "%s: Offset too large. (offset=%d)",
6365*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), offset);
6366*fcf3ce44SJohn Forte 
6367*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOBIG);
6368*fcf3ce44SJohn Forte 	}
6369*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
6370*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6371*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
6372*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6373*fcf3ce44SJohn Forte 
6374*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
6375*fcf3ce44SJohn Forte 	}
6376*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (uint32_t)) {
6377*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6378*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
6379*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6380*fcf3ce44SJohn Forte 
6381*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
6382*fcf3ce44SJohn Forte 	}
6383*fcf3ce44SJohn Forte 	value = READ_CSR_REG(hba, (hba->csr_addr + offset));
6384*fcf3ce44SJohn Forte 
6385*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&value, (void *)dfc->buf1,
6386*fcf3ce44SJohn Forte 	    sizeof (uint32_t), mode) != 0) {
6387*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6388*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
6389*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6390*fcf3ce44SJohn Forte 
6391*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
6392*fcf3ce44SJohn Forte 	}
6393*fcf3ce44SJohn Forte 	return (0);
6394*fcf3ce44SJohn Forte 
6395*fcf3ce44SJohn Forte } /* emlxs_dfc_read_ctlreg() */
6396*fcf3ce44SJohn Forte 
6397*fcf3ce44SJohn Forte 
6398*fcf3ce44SJohn Forte static int32_t
6399*fcf3ce44SJohn Forte emlxs_dfc_set_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6400*fcf3ce44SJohn Forte {
6401*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
6402*fcf3ce44SJohn Forte 	uint32_t event;
6403*fcf3ce44SJohn Forte 	uint32_t enable;
6404*fcf3ce44SJohn Forte 	uint32_t pid;
6405*fcf3ce44SJohn Forte 	uint32_t count;
6406*fcf3ce44SJohn Forte 	uint32_t i;
6407*fcf3ce44SJohn Forte 	emlxs_dfc_event_t *dfc_event;
6408*fcf3ce44SJohn Forte 
6409*fcf3ce44SJohn Forte 	event = dfc->data1;
6410*fcf3ce44SJohn Forte 	pid = dfc->data2;
6411*fcf3ce44SJohn Forte 	enable = dfc->flag;
6412*fcf3ce44SJohn Forte 
6413*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6414*fcf3ce44SJohn Forte 	    "%s: %s. pid=%d enable=%d",
6415*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd),
6416*fcf3ce44SJohn Forte 	    emlxs_dfc_event_xlate(event), pid, enable);
6417*fcf3ce44SJohn Forte 
6418*fcf3ce44SJohn Forte 	switch (event) {
6419*fcf3ce44SJohn Forte 	case FC_REG_LINK_EVENT:
6420*fcf3ce44SJohn Forte 	case FC_REG_RSCN_EVENT:
6421*fcf3ce44SJohn Forte 	case FC_REG_CT_EVENT:
6422*fcf3ce44SJohn Forte 	case FC_REG_DUMP_EVENT:
6423*fcf3ce44SJohn Forte 	case FC_REG_TEMP_EVENT:
6424*fcf3ce44SJohn Forte 	case FC_REG_FCOE_EVENT:
6425*fcf3ce44SJohn Forte 		break;
6426*fcf3ce44SJohn Forte 
6427*fcf3ce44SJohn Forte 	case FC_REG_MULTIPULSE_EVENT:
6428*fcf3ce44SJohn Forte 	default:
6429*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6430*fcf3ce44SJohn Forte 		    "%s: %s. Invalid event. pid=%d enable=%d",
6431*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
6432*fcf3ce44SJohn Forte 		    emlxs_dfc_event_xlate(event), pid, enable);
6433*fcf3ce44SJohn Forte 
6434*fcf3ce44SJohn Forte 		return (DFC_ARG_INVALID);
6435*fcf3ce44SJohn Forte 	}
6436*fcf3ce44SJohn Forte 
6437*fcf3ce44SJohn Forte 	if (enable) {
6438*fcf3ce44SJohn Forte 		if (dfc->buf1_size < sizeof (uint32_t)) {
6439*fcf3ce44SJohn Forte 			dfc->buf1 = NULL;
6440*fcf3ce44SJohn Forte 		} else if (!dfc->buf1) {
6441*fcf3ce44SJohn Forte 			dfc->buf1_size = 0;
6442*fcf3ce44SJohn Forte 		}
6443*fcf3ce44SJohn Forte 		/* Make sure this pid/event is not already registered */
6444*fcf3ce44SJohn Forte 		dfc_event = NULL;
6445*fcf3ce44SJohn Forte 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
6446*fcf3ce44SJohn Forte 			dfc_event = &hba->dfc_event[i];
6447*fcf3ce44SJohn Forte 
6448*fcf3ce44SJohn Forte 			if (dfc_event->pid == pid &&
6449*fcf3ce44SJohn Forte 			    dfc_event->event == event) {
6450*fcf3ce44SJohn Forte 				break;
6451*fcf3ce44SJohn Forte 			}
6452*fcf3ce44SJohn Forte 		}
6453*fcf3ce44SJohn Forte 
6454*fcf3ce44SJohn Forte 		if (i == MAX_DFC_EVENTS) {
6455*fcf3ce44SJohn Forte 			/* Find next available event object */
6456*fcf3ce44SJohn Forte 			for (i = 0; i < MAX_DFC_EVENTS; i++) {
6457*fcf3ce44SJohn Forte 				dfc_event = &hba->dfc_event[i];
6458*fcf3ce44SJohn Forte 
6459*fcf3ce44SJohn Forte 				if (!dfc_event->pid && !dfc_event->event) {
6460*fcf3ce44SJohn Forte 					break;
6461*fcf3ce44SJohn Forte 				}
6462*fcf3ce44SJohn Forte 			}
6463*fcf3ce44SJohn Forte 
6464*fcf3ce44SJohn Forte 			/* Return if all event objects are busy */
6465*fcf3ce44SJohn Forte 			if (i == MAX_DFC_EVENTS) {
6466*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6467*fcf3ce44SJohn Forte 				    "%s: %s. Too many events registered."
6468*fcf3ce44SJohn Forte 				    " pid=%d enable=%d",
6469*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd),
6470*fcf3ce44SJohn Forte 				    emlxs_dfc_event_xlate(event),
6471*fcf3ce44SJohn Forte 				    pid, enable);
6472*fcf3ce44SJohn Forte 
6473*fcf3ce44SJohn Forte 				return (DFC_DRVRES_ERROR);
6474*fcf3ce44SJohn Forte 			}
6475*fcf3ce44SJohn Forte 		}
6476*fcf3ce44SJohn Forte 		/* Initialize */
6477*fcf3ce44SJohn Forte 		dfc_event->pid = pid;
6478*fcf3ce44SJohn Forte 		dfc_event->event = event;
6479*fcf3ce44SJohn Forte 		dfc_event->last_id = (uint32_t)-1;
6480*fcf3ce44SJohn Forte 		dfc_event->dataout = NULL;
6481*fcf3ce44SJohn Forte 		dfc_event->size = 0;
6482*fcf3ce44SJohn Forte 		dfc_event->mode = 0;
6483*fcf3ce44SJohn Forte 
6484*fcf3ce44SJohn Forte 		(void) emlxs_get_dfc_event(port, dfc_event, 0);
6485*fcf3ce44SJohn Forte 
6486*fcf3ce44SJohn Forte 		if (dfc->buf1) {
6487*fcf3ce44SJohn Forte 			if (ddi_copyout((void *)&dfc_event->last_id, dfc->buf1,
6488*fcf3ce44SJohn Forte 			    sizeof (uint32_t), mode) != 0) {
6489*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6490*fcf3ce44SJohn Forte 				    "%s: ddi_copyout failed.",
6491*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
6492*fcf3ce44SJohn Forte 
6493*fcf3ce44SJohn Forte 				return (DFC_COPYOUT_ERROR);
6494*fcf3ce44SJohn Forte 			}
6495*fcf3ce44SJohn Forte 		}
6496*fcf3ce44SJohn Forte 		/*
6497*fcf3ce44SJohn Forte 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, "%s: %s.
6498*fcf3ce44SJohn Forte 		 * Enabled. pid=%d id=%d", emlxs_dfc_xlate(dfc->cmd),
6499*fcf3ce44SJohn Forte 		 * emlxs_dfc_event_xlate(event), pid, dfc_event->last_id);
6500*fcf3ce44SJohn Forte 		 */
6501*fcf3ce44SJohn Forte 
6502*fcf3ce44SJohn Forte 		hba->log_events |= event;
6503*fcf3ce44SJohn Forte 	} else {	/* Disable */
6504*fcf3ce44SJohn Forte 		/* Find the event entry */
6505*fcf3ce44SJohn Forte 		dfc_event = NULL;
6506*fcf3ce44SJohn Forte 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
6507*fcf3ce44SJohn Forte 			dfc_event = &hba->dfc_event[i];
6508*fcf3ce44SJohn Forte 
6509*fcf3ce44SJohn Forte 			if (dfc_event->pid == pid &&
6510*fcf3ce44SJohn Forte 			    dfc_event->event == event) {
6511*fcf3ce44SJohn Forte 				break;
6512*fcf3ce44SJohn Forte 			}
6513*fcf3ce44SJohn Forte 		}
6514*fcf3ce44SJohn Forte 
6515*fcf3ce44SJohn Forte 		if (i == MAX_DFC_EVENTS) {
6516*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6517*fcf3ce44SJohn Forte 			    "%s: %s. Event not registered."
6518*fcf3ce44SJohn Forte 			    " pid=%d enable=%d",
6519*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
6520*fcf3ce44SJohn Forte 			    emlxs_dfc_event_xlate(event),
6521*fcf3ce44SJohn Forte 			    pid, enable);
6522*fcf3ce44SJohn Forte 
6523*fcf3ce44SJohn Forte 			return (DFC_ARG_INVALID);
6524*fcf3ce44SJohn Forte 		}
6525*fcf3ce44SJohn Forte 		/* Kill the event thread if it is sleeping */
6526*fcf3ce44SJohn Forte 		(void) emlxs_kill_dfc_event(port, dfc_event);
6527*fcf3ce44SJohn Forte 
6528*fcf3ce44SJohn Forte 		/* Count the number of pids still registered for this event */
6529*fcf3ce44SJohn Forte 		count = 0;
6530*fcf3ce44SJohn Forte 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
6531*fcf3ce44SJohn Forte 			dfc_event = &hba->dfc_event[i];
6532*fcf3ce44SJohn Forte 
6533*fcf3ce44SJohn Forte 			if (dfc_event->event == event) {
6534*fcf3ce44SJohn Forte 				count++;
6535*fcf3ce44SJohn Forte 			}
6536*fcf3ce44SJohn Forte 		}
6537*fcf3ce44SJohn Forte 
6538*fcf3ce44SJohn Forte 		/*
6539*fcf3ce44SJohn Forte 		 * If no more pids need this event, then disable logging for
6540*fcf3ce44SJohn Forte 		 * this event
6541*fcf3ce44SJohn Forte 		 */
6542*fcf3ce44SJohn Forte 		if (count == 0) {
6543*fcf3ce44SJohn Forte 			hba->log_events &= ~event;
6544*fcf3ce44SJohn Forte 		}
6545*fcf3ce44SJohn Forte 	}
6546*fcf3ce44SJohn Forte 
6547*fcf3ce44SJohn Forte 	return (0);
6548*fcf3ce44SJohn Forte 
6549*fcf3ce44SJohn Forte } /* emlxs_dfc_set_event() */
6550*fcf3ce44SJohn Forte 
6551*fcf3ce44SJohn Forte 
6552*fcf3ce44SJohn Forte static int32_t
6553*fcf3ce44SJohn Forte emlxs_dfc_get_eventinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6554*fcf3ce44SJohn Forte {
6555*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
6556*fcf3ce44SJohn Forte 	uint32_t size;
6557*fcf3ce44SJohn Forte 	/* uint32_t i; */
6558*fcf3ce44SJohn Forte 	int32_t rval = 0;
6559*fcf3ce44SJohn Forte 	HBA_EVENTINFO *event_buffer = NULL;
6560*fcf3ce44SJohn Forte 	uint32_t event_count = 0;
6561*fcf3ce44SJohn Forte 	uint32_t missed = 0;
6562*fcf3ce44SJohn Forte 
6563*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
6564*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6565*fcf3ce44SJohn Forte 		    "%s: Null buffer1 buffer.",
6566*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6567*fcf3ce44SJohn Forte 
6568*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
6569*fcf3ce44SJohn Forte 	}
6570*fcf3ce44SJohn Forte 	event_count = dfc->buf1_size / sizeof (HBA_EVENTINFO);
6571*fcf3ce44SJohn Forte 
6572*fcf3ce44SJohn Forte 	if (!event_count) {
6573*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6574*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
6575*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6576*fcf3ce44SJohn Forte 
6577*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
6578*fcf3ce44SJohn Forte 	}
6579*fcf3ce44SJohn Forte 	if (!dfc->buf2 || !dfc->buf2_size) {
6580*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6581*fcf3ce44SJohn Forte 		    "%s: Null buffer2 buffer.",
6582*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6583*fcf3ce44SJohn Forte 
6584*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
6585*fcf3ce44SJohn Forte 	}
6586*fcf3ce44SJohn Forte 	if (dfc->buf2_size < sizeof (uint32_t)) {
6587*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6588*fcf3ce44SJohn Forte 		    "%s: Buffer2 too small. (size=%d)",
6589*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
6590*fcf3ce44SJohn Forte 
6591*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
6592*fcf3ce44SJohn Forte 	}
6593*fcf3ce44SJohn Forte 	if (!dfc->buf3 || !dfc->buf3_size) {
6594*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6595*fcf3ce44SJohn Forte 		    "%s: Null buffer3 found.",
6596*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6597*fcf3ce44SJohn Forte 
6598*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
6599*fcf3ce44SJohn Forte 	}
6600*fcf3ce44SJohn Forte 	if (dfc->buf3_size < sizeof (uint32_t)) {
6601*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6602*fcf3ce44SJohn Forte 		    "%s: Buffer3 too small. (size=%d)",
6603*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
6604*fcf3ce44SJohn Forte 
6605*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
6606*fcf3ce44SJohn Forte 	}
6607*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6608*fcf3ce44SJohn Forte 	    "%s called. max=%d",
6609*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd), event_count);
6610*fcf3ce44SJohn Forte 
6611*fcf3ce44SJohn Forte 	size = (event_count * sizeof (HBA_EVENTINFO));
6612*fcf3ce44SJohn Forte 	if (!(event_buffer = (HBA_EVENTINFO *)kmem_zalloc(size, KM_SLEEP))) {
6613*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6614*fcf3ce44SJohn Forte 		    "%s: Unable to allocate buffer. size=%d",
6615*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), size);
6616*fcf3ce44SJohn Forte 
6617*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
6618*fcf3ce44SJohn Forte 	}
6619*fcf3ce44SJohn Forte 	if (emlxs_get_dfc_eventinfo(port, event_buffer,
6620*fcf3ce44SJohn Forte 	    &event_count, &missed) != 0) {
6621*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6622*fcf3ce44SJohn Forte 		    "%s: emlxs_get_dfc_eventinfo failed.",
6623*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6624*fcf3ce44SJohn Forte 
6625*fcf3ce44SJohn Forte 		rval = DFC_DRV_ERROR;
6626*fcf3ce44SJohn Forte 		goto done;
6627*fcf3ce44SJohn Forte 	}
6628*fcf3ce44SJohn Forte 	if (event_count) {
6629*fcf3ce44SJohn Forte 		if (ddi_copyout((void *)event_buffer, dfc->buf1,
6630*fcf3ce44SJohn Forte 		    (event_count * sizeof (HBA_EVENTINFO)), mode) != 0) {
6631*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6632*fcf3ce44SJohn Forte 			    "%s: ddi_copyout failed.",
6633*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
6634*fcf3ce44SJohn Forte 
6635*fcf3ce44SJohn Forte 			rval = DFC_COPYOUT_ERROR;
6636*fcf3ce44SJohn Forte 			goto done;
6637*fcf3ce44SJohn Forte 		}
6638*fcf3ce44SJohn Forte 	}
6639*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&event_count, dfc->buf2,
6640*fcf3ce44SJohn Forte 	    sizeof (uint32_t), mode) != 0) {
6641*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6642*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
6643*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6644*fcf3ce44SJohn Forte 
6645*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
6646*fcf3ce44SJohn Forte 		goto done;
6647*fcf3ce44SJohn Forte 	}
6648*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&missed, dfc->buf3,
6649*fcf3ce44SJohn Forte 	    sizeof (uint32_t), mode) != 0) {
6650*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6651*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
6652*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6653*fcf3ce44SJohn Forte 
6654*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
6655*fcf3ce44SJohn Forte 		goto done;
6656*fcf3ce44SJohn Forte 	}
6657*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6658*fcf3ce44SJohn Forte 	    "%s: events=%d missed=%d new=%d last_id=%d",
6659*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd), event_count,
6660*fcf3ce44SJohn Forte 	    hba->hba_event.missed, hba->hba_event.new,
6661*fcf3ce44SJohn Forte 	    hba->hba_event.last_id);
6662*fcf3ce44SJohn Forte 
6663*fcf3ce44SJohn Forte done:
6664*fcf3ce44SJohn Forte 
6665*fcf3ce44SJohn Forte 	if (event_buffer) {
6666*fcf3ce44SJohn Forte 		kmem_free(event_buffer, size);
6667*fcf3ce44SJohn Forte 	}
6668*fcf3ce44SJohn Forte 	return (rval);
6669*fcf3ce44SJohn Forte 
6670*fcf3ce44SJohn Forte } /* emlxs_dfc_get_eventinfo() */
6671*fcf3ce44SJohn Forte 
6672*fcf3ce44SJohn Forte 
6673*fcf3ce44SJohn Forte static int32_t
6674*fcf3ce44SJohn Forte emlxs_dfc_get_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6675*fcf3ce44SJohn Forte {
6676*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
6677*fcf3ce44SJohn Forte 	uint32_t event;
6678*fcf3ce44SJohn Forte 	uint32_t pid;
6679*fcf3ce44SJohn Forte 	uint32_t sleep;
6680*fcf3ce44SJohn Forte 	uint32_t i;
6681*fcf3ce44SJohn Forte 	int32_t rval = DFC_SUCCESS;
6682*fcf3ce44SJohn Forte 	/* char *bp; */
6683*fcf3ce44SJohn Forte 	emlxs_dfc_event_t *dfc_event;
6684*fcf3ce44SJohn Forte 
6685*fcf3ce44SJohn Forte 	event = dfc->data1;
6686*fcf3ce44SJohn Forte 	pid = dfc->data2;
6687*fcf3ce44SJohn Forte 
6688*fcf3ce44SJohn Forte 	if (!dfc->buf1_size) {
6689*fcf3ce44SJohn Forte 		dfc->buf1 = NULL;
6690*fcf3ce44SJohn Forte 	} else if (!dfc->buf1) {
6691*fcf3ce44SJohn Forte 		dfc->buf1_size = 0;
6692*fcf3ce44SJohn Forte 	}
6693*fcf3ce44SJohn Forte 	if (dfc->buf2_size < sizeof (uint32_t)) {
6694*fcf3ce44SJohn Forte 		dfc->buf2 = NULL;
6695*fcf3ce44SJohn Forte 	} else if (!dfc->buf2) {
6696*fcf3ce44SJohn Forte 		dfc->buf2_size = 0;
6697*fcf3ce44SJohn Forte 	}
6698*fcf3ce44SJohn Forte 	if (dfc->buf3_size < sizeof (uint32_t)) {
6699*fcf3ce44SJohn Forte 		dfc->buf3 = NULL;
6700*fcf3ce44SJohn Forte 	} else if (!dfc->buf3) {
6701*fcf3ce44SJohn Forte 		dfc->buf3_size = 0;
6702*fcf3ce44SJohn Forte 	}
6703*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6704*fcf3ce44SJohn Forte 	    "%s: %s. pid=%d size=%d,%p rcv_size=%d,%p id=%d",
6705*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event),
6706*fcf3ce44SJohn Forte 	    pid, dfc->buf1_size, dfc->buf1, dfc->buf2_size, dfc->buf2,
6707*fcf3ce44SJohn Forte 	    dfc->data3);
6708*fcf3ce44SJohn Forte 
6709*fcf3ce44SJohn Forte 	/* Find the event entry */
6710*fcf3ce44SJohn Forte 	dfc_event = NULL;
6711*fcf3ce44SJohn Forte 	for (i = 0; i < MAX_DFC_EVENTS; i++) {
6712*fcf3ce44SJohn Forte 		dfc_event = &hba->dfc_event[i];
6713*fcf3ce44SJohn Forte 
6714*fcf3ce44SJohn Forte 		if (dfc_event->pid == pid && dfc_event->event == event) {
6715*fcf3ce44SJohn Forte 			break;
6716*fcf3ce44SJohn Forte 		}
6717*fcf3ce44SJohn Forte 	}
6718*fcf3ce44SJohn Forte 
6719*fcf3ce44SJohn Forte 	if (i == MAX_DFC_EVENTS) {
6720*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6721*fcf3ce44SJohn Forte 		    "%s: %s. Event not registered. pid=%d",
6722*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
6723*fcf3ce44SJohn Forte 		    emlxs_dfc_event_xlate(event), pid);
6724*fcf3ce44SJohn Forte 
6725*fcf3ce44SJohn Forte 		return (DFC_ARG_INVALID);
6726*fcf3ce44SJohn Forte 	}
6727*fcf3ce44SJohn Forte 	if (!(hba->log_events & dfc_event->event)) {
6728*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6729*fcf3ce44SJohn Forte 		    "%s: %s. Event not registered. pid=%d",
6730*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
6731*fcf3ce44SJohn Forte 		    emlxs_dfc_event_xlate(event), pid);
6732*fcf3ce44SJohn Forte 
6733*fcf3ce44SJohn Forte 		return (DFC_ARG_INVALID);
6734*fcf3ce44SJohn Forte 	}
6735*fcf3ce44SJohn Forte 	/* Initialize event buffer pointers */
6736*fcf3ce44SJohn Forte 	dfc_event->dataout = dfc->buf1;
6737*fcf3ce44SJohn Forte 	dfc_event->size = dfc->buf1_size;
6738*fcf3ce44SJohn Forte 	dfc_event->last_id = dfc->data3;
6739*fcf3ce44SJohn Forte 	dfc_event->mode = mode;
6740*fcf3ce44SJohn Forte 
6741*fcf3ce44SJohn Forte 	sleep = (dfc->flag & 0x01) ? 1 : 0;
6742*fcf3ce44SJohn Forte 
6743*fcf3ce44SJohn Forte 	if ((rval = emlxs_get_dfc_event(port, dfc_event, sleep))) {
6744*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
6745*fcf3ce44SJohn Forte 		    "%s: %s. Exiting. pid=%d rsize=%d id=%d rval=%d",
6746*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
6747*fcf3ce44SJohn Forte 		    emlxs_dfc_event_xlate(event), pid,
6748*fcf3ce44SJohn Forte 		    dfc_event->size, dfc_event->last_id, rval);
6749*fcf3ce44SJohn Forte 
6750*fcf3ce44SJohn Forte 		return (rval);
6751*fcf3ce44SJohn Forte 	}
6752*fcf3ce44SJohn Forte 	if (dfc->buf2) {
6753*fcf3ce44SJohn Forte 		if (ddi_copyout((void *)&dfc_event->size, dfc->buf2,
6754*fcf3ce44SJohn Forte 		    sizeof (uint32_t), mode) != 0) {
6755*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6756*fcf3ce44SJohn Forte 			    "%s: ddi_copyout failed.",
6757*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
6758*fcf3ce44SJohn Forte 
6759*fcf3ce44SJohn Forte 			return (DFC_COPYOUT_ERROR);
6760*fcf3ce44SJohn Forte 		}
6761*fcf3ce44SJohn Forte 	}
6762*fcf3ce44SJohn Forte 	if (dfc->buf3) {
6763*fcf3ce44SJohn Forte 		if (ddi_copyout((void *)&dfc_event->last_id, dfc->buf3,
6764*fcf3ce44SJohn Forte 		    sizeof (uint32_t), mode) != 0) {
6765*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6766*fcf3ce44SJohn Forte 			    "%s: ddi_copyout failed.",
6767*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
6768*fcf3ce44SJohn Forte 
6769*fcf3ce44SJohn Forte 			return (DFC_COPYOUT_ERROR);
6770*fcf3ce44SJohn Forte 		}
6771*fcf3ce44SJohn Forte 	}
6772*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
6773*fcf3ce44SJohn Forte 	    "%s: %s. Completed. pid=%d rsize=%d id=%d",
6774*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd),
6775*fcf3ce44SJohn Forte 	    emlxs_dfc_event_xlate(event), pid,
6776*fcf3ce44SJohn Forte 	    dfc_event->size, dfc_event->last_id);
6777*fcf3ce44SJohn Forte 
6778*fcf3ce44SJohn Forte 	return (rval);
6779*fcf3ce44SJohn Forte 
6780*fcf3ce44SJohn Forte } /* emlxs_dfc_get_event() */
6781*fcf3ce44SJohn Forte 
6782*fcf3ce44SJohn Forte 
6783*fcf3ce44SJohn Forte 
6784*fcf3ce44SJohn Forte static int32_t
6785*fcf3ce44SJohn Forte emlxs_dfc_get_dump_region(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6786*fcf3ce44SJohn Forte {
6787*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
6788*fcf3ce44SJohn Forte 	uint32_t size;
6789*fcf3ce44SJohn Forte 	uint32_t size_only;
6790*fcf3ce44SJohn Forte 	uint32_t rval = 0;
6791*fcf3ce44SJohn Forte 	uint8_t *buffer = NULL;
6792*fcf3ce44SJohn Forte 	uint8_t *memptr;
6793*fcf3ce44SJohn Forte 	uint32_t *wptr;
6794*fcf3ce44SJohn Forte 
6795*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6796*fcf3ce44SJohn Forte 	    "%s: region=%d size=%d",
6797*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd),
6798*fcf3ce44SJohn Forte 	    dfc->data1, dfc->buf1_size);
6799*fcf3ce44SJohn Forte 
6800*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
6801*fcf3ce44SJohn Forte 		size_only = 1;
6802*fcf3ce44SJohn Forte 		size = (uint32_t)-1;
6803*fcf3ce44SJohn Forte 	} else {
6804*fcf3ce44SJohn Forte 		size_only = 0;
6805*fcf3ce44SJohn Forte 		size = dfc->buf1_size;
6806*fcf3ce44SJohn Forte 	}
6807*fcf3ce44SJohn Forte 
6808*fcf3ce44SJohn Forte 	if (!dfc->buf2 || !dfc->buf2_size) {
6809*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6810*fcf3ce44SJohn Forte 		    "%s: Null buffer2 found.",
6811*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
6812*fcf3ce44SJohn Forte 
6813*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
6814*fcf3ce44SJohn Forte 	}
6815*fcf3ce44SJohn Forte 	if (dfc->buf2_size < sizeof (uint32_t)) {
6816*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6817*fcf3ce44SJohn Forte 		    "%s: Buffer2 too small. (size=%d)",
6818*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
6819*fcf3ce44SJohn Forte 
6820*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
6821*fcf3ce44SJohn Forte 	}
6822*fcf3ce44SJohn Forte 	switch (dfc->data1) {
6823*fcf3ce44SJohn Forte 	case 0:	/* SLI Registers */
6824*fcf3ce44SJohn Forte 
6825*fcf3ce44SJohn Forte 		if (size < (4 * sizeof (uint32_t))) {
6826*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6827*fcf3ce44SJohn Forte 			    "%s: Buffer1 too small. (size=%d)",
6828*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
6829*fcf3ce44SJohn Forte 
6830*fcf3ce44SJohn Forte 			rval = DFC_ARG_TOOSMALL;
6831*fcf3ce44SJohn Forte 			goto done;
6832*fcf3ce44SJohn Forte 		}
6833*fcf3ce44SJohn Forte 		size = (4 * sizeof (uint32_t));
6834*fcf3ce44SJohn Forte 
6835*fcf3ce44SJohn Forte 		if (size_only) {
6836*fcf3ce44SJohn Forte 			break;
6837*fcf3ce44SJohn Forte 		}
6838*fcf3ce44SJohn Forte 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
6839*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6840*fcf3ce44SJohn Forte 			    "%s: Unable to allocate buffer. size=%d",
6841*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
6842*fcf3ce44SJohn Forte 
6843*fcf3ce44SJohn Forte 			rval = DFC_SYSRES_ERROR;
6844*fcf3ce44SJohn Forte 			goto done;
6845*fcf3ce44SJohn Forte 		}
6846*fcf3ce44SJohn Forte 		wptr = (uint32_t *)buffer;
6847*fcf3ce44SJohn Forte 
6848*fcf3ce44SJohn Forte 		wptr[0] = READ_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr));
6849*fcf3ce44SJohn Forte 
6850*fcf3ce44SJohn Forte 		wptr[1] = READ_CSR_REG(hba, FC_CA_REG(hba, hba->csr_addr));
6851*fcf3ce44SJohn Forte 
6852*fcf3ce44SJohn Forte 		wptr[2] = READ_CSR_REG(hba, FC_HS_REG(hba, hba->csr_addr));
6853*fcf3ce44SJohn Forte 
6854*fcf3ce44SJohn Forte 		wptr[3] = READ_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr));
6855*fcf3ce44SJohn Forte 
6856*fcf3ce44SJohn Forte 		break;
6857*fcf3ce44SJohn Forte 
6858*fcf3ce44SJohn Forte 	case 1:	/* SLIM */
6859*fcf3ce44SJohn Forte 
6860*fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
6861*fcf3ce44SJohn Forte 			size = MIN(SLI2_SLIM2_SIZE, size);
6862*fcf3ce44SJohn Forte 		} else {
6863*fcf3ce44SJohn Forte 			size = MIN(4096, size);
6864*fcf3ce44SJohn Forte 		}
6865*fcf3ce44SJohn Forte 
6866*fcf3ce44SJohn Forte 		if (size_only) {
6867*fcf3ce44SJohn Forte 			break;
6868*fcf3ce44SJohn Forte 		}
6869*fcf3ce44SJohn Forte 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
6870*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6871*fcf3ce44SJohn Forte 			    "%s: Unable to allocate buffer. size=%d",
6872*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
6873*fcf3ce44SJohn Forte 
6874*fcf3ce44SJohn Forte 			rval = DFC_SYSRES_ERROR;
6875*fcf3ce44SJohn Forte 			goto done;
6876*fcf3ce44SJohn Forte 		}
6877*fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
6878*fcf3ce44SJohn Forte 			memptr = (uint8_t *)hba->slim2.virt;
6879*fcf3ce44SJohn Forte 			emlxs_pcimem_bcopy((uint32_t *)memptr,
6880*fcf3ce44SJohn Forte 			    (uint32_t *)buffer, size);
6881*fcf3ce44SJohn Forte 		} else {
6882*fcf3ce44SJohn Forte 			memptr = (uint8_t *)hba->slim_addr;
6883*fcf3ce44SJohn Forte 			READ_SLIM_COPY(hba, (uint32_t *)buffer,
6884*fcf3ce44SJohn Forte 			    (uint32_t *)memptr, (size / 4));
6885*fcf3ce44SJohn Forte 		}
6886*fcf3ce44SJohn Forte 
6887*fcf3ce44SJohn Forte 		break;
6888*fcf3ce44SJohn Forte 
6889*fcf3ce44SJohn Forte 	case 2:	/* Port Control Block */
6890*fcf3ce44SJohn Forte 
6891*fcf3ce44SJohn Forte 		if (size < sizeof (PCB)) {
6892*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6893*fcf3ce44SJohn Forte 			    "%s: Buffer1 too small. (size=%d)",
6894*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
6895*fcf3ce44SJohn Forte 
6896*fcf3ce44SJohn Forte 			rval = DFC_ARG_TOOSMALL;
6897*fcf3ce44SJohn Forte 			goto done;
6898*fcf3ce44SJohn Forte 		}
6899*fcf3ce44SJohn Forte 		size = sizeof (PCB);
6900*fcf3ce44SJohn Forte 
6901*fcf3ce44SJohn Forte 		if (size_only) {
6902*fcf3ce44SJohn Forte 			break;
6903*fcf3ce44SJohn Forte 		}
6904*fcf3ce44SJohn Forte 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
6905*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6906*fcf3ce44SJohn Forte 			    "%s: Unable to allocate buffer. size=%d",
6907*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
6908*fcf3ce44SJohn Forte 
6909*fcf3ce44SJohn Forte 			rval = DFC_SYSRES_ERROR;
6910*fcf3ce44SJohn Forte 			goto done;
6911*fcf3ce44SJohn Forte 		}
6912*fcf3ce44SJohn Forte 		memptr = (uint8_t *)&(((SLIM2 *)hba->slim2.virt)->pcb);
6913*fcf3ce44SJohn Forte 		emlxs_pcimem_bcopy((uint32_t *)memptr,
6914*fcf3ce44SJohn Forte 		    (uint32_t *)buffer, size);
6915*fcf3ce44SJohn Forte 
6916*fcf3ce44SJohn Forte 		break;
6917*fcf3ce44SJohn Forte 
6918*fcf3ce44SJohn Forte 	case 3:	/* MailBox */
6919*fcf3ce44SJohn Forte 
6920*fcf3ce44SJohn Forte 		if (size < MAILBOX_CMD_BSIZE) {
6921*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6922*fcf3ce44SJohn Forte 			    "%s: Buffer1 too small. (size=%d)",
6923*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
6924*fcf3ce44SJohn Forte 
6925*fcf3ce44SJohn Forte 			rval = DFC_ARG_TOOSMALL;
6926*fcf3ce44SJohn Forte 			goto done;
6927*fcf3ce44SJohn Forte 		}
6928*fcf3ce44SJohn Forte 		size = MAILBOX_CMD_BSIZE;
6929*fcf3ce44SJohn Forte 
6930*fcf3ce44SJohn Forte 		if (size_only) {
6931*fcf3ce44SJohn Forte 			break;
6932*fcf3ce44SJohn Forte 		}
6933*fcf3ce44SJohn Forte 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
6934*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6935*fcf3ce44SJohn Forte 			    "%s: Unable to allocate buffer. size=%d",
6936*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
6937*fcf3ce44SJohn Forte 
6938*fcf3ce44SJohn Forte 			rval = DFC_SYSRES_ERROR;
6939*fcf3ce44SJohn Forte 			goto done;
6940*fcf3ce44SJohn Forte 		}
6941*fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
6942*fcf3ce44SJohn Forte 			memptr = (uint8_t *)hba->slim2.virt;
6943*fcf3ce44SJohn Forte 			emlxs_pcimem_bcopy((uint32_t *)memptr,
6944*fcf3ce44SJohn Forte 			    (uint32_t *)buffer, size);
6945*fcf3ce44SJohn Forte 		} else {
6946*fcf3ce44SJohn Forte 			memptr = (uint8_t *)hba->slim_addr;
6947*fcf3ce44SJohn Forte 			READ_SLIM_COPY(hba, (uint32_t *)buffer,
6948*fcf3ce44SJohn Forte 			    (uint32_t *)memptr, (size / 4));
6949*fcf3ce44SJohn Forte 		}
6950*fcf3ce44SJohn Forte 
6951*fcf3ce44SJohn Forte 		break;
6952*fcf3ce44SJohn Forte 
6953*fcf3ce44SJohn Forte 	case 4:	/* Host Put/Get pointer array */
6954*fcf3ce44SJohn Forte 
6955*fcf3ce44SJohn Forte 		if (size < MAX_RINGS * sizeof (HGP)) {
6956*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6957*fcf3ce44SJohn Forte 			    "%s: Buffer1 too small. (size=%d)",
6958*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
6959*fcf3ce44SJohn Forte 
6960*fcf3ce44SJohn Forte 			rval = DFC_ARG_TOOSMALL;
6961*fcf3ce44SJohn Forte 			goto done;
6962*fcf3ce44SJohn Forte 		}
6963*fcf3ce44SJohn Forte 		size = MAX_RINGS * sizeof (HGP);
6964*fcf3ce44SJohn Forte 
6965*fcf3ce44SJohn Forte 		if (size_only) {
6966*fcf3ce44SJohn Forte 			break;
6967*fcf3ce44SJohn Forte 		}
6968*fcf3ce44SJohn Forte 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
6969*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6970*fcf3ce44SJohn Forte 			    "%s: Unable to allocate buffer. size=%d",
6971*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
6972*fcf3ce44SJohn Forte 
6973*fcf3ce44SJohn Forte 			rval = DFC_SYSRES_ERROR;
6974*fcf3ce44SJohn Forte 			goto done;
6975*fcf3ce44SJohn Forte 		} {
6976*fcf3ce44SJohn Forte 			memptr = (uint8_t *)hba->slim_addr +
6977*fcf3ce44SJohn Forte 			    hba->hgp_ring_offset;
6978*fcf3ce44SJohn Forte 			READ_SLIM_COPY(hba, (uint32_t *)buffer,
6979*fcf3ce44SJohn Forte 			    (uint32_t *)memptr, (size / 4));
6980*fcf3ce44SJohn Forte 		}
6981*fcf3ce44SJohn Forte 
6982*fcf3ce44SJohn Forte 		break;
6983*fcf3ce44SJohn Forte 
6984*fcf3ce44SJohn Forte 	case 5:	/* Port  Get/Put pointer array */
6985*fcf3ce44SJohn Forte 
6986*fcf3ce44SJohn Forte 		if (size < MAX_RINGS * sizeof (PGP)) {
6987*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6988*fcf3ce44SJohn Forte 			    "%s: Buffer1 too small. (size=%d)",
6989*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
6990*fcf3ce44SJohn Forte 
6991*fcf3ce44SJohn Forte 			rval = DFC_ARG_TOOSMALL;
6992*fcf3ce44SJohn Forte 			goto done;
6993*fcf3ce44SJohn Forte 		}
6994*fcf3ce44SJohn Forte 		size = MAX_RINGS * sizeof (PGP);
6995*fcf3ce44SJohn Forte 
6996*fcf3ce44SJohn Forte 		if (size_only) {
6997*fcf3ce44SJohn Forte 			break;
6998*fcf3ce44SJohn Forte 		}
6999*fcf3ce44SJohn Forte 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
7000*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7001*fcf3ce44SJohn Forte 			    "%s: Unable to allocate buffer. size=%d",
7002*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
7003*fcf3ce44SJohn Forte 
7004*fcf3ce44SJohn Forte 			rval = DFC_SYSRES_ERROR;
7005*fcf3ce44SJohn Forte 			goto done;
7006*fcf3ce44SJohn Forte 		}
7007*fcf3ce44SJohn Forte 		memptr = (uint8_t *)((SLIM2 *)hba->slim2.virt)->mbx.us.s2.port;
7008*fcf3ce44SJohn Forte 		emlxs_pcimem_bcopy((uint32_t *)memptr,
7009*fcf3ce44SJohn Forte 		    (uint32_t *)buffer, size);
7010*fcf3ce44SJohn Forte 
7011*fcf3ce44SJohn Forte 		break;
7012*fcf3ce44SJohn Forte 
7013*fcf3ce44SJohn Forte 	case 6:	/* Command/Response Ring */
7014*fcf3ce44SJohn Forte 
7015*fcf3ce44SJohn Forte 		if (size < SLI_IOCB_MAX_SIZE) {
7016*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7017*fcf3ce44SJohn Forte 			    "%s: Buffer1 too small. (size=%d)",
7018*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
7019*fcf3ce44SJohn Forte 
7020*fcf3ce44SJohn Forte 			rval = DFC_ARG_TOOSMALL;
7021*fcf3ce44SJohn Forte 			goto done;
7022*fcf3ce44SJohn Forte 		}
7023*fcf3ce44SJohn Forte 		size = SLI_IOCB_MAX_SIZE;
7024*fcf3ce44SJohn Forte 
7025*fcf3ce44SJohn Forte 		if (size_only) {
7026*fcf3ce44SJohn Forte 			break;
7027*fcf3ce44SJohn Forte 		}
7028*fcf3ce44SJohn Forte 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
7029*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7030*fcf3ce44SJohn Forte 			    "%s: Unable to allocate buffer. size=%d",
7031*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
7032*fcf3ce44SJohn Forte 
7033*fcf3ce44SJohn Forte 			rval = DFC_SYSRES_ERROR;
7034*fcf3ce44SJohn Forte 			goto done;
7035*fcf3ce44SJohn Forte 		}
7036*fcf3ce44SJohn Forte 		memptr = (uint8_t *)((SLIM2 *)hba->slim2.virt)->IOCBs;
7037*fcf3ce44SJohn Forte 		emlxs_pcimem_bcopy((uint32_t *)memptr,
7038*fcf3ce44SJohn Forte 		    (uint32_t *)buffer, size);
7039*fcf3ce44SJohn Forte 
7040*fcf3ce44SJohn Forte 		break;
7041*fcf3ce44SJohn Forte 
7042*fcf3ce44SJohn Forte 	case 7:	/* All driver specific structures */
7043*fcf3ce44SJohn Forte 
7044*fcf3ce44SJohn Forte 		if (size < sizeof (emlxs_hba_t)) {
7045*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7046*fcf3ce44SJohn Forte 			    "%s: Buffer1 too small. (size=%d)",
7047*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
7048*fcf3ce44SJohn Forte 
7049*fcf3ce44SJohn Forte 			rval = DFC_ARG_TOOSMALL;
7050*fcf3ce44SJohn Forte 			goto done;
7051*fcf3ce44SJohn Forte 		}
7052*fcf3ce44SJohn Forte 		size = sizeof (emlxs_hba_t);
7053*fcf3ce44SJohn Forte 
7054*fcf3ce44SJohn Forte 		if (size_only) {
7055*fcf3ce44SJohn Forte 			break;
7056*fcf3ce44SJohn Forte 		}
7057*fcf3ce44SJohn Forte 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
7058*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7059*fcf3ce44SJohn Forte 			    "%s: Unable to allocate buffer. size=%d",
7060*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd), size);
7061*fcf3ce44SJohn Forte 
7062*fcf3ce44SJohn Forte 			rval = DFC_SYSRES_ERROR;
7063*fcf3ce44SJohn Forte 			goto done;
7064*fcf3ce44SJohn Forte 		}
7065*fcf3ce44SJohn Forte 		memptr = (uint8_t *)hba;
7066*fcf3ce44SJohn Forte 		bcopy((void *)memptr, (void *)buffer, size);
7067*fcf3ce44SJohn Forte 
7068*fcf3ce44SJohn Forte 		break;
7069*fcf3ce44SJohn Forte 
7070*fcf3ce44SJohn Forte 	default:
7071*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7072*fcf3ce44SJohn Forte 		    "%s: Invalid id.  id=%d",
7073*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->data1);
7074*fcf3ce44SJohn Forte 
7075*fcf3ce44SJohn Forte 		rval = DFC_ARG_INVALID;
7076*fcf3ce44SJohn Forte 	}
7077*fcf3ce44SJohn Forte 
7078*fcf3ce44SJohn Forte 	if (rval == 0) {
7079*fcf3ce44SJohn Forte 		if (buffer) {
7080*fcf3ce44SJohn Forte 			if (ddi_copyout((void *)buffer, (void *)dfc->buf1,
7081*fcf3ce44SJohn Forte 			    size, mode) != 0) {
7082*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7083*fcf3ce44SJohn Forte 				    "%s: ddi_copyout failed.",
7084*fcf3ce44SJohn Forte 				    emlxs_dfc_xlate(dfc->cmd));
7085*fcf3ce44SJohn Forte 
7086*fcf3ce44SJohn Forte 				rval = DFC_COPYOUT_ERROR;
7087*fcf3ce44SJohn Forte 				goto done;
7088*fcf3ce44SJohn Forte 			}
7089*fcf3ce44SJohn Forte 		}
7090*fcf3ce44SJohn Forte 		if (ddi_copyout((void *)&size, (void *)dfc->buf2,
7091*fcf3ce44SJohn Forte 		    sizeof (uint32_t), mode) != 0) {
7092*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7093*fcf3ce44SJohn Forte 			    "%s: ddi_copyout failed.",
7094*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
7095*fcf3ce44SJohn Forte 
7096*fcf3ce44SJohn Forte 			rval = DFC_COPYOUT_ERROR;
7097*fcf3ce44SJohn Forte 			goto done;
7098*fcf3ce44SJohn Forte 		}
7099*fcf3ce44SJohn Forte 	}
7100*fcf3ce44SJohn Forte done:
7101*fcf3ce44SJohn Forte 
7102*fcf3ce44SJohn Forte 	if (buffer) {
7103*fcf3ce44SJohn Forte 		kmem_free(buffer, size);
7104*fcf3ce44SJohn Forte 	}
7105*fcf3ce44SJohn Forte 	return (rval);
7106*fcf3ce44SJohn Forte 
7107*fcf3ce44SJohn Forte } /* emlxs_dfc_get_dump_region() */
7108*fcf3ce44SJohn Forte 
7109*fcf3ce44SJohn Forte 
7110*fcf3ce44SJohn Forte 
7111*fcf3ce44SJohn Forte /*ARGSUSED*/
7112*fcf3ce44SJohn Forte static int32_t
7113*fcf3ce44SJohn Forte emlxs_dfc_loopback_mode(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7114*fcf3ce44SJohn Forte {
7115*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
7116*fcf3ce44SJohn Forte 	MAILBOXQ *mbq = NULL;
7117*fcf3ce44SJohn Forte 	MAILBOX *mb = NULL;
7118*fcf3ce44SJohn Forte 	uint32_t rval = DFC_SUCCESS;
7119*fcf3ce44SJohn Forte 	uint32_t i;
7120*fcf3ce44SJohn Forte 	uint32_t timeout;
7121*fcf3ce44SJohn Forte 	uint32_t topology;
7122*fcf3ce44SJohn Forte 	uint32_t new_mode;
7123*fcf3ce44SJohn Forte 	NODELIST *ndlp;
7124*fcf3ce44SJohn Forte 
7125*fcf3ce44SJohn Forte 	/* Reinitialize the link */
7126*fcf3ce44SJohn Forte 	switch (dfc->flag) {
7127*fcf3ce44SJohn Forte 	case 0:	/* Disable */
7128*fcf3ce44SJohn Forte 
7129*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7130*fcf3ce44SJohn Forte 		    "%s: Disabling Loopback.",
7131*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7132*fcf3ce44SJohn Forte 
7133*fcf3ce44SJohn Forte 		if (!(hba->flag & FC_LOOPBACK_MODE)) {
7134*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7135*fcf3ce44SJohn Forte 			    "%s: Loopback already disabled.",
7136*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
7137*fcf3ce44SJohn Forte 
7138*fcf3ce44SJohn Forte 			return (0);
7139*fcf3ce44SJohn Forte 		}
7140*fcf3ce44SJohn Forte 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
7141*fcf3ce44SJohn Forte 
7142*fcf3ce44SJohn Forte 		return (0);
7143*fcf3ce44SJohn Forte 
7144*fcf3ce44SJohn Forte 	case 1:	/* Internal loopback */
7145*fcf3ce44SJohn Forte 		new_mode = FC_ILB_MODE;
7146*fcf3ce44SJohn Forte 		topology = FLAGS_LOCAL_LB;
7147*fcf3ce44SJohn Forte 
7148*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7149*fcf3ce44SJohn Forte 		    "%s: Enabling ILB.",
7150*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7151*fcf3ce44SJohn Forte 
7152*fcf3ce44SJohn Forte 		/* Check if mode already set */
7153*fcf3ce44SJohn Forte 		if ((hba->flag & FC_ILB_MODE)) {
7154*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7155*fcf3ce44SJohn Forte 			    "%s: ILB mode already enabled.",
7156*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
7157*fcf3ce44SJohn Forte 
7158*fcf3ce44SJohn Forte 			return (0);
7159*fcf3ce44SJohn Forte 		}
7160*fcf3ce44SJohn Forte 		break;
7161*fcf3ce44SJohn Forte 
7162*fcf3ce44SJohn Forte 	case 2:	/* External loopback */
7163*fcf3ce44SJohn Forte 		new_mode = FC_ELB_MODE;
7164*fcf3ce44SJohn Forte 		topology = FLAGS_TOPOLOGY_MODE_LOOP;
7165*fcf3ce44SJohn Forte 
7166*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7167*fcf3ce44SJohn Forte 		    "%s: Enabling ELB.",
7168*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7169*fcf3ce44SJohn Forte 
7170*fcf3ce44SJohn Forte 		/* Check if mode already set */
7171*fcf3ce44SJohn Forte 		if ((hba->flag & FC_ELB_MODE)) {
7172*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7173*fcf3ce44SJohn Forte 			    "%s: ELB mode already enabled.",
7174*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
7175*fcf3ce44SJohn Forte 
7176*fcf3ce44SJohn Forte 			return (0);
7177*fcf3ce44SJohn Forte 		}
7178*fcf3ce44SJohn Forte 		break;
7179*fcf3ce44SJohn Forte 
7180*fcf3ce44SJohn Forte 	default:
7181*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7182*fcf3ce44SJohn Forte 		    "%s: Invalid loopback mode. (mode=%x)",
7183*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->flag);
7184*fcf3ce44SJohn Forte 
7185*fcf3ce44SJohn Forte 		return (DFC_ARG_INVALID);
7186*fcf3ce44SJohn Forte 	}
7187*fcf3ce44SJohn Forte 
7188*fcf3ce44SJohn Forte 	/* Make sure adapter is online */
7189*fcf3ce44SJohn Forte 	if (emlxs_online(hba)) {
7190*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7191*fcf3ce44SJohn Forte 		    "%s: Unable to bring adapter online.",
7192*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7193*fcf3ce44SJohn Forte 
7194*fcf3ce44SJohn Forte 		return (DFC_OFFLINE_ERROR);
7195*fcf3ce44SJohn Forte 	}
7196*fcf3ce44SJohn Forte 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP)) == 0) {
7197*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7198*fcf3ce44SJohn Forte 		    "%s: Unable to allocate mailbox buffer.",
7199*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7200*fcf3ce44SJohn Forte 
7201*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
7202*fcf3ce44SJohn Forte 	}
7203*fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbq;
7204*fcf3ce44SJohn Forte 
7205*fcf3ce44SJohn Forte 	/* Take the link down */
7206*fcf3ce44SJohn Forte 	emlxs_mb_down_link(hba, mb);
7207*fcf3ce44SJohn Forte 
7208*fcf3ce44SJohn Forte 	rval = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
7209*fcf3ce44SJohn Forte 
7210*fcf3ce44SJohn Forte 	if (rval == MBX_TIMEOUT) {
7211*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7212*fcf3ce44SJohn Forte 		    "%s: Mailbox timed out. cmd=%x",
7213*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
7214*fcf3ce44SJohn Forte 
7215*fcf3ce44SJohn Forte 		rval = DFC_TIMEOUT;
7216*fcf3ce44SJohn Forte 		goto done;
7217*fcf3ce44SJohn Forte 	}
7218*fcf3ce44SJohn Forte 	if (rval) {
7219*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7220*fcf3ce44SJohn Forte 		    "%s: %s failed. status=%x",
7221*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
7222*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
7223*fcf3ce44SJohn Forte 
7224*fcf3ce44SJohn Forte 		rval = DFC_IO_ERROR;
7225*fcf3ce44SJohn Forte 		goto done;
7226*fcf3ce44SJohn Forte 	}
7227*fcf3ce44SJohn Forte 	/* Reinitialize the link */
7228*fcf3ce44SJohn Forte 	emlxs_mb_init_link(hba, mb, topology, 0);
7229*fcf3ce44SJohn Forte 
7230*fcf3ce44SJohn Forte 	/* Set the loopback mode and timer */
7231*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
7232*fcf3ce44SJohn Forte 	hba->flag |= new_mode;
7233*fcf3ce44SJohn Forte 	hba->loopback_tics = hba->timer_tics + emlxs_loopback_tmo;
7234*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
7235*fcf3ce44SJohn Forte 
7236*fcf3ce44SJohn Forte 	rval = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
7237*fcf3ce44SJohn Forte 
7238*fcf3ce44SJohn Forte 	if (rval == MBX_TIMEOUT) {
7239*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7240*fcf3ce44SJohn Forte 		    "%s: Mailbox timed out. cmd=%x",
7241*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
7242*fcf3ce44SJohn Forte 
7243*fcf3ce44SJohn Forte 		rval = DFC_TIMEOUT;
7244*fcf3ce44SJohn Forte 		goto done;
7245*fcf3ce44SJohn Forte 	}
7246*fcf3ce44SJohn Forte 	if (rval) {
7247*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7248*fcf3ce44SJohn Forte 		    "%s: %s failed. status=%x",
7249*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
7250*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
7251*fcf3ce44SJohn Forte 
7252*fcf3ce44SJohn Forte 		rval = DFC_IO_ERROR;
7253*fcf3ce44SJohn Forte 		goto done;
7254*fcf3ce44SJohn Forte 	}
7255*fcf3ce44SJohn Forte 	/* Wait for adapter to come online */
7256*fcf3ce44SJohn Forte 	timeout = dfc->data1;
7257*fcf3ce44SJohn Forte 	if (!timeout) {
7258*fcf3ce44SJohn Forte 		timeout = 60;
7259*fcf3ce44SJohn Forte 	}
7260*fcf3ce44SJohn Forte 	i = 0;
7261*fcf3ce44SJohn Forte 	while ((hba->state < FC_LINK_UP) && (hba->state != FC_ERROR)) {
7262*fcf3ce44SJohn Forte 		delay(drv_usectohz(500000));
7263*fcf3ce44SJohn Forte 		i++;
7264*fcf3ce44SJohn Forte 
7265*fcf3ce44SJohn Forte 		if (i == timeout) {
7266*fcf3ce44SJohn Forte 			rval = DFC_TIMEOUT;
7267*fcf3ce44SJohn Forte 
7268*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7269*fcf3ce44SJohn Forte 			    "%s: Linkup timeout.",
7270*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
7271*fcf3ce44SJohn Forte 
7272*fcf3ce44SJohn Forte 			goto done;
7273*fcf3ce44SJohn Forte 		}
7274*fcf3ce44SJohn Forte 	}
7275*fcf3ce44SJohn Forte 
7276*fcf3ce44SJohn Forte 
7277*fcf3ce44SJohn Forte 	/* Create host node */
7278*fcf3ce44SJohn Forte 	if (emlxs_mb_reg_did(port, port->did, (SERV_PARM *)&hba->sparam,
7279*fcf3ce44SJohn Forte 	    NULL, NULL, NULL)) {
7280*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7281*fcf3ce44SJohn Forte 		    "%s: Unable to register host node.",
7282*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7283*fcf3ce44SJohn Forte 
7284*fcf3ce44SJohn Forte 		rval = DFC_DRV_ERROR;
7285*fcf3ce44SJohn Forte 		goto done;
7286*fcf3ce44SJohn Forte 	}
7287*fcf3ce44SJohn Forte 	i = 0;
7288*fcf3ce44SJohn Forte 	do {
7289*fcf3ce44SJohn Forte 		if (i++ > 300) {
7290*fcf3ce44SJohn Forte 			break;
7291*fcf3ce44SJohn Forte 		}
7292*fcf3ce44SJohn Forte 		delay(drv_usectohz(100000));
7293*fcf3ce44SJohn Forte 
7294*fcf3ce44SJohn Forte 	} while (!(ndlp = emlxs_node_find_did(port, port->did)));
7295*fcf3ce44SJohn Forte 
7296*fcf3ce44SJohn Forte 	if (!ndlp) {
7297*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7298*fcf3ce44SJohn Forte 		    "%s: Unable to create host node.",
7299*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7300*fcf3ce44SJohn Forte 
7301*fcf3ce44SJohn Forte 		rval = DFC_DRV_ERROR;
7302*fcf3ce44SJohn Forte 		goto done;
7303*fcf3ce44SJohn Forte 	}
7304*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7305*fcf3ce44SJohn Forte 	    "%s: Node created. node=%p",
7306*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd), ndlp);
7307*fcf3ce44SJohn Forte 
7308*fcf3ce44SJohn Forte 
7309*fcf3ce44SJohn Forte 	/* Create host XRI */
7310*fcf3ce44SJohn Forte 	(void) emlxs_create_xri(port, &hba->ring[FC_CT_RING], ndlp);
7311*fcf3ce44SJohn Forte 
7312*fcf3ce44SJohn Forte 	i = 0;
7313*fcf3ce44SJohn Forte 	do {
7314*fcf3ce44SJohn Forte 		if (i++ > 300) {
7315*fcf3ce44SJohn Forte 			break;
7316*fcf3ce44SJohn Forte 		}
7317*fcf3ce44SJohn Forte 		delay(drv_usectohz(100000));
7318*fcf3ce44SJohn Forte 
7319*fcf3ce44SJohn Forte 	} while (!ndlp->nlp_Xri);
7320*fcf3ce44SJohn Forte 
7321*fcf3ce44SJohn Forte 	if (!ndlp->nlp_Xri) {
7322*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7323*fcf3ce44SJohn Forte 		    "%s: Unable to create XRI.",
7324*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7325*fcf3ce44SJohn Forte 
7326*fcf3ce44SJohn Forte 		rval = DFC_DRV_ERROR;
7327*fcf3ce44SJohn Forte 		goto done;
7328*fcf3ce44SJohn Forte 	}
7329*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7330*fcf3ce44SJohn Forte 	    "%s: XRI created. xri=%x",
7331*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd), ndlp->nlp_Xri);
7332*fcf3ce44SJohn Forte 
7333*fcf3ce44SJohn Forte 
7334*fcf3ce44SJohn Forte done:
7335*fcf3ce44SJohn Forte 
7336*fcf3ce44SJohn Forte 	/* Free allocated mbox memory */
7337*fcf3ce44SJohn Forte 	if (mbq) {
7338*fcf3ce44SJohn Forte 		kmem_free(mbq, sizeof (MAILBOXQ));
7339*fcf3ce44SJohn Forte 	}
7340*fcf3ce44SJohn Forte 	if (rval) {
7341*fcf3ce44SJohn Forte 		/* Reset the adapter */
7342*fcf3ce44SJohn Forte 		(void) emlxs_reset(port, FC_FCA_RESET);
7343*fcf3ce44SJohn Forte 	}
7344*fcf3ce44SJohn Forte 	return (rval);
7345*fcf3ce44SJohn Forte 
7346*fcf3ce44SJohn Forte } /* emlxs_dfc_loopback_mode() */
7347*fcf3ce44SJohn Forte 
7348*fcf3ce44SJohn Forte 
7349*fcf3ce44SJohn Forte static int32_t
7350*fcf3ce44SJohn Forte emlxs_dfc_loopback_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7351*fcf3ce44SJohn Forte {
7352*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
7353*fcf3ce44SJohn Forte 	uint32_t rval = 0;
7354*fcf3ce44SJohn Forte 	/* uint32_t i; */
7355*fcf3ce44SJohn Forte 	NODELIST *ndlp;
7356*fcf3ce44SJohn Forte 	clock_t timeout;
7357*fcf3ce44SJohn Forte 	/* uint32_t tics_timeout; */
7358*fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
7359*fcf3ce44SJohn Forte 	SLI_CT_REQUEST *CtCmd;
7360*fcf3ce44SJohn Forte 	uint16_t CtRsp;
7361*fcf3ce44SJohn Forte 
7362*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
7363*fcf3ce44SJohn Forte 	if (!(hba->flag & FC_LOOPBACK_MODE)) {
7364*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
7365*fcf3ce44SJohn Forte 
7366*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7367*fcf3ce44SJohn Forte 		    "%s: Adapter not in loopback mode.",
7368*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7369*fcf3ce44SJohn Forte 
7370*fcf3ce44SJohn Forte 		rval = DFC_DRV_ERROR;
7371*fcf3ce44SJohn Forte 		goto done;
7372*fcf3ce44SJohn Forte 	}
7373*fcf3ce44SJohn Forte 	hba->loopback_tics = hba->timer_tics + emlxs_loopback_tmo;
7374*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
7375*fcf3ce44SJohn Forte 
7376*fcf3ce44SJohn Forte 	if (!(hba->flag & FC_ONLINE_MODE)) {
7377*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7378*fcf3ce44SJohn Forte 		    "%s: Adapter offline.",
7379*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7380*fcf3ce44SJohn Forte 
7381*fcf3ce44SJohn Forte 		rval = DFC_OFFLINE_ERROR;
7382*fcf3ce44SJohn Forte 		goto done;
7383*fcf3ce44SJohn Forte 	}
7384*fcf3ce44SJohn Forte 	if (hba->state < FC_LINK_UP) {
7385*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7386*fcf3ce44SJohn Forte 		    "%s: Link not up.",
7387*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7388*fcf3ce44SJohn Forte 
7389*fcf3ce44SJohn Forte 		rval = DFC_OFFLINE_ERROR;
7390*fcf3ce44SJohn Forte 		goto done;
7391*fcf3ce44SJohn Forte 	}
7392*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
7393*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7394*fcf3ce44SJohn Forte 		    "%s: NULL buffer1 found.",
7395*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7396*fcf3ce44SJohn Forte 
7397*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
7398*fcf3ce44SJohn Forte 		goto done;
7399*fcf3ce44SJohn Forte 	}
7400*fcf3ce44SJohn Forte 	if (!dfc->buf2 || !dfc->buf2_size) {
7401*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7402*fcf3ce44SJohn Forte 		    "%s: NULL buffer2 found.",
7403*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7404*fcf3ce44SJohn Forte 
7405*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
7406*fcf3ce44SJohn Forte 		goto done;
7407*fcf3ce44SJohn Forte 	}
7408*fcf3ce44SJohn Forte 	if (dfc->buf1_size > MAX_CT_PAYLOAD) {
7409*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7410*fcf3ce44SJohn Forte 		    "%s: Buffer1 too large. (size=%d)",
7411*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7412*fcf3ce44SJohn Forte 
7413*fcf3ce44SJohn Forte 		rval = DFC_ARG_TOOBIG;
7414*fcf3ce44SJohn Forte 		goto done;
7415*fcf3ce44SJohn Forte 	}
7416*fcf3ce44SJohn Forte 	/* Check if we have a node for ourselves */
7417*fcf3ce44SJohn Forte 	ndlp = emlxs_node_find_did(port, port->did);
7418*fcf3ce44SJohn Forte 
7419*fcf3ce44SJohn Forte 	if (!ndlp) {
7420*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7421*fcf3ce44SJohn Forte 		    "%s: Host node not found.",
7422*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7423*fcf3ce44SJohn Forte 
7424*fcf3ce44SJohn Forte 		rval = DFC_ARG_INVALID;
7425*fcf3ce44SJohn Forte 		goto done;
7426*fcf3ce44SJohn Forte 	}
7427*fcf3ce44SJohn Forte 	if (!ndlp->nlp_Xri) {
7428*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7429*fcf3ce44SJohn Forte 		    "%s: Host XRI not found.",
7430*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7431*fcf3ce44SJohn Forte 
7432*fcf3ce44SJohn Forte 		rval = DFC_DRV_ERROR;
7433*fcf3ce44SJohn Forte 		goto done;
7434*fcf3ce44SJohn Forte 	}
7435*fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, dfc->buf1_size + 16,
7436*fcf3ce44SJohn Forte 	    dfc->buf2_size + 16, 0, KM_SLEEP))) {
7437*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7438*fcf3ce44SJohn Forte 		    "%s: Unable to allocate pkt.",
7439*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7440*fcf3ce44SJohn Forte 
7441*fcf3ce44SJohn Forte 		rval = DFC_SYSRES_ERROR;
7442*fcf3ce44SJohn Forte 		goto done;
7443*fcf3ce44SJohn Forte 	}
7444*fcf3ce44SJohn Forte 	CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd;
7445*fcf3ce44SJohn Forte 	CtRsp = SLI_CT_LOOPBACK;
7446*fcf3ce44SJohn Forte 	CtCmd->CommandResponse.bits.CmdRsp = SWAP_DATA16(CtRsp);
7447*fcf3ce44SJohn Forte 
7448*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)&CtCmd->un.data,
7449*fcf3ce44SJohn Forte 	    dfc->buf1_size, mode) != 0) {
7450*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7451*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
7452*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7453*fcf3ce44SJohn Forte 
7454*fcf3ce44SJohn Forte 		rval = DFC_COPYIN_ERROR;
7455*fcf3ce44SJohn Forte 		goto done;
7456*fcf3ce44SJohn Forte 	}
7457*fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
7458*fcf3ce44SJohn Forte 	pkt->pkt_timeout = 2 * hba->fc_ratov;
7459*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
7460*fcf3ce44SJohn Forte 	pkt->pkt_comp = NULL;
7461*fcf3ce44SJohn Forte 
7462*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.d_id = port->did;
7463*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = FC_SOL_CTL;
7464*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.s_id = port->did;
7465*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_CT_TYPE;
7466*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.f_ctl = 0;
7467*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
7468*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
7469*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
7470*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
7471*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = ndlp->nlp_Xri;
7472*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
7473*fcf3ce44SJohn Forte 
7474*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PKT_LOCK);
7475*fcf3ce44SJohn Forte 	timeout = emlxs_timeout(hba, (pkt->pkt_timeout + 15));
7476*fcf3ce44SJohn Forte 
7477*fcf3ce44SJohn Forte 	if (hba->loopback_pkt) {
7478*fcf3ce44SJohn Forte 		rval = 0;
7479*fcf3ce44SJohn Forte 		while ((rval != -1) && hba->loopback_pkt) {
7480*fcf3ce44SJohn Forte 			rval = cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK,
7481*fcf3ce44SJohn Forte 			    timeout);
7482*fcf3ce44SJohn Forte 		}
7483*fcf3ce44SJohn Forte 
7484*fcf3ce44SJohn Forte 		if (rval == -1) {
7485*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PKT_LOCK);
7486*fcf3ce44SJohn Forte 
7487*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7488*fcf3ce44SJohn Forte 			    "Loopback busy timeout.");
7489*fcf3ce44SJohn Forte 			rval = DFC_TIMEOUT;
7490*fcf3ce44SJohn Forte 			goto done;
7491*fcf3ce44SJohn Forte 		}
7492*fcf3ce44SJohn Forte 	}
7493*fcf3ce44SJohn Forte 	hba->loopback_pkt = (void *)pkt;
7494*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PKT_LOCK);
7495*fcf3ce44SJohn Forte 
7496*fcf3ce44SJohn Forte 	/* Send polled command */
7497*fcf3ce44SJohn Forte 	if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) {
7498*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7499*fcf3ce44SJohn Forte 		    "Pkt Transport error. ret=%x state=%x",
7500*fcf3ce44SJohn Forte 		    rval, pkt->pkt_state);
7501*fcf3ce44SJohn Forte 
7502*fcf3ce44SJohn Forte 		rval = DFC_IO_ERROR;
7503*fcf3ce44SJohn Forte 		goto done;
7504*fcf3ce44SJohn Forte 	}
7505*fcf3ce44SJohn Forte 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
7506*fcf3ce44SJohn Forte 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
7507*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7508*fcf3ce44SJohn Forte 			    "Pkt Transport error. Pkt Timeout.");
7509*fcf3ce44SJohn Forte 			rval = DFC_TIMEOUT;
7510*fcf3ce44SJohn Forte 		} else {
7511*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7512*fcf3ce44SJohn Forte 			    "Pkt Transport error. state=%x",
7513*fcf3ce44SJohn Forte 			    pkt->pkt_state);
7514*fcf3ce44SJohn Forte 			rval = DFC_IO_ERROR;
7515*fcf3ce44SJohn Forte 		}
7516*fcf3ce44SJohn Forte 		goto done;
7517*fcf3ce44SJohn Forte 	}
7518*fcf3ce44SJohn Forte 	/* Wait for sequence completion */
7519*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PKT_LOCK);
7520*fcf3ce44SJohn Forte 	rval = 0;
7521*fcf3ce44SJohn Forte 	while ((rval != -1) && !(pkt->pkt_tran_flags & FC_TRAN_COMPLETED)) {
7522*fcf3ce44SJohn Forte 		rval = cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK, timeout);
7523*fcf3ce44SJohn Forte 	}
7524*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PKT_LOCK);
7525*fcf3ce44SJohn Forte 
7526*fcf3ce44SJohn Forte 	if (rval == -1) {
7527*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7528*fcf3ce44SJohn Forte 		    "Loopback sequence timeout.");
7529*fcf3ce44SJohn Forte 
7530*fcf3ce44SJohn Forte 		rval = DFC_TIMEOUT;
7531*fcf3ce44SJohn Forte 		goto done;
7532*fcf3ce44SJohn Forte 	}
7533*fcf3ce44SJohn Forte 	CtCmd = (SLI_CT_REQUEST *)pkt->pkt_resp;
7534*fcf3ce44SJohn Forte 
7535*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&CtCmd->un.data, (void *)dfc->buf2,
7536*fcf3ce44SJohn Forte 	    dfc->buf2_size, mode) != 0) {
7537*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7538*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
7539*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7540*fcf3ce44SJohn Forte 
7541*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
7542*fcf3ce44SJohn Forte 		goto done;
7543*fcf3ce44SJohn Forte 	}
7544*fcf3ce44SJohn Forte 	rval = 0;
7545*fcf3ce44SJohn Forte 
7546*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7547*fcf3ce44SJohn Forte 	    "%s: Test completed.",
7548*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
7549*fcf3ce44SJohn Forte 
7550*fcf3ce44SJohn Forte done:
7551*fcf3ce44SJohn Forte 
7552*fcf3ce44SJohn Forte 	if (rval) {
7553*fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PKT_LOCK);
7554*fcf3ce44SJohn Forte 		if (pkt && (hba->loopback_pkt == pkt)) {
7555*fcf3ce44SJohn Forte 			hba->loopback_pkt = NULL;
7556*fcf3ce44SJohn Forte 		}
7557*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PKT_LOCK);
7558*fcf3ce44SJohn Forte 
7559*fcf3ce44SJohn Forte 		/* Reset the adapter */
7560*fcf3ce44SJohn Forte 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
7561*fcf3ce44SJohn Forte 	}
7562*fcf3ce44SJohn Forte 	if (pkt) {
7563*fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
7564*fcf3ce44SJohn Forte 	}
7565*fcf3ce44SJohn Forte 	return (rval);
7566*fcf3ce44SJohn Forte 
7567*fcf3ce44SJohn Forte } /* emlxs_dfc_loopback_test() */
7568*fcf3ce44SJohn Forte 
7569*fcf3ce44SJohn Forte 
7570*fcf3ce44SJohn Forte extern int32_t
7571*fcf3ce44SJohn Forte emlxs_dfc_handle_event(emlxs_hba_t *hba, RING *rp, IOCBQ * iocbq)
7572*fcf3ce44SJohn Forte {
7573*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
7574*fcf3ce44SJohn Forte 	IOCB *cmd;
7575*fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
7576*fcf3ce44SJohn Forte 	/* NODELIST *ndlp; */
7577*fcf3ce44SJohn Forte 
7578*fcf3ce44SJohn Forte 	cmd = &iocbq->iocb;
7579*fcf3ce44SJohn Forte 
7580*fcf3ce44SJohn Forte 	HBASTATS.CtEvent++;
7581*fcf3ce44SJohn Forte 
7582*fcf3ce44SJohn Forte 	sbp = (emlxs_buf_t *)iocbq->sbp;
7583*fcf3ce44SJohn Forte 
7584*fcf3ce44SJohn Forte 	if (!sbp) {
7585*fcf3ce44SJohn Forte 		HBASTATS.CtStray++;
7586*fcf3ce44SJohn Forte 
7587*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7588*fcf3ce44SJohn Forte 		    "Stray interrupt. cmd=0x%x iotag=0x%x"
7589*fcf3ce44SJohn Forte 		    " status=0x%x perr=0x%x",
7590*fcf3ce44SJohn Forte 		    (uint32_t)cmd->ulpCommand,
7591*fcf3ce44SJohn Forte 		    (uint32_t)cmd->ulpIoTag,
7592*fcf3ce44SJohn Forte 		    cmd->ulpStatus, cmd->un.ulpWord[4]);
7593*fcf3ce44SJohn Forte 
7594*fcf3ce44SJohn Forte 		return (DFC_ARG_INVALID);
7595*fcf3ce44SJohn Forte 	}
7596*fcf3ce44SJohn Forte 	if (rp->ringno != FC_CT_RING) {
7597*fcf3ce44SJohn Forte 		HBASTATS.CtStray++;
7598*fcf3ce44SJohn Forte 
7599*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7600*fcf3ce44SJohn Forte 		    "CT Event: Invalid ring: ring=%d iocbq=%p",
7601*fcf3ce44SJohn Forte 		    rp->ringno, iocbq);
7602*fcf3ce44SJohn Forte 
7603*fcf3ce44SJohn Forte 		return (DFC_ARG_INVALID);
7604*fcf3ce44SJohn Forte 	}
7605*fcf3ce44SJohn Forte 	switch (cmd->ulpCommand) {
7606*fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE_CR:
7607*fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE64_CR:
7608*fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE_CX:
7609*fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE64_CX:
7610*fcf3ce44SJohn Forte 
7611*fcf3ce44SJohn Forte 		HBASTATS.CtCmdCompleted++;
7612*fcf3ce44SJohn Forte 
7613*fcf3ce44SJohn Forte 		if (cmd->ulpStatus == 0) {
7614*fcf3ce44SJohn Forte 			HBASTATS.CtCmdGood++;
7615*fcf3ce44SJohn Forte 
7616*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7617*fcf3ce44SJohn Forte 			    "XMIT_SEQUENCE comp: status=0x%x",
7618*fcf3ce44SJohn Forte 			    cmd->ulpStatus);
7619*fcf3ce44SJohn Forte 		} else {
7620*fcf3ce44SJohn Forte 			HBASTATS.CtCmdError++;
7621*fcf3ce44SJohn Forte 
7622*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7623*fcf3ce44SJohn Forte 			    "XMIT_SEQUENCE comp: status=0x%x [%08x,%08x]",
7624*fcf3ce44SJohn Forte 			    cmd->ulpStatus, cmd->un.ulpWord[4],
7625*fcf3ce44SJohn Forte 			    cmd->un.ulpWord[5]);
7626*fcf3ce44SJohn Forte 		}
7627*fcf3ce44SJohn Forte 
7628*fcf3ce44SJohn Forte 		emlxs_pkt_complete(sbp, cmd->ulpStatus,
7629*fcf3ce44SJohn Forte 		    cmd->un.grsp.perr.statLocalError, 1);
7630*fcf3ce44SJohn Forte 
7631*fcf3ce44SJohn Forte 		break;
7632*fcf3ce44SJohn Forte 
7633*fcf3ce44SJohn Forte 	default:
7634*fcf3ce44SJohn Forte 
7635*fcf3ce44SJohn Forte 		HBASTATS.CtStray++;
7636*fcf3ce44SJohn Forte 
7637*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7638*fcf3ce44SJohn Forte 		    "Invalid iocb: cmd=0x%x",
7639*fcf3ce44SJohn Forte 		    cmd->ulpCommand);
7640*fcf3ce44SJohn Forte 
7641*fcf3ce44SJohn Forte 		emlxs_pkt_complete(sbp, cmd->ulpStatus,
7642*fcf3ce44SJohn Forte 		    cmd->un.grsp.perr.statLocalError, 1);
7643*fcf3ce44SJohn Forte 
7644*fcf3ce44SJohn Forte 		break;
7645*fcf3ce44SJohn Forte 
7646*fcf3ce44SJohn Forte 	}	/* switch(cmd->ulpCommand) */
7647*fcf3ce44SJohn Forte 
7648*fcf3ce44SJohn Forte 	return (0);
7649*fcf3ce44SJohn Forte 
7650*fcf3ce44SJohn Forte } /* emlxs_dfc_handle_event() */
7651*fcf3ce44SJohn Forte 
7652*fcf3ce44SJohn Forte 
7653*fcf3ce44SJohn Forte /*ARGSUSED*/
7654*fcf3ce44SJohn Forte extern int
7655*fcf3ce44SJohn Forte emlxs_dfc_handle_unsol_req(emlxs_port_t *port, RING *rp,
7656*fcf3ce44SJohn Forte 	IOCBQ *iocbq, MATCHMAP *mp, uint32_t size)
7657*fcf3ce44SJohn Forte {
7658*fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
7659*fcf3ce44SJohn Forte 	IOCB *iocb;
7660*fcf3ce44SJohn Forte 	uint8_t *bp;
7661*fcf3ce44SJohn Forte 	/* dfc_t *dfc; */
7662*fcf3ce44SJohn Forte 	fc_packet_t *pkt;
7663*fcf3ce44SJohn Forte 
7664*fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
7665*fcf3ce44SJohn Forte 	bp = (uint8_t *)mp->virt;
7666*fcf3ce44SJohn Forte 
7667*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7668*fcf3ce44SJohn Forte 	    "CT Receive: cmd=%x status=0x%x ",
7669*fcf3ce44SJohn Forte 	    iocb->ulpCommand, iocb->ulpStatus);
7670*fcf3ce44SJohn Forte 
7671*fcf3ce44SJohn Forte 	/*
7672*fcf3ce44SJohn Forte 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, "CT Receive:
7673*fcf3ce44SJohn Forte 	 * payload=%p size=%d [%02x,%02x, %02x, %02x]", bp, size, bp[0],
7674*fcf3ce44SJohn Forte 	 * bp[1], bp[2],bp[3]);
7675*fcf3ce44SJohn Forte 	 */
7676*fcf3ce44SJohn Forte 
7677*fcf3ce44SJohn Forte 	/* Return payload */
7678*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PKT_LOCK);
7679*fcf3ce44SJohn Forte 	if (hba->loopback_pkt) {
7680*fcf3ce44SJohn Forte 		pkt = (fc_packet_t *)hba->loopback_pkt;
7681*fcf3ce44SJohn Forte 		hba->loopback_pkt = NULL;
7682*fcf3ce44SJohn Forte 
7683*fcf3ce44SJohn Forte 		size = MIN(size, pkt->pkt_rsplen);
7684*fcf3ce44SJohn Forte 		bcopy(bp, pkt->pkt_resp, size);
7685*fcf3ce44SJohn Forte 		pkt->pkt_tran_flags |= FC_TRAN_COMPLETED;
7686*fcf3ce44SJohn Forte 
7687*fcf3ce44SJohn Forte 		cv_broadcast(&EMLXS_PKT_CV);
7688*fcf3ce44SJohn Forte 	}
7689*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PKT_LOCK);
7690*fcf3ce44SJohn Forte 
7691*fcf3ce44SJohn Forte 	return (0);
7692*fcf3ce44SJohn Forte 
7693*fcf3ce44SJohn Forte } /* emlxs_dfc_handle_unsol_req() */
7694*fcf3ce44SJohn Forte 
7695*fcf3ce44SJohn Forte 
7696*fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
7697*fcf3ce44SJohn Forte 
7698*fcf3ce44SJohn Forte static int32_t
7699*fcf3ce44SJohn Forte emlxs_dfc_init_auth(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7700*fcf3ce44SJohn Forte {
7701*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
7702*fcf3ce44SJohn Forte 	uint8_t lwwpn[8];
7703*fcf3ce44SJohn Forte 	uint8_t rwwpn[8];
7704*fcf3ce44SJohn Forte 	int32_t rval = 0;
7705*fcf3ce44SJohn Forte 
7706*fcf3ce44SJohn Forte 	/*
7707*fcf3ce44SJohn Forte 	 * dfc.cmd = EMLXS_INIT_AUTH; dfc.buf1_size = 8; dfc.buf1
7708*fcf3ce44SJohn Forte 	 * = lwwpn; dfc.buf2_size = 8; dfc.buf2 = rwwpn;
7709*fcf3ce44SJohn Forte 	 */
7710*fcf3ce44SJohn Forte 
7711*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7712*fcf3ce44SJohn Forte 	    "%s requested.",
7713*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
7714*fcf3ce44SJohn Forte 
7715*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
7716*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7717*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
7718*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7719*fcf3ce44SJohn Forte 
7720*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
7721*fcf3ce44SJohn Forte 	}
7722*fcf3ce44SJohn Forte 	if (dfc->buf1_size < 8) {
7723*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7724*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
7725*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7726*fcf3ce44SJohn Forte 
7727*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
7728*fcf3ce44SJohn Forte 	}
7729*fcf3ce44SJohn Forte 	if (!dfc->buf2 || !dfc->buf2_size) {
7730*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7731*fcf3ce44SJohn Forte 		    "%s: Null buffer2 found.",
7732*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7733*fcf3ce44SJohn Forte 
7734*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
7735*fcf3ce44SJohn Forte 	}
7736*fcf3ce44SJohn Forte 	if (dfc->buf2_size < 8) {
7737*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7738*fcf3ce44SJohn Forte 		    "%s: Buffer2 too small. (size=%d)",
7739*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7740*fcf3ce44SJohn Forte 
7741*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
7742*fcf3ce44SJohn Forte 	}
7743*fcf3ce44SJohn Forte 	/* Read the lwwpn */
7744*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)&lwwpn,
7745*fcf3ce44SJohn Forte 	    8, mode) != 0) {
7746*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7747*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
7748*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7749*fcf3ce44SJohn Forte 
7750*fcf3ce44SJohn Forte 		return (DFC_COPYIN_ERROR);
7751*fcf3ce44SJohn Forte 	}
7752*fcf3ce44SJohn Forte 	/* Read the rwwpn */
7753*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf2, (void *)&rwwpn,
7754*fcf3ce44SJohn Forte 	    8, mode) != 0) {
7755*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7756*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
7757*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7758*fcf3ce44SJohn Forte 
7759*fcf3ce44SJohn Forte 		return (DFC_COPYIN_ERROR);
7760*fcf3ce44SJohn Forte 	}
7761*fcf3ce44SJohn Forte 	/* Initiate authentication here */
7762*fcf3ce44SJohn Forte 	rval = emlxs_dhc_init_auth(hba, lwwpn, rwwpn);
7763*fcf3ce44SJohn Forte 
7764*fcf3ce44SJohn Forte 	return (rval);
7765*fcf3ce44SJohn Forte 
7766*fcf3ce44SJohn Forte } /* emlxs_dfc_init_auth() */
7767*fcf3ce44SJohn Forte 
7768*fcf3ce44SJohn Forte 
7769*fcf3ce44SJohn Forte static int32_t
7770*fcf3ce44SJohn Forte emlxs_dfc_get_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7771*fcf3ce44SJohn Forte {
7772*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
7773*fcf3ce44SJohn Forte 	dfc_fcsp_config_t fcsp_config;
7774*fcf3ce44SJohn Forte 	uint32_t rval = DFC_SUCCESS;
7775*fcf3ce44SJohn Forte 
7776*fcf3ce44SJohn Forte 	/*
7777*fcf3ce44SJohn Forte 	 * dfc.cmd = EMLXS_GET_AUTH_CFG; dfc.buf1_size =
7778*fcf3ce44SJohn Forte 	 * sizeof(dfc_fcsp_config_t); dfc.buf1 = config;
7779*fcf3ce44SJohn Forte 	 */
7780*fcf3ce44SJohn Forte 
7781*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7782*fcf3ce44SJohn Forte 	    "%s requested.",
7783*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
7784*fcf3ce44SJohn Forte 
7785*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
7786*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7787*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
7788*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7789*fcf3ce44SJohn Forte 
7790*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
7791*fcf3ce44SJohn Forte 	}
7792*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (dfc_fcsp_config_t)) {
7793*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7794*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
7795*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7796*fcf3ce44SJohn Forte 
7797*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
7798*fcf3ce44SJohn Forte 	}
7799*fcf3ce44SJohn Forte 	/* Read the fcsp_config */
7800*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)&fcsp_config,
7801*fcf3ce44SJohn Forte 	    sizeof (dfc_fcsp_config_t), mode) != 0) {
7802*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7803*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
7804*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7805*fcf3ce44SJohn Forte 
7806*fcf3ce44SJohn Forte 		return (DFC_COPYIN_ERROR);
7807*fcf3ce44SJohn Forte 	}
7808*fcf3ce44SJohn Forte 	if ((rval = emlxs_dhc_get_auth_cfg(hba, &fcsp_config)) != 0) {
7809*fcf3ce44SJohn Forte 		return (rval);
7810*fcf3ce44SJohn Forte 	}
7811*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&fcsp_config, (void *)dfc->buf1,
7812*fcf3ce44SJohn Forte 	    sizeof (dfc_fcsp_config_t), mode) != 0) {
7813*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7814*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
7815*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7816*fcf3ce44SJohn Forte 
7817*fcf3ce44SJohn Forte 	}
7818*fcf3ce44SJohn Forte 	return (0);
7819*fcf3ce44SJohn Forte 
7820*fcf3ce44SJohn Forte } /* emlxs_dfc_get_auth_cfg() */
7821*fcf3ce44SJohn Forte 
7822*fcf3ce44SJohn Forte 
7823*fcf3ce44SJohn Forte 
7824*fcf3ce44SJohn Forte static int32_t
7825*fcf3ce44SJohn Forte emlxs_dfc_set_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7826*fcf3ce44SJohn Forte {
7827*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
7828*fcf3ce44SJohn Forte 	dfc_fcsp_config_t fcsp_config;
7829*fcf3ce44SJohn Forte 	dfc_password_t dfc_pwd;
7830*fcf3ce44SJohn Forte 	uint32_t rval = DFC_SUCCESS;
7831*fcf3ce44SJohn Forte 
7832*fcf3ce44SJohn Forte 
7833*fcf3ce44SJohn Forte 	/*
7834*fcf3ce44SJohn Forte 	 * dfc.cmd = EMLXS_SET_AUTH_CFG; dfc.flag =
7835*fcf3ce44SJohn Forte 	 * EMLXS_AUTH_CFG_ADD; dfc.buf1_size = sizeof(dfc_fcsp_config_t);
7836*fcf3ce44SJohn Forte 	 * dfc.buf1 = config; dfc.buf2_size = sizeof(dfc_password_t);
7837*fcf3ce44SJohn Forte 	 * dfc.buf2 = password;
7838*fcf3ce44SJohn Forte 	 */
7839*fcf3ce44SJohn Forte 
7840*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7841*fcf3ce44SJohn Forte 	    "%s requested.",
7842*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
7843*fcf3ce44SJohn Forte 
7844*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
7845*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7846*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
7847*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7848*fcf3ce44SJohn Forte 
7849*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
7850*fcf3ce44SJohn Forte 	}
7851*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (dfc_fcsp_config_t)) {
7852*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7853*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
7854*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7855*fcf3ce44SJohn Forte 
7856*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
7857*fcf3ce44SJohn Forte 	}
7858*fcf3ce44SJohn Forte 	if (!dfc->buf2 || !dfc->buf2_size) {
7859*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7860*fcf3ce44SJohn Forte 		    "%s: Null buffer2 found.",
7861*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7862*fcf3ce44SJohn Forte 
7863*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
7864*fcf3ce44SJohn Forte 	}
7865*fcf3ce44SJohn Forte 	if (dfc->buf2_size < sizeof (dfc_password_t)) {
7866*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7867*fcf3ce44SJohn Forte 		    "%s: Buffer2 too small. (size=%d)",
7868*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7869*fcf3ce44SJohn Forte 
7870*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
7871*fcf3ce44SJohn Forte 	}
7872*fcf3ce44SJohn Forte 	/* Read the fcsp_config */
7873*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)&fcsp_config,
7874*fcf3ce44SJohn Forte 	    sizeof (dfc_fcsp_config_t), mode) != 0) {
7875*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7876*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
7877*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7878*fcf3ce44SJohn Forte 
7879*fcf3ce44SJohn Forte 		return (DFC_COPYIN_ERROR);
7880*fcf3ce44SJohn Forte 	}
7881*fcf3ce44SJohn Forte 	/* Read the password */
7882*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf2, (void *)&dfc_pwd,
7883*fcf3ce44SJohn Forte 	    sizeof (dfc_password_t), mode) != 0) {
7884*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7885*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
7886*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7887*fcf3ce44SJohn Forte 
7888*fcf3ce44SJohn Forte 		return (DFC_COPYIN_ERROR);
7889*fcf3ce44SJohn Forte 	}
7890*fcf3ce44SJohn Forte 	switch (dfc->flag) {
7891*fcf3ce44SJohn Forte 	case EMLXS_AUTH_CFG_ADD:
7892*fcf3ce44SJohn Forte 		rval = emlxs_dhc_add_auth_cfg(hba, &fcsp_config, &dfc_pwd);
7893*fcf3ce44SJohn Forte 		break;
7894*fcf3ce44SJohn Forte 
7895*fcf3ce44SJohn Forte 	case EMLXS_AUTH_CFG_DELETE:
7896*fcf3ce44SJohn Forte 		rval = emlxs_dhc_delete_auth_cfg(hba, &fcsp_config, &dfc_pwd);
7897*fcf3ce44SJohn Forte 		break;
7898*fcf3ce44SJohn Forte 	}
7899*fcf3ce44SJohn Forte 
7900*fcf3ce44SJohn Forte 	if (rval) {
7901*fcf3ce44SJohn Forte 		return (rval);
7902*fcf3ce44SJohn Forte 	}
7903*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&fcsp_config, (void *)dfc->buf1,
7904*fcf3ce44SJohn Forte 	    sizeof (dfc_fcsp_config_t), mode) != 0) {
7905*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7906*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
7907*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7908*fcf3ce44SJohn Forte 
7909*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
7910*fcf3ce44SJohn Forte 	}
7911*fcf3ce44SJohn Forte 	return (0);
7912*fcf3ce44SJohn Forte 
7913*fcf3ce44SJohn Forte } /* emlxs_dfc_set_auth_cfg() */
7914*fcf3ce44SJohn Forte 
7915*fcf3ce44SJohn Forte 
7916*fcf3ce44SJohn Forte 
7917*fcf3ce44SJohn Forte static int32_t
7918*fcf3ce44SJohn Forte emlxs_dfc_get_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7919*fcf3ce44SJohn Forte {
7920*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
7921*fcf3ce44SJohn Forte 	dfc_auth_password_t dfc_pwd;
7922*fcf3ce44SJohn Forte 	uint32_t rval = DFC_SUCCESS;
7923*fcf3ce44SJohn Forte 
7924*fcf3ce44SJohn Forte 
7925*fcf3ce44SJohn Forte 	/*
7926*fcf3ce44SJohn Forte 	 * dfc.cmd = EMLXS_GET_AUTH_PASSWORD; dfc.buf1_size =
7927*fcf3ce44SJohn Forte 	 * sizeof(dfc_auth_password_t); dfc.buf1 = auth_password;
7928*fcf3ce44SJohn Forte 	 */
7929*fcf3ce44SJohn Forte 
7930*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7931*fcf3ce44SJohn Forte 	    "%s requested.",
7932*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
7933*fcf3ce44SJohn Forte 
7934*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
7935*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7936*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
7937*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7938*fcf3ce44SJohn Forte 
7939*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
7940*fcf3ce44SJohn Forte 	}
7941*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (dfc_auth_password_t)) {
7942*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7943*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
7944*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7945*fcf3ce44SJohn Forte 
7946*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
7947*fcf3ce44SJohn Forte 	}
7948*fcf3ce44SJohn Forte 	/* Read the auth password */
7949*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)&dfc_pwd,
7950*fcf3ce44SJohn Forte 	    sizeof (dfc_auth_password_t), mode) != 0) {
7951*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7952*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
7953*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7954*fcf3ce44SJohn Forte 
7955*fcf3ce44SJohn Forte 		return (DFC_COPYIN_ERROR);
7956*fcf3ce44SJohn Forte 	}
7957*fcf3ce44SJohn Forte 	if ((rval = emlxs_dhc_get_auth_key(hba, &dfc_pwd)) != 0) {
7958*fcf3ce44SJohn Forte 		return (rval);
7959*fcf3ce44SJohn Forte 	}
7960*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&dfc_pwd, (void *)dfc->buf1,
7961*fcf3ce44SJohn Forte 	    sizeof (dfc_auth_password_t), mode) != 0) {
7962*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7963*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
7964*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7965*fcf3ce44SJohn Forte 
7966*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
7967*fcf3ce44SJohn Forte 	}
7968*fcf3ce44SJohn Forte 	return (0);
7969*fcf3ce44SJohn Forte 
7970*fcf3ce44SJohn Forte } /* emlxs_dfc_get_auth_pwd() */
7971*fcf3ce44SJohn Forte 
7972*fcf3ce44SJohn Forte 
7973*fcf3ce44SJohn Forte static int32_t
7974*fcf3ce44SJohn Forte emlxs_dfc_set_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7975*fcf3ce44SJohn Forte {
7976*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
7977*fcf3ce44SJohn Forte 	dfc_auth_password_t dfc_pwd;
7978*fcf3ce44SJohn Forte 	uint32_t rval = DFC_SUCCESS;
7979*fcf3ce44SJohn Forte 
7980*fcf3ce44SJohn Forte 	/*
7981*fcf3ce44SJohn Forte 	 * dfc.cmd = EMLXS_SET_AUTH_PASSWORD; dfc.buf1_size =
7982*fcf3ce44SJohn Forte 	 * sizeof(dfc_auth_password_t); dfc.buf1 = auth_password;
7983*fcf3ce44SJohn Forte 	 */
7984*fcf3ce44SJohn Forte 
7985*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7986*fcf3ce44SJohn Forte 	    "%s requested.",
7987*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
7988*fcf3ce44SJohn Forte 
7989*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
7990*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7991*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
7992*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
7993*fcf3ce44SJohn Forte 
7994*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
7995*fcf3ce44SJohn Forte 	}
7996*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (dfc_auth_password_t)) {
7997*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7998*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (size=%d)",
7999*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
8000*fcf3ce44SJohn Forte 
8001*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
8002*fcf3ce44SJohn Forte 	}
8003*fcf3ce44SJohn Forte 	/* Read the auth password */
8004*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)&dfc_pwd,
8005*fcf3ce44SJohn Forte 	    sizeof (dfc_auth_password_t), mode) != 0) {
8006*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8007*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
8008*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8009*fcf3ce44SJohn Forte 
8010*fcf3ce44SJohn Forte 		return (DFC_COPYIN_ERROR);
8011*fcf3ce44SJohn Forte 	}
8012*fcf3ce44SJohn Forte 	if ((rval = emlxs_dhc_set_auth_key(hba, &dfc_pwd))) {
8013*fcf3ce44SJohn Forte 		return (rval);
8014*fcf3ce44SJohn Forte 	}
8015*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&dfc_pwd, (void *)dfc->buf1,
8016*fcf3ce44SJohn Forte 	    sizeof (dfc_auth_password_t), mode) != 0) {
8017*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8018*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
8019*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8020*fcf3ce44SJohn Forte 
8021*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
8022*fcf3ce44SJohn Forte 	}
8023*fcf3ce44SJohn Forte 	return (0);
8024*fcf3ce44SJohn Forte 
8025*fcf3ce44SJohn Forte } /* emlxs_dfc_set_auth_pwd() */
8026*fcf3ce44SJohn Forte 
8027*fcf3ce44SJohn Forte 
8028*fcf3ce44SJohn Forte static int32_t
8029*fcf3ce44SJohn Forte emlxs_dfc_get_auth_status(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8030*fcf3ce44SJohn Forte {
8031*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
8032*fcf3ce44SJohn Forte 	dfc_auth_status_t fcsp_status;
8033*fcf3ce44SJohn Forte 	uint32_t rval = DFC_SUCCESS;
8034*fcf3ce44SJohn Forte 
8035*fcf3ce44SJohn Forte 	/*
8036*fcf3ce44SJohn Forte 	 * dfc.cmd = EMLXS_GET_AUTH_STATUS; dfc.buf1_size =
8037*fcf3ce44SJohn Forte 	 * sizeof(dfc_auth_status_t); dfc.buf1 = status;
8038*fcf3ce44SJohn Forte 	 */
8039*fcf3ce44SJohn Forte 
8040*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
8041*fcf3ce44SJohn Forte 	    "%s requested.",
8042*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
8043*fcf3ce44SJohn Forte 
8044*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
8045*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8046*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
8047*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8048*fcf3ce44SJohn Forte 
8049*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
8050*fcf3ce44SJohn Forte 	}
8051*fcf3ce44SJohn Forte 	if (dfc->buf1_size < sizeof (dfc_auth_status_t)) {
8052*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8053*fcf3ce44SJohn Forte 		    "%s: Buffer too small. (size=%d)",
8054*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
8055*fcf3ce44SJohn Forte 
8056*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
8057*fcf3ce44SJohn Forte 	}
8058*fcf3ce44SJohn Forte 	/* Read the fcsp_config */
8059*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)&fcsp_status,
8060*fcf3ce44SJohn Forte 	    sizeof (dfc_auth_status_t), mode) != 0) {
8061*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8062*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
8063*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8064*fcf3ce44SJohn Forte 
8065*fcf3ce44SJohn Forte 		return (DFC_COPYIN_ERROR);
8066*fcf3ce44SJohn Forte 	}
8067*fcf3ce44SJohn Forte 	if ((rval = emlxs_dhc_get_auth_status(hba, &fcsp_status)) != 0) {
8068*fcf3ce44SJohn Forte 		return (rval);
8069*fcf3ce44SJohn Forte 	}
8070*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&fcsp_status, (void *)dfc->buf1,
8071*fcf3ce44SJohn Forte 	    sizeof (dfc_auth_status_t), mode) != 0) {
8072*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8073*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
8074*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8075*fcf3ce44SJohn Forte 
8076*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
8077*fcf3ce44SJohn Forte 	}
8078*fcf3ce44SJohn Forte 	return (0);
8079*fcf3ce44SJohn Forte 
8080*fcf3ce44SJohn Forte } /* emlxs_dfc_get_auth_status() */
8081*fcf3ce44SJohn Forte 
8082*fcf3ce44SJohn Forte 
8083*fcf3ce44SJohn Forte static int32_t
8084*fcf3ce44SJohn Forte emlxs_dfc_get_auth_cfg_table(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8085*fcf3ce44SJohn Forte {
8086*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
8087*fcf3ce44SJohn Forte 	dfc_fcsp_config_t *fcsp_cfg;
8088*fcf3ce44SJohn Forte 	uint32_t count;
8089*fcf3ce44SJohn Forte 	uint32_t size;
8090*fcf3ce44SJohn Forte 	uint32_t rval = DFC_SUCCESS;
8091*fcf3ce44SJohn Forte 	/* uint32_t count_sent = 0; */
8092*fcf3ce44SJohn Forte 
8093*fcf3ce44SJohn Forte 	/*
8094*fcf3ce44SJohn Forte 	 * dfc.cmd = EMLXS_GET_AUTH_CFG_TABLE; dfc.buf1_size = size;
8095*fcf3ce44SJohn Forte 	 * dfc.buf1 = fcsp_cfg; dfc.buf2_size = sizeof(uint32_t);
8096*fcf3ce44SJohn Forte 	 * dfc.buf2 = &count;
8097*fcf3ce44SJohn Forte 	 */
8098*fcf3ce44SJohn Forte 
8099*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
8100*fcf3ce44SJohn Forte 	    "%s requested.",
8101*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
8102*fcf3ce44SJohn Forte 
8103*fcf3ce44SJohn Forte 	/* Lock cfg table while we do this */
8104*fcf3ce44SJohn Forte 	/* This prevents the table from changing while we get a copy */
8105*fcf3ce44SJohn Forte 	mutex_enter(&hba->auth_lock);
8106*fcf3ce44SJohn Forte 
8107*fcf3ce44SJohn Forte 	if (!dfc->buf2 || !dfc->buf2_size) {
8108*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8109*fcf3ce44SJohn Forte 		    "%s: Null buffer2 found.",
8110*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8111*fcf3ce44SJohn Forte 
8112*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8113*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
8114*fcf3ce44SJohn Forte 	}
8115*fcf3ce44SJohn Forte 	if (dfc->buf2_size < sizeof (uint32_t)) {
8116*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8117*fcf3ce44SJohn Forte 		    "%s: Buffer2 too small. (size=%d)",
8118*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
8119*fcf3ce44SJohn Forte 
8120*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8121*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
8122*fcf3ce44SJohn Forte 	}
8123*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&hba->auth_cfg_count, (void *)dfc->buf2,
8124*fcf3ce44SJohn Forte 	    sizeof (uint32_t), mode) != 0) {
8125*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8126*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed for table count. count=%d",
8127*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), hba->auth_cfg_count);
8128*fcf3ce44SJohn Forte 
8129*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8130*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
8131*fcf3ce44SJohn Forte 	}
8132*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
8133*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8134*fcf3ce44SJohn Forte 		return (DFC_SUCCESS);
8135*fcf3ce44SJohn Forte 	}
8136*fcf3ce44SJohn Forte 	/* Check table size */
8137*fcf3ce44SJohn Forte 	count = dfc->buf1_size / sizeof (dfc_fcsp_config_t);
8138*fcf3ce44SJohn Forte 	if (count < hba->auth_cfg_count) {
8139*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8140*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (%d < %d)",
8141*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), count,
8142*fcf3ce44SJohn Forte 		    hba->auth_cfg_count);
8143*fcf3ce44SJohn Forte 
8144*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8145*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
8146*fcf3ce44SJohn Forte 	}
8147*fcf3ce44SJohn Forte 	size = hba->auth_cfg_count * sizeof (dfc_fcsp_config_t);
8148*fcf3ce44SJohn Forte 	if (!(fcsp_cfg = (dfc_fcsp_config_t *)kmem_zalloc(size, KM_SLEEP))) {
8149*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8150*fcf3ce44SJohn Forte 		    "%s: Unable to allocate table buffer.",
8151*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8152*fcf3ce44SJohn Forte 
8153*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8154*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
8155*fcf3ce44SJohn Forte 	}
8156*fcf3ce44SJohn Forte 	if ((rval = emlxs_dhc_get_auth_cfg_table(hba, fcsp_cfg)) != 0) {
8157*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8158*fcf3ce44SJohn Forte 		kmem_free(fcsp_cfg, size);
8159*fcf3ce44SJohn Forte 		return (rval);
8160*fcf3ce44SJohn Forte 	}
8161*fcf3ce44SJohn Forte 	mutex_exit(&hba->auth_lock);
8162*fcf3ce44SJohn Forte 
8163*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)fcsp_cfg, (void *)dfc->buf1,
8164*fcf3ce44SJohn Forte 	    size, mode) != 0) {
8165*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8166*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
8167*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8168*fcf3ce44SJohn Forte 
8169*fcf3ce44SJohn Forte 		kmem_free(fcsp_cfg, size);
8170*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
8171*fcf3ce44SJohn Forte 	}
8172*fcf3ce44SJohn Forte 	kmem_free(fcsp_cfg, size);
8173*fcf3ce44SJohn Forte 	return (0);
8174*fcf3ce44SJohn Forte 
8175*fcf3ce44SJohn Forte } /* emlxs_dfc_get_auth_cfg_table() */
8176*fcf3ce44SJohn Forte 
8177*fcf3ce44SJohn Forte 
8178*fcf3ce44SJohn Forte static int32_t
8179*fcf3ce44SJohn Forte emlxs_dfc_get_auth_key_table(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8180*fcf3ce44SJohn Forte {
8181*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
8182*fcf3ce44SJohn Forte 	dfc_auth_password_t *auth_pwd;
8183*fcf3ce44SJohn Forte 	uint32_t count;
8184*fcf3ce44SJohn Forte 	uint32_t size;
8185*fcf3ce44SJohn Forte 	uint32_t rval = DFC_SUCCESS;
8186*fcf3ce44SJohn Forte 	/* uint32_t count_sent = 0; */
8187*fcf3ce44SJohn Forte 
8188*fcf3ce44SJohn Forte 	/*
8189*fcf3ce44SJohn Forte 	 * dfc.cmd = EMLXS_GET_AUTH_KEY_TABLE; dfc.buf1_size = size;
8190*fcf3ce44SJohn Forte 	 * dfc.buf1 = auth_pwd; dfc.buf2_size = sizeof(uint32_t);
8191*fcf3ce44SJohn Forte 	 * dfc.buf2 = &count;
8192*fcf3ce44SJohn Forte 	 */
8193*fcf3ce44SJohn Forte 
8194*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
8195*fcf3ce44SJohn Forte 	    "%s requested.",
8196*fcf3ce44SJohn Forte 	    emlxs_dfc_xlate(dfc->cmd));
8197*fcf3ce44SJohn Forte 
8198*fcf3ce44SJohn Forte 	/* Lock cfg table while we do this */
8199*fcf3ce44SJohn Forte 	/* This prevents the table from changing while we get a copy */
8200*fcf3ce44SJohn Forte 	mutex_enter(&hba->auth_lock);
8201*fcf3ce44SJohn Forte 
8202*fcf3ce44SJohn Forte 	if (!dfc->buf2 || !dfc->buf2_size) {
8203*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8204*fcf3ce44SJohn Forte 		    "%s: Null buffer2 found.",
8205*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8206*fcf3ce44SJohn Forte 
8207*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8208*fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
8209*fcf3ce44SJohn Forte 	}
8210*fcf3ce44SJohn Forte 	if (dfc->buf2_size < sizeof (uint32_t)) {
8211*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8212*fcf3ce44SJohn Forte 		    "%s: Buffer2 too small. (size=%d)",
8213*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
8214*fcf3ce44SJohn Forte 
8215*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8216*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
8217*fcf3ce44SJohn Forte 	}
8218*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&hba->auth_key_count, (void *)dfc->buf2,
8219*fcf3ce44SJohn Forte 	    sizeof (uint32_t), mode) != 0) {
8220*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8221*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed for table count. count=%d",
8222*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), hba->auth_key_count);
8223*fcf3ce44SJohn Forte 
8224*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8225*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
8226*fcf3ce44SJohn Forte 	}
8227*fcf3ce44SJohn Forte 	if (!dfc->buf1 || !dfc->buf1_size) {
8228*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8229*fcf3ce44SJohn Forte 		return (DFC_SUCCESS);
8230*fcf3ce44SJohn Forte 	}
8231*fcf3ce44SJohn Forte 	/* Check table size */
8232*fcf3ce44SJohn Forte 	count = dfc->buf1_size / sizeof (dfc_auth_password_t);
8233*fcf3ce44SJohn Forte 	if (count < hba->auth_key_count) {
8234*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8235*fcf3ce44SJohn Forte 		    "%s: Buffer1 too small. (%d < %d)",
8236*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd), count,
8237*fcf3ce44SJohn Forte 		    hba->auth_key_count);
8238*fcf3ce44SJohn Forte 
8239*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8240*fcf3ce44SJohn Forte 		return (DFC_ARG_TOOSMALL);
8241*fcf3ce44SJohn Forte 	}
8242*fcf3ce44SJohn Forte 	size = hba->auth_key_count * sizeof (dfc_auth_password_t);
8243*fcf3ce44SJohn Forte 	if (!(auth_pwd = (dfc_auth_password_t *)kmem_zalloc(size, KM_SLEEP))) {
8244*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8245*fcf3ce44SJohn Forte 		    "%s: Unable to allocate table buffer.",
8246*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8247*fcf3ce44SJohn Forte 
8248*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8249*fcf3ce44SJohn Forte 		return (DFC_SYSRES_ERROR);
8250*fcf3ce44SJohn Forte 	}
8251*fcf3ce44SJohn Forte 	if ((rval = emlxs_dhc_get_auth_key_table(hba, auth_pwd)) != 0) {
8252*fcf3ce44SJohn Forte 		mutex_exit(&hba->auth_lock);
8253*fcf3ce44SJohn Forte 		kmem_free(auth_pwd, size);
8254*fcf3ce44SJohn Forte 		return (rval);
8255*fcf3ce44SJohn Forte 	}
8256*fcf3ce44SJohn Forte 	mutex_exit(&hba->auth_lock);
8257*fcf3ce44SJohn Forte 
8258*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)auth_pwd, (void *)dfc->buf1,
8259*fcf3ce44SJohn Forte 	    size, mode) != 0) {
8260*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8261*fcf3ce44SJohn Forte 		    "%s: ddi_copyout failed.",
8262*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8263*fcf3ce44SJohn Forte 
8264*fcf3ce44SJohn Forte 		kmem_free(auth_pwd, size);
8265*fcf3ce44SJohn Forte 		return (DFC_COPYOUT_ERROR);
8266*fcf3ce44SJohn Forte 	}
8267*fcf3ce44SJohn Forte 	kmem_free(auth_pwd, size);
8268*fcf3ce44SJohn Forte 	return (0);
8269*fcf3ce44SJohn Forte 
8270*fcf3ce44SJohn Forte } /* emlxs_dfc_get_auth_key_table() */
8271*fcf3ce44SJohn Forte 
8272*fcf3ce44SJohn Forte 
8273*fcf3ce44SJohn Forte 
8274*fcf3ce44SJohn Forte #endif	/* DHCHAP_SUPPORT */
8275*fcf3ce44SJohn Forte 
8276*fcf3ce44SJohn Forte static int32_t
8277*fcf3ce44SJohn Forte emlxs_dfc_send_scsi_fcp(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8278*fcf3ce44SJohn Forte {
8279*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
8280*fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
8281*fcf3ce44SJohn Forte 	NODELIST *ndlp;
8282*fcf3ce44SJohn Forte 	FCP_CMND *fcp_cmd;
8283*fcf3ce44SJohn Forte 	FCP_RSP *fcp_rsp;
8284*fcf3ce44SJohn Forte 	/* emlxs_xlat_err_t *entry; */
8285*fcf3ce44SJohn Forte 	void *ptr;
8286*fcf3ce44SJohn Forte 	char buffer[64];
8287*fcf3ce44SJohn Forte 	dfc_send_scsi_fcp_cmd_info_t cmdinfo;
8288*fcf3ce44SJohn Forte 	uint32_t rval = 0;
8289*fcf3ce44SJohn Forte 
8290*fcf3ce44SJohn Forte 	/* cmd info */
8291*fcf3ce44SJohn Forte 	if (!dfc->buf1 ||
8292*fcf3ce44SJohn Forte 	    (dfc->buf1_size != sizeof (dfc_send_scsi_fcp_cmd_info_t))) {
8293*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8294*fcf3ce44SJohn Forte 		    "%s: Null buffer1 found.",
8295*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8296*fcf3ce44SJohn Forte 
8297*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
8298*fcf3ce44SJohn Forte 		goto done;
8299*fcf3ce44SJohn Forte 	}
8300*fcf3ce44SJohn Forte 	/* reqBuffer info */
8301*fcf3ce44SJohn Forte 	if (!dfc->buf2 || (dfc->buf2_size != sizeof (FCP_CMND))) {
8302*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8303*fcf3ce44SJohn Forte 		    "%s: Null buffer2 found.",
8304*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8305*fcf3ce44SJohn Forte 
8306*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
8307*fcf3ce44SJohn Forte 		goto done;
8308*fcf3ce44SJohn Forte 	}
8309*fcf3ce44SJohn Forte 	/* rspBuffer info, could be 0 for SCSI commands like TUR */
8310*fcf3ce44SJohn Forte 	if (!dfc->buf3 && dfc->buf3_size) {
8311*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8312*fcf3ce44SJohn Forte 		    "%s: Null buffer3 found.",
8313*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8314*fcf3ce44SJohn Forte 
8315*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
8316*fcf3ce44SJohn Forte 		goto done;
8317*fcf3ce44SJohn Forte 	}
8318*fcf3ce44SJohn Forte 	/* senseBuffer info */
8319*fcf3ce44SJohn Forte 	if (!dfc->buf4 || !dfc->buf4_size) {
8320*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8321*fcf3ce44SJohn Forte 		    "%s: Null buffer4 found.",
8322*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8323*fcf3ce44SJohn Forte 
8324*fcf3ce44SJohn Forte 		rval = DFC_ARG_NULL;
8325*fcf3ce44SJohn Forte 		goto done;
8326*fcf3ce44SJohn Forte 	}
8327*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf1, (void *)&cmdinfo,
8328*fcf3ce44SJohn Forte 	    sizeof (dfc_send_scsi_fcp_cmd_info_t), mode) != 0) {
8329*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8330*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
8331*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8332*fcf3ce44SJohn Forte 
8333*fcf3ce44SJohn Forte 		rval = DFC_COPYIN_ERROR;
8334*fcf3ce44SJohn Forte 		goto done;
8335*fcf3ce44SJohn Forte 	}
8336*fcf3ce44SJohn Forte 	if (cmdinfo.ver == DFC_SEND_SCSI_FCP_V2) {
8337*fcf3ce44SJohn Forte 		port = emlxs_vport_find_wwpn(hba,
8338*fcf3ce44SJohn Forte 		    (uint8_t *)&cmdinfo.src_wwn);
8339*fcf3ce44SJohn Forte 		if (port == NULL) {
8340*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8341*fcf3ce44SJohn Forte 			    "%s: WWPN does not exists. %s",
8342*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd),
8343*fcf3ce44SJohn Forte 			    emlxs_wwn_xlate(buffer,
8344*fcf3ce44SJohn Forte 			    (uint8_t *)&cmdinfo.src_wwn));
8345*fcf3ce44SJohn Forte 
8346*fcf3ce44SJohn Forte 			rval = DFC_ARG_INVALID;
8347*fcf3ce44SJohn Forte 			goto done;
8348*fcf3ce44SJohn Forte 		}
8349*fcf3ce44SJohn Forte 	}
8350*fcf3ce44SJohn Forte 	if ((ndlp = emlxs_node_find_wwpn(port,
8351*fcf3ce44SJohn Forte 	    (uint8_t *)&cmdinfo.dst_wwn)) == NULL) {
8352*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8353*fcf3ce44SJohn Forte 		    "%s: WWPN does not exists. %s",
8354*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd),
8355*fcf3ce44SJohn Forte 		    emlxs_wwn_xlate(buffer,
8356*fcf3ce44SJohn Forte 		    (uint8_t *)&cmdinfo.dst_wwn));
8357*fcf3ce44SJohn Forte 
8358*fcf3ce44SJohn Forte 		rval = DFC_ARG_INVALID;
8359*fcf3ce44SJohn Forte 		goto done;
8360*fcf3ce44SJohn Forte 	}
8361*fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (FCP_CMND),
8362*fcf3ce44SJohn Forte 	    sizeof (FCP_RSP), dfc->buf3_size, KM_NOSLEEP))) {
8363*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8364*fcf3ce44SJohn Forte 		    "%s: Unable to allocate packet.",
8365*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8366*fcf3ce44SJohn Forte 
8367*fcf3ce44SJohn Forte 		rval = DFC_SYSRES_ERROR;
8368*fcf3ce44SJohn Forte 		goto done;
8369*fcf3ce44SJohn Forte 	}
8370*fcf3ce44SJohn Forte 	fcp_cmd = (FCP_CMND *)pkt->pkt_cmd;
8371*fcf3ce44SJohn Forte 	/* Copy in the command buffer */
8372*fcf3ce44SJohn Forte 	if (ddi_copyin((void *)dfc->buf2, (void *)fcp_cmd,
8373*fcf3ce44SJohn Forte 	    sizeof (FCP_CMND), mode) != 0) {
8374*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8375*fcf3ce44SJohn Forte 		    "%s: ddi_copyin failed.",
8376*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8377*fcf3ce44SJohn Forte 
8378*fcf3ce44SJohn Forte 		rval = DFC_COPYIN_ERROR;
8379*fcf3ce44SJohn Forte 		goto done;
8380*fcf3ce44SJohn Forte 	}
8381*fcf3ce44SJohn Forte 	/* Make this a polled IO */
8382*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
8383*fcf3ce44SJohn Forte 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
8384*fcf3ce44SJohn Forte 	pkt->pkt_comp = NULL;
8385*fcf3ce44SJohn Forte 
8386*fcf3ce44SJohn Forte 	/* Build the fc header */
8387*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(ndlp->nlp_DID);
8388*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = FC_FCP_CMND;
8389*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
8390*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_FCP_DATA;
8391*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
8392*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
8393*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
8394*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
8395*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
8396*fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
8397*fcf3ce44SJohn Forte 
8398*fcf3ce44SJohn Forte 	pkt->pkt_timeout = 30;
8399*fcf3ce44SJohn Forte 
8400*fcf3ce44SJohn Forte 	if ((fcp_cmd->fcpCntl3 == WRITE_DATA) && dfc->buf3_size) {
8401*fcf3ce44SJohn Forte 		pkt->pkt_tran_type = FC_PKT_FCP_WRITE;
8402*fcf3ce44SJohn Forte 		if (ddi_copyin((void *)dfc->buf3, (void *)pkt->pkt_data,
8403*fcf3ce44SJohn Forte 		    dfc->buf3_size, mode) != 0) {
8404*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8405*fcf3ce44SJohn Forte 			    "%s: ddi_copyin failed.",
8406*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
8407*fcf3ce44SJohn Forte 
8408*fcf3ce44SJohn Forte 			rval = DFC_COPYIN_ERROR;
8409*fcf3ce44SJohn Forte 			goto done;
8410*fcf3ce44SJohn Forte 		}
8411*fcf3ce44SJohn Forte 	} else {
8412*fcf3ce44SJohn Forte 		pkt->pkt_tran_type = FC_PKT_FCP_READ;
8413*fcf3ce44SJohn Forte 	}
8414*fcf3ce44SJohn Forte 
8415*fcf3ce44SJohn Forte 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
8416*fcf3ce44SJohn Forte 		rval = DFC_IO_ERROR;
8417*fcf3ce44SJohn Forte 		goto done;
8418*fcf3ce44SJohn Forte 	}
8419*fcf3ce44SJohn Forte 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
8420*fcf3ce44SJohn Forte 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
8421*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8422*fcf3ce44SJohn Forte 			    "Pkt Transport error. Pkt Timeout.");
8423*fcf3ce44SJohn Forte 			rval = DFC_TIMEOUT;
8424*fcf3ce44SJohn Forte 		} else {
8425*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8426*fcf3ce44SJohn Forte 			    "Pkt Transport error. state=%x",
8427*fcf3ce44SJohn Forte 			    pkt->pkt_state);
8428*fcf3ce44SJohn Forte 			rval = DFC_IO_ERROR;
8429*fcf3ce44SJohn Forte 		}
8430*fcf3ce44SJohn Forte 		goto done;
8431*fcf3ce44SJohn Forte 	}
8432*fcf3ce44SJohn Forte 	if (pkt->pkt_data_resid) {
8433*fcf3ce44SJohn Forte 		if (pkt->pkt_data_resid < dfc->buf3_size)
8434*fcf3ce44SJohn Forte 			dfc->buf3_size -= pkt->pkt_data_resid;
8435*fcf3ce44SJohn Forte 		else
8436*fcf3ce44SJohn Forte 			dfc->buf3_size = 0;
8437*fcf3ce44SJohn Forte 	}
8438*fcf3ce44SJohn Forte 	SCSI_RSP_CNT(cmdinfo) = dfc->buf3_size;
8439*fcf3ce44SJohn Forte 
8440*fcf3ce44SJohn Forte 	fcp_rsp = (FCP_RSP *)pkt->pkt_resp;
8441*fcf3ce44SJohn Forte 	/*
8442*fcf3ce44SJohn Forte 	 * This is sense count for flag = 0. It is fcp response size for flag
8443*fcf3ce44SJohn Forte 	 * = 1.
8444*fcf3ce44SJohn Forte 	 */
8445*fcf3ce44SJohn Forte 	if (dfc->flag) {
8446*fcf3ce44SJohn Forte 		SCSI_SNS_CNT(cmdinfo) = 24 + SWAP_DATA32(fcp_rsp->rspSnsLen) +
8447*fcf3ce44SJohn Forte 		    SWAP_DATA32(fcp_rsp->rspRspLen);
8448*fcf3ce44SJohn Forte 		ptr = (void *)fcp_rsp;
8449*fcf3ce44SJohn Forte 	} else {
8450*fcf3ce44SJohn Forte 		SCSI_SNS_CNT(cmdinfo) = SWAP_DATA32(fcp_rsp->rspSnsLen);
8451*fcf3ce44SJohn Forte 		ptr = (void *)&fcp_rsp->rspSnsInfo[0];
8452*fcf3ce44SJohn Forte 	}
8453*fcf3ce44SJohn Forte 
8454*fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&cmdinfo, (void *)dfc->buf1,
8455*fcf3ce44SJohn Forte 	    sizeof (dfc_send_scsi_fcp_cmd_info_t), mode) != 0) {
8456*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8457*fcf3ce44SJohn Forte 		    "%s: rsp_buf ddi_copyout failed.",
8458*fcf3ce44SJohn Forte 		    emlxs_dfc_xlate(dfc->cmd));
8459*fcf3ce44SJohn Forte 
8460*fcf3ce44SJohn Forte 		rval = DFC_COPYOUT_ERROR;
8461*fcf3ce44SJohn Forte 		goto done;
8462*fcf3ce44SJohn Forte 	}
8463*fcf3ce44SJohn Forte 	if (SCSI_SNS_CNT(cmdinfo)) {
8464*fcf3ce44SJohn Forte 		if (ddi_copyout(ptr, (void *)dfc->buf4,
8465*fcf3ce44SJohn Forte 		    SCSI_SNS_CNT(cmdinfo), mode) != 0) {
8466*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8467*fcf3ce44SJohn Forte 			    "%s: rsp_size ddi_copyout failed.",
8468*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
8469*fcf3ce44SJohn Forte 
8470*fcf3ce44SJohn Forte 			rval = DFC_COPYOUT_ERROR;
8471*fcf3ce44SJohn Forte 			goto done;
8472*fcf3ce44SJohn Forte 		}
8473*fcf3ce44SJohn Forte 	}
8474*fcf3ce44SJohn Forte 	if (SCSI_RSP_CNT(cmdinfo)) {
8475*fcf3ce44SJohn Forte 		if (ddi_copyout((void *)pkt->pkt_data, (void *)dfc->buf3,
8476*fcf3ce44SJohn Forte 		    SCSI_RSP_CNT(cmdinfo), mode) != 0) {
8477*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8478*fcf3ce44SJohn Forte 			    "%s: rsp_size ddi_copyout failed.",
8479*fcf3ce44SJohn Forte 			    emlxs_dfc_xlate(dfc->cmd));
8480*fcf3ce44SJohn Forte 
8481*fcf3ce44SJohn Forte 			rval = DFC_COPYOUT_ERROR;
8482*fcf3ce44SJohn Forte 			goto done;
8483*fcf3ce44SJohn Forte 		}
8484*fcf3ce44SJohn Forte 	}
8485*fcf3ce44SJohn Forte 	rval = 0;
8486*fcf3ce44SJohn Forte 
8487*fcf3ce44SJohn Forte done:
8488*fcf3ce44SJohn Forte 	if (pkt) {
8489*fcf3ce44SJohn Forte 		emlxs_pkt_free(pkt);
8490*fcf3ce44SJohn Forte 	}
8491*fcf3ce44SJohn Forte 	return (rval);
8492*fcf3ce44SJohn Forte 
8493*fcf3ce44SJohn Forte } /* emlxs_dfc_send_scsi_fcp() */
8494*fcf3ce44SJohn Forte 
8495*fcf3ce44SJohn Forte #endif	/* DFC_SUPPORT */
8496