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