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(