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 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright (c) 2000 to 2009, LSI Corporation. 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms of all code within 32 * this file that is exclusively owned by LSI, with or without 33 * modification, is permitted provided that, in addition to the CDDL 1.0 34 * License requirements, the following conditions are met: 35 * 36 * Neither the name of the author nor the names of its contributors may be 37 * used to endorse or promote products derived from this software without 38 * specific prior written permission. 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 43 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 44 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 45 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 46 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 47 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 48 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 49 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 50 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 51 * DAMAGE. 52 */ 53 54 /* 55 * mptsas_init - This file contains all the functions used to initialize 56 * MPT2.0 based hardware. 57 */ 58 59 #if defined(lint) || defined(DEBUG) 60 #define MPTSAS_DEBUG 61 #endif 62 63 /* 64 * standard header files 65 */ 66 #include <sys/note.h> 67 #include <sys/scsi/scsi.h> 68 69 #pragma pack(1) 70 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h> 71 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h> 72 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h> 73 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h> 74 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h> 75 #pragma pack() 76 /* 77 * private header files. 78 */ 79 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h> 80 81 static int mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var, 82 ddi_acc_handle_t accessp); 83 static int mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var, 84 ddi_acc_handle_t accessp); 85 static int mptsas_ioc_do_get_port_facts(mptsas_t *mpt, caddr_t memp, int var, 86 ddi_acc_handle_t accessp); 87 static int mptsas_ioc_do_get_port_facts_reply(mptsas_t *mpt, caddr_t memp, 88 int var, ddi_acc_handle_t accessp); 89 static int mptsas_ioc_do_enable_port(mptsas_t *mpt, caddr_t memp, int var, 90 ddi_acc_handle_t accessp); 91 static int mptsas_ioc_do_enable_port_reply(mptsas_t *mpt, caddr_t memp, int var, 92 ddi_acc_handle_t accessp); 93 static int mptsas_ioc_do_enable_event_notification(mptsas_t *mpt, caddr_t memp, 94 int var, ddi_acc_handle_t accessp); 95 static int mptsas_ioc_do_enable_event_notification_reply(mptsas_t *mpt, 96 caddr_t memp, int var, ddi_acc_handle_t accessp); 97 static int mptsas_do_ioc_init(mptsas_t *mpt, caddr_t memp, int var, 98 ddi_acc_handle_t accessp); 99 static int mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var, 100 ddi_acc_handle_t accessp); 101 102 static const char * 103 mptsas_product_type_string(mptsas_t *mpt) 104 { 105 switch (mpt->m_productid & MPI2_FW_HEADER_PID_PROD_MASK) { 106 107 case MPI2_FW_HEADER_PID_PROD_A: 108 return ("A"); 109 default: 110 return ("?"); 111 } 112 } 113 114 int 115 mptsas_ioc_get_facts(mptsas_t *mpt) 116 { 117 /* 118 * Send get facts messages 119 */ 120 if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_FACTS_REQUEST), NULL, 121 mptsas_ioc_do_get_facts)) { 122 return (DDI_FAILURE); 123 } 124 125 /* 126 * Get facts reply messages 127 */ 128 if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_FACTS_REPLY), NULL, 129 mptsas_ioc_do_get_facts_reply)) { 130 return (DDI_FAILURE); 131 } 132 133 return (DDI_SUCCESS); 134 } 135 136 static int 137 mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var, 138 ddi_acc_handle_t accessp) 139 { 140 #ifndef __lock_lint 141 _NOTE(ARGUNUSED(var)) 142 #endif 143 pMpi2IOCFactsRequest_t facts; 144 int numbytes; 145 146 bzero(memp, sizeof (*facts)); 147 facts = (void *)memp; 148 ddi_put8(accessp, &facts->Function, MPI2_FUNCTION_IOC_FACTS); 149 numbytes = sizeof (*facts); 150 151 /* 152 * Post message via handshake 153 */ 154 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 155 return (DDI_FAILURE); 156 } 157 158 return (DDI_SUCCESS); 159 } 160 161 static int 162 mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var, 163 ddi_acc_handle_t accessp) 164 { 165 #ifndef __lock_lint 166 _NOTE(ARGUNUSED(var)) 167 #endif 168 169 pMpi2IOCFactsReply_t factsreply; 170 int numbytes; 171 uint_t iocstatus; 172 char buf[32]; 173 uint16_t numReplyFrames; 174 uint16_t queueSize, queueDiff; 175 int simple_sge_main; 176 int simple_sge_next; 177 178 bzero(memp, sizeof (*factsreply)); 179 factsreply = (void *)memp; 180 numbytes = sizeof (*factsreply); 181 182 /* 183 * get ioc facts reply message 184 */ 185 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 186 return (DDI_FAILURE); 187 } 188 189 if (iocstatus = ddi_get16(accessp, &factsreply->IOCStatus)) { 190 mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_get_facts_reply: " 191 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 192 ddi_get32(accessp, &factsreply->IOCLogInfo)); 193 return (DDI_FAILURE); 194 } 195 196 /* 197 * store key values from reply to mpt structure 198 */ 199 mpt->m_fwversion = ddi_get32(accessp, &factsreply->FWVersion.Word); 200 mpt->m_productid = ddi_get16(accessp, &factsreply->ProductID); 201 202 203 (void) sprintf(buf, "%u.%u.%u.%u", 204 ddi_get8(accessp, &factsreply->FWVersion.Struct.Major), 205 ddi_get8(accessp, &factsreply->FWVersion.Struct.Minor), 206 ddi_get8(accessp, &factsreply->FWVersion.Struct.Unit), 207 ddi_get8(accessp, &factsreply->FWVersion.Struct.Dev)); 208 mptsas_log(mpt, CE_NOTE, "?mpt%d Firmware version v%s (%s)\n", 209 mpt->m_instance, buf, mptsas_product_type_string(mpt)); 210 (void) ddi_prop_update_string(DDI_DEV_T_NONE, mpt->m_dip, 211 "firmware-version", buf); 212 213 /* 214 * Set up request info. 215 */ 216 mpt->m_max_requests = ddi_get16(accessp, 217 &factsreply->RequestCredit) - 1; 218 mpt->m_req_frame_size = ddi_get16(accessp, 219 &factsreply->IOCRequestFrameSize) * 4; 220 221 /* 222 * Size of reply free queue should be the number of requests 223 * plus some additional for events (32). Make sure number of 224 * reply frames is not a multiple of 16 so that the queue sizes 225 * are calculated correctly later to be a multiple of 16. 226 */ 227 mpt->m_reply_frame_size = ddi_get8(accessp, 228 &factsreply->ReplyFrameSize) * 4; 229 numReplyFrames = mpt->m_max_requests + 32; 230 if (!(numReplyFrames % 16)) { 231 numReplyFrames--; 232 } 233 mpt->m_max_replies = numReplyFrames; 234 queueSize = numReplyFrames; 235 queueSize += 16 - (queueSize % 16); 236 mpt->m_free_queue_depth = queueSize; 237 238 /* 239 * Size of reply descriptor post queue should be the number of 240 * request frames + the number of reply frames + 1 and needs to 241 * be a multiple of 16. This size can be no larger than 242 * MaxReplyDescriptorPostQueueDepth from IOCFacts. If the 243 * calculated queue size is larger than allowed, subtract a 244 * multiple of 16 from m_max_requests, m_max_replies, and 245 * m_reply_free_depth. 246 */ 247 queueSize = mpt->m_max_requests + numReplyFrames + 1; 248 if (queueSize % 16) { 249 queueSize += 16 - (queueSize % 16); 250 } 251 mpt->m_post_queue_depth = ddi_get16(accessp, 252 &factsreply->MaxReplyDescriptorPostQueueDepth); 253 if (queueSize > mpt->m_post_queue_depth) { 254 queueDiff = queueSize - mpt->m_post_queue_depth; 255 if (queueDiff % 16) { 256 queueDiff += 16 - (queueDiff % 16); 257 } 258 mpt->m_max_requests -= queueDiff; 259 mpt->m_max_replies -= queueDiff; 260 mpt->m_free_queue_depth -= queueDiff; 261 queueSize -= queueDiff; 262 } 263 mpt->m_post_queue_depth = queueSize; 264 265 /* 266 * Set up other stuff. 267 */ 268 mpt->m_max_chain_depth = ddi_get8(accessp, 269 &factsreply->MaxChainDepth); 270 271 /* 272 * Calculate max frames per request based on DMA S/G length. 273 */ 274 275 simple_sge_main = MPTSAS_MAX_FRAME_SGES64(mpt) - 1; 276 simple_sge_next = mpt->m_req_frame_size / 277 sizeof (MPI2_SGE_SIMPLE64) - 1; 278 279 mpt->m_max_request_frames = (MPTSAS_MAX_DMA_SEGS - 280 simple_sge_main) / simple_sge_next + 1; 281 if (((MPTSAS_MAX_DMA_SEGS - simple_sge_main) % 282 simple_sge_next) > 1) { 283 mpt->m_max_request_frames++; 284 } 285 286 return (DDI_SUCCESS); 287 } 288 289 int 290 mptsas_ioc_get_port_facts(mptsas_t *mpt, int port) 291 { 292 /* 293 * Send get port facts message 294 */ 295 if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_FACTS_REQUEST), port, 296 mptsas_ioc_do_get_port_facts)) { 297 return (DDI_FAILURE); 298 } 299 300 /* 301 * Get port facts reply message 302 */ 303 if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_FACTS_REPLY), port, 304 mptsas_ioc_do_get_port_facts_reply)) { 305 return (DDI_FAILURE); 306 } 307 308 return (DDI_SUCCESS); 309 } 310 311 static int 312 mptsas_ioc_do_get_port_facts(mptsas_t *mpt, caddr_t memp, int var, 313 ddi_acc_handle_t accessp) 314 { 315 pMpi2PortFactsRequest_t facts; 316 int numbytes; 317 318 bzero(memp, sizeof (*facts)); 319 facts = (void *)memp; 320 ddi_put8(accessp, &facts->Function, MPI2_FUNCTION_PORT_FACTS); 321 ddi_put8(accessp, &facts->PortNumber, var); 322 numbytes = sizeof (*facts); 323 324 /* 325 * Send port facts message via handshake 326 */ 327 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 328 return (DDI_FAILURE); 329 } 330 331 return (DDI_SUCCESS); 332 } 333 334 static int 335 mptsas_ioc_do_get_port_facts_reply(mptsas_t *mpt, caddr_t memp, int var, 336 ddi_acc_handle_t accessp) 337 { 338 #ifndef __lock_lint 339 _NOTE(ARGUNUSED(var)) 340 #endif 341 pMpi2PortFactsReply_t factsreply; 342 int numbytes; 343 uint_t iocstatus; 344 345 bzero(memp, sizeof (*factsreply)); 346 factsreply = (void *)memp; 347 numbytes = sizeof (*factsreply); 348 349 /* 350 * Get port facts reply message via handshake 351 */ 352 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 353 return (DDI_FAILURE); 354 } 355 356 if (iocstatus = ddi_get16(accessp, &factsreply->IOCStatus)) { 357 mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_get_port_facts_reply: " 358 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 359 ddi_get32(accessp, &factsreply->IOCLogInfo)); 360 return (DDI_FAILURE); 361 } 362 363 return (DDI_SUCCESS); 364 } 365 366 int 367 mptsas_ioc_enable_port(mptsas_t *mpt) 368 { 369 /* 370 * Send enable port message 371 */ 372 if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_ENABLE_REQUEST), 0, 373 mptsas_ioc_do_enable_port)) { 374 return (DDI_FAILURE); 375 } 376 377 /* 378 * Get enable port reply message 379 */ 380 if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_ENABLE_REPLY), 0, 381 mptsas_ioc_do_enable_port_reply)) { 382 return (DDI_FAILURE); 383 } 384 385 return (DDI_SUCCESS); 386 } 387 388 static int 389 mptsas_ioc_do_enable_port(mptsas_t *mpt, caddr_t memp, int var, 390 ddi_acc_handle_t accessp) 391 { 392 #ifndef __lock_lint 393 _NOTE(ARGUNUSED(var)) 394 #endif 395 pMpi2PortEnableRequest_t enable; 396 int numbytes; 397 398 bzero(memp, sizeof (*enable)); 399 enable = (void *)memp; 400 ddi_put8(accessp, &enable->Function, MPI2_FUNCTION_PORT_ENABLE); 401 numbytes = sizeof (*enable); 402 403 /* 404 * Send message via handshake 405 */ 406 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 407 return (DDI_FAILURE); 408 } 409 410 return (DDI_SUCCESS); 411 } 412 413 static int 414 mptsas_ioc_do_enable_port_reply(mptsas_t *mpt, caddr_t memp, int var, 415 ddi_acc_handle_t accessp) 416 { 417 #ifndef __lock_lint 418 _NOTE(ARGUNUSED(var)) 419 #endif 420 421 int numbytes; 422 uint_t iocstatus; 423 pMpi2PortEnableReply_t portreply; 424 425 numbytes = sizeof (MPI2_PORT_ENABLE_REPLY); 426 bzero(memp, numbytes); 427 portreply = (void *)memp; 428 429 /* 430 * Get message via handshake 431 */ 432 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 433 return (DDI_FAILURE); 434 } 435 436 if (iocstatus = ddi_get16(accessp, &portreply->IOCStatus)) { 437 mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_enable_port_reply: " 438 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 439 ddi_get32(accessp, &portreply->IOCLogInfo)); 440 return (DDI_FAILURE); 441 } 442 443 return (DDI_SUCCESS); 444 } 445 446 int 447 mptsas_ioc_enable_event_notification(mptsas_t *mpt) 448 { 449 ASSERT(mutex_owned(&mpt->m_mutex)); 450 451 /* 452 * Send enable event notification message 453 */ 454 if (mptsas_do_dma(mpt, sizeof (MPI2_EVENT_NOTIFICATION_REQUEST), NULL, 455 mptsas_ioc_do_enable_event_notification)) { 456 return (DDI_FAILURE); 457 } 458 459 /* 460 * Get enable event reply message 461 */ 462 if (mptsas_do_dma(mpt, sizeof (MPI2_EVENT_NOTIFICATION_REPLY), NULL, 463 mptsas_ioc_do_enable_event_notification_reply)) { 464 return (DDI_FAILURE); 465 } 466 467 return (DDI_SUCCESS); 468 } 469 470 static int 471 mptsas_ioc_do_enable_event_notification(mptsas_t *mpt, caddr_t memp, int var, 472 ddi_acc_handle_t accessp) 473 { 474 #ifndef __lock_lint 475 _NOTE(ARGUNUSED(var)) 476 #endif 477 478 pMpi2EventNotificationRequest_t event; 479 int numbytes; 480 481 bzero(memp, sizeof (*event)); 482 event = (void *)memp; 483 ddi_put8(accessp, &event->Function, MPI2_FUNCTION_EVENT_NOTIFICATION); 484 numbytes = sizeof (*event); 485 486 /* 487 * Send message via handshake 488 */ 489 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 490 return (DDI_FAILURE); 491 } 492 493 return (DDI_SUCCESS); 494 } 495 496 static int 497 mptsas_ioc_do_enable_event_notification_reply(mptsas_t *mpt, caddr_t memp, 498 int var, ddi_acc_handle_t accessp) 499 { 500 #ifndef __lock_lint 501 _NOTE(ARGUNUSED(var)) 502 #endif 503 int numbytes; 504 uint_t iocstatus; 505 pMpi2EventNotificationReply_t eventsreply; 506 507 numbytes = sizeof (MPI2_EVENT_NOTIFICATION_REPLY); 508 bzero(memp, numbytes); 509 eventsreply = (void *)memp; 510 511 /* 512 * Get message via handshake 513 */ 514 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 515 return (DDI_FAILURE); 516 } 517 518 if (iocstatus = ddi_get16(accessp, &eventsreply->IOCStatus)) { 519 mptsas_log(mpt, CE_WARN, 520 "mptsas_ioc_do_enable_event_notification_reply: " 521 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 522 ddi_get32(accessp, &eventsreply->IOCLogInfo)); 523 return (DDI_FAILURE); 524 } 525 526 return (DDI_SUCCESS); 527 } 528 529 int 530 mptsas_ioc_init(mptsas_t *mpt) 531 { 532 /* 533 * Send ioc init message 534 */ 535 if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_INIT_REQUEST), NULL, 536 mptsas_do_ioc_init)) { 537 return (DDI_FAILURE); 538 } 539 540 /* 541 * Get ioc init reply message 542 */ 543 if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_INIT_REPLY), NULL, 544 mptsas_do_ioc_init_reply)) { 545 return (DDI_FAILURE); 546 } 547 548 return (DDI_SUCCESS); 549 } 550 551 static int 552 mptsas_do_ioc_init(mptsas_t *mpt, caddr_t memp, int var, 553 ddi_acc_handle_t accessp) 554 { 555 #ifndef __lock_lint 556 _NOTE(ARGUNUSED(var)) 557 #endif 558 559 pMpi2IOCInitRequest_t init; 560 int numbytes; 561 562 bzero(memp, sizeof (*init)); 563 init = (void *)memp; 564 ddi_put8(accessp, &init->Function, MPI2_FUNCTION_IOC_INIT); 565 ddi_put8(accessp, &init->WhoInit, MPI2_WHOINIT_HOST_DRIVER); 566 ddi_put16(accessp, &init->MsgVersion, MPI2_VERSION); 567 ddi_put16(accessp, &init->HeaderVersion, MPI2_HEADER_VERSION); 568 ddi_put16(accessp, &init->SystemRequestFrameSize, 569 mpt->m_req_frame_size / 4); 570 ddi_put16(accessp, &init->ReplyDescriptorPostQueueDepth, 571 mpt->m_post_queue_depth); 572 ddi_put16(accessp, &init->ReplyFreeQueueDepth, 573 mpt->m_free_queue_depth); 574 575 /* 576 * These addresses are set using the DMA cookie addresses from when the 577 * memory was allocated. Sense buffer hi address should be 0. 578 */ 579 ddi_put32(accessp, &init->SenseBufferAddressHigh, 0); 580 ddi_put32(accessp, &init->SystemReplyAddressHigh, 581 (uint32_t)(mpt->m_reply_frame_dma_addr >> 32)); 582 ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.High, 583 (uint32_t)(mpt->m_req_frame_dma_addr >> 32)); 584 ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.Low, 585 (uint32_t)mpt->m_req_frame_dma_addr); 586 ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.High, 587 (uint32_t)(mpt->m_post_queue_dma_addr >> 32)); 588 ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.Low, 589 (uint32_t)mpt->m_post_queue_dma_addr); 590 ddi_put32(accessp, &init->ReplyFreeQueueAddress.High, 591 (uint32_t)(mpt->m_free_queue_dma_addr >> 32)); 592 ddi_put32(accessp, &init->ReplyFreeQueueAddress.Low, 593 (uint32_t)mpt->m_free_queue_dma_addr); 594 595 numbytes = sizeof (*init); 596 597 /* 598 * Post message via handshake 599 */ 600 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 601 return (DDI_FAILURE); 602 } 603 604 return (DDI_SUCCESS); 605 } 606 607 static int 608 mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var, 609 ddi_acc_handle_t accessp) 610 { 611 #ifndef __lock_lint 612 _NOTE(ARGUNUSED(var)) 613 #endif 614 615 pMpi2IOCInitReply_t initreply; 616 int numbytes; 617 uint_t iocstatus; 618 619 numbytes = sizeof (MPI2_IOC_INIT_REPLY); 620 bzero(memp, numbytes); 621 initreply = (void *)memp; 622 623 /* 624 * Get reply message via handshake 625 */ 626 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 627 return (DDI_FAILURE); 628 } 629 630 if (iocstatus = ddi_get16(accessp, &initreply->IOCStatus)) { 631 mptsas_log(mpt, CE_WARN, "mptsas_do_ioc_init_reply: " 632 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 633 ddi_get32(accessp, &initreply->IOCLogInfo)); 634 return (DDI_FAILURE); 635 } 636 637 if ((ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell)) & 638 MPI2_IOC_STATE_OPERATIONAL) { 639 mptsas_log(mpt, CE_NOTE, 640 "?mpt%d: IOC Operational.\n", mpt->m_instance); 641 } else { 642 return (DDI_FAILURE); 643 } 644 645 return (DDI_SUCCESS); 646 } 647