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_sas/mpi/mpi2_type.h>
  72 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
  73 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
  74 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
  75 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
  76 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
  77 #pragma pack()
  78 /*
  79  * private header files.
  80  */
  81 #include <sys/scsi/adapters/mpt_sas/mptsas_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                 return ("SAS2208");
 126         case MPI2_MFGPAGE_DEVID_SAS2308_1:
 127         case MPI2_MFGPAGE_DEVID_SAS2308_2:
 128         case MPI2_MFGPAGE_DEVID_SAS2308_3:
 129                 return ("SAS2308");
 130         case MPI25_MFGPAGE_DEVID_SAS3004:
 131                 return ("SAS3004");
 132         case MPI25_MFGPAGE_DEVID_SAS3008:
 133                 return ("SAS3008");
 134         case MPI25_MFGPAGE_DEVID_SAS3108_1:
 135         case MPI25_MFGPAGE_DEVID_SAS3108_2:
 136         case MPI25_MFGPAGE_DEVID_SAS3108_5:
 137         case MPI25_MFGPAGE_DEVID_SAS3108_6:
 138                 return ("SAS3108");
 139         default:
 140                 return ("?");
 141         }
 142 }
 143 
 144 int
 145 mptsas_ioc_get_facts(mptsas_t *mpt)
 146 {
 147         /*
 148          * Send get facts messages
 149          */
 150         if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_FACTS_REQUEST), NULL,
 151             mptsas_ioc_do_get_facts)) {
 152                 return (DDI_FAILURE);
 153         }
 154 
 155         /*
 156          * Get facts reply messages
 157          */
 158         if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_FACTS_REPLY), NULL,
 159             mptsas_ioc_do_get_facts_reply)) {
 160                 return (DDI_FAILURE);
 161         }
 162 
 163         return (DDI_SUCCESS);
 164 }
 165 
 166 static int
 167 mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var,
 168                 ddi_acc_handle_t accessp)
 169 {
 170 #ifndef __lock_lint
 171         _NOTE(ARGUNUSED(var))
 172 #endif
 173         pMpi2IOCFactsRequest_t  facts;
 174         int                     numbytes;
 175 
 176         bzero(memp, sizeof (*facts));
 177         facts = (void *)memp;
 178         ddi_put8(accessp, &facts->Function, MPI2_FUNCTION_IOC_FACTS);
 179         numbytes = sizeof (*facts);
 180 
 181         /*
 182          * Post message via handshake
 183          */
 184         if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
 185                 return (DDI_FAILURE);
 186         }
 187 
 188         return (DDI_SUCCESS);
 189 }
 190 
 191 static int
 192 mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var,
 193                 ddi_acc_handle_t accessp)
 194 {
 195 #ifndef __lock_lint
 196         _NOTE(ARGUNUSED(var))
 197 #endif
 198 
 199         pMpi2IOCFactsReply_t    factsreply;
 200         int                     numbytes;
 201         uint_t                  iocstatus;
 202         char                    buf[32];
 203         uint16_t                numReplyFrames;
 204         uint16_t                queueSize, queueDiff;
 205         int                     simple_sge_main;
 206         int                     simple_sge_next;
 207         uint32_t                capabilities;
 208         uint16_t                msgversion;
 209 
 210         bzero(memp, sizeof (*factsreply));
 211         factsreply = (void *)memp;
 212         numbytes = sizeof (*factsreply);
 213 
 214         /*
 215          * get ioc facts reply message
 216          */
 217         if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
 218                 return (DDI_FAILURE);
 219         }
 220 
 221         if (iocstatus = ddi_get16(accessp, &factsreply->IOCStatus)) {
 222                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_get_facts_reply: "
 223                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
 224                     ddi_get32(accessp, &factsreply->IOCLogInfo));
 225                 return (DDI_FAILURE);
 226         }
 227 
 228         /*
 229          * store key values from reply to mpt structure
 230          */
 231         mpt->m_fwversion = ddi_get32(accessp, &factsreply->FWVersion.Word);
 232         mpt->m_productid = ddi_get16(accessp, &factsreply->ProductID);
 233 
 234 
 235         (void) sprintf(buf, "%u.%u.%u.%u",
 236             ddi_get8(accessp, &factsreply->FWVersion.Struct.Major),
 237             ddi_get8(accessp, &factsreply->FWVersion.Struct.Minor),
 238             ddi_get8(accessp, &factsreply->FWVersion.Struct.Unit),
 239             ddi_get8(accessp, &factsreply->FWVersion.Struct.Dev));
 240         mptsas_log(mpt, CE_NOTE, "?MPT Firmware version v%s (%s)\n",
 241             buf, mptsas_devid_type_string(mpt));
 242         (void) ddi_prop_update_string(DDI_DEV_T_NONE, mpt->m_dip,
 243             "firmware-version", buf);
 244 
 245         /*
 246          * Set up request info.
 247          */
 248         mpt->m_max_requests = ddi_get16(accessp,
 249             &factsreply->RequestCredit) - 1;
 250         mpt->m_req_frame_size = ddi_get16(accessp,
 251             &factsreply->IOCRequestFrameSize) * 4;
 252 
 253         /*
 254          * Size of reply free queue should be the number of requests
 255          * plus some additional for events (32).  Make sure number of
 256          * reply frames is not a multiple of 16 so that the queue sizes
 257          * are calculated correctly later to be a multiple of 16.
 258          */
 259         mpt->m_reply_frame_size = ddi_get8(accessp,
 260             &factsreply->ReplyFrameSize) * 4;
 261         numReplyFrames = mpt->m_max_requests + 32;
 262         if (!(numReplyFrames % 16)) {
 263                 numReplyFrames--;
 264         }
 265         mpt->m_max_replies = numReplyFrames;
 266         queueSize = numReplyFrames;
 267         queueSize += 16 - (queueSize % 16);
 268         mpt->m_free_queue_depth = queueSize;
 269 
 270         /*
 271          * Size of reply descriptor post queue should be the number of
 272          * request frames + the number of reply frames + 1 and needs to
 273          * be a multiple of 16.  This size can be no larger than
 274          * MaxReplyDescriptorPostQueueDepth from IOCFacts.  If the
 275          * calculated queue size is larger than allowed, subtract a
 276          * multiple of 16 from m_max_requests, m_max_replies, and
 277          * m_reply_free_depth.
 278          */
 279         queueSize = mpt->m_max_requests + numReplyFrames + 1;
 280         if (queueSize % 16) {
 281                 queueSize += 16 - (queueSize % 16);
 282         }
 283         mpt->m_post_queue_depth = ddi_get16(accessp,
 284             &factsreply->MaxReplyDescriptorPostQueueDepth);
 285         if (queueSize > mpt->m_post_queue_depth) {
 286                 queueDiff = queueSize - mpt->m_post_queue_depth;
 287                 if (queueDiff % 16) {
 288                         queueDiff += 16 - (queueDiff % 16);
 289                 }
 290                 mpt->m_max_requests -= queueDiff;
 291                 mpt->m_max_replies -= queueDiff;
 292                 mpt->m_free_queue_depth -= queueDiff;
 293                 queueSize -= queueDiff;
 294         }
 295         mpt->m_post_queue_depth = queueSize;
 296 
 297         /*
 298          * Set up max chain depth.
 299          */
 300         mpt->m_max_chain_depth = ddi_get8(accessp,
 301             &factsreply->MaxChainDepth);
 302         mpt->m_ioc_capabilities = ddi_get32(accessp,
 303             &factsreply->IOCCapabilities);
 304 
 305         /*
 306          * Set flag to check for SAS3 support.
 307          */
 308         msgversion = ddi_get16(accessp, &factsreply->MsgVersion);
 309         if (msgversion == MPI2_VERSION_02_05) {
 310                 mptsas_log(mpt, CE_NOTE, "?mpt_sas%d SAS 3 Supported\n",
 311                     mpt->m_instance);
 312                 mpt->m_MPI25 = TRUE;
 313         } else {
 314                 mptsas_log(mpt, CE_NOTE, "?mpt_sas%d MPI Version 0x%x\n",
 315                     mpt->m_instance, msgversion);
 316         }
 317 
 318         /*
 319          * Calculate max frames per request based on DMA S/G length.
 320          */
 321         simple_sge_main = MPTSAS_MAX_FRAME_SGES64(mpt) - 1;
 322         simple_sge_next = mpt->m_req_frame_size / MPTSAS_SGE_SIZE(mpt) - 1;
 323 
 324         mpt->m_max_request_frames = (MPTSAS_MAX_DMA_SEGS -
 325             simple_sge_main) / simple_sge_next + 1;
 326         if (((MPTSAS_MAX_DMA_SEGS - simple_sge_main) %
 327             simple_sge_next) > 1) {
 328                 mpt->m_max_request_frames++;
 329         }
 330 
 331         /*
 332          * Check if controller supports FW diag buffers and set flag to enable
 333          * each type.
 334          */
 335         capabilities = ddi_get32(accessp, &factsreply->IOCCapabilities);
 336         if (capabilities & MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
 337                 mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled =
 338                     TRUE;
 339         }
 340         if (capabilities & MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
 341                 mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT].
 342                     enabled = TRUE;
 343         }
 344         if (capabilities & MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
 345                 mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED].
 346                     enabled = TRUE;
 347         }
 348 
 349         /*
 350          * Check if controller supports replaying events when issuing Message
 351          * Unit Reset and set flag to enable MUR.
 352          */
 353         if (capabilities & MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) {
 354                 mpt->m_event_replay = TRUE;
 355         }
 356 
 357         /*
 358          * Check if controller supports IR.
 359          */
 360         if (capabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
 361                 mpt->m_ir_capable = TRUE;
 362         }
 363 
 364         return (DDI_SUCCESS);
 365 }
 366 
 367 int
 368 mptsas_ioc_get_port_facts(mptsas_t *mpt, int port)
 369 {
 370         /*
 371          * Send get port facts message
 372          */
 373         if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_FACTS_REQUEST), port,
 374             mptsas_ioc_do_get_port_facts)) {
 375                 return (DDI_FAILURE);
 376         }
 377 
 378         /*
 379          * Get port facts reply message
 380          */
 381         if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_FACTS_REPLY), port,
 382             mptsas_ioc_do_get_port_facts_reply)) {
 383                 return (DDI_FAILURE);
 384         }
 385 
 386         return (DDI_SUCCESS);
 387 }
 388 
 389 static int
 390 mptsas_ioc_do_get_port_facts(mptsas_t *mpt, caddr_t memp, int var,
 391                         ddi_acc_handle_t accessp)
 392 {
 393         pMpi2PortFactsRequest_t facts;
 394         int                     numbytes;
 395 
 396         bzero(memp, sizeof (*facts));
 397         facts = (void *)memp;
 398         ddi_put8(accessp, &facts->Function, MPI2_FUNCTION_PORT_FACTS);
 399         ddi_put8(accessp, &facts->PortNumber, var);
 400         numbytes = sizeof (*facts);
 401 
 402         /*
 403          * Send port facts message via handshake
 404          */
 405         if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
 406                 return (DDI_FAILURE);
 407         }
 408 
 409         return (DDI_SUCCESS);
 410 }
 411 
 412 static int
 413 mptsas_ioc_do_get_port_facts_reply(mptsas_t *mpt, caddr_t memp, int var,
 414                                 ddi_acc_handle_t accessp)
 415 {
 416 #ifndef __lock_lint
 417         _NOTE(ARGUNUSED(var))
 418 #endif
 419         pMpi2PortFactsReply_t   factsreply;
 420         int                     numbytes;
 421         uint_t                  iocstatus;
 422 
 423         bzero(memp, sizeof (*factsreply));
 424         factsreply = (void *)memp;
 425         numbytes = sizeof (*factsreply);
 426 
 427         /*
 428          * Get port facts reply message via handshake
 429          */
 430         if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
 431                 return (DDI_FAILURE);
 432         }
 433 
 434         if (iocstatus = ddi_get16(accessp, &factsreply->IOCStatus)) {
 435                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_get_port_facts_reply: "
 436                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
 437                     ddi_get32(accessp, &factsreply->IOCLogInfo));
 438                 return (DDI_FAILURE);
 439         }
 440 
 441         return (DDI_SUCCESS);
 442 }
 443 
 444 int
 445 mptsas_ioc_enable_port(mptsas_t *mpt)
 446 {
 447         /*
 448          * Send enable port message
 449          */
 450         if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_ENABLE_REQUEST), 0,
 451             mptsas_ioc_do_enable_port)) {
 452                 return (DDI_FAILURE);
 453         }
 454 
 455         /*
 456          * Get enable port reply message
 457          */
 458         if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_ENABLE_REPLY), 0,
 459             mptsas_ioc_do_enable_port_reply)) {
 460                 return (DDI_FAILURE);
 461         }
 462 
 463         return (DDI_SUCCESS);
 464 }
 465 
 466 static int
 467 mptsas_ioc_do_enable_port(mptsas_t *mpt, caddr_t memp, int var,
 468         ddi_acc_handle_t accessp)
 469 {
 470 #ifndef __lock_lint
 471         _NOTE(ARGUNUSED(var))
 472 #endif
 473         pMpi2PortEnableRequest_t        enable;
 474         int                             numbytes;
 475 
 476         bzero(memp, sizeof (*enable));
 477         enable = (void *)memp;
 478         ddi_put8(accessp, &enable->Function, MPI2_FUNCTION_PORT_ENABLE);
 479         numbytes = sizeof (*enable);
 480 
 481         /*
 482          * Send message via handshake
 483          */
 484         if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
 485                 return (DDI_FAILURE);
 486         }
 487 
 488         return (DDI_SUCCESS);
 489 }
 490 
 491 static int
 492 mptsas_ioc_do_enable_port_reply(mptsas_t *mpt, caddr_t memp, int var,
 493         ddi_acc_handle_t accessp)
 494 {
 495 #ifndef __lock_lint
 496         _NOTE(ARGUNUSED(var))
 497 #endif
 498 
 499         int                     numbytes;
 500         uint_t                  iocstatus;
 501         pMpi2PortEnableReply_t  portreply;
 502 
 503         numbytes = sizeof (MPI2_PORT_ENABLE_REPLY);
 504         bzero(memp, numbytes);
 505         portreply = (void *)memp;
 506 
 507         /*
 508          * Get message via handshake
 509          */
 510         if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
 511                 return (DDI_FAILURE);
 512         }
 513 
 514         if (iocstatus = ddi_get16(accessp, &portreply->IOCStatus)) {
 515                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_enable_port_reply: "
 516                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
 517                     ddi_get32(accessp, &portreply->IOCLogInfo));
 518                 return (DDI_FAILURE);
 519         }
 520 
 521         return (DDI_SUCCESS);
 522 }
 523 
 524 int
 525 mptsas_ioc_enable_event_notification(mptsas_t *mpt)
 526 {
 527         ASSERT(mutex_owned(&mpt->m_mutex));
 528 
 529         /*
 530          * Send enable event notification message
 531          */
 532         if (mptsas_do_dma(mpt, sizeof (MPI2_EVENT_NOTIFICATION_REQUEST), NULL,
 533             mptsas_ioc_do_enable_event_notification)) {
 534                 return (DDI_FAILURE);
 535         }
 536 
 537         /*
 538          * Get enable event reply message
 539          */
 540         if (mptsas_do_dma(mpt, sizeof (MPI2_EVENT_NOTIFICATION_REPLY), NULL,
 541             mptsas_ioc_do_enable_event_notification_reply)) {
 542                 return (DDI_FAILURE);
 543         }
 544 
 545         return (DDI_SUCCESS);
 546 }
 547 
 548 static int
 549 mptsas_ioc_do_enable_event_notification(mptsas_t *mpt, caddr_t memp, int var,
 550         ddi_acc_handle_t accessp)
 551 {
 552 #ifndef __lock_lint
 553         _NOTE(ARGUNUSED(var))
 554 #endif
 555 
 556         pMpi2EventNotificationRequest_t event;
 557         int                             numbytes;
 558 
 559         bzero(memp, sizeof (*event));
 560         event = (void *)memp;
 561         ddi_put8(accessp, &event->Function, MPI2_FUNCTION_EVENT_NOTIFICATION);
 562         numbytes = sizeof (*event);
 563 
 564         /*
 565          * Send message via handshake
 566          */
 567         if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
 568                 return (DDI_FAILURE);
 569         }
 570 
 571         return (DDI_SUCCESS);
 572 }
 573 
 574 static int
 575 mptsas_ioc_do_enable_event_notification_reply(mptsas_t *mpt, caddr_t memp,
 576     int var, ddi_acc_handle_t accessp)
 577 {
 578 #ifndef __lock_lint
 579         _NOTE(ARGUNUSED(var))
 580 #endif
 581         int                             numbytes;
 582         uint_t                          iocstatus;
 583         pMpi2EventNotificationReply_t   eventsreply;
 584 
 585         numbytes = sizeof (MPI2_EVENT_NOTIFICATION_REPLY);
 586         bzero(memp, numbytes);
 587         eventsreply = (void *)memp;
 588 
 589         /*
 590          * Get message via handshake
 591          */
 592         if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
 593                 return (DDI_FAILURE);
 594         }
 595 
 596         if (iocstatus = ddi_get16(accessp, &eventsreply->IOCStatus)) {
 597                 mptsas_log(mpt, CE_WARN,
 598                     "mptsas_ioc_do_enable_event_notification_reply: "
 599                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
 600                     ddi_get32(accessp, &eventsreply->IOCLogInfo));
 601                 return (DDI_FAILURE);
 602         }
 603 
 604         return (DDI_SUCCESS);
 605 }
 606 
 607 int
 608 mptsas_ioc_init(mptsas_t *mpt)
 609 {
 610         /*
 611          * Send ioc init message
 612          */
 613         if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_INIT_REQUEST), NULL,
 614             mptsas_do_ioc_init)) {
 615                 return (DDI_FAILURE);
 616         }
 617 
 618         /*
 619          * Get ioc init reply message
 620          */
 621         if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_INIT_REPLY), NULL,
 622             mptsas_do_ioc_init_reply)) {
 623                 return (DDI_FAILURE);
 624         }
 625 
 626         return (DDI_SUCCESS);
 627 }
 628 
 629 static int
 630 mptsas_do_ioc_init(mptsas_t *mpt, caddr_t memp, int var,
 631     ddi_acc_handle_t accessp)
 632 {
 633 #ifndef __lock_lint
 634         _NOTE(ARGUNUSED(var))
 635 #endif
 636 
 637         pMpi2IOCInitRequest_t   init;
 638         int                     numbytes;
 639         timespec_t              time;
 640         uint64_t                mSec;
 641 
 642         bzero(memp, sizeof (*init));
 643         init = (void *)memp;
 644         ddi_put8(accessp, &init->Function, MPI2_FUNCTION_IOC_INIT);
 645         ddi_put8(accessp, &init->WhoInit, MPI2_WHOINIT_HOST_DRIVER);
 646         ddi_put16(accessp, &init->MsgVersion, MPI2_VERSION);
 647         ddi_put16(accessp, &init->HeaderVersion, MPI2_HEADER_VERSION);
 648         ddi_put16(accessp, &init->SystemRequestFrameSize,
 649             mpt->m_req_frame_size / 4);
 650         ddi_put16(accessp, &init->ReplyDescriptorPostQueueDepth,
 651             mpt->m_post_queue_depth);
 652         ddi_put16(accessp, &init->ReplyFreeQueueDepth,
 653             mpt->m_free_queue_depth);
 654 
 655         /*
 656          * These addresses are set using the DMA cookie addresses from when the
 657          * memory was allocated.  Sense buffer hi address should be 0.
 658          */
 659         ddi_put32(accessp, &init->SenseBufferAddressHigh,
 660             (uint32_t)(mpt->m_req_sense_dma_addr >> 32));
 661         ddi_put32(accessp, &init->SystemReplyAddressHigh,
 662             (uint32_t)(mpt->m_reply_frame_dma_addr >> 32));
 663         ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.High,
 664             (uint32_t)(mpt->m_req_frame_dma_addr >> 32));
 665         ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.Low,
 666             (uint32_t)mpt->m_req_frame_dma_addr);
 667         ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.High,
 668             (uint32_t)(mpt->m_post_queue_dma_addr >> 32));
 669         ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.Low,
 670             (uint32_t)mpt->m_post_queue_dma_addr);
 671         ddi_put32(accessp, &init->ReplyFreeQueueAddress.High,
 672             (uint32_t)(mpt->m_free_queue_dma_addr >> 32));
 673         ddi_put32(accessp, &init->ReplyFreeQueueAddress.Low,
 674             (uint32_t)mpt->m_free_queue_dma_addr);
 675 
 676         /*
 677          * Fill in the timestamp with the number of milliseconds since midnight
 678          * of January 1, 1970 UT (Greenwich Mean Time).  Time is returned in
 679          * seconds and nanoseconds.  Translate both to milliseconds and add
 680          * them together to get total milliseconds.
 681          */
 682         gethrestime(&time);
 683         mSec = time.tv_sec * MILLISEC;
 684         mSec += (time.tv_nsec / MICROSEC);
 685         ddi_put32(accessp, &init->TimeStamp.High, (uint32_t)(mSec >> 32));
 686         ddi_put32(accessp, &init->TimeStamp.Low, (uint32_t)mSec);
 687 
 688         numbytes = sizeof (*init);
 689 
 690         /*
 691          * Post message via handshake
 692          */
 693         if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
 694                 return (DDI_FAILURE);
 695         }
 696 
 697         return (DDI_SUCCESS);
 698 }
 699 
 700 static int
 701 mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var,
 702                 ddi_acc_handle_t accessp)
 703 {
 704 #ifndef __lock_lint
 705         _NOTE(ARGUNUSED(var))
 706 #endif
 707 
 708         pMpi2IOCInitReply_t     initreply;
 709         int                     numbytes;
 710         uint_t                  iocstatus;
 711 
 712         numbytes = sizeof (MPI2_IOC_INIT_REPLY);
 713         bzero(memp, numbytes);
 714         initreply = (void *)memp;
 715 
 716         /*
 717          * Get reply message via handshake
 718          */
 719         if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
 720                 return (DDI_FAILURE);
 721         }
 722 
 723         if (iocstatus = ddi_get16(accessp, &initreply->IOCStatus)) {
 724                 mptsas_log(mpt, CE_WARN, "mptsas_do_ioc_init_reply: "
 725                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
 726                     ddi_get32(accessp, &initreply->IOCLogInfo));
 727                 return (DDI_FAILURE);
 728         }
 729 
 730         if ((ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell)) &
 731             MPI2_IOC_STATE_OPERATIONAL) {
 732                 mptsas_log(mpt, CE_NOTE,
 733                     "?mpt%d: IOC Operational.\n", mpt->m_instance);
 734         } else {
 735                 return (DDI_FAILURE);
 736         }
 737 
 738         return (DDI_SUCCESS);
 739 }