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