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