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