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