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