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 return (0); 3490 3491 } /* emlxs_dfc_get_hbainfo() */ 3492 3493 3494 3495 static int32_t 3496 emlxs_dfc_get_hbastats(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 3497 { 3498 emlxs_port_t *port = &PPORT; 3499 dfc_hbastats_t stats; 3500 MAILBOX *mb = NULL; 3501 MAILBOXQ *mbq = NULL; 3502 uint32_t rval = 0; 3503 3504 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.", 3505 emlxs_dfc_xlate(dfc->cmd)); 3506 3507 if (!dfc->buf1 || !dfc->buf1_size) { 3508 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3509 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 3510 3511 return (DFC_ARG_NULL); 3512 } 3513 3514 if (dfc->buf1_size < sizeof (dfc_hbastats_t)) { 3515 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3516 "%s: Buffer1 too small. (size=%d)", 3517 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 3518 3519 return (DFC_ARG_TOOSMALL); 3520 } 3521 3522 if ((mbq = 3523 (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP)) == 0) { 3524 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3525 "%s: Unable to allocate mailbox buffer.", 3526 emlxs_dfc_xlate(dfc->cmd)); 3527 3528 return (DFC_SYSRES_ERROR); 3529 } 3530 3531 mb = (MAILBOX *)mbq; 3532 3533 emlxs_mb_read_status(hba, mb); 3534 3535 rval = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0); 3536 3537 if (rval == MBX_TIMEOUT) { 3538 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3539 "%s: Mailbox timed out. cmd=%x", 3540 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 3541 3542 rval = DFC_TIMEOUT; 3543 goto done; 3544 } 3545 3546 if (rval) { 3547 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3548 "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd), 3549 emlxs_mb_cmd_xlate(mb->mbxCommand), rval); 3550 3551 rval = DFC_IO_ERROR; 3552 goto done; 3553 } 3554 3555 bzero((void *) &stats, sizeof (dfc_hbastats_t)); 3556 3557 stats.tx_frame_cnt = mb->un.varRdStatus.xmitFrameCnt; 3558 stats.rx_frame_cnt = mb->un.varRdStatus.rcvFrameCnt; 3559 stats.tx_kbyte_cnt = mb->un.varRdStatus.xmitByteCnt; 3560 stats.rx_kbyte_cnt = mb->un.varRdStatus.rcvByteCnt; 3561 stats.tx_seq_cnt = mb->un.varRdStatus.xmitSeqCnt; 3562 stats.rx_seq_cnt = mb->un.varRdStatus.rcvSeqCnt; 3563 stats.orig_exch_cnt = mb->un.varRdStatus.totalOrigExchanges; 3564 stats.resp_exch_cnt = mb->un.varRdStatus.totalRespExchanges; 3565 stats.pbsy_cnt = mb->un.varRdStatus.rcvPbsyCnt; 3566 stats.fbsy_cnt = mb->un.varRdStatus.rcvFbsyCnt; 3567 3568 emlxs_mb_read_lnk_stat(hba, mb); 3569 3570 rval = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0); 3571 3572 if (rval == MBX_TIMEOUT) { 3573 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3574 "%s: Mailbox timed out. cmd=%x", 3575 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 3576 3577 rval = DFC_TIMEOUT; 3578 goto done; 3579 } 3580 3581 if (rval) { 3582 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3583 "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd), 3584 emlxs_mb_cmd_xlate(mb->mbxCommand), rval); 3585 3586 rval = DFC_IO_ERROR; 3587 goto done; 3588 } 3589 3590 stats.link_failure_cnt = mb->un.varRdLnk.linkFailureCnt; 3591 stats.loss_sync_cnt = mb->un.varRdLnk.lossSyncCnt; 3592 stats.loss_signal_cnt = mb->un.varRdLnk.lossSignalCnt; 3593 stats.seq_error_cnt = mb->un.varRdLnk.primSeqErrCnt; 3594 stats.inval_tx_word_cnt = mb->un.varRdLnk.invalidXmitWord; 3595 stats.crc_error_cnt = mb->un.varRdLnk.crcCnt; 3596 stats.seq_timeout_cnt = mb->un.varRdLnk.primSeqTimeout; 3597 stats.elastic_overrun_cnt = mb->un.varRdLnk.elasticOverrun; 3598 stats.arb_timeout_cnt = mb->un.varRdLnk.arbTimeout; 3599 stats.rx_buf_credit = mb->un.varRdLnk.rxBufCredit; 3600 stats.rx_buf_cnt = mb->un.varRdLnk.rxBufCreditCur; 3601 stats.tx_buf_credit = mb->un.varRdLnk.txBufCredit; 3602 stats.tx_buf_cnt = mb->un.varRdLnk.txBufCreditCur; 3603 stats.EOFa_cnt = mb->un.varRdLnk.EOFaCnt; 3604 stats.EOFdti_cnt = mb->un.varRdLnk.EOFdtiCnt; 3605 stats.EOFni_cnt = mb->un.varRdLnk.EOFniCnt; 3606 stats.SOFf_cnt = mb->un.varRdLnk.SOFfCnt; 3607 stats.link_event_tag = hba->link_event_tag; 3608 stats.last_reset_time = hba->timer_tics - hba->stats.ResetTime; 3609 stats.port_type = HBA_PORTTYPE_UNKNOWN; 3610 3611 #ifdef MENLO_SUPPORT 3612 if (hba->flag & FC_MENLO_MODE) { 3613 stats.topology = LNK_MENLO_MAINTENANCE; 3614 } else 3615 #endif /* MENLO_SUPPORT */ 3616 3617 if (hba->state >= FC_LINK_UP) { 3618 if (hba->topology == TOPOLOGY_LOOP) { 3619 if (hba->flag & FC_FABRIC_ATTACHED) { 3620 stats.port_type = HBA_PORTTYPE_NLPORT; 3621 stats.topology = LNK_PUBLIC_LOOP; 3622 } else { 3623 stats.port_type = HBA_PORTTYPE_LPORT; 3624 stats.topology = LNK_LOOP; 3625 } 3626 } else { 3627 if (hba->flag & FC_FABRIC_ATTACHED) { 3628 stats.port_type = HBA_PORTTYPE_NPORT; 3629 stats.topology = LNK_FABRIC; 3630 } else { 3631 stats.port_type = HBA_PORTTYPE_PTP; 3632 stats.topology = LNK_PT2PT; 3633 } 3634 } 3635 3636 if (hba->linkspeed == LA_2GHZ_LINK) { 3637 stats.link_speed = HBA_PORTSPEED_2GBIT; 3638 } else if (hba->linkspeed == LA_4GHZ_LINK) { 3639 stats.link_speed = HBA_PORTSPEED_4GBIT; 3640 } else if (hba->linkspeed == LA_8GHZ_LINK) { 3641 stats.link_speed = HBA_PORTSPEED_8GBIT; 3642 } else if (hba->linkspeed == LA_10GHZ_LINK) { 3643 stats.link_speed = HBA_PORTSPEED_10GBIT; 3644 } else { 3645 stats.link_speed = HBA_PORTSPEED_1GBIT; 3646 } 3647 } 3648 3649 if (ddi_copyout((void *)&stats, (void *)dfc->buf1, 3650 sizeof (dfc_hbastats_t), mode) != 0) { 3651 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3652 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 3653 3654 return (DFC_COPYOUT_ERROR); 3655 } 3656 3657 done: 3658 3659 /* Free allocated mbox memory */ 3660 if (mbq) { 3661 kmem_free(mbq, sizeof (MAILBOXQ)); 3662 } 3663 3664 return (rval); 3665 3666 } /* emlxs_dfc_get_hbastats() */ 3667 3668 3669 3670 static int32_t 3671 emlxs_dfc_get_drvstats(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 3672 { 3673 emlxs_port_t *port = &PPORT; 3674 dfc_drvstats_t stats; 3675 uint32_t rval = 0; 3676 3677 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.", 3678 emlxs_dfc_xlate(dfc->cmd)); 3679 3680 if (!dfc->buf1 || !dfc->buf1_size) { 3681 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3682 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 3683 3684 return (DFC_ARG_NULL); 3685 } 3686 3687 bzero((void *) &stats, sizeof (dfc_drvstats_t)); 3688 3689 stats.LinkUp = hba->stats.LinkUp; 3690 stats.LinkDown = hba->stats.LinkDown; 3691 stats.LinkEvent = hba->stats.LinkEvent; 3692 stats.LinkMultiEvent = hba->stats.LinkMultiEvent; 3693 3694 stats.MboxIssued = hba->stats.MboxIssued; 3695 stats.MboxCompleted = hba->stats.MboxCompleted; 3696 stats.MboxGood = hba->stats.MboxGood; 3697 stats.MboxError = hba->stats.MboxError; 3698 stats.MboxBusy = hba->stats.MboxBusy; 3699 stats.MboxInvalid = hba->stats.MboxInvalid; 3700 3701 stats.IocbIssued[0] = hba->stats.IocbIssued[0]; 3702 stats.IocbIssued[1] = hba->stats.IocbIssued[1]; 3703 stats.IocbIssued[2] = hba->stats.IocbIssued[2]; 3704 stats.IocbIssued[3] = hba->stats.IocbIssued[3]; 3705 stats.IocbReceived[0] = hba->stats.IocbReceived[0]; 3706 stats.IocbReceived[1] = hba->stats.IocbReceived[1]; 3707 stats.IocbReceived[2] = hba->stats.IocbReceived[2]; 3708 stats.IocbReceived[3] = hba->stats.IocbReceived[3]; 3709 stats.IocbTxPut[0] = hba->stats.IocbTxPut[0]; 3710 stats.IocbTxPut[1] = hba->stats.IocbTxPut[1]; 3711 stats.IocbTxPut[2] = hba->stats.IocbTxPut[2]; 3712 stats.IocbTxPut[3] = hba->stats.IocbTxPut[3]; 3713 stats.IocbTxGet[0] = hba->stats.IocbTxGet[0]; 3714 stats.IocbTxGet[1] = hba->stats.IocbTxGet[1]; 3715 stats.IocbTxGet[2] = hba->stats.IocbTxGet[2]; 3716 stats.IocbTxGet[3] = hba->stats.IocbTxGet[3]; 3717 stats.IocbRingFull[0] = hba->stats.IocbRingFull[0]; 3718 stats.IocbRingFull[1] = hba->stats.IocbRingFull[1]; 3719 stats.IocbRingFull[2] = hba->stats.IocbRingFull[2]; 3720 stats.IocbRingFull[3] = hba->stats.IocbRingFull[3]; 3721 3722 stats.IntrEvent[0] = hba->stats.IntrEvent[0]; 3723 stats.IntrEvent[1] = hba->stats.IntrEvent[1]; 3724 stats.IntrEvent[2] = hba->stats.IntrEvent[2]; 3725 stats.IntrEvent[3] = hba->stats.IntrEvent[3]; 3726 stats.IntrEvent[4] = hba->stats.IntrEvent[4]; 3727 stats.IntrEvent[5] = hba->stats.IntrEvent[5]; 3728 stats.IntrEvent[6] = hba->stats.IntrEvent[6]; 3729 stats.IntrEvent[7] = hba->stats.IntrEvent[7]; 3730 3731 stats.FcpIssued = hba->stats.FcpIssued; 3732 stats.FcpCompleted = hba->stats.FcpCompleted; 3733 stats.FcpGood = hba->stats.FcpGood; 3734 stats.FcpError = hba->stats.FcpError; 3735 3736 stats.FcpEvent = hba->stats.FcpEvent; 3737 stats.FcpStray = hba->stats.FcpStray; 3738 3739 stats.ElsEvent = hba->stats.ElsEvent; 3740 stats.ElsStray = hba->stats.ElsStray; 3741 3742 stats.ElsCmdIssued = hba->stats.ElsCmdIssued; 3743 stats.ElsCmdCompleted = hba->stats.ElsCmdCompleted; 3744 stats.ElsCmdGood = hba->stats.ElsCmdGood; 3745 stats.ElsCmdError = hba->stats.ElsCmdError; 3746 3747 stats.ElsRspIssued = hba->stats.ElsRspIssued; 3748 stats.ElsRspCompleted = hba->stats.ElsRspCompleted; 3749 3750 stats.ElsRcvEvent = hba->stats.ElsRcvEvent; 3751 stats.ElsRcvError = hba->stats.ElsRcvError; 3752 stats.ElsRcvDropped = hba->stats.ElsRcvDropped; 3753 stats.ElsCmdReceived = hba->stats.ElsCmdReceived; 3754 stats.ElsRscnReceived = hba->stats.ElsRscnReceived; 3755 stats.ElsPlogiReceived = hba->stats.ElsPlogiReceived; 3756 stats.ElsPrliReceived = hba->stats.ElsPrliReceived; 3757 stats.ElsPrloReceived = hba->stats.ElsPrloReceived; 3758 stats.ElsLogoReceived = hba->stats.ElsLogoReceived; 3759 stats.ElsAdiscReceived = hba->stats.ElsAdiscReceived; 3760 stats.ElsGenReceived = hba->stats.ElsGenReceived; 3761 3762 stats.CtEvent = hba->stats.CtEvent; 3763 stats.CtStray = hba->stats.CtStray; 3764 3765 stats.CtCmdIssued = hba->stats.CtCmdIssued; 3766 stats.CtCmdCompleted = hba->stats.CtCmdCompleted; 3767 stats.CtCmdGood = hba->stats.CtCmdGood; 3768 stats.CtCmdError = hba->stats.CtCmdError; 3769 3770 stats.CtRspIssued = hba->stats.CtRspIssued; 3771 stats.CtRspCompleted = hba->stats.CtRspCompleted; 3772 3773 stats.CtRcvEvent = hba->stats.CtRcvEvent; 3774 stats.CtRcvError = hba->stats.CtRcvError; 3775 stats.CtRcvDropped = hba->stats.CtRcvDropped; 3776 stats.CtCmdReceived = hba->stats.CtCmdReceived; 3777 3778 stats.IpEvent = hba->stats.IpEvent; 3779 stats.IpStray = hba->stats.IpStray; 3780 3781 stats.IpSeqIssued = hba->stats.IpSeqIssued; 3782 stats.IpSeqCompleted = hba->stats.IpSeqCompleted; 3783 stats.IpSeqGood = hba->stats.IpSeqGood; 3784 stats.IpSeqError = hba->stats.IpSeqError; 3785 3786 stats.IpBcastIssued = hba->stats.IpBcastIssued; 3787 stats.IpBcastCompleted = hba->stats.IpBcastCompleted; 3788 stats.IpBcastGood = hba->stats.IpBcastGood; 3789 stats.IpBcastError = hba->stats.IpBcastError; 3790 3791 stats.IpRcvEvent = hba->stats.IpRcvEvent; 3792 stats.IpDropped = hba->stats.IpDropped; 3793 stats.IpSeqReceived = hba->stats.IpSeqReceived; 3794 stats.IpBcastReceived = hba->stats.IpBcastReceived; 3795 3796 stats.IpUbPosted = hba->stats.IpUbPosted; 3797 stats.ElsUbPosted = hba->stats.ElsUbPosted; 3798 stats.CtUbPosted = hba->stats.CtUbPosted; 3799 3800 #if (DFC_REV >= 2) 3801 stats.IocbThrottled = hba->stats.IocbThrottled; 3802 stats.ElsAuthReceived = hba->stats.ElsAuthReceived; 3803 #endif 3804 3805 if (ddi_copyout((void *)&stats, (void *)dfc->buf1, dfc->buf1_size, 3806 mode) != 0) { 3807 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3808 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 3809 3810 return (DFC_COPYOUT_ERROR); 3811 } 3812 3813 return (rval); 3814 3815 } /* emlxs_dfc_get_drvstats() */ 3816 3817 3818 extern uint32_t 3819 emlxs_set_hba_mode(emlxs_hba_t *hba, uint32_t mode) 3820 { 3821 emlxs_port_t *port = &PPORT; 3822 uint32_t i; 3823 3824 mutex_enter(&EMLXS_PORT_LOCK); 3825 3826 /* Wait if adapter is in transition */ 3827 i = 0; 3828 while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) { 3829 if (i++ > 30) { 3830 break; 3831 } 3832 3833 mutex_exit(&EMLXS_PORT_LOCK); 3834 delay(drv_usectohz(1000000)); 3835 mutex_enter(&EMLXS_PORT_LOCK); 3836 } 3837 3838 switch (mode) { 3839 case DDI_SHOW: 3840 break; 3841 3842 case DDI_ONDI: 3843 if (hba->flag & FC_OFFLINE_MODE) { 3844 mutex_exit(&EMLXS_PORT_LOCK); 3845 (void) emlxs_online(hba); 3846 mutex_enter(&EMLXS_PORT_LOCK); 3847 } 3848 break; 3849 3850 3851 /* Killed + Restart state */ 3852 case DDI_OFFDI: 3853 if (hba->flag & FC_ONLINE_MODE) { 3854 mutex_exit(&EMLXS_PORT_LOCK); 3855 3856 (void) emlxs_offline(hba); 3857 3858 /* Reset with restart */ 3859 emlxs_sli_hba_reset(hba, 1, 1); 3860 3861 mutex_enter(&EMLXS_PORT_LOCK); 3862 } else if (hba->state < FC_INIT_START) { 3863 mutex_exit(&EMLXS_PORT_LOCK); 3864 3865 /* Reset with restart */ 3866 emlxs_sli_hba_reset(hba, 1, 1); 3867 3868 mutex_enter(&EMLXS_PORT_LOCK); 3869 } 3870 3871 break; 3872 3873 /* Killed + Reset state */ 3874 case DDI_WARMDI: 3875 if (hba->flag & FC_ONLINE_MODE) { 3876 mutex_exit(&EMLXS_PORT_LOCK); 3877 3878 (void) emlxs_offline(hba); 3879 3880 /* Reset with no restart */ 3881 emlxs_sli_hba_reset(hba, 0, 0); 3882 3883 mutex_enter(&EMLXS_PORT_LOCK); 3884 } else if (hba->state != FC_WARM_START) { 3885 mutex_exit(&EMLXS_PORT_LOCK); 3886 3887 /* Reset with no restart */ 3888 emlxs_sli_hba_reset(hba, 0, 0); 3889 3890 mutex_enter(&EMLXS_PORT_LOCK); 3891 } 3892 3893 break; 3894 3895 /* Killed */ 3896 case DDI_DIAGDI: 3897 if (hba->flag & FC_ONLINE_MODE) { 3898 mutex_exit(&EMLXS_PORT_LOCK); 3899 3900 (void) emlxs_offline(hba); 3901 3902 mutex_enter(&EMLXS_PORT_LOCK); 3903 } else if (hba->state != FC_KILLED) { 3904 mutex_exit(&EMLXS_PORT_LOCK); 3905 3906 emlxs_sli_offline(hba); 3907 3908 mutex_enter(&EMLXS_PORT_LOCK); 3909 } 3910 3911 break; 3912 3913 default: 3914 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3915 "emlxs_set_hba_mode: Invalid mode. mode%x", mode); 3916 } 3917 3918 /* Wait if adapter is in transition */ 3919 i = 0; 3920 while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) { 3921 if (i++ > 30) { 3922 break; 3923 } 3924 3925 mutex_exit(&EMLXS_PORT_LOCK); 3926 delay(drv_usectohz(1000000)); 3927 mutex_enter(&EMLXS_PORT_LOCK); 3928 } 3929 3930 /* Return current state */ 3931 if (hba->flag & FC_ONLINE_MODE) { 3932 mode = DDI_ONDI; 3933 } else if (hba->state == FC_KILLED) { 3934 mode = DDI_DIAGDI; 3935 } else if (hba->state == FC_WARM_START) { 3936 mode = DDI_WARMDI; 3937 } else { 3938 mode = DDI_OFFDI; 3939 } 3940 3941 mutex_exit(&EMLXS_PORT_LOCK); 3942 3943 return (mode); 3944 3945 } /* emlxs_set_hba_mode() */ 3946 3947 3948 static int32_t 3949 emlxs_dfc_set_diag(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 3950 { 3951 emlxs_port_t *port = &PPORT; 3952 int32_t rval = 0; 3953 int32_t flag; 3954 3955 if (!dfc->buf1 || !dfc->buf1_size) { 3956 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3957 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 3958 3959 return (DFC_ARG_NULL); 3960 } 3961 3962 if (dfc->buf1_size < sizeof (uint32_t)) { 3963 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3964 "%s: Buffer1 too small. (size=%d)", 3965 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 3966 3967 return (DFC_ARG_TOOSMALL); 3968 } 3969 3970 flag = emlxs_set_hba_mode(hba, dfc->flag); 3971 3972 if (ddi_copyout((void *)&flag, (void *)dfc->buf1, sizeof (uint32_t), 3973 mode) != 0) { 3974 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 3975 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 3976 3977 return (DFC_COPYOUT_ERROR); 3978 } 3979 3980 return (rval); 3981 3982 } /* emlxs_dfc_set_diag() */ 3983 3984 3985 3986 static int32_t 3987 emlxs_dfc_send_mbox(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 3988 { 3989 emlxs_port_t *port = &PPORT; 3990 MAILBOX *mb = NULL; 3991 MAILBOXQ *mbq = NULL; 3992 uint32_t size = 0; 3993 MATCHMAP *rx_mp = NULL; 3994 MATCHMAP *tx_mp = NULL; 3995 uintptr_t lptr; 3996 int32_t rval = 0; 3997 int32_t mbxstatus = 0; 3998 NODELIST *ndlp; 3999 uint32_t did; 4000 uint32_t extsize = 0; 4001 uint8_t *extbuf = NULL; 4002 4003 if (!dfc->buf1 || !dfc->buf1_size) { 4004 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4005 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 4006 4007 return (DFC_ARG_NULL); 4008 } 4009 4010 if (!dfc->buf2 || !dfc->buf2_size) { 4011 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4012 "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd)); 4013 4014 return (DFC_ARG_NULL); 4015 } 4016 4017 if (dfc->buf1_size > MAILBOX_CMD_BSIZE) { 4018 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4019 "%s: Buffer1 too large. (size=%d)", 4020 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 4021 4022 return (DFC_ARG_TOOBIG); 4023 } 4024 #ifdef MBOX_EXT_SUPPORT 4025 if (dfc->buf3_size || dfc->buf4_size) { 4026 if (dfc->buf3_size && !dfc->buf3) { 4027 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4028 "%s: Null buffer3 found.", 4029 emlxs_dfc_xlate(dfc->cmd)); 4030 4031 return (DFC_ARG_NULL); 4032 } 4033 4034 if (dfc->buf3_size > MBOX_EXTENSION_SIZE) { 4035 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4036 "%s: buffer3 too large. (size=%d)", 4037 emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size); 4038 4039 return (DFC_ARG_TOOBIG); 4040 } 4041 4042 if (dfc->buf4_size && !dfc->buf4) { 4043 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4044 "%s: Null buffer4 found.", 4045 emlxs_dfc_xlate(dfc->cmd)); 4046 4047 return (DFC_ARG_NULL); 4048 } 4049 4050 if (dfc->buf4_size > MBOX_EXTENSION_SIZE) { 4051 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4052 "%s: buffer4 too large. (size=%d)", 4053 emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size); 4054 4055 return (DFC_ARG_TOOBIG); 4056 } 4057 4058 extsize = 4059 (dfc->buf3_size > 4060 dfc->buf4_size) ? dfc->buf3_size : dfc->buf4_size; 4061 if ((extbuf = 4062 (uint8_t *)kmem_zalloc(extsize, KM_SLEEP)) == 0) { 4063 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4064 "%s: Unable to allocate mailbox extension buffer.", 4065 emlxs_dfc_xlate(dfc->cmd)); 4066 4067 return (DFC_SYSRES_ERROR); 4068 } 4069 4070 if (dfc->buf3_size) { 4071 if (ddi_copyin((void *)dfc->buf3, (void *)extbuf, 4072 dfc->buf3_size, mode) != 0) { 4073 EMLXS_MSGF(EMLXS_CONTEXT, 4074 &emlxs_dfc_error_msg, 4075 "%s: ddi_copyin mbox extension data " 4076 "failed.", emlxs_dfc_xlate(dfc->cmd)); 4077 4078 rval = DFC_COPYIN_ERROR; 4079 goto done; 4080 } 4081 } 4082 } 4083 #endif /* MBOX_EXT_SUPPORT */ 4084 4085 if ((mbq = 4086 (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP)) == 0) { 4087 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4088 "%s: Unable to allocate mailbox buffer.", 4089 emlxs_dfc_xlate(dfc->cmd)); 4090 4091 rval = DFC_SYSRES_ERROR; 4092 goto done; 4093 } 4094 4095 mb = (MAILBOX *) mbq; 4096 4097 bzero((void *) mb, MAILBOX_CMD_BSIZE); 4098 4099 if (ddi_copyin((void *)dfc->buf1, (void *)mb, dfc->buf1_size, 4100 mode) != 0) { 4101 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4102 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 4103 4104 rval = DFC_COPYIN_ERROR; 4105 goto done; 4106 } 4107 #ifdef _LP64 4108 if ((mb->mbxCommand == MBX_READ_SPARM) || 4109 (mb->mbxCommand == MBX_READ_RPI) || 4110 (mb->mbxCommand == MBX_REG_LOGIN) || 4111 (mb->mbxCommand == MBX_READ_LA) || 4112 (mb->mbxCommand == MBX_RUN_BIU_DIAG)) { 4113 4114 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4115 "%s: Invalid mailbox command. Must use 64bit version. " 4116 "cmd=%x", emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4117 4118 /* Must use 64 bit versions of these mbox cmds */ 4119 rval = DFC_ARG_INVALID; 4120 goto done; 4121 } 4122 #endif 4123 4124 lptr = 0; 4125 size = 0; 4126 switch (mb->mbxCommand) { 4127 /* Offline only */ 4128 case MBX_CONFIG_LINK: /* 0x07 */ 4129 case MBX_PART_SLIM: /* 0x08 */ 4130 case MBX_CONFIG_RING: /* 0x09 */ 4131 case MBX_DUMP_CONTEXT: /* 0x18 */ 4132 case MBX_RUN_DIAGS: /* 0x19 */ 4133 case MBX_RESTART: /* 0x1A */ 4134 case MBX_SET_MASK: /* 0x20 */ 4135 case MBX_FLASH_WR_ULA: /* 0x98 */ 4136 if (!(hba->flag & FC_OFFLINE_MODE)) { 4137 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4138 "%s: Adapter not offline. cmd=%x", 4139 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4140 4141 rval = DFC_ONLINE_ERROR; 4142 goto done; 4143 } 4144 break; 4145 4146 /* Online / Offline */ 4147 case MBX_UNREG_LOGIN: /* 0x14 */ 4148 ndlp = emlxs_node_find_rpi(port, mb->un.varUnregLogin.rpi); 4149 4150 if (ndlp) { 4151 did = ndlp->nlp_DID; 4152 4153 /* remove it */ 4154 emlxs_node_rm(port, ndlp); 4155 4156 /* 4157 * If we just unregistered the host node then 4158 * clear the host DID 4159 */ 4160 if (did == port->did) { 4161 port->did = 0; 4162 } 4163 } else { 4164 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4165 "%s: Node not found. cmd=%x rpi=%x", 4166 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, 4167 mb->un.varUnregLogin.rpi); 4168 4169 /* Node does not exist */ 4170 rval = DFC_ARG_INVALID; 4171 goto done; 4172 } 4173 4174 /* Send it */ 4175 break; 4176 4177 case MBX_UNREG_D_ID: /* 0x23 */ 4178 4179 did = mb->un.varRegLogin.did; 4180 4181 if (did == 0) { 4182 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4183 "%s: Node not found. cmd=%x did=%x", 4184 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did); 4185 4186 rval = DFC_ARG_INVALID; 4187 goto done; 4188 } 4189 4190 if (did == 0xffffffff) { 4191 emlxs_node_destroy_all(port); 4192 break; 4193 } 4194 4195 /* Check for base node */ 4196 if (did == Bcast_DID) { 4197 /* just flush base node */ 4198 (void) emlxs_tx_node_flush(port, &port->node_base, 4199 0, 0, 0); 4200 (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 4201 0); 4202 4203 /* Return now */ 4204 rval = 0; 4205 goto done; 4206 } 4207 4208 /* Make sure the node does already exist */ 4209 ndlp = emlxs_node_find_did(port, did); 4210 4211 if (ndlp) { 4212 /* remove it */ 4213 emlxs_node_rm(port, ndlp); 4214 4215 /* 4216 * If we just unregistered the host node then 4217 * clear the host DID 4218 */ 4219 if (did == port->did) { 4220 port->did = 0; 4221 } 4222 } else { 4223 4224 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4225 "%s: Node not found. cmd=%x did=%x", 4226 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did); 4227 4228 /* Node does not exist */ 4229 rval = DFC_ARG_INVALID; 4230 goto done; 4231 } 4232 4233 /* Send it */ 4234 break; 4235 4236 /* Online / Offline - with DMA */ 4237 case MBX_READ_EVENT_LOG: /* 0x38 */ 4238 lptr = 4239 (uintptr_t)getPaddr(mb->un.varRdEvtLog.un.sp64.addrHigh, 4240 mb->un.varRdEvtLog.un.sp64.addrLow); 4241 size = (int)mb->un.varRdEvtLog.un.sp64.tus.f.bdeSize; 4242 4243 if (!lptr || !size || (size > MEM_BUF_SIZE)) { 4244 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4245 "%s: Invalid BDE. cmd=%x", 4246 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4247 4248 rval = DFC_ARG_INVALID; 4249 goto done; 4250 } 4251 4252 /* Allocate receive buffer */ 4253 if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) { 4254 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4255 "%s: Unable to allocate receive buffer. cmd=%x", 4256 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4257 4258 rval = DFC_DRVRES_ERROR; 4259 goto done; 4260 } 4261 4262 mb->un.varRdEvtLog.un.sp64.addrHigh = putPaddrHigh(rx_mp->phys); 4263 mb->un.varRdEvtLog.un.sp64.addrLow = putPaddrLow(rx_mp->phys); 4264 mb->un.varRdEvtLog.un.sp64.tus.f.bdeFlags = 0; 4265 4266 break; 4267 4268 case MBX_READ_SPARM: /* 0x0D */ 4269 case MBX_READ_SPARM64: /* 0x8D */ 4270 lptr = 4271 (uintptr_t)getPaddr(mb->un.varRdSparm.un.sp64.addrHigh, 4272 mb->un.varRdSparm.un.sp64.addrLow); 4273 size = (int)mb->un.varRdSparm.un.sp64.tus.f.bdeSize; 4274 4275 if (!lptr || !size || (size > MEM_BUF_SIZE)) { 4276 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4277 "%s: Invalid BDE. cmd=%x", 4278 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4279 4280 rval = DFC_ARG_INVALID; 4281 goto done; 4282 } 4283 4284 /* Allocate receive buffer */ 4285 if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) { 4286 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4287 "%s: Unable to allocate receive buffer. cmd=%x", 4288 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4289 4290 rval = DFC_DRVRES_ERROR; 4291 goto done; 4292 } 4293 4294 mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(rx_mp->phys); 4295 mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(rx_mp->phys); 4296 mb->un.varRdSparm.un.sp64.tus.f.bdeFlags = 0; 4297 4298 break; 4299 4300 case MBX_READ_RPI: /* 0x0F */ 4301 case MBX_READ_RPI64: /* 0x8F */ 4302 lptr = 4303 (uintptr_t)getPaddr(mb->un.varRdRPI.un.sp64.addrHigh, 4304 mb->un.varRdRPI.un.sp64.addrLow); 4305 size = (int)mb->un.varRdRPI.un.sp64.tus.f.bdeSize; 4306 4307 if (!lptr || !size || (size > MEM_BUF_SIZE)) { 4308 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4309 "%s: Invalid BDE. cmd=%x", 4310 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4311 4312 rval = DFC_ARG_INVALID; 4313 goto done; 4314 } 4315 4316 /* Allocate receive buffer */ 4317 if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) { 4318 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4319 "%s: Unable to allocate receive buffer. cmd=%x", 4320 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4321 4322 rval = DFC_DRVRES_ERROR; 4323 goto done; 4324 } 4325 4326 mb->un.varRdRPI.un.sp64.addrHigh = putPaddrHigh(rx_mp->phys); 4327 mb->un.varRdRPI.un.sp64.addrLow = putPaddrLow(rx_mp->phys); 4328 mb->un.varRdRPI.un.sp64.tus.f.bdeFlags = 0; 4329 4330 break; 4331 4332 case MBX_RUN_BIU_DIAG: /* 0x04 */ 4333 case MBX_RUN_BIU_DIAG64: /* 0x84 */ 4334 lptr = 4335 (uintptr_t)getPaddr(mb->un.varBIUdiag.un.s2.xmit_bde64. 4336 addrHigh, mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow); 4337 size = (int)mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize; 4338 4339 if (!lptr || !size || (size > MEM_BUF_SIZE)) { 4340 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4341 "%s: Invalid xmit BDE. cmd=%x", 4342 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4343 4344 rval = DFC_ARG_INVALID; 4345 goto done; 4346 } 4347 4348 /* Allocate xmit buffer */ 4349 if ((tx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) { 4350 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4351 "%s: Unable to allocate xmit buffer. cmd=%x", 4352 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4353 4354 rval = DFC_DRVRES_ERROR; 4355 goto done; 4356 } 4357 4358 /* Initialize the xmit buffer */ 4359 if (ddi_copyin((void *)lptr, (void *)tx_mp->virt, size, 4360 mode) != 0) { 4361 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4362 "%s: ddi_copyin failed. cmd=%x", 4363 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4364 4365 rval = DFC_COPYIN_ERROR; 4366 goto done; 4367 } 4368 emlxs_mpdata_sync(tx_mp->dma_handle, 0, size, 4369 DDI_DMA_SYNC_FORDEV); 4370 4371 mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh = 4372 putPaddrHigh(tx_mp->phys); 4373 mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow = 4374 putPaddrLow(tx_mp->phys); 4375 mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeFlags = 0; 4376 4377 /* Initialize the receive buffer */ 4378 lptr = 4379 (uintptr_t)getPaddr(mb->un.varBIUdiag.un.s2.rcv_bde64. 4380 addrHigh, mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow); 4381 size = (int)mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize; 4382 4383 if (!lptr || !size || (size > MEM_BUF_SIZE)) { 4384 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4385 "%s: Invalid rcv BDE. cmd=%x", 4386 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4387 4388 rval = DFC_ARG_INVALID; 4389 goto done; 4390 } 4391 4392 /* Allocate receive buffer */ 4393 if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) { 4394 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4395 "%s: Unable to allocate receive buffer. cmd=%x", 4396 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4397 4398 rval = DFC_DRVRES_ERROR; 4399 goto done; 4400 } 4401 4402 mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh = 4403 putPaddrHigh(rx_mp->phys); 4404 mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = 4405 putPaddrLow(rx_mp->phys); 4406 mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeFlags = 0; 4407 4408 break; 4409 4410 case MBX_REG_LOGIN: /* 0x13 */ 4411 case MBX_REG_LOGIN64: /* 0x93 */ 4412 4413 did = mb->un.varRegLogin.did; 4414 4415 /* Check for invalid node ids to register */ 4416 if (did == 0 || (did & 0xff000000)) { 4417 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4418 "%s: Invalid node id. cmd=%x did=%x", 4419 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did); 4420 4421 rval = DFC_ARG_INVALID; 4422 goto done; 4423 } 4424 4425 /* Check if the node limit has been reached */ 4426 if (port->node_count >= hba->max_nodes) { 4427 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4428 "%s: Too many nodes. cmd=%x", 4429 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4430 4431 rval = DFC_HBARES_ERROR; 4432 goto done; 4433 } 4434 4435 lptr = 4436 (uintptr_t)getPaddr(mb->un.varRegLogin.un.sp64.addrHigh, 4437 mb->un.varRegLogin.un.sp64.addrLow); 4438 size = (int)mb->un.varRegLogin.un.sp64.tus.f.bdeSize; 4439 4440 if (!lptr || (size > MEM_BUF_SIZE)) { 4441 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4442 "%s: Invalid BDE. cmd=%x", 4443 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4444 4445 rval = DFC_ARG_INVALID; 4446 goto done; 4447 } 4448 4449 /* Allocate xmit buffer */ 4450 if ((tx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) { 4451 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4452 "%s: Unable to allocate xmit buffer. cmd=%x", 4453 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4454 4455 rval = DFC_DRVRES_ERROR; 4456 goto done; 4457 } 4458 4459 /* Initialize the xmit buffer */ 4460 if (ddi_copyin((void *)lptr, (void *)tx_mp->virt, size, 4461 mode) != 0) { 4462 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4463 "%s: Unable to allocate xmit buffer. cmd=%x", 4464 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4465 4466 rval = DFC_COPYIN_ERROR; 4467 goto done; 4468 } 4469 emlxs_mpdata_sync(tx_mp->dma_handle, 0, size, 4470 DDI_DMA_SYNC_FORDEV); 4471 4472 mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(tx_mp->phys); 4473 mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(tx_mp->phys); 4474 mb->un.varRegLogin.un.sp64.tus.f.bdeFlags = 0; 4475 4476 break; 4477 4478 case MBX_READ_LA: /* 0x15 */ 4479 case MBX_READ_LA64: /* 0x95 */ 4480 lptr = 4481 (uintptr_t)getPaddr(mb->un.varReadLA.un.lilpBde64. 4482 addrHigh, mb->un.varReadLA.un.lilpBde64.addrLow); 4483 size = (int)mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize; 4484 4485 if (!lptr || !size || (size > MEM_BUF_SIZE)) { 4486 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4487 "%s: Invalid BDE. cmd=%x", 4488 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4489 4490 rval = DFC_ARG_INVALID; 4491 goto done; 4492 } 4493 4494 /* Allocate receive buffer */ 4495 if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) { 4496 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4497 "%s: Unable to allocate receive buffer. cmd=%x", 4498 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4499 4500 rval = DFC_DRVRES_ERROR; 4501 goto done; 4502 } 4503 4504 mb->un.varReadLA.un.lilpBde64.addrHigh = 4505 putPaddrHigh(rx_mp->phys); 4506 mb->un.varReadLA.un.lilpBde64.addrLow = 4507 putPaddrLow(rx_mp->phys); 4508 mb->un.varReadLA.un.lilpBde64.tus.f.bdeFlags = 0; 4509 4510 break; 4511 4512 4513 /* Do not allow these commands */ 4514 case MBX_CONFIG_PORT: /* 0x88 */ 4515 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4516 "%s: Command not allowed. cmd=%x", 4517 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4518 4519 rval = DFC_ARG_INVALID; 4520 goto done; 4521 4522 4523 /* Online / Offline */ 4524 default: 4525 break; 4526 4527 } /* switch() */ 4528 4529 mb->mbxOwner = OWN_HOST; 4530 4531 /* Set or don't set the PASSTHRU bit. */ 4532 /* Setting will prevent the driver from processing it as its own */ 4533 switch (mb->mbxCommand) { 4534 case MBX_REG_LOGIN: /* 0x13 */ 4535 case MBX_REG_LOGIN64: /* 0x93 */ 4536 break; 4537 4538 default: 4539 mbq->flag |= MBQ_PASSTHRU; 4540 } 4541 4542 #ifdef MBOX_EXT_SUPPORT 4543 if (extbuf) { 4544 mbq->extbuf = extbuf; 4545 mbq->extsize = extsize; 4546 } 4547 #endif /* MBOX_EXT_SUPPORT */ 4548 4549 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 4550 "%s: %s sent. (%x %x %x %x)", emlxs_dfc_xlate(dfc->cmd), 4551 emlxs_mb_cmd_xlate(mb->mbxCommand), mb->un.varWords[0], 4552 mb->un.varWords[1], mb->un.varWords[2], mb->un.varWords[3]); 4553 4554 /* issue the mbox cmd to the sli */ 4555 mbxstatus = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0); 4556 4557 if (mbxstatus) { 4558 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4559 "%s: %s failed. mbxstatus=0x%x", 4560 emlxs_dfc_xlate(dfc->cmd), 4561 emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus); 4562 4563 } 4564 4565 if (ddi_copyout((void *)mb, (void *)dfc->buf2, dfc->buf2_size, 4566 mode) != 0) { 4567 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4568 "%s: ddi_copyout failed. cmd=%x", 4569 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4570 4571 rval = DFC_COPYOUT_ERROR; 4572 goto done; 4573 } 4574 4575 if (rx_mp) { 4576 emlxs_mpdata_sync(rx_mp->dma_handle, 0, size, 4577 DDI_DMA_SYNC_FORKERNEL); 4578 4579 if (ddi_copyout((void *)rx_mp->virt, (void *)lptr, size, 4580 mode) != 0) { 4581 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4582 "%s: ddi_copyout failed for receive buffer. cmd=%x", 4583 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 4584 4585 rval = DFC_COPYOUT_ERROR; 4586 goto done; 4587 } 4588 } 4589 #ifdef MBOX_EXT_SUPPORT 4590 /* Any data needs to copy to mbox extension area */ 4591 if (dfc->buf4_size) { 4592 if (ddi_copyout((void *)extbuf, (void *)dfc->buf4, 4593 dfc->buf4_size, mode) != 0) { 4594 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4595 "%s: ddi_copyout failed for mbox extension data.", 4596 emlxs_dfc_xlate(dfc->cmd)); 4597 4598 rval = DFC_COPYIN_ERROR; 4599 goto done; 4600 } 4601 } 4602 #endif /* MBOX_EXT_SUPPORT */ 4603 4604 rval = 0; 4605 4606 done: 4607 4608 /* Free allocated mbox memory */ 4609 if (extbuf) { 4610 kmem_free(extbuf, extsize); 4611 } 4612 4613 /* Free allocated mbox memory */ 4614 if (mbq) { 4615 kmem_free(mbq, sizeof (MAILBOXQ)); 4616 } 4617 4618 /* Free allocated mbuf memory */ 4619 if (rx_mp) { 4620 (void) emlxs_mem_buf_free(hba, (uint8_t *)rx_mp); 4621 } 4622 4623 if (tx_mp) { 4624 (void) emlxs_mem_buf_free(hba, (uint8_t *)tx_mp); 4625 } 4626 4627 return (rval); 4628 4629 } /* emlxs_dfc_send_mbox() */ 4630 4631 4632 static int32_t 4633 emlxs_dfc_read_pci(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 4634 { 4635 emlxs_port_t *port = &PPORT; 4636 uint32_t offset; 4637 uint32_t cnt; 4638 uint32_t outsz; 4639 uint32_t i; 4640 uint32_t *buffer; 4641 uint32_t *bptr; 4642 uint32_t value; 4643 uint32_t size; 4644 uint32_t max = 4096; 4645 4646 offset = dfc->data1; 4647 cnt = dfc->data2; 4648 outsz = dfc->buf1_size; 4649 4650 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 4651 "%s: offset=%x count=%d", emlxs_dfc_xlate(dfc->cmd), offset, cnt); 4652 4653 if (!dfc->buf1_size || !dfc->buf1) { 4654 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4655 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 4656 4657 return (DFC_ARG_NULL); 4658 } 4659 4660 if (offset & 0x3) { 4661 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4662 "%s: Offset misaligned. (offset=%d)", 4663 emlxs_dfc_xlate(dfc->cmd), offset); 4664 4665 return (DFC_ARG_MISALIGNED); 4666 } 4667 4668 if (cnt & 0x3) { 4669 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4670 "%s: Count misaligned. (count=%d)", 4671 emlxs_dfc_xlate(dfc->cmd), cnt); 4672 4673 return (DFC_ARG_MISALIGNED); 4674 } 4675 4676 if (outsz & 0x3) { 4677 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4678 "%s: Output size misaligned. (size=%d)", 4679 emlxs_dfc_xlate(dfc->cmd), outsz); 4680 4681 return (DFC_ARG_MISALIGNED); 4682 } 4683 4684 /* Get max PCI config range */ 4685 if (hba->model_info.chip <= EMLXS_HELIOS_CHIP) { 4686 max = 256; 4687 } else { 4688 max = 4096; 4689 } 4690 4691 if ((cnt + offset) > max) { 4692 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4693 "%s: Offset+Count too large. (offset=%d count=%d max=%d)", 4694 emlxs_dfc_xlate(dfc->cmd), offset, cnt, max); 4695 4696 return (DFC_ARG_TOOBIG); 4697 } 4698 4699 if (outsz > max) { 4700 outsz = max; 4701 } 4702 4703 if (cnt > outsz) { 4704 cnt = outsz; 4705 } 4706 4707 size = cnt; 4708 4709 if (!(buffer = (uint32_t *)kmem_zalloc(size, KM_NOSLEEP))) { 4710 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4711 "%s: Unable to allocate buffer.", 4712 emlxs_dfc_xlate(dfc->cmd)); 4713 4714 return (DFC_SYSRES_ERROR); 4715 } 4716 4717 bptr = buffer; 4718 for (i = offset; i < (offset + cnt); i += 4) { 4719 value = 4720 ddi_get32(hba->pci_acc_handle, 4721 (uint32_t *)(hba->pci_addr + i)); 4722 *bptr++ = PCIMEM_LONG(value); 4723 } 4724 4725 if (ddi_copyout((void *)buffer, (void *)dfc->buf1, outsz, mode) != 0) { 4726 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4727 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 4728 4729 kmem_free(buffer, size); 4730 return (DFC_COPYOUT_ERROR); 4731 } 4732 4733 kmem_free(buffer, size); 4734 return (0); 4735 4736 } /* emlxs_dfc_read_pci() */ 4737 4738 4739 static int32_t 4740 emlxs_dfc_write_pci(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 4741 { 4742 emlxs_port_t *port = &PPORT; 4743 uint32_t offset; 4744 uint32_t cnt; 4745 uint32_t value; 4746 uint32_t i; 4747 uint32_t max; 4748 uint8_t buffer[256]; 4749 uint32_t *bptr; 4750 uint16_t word0; 4751 uint16_t word1; 4752 4753 offset = dfc->data1; 4754 cnt = dfc->data2; 4755 4756 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 4757 "%s: offset=%x count=%d", emlxs_dfc_xlate(dfc->cmd), offset, cnt); 4758 4759 if (!dfc->buf1 || !dfc->buf1_size) { 4760 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4761 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 4762 4763 return (DFC_ARG_NULL); 4764 } 4765 4766 if (offset & 0x3) { 4767 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4768 "%s: Offset misaligned. (offset=%d)", 4769 emlxs_dfc_xlate(dfc->cmd), offset); 4770 4771 return (DFC_ARG_MISALIGNED); 4772 } 4773 4774 if (cnt > dfc->buf1_size) { 4775 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4776 "%s: Count too large. (count=%d)", 4777 emlxs_dfc_xlate(dfc->cmd), cnt); 4778 4779 return (DFC_ARG_TOOBIG); 4780 } 4781 4782 if (cnt & 0x3) { 4783 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4784 "%s: Count misaligned. (count=%d)", 4785 emlxs_dfc_xlate(dfc->cmd), cnt); 4786 4787 return (DFC_ARG_MISALIGNED); 4788 } 4789 4790 /* Get max PCI config range */ 4791 if (hba->model_info.chip <= EMLXS_HELIOS_CHIP) { 4792 max = 256; 4793 } else { 4794 max = 4096; 4795 } 4796 4797 if ((cnt + offset) > max) { 4798 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4799 "%s: Count+Offset too large. (offset=%d count=%d max=%d)", 4800 emlxs_dfc_xlate(dfc->cmd), offset, cnt, max); 4801 4802 return (DFC_ARG_TOOBIG); 4803 } 4804 4805 bzero(buffer, sizeof (buffer)); 4806 4807 if (ddi_copyin((void *)dfc->buf1, (void *)buffer, cnt, mode) != 0) { 4808 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4809 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 4810 4811 return (DFC_COPYIN_ERROR); 4812 } 4813 4814 bptr = (uint32_t *)buffer; 4815 for (i = offset; i < (offset + cnt); i += 4) { 4816 value = *bptr++; 4817 value = PCIMEM_LONG(value); 4818 4819 word0 = value & 0xFFFF; 4820 word1 = value >> 16; 4821 4822 /* 4823 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 4824 * "%s: Writing. offset=%x cnt=%d value=%08x %04x %04x", 4825 * emlxs_dfc_xlate(dfc->cmd), i, value, word0, word1); 4826 */ 4827 4828 /* word0 = PCIMEM_SHORT(word0); */ 4829 ddi_put16(hba->pci_acc_handle, 4830 (uint16_t *)(hba->pci_addr + i), (uint16_t)word0); 4831 4832 /* word1 = PCIMEM_SHORT(word1); */ 4833 ddi_put16(hba->pci_acc_handle, 4834 (uint16_t *)(hba->pci_addr + i + 2), (uint16_t)word1); 4835 } 4836 4837 return (0); 4838 4839 } /* emlxs_dfc_write_pci() */ 4840 4841 4842 static int32_t 4843 emlxs_dfc_get_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 4844 { 4845 emlxs_port_t *port = &PPORT; 4846 dfc_cfgparam_t *cfgparam; 4847 uint32_t size; 4848 uint32_t count; 4849 uint32_t i; 4850 int32_t rval = 0; 4851 emlxs_config_t *cfg; 4852 4853 if (!dfc->buf1 || !dfc->buf1_size) { 4854 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4855 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 4856 4857 return (DFC_ARG_NULL); 4858 } 4859 4860 count = dfc->buf1_size / sizeof (dfc_cfgparam_t); 4861 4862 if (count > MAX_CFG_PARAM) { 4863 count = MAX_CFG_PARAM; 4864 } 4865 4866 if (count > NUM_CFG_PARAM) { 4867 count = NUM_CFG_PARAM; 4868 } 4869 4870 size = count * sizeof (dfc_cfgparam_t); 4871 4872 if (!(cfgparam = (dfc_cfgparam_t *)kmem_zalloc(size, KM_NOSLEEP))) { 4873 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4874 "%s: Unable to allocate cfgparm buffer.", 4875 emlxs_dfc_xlate(dfc->cmd)); 4876 4877 return (DFC_SYSRES_ERROR); 4878 } 4879 4880 cfg = &CFG; 4881 for (i = 0; i < count; i++) { 4882 (void) strncpy(cfgparam[i].a_string, cfg[i].string, 4883 sizeof (cfgparam[i].a_string)); 4884 cfgparam[i].a_low = cfg[i].low; 4885 cfgparam[i].a_hi = cfg[i].hi; 4886 cfgparam[i].a_default = cfg[i].def; 4887 cfgparam[i].a_current = cfg[i].current; 4888 4889 if (!(cfg[i].flags & PARM_HIDDEN)) { 4890 cfgparam[i].a_flag |= CFG_EXPORT; 4891 } 4892 4893 if ((cfg[i].flags & PARM_DYNAMIC)) { 4894 if ((cfg[i].flags & PARM_DYNAMIC_RESET) == 4895 PARM_DYNAMIC_RESET) { 4896 cfgparam[i].a_changestate = CFG_RESTART; 4897 } else if ((cfg[i].flags & PARM_DYNAMIC_LINK) == 4898 PARM_DYNAMIC_LINK) { 4899 cfgparam[i].a_changestate = CFG_LINKRESET; 4900 } else { 4901 cfgparam[i].a_changestate = CFG_DYMANIC; 4902 } 4903 } else { 4904 cfgparam[i].a_changestate = CFG_REBOOT; 4905 } 4906 4907 (void) strncpy(cfgparam[i].a_help, cfg[i].help, 4908 sizeof (cfgparam[i].a_help)); 4909 } 4910 4911 if (ddi_copyout((void *)cfgparam, (void *)dfc->buf1, size, mode) != 0) { 4912 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4913 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 4914 4915 rval = DFC_COPYOUT_ERROR; 4916 } 4917 4918 rval = 0; 4919 4920 kmem_free(cfgparam, size); 4921 4922 return (rval); 4923 4924 } /* emlxs_dfc_get_cfg() */ 4925 4926 4927 /* ARGSUSED */ 4928 static int32_t 4929 emlxs_dfc_set_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 4930 { 4931 emlxs_port_t *port = &PPORT; 4932 uint32_t index; 4933 uint32_t new_value; 4934 uint32_t rc; 4935 4936 index = dfc->data1; 4937 new_value = dfc->data2; 4938 4939 rc = emlxs_set_parm(hba, index, new_value); 4940 4941 if (rc) { 4942 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4943 "%s: Unable to set parameter. code=%d", 4944 emlxs_dfc_xlate(dfc->cmd), rc); 4945 4946 switch (rc) { 4947 case 2: 4948 return (DFC_NPIV_ACTIVE); 4949 4950 default: 4951 return (DFC_ARG_INVALID); 4952 } 4953 } 4954 4955 return (0); 4956 4957 } /* emlxs_dfc_set_cfg() */ 4958 4959 4960 static int32_t 4961 emlxs_dfc_send_ct(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 4962 { 4963 emlxs_port_t *port = &PPORT; 4964 uint8_t *rsp_buf; 4965 uint8_t *cmd_buf; 4966 uint32_t did; 4967 uint32_t rsp_size; 4968 uint32_t cmd_size; 4969 uint32_t timeout; 4970 fc_packet_t *pkt = NULL; 4971 uint32_t rval = 0; 4972 dfc_destid_t destid; 4973 NODELIST *nlp; 4974 char buffer[128]; 4975 4976 cmd_buf = dfc->buf1; 4977 cmd_size = dfc->buf1_size; 4978 rsp_buf = dfc->buf2; 4979 rsp_size = dfc->buf2_size; 4980 timeout = dfc->data1; 4981 4982 if (timeout < (2 * hba->fc_ratov)) { 4983 timeout = 2 * hba->fc_ratov; 4984 } 4985 4986 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 4987 "%s: csize=%d rsize=%d", emlxs_dfc_xlate(dfc->cmd), cmd_size, 4988 rsp_size); 4989 4990 4991 if (!cmd_size || !cmd_buf) { 4992 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 4993 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 4994 4995 rval = DFC_ARG_NULL; 4996 goto done; 4997 } 4998 4999 if (!rsp_size || !rsp_buf) { 5000 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5001 "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd)); 5002 5003 rval = DFC_ARG_NULL; 5004 goto done; 5005 } 5006 5007 if (!dfc->buf3 || !dfc->buf3_size) { 5008 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5009 "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd)); 5010 5011 rval = DFC_ARG_NULL; 5012 goto done; 5013 } 5014 5015 if (!dfc->buf4 || !dfc->buf4_size) { 5016 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5017 "%s: Null buffer4 found.", emlxs_dfc_xlate(dfc->cmd)); 5018 5019 rval = DFC_ARG_NULL; 5020 goto done; 5021 } 5022 5023 if (rsp_size > MAX_CT_PAYLOAD) { 5024 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5025 "%s: Buffer2 too large. size=%d", 5026 emlxs_dfc_xlate(dfc->cmd), rsp_size); 5027 5028 rval = DFC_ARG_TOOBIG; 5029 goto done; 5030 } 5031 5032 if (cmd_size > MAX_CT_PAYLOAD) { 5033 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5034 "%s: Buffer1 too large. size=%d", 5035 emlxs_dfc_xlate(dfc->cmd), cmd_size); 5036 5037 rval = DFC_ARG_TOOBIG; 5038 goto done; 5039 } 5040 5041 if (dfc->buf3_size < sizeof (dfc_destid_t)) { 5042 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5043 "%s: Buffer3 too small. (size=%d)", 5044 emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size); 5045 5046 rval = DFC_ARG_TOOSMALL; 5047 goto done; 5048 } 5049 5050 if (dfc->buf4_size < sizeof (uint32_t)) { 5051 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5052 "%s: Buffer4 too small. (size=%d)", 5053 emlxs_dfc_xlate(dfc->cmd), dfc->buf4_size); 5054 5055 rval = DFC_ARG_TOOSMALL; 5056 goto done; 5057 } 5058 5059 if (ddi_copyin((void *)dfc->buf3, (void *)&destid, 5060 sizeof (dfc_destid_t), mode) != 0) { 5061 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5062 "%s: Unable to read destination id.", 5063 emlxs_dfc_xlate(dfc->cmd)); 5064 5065 rval = DFC_COPYIN_ERROR; 5066 goto done; 5067 } 5068 5069 if (destid.idType == 0) { 5070 if ((nlp = emlxs_node_find_wwpn(port, destid.wwpn)) == NULL) { 5071 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5072 "%s: WWPN does not exists. %s", 5073 emlxs_dfc_xlate(dfc->cmd), emlxs_wwn_xlate(buffer, 5074 destid.wwpn)); 5075 5076 rval = DFC_ARG_INVALID; 5077 goto done; 5078 } 5079 did = nlp->nlp_DID; 5080 } else { 5081 if (emlxs_node_find_did(port, destid.d_id) == NULL) { 5082 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5083 "%s: DID does not exist. did=%x", 5084 emlxs_dfc_xlate(dfc->cmd), destid.d_id); 5085 5086 rval = DFC_ARG_INVALID; 5087 goto done; 5088 } 5089 did = destid.d_id; 5090 } 5091 5092 if (did == 0) { 5093 did = port->did; 5094 } 5095 5096 if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size, 0, KM_NOSLEEP))) { 5097 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5098 "%s: Unable to allocate packet.", 5099 emlxs_dfc_xlate(dfc->cmd)); 5100 5101 rval = DFC_SYSRES_ERROR; 5102 goto done; 5103 } 5104 5105 /* Make this a polled IO */ 5106 pkt->pkt_tran_flags &= ~FC_TRAN_INTR; 5107 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR; 5108 pkt->pkt_comp = NULL; 5109 5110 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 5111 pkt->pkt_timeout = (timeout) ? timeout : 30; 5112 5113 /* Build the fc header */ 5114 pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(did); 5115 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL; 5116 pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did); 5117 pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES; 5118 pkt->pkt_cmd_fhdr.f_ctl = 5119 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 5120 pkt->pkt_cmd_fhdr.seq_id = 0; 5121 pkt->pkt_cmd_fhdr.df_ctl = 0; 5122 pkt->pkt_cmd_fhdr.seq_cnt = 0; 5123 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 5124 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF; 5125 pkt->pkt_cmd_fhdr.ro = 0; 5126 5127 /* Copy in the command buffer */ 5128 if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size, 5129 mode) != 0) { 5130 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5131 "%s: Unable to read command buffer.", 5132 emlxs_dfc_xlate(dfc->cmd)); 5133 5134 rval = DFC_COPYIN_ERROR; 5135 goto done; 5136 } 5137 5138 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 5139 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5140 "%s: Unable to send packet.", emlxs_dfc_xlate(dfc->cmd)); 5141 5142 rval = DFC_IO_ERROR; 5143 goto done; 5144 } 5145 5146 if ((pkt->pkt_state != FC_PKT_SUCCESS) && 5147 (pkt->pkt_state != FC_PKT_FS_RJT)) { 5148 if (pkt->pkt_state == FC_PKT_TIMEOUT) { 5149 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5150 "Pkt Transport error. Pkt Timeout."); 5151 rval = DFC_TIMEOUT; 5152 } else { 5153 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5154 "Pkt Transport error. state=%x", pkt->pkt_state); 5155 rval = DFC_IO_ERROR; 5156 } 5157 goto done; 5158 } 5159 5160 if (ddi_copyout((void *)pkt->pkt_resp, (void *)rsp_buf, rsp_size, 5161 mode) != 0) { 5162 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5163 "%s: Unable to read response.", 5164 emlxs_dfc_xlate(dfc->cmd)); 5165 5166 rval = DFC_COPYOUT_ERROR; 5167 goto done; 5168 } 5169 5170 rsp_size -= pkt->pkt_resp_resid; 5171 if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf4, dfc->buf4_size, 5172 mode) != 0) { 5173 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5174 "%s: Unable to write response.", 5175 emlxs_dfc_xlate(dfc->cmd)); 5176 5177 rval = DFC_COPYOUT_ERROR; 5178 goto done; 5179 } 5180 5181 rval = 0; 5182 5183 done: 5184 5185 if (pkt) { 5186 emlxs_pkt_free(pkt); 5187 } 5188 5189 return (rval); 5190 5191 } /* emlxs_dfc_send_ct() */ 5192 5193 5194 static int32_t 5195 emlxs_dfc_send_ct_rsp(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 5196 { 5197 emlxs_port_t *port = &PPORT; 5198 uint8_t *cmd_buf; 5199 uint32_t rx_id; 5200 uint32_t cmd_size; 5201 uint32_t timeout; 5202 fc_packet_t *pkt = NULL; 5203 uint32_t rval = 0; 5204 5205 cmd_buf = dfc->buf1; 5206 cmd_size = dfc->buf1_size; 5207 rx_id = dfc->flag; 5208 timeout = 2 * hba->fc_ratov; 5209 5210 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s: csize=%d", 5211 emlxs_dfc_xlate(dfc->cmd), cmd_size); 5212 5213 if (!cmd_size || !cmd_buf) { 5214 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5215 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 5216 5217 rval = DFC_ARG_NULL; 5218 goto done; 5219 } 5220 5221 if (!(pkt = emlxs_pkt_alloc(port, cmd_size, 0, 0, KM_NOSLEEP))) { 5222 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5223 "%s: Unable to allocate packet.", 5224 emlxs_dfc_xlate(dfc->cmd)); 5225 5226 rval = DFC_SYSRES_ERROR; 5227 goto done; 5228 } 5229 5230 /* Make this a polled IO */ 5231 pkt->pkt_tran_flags &= ~FC_TRAN_INTR; 5232 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR; 5233 pkt->pkt_comp = NULL; 5234 5235 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 5236 pkt->pkt_timeout = (timeout) ? timeout : 30; 5237 5238 /* Build the fc header */ 5239 pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(0); 5240 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_SOLICITED_CONTROL; 5241 pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did); 5242 pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES; 5243 pkt->pkt_cmd_fhdr.f_ctl = 5244 F_CTL_LAST_SEQ | F_CTL_END_SEQ | F_CTL_XCHG_CONTEXT; 5245 pkt->pkt_cmd_fhdr.seq_id = 0; 5246 pkt->pkt_cmd_fhdr.df_ctl = 0; 5247 pkt->pkt_cmd_fhdr.seq_cnt = 0; 5248 pkt->pkt_cmd_fhdr.ox_id = 0xffff; 5249 pkt->pkt_cmd_fhdr.rx_id = rx_id; 5250 pkt->pkt_cmd_fhdr.ro = 0; 5251 5252 /* Copy in the command buffer */ 5253 if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size, 5254 mode) != 0) { 5255 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5256 "%s: Unable to read command buffer.", 5257 emlxs_dfc_xlate(dfc->cmd)); 5258 5259 rval = DFC_COPYIN_ERROR; 5260 goto done; 5261 } 5262 5263 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 5264 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5265 "%s: Unable to send packet.", emlxs_dfc_xlate(dfc->cmd)); 5266 5267 rval = DFC_IO_ERROR; 5268 goto done; 5269 } 5270 5271 if (pkt->pkt_state != FC_PKT_SUCCESS) { 5272 if (pkt->pkt_state == FC_PKT_TIMEOUT) { 5273 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5274 "Pkt Transport error. Pkt Timeout."); 5275 rval = DFC_TIMEOUT; 5276 } else { 5277 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5278 "Pkt Transport error. state=%x", pkt->pkt_state); 5279 rval = DFC_IO_ERROR; 5280 } 5281 goto done; 5282 } 5283 5284 rval = 0; 5285 5286 done: 5287 5288 if (pkt) { 5289 emlxs_pkt_free(pkt); 5290 } 5291 5292 return (rval); 5293 5294 } /* emlxs_dfc_send_ct_rsp() */ 5295 5296 5297 #ifdef MENLO_SUPPORT 5298 5299 static int32_t 5300 emlxs_dfc_send_menlo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 5301 { 5302 emlxs_port_t *port = &PPORT; 5303 uint8_t *rsp_buf = NULL; 5304 uint8_t *cmd_buf = NULL; 5305 uint32_t rsp_size = 0; 5306 uint32_t cmd_size = 0; 5307 uint32_t rval = 0; 5308 5309 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 5310 "%s: csize=%d rsize=%d", emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size, 5311 dfc->buf2_size); 5312 5313 if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) { 5314 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5315 "%s: Menlo device not present. device=%x,%x", 5316 emlxs_dfc_xlate(dfc->cmd), hba->model_info.device_id, 5317 hba->model_info.ssdid); 5318 5319 rval = DFC_INVALID_ADAPTER; 5320 goto done; 5321 } 5322 5323 if (!dfc->buf1_size || !dfc->buf1) { 5324 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5325 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 5326 5327 rval = DFC_ARG_NULL; 5328 goto done; 5329 } 5330 5331 if (!dfc->buf2_size || !dfc->buf2) { 5332 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5333 "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd)); 5334 5335 rval = DFC_ARG_NULL; 5336 goto done; 5337 } 5338 5339 if (!dfc->buf3 || !dfc->buf3_size) { 5340 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5341 "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd)); 5342 5343 rval = DFC_ARG_NULL; 5344 goto done; 5345 } 5346 5347 if (dfc->buf3_size < sizeof (uint32_t)) { 5348 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5349 "%s: Buffer3 too small. %d < %d", 5350 emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size, 5351 sizeof (uint32_t)); 5352 5353 rval = DFC_ARG_TOOSMALL; 5354 goto done; 5355 } 5356 5357 cmd_size = dfc->buf1_size; 5358 if ((cmd_buf = (uint8_t *)kmem_zalloc(cmd_size, 5359 KM_SLEEP)) == 0) { 5360 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5361 "%s: Unable to allocate command buffer.", 5362 emlxs_dfc_xlate(dfc->cmd)); 5363 5364 rval = DFC_SYSRES_ERROR; 5365 goto done; 5366 } 5367 5368 rsp_size = dfc->buf2_size; 5369 if ((rsp_buf = (uint8_t *)kmem_zalloc(rsp_size, 5370 KM_SLEEP)) == 0) { 5371 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5372 "%s: Unable to allocate response buffer.", 5373 emlxs_dfc_xlate(dfc->cmd)); 5374 5375 rval = DFC_SYSRES_ERROR; 5376 goto done; 5377 } 5378 5379 /* Read the command buffer */ 5380 if (ddi_copyin((void *)dfc->buf1, (void *)cmd_buf, 5381 cmd_size, mode) != 0) { 5382 EMLXS_MSGF(EMLXS_CONTEXT, 5383 &emlxs_dfc_error_msg, 5384 "%s: Unable to read command buffer.", 5385 emlxs_dfc_xlate(dfc->cmd)); 5386 5387 rval = DFC_COPYIN_ERROR; 5388 goto done; 5389 } 5390 5391 /* Send the command */ 5392 rval = emlxs_send_menlo_cmd(hba, cmd_buf, cmd_size, 5393 rsp_buf, &rsp_size); 5394 5395 if (rval == 0) { 5396 /* Return the response */ 5397 if (ddi_copyout((void *)rsp_buf, (void *)dfc->buf2, 5398 rsp_size, mode) != 0) { 5399 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5400 "%s: Unable to write response.", 5401 emlxs_dfc_xlate(dfc->cmd)); 5402 5403 rval = DFC_COPYOUT_ERROR; 5404 goto done; 5405 } 5406 5407 /* Return the response size */ 5408 if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf3, 5409 dfc->buf3_size, mode) != 0) { 5410 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5411 "%s: Unable to write response size.", 5412 emlxs_dfc_xlate(dfc->cmd)); 5413 5414 rval = DFC_COPYOUT_ERROR; 5415 goto done; 5416 } 5417 } 5418 5419 done: 5420 5421 if (cmd_buf) { 5422 kmem_free(cmd_buf, dfc->buf1_size); 5423 } 5424 5425 if (rsp_buf) { 5426 kmem_free(rsp_buf, dfc->buf2_size); 5427 } 5428 5429 return (rval); 5430 5431 } /* emlxs_dfc_send_menlo() */ 5432 5433 5434 extern int32_t 5435 emlxs_send_menlo_cmd(emlxs_hba_t *hba, uint8_t *cmd_buf, uint32_t cmd_size, 5436 uint8_t *rsp_buf, uint32_t *rsp_size) 5437 { 5438 emlxs_port_t *port = &PPORT; 5439 uint8_t *data_buf = NULL; 5440 uint32_t data_size = 0; 5441 fc_packet_t *pkt = NULL; 5442 uint32_t rval = 0; 5443 menlo_set_cmd_t set_cmd; 5444 menlo_reset_cmd_t reset_cmd; 5445 uint32_t rsp_code; 5446 uint32_t mm_mode = 0; 5447 uint32_t cmd_code; 5448 clock_t timeout; 5449 MAILBOXQ *mbq = NULL; 5450 MAILBOX *mb; 5451 uint32_t addr; 5452 uint32_t value; 5453 uint32_t mbxstatus; 5454 5455 cmd_code = *(uint32_t *)cmd_buf; 5456 cmd_code = SWAP_LONG(cmd_code); 5457 5458 /* Look for Zephyr specific commands */ 5459 if (cmd_code & 0x80000000) { 5460 bzero((uint8_t *)&reset_cmd, sizeof (menlo_reset_cmd_t)); 5461 bzero((uint8_t *)&set_cmd, sizeof (menlo_set_cmd_t)); 5462 bzero((uint8_t *)&rsp_code, sizeof (uint32_t)); 5463 5464 /* Validate response buffer */ 5465 if (*rsp_size < sizeof (uint32_t)) { 5466 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5467 "emlxs_send_menlo_cmd: Response overrun."); 5468 rval = DFC_RSP_BUF_OVERRUN; 5469 goto done; 5470 } 5471 5472 /* All of these responses will be 4 bytes only */ 5473 *rsp_size = sizeof (uint32_t); 5474 rsp_code = 0; 5475 5476 /* Validate command buffer */ 5477 switch (cmd_code) { 5478 case MENLO_CMD_RESET: 5479 if (cmd_size < sizeof (menlo_reset_cmd_t)) { 5480 EMLXS_MSGF(EMLXS_CONTEXT, 5481 &emlxs_dfc_error_msg, 5482 "emlxs_send_menlo_cmd: " 5483 "Invalid command size. %d < %d", 5484 cmd_size, 5485 sizeof (menlo_reset_cmd_t)); 5486 rval = DFC_ARG_INVALID; 5487 goto done; 5488 } 5489 cmd_size = sizeof (menlo_reset_cmd_t); 5490 5491 /* Read the command buffer */ 5492 bcopy((void *)cmd_buf, (void *)&reset_cmd, cmd_size); 5493 5494 if (reset_cmd.firmware) { 5495 /* MENLO_FW_GOLDEN */ 5496 value = 1; 5497 5498 EMLXS_MSGF(EMLXS_CONTEXT, 5499 &emlxs_dfc_detail_msg, 5500 "emlxs_send_menlo_cmd: Reset with Golden " 5501 "firmware requested."); 5502 5503 } else { 5504 /* MENLO_FW_OPERATIONAL */ 5505 value = 0; 5506 5507 EMLXS_MSGF(EMLXS_CONTEXT, 5508 &emlxs_dfc_detail_msg, 5509 "emlxs_send_menlo_cmd: Reset with " 5510 "Operational firmware requested."); 5511 } 5512 5513 addr = 0x103007; 5514 5515 break; 5516 5517 case MENLO_CMD_SET_MODE: 5518 if (cmd_size < sizeof (menlo_set_cmd_t)) { 5519 EMLXS_MSGF(EMLXS_CONTEXT, 5520 &emlxs_dfc_error_msg, 5521 "emlxs_send_menlo_cmd: " 5522 "Invalid command size. %d < %d", 5523 cmd_size, 5524 sizeof (menlo_set_cmd_t)); 5525 rval = DFC_ARG_INVALID; 5526 goto done; 5527 } 5528 cmd_size = sizeof (menlo_set_cmd_t); 5529 5530 /* Read the command buffer */ 5531 bcopy((void *)cmd_buf, (void *)&set_cmd, cmd_size); 5532 5533 if (set_cmd.value1) { 5534 EMLXS_MSGF(EMLXS_CONTEXT, 5535 &emlxs_dfc_detail_msg, 5536 "emlxs_send_menlo_cmd: " 5537 "Maintenance mode enable requested."); 5538 5539 /* Make sure the mode flag is cleared */ 5540 if (hba->flag & FC_MENLO_MODE) { 5541 mutex_enter(&EMLXS_PORT_LOCK); 5542 hba->flag &= ~FC_MENLO_MODE; 5543 mutex_exit(&EMLXS_PORT_LOCK); 5544 } 5545 5546 mm_mode = 1; 5547 } else { 5548 EMLXS_MSGF(EMLXS_CONTEXT, 5549 &emlxs_dfc_detail_msg, 5550 "emlxs_send_menlo_cmd: " 5551 "Maintenance mode disable requested."); 5552 } 5553 5554 addr = 0x103107; 5555 value = mm_mode; 5556 5557 break; 5558 5559 default: 5560 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5561 "emlxs_send_menlo_cmd: " 5562 "Invalid command. cmd=%x", cmd_code); 5563 rval = DFC_ARG_INVALID; 5564 goto done; 5565 } 5566 5567 if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 5568 KM_SLEEP)) == 0) { 5569 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5570 "emlxs_send_menlo_cmd: " 5571 "Unable to allocate mailbox buffer."); 5572 5573 rval = DFC_SYSRES_ERROR; 5574 goto done; 5575 } 5576 5577 mb = (MAILBOX *) mbq; 5578 5579 /* Create the set_variable mailbox request */ 5580 emlxs_mb_set_var(hba, mb, addr, value); 5581 5582 mbq->flag |= MBQ_PASSTHRU; 5583 5584 /* issue the mbox cmd to the sli */ 5585 mbxstatus = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0); 5586 5587 if (mbxstatus) { 5588 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5589 "emlxs_send_menlo_cmd: %s failed. mbxstatus=0x%x", 5590 emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus); 5591 5592 if (mbxstatus == MBX_TIMEOUT) { 5593 rval = DFC_TIMEOUT; 5594 } else { 5595 rval = DFC_IO_ERROR; 5596 } 5597 goto done; 5598 } 5599 5600 bcopy((void *)&rsp_code, (void *)rsp_buf, *rsp_size); 5601 5602 /* Check if we need to wait for maintenance mode */ 5603 if (mm_mode && !(hba->flag & FC_MENLO_MODE)) { 5604 /* Wait for link to come up in maintenance mode */ 5605 mutex_enter(&EMLXS_LINKUP_LOCK); 5606 5607 timeout = emlxs_timeout(hba, 30); 5608 5609 rval = 0; 5610 while ((rval != -1) && !(hba->flag & FC_MENLO_MODE)) { 5611 rval = 5612 cv_timedwait(&EMLXS_LINKUP_CV, 5613 &EMLXS_LINKUP_LOCK, timeout); 5614 } 5615 5616 mutex_exit(&EMLXS_LINKUP_LOCK); 5617 5618 if (rval == -1) { 5619 EMLXS_MSGF(EMLXS_CONTEXT, 5620 &emlxs_dfc_error_msg, 5621 "emlxs_send_menlo_cmd: " 5622 "Menlo maintenance mode error. Timeout."); 5623 5624 rval = DFC_TIMEOUT; 5625 goto done; 5626 } 5627 } 5628 } else { /* Standard commands */ 5629 5630 if (hba->state <= FC_LINK_DOWN) { 5631 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5632 "emlxs_send_menlo_cmd: Adapter link down."); 5633 5634 rval = DFC_LINKDOWN_ERROR; 5635 goto done; 5636 } 5637 5638 if (cmd_code == MENLO_CMD_FW_DOWNLOAD) { 5639 /* Check cmd size */ 5640 /* Must be at least 12 bytes of command */ 5641 /* plus 4 bytes of data */ 5642 if (cmd_size < (12 + 4)) { 5643 EMLXS_MSGF(EMLXS_CONTEXT, 5644 &emlxs_dfc_error_msg, 5645 "emlxs_send_menlo_cmd: " 5646 "Invalid command size. %d < %d", 5647 cmd_size, 5648 (12 + 4)); 5649 5650 rval = DFC_ARG_INVALID; 5651 goto done; 5652 } 5653 5654 /* Extract data buffer from command buffer */ 5655 data_buf = cmd_buf + 12; 5656 data_size = cmd_size - 12; 5657 cmd_size = 12; 5658 } 5659 5660 if (!(pkt = emlxs_pkt_alloc(port, cmd_size, *rsp_size, 0, 5661 KM_NOSLEEP))) { 5662 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5663 "emlxs_send_menlo_cmd: Unable to allocate packet."); 5664 5665 rval = DFC_SYSRES_ERROR; 5666 goto done; 5667 } 5668 5669 /* Make this a polled IO */ 5670 pkt->pkt_tran_flags &= ~FC_TRAN_INTR; 5671 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR; 5672 pkt->pkt_comp = NULL; 5673 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 5674 pkt->pkt_timeout = 30; 5675 5676 /* Build the fc header */ 5677 pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(EMLXS_MENLO_DID); 5678 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND; 5679 pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did); 5680 pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE; 5681 pkt->pkt_cmd_fhdr.f_ctl = 5682 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 5683 pkt->pkt_cmd_fhdr.seq_id = 0; 5684 pkt->pkt_cmd_fhdr.df_ctl = 0; 5685 pkt->pkt_cmd_fhdr.seq_cnt = 0; 5686 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 5687 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF; 5688 pkt->pkt_cmd_fhdr.ro = 0; 5689 5690 /* Copy in the command buffer */ 5691 bcopy((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size); 5692 5693 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 5694 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5695 "emlxs_send_menlo_cmd: Unable to send packet."); 5696 5697 rval = DFC_IO_ERROR; 5698 goto done; 5699 } 5700 5701 if (pkt->pkt_state != FC_PKT_SUCCESS) { 5702 if (pkt->pkt_state == FC_PKT_TIMEOUT) { 5703 EMLXS_MSGF(EMLXS_CONTEXT, 5704 &emlxs_dfc_error_msg, 5705 "emlxs_send_menlo_cmd: " 5706 "Pkt Transport error. Pkt Timeout."); 5707 rval = DFC_TIMEOUT; 5708 } else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) && 5709 (pkt->pkt_reason == FC_REASON_OVERRUN)) { 5710 EMLXS_MSGF(EMLXS_CONTEXT, 5711 &emlxs_dfc_error_msg, 5712 "emlxs_send_menlo_cmd: " 5713 "Pkt Transport error. Response overrun."); 5714 rval = DFC_RSP_BUF_OVERRUN; 5715 } else { 5716 EMLXS_MSGF(EMLXS_CONTEXT, 5717 &emlxs_dfc_error_msg, 5718 "emlxs_send_menlo_cmd: " 5719 "Pkt Transport error. state=%x", 5720 pkt->pkt_state); 5721 rval = DFC_IO_ERROR; 5722 } 5723 goto done; 5724 } 5725 5726 if (cmd_code == MENLO_CMD_FW_DOWNLOAD) { 5727 uint32_t *rsp; 5728 5729 /* Check response code */ 5730 rsp = (uint32_t *)pkt->pkt_resp; 5731 rsp_code = *rsp; 5732 rsp_code = SWAP_LONG(rsp_code); 5733 5734 if (rsp_code == MENLO_RSP_SUCCESS) { 5735 /* Now transmit the data phase */ 5736 5737 /* Save last rx_id */ 5738 uint32_t rx_id = pkt->pkt_cmd_fhdr.rx_id; 5739 5740 /* Free old pkt */ 5741 emlxs_pkt_free(pkt); 5742 5743 /* Allocate data pkt */ 5744 if (!(pkt = emlxs_pkt_alloc(port, data_size, 5745 *rsp_size, 0, KM_NOSLEEP))) { 5746 EMLXS_MSGF(EMLXS_CONTEXT, 5747 &emlxs_dfc_error_msg, 5748 "emlxs_send_menlo_cmd: " 5749 "Unable to allocate data " 5750 "packet."); 5751 5752 rval = DFC_SYSRES_ERROR; 5753 goto done; 5754 } 5755 5756 /* Make this a polled IO */ 5757 pkt->pkt_tran_flags &= ~FC_TRAN_INTR; 5758 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR; 5759 pkt->pkt_comp = NULL; 5760 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 5761 pkt->pkt_timeout = 30; 5762 5763 /* Build the fc header */ 5764 pkt->pkt_cmd_fhdr.d_id = 5765 SWAP_DATA24_LO(EMLXS_MENLO_DID); 5766 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND; 5767 pkt->pkt_cmd_fhdr.s_id = 5768 SWAP_DATA24_LO(port->did); 5769 pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE; 5770 pkt->pkt_cmd_fhdr.f_ctl = 5771 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | 5772 F_CTL_SEQ_INITIATIVE; 5773 pkt->pkt_cmd_fhdr.seq_id = 0; 5774 pkt->pkt_cmd_fhdr.df_ctl = 0; 5775 pkt->pkt_cmd_fhdr.seq_cnt = 0; 5776 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 5777 pkt->pkt_cmd_fhdr.rx_id = rx_id; 5778 pkt->pkt_cmd_fhdr.ro = 0; 5779 5780 /* Copy in the data buffer */ 5781 bcopy((void *)data_buf, (void *)pkt->pkt_cmd, 5782 data_size); 5783 5784 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 5785 EMLXS_MSGF(EMLXS_CONTEXT, 5786 &emlxs_dfc_error_msg, 5787 "emlxs_send_menlo_cmd: " 5788 "Unable to send data packet."); 5789 5790 rval = DFC_IO_ERROR; 5791 goto done; 5792 } 5793 5794 if (pkt->pkt_state != FC_PKT_SUCCESS) { 5795 if (pkt->pkt_state == FC_PKT_TIMEOUT) { 5796 EMLXS_MSGF(EMLXS_CONTEXT, 5797 &emlxs_dfc_error_msg, 5798 "emlxs_send_menlo_cmd: " 5799 "Data Pkt Transport " 5800 "error. Pkt Timeout."); 5801 rval = DFC_TIMEOUT; 5802 } else if ((pkt->pkt_state == 5803 FC_PKT_LOCAL_RJT) && 5804 (pkt->pkt_reason == 5805 FC_REASON_OVERRUN)) { 5806 EMLXS_MSGF(EMLXS_CONTEXT, 5807 &emlxs_dfc_error_msg, 5808 "emlxs_send_menlo_cmd: " 5809 "Data Pkt Transport " 5810 "error. Response overrun."); 5811 rval = DFC_RSP_BUF_OVERRUN; 5812 } else { 5813 EMLXS_MSGF(EMLXS_CONTEXT, 5814 &emlxs_dfc_error_msg, 5815 "emlxs_send_menlo_cmd: " 5816 "Data Pkt Transport " 5817 "error. state=%x", 5818 pkt->pkt_state); 5819 rval = DFC_IO_ERROR; 5820 } 5821 goto done; 5822 } 5823 } 5824 } 5825 5826 bcopy((void *)pkt->pkt_resp, (void *)rsp_buf, *rsp_size); 5827 *rsp_size = *rsp_size - pkt->pkt_resp_resid; 5828 } 5829 5830 rval = 0; 5831 5832 done: 5833 5834 if (pkt) { 5835 emlxs_pkt_free(pkt); 5836 } 5837 5838 if (mbq) { 5839 kmem_free(mbq, sizeof (MAILBOXQ)); 5840 } 5841 5842 return (rval); 5843 5844 } /* emlxs_send_menlo_cmd() */ 5845 5846 5847 /* ARGSUSED */ 5848 extern void 5849 emlxs_fcoe_attention_thread(emlxs_hba_t *hba, 5850 void *arg1, void *arg2) 5851 { 5852 emlxs_port_t *port = &PPORT; 5853 menlo_init_rsp_t *rsp; 5854 menlo_get_cmd_t *cmd; 5855 fc_packet_t *pkt = NULL; 5856 5857 if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_get_cmd_t), 5858 sizeof (menlo_init_rsp_t), 0, KM_NOSLEEP))) { 5859 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5860 "FCoE attention: Unable to allocate packet."); 5861 5862 return; 5863 } 5864 5865 /* Make this a polled IO */ 5866 pkt->pkt_tran_flags &= ~FC_TRAN_INTR; 5867 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR; 5868 pkt->pkt_comp = NULL; 5869 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 5870 pkt->pkt_timeout = 30; 5871 5872 /* Build the fc header */ 5873 pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(EMLXS_MENLO_DID); 5874 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND; 5875 pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did); 5876 pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE; 5877 pkt->pkt_cmd_fhdr.f_ctl = 5878 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 5879 pkt->pkt_cmd_fhdr.seq_id = 0; 5880 pkt->pkt_cmd_fhdr.df_ctl = 0; 5881 pkt->pkt_cmd_fhdr.seq_cnt = 0; 5882 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 5883 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF; 5884 pkt->pkt_cmd_fhdr.ro = 0; 5885 5886 cmd = (menlo_get_cmd_t *)pkt->pkt_cmd; 5887 cmd->code = MENLO_CMD_GET_INIT; 5888 cmd->context = 0; 5889 cmd->length = sizeof (menlo_init_rsp_t); 5890 5891 /* Little Endian Swap */ 5892 cmd->code = SWAP_LONG(cmd->code); 5893 cmd->length = SWAP_LONG(cmd->length); 5894 5895 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 5896 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5897 "FCoE attention: Unable to send packet."); 5898 5899 goto done; 5900 } 5901 5902 if (pkt->pkt_state != FC_PKT_SUCCESS) { 5903 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5904 "FCoE attention: Pkt Transport error. state=%x", 5905 pkt->pkt_state); 5906 5907 goto done; 5908 } 5909 5910 /* Check response code */ 5911 rsp = (menlo_init_rsp_t *)pkt->pkt_resp; 5912 rsp->code = SWAP_LONG(rsp->code); 5913 5914 if (rsp->code != MENLO_RSP_SUCCESS) { 5915 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5916 "FCoE attention: FCOE Response error =%x", rsp->code); 5917 5918 goto done; 5919 } 5920 5921 /* Little Endian Swap */ 5922 rsp->bb_credit = SWAP_LONG(rsp->bb_credit); 5923 rsp->frame_size = SWAP_LONG(rsp->frame_size); 5924 rsp->fw_version = SWAP_LONG(rsp->fw_version); 5925 rsp->reset_status = SWAP_LONG(rsp->reset_status); 5926 rsp->maint_status = SWAP_LONG(rsp->maint_status); 5927 rsp->fw_type = SWAP_LONG(rsp->fw_type); 5928 rsp->fru_data_valid = SWAP_LONG(rsp->fru_data_valid); 5929 5930 /* Log the event */ 5931 emlxs_log_fcoe_event(port, rsp); 5932 5933 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 5934 "MENLO_INIT: bb_credit = 0x%x", rsp->bb_credit); 5935 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 5936 "MENLO_INIT: frame_size = 0x%x", rsp->frame_size); 5937 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 5938 "MENLO_INIT: fw_version = 0x%x", rsp->fw_version); 5939 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 5940 "MENLO_INIT: reset_status = 0x%x", rsp->reset_status); 5941 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 5942 "MENLO_INIT: maint_status = 0x%x", rsp->maint_status); 5943 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 5944 "MENLO_INIT: fw_type = 0x%x", rsp->fw_type); 5945 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 5946 "MENLO_INIT: fru_data_valid = 0x%x", rsp->fru_data_valid); 5947 5948 /* Perform attention checks */ 5949 if (rsp->fru_data_valid == 0) { 5950 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_error_msg, 5951 "Invalid FRU data found on adapter. " 5952 "Return adapter to Emulex for repair."); 5953 } 5954 5955 switch (rsp->fw_type) { 5956 case MENLO_FW_TYPE_GOLDEN: 5957 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_warning_msg, 5958 "FCoE chip is running Golden firmware. " 5959 "Update FCoE firmware immediately."); 5960 break; 5961 5962 case MENLO_FW_TYPE_DIAG: 5963 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_notice_msg, 5964 "FCoE chip is running Diagnostic firmware. " 5965 "Operational use of the adapter is suspended."); 5966 break; 5967 } 5968 5969 done: 5970 5971 if (pkt) { 5972 emlxs_pkt_free(pkt); 5973 } 5974 5975 return; 5976 5977 } /* emlxs_fcoe_attention_thread() */ 5978 5979 #endif /* MENLO_SUPPORT */ 5980 5981 5982 static int32_t 5983 emlxs_dfc_write_flash(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 5984 { 5985 emlxs_port_t *port = &PPORT; 5986 uint32_t offset; 5987 uint32_t cnt; 5988 uint8_t *buffer; 5989 uint8_t *bptr; 5990 uint32_t i; 5991 5992 if (hba->bus_type != SBUS_FC) { 5993 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 5994 "%s: Invalid bus_type. (bus_type=%x)", 5995 emlxs_dfc_xlate(dfc->cmd), hba->bus_type); 5996 5997 return (DFC_ARG_INVALID); 5998 } 5999 6000 if (!(hba->flag & FC_OFFLINE_MODE)) { 6001 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6002 "%s: Adapter not offline.", emlxs_dfc_xlate(dfc->cmd)); 6003 6004 return (DFC_ONLINE_ERROR); 6005 } 6006 6007 if (!dfc->buf1 || !dfc->buf1_size) { 6008 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6009 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 6010 6011 return (DFC_ARG_NULL); 6012 } 6013 6014 offset = dfc->data1; 6015 cnt = dfc->data2; 6016 6017 if (offset > (64 * 1024)) { 6018 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6019 "%s: Offset too large. (offset=%d)", 6020 emlxs_dfc_xlate(dfc->cmd), offset); 6021 6022 return (DFC_ARG_TOOBIG); 6023 } 6024 6025 if (cnt > dfc->buf1_size) { 6026 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6027 "%s: Count too large. (count=%d)", 6028 emlxs_dfc_xlate(dfc->cmd), cnt); 6029 6030 return (DFC_ARG_TOOBIG); 6031 } 6032 6033 if ((cnt + offset) > (64 * 1024)) { 6034 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6035 "%s: Count+Offset too large. (count=%d offset=%d)", 6036 emlxs_dfc_xlate(dfc->cmd), cnt, offset); 6037 6038 return (DFC_ARG_TOOBIG); 6039 } 6040 6041 if (cnt == 0) { 6042 return (0); 6043 } 6044 6045 if ((buffer = (uint8_t *)kmem_zalloc(cnt, KM_NOSLEEP)) == NULL) { 6046 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6047 "%s: Unable to allocate buffer.", 6048 emlxs_dfc_xlate(dfc->cmd)); 6049 6050 return (DFC_SYSRES_ERROR); 6051 } 6052 6053 if (ddi_copyin((void *)dfc->buf1, (void *)buffer, cnt, mode) != 0) { 6054 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6055 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 6056 6057 kmem_free(buffer, cnt); 6058 return (DFC_COPYIN_ERROR); 6059 } 6060 6061 bptr = buffer; 6062 for (i = 0; i < cnt; i++) { 6063 SBUS_WRITE_FLASH_COPY(hba, offset, *bptr); 6064 offset++; 6065 bptr++; 6066 } 6067 6068 kmem_free(buffer, cnt); 6069 6070 return (0); 6071 6072 } /* emlxs_dfc_write_flash() */ 6073 6074 6075 static int32_t 6076 emlxs_dfc_read_flash(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 6077 { 6078 emlxs_port_t *port = &PPORT; 6079 uint32_t offset; 6080 uint32_t count; 6081 uint32_t outsz; 6082 uint8_t *buffer; 6083 uint8_t *bptr; 6084 uint32_t i; 6085 6086 if (hba->bus_type != SBUS_FC) { 6087 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6088 "%s: Invalid bus_type. (bus_type=%x)", 6089 emlxs_dfc_xlate(dfc->cmd), hba->bus_type); 6090 6091 return (DFC_ARG_INVALID); 6092 } 6093 6094 if (!(hba->flag & FC_OFFLINE_MODE)) { 6095 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6096 "%s: Adapter not offline.", emlxs_dfc_xlate(dfc->cmd)); 6097 6098 return (DFC_ONLINE_ERROR); 6099 } 6100 6101 if (!dfc->buf1 || !dfc->buf1_size) { 6102 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6103 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 6104 6105 return (DFC_ARG_NULL); 6106 } 6107 6108 offset = dfc->data1; 6109 count = dfc->data2; 6110 outsz = dfc->buf1_size; 6111 6112 if (offset > (64 * 1024)) { 6113 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6114 "%s: Offset too large. (offset=%d)", 6115 emlxs_dfc_xlate(dfc->cmd), offset); 6116 6117 return (DFC_ARG_TOOBIG); 6118 } 6119 6120 if ((count + offset) > (64 * 1024)) { 6121 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6122 "%s: Count+Offset too large. (count=%d offset=%d)", 6123 emlxs_dfc_xlate(dfc->cmd), count, offset); 6124 6125 return (DFC_ARG_TOOBIG); 6126 } 6127 6128 if (count < outsz) { 6129 outsz = count; 6130 } 6131 6132 if ((buffer = (uint8_t *)kmem_zalloc(outsz, KM_NOSLEEP)) == NULL) { 6133 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6134 "%s: Unable to allocate buffer.", 6135 emlxs_dfc_xlate(dfc->cmd)); 6136 6137 return (DFC_SYSRES_ERROR); 6138 } 6139 6140 bptr = buffer; 6141 for (i = 0; i < outsz; i++) { 6142 *bptr++ = SBUS_READ_FLASH_COPY(hba, offset++); 6143 } 6144 6145 if (ddi_copyout((void *)buffer, (void *)dfc->buf1, outsz, mode) != 0) { 6146 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6147 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 6148 6149 kmem_free(buffer, outsz); 6150 return (DFC_COPYOUT_ERROR); 6151 } 6152 6153 kmem_free(buffer, outsz); 6154 6155 return (0); 6156 6157 } /* emlxs_dfc_read_flash() */ 6158 6159 6160 static int32_t 6161 emlxs_dfc_send_els(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 6162 { 6163 emlxs_port_t *port = &PPORT; 6164 uint8_t *rsp_buf; 6165 uint8_t *cmd_buf; 6166 dfc_destid_t destid; 6167 uint32_t rsp_size; 6168 uint32_t cmd_size; 6169 uint32_t timeout; 6170 fc_packet_t *pkt = NULL; 6171 NODELIST *ndlp; 6172 uint32_t did; 6173 uint32_t rval = 0; 6174 char buffer[128]; 6175 6176 cmd_buf = dfc->buf1; 6177 cmd_size = dfc->buf1_size; 6178 rsp_buf = dfc->buf2; 6179 rsp_size = dfc->buf2_size; 6180 6181 timeout = 2 * hba->fc_ratov; 6182 6183 if (!cmd_size || !cmd_buf) { 6184 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6185 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 6186 6187 rval = DFC_ARG_NULL; 6188 goto done; 6189 } 6190 6191 if (!rsp_buf || !rsp_size) { 6192 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6193 "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd)); 6194 6195 rval = DFC_ARG_NULL; 6196 goto done; 6197 } 6198 6199 if (!dfc->buf3 || !dfc->buf3_size) { 6200 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6201 "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd)); 6202 6203 rval = DFC_ARG_NULL; 6204 goto done; 6205 } 6206 6207 if (dfc->buf3_size < sizeof (dfc_destid_t)) { 6208 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6209 "%s: Buffer3 too small. (size=%d)", 6210 emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size); 6211 6212 rval = DFC_ARG_TOOSMALL; 6213 goto done; 6214 } 6215 6216 if (!dfc->buf4 || !dfc->buf4_size) { 6217 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6218 "%s: Null buffer4 found.", emlxs_dfc_xlate(dfc->cmd)); 6219 6220 rval = DFC_ARG_NULL; 6221 goto done; 6222 } 6223 6224 if (dfc->buf4_size < sizeof (uint32_t)) { 6225 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6226 "%s: Buffer4 too small. (size=%d)", 6227 emlxs_dfc_xlate(dfc->cmd), dfc->buf4_size); 6228 6229 rval = DFC_ARG_TOOSMALL; 6230 goto done; 6231 } 6232 6233 if (ddi_copyin((void *)dfc->buf3, (void *)&destid, 6234 sizeof (dfc_destid_t), mode) != 0) { 6235 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6236 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 6237 6238 rval = DFC_COPYIN_ERROR; 6239 goto done; 6240 } 6241 6242 if (destid.idType == 0) { 6243 if ((ndlp = emlxs_node_find_wwpn(port, destid.wwpn)) == NULL) { 6244 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6245 "%s: WWPN does not exists. %s", 6246 emlxs_dfc_xlate(dfc->cmd), emlxs_wwn_xlate(buffer, 6247 destid.wwpn)); 6248 6249 rval = DFC_ARG_INVALID; 6250 goto done; 6251 } 6252 did = ndlp->nlp_DID; 6253 } else { 6254 if (emlxs_node_find_did(port, destid.d_id) == NULL) { 6255 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6256 "%s: DID does not exist. did=%x", 6257 emlxs_dfc_xlate(dfc->cmd), destid.d_id); 6258 6259 rval = DFC_ARG_INVALID; 6260 goto done; 6261 } 6262 did = destid.d_id; 6263 } 6264 6265 if (did == 0) { 6266 did = port->did; 6267 } 6268 6269 if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size, 0, KM_NOSLEEP))) { 6270 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6271 "%s: Unable to allocate packet.", 6272 emlxs_dfc_xlate(dfc->cmd)); 6273 6274 rval = DFC_SYSRES_ERROR; 6275 goto done; 6276 } 6277 6278 /* Make this a polled IO */ 6279 pkt->pkt_tran_flags &= ~FC_TRAN_INTR; 6280 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR; 6281 pkt->pkt_comp = NULL; 6282 6283 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 6284 pkt->pkt_timeout = (timeout) ? timeout : 30; 6285 6286 /* Build the fc header */ 6287 pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(did); 6288 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ; 6289 pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did); 6290 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 6291 pkt->pkt_cmd_fhdr.f_ctl = 6292 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 6293 pkt->pkt_cmd_fhdr.seq_id = 0; 6294 pkt->pkt_cmd_fhdr.df_ctl = 0; 6295 pkt->pkt_cmd_fhdr.seq_cnt = 0; 6296 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 6297 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF; 6298 pkt->pkt_cmd_fhdr.ro = 0; 6299 6300 /* Copy in the command buffer */ 6301 if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size, 6302 mode) != 0) { 6303 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6304 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 6305 6306 rval = DFC_COPYIN_ERROR; 6307 goto done; 6308 } 6309 6310 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 6311 rval = DFC_IO_ERROR; 6312 goto done; 6313 } 6314 6315 if (pkt->pkt_state != FC_PKT_SUCCESS) { 6316 if (pkt->pkt_state == FC_PKT_TIMEOUT) { 6317 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6318 "Pkt Transport error. Pkt Timeout."); 6319 rval = DFC_TIMEOUT; 6320 } else { 6321 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6322 "Pkt Transport error. state=%x", pkt->pkt_state); 6323 rval = DFC_IO_ERROR; 6324 } 6325 goto done; 6326 } 6327 6328 rsp_size -= pkt->pkt_resp_resid; 6329 if (ddi_copyout((void *)pkt->pkt_resp, (void *)rsp_buf, rsp_size, 6330 mode) != 0) { 6331 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6332 "%s: rsp_buf ddi_copyout failed.", 6333 emlxs_dfc_xlate(dfc->cmd)); 6334 6335 rval = DFC_COPYOUT_ERROR; 6336 goto done; 6337 } 6338 6339 if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf4, 6340 sizeof (uint32_t), mode) != 0) { 6341 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6342 "%s: rsp_size ddi_copyout failed.", 6343 emlxs_dfc_xlate(dfc->cmd)); 6344 6345 rval = DFC_COPYOUT_ERROR; 6346 goto done; 6347 } 6348 6349 rval = 0; 6350 6351 done: 6352 if (pkt) { 6353 emlxs_pkt_free(pkt); 6354 } 6355 6356 return (rval); 6357 6358 } /* emlxs_dfc_send_els() */ 6359 6360 6361 static int32_t 6362 emlxs_dfc_get_ioinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 6363 { 6364 emlxs_port_t *port = &PPORT; 6365 dfc_ioinfo_t ioinfo; 6366 uint32_t i; 6367 6368 if (!dfc->buf1 || !dfc->buf1_size) { 6369 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6370 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 6371 6372 return (DFC_ARG_NULL); 6373 } 6374 6375 if (dfc->buf1_size < sizeof (dfc_ioinfo_t)) { 6376 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6377 "%s: Buffer1 too small. (size=%d)", 6378 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 6379 6380 return (DFC_ARG_TOOSMALL); 6381 } 6382 6383 bzero(&ioinfo, sizeof (dfc_ioinfo_t)); 6384 6385 ioinfo.a_mboxCmd = HBASTATS.MboxIssued; 6386 ioinfo.a_mboxCmpl = HBASTATS.MboxCompleted; 6387 ioinfo.a_mboxErr = HBASTATS.MboxError; 6388 6389 for (i = 0; i < MAX_RINGS; i++) { 6390 ioinfo.a_iocbCmd += HBASTATS.IocbIssued[i]; 6391 ioinfo.a_iocbRsp += HBASTATS.IocbReceived[i]; 6392 } 6393 6394 ioinfo.a_adapterIntr = HBASTATS.IntrEvent[0] + HBASTATS.IntrEvent[1] + 6395 HBASTATS.IntrEvent[2] + HBASTATS.IntrEvent[3] + 6396 HBASTATS.IntrEvent[4] + HBASTATS.IntrEvent[5] + 6397 HBASTATS.IntrEvent[6] + HBASTATS.IntrEvent[7]; 6398 6399 ioinfo.a_fcpCmd = HBASTATS.FcpIssued; 6400 ioinfo.a_fcpCmpl = HBASTATS.FcpCompleted; 6401 ioinfo.a_fcpErr = HBASTATS.FcpCompleted - HBASTATS.FcpGood; 6402 6403 ioinfo.a_seqXmit = HBASTATS.IpSeqIssued; 6404 ioinfo.a_seqRcv = HBASTATS.IpSeqReceived; 6405 ioinfo.a_seqXmitErr = HBASTATS.IpSeqCompleted - HBASTATS.IpSeqGood; 6406 6407 ioinfo.a_bcastXmit = HBASTATS.IpBcastIssued; 6408 ioinfo.a_bcastRcv = HBASTATS.IpBcastReceived; 6409 6410 ioinfo.a_elsXmit = HBASTATS.ElsCmdIssued; 6411 ioinfo.a_elsRcv = HBASTATS.ElsCmdReceived; 6412 ioinfo.a_elsXmitErr = HBASTATS.ElsCmdCompleted - HBASTATS.ElsCmdGood; 6413 6414 ioinfo.a_RSCNRcv = HBASTATS.ElsRscnReceived; 6415 6416 ioinfo.a_elsBufPost = HBASTATS.ElsUbPosted; 6417 ioinfo.a_ipBufPost = HBASTATS.IpUbPosted; 6418 6419 ioinfo.a_cnt1 = 0; 6420 ioinfo.a_cnt2 = 0; 6421 ioinfo.a_cnt3 = 0; 6422 ioinfo.a_cnt4 = 0; 6423 6424 if (ddi_copyout((void *)&ioinfo, (void *)dfc->buf1, 6425 sizeof (dfc_ioinfo_t), mode) != 0) { 6426 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6427 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 6428 6429 return (DFC_COPYOUT_ERROR); 6430 } 6431 6432 return (0); 6433 6434 } /* emlxs_dfc_get_ioinfo() */ 6435 6436 6437 static int32_t 6438 emlxs_dfc_get_linkinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 6439 { 6440 emlxs_port_t *port = &PPORT; 6441 dfc_linkinfo_t linkinfo; 6442 6443 if (!dfc->buf1 || !dfc->buf1_size) { 6444 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6445 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 6446 6447 return (DFC_ARG_NULL); 6448 } 6449 6450 if (dfc->buf1_size < sizeof (dfc_linkinfo_t)) { 6451 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6452 "%s: Buffer1 too small. (size=%d)", 6453 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 6454 6455 return (DFC_ARG_TOOSMALL); 6456 } 6457 6458 bzero(&linkinfo, sizeof (dfc_linkinfo_t)); 6459 6460 linkinfo.a_linkEventTag = hba->link_event_tag; 6461 linkinfo.a_linkUp = HBASTATS.LinkUp; 6462 linkinfo.a_linkDown = HBASTATS.LinkDown; 6463 linkinfo.a_linkMulti = HBASTATS.LinkMultiEvent; 6464 linkinfo.a_DID = port->did; 6465 linkinfo.a_topology = 0; 6466 6467 if (hba->state <= FC_LINK_DOWN) { 6468 linkinfo.a_linkState = LNK_DOWN; 6469 } 6470 #ifdef MENLO_SUPPORT 6471 else if (hba->flag & FC_MENLO_MODE) { 6472 linkinfo.a_linkState = LNK_DOWN; 6473 linkinfo.a_topology = LNK_MENLO_MAINTENANCE; 6474 6475 } 6476 #endif /* MENLO_SUPPORT */ 6477 else if (hba->state < FC_READY) { 6478 linkinfo.a_linkState = LNK_DISCOVERY; 6479 } else { 6480 linkinfo.a_linkState = LNK_READY; 6481 } 6482 6483 if (linkinfo.a_linkState != LNK_DOWN) { 6484 if (hba->topology == TOPOLOGY_LOOP) { 6485 if (hba->flag & FC_FABRIC_ATTACHED) { 6486 linkinfo.a_topology = LNK_PUBLIC_LOOP; 6487 } else { 6488 linkinfo.a_topology = LNK_LOOP; 6489 } 6490 6491 linkinfo.a_alpa = port->did & 0xff; 6492 linkinfo.a_alpaCnt = port->alpa_map[0]; 6493 6494 if (linkinfo.a_alpaCnt > 127) { 6495 linkinfo.a_alpaCnt = 127; 6496 } 6497 6498 bcopy((void *)&port->alpa_map[0], linkinfo.a_alpaMap, 6499 linkinfo.a_alpaCnt + 1); 6500 } else { 6501 if (hba->flag & FC_FABRIC_ATTACHED) { 6502 linkinfo.a_topology = LNK_FABRIC; 6503 } else { 6504 linkinfo.a_topology = LNK_PT2PT; 6505 } 6506 } 6507 } 6508 6509 bcopy(&hba->wwpn, linkinfo.a_wwpName, 8); 6510 bcopy(&hba->wwnn, linkinfo.a_wwnName, 8); 6511 6512 if (ddi_copyout((void *)&linkinfo, (void *)dfc->buf1, 6513 sizeof (dfc_linkinfo_t), mode) != 0) { 6514 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6515 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 6516 6517 return (DFC_COPYOUT_ERROR); 6518 } 6519 6520 return (0); 6521 6522 } /* emlxs_dfc_get_linkinfo() */ 6523 6524 #ifdef SFCT_SUPPORT 6525 static int32_t 6526 emlxs_dfc_get_fctstat(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 6527 { 6528 emlxs_port_t *port = &PPORT; 6529 emlxs_tgtport_stat_t *statp = &TGTPORTSTAT; 6530 dfc_tgtport_stat_t dfcstat; 6531 6532 if (!dfc->buf1 || !dfc->buf1_size) { 6533 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6534 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 6535 6536 return (DFC_ARG_NULL); 6537 } 6538 6539 if (dfc->buf1_size < sizeof (emlxs_tgtport_stat_t)) { 6540 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6541 "%s: Buffer1 too small. (size=%d)", 6542 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 6543 6544 return (DFC_ARG_TOOSMALL); 6545 } 6546 6547 bzero(&dfcstat, sizeof (dfcstat)); 6548 6549 dfcstat.Version = DFC_TGTPORT_STAT_VERSION; 6550 6551 dfcstat.FctRcvDropped = statp->FctRcvDropped; 6552 dfcstat.FctOverQDepth = statp->FctOverQDepth; 6553 dfcstat.FctOutstandingIO = statp->FctOutstandingIO; 6554 dfcstat.FctFailedPortRegister = statp->FctFailedPortRegister; 6555 dfcstat.FctPortRegister = statp->FctPortRegister; 6556 dfcstat.FctPortDeregister = statp->FctPortDeregister; 6557 6558 dfcstat.FctAbortSent = statp->FctAbortSent; 6559 dfcstat.FctNoBuffer = statp->FctNoBuffer; 6560 dfcstat.FctScsiStatusErr = statp->FctScsiStatusErr; 6561 dfcstat.FctScsiQfullErr = statp->FctScsiQfullErr; 6562 dfcstat.FctScsiResidOver = statp->FctScsiResidOver; 6563 dfcstat.FctScsiResidUnder = statp->FctScsiResidUnder; 6564 dfcstat.FctScsiSenseErr = statp->FctScsiSenseErr; 6565 6566 dfcstat.FctEvent = statp->FctEvent; 6567 dfcstat.FctCompleted = statp->FctCompleted; 6568 dfcstat.FctCmplGood = statp->FctCmplGood; 6569 dfcstat.FctCmplError = statp->FctCmplError; 6570 dfcstat.FctStray = statp->FctStray; 6571 6572 bcopy(&statp->FctP2IOWcnt[0], &dfcstat.FctP2IOWcnt[0], 6573 (sizeof (uint64_t) * MAX_TGTPORT_IOCNT)); 6574 bcopy(&statp->FctP2IORcnt[0], &dfcstat.FctP2IORcnt[0], 6575 (sizeof (uint64_t) * MAX_TGTPORT_IOCNT)); 6576 dfcstat.FctIOCmdCnt = statp->FctIOCmdCnt; 6577 dfcstat.FctReadBytes = statp->FctReadBytes; 6578 dfcstat.FctWriteBytes = statp->FctWriteBytes; 6579 dfcstat.FctCmdReceived = statp->FctCmdReceived; 6580 6581 if (dfc->flag) { /* Clear counters after read */ 6582 bzero(&statp->FctP2IOWcnt[0], 6583 (sizeof (uint64_t) * MAX_TGTPORT_IOCNT)); 6584 bzero(&statp->FctP2IORcnt[0], 6585 (sizeof (uint64_t) * MAX_TGTPORT_IOCNT)); 6586 statp->FctIOCmdCnt = 0; 6587 statp->FctReadBytes = 0; 6588 statp->FctWriteBytes = 0; 6589 statp->FctCmdReceived = 0; 6590 } 6591 if (hba->state <= FC_LINK_DOWN) { 6592 dfcstat.FctLinkState = LNK_DOWN; 6593 } 6594 #ifdef MENLO_SUPPORT 6595 else if (hba->flag & FC_MENLO_MODE) { 6596 dfcstat.FctLinkState = LNK_DOWN; 6597 } 6598 #endif /* MENLO_SUPPORT */ 6599 else if (hba->state < FC_READY) { 6600 dfcstat.FctLinkState = LNK_DISCOVERY; 6601 } else { 6602 dfcstat.FctLinkState = LNK_READY; 6603 } 6604 6605 if (ddi_copyout((void *)&dfcstat, (void *)dfc->buf1, 6606 sizeof (dfc_tgtport_stat_t), mode) != 0) { 6607 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6608 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 6609 6610 return (DFC_COPYOUT_ERROR); 6611 } 6612 6613 return (0); 6614 6615 } /* emlxs_dfc_get_fctstat() */ 6616 #endif /* SFCT_SUPPORT */ 6617 6618 static int32_t 6619 emlxs_dfc_get_nodeinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 6620 { 6621 emlxs_port_t *port; 6622 emlxs_config_t *cfg = &CFG; 6623 dfc_node_t *dfc_node; 6624 dfc_node_t *dnp; 6625 uint32_t node_count; 6626 NODELIST *nlp; 6627 uint32_t size; 6628 uint32_t i; 6629 6630 port = &VPORT(dfc->data1); 6631 6632 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.", 6633 emlxs_dfc_xlate(dfc->cmd)); 6634 6635 if (!dfc->buf1 || !dfc->buf1_size) { 6636 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6637 "%s: NULL buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 6638 6639 return (DFC_ARG_NULL); 6640 } 6641 6642 if (dfc->buf1_size < (sizeof (dfc_node_t) * MAX_NODES)) { 6643 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6644 "%s: Buffer1 too small. (size=%d)", 6645 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 6646 6647 return (DFC_ARG_TOOSMALL); 6648 } 6649 6650 if (!dfc->buf2 || !dfc->buf2_size) { 6651 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6652 "%s: NULL buffer2 found.", emlxs_dfc_xlate(dfc->cmd)); 6653 6654 return (DFC_ARG_NULL); 6655 } 6656 6657 if (dfc->buf2_size < sizeof (uint32_t)) { 6658 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6659 "%s: Buffer2 too small. (size=%d)", 6660 emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size); 6661 6662 return (DFC_ARG_TOOSMALL); 6663 } 6664 6665 node_count = port->node_count; 6666 6667 if (node_count == 0) { 6668 return (0); 6669 } 6670 6671 if (node_count > MAX_NODES) { 6672 node_count = MAX_NODES; 6673 } 6674 6675 size = node_count * sizeof (dfc_node_t); 6676 6677 if (!(dfc_node = (dfc_node_t *)kmem_zalloc(size, KM_NOSLEEP))) { 6678 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6679 "%s: Unable to allocate dfc_node.", 6680 emlxs_dfc_xlate(dfc->cmd)); 6681 6682 return (DFC_SYSRES_ERROR); 6683 } 6684 6685 dnp = dfc_node; 6686 6687 rw_enter(&port->node_rwlock, RW_READER); 6688 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 6689 nlp = port->node_table[i]; 6690 while (nlp != NULL) { 6691 dnp->port_id = nlp->nlp_DID; 6692 dnp->rpi = nlp->nlp_Rpi; 6693 dnp->xri = nlp->nlp_Xri; 6694 6695 bcopy((char *)&nlp->sparm, (char *)&dnp->sparm, 6696 sizeof (dnp->sparm)); 6697 6698 if (nlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE) { 6699 dnp->flags |= PORT_FLAG_FCP_TARGET; 6700 } 6701 if (nlp->nlp_fcp_info & NLP_FCP_INI_DEVICE) { 6702 dnp->flags |= PORT_FLAG_FCP_INI; 6703 6704 } 6705 if (nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { 6706 dnp->flags |= PORT_FLAG_FCP2; 6707 } 6708 if (cfg[CFG_NETWORK_ON].current && nlp->nlp_Xri) { 6709 dnp->flags |= PORT_FLAG_IP; 6710 } 6711 if (nlp->nlp_fcp_info & NLP_EMLX_VPORT) { 6712 dnp->flags |= PORT_FLAG_VPORT; 6713 } 6714 6715 dnp++; 6716 nlp = (NODELIST *) nlp->nlp_list_next; 6717 } 6718 } 6719 rw_exit(&port->node_rwlock); 6720 6721 if (ddi_copyout((void *)dfc_node, (void *)dfc->buf1, size, mode) != 0) { 6722 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6723 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 6724 6725 kmem_free(dfc_node, size); 6726 return (DFC_COPYOUT_ERROR); 6727 } 6728 6729 if (ddi_copyout((void *)&node_count, (void *)dfc->buf2, 6730 sizeof (uint32_t), mode) != 0) { 6731 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6732 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 6733 6734 kmem_free(dfc_node, size); 6735 return (DFC_COPYOUT_ERROR); 6736 } 6737 6738 kmem_free(dfc_node, size); 6739 6740 return (0); 6741 6742 } /* emlxs_dfc_get_nodeinfo() */ 6743 6744 6745 static int32_t 6746 emlxs_dfc_read_mem(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 6747 { 6748 emlxs_port_t *port = &PPORT; 6749 uint32_t offset; 6750 uint32_t size; 6751 uint32_t max_size; 6752 uint8_t *buffer; 6753 uint8_t *slim; 6754 6755 offset = dfc->data1; 6756 size = dfc->data2; 6757 6758 if (!dfc->buf1 || !dfc->buf1_size) { 6759 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6760 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 6761 6762 return (DFC_ARG_NULL); 6763 } 6764 6765 if (size > dfc->buf1_size) { 6766 size = dfc->buf1_size; 6767 } 6768 6769 if (offset % 4) { 6770 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6771 "%s: Offset misaligned. (offset=%d)", 6772 emlxs_dfc_xlate(dfc->cmd), offset); 6773 6774 return (DFC_ARG_MISALIGNED); 6775 } 6776 6777 if (size % 4) { 6778 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6779 "%s: Size misaligned. (size=%d)", 6780 emlxs_dfc_xlate(dfc->cmd), size); 6781 6782 return (DFC_ARG_MISALIGNED); 6783 } 6784 6785 if (hba->flag & FC_SLIM2_MODE) { 6786 max_size = SLI2_SLIM2_SIZE; 6787 } else { 6788 max_size = 4096; 6789 } 6790 6791 if (offset >= max_size) { 6792 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6793 "%s: Offset too large. (offset=%d)", 6794 emlxs_dfc_xlate(dfc->cmd), offset); 6795 6796 return (DFC_ARG_TOOBIG); 6797 } 6798 6799 if ((size + offset) > max_size) { 6800 size = (max_size - offset); 6801 } 6802 6803 if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_NOSLEEP))) { 6804 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6805 "%s: Unable to allocate buffer.", 6806 emlxs_dfc_xlate(dfc->cmd)); 6807 6808 return (DFC_SYSRES_ERROR); 6809 } 6810 6811 if (hba->flag & FC_SLIM2_MODE) { 6812 slim = (uint8_t *)hba->slim2.virt + offset; 6813 emlxs_pcimem_bcopy((uint32_t *)slim, (uint32_t *)buffer, 6814 size); 6815 } else { 6816 slim = (uint8_t *)hba->slim_addr + offset; 6817 READ_SLIM_COPY(hba, (uint32_t *)buffer, (uint32_t *)slim, 6818 (size / 4)); 6819 } 6820 6821 if (ddi_copyout((void *)buffer, (void *)dfc->buf1, size, mode) != 0) { 6822 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6823 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 6824 6825 kmem_free(buffer, size); 6826 return (DFC_COPYOUT_ERROR); 6827 } 6828 6829 kmem_free(buffer, size); 6830 6831 return (0); 6832 6833 } /* emlxs_dfc_read_mem() */ 6834 6835 6836 static int32_t 6837 emlxs_dfc_write_mem(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 6838 { 6839 emlxs_port_t *port = &PPORT; 6840 uint32_t offset; 6841 uint32_t size; 6842 uint32_t max_size; 6843 uint8_t *buffer; 6844 uint8_t *slim; 6845 6846 offset = dfc->data1; 6847 size = dfc->data2; 6848 6849 if (!dfc->buf1 || !dfc->buf1_size) { 6850 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6851 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 6852 6853 return (DFC_ARG_NULL); 6854 } 6855 6856 if (size > dfc->buf1_size) { 6857 size = dfc->buf1_size; 6858 } 6859 6860 if (offset % 4) { 6861 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6862 "%s: Offset misaligned. (offset=%d)", 6863 emlxs_dfc_xlate(dfc->cmd), offset); 6864 6865 return (DFC_ARG_MISALIGNED); 6866 } 6867 6868 if (size % 4) { 6869 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6870 "%s: Size misaligned. (szie=%d)", 6871 emlxs_dfc_xlate(dfc->cmd), size); 6872 6873 return (DFC_ARG_MISALIGNED); 6874 } 6875 6876 if (hba->flag & FC_SLIM2_MODE) { 6877 max_size = SLI2_SLIM2_SIZE; 6878 } else { 6879 max_size = 4096; 6880 } 6881 6882 if (offset >= max_size) { 6883 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6884 "%s: Offset too large. (offset=%d)", 6885 emlxs_dfc_xlate(dfc->cmd), offset); 6886 6887 return (DFC_ARG_TOOBIG); 6888 } 6889 6890 if ((size + offset) > max_size) { 6891 size = (max_size - offset); 6892 } 6893 6894 if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_NOSLEEP))) { 6895 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6896 "%s: Unable to allocate buffer.", 6897 emlxs_dfc_xlate(dfc->cmd)); 6898 6899 return (DFC_SYSRES_ERROR); 6900 } 6901 6902 if (ddi_copyin((void *)dfc->buf1, (void *)buffer, size, mode) != 0) { 6903 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6904 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 6905 6906 kmem_free(buffer, size); 6907 return (DFC_COPYIN_ERROR); 6908 } 6909 6910 if (hba->flag & FC_SLIM2_MODE) { 6911 slim = (uint8_t *)hba->slim2.virt + offset; 6912 emlxs_pcimem_bcopy((uint32_t *)buffer, (uint32_t *)slim, 6913 size); 6914 } else { 6915 slim = (uint8_t *)hba->slim_addr + offset; 6916 WRITE_SLIM_COPY(hba, (uint32_t *)buffer, (uint32_t *)slim, 6917 (size / 4)); 6918 } 6919 6920 kmem_free(buffer, size); 6921 6922 return (0); 6923 6924 } /* emlxs_dfc_write_mem() */ 6925 6926 6927 /* ARGSUSED */ 6928 static int32_t 6929 emlxs_dfc_write_ctlreg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 6930 { 6931 emlxs_port_t *port = &PPORT; 6932 uint32_t offset; 6933 uint32_t value; 6934 6935 offset = dfc->data1; 6936 value = dfc->data2; 6937 6938 if (!(hba->flag & FC_OFFLINE_MODE)) { 6939 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6940 "%s: Adapter not offline.", emlxs_dfc_xlate(dfc->cmd)); 6941 6942 return (DFC_ONLINE_ERROR); 6943 } 6944 6945 if (offset % 4) { 6946 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6947 "%s: Offset misaligned. (offset=%d)", 6948 emlxs_dfc_xlate(dfc->cmd), offset); 6949 6950 return (DFC_ARG_MISALIGNED); 6951 } 6952 6953 if (offset > 255) { 6954 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6955 "%s: Offset too large. (offset=%d)", 6956 emlxs_dfc_xlate(dfc->cmd), offset); 6957 6958 return (DFC_ARG_TOOBIG); 6959 } 6960 6961 WRITE_CSR_REG(hba, (hba->csr_addr + offset), value); 6962 6963 return (0); 6964 6965 } /* emlxs_dfc_write_ctlreg() */ 6966 6967 6968 static int32_t 6969 emlxs_dfc_read_ctlreg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 6970 { 6971 emlxs_port_t *port = &PPORT; 6972 uint32_t offset; 6973 uint32_t value; 6974 6975 offset = dfc->data1; 6976 6977 if (offset % 4) { 6978 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6979 "%s: Offset misaligned. (offset=%d)", 6980 emlxs_dfc_xlate(dfc->cmd), offset); 6981 6982 return (DFC_ARG_MISALIGNED); 6983 } 6984 6985 if (offset > 255) { 6986 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6987 "%s: Offset too large. (offset=%d)", 6988 emlxs_dfc_xlate(dfc->cmd), offset); 6989 6990 return (DFC_ARG_TOOBIG); 6991 } 6992 6993 if (!dfc->buf1 || !dfc->buf1_size) { 6994 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 6995 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 6996 6997 return (DFC_ARG_NULL); 6998 } 6999 7000 if (dfc->buf1_size < sizeof (uint32_t)) { 7001 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7002 "%s: Buffer1 too small. (size=%d)", 7003 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 7004 7005 return (DFC_ARG_TOOSMALL); 7006 } 7007 7008 value = READ_CSR_REG(hba, (hba->csr_addr + offset)); 7009 7010 if (ddi_copyout((void *)&value, (void *)dfc->buf1, sizeof (uint32_t), 7011 mode) != 0) { 7012 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7013 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 7014 7015 return (DFC_COPYOUT_ERROR); 7016 } 7017 7018 return (0); 7019 7020 } /* emlxs_dfc_read_ctlreg() */ 7021 7022 7023 static int32_t 7024 emlxs_dfc_set_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 7025 { 7026 emlxs_port_t *port = &PPORT; 7027 uint32_t event; 7028 uint32_t enable; 7029 uint32_t pid; 7030 uint32_t count; 7031 uint32_t i; 7032 emlxs_dfc_event_t *dfc_event; 7033 7034 event = dfc->data1; 7035 pid = dfc->data2; 7036 enable = dfc->flag; 7037 7038 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 7039 "%s: %s. pid=%d enable=%d", emlxs_dfc_xlate(dfc->cmd), 7040 emlxs_dfc_event_xlate(event), pid, enable); 7041 7042 switch (event) { 7043 case FC_REG_LINK_EVENT: 7044 case FC_REG_RSCN_EVENT: 7045 case FC_REG_CT_EVENT: 7046 case FC_REG_DUMP_EVENT: 7047 case FC_REG_TEMP_EVENT: 7048 case FC_REG_VPORTRSCN_EVENT: 7049 case FC_REG_FCOE_EVENT: 7050 break; 7051 7052 case FC_REG_MULTIPULSE_EVENT: 7053 default: 7054 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7055 "%s: %s. Invalid event. pid=%d enable=%d", 7056 emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event), 7057 pid, enable); 7058 7059 return (DFC_ARG_INVALID); 7060 } 7061 7062 if (enable) { 7063 if (dfc->buf1_size < sizeof (uint32_t)) { 7064 dfc->buf1 = NULL; 7065 } else if (!dfc->buf1) { 7066 dfc->buf1_size = 0; 7067 } 7068 7069 /* Make sure this pid/event is not already registered */ 7070 dfc_event = NULL; 7071 for (i = 0; i < MAX_DFC_EVENTS; i++) { 7072 dfc_event = &hba->dfc_event[i]; 7073 7074 if (dfc_event->pid == pid && 7075 dfc_event->event == event) { 7076 break; 7077 } 7078 } 7079 7080 if (i == MAX_DFC_EVENTS) { 7081 /* Find next available event object */ 7082 for (i = 0; i < MAX_DFC_EVENTS; i++) { 7083 dfc_event = &hba->dfc_event[i]; 7084 7085 if (!dfc_event->pid && !dfc_event->event) { 7086 break; 7087 } 7088 } 7089 7090 /* Return if all event objects are busy */ 7091 if (i == MAX_DFC_EVENTS) { 7092 EMLXS_MSGF(EMLXS_CONTEXT, 7093 &emlxs_dfc_error_msg, 7094 "%s: %s. Too many events registered. " 7095 "pid=%d enable=%d", 7096 emlxs_dfc_xlate(dfc->cmd), 7097 emlxs_dfc_event_xlate(event), pid, 7098 enable); 7099 7100 return (DFC_DRVRES_ERROR); 7101 } 7102 } 7103 7104 /* Initialize */ 7105 dfc_event->pid = pid; 7106 dfc_event->event = event; 7107 dfc_event->last_id = (uint32_t)-1; 7108 dfc_event->dataout = NULL; 7109 dfc_event->size = 0; 7110 dfc_event->mode = 0; 7111 7112 (void) emlxs_get_dfc_event(port, dfc_event, 0); 7113 7114 if (dfc->buf1) { 7115 if (ddi_copyout((void *)&dfc_event->last_id, 7116 dfc->buf1, sizeof (uint32_t), mode) != 0) { 7117 EMLXS_MSGF(EMLXS_CONTEXT, 7118 &emlxs_dfc_error_msg, 7119 "%s: ddi_copyout failed.", 7120 emlxs_dfc_xlate(dfc->cmd)); 7121 7122 return (DFC_COPYOUT_ERROR); 7123 } 7124 } 7125 7126 /* 7127 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 7128 * "%s: %s. Enabled. pid=%d id=%d", emlxs_dfc_xlate(dfc->cmd), 7129 * emlxs_dfc_event_xlate(event), pid, dfc_event->last_id); 7130 */ 7131 7132 hba->log_events |= event; 7133 } else { /* Disable */ 7134 7135 /* Find the event entry */ 7136 dfc_event = NULL; 7137 for (i = 0; i < MAX_DFC_EVENTS; i++) { 7138 dfc_event = &hba->dfc_event[i]; 7139 7140 if (dfc_event->pid == pid && 7141 dfc_event->event == event) { 7142 break; 7143 } 7144 } 7145 7146 if (i == MAX_DFC_EVENTS) { 7147 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7148 "%s: %s. Event not registered. pid=%d enable=%d", 7149 emlxs_dfc_xlate(dfc->cmd), 7150 emlxs_dfc_event_xlate(event), pid, enable); 7151 7152 return (DFC_ARG_INVALID); 7153 } 7154 7155 /* Kill the event thread if it is sleeping */ 7156 (void) emlxs_kill_dfc_event(port, dfc_event); 7157 7158 /* Count the number of pids still registered for this event */ 7159 count = 0; 7160 for (i = 0; i < MAX_DFC_EVENTS; i++) { 7161 dfc_event = &hba->dfc_event[i]; 7162 7163 if (dfc_event->event == event) { 7164 count++; 7165 } 7166 } 7167 7168 /* If no more pids need this event, */ 7169 /* then disable logging for this event */ 7170 if (count == 0) { 7171 hba->log_events &= ~event; 7172 } 7173 } 7174 7175 return (0); 7176 7177 } /* emlxs_dfc_set_event() */ 7178 7179 7180 static int32_t 7181 emlxs_dfc_get_eventinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 7182 { 7183 emlxs_port_t *port = &PPORT; 7184 uint32_t size; 7185 int32_t rval = 0; 7186 HBA_EVENTINFO *event_buffer = NULL; 7187 uint32_t event_count = 0; 7188 uint32_t missed = 0; 7189 7190 if (!dfc->buf1 || !dfc->buf1_size) { 7191 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7192 "%s: Null buffer1 buffer.", emlxs_dfc_xlate(dfc->cmd)); 7193 7194 return (DFC_ARG_NULL); 7195 } 7196 7197 event_count = dfc->buf1_size / sizeof (HBA_EVENTINFO); 7198 7199 if (!event_count) { 7200 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7201 "%s: Buffer1 too small. (size=%d)", 7202 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 7203 7204 return (DFC_ARG_TOOSMALL); 7205 } 7206 7207 if (!dfc->buf2 || !dfc->buf2_size) { 7208 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7209 "%s: Null buffer2 buffer.", emlxs_dfc_xlate(dfc->cmd)); 7210 7211 return (DFC_ARG_NULL); 7212 } 7213 7214 if (dfc->buf2_size < sizeof (uint32_t)) { 7215 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7216 "%s: Buffer2 too small. (size=%d)", 7217 emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size); 7218 7219 return (DFC_ARG_TOOSMALL); 7220 } 7221 7222 if (!dfc->buf3 || !dfc->buf3_size) { 7223 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7224 "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd)); 7225 7226 return (DFC_ARG_NULL); 7227 } 7228 7229 if (dfc->buf3_size < sizeof (uint32_t)) { 7230 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7231 "%s: Buffer3 too small. (size=%d)", 7232 emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size); 7233 7234 return (DFC_ARG_TOOSMALL); 7235 } 7236 7237 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s called. max=%d", 7238 emlxs_dfc_xlate(dfc->cmd), event_count); 7239 7240 size = (event_count * sizeof (HBA_EVENTINFO)); 7241 if (!(event_buffer = (HBA_EVENTINFO *)kmem_zalloc(size, KM_SLEEP))) { 7242 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7243 "%s: Unable to allocate buffer. size=%d", 7244 emlxs_dfc_xlate(dfc->cmd), size); 7245 7246 return (DFC_SYSRES_ERROR); 7247 } 7248 7249 if (emlxs_get_dfc_eventinfo(port, event_buffer, &event_count, 7250 &missed) != 0) { 7251 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7252 "%s: emlxs_get_dfc_eventinfo failed.", 7253 emlxs_dfc_xlate(dfc->cmd)); 7254 7255 rval = DFC_DRV_ERROR; 7256 goto done; 7257 } 7258 7259 if (event_count) { 7260 if (ddi_copyout((void *)event_buffer, dfc->buf1, 7261 (event_count * sizeof (HBA_EVENTINFO)), mode) != 0) { 7262 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7263 "%s: ddi_copyout failed.", 7264 emlxs_dfc_xlate(dfc->cmd)); 7265 7266 rval = DFC_COPYOUT_ERROR; 7267 goto done; 7268 } 7269 } 7270 7271 if (ddi_copyout((void *)&event_count, dfc->buf2, sizeof (uint32_t), 7272 mode) != 0) { 7273 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7274 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 7275 7276 rval = DFC_COPYOUT_ERROR; 7277 goto done; 7278 } 7279 7280 if (ddi_copyout((void *)&missed, dfc->buf3, sizeof (uint32_t), 7281 mode) != 0) { 7282 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7283 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 7284 7285 rval = DFC_COPYOUT_ERROR; 7286 goto done; 7287 } 7288 7289 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 7290 "%s: events=%d missed=%d new=%d last_id=%d", 7291 emlxs_dfc_xlate(dfc->cmd), event_count, hba->hba_event.missed, 7292 hba->hba_event.new, hba->hba_event.last_id); 7293 7294 done: 7295 7296 if (event_buffer) { 7297 kmem_free(event_buffer, size); 7298 } 7299 7300 return (rval); 7301 7302 } /* emlxs_dfc_get_eventinfo() */ 7303 7304 7305 static int32_t 7306 emlxs_dfc_get_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 7307 { 7308 emlxs_port_t *port = &PPORT; 7309 uint32_t event; 7310 uint32_t pid; 7311 uint32_t sleep; 7312 uint32_t i; 7313 int32_t rval = DFC_SUCCESS; 7314 emlxs_dfc_event_t *dfc_event; 7315 7316 event = dfc->data1; 7317 pid = dfc->data2; 7318 7319 if (!dfc->buf1_size) { 7320 dfc->buf1 = NULL; 7321 } else if (!dfc->buf1) { 7322 dfc->buf1_size = 0; 7323 } 7324 7325 if (dfc->buf2_size < sizeof (uint32_t)) { 7326 dfc->buf2 = NULL; 7327 } else if (!dfc->buf2) { 7328 dfc->buf2_size = 0; 7329 } 7330 7331 if (dfc->buf3_size < sizeof (uint32_t)) { 7332 dfc->buf3 = NULL; 7333 } else if (!dfc->buf3) { 7334 dfc->buf3_size = 0; 7335 } 7336 7337 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 7338 "%s: %s. pid=%d size=%d,%p rcv_size=%d,%p id=%d", 7339 emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event), pid, 7340 dfc->buf1_size, dfc->buf1, dfc->buf2_size, dfc->buf2, dfc->data3); 7341 7342 /* Find the event entry */ 7343 dfc_event = NULL; 7344 for (i = 0; i < MAX_DFC_EVENTS; i++) { 7345 dfc_event = &hba->dfc_event[i]; 7346 7347 if (dfc_event->pid == pid && dfc_event->event == event) { 7348 break; 7349 } 7350 } 7351 7352 if (i == MAX_DFC_EVENTS) { 7353 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7354 "%s: %s. Event not registered. pid=%d", 7355 emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event), 7356 pid); 7357 7358 return (DFC_ARG_INVALID); 7359 } 7360 7361 if (!(hba->log_events & dfc_event->event)) { 7362 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7363 "%s: %s. Event not registered. pid=%d", 7364 emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event), 7365 pid); 7366 7367 return (DFC_ARG_INVALID); 7368 } 7369 7370 /* Initialize event buffer pointers */ 7371 dfc_event->dataout = dfc->buf1; 7372 dfc_event->size = dfc->buf1_size; 7373 dfc_event->last_id = dfc->data3; 7374 dfc_event->mode = mode; 7375 7376 sleep = (dfc->flag & 0x01) ? 1 : 0; 7377 7378 if ((rval = emlxs_get_dfc_event(port, dfc_event, sleep))) { 7379 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 7380 "%s: %s. Exiting. pid=%d rsize=%d id=%d rval=%d", 7381 emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event), 7382 pid, dfc_event->size, dfc_event->last_id, rval); 7383 7384 return (rval); 7385 } 7386 7387 if (dfc->buf2) { 7388 if (ddi_copyout((void *)&dfc_event->size, dfc->buf2, 7389 sizeof (uint32_t), mode) != 0) { 7390 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7391 "%s: ddi_copyout failed.", 7392 emlxs_dfc_xlate(dfc->cmd)); 7393 7394 return (DFC_COPYOUT_ERROR); 7395 } 7396 } 7397 7398 if (dfc->buf3) { 7399 if (ddi_copyout((void *)&dfc_event->last_id, dfc->buf3, 7400 sizeof (uint32_t), mode) != 0) { 7401 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7402 "%s: ddi_copyout failed.", 7403 emlxs_dfc_xlate(dfc->cmd)); 7404 7405 return (DFC_COPYOUT_ERROR); 7406 } 7407 } 7408 7409 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 7410 "%s: %s. Completed. pid=%d rsize=%d id=%d", 7411 emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event), pid, 7412 dfc_event->size, dfc_event->last_id); 7413 7414 return (rval); 7415 7416 } /* emlxs_dfc_get_event() */ 7417 7418 7419 extern uint32_t 7420 emlxs_get_dump_region(emlxs_hba_t *hba, uint32_t region, 7421 uint8_t *buffer, uint32_t *psize) 7422 { 7423 emlxs_port_t *port = &PPORT; 7424 uint32_t size; 7425 uint32_t size_only; 7426 uint32_t rval = 0; 7427 uint8_t *memptr; 7428 uint32_t *wptr; 7429 7430 if (!buffer || !(*psize)) { 7431 size_only = 1; 7432 size = 0xffffffff; 7433 } else { 7434 size_only = 0; 7435 size = *psize; 7436 } 7437 7438 switch (region) { 7439 case 0: /* SLI Registers */ 7440 7441 if (size < (4 * sizeof (uint32_t))) { 7442 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7443 "emlxs_get_dump_region: Buffer too small. " 7444 "(SLI Registers: size=%d)", size); 7445 7446 rval = DFC_ARG_TOOSMALL; 7447 goto done; 7448 } 7449 7450 size = (4 * sizeof (uint32_t)); 7451 7452 if (size_only) { 7453 break; 7454 } 7455 7456 wptr = (uint32_t *)buffer; 7457 wptr[0] = READ_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr)); 7458 wptr[1] = READ_CSR_REG(hba, FC_CA_REG(hba, hba->csr_addr)); 7459 wptr[2] = READ_CSR_REG(hba, FC_HS_REG(hba, hba->csr_addr)); 7460 wptr[3] = READ_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr)); 7461 7462 break; 7463 7464 case 1: /* SLIM */ 7465 7466 if (hba->flag & FC_SLIM2_MODE) { 7467 size = MIN(SLI2_SLIM2_SIZE, size); 7468 } else { 7469 size = MIN(4096, size); 7470 } 7471 7472 if (size_only) { 7473 break; 7474 } 7475 7476 if (hba->flag & FC_SLIM2_MODE) { 7477 memptr = (uint8_t *)hba->slim2.virt; 7478 emlxs_pcimem_bcopy((uint32_t *)memptr, 7479 (uint32_t *)buffer, size); 7480 } else { 7481 memptr = (uint8_t *)hba->slim_addr; 7482 READ_SLIM_COPY(hba, (uint32_t *)buffer, 7483 (uint32_t *)memptr, (size / 4)); 7484 } 7485 7486 break; 7487 7488 case 2: /* Port Control Block */ 7489 7490 if (size < sizeof (PCB)) { 7491 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7492 "emlxs_get_dump_region: Buffer too small. " 7493 "(PCB: size=%d)", size); 7494 7495 rval = DFC_ARG_TOOSMALL; 7496 goto done; 7497 } 7498 7499 size = sizeof (PCB); 7500 7501 if (size_only) { 7502 break; 7503 } 7504 7505 memptr = (uint8_t *)&(((SLIM2 *)hba->slim2.virt)->pcb); 7506 emlxs_pcimem_bcopy((uint32_t *)memptr, (uint32_t *)buffer, 7507 size); 7508 7509 break; 7510 7511 case 3: /* MailBox */ 7512 7513 if (size < MAILBOX_CMD_BSIZE) { 7514 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7515 "emlxs_get_dump_region: Buffer too small. " 7516 "(Mailbox: size=%d)", size); 7517 7518 rval = DFC_ARG_TOOSMALL; 7519 goto done; 7520 } 7521 7522 size = MAILBOX_CMD_BSIZE; 7523 7524 if (size_only) { 7525 break; 7526 } 7527 7528 if (hba->flag & FC_SLIM2_MODE) { 7529 memptr = (uint8_t *)hba->slim2.virt; 7530 emlxs_pcimem_bcopy((uint32_t *)memptr, 7531 (uint32_t *)buffer, size); 7532 } else { 7533 memptr = (uint8_t *)hba->slim_addr; 7534 READ_SLIM_COPY(hba, (uint32_t *)buffer, 7535 (uint32_t *)memptr, (size / 4)); 7536 } 7537 7538 break; 7539 7540 case 4: /* Host Put/Get pointer array */ 7541 7542 if (size < MAX_RINGS * sizeof (HGP)) { 7543 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7544 "emlxs_get_dump_region: Buffer too small. " 7545 "(HGP: size=%d)", size); 7546 7547 rval = DFC_ARG_TOOSMALL; 7548 goto done; 7549 } 7550 7551 size = MAX_RINGS * sizeof (HGP); 7552 7553 if (size_only) { 7554 break; 7555 } 7556 7557 { 7558 memptr = 7559 (uint8_t *)hba->slim_addr + hba->hgp_ring_offset; 7560 READ_SLIM_COPY(hba, (uint32_t *)buffer, 7561 (uint32_t *)memptr, (size / 4)); 7562 } 7563 7564 break; 7565 7566 case 5: /* Port Get/Put pointer array */ 7567 7568 if (size < MAX_RINGS * sizeof (PGP)) { 7569 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7570 "emlxs_get_dump_region: Buffer too small. " 7571 "(PGP: size=%d)", size); 7572 7573 rval = DFC_ARG_TOOSMALL; 7574 goto done; 7575 } 7576 7577 size = MAX_RINGS * sizeof (PGP); 7578 7579 if (size_only) { 7580 break; 7581 } 7582 7583 memptr = 7584 (uint8_t *)((SLIM2 *)hba->slim2.virt)->mbx.us.s2.port; 7585 emlxs_pcimem_bcopy((uint32_t *)memptr, (uint32_t *)buffer, 7586 size); 7587 7588 break; 7589 7590 case 6: /* Command/Response Ring */ 7591 7592 if (size < SLI_IOCB_MAX_SIZE) { 7593 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7594 "emlxs_get_dump_region: Buffer too small. " 7595 "(Rings: size=%d)", size); 7596 7597 rval = DFC_ARG_TOOSMALL; 7598 goto done; 7599 } 7600 7601 size = SLI_IOCB_MAX_SIZE; 7602 7603 if (size_only) { 7604 break; 7605 } 7606 7607 memptr = (uint8_t *)((SLIM2 *)hba->slim2.virt)->IOCBs; 7608 emlxs_pcimem_bcopy((uint32_t *)memptr, (uint32_t *)buffer, 7609 size); 7610 7611 break; 7612 7613 case 7: /* All driver specific structures */ 7614 7615 if (size < sizeof (emlxs_hba_t)) { 7616 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7617 "emlxs_get_dump_region: Buffer too small. " 7618 "(Driver: size=%d)", size); 7619 7620 rval = DFC_ARG_TOOSMALL; 7621 goto done; 7622 } 7623 7624 size = sizeof (emlxs_hba_t); 7625 7626 if (size_only) { 7627 break; 7628 } 7629 7630 memptr = (uint8_t *)hba; 7631 bcopy((void *)memptr, (void *)buffer, size); 7632 7633 break; 7634 7635 default: 7636 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7637 "emlxs_get_dump_region: Invalid region. (id=%d)", region); 7638 7639 rval = DFC_ARG_INVALID; 7640 } 7641 7642 done: 7643 7644 *psize = size; 7645 7646 return (rval); 7647 7648 } /* emlxs_get_dump_region() */ 7649 7650 7651 7652 static int32_t 7653 emlxs_dfc_get_dump_region(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 7654 { 7655 emlxs_port_t *port = &PPORT; 7656 uint32_t size; 7657 uint32_t size_only = 0; 7658 uint32_t rval = 0; 7659 uint8_t *buffer = NULL; 7660 7661 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 7662 "%s: region=%d size=%d", 7663 emlxs_dfc_xlate(dfc->cmd), dfc->data1, dfc->buf1_size); 7664 7665 if (!dfc->buf1 || !dfc->buf1_size) { 7666 size_only = 1; 7667 } 7668 7669 if (!dfc->buf2 || !dfc->buf2_size) { 7670 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7671 "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd)); 7672 7673 return (DFC_ARG_NULL); 7674 } 7675 7676 if (dfc->buf2_size < sizeof (uint32_t)) { 7677 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7678 "%s: Buffer2 too small. (size=%d)", 7679 emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size); 7680 7681 return (DFC_ARG_TOOSMALL); 7682 } 7683 7684 /* First get region size only */ 7685 size = 0; 7686 rval = emlxs_get_dump_region(hba, dfc->data1, NULL, &size); 7687 7688 if (rval != 0) { 7689 goto done; 7690 } 7691 7692 if (!size_only) { 7693 if (dfc->buf1_size < size) { 7694 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7695 "%s: Buffer1 too small. (size: %d < %d)", 7696 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size, size); 7697 7698 rval = DFC_ARG_TOOSMALL; 7699 goto done; 7700 } 7701 7702 if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) { 7703 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7704 "%s: Unable to allocate buffer. size=%d", 7705 emlxs_dfc_xlate(dfc->cmd), size); 7706 7707 rval = DFC_SYSRES_ERROR; 7708 goto done; 7709 } 7710 7711 /* Get the region data */ 7712 rval = emlxs_get_dump_region(hba, dfc->data1, buffer, &size); 7713 7714 if (rval != 0) { 7715 goto done; 7716 } 7717 7718 /* Return the region data */ 7719 if (ddi_copyout((void *)buffer, (void *) dfc->buf1, 7720 size, mode) != 0) { 7721 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7722 "%s: ddi_copyout failed.", 7723 emlxs_dfc_xlate(dfc->cmd)); 7724 7725 rval = DFC_COPYOUT_ERROR; 7726 goto done; 7727 } 7728 } 7729 7730 /* Return the region size */ 7731 if (ddi_copyout((void *) &size, (void *) dfc->buf2, 7732 sizeof (uint32_t), mode) != 0) { 7733 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7734 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 7735 7736 rval = DFC_COPYOUT_ERROR; 7737 goto done; 7738 } 7739 7740 done: 7741 7742 if (buffer) { 7743 kmem_free(buffer, size); 7744 } 7745 7746 return (rval); 7747 7748 } /* emlxs_dfc_get_dump_region() */ 7749 7750 7751 7752 #ifdef MENLO_SUPPORT 7753 static int32_t 7754 emlxs_dfc_menlo_port_offset(emlxs_hba_t *hba) 7755 { 7756 uint32_t cnt; 7757 char pathname[256]; 7758 7759 (void) ddi_pathname(hba->dip, pathname); 7760 cnt = strlen(pathname); 7761 if ((cnt < 4) || (strcmp(&pathname[cnt-3], "0,1") != 0)) 7762 return (0); 7763 return (1); 7764 } 7765 7766 static int32_t 7767 emlxs_dfc_set_menlo_loopback(emlxs_hba_t *hba) 7768 { 7769 emlxs_port_t *port = &PPORT; 7770 MAILBOXQ *mbq = NULL; 7771 MAILBOX *mb = NULL; 7772 fc_packet_t *pkt = NULL; 7773 uint32_t mbxstatus; 7774 uint32_t i; 7775 uint32_t offset; 7776 uint32_t rval = 0; 7777 menlo_cmd_t *cmd; 7778 7779 if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 7780 KM_SLEEP)) == 0) { 7781 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7782 "%s: Unable to allocate mailbox buffer.", 7783 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE)); 7784 7785 rval = DFC_SYSRES_ERROR; 7786 goto done; 7787 } 7788 7789 mb = (MAILBOX *)mbq; 7790 7791 /* SET MENLO maint mode */ 7792 /* Create the set_variable mailbox request */ 7793 emlxs_mb_set_var(hba, mb, 0x103107, 1); 7794 7795 mbq->flag |= MBQ_PASSTHRU; 7796 7797 /* issue the mbox cmd to the sli */ 7798 mbxstatus = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0); 7799 7800 if (mbxstatus) { 7801 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7802 "%s: %s failed. mbxstatus=0x%x", 7803 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE), 7804 emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus); 7805 7806 rval = DFC_IO_ERROR; 7807 if (mbxstatus == MBX_TIMEOUT) 7808 rval = DFC_TIMEOUT; 7809 goto done; 7810 } 7811 7812 7813 /* Wait 30 sec for maint mode */ 7814 i = 0; 7815 do { 7816 if (i++ > 300) { 7817 break; 7818 } 7819 7820 delay(drv_usectohz(100000)); 7821 7822 } while (!(hba->flag & FC_MENLO_MODE)); 7823 7824 if (!(hba->flag & FC_MENLO_MODE)) { 7825 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7826 "%s: Unable to enter maint mode.", 7827 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE)); 7828 7829 rval = DFC_DRV_ERROR; 7830 goto done; 7831 } 7832 7833 offset = emlxs_dfc_menlo_port_offset(hba); 7834 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7835 "%s: Entered maint mode. Port offset: %d", 7836 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE), offset); 7837 7838 7839 /* Issue Menlo loopback command */ 7840 if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_cmd_t), 7841 sizeof (uint32_t), 0, KM_NOSLEEP))) { 7842 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7843 "%s: Unable to allocate packet.", 7844 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE)); 7845 7846 rval = DFC_SYSRES_ERROR; 7847 goto done; 7848 } 7849 7850 /* Make this a polled IO */ 7851 pkt->pkt_tran_flags &= ~FC_TRAN_INTR; 7852 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR; 7853 pkt->pkt_comp = NULL; 7854 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 7855 pkt->pkt_timeout = 30; 7856 7857 /* Build the fc header */ 7858 pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(EMLXS_MENLO_DID); 7859 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND; 7860 pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did); 7861 pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE; 7862 pkt->pkt_cmd_fhdr.f_ctl = 7863 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 7864 pkt->pkt_cmd_fhdr.seq_id = 0; 7865 pkt->pkt_cmd_fhdr.df_ctl = 0; 7866 pkt->pkt_cmd_fhdr.seq_cnt = 0; 7867 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 7868 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF; 7869 pkt->pkt_cmd_fhdr.ro = 0; 7870 7871 cmd = (menlo_cmd_t *)pkt->pkt_cmd; 7872 cmd->code = SWAP_LONG(MENLO_CMD_LOOPBACK); 7873 cmd->lb.context = SWAP_LONG(offset); 7874 cmd->lb.type = SWAP_LONG(MENLO_LOOPBACK_ENABLE); 7875 7876 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 7877 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7878 "%s: Unable to send packet.", 7879 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE)); 7880 7881 rval = DFC_IO_ERROR; 7882 goto done; 7883 } 7884 7885 if (pkt->pkt_state != FC_PKT_SUCCESS) { 7886 if (pkt->pkt_state == FC_PKT_TIMEOUT) { 7887 EMLXS_MSGF(EMLXS_CONTEXT, 7888 &emlxs_dfc_error_msg, 7889 "%s: Pkt Transport error. Pkt Timeout.", 7890 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE)); 7891 rval = DFC_TIMEOUT; 7892 } else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) && 7893 (pkt->pkt_reason == FC_REASON_OVERRUN)) { 7894 EMLXS_MSGF(EMLXS_CONTEXT, 7895 &emlxs_dfc_error_msg, 7896 "%s: Pkt Transport error. Rsp overrun.", 7897 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE)); 7898 rval = DFC_RSP_BUF_OVERRUN; 7899 } else { 7900 EMLXS_MSGF(EMLXS_CONTEXT, 7901 &emlxs_dfc_error_msg, 7902 "%s: Pkt Transport error. state=%x", 7903 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE), 7904 pkt->pkt_state); 7905 rval = DFC_IO_ERROR; 7906 } 7907 goto done; 7908 } 7909 7910 7911 /* CLEAR MENLO maint mode */ 7912 /* Create the set_variable mailbox request */ 7913 emlxs_mb_set_var(hba, mb, 0x103107, 0); 7914 7915 mbq->flag |= MBQ_PASSTHRU; 7916 7917 /* issue the mbox cmd to the sli */ 7918 mbxstatus = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0); 7919 7920 if (mbxstatus) { 7921 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7922 "%s: %s failed. mbxstatus=0x%x", 7923 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE), 7924 emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus); 7925 7926 rval = DFC_IO_ERROR; 7927 if (mbxstatus == MBX_TIMEOUT) 7928 rval = DFC_TIMEOUT; 7929 } 7930 7931 delay(drv_usectohz(1000000)); 7932 i = 0; 7933 while ((hba->state < FC_LINK_UP) && (hba->state != FC_ERROR)) { 7934 delay(drv_usectohz(100000)); 7935 i++; 7936 7937 if (i == 300) { 7938 rval = DFC_TIMEOUT; 7939 7940 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7941 "%s: Linkup timeout.", 7942 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE)); 7943 7944 goto done; 7945 } 7946 } 7947 7948 done: 7949 /* Free allocated mbox memory */ 7950 if (mbq) { 7951 kmem_free(mbq, sizeof (MAILBOXQ)); 7952 } 7953 if (pkt) { 7954 emlxs_pkt_free(pkt); 7955 } 7956 return (rval); 7957 } 7958 7959 static int32_t 7960 emlxs_dfc_set_menlo_fte(emlxs_hba_t *hba) 7961 { 7962 emlxs_port_t *port = &PPORT; 7963 fc_packet_t *pkt = NULL; 7964 uint32_t rval = 0; 7965 menlo_cmd_t *cmd; 7966 7967 7968 /* Issue Menlo loopback command */ 7969 if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_cmd_t), 7970 sizeof (uint32_t), 0, KM_NOSLEEP))) { 7971 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 7972 "%s: Unable to allocate packet.", 7973 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE)); 7974 7975 rval = DFC_SYSRES_ERROR; 7976 goto done; 7977 } 7978 7979 /* Make this a polled IO */ 7980 pkt->pkt_tran_flags &= ~FC_TRAN_INTR; 7981 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR; 7982 pkt->pkt_comp = NULL; 7983 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 7984 pkt->pkt_timeout = 30; 7985 7986 /* Build the fc header */ 7987 pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(EMLXS_MENLO_DID); 7988 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND; 7989 pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did); 7990 pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE; 7991 pkt->pkt_cmd_fhdr.f_ctl = 7992 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 7993 pkt->pkt_cmd_fhdr.seq_id = 0; 7994 pkt->pkt_cmd_fhdr.df_ctl = 0; 7995 pkt->pkt_cmd_fhdr.seq_cnt = 0; 7996 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 7997 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF; 7998 pkt->pkt_cmd_fhdr.ro = 0; 7999 8000 cmd = (menlo_cmd_t *)pkt->pkt_cmd; 8001 cmd->code = SWAP_LONG(MENLO_CMD_FTE_INSERT); 8002 cmd->fte_insert.fcid = SWAP_LONG(0); 8003 bcopy((caddr_t)&port->wwpn, (caddr_t)cmd->fte_insert.wwpn, 8); 8004 8005 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 8006 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8007 "%s: Unable to send packet.", 8008 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE)); 8009 8010 rval = DFC_IO_ERROR; 8011 goto done; 8012 } 8013 8014 if (pkt->pkt_state != FC_PKT_SUCCESS) { 8015 if (pkt->pkt_state == FC_PKT_TIMEOUT) { 8016 EMLXS_MSGF(EMLXS_CONTEXT, 8017 &emlxs_dfc_error_msg, 8018 "%s: Pkt Transport error. Pkt Timeout.", 8019 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE)); 8020 rval = DFC_TIMEOUT; 8021 } else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) && 8022 (pkt->pkt_reason == FC_REASON_OVERRUN)) { 8023 EMLXS_MSGF(EMLXS_CONTEXT, 8024 &emlxs_dfc_error_msg, 8025 "%s: Pkt Transport error. Rsp overrun.", 8026 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE)); 8027 rval = DFC_RSP_BUF_OVERRUN; 8028 } else { 8029 EMLXS_MSGF(EMLXS_CONTEXT, 8030 &emlxs_dfc_error_msg, 8031 "%s: Pkt Transport error. state=%x", 8032 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE), 8033 pkt->pkt_state); 8034 rval = DFC_IO_ERROR; 8035 } 8036 goto done; 8037 } 8038 8039 8040 done: 8041 if (pkt) { 8042 emlxs_pkt_free(pkt); 8043 } 8044 return (rval); 8045 } 8046 8047 static int32_t 8048 emlxs_dfc_reset_menlo(emlxs_hba_t *hba) 8049 { 8050 emlxs_port_t *port = &PPORT; 8051 MAILBOXQ *mbq = NULL; 8052 MAILBOX *mb = NULL; 8053 uint32_t mbxstatus; 8054 uint32_t rval = 0; 8055 8056 if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 8057 KM_SLEEP)) == 0) { 8058 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8059 "%s: Unable to allocate mailbox buffer.", 8060 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE)); 8061 8062 rval = DFC_SYSRES_ERROR; 8063 goto done; 8064 } 8065 8066 mb = (MAILBOX *)mbq; 8067 8068 /* RESET MENLO */ 8069 /* Create the set_variable mailbox request */ 8070 emlxs_mb_set_var(hba, mb, 0x103007, 0); 8071 8072 mbq->flag |= MBQ_PASSTHRU; 8073 8074 /* issue the mbox cmd to the sli */ 8075 mbxstatus = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0); 8076 8077 if (mbxstatus) { 8078 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8079 "%s: %s failed. mbxstatus=0x%x", 8080 emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE), 8081 emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus); 8082 8083 rval = DFC_IO_ERROR; 8084 if (mbxstatus == MBX_TIMEOUT) 8085 rval = DFC_TIMEOUT; 8086 goto done; 8087 } 8088 done: 8089 /* Free allocated mbox memory */ 8090 if (mbq) { 8091 kmem_free(mbq, sizeof (MAILBOXQ)); 8092 } 8093 return (rval); 8094 } 8095 8096 #endif /* MENLO_SUPPORT */ 8097 8098 /* ARGSUSED */ 8099 static int32_t 8100 emlxs_dfc_loopback_mode(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 8101 { 8102 emlxs_port_t *port = &PPORT; 8103 emlxs_config_t *cfg = &CFG; 8104 MAILBOXQ *mbq = NULL; 8105 MAILBOX *mb = NULL; 8106 uint32_t rval = DFC_SUCCESS; 8107 uint32_t i; 8108 uint32_t timeout; 8109 uint32_t topology; 8110 uint32_t speed; 8111 uint32_t new_mode; 8112 NODELIST *ndlp; 8113 8114 /* Reinitialize the link */ 8115 switch (dfc->flag) { 8116 case 0: /* Disable */ 8117 8118 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 8119 "%s: Disabling Loopback.", emlxs_dfc_xlate(dfc->cmd)); 8120 8121 if (!(hba->flag & FC_LOOPBACK_MODE)) { 8122 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 8123 "%s: Loopback already disabled.", 8124 emlxs_dfc_xlate(dfc->cmd)); 8125 8126 return (rval); 8127 } 8128 goto resetdone; 8129 8130 case 1: /* Internal loopback */ 8131 new_mode = FC_ILB_MODE; 8132 topology = FLAGS_LOCAL_LB; 8133 speed = 0; 8134 8135 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 8136 "%s: Enabling ILB.", emlxs_dfc_xlate(dfc->cmd)); 8137 8138 /* Check if mode already set */ 8139 if ((hba->flag & FC_ILB_MODE)) { 8140 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 8141 "%s: ILB mode already enabled.", 8142 emlxs_dfc_xlate(dfc->cmd)); 8143 8144 return (rval); 8145 } 8146 8147 break; 8148 8149 case 2: /* External loopback */ 8150 new_mode = FC_ELB_MODE; 8151 topology = FLAGS_TOPOLOGY_MODE_LOOP; 8152 speed = cfg[CFG_LINK_SPEED].current; 8153 8154 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 8155 "%s: Enabling ELB.", emlxs_dfc_xlate(dfc->cmd)); 8156 8157 /* Check if mode already set */ 8158 if ((hba->flag & FC_ELB_MODE)) { 8159 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 8160 "%s: ELB mode already enabled.", 8161 emlxs_dfc_xlate(dfc->cmd)); 8162 8163 return (rval); 8164 } 8165 8166 break; 8167 8168 default: 8169 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8170 "%s: Invalid loopback mode. (mode=%x)", 8171 emlxs_dfc_xlate(dfc->cmd), dfc->flag); 8172 8173 return (DFC_ARG_INVALID); 8174 } 8175 8176 /* Make sure adapter is online */ 8177 if (emlxs_online(hba)) { 8178 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8179 "%s: Unable to bring adapter online.", 8180 emlxs_dfc_xlate(dfc->cmd)); 8181 8182 return (DFC_OFFLINE_ERROR); 8183 } 8184 8185 #ifdef MENLO_SUPPORT 8186 if (hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) { 8187 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8188 "%s: Menlo support detected: mode:x%x", 8189 emlxs_dfc_xlate(dfc->cmd), new_mode); 8190 8191 if (new_mode == FC_ILB_MODE) { 8192 rval = emlxs_dfc_set_menlo_loopback(hba); 8193 if (rval) 8194 goto done; 8195 } 8196 } 8197 #endif /* MENLO_SUPPORT */ 8198 8199 if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 8200 KM_SLEEP)) == 0) { 8201 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8202 "%s: Unable to allocate mailbox buffer.", 8203 emlxs_dfc_xlate(dfc->cmd)); 8204 8205 rval = DFC_SYSRES_ERROR; 8206 goto done; 8207 } 8208 8209 mb = (MAILBOX *) mbq; 8210 8211 /* Take the link down */ 8212 emlxs_mb_down_link(hba, mb); 8213 8214 rval = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0); 8215 8216 if (rval == MBX_TIMEOUT) { 8217 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8218 "%s: Mailbox timed out. cmd=%x", 8219 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 8220 8221 rval = DFC_TIMEOUT; 8222 goto done; 8223 } 8224 8225 if (rval) { 8226 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8227 "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd), 8228 emlxs_mb_cmd_xlate(mb->mbxCommand), rval); 8229 8230 rval = DFC_IO_ERROR; 8231 goto done; 8232 } 8233 8234 /* Reinitialize the link */ 8235 emlxs_mb_init_link(hba, mb, topology, speed); 8236 8237 /* Set the loopback mode and timer */ 8238 mutex_enter(&EMLXS_PORT_LOCK); 8239 hba->flag |= new_mode; 8240 hba->loopback_tics = hba->timer_tics + emlxs_loopback_tmo; 8241 mutex_exit(&EMLXS_PORT_LOCK); 8242 8243 rval = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0); 8244 8245 if (rval == MBX_TIMEOUT) { 8246 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8247 "%s: Mailbox timed out. cmd=%x", 8248 emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand); 8249 8250 rval = DFC_TIMEOUT; 8251 goto done; 8252 } 8253 8254 if (rval) { 8255 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8256 "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd), 8257 emlxs_mb_cmd_xlate(mb->mbxCommand), rval); 8258 8259 rval = DFC_IO_ERROR; 8260 goto done; 8261 } 8262 8263 /* 8264 * Wait for adapter to come online. 8265 * Need *2 since we wait 1/2 sec in while loop. 8266 */ 8267 timeout = dfc->data1; 8268 if (!timeout) { 8269 timeout = 60 * 2; 8270 } else { 8271 timeout = timeout * 2; 8272 } 8273 8274 i = 0; 8275 while ((hba->state < FC_LINK_UP) && (hba->state != FC_ERROR)) { 8276 delay(drv_usectohz(500000)); 8277 i++; 8278 8279 if (i == timeout) { 8280 rval = DFC_TIMEOUT; 8281 8282 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8283 "%s: Linkup timeout.", emlxs_dfc_xlate(dfc->cmd)); 8284 8285 goto done; 8286 } 8287 } 8288 8289 /* Create host node */ 8290 if (emlxs_mb_reg_did(port, port->did, (SERV_PARM *)&hba->sparam, 8291 NULL, NULL, NULL)) { 8292 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8293 "%s: Unable to register host node.", 8294 emlxs_dfc_xlate(dfc->cmd)); 8295 8296 rval = DFC_DRV_ERROR; 8297 goto done; 8298 } 8299 8300 i = 0; 8301 do { 8302 if (i++ > 300) { 8303 break; 8304 } 8305 8306 delay(drv_usectohz(100000)); 8307 8308 } while (!(ndlp = emlxs_node_find_did(port, port->did))); 8309 8310 if (!ndlp) { 8311 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8312 "%s: Unable to create host node.", 8313 emlxs_dfc_xlate(dfc->cmd)); 8314 8315 rval = DFC_DRV_ERROR; 8316 goto done; 8317 } 8318 8319 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 8320 "%s: Node created. node=%p", emlxs_dfc_xlate(dfc->cmd), ndlp); 8321 8322 #ifdef MENLO_SUPPORT 8323 if (hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) { 8324 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8325 "%s: Menlo support detected: mode:x%x", 8326 emlxs_dfc_xlate(dfc->cmd), new_mode); 8327 8328 rval = emlxs_dfc_set_menlo_fte(hba); 8329 if (rval) 8330 goto done; 8331 } 8332 #endif /* MENLO_SUPPORT */ 8333 8334 /* Create host XRI */ 8335 (void) emlxs_create_xri(port, &hba->ring[FC_CT_RING], ndlp); 8336 8337 i = 0; 8338 do { 8339 if (i++ > 300) { 8340 break; 8341 } 8342 8343 delay(drv_usectohz(100000)); 8344 8345 } while (!ndlp->nlp_Xri); 8346 8347 if (!ndlp->nlp_Xri) { 8348 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8349 "%s: Unable to create XRI.", emlxs_dfc_xlate(dfc->cmd)); 8350 8351 rval = DFC_DRV_ERROR; 8352 goto done; 8353 } 8354 8355 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 8356 "%s: XRI created. xri=%x", emlxs_dfc_xlate(dfc->cmd), 8357 ndlp->nlp_Xri); 8358 done: 8359 /* Free allocated mbox memory */ 8360 if (mbq) { 8361 kmem_free(mbq, sizeof (MAILBOXQ)); 8362 } 8363 8364 if (rval) { 8365 resetdone: 8366 /* Reset the adapter */ 8367 #ifdef MENLO_SUPPORT 8368 if (hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) { 8369 8370 rval = emlxs_dfc_reset_menlo(hba); 8371 8372 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 8373 "%s: Menlo reset: rval:x%x", 8374 emlxs_dfc_xlate(dfc->cmd), rval); 8375 } 8376 #endif /* MENLO_SUPPORT */ 8377 8378 /* Reset link whether we are bound to ULP or not */ 8379 (void) emlxs_reset_link(hba, 1); 8380 } 8381 8382 return (rval); 8383 } /* emlxs_dfc_loopback_mode() */ 8384 8385 8386 static int32_t 8387 emlxs_dfc_loopback_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 8388 { 8389 emlxs_port_t *port = &PPORT; 8390 uint32_t rval = 0; 8391 NODELIST *ndlp; 8392 clock_t timeout; 8393 fc_packet_t *pkt = NULL; 8394 SLI_CT_REQUEST *CtCmd; 8395 uint16_t CtRsp; 8396 8397 mutex_enter(&EMLXS_PORT_LOCK); 8398 if (!(hba->flag & FC_LOOPBACK_MODE)) { 8399 mutex_exit(&EMLXS_PORT_LOCK); 8400 8401 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8402 "%s: Adapter not in loopback mode.", 8403 emlxs_dfc_xlate(dfc->cmd)); 8404 8405 rval = DFC_DRV_ERROR; 8406 goto done; 8407 } 8408 hba->loopback_tics = hba->timer_tics + emlxs_loopback_tmo; 8409 mutex_exit(&EMLXS_PORT_LOCK); 8410 8411 if (!(hba->flag & FC_ONLINE_MODE)) { 8412 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8413 "%s: Adapter offline.", emlxs_dfc_xlate(dfc->cmd)); 8414 8415 rval = DFC_OFFLINE_ERROR; 8416 goto done; 8417 } 8418 8419 if (hba->state < FC_LINK_UP) { 8420 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8421 "%s: Link not up.", emlxs_dfc_xlate(dfc->cmd)); 8422 8423 rval = DFC_OFFLINE_ERROR; 8424 goto done; 8425 } 8426 8427 if (!dfc->buf1 || !dfc->buf1_size) { 8428 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8429 "%s: NULL buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 8430 8431 rval = DFC_ARG_NULL; 8432 goto done; 8433 } 8434 8435 if (!dfc->buf2 || !dfc->buf2_size) { 8436 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8437 "%s: NULL buffer2 found.", emlxs_dfc_xlate(dfc->cmd)); 8438 8439 rval = DFC_ARG_NULL; 8440 goto done; 8441 } 8442 8443 if (dfc->buf1_size > MAX_CT_PAYLOAD) { 8444 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8445 "%s: Buffer1 too large. (size=%d)", 8446 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 8447 8448 rval = DFC_ARG_TOOBIG; 8449 goto done; 8450 } 8451 8452 /* Check if we have a node for ourselves */ 8453 ndlp = emlxs_node_find_did(port, port->did); 8454 8455 if (!ndlp) { 8456 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8457 "%s: Host node not found.", emlxs_dfc_xlate(dfc->cmd)); 8458 8459 rval = DFC_ARG_INVALID; 8460 goto done; 8461 } 8462 8463 if (!ndlp->nlp_Xri) { 8464 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8465 "%s: Host XRI not found.", emlxs_dfc_xlate(dfc->cmd)); 8466 8467 rval = DFC_DRV_ERROR; 8468 goto done; 8469 } 8470 8471 if (!(pkt = emlxs_pkt_alloc(port, dfc->buf1_size + 16, 8472 dfc->buf2_size + 16, 0, KM_SLEEP))) { 8473 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8474 "%s: Unable to allocate pkt.", emlxs_dfc_xlate(dfc->cmd)); 8475 8476 rval = DFC_SYSRES_ERROR; 8477 goto done; 8478 } 8479 8480 CtCmd = (SLI_CT_REQUEST*)pkt->pkt_cmd; 8481 CtRsp = SLI_CT_LOOPBACK; 8482 CtCmd->CommandResponse.bits.CmdRsp = SWAP_DATA16(CtRsp); 8483 8484 if (ddi_copyin((void *)dfc->buf1, (void *)&CtCmd->un.data, 8485 dfc->buf1_size, mode) != 0) { 8486 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8487 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 8488 8489 rval = DFC_COPYIN_ERROR; 8490 goto done; 8491 } 8492 8493 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 8494 pkt->pkt_timeout = 2 * hba->fc_ratov; 8495 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR; 8496 pkt->pkt_comp = NULL; 8497 8498 pkt->pkt_cmd_fhdr.d_id = port->did; 8499 pkt->pkt_cmd_fhdr.r_ctl = FC_SOL_CTL; 8500 pkt->pkt_cmd_fhdr.s_id = port->did; 8501 pkt->pkt_cmd_fhdr.type = FC_CT_TYPE; 8502 pkt->pkt_cmd_fhdr.f_ctl = 0; 8503 pkt->pkt_cmd_fhdr.seq_id = 0; 8504 pkt->pkt_cmd_fhdr.df_ctl = 0; 8505 pkt->pkt_cmd_fhdr.seq_cnt = 0; 8506 pkt->pkt_cmd_fhdr.ox_id = 0xffff; 8507 pkt->pkt_cmd_fhdr.rx_id = ndlp->nlp_Xri; 8508 pkt->pkt_cmd_fhdr.ro = 0; 8509 8510 mutex_enter(&EMLXS_PKT_LOCK); 8511 timeout = emlxs_timeout(hba, (pkt->pkt_timeout + 15)); 8512 8513 if (hba->loopback_pkt) { 8514 rval = 0; 8515 while ((rval != -1) && hba->loopback_pkt) { 8516 rval = 8517 cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK, 8518 timeout); 8519 } 8520 8521 if (rval == -1) { 8522 mutex_exit(&EMLXS_PKT_LOCK); 8523 8524 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8525 "Loopback busy timeout."); 8526 rval = DFC_TIMEOUT; 8527 goto done; 8528 } 8529 } 8530 hba->loopback_pkt = (void *) pkt; 8531 mutex_exit(&EMLXS_PKT_LOCK); 8532 8533 /* Send polled command */ 8534 if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) { 8535 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8536 "Pkt Transport error. ret=%x state=%x", rval, 8537 pkt->pkt_state); 8538 8539 rval = DFC_IO_ERROR; 8540 goto done; 8541 } 8542 8543 if (pkt->pkt_state != FC_PKT_SUCCESS) { 8544 if (pkt->pkt_state == FC_PKT_TIMEOUT) { 8545 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8546 "Pkt Transport error. Pkt Timeout."); 8547 rval = DFC_TIMEOUT; 8548 } else { 8549 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8550 "Pkt Transport error. state=%x", pkt->pkt_state); 8551 rval = DFC_IO_ERROR; 8552 } 8553 goto done; 8554 } 8555 8556 /* Wait for sequence completion */ 8557 mutex_enter(&EMLXS_PKT_LOCK); 8558 rval = 0; 8559 while ((rval != -1) && !(pkt->pkt_tran_flags & FC_TRAN_COMPLETED)) { 8560 rval = cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK, timeout); 8561 } 8562 mutex_exit(&EMLXS_PKT_LOCK); 8563 8564 if (rval == -1) { 8565 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8566 "Loopback sequence timeout."); 8567 8568 rval = DFC_TIMEOUT; 8569 goto done; 8570 } 8571 8572 CtCmd = (SLI_CT_REQUEST*)pkt->pkt_resp; 8573 8574 if (ddi_copyout((void *)&CtCmd->un.data, (void *)dfc->buf2, 8575 dfc->buf2_size, mode) != 0) { 8576 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8577 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 8578 8579 rval = DFC_COPYOUT_ERROR; 8580 goto done; 8581 } 8582 8583 rval = 0; 8584 8585 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, "%s: Test completed.", 8586 emlxs_dfc_xlate(dfc->cmd)); 8587 8588 done: 8589 8590 if (rval) { 8591 mutex_enter(&EMLXS_PKT_LOCK); 8592 if (pkt && (hba->loopback_pkt == pkt)) { 8593 hba->loopback_pkt = NULL; 8594 } 8595 mutex_exit(&EMLXS_PKT_LOCK); 8596 8597 /* Reset the adapter */ 8598 (void) emlxs_reset(port, FC_FCA_LINK_RESET); 8599 } 8600 8601 if (pkt) { 8602 emlxs_pkt_free(pkt); 8603 } 8604 8605 return (rval); 8606 8607 } /* emlxs_dfc_loopback_test() */ 8608 8609 8610 extern int32_t 8611 emlxs_dfc_handle_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 8612 { 8613 emlxs_port_t *port = &PPORT; 8614 IOCB *cmd; 8615 emlxs_buf_t *sbp; 8616 8617 cmd = &iocbq->iocb; 8618 8619 HBASTATS.CtEvent++; 8620 8621 sbp = (emlxs_buf_t *)iocbq->sbp; 8622 8623 if (!sbp) { 8624 HBASTATS.CtStray++; 8625 8626 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8627 "Stray interrupt. cmd=0x%x iotag=0x%x status=0x%x " 8628 "perr=0x%x", (uint32_t)cmd->ulpCommand, 8629 (uint32_t)cmd->ulpIoTag, cmd->ulpStatus, 8630 cmd->un.ulpWord[4]); 8631 8632 return (DFC_ARG_INVALID); 8633 } 8634 8635 if (rp->ringno != FC_CT_RING) { 8636 HBASTATS.CtStray++; 8637 8638 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8639 "CT Event: Invalid ring: ring=%d iocbq=%p", rp->ringno, 8640 iocbq); 8641 8642 return (DFC_ARG_INVALID); 8643 } 8644 8645 switch (cmd->ulpCommand) { 8646 case CMD_XMIT_SEQUENCE_CR: 8647 case CMD_XMIT_SEQUENCE64_CR: 8648 case CMD_XMIT_SEQUENCE_CX: 8649 case CMD_XMIT_SEQUENCE64_CX: 8650 8651 HBASTATS.CtCmdCompleted++; 8652 8653 if (cmd->ulpStatus == 0) { 8654 HBASTATS.CtCmdGood++; 8655 8656 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 8657 "XMIT_SEQUENCE comp: status=0x%x", 8658 cmd->ulpStatus); 8659 } else { 8660 HBASTATS.CtCmdError++; 8661 8662 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8663 "XMIT_SEQUENCE comp: status=0x%x [%08x,%08x]", 8664 cmd->ulpStatus, cmd->un.ulpWord[4], 8665 cmd->un.ulpWord[5]); 8666 } 8667 8668 emlxs_pkt_complete(sbp, cmd->ulpStatus, 8669 cmd->un.grsp.perr.statLocalError, 1); 8670 8671 break; 8672 8673 default: 8674 8675 HBASTATS.CtStray++; 8676 8677 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8678 "Invalid iocb: cmd=0x%x", cmd->ulpCommand); 8679 8680 emlxs_pkt_complete(sbp, cmd->ulpStatus, 8681 cmd->un.grsp.perr.statLocalError, 1); 8682 8683 break; 8684 8685 } /* switch(cmd->ulpCommand) */ 8686 8687 return (0); 8688 8689 } /* emlxs_dfc_handle_event() */ 8690 8691 8692 /* ARGSUSED */ 8693 extern int 8694 emlxs_dfc_handle_unsol_req(emlxs_port_t *port, RING *rp, IOCBQ *iocbq, 8695 MATCHMAP *mp, uint32_t size) 8696 { 8697 emlxs_hba_t *hba = HBA; 8698 IOCB *iocb; 8699 uint8_t *bp; 8700 fc_packet_t *pkt; 8701 8702 iocb = &iocbq->iocb; 8703 bp = (uint8_t *)mp->virt; 8704 8705 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, 8706 "CT Receive: cmd=%x status=0x%x ", 8707 iocb->ulpCommand, iocb->ulpStatus); 8708 8709 /* 8710 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, 8711 * "CT Receive: payload=%p size=%d [%02x,%02x, %02x, %02x]", bp, 8712 * size, bp[0], bp[1], bp[2],bp[3]); 8713 */ 8714 8715 /* Return payload */ 8716 mutex_enter(&EMLXS_PKT_LOCK); 8717 if (hba->loopback_pkt) { 8718 pkt = (fc_packet_t *)hba->loopback_pkt; 8719 hba->loopback_pkt = NULL; 8720 8721 size = MIN(size, pkt->pkt_rsplen); 8722 bcopy(bp, pkt->pkt_resp, size); 8723 pkt->pkt_tran_flags |= FC_TRAN_COMPLETED; 8724 8725 cv_broadcast(&EMLXS_PKT_CV); 8726 } 8727 mutex_exit(&EMLXS_PKT_LOCK); 8728 8729 return (0); 8730 8731 } /* emlxs_dfc_handle_unsol_req() */ 8732 8733 8734 #ifdef DHCHAP_SUPPORT 8735 8736 static int32_t 8737 emlxs_dfc_init_auth(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 8738 { 8739 emlxs_port_t *port = &PPORT; 8740 uint8_t lwwpn[8]; 8741 uint8_t rwwpn[8]; 8742 int32_t rval = 0; 8743 8744 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.", 8745 emlxs_dfc_xlate(dfc->cmd)); 8746 8747 if (!dfc->buf1 || !dfc->buf1_size) { 8748 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8749 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 8750 8751 return (DFC_ARG_NULL); 8752 } 8753 8754 if (dfc->buf1_size < 8) { 8755 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8756 "%s: Buffer1 too small. (size=%d)", 8757 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 8758 8759 return (DFC_ARG_TOOSMALL); 8760 } 8761 8762 if (!dfc->buf2 || !dfc->buf2_size) { 8763 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8764 "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd)); 8765 8766 return (DFC_ARG_NULL); 8767 } 8768 8769 if (dfc->buf2_size < 8) { 8770 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8771 "%s: Buffer2 too small. (size=%d)", 8772 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 8773 8774 return (DFC_ARG_TOOSMALL); 8775 } 8776 8777 /* Read the lwwpn */ 8778 if (ddi_copyin((void *)dfc->buf1, (void *)&lwwpn, 8, mode) != 0) { 8779 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8780 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 8781 8782 return (DFC_COPYIN_ERROR); 8783 } 8784 8785 /* Read the rwwpn */ 8786 if (ddi_copyin((void *)dfc->buf2, (void *)&rwwpn, 8, mode) != 0) { 8787 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8788 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 8789 8790 return (DFC_COPYIN_ERROR); 8791 } 8792 8793 /* Initiate authentication here */ 8794 rval = emlxs_dhc_init_auth(hba, lwwpn, rwwpn); 8795 8796 return (rval); 8797 8798 } /* emlxs_dfc_init_auth() */ 8799 8800 8801 static int32_t 8802 emlxs_dfc_get_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 8803 { 8804 emlxs_port_t *port = &PPORT; 8805 dfc_fcsp_config_t fcsp_config; 8806 uint32_t rval = DFC_SUCCESS; 8807 8808 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.", 8809 emlxs_dfc_xlate(dfc->cmd)); 8810 8811 if (!dfc->buf1 || !dfc->buf1_size) { 8812 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8813 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 8814 8815 return (DFC_ARG_NULL); 8816 } 8817 8818 if (dfc->buf1_size < sizeof (dfc_fcsp_config_t)) { 8819 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8820 "%s: Buffer1 too small. (size=%d)", 8821 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 8822 8823 return (DFC_ARG_TOOSMALL); 8824 } 8825 8826 /* Read the fcsp_config */ 8827 if (ddi_copyin((void *)dfc->buf1, (void *)&fcsp_config, 8828 sizeof (dfc_fcsp_config_t), mode) != 0) { 8829 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8830 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 8831 8832 return (DFC_COPYIN_ERROR); 8833 } 8834 8835 if ((rval = emlxs_dhc_get_auth_cfg(hba, &fcsp_config)) != 0) { 8836 return (rval); 8837 } 8838 8839 if (ddi_copyout((void *)&fcsp_config, (void *)dfc->buf1, 8840 sizeof (dfc_fcsp_config_t), mode) != 0) { 8841 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8842 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 8843 8844 return (DFC_COPYOUT_ERROR); 8845 } 8846 8847 return (0); 8848 8849 } /* emlxs_dfc_get_auth_cfg() */ 8850 8851 8852 8853 static int32_t 8854 emlxs_dfc_set_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 8855 { 8856 emlxs_port_t *port = &PPORT; 8857 dfc_fcsp_config_t fcsp_config; 8858 dfc_password_t dfc_pwd; 8859 uint32_t rval = DFC_SUCCESS; 8860 8861 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.", 8862 emlxs_dfc_xlate(dfc->cmd)); 8863 8864 if (!dfc->buf1 || !dfc->buf1_size) { 8865 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8866 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 8867 8868 return (DFC_ARG_NULL); 8869 } 8870 8871 if (dfc->buf1_size < sizeof (dfc_fcsp_config_t)) { 8872 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8873 "%s: Buffer1 too small. (size=%d)", 8874 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 8875 8876 return (DFC_ARG_TOOSMALL); 8877 } 8878 8879 if (!dfc->buf2 || !dfc->buf2_size) { 8880 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8881 "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd)); 8882 8883 return (DFC_ARG_NULL); 8884 } 8885 8886 if (dfc->buf2_size < sizeof (dfc_password_t)) { 8887 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8888 "%s: Buffer2 too small. (size=%d)", 8889 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 8890 8891 return (DFC_ARG_TOOSMALL); 8892 } 8893 8894 /* Read the fcsp_config */ 8895 if (ddi_copyin((void *)dfc->buf1, (void *)&fcsp_config, 8896 sizeof (dfc_fcsp_config_t), mode) != 0) { 8897 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8898 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 8899 8900 return (DFC_COPYIN_ERROR); 8901 } 8902 8903 /* Read the password */ 8904 if (ddi_copyin((void *)dfc->buf2, (void *)&dfc_pwd, 8905 sizeof (dfc_password_t), mode) != 0) { 8906 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8907 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 8908 8909 return (DFC_COPYIN_ERROR); 8910 } 8911 8912 switch (dfc->flag) { 8913 case EMLXS_AUTH_CFG_ADD: 8914 rval = emlxs_dhc_add_auth_cfg(hba, &fcsp_config, &dfc_pwd); 8915 break; 8916 8917 case EMLXS_AUTH_CFG_DELETE: 8918 rval = emlxs_dhc_delete_auth_cfg(hba, &fcsp_config, &dfc_pwd); 8919 break; 8920 } 8921 8922 if (rval) { 8923 return (rval); 8924 } 8925 8926 if (ddi_copyout((void *)&fcsp_config, (void *)dfc->buf1, 8927 sizeof (dfc_fcsp_config_t), mode) != 0) { 8928 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8929 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 8930 8931 return (DFC_COPYOUT_ERROR); 8932 } 8933 8934 return (0); 8935 8936 } /* emlxs_dfc_set_auth_cfg() */ 8937 8938 8939 8940 static int32_t 8941 emlxs_dfc_get_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 8942 { 8943 emlxs_port_t *port = &PPORT; 8944 dfc_auth_password_t dfc_pwd; 8945 uint32_t rval = DFC_SUCCESS; 8946 8947 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.", 8948 emlxs_dfc_xlate(dfc->cmd)); 8949 8950 if (!dfc->buf1 || !dfc->buf1_size) { 8951 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8952 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 8953 8954 return (DFC_ARG_NULL); 8955 } 8956 8957 if (dfc->buf1_size < sizeof (dfc_auth_password_t)) { 8958 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8959 "%s: Buffer1 too small. (size=%d)", 8960 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 8961 8962 return (DFC_ARG_TOOSMALL); 8963 } 8964 8965 8966 /* Read the auth password */ 8967 if (ddi_copyin((void *)dfc->buf1, (void *)&dfc_pwd, 8968 sizeof (dfc_auth_password_t), mode) != 0) { 8969 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8970 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 8971 8972 return (DFC_COPYIN_ERROR); 8973 } 8974 8975 if ((rval = emlxs_dhc_get_auth_key(hba, &dfc_pwd)) != 0) { 8976 return (rval); 8977 } 8978 8979 if (ddi_copyout((void *)&dfc_pwd, (void *)dfc->buf1, 8980 sizeof (dfc_auth_password_t), mode) != 0) { 8981 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 8982 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 8983 8984 return (DFC_COPYOUT_ERROR); 8985 } 8986 8987 return (0); 8988 8989 } /* emlxs_dfc_get_auth_pwd() */ 8990 8991 8992 static int32_t 8993 emlxs_dfc_set_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 8994 { 8995 emlxs_port_t *port = &PPORT; 8996 dfc_auth_password_t dfc_pwd; 8997 uint32_t rval = DFC_SUCCESS; 8998 8999 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.", 9000 emlxs_dfc_xlate(dfc->cmd)); 9001 9002 if (!dfc->buf1 || !dfc->buf1_size) { 9003 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9004 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 9005 9006 return (DFC_ARG_NULL); 9007 } 9008 9009 if (dfc->buf1_size < sizeof (dfc_auth_password_t)) { 9010 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9011 "%s: Buffer1 too small. (size=%d)", 9012 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 9013 9014 return (DFC_ARG_TOOSMALL); 9015 } 9016 9017 /* Read the auth password */ 9018 if (ddi_copyin((void *)dfc->buf1, (void *)&dfc_pwd, 9019 sizeof (dfc_auth_password_t), mode) != 0) { 9020 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9021 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 9022 9023 return (DFC_COPYIN_ERROR); 9024 } 9025 9026 if ((rval = emlxs_dhc_set_auth_key(hba, &dfc_pwd))) { 9027 return (rval); 9028 } 9029 9030 if (ddi_copyout((void *)&dfc_pwd, (void *)dfc->buf1, 9031 sizeof (dfc_auth_password_t), mode) != 0) { 9032 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9033 "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd)); 9034 9035 return (DFC_COPYOUT_ERROR); 9036 } 9037 9038 return (0); 9039 9040 } /* emlxs_dfc_set_auth_pwd() */ 9041 9042 9043 static int32_t 9044 emlxs_dfc_get_auth_status(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 9045 { 9046 emlxs_port_t *port = &PPORT; 9047 dfc_auth_status_t fcsp_status; 9048 uint32_t rval = DFC_SUCCESS; 9049 9050 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.", 9051 emlxs_dfc_xlate(dfc->cmd)); 9052 9053 if (!dfc->buf1 || !dfc->buf1_size) { 9054 EMLXS_MSGF(EMLXS_CONTEXT, 9055 &emlxs_dfc_error_msg, "%s: Null buffer1 found.", 9056 emlxs_dfc_xlate(dfc->cmd)); 9057 9058 return (DFC_ARG_NULL); 9059 } 9060 9061 if (dfc->buf1_size < sizeof (dfc_auth_status_t)) { 9062 EMLXS_MSGF(EMLXS_CONTEXT, 9063 &emlxs_dfc_error_msg, "%s: Buffer too small. (size=%d)", 9064 emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size); 9065 9066 return (DFC_ARG_TOOSMALL); 9067 } 9068 9069 /* Read the fcsp_config */ 9070 if (ddi_copyin((void *) dfc->buf1, (void *) &fcsp_status, 9071 sizeof (dfc_auth_status_t), mode) != 0) { 9072 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9073 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 9074 9075 return (DFC_COPYIN_ERROR); 9076 } 9077 9078 if ((rval = emlxs_dhc_get_auth_status(hba, &fcsp_status)) != 0) { 9079 return (rval); 9080 } 9081 9082 if (ddi_copyout((void *) &fcsp_status, (void *) dfc->buf1, 9083 sizeof (dfc_auth_status_t), mode) != 0) { 9084 EMLXS_MSGF(EMLXS_CONTEXT, 9085 &emlxs_dfc_error_msg, "%s: ddi_copyout failed.", 9086 emlxs_dfc_xlate(dfc->cmd)); 9087 9088 return (DFC_COPYOUT_ERROR); 9089 } 9090 9091 return (0); 9092 9093 } /* emlxs_dfc_get_auth_status() */ 9094 9095 9096 static int32_t 9097 emlxs_dfc_get_auth_cfg_table(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 9098 { 9099 emlxs_port_t *port = &PPORT; 9100 dfc_fcsp_config_t *fcsp_cfg; 9101 uint32_t count; 9102 uint32_t size; 9103 uint32_t rval = DFC_SUCCESS; 9104 9105 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.", 9106 emlxs_dfc_xlate(dfc->cmd)); 9107 9108 /* Lock cfg table while we do this */ 9109 /* This prevents the table from changing while we get a copy */ 9110 mutex_enter(&hba->auth_lock); 9111 9112 if (!dfc->buf2 || !dfc->buf2_size) { 9113 EMLXS_MSGF(EMLXS_CONTEXT, 9114 &emlxs_dfc_error_msg, "%s: Null buffer2 found.", 9115 emlxs_dfc_xlate(dfc->cmd)); 9116 9117 mutex_exit(&hba->auth_lock); 9118 return (DFC_ARG_NULL); 9119 } 9120 9121 if (dfc->buf2_size < sizeof (uint32_t)) { 9122 EMLXS_MSGF(EMLXS_CONTEXT, 9123 &emlxs_dfc_error_msg, "%s: Buffer2 too small. (size=%d)", 9124 emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size); 9125 9126 mutex_exit(&hba->auth_lock); 9127 return (DFC_ARG_TOOSMALL); 9128 } 9129 9130 if (ddi_copyout((void *)&hba->auth_cfg_count, (void *)dfc->buf2, 9131 sizeof (uint32_t), mode) != 0) { 9132 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9133 "%s: ddi_copyout failed for table count. count=%d", 9134 emlxs_dfc_xlate(dfc->cmd), hba->auth_cfg_count); 9135 9136 mutex_exit(&hba->auth_lock); 9137 return (DFC_COPYOUT_ERROR); 9138 } 9139 9140 if (!dfc->buf1 || !dfc->buf1_size) { 9141 mutex_exit(&hba->auth_lock); 9142 return (DFC_SUCCESS); 9143 } 9144 9145 /* Check table size */ 9146 count = dfc->buf1_size / sizeof (dfc_fcsp_config_t); 9147 if (count < hba->auth_cfg_count) { 9148 EMLXS_MSGF(EMLXS_CONTEXT, 9149 &emlxs_dfc_error_msg, "%s: Buffer1 too small. (%d < %d)", 9150 emlxs_dfc_xlate(dfc->cmd), count, hba->auth_cfg_count); 9151 9152 mutex_exit(&hba->auth_lock); 9153 return (DFC_ARG_TOOSMALL); 9154 } 9155 9156 size = hba->auth_cfg_count * sizeof (dfc_fcsp_config_t); 9157 if (!(fcsp_cfg = (dfc_fcsp_config_t *)kmem_zalloc(size, KM_SLEEP))) { 9158 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9159 "%s: Unable to allocate table buffer.", 9160 emlxs_dfc_xlate(dfc->cmd)); 9161 9162 mutex_exit(&hba->auth_lock); 9163 return (DFC_SYSRES_ERROR); 9164 } 9165 9166 if ((rval = emlxs_dhc_get_auth_cfg_table(hba, fcsp_cfg)) != 0) { 9167 mutex_exit(&hba->auth_lock); 9168 kmem_free(fcsp_cfg, size); 9169 return (rval); 9170 } 9171 9172 mutex_exit(&hba->auth_lock); 9173 9174 if (ddi_copyout((void *)fcsp_cfg, (void *)dfc->buf1, size, mode) != 0) { 9175 EMLXS_MSGF(EMLXS_CONTEXT, 9176 &emlxs_dfc_error_msg, "%s: ddi_copyout failed.", 9177 emlxs_dfc_xlate(dfc->cmd)); 9178 9179 kmem_free(fcsp_cfg, size); 9180 return (DFC_COPYOUT_ERROR); 9181 } 9182 9183 kmem_free(fcsp_cfg, size); 9184 return (0); 9185 9186 } /* emlxs_dfc_get_auth_cfg_table() */ 9187 9188 9189 static int32_t 9190 emlxs_dfc_get_auth_key_table(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 9191 { 9192 emlxs_port_t *port = &PPORT; 9193 dfc_auth_password_t *auth_pwd; 9194 uint32_t count; 9195 uint32_t size; 9196 uint32_t rval = DFC_SUCCESS; 9197 9198 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.", 9199 emlxs_dfc_xlate(dfc->cmd)); 9200 9201 /* Lock cfg table while we do this */ 9202 /* This prevents the table from changing while we get a copy */ 9203 mutex_enter(&hba->auth_lock); 9204 9205 if (!dfc->buf2 || !dfc->buf2_size) { 9206 EMLXS_MSGF(EMLXS_CONTEXT, 9207 &emlxs_dfc_error_msg, "%s: Null buffer2 found.", 9208 emlxs_dfc_xlate(dfc->cmd)); 9209 9210 mutex_exit(&hba->auth_lock); 9211 return (DFC_ARG_NULL); 9212 } 9213 9214 if (dfc->buf2_size < sizeof (uint32_t)) { 9215 EMLXS_MSGF(EMLXS_CONTEXT, 9216 &emlxs_dfc_error_msg, "%s: Buffer2 too small. (size=%d)", 9217 emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size); 9218 9219 mutex_exit(&hba->auth_lock); 9220 return (DFC_ARG_TOOSMALL); 9221 } 9222 9223 if (ddi_copyout((void *)&hba->auth_key_count, (void *)dfc->buf2, 9224 sizeof (uint32_t), mode) != 0) { 9225 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9226 "%s: ddi_copyout failed for table count. count=%d", 9227 emlxs_dfc_xlate(dfc->cmd), hba->auth_key_count); 9228 9229 mutex_exit(&hba->auth_lock); 9230 return (DFC_COPYOUT_ERROR); 9231 } 9232 9233 if (!dfc->buf1 || !dfc->buf1_size) { 9234 mutex_exit(&hba->auth_lock); 9235 return (DFC_SUCCESS); 9236 } 9237 9238 /* Check table size */ 9239 count = dfc->buf1_size / sizeof (dfc_auth_password_t); 9240 if (count < hba->auth_key_count) { 9241 EMLXS_MSGF(EMLXS_CONTEXT, 9242 &emlxs_dfc_error_msg, "%s: Buffer1 too small. (%d < %d)", 9243 emlxs_dfc_xlate(dfc->cmd), count, hba->auth_key_count); 9244 9245 mutex_exit(&hba->auth_lock); 9246 return (DFC_ARG_TOOSMALL); 9247 } 9248 9249 size = hba->auth_key_count * sizeof (dfc_auth_password_t); 9250 if (!(auth_pwd = (dfc_auth_password_t *)kmem_zalloc(size, KM_SLEEP))) { 9251 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9252 "%s: Unable to allocate table buffer.", 9253 emlxs_dfc_xlate(dfc->cmd)); 9254 9255 mutex_exit(&hba->auth_lock); 9256 return (DFC_SYSRES_ERROR); 9257 } 9258 9259 if ((rval = emlxs_dhc_get_auth_key_table(hba, auth_pwd)) != 0) { 9260 mutex_exit(&hba->auth_lock); 9261 kmem_free(auth_pwd, size); 9262 return (rval); 9263 } 9264 9265 mutex_exit(&hba->auth_lock); 9266 9267 if (ddi_copyout((void *)auth_pwd, (void *)dfc->buf1, size, mode) != 0) { 9268 EMLXS_MSGF(EMLXS_CONTEXT, 9269 &emlxs_dfc_error_msg, "%s: ddi_copyout failed.", 9270 emlxs_dfc_xlate(dfc->cmd)); 9271 9272 kmem_free(auth_pwd, size); 9273 return (DFC_COPYOUT_ERROR); 9274 } 9275 9276 kmem_free(auth_pwd, size); 9277 return (0); 9278 9279 } /* emlxs_dfc_get_auth_key_table() */ 9280 9281 9282 9283 #endif /* DHCHAP_SUPPORT */ 9284 9285 #ifdef SAN_DIAG_SUPPORT 9286 static int32_t 9287 emlxs_dfc_sd_set_bucket(dfc_t *dfc, int32_t mode) 9288 { 9289 uint32_t type, search_type; 9290 uint16_t state; 9291 int32_t rval = DFC_SD_OK; 9292 9293 type = dfc->data1; 9294 search_type = dfc->data2; 9295 9296 mutex_enter(&sd_bucket_mutex); 9297 state = sd_bucket.state; 9298 mutex_exit(&sd_bucket_mutex); 9299 9300 if (state == SD_COLLECTING) 9301 rval = DFC_SD_ERROR_DATA_COLLECTION_ACTIVE; 9302 else if ((search_type < SD_SEARCH_LINEAR) || 9303 (search_type > SD_SEARCH_POWER_2)) 9304 rval = DFC_SD_ERROR_INVALID_ARG; 9305 else if (type != SD_SCSI_IO_LATENCY_TYPE) 9306 rval = DFC_SD_ERROR_NOT_SUPPORTED; 9307 else { 9308 (void) ddi_copyin(dfc->buf3, (void *) &sd_bucket, 9309 sizeof (sd_bucket_info_t), mode); 9310 mutex_enter(&sd_bucket_mutex); 9311 sd_bucket.state = SD_STOPPED; 9312 mutex_exit(&sd_bucket_mutex); 9313 } 9314 9315 set_bucket_exit: 9316 return (rval); 9317 } 9318 9319 9320 static int32_t 9321 emlxs_dfc_sd_destroy_bucket(dfc_t *dfc) 9322 { 9323 uint32_t type; 9324 int32_t rval = DFC_SD_OK; 9325 9326 type = dfc->data1; 9327 9328 mutex_enter(&sd_bucket_mutex); 9329 9330 if (sd_bucket.search_type == 0) 9331 rval = DFC_SD_ERROR_BUCKET_NOT_SET; 9332 else if (sd_bucket.state == SD_COLLECTING) 9333 rval = DFC_SD_ERROR_DATA_COLLECTION_ACTIVE; 9334 else if (type != SD_SCSI_IO_LATENCY_TYPE) 9335 rval = DFC_SD_ERROR_NOT_SUPPORTED; 9336 else 9337 bzero((uint8_t *)&sd_bucket, sizeof (sd_bucket_info_t)); 9338 9339 destroy_bucket_exit: 9340 mutex_exit(&sd_bucket_mutex); 9341 return (rval); 9342 } 9343 9344 9345 static int32_t 9346 emlxs_dfc_sd_get_bucket(dfc_t *dfc, int32_t mode) 9347 { 9348 uint32_t type; 9349 int32_t rval = DFC_SD_OK; 9350 9351 type = dfc->data1; 9352 9353 if (sd_bucket.search_type == 0) 9354 rval = DFC_SD_ERROR_BUCKET_NOT_SET; 9355 else if (type != SD_SCSI_IO_LATENCY_TYPE) 9356 rval = DFC_SD_ERROR_NOT_SUPPORTED; 9357 else 9358 (void) ddi_copyout(&sd_bucket, dfc->buf3, 9359 sizeof (sd_bucket_info_t), mode); 9360 9361 return (rval); 9362 } 9363 9364 9365 static int32_t 9366 emlxs_dfc_sd_start_collection(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 9367 { 9368 emlxs_port_t *vport; 9369 NODELIST *nlp; 9370 uint8_t wwpn[8]; 9371 int32_t rval = DFC_SD_OK; 9372 int i; 9373 9374 if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) { 9375 rval = DFC_SD_ERROR_NOT_SUPPORTED; 9376 goto start_collect_exit; 9377 } 9378 9379 if (sd_bucket.search_type == 0) { 9380 rval = DFC_SD_ERROR_BUCKET_NOT_SET; 9381 goto start_collect_exit; 9382 } 9383 9384 /* Read the wwn object */ 9385 (void) ddi_copyin((void *)dfc->buf3, (void *)wwpn, 8, mode); 9386 9387 /* Make sure WWPN is unique */ 9388 vport = emlxs_vport_find_wwpn(hba, wwpn); 9389 9390 if (!vport) { 9391 rval = DFC_SD_ERROR_INVALID_PORT; 9392 goto start_collect_exit; 9393 } 9394 9395 /* traverse list of nodes for this vport and reset counter */ 9396 rw_enter(&vport->node_rwlock, RW_READER); 9397 if (vport->sd_io_latency_state == SD_COLLECTING) { 9398 rval = DFC_SD_ERROR_DATA_COLLECTION_ACTIVE; 9399 rw_exit(&vport->node_rwlock); 9400 goto start_collect_exit; 9401 } 9402 9403 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 9404 nlp = vport->node_table[i]; 9405 while (nlp != NULL) { 9406 bzero((void *)&nlp->sd_dev_bucket[0], 9407 sizeof (struct SD_time_stats_v0) * 9408 SD_IO_LATENCY_MAX_BUCKETS); 9409 9410 nlp = nlp->nlp_list_next; 9411 } 9412 } 9413 9414 vport->sd_io_latency_state = SD_COLLECTING; 9415 rw_exit(&vport->node_rwlock); 9416 9417 mutex_enter(&sd_bucket_mutex); 9418 sd_bucket.state = SD_COLLECTING; 9419 mutex_exit(&sd_bucket_mutex); 9420 9421 start_collect_exit: 9422 return (rval); 9423 } 9424 9425 9426 static int32_t 9427 emlxs_dfc_sd_stop_collection(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 9428 { 9429 emlxs_port_t *vport; 9430 emlxs_hba_t *temp_hba; 9431 uint8_t wwpn[8]; 9432 int32_t rval = DFC_SD_OK; 9433 int i, j; 9434 9435 if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) { 9436 rval = DFC_SD_ERROR_NOT_SUPPORTED; 9437 goto stop_collect_exit; 9438 } 9439 9440 if (sd_bucket.search_type == 0) { 9441 rval = DFC_SD_ERROR_BUCKET_NOT_SET; 9442 goto stop_collect_exit; 9443 } 9444 9445 /* Read the wwn object */ 9446 (void) ddi_copyin((void *)dfc->buf3, (void *)wwpn, 8, mode); 9447 9448 /* Make sure WWPN is unique */ 9449 vport = emlxs_vport_find_wwpn(hba, wwpn); 9450 9451 if (!vport) { 9452 rval = DFC_SD_ERROR_INVALID_PORT; 9453 goto stop_collect_exit; 9454 } 9455 9456 rw_enter(&vport->node_rwlock, RW_READER); 9457 if (vport->sd_io_latency_state != SD_COLLECTING) { 9458 rval = DFC_SD_ERROR_DATA_COLLECTION_NOT_ACTIVE; 9459 rw_exit(&vport->node_rwlock); 9460 goto stop_collect_exit; 9461 } 9462 vport->sd_io_latency_state = SD_STOPPED; 9463 rw_exit(&vport->node_rwlock); 9464 9465 /* see if any other port is collecting io latency */ 9466 for (i = 0; i < emlxs_device.hba_count; i++) { 9467 temp_hba = emlxs_device.hba[i]; 9468 for (j = 0; j < temp_hba->num_of_ports; j++) { 9469 vport = &temp_hba->port[j]; 9470 if (vport->sd_io_latency_state == SD_COLLECTING) 9471 goto stop_collect_exit; 9472 } 9473 } 9474 9475 /* 9476 * if we get here, that means no one else is collecting 9477 * io latency data. 9478 */ 9479 mutex_enter(&sd_bucket_mutex); 9480 sd_bucket.state = SD_STOPPED; 9481 mutex_exit(&sd_bucket_mutex); 9482 9483 stop_collect_exit: 9484 return (rval); 9485 } 9486 9487 9488 static int32_t 9489 emlxs_dfc_sd_reset_collection(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 9490 { 9491 emlxs_port_t *vport; 9492 NODELIST *nlp; 9493 uint8_t wwpn[8]; 9494 int32_t rval = DFC_SD_OK; 9495 int i; 9496 9497 if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) { 9498 rval = DFC_SD_ERROR_NOT_SUPPORTED; 9499 goto reset_collect_exit; 9500 } 9501 9502 if (sd_bucket.search_type == 0) { 9503 rval = DFC_SD_ERROR_BUCKET_NOT_SET; 9504 goto reset_collect_exit; 9505 } 9506 9507 /* Read the wwn object */ 9508 (void) ddi_copyin((void *)dfc->buf3, (void *)wwpn, 8, mode); 9509 9510 /* Make sure WWPN is unique */ 9511 vport = emlxs_vport_find_wwpn(hba, wwpn); 9512 9513 if (!vport) { 9514 rval = DFC_SD_ERROR_INVALID_PORT; 9515 goto reset_collect_exit; 9516 } 9517 9518 /* traverse list of nodes for this vport and reset counter */ 9519 rw_enter(&vport->node_rwlock, RW_READER); 9520 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 9521 nlp = vport->node_table[i]; 9522 while (nlp != NULL) { 9523 bzero((void *)&nlp->sd_dev_bucket[0], 9524 sizeof (struct SD_time_stats_v0) * 9525 SD_IO_LATENCY_MAX_BUCKETS); 9526 9527 nlp = nlp->nlp_list_next; 9528 } 9529 } 9530 rw_exit(&vport->node_rwlock); 9531 9532 reset_collect_exit: 9533 return (rval); 9534 } 9535 9536 9537 static int32_t 9538 emlxs_dfc_sd_get_data(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 9539 { 9540 emlxs_port_t *vport; 9541 uint8_t wwpn[8]; 9542 int i, skip_bytes; 9543 uint16_t count; 9544 uint32_t bufsize, size_needed; 9545 NODELIST *nlp; 9546 int32_t rval = DFC_SD_OK; 9547 9548 if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) { 9549 rval = DFC_SD_ERROR_NOT_SUPPORTED; 9550 goto get_data_exit; 9551 } 9552 9553 if (sd_bucket.search_type == 0) { 9554 rval = DFC_SD_ERROR_BUCKET_NOT_SET; 9555 goto get_data_exit; 9556 } 9557 9558 /* Read the wwn object */ 9559 (void) ddi_copyin((void *)dfc->buf3, (void *)wwpn, 8, mode); 9560 9561 /* Make sure WWPN is unique */ 9562 vport = emlxs_vport_find_wwpn(hba, wwpn); 9563 9564 if (!vport) { 9565 rval = DFC_SD_ERROR_INVALID_PORT; 9566 goto get_data_exit; 9567 } 9568 9569 bufsize = dfc->buf4_size; 9570 9571 /* 9572 * count # of targets to see if buffer is big enough 9573 */ 9574 count = 0; 9575 rw_enter(&vport->node_rwlock, RW_READER); 9576 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 9577 nlp = vport->node_table[i]; 9578 while (nlp != NULL) { 9579 count++; 9580 nlp = nlp->nlp_list_next; 9581 } 9582 } 9583 rw_exit(&vport->node_rwlock); 9584 9585 size_needed = count * (sizeof (HBA_WWN) + 9586 sizeof (struct SD_time_stats_v0) * SD_IO_LATENCY_MAX_BUCKETS); 9587 9588 if (bufsize < size_needed) { 9589 rval = DFC_SD_ERROR_MORE_DATA_AVAIL; 9590 goto update_count; /* not enough space, return */ 9591 } 9592 9593 /* 9594 * return data collected, reset counter. 9595 */ 9596 count = 0; 9597 skip_bytes = 0; 9598 rw_enter(&vport->node_rwlock, RW_READER); 9599 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 9600 nlp = vport->node_table[i]; 9601 while (nlp != NULL) { 9602 /* copy port name */ 9603 (void) ddi_copyout((void *)&nlp->nlp_portname, 9604 (void *)((char *)dfc->buf4 + skip_bytes), 9605 sizeof (HBA_WWN), mode); 9606 skip_bytes += sizeof (HBA_WWN); 9607 9608 /* copy bucket data */ 9609 (void) ddi_copyout((void *)&nlp->sd_dev_bucket[0], 9610 (void *)((char *)dfc->buf4 + skip_bytes), 9611 sizeof (struct SD_time_stats_v0) * 9612 SD_IO_LATENCY_MAX_BUCKETS, mode); 9613 skip_bytes += sizeof (struct SD_time_stats_v0) * 9614 SD_IO_LATENCY_MAX_BUCKETS; 9615 9616 bzero((void *)&nlp->sd_dev_bucket[0], 9617 sizeof (struct SD_time_stats_v0) * 9618 SD_IO_LATENCY_MAX_BUCKETS); 9619 9620 count++; 9621 bufsize -= sizeof (struct SD_IO_Latency_Response); 9622 9623 nlp = nlp->nlp_list_next; 9624 } 9625 } 9626 rw_exit(&vport->node_rwlock); 9627 9628 update_count: 9629 (void) ddi_copyout((void *)&count, (void *)dfc->buf2, 9630 sizeof (uint16_t), mode); 9631 9632 get_data_exit: 9633 return (rval); 9634 } 9635 9636 9637 static int32_t 9638 emlxs_dfc_sd_set_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 9639 { 9640 emlxs_port_t *vport; 9641 uint8_t wwpn[8]; 9642 uint32_t event, pid, enable; 9643 int32_t rval = DFC_SD_OK; 9644 int i, count; 9645 emlxs_dfc_event_t *dfc_event; 9646 9647 /* 9648 * The value of "event" has been shifted left based on 9649 * the category that the application gave to libdfc. 9650 * 9651 * This is so the old Event handling code won't mistakenly 9652 * grab an SD Event. 9653 */ 9654 event = dfc->data1; 9655 pid = dfc->data3; 9656 enable = dfc->flag; 9657 9658 /* Read the wwn object */ 9659 (void) ddi_copyin((void *)dfc->buf3, (void *)wwpn, 8, mode); 9660 9661 /* Make sure WWPN is unique */ 9662 vport = emlxs_vport_find_wwpn(hba, wwpn); 9663 9664 if (!vport) { 9665 rval = DFC_SD_ERROR_INVALID_PORT; 9666 goto set_sd_event_exit; 9667 } 9668 9669 if (enable) { 9670 /* Find next available event object */ 9671 for (i = 0; i < MAX_DFC_EVENTS; i++) { 9672 dfc_event = &vport->sd_events[i]; 9673 9674 if (!dfc_event->pid && !dfc_event->event) 9675 break; 9676 } 9677 9678 /* Return if all event objects are busy */ 9679 if (i == MAX_DFC_EVENTS) { 9680 rval = DFC_SD_ERROR_OUT_OF_HANDLES; 9681 goto set_sd_event_exit; 9682 } 9683 9684 /* Initialize */ 9685 /* TODO: Should we add SUBCAT in dfc_event ??? */ 9686 dfc_event->pid = pid; 9687 dfc_event->event = event; 9688 dfc_event->last_id = (uint32_t)-1; 9689 dfc_event->dataout = NULL; 9690 dfc_event->size = 0; 9691 dfc_event->mode = 0; 9692 9693 (void) emlxs_get_sd_event(vport, dfc_event, 0); 9694 9695 if (dfc->buf1) 9696 (void) ddi_copyout((void *) &dfc_event->last_id, 9697 dfc->buf1, sizeof (uint32_t), mode); 9698 9699 vport->sd_reg_events |= event; 9700 } else { /* Disable */ 9701 /* find event entry */ 9702 for (i = 0; i < MAX_DFC_EVENTS; i++) { 9703 dfc_event = &vport->sd_events[i]; 9704 9705 if (dfc_event->pid == pid && dfc_event->event == event) 9706 break; 9707 } 9708 9709 /* Return if not found */ 9710 if (i == MAX_DFC_EVENTS) { 9711 rval = DFC_SD_ERROR_INVALID_ARG; 9712 goto set_sd_event_exit; 9713 } 9714 9715 /* Kill the event thread if it is sleeping */ 9716 (void) emlxs_kill_dfc_event(vport, dfc_event); 9717 9718 /* Count the number of pids still registered for this event */ 9719 count = 0; 9720 for (i = 0; i < MAX_DFC_EVENTS; i++) { 9721 dfc_event = &vport->sd_events[i]; 9722 9723 if (dfc_event->event == event) 9724 count++; 9725 } 9726 9727 /* 9728 * If no more pids need this event, 9729 * then disable logging for this event 9730 */ 9731 if (count == 0) 9732 vport->sd_reg_events &= ~event; 9733 } 9734 9735 set_sd_event_exit: 9736 return (rval); 9737 } /* emlxs_dfc_sd_set_event */ 9738 9739 9740 static int32_t 9741 emlxs_dfc_sd_get_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 9742 { 9743 emlxs_port_t *vport; 9744 uint8_t wwpn[8]; 9745 uint32_t event, pid, sleep, i; 9746 int32_t rval = DFC_SD_OK; 9747 emlxs_dfc_event_t *dfc_event; 9748 9749 event = dfc->data1; 9750 pid = dfc->data2; 9751 9752 /* Read the wwn object */ 9753 (void) ddi_copyin((void *)dfc->buf4, (void *)wwpn, 8, mode); 9754 9755 /* Make sure WWPN is unique */ 9756 vport = emlxs_vport_find_wwpn(hba, wwpn); 9757 9758 if (!vport) { 9759 rval = DFC_SD_ERROR_INVALID_PORT; 9760 goto get_sd_event_exit; 9761 } 9762 9763 /* Find the event entry */ 9764 dfc_event = NULL; 9765 for (i = 0; i < MAX_DFC_EVENTS; i++) { 9766 dfc_event = &vport->sd_events[i]; 9767 9768 if (dfc_event->pid == pid && dfc_event->event == event) 9769 break; 9770 } 9771 9772 if (i == MAX_DFC_EVENTS) { 9773 rval = DFC_SD_ERROR_GENERIC; 9774 goto get_sd_event_exit; 9775 } 9776 9777 if (!(vport->sd_reg_events & dfc_event->event)) { 9778 rval = DFC_SD_ERROR_GENERIC; 9779 goto get_sd_event_exit; 9780 } 9781 9782 /* Initialize event buffer pointers */ 9783 dfc_event->dataout = dfc->buf1; 9784 dfc_event->size = dfc->buf1_size; 9785 dfc_event->last_id = dfc->data3; 9786 dfc_event->mode = mode; 9787 9788 sleep = (dfc->flag & 0x01) ? 1 : 0; 9789 9790 if (emlxs_get_sd_event(vport, dfc_event, sleep)) 9791 return (DFC_SD_ERROR_GENERIC); 9792 9793 /* 9794 * update rcv_size. 9795 */ 9796 if (dfc->buf2) 9797 (void) ddi_copyout((void *) &dfc_event->size, dfc->buf2, 9798 sizeof (uint32_t), mode); 9799 9800 /* 9801 * update index 9802 */ 9803 if (dfc->buf3) 9804 (void) ddi_copyout((void *) &dfc_event->last_id, dfc->buf3, 9805 sizeof (uint32_t), mode); 9806 9807 get_sd_event_exit: 9808 return (rval); 9809 } /* emlxs_dfc_sd_get_event */ 9810 #endif 9811 9812 static int32_t 9813 emlxs_dfc_send_scsi_fcp(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) 9814 { 9815 emlxs_port_t *port = &PPORT; 9816 fc_packet_t *pkt = NULL; 9817 NODELIST *ndlp; 9818 FCP_CMND *fcp_cmd; 9819 FCP_RSP *fcp_rsp; 9820 void *ptr; 9821 char buffer[64]; 9822 dfc_send_scsi_fcp_cmd_info_t cmdinfo; 9823 uint32_t rval = 0; 9824 9825 /* cmd info */ 9826 if (!dfc->buf1 || 9827 (dfc->buf1_size != sizeof (dfc_send_scsi_fcp_cmd_info_t))) { 9828 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9829 "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd)); 9830 9831 rval = DFC_ARG_NULL; 9832 goto done; 9833 } 9834 9835 /* reqBuffer info */ 9836 if (!dfc->buf2 || (dfc->buf2_size != sizeof (FCP_CMND))) { 9837 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9838 "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd)); 9839 9840 rval = DFC_ARG_NULL; 9841 goto done; 9842 } 9843 9844 /* rspBuffer info, could be 0 for SCSI commands like TUR */ 9845 if (!dfc->buf3 && dfc->buf3_size) { 9846 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9847 "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd)); 9848 9849 rval = DFC_ARG_NULL; 9850 goto done; 9851 } 9852 9853 /* senseBuffer info */ 9854 if (!dfc->buf4 || !dfc->buf4_size) { 9855 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9856 "%s: Null buffer4 found.", emlxs_dfc_xlate(dfc->cmd)); 9857 9858 rval = DFC_ARG_NULL; 9859 goto done; 9860 } 9861 9862 if (ddi_copyin((void *) dfc->buf1, (void *) &cmdinfo, 9863 sizeof (dfc_send_scsi_fcp_cmd_info_t), mode) != 0) { 9864 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9865 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 9866 9867 rval = DFC_COPYIN_ERROR; 9868 goto done; 9869 } 9870 #ifdef NPIV_SUPPORT 9871 if (cmdinfo.ver == DFC_SEND_SCSI_FCP_V2) { 9872 port = 9873 emlxs_vport_find_wwpn(hba, (uint8_t *)&cmdinfo.src_wwn); 9874 if (port == NULL) { 9875 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9876 "%s: WWPN does not exists. %s", 9877 emlxs_dfc_xlate(dfc->cmd), emlxs_wwn_xlate(buffer, 9878 (uint8_t *)&cmdinfo.src_wwn)); 9879 9880 rval = DFC_ARG_INVALID; 9881 goto done; 9882 } 9883 } 9884 #endif /* NPIV_SUPPORT */ 9885 9886 if ((ndlp = emlxs_node_find_wwpn(port, 9887 (uint8_t *)&cmdinfo.dst_wwn)) == NULL) { 9888 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9889 "%s: WWPN does not exists. %s", emlxs_dfc_xlate(dfc->cmd), 9890 emlxs_wwn_xlate(buffer, (uint8_t *)&cmdinfo.dst_wwn)); 9891 9892 rval = DFC_ARG_INVALID; 9893 goto done; 9894 } 9895 9896 if (!(pkt = emlxs_pkt_alloc(port, sizeof (FCP_CMND), sizeof (FCP_RSP), 9897 dfc->buf3_size, KM_NOSLEEP))) { 9898 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9899 "%s: Unable to allocate packet.", 9900 emlxs_dfc_xlate(dfc->cmd)); 9901 9902 rval = DFC_SYSRES_ERROR; 9903 goto done; 9904 } 9905 fcp_cmd = (FCP_CMND *) pkt->pkt_cmd; 9906 /* Copy in the command buffer */ 9907 if (ddi_copyin((void *)dfc->buf2, (void *)fcp_cmd, sizeof (FCP_CMND), 9908 mode) != 0) { 9909 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9910 "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd)); 9911 9912 rval = DFC_COPYIN_ERROR; 9913 goto done; 9914 } 9915 9916 /* Make this a polled IO */ 9917 pkt->pkt_tran_flags &= ~FC_TRAN_INTR; 9918 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR; 9919 pkt->pkt_comp = NULL; 9920 9921 /* Build the fc header */ 9922 pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(ndlp->nlp_DID); 9923 pkt->pkt_cmd_fhdr.r_ctl = FC_FCP_CMND; 9924 pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did); 9925 pkt->pkt_cmd_fhdr.type = FC_FCP_DATA; 9926 pkt->pkt_cmd_fhdr.seq_id = 0; 9927 pkt->pkt_cmd_fhdr.df_ctl = 0; 9928 pkt->pkt_cmd_fhdr.seq_cnt = 0; 9929 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 9930 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF; 9931 pkt->pkt_cmd_fhdr.ro = 0; 9932 9933 pkt->pkt_timeout = 30; 9934 9935 if ((fcp_cmd->fcpCntl3 == WRITE_DATA) && dfc->buf3_size) { 9936 pkt->pkt_tran_type = FC_PKT_FCP_WRITE; 9937 if (ddi_copyin((void *)dfc->buf3, (void *)pkt->pkt_data, 9938 dfc->buf3_size, mode) != 0) { 9939 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9940 "%s: ddi_copyin failed.", 9941 emlxs_dfc_xlate(dfc->cmd)); 9942 9943 rval = DFC_COPYIN_ERROR; 9944 goto done; 9945 } 9946 } else { 9947 pkt->pkt_tran_type = FC_PKT_FCP_READ; 9948 } 9949 9950 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 9951 rval = DFC_IO_ERROR; 9952 goto done; 9953 } 9954 9955 if (pkt->pkt_state != FC_PKT_SUCCESS) { 9956 if (pkt->pkt_state == FC_PKT_TIMEOUT) { 9957 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9958 "Pkt Transport error. Pkt Timeout."); 9959 rval = DFC_TIMEOUT; 9960 } else { 9961 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9962 "Pkt Transport error. state=%x", pkt->pkt_state); 9963 rval = DFC_IO_ERROR; 9964 } 9965 goto done; 9966 } 9967 9968 if (pkt->pkt_data_resid) { 9969 if (pkt->pkt_data_resid < dfc->buf3_size) 9970 dfc->buf3_size -= pkt->pkt_data_resid; 9971 else 9972 dfc->buf3_size = 0; 9973 } 9974 9975 SCSI_RSP_CNT(cmdinfo) = dfc->buf3_size; 9976 9977 fcp_rsp = (FCP_RSP *) pkt->pkt_resp; 9978 /* 9979 * This is sense count for flag = 0. 9980 * It is fcp response size for flag = 1. 9981 */ 9982 if (dfc->flag) { 9983 SCSI_SNS_CNT(cmdinfo) = 24 + SWAP_DATA32(fcp_rsp->rspSnsLen) + 9984 SWAP_DATA32(fcp_rsp->rspRspLen); 9985 ptr = (void *)fcp_rsp; 9986 } else { 9987 SCSI_SNS_CNT(cmdinfo) = SWAP_DATA32(fcp_rsp->rspSnsLen); 9988 ptr = (void *)&fcp_rsp->rspSnsInfo[0]; 9989 } 9990 9991 if (ddi_copyout((void *) &cmdinfo, (void *) dfc->buf1, 9992 sizeof (dfc_send_scsi_fcp_cmd_info_t), mode) != 0) { 9993 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 9994 "%s: rsp_buf ddi_copyout failed.", 9995 emlxs_dfc_xlate(dfc->cmd)); 9996 9997 rval = DFC_COPYOUT_ERROR; 9998 goto done; 9999 } 10000 10001 if (SCSI_SNS_CNT(cmdinfo)) { 10002 if (ddi_copyout(ptr, (void *)dfc->buf4, SCSI_SNS_CNT(cmdinfo), 10003 mode) != 0) { 10004 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 10005 "%s: rsp_size ddi_copyout failed.", 10006 emlxs_dfc_xlate(dfc->cmd)); 10007 10008 rval = DFC_COPYOUT_ERROR; 10009 goto done; 10010 } 10011 } 10012 10013 if (SCSI_RSP_CNT(cmdinfo)) { 10014 if (ddi_copyout((void *)pkt->pkt_data, (void *)dfc->buf3, 10015 SCSI_RSP_CNT(cmdinfo), mode) != 0) { 10016 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, 10017 "%s: rsp_size ddi_copyout failed.", 10018 emlxs_dfc_xlate(dfc->cmd)); 10019 10020 rval = DFC_COPYOUT_ERROR; 10021 goto done; 10022 } 10023 } 10024 10025 10026 rval = 0; 10027 10028 done: 10029 if (pkt) { 10030 emlxs_pkt_free(pkt); 10031 } 10032 10033 return (rval); 10034 10035 } /* emlxs_dfc_send_scsi_fcp() */ 10036 10037 #endif /* DFC_SUPPORT */ 10038