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