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