1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Emulex. All rights reserved. 24 * Use is subject to License terms. 25 */ 26 27 #include <emlxs.h> 28 29 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 30 EMLXS_MSG_DEF(EMLXS_MBOX_C); 31 32 static void emlxs_mb_part_slim(emlxs_hba_t *hba, MAILBOX *mb, 33 uint32_t hbainit); 34 static void emlxs_mb_set_mask(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mask, 35 uint32_t ringno); 36 static void emlxs_mb_set_debug(emlxs_hba_t *hba, MAILBOX *mb, 37 uint32_t word0, uint32_t word1, uint32_t word2); 38 static int32_t emlxs_mb_handle_cmd(emlxs_hba_t *hba, MAILBOX *mb); 39 static void emlxs_mb_write_nv(emlxs_hba_t *hba, MAILBOX *mb); 40 41 42 emlxs_table_t emlxs_mb_cmd_table[] = { 43 {MBX_SHUTDOWN, "SHUTDOWN"}, 44 {MBX_LOAD_SM, "LOAD_SM"}, 45 {MBX_READ_NV, "READ_NV"}, 46 {MBX_WRITE_NV, "WRITE_NV"}, 47 {MBX_RUN_BIU_DIAG, "RUN_BIU_DIAG"}, 48 {MBX_INIT_LINK, "INIT_LINK"}, 49 {MBX_DOWN_LINK, "DOWN_LINK"}, 50 {MBX_CONFIG_LINK, "CONFIG_LINK"}, 51 {MBX_PART_SLIM, "PART_SLIM"}, 52 {MBX_CONFIG_RING, "CONFIG_RING"}, 53 {MBX_RESET_RING, "RESET_RING"}, 54 {MBX_READ_CONFIG, "READ_CONFIG"}, 55 {MBX_READ_RCONFIG, "READ_RCONFIG"}, 56 {MBX_READ_SPARM, "READ_SPARM"}, 57 {MBX_READ_STATUS, "READ_STATUS"}, 58 {MBX_READ_RPI, "READ_RPI"}, 59 {MBX_READ_XRI, "READ_XRI"}, 60 {MBX_READ_REV, "READ_REV"}, 61 {MBX_READ_LNK_STAT, "READ_LNK_STAT"}, 62 {MBX_REG_LOGIN, "REG_LOGIN"}, 63 {MBX_UNREG_LOGIN, "UNREG_LOGIN"}, 64 {MBX_READ_LA, "READ_LA"}, 65 {MBX_CLEAR_LA, "CLEAR_LA"}, 66 {MBX_DUMP_MEMORY, "DUMP_MEMORY"}, 67 {MBX_DUMP_CONTEXT, "DUMP_CONTEXT"}, 68 {MBX_RUN_DIAGS, "RUN_DIAGS"}, 69 {MBX_RESTART, "RESTART"}, 70 {MBX_UPDATE_CFG, "UPDATE_CFG"}, 71 {MBX_DOWN_LOAD, "DOWN_LOAD"}, 72 {MBX_DEL_LD_ENTRY, "DEL_LD_ENTRY"}, 73 {MBX_RUN_PROGRAM, "RUN_PROGRAM"}, 74 {MBX_SET_MASK, "SET_MASK"}, 75 {MBX_SET_VARIABLE, "SET_VARIABLE"}, 76 {MBX_UNREG_D_ID, "UNREG_D_ID"}, 77 {MBX_KILL_BOARD, "KILL_BOARD"}, 78 {MBX_CONFIG_FARP, "CONFIG_FARP"}, 79 {MBX_LOAD_AREA, "LOAD_AREA"}, 80 {MBX_RUN_BIU_DIAG64, "RUN_BIU_DIAG64"}, 81 {MBX_CONFIG_PORT, "CONFIG_PORT"}, 82 {MBX_READ_SPARM64, "READ_SPARM64"}, 83 {MBX_READ_RPI64, "READ_RPI64"}, 84 {MBX_CONFIG_MSI, "CONFIG_MSI"}, 85 {MBX_CONFIG_MSIX, "CONFIG_MSIX"}, 86 {MBX_REG_LOGIN64, "REG_LOGIN64"}, 87 {MBX_READ_LA64, "READ_LA64"}, 88 {MBX_FLASH_WR_ULA, "FLASH_WR_ULA"}, 89 {MBX_SET_DEBUG, "SET_DEBUG"}, 90 {MBX_GET_DEBUG, "GET_DEBUG"}, 91 {MBX_LOAD_EXP_ROM, "LOAD_EXP_ROM"}, 92 {MBX_BEACON, "BEACON"}, 93 {MBX_CONFIG_HBQ, "CONFIG_HBQ"}, /* SLI3 */ 94 {MBX_REG_VPI, "REG_VPI"}, /* NPIV */ 95 {MBX_ASYNC_EVENT, "ASYNC_EVENT"}, 96 {MBX_HEARTBEAT, "HEARTBEAT"}, 97 {MBX_READ_EVENT_LOG_STATUS, "READ_EVENT_LOG_STATUS"}, 98 {MBX_READ_EVENT_LOG, "READ_EVENT_LOG"}, 99 {MBX_WRITE_EVENT_LOG, "WRITE_EVENT_LOG"}, 100 {MBX_NV_LOG, "NV_LOG"}, 101 {MBX_PORT_CAPABILITIES, "PORT_CAPABILITIES"}, 102 {MBX_IOV_CONTROL, "IOV_CONTROL"}, 103 {MBX_IOV_MBX, "IOV_MBX"} 104 }; /* emlxs_mb_cmd_table */ 105 106 107 /*ARGSUSED*/ 108 extern void 109 emlxs_mb_async_event(emlxs_hba_t *hba, MAILBOX *mb) 110 { 111 bzero((void *) mb, MAILBOX_CMD_BSIZE); 112 113 mb->mbxCommand = MBX_ASYNC_EVENT; 114 mb->mbxOwner = OWN_HOST; 115 mb->un.varWords[0] = FC_ELS_RING; 116 117 return; 118 119 } /* emlxs_mb_async_event() */ 120 121 122 /*ARGSUSED*/ 123 extern void 124 emlxs_mb_heartbeat(emlxs_hba_t *hba, MAILBOX *mb) 125 { 126 bzero((void *) mb, MAILBOX_CMD_BSIZE); 127 128 mb->mbxCommand = MBX_HEARTBEAT; 129 mb->mbxOwner = OWN_HOST; 130 131 return; 132 133 } /* emlxs_mb_heartbeat() */ 134 135 136 #ifdef MSI_SUPPORT 137 138 /*ARGSUSED*/ 139 extern void 140 emlxs_mb_config_msi(emlxs_hba_t *hba, MAILBOX *mb, uint32_t *intr_map, 141 uint32_t intr_count) 142 { 143 uint32_t i; 144 uint32_t mask; 145 146 bzero((void *)mb, MAILBOX_CMD_BSIZE); 147 148 mb->mbxCommand = MBX_CONFIG_MSI; 149 150 /* Set the default message id to zero */ 151 mb->un.varCfgMSI.defaultPresent = 1; 152 mb->un.varCfgMSI.defaultMessageNumber = 0; 153 154 for (i = 1; i < intr_count; i++) { 155 mask = intr_map[i]; 156 157 mb->un.varCfgMSI.attConditions |= mask; 158 159 #ifdef EMLXS_BIG_ENDIAN 160 if (mask & HA_R0ATT) { 161 mb->un.varCfgMSI.messageNumberByHA[3] = i; 162 } 163 if (mask & HA_R1ATT) { 164 mb->un.varCfgMSI.messageNumberByHA[7] = i; 165 } 166 if (mask & HA_R2ATT) { 167 mb->un.varCfgMSI.messageNumberByHA[11] = i; 168 } 169 if (mask & HA_R3ATT) { 170 mb->un.varCfgMSI.messageNumberByHA[15] = i; 171 } 172 if (mask & HA_LATT) { 173 mb->un.varCfgMSI.messageNumberByHA[29] = i; 174 } 175 if (mask & HA_MBATT) { 176 mb->un.varCfgMSI.messageNumberByHA[30] = i; 177 } 178 if (mask & HA_ERATT) { 179 mb->un.varCfgMSI.messageNumberByHA[31] = i; 180 } 181 #endif /* EMLXS_BIG_ENDIAN */ 182 183 #ifdef EMLXS_LITTLE_ENDIAN 184 /* Accounts for half word swap of LE architecture */ 185 if (mask & HA_R0ATT) { 186 mb->un.varCfgMSI.messageNumberByHA[2] = i; 187 } 188 if (mask & HA_R1ATT) { 189 mb->un.varCfgMSI.messageNumberByHA[6] = i; 190 } 191 if (mask & HA_R2ATT) { 192 mb->un.varCfgMSI.messageNumberByHA[10] = i; 193 } 194 if (mask & HA_R3ATT) { 195 mb->un.varCfgMSI.messageNumberByHA[14] = i; 196 } 197 if (mask & HA_LATT) { 198 mb->un.varCfgMSI.messageNumberByHA[28] = i; 199 } 200 if (mask & HA_MBATT) { 201 mb->un.varCfgMSI.messageNumberByHA[31] = i; 202 } 203 if (mask & HA_ERATT) { 204 mb->un.varCfgMSI.messageNumberByHA[30] = i; 205 } 206 #endif /* EMLXS_LITTLE_ENDIAN */ 207 } 208 209 mb->mbxOwner = OWN_HOST; 210 211 return; 212 213 } /* emlxs_mb_config_msi() */ 214 215 216 /*ARGSUSED*/ 217 extern void 218 emlxs_mb_config_msix(emlxs_hba_t *hba, MAILBOX *mb, uint32_t *intr_map, 219 uint32_t intr_count) 220 { 221 uint32_t i; 222 uint32_t mask; 223 224 bzero((void *)mb, MAILBOX_CMD_BSIZE); 225 226 mb->mbxCommand = MBX_CONFIG_MSIX; 227 228 /* Set the default message id to zero */ 229 mb->un.varCfgMSIX.defaultPresent = 1; 230 mb->un.varCfgMSIX.defaultMessageNumber = 0; 231 232 for (i = 1; i < intr_count; i++) { 233 mask = intr_map[i]; 234 235 mb->un.varCfgMSIX.attConditions1 |= mask; 236 237 #ifdef EMLXS_BIG_ENDIAN 238 if (mask & HA_R0ATT) { 239 mb->un.varCfgMSIX.messageNumberByHA[3] = i; 240 } 241 if (mask & HA_R1ATT) { 242 mb->un.varCfgMSIX.messageNumberByHA[7] = i; 243 } 244 if (mask & HA_R2ATT) { 245 mb->un.varCfgMSIX.messageNumberByHA[11] = i; 246 } 247 if (mask & HA_R3ATT) { 248 mb->un.varCfgMSIX.messageNumberByHA[15] = i; 249 } 250 if (mask & HA_LATT) { 251 mb->un.varCfgMSIX.messageNumberByHA[29] = i; 252 } 253 if (mask & HA_MBATT) { 254 mb->un.varCfgMSIX.messageNumberByHA[30] = i; 255 } 256 if (mask & HA_ERATT) { 257 mb->un.varCfgMSIX.messageNumberByHA[31] = i; 258 } 259 #endif /* EMLXS_BIG_ENDIAN */ 260 261 #ifdef EMLXS_LITTLE_ENDIAN 262 /* Accounts for word swap of LE architecture */ 263 if (mask & HA_R0ATT) { 264 mb->un.varCfgMSIX.messageNumberByHA[0] = i; 265 } 266 if (mask & HA_R1ATT) { 267 mb->un.varCfgMSIX.messageNumberByHA[4] = i; 268 } 269 if (mask & HA_R2ATT) { 270 mb->un.varCfgMSIX.messageNumberByHA[8] = i; 271 } 272 if (mask & HA_R3ATT) { 273 mb->un.varCfgMSIX.messageNumberByHA[12] = i; 274 } 275 if (mask & HA_LATT) { 276 mb->un.varCfgMSIX.messageNumberByHA[30] = i; 277 } 278 if (mask & HA_MBATT) { 279 mb->un.varCfgMSIX.messageNumberByHA[29] = i; 280 } 281 if (mask & HA_ERATT) { 282 mb->un.varCfgMSIX.messageNumberByHA[28] = i; 283 } 284 #endif /* EMLXS_LITTLE_ENDIAN */ 285 } 286 287 mb->mbxOwner = OWN_HOST; 288 289 return; 290 291 } /* emlxs_mb_config_msix() */ 292 293 294 #endif /* MSI_SUPPORT */ 295 296 297 /*ARGSUSED*/ 298 extern void 299 emlxs_mb_reset_ring(emlxs_hba_t *hba, MAILBOX *mb, uint32_t ringno) 300 { 301 bzero((void *)mb, MAILBOX_CMD_BSIZE); 302 303 mb->mbxCommand = MBX_RESET_RING; 304 mb->un.varRstRing.ring_no = ringno; 305 mb->mbxOwner = OWN_HOST; 306 307 return; 308 309 } /* emlxs_mb_reset_ring() */ 310 311 312 313 /* 314 * emlxs_mb_dump_vpd Issue a DUMP MEMORY mailbox command 315 */ 316 /*ARGSUSED*/ 317 extern void 318 emlxs_mb_dump_vpd(emlxs_hba_t *hba, MAILBOX *mb, uint32_t offset) 319 { 320 bzero((void *)mb, MAILBOX_CMD_BSIZE); 321 322 /* 323 * Setup to dump VPD region 324 */ 325 mb->mbxCommand = MBX_DUMP_MEMORY; 326 mb->un.varDmp.cv = 1; 327 mb->un.varDmp.type = DMP_NV_PARAMS; 328 mb->un.varDmp.entry_index = offset; 329 mb->un.varDmp.region_id = DMP_VPD_REGION; 330 331 /* limited by mailbox size */ 332 mb->un.varDmp.word_cnt = DMP_VPD_DUMP_WCOUNT; 333 334 mb->un.varDmp.co = 0; 335 mb->un.varDmp.resp_offset = 0; 336 mb->mbxOwner = OWN_HOST; 337 338 } /* emlxs_mb_dump_vpd() */ 339 340 341 /*ARGSUSED*/ 342 extern void 343 emlxs_mb_dump(emlxs_hba_t *hba, MAILBOX *mb, uint32_t offset, uint32_t words) 344 { 345 bzero((void *)mb, MAILBOX_CMD_BSIZE); 346 347 mb->mbxCommand = MBX_DUMP_MEMORY; 348 mb->un.varDmp.type = DMP_MEM_REG; 349 mb->un.varDmp.word_cnt = words; 350 mb->un.varDmp.base_adr = offset; 351 352 mb->un.varDmp.co = 0; 353 mb->un.varDmp.resp_offset = 0; 354 mb->mbxOwner = OWN_HOST; 355 356 return; 357 358 } /* emlxs_mb_dump() */ 359 360 361 362 /* 363 * emlxs_mb_read_nv Issue a READ NVPARAM mailbox command 364 */ 365 /*ARGSUSED*/ 366 extern void 367 emlxs_mb_read_nv(emlxs_hba_t *hba, MAILBOX *mb) 368 { 369 bzero((void *)mb, MAILBOX_CMD_BSIZE); 370 371 mb->mbxCommand = MBX_READ_NV; 372 mb->mbxOwner = OWN_HOST; 373 } /* End emlxs_mb_read_nv */ 374 375 376 /* 377 * emlxs_mb_read_rev Issue a READ REV mailbox command 378 */ 379 /*ARGSUSED*/ 380 extern void 381 emlxs_mb_read_rev(emlxs_hba_t *hba, MAILBOX *mb, uint32_t v3) 382 { 383 bzero((void *)mb, MAILBOX_CMD_BSIZE); 384 385 mb->un.varRdRev.cv = 1; 386 387 if (v3) { 388 mb->un.varRdRev.cv3 = 1; 389 } 390 391 mb->mbxCommand = MBX_READ_REV; 392 mb->mbxOwner = OWN_HOST; 393 } /* End emlxs_mb_read_rev */ 394 395 396 /* 397 * emlxs_mb_run_biu_diag Issue a RUN_BIU_DIAG mailbox command 398 */ 399 /*ARGSUSED*/ 400 extern uint32_t 401 emlxs_mb_run_biu_diag(emlxs_hba_t *hba, MAILBOX *mb, uint64_t out, 402 uint64_t in) 403 { 404 bzero((void *)mb, MAILBOX_CMD_BSIZE); 405 406 mb->mbxCommand = MBX_RUN_BIU_DIAG64; 407 mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize = MEM_ELSBUF_SIZE; 408 mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh = putPaddrHigh(out); 409 mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow = putPaddrLow(out); 410 mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize = MEM_ELSBUF_SIZE; 411 mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh = putPaddrHigh(in); 412 mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = putPaddrLow(in); 413 mb->mbxOwner = OWN_HOST; 414 415 return (0); 416 } /* End emlxs_mb_run_biu_diag */ 417 418 419 /* 420 * emlxs_mb_read_la Issue a READ LA mailbox command 421 */ 422 extern uint32_t 423 emlxs_mb_read_la(emlxs_hba_t *hba, MAILBOX *mb) 424 { 425 MATCHMAP *mp; 426 427 bzero((void *)mb, MAILBOX_CMD_BSIZE); 428 429 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) { 430 mb->mbxCommand = MBX_READ_LA64; 431 432 return (1); 433 } 434 435 mb->mbxCommand = MBX_READ_LA64; 436 mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128; 437 mb->un.varReadLA.un.lilpBde64.addrHigh = putPaddrHigh(mp->phys); 438 mb->un.varReadLA.un.lilpBde64.addrLow = putPaddrLow(mp->phys); 439 mb->mbxOwner = OWN_HOST; 440 441 /* 442 * save address for completion 443 */ 444 ((MAILBOXQ *)mb)->bp = (uint8_t *)mp; 445 446 return (0); 447 448 } /* emlxs_mb_read_la() */ 449 450 451 /* 452 * emlxs_mb_clear_la Issue a CLEAR LA mailbox command 453 */ 454 extern void 455 emlxs_mb_clear_la(emlxs_hba_t *hba, MAILBOX *mb) 456 { 457 #ifdef FC_RPI_CHECK 458 emlxs_rpi_check(hba); 459 #endif /* FC_RPI_CHECK */ 460 461 bzero((void *)mb, MAILBOX_CMD_BSIZE); 462 463 mb->un.varClearLA.eventTag = hba->link_event_tag; 464 mb->mbxCommand = MBX_CLEAR_LA; 465 mb->mbxOwner = OWN_HOST; 466 467 return; 468 469 } /* End emlxs_mb_clear_la */ 470 471 472 /* 473 * emlxs_mb_read_status Issue a READ STATUS mailbox command 474 */ 475 /*ARGSUSED*/ 476 extern void 477 emlxs_mb_read_status(emlxs_hba_t *hba, MAILBOX *mb) 478 { 479 bzero((void *)mb, MAILBOX_CMD_BSIZE); 480 481 mb->mbxCommand = MBX_READ_STATUS; 482 mb->mbxOwner = OWN_HOST; 483 } /* End fc_read_status */ 484 485 /* 486 * emlxs_mb_read_lnk_stat Issue a LINK STATUS mailbox command 487 */ 488 /*ARGSUSED*/ 489 extern void 490 emlxs_mb_read_lnk_stat(emlxs_hba_t *hba, MAILBOX *mb) 491 { 492 bzero((void *)mb, MAILBOX_CMD_BSIZE); 493 494 mb->mbxCommand = MBX_READ_LNK_STAT; 495 mb->mbxOwner = OWN_HOST; 496 } /* End emlxs_mb_read_lnk_stat */ 497 498 499 /* 500 * emlxs_mb_write_nv Issue a WRITE NVPARAM mailbox command 501 */ 502 static void 503 emlxs_emb_mb_write_nv(emlxs_hba_t *hba, MAILBOX *mb) 504 { 505 int32_t i; 506 emlxs_config_t *cfg = &CFG; 507 508 bzero((void *)mb, MAILBOX_CMD_BSIZE); 509 510 bcopy((void *)&hba->wwnn, 511 (void *)mb->un.varWTnvp.nodename, sizeof (NAME_TYPE)); 512 513 bcopy((void *)&hba->wwpn, 514 (void *)mb->un.varWTnvp.portname, sizeof (NAME_TYPE)); 515 516 mb->un.varWTnvp.pref_DID = 0; 517 mb->un.varWTnvp.hardAL_PA = (uint8_t)cfg[CFG_ASSIGN_ALPA].current; 518 mb->un.varWTnvp.rsvd1[0] = 0xffffffff; 519 mb->un.varWTnvp.rsvd1[1] = 0xffffffff; 520 mb->un.varWTnvp.rsvd1[2] = 0xffffffff; 521 for (i = 0; i < 21; i++) { 522 mb->un.varWTnvp.rsvd3[i] = 0xffffffff; 523 } 524 525 mb->mbxCommand = MBX_WRITE_NV; 526 mb->mbxOwner = OWN_HOST; 527 } /* End emlxs_mb_write_nv */ 528 529 530 /* 531 * emlxs_mb_part_slim Issue a PARTITION SLIM mailbox command 532 */ 533 static void 534 emlxs_mb_part_slim(emlxs_hba_t *hba, MAILBOX *mb, uint32_t hbainit) 535 { 536 bzero((void *)mb, MAILBOX_CMD_BSIZE); 537 538 539 mb->un.varSlim.numRing = hba->ring_count; 540 mb->un.varSlim.hbainit = hbainit; 541 mb->mbxCommand = MBX_PART_SLIM; 542 mb->mbxOwner = OWN_HOST; 543 } /* End emlxs_mb_part_slim */ 544 545 546 /* 547 * emlxs_mb_config_ring Issue a CONFIG RING mailbox command 548 */ 549 extern void 550 emlxs_mb_config_ring(emlxs_hba_t *hba, int32_t ring, MAILBOX *mb) 551 { 552 int32_t i; 553 int32_t j; 554 555 bzero((void *)mb, MAILBOX_CMD_BSIZE); 556 557 j = 0; 558 for (i = 0; i < ring; i++) { 559 j += hba->ring_masks[i]; 560 } 561 562 for (i = 0; i < hba->ring_masks[ring]; i++) { 563 if ((j + i) >= 6) { 564 break; 565 } 566 567 mb->un.varCfgRing.rrRegs[i].rval = hba->ring_rval[j + i]; 568 mb->un.varCfgRing.rrRegs[i].rmask = hba->ring_rmask[j + i]; 569 570 mb->un.varCfgRing.rrRegs[i].tval = hba->ring_tval[j + i]; 571 mb->un.varCfgRing.rrRegs[i].tmask = hba->ring_tmask[j + i]; 572 } 573 574 mb->un.varCfgRing.ring = ring; 575 mb->un.varCfgRing.profile = 0; 576 mb->un.varCfgRing.maxOrigXchg = 0; 577 mb->un.varCfgRing.maxRespXchg = 0; 578 mb->un.varCfgRing.recvNotify = 1; 579 mb->un.varCfgRing.numMask = hba->ring_masks[ring]; 580 mb->mbxCommand = MBX_CONFIG_RING; 581 mb->mbxOwner = OWN_HOST; 582 583 return; 584 585 } /* End emlxs_mb_config_ring */ 586 587 588 /* 589 * emlxs_mb_config_link Issue a CONFIG LINK mailbox command 590 */ 591 extern void 592 emlxs_mb_config_link(emlxs_hba_t *hba, MAILBOX *mb) 593 { 594 emlxs_port_t *port = &PPORT; 595 emlxs_config_t *cfg = &CFG; 596 597 bzero((void *)mb, MAILBOX_CMD_BSIZE); 598 599 /* 600 * NEW_FEATURE SLI-2, Coalescing Response Feature. 601 */ 602 if (cfg[CFG_CR_DELAY].current) { 603 mb->un.varCfgLnk.cr = 1; 604 mb->un.varCfgLnk.ci = 1; 605 mb->un.varCfgLnk.cr_delay = cfg[CFG_CR_DELAY].current; 606 mb->un.varCfgLnk.cr_count = cfg[CFG_CR_COUNT].current; 607 } 608 609 if (cfg[CFG_ACK0].current) 610 mb->un.varCfgLnk.ack0_enable = 1; 611 612 mb->un.varCfgLnk.myId = port->did; 613 mb->un.varCfgLnk.edtov = hba->fc_edtov; 614 mb->un.varCfgLnk.arbtov = hba->fc_arbtov; 615 mb->un.varCfgLnk.ratov = hba->fc_ratov; 616 mb->un.varCfgLnk.rttov = hba->fc_rttov; 617 mb->un.varCfgLnk.altov = hba->fc_altov; 618 mb->un.varCfgLnk.crtov = hba->fc_crtov; 619 mb->un.varCfgLnk.citov = hba->fc_citov; 620 mb->mbxCommand = MBX_CONFIG_LINK; 621 mb->mbxOwner = OWN_HOST; 622 623 return; 624 625 } /* emlxs_mb_config_link() */ 626 627 628 /* 629 * emlxs_mb_init_link Issue an INIT LINK mailbox command 630 */ 631 extern void 632 emlxs_mb_init_link(emlxs_hba_t *hba, MAILBOX *mb, uint32_t topology, 633 uint32_t linkspeed) 634 { 635 emlxs_vpd_t *vpd = &VPD; 636 emlxs_config_t *cfg = &CFG; 637 638 bzero((void *)mb, MAILBOX_CMD_BSIZE); 639 640 switch (topology) { 641 case FLAGS_LOCAL_LB: 642 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP; 643 mb->un.varInitLnk.link_flags |= FLAGS_LOCAL_LB; 644 break; 645 case FLAGS_TOPOLOGY_MODE_LOOP_PT: 646 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP; 647 mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER; 648 break; 649 case FLAGS_TOPOLOGY_MODE_PT_PT: 650 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT; 651 break; 652 case FLAGS_TOPOLOGY_MODE_LOOP: 653 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP; 654 break; 655 case FLAGS_TOPOLOGY_MODE_PT_LOOP: 656 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT; 657 mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER; 658 break; 659 } 660 661 if (cfg[CFG_LILP_ENABLE].current == 0) { 662 /* Disable LIRP/LILP support */ 663 mb->un.varInitLnk.link_flags |= FLAGS_LIRP_LILP; 664 } 665 666 /* 667 * Setting up the link speed 668 */ 669 switch (linkspeed) { 670 case 0: 671 break; 672 673 case 1: 674 if (!(vpd->link_speed & LMT_1GB_CAPABLE)) { 675 linkspeed = 0; 676 } 677 break; 678 679 case 2: 680 if (!(vpd->link_speed & LMT_2GB_CAPABLE)) { 681 linkspeed = 0; 682 } 683 break; 684 685 case 4: 686 if (!(vpd->link_speed & LMT_4GB_CAPABLE)) { 687 linkspeed = 0; 688 } 689 break; 690 691 case 8: 692 if (!(vpd->link_speed & LMT_8GB_CAPABLE)) { 693 linkspeed = 0; 694 } 695 break; 696 697 case 10: 698 if (!(vpd->link_speed & LMT_10GB_CAPABLE)) { 699 linkspeed = 0; 700 } 701 break; 702 703 default: 704 linkspeed = 0; 705 break; 706 707 } 708 709 if ((linkspeed > 0) && (vpd->feaLevelHigh >= 0x02)) { 710 mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; 711 mb->un.varInitLnk.link_speed = linkspeed; 712 } 713 714 mb->un.varInitLnk.link_flags |= FLAGS_PREABORT_RETURN; 715 716 mb->un.varInitLnk.fabric_AL_PA = 717 (uint8_t)cfg[CFG_ASSIGN_ALPA].current; 718 mb->mbxCommand = (volatile uint8_t) MBX_INIT_LINK; 719 mb->mbxOwner = OWN_HOST; 720 721 722 return; 723 724 } /* emlxs_mb_init_link() */ 725 726 727 /* 728 * emlxs_mb_down_link Issue a DOWN LINK mailbox command 729 */ 730 /*ARGSUSED*/ 731 extern void 732 emlxs_mb_down_link(emlxs_hba_t *hba, MAILBOX *mb) 733 { 734 bzero((void *)mb, MAILBOX_CMD_BSIZE); 735 736 mb->mbxCommand = MBX_DOWN_LINK; 737 mb->mbxOwner = OWN_HOST; 738 739 return; 740 741 } /* emlxs_mb_down_link() */ 742 743 744 /* 745 * emlxs_mb_read_sparam Issue a READ SPARAM mailbox command 746 */ 747 extern uint32_t 748 emlxs_mb_read_sparam(emlxs_hba_t *hba, MAILBOX *mb) 749 { 750 MATCHMAP *mp; 751 752 bzero((void *)mb, MAILBOX_CMD_BSIZE); 753 754 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) { 755 mb->mbxCommand = MBX_READ_SPARM64; 756 757 return (1); 758 } 759 760 mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM); 761 mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys); 762 mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys); 763 mb->mbxCommand = MBX_READ_SPARM64; 764 mb->mbxOwner = OWN_HOST; 765 766 /* 767 * save address for completion 768 */ 769 ((MAILBOXQ *)mb)->bp = (uint8_t *)mp; 770 771 return (0); 772 773 } /* emlxs_mb_read_sparam() */ 774 775 776 /* 777 * emlxs_mb_read_rpi Issue a READ RPI mailbox command 778 */ 779 /*ARGSUSED*/ 780 extern uint32_t 781 emlxs_mb_read_rpi(emlxs_hba_t *hba, uint32_t rpi, MAILBOX *mb, 782 uint32_t flag) 783 { 784 bzero((void *)mb, MAILBOX_CMD_BSIZE); 785 786 /* 787 * Set flag to issue action on cmpl 788 */ 789 mb->un.varWords[30] = flag; 790 mb->un.varRdRPI.reqRpi = (volatile uint16_t) rpi; 791 mb->mbxCommand = MBX_READ_RPI64; 792 mb->mbxOwner = OWN_HOST; 793 794 return (0); 795 } /* End emlxs_mb_read_rpi */ 796 797 798 /* 799 * emlxs_mb_read_xri Issue a READ XRI mailbox command 800 */ 801 /*ARGSUSED*/ 802 extern uint32_t 803 emlxs_mb_read_xri(emlxs_hba_t *hba, uint32_t xri, MAILBOX *mb, 804 uint32_t flag) 805 { 806 bzero((void *)mb, MAILBOX_CMD_BSIZE); 807 808 /* 809 * Set flag to issue action on cmpl 810 */ 811 mb->un.varWords[30] = flag; 812 mb->un.varRdXRI.reqXri = (volatile uint16_t)xri; 813 mb->mbxCommand = MBX_READ_XRI; 814 mb->mbxOwner = OWN_HOST; 815 816 return (0); 817 } /* End emlxs_mb_read_xri */ 818 819 820 /*ARGSUSED*/ 821 extern int32_t 822 emlxs_mb_check_sparm(emlxs_hba_t *hba, SERV_PARM *nsp) 823 { 824 uint32_t nsp_value; 825 uint32_t *iptr; 826 827 if (nsp->cmn.fPort) { 828 return (0); 829 } 830 831 /* Validate the service parameters */ 832 iptr = (uint32_t *)&nsp->portName; 833 if (iptr[0] == 0 && iptr[1] == 0) { 834 return (1); 835 } 836 837 iptr = (uint32_t *)&nsp->nodeName; 838 if (iptr[0] == 0 && iptr[1] == 0) { 839 return (2); 840 } 841 842 if (nsp->cls2.classValid) { 843 nsp_value = 844 ((nsp->cls2.rcvDataSizeMsb & 0x0f) << 8) | nsp->cls2. 845 rcvDataSizeLsb; 846 847 /* If the receive data length is zero then set it to */ 848 /* the CSP value */ 849 if (!nsp_value) { 850 nsp->cls2.rcvDataSizeMsb = nsp->cmn.bbRcvSizeMsb; 851 nsp->cls2.rcvDataSizeLsb = nsp->cmn.bbRcvSizeLsb; 852 return (0); 853 } 854 } 855 856 if (nsp->cls3.classValid) { 857 nsp_value = 858 ((nsp->cls3.rcvDataSizeMsb & 0x0f) << 8) | nsp->cls3. 859 rcvDataSizeLsb; 860 861 /* If the receive data length is zero then set it to */ 862 /* the CSP value */ 863 if (!nsp_value) { 864 nsp->cls3.rcvDataSizeMsb = nsp->cmn.bbRcvSizeMsb; 865 nsp->cls3.rcvDataSizeLsb = nsp->cmn.bbRcvSizeLsb; 866 return (0); 867 } 868 } 869 870 return (0); 871 872 } /* emlxs_mb_check_sparm() */ 873 874 875 /* 876 * emlxs_mb_reg_did Issue a REG_LOGIN mailbox command 877 */ 878 extern uint32_t 879 emlxs_mb_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param, 880 emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq) 881 { 882 emlxs_hba_t *hba = HBA; 883 MATCHMAP *mp; 884 MAILBOXQ *mbq; 885 MAILBOX *mb; 886 uint32_t rval; 887 888 /* Check for invalid node ids to register */ 889 if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) { 890 return (1); 891 } 892 893 if (did & 0xff000000) { 894 return (1); 895 } 896 897 if ((rval = emlxs_mb_check_sparm(hba, param))) { 898 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 899 "Invalid service parameters. did=%06x rval=%d", did, 900 rval); 901 902 return (1); 903 } 904 905 /* Check if the node limit has been reached */ 906 if (port->node_count >= hba->max_nodes) { 907 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 908 "Limit reached. did=%06x count=%d", did, 909 port->node_count); 910 911 return (1); 912 } 913 914 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) { 915 return (1); 916 } 917 918 /* Build login request */ 919 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF | MEM_PRI)) == 0) { 920 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 921 return (1); 922 } 923 924 bcopy((void *)param, (void *)mp->virt, sizeof (SERV_PARM)); 925 926 mb = (MAILBOX *)mbq->mbox; 927 mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM); 928 mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys); 929 mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys); 930 mb->un.varRegLogin.rpi = 0; 931 mb->un.varRegLogin.did = did; 932 mb->un.varWords[30] = 0; /* flags */ 933 mb->mbxCommand = MBX_REG_LOGIN64; 934 mb->mbxOwner = OWN_HOST; 935 936 #ifdef SLI3_SUPPORT 937 mb->un.varRegLogin.vpi = port->vpi; 938 #endif /* SLI3_SUPPORT */ 939 940 mbq->sbp = (uint8_t *)sbp; 941 mbq->ubp = (uint8_t *)ubp; 942 mbq->iocbq = (uint8_t *)iocbq; 943 mbq->bp = (uint8_t *)mp; 944 945 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) { 946 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 947 } 948 949 return (0); 950 951 } /* emlxs_mb_reg_did() */ 952 953 /* 954 * emlxs_mb_unreg_rpi Issue a UNREG_LOGIN mailbox command 955 */ 956 extern uint32_t 957 emlxs_mb_unreg_rpi(emlxs_port_t *port, uint32_t rpi, emlxs_buf_t *sbp, 958 fc_unsol_buf_t *ubp, IOCBQ *iocbq) 959 { 960 emlxs_hba_t *hba = HBA; 961 MAILBOXQ *mbq; 962 MAILBOX *mb; 963 NODELIST *ndlp; 964 965 if (rpi != 0xffff) { 966 /* Make sure the node does already exist */ 967 ndlp = emlxs_node_find_rpi(port, rpi); 968 969 970 if (ndlp) { 971 /* 972 * If we just unregistered the host node then 973 * clear the host DID 974 */ 975 if (ndlp->nlp_DID == port->did) { 976 port->did = 0; 977 } 978 979 /* remove it */ 980 emlxs_node_rm(port, ndlp); 981 982 } else { 983 return (1); 984 } 985 } else { /* Unreg all */ 986 987 emlxs_node_destroy_all(port); 988 } 989 990 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) { 991 return (1); 992 } 993 994 mb = (MAILBOX *)mbq->mbox; 995 mb->un.varUnregLogin.rpi = (uint16_t)rpi; 996 997 #ifdef SLI3_SUPPORT 998 mb->un.varUnregLogin.vpi = port->vpi; 999 #endif /* SLI3_SUPPORT */ 1000 1001 mb->mbxCommand = MBX_UNREG_LOGIN; 1002 mb->mbxOwner = OWN_HOST; 1003 mbq->sbp = (uint8_t *)sbp; 1004 mbq->ubp = (uint8_t *)ubp; 1005 mbq->iocbq = (uint8_t *)iocbq; 1006 1007 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) { 1008 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 1009 } 1010 1011 return (0); 1012 } /* emlxs_mb_unreg_rpi() */ 1013 1014 /* 1015 * emlxs_mb_unreg_did Issue a UNREG_DID mailbox command 1016 */ 1017 extern uint32_t 1018 emlxs_mb_unreg_did(emlxs_port_t *port, uint32_t did, emlxs_buf_t *sbp, 1019 fc_unsol_buf_t *ubp, IOCBQ *iocbq) 1020 { 1021 emlxs_hba_t *hba = HBA; 1022 NODELIST *ndlp; 1023 MAILBOXQ *mbq; 1024 MAILBOX *mb; 1025 1026 /* 1027 * Unregister all default RPIs if did == 0xffffffff 1028 */ 1029 if (did != 0xffffffff) { 1030 /* Check for base node */ 1031 if (did == Bcast_DID) { 1032 /* just flush base node */ 1033 (void) emlxs_tx_node_flush(port, &port->node_base, 1034 0, 0, 0); 1035 (void) emlxs_chipq_node_flush(port, 0, 1036 &port->node_base, 0); 1037 1038 /* Return now */ 1039 return (1); 1040 } 1041 1042 1043 /* 1044 * A zero DID means that we are trying to unreg the host node 1045 * after a link bounce 1046 */ 1047 1048 /* 1049 * If the prev_did == 0 then the adapter has been reset and 1050 * there is no need in unregistering 1051 */ 1052 1053 /* 1054 * If the prev_did != 0 then we can look for the hosts 1055 * last known DID node 1056 */ 1057 1058 if (did == 0) { 1059 if (port->prev_did == 0) { 1060 return (1); 1061 } 1062 1063 did = port->prev_did; 1064 } 1065 1066 /* Make sure the node does already exist */ 1067 ndlp = emlxs_node_find_did(port, did); 1068 1069 1070 if (ndlp) { 1071 /* remove it */ 1072 emlxs_node_rm(port, ndlp); 1073 1074 /* 1075 * If we just unregistered the host node then 1076 * clear the host DID 1077 */ 1078 if (did == port->did) { 1079 port->did = 0; 1080 } 1081 1082 } else { 1083 return (1); 1084 } 1085 } 1086 1087 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) { 1088 return (1); 1089 } 1090 1091 mb = (MAILBOX *)mbq->mbox; 1092 mb->un.varUnregDID.did = did; 1093 1094 #ifdef SLI3_SUPPORT 1095 mb->un.varUnregDID.vpi = port->vpi; 1096 #endif /* SLI3_SUPPORT */ 1097 1098 mb->mbxCommand = MBX_UNREG_D_ID; 1099 mb->mbxOwner = OWN_HOST; 1100 mbq->sbp = (uint8_t *)sbp; 1101 mbq->ubp = (uint8_t *)ubp; 1102 mbq->iocbq = (uint8_t *)iocbq; 1103 1104 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) { 1105 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 1106 } 1107 1108 return (0); 1109 1110 } /* End emlxs_mb_unreg_did */ 1111 1112 1113 /* 1114 * emlxs_mb_set_mask Issue a SET MASK mailbox command 1115 */ 1116 /*ARGSUSED*/ 1117 static void 1118 emlxs_mb_set_mask(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mask, 1119 uint32_t ringno) 1120 { 1121 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1122 1123 mb->un.varWords[0] = 0x11223344; /* set passwd */ 1124 mb->un.varWords[1] = mask; /* set mask */ 1125 mb->un.varWords[2] = ringno; /* set ringno */ 1126 mb->mbxCommand = MBX_SET_MASK; 1127 mb->mbxOwner = OWN_HOST; 1128 } /* End emlxs_mb_set_mask */ 1129 1130 1131 /* 1132 * emlxs_mb_set_debug Issue a special debug mailbox command 1133 */ 1134 /*ARGSUSED*/ 1135 static void 1136 emlxs_mb_set_debug(emlxs_hba_t *hba, MAILBOX *mb, uint32_t word0, 1137 uint32_t word1, uint32_t word2) 1138 { 1139 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1140 1141 mb->un.varWords[0] = word0; 1142 mb->un.varWords[1] = word1; 1143 mb->un.varWords[2] = word2; 1144 mb->mbxCommand = MBX_SET_DEBUG; 1145 mb->mbxOwner = OWN_HOST; 1146 } /* End emlxs_mb_set_debug */ 1147 1148 1149 /* 1150 * emlxs_mb_set_var Issue a special debug mbox command to write slim 1151 */ 1152 /*ARGSUSED*/ 1153 extern void 1154 emlxs_mb_set_var(emlxs_hba_t *hba, MAILBOX *mb, uint32_t addr, 1155 uint32_t value) 1156 { 1157 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1158 1159 /* addr = 0x090597 is AUTO ABTS disable for ELS commands */ 1160 /* addr = 0x052198 is DELAYED ABTS enable for ELS commands */ 1161 /* addr = 0x100506 is for setting PCI MAX READ value */ 1162 1163 /* 1164 * Always turn on DELAYED ABTS for ELS timeouts 1165 */ 1166 if ((addr == 0x052198) && (value == 0)) { 1167 value = 1; 1168 } 1169 1170 mb->un.varWords[0] = addr; 1171 mb->un.varWords[1] = value; 1172 mb->mbxCommand = MBX_SET_VARIABLE; 1173 mb->mbxOwner = OWN_HOST; 1174 } /* End emlxs_mb_set_var */ 1175 1176 1177 /* 1178 * Disable Traffic Cop 1179 */ 1180 /*ARGSUSED*/ 1181 extern void 1182 emlxs_disable_tc(emlxs_hba_t *hba, MAILBOX *mb) 1183 { 1184 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1185 1186 mb->un.varWords[0] = 0x50797; 1187 mb->un.varWords[1] = 0; 1188 mb->un.varWords[2] = 0xfffffffe; 1189 mb->mbxCommand = MBX_SET_VARIABLE; 1190 mb->mbxOwner = OWN_HOST; 1191 1192 } /* End emlxs_disable_tc */ 1193 1194 1195 1196 #ifdef SLI3_SUPPORT 1197 extern void 1198 emlxs_mb_config_hbq(emlxs_hba_t *hba, MAILBOX *mb, int hbq_id) 1199 { 1200 HBQ_INIT_t *hbq; 1201 int i; 1202 1203 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1204 1205 hbq = &hba->hbq_table[hbq_id]; 1206 1207 mb->un.varCfgHbq.hbqId = hbq_id; 1208 mb->un.varCfgHbq.numEntries = hbq->HBQ_numEntries; 1209 mb->un.varCfgHbq.recvNotify = hbq->HBQ_recvNotify; 1210 mb->un.varCfgHbq.numMask = hbq->HBQ_num_mask; 1211 mb->un.varCfgHbq.profile = hbq->HBQ_profile; 1212 mb->un.varCfgHbq.ringMask = hbq->HBQ_ringMask; 1213 mb->un.varCfgHbq.headerLen = hbq->HBQ_headerLen; 1214 mb->un.varCfgHbq.logEntry = hbq->HBQ_logEntry; 1215 mb->un.varCfgHbq.hbqaddrLow = putPaddrLow(hbq->HBQ_host_buf.phys); 1216 mb->un.varCfgHbq.hbqaddrHigh = putPaddrHigh(hbq->HBQ_host_buf.phys); 1217 mb->mbxCommand = MBX_CONFIG_HBQ; 1218 mb->mbxOwner = OWN_HOST; 1219 1220 /* Copy info for profiles 2,3,5. Other profiles this area is reserved */ 1221 if ((hbq->HBQ_profile == 2) || (hbq->HBQ_profile == 3) || 1222 (hbq->HBQ_profile == 5)) { 1223 bcopy(&hbq->profiles.allprofiles, 1224 &mb->un.varCfgHbq.profiles.allprofiles, 1225 sizeof (hbq->profiles)); 1226 } 1227 1228 /* Return if no rctl / type masks for this HBQ */ 1229 if (!hbq->HBQ_num_mask) { 1230 return; 1231 } 1232 1233 /* Otherwise we setup specific rctl / type masks for this HBQ */ 1234 for (i = 0; i < hbq->HBQ_num_mask; i++) { 1235 mb->un.varCfgHbq.hbqMasks[i].tmatch = 1236 hbq->HBQ_Masks[i].tmatch; 1237 mb->un.varCfgHbq.hbqMasks[i].tmask = hbq->HBQ_Masks[i].tmask; 1238 mb->un.varCfgHbq.hbqMasks[i].rctlmatch = 1239 hbq->HBQ_Masks[i].rctlmatch; 1240 mb->un.varCfgHbq.hbqMasks[i].rctlmask = 1241 hbq->HBQ_Masks[i].rctlmask; 1242 } 1243 1244 return; 1245 1246 } /* emlxs_mb_config_hbq() */ 1247 1248 #endif /* SLI3_SUPPORT */ 1249 1250 1251 extern uint32_t 1252 emlxs_mb_reg_vpi(emlxs_port_t *port) 1253 { 1254 emlxs_hba_t *hba = HBA; 1255 MAILBOXQ *mbq; 1256 MAILBOX *mb; 1257 1258 if (!(hba->flag & FC_NPIV_ENABLED)) { 1259 return (0); 1260 } 1261 1262 mutex_enter(&EMLXS_PORT_LOCK); 1263 1264 /* Can't reg vpi until ClearLA is sent */ 1265 if (hba->state != FC_READY) { 1266 mutex_exit(&EMLXS_PORT_LOCK); 1267 1268 return (1); 1269 } 1270 1271 /* Must have port id */ 1272 if (!port->did) { 1273 mutex_exit(&EMLXS_PORT_LOCK); 1274 1275 return (1); 1276 } 1277 1278 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) { 1279 mutex_exit(&EMLXS_PORT_LOCK); 1280 1281 return (1); 1282 } 1283 1284 port->flag |= EMLXS_PORT_REGISTERED; 1285 1286 mutex_exit(&EMLXS_PORT_LOCK); 1287 1288 mb = (MAILBOX *)mbq->mbox; 1289 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1290 mb->un.varRegVpi.vpi = port->vpi; 1291 mb->un.varRegVpi.sid = port->did; 1292 mb->mbxCommand = MBX_REG_VPI; 1293 mb->mbxOwner = OWN_HOST; 1294 1295 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) { 1296 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 1297 } 1298 1299 return (0); 1300 1301 } /* emlxs_mb_reg_vpi() */ 1302 1303 1304 extern uint32_t 1305 emlxs_mb_unreg_vpi(emlxs_port_t *port) 1306 { 1307 emlxs_hba_t *hba = HBA; 1308 MAILBOXQ *mbq; 1309 MAILBOX *mb; 1310 1311 mutex_enter(&EMLXS_PORT_LOCK); 1312 1313 if (!(port->flag & EMLXS_PORT_REGISTERED)) { 1314 mutex_exit(&EMLXS_PORT_LOCK); 1315 1316 return (0); 1317 } 1318 1319 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) { 1320 mutex_exit(&EMLXS_PORT_LOCK); 1321 1322 return (1); 1323 } 1324 1325 port->flag &= ~EMLXS_PORT_REGISTERED; 1326 1327 mutex_exit(&EMLXS_PORT_LOCK); 1328 1329 mb = (MAILBOX *)mbq->mbox; 1330 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1331 mb->un.varUnregVpi.vpi = port->vpi; 1332 mb->mbxCommand = MBX_UNREG_VPI; 1333 mb->mbxOwner = OWN_HOST; 1334 1335 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) { 1336 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 1337 } 1338 1339 return (0); 1340 1341 } /* emlxs_mb_unreg_vpi() */ 1342 1343 1344 /* 1345 * emlxs_mb_config_farp Issue a CONFIG FARP mailbox command 1346 */ 1347 extern void 1348 emlxs_mb_config_farp(emlxs_hba_t *hba, MAILBOX *mb) 1349 { 1350 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1351 1352 bcopy((uint8_t *)&hba->wwpn, 1353 (uint8_t *)&mb->un.varCfgFarp.portname, sizeof (NAME_TYPE)); 1354 1355 bcopy((uint8_t *)&hba->wwpn, 1356 (uint8_t *)&mb->un.varCfgFarp.nodename, sizeof (NAME_TYPE)); 1357 1358 mb->un.varCfgFarp.filterEnable = 1; 1359 mb->un.varCfgFarp.portName = 1; 1360 mb->un.varCfgFarp.nodeName = 1; 1361 mb->mbxCommand = MBX_CONFIG_FARP; 1362 mb->mbxOwner = OWN_HOST; 1363 } /* emlxs_mb_config_farp() */ 1364 1365 1366 /* 1367 * emlxs_mb_read_nv Issue a READ CONFIG mailbox command 1368 */ 1369 /*ARGSUSED*/ 1370 extern void 1371 emlxs_mb_read_config(emlxs_hba_t *hba, MAILBOX *mb) 1372 { 1373 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1374 1375 mb->mbxCommand = MBX_READ_CONFIG; 1376 mb->mbxOwner = OWN_HOST; 1377 } /* emlxs_mb_read_config() */ 1378 1379 1380 1381 /* 1382 * NAME: emlxs_mb_put 1383 * 1384 * FUNCTION: put mailbox cmd onto the mailbox queue. 1385 * 1386 * EXECUTION ENVIRONMENT: process and interrupt level. 1387 * 1388 * NOTES: 1389 * 1390 * CALLED FROM: emlxs_sli_issue_mbox_cmd 1391 * 1392 * INPUT: hba - pointer to the device info area 1393 * mbp - pointer to mailbox queue entry of mailbox cmd 1394 * 1395 * RETURNS: NULL - command queued 1396 */ 1397 extern void 1398 emlxs_mb_put(emlxs_hba_t *hba, MAILBOXQ *mbq) 1399 { 1400 1401 mutex_enter(&EMLXS_MBOX_LOCK); 1402 1403 if (hba->mbox_queue.q_first) { 1404 1405 /* 1406 * queue command to end of list 1407 */ 1408 ((MAILBOXQ *)hba->mbox_queue.q_last)->next = mbq; 1409 hba->mbox_queue.q_last = (uint8_t *)mbq; 1410 hba->mbox_queue.q_cnt++; 1411 } else { 1412 1413 /* 1414 * add command to empty list 1415 */ 1416 hba->mbox_queue.q_first = (uint8_t *)mbq; 1417 hba->mbox_queue.q_last = (uint8_t *)mbq; 1418 hba->mbox_queue.q_cnt = 1; 1419 } 1420 1421 mbq->next = NULL; 1422 1423 mutex_exit(&EMLXS_MBOX_LOCK); 1424 } /* emlxs_mb_put() */ 1425 1426 1427 /* 1428 * NAME: emlxs_mb_get 1429 * 1430 * FUNCTION: get a mailbox command from mailbox command queue 1431 * 1432 * EXECUTION ENVIRONMENT: interrupt level. 1433 * 1434 * NOTES: 1435 * 1436 * CALLED FROM: emlxs_handle_mb_event 1437 * 1438 * INPUT: hba - pointer to the device info area 1439 * 1440 * RETURNS: NULL - no match found mb pointer - pointer to a mailbox command 1441 */ 1442 extern MAILBOXQ * 1443 emlxs_mb_get(emlxs_hba_t *hba) 1444 { 1445 MAILBOXQ *p_first = NULL; 1446 1447 mutex_enter(&EMLXS_MBOX_LOCK); 1448 1449 if (hba->mbox_queue.q_first) { 1450 p_first = (MAILBOXQ *)hba->mbox_queue.q_first; 1451 hba->mbox_queue.q_first = (uint8_t *)p_first->next; 1452 1453 if (hba->mbox_queue.q_first == NULL) { 1454 hba->mbox_queue.q_last = NULL; 1455 hba->mbox_queue.q_cnt = 0; 1456 } else { 1457 hba->mbox_queue.q_cnt--; 1458 } 1459 1460 p_first->next = NULL; 1461 } 1462 1463 mutex_exit(&EMLXS_MBOX_LOCK); 1464 1465 return (p_first); 1466 1467 } /* emlxs_mb_get() */ 1468 1469 1470 1471 /* EMLXS_PORT_LOCK must be held when calling this */ 1472 void 1473 emlxs_mb_init(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t flag, uint32_t tmo) 1474 { 1475 #ifdef FMA_SUPPORT 1476 emlxs_port_t *port = &PPORT; 1477 #endif /* FMA_SUPPORT */ 1478 MATCHMAP *mp; 1479 1480 HBASTATS.MboxIssued++; 1481 hba->mbox_queue_flag = flag; 1482 1483 /* Set the Mailbox timer */ 1484 hba->mbox_timer = hba->timer_tics + tmo; 1485 1486 /* Initialize mailbox */ 1487 mbq->flag &= MBQ_INIT_MASK; 1488 hba->mbox_mbqflag = mbq->flag; 1489 1490 mbq->next = 0; 1491 1492 mutex_enter(&EMLXS_MBOX_LOCK); 1493 if (flag == MBX_NOWAIT) { 1494 hba->mbox_mbq = 0; 1495 } else { 1496 hba->mbox_mbq = (uint8_t *)mbq; 1497 } 1498 mutex_exit(&EMLXS_MBOX_LOCK); 1499 1500 if (mbq->bp) { 1501 mp = (MATCHMAP *) mbq->bp; 1502 emlxs_mpdata_sync(mp->dma_handle, 0, mp->size, 1503 DDI_DMA_SYNC_FORDEV); 1504 1505 hba->mbox_bp = mbq->bp; 1506 mbq->bp = 0; 1507 } 1508 1509 if (mbq->sbp) { 1510 hba->mbox_sbp = mbq->sbp; 1511 mbq->sbp = 0; 1512 } 1513 1514 if (mbq->ubp) { 1515 hba->mbox_ubp = mbq->ubp; 1516 mbq->ubp = 0; 1517 } 1518 1519 if (mbq->iocbq) { 1520 hba->mbox_iocbq = mbq->iocbq; 1521 mbq->iocbq = 0; 1522 } 1523 #ifdef MBOX_EXT_SUPPORT 1524 if (mbq->extbuf && mbq->extsize) { 1525 hba->mbox_ext = mbq->extbuf; 1526 hba->mbox_ext_size = mbq->extsize; 1527 } 1528 #endif /* MBOX_EXT_SUPPORT */ 1529 1530 return; 1531 1532 } /* emlxs_mb_init() */ 1533 1534 1535 extern void 1536 emlxs_mb_fini(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mbxStatus) 1537 { 1538 emlxs_port_t *port = &PPORT; 1539 MATCHMAP *mbox_bp; 1540 emlxs_buf_t *mbox_sbp; 1541 fc_unsol_buf_t *mbox_ubp; 1542 IOCBQ *mbox_iocbq; 1543 MAILBOXQ *mbox_mbq; 1544 MAILBOX *mbox; 1545 uint32_t mbox_queue_flag; 1546 emlxs_ub_priv_t *ub_priv; 1547 1548 mutex_enter(&EMLXS_PORT_LOCK); 1549 1550 if (hba->mbox_queue_flag) { 1551 HBASTATS.MboxCompleted++; 1552 1553 if (mbxStatus != MBX_SUCCESS) { 1554 HBASTATS.MboxError++; 1555 } else { 1556 HBASTATS.MboxGood++; 1557 } 1558 } 1559 1560 mbox_bp = (MATCHMAP *)hba->mbox_bp; 1561 mbox_sbp = (emlxs_buf_t *)hba->mbox_sbp; 1562 mbox_ubp = (fc_unsol_buf_t *)hba->mbox_ubp; 1563 mbox_iocbq = (IOCBQ *)hba->mbox_iocbq; 1564 mbox_mbq = (MAILBOXQ *)hba->mbox_mbq; 1565 mbox_queue_flag = hba->mbox_queue_flag; 1566 1567 #ifdef MBOX_EXT_SUPPORT 1568 hba->mbox_ext = 0; 1569 hba->mbox_ext_size = 0; 1570 #endif /* MBOX_EXT_SUPPORT */ 1571 1572 hba->mbox_bp = 0; 1573 hba->mbox_sbp = 0; 1574 hba->mbox_ubp = 0; 1575 hba->mbox_iocbq = 0; 1576 hba->mbox_mbqflag = 0; 1577 hba->mbox_mbq = 0; 1578 hba->mbox_timer = 0; 1579 hba->mbox_queue_flag = 0; 1580 1581 mutex_exit(&EMLXS_PORT_LOCK); 1582 1583 if (mbox_mbq) { 1584 if (mb) { 1585 /* Copy the local mailbox provided back into */ 1586 /* the original mailbox */ 1587 bcopy((uint32_t *)mb, (uint32_t *)mbox_mbq, 1588 MAILBOX_CMD_BSIZE); 1589 } 1590 1591 mbox = (MAILBOX *)mbox_mbq; 1592 mbox->mbxStatus = mbxStatus; 1593 1594 /* Mark mailbox complete */ 1595 mbox_mbq->flag |= MBQ_COMPLETED; 1596 1597 /* Wake up the sleeping thread */ 1598 if (mbox_queue_flag == MBX_SLEEP) { 1599 mutex_enter(&EMLXS_MBOX_LOCK); 1600 cv_broadcast(&EMLXS_MBOX_CV); 1601 mutex_exit(&EMLXS_MBOX_LOCK); 1602 } 1603 } 1604 1605 /* Check for deferred MBUF cleanup */ 1606 if (mbox_bp && (mbox_queue_flag == MBX_NOWAIT)) { 1607 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mbox_bp); 1608 } 1609 #ifdef SFCT_SUPPORT 1610 if (mbox_sbp && mbox_sbp->fct_cmd) { 1611 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1612 "FCT mailbox: %s: status=%x", 1613 emlxs_mb_cmd_xlate(mb->mbxCommand), 1614 (uint32_t)mb->mbxStatus); 1615 } 1616 #endif /* SFCT_SUPPORT */ 1617 1618 /* Check for deferred pkt completion */ 1619 if (mbox_sbp) { 1620 if (mbxStatus != MBX_SUCCESS) { 1621 /* Set error status */ 1622 mbox_sbp->pkt_flags &= ~PACKET_STATE_VALID; 1623 emlxs_set_pkt_state(mbox_sbp, IOSTAT_LOCAL_REJECT, 1624 IOERR_NO_RESOURCES, 1); 1625 } 1626 1627 emlxs_pkt_complete(mbox_sbp, -1, 0, 1); 1628 } 1629 1630 /* Check for deferred ub completion */ 1631 if (mbox_ubp) { 1632 ub_priv = mbox_ubp->ub_fca_private; 1633 port = ub_priv->port; 1634 1635 emlxs_ub_callback(port, mbox_ubp); 1636 } 1637 1638 /* Check for deferred iocb tx */ 1639 if (mbox_iocbq) { 1640 emlxs_sli_issue_iocb_cmd(hba, mbox_iocbq->ring, mbox_iocbq); 1641 } 1642 1643 return; 1644 1645 } /* emlxs_mb_fini() */ 1646 1647 1648 1649 /* This should only be called with active MBX_NOWAIT mailboxes */ 1650 void 1651 emlxs_mb_retry(emlxs_hba_t *hba, MAILBOX *mb) 1652 { 1653 MAILBOXQ *mbq; 1654 1655 mutex_enter(&EMLXS_PORT_LOCK); 1656 1657 HBASTATS.MboxCompleted++; 1658 1659 if (mb->mbxStatus != 0) { 1660 HBASTATS.MboxError++; 1661 } else { 1662 HBASTATS.MboxGood++; 1663 } 1664 1665 mbq = (MAILBOXQ *)mb; 1666 mbq->bp = (uint8_t *)hba->mbox_bp; 1667 mbq->sbp = (uint8_t *)hba->mbox_sbp; 1668 mbq->ubp = (uint8_t *)hba->mbox_ubp; 1669 mbq->iocbq = (uint8_t *)hba->mbox_iocbq; 1670 1671 hba->mbox_bp = 0; 1672 hba->mbox_sbp = 0; 1673 hba->mbox_ubp = 0; 1674 hba->mbox_iocbq = 0; 1675 hba->mbox_mbq = 0; 1676 hba->mbox_mbqflag = 0; 1677 hba->mbox_queue_flag = 0; 1678 1679 mutex_exit(&EMLXS_PORT_LOCK); 1680 1681 return; 1682 1683 } /* emlxs_mb_retry() */ 1684 1685 1686 extern char * 1687 emlxs_mb_cmd_xlate(uint8_t cmd) 1688 { 1689 static char buffer[32]; 1690 uint32_t i; 1691 uint32_t count; 1692 1693 count = sizeof (emlxs_mb_cmd_table) / sizeof (emlxs_table_t); 1694 for (i = 0; i < count; i++) { 1695 if (cmd == emlxs_mb_cmd_table[i].code) { 1696 return (emlxs_mb_cmd_table[i].string); 1697 } 1698 } 1699 1700 (void) sprintf(buffer, "Cmd=0x%x", cmd); 1701 return (buffer); 1702 1703 } /* emlxs_mb_cmd_xlate() */ 1704