mptsas_init.c revision 9907:98086c85a8f7
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 81static int mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var, 82 ddi_acc_handle_t accessp); 83static int mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var, 84 ddi_acc_handle_t accessp); 85static int mptsas_ioc_do_get_port_facts(mptsas_t *mpt, caddr_t memp, int var, 86 ddi_acc_handle_t accessp); 87static int mptsas_ioc_do_get_port_facts_reply(mptsas_t *mpt, caddr_t memp, 88 int var, ddi_acc_handle_t accessp); 89static int mptsas_ioc_do_enable_port(mptsas_t *mpt, caddr_t memp, int var, 90 ddi_acc_handle_t accessp); 91static int mptsas_ioc_do_enable_port_reply(mptsas_t *mpt, caddr_t memp, int var, 92 ddi_acc_handle_t accessp); 93static int mptsas_ioc_do_enable_event_notification(mptsas_t *mpt, caddr_t memp, 94 int var, ddi_acc_handle_t accessp); 95static int mptsas_ioc_do_enable_event_notification_reply(mptsas_t *mpt, 96 caddr_t memp, int var, ddi_acc_handle_t accessp); 97static int mptsas_do_ioc_init(mptsas_t *mpt, caddr_t memp, int var, 98 ddi_acc_handle_t accessp); 99static int mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var, 100 ddi_acc_handle_t accessp); 101 102static const char * 103mptsas_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 114int 115mptsas_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 136static int 137mptsas_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 161static int 162mptsas_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 289int 290mptsas_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 311static int 312mptsas_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 334static int 335mptsas_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 366int 367mptsas_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 388static int 389mptsas_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 413static int 414mptsas_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 446int 447mptsas_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 470static int 471mptsas_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 496static int 497mptsas_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 529int 530mptsas_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 551static int 552mptsas_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 607static int 608mptsas_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