1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at
9  * http://www.opensource.org/licenses/cddl1.txt.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2004-2012 Emulex. All rights reserved.
24  * Use is subject to license terms.
25  * Copyright 2020 RackTop Systems, Inc.
26  */
27 
28 #include <emlxs.h>
29 
30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31 EMLXS_MSG_DEF(EMLXS_DFC_C);
32 
33 static int32_t		emlxs_dfc_get_rev(emlxs_hba_t *hba, dfc_t *dfc,
34 				int32_t mode);
35 static int32_t		emlxs_dfc_get_hbainfo(emlxs_hba_t *hba, dfc_t *dfc,
36 				int32_t mode);
37 static int32_t		emlxs_dfc_get_hbastats(emlxs_hba_t *hba, dfc_t *dfc,
38 				int32_t mode);
39 static int32_t		emlxs_dfc_get_drvstats(emlxs_hba_t *hba, dfc_t *dfc,
40 				int32_t mode);
41 static int32_t		emlxs_dfc_set_diag(emlxs_hba_t *hba, dfc_t *dfc,
42 				int32_t mode);
43 static int32_t		emlxs_dfc_send_mbox(emlxs_hba_t *hba, dfc_t *dfc,
44 				int32_t mode);
45 static int32_t		emlxs_dfc_read_pci(emlxs_hba_t *hba, dfc_t *dfc,
46 				int32_t mode);
47 static int32_t		emlxs_dfc_write_pci(emlxs_hba_t *hba, dfc_t *dfc,
48 				int32_t mode);
49 static int32_t		emlxs_dfc_get_cfg(emlxs_hba_t *hba, dfc_t *dfc,
50 				int32_t mode);
51 static int32_t		emlxs_dfc_set_cfg(emlxs_hba_t *hba, dfc_t *dfc,
52 				int32_t mode);
53 static int32_t		emlxs_dfc_send_menlo(emlxs_hba_t *hba, dfc_t *dfc,
54 				int32_t mode);
55 static int32_t		emlxs_dfc_send_ct(emlxs_hba_t *hba, dfc_t *dfc,
56 				int32_t mode);
57 static int32_t		emlxs_dfc_send_ct_rsp(emlxs_hba_t *hba, dfc_t *dfc,
58 				int32_t mode);
59 static int32_t		emlxs_dfc_write_flash(emlxs_hba_t *hba, dfc_t *dfc,
60 				int32_t mode);
61 static int32_t		emlxs_dfc_read_flash(emlxs_hba_t *hba, dfc_t *dfc,
62 				int32_t mode);
63 static int32_t		emlxs_dfc_send_els(emlxs_hba_t *hba, dfc_t *dfc,
64 				int32_t mode);
65 static int32_t		emlxs_dfc_loopback_test(emlxs_hba_t *hba, dfc_t *dfc,
66 				int32_t mode);
67 static int32_t		emlxs_dfc_reset_port(emlxs_hba_t *hba, dfc_t *dfc,
68 				int32_t mode);
69 static int32_t		emlxs_dfc_get_dump_region(emlxs_hba_t *hba, dfc_t *dfc,
70 				int32_t mode);
71 static int32_t		emlxs_dfc_loopback_mode(emlxs_hba_t *hba, dfc_t *dfc,
72 				int32_t mode);
73 static int32_t		emlxs_dfc_get_ioinfo(emlxs_hba_t *hba, dfc_t *dfc,
74 				int32_t mode);
75 static int32_t		emlxs_dfc_get_linkinfo(emlxs_hba_t *hba, dfc_t *dfc,
76 				int32_t mode);
77 static int32_t		emlxs_dfc_read_mem(emlxs_hba_t *hba, dfc_t *dfc,
78 				int32_t mode);
79 static int32_t		emlxs_dfc_write_mem(emlxs_hba_t *hba, dfc_t *dfc,
80 				int32_t mode);
81 static int32_t		emlxs_dfc_write_ctlreg(emlxs_hba_t *hba, dfc_t *dfc,
82 				int32_t mode);
83 static int32_t		emlxs_dfc_read_ctlreg(emlxs_hba_t *hba, dfc_t *dfc,
84 				int32_t mode);
85 static int32_t		emlxs_dfc_get_event(emlxs_hba_t *hba, dfc_t *dfc,
86 				int32_t mode);
87 static int32_t		emlxs_dfc_set_event(emlxs_hba_t *hba, dfc_t *dfc,
88 				int32_t mode);
89 static int32_t		emlxs_dfc_get_eventinfo(emlxs_hba_t *hba, dfc_t *dfc,
90 				int32_t mode);
91 static int32_t		emlxs_dfc_get_nodeinfo(emlxs_hba_t *hba, dfc_t *dfc,
92 				int32_t mode);
93 
94 #ifdef SFCT_SUPPORT
95 static int32_t		emlxs_dfc_get_fctstat(emlxs_hba_t *hba, dfc_t *dfc,
96 				int32_t mode);
97 #endif /* SFCT_SUPPORT */
98 
99 static int32_t		emlxs_dfc_create_vport(emlxs_hba_t *hba, dfc_t *dfc,
100 				int32_t mode);
101 static int32_t		emlxs_dfc_destroy_vport(emlxs_hba_t *hba, dfc_t *dfc,
102 				int32_t mode);
103 static int32_t		emlxs_dfc_get_vportinfo(emlxs_hba_t *hba, dfc_t *dfc,
104 				int32_t mode);
105 static int32_t		emlxs_dfc_npiv_resource(emlxs_hba_t *hba, dfc_t *dfc,
106 				int32_t mode);
107 static int32_t		emlxs_dfc_npiv_test(emlxs_hba_t *hba, dfc_t *dfc,
108 				int32_t mode);
109 static emlxs_port_t	*emlxs_vport_find_wwpn(emlxs_hba_t *hba, uint8_t *wwpn);
110 
111 #ifdef DHCHAP_SUPPORT
112 static int32_t		emlxs_dfc_init_auth(emlxs_hba_t *hba, dfc_t *dfc,
113 				int32_t mode);
114 static int32_t		emlxs_dfc_get_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc,
115 				int32_t mode);
116 static int32_t		emlxs_dfc_set_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc,
117 				int32_t mode);
118 static int32_t		emlxs_dfc_get_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc,
119 				int32_t mode);
120 static int32_t		emlxs_dfc_set_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc,
121 				int32_t mode);
122 static int32_t		emlxs_dfc_get_auth_status(emlxs_hba_t *hba, dfc_t *dfc,
123 				int32_t mode);
124 static int32_t		emlxs_dfc_get_auth_cfg_table(emlxs_hba_t *hba,
125 				dfc_t *dfc, int32_t mode);
126 static int32_t		emlxs_dfc_get_auth_key_table(emlxs_hba_t *hba,
127 				dfc_t *dfc, int32_t mode);
128 #endif	/* DHCHAP_SUPPORT */
129 
130 #ifdef SAN_DIAG_SUPPORT
131 static int32_t		emlxs_dfc_sd_set_bucket(emlxs_hba_t *hba, dfc_t *dfc,
132 				int32_t mode);
133 static int32_t		emlxs_dfc_sd_destroy_bucket(emlxs_hba_t *hba,
134 				dfc_t *dfc, int32_t mode);
135 static int32_t		emlxs_dfc_sd_get_bucket(emlxs_hba_t *hba, dfc_t *dfc,
136 				int32_t mode);
137 static int32_t		emlxs_dfc_sd_start_collection(emlxs_hba_t *hba,
138 				dfc_t *dfc, int32_t mode);
139 static int32_t		emlxs_dfc_sd_stop_collection(emlxs_hba_t *hba,
140 				dfc_t *dfc, int32_t mode);
141 static int32_t		emlxs_dfc_sd_reset_collection(emlxs_hba_t *hba,
142 				dfc_t *dfc, int32_t mode);
143 static int32_t		emlxs_dfc_sd_get_data(emlxs_hba_t *hba, dfc_t *dfc,
144 				int32_t mode);
145 static int32_t		emlxs_dfc_sd_set_event(emlxs_hba_t *hba, dfc_t *dfc,
146 				int32_t mode);
147 static int32_t		emlxs_dfc_sd_get_event(emlxs_hba_t *hba, dfc_t *dfc,
148 				int32_t mode);
149 #endif	/* SAN_DIAG_SUPPORT */
150 
151 static int32_t		emlxs_dfc_send_scsi_fcp(emlxs_hba_t *hba, dfc_t *dfc,
152 				int32_t mode);
153 #ifdef FCIO_SUPPORT
154 static int32_t		emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc,
155 				int32_t mode);
156 static int32_t		emlxs_fcio_get_num_devs(emlxs_port_t *port,
157 				fcio_t *fcio, int32_t mode);
158 static int32_t		emlxs_fcio_get_dev_list(emlxs_port_t *port,
159 				fcio_t *fcio, int32_t mode);
160 static int32_t		emlxs_fcio_get_sym_pname(emlxs_port_t *port,
161 				fcio_t *fcio, int32_t mode);
162 static int32_t		emlxs_fcio_get_sym_nname(emlxs_port_t *port,
163 				fcio_t *fcio, int32_t mode);
164 static int32_t		emlxs_fcio_unsupported(emlxs_port_t *port,
165 				fcio_t *fcio, int32_t mode);
166 static int32_t		emlxs_fcio_get_logi_params(emlxs_port_t *port,
167 				fcio_t *fcio, int32_t mode);
168 static int32_t		emlxs_fcio_get_state(emlxs_port_t *port,
169 				fcio_t *fcio, int32_t mode);
170 static int32_t		emlxs_fcio_get_fcode_rev(emlxs_port_t *port,
171 				fcio_t *fcio, int32_t mode);
172 static int32_t		emlxs_fcio_get_fw_rev(emlxs_port_t *port,
173 				fcio_t *fcio, int32_t mode);
174 static int32_t		emlxs_fcio_get_dump_size(emlxs_port_t *port,
175 				fcio_t *fcio, int32_t mode);
176 static int32_t		emlxs_fcio_force_dump(emlxs_port_t *port,
177 				fcio_t *fcio, int32_t mode);
178 static int32_t		emlxs_fcio_get_dump(emlxs_port_t *port,
179 				fcio_t *fcio, int32_t mode);
180 static int32_t		emlxs_fcio_get_topology(emlxs_port_t *port,
181 				fcio_t *fcio, int32_t mode);
182 static int32_t		emlxs_fcio_reset_link(emlxs_port_t *port,
183 				fcio_t *fcio, int32_t mode);
184 static int32_t		emlxs_fcio_reset_hard(emlxs_port_t *port,
185 				fcio_t *fcio, int32_t mode);
186 static int32_t		emlxs_fcio_diag(emlxs_port_t *port,
187 				fcio_t *fcio, int32_t mode);
188 static int32_t		emlxs_fcio_download_fw(emlxs_port_t *port,
189 				fcio_t *fcio, int32_t mode);
190 static int32_t		emlxs_fcio_get_host_params(emlxs_port_t *port,
191 				fcio_t *fcio, int32_t mode);
192 static int32_t		emlxs_fcio_get_link_status(emlxs_port_t *port,
193 				fcio_t *fcio, int32_t mode);
194 static int32_t		emlxs_fcio_download_fcode(emlxs_port_t *port,
195 				fcio_t *fcio, int32_t mode);
196 static int32_t		emlxs_fcio_get_node_id(emlxs_port_t *port,
197 				fcio_t *fcio, int32_t mode);
198 static int32_t		emlxs_fcio_set_node_id(emlxs_port_t *port,
199 				fcio_t *fcio, int32_t mode);
200 static int32_t		emlxs_fcio_get_adapter_attrs(emlxs_port_t *port,
201 				fcio_t *fcio, int32_t mode);
202 static int32_t		emlxs_fcio_get_other_adapter_ports(emlxs_port_t *port,
203 				fcio_t *fcio, int32_t mode);
204 static int32_t		emlxs_fcio_get_adapter_port_attrs(emlxs_port_t *port,
205 				fcio_t *fcio, int32_t mode);
206 static int32_t		emlxs_fcio_get_disc_port_attrs(emlxs_port_t *port,
207 				fcio_t *fcio, int32_t mode);
208 static int32_t		emlxs_fcio_get_port_attrs(emlxs_port_t *port,
209 				fcio_t *fcio, int32_t mode);
210 #endif	/* FCIO_SUPPORT */
211 
212 static int32_t		emlxs_dfc_get_persist_linkdown(emlxs_hba_t *hba,
213 				dfc_t *dfc, int32_t mode);
214 static int32_t		emlxs_dfc_set_persist_linkdown(emlxs_hba_t *hba,
215 				dfc_t *dfc, int32_t mode);
216 
217 /* SLI-4 ioctls */
218 static int32_t		emlxs_dfc_get_fcflist(emlxs_hba_t *hba, dfc_t *dfc,
219 				int32_t mode);
220 static int32_t		emlxs_dfc_send_mbox4(emlxs_hba_t *hba, dfc_t *dfc,
221 				int32_t mode);
222 static int		emlxs_dfc_rd_be_fcf(emlxs_hba_t *hba, dfc_t *dfc,
223 			    int32_t mode);
224 static int		emlxs_dfc_set_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc,
225 			    int32_t mode);
226 static int		emlxs_dfc_get_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc,
227 			    int32_t mode);
228 static int		emlxs_dfc_get_qos(emlxs_hba_t *hba, dfc_t *dfc,
229 			    int32_t mode);
230 
231 uint32_t	emlxs_loopback_tmo = 60;
232 
233 typedef struct
234 {
235 	uint32_t	code;
236 	char		string[32];
237 	int		(*func)(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode);
238 } emlxs_dfc_table_t;
239 
240 emlxs_dfc_table_t emlxs_dfc_table[] = {
241 	{EMLXS_GET_HBAINFO, "GET_HBAINFO", emlxs_dfc_get_hbainfo},
242 	{EMLXS_GET_REV, "GET_REV", emlxs_dfc_get_rev},
243 	{EMLXS_SET_DIAG, "SET_DIAG", emlxs_dfc_set_diag},
244 	{EMLXS_SEND_MBOX, "SEND_MBOX", emlxs_dfc_send_mbox},
245 	{EMLXS_READ_PCI, "READ_PCI", emlxs_dfc_read_pci},
246 	{EMLXS_WRITE_PCI, "WRITE_PCI", emlxs_dfc_write_pci},
247 	{EMLXS_GET_CFG, "GET_CFG", emlxs_dfc_get_cfg},
248 	{EMLXS_SET_CFG, "SET_CFG", emlxs_dfc_set_cfg},
249 	{EMLXS_SEND_CT, "SEND_CT", emlxs_dfc_send_ct},
250 	{EMLXS_SEND_CT_RSP, "SEND_CT_RSP", emlxs_dfc_send_ct_rsp},
251 	{EMLXS_WRITE_FLASH, "WRITE_FLASH", emlxs_dfc_write_flash},
252 	{EMLXS_READ_FLASH, "READ_FLASH", emlxs_dfc_read_flash},
253 	{EMLXS_SEND_ELS, "SEND_ELS", emlxs_dfc_send_els},
254 	{EMLXS_LOOPBACK_TEST, "LOOPBACK_TEST", emlxs_dfc_loopback_test},
255 	{EMLXS_RESET_PORT, "RESET_PORT", emlxs_dfc_reset_port},
256 	{EMLXS_GET_DUMPREGION, "GET_DUMPREGION", emlxs_dfc_get_dump_region},
257 	{EMLXS_LOOPBACK_MODE, "LOOPBACK_MODE", emlxs_dfc_loopback_mode},
258 	{EMLXS_GET_IOINFO, "GET_IOINFO", emlxs_dfc_get_ioinfo},
259 	{EMLXS_GET_LINKINFO, "GET_LINKINFO", emlxs_dfc_get_linkinfo},
260 	{EMLXS_GET_NODEINFO, "GET_NODEINFO", emlxs_dfc_get_nodeinfo},
261 	{EMLXS_READ_MEM, "READ_MEM", emlxs_dfc_read_mem},
262 	{EMLXS_WRITE_MEM, "WRITE_MEM", emlxs_dfc_write_mem},
263 	{EMLXS_WRITE_CTLREG, "WRITE_CTLREG", emlxs_dfc_write_ctlreg},
264 	{EMLXS_READ_CTLREG, "READ_CTLREG", emlxs_dfc_read_ctlreg},
265 	{EMLXS_SEND_SCSI, "SEND_SCSI", emlxs_dfc_send_scsi_fcp},
266 	{EMLXS_GET_EVENT, "GET_EVENT", emlxs_dfc_get_event},
267 	{EMLXS_SET_EVENT, "SET_EVENT", emlxs_dfc_set_event},
268 	{EMLXS_GET_EVENTINFO, "GET_EVENTINFO", emlxs_dfc_get_eventinfo},
269 	{EMLXS_GET_HBASTATS, "GET_HBASTATS", emlxs_dfc_get_hbastats},
270 	{EMLXS_GET_DRVSTATS, "GET_DRVSTATS", emlxs_dfc_get_drvstats},
271 	{EMLXS_CREATE_VPORT, "CREATE_VPORT", emlxs_dfc_create_vport},
272 	{EMLXS_DESTROY_VPORT, "DESTROY_VPORT", emlxs_dfc_destroy_vport},
273 	{EMLXS_GET_VPORTINFO, "GET_VPORTINFO", emlxs_dfc_get_vportinfo},
274 	{EMLXS_NPIV_RESOURCE, "NPIV_RESOURCE", emlxs_dfc_npiv_resource},
275 	{EMLXS_NPIV_TEST, "NPIV_TEST", emlxs_dfc_npiv_test},
276 	{EMLXS_GET_PERSIST_LINKDOWN, "GET_PERSIST_LINKDOWN",
277 	    emlxs_dfc_get_persist_linkdown},
278 	{EMLXS_SET_PERSIST_LINKDOWN, "SET_PERSIST_LINKDOWN",
279 	    emlxs_dfc_set_persist_linkdown},
280 	{EMLXS_GET_FCOE_FCFLIST, "GET_FCOE_FCFLIST", emlxs_dfc_get_fcflist},
281 	{EMLXS_SEND_MBOX4, "SEND_MBOX4", emlxs_dfc_send_mbox4},
282 	{EMLXS_RD_BE_FCF, "RD_BE_FCF", emlxs_dfc_rd_be_fcf},
283 	{EMLXS_SET_BE_DCBX, "SET_BE_DCBX", emlxs_dfc_set_be_dcbx},
284 	{EMLXS_GET_BE_DCBX, "GET_BE_DCBX", emlxs_dfc_get_be_dcbx},
285 	{EMLXS_GET_QOS, "GET_QOS", emlxs_dfc_get_qos},
286 #ifdef MENLO_SUPPORT
287 	{EMLXS_SEND_MENLO, "SEND_MENLO", emlxs_dfc_send_menlo},
288 #endif /* MENLO_SUPPORT */
289 #ifdef DHCHAP_SUPPORT
290 	{EMLXS_INIT_AUTH, "INIT_AUTH", emlxs_dfc_init_auth},
291 	{EMLXS_GET_AUTH_CFG, "GET_AUTH_CFG", emlxs_dfc_get_auth_cfg},
292 	{EMLXS_SET_AUTH_CFG, "SET_AUTH_CFG", emlxs_dfc_set_auth_cfg},
293 	{EMLXS_GET_AUTH_PASSWORD, "GET_AUTH_PASSWORD", emlxs_dfc_get_auth_pwd},
294 	{EMLXS_SET_AUTH_PASSWORD, "SET_AUTH_PASSWORD", emlxs_dfc_set_auth_pwd},
295 	{EMLXS_GET_AUTH_STATUS, "GET_AUTH_STATUS", emlxs_dfc_get_auth_status},
296 	{EMLXS_GET_AUTH_CFG_TABLE, "GET_AUTH_CFG_TABLE",
297 	    emlxs_dfc_get_auth_cfg_table},
298 	{EMLXS_GET_AUTH_KEY_TABLE, "GET_AUTH_KEY_TABLE",
299 	    emlxs_dfc_get_auth_key_table},
300 #endif	/* DHCHAP_SUPPORT */
301 #ifdef FCIO_SUPPORT
302 	{EMLXS_FCIO_CMD, "FCIO_CMD", emlxs_fcio_manage},
303 #endif /* FCIO_SUPPORT */
304 #ifdef SFCT_SUPPORT
305 	{EMLXS_GET_FCTSTAT, "GET_FCTSTAT", emlxs_dfc_get_fctstat},
306 #endif /* SFCT_SUPPORT */
307 #ifdef SAN_DIAG_SUPPORT
308 	{EMLXS_SD_SET_BUCKET, "SD_SET_BUCKET", emlxs_dfc_sd_set_bucket},
309 	{EMLXS_SD_DESTROY_BUCKET, "SD_DESTROY_BUCKET",
310 	    emlxs_dfc_sd_destroy_bucket},
311 	{EMLXS_SD_GET_BUCKET, "SD_GET_BUCKET", emlxs_dfc_sd_get_bucket},
312 	{EMLXS_SD_START_DATA_COLLECTION, "SD_START_DATA_COLLECTION",
313 	    emlxs_dfc_sd_start_collection},
314 	{EMLXS_SD_STOP_DATA_COLLECTION, "SD_STOP_DATA_COLLECTION",
315 	    emlxs_dfc_sd_stop_collection},
316 	{EMLXS_SD_RESET_DATA_COLLECTION, "SD_RESET_DATA_COLLECTION",
317 	    emlxs_dfc_sd_reset_collection},
318 	{EMLXS_SD_GET_DATA, "SD_GET_DATA", emlxs_dfc_sd_get_data},
319 	{EMLXS_SD_SET_EVENT, "SD_SET_EVENT", emlxs_dfc_sd_set_event},
320 	{EMLXS_SD_GET_EVENT, "SD_GET_EVENT", emlxs_dfc_sd_get_event},
321 #endif	/* SAN_DIAG_SUPPORT */
322 };	/* emlxs_dfc_table */
323 
324 
325 emlxs_table_t emlxs_dfc_event_table[] = {
326 	{FC_REG_LINK_EVENT,		"LINK_EVENT"},
327 	{FC_REG_RSCN_EVENT,		"RSCN_EVENT"},
328 	{FC_REG_CT_EVENT,		"CT_EVENT"},
329 	{FC_REG_DUMP_EVENT,		"DUMP_EVENT"},
330 	{FC_REG_TEMP_EVENT,		"TEMP_EVENT"},
331 	{FC_REG_VPORTRSCN_EVENT,	"VPORTRSCN_EVENT"},
332 	{FC_REG_FCOE_EVENT,		"FCOE_EVENT"},
333 
334 };	/* emlxs_dfc_event_table */
335 
336 
337 #ifdef SAN_DIAG_SUPPORT
338 kmutex_t		emlxs_sd_bucket_mutex;
339 sd_bucket_info_t	emlxs_sd_bucket;
340 #endif	/* SAN_DIAG_SUPPORT */
341 
342 extern char    *
emlxs_dfc_xlate(uint16_t cmd)343 emlxs_dfc_xlate(uint16_t cmd)
344 {
345 	static char	buffer[32];
346 	uint32_t	i;
347 	uint32_t	count;
348 
349 	count = sizeof (emlxs_dfc_table) / sizeof (emlxs_dfc_table_t);
350 	for (i = 0; i < count; i++) {
351 		if (cmd == emlxs_dfc_table[i].code) {
352 			return (emlxs_dfc_table[i].string);
353 		}
354 	}
355 
356 	(void) snprintf(buffer, sizeof (buffer), "Cmd=0x%x", cmd);
357 	return (buffer);
358 
359 } /* emlxs_dfc_xlate() */
360 
361 
362 static int
emlxs_dfc_func(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)363 emlxs_dfc_func(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
364 {
365 	emlxs_port_t *port = &PPORT;
366 	uint32_t	i;
367 	uint32_t	count;
368 	int		rval;
369 
370 	count = sizeof (emlxs_dfc_table) / sizeof (emlxs_dfc_table_t);
371 	for (i = 0; i < count; i++) {
372 		if (dfc->cmd == emlxs_dfc_table[i].code) {
373 			if ((dfc->cmd != EMLXS_FCIO_CMD) ||
374 			    (dfc->data1 != FCIO_DIAG) ||
375 			    (dfc->data2 != EMLXS_LOG_GET)) {
376 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
377 				    "%s requested.",
378 				    emlxs_dfc_table[i].string);
379 			}
380 
381 			rval = emlxs_dfc_table[i].func(hba, dfc, mode);
382 			return (rval);
383 		}
384 	}
385 
386 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
387 	    "Unknown DFC command. (0x%x)", dfc->cmd);
388 
389 	return (DFC_ARG_INVALID);
390 
391 } /* emlxs_dfc_func() */
392 
393 
394 extern char    *
emlxs_dfc_event_xlate(uint32_t event)395 emlxs_dfc_event_xlate(uint32_t event)
396 {
397 	static char	buffer[32];
398 	uint32_t	i;
399 	uint32_t	count;
400 
401 	count = sizeof (emlxs_dfc_event_table) / sizeof (emlxs_table_t);
402 	for (i = 0; i < count; i++) {
403 		if (event == emlxs_dfc_event_table[i].code) {
404 			return (emlxs_dfc_event_table[i].string);
405 		}
406 	}
407 
408 	(void) snprintf(buffer, sizeof (buffer), "Event=0x%x", event);
409 	return (buffer);
410 
411 } /* emlxs_dfc_event_xlate() */
412 
413 
414 static int32_t
emlxs_dfc_copyin(emlxs_hba_t * hba,void * arg,dfc_t * dfc1,dfc_t * dfc2,int32_t mode)415 emlxs_dfc_copyin(emlxs_hba_t *hba, void *arg, dfc_t *dfc1, dfc_t *dfc2,
416     int32_t mode)
417 {
418 	emlxs_port_t	*port = &PPORT;
419 	int		rval = 0;
420 	uint32_t	use32 = 0;
421 
422 #ifdef	_MULTI_DATAMODEL
423 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
424 		use32 = 1;
425 	}
426 #endif	/* _MULTI_DATAMODEL */
427 
428 	if (use32) {
429 		dfc32_t dfc32;
430 
431 		if (ddi_copyin((void *)arg, (void *)&dfc32,
432 		    sizeof (dfc32_t), mode)) {
433 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
434 			    "ddi_copyin32 failed.");
435 
436 			rval = DFC_COPYIN_ERROR;
437 			goto done;
438 		}
439 
440 		dfc1->cmd = dfc32.cmd;
441 		dfc1->flag = dfc32.flag;
442 		dfc1->buf1 = (void *)((uintptr_t)dfc32.buf1);
443 		dfc1->buf1_size = dfc32.buf1_size;
444 		dfc1->data1 = dfc32.data1;
445 		dfc1->buf2 = (void *)((uintptr_t)dfc32.buf2);
446 		dfc1->buf2_size = dfc32.buf2_size;
447 		dfc1->data2 = dfc32.data2;
448 		dfc1->buf3 = (void *)((uintptr_t)dfc32.buf3);
449 		dfc1->buf3_size = dfc32.buf3_size;
450 		dfc1->data3 = dfc32.data3;
451 		dfc1->buf4 = (void *)((uintptr_t)dfc32.buf4);
452 		dfc1->buf4_size = dfc32.buf4_size;
453 		dfc1->data4 = dfc32.data4;
454 
455 	} else {
456 		if (ddi_copyin((void *)arg, (void *)dfc1, sizeof (dfc_t),
457 		    mode)) {
458 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
459 			    "ddi_copyin failed.");
460 
461 			rval = DFC_COPYIN_ERROR;
462 			goto done;
463 		}
464 	}
465 
466 	/* Map dfc1 to dfc2 */
467 	dfc2->cmd   = dfc1->cmd;
468 	dfc2->flag  = dfc1->flag;
469 	dfc2->data1 = dfc1->data1;
470 	dfc2->data2 = dfc1->data2;
471 	dfc2->data3 = dfc1->data3;
472 	dfc2->data4 = dfc1->data4;
473 	dfc2->buf1  = 0;
474 	dfc2->buf1_size = 0;
475 	dfc2->buf2  = 0;
476 	dfc2->buf2_size = 0;
477 	dfc2->buf3  = 0;
478 	dfc2->buf3_size = 0;
479 	dfc2->buf4  = 0;
480 	dfc2->buf4_size = 0;
481 
482 	/* Copyin data buffers */
483 	if (dfc1->buf1_size && dfc1->buf1) {
484 		dfc2->buf1_size = dfc1->buf1_size;
485 		dfc2->buf1 = kmem_zalloc(dfc1->buf1_size, KM_SLEEP);
486 
487 		if (ddi_copyin(dfc1->buf1, dfc2->buf1, dfc1->buf1_size,
488 		    mode)) {
489 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
490 			    "%s: buf1 ddi_copyin failed. (size=%d)",
491 			    emlxs_dfc_xlate(dfc1->cmd),
492 			    dfc1->buf1_size);
493 
494 			rval = DFC_COPYIN_ERROR;
495 			goto done;
496 		}
497 	}
498 
499 	if (dfc1->buf2_size && dfc1->buf2) {
500 		dfc2->buf2_size = dfc1->buf2_size;
501 		dfc2->buf2 = kmem_zalloc(dfc1->buf2_size, KM_SLEEP);
502 
503 		if (ddi_copyin(dfc1->buf2, dfc2->buf2, dfc1->buf2_size,
504 		    mode)) {
505 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
506 			    "%s: buf2 ddi_copyin failed. (size=%d)",
507 			    emlxs_dfc_xlate(dfc1->cmd),
508 			    dfc1->buf2_size);
509 
510 			rval = DFC_COPYIN_ERROR;
511 			goto done;
512 		}
513 	}
514 
515 	if (dfc1->buf3_size && dfc1->buf3) {
516 		dfc2->buf3_size = dfc1->buf3_size;
517 		dfc2->buf3 = kmem_zalloc(dfc1->buf3_size, KM_SLEEP);
518 
519 		if (ddi_copyin(dfc1->buf3, dfc2->buf3, dfc1->buf3_size,
520 		    mode)) {
521 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
522 			    "%s buf3 ddi_copyin failed. (size=%d)",
523 			    emlxs_dfc_xlate(dfc1->cmd),
524 			    dfc1->buf3_size);
525 
526 			rval = DFC_COPYIN_ERROR;
527 			goto done;
528 		}
529 	}
530 
531 	if (dfc1->buf4_size && dfc1->buf4) {
532 		dfc2->buf4_size = dfc1->buf4_size;
533 		dfc2->buf4 = kmem_zalloc(dfc1->buf4_size, KM_SLEEP);
534 
535 		if (ddi_copyin(dfc1->buf4, dfc2->buf4, dfc1->buf4_size,
536 		    mode)) {
537 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
538 			    "%s: buf4 ddi_copyin failed. (size=%d)",
539 			    emlxs_dfc_xlate(dfc1->cmd),
540 			    dfc1->buf4_size);
541 
542 			rval = DFC_COPYIN_ERROR;
543 			goto done;
544 		}
545 	}
546 
547 done:
548 	return (rval);
549 
550 } /* emlxs_dfc_copyin() */
551 
552 
553 static int32_t
emlxs_dfc_copyout(emlxs_hba_t * hba,void * arg,dfc_t * dfc2,dfc_t * dfc1,int32_t mode)554 emlxs_dfc_copyout(emlxs_hba_t *hba, void *arg, dfc_t *dfc2, dfc_t *dfc1,
555     int32_t mode)
556 {
557 	emlxs_port_t	*port = &PPORT;
558 	int		rval = 0;
559 	uint32_t	use32 = 0;
560 
561 #ifdef	_MULTI_DATAMODEL
562 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
563 		use32 = 1;
564 	}
565 #endif	/* _MULTI_DATAMODEL */
566 
567 	/* Copyout data buffers */
568 	if (dfc2->buf1) {
569 		if (ddi_copyout(dfc2->buf1, dfc1->buf1, dfc1->buf1_size,
570 		    mode)) {
571 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
572 			    "%s: buf1 ddi_copyout failed. (size=%d)",
573 			    emlxs_dfc_xlate(dfc2->cmd),
574 			    dfc2->buf1_size);
575 
576 			rval = DFC_COPYOUT_ERROR;
577 		}
578 		kmem_free(dfc2->buf1, dfc2->buf1_size);
579 		dfc2->buf1 = 0;
580 	}
581 
582 	if (dfc2->buf2) {
583 		if (ddi_copyout(dfc2->buf2, dfc1->buf2, dfc1->buf2_size,
584 		    mode)) {
585 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
586 			    "%s: buf2 ddi_copyout failed. (size=%d)",
587 			    emlxs_dfc_xlate(dfc2->cmd),
588 			    dfc2->buf2_size);
589 
590 			rval = DFC_COPYOUT_ERROR;
591 		}
592 		kmem_free(dfc2->buf2, dfc2->buf2_size);
593 		dfc2->buf2 = 0;
594 	}
595 
596 	if (dfc2->buf3) {
597 		if (ddi_copyout(dfc2->buf3, dfc1->buf3, dfc1->buf3_size,
598 		    mode)) {
599 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
600 			    "%s buf3 ddi_copyout failed. (size=%d)",
601 			    emlxs_dfc_xlate(dfc2->cmd),
602 			    dfc2->buf3_size);
603 
604 			rval = DFC_COPYOUT_ERROR;
605 		}
606 		kmem_free(dfc2->buf3, dfc2->buf3_size);
607 		dfc2->buf3 = 0;
608 	}
609 
610 	if (dfc2->buf4) {
611 		if (ddi_copyout(dfc2->buf4, dfc1->buf4, dfc1->buf4_size,
612 		    mode)) {
613 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
614 			    "%s: buf4 ddi_copyout failed. (size=%d)",
615 			    emlxs_dfc_xlate(dfc2->cmd),
616 			    dfc2->buf4_size);
617 
618 			rval = DFC_COPYOUT_ERROR;
619 		}
620 		kmem_free(dfc2->buf4, dfc2->buf4_size);
621 		dfc2->buf4 = 0;
622 	}
623 
624 	if (use32) {
625 		dfc32_t dfc32;
626 
627 		dfc32.cmd = dfc1->cmd;
628 		dfc32.flag = dfc1->flag;
629 		dfc32.buf1 = (uint32_t)((uintptr_t)dfc1->buf1);
630 		dfc32.buf1_size = dfc1->buf1_size;
631 		dfc32.data1 = dfc1->data1;
632 		dfc32.buf2 = (uint32_t)((uintptr_t)dfc1->buf2);
633 		dfc32.buf2_size = dfc1->buf2_size;
634 		dfc32.data2 = dfc1->data2;
635 		dfc32.buf3 = (uint32_t)((uintptr_t)dfc1->buf3);
636 		dfc32.buf3_size = dfc1->buf3_size;
637 		dfc32.data3 = dfc1->data3;
638 		dfc32.buf4 = (uint32_t)((uintptr_t)dfc1->buf4);
639 		dfc32.buf4_size = dfc1->buf4_size;
640 		dfc32.data4 = dfc1->data4;
641 
642 		if (ddi_copyout((void *)&dfc32, (void *)arg,
643 		    sizeof (dfc32_t), mode)) {
644 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
645 			    "ddi_copyout32 failed.");
646 
647 			rval = DFC_COPYOUT_ERROR;
648 			goto done;
649 		}
650 	} else {
651 		if (ddi_copyout((void *)dfc1, (void *)arg, sizeof (dfc_t),
652 		    mode)) {
653 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
654 			    "ddi_copyout failed.");
655 
656 			rval = DFC_COPYOUT_ERROR;
657 			goto done;
658 		}
659 	}
660 
661 done:
662 	return (rval);
663 
664 } /* emlxs_dfc_copyout() */
665 
666 
667 extern int32_t
emlxs_dfc_manage(emlxs_hba_t * hba,void * arg,int32_t mode)668 emlxs_dfc_manage(emlxs_hba_t *hba, void *arg, int32_t mode)
669 {
670 	dfc_t		dfc1;
671 	dfc_t		dfc2;
672 	int		rval = 0;
673 
674 	/* This copies arg data to dfc1 space, */
675 	/* then creates local dfc2 buffers */
676 	rval = emlxs_dfc_copyin(hba, arg, &dfc1, &dfc2, mode);
677 
678 	if (rval) {
679 		return (rval);
680 	}
681 
682 	rval = emlxs_dfc_func(hba, &dfc2, mode);
683 
684 	if (rval) {
685 		return (rval);
686 	}
687 
688 	/* This copies dfc2 local buffers back to dfc1 addresses */
689 	rval = emlxs_dfc_copyout(hba, arg, &dfc2, &dfc1, mode);
690 
691 	return (rval);
692 
693 } /* emlxs_dfc_manage() */
694 
695 
696 #ifdef FCIO_SUPPORT
697 typedef struct
698 {
699 	uint32_t	code;
700 	char		string[32];
701 	int		(*func)(emlxs_port_t *port, fcio_t *fcio, int32_t mode);
702 } emlxs_fcio_table_t;
703 
704 emlxs_fcio_table_t emlxs_fcio_table[] = {
705 	{FCIO_GET_NUM_DEVS, "GET_NUM_DEVS", emlxs_fcio_get_num_devs},
706 	{FCIO_GET_DEV_LIST, "GET_DEV_LIST", emlxs_fcio_get_dev_list},
707 	{FCIO_GET_SYM_PNAME, "GET_SYM_PNAME", emlxs_fcio_get_sym_pname},
708 	{FCIO_GET_SYM_NNAME, "GET_SYM_NNAME", emlxs_fcio_get_sym_nname},
709 	{FCIO_SET_SYM_PNAME, "SET_SYM_PNAME", emlxs_fcio_unsupported},
710 	{FCIO_SET_SYM_NNAME, "SET_SYM_NNAME", emlxs_fcio_unsupported},
711 	{FCIO_GET_LOGI_PARAMS, "GET_LOGI_PARAMS", emlxs_fcio_get_logi_params},
712 	{FCIO_DEV_LOGIN, "DEV_LOGIN", emlxs_fcio_unsupported},
713 	{FCIO_DEV_LOGOUT, "DEV_LOGOUT", emlxs_fcio_unsupported},
714 	{FCIO_GET_STATE, "GET_STATE", emlxs_fcio_get_state},
715 	{FCIO_DEV_REMOVE, "DEV_REMOVE", emlxs_fcio_unsupported},
716 	{FCIO_GET_FCODE_REV, "GET_FCODE_REV", emlxs_fcio_get_fcode_rev},
717 	{FCIO_GET_FW_REV, "GET_FW_REV", emlxs_fcio_get_fw_rev},
718 	{FCIO_GET_DUMP_SIZE, "GET_DUMP_SIZE", emlxs_fcio_get_dump_size},
719 	{FCIO_FORCE_DUMP, "FORCE_DUMP", emlxs_fcio_force_dump},
720 	{FCIO_GET_DUMP, "GET_DUMP", emlxs_fcio_get_dump},
721 	{FCIO_GET_TOPOLOGY, "GET_TOPOLOGY", emlxs_fcio_get_topology},
722 	{FCIO_RESET_LINK, "RESET_LINK", emlxs_fcio_reset_link},
723 	{FCIO_RESET_HARD, "RESET_HARD", emlxs_fcio_reset_hard},
724 	{FCIO_RESET_HARD_CORE, "RESET_HARD_CORE", emlxs_fcio_reset_hard},
725 	{FCIO_DIAG, "DIAG", emlxs_fcio_diag},
726 	{FCIO_NS, "NS", emlxs_fcio_unsupported},
727 	{FCIO_DOWNLOAD_FW, "DOWNLOAD_FW", emlxs_fcio_download_fw},
728 	{FCIO_GET_HOST_PARAMS, "GET_HOST_PARAMS", emlxs_fcio_get_host_params},
729 	{FCIO_LINK_STATUS, "LINK_STATUS", emlxs_fcio_get_link_status},
730 	{FCIO_DOWNLOAD_FCODE, "DOWNLOAD_FCODE", emlxs_fcio_download_fcode},
731 	{FCIO_GET_NODE_ID, "GET_NODE_ID", emlxs_fcio_get_node_id},
732 	{FCIO_SET_NODE_ID, "SET_NODE_ID", emlxs_fcio_set_node_id},
733 	{FCIO_SEND_NODE_ID, "SEND_NODE_ID", emlxs_fcio_unsupported},
734 	/* {FCIO_GET_P2P_INFO, "GET_P2P_INFO", emlxs_fcio_get_p2p_info}, */
735 	{FCIO_GET_ADAPTER_ATTRIBUTES, "GET_ADAPTER_ATTRIBUTES",
736 	    emlxs_fcio_get_adapter_attrs},
737 	{FCIO_GET_OTHER_ADAPTER_PORTS, "GET_OTHER_ADAPTER_PORTS",
738 	    emlxs_fcio_get_other_adapter_ports},
739 	{FCIO_GET_ADAPTER_PORT_ATTRIBUTES, "GET_ADAPTER_PORT_ATTRIBUTES",
740 	    emlxs_fcio_get_adapter_port_attrs},
741 	{FCIO_GET_DISCOVERED_PORT_ATTRIBUTES, "GET_DISCOVERED_PORT_ATTRIBUTES",
742 	    emlxs_fcio_get_disc_port_attrs},
743 	{FCIO_GET_PORT_ATTRIBUTES, "GET_PORT_ATTRIBUTES",
744 	    emlxs_fcio_get_port_attrs},
745 	{FCIO_GET_ADAPTER_PORT_STATS, "GET_ADAPTER_PORT_STATS",
746 	    emlxs_fcio_unsupported},
747 };	/* emlxs_fcio_table */
748 
749 
750 extern char *
emlxs_fcio_xlate(uint16_t cmd)751 emlxs_fcio_xlate(uint16_t cmd)
752 {
753 	static char	buffer[32];
754 	uint32_t	i;
755 	uint32_t	count;
756 
757 	count = sizeof (emlxs_fcio_table) / sizeof (emlxs_fcio_table_t);
758 	for (i = 0; i < count; i++) {
759 		if (cmd == emlxs_fcio_table[i].code) {
760 			return (emlxs_fcio_table[i].string);
761 		}
762 	}
763 
764 	(void) snprintf(buffer, sizeof (buffer), "Cmd=0x%x", cmd);
765 	return (buffer);
766 
767 } /* emlxs_fcio_xlate() */
768 
769 
770 static int
emlxs_fcio_func(emlxs_port_t * port,fcio_t * fcio,int32_t mode)771 emlxs_fcio_func(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
772 {
773 	uint32_t	i;
774 	uint32_t	count;
775 	int		rval;
776 
777 	count = sizeof (emlxs_fcio_table) / sizeof (emlxs_fcio_table_t);
778 	for (i = 0; i < count; i++) {
779 		if (fcio->fcio_cmd == emlxs_fcio_table[i].code) {
780 			if ((fcio->fcio_cmd != FCIO_DIAG) ||
781 			    (fcio->fcio_cmd_flags != EMLXS_LOG_GET)) {
782 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
783 				    "%s requested.",
784 				    emlxs_fcio_table[i].string);
785 			}
786 
787 			rval = emlxs_fcio_table[i].func(port, fcio, mode);
788 			return (rval);
789 		}
790 	}
791 
792 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
793 	    "Unknown FCIO command. (0x%x)", fcio->fcio_cmd);
794 
795 	return (EFAULT);
796 
797 } /* emlxs_fcio_func() */
798 
799 
800 /* This is used by FCT ports to mimic SFS ports for FCIO support */
801 /*ARGSUSED*/
802 extern int32_t
emlxs_fcio_manage(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)803 emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
804 {
805 	emlxs_port_t	*port = &PPORT;
806 	int32_t		rval = 0;
807 	fcio_t		fcio;
808 	uint32_t	vpi;
809 
810 	/* Map DFC to FCIO */
811 	vpi = (dfc->data4 < MAX_VPORTS)? dfc->data4:0;
812 	port = &VPORT(vpi);
813 
814 	bzero(&fcio, sizeof (fcio_t));
815 	fcio.fcio_flags		= dfc->flag;
816 	fcio.fcio_cmd		= dfc->data1;
817 	fcio.fcio_cmd_flags	= dfc->data2;
818 	fcio.fcio_xfer		= dfc->data3;
819 
820 	if (dfc->buf1_size && dfc->buf1) {
821 		fcio.fcio_ilen = dfc->buf1_size;
822 		fcio.fcio_ibuf = dfc->buf1;
823 	}
824 
825 	if (dfc->buf2_size && dfc->buf2) {
826 		fcio.fcio_olen = dfc->buf2_size;
827 		fcio.fcio_obuf = dfc->buf2;
828 	}
829 
830 	if (dfc->buf3_size && dfc->buf3) {
831 		fcio.fcio_alen = dfc->buf3_size;
832 		fcio.fcio_abuf = dfc->buf3;
833 	}
834 
835 	if (!dfc->buf4 || (dfc->buf4_size < sizeof (uint32_t))) {
836 		EMLXS_MSGF(EMLXS_CONTEXT,
837 		    &emlxs_dfc_error_msg,
838 		    "%s: %s: buf4 invalid. (buf4=%p size=%d)",
839 		    emlxs_dfc_xlate(dfc->cmd), emlxs_fcio_xlate(dfc->data1),
840 		    dfc->buf4, dfc->buf4_size);
841 
842 		rval = EFAULT;
843 		goto done;
844 	}
845 
846 	rval = emlxs_fcio_func(port, &fcio, mode);
847 
848 	/* Map FCIO to DFC */
849 	dfc->flag  = fcio.fcio_flags;
850 	dfc->data1 = fcio.fcio_cmd;
851 	dfc->data2 = fcio.fcio_cmd_flags;
852 	dfc->data3 = fcio.fcio_xfer;
853 
854 done:
855 	/* Set fcio_errno if needed */
856 	if ((rval != 0) && (fcio.fcio_errno == 0)) {
857 		fcio.fcio_errno = FC_FAILURE;
858 	}
859 
860 	bcopy((void *)&fcio.fcio_errno, (void *)dfc->buf4, sizeof (uint32_t));
861 
862 	return (rval);
863 
864 } /* emlxs_fcio_manage() */
865 
866 
867 /*ARGSUSED*/
868 static int32_t
emlxs_fcio_diag(emlxs_port_t * port,fcio_t * fcio,int32_t mode)869 emlxs_fcio_diag(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
870 {
871 	fc_fca_pm_t 	pm;
872 	int32_t		rval = 0;
873 
874 	bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
875 
876 	pm.pm_cmd_len   = fcio->fcio_ilen;
877 	pm.pm_cmd_buf   = fcio->fcio_ibuf;
878 	pm.pm_data_len  = fcio->fcio_alen;
879 	pm.pm_data_buf  = fcio->fcio_abuf;
880 	pm.pm_stat_len  = fcio->fcio_olen;
881 	pm.pm_stat_buf  = fcio->fcio_obuf;
882 	pm.pm_cmd_code  = FC_PORT_DIAG;
883 	pm.pm_cmd_flags = fcio->fcio_cmd_flags;
884 
885 	rval = emlxs_fca_port_manage(port, &pm);
886 
887 	if (rval != FC_SUCCESS) {
888 		fcio->fcio_errno = rval;
889 
890 		if (rval == FC_INVALID_REQUEST) {
891 			rval = ENOTTY;
892 		} else {
893 			rval = EIO;
894 		}
895 	}
896 	if (fcio->fcio_olen > pm.pm_stat_len) {
897 		fcio->fcio_olen = pm.pm_stat_len;
898 	}
899 
900 	return (rval);
901 
902 } /* emlxs_fcio_diag() */
903 
904 
905 #ifndef _MULTI_DATAMODEL
906 /* ARGSUSED */
907 #endif
908 static int32_t
emlxs_fcio_get_host_params(emlxs_port_t * port,fcio_t * fcio,int32_t mode)909 emlxs_fcio_get_host_params(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
910 {
911 	emlxs_hba_t	*hba = HBA;
912 	int32_t		rval = 0;
913 	uint32_t	use32 = 0;
914 	emlxs_config_t	*cfg  = &CFG;
915 
916 #ifdef	_MULTI_DATAMODEL
917 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
918 		use32 = 1;
919 	}
920 #endif	/* _MULTI_DATAMODEL */
921 
922 	if (use32) {
923 		fc_port_dev32_t *port_dev;
924 		uint32_t i;
925 
926 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
927 		    fcio->fcio_olen != sizeof (fc_port_dev32_t)) {
928 			rval = EINVAL;
929 			goto done;
930 		}
931 
932 		port_dev = (fc_port_dev32_t *)fcio->fcio_obuf;
933 
934 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
935 		    "fcio_get_host_params: fct_flags=%x ulp_statec=%x",
936 		    port->fct_flags, port->ulp_statec);
937 
938 		if ((port->mode == MODE_TARGET) &&
939 		    (port->fct_port) &&
940 		    (port->fct_flags & FCT_STATE_PORT_ONLINE)) {
941 			port_dev->dev_state = port->ulp_statec;
942 			port_dev->dev_did.port_id = port->did;
943 
944 			if (hba->topology == TOPOLOGY_LOOP) {
945 				for (i = 0; i < port->alpa_map[0]; i++) {
946 				if (port->alpa_map[i + 1] == port->did) {
947 					port_dev->dev_did.priv_lilp_posit =
948 					    (uint8_t)(i & 0xff);
949 					goto done;
950 				}
951 				}
952 			}
953 
954 		} else {
955 			port_dev->dev_state = FC_STATE_OFFLINE;
956 			port_dev->dev_did.port_id = 0;
957 		}
958 
959 		port_dev->dev_hard_addr.hard_addr =
960 		    cfg[CFG_ASSIGN_ALPA].current;
961 
962 		bcopy((caddr_t)&port->wwpn,
963 		    (caddr_t)&port_dev->dev_pwwn, 8);
964 		bcopy((caddr_t)&port->wwnn,
965 		    (caddr_t)&port_dev->dev_nwwn, 8);
966 
967 		port_dev->dev_type[0] = LE_SWAP32(0x00000120);
968 		port_dev->dev_type[1] = LE_SWAP32(0x00000001);
969 
970 	} else {
971 
972 		fc_port_dev_t *port_dev;
973 		uint32_t i;
974 
975 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
976 		    fcio->fcio_olen != sizeof (fc_port_dev_t)) {
977 			rval = EINVAL;
978 			goto done;
979 		}
980 
981 		port_dev = (fc_port_dev_t *)fcio->fcio_obuf;
982 
983 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
984 		    "fcio_get_host_params: fct_flags=%x ulp_statec=%x",
985 		    port->fct_flags, port->ulp_statec);
986 
987 		if ((port->mode == MODE_TARGET) &&
988 		    (port->fct_port) &&
989 		    (port->fct_flags & FCT_STATE_PORT_ONLINE)) {
990 			port_dev->dev_state = port->ulp_statec;
991 			port_dev->dev_did.port_id = port->did;
992 
993 			if (hba->topology == TOPOLOGY_LOOP) {
994 				for (i = 0; i < port->alpa_map[0]; i++) {
995 				if (port->alpa_map[i + 1] == port->did) {
996 					port_dev->dev_did.priv_lilp_posit =
997 					    (uint8_t)(i & 0xff);
998 					goto done;
999 				}
1000 				}
1001 			}
1002 
1003 		} else {
1004 			port_dev->dev_state = FC_STATE_OFFLINE;
1005 			port_dev->dev_did.port_id = 0;
1006 		}
1007 
1008 		port_dev->dev_hard_addr.hard_addr =
1009 		    cfg[CFG_ASSIGN_ALPA].current;
1010 
1011 		bcopy((caddr_t)&port->wwpn,
1012 		    (caddr_t)&port_dev->dev_pwwn, 8);
1013 		bcopy((caddr_t)&port->wwnn,
1014 		    (caddr_t)&port_dev->dev_nwwn, 8);
1015 
1016 		port_dev->dev_type[0] = LE_SWAP32(0x00000120);
1017 		port_dev->dev_type[1] = LE_SWAP32(0x00000001);
1018 	}
1019 
1020 done:
1021 	return (rval);
1022 
1023 } /* emlxs_fcio_get_host_params() */
1024 
1025 
1026 /*ARGSUSED*/
1027 static int32_t
emlxs_fcio_reset_link(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1028 emlxs_fcio_reset_link(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1029 {
1030 	int32_t		rval = 0;
1031 	uint8_t		null_wwn[8];
1032 
1033 	if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1034 	    fcio->fcio_ilen != 8) {
1035 		rval = EINVAL;
1036 		goto done;
1037 	}
1038 
1039 	if (port->mode != MODE_TARGET) {
1040 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1041 		    "fcio_reset_link failed. Port is not in target mode.");
1042 
1043 		fcio->fcio_errno = FC_FAILURE;
1044 		rval = EIO;
1045 		goto done;
1046 	}
1047 
1048 	bzero(null_wwn, 8);
1049 
1050 	if (bcmp((uint8_t *)fcio->fcio_ibuf, null_wwn, 8) == 0) {
1051 		rval = emlxs_fca_reset(port, FC_FCA_LINK_RESET);
1052 
1053 		if (rval != FC_SUCCESS) {
1054 			fcio->fcio_errno = rval;
1055 			rval = EIO;
1056 		}
1057 	} else {
1058 		rval = ENOTSUP;
1059 	}
1060 
1061 done:
1062 	return (rval);
1063 
1064 } /* emlxs_fcio_reset_link() */
1065 
1066 
1067 /*ARGSUSED*/
1068 static int32_t
emlxs_fcio_reset_hard(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1069 emlxs_fcio_reset_hard(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1070 {
1071 	int32_t		rval = 0;
1072 
1073 	if (port->mode != MODE_TARGET) {
1074 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1075 		    "fcio_reset_hard failed. Port is not in target mode.");
1076 
1077 		fcio->fcio_errno = FC_FAILURE;
1078 		rval = EIO;
1079 		goto done;
1080 	}
1081 
1082 	rval = emlxs_reset(port, FC_FCA_RESET);
1083 
1084 	if (rval != FC_SUCCESS) {
1085 		fcio->fcio_errno = rval;
1086 		rval = EIO;
1087 	}
1088 
1089 done:
1090 	return (rval);
1091 
1092 } /* emlxs_fcio_reset_hard() */
1093 
1094 
1095 /*ARGSUSED*/
1096 static int32_t
emlxs_fcio_download_fw(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1097 emlxs_fcio_download_fw(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1098 {
1099 	int32_t		rval = 0;
1100 	fc_fca_pm_t	pm;
1101 
1102 	if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1103 	    fcio->fcio_ilen == 0) {
1104 		rval = EINVAL;
1105 		goto done;
1106 	}
1107 
1108 	bzero((caddr_t)&pm, sizeof (pm));
1109 
1110 	pm.pm_cmd_flags = FC_FCA_PM_WRITE;
1111 	pm.pm_cmd_code  = FC_PORT_DOWNLOAD_FW;
1112 	pm.pm_data_len  = fcio->fcio_ilen;
1113 	pm.pm_data_buf  = fcio->fcio_ibuf;
1114 
1115 	rval = emlxs_fca_port_manage(port, &pm);
1116 
1117 	if ((rval != FC_SUCCESS) && (rval != EMLXS_REBOOT_REQUIRED)) {
1118 		fcio->fcio_errno = rval;
1119 		rval = EIO;
1120 	}
1121 
1122 done:
1123 	return (rval);
1124 
1125 } /* emlxs_fcio_download_fw() */
1126 
1127 
1128 /*ARGSUSED*/
1129 static int32_t
emlxs_fcio_get_fw_rev(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1130 emlxs_fcio_get_fw_rev(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1131 {
1132 	int32_t		rval = 0;
1133 	fc_fca_pm_t	pm;
1134 
1135 	if (fcio->fcio_xfer != FCIO_XFER_READ ||
1136 	    fcio->fcio_olen < FC_FW_REV_SIZE) {
1137 		rval = EINVAL;
1138 		goto done;
1139 	}
1140 
1141 	bzero((caddr_t)&pm, sizeof (pm));
1142 
1143 	pm.pm_cmd_flags = FC_FCA_PM_READ;
1144 	pm.pm_cmd_code  = FC_PORT_GET_FW_REV;
1145 	pm.pm_data_len  = fcio->fcio_olen;
1146 	pm.pm_data_buf  = fcio->fcio_obuf;
1147 
1148 	rval = emlxs_fca_port_manage(port, &pm);
1149 
1150 	if (rval != FC_SUCCESS) {
1151 		fcio->fcio_errno = rval;
1152 		rval = EIO;
1153 	}
1154 
1155 done:
1156 	return (rval);
1157 
1158 } /* emlxs_fcio_get_fw_rev() */
1159 
1160 
1161 /*ARGSUSED*/
1162 static int32_t
emlxs_fcio_get_fcode_rev(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1163 emlxs_fcio_get_fcode_rev(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1164 {
1165 	int32_t		rval = 0;
1166 	fc_fca_pm_t	pm;
1167 
1168 	if (fcio->fcio_xfer != FCIO_XFER_READ ||
1169 	    fcio->fcio_olen < FC_FCODE_REV_SIZE) {
1170 		rval = EINVAL;
1171 		goto done;
1172 	}
1173 
1174 	bzero((caddr_t)&pm, sizeof (pm));
1175 
1176 	pm.pm_cmd_flags = FC_FCA_PM_READ;
1177 	pm.pm_cmd_code  = FC_PORT_GET_FCODE_REV;
1178 	pm.pm_data_len  = fcio->fcio_olen;
1179 	pm.pm_data_buf  = fcio->fcio_obuf;
1180 
1181 	rval = emlxs_fca_port_manage(port, &pm);
1182 
1183 	if (rval != FC_SUCCESS) {
1184 		fcio->fcio_errno = rval;
1185 		rval = EIO;
1186 	}
1187 
1188 done:
1189 	return (rval);
1190 
1191 } /* emlxs_fcio_get_fcode_rev() */
1192 
1193 
1194 /*ARGSUSED*/
1195 static int32_t
emlxs_fcio_download_fcode(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1196 emlxs_fcio_download_fcode(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1197 {
1198 	int32_t		rval = 0;
1199 	fc_fca_pm_t	pm;
1200 
1201 	if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1202 	    fcio->fcio_ilen == 0) {
1203 		rval = EINVAL;
1204 		goto done;
1205 	}
1206 
1207 	bzero((caddr_t)&pm, sizeof (pm));
1208 
1209 	pm.pm_cmd_flags = FC_FCA_PM_WRITE;
1210 	pm.pm_cmd_code  = FC_PORT_DOWNLOAD_FCODE;
1211 	pm.pm_data_len  = fcio->fcio_ilen;
1212 	pm.pm_data_buf  = fcio->fcio_ibuf;
1213 
1214 	rval = emlxs_fca_port_manage(port, &pm);
1215 
1216 	if (rval != FC_SUCCESS) {
1217 		fcio->fcio_errno = rval;
1218 		rval = EIO;
1219 	}
1220 
1221 done:
1222 	return (rval);
1223 
1224 } /* emlxs_fcio_download_fcode() */
1225 
1226 
1227 #ifndef _MULTI_DATAMODEL
1228 /* ARGSUSED */
1229 #endif
1230 static int32_t
emlxs_fcio_get_adapter_attrs(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1231 emlxs_fcio_get_adapter_attrs(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1232 {
1233 	emlxs_hba_t	*hba = HBA;
1234 	int32_t		rval = 0;
1235 	uint32_t	use32 = 0;
1236 	emlxs_vpd_t	*vpd = &VPD;
1237 
1238 #ifdef	_MULTI_DATAMODEL
1239 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
1240 		use32 = 1;
1241 	}
1242 #endif	/* _MULTI_DATAMODEL */
1243 
1244 	if (use32) {
1245 		fc_hba_adapter_attributes32_t	*hba_attrs;
1246 
1247 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
1248 		    fcio->fcio_olen <
1249 		    sizeof (fc_hba_adapter_attributes32_t)) {
1250 			rval = EINVAL;
1251 			goto done;
1252 		}
1253 
1254 		hba_attrs =
1255 		    (fc_hba_adapter_attributes32_t *)fcio->fcio_obuf;
1256 
1257 		hba_attrs->version = FC_HBA_ADAPTER_ATTRIBUTES_VERSION;
1258 		(void) strncpy(hba_attrs->Manufacturer,
1259 		    hba->model_info.manufacturer,
1260 		    (sizeof (hba_attrs->Manufacturer)-1));
1261 		(void) strncpy(hba_attrs->SerialNumber, vpd->serial_num,
1262 		    (sizeof (hba_attrs->SerialNumber)-1));
1263 		(void) strncpy(hba_attrs->Model, hba->model_info.model,
1264 		    (sizeof (hba_attrs->Model)-1));
1265 		(void) strncpy(hba_attrs->ModelDescription,
1266 		    hba->model_info.model_desc,
1267 		    (sizeof (hba_attrs->ModelDescription)-1));
1268 		bcopy((caddr_t)&port->wwnn,
1269 		    (caddr_t)&hba_attrs->NodeWWN, 8);
1270 		(void) strncpy((caddr_t)hba_attrs->NodeSymbolicName,
1271 		    (caddr_t)port->snn,
1272 		    (sizeof (hba_attrs->NodeSymbolicName)-1));
1273 		(void) snprintf(hba_attrs->HardwareVersion,
1274 		    (sizeof (hba_attrs->HardwareVersion)-1),
1275 		    "%x", vpd->biuRev);
1276 		(void) snprintf(hba_attrs->DriverVersion,
1277 		    (sizeof (hba_attrs->DriverVersion)-1),
1278 		    "%s (%s)", emlxs_version, emlxs_revision);
1279 		(void) strncpy(hba_attrs->OptionROMVersion,
1280 		    vpd->fcode_version,
1281 		    (sizeof (hba_attrs->OptionROMVersion)-1));
1282 		(void) snprintf(hba_attrs->FirmwareVersion,
1283 		    (sizeof (hba_attrs->FirmwareVersion)-1),
1284 		    "%s (%s)", vpd->fw_version, vpd->fw_label);
1285 		(void) strncpy(hba_attrs->DriverName, DRIVER_NAME,
1286 		    (sizeof (hba_attrs->DriverName)-1));
1287 		hba_attrs->VendorSpecificID =
1288 		    (hba->model_info.device_id << 16) |
1289 		    hba->model_info.vendor_id;
1290 		hba_attrs->NumberOfPorts = hba->num_of_ports;
1291 	} else {
1292 		fc_hba_adapter_attributes_t	*hba_attrs;
1293 
1294 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
1295 		    fcio->fcio_olen <
1296 		    sizeof (fc_hba_adapter_attributes_t)) {
1297 			rval = EINVAL;
1298 			goto done;
1299 		}
1300 
1301 		hba_attrs =
1302 		    (fc_hba_adapter_attributes_t *)fcio->fcio_obuf;
1303 
1304 		hba_attrs->version = FC_HBA_ADAPTER_ATTRIBUTES_VERSION;
1305 		(void) strncpy(hba_attrs->Manufacturer,
1306 		    hba->model_info.manufacturer,
1307 		    (sizeof (hba_attrs->Manufacturer)-1));
1308 		(void) strncpy(hba_attrs->SerialNumber, vpd->serial_num,
1309 		    (sizeof (hba_attrs->SerialNumber)-1));
1310 		(void) strncpy(hba_attrs->Model, hba->model_info.model,
1311 		    (sizeof (hba_attrs->Model)-1));
1312 		(void) strncpy(hba_attrs->ModelDescription,
1313 		    hba->model_info.model_desc,
1314 		    (sizeof (hba_attrs->ModelDescription)-1));
1315 		bcopy((caddr_t)&port->wwnn,
1316 		    (caddr_t)&hba_attrs->NodeWWN, 8);
1317 		(void) strncpy((caddr_t)hba_attrs->NodeSymbolicName,
1318 		    (caddr_t)port->snn,
1319 		    (sizeof (hba_attrs->NodeSymbolicName)-1));
1320 		(void) snprintf(hba_attrs->HardwareVersion,
1321 		    (sizeof (hba_attrs->HardwareVersion)-1),
1322 		    "%x", vpd->biuRev);
1323 		(void) snprintf(hba_attrs->DriverVersion,
1324 		    (sizeof (hba_attrs->DriverVersion)-1),
1325 		    "%s (%s)", emlxs_version, emlxs_revision);
1326 		(void) strncpy(hba_attrs->OptionROMVersion,
1327 		    vpd->fcode_version,
1328 		    (sizeof (hba_attrs->OptionROMVersion)-1));
1329 		(void) snprintf(hba_attrs->FirmwareVersion,
1330 		    (sizeof (hba_attrs->FirmwareVersion)-1),
1331 		    "%s (%s)", vpd->fw_version, vpd->fw_label);
1332 		(void) strncpy(hba_attrs->DriverName, DRIVER_NAME,
1333 		    (sizeof (hba_attrs->DriverName)-1));
1334 		hba_attrs->VendorSpecificID =
1335 		    (hba->model_info.device_id << 16) |
1336 		    hba->model_info.vendor_id;
1337 		hba_attrs->NumberOfPorts = hba->num_of_ports;
1338 	}
1339 
1340 done:
1341 	return (rval);
1342 
1343 } /* emlxs_fcio_get_adapter_attrs() */
1344 
1345 
1346 #ifndef _MULTI_DATAMODEL
1347 /* ARGSUSED */
1348 #endif
1349 static int32_t
emlxs_fcio_get_adapter_port_attrs(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1350 emlxs_fcio_get_adapter_port_attrs(emlxs_port_t *port, fcio_t *fcio,
1351     int32_t mode)
1352 {
1353 	emlxs_hba_t	*hba = HBA;
1354 	int32_t		rval = 0;
1355 	uint32_t	use32 = 0;
1356 	emlxs_vpd_t	*vpd = &VPD;
1357 
1358 #ifdef	_MULTI_DATAMODEL
1359 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
1360 		use32 = 1;
1361 	}
1362 #endif	/* _MULTI_DATAMODEL */
1363 
1364 	if (use32) {
1365 		fc_hba_port_attributes32_t  *port_attrs;
1366 		uint32_t value1;
1367 		uint32_t value2;
1368 
1369 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
1370 		    fcio->fcio_olen <
1371 		    sizeof (fc_hba_port_attributes32_t)) {
1372 			rval = EINVAL;
1373 			goto done;
1374 		}
1375 
1376 		port_attrs =
1377 		    (fc_hba_port_attributes32_t *)fcio->fcio_obuf;
1378 
1379 		port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
1380 		port_attrs->lastChange = 0;
1381 		port_attrs->fp_minor   = 0;
1382 		bcopy((caddr_t)&port->wwnn,
1383 		    (caddr_t)&port_attrs->NodeWWN, 8);
1384 		bcopy((caddr_t)&port->wwpn,
1385 		    (caddr_t)&port_attrs->PortWWN, 8);
1386 
1387 		if ((port->mode != MODE_TARGET) ||
1388 		    (port->ulp_statec == FC_STATE_OFFLINE)) {
1389 			/* port_attrs->PortFcId   */
1390 			/* port_attrs->PortType   */
1391 			/* port_attrs->PortSpeed  */
1392 			/* port_attrs->FabricName */
1393 			port_attrs->PortState =
1394 			    FC_HBA_PORTSTATE_OFFLINE;
1395 		} else {
1396 			port_attrs->PortFcId  = port->did;
1397 			port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
1398 
1399 			if (hba->topology == TOPOLOGY_LOOP) {
1400 				if (hba->flag & FC_FABRIC_ATTACHED) {
1401 					port_attrs->PortType =
1402 					    FC_HBA_PORTTYPE_NLPORT;
1403 				} else {
1404 					port_attrs->PortType =
1405 					    FC_HBA_PORTTYPE_LPORT;
1406 				}
1407 
1408 			} else {
1409 				if (hba->flag & FC_PT_TO_PT) {
1410 					port_attrs->PortType =
1411 					    FC_HBA_PORTTYPE_PTP;
1412 				} else {
1413 					port_attrs->PortType =
1414 					    FC_HBA_PORTTYPE_NPORT;
1415 				}
1416 			}
1417 
1418 			if (hba->flag & FC_FABRIC_ATTACHED) {
1419 				bcopy(&port->fabric_sparam.portName,
1420 				    (caddr_t)&port_attrs->FabricName,
1421 				    sizeof (port_attrs->FabricName));
1422 			}
1423 
1424 			switch (hba->linkspeed) {
1425 			case 0:
1426 				port_attrs->PortSpeed =
1427 				    HBA_PORTSPEED_1GBIT;
1428 				break;
1429 			case LA_1GHZ_LINK:
1430 				port_attrs->PortSpeed =
1431 				    HBA_PORTSPEED_1GBIT;
1432 				break;
1433 			case LA_2GHZ_LINK:
1434 				port_attrs->PortSpeed =
1435 				    HBA_PORTSPEED_2GBIT;
1436 				break;
1437 			case LA_4GHZ_LINK:
1438 				port_attrs->PortSpeed =
1439 				    HBA_PORTSPEED_4GBIT;
1440 				break;
1441 			case LA_8GHZ_LINK:
1442 				port_attrs->PortSpeed =
1443 				    HBA_PORTSPEED_8GBIT;
1444 				break;
1445 			case LA_10GHZ_LINK:
1446 				port_attrs->PortSpeed =
1447 				    HBA_PORTSPEED_10GBIT;
1448 				break;
1449 			case LA_16GHZ_LINK:
1450 				port_attrs->PortSpeed =
1451 				    HBA_PORTSPEED_16GBIT;
1452 				break;
1453 			case LA_32GHZ_LINK:
1454 				port_attrs->PortSpeed =
1455 				    HBA_PORTSPEED_32GBIT;
1456 				break;
1457 			default:
1458 				port_attrs->PortSpeed =
1459 				    HBA_PORTSPEED_UNKNOWN;
1460 			}
1461 
1462 			port_attrs->NumberofDiscoveredPorts =
1463 			    emlxs_nport_count(port);
1464 		}
1465 
1466 		port_attrs->PortSupportedClassofService =
1467 		    LE_SWAP32(FC_NS_CLASS3);
1468 		(void) strncpy((caddr_t)port_attrs->PortSymbolicName,
1469 		    (caddr_t)port->spn,
1470 		    (sizeof (port_attrs->PortSymbolicName)-1));
1471 
1472 		/* Set the hba speed limit */
1473 		if (vpd->link_speed & LMT_32GB_CAPABLE) {
1474 			port_attrs->PortSupportedSpeed |=
1475 			    FC_HBA_PORTSPEED_32GBIT;
1476 		}
1477 		if (vpd->link_speed & LMT_16GB_CAPABLE) {
1478 			port_attrs->PortSupportedSpeed |=
1479 			    FC_HBA_PORTSPEED_16GBIT;
1480 		}
1481 		if (vpd->link_speed & LMT_10GB_CAPABLE) {
1482 			port_attrs->PortSupportedSpeed |=
1483 			    FC_HBA_PORTSPEED_10GBIT;
1484 		}
1485 		if (vpd->link_speed & LMT_8GB_CAPABLE) {
1486 			port_attrs->PortSupportedSpeed |=
1487 			    FC_HBA_PORTSPEED_8GBIT;
1488 		}
1489 		if (vpd->link_speed & LMT_4GB_CAPABLE) {
1490 			port_attrs->PortSupportedSpeed |=
1491 			    FC_HBA_PORTSPEED_4GBIT;
1492 		}
1493 		if (vpd->link_speed & LMT_2GB_CAPABLE) {
1494 			port_attrs->PortSupportedSpeed |=
1495 			    FC_HBA_PORTSPEED_2GBIT;
1496 		}
1497 		if (vpd->link_speed & LMT_1GB_CAPABLE) {
1498 			port_attrs->PortSupportedSpeed |=
1499 			    FC_HBA_PORTSPEED_1GBIT;
1500 		}
1501 
1502 		value1 = 0x00000120;
1503 		value2 = 0x00000001;
1504 
1505 		bcopy((caddr_t)&value1,
1506 		    (caddr_t)&port_attrs->PortSupportedFc4Types[0], 4);
1507 		bcopy((caddr_t)&value2,
1508 		    (caddr_t)&port_attrs->PortSupportedFc4Types[4], 4);
1509 
1510 		bcopy((caddr_t)&value1,
1511 		    (caddr_t)&port_attrs->PortActiveFc4Types[0], 4);
1512 		bcopy((caddr_t)&value2,
1513 		    (caddr_t)&port_attrs->PortActiveFc4Types[4], 4);
1514 
1515 		port_attrs->PortMaxFrameSize = FF_FRAME_SIZE;
1516 
1517 	} else {
1518 
1519 		fc_hba_port_attributes_t  *port_attrs;
1520 		uint32_t value1;
1521 		uint32_t value2;
1522 
1523 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
1524 		    fcio->fcio_olen <
1525 		    sizeof (fc_hba_port_attributes_t)) {
1526 			rval = EINVAL;
1527 			goto done;
1528 		}
1529 
1530 		port_attrs =
1531 		    (fc_hba_port_attributes_t *)fcio->fcio_obuf;
1532 
1533 		port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
1534 		port_attrs->lastChange = 0;
1535 		port_attrs->fp_minor   = 0;
1536 		bcopy((caddr_t)&port->wwnn,
1537 		    (caddr_t)&port_attrs->NodeWWN, 8);
1538 		bcopy((caddr_t)&port->wwpn,
1539 		    (caddr_t)&port_attrs->PortWWN, 8);
1540 
1541 		if (port->mode != MODE_TARGET ||
1542 		    (port->ulp_statec == FC_STATE_OFFLINE)) {
1543 			/* port_attrs->PortFcId   */
1544 			/* port_attrs->PortType   */
1545 			/* port_attrs->PortSpeed  */
1546 			/* port_attrs->FabricName */
1547 			port_attrs->PortState =
1548 			    FC_HBA_PORTSTATE_OFFLINE;
1549 		} else {
1550 			port_attrs->PortFcId  = port->did;
1551 			port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
1552 
1553 			if (hba->topology == TOPOLOGY_LOOP) {
1554 				if (hba->flag & FC_FABRIC_ATTACHED) {
1555 					port_attrs->PortType =
1556 					    FC_HBA_PORTTYPE_NLPORT;
1557 				} else {
1558 					port_attrs->PortType =
1559 					    FC_HBA_PORTTYPE_LPORT;
1560 				}
1561 
1562 			} else {
1563 				if (hba->flag & FC_PT_TO_PT) {
1564 					port_attrs->PortType =
1565 					    FC_HBA_PORTTYPE_PTP;
1566 				} else {
1567 					port_attrs->PortType =
1568 					    FC_HBA_PORTTYPE_NPORT;
1569 				}
1570 			}
1571 
1572 			if (hba->flag & FC_FABRIC_ATTACHED) {
1573 				bcopy(&port->fabric_sparam.portName,
1574 				    (caddr_t)&port_attrs->FabricName,
1575 				    sizeof (port_attrs->FabricName));
1576 			}
1577 
1578 			switch (hba->linkspeed) {
1579 			case 0:
1580 				port_attrs->PortSpeed =
1581 				    HBA_PORTSPEED_1GBIT;
1582 				break;
1583 			case LA_1GHZ_LINK:
1584 				port_attrs->PortSpeed =
1585 				    HBA_PORTSPEED_1GBIT;
1586 				break;
1587 			case LA_2GHZ_LINK:
1588 				port_attrs->PortSpeed =
1589 				    HBA_PORTSPEED_2GBIT;
1590 				break;
1591 			case LA_4GHZ_LINK:
1592 				port_attrs->PortSpeed =
1593 				    HBA_PORTSPEED_4GBIT;
1594 				break;
1595 			case LA_8GHZ_LINK:
1596 				port_attrs->PortSpeed =
1597 				    HBA_PORTSPEED_8GBIT;
1598 				break;
1599 			case LA_10GHZ_LINK:
1600 				port_attrs->PortSpeed =
1601 				    HBA_PORTSPEED_10GBIT;
1602 				break;
1603 			case LA_16GHZ_LINK:
1604 				port_attrs->PortSpeed =
1605 				    HBA_PORTSPEED_16GBIT;
1606 				break;
1607 			case LA_32GHZ_LINK:
1608 				port_attrs->PortSpeed =
1609 				    HBA_PORTSPEED_32GBIT;
1610 				break;
1611 			default:
1612 				port_attrs->PortSpeed =
1613 				    HBA_PORTSPEED_UNKNOWN;
1614 			}
1615 
1616 			port_attrs->NumberofDiscoveredPorts =
1617 			    emlxs_nport_count(port);
1618 		}
1619 
1620 		port_attrs->PortSupportedClassofService =
1621 		    LE_SWAP32(FC_NS_CLASS3);
1622 		(void) strncpy((caddr_t)port_attrs->PortSymbolicName,
1623 		    (caddr_t)port->spn,
1624 		    (sizeof (port_attrs->PortSymbolicName)-1));
1625 
1626 		/* Set the hba speed limit */
1627 		if (vpd->link_speed & LMT_32GB_CAPABLE) {
1628 			port_attrs->PortSupportedSpeed |=
1629 			    FC_HBA_PORTSPEED_32GBIT;
1630 		}
1631 		if (vpd->link_speed & LMT_16GB_CAPABLE) {
1632 			port_attrs->PortSupportedSpeed |=
1633 			    FC_HBA_PORTSPEED_16GBIT;
1634 		}
1635 		if (vpd->link_speed & LMT_10GB_CAPABLE) {
1636 			port_attrs->PortSupportedSpeed |=
1637 			    FC_HBA_PORTSPEED_10GBIT;
1638 		}
1639 		if (vpd->link_speed & LMT_8GB_CAPABLE) {
1640 			port_attrs->PortSupportedSpeed |=
1641 			    FC_HBA_PORTSPEED_8GBIT;
1642 		}
1643 		if (vpd->link_speed & LMT_4GB_CAPABLE) {
1644 			port_attrs->PortSupportedSpeed |=
1645 			    FC_HBA_PORTSPEED_4GBIT;
1646 		}
1647 		if (vpd->link_speed & LMT_2GB_CAPABLE) {
1648 			port_attrs->PortSupportedSpeed |=
1649 			    FC_HBA_PORTSPEED_2GBIT;
1650 		}
1651 		if (vpd->link_speed & LMT_1GB_CAPABLE) {
1652 			port_attrs->PortSupportedSpeed |=
1653 			    FC_HBA_PORTSPEED_1GBIT;
1654 		}
1655 
1656 		value1 = 0x00000120;
1657 		value2 = 0x00000001;
1658 
1659 		bcopy((caddr_t)&value1,
1660 		    (caddr_t)&port_attrs->PortSupportedFc4Types[0], 4);
1661 		bcopy((caddr_t)&value2,
1662 		    (caddr_t)&port_attrs->PortSupportedFc4Types[4], 4);
1663 
1664 		bcopy((caddr_t)&value1,
1665 		    (caddr_t)&port_attrs->PortActiveFc4Types[0], 4);
1666 		bcopy((caddr_t)&value2,
1667 		    (caddr_t)&port_attrs->PortActiveFc4Types[4], 4);
1668 
1669 		port_attrs->PortMaxFrameSize = FF_FRAME_SIZE;
1670 	}
1671 
1672 done:
1673 	return (rval);
1674 
1675 } /* emlxs_fcio_get_adapter_port_attrs() */
1676 
1677 
1678 /*ARGSUSED*/
1679 static int32_t
emlxs_fcio_get_node_id(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1680 emlxs_fcio_get_node_id(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1681 {
1682 	int32_t		rval = 0;
1683 	fc_fca_pm_t	pm;
1684 
1685 	if (fcio->fcio_xfer != FCIO_XFER_READ ||
1686 	    fcio->fcio_olen < sizeof (fc_rnid_t)) {
1687 		rval = EINVAL;
1688 		goto done;
1689 	}
1690 
1691 	bzero((caddr_t)&pm, sizeof (pm));
1692 
1693 	pm.pm_cmd_flags = FC_FCA_PM_READ;
1694 	pm.pm_cmd_code  = FC_PORT_GET_NODE_ID;
1695 	pm.pm_data_len  = fcio->fcio_olen;
1696 	pm.pm_data_buf  = fcio->fcio_obuf;
1697 
1698 	rval = emlxs_fca_port_manage(port, &pm);
1699 
1700 	if (rval != FC_SUCCESS) {
1701 		fcio->fcio_errno = rval;
1702 		rval = EIO;
1703 	}
1704 
1705 done:
1706 	return (rval);
1707 
1708 } /* emlxs_fcio_get_node_id() */
1709 
1710 
1711 /*ARGSUSED*/
1712 static int32_t
emlxs_fcio_set_node_id(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1713 emlxs_fcio_set_node_id(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1714 {
1715 	int32_t		rval = 0;
1716 	fc_fca_pm_t	pm;
1717 
1718 	if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1719 	    fcio->fcio_ilen < sizeof (fc_rnid_t)) {
1720 		rval = EINVAL;
1721 		goto done;
1722 	}
1723 
1724 	bzero((caddr_t)&pm, sizeof (pm));
1725 
1726 	pm.pm_cmd_flags = FC_FCA_PM_READ;
1727 	pm.pm_cmd_code  = FC_PORT_SET_NODE_ID;
1728 	pm.pm_data_len  = fcio->fcio_ilen;
1729 	pm.pm_data_buf  = fcio->fcio_ibuf;
1730 
1731 	rval = emlxs_fca_port_manage(port, &pm);
1732 
1733 	if (rval != FC_SUCCESS) {
1734 		fcio->fcio_errno = rval;
1735 		rval = EIO;
1736 	}
1737 
1738 done:
1739 	return (rval);
1740 
1741 } /* emlxs_fcio_set_node_id() */
1742 
1743 
1744 
1745 
1746 /*ARGSUSED*/
1747 static int32_t
emlxs_fcio_get_num_devs(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1748 emlxs_fcio_get_num_devs(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1749 {
1750 	int32_t		rval = 0;
1751 
1752 	if (fcio->fcio_xfer != FCIO_XFER_READ ||
1753 	    fcio->fcio_olen < sizeof (uint32_t)) {
1754 		rval = EINVAL;
1755 		goto done;
1756 	}
1757 
1758 	if (port->mode == MODE_TARGET) {
1759 		*(uint32_t *)fcio->fcio_obuf = emlxs_nport_count(port);
1760 	}
1761 
1762 done:
1763 	return (rval);
1764 
1765 } /* emlxs_fcio_get_num_devs() */
1766 
1767 
1768 #ifndef _MULTI_DATAMODEL
1769 /* ARGSUSED */
1770 #endif
1771 static int32_t
emlxs_fcio_get_dev_list(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1772 emlxs_fcio_get_dev_list(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1773 {
1774 	emlxs_hba_t	*hba = HBA;
1775 	int32_t		rval = 0;
1776 	uint32_t	use32 = 0;
1777 
1778 #ifdef	_MULTI_DATAMODEL
1779 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
1780 		use32 = 1;
1781 	}
1782 #endif	/* _MULTI_DATAMODEL */
1783 
1784 	if (use32) {
1785 		fc_port_dev32_t *port_dev;
1786 		uint32_t max_count;
1787 		uint32_t i;
1788 		uint32_t j;
1789 		emlxs_node_t *nlp;
1790 		uint32_t nport_count = 0;
1791 
1792 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
1793 		    fcio->fcio_alen < sizeof (uint32_t)) {
1794 			rval = EINVAL;
1795 			goto done;
1796 		}
1797 
1798 		port_dev = (fc_port_dev32_t *)fcio->fcio_obuf;
1799 		max_count = fcio->fcio_olen / sizeof (fc_port_dev32_t);
1800 
1801 		rw_enter(&port->node_rwlock, RW_READER);
1802 
1803 		if (port->mode == MODE_TARGET) {
1804 			nport_count = emlxs_nport_count(port);
1805 		}
1806 
1807 		*(uint32_t *)fcio->fcio_abuf = nport_count;
1808 
1809 		if (nport_count == 0) {
1810 			rw_exit(&port->node_rwlock);
1811 
1812 			fcio->fcio_errno = FC_NO_MAP;
1813 			rval = EIO;
1814 			goto done;
1815 		}
1816 
1817 		if (nport_count > max_count) {
1818 			rw_exit(&port->node_rwlock);
1819 
1820 			fcio->fcio_errno = FC_TOOMANY;
1821 			rval = EIO;
1822 			goto done;
1823 		}
1824 
1825 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
1826 			nlp = port->node_table[i];
1827 			while (nlp != NULL) {
1828 			if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) {
1829 				port_dev->dev_dtype = 0;
1830 				port_dev->dev_type[0] =
1831 				    BE_SWAP32(0x00000100);
1832 				port_dev->dev_state =
1833 				    PORT_DEVICE_LOGGED_IN;
1834 				port_dev->dev_did.port_id =
1835 				    nlp->nlp_DID;
1836 				port_dev->dev_did.priv_lilp_posit = 0;
1837 				port_dev->dev_hard_addr.hard_addr = 0;
1838 
1839 		if (hba->topology == TOPOLOGY_LOOP) {
1840 			for (j = 1; j < port->alpa_map[0]; j++) {
1841 				if (nlp->nlp_DID == port->alpa_map[j]) {
1842 					port_dev->dev_did.priv_lilp_posit = j-1;
1843 					goto done;
1844 				}
1845 			}
1846 			port_dev->dev_hard_addr.hard_addr = nlp->nlp_DID;
1847 		}
1848 
1849 				bcopy((caddr_t)&nlp->nlp_portname,
1850 				    (caddr_t)&port_dev->dev_pwwn, 8);
1851 				bcopy((caddr_t)&nlp->nlp_nodename,
1852 				    (caddr_t)&port_dev->dev_nwwn, 8);
1853 				port_dev++;
1854 			}
1855 
1856 			nlp = (NODELIST *) nlp->nlp_list_next;
1857 			}
1858 		}
1859 		rw_exit(&port->node_rwlock);
1860 
1861 	} else {
1862 
1863 		fc_port_dev_t *port_dev;
1864 		uint32_t max_count;
1865 		uint32_t i;
1866 		uint32_t j;
1867 		emlxs_node_t *nlp;
1868 		uint32_t nport_count = 0;
1869 
1870 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
1871 		    fcio->fcio_alen < sizeof (uint32_t)) {
1872 			rval = EINVAL;
1873 			goto done;
1874 		}
1875 
1876 		port_dev = (fc_port_dev_t *)fcio->fcio_obuf;
1877 		max_count = fcio->fcio_olen / sizeof (fc_port_dev_t);
1878 
1879 		rw_enter(&port->node_rwlock, RW_READER);
1880 
1881 		if (port->mode == MODE_TARGET) {
1882 			nport_count = emlxs_nport_count(port);
1883 		}
1884 
1885 		*(uint32_t *)fcio->fcio_abuf = nport_count;
1886 
1887 		if (nport_count == 0) {
1888 			rw_exit(&port->node_rwlock);
1889 
1890 			fcio->fcio_errno = FC_NO_MAP;
1891 			rval = EIO;
1892 			goto done;
1893 		}
1894 
1895 		if (nport_count > max_count) {
1896 			rw_exit(&port->node_rwlock);
1897 
1898 			fcio->fcio_errno = FC_TOOMANY;
1899 			rval = EIO;
1900 			goto done;
1901 		}
1902 
1903 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
1904 			nlp = port->node_table[i];
1905 			while (nlp != NULL) {
1906 			if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) {
1907 				port_dev->dev_dtype = 0;
1908 				port_dev->dev_type[0] =
1909 				    BE_SWAP32(0x00000100);
1910 				port_dev->dev_state =
1911 				    PORT_DEVICE_LOGGED_IN;
1912 				port_dev->dev_did.port_id =
1913 				    nlp->nlp_DID;
1914 				port_dev->dev_did.priv_lilp_posit = 0;
1915 				port_dev->dev_hard_addr.hard_addr = 0;
1916 
1917 		if (hba->topology == TOPOLOGY_LOOP) {
1918 			for (j = 1; j < port->alpa_map[0]; j++) {
1919 				if (nlp->nlp_DID == port->alpa_map[j]) {
1920 					port_dev->dev_did.priv_lilp_posit = j-1;
1921 					goto done;
1922 				}
1923 			}
1924 			port_dev->dev_hard_addr.hard_addr = nlp->nlp_DID;
1925 		}
1926 
1927 				bcopy((caddr_t)&nlp->nlp_portname,
1928 				    (caddr_t)&port_dev->dev_pwwn, 8);
1929 				bcopy((caddr_t)&nlp->nlp_nodename,
1930 				    (caddr_t)&port_dev->dev_nwwn, 8);
1931 				port_dev++;
1932 			}
1933 
1934 			nlp = (NODELIST *) nlp->nlp_list_next;
1935 			}
1936 		}
1937 		rw_exit(&port->node_rwlock);
1938 	}
1939 
1940 done:
1941 	return (rval);
1942 
1943 } /* emlxs_fcio_get_dev_list() */
1944 
1945 
1946 /*ARGSUSED*/
1947 static int32_t
emlxs_fcio_get_logi_params(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1948 emlxs_fcio_get_logi_params(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1949 {
1950 	int32_t		rval = 0;
1951 	uint8_t 	null_wwn[8];
1952 	uint8_t 	*wwpn;
1953 	emlxs_node_t	*ndlp;
1954 
1955 	if (fcio->fcio_ilen != sizeof (la_wwn_t) ||
1956 	    (fcio->fcio_xfer & FCIO_XFER_READ) == 0 ||
1957 	    (fcio->fcio_xfer & FCIO_XFER_WRITE) == 0) {
1958 		rval = EINVAL;
1959 		goto done;
1960 	}
1961 
1962 	bzero(null_wwn, 8);
1963 	wwpn = (uint8_t *)fcio->fcio_ibuf;
1964 
1965 	if ((bcmp((caddr_t)wwpn, (caddr_t)null_wwn, 8) == 0) ||
1966 	    (bcmp((caddr_t)wwpn, (caddr_t)&port->wwpn, 8) == 0)) {
1967 		bcopy((caddr_t)&port->sparam,
1968 		    (caddr_t)fcio->fcio_obuf, fcio->fcio_olen);
1969 	} else {
1970 		ndlp = emlxs_node_find_wwpn(port, wwpn, 1);
1971 
1972 		if (ndlp) {
1973 			bcopy((caddr_t)&ndlp->sparm,
1974 			    (caddr_t)fcio->fcio_obuf,
1975 			    fcio->fcio_olen);
1976 		} else {
1977 			rval = ENXIO;
1978 		}
1979 	}
1980 
1981 done:
1982 	return (rval);
1983 
1984 } /* emlxs_fcio_get_logi_params() */
1985 
1986 
1987 /*ARGSUSED*/
1988 static int32_t
emlxs_fcio_get_state(emlxs_port_t * port,fcio_t * fcio,int32_t mode)1989 emlxs_fcio_get_state(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1990 {
1991 	int32_t		rval = 0;
1992 	uint8_t		null_wwn[8];
1993 	uint32_t	*statep;
1994 	uint8_t 	*wwpn;
1995 	emlxs_node_t	*ndlp;
1996 
1997 	if (fcio->fcio_ilen != 8 ||
1998 	    fcio->fcio_olen != 4 ||
1999 	    (fcio->fcio_xfer & FCIO_XFER_WRITE) == 0 ||
2000 	    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
2001 		rval = EINVAL;
2002 		goto done;
2003 	}
2004 
2005 	bzero(null_wwn, 8);
2006 	wwpn   = (uint8_t *)fcio->fcio_ibuf;
2007 	statep = (uint32_t *)fcio->fcio_obuf;
2008 
2009 	if ((bcmp((caddr_t)wwpn, (caddr_t)null_wwn, 8) == 0) ||
2010 	    (bcmp((caddr_t)wwpn, (caddr_t)&port->wwpn, 8) == 0)) {
2011 		*statep = PORT_DEVICE_VALID;
2012 	} else {
2013 		ndlp = emlxs_node_find_wwpn(port, wwpn, 1);
2014 
2015 		if (ndlp) {
2016 			*statep = PORT_DEVICE_VALID;
2017 		} else {
2018 			*statep = PORT_DEVICE_INVALID;
2019 		}
2020 	}
2021 
2022 done:
2023 	return (rval);
2024 
2025 } /* emlxs_fcio_get_state() */
2026 
2027 
2028 /*ARGSUSED*/
2029 static int32_t
emlxs_fcio_get_topology(emlxs_port_t * port,fcio_t * fcio,int32_t mode)2030 emlxs_fcio_get_topology(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2031 {
2032 	emlxs_hba_t	*hba = HBA;
2033 	int32_t		rval = 0;
2034 	uint32_t	*tp;
2035 	emlxs_node_t	*ndlp;
2036 
2037 	if (fcio->fcio_olen != 4 ||
2038 	    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
2039 		rval = EINVAL;
2040 		goto done;
2041 	}
2042 
2043 	tp = (uint32_t *)fcio->fcio_obuf;
2044 
2045 	if ((port->mode != MODE_TARGET) ||
2046 	    (port->ulp_statec == FC_STATE_OFFLINE)) {
2047 		*tp = FC_TOP_UNKNOWN;
2048 	} else {
2049 		ndlp = emlxs_node_find_did(port, FABRIC_DID, 1);
2050 
2051 		if (hba->topology == TOPOLOGY_LOOP) {
2052 			if (ndlp) {
2053 				*tp = FC_TOP_PUBLIC_LOOP;
2054 			} else {
2055 				*tp = FC_TOP_PRIVATE_LOOP;
2056 			}
2057 		} else {
2058 			if (ndlp) {
2059 				*tp = FC_TOP_FABRIC;
2060 			} else {
2061 				*tp = FC_TOP_PT_PT;
2062 			}
2063 		}
2064 	}
2065 
2066 done:
2067 	return (rval);
2068 
2069 } /* emlxs_fcio_get_topology() */
2070 
2071 
2072 /*ARGSUSED*/
2073 static int32_t
emlxs_fcio_get_link_status(emlxs_port_t * port,fcio_t * fcio,int32_t mode)2074 emlxs_fcio_get_link_status(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2075 {
2076 	int32_t		rval = 0;
2077 	fc_portid_t	*portid;
2078 	fc_rls_acc_t	*rls;
2079 	fc_fca_pm_t	pm;
2080 
2081 	if (fcio->fcio_ilen != sizeof (fc_portid_t) ||
2082 	    fcio->fcio_olen != sizeof (fc_rls_acc_t) ||
2083 	    fcio->fcio_xfer != FCIO_XFER_RW) {
2084 		rval = EINVAL;
2085 		goto done;
2086 	}
2087 
2088 	if ((fcio->fcio_cmd_flags != FCIO_CFLAGS_RLS_DEST_FPORT) &&
2089 	    (fcio->fcio_cmd_flags != FCIO_CFLAGS_RLS_DEST_NPORT)) {
2090 		rval = EINVAL;
2091 		goto done;
2092 	}
2093 
2094 	portid = (fc_portid_t *)fcio->fcio_ibuf;
2095 	rls    = (fc_rls_acc_t *)fcio->fcio_obuf;
2096 
2097 	if (portid->port_id == 0 || portid->port_id == port->did) {
2098 		bzero((caddr_t)&pm, sizeof (pm));
2099 
2100 		pm.pm_cmd_flags = FC_FCA_PM_READ;
2101 		pm.pm_cmd_code  = FC_PORT_RLS;
2102 		pm.pm_data_len  = sizeof (fc_rls_acc_t);
2103 		pm.pm_data_buf  = (caddr_t)rls;
2104 
2105 		rval = emlxs_fca_port_manage(port, &pm);
2106 
2107 		if (rval != FC_SUCCESS) {
2108 			fcio->fcio_errno = rval;
2109 			rval = EIO;
2110 		}
2111 	} else {
2112 		rval = ENOTSUP;
2113 	}
2114 
2115 done:
2116 	return (rval);
2117 
2118 } /* emlxs_fcio_get_link_status() */
2119 
2120 
2121 /*ARGSUSED*/
2122 static int32_t
emlxs_fcio_get_other_adapter_ports(emlxs_port_t * port,fcio_t * fcio,int32_t mode)2123 emlxs_fcio_get_other_adapter_ports(emlxs_port_t *port, fcio_t *fcio,
2124     int32_t mode)
2125 {
2126 	emlxs_hba_t	*hba = HBA;
2127 	int32_t		rval = 0;
2128 	uint32_t	index;
2129 	char		*path;
2130 
2131 	if (fcio->fcio_olen < MAXPATHLEN ||
2132 	    fcio->fcio_ilen != sizeof (uint32_t)) {
2133 		rval = EINVAL;
2134 		goto done;
2135 	}
2136 
2137 	index = *(uint32_t *)fcio->fcio_ibuf;
2138 	path  = (char *)fcio->fcio_obuf;
2139 
2140 	if (index > hba->vpi_max) {
2141 		fcio->fcio_errno = FC_BADPORT;
2142 		rval = EFAULT;
2143 		goto done;
2144 	}
2145 
2146 	(void) ddi_pathname(hba->dip, path);
2147 
2148 done:
2149 	return (rval);
2150 
2151 } /* emlxs_fcio_get_other_adapter_ports() */
2152 
2153 
2154 /*ARGSUSED*/
2155 static int32_t
emlxs_fcio_get_disc_port_attrs(emlxs_port_t * port,fcio_t * fcio,int32_t mode)2156 emlxs_fcio_get_disc_port_attrs(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2157 {
2158 	emlxs_hba_t	*hba = HBA;
2159 	int32_t		rval = 0;
2160 	uint32_t	index;
2161 	emlxs_node_t	*ndlp;
2162 	uint32_t	use32 = 0;
2163 
2164 #ifdef	_MULTI_DATAMODEL
2165 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
2166 		use32 = 1;
2167 	}
2168 #endif	/* _MULTI_DATAMODEL */
2169 
2170 	if (use32) {
2171 		fc_hba_port_attributes32_t  *port_attrs;
2172 
2173 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
2174 		    fcio->fcio_ilen < sizeof (uint32_t) ||
2175 		    fcio->fcio_olen < sizeof (fc_hba_port_attributes32_t)) {
2176 			rval = EINVAL;
2177 			goto done;
2178 		}
2179 
2180 		index = *(uint32_t *)fcio->fcio_ibuf;
2181 		ndlp  = emlxs_node_find_index(port, index, 1);
2182 
2183 		if (!ndlp) {
2184 			fcio->fcio_errno = FC_OUTOFBOUNDS;
2185 			rval = EINVAL;
2186 			goto done;
2187 		}
2188 
2189 		port_attrs = (fc_hba_port_attributes32_t *)fcio->fcio_obuf;
2190 
2191 		port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
2192 		/* port_attrs->lastChange */
2193 		/* port_attrs->fp_minor   */
2194 		bcopy((caddr_t)&ndlp->nlp_nodename,
2195 		    (caddr_t)&port_attrs->NodeWWN, 8);
2196 		bcopy((caddr_t)&ndlp->nlp_portname,
2197 		    (caddr_t)&port_attrs->PortWWN, 8);
2198 
2199 		port_attrs->PortSpeed = HBA_PORTSPEED_UNKNOWN;
2200 		port_attrs->PortType  = FC_HBA_PORTTYPE_UNKNOWN;
2201 		port_attrs->PortState = FC_HBA_PORTSTATE_OFFLINE;
2202 
2203 		if ((port->mode == MODE_TARGET) &&
2204 		    (hba->state >= FC_LINK_UP)) {
2205 			port_attrs->PortFcId  = ndlp->nlp_DID;
2206 			port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
2207 
2208 			/* no switch */
2209 			if (!(hba->flag & FC_FABRIC_ATTACHED)) {
2210 				if (hba->topology == TOPOLOGY_LOOP) {
2211 					port_attrs->PortType =
2212 					    FC_HBA_PORTTYPE_LPORT;
2213 				} else {
2214 					port_attrs->PortType =
2215 					    FC_HBA_PORTTYPE_PTP;
2216 				}
2217 
2218 				/* We share a common speed */
2219 				switch (hba->linkspeed) {
2220 				case 0:
2221 					port_attrs->PortSpeed =
2222 					    HBA_PORTSPEED_1GBIT;
2223 					break;
2224 				case LA_1GHZ_LINK:
2225 					port_attrs->PortSpeed =
2226 					    HBA_PORTSPEED_1GBIT;
2227 					break;
2228 				case LA_2GHZ_LINK:
2229 					port_attrs->PortSpeed =
2230 					    HBA_PORTSPEED_2GBIT;
2231 					break;
2232 				case LA_4GHZ_LINK:
2233 					port_attrs->PortSpeed =
2234 					    HBA_PORTSPEED_4GBIT;
2235 					break;
2236 				case LA_8GHZ_LINK:
2237 					port_attrs->PortSpeed =
2238 					    HBA_PORTSPEED_8GBIT;
2239 					break;
2240 				case LA_10GHZ_LINK:
2241 					port_attrs->PortSpeed =
2242 					    HBA_PORTSPEED_10GBIT;
2243 					break;
2244 				case LA_16GHZ_LINK:
2245 					port_attrs->PortSpeed =
2246 					    HBA_PORTSPEED_16GBIT;
2247 					break;
2248 				case LA_32GHZ_LINK:
2249 					port_attrs->PortSpeed =
2250 					    HBA_PORTSPEED_32GBIT;
2251 					break;
2252 				}
2253 			}
2254 			/* public loop */
2255 			else if (hba->topology == TOPOLOGY_LOOP) {
2256 				/* Check for common area and domain */
2257 				if ((ndlp->nlp_DID & 0xFFFF00) ==
2258 				    (port->did & 0xFFFF00)) {
2259 					port_attrs->PortType =
2260 					    FC_HBA_PORTTYPE_NLPORT;
2261 
2262 					/* We share a common speed */
2263 					switch (hba->linkspeed) {
2264 					case 0:
2265 						port_attrs->PortSpeed =
2266 						    HBA_PORTSPEED_1GBIT;
2267 						break;
2268 					case LA_1GHZ_LINK:
2269 						port_attrs->PortSpeed =
2270 						    HBA_PORTSPEED_1GBIT;
2271 						break;
2272 					case LA_2GHZ_LINK:
2273 						port_attrs->PortSpeed =
2274 						    HBA_PORTSPEED_2GBIT;
2275 						break;
2276 					case LA_4GHZ_LINK:
2277 						port_attrs->PortSpeed =
2278 						    HBA_PORTSPEED_4GBIT;
2279 						break;
2280 					case LA_8GHZ_LINK:
2281 						port_attrs->PortSpeed =
2282 						    HBA_PORTSPEED_8GBIT;
2283 						break;
2284 					case LA_10GHZ_LINK:
2285 						port_attrs->PortSpeed =
2286 						    HBA_PORTSPEED_10GBIT;
2287 						break;
2288 					case LA_16GHZ_LINK:
2289 						port_attrs->PortSpeed =
2290 						    HBA_PORTSPEED_16GBIT;
2291 						break;
2292 					case LA_32GHZ_LINK:
2293 						port_attrs->PortSpeed =
2294 						    HBA_PORTSPEED_32GBIT;
2295 						break;
2296 					}
2297 				}
2298 			}
2299 		}
2300 
2301 		port_attrs->PortSupportedClassofService =
2302 		    LE_SWAP32(FC_NS_CLASS3);
2303 		/* port_attrs->PortSymbolicName		*/
2304 		/* port_attrs->PortSupportedSpeed	*/
2305 		/* port_attrs->PortSupportedFc4Types	*/
2306 		/* port_attrs->PortActiveFc4Types	*/
2307 		/* port_attrs->PortMaxFrameSize		*/
2308 		/* port_attrs->NumberofDiscoveredPorts	*/
2309 
2310 	} else {
2311 		fc_hba_port_attributes_t  *port_attrs;
2312 
2313 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
2314 		    fcio->fcio_ilen < sizeof (uint32_t) ||
2315 		    fcio->fcio_olen < sizeof (fc_hba_port_attributes_t)) {
2316 			rval = EINVAL;
2317 			goto done;
2318 		}
2319 
2320 		index = *(uint32_t *)fcio->fcio_ibuf;
2321 		ndlp  = emlxs_node_find_index(port, index, 1);
2322 
2323 		if (!ndlp) {
2324 			fcio->fcio_errno = FC_OUTOFBOUNDS;
2325 			rval = EINVAL;
2326 			goto done;
2327 		}
2328 
2329 		port_attrs = (fc_hba_port_attributes_t *)fcio->fcio_obuf;
2330 
2331 		port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
2332 		/* port_attrs->lastChange */
2333 		/* port_attrs->fp_minor   */
2334 		bcopy((caddr_t)&ndlp->nlp_nodename,
2335 		    (caddr_t)&port_attrs->NodeWWN, 8);
2336 		bcopy((caddr_t)&ndlp->nlp_portname,
2337 		    (caddr_t)&port_attrs->PortWWN, 8);
2338 
2339 		port_attrs->PortSpeed = HBA_PORTSPEED_UNKNOWN;
2340 		port_attrs->PortType  = FC_HBA_PORTTYPE_UNKNOWN;
2341 		port_attrs->PortState = FC_HBA_PORTSTATE_OFFLINE;
2342 
2343 		if ((port->mode == MODE_TARGET) &&
2344 		    (hba->state >= FC_LINK_UP)) {
2345 			port_attrs->PortFcId  = ndlp->nlp_DID;
2346 			port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
2347 
2348 			/* no switch */
2349 			if (!(hba->flag & FC_FABRIC_ATTACHED)) {
2350 				if (hba->topology == TOPOLOGY_LOOP) {
2351 					port_attrs->PortType =
2352 					    FC_HBA_PORTTYPE_LPORT;
2353 				} else {
2354 					port_attrs->PortType =
2355 					    FC_HBA_PORTTYPE_PTP;
2356 				}
2357 
2358 				/* We share a common speed */
2359 				switch (hba->linkspeed) {
2360 				case 0:
2361 					port_attrs->PortSpeed =
2362 					    HBA_PORTSPEED_1GBIT;
2363 					break;
2364 				case LA_1GHZ_LINK:
2365 					port_attrs->PortSpeed =
2366 					    HBA_PORTSPEED_1GBIT;
2367 					break;
2368 				case LA_2GHZ_LINK:
2369 					port_attrs->PortSpeed =
2370 					    HBA_PORTSPEED_2GBIT;
2371 					break;
2372 				case LA_4GHZ_LINK:
2373 					port_attrs->PortSpeed =
2374 					    HBA_PORTSPEED_4GBIT;
2375 					break;
2376 				case LA_8GHZ_LINK:
2377 					port_attrs->PortSpeed =
2378 					    HBA_PORTSPEED_8GBIT;
2379 					break;
2380 				case LA_10GHZ_LINK:
2381 					port_attrs->PortSpeed =
2382 					    HBA_PORTSPEED_10GBIT;
2383 					break;
2384 				case LA_16GHZ_LINK:
2385 					port_attrs->PortSpeed =
2386 					    HBA_PORTSPEED_16GBIT;
2387 					break;
2388 				case LA_32GHZ_LINK:
2389 					port_attrs->PortSpeed =
2390 					    HBA_PORTSPEED_32GBIT;
2391 					break;
2392 				}
2393 			}
2394 			/* public loop */
2395 			else if (hba->topology == TOPOLOGY_LOOP) {
2396 				/* Check for common area and domain */
2397 				if ((ndlp->nlp_DID & 0xFFFF00) ==
2398 				    (port->did & 0xFFFF00)) {
2399 					port_attrs->PortType =
2400 					    FC_HBA_PORTTYPE_NLPORT;
2401 
2402 					/* We share a common speed */
2403 					switch (hba->linkspeed) {
2404 					case 0:
2405 						port_attrs->PortSpeed =
2406 						    HBA_PORTSPEED_1GBIT;
2407 						break;
2408 					case LA_1GHZ_LINK:
2409 						port_attrs->PortSpeed =
2410 						    HBA_PORTSPEED_1GBIT;
2411 						break;
2412 					case LA_2GHZ_LINK:
2413 						port_attrs->PortSpeed =
2414 						    HBA_PORTSPEED_2GBIT;
2415 						break;
2416 					case LA_4GHZ_LINK:
2417 						port_attrs->PortSpeed =
2418 						    HBA_PORTSPEED_4GBIT;
2419 						break;
2420 					case LA_8GHZ_LINK:
2421 						port_attrs->PortSpeed =
2422 						    HBA_PORTSPEED_8GBIT;
2423 						break;
2424 					case LA_10GHZ_LINK:
2425 						port_attrs->PortSpeed =
2426 						    HBA_PORTSPEED_10GBIT;
2427 						break;
2428 					case LA_16GHZ_LINK:
2429 						port_attrs->PortSpeed =
2430 						    HBA_PORTSPEED_16GBIT;
2431 						break;
2432 					case LA_32GHZ_LINK:
2433 						port_attrs->PortSpeed =
2434 						    HBA_PORTSPEED_32GBIT;
2435 						break;
2436 					}
2437 				}
2438 			}
2439 		}
2440 
2441 		port_attrs->PortSupportedClassofService =
2442 		    LE_SWAP32(FC_NS_CLASS3);
2443 		/* port_attrs->PortSymbolicName		*/
2444 		/* port_attrs->PortSupportedSpeed	*/
2445 		/* port_attrs->PortSupportedFc4Types	*/
2446 		/* port_attrs->PortActiveFc4Types	*/
2447 		/* port_attrs->PortMaxFrameSize		*/
2448 		/* port_attrs->NumberofDiscoveredPorts	*/
2449 	}
2450 
2451 done:
2452 	return (rval);
2453 
2454 } /* emlxs_fcio_get_disc_port_attrs() */
2455 
2456 
2457 /*ARGSUSED*/
2458 static int32_t
emlxs_fcio_get_port_attrs(emlxs_port_t * port,fcio_t * fcio,int32_t mode)2459 emlxs_fcio_get_port_attrs(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2460 {
2461 	emlxs_hba_t	*hba = HBA;
2462 	int32_t		rval = 0;
2463 	emlxs_node_t	*ndlp;
2464 	uint8_t		*wwpn;
2465 	uint32_t	use32 = 0;
2466 
2467 #ifdef	_MULTI_DATAMODEL
2468 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
2469 		use32 = 1;
2470 	}
2471 #endif	/* _MULTI_DATAMODEL */
2472 
2473 	if (use32) {
2474 		fc_hba_port_attributes32_t  *port_attrs;
2475 
2476 		if ((fcio->fcio_xfer != FCIO_XFER_READ) ||
2477 		    (fcio->fcio_ilen < 8) ||
2478 		    (fcio->fcio_olen < sizeof (fc_hba_port_attributes32_t))) {
2479 			rval = EINVAL;
2480 			goto done;
2481 		}
2482 
2483 		wwpn  = (uint8_t *)fcio->fcio_ibuf;
2484 		ndlp  = emlxs_node_find_wwpn(port, wwpn, 1);
2485 
2486 		if (!ndlp) {
2487 			fcio->fcio_errno = FC_NOMAP;
2488 			rval = EINVAL;
2489 			goto done;
2490 		}
2491 
2492 		/* Filter fabric ports */
2493 		if ((ndlp->nlp_DID & 0xFFF000) == 0xFFF000) {
2494 			fcio->fcio_errno = FC_NOMAP;
2495 			rval = EINVAL;
2496 			goto done;
2497 		}
2498 
2499 		port_attrs = (fc_hba_port_attributes32_t *)fcio->fcio_obuf;
2500 
2501 		port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
2502 		/* port_attrs->lastChange */
2503 		/* port_attrs->fp_minor   */
2504 		bcopy((caddr_t)&ndlp->nlp_nodename,
2505 		    (caddr_t)&port_attrs->NodeWWN, 8);
2506 		bcopy((caddr_t)&ndlp->nlp_portname,
2507 		    (caddr_t)&port_attrs->PortWWN, 8);
2508 
2509 		port_attrs->PortSpeed = HBA_PORTSPEED_UNKNOWN;
2510 		port_attrs->PortType  = FC_HBA_PORTTYPE_UNKNOWN;
2511 		port_attrs->PortState = FC_HBA_PORTSTATE_OFFLINE;
2512 
2513 		if ((port->mode == MODE_TARGET) &&
2514 		    (hba->state >= FC_LINK_UP)) {
2515 			port_attrs->PortFcId  = ndlp->nlp_DID;
2516 			port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
2517 
2518 			/* no switch */
2519 			if (!(hba->flag & FC_FABRIC_ATTACHED)) {
2520 				if (hba->topology == TOPOLOGY_LOOP) {
2521 					port_attrs->PortType =
2522 					    FC_HBA_PORTTYPE_LPORT;
2523 				} else {
2524 					port_attrs->PortType =
2525 					    FC_HBA_PORTTYPE_PTP;
2526 				}
2527 
2528 				/* We share a common speed */
2529 				switch (hba->linkspeed) {
2530 				case 0:
2531 					port_attrs->PortSpeed =
2532 					    HBA_PORTSPEED_1GBIT;
2533 					break;
2534 				case LA_1GHZ_LINK:
2535 					port_attrs->PortSpeed =
2536 					    HBA_PORTSPEED_1GBIT;
2537 					break;
2538 				case LA_2GHZ_LINK:
2539 					port_attrs->PortSpeed =
2540 					    HBA_PORTSPEED_2GBIT;
2541 					break;
2542 				case LA_4GHZ_LINK:
2543 					port_attrs->PortSpeed =
2544 					    HBA_PORTSPEED_4GBIT;
2545 					break;
2546 				case LA_8GHZ_LINK:
2547 					port_attrs->PortSpeed =
2548 					    HBA_PORTSPEED_8GBIT;
2549 					break;
2550 				case LA_10GHZ_LINK:
2551 					port_attrs->PortSpeed =
2552 					    HBA_PORTSPEED_10GBIT;
2553 					break;
2554 				case LA_16GHZ_LINK:
2555 					port_attrs->PortSpeed =
2556 					    HBA_PORTSPEED_16GBIT;
2557 					break;
2558 				case LA_32GHZ_LINK:
2559 					port_attrs->PortSpeed =
2560 					    HBA_PORTSPEED_32GBIT;
2561 					break;
2562 				}
2563 			}
2564 			/* public loop */
2565 			else if (hba->topology == TOPOLOGY_LOOP) {
2566 				/* Check for common area and domain */
2567 				if ((ndlp->nlp_DID & 0xFFFF00) ==
2568 				    (port->did & 0xFFFF00)) {
2569 					port_attrs->PortType =
2570 					    FC_HBA_PORTTYPE_NLPORT;
2571 
2572 					/* We share a common speed */
2573 					switch (hba->linkspeed) {
2574 					case 0:
2575 						port_attrs->PortSpeed =
2576 						    HBA_PORTSPEED_1GBIT;
2577 						break;
2578 					case LA_1GHZ_LINK:
2579 						port_attrs->PortSpeed =
2580 						    HBA_PORTSPEED_1GBIT;
2581 						break;
2582 					case LA_2GHZ_LINK:
2583 						port_attrs->PortSpeed =
2584 						    HBA_PORTSPEED_2GBIT;
2585 						break;
2586 					case LA_4GHZ_LINK:
2587 						port_attrs->PortSpeed =
2588 						    HBA_PORTSPEED_4GBIT;
2589 						break;
2590 					case LA_8GHZ_LINK:
2591 						port_attrs->PortSpeed =
2592 						    HBA_PORTSPEED_8GBIT;
2593 						break;
2594 					case LA_10GHZ_LINK:
2595 						port_attrs->PortSpeed =
2596 						    HBA_PORTSPEED_10GBIT;
2597 						break;
2598 					case LA_16GHZ_LINK:
2599 						port_attrs->PortSpeed =
2600 						    HBA_PORTSPEED_16GBIT;
2601 						break;
2602 					case LA_32GHZ_LINK:
2603 						port_attrs->PortSpeed =
2604 						    HBA_PORTSPEED_32GBIT;
2605 						break;
2606 					}
2607 				}
2608 			}
2609 		}
2610 
2611 		port_attrs->PortSupportedClassofService =
2612 		    LE_SWAP32(FC_NS_CLASS3);
2613 		/* port_attrs->PortSymbolicName		*/
2614 		/* port_attrs->PortSupportedSpeed	*/
2615 		/* port_attrs->PortSupportedFc4Types	*/
2616 		/* port_attrs->PortActiveFc4Types	*/
2617 		/* port_attrs->PortMaxFrameSize		*/
2618 		/* port_attrs->NumberofDiscoveredPorts	*/
2619 
2620 	} else {
2621 		fc_hba_port_attributes_t  *port_attrs;
2622 
2623 		if ((fcio->fcio_xfer != FCIO_XFER_READ) ||
2624 		    (fcio->fcio_ilen < 8) ||
2625 		    (fcio->fcio_olen < sizeof (fc_hba_port_attributes_t))) {
2626 			rval = EINVAL;
2627 			goto done;
2628 		}
2629 
2630 		wwpn  = (uint8_t *)fcio->fcio_ibuf;
2631 		ndlp  = emlxs_node_find_wwpn(port, wwpn, 1);
2632 
2633 		if (!ndlp) {
2634 			fcio->fcio_errno = FC_NOMAP;
2635 			rval = EINVAL;
2636 			goto done;
2637 		}
2638 
2639 		/* Filter fabric ports */
2640 		if ((ndlp->nlp_DID & 0xFFF000) == 0xFFF000) {
2641 			fcio->fcio_errno = FC_NOMAP;
2642 			rval = EINVAL;
2643 			goto done;
2644 		}
2645 
2646 		port_attrs = (fc_hba_port_attributes_t *)fcio->fcio_obuf;
2647 
2648 		port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
2649 		/* port_attrs->lastChange */
2650 		/* port_attrs->fp_minor   */
2651 		bcopy((caddr_t)&ndlp->nlp_nodename,
2652 		    (caddr_t)&port_attrs->NodeWWN, 8);
2653 		bcopy((caddr_t)&ndlp->nlp_portname,
2654 		    (caddr_t)&port_attrs->PortWWN, 8);
2655 
2656 		port_attrs->PortSpeed = HBA_PORTSPEED_UNKNOWN;
2657 		port_attrs->PortType  = FC_HBA_PORTTYPE_UNKNOWN;
2658 		port_attrs->PortState = FC_HBA_PORTSTATE_OFFLINE;
2659 
2660 		if ((port->mode == MODE_TARGET) &&
2661 		    (hba->state >= FC_LINK_UP)) {
2662 			port_attrs->PortFcId  = ndlp->nlp_DID;
2663 			port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
2664 
2665 			/* no switch */
2666 			if (!(hba->flag & FC_FABRIC_ATTACHED)) {
2667 				if (hba->topology == TOPOLOGY_LOOP) {
2668 					port_attrs->PortType =
2669 					    FC_HBA_PORTTYPE_LPORT;
2670 				} else {
2671 					port_attrs->PortType =
2672 					    FC_HBA_PORTTYPE_PTP;
2673 				}
2674 
2675 				/* We share a common speed */
2676 				switch (hba->linkspeed) {
2677 				case 0:
2678 					port_attrs->PortSpeed =
2679 					    HBA_PORTSPEED_1GBIT;
2680 					break;
2681 				case LA_1GHZ_LINK:
2682 					port_attrs->PortSpeed =
2683 					    HBA_PORTSPEED_1GBIT;
2684 					break;
2685 				case LA_2GHZ_LINK:
2686 					port_attrs->PortSpeed =
2687 					    HBA_PORTSPEED_2GBIT;
2688 					break;
2689 				case LA_4GHZ_LINK:
2690 					port_attrs->PortSpeed =
2691 					    HBA_PORTSPEED_4GBIT;
2692 					break;
2693 				case LA_8GHZ_LINK:
2694 					port_attrs->PortSpeed =
2695 					    HBA_PORTSPEED_8GBIT;
2696 					break;
2697 				case LA_10GHZ_LINK:
2698 					port_attrs->PortSpeed =
2699 					    HBA_PORTSPEED_10GBIT;
2700 					break;
2701 				case LA_16GHZ_LINK:
2702 					port_attrs->PortSpeed =
2703 					    HBA_PORTSPEED_16GBIT;
2704 					break;
2705 				case LA_32GHZ_LINK:
2706 					port_attrs->PortSpeed =
2707 					    HBA_PORTSPEED_32GBIT;
2708 					break;
2709 				}
2710 			}
2711 			/* public loop */
2712 			else if (hba->topology == TOPOLOGY_LOOP) {
2713 				/* Check for common area and domain */
2714 				if ((ndlp->nlp_DID & 0xFFFF00) ==
2715 				    (port->did & 0xFFFF00)) {
2716 					port_attrs->PortType =
2717 					    FC_HBA_PORTTYPE_NLPORT;
2718 
2719 					/* We share a common speed */
2720 					switch (hba->linkspeed) {
2721 					case 0:
2722 						port_attrs->PortSpeed =
2723 						    HBA_PORTSPEED_1GBIT;
2724 						break;
2725 					case LA_1GHZ_LINK:
2726 						port_attrs->PortSpeed =
2727 						    HBA_PORTSPEED_1GBIT;
2728 						break;
2729 					case LA_2GHZ_LINK:
2730 						port_attrs->PortSpeed =
2731 						    HBA_PORTSPEED_2GBIT;
2732 						break;
2733 					case LA_4GHZ_LINK:
2734 						port_attrs->PortSpeed =
2735 						    HBA_PORTSPEED_4GBIT;
2736 						break;
2737 					case LA_8GHZ_LINK:
2738 						port_attrs->PortSpeed =
2739 						    HBA_PORTSPEED_8GBIT;
2740 						break;
2741 					case LA_10GHZ_LINK:
2742 						port_attrs->PortSpeed =
2743 						    HBA_PORTSPEED_10GBIT;
2744 						break;
2745 					case LA_16GHZ_LINK:
2746 						port_attrs->PortSpeed =
2747 						    HBA_PORTSPEED_16GBIT;
2748 						break;
2749 					case LA_32GHZ_LINK:
2750 						port_attrs->PortSpeed =
2751 						    HBA_PORTSPEED_32GBIT;
2752 						break;
2753 					}
2754 				}
2755 			}
2756 		}
2757 
2758 		port_attrs->PortSupportedClassofService =
2759 		    LE_SWAP32(FC_NS_CLASS3);
2760 		/* port_attrs->PortSymbolicName		*/
2761 		/* port_attrs->PortSupportedSpeed	*/
2762 		/* port_attrs->PortSupportedFc4Types	*/
2763 		/* port_attrs->PortActiveFc4Types	*/
2764 		/* port_attrs->PortMaxFrameSize		*/
2765 		/* port_attrs->NumberofDiscoveredPorts	*/
2766 	}
2767 
2768 done:
2769 	return (rval);
2770 
2771 } /* emlxs_fcio_get_port_attrs() */
2772 
2773 
2774 /*ARGSUSED*/
2775 static int32_t
emlxs_fcio_get_sym_pname(emlxs_port_t * port,fcio_t * fcio,int32_t mode)2776 emlxs_fcio_get_sym_pname(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2777 {
2778 	int32_t		rval = 0;
2779 
2780 	if (fcio->fcio_olen < (strlen(port->spn)+1) ||
2781 	    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
2782 		rval = EINVAL;
2783 		goto done;
2784 	}
2785 
2786 	(void) strlcpy((caddr_t)fcio->fcio_obuf, (caddr_t)port->spn,
2787 	    fcio->fcio_olen);
2788 
2789 done:
2790 	return (rval);
2791 
2792 } /* emlxs_fcio_get_sym_pname() */
2793 
2794 
2795 /*ARGSUSED*/
2796 static int32_t
emlxs_fcio_get_sym_nname(emlxs_port_t * port,fcio_t * fcio,int32_t mode)2797 emlxs_fcio_get_sym_nname(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2798 {
2799 	int32_t		rval = 0;
2800 
2801 	if (fcio->fcio_olen < (strlen(port->snn)+1) ||
2802 	    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
2803 		rval = EINVAL;
2804 		goto done;
2805 	}
2806 
2807 	(void) strlcpy((caddr_t)fcio->fcio_obuf, (caddr_t)port->snn,
2808 	    fcio->fcio_olen);
2809 
2810 done:
2811 	return (rval);
2812 
2813 } /* emlxs_fcio_get_sym_nname() */
2814 
2815 
2816 /*ARGSUSED*/
2817 static int32_t
emlxs_fcio_force_dump(emlxs_port_t * port,fcio_t * fcio,int32_t mode)2818 emlxs_fcio_force_dump(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2819 {
2820 	int32_t		rval = 0;
2821 
2822 	if (port->mode != MODE_TARGET) {
2823 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2824 		    "fcio_force_dump failed. Port is not in target mode.");
2825 
2826 		fcio->fcio_errno = FC_FAILURE;
2827 		rval = EIO;
2828 		goto done;
2829 	}
2830 
2831 	rval = emlxs_reset(port, FC_FCA_CORE);
2832 
2833 	if (rval != FC_SUCCESS) {
2834 		fcio->fcio_errno = rval;
2835 		rval = EIO;
2836 		goto done;
2837 	}
2838 
2839 done:
2840 	return (rval);
2841 
2842 } /* emlxs_fcio_force_dump() */
2843 
2844 
2845 /*ARGSUSED*/
2846 static int32_t
emlxs_fcio_get_dump_size(emlxs_port_t * port,fcio_t * fcio,int32_t mode)2847 emlxs_fcio_get_dump_size(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2848 {
2849 	int32_t		rval = 0;
2850 	fc_fca_pm_t pm;
2851 
2852 	if (fcio->fcio_olen != sizeof (uint32_t) ||
2853 	    fcio->fcio_xfer != FCIO_XFER_READ) {
2854 		rval = EINVAL;
2855 		goto done;
2856 	}
2857 
2858 	bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
2859 
2860 	pm.pm_data_len  = fcio->fcio_olen;
2861 	pm.pm_data_buf  = fcio->fcio_obuf;
2862 	pm.pm_cmd_code  = FC_PORT_GET_DUMP_SIZE;
2863 	pm.pm_cmd_flags = FC_FCA_PM_READ;
2864 
2865 	rval = emlxs_fca_port_manage(port, &pm);
2866 
2867 	if (rval != FC_SUCCESS) {
2868 		fcio->fcio_errno = rval;
2869 
2870 		if (rval == FC_INVALID_REQUEST) {
2871 			rval = ENOTTY;
2872 		} else {
2873 			rval = EIO;
2874 		}
2875 	}
2876 
2877 done:
2878 	return (rval);
2879 
2880 } /* emlxs_fcio_get_dump_size() */
2881 
2882 
2883 /*ARGSUSED*/
2884 static int32_t
emlxs_fcio_get_dump(emlxs_port_t * port,fcio_t * fcio,int32_t mode)2885 emlxs_fcio_get_dump(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2886 {
2887 	int32_t		rval = 0;
2888 	fc_fca_pm_t	pm;
2889 	uint32_t	dump_size;
2890 
2891 	if (fcio->fcio_xfer != FCIO_XFER_READ) {
2892 		rval = EINVAL;
2893 		goto done;
2894 	}
2895 
2896 	bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
2897 
2898 	pm.pm_data_len  = sizeof (uint32_t);
2899 	pm.pm_data_buf  = (caddr_t)&dump_size;
2900 	pm.pm_cmd_code  = FC_PORT_GET_DUMP_SIZE;
2901 	pm.pm_cmd_flags = FC_FCA_PM_READ;
2902 
2903 	rval = emlxs_fca_port_manage(port, &pm);
2904 
2905 	if (rval != FC_SUCCESS) {
2906 		fcio->fcio_errno = rval;
2907 
2908 		if (rval == FC_INVALID_REQUEST) {
2909 			rval = ENOTTY;
2910 		} else {
2911 			rval = EIO;
2912 		}
2913 		goto done;
2914 	}
2915 
2916 	if (fcio->fcio_olen != dump_size) {
2917 		fcio->fcio_errno = FC_NOMEM;
2918 		rval = EINVAL;
2919 		goto done;
2920 	}
2921 
2922 	bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
2923 
2924 	pm.pm_data_len  = fcio->fcio_olen;
2925 	pm.pm_data_buf  = fcio->fcio_obuf;
2926 	pm.pm_cmd_code  = FC_PORT_GET_DUMP;
2927 	pm.pm_cmd_flags = FC_FCA_PM_READ;
2928 
2929 	rval = emlxs_fca_port_manage(port, &pm);
2930 
2931 	if (rval != FC_SUCCESS) {
2932 		fcio->fcio_errno = rval;
2933 
2934 		if (rval == FC_INVALID_REQUEST) {
2935 			rval = ENOTTY;
2936 		} else {
2937 			rval = EIO;
2938 		}
2939 	}
2940 
2941 done:
2942 	return (rval);
2943 
2944 } /* emlxs_fcio_get_dump() */
2945 
2946 
2947 /*ARGSUSED*/
2948 static int32_t
emlxs_fcio_unsupported(emlxs_port_t * port,fcio_t * fcio,int32_t mode)2949 emlxs_fcio_unsupported(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2950 {
2951 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
2952 	    "%s: Command not supported.",
2953 	    emlxs_fcio_xlate(fcio->fcio_cmd));
2954 
2955 	return (ENOTSUP);
2956 
2957 } /* emlxs_fcio_unsupported() */
2958 #endif /* FCIO_SUPPORT */
2959 
2960 
2961 /*ARGSUSED*/
2962 static int32_t
emlxs_dfc_create_vport(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)2963 emlxs_dfc_create_vport(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2964 {
2965 	emlxs_port_t	*port = &PPORT;
2966 	emlxs_config_t	*cfg = &CFG;
2967 	emlxs_port_t	*vport;
2968 	emlxs_port_t	*tport;
2969 	dfc_vportinfo_t	*dfc_vport;
2970 	uint32_t	vpi;
2971 	uint32_t	options;
2972 	char		name[256];
2973 	uint8_t		wwn[8];
2974 
2975 	options = dfc->data1;
2976 
2977 	if (!dfc->buf1 || !dfc->buf1_size) {
2978 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2979 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
2980 
2981 		return (DFC_ARG_NULL);
2982 	}
2983 
2984 	if (dfc->buf1_size < sizeof (dfc_vportinfo_t)) {
2985 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2986 		    "%s: Buffer1 too small. (size=%d)",
2987 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2988 
2989 		return (DFC_ARG_TOOSMALL);
2990 	}
2991 
2992 	dfc_vport = (dfc_vportinfo_t *)dfc->buf1;
2993 
2994 	if (!(options & VPORT_OPT_AUTORETRY)) {
2995 		if (!(hba->flag & FC_NPIV_ENABLED)) {
2996 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2997 			    "%s: NPIV currently not enabled.",
2998 			    emlxs_dfc_xlate(dfc->cmd));
2999 
3000 			return (DFC_NPIV_DISABLED);
3001 		}
3002 
3003 		if (!(hba->flag & FC_NPIV_SUPPORTED)) {
3004 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3005 			    "%s: NPIV currently not supported.",
3006 			    emlxs_dfc_xlate(dfc->cmd));
3007 
3008 			return (DFC_NPIV_UNSUPPORTED);
3009 		}
3010 	}
3011 
3012 	/*
3013 	 * Only the same WWNN and WWPN can be re-created
3014 	 */
3015 	bzero(wwn, 8);
3016 	if (bcmp(wwn, dfc_vport->wwpn, 8) || bcmp(wwn, dfc_vport->wwnn, 8)) {
3017 		for (vpi = 1; vpi <= hba->vpi_max; vpi++) {
3018 			vport = &VPORT(vpi);
3019 
3020 			if ((bcmp((caddr_t)&vport->wwnn,
3021 			    (caddr_t)dfc_vport->wwnn, 8) == 0) &&
3022 			    (bcmp((caddr_t)&vport->wwpn,
3023 			    (caddr_t)dfc_vport->wwpn, 8) == 0)) {
3024 				if (!(vport->flag & EMLXS_PORT_CONFIG) &&
3025 				    (vport->flag & EMLXS_PORT_BOUND)) {
3026 					dfc_vport->vpi = vpi;
3027 					break;
3028 				} else {
3029 					EMLXS_MSGF(EMLXS_CONTEXT,
3030 					    &emlxs_dfc_error_msg,
3031 					    "%s: VPI already in use.",
3032 					    emlxs_dfc_xlate(dfc->cmd));
3033 
3034 					return (DFC_ARG_INVALID);
3035 				}
3036 			}
3037 		}
3038 	}
3039 
3040 	/* else auto assign */
3041 	/* Acquire a VPI */
3042 	if (dfc_vport->vpi == 0) {
3043 		/* Auto Assign VPI */
3044 		for (vpi = 1; vpi <= hba->vpi_max; vpi++) {
3045 			vport = &VPORT(vpi);
3046 
3047 			if (!(vport->flag & EMLXS_PORT_CONFIG)) {
3048 				break;
3049 			}
3050 		}
3051 
3052 		if (vpi > hba->vpi_max) {
3053 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3054 			    "%s: Out of resources.",
3055 			    emlxs_dfc_xlate(dfc->cmd));
3056 
3057 			return (DFC_DRVRES_ERROR);
3058 		}
3059 
3060 		dfc_vport->vpi = vpi;
3061 	}
3062 
3063 	/* Establish a WWPN */
3064 	bzero(wwn, 8);
3065 	if (!(bcmp(wwn, dfc_vport->wwpn, 8))) {
3066 		/* Generate new WWPN */
3067 		bcopy((caddr_t)&hba->wwpn, (caddr_t)dfc_vport->wwpn, 8);
3068 		dfc_vport->wwpn[0] = 0x20;
3069 		dfc_vport->wwpn[1] = (uint8_t)vpi;
3070 	} else {	/* use one provided */
3071 
3072 		/* Make sure WWPN is unique */
3073 		if (tport = emlxs_vport_find_wwpn(hba, dfc_vport->wwpn)) {
3074 			if ((tport->flag & EMLXS_PORT_CONFIG) &&
3075 			    (tport->flag & EMLXS_PORT_BOUND)) {
3076 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3077 				    "%s: WWPN already exists. vpi=%d",
3078 				    emlxs_dfc_xlate(dfc->cmd), vpi);
3079 				return (DFC_ARG_INVALID);
3080 			}
3081 		}
3082 	}
3083 
3084 	/* Establish a WWNN */
3085 	bzero(wwn, 8);
3086 	if (!(bcmp(wwn, dfc_vport->wwnn, 8))) {
3087 		/* Generate new WWNN */
3088 		bcopy((caddr_t)&hba->wwnn, (caddr_t)dfc_vport->wwnn, 8);
3089 		dfc_vport->wwnn[0] = 0x28;
3090 		dfc_vport->wwnn[1] = (uint8_t)vpi;
3091 	}
3092 	/* else use WWNN provided */
3093 
3094 	/* Generate the symbolic node name */
3095 	if (dfc_vport->snn[0]) {
3096 		(void) strncpy(name, dfc_vport->snn,
3097 		    (sizeof (name)-1));
3098 		(void) snprintf(dfc_vport->snn, (sizeof (dfc_vport->snn)-1),
3099 		    "%s %s", hba->snn, name);
3100 	} else {
3101 		(void) strncpy(dfc_vport->snn, hba->snn,
3102 		    (sizeof (dfc_vport->snn)-1));
3103 	}
3104 
3105 	/* Generate the symbolic port name */
3106 	if (dfc_vport->spn[0]) {
3107 		(void) strncpy(name, dfc_vport->spn,
3108 		    (sizeof (name)-1));
3109 		(void) snprintf(dfc_vport->spn, (sizeof (dfc_vport->spn)-1),
3110 		    "%s VPort-%d VName-%s", hba->spn,
3111 		    vpi, name);
3112 	} else {
3113 		(void) snprintf(dfc_vport->spn, (sizeof (dfc_vport->spn)-1),
3114 		    "%s VPort-%d", hba->spn, vpi);
3115 	}
3116 
3117 	dfc_vport->port_id = 0;
3118 	dfc_vport->ulp_statec = FC_STATE_OFFLINE;
3119 	dfc_vport->flags = VPORT_CONFIG;
3120 
3121 	/* Set the highest configured vpi */
3122 	if (dfc_vport->vpi >= hba->vpi_high) {
3123 		hba->vpi_high = dfc_vport->vpi;
3124 	}
3125 
3126 	/* Configure the port object */
3127 	bcopy((caddr_t)dfc_vport->wwnn, (caddr_t)&vport->wwnn, 8);
3128 	bcopy((caddr_t)dfc_vport->wwpn, (caddr_t)&vport->wwpn, 8);
3129 	(void) strncpy((caddr_t)vport->snn, (caddr_t)dfc_vport->snn,
3130 	    (sizeof (vport->snn)-1));
3131 	(void) strncpy((caddr_t)vport->spn, (caddr_t)dfc_vport->spn,
3132 	    (sizeof (vport->spn)-1));
3133 	vport->flag |= (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLED);
3134 
3135 	/* Adjust restricted flags */
3136 	vport->options &= ~EMLXS_OPT_RESTRICT_MASK;
3137 	vport->flag &= ~EMLXS_PORT_RESTRICTED;
3138 	if (options & VPORT_OPT_RESTRICT) {
3139 		vport->options |= EMLXS_OPT_RESTRICT;
3140 		vport->flag |= EMLXS_PORT_RESTRICTED;
3141 		dfc_vport->flags |= VPORT_RESTRICTED;
3142 	} else if (options & VPORT_OPT_UNRESTRICT) {
3143 		vport->options |= EMLXS_OPT_UNRESTRICT;
3144 	} else if (cfg[CFG_VPORT_RESTRICTED].current) {
3145 		vport->flag |= EMLXS_PORT_RESTRICTED;
3146 		dfc_vport->flags |= VPORT_RESTRICTED;
3147 	}
3148 
3149 	if (vport->flag & EMLXS_PORT_BOUND) {
3150 		/*
3151 		 * The same WWNN, WWPN and VPI has been re-created.
3152 		 * Bring up the vport now!
3153 		 */
3154 		emlxs_port_online(vport);
3155 	}
3156 
3157 	return (0);
3158 
3159 } /* emlxs_dfc_create_vport() */
3160 
3161 
3162 /*ARGSUSED*/
3163 static int32_t
emlxs_dfc_destroy_vport(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)3164 emlxs_dfc_destroy_vport(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3165 {
3166 	emlxs_port_t	*port = &PPORT;
3167 	emlxs_port_t	*vport;
3168 	uint8_t		wwpn[8];
3169 	fc_packet_t	*pkt = NULL;
3170 	uint32_t	rval = 0;
3171 	ELS_PKT		*els;
3172 	char		buffer[256];
3173 
3174 	if (!dfc->buf1 || !dfc->buf1_size) {
3175 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3176 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3177 
3178 		rval = DFC_ARG_NULL;
3179 		goto done;
3180 	}
3181 
3182 	if (dfc->buf1_size < 8) {
3183 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3184 		    "%s: Buffer1 too small. (size=%d)",
3185 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3186 
3187 		rval = DFC_ARG_TOOSMALL;
3188 		goto done;
3189 	}
3190 
3191 	/* Read the wwn object */
3192 	bcopy((void *)dfc->buf1, (void *)wwpn, 8);
3193 
3194 	/* Make sure WWPN is unique */
3195 	vport = emlxs_vport_find_wwpn(hba, wwpn);
3196 
3197 	/* Physical does not have EMLXS_PORT_CONFIG set */
3198 	if (!vport || !(vport->flag & EMLXS_PORT_CONFIG)) {
3199 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3200 		    "%s: WWPN does not exists. %s", emlxs_dfc_xlate(dfc->cmd),
3201 		    emlxs_wwn_xlate(buffer, sizeof (buffer), wwpn));
3202 
3203 		rval = DFC_ARG_INVALID;
3204 		goto done;
3205 	}
3206 
3207 	if (vport->did) {
3208 		/* Fabric Logout */
3209 		if (!(pkt = emlxs_pkt_alloc(vport,
3210 		    sizeof (uint32_t) + sizeof (LOGO),
3211 		    sizeof (FCP_RSP), 0, KM_NOSLEEP))) {
3212 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3213 			    "%s: Unable to allocate packet.",
3214 			    emlxs_dfc_xlate(dfc->cmd));
3215 
3216 			rval = DFC_SYSRES_ERROR;
3217 			goto done;
3218 		}
3219 
3220 		/* Make this a polled IO */
3221 		pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
3222 		pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
3223 		pkt->pkt_comp = NULL;
3224 
3225 		pkt->pkt_tran_type = FC_PKT_EXCHANGE;
3226 		pkt->pkt_timeout = 60;
3227 
3228 		/* Build the fc header */
3229 		pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(FABRIC_DID);
3230 		pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
3231 		pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(vport->did);
3232 		pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3233 		pkt->pkt_cmd_fhdr.f_ctl =
3234 		    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
3235 		pkt->pkt_cmd_fhdr.seq_id = 0;
3236 		pkt->pkt_cmd_fhdr.df_ctl = 0;
3237 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
3238 		pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
3239 		pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
3240 		pkt->pkt_cmd_fhdr.ro = 0;
3241 
3242 		/* Build the command */
3243 		els = (ELS_PKT *) pkt->pkt_cmd;
3244 		els->elsCode = 0x05;	/* LOGO */
3245 		els->un.logo.un.nPortId32 = LE_SWAP32(vport->did);
3246 		bcopy(&vport->wwpn, &els->un.logo.portName, 8);
3247 
3248 		/*
3249 		 * Just send LOGO. Don't worry about result.
3250 		 * This is just a courtesy anyway.
3251 		 */
3252 		(void) emlxs_pkt_send(pkt, 1);
3253 
3254 
3255 		/* Take the port offline */
3256 		(void) emlxs_port_offline(vport, 0xffffffff);
3257 	}
3258 
3259 	vport->flag &= ~(EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLED);
3260 
3261 	rval = 0;
3262 
3263 done:
3264 
3265 	if (pkt) {
3266 		emlxs_pkt_free(pkt);
3267 	}
3268 
3269 	return (rval);
3270 
3271 } /* emlxs_dfc_destroy_vport() */
3272 
3273 
3274 /*ARGSUSED*/
3275 static int32_t
emlxs_dfc_get_vportinfo(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)3276 emlxs_dfc_get_vportinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3277 {
3278 	emlxs_port_t	*port = &PPORT;
3279 	emlxs_port_t	*vport;
3280 	dfc_vportinfo_t	*dfc_vport;
3281 	dfc_vportinfo_t	*dfc_vport_list = NULL;
3282 	uint32_t	i;
3283 	uint32_t	size;
3284 	uint32_t	max_count;
3285 	uint32_t	rval = DFC_SUCCESS;
3286 
3287 	if (!dfc->buf1 || !dfc->buf1_size) {
3288 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3289 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3290 
3291 		return (DFC_ARG_NULL);
3292 	}
3293 
3294 	size = (sizeof (dfc_vportinfo_t) * MAX_VPORTS);
3295 
3296 	if (!(dfc_vport_list =
3297 	    (dfc_vportinfo_t *)kmem_zalloc(size, KM_NOSLEEP))) {
3298 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3299 		    "%s: Unable to allocate memory.",
3300 		    emlxs_dfc_xlate(dfc->cmd));
3301 
3302 		return (DFC_SYSRES_ERROR);
3303 	}
3304 
3305 	max_count = 0;
3306 	for (i = 0; i <= hba->vpi_max; i++) {
3307 		vport = &VPORT(i);
3308 		dfc_vport = &dfc_vport_list[i];
3309 
3310 		if (!(vport->flag & EMLXS_PORT_CONFIG)) {
3311 			continue;
3312 		}
3313 
3314 		bcopy(vport->snn, dfc_vport->snn, 256);
3315 		bcopy(vport->spn, dfc_vport->spn, 256);
3316 		bcopy(&vport->wwpn, dfc_vport->wwpn, 8);
3317 		bcopy(&vport->wwnn, dfc_vport->wwnn, 8);
3318 		dfc_vport->port_id = vport->did;
3319 		dfc_vport->vpi = vport->vpi;
3320 		dfc_vport->ulp_statec = vport->ulp_statec;
3321 		dfc_vport->flags = VPORT_CONFIG;
3322 
3323 		if (vport->flag & EMLXS_PORT_ENABLED) {
3324 			dfc_vport->flags |= VPORT_ENABLED;
3325 		}
3326 
3327 		if (vport->flag & EMLXS_PORT_BOUND) {
3328 			dfc_vport->flags |= VPORT_BOUND;
3329 		}
3330 
3331 		if (vport->flag & EMLXS_PORT_IP_UP) {
3332 			dfc_vport->flags |= VPORT_IP;
3333 		}
3334 
3335 		if (vport->flag & EMLXS_PORT_RESTRICTED) {
3336 			dfc_vport->flags |= VPORT_RESTRICTED;
3337 		}
3338 
3339 		max_count++;
3340 	}
3341 
3342 	max_count *= sizeof (dfc_vportinfo_t);
3343 
3344 	if (max_count > dfc->buf1_size) {
3345 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3346 		    "%s: Buffer1 too small. (%d > %d)",
3347 		    emlxs_dfc_xlate(dfc->cmd), max_count, dfc->buf1_size);
3348 
3349 		rval = DFC_ARG_TOOSMALL;
3350 		goto done;
3351 	}
3352 
3353 	bcopy((void *)dfc_vport_list, (void *)dfc->buf1, dfc->buf1_size);
3354 
3355 done:
3356 
3357 	if (dfc_vport_list) {
3358 		kmem_free(dfc_vport_list, size);
3359 	}
3360 
3361 	return (rval);
3362 
3363 } /* emlxs_dfc_get_vportinfo() */
3364 
3365 
3366 static emlxs_port_t *
emlxs_vport_find_wwpn(emlxs_hba_t * hba,uint8_t * wwpn)3367 emlxs_vport_find_wwpn(emlxs_hba_t *hba, uint8_t *wwpn)
3368 {
3369 	emlxs_port_t	*port;
3370 	NODELIST	*nlp;
3371 	int		i, j;
3372 
3373 	for (i = 0; i <= hba->vpi_max; i++) {
3374 		port = &VPORT(i);
3375 
3376 		/* Check Local N-port, including physical port */
3377 		if (bcmp(&port->wwpn, wwpn, 8) == 0) {
3378 			return (port);
3379 		}
3380 
3381 		/* Check Remote N-port */
3382 		rw_enter(&port->node_rwlock, RW_READER);
3383 		for (j = 0; j < EMLXS_NUM_HASH_QUES; j++) {
3384 			nlp = port->node_table[j];
3385 			while (nlp != NULL) {
3386 				/* Check Local N-port */
3387 				if (bcmp(&nlp->nlp_portname, wwpn, 8) == 0) {
3388 					rw_exit(&port->node_rwlock);
3389 					return (port);
3390 				}
3391 				nlp = nlp->nlp_list_next;
3392 			}
3393 		}
3394 
3395 		rw_exit(&port->node_rwlock);
3396 	}
3397 
3398 	return (0);
3399 
3400 } /* emlxs_vport_find_wwpn() */
3401 
3402 
3403 /*ARGSUSED*/
3404 static int32_t
emlxs_dfc_npiv_resource(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)3405 emlxs_dfc_npiv_resource(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3406 {
3407 	emlxs_port_t		*port = &PPORT;
3408 	dfc_vport_resource_t	*vres;
3409 	MAILBOXQ		*mbq = NULL;
3410 	MAILBOX			*mb;
3411 	uint32_t		rval = DFC_SUCCESS;
3412 
3413 	if (!dfc->buf1 || !dfc->buf1_size) {
3414 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3415 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3416 
3417 		return (DFC_ARG_NULL);
3418 	}
3419 
3420 	if (dfc->buf1_size < sizeof (dfc_vport_resource_t)) {
3421 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3422 		    "%s: Buffer1 too small. (size=%d)",
3423 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3424 
3425 		return (DFC_ARG_TOOSMALL);
3426 	}
3427 
3428 	vres = (dfc_vport_resource_t *)dfc->buf1;
3429 	bzero(vres, sizeof (dfc_vport_resource_t));
3430 
3431 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3432 		int i;
3433 		int total_rpi;
3434 		emlxs_port_t *vport;
3435 
3436 		vres->vpi_max = min(hba->sli.sli4.VPICount, MAX_VPORTS) - 1;
3437 
3438 		total_rpi = 0;
3439 		for (i = 0; i < vres->vpi_max; i++) {
3440 			vport = &VPORT(i);
3441 			total_rpi += vport->vpip->rpi_online;
3442 		}
3443 
3444 		vres->vpi_inuse = (port->vpip->vfip == NULL) ? 0 :
3445 		    (port->vpip->vfip->vpi_online - 1);
3446 		vres->rpi_max = hba->sli.sli4.RPICount;
3447 		vres->rpi_inuse = total_rpi;
3448 
3449 		return (rval);
3450 	}
3451 
3452 	mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
3453 	mb = (MAILBOX *) mbq;
3454 
3455 	emlxs_mb_read_config(hba, mbq);
3456 
3457 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
3458 
3459 	if (rval == MBX_TIMEOUT) {
3460 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3461 		    "%s: Mailbox timed out. cmd=%x",
3462 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3463 
3464 		rval = DFC_TIMEOUT;
3465 		goto done;
3466 	}
3467 
3468 	if (rval) {
3469 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3470 		    "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
3471 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
3472 
3473 		rval = DFC_IO_ERROR;
3474 		goto done;
3475 	}
3476 
3477 	vres->vpi_max = mb->un.varRdConfig.max_vpi;
3478 	vres->vpi_inuse =
3479 	    (mb->un.varRdConfig.max_vpi <=
3480 	    mb->un.varRdConfig.avail_vpi) ? 0 : mb->un.varRdConfig.max_vpi -
3481 	    mb->un.varRdConfig.avail_vpi;
3482 
3483 	vres->rpi_max = mb->un.varRdConfig.max_rpi;
3484 	vres->rpi_inuse =
3485 	    (mb->un.varRdConfig.max_rpi <=
3486 	    mb->un.varRdConfig.avail_rpi) ? 0 : mb->un.varRdConfig.max_rpi -
3487 	    mb->un.varRdConfig.avail_rpi;
3488 
3489 done:
3490 
3491 	/* Free allocated mbox memory */
3492 	if (mbq) {
3493 		kmem_free(mbq, sizeof (MAILBOXQ));
3494 	}
3495 
3496 	return (rval);
3497 
3498 } /* emlxs_dfc_npiv_resource() */
3499 
3500 
3501 /*ARGSUSED*/
3502 static int32_t
emlxs_dfc_npiv_test(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)3503 emlxs_dfc_npiv_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3504 {
3505 	emlxs_port_t	*port = &PPORT;
3506 	emlxs_port_t	*vport = &VPORT(hba->vpi_max);
3507 	emlxs_config_t	*cfg = &CFG;
3508 	fc_packet_t	*pkt = NULL;
3509 	fc_packet_t	*pkt1 = NULL;
3510 	ELS_PKT		*els;
3511 	LS_RJT		*lsrjt;
3512 	uint32_t	checklist = 0;
3513 	uint32_t	mask = 0;
3514 	uint32_t	rval = DFC_SUCCESS;
3515 	uint8_t		wwn[8];
3516 	emlxs_vpd_t	*vpd = &VPD;
3517 	int		i;
3518 
3519 	if (!dfc->buf1 || !dfc->buf1_size) {
3520 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3521 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3522 
3523 		return (DFC_ARG_NULL);
3524 	}
3525 
3526 	if (dfc->buf1_size < sizeof (uint32_t)) {
3527 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3528 		    "%s: Buffer1 too small. (size=%d)",
3529 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3530 
3531 		return (DFC_ARG_TOOSMALL);
3532 	}
3533 
3534 	if (cfg[CFG_NPIV_ENABLE].current) {
3535 		checklist |= CL_NPIV_PARM_ENABLE;
3536 	}
3537 
3538 	if (hba->sli_mode >= 3) {
3539 		checklist |= CL_SLI3_ENABLE;
3540 	}
3541 
3542 
3543 	if ((vpd->feaLevelHigh >= 0x09) || (hba->sli_mode >= 4)) {
3544 		checklist |= CL_HBA_SUPPORT_NPIV;
3545 	}
3546 
3547 
3548 	if (hba->num_of_ports <= hba->vpi_max) {
3549 		checklist |= CL_HBA_HAS_RESOURCES;
3550 	}
3551 
3552 	if (hba->state < FC_LINK_UP) {
3553 		goto done;
3554 	}
3555 
3556 	checklist |= CL_HBA_LINKUP;
3557 
3558 	if (hba->topology == TOPOLOGY_LOOP) {
3559 		goto done;
3560 	}
3561 
3562 	if (!(hba->flag & FC_FABRIC_ATTACHED)) {
3563 		goto done;
3564 	}
3565 
3566 	checklist |= CL_P2P_TOPOLOGY;
3567 
3568 	if (!(hba->flag & FC_NPIV_SUPPORTED)) {
3569 		goto done;
3570 	}
3571 
3572 	checklist |= CL_FABRIC_SUPPORTS_NPIV;
3573 
3574 	mask =
3575 	    (CL_NPIV_PARM_ENABLE | CL_SLI3_ENABLE | CL_HBA_SUPPORT_NPIV |
3576 	    CL_HBA_HAS_RESOURCES);
3577 
3578 	/*
3579 	 * Check if those four conditions are met
3580 	 */
3581 	if ((checklist & mask) != mask) {
3582 		/*
3583 		 * One or more conditions are not met
3584 		 */
3585 		goto done;
3586 	}
3587 
3588 	/* Now check if fabric have resources */
3589 	for (i = 1; i <= hba->vpi_max; i++) {
3590 		vport = &VPORT(i);
3591 		if (vport->did) {
3592 			checklist |= CL_FABRIC_HAS_RESOURCES;
3593 			goto done;
3594 		}
3595 	}
3596 
3597 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3598 		(void) emlxs_vpi_port_bind_notify(vport);
3599 		/* wait one second for INIT_VPI completion */
3600 		drv_usecwait(1000000);
3601 	}
3602 
3603 	vport->vpi = hba->vpi_max;
3604 	vport->hba = hba;
3605 
3606 	if (!(pkt = emlxs_pkt_alloc(vport,
3607 	    sizeof (uint32_t) + sizeof (SERV_PARM), sizeof (FCP_RSP),
3608 	    0, KM_NOSLEEP))) {
3609 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3610 		    "Unable to allocate packet.");
3611 		goto done;
3612 	}
3613 
3614 	/* Build (FDISC) the fc header */
3615 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(FABRIC_DID);
3616 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_EXTENDED_SVC | R_CTL_UNSOL_CONTROL;
3617 	pkt->pkt_cmd_fhdr.s_id = 0;
3618 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3619 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE;
3620 	pkt->pkt_cmd_fhdr.seq_id = 0;
3621 	pkt->pkt_cmd_fhdr.df_ctl = 0;
3622 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
3623 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
3624 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
3625 	pkt->pkt_cmd_fhdr.ro = 0;
3626 
3627 	/* Build the command (FDISC) */
3628 	els = (ELS_PKT *) pkt->pkt_cmd;
3629 	els->elsCode = 0x04;	/* FLOGI - This will be changed automatically */
3630 				/* by the drive (See emlxs_send_els()) */
3631 
3632 	/* Copy latest service parameters to payload */
3633 	bcopy((void *)&port->sparam,
3634 	    (void *)&els->un.logi, sizeof (SERV_PARM));
3635 
3636 	bcopy((caddr_t)&hba->wwnn, (caddr_t)wwn, 8);
3637 	wwn[0] = 0x28;
3638 	wwn[1] = hba->vpi_max;
3639 	bcopy((caddr_t)wwn, (caddr_t)&els->un.logi.nodeName, 8);
3640 	bcopy((caddr_t)wwn, (caddr_t)&vport->wwnn, 8);
3641 
3642 	bcopy((caddr_t)&hba->wwpn, (caddr_t)wwn, 8);
3643 	wwn[0] = 0x20;
3644 	wwn[1] = hba->vpi_max;
3645 	bcopy((caddr_t)wwn, (caddr_t)&els->un.logi.portName, 8);
3646 	bcopy((caddr_t)wwn, (caddr_t)&vport->wwpn, 8);
3647 
3648 	bcopy((void *)&els->un.logi, (void *)&vport->sparam,
3649 	    sizeof (SERV_PARM));
3650 
3651 	/* Make this a polled IO */
3652 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
3653 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
3654 	pkt->pkt_comp = NULL;
3655 
3656 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
3657 	pkt->pkt_timeout = 60;
3658 
3659 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
3660 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3661 		    "%s: Unable to send packet.", emlxs_dfc_xlate(dfc->cmd));
3662 
3663 		goto done;
3664 	}
3665 
3666 	if (pkt->pkt_state == FC_PKT_SUCCESS) {
3667 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3668 			(void) emlxs_vpi_port_unbind_notify(vport, 1);
3669 			checklist |= CL_FABRIC_HAS_RESOURCES;
3670 		} else {
3671 			if (!(pkt1 = emlxs_pkt_alloc(vport,
3672 			    sizeof (uint32_t) + sizeof (LOGO), sizeof (FCP_RSP),
3673 			    0, KM_NOSLEEP))) {
3674 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3675 				    "Unable to allocate LOGO packet.");
3676 				goto free_resc;
3677 			}
3678 
3679 			/* Make this a polled IO */
3680 			pkt1->pkt_tran_flags &= ~FC_TRAN_INTR;
3681 			pkt1->pkt_tran_flags |= FC_TRAN_NO_INTR;
3682 			pkt1->pkt_comp = NULL;
3683 
3684 			pkt1->pkt_tran_type = FC_PKT_EXCHANGE;
3685 			pkt1->pkt_timeout = 60;
3686 
3687 			/* Build (LOGO) the fc header */
3688 			pkt1->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(FABRIC_DID);
3689 			pkt1->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
3690 			pkt1->pkt_cmd_fhdr.s_id =
3691 			    LE_SWAP24_LO(pkt->pkt_resp_fhdr.d_id);
3692 			pkt1->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3693 			pkt1->pkt_cmd_fhdr.f_ctl =
3694 			    F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
3695 			    F_CTL_SEQ_INITIATIVE;
3696 			pkt1->pkt_cmd_fhdr.seq_id = 0;
3697 			pkt1->pkt_cmd_fhdr.df_ctl = 0;
3698 			pkt1->pkt_cmd_fhdr.seq_cnt = 0;
3699 			pkt1->pkt_cmd_fhdr.ox_id = 0xFFFF;
3700 			pkt1->pkt_cmd_fhdr.rx_id = 0xFFFF;
3701 			pkt1->pkt_cmd_fhdr.ro = 0;
3702 
3703 			/* Build the command (LOGO) */
3704 			els = (ELS_PKT *) pkt1->pkt_cmd;
3705 			els->elsCode = 0x05;	/* LOGO */
3706 			els->un.logo.un.nPortId32 =
3707 			    LE_SWAP32(pkt->pkt_resp_fhdr.d_id);
3708 			bcopy((caddr_t)&hba->wwpn, (caddr_t)wwn, 8);
3709 			wwn[0] = 0x20;
3710 			wwn[1] = hba->vpi_max;
3711 			bcopy(wwn, &els->un.logo.portName, 8);
3712 
3713 			if (emlxs_pkt_send(pkt1, 1) != FC_SUCCESS) {
3714 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3715 				    "%s: Unable to send packet.",
3716 				    emlxs_dfc_xlate(dfc->cmd));
3717 
3718 				goto free_resc;
3719 			}
3720 
3721 			if (pkt1->pkt_state != FC_PKT_SUCCESS) {
3722 				if (pkt1->pkt_state == FC_PKT_TIMEOUT) {
3723 					EMLXS_MSGF(EMLXS_CONTEXT,
3724 					    &emlxs_dfc_error_msg,
3725 					    "%s: Pkt Transport error. "
3726 					    "Pkt Timeout.",
3727 					    emlxs_dfc_xlate(dfc->cmd));
3728 				} else {
3729 					EMLXS_MSGF(EMLXS_CONTEXT,
3730 					    &emlxs_dfc_error_msg,
3731 					    "%s: Pkt Transport error. state=%x",
3732 					    emlxs_dfc_xlate(dfc->cmd),
3733 					    pkt1->pkt_state);
3734 				}
3735 				goto free_resc;
3736 			}
3737 
3738 			checklist |= CL_FABRIC_HAS_RESOURCES;
3739 free_resc:
3740 			/* Free default RPIs and VPI */
3741 			/* Unregister all nodes */
3742 			(void) EMLXS_SLI_UNREG_NODE(vport, 0, 0, 0, 0);
3743 
3744 			(void) emlxs_mb_unreg_vpi(vport);
3745 		}
3746 	} else if (pkt->pkt_state == FC_PKT_LS_RJT) {
3747 		lsrjt = (LS_RJT *) pkt->pkt_resp;
3748 		if (lsrjt->un.b.lsRjtRsnCodeExp != LSEXP_OUT_OF_RESOURCE) {
3749 			checklist |= CL_FABRIC_HAS_RESOURCES;
3750 		}
3751 	}
3752 
3753 done:
3754 	bcopy((void *)&checklist, (void *)dfc->buf1, sizeof (uint32_t));
3755 
3756 	if (pkt) {
3757 		/* Free the pkt */
3758 		emlxs_pkt_free(pkt);
3759 	}
3760 
3761 	if (pkt1) {
3762 		/* Free the pkt */
3763 		emlxs_pkt_free(pkt1);
3764 	}
3765 
3766 	return (rval);
3767 
3768 } /* emlxs_dfc_npiv_test() */
3769 
3770 
3771 /*ARGSUSED*/
3772 static int32_t
emlxs_dfc_get_rev(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)3773 emlxs_dfc_get_rev(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3774 {
3775 	emlxs_port_t	*port = &PPORT;
3776 	uint32_t	rev;
3777 
3778 	if (!dfc->buf1 || !dfc->buf1_size) {
3779 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3780 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3781 
3782 		return (DFC_ARG_NULL);
3783 	}
3784 
3785 	if (dfc->buf1_size < sizeof (uint32_t)) {
3786 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3787 		    "%s: Buffer1 too small. (size=%d)",
3788 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3789 
3790 		return (DFC_ARG_TOOSMALL);
3791 	}
3792 
3793 	rev = DFC_REV;
3794 	bcopy((void *)&rev, (void *)dfc->buf1, sizeof (uint32_t));
3795 
3796 	return (0);
3797 
3798 } /* emlxs_dfc_get_rev() */
3799 
3800 
3801 /*ARGSUSED*/
3802 static int32_t
emlxs_dfc_get_hbainfo(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)3803 emlxs_dfc_get_hbainfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3804 {
3805 	emlxs_port_t	*port = &PPORT;
3806 	emlxs_vpd_t	*vpd = &VPD;
3807 	emlxs_config_t	*cfg = &CFG;
3808 	dfc_hbainfo_t	*hbainfo;
3809 	char		pathname[256];
3810 
3811 	if (!dfc->buf1 || !dfc->buf1_size) {
3812 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3813 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3814 
3815 		return (DFC_ARG_NULL);
3816 	}
3817 
3818 	if (dfc->buf1_size < sizeof (dfc_hbainfo_t)) {
3819 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3820 		    "%s: Buffer1 too small. (size=%d)",
3821 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3822 
3823 		return (DFC_ARG_TOOSMALL);
3824 	}
3825 
3826 	hbainfo = (dfc_hbainfo_t *)dfc->buf1;
3827 	bzero((void *) hbainfo, sizeof (dfc_hbainfo_t));
3828 
3829 	(void) strncpy(hbainfo->vpd_serial_num, vpd->serial_num,
3830 	    (sizeof (hbainfo->vpd_serial_num)-1));
3831 	(void) strncpy(hbainfo->vpd_part_num, vpd->part_num,
3832 	    (sizeof (hbainfo->vpd_part_num)-1));
3833 	(void) strncpy(hbainfo->vpd_port_num, vpd->port_num,
3834 	    (sizeof (hbainfo->vpd_port_num)-1));
3835 	(void) strncpy(hbainfo->vpd_eng_change, vpd->eng_change,
3836 	    (sizeof (hbainfo->vpd_eng_change)-1));
3837 	(void) strncpy(hbainfo->vpd_manufacturer, vpd->manufacturer,
3838 	    (sizeof (hbainfo->vpd_manufacturer)-1));
3839 	(void) strncpy(hbainfo->vpd_model, vpd->model,
3840 	    (sizeof (hbainfo->vpd_model)-1));
3841 	(void) strncpy(hbainfo->vpd_model_desc, vpd->model_desc,
3842 	    (sizeof (hbainfo->vpd_model_desc)-1));
3843 	(void) strncpy(hbainfo->vpd_prog_types, vpd->prog_types,
3844 	    (sizeof (hbainfo->vpd_prog_types)-1));
3845 	(void) strncpy(hbainfo->vpd_id, vpd->id,
3846 	    (sizeof (hbainfo->vpd_id)-1));
3847 
3848 	hbainfo->device_id = hba->model_info.device_id;
3849 	hbainfo->vendor_id = hba->model_info.vendor_id;
3850 
3851 	hbainfo->ports = hba->num_of_ports;
3852 	hbainfo->port_index = vpd->port_index;
3853 
3854 	bcopy(&hba->wwnn, hbainfo->wwnn, sizeof (hbainfo->wwnn));
3855 	(void) strncpy(hbainfo->snn, port->snn, (sizeof (hbainfo->snn)-1));
3856 
3857 	bcopy(&hba->wwpn, hbainfo->wwpn, sizeof (hbainfo->wwpn));
3858 	(void) strncpy(hbainfo->spn, port->spn, (sizeof (hbainfo->spn)-1));
3859 
3860 	hbainfo->biuRev = vpd->biuRev;
3861 	hbainfo->smRev = vpd->smRev;
3862 	hbainfo->smFwRev = vpd->smFwRev;
3863 	hbainfo->endecRev = vpd->endecRev;
3864 	hbainfo->rBit = vpd->rBit;
3865 	hbainfo->fcphHigh = vpd->fcphHigh;
3866 	hbainfo->fcphLow = vpd->fcphLow;
3867 	hbainfo->feaLevelHigh = vpd->feaLevelHigh;
3868 	hbainfo->feaLevelLow = vpd->feaLevelLow;
3869 
3870 	hbainfo->kern_rev = vpd->postKernRev;
3871 	(void) strncpy(hbainfo->kern_name, vpd->postKernName,
3872 	    (sizeof (hbainfo->kern_name)-1));
3873 
3874 	hbainfo->stub_rev = vpd->opFwRev;
3875 	(void) strncpy(hbainfo->stub_name, vpd->opFwName,
3876 	    (sizeof (hbainfo->stub_name)-1));
3877 
3878 	hbainfo->sli1_rev = vpd->sli1FwRev;
3879 	(void) strncpy(hbainfo->sli1_name, vpd->sli1FwName,
3880 	    (sizeof (hbainfo->sli1_name)-1));
3881 
3882 	hbainfo->sli2_rev = vpd->sli2FwRev;
3883 	(void) strncpy(hbainfo->sli2_name, vpd->sli2FwName,
3884 	    (sizeof (hbainfo->sli2_name)-1));
3885 
3886 	hbainfo->sli3_rev = vpd->sli3FwRev;
3887 	(void) strncpy(hbainfo->sli3_name, vpd->sli3FwName,
3888 	    (sizeof (hbainfo->sli3_name)-1));
3889 
3890 	hbainfo->sli4_rev = vpd->sli4FwRev;
3891 	(void) strncpy(hbainfo->sli4_name, vpd->sli4FwName,
3892 	    (sizeof (hbainfo->sli4_name)-1));
3893 
3894 	hbainfo->sli_mode = hba->sli_mode;
3895 	hbainfo->vpi_max  = hba->vpi_max;
3896 	hbainfo->vpi_high = hba->vpi_high;
3897 	hbainfo->flags = 0;
3898 
3899 	/* Set support flags */
3900 	hbainfo->flags  = HBA_FLAG_DYN_WWN;
3901 	hbainfo->flags |= HBA_FLAG_NPIV;
3902 
3903 #ifdef DHCHAP_SUPPORT
3904 	hbainfo->flags |= HBA_FLAG_DHCHAP;
3905 
3906 	if (cfg[CFG_AUTH_E2E].current) {
3907 		hbainfo->flags |= HBA_FLAG_E2E_AUTH;
3908 	}
3909 #endif	/* DHCHAP_SUPPORT */
3910 
3911 #ifdef SAN_DIAG_SUPPORT
3912 	hbainfo->flags |= HBA_FLAG_SAN_DIAG;
3913 #endif	/* SAN_DIAG_SUPPORT */
3914 
3915 #ifdef SFCT_SUPPORT
3916 	hbainfo->flags |= HBA_FLAG_TARGET_MODE;
3917 	if (port->mode == MODE_TARGET) {
3918 		hbainfo->flags |= HBA_FLAG_TARGET_MODE_ENA;
3919 	}
3920 #endif /* SFCT_SUPPORT */
3921 
3922 	hbainfo->flags |= HBA_FLAG_PERSISTLINK;
3923 
3924 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3925 		hbainfo->flags |= HBA_FLAG_EXT_MBOX;
3926 		if (SLI4_FCOE_MODE) {
3927 			hbainfo->flags |= HBA_FLAG_FCOE;
3928 			hbainfo->flags &= ~HBA_FLAG_PERSISTLINK;
3929 		}
3930 	}
3931 
3932 	(void) strncpy(hbainfo->fcode_version, vpd->fcode_version,
3933 	    (sizeof (hbainfo->fcode_version)-1));
3934 	(void) strncpy(hbainfo->boot_version, vpd->boot_version,
3935 	    (sizeof (hbainfo->boot_version)-1));
3936 	(void) strncpy(hbainfo->fw_version, vpd->fw_version,
3937 	    (sizeof (hbainfo->fw_version)-1));
3938 	(void) strncpy(hbainfo->drv_label, emlxs_label,
3939 	    (sizeof (hbainfo->drv_label)-1));
3940 	(void) strncpy(hbainfo->drv_module, emlxs_name,
3941 	    (sizeof (hbainfo->drv_module)-1));
3942 	(void) strncpy(hbainfo->drv_name, DRIVER_NAME,
3943 	    (sizeof (hbainfo->drv_name)-1));
3944 	(void) strncpy(hbainfo->drv_version, emlxs_version,
3945 	    (sizeof (hbainfo->drv_version)-1));
3946 	(void) strncpy(hbainfo->drv_revision, emlxs_revision,
3947 	    (sizeof (hbainfo->drv_revision)-1));
3948 	(void) strncpy(hbainfo->hostname, (char *)utsname.nodename,
3949 	    (sizeof (hbainfo->hostname)-1));
3950 
3951 	(void) ddi_pathname(hba->dip, pathname);
3952 	(void) snprintf(hbainfo->os_devname, (sizeof (hbainfo->os_devname)-1),
3953 	    "/devices%s", pathname);
3954 
3955 	if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) {
3956 		hbainfo->flags |= HBA_FLAG_OFFLINE;
3957 	}
3958 
3959 	hbainfo->drv_instance = hba->ddiinst;
3960 	hbainfo->port_id = port->did;
3961 	hbainfo->port_type = HBA_PORTTYPE_UNKNOWN;
3962 
3963 #ifdef MENLO_SUPPORT
3964 	if (hba->flag & FC_MENLO_MODE) {
3965 		hbainfo->topology  = LNK_MENLO_MAINTENANCE;
3966 	} else
3967 #endif /* MENLO_SUPPORT */
3968 
3969 	if (hba->state >= FC_LINK_UP) {
3970 		if (hba->topology == TOPOLOGY_LOOP) {
3971 			if (hba->flag & FC_FABRIC_ATTACHED) {
3972 				hbainfo->port_type = HBA_PORTTYPE_NLPORT;
3973 				hbainfo->topology = LNK_PUBLIC_LOOP;
3974 			} else {
3975 				hbainfo->port_type = HBA_PORTTYPE_LPORT;
3976 				hbainfo->topology = LNK_LOOP;
3977 			}
3978 
3979 			hbainfo->alpa_count = port->alpa_map[0];
3980 			bcopy((void *)&port->alpa_map[1], hbainfo->alpa_map,
3981 			    hbainfo->alpa_count);
3982 		} else {
3983 			if (hba->flag & FC_PT_TO_PT) {
3984 				hbainfo->port_type = HBA_PORTTYPE_PTP;
3985 				hbainfo->topology = LNK_PT2PT;
3986 			} else {
3987 				hbainfo->port_type = HBA_PORTTYPE_NPORT;
3988 				hbainfo->topology = LNK_FABRIC;
3989 			}
3990 		}
3991 
3992 		if (hba->flag & FC_FABRIC_ATTACHED) {
3993 			bcopy(&port->fabric_sparam.nodeName,
3994 			    hbainfo->fabric_wwnn,
3995 			    sizeof (hbainfo->fabric_wwnn));
3996 			bcopy(&port->fabric_sparam.portName,
3997 			    hbainfo->fabric_wwpn,
3998 			    sizeof (hbainfo->fabric_wwpn));
3999 		}
4000 
4001 		if (hba->linkspeed == LA_2GHZ_LINK) {
4002 			hbainfo->port_speed = HBA_PORTSPEED_2GBIT;
4003 		} else if (hba->linkspeed == LA_4GHZ_LINK) {
4004 			hbainfo->port_speed = HBA_PORTSPEED_4GBIT;
4005 		} else if (hba->linkspeed == LA_8GHZ_LINK) {
4006 			hbainfo->port_speed = HBA_PORTSPEED_8GBIT;
4007 		} else if (hba->linkspeed == LA_10GHZ_LINK) {
4008 			hbainfo->port_speed = HBA_PORTSPEED_10GBIT;
4009 		} else if (hba->linkspeed == LA_16GHZ_LINK) {
4010 			hbainfo->port_speed = HBA_PORTSPEED_16GBIT;
4011 		} else if (hba->linkspeed == LA_32GHZ_LINK) {
4012 			hbainfo->port_speed = HBA_PORTSPEED_32GBIT;
4013 		} else {
4014 			hbainfo->port_speed = HBA_PORTSPEED_1GBIT;
4015 		}
4016 
4017 		hbainfo->node_count = port->node_count;
4018 	}
4019 
4020 	hbainfo->hard_alpa = cfg[CFG_ASSIGN_ALPA].current;
4021 	hbainfo->supported_cos = LE_SWAP32((FC_NS_CLASS3 | FC_NS_CLASS2));
4022 
4023 	hbainfo->supported_types[0] = LE_SWAP32(0x00000120);
4024 	hbainfo->supported_types[1] = LE_SWAP32(0x00000001);
4025 
4026 	hbainfo->active_types[0] = LE_SWAP32(0x00000120);
4027 	hbainfo->active_types[1] = LE_SWAP32(0x00000001);
4028 
4029 	if (!cfg[CFG_NETWORK_ON].current) {
4030 		hbainfo->active_types[0] &= ~(LE_SWAP32(0x00000020));
4031 	}
4032 
4033 	if (vpd->link_speed & LMT_32GB_CAPABLE) {
4034 		hbainfo->supported_speeds |= FC_HBA_PORTSPEED_32GBIT;
4035 	}
4036 	if (vpd->link_speed & LMT_16GB_CAPABLE) {
4037 		hbainfo->supported_speeds |= FC_HBA_PORTSPEED_16GBIT;
4038 	}
4039 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
4040 		hbainfo->supported_speeds |= FC_HBA_PORTSPEED_10GBIT;
4041 	}
4042 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
4043 		hbainfo->supported_speeds |= FC_HBA_PORTSPEED_8GBIT;
4044 	}
4045 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
4046 		hbainfo->supported_speeds |= FC_HBA_PORTSPEED_4GBIT;
4047 	}
4048 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
4049 		hbainfo->supported_speeds |= FC_HBA_PORTSPEED_2GBIT;
4050 	}
4051 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
4052 		hbainfo->supported_speeds |= FC_HBA_PORTSPEED_1GBIT;
4053 	}
4054 
4055 	hbainfo->max_frame_size = FF_FRAME_SIZE;
4056 
4057 	if (hba->bus_type == SBUS_FC) {
4058 		hbainfo->flags |= HBA_FLAG_SBUS;
4059 	}
4060 
4061 	if (hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE)) {
4062 		hbainfo->flags |= HBA_FLAG_OFFLINE;
4063 		hbainfo->port_state = HBA_PORTSTATE_UNKNOWN;
4064 	} else if (hba->flag & FC_ONLINE_MODE) {
4065 		if (hba->flag & FC_LOOPBACK_MODE) {
4066 			hbainfo->port_state = HBA_PORTSTATE_LOOPBACK;
4067 		} else if (hba->state <= FC_LINK_DOWN) {
4068 			hbainfo->port_state = HBA_PORTSTATE_LINKDOWN;
4069 		}
4070 #ifdef MENLO_SUPPORT
4071 		else if (hba->flag & FC_MENLO_MODE) {
4072 			hbainfo->port_state = HBA_PORTSTATE_LINKDOWN;
4073 		}
4074 #endif /* MENLO_SUPPORT */
4075 		else {
4076 			hbainfo->port_state = HBA_PORTSTATE_ONLINE;
4077 		}
4078 	} else {
4079 		hbainfo->flags |= HBA_FLAG_OFFLINE;
4080 
4081 		if (hba->state == FC_ERROR) {
4082 			hbainfo->port_state = HBA_PORTSTATE_ERROR;
4083 		} else {
4084 			hbainfo->port_state = HBA_PORTSTATE_OFFLINE;
4085 		}
4086 	}
4087 
4088 	hbainfo->pci_function_number = hba->pci_function_number;
4089 	hbainfo->pci_device_number = hba->pci_device_number;
4090 	hbainfo->pci_bus_number = hba->pci_bus_number;
4091 
4092 #ifdef FMA_SUPPORT
4093 	/* Access handle validation */
4094 	if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
4095 	    != DDI_FM_OK) {
4096 		EMLXS_MSGF(EMLXS_CONTEXT,
4097 		    &emlxs_invalid_access_handle_msg, NULL);
4098 		return (DFC_DRV_ERROR);
4099 	}
4100 #endif  /* FMA_SUPPORT */
4101 
4102 	return (0);
4103 
4104 } /* emlxs_dfc_get_hbainfo() */
4105 
4106 
4107 
4108 /*ARGSUSED*/
4109 static int32_t
emlxs_dfc_get_hbastats(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)4110 emlxs_dfc_get_hbastats(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4111 {
4112 	emlxs_port_t	*port = &PPORT;
4113 	dfc_hbastats_t	*stats;
4114 	MAILBOX		*mb = NULL;
4115 	MAILBOXQ	*mbq = NULL;
4116 	uint32_t	rval = 0;
4117 
4118 	if (!dfc->buf1 || !dfc->buf1_size) {
4119 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4120 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4121 
4122 		return (DFC_ARG_NULL);
4123 	}
4124 
4125 	if (dfc->buf1_size < sizeof (dfc_hbastats_t)) {
4126 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4127 		    "%s: Buffer1 too small. (size=%d)",
4128 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
4129 
4130 		return (DFC_ARG_TOOSMALL);
4131 	}
4132 
4133 	mbq =
4134 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
4135 
4136 	mb = (MAILBOX *)mbq;
4137 
4138 	emlxs_mb_read_status(hba, mbq);
4139 
4140 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
4141 
4142 	if (rval == MBX_TIMEOUT) {
4143 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4144 		    "%s: Mailbox timed out. cmd=%x",
4145 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4146 
4147 		rval = DFC_TIMEOUT;
4148 		goto done;
4149 	}
4150 
4151 	if (rval) {
4152 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4153 		    "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
4154 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
4155 
4156 		rval = DFC_IO_ERROR;
4157 		goto done;
4158 	}
4159 
4160 	stats = (dfc_hbastats_t *)dfc->buf1;
4161 	bzero((void *)stats, sizeof (dfc_hbastats_t));
4162 
4163 	stats->tx_frame_cnt = mb->un.varRdStatus.xmitFrameCnt;
4164 	stats->rx_frame_cnt = mb->un.varRdStatus.rcvFrameCnt;
4165 	stats->tx_kbyte_cnt = mb->un.varRdStatus.xmitByteCnt;
4166 	stats->rx_kbyte_cnt = mb->un.varRdStatus.rcvByteCnt;
4167 	stats->tx_seq_cnt = mb->un.varRdStatus.xmitSeqCnt;
4168 	stats->rx_seq_cnt = mb->un.varRdStatus.rcvSeqCnt;
4169 	stats->orig_exch_cnt = mb->un.varRdStatus.totalOrigExchanges;
4170 	stats->resp_exch_cnt = mb->un.varRdStatus.totalRespExchanges;
4171 	stats->pbsy_cnt = mb->un.varRdStatus.rcvPbsyCnt;
4172 	stats->fbsy_cnt = mb->un.varRdStatus.rcvFbsyCnt;
4173 
4174 	emlxs_mb_read_lnk_stat(hba, mbq);
4175 
4176 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
4177 
4178 	if (rval == MBX_TIMEOUT) {
4179 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4180 		    "%s: Mailbox timed out. cmd=%x",
4181 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4182 
4183 		rval = DFC_TIMEOUT;
4184 		goto done;
4185 	}
4186 
4187 	if (rval) {
4188 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4189 		    "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
4190 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
4191 
4192 		rval = DFC_IO_ERROR;
4193 		goto done;
4194 	}
4195 
4196 	stats->link_failure_cnt = mb->un.varRdLnk.linkFailureCnt;
4197 	stats->loss_sync_cnt = mb->un.varRdLnk.lossSyncCnt;
4198 	stats->loss_signal_cnt = mb->un.varRdLnk.lossSignalCnt;
4199 	stats->seq_error_cnt = mb->un.varRdLnk.primSeqErrCnt;
4200 	stats->inval_tx_word_cnt = mb->un.varRdLnk.invalidXmitWord;
4201 	stats->crc_error_cnt = mb->un.varRdLnk.crcCnt;
4202 	stats->seq_timeout_cnt = mb->un.varRdLnk.primSeqTimeout;
4203 	stats->elastic_overrun_cnt = mb->un.varRdLnk.elasticOverrun;
4204 	stats->arb_timeout_cnt = mb->un.varRdLnk.arbTimeout;
4205 	stats->rx_buf_credit = mb->un.varRdLnk.rxBufCredit;
4206 	stats->rx_buf_cnt = mb->un.varRdLnk.rxBufCreditCur;
4207 	stats->tx_buf_credit = mb->un.varRdLnk.txBufCredit;
4208 	stats->tx_buf_cnt = mb->un.varRdLnk.txBufCreditCur;
4209 	stats->EOFa_cnt = mb->un.varRdLnk.EOFaCnt;
4210 	stats->EOFdti_cnt = mb->un.varRdLnk.EOFdtiCnt;
4211 	stats->EOFni_cnt = mb->un.varRdLnk.EOFniCnt;
4212 	stats->SOFf_cnt = mb->un.varRdLnk.SOFfCnt;
4213 	stats->link_event_tag = hba->link_event_tag;
4214 	stats->last_reset_time = hba->timer_tics - hba->stats.ResetTime;
4215 	stats->port_type = HBA_PORTTYPE_UNKNOWN;
4216 
4217 #ifdef MENLO_SUPPORT
4218 	if (hba->flag & FC_MENLO_MODE) {
4219 		stats->topology = LNK_MENLO_MAINTENANCE;
4220 	} else
4221 #endif /* MENLO_SUPPORT */
4222 
4223 	if (hba->state >= FC_LINK_UP) {
4224 		if (hba->topology == TOPOLOGY_LOOP) {
4225 			if (hba->flag & FC_FABRIC_ATTACHED) {
4226 				stats->port_type = HBA_PORTTYPE_NLPORT;
4227 				stats->topology = LNK_PUBLIC_LOOP;
4228 			} else {
4229 				stats->port_type = HBA_PORTTYPE_LPORT;
4230 				stats->topology = LNK_LOOP;
4231 			}
4232 		} else {
4233 			if (hba->flag & FC_PT_TO_PT) {
4234 				stats->port_type = HBA_PORTTYPE_PTP;
4235 				stats->topology = LNK_PT2PT;
4236 			} else {
4237 				stats->port_type = HBA_PORTTYPE_NPORT;
4238 				stats->topology = LNK_FABRIC;
4239 			}
4240 		}
4241 
4242 		if (hba->linkspeed == LA_2GHZ_LINK) {
4243 			stats->link_speed = HBA_PORTSPEED_2GBIT;
4244 		} else if (hba->linkspeed == LA_4GHZ_LINK) {
4245 			stats->link_speed = HBA_PORTSPEED_4GBIT;
4246 		} else if (hba->linkspeed == LA_8GHZ_LINK) {
4247 			stats->link_speed = HBA_PORTSPEED_8GBIT;
4248 		} else if (hba->linkspeed == LA_10GHZ_LINK) {
4249 			stats->link_speed = HBA_PORTSPEED_10GBIT;
4250 		} else if (hba->linkspeed == LA_16GHZ_LINK) {
4251 			stats->link_speed = HBA_PORTSPEED_16GBIT;
4252 		} else if (hba->linkspeed == LA_32GHZ_LINK) {
4253 			stats->link_speed = HBA_PORTSPEED_32GBIT;
4254 		} else {
4255 			stats->link_speed = HBA_PORTSPEED_1GBIT;
4256 		}
4257 	}
4258 
4259 done:
4260 
4261 	/* Free allocated mbox memory */
4262 	if (mbq) {
4263 		kmem_free(mbq, sizeof (MAILBOXQ));
4264 	}
4265 
4266 	return (rval);
4267 
4268 } /* emlxs_dfc_get_hbastats() */
4269 
4270 
4271 
4272 /*ARGSUSED*/
4273 static int32_t
emlxs_dfc_get_drvstats(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)4274 emlxs_dfc_get_drvstats(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4275 {
4276 	emlxs_port_t	*port = &PPORT;
4277 	dfc_drvstats_t	*stats;
4278 	uint32_t	rval = 0;
4279 
4280 	if (!dfc->buf1 || !dfc->buf1_size) {
4281 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4282 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4283 
4284 		return (DFC_ARG_NULL);
4285 	}
4286 
4287 	stats = (dfc_drvstats_t *)dfc->buf1;
4288 	bzero((void *)stats, sizeof (dfc_drvstats_t));
4289 
4290 	stats->LinkUp = hba->stats.LinkUp;
4291 	stats->LinkDown = hba->stats.LinkDown;
4292 	stats->LinkEvent = hba->stats.LinkEvent;
4293 	stats->LinkMultiEvent = hba->stats.LinkMultiEvent;
4294 
4295 	stats->MboxIssued = hba->stats.MboxIssued;
4296 	stats->MboxCompleted = hba->stats.MboxCompleted;
4297 	stats->MboxGood = hba->stats.MboxGood;
4298 	stats->MboxError = hba->stats.MboxError;
4299 	stats->MboxBusy = hba->stats.MboxBusy;
4300 	stats->MboxInvalid = hba->stats.MboxInvalid;
4301 
4302 	stats->IocbIssued[0] = hba->stats.IocbIssued[0];
4303 	stats->IocbIssued[1] = hba->stats.IocbIssued[1];
4304 	stats->IocbIssued[2] = hba->stats.IocbIssued[2];
4305 	stats->IocbIssued[3] = hba->stats.IocbIssued[3];
4306 	stats->IocbReceived[0] = hba->stats.IocbReceived[0];
4307 	stats->IocbReceived[1] = hba->stats.IocbReceived[1];
4308 	stats->IocbReceived[2] = hba->stats.IocbReceived[2];
4309 	stats->IocbReceived[3] = hba->stats.IocbReceived[3];
4310 	stats->IocbTxPut[0] = hba->stats.IocbTxPut[0];
4311 	stats->IocbTxPut[1] = hba->stats.IocbTxPut[1];
4312 	stats->IocbTxPut[2] = hba->stats.IocbTxPut[2];
4313 	stats->IocbTxPut[3] = hba->stats.IocbTxPut[3];
4314 	stats->IocbTxGet[0] = hba->stats.IocbTxGet[0];
4315 	stats->IocbTxGet[1] = hba->stats.IocbTxGet[1];
4316 	stats->IocbTxGet[2] = hba->stats.IocbTxGet[2];
4317 	stats->IocbTxGet[3] = hba->stats.IocbTxGet[3];
4318 	stats->IocbRingFull[0] = hba->stats.IocbRingFull[0];
4319 	stats->IocbRingFull[1] = hba->stats.IocbRingFull[1];
4320 	stats->IocbRingFull[2] = hba->stats.IocbRingFull[2];
4321 	stats->IocbRingFull[3] = hba->stats.IocbRingFull[3];
4322 
4323 	stats->IntrEvent[0] = hba->stats.IntrEvent[0];
4324 	stats->IntrEvent[1] = hba->stats.IntrEvent[1];
4325 	stats->IntrEvent[2] = hba->stats.IntrEvent[2];
4326 	stats->IntrEvent[3] = hba->stats.IntrEvent[3];
4327 	stats->IntrEvent[4] = hba->stats.IntrEvent[4];
4328 	stats->IntrEvent[5] = hba->stats.IntrEvent[5];
4329 	stats->IntrEvent[6] = hba->stats.IntrEvent[6];
4330 	stats->IntrEvent[7] = hba->stats.IntrEvent[7];
4331 
4332 	stats->FcpIssued = hba->stats.FcpIssued;
4333 	stats->FcpCompleted = hba->stats.FcpCompleted;
4334 	stats->FcpGood = hba->stats.FcpGood;
4335 	stats->FcpError = hba->stats.FcpError;
4336 
4337 	stats->FcpEvent = hba->stats.FcpEvent;
4338 	stats->FcpStray = hba->stats.FcpStray;
4339 
4340 	stats->ElsEvent = hba->stats.ElsEvent;
4341 	stats->ElsStray = hba->stats.ElsStray;
4342 
4343 	stats->ElsCmdIssued = hba->stats.ElsCmdIssued;
4344 	stats->ElsCmdCompleted = hba->stats.ElsCmdCompleted;
4345 	stats->ElsCmdGood = hba->stats.ElsCmdGood;
4346 	stats->ElsCmdError = hba->stats.ElsCmdError;
4347 
4348 	stats->ElsRspIssued = hba->stats.ElsRspIssued;
4349 	stats->ElsRspCompleted = hba->stats.ElsRspCompleted;
4350 
4351 	stats->ElsRcvEvent = hba->stats.ElsRcvEvent;
4352 	stats->ElsRcvError = hba->stats.ElsRcvError;
4353 	stats->ElsRcvDropped = hba->stats.ElsRcvDropped;
4354 	stats->ElsCmdReceived = hba->stats.ElsCmdReceived;
4355 	stats->ElsRscnReceived = hba->stats.ElsRscnReceived;
4356 	stats->ElsPlogiReceived = hba->stats.ElsPlogiReceived;
4357 	stats->ElsPrliReceived = hba->stats.ElsPrliReceived;
4358 	stats->ElsPrloReceived = hba->stats.ElsPrloReceived;
4359 	stats->ElsLogoReceived = hba->stats.ElsLogoReceived;
4360 	stats->ElsAdiscReceived = hba->stats.ElsAdiscReceived;
4361 	stats->ElsGenReceived = hba->stats.ElsGenReceived;
4362 
4363 	stats->CtEvent = hba->stats.CtEvent;
4364 	stats->CtStray = hba->stats.CtStray;
4365 
4366 	stats->CtCmdIssued = hba->stats.CtCmdIssued;
4367 	stats->CtCmdCompleted = hba->stats.CtCmdCompleted;
4368 	stats->CtCmdGood = hba->stats.CtCmdGood;
4369 	stats->CtCmdError = hba->stats.CtCmdError;
4370 
4371 	stats->CtRspIssued = hba->stats.CtRspIssued;
4372 	stats->CtRspCompleted = hba->stats.CtRspCompleted;
4373 
4374 	stats->CtRcvEvent = hba->stats.CtRcvEvent;
4375 	stats->CtRcvError = hba->stats.CtRcvError;
4376 	stats->CtRcvDropped = hba->stats.CtRcvDropped;
4377 	stats->CtCmdReceived = hba->stats.CtCmdReceived;
4378 
4379 	stats->IpEvent = hba->stats.IpEvent;
4380 	stats->IpStray = hba->stats.IpStray;
4381 
4382 	stats->IpSeqIssued = hba->stats.IpSeqIssued;
4383 	stats->IpSeqCompleted = hba->stats.IpSeqCompleted;
4384 	stats->IpSeqGood = hba->stats.IpSeqGood;
4385 	stats->IpSeqError = hba->stats.IpSeqError;
4386 
4387 	stats->IpBcastIssued = hba->stats.IpBcastIssued;
4388 	stats->IpBcastCompleted = hba->stats.IpBcastCompleted;
4389 	stats->IpBcastGood = hba->stats.IpBcastGood;
4390 	stats->IpBcastError = hba->stats.IpBcastError;
4391 
4392 	stats->IpRcvEvent = hba->stats.IpRcvEvent;
4393 	stats->IpDropped = hba->stats.IpDropped;
4394 	stats->IpSeqReceived = hba->stats.IpSeqReceived;
4395 	stats->IpBcastReceived = hba->stats.IpBcastReceived;
4396 
4397 	stats->IpUbPosted = hba->stats.IpUbPosted;
4398 	stats->ElsUbPosted = hba->stats.ElsUbPosted;
4399 	stats->CtUbPosted = hba->stats.CtUbPosted;
4400 
4401 #if (DFC_REV >= 2)
4402 	stats->IocbThrottled   = hba->stats.IocbThrottled;
4403 	stats->ElsAuthReceived = hba->stats.ElsAuthReceived;
4404 #endif
4405 
4406 	return (rval);
4407 
4408 } /* emlxs_dfc_get_drvstats() */
4409 
4410 
4411 extern uint32_t
emlxs_set_hba_mode(emlxs_hba_t * hba,uint32_t mode)4412 emlxs_set_hba_mode(emlxs_hba_t *hba, uint32_t mode)
4413 {
4414 	emlxs_port_t	*port = &PPORT;
4415 	uint32_t	i;
4416 
4417 	mutex_enter(&EMLXS_PORT_LOCK);
4418 
4419 	/* Wait if adapter is in transition */
4420 	i = 0;
4421 	while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) {
4422 		if (i++ > 30) {
4423 			break;
4424 		}
4425 
4426 		mutex_exit(&EMLXS_PORT_LOCK);
4427 		delay(drv_usectohz(1000000));
4428 		mutex_enter(&EMLXS_PORT_LOCK);
4429 	}
4430 
4431 	if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
4432 		switch (mode) {
4433 		case DDI_SHOW:
4434 			break;
4435 
4436 		case DDI_ONDI:
4437 			if (hba->flag & FC_OFFLINE_MODE) {
4438 				mutex_exit(&EMLXS_PORT_LOCK);
4439 				(void) emlxs_online(hba);
4440 				mutex_enter(&EMLXS_PORT_LOCK);
4441 			}
4442 			break;
4443 
4444 
4445 		/* Killed + Restart state */
4446 		case DDI_OFFDI:
4447 			if (hba->flag & FC_ONLINE_MODE) {
4448 				mutex_exit(&EMLXS_PORT_LOCK);
4449 
4450 				(void) emlxs_offline(hba, 0);
4451 
4452 				/* Reset with restart */
4453 				EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
4454 
4455 				mutex_enter(&EMLXS_PORT_LOCK);
4456 			} else if (hba->state < FC_INIT_START) {
4457 				mutex_exit(&EMLXS_PORT_LOCK);
4458 
4459 				/* Reset with restart */
4460 				EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
4461 
4462 				mutex_enter(&EMLXS_PORT_LOCK);
4463 			}
4464 
4465 			break;
4466 
4467 		/* Killed + Reset state */
4468 		case DDI_WARMDI:
4469 			if (hba->flag & FC_ONLINE_MODE) {
4470 				mutex_exit(&EMLXS_PORT_LOCK);
4471 
4472 				(void) emlxs_offline(hba, 0);
4473 
4474 				/* Reset with no restart */
4475 				EMLXS_SLI_HBA_RESET(hba, 0, 0, 0);
4476 
4477 				mutex_enter(&EMLXS_PORT_LOCK);
4478 			} else if (hba->state != FC_WARM_START) {
4479 				mutex_exit(&EMLXS_PORT_LOCK);
4480 
4481 				/* Reset with no restart */
4482 				EMLXS_SLI_HBA_RESET(hba, 0, 0, 0);
4483 
4484 				mutex_enter(&EMLXS_PORT_LOCK);
4485 			}
4486 
4487 			break;
4488 
4489 		/* Killed */
4490 		case DDI_DIAGDI:
4491 			if (hba->flag & FC_ONLINE_MODE) {
4492 				mutex_exit(&EMLXS_PORT_LOCK);
4493 
4494 				(void) emlxs_offline(hba, 0);
4495 
4496 				mutex_enter(&EMLXS_PORT_LOCK);
4497 			} else if (hba->state != FC_KILLED) {
4498 				mutex_exit(&EMLXS_PORT_LOCK);
4499 
4500 				EMLXS_SLI_HBA_KILL(hba);
4501 
4502 				mutex_enter(&EMLXS_PORT_LOCK);
4503 			}
4504 
4505 			break;
4506 
4507 		default:
4508 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4509 			    "set_hba_mode: Invalid mode. mode=%x", mode);
4510 			mutex_exit(&EMLXS_PORT_LOCK);
4511 			return (0);
4512 		}
4513 
4514 		/* Wait if adapter is in transition */
4515 		i = 0;
4516 		while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) {
4517 			if (i++ > 30) {
4518 				break;
4519 			}
4520 
4521 			mutex_exit(&EMLXS_PORT_LOCK);
4522 			delay(drv_usectohz(1000000));
4523 			mutex_enter(&EMLXS_PORT_LOCK);
4524 		}
4525 
4526 		/* Return current state */
4527 		if (hba->flag & FC_ONLINE_MODE) {
4528 			mode = DDI_ONDI;
4529 		} else if (hba->state == FC_KILLED) {
4530 			mode = DDI_DIAGDI;
4531 		} else if (hba->state == FC_WARM_START) {
4532 			mode = DDI_WARMDI;
4533 		} else {
4534 			mode = DDI_OFFDI;
4535 		}
4536 
4537 		mutex_exit(&EMLXS_PORT_LOCK);
4538 
4539 		return (mode);
4540 
4541 	} else { /* SLI4 */
4542 		switch (mode) {
4543 		case DDI_SHOW:
4544 			break;
4545 
4546 		case DDI_ONDI:
4547 			if (hba->flag & FC_OFFLINE_MODE) {
4548 				mutex_exit(&EMLXS_PORT_LOCK);
4549 				(void) emlxs_online(hba);
4550 				mutex_enter(&EMLXS_PORT_LOCK);
4551 			}
4552 			break;
4553 
4554 		case DDI_OFFDI:
4555 			if (hba->flag & FC_ONLINE_MODE) {
4556 				mutex_exit(&EMLXS_PORT_LOCK);
4557 
4558 				(void) emlxs_offline(hba, 0);
4559 
4560 				/* Reset with restart */
4561 				EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
4562 
4563 				mutex_enter(&EMLXS_PORT_LOCK);
4564 			} else if (hba->state < FC_INIT_START) {
4565 				mutex_exit(&EMLXS_PORT_LOCK);
4566 
4567 				/* Reset with restart */
4568 				EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
4569 
4570 				mutex_enter(&EMLXS_PORT_LOCK);
4571 			}
4572 			break;
4573 
4574 		case DDI_DIAGDI:
4575 			if (!(hba->model_info.chip & EMLXS_LANCER_CHIPS)) {
4576 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4577 				    "set_hba_mode: Invalid mode. mode=%x",
4578 				    mode);
4579 				mutex_exit(&EMLXS_PORT_LOCK);
4580 				return (0);
4581 			}
4582 
4583 			mutex_exit(&EMLXS_PORT_LOCK);
4584 			(void) emlxs_reset(port,
4585 			    EMLXS_DFC_RESET_ALL_FORCE_DUMP);
4586 
4587 			return (mode);
4588 
4589 		case DDI_WARMDI:
4590 		default:
4591 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4592 			    "set_hba_mode: Invalid mode. mode=%x", mode);
4593 			mutex_exit(&EMLXS_PORT_LOCK);
4594 			return (0);
4595 		}
4596 
4597 		/* Wait if adapter is in transition */
4598 		i = 0;
4599 		while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) {
4600 			if (i++ > 30) {
4601 				break;
4602 			}
4603 
4604 			mutex_exit(&EMLXS_PORT_LOCK);
4605 			delay(drv_usectohz(1000000));
4606 			mutex_enter(&EMLXS_PORT_LOCK);
4607 		}
4608 
4609 		/* Return current state */
4610 		if (hba->flag & FC_ONLINE_MODE) {
4611 			mode = DDI_ONDI;
4612 		} else {
4613 			mode = DDI_OFFDI;
4614 		}
4615 
4616 		mutex_exit(&EMLXS_PORT_LOCK);
4617 
4618 		return (mode);
4619 	}
4620 
4621 } /* emlxs_set_hba_mode() */
4622 
4623 
4624 /*ARGSUSED*/
4625 static int32_t
emlxs_dfc_set_diag(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)4626 emlxs_dfc_set_diag(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4627 {
4628 	emlxs_port_t	*port = &PPORT;
4629 	int32_t		rval = 0;
4630 	int32_t		flag;
4631 
4632 	if (!dfc->buf1 || !dfc->buf1_size) {
4633 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4634 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4635 
4636 		return (DFC_ARG_NULL);
4637 	}
4638 
4639 	if (dfc->buf1_size < sizeof (uint32_t)) {
4640 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4641 		    "%s: Buffer1 too small. (size=%d)",
4642 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
4643 
4644 		return (DFC_ARG_TOOSMALL);
4645 	}
4646 
4647 	flag = emlxs_set_hba_mode(hba, dfc->flag);
4648 	bcopy((void *)&flag, (void *)dfc->buf1, sizeof (uint32_t));
4649 
4650 	return (rval);
4651 
4652 } /* emlxs_dfc_set_diag() */
4653 
4654 
4655 
4656 /*ARGSUSED*/
4657 static int32_t
emlxs_dfc_send_mbox(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)4658 emlxs_dfc_send_mbox(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4659 {
4660 	emlxs_port_t	*port  = &PPORT;
4661 	MAILBOX		*mb    = NULL;
4662 	MAILBOXQ	*mbq   = NULL;
4663 	uint32_t	size  = 0;
4664 	MATCHMAP	*rx_mp = NULL;
4665 	MATCHMAP	*tx_mp = NULL;
4666 	uintptr_t	lptr;
4667 	int32_t		rval  = 0;
4668 	int32_t		mbxstatus = 0;
4669 	NODELIST	*ndlp;
4670 	uint32_t	did;
4671 	uint32_t	extsize = 0;
4672 	uint8_t		*extbuf  = NULL;
4673 
4674 	if (hba->sli_mode > EMLXS_HBA_SLI3_MODE) {
4675 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4676 		    "%s: SLI Mode %d not supported.", emlxs_dfc_xlate(dfc->cmd),
4677 		    hba->sli_mode);
4678 
4679 		return (DFC_NOT_SUPPORTED);
4680 	}
4681 
4682 	if (!dfc->buf1 || !dfc->buf1_size) {
4683 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4684 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4685 
4686 		return (DFC_ARG_NULL);
4687 	}
4688 
4689 	if (!dfc->buf2 || !dfc->buf2_size) {
4690 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4691 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
4692 
4693 		return (DFC_ARG_NULL);
4694 	}
4695 
4696 	if (dfc->buf1_size > MAILBOX_CMD_BSIZE) {
4697 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4698 		    "%s: Buffer1 too large. (size=%d)",
4699 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
4700 
4701 		return (DFC_ARG_TOOBIG);
4702 	}
4703 #ifdef MBOX_EXT_SUPPORT
4704 	if (dfc->buf3_size || dfc->buf4_size) {
4705 		if (dfc->buf3_size && !dfc->buf3) {
4706 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4707 			    "%s: Null buffer3 found.",
4708 			    emlxs_dfc_xlate(dfc->cmd));
4709 
4710 			return (DFC_ARG_NULL);
4711 		}
4712 
4713 		if (dfc->buf3_size > MBOX_EXTENSION_SIZE) {
4714 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4715 			    "%s: buffer3 too large. (size=%d)",
4716 			    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
4717 
4718 			return (DFC_ARG_TOOBIG);
4719 		}
4720 
4721 		if (dfc->buf4_size && !dfc->buf4) {
4722 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4723 			    "%s: Null buffer4 found.",
4724 			    emlxs_dfc_xlate(dfc->cmd));
4725 
4726 			return (DFC_ARG_NULL);
4727 		}
4728 
4729 		if (dfc->buf4_size > MBOX_EXTENSION_SIZE) {
4730 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4731 			    "%s: buffer4 too large. (size=%d)",
4732 			    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
4733 
4734 			return (DFC_ARG_TOOBIG);
4735 		}
4736 
4737 		extsize = (dfc->buf3_size > dfc->buf4_size) ?
4738 		    dfc->buf3_size : dfc->buf4_size;
4739 		extbuf = (uint8_t *)kmem_zalloc(extsize, KM_SLEEP);
4740 
4741 		if (dfc->buf3_size) {
4742 			bcopy((void *)dfc->buf3, (void *)extbuf,
4743 			    dfc->buf3_size);
4744 		}
4745 	}
4746 #endif /* MBOX_EXT_SUPPORT */
4747 
4748 	mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
4749 	mb = (MAILBOX *) mbq;
4750 	bcopy((void *)dfc->buf1, (void *)mb, dfc->buf1_size);
4751 
4752 #ifdef _LP64
4753 	if ((mb->mbxCommand == MBX_READ_SPARM) ||
4754 	    (mb->mbxCommand == MBX_READ_RPI) ||
4755 	    (mb->mbxCommand == MBX_REG_LOGIN) ||
4756 	    (mb->mbxCommand == MBX_READ_LA) ||
4757 	    (mb->mbxCommand == MBX_RUN_BIU_DIAG)) {
4758 
4759 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4760 		    "%s: Invalid mailbox command. Must use 64bit version. "
4761 		    "cmd=%x", emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4762 
4763 		/* Must use 64 bit versions of these mbox cmds */
4764 		rval = DFC_ARG_INVALID;
4765 		goto done;
4766 	}
4767 #endif
4768 
4769 	lptr = 0;
4770 	size = 0;
4771 	switch (mb->mbxCommand) {
4772 	/* Offline only */
4773 	case MBX_CONFIG_LINK:	/* 0x07 */
4774 	case MBX_PART_SLIM:	    /* 0x08 */
4775 	case MBX_CONFIG_RING:	/* 0x09 */
4776 	case MBX_DUMP_CONTEXT:	/* 0x18 */
4777 	case MBX_RUN_DIAGS:	    /* 0x19 */
4778 	case MBX_RESTART:	    /* 0x1A */
4779 	case MBX_SET_MASK:	    /* 0x20 */
4780 	case MBX_FLASH_WR_ULA:	/* 0x98 */
4781 		if (!(hba->flag & FC_OFFLINE_MODE)) {
4782 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4783 			    "%s: Adapter not offline. cmd=%x",
4784 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4785 
4786 			rval = DFC_ONLINE_ERROR;
4787 			goto done;
4788 		}
4789 		break;
4790 
4791 	/* Online / Offline */
4792 	case MBX_UNREG_LOGIN:	/* 0x14 */
4793 		ndlp = emlxs_node_find_rpi(port, mb->un.varUnregLogin.rpi);
4794 
4795 		if (ndlp) {
4796 			did = ndlp->nlp_DID;
4797 
4798 			/* remove it */
4799 			emlxs_node_rm(port, ndlp);
4800 
4801 			/*
4802 			 * If we just unregistered the host node then
4803 			 * clear the host DID
4804 			 */
4805 			if (did == port->did) {
4806 				port->did = 0;
4807 			}
4808 		} else {
4809 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4810 			    "%s: Node not found. cmd=%x rpi=%d",
4811 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand,
4812 			    mb->un.varUnregLogin.rpi);
4813 
4814 			/* Node does not exist */
4815 			rval = DFC_ARG_INVALID;
4816 			goto done;
4817 		}
4818 
4819 		/* Send it */
4820 		break;
4821 
4822 	case MBX_UNREG_D_ID:	/* 0x23 */
4823 
4824 		did = mb->un.varRegLogin.did;
4825 
4826 		if (did == 0) {
4827 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4828 			    "%s: Node not found. cmd=%x did=%x",
4829 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
4830 
4831 			rval = DFC_ARG_INVALID;
4832 			goto done;
4833 		}
4834 
4835 		if (did == 0xffffffff) {
4836 			emlxs_node_destroy_all(port);
4837 			break;
4838 		}
4839 
4840 		/* Check for base node */
4841 		if (did == BCAST_DID) {
4842 			/* just flush base node */
4843 			(void) emlxs_tx_node_flush(port, &port->node_base,
4844 			    0, 0, 0);
4845 			(void) emlxs_chipq_node_flush(port, 0, &port->node_base,
4846 			    0);
4847 
4848 			/* Return now */
4849 			rval = 0;
4850 			goto done;
4851 		}
4852 
4853 		/* Make sure the node does already exist */
4854 		ndlp = emlxs_node_find_did(port, did, 1);
4855 
4856 		if (ndlp) {
4857 			/* remove it */
4858 			emlxs_node_rm(port, ndlp);
4859 
4860 			/*
4861 			 * If we just unregistered the host node then
4862 			 * clear the host DID
4863 			 */
4864 			if (did == port->did) {
4865 				port->did = 0;
4866 			}
4867 		} else {
4868 
4869 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4870 			    "%s: Node not found. cmd=%x did=%x",
4871 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
4872 
4873 			/* Node does not exist */
4874 			rval = DFC_ARG_INVALID;
4875 			goto done;
4876 		}
4877 
4878 		/* Send it */
4879 		break;
4880 
4881 	/* Online / Offline - with DMA */
4882 	case MBX_READ_EVENT_LOG:	/* 0x38 */
4883 		lptr =
4884 		    (uintptr_t)PADDR(mb->un.varRdEvtLog.un.sp64.addrHigh,
4885 		    mb->un.varRdEvtLog.un.sp64.addrLow);
4886 		size = (int)mb->un.varRdEvtLog.un.sp64.tus.f.bdeSize;
4887 
4888 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4889 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4890 			    "%s: Invalid BDE. cmd=%x",
4891 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4892 
4893 			rval = DFC_ARG_INVALID;
4894 			goto done;
4895 		}
4896 
4897 		/* Allocate receive buffer */
4898 		if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4899 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4900 			    "%s: Unable to allocate receive buffer. cmd=%x",
4901 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4902 
4903 			rval = DFC_DRVRES_ERROR;
4904 			goto done;
4905 		}
4906 
4907 		mb->un.varRdEvtLog.un.sp64.addrHigh = PADDR_HI(rx_mp->phys);
4908 		mb->un.varRdEvtLog.un.sp64.addrLow = PADDR_LO(rx_mp->phys);
4909 		mb->un.varRdEvtLog.un.sp64.tus.f.bdeFlags = 0;
4910 
4911 		break;
4912 
4913 	case MBX_READ_SPARM:	/* 0x0D */
4914 	case MBX_READ_SPARM64:	/* 0x8D */
4915 		lptr =
4916 		    (uintptr_t)PADDR(mb->un.varRdSparm.un.sp64.addrHigh,
4917 		    mb->un.varRdSparm.un.sp64.addrLow);
4918 		size = (int)mb->un.varRdSparm.un.sp64.tus.f.bdeSize;
4919 
4920 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4921 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4922 			    "%s: Invalid BDE. cmd=%x",
4923 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4924 
4925 			rval = DFC_ARG_INVALID;
4926 			goto done;
4927 		}
4928 
4929 		/* Allocate receive buffer */
4930 		if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4931 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4932 			    "%s: Unable to allocate receive buffer. cmd=%x",
4933 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4934 
4935 			rval = DFC_DRVRES_ERROR;
4936 			goto done;
4937 		}
4938 
4939 		mb->un.varRdSparm.un.sp64.addrHigh = PADDR_HI(rx_mp->phys);
4940 		mb->un.varRdSparm.un.sp64.addrLow = PADDR_LO(rx_mp->phys);
4941 		mb->un.varRdSparm.un.sp64.tus.f.bdeFlags = 0;
4942 
4943 		break;
4944 
4945 	case MBX_READ_RPI:	/* 0x0F */
4946 	case MBX_READ_RPI64:	/* 0x8F */
4947 		lptr =
4948 		    (uintptr_t)PADDR(mb->un.varRdRPI.un.sp64.addrHigh,
4949 		    mb->un.varRdRPI.un.sp64.addrLow);
4950 		size = (int)mb->un.varRdRPI.un.sp64.tus.f.bdeSize;
4951 
4952 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4953 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4954 			    "%s: Invalid BDE. cmd=%x",
4955 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4956 
4957 			rval = DFC_ARG_INVALID;
4958 			goto done;
4959 		}
4960 
4961 		/* Allocate receive buffer */
4962 		if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4963 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4964 			    "%s: Unable to allocate receive buffer. cmd=%x",
4965 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4966 
4967 			rval = DFC_DRVRES_ERROR;
4968 			goto done;
4969 		}
4970 
4971 		mb->un.varRdRPI.un.sp64.addrHigh = PADDR_HI(rx_mp->phys);
4972 		mb->un.varRdRPI.un.sp64.addrLow = PADDR_LO(rx_mp->phys);
4973 		mb->un.varRdRPI.un.sp64.tus.f.bdeFlags = 0;
4974 
4975 		break;
4976 
4977 	case MBX_RUN_BIU_DIAG:	 /* 0x04 */
4978 	case MBX_RUN_BIU_DIAG64: /* 0x84 */
4979 		lptr =
4980 		    (uintptr_t)PADDR(mb->un.varBIUdiag.un.s2.xmit_bde64.
4981 		    addrHigh, mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow);
4982 		size = (int)mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize;
4983 
4984 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4985 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4986 			    "%s: Invalid xmit BDE. cmd=%x",
4987 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4988 
4989 			rval = DFC_ARG_INVALID;
4990 			goto done;
4991 		}
4992 
4993 		/* Allocate xmit buffer */
4994 		if ((tx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4995 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4996 			    "%s: Unable to allocate xmit buffer. cmd=%x",
4997 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4998 
4999 			rval = DFC_DRVRES_ERROR;
5000 			goto done;
5001 		}
5002 
5003 		/* Initialize the xmit buffer */
5004 		if (ddi_copyin((void *)lptr, (void *)tx_mp->virt, size,
5005 		    mode) != 0) {
5006 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5007 			    "%s: ddi_copyin failed. cmd=%x",
5008 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5009 
5010 			rval = DFC_COPYIN_ERROR;
5011 			goto done;
5012 		}
5013 		EMLXS_MPDATA_SYNC(tx_mp->dma_handle, 0, size,
5014 		    DDI_DMA_SYNC_FORDEV);
5015 
5016 		mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh =
5017 		    PADDR_HI(tx_mp->phys);
5018 		mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow =
5019 		    PADDR_LO(tx_mp->phys);
5020 		mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeFlags = 0;
5021 
5022 		/* Initialize the receive buffer */
5023 		lptr =
5024 		    (uintptr_t)PADDR(mb->un.varBIUdiag.un.s2.rcv_bde64.
5025 		    addrHigh, mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow);
5026 		size = (int)mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize;
5027 
5028 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
5029 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5030 			    "%s: Invalid rcv BDE. cmd=%x",
5031 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5032 
5033 			rval = DFC_ARG_INVALID;
5034 			goto done;
5035 		}
5036 
5037 		/* Allocate receive buffer */
5038 		if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
5039 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5040 			    "%s: Unable to allocate receive buffer. cmd=%x",
5041 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5042 
5043 			rval = DFC_DRVRES_ERROR;
5044 			goto done;
5045 		}
5046 
5047 		mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh =
5048 		    PADDR_HI(rx_mp->phys);
5049 		mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow =
5050 		    PADDR_LO(rx_mp->phys);
5051 		mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeFlags = 0;
5052 
5053 		break;
5054 
5055 	case MBX_REG_LOGIN:	/* 0x13 */
5056 	case MBX_REG_LOGIN64:	/* 0x93 */
5057 
5058 		did = mb->un.varRegLogin.did;
5059 
5060 		/* Check for invalid node ids to register */
5061 		if (did == 0 || (did & 0xff000000)) {
5062 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5063 			    "%s: Invalid node id. cmd=%x did=%x",
5064 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
5065 
5066 			rval = DFC_ARG_INVALID;
5067 			goto done;
5068 		}
5069 
5070 		/* Check if the node limit has been reached */
5071 		if (port->node_count >= hba->max_nodes) {
5072 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5073 			    "%s: Too many nodes. cmd=%x",
5074 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5075 
5076 			rval = DFC_HBARES_ERROR;
5077 			goto done;
5078 		}
5079 
5080 		lptr =
5081 		    (uintptr_t)PADDR(mb->un.varRegLogin.un.sp64.addrHigh,
5082 		    mb->un.varRegLogin.un.sp64.addrLow);
5083 		size = (int)mb->un.varRegLogin.un.sp64.tus.f.bdeSize;
5084 
5085 		if (!lptr || (size > MEM_BUF_SIZE)) {
5086 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5087 			    "%s: Invalid BDE. cmd=%x",
5088 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5089 
5090 			rval = DFC_ARG_INVALID;
5091 			goto done;
5092 		}
5093 
5094 		/* Allocate xmit buffer */
5095 		if ((tx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
5096 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5097 			    "%s: Unable to allocate xmit buffer. cmd=%x",
5098 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5099 
5100 			rval = DFC_DRVRES_ERROR;
5101 			goto done;
5102 		}
5103 
5104 		/* Initialize the xmit buffer */
5105 		if (ddi_copyin((void *)lptr, (void *)tx_mp->virt, size,
5106 		    mode) != 0) {
5107 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5108 			    "%s: Unable to allocate xmit buffer. cmd=%x",
5109 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5110 
5111 			rval = DFC_COPYIN_ERROR;
5112 			goto done;
5113 		}
5114 		EMLXS_MPDATA_SYNC(tx_mp->dma_handle, 0, size,
5115 		    DDI_DMA_SYNC_FORDEV);
5116 
5117 		mb->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(tx_mp->phys);
5118 		mb->un.varRegLogin.un.sp64.addrLow = PADDR_LO(tx_mp->phys);
5119 		mb->un.varRegLogin.un.sp64.tus.f.bdeFlags = 0;
5120 
5121 		break;
5122 
5123 	case MBX_READ_LA:	/* 0x15 */
5124 	case MBX_READ_LA64:	/* 0x95 */
5125 		lptr =
5126 		    (uintptr_t)PADDR(mb->un.varReadLA.un.lilpBde64.
5127 		    addrHigh, mb->un.varReadLA.un.lilpBde64.addrLow);
5128 		size = (int)mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize;
5129 
5130 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
5131 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5132 			    "%s: Invalid BDE. cmd=%x",
5133 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5134 
5135 			rval = DFC_ARG_INVALID;
5136 			goto done;
5137 		}
5138 
5139 		/* Allocate receive buffer */
5140 		if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
5141 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5142 			    "%s: Unable to allocate receive buffer. cmd=%x",
5143 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5144 
5145 			rval = DFC_DRVRES_ERROR;
5146 			goto done;
5147 		}
5148 
5149 		mb->un.varReadLA.un.lilpBde64.addrHigh =
5150 		    PADDR_HI(rx_mp->phys);
5151 		mb->un.varReadLA.un.lilpBde64.addrLow =
5152 		    PADDR_LO(rx_mp->phys);
5153 		mb->un.varReadLA.un.lilpBde64.tus.f.bdeFlags = 0;
5154 
5155 		break;
5156 
5157 
5158 		/* Do not allow these commands */
5159 	case MBX_CONFIG_PORT:	/* 0x88 */
5160 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5161 		    "%s: Command not allowed. cmd=%x",
5162 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5163 
5164 		rval = DFC_ARG_INVALID;
5165 		goto done;
5166 
5167 
5168 	/* Online / Offline */
5169 	default:
5170 		break;
5171 
5172 	}	/* switch() */
5173 
5174 	mb->mbxOwner = OWN_HOST;
5175 
5176 	/* Set or don't set the PASSTHRU bit. */
5177 	/* Setting will prevent the driver from processing it as its own */
5178 	switch (mb->mbxCommand) {
5179 	case MBX_REG_LOGIN:	/* 0x13 */
5180 	case MBX_REG_LOGIN64:	/* 0x93 */
5181 		break;
5182 
5183 	default:
5184 		mbq->flag |= MBQ_PASSTHRU;
5185 	}
5186 
5187 #ifdef MBOX_EXT_SUPPORT
5188 	if (extbuf) {
5189 		mbq->extbuf  = extbuf;
5190 		mbq->extsize = extsize;
5191 	}
5192 #endif /* MBOX_EXT_SUPPORT */
5193 
5194 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5195 	    "%s: %s sent.  (%x %x %x %x)", emlxs_dfc_xlate(dfc->cmd),
5196 	    emlxs_mb_cmd_xlate(mb->mbxCommand), mb->un.varWords[0],
5197 	    mb->un.varWords[1], mb->un.varWords[2], mb->un.varWords[3]);
5198 
5199 	/* issue the mbox cmd to the sli */
5200 	mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
5201 
5202 	if (mbxstatus) {
5203 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5204 		    "%s: %s failed. mbxstatus=0x%x",
5205 		    emlxs_dfc_xlate(dfc->cmd),
5206 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
5207 
5208 	}
5209 
5210 	bcopy((void *)mb, (void *)dfc->buf2, dfc->buf2_size);
5211 
5212 	if (rx_mp) {
5213 		EMLXS_MPDATA_SYNC(rx_mp->dma_handle, 0, size,
5214 		    DDI_DMA_SYNC_FORKERNEL);
5215 
5216 		if (ddi_copyout((void *)rx_mp->virt, (void *)lptr, size,
5217 		    mode) != 0) {
5218 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5219 			    "%s: ddi_copyout failed for receive buffer. cmd=%x",
5220 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5221 
5222 			rval = DFC_COPYOUT_ERROR;
5223 			goto done;
5224 		}
5225 	}
5226 #ifdef MBOX_EXT_SUPPORT
5227 	/*  Any data needs to copy to mbox extension area */
5228 	if (dfc->buf4_size) {
5229 		bcopy((void *)extbuf, (void *)dfc->buf4, dfc->buf4_size);
5230 	}
5231 #endif /* MBOX_EXT_SUPPORT */
5232 
5233 	rval = 0;
5234 
5235 done:
5236 
5237 	/* Free allocated mbox memory */
5238 	if (extbuf) {
5239 		kmem_free(extbuf, extsize);
5240 	}
5241 
5242 	/* Free allocated mbox memory */
5243 	if (mbq) {
5244 		kmem_free(mbq, sizeof (MAILBOXQ));
5245 	}
5246 
5247 	/* Free allocated mbuf memory */
5248 	if (rx_mp) {
5249 #ifdef FMA_SUPPORT
5250 		if (!rval) {
5251 			if (emlxs_fm_check_dma_handle(hba, rx_mp->dma_handle)
5252 			    != DDI_FM_OK) {
5253 				EMLXS_MSGF(EMLXS_CONTEXT,
5254 				    &emlxs_invalid_dma_handle_msg,
5255 				    "dfc_send_mbox: hdl=%p",
5256 				    rx_mp->dma_handle);
5257 				rval = DFC_IO_ERROR;
5258 			}
5259 		}
5260 #endif  /* FMA_SUPPORT */
5261 		emlxs_mem_buf_free(hba, rx_mp);
5262 	}
5263 
5264 	if (tx_mp) {
5265 #ifdef FMA_SUPPORT
5266 		if (!rval) {
5267 			if (emlxs_fm_check_dma_handle(hba, tx_mp->dma_handle)
5268 			    != DDI_FM_OK) {
5269 				EMLXS_MSGF(EMLXS_CONTEXT,
5270 				    &emlxs_invalid_dma_handle_msg,
5271 				    "dfc_send_mbox: hdl=%p",
5272 				    tx_mp->dma_handle);
5273 				rval = DFC_IO_ERROR;
5274 			}
5275 		}
5276 #endif  /* FMA_SUPPORT */
5277 		emlxs_mem_buf_free(hba, tx_mp);
5278 	}
5279 
5280 	return (rval);
5281 
5282 } /* emlxs_dfc_send_mbox() */
5283 
5284 
5285 /*ARGSUSED*/
5286 static int32_t
emlxs_dfc_read_pci(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)5287 emlxs_dfc_read_pci(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5288 {
5289 	emlxs_port_t	*port = &PPORT;
5290 	uint32_t	offset;
5291 	uint32_t	cnt;
5292 	uint32_t	outsz;
5293 	uint32_t	i;
5294 	uint32_t	*bptr;
5295 	uint32_t	value;
5296 	uint32_t	max = 4096;
5297 
5298 	offset = dfc->data1;
5299 	cnt = dfc->data2;
5300 	outsz = dfc->buf1_size;
5301 
5302 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5303 	    "%s: offset=%x count=%d", emlxs_dfc_xlate(dfc->cmd), offset, cnt);
5304 
5305 	if (!dfc->buf1_size || !dfc->buf1) {
5306 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5307 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5308 
5309 		return (DFC_ARG_NULL);
5310 	}
5311 
5312 	if (offset & 0x3) {
5313 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5314 		    "%s: Offset misaligned. (offset=%d)",
5315 		    emlxs_dfc_xlate(dfc->cmd), offset);
5316 
5317 		return (DFC_ARG_MISALIGNED);
5318 	}
5319 
5320 	if (cnt & 0x3) {
5321 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5322 		    "%s: Count misaligned. (count=%d)",
5323 		    emlxs_dfc_xlate(dfc->cmd), cnt);
5324 
5325 		return (DFC_ARG_MISALIGNED);
5326 	}
5327 
5328 	if (outsz & 0x3) {
5329 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5330 		    "%s: Output size misaligned. (size=%d)",
5331 		    emlxs_dfc_xlate(dfc->cmd), outsz);
5332 
5333 		return (DFC_ARG_MISALIGNED);
5334 	}
5335 
5336 	/* Get max PCI config range */
5337 	if (hba->model_info.chip <= EMLXS_HELIOS_CHIP) {
5338 		max = 256;
5339 	} else {
5340 		max = 4096;
5341 	}
5342 
5343 	if ((cnt + offset) > max) {
5344 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5345 		    "%s: Offset+Count too large. (offset=%d count=%d max=%d)",
5346 		    emlxs_dfc_xlate(dfc->cmd), offset, cnt, max);
5347 
5348 		return (DFC_ARG_TOOBIG);
5349 	}
5350 
5351 	if (outsz > max) {
5352 		outsz = max;
5353 	}
5354 
5355 	if (cnt > outsz) {
5356 		cnt = outsz;
5357 	}
5358 
5359 	bptr = (uint32_t *)dfc->buf1;
5360 	for (i = offset; i < (offset + cnt); i += 4) {
5361 		value =
5362 		    ddi_get32(hba->pci_acc_handle,
5363 		    (uint32_t *)(hba->pci_addr + i));
5364 		*bptr++ = BE_SWAP32(value);
5365 	}
5366 
5367 #ifdef FMA_SUPPORT
5368 	/* Access handle validation */
5369 	if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
5370 	    != DDI_FM_OK) {
5371 		EMLXS_MSGF(EMLXS_CONTEXT,
5372 		    &emlxs_invalid_access_handle_msg, NULL);
5373 		return (DFC_DRV_ERROR);
5374 	}
5375 #endif  /* FMA_SUPPORT */
5376 
5377 	return (0);
5378 
5379 } /* emlxs_dfc_read_pci() */
5380 
5381 
5382 /*ARGSUSED*/
5383 static int32_t
emlxs_dfc_write_pci(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)5384 emlxs_dfc_write_pci(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5385 {
5386 	emlxs_port_t	*port = &PPORT;
5387 	uint32_t	offset;
5388 	uint32_t	cnt;
5389 	uint32_t	value;
5390 	uint32_t	i;
5391 	uint32_t	max;
5392 	uint32_t	*bptr;
5393 	uint16_t	word0;
5394 	uint16_t	word1;
5395 
5396 	offset = dfc->data1;
5397 	cnt = dfc->data2;
5398 
5399 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5400 	    "%s: offset=%x count=%d", emlxs_dfc_xlate(dfc->cmd), offset, cnt);
5401 
5402 	if (!dfc->buf1 || !dfc->buf1_size) {
5403 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5404 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5405 
5406 		return (DFC_ARG_NULL);
5407 	}
5408 
5409 	if (offset & 0x3) {
5410 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5411 		    "%s: Offset misaligned. (offset=%d)",
5412 		    emlxs_dfc_xlate(dfc->cmd), offset);
5413 
5414 		return (DFC_ARG_MISALIGNED);
5415 	}
5416 
5417 	if (cnt > dfc->buf1_size) {
5418 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5419 		    "%s: Count too large. (count=%d)",
5420 		    emlxs_dfc_xlate(dfc->cmd), cnt);
5421 
5422 		return (DFC_ARG_TOOBIG);
5423 	}
5424 
5425 	if (cnt & 0x3) {
5426 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5427 		    "%s: Count misaligned. (count=%d)",
5428 		    emlxs_dfc_xlate(dfc->cmd), cnt);
5429 
5430 		return (DFC_ARG_MISALIGNED);
5431 	}
5432 
5433 	/* Get max PCI config range */
5434 	if (hba->model_info.chip <= EMLXS_HELIOS_CHIP) {
5435 		max = 256;
5436 	} else {
5437 		max = 4096;
5438 	}
5439 
5440 	if ((cnt + offset) > max) {
5441 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5442 		    "%s: Count+Offset too large. (offset=%d count=%d max=%d)",
5443 		    emlxs_dfc_xlate(dfc->cmd), offset, cnt, max);
5444 
5445 		return (DFC_ARG_TOOBIG);
5446 	}
5447 
5448 	bptr = (uint32_t *)dfc->buf1;
5449 	for (i = offset; i < (offset + cnt); i += 4) {
5450 		value = *bptr++;
5451 		value = BE_SWAP32(value);
5452 
5453 		word0 = value & 0xFFFF;
5454 		word1 = value >> 16;
5455 
5456 		/*
5457 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
5458 		 * "%s: Writing. offset=%x cnt=%d value=%08x %04x %04x",
5459 		 * emlxs_dfc_xlate(dfc->cmd), i, value, word0, word1);
5460 		 */
5461 
5462 		/* word0 = PCIMEM_SHORT(word0); */
5463 		ddi_put16(hba->pci_acc_handle,
5464 		    (uint16_t *)(hba->pci_addr + i), (uint16_t)word0);
5465 
5466 		/* word1 = PCIMEM_SHORT(word1); */
5467 		ddi_put16(hba->pci_acc_handle,
5468 		    (uint16_t *)(hba->pci_addr + i + 2), (uint16_t)word1);
5469 	}
5470 
5471 #ifdef FMA_SUPPORT
5472 	/* Access handle validation */
5473 	if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
5474 	    != DDI_FM_OK) {
5475 		EMLXS_MSGF(EMLXS_CONTEXT,
5476 		    &emlxs_invalid_access_handle_msg, NULL);
5477 		return (DFC_DRV_ERROR);
5478 	}
5479 #endif  /* FMA_SUPPORT */
5480 
5481 	return (0);
5482 
5483 } /* emlxs_dfc_write_pci() */
5484 
5485 
5486 /*ARGSUSED*/
5487 static int32_t
emlxs_dfc_get_cfg(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)5488 emlxs_dfc_get_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5489 {
5490 	emlxs_port_t	*port = &PPORT;
5491 	dfc_cfgparam_t	*cfgparam;
5492 	uint32_t	count;
5493 	uint32_t	i;
5494 	emlxs_config_t	*cfg;
5495 
5496 	if (!dfc->buf1 || !dfc->buf1_size) {
5497 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5498 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5499 
5500 		return (DFC_ARG_NULL);
5501 	}
5502 
5503 	count = dfc->buf1_size / sizeof (dfc_cfgparam_t);
5504 
5505 	if (count > MAX_CFG_PARAM) {
5506 		count = MAX_CFG_PARAM;
5507 	}
5508 
5509 	cfgparam = (dfc_cfgparam_t *)dfc->buf1;
5510 	bzero(cfgparam, sizeof (dfc_cfgparam_t));
5511 
5512 	cfg = &CFG;
5513 	for (i = 0; i < count; i++) {
5514 		(void) strncpy(cfgparam[i].a_string, cfg[i].string,
5515 		    (sizeof (cfgparam[i].a_string)-1));
5516 		cfgparam[i].a_low = cfg[i].low;
5517 		cfgparam[i].a_hi = cfg[i].hi;
5518 		cfgparam[i].a_default = cfg[i].def;
5519 		cfgparam[i].a_current = cfg[i].current;
5520 
5521 		if (!(cfg[i].flags & PARM_HIDDEN)) {
5522 			cfgparam[i].a_flag |= CFG_EXPORT;
5523 		}
5524 		cfgparam[i].a_flag |= CFG_COMMON;
5525 
5526 		/* Adjust a_flag based on the hba model */
5527 		switch (i) {
5528 			case CFG_NETWORK_ON:
5529 			case CFG_TOPOLOGY:
5530 			case CFG_LINK_SPEED:
5531 			case CFG_CR_DELAY:
5532 			case CFG_CR_COUNT:
5533 			if (! ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) &&
5534 			    SLI4_FCOE_MODE)) {
5535 				cfgparam[i].a_flag |= CFG_APPLICABLE;
5536 			}
5537 			break;
5538 
5539 			case CFG_NUM_WQ:
5540 			if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) &&
5541 			    SLI4_FCOE_MODE) {
5542 				cfgparam[i].a_flag |= CFG_APPLICABLE;
5543 			}
5544 			break;
5545 
5546 			case CFG_PERSIST_LINKDOWN:
5547 			cfgparam[i].a_flag &= ~CFG_EXPORT;
5548 			break;
5549 
5550 			default:
5551 			cfgparam[i].a_flag |= CFG_APPLICABLE;
5552 			break;
5553 		}
5554 
5555 		if ((cfg[i].flags & PARM_DYNAMIC)) {
5556 			if ((cfg[i].flags & PARM_DYNAMIC_RESET) ==
5557 			    PARM_DYNAMIC_RESET) {
5558 				cfgparam[i].a_changestate = CFG_RESTART;
5559 			} else if ((cfg[i].flags & PARM_DYNAMIC_LINK) ==
5560 			    PARM_DYNAMIC_LINK) {
5561 				cfgparam[i].a_changestate = CFG_LINKRESET;
5562 			} else {
5563 				cfgparam[i].a_changestate = CFG_DYMANIC;
5564 			}
5565 		} else {
5566 			cfgparam[i].a_changestate = CFG_REBOOT;
5567 		}
5568 
5569 		(void) strncpy(cfgparam[i].a_help, cfg[i].help,
5570 		    (sizeof (cfgparam[i].a_help)-1));
5571 	}
5572 
5573 	return (0);
5574 
5575 } /* emlxs_dfc_get_cfg() */
5576 
5577 
5578 /* ARGSUSED */
5579 static int32_t
emlxs_dfc_set_cfg(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)5580 emlxs_dfc_set_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5581 {
5582 	emlxs_port_t	*port = &PPORT;
5583 	uint32_t	index;
5584 	uint32_t	new_value;
5585 	uint32_t	rc;
5586 
5587 	index = dfc->data1;
5588 	new_value = dfc->data2;
5589 
5590 	rc = emlxs_set_parm(hba, index, new_value);
5591 
5592 	if (rc) {
5593 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5594 		    "%s: Unable to set parameter. code=%d",
5595 		    emlxs_dfc_xlate(dfc->cmd), rc);
5596 
5597 		switch (rc) {
5598 		case 2:
5599 			return (DFC_NPIV_ACTIVE);
5600 
5601 		default:
5602 			return (DFC_ARG_INVALID);
5603 		}
5604 	}
5605 
5606 	return (0);
5607 
5608 } /* emlxs_dfc_set_cfg() */
5609 
5610 
5611 /*ARGSUSED*/
5612 static int32_t
emlxs_dfc_send_ct(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)5613 emlxs_dfc_send_ct(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5614 {
5615 	emlxs_port_t	*port = &PPORT;
5616 	uint8_t		*rsp_buf;
5617 	uint8_t		*cmd_buf;
5618 	uint32_t	did;
5619 	uint32_t	rsp_size;
5620 	uint32_t	cmd_size;
5621 	uint32_t	timeout;
5622 	fc_packet_t	*pkt = NULL;
5623 	uint32_t	rval = 0;
5624 	dfc_destid_t	*destid;
5625 	NODELIST	*nlp;
5626 	char		buffer[128];
5627 
5628 	cmd_buf = dfc->buf1;
5629 	cmd_size = dfc->buf1_size;
5630 	rsp_buf = dfc->buf2;
5631 	rsp_size = dfc->buf2_size;
5632 	timeout = dfc->data1;
5633 
5634 	if (timeout < (2 * hba->fc_ratov)) {
5635 		timeout = 2 * hba->fc_ratov;
5636 	}
5637 
5638 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5639 	    "%s: csize=%d rsize=%d", emlxs_dfc_xlate(dfc->cmd), cmd_size,
5640 	    rsp_size);
5641 
5642 
5643 	if (!cmd_size || !cmd_buf) {
5644 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5645 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5646 
5647 		rval = DFC_ARG_NULL;
5648 		goto done;
5649 	}
5650 
5651 	if (!rsp_size || !rsp_buf) {
5652 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5653 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
5654 
5655 		rval = DFC_ARG_NULL;
5656 		goto done;
5657 	}
5658 
5659 	if (!dfc->buf3 || !dfc->buf3_size) {
5660 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5661 		    "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
5662 
5663 		rval = DFC_ARG_NULL;
5664 		goto done;
5665 	}
5666 
5667 	if (!dfc->buf4 || !dfc->buf4_size) {
5668 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5669 		    "%s: Null buffer4 found.", emlxs_dfc_xlate(dfc->cmd));
5670 
5671 		rval = DFC_ARG_NULL;
5672 		goto done;
5673 	}
5674 
5675 	if (rsp_size > MAX_CT_PAYLOAD) {
5676 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5677 		    "%s: Buffer2 too large. size=%d",
5678 		    emlxs_dfc_xlate(dfc->cmd), rsp_size);
5679 
5680 		rval = DFC_ARG_TOOBIG;
5681 		goto done;
5682 	}
5683 
5684 	if (cmd_size > MAX_CT_PAYLOAD) {
5685 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5686 		    "%s: Buffer1 too large. size=%d",
5687 		    emlxs_dfc_xlate(dfc->cmd), cmd_size);
5688 
5689 		rval = DFC_ARG_TOOBIG;
5690 		goto done;
5691 	}
5692 
5693 	if (dfc->buf3_size < sizeof (dfc_destid_t)) {
5694 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5695 		    "%s: Buffer3 too small. (size=%d)",
5696 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
5697 
5698 		rval = DFC_ARG_TOOSMALL;
5699 		goto done;
5700 	}
5701 
5702 	if (dfc->buf4_size < sizeof (uint32_t)) {
5703 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5704 		    "%s: Buffer4 too small. (size=%d)",
5705 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf4_size);
5706 
5707 		rval = DFC_ARG_TOOSMALL;
5708 		goto done;
5709 	}
5710 
5711 	destid = (dfc_destid_t *)dfc->buf3;
5712 
5713 	if (destid->idType == 0) {
5714 		if ((nlp = emlxs_node_find_wwpn(port, destid->wwpn, 1))
5715 		    == NULL) {
5716 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5717 			    "%s: WWPN does not exists. %s",
5718 			    emlxs_dfc_xlate(dfc->cmd), emlxs_wwn_xlate(buffer,
5719 			    sizeof (buffer), destid->wwpn));
5720 
5721 			rval = DFC_ARG_INVALID;
5722 			goto done;
5723 		}
5724 		did = nlp->nlp_DID;
5725 	} else {
5726 		if (emlxs_node_find_did(port, destid->d_id, 1) == NULL) {
5727 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5728 			    "%s: DID does not exist. did=%x",
5729 			    emlxs_dfc_xlate(dfc->cmd), destid->d_id);
5730 
5731 			rval = DFC_ARG_INVALID;
5732 			goto done;
5733 		}
5734 		did = destid->d_id;
5735 	}
5736 
5737 	if (did == 0) {
5738 		did = port->did;
5739 	}
5740 
5741 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size, 0, KM_NOSLEEP))) {
5742 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5743 		    "%s: Unable to allocate packet.",
5744 		    emlxs_dfc_xlate(dfc->cmd));
5745 
5746 		rval = DFC_SYSRES_ERROR;
5747 		goto done;
5748 	}
5749 
5750 	/* Make this a polled IO */
5751 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5752 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5753 	pkt->pkt_comp = NULL;
5754 
5755 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
5756 	pkt->pkt_timeout = (timeout) ? timeout : 30;
5757 
5758 	/* Build the fc header */
5759 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
5760 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL;
5761 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
5762 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
5763 	pkt->pkt_cmd_fhdr.f_ctl =
5764 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
5765 	pkt->pkt_cmd_fhdr.seq_id = 0;
5766 	pkt->pkt_cmd_fhdr.df_ctl = 0;
5767 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
5768 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5769 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
5770 	pkt->pkt_cmd_fhdr.ro = 0;
5771 
5772 	/* Copy in the command buffer */
5773 	bcopy((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size);
5774 
5775 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5776 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5777 		    "%s: Unable to send packet.", emlxs_dfc_xlate(dfc->cmd));
5778 
5779 		rval = DFC_IO_ERROR;
5780 		goto done;
5781 	}
5782 
5783 	if ((pkt->pkt_state != FC_PKT_SUCCESS) &&
5784 	    (pkt->pkt_state != FC_PKT_FS_RJT)) {
5785 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5786 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5787 			    "Pkt Transport error. Pkt Timeout.");
5788 			rval = DFC_TIMEOUT;
5789 		} else {
5790 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5791 			    "Pkt Transport error. state=%x", pkt->pkt_state);
5792 			rval = DFC_IO_ERROR;
5793 		}
5794 		goto done;
5795 	}
5796 
5797 	bcopy((void *)pkt->pkt_resp, (void *)rsp_buf, rsp_size);
5798 
5799 	rsp_size -= pkt->pkt_resp_resid;
5800 	bcopy((void *)&rsp_size, (void *)dfc->buf4, sizeof (uint32_t));
5801 
5802 	rval = 0;
5803 
5804 done:
5805 
5806 	if (pkt) {
5807 		emlxs_pkt_free(pkt);
5808 	}
5809 
5810 	return (rval);
5811 
5812 } /* emlxs_dfc_send_ct() */
5813 
5814 
5815 /*ARGSUSED*/
5816 static int32_t
emlxs_dfc_send_ct_rsp(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)5817 emlxs_dfc_send_ct_rsp(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5818 {
5819 	emlxs_port_t	*port = &PPORT;
5820 	uint8_t		*cmd_buf;
5821 	uint32_t	rx_id;
5822 	uint32_t	cmd_size;
5823 	uint32_t	timeout;
5824 	fc_packet_t	*pkt = NULL;
5825 	uint32_t	rval = 0;
5826 
5827 	cmd_buf = dfc->buf1;
5828 	cmd_size = dfc->buf1_size;
5829 	rx_id = dfc->flag;
5830 	timeout = 2 * hba->fc_ratov;
5831 
5832 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s: csize=%d",
5833 	    emlxs_dfc_xlate(dfc->cmd), cmd_size);
5834 
5835 	if (!cmd_size || !cmd_buf) {
5836 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5837 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5838 
5839 		rval = DFC_ARG_NULL;
5840 		goto done;
5841 	}
5842 
5843 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, 0, 0, KM_NOSLEEP))) {
5844 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5845 		    "%s: Unable to allocate packet.",
5846 		    emlxs_dfc_xlate(dfc->cmd));
5847 
5848 		rval = DFC_SYSRES_ERROR;
5849 		goto done;
5850 	}
5851 
5852 	/* Make this a polled IO */
5853 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5854 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5855 	pkt->pkt_comp = NULL;
5856 
5857 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
5858 	pkt->pkt_timeout = (timeout) ? timeout : 30;
5859 
5860 	/* Build the fc header */
5861 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(0);
5862 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_SOLICITED_CONTROL;
5863 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
5864 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
5865 	pkt->pkt_cmd_fhdr.f_ctl =
5866 	    F_CTL_LAST_SEQ | F_CTL_END_SEQ | F_CTL_XCHG_CONTEXT;
5867 	pkt->pkt_cmd_fhdr.seq_id = 0;
5868 	pkt->pkt_cmd_fhdr.df_ctl = 0;
5869 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
5870 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
5871 	pkt->pkt_cmd_fhdr.rx_id = rx_id;
5872 	pkt->pkt_cmd_fhdr.ro = 0;
5873 
5874 	/* Copy in the command buffer */
5875 	bcopy((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size);
5876 
5877 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5878 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5879 		    "%s: Unable to send packet.", emlxs_dfc_xlate(dfc->cmd));
5880 
5881 		rval = DFC_IO_ERROR;
5882 		goto done;
5883 	}
5884 
5885 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
5886 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5887 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5888 			    "Pkt Transport error. Pkt Timeout.");
5889 			rval = DFC_TIMEOUT;
5890 		} else {
5891 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5892 			    "Pkt Transport error. state=%x", pkt->pkt_state);
5893 			rval = DFC_IO_ERROR;
5894 		}
5895 		goto done;
5896 	}
5897 
5898 	rval = 0;
5899 
5900 done:
5901 
5902 	if (pkt) {
5903 		emlxs_pkt_free(pkt);
5904 	}
5905 
5906 	return (rval);
5907 
5908 } /* emlxs_dfc_send_ct_rsp() */
5909 
5910 
5911 #ifdef MENLO_SUPPORT
5912 
5913 /*ARGSUSED*/
5914 static int32_t
emlxs_dfc_send_menlo(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)5915 emlxs_dfc_send_menlo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5916 {
5917 	emlxs_port_t	*port = &PPORT;
5918 	uint8_t		*rsp_buf = NULL;
5919 	uint8_t		*cmd_buf = NULL;
5920 	uint32_t	rsp_size = 0;
5921 	uint32_t	cmd_size = 0;
5922 	uint32_t	rval = 0;
5923 
5924 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5925 	    "%s: csize=%d rsize=%d", emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size,
5926 	    dfc->buf2_size);
5927 
5928 	if (hba->model_info.vendor_id != PCI_VENDOR_ID_EMULEX ||
5929 	    hba->model_info.device_id != PCI_DEVICE_ID_HORNET) {
5930 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5931 		    "%s: Menlo device not present. device=%x,%x,%x",
5932 		    emlxs_dfc_xlate(dfc->cmd), hba->model_info.vendor_id,
5933 		    hba->model_info.device_id, hba->model_info.ssdid);
5934 
5935 		rval = DFC_INVALID_ADAPTER;
5936 		goto done;
5937 	}
5938 
5939 	if (!dfc->buf1_size || !dfc->buf1) {
5940 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5941 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5942 
5943 		rval = DFC_ARG_NULL;
5944 		goto done;
5945 	}
5946 
5947 	if (!dfc->buf2_size || !dfc->buf2) {
5948 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5949 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
5950 
5951 		rval = DFC_ARG_NULL;
5952 		goto done;
5953 	}
5954 
5955 	if (!dfc->buf3 || !dfc->buf3_size) {
5956 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5957 		    "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
5958 
5959 		rval = DFC_ARG_NULL;
5960 		goto done;
5961 	}
5962 
5963 	if (dfc->buf3_size < sizeof (uint32_t)) {
5964 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5965 		    "%s: Buffer3 too small. %d < %d",
5966 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size,
5967 		    sizeof (uint32_t));
5968 
5969 		rval = DFC_ARG_TOOSMALL;
5970 		goto done;
5971 	}
5972 
5973 	cmd_size  = dfc->buf1_size;
5974 	cmd_buf = (uint8_t *)dfc->buf1;
5975 
5976 	rsp_size  = dfc->buf2_size;
5977 	rsp_buf = (uint8_t *)dfc->buf2;
5978 
5979 	/* Send the command */
5980 	rval = emlxs_send_menlo_cmd(hba, cmd_buf, cmd_size,
5981 	    rsp_buf, &rsp_size);
5982 
5983 	if (rval == 0) {
5984 		/* Return the response & size */
5985 		bcopy((void *)rsp_buf, (void *)dfc->buf2, rsp_size);
5986 		bcopy((void *)&rsp_size, (void *)dfc->buf3, sizeof (uint32_t));
5987 	}
5988 
5989 done:
5990 
5991 	return (rval);
5992 
5993 } /* emlxs_dfc_send_menlo() */
5994 
5995 
5996 extern int32_t
emlxs_send_menlo_cmd(emlxs_hba_t * hba,uint8_t * cmd_buf,uint32_t cmd_size,uint8_t * rsp_buf,uint32_t * rsp_size)5997 emlxs_send_menlo_cmd(emlxs_hba_t *hba, uint8_t *cmd_buf, uint32_t cmd_size,
5998     uint8_t *rsp_buf, uint32_t *rsp_size)
5999 {
6000 	emlxs_port_t		*port = &PPORT;
6001 	uint8_t			*data_buf = NULL;
6002 	uint32_t		data_size = 0;
6003 	fc_packet_t		*pkt = NULL;
6004 	int32_t			rval = 0;
6005 	menlo_set_cmd_t		set_cmd;
6006 	menlo_reset_cmd_t	reset_cmd;
6007 	uint32_t		rsp_code;
6008 	uint32_t		mm_mode = 0;
6009 	uint32_t		cmd_code;
6010 	clock_t			timeout;
6011 	MAILBOXQ		*mbq = NULL;
6012 	MAILBOX			*mb;
6013 	uint32_t		addr;
6014 	uint32_t		value;
6015 	uint32_t		mbxstatus;
6016 
6017 	cmd_code = *(uint32_t *)cmd_buf;
6018 	cmd_code = BE_SWAP32(cmd_code);
6019 
6020 	/* Look for Zephyr specific commands */
6021 	if (cmd_code & 0x80000000) {
6022 		bzero((uint8_t *)&reset_cmd, sizeof (menlo_reset_cmd_t));
6023 		bzero((uint8_t *)&set_cmd, sizeof (menlo_set_cmd_t));
6024 		bzero((uint8_t *)&rsp_code, sizeof (uint32_t));
6025 
6026 		/* Validate response buffer */
6027 		if (*rsp_size < sizeof (uint32_t)) {
6028 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6029 			    "send_menlo_cmd: Response overrun.");
6030 			rval = DFC_RSP_BUF_OVERRUN;
6031 			goto done;
6032 		}
6033 
6034 		/* All of these responses will be 4 bytes only */
6035 		*rsp_size = sizeof (uint32_t);
6036 		rsp_code = 0;
6037 
6038 		/* Validate command buffer */
6039 		switch (cmd_code) {
6040 		case MENLO_CMD_RESET:
6041 			if (cmd_size < sizeof (menlo_reset_cmd_t)) {
6042 				EMLXS_MSGF(EMLXS_CONTEXT,
6043 				    &emlxs_dfc_error_msg,
6044 				    "send_menlo_cmd: "
6045 				    "Invalid command size. %d < %d",
6046 				    cmd_size,
6047 				    sizeof (menlo_reset_cmd_t));
6048 				rval = DFC_ARG_INVALID;
6049 				goto done;
6050 			}
6051 			cmd_size = sizeof (menlo_reset_cmd_t);
6052 
6053 			/* Read the command buffer */
6054 			bcopy((void *)cmd_buf, (void *)&reset_cmd, cmd_size);
6055 
6056 			if (reset_cmd.firmware) {
6057 				/* MENLO_FW_GOLDEN */
6058 				value = 1;
6059 
6060 				EMLXS_MSGF(EMLXS_CONTEXT,
6061 				    &emlxs_dfc_detail_msg,
6062 				    "send_menlo_cmd: Reset with Golden "
6063 				    "firmware requested.");
6064 
6065 			} else {
6066 				/* MENLO_FW_OPERATIONAL */
6067 				value = 0;
6068 
6069 				EMLXS_MSGF(EMLXS_CONTEXT,
6070 				    &emlxs_dfc_detail_msg,
6071 				    "send_menlo_cmd: Reset with "
6072 				    "Operational firmware requested.");
6073 			}
6074 
6075 			addr  = 0x103007;
6076 
6077 			break;
6078 
6079 		case MENLO_CMD_SET_MODE:
6080 			if (cmd_size < sizeof (menlo_set_cmd_t)) {
6081 				EMLXS_MSGF(EMLXS_CONTEXT,
6082 				    &emlxs_dfc_error_msg,
6083 				    "send_menlo_cmd: "
6084 				    "Invalid command size. %d < %d",
6085 				    cmd_size,
6086 				    sizeof (menlo_set_cmd_t));
6087 				rval = DFC_ARG_INVALID;
6088 				goto done;
6089 			}
6090 			cmd_size = sizeof (menlo_set_cmd_t);
6091 
6092 			/* Read the command buffer */
6093 			bcopy((void *)cmd_buf, (void *)&set_cmd, cmd_size);
6094 
6095 			if (set_cmd.value1) {
6096 				EMLXS_MSGF(EMLXS_CONTEXT,
6097 				    &emlxs_dfc_detail_msg,
6098 				    "send_menlo_cmd: "
6099 				    "Maintenance mode enable requested.");
6100 
6101 				/* Make sure the mode flag is cleared */
6102 				if (hba->flag & FC_MENLO_MODE) {
6103 					mutex_enter(&EMLXS_PORT_LOCK);
6104 					hba->flag &= ~FC_MENLO_MODE;
6105 					mutex_exit(&EMLXS_PORT_LOCK);
6106 				}
6107 
6108 				mm_mode = 1;
6109 			} else {
6110 				EMLXS_MSGF(EMLXS_CONTEXT,
6111 				    &emlxs_dfc_detail_msg,
6112 				    "send_menlo_cmd: "
6113 				    "Maintenance mode disable requested.");
6114 			}
6115 
6116 			addr  = 0x103107;
6117 			value = mm_mode;
6118 
6119 			break;
6120 
6121 		default:
6122 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6123 			    "send_menlo_cmd: "
6124 			    "Invalid command. cmd=%x", cmd_code);
6125 			rval = DFC_ARG_INVALID;
6126 			goto done;
6127 		}
6128 
6129 		mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
6130 		    KM_SLEEP);
6131 
6132 		mb = (MAILBOX *) mbq;
6133 
6134 		/* Create the set_variable mailbox request */
6135 		emlxs_mb_set_var(hba, mbq, addr, value);
6136 
6137 		mbq->flag |= MBQ_PASSTHRU;
6138 
6139 		/* issue the mbox cmd to the sli */
6140 		mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
6141 
6142 		if (mbxstatus) {
6143 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6144 			    "send_menlo_cmd: %s failed. mbxstatus=0x%x",
6145 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
6146 
6147 			if (mbxstatus == MBX_TIMEOUT) {
6148 				rval = DFC_TIMEOUT;
6149 			} else {
6150 				rval = DFC_IO_ERROR;
6151 			}
6152 			goto done;
6153 		}
6154 
6155 		bcopy((void *)&rsp_code, (void *)rsp_buf, *rsp_size);
6156 
6157 		/* Check if we need to wait for maintenance mode */
6158 		if (mm_mode && !(hba->flag & FC_MENLO_MODE)) {
6159 			/* Wait for link to come up in maintenance mode */
6160 			mutex_enter(&EMLXS_LINKUP_LOCK);
6161 
6162 			timeout = emlxs_timeout(hba, 30);
6163 
6164 			rval = 0;
6165 			while ((rval != -1) && !(hba->flag & FC_MENLO_MODE)) {
6166 				rval =
6167 				    cv_timedwait(&EMLXS_LINKUP_CV,
6168 				    &EMLXS_LINKUP_LOCK, timeout);
6169 			}
6170 
6171 			mutex_exit(&EMLXS_LINKUP_LOCK);
6172 
6173 			if (rval == -1) {
6174 				EMLXS_MSGF(EMLXS_CONTEXT,
6175 				    &emlxs_dfc_error_msg,
6176 				    "send_menlo_cmd: "
6177 				    "Menlo maintenance mode error. Timeout.");
6178 
6179 				rval = DFC_TIMEOUT;
6180 				goto done;
6181 			}
6182 		}
6183 	} else {	/* Standard commands */
6184 
6185 		if (hba->state <= FC_LINK_DOWN) {
6186 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6187 			    "send_menlo_cmd: Adapter link down.");
6188 
6189 			rval = DFC_LINKDOWN_ERROR;
6190 			goto done;
6191 		}
6192 
6193 		if (cmd_code == MENLO_CMD_FW_DOWNLOAD) {
6194 			/* Check cmd size */
6195 			/* Must be at least 12 bytes of command */
6196 			/* plus 4 bytes of data */
6197 			if (cmd_size < (12 + 4)) {
6198 				EMLXS_MSGF(EMLXS_CONTEXT,
6199 				    &emlxs_dfc_error_msg,
6200 				    "send_menlo_cmd: "
6201 				    "Invalid command size. %d < %d",
6202 				    cmd_size,
6203 				    (12 + 4));
6204 
6205 				rval = DFC_ARG_INVALID;
6206 				goto done;
6207 			}
6208 
6209 			/* Extract data buffer from command buffer */
6210 			data_buf    = cmd_buf  + 12;
6211 			data_size   = cmd_size - 12;
6212 			cmd_size    = 12;
6213 		}
6214 
6215 		if (!(pkt = emlxs_pkt_alloc(port, cmd_size, *rsp_size, 0,
6216 		    KM_NOSLEEP))) {
6217 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6218 			    "send_menlo_cmd: Unable to allocate packet.");
6219 
6220 			rval = DFC_SYSRES_ERROR;
6221 			goto done;
6222 		}
6223 
6224 		/* Make this a polled IO */
6225 		pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
6226 		pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6227 		pkt->pkt_comp = NULL;
6228 		pkt->pkt_tran_type = FC_PKT_EXCHANGE;
6229 		pkt->pkt_timeout = 30;
6230 
6231 		/* Build the fc header */
6232 		pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(EMLXS_MENLO_DID);
6233 		pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
6234 		pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
6235 		pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
6236 		pkt->pkt_cmd_fhdr.f_ctl =
6237 		    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
6238 		pkt->pkt_cmd_fhdr.seq_id = 0;
6239 		pkt->pkt_cmd_fhdr.df_ctl = 0;
6240 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
6241 		pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
6242 		pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
6243 		pkt->pkt_cmd_fhdr.ro = 0;
6244 
6245 		/* Copy in the command buffer */
6246 		bcopy((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size);
6247 
6248 		if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
6249 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6250 			    "send_menlo_cmd: Unable to send packet.");
6251 
6252 			rval = DFC_IO_ERROR;
6253 			goto done;
6254 		}
6255 
6256 		if (pkt->pkt_state != FC_PKT_SUCCESS) {
6257 			if (pkt->pkt_state == FC_PKT_TIMEOUT) {
6258 				EMLXS_MSGF(EMLXS_CONTEXT,
6259 				    &emlxs_dfc_error_msg,
6260 				    "send_menlo_cmd: "
6261 				    "Pkt Transport error. Pkt Timeout.");
6262 				rval = DFC_TIMEOUT;
6263 			} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
6264 			    (pkt->pkt_reason == FC_REASON_OVERRUN)) {
6265 				EMLXS_MSGF(EMLXS_CONTEXT,
6266 				    &emlxs_dfc_error_msg,
6267 				    "send_menlo_cmd: "
6268 				    "Pkt Transport error. Response overrun.");
6269 				rval = DFC_RSP_BUF_OVERRUN;
6270 			} else {
6271 				EMLXS_MSGF(EMLXS_CONTEXT,
6272 				    &emlxs_dfc_error_msg,
6273 				    "send_menlo_cmd: "
6274 				    "Pkt Transport error. state=%x",
6275 				    pkt->pkt_state);
6276 				rval = DFC_IO_ERROR;
6277 			}
6278 			goto done;
6279 		}
6280 
6281 		if (cmd_code == MENLO_CMD_FW_DOWNLOAD) {
6282 			uint32_t *rsp;
6283 
6284 			/* Check response code */
6285 			rsp = (uint32_t *)pkt->pkt_resp;
6286 			rsp_code = *rsp;
6287 			rsp_code = BE_SWAP32(rsp_code);
6288 
6289 			if (rsp_code == MENLO_RSP_SUCCESS) {
6290 				/* Now transmit the data phase */
6291 
6292 				/* Save last rx_id */
6293 				uint32_t rx_id = pkt->pkt_cmd_fhdr.rx_id;
6294 
6295 				/* Free old pkt */
6296 				emlxs_pkt_free(pkt);
6297 
6298 				/* Allocate data pkt */
6299 				if (!(pkt = emlxs_pkt_alloc(port, data_size,
6300 				    *rsp_size, 0, KM_NOSLEEP))) {
6301 					EMLXS_MSGF(EMLXS_CONTEXT,
6302 					    &emlxs_dfc_error_msg,
6303 					    "send_menlo_cmd: "
6304 					    "Unable to allocate data "
6305 					    "packet.");
6306 
6307 					rval = DFC_SYSRES_ERROR;
6308 					goto done;
6309 				}
6310 
6311 				/* Make this a polled IO */
6312 				pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
6313 				pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6314 				pkt->pkt_comp = NULL;
6315 				pkt->pkt_tran_type = FC_PKT_OUTBOUND;
6316 				pkt->pkt_timeout = 30;
6317 
6318 				/* Build the fc header */
6319 				pkt->pkt_cmd_fhdr.d_id =
6320 				    LE_SWAP24_LO(EMLXS_MENLO_DID);
6321 				pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
6322 				pkt->pkt_cmd_fhdr.s_id =
6323 				    LE_SWAP24_LO(port->did);
6324 				pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
6325 				pkt->pkt_cmd_fhdr.f_ctl =
6326 				    F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
6327 				    F_CTL_SEQ_INITIATIVE;
6328 				pkt->pkt_cmd_fhdr.seq_id = 0;
6329 				pkt->pkt_cmd_fhdr.df_ctl = 0;
6330 				pkt->pkt_cmd_fhdr.seq_cnt = 0;
6331 				pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
6332 				pkt->pkt_cmd_fhdr.rx_id = rx_id;
6333 				pkt->pkt_cmd_fhdr.ro = 0;
6334 
6335 				/* Copy in the data buffer */
6336 				bcopy((void *)data_buf, (void *)pkt->pkt_cmd,
6337 				    data_size);
6338 
6339 				if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
6340 					EMLXS_MSGF(EMLXS_CONTEXT,
6341 					    &emlxs_dfc_error_msg,
6342 					    "send_menlo_cmd: "
6343 					    "Unable to send data packet.");
6344 
6345 					rval = DFC_IO_ERROR;
6346 					goto done;
6347 				}
6348 
6349 				if (pkt->pkt_state != FC_PKT_SUCCESS) {
6350 					if (pkt->pkt_state == FC_PKT_TIMEOUT) {
6351 						EMLXS_MSGF(EMLXS_CONTEXT,
6352 						    &emlxs_dfc_error_msg,
6353 						    "send_menlo_cmd: "
6354 						    "Data Pkt Transport "
6355 						    "error. Pkt Timeout.");
6356 						rval = DFC_TIMEOUT;
6357 					} else if ((pkt->pkt_state ==
6358 					    FC_PKT_LOCAL_RJT) &&
6359 					    (pkt->pkt_reason ==
6360 					    FC_REASON_OVERRUN)) {
6361 						EMLXS_MSGF(EMLXS_CONTEXT,
6362 						    &emlxs_dfc_error_msg,
6363 						    "send_menlo_cmd: "
6364 						    "Data Pkt Transport "
6365 						    "error. Response overrun.");
6366 						rval = DFC_RSP_BUF_OVERRUN;
6367 					} else {
6368 						EMLXS_MSGF(EMLXS_CONTEXT,
6369 						    &emlxs_dfc_error_msg,
6370 						    "send_menlo_cmd: "
6371 						    "Data Pkt Transport "
6372 						    "error. state=%x",
6373 						    pkt->pkt_state);
6374 						rval = DFC_IO_ERROR;
6375 					}
6376 					goto done;
6377 				}
6378 			}
6379 		}
6380 
6381 		bcopy((void *)pkt->pkt_resp, (void *)rsp_buf, *rsp_size);
6382 		*rsp_size = *rsp_size - pkt->pkt_resp_resid;
6383 	}
6384 
6385 	rval = 0;
6386 
6387 done:
6388 
6389 	if (pkt) {
6390 		emlxs_pkt_free(pkt);
6391 	}
6392 
6393 	if (mbq) {
6394 		kmem_free(mbq, sizeof (MAILBOXQ));
6395 	}
6396 
6397 	return (rval);
6398 
6399 } /* emlxs_send_menlo_cmd() */
6400 
6401 
6402 /* ARGSUSED */
6403 extern void
emlxs_fcoe_attention_thread(emlxs_hba_t * hba,void * arg1,void * arg2)6404 emlxs_fcoe_attention_thread(emlxs_hba_t *hba,
6405     void *arg1, void *arg2)
6406 {
6407 	emlxs_port_t		*port = &PPORT;
6408 	menlo_init_rsp_t	*rsp;
6409 	menlo_get_cmd_t		*cmd;
6410 	fc_packet_t		*pkt = NULL;
6411 
6412 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_get_cmd_t),
6413 	    sizeof (menlo_init_rsp_t), 0, KM_NOSLEEP))) {
6414 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6415 		    "FCoE attention: Unable to allocate packet.");
6416 
6417 		return;
6418 	}
6419 
6420 	/* Make this a polled IO */
6421 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
6422 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6423 	pkt->pkt_comp = NULL;
6424 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
6425 	pkt->pkt_timeout = 30;
6426 
6427 	/* Build the fc header */
6428 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(EMLXS_MENLO_DID);
6429 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
6430 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
6431 	pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
6432 	pkt->pkt_cmd_fhdr.f_ctl =
6433 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
6434 	pkt->pkt_cmd_fhdr.seq_id = 0;
6435 	pkt->pkt_cmd_fhdr.df_ctl = 0;
6436 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
6437 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
6438 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
6439 	pkt->pkt_cmd_fhdr.ro = 0;
6440 
6441 	cmd = (menlo_get_cmd_t *)pkt->pkt_cmd;
6442 	cmd->code = MENLO_CMD_GET_INIT;
6443 	cmd->context = 0;
6444 	cmd->length = sizeof (menlo_init_rsp_t);
6445 
6446 	/* Little Endian Swap */
6447 	cmd->code = BE_SWAP32(cmd->code);
6448 	cmd->length = BE_SWAP32(cmd->length);
6449 
6450 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
6451 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6452 		    "FCoE attention: Unable to send packet.");
6453 
6454 		goto done;
6455 	}
6456 
6457 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
6458 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6459 		    "FCoE attention: Pkt Transport error. state=%x",
6460 		    pkt->pkt_state);
6461 
6462 		goto done;
6463 	}
6464 
6465 	/* Check response code */
6466 	rsp = (menlo_init_rsp_t *)pkt->pkt_resp;
6467 	rsp->code = BE_SWAP32(rsp->code);
6468 
6469 	if (rsp->code != MENLO_RSP_SUCCESS) {
6470 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6471 		    "FCoE attention: FCOE Response error =%x", rsp->code);
6472 
6473 		goto done;
6474 	}
6475 
6476 	/* Little Endian Swap */
6477 	rsp->bb_credit = BE_SWAP32(rsp->bb_credit);
6478 	rsp->frame_size = BE_SWAP32(rsp->frame_size);
6479 	rsp->fw_version = BE_SWAP32(rsp->fw_version);
6480 	rsp->reset_status = BE_SWAP32(rsp->reset_status);
6481 	rsp->maint_status = BE_SWAP32(rsp->maint_status);
6482 	rsp->fw_type = BE_SWAP32(rsp->fw_type);
6483 	rsp->fru_data_valid = BE_SWAP32(rsp->fru_data_valid);
6484 
6485 	/* Log the event */
6486 	emlxs_log_fcoe_event(port, rsp);
6487 
6488 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6489 	    "MENLO_INIT: bb_credit      = 0x%x", rsp->bb_credit);
6490 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6491 	    "MENLO_INIT: frame_size     = 0x%x", rsp->frame_size);
6492 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6493 	    "MENLO_INIT: fw_version     = 0x%x", rsp->fw_version);
6494 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6495 	    "MENLO_INIT: reset_status   = 0x%x", rsp->reset_status);
6496 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6497 	    "MENLO_INIT: maint_status   = 0x%x", rsp->maint_status);
6498 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6499 	    "MENLO_INIT: fw_type        = 0x%x", rsp->fw_type);
6500 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6501 	    "MENLO_INIT: fru_data_valid = 0x%x", rsp->fru_data_valid);
6502 
6503 	/* Perform attention checks */
6504 	if (rsp->fru_data_valid == 0) {
6505 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_error_msg,
6506 		    "Invalid FRU data found on adapter. "
6507 		    "Return adapter to %s for repair.",
6508 		    hba->model_info.manufacturer);
6509 	}
6510 
6511 	switch (rsp->fw_type) {
6512 	case MENLO_FW_TYPE_GOLDEN:
6513 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_warning_msg,
6514 		    "FCoE chip is running Golden firmware. "
6515 		    "Update FCoE firmware immediately.");
6516 		break;
6517 
6518 	case MENLO_FW_TYPE_DIAG:
6519 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_notice_msg,
6520 		    "FCoE chip is running Diagnostic firmware. "
6521 		    "Operational use of the adapter is suspended.");
6522 		break;
6523 	}
6524 
6525 done:
6526 
6527 	if (pkt) {
6528 		emlxs_pkt_free(pkt);
6529 	}
6530 
6531 	return;
6532 
6533 } /* emlxs_fcoe_attention_thread() */
6534 
6535 #endif /* MENLO_SUPPORT */
6536 
6537 
6538 /*ARGSUSED*/
6539 static int32_t
emlxs_dfc_write_flash(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)6540 emlxs_dfc_write_flash(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6541 {
6542 	emlxs_port_t	*port = &PPORT;
6543 	uint32_t	offset;
6544 	uint32_t	cnt;
6545 	uint8_t		*bptr;
6546 	uint32_t	i;
6547 
6548 	if (hba->bus_type != SBUS_FC) {
6549 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6550 		    "%s: Invalid bus_type. (bus_type=%x)",
6551 		    emlxs_dfc_xlate(dfc->cmd), hba->bus_type);
6552 
6553 		return (DFC_ARG_INVALID);
6554 	}
6555 
6556 	if (!(hba->flag & FC_OFFLINE_MODE)) {
6557 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6558 		    "%s: Adapter not offline.", emlxs_dfc_xlate(dfc->cmd));
6559 
6560 		return (DFC_ONLINE_ERROR);
6561 	}
6562 
6563 	if (!dfc->buf1 || !dfc->buf1_size) {
6564 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6565 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6566 
6567 		return (DFC_ARG_NULL);
6568 	}
6569 
6570 	offset = dfc->data1;
6571 	cnt = dfc->data2;
6572 
6573 	if (offset > (64 * 1024)) {
6574 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6575 		    "%s: Offset too large. (offset=%d)",
6576 		    emlxs_dfc_xlate(dfc->cmd), offset);
6577 
6578 		return (DFC_ARG_TOOBIG);
6579 	}
6580 
6581 	if (cnt > dfc->buf1_size) {
6582 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6583 		    "%s: Count too large. (count=%d)",
6584 		    emlxs_dfc_xlate(dfc->cmd), cnt);
6585 
6586 		return (DFC_ARG_TOOBIG);
6587 	}
6588 
6589 	if ((cnt + offset) > (64 * 1024)) {
6590 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6591 		    "%s: Count+Offset too large. (count=%d offset=%d)",
6592 		    emlxs_dfc_xlate(dfc->cmd), cnt, offset);
6593 
6594 		return (DFC_ARG_TOOBIG);
6595 	}
6596 
6597 	if (cnt == 0) {
6598 		return (0);
6599 	}
6600 
6601 	bptr = (uint8_t *)dfc->buf1;
6602 	for (i = 0; i < cnt; i++) {
6603 		SBUS_WRITE_FLASH_COPY(hba, offset, *bptr);
6604 		offset++;
6605 		bptr++;
6606 	}
6607 
6608 #ifdef FMA_SUPPORT
6609 	/* Access handle validation */
6610 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
6611 	    != DDI_FM_OK) {
6612 		EMLXS_MSGF(EMLXS_CONTEXT,
6613 		    &emlxs_invalid_access_handle_msg, NULL);
6614 		return (DFC_DRV_ERROR);
6615 	}
6616 #endif  /* FMA_SUPPORT */
6617 
6618 	return (0);
6619 
6620 } /* emlxs_dfc_write_flash() */
6621 
6622 
6623 /*ARGSUSED*/
6624 static int32_t
emlxs_dfc_read_flash(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)6625 emlxs_dfc_read_flash(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6626 {
6627 	emlxs_port_t	*port = &PPORT;
6628 	uint32_t	offset;
6629 	uint32_t	count;
6630 	uint32_t	outsz;
6631 	uint8_t		*bptr;
6632 	uint32_t	i;
6633 
6634 	if (hba->bus_type != SBUS_FC) {
6635 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6636 		    "%s: Invalid bus_type. (bus_type=%x)",
6637 		    emlxs_dfc_xlate(dfc->cmd), hba->bus_type);
6638 
6639 		return (DFC_ARG_INVALID);
6640 	}
6641 
6642 	if (!(hba->flag & FC_OFFLINE_MODE)) {
6643 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6644 		    "%s: Adapter not offline.", emlxs_dfc_xlate(dfc->cmd));
6645 
6646 		return (DFC_ONLINE_ERROR);
6647 	}
6648 
6649 	if (!dfc->buf1 || !dfc->buf1_size) {
6650 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6651 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6652 
6653 		return (DFC_ARG_NULL);
6654 	}
6655 
6656 	offset = dfc->data1;
6657 	count = dfc->data2;
6658 	outsz = dfc->buf1_size;
6659 
6660 	if (offset > (64 * 1024)) {
6661 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6662 		    "%s: Offset too large. (offset=%d)",
6663 		    emlxs_dfc_xlate(dfc->cmd), offset);
6664 
6665 		return (DFC_ARG_TOOBIG);
6666 	}
6667 
6668 	if ((count + offset) > (64 * 1024)) {
6669 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6670 		    "%s: Count+Offset too large. (count=%d offset=%d)",
6671 		    emlxs_dfc_xlate(dfc->cmd), count, offset);
6672 
6673 		return (DFC_ARG_TOOBIG);
6674 	}
6675 
6676 	if (count < outsz) {
6677 		outsz = count;
6678 	}
6679 
6680 	bptr = (uint8_t *)dfc->buf1;
6681 	for (i = 0; i < outsz; i++) {
6682 		*bptr++ = SBUS_READ_FLASH_COPY(hba, offset++);
6683 	}
6684 
6685 #ifdef FMA_SUPPORT
6686 	/* Access handle validation */
6687 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
6688 	    != DDI_FM_OK) {
6689 		EMLXS_MSGF(EMLXS_CONTEXT,
6690 		    &emlxs_invalid_access_handle_msg, NULL);
6691 		return (DFC_DRV_ERROR);
6692 	}
6693 #endif  /* FMA_SUPPORT */
6694 
6695 	return (0);
6696 
6697 } /* emlxs_dfc_read_flash() */
6698 
6699 
6700 /*ARGSUSED*/
6701 static int32_t
emlxs_dfc_send_els(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)6702 emlxs_dfc_send_els(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6703 {
6704 	emlxs_port_t	*port = &PPORT;
6705 	uint8_t		*rsp_buf;
6706 	uint8_t		*cmd_buf;
6707 	dfc_destid_t	*destid;
6708 	uint32_t	rsp_size;
6709 	uint32_t	cmd_size;
6710 	uint32_t	timeout;
6711 	fc_packet_t	*pkt = NULL;
6712 	NODELIST	*ndlp;
6713 	uint32_t	did;
6714 	uint32_t	rval = 0;
6715 	char		buffer[128];
6716 
6717 	cmd_buf = dfc->buf1;
6718 	cmd_size = dfc->buf1_size;
6719 	rsp_buf = dfc->buf2;
6720 	rsp_size = dfc->buf2_size;
6721 
6722 	timeout = 2 * hba->fc_ratov;
6723 
6724 	if (!cmd_size || !cmd_buf) {
6725 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6726 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6727 
6728 		rval = DFC_ARG_NULL;
6729 		goto done;
6730 	}
6731 
6732 	if (!rsp_buf || !rsp_size) {
6733 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6734 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
6735 
6736 		rval = DFC_ARG_NULL;
6737 		goto done;
6738 	}
6739 
6740 	if (!dfc->buf3 || !dfc->buf3_size) {
6741 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6742 		    "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
6743 
6744 		rval = DFC_ARG_NULL;
6745 		goto done;
6746 	}
6747 
6748 	if (dfc->buf3_size < sizeof (dfc_destid_t)) {
6749 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6750 		    "%s: Buffer3 too small. (size=%d)",
6751 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
6752 
6753 		rval = DFC_ARG_TOOSMALL;
6754 		goto done;
6755 	}
6756 
6757 	if (!dfc->buf4 || !dfc->buf4_size) {
6758 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6759 		    "%s: Null buffer4 found.", emlxs_dfc_xlate(dfc->cmd));
6760 
6761 		rval = DFC_ARG_NULL;
6762 		goto done;
6763 	}
6764 
6765 	if (dfc->buf4_size < sizeof (uint32_t)) {
6766 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6767 		    "%s: Buffer4 too small. (size=%d)",
6768 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf4_size);
6769 
6770 		rval = DFC_ARG_TOOSMALL;
6771 		goto done;
6772 	}
6773 
6774 	destid = (dfc_destid_t *)dfc->buf3;
6775 
6776 	if (destid->idType == 0) {
6777 		if ((ndlp = emlxs_node_find_wwpn(port, destid->wwpn, 1))
6778 		    == NULL) {
6779 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6780 			    "%s: WWPN does not exists. %s",
6781 			    emlxs_dfc_xlate(dfc->cmd), emlxs_wwn_xlate(buffer,
6782 			    sizeof (buffer), destid->wwpn));
6783 
6784 			rval = DFC_ARG_INVALID;
6785 			goto done;
6786 		}
6787 		did = ndlp->nlp_DID;
6788 	} else {
6789 		if (emlxs_node_find_did(port, destid->d_id, 1) == NULL) {
6790 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6791 			    "%s: DID does not exist. did=%x",
6792 			    emlxs_dfc_xlate(dfc->cmd), destid->d_id);
6793 
6794 			rval = DFC_ARG_INVALID;
6795 			goto done;
6796 		}
6797 		did = destid->d_id;
6798 	}
6799 
6800 	if (did == 0) {
6801 		did = port->did;
6802 	}
6803 
6804 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size, 0, KM_NOSLEEP))) {
6805 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6806 		    "%s: Unable to allocate packet.",
6807 		    emlxs_dfc_xlate(dfc->cmd));
6808 
6809 		rval = DFC_SYSRES_ERROR;
6810 		goto done;
6811 	}
6812 
6813 	/* Make this a polled IO */
6814 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
6815 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6816 	pkt->pkt_comp = NULL;
6817 
6818 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
6819 	pkt->pkt_timeout = (timeout) ? timeout : 30;
6820 
6821 	/* Build the fc header */
6822 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
6823 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
6824 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
6825 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
6826 	pkt->pkt_cmd_fhdr.f_ctl =
6827 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
6828 	pkt->pkt_cmd_fhdr.seq_id = 0;
6829 	pkt->pkt_cmd_fhdr.df_ctl = 0;
6830 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
6831 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
6832 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
6833 	pkt->pkt_cmd_fhdr.ro = 0;
6834 
6835 	/* Copy in the command buffer */
6836 	bcopy((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size);
6837 
6838 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
6839 		rval = DFC_IO_ERROR;
6840 		bzero((void *)rsp_buf, rsp_size);
6841 		bzero((void *)dfc->buf4, sizeof (uint32_t));
6842 		goto done;
6843 	}
6844 
6845 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
6846 		if (pkt->pkt_state == FC_PKT_LS_RJT) {
6847 			LS_RJT *ls_rjt;
6848 			uint32_t *word;
6849 
6850 			word = (uint32_t *)rsp_buf;
6851 			word[0] = ELS_CMD_LS_RJT;
6852 
6853 			word[1] = 0;
6854 			ls_rjt = (LS_RJT *)&word[1];
6855 			ls_rjt->un.b.lsRjtRsnCode = pkt->pkt_reason;
6856 			ls_rjt->un.b.lsRjtRsnCodeExp = pkt->pkt_expln;
6857 
6858 			rsp_size = 8;
6859 			bcopy((void *)&rsp_size, (void *)dfc->buf4,
6860 			    sizeof (uint32_t));
6861 
6862 			goto done;
6863 
6864 		} else if (pkt->pkt_state == FC_PKT_TIMEOUT) {
6865 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6866 			    "Pkt Transport error. Pkt Timeout.");
6867 			rval = DFC_TIMEOUT;
6868 		} else {
6869 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6870 			    "Pkt Transport error. state=%x", pkt->pkt_state);
6871 			rval = DFC_IO_ERROR;
6872 		}
6873 
6874 		bzero((void *)rsp_buf, rsp_size);
6875 		bzero((void *)dfc->buf4, sizeof (uint32_t));
6876 		goto done;
6877 	}
6878 
6879 	rsp_size -= pkt->pkt_resp_resid;
6880 	bcopy((void *)pkt->pkt_resp, (void *)rsp_buf, rsp_size);
6881 	bcopy((void *)&rsp_size, (void *)dfc->buf4, sizeof (uint32_t));
6882 
6883 	rval = 0;
6884 
6885 done:
6886 	if (pkt) {
6887 		emlxs_pkt_free(pkt);
6888 	}
6889 
6890 	return (rval);
6891 
6892 } /* emlxs_dfc_send_els() */
6893 
6894 
6895 /*ARGSUSED*/
6896 static int32_t
emlxs_dfc_get_ioinfo(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)6897 emlxs_dfc_get_ioinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6898 {
6899 	emlxs_port_t	*port = &PPORT;
6900 	dfc_ioinfo_t	*ioinfo;
6901 	uint32_t	i;
6902 
6903 	if (!dfc->buf1 || !dfc->buf1_size) {
6904 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6905 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6906 
6907 		return (DFC_ARG_NULL);
6908 	}
6909 
6910 	if (dfc->buf1_size < sizeof (dfc_ioinfo_t)) {
6911 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6912 		    "%s: Buffer1 too small. (size=%d)",
6913 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6914 
6915 		return (DFC_ARG_TOOSMALL);
6916 	}
6917 
6918 	ioinfo = (dfc_ioinfo_t *)dfc->buf1;
6919 	bzero(ioinfo, sizeof (dfc_ioinfo_t));
6920 
6921 	ioinfo->a_mboxCmd = HBASTATS.MboxIssued;
6922 	ioinfo->a_mboxCmpl = HBASTATS.MboxCompleted;
6923 	ioinfo->a_mboxErr = HBASTATS.MboxError;
6924 
6925 	for (i = 0; i < hba->chan_count; i++) {
6926 		ioinfo->a_iocbCmd += HBASTATS.IocbIssued[i];
6927 		ioinfo->a_iocbRsp += HBASTATS.IocbReceived[i];
6928 	}
6929 
6930 	ioinfo->a_adapterIntr = HBASTATS.IntrEvent[0] + HBASTATS.IntrEvent[1] +
6931 	    HBASTATS.IntrEvent[2] + HBASTATS.IntrEvent[3] +
6932 	    HBASTATS.IntrEvent[4] + HBASTATS.IntrEvent[5] +
6933 	    HBASTATS.IntrEvent[6] + HBASTATS.IntrEvent[7];
6934 
6935 	ioinfo->a_fcpCmd = HBASTATS.FcpIssued;
6936 	ioinfo->a_fcpCmpl = HBASTATS.FcpCompleted;
6937 	ioinfo->a_fcpErr = HBASTATS.FcpCompleted - HBASTATS.FcpGood;
6938 
6939 	ioinfo->a_seqXmit = HBASTATS.IpSeqIssued;
6940 	ioinfo->a_seqRcv = HBASTATS.IpSeqReceived;
6941 	ioinfo->a_seqXmitErr = HBASTATS.IpSeqCompleted - HBASTATS.IpSeqGood;
6942 
6943 	ioinfo->a_bcastXmit = HBASTATS.IpBcastIssued;
6944 	ioinfo->a_bcastRcv = HBASTATS.IpBcastReceived;
6945 
6946 	ioinfo->a_elsXmit = HBASTATS.ElsCmdIssued;
6947 	ioinfo->a_elsRcv = HBASTATS.ElsCmdReceived;
6948 	ioinfo->a_elsXmitErr = HBASTATS.ElsCmdCompleted - HBASTATS.ElsCmdGood;
6949 
6950 	ioinfo->a_RSCNRcv = HBASTATS.ElsRscnReceived;
6951 
6952 	ioinfo->a_elsBufPost = HBASTATS.ElsUbPosted;
6953 	ioinfo->a_ipBufPost = HBASTATS.IpUbPosted;
6954 
6955 	ioinfo->a_cnt1 = 0;
6956 	ioinfo->a_cnt2 = 0;
6957 	ioinfo->a_cnt3 = 0;
6958 	ioinfo->a_cnt4 = 0;
6959 
6960 	return (0);
6961 
6962 } /* emlxs_dfc_get_ioinfo() */
6963 
6964 
6965 /*ARGSUSED*/
6966 static int32_t
emlxs_dfc_get_linkinfo(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)6967 emlxs_dfc_get_linkinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6968 {
6969 	emlxs_port_t	*port = &PPORT;
6970 	dfc_linkinfo_t	*linkinfo;
6971 
6972 	if (!dfc->buf1 || !dfc->buf1_size) {
6973 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6974 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6975 
6976 		return (DFC_ARG_NULL);
6977 	}
6978 
6979 	if (dfc->buf1_size < sizeof (dfc_linkinfo_t)) {
6980 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6981 		    "%s: Buffer1 too small. (size=%d)",
6982 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6983 
6984 		return (DFC_ARG_TOOSMALL);
6985 	}
6986 
6987 	linkinfo = (dfc_linkinfo_t *)dfc->buf1;
6988 	bzero(linkinfo, sizeof (dfc_linkinfo_t));
6989 
6990 	linkinfo->a_linkEventTag = hba->link_event_tag;
6991 	linkinfo->a_linkUp = HBASTATS.LinkUp;
6992 	linkinfo->a_linkDown = HBASTATS.LinkDown;
6993 	linkinfo->a_linkMulti = HBASTATS.LinkMultiEvent;
6994 	linkinfo->a_DID = port->did;
6995 	linkinfo->a_topology = 0;
6996 
6997 	if (hba->state <= FC_LINK_DOWN) {
6998 		linkinfo->a_linkState = LNK_DOWN;
6999 	}
7000 #ifdef MENLO_SUPPORT
7001 	else if (hba->flag & FC_MENLO_MODE) {
7002 		linkinfo->a_linkState = LNK_DOWN;
7003 		linkinfo->a_topology  = LNK_MENLO_MAINTENANCE;
7004 
7005 	}
7006 #endif /* MENLO_SUPPORT */
7007 	else if (hba->state == FC_LINK_DOWN_PERSIST) {
7008 		linkinfo->a_linkState = LNK_DOWN_PERSIST;
7009 	} else if (hba->state < FC_READY) {
7010 		linkinfo->a_linkState = LNK_DISCOVERY;
7011 	} else {
7012 		linkinfo->a_linkState = LNK_READY;
7013 	}
7014 
7015 	if (linkinfo->a_linkState != LNK_DOWN) {
7016 		if (hba->topology == TOPOLOGY_LOOP) {
7017 			if (hba->flag & FC_FABRIC_ATTACHED) {
7018 				linkinfo->a_topology = LNK_PUBLIC_LOOP;
7019 			} else {
7020 				linkinfo->a_topology = LNK_LOOP;
7021 			}
7022 
7023 			linkinfo->a_alpa = port->did & 0xff;
7024 			linkinfo->a_alpaCnt = port->alpa_map[0];
7025 
7026 			if (linkinfo->a_alpaCnt > 127) {
7027 				linkinfo->a_alpaCnt = 127;
7028 			}
7029 
7030 			bcopy((void *)&port->alpa_map[0], linkinfo->a_alpaMap,
7031 			    linkinfo->a_alpaCnt+1);
7032 		} else {
7033 			if (hba->flag & FC_FABRIC_ATTACHED) {
7034 				linkinfo->a_topology = LNK_FABRIC;
7035 			} else {
7036 				linkinfo->a_topology = LNK_PT2PT;
7037 			}
7038 		}
7039 	}
7040 
7041 	bcopy(&hba->wwpn, linkinfo->a_wwpName, 8);
7042 	bcopy(&hba->wwnn, linkinfo->a_wwnName, 8);
7043 
7044 	return (0);
7045 
7046 } /* emlxs_dfc_get_linkinfo() */
7047 
7048 #ifdef SFCT_SUPPORT
7049 /*ARGSUSED*/
7050 static int32_t
emlxs_dfc_get_fctstat(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)7051 emlxs_dfc_get_fctstat(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7052 {
7053 	emlxs_port_t		*port = &PPORT;
7054 	emlxs_tgtport_stat_t	*statp = &TGTPORTSTAT;
7055 	dfc_tgtport_stat_t	*dfcstat;
7056 
7057 	if (!dfc->buf1 || !dfc->buf1_size) {
7058 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7059 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
7060 
7061 		return (DFC_ARG_NULL);
7062 	}
7063 
7064 	if (dfc->buf1_size < sizeof (emlxs_tgtport_stat_t)) {
7065 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7066 		    "%s: Buffer1 too small. (size=%d)",
7067 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7068 
7069 		return (DFC_ARG_TOOSMALL);
7070 	}
7071 
7072 	dfcstat = (dfc_tgtport_stat_t *)dfc->buf1;
7073 	bzero(dfcstat, sizeof (dfc_tgtport_stat_t));
7074 
7075 	dfcstat->Version = DFC_TGTPORT_STAT_VERSION;
7076 
7077 	dfcstat->FctRcvDropped = statp->FctRcvDropped;
7078 	dfcstat->FctOverQDepth = statp->FctOverQDepth;
7079 	dfcstat->FctOutstandingIO = statp->FctOutstandingIO;
7080 	dfcstat->FctFailedPortRegister = statp->FctFailedPortRegister;
7081 	dfcstat->FctPortRegister = statp->FctPortRegister;
7082 	dfcstat->FctPortDeregister = statp->FctPortDeregister;
7083 
7084 	dfcstat->FctAbortSent = statp->FctAbortSent;
7085 	dfcstat->FctNoBuffer = statp->FctNoBuffer;
7086 	dfcstat->FctScsiStatusErr = statp->FctScsiStatusErr;
7087 	dfcstat->FctScsiQfullErr = statp->FctScsiQfullErr;
7088 	dfcstat->FctScsiResidOver = statp->FctScsiResidOver;
7089 	dfcstat->FctScsiResidUnder = statp->FctScsiResidUnder;
7090 	dfcstat->FctScsiSenseErr = statp->FctScsiSenseErr;
7091 
7092 	dfcstat->FctEvent = statp->FctEvent;
7093 	dfcstat->FctCompleted = statp->FctCompleted;
7094 	dfcstat->FctCmplGood = statp->FctCmplGood;
7095 	dfcstat->FctCmplError = statp->FctCmplError;
7096 	dfcstat->FctStray = statp->FctStray;
7097 
7098 	bcopy(&statp->FctP2IOWcnt[0], &dfcstat->FctP2IOWcnt[0],
7099 	    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
7100 	bcopy(&statp->FctP2IORcnt[0], &dfcstat->FctP2IORcnt[0],
7101 	    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
7102 	dfcstat->FctIOCmdCnt = statp->FctIOCmdCnt;
7103 	dfcstat->FctReadBytes = statp->FctReadBytes;
7104 	dfcstat->FctWriteBytes = statp->FctWriteBytes;
7105 	dfcstat->FctCmdReceived = statp->FctCmdReceived;
7106 
7107 	if (dfc->flag) {	/* Clear counters after read */
7108 		bzero(&statp->FctP2IOWcnt[0],
7109 		    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
7110 		bzero(&statp->FctP2IORcnt[0],
7111 		    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
7112 		statp->FctIOCmdCnt = 0;
7113 		statp->FctReadBytes = 0;
7114 		statp->FctWriteBytes = 0;
7115 		statp->FctCmdReceived = 0;
7116 	}
7117 	if (hba->state <= FC_LINK_DOWN) {
7118 		dfcstat->FctLinkState = LNK_DOWN;
7119 	}
7120 #ifdef MENLO_SUPPORT
7121 	else if (hba->flag & FC_MENLO_MODE) {
7122 		dfcstat->FctLinkState = LNK_DOWN;
7123 	}
7124 #endif /* MENLO_SUPPORT */
7125 	else if (hba->state < FC_READY) {
7126 		dfcstat->FctLinkState = LNK_DISCOVERY;
7127 	} else {
7128 		dfcstat->FctLinkState = LNK_READY;
7129 	}
7130 
7131 	return (0);
7132 
7133 } /* emlxs_dfc_get_fctstat() */
7134 #endif /* SFCT_SUPPORT */
7135 
7136 /*ARGSUSED*/
7137 static int32_t
emlxs_dfc_get_nodeinfo(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)7138 emlxs_dfc_get_nodeinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7139 {
7140 	emlxs_port_t	*port;
7141 	emlxs_config_t	*cfg = &CFG;
7142 	dfc_node_t	*dnp;
7143 	uint32_t	node_count;
7144 	NODELIST	*nlp;
7145 	uint32_t	i;
7146 
7147 	port = &VPORT(dfc->data1);
7148 
7149 	if (!dfc->buf1 || !dfc->buf1_size) {
7150 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7151 		    "%s: NULL buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
7152 
7153 		return (DFC_ARG_NULL);
7154 	}
7155 
7156 	if (dfc->buf1_size < (sizeof (dfc_node_t) * MAX_NODES)) {
7157 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7158 		    "%s: Buffer1 too small. (size=%d)",
7159 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7160 
7161 		return (DFC_ARG_TOOSMALL);
7162 	}
7163 
7164 	if (!dfc->buf2 || !dfc->buf2_size) {
7165 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7166 		    "%s: NULL buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
7167 
7168 		return (DFC_ARG_NULL);
7169 	}
7170 
7171 	if (dfc->buf2_size < sizeof (uint32_t)) {
7172 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7173 		    "%s: Buffer2 too small. (size=%d)",
7174 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
7175 
7176 		return (DFC_ARG_TOOSMALL);
7177 	}
7178 
7179 	node_count = port->node_count;
7180 
7181 	if (node_count == 0) {
7182 		return (0);
7183 	}
7184 
7185 	dnp = (dfc_node_t *)dfc->buf1;
7186 
7187 	node_count = 0;
7188 	rw_enter(&port->node_rwlock, RW_READER);
7189 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
7190 		nlp = port->node_table[i];
7191 		while (nlp && nlp->nlp_active &&
7192 		    *((uint64_t *)&nlp->nlp_portname)) {
7193 			dnp->port_id = nlp->nlp_DID;
7194 			dnp->rpi = nlp->nlp_Rpi;
7195 			dnp->xri = nlp->nlp_Xri;
7196 
7197 			bcopy((char *)&nlp->sparm, (char *)&dnp->sparm,
7198 			    sizeof (dnp->sparm));
7199 
7200 			if (nlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE) {
7201 				dnp->flags |= PORT_FLAG_FCP_TARGET;
7202 			}
7203 			if (nlp->nlp_fcp_info & NLP_FCP_INI_DEVICE) {
7204 				dnp->flags |= PORT_FLAG_FCP_INI;
7205 
7206 			}
7207 			if (nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
7208 				dnp->flags |= PORT_FLAG_FCP2;
7209 			}
7210 			if (cfg[CFG_NETWORK_ON].current && nlp->nlp_Xri) {
7211 				dnp->flags |= PORT_FLAG_IP;
7212 			}
7213 			if (nlp->nlp_fcp_info & NLP_EMLX_VPORT) {
7214 				dnp->flags |= PORT_FLAG_VPORT;
7215 			}
7216 
7217 			/* Copy our dfc_state */
7218 			dnp->flags |= ((nlp->dfc_state & 0xF) << 28);
7219 			dnp->flags |= PORT_FLAG_DFC_STATE_VALID;
7220 
7221 			dnp++;
7222 			node_count++;
7223 			nlp = (NODELIST *) nlp->nlp_list_next;
7224 		}
7225 	}
7226 	rw_exit(&port->node_rwlock);
7227 
7228 	bcopy((void *)&node_count, (void *)dfc->buf2, sizeof (uint32_t));
7229 	return (0);
7230 
7231 } /* emlxs_dfc_get_nodeinfo() */
7232 
7233 
7234 /*ARGSUSED*/
7235 static int32_t
emlxs_dfc_read_mem(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)7236 emlxs_dfc_read_mem(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7237 {
7238 	emlxs_port_t	*port = &PPORT;
7239 	uint32_t	offset;
7240 	uint32_t	size;
7241 	uint32_t	max_size;
7242 	uint8_t		*slim;
7243 
7244 	offset = dfc->data1;
7245 	size = dfc->data2;
7246 
7247 	if (!dfc->buf1 || !dfc->buf1_size) {
7248 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7249 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
7250 
7251 		return (DFC_ARG_NULL);
7252 	}
7253 
7254 	if (size > dfc->buf1_size) {
7255 		size = dfc->buf1_size;
7256 	}
7257 
7258 	if (offset % 4) {
7259 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7260 		    "%s: Offset misaligned. (offset=%d)",
7261 		    emlxs_dfc_xlate(dfc->cmd), offset);
7262 
7263 		return (DFC_ARG_MISALIGNED);
7264 	}
7265 
7266 	if (size % 4) {
7267 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7268 		    "%s: Size misaligned. (size=%d)",
7269 		    emlxs_dfc_xlate(dfc->cmd), size);
7270 
7271 		return (DFC_ARG_MISALIGNED);
7272 	}
7273 
7274 	if (hba->flag & FC_SLIM2_MODE) {
7275 		max_size = SLI2_SLIM2_SIZE;
7276 	} else {
7277 		max_size = 4096;
7278 	}
7279 
7280 	if (offset >= max_size) {
7281 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7282 		    "%s: Offset too large. (offset=%d)",
7283 		    emlxs_dfc_xlate(dfc->cmd), offset);
7284 
7285 		return (DFC_ARG_TOOBIG);
7286 	}
7287 
7288 	if ((size + offset) > max_size) {
7289 		size = (max_size - offset);
7290 	}
7291 
7292 	if (hba->flag & FC_SLIM2_MODE) {
7293 		slim = (uint8_t *)hba->sli.sli3.slim2.virt + offset;
7294 		BE_SWAP32_BCOPY((uint8_t *)slim, (uint8_t *)dfc->buf1, size);
7295 	} else {
7296 		slim = (uint8_t *)hba->sli.sli3.slim_addr + offset;
7297 		READ_SLIM_COPY(hba, (uint32_t *)dfc->buf1, (uint32_t *)slim,
7298 		    (size / 4));
7299 	}
7300 
7301 #ifdef FMA_SUPPORT
7302 	/* Access handle validation */
7303 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
7304 	    != DDI_FM_OK) {
7305 		EMLXS_MSGF(EMLXS_CONTEXT,
7306 		    &emlxs_invalid_access_handle_msg, NULL);
7307 		return (DFC_DRV_ERROR);
7308 	}
7309 #endif  /* FMA_SUPPORT */
7310 
7311 	return (0);
7312 
7313 } /* emlxs_dfc_read_mem() */
7314 
7315 
7316 /*ARGSUSED*/
7317 static int32_t
emlxs_dfc_write_mem(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)7318 emlxs_dfc_write_mem(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7319 {
7320 	emlxs_port_t	*port = &PPORT;
7321 	uint32_t	offset;
7322 	uint32_t	size;
7323 	uint32_t	max_size;
7324 	uint8_t		*slim;
7325 
7326 	offset = dfc->data1;
7327 	size = dfc->data2;
7328 
7329 	if (!dfc->buf1 || !dfc->buf1_size) {
7330 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7331 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
7332 
7333 		return (DFC_ARG_NULL);
7334 	}
7335 
7336 	if (size > dfc->buf1_size) {
7337 		size = dfc->buf1_size;
7338 	}
7339 
7340 	if (offset % 4) {
7341 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7342 		    "%s: Offset misaligned. (offset=%d)",
7343 		    emlxs_dfc_xlate(dfc->cmd), offset);
7344 
7345 		return (DFC_ARG_MISALIGNED);
7346 	}
7347 
7348 	if (size % 4) {
7349 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7350 		    "%s: Size misaligned. (szie=%d)",
7351 		    emlxs_dfc_xlate(dfc->cmd), size);
7352 
7353 		return (DFC_ARG_MISALIGNED);
7354 	}
7355 
7356 	if (hba->flag & FC_SLIM2_MODE) {
7357 		max_size = SLI2_SLIM2_SIZE;
7358 	} else {
7359 		max_size = 4096;
7360 	}
7361 
7362 	if (offset >= max_size) {
7363 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7364 		    "%s: Offset too large. (offset=%d)",
7365 		    emlxs_dfc_xlate(dfc->cmd), offset);
7366 
7367 		return (DFC_ARG_TOOBIG);
7368 	}
7369 
7370 	if ((size + offset) > max_size) {
7371 		size = (max_size - offset);
7372 	}
7373 
7374 	if (hba->flag & FC_SLIM2_MODE) {
7375 		slim = (uint8_t *)hba->sli.sli3.slim2.virt + offset;
7376 		BE_SWAP32_BCOPY((uint8_t *)dfc->buf1, (uint8_t *)slim, size);
7377 	} else {
7378 		slim = (uint8_t *)hba->sli.sli3.slim_addr + offset;
7379 		WRITE_SLIM_COPY(hba, (uint32_t *)dfc->buf1, (uint32_t *)slim,
7380 		    (size / 4));
7381 	}
7382 
7383 #ifdef FMA_SUPPORT
7384 	/* Access handle validation */
7385 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
7386 	    != DDI_FM_OK) {
7387 		EMLXS_MSGF(EMLXS_CONTEXT,
7388 		    &emlxs_invalid_access_handle_msg, NULL);
7389 		return (DFC_DRV_ERROR);
7390 	}
7391 #endif  /* FMA_SUPPORT */
7392 
7393 	return (0);
7394 
7395 } /* emlxs_dfc_write_mem() */
7396 
7397 
7398 /* ARGSUSED */
7399 static int32_t
emlxs_dfc_write_ctlreg(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)7400 emlxs_dfc_write_ctlreg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7401 {
7402 	emlxs_port_t	*port = &PPORT;
7403 	uint32_t	offset;
7404 	uint32_t	value;
7405 
7406 	offset = dfc->data1;
7407 	value = dfc->data2;
7408 
7409 	if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE) {
7410 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7411 		    "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
7412 
7413 		return (DFC_NOT_SUPPORTED);
7414 	}
7415 
7416 	if (!(hba->flag & FC_OFFLINE_MODE)) {
7417 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7418 		    "%s: Adapter not offline.", emlxs_dfc_xlate(dfc->cmd));
7419 
7420 		return (DFC_ONLINE_ERROR);
7421 	}
7422 
7423 	if (offset % 4) {
7424 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7425 		    "%s: Offset misaligned. (offset=%d)",
7426 		    emlxs_dfc_xlate(dfc->cmd), offset);
7427 
7428 		return (DFC_ARG_MISALIGNED);
7429 	}
7430 
7431 	if (offset > 255) {
7432 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7433 		    "%s: Offset too large. (offset=%d)",
7434 		    emlxs_dfc_xlate(dfc->cmd), offset);
7435 
7436 		return (DFC_ARG_TOOBIG);
7437 	}
7438 
7439 	WRITE_CSR_REG(hba, (hba->sli.sli3.csr_addr + offset), value);
7440 
7441 #ifdef FMA_SUPPORT
7442 	/* Access handle validation */
7443 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
7444 	    != DDI_FM_OK) {
7445 		EMLXS_MSGF(EMLXS_CONTEXT,
7446 		    &emlxs_invalid_access_handle_msg, NULL);
7447 		return (DFC_DRV_ERROR);
7448 	}
7449 #endif  /* FMA_SUPPORT */
7450 
7451 	return (0);
7452 
7453 } /* emlxs_dfc_write_ctlreg() */
7454 
7455 
7456 /*ARGSUSED*/
7457 static int32_t
emlxs_dfc_read_ctlreg(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)7458 emlxs_dfc_read_ctlreg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7459 {
7460 	emlxs_port_t	*port = &PPORT;
7461 	uint32_t	offset;
7462 	uint32_t	value;
7463 
7464 	offset = dfc->data1;
7465 
7466 	if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE) {
7467 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7468 		    "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
7469 
7470 		return (DFC_NOT_SUPPORTED);
7471 	}
7472 
7473 	if (offset % 4) {
7474 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7475 		    "%s: Offset misaligned. (offset=%d)",
7476 		    emlxs_dfc_xlate(dfc->cmd), offset);
7477 
7478 		return (DFC_ARG_MISALIGNED);
7479 	}
7480 
7481 	if (offset > 255) {
7482 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7483 		    "%s: Offset too large. (offset=%d)",
7484 		    emlxs_dfc_xlate(dfc->cmd), offset);
7485 
7486 		return (DFC_ARG_TOOBIG);
7487 	}
7488 
7489 	if (!dfc->buf1 || !dfc->buf1_size) {
7490 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7491 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
7492 
7493 		return (DFC_ARG_NULL);
7494 	}
7495 
7496 	if (dfc->buf1_size < sizeof (uint32_t)) {
7497 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7498 		    "%s: Buffer1 too small. (size=%d)",
7499 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7500 
7501 		return (DFC_ARG_TOOSMALL);
7502 	}
7503 
7504 	value = READ_CSR_REG(hba, (hba->sli.sli3.csr_addr + offset));
7505 	bcopy((void *)&value, (void *)dfc->buf1, sizeof (uint32_t));
7506 
7507 #ifdef FMA_SUPPORT
7508 	/* Access handle validation */
7509 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
7510 	    != DDI_FM_OK) {
7511 		EMLXS_MSGF(EMLXS_CONTEXT,
7512 		    &emlxs_invalid_access_handle_msg, NULL);
7513 		return (DFC_DRV_ERROR);
7514 	}
7515 #endif  /* FMA_SUPPORT */
7516 
7517 	return (0);
7518 
7519 } /* emlxs_dfc_read_ctlreg() */
7520 
7521 
7522 /*ARGSUSED*/
7523 static int32_t
emlxs_dfc_set_event(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)7524 emlxs_dfc_set_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7525 {
7526 	emlxs_port_t		*port = &PPORT;
7527 	uint32_t		event;
7528 	uint32_t		enable;
7529 	uint32_t		pid;
7530 	uint32_t		count;
7531 	uint32_t		i;
7532 	emlxs_dfc_event_t	*dfc_event;
7533 
7534 	event = dfc->data1;
7535 	pid = dfc->data2;
7536 	enable = dfc->flag;
7537 
7538 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7539 	    "%s: %s. pid=%d enable=%d", emlxs_dfc_xlate(dfc->cmd),
7540 	    emlxs_dfc_event_xlate(event), pid, enable);
7541 
7542 	switch (event) {
7543 	case FC_REG_LINK_EVENT:
7544 	case FC_REG_RSCN_EVENT:
7545 	case FC_REG_CT_EVENT:
7546 	case FC_REG_DUMP_EVENT:
7547 	case FC_REG_TEMP_EVENT:
7548 	case FC_REG_VPORTRSCN_EVENT:
7549 	case FC_REG_FCOE_EVENT:
7550 		break;
7551 
7552 	case FC_REG_MULTIPULSE_EVENT:
7553 	default:
7554 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7555 		    "%s: %s. Invalid event. pid=%d enable=%d",
7556 		    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event),
7557 		    pid, enable);
7558 
7559 		return (DFC_ARG_INVALID);
7560 	}
7561 
7562 	if (enable) {
7563 		if (dfc->buf1_size < sizeof (uint32_t)) {
7564 			dfc->buf1 = NULL;
7565 		} else if (!dfc->buf1) {
7566 			dfc->buf1_size = 0;
7567 		}
7568 
7569 		/* Make sure this pid/event is not already registered */
7570 		dfc_event = NULL;
7571 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
7572 			dfc_event = &hba->dfc_event[i];
7573 
7574 			if (dfc_event->pid == pid &&
7575 			    dfc_event->event == event) {
7576 				break;
7577 			}
7578 		}
7579 
7580 		if (i == MAX_DFC_EVENTS) {
7581 			/* Find next available event object */
7582 			for (i = 0; i < MAX_DFC_EVENTS; i++) {
7583 				dfc_event = &hba->dfc_event[i];
7584 
7585 				if (!dfc_event->pid && !dfc_event->event) {
7586 					break;
7587 				}
7588 			}
7589 
7590 			/* Return if all event objects are busy */
7591 			if (i == MAX_DFC_EVENTS) {
7592 				EMLXS_MSGF(EMLXS_CONTEXT,
7593 				    &emlxs_dfc_error_msg,
7594 				    "%s: %s. Too many events registered. "
7595 				    "pid=%d enable=%d",
7596 				    emlxs_dfc_xlate(dfc->cmd),
7597 				    emlxs_dfc_event_xlate(event), pid,
7598 				    enable);
7599 
7600 				return (DFC_DRVRES_ERROR);
7601 			}
7602 		}
7603 
7604 		/* Initialize */
7605 		dfc_event->pid = pid;
7606 		dfc_event->event = event;
7607 		dfc_event->last_id = (uint32_t)-1;
7608 		dfc_event->dataout = NULL;
7609 		dfc_event->size = 0;
7610 		dfc_event->mode = 0;
7611 
7612 		emlxs_get_dfc_event(port, dfc_event, 0);
7613 
7614 		if (dfc->buf1) {
7615 			bcopy((void *)&dfc_event->last_id, dfc->buf1,
7616 			    sizeof (uint32_t));
7617 		}
7618 
7619 		/*
7620 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7621 		 * "%s: %s. Enabled. pid=%d id=%d", emlxs_dfc_xlate(dfc->cmd),
7622 		 * emlxs_dfc_event_xlate(event), pid, dfc_event->last_id);
7623 		 */
7624 
7625 		hba->event_mask |= event;
7626 
7627 	} else {	/* Disable */
7628 
7629 		/* Find the event entry */
7630 		dfc_event = NULL;
7631 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
7632 			dfc_event = &hba->dfc_event[i];
7633 
7634 			if (dfc_event->pid == pid &&
7635 			    dfc_event->event == event) {
7636 				break;
7637 			}
7638 		}
7639 
7640 		if (i == MAX_DFC_EVENTS) {
7641 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7642 			    "%s: %s. Event not registered. pid=%d enable=%d",
7643 			    emlxs_dfc_xlate(dfc->cmd),
7644 			    emlxs_dfc_event_xlate(event), pid, enable);
7645 
7646 			return (DFC_ARG_INVALID);
7647 		}
7648 
7649 		/* Kill the event thread if it is sleeping */
7650 		(void) emlxs_kill_dfc_event(port, dfc_event);
7651 
7652 		/* Count the number of pids still registered for this event */
7653 		count = 0;
7654 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
7655 			dfc_event = &hba->dfc_event[i];
7656 
7657 			if (dfc_event->event == event) {
7658 				count++;
7659 			}
7660 		}
7661 
7662 		/* If no more pids need this event, */
7663 		/* then disable logging for this event */
7664 		if (count == 0) {
7665 			hba->event_mask &= ~event;
7666 		}
7667 	}
7668 
7669 	return (0);
7670 
7671 } /* emlxs_dfc_set_event() */
7672 
7673 
7674 /*ARGSUSED*/
7675 static int32_t
emlxs_dfc_get_eventinfo(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)7676 emlxs_dfc_get_eventinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7677 {
7678 	emlxs_port_t	*port = &PPORT;
7679 	uint32_t	size;
7680 	int32_t		rval = 0;
7681 	HBA_EVENTINFO 	*event_buffer = NULL;
7682 	uint32_t	event_count = 0;
7683 	uint32_t	missed = 0;
7684 
7685 	if (!dfc->buf1 || !dfc->buf1_size) {
7686 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7687 		    "%s: Null buffer1 buffer.", emlxs_dfc_xlate(dfc->cmd));
7688 
7689 		return (DFC_ARG_NULL);
7690 	}
7691 
7692 	event_count = dfc->buf1_size / sizeof (HBA_EVENTINFO);
7693 
7694 	if (!event_count) {
7695 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7696 		    "%s: Buffer1 too small. (size=%d)",
7697 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7698 
7699 		return (DFC_ARG_TOOSMALL);
7700 	}
7701 
7702 	if (!dfc->buf2 || !dfc->buf2_size) {
7703 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7704 		    "%s: Null buffer2 buffer.", emlxs_dfc_xlate(dfc->cmd));
7705 
7706 		return (DFC_ARG_NULL);
7707 	}
7708 
7709 	if (dfc->buf2_size < sizeof (uint32_t)) {
7710 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7711 		    "%s: Buffer2 too small. (size=%d)",
7712 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
7713 
7714 		return (DFC_ARG_TOOSMALL);
7715 	}
7716 
7717 	if (!dfc->buf3 || !dfc->buf3_size) {
7718 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7719 		    "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
7720 
7721 		return (DFC_ARG_NULL);
7722 	}
7723 
7724 	if (dfc->buf3_size < sizeof (uint32_t)) {
7725 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7726 		    "%s: Buffer3 too small. (size=%d)",
7727 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
7728 
7729 		return (DFC_ARG_TOOSMALL);
7730 	}
7731 
7732 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s called. max=%d",
7733 	    emlxs_dfc_xlate(dfc->cmd), event_count);
7734 
7735 	size = (event_count * sizeof (HBA_EVENTINFO));
7736 	event_buffer = (HBA_EVENTINFO *)kmem_zalloc(size, KM_SLEEP);
7737 
7738 	if (emlxs_get_dfc_eventinfo(port, event_buffer, &event_count,
7739 	    &missed) != 0) {
7740 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7741 		    "%s: get_dfc_eventinfo failed.",
7742 		    emlxs_dfc_xlate(dfc->cmd));
7743 
7744 		rval = DFC_DRV_ERROR;
7745 		goto done;
7746 	}
7747 
7748 	if (event_count) {
7749 		bcopy((void *)event_buffer, dfc->buf1,
7750 		    (event_count * sizeof (HBA_EVENTINFO)));
7751 	}
7752 
7753 	bcopy((void *)&event_count, dfc->buf2, sizeof (uint32_t));
7754 	bcopy((void *)&missed, dfc->buf3, sizeof (uint32_t));
7755 
7756 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7757 	    "%s: events=%d missed=%d new=%d last_id=%d",
7758 	    emlxs_dfc_xlate(dfc->cmd), event_count, hba->hba_event.missed,
7759 	    hba->hba_event.new, hba->hba_event.last_id);
7760 
7761 done:
7762 
7763 	if (event_buffer) {
7764 		kmem_free(event_buffer, size);
7765 	}
7766 
7767 	return (rval);
7768 
7769 } /* emlxs_dfc_get_eventinfo() */
7770 
7771 
7772 /*ARGSUSED*/
7773 static int32_t
emlxs_dfc_get_event(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)7774 emlxs_dfc_get_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7775 {
7776 	emlxs_port_t		*port = &PPORT;
7777 	uint32_t		event;
7778 	uint32_t		pid;
7779 	uint32_t		sleep;
7780 	uint32_t		i;
7781 	int32_t			rval = DFC_SUCCESS;
7782 	emlxs_dfc_event_t	*dfc_event;
7783 
7784 	event = dfc->data1;
7785 	pid = dfc->data2;
7786 
7787 	if (!dfc->buf1_size) {
7788 		dfc->buf1 = NULL;
7789 	} else if (!dfc->buf1) {
7790 		dfc->buf1_size = 0;
7791 	}
7792 
7793 	if (dfc->buf2_size < sizeof (uint32_t)) {
7794 		dfc->buf2 = NULL;
7795 	} else if (!dfc->buf2) {
7796 		dfc->buf2_size = 0;
7797 	}
7798 
7799 	if (dfc->buf3_size < sizeof (uint32_t)) {
7800 		dfc->buf3 = NULL;
7801 	} else if (!dfc->buf3) {
7802 		dfc->buf3_size = 0;
7803 	}
7804 
7805 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7806 	    "%s: %s. pid=%d size=%d,%p rcv_size=%d,%p id=%d",
7807 	    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event), pid,
7808 	    dfc->buf1_size, dfc->buf1, dfc->buf2_size, dfc->buf2, dfc->data3);
7809 
7810 	/* Find the event entry */
7811 	dfc_event = NULL;
7812 	for (i = 0; i < MAX_DFC_EVENTS; i++) {
7813 		dfc_event = &hba->dfc_event[i];
7814 
7815 		if (dfc_event->pid == pid && dfc_event->event == event) {
7816 			break;
7817 		}
7818 	}
7819 
7820 	if (i == MAX_DFC_EVENTS) {
7821 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7822 		    "%s: %s. Event not registered. pid=%d",
7823 		    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event),
7824 		    pid);
7825 
7826 		return (DFC_ARG_INVALID);
7827 	}
7828 
7829 	if (!(hba->event_mask & dfc_event->event)) {
7830 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7831 		    "%s: %s. Event not registered. pid=%d",
7832 		    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event),
7833 		    pid);
7834 
7835 		return (DFC_ARG_INVALID);
7836 	}
7837 
7838 	/* Initialize event buffer pointers */
7839 	dfc_event->dataout = dfc->buf1;
7840 	dfc_event->size = dfc->buf1_size;
7841 	dfc_event->last_id = dfc->data3;
7842 	dfc_event->mode = mode;
7843 
7844 	sleep = (dfc->flag & 0x01) ? 1 : 0;
7845 
7846 	emlxs_get_dfc_event(port, dfc_event, sleep);
7847 
7848 	if (dfc->buf2) {
7849 		bcopy((void *)&dfc_event->size, dfc->buf2, sizeof (uint32_t));
7850 	}
7851 
7852 	if (dfc->buf3) {
7853 		bcopy((void *)&dfc_event->last_id, dfc->buf3,
7854 		    sizeof (uint32_t));
7855 	}
7856 
7857 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7858 	    "%s: %s. Completed. pid=%d rsize=%d id=%d",
7859 	    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event), pid,
7860 	    dfc_event->size, dfc_event->last_id);
7861 
7862 	return (rval);
7863 
7864 } /* emlxs_dfc_get_event() */
7865 
7866 
7867 extern uint32_t
emlxs_get_dump_region(emlxs_hba_t * hba,uint32_t region,uint8_t * buffer,uint32_t * psize)7868 emlxs_get_dump_region(emlxs_hba_t *hba, uint32_t region,
7869     uint8_t *buffer, uint32_t *psize)
7870 {
7871 	emlxs_port_t	*port = &PPORT;
7872 	uint32_t	size;
7873 	uint32_t	size_only;
7874 	uint32_t	rval = 0;
7875 	uint8_t		*memptr;
7876 	uint32_t	*wptr;
7877 
7878 	if (!buffer || !(*psize)) {
7879 		size_only = 1;
7880 		size = 0xffffffff;
7881 	} else {
7882 		size_only = 0;
7883 		size = *psize;
7884 	}
7885 
7886 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
7887 		if (region != 7) {
7888 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7889 			    "get_dump_region: Invalid sli4 region. "
7890 			    "(id=%d)", region);
7891 
7892 			rval = DFC_ARG_INVALID;
7893 			goto done;
7894 		}
7895 	}
7896 
7897 	switch (region) {
7898 	case 0:	/* SLI Registers */
7899 
7900 		if (size < (4 * sizeof (uint32_t))) {
7901 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7902 			    "get_dump_region: Buffer too small. "
7903 			    "(SLI Registers: size=%d)", size);
7904 
7905 			rval = DFC_ARG_TOOSMALL;
7906 			goto done;
7907 		}
7908 
7909 		size = (4 * sizeof (uint32_t));
7910 
7911 		if (size_only) {
7912 			break;
7913 		}
7914 
7915 		wptr = (uint32_t *)buffer;
7916 		wptr[0] = READ_CSR_REG(hba, FC_HA_REG(hba));
7917 		wptr[1] = READ_CSR_REG(hba, FC_CA_REG(hba));
7918 		wptr[2] = READ_CSR_REG(hba, FC_HS_REG(hba));
7919 		wptr[3] = READ_CSR_REG(hba, FC_HC_REG(hba));
7920 
7921 #ifdef FMA_SUPPORT
7922 		/* Access handle validation */
7923 		if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
7924 		    != DDI_FM_OK) {
7925 			EMLXS_MSGF(EMLXS_CONTEXT,
7926 			    &emlxs_invalid_access_handle_msg, NULL);
7927 			rval = DFC_DRV_ERROR;
7928 		}
7929 #endif  /* FMA_SUPPORT */
7930 
7931 		break;
7932 
7933 	case 1:	/* SLIM */
7934 
7935 		if (hba->flag & FC_SLIM2_MODE) {
7936 			size = MIN(SLI2_SLIM2_SIZE, size);
7937 		} else {
7938 			size = MIN(4096, size);
7939 		}
7940 
7941 		if (size_only) {
7942 			break;
7943 		}
7944 
7945 		if (hba->flag & FC_SLIM2_MODE) {
7946 			memptr = (uint8_t *)hba->sli.sli3.slim2.virt;
7947 			BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer,
7948 			    size);
7949 		} else {
7950 			memptr = (uint8_t *)hba->sli.sli3.slim_addr;
7951 			READ_SLIM_COPY(hba, (uint32_t *)buffer,
7952 			    (uint32_t *)memptr, (size / 4));
7953 #ifdef FMA_SUPPORT
7954 			/* Access handle validation */
7955 			if (emlxs_fm_check_acc_handle(hba,
7956 			    hba->sli.sli3.slim_acc_handle) != DDI_FM_OK) {
7957 				EMLXS_MSGF(EMLXS_CONTEXT,
7958 				    &emlxs_invalid_access_handle_msg, NULL);
7959 				rval = DFC_DRV_ERROR;
7960 			}
7961 #endif  /* FMA_SUPPORT */
7962 		}
7963 
7964 		break;
7965 
7966 	case 2:	/* Port Control Block */
7967 
7968 		if (size < sizeof (PCB)) {
7969 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7970 			    "get_dump_region: Buffer too small. "
7971 			    "(PCB: size=%d)", size);
7972 
7973 			rval = DFC_ARG_TOOSMALL;
7974 			goto done;
7975 		}
7976 
7977 		size = sizeof (PCB);
7978 
7979 		if (size_only) {
7980 			break;
7981 		}
7982 
7983 		memptr = (uint8_t *)&(((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb);
7984 		BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer, size);
7985 		break;
7986 
7987 	case 3:	/* MailBox */
7988 
7989 		if (size < MAILBOX_CMD_BSIZE) {
7990 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7991 			    "get_dump_region: Buffer too small. "
7992 			    "(Mailbox: size=%d)", size);
7993 
7994 			rval = DFC_ARG_TOOSMALL;
7995 			goto done;
7996 		}
7997 
7998 		size = MAILBOX_CMD_BSIZE;
7999 
8000 		if (size_only) {
8001 			break;
8002 		}
8003 
8004 		if (hba->flag & FC_SLIM2_MODE) {
8005 			memptr = (uint8_t *)hba->sli.sli3.slim2.virt;
8006 			BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer,
8007 			    size);
8008 		} else {
8009 			memptr = (uint8_t *)hba->sli.sli3.slim_addr;
8010 			READ_SLIM_COPY(hba, (uint32_t *)buffer,
8011 			    (uint32_t *)memptr, (size / 4));
8012 #ifdef FMA_SUPPORT
8013 			/* Access handle validation */
8014 			if (emlxs_fm_check_acc_handle(hba,
8015 			    hba->sli.sli3.slim_acc_handle) != DDI_FM_OK) {
8016 				EMLXS_MSGF(EMLXS_CONTEXT,
8017 				    &emlxs_invalid_access_handle_msg, NULL);
8018 				rval = DFC_DRV_ERROR;
8019 			}
8020 #endif  /* FMA_SUPPORT */
8021 		}
8022 
8023 		break;
8024 
8025 	case 4:	/* Host Put/Get pointer array */
8026 
8027 		if (size < MAX_RINGS * sizeof (HGP)) {
8028 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8029 			    "get_dump_region: Buffer too small. "
8030 			    "(HGP: size=%d)", size);
8031 
8032 			rval = DFC_ARG_TOOSMALL;
8033 			goto done;
8034 		}
8035 
8036 		size = MAX_RINGS * sizeof (HGP);
8037 
8038 		if (size_only) {
8039 			break;
8040 		}
8041 
8042 		{
8043 			memptr = (uint8_t *)hba->sli.sli3.slim_addr +
8044 			    hba->sli.sli3.hgp_ring_offset;
8045 
8046 			READ_SLIM_COPY(hba, (uint32_t *)buffer,
8047 			    (uint32_t *)memptr, (size / 4));
8048 #ifdef FMA_SUPPORT
8049 			/* Access handle validation */
8050 			if (emlxs_fm_check_acc_handle(hba,
8051 			    hba->sli.sli3.slim_acc_handle) != DDI_FM_OK) {
8052 				EMLXS_MSGF(EMLXS_CONTEXT,
8053 				    &emlxs_invalid_access_handle_msg, NULL);
8054 				rval = DFC_DRV_ERROR;
8055 			}
8056 #endif  /* FMA_SUPPORT */
8057 		}
8058 
8059 		break;
8060 
8061 	case 5:	/* Port  Get/Put pointer array */
8062 
8063 		if (size < MAX_RINGS * sizeof (PGP)) {
8064 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8065 			    "get_dump_region: Buffer too small. "
8066 			    "(PGP: size=%d)", size);
8067 
8068 			rval = DFC_ARG_TOOSMALL;
8069 			goto done;
8070 		}
8071 
8072 		size = MAX_RINGS * sizeof (PGP);
8073 
8074 		if (size_only) {
8075 			break;
8076 		}
8077 
8078 		memptr = (uint8_t *)
8079 		    ((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.port;
8080 		BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer, size);
8081 		break;
8082 
8083 	case 6:	/* Command/Response Ring */
8084 
8085 		if (size < SLI_IOCB_MAX_SIZE) {
8086 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8087 			    "get_dump_region: Buffer too small. "
8088 			    "(Rings: size=%d)", size);
8089 
8090 			rval = DFC_ARG_TOOSMALL;
8091 			goto done;
8092 		}
8093 
8094 		size = SLI_IOCB_MAX_SIZE;
8095 
8096 		if (size_only) {
8097 			break;
8098 		}
8099 
8100 		memptr = (uint8_t *)((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs;
8101 		BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer, size);
8102 		break;
8103 
8104 	case 7:	/* All driver specific structures */
8105 
8106 		if (size < sizeof (emlxs_hba_t)) {
8107 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8108 			    "get_dump_region: Buffer too small. "
8109 			    "(Driver: size=%d)", size);
8110 
8111 			rval = DFC_ARG_TOOSMALL;
8112 			goto done;
8113 		}
8114 
8115 		size = sizeof (emlxs_hba_t);
8116 
8117 		if (size_only) {
8118 			break;
8119 		}
8120 
8121 		memptr = (uint8_t *)hba;
8122 		bcopy((void *)memptr, (void *)buffer, size);
8123 
8124 		break;
8125 
8126 	default:
8127 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8128 		    "get_dump_region: Invalid region. (id=%d)", region);
8129 
8130 		rval = DFC_ARG_INVALID;
8131 	}
8132 
8133 done:
8134 
8135 	*psize = size;
8136 
8137 	return (rval);
8138 
8139 } /* emlxs_get_dump_region() */
8140 
8141 
8142 
8143 /*ARGSUSED*/
8144 static int32_t
emlxs_dfc_get_dump_region(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)8145 emlxs_dfc_get_dump_region(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8146 {
8147 	emlxs_port_t	*port = &PPORT;
8148 	uint32_t	size;
8149 	uint32_t	size_only = 0;
8150 	uint32_t	rval = 0;
8151 
8152 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
8153 	    "%s: region=%d size=%d",
8154 	    emlxs_dfc_xlate(dfc->cmd), dfc->data1, dfc->buf1_size);
8155 
8156 	if (!dfc->buf1 || !dfc->buf1_size) {
8157 		size_only = 1;
8158 	}
8159 
8160 	if (!dfc->buf2 || !dfc->buf2_size) {
8161 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8162 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
8163 
8164 		return (DFC_ARG_NULL);
8165 	}
8166 
8167 	if (dfc->buf2_size < sizeof (uint32_t)) {
8168 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8169 		    "%s: Buffer2 too small. (size=%d)",
8170 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
8171 
8172 		return (DFC_ARG_TOOSMALL);
8173 	}
8174 
8175 	/* First get region size only */
8176 	size = 0;
8177 	rval = emlxs_get_dump_region(hba, dfc->data1, NULL, &size);
8178 
8179 	if (rval != 0) {
8180 		goto done;
8181 	}
8182 
8183 	if (!size_only) {
8184 		if (dfc->buf1_size < size) {
8185 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8186 			    "%s: Buffer1 too small. (size: %d < %d)",
8187 			    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size, size);
8188 
8189 			rval = DFC_ARG_TOOSMALL;
8190 			goto done;
8191 		}
8192 
8193 		/* Get the region data */
8194 		rval = emlxs_get_dump_region(hba, dfc->data1, dfc->buf1, &size);
8195 
8196 		if (rval != 0) {
8197 			goto done;
8198 		}
8199 	}
8200 
8201 	/* Return the region size */
8202 	bcopy((void *) &size, (void *) dfc->buf2, sizeof (uint32_t));
8203 
8204 done:
8205 	return (rval);
8206 
8207 } /* emlxs_dfc_get_dump_region() */
8208 
8209 
8210 
8211 #ifdef MENLO_SUPPORT
8212 /*ARGSUSED*/
8213 static int32_t
emlxs_dfc_menlo_port_offset(emlxs_hba_t * hba)8214 emlxs_dfc_menlo_port_offset(emlxs_hba_t *hba)
8215 {
8216 	uint32_t	cnt;
8217 	char		pathname[256];
8218 
8219 	(void) ddi_pathname(hba->dip, pathname);
8220 	cnt = strlen(pathname);
8221 	if ((cnt < 4) || (strcmp(&pathname[cnt-3], "0,1") != 0))
8222 		return (0);
8223 	return (1);
8224 }
8225 
8226 /*ARGSUSED*/
8227 static int32_t
emlxs_dfc_set_menlo_loopback(emlxs_hba_t * hba)8228 emlxs_dfc_set_menlo_loopback(emlxs_hba_t *hba)
8229 {
8230 	emlxs_port_t *port = &PPORT;
8231 	MAILBOXQ *mbq = NULL;
8232 	MAILBOX *mb = NULL;
8233 	fc_packet_t *pkt = NULL;
8234 	uint32_t mbxstatus;
8235 	uint32_t i;
8236 	uint32_t offset;
8237 	uint32_t rval = 0;
8238 	menlo_cmd_t *cmd;
8239 
8240 	mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
8241 	    KM_SLEEP);
8242 
8243 	mb = (MAILBOX *)mbq;
8244 
8245 	/* SET MENLO maint mode */
8246 	/* Create the set_variable mailbox request */
8247 	emlxs_mb_set_var(hba, mbq, 0x103107, 1);
8248 
8249 	mbq->flag |= MBQ_PASSTHRU;
8250 
8251 	/* issue the mbox cmd to the sli */
8252 	mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8253 
8254 	if (mbxstatus) {
8255 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8256 		    "%s: %s failed. mbxstatus=0x%x",
8257 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8258 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
8259 
8260 		rval = DFC_IO_ERROR;
8261 		if (mbxstatus == MBX_TIMEOUT)
8262 			rval = DFC_TIMEOUT;
8263 		goto done;
8264 	}
8265 
8266 
8267 	/* Wait 30 sec for maint mode */
8268 	i = 0;
8269 	do {
8270 		if (i++ > 300) {
8271 			break;
8272 		}
8273 
8274 		delay(drv_usectohz(100000));
8275 
8276 	} while (!(hba->flag & FC_MENLO_MODE));
8277 
8278 	if (!(hba->flag & FC_MENLO_MODE)) {
8279 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8280 		    "%s: Unable to enter maint mode.",
8281 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8282 
8283 		rval = DFC_DRV_ERROR;
8284 		goto done;
8285 	}
8286 
8287 	offset = emlxs_dfc_menlo_port_offset(hba);
8288 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8289 	    "%s: Entered maint mode. Port offset: %d",
8290 	    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE), offset);
8291 
8292 
8293 	/* Issue Menlo loopback command */
8294 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_cmd_t),
8295 	    sizeof (uint32_t), 0, KM_NOSLEEP))) {
8296 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8297 		    "%s: Unable to allocate packet.",
8298 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8299 
8300 		rval = DFC_SYSRES_ERROR;
8301 		goto done;
8302 	}
8303 
8304 	/* Make this a polled IO */
8305 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
8306 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
8307 	pkt->pkt_comp = NULL;
8308 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
8309 	pkt->pkt_timeout = 30;
8310 
8311 	/* Build the fc header */
8312 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(EMLXS_MENLO_DID);
8313 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
8314 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
8315 	pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
8316 	pkt->pkt_cmd_fhdr.f_ctl =
8317 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
8318 	pkt->pkt_cmd_fhdr.seq_id = 0;
8319 	pkt->pkt_cmd_fhdr.df_ctl = 0;
8320 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
8321 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
8322 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
8323 	pkt->pkt_cmd_fhdr.ro = 0;
8324 
8325 	cmd = (menlo_cmd_t *)pkt->pkt_cmd;
8326 	cmd->code = BE_SWAP32(MENLO_CMD_LOOPBACK);
8327 	cmd->lb.context = BE_SWAP32(offset);
8328 	cmd->lb.type = BE_SWAP32(MENLO_LOOPBACK_ENABLE);
8329 
8330 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
8331 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8332 		    "%s: Unable to send packet.",
8333 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8334 
8335 		rval = DFC_IO_ERROR;
8336 		goto done;
8337 	}
8338 
8339 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
8340 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
8341 			EMLXS_MSGF(EMLXS_CONTEXT,
8342 			    &emlxs_dfc_error_msg,
8343 			    "%s: Pkt Transport error. Pkt Timeout.",
8344 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8345 			rval = DFC_TIMEOUT;
8346 		} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
8347 		    (pkt->pkt_reason == FC_REASON_OVERRUN)) {
8348 			EMLXS_MSGF(EMLXS_CONTEXT,
8349 			    &emlxs_dfc_error_msg,
8350 			    "%s: Pkt Transport error. Rsp overrun.",
8351 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8352 			rval = DFC_RSP_BUF_OVERRUN;
8353 		} else {
8354 			EMLXS_MSGF(EMLXS_CONTEXT,
8355 			    &emlxs_dfc_error_msg,
8356 			    "%s: Pkt Transport error. state=%x",
8357 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8358 			    pkt->pkt_state);
8359 			rval = DFC_IO_ERROR;
8360 		}
8361 		goto done;
8362 	}
8363 
8364 
8365 	/* CLEAR MENLO maint mode */
8366 	/* Create the set_variable mailbox request */
8367 	emlxs_mb_set_var(hba, mbq, 0x103107, 0);
8368 
8369 	mbq->flag |= MBQ_PASSTHRU;
8370 
8371 	/* issue the mbox cmd to the sli */
8372 	mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8373 
8374 	if (mbxstatus) {
8375 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8376 		    "%s: %s failed. mbxstatus=0x%x",
8377 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8378 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
8379 
8380 		rval = DFC_IO_ERROR;
8381 		if (mbxstatus == MBX_TIMEOUT)
8382 			rval = DFC_TIMEOUT;
8383 	}
8384 
8385 	delay(drv_usectohz(1000000));
8386 	i = 0;
8387 	while ((hba->state < FC_LINK_UP) && (hba->state != FC_ERROR)) {
8388 		delay(drv_usectohz(100000));
8389 		i++;
8390 
8391 		if (i == 300) {
8392 			rval = DFC_TIMEOUT;
8393 
8394 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8395 			    "%s: Linkup timeout.",
8396 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8397 
8398 			goto done;
8399 		}
8400 	}
8401 
8402 done:
8403 	/* Free allocated mbox memory */
8404 	if (mbq) {
8405 		kmem_free(mbq, sizeof (MAILBOXQ));
8406 	}
8407 	if (pkt) {
8408 		emlxs_pkt_free(pkt);
8409 	}
8410 	return (rval);
8411 }
8412 
8413 /*ARGSUSED*/
8414 static int32_t
emlxs_dfc_set_menlo_fte(emlxs_hba_t * hba)8415 emlxs_dfc_set_menlo_fte(emlxs_hba_t *hba)
8416 {
8417 	emlxs_port_t *port = &PPORT;
8418 	fc_packet_t *pkt = NULL;
8419 	uint32_t rval = 0;
8420 	menlo_cmd_t *cmd;
8421 
8422 
8423 	/* Issue Menlo loopback command */
8424 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_cmd_t),
8425 	    sizeof (uint32_t), 0, KM_NOSLEEP))) {
8426 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8427 		    "%s: Unable to allocate packet.",
8428 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8429 
8430 		rval = DFC_SYSRES_ERROR;
8431 		goto done;
8432 	}
8433 
8434 	/* Make this a polled IO */
8435 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
8436 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
8437 	pkt->pkt_comp = NULL;
8438 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
8439 	pkt->pkt_timeout = 30;
8440 
8441 	/* Build the fc header */
8442 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(EMLXS_MENLO_DID);
8443 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
8444 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
8445 	pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
8446 	pkt->pkt_cmd_fhdr.f_ctl =
8447 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
8448 	pkt->pkt_cmd_fhdr.seq_id = 0;
8449 	pkt->pkt_cmd_fhdr.df_ctl = 0;
8450 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
8451 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
8452 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
8453 	pkt->pkt_cmd_fhdr.ro = 0;
8454 
8455 	cmd = (menlo_cmd_t *)pkt->pkt_cmd;
8456 	cmd->code = BE_SWAP32(MENLO_CMD_FTE_INSERT);
8457 	cmd->fte_insert.fcid = BE_SWAP32(0);
8458 	bcopy((caddr_t)&port->wwpn, (caddr_t)cmd->fte_insert.wwpn, 8);
8459 
8460 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
8461 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8462 		    "%s: Unable to send packet.",
8463 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8464 
8465 		rval = DFC_IO_ERROR;
8466 		goto done;
8467 	}
8468 
8469 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
8470 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
8471 			EMLXS_MSGF(EMLXS_CONTEXT,
8472 			    &emlxs_dfc_error_msg,
8473 			    "%s: Pkt Transport error. Pkt Timeout.",
8474 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8475 			rval = DFC_TIMEOUT;
8476 		} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
8477 		    (pkt->pkt_reason == FC_REASON_OVERRUN)) {
8478 			EMLXS_MSGF(EMLXS_CONTEXT,
8479 			    &emlxs_dfc_error_msg,
8480 			    "%s: Pkt Transport error. Rsp overrun.",
8481 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8482 			rval = DFC_RSP_BUF_OVERRUN;
8483 		} else {
8484 			EMLXS_MSGF(EMLXS_CONTEXT,
8485 			    &emlxs_dfc_error_msg,
8486 			    "%s: Pkt Transport error. state=%x",
8487 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8488 			    pkt->pkt_state);
8489 			rval = DFC_IO_ERROR;
8490 		}
8491 		goto done;
8492 	}
8493 
8494 
8495 done:
8496 	if (pkt) {
8497 		emlxs_pkt_free(pkt);
8498 	}
8499 	return (rval);
8500 }
8501 
8502 /*ARGSUSED*/
8503 static int32_t
emlxs_dfc_reset_menlo(emlxs_hba_t * hba)8504 emlxs_dfc_reset_menlo(emlxs_hba_t *hba)
8505 {
8506 	emlxs_port_t *port = &PPORT;
8507 	MAILBOXQ *mbq = NULL;
8508 	MAILBOX *mb = NULL;
8509 	uint32_t mbxstatus;
8510 	uint32_t rval = 0;
8511 
8512 	mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
8513 	    KM_SLEEP);
8514 
8515 	mb = (MAILBOX *)mbq;
8516 
8517 	/* RESET MENLO */
8518 	/* Create the set_variable mailbox request */
8519 	emlxs_mb_set_var(hba, mbq, 0x103007, 0);
8520 
8521 	mbq->flag |= MBQ_PASSTHRU;
8522 
8523 	/* issue the mbox cmd to the sli */
8524 	mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8525 
8526 	if (mbxstatus) {
8527 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8528 		    "%s: %s failed. mbxstatus=0x%x",
8529 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8530 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
8531 
8532 		rval = DFC_IO_ERROR;
8533 		if (mbxstatus == MBX_TIMEOUT)
8534 			rval = DFC_TIMEOUT;
8535 		goto done;
8536 	}
8537 done:
8538 	/* Free allocated mbox memory */
8539 	if (mbq) {
8540 		kmem_free(mbq, sizeof (MAILBOXQ));
8541 	}
8542 	return (rval);
8543 }
8544 
8545 #endif /* MENLO_SUPPORT */
8546 
8547 /* ARGSUSED */
8548 static int32_t
emlxs_dfc_loopback_mode(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)8549 emlxs_dfc_loopback_mode(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8550 {
8551 	emlxs_port_t	*port = &PPORT;
8552 	emlxs_config_t	*cfg = &CFG;
8553 	MAILBOXQ	*mbq = NULL;
8554 	MAILBOX		*mb = NULL;
8555 	uint32_t	rval = DFC_SUCCESS;
8556 	uint32_t	i;
8557 	uint32_t	timeout;
8558 	uint32_t	topology;
8559 	uint32_t	speed;
8560 	uint32_t	new_mode;
8561 	NODELIST	*ndlp;
8562 	XRIobj_t	*xrip;
8563 
8564 	if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE) {
8565 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8566 		    "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
8567 
8568 		return (DFC_NOT_SUPPORTED);
8569 	}
8570 
8571 	/* Reinitialize the link */
8572 	switch (dfc->flag) {
8573 	case 0:	/* Disable */
8574 
8575 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8576 		    "%s: Disabling Loopback.", emlxs_dfc_xlate(dfc->cmd));
8577 
8578 		if (!(hba->flag & FC_LOOPBACK_MODE)) {
8579 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8580 			    "%s: Loopback already disabled.",
8581 			    emlxs_dfc_xlate(dfc->cmd));
8582 
8583 			return (rval);
8584 		}
8585 		goto resetdone;
8586 
8587 	case 1:	/* Internal loopback */
8588 		new_mode = FC_ILB_MODE;
8589 		topology = FLAGS_LOCAL_LB;
8590 		speed = 0;
8591 
8592 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8593 		    "%s: Enabling ILB.", emlxs_dfc_xlate(dfc->cmd));
8594 
8595 		/* Check if mode already set */
8596 		if ((hba->flag & FC_ILB_MODE)) {
8597 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8598 			    "%s: ILB mode already enabled.",
8599 			    emlxs_dfc_xlate(dfc->cmd));
8600 
8601 			return (rval);
8602 		}
8603 
8604 		break;
8605 
8606 	case 2:	/* External loopback */
8607 		new_mode = FC_ELB_MODE;
8608 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
8609 			topology = FLAGS_TOPOLOGY_MODE_LOOP_PT;
8610 		} else {
8611 			topology = FLAGS_TOPOLOGY_MODE_LOOP;
8612 		}
8613 		speed = cfg[CFG_LINK_SPEED].current;
8614 
8615 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8616 		    "%s: Enabling ELB.", emlxs_dfc_xlate(dfc->cmd));
8617 
8618 		/* Check if mode already set */
8619 		if ((hba->flag & FC_ELB_MODE)) {
8620 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8621 			    "%s: ELB mode already enabled.",
8622 			    emlxs_dfc_xlate(dfc->cmd));
8623 
8624 			return (rval);
8625 		}
8626 
8627 		break;
8628 
8629 	default:
8630 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8631 		    "%s: Invalid loopback mode. (mode=%x)",
8632 		    emlxs_dfc_xlate(dfc->cmd), dfc->flag);
8633 
8634 		return (DFC_ARG_INVALID);
8635 	}
8636 
8637 	/* Make sure adapter is online */
8638 	if (emlxs_online(hba)) {
8639 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8640 		    "%s: Unable to bring adapter online.",
8641 		    emlxs_dfc_xlate(dfc->cmd));
8642 
8643 		return (DFC_OFFLINE_ERROR);
8644 	}
8645 
8646 #ifdef MENLO_SUPPORT
8647 	if (hba->model_info.vendor_id == PCI_VENDOR_ID_EMULEX &&
8648 	    hba->model_info.device_id == PCI_DEVICE_ID_HORNET) {
8649 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8650 		    "%s: Menlo support detected: mode:x%x",
8651 		    emlxs_dfc_xlate(dfc->cmd), new_mode);
8652 
8653 		if (new_mode == FC_ILB_MODE) {
8654 			rval = emlxs_dfc_set_menlo_loopback(hba);
8655 			if (rval)
8656 				goto done;
8657 		}
8658 	}
8659 #endif /* MENLO_SUPPORT */
8660 
8661 	mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
8662 	    KM_SLEEP);
8663 
8664 	mb = (MAILBOX *) mbq;
8665 
8666 	/* Take the link down */
8667 	emlxs_mb_down_link(hba, mbq);
8668 
8669 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8670 
8671 	if (rval == MBX_TIMEOUT) {
8672 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8673 		    "%s: Mailbox timed out. cmd=%x",
8674 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
8675 
8676 		rval = DFC_TIMEOUT;
8677 		goto done;
8678 	}
8679 
8680 	if (rval) {
8681 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8682 		    "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
8683 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
8684 
8685 		rval = DFC_IO_ERROR;
8686 		goto done;
8687 	}
8688 
8689 	/*
8690 	 * Need *2 since we wait 1/2 sec in while loop.
8691 	 */
8692 	timeout = dfc->data1;
8693 	if (!timeout) {
8694 		timeout = 60 * 2;
8695 	} else {
8696 		timeout = timeout * 2;
8697 	}
8698 
8699 	i = 0;
8700 	while ((hba->state >= FC_LINK_UP) && (hba->state != FC_ERROR)) {
8701 		delay(drv_usectohz(500000));
8702 		i++;
8703 
8704 		if (i == timeout) {
8705 			rval = DFC_TIMEOUT;
8706 
8707 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8708 			    "%s: Linkdown timeout.", emlxs_dfc_xlate(dfc->cmd));
8709 
8710 			goto done;
8711 		}
8712 	}
8713 
8714 	/* Reinitialize the link */
8715 	emlxs_mb_init_link(hba, mbq, topology, speed);
8716 
8717 	/* Set the loopback mode and timer */
8718 	mutex_enter(&EMLXS_PORT_LOCK);
8719 	hba->flag |= new_mode;
8720 	hba->loopback_tics = hba->timer_tics + emlxs_loopback_tmo;
8721 	mutex_exit(&EMLXS_PORT_LOCK);
8722 
8723 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8724 
8725 	if (rval == MBX_TIMEOUT) {
8726 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8727 		    "%s: Mailbox timed out. cmd=%x",
8728 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
8729 
8730 		rval = DFC_TIMEOUT;
8731 		goto done;
8732 	}
8733 
8734 	if (rval) {
8735 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8736 		    "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
8737 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
8738 
8739 		rval = DFC_IO_ERROR;
8740 		goto done;
8741 	}
8742 
8743 	i = 0;
8744 	while ((hba->state < FC_LINK_UP) && (hba->state != FC_ERROR)) {
8745 		delay(drv_usectohz(500000));
8746 		i++;
8747 
8748 		if (i == timeout) {
8749 			rval = DFC_TIMEOUT;
8750 
8751 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8752 			    "%s: Linkup timeout.", emlxs_dfc_xlate(dfc->cmd));
8753 
8754 			goto done;
8755 		}
8756 	}
8757 
8758 	/* Create host node */
8759 	if (EMLXS_SLI_REG_DID(port, port->did, (SERV_PARM *)&hba->sparam,
8760 	    NULL, NULL, NULL)) {
8761 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8762 		    "%s: Unable to register host node.",
8763 		    emlxs_dfc_xlate(dfc->cmd));
8764 
8765 		rval = DFC_DRV_ERROR;
8766 		goto done;
8767 	}
8768 
8769 	i = 0;
8770 	do {
8771 		if (i++ > 300) {
8772 			break;
8773 		}
8774 
8775 		delay(drv_usectohz(100000));
8776 
8777 	} while (!(ndlp = emlxs_node_find_did(port, port->did, 1)));
8778 
8779 	if (!ndlp) {
8780 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8781 		    "%s: Unable to create host node.",
8782 		    emlxs_dfc_xlate(dfc->cmd));
8783 
8784 		rval = DFC_DRV_ERROR;
8785 		goto done;
8786 	}
8787 
8788 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8789 	    "%s: Node created. node=%p", emlxs_dfc_xlate(dfc->cmd), ndlp);
8790 
8791 #ifdef MENLO_SUPPORT
8792 	if (hba->model_info.vendor_id == PCI_VENDOR_ID_EMULEX &&
8793 	    hba->model_info.device_id == PCI_DEVICE_ID_HORNET) {
8794 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8795 		    "%s: Menlo support detected: mode:x%x",
8796 		    emlxs_dfc_xlate(dfc->cmd), new_mode);
8797 
8798 		rval = emlxs_dfc_set_menlo_fte(hba);
8799 		if (rval)
8800 			goto done;
8801 	}
8802 #endif /* MENLO_SUPPORT */
8803 
8804 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
8805 		/* Create host XRI */
8806 		(void) emlxs_create_xri(port, &hba->chan[hba->channel_ct],
8807 		    ndlp);
8808 
8809 		i = 0;
8810 		do {
8811 			if (i++ > 300) {
8812 				break;
8813 			}
8814 
8815 			delay(drv_usectohz(100000));
8816 
8817 		} while (!ndlp->nlp_Xri);
8818 
8819 		if (!ndlp->nlp_Xri) {
8820 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8821 			    "%s: Unable to create XRI.",
8822 			    emlxs_dfc_xlate(dfc->cmd));
8823 
8824 			rval = DFC_DRV_ERROR;
8825 			goto done;
8826 		}
8827 
8828 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8829 		    "%s: XRI created. xri=%d", emlxs_dfc_xlate(dfc->cmd),
8830 		    ndlp->nlp_Xri);
8831 	} else {
8832 		xrip = emlxs_sli4_reserve_xri(port,
8833 		    EMLXS_NODE_TO_RPI(port, ndlp),
8834 		    EMLXS_XRI_SOL_CT_TYPE, 0xffff);
8835 
8836 		if (xrip == NULL) {
8837 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8838 			    "%s: Unable to reserve XRI.",
8839 			    emlxs_dfc_xlate(dfc->cmd));
8840 
8841 			rval = DFC_DRV_ERROR;
8842 			goto done;
8843 		}
8844 
8845 		ndlp->nlp_Xri = xrip->XRI;
8846 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8847 		    "%s: XRI reserved. xri=%d", emlxs_dfc_xlate(dfc->cmd),
8848 		    ndlp->nlp_Xri);
8849 	}
8850 
8851 done:
8852 	/* Free allocated mbox memory */
8853 	if (mbq) {
8854 		kmem_free(mbq, sizeof (MAILBOXQ));
8855 	}
8856 
8857 	if (rval) {
8858 resetdone:
8859 		/* Reset the adapter */
8860 #ifdef MENLO_SUPPORT
8861 		if (hba->model_info.vendor_id == PCI_VENDOR_ID_EMULEX &&
8862 		    hba->model_info.device_id == PCI_DEVICE_ID_HORNET) {
8863 
8864 			rval = emlxs_dfc_reset_menlo(hba);
8865 
8866 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8867 			    "%s: Menlo reset: rval:x%x",
8868 			    emlxs_dfc_xlate(dfc->cmd), rval);
8869 	}
8870 #endif /* MENLO_SUPPORT */
8871 
8872 		/* Reset link whether we are bound to ULP or not */
8873 		(void) emlxs_reset_link(hba, 1, 1);
8874 	}
8875 
8876 	return (rval);
8877 } /* emlxs_dfc_loopback_mode() */
8878 
8879 
8880 /*ARGSUSED*/
8881 static int32_t
emlxs_dfc_loopback_test(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)8882 emlxs_dfc_loopback_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8883 {
8884 	emlxs_port_t	*port = &PPORT;
8885 	int32_t		rval = 0;
8886 	NODELIST	*ndlp;
8887 	clock_t		timeout;
8888 	fc_packet_t	*pkt = NULL;
8889 	SLI_CT_REQUEST	*CtCmd;
8890 	uint16_t	CtRsp;
8891 
8892 	if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE) {
8893 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8894 		    "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
8895 
8896 		return (DFC_NOT_SUPPORTED);
8897 	}
8898 
8899 	mutex_enter(&EMLXS_PORT_LOCK);
8900 	if (!(hba->flag & FC_LOOPBACK_MODE)) {
8901 		mutex_exit(&EMLXS_PORT_LOCK);
8902 
8903 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8904 		    "%s: Adapter not in loopback mode.",
8905 		    emlxs_dfc_xlate(dfc->cmd));
8906 
8907 		rval = DFC_DRV_ERROR;
8908 		goto done;
8909 	}
8910 	hba->loopback_tics = hba->timer_tics + emlxs_loopback_tmo;
8911 	mutex_exit(&EMLXS_PORT_LOCK);
8912 
8913 	if (!(hba->flag & FC_ONLINE_MODE)) {
8914 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8915 		    "%s: Adapter offline.", emlxs_dfc_xlate(dfc->cmd));
8916 
8917 		rval = DFC_OFFLINE_ERROR;
8918 		goto done;
8919 	}
8920 
8921 	if (hba->state < FC_LINK_UP) {
8922 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8923 		    "%s: Link not up.", emlxs_dfc_xlate(dfc->cmd));
8924 
8925 		rval = DFC_OFFLINE_ERROR;
8926 		goto done;
8927 	}
8928 
8929 	if (!dfc->buf1 || !dfc->buf1_size) {
8930 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8931 		    "%s: NULL buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
8932 
8933 		rval = DFC_ARG_NULL;
8934 		goto done;
8935 	}
8936 
8937 	if (!dfc->buf2 || !dfc->buf2_size) {
8938 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8939 		    "%s: NULL buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
8940 
8941 		rval = DFC_ARG_NULL;
8942 		goto done;
8943 	}
8944 
8945 	if (dfc->buf1_size > MAX_CT_PAYLOAD) {
8946 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8947 		    "%s: Buffer1 too large. (size=%d)",
8948 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
8949 
8950 		rval = DFC_ARG_TOOBIG;
8951 		goto done;
8952 	}
8953 
8954 	/* Check if we have a node for ourselves */
8955 	ndlp = emlxs_node_find_did(port, port->did, 1);
8956 
8957 	if (!ndlp) {
8958 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8959 		    "%s: Host node not found.", emlxs_dfc_xlate(dfc->cmd));
8960 
8961 		rval = DFC_ARG_INVALID;
8962 		goto done;
8963 	}
8964 
8965 	if (!ndlp->nlp_Xri) {
8966 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8967 		    "%s: Host XRI not found.", emlxs_dfc_xlate(dfc->cmd));
8968 
8969 		rval = DFC_DRV_ERROR;
8970 		goto done;
8971 	}
8972 
8973 	pkt = emlxs_pkt_alloc(port, dfc->buf1_size + 16,
8974 	    dfc->buf2_size + 16, 0, KM_SLEEP);
8975 
8976 	if (pkt == NULL) {
8977 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8978 		    "%s: Unable to allocate pkt.", emlxs_dfc_xlate(dfc->cmd));
8979 		rval = DFC_SYSRES_ERROR;
8980 		goto done;
8981 	}
8982 
8983 	CtCmd = (SLI_CT_REQUEST*)pkt->pkt_cmd;
8984 	CtRsp = SLI_CT_LOOPBACK;
8985 	CtCmd->CommandResponse.bits.CmdRsp = LE_SWAP16(CtRsp);
8986 
8987 	bcopy((void *)dfc->buf1, (void *)&CtCmd->un.data, dfc->buf1_size);
8988 
8989 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
8990 	pkt->pkt_timeout = 2 * hba->fc_ratov;
8991 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
8992 	pkt->pkt_comp = NULL;
8993 
8994 	pkt->pkt_cmd_fhdr.d_id = port->did;
8995 	pkt->pkt_cmd_fhdr.r_ctl = FC_SOL_CTL;
8996 	pkt->pkt_cmd_fhdr.s_id = port->did;
8997 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
8998 	pkt->pkt_cmd_fhdr.f_ctl = 0;
8999 	pkt->pkt_cmd_fhdr.seq_id = 0;
9000 	pkt->pkt_cmd_fhdr.df_ctl = 0;
9001 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
9002 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
9003 	pkt->pkt_cmd_fhdr.rx_id = ndlp->nlp_Xri;
9004 	pkt->pkt_cmd_fhdr.ro = 0;
9005 
9006 	mutex_enter(&EMLXS_PKT_LOCK);
9007 	timeout = emlxs_timeout(hba, (pkt->pkt_timeout + 15));
9008 
9009 	if (hba->loopback_pkt) {
9010 		rval = 0;
9011 		while ((rval != -1) && hba->loopback_pkt) {
9012 			rval =
9013 			    cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK,
9014 			    timeout);
9015 		}
9016 
9017 		if (rval == -1) {
9018 			mutex_exit(&EMLXS_PKT_LOCK);
9019 
9020 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9021 			    "Loopback busy timeout.");
9022 			rval = DFC_TIMEOUT;
9023 			goto done;
9024 		}
9025 	}
9026 	hba->loopback_pkt = (void *) pkt;
9027 	mutex_exit(&EMLXS_PKT_LOCK);
9028 
9029 	/* Send polled command */
9030 	if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) {
9031 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9032 		    "Pkt Transport error. ret=%x state=%x", rval,
9033 		    pkt->pkt_state);
9034 
9035 		rval = DFC_IO_ERROR;
9036 		goto done;
9037 	}
9038 
9039 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
9040 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
9041 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9042 			    "Pkt Transport error. Pkt Timeout.");
9043 			rval = DFC_TIMEOUT;
9044 		} else {
9045 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9046 			    "Pkt Transport error. state=%x", pkt->pkt_state);
9047 			rval = DFC_IO_ERROR;
9048 		}
9049 		goto done;
9050 	}
9051 
9052 	/* Wait for sequence completion */
9053 	mutex_enter(&EMLXS_PKT_LOCK);
9054 	rval = 0;
9055 	while ((rval != -1) && !(pkt->pkt_tran_flags & FC_TRAN_COMPLETED)) {
9056 		rval = cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK, timeout);
9057 	}
9058 	mutex_exit(&EMLXS_PKT_LOCK);
9059 
9060 	if (rval == -1) {
9061 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9062 		    "Loopback sequence timeout.");
9063 
9064 		rval = DFC_TIMEOUT;
9065 		goto done;
9066 	}
9067 
9068 	CtCmd = (SLI_CT_REQUEST*)pkt->pkt_resp;
9069 	bcopy((void *)&CtCmd->un.data, (void *)dfc->buf2, dfc->buf2_size);
9070 
9071 	rval = 0;
9072 
9073 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, "%s: Test completed.",
9074 	    emlxs_dfc_xlate(dfc->cmd));
9075 
9076 done:
9077 
9078 	if (rval) {
9079 		mutex_enter(&EMLXS_PKT_LOCK);
9080 		if (pkt && (hba->loopback_pkt == pkt)) {
9081 			hba->loopback_pkt = NULL;
9082 		}
9083 		mutex_exit(&EMLXS_PKT_LOCK);
9084 
9085 		/* Reset the adapter */
9086 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
9087 	}
9088 
9089 	if (pkt) {
9090 		emlxs_pkt_free(pkt);
9091 	}
9092 
9093 	return (rval);
9094 
9095 } /* emlxs_dfc_loopback_test() */
9096 
9097 
9098 /*ARGSUSED*/
9099 static int32_t
emlxs_dfc_reset_port(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9100 emlxs_dfc_reset_port(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9101 {
9102 	emlxs_port_t	*port = &PPORT;
9103 	int32_t		rval = 0;
9104 
9105 	switch (dfc->flag) {
9106 	case 1:
9107 	case 2:
9108 		rval = emlxs_reset(port, FC_FCA_RESET);
9109 		break;
9110 	case 3:
9111 		if ((hba->sli_mode < EMLXS_HBA_SLI4_MODE) ||
9112 		    ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) &&
9113 		    (hba->model_info.chip & EMLXS_BE_CHIPS))) {
9114 			rval = emlxs_reset(port, FC_FCA_RESET);
9115 		} else {
9116 			/* Perform All Firmware Reset */
9117 			rval = emlxs_reset(port, EMLXS_DFC_RESET_ALL);
9118 		}
9119 
9120 		break;
9121 
9122 	default:
9123 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9124 		    "%s: Invalid reset type. (mode=%x)",
9125 		    emlxs_dfc_xlate(dfc->cmd), dfc->flag);
9126 
9127 		return (DFC_ARG_INVALID);
9128 	}
9129 
9130 	if (rval) {
9131 		rval = DFC_HBA_ERROR;
9132 	}
9133 	return (rval);
9134 
9135 } /* emlxs_dfc_reset_port() */
9136 
9137 
9138 extern int32_t
emlxs_dfc_handle_event(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)9139 emlxs_dfc_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
9140 {
9141 	emlxs_port_t	*port = &PPORT;
9142 	IOCB		*cmd;
9143 	emlxs_buf_t	*sbp;
9144 
9145 	cmd = &iocbq->iocb;
9146 
9147 	HBASTATS.CtEvent++;
9148 
9149 	sbp = (emlxs_buf_t *)iocbq->sbp;
9150 
9151 	if (!sbp) {
9152 		HBASTATS.CtStray++;
9153 
9154 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9155 		    "Stray interrupt. cmd=0x%x iotag=0x%x status=0x%x "
9156 		    "perr=0x%x", (uint32_t)cmd->ULPCOMMAND,
9157 		    (uint32_t)cmd->ULPIOTAG, cmd->ULPSTATUS,
9158 		    cmd->un.ulpWord[4]);
9159 
9160 		return (DFC_ARG_INVALID);
9161 	}
9162 
9163 	if (cp->channelno != hba->channel_ct) {
9164 		HBASTATS.CtStray++;
9165 
9166 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9167 		    "CT Event: Invalid IO Channel:%d iocbq=%p", cp->channelno,
9168 		    iocbq);
9169 
9170 		return (DFC_ARG_INVALID);
9171 	}
9172 
9173 	switch (cmd->ULPCOMMAND) {
9174 	case CMD_XMIT_SEQUENCE_CR:
9175 	case CMD_XMIT_SEQUENCE64_CR:
9176 	case CMD_XMIT_SEQUENCE_CX:
9177 	case CMD_XMIT_SEQUENCE64_CX:
9178 
9179 		HBASTATS.CtCmdCompleted++;
9180 
9181 		if (cmd->ULPSTATUS == 0) {
9182 			HBASTATS.CtCmdGood++;
9183 
9184 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
9185 			    "XMIT_SEQUENCE comp: status=0x%x",
9186 			    cmd->ULPSTATUS);
9187 		} else {
9188 			HBASTATS.CtCmdError++;
9189 
9190 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9191 			    "XMIT_SEQUENCE comp: status=0x%x [%08x,%08x]",
9192 			    cmd->ULPSTATUS, cmd->un.ulpWord[4],
9193 			    cmd->un.ulpWord[5]);
9194 		}
9195 
9196 		emlxs_pkt_complete(sbp, cmd->ULPSTATUS,
9197 		    cmd->un.grsp.perr.statLocalError, 1);
9198 
9199 		break;
9200 
9201 	default:
9202 
9203 		HBASTATS.CtStray++;
9204 
9205 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9206 		    "Invalid iocb: cmd=0x%x", cmd->ULPCOMMAND);
9207 
9208 		emlxs_pkt_complete(sbp, cmd->ULPSTATUS,
9209 		    cmd->un.grsp.perr.statLocalError, 1);
9210 
9211 		break;
9212 
9213 	}	/* switch(cmd->ULPCOMMAND) */
9214 
9215 	return (0);
9216 
9217 } /* emlxs_dfc_handle_event() */
9218 
9219 
9220 /* ARGSUSED */
9221 extern int
emlxs_dfc_handle_unsol_req(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)9222 emlxs_dfc_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
9223     MATCHMAP *mp, uint32_t size)
9224 {
9225 	emlxs_hba_t	*hba = HBA;
9226 	IOCB		*iocb;
9227 	uint8_t		*bp;
9228 	fc_packet_t	*pkt;
9229 
9230 	iocb = &iocbq->iocb;
9231 	bp = (uint8_t *)mp->virt;
9232 
9233 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
9234 	    "CT Receive: cmd=%x status=0x%x ",
9235 	    iocb->ULPCOMMAND, iocb->ULPSTATUS);
9236 
9237 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
9238 		/*
9239 		 * No response sent on loopback; free the exchange now
9240 		 */
9241 		emlxs_abort_ct_exchange(hba, port, iocb->ULPCONTEXT);
9242 	}
9243 
9244 	/*
9245 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
9246 	 * "CT Receive: payload=%p size=%d [%02x,%02x, %02x, %02x]", bp,
9247 	 * size, bp[0], bp[1], bp[2],bp[3]);
9248 	 */
9249 
9250 	/* Return payload */
9251 	mutex_enter(&EMLXS_PKT_LOCK);
9252 	if (hba->loopback_pkt) {
9253 		pkt = (fc_packet_t *)hba->loopback_pkt;
9254 		hba->loopback_pkt = NULL;
9255 
9256 		size = MIN(size, pkt->pkt_rsplen);
9257 		bcopy(bp, pkt->pkt_resp, size);
9258 		pkt->pkt_tran_flags |= FC_TRAN_COMPLETED;
9259 
9260 		cv_broadcast(&EMLXS_PKT_CV);
9261 	}
9262 	mutex_exit(&EMLXS_PKT_LOCK);
9263 
9264 	return (0);
9265 
9266 } /* emlxs_dfc_handle_unsol_req() */
9267 
9268 
9269 #ifdef DHCHAP_SUPPORT
9270 
9271 /*ARGSUSED*/
9272 static int32_t
emlxs_dfc_init_auth(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9273 emlxs_dfc_init_auth(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9274 {
9275 	emlxs_port_t	*port = &PPORT;
9276 	uint8_t		*lwwpn;
9277 	uint8_t		*rwwpn;
9278 	int32_t		rval = 0;
9279 
9280 	if (!dfc->buf1 || !dfc->buf1_size) {
9281 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9282 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9283 
9284 		return (DFC_ARG_NULL);
9285 	}
9286 
9287 	if (dfc->buf1_size < 8) {
9288 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9289 		    "%s: Buffer1 too small. (size=%d)",
9290 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9291 
9292 		return (DFC_ARG_TOOSMALL);
9293 	}
9294 
9295 	if (!dfc->buf2 || !dfc->buf2_size) {
9296 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9297 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
9298 
9299 		return (DFC_ARG_NULL);
9300 	}
9301 
9302 	if (dfc->buf2_size < 8) {
9303 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9304 		    "%s: Buffer2 too small. (size=%d)",
9305 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9306 
9307 		return (DFC_ARG_TOOSMALL);
9308 	}
9309 
9310 	lwwpn = (uint8_t *)dfc->buf1;
9311 	rwwpn = (uint8_t *)dfc->buf2;
9312 
9313 	/* Initiate authentication here */
9314 	rval = emlxs_dhc_init_auth(hba, lwwpn, rwwpn);
9315 
9316 	return (rval);
9317 
9318 } /* emlxs_dfc_init_auth() */
9319 
9320 
9321 /*ARGSUSED*/
9322 static int32_t
emlxs_dfc_get_auth_cfg(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9323 emlxs_dfc_get_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9324 {
9325 	emlxs_port_t		*port = &PPORT;
9326 	dfc_fcsp_config_t	*fcsp_config;
9327 	uint32_t		rval = DFC_SUCCESS;
9328 
9329 	if (!dfc->buf1 || !dfc->buf1_size) {
9330 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9331 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9332 
9333 		return (DFC_ARG_NULL);
9334 	}
9335 
9336 	if (dfc->buf1_size < sizeof (dfc_fcsp_config_t)) {
9337 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9338 		    "%s: Buffer1 too small. (size=%d)",
9339 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9340 
9341 		return (DFC_ARG_TOOSMALL);
9342 	}
9343 
9344 	fcsp_config = (dfc_fcsp_config_t *)dfc->buf1;
9345 
9346 	if ((rval = emlxs_dhc_get_auth_cfg(hba, fcsp_config)) != 0) {
9347 		return (rval);
9348 	}
9349 
9350 	return (0);
9351 
9352 } /* emlxs_dfc_get_auth_cfg() */
9353 
9354 
9355 
9356 /*ARGSUSED*/
9357 static int32_t
emlxs_dfc_set_auth_cfg(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9358 emlxs_dfc_set_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9359 {
9360 	emlxs_port_t		*port = &PPORT;
9361 	dfc_fcsp_config_t	*fcsp_config;
9362 	dfc_password_t		*dfc_pwd;
9363 	uint32_t		rval = DFC_SUCCESS;
9364 
9365 	if (!dfc->buf1 || !dfc->buf1_size) {
9366 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9367 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9368 
9369 		return (DFC_ARG_NULL);
9370 	}
9371 
9372 	if (dfc->buf1_size < sizeof (dfc_fcsp_config_t)) {
9373 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9374 		    "%s: Buffer1 too small. (size=%d)",
9375 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9376 
9377 		return (DFC_ARG_TOOSMALL);
9378 	}
9379 
9380 	if (!dfc->buf2 || !dfc->buf2_size) {
9381 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9382 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
9383 
9384 		return (DFC_ARG_NULL);
9385 	}
9386 
9387 	if (dfc->buf2_size < sizeof (dfc_password_t)) {
9388 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9389 		    "%s: Buffer2 too small. (size=%d)",
9390 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9391 
9392 		return (DFC_ARG_TOOSMALL);
9393 	}
9394 
9395 	fcsp_config = (dfc_fcsp_config_t *)dfc->buf1;
9396 	dfc_pwd = (dfc_password_t *)dfc->buf2;
9397 
9398 	switch (dfc->flag) {
9399 	case EMLXS_AUTH_CFG_ADD:
9400 		rval = emlxs_dhc_add_auth_cfg(hba, fcsp_config, dfc_pwd);
9401 		break;
9402 
9403 	case EMLXS_AUTH_CFG_DELETE:
9404 		rval = emlxs_dhc_delete_auth_cfg(hba, fcsp_config, dfc_pwd);
9405 		break;
9406 	}
9407 
9408 	if (rval) {
9409 		return (rval);
9410 	}
9411 
9412 	return (0);
9413 
9414 } /* emlxs_dfc_set_auth_cfg() */
9415 
9416 
9417 
9418 /*ARGSUSED*/
9419 static int32_t
emlxs_dfc_get_auth_pwd(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9420 emlxs_dfc_get_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9421 {
9422 	emlxs_port_t		*port = &PPORT;
9423 	dfc_auth_password_t	*dfc_pwd;
9424 	uint32_t		rval = DFC_SUCCESS;
9425 
9426 	if (!dfc->buf1 || !dfc->buf1_size) {
9427 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9428 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9429 
9430 		return (DFC_ARG_NULL);
9431 	}
9432 
9433 	if (dfc->buf1_size < sizeof (dfc_auth_password_t)) {
9434 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9435 		    "%s: Buffer1 too small. (size=%d)",
9436 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9437 
9438 		return (DFC_ARG_TOOSMALL);
9439 	}
9440 
9441 	/* Read the auth password */
9442 	dfc_pwd = (dfc_auth_password_t *)dfc->buf1;
9443 
9444 	if ((rval = emlxs_dhc_get_auth_key(hba, dfc_pwd)) != 0) {
9445 		return (rval);
9446 	}
9447 
9448 	return (0);
9449 
9450 } /* emlxs_dfc_get_auth_pwd() */
9451 
9452 
9453 /*ARGSUSED*/
9454 static int32_t
emlxs_dfc_set_auth_pwd(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9455 emlxs_dfc_set_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9456 {
9457 	emlxs_port_t		*port = &PPORT;
9458 	dfc_auth_password_t	*dfc_pwd;
9459 	uint32_t		rval = DFC_SUCCESS;
9460 
9461 	if (!dfc->buf1 || !dfc->buf1_size) {
9462 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9463 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9464 
9465 		return (DFC_ARG_NULL);
9466 	}
9467 
9468 	if (dfc->buf1_size < sizeof (dfc_auth_password_t)) {
9469 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9470 		    "%s: Buffer1 too small. (size=%d)",
9471 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9472 
9473 		return (DFC_ARG_TOOSMALL);
9474 	}
9475 
9476 	dfc_pwd = (dfc_auth_password_t *)dfc->buf1;
9477 
9478 	if ((rval = emlxs_dhc_set_auth_key(hba, dfc_pwd))) {
9479 		return (rval);
9480 	}
9481 
9482 	return (0);
9483 
9484 } /* emlxs_dfc_set_auth_pwd() */
9485 
9486 
9487 /*ARGSUSED*/
9488 static int32_t
emlxs_dfc_get_auth_status(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9489 emlxs_dfc_get_auth_status(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9490 {
9491 	emlxs_port_t		*port = &PPORT;
9492 	dfc_auth_status_t	*fcsp_status;
9493 	uint32_t		rval = DFC_SUCCESS;
9494 
9495 	if (!dfc->buf1 || !dfc->buf1_size) {
9496 		EMLXS_MSGF(EMLXS_CONTEXT,
9497 		    &emlxs_dfc_error_msg, "%s: Null buffer1 found.",
9498 		    emlxs_dfc_xlate(dfc->cmd));
9499 
9500 		return (DFC_ARG_NULL);
9501 	}
9502 
9503 	if (dfc->buf1_size < sizeof (dfc_auth_status_t)) {
9504 		EMLXS_MSGF(EMLXS_CONTEXT,
9505 		    &emlxs_dfc_error_msg, "%s: Buffer too small. (size=%d)",
9506 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9507 
9508 		return (DFC_ARG_TOOSMALL);
9509 	}
9510 
9511 	fcsp_status = (dfc_auth_status_t *)dfc->buf1;
9512 
9513 	if ((rval = emlxs_dhc_get_auth_status(hba, fcsp_status)) != 0) {
9514 		return (rval);
9515 	}
9516 
9517 	return (0);
9518 
9519 } /* emlxs_dfc_get_auth_status() */
9520 
9521 
9522 /*ARGSUSED*/
9523 static int32_t
emlxs_dfc_get_auth_cfg_table(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9524 emlxs_dfc_get_auth_cfg_table(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9525 {
9526 	emlxs_port_t		*port = &PPORT;
9527 	uint32_t		count;
9528 	uint32_t		rval = DFC_SUCCESS;
9529 
9530 	/* Lock cfg table while we do this */
9531 	/* This prevents the table from changing while we get a copy */
9532 	mutex_enter(&hba->auth_lock);
9533 
9534 	if (!dfc->buf2 || !dfc->buf2_size) {
9535 		EMLXS_MSGF(EMLXS_CONTEXT,
9536 		    &emlxs_dfc_error_msg, "%s: Null buffer2 found.",
9537 		    emlxs_dfc_xlate(dfc->cmd));
9538 
9539 		mutex_exit(&hba->auth_lock);
9540 		return (DFC_ARG_NULL);
9541 	}
9542 
9543 	if (dfc->buf2_size < sizeof (uint32_t)) {
9544 		EMLXS_MSGF(EMLXS_CONTEXT,
9545 		    &emlxs_dfc_error_msg, "%s: Buffer2 too small. (size=%d)",
9546 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
9547 
9548 		mutex_exit(&hba->auth_lock);
9549 		return (DFC_ARG_TOOSMALL);
9550 	}
9551 
9552 	bcopy((void *)&hba->auth_cfg_count, (void *)dfc->buf2,
9553 	    sizeof (uint32_t));
9554 
9555 	if (!dfc->buf1 || !dfc->buf1_size) {
9556 		mutex_exit(&hba->auth_lock);
9557 		return (DFC_SUCCESS);
9558 	}
9559 
9560 	/* Check table size */
9561 	count = dfc->buf1_size / sizeof (dfc_fcsp_config_t);
9562 	if (count < hba->auth_cfg_count) {
9563 		EMLXS_MSGF(EMLXS_CONTEXT,
9564 		    &emlxs_dfc_error_msg, "%s: Buffer1 too small. (%d < %d)",
9565 		    emlxs_dfc_xlate(dfc->cmd), count, hba->auth_cfg_count);
9566 
9567 		mutex_exit(&hba->auth_lock);
9568 		return (DFC_ARG_TOOSMALL);
9569 	}
9570 
9571 	rval = emlxs_dhc_get_auth_cfg_table(hba,
9572 	    (dfc_fcsp_config_t *)dfc->buf1);
9573 	mutex_exit(&hba->auth_lock);
9574 	return (rval);
9575 
9576 } /* emlxs_dfc_get_auth_cfg_table() */
9577 
9578 
9579 /*ARGSUSED*/
9580 static int32_t
emlxs_dfc_get_auth_key_table(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9581 emlxs_dfc_get_auth_key_table(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9582 {
9583 	emlxs_port_t		*port = &PPORT;
9584 	uint32_t		count;
9585 	uint32_t		rval = DFC_SUCCESS;
9586 
9587 	/* Lock cfg table while we do this */
9588 	/* This prevents the table from changing while we get a copy */
9589 	mutex_enter(&hba->auth_lock);
9590 
9591 	if (!dfc->buf2 || !dfc->buf2_size) {
9592 		EMLXS_MSGF(EMLXS_CONTEXT,
9593 		    &emlxs_dfc_error_msg, "%s: Null buffer2 found.",
9594 		    emlxs_dfc_xlate(dfc->cmd));
9595 
9596 		mutex_exit(&hba->auth_lock);
9597 		return (DFC_ARG_NULL);
9598 	}
9599 
9600 	if (dfc->buf2_size < sizeof (uint32_t)) {
9601 		EMLXS_MSGF(EMLXS_CONTEXT,
9602 		    &emlxs_dfc_error_msg, "%s: Buffer2 too small. (size=%d)",
9603 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
9604 
9605 		mutex_exit(&hba->auth_lock);
9606 		return (DFC_ARG_TOOSMALL);
9607 	}
9608 
9609 	bcopy((void *)&hba->auth_key_count, (void *)dfc->buf2,
9610 	    sizeof (uint32_t));
9611 
9612 	if (!dfc->buf1 || !dfc->buf1_size) {
9613 		mutex_exit(&hba->auth_lock);
9614 		return (DFC_SUCCESS);
9615 	}
9616 
9617 	/* Check table size */
9618 	count = dfc->buf1_size / sizeof (dfc_auth_password_t);
9619 	if (count < hba->auth_key_count) {
9620 		EMLXS_MSGF(EMLXS_CONTEXT,
9621 		    &emlxs_dfc_error_msg, "%s: Buffer1 too small. (%d < %d)",
9622 		    emlxs_dfc_xlate(dfc->cmd), count, hba->auth_key_count);
9623 
9624 		mutex_exit(&hba->auth_lock);
9625 		return (DFC_ARG_TOOSMALL);
9626 	}
9627 
9628 	rval = emlxs_dhc_get_auth_key_table(hba,
9629 	    (dfc_auth_password_t *)dfc->buf1);
9630 	mutex_exit(&hba->auth_lock);
9631 	return (rval);
9632 
9633 } /* emlxs_dfc_get_auth_key_table() */
9634 
9635 
9636 
9637 #endif	/* DHCHAP_SUPPORT */
9638 
9639 #ifdef SAN_DIAG_SUPPORT
9640 /*ARGSUSED*/
9641 static int32_t
emlxs_dfc_sd_set_bucket(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9642 emlxs_dfc_sd_set_bucket(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9643 {
9644 	uint32_t	type, search_type;
9645 	uint16_t	state;
9646 	int32_t		rval = DFC_SD_OK;
9647 
9648 	type = dfc->data1;
9649 	search_type = dfc->data2;
9650 
9651 	mutex_enter(&emlxs_sd_bucket_mutex);
9652 	state = emlxs_sd_bucket.state;
9653 
9654 	if (state == SD_COLLECTING)
9655 		rval = DFC_SD_ERROR_DATA_COLLECTION_ACTIVE;
9656 	else if ((search_type < SD_SEARCH_LINEAR) ||
9657 	    (search_type > SD_SEARCH_POWER_2))
9658 		rval = DFC_SD_ERROR_INVALID_ARG;
9659 	else if (type != SD_SCSI_IO_LATENCY_TYPE)
9660 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9661 	else {
9662 		bcopy(dfc->buf3, (void *) &emlxs_sd_bucket,
9663 		    sizeof (sd_bucket_info_t));
9664 		emlxs_sd_bucket.state = SD_STOPPED;
9665 	}
9666 
9667 	mutex_exit(&emlxs_sd_bucket_mutex);
9668 	return (rval);
9669 }
9670 
9671 /*ARGSUSED*/
9672 static int32_t
emlxs_dfc_sd_destroy_bucket(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9673 emlxs_dfc_sd_destroy_bucket(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9674 {
9675 	uint32_t	type;
9676 	int32_t 	rval = DFC_SD_OK;
9677 
9678 	type = dfc->data1;
9679 
9680 	mutex_enter(&emlxs_sd_bucket_mutex);
9681 
9682 	if (emlxs_sd_bucket.search_type == 0) {
9683 		rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9684 	} else if (emlxs_sd_bucket.state == SD_COLLECTING) {
9685 		rval = DFC_SD_ERROR_DATA_COLLECTION_ACTIVE;
9686 	} else if (type != SD_SCSI_IO_LATENCY_TYPE) {
9687 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9688 	} else {
9689 		bzero((uint8_t *)&emlxs_sd_bucket, sizeof (sd_bucket_info_t));
9690 	}
9691 
9692 	mutex_exit(&emlxs_sd_bucket_mutex);
9693 	return (rval);
9694 
9695 } /* emlxs_dfc_sd_destroy_bucket() */
9696 
9697 
9698 /*ARGSUSED*/
9699 static int32_t
emlxs_dfc_sd_get_bucket(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9700 emlxs_dfc_sd_get_bucket(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9701 {
9702 	uint32_t	type;
9703 	int32_t		rval = DFC_SD_OK;
9704 
9705 	type = dfc->data1;
9706 
9707 	mutex_enter(&emlxs_sd_bucket_mutex);
9708 
9709 	if (emlxs_sd_bucket.search_type == 0) {
9710 		rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9711 	} else if (type != SD_SCSI_IO_LATENCY_TYPE) {
9712 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9713 	} else {
9714 		bcopy(&emlxs_sd_bucket, dfc->buf3,
9715 		    sizeof (sd_bucket_info_t));
9716 	}
9717 
9718 	mutex_exit(&emlxs_sd_bucket_mutex);
9719 	return (rval);
9720 
9721 } /* emlxs_dfc_sd_get_bucket() */
9722 
9723 
9724 /*ARGSUSED*/
9725 static int32_t
emlxs_dfc_sd_start_collection(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9726 emlxs_dfc_sd_start_collection(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9727 {
9728 	emlxs_port_t	*vport;
9729 	NODELIST	*nlp;
9730 	uint8_t		wwpn[8];
9731 	int32_t		rval = DFC_SD_OK;
9732 	int		i;
9733 
9734 	if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) {
9735 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9736 		goto start_collect_exit;
9737 	}
9738 
9739 	if (emlxs_sd_bucket.search_type == 0) {
9740 		rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9741 		goto start_collect_exit;
9742 	}
9743 
9744 	/* Read the wwn object */
9745 	bcopy((void *)dfc->buf3, (void *)wwpn, 8);
9746 
9747 	/* Make sure WWPN is unique */
9748 	vport = emlxs_vport_find_wwpn(hba, wwpn);
9749 
9750 	if (!vport) {
9751 		rval = DFC_SD_ERROR_INVALID_PORT;
9752 		goto start_collect_exit;
9753 	}
9754 
9755 	/* traverse list of nodes for this vport and reset counter */
9756 	rw_enter(&vport->node_rwlock, RW_READER);
9757 	if (vport->sd_io_latency_state == SD_COLLECTING) {
9758 		rval = DFC_SD_ERROR_DATA_COLLECTION_ACTIVE;
9759 		rw_exit(&vport->node_rwlock);
9760 		goto start_collect_exit;
9761 	}
9762 
9763 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
9764 		nlp = vport->node_table[i];
9765 		while (nlp != NULL) {
9766 			bzero((void *)&nlp->sd_dev_bucket[0],
9767 			    sizeof (struct SD_time_stats_v0) *
9768 			    SD_IO_LATENCY_MAX_BUCKETS);
9769 
9770 			nlp = nlp->nlp_list_next;
9771 		}
9772 	}
9773 
9774 	vport->sd_io_latency_state = SD_COLLECTING;
9775 	rw_exit(&vport->node_rwlock);
9776 
9777 	mutex_enter(&emlxs_sd_bucket_mutex);
9778 	emlxs_sd_bucket.state = SD_COLLECTING;
9779 	mutex_exit(&emlxs_sd_bucket_mutex);
9780 
9781 start_collect_exit:
9782 	return (rval);
9783 }
9784 
9785 
9786 /*ARGSUSED*/
9787 static int32_t
emlxs_dfc_sd_stop_collection(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9788 emlxs_dfc_sd_stop_collection(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9789 {
9790 	emlxs_port_t	*vport;
9791 	emlxs_hba_t	*temp_hba;
9792 	uint8_t		wwpn[8];
9793 	int32_t		rval = DFC_SD_OK;
9794 	int		i, j;
9795 
9796 	if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) {
9797 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9798 		goto stop_collect_exit;
9799 	}
9800 
9801 	if (emlxs_sd_bucket.search_type == 0) {
9802 		rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9803 		goto stop_collect_exit;
9804 	}
9805 
9806 	/* Read the wwn object */
9807 	bcopy((void *)dfc->buf3, (void *)wwpn, 8);
9808 
9809 	/* Make sure WWPN is unique */
9810 	vport = emlxs_vport_find_wwpn(hba, wwpn);
9811 
9812 	if (!vport) {
9813 		rval = DFC_SD_ERROR_INVALID_PORT;
9814 		goto stop_collect_exit;
9815 	}
9816 
9817 	rw_enter(&vport->node_rwlock, RW_READER);
9818 	if (vport->sd_io_latency_state != SD_COLLECTING) {
9819 		rval = DFC_SD_ERROR_DATA_COLLECTION_NOT_ACTIVE;
9820 		rw_exit(&vport->node_rwlock);
9821 		goto stop_collect_exit;
9822 	}
9823 	vport->sd_io_latency_state = SD_STOPPED;
9824 	rw_exit(&vport->node_rwlock);
9825 
9826 	/* see if any other port is collecting io latency */
9827 	for (i = 0; i < emlxs_device.hba_count; i++) {
9828 		temp_hba = emlxs_device.hba[i];
9829 		for (j = 0; j < temp_hba->num_of_ports; j++) {
9830 			vport = &temp_hba->port[j];
9831 			if (vport->sd_io_latency_state == SD_COLLECTING)
9832 				goto stop_collect_exit;
9833 		}
9834 	}
9835 
9836 	/*
9837 	 * if we get here, that means no one else is collecting
9838 	 * io latency data.
9839 	 */
9840 	mutex_enter(&emlxs_sd_bucket_mutex);
9841 	emlxs_sd_bucket.state = SD_STOPPED;
9842 	mutex_exit(&emlxs_sd_bucket_mutex);
9843 
9844 stop_collect_exit:
9845 	return (rval);
9846 }
9847 
9848 
9849 /*ARGSUSED*/
9850 static int32_t
emlxs_dfc_sd_reset_collection(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9851 emlxs_dfc_sd_reset_collection(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9852 {
9853 	emlxs_port_t   *vport;
9854 	NODELIST	*nlp;
9855 	uint8_t		wwpn[8];
9856 	int32_t 	rval = DFC_SD_OK;
9857 	int		i;
9858 
9859 	if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) {
9860 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9861 		goto reset_collect_exit;
9862 	}
9863 
9864 	if (emlxs_sd_bucket.search_type == 0) {
9865 		rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9866 		goto reset_collect_exit;
9867 	}
9868 
9869 	/* Read the wwn object */
9870 	bcopy((void *)dfc->buf3, (void *)wwpn, 8);
9871 
9872 	/* Make sure WWPN is unique */
9873 	vport = emlxs_vport_find_wwpn(hba, wwpn);
9874 
9875 	if (!vport) {
9876 		rval = DFC_SD_ERROR_INVALID_PORT;
9877 		goto reset_collect_exit;
9878 	}
9879 
9880 	/* traverse list of nodes for this vport and reset counter */
9881 	rw_enter(&vport->node_rwlock, RW_READER);
9882 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
9883 		nlp = vport->node_table[i];
9884 		while (nlp != NULL) {
9885 			bzero((void *)&nlp->sd_dev_bucket[0],
9886 			    sizeof (struct SD_time_stats_v0) *
9887 			    SD_IO_LATENCY_MAX_BUCKETS);
9888 
9889 			nlp = nlp->nlp_list_next;
9890 		}
9891 	}
9892 	rw_exit(&vport->node_rwlock);
9893 
9894 reset_collect_exit:
9895 	return (rval);
9896 }
9897 
9898 
9899 /*ARGSUSED*/
9900 static int32_t
emlxs_dfc_sd_get_data(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)9901 emlxs_dfc_sd_get_data(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9902 {
9903 	emlxs_port_t   *vport;
9904 	uint8_t		wwpn[8];
9905 	int		i, skip_bytes;
9906 	uint16_t	count;
9907 	uint32_t	bufsize, size_needed;
9908 	NODELIST	*nlp;
9909 	int32_t 	rval = DFC_SD_OK;
9910 
9911 	if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) {
9912 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9913 		goto get_data_exit;
9914 	}
9915 
9916 	if (emlxs_sd_bucket.search_type == 0) {
9917 		rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9918 		goto get_data_exit;
9919 	}
9920 
9921 	/* Read the wwn object */
9922 	bcopy((void *)dfc->buf3, (void *)wwpn, 8);
9923 
9924 	/* Make sure WWPN is unique */
9925 	vport = emlxs_vport_find_wwpn(hba, wwpn);
9926 
9927 	if (!vport) {
9928 		rval = DFC_SD_ERROR_INVALID_PORT;
9929 		goto get_data_exit;
9930 	}
9931 
9932 	bufsize = dfc->buf4_size;
9933 
9934 	/*
9935 	 * count # of targets to see if buffer is big enough
9936 	 */
9937 	count = 0;
9938 	rw_enter(&vport->node_rwlock, RW_READER);
9939 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
9940 		nlp = vport->node_table[i];
9941 		while (nlp != NULL) {
9942 			count++;
9943 			nlp = nlp->nlp_list_next;
9944 		}
9945 	}
9946 	rw_exit(&vport->node_rwlock);
9947 
9948 	size_needed = count * (sizeof (HBA_WWN) +
9949 	    sizeof (struct SD_time_stats_v0) * SD_IO_LATENCY_MAX_BUCKETS);
9950 
9951 	if (bufsize < size_needed) {
9952 		rval = DFC_SD_ERROR_MORE_DATA_AVAIL;
9953 		goto update_count;	/* not enough space, return */
9954 	}
9955 
9956 	/*
9957 	 * return data collected, reset counter.
9958 	 */
9959 	count = 0;
9960 	skip_bytes = 0;
9961 	rw_enter(&vport->node_rwlock, RW_READER);
9962 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
9963 		nlp = vport->node_table[i];
9964 		while (nlp != NULL) {
9965 			/* copy port name */
9966 			bcopy((void *)&nlp->nlp_portname,
9967 			    (void *)((char *)dfc->buf4 + skip_bytes),
9968 			    sizeof (HBA_WWN));
9969 			skip_bytes += sizeof (HBA_WWN);
9970 
9971 			/* copy bucket data */
9972 			bcopy((void *)&nlp->sd_dev_bucket[0],
9973 			    (void *)((char *)dfc->buf4 + skip_bytes),
9974 			    sizeof (struct SD_time_stats_v0) *
9975 			    SD_IO_LATENCY_MAX_BUCKETS);
9976 			skip_bytes += sizeof (struct SD_time_stats_v0) *
9977 			    SD_IO_LATENCY_MAX_BUCKETS;
9978 
9979 			bzero((void *)&nlp->sd_dev_bucket[0],
9980 			    sizeof (struct SD_time_stats_v0) *
9981 			    SD_IO_LATENCY_MAX_BUCKETS);
9982 
9983 			count++;
9984 			bufsize -= sizeof (struct SD_IO_Latency_Response);
9985 
9986 			nlp = nlp->nlp_list_next;
9987 		}
9988 	}
9989 	rw_exit(&vport->node_rwlock);
9990 
9991 update_count:
9992 	bcopy((void *)&count, (void *)dfc->buf2, sizeof (uint16_t));
9993 
9994 get_data_exit:
9995 	return (rval);
9996 
9997 } /* emlxs_dfc_sd_get_data() */
9998 
9999 
10000 /*ARGSUSED*/
10001 static int32_t
emlxs_dfc_sd_set_event(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)10002 emlxs_dfc_sd_set_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10003 {
10004 	emlxs_port_t		*vport;
10005 	uint8_t			wwpn[8];
10006 	uint32_t		event, pid, enable;
10007 	int32_t 		rval = DFC_SD_OK;
10008 	int			i, count;
10009 	emlxs_dfc_event_t	*dfc_event;
10010 
10011 	/*
10012 	 * The value of "event" has been shifted left based on
10013 	 * the category that the application gave to libdfc.
10014 	 *
10015 	 * This is so the old Event handling code won't mistakenly
10016 	 * grab an SD Event.
10017 	 */
10018 	event = dfc->data1;
10019 	pid = dfc->data3;
10020 	enable = dfc->flag;
10021 
10022 	/* Read the wwn object */
10023 	bcopy((void *)dfc->buf3, (void *)wwpn, 8);
10024 
10025 	/* Make sure WWPN is unique */
10026 	vport = emlxs_vport_find_wwpn(hba, wwpn);
10027 
10028 	if (!vport) {
10029 		rval = DFC_SD_ERROR_INVALID_PORT;
10030 		goto set_sd_event_exit;
10031 	}
10032 
10033 	if (enable) {
10034 		/* Find next available event object */
10035 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
10036 			dfc_event = &vport->sd_events[i];
10037 
10038 			if (!dfc_event->pid && !dfc_event->event)
10039 				break;
10040 		}
10041 
10042 		/* Return if all event objects are busy */
10043 		if (i == MAX_DFC_EVENTS) {
10044 			rval = DFC_SD_ERROR_OUT_OF_HANDLES;
10045 			goto set_sd_event_exit;
10046 		}
10047 
10048 		/* Initialize */
10049 		/* TODO: Should we add SUBCAT in dfc_event ??? */
10050 		dfc_event->pid = pid;
10051 		dfc_event->event = event;
10052 		dfc_event->last_id = (uint32_t)-1;
10053 		dfc_event->dataout = NULL;
10054 		dfc_event->size = 0;
10055 		dfc_event->mode = 0;
10056 
10057 		emlxs_get_sd_event(vport, dfc_event, 0);
10058 
10059 		if (dfc->buf1) {
10060 			bcopy((void *) &dfc_event->last_id, dfc->buf1,
10061 			    sizeof (uint32_t));
10062 		}
10063 
10064 		vport->sd_event_mask |= event;
10065 	} else { /* Disable */
10066 		/* find event entry */
10067 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
10068 			dfc_event = &vport->sd_events[i];
10069 
10070 			if (dfc_event->pid  == pid && dfc_event->event == event)
10071 				break;
10072 		}
10073 
10074 		/* Return if not found */
10075 		if (i == MAX_DFC_EVENTS) {
10076 			rval = DFC_SD_ERROR_INVALID_ARG;
10077 			goto set_sd_event_exit;
10078 		}
10079 
10080 		/* Kill the event thread if it is sleeping */
10081 		(void) emlxs_kill_dfc_event(vport, dfc_event);
10082 
10083 		/* Count the number of pids still registered for this event */
10084 		count = 0;
10085 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
10086 			dfc_event = &vport->sd_events[i];
10087 
10088 			if (dfc_event->event == event)
10089 				count++;
10090 		}
10091 
10092 		/*
10093 		 * If no more pids need this event,
10094 		 * then disable logging for this event
10095 		 */
10096 		if (count == 0)
10097 			vport->sd_event_mask &= ~event;
10098 	}
10099 
10100 set_sd_event_exit:
10101 	return (rval);
10102 } /* emlxs_dfc_sd_set_event */
10103 
10104 
10105 /*ARGSUSED*/
10106 static int32_t
emlxs_dfc_sd_get_event(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)10107 emlxs_dfc_sd_get_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10108 {
10109 	emlxs_port_t   *vport;
10110 	uint8_t		wwpn[8];
10111 	uint32_t	event, pid, sleep, i;
10112 	int32_t		rval = DFC_SD_OK;
10113 	emlxs_dfc_event_t *dfc_event;
10114 
10115 	event = dfc->data1;
10116 	pid = dfc->data2;
10117 
10118 	/* Read the wwn object */
10119 	bcopy((void *)dfc->buf4, (void *)wwpn, 8);
10120 
10121 	/* Make sure WWPN is unique */
10122 	vport = emlxs_vport_find_wwpn(hba, wwpn);
10123 
10124 	if (!vport) {
10125 		rval = DFC_SD_ERROR_INVALID_PORT;
10126 		goto get_sd_event_exit;
10127 	}
10128 
10129 	/* Find the event entry */
10130 	dfc_event = NULL;
10131 	for (i = 0; i < MAX_DFC_EVENTS; i++) {
10132 		dfc_event = &vport->sd_events[i];
10133 
10134 		if (dfc_event->pid == pid && dfc_event->event == event)
10135 			break;
10136 	}
10137 
10138 	if (i == MAX_DFC_EVENTS) {
10139 		rval = DFC_SD_ERROR_GENERIC;
10140 		goto get_sd_event_exit;
10141 	}
10142 
10143 	if (!(vport->sd_event_mask & dfc_event->event)) {
10144 		rval = DFC_SD_ERROR_GENERIC;
10145 		goto get_sd_event_exit;
10146 	}
10147 
10148 	/* Initialize event buffer pointers */
10149 	dfc_event->dataout = dfc->buf1;
10150 	dfc_event->size = dfc->buf1_size;
10151 	dfc_event->last_id = dfc->data3;
10152 	dfc_event->mode = mode;
10153 
10154 	sleep = (dfc->flag & 0x01) ? 1 : 0;
10155 
10156 	emlxs_get_sd_event(vport, dfc_event, sleep);
10157 
10158 	/*
10159 	 * update rcv_size.
10160 	 */
10161 	if (dfc->buf2) {
10162 		bcopy((void *) &dfc_event->size, dfc->buf2,
10163 		    sizeof (uint32_t));
10164 	}
10165 
10166 	/*
10167 	 * update index
10168 	 */
10169 	if (dfc->buf3) {
10170 		bcopy((void *) &dfc_event->last_id, dfc->buf3,
10171 		    sizeof (uint32_t));
10172 	}
10173 
10174 get_sd_event_exit:
10175 	return (rval);
10176 } /* emlxs_dfc_sd_get_event */
10177 #endif
10178 
10179 /*ARGSUSED*/
10180 static int32_t
emlxs_dfc_send_scsi_fcp(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)10181 emlxs_dfc_send_scsi_fcp(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10182 {
10183 	emlxs_port_t			*port = &PPORT;
10184 	fc_packet_t			*pkt = NULL;
10185 	NODELIST			*ndlp;
10186 	FCP_CMND			*fcp_cmd;
10187 	FCP_RSP				*fcp_rsp;
10188 	void				*ptr;
10189 	char				buffer[64];
10190 	dfc_send_scsi_fcp_cmd_info_t	*cmdinfo;
10191 	uint32_t			rval = 0;
10192 
10193 	/* cmd info */
10194 	if (!dfc->buf1 ||
10195 	    (dfc->buf1_size != sizeof (dfc_send_scsi_fcp_cmd_info_t))) {
10196 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10197 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10198 
10199 		rval = DFC_ARG_NULL;
10200 		goto done;
10201 	}
10202 
10203 	/* reqBuffer info */
10204 	if (!dfc->buf2 || (dfc->buf2_size != sizeof (FCP_CMND))) {
10205 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10206 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
10207 
10208 		rval = DFC_ARG_NULL;
10209 		goto done;
10210 	}
10211 
10212 	/* rspBuffer info, could be 0 for SCSI commands like TUR */
10213 	if (!dfc->buf3 && dfc->buf3_size) {
10214 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10215 		    "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
10216 
10217 		rval = DFC_ARG_NULL;
10218 		goto done;
10219 	}
10220 
10221 	/* senseBuffer info */
10222 	if (!dfc->buf4 || !dfc->buf4_size) {
10223 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10224 		    "%s: Null buffer4 found.", emlxs_dfc_xlate(dfc->cmd));
10225 
10226 		rval = DFC_ARG_NULL;
10227 		goto done;
10228 	}
10229 
10230 	cmdinfo = (dfc_send_scsi_fcp_cmd_info_t *)dfc->buf1;
10231 
10232 	if (cmdinfo->ver == DFC_SEND_SCSI_FCP_V2) {
10233 		port =
10234 		    emlxs_vport_find_wwpn(hba, (uint8_t *)&cmdinfo->src_wwn);
10235 		if (port == NULL) {
10236 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10237 			    "%s: WWPN does not exists. %s",
10238 			    emlxs_dfc_xlate(dfc->cmd), emlxs_wwn_xlate(buffer,
10239 			    sizeof (buffer), (uint8_t *)&cmdinfo->src_wwn));
10240 
10241 			rval = DFC_ARG_INVALID;
10242 			goto done;
10243 		}
10244 	}
10245 
10246 	if ((ndlp = emlxs_node_find_wwpn(port,
10247 	    (uint8_t *)&cmdinfo->dst_wwn, 1)) == NULL) {
10248 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10249 		    "%s: WWPN does not exists. %s", emlxs_dfc_xlate(dfc->cmd),
10250 		    emlxs_wwn_xlate(buffer, sizeof (buffer),
10251 		    (uint8_t *)&cmdinfo->dst_wwn));
10252 
10253 		rval = DFC_ARG_INVALID;
10254 		goto done;
10255 	}
10256 
10257 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (FCP_CMND), sizeof (FCP_RSP),
10258 	    dfc->buf3_size, KM_NOSLEEP))) {
10259 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10260 		    "%s: Unable to allocate packet.",
10261 		    emlxs_dfc_xlate(dfc->cmd));
10262 
10263 		rval = DFC_SYSRES_ERROR;
10264 		goto done;
10265 	}
10266 	fcp_cmd = (FCP_CMND *) pkt->pkt_cmd;
10267 
10268 	/* Copy in the command buffer */
10269 	bcopy((void *)dfc->buf2, (void *)fcp_cmd, sizeof (FCP_CMND));
10270 
10271 	/* Make this a polled IO */
10272 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
10273 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
10274 	pkt->pkt_comp = NULL;
10275 
10276 	/* Build the fc header */
10277 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(ndlp->nlp_DID);
10278 	pkt->pkt_cmd_fhdr.r_ctl = FC_FCP_CMND;
10279 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
10280 	pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP;
10281 	pkt->pkt_cmd_fhdr.seq_id = 0;
10282 	pkt->pkt_cmd_fhdr.df_ctl = 0;
10283 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
10284 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
10285 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
10286 	pkt->pkt_cmd_fhdr.ro = 0;
10287 
10288 	pkt->pkt_timeout = 30;
10289 
10290 	if ((fcp_cmd->fcpCntl3 == WRITE_DATA) && dfc->buf3_size) {
10291 		pkt->pkt_tran_type = FC_PKT_FCP_WRITE;
10292 		bcopy((void *)dfc->buf3, (void *)pkt->pkt_data, dfc->buf3_size);
10293 	} else {
10294 		pkt->pkt_tran_type = FC_PKT_FCP_READ;
10295 	}
10296 
10297 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
10298 		rval = DFC_IO_ERROR;
10299 		goto done;
10300 	}
10301 
10302 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
10303 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
10304 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10305 			    "Pkt Transport error. Pkt Timeout.");
10306 			rval = DFC_TIMEOUT;
10307 		} else {
10308 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10309 			    "Pkt Transport error. state=%x", pkt->pkt_state);
10310 			rval = DFC_IO_ERROR;
10311 		}
10312 		goto done;
10313 	}
10314 
10315 	if (pkt->pkt_data_resid) {
10316 		if (pkt->pkt_data_resid < dfc->buf3_size)
10317 			dfc->buf3_size -= pkt->pkt_data_resid;
10318 		else
10319 			dfc->buf3_size = 0;
10320 	}
10321 
10322 	SCSI_RSP_CNT(cmdinfo) = dfc->buf3_size;
10323 
10324 	fcp_rsp = (FCP_RSP *) pkt->pkt_resp;
10325 	/*
10326 	 * This is sense count for flag = 0.
10327 	 * It is fcp response size for flag = 1.
10328 	 */
10329 	if (dfc->flag) {
10330 		SCSI_SNS_CNT(cmdinfo) = 24 + LE_SWAP32(fcp_rsp->rspSnsLen) +
10331 		    LE_SWAP32(fcp_rsp->rspRspLen);
10332 		ptr = (void *)fcp_rsp;
10333 	} else {
10334 		SCSI_SNS_CNT(cmdinfo) = LE_SWAP32(fcp_rsp->rspSnsLen);
10335 		ptr = (void *)&fcp_rsp->rspSnsInfo[0];
10336 	}
10337 
10338 	if (SCSI_SNS_CNT(cmdinfo)) {
10339 		bcopy(ptr, (void *)dfc->buf4, SCSI_SNS_CNT(cmdinfo));
10340 	}
10341 
10342 	if (SCSI_RSP_CNT(cmdinfo)) {
10343 		bcopy((void *)pkt->pkt_data, (void *)dfc->buf3,
10344 		    SCSI_RSP_CNT(cmdinfo));
10345 	}
10346 
10347 	rval = 0;
10348 
10349 done:
10350 	if (pkt) {
10351 		emlxs_pkt_free(pkt);
10352 	}
10353 
10354 	return (rval);
10355 
10356 } /* emlxs_dfc_send_scsi_fcp() */
10357 
10358 
10359 /*ARGSUSED*/
10360 static int32_t
emlxs_dfc_get_persist_linkdown(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)10361 emlxs_dfc_get_persist_linkdown(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10362 {
10363 	emlxs_port_t		*port = &PPORT;
10364 	emlxs_config_t		*cfg = &CFG;
10365 	uint16_t		linkdown = 0;
10366 	uint32_t		rval = 0;
10367 
10368 	if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE) {
10369 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10370 		    "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
10371 
10372 		return (DFC_NOT_SUPPORTED);
10373 	}
10374 
10375 	if (!dfc->buf1 || !dfc->buf1_size) {
10376 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10377 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10378 
10379 		return (DFC_ARG_NULL);
10380 	}
10381 
10382 	linkdown = (uint16_t)cfg[CFG_PERSIST_LINKDOWN].current;
10383 	bcopy((void *)&linkdown, dfc->buf1, sizeof (uint16_t));
10384 
10385 	return (rval);
10386 
10387 } /* emlxs_dfc_get_persist_linkdown() */
10388 
10389 
10390 /*ARGSUSED*/
10391 static int32_t
emlxs_dfc_set_persist_linkdown(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)10392 emlxs_dfc_set_persist_linkdown(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10393 {
10394 	emlxs_port_t		*port = &PPORT;
10395 	emlxs_config_t		*cfg = &CFG;
10396 	uint32_t		rval = 0;
10397 
10398 	if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE) {
10399 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10400 		    "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
10401 
10402 		return (DFC_NOT_SUPPORTED);
10403 	}
10404 
10405 	if (dfc->data1) {
10406 		cfg[CFG_PERSIST_LINKDOWN].current = 1;
10407 	} else {
10408 		cfg[CFG_PERSIST_LINKDOWN].current = 0;
10409 	}
10410 
10411 	return (rval);
10412 
10413 } /* emlxs_dfc_set_persist_linkdown() */
10414 
10415 
10416 /*ARGSUSED*/
10417 static int32_t
emlxs_dfc_get_fcflist(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)10418 emlxs_dfc_get_fcflist(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10419 {
10420 	emlxs_port_t		*port = &PPORT;
10421 	DFC_FCoEFCFInfo_t	*fcflistentry;
10422 	DFC_FCoEFCFList_t	*fcflist;
10423 	FCFIobj_t		*fcfp;
10424 	uint32_t		size;
10425 	uint32_t		i;
10426 	uint32_t		count = 0;
10427 	uint32_t		rval = 0;
10428 
10429 	if (!dfc->buf1 || !dfc->buf1_size) {
10430 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10431 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10432 
10433 		return (DFC_ARG_NULL);
10434 	}
10435 
10436 	if (dfc->buf1_size < sizeof (DFC_FCoEFCFList_t)) {
10437 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10438 		    "%s: Buffer1 too small. (size=%d)",
10439 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10440 
10441 		return (DFC_ARG_TOOSMALL);
10442 	}
10443 
10444 	if (! ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE)) {
10445 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10446 		    "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
10447 
10448 		return (DFC_NOT_SUPPORTED);
10449 	}
10450 
10451 	if (hba->state != FC_READY) {
10452 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10453 		    "%s: HBA not ready.", emlxs_dfc_xlate(dfc->cmd));
10454 
10455 		return (DFC_DRV_ERROR);
10456 	}
10457 
10458 	size = sizeof (DFC_FCoEFCFList_t) +
10459 	    hba->sli.sli4.fcftab.table_count * sizeof (DFC_FCoEFCFInfo_t);
10460 	fcflist = (DFC_FCoEFCFList_t *)kmem_zalloc(size, KM_SLEEP);
10461 
10462 	bcopy(dfc->buf1, (void *)fcflist, sizeof (DFC_FCoEFCFList_t));
10463 
10464 	fcflistentry = fcflist->entries;
10465 	mutex_enter(&EMLXS_FCF_LOCK);
10466 	fcfp = hba->sli.sli4.fcftab.table;
10467 	for (i = 0; i < hba->sli.sli4.fcftab.table_count; i++, fcfp++) {
10468 		if ((fcfp->state != FCFI_STATE_FREE) &&
10469 		    (fcfp->fcf_rec.fcf_valid)) {
10470 			fcflistentry->Priority = fcfp->fcf_rec.fip_priority;
10471 			if (fcfp->fcf_rec.fcf_available) {
10472 				fcflistentry->State = FCF_AVAILABLE_STATE;
10473 			}
10474 			fcflistentry->LKA_Period = fcfp->fcf_rec.fka_adv_period;
10475 
10476 			bcopy((void *)fcfp->fcf_rec.vlan_bitmap,
10477 			    (void *)fcflistentry->VLanBitMap, 512);
10478 			bcopy((void *)fcfp->fcf_rec.fc_map,
10479 			    (void *)fcflistentry->FC_Map, 3);
10480 			bcopy((void *)fcfp->fcf_rec.fabric_name_identifier,
10481 			    (void *)fcflistentry->FabricName, 8);
10482 			bcopy((void *)fcfp->fcf_rec.switch_name_identifier,
10483 			    (void *)fcflistentry->SwitchName, 8);
10484 			bcopy((void *)&fcfp->fcf_rec.fcf_mac_address_hi,
10485 			    (void *)fcflistentry->Mac, 6);
10486 
10487 			count++;
10488 			fcflistentry++;
10489 		}
10490 	}
10491 	mutex_exit(&EMLXS_FCF_LOCK);
10492 
10493 	fcflist->nActiveFCFs = hba->sli.sli4.fcftab.fcfi_count;
10494 
10495 	if (count > fcflist->numberOfEntries) {
10496 		rval = DFC_ARG_TOOSMALL;
10497 	}
10498 
10499 	i = sizeof (DFC_FCoEFCFList_t) +
10500 	    (fcflist->numberOfEntries - 1) * sizeof (DFC_FCoEFCFInfo_t);
10501 	fcflist->numberOfEntries = (uint16_t)count;
10502 
10503 	bcopy((void *)fcflist, dfc->buf1, i);
10504 
10505 done:
10506 	kmem_free(fcflist, size);
10507 	return (rval);
10508 
10509 } /* emlxs_dfc_get_fcflist() */
10510 
10511 
10512 /*ARGSUSED*/
10513 static int32_t
emlxs_dfc_send_mbox4(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)10514 emlxs_dfc_send_mbox4(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10515 {
10516 	emlxs_port_t	*port = &PPORT;
10517 	MAILBOX4	*mb4 = NULL;
10518 	MAILBOXQ	*mbq = NULL;
10519 	mbox_req_hdr_t	*hdr_req;
10520 	IOCTL_COMMON_WRITE_OBJECT *write_obj;
10521 	MATCHMAP	*mp = NULL, *tx_mp = NULL, *rx_mp = NULL;
10522 	uintptr_t	addr;	/* Was uint64_t in Emulex drop... */
10523 	uint32_t	size;
10524 	int32_t		mbxstatus = 0;
10525 	uint32_t	rval = 0;
10526 
10527 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
10528 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10529 		    "%s: SLI Mode %d not supported.", emlxs_dfc_xlate(dfc->cmd),
10530 		    hba->sli_mode);
10531 
10532 		return (DFC_NOT_SUPPORTED);
10533 	}
10534 
10535 	if (!dfc->buf1 || !dfc->buf1_size) {
10536 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10537 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10538 
10539 		return (DFC_ARG_NULL);
10540 	}
10541 
10542 	if (!dfc->buf2 || !dfc->buf2_size) {
10543 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10544 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
10545 
10546 		return (DFC_ARG_NULL);
10547 	}
10548 
10549 	if ((dfc->buf1_size != dfc->buf2_size) ||
10550 	    (dfc->buf1_size < sizeof (MAILBOX4))) {
10551 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10552 		    "%s: Invalid buffer size. (size=%d)",
10553 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10554 
10555 		return (DFC_ARG_INVALID);
10556 	}
10557 
10558 	mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
10559 	mb4 = (MAILBOX4 *) mbq;
10560 	bcopy(dfc->buf1, (void *)mb4, sizeof (MAILBOX4));
10561 
10562 	/*
10563 	 * Now snoop the mailbox command
10564 	 */
10565 	switch (mb4->mbxCommand) {
10566 		case MBX_SLI_CONFIG:
10567 		if (! mb4->un.varSLIConfig.be.embedded) {
10568 			if (mb4->un.varSLIConfig.be.sge_cnt > 1) {
10569 				/*
10570 				 * Allow only one buffer descriptor
10571 				 * for non-embedded commands
10572 				 */
10573 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10574 				    "%s: Only one buffer descriptor allowed.",
10575 				    emlxs_dfc_xlate(dfc->cmd));
10576 
10577 				rval = DFC_ARG_INVALID;
10578 				break;
10579 			}
10580 
10581 			if ((!mb4->un.varSLIConfig.be.payload_length) ||
10582 			    (mb4->un.varSLIConfig.be.payload_length !=
10583 			    (dfc->buf1_size - sizeof (MAILBOX4)))) {
10584 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10585 				    "%s: Invalid buffer size. (size=%d)",
10586 				    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10587 
10588 				rval = DFC_ARG_INVALID;
10589 				break;
10590 			}
10591 
10592 			mp = emlxs_mem_buf_alloc(hba,
10593 			    mb4->un.varSLIConfig.be.payload_length);
10594 
10595 			if (mp == NULL) {
10596 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10597 				    "%s: Unable to allocate buffer.",
10598 				    emlxs_dfc_xlate(dfc->cmd));
10599 
10600 				rval = DFC_SYSRES_ERROR;
10601 				break;
10602 			}
10603 
10604 			bcopy((uint8_t *)dfc->buf1 + sizeof (MAILBOX4),
10605 			    mp->virt, mp->size);
10606 			EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
10607 			    DDI_DMA_SYNC_FORDEV);
10608 
10609 			mbq->nonembed = (void *) mp;
10610 			break;
10611 		}
10612 
10613 		hdr_req = (mbox_req_hdr_t *)
10614 		    &mb4->un.varSLIConfig.be.un_hdr.hdr_req;
10615 
10616 		/*
10617 		 * WRITE_OBJECT, READ_OBJECT and READ_OBJECT_LIST are
10618 		 * special because they use buffer descriptors
10619 		 */
10620 		if ((hdr_req->subsystem == IOCTL_SUBSYSTEM_COMMON) &&
10621 		    ((hdr_req->opcode == COMMON_OPCODE_WRITE_OBJ) ||
10622 		    (hdr_req->opcode == COMMON_OPCODE_READ_OBJ_LIST) ||
10623 		    (hdr_req->opcode == COMMON_OPCODE_READ_OBJ))) {
10624 			write_obj =
10625 			    (IOCTL_COMMON_WRITE_OBJECT *)(hdr_req + 1);
10626 
10627 			if (write_obj->params.request.buffer_desc_count
10628 			    > 1) {
10629 				/*
10630 				 * Allow only one buffer descriptor
10631 				 * for embedded commands
10632 				 */
10633 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10634 				    "%s: Only one buffer descriptor allowed.",
10635 				    emlxs_dfc_xlate(dfc->cmd));
10636 
10637 				rval = DFC_ARG_INVALID;
10638 				break;
10639 			}
10640 
10641 			if (write_obj->params.request.buffer_length !=
10642 			    (dfc->buf1_size - sizeof (MAILBOX4))) {
10643 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10644 				    "%s: Invalid buffer size. (size=%d)",
10645 				    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10646 
10647 				rval = DFC_ARG_INVALID;
10648 				break;
10649 			}
10650 
10651 			if (write_obj->params.request.buffer_length) {
10652 				mp = emlxs_mem_buf_alloc(hba,
10653 				    write_obj->params.request.buffer_length);
10654 
10655 				if (mp == NULL) {
10656 					EMLXS_MSGF(EMLXS_CONTEXT,
10657 					    &emlxs_dfc_error_msg,
10658 					    "%s: Unable to allocate buffer.",
10659 					    emlxs_dfc_xlate(dfc->cmd));
10660 
10661 					rval = DFC_SYSRES_ERROR;
10662 					break;
10663 				}
10664 
10665 				bcopy((uint8_t *)dfc->buf1 + sizeof (MAILBOX4),
10666 				    mp->virt, mp->size);
10667 				EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
10668 				    DDI_DMA_SYNC_FORDEV);
10669 				write_obj->params.request.buffer_addrlo =
10670 				    PADDR_LO(mp->phys);
10671 				write_obj->params.request.buffer_addrhi =
10672 				    PADDR_HI(mp->phys);
10673 			}
10674 			break;
10675 		}
10676 		break;
10677 
10678 		case MBX_DUMP_MEMORY:
10679 		if (mb4->un.varDmp4.available_cnt == 0)
10680 			break;
10681 
10682 		if (mb4->un.varDmp4.available_cnt !=
10683 		    (dfc->buf1_size - sizeof (MAILBOX4))) {
10684 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10685 			    "%s: Invalid buffer size. (size=%d)",
10686 			    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10687 
10688 			rval = DFC_ARG_INVALID;
10689 			break;
10690 		}
10691 
10692 		mp = emlxs_mem_buf_alloc(hba,
10693 		    mb4->un.varDmp4.available_cnt);
10694 
10695 		if (mp == NULL) {
10696 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10697 			    "%s: Unable to allocate buffer.",
10698 			    emlxs_dfc_xlate(dfc->cmd));
10699 
10700 			rval = DFC_SYSRES_ERROR;
10701 			break;
10702 		}
10703 
10704 		bcopy((uint8_t *)dfc->buf1 + sizeof (MAILBOX4),
10705 		    mp->virt, mp->size);
10706 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
10707 		    DDI_DMA_SYNC_FORDEV);
10708 
10709 		mb4->un.varDmp4.addrLow = PADDR_LO(mp->phys);
10710 		mb4->un.varDmp4.addrHigh = PADDR_HI(mp->phys);
10711 		break;
10712 
10713 		case MBX_UPDATE_CFG:
10714 		if (mb4->un.varUpdateCfg.Obit == 0)
10715 			break;
10716 
10717 		if (mb4->un.varUpdateCfg.byte_len !=
10718 		    (dfc->buf1_size - sizeof (MAILBOX4))) {
10719 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10720 			    "%s: Invalid buffer size. (size=%d)",
10721 			    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10722 
10723 			rval = DFC_ARG_INVALID;
10724 			break;
10725 		}
10726 
10727 		mp = emlxs_mem_buf_alloc(hba,
10728 		    mb4->un.varUpdateCfg.byte_len);
10729 
10730 		if (mp == NULL) {
10731 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10732 			    "%s: Unable to allocate buffer.",
10733 			    emlxs_dfc_xlate(dfc->cmd));
10734 
10735 			rval = DFC_SYSRES_ERROR;
10736 			break;
10737 		}
10738 
10739 		bcopy((uint8_t *)dfc->buf1 + sizeof (MAILBOX4),
10740 		    mp->virt, mp->size);
10741 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
10742 		    DDI_DMA_SYNC_FORDEV);
10743 
10744 		mb4->un.varWords[5] = PADDR_LO(mp->phys);
10745 		mb4->un.varWords[6] = PADDR_HI(mp->phys);
10746 		break;
10747 
10748 		case MBX_RUN_BIU_DIAG64:
10749 		size = mb4->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize;
10750 		addr = PADDR(mb4->un.varBIUdiag.un.s2.xmit_bde64.addrHigh,
10751 		    mb4->un.varBIUdiag.un.s2.xmit_bde64.addrLow);
10752 
10753 		if (!addr || !size) {
10754 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10755 			    "%s: Invalid xmit BDE. cmd=%x",
10756 			    emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10757 
10758 			rval = DFC_ARG_INVALID;
10759 			break;
10760 		}
10761 
10762 		/* Allocate xmit buffer */
10763 		if ((tx_mp = emlxs_mem_buf_alloc(hba, size)) == 0) {
10764 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10765 			    "%s: Unable to allocate xmit buffer. cmd=%x",
10766 			    emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10767 
10768 			rval = DFC_DRVRES_ERROR;
10769 			break;
10770 		}
10771 
10772 		/* Initialize the xmit buffer */
10773 		if (ddi_copyin((void *)addr, (void *)tx_mp->virt, size,
10774 		    mode) != 0) {
10775 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10776 			    "%s: ddi_copyin failed. cmd=%x",
10777 			    emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10778 
10779 			rval = DFC_COPYIN_ERROR;
10780 			break;
10781 		}
10782 		EMLXS_MPDATA_SYNC(tx_mp->dma_handle, 0, size,
10783 		    DDI_DMA_SYNC_FORDEV);
10784 
10785 		mb4->un.varBIUdiag.un.s2.xmit_bde64.addrHigh =
10786 		    PADDR_HI(tx_mp->phys);
10787 		mb4->un.varBIUdiag.un.s2.xmit_bde64.addrLow =
10788 		    PADDR_LO(tx_mp->phys);
10789 		mb4->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeFlags = 0;
10790 
10791 		size = mb4->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize;
10792 		addr = PADDR(mb4->un.varBIUdiag.un.s2.rcv_bde64.addrHigh,
10793 		    mb4->un.varBIUdiag.un.s2.rcv_bde64.addrLow);
10794 
10795 		if (!addr || !size) {
10796 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10797 			    "%s: Invalid xmit BDE. cmd=%x",
10798 			    emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10799 
10800 			rval = DFC_ARG_INVALID;
10801 			break;
10802 		}
10803 
10804 		/* Allocate receive buffer */
10805 		if ((rx_mp = emlxs_mem_buf_alloc(hba, size)) == 0) {
10806 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10807 			    "%s: Unable to allocate receive buffer. cmd=%x",
10808 			    emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10809 
10810 			rval = DFC_DRVRES_ERROR;
10811 			break;
10812 		}
10813 
10814 		mb4->un.varBIUdiag.un.s2.rcv_bde64.addrHigh =
10815 		    PADDR_HI(rx_mp->phys);
10816 		mb4->un.varBIUdiag.un.s2.rcv_bde64.addrLow =
10817 		    PADDR_LO(rx_mp->phys);
10818 		mb4->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeFlags = 0;
10819 		break;
10820 
10821 		default:
10822 		break;
10823 	}
10824 
10825 	if (rval)
10826 		goto done;
10827 
10828 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
10829 	    "%s: %s sent.  (%x %x %x %x)", emlxs_dfc_xlate(dfc->cmd),
10830 	    emlxs_mb_cmd_xlate(mb4->mbxCommand), mb4->un.varWords[0],
10831 	    mb4->un.varWords[1], mb4->un.varWords[2], mb4->un.varWords[3]);
10832 
10833 	/* issue the mbox cmd to the sli */
10834 	mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
10835 
10836 	if (mbxstatus) {
10837 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
10838 		    "%s: %s failed. mbxstatus=0x%x",
10839 		    emlxs_dfc_xlate(dfc->cmd),
10840 		    emlxs_mb_cmd_xlate(mb4->mbxCommand), mbxstatus);
10841 	}
10842 
10843 	bcopy((void *)mb4, dfc->buf2, sizeof (MAILBOX4));
10844 	if (mp) {
10845 		bcopy(mp->virt, (uint8_t *)dfc->buf2 + sizeof (MAILBOX4),
10846 		    mp->size);
10847 	}
10848 
10849 	if (rx_mp) {
10850 		EMLXS_MPDATA_SYNC(rx_mp->dma_handle, 0, size,
10851 		    DDI_DMA_SYNC_FORKERNEL);
10852 
10853 		if (ddi_copyout((void *)rx_mp->virt, (void *)addr, size,
10854 		    mode) != 0) {
10855 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10856 			    "%s: ddi_copyout failed for receive buffer. cmd=%x",
10857 			    emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10858 
10859 			rval = DFC_COPYOUT_ERROR;
10860 			goto done;
10861 		}
10862 	}
10863 
10864 done:
10865 	/* Free allocated memory */
10866 	if (mp) {
10867 		emlxs_mem_buf_free(hba, mp);
10868 	}
10869 
10870 	if (tx_mp) {
10871 		emlxs_mem_buf_free(hba, tx_mp);
10872 	}
10873 
10874 	if (rx_mp) {
10875 		emlxs_mem_buf_free(hba, rx_mp);
10876 	}
10877 
10878 	if (mbq) {
10879 		kmem_free(mbq, sizeof (MAILBOXQ));
10880 	}
10881 
10882 	return (rval);
10883 } /* emlxs_dfc_send_mbox4() */
10884 
10885 
10886 /* ARGSUSED */
10887 static int
emlxs_dfc_rd_be_fcf(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)10888 emlxs_dfc_rd_be_fcf(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10889 {
10890 	emlxs_port_t			*port = &PPORT;
10891 	MATCHMAP			*mp;
10892 	MAILBOX4			*mb  = NULL;
10893 	MAILBOXQ			*mbq = NULL;
10894 	IOCTL_FCOE_READ_FCF_TABLE	*fcf;
10895 	mbox_req_hdr_t			*hdr_req;
10896 	mbox_rsp_hdr_t			*hdr_rsp;
10897 	FCF_RECORD_t			*fcfrec;
10898 	uint32_t			rc = 0;
10899 	uint32_t			rval = 0;
10900 	uint16_t			index;
10901 
10902 	if (!dfc->buf1 || !dfc->buf1_size) {
10903 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10904 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10905 
10906 		return (DFC_ARG_NULL);
10907 	}
10908 
10909 	mbq =
10910 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
10911 
10912 	index = dfc->data1;
10913 	mb = (MAILBOX4 *)mbq;
10914 
10915 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
10916 
10917 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
10918 		rval = DFC_SYSRES_ERROR;
10919 		goto done;
10920 	}
10921 	bzero(mp->virt, mp->size);
10922 
10923 	/*
10924 	 * Signifies a non-embedded command
10925 	 */
10926 	mb->un.varSLIConfig.be.embedded = 0;
10927 	mbq->nonembed = (void *)mp;
10928 	mbq->mbox_cmpl = NULL;
10929 
10930 	mb->mbxCommand = MBX_SLI_CONFIG;
10931 	mb->mbxOwner = OWN_HOST;
10932 
10933 	hdr_req = (mbox_req_hdr_t *)mp->virt;
10934 	hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
10935 
10936 	hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
10937 	hdr_req->opcode = FCOE_OPCODE_READ_FCF_TABLE;
10938 	hdr_req->timeout = 0;
10939 	hdr_req->req_length = sizeof (IOCTL_FCOE_READ_FCF_TABLE);
10940 	fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_req + 1);
10941 	fcf->params.request.fcf_index = index;
10942 
10943 	rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
10944 	if (rc == MBX_SUCCESS) {
10945 		fcfrec = &fcf->params.response.fcf_entry[0];
10946 
10947 		bcopy((void *)fcfrec, (void *)dfc->buf1, dfc->buf1_size);
10948 		bcopy((void *)&fcf->params.response.next_valid_fcf_index,
10949 		    (void *)dfc->buf2, dfc->buf2_size);
10950 	} else {
10951 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
10952 		    "%s: %s failed. mbxstatus=0x%x", emlxs_dfc_xlate(dfc->cmd),
10953 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rc);
10954 
10955 		if ((rc == MBX_NONEMBED_ERROR) &&
10956 		    (hdr_rsp->status == MBX_RSP_STATUS_NO_FCF)) {
10957 			rval = DFC_NO_DATA;
10958 		} else {
10959 			rval = DFC_IO_ERROR;
10960 		}
10961 	}
10962 
10963 done:
10964 	if (mp) {
10965 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
10966 	}
10967 
10968 	if (mbq) {
10969 		kmem_free(mbq, sizeof (MAILBOXQ));
10970 	}
10971 
10972 	return (rval);
10973 
10974 } /* emlxs_dfc_rd_be_fcf() */
10975 
10976 
10977 /*ARGSUSED*/
10978 static int
emlxs_dfc_set_be_dcbx(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)10979 emlxs_dfc_set_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10980 {
10981 	emlxs_port_t				*port = &PPORT;
10982 	MAILBOXQ				*mbq = NULL;
10983 	MAILBOX4				*mb;
10984 	IOCTL_DCBX_SET_DCBX_MODE		*dcbx_mode;
10985 	uint32_t				port_num = 0;
10986 	uint32_t				rval = 0;
10987 
10988 	mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
10989 	mb = (MAILBOX4 *)mbq;
10990 
10991 	/*
10992 	 * Signifies an embedded command
10993 	 */
10994 	mb->un.varSLIConfig.be.embedded = 1;
10995 	mbq->mbox_cmpl = NULL;
10996 
10997 	mb->mbxCommand = MBX_SLI_CONFIG;
10998 	mb->mbxOwner = OWN_HOST;
10999 	mb->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
11000 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
11001 	    IOCTL_SUBSYSTEM_DCBX;
11002 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
11003 	    DCBX_OPCODE_SET_DCBX_MODE;
11004 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
11005 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
11006 	    sizeof (IOCTL_DCBX_SET_DCBX_MODE);
11007 	dcbx_mode = (IOCTL_DCBX_SET_DCBX_MODE *)&mb->un.varSLIConfig.payload;
11008 	dcbx_mode->params.request.port_num = (uint8_t)port_num;
11009 	dcbx_mode->params.request.dcbx_mode = dfc->data1;
11010 
11011 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
11012 	    "%s requested on port %d.", emlxs_dfc_xlate(dfc->cmd), port_num);
11013 
11014 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
11015 	if (rval != MBX_SUCCESS) {
11016 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
11017 		    "%s: %s failed. mbxstatus=0x%x", emlxs_dfc_xlate(dfc->cmd),
11018 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
11019 
11020 		rval = DFC_DRV_ERROR;
11021 	}
11022 
11023 done:
11024 	if (mbq) {
11025 		kmem_free(mbq, sizeof (MAILBOXQ));
11026 	}
11027 
11028 	return (rval);
11029 
11030 } /* emlxs_dfc_set_be_dcbx() */
11031 
11032 
11033 /* ARGSUSED */
11034 static int
emlxs_dfc_get_be_dcbx(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)11035 emlxs_dfc_get_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
11036 {
11037 	emlxs_port_t				*port = &PPORT;
11038 	MAILBOXQ				*mbq = NULL;
11039 	MAILBOX4				*mb;
11040 	IOCTL_DCBX_GET_DCBX_MODE		*dcbx_mode;
11041 	uint32_t				port_num = 0;
11042 	uint32_t				rval = 0;
11043 
11044 	mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
11045 	mb = (MAILBOX4 *)mbq;
11046 
11047 	/*
11048 	 * Signifies an embedded command
11049 	 */
11050 	mb->un.varSLIConfig.be.embedded = 1;
11051 	mbq->mbox_cmpl = NULL;
11052 
11053 	mb->mbxCommand = MBX_SLI_CONFIG;
11054 	mb->mbxOwner = OWN_HOST;
11055 	mb->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
11056 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
11057 	    IOCTL_SUBSYSTEM_DCBX;
11058 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
11059 	    DCBX_OPCODE_GET_DCBX_MODE;
11060 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
11061 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
11062 	    sizeof (IOCTL_DCBX_SET_DCBX_MODE);
11063 	dcbx_mode = (IOCTL_DCBX_GET_DCBX_MODE *)&mb->un.varSLIConfig.payload;
11064 	dcbx_mode->params.request.port_num = (uint8_t)port_num;
11065 
11066 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
11067 	    "%s requested on port %d.", emlxs_dfc_xlate(dfc->cmd), port_num);
11068 
11069 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
11070 	if (rval != MBX_SUCCESS) {
11071 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
11072 		    "%s: %s failed. mbxstatus=0x%x", emlxs_dfc_xlate(dfc->cmd),
11073 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
11074 
11075 		rval = DFC_DRV_ERROR;
11076 		goto done;
11077 	}
11078 
11079 	bcopy((void *)&dcbx_mode->params.response.dcbx_mode,
11080 	    (void *)dfc->buf1, dfc->buf1_size);
11081 
11082 done:
11083 	if (mbq) {
11084 		kmem_free(mbq, sizeof (MAILBOXQ));
11085 	}
11086 
11087 	return (rval);
11088 
11089 } /* emlxs_dfc_get_be_dcbx() */
11090 
11091 
11092 /* ARGSUSED */
11093 static int
emlxs_dfc_get_qos(emlxs_hba_t * hba,dfc_t * dfc,int32_t mode)11094 emlxs_dfc_get_qos(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
11095 {
11096 	emlxs_port_t	*port = &PPORT;
11097 	uint32_t	rval = 0;
11098 
11099 	if (! ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE)) {
11100 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
11101 		    "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
11102 
11103 		return (DFC_NOT_SUPPORTED);
11104 	}
11105 
11106 	if (dfc->buf1_size) {
11107 		bcopy((void *)&hba->qos_linkspeed, (void *)dfc->buf1,
11108 		    dfc->buf1_size);
11109 	}
11110 
11111 	return (rval);
11112 
11113 } /* emlxs_dfc_get_qos() */
11114