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