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