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