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