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