Print this page
Update tx waitq's code.
Create 2 threads, divide the workflow and deliver
to the hardware from the threads.
Enable Fast Path for capable devices.
Lint and cstyle fixes.
Fix problem with running against 64bit msgaddr attributes for DMA.
Default is now to run like this.
Major rework of mutexes.
During normal operation do not grab m_mutex during interrupt.
Use reply post queues instead.
Fixes to some address arithmetic using 32bit values.
Merge fixes for "4403 mpt_sas panic when pulling a drive", commit f7d0d869a9ae78d
Initial modifications using the code changes present between
the LSI source code for FreeBSD drivers. Specifically the changes
between from mpslsi-source-17.00.00.00 -> mpslsi-source-03.00.00.00.
This mainly involves using a different scatter/gather element in
frame setup.
Changes to enable driver to compile.
Header paths, object lists, etc.


   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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.


  25  */
  26 
  27 /*
  28  * Copyright (c) 2000 to 2010, 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,


  51  * DAMAGE.
  52  */
  53 
  54 /*
  55  * mptsas_impl - This file contains all the basic functions for communicating
  56  * to MPT 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 #include <sys/pci.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_sas.h>
  77 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
  78 #pragma pack()
  79 
  80 /*
  81  * private header files.
  82  */
  83 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
  84 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
  85 
  86 /*
  87  * FMA header files.
  88  */
  89 #include <sys/fm/io/ddi.h>
  90 
  91 #if defined(MPTSAS_DEBUG)
  92 extern uint32_t mptsas_debug_flags;

  93 #endif
  94 
  95 /*
  96  *  prototypes
  97  */
  98 static void mptsas_ioc_event_cmdq_add(mptsas_t *mpt, m_event_struct_t *cmd);
  99 static void mptsas_ioc_event_cmdq_delete(mptsas_t *mpt, m_event_struct_t *cmd);
 100 static m_event_struct_t *mptsas_ioc_event_find_by_cmd(mptsas_t *mpt,
 101     struct mptsas_cmd *cmd);
 102 
 103 /*
 104  * add ioc evnet cmd into the queue
 105  */
 106 static void
 107 mptsas_ioc_event_cmdq_add(mptsas_t *mpt, m_event_struct_t *cmd)
 108 {
 109         if ((cmd->m_event_linkp = mpt->m_ioc_event_cmdq) == NULL) {
 110                 mpt->m_ioc_event_cmdtail = &cmd->m_event_linkp;
 111                 mpt->m_ioc_event_cmdq = cmd;
 112         } else {


 188                 } else {
 189                         /*
 190                          * it's not ack cmd, so continue to check next one
 191                          */
 192 
 193                         NDBG20(("destroy!! it's not Ack Flag, continue\n"));
 194                         ioc_cmd = ioc_cmd->m_event_linkp;
 195                 }
 196 
 197         }
 198 }
 199 
 200 void
 201 mptsas_start_config_page_access(mptsas_t *mpt, mptsas_cmd_t *cmd)
 202 {
 203         pMpi2ConfigRequest_t    request;
 204         pMpi2SGESimple64_t      sge;
 205         struct scsi_pkt         *pkt = cmd->cmd_pkt;
 206         mptsas_config_request_t *config = pkt->pkt_ha_private;
 207         uint8_t                 direction;
 208         uint32_t                length, flagslength, request_desc_low;

 209 
 210         ASSERT(mutex_owned(&mpt->m_mutex));
 211 
 212         /*
 213          * Point to the correct message and clear it as well as the global
 214          * config page memory.
 215          */
 216         request = (pMpi2ConfigRequest_t)(mpt->m_req_frame +
 217             (mpt->m_req_frame_size * cmd->cmd_slot));
 218         bzero(request, mpt->m_req_frame_size);
 219 
 220         /*
 221          * Form the request message.
 222          */
 223         ddi_put8(mpt->m_acc_req_frame_hdl, &request->Function,
 224             MPI2_FUNCTION_CONFIG);
 225         ddi_put8(mpt->m_acc_req_frame_hdl, &request->Action, config->action);
 226         direction = MPI2_SGE_FLAGS_IOC_TO_HOST;
 227         length = 0;
 228         sge = (pMpi2SGESimple64_t)&request->PageBufferSGE;


 242                     config->ext_page_type);
 243                 ddi_put16(mpt->m_acc_req_frame_hdl, &request->ExtPageLength,
 244                     config->ext_page_length);
 245                 ddi_put8(mpt->m_acc_req_frame_hdl, &request->Header.PageType,
 246                     config->page_type);
 247                 ddi_put8(mpt->m_acc_req_frame_hdl, &request->Header.PageLength,
 248                     config->page_length);
 249                 ddi_put8(mpt->m_acc_req_frame_hdl,
 250                     &request->Header.PageVersion, config->page_version);
 251                 if ((config->page_type & MPI2_CONFIG_PAGETYPE_MASK) ==
 252                     MPI2_CONFIG_PAGETYPE_EXTENDED) {
 253                         length = config->ext_page_length * 4;
 254                 } else {
 255                         length = config->page_length * 4;
 256                 }
 257 
 258                 if (config->action == MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
 259                         direction = MPI2_SGE_FLAGS_HOST_TO_IOC;
 260                 }
 261                 ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.Low,
 262                     (uint32_t)cmd->cmd_dma_addr);
 263                 ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.High,
 264                     (uint32_t)(cmd->cmd_dma_addr >> 32));
 265         }
 266         ddi_put8(mpt->m_acc_req_frame_hdl, &request->Header.PageNumber,
 267             config->page_number);
 268         ddi_put32(mpt->m_acc_req_frame_hdl, &request->PageAddress,
 269             config->page_address);
 270         flagslength = ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
 271             MPI2_SGE_FLAGS_END_OF_BUFFER |
 272             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
 273             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
 274             MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
 275             direction |
 276             MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
 277         flagslength |= length;
 278         ddi_put32(mpt->m_acc_req_frame_hdl, &sge->FlagsLength, flagslength);
 279 
 280         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
 281             DDI_DMA_SYNC_FORDEV);
 282         request_desc_low = (cmd->cmd_slot << 16) +
 283             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 284         cmd->cmd_rfm = NULL;
 285         MPTSAS_START_CMD(mpt, request_desc_low, 0);
 286         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
 287             DDI_SUCCESS) ||
 288             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
 289             DDI_SUCCESS)) {
 290                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
 291         }
 292 }
 293 
 294 int
 295 mptsas_access_config_page(mptsas_t *mpt, uint8_t action, uint8_t page_type,
 296     uint8_t page_number, uint32_t page_address, int (*callback) (mptsas_t *,
 297     caddr_t, ddi_acc_handle_t, uint16_t, uint32_t, va_list), ...)
 298 {
 299         va_list                 ap;
 300         ddi_dma_attr_t          attrs;
 301         ddi_dma_cookie_t        cookie;
 302         ddi_acc_handle_t        accessp;
 303         size_t                  len = 0;
 304         mptsas_config_request_t config;
 305         int                     rval = DDI_SUCCESS, config_flags = 0;
 306         mptsas_cmd_t            *cmd;
 307         struct scsi_pkt         *pkt;
 308         pMpi2ConfigReply_t      reply;
 309         uint16_t                iocstatus = 0;
 310         uint32_t                iocloginfo;
 311         caddr_t                 page_memp;

 312 
 313         va_start(ap, callback);
 314         ASSERT(mutex_owned(&mpt->m_mutex));
 315 
 316         /*
 317          * Get a command from the pool.
 318          */
 319         if ((rval = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
 320                 mptsas_log(mpt, CE_NOTE, "command pool is full for config "
 321                     "page request");
 322                 rval = DDI_FAILURE;
 323                 goto page_done;
 324         }
 325         config_flags |= MPTSAS_REQUEST_POOL_CMD;
 326 
 327         bzero((caddr_t)cmd, sizeof (*cmd));
 328         bzero((caddr_t)pkt, scsi_pkt_size());
 329         bzero((caddr_t)&config, sizeof (config));
 330 
 331         /*


 374         }
 375 
 376         /*
 377          * Check if the header request completed without timing out
 378          */
 379         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
 380                 mptsas_log(mpt, CE_WARN, "config header request timeout");
 381                 rval = DDI_FAILURE;
 382                 goto page_done;
 383         }
 384 
 385         /*
 386          * cmd_rfm points to the reply message if a reply was given.  Check the
 387          * IOCStatus to make sure everything went OK with the header request.
 388          */
 389         if (cmd->cmd_rfm) {
 390                 config_flags |= MPTSAS_ADDRESS_REPLY;
 391                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
 392                     DDI_DMA_SYNC_FORCPU);
 393                 reply = (pMpi2ConfigReply_t)(mpt->m_reply_frame + (cmd->cmd_rfm
 394                     - mpt->m_reply_frame_dma_addr));
 395                 config.page_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
 396                     &reply->Header.PageType);
 397                 config.page_number = ddi_get8(mpt->m_acc_reply_frame_hdl,
 398                     &reply->Header.PageNumber);
 399                 config.page_length = ddi_get8(mpt->m_acc_reply_frame_hdl,
 400                     &reply->Header.PageLength);
 401                 config.page_version = ddi_get8(mpt->m_acc_reply_frame_hdl,
 402                     &reply->Header.PageVersion);
 403                 config.ext_page_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
 404                     &reply->ExtPageType);
 405                 config.ext_page_length = ddi_get16(mpt->m_acc_reply_frame_hdl,
 406                     &reply->ExtPageLength);
 407 
 408                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
 409                     &reply->IOCStatus);
 410                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
 411                     &reply->IOCLogInfo);
 412 
 413                 if (iocstatus) {
 414                         NDBG13(("mptsas_access_config_page header: "


 448                         mpt->m_free_index = 0;
 449                 }
 450                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
 451                     mpt->m_free_index);
 452                 config_flags &= (~MPTSAS_ADDRESS_REPLY);
 453         }
 454 
 455         /*
 456          * Allocate DMA buffer here.  Store the info regarding this buffer in
 457          * the cmd struct so that it can be used for this specific command and
 458          * de-allocated after the command completes.  The size of the reply
 459          * will not be larger than the reply frame size.
 460          */
 461         attrs = mpt->m_msg_dma_attr;
 462         attrs.dma_attr_sgllen = 1;
 463         attrs.dma_attr_granular = (uint32_t)len;
 464 
 465         if (mptsas_dma_addr_create(mpt, attrs,
 466             &cmd->cmd_dmahandle, &accessp, &page_memp,
 467             len, &cookie) == FALSE) {



 468                 goto page_done;
 469         }



 470         cmd->cmd_dma_addr = cookie.dmac_laddress;
 471         bzero(page_memp, len);
 472 
 473         /*
 474          * Save the data for this request to be used in the call to start the
 475          * config page read
 476          */
 477         config.action = action;
 478         config.page_address = page_address;
 479 
 480         /*
 481          * Re-use the cmd that was used to get the header.  Reset some of the
 482          * values.
 483          */
 484         bzero((caddr_t)pkt, scsi_pkt_size());
 485         pkt->pkt_ha_private  = (opaque_t)&config;
 486         pkt->pkt_flags               = FLAG_HEAD;
 487         pkt->pkt_time                = 60;
 488         cmd->cmd_flags               = CFLAG_PREPARED | CFLAG_CMDIOC | CFLAG_CONFIG;
 489 


 513          * Check if the request completed without timing out
 514          */
 515         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
 516                 mptsas_log(mpt, CE_WARN, "config page request timeout");
 517                 rval = DDI_FAILURE;
 518                 goto page_done;
 519         }
 520 
 521         /*
 522          * cmd_rfm points to the reply message if a reply was given.  The reply
 523          * frame and the config page are returned from this function in the
 524          * param list.
 525          */
 526         if (cmd->cmd_rfm) {
 527                 config_flags |= MPTSAS_ADDRESS_REPLY;
 528                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
 529                     DDI_DMA_SYNC_FORCPU);
 530                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
 531                     DDI_DMA_SYNC_FORCPU);
 532                 reply = (pMpi2ConfigReply_t)(mpt->m_reply_frame + (cmd->cmd_rfm
 533                     - mpt->m_reply_frame_dma_addr));
 534                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
 535                     &reply->IOCStatus);
 536                 iocstatus = MPTSAS_IOCSTATUS(iocstatus);
 537                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
 538                     &reply->IOCLogInfo);
 539         }
 540 
 541         if (callback(mpt, page_memp, accessp, iocstatus, iocloginfo, ap)) {
 542                 rval = DDI_FAILURE;
 543                 goto page_done;
 544         }
 545 
 546         mptsas_fma_check(mpt, cmd);
 547         /*
 548          * Check the DMA/ACC handles and then free the DMA buffer.
 549          */
 550         if ((mptsas_check_dma_handle(cmd->cmd_dmahandle) != DDI_SUCCESS) ||
 551             (mptsas_check_acc_handle(accessp) != DDI_SUCCESS)) {
 552                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
 553                 rval = DDI_FAILURE;


 567 page_done:
 568         va_end(ap);
 569         /*
 570          * Put the reply frame back on the free queue, increment the free
 571          * index, and write the new index to the free index register.  But only
 572          * if this reply is an ADDRESS reply.
 573          */
 574         if (config_flags & MPTSAS_ADDRESS_REPLY) {
 575                 ddi_put32(mpt->m_acc_free_queue_hdl,
 576                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
 577                     cmd->cmd_rfm);
 578                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
 579                     DDI_DMA_SYNC_FORDEV);
 580                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
 581                         mpt->m_free_index = 0;
 582                 }
 583                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
 584                     mpt->m_free_index);
 585         }
 586 

 587         mptsas_dma_addr_destroy(&cmd->cmd_dmahandle, &accessp);
 588 
 589         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
 590                 mptsas_remove_cmd(mpt, cmd);
 591                 config_flags &= (~MPTSAS_REQUEST_POOL_CMD);
 592         }
 593         if (config_flags & MPTSAS_REQUEST_POOL_CMD)
 594                 mptsas_return_to_pool(mpt, cmd);
 595 
 596         if (config_flags & MPTSAS_CMD_TIMEOUT) {
 597                 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
 598                 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
 599                         mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
 600                 }
 601         }
 602 
 603         return (rval);
 604 }
 605 
 606 int
 607 mptsas_send_config_request_msg(mptsas_t *mpt, uint8_t action, uint8_t pagetype,
 608         uint32_t pageaddress, uint8_t pagenumber, uint8_t pageversion,
 609         uint8_t pagelength, uint32_t SGEflagslength, uint32_t SGEaddress32)
 610 {
 611         pMpi2ConfigRequest_t    config;
 612         int                     send_numbytes;
 613 
 614         bzero(mpt->m_hshk_memp, sizeof (MPI2_CONFIG_REQUEST));
 615         config = (pMpi2ConfigRequest_t)mpt->m_hshk_memp;
 616         ddi_put8(mpt->m_hshk_acc_hdl, &config->Function, MPI2_FUNCTION_CONFIG);
 617         ddi_put8(mpt->m_hshk_acc_hdl, &config->Action, action);
 618         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageNumber, pagenumber);
 619         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageType, pagetype);
 620         ddi_put32(mpt->m_hshk_acc_hdl, &config->PageAddress, pageaddress);
 621         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageVersion, pageversion);
 622         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageLength, pagelength);
 623         ddi_put32(mpt->m_hshk_acc_hdl,
 624             &config->PageBufferSGE.MpiSimple.FlagsLength, SGEflagslength);
 625         ddi_put32(mpt->m_hshk_acc_hdl,
 626             &config->PageBufferSGE.MpiSimple.u.Address32, SGEaddress32);




 627         send_numbytes = sizeof (MPI2_CONFIG_REQUEST);
 628 
 629         /*
 630          * Post message via handshake
 631          */
 632         if (mptsas_send_handshake_msg(mpt, (caddr_t)config, send_numbytes,
 633             mpt->m_hshk_acc_hdl)) {
 634                 return (-1);
 635         }
 636         return (0);
 637 }
 638 
 639 int
 640 mptsas_send_extended_config_request_msg(mptsas_t *mpt, uint8_t action,
 641         uint8_t extpagetype, uint32_t pageaddress, uint8_t pagenumber,
 642         uint8_t pageversion, uint16_t extpagelength,
 643         uint32_t SGEflagslength, uint32_t SGEaddress32)
 644 {
 645         pMpi2ConfigRequest_t    config;
 646         int                     send_numbytes;
 647 
 648         bzero(mpt->m_hshk_memp, sizeof (MPI2_CONFIG_REQUEST));
 649         config = (pMpi2ConfigRequest_t)mpt->m_hshk_memp;
 650         ddi_put8(mpt->m_hshk_acc_hdl, &config->Function, MPI2_FUNCTION_CONFIG);
 651         ddi_put8(mpt->m_hshk_acc_hdl, &config->Action, action);
 652         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageNumber, pagenumber);
 653         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageType,
 654             MPI2_CONFIG_PAGETYPE_EXTENDED);
 655         ddi_put8(mpt->m_hshk_acc_hdl, &config->ExtPageType, extpagetype);
 656         ddi_put32(mpt->m_hshk_acc_hdl, &config->PageAddress, pageaddress);
 657         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageVersion, pageversion);
 658         ddi_put16(mpt->m_hshk_acc_hdl, &config->ExtPageLength, extpagelength);
 659         ddi_put32(mpt->m_hshk_acc_hdl,
 660             &config->PageBufferSGE.MpiSimple.FlagsLength, SGEflagslength);
 661         ddi_put32(mpt->m_hshk_acc_hdl,
 662             &config->PageBufferSGE.MpiSimple.u.Address32, SGEaddress32);




 663         send_numbytes = sizeof (MPI2_CONFIG_REQUEST);
 664 
 665         /*
 666          * Post message via handshake
 667          */
 668         if (mptsas_send_handshake_msg(mpt, (caddr_t)config, send_numbytes,
 669             mpt->m_hshk_acc_hdl)) {
 670                 return (-1);
 671         }
 672         return (0);
 673 }
 674 
 675 int
 676 mptsas_ioc_wait_for_response(mptsas_t *mpt)
 677 {
 678         int     polls = 0;
 679 
 680         while ((ddi_get32(mpt->m_datap,
 681             &mpt->m_reg->HostInterruptStatus) & MPI2_HIS_IOP_DOORBELL_STATUS)) {
 682                 drv_usecwait(1000);


1070  * priority queue with its limit and the controller will reply as they are
1071  * completed.  This way, we don't have to poll for one reply at a time.
1072  * Think about enhancing this later.
1073  */
1074 int
1075 mptsas_ioc_task_management(mptsas_t *mpt, int task_type, uint16_t dev_handle,
1076         int lun, uint8_t *reply, uint32_t reply_size, int mode)
1077 {
1078         /*
1079          * In order to avoid allocating variables on the stack,
1080          * we make use of the pre-existing mptsas_cmd_t and
1081          * scsi_pkt which are included in the mptsas_t which
1082          * is passed to this routine.
1083          */
1084 
1085         pMpi2SCSITaskManagementRequest_t        task;
1086         int                                     rval = FALSE;
1087         mptsas_cmd_t                            *cmd;
1088         struct scsi_pkt                         *pkt;
1089         mptsas_slots_t                          *slots = mpt->m_active;
1090         uint32_t                                request_desc_low, i;

1091         pMPI2DefaultReply_t                     reply_msg;
1092 
1093         /*
1094          * Can't start another task management routine.
1095          */
1096         if (slots->m_slot[MPTSAS_TM_SLOT(mpt)] != NULL) {
1097                 mptsas_log(mpt, CE_WARN, "Can only start 1 task management"
1098                     " command at a time\n");
1099                 return (FALSE);
1100         }
1101 
1102         cmd = &(mpt->m_event_task_mgmt.m_event_cmd);
1103         pkt = &(mpt->m_event_task_mgmt.m_event_pkt);
1104 
1105         bzero((caddr_t)cmd, sizeof (*cmd));
1106         bzero((caddr_t)pkt, scsi_pkt_size());
1107 
1108         pkt->pkt_cdbp                = (opaque_t)&cmd->cmd_cdb[0];
1109         pkt->pkt_scbp                = (opaque_t)&cmd->cmd_scb;
1110         pkt->pkt_ha_private  = (opaque_t)cmd;


1126         task = (pMpi2SCSITaskManagementRequest_t)(mpt->m_req_frame +
1127             (mpt->m_req_frame_size * cmd->cmd_slot));
1128         bzero(task, mpt->m_req_frame_size);
1129 
1130         /*
1131          * form message for requested task
1132          */
1133         mptsas_init_std_hdr(mpt->m_acc_req_frame_hdl, task, dev_handle, lun, 0,
1134             MPI2_FUNCTION_SCSI_TASK_MGMT);
1135 
1136         /*
1137          * Set the task type
1138          */
1139         ddi_put8(mpt->m_acc_req_frame_hdl, &task->TaskType, task_type);
1140 
1141         /*
1142          * Send TM request using High Priority Queue.
1143          */
1144         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
1145             DDI_DMA_SYNC_FORDEV);
1146         request_desc_low = (cmd->cmd_slot << 16) +
1147             MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
1148         MPTSAS_START_CMD(mpt, request_desc_low, 0);
1149         rval = mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
1150 
1151         if (pkt->pkt_reason == CMD_INCOMPLETE)
1152                 rval = FALSE;
1153 
1154         /*
1155          * If a reply frame was used and there is a reply buffer to copy the
1156          * reply data into, copy it.  If this fails, log a message, but don't
1157          * fail the TM request.
1158          */
1159         if (cmd->cmd_rfm && reply) {
1160                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
1161                     DDI_DMA_SYNC_FORCPU);
1162                 reply_msg = (pMPI2DefaultReply_t)
1163                     (mpt->m_reply_frame + (cmd->cmd_rfm -
1164                     mpt->m_reply_frame_dma_addr));
1165                 if (reply_size > sizeof (MPI2_SCSI_TASK_MANAGE_REPLY)) {
1166                         reply_size = sizeof (MPI2_SCSI_TASK_MANAGE_REPLY);
1167                 }
1168                 mutex_exit(&mpt->m_mutex);
1169                 for (i = 0; i < reply_size; i++) {
1170                         if (ddi_copyout((uint8_t *)reply_msg + i, reply + i, 1,
1171                             mode)) {
1172                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
1173                                     "reply data for TM request");
1174                                 break;
1175                         }
1176                 }
1177                 mutex_enter(&mpt->m_mutex);
1178         }
1179 
1180         /*
1181          * clear the TM slot before returning
1182          */
1183         slots->m_slot[MPTSAS_TM_SLOT(mpt)] = NULL;
1184 
1185         /*
1186          * If we lost our task management command
1187          * we need to reset the ioc
1188          */
1189         if (rval == FALSE) {
1190                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_task_management failed "
1191                     "try to reset ioc to recovery!");
1192                 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
1193                 if (mptsas_restart_ioc(mpt)) {
1194                         mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
1195                         rval = FAILED;
1196                 }
1197         }
1198 
1199         return (rval);
1200 }
1201 













































































1202 int
1203 mptsas_update_flash(mptsas_t *mpt, caddr_t ptrbuffer, uint32_t size,
1204     uint8_t type, int mode)
1205 {
1206 
1207         /*
1208          * In order to avoid allocating variables on the stack,
1209          * we make use of the pre-existing mptsas_cmd_t and
1210          * scsi_pkt which are included in the mptsas_t which
1211          * is passed to this routine.
1212          */
1213 
1214         ddi_dma_attr_t          flsh_dma_attrs;
1215         ddi_dma_cookie_t        flsh_cookie;
1216         ddi_dma_handle_t        flsh_dma_handle;
1217         ddi_acc_handle_t        flsh_accessp;
1218         caddr_t                 memp, flsh_memp;
1219         uint32_t                flagslength;
1220         pMpi2FWDownloadRequest  fwdownload;
1221         pMpi2FWDownloadTCSGE_t  tcsge;
1222         pMpi2SGESimple64_t      sge;
1223         mptsas_cmd_t            *cmd;
1224         struct scsi_pkt         *pkt;
1225         int                     i;
1226         int                     rvalue = 0;
1227         uint32_t                request_desc_low;













1228 
1229         if ((rvalue = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
1230                 mptsas_log(mpt, CE_WARN, "mptsas_update_flash(): allocation "
1231                     "failed. event ack command pool is full\n");
1232                 return (rvalue);
1233         }
1234 
1235         bzero((caddr_t)cmd, sizeof (*cmd));
1236         bzero((caddr_t)pkt, scsi_pkt_size());
1237         cmd->ioc_cmd_slot = (uint32_t)rvalue;
1238 
1239         /*
1240          * dynamically create a customized dma attribute structure
1241          * that describes the flash file.
1242          */
1243         flsh_dma_attrs = mpt->m_msg_dma_attr;
1244         flsh_dma_attrs.dma_attr_sgllen = 1;
1245 
1246         if (mptsas_dma_addr_create(mpt, flsh_dma_attrs, &flsh_dma_handle,
1247             &flsh_accessp, &flsh_memp, size, &flsh_cookie) == FALSE) {


1268         pkt->pkt_time                = 60;
1269         cmd->cmd_pkt         = pkt;
1270         cmd->cmd_scblen              = 1;
1271         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_CMD;
1272 
1273         /*
1274          * Save the command in a slot
1275          */
1276         if (mptsas_save_cmd(mpt, cmd) == FALSE) {
1277                 mptsas_dma_addr_destroy(&flsh_dma_handle, &flsh_accessp);
1278                 mptsas_return_to_pool(mpt, cmd);
1279                 return (-1);
1280         }
1281 
1282         /*
1283          * Fill in fw download message
1284          */
1285         ASSERT(cmd->cmd_slot != 0);
1286         memp = mpt->m_req_frame + (mpt->m_req_frame_size * cmd->cmd_slot);
1287         bzero(memp, mpt->m_req_frame_size);
1288         fwdownload = (void *)memp;
1289         ddi_put8(mpt->m_acc_req_frame_hdl, &fwdownload->Function,
1290             MPI2_FUNCTION_FW_DOWNLOAD);
1291         ddi_put8(mpt->m_acc_req_frame_hdl, &fwdownload->ImageType, type);
1292         ddi_put8(mpt->m_acc_req_frame_hdl, &fwdownload->MsgFlags,
1293             MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT);
1294         ddi_put32(mpt->m_acc_req_frame_hdl, &fwdownload->TotalImageSize, size);
1295 
1296         tcsge = (pMpi2FWDownloadTCSGE_t)&fwdownload->SGL;
1297         ddi_put8(mpt->m_acc_req_frame_hdl, &tcsge->ContextSize, 0);
1298         ddi_put8(mpt->m_acc_req_frame_hdl, &tcsge->DetailsLength, 12);
1299         ddi_put8(mpt->m_acc_req_frame_hdl, &tcsge->Flags, 0);
1300         ddi_put32(mpt->m_acc_req_frame_hdl, &tcsge->ImageOffset, 0);
1301         ddi_put32(mpt->m_acc_req_frame_hdl, &tcsge->ImageSize, size);
1302 
1303         sge = (pMpi2SGESimple64_t)(tcsge + 1);
1304         flagslength = size;
1305         flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
1306             MPI2_SGE_FLAGS_END_OF_BUFFER |
1307             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1308             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
1309             MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
1310             MPI2_SGE_FLAGS_HOST_TO_IOC |
1311             MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
1312         ddi_put32(mpt->m_acc_req_frame_hdl, &sge->FlagsLength, flagslength);
1313         ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.Low,
1314             flsh_cookie.dmac_address);
1315         ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.High,
1316             (uint32_t)(flsh_cookie.dmac_laddress >> 32));
1317 
1318         /*
1319          * Start command
1320          */
1321         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
1322             DDI_DMA_SYNC_FORDEV);
1323         request_desc_low = (cmd->cmd_slot << 16) +
1324             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1325         cmd->cmd_rfm = NULL;
1326         MPTSAS_START_CMD(mpt, request_desc_low, 0);
1327 
1328         rvalue = 0;
1329         (void) cv_reltimedwait(&mpt->m_fw_cv, &mpt->m_mutex,
1330             drv_usectohz(60 * MICROSEC), TR_CLOCK_TICK);
1331         if (!(cmd->cmd_flags & CFLAG_FINISHED)) {
1332                 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
1333                 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
1334                         mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
1335                 }
1336                 rvalue = -1;
1337         }
1338         mptsas_remove_cmd(mpt, cmd);
1339         mptsas_dma_addr_destroy(&flsh_dma_handle, &flsh_accessp);
1340 
1341         return (rvalue);
1342 }
1343 
1344 static int
1345 mptsas_sasdevpage_0_cb(mptsas_t *mpt, caddr_t page_memp,
1346     ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
1347     va_list ap)
1348 {
1349 #ifndef __lock_lint
1350         _NOTE(ARGUNUSED(ap))
1351 #endif
1352         pMpi2SasDevicePage0_t   sasdevpage;
1353         int                     rval = DDI_SUCCESS, i;
1354         uint8_t                 *sas_addr = NULL;
1355         uint8_t                 tmp_sas_wwn[SAS_WWN_BYTE_SIZE];
1356         uint16_t                *devhdl, *bay_num, *enclosure;
1357         uint64_t                *sas_wwn;
1358         uint32_t                *dev_info;
1359         uint8_t                 *physport, *phynum;
1360         uint16_t                *pdevhdl;
1361         uint32_t                page_address;
1362 
1363         if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) &&
1364             (iocstatus != MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)) {
1365                 mptsas_log(mpt, CE_WARN, "mptsas_get_sas_device_page0 "
1366                     "header: IOCStatus=0x%x, IOCLogInfo=0x%x",
1367                     iocstatus, iocloginfo);
1368                 rval = DDI_FAILURE;
1369                 return (rval);
1370         }
1371         page_address = va_arg(ap, uint32_t);
1372         /*
1373          * The INVALID_PAGE status is normal if using GET_NEXT_HANDLE and there
1374          * are no more pages.  If everything is OK up to this point but the
1375          * status is INVALID_PAGE, change rval to FAILURE and quit.  Also,
1376          * signal that device traversal is complete.
1377          */
1378         if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
1379                 if ((page_address & MPI2_SAS_DEVICE_PGAD_FORM_MASK) ==
1380                     MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE) {
1381                         mpt->m_done_traverse_dev = 1;
1382                 }
1383                 rval = DDI_FAILURE;
1384                 return (rval);
1385         }
1386         devhdl = va_arg(ap, uint16_t *);
1387         sas_wwn = va_arg(ap, uint64_t *);
1388         dev_info = va_arg(ap, uint32_t *);
1389         physport = va_arg(ap, uint8_t *);
1390         phynum = va_arg(ap, uint8_t *);
1391         pdevhdl = va_arg(ap, uint16_t *);
1392         bay_num = va_arg(ap, uint16_t *);
1393         enclosure = va_arg(ap, uint16_t *);
1394 
1395 
1396         sasdevpage = (pMpi2SasDevicePage0_t)page_memp;
1397 
1398         *dev_info = ddi_get32(accessp, &sasdevpage->DeviceInfo);
1399         *devhdl = ddi_get16(accessp, &sasdevpage->DevHandle);
1400         sas_addr = (uint8_t *)(&sasdevpage->SASAddress);
1401         for (i = 0; i < SAS_WWN_BYTE_SIZE; i++) {
1402                 tmp_sas_wwn[i] = ddi_get8(accessp, sas_addr + i);
1403         }
1404         bcopy(tmp_sas_wwn, sas_wwn, SAS_WWN_BYTE_SIZE);
1405         *sas_wwn = LE_64(*sas_wwn);
1406         *physport = ddi_get8(accessp, &sasdevpage->PhysicalPort);
1407         *phynum = ddi_get8(accessp, &sasdevpage->PhyNum);
1408         *pdevhdl = ddi_get16(accessp, &sasdevpage->ParentDevHandle);
1409         *bay_num = ddi_get16(accessp, &sasdevpage->Slot);
1410         *enclosure = ddi_get16(accessp, &sasdevpage->EnclosureHandle);













1411         return (rval);
1412 }
1413 
1414 /*
1415  * Request MPI configuration page SAS device page 0 to get DevHandle, device
1416  * info and SAS address.
1417  */
1418 int
1419 mptsas_get_sas_device_page0(mptsas_t *mpt, uint32_t page_address,
1420     uint16_t *dev_handle, uint64_t *sas_wwn, uint32_t *dev_info,
1421     uint8_t *physport, uint8_t *phynum, uint16_t *pdev_handle,
1422     uint16_t *bay_num, uint16_t *enclosure)
1423 {
1424         int rval = DDI_SUCCESS;
1425 
1426         ASSERT(mutex_owned(&mpt->m_mutex));
1427 
1428         /*
1429          * Get the header and config page.  reply contains the reply frame,
1430          * which holds status info for the request.
1431          */
1432         rval = mptsas_access_config_page(mpt,
1433             MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
1434             MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0, page_address,
1435             mptsas_sasdevpage_0_cb, page_address, dev_handle, sas_wwn,
1436             dev_info, physport, phynum, pdev_handle,
1437             bay_num, enclosure);
1438 
1439         return (rval);
1440 }
1441 
1442 static int
1443 mptsas_sasexpdpage_0_cb(mptsas_t *mpt, caddr_t page_memp,
1444     ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
1445     va_list ap)
1446 {
1447 #ifndef __lock_lint
1448         _NOTE(ARGUNUSED(ap))
1449 #endif
1450         pMpi2ExpanderPage0_t    expddevpage;
1451         int                     rval = DDI_SUCCESS, i;
1452         uint8_t                 *sas_addr = NULL;
1453         uint8_t                 tmp_sas_wwn[SAS_WWN_BYTE_SIZE];
1454         uint16_t                *devhdl;
1455         uint64_t                *sas_wwn;
1456         uint8_t                 physport;
1457         mptsas_phymask_t        *phymask;


1840         pMpi2ConfigReply_t      configreply;
1841         pMpi2SasIOUnitPage0_t   sasioupage0;
1842         pMpi2SasIOUnitPage1_t   sasioupage1;
1843         int                     recv_numbytes;
1844         caddr_t                 recv_memp, page_memp;
1845         int                     i, num_phys, start_phy = 0;
1846         int                     page0_size =
1847             sizeof (MPI2_CONFIG_PAGE_SASIOUNIT_0) +
1848             (sizeof (MPI2_SAS_IO_UNIT0_PHY_DATA) * (MPTSAS_MAX_PHYS - 1));
1849         int                     page1_size =
1850             sizeof (MPI2_CONFIG_PAGE_SASIOUNIT_1) +
1851             (sizeof (MPI2_SAS_IO_UNIT1_PHY_DATA) * (MPTSAS_MAX_PHYS - 1));
1852         uint32_t                flags_length;
1853         uint32_t                cpdi[MPTSAS_MAX_PHYS];
1854         uint32_t                readpage1 = 0, retrypage0 = 0;
1855         uint16_t                iocstatus;
1856         uint8_t                 port_flags, page_number, action;
1857         uint32_t                reply_size = 256; /* Big enough for any page */
1858         uint_t                  state;
1859         int                     rval = DDI_FAILURE;

1860 
1861         /*
1862          * Initialize our "state machine".  This is a bit convoluted,
1863          * but it keeps us from having to do the ddi allocations numerous
1864          * times.
1865          */
1866 
1867         NDBG20(("mptsas_get_sas_io_unit_page_hndshk enter"));
1868         ASSERT(mutex_owned(&mpt->m_mutex));
1869         state = IOUC_READ_PAGE0;
1870 
1871         /*
1872          * dynamically create a customized dma attribute structure
1873          * that describes mpt's config reply page request structure.
1874          */
1875         recv_dma_attrs = mpt->m_msg_dma_attr;
1876         recv_dma_attrs.dma_attr_sgllen = 1;
1877         recv_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_REPLY));
1878 
1879         if (mptsas_dma_addr_create(mpt, recv_dma_attrs,
1880             &recv_dma_handle, &recv_accessp, &recv_memp,
1881             (sizeof (MPI2_CONFIG_REPLY)), NULL) == FALSE) {
1882                 mptsas_log(mpt, CE_WARN,
1883                     "mptsas_get_sas_io_unit_page_hndshk: recv dma failed");
1884                 goto cleanup;
1885         }


1886 
1887         page_dma_attrs = mpt->m_msg_dma_attr;
1888         page_dma_attrs.dma_attr_sgllen = 1;
1889         page_dma_attrs.dma_attr_granular = reply_size;
1890 
1891         if (mptsas_dma_addr_create(mpt, page_dma_attrs,
1892             &page_dma_handle, &page_accessp, &page_memp,
1893             reply_size, &page_cookie) == FALSE) {
1894                 mptsas_log(mpt, CE_WARN,
1895                     "mptsas_get_sas_io_unit_page_hndshk: page dma failed");
1896                 goto cleanup;
1897         }


1898 
1899         /*
1900          * Now we cycle through the state machine.  Here's what happens:
1901          * 1. Read IO unit page 0 and set phy information
1902          * 2. See if Read IO unit page1 is needed because of port configuration
1903          * 3. Read IO unit page 1 and update phy information.
1904          */
1905 
1906         sasioupage0 = (pMpi2SasIOUnitPage0_t)page_memp;
1907         sasioupage1 = (pMpi2SasIOUnitPage1_t)page_memp;
1908 
1909         while (state != IOUC_DONE) {
1910                 switch (state) {
1911                 case IOUC_READ_PAGE0:
1912                         page_number = 0;
1913                         action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1914                         flags_length = (uint32_t)page0_size;
1915                         flags_length |= ((uint32_t)(
1916                             MPI2_SGE_FLAGS_LAST_ELEMENT |
1917                             MPI2_SGE_FLAGS_END_OF_BUFFER |
1918                             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1919                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
1920                             MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
1921                             MPI2_SGE_FLAGS_IOC_TO_HOST |
1922                             MPI2_SGE_FLAGS_END_OF_LIST) <<
1923                             MPI2_SGE_FLAGS_SHIFT);
1924 
1925                         break;
1926 
1927                 case IOUC_READ_PAGE1:
1928                         page_number = 1;
1929                         action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1930                         flags_length = (uint32_t)page1_size;
1931                         flags_length |= ((uint32_t)(
1932                             MPI2_SGE_FLAGS_LAST_ELEMENT |
1933                             MPI2_SGE_FLAGS_END_OF_BUFFER |
1934                             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1935                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
1936                             MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
1937                             MPI2_SGE_FLAGS_IOC_TO_HOST |
1938                             MPI2_SGE_FLAGS_END_OF_LIST) <<
1939                             MPI2_SGE_FLAGS_SHIFT);
1940 
1941                         break;
1942                 default:
1943                         break;
1944                 }
1945 
1946                 bzero(recv_memp, sizeof (MPI2_CONFIG_REPLY));
1947                 configreply = (pMpi2ConfigReply_t)recv_memp;
1948                 recv_numbytes = sizeof (MPI2_CONFIG_REPLY);
1949 
1950                 if (mptsas_send_extended_config_request_msg(mpt,
1951                     MPI2_CONFIG_ACTION_PAGE_HEADER,
1952                     MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
1953                     0, page_number, 0, 0, 0, 0)) {
1954                         goto cleanup;
1955                 }
1956 


1960                 }
1961 
1962                 iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus);
1963                 iocstatus = MPTSAS_IOCSTATUS(iocstatus);
1964 
1965                 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
1966                         mptsas_log(mpt, CE_WARN,
1967                             "mptsas_get_sas_io_unit_page_hndshk: read page "
1968                             "header iocstatus = 0x%x", iocstatus);
1969                         goto cleanup;
1970                 }
1971 
1972                 if (action != MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
1973                         bzero(page_memp, reply_size);
1974                 }
1975 
1976                 if (mptsas_send_extended_config_request_msg(mpt, action,
1977                     MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, page_number,
1978                     ddi_get8(recv_accessp, &configreply->Header.PageVersion),
1979                     ddi_get16(recv_accessp, &configreply->ExtPageLength),
1980                     flags_length, page_cookie.dmac_address)) {
1981                         goto cleanup;
1982                 }
1983 
1984                 if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
1985                     recv_accessp)) {
1986                         goto cleanup;
1987                 }
1988 
1989                 iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus);
1990                 iocstatus = MPTSAS_IOCSTATUS(iocstatus);
1991 
1992                 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
1993                         mptsas_log(mpt, CE_WARN,
1994                             "mptsas_get_sas_io_unit_page_hndshk: IO unit "
1995                             "config failed for action %d, iocstatus = 0x%x",
1996                             action, iocstatus);
1997                         goto cleanup;
1998                 }
1999 
2000                 switch (state) {


2113 
2114                         state = IOUC_DONE;
2115                         rval = DDI_SUCCESS;
2116                         break;
2117                 }
2118         }
2119         if ((mptsas_check_dma_handle(recv_dma_handle) != DDI_SUCCESS) ||
2120             (mptsas_check_dma_handle(page_dma_handle) != DDI_SUCCESS)) {
2121                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2122                 rval = DDI_FAILURE;
2123                 goto cleanup;
2124         }
2125         if ((mptsas_check_acc_handle(recv_accessp) != DDI_SUCCESS) ||
2126             (mptsas_check_acc_handle(page_accessp) != DDI_SUCCESS)) {
2127                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2128                 rval = DDI_FAILURE;
2129                 goto cleanup;
2130         }
2131 
2132 cleanup:

2133         mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);

2134         mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
2135         if (rval != DDI_SUCCESS) {
2136                 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
2137                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
2138         }
2139         return (rval);
2140 }
2141 
2142 /*
2143  * mptsas_get_manufacture_page5
2144  *
2145  * This function will retrieve the base WWID from the adapter.  Since this
2146  * function is only called during the initialization process, use handshaking.
2147  */
2148 int
2149 mptsas_get_manufacture_page5(mptsas_t *mpt)
2150 {
2151         ddi_dma_attr_t                  recv_dma_attrs, page_dma_attrs;
2152         ddi_dma_cookie_t                page_cookie;
2153         ddi_dma_handle_t                recv_dma_handle, page_dma_handle;
2154         ddi_acc_handle_t                recv_accessp, page_accessp;
2155         pMpi2ConfigReply_t              configreply;
2156         caddr_t                         recv_memp, page_memp;
2157         int                             recv_numbytes;
2158         pMpi2ManufacturingPage5_t       m5;
2159         uint32_t                        flagslength;
2160         int                             rval = DDI_SUCCESS;
2161         uint_t                          iocstatus;

2162 
2163         MPTSAS_DISABLE_INTR(mpt);
2164 
2165         if (mptsas_send_config_request_msg(mpt, MPI2_CONFIG_ACTION_PAGE_HEADER,
2166             MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 5, 0, 0, 0, 0)) {
2167                 rval = DDI_FAILURE;
2168                 goto done;
2169         }
2170 
2171         /*
2172          * dynamically create a customized dma attribute structure
2173          * that describes the MPT's config reply page request structure.
2174          */
2175         recv_dma_attrs = mpt->m_msg_dma_attr;
2176         recv_dma_attrs.dma_attr_sgllen = 1;
2177         recv_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_REPLY));
2178 
2179         if (mptsas_dma_addr_create(mpt, recv_dma_attrs,
2180             &recv_dma_handle, &recv_accessp, &recv_memp,
2181             (sizeof (MPI2_CONFIG_REPLY)), NULL) == FALSE) {

2182                 goto done;
2183         }


2184 
2185         bzero(recv_memp, sizeof (MPI2_CONFIG_REPLY));
2186         configreply = (pMpi2ConfigReply_t)recv_memp;
2187         recv_numbytes = sizeof (MPI2_CONFIG_REPLY);
2188 
2189         /*
2190          * get config reply message
2191          */
2192         if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2193             recv_accessp)) {
2194                 rval = DDI_FAILURE;
2195                 goto done;
2196         }
2197 
2198         if (iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus)) {
2199                 mptsas_log(mpt, CE_WARN, "mptsas_get_manufacture_page5 update: "
2200                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
2201                     ddi_get32(recv_accessp, &configreply->IOCLogInfo));
2202                 goto done;
2203         }
2204 
2205         /*
2206          * dynamically create a customized dma attribute structure
2207          * that describes the MPT's config page structure.
2208          */
2209         page_dma_attrs = mpt->m_msg_dma_attr;
2210         page_dma_attrs.dma_attr_sgllen = 1;
2211         page_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_PAGE_MAN_5));
2212 
2213         if (mptsas_dma_addr_create(mpt, page_dma_attrs, &page_dma_handle,
2214             &page_accessp, &page_memp, (sizeof (MPI2_CONFIG_PAGE_MAN_5)),
2215             &page_cookie) == FALSE) {

2216                 goto done;
2217         }



2218         bzero(page_memp, sizeof (MPI2_CONFIG_PAGE_MAN_5));
2219         m5 = (pMpi2ManufacturingPage5_t)page_memp;



2220 
2221         /*
2222          * Give reply address to IOC to store config page in and send
2223          * config request out.
2224          */
2225 
2226         flagslength = sizeof (MPI2_CONFIG_PAGE_MAN_5);
2227         flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
2228             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
2229             MPI2_SGE_FLAGS_SYSTEM_ADDRESS | MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
2230             MPI2_SGE_FLAGS_IOC_TO_HOST |
2231             MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
2232 
2233         if (mptsas_send_config_request_msg(mpt,
2234             MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
2235             MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 5,
2236             ddi_get8(recv_accessp, &configreply->Header.PageVersion),
2237             ddi_get8(recv_accessp, &configreply->Header.PageLength),
2238             flagslength, page_cookie.dmac_address)) {
2239                 rval = DDI_FAILURE;
2240                 goto done;
2241         }
2242 
2243         /*
2244          * get reply view handshake
2245          */
2246         if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2247             recv_accessp)) {
2248                 rval = DDI_FAILURE;
2249                 goto done;
2250         }
2251 
2252         if (iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus)) {
2253                 mptsas_log(mpt, CE_WARN, "mptsas_get_manufacture_page5 config: "
2254                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
2255                     ddi_get32(recv_accessp, &configreply->IOCLogInfo));
2256                 goto done;
2257         }
2258 


2286 
2287         mptsas_log(mpt, CE_NOTE, "!mpt%d: Initiator WWNs: 0x%016llx-0x%016llx",
2288             mpt->m_instance, (unsigned long long)mpt->un.m_base_wwid,
2289             (unsigned long long)mpt->un.m_base_wwid + mpt->m_num_phys - 1);
2290 
2291         if ((mptsas_check_dma_handle(recv_dma_handle) != DDI_SUCCESS) ||
2292             (mptsas_check_dma_handle(page_dma_handle) != DDI_SUCCESS)) {
2293                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2294                 rval = DDI_FAILURE;
2295                 goto done;
2296         }
2297         if ((mptsas_check_acc_handle(recv_accessp) != DDI_SUCCESS) ||
2298             (mptsas_check_acc_handle(page_accessp) != DDI_SUCCESS)) {
2299                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2300                 rval = DDI_FAILURE;
2301         }
2302 done:
2303         /*
2304          * free up memory
2305          */

2306         mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);

2307         mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
2308         MPTSAS_ENABLE_INTR(mpt);
2309 
2310         return (rval);
2311 }
2312 
2313 static int
2314 mptsas_sasphypage_0_cb(mptsas_t *mpt, caddr_t page_memp,
2315     ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
2316     va_list ap)
2317 {
2318 #ifndef __lock_lint
2319         _NOTE(ARGUNUSED(ap))
2320 #endif
2321         pMpi2SasPhyPage0_t      sasphypage;
2322         int                     rval = DDI_SUCCESS;
2323         uint16_t                *owner_devhdl, *attached_devhdl;
2324         uint8_t                 *attached_phy_identify;
2325         uint32_t                *attached_phy_info;
2326         uint8_t                 *programmed_link_rate;


2508  * This function will retrieve the base
2509  * Chip name, Board Name,Board Trace number from the adapter.
2510  * Since this function is only called during the
2511  * initialization process, use handshaking.
2512  */
2513 int
2514 mptsas_get_manufacture_page0(mptsas_t *mpt)
2515 {
2516         ddi_dma_attr_t                  recv_dma_attrs, page_dma_attrs;
2517         ddi_dma_cookie_t                page_cookie;
2518         ddi_dma_handle_t                recv_dma_handle, page_dma_handle;
2519         ddi_acc_handle_t                recv_accessp, page_accessp;
2520         pMpi2ConfigReply_t              configreply;
2521         caddr_t                         recv_memp, page_memp;
2522         int                             recv_numbytes;
2523         pMpi2ManufacturingPage0_t       m0;
2524         uint32_t                        flagslength;
2525         int                             rval = DDI_SUCCESS;
2526         uint_t                          iocstatus;
2527         uint8_t                         i = 0;

2528 
2529         MPTSAS_DISABLE_INTR(mpt);
2530 
2531         if (mptsas_send_config_request_msg(mpt, MPI2_CONFIG_ACTION_PAGE_HEADER,
2532             MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 0, 0, 0, 0, 0)) {
2533                 rval = DDI_FAILURE;
2534                 goto done;
2535         }
2536 
2537         /*
2538          * dynamically create a customized dma attribute structure
2539          * that describes the MPT's config reply page request structure.
2540          */
2541         recv_dma_attrs = mpt->m_msg_dma_attr;
2542         recv_dma_attrs.dma_attr_sgllen = 1;
2543         recv_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_REPLY));
2544 
2545         if (mptsas_dma_addr_create(mpt, recv_dma_attrs, &recv_dma_handle,
2546             &recv_accessp, &recv_memp, (sizeof (MPI2_CONFIG_REPLY)),
2547             NULL) == FALSE) {

2548                 goto done;
2549         }



2550         bzero(recv_memp, sizeof (MPI2_CONFIG_REPLY));
2551         configreply = (pMpi2ConfigReply_t)recv_memp;
2552         recv_numbytes = sizeof (MPI2_CONFIG_REPLY);
2553 
2554         /*
2555          * get config reply message
2556          */
2557         if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2558             recv_accessp)) {
2559                 rval = DDI_FAILURE;
2560                 goto done;
2561         }
2562 
2563         if (iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus)) {
2564                 mptsas_log(mpt, CE_WARN, "mptsas_get_manufacture_page5 update: "
2565                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
2566                     ddi_get32(recv_accessp, &configreply->IOCLogInfo));
2567                 goto done;
2568         }
2569 
2570         /*
2571          * dynamically create a customized dma attribute structure
2572          * that describes the MPT's config page structure.
2573          */
2574         page_dma_attrs = mpt->m_msg_dma_attr;
2575         page_dma_attrs.dma_attr_sgllen = 1;
2576         page_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_PAGE_MAN_0));
2577 
2578         if (mptsas_dma_addr_create(mpt, page_dma_attrs, &page_dma_handle,
2579             &page_accessp, &page_memp, (sizeof (MPI2_CONFIG_PAGE_MAN_0)),
2580             &page_cookie) == FALSE) {

2581                 goto done;
2582         }



2583         bzero(page_memp, sizeof (MPI2_CONFIG_PAGE_MAN_0));
2584         m0 = (pMpi2ManufacturingPage0_t)page_memp;
2585 
2586         /*
2587          * Give reply address to IOC to store config page in and send
2588          * config request out.
2589          */
2590 
2591         flagslength = sizeof (MPI2_CONFIG_PAGE_MAN_0);
2592         flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
2593             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
2594             MPI2_SGE_FLAGS_SYSTEM_ADDRESS | MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
2595             MPI2_SGE_FLAGS_IOC_TO_HOST |
2596             MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
2597 
2598         if (mptsas_send_config_request_msg(mpt,
2599             MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
2600             MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 0,
2601             ddi_get8(recv_accessp, &configreply->Header.PageVersion),
2602             ddi_get8(recv_accessp, &configreply->Header.PageLength),
2603             flagslength, page_cookie.dmac_address)) {
2604                 rval = DDI_FAILURE;
2605                 goto done;
2606         }
2607 
2608         /*
2609          * get reply view handshake
2610          */
2611         if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2612             recv_accessp)) {
2613                 rval = DDI_FAILURE;
2614                 goto done;
2615         }
2616 
2617         if (iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus)) {
2618                 mptsas_log(mpt, CE_WARN, "mptsas_get_manufacture_page0 config: "
2619                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
2620                     ddi_get32(recv_accessp, &configreply->IOCLogInfo));
2621                 goto done;
2622         }
2623 


2656                 mpt->m_MANU_page0.BoardTracerNumber[i] =
2657                     ddi_get8(page_accessp,
2658                     (uint8_t *)(void *)&m0->BoardTracerNumber[i]);
2659         }
2660 
2661         if ((mptsas_check_dma_handle(recv_dma_handle) != DDI_SUCCESS) ||
2662             (mptsas_check_dma_handle(page_dma_handle) != DDI_SUCCESS)) {
2663                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2664                 rval = DDI_FAILURE;
2665                 goto done;
2666         }
2667         if ((mptsas_check_acc_handle(recv_accessp) != DDI_SUCCESS) ||
2668             (mptsas_check_acc_handle(page_accessp) != DDI_SUCCESS)) {
2669                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2670                 rval = DDI_FAILURE;
2671         }
2672 done:
2673         /*
2674          * free up memory
2675          */

2676         mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);

2677         mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
2678         MPTSAS_ENABLE_INTR(mpt);
2679 
2680         return (rval);
2681 }


   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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
  26  * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
  27  */
  28 
  29 /*
  30  * Copyright (c) 2000 to 2010, LSI Corporation.
  31  * All rights reserved.
  32  *
  33  * Redistribution and use in source and binary forms of all code within
  34  * this file that is exclusively owned by LSI, with or without
  35  * modification, is permitted provided that, in addition to the CDDL 1.0
  36  * License requirements, the following conditions are met:
  37  *
  38  *    Neither the name of the author nor the names of its contributors may be
  39  *    used to endorse or promote products derived from this software without
  40  *    specific prior written permission.
  41  *
  42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  43  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  45  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  46  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,


  53  * DAMAGE.
  54  */
  55 
  56 /*
  57  * mptsas_impl - This file contains all the basic functions for communicating
  58  * to MPT based hardware.
  59  */
  60 
  61 #if defined(lint) || defined(DEBUG)
  62 #define MPTSAS_DEBUG
  63 #endif
  64 
  65 /*
  66  * standard header files
  67  */
  68 #include <sys/note.h>
  69 #include <sys/scsi/scsi.h>
  70 #include <sys/pci.h>
  71 
  72 #pragma pack(1)
  73 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_type.h>
  74 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2.h>
  75 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_cnfg.h>
  76 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_init.h>
  77 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_ioc.h>
  78 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_sas.h>
  79 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_tool.h>
  80 #pragma pack()
  81 
  82 /*
  83  * private header files.
  84  */
  85 #include <sys/scsi/adapters/mpt_sas3/mptsas3_var.h>
  86 #include <sys/scsi/adapters/mpt_sas3/mptsas3_smhba.h>
  87 
  88 /*
  89  * FMA header files.
  90  */
  91 #include <sys/fm/io/ddi.h>
  92 
  93 #if defined(MPTSAS_DEBUG)
  94 extern uint32_t mptsas_debug_flags;
  95 extern uint32_t mptsas_dbglog_imask;
  96 #endif
  97 
  98 /*
  99  *  prototypes
 100  */
 101 static void mptsas_ioc_event_cmdq_add(mptsas_t *mpt, m_event_struct_t *cmd);
 102 static void mptsas_ioc_event_cmdq_delete(mptsas_t *mpt, m_event_struct_t *cmd);
 103 static m_event_struct_t *mptsas_ioc_event_find_by_cmd(mptsas_t *mpt,
 104     struct mptsas_cmd *cmd);
 105 
 106 /*
 107  * add ioc evnet cmd into the queue
 108  */
 109 static void
 110 mptsas_ioc_event_cmdq_add(mptsas_t *mpt, m_event_struct_t *cmd)
 111 {
 112         if ((cmd->m_event_linkp = mpt->m_ioc_event_cmdq) == NULL) {
 113                 mpt->m_ioc_event_cmdtail = &cmd->m_event_linkp;
 114                 mpt->m_ioc_event_cmdq = cmd;
 115         } else {


 191                 } else {
 192                         /*
 193                          * it's not ack cmd, so continue to check next one
 194                          */
 195 
 196                         NDBG20(("destroy!! it's not Ack Flag, continue\n"));
 197                         ioc_cmd = ioc_cmd->m_event_linkp;
 198                 }
 199 
 200         }
 201 }
 202 
 203 void
 204 mptsas_start_config_page_access(mptsas_t *mpt, mptsas_cmd_t *cmd)
 205 {
 206         pMpi2ConfigRequest_t    request;
 207         pMpi2SGESimple64_t      sge;
 208         struct scsi_pkt         *pkt = cmd->cmd_pkt;
 209         mptsas_config_request_t *config = pkt->pkt_ha_private;
 210         uint8_t                 direction;
 211         uint32_t                length, flagslength;
 212         uint64_t                request_desc;
 213 
 214         ASSERT(mutex_owned(&mpt->m_mutex));
 215 
 216         /*
 217          * Point to the correct message and clear it as well as the global
 218          * config page memory.
 219          */
 220         request = (pMpi2ConfigRequest_t)(mpt->m_req_frame +
 221             (mpt->m_req_frame_size * cmd->cmd_slot));
 222         bzero(request, mpt->m_req_frame_size);
 223 
 224         /*
 225          * Form the request message.
 226          */
 227         ddi_put8(mpt->m_acc_req_frame_hdl, &request->Function,
 228             MPI2_FUNCTION_CONFIG);
 229         ddi_put8(mpt->m_acc_req_frame_hdl, &request->Action, config->action);
 230         direction = MPI2_SGE_FLAGS_IOC_TO_HOST;
 231         length = 0;
 232         sge = (pMpi2SGESimple64_t)&request->PageBufferSGE;


 246                     config->ext_page_type);
 247                 ddi_put16(mpt->m_acc_req_frame_hdl, &request->ExtPageLength,
 248                     config->ext_page_length);
 249                 ddi_put8(mpt->m_acc_req_frame_hdl, &request->Header.PageType,
 250                     config->page_type);
 251                 ddi_put8(mpt->m_acc_req_frame_hdl, &request->Header.PageLength,
 252                     config->page_length);
 253                 ddi_put8(mpt->m_acc_req_frame_hdl,
 254                     &request->Header.PageVersion, config->page_version);
 255                 if ((config->page_type & MPI2_CONFIG_PAGETYPE_MASK) ==
 256                     MPI2_CONFIG_PAGETYPE_EXTENDED) {
 257                         length = config->ext_page_length * 4;
 258                 } else {
 259                         length = config->page_length * 4;
 260                 }
 261 
 262                 if (config->action == MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
 263                         direction = MPI2_SGE_FLAGS_HOST_TO_IOC;
 264                 }
 265                 ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.Low,
 266                     (uint32_t)(cmd->cmd_dma_addr&0xfffffffful));
 267                 ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.High,
 268                     (uint32_t)(cmd->cmd_dma_addr >> 32));
 269         }
 270         ddi_put8(mpt->m_acc_req_frame_hdl, &request->Header.PageNumber,
 271             config->page_number);
 272         ddi_put32(mpt->m_acc_req_frame_hdl, &request->PageAddress,
 273             config->page_address);
 274         flagslength = ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
 275             MPI2_SGE_FLAGS_END_OF_BUFFER |
 276             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
 277             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
 278             MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
 279             direction |
 280             MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
 281         flagslength |= length;
 282         ddi_put32(mpt->m_acc_req_frame_hdl, &sge->FlagsLength, flagslength);
 283 
 284         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
 285             DDI_DMA_SYNC_FORDEV);
 286         request_desc = (cmd->cmd_slot << 16) +
 287             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 288         cmd->cmd_rfm = NULL;
 289         MPTSAS_START_CMD(mpt, request_desc);
 290         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
 291             DDI_SUCCESS) ||
 292             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
 293             DDI_SUCCESS)) {
 294                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
 295         }
 296 }
 297 
 298 int
 299 mptsas_access_config_page(mptsas_t *mpt, uint8_t action, uint8_t page_type,
 300     uint8_t page_number, uint32_t page_address, int (*callback) (mptsas_t *,
 301     caddr_t, ddi_acc_handle_t, uint16_t, uint32_t, va_list), ...)
 302 {
 303         va_list                 ap;
 304         ddi_dma_attr_t          attrs;
 305         ddi_dma_cookie_t        cookie;
 306         ddi_acc_handle_t        accessp;
 307         size_t                  len = 0;
 308         mptsas_config_request_t config;
 309         int                     rval = DDI_SUCCESS, config_flags = 0;
 310         mptsas_cmd_t            *cmd;
 311         struct scsi_pkt         *pkt;
 312         pMpi2ConfigReply_t      reply;
 313         uint16_t                iocstatus = 0;
 314         uint32_t                iocloginfo;
 315         caddr_t                 page_memp;
 316         boolean_t               free_dma = B_FALSE;
 317 
 318         va_start(ap, callback);
 319         ASSERT(mutex_owned(&mpt->m_mutex));
 320 
 321         /*
 322          * Get a command from the pool.
 323          */
 324         if ((rval = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
 325                 mptsas_log(mpt, CE_NOTE, "command pool is full for config "
 326                     "page request");
 327                 rval = DDI_FAILURE;
 328                 goto page_done;
 329         }
 330         config_flags |= MPTSAS_REQUEST_POOL_CMD;
 331 
 332         bzero((caddr_t)cmd, sizeof (*cmd));
 333         bzero((caddr_t)pkt, scsi_pkt_size());
 334         bzero((caddr_t)&config, sizeof (config));
 335 
 336         /*


 379         }
 380 
 381         /*
 382          * Check if the header request completed without timing out
 383          */
 384         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
 385                 mptsas_log(mpt, CE_WARN, "config header request timeout");
 386                 rval = DDI_FAILURE;
 387                 goto page_done;
 388         }
 389 
 390         /*
 391          * cmd_rfm points to the reply message if a reply was given.  Check the
 392          * IOCStatus to make sure everything went OK with the header request.
 393          */
 394         if (cmd->cmd_rfm) {
 395                 config_flags |= MPTSAS_ADDRESS_REPLY;
 396                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
 397                     DDI_DMA_SYNC_FORCPU);
 398                 reply = (pMpi2ConfigReply_t)(mpt->m_reply_frame + (cmd->cmd_rfm
 399                     - (mpt->m_reply_frame_dma_addr&0xfffffffful)));
 400                 config.page_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
 401                     &reply->Header.PageType);
 402                 config.page_number = ddi_get8(mpt->m_acc_reply_frame_hdl,
 403                     &reply->Header.PageNumber);
 404                 config.page_length = ddi_get8(mpt->m_acc_reply_frame_hdl,
 405                     &reply->Header.PageLength);
 406                 config.page_version = ddi_get8(mpt->m_acc_reply_frame_hdl,
 407                     &reply->Header.PageVersion);
 408                 config.ext_page_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
 409                     &reply->ExtPageType);
 410                 config.ext_page_length = ddi_get16(mpt->m_acc_reply_frame_hdl,
 411                     &reply->ExtPageLength);
 412 
 413                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
 414                     &reply->IOCStatus);
 415                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
 416                     &reply->IOCLogInfo);
 417 
 418                 if (iocstatus) {
 419                         NDBG13(("mptsas_access_config_page header: "


 453                         mpt->m_free_index = 0;
 454                 }
 455                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
 456                     mpt->m_free_index);
 457                 config_flags &= (~MPTSAS_ADDRESS_REPLY);
 458         }
 459 
 460         /*
 461          * Allocate DMA buffer here.  Store the info regarding this buffer in
 462          * the cmd struct so that it can be used for this specific command and
 463          * de-allocated after the command completes.  The size of the reply
 464          * will not be larger than the reply frame size.
 465          */
 466         attrs = mpt->m_msg_dma_attr;
 467         attrs.dma_attr_sgllen = 1;
 468         attrs.dma_attr_granular = (uint32_t)len;
 469 
 470         if (mptsas_dma_addr_create(mpt, attrs,
 471             &cmd->cmd_dmahandle, &accessp, &page_memp,
 472             len, &cookie) == FALSE) {
 473                 mptsas_log(mpt, CE_WARN,
 474                     "mptsas_dma_addr_create(len=0x%x) failed", (int)len);
 475                 rval = DDI_FAILURE;
 476                 goto page_done;
 477         }
 478         /* NOW we can safely call mptsas_dma_addr_destroy(). */
 479         free_dma = B_TRUE;
 480 
 481         cmd->cmd_dma_addr = cookie.dmac_laddress;
 482         bzero(page_memp, len);
 483 
 484         /*
 485          * Save the data for this request to be used in the call to start the
 486          * config page read
 487          */
 488         config.action = action;
 489         config.page_address = page_address;
 490 
 491         /*
 492          * Re-use the cmd that was used to get the header.  Reset some of the
 493          * values.
 494          */
 495         bzero((caddr_t)pkt, scsi_pkt_size());
 496         pkt->pkt_ha_private  = (opaque_t)&config;
 497         pkt->pkt_flags               = FLAG_HEAD;
 498         pkt->pkt_time                = 60;
 499         cmd->cmd_flags               = CFLAG_PREPARED | CFLAG_CMDIOC | CFLAG_CONFIG;
 500 


 524          * Check if the request completed without timing out
 525          */
 526         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
 527                 mptsas_log(mpt, CE_WARN, "config page request timeout");
 528                 rval = DDI_FAILURE;
 529                 goto page_done;
 530         }
 531 
 532         /*
 533          * cmd_rfm points to the reply message if a reply was given.  The reply
 534          * frame and the config page are returned from this function in the
 535          * param list.
 536          */
 537         if (cmd->cmd_rfm) {
 538                 config_flags |= MPTSAS_ADDRESS_REPLY;
 539                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
 540                     DDI_DMA_SYNC_FORCPU);
 541                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
 542                     DDI_DMA_SYNC_FORCPU);
 543                 reply = (pMpi2ConfigReply_t)(mpt->m_reply_frame + (cmd->cmd_rfm
 544                     - (mpt->m_reply_frame_dma_addr&0xfffffffful)));
 545                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
 546                     &reply->IOCStatus);
 547                 iocstatus = MPTSAS_IOCSTATUS(iocstatus);
 548                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
 549                     &reply->IOCLogInfo);
 550         }
 551 
 552         if (callback(mpt, page_memp, accessp, iocstatus, iocloginfo, ap)) {
 553                 rval = DDI_FAILURE;
 554                 goto page_done;
 555         }
 556 
 557         mptsas_fma_check(mpt, cmd);
 558         /*
 559          * Check the DMA/ACC handles and then free the DMA buffer.
 560          */
 561         if ((mptsas_check_dma_handle(cmd->cmd_dmahandle) != DDI_SUCCESS) ||
 562             (mptsas_check_acc_handle(accessp) != DDI_SUCCESS)) {
 563                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
 564                 rval = DDI_FAILURE;


 578 page_done:
 579         va_end(ap);
 580         /*
 581          * Put the reply frame back on the free queue, increment the free
 582          * index, and write the new index to the free index register.  But only
 583          * if this reply is an ADDRESS reply.
 584          */
 585         if (config_flags & MPTSAS_ADDRESS_REPLY) {
 586                 ddi_put32(mpt->m_acc_free_queue_hdl,
 587                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
 588                     cmd->cmd_rfm);
 589                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
 590                     DDI_DMA_SYNC_FORDEV);
 591                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
 592                         mpt->m_free_index = 0;
 593                 }
 594                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
 595                     mpt->m_free_index);
 596         }
 597 
 598         if (free_dma)
 599                 mptsas_dma_addr_destroy(&cmd->cmd_dmahandle, &accessp);
 600 
 601         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
 602                 mptsas_remove_cmd(mpt, cmd);
 603                 config_flags &= (~MPTSAS_REQUEST_POOL_CMD);
 604         }
 605         if (config_flags & MPTSAS_REQUEST_POOL_CMD)
 606                 mptsas_return_to_pool(mpt, cmd);
 607 
 608         if (config_flags & MPTSAS_CMD_TIMEOUT) {
 609                 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
 610                 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
 611                         mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
 612                 }
 613         }
 614 
 615         return (rval);
 616 }
 617 
 618 int
 619 mptsas_send_config_request_msg(mptsas_t *mpt, uint8_t action, uint8_t pagetype,
 620         uint32_t pageaddress, uint8_t pagenumber, uint8_t pageversion,
 621         uint8_t pagelength, uint32_t SGEflagslength, uint64_t SGEaddress)
 622 {
 623         pMpi2ConfigRequest_t    config;
 624         int                     send_numbytes;
 625 
 626         bzero(mpt->m_hshk_memp, sizeof (MPI2_CONFIG_REQUEST));
 627         config = (pMpi2ConfigRequest_t)mpt->m_hshk_memp;
 628         ddi_put8(mpt->m_hshk_acc_hdl, &config->Function, MPI2_FUNCTION_CONFIG);
 629         ddi_put8(mpt->m_hshk_acc_hdl, &config->Action, action);
 630         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageNumber, pagenumber);
 631         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageType, pagetype);
 632         ddi_put32(mpt->m_hshk_acc_hdl, &config->PageAddress, pageaddress);
 633         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageVersion, pageversion);
 634         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageLength, pagelength);
 635         ddi_put32(mpt->m_hshk_acc_hdl,
 636             &config->PageBufferSGE.MpiSimple.FlagsLength, SGEflagslength);
 637         ddi_put32(mpt->m_hshk_acc_hdl,
 638             &config->PageBufferSGE.MpiSimple.u.Address64.Low,
 639             SGEaddress&0xfffffffful);
 640         ddi_put32(mpt->m_hshk_acc_hdl,
 641             &config->PageBufferSGE.MpiSimple.u.Address64.High,
 642             SGEaddress >> 32);
 643         send_numbytes = sizeof (MPI2_CONFIG_REQUEST);
 644 
 645         /*
 646          * Post message via handshake
 647          */
 648         if (mptsas_send_handshake_msg(mpt, (caddr_t)config, send_numbytes,
 649             mpt->m_hshk_acc_hdl)) {
 650                 return (-1);
 651         }
 652         return (0);
 653 }
 654 
 655 int
 656 mptsas_send_extended_config_request_msg(mptsas_t *mpt, uint8_t action,
 657         uint8_t extpagetype, uint32_t pageaddress, uint8_t pagenumber,
 658         uint8_t pageversion, uint16_t extpagelength,
 659         uint32_t SGEflagslength, uint64_t SGEaddress)
 660 {
 661         pMpi2ConfigRequest_t    config;
 662         int                     send_numbytes;
 663 
 664         bzero(mpt->m_hshk_memp, sizeof (MPI2_CONFIG_REQUEST));
 665         config = (pMpi2ConfigRequest_t)mpt->m_hshk_memp;
 666         ddi_put8(mpt->m_hshk_acc_hdl, &config->Function, MPI2_FUNCTION_CONFIG);
 667         ddi_put8(mpt->m_hshk_acc_hdl, &config->Action, action);
 668         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageNumber, pagenumber);
 669         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageType,
 670             MPI2_CONFIG_PAGETYPE_EXTENDED);
 671         ddi_put8(mpt->m_hshk_acc_hdl, &config->ExtPageType, extpagetype);
 672         ddi_put32(mpt->m_hshk_acc_hdl, &config->PageAddress, pageaddress);
 673         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageVersion, pageversion);
 674         ddi_put16(mpt->m_hshk_acc_hdl, &config->ExtPageLength, extpagelength);
 675         ddi_put32(mpt->m_hshk_acc_hdl,
 676             &config->PageBufferSGE.MpiSimple.FlagsLength, SGEflagslength);
 677         ddi_put32(mpt->m_hshk_acc_hdl,
 678             &config->PageBufferSGE.MpiSimple.u.Address64.Low,
 679             SGEaddress&0xfffffffful);
 680         ddi_put32(mpt->m_hshk_acc_hdl,
 681             &config->PageBufferSGE.MpiSimple.u.Address64.High,
 682             SGEaddress >> 32);
 683         send_numbytes = sizeof (MPI2_CONFIG_REQUEST);
 684 
 685         /*
 686          * Post message via handshake
 687          */
 688         if (mptsas_send_handshake_msg(mpt, (caddr_t)config, send_numbytes,
 689             mpt->m_hshk_acc_hdl)) {
 690                 return (-1);
 691         }
 692         return (0);
 693 }
 694 
 695 int
 696 mptsas_ioc_wait_for_response(mptsas_t *mpt)
 697 {
 698         int     polls = 0;
 699 
 700         while ((ddi_get32(mpt->m_datap,
 701             &mpt->m_reg->HostInterruptStatus) & MPI2_HIS_IOP_DOORBELL_STATUS)) {
 702                 drv_usecwait(1000);


1090  * priority queue with its limit and the controller will reply as they are
1091  * completed.  This way, we don't have to poll for one reply at a time.
1092  * Think about enhancing this later.
1093  */
1094 int
1095 mptsas_ioc_task_management(mptsas_t *mpt, int task_type, uint16_t dev_handle,
1096         int lun, uint8_t *reply, uint32_t reply_size, int mode)
1097 {
1098         /*
1099          * In order to avoid allocating variables on the stack,
1100          * we make use of the pre-existing mptsas_cmd_t and
1101          * scsi_pkt which are included in the mptsas_t which
1102          * is passed to this routine.
1103          */
1104 
1105         pMpi2SCSITaskManagementRequest_t        task;
1106         int                                     rval = FALSE;
1107         mptsas_cmd_t                            *cmd;
1108         struct scsi_pkt                         *pkt;
1109         mptsas_slots_t                          *slots = mpt->m_active;
1110         uint32_t                                i;
1111         uint64_t                                request_desc;
1112         pMPI2DefaultReply_t                     reply_msg;
1113 
1114         /*
1115          * Can't start another task management routine.
1116          */
1117         if (slots->m_slot[MPTSAS_TM_SLOT(mpt)] != NULL) {
1118                 mptsas_log(mpt, CE_WARN, "Can only start 1 task management"
1119                     " command at a time\n");
1120                 return (FALSE);
1121         }
1122 
1123         cmd = &(mpt->m_event_task_mgmt.m_event_cmd);
1124         pkt = &(mpt->m_event_task_mgmt.m_event_pkt);
1125 
1126         bzero((caddr_t)cmd, sizeof (*cmd));
1127         bzero((caddr_t)pkt, scsi_pkt_size());
1128 
1129         pkt->pkt_cdbp                = (opaque_t)&cmd->cmd_cdb[0];
1130         pkt->pkt_scbp                = (opaque_t)&cmd->cmd_scb;
1131         pkt->pkt_ha_private  = (opaque_t)cmd;


1147         task = (pMpi2SCSITaskManagementRequest_t)(mpt->m_req_frame +
1148             (mpt->m_req_frame_size * cmd->cmd_slot));
1149         bzero(task, mpt->m_req_frame_size);
1150 
1151         /*
1152          * form message for requested task
1153          */
1154         mptsas_init_std_hdr(mpt->m_acc_req_frame_hdl, task, dev_handle, lun, 0,
1155             MPI2_FUNCTION_SCSI_TASK_MGMT);
1156 
1157         /*
1158          * Set the task type
1159          */
1160         ddi_put8(mpt->m_acc_req_frame_hdl, &task->TaskType, task_type);
1161 
1162         /*
1163          * Send TM request using High Priority Queue.
1164          */
1165         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
1166             DDI_DMA_SYNC_FORDEV);
1167         request_desc = (cmd->cmd_slot << 16) +
1168             MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
1169         MPTSAS_START_CMD(mpt, request_desc);
1170         rval = mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
1171 
1172         if (pkt->pkt_reason == CMD_INCOMPLETE)
1173                 rval = FALSE;
1174 
1175         /*
1176          * If a reply frame was used and there is a reply buffer to copy the
1177          * reply data into, copy it.  If this fails, log a message, but don't
1178          * fail the TM request.
1179          */
1180         if (cmd->cmd_rfm && reply) {
1181                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
1182                     DDI_DMA_SYNC_FORCPU);
1183                 reply_msg = (pMPI2DefaultReply_t)
1184                     (mpt->m_reply_frame + (cmd->cmd_rfm -
1185                     (mpt->m_reply_frame_dma_addr&0xfffffffful)));
1186                 if (reply_size > sizeof (MPI2_SCSI_TASK_MANAGE_REPLY)) {
1187                         reply_size = sizeof (MPI2_SCSI_TASK_MANAGE_REPLY);
1188                 }
1189                 mutex_exit(&mpt->m_mutex);
1190                 for (i = 0; i < reply_size; i++) {
1191                         if (ddi_copyout((uint8_t *)reply_msg + i, reply + i, 1,
1192                             mode)) {
1193                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
1194                                     "reply data for TM request");
1195                                 break;
1196                         }
1197                 }
1198                 mutex_enter(&mpt->m_mutex);
1199         }
1200 
1201         /*
1202          * clear the TM slot before returning
1203          */
1204         slots->m_slot[MPTSAS_TM_SLOT(mpt)] = NULL;
1205 
1206         /*
1207          * If we lost our task management command
1208          * we need to reset the ioc
1209          */
1210         if (rval == FALSE) {
1211                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_task_management failed "
1212                     "try to reset ioc to recovery!");
1213                 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
1214                 if (mptsas_restart_ioc(mpt)) {
1215                         mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
1216                         rval = FAILED;
1217                 }
1218         }
1219 
1220         return (rval);
1221 }
1222 
1223 /*
1224  * Complete firmware download frame for v2.0 cards.
1225  */
1226 static void
1227 mptsas_uflash2(pMpi2FWDownloadRequest fwdownload,
1228     ddi_acc_handle_t acc_hdl, uint32_t size, uint8_t type,
1229     ddi_dma_cookie_t flsh_cookie)
1230 {
1231         pMpi2FWDownloadTCSGE_t  tcsge;
1232         pMpi2SGESimple64_t      sge;
1233         uint32_t                flagslength;
1234 
1235         ddi_put8(acc_hdl, &fwdownload->Function,
1236             MPI2_FUNCTION_FW_DOWNLOAD);
1237         ddi_put8(acc_hdl, &fwdownload->ImageType, type);
1238         ddi_put8(acc_hdl, &fwdownload->MsgFlags,
1239             MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT);
1240         ddi_put32(acc_hdl, &fwdownload->TotalImageSize, size);
1241 
1242         tcsge = (pMpi2FWDownloadTCSGE_t)&fwdownload->SGL;
1243         ddi_put8(acc_hdl, &tcsge->ContextSize, 0);
1244         ddi_put8(acc_hdl, &tcsge->DetailsLength, 12);
1245         ddi_put8(acc_hdl, &tcsge->Flags, 0);
1246         ddi_put32(acc_hdl, &tcsge->ImageOffset, 0);
1247         ddi_put32(acc_hdl, &tcsge->ImageSize, size);
1248 
1249         sge = (pMpi2SGESimple64_t)(tcsge + 1);
1250         flagslength = size;
1251         flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
1252             MPI2_SGE_FLAGS_END_OF_BUFFER |
1253             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1254             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
1255             MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
1256             MPI2_SGE_FLAGS_HOST_TO_IOC |
1257             MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
1258         ddi_put32(acc_hdl, &sge->FlagsLength, flagslength);
1259         ddi_put32(acc_hdl, &sge->Address.Low,
1260             flsh_cookie.dmac_address);
1261         ddi_put32(acc_hdl, &sge->Address.High,
1262             (uint32_t)(flsh_cookie.dmac_laddress >> 32));
1263 }
1264 
1265 /*
1266  * Complete firmware download frame for v2.5 cards.
1267  */
1268 static void
1269 mptsas_uflash25(pMpi25FWDownloadRequest fwdownload,
1270     ddi_acc_handle_t acc_hdl, uint32_t size, uint8_t type,
1271     ddi_dma_cookie_t flsh_cookie)
1272 {
1273         pMpi2IeeeSgeSimple64_t  sge;
1274         uint8_t                 flags;
1275 
1276         ddi_put8(acc_hdl, &fwdownload->Function,
1277             MPI2_FUNCTION_FW_DOWNLOAD);
1278         ddi_put8(acc_hdl, &fwdownload->ImageType, type);
1279         ddi_put8(acc_hdl, &fwdownload->MsgFlags,
1280             MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT);
1281         ddi_put32(acc_hdl, &fwdownload->TotalImageSize, size);
1282 
1283         ddi_put32(acc_hdl, &fwdownload->ImageOffset, 0);
1284         ddi_put32(acc_hdl, &fwdownload->ImageSize, size);
1285 
1286         sge = (pMpi2IeeeSgeSimple64_t)&fwdownload->SGL;
1287         flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
1288             MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR |
1289             MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
1290         ddi_put8(acc_hdl, &sge->Flags, flags);
1291         ddi_put32(acc_hdl, &sge->Length, size);
1292         ddi_put32(acc_hdl, &sge->Address.Low,
1293             flsh_cookie.dmac_address);
1294         ddi_put32(acc_hdl, &sge->Address.High,
1295             (uint32_t)(flsh_cookie.dmac_laddress >> 32));
1296 }
1297 
1298 static int mptsas_enable_mpi25_flashupdate = 0;
1299 
1300 int
1301 mptsas_update_flash(mptsas_t *mpt, caddr_t ptrbuffer, uint32_t size,
1302     uint8_t type, int mode)
1303 {
1304 
1305         /*
1306          * In order to avoid allocating variables on the stack,
1307          * we make use of the pre-existing mptsas_cmd_t and
1308          * scsi_pkt which are included in the mptsas_t which
1309          * is passed to this routine.
1310          */
1311 
1312         ddi_dma_attr_t          flsh_dma_attrs;
1313         ddi_dma_cookie_t        flsh_cookie;
1314         ddi_dma_handle_t        flsh_dma_handle;
1315         ddi_acc_handle_t        flsh_accessp;
1316         caddr_t                 memp, flsh_memp;




1317         mptsas_cmd_t            *cmd;
1318         struct scsi_pkt         *pkt;
1319         int                     i;
1320         int                     rvalue = 0;
1321         uint64_t                request_desc;
1322 
1323         if (mpt->m_MPI25) {
1324                 /*
1325                  * The code is there but not tested yet.
1326                  * User has to know there are risks here.
1327                  */
1328                 mptsas_log(mpt, CE_WARN, "mptsas_update_flash(): "
1329                     "Updating firmware through MPI 2.5 has not been "
1330                     "tested yet!\n"
1331                     "To enable set mptsas_enable_mpi25_flashupdate to 1\n");
1332                 if (!mptsas_enable_mpi25_flashupdate)
1333                         return (-1);
1334         }
1335 
1336         if ((rvalue = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
1337                 mptsas_log(mpt, CE_WARN, "mptsas_update_flash(): allocation "
1338                     "failed. event ack command pool is full\n");
1339                 return (rvalue);
1340         }
1341 
1342         bzero((caddr_t)cmd, sizeof (*cmd));
1343         bzero((caddr_t)pkt, scsi_pkt_size());
1344         cmd->ioc_cmd_slot = (uint32_t)rvalue;
1345 
1346         /*
1347          * dynamically create a customized dma attribute structure
1348          * that describes the flash file.
1349          */
1350         flsh_dma_attrs = mpt->m_msg_dma_attr;
1351         flsh_dma_attrs.dma_attr_sgllen = 1;
1352 
1353         if (mptsas_dma_addr_create(mpt, flsh_dma_attrs, &flsh_dma_handle,
1354             &flsh_accessp, &flsh_memp, size, &flsh_cookie) == FALSE) {


1375         pkt->pkt_time                = 60;
1376         cmd->cmd_pkt         = pkt;
1377         cmd->cmd_scblen              = 1;
1378         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_CMD;
1379 
1380         /*
1381          * Save the command in a slot
1382          */
1383         if (mptsas_save_cmd(mpt, cmd) == FALSE) {
1384                 mptsas_dma_addr_destroy(&flsh_dma_handle, &flsh_accessp);
1385                 mptsas_return_to_pool(mpt, cmd);
1386                 return (-1);
1387         }
1388 
1389         /*
1390          * Fill in fw download message
1391          */
1392         ASSERT(cmd->cmd_slot != 0);
1393         memp = mpt->m_req_frame + (mpt->m_req_frame_size * cmd->cmd_slot);
1394         bzero(memp, mpt->m_req_frame_size);







1395 
1396         if (mpt->m_MPI25)
1397                 mptsas_uflash25((pMpi25FWDownloadRequest)memp,
1398                     mpt->m_acc_req_frame_hdl, size, type, flsh_cookie);
1399         else
1400                 mptsas_uflash2((pMpi2FWDownloadRequest)memp,
1401                     mpt->m_acc_req_frame_hdl, size, type, flsh_cookie);















1402 
1403         /*
1404          * Start command
1405          */
1406         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
1407             DDI_DMA_SYNC_FORDEV);
1408         request_desc = (cmd->cmd_slot << 16) +
1409             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1410         cmd->cmd_rfm = NULL;
1411         MPTSAS_START_CMD(mpt, request_desc);
1412 
1413         rvalue = 0;
1414         (void) cv_reltimedwait(&mpt->m_fw_cv, &mpt->m_mutex,
1415             drv_usectohz(60 * MICROSEC), TR_CLOCK_TICK);
1416         if (!(cmd->cmd_flags & CFLAG_FINISHED)) {
1417                 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
1418                 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
1419                         mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
1420                 }
1421                 rvalue = -1;
1422         }
1423         mptsas_remove_cmd(mpt, cmd);
1424         mptsas_dma_addr_destroy(&flsh_dma_handle, &flsh_accessp);
1425 
1426         return (rvalue);
1427 }
1428 
1429 static int
1430 mptsas_sasdevpage_0_cb(mptsas_t *mpt, caddr_t page_memp,
1431     ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
1432     va_list ap)
1433 {
1434 #ifndef __lock_lint
1435         _NOTE(ARGUNUSED(ap))
1436 #endif
1437         pMpi2SasDevicePage0_t   sasdevpage;
1438         int                     rval = DDI_SUCCESS, i;
1439         uint8_t                 *sas_addr = NULL;
1440         uint8_t                 tmp_sas_wwn[SAS_WWN_BYTE_SIZE];
1441         uint16_t                *devhdl, *bay_num, *enclosure;
1442         uint64_t                *sas_wwn;
1443         uint32_t                *dev_info;
1444         uint8_t                 *physport, *phynum;
1445         uint16_t                *pdevhdl, *io_flags;
1446         uint32_t                page_address;
1447 
1448         if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) &&
1449             (iocstatus != MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)) {
1450                 mptsas_log(mpt, CE_WARN, "mptsas_get_sas_device_page0 "
1451                     "header: IOCStatus=0x%x, IOCLogInfo=0x%x",
1452                     iocstatus, iocloginfo);
1453                 rval = DDI_FAILURE;
1454                 return (rval);
1455         }
1456         page_address = va_arg(ap, uint32_t);
1457         /*
1458          * The INVALID_PAGE status is normal if using GET_NEXT_HANDLE and there
1459          * are no more pages.  If everything is OK up to this point but the
1460          * status is INVALID_PAGE, change rval to FAILURE and quit.  Also,
1461          * signal that device traversal is complete.
1462          */
1463         if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
1464                 if ((page_address & MPI2_SAS_DEVICE_PGAD_FORM_MASK) ==
1465                     MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE) {
1466                         mpt->m_done_traverse_dev = 1;
1467                 }
1468                 rval = DDI_FAILURE;
1469                 return (rval);
1470         }
1471         devhdl = va_arg(ap, uint16_t *);
1472         sas_wwn = va_arg(ap, uint64_t *);
1473         dev_info = va_arg(ap, uint32_t *);
1474         physport = va_arg(ap, uint8_t *);
1475         phynum = va_arg(ap, uint8_t *);
1476         pdevhdl = va_arg(ap, uint16_t *);
1477         bay_num = va_arg(ap, uint16_t *);
1478         enclosure = va_arg(ap, uint16_t *);
1479         io_flags = va_arg(ap, uint16_t *);
1480 
1481         sasdevpage = (pMpi2SasDevicePage0_t)page_memp;
1482 
1483         *dev_info = ddi_get32(accessp, &sasdevpage->DeviceInfo);
1484         *devhdl = ddi_get16(accessp, &sasdevpage->DevHandle);
1485         sas_addr = (uint8_t *)(&sasdevpage->SASAddress);
1486         for (i = 0; i < SAS_WWN_BYTE_SIZE; i++) {
1487                 tmp_sas_wwn[i] = ddi_get8(accessp, sas_addr + i);
1488         }
1489         bcopy(tmp_sas_wwn, sas_wwn, SAS_WWN_BYTE_SIZE);
1490         *sas_wwn = LE_64(*sas_wwn);
1491         *physport = ddi_get8(accessp, &sasdevpage->PhysicalPort);
1492         *phynum = ddi_get8(accessp, &sasdevpage->PhyNum);
1493         *pdevhdl = ddi_get16(accessp, &sasdevpage->ParentDevHandle);
1494         *bay_num = ddi_get16(accessp, &sasdevpage->Slot);
1495         *enclosure = ddi_get16(accessp, &sasdevpage->EnclosureHandle);
1496         *io_flags = ddi_get16(accessp, &sasdevpage->Flags);
1497 
1498         if (*io_flags & MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) {
1499                 /*
1500                  * Leave a messages about FP cabability in the log.
1501                  */
1502                 mptsas_log(mpt, CE_CONT,
1503                     "!w%016"PRIx64" FastPath Capable%s", *sas_wwn,
1504                     (*io_flags &
1505                     MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)?
1506                     " and Enabled":" but Disabled");
1507         }
1508 
1509         return (rval);
1510 }
1511 
1512 /*
1513  * Request MPI configuration page SAS device page 0 to get DevHandle, device
1514  * info and SAS address.
1515  */
1516 int
1517 mptsas_get_sas_device_page0(mptsas_t *mpt, uint32_t page_address,
1518     uint16_t *dev_handle, uint64_t *sas_wwn, uint32_t *dev_info,
1519     uint8_t *physport, uint8_t *phynum, uint16_t *pdev_handle,
1520     uint16_t *bay_num, uint16_t *enclosure, uint16_t *io_flags)
1521 {
1522         int rval = DDI_SUCCESS;
1523 
1524         ASSERT(mutex_owned(&mpt->m_mutex));
1525 
1526         /*
1527          * Get the header and config page.  reply contains the reply frame,
1528          * which holds status info for the request.
1529          */
1530         rval = mptsas_access_config_page(mpt,
1531             MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
1532             MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0, page_address,
1533             mptsas_sasdevpage_0_cb, page_address, dev_handle, sas_wwn,
1534             dev_info, physport, phynum, pdev_handle,
1535             bay_num, enclosure, io_flags);
1536 
1537         return (rval);
1538 }
1539 
1540 static int
1541 mptsas_sasexpdpage_0_cb(mptsas_t *mpt, caddr_t page_memp,
1542     ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
1543     va_list ap)
1544 {
1545 #ifndef __lock_lint
1546         _NOTE(ARGUNUSED(ap))
1547 #endif
1548         pMpi2ExpanderPage0_t    expddevpage;
1549         int                     rval = DDI_SUCCESS, i;
1550         uint8_t                 *sas_addr = NULL;
1551         uint8_t                 tmp_sas_wwn[SAS_WWN_BYTE_SIZE];
1552         uint16_t                *devhdl;
1553         uint64_t                *sas_wwn;
1554         uint8_t                 physport;
1555         mptsas_phymask_t        *phymask;


1938         pMpi2ConfigReply_t      configreply;
1939         pMpi2SasIOUnitPage0_t   sasioupage0;
1940         pMpi2SasIOUnitPage1_t   sasioupage1;
1941         int                     recv_numbytes;
1942         caddr_t                 recv_memp, page_memp;
1943         int                     i, num_phys, start_phy = 0;
1944         int                     page0_size =
1945             sizeof (MPI2_CONFIG_PAGE_SASIOUNIT_0) +
1946             (sizeof (MPI2_SAS_IO_UNIT0_PHY_DATA) * (MPTSAS_MAX_PHYS - 1));
1947         int                     page1_size =
1948             sizeof (MPI2_CONFIG_PAGE_SASIOUNIT_1) +
1949             (sizeof (MPI2_SAS_IO_UNIT1_PHY_DATA) * (MPTSAS_MAX_PHYS - 1));
1950         uint32_t                flags_length;
1951         uint32_t                cpdi[MPTSAS_MAX_PHYS];
1952         uint32_t                readpage1 = 0, retrypage0 = 0;
1953         uint16_t                iocstatus;
1954         uint8_t                 port_flags, page_number, action;
1955         uint32_t                reply_size = 256; /* Big enough for any page */
1956         uint_t                  state;
1957         int                     rval = DDI_FAILURE;
1958         boolean_t               free_recv = B_FALSE, free_page = B_FALSE;
1959 
1960         /*
1961          * Initialize our "state machine".  This is a bit convoluted,
1962          * but it keeps us from having to do the ddi allocations numerous
1963          * times.
1964          */
1965 
1966         NDBG20(("mptsas_get_sas_io_unit_page_hndshk enter"));
1967         ASSERT(mutex_owned(&mpt->m_mutex));
1968         state = IOUC_READ_PAGE0;
1969 
1970         /*
1971          * dynamically create a customized dma attribute structure
1972          * that describes mpt's config reply page request structure.
1973          */
1974         recv_dma_attrs = mpt->m_msg_dma_attr;
1975         recv_dma_attrs.dma_attr_sgllen = 1;
1976         recv_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_REPLY));
1977 
1978         if (mptsas_dma_addr_create(mpt, recv_dma_attrs,
1979             &recv_dma_handle, &recv_accessp, &recv_memp,
1980             (sizeof (MPI2_CONFIG_REPLY)), NULL) == FALSE) {
1981                 mptsas_log(mpt, CE_WARN,
1982                     "mptsas_get_sas_io_unit_page_hndshk: recv dma failed");
1983                 goto cleanup;
1984         }
1985         /* Now safe to call mptsas_dma_addr_destroy(recv_dma_handle). */
1986         free_recv = B_TRUE;
1987 
1988         page_dma_attrs = mpt->m_msg_dma_attr;
1989         page_dma_attrs.dma_attr_sgllen = 1;
1990         page_dma_attrs.dma_attr_granular = reply_size;
1991 
1992         if (mptsas_dma_addr_create(mpt, page_dma_attrs,
1993             &page_dma_handle, &page_accessp, &page_memp,
1994             reply_size, &page_cookie) == FALSE) {
1995                 mptsas_log(mpt, CE_WARN,
1996                     "mptsas_get_sas_io_unit_page_hndshk: page dma failed");
1997                 goto cleanup;
1998         }
1999         /* Now safe to call mptsas_dma_addr_destroy(page_dma_handle). */
2000         free_page = B_TRUE;
2001 
2002         /*
2003          * Now we cycle through the state machine.  Here's what happens:
2004          * 1. Read IO unit page 0 and set phy information
2005          * 2. See if Read IO unit page1 is needed because of port configuration
2006          * 3. Read IO unit page 1 and update phy information.
2007          */
2008 
2009         sasioupage0 = (pMpi2SasIOUnitPage0_t)page_memp;
2010         sasioupage1 = (pMpi2SasIOUnitPage1_t)page_memp;
2011 
2012         while (state != IOUC_DONE) {
2013                 switch (state) {
2014                 case IOUC_READ_PAGE0:
2015                         page_number = 0;
2016                         action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2017                         flags_length = (uint32_t)page0_size;
2018                         flags_length |= ((uint32_t)(
2019                             MPI2_SGE_FLAGS_LAST_ELEMENT |
2020                             MPI2_SGE_FLAGS_END_OF_BUFFER |
2021                             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
2022                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
2023                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
2024                             MPI2_SGE_FLAGS_IOC_TO_HOST |
2025                             MPI2_SGE_FLAGS_END_OF_LIST) <<
2026                             MPI2_SGE_FLAGS_SHIFT);
2027 
2028                         break;
2029 
2030                 case IOUC_READ_PAGE1:
2031                         page_number = 1;
2032                         action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2033                         flags_length = (uint32_t)page1_size;
2034                         flags_length |= ((uint32_t)(
2035                             MPI2_SGE_FLAGS_LAST_ELEMENT |
2036                             MPI2_SGE_FLAGS_END_OF_BUFFER |
2037                             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
2038                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
2039                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
2040                             MPI2_SGE_FLAGS_IOC_TO_HOST |
2041                             MPI2_SGE_FLAGS_END_OF_LIST) <<
2042                             MPI2_SGE_FLAGS_SHIFT);
2043 
2044                         break;
2045                 default:
2046                         break;
2047                 }
2048 
2049                 bzero(recv_memp, sizeof (MPI2_CONFIG_REPLY));
2050                 configreply = (pMpi2ConfigReply_t)recv_memp;
2051                 recv_numbytes = sizeof (MPI2_CONFIG_REPLY);
2052 
2053                 if (mptsas_send_extended_config_request_msg(mpt,
2054                     MPI2_CONFIG_ACTION_PAGE_HEADER,
2055                     MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
2056                     0, page_number, 0, 0, 0, 0)) {
2057                         goto cleanup;
2058                 }
2059 


2063                 }
2064 
2065                 iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus);
2066                 iocstatus = MPTSAS_IOCSTATUS(iocstatus);
2067 
2068                 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
2069                         mptsas_log(mpt, CE_WARN,
2070                             "mptsas_get_sas_io_unit_page_hndshk: read page "
2071                             "header iocstatus = 0x%x", iocstatus);
2072                         goto cleanup;
2073                 }
2074 
2075                 if (action != MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
2076                         bzero(page_memp, reply_size);
2077                 }
2078 
2079                 if (mptsas_send_extended_config_request_msg(mpt, action,
2080                     MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, page_number,
2081                     ddi_get8(recv_accessp, &configreply->Header.PageVersion),
2082                     ddi_get16(recv_accessp, &configreply->ExtPageLength),
2083                     flags_length, page_cookie.dmac_laddress)) {
2084                         goto cleanup;
2085                 }
2086 
2087                 if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2088                     recv_accessp)) {
2089                         goto cleanup;
2090                 }
2091 
2092                 iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus);
2093                 iocstatus = MPTSAS_IOCSTATUS(iocstatus);
2094 
2095                 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
2096                         mptsas_log(mpt, CE_WARN,
2097                             "mptsas_get_sas_io_unit_page_hndshk: IO unit "
2098                             "config failed for action %d, iocstatus = 0x%x",
2099                             action, iocstatus);
2100                         goto cleanup;
2101                 }
2102 
2103                 switch (state) {


2216 
2217                         state = IOUC_DONE;
2218                         rval = DDI_SUCCESS;
2219                         break;
2220                 }
2221         }
2222         if ((mptsas_check_dma_handle(recv_dma_handle) != DDI_SUCCESS) ||
2223             (mptsas_check_dma_handle(page_dma_handle) != DDI_SUCCESS)) {
2224                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2225                 rval = DDI_FAILURE;
2226                 goto cleanup;
2227         }
2228         if ((mptsas_check_acc_handle(recv_accessp) != DDI_SUCCESS) ||
2229             (mptsas_check_acc_handle(page_accessp) != DDI_SUCCESS)) {
2230                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2231                 rval = DDI_FAILURE;
2232                 goto cleanup;
2233         }
2234 
2235 cleanup:
2236         if (free_recv)
2237                 mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);
2238         if (free_page)
2239                 mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
2240         if (rval != DDI_SUCCESS) {
2241                 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
2242                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
2243         }
2244         return (rval);
2245 }
2246 
2247 /*
2248  * mptsas_get_manufacture_page5
2249  *
2250  * This function will retrieve the base WWID from the adapter.  Since this
2251  * function is only called during the initialization process, use handshaking.
2252  */
2253 int
2254 mptsas_get_manufacture_page5(mptsas_t *mpt)
2255 {
2256         ddi_dma_attr_t                  recv_dma_attrs, page_dma_attrs;
2257         ddi_dma_cookie_t                page_cookie;
2258         ddi_dma_handle_t                recv_dma_handle, page_dma_handle;
2259         ddi_acc_handle_t                recv_accessp, page_accessp;
2260         pMpi2ConfigReply_t              configreply;
2261         caddr_t                         recv_memp, page_memp;
2262         int                             recv_numbytes;
2263         pMpi2ManufacturingPage5_t       m5;
2264         uint32_t                        flagslength;
2265         int                             rval = DDI_SUCCESS;
2266         uint_t                          iocstatus;
2267         boolean_t               free_recv = B_FALSE, free_page = B_FALSE;
2268 
2269         MPTSAS_DISABLE_INTR(mpt);
2270 
2271         if (mptsas_send_config_request_msg(mpt, MPI2_CONFIG_ACTION_PAGE_HEADER,
2272             MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 5, 0, 0, 0, 0)) {
2273                 rval = DDI_FAILURE;
2274                 goto done;
2275         }
2276 
2277         /*
2278          * dynamically create a customized dma attribute structure
2279          * that describes the MPT's config reply page request structure.
2280          */
2281         recv_dma_attrs = mpt->m_msg_dma_attr;
2282         recv_dma_attrs.dma_attr_sgllen = 1;
2283         recv_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_REPLY));
2284 
2285         if (mptsas_dma_addr_create(mpt, recv_dma_attrs,
2286             &recv_dma_handle, &recv_accessp, &recv_memp,
2287             (sizeof (MPI2_CONFIG_REPLY)), NULL) == FALSE) {
2288                 rval = DDI_FAILURE;
2289                 goto done;
2290         }
2291         /* Now safe to call mptsas_dma_addr_destroy(recv_dma_handle). */
2292         free_recv = B_TRUE;
2293 
2294         bzero(recv_memp, sizeof (MPI2_CONFIG_REPLY));
2295         configreply = (pMpi2ConfigReply_t)recv_memp;
2296         recv_numbytes = sizeof (MPI2_CONFIG_REPLY);
2297 
2298         /*
2299          * get config reply message
2300          */
2301         if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2302             recv_accessp)) {
2303                 rval = DDI_FAILURE;
2304                 goto done;
2305         }
2306 
2307         if (iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus)) {
2308                 mptsas_log(mpt, CE_WARN, "mptsas_get_manufacture_page5 update: "
2309                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
2310                     ddi_get32(recv_accessp, &configreply->IOCLogInfo));
2311                 goto done;
2312         }
2313 
2314         /*
2315          * dynamically create a customized dma attribute structure
2316          * that describes the MPT's config page structure.
2317          */
2318         page_dma_attrs = mpt->m_msg_dma_attr;
2319         page_dma_attrs.dma_attr_sgllen = 1;
2320         page_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_PAGE_MAN_5));
2321 
2322         if (mptsas_dma_addr_create(mpt, page_dma_attrs, &page_dma_handle,
2323             &page_accessp, &page_memp, (sizeof (MPI2_CONFIG_PAGE_MAN_5)),
2324             &page_cookie) == FALSE) {
2325                 rval = DDI_FAILURE;
2326                 goto done;
2327         }
2328         /* Now safe to call mptsas_dma_addr_destroy(page_dma_handle). */
2329         free_page = B_TRUE;
2330 
2331         bzero(page_memp, sizeof (MPI2_CONFIG_PAGE_MAN_5));
2332         m5 = (pMpi2ManufacturingPage5_t)page_memp;
2333         NDBG20(("mptsas_get_manufacture_page5: paddr 0x%x%08x",
2334             (uint32_t)(page_cookie.dmac_laddress>>32),
2335             (uint32_t)(page_cookie.dmac_laddress&0xfffffffful)));
2336 
2337         /*
2338          * Give reply address to IOC to store config page in and send
2339          * config request out.
2340          */
2341 
2342         flagslength = sizeof (MPI2_CONFIG_PAGE_MAN_5);
2343         flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
2344             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
2345             MPI2_SGE_FLAGS_SYSTEM_ADDRESS | MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
2346             MPI2_SGE_FLAGS_IOC_TO_HOST |
2347             MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
2348 
2349         if (mptsas_send_config_request_msg(mpt,
2350             MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
2351             MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 5,
2352             ddi_get8(recv_accessp, &configreply->Header.PageVersion),
2353             ddi_get8(recv_accessp, &configreply->Header.PageLength),
2354             flagslength, page_cookie.dmac_laddress)) {
2355                 rval = DDI_FAILURE;
2356                 goto done;
2357         }
2358 
2359         /*
2360          * get reply view handshake
2361          */
2362         if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2363             recv_accessp)) {
2364                 rval = DDI_FAILURE;
2365                 goto done;
2366         }
2367 
2368         if (iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus)) {
2369                 mptsas_log(mpt, CE_WARN, "mptsas_get_manufacture_page5 config: "
2370                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
2371                     ddi_get32(recv_accessp, &configreply->IOCLogInfo));
2372                 goto done;
2373         }
2374 


2402 
2403         mptsas_log(mpt, CE_NOTE, "!mpt%d: Initiator WWNs: 0x%016llx-0x%016llx",
2404             mpt->m_instance, (unsigned long long)mpt->un.m_base_wwid,
2405             (unsigned long long)mpt->un.m_base_wwid + mpt->m_num_phys - 1);
2406 
2407         if ((mptsas_check_dma_handle(recv_dma_handle) != DDI_SUCCESS) ||
2408             (mptsas_check_dma_handle(page_dma_handle) != DDI_SUCCESS)) {
2409                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2410                 rval = DDI_FAILURE;
2411                 goto done;
2412         }
2413         if ((mptsas_check_acc_handle(recv_accessp) != DDI_SUCCESS) ||
2414             (mptsas_check_acc_handle(page_accessp) != DDI_SUCCESS)) {
2415                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2416                 rval = DDI_FAILURE;
2417         }
2418 done:
2419         /*
2420          * free up memory
2421          */
2422         if (free_recv)
2423                 mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);
2424         if (free_page)
2425                 mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
2426         MPTSAS_ENABLE_INTR(mpt);
2427 
2428         return (rval);
2429 }
2430 
2431 static int
2432 mptsas_sasphypage_0_cb(mptsas_t *mpt, caddr_t page_memp,
2433     ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
2434     va_list ap)
2435 {
2436 #ifndef __lock_lint
2437         _NOTE(ARGUNUSED(ap))
2438 #endif
2439         pMpi2SasPhyPage0_t      sasphypage;
2440         int                     rval = DDI_SUCCESS;
2441         uint16_t                *owner_devhdl, *attached_devhdl;
2442         uint8_t                 *attached_phy_identify;
2443         uint32_t                *attached_phy_info;
2444         uint8_t                 *programmed_link_rate;


2626  * This function will retrieve the base
2627  * Chip name, Board Name,Board Trace number from the adapter.
2628  * Since this function is only called during the
2629  * initialization process, use handshaking.
2630  */
2631 int
2632 mptsas_get_manufacture_page0(mptsas_t *mpt)
2633 {
2634         ddi_dma_attr_t                  recv_dma_attrs, page_dma_attrs;
2635         ddi_dma_cookie_t                page_cookie;
2636         ddi_dma_handle_t                recv_dma_handle, page_dma_handle;
2637         ddi_acc_handle_t                recv_accessp, page_accessp;
2638         pMpi2ConfigReply_t              configreply;
2639         caddr_t                         recv_memp, page_memp;
2640         int                             recv_numbytes;
2641         pMpi2ManufacturingPage0_t       m0;
2642         uint32_t                        flagslength;
2643         int                             rval = DDI_SUCCESS;
2644         uint_t                          iocstatus;
2645         uint8_t                         i = 0;
2646         boolean_t               free_recv = B_FALSE, free_page = B_FALSE;
2647 
2648         MPTSAS_DISABLE_INTR(mpt);
2649 
2650         if (mptsas_send_config_request_msg(mpt, MPI2_CONFIG_ACTION_PAGE_HEADER,
2651             MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 0, 0, 0, 0, 0)) {
2652                 rval = DDI_FAILURE;
2653                 goto done;
2654         }
2655 
2656         /*
2657          * dynamically create a customized dma attribute structure
2658          * that describes the MPT's config reply page request structure.
2659          */
2660         recv_dma_attrs = mpt->m_msg_dma_attr;
2661         recv_dma_attrs.dma_attr_sgllen = 1;
2662         recv_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_REPLY));
2663 
2664         if (mptsas_dma_addr_create(mpt, recv_dma_attrs, &recv_dma_handle,
2665             &recv_accessp, &recv_memp, (sizeof (MPI2_CONFIG_REPLY)),
2666             NULL) == FALSE) {
2667                 rval = DDI_FAILURE;
2668                 goto done;
2669         }
2670         /* Now safe to call mptsas_dma_addr_destroy(recv_dma_handle). */
2671         free_recv = B_TRUE;
2672 
2673         bzero(recv_memp, sizeof (MPI2_CONFIG_REPLY));
2674         configreply = (pMpi2ConfigReply_t)recv_memp;
2675         recv_numbytes = sizeof (MPI2_CONFIG_REPLY);
2676 
2677         /*
2678          * get config reply message
2679          */
2680         if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2681             recv_accessp)) {
2682                 rval = DDI_FAILURE;
2683                 goto done;
2684         }
2685 
2686         if (iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus)) {
2687                 mptsas_log(mpt, CE_WARN, "mptsas_get_manufacture_page5 update: "
2688                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
2689                     ddi_get32(recv_accessp, &configreply->IOCLogInfo));
2690                 goto done;
2691         }
2692 
2693         /*
2694          * dynamically create a customized dma attribute structure
2695          * that describes the MPT's config page structure.
2696          */
2697         page_dma_attrs = mpt->m_msg_dma_attr;
2698         page_dma_attrs.dma_attr_sgllen = 1;
2699         page_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_PAGE_MAN_0));
2700 
2701         if (mptsas_dma_addr_create(mpt, page_dma_attrs, &page_dma_handle,
2702             &page_accessp, &page_memp, (sizeof (MPI2_CONFIG_PAGE_MAN_0)),
2703             &page_cookie) == FALSE) {
2704                 rval = DDI_FAILURE;
2705                 goto done;
2706         }
2707         /* Now safe to call mptsas_dma_addr_destroy(page_dma_handle). */
2708         free_page = B_TRUE;
2709 
2710         bzero(page_memp, sizeof (MPI2_CONFIG_PAGE_MAN_0));
2711         m0 = (pMpi2ManufacturingPage0_t)page_memp;
2712 
2713         /*
2714          * Give reply address to IOC to store config page in and send
2715          * config request out.
2716          */
2717 
2718         flagslength = sizeof (MPI2_CONFIG_PAGE_MAN_0);
2719         flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
2720             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
2721             MPI2_SGE_FLAGS_SYSTEM_ADDRESS | MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
2722             MPI2_SGE_FLAGS_IOC_TO_HOST |
2723             MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
2724 
2725         if (mptsas_send_config_request_msg(mpt,
2726             MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
2727             MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 0,
2728             ddi_get8(recv_accessp, &configreply->Header.PageVersion),
2729             ddi_get8(recv_accessp, &configreply->Header.PageLength),
2730             flagslength, page_cookie.dmac_laddress)) {
2731                 rval = DDI_FAILURE;
2732                 goto done;
2733         }
2734 
2735         /*
2736          * get reply view handshake
2737          */
2738         if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2739             recv_accessp)) {
2740                 rval = DDI_FAILURE;
2741                 goto done;
2742         }
2743 
2744         if (iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus)) {
2745                 mptsas_log(mpt, CE_WARN, "mptsas_get_manufacture_page0 config: "
2746                     "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
2747                     ddi_get32(recv_accessp, &configreply->IOCLogInfo));
2748                 goto done;
2749         }
2750 


2783                 mpt->m_MANU_page0.BoardTracerNumber[i] =
2784                     ddi_get8(page_accessp,
2785                     (uint8_t *)(void *)&m0->BoardTracerNumber[i]);
2786         }
2787 
2788         if ((mptsas_check_dma_handle(recv_dma_handle) != DDI_SUCCESS) ||
2789             (mptsas_check_dma_handle(page_dma_handle) != DDI_SUCCESS)) {
2790                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2791                 rval = DDI_FAILURE;
2792                 goto done;
2793         }
2794         if ((mptsas_check_acc_handle(recv_accessp) != DDI_SUCCESS) ||
2795             (mptsas_check_acc_handle(page_accessp) != DDI_SUCCESS)) {
2796                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2797                 rval = DDI_FAILURE;
2798         }
2799 done:
2800         /*
2801          * free up memory
2802          */
2803         if (free_recv)
2804                 mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);
2805         if (free_page)
2806                 mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
2807         MPTSAS_ENABLE_INTR(mpt);
2808 
2809         return (rval);
2810 }