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