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