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_MBOX_C); 32 33 static void emlxs_mb_part_slim(emlxs_hba_t *hba, MAILBOXQ *mbq, 34 uint32_t hbainit); 35 static void emlxs_mb_set_mask(emlxs_hba_t *hba, MAILBOXQ *mbq, 36 uint32_t mask, uint32_t ringno); 37 static void emlxs_mb_set_debug(emlxs_hba_t *hba, MAILBOXQ *mbq, 38 uint32_t word0, uint32_t word1, uint32_t word2); 39 static void emlxs_mb_write_nv(emlxs_hba_t *hba, MAILBOXQ *mbq); 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_UNREG_VPI, "UNREG_VPI"}, /* NPIV */ 96 {MBX_ASYNC_EVENT, "ASYNC_EVENT"}, 97 {MBX_HEARTBEAT, "HEARTBEAT"}, 98 {MBX_READ_EVENT_LOG_STATUS, "READ_EVENT_LOG_STATUS"}, 99 {MBX_READ_EVENT_LOG, "READ_EVENT_LOG"}, 100 {MBX_WRITE_EVENT_LOG, "WRITE_EVENT_LOG"}, 101 {MBX_NV_LOG, "NV_LOG"}, 102 {MBX_PORT_CAPABILITIES, "PORT_CAPABILITIES"}, 103 {MBX_IOV_CONTROL, "IOV_CONTROL"}, 104 {MBX_IOV_MBX, "IOV_MBX"}, 105 {MBX_SLI_CONFIG, "SLI_CONFIG"}, 106 {MBX_REQUEST_FEATURES, "REQUEST_FEATURES"}, 107 {MBX_RESUME_RPI, "RESUME_RPI"}, 108 {MBX_REG_VFI, "REG_VFI"}, 109 {MBX_REG_FCFI, "REG_FCFI"}, 110 {MBX_UNREG_VFI, "UNREG_VFI"}, 111 {MBX_UNREG_FCFI, "UNREG_FCFI"}, 112 {MBX_INIT_VFI, "INIT_VFI"}, 113 {MBX_INIT_VPI, "INIT_VPI"} 114 }; /* emlxs_mb_cmd_table */ 115 116 117 /* 118 * emlxs_mb_resetport Issue a Port Reset mailbox command 119 */ 120 /*ARGSUSED*/ 121 extern void 122 emlxs_mb_resetport(emlxs_hba_t *hba, MAILBOXQ *mbq) 123 { 124 MAILBOX4 *mb = (MAILBOX4 *)mbq; 125 126 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 127 mbq->nonembed = NULL; 128 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 129 130 /* 131 * Signifies an embedded command 132 */ 133 mb->un.varSLIConfig.be.embedded = 1; 134 135 mb->mbxCommand = MBX_SLI_CONFIG; 136 mb->mbxOwner = OWN_HOST; 137 mb->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ; 138 mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = 139 IOCTL_SUBSYSTEM_COMMON; 140 mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_RESET; 141 mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; 142 mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 0; 143 144 return; 145 146 } /* emlxs_mb_resetport() */ 147 148 149 /* 150 * emlxs_mb_request_features Issue a REQUEST FEATURES mailbox command 151 */ 152 /*ARGSUSED*/ 153 extern void 154 emlxs_mb_request_features(emlxs_hba_t *hba, MAILBOXQ *mbq) 155 { 156 emlxs_config_t *cfg = &CFG; 157 MAILBOX4 *mb = (MAILBOX4 *)mbq; 158 159 hba->flag &= ~FC_NPIV_ENABLED; 160 161 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 162 mbq->nonembed = NULL; 163 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 164 165 mb->mbxCommand = MBX_REQUEST_FEATURES; 166 mb->mbxOwner = OWN_HOST; 167 mb->un.varReqFeatures.featuresRequested |= 168 SLI4_FEATURE_FCP_INITIATOR; 169 170 if (cfg[CFG_NPIV_ENABLE].current) { 171 mb->un.varReqFeatures.featuresRequested |= 172 SLI4_FEATURE_NPIV; 173 } 174 175 } /* emlxs_mb_request_features() */ 176 177 178 /* 179 * emlxs_mb_resume_rpi Issue a RESUME_RPI mailbox command 180 */ 181 /*ARGSUSED*/ 182 extern int 183 emlxs_mb_resume_rpi(emlxs_hba_t *hba, emlxs_buf_t *sbp, uint16_t rpi) 184 { 185 MAILBOX4 *mb; 186 MAILBOXQ *mbq; 187 uint32_t rval; 188 189 (void) emlxs_sli4_find_rpi(hba, rpi); 190 191 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 192 return (1); 193 } 194 mb = (MAILBOX4 *)mbq; 195 196 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 197 mbq->nonembed = NULL; 198 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 199 mbq->sbp = (uint8_t *)sbp; 200 201 mb->mbxCommand = MBX_RESUME_RPI; 202 mb->mbxOwner = OWN_HOST; 203 mb->un.varResumeRPI.EventTag = hba->link_event_tag; 204 mb->un.varResumeRPI.RPI = rpi; 205 206 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 207 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 208 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 209 } 210 return (rval); 211 212 } /* emlxs_mb_resume_rpi() */ 213 214 215 /*ARGSUSED*/ 216 extern void 217 emlxs_mb_noop(emlxs_hba_t *hba, MAILBOXQ *mbq) 218 { 219 MAILBOX4 *mb = (MAILBOX4 *)mbq; 220 IOCTL_COMMON_NOP *nop; 221 222 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 223 mbq->nonembed = NULL; 224 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 225 226 /* 227 * Signifies an embedded command 228 */ 229 mb->un.varSLIConfig.be.embedded = 1; 230 231 mb->mbxCommand = MBX_SLI_CONFIG; 232 mb->mbxOwner = OWN_HOST; 233 mb->un.varSLIConfig.be.payload_length = sizeof (IOCTL_COMMON_NOP) + 234 IOCTL_HEADER_SZ; 235 mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = 236 IOCTL_SUBSYSTEM_COMMON; 237 mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_NOP; 238 mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; 239 mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 240 sizeof (IOCTL_COMMON_NOP); 241 nop = (IOCTL_COMMON_NOP *)&mb->un.varSLIConfig.payload; 242 nop->params.request.context = -1; 243 244 return; 245 246 } /* emlxs_mb_noop() */ 247 248 249 /*ARGSUSED*/ 250 extern int 251 emlxs_mbext_noop(emlxs_hba_t *hba, MAILBOXQ *mbq) 252 { 253 MAILBOX4 *mb = (MAILBOX4 *)mbq; 254 IOCTL_COMMON_NOP *nop; 255 MATCHMAP *mp; 256 mbox_req_hdr_t *hdr_req; 257 258 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 259 260 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { 261 return (1); 262 } 263 /* 264 * Save address for completion 265 * Signifies a non-embedded command 266 */ 267 mb->un.varSLIConfig.be.embedded = 0; 268 mbq->nonembed = (uint8_t *)mp; 269 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 270 271 mb->mbxCommand = MBX_SLI_CONFIG; 272 mb->mbxOwner = OWN_HOST; 273 274 hdr_req = (mbox_req_hdr_t *)mp->virt; 275 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON; 276 hdr_req->opcode = COMMON_OPCODE_NOP; 277 hdr_req->timeout = 0; 278 hdr_req->req_length = sizeof (IOCTL_COMMON_NOP); 279 nop = (IOCTL_COMMON_NOP *)(hdr_req + 1); 280 nop->params.request.context = -1; 281 282 return (0); 283 284 } /* emlxs_mbext_noop() */ 285 286 287 int 288 emlxs_cmpl_read_fcf_table(void *arg1, MAILBOXQ *mbq) 289 { 290 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 291 emlxs_port_t *port = &PPORT; 292 mbox_rsp_hdr_t *hdr_rsp; 293 IOCTL_FCOE_READ_FCF_TABLE *fcf; 294 FCF_RECORD_t *fcfrec; 295 FCFIobj_t *fcfp; 296 MAILBOX4 *mb; 297 MATCHMAP *mp; 298 MAILBOXQ *fcfmbq; 299 uint32_t i, *iptr; 300 uint16_t s, *sptr; 301 int rc; 302 303 mb = (MAILBOX4 *)mbq; 304 mp = (MATCHMAP *)mbq->nonembed; 305 hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; 306 307 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 308 "CMPL read fcf: stats: %x %x %x", 309 mb->mbxStatus, hdr_rsp->status, hdr_rsp->extra_status); 310 311 if (mb->mbxStatus || hdr_rsp->status) { 312 /* Wait for FCF found async event */ 313 return (0); 314 } 315 316 /* 317 * Only support 1 FCF for now, so we don't need to walk 318 * thru the FCF table. 319 */ 320 fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_rsp + 1); 321 fcfrec = &fcf->params.response.fcf_entry[0]; 322 323 /* Fix up data in FCF record */ 324 BE_SWAP32_BUFFER(&fcfrec->fabric_name_identifier[0], 8); 325 BE_SWAP32_BUFFER(&fcfrec->switch_name_identifier[0], 8); 326 BE_SWAP32_BUFFER(&fcfrec->vlan_bitmap[0], 512); 327 iptr = (uint32_t *)&fcfrec->fcf_mac_address_hi[0]; 328 i = *iptr; 329 *iptr = BE_SWAP32(i); 330 sptr = (uint16_t *)&fcfrec->fcf_mac_address_low[0]; 331 s = *sptr; 332 *sptr = BE_SWAP16(s); 333 #ifdef EMLXS_BIG_ENDIAN 334 i = fcfrec->fc_map[0]; 335 fcfrec->fc_map[0] = fcfrec->fc_map[2]; 336 fcfrec->fc_map[2] = i; 337 #endif 338 339 /* Assign a FCFI object for the fcf_index */ 340 fcfp = emlxs_sli4_assign_fcfi(hba, fcfrec); 341 if (!fcfp) { 342 return (0); 343 } 344 fcfp->EventTag = fcf->params.response.event_tag; 345 346 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 347 "CMPL read fcf: info: x%x x%x", 348 fcfp->EventTag, fcf->params.response.next_valid_fcf_index); 349 350 if (emlxs_sli4_bind_fcfi(hba)) { 351 /* 352 * In this phase, if we successfully bind to just 353 * 1 FCFI we are done. 354 */ 355 return (0); 356 } 357 358 if (fcf->params.response.next_valid_fcf_index == 0xffff) { 359 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 360 "Waiting for a valid FCF to be discovered"); 361 return (0); 362 } 363 364 /* Get the next one */ 365 if (!(fcfmbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 366 return (0); 367 } 368 rc = emlxs_mbext_read_fcf_table(hba, fcfmbq, 369 fcf->params.response.next_valid_fcf_index); 370 if (rc == 0) { 371 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)fcfmbq); 372 return (0); 373 } 374 375 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, fcfmbq, MBX_NOWAIT, 0); 376 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 377 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)fcfmbq); 378 } 379 return (0); 380 } /* emlxs_cmpl_read_fcf_table() */ 381 382 383 extern int 384 emlxs_mbext_read_fcf_table(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t index) 385 { 386 MAILBOX4 *mb = (MAILBOX4 *)mbq; 387 IOCTL_FCOE_READ_FCF_TABLE *fcf; 388 MATCHMAP *mp; 389 mbox_req_hdr_t *hdr_req; 390 391 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 392 393 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { 394 return (0); 395 } 396 /* 397 * Save address for completion 398 * Signifies a non-embedded command 399 */ 400 mb->un.varSLIConfig.be.embedded = 0; 401 mbq->nonembed = (uint8_t *)mp; 402 mbq->mbox_cmpl = emlxs_cmpl_read_fcf_table; 403 404 mb->mbxCommand = MBX_SLI_CONFIG; 405 mb->mbxOwner = OWN_HOST; 406 407 hdr_req = (mbox_req_hdr_t *)mp->virt; 408 hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE; 409 hdr_req->opcode = FCOE_OPCODE_READ_FCF_TABLE; 410 hdr_req->timeout = 0; 411 hdr_req->req_length = sizeof (IOCTL_FCOE_READ_FCF_TABLE); 412 fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_req + 1); 413 fcf->params.request.fcf_index = index; 414 415 return (1); 416 417 } /* emlxs_mbext_read_fcf_table() */ 418 419 420 int 421 emlxs_cmpl_add_fcf_table(void *arg1, MAILBOXQ *mbq) 422 { 423 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 424 emlxs_port_t *port = &PPORT; 425 MAILBOX4 *mb; 426 MAILBOXQ *mq; 427 MATCHMAP *mp; 428 mbox_rsp_hdr_t *hdr_rsp; 429 uint32_t rc; 430 431 mb = (MAILBOX4 *)mbq; 432 mp = (MATCHMAP *)mbq->nonembed; 433 434 hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; 435 436 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 437 "CMPL add fcf: stats: %x %x %x", 438 mb->mbxStatus, hdr_rsp->status, hdr_rsp->extra_status); 439 440 if (mbq->nonembed) { 441 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mbq->nonembed); 442 mbq->nonembed = 0; 443 } 444 445 if (mb->mbxStatus) { 446 /* In nonFIP mode, FCF Entries are persistent */ 447 if (!hdr_rsp->status || 448 (hdr_rsp->status != MGMT_STATUS_FCF_IN_USE)) { 449 return (0); 450 } 451 } 452 453 /* 454 * Now that we have a fcf table entry, read it back 455 * to fall into the normal link up processing. 456 */ 457 if (!(mq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 458 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 459 "CMPL add fcf: Cannot alloc mbox"); 460 return (0); 461 } 462 rc = emlxs_mbext_read_fcf_table(hba, mq, -1); 463 464 if (rc == 0) { 465 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 466 "CMPL add fcf: Cannot build read fcf mbox"); 467 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mq); 468 return (0); 469 } 470 471 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mq, MBX_NOWAIT, 0); 472 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 473 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 474 "CMPL add fcf: Cannot issue read fcf mbox"); 475 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mq); 476 } 477 return (0); 478 } /* emlxs_cmpl_add_fcf_table() */ 479 480 481 extern int 482 emlxs_mbext_add_fcf_table(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t index) 483 { 484 emlxs_port_t *port = &PPORT; 485 MAILBOX4 *mb = (MAILBOX4 *)mbq; 486 IOCTL_FCOE_ADD_FCF_TABLE *fcf; 487 FCF_RECORD_t *fcfrec; 488 MATCHMAP *mp; 489 mbox_req_hdr_t *hdr_req; 490 491 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 492 493 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { 494 return (0); 495 } 496 /* 497 * Save address for completion 498 * Signifies a non-embedded command 499 */ 500 mb->un.varSLIConfig.be.embedded = 0; 501 mbq->nonembed = (uint8_t *)mp; 502 mbq->mbox_cmpl = emlxs_cmpl_add_fcf_table; 503 504 mb->mbxCommand = MBX_SLI_CONFIG; 505 mb->mbxOwner = OWN_HOST; 506 507 hdr_req = (mbox_req_hdr_t *)mp->virt; 508 hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE; 509 hdr_req->opcode = FCOE_OPCODE_ADD_FCF_TABLE; 510 hdr_req->timeout = 0; 511 hdr_req->req_length = sizeof (IOCTL_FCOE_ADD_FCF_TABLE); 512 fcf = (IOCTL_FCOE_ADD_FCF_TABLE *)(hdr_req + 1); 513 fcf->params.request.fcf_index = index; 514 515 fcfrec = &fcf->params.request.fcf_entry; 516 fcfrec->max_recv_size = EMLXS_FCOE_MAX_RCV_SZ; 517 fcfrec->fka_adv_period = 0; 518 fcfrec->fip_priority = 128; 519 #ifdef EMLXS_BIG_ENDIAN 520 fcfrec->fcf_mac_address_hi[0] = FCOE_FCF_MAC3; 521 fcfrec->fcf_mac_address_hi[1] = FCOE_FCF_MAC2; 522 fcfrec->fcf_mac_address_hi[2] = FCOE_FCF_MAC1; 523 fcfrec->fcf_mac_address_hi[3] = FCOE_FCF_MAC0; 524 fcfrec->fcf_mac_address_low[0] = FCOE_FCF_MAC5; 525 fcfrec->fcf_mac_address_low[1] = FCOE_FCF_MAC4; 526 fcfrec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[2]; 527 fcfrec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1]; 528 fcfrec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[0]; 529 #endif 530 #ifdef EMLXS_LITTLE_ENDIAN 531 fcfrec->fcf_mac_address_hi[0] = FCOE_FCF_MAC0; 532 fcfrec->fcf_mac_address_hi[1] = FCOE_FCF_MAC1; 533 fcfrec->fcf_mac_address_hi[2] = FCOE_FCF_MAC2; 534 fcfrec->fcf_mac_address_hi[3] = FCOE_FCF_MAC3; 535 fcfrec->fcf_mac_address_low[0] = FCOE_FCF_MAC4; 536 fcfrec->fcf_mac_address_low[1] = FCOE_FCF_MAC5; 537 fcfrec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[0]; 538 fcfrec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1]; 539 fcfrec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[2]; 540 #endif 541 542 if (hba->sli.sli4.cfgFCOE.fip_flags & TLV_FCOE_VLAN) { 543 uint16_t i; 544 uint8_t bitmap[512]; 545 546 bzero((void *) bitmap, 512); 547 i = hba->sli.sli4.cfgFCOE.VLanId; 548 bitmap[i / 8] = (1 << (i % 8)); 549 BE_SWAP32_BCOPY(bitmap, fcfrec->vlan_bitmap, 512); 550 } 551 552 fcfrec->fcf_valid = 1; 553 fcfrec->fcf_available = 1; 554 555 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 556 "ADD FCF %d: av: %x %x ste %x macp %x " 557 "addr: %02x:%02x:%02x:%02x:%02x:%02x", 558 fcfrec->fcf_index, 559 fcfrec->fcf_available, 560 fcfrec->fcf_valid, 561 fcfrec->fcf_state, 562 fcfrec->mac_address_provider, 563 fcfrec->fcf_mac_address_hi[0], 564 fcfrec->fcf_mac_address_hi[1], 565 fcfrec->fcf_mac_address_hi[2], 566 fcfrec->fcf_mac_address_hi[3], 567 fcfrec->fcf_mac_address_low[0], 568 fcfrec->fcf_mac_address_low[1]); 569 return (1); 570 571 } /* emlxs_mbext_add_fcf_table() */ 572 573 574 /*ARGSUSED*/ 575 extern void 576 emlxs_mb_eq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num) 577 { 578 MAILBOX4 *mb = (MAILBOX4 *)mbq; 579 IOCTL_COMMON_EQ_CREATE *qp; 580 uint64_t addr; 581 582 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 583 mbq->nonembed = NULL; 584 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 585 586 /* 587 * Signifies an embedded command 588 */ 589 mb->un.varSLIConfig.be.embedded = 1; 590 591 mb->mbxCommand = MBX_SLI_CONFIG; 592 mb->mbxOwner = OWN_HOST; 593 mb->un.varSLIConfig.be.payload_length = 594 sizeof (IOCTL_COMMON_EQ_CREATE) + IOCTL_HEADER_SZ; 595 mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = 596 IOCTL_SUBSYSTEM_COMMON; 597 mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_EQ_CREATE; 598 mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; 599 mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 600 sizeof (IOCTL_COMMON_EQ_CREATE); 601 qp = (IOCTL_COMMON_EQ_CREATE *)&mb->un.varSLIConfig.payload; 602 603 /* 1024 * 4 bytes = 4K */ 604 qp->params.request.EQContext.Count = EQ_ELEMENT_COUNT_1024; 605 qp->params.request.EQContext.Valid = 1; 606 qp->params.request.EQContext.NoDelay = 0; 607 qp->params.request.EQContext.DelayMult = EQ_DELAY_MULT; 608 609 addr = hba->sli.sli4.eq[num].addr.phys; 610 qp->params.request.NumPages = 1; 611 qp->params.request.Pages[0].addrLow = PADDR_LO(addr); 612 qp->params.request.Pages[0].addrHigh = PADDR_HI(addr); 613 614 return; 615 616 } /* emlxs_mb_eq_create() */ 617 618 619 /*ARGSUSED*/ 620 extern void 621 emlxs_mb_cq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num) 622 { 623 MAILBOX4 *mb = (MAILBOX4 *)mbq; 624 IOCTL_COMMON_CQ_CREATE *qp; 625 uint64_t addr; 626 627 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 628 mbq->nonembed = NULL; 629 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 630 631 /* 632 * Signifies an embedded command 633 */ 634 mb->un.varSLIConfig.be.embedded = 1; 635 636 mb->mbxCommand = MBX_SLI_CONFIG; 637 mb->mbxOwner = OWN_HOST; 638 mb->un.varSLIConfig.be.payload_length = 639 sizeof (IOCTL_COMMON_CQ_CREATE) + IOCTL_HEADER_SZ; 640 mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = 641 IOCTL_SUBSYSTEM_COMMON; 642 mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_CQ_CREATE; 643 mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; 644 mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 645 sizeof (IOCTL_COMMON_CQ_CREATE); 646 qp = (IOCTL_COMMON_CQ_CREATE *)&mb->un.varSLIConfig.payload; 647 648 /* 256 * 16 bytes = 4K */ 649 qp->params.request.CQContext.Count = CQ_ELEMENT_COUNT_256; 650 qp->params.request.CQContext.EQId = hba->sli.sli4.cq[num].eqid; 651 qp->params.request.CQContext.Valid = 1; 652 qp->params.request.CQContext.Eventable = 1; 653 qp->params.request.CQContext.NoDelay = 0; 654 655 addr = hba->sli.sli4.cq[num].addr.phys; 656 qp->params.request.NumPages = 1; 657 qp->params.request.Pages[0].addrLow = PADDR_LO(addr); 658 qp->params.request.Pages[0].addrHigh = PADDR_HI(addr); 659 660 return; 661 662 } /* emlxs_mb_cq_create() */ 663 664 665 /*ARGSUSED*/ 666 extern void 667 emlxs_mb_wq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num) 668 { 669 MAILBOX4 *mb = (MAILBOX4 *)mbq; 670 IOCTL_FCOE_WQ_CREATE *qp; 671 uint64_t addr; 672 int i; 673 674 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 675 mbq->nonembed = NULL; 676 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 677 678 /* 679 * Signifies an embedded command 680 */ 681 mb->un.varSLIConfig.be.embedded = 1; 682 683 mb->mbxCommand = MBX_SLI_CONFIG; 684 mb->mbxOwner = OWN_HOST; 685 mb->un.varSLIConfig.be.payload_length = 686 sizeof (IOCTL_FCOE_WQ_CREATE) + IOCTL_HEADER_SZ; 687 mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = 688 IOCTL_SUBSYSTEM_FCOE; 689 mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = FCOE_OPCODE_WQ_CREATE; 690 mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; 691 mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 692 sizeof (IOCTL_FCOE_WQ_CREATE); 693 694 addr = hba->sli.sli4.wq[num].addr.phys; 695 qp = (IOCTL_FCOE_WQ_CREATE *)&mb->un.varSLIConfig.payload; 696 697 qp->params.request.CQId = hba->sli.sli4.wq[num].cqid; 698 699 qp->params.request.NumPages = EMLXS_NUM_WQ_PAGES; 700 for (i = 0; i < EMLXS_NUM_WQ_PAGES; i++) { 701 qp->params.request.Pages[i].addrLow = PADDR_LO(addr); 702 qp->params.request.Pages[i].addrHigh = PADDR_HI(addr); 703 addr += 4096; 704 } 705 706 return; 707 708 } /* emlxs_mb_wq_create() */ 709 710 711 /*ARGSUSED*/ 712 extern void 713 emlxs_mb_rq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num) 714 { 715 MAILBOX4 *mb = (MAILBOX4 *)mbq; 716 IOCTL_FCOE_RQ_CREATE *qp; 717 uint64_t addr; 718 719 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 720 mbq->nonembed = NULL; 721 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 722 723 /* 724 * Signifies an embedded command 725 */ 726 mb->un.varSLIConfig.be.embedded = 1; 727 728 mb->mbxCommand = MBX_SLI_CONFIG; 729 mb->mbxOwner = OWN_HOST; 730 mb->un.varSLIConfig.be.payload_length = 731 sizeof (IOCTL_FCOE_RQ_CREATE) + IOCTL_HEADER_SZ; 732 mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = 733 IOCTL_SUBSYSTEM_FCOE; 734 mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = FCOE_OPCODE_RQ_CREATE; 735 mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; 736 mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 737 sizeof (IOCTL_FCOE_RQ_CREATE); 738 addr = hba->sli.sli4.rq[num].addr.phys; 739 740 qp = (IOCTL_FCOE_RQ_CREATE *)&mb->un.varSLIConfig.payload; 741 742 qp->params.request.RQContext.RQSize = RQ_DEPTH_EXPONENT; 743 qp->params.request.RQContext.BufferSize = RQB_DATA_SIZE; 744 qp->params.request.RQContext.CQIdRecv = hba->sli.sli4.rq[num].cqid; 745 746 qp->params.request.NumPages = 1; 747 qp->params.request.Pages[0].addrLow = PADDR_LO(addr); 748 qp->params.request.Pages[0].addrHigh = PADDR_HI(addr); 749 750 return; 751 752 } /* emlxs_mb_rq_create() */ 753 754 755 /*ARGSUSED*/ 756 extern void 757 emlxs_mb_mq_create(emlxs_hba_t *hba, MAILBOXQ *mbq) 758 { 759 MAILBOX4 *mb = (MAILBOX4 *)mbq; 760 IOCTL_COMMON_MQ_CREATE *qp; 761 uint64_t addr; 762 763 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 764 mbq->nonembed = NULL; 765 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 766 767 /* 768 * Signifies an embedded command 769 */ 770 mb->un.varSLIConfig.be.embedded = 1; 771 772 mb->mbxCommand = MBX_SLI_CONFIG; 773 mb->mbxOwner = OWN_HOST; 774 mb->un.varSLIConfig.be.payload_length = 775 sizeof (IOCTL_COMMON_MQ_CREATE) + IOCTL_HEADER_SZ; 776 mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = 777 IOCTL_SUBSYSTEM_COMMON; 778 mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_MQ_CREATE; 779 mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; 780 mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 781 sizeof (IOCTL_COMMON_MQ_CREATE); 782 783 addr = hba->sli.sli4.mq.addr.phys; 784 qp = (IOCTL_COMMON_MQ_CREATE *)&mb->un.varSLIConfig.payload; 785 786 qp->params.request.MQContext.Size = MQ_ELEMENT_COUNT_16; 787 qp->params.request.MQContext.Valid = 1; 788 qp->params.request.MQContext.CQId = hba->sli.sli4.mq.cqid; 789 790 qp->params.request.NumPages = 1; 791 qp->params.request.Pages[0].addrLow = PADDR_LO(addr); 792 qp->params.request.Pages[0].addrHigh = PADDR_HI(addr); 793 794 return; 795 796 } /* emlxs_mb_mq_create() */ 797 798 799 static int 800 emlxs_cmpl_reg_fcfi(void *arg1, MAILBOXQ *mbq) 801 { 802 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 803 emlxs_port_t *port = &PPORT; 804 FCFIobj_t *fcfp; 805 VFIobj_t *vfip; 806 RPIobj_t *rpip; 807 MAILBOX4 *mb; 808 809 mb = (MAILBOX4 *)mbq; 810 fcfp = (FCFIobj_t *)mbq->context; 811 812 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 813 "CMPL reg fcfi: status: %x", mb->mbxStatus); 814 815 if (mb->mbxStatus) { 816 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 817 "Unable to register FCFI for FCFI %d index %d", 818 mb->un.varRegFCFI.FCFI, mb->un.varRegFCFI.InfoIndex); 819 (void) emlxs_sli4_free_fcfi(hba, fcfp); 820 return (0); 821 } 822 823 fcfp->state |= RESOURCE_FCFI_REG; 824 825 if (!fcfp->fcf_vfi) { 826 vfip = emlxs_sli4_alloc_vfi(hba, fcfp); 827 if (!vfip) { 828 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 829 "Unable to alloc VFI for Fabric, fcf index %d", 830 fcfp->FCF_index); 831 (void) emlxs_sli4_free_fcfi(hba, fcfp); 832 return (0); 833 } 834 fcfp->fcf_vfi = vfip; 835 } 836 837 if (!fcfp->fcf_vpi) { 838 fcfp->fcf_vpi = port; 839 port->VFIp = fcfp->fcf_vfi; 840 port->VFIp->outstandingVPIs++; 841 } 842 843 rpip = &fcfp->scratch_rpi; 844 rpip->state = RESOURCE_ALLOCATED; 845 rpip->VPIp = fcfp->fcf_vpi; 846 rpip->RPI = 0xffff; 847 rpip->index = 0xffff; 848 849 fcfp->FCFI = mb->un.varRegFCFI.FCFI; 850 851 /* Declare the linkup here */ 852 if (!(fcfp->state & RESOURCE_FCFI_DISC)) { 853 fcfp->state |= RESOURCE_FCFI_DISC; 854 emlxs_linkup(hba); 855 } 856 return (0); 857 858 } /* emlxs_cmpl_reg_fcfi() */ 859 860 861 /*ARGSUSED*/ 862 extern void 863 emlxs_mb_reg_fcfi(emlxs_hba_t *hba, MAILBOXQ *mbq, FCFIobj_t *fcfp) 864 { 865 MAILBOX4 *mb = (MAILBOX4 *)mbq; 866 867 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 868 869 mb->mbxCommand = MBX_REG_FCFI; 870 mb->mbxOwner = OWN_HOST; 871 mb->un.varRegFCFI.FCFI = 0; /* FCFI will be returned by firmware */ 872 mb->un.varRegFCFI.InfoIndex = fcfp->FCF_index; 873 874 mb->un.varRegFCFI.RQId0 = hba->sli.sli4.rq[EMLXS_FCFI_RQ0_INDEX].qid; 875 mb->un.varRegFCFI.Id0_rctl_mask = EMLXS_FCFI_RQ0_RMASK; 876 mb->un.varRegFCFI.Id0_rctl = EMLXS_FCFI_RQ0_RCTL; 877 mb->un.varRegFCFI.Id0_type_mask = EMLXS_FCFI_RQ0_TMASK; 878 mb->un.varRegFCFI.Id0_type = EMLXS_FCFI_RQ0_TYPE; 879 880 mb->un.varRegFCFI.RQId1 = 0xffff; 881 mb->un.varRegFCFI.RQId2 = 0xffff; 882 mb->un.varRegFCFI.RQId3 = 0xffff; 883 884 if (fcfp->state & RESOURCE_FCFI_VLAN_ID) { 885 mb->un.varRegFCFI.vv = 1; 886 mb->un.varRegFCFI.vlanTag = fcfp->vlan_id; 887 } 888 889 /* Ignore the fcf record and force FPMA */ 890 mb->un.varRegFCFI.mam = EMLXS_REG_FCFI_MAM_FPMA; 891 892 mbq->mbox_cmpl = emlxs_cmpl_reg_fcfi; 893 mbq->context = (uint8_t *)fcfp; 894 return; 895 896 } /* emlxs_mb_reg_fcfi() */ 897 898 899 /* SLI4 */ 900 static int 901 emlxs_cmpl_unreg_fcfi(void *arg1, MAILBOXQ *mbq) 902 { 903 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 904 emlxs_port_t *port = &PPORT; 905 FCFIobj_t *fcfp; 906 MAILBOX4 *mb; 907 908 mb = (MAILBOX4 *)mbq; 909 fcfp = (FCFIobj_t *)mbq->context; 910 911 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 912 "CMPL unreg fcfi: status: %x", mb->mbxStatus); 913 914 if (mb->mbxStatus) { 915 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 916 "Unable to unregister FCFI %d index %d", 917 fcfp->FCFI, fcfp->FCF_index); 918 } 919 920 (void) emlxs_sli4_free_fcfi(hba, fcfp); 921 922 /* Make sure link is declared down */ 923 emlxs_linkdown(hba); 924 925 return (0); 926 927 } /* emlxs_cmpl_unreg_fcfi() */ 928 929 930 /* ARGSUSED */ 931 extern int 932 emlxs_mb_unreg_fcfi(emlxs_hba_t *hba, FCFIobj_t *fcfp) 933 { 934 MAILBOXQ *mbq; 935 MAILBOX4 *mb; 936 uint32_t rval; 937 938 mutex_enter(&EMLXS_PORT_LOCK); 939 940 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 941 mutex_exit(&EMLXS_PORT_LOCK); 942 return (1); 943 } 944 mb = (MAILBOX4 *)mbq; 945 mutex_exit(&EMLXS_PORT_LOCK); 946 947 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 948 949 mb->mbxCommand = MBX_UNREG_FCFI; 950 mb->mbxOwner = OWN_HOST; 951 mb->un.varUnRegFCFI.FCFI = fcfp->FCFI; 952 953 mbq->mbox_cmpl = emlxs_cmpl_unreg_fcfi; 954 mbq->context = (uint8_t *)fcfp; 955 fcfp->fcf_vfi = NULL; 956 fcfp->fcf_vpi = NULL; 957 958 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 959 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 960 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 961 } 962 963 return (0); 964 965 } /* emlxs_mb_unreg_fcfi() */ 966 967 968 int 969 emlxs_mb_cmpl_reg_vfi(void *arg1, MAILBOXQ *mbq) 970 { 971 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 972 emlxs_port_t *port = &PPORT; 973 MAILBOX4 *mb; 974 MAILBOXQ *mbox; 975 MATCHMAP *mp; 976 NODELIST *ndlp; 977 emlxs_port_t *vport; 978 VFIobj_t *vfip; 979 uint8_t *wwn; 980 volatile SERV_PARM *sp; 981 int32_t i; 982 uint32_t ldid; 983 emlxs_vvl_fmt_t vvl; 984 985 mb = (MAILBOX4 *)mbq; 986 if (mb->mbxStatus) { 987 EMLXS_MSGF(EMLXS_CONTEXT, 988 &emlxs_sli_detail_msg, 989 "REG_VFI failed. status=x%x", mb->mbxStatus); 990 return (0); 991 } 992 993 vport = (emlxs_port_t *)mbq->context; 994 vfip = vport->VFIp; 995 vfip->state |= RESOURCE_VFI_REG; 996 997 if (mb->un.varRegVFI4.vp) { 998 vport->flag |= EMLXS_PORT_REGISTERED; 999 } 1000 1001 mp = (MATCHMAP *)mbq->bp; 1002 if (!mp) { 1003 return (0); 1004 } 1005 sp = (volatile SERV_PARM *)mp->virt; 1006 1007 ldid = FABRIC_DID; 1008 ndlp = emlxs_node_find_did(port, ldid); 1009 1010 if (!ndlp) { 1011 /* Attempt to create a node */ 1012 if ((ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP, 0))) { 1013 ndlp->nlp_Rpi = 0xffff; 1014 ndlp->nlp_DID = ldid; 1015 1016 bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm, 1017 sizeof (SERV_PARM)); 1018 1019 bcopy((uint8_t *)&sp->nodeName, 1020 (uint8_t *)&ndlp->nlp_nodename, 1021 sizeof (NAME_TYPE)); 1022 1023 bcopy((uint8_t *)&sp->portName, 1024 (uint8_t *)&ndlp->nlp_portname, 1025 sizeof (NAME_TYPE)); 1026 1027 ndlp->nlp_active = 1; 1028 ndlp->nlp_flag[hba->channel_ct] |= NLP_CLOSED; 1029 ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED; 1030 ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED; 1031 ndlp->nlp_flag[hba->channel_ip] |= NLP_CLOSED; 1032 1033 /* Add the node */ 1034 emlxs_node_add(port, ndlp); 1035 1036 /* Open the node */ 1037 emlxs_node_open(port, ndlp, hba->channel_ct); 1038 emlxs_node_open(port, ndlp, hba->channel_els); 1039 emlxs_node_open(port, ndlp, hba->channel_ip); 1040 emlxs_node_open(port, ndlp, hba->channel_fcp); 1041 } else { 1042 wwn = (uint8_t *)&sp->portName; 1043 EMLXS_MSGF(EMLXS_CONTEXT, 1044 &emlxs_node_create_failed_msg, 1045 "Unable to allocate node. did=%06x " 1046 "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", 1047 ldid, wwn[0], wwn[1], wwn[2], 1048 wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 1049 1050 return (0); 1051 } 1052 } else { 1053 mutex_enter(&EMLXS_PORT_LOCK); 1054 1055 ndlp->nlp_Rpi = 0xffff; 1056 ndlp->nlp_DID = ldid; 1057 1058 bcopy((uint8_t *)sp, 1059 (uint8_t *)&ndlp->sparm, sizeof (SERV_PARM)); 1060 1061 bcopy((uint8_t *)&sp->nodeName, 1062 (uint8_t *)&ndlp->nlp_nodename, sizeof (NAME_TYPE)); 1063 1064 bcopy((uint8_t *)&sp->portName, 1065 (uint8_t *)&ndlp->nlp_portname, sizeof (NAME_TYPE)); 1066 1067 wwn = (uint8_t *)&ndlp->nlp_portname; 1068 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg, 1069 "node=%p did=%06x rpi=%x " 1070 "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", 1071 ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], 1072 wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 1073 1074 mutex_exit(&EMLXS_PORT_LOCK); 1075 1076 /* Open the node */ 1077 emlxs_node_open(port, ndlp, hba->channel_ct); 1078 emlxs_node_open(port, ndlp, hba->channel_els); 1079 emlxs_node_open(port, ndlp, hba->channel_ip); 1080 emlxs_node_open(port, ndlp, hba->channel_fcp); 1081 } 1082 1083 bzero((char *)&vvl, sizeof (emlxs_vvl_fmt_t)); 1084 1085 if (sp->VALID_VENDOR_VERSION) { 1086 1087 bcopy((caddr_t *)&sp->vendorVersion[0], 1088 (caddr_t *)&vvl, sizeof (emlxs_vvl_fmt_t)); 1089 1090 vvl.un0.word0 = LE_SWAP32(vvl.un0.word0); 1091 vvl.un1.word1 = LE_SWAP32(vvl.un1.word1); 1092 1093 if ((vvl.un0.w0.oui == 0x0000C9) && 1094 (vvl.un1.w1.vport)) { 1095 ndlp->nlp_fcp_info |= NLP_EMLX_VPORT; 1096 } 1097 } 1098 1099 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 1100 /* If link not already down then */ 1101 /* declare it down now */ 1102 if (emlxs_mb_read_sparam(hba, mbox) == 0) { 1103 emlxs_mb_put(hba, mbox); 1104 } else { 1105 (void) emlxs_mem_put(hba, MEM_MBOX, 1106 (uint8_t *)mbox); 1107 } 1108 } 1109 1110 /* Since this is a fabric login */ 1111 /* 1112 * If NPIV Fabric support has just been established on 1113 * the physical port, then notify the vports of the 1114 * link up 1115 */ 1116 EMLXS_STATE_CHANGE_LOCKED(hba, FC_READY); 1117 if ((hba->flag & FC_NPIV_ENABLED) && 1118 (hba->flag & FC_NPIV_SUPPORTED)) { 1119 /* Skip the physical port */ 1120 for (i = 1; i < MAX_VPORTS; i++) { 1121 vport = &VPORT(i); 1122 1123 if (!(vport->flag & EMLXS_PORT_BOUND) || 1124 !(vport->flag & EMLXS_PORT_ENABLE)) { 1125 continue; 1126 } 1127 1128 emlxs_port_online(vport); 1129 } 1130 } 1131 1132 #ifdef SFCT_SUPPORT 1133 if (mbq->sbp && ((emlxs_buf_t *)mbq->sbp)->fct_cmd) { 1134 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)mbq->sbp; 1135 1136 if (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) { 1137 mbq->sbp = NULL; 1138 1139 mutex_enter(&EMLXS_PKT_LOCK); 1140 cmd_sbp->node = ndlp; 1141 cv_broadcast(&EMLXS_PKT_CV); 1142 mutex_exit(&EMLXS_PKT_LOCK); 1143 } 1144 } 1145 #endif /* SFCT_SUPPORT */ 1146 return (0); 1147 1148 } /* emlxs_mb_cmpl_reg_vfi */ 1149 1150 1151 /*ARGSUSED*/ 1152 extern int 1153 emlxs_mb_reg_vfi(emlxs_hba_t *hba, MAILBOXQ *mbq, VFIobj_t *vfip, 1154 emlxs_port_t *port) 1155 { 1156 MAILBOX4 *mb = (MAILBOX4 *)mbq; 1157 FCFIobj_t *fcfp; 1158 MATCHMAP *mp; 1159 1160 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 1161 1162 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { 1163 return (0); 1164 } 1165 1166 mb->mbxCommand = MBX_REG_VFI; 1167 mb->mbxOwner = OWN_HOST; 1168 mb->un.varRegVFI4.vfi = vfip->VFI; 1169 if (!(port->flag & EMLXS_PORT_REGISTERED)) { 1170 mb->un.varRegVFI4.vp = 1; 1171 mb->un.varRegVFI4.vpi = port->vpi + hba->vpi_base; 1172 } 1173 fcfp = vfip->FCFIp; 1174 mb->un.varRegVFI4.fcfi = fcfp->FCFI; 1175 mb->un.varRegVFI4.sid = port->did; 1176 1177 /* in ms */ 1178 mb->un.varRegVFI4.edtov = fcfp->fcf_sparam.cmn.e_d_tov; 1179 1180 /* Convert to seconds */ 1181 mb->un.varRegVFI4.ratov = (fcfp->fcf_sparam.cmn.w2.r_a_tov + 1182 999) / 1000; 1183 1184 mb->un.varRegVFI4.bde.tus.f.bdeSize = sizeof (SERV_PARM); 1185 mb->un.varRegVFI4.bde.addrHigh = PADDR_HI(mp->phys); 1186 mb->un.varRegVFI4.bde.addrLow = PADDR_LO(mp->phys); 1187 bcopy((uint32_t *)&fcfp->fcf_sparam, 1188 (uint32_t *)mp->virt, sizeof (SERV_PARM)); 1189 1190 mbq->mbox_cmpl = emlxs_mb_cmpl_reg_vfi; 1191 1192 /* 1193 * save address for completion 1194 */ 1195 mbq->bp = (uint8_t *)mp; 1196 mbq->context = (uint8_t *)port; 1197 return (1); 1198 1199 } /* emlxs_mb_reg_vfi() */ 1200 1201 1202 /*ARGSUSED*/ 1203 extern int 1204 emlxs_mb_unreg_vfi(emlxs_hba_t *hba, VFIobj_t *vfip) 1205 { 1206 FCFIobj_t *fcfp; 1207 MAILBOX4 *mb; 1208 MAILBOXQ *mbq; 1209 uint32_t rval; 1210 1211 mutex_enter(&EMLXS_PORT_LOCK); 1212 if (!(vfip->state & RESOURCE_VFI_REG)) { 1213 mutex_exit(&EMLXS_PORT_LOCK); 1214 return (1); 1215 1216 } 1217 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 1218 mutex_exit(&EMLXS_PORT_LOCK); 1219 return (1); 1220 } 1221 1222 vfip->state &= ~RESOURCE_VFI_REG; 1223 mutex_exit(&EMLXS_PORT_LOCK); 1224 1225 mb = (MAILBOX4 *)mbq->mbox; 1226 1227 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 1228 1229 mb->mbxCommand = MBX_UNREG_VFI; 1230 mb->mbxOwner = OWN_HOST; 1231 1232 mb->un.varUnRegVFI4.vfi = vfip->VFI; 1233 1234 mbq->mbox_cmpl = NULL; 1235 1236 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 1237 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 1238 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 1239 } 1240 1241 fcfp = vfip->FCFIp; 1242 if (vfip == fcfp->fcf_vfi) { 1243 fcfp->fcf_vfi = NULL; 1244 } 1245 emlxs_sli4_free_vfi(hba, vfip); 1246 return (1); 1247 1248 } /* emlxs_mb_unreg_vfi() */ 1249 1250 1251 /*ARGSUSED*/ 1252 extern void 1253 emlxs_mb_async_event(emlxs_hba_t *hba, MAILBOXQ *mbq) 1254 { 1255 MAILBOX *mb = (MAILBOX *)mbq; 1256 1257 bzero((void *) mb, MAILBOX_CMD_BSIZE); 1258 1259 mb->mbxCommand = MBX_ASYNC_EVENT; 1260 mb->mbxOwner = OWN_HOST; 1261 mb->un.varWords[0] = hba->channel_els; 1262 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 1263 1264 return; 1265 1266 } /* emlxs_mb_async_event() */ 1267 1268 1269 /*ARGSUSED*/ 1270 extern void 1271 emlxs_mb_heartbeat(emlxs_hba_t *hba, MAILBOXQ *mbq) 1272 { 1273 MAILBOX *mb = (MAILBOX *)mbq; 1274 1275 bzero((void *) mb, MAILBOX_CMD_BSIZE); 1276 1277 mb->mbxCommand = MBX_HEARTBEAT; 1278 mb->mbxOwner = OWN_HOST; 1279 mbq->mbox_cmpl = NULL; /* no cmpl needed for hbeat */ 1280 1281 return; 1282 1283 } /* emlxs_mb_heartbeat() */ 1284 1285 1286 #ifdef MSI_SUPPORT 1287 1288 /*ARGSUSED*/ 1289 extern void 1290 emlxs_mb_config_msi(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t *intr_map, 1291 uint32_t intr_count) 1292 { 1293 MAILBOX *mb = (MAILBOX *)mbq; 1294 uint32_t i; 1295 uint32_t mask; 1296 1297 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1298 1299 mb->mbxCommand = MBX_CONFIG_MSI; 1300 1301 /* Set the default message id to zero */ 1302 mb->un.varCfgMSI.defaultPresent = 1; 1303 mb->un.varCfgMSI.defaultMessageNumber = 0; 1304 1305 for (i = 1; i < intr_count; i++) { 1306 mask = intr_map[i]; 1307 1308 mb->un.varCfgMSI.attConditions |= mask; 1309 1310 #ifdef EMLXS_BIG_ENDIAN 1311 if (mask & HA_R0ATT) { 1312 mb->un.varCfgMSI.messageNumberByHA[3] = i; 1313 } 1314 if (mask & HA_R1ATT) { 1315 mb->un.varCfgMSI.messageNumberByHA[7] = i; 1316 } 1317 if (mask & HA_R2ATT) { 1318 mb->un.varCfgMSI.messageNumberByHA[11] = i; 1319 } 1320 if (mask & HA_R3ATT) { 1321 mb->un.varCfgMSI.messageNumberByHA[15] = i; 1322 } 1323 if (mask & HA_LATT) { 1324 mb->un.varCfgMSI.messageNumberByHA[29] = i; 1325 } 1326 if (mask & HA_MBATT) { 1327 mb->un.varCfgMSI.messageNumberByHA[30] = i; 1328 } 1329 if (mask & HA_ERATT) { 1330 mb->un.varCfgMSI.messageNumberByHA[31] = i; 1331 } 1332 #endif /* EMLXS_BIG_ENDIAN */ 1333 1334 #ifdef EMLXS_LITTLE_ENDIAN 1335 /* Accounts for half word swap of LE architecture */ 1336 if (mask & HA_R0ATT) { 1337 mb->un.varCfgMSI.messageNumberByHA[2] = i; 1338 } 1339 if (mask & HA_R1ATT) { 1340 mb->un.varCfgMSI.messageNumberByHA[6] = i; 1341 } 1342 if (mask & HA_R2ATT) { 1343 mb->un.varCfgMSI.messageNumberByHA[10] = i; 1344 } 1345 if (mask & HA_R3ATT) { 1346 mb->un.varCfgMSI.messageNumberByHA[14] = i; 1347 } 1348 if (mask & HA_LATT) { 1349 mb->un.varCfgMSI.messageNumberByHA[28] = i; 1350 } 1351 if (mask & HA_MBATT) { 1352 mb->un.varCfgMSI.messageNumberByHA[31] = i; 1353 } 1354 if (mask & HA_ERATT) { 1355 mb->un.varCfgMSI.messageNumberByHA[30] = i; 1356 } 1357 #endif /* EMLXS_LITTLE_ENDIAN */ 1358 } 1359 1360 mb->mbxOwner = OWN_HOST; 1361 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 1362 1363 return; 1364 1365 } /* emlxs_mb_config_msi() */ 1366 1367 1368 /*ARGSUSED*/ 1369 extern void 1370 emlxs_mb_config_msix(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t *intr_map, 1371 uint32_t intr_count) 1372 { 1373 MAILBOX *mb = (MAILBOX *)mbq; 1374 uint32_t i; 1375 uint32_t mask; 1376 1377 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1378 1379 mb->mbxCommand = MBX_CONFIG_MSIX; 1380 1381 /* Set the default message id to zero */ 1382 mb->un.varCfgMSIX.defaultPresent = 1; 1383 mb->un.varCfgMSIX.defaultMessageNumber = 0; 1384 1385 for (i = 1; i < intr_count; i++) { 1386 mask = intr_map[i]; 1387 1388 mb->un.varCfgMSIX.attConditions1 |= mask; 1389 1390 #ifdef EMLXS_BIG_ENDIAN 1391 if (mask & HA_R0ATT) { 1392 mb->un.varCfgMSIX.messageNumberByHA[3] = i; 1393 } 1394 if (mask & HA_R1ATT) { 1395 mb->un.varCfgMSIX.messageNumberByHA[7] = i; 1396 } 1397 if (mask & HA_R2ATT) { 1398 mb->un.varCfgMSIX.messageNumberByHA[11] = i; 1399 } 1400 if (mask & HA_R3ATT) { 1401 mb->un.varCfgMSIX.messageNumberByHA[15] = i; 1402 } 1403 if (mask & HA_LATT) { 1404 mb->un.varCfgMSIX.messageNumberByHA[29] = i; 1405 } 1406 if (mask & HA_MBATT) { 1407 mb->un.varCfgMSIX.messageNumberByHA[30] = i; 1408 } 1409 if (mask & HA_ERATT) { 1410 mb->un.varCfgMSIX.messageNumberByHA[31] = i; 1411 } 1412 #endif /* EMLXS_BIG_ENDIAN */ 1413 1414 #ifdef EMLXS_LITTLE_ENDIAN 1415 /* Accounts for word swap of LE architecture */ 1416 if (mask & HA_R0ATT) { 1417 mb->un.varCfgMSIX.messageNumberByHA[0] = i; 1418 } 1419 if (mask & HA_R1ATT) { 1420 mb->un.varCfgMSIX.messageNumberByHA[4] = i; 1421 } 1422 if (mask & HA_R2ATT) { 1423 mb->un.varCfgMSIX.messageNumberByHA[8] = i; 1424 } 1425 if (mask & HA_R3ATT) { 1426 mb->un.varCfgMSIX.messageNumberByHA[12] = i; 1427 } 1428 if (mask & HA_LATT) { 1429 mb->un.varCfgMSIX.messageNumberByHA[30] = i; 1430 } 1431 if (mask & HA_MBATT) { 1432 mb->un.varCfgMSIX.messageNumberByHA[29] = i; 1433 } 1434 if (mask & HA_ERATT) { 1435 mb->un.varCfgMSIX.messageNumberByHA[28] = i; 1436 } 1437 #endif /* EMLXS_LITTLE_ENDIAN */ 1438 } 1439 1440 mb->mbxOwner = OWN_HOST; 1441 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 1442 1443 return; 1444 1445 } /* emlxs_mb_config_msix() */ 1446 1447 1448 #endif /* MSI_SUPPORT */ 1449 1450 1451 /*ARGSUSED*/ 1452 extern void 1453 emlxs_mb_reset_ring(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t ringno) 1454 { 1455 MAILBOX *mb = (MAILBOX *)mbq; 1456 1457 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1458 1459 mb->mbxCommand = MBX_RESET_RING; 1460 mb->un.varRstRing.ring_no = ringno; 1461 mb->mbxOwner = OWN_HOST; 1462 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 1463 1464 return; 1465 1466 } /* emlxs_mb_reset_ring() */ 1467 1468 1469 /*ARGSUSED*/ 1470 extern void 1471 emlxs_mb_dump_vpd(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset) 1472 { 1473 1474 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1475 MAILBOX4 *mb = (MAILBOX4 *)mbq; 1476 1477 /* Clear the local dump_region */ 1478 bzero(hba->sli.sli4.dump_region.virt, 1479 hba->sli.sli4.dump_region.size); 1480 1481 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 1482 1483 mb->mbxCommand = MBX_DUMP_MEMORY; 1484 mb->un.varDmp4.type = DMP_NV_PARAMS; 1485 mb->un.varDmp4.entry_index = offset; 1486 mb->un.varDmp4.region_id = DMP_VPD_REGION; 1487 1488 mb->un.varDmp4.available_cnt = hba->sli.sli4.dump_region.size; 1489 mb->un.varDmp4.addrHigh = 1490 PADDR_HI(hba->sli.sli4.dump_region.phys); 1491 mb->un.varDmp4.addrLow = 1492 PADDR_LO(hba->sli.sli4.dump_region.phys); 1493 mb->un.varDmp4.rsp_cnt = 0; 1494 1495 mb->mbxOwner = OWN_HOST; 1496 1497 } else { 1498 MAILBOX *mb = (MAILBOX *)mbq; 1499 1500 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1501 1502 mb->mbxCommand = MBX_DUMP_MEMORY; 1503 mb->un.varDmp.cv = 1; 1504 mb->un.varDmp.type = DMP_NV_PARAMS; 1505 mb->un.varDmp.entry_index = offset; 1506 mb->un.varDmp.region_id = DMP_VPD_REGION; 1507 1508 /* limited by mailbox size */ 1509 mb->un.varDmp.word_cnt = DMP_VPD_DUMP_WCOUNT; 1510 1511 mb->un.varDmp.co = 0; 1512 mb->un.varDmp.resp_offset = 0; 1513 mb->mbxOwner = OWN_HOST; 1514 } 1515 1516 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 1517 1518 } /* emlxs_mb_dump_vpd() */ 1519 1520 1521 /*ARGSUSED*/ 1522 extern void 1523 emlxs_mb_dump_fcoe(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset) 1524 { 1525 MAILBOX4 *mb = (MAILBOX4 *)mbq; 1526 1527 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 1528 return; 1529 } 1530 /* Clear the local dump_region */ 1531 bzero(hba->sli.sli4.dump_region.virt, 1532 hba->sli.sli4.dump_region.size); 1533 1534 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 1535 1536 mb->mbxCommand = MBX_DUMP_MEMORY; 1537 mb->un.varDmp4.type = DMP_NV_PARAMS; 1538 mb->un.varDmp4.entry_index = offset; 1539 mb->un.varDmp4.region_id = DMP_FCOE_REGION; 1540 1541 mb->un.varDmp4.available_cnt = hba->sli.sli4.dump_region.size; 1542 mb->un.varDmp4.addrHigh = 1543 PADDR_HI(hba->sli.sli4.dump_region.phys); 1544 mb->un.varDmp4.addrLow = 1545 PADDR_LO(hba->sli.sli4.dump_region.phys); 1546 mb->un.varDmp4.rsp_cnt = 0; 1547 1548 mb->mbxOwner = OWN_HOST; 1549 1550 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 1551 1552 } /* emlxs_mb_dump_fcoe() */ 1553 1554 1555 /*ARGSUSED*/ 1556 extern void 1557 emlxs_mb_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset, uint32_t words) 1558 { 1559 1560 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1561 MAILBOX4 *mb = (MAILBOX4 *)mbq; 1562 1563 /* Clear the local dump_region */ 1564 bzero(hba->sli.sli4.dump_region.virt, 1565 hba->sli.sli4.dump_region.size); 1566 1567 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 1568 1569 mb->mbxCommand = MBX_DUMP_MEMORY; 1570 mb->un.varDmp4.type = DMP_MEM_REG; 1571 mb->un.varDmp4.entry_index = offset; 1572 mb->un.varDmp4.region_id = 0; 1573 1574 mb->un.varDmp4.available_cnt = min((words*4), 1575 hba->sli.sli4.dump_region.size); 1576 mb->un.varDmp4.addrHigh = 1577 PADDR_HI(hba->sli.sli4.dump_region.phys); 1578 mb->un.varDmp4.addrLow = 1579 PADDR_LO(hba->sli.sli4.dump_region.phys); 1580 mb->un.varDmp4.rsp_cnt = 0; 1581 1582 mb->mbxOwner = OWN_HOST; 1583 1584 } else { 1585 1586 MAILBOX *mb = (MAILBOX *)mbq; 1587 1588 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1589 1590 mb->mbxCommand = MBX_DUMP_MEMORY; 1591 mb->un.varDmp.type = DMP_MEM_REG; 1592 mb->un.varDmp.word_cnt = words; 1593 mb->un.varDmp.base_adr = offset; 1594 1595 mb->un.varDmp.co = 0; 1596 mb->un.varDmp.resp_offset = 0; 1597 mb->mbxOwner = OWN_HOST; 1598 } 1599 1600 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 1601 1602 return; 1603 1604 } /* emlxs_mb_dump() */ 1605 1606 1607 /* 1608 * emlxs_mb_read_nv Issue a READ NVPARAM mailbox command 1609 */ 1610 /*ARGSUSED*/ 1611 extern void 1612 emlxs_mb_read_nv(emlxs_hba_t *hba, MAILBOXQ *mbq) 1613 { 1614 MAILBOX *mb = (MAILBOX *)mbq; 1615 1616 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1617 1618 mb->mbxCommand = MBX_READ_NV; 1619 mb->mbxOwner = OWN_HOST; 1620 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 1621 1622 } /* emlxs_mb_read_nv() */ 1623 1624 1625 /* 1626 * emlxs_mb_read_rev Issue a READ REV mailbox command 1627 */ 1628 /*ARGSUSED*/ 1629 extern void 1630 emlxs_mb_read_rev(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t v3) 1631 { 1632 MAILBOX *mb = (MAILBOX *)mbq; 1633 1634 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1635 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 1636 mbq->nonembed = NULL; 1637 } else { 1638 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1639 1640 mb->un.varRdRev.cv = 1; 1641 1642 if (v3) { 1643 mb->un.varRdRev.cv3 = 1; 1644 } 1645 } 1646 1647 mb->mbxCommand = MBX_READ_REV; 1648 mb->mbxOwner = OWN_HOST; 1649 mbq->mbox_cmpl = NULL; 1650 1651 } /* emlxs_mb_read_rev() */ 1652 1653 1654 /* 1655 * emlxs_mb_run_biu_diag Issue a RUN_BIU_DIAG mailbox command 1656 */ 1657 /*ARGSUSED*/ 1658 extern uint32_t 1659 emlxs_mb_run_biu_diag(emlxs_hba_t *hba, MAILBOXQ *mbq, uint64_t out, 1660 uint64_t in) 1661 { 1662 MAILBOX *mb = (MAILBOX *)mbq; 1663 1664 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1665 1666 mb->mbxCommand = MBX_RUN_BIU_DIAG64; 1667 mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize = MEM_ELSBUF_SIZE; 1668 mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh = PADDR_HI(out); 1669 mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow = PADDR_LO(out); 1670 mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize = MEM_ELSBUF_SIZE; 1671 mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh = PADDR_HI(in); 1672 mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = PADDR_LO(in); 1673 mb->mbxOwner = OWN_HOST; 1674 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 1675 1676 return (0); 1677 } /* emlxs_mb_run_biu_diag() */ 1678 1679 1680 /* This should only be called with active MBX_NOWAIT mailboxes */ 1681 void 1682 emlxs_mb_retry(emlxs_hba_t *hba, MAILBOXQ *mbq) 1683 { 1684 MAILBOX *mb; 1685 MAILBOX *mbox; 1686 int rc; 1687 1688 mbox = (MAILBOX *)emlxs_mem_get(hba, MEM_MBOX, 1); 1689 if (!mbox) { 1690 return; 1691 } 1692 mb = (MAILBOX *)mbq; 1693 bcopy((uint8_t *)mb, (uint8_t *)mbox, MAILBOX_CMD_BSIZE); 1694 mbox->mbxOwner = OWN_HOST; 1695 mbox->mbxStatus = 0; 1696 1697 mutex_enter(&EMLXS_PORT_LOCK); 1698 1699 HBASTATS.MboxCompleted++; 1700 1701 if (mb->mbxStatus != 0) { 1702 HBASTATS.MboxError++; 1703 } else { 1704 HBASTATS.MboxGood++; 1705 } 1706 1707 hba->mbox_mbq = 0; 1708 hba->mbox_queue_flag = 0; 1709 1710 mutex_exit(&EMLXS_PORT_LOCK); 1711 1712 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0); 1713 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 1714 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbox); 1715 } 1716 return; 1717 1718 } /* emlxs_mb_retry() */ 1719 1720 1721 int 1722 emlxs_cmpl_read_la(void *arg1, MAILBOXQ *mbq) 1723 { 1724 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 1725 emlxs_port_t *port = &PPORT; 1726 MAILBOX *mb; 1727 MAILBOXQ *mbox; 1728 MATCHMAP *mp; 1729 READ_LA_VAR la; 1730 int i; 1731 uint32_t control; 1732 1733 mb = (MAILBOX *)mbq; 1734 if (mb->mbxStatus) { 1735 if (mb->mbxStatus == MBXERR_NO_RESOURCES) { 1736 control = mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize; 1737 if (control == 0) { 1738 (void) emlxs_mb_read_la(hba, mbq); 1739 } 1740 emlxs_mb_retry(hba, mbq); 1741 return (1); 1742 } 1743 /* Enable Link Attention interrupts */ 1744 mutex_enter(&EMLXS_PORT_LOCK); 1745 1746 if (!(hba->sli.sli3.hc_copy & HC_LAINT_ENA)) { 1747 hba->sli.sli3.hc_copy |= HC_LAINT_ENA; 1748 WRITE_CSR_REG(hba, FC_HC_REG(hba), 1749 hba->sli.sli3.hc_copy); 1750 #ifdef FMA_SUPPORT 1751 /* Access handle validation */ 1752 EMLXS_CHK_ACC_HANDLE(hba, 1753 hba->sli.sli3.csr_acc_handle); 1754 #endif /* FMA_SUPPORT */ 1755 } 1756 1757 mutex_exit(&EMLXS_PORT_LOCK); 1758 return (0); 1759 } 1760 bcopy((uint32_t *)((char *)mb + sizeof (uint32_t)), 1761 (uint32_t *)&la, sizeof (READ_LA_VAR)); 1762 1763 mp = (MATCHMAP *)mbq->bp; 1764 if (mp) { 1765 bcopy((caddr_t)mp->virt, (caddr_t)port->alpa_map, 128); 1766 } else { 1767 bzero((caddr_t)port->alpa_map, 128); 1768 } 1769 1770 if (la.attType == AT_LINK_UP) { 1771 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_linkup_atten_msg, 1772 "tag=%d -> %d ALPA=%x", 1773 (uint32_t)hba->link_event_tag, 1774 (uint32_t)la.eventTag, 1775 (uint32_t)la.granted_AL_PA); 1776 } else { 1777 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_linkdown_atten_msg, 1778 "tag=%d -> %d ALPA=%x", 1779 (uint32_t)hba->link_event_tag, 1780 (uint32_t)la.eventTag, 1781 (uint32_t)la.granted_AL_PA); 1782 } 1783 1784 if (la.pb) { 1785 hba->flag |= FC_BYPASSED_MODE; 1786 } else { 1787 hba->flag &= ~FC_BYPASSED_MODE; 1788 } 1789 1790 if (hba->link_event_tag == la.eventTag) { 1791 HBASTATS.LinkMultiEvent++; 1792 } else if (hba->link_event_tag + 1 < la.eventTag) { 1793 HBASTATS.LinkMultiEvent++; 1794 1795 /* Make sure link is declared down */ 1796 emlxs_linkdown(hba); 1797 } 1798 1799 hba->link_event_tag = la.eventTag; 1800 port->lip_type = 0; 1801 1802 /* If link not already up then declare it up now */ 1803 if ((la.attType == AT_LINK_UP) && (hba->state < FC_LINK_UP)) { 1804 1805 #ifdef MENLO_SUPPORT 1806 if ((hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) && 1807 (hba->flag & (FC_ILB_MODE | FC_ELB_MODE))) { 1808 la.topology = TOPOLOGY_LOOP; 1809 la.granted_AL_PA = 0; 1810 port->alpa_map[0] = 1; 1811 port->alpa_map[1] = 0; 1812 la.lipType = LT_PORT_INIT; 1813 } 1814 #endif /* MENLO_SUPPORT */ 1815 /* Save the linkspeed */ 1816 hba->linkspeed = la.UlnkSpeed; 1817 1818 /* Check for old model adapters that only */ 1819 /* supported 1Gb */ 1820 if ((hba->linkspeed == 0) && 1821 (hba->model_info.chip & EMLXS_DRAGONFLY_CHIP)) { 1822 hba->linkspeed = LA_1GHZ_LINK; 1823 } 1824 1825 if ((hba->topology = la.topology) == TOPOLOGY_LOOP) { 1826 port->did = la.granted_AL_PA; 1827 port->lip_type = la.lipType; 1828 if (hba->flag & FC_SLIM2_MODE) { 1829 i = la.un.lilpBde64.tus.f.bdeSize; 1830 } else { 1831 i = la.un.lilpBde.bdeSize; 1832 } 1833 1834 if (i == 0) { 1835 port->alpa_map[0] = 0; 1836 } else { 1837 uint8_t *alpa_map; 1838 uint32_t j; 1839 1840 /* Check number of devices in map */ 1841 if (port->alpa_map[0] > 127) { 1842 port->alpa_map[0] = 127; 1843 } 1844 1845 alpa_map = (uint8_t *)port->alpa_map; 1846 1847 EMLXS_MSGF(EMLXS_CONTEXT, 1848 &emlxs_link_atten_msg, 1849 "alpa_map: %d device(s): " 1850 "%02x %02x %02x %02x %02x %02x " 1851 "%02x", alpa_map[0], alpa_map[1], 1852 alpa_map[2], alpa_map[3], 1853 alpa_map[4], alpa_map[5], 1854 alpa_map[6], alpa_map[7]); 1855 1856 for (j = 8; j <= alpa_map[0]; j += 8) { 1857 EMLXS_MSGF(EMLXS_CONTEXT, 1858 &emlxs_link_atten_msg, 1859 "alpa_map: " 1860 "%02x %02x %02x %02x %02x " 1861 "%02x %02x %02x", 1862 alpa_map[j], 1863 alpa_map[j + 1], 1864 alpa_map[j + 2], 1865 alpa_map[j + 3], 1866 alpa_map[j + 4], 1867 alpa_map[j + 5], 1868 alpa_map[j + 6], 1869 alpa_map[j + 7]); 1870 } 1871 } 1872 } 1873 #ifdef MENLO_SUPPORT 1874 /* Check if Menlo maintenance mode is enabled */ 1875 if (hba->model_info.device_id == 1876 PCI_DEVICE_ID_LP21000_M) { 1877 if (la.mm == 1) { 1878 EMLXS_MSGF(EMLXS_CONTEXT, 1879 &emlxs_link_atten_msg, 1880 "Maintenance Mode enabled."); 1881 1882 mutex_enter(&EMLXS_PORT_LOCK); 1883 hba->flag |= FC_MENLO_MODE; 1884 mutex_exit(&EMLXS_PORT_LOCK); 1885 1886 mutex_enter(&EMLXS_LINKUP_LOCK); 1887 cv_broadcast(&EMLXS_LINKUP_CV); 1888 mutex_exit(&EMLXS_LINKUP_LOCK); 1889 } else { 1890 EMLXS_MSGF(EMLXS_CONTEXT, 1891 &emlxs_link_atten_msg, 1892 "Maintenance Mode disabled."); 1893 } 1894 1895 /* Check FCoE attention bit */ 1896 if (la.fa == 1) { 1897 emlxs_thread_spawn(hba, 1898 emlxs_fcoe_attention_thread, 1899 NULL, NULL); 1900 } 1901 } 1902 #endif /* MENLO_SUPPORT */ 1903 1904 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, 1905 MEM_MBOX, 1))) { 1906 /* This should turn on DELAYED ABTS for */ 1907 /* ELS timeouts */ 1908 emlxs_mb_set_var(hba, mbox, 0x00052198, 0x1); 1909 1910 emlxs_mb_put(hba, mbox); 1911 } 1912 1913 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, 1914 MEM_MBOX, 1))) { 1915 /* If link not already down then */ 1916 /* declare it down now */ 1917 if (emlxs_mb_read_sparam(hba, mbox) == 0) { 1918 emlxs_mb_put(hba, mbox); 1919 } else { 1920 (void) emlxs_mem_put(hba, MEM_MBOX, 1921 (uint8_t *)mbox); 1922 } 1923 } 1924 1925 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, 1926 MEM_MBOX, 1))) { 1927 emlxs_mb_config_link(hba, mbox); 1928 1929 emlxs_mb_put(hba, mbox); 1930 } 1931 1932 /* Declare the linkup here */ 1933 emlxs_linkup(hba); 1934 } 1935 1936 /* If link not already down then declare it down now */ 1937 else if (la.attType == AT_LINK_DOWN) { 1938 /* Make sure link is declared down */ 1939 emlxs_linkdown(hba); 1940 } 1941 1942 /* Enable Link attention interrupt */ 1943 mutex_enter(&EMLXS_PORT_LOCK); 1944 1945 if (!(hba->sli.sli3.hc_copy & HC_LAINT_ENA)) { 1946 hba->sli.sli3.hc_copy |= HC_LAINT_ENA; 1947 WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 1948 #ifdef FMA_SUPPORT 1949 /* Access handle validation */ 1950 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 1951 #endif /* FMA_SUPPORT */ 1952 } 1953 1954 mutex_exit(&EMLXS_PORT_LOCK); 1955 1956 /* Log the link event */ 1957 emlxs_log_link_event(port); 1958 return (0); 1959 1960 } /* emlxs_cmpl_read_la() */ 1961 1962 1963 /* 1964 * emlxs_mb_read_la Issue a READ LA mailbox command 1965 */ 1966 extern uint32_t 1967 emlxs_mb_read_la(emlxs_hba_t *hba, MAILBOXQ *mbq) 1968 { 1969 MAILBOX *mb = (MAILBOX *)mbq; 1970 MATCHMAP *mp; 1971 1972 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1973 1974 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { 1975 mb->mbxCommand = MBX_READ_LA64; 1976 1977 return (1); 1978 } 1979 1980 mb->mbxCommand = MBX_READ_LA64; 1981 mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128; 1982 mb->un.varReadLA.un.lilpBde64.addrHigh = PADDR_HI(mp->phys); 1983 mb->un.varReadLA.un.lilpBde64.addrLow = PADDR_LO(mp->phys); 1984 mb->mbxOwner = OWN_HOST; 1985 mbq->mbox_cmpl = emlxs_cmpl_read_la; 1986 1987 /* 1988 * save address for completion 1989 */ 1990 ((MAILBOXQ *)mb)->bp = (uint8_t *)mp; 1991 1992 return (0); 1993 1994 } /* emlxs_mb_read_la() */ 1995 1996 1997 int 1998 emlxs_cmpl_clear_la(void *arg1, MAILBOXQ *mbq) 1999 { 2000 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 2001 emlxs_port_t *port = &PPORT; 2002 MAILBOX *mb; 2003 MAILBOXQ *mbox; 2004 emlxs_port_t *vport; 2005 uint32_t la_enable; 2006 int i, rc; 2007 2008 mb = (MAILBOX *)mbq; 2009 if (mb->mbxStatus) { 2010 la_enable = 1; 2011 2012 if (mb->mbxStatus == 0x1601) { 2013 /* Get a buffer which will be used for */ 2014 /* mailbox commands */ 2015 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, 2016 MEM_MBOX, 1))) { 2017 /* Get link attention message */ 2018 if (emlxs_mb_read_la(hba, mbox) == 0) { 2019 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, 2020 (MAILBOX *)mbox, MBX_NOWAIT, 0); 2021 if ((rc != MBX_BUSY) && 2022 (rc != MBX_SUCCESS)) { 2023 (void) emlxs_mem_put(hba, 2024 MEM_MBOX, (uint8_t *)mbox); 2025 } 2026 la_enable = 0; 2027 } else { 2028 (void) emlxs_mem_put(hba, MEM_MBOX, 2029 (uint8_t *)mbox); 2030 } 2031 } 2032 } 2033 2034 mutex_enter(&EMLXS_PORT_LOCK); 2035 if (la_enable) { 2036 if (!(hba->sli.sli3.hc_copy & HC_LAINT_ENA)) { 2037 /* Enable Link Attention interrupts */ 2038 hba->sli.sli3.hc_copy |= HC_LAINT_ENA; 2039 WRITE_CSR_REG(hba, FC_HC_REG(hba), 2040 hba->sli.sli3.hc_copy); 2041 #ifdef FMA_SUPPORT 2042 /* Access handle validation */ 2043 EMLXS_CHK_ACC_HANDLE(hba, 2044 hba->sli.sli3.csr_acc_handle); 2045 #endif /* FMA_SUPPORT */ 2046 } 2047 } else { 2048 if (hba->sli.sli3.hc_copy & HC_LAINT_ENA) { 2049 /* Disable Link Attention interrupts */ 2050 hba->sli.sli3.hc_copy &= ~HC_LAINT_ENA; 2051 WRITE_CSR_REG(hba, FC_HC_REG(hba), 2052 hba->sli.sli3.hc_copy); 2053 #ifdef FMA_SUPPORT 2054 /* Access handle validation */ 2055 EMLXS_CHK_ACC_HANDLE(hba, 2056 hba->sli.sli3.csr_acc_handle); 2057 #endif /* FMA_SUPPORT */ 2058 } 2059 } 2060 mutex_exit(&EMLXS_PORT_LOCK); 2061 2062 return (0); 2063 } 2064 /* Enable on Link Attention interrupts */ 2065 mutex_enter(&EMLXS_PORT_LOCK); 2066 2067 if (!(hba->sli.sli3.hc_copy & HC_LAINT_ENA)) { 2068 hba->sli.sli3.hc_copy |= HC_LAINT_ENA; 2069 WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 2070 #ifdef FMA_SUPPORT 2071 /* Access handle validation */ 2072 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 2073 #endif /* FMA_SUPPORT */ 2074 } 2075 2076 if (hba->state >= FC_LINK_UP) { 2077 EMLXS_STATE_CHANGE_LOCKED(hba, FC_READY); 2078 } 2079 2080 mutex_exit(&EMLXS_PORT_LOCK); 2081 2082 /* Adapter is now ready for FCP traffic */ 2083 if (hba->state == FC_READY) { 2084 /* Register vpi's for all ports that have did's */ 2085 for (i = 0; i < MAX_VPORTS; i++) { 2086 vport = &VPORT(i); 2087 2088 if (!(vport->flag & EMLXS_PORT_BOUND) || 2089 !(vport->did)) { 2090 continue; 2091 } 2092 2093 (void) emlxs_mb_reg_vpi(vport, NULL); 2094 } 2095 2096 /* Attempt to send any pending IO */ 2097 EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[hba->channel_fcp], 0); 2098 } 2099 return (0); 2100 2101 } /* emlxs_cmpl_clear_la() */ 2102 2103 2104 /* 2105 * emlxs_mb_clear_la Issue a CLEAR LA mailbox command 2106 */ 2107 extern void 2108 emlxs_mb_clear_la(emlxs_hba_t *hba, MAILBOXQ *mbq) 2109 { 2110 MAILBOX *mb = (MAILBOX *)mbq; 2111 2112 #ifdef FC_RPI_CHECK 2113 emlxs_rpi_check(hba); 2114 #endif /* FC_RPI_CHECK */ 2115 2116 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2117 2118 mb->un.varClearLA.eventTag = hba->link_event_tag; 2119 mb->mbxCommand = MBX_CLEAR_LA; 2120 mb->mbxOwner = OWN_HOST; 2121 mbq->mbox_cmpl = emlxs_cmpl_clear_la; 2122 2123 return; 2124 2125 } /* emlxs_mb_clear_la() */ 2126 2127 2128 /* 2129 * emlxs_mb_read_status Issue a READ STATUS mailbox command 2130 */ 2131 /*ARGSUSED*/ 2132 extern void 2133 emlxs_mb_read_status(emlxs_hba_t *hba, MAILBOXQ *mbq) 2134 { 2135 MAILBOX *mb = (MAILBOX *)mbq; 2136 2137 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2138 2139 mb->mbxCommand = MBX_READ_STATUS; 2140 mb->mbxOwner = OWN_HOST; 2141 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 2142 2143 } /* fc_read_status() */ 2144 2145 2146 /* 2147 * emlxs_mb_read_lnk_stat Issue a LINK STATUS mailbox command 2148 */ 2149 /*ARGSUSED*/ 2150 extern void 2151 emlxs_mb_read_lnk_stat(emlxs_hba_t *hba, MAILBOXQ *mbq) 2152 { 2153 MAILBOX *mb = (MAILBOX *)mbq; 2154 2155 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2156 2157 mb->mbxCommand = MBX_READ_LNK_STAT; 2158 mb->mbxOwner = OWN_HOST; 2159 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 2160 2161 } /* emlxs_mb_read_lnk_stat() */ 2162 2163 2164 /* 2165 * emlxs_mb_write_nv Issue a WRITE NVPARAM mailbox command 2166 */ 2167 static void 2168 emlxs_emb_mb_write_nv(emlxs_hba_t *hba, MAILBOXQ *mbq) 2169 { 2170 MAILBOX *mb = (MAILBOX *)mbq; 2171 int32_t i; 2172 emlxs_config_t *cfg = &CFG; 2173 2174 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2175 2176 bcopy((void *)&hba->wwnn, 2177 (void *)mb->un.varWTnvp.nodename, sizeof (NAME_TYPE)); 2178 2179 bcopy((void *)&hba->wwpn, 2180 (void *)mb->un.varWTnvp.portname, sizeof (NAME_TYPE)); 2181 2182 mb->un.varWTnvp.pref_DID = 0; 2183 mb->un.varWTnvp.hardAL_PA = (uint8_t)cfg[CFG_ASSIGN_ALPA].current; 2184 mb->un.varWTnvp.rsvd1[0] = 0xffffffff; 2185 mb->un.varWTnvp.rsvd1[1] = 0xffffffff; 2186 mb->un.varWTnvp.rsvd1[2] = 0xffffffff; 2187 for (i = 0; i < 21; i++) { 2188 mb->un.varWTnvp.rsvd3[i] = 0xffffffff; 2189 } 2190 2191 mb->mbxCommand = MBX_WRITE_NV; 2192 mb->mbxOwner = OWN_HOST; 2193 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 2194 2195 } /* emlxs_mb_write_nv() */ 2196 2197 2198 /* 2199 * emlxs_mb_part_slim Issue a PARTITION SLIM mailbox command 2200 */ 2201 static void 2202 emlxs_mb_part_slim(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t hbainit) 2203 { 2204 MAILBOX *mb = (MAILBOX *)mbq; 2205 2206 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2207 2208 2209 mb->un.varSlim.numRing = hba->chan_count; 2210 mb->un.varSlim.hbainit = hbainit; 2211 mb->mbxCommand = MBX_PART_SLIM; 2212 mb->mbxOwner = OWN_HOST; 2213 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 2214 2215 } /* emlxs_mb_part_slim() */ 2216 2217 2218 /* 2219 * emlxs_mb_config_ring Issue a CONFIG RING mailbox command 2220 */ 2221 extern void 2222 emlxs_mb_config_ring(emlxs_hba_t *hba, int32_t ring, MAILBOXQ *mbq) 2223 { 2224 MAILBOX *mb = (MAILBOX *)mbq; 2225 int32_t i; 2226 int32_t j; 2227 2228 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2229 2230 j = 0; 2231 for (i = 0; i < ring; i++) { 2232 j += hba->sli.sli3.ring_masks[i]; 2233 } 2234 2235 for (i = 0; i < hba->sli.sli3.ring_masks[ring]; i++) { 2236 if ((j + i) >= 6) { 2237 break; 2238 } 2239 2240 mb->un.varCfgRing.rrRegs[i].rval = 2241 hba->sli.sli3.ring_rval[j + i]; 2242 mb->un.varCfgRing.rrRegs[i].rmask = 2243 hba->sli.sli3.ring_rmask[j + i]; 2244 mb->un.varCfgRing.rrRegs[i].tval = 2245 hba->sli.sli3.ring_tval[j + i]; 2246 mb->un.varCfgRing.rrRegs[i].tmask = 2247 hba->sli.sli3.ring_tmask[j + i]; 2248 } 2249 2250 mb->un.varCfgRing.ring = ring; 2251 mb->un.varCfgRing.profile = 0; 2252 mb->un.varCfgRing.maxOrigXchg = 0; 2253 mb->un.varCfgRing.maxRespXchg = 0; 2254 mb->un.varCfgRing.recvNotify = 1; 2255 mb->un.varCfgRing.numMask = hba->sli.sli3.ring_masks[ring]; 2256 mb->mbxCommand = MBX_CONFIG_RING; 2257 mb->mbxOwner = OWN_HOST; 2258 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 2259 2260 return; 2261 2262 } /* emlxs_mb_config_ring() */ 2263 2264 2265 /* 2266 * emlxs_mb_config_link Issue a CONFIG LINK mailbox command 2267 */ 2268 extern void 2269 emlxs_mb_config_link(emlxs_hba_t *hba, MAILBOXQ *mbq) 2270 { 2271 MAILBOX *mb = (MAILBOX *)mbq; 2272 emlxs_port_t *port = &PPORT; 2273 emlxs_config_t *cfg = &CFG; 2274 2275 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2276 2277 /* 2278 * NEW_FEATURE SLI-2, Coalescing Response Feature. 2279 */ 2280 if (cfg[CFG_CR_DELAY].current) { 2281 mb->un.varCfgLnk.cr = 1; 2282 mb->un.varCfgLnk.ci = 1; 2283 mb->un.varCfgLnk.cr_delay = cfg[CFG_CR_DELAY].current; 2284 mb->un.varCfgLnk.cr_count = cfg[CFG_CR_COUNT].current; 2285 } 2286 2287 if (cfg[CFG_ACK0].current) 2288 mb->un.varCfgLnk.ack0_enable = 1; 2289 2290 mb->un.varCfgLnk.myId = port->did; 2291 mb->un.varCfgLnk.edtov = hba->fc_edtov; 2292 mb->un.varCfgLnk.arbtov = hba->fc_arbtov; 2293 mb->un.varCfgLnk.ratov = hba->fc_ratov; 2294 mb->un.varCfgLnk.rttov = hba->fc_rttov; 2295 mb->un.varCfgLnk.altov = hba->fc_altov; 2296 mb->un.varCfgLnk.crtov = hba->fc_crtov; 2297 mb->un.varCfgLnk.citov = hba->fc_citov; 2298 mb->mbxCommand = MBX_CONFIG_LINK; 2299 mb->mbxOwner = OWN_HOST; 2300 mbq->mbox_cmpl = NULL; 2301 2302 return; 2303 2304 } /* emlxs_mb_config_link() */ 2305 2306 2307 int 2308 emlxs_cmpl_init_link(void *arg1, MAILBOXQ *mbq) 2309 { 2310 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 2311 emlxs_port_t *port = &PPORT; 2312 emlxs_config_t *cfg = &CFG; 2313 MAILBOX *mb; 2314 2315 mb = (MAILBOX *)mbq; 2316 if (mb->mbxStatus) { 2317 if ((hba->flag & FC_SLIM2_MODE) && 2318 (hba->mbox_queue_flag == MBX_NOWAIT)) { 2319 /* Retry only MBX_NOWAIT requests */ 2320 2321 if ((cfg[CFG_LINK_SPEED].current > 0) && 2322 ((mb->mbxStatus == 0x0011) || 2323 (mb->mbxStatus == 0x0500))) { 2324 2325 EMLXS_MSGF(EMLXS_CONTEXT, 2326 &emlxs_mbox_event_msg, 2327 "Retrying. %s: status=%x. Auto-speed set.", 2328 emlxs_mb_cmd_xlate(mb->mbxCommand), 2329 (uint32_t)mb->mbxStatus); 2330 2331 mb->un.varInitLnk.link_flags &= 2332 ~FLAGS_LINK_SPEED; 2333 mb->un.varInitLnk.link_speed = 0; 2334 2335 emlxs_mb_retry(hba, mbq); 2336 return (1); 2337 } 2338 } 2339 } 2340 return (0); 2341 2342 } /* emlxs_cmpl_init_link() */ 2343 2344 2345 /* 2346 * emlxs_mb_init_link Issue an INIT LINK mailbox command 2347 */ 2348 extern void 2349 emlxs_mb_init_link(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t topology, 2350 uint32_t linkspeed) 2351 { 2352 MAILBOX *mb = (MAILBOX *)mbq; 2353 emlxs_vpd_t *vpd = &VPD; 2354 emlxs_config_t *cfg = &CFG; 2355 2356 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2357 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 2358 mbq->nonembed = NULL; 2359 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 2360 2361 mb->mbxCommand = (volatile uint8_t) MBX_INIT_LINK; 2362 mb->mbxOwner = OWN_HOST; 2363 return; 2364 } 2365 2366 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2367 2368 switch (topology) { 2369 case FLAGS_LOCAL_LB: 2370 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP; 2371 mb->un.varInitLnk.link_flags |= FLAGS_LOCAL_LB; 2372 break; 2373 case FLAGS_TOPOLOGY_MODE_LOOP_PT: 2374 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP; 2375 mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER; 2376 break; 2377 case FLAGS_TOPOLOGY_MODE_PT_PT: 2378 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT; 2379 break; 2380 case FLAGS_TOPOLOGY_MODE_LOOP: 2381 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP; 2382 break; 2383 case FLAGS_TOPOLOGY_MODE_PT_LOOP: 2384 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT; 2385 mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER; 2386 break; 2387 } 2388 2389 if (cfg[CFG_LILP_ENABLE].current == 0) { 2390 /* Disable LIRP/LILP support */ 2391 mb->un.varInitLnk.link_flags |= FLAGS_LIRP_LILP; 2392 } 2393 2394 /* 2395 * Setting up the link speed 2396 */ 2397 switch (linkspeed) { 2398 case 0: 2399 break; 2400 2401 case 1: 2402 if (!(vpd->link_speed & LMT_1GB_CAPABLE)) { 2403 linkspeed = 0; 2404 } 2405 break; 2406 2407 case 2: 2408 if (!(vpd->link_speed & LMT_2GB_CAPABLE)) { 2409 linkspeed = 0; 2410 } 2411 break; 2412 2413 case 4: 2414 if (!(vpd->link_speed & LMT_4GB_CAPABLE)) { 2415 linkspeed = 0; 2416 } 2417 break; 2418 2419 case 8: 2420 if (!(vpd->link_speed & LMT_8GB_CAPABLE)) { 2421 linkspeed = 0; 2422 } 2423 break; 2424 2425 case 10: 2426 if (!(vpd->link_speed & LMT_10GB_CAPABLE)) { 2427 linkspeed = 0; 2428 } 2429 break; 2430 2431 default: 2432 linkspeed = 0; 2433 break; 2434 2435 } 2436 2437 if ((linkspeed > 0) && (vpd->feaLevelHigh >= 0x02)) { 2438 mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; 2439 mb->un.varInitLnk.link_speed = linkspeed; 2440 } 2441 2442 mb->un.varInitLnk.link_flags |= FLAGS_PREABORT_RETURN; 2443 2444 mb->un.varInitLnk.fabric_AL_PA = 2445 (uint8_t)cfg[CFG_ASSIGN_ALPA].current; 2446 mb->mbxCommand = (volatile uint8_t) MBX_INIT_LINK; 2447 mb->mbxOwner = OWN_HOST; 2448 mbq->mbox_cmpl = emlxs_cmpl_init_link; 2449 2450 2451 return; 2452 2453 } /* emlxs_mb_init_link() */ 2454 2455 2456 /* 2457 * emlxs_mb_down_link Issue a DOWN LINK mailbox command 2458 */ 2459 /*ARGSUSED*/ 2460 extern void 2461 emlxs_mb_down_link(emlxs_hba_t *hba, MAILBOXQ *mbq) 2462 { 2463 MAILBOX *mb = (MAILBOX *)mbq; 2464 2465 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2466 2467 mb->mbxCommand = MBX_DOWN_LINK; 2468 mb->mbxOwner = OWN_HOST; 2469 mbq->mbox_cmpl = NULL; 2470 2471 return; 2472 2473 } /* emlxs_mb_down_link() */ 2474 2475 2476 int 2477 emlxs_cmpl_read_sparam(void *arg1, MAILBOXQ *mbq) 2478 { 2479 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 2480 emlxs_port_t *port = &PPORT; 2481 MAILBOX *mb; 2482 MATCHMAP *mp; 2483 emlxs_port_t *vport; 2484 int32_t i; 2485 uint32_t control; 2486 uint8_t null_wwn[8]; 2487 2488 mb = (MAILBOX *)mbq; 2489 if (mb->mbxStatus) { 2490 if (mb->mbxStatus == MBXERR_NO_RESOURCES) { 2491 control = mb->un.varRdSparm.un.sp64.tus.f.bdeSize; 2492 if (control == 0) { 2493 (void) emlxs_mb_read_sparam(hba, mbq); 2494 } 2495 emlxs_mb_retry(hba, mbq); 2496 return (1); 2497 } 2498 return (0); 2499 } 2500 mp = (MATCHMAP *)mbq->bp; 2501 if (!mp) { 2502 return (0); 2503 } 2504 2505 bcopy((caddr_t)mp->virt, (caddr_t)&hba->sparam, sizeof (SERV_PARM)); 2506 2507 /* Initialize the node name and port name only once */ 2508 bzero(null_wwn, 8); 2509 if ((bcmp((caddr_t)&hba->wwnn, (caddr_t)null_wwn, 8) == 0) && 2510 (bcmp((caddr_t)&hba->wwpn, (caddr_t)null_wwn, 8) == 0)) { 2511 bcopy((caddr_t)&hba->sparam.nodeName, 2512 (caddr_t)&hba->wwnn, sizeof (NAME_TYPE)); 2513 2514 bcopy((caddr_t)&hba->sparam.portName, 2515 (caddr_t)&hba->wwpn, sizeof (NAME_TYPE)); 2516 } else { 2517 bcopy((caddr_t)&hba->wwnn, 2518 (caddr_t)&hba->sparam.nodeName, sizeof (NAME_TYPE)); 2519 2520 bcopy((caddr_t)&hba->wwpn, 2521 (caddr_t)&hba->sparam.portName, sizeof (NAME_TYPE)); 2522 } 2523 2524 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 2525 "SPARAM: EDTOV hba=x%x mbox_csp=x%x, BBC=x%x", 2526 hba->fc_edtov, hba->sparam.cmn.e_d_tov, 2527 hba->sparam.cmn.bbCreditlsb); 2528 2529 hba->sparam.cmn.e_d_tov = hba->fc_edtov; 2530 2531 /* Initialize the physical port */ 2532 bcopy((caddr_t)&hba->sparam, 2533 (caddr_t)&port->sparam, sizeof (SERV_PARM)); 2534 bcopy((caddr_t)&hba->wwpn, (caddr_t)&port->wwpn, 2535 sizeof (NAME_TYPE)); 2536 bcopy((caddr_t)&hba->wwnn, (caddr_t)&port->wwnn, 2537 sizeof (NAME_TYPE)); 2538 2539 /* Initialize the virtual ports */ 2540 for (i = 1; i < MAX_VPORTS; i++) { 2541 vport = &VPORT(i); 2542 if (vport->flag & EMLXS_PORT_BOUND) { 2543 continue; 2544 } 2545 2546 bcopy((caddr_t)&hba->sparam, 2547 (caddr_t)&vport->sparam, 2548 sizeof (SERV_PARM)); 2549 2550 bcopy((caddr_t)&vport->wwnn, 2551 (caddr_t)&vport->sparam.nodeName, 2552 sizeof (NAME_TYPE)); 2553 2554 bcopy((caddr_t)&vport->wwpn, 2555 (caddr_t)&vport->sparam.portName, 2556 sizeof (NAME_TYPE)); 2557 } 2558 2559 return (0); 2560 2561 } /* emlxs_cmpl_read_sparam() */ 2562 2563 2564 /* 2565 * emlxs_mb_read_sparam Issue a READ SPARAM mailbox command 2566 */ 2567 extern uint32_t 2568 emlxs_mb_read_sparam(emlxs_hba_t *hba, MAILBOXQ *mbq) 2569 { 2570 MAILBOX *mb = (MAILBOX *)mbq; 2571 MATCHMAP *mp; 2572 2573 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2574 2575 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { 2576 mb->mbxCommand = MBX_READ_SPARM64; 2577 2578 return (1); 2579 } 2580 2581 mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM); 2582 mb->un.varRdSparm.un.sp64.addrHigh = PADDR_HI(mp->phys); 2583 mb->un.varRdSparm.un.sp64.addrLow = PADDR_LO(mp->phys); 2584 mb->mbxCommand = MBX_READ_SPARM64; 2585 mb->mbxOwner = OWN_HOST; 2586 mbq->mbox_cmpl = emlxs_cmpl_read_sparam; 2587 2588 /* 2589 * save address for completion 2590 */ 2591 mbq->bp = (uint8_t *)mp; 2592 2593 return (0); 2594 2595 } /* emlxs_mb_read_sparam() */ 2596 2597 2598 /* 2599 * emlxs_mb_read_rpi Issue a READ RPI mailbox command 2600 */ 2601 /*ARGSUSED*/ 2602 extern uint32_t 2603 emlxs_mb_read_rpi(emlxs_hba_t *hba, uint32_t rpi, MAILBOXQ *mbq, 2604 uint32_t flag) 2605 { 2606 MAILBOX *mb = (MAILBOX *)mbq; 2607 2608 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2609 2610 /* 2611 * Set flag to issue action on cmpl 2612 */ 2613 mb->un.varWords[30] = flag; 2614 mb->un.varRdRPI.reqRpi = (volatile uint16_t) rpi; 2615 mb->mbxCommand = MBX_READ_RPI64; 2616 mb->mbxOwner = OWN_HOST; 2617 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 2618 2619 return (0); 2620 } /* emlxs_mb_read_rpi() */ 2621 2622 2623 /* 2624 * emlxs_mb_read_xri Issue a READ XRI mailbox command 2625 */ 2626 /*ARGSUSED*/ 2627 extern uint32_t 2628 emlxs_mb_read_xri(emlxs_hba_t *hba, uint32_t xri, MAILBOXQ *mbq, 2629 uint32_t flag) 2630 { 2631 MAILBOX *mb = (MAILBOX *)mbq; 2632 2633 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2634 2635 /* 2636 * Set flag to issue action on cmpl 2637 */ 2638 mb->un.varWords[30] = flag; 2639 mb->un.varRdXRI.reqXri = (volatile uint16_t)xri; 2640 mb->mbxCommand = MBX_READ_XRI; 2641 mb->mbxOwner = OWN_HOST; 2642 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 2643 2644 return (0); 2645 } /* emlxs_mb_read_xri() */ 2646 2647 2648 /*ARGSUSED*/ 2649 extern int32_t 2650 emlxs_mb_check_sparm(emlxs_hba_t *hba, SERV_PARM *nsp) 2651 { 2652 uint32_t nsp_value; 2653 uint32_t *iptr; 2654 2655 if (nsp->cmn.fPort) { 2656 return (0); 2657 } 2658 2659 /* Validate the service parameters */ 2660 iptr = (uint32_t *)&nsp->portName; 2661 if (iptr[0] == 0 && iptr[1] == 0) { 2662 return (1); 2663 } 2664 2665 iptr = (uint32_t *)&nsp->nodeName; 2666 if (iptr[0] == 0 && iptr[1] == 0) { 2667 return (2); 2668 } 2669 2670 if (nsp->cls2.classValid) { 2671 nsp_value = 2672 ((nsp->cls2.rcvDataSizeMsb & 0x0f) << 8) | nsp->cls2. 2673 rcvDataSizeLsb; 2674 2675 /* If the receive data length is zero then set it to */ 2676 /* the CSP value */ 2677 if (!nsp_value) { 2678 nsp->cls2.rcvDataSizeMsb = nsp->cmn.bbRcvSizeMsb; 2679 nsp->cls2.rcvDataSizeLsb = nsp->cmn.bbRcvSizeLsb; 2680 return (0); 2681 } 2682 } 2683 2684 if (nsp->cls3.classValid) { 2685 nsp_value = 2686 ((nsp->cls3.rcvDataSizeMsb & 0x0f) << 8) | nsp->cls3. 2687 rcvDataSizeLsb; 2688 2689 /* If the receive data length is zero then set it to */ 2690 /* the CSP value */ 2691 if (!nsp_value) { 2692 nsp->cls3.rcvDataSizeMsb = nsp->cmn.bbRcvSizeMsb; 2693 nsp->cls3.rcvDataSizeLsb = nsp->cmn.bbRcvSizeLsb; 2694 return (0); 2695 } 2696 } 2697 2698 return (0); 2699 2700 } /* emlxs_mb_check_sparm() */ 2701 2702 2703 int 2704 emlxs_cmpl_reg_did(void *arg1, MAILBOXQ *mbq) 2705 { 2706 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 2707 emlxs_port_t *port = &PPORT; 2708 MAILBOX *mb; 2709 MATCHMAP *mp; 2710 NODELIST *ndlp; 2711 emlxs_port_t *vport; 2712 uint8_t *wwn; 2713 volatile SERV_PARM *sp; 2714 int32_t i; 2715 uint32_t control; 2716 uint32_t ldata; 2717 uint32_t ldid; 2718 uint16_t lrpi; 2719 uint16_t lvpi; 2720 emlxs_vvl_fmt_t vvl; 2721 2722 mb = (MAILBOX *)mbq; 2723 if (mb->mbxStatus) { 2724 if (mb->mbxStatus == MBXERR_NO_RESOURCES) { 2725 control = mb->un.varRegLogin.un.sp.bdeSize; 2726 if (control == 0) { 2727 /* Special handle for vport PLOGI */ 2728 if (mbq->iocbq == (uint8_t *)1) { 2729 mbq->iocbq = NULL; 2730 } 2731 return (0); 2732 } 2733 emlxs_mb_retry(hba, mbq); 2734 return (1); 2735 } 2736 if (mb->mbxStatus == MBXERR_RPI_FULL) { 2737 port = &VPORT((mb->un.varRegLogin.vpi - hba->vpi_base)); 2738 2739 EMLXS_MSGF(EMLXS_CONTEXT, 2740 &emlxs_node_create_failed_msg, 2741 "Limit reached. count=%d", port->node_count); 2742 } 2743 2744 /* Special handle for vport PLOGI */ 2745 if (mbq->iocbq == (uint8_t *)1) { 2746 mbq->iocbq = NULL; 2747 } 2748 2749 return (0); 2750 } 2751 2752 mp = (MATCHMAP *)mbq->bp; 2753 if (!mp) { 2754 return (0); 2755 } 2756 ldata = mb->un.varWords[5]; 2757 lvpi = (ldata & 0xffff) - hba->vpi_base; 2758 port = &VPORT(lvpi); 2759 2760 /* First copy command data */ 2761 ldata = mb->un.varWords[0]; /* get rpi */ 2762 lrpi = ldata & 0xffff; 2763 2764 ldata = mb->un.varWords[1]; /* get did */ 2765 ldid = ldata & MASK_DID; 2766 2767 sp = (volatile SERV_PARM *)mp->virt; 2768 ndlp = emlxs_node_find_did(port, ldid); 2769 2770 if (!ndlp) { 2771 /* Attempt to create a node */ 2772 if ((ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP, 0))) { 2773 ndlp->nlp_Rpi = lrpi; 2774 ndlp->nlp_DID = ldid; 2775 2776 bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm, 2777 sizeof (SERV_PARM)); 2778 2779 bcopy((uint8_t *)&sp->nodeName, 2780 (uint8_t *)&ndlp->nlp_nodename, 2781 sizeof (NAME_TYPE)); 2782 2783 bcopy((uint8_t *)&sp->portName, 2784 (uint8_t *)&ndlp->nlp_portname, 2785 sizeof (NAME_TYPE)); 2786 2787 ndlp->nlp_active = 1; 2788 ndlp->nlp_flag[hba->channel_ct] |= NLP_CLOSED; 2789 ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED; 2790 ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED; 2791 ndlp->nlp_flag[hba->channel_ip] |= NLP_CLOSED; 2792 2793 /* Add the node */ 2794 emlxs_node_add(port, ndlp); 2795 2796 /* Open the node */ 2797 emlxs_node_open(port, ndlp, hba->channel_ct); 2798 emlxs_node_open(port, ndlp, hba->channel_els); 2799 emlxs_node_open(port, ndlp, hba->channel_ip); 2800 emlxs_node_open(port, ndlp, hba->channel_fcp); 2801 } else { 2802 wwn = (uint8_t *)&sp->portName; 2803 EMLXS_MSGF(EMLXS_CONTEXT, 2804 &emlxs_node_create_failed_msg, 2805 "Unable to allocate node. did=%06x rpi=%x " 2806 "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", 2807 ldid, lrpi, wwn[0], wwn[1], wwn[2], 2808 wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 2809 2810 return (0); 2811 } 2812 } else { 2813 mutex_enter(&EMLXS_PORT_LOCK); 2814 2815 ndlp->nlp_Rpi = lrpi; 2816 ndlp->nlp_DID = ldid; 2817 2818 bcopy((uint8_t *)sp, 2819 (uint8_t *)&ndlp->sparm, sizeof (SERV_PARM)); 2820 2821 bcopy((uint8_t *)&sp->nodeName, 2822 (uint8_t *)&ndlp->nlp_nodename, sizeof (NAME_TYPE)); 2823 2824 bcopy((uint8_t *)&sp->portName, 2825 (uint8_t *)&ndlp->nlp_portname, sizeof (NAME_TYPE)); 2826 2827 wwn = (uint8_t *)&ndlp->nlp_portname; 2828 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg, 2829 "node=%p did=%06x rpi=%x " 2830 "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", 2831 ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], 2832 wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 2833 2834 mutex_exit(&EMLXS_PORT_LOCK); 2835 2836 /* Open the node */ 2837 emlxs_node_open(port, ndlp, hba->channel_ct); 2838 emlxs_node_open(port, ndlp, hba->channel_els); 2839 emlxs_node_open(port, ndlp, hba->channel_ip); 2840 emlxs_node_open(port, ndlp, hba->channel_fcp); 2841 } 2842 2843 bzero((char *)&vvl, sizeof (emlxs_vvl_fmt_t)); 2844 2845 if (sp->VALID_VENDOR_VERSION) { 2846 2847 bcopy((caddr_t *)&sp->vendorVersion[0], 2848 (caddr_t *)&vvl, sizeof (emlxs_vvl_fmt_t)); 2849 2850 vvl.un0.word0 = LE_SWAP32(vvl.un0.word0); 2851 vvl.un1.word1 = LE_SWAP32(vvl.un1.word1); 2852 2853 if ((vvl.un0.w0.oui == 0x0000C9) && 2854 (vvl.un1.w1.vport)) { 2855 ndlp->nlp_fcp_info |= NLP_EMLX_VPORT; 2856 } 2857 } 2858 2859 if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && 2860 (ndlp->nlp_DID == NAMESERVER_DID)) { 2861 EMLXS_STATE_CHANGE_LOCKED(hba, FC_READY); 2862 } 2863 2864 /* If this was a fabric login */ 2865 if (ndlp->nlp_DID == FABRIC_DID) { 2866 /* If CLEAR_LA has been sent, then attempt to */ 2867 /* register the vpi now */ 2868 if (hba->state == FC_READY) { 2869 (void) emlxs_mb_reg_vpi(port, NULL); 2870 } 2871 2872 /* 2873 * If NPIV Fabric support has just been established on 2874 * the physical port, then notify the vports of the 2875 * link up 2876 */ 2877 if ((lvpi == 0) && 2878 (hba->flag & FC_NPIV_ENABLED) && 2879 (hba->flag & FC_NPIV_SUPPORTED)) { 2880 /* Skip the physical port */ 2881 for (i = 1; i < MAX_VPORTS; i++) { 2882 vport = &VPORT(i); 2883 2884 if (!(vport->flag & EMLXS_PORT_BOUND) || 2885 !(vport->flag & EMLXS_PORT_ENABLE)) { 2886 continue; 2887 } 2888 2889 emlxs_port_online(vport); 2890 } 2891 } 2892 } 2893 2894 if (mbq->iocbq == (uint8_t *)1) { 2895 mbq->iocbq = NULL; 2896 (void) emlxs_mb_unreg_did(port, ldid, NULL, NULL, NULL); 2897 } 2898 2899 #ifdef DHCHAP_SUPPORT 2900 if (mbq->sbp || mbq->ubp) { 2901 if (emlxs_dhc_auth_start(port, ndlp, mbq->sbp, 2902 mbq->ubp) == 0) { 2903 /* Auth started - auth completion will */ 2904 /* handle sbp and ubp now */ 2905 mbq->sbp = NULL; 2906 mbq->ubp = NULL; 2907 } 2908 } 2909 #endif /* DHCHAP_SUPPORT */ 2910 2911 #ifdef SFCT_SUPPORT 2912 if (mbq->sbp && ((emlxs_buf_t *)mbq->sbp)->fct_cmd) { 2913 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)mbq->sbp; 2914 2915 if (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) { 2916 mbq->sbp = NULL; 2917 2918 mutex_enter(&EMLXS_PKT_LOCK); 2919 cmd_sbp->node = ndlp; 2920 cv_broadcast(&EMLXS_PKT_CV); 2921 mutex_exit(&EMLXS_PKT_LOCK); 2922 } 2923 } 2924 #endif /* SFCT_SUPPORT */ 2925 return (0); 2926 2927 } /* emlxs_cmpl_reg_did() */ 2928 2929 2930 /* 2931 * emlxs_mb_reg_did Issue a REG_LOGIN mailbox command 2932 */ 2933 extern uint32_t 2934 emlxs_mb_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param, 2935 emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq) 2936 { 2937 emlxs_hba_t *hba = HBA; 2938 MATCHMAP *mp; 2939 MAILBOXQ *mbq; 2940 MAILBOX *mb; 2941 NODELIST *node; 2942 RPIobj_t *rp = NULL; 2943 uint32_t rval; 2944 2945 /* Check for invalid node ids to register */ 2946 if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) { 2947 return (1); 2948 } 2949 2950 if (did & 0xff000000) { 2951 return (1); 2952 } 2953 2954 if ((rval = emlxs_mb_check_sparm(hba, param))) { 2955 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 2956 "Invalid service parameters. did=%06x rval=%d", did, 2957 rval); 2958 2959 return (1); 2960 } 2961 2962 /* Check if the node limit has been reached */ 2963 if (port->node_count >= hba->max_nodes) { 2964 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 2965 "Limit reached. did=%06x count=%d", did, 2966 port->node_count); 2967 2968 return (1); 2969 } 2970 2971 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 2972 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 2973 "Unable to allocate mailbox. did=%x", did); 2974 2975 return (1); 2976 } 2977 mb = (MAILBOX *)mbq->mbox; 2978 2979 /* Build login request */ 2980 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { 2981 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 2982 "Unable to allocate buffer. did=%x", did); 2983 2984 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 2985 return (1); 2986 } 2987 2988 /* 2989 * If we are SLI4, the RPI number gets assigned by the driver. 2990 * For SLI3, the firmware assigns the RPI number. 2991 */ 2992 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2993 node = emlxs_node_find_did(port, did); 2994 rp = EMLXS_NODE_TO_RPI(hba, node); 2995 2996 if (!rp) { 2997 rp = emlxs_sli4_alloc_rpi(port); 2998 } 2999 3000 if (!rp) { 3001 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 3002 "Unable to get an rpi. did=%x", did); 3003 3004 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 3005 return (1); 3006 } 3007 rp->state &= ~RESOURCE_RPI_PAUSED; 3008 } 3009 3010 bcopy((void *)param, (void *)mp->virt, sizeof (SERV_PARM)); 3011 3012 mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM); 3013 mb->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(mp->phys); 3014 mb->un.varRegLogin.un.sp64.addrLow = PADDR_LO(mp->phys); 3015 mb->un.varRegLogin.did = did; 3016 mb->un.varWords[30] = 0; /* flags */ 3017 mb->mbxCommand = MBX_REG_LOGIN64; 3018 mb->mbxOwner = OWN_HOST; 3019 mb->un.varRegLogin.vpi = port->vpi + hba->vpi_base; 3020 mb->un.varRegLogin.rpi = (rp)? rp->RPI: 0; 3021 3022 mbq->sbp = (uint8_t *)sbp; 3023 mbq->ubp = (uint8_t *)ubp; 3024 mbq->iocbq = (uint8_t *)iocbq; 3025 mbq->bp = (uint8_t *)mp; 3026 mbq->mbox_cmpl = emlxs_cmpl_reg_did; 3027 3028 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 3029 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 3030 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 3031 if (rp) { 3032 emlxs_sli4_free_rpi(hba, rp); 3033 } 3034 } 3035 3036 return (0); 3037 3038 } /* emlxs_mb_reg_did() */ 3039 3040 /* 3041 * emlxs_mb_unreg_rpi Issue a UNREG_LOGIN mailbox command 3042 */ 3043 extern uint32_t 3044 emlxs_mb_unreg_rpi(emlxs_port_t *port, uint32_t rpi, emlxs_buf_t *sbp, 3045 fc_unsol_buf_t *ubp, IOCBQ *iocbq) 3046 { 3047 emlxs_hba_t *hba = HBA; 3048 MAILBOXQ *mbq; 3049 MAILBOX *mb; 3050 NODELIST *ndlp; 3051 int rval; 3052 3053 if (rpi != 0xffff) { 3054 /* Make sure the node does already exist */ 3055 ndlp = emlxs_node_find_rpi(port, rpi); 3056 3057 3058 if (ndlp) { 3059 /* 3060 * If we just unregistered the host node then 3061 * clear the host DID 3062 */ 3063 if (ndlp->nlp_DID == port->did) { 3064 port->did = 0; 3065 } 3066 3067 /* remove it */ 3068 emlxs_node_rm(port, ndlp); 3069 3070 } else { 3071 return (1); 3072 } 3073 } else { /* Unreg all */ 3074 3075 emlxs_node_destroy_all(port); 3076 } 3077 3078 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 3079 return (1); 3080 } 3081 3082 mb = (MAILBOX *)mbq->mbox; 3083 3084 #define INDEX_INDICATOR_VPI 1 3085 3086 if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && (rpi == 0xffff)) { 3087 mb->un.varUnregLogin.ll = INDEX_INDICATOR_VPI; 3088 mb->un.varUnregLogin.rpi = (uint16_t)port->vpi + hba->vpi_base; 3089 } else { 3090 mb->un.varUnregLogin.rpi = (uint16_t)rpi; 3091 } 3092 3093 mb->un.varUnregLogin.vpi = port->vpi + hba->vpi_base; 3094 mb->mbxCommand = MBX_UNREG_LOGIN; 3095 mb->mbxOwner = OWN_HOST; 3096 mbq->sbp = (uint8_t *)sbp; 3097 mbq->ubp = (uint8_t *)ubp; 3098 mbq->iocbq = (uint8_t *)iocbq; 3099 mbq->mbox_cmpl = NULL; 3100 3101 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 3102 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 3103 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 3104 } 3105 3106 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3107 port->outstandingRPIs--; 3108 if ((port->outstandingRPIs == 0) && 3109 (hba->state == FC_LINK_DOWN)) { 3110 /* No more RPIs so unreg the VPI */ 3111 (void) emlxs_mb_unreg_vpi(port); 3112 } 3113 } 3114 3115 return (0); 3116 } /* emlxs_mb_unreg_rpi() */ 3117 3118 3119 /* 3120 * emlxs_mb_unreg_did Issue a UNREG_DID mailbox command 3121 */ 3122 extern uint32_t 3123 emlxs_mb_unreg_did(emlxs_port_t *port, uint32_t did, emlxs_buf_t *sbp, 3124 fc_unsol_buf_t *ubp, IOCBQ *iocbq) 3125 { 3126 emlxs_hba_t *hba = HBA; 3127 NODELIST *ndlp; 3128 MAILBOXQ *mbq; 3129 MAILBOX *mb; 3130 int rval = 0; 3131 3132 /* 3133 * Unregister all default RPIs if did == 0xffffffff 3134 */ 3135 if (did != 0xffffffff) { 3136 /* Check for base node */ 3137 if (did == BCAST_DID) { 3138 /* just flush base node */ 3139 (void) emlxs_tx_node_flush(port, &port->node_base, 3140 0, 0, 0); 3141 (void) emlxs_chipq_node_flush(port, 0, 3142 &port->node_base, 0); 3143 3144 /* Return now */ 3145 return (1); 3146 } 3147 3148 3149 /* 3150 * A zero DID means that we are trying to unreg the host node 3151 * after a link bounce 3152 */ 3153 3154 /* 3155 * If the prev_did == 0 then the adapter has been reset and 3156 * there is no need in unregistering 3157 */ 3158 3159 /* 3160 * If the prev_did != 0 then we can look for the hosts 3161 * last known DID node 3162 */ 3163 3164 if (did == 0) { 3165 if (port->prev_did == 0) { 3166 return (1); 3167 } 3168 3169 did = port->prev_did; 3170 } 3171 3172 /* Make sure the node does already exist */ 3173 ndlp = emlxs_node_find_did(port, did); 3174 3175 if (ndlp) { 3176 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3177 /* Use UNREG_RPI for SLI4 */ 3178 if (ndlp->nlp_Rpi != 0xffff) { 3179 rval = emlxs_mb_unreg_rpi(port, 3180 ndlp->nlp_Rpi, sbp, ubp, iocbq); 3181 } 3182 return (rval); 3183 } 3184 /* remove it */ 3185 emlxs_node_rm(port, ndlp); 3186 3187 /* 3188 * If we just unregistered the host node then 3189 * clear the host DID 3190 */ 3191 if (did == port->did) { 3192 port->did = 0; 3193 } 3194 3195 } else { 3196 return (1); 3197 } 3198 } else { 3199 /* SLI4 doesn't have dflt RPIs in SLI Port */ 3200 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3201 return (0); 3202 } 3203 } 3204 3205 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 3206 return (1); 3207 } 3208 3209 mb = (MAILBOX *)mbq->mbox; 3210 mb->un.varUnregDID.did = did; 3211 mb->un.varUnregDID.vpi = port->vpi + hba->vpi_base; 3212 mb->mbxCommand = MBX_UNREG_D_ID; 3213 mb->mbxOwner = OWN_HOST; 3214 mbq->sbp = (uint8_t *)sbp; 3215 mbq->ubp = (uint8_t *)ubp; 3216 mbq->iocbq = (uint8_t *)iocbq; 3217 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 3218 3219 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 3220 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 3221 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 3222 } 3223 3224 return (0); 3225 3226 } /* emlxs_mb_unreg_did() */ 3227 3228 3229 /* 3230 * emlxs_mb_set_mask Issue a SET MASK mailbox command 3231 */ 3232 /*ARGSUSED*/ 3233 static void 3234 emlxs_mb_set_mask(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t mask, 3235 uint32_t ringno) 3236 { 3237 MAILBOX *mb = (MAILBOX *)mbq; 3238 3239 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3240 3241 mb->un.varWords[0] = 0x11223344; /* set passwd */ 3242 mb->un.varWords[1] = mask; /* set mask */ 3243 mb->un.varWords[2] = ringno; /* set ringno */ 3244 mb->mbxCommand = MBX_SET_MASK; 3245 mb->mbxOwner = OWN_HOST; 3246 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 3247 3248 } /* emlxs_mb_set_mask() */ 3249 3250 3251 /* 3252 * emlxs_mb_set_debug Issue a special debug mailbox command 3253 */ 3254 /*ARGSUSED*/ 3255 static void 3256 emlxs_mb_set_debug(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t word0, 3257 uint32_t word1, uint32_t word2) 3258 { 3259 MAILBOX *mb = (MAILBOX *)mbq; 3260 3261 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3262 3263 mb->un.varWords[0] = word0; 3264 mb->un.varWords[1] = word1; 3265 mb->un.varWords[2] = word2; 3266 mb->mbxCommand = MBX_SET_DEBUG; 3267 mb->mbxOwner = OWN_HOST; 3268 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 3269 3270 } /* emlxs_mb_set_debug() */ 3271 3272 3273 /* 3274 * emlxs_mb_set_var Issue a special debug mbox command to write slim 3275 */ 3276 /*ARGSUSED*/ 3277 extern void 3278 emlxs_mb_set_var(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t addr, 3279 uint32_t value) 3280 { 3281 MAILBOX *mb = (MAILBOX *)mbq; 3282 3283 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3284 3285 /* addr = 0x090597 is AUTO ABTS disable for ELS commands */ 3286 /* addr = 0x052198 is DELAYED ABTS enable for ELS commands */ 3287 /* addr = 0x100506 is for setting PCI MAX READ value */ 3288 3289 /* 3290 * Always turn on DELAYED ABTS for ELS timeouts 3291 */ 3292 if ((addr == 0x052198) && (value == 0)) { 3293 value = 1; 3294 } 3295 3296 mb->un.varWords[0] = addr; 3297 mb->un.varWords[1] = value; 3298 mb->mbxCommand = MBX_SET_VARIABLE; 3299 mb->mbxOwner = OWN_HOST; 3300 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 3301 3302 } /* emlxs_mb_set_var() */ 3303 3304 3305 /* 3306 * Disable Traffic Cop 3307 */ 3308 /*ARGSUSED*/ 3309 extern void 3310 emlxs_disable_tc(emlxs_hba_t *hba, MAILBOXQ *mbq) 3311 { 3312 MAILBOX *mb = (MAILBOX *)mbq; 3313 3314 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3315 3316 mb->un.varWords[0] = 0x50797; 3317 mb->un.varWords[1] = 0; 3318 mb->un.varWords[2] = 0xfffffffe; 3319 mb->mbxCommand = MBX_SET_VARIABLE; 3320 mb->mbxOwner = OWN_HOST; 3321 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 3322 3323 } /* emlxs_disable_tc() */ 3324 3325 3326 extern void 3327 emlxs_mb_config_hbq(emlxs_hba_t *hba, MAILBOXQ *mbq, int hbq_id) 3328 { 3329 HBQ_INIT_t *hbq; 3330 MAILBOX *mb = (MAILBOX *)mbq; 3331 int i; 3332 3333 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3334 3335 hbq = &hba->sli.sli3.hbq_table[hbq_id]; 3336 3337 mb->un.varCfgHbq.hbqId = hbq_id; 3338 mb->un.varCfgHbq.numEntries = hbq->HBQ_numEntries; 3339 mb->un.varCfgHbq.recvNotify = hbq->HBQ_recvNotify; 3340 mb->un.varCfgHbq.numMask = hbq->HBQ_num_mask; 3341 mb->un.varCfgHbq.profile = hbq->HBQ_profile; 3342 mb->un.varCfgHbq.ringMask = hbq->HBQ_ringMask; 3343 mb->un.varCfgHbq.headerLen = hbq->HBQ_headerLen; 3344 mb->un.varCfgHbq.logEntry = hbq->HBQ_logEntry; 3345 mb->un.varCfgHbq.hbqaddrLow = PADDR_LO(hbq->HBQ_host_buf.phys); 3346 mb->un.varCfgHbq.hbqaddrHigh = PADDR_HI(hbq->HBQ_host_buf.phys); 3347 mb->mbxCommand = MBX_CONFIG_HBQ; 3348 mb->mbxOwner = OWN_HOST; 3349 mbq->mbox_cmpl = NULL; 3350 3351 /* Copy info for profiles 2,3,5. Other profiles this area is reserved */ 3352 if ((hbq->HBQ_profile == 2) || (hbq->HBQ_profile == 3) || 3353 (hbq->HBQ_profile == 5)) { 3354 bcopy(&hbq->profiles.allprofiles, 3355 &mb->un.varCfgHbq.profiles.allprofiles, 3356 sizeof (hbq->profiles)); 3357 } 3358 3359 /* Return if no rctl / type masks for this HBQ */ 3360 if (!hbq->HBQ_num_mask) { 3361 return; 3362 } 3363 3364 /* Otherwise we setup specific rctl / type masks for this HBQ */ 3365 for (i = 0; i < hbq->HBQ_num_mask; i++) { 3366 mb->un.varCfgHbq.hbqMasks[i].tmatch = 3367 hbq->HBQ_Masks[i].tmatch; 3368 mb->un.varCfgHbq.hbqMasks[i].tmask = hbq->HBQ_Masks[i].tmask; 3369 mb->un.varCfgHbq.hbqMasks[i].rctlmatch = 3370 hbq->HBQ_Masks[i].rctlmatch; 3371 mb->un.varCfgHbq.hbqMasks[i].rctlmask = 3372 hbq->HBQ_Masks[i].rctlmask; 3373 } 3374 3375 return; 3376 3377 } /* emlxs_mb_config_hbq() */ 3378 3379 int 3380 emlxs_cmpl_init_vpi(void *arg1, MAILBOXQ *mbq) 3381 { 3382 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 3383 emlxs_port_t *port = &PPORT; 3384 emlxs_port_t *vport; 3385 MAILBOX4 *mb; 3386 3387 mb = (MAILBOX4 *)mbq; 3388 3389 if (mb->mbxStatus == MBX_SUCCESS) { 3390 vport = &VPORT((mb->un.varInitVPI4.vpi - hba->vpi_base)); 3391 vport->flag |= EMLXS_PORT_INIT_VPI_CMPL; 3392 } 3393 3394 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 3395 "CMPL init_vpi: stats: %x", mb->mbxStatus); 3396 3397 return (0); 3398 3399 } /* emlxs_cmpl_init_vpi() */ 3400 3401 3402 extern uint32_t 3403 emlxs_mb_init_vpi(emlxs_port_t *port) 3404 { 3405 emlxs_hba_t *hba = HBA; 3406 emlxs_port_t *phy_port = &PPORT; 3407 MAILBOXQ *mbq; 3408 MAILBOX4 *mb; 3409 int rval; 3410 3411 if (!(hba->flag & FC_NPIV_ENABLED)) { 3412 return (0); 3413 } 3414 3415 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 3416 return (1); 3417 } 3418 3419 3420 mb = (MAILBOX4 *)mbq->mbox; 3421 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 3422 mbq->nonembed = NULL; 3423 mb->un.varInitVPI4.vfi = phy_port->VFIp->VFI; 3424 mb->un.varInitVPI4.vpi = port->vpi + hba->vpi_base; 3425 mb->mbxCommand = MBX_INIT_VPI; 3426 mb->mbxOwner = OWN_HOST; 3427 mbq->mbox_cmpl = emlxs_cmpl_init_vpi; 3428 3429 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0); 3430 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 3431 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 3432 } 3433 3434 return (0); 3435 3436 } /* emlxs_mb_init_vpi() */ 3437 3438 3439 /* Leadville wll start sending PLOGI right after */ 3440 /* FDISC completion, we need to wait for REG_VPI */ 3441 /* completion, before sending back the FDISK request */ 3442 /* Also, allocate a node structure for Fabric port */ 3443 int 3444 emlxs_cmpl_reg_vpi(void *arg1, MAILBOXQ *mbq) 3445 { 3446 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 3447 emlxs_port_t *port = &PPORT; 3448 emlxs_port_t *vport; 3449 MAILBOX *mb; 3450 emlxs_buf_t *sbp; 3451 SERV_PARM *sp; 3452 fc_packet_t *pkt; 3453 NODELIST *ndlp; 3454 uint32_t ldid; 3455 uint8_t *wwn; 3456 3457 mb = (MAILBOX *)mbq; 3458 3459 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 3460 "CMPL reg_vpi: stats: %x", mb->mbxStatus); 3461 3462 if (mb->mbxStatus != MBX_SUCCESS) { 3463 return (0); 3464 } 3465 3466 vport = &VPORT((mb->un.varRegVpi.vpi - hba->vpi_base)); 3467 vport->flag |= EMLXS_PORT_REG_VPI_CMPL; 3468 sbp = (emlxs_buf_t *)mbq->sbp; 3469 3470 if (!sbp) { 3471 return (0); 3472 } 3473 3474 pkt = PRIV2PKT(sbp); 3475 sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t)); 3476 3477 vport->VFIp->outstandingVPIs++; 3478 3479 ldid = FABRIC_DID; 3480 ndlp = emlxs_node_find_did(vport, ldid); 3481 3482 if (!ndlp) { 3483 /* Attempt to create a node */ 3484 if ((ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP, 0))) { 3485 ndlp->nlp_Rpi = 0xffff; 3486 ndlp->nlp_DID = ldid; 3487 3488 bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm, 3489 sizeof (SERV_PARM)); 3490 3491 bcopy((uint8_t *)&sp->nodeName, 3492 (uint8_t *)&ndlp->nlp_nodename, 3493 sizeof (NAME_TYPE)); 3494 3495 bcopy((uint8_t *)&sp->portName, 3496 (uint8_t *)&ndlp->nlp_portname, 3497 sizeof (NAME_TYPE)); 3498 3499 ndlp->nlp_active = 1; 3500 ndlp->nlp_flag[hba->channel_ct] |= NLP_CLOSED; 3501 ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED; 3502 ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED; 3503 ndlp->nlp_flag[hba->channel_ip] |= NLP_CLOSED; 3504 3505 /* Add the node */ 3506 emlxs_node_add(vport, ndlp); 3507 3508 /* Open the node */ 3509 emlxs_node_open(vport, ndlp, hba->channel_ct); 3510 emlxs_node_open(vport, ndlp, hba->channel_els); 3511 emlxs_node_open(vport, ndlp, hba->channel_ip); 3512 emlxs_node_open(vport, ndlp, hba->channel_fcp); 3513 } else { 3514 wwn = (uint8_t *)&sp->portName; 3515 EMLXS_MSGF(EMLXS_CONTEXT, 3516 &emlxs_node_create_failed_msg, 3517 "Unable to allocate node. did=%06x " 3518 "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", 3519 ldid, wwn[0], wwn[1], wwn[2], 3520 wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 3521 3522 return (0); 3523 } 3524 } else { 3525 mutex_enter(&EMLXS_PORT_LOCK); 3526 3527 ndlp->nlp_Rpi = 0xffff; 3528 ndlp->nlp_DID = ldid; 3529 3530 bcopy((uint8_t *)sp, 3531 (uint8_t *)&ndlp->sparm, sizeof (SERV_PARM)); 3532 3533 bcopy((uint8_t *)&sp->nodeName, 3534 (uint8_t *)&ndlp->nlp_nodename, sizeof (NAME_TYPE)); 3535 3536 bcopy((uint8_t *)&sp->portName, 3537 (uint8_t *)&ndlp->nlp_portname, sizeof (NAME_TYPE)); 3538 3539 wwn = (uint8_t *)&ndlp->nlp_portname; 3540 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg, 3541 "node=%p did=%06x rpi=%x " 3542 "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", 3543 ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], 3544 wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 3545 3546 mutex_exit(&EMLXS_PORT_LOCK); 3547 3548 /* Open the node */ 3549 emlxs_node_open(vport, ndlp, hba->channel_ct); 3550 emlxs_node_open(vport, ndlp, hba->channel_els); 3551 emlxs_node_open(vport, ndlp, hba->channel_ip); 3552 emlxs_node_open(vport, ndlp, hba->channel_fcp); 3553 } 3554 3555 return (0); 3556 } /* emlxs_cmpl_reg_vpi */ 3557 3558 3559 extern uint32_t 3560 emlxs_mb_reg_vpi(emlxs_port_t *port, emlxs_buf_t *sbp) 3561 { 3562 emlxs_hba_t *hba = HBA; 3563 MAILBOXQ *mbq; 3564 MAILBOX *mb; 3565 int rval; 3566 3567 if (!(hba->flag & FC_NPIV_ENABLED)) { 3568 return (0); 3569 } 3570 3571 mutex_enter(&EMLXS_PORT_LOCK); 3572 3573 /* Can't reg vpi until ClearLA is sent */ 3574 if (hba->state != FC_READY) { 3575 mutex_exit(&EMLXS_PORT_LOCK); 3576 3577 return (1); 3578 } 3579 3580 /* Must have port id */ 3581 if (!port->did) { 3582 mutex_exit(&EMLXS_PORT_LOCK); 3583 3584 return (1); 3585 } 3586 3587 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 3588 mutex_exit(&EMLXS_PORT_LOCK); 3589 3590 return (1); 3591 } 3592 3593 port->flag |= EMLXS_PORT_REGISTERED; 3594 3595 mutex_exit(&EMLXS_PORT_LOCK); 3596 3597 mb = (MAILBOX *)mbq->mbox; 3598 3599 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3600 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 3601 mbq->nonembed = NULL; 3602 mb->un.varRegVpi.vfi = port->VFIp->VFI; 3603 mbq->mbox_cmpl = emlxs_cmpl_reg_vpi; 3604 } else { 3605 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3606 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 3607 } 3608 3609 if (sbp) { 3610 mbq->sbp = (uint8_t *)sbp; 3611 } 3612 3613 mb->un.varRegVpi.vpi = port->vpi + hba->vpi_base; 3614 mb->un.varRegVpi.sid = port->did; 3615 mb->mbxCommand = MBX_REG_VPI; 3616 mb->mbxOwner = OWN_HOST; 3617 3618 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 3619 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 3620 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 3621 } 3622 3623 return (0); 3624 3625 } /* emlxs_mb_reg_vpi() */ 3626 3627 3628 int 3629 emlxs_cmpl_unreg_vpi(void *arg1, MAILBOXQ *mbq) 3630 { 3631 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 3632 emlxs_port_t *vport; 3633 MAILBOX *mb; 3634 3635 mb = (MAILBOX *)mbq; 3636 if (mb->mbxStatus == MBX_SUCCESS) { 3637 vport = &VPORT(mb->un.varUnregVpi.vpi); 3638 vport->flag &= ~EMLXS_PORT_INIT_VPI_CMPL; 3639 vport->flag &= ~EMLXS_PORT_REG_VPI_CMPL; 3640 } 3641 return (0); 3642 3643 } /* emlxs_cmpl_unreg_vpi() */ 3644 3645 3646 extern uint32_t 3647 emlxs_mb_unreg_vpi(emlxs_port_t *port) 3648 { 3649 emlxs_hba_t *hba = HBA; 3650 MAILBOXQ *mbq; 3651 MAILBOX *mb; 3652 MAILBOX4 *mb4; 3653 VFIobj_t *vfip; 3654 FCFIobj_t *fcfp; 3655 int rval; 3656 3657 mutex_enter(&EMLXS_PORT_LOCK); 3658 3659 if (!(port->flag & EMLXS_PORT_REGISTERED)) { 3660 mutex_exit(&EMLXS_PORT_LOCK); 3661 return (0); 3662 } 3663 3664 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 3665 mutex_exit(&EMLXS_PORT_LOCK); 3666 return (1); 3667 } 3668 3669 port->flag &= ~EMLXS_PORT_REGISTERED; 3670 3671 mutex_exit(&EMLXS_PORT_LOCK); 3672 3673 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3674 mb4 = (MAILBOX4 *)mbq->mbox; 3675 bzero((void *)mb4, MAILBOX_CMD_SLI4_BSIZE); 3676 mb4->un.varUnRegVPI4.ii = 0; /* index is a VPI */ 3677 mb4->un.varUnRegVPI4.index = port->vpi + hba->vpi_base; 3678 mb4->mbxCommand = MBX_UNREG_VPI; 3679 mb4->mbxOwner = OWN_HOST; 3680 mbq->mbox_cmpl = emlxs_cmpl_unreg_vpi; 3681 } else { 3682 mb = (MAILBOX *)mbq->mbox; 3683 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3684 mb->un.varUnregVpi.vpi = port->vpi + hba->vpi_base; 3685 mb->mbxCommand = MBX_UNREG_VPI; 3686 mb->mbxOwner = OWN_HOST; 3687 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 3688 } 3689 3690 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 3691 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 3692 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 3693 } 3694 3695 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3696 if ((vfip = port->VFIp) != NULL) { 3697 3698 fcfp = vfip->FCFIp; 3699 if (port == fcfp->fcf_vpi) { 3700 fcfp->fcf_vpi = NULL; 3701 } 3702 3703 mutex_enter(&EMLXS_PORT_LOCK); 3704 vfip->outstandingVPIs--; 3705 if ((vfip->outstandingVPIs == 0) && 3706 (hba->state == FC_LINK_DOWN)) { 3707 mutex_exit(&EMLXS_PORT_LOCK); 3708 3709 /* No more VPIs so unreg the VFI */ 3710 (void) emlxs_mb_unreg_vfi(hba, vfip); 3711 } else { 3712 mutex_exit(&EMLXS_PORT_LOCK); 3713 } 3714 } 3715 } 3716 return (0); 3717 3718 } /* emlxs_mb_unreg_vpi() */ 3719 3720 3721 /* 3722 * emlxs_mb_config_farp Issue a CONFIG FARP mailbox command 3723 */ 3724 extern void 3725 emlxs_mb_config_farp(emlxs_hba_t *hba, MAILBOXQ *mbq) 3726 { 3727 MAILBOX *mb = (MAILBOX *)mbq; 3728 3729 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3730 3731 bcopy((uint8_t *)&hba->wwpn, 3732 (uint8_t *)&mb->un.varCfgFarp.portname, sizeof (NAME_TYPE)); 3733 3734 bcopy((uint8_t *)&hba->wwpn, 3735 (uint8_t *)&mb->un.varCfgFarp.nodename, sizeof (NAME_TYPE)); 3736 3737 mb->un.varCfgFarp.filterEnable = 1; 3738 mb->un.varCfgFarp.portName = 1; 3739 mb->un.varCfgFarp.nodeName = 1; 3740 mb->mbxCommand = MBX_CONFIG_FARP; 3741 mb->mbxOwner = OWN_HOST; 3742 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 3743 } /* emlxs_mb_config_farp() */ 3744 3745 3746 /* 3747 * emlxs_mb_read_nv Issue a READ CONFIG mailbox command 3748 */ 3749 /*ARGSUSED*/ 3750 extern void 3751 emlxs_mb_read_config(emlxs_hba_t *hba, MAILBOXQ *mbq) 3752 { 3753 MAILBOX *mb = (MAILBOX *)mbq; 3754 3755 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3756 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 3757 mbq->nonembed = NULL; 3758 } else { 3759 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3760 } 3761 3762 mb->mbxCommand = MBX_READ_CONFIG; 3763 mb->mbxOwner = OWN_HOST; 3764 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 3765 } /* emlxs_mb_read_config() */ 3766 3767 3768 /* 3769 * NAME: emlxs_mb_put 3770 * 3771 * FUNCTION: put mailbox cmd onto the mailbox queue. 3772 * 3773 * EXECUTION ENVIRONMENT: process and interrupt level. 3774 * 3775 * NOTES: 3776 * 3777 * CALLED FROM: EMLXS_SLI_ISSUE_MBOX_CMD 3778 * 3779 * INPUT: hba - pointer to the device info area 3780 * mbp - pointer to mailbox queue entry of mailbox cmd 3781 * 3782 * RETURNS: NULL - command queued 3783 */ 3784 extern void 3785 emlxs_mb_put(emlxs_hba_t *hba, MAILBOXQ *mbq) 3786 { 3787 3788 mutex_enter(&EMLXS_MBOX_LOCK); 3789 3790 if (hba->mbox_queue.q_first) { 3791 3792 /* 3793 * queue command to end of list 3794 */ 3795 ((MAILBOXQ *)hba->mbox_queue.q_last)->next = mbq; 3796 hba->mbox_queue.q_last = (uint8_t *)mbq; 3797 hba->mbox_queue.q_cnt++; 3798 } else { 3799 3800 /* 3801 * add command to empty list 3802 */ 3803 hba->mbox_queue.q_first = (uint8_t *)mbq; 3804 hba->mbox_queue.q_last = (uint8_t *)mbq; 3805 hba->mbox_queue.q_cnt = 1; 3806 } 3807 3808 mbq->next = NULL; 3809 3810 mutex_exit(&EMLXS_MBOX_LOCK); 3811 } /* emlxs_mb_put() */ 3812 3813 3814 /* 3815 * NAME: emlxs_mb_get 3816 * 3817 * FUNCTION: get a mailbox command from mailbox command queue 3818 * 3819 * EXECUTION ENVIRONMENT: interrupt level. 3820 * 3821 * NOTES: 3822 * 3823 * CALLED FROM: emlxs_handle_mb_event 3824 * 3825 * INPUT: hba - pointer to the device info area 3826 * 3827 * RETURNS: NULL - no match found mb pointer - pointer to a mailbox command 3828 */ 3829 extern MAILBOXQ * 3830 emlxs_mb_get(emlxs_hba_t *hba) 3831 { 3832 MAILBOXQ *p_first = NULL; 3833 3834 mutex_enter(&EMLXS_MBOX_LOCK); 3835 3836 if (hba->mbox_queue.q_first) { 3837 p_first = (MAILBOXQ *)hba->mbox_queue.q_first; 3838 hba->mbox_queue.q_first = (uint8_t *)p_first->next; 3839 3840 if (hba->mbox_queue.q_first == NULL) { 3841 hba->mbox_queue.q_last = NULL; 3842 hba->mbox_queue.q_cnt = 0; 3843 } else { 3844 hba->mbox_queue.q_cnt--; 3845 } 3846 3847 p_first->next = NULL; 3848 } 3849 3850 mutex_exit(&EMLXS_MBOX_LOCK); 3851 3852 return (p_first); 3853 3854 } /* emlxs_mb_get() */ 3855 3856 3857 /* EMLXS_PORT_LOCK must be held when calling this */ 3858 void 3859 emlxs_mb_init(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t flag, uint32_t tmo) 3860 { 3861 #ifdef FMA_SUPPORT 3862 emlxs_port_t *port = &PPORT; 3863 #endif /* FMA_SUPPORT */ 3864 MATCHMAP *mp; 3865 3866 HBASTATS.MboxIssued++; 3867 hba->mbox_queue_flag = flag; 3868 3869 /* Set the Mailbox timer */ 3870 hba->mbox_timer = hba->timer_tics + tmo; 3871 3872 /* Initialize mailbox */ 3873 mbq->flag &= MBQ_INIT_MASK; 3874 mbq->next = 0; 3875 3876 mutex_enter(&EMLXS_MBOX_LOCK); 3877 hba->mbox_mbq = (uint8_t *)mbq; 3878 mutex_exit(&EMLXS_MBOX_LOCK); 3879 3880 if (mbq->nonembed) { 3881 mp = (MATCHMAP *) mbq->nonembed; 3882 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size, 3883 DDI_DMA_SYNC_FORDEV); 3884 } 3885 3886 if (mbq->bp) { 3887 mp = (MATCHMAP *) mbq->bp; 3888 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size, 3889 DDI_DMA_SYNC_FORDEV); 3890 } 3891 return; 3892 3893 } /* emlxs_mb_init() */ 3894 3895 3896 extern void 3897 emlxs_mb_fini(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mbxStatus) 3898 { 3899 emlxs_port_t *port = &PPORT; 3900 MATCHMAP *mbox_nonembed; 3901 MATCHMAP *mbox_bp; 3902 emlxs_buf_t *mbox_sbp; 3903 fc_unsol_buf_t *mbox_ubp; 3904 IOCBQ *mbox_iocbq; 3905 MAILBOXQ *mbox_mbq; 3906 MAILBOX *mbox; 3907 uint32_t mbox_queue_flag; 3908 emlxs_ub_priv_t *ub_priv; 3909 3910 mutex_enter(&EMLXS_PORT_LOCK); 3911 3912 if (hba->mbox_queue_flag) { 3913 HBASTATS.MboxCompleted++; 3914 3915 if (mbxStatus != MBX_SUCCESS) { 3916 HBASTATS.MboxError++; 3917 } else { 3918 HBASTATS.MboxGood++; 3919 } 3920 } 3921 3922 mutex_enter(&EMLXS_MBOX_LOCK); 3923 mbox_queue_flag = hba->mbox_queue_flag; 3924 mbox_mbq = (MAILBOXQ *)hba->mbox_mbq; 3925 3926 if (mbox_mbq) { 3927 mbox_nonembed = (MATCHMAP *)mbox_mbq->nonembed; 3928 mbox_bp = (MATCHMAP *)mbox_mbq->bp; 3929 mbox_sbp = (emlxs_buf_t *)mbox_mbq->sbp; 3930 mbox_ubp = (fc_unsol_buf_t *)mbox_mbq->ubp; 3931 mbox_iocbq = (IOCBQ *)mbox_mbq->iocbq; 3932 } else { 3933 mbox_nonembed = NULL; 3934 mbox_bp = NULL; 3935 mbox_sbp = NULL; 3936 mbox_ubp = NULL; 3937 mbox_iocbq = NULL; 3938 } 3939 3940 hba->mbox_mbq = 0; 3941 hba->mbox_queue_flag = 0; 3942 hba->mbox_timer = 0; 3943 mutex_exit(&EMLXS_MBOX_LOCK); 3944 3945 mutex_exit(&EMLXS_PORT_LOCK); 3946 3947 if (mbox_queue_flag == MBX_NOWAIT) { 3948 /* Check for deferred MBUF cleanup */ 3949 if (mbox_bp) { 3950 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mbox_bp); 3951 } 3952 if (mbox_nonembed) { 3953 (void) emlxs_mem_put(hba, MEM_BUF, 3954 (uint8_t *)mbox_nonembed); 3955 } 3956 if (mbox_mbq) { 3957 (void) emlxs_mem_put(hba, MEM_MBOX, 3958 (uint8_t *)mbox_mbq); 3959 } 3960 } else { /* MBX_WAIT */ 3961 if (mbox_mbq) { 3962 if (mb) { 3963 /* Copy the local mailbox provided back into */ 3964 /* the original mailbox */ 3965 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3966 bcopy((uint32_t *)mb, 3967 (uint32_t *)mbox_mbq, 3968 MAILBOX_CMD_SLI4_BSIZE); 3969 } else { 3970 bcopy((uint32_t *)mb, 3971 (uint32_t *)mbox_mbq, 3972 MAILBOX_CMD_BSIZE); 3973 } 3974 } 3975 3976 mbox = (MAILBOX *)mbox_mbq; 3977 mbox->mbxStatus = mbxStatus; 3978 3979 /* Mark mailbox complete */ 3980 mbox_mbq->flag |= MBQ_COMPLETED; 3981 } 3982 3983 /* Wake up the sleeping thread */ 3984 if (mbox_queue_flag == MBX_SLEEP) { 3985 mutex_enter(&EMLXS_MBOX_LOCK); 3986 cv_broadcast(&EMLXS_MBOX_CV); 3987 mutex_exit(&EMLXS_MBOX_LOCK); 3988 } 3989 } 3990 3991 #ifdef SFCT_SUPPORT 3992 if (mb && mbox_sbp && mbox_sbp->fct_cmd) { 3993 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3994 "FCT mailbox: %s: status=%x", 3995 emlxs_mb_cmd_xlate(mb->mbxCommand), 3996 (uint32_t)mb->mbxStatus); 3997 } 3998 #endif /* SFCT_SUPPORT */ 3999 4000 /* Check for deferred pkt completion */ 4001 if (mbox_sbp) { 4002 if (mbxStatus != MBX_SUCCESS) { 4003 /* Set error status */ 4004 mbox_sbp->pkt_flags &= ~PACKET_STATE_VALID; 4005 emlxs_set_pkt_state(mbox_sbp, IOSTAT_LOCAL_REJECT, 4006 IOERR_NO_RESOURCES, 1); 4007 } 4008 4009 emlxs_pkt_complete(mbox_sbp, -1, 0, 1); 4010 } 4011 4012 /* Check for deferred ub completion */ 4013 if (mbox_ubp) { 4014 ub_priv = mbox_ubp->ub_fca_private; 4015 port = ub_priv->port; 4016 4017 emlxs_ub_callback(port, mbox_ubp); 4018 } 4019 4020 /* Special handling for vport PLOGI */ 4021 if (mbox_iocbq == (IOCBQ *)1) { 4022 mbox_iocbq = NULL; 4023 } 4024 4025 /* Check for deferred iocb tx */ 4026 if (mbox_iocbq) { 4027 /* Check for driver special codes */ 4028 /* These indicate the mailbox is being flushed */ 4029 if (mbxStatus >= MBX_DRIVER_RESERVED) { 4030 /* Set the error status and return it */ 4031 mbox_iocbq->iocb.ULPSTATUS = IOSTAT_LOCAL_REJECT; 4032 mbox_iocbq->iocb.un.grsp.perr.statLocalError = 4033 IOERR_ABORT_REQUESTED; 4034 4035 emlxs_proc_channel_event(hba, mbox_iocbq->channel, 4036 mbox_iocbq); 4037 } else { 4038 EMLXS_SLI_ISSUE_IOCB_CMD(hba, mbox_iocbq->channel, 4039 mbox_iocbq); 4040 } 4041 } 4042 return; 4043 4044 } /* emlxs_mb_fini() */ 4045 4046 4047 extern void 4048 emlxs_mb_flush(emlxs_hba_t *hba) 4049 { 4050 MAILBOXQ *mbq; 4051 uint32_t mbxStatus; 4052 4053 mbxStatus = (hba->flag & FC_HARDWARE_ERROR) ? 4054 MBX_HARDWARE_ERROR : MBX_NOT_FINISHED; 4055 4056 /* Flush out the active mbox command */ 4057 emlxs_mb_fini(hba, NULL, mbxStatus); 4058 4059 /* Flush out the queued mbox commands */ 4060 while (mbq = (MAILBOXQ *)emlxs_mb_get(hba)) { 4061 mutex_enter(&EMLXS_MBOX_LOCK); 4062 hba->mbox_queue_flag = MBX_NOWAIT; 4063 hba->mbox_mbq = (uint8_t *)mbq; 4064 mutex_exit(&EMLXS_MBOX_LOCK); 4065 4066 emlxs_mb_fini(hba, NULL, mbxStatus); 4067 } 4068 4069 return; 4070 4071 } /* emlxs_mb_flush */ 4072 4073 4074 extern char * 4075 emlxs_mb_cmd_xlate(uint8_t cmd) 4076 { 4077 static char buffer[32]; 4078 uint32_t i; 4079 uint32_t count; 4080 4081 count = sizeof (emlxs_mb_cmd_table) / sizeof (emlxs_table_t); 4082 for (i = 0; i < count; i++) { 4083 if (cmd == emlxs_mb_cmd_table[i].code) { 4084 return (emlxs_mb_cmd_table[i].string); 4085 } 4086 } 4087 4088 (void) sprintf(buffer, "Cmd=0x%x", cmd); 4089 return (buffer); 4090 4091 } /* emlxs_mb_cmd_xlate() */ 4092