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