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