1 /*
   2  * megaraid_sas.c: source for mega_sas driver
   3  *
   4  * MegaRAID device driver for SAS controllers
   5  * Copyright (c) 2005-2008, LSI Logic Corporation.
   6  * All rights reserved.
   7  *
   8  * Version:
   9  * Author:
  10  *              Rajesh Prabhakaran<Rajesh.Prabhakaran@lsil.com>
  11  *              Seokmann Ju
  12  *
  13  * Redistribution and use in source and binary forms, with or without
  14  * modification, are permitted provided that the following conditions are met:
  15  *
  16  * 1. Redistributions of source code must retain the above copyright notice,
  17  *    this list of conditions and the following disclaimer.
  18  *
  19  * 2. Redistributions in binary form must reproduce the above copyright notice,
  20  *    this list of conditions and the following disclaimer in the documentation
  21  *    and/or other materials provided with the distribution.
  22  *
  23  * 3. Neither the name of the author nor the names of its contributors may be
  24  *    used to endorse or promote products derived from this software without
  25  *    specific prior written permission.
  26  *
  27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  28  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  30  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  31  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  32  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  33  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  34  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  35  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  36  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  38  * DAMAGE.
  39  */
  40 
  41 /*
  42  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  43  * Use is subject to license terms.
  44  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
  45  */
  46 
  47 #include <sys/types.h>
  48 #include <sys/param.h>
  49 #include <sys/file.h>
  50 #include <sys/errno.h>
  51 #include <sys/open.h>
  52 #include <sys/cred.h>
  53 #include <sys/modctl.h>
  54 #include <sys/conf.h>
  55 #include <sys/devops.h>
  56 #include <sys/cmn_err.h>
  57 #include <sys/kmem.h>
  58 #include <sys/stat.h>
  59 #include <sys/mkdev.h>
  60 #include <sys/pci.h>
  61 #include <sys/scsi/scsi.h>
  62 #include <sys/ddi.h>
  63 #include <sys/sunddi.h>
  64 #include <sys/atomic.h>
  65 #include <sys/signal.h>
  66 
  67 #include "megaraid_sas.h"
  68 
  69 /*
  70  * FMA header files
  71  */
  72 #include <sys/ddifm.h>
  73 #include <sys/fm/protocol.h>
  74 #include <sys/fm/util.h>
  75 #include <sys/fm/io/ddi.h>
  76 
  77 /*
  78  * Local static data
  79  */
  80 static void     *megasas_state = NULL;
  81 static int      debug_level_g = CL_ANN;
  82 
  83 #pragma weak scsi_hba_open
  84 #pragma weak scsi_hba_close
  85 #pragma weak scsi_hba_ioctl
  86 
  87 static ddi_dma_attr_t megasas_generic_dma_attr = {
  88         DMA_ATTR_V0,            /* dma_attr_version */
  89         0,                      /* low DMA address range */
  90         0xFFFFFFFFU,            /* high DMA address range */
  91         0xFFFFFFFFU,            /* DMA counter register  */
  92         8,                      /* DMA address alignment */
  93         0x07,                   /* DMA burstsizes  */
  94         1,                      /* min DMA size */
  95         0xFFFFFFFFU,            /* max DMA size */
  96         0xFFFFFFFFU,            /* segment boundary */
  97         MEGASAS_MAX_SGE_CNT,    /* dma_attr_sglen */
  98         512,                    /* granularity of device */
  99         0                       /* bus specific DMA flags */
 100 };
 101 
 102 int32_t megasas_max_cap_maxxfer = 0x1000000;
 103 
 104 /*
 105  * cb_ops contains base level routines
 106  */
 107 static struct cb_ops megasas_cb_ops = {
 108         megasas_open,           /* open */
 109         megasas_close,          /* close */
 110         nodev,                  /* strategy */
 111         nodev,                  /* print */
 112         nodev,                  /* dump */
 113         nodev,                  /* read */
 114         nodev,                  /* write */
 115         megasas_ioctl,          /* ioctl */
 116         nodev,                  /* devmap */
 117         nodev,                  /* mmap */
 118         nodev,                  /* segmap */
 119         nochpoll,               /* poll */
 120         nodev,                  /* cb_prop_op */
 121         0,                      /* streamtab  */
 122         D_NEW | D_HOTPLUG,      /* cb_flag */
 123         CB_REV,                 /* cb_rev */
 124         nodev,                  /* cb_aread */
 125         nodev                   /* cb_awrite */
 126 };
 127 
 128 /*
 129  * dev_ops contains configuration routines
 130  */
 131 static struct dev_ops megasas_ops = {
 132         DEVO_REV,               /* rev, */
 133         0,                      /* refcnt */
 134         megasas_getinfo,        /* getinfo */
 135         nulldev,                /* identify */
 136         nulldev,                /* probe */
 137         megasas_attach,         /* attach */
 138         megasas_detach,         /* detach */
 139         megasas_reset,          /* reset */
 140         &megasas_cb_ops,    /* char/block ops */
 141         NULL,                   /* bus ops */
 142         NULL,                   /* power */
 143         ddi_quiesce_not_supported,      /* devo_quiesce */
 144 };
 145 
 146 static struct modldrv modldrv = {
 147         &mod_driverops,             /* module type - driver */
 148         MEGASAS_VERSION,
 149         &megasas_ops,               /* driver ops */
 150 };
 151 
 152 static struct modlinkage modlinkage = {
 153         MODREV_1,               /* ml_rev - must be MODREV_1 */
 154         { &modldrv, NULL }  /* ml_linkage */
 155 };
 156 
 157 static struct ddi_device_acc_attr endian_attr = {
 158         DDI_DEVICE_ATTR_V1,
 159         DDI_STRUCTURE_LE_ACC,
 160         DDI_STRICTORDER_ACC,
 161         DDI_DEFAULT_ACC
 162 };
 163 
 164 
 165 /*
 166  * ************************************************************************** *
 167  *                                                                            *
 168  *         common entry points - for loadable kernel modules                  *
 169  *                                                                            *
 170  * ************************************************************************** *
 171  */
 172 
 173 /*
 174  * _init - initialize a loadable module
 175  * @void
 176  *
 177  * The driver should perform any one-time resource allocation or data
 178  * initialization during driver loading in _init(). For example, the driver
 179  * should initialize any mutexes global to the driver in this routine.
 180  * The driver should not, however, use _init() to allocate or initialize
 181  * anything that has to do with a particular instance of the device.
 182  * Per-instance initialization must be done in attach().
 183  */
 184 int
 185 _init(void)
 186 {
 187         int ret;
 188 
 189         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
 190 
 191         ret = ddi_soft_state_init(&megasas_state,
 192             sizeof (struct megasas_instance), 0);
 193 
 194         if (ret != 0) {
 195                 con_log(CL_ANN, (CE_WARN, "megaraid: could not init state"));
 196                 return (ret);
 197         }
 198 
 199         if ((ret = scsi_hba_init(&modlinkage)) != 0) {
 200                 con_log(CL_ANN, (CE_WARN, "megaraid: could not init scsi hba"));
 201                 ddi_soft_state_fini(&megasas_state);
 202                 return (ret);
 203         }
 204 
 205         ret = mod_install(&modlinkage);
 206 
 207         if (ret != 0) {
 208                 con_log(CL_ANN, (CE_WARN, "megaraid: mod_install failed"));
 209                 scsi_hba_fini(&modlinkage);
 210                 ddi_soft_state_fini(&megasas_state);
 211         }
 212 
 213         return (ret);
 214 }
 215 
 216 /*
 217  * _info - returns information about a loadable module.
 218  * @void
 219  *
 220  * _info() is called to return module information. This is a typical entry
 221  * point that does predefined role. It simply calls mod_info().
 222  */
 223 int
 224 _info(struct modinfo *modinfop)
 225 {
 226         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
 227 
 228         return (mod_info(&modlinkage, modinfop));
 229 }
 230 
 231 /*
 232  * _fini - prepare a loadable module for unloading
 233  * @void
 234  *
 235  * In _fini(), the driver should release any resources that were allocated in
 236  * _init(). The driver must remove itself from the system module list.
 237  */
 238 int
 239 _fini(void)
 240 {
 241         int ret;
 242 
 243         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
 244 
 245         if ((ret = mod_remove(&modlinkage)) != 0)
 246                 return (ret);
 247 
 248         scsi_hba_fini(&modlinkage);
 249 
 250         ddi_soft_state_fini(&megasas_state);
 251 
 252         return (ret);
 253 }
 254 
 255 
 256 /*
 257  * ************************************************************************** *
 258  *                                                                            *
 259  *               common entry points - for autoconfiguration                  *
 260  *                                                                            *
 261  * ************************************************************************** *
 262  */
 263 /*
 264  * attach - adds a device to the system as part of initialization
 265  * @dip:
 266  * @cmd:
 267  *
 268  * The kernel calls a driver's attach() entry point to attach an instance of
 269  * a device (for MegaRAID, it is instance of a controller) or to resume
 270  * operation for an instance of a device that has been suspended or has been
 271  * shut down by the power management framework
 272  * The attach() entry point typically includes the following types of
 273  * processing:
 274  * - allocate a soft-state structure for the device instance (for MegaRAID,
 275  *   controller instance)
 276  * - initialize per-instance mutexes
 277  * - initialize condition variables
 278  * - register the device's interrupts (for MegaRAID, controller's interrupts)
 279  * - map the registers and memory of the device instance (for MegaRAID,
 280  *   controller instance)
 281  * - create minor device nodes for the device instance (for MegaRAID,
 282  *   controller instance)
 283  * - report that the device instance (for MegaRAID, controller instance) has
 284  *   attached
 285  */
 286 static int
 287 megasas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 288 {
 289         int             instance_no;
 290         int             nregs;
 291         uint8_t         added_isr_f = 0;
 292         uint8_t         added_soft_isr_f = 0;
 293         uint8_t         create_devctl_node_f = 0;
 294         uint8_t         create_scsi_node_f = 0;
 295         uint8_t         create_ioc_node_f = 0;
 296         uint8_t         tran_alloc_f = 0;
 297         uint8_t         irq;
 298         uint16_t        vendor_id;
 299         uint16_t        device_id;
 300         uint16_t        subsysvid;
 301         uint16_t        subsysid;
 302         uint16_t        command;
 303 
 304         scsi_hba_tran_t         *tran;
 305         ddi_dma_attr_t  tran_dma_attr;
 306         struct megasas_instance *instance;
 307 
 308         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
 309 
 310         /* CONSTCOND */
 311         ASSERT(NO_COMPETING_THREADS);
 312 
 313         instance_no = ddi_get_instance(dip);
 314 
 315         /*
 316          * Since we know that some instantiations of this device can be
 317          * plugged into slave-only SBus slots, check to see whether this is
 318          * one such.
 319          */
 320         if (ddi_slaveonly(dip) == DDI_SUCCESS) {
 321                 con_log(CL_ANN, (CE_WARN,
 322                     "mega%d: Device in slave-only slot, unused", instance_no));
 323                 return (DDI_FAILURE);
 324         }
 325 
 326         switch (cmd) {
 327                 case DDI_ATTACH:
 328                         con_log(CL_DLEVEL1, (CE_NOTE, "megasas: DDI_ATTACH"));
 329                         /* allocate the soft state for the instance */
 330                         if (ddi_soft_state_zalloc(megasas_state, instance_no)
 331                             != DDI_SUCCESS) {
 332                                 con_log(CL_ANN, (CE_WARN,
 333                                     "mega%d: Failed to allocate soft state",
 334                                     instance_no));
 335 
 336                                 return (DDI_FAILURE);
 337                         }
 338 
 339                         instance = (struct megasas_instance *)ddi_get_soft_state
 340                             (megasas_state, instance_no);
 341 
 342                         if (instance == NULL) {
 343                                 con_log(CL_ANN, (CE_WARN,
 344                                     "mega%d: Bad soft state", instance_no));
 345 
 346                                 ddi_soft_state_free(megasas_state, instance_no);
 347 
 348                                 return (DDI_FAILURE);
 349                         }
 350 
 351                         bzero((caddr_t)instance,
 352                             sizeof (struct megasas_instance));
 353 
 354                         instance->func_ptr = kmem_zalloc(
 355                             sizeof (struct megasas_func_ptr), KM_SLEEP);
 356                         ASSERT(instance->func_ptr);
 357 
 358                         /* Setup the PCI configuration space handles */
 359                         if (pci_config_setup(dip, &instance->pci_handle) !=
 360                             DDI_SUCCESS) {
 361                                 con_log(CL_ANN, (CE_WARN,
 362                                     "mega%d: pci config setup failed ",
 363                                     instance_no));
 364 
 365                                 kmem_free(instance->func_ptr,
 366                                     sizeof (struct megasas_func_ptr));
 367                                 ddi_soft_state_free(megasas_state, instance_no);
 368 
 369                                 return (DDI_FAILURE);
 370                         }
 371 
 372                         if (ddi_dev_nregs(dip, &nregs) != DDI_SUCCESS) {
 373                                 con_log(CL_ANN, (CE_WARN,
 374                                     "megaraid: failed to get registers."));
 375 
 376                                 pci_config_teardown(&instance->pci_handle);
 377                                 kmem_free(instance->func_ptr,
 378                                     sizeof (struct megasas_func_ptr));
 379                                 ddi_soft_state_free(megasas_state, instance_no);
 380 
 381                                 return (DDI_FAILURE);
 382                         }
 383 
 384                         vendor_id = pci_config_get16(instance->pci_handle,
 385                             PCI_CONF_VENID);
 386                         device_id = pci_config_get16(instance->pci_handle,
 387                             PCI_CONF_DEVID);
 388 
 389                         subsysvid = pci_config_get16(instance->pci_handle,
 390                             PCI_CONF_SUBVENID);
 391                         subsysid = pci_config_get16(instance->pci_handle,
 392                             PCI_CONF_SUBSYSID);
 393 
 394                         pci_config_put16(instance->pci_handle, PCI_CONF_COMM,
 395                             (pci_config_get16(instance->pci_handle,
 396                             PCI_CONF_COMM) | PCI_COMM_ME));
 397                         irq = pci_config_get8(instance->pci_handle,
 398                             PCI_CONF_ILINE);
 399 
 400                         con_log(CL_DLEVEL1, (CE_CONT, "megasas%d: "
 401                             "0x%x:0x%x 0x%x:0x%x, irq:%d drv-ver:%s\n",
 402                             instance_no, vendor_id, device_id, subsysvid,
 403                             subsysid, irq, MEGASAS_VERSION));
 404 
 405                         /* enable bus-mastering */
 406                         command = pci_config_get16(instance->pci_handle,
 407                             PCI_CONF_COMM);
 408 
 409                         if (!(command & PCI_COMM_ME)) {
 410                                 command |= PCI_COMM_ME;
 411 
 412                                 pci_config_put16(instance->pci_handle,
 413                                     PCI_CONF_COMM, command);
 414 
 415                                 con_log(CL_ANN, (CE_CONT, "megaraid%d: "
 416                                     "enable bus-mastering\n", instance_no));
 417                         } else {
 418                                 con_log(CL_DLEVEL1, (CE_CONT, "megaraid%d: "
 419                                 "bus-mastering already set\n", instance_no));
 420                         }
 421 
 422                         /* initialize function pointers */
 423                         if ((device_id == PCI_DEVICE_ID_LSI_1078) ||
 424                             (device_id == PCI_DEVICE_ID_LSI_1078DE)) {
 425                                 con_log(CL_DLEVEL1, (CE_CONT, "megasas%d: "
 426                                     "1078R/DE detected\n", instance_no));
 427                                 instance->func_ptr->read_fw_status_reg =
 428                                     read_fw_status_reg_ppc;
 429                                 instance->func_ptr->issue_cmd = issue_cmd_ppc;
 430                                 instance->func_ptr->issue_cmd_in_sync_mode =
 431                                     issue_cmd_in_sync_mode_ppc;
 432                                 instance->func_ptr->issue_cmd_in_poll_mode =
 433                                     issue_cmd_in_poll_mode_ppc;
 434                                 instance->func_ptr->enable_intr =
 435                                     enable_intr_ppc;
 436                                 instance->func_ptr->disable_intr =
 437                                     disable_intr_ppc;
 438                                 instance->func_ptr->intr_ack = intr_ack_ppc;
 439                         } else {
 440                                 con_log(CL_DLEVEL1, (CE_CONT, "megasas%d: "
 441                                     "1064/8R detected\n", instance_no));
 442                                 instance->func_ptr->read_fw_status_reg =
 443                                     read_fw_status_reg_xscale;
 444                                 instance->func_ptr->issue_cmd =
 445                                     issue_cmd_xscale;
 446                                 instance->func_ptr->issue_cmd_in_sync_mode =
 447                                     issue_cmd_in_sync_mode_xscale;
 448                                 instance->func_ptr->issue_cmd_in_poll_mode =
 449                                     issue_cmd_in_poll_mode_xscale;
 450                                 instance->func_ptr->enable_intr =
 451                                     enable_intr_xscale;
 452                                 instance->func_ptr->disable_intr =
 453                                     disable_intr_xscale;
 454                                 instance->func_ptr->intr_ack =
 455                                     intr_ack_xscale;
 456                         }
 457 
 458                         instance->baseaddress = pci_config_get32(
 459                             instance->pci_handle, PCI_CONF_BASE0);
 460                         instance->baseaddress &= 0x0fffc;
 461 
 462                         instance->dip                = dip;
 463                         instance->vendor_id  = vendor_id;
 464                         instance->device_id  = device_id;
 465                         instance->subsysvid  = subsysvid;
 466                         instance->subsysid   = subsysid;
 467 
 468                         /* Initialize FMA */
 469                         instance->fm_capabilities = ddi_prop_get_int(
 470                             DDI_DEV_T_ANY, instance->dip, DDI_PROP_DONTPASS,
 471                             "fm-capable", DDI_FM_EREPORT_CAPABLE |
 472                             DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE
 473                             | DDI_FM_ERRCB_CAPABLE);
 474 
 475                         megasas_fm_init(instance);
 476 
 477                         /* setup the mfi based low level driver */
 478                         if (init_mfi(instance) != DDI_SUCCESS) {
 479                                 con_log(CL_ANN, (CE_WARN, "megaraid: "
 480                                 "could not initialize the low level driver"));
 481 
 482                                 goto fail_attach;
 483                         }
 484 
 485                         /*
 486                          * Allocate the interrupt blocking cookie.
 487                          * It represents the information the framework
 488                          * needs to block interrupts. This cookie will
 489                          * be used by the locks shared accross our ISR.
 490                          * These locks must be initialized before we
 491                          * register our ISR.
 492                          * ddi_add_intr(9F)
 493                          */
 494                         if (ddi_get_iblock_cookie(dip, 0,
 495                             &instance->iblock_cookie) != DDI_SUCCESS) {
 496 
 497                                 goto fail_attach;
 498                         }
 499 
 500                         if (ddi_get_soft_iblock_cookie(dip, DDI_SOFTINT_HIGH,
 501                             &instance->soft_iblock_cookie) != DDI_SUCCESS) {
 502 
 503                                 goto fail_attach;
 504                         }
 505 
 506                         /*
 507                          * Initialize the driver mutexes common to
 508                          * normal/high level isr
 509                          */
 510                         if (ddi_intr_hilevel(dip, 0)) {
 511                                 instance->isr_level = HIGH_LEVEL_INTR;
 512                                 mutex_init(&instance->cmd_pool_mtx,
 513                                     "cmd_pool_mtx", MUTEX_DRIVER,
 514                                     instance->soft_iblock_cookie);
 515                                 mutex_init(&instance->cmd_pend_mtx,
 516                                     "cmd_pend_mtx", MUTEX_DRIVER,
 517                                     instance->soft_iblock_cookie);
 518                         } else {
 519                                 /*
 520                                  * Initialize the driver mutexes
 521                                  * specific to soft-isr
 522                                  */
 523                                 instance->isr_level = NORMAL_LEVEL_INTR;
 524                                 mutex_init(&instance->cmd_pool_mtx,
 525                                     "cmd_pool_mtx", MUTEX_DRIVER,
 526                                     instance->iblock_cookie);
 527                                 mutex_init(&instance->cmd_pend_mtx,
 528                                     "cmd_pend_mtx", MUTEX_DRIVER,
 529                                     instance->iblock_cookie);
 530                         }
 531 
 532                         mutex_init(&instance->completed_pool_mtx,
 533                             "completed_pool_mtx", MUTEX_DRIVER,
 534                             instance->iblock_cookie);
 535                         mutex_init(&instance->int_cmd_mtx, "int_cmd_mtx",
 536                             MUTEX_DRIVER, instance->iblock_cookie);
 537                         mutex_init(&instance->aen_cmd_mtx, "aen_cmd_mtx",
 538                             MUTEX_DRIVER, instance->iblock_cookie);
 539                         mutex_init(&instance->abort_cmd_mtx, "abort_cmd_mtx",
 540                             MUTEX_DRIVER, instance->iblock_cookie);
 541 
 542                         cv_init(&instance->int_cmd_cv, NULL, CV_DRIVER, NULL);
 543                         cv_init(&instance->abort_cmd_cv, NULL, CV_DRIVER, NULL);
 544 
 545                         INIT_LIST_HEAD(&instance->completed_pool_list);
 546 
 547                         /* Register our isr. */
 548                         if (ddi_add_intr(dip, 0, NULL, NULL, megasas_isr,
 549                             (caddr_t)instance) != DDI_SUCCESS) {
 550                                 con_log(CL_ANN, (CE_WARN,
 551                                     " ISR did not register"));
 552 
 553                                 goto fail_attach;
 554                         }
 555 
 556                         added_isr_f = 1;
 557 
 558                         /* Register our soft-isr for highlevel interrupts. */
 559                         if (instance->isr_level == HIGH_LEVEL_INTR) {
 560                                 if (ddi_add_softintr(dip, DDI_SOFTINT_HIGH,
 561                                     &instance->soft_intr_id, NULL, NULL,
 562                                     megasas_softintr, (caddr_t)instance) !=
 563                                     DDI_SUCCESS) {
 564                                         con_log(CL_ANN, (CE_WARN,
 565                                             " Software ISR did not register"));
 566 
 567                                         goto fail_attach;
 568                                 }
 569 
 570                                 added_soft_isr_f = 1;
 571                         }
 572 
 573                         /* Allocate a transport structure */
 574                         tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP);
 575 
 576                         if (tran == NULL) {
 577                                 con_log(CL_ANN, (CE_WARN,
 578                                     "scsi_hba_tran_alloc failed"));
 579                                 goto fail_attach;
 580                         }
 581 
 582                         tran_alloc_f = 1;
 583 
 584                         instance->tran = tran;
 585 
 586                         tran->tran_hba_private       = instance;
 587                         tran->tran_tgt_private       = NULL;
 588                         tran->tran_tgt_init  = megasas_tran_tgt_init;
 589                         tran->tran_tgt_probe = scsi_hba_probe;
 590                         tran->tran_tgt_free  = (void (*)())NULL;
 591                         tran->tran_init_pkt  = megasas_tran_init_pkt;
 592                         tran->tran_start     = megasas_tran_start;
 593                         tran->tran_abort     = megasas_tran_abort;
 594                         tran->tran_reset     = megasas_tran_reset;
 595                         tran->tran_bus_reset = megasas_tran_bus_reset;
 596                         tran->tran_getcap    = megasas_tran_getcap;
 597                         tran->tran_setcap    = megasas_tran_setcap;
 598                         tran->tran_destroy_pkt       = megasas_tran_destroy_pkt;
 599                         tran->tran_dmafree   = megasas_tran_dmafree;
 600                         tran->tran_sync_pkt  = megasas_tran_sync_pkt;
 601                         tran->tran_reset_notify      = NULL;
 602                         tran->tran_quiesce   = megasas_tran_quiesce;
 603                         tran->tran_unquiesce = megasas_tran_unquiesce;
 604 
 605                         tran_dma_attr = megasas_generic_dma_attr;
 606                         tran_dma_attr.dma_attr_sgllen = instance->max_num_sge;
 607 
 608                         /* Attach this instance of the hba */
 609                         if (scsi_hba_attach_setup(dip, &tran_dma_attr, tran, 0)
 610                             != DDI_SUCCESS) {
 611                                 con_log(CL_ANN, (CE_WARN,
 612                                     "scsi_hba_attach failed\n"));
 613 
 614                                 goto fail_attach;
 615                         }
 616 
 617                         /* create devctl node for cfgadm command */
 618                         if (ddi_create_minor_node(dip, "devctl",
 619                             S_IFCHR, INST2DEVCTL(instance_no),
 620                             DDI_NT_SCSI_NEXUS, 0) == DDI_FAILURE) {
 621                                 con_log(CL_ANN, (CE_WARN,
 622                                     "megaraid: failed to create devctl node."));
 623 
 624                                 goto fail_attach;
 625                         }
 626 
 627                         create_devctl_node_f = 1;
 628 
 629                         /* create scsi node for cfgadm command */
 630                         if (ddi_create_minor_node(dip, "scsi", S_IFCHR,
 631                             INST2SCSI(instance_no),
 632                             DDI_NT_SCSI_ATTACHMENT_POINT, 0) ==
 633                             DDI_FAILURE) {
 634                                 con_log(CL_ANN, (CE_WARN,
 635                                     "megaraid: failed to create scsi node."));
 636 
 637                                 goto fail_attach;
 638                         }
 639 
 640                         create_scsi_node_f = 1;
 641 
 642                         (void) sprintf(instance->iocnode, "%d:lsirdctl",
 643                             instance_no);
 644 
 645                         /*
 646                          * Create a node for applications
 647                          * for issuing ioctl to the driver.
 648                          */
 649                         if (ddi_create_minor_node(dip, instance->iocnode,
 650                             S_IFCHR, INST2LSIRDCTL(instance_no),
 651                             DDI_PSEUDO, 0) == DDI_FAILURE) {
 652                                 con_log(CL_ANN, (CE_WARN,
 653                                     "megaraid: failed to create ioctl node."));
 654 
 655                                 goto fail_attach;
 656                         }
 657 
 658                         create_ioc_node_f = 1;
 659 
 660                         /* enable interrupt */
 661                         instance->func_ptr->enable_intr(instance);
 662 
 663                         /* initiate AEN */
 664                         if (start_mfi_aen(instance)) {
 665                                 con_log(CL_ANN, (CE_WARN,
 666                                     "megaraid: failed to initiate AEN."));
 667                                 goto fail_initiate_aen;
 668                         }
 669 
 670                         con_log(CL_DLEVEL1, (CE_NOTE,
 671                             "AEN started for instance %d.", instance_no));
 672 
 673                         /* Finally! We are on the air.  */
 674                         ddi_report_dev(dip);
 675 
 676                         if (megasas_check_acc_handle(instance->regmap_handle) !=
 677                             DDI_SUCCESS) {
 678                                 goto fail_attach;
 679                         }
 680                         if (megasas_check_acc_handle(instance->pci_handle) !=
 681                             DDI_SUCCESS) {
 682                                 goto fail_attach;
 683                         }
 684                         break;
 685                 case DDI_PM_RESUME:
 686                         con_log(CL_ANN, (CE_NOTE,
 687                             "megasas: DDI_PM_RESUME"));
 688                         break;
 689                 case DDI_RESUME:
 690                         con_log(CL_ANN, (CE_NOTE,
 691                             "megasas: DDI_RESUME"));
 692                         break;
 693                 default:
 694                         con_log(CL_ANN, (CE_WARN,
 695                             "megasas: invalid attach cmd=%x", cmd));
 696                         return (DDI_FAILURE);
 697         }
 698 
 699         return (DDI_SUCCESS);
 700 
 701 fail_initiate_aen:
 702 fail_attach:
 703         if (create_devctl_node_f) {
 704                 ddi_remove_minor_node(dip, "devctl");
 705         }
 706 
 707         if (create_scsi_node_f) {
 708                 ddi_remove_minor_node(dip, "scsi");
 709         }
 710 
 711         if (create_ioc_node_f) {
 712                 ddi_remove_minor_node(dip, instance->iocnode);
 713         }
 714 
 715         if (tran_alloc_f) {
 716                 scsi_hba_tran_free(tran);
 717         }
 718 
 719 
 720         if (added_soft_isr_f) {
 721                 ddi_remove_softintr(instance->soft_intr_id);
 722         }
 723 
 724         if (added_isr_f) {
 725                 ddi_remove_intr(dip, 0, instance->iblock_cookie);
 726         }
 727 
 728         megasas_fm_ereport(instance, DDI_FM_DEVICE_NO_RESPONSE);
 729         ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
 730 
 731         megasas_fm_fini(instance);
 732 
 733         pci_config_teardown(&instance->pci_handle);
 734 
 735         ddi_soft_state_free(megasas_state, instance_no);
 736 
 737         con_log(CL_ANN, (CE_NOTE,
 738             "megasas: return failure from mega_attach\n"));
 739 
 740         return (DDI_FAILURE);
 741 }
 742 
 743 /*
 744  * getinfo - gets device information
 745  * @dip:
 746  * @cmd:
 747  * @arg:
 748  * @resultp:
 749  *
 750  * The system calls getinfo() to obtain configuration information that only
 751  * the driver knows. The mapping of minor numbers to device instance is
 752  * entirely under the control of the driver. The system sometimes needs to ask
 753  * the driver which device a particular dev_t represents.
 754  * Given the device number return the devinfo pointer from the scsi_device
 755  * structure.
 756  */
 757 /*ARGSUSED*/
 758 static int
 759 megasas_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,  void *arg, void **resultp)
 760 {
 761         int     rval;
 762         int     megasas_minor = getminor((dev_t)arg);
 763 
 764         struct megasas_instance *instance;
 765 
 766         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
 767 
 768         switch (cmd) {
 769                 case DDI_INFO_DEVT2DEVINFO:
 770                         instance = (struct megasas_instance *)
 771                             ddi_get_soft_state(megasas_state,
 772                             MINOR2INST(megasas_minor));
 773 
 774                         if (instance == NULL) {
 775                                 *resultp = NULL;
 776                                 rval = DDI_FAILURE;
 777                         } else {
 778                                 *resultp = instance->dip;
 779                                 rval = DDI_SUCCESS;
 780                         }
 781                         break;
 782                 case DDI_INFO_DEVT2INSTANCE:
 783                         *resultp = (void *)instance;
 784                         rval = DDI_SUCCESS;
 785                         break;
 786                 default:
 787                         *resultp = NULL;
 788                         rval = DDI_FAILURE;
 789         }
 790 
 791         return (rval);
 792 }
 793 
 794 /*
 795  * detach - detaches a device from the system
 796  * @dip: pointer to the device's dev_info structure
 797  * @cmd: type of detach
 798  *
 799  * A driver's detach() entry point is called to detach an instance of a device
 800  * that is bound to the driver. The entry point is called with the instance of
 801  * the device node to be detached and with DDI_DETACH, which is specified as
 802  * the cmd argument to the entry point.
 803  * This routine is called during driver unload. We free all the allocated
 804  * resources and call the corresponding LLD so that it can also release all
 805  * its resources.
 806  */
 807 static int
 808 megasas_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 809 {
 810         int     instance_no;
 811 
 812         struct megasas_instance *instance;
 813 
 814         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
 815 
 816         /* CONSTCOND */
 817         ASSERT(NO_COMPETING_THREADS);
 818 
 819         instance_no = ddi_get_instance(dip);
 820 
 821         instance = (struct megasas_instance *)ddi_get_soft_state(megasas_state,
 822             instance_no);
 823 
 824         if (!instance) {
 825                 con_log(CL_ANN, (CE_WARN,
 826                     "megasas:%d could not get instance in detach",
 827                     instance_no));
 828 
 829                 return (DDI_FAILURE);
 830         }
 831 
 832         con_log(CL_ANN, (CE_NOTE,
 833             "megasas%d: detaching device 0x%4x:0x%4x:0x%4x:0x%4x\n",
 834             instance_no, instance->vendor_id, instance->device_id,
 835             instance->subsysvid, instance->subsysid));
 836 
 837         switch (cmd) {
 838                 case DDI_DETACH:
 839                         con_log(CL_ANN, (CE_NOTE,
 840                             "megasas_detach: DDI_DETACH\n"));
 841 
 842                         if (scsi_hba_detach(dip) != DDI_SUCCESS) {
 843                                 con_log(CL_ANN, (CE_WARN,
 844                                     "megasas:%d failed to detach",
 845                                     instance_no));
 846 
 847                                 return (DDI_FAILURE);
 848                         }
 849 
 850                         scsi_hba_tran_free(instance->tran);
 851 
 852                         if (abort_aen_cmd(instance, instance->aen_cmd)) {
 853                                 con_log(CL_ANN, (CE_WARN, "megasas_detach: "
 854                                     "failed to abort prevous AEN command\n"));
 855 
 856                                 return (DDI_FAILURE);
 857                         }
 858 
 859                         instance->func_ptr->disable_intr(instance);
 860 
 861                         if (instance->isr_level == HIGH_LEVEL_INTR) {
 862                                 ddi_remove_softintr(instance->soft_intr_id);
 863                         }
 864 
 865                         ddi_remove_intr(dip, 0, instance->iblock_cookie);
 866 
 867                         free_space_for_mfi(instance);
 868 
 869                         megasas_fm_fini(instance);
 870 
 871                         pci_config_teardown(&instance->pci_handle);
 872 
 873                         kmem_free(instance->func_ptr,
 874                             sizeof (struct megasas_func_ptr));
 875 
 876                         ddi_soft_state_free(megasas_state, instance_no);
 877                         break;
 878                 case DDI_PM_SUSPEND:
 879                         con_log(CL_ANN, (CE_NOTE,
 880                             "megasas_detach: DDI_PM_SUSPEND\n"));
 881 
 882                         break;
 883                 case DDI_SUSPEND:
 884                         con_log(CL_ANN, (CE_NOTE,
 885                             "megasas_detach: DDI_SUSPEND\n"));
 886 
 887                         break;
 888                 default:
 889                         con_log(CL_ANN, (CE_WARN,
 890                             "invalid detach command:0x%x", cmd));
 891                         return (DDI_FAILURE);
 892         }
 893 
 894         return (DDI_SUCCESS);
 895 }
 896 
 897 /*
 898  * ************************************************************************** *
 899  *                                                                            *
 900  *             common entry points - for character driver types               *
 901  *                                                                            *
 902  * ************************************************************************** *
 903  */
 904 /*
 905  * open - gets access to a device
 906  * @dev:
 907  * @openflags:
 908  * @otyp:
 909  * @credp:
 910  *
 911  * Access to a device by one or more application programs is controlled
 912  * through the open() and close() entry points. The primary function of
 913  * open() is to verify that the open request is allowed.
 914  */
 915 static  int
 916 megasas_open(dev_t *dev, int openflags, int otyp, cred_t *credp)
 917 {
 918         int     rval = 0;
 919 
 920         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
 921 
 922         /* Check root permissions */
 923         if (drv_priv(credp) != 0) {
 924                 con_log(CL_ANN, (CE_WARN,
 925                     "megaraid: Non-root ioctl access tried!"));
 926                 return (EPERM);
 927         }
 928 
 929         /* Verify we are being opened as a character device */
 930         if (otyp != OTYP_CHR) {
 931                 con_log(CL_ANN, (CE_WARN,
 932                     "megaraid: ioctl node must be a char node\n"));
 933                 return (EINVAL);
 934         }
 935 
 936         if (ddi_get_soft_state(megasas_state, MINOR2INST(getminor(*dev)))
 937             == NULL) {
 938                 return (ENXIO);
 939         }
 940 
 941         if (scsi_hba_open) {
 942                 rval = scsi_hba_open(dev, openflags, otyp, credp);
 943         }
 944 
 945         return (rval);
 946 }
 947 
 948 /*
 949  * close - gives up access to a device
 950  * @dev:
 951  * @openflags:
 952  * @otyp:
 953  * @credp:
 954  *
 955  * close() should perform any cleanup necessary to finish using the minor
 956  * device, and prepare the device (and driver) to be opened again.
 957  */
 958 static  int
 959 megasas_close(dev_t dev, int openflags, int otyp, cred_t *credp)
 960 {
 961         int     rval = 0;
 962 
 963         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
 964 
 965         /* no need for locks! */
 966 
 967         if (scsi_hba_close) {
 968                 rval = scsi_hba_close(dev, openflags, otyp, credp);
 969         }
 970 
 971         return (rval);
 972 }
 973 
 974 /*
 975  * ioctl - performs a range of I/O commands for character drivers
 976  * @dev:
 977  * @cmd:
 978  * @arg:
 979  * @mode:
 980  * @credp:
 981  * @rvalp:
 982  *
 983  * ioctl() routine must make sure that user data is copied into or out of the
 984  * kernel address space explicitly using copyin(), copyout(), ddi_copyin(),
 985  * and ddi_copyout(), as appropriate.
 986  * This is a wrapper routine to serialize access to the actual ioctl routine.
 987  * ioctl() should return 0 on success, or the appropriate error number. The
 988  * driver may also set the value returned to the calling process through rvalp.
 989  */
 990 static int
 991 megasas_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
 992     int *rvalp)
 993 {
 994         int     rval = 0;
 995 
 996         struct megasas_instance *instance;
 997         struct megasas_ioctl    ioctl;
 998         struct megasas_aen      aen;
 999 
1000         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1001 
1002         instance = ddi_get_soft_state(megasas_state, MINOR2INST(getminor(dev)));
1003 
1004         if (instance == NULL) {
1005                 /* invalid minor number */
1006                 con_log(CL_ANN, (CE_WARN, "megaraid: adapter not found."));
1007                 return (ENXIO);
1008         }
1009 
1010         switch ((uint_t)cmd) {
1011                 case MEGASAS_IOCTL_FIRMWARE:
1012                         if (ddi_copyin((void *) arg, &ioctl,
1013                             sizeof (struct megasas_ioctl), mode)) {
1014                                 con_log(CL_ANN, (CE_WARN, "megasas_ioctl: "
1015                                     "ERROR IOCTL copyin"));
1016                                 return (EFAULT);
1017                         }
1018 
1019                         if (ioctl.control_code == MR_DRIVER_IOCTL_COMMON) {
1020                                 rval = handle_drv_ioctl(instance, &ioctl, mode);
1021                         } else {
1022                                 rval = handle_mfi_ioctl(instance, &ioctl, mode);
1023                         }
1024 
1025                         if (ddi_copyout((void *) &ioctl, (void *)arg,
1026                             (sizeof (struct megasas_ioctl) - 1), mode)) {
1027                                 con_log(CL_ANN, (CE_WARN,
1028                                     "megasas_ioctl: copy_to_user failed\n"));
1029                                 rval = 1;
1030                         }
1031 
1032                         break;
1033                 case MEGASAS_IOCTL_AEN:
1034                         if (ddi_copyin((void *) arg, &aen,
1035                             sizeof (struct megasas_aen), mode)) {
1036                                 con_log(CL_ANN, (CE_WARN,
1037                                     "megasas_ioctl: ERROR AEN copyin"));
1038                                 return (EFAULT);
1039                         }
1040 
1041                         rval = handle_mfi_aen(instance, &aen);
1042 
1043                         if (ddi_copyout((void *) &aen, (void *)arg,
1044                             sizeof (struct megasas_aen), mode)) {
1045                                 con_log(CL_ANN, (CE_WARN,
1046                                     "megasas_ioctl: copy_to_user failed\n"));
1047                                 rval = 1;
1048                         }
1049 
1050                         break;
1051                 default:
1052                         rval = scsi_hba_ioctl(dev, cmd, arg,
1053                             mode, credp, rvalp);
1054 
1055                         con_log(CL_DLEVEL1, (CE_NOTE, "megasas_ioctl: "
1056                             "scsi_hba_ioctl called, ret = %x.", rval));
1057         }
1058 
1059         return (rval);
1060 }
1061 
1062 /*
1063  * ************************************************************************** *
1064  *                                                                            *
1065  *               common entry points - for block driver types                 *
1066  *                                                                            *
1067  * ************************************************************************** *
1068  */
1069 /*
1070  * reset - TBD
1071  * @dip:
1072  * @cmd:
1073  *
1074  * TBD
1075  */
1076 /*ARGSUSED*/
1077 static int
1078 megasas_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
1079 {
1080         int     instance_no;
1081 
1082         struct megasas_instance *instance;
1083 
1084         instance_no = ddi_get_instance(dip);
1085         instance = (struct megasas_instance *)ddi_get_soft_state
1086             (megasas_state, instance_no);
1087 
1088         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1089 
1090         if (!instance) {
1091                 con_log(CL_ANN, (CE_WARN,
1092                     "megaraid:%d could not get adapter in reset",
1093                     instance_no));
1094                 return (DDI_FAILURE);
1095         }
1096 
1097         con_log(CL_ANN, (CE_NOTE, "flushing cache for instance %d ..",
1098             instance_no));
1099 
1100         flush_cache(instance);
1101 
1102         return (DDI_SUCCESS);
1103 }
1104 
1105 
1106 /*
1107  * ************************************************************************** *
1108  *                                                                            *
1109  *                          entry points (SCSI HBA)                           *
1110  *                                                                            *
1111  * ************************************************************************** *
1112  */
1113 /*
1114  * tran_tgt_init - initialize a target device instance
1115  * @hba_dip:
1116  * @tgt_dip:
1117  * @tran:
1118  * @sd:
1119  *
1120  * The tran_tgt_init() entry point enables the HBA to allocate and initialize
1121  * any per-target resources. tran_tgt_init() also enables the HBA to qualify
1122  * the device's address as valid and supportable for that particular HBA.
1123  * By returning DDI_FAILURE, the instance of the target driver for that device
1124  * is not probed or attached.
1125  */
1126 /*ARGSUSED*/
1127 static int
1128 megasas_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
1129                 scsi_hba_tran_t *tran, struct scsi_device *sd)
1130 {
1131         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1132 
1133         return (DDI_SUCCESS);
1134 }
1135 
1136 /*
1137  * tran_init_pkt - allocate & initialize a scsi_pkt structure
1138  * @ap:
1139  * @pkt:
1140  * @bp:
1141  * @cmdlen:
1142  * @statuslen:
1143  * @tgtlen:
1144  * @flags:
1145  * @callback:
1146  *
1147  * The tran_init_pkt() entry point allocates and initializes a scsi_pkt
1148  * structure and DMA resources for a target driver request. The
1149  * tran_init_pkt() entry point is called when the target driver calls the
1150  * SCSA function scsi_init_pkt(). Each call of the tran_init_pkt() entry point
1151  * is a request to perform one or more of three possible services:
1152  *  - allocation and initialization of a scsi_pkt structure
1153  *  - allocation of DMA resources for data transfer
1154  *  - reallocation of DMA resources for the next portion of the data transfer
1155  */
1156 static struct scsi_pkt *
1157 megasas_tran_init_pkt(struct scsi_address *ap, register struct scsi_pkt *pkt,
1158         struct buf *bp, int cmdlen, int statuslen, int tgtlen,
1159         int flags, int (*callback)(), caddr_t arg)
1160 {
1161         struct scsa_cmd *acmd;
1162         struct megasas_instance *instance;
1163         struct scsi_pkt *new_pkt;
1164 
1165         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1166 
1167         instance = ADDR2MEGA(ap);
1168 
1169         /* step #1 : pkt allocation */
1170         if (pkt == NULL) {
1171                 pkt = scsi_hba_pkt_alloc(instance->dip, ap, cmdlen, statuslen,
1172                     tgtlen, sizeof (struct scsa_cmd), callback, arg);
1173                 if (pkt == NULL) {
1174                         return (NULL);
1175                 }
1176 
1177                 acmd = PKT2CMD(pkt);
1178 
1179                 /*
1180                  * Initialize the new pkt - we redundantly initialize
1181                  * all the fields for illustrative purposes.
1182                  */
1183                 acmd->cmd_pkt                = pkt;
1184                 acmd->cmd_flags              = 0;
1185                 acmd->cmd_scblen     = statuslen;
1186                 acmd->cmd_cdblen     = cmdlen;
1187                 acmd->cmd_dmahandle  = NULL;
1188                 acmd->cmd_ncookies   = 0;
1189                 acmd->cmd_cookie     = 0;
1190                 acmd->cmd_cookiecnt  = 0;
1191                 acmd->cmd_nwin               = 0;
1192 
1193                 pkt->pkt_address     = *ap;
1194                 pkt->pkt_comp                = (void (*)())NULL;
1195                 pkt->pkt_flags               = 0;
1196                 pkt->pkt_time                = 0;
1197                 pkt->pkt_resid               = 0;
1198                 pkt->pkt_state               = 0;
1199                 pkt->pkt_statistics  = 0;
1200                 pkt->pkt_reason              = 0;
1201                 new_pkt                 = pkt;
1202         } else {
1203                 acmd = PKT2CMD(pkt);
1204                 new_pkt = NULL;
1205         }
1206 
1207         /* step #2 : dma allocation/move */
1208         if (bp && bp->b_bcount != 0) {
1209                 if (acmd->cmd_dmahandle == NULL) {
1210                         if (megasas_dma_alloc(instance, pkt, bp, flags,
1211                             callback) == -1) {
1212                                 if (new_pkt) {
1213                                         scsi_hba_pkt_free(ap, new_pkt);
1214                                 }
1215 
1216                                 return ((struct scsi_pkt *)NULL);
1217                         }
1218                 } else {
1219                         if (megasas_dma_move(instance, pkt, bp) == -1) {
1220                                 return ((struct scsi_pkt *)NULL);
1221                         }
1222                 }
1223         }
1224 
1225         return (pkt);
1226 }
1227 
1228 /*
1229  * tran_start - transport a SCSI command to the addressed target
1230  * @ap:
1231  * @pkt:
1232  *
1233  * The tran_start() entry point for a SCSI HBA driver is called to transport a
1234  * SCSI command to the addressed target. The SCSI command is described
1235  * entirely within the scsi_pkt structure, which the target driver allocated
1236  * through the HBA driver's tran_init_pkt() entry point. If the command
1237  * involves a data transfer, DMA resources must also have been allocated for
1238  * the scsi_pkt structure.
1239  *
1240  * Return Values :
1241  *      TRAN_BUSY - request queue is full, no more free scbs
1242  *      TRAN_ACCEPT - pkt has been submitted to the instance
1243  */
1244 static int
1245 megasas_tran_start(struct scsi_address *ap, register struct scsi_pkt *pkt)
1246 {
1247         uchar_t         cmd_done = 0;
1248 
1249         struct megasas_instance *instance = ADDR2MEGA(ap);
1250         struct megasas_cmd      *cmd;
1251 
1252         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d:SCSI CDB[0]=0x%x",
1253             __func__, __LINE__, pkt->pkt_cdbp[0]));
1254 
1255         pkt->pkt_reason      = CMD_CMPLT;
1256         *pkt->pkt_scbp = STATUS_GOOD; /* clear arq scsi_status */
1257 
1258         cmd = build_cmd(instance, ap, pkt, &cmd_done);
1259 
1260         /*
1261          * Check if the command is already completed by the mega_build_cmd()
1262          * routine. In which case the busy_flag would be clear and scb will be
1263          * NULL and appropriate reason provided in pkt_reason field
1264          */
1265         if (cmd_done) {
1266                 if ((pkt->pkt_flags & FLAG_NOINTR) == 0) {
1267                         scsi_hba_pkt_comp(pkt);
1268                 }
1269                 pkt->pkt_reason = CMD_CMPLT;
1270                 pkt->pkt_scbp[0] = STATUS_GOOD;
1271                 pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET
1272                     | STATE_SENT_CMD;
1273                 return (TRAN_ACCEPT);
1274         }
1275 
1276         if (cmd == NULL) {
1277                 return (TRAN_BUSY);
1278         }
1279 
1280         if ((pkt->pkt_flags & FLAG_NOINTR) == 0) {
1281                 if (instance->fw_outstanding > instance->max_fw_cmds) {
1282                         con_log(CL_ANN, (CE_CONT, "megasas:Firmware busy"));
1283                         return_mfi_pkt(instance, cmd);
1284                         return (TRAN_BUSY);
1285                 }
1286 
1287                 /* Syncronize the Cmd frame for the controller */
1288                 (void) ddi_dma_sync(cmd->frame_dma_obj.dma_handle, 0, 0,
1289                     DDI_DMA_SYNC_FORDEV);
1290 
1291                 instance->func_ptr->issue_cmd(cmd, instance);
1292 
1293         } else {
1294                 struct megasas_header *hdr = &cmd->frame->hdr;
1295 
1296                 cmd->sync_cmd = MEGASAS_TRUE;
1297 
1298                 instance->func_ptr-> issue_cmd_in_poll_mode(instance, cmd);
1299 
1300                 pkt->pkt_reason              = CMD_CMPLT;
1301                 pkt->pkt_statistics  = 0;
1302                 pkt->pkt_state |= STATE_XFERRED_DATA | STATE_GOT_STATUS;
1303 
1304                 switch (hdr->cmd_status) {
1305                 case MFI_STAT_OK:
1306                         pkt->pkt_scbp[0] = STATUS_GOOD;
1307                         break;
1308 
1309                 case MFI_STAT_SCSI_DONE_WITH_ERROR:
1310 
1311                         pkt->pkt_reason      = CMD_CMPLT;
1312                         pkt->pkt_statistics = 0;
1313 
1314                         ((struct scsi_status *)pkt->pkt_scbp)->sts_chk = 1;
1315                         break;
1316 
1317                 case MFI_STAT_DEVICE_NOT_FOUND:
1318                         pkt->pkt_reason              = CMD_DEV_GONE;
1319                         pkt->pkt_statistics  = STAT_DISCON;
1320                         break;
1321 
1322                 default:
1323                         ((struct scsi_status *)pkt->pkt_scbp)->sts_busy = 1;
1324                 }
1325 
1326                 return_mfi_pkt(instance, cmd);
1327                 (void) megasas_common_check(instance, cmd);
1328 
1329                 scsi_hba_pkt_comp(pkt);
1330 
1331         }
1332 
1333         return (TRAN_ACCEPT);
1334 }
1335 
1336 /*
1337  * tran_abort - Abort any commands that are currently in transport
1338  * @ap:
1339  * @pkt:
1340  *
1341  * The tran_abort() entry point for a SCSI HBA driver is called to abort any
1342  * commands that are currently in transport for a particular target. This entry
1343  * point is called when a target driver calls scsi_abort(). The tran_abort()
1344  * entry point should attempt to abort the command denoted by the pkt
1345  * parameter. If the pkt parameter is NULL, tran_abort() should attempt to
1346  * abort all outstanding commands in the transport layer for the particular
1347  * target or logical unit.
1348  */
1349 /*ARGSUSED*/
1350 static int
1351 megasas_tran_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
1352 {
1353         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1354 
1355         /* aborting command not supported by H/W */
1356 
1357         return (DDI_FAILURE);
1358 }
1359 
1360 /*
1361  * tran_reset - reset either the SCSI bus or target
1362  * @ap:
1363  * @level:
1364  *
1365  * The tran_reset() entry point for a SCSI HBA driver is called to reset either
1366  * the SCSI bus or a particular SCSI target device. This entry point is called
1367  * when a target driver calls scsi_reset(). The tran_reset() entry point must
1368  * reset the SCSI bus if level is RESET_ALL. If level is RESET_TARGET, just the
1369  * particular target or logical unit must be reset.
1370  */
1371 /*ARGSUSED*/
1372 static int
1373 megasas_tran_reset(struct scsi_address *ap, int level)
1374 {
1375         struct megasas_instance *instance = ADDR2MEGA(ap);
1376 
1377         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1378 
1379         if (wait_for_outstanding(instance)) {
1380                 return (DDI_FAILURE);
1381         } else {
1382                 return (DDI_SUCCESS);
1383         }
1384 }
1385 
1386 /*
1387  * tran_bus_reset - reset the SCSI bus
1388  * @dip:
1389  * @level:
1390  *
1391  * The tran_bus_reset() vector in the scsi_hba_tran structure should be
1392  * initialized during the HBA driver's attach(). The vector should point to
1393  * an HBA entry point that is to be called when a user initiates a bus reset.
1394  * Implementation is hardware specific. If the HBA driver cannot reset the
1395  * SCSI bus without affecting the targets, the driver should fail RESET_BUS
1396  * or not initialize this vector.
1397  */
1398 /*ARGSUSED*/
1399 static int
1400 megasas_tran_bus_reset(dev_info_t *dip, int level)
1401 {
1402         int     instance_no = ddi_get_instance(dip);
1403 
1404         struct megasas_instance *instance = ddi_get_soft_state(megasas_state,
1405             instance_no);
1406 
1407         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1408 
1409         if (wait_for_outstanding(instance)) {
1410                 return (DDI_FAILURE);
1411         } else {
1412                 return (DDI_SUCCESS);
1413         }
1414 }
1415 
1416 /*
1417  * tran_getcap - get one of a set of SCSA-defined capabilities
1418  * @ap:
1419  * @cap:
1420  * @whom:
1421  *
1422  * The target driver can request the current setting of the capability for a
1423  * particular target by setting the whom parameter to nonzero. A whom value of
1424  * zero indicates a request for the current setting of the general capability
1425  * for the SCSI bus or for adapter hardware. The tran_getcap() should return -1
1426  * for undefined capabilities or the current value of the requested capability.
1427  */
1428 /*ARGSUSED*/
1429 static int
1430 megasas_tran_getcap(struct scsi_address *ap, char *cap, int whom)
1431 {
1432         int     rval = 0;
1433 
1434         struct megasas_instance *instance = ADDR2MEGA(ap);
1435 
1436         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1437 
1438         /* we do allow inquiring about capabilities for other targets */
1439         if (cap == NULL) {
1440                 return (-1);
1441         }
1442 
1443         switch (scsi_hba_lookup_capstr(cap)) {
1444                 case SCSI_CAP_DMA_MAX:
1445                         /* Limit to 16MB max transfer */
1446                         rval = megasas_max_cap_maxxfer;
1447                         break;
1448                 case SCSI_CAP_MSG_OUT:
1449                         rval = 1;
1450                         break;
1451                 case SCSI_CAP_DISCONNECT:
1452                         rval = 0;
1453                         break;
1454                 case SCSI_CAP_SYNCHRONOUS:
1455                         rval = 0;
1456                         break;
1457                 case SCSI_CAP_WIDE_XFER:
1458                         rval = 1;
1459                         break;
1460                 case SCSI_CAP_TAGGED_QING:
1461                         rval = 1;
1462                         break;
1463                 case SCSI_CAP_UNTAGGED_QING:
1464                         rval = 1;
1465                         break;
1466                 case SCSI_CAP_PARITY:
1467                         rval = 1;
1468                         break;
1469                 case SCSI_CAP_INITIATOR_ID:
1470                         rval = instance->init_id;
1471                         break;
1472                 case SCSI_CAP_ARQ:
1473                         rval = 1;
1474                         break;
1475                 case SCSI_CAP_LINKED_CMDS:
1476                         rval = 0;
1477                         break;
1478                 case SCSI_CAP_RESET_NOTIFICATION:
1479                         rval = 1;
1480                         break;
1481                 case SCSI_CAP_GEOMETRY:
1482                         rval = -1;
1483 
1484                         break;
1485                 default:
1486                         con_log(CL_DLEVEL2, (CE_NOTE, "Default cap coming 0x%x",
1487                             scsi_hba_lookup_capstr(cap)));
1488                         rval = -1;
1489                         break;
1490         }
1491 
1492         return (rval);
1493 }
1494 
1495 /*
1496  * tran_setcap - set one of a set of SCSA-defined capabilities
1497  * @ap:
1498  * @cap:
1499  * @value:
1500  * @whom:
1501  *
1502  * The target driver might request that the new value be set for a particular
1503  * target by setting the whom parameter to nonzero. A whom value of zero
1504  * means that request is to set the new value for the SCSI bus or for adapter
1505  * hardware in general.
1506  * The tran_setcap() should return the following values as appropriate:
1507  * - -1 for undefined capabilities
1508  * - 0 if the HBA driver cannot set the capability to the requested value
1509  * - 1 if the HBA driver is able to set the capability to the requested value
1510  */
1511 /*ARGSUSED*/
1512 static int
1513 megasas_tran_setcap(struct scsi_address *ap, char *cap, int value, int whom)
1514 {
1515         int             rval = 1;
1516 
1517         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1518 
1519         /* We don't allow setting capabilities for other targets */
1520         if (cap == NULL || whom == 0) {
1521                 return (-1);
1522         }
1523 
1524         switch (scsi_hba_lookup_capstr(cap)) {
1525                 case SCSI_CAP_DMA_MAX:
1526                 case SCSI_CAP_MSG_OUT:
1527                 case SCSI_CAP_PARITY:
1528                 case SCSI_CAP_LINKED_CMDS:
1529                 case SCSI_CAP_RESET_NOTIFICATION:
1530                 case SCSI_CAP_DISCONNECT:
1531                 case SCSI_CAP_SYNCHRONOUS:
1532                 case SCSI_CAP_UNTAGGED_QING:
1533                 case SCSI_CAP_WIDE_XFER:
1534                 case SCSI_CAP_INITIATOR_ID:
1535                 case SCSI_CAP_ARQ:
1536                         /*
1537                          * None of these are settable via
1538                          * the capability interface.
1539                          */
1540                         break;
1541                 case SCSI_CAP_TAGGED_QING:
1542                         rval = 1;
1543                         break;
1544                 case SCSI_CAP_SECTOR_SIZE:
1545                         rval = 1;
1546                         break;
1547 
1548                 case SCSI_CAP_TOTAL_SECTORS:
1549                         rval = 1;
1550                         break;
1551                 default:
1552                         rval = -1;
1553                         break;
1554         }
1555 
1556         return (rval);
1557 }
1558 
1559 /*
1560  * tran_destroy_pkt - deallocate scsi_pkt structure
1561  * @ap:
1562  * @pkt:
1563  *
1564  * The tran_destroy_pkt() entry point is the HBA driver function that
1565  * deallocates scsi_pkt structures. The tran_destroy_pkt() entry point is
1566  * called when the target driver calls scsi_destroy_pkt(). The
1567  * tran_destroy_pkt() entry point must free any DMA resources that have been
1568  * allocated for the packet. An implicit DMA synchronization occurs if the
1569  * DMA resources are freed and any cached data remains after the completion
1570  * of the transfer.
1571  */
1572 static void
1573 megasas_tran_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1574 {
1575         struct scsa_cmd *acmd = PKT2CMD(pkt);
1576 
1577         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1578 
1579         if (acmd->cmd_flags & CFLAG_DMAVALID) {
1580                 acmd->cmd_flags &= ~CFLAG_DMAVALID;
1581 
1582                 (void) ddi_dma_unbind_handle(acmd->cmd_dmahandle);
1583 
1584                 ddi_dma_free_handle(&acmd->cmd_dmahandle);
1585 
1586                 acmd->cmd_dmahandle = NULL;
1587         }
1588 
1589         /* free the pkt */
1590         scsi_hba_pkt_free(ap, pkt);
1591 }
1592 
1593 /*
1594  * tran_dmafree - deallocates DMA resources
1595  * @ap:
1596  * @pkt:
1597  *
1598  * The tran_dmafree() entry point deallocates DMAQ resources that have been
1599  * allocated for a scsi_pkt structure. The tran_dmafree() entry point is
1600  * called when the target driver calls scsi_dmafree(). The tran_dmafree() must
1601  * free only DMA resources allocated for a scsi_pkt structure, not the
1602  * scsi_pkt itself. When DMA resources are freed, a DMA synchronization is
1603  * implicitly performed.
1604  */
1605 /*ARGSUSED*/
1606 static void
1607 megasas_tran_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
1608 {
1609         register struct scsa_cmd *acmd = PKT2CMD(pkt);
1610 
1611         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1612 
1613         if (acmd->cmd_flags & CFLAG_DMAVALID) {
1614                 acmd->cmd_flags &= ~CFLAG_DMAVALID;
1615 
1616                 (void) ddi_dma_unbind_handle(acmd->cmd_dmahandle);
1617 
1618                 ddi_dma_free_handle(&acmd->cmd_dmahandle);
1619 
1620                 acmd->cmd_dmahandle = NULL;
1621         }
1622 }
1623 
1624 /*
1625  * tran_sync_pkt - synchronize the DMA object allocated
1626  * @ap:
1627  * @pkt:
1628  *
1629  * The tran_sync_pkt() entry point synchronizes the DMA object allocated for
1630  * the scsi_pkt structure before or after a DMA transfer. The tran_sync_pkt()
1631  * entry point is called when the target driver calls scsi_sync_pkt(). If the
1632  * data transfer direction is a DMA read from device to memory, tran_sync_pkt()
1633  * must synchronize the CPU's view of the data. If the data transfer direction
1634  * is a DMA write from memory to device, tran_sync_pkt() must synchronize the
1635  * device's view of the data.
1636  */
1637 /*ARGSUSED*/
1638 static void
1639 megasas_tran_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1640 {
1641         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1642 
1643         /*
1644          * following 'ddi_dma_sync()' API call
1645          * already called for each I/O in the ISR
1646          */
1647 #if 0
1648         int     i;
1649 
1650         register struct scsa_cmd        *acmd = PKT2CMD(pkt);
1651 
1652         if (acmd->cmd_flags & CFLAG_DMAVALID) {
1653                 (void) ddi_dma_sync(acmd->cmd_dmahandle, acmd->cmd_dma_offset,
1654                     acmd->cmd_dma_len, (acmd->cmd_flags & CFLAG_DMASEND) ?
1655                     DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
1656         }
1657 #endif
1658 }
1659 
1660 /*ARGSUSED*/
1661 static int
1662 megasas_tran_quiesce(dev_info_t *dip)
1663 {
1664         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1665 
1666         return (1);
1667 }
1668 
1669 /*ARGSUSED*/
1670 static int
1671 megasas_tran_unquiesce(dev_info_t *dip)
1672 {
1673         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1674 
1675         return (1);
1676 }
1677 
1678 /*
1679  * megasas_isr(caddr_t)
1680  *
1681  * The Interrupt Service Routine
1682  *
1683  * Collect status for all completed commands and do callback
1684  *
1685  */
1686 static uint_t
1687 megasas_isr(struct megasas_instance *instance)
1688 {
1689         int             need_softintr;
1690         uint32_t        producer;
1691         uint32_t        consumer;
1692         uint32_t        context;
1693 
1694         struct megasas_cmd      *cmd;
1695 
1696         con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1697 
1698         ASSERT(instance);
1699         if (!instance->func_ptr->intr_ack(instance)) {
1700                 return (DDI_INTR_UNCLAIMED);
1701         }
1702 
1703         (void) ddi_dma_sync(instance->mfi_internal_dma_obj.dma_handle,
1704             0, 0, DDI_DMA_SYNC_FORCPU);
1705 
1706         if (megasas_check_dma_handle(instance->mfi_internal_dma_obj.dma_handle)
1707             != DDI_SUCCESS) {
1708                 megasas_fm_ereport(instance, DDI_FM_DEVICE_NO_RESPONSE);
1709                 ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
1710                 return (DDI_INTR_UNCLAIMED);
1711         }
1712 
1713         producer = *instance->producer;
1714         consumer = *instance->consumer;
1715 
1716         con_log(CL_ANN1, (CE_CONT, " producer %x consumer %x ",
1717             producer, consumer));
1718 
1719         mutex_enter(&instance->completed_pool_mtx);
1720 
1721         while (consumer != producer) {
1722                 context = instance->reply_queue[consumer];
1723                 cmd = instance->cmd_list[context];
1724                 mlist_add_tail(&cmd->list, &instance->completed_pool_list);
1725 
1726                 consumer++;
1727                 if (consumer == (instance->max_fw_cmds + 1)) {
1728                         consumer = 0;
1729                 }
1730         }
1731 
1732         mutex_exit(&instance->completed_pool_mtx);
1733 
1734         *instance->consumer = consumer;
1735         (void) ddi_dma_sync(instance->mfi_internal_dma_obj.dma_handle,
1736             0, 0, DDI_DMA_SYNC_FORDEV);
1737 
1738         if (instance->softint_running) {
1739                 need_softintr = 0;
1740         } else {
1741                 need_softintr = 1;
1742         }
1743 
1744         if (instance->isr_level == HIGH_LEVEL_INTR) {
1745                 if (need_softintr) {
1746                         ddi_trigger_softintr(instance->soft_intr_id);
1747                 }
1748         } else {
1749                 /*
1750                  * Not a high-level interrupt, therefore call the soft level
1751                  * interrupt explicitly
1752                  */
1753                 (void) megasas_softintr(instance);
1754         }
1755 
1756         return (DDI_INTR_CLAIMED);
1757 }
1758 
1759 
1760 /*
1761  * ************************************************************************** *
1762  *                                                                            *
1763  *                                  libraries                                 *
1764  *                                                                            *
1765  * ************************************************************************** *
1766  */
1767 /*
1768  * get_mfi_pkt : Get a command from the free pool
1769  */
1770 static struct megasas_cmd *
1771 get_mfi_pkt(struct megasas_instance *instance)
1772 {
1773         mlist_t                 *head = &instance->cmd_pool_list;
1774         struct megasas_cmd      *cmd = NULL;
1775 
1776         mutex_enter(&instance->cmd_pool_mtx);
1777         ASSERT(mutex_owned(&instance->cmd_pool_mtx));
1778 
1779         if (!mlist_empty(head)) {
1780                 cmd = mlist_entry(head->next, struct megasas_cmd, list);
1781                 mlist_del_init(head->next);
1782         }
1783         if (cmd != NULL)
1784                 cmd->pkt = NULL;
1785         mutex_exit(&instance->cmd_pool_mtx);
1786 
1787         return (cmd);
1788 }
1789 
1790 /*
1791  * return_mfi_pkt : Return a cmd to free command pool
1792  */
1793 static void
1794 return_mfi_pkt(struct megasas_instance *instance, struct megasas_cmd *cmd)
1795 {
1796         mutex_enter(&instance->cmd_pool_mtx);
1797         ASSERT(mutex_owned(&instance->cmd_pool_mtx));
1798 
1799         mlist_add(&cmd->list, &instance->cmd_pool_list);
1800 
1801         mutex_exit(&instance->cmd_pool_mtx);
1802 }
1803 
1804 /*
1805  * destroy_mfi_frame_pool
1806  */
1807 static void
1808 destroy_mfi_frame_pool(struct megasas_instance *instance)
1809 {
1810         int             i;
1811         uint32_t        max_cmd = instance->max_fw_cmds;
1812 
1813         struct megasas_cmd      *cmd;
1814 
1815         /* return all frames to pool */
1816         for (i = 0; i < max_cmd; i++) {
1817 
1818                 cmd = instance->cmd_list[i];
1819 
1820                 if (cmd->frame_dma_obj_status == DMA_OBJ_ALLOCATED)
1821                         (void) mega_free_dma_obj(instance, cmd->frame_dma_obj);
1822 
1823                 cmd->frame_dma_obj_status  = DMA_OBJ_FREED;
1824         }
1825 
1826 }
1827 
1828 /*
1829  * create_mfi_frame_pool
1830  */
1831 static int
1832 create_mfi_frame_pool(struct megasas_instance *instance)
1833 {
1834         int             i = 0;
1835         int             cookie_cnt;
1836         uint16_t        max_cmd;
1837         uint16_t        sge_sz;
1838         uint32_t        sgl_sz;
1839         uint32_t        tot_frame_size;
1840 
1841         struct megasas_cmd      *cmd;
1842 
1843         max_cmd = instance->max_fw_cmds;
1844 
1845         sge_sz  = sizeof (struct megasas_sge64);
1846 
1847         /* calculated the number of 64byte frames required for SGL */
1848         sgl_sz          = sge_sz * instance->max_num_sge;
1849         tot_frame_size  = sgl_sz + MEGAMFI_FRAME_SIZE + SENSE_LENGTH;
1850 
1851         con_log(CL_DLEVEL3, (CE_NOTE, "create_mfi_frame_pool: "
1852             "sgl_sz %x tot_frame_size %x", sgl_sz, tot_frame_size));
1853 
1854         while (i < max_cmd) {
1855                 cmd = instance->cmd_list[i];
1856 
1857                 cmd->frame_dma_obj.size      = tot_frame_size;
1858                 cmd->frame_dma_obj.dma_attr = megasas_generic_dma_attr;
1859                 cmd->frame_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
1860                 cmd->frame_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
1861                 cmd->frame_dma_obj.dma_attr.dma_attr_sgllen = 1;
1862                 cmd->frame_dma_obj.dma_attr.dma_attr_align = 64;
1863 
1864 
1865                 cookie_cnt = mega_alloc_dma_obj(instance, &cmd->frame_dma_obj);
1866 
1867                 if (cookie_cnt == -1 || cookie_cnt > 1) {
1868                         con_log(CL_ANN, (CE_WARN,
1869                             "create_mfi_frame_pool: could not alloc."));
1870                         return (DDI_FAILURE);
1871                 }
1872 
1873                 bzero(cmd->frame_dma_obj.buffer, tot_frame_size);
1874 
1875                 cmd->frame_dma_obj_status = DMA_OBJ_ALLOCATED;
1876                 cmd->frame = (union megasas_frame *)cmd->frame_dma_obj.buffer;
1877                 cmd->frame_phys_addr =
1878                     cmd->frame_dma_obj.dma_cookie[0].dmac_address;
1879 
1880                 cmd->sense = (uint8_t *)(((unsigned long)
1881                     cmd->frame_dma_obj.buffer) +
1882                     tot_frame_size - SENSE_LENGTH);
1883                 cmd->sense_phys_addr =
1884                     cmd->frame_dma_obj.dma_cookie[0].dmac_address +
1885                     tot_frame_size - SENSE_LENGTH;
1886 
1887                 if (!cmd->frame || !cmd->sense) {
1888                         con_log(CL_ANN, (CE_NOTE,
1889                             "megasas: pci_pool_alloc failed \n"));
1890 
1891                         return (-ENOMEM);
1892                 }
1893 
1894                 cmd->frame->io.context = cmd->index;
1895                 i++;
1896 
1897                 con_log(CL_DLEVEL3, (CE_NOTE, "[%x]-%x",
1898                     cmd->frame->io.context, cmd->frame_phys_addr));
1899         }
1900 
1901         return (DDI_SUCCESS);
1902 }
1903 
1904 /*
1905  * free_additional_dma_buffer
1906  */
1907 static void
1908 free_additional_dma_buffer(struct megasas_instance *instance)
1909 {
1910         if (instance->mfi_internal_dma_obj.status == DMA_OBJ_ALLOCATED) {
1911                 (void) mega_free_dma_obj(instance,
1912                     instance->mfi_internal_dma_obj);
1913                 instance->mfi_internal_dma_obj.status = DMA_OBJ_FREED;
1914         }
1915 
1916         if (instance->mfi_evt_detail_obj.status == DMA_OBJ_ALLOCATED) {
1917                 (void) mega_free_dma_obj(instance,
1918                     instance->mfi_evt_detail_obj);
1919                 instance->mfi_evt_detail_obj.status = DMA_OBJ_FREED;
1920         }
1921 }
1922 
1923 /*
1924  * alloc_additional_dma_buffer
1925  */
1926 static int
1927 alloc_additional_dma_buffer(struct megasas_instance *instance)
1928 {
1929         uint32_t        reply_q_sz;
1930         uint32_t        internal_buf_size = PAGESIZE*2;
1931 
1932         /* max cmds plus 1 + producer & consumer */
1933         reply_q_sz = sizeof (uint32_t) * (instance->max_fw_cmds + 1 + 2);
1934 
1935         instance->mfi_internal_dma_obj.size = internal_buf_size;
1936         instance->mfi_internal_dma_obj.dma_attr      = megasas_generic_dma_attr;
1937         instance->mfi_internal_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
1938         instance->mfi_internal_dma_obj.dma_attr.dma_attr_count_max =
1939             0xFFFFFFFFU;
1940         instance->mfi_internal_dma_obj.dma_attr.dma_attr_sgllen      = 1;
1941 
1942         if (mega_alloc_dma_obj(instance, &instance->mfi_internal_dma_obj)
1943             != 1) {
1944                 con_log(CL_ANN, (CE_WARN, "megaraid: could not alloc reply Q"));
1945                 return (DDI_FAILURE);
1946         }
1947 
1948         bzero(instance->mfi_internal_dma_obj.buffer, internal_buf_size);
1949 
1950         instance->mfi_internal_dma_obj.status |= DMA_OBJ_ALLOCATED;
1951 
1952         instance->producer = (uint32_t *)((unsigned long)
1953             instance->mfi_internal_dma_obj.buffer);
1954         instance->consumer = (uint32_t *)((unsigned long)
1955             instance->mfi_internal_dma_obj.buffer + 4);
1956         instance->reply_queue = (uint32_t *)((unsigned long)
1957             instance->mfi_internal_dma_obj.buffer + 8);
1958         instance->internal_buf = (caddr_t)(((unsigned long)
1959             instance->mfi_internal_dma_obj.buffer) + reply_q_sz + 8);
1960         instance->internal_buf_dmac_add =
1961             instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address +
1962             reply_q_sz;
1963         instance->internal_buf_size = internal_buf_size -
1964             (reply_q_sz + 8);
1965 
1966         /* allocate evt_detail */
1967         instance->mfi_evt_detail_obj.size = sizeof (struct megasas_evt_detail);
1968         instance->mfi_evt_detail_obj.dma_attr = megasas_generic_dma_attr;
1969         instance->mfi_evt_detail_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
1970         instance->mfi_evt_detail_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
1971         instance->mfi_evt_detail_obj.dma_attr.dma_attr_sgllen = 1;
1972         instance->mfi_evt_detail_obj.dma_attr.dma_attr_align = 1;
1973 
1974         if (mega_alloc_dma_obj(instance, &instance->mfi_evt_detail_obj) != 1) {
1975                 con_log(CL_ANN, (CE_WARN, "alloc_additional_dma_buffer: "
1976                     "could not data transfer buffer alloc."));
1977                 return (DDI_FAILURE);
1978         }
1979 
1980         bzero(instance->mfi_evt_detail_obj.buffer,
1981             sizeof (struct megasas_evt_detail));
1982 
1983         instance->mfi_evt_detail_obj.status |= DMA_OBJ_ALLOCATED;
1984 
1985         return (DDI_SUCCESS);
1986 }
1987 
1988 /*
1989  * free_space_for_mfi
1990  */
1991 static void
1992 free_space_for_mfi(struct megasas_instance *instance)
1993 {
1994         int             i;
1995         uint32_t        max_cmd = instance->max_fw_cmds;
1996 
1997         /* already freed */
1998         if (instance->cmd_list == NULL) {
1999                 return;
2000         }
2001 
2002         free_additional_dma_buffer(instance);
2003 
2004         /* first free the MFI frame pool */
2005         destroy_mfi_frame_pool(instance);
2006 
2007         /* free all the commands in the cmd_list */
2008         for (i = 0; i < instance->max_fw_cmds; i++) {
2009                 kmem_free(instance->cmd_list[i],
2010                     sizeof (struct megasas_cmd));
2011 
2012                 instance->cmd_list[i] = NULL;
2013         }
2014 
2015         /* free the cmd_list buffer itself */
2016         kmem_free(instance->cmd_list,
2017             sizeof (struct megasas_cmd *) * max_cmd);
2018 
2019         instance->cmd_list = NULL;
2020 
2021         INIT_LIST_HEAD(&instance->cmd_pool_list);
2022 }
2023 
2024 /*
2025  * alloc_space_for_mfi
2026  */
2027 static int
2028 alloc_space_for_mfi(struct megasas_instance *instance)
2029 {
2030         int             i;
2031         uint32_t        max_cmd;
2032         size_t          sz;
2033 
2034         struct megasas_cmd      *cmd;
2035 
2036         max_cmd = instance->max_fw_cmds;
2037         sz = sizeof (struct megasas_cmd *) * max_cmd;
2038 
2039         /*
2040          * instance->cmd_list is an array of struct megasas_cmd pointers.
2041          * Allocate the dynamic array first and then allocate individual
2042          * commands.
2043          */
2044         instance->cmd_list = kmem_zalloc(sz, KM_SLEEP);
2045         ASSERT(instance->cmd_list);
2046 
2047         for (i = 0; i < max_cmd; i++) {
2048                 instance->cmd_list[i] = kmem_zalloc(sizeof (struct megasas_cmd),
2049                     KM_SLEEP);
2050                 ASSERT(instance->cmd_list[i]);
2051         }
2052 
2053         INIT_LIST_HEAD(&instance->cmd_pool_list);
2054 
2055         /* add all the commands to command pool (instance->cmd_pool) */
2056         for (i = 0; i < max_cmd; i++) {
2057                 cmd             = instance->cmd_list[i];
2058                 cmd->index   = i;
2059 
2060                 mlist_add_tail(&cmd->list, &instance->cmd_pool_list);
2061         }
2062 
2063         /* create a frame pool and assign one frame to each cmd */
2064         if (create_mfi_frame_pool(instance)) {
2065                 con_log(CL_ANN, (CE_NOTE, "error creating frame DMA pool\n"));
2066                 return (DDI_FAILURE);
2067         }
2068 
2069         /* create a frame pool and assign one frame to each cmd */
2070         if (alloc_additional_dma_buffer(instance)) {
2071                 con_log(CL_ANN, (CE_NOTE, "error creating frame DMA pool\n"));
2072                 return (DDI_FAILURE);
2073         }
2074 
2075         return (DDI_SUCCESS);
2076 }
2077 
2078 /*
2079  * get_ctrl_info
2080  */
2081 static int
2082 get_ctrl_info(struct megasas_instance *instance,
2083     struct megasas_ctrl_info *ctrl_info)
2084 {
2085         int     ret = 0;
2086 
2087         struct megasas_cmd              *cmd;
2088         struct megasas_dcmd_frame       *dcmd;
2089         struct megasas_ctrl_info        *ci;
2090 
2091         cmd = get_mfi_pkt(instance);
2092 
2093         if (!cmd) {
2094                 con_log(CL_ANN, (CE_WARN,
2095                     "Failed to get a cmd for ctrl info\n"));
2096                 return (DDI_FAILURE);
2097         }
2098 
2099         dcmd = &cmd->frame->dcmd;
2100 
2101         ci = (struct megasas_ctrl_info *)instance->internal_buf;
2102 
2103         if (!ci) {
2104                 con_log(CL_ANN, (CE_WARN,
2105                     "Failed to alloc mem for ctrl info\n"));
2106                 return_mfi_pkt(instance, cmd);
2107                 return (DDI_FAILURE);
2108         }
2109 
2110         (void) memset(ci, 0, sizeof (struct megasas_ctrl_info));
2111 
2112         /* for( i = 0; i < DCMD_MBOX_SZ; i++ ) dcmd->mbox.b[i] = 0; */
2113         (void) memset(dcmd->mbox.b, 0, DCMD_MBOX_SZ);
2114 
2115         dcmd->cmd                    = MFI_CMD_OP_DCMD;
2116         dcmd->cmd_status             = MFI_CMD_STATUS_POLL_MODE;
2117         dcmd->sge_count                      = 1;
2118         dcmd->flags                  = MFI_FRAME_DIR_READ;
2119         dcmd->timeout                        = 0;
2120         dcmd->data_xfer_len          = sizeof (struct megasas_ctrl_info);
2121         dcmd->opcode                 = MR_DCMD_CTRL_GET_INFO;
2122         dcmd->sgl.sge32[0].phys_addr = instance->internal_buf_dmac_add;
2123         dcmd->sgl.sge32[0].length    = sizeof (struct megasas_ctrl_info);
2124 
2125         cmd->frame_count = 1;
2126 
2127         if (!instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd)) {
2128                 ret = 0;
2129                 (void) memcpy(ctrl_info, ci, sizeof (struct megasas_ctrl_info));
2130         } else {
2131                 con_log(CL_ANN, (CE_WARN, "get_ctrl_info: Ctrl info failed\n"));
2132                 ret = -1;
2133         }
2134 
2135         return_mfi_pkt(instance, cmd);
2136         if (megasas_common_check(instance, cmd) != DDI_SUCCESS) {
2137                 ret = -1;
2138         }
2139 
2140         return (ret);
2141 }
2142 
2143 /*
2144  * abort_aen_cmd
2145  */
2146 static int
2147 abort_aen_cmd(struct megasas_instance *instance,
2148     struct megasas_cmd *cmd_to_abort)
2149 {
2150         int     ret = 0;
2151 
2152         struct megasas_cmd              *cmd;
2153         struct megasas_abort_frame      *abort_fr;
2154 
2155         cmd = get_mfi_pkt(instance);
2156 
2157         if (!cmd) {
2158                 con_log(CL_ANN, (CE_WARN,
2159                     "Failed to get a cmd for ctrl info\n"));
2160                 return (DDI_FAILURE);
2161         }
2162 
2163         abort_fr = &cmd->frame->abort;
2164 
2165         /* prepare and issue the abort frame */
2166         abort_fr->cmd = MFI_CMD_OP_ABORT;
2167         abort_fr->cmd_status = MFI_CMD_STATUS_SYNC_MODE;
2168         abort_fr->flags = 0;
2169         abort_fr->abort_context = cmd_to_abort->index;
2170         abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr;
2171         abort_fr->abort_mfi_phys_addr_hi = 0;
2172 
2173         instance->aen_cmd->abort_aen = 1;
2174 
2175         cmd->sync_cmd = MEGASAS_TRUE;
2176         cmd->frame_count = 1;
2177 
2178         if (instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd)) {
2179                 con_log(CL_ANN, (CE_WARN,
2180                     "abort_aen_cmd: issue_cmd_in_sync_mode failed\n"));
2181                 ret = -1;
2182         } else {
2183                 ret = 0;
2184         }
2185 
2186         instance->aen_cmd->abort_aen = 1;
2187         instance->aen_cmd = 0;
2188 
2189         return_mfi_pkt(instance, cmd);
2190         (void) megasas_common_check(instance, cmd);
2191 
2192         return (ret);
2193 }
2194 
2195 /*
2196  * init_mfi
2197  */
2198 static int
2199 init_mfi(struct megasas_instance *instance)
2200 {
2201         off_t                           reglength;
2202         struct megasas_cmd              *cmd;
2203         struct megasas_ctrl_info        ctrl_info;
2204         struct megasas_init_frame       *init_frame;
2205         struct megasas_init_queue_info  *initq_info;
2206 
2207         if ((ddi_dev_regsize(instance->dip, REGISTER_SET_IO, &reglength)
2208             != DDI_SUCCESS) || reglength < MINIMUM_MFI_MEM_SZ) {
2209                 return (DDI_FAILURE);
2210         }
2211 
2212         if (reglength > DEFAULT_MFI_MEM_SZ) {
2213                 reglength = DEFAULT_MFI_MEM_SZ;
2214                 con_log(CL_DLEVEL1, (CE_NOTE,
2215                     "mega: register length to map is 0x%lx bytes", reglength));
2216         }
2217 
2218         if (ddi_regs_map_setup(instance->dip, REGISTER_SET_IO,
2219             &instance->regmap, 0, reglength, &endian_attr,
2220             &instance->regmap_handle) != DDI_SUCCESS) {
2221                 con_log(CL_ANN, (CE_NOTE,
2222                     "megaraid: couldn't map control registers"));
2223 
2224                 goto fail_mfi_reg_setup;
2225         }
2226 
2227         /* we expect the FW state to be READY */
2228         if (mfi_state_transition_to_ready(instance)) {
2229                 con_log(CL_ANN, (CE_WARN, "megaraid: F/W is not ready"));
2230                 goto fail_ready_state;
2231         }
2232 
2233         /* get various operational parameters from status register */
2234         instance->max_num_sge =
2235             (instance->func_ptr->read_fw_status_reg(instance) &
2236             0xFF0000) >> 0x10;
2237         /*
2238          * Reduce the max supported cmds by 1. This is to ensure that the
2239          * reply_q_sz (1 more than the max cmd that driver may send)
2240          * does not exceed max cmds that the FW can support
2241          */
2242         instance->max_fw_cmds =
2243             instance->func_ptr->read_fw_status_reg(instance) & 0xFFFF;
2244         instance->max_fw_cmds = instance->max_fw_cmds - 1;
2245 
2246         instance->max_num_sge =
2247             (instance->max_num_sge > MEGASAS_MAX_SGE_CNT) ?
2248             MEGASAS_MAX_SGE_CNT : instance->max_num_sge;
2249 
2250         /* create a pool of commands */
2251         if (alloc_space_for_mfi(instance))
2252                 goto fail_alloc_fw_space;
2253 
2254         /* disable interrupt for initial preparation */
2255         instance->func_ptr->disable_intr(instance);
2256 
2257         /*
2258          * Prepare a init frame. Note the init frame points to queue info
2259          * structure. Each frame has SGL allocated after first 64 bytes. For
2260          * this frame - since we don't need any SGL - we use SGL's space as
2261          * queue info structure
2262          */
2263         cmd = get_mfi_pkt(instance);
2264 
2265         init_frame = (struct megasas_init_frame *)cmd->frame;
2266         initq_info = (struct megasas_init_queue_info *)
2267             ((unsigned long)init_frame + 64);
2268 
2269         (void) memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
2270         (void) memset(initq_info, 0, sizeof (struct megasas_init_queue_info));
2271 
2272         initq_info->init_flags = 0;
2273 
2274         initq_info->reply_queue_entries      = instance->max_fw_cmds + 1;
2275 
2276         initq_info->producer_index_phys_addr_hi      = 0;
2277         initq_info->producer_index_phys_addr_lo =
2278             instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address;
2279 
2280         initq_info->consumer_index_phys_addr_hi = 0;
2281         initq_info->consumer_index_phys_addr_lo =
2282             instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address + 4;
2283 
2284         initq_info->reply_queue_start_phys_addr_hi = 0;
2285         initq_info->reply_queue_start_phys_addr_lo =
2286             instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address + 8;
2287 
2288         init_frame->cmd                              = MFI_CMD_OP_INIT;
2289         init_frame->cmd_status                       = MFI_CMD_STATUS_POLL_MODE;
2290         init_frame->flags                    = 0;
2291         init_frame->queue_info_new_phys_addr_lo      =
2292             cmd->frame_phys_addr + 64;
2293         init_frame->queue_info_new_phys_addr_hi      = 0;
2294 
2295         init_frame->data_xfer_len = sizeof (struct megasas_init_queue_info);
2296 
2297         cmd->frame_count = 1;
2298 
2299         /* issue the init frame in polled mode */
2300         if (instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd)) {
2301                 con_log(CL_ANN, (CE_WARN, "failed to init firmware"));
2302                 goto fail_fw_init;
2303         }
2304 
2305         return_mfi_pkt(instance, cmd);
2306         if (megasas_common_check(instance, cmd) != DDI_SUCCESS) {
2307                 goto fail_fw_init;
2308         }
2309 
2310         /* gather misc FW related information */
2311         if (!get_ctrl_info(instance, &ctrl_info)) {
2312                 instance->max_sectors_per_req = ctrl_info.max_request_size;
2313                 con_log(CL_ANN1, (CE_NOTE, "product name %s ld present %d",
2314                     ctrl_info.product_name, ctrl_info.ld_present_count));
2315         } else {
2316                 instance->max_sectors_per_req = instance->max_num_sge *
2317                     PAGESIZE / 512;
2318         }
2319 
2320         if (megasas_check_acc_handle(instance->regmap_handle) != DDI_SUCCESS) {
2321                 goto fail_fw_init;
2322         }
2323 
2324         return (0);
2325 
2326 fail_fw_init:
2327 fail_alloc_fw_space:
2328 
2329         free_space_for_mfi(instance);
2330 
2331 fail_ready_state:
2332         ddi_regs_map_free(&instance->regmap_handle);
2333 
2334 fail_mfi_reg_setup:
2335         return (DDI_FAILURE);
2336 }
2337 
2338 /*
2339  * mfi_state_transition_to_ready        : Move the FW to READY state
2340  *
2341  * @reg_set                     : MFI register set
2342  */
2343 static int
2344 mfi_state_transition_to_ready(struct megasas_instance *instance)
2345 {
2346         int             i;
2347         uint8_t         max_wait;
2348         uint32_t        fw_ctrl;
2349         uint32_t        fw_state;
2350         uint32_t        cur_state;
2351 
2352         fw_state =
2353             instance->func_ptr->read_fw_status_reg(instance) & MFI_STATE_MASK;
2354         con_log(CL_ANN1, (CE_NOTE,
2355             "mfi_state_transition_to_ready:FW state = 0x%x", fw_state));
2356 
2357         while (fw_state != MFI_STATE_READY) {
2358                 con_log(CL_ANN, (CE_NOTE,
2359                     "mfi_state_transition_to_ready:FW state%x", fw_state));
2360 
2361                 switch (fw_state) {
2362                 case MFI_STATE_FAULT:
2363                         con_log(CL_ANN, (CE_NOTE,
2364                             "megasas: FW in FAULT state!!"));
2365 
2366                         return (-ENODEV);
2367                 case MFI_STATE_WAIT_HANDSHAKE:
2368                         /* set the CLR bit in IMR0 */
2369                         con_log(CL_ANN, (CE_NOTE,
2370                             "megasas: FW waiting for HANDSHAKE"));
2371                         /*
2372                          * PCI_Hot Plug: MFI F/W requires
2373                          * (MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG)
2374                          * to be set
2375                          */
2376                         /* WR_IB_MSG_0(MFI_INIT_CLEAR_HANDSHAKE, instance); */
2377                         WR_IB_DOORBELL(MFI_INIT_CLEAR_HANDSHAKE |
2378                             MFI_INIT_HOTPLUG, instance);
2379 
2380                         max_wait        = 2;
2381                         cur_state       = MFI_STATE_WAIT_HANDSHAKE;
2382                         break;
2383                 case MFI_STATE_BOOT_MESSAGE_PENDING:
2384                         /* set the CLR bit in IMR0 */
2385                         con_log(CL_ANN, (CE_NOTE,
2386                             "megasas: FW state boot message pending"));
2387                         /*
2388                          * PCI_Hot Plug: MFI F/W requires
2389                          * (MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG)
2390                          * to be set
2391                          */
2392                         WR_IB_DOORBELL(MFI_INIT_HOTPLUG, instance);
2393 
2394                         max_wait        = 10;
2395                         cur_state       = MFI_STATE_BOOT_MESSAGE_PENDING;
2396                         break;
2397                 case MFI_STATE_OPERATIONAL:
2398                         /* bring it to READY state; assuming max wait 2 secs */
2399                         instance->func_ptr->disable_intr(instance);
2400                         con_log(CL_ANN1, (CE_NOTE,
2401                             "megasas: FW in OPERATIONAL state"));
2402                         /*
2403                          * PCI_Hot Plug: MFI F/W requires
2404                          * (MFI_INIT_READY | MFI_INIT_MFIMODE | MFI_INIT_ABORT)
2405                          * to be set
2406                          */
2407                         /* WR_IB_DOORBELL(MFI_INIT_READY, instance); */
2408                         WR_IB_DOORBELL(MFI_RESET_FLAGS, instance);
2409 
2410                         max_wait        = 10;
2411                         cur_state       = MFI_STATE_OPERATIONAL;
2412                         break;
2413                 case MFI_STATE_UNDEFINED:
2414                         /* this state should not last for more than 2 seconds */
2415                         con_log(CL_ANN, (CE_NOTE, "FW state undefined\n"));
2416 
2417                         max_wait        = 2;
2418                         cur_state       = MFI_STATE_UNDEFINED;
2419                         break;
2420                 case MFI_STATE_BB_INIT:
2421                         max_wait        = 2;
2422                         cur_state       = MFI_STATE_BB_INIT;
2423                         break;
2424                 case MFI_STATE_FW_INIT:
2425                         max_wait        = 2;
2426                         cur_state       = MFI_STATE_FW_INIT;
2427                         break;
2428                 case MFI_STATE_DEVICE_SCAN:
2429                         max_wait        = 10;
2430                         cur_state       = MFI_STATE_DEVICE_SCAN;
2431                         break;
2432                 default:
2433                         con_log(CL_ANN, (CE_NOTE,
2434                             "megasas: Unknown state 0x%x\n", fw_state));
2435                         return (-ENODEV);
2436                 }
2437 
2438                 /* the cur_state should not last for more than max_wait secs */
2439                 for (i = 0; i < (max_wait * MILLISEC); i++) {
2440                         /* fw_state = RD_OB_MSG_0(instance) & MFI_STATE_MASK; */
2441                         fw_state =
2442                             instance->func_ptr->read_fw_status_reg(instance) &
2443                             MFI_STATE_MASK;
2444 
2445                         if (fw_state == cur_state) {
2446                                 delay(1 * drv_usectohz(MILLISEC));
2447                         } else {
2448                                 break;
2449                         }
2450                 }
2451 
2452                 /* return error if fw_state hasn't changed after max_wait */
2453                 if (fw_state == cur_state) {
2454                         con_log(CL_ANN, (CE_NOTE,
2455                             "FW state hasn't changed in %d secs\n", max_wait));
2456                         return (-ENODEV);
2457                 }
2458         };
2459 
2460         fw_ctrl = RD_IB_DOORBELL(instance);
2461 
2462         con_log(CL_ANN1, (CE_NOTE,
2463             "mfi_state_transition_to_ready:FW ctrl = 0x%x", fw_ctrl));
2464 
2465         /*
2466          * Write 0xF to the doorbell register to do the following.
2467          * - Abort all outstanding commands (bit 0).
2468          * - Transition from OPERATIONAL to READY state (bit 1).
2469          * - Discard (possible) low MFA posted in 64-bit mode (bit-2).
2470          * - Set to release FW to continue running (i.e. BIOS handshake
2471          *   (bit 3).
2472          */
2473         WR_IB_DOORBELL(0xF, instance);
2474 
2475         if (megasas_check_acc_handle(instance->regmap_handle) != DDI_SUCCESS) {
2476                 return (-ENODEV);
2477         }
2478         return (0);
2479 }
2480 
2481 /*
2482  * get_seq_num
2483  */
2484 static int
2485 get_seq_num(struct megasas_instance *instance,
2486     struct megasas_evt_log_info *eli)
2487 {
2488         int     ret = 0;
2489 
2490         dma_obj_t                       dcmd_dma_obj;
2491         struct megasas_cmd              *cmd;
2492         struct megasas_dcmd_frame       *dcmd;
2493 
2494         cmd = get_mfi_pkt(instance);
2495 
2496         if (!cmd) {
2497                 cmn_err(CE_WARN, "megasas: failed to get a cmd\n");
2498                 return (-ENOMEM);
2499         }
2500 
2501         dcmd    = &cmd->frame->dcmd;
2502 
2503         /* allocate the data transfer buffer */
2504         dcmd_dma_obj.size = sizeof (struct megasas_evt_log_info);
2505         dcmd_dma_obj.dma_attr = megasas_generic_dma_attr;
2506         dcmd_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
2507         dcmd_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
2508         dcmd_dma_obj.dma_attr.dma_attr_sgllen = 1;
2509         dcmd_dma_obj.dma_attr.dma_attr_align = 1;
2510 
2511         if (mega_alloc_dma_obj(instance, &dcmd_dma_obj) != 1) {
2512                 con_log(CL_ANN, (CE_WARN,
2513                     "get_seq_num: could not data transfer buffer alloc."));
2514                 return (DDI_FAILURE);
2515         }
2516 
2517         (void) memset(dcmd_dma_obj.buffer, 0,
2518             sizeof (struct megasas_evt_log_info));
2519 
2520         (void) memset(dcmd->mbox.b, 0, DCMD_MBOX_SZ);
2521 
2522         dcmd->cmd = MFI_CMD_OP_DCMD;
2523         dcmd->cmd_status = 0;
2524         dcmd->sge_count      = 1;
2525         dcmd->flags = MFI_FRAME_DIR_READ;
2526         dcmd->timeout = 0;
2527         dcmd->data_xfer_len = sizeof (struct megasas_evt_log_info);
2528         dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO;
2529         dcmd->sgl.sge32[0].length = sizeof (struct megasas_evt_log_info);
2530         dcmd->sgl.sge32[0].phys_addr = dcmd_dma_obj.dma_cookie[0].dmac_address;
2531 
2532         cmd->sync_cmd = MEGASAS_TRUE;
2533         cmd->frame_count = 1;
2534 
2535         if (instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd)) {
2536                 cmn_err(CE_WARN, "get_seq_num: "
2537                     "failed to issue MR_DCMD_CTRL_EVENT_GET_INFO\n");
2538                 ret = -1;
2539         } else {
2540                 /* copy the data back into callers buffer */
2541                 bcopy(dcmd_dma_obj.buffer, eli,
2542                     sizeof (struct megasas_evt_log_info));
2543                 ret = 0;
2544         }
2545 
2546         if (mega_free_dma_obj(instance, dcmd_dma_obj) != DDI_SUCCESS)
2547                 ret = -1;
2548 
2549         return_mfi_pkt(instance, cmd);
2550         if (megasas_common_check(instance, cmd) != DDI_SUCCESS) {
2551                 ret = -1;
2552         }
2553         return (ret);
2554 }
2555 
2556 /*
2557  * start_mfi_aen
2558  */
2559 static int
2560 start_mfi_aen(struct megasas_instance *instance)
2561 {
2562         int     ret = 0;
2563 
2564         struct megasas_evt_log_info     eli;
2565         union megasas_evt_class_locale  class_locale;
2566 
2567         /* get the latest sequence number from FW */
2568         (void) memset(&eli, 0, sizeof (struct megasas_evt_log_info));
2569 
2570         if (get_seq_num(instance, &eli)) {
2571                 cmn_err(CE_WARN, "start_mfi_aen: failed to get seq num\n");
2572                 return (-1);
2573         }
2574 
2575         /* register AEN with FW for latest sequence number plus 1 */
2576         class_locale.members.reserved   = 0;
2577         class_locale.members.locale     = MR_EVT_LOCALE_ALL;
2578         class_locale.members.class      = MR_EVT_CLASS_CRITICAL;
2579 
2580         ret = register_mfi_aen(instance, eli.newest_seq_num + 1,
2581             class_locale.word);
2582 
2583         if (ret) {
2584                 cmn_err(CE_WARN, "start_mfi_aen: aen registration failed\n");
2585                 return (-1);
2586         }
2587 
2588         return (ret);
2589 }
2590 
2591 /*
2592  * flush_cache
2593  */
2594 static void
2595 flush_cache(struct megasas_instance *instance)
2596 {
2597         struct megasas_cmd              *cmd;
2598         struct megasas_dcmd_frame       *dcmd;
2599 
2600         if (!(cmd = get_mfi_pkt(instance)))
2601                 return;
2602 
2603         dcmd = &cmd->frame->dcmd;
2604 
2605         (void) memset(dcmd->mbox.b, 0, DCMD_MBOX_SZ);
2606 
2607         dcmd->cmd            = MFI_CMD_OP_DCMD;
2608         dcmd->cmd_status     = 0x0;
2609         dcmd->sge_count              = 0;
2610         dcmd->flags          = MFI_FRAME_DIR_NONE;
2611         dcmd->timeout                = 0;
2612         dcmd->data_xfer_len  = 0;
2613         dcmd->opcode         = MR_DCMD_CTRL_CACHE_FLUSH;
2614         dcmd->mbox.b[0]              = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
2615 
2616         cmd->frame_count = 1;
2617 
2618         if (instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd)) {
2619                 cmn_err(CE_WARN,
2620                     "flush_cache: failed to issue MFI_DCMD_CTRL_CACHE_FLUSH\n");
2621         }
2622         con_log(CL_DLEVEL1, (CE_NOTE, "done"));
2623         return_mfi_pkt(instance, cmd);
2624         (void) megasas_common_check(instance, cmd);
2625 }
2626 
2627 /*
2628  * service_mfi_aen-     Completes an AEN command
2629  * @instance:                   Adapter soft state
2630  * @cmd:                        Command to be completed
2631  *
2632  */
2633 static void
2634 service_mfi_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
2635 {
2636         uint32_t        seq_num;
2637         struct megasas_evt_detail *evt_detail =
2638             (struct megasas_evt_detail *)instance->mfi_evt_detail_obj.buffer;
2639 
2640         cmd->cmd_status = cmd->frame->io.cmd_status;
2641 
2642         if (cmd->cmd_status == ENODATA) {
2643                 cmd->cmd_status = 0;
2644         }
2645 
2646         /*
2647          * log the MFI AEN event to the sysevent queue so that
2648          * application will get noticed
2649          */
2650         if (ddi_log_sysevent(instance->dip, DDI_VENDOR_LSI, "LSIMEGA", "SAS",
2651             NULL, NULL, DDI_NOSLEEP) != DDI_SUCCESS) {
2652                 int     instance_no = ddi_get_instance(instance->dip);
2653                 con_log(CL_ANN, (CE_WARN,
2654                     "mega%d: Failed to log AEN event", instance_no));
2655         }
2656 
2657         /* get copy of seq_num and class/locale for re-registration */
2658         seq_num = evt_detail->seq_num;
2659         seq_num++;
2660         (void) memset(instance->mfi_evt_detail_obj.buffer, 0,
2661             sizeof (struct megasas_evt_detail));
2662 
2663         cmd->frame->dcmd.cmd_status = 0x0;
2664         cmd->frame->dcmd.mbox.w[0] = seq_num;
2665 
2666         instance->aen_seq_num = seq_num;
2667 
2668         cmd->frame_count = 1;
2669 
2670         /* Issue the aen registration frame */
2671         instance->func_ptr->issue_cmd(cmd, instance);
2672 }
2673 
2674 /*
2675  * complete_cmd_in_sync_mode -  Completes an internal command
2676  * @instance:                   Adapter soft state
2677  * @cmd:                        Command to be completed
2678  *
2679  * The issue_cmd_in_sync_mode() function waits for a command to complete
2680  * after it issues a command. This function wakes up that waiting routine by
2681  * calling wake_up() on the wait queue.
2682  */
2683 static void
2684 complete_cmd_in_sync_mode(struct megasas_instance *instance,
2685     struct megasas_cmd *cmd)
2686 {
2687         cmd->cmd_status = cmd->frame->io.cmd_status;
2688 
2689         cmd->sync_cmd = MEGASAS_FALSE;
2690 
2691         if (cmd->cmd_status == ENODATA) {
2692                 cmd->cmd_status = 0;
2693         }
2694 
2695         cv_broadcast(&instance->int_cmd_cv);
2696 }
2697 
2698 /*
2699  * megasas_softintr - The Software ISR
2700  * @param arg   : HBA soft state
2701  *
2702  * called from high-level interrupt if hi-level interrupt are not there,
2703  * otherwise triggered as a soft interrupt
2704  */
2705 static uint_t
2706 megasas_softintr(struct megasas_instance *instance)
2707 {
2708         struct scsi_pkt         *pkt;
2709         struct scsa_cmd         *acmd;
2710         struct megasas_cmd      *cmd;
2711         struct mlist_head       *pos, *next;
2712         mlist_t                 process_list;
2713         struct megasas_header   *hdr;
2714         struct scsi_arq_status  *arqstat;
2715 
2716         con_log(CL_ANN1, (CE_CONT, "megasas_softintr called"));
2717 
2718         ASSERT(instance);
2719         mutex_enter(&instance->completed_pool_mtx);
2720 
2721         if (mlist_empty(&instance->completed_pool_list)) {
2722                 mutex_exit(&instance->completed_pool_mtx);
2723                 return (DDI_INTR_UNCLAIMED);
2724         }
2725 
2726         instance->softint_running = 1;
2727 
2728         INIT_LIST_HEAD(&process_list);
2729         mlist_splice(&instance->completed_pool_list, &process_list);
2730         INIT_LIST_HEAD(&instance->completed_pool_list);
2731 
2732         mutex_exit(&instance->completed_pool_mtx);
2733 
2734         /* perform all callbacks first, before releasing the SCBs */
2735         mlist_for_each_safe(pos, next, &process_list) {
2736                 cmd = mlist_entry(pos, struct megasas_cmd, list);
2737 
2738                 /* syncronize the Cmd frame for the controller */
2739                 (void) ddi_dma_sync(cmd->frame_dma_obj.dma_handle,
2740                     0, 0, DDI_DMA_SYNC_FORCPU);
2741 
2742                 if (megasas_check_dma_handle(cmd->frame_dma_obj.dma_handle) !=
2743                     DDI_SUCCESS) {
2744                         megasas_fm_ereport(instance, DDI_FM_DEVICE_NO_RESPONSE);
2745                         ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
2746                         return (DDI_INTR_UNCLAIMED);
2747                 }
2748 
2749                 hdr = &cmd->frame->hdr;
2750 
2751                 /* remove the internal command from the process list */
2752                 mlist_del_init(&cmd->list);
2753 
2754                 switch (hdr->cmd) {
2755                 case MFI_CMD_OP_PD_SCSI:
2756                 case MFI_CMD_OP_LD_SCSI:
2757                 case MFI_CMD_OP_LD_READ:
2758                 case MFI_CMD_OP_LD_WRITE:
2759                         /*
2760                          * MFI_CMD_OP_PD_SCSI and MFI_CMD_OP_LD_SCSI
2761                          * could have been issued either through an
2762                          * IO path or an IOCTL path. If it was via IOCTL,
2763                          * we will send it to internal completion.
2764                          */
2765                         if (cmd->sync_cmd == MEGASAS_TRUE) {
2766                                 complete_cmd_in_sync_mode(instance, cmd);
2767                                 break;
2768                         }
2769 
2770                         /* regular commands */
2771                         acmd =  cmd->cmd;
2772                         pkt =   CMD2PKT(acmd);
2773 
2774                         if (acmd->cmd_flags & CFLAG_DMAVALID) {
2775                                 if (acmd->cmd_flags & CFLAG_CONSISTENT) {
2776                                         (void) ddi_dma_sync(acmd->cmd_dmahandle,
2777                                             acmd->cmd_dma_offset,
2778                                             acmd->cmd_dma_len,
2779                                             DDI_DMA_SYNC_FORCPU);
2780                                 }
2781                         }
2782 
2783                         pkt->pkt_reason              = CMD_CMPLT;
2784                         pkt->pkt_statistics  = 0;
2785                         pkt->pkt_state = STATE_GOT_BUS
2786                             | STATE_GOT_TARGET | STATE_SENT_CMD
2787                             | STATE_XFERRED_DATA | STATE_GOT_STATUS;
2788 
2789                         con_log(CL_ANN1, (CE_CONT,
2790                             "CDB[0] = %x completed for %s: size %lx context %x",
2791                             pkt->pkt_cdbp[0], ((acmd->islogical) ? "LD" : "PD"),
2792                             acmd->cmd_dmacount, hdr->context));
2793 
2794                         if (pkt->pkt_cdbp[0] == SCMD_INQUIRY) {
2795                                 struct scsi_inquiry     *inq;
2796 
2797                                 if (acmd->cmd_dmacount != 0) {
2798                                         bp_mapin(acmd->cmd_buf);
2799                                         inq = (struct scsi_inquiry *)
2800                                             acmd->cmd_buf->b_un.b_addr;
2801 
2802                                         /* don't expose physical drives to OS */
2803                                         if (acmd->islogical &&
2804                                             (hdr->cmd_status == MFI_STAT_OK)) {
2805                                                 display_scsi_inquiry(
2806                                                     (caddr_t)inq);
2807                                         } else if ((hdr->cmd_status ==
2808                                             MFI_STAT_OK) && inq->inq_dtype ==
2809                                             DTYPE_DIRECT) {
2810 
2811                                                 display_scsi_inquiry(
2812                                                     (caddr_t)inq);
2813 
2814                                                 /* for physical disk */
2815                                                 hdr->cmd_status =
2816                                                     MFI_STAT_DEVICE_NOT_FOUND;
2817                                         }
2818                                 }
2819                         }
2820 
2821                         switch (hdr->cmd_status) {
2822                         case MFI_STAT_OK:
2823                                 pkt->pkt_scbp[0] = STATUS_GOOD;
2824                                 break;
2825                         case MFI_STAT_LD_CC_IN_PROGRESS:
2826                         case MFI_STAT_LD_RECON_IN_PROGRESS:
2827                             /* SJ - these are not correct way */
2828                                 pkt->pkt_scbp[0] = STATUS_GOOD;
2829                                 break;
2830                         case MFI_STAT_LD_INIT_IN_PROGRESS:
2831                                 con_log(CL_ANN,
2832                                     (CE_WARN, "Initialization in Progress"));
2833                                 pkt->pkt_reason      = CMD_TRAN_ERR;
2834 
2835                                 break;
2836                         case MFI_STAT_SCSI_DONE_WITH_ERROR:
2837                                 con_log(CL_ANN1, (CE_CONT, "scsi_done error"));
2838 
2839                                 pkt->pkt_reason      = CMD_CMPLT;
2840                                 ((struct scsi_status *)
2841                                     pkt->pkt_scbp)->sts_chk = 1;
2842 
2843                                 if (pkt->pkt_cdbp[0] == SCMD_TEST_UNIT_READY) {
2844 
2845                                         con_log(CL_ANN,
2846                                             (CE_WARN, "TEST_UNIT_READY fail"));
2847 
2848                                 } else {
2849                                         pkt->pkt_state |= STATE_ARQ_DONE;
2850                                         arqstat = (void *)(pkt->pkt_scbp);
2851                                         arqstat->sts_rqpkt_reason = CMD_CMPLT;
2852                                         arqstat->sts_rqpkt_resid = 0;
2853                                         arqstat->sts_rqpkt_state |=
2854                                             STATE_GOT_BUS | STATE_GOT_TARGET
2855                                             | STATE_SENT_CMD
2856                                             | STATE_XFERRED_DATA;
2857                                         *(uint8_t *)&arqstat->sts_rqpkt_status =
2858                                             STATUS_GOOD;
2859 
2860                                         bcopy(cmd->sense,
2861                                             &(arqstat->sts_sensedata),
2862                                             acmd->cmd_scblen -
2863                                             offsetof(struct scsi_arq_status,
2864                                             sts_sensedata));
2865                                 }
2866                                 break;
2867                         case MFI_STAT_LD_OFFLINE:
2868                         case MFI_STAT_DEVICE_NOT_FOUND:
2869                                 con_log(CL_ANN1, (CE_CONT,
2870                                     "device not found error"));
2871                                 pkt->pkt_reason      = CMD_DEV_GONE;
2872                                 pkt->pkt_statistics  = STAT_DISCON;
2873                                 break;
2874                         case MFI_STAT_LD_LBA_OUT_OF_RANGE:
2875                                 pkt->pkt_state |= STATE_ARQ_DONE;
2876                                 pkt->pkt_reason      = CMD_CMPLT;
2877                                 ((struct scsi_status *)
2878                                     pkt->pkt_scbp)->sts_chk = 1;
2879 
2880                                 arqstat = (void *)(pkt->pkt_scbp);
2881                                 arqstat->sts_rqpkt_reason = CMD_CMPLT;
2882                                 arqstat->sts_rqpkt_resid = 0;
2883                                 arqstat->sts_rqpkt_state |= STATE_GOT_BUS
2884                                     | STATE_GOT_TARGET | STATE_SENT_CMD
2885                                     | STATE_XFERRED_DATA;
2886                                 *(uint8_t *)&arqstat->sts_rqpkt_status =
2887                                     STATUS_GOOD;
2888 
2889                                 arqstat->sts_sensedata.es_valid = 1;
2890                                 arqstat->sts_sensedata.es_key =
2891                                     KEY_ILLEGAL_REQUEST;
2892                                 arqstat->sts_sensedata.es_class =
2893                                     CLASS_EXTENDED_SENSE;
2894 
2895                                 /*
2896                                  * LOGICAL BLOCK ADDRESS OUT OF RANGE:
2897                                  * ASC: 0x21h; ASCQ: 0x00h;
2898                                  */
2899                                 arqstat->sts_sensedata.es_add_code = 0x21;
2900                                 arqstat->sts_sensedata.es_qual_code = 0x00;
2901 
2902                                 break;
2903 
2904                         default:
2905                                 con_log(CL_ANN, (CE_CONT, "Unknown status!"));
2906                                 pkt->pkt_reason      = CMD_TRAN_ERR;
2907 
2908                                 break;
2909                         }
2910 
2911                         atomic_add_16(&instance->fw_outstanding, (-1));
2912 
2913                         return_mfi_pkt(instance, cmd);
2914 
2915                         (void) megasas_common_check(instance, cmd);
2916 
2917                         if (acmd->cmd_dmahandle) {
2918                                 if (megasas_check_dma_handle(
2919                                     acmd->cmd_dmahandle) != DDI_SUCCESS) {
2920                                         ddi_fm_service_impact(instance->dip,
2921                                             DDI_SERVICE_UNAFFECTED);
2922                                         pkt->pkt_reason = CMD_TRAN_ERR;
2923                                         pkt->pkt_statistics = 0;
2924                                 }
2925                         }
2926 
2927                         /* Call the callback routine */
2928                         if ((pkt->pkt_flags & FLAG_NOINTR) == 0) {
2929                                 scsi_hba_pkt_comp(pkt);
2930                         }
2931 
2932                         break;
2933                 case MFI_CMD_OP_SMP:
2934                 case MFI_CMD_OP_STP:
2935                         complete_cmd_in_sync_mode(instance, cmd);
2936                         break;
2937                 case MFI_CMD_OP_DCMD:
2938                         /* see if got an event notification */
2939                         if (cmd->frame->dcmd.opcode ==
2940                             MR_DCMD_CTRL_EVENT_WAIT) {
2941                                 if ((instance->aen_cmd == cmd) &&
2942                                     (instance->aen_cmd->abort_aen)) {
2943                                         con_log(CL_ANN, (CE_WARN,
2944                                             "megasas_softintr: "
2945                                             "aborted_aen returned"));
2946                                 } else {
2947                                         service_mfi_aen(instance, cmd);
2948 
2949                                         atomic_add_16(&instance->fw_outstanding,
2950                                             (-1));
2951                                 }
2952                         } else {
2953                                 complete_cmd_in_sync_mode(instance, cmd);
2954                         }
2955 
2956                         break;
2957                 case MFI_CMD_OP_ABORT:
2958                         con_log(CL_ANN, (CE_WARN, "MFI_CMD_OP_ABORT complete"));
2959                         /*
2960                          * MFI_CMD_OP_ABORT successfully completed
2961                          * in the synchronous mode
2962                          */
2963                         complete_cmd_in_sync_mode(instance, cmd);
2964                         break;
2965                 default:
2966                         megasas_fm_ereport(instance, DDI_FM_DEVICE_NO_RESPONSE);
2967                         ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
2968 
2969                         if (cmd->pkt != NULL) {
2970                                 pkt = cmd->pkt;
2971                                 if ((pkt->pkt_flags & FLAG_NOINTR) == 0) {
2972                                         scsi_hba_pkt_comp(pkt);
2973                                 }
2974                         }
2975                         con_log(CL_ANN, (CE_WARN, "Cmd type unknown !!"));
2976                         break;
2977                 }
2978         }
2979 
2980         instance->softint_running = 0;
2981 
2982         return (DDI_INTR_CLAIMED);
2983 }
2984 
2985 /*
2986  * mega_alloc_dma_obj
2987  *
2988  * Allocate the memory and other resources for an dma object.
2989  */
2990 static int
2991 mega_alloc_dma_obj(struct megasas_instance *instance, dma_obj_t *obj)
2992 {
2993         int     i;
2994         size_t  alen = 0;
2995         uint_t  cookie_cnt;
2996         struct ddi_device_acc_attr      tmp_endian_attr;
2997 
2998         tmp_endian_attr = endian_attr;
2999         tmp_endian_attr.devacc_attr_access = DDI_DEFAULT_ACC;
3000         i = ddi_dma_alloc_handle(instance->dip, &obj->dma_attr,
3001             DDI_DMA_SLEEP, NULL, &obj->dma_handle);
3002         if (i != DDI_SUCCESS) {
3003 
3004                 switch (i) {
3005                         case DDI_DMA_BADATTR :
3006                                 con_log(CL_ANN, (CE_WARN,
3007                                 "Failed ddi_dma_alloc_handle- Bad atrib"));
3008                                 break;
3009                         case DDI_DMA_NORESOURCES :
3010                                 con_log(CL_ANN, (CE_WARN,
3011                                 "Failed ddi_dma_alloc_handle- No Resources"));
3012                                 break;
3013                         default :
3014                                 con_log(CL_ANN, (CE_WARN,
3015                                 "Failed ddi_dma_alloc_handle :unknown %d", i));
3016                                 break;
3017                 }
3018 
3019                 return (-1);
3020         }
3021 
3022         if ((ddi_dma_mem_alloc(obj->dma_handle, obj->size, &tmp_endian_attr,
3023             DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
3024             &obj->buffer, &alen, &obj->acc_handle) != DDI_SUCCESS) ||
3025             alen < obj->size) {
3026 
3027                 ddi_dma_free_handle(&obj->dma_handle);
3028 
3029                 con_log(CL_ANN, (CE_WARN, "Failed : ddi_dma_mem_alloc"));
3030 
3031                 return (-1);
3032         }
3033 
3034         if (ddi_dma_addr_bind_handle(obj->dma_handle, NULL, obj->buffer,
3035             obj->size, DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_SLEEP,
3036             NULL, &obj->dma_cookie[0], &cookie_cnt) != DDI_SUCCESS) {
3037 
3038                 ddi_dma_mem_free(&obj->acc_handle);
3039                 ddi_dma_free_handle(&obj->dma_handle);
3040 
3041                 con_log(CL_ANN, (CE_WARN, "Failed : ddi_dma_addr_bind_handle"));
3042 
3043                 return (-1);
3044         }
3045 
3046         if (megasas_check_dma_handle(obj->dma_handle) != DDI_SUCCESS) {
3047                 ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
3048                 return (-1);
3049         }
3050 
3051         if (megasas_check_acc_handle(obj->acc_handle) != DDI_SUCCESS) {
3052                 ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
3053                 return (-1);
3054         }
3055 
3056         return (cookie_cnt);
3057 }
3058 
3059 /*
3060  * mega_free_dma_obj(struct megasas_instance *, dma_obj_t)
3061  *
3062  * De-allocate the memory and other resources for an dma object, which must
3063  * have been alloated by a previous call to mega_alloc_dma_obj()
3064  */
3065 static int
3066 mega_free_dma_obj(struct megasas_instance *instance, dma_obj_t obj)
3067 {
3068 
3069         if (megasas_check_dma_handle(obj.dma_handle) != DDI_SUCCESS) {
3070                 ddi_fm_service_impact(instance->dip, DDI_SERVICE_UNAFFECTED);
3071                 return (DDI_FAILURE);
3072         }
3073 
3074         if (megasas_check_acc_handle(obj.acc_handle) != DDI_SUCCESS) {
3075                 ddi_fm_service_impact(instance->dip, DDI_SERVICE_UNAFFECTED);
3076                 return (DDI_FAILURE);
3077         }
3078 
3079         (void) ddi_dma_unbind_handle(obj.dma_handle);
3080         ddi_dma_mem_free(&obj.acc_handle);
3081         ddi_dma_free_handle(&obj.dma_handle);
3082 
3083         return (DDI_SUCCESS);
3084 }
3085 
3086 /*
3087  * megasas_dma_alloc(instance_t *, struct scsi_pkt *, struct buf *,
3088  * int, int (*)())
3089  *
3090  * Allocate dma resources for a new scsi command
3091  */
3092 static int
3093 megasas_dma_alloc(struct megasas_instance *instance, struct scsi_pkt *pkt,
3094     struct buf *bp, int flags, int (*callback)())
3095 {
3096         int     dma_flags;
3097         int     (*cb)(caddr_t);
3098         int     i;
3099 
3100         ddi_dma_attr_t  tmp_dma_attr = megasas_generic_dma_attr;
3101         struct scsa_cmd *acmd = PKT2CMD(pkt);
3102 
3103         acmd->cmd_buf = bp;
3104 
3105         if (bp->b_flags & B_READ) {
3106                 acmd->cmd_flags &= ~CFLAG_DMASEND;
3107                 dma_flags = DDI_DMA_READ;
3108         } else {
3109                 acmd->cmd_flags |= CFLAG_DMASEND;
3110                 dma_flags = DDI_DMA_WRITE;
3111         }
3112 
3113         if (flags & PKT_CONSISTENT) {
3114                 acmd->cmd_flags |= CFLAG_CONSISTENT;
3115                 dma_flags |= DDI_DMA_CONSISTENT;
3116         }
3117 
3118         if (flags & PKT_DMA_PARTIAL) {
3119                 dma_flags |= DDI_DMA_PARTIAL;
3120         }
3121 
3122         dma_flags |= DDI_DMA_REDZONE;
3123 
3124         cb = (callback == NULL_FUNC) ? DDI_DMA_DONTWAIT : DDI_DMA_SLEEP;
3125 
3126         tmp_dma_attr.dma_attr_sgllen = instance->max_num_sge;
3127         tmp_dma_attr.dma_attr_addr_hi = 0xffffffffffffffffull;
3128 
3129         if ((i = ddi_dma_alloc_handle(instance->dip, &tmp_dma_attr,
3130             cb, 0, &acmd->cmd_dmahandle)) != DDI_SUCCESS) {
3131                 switch (i) {
3132                 case DDI_DMA_BADATTR:
3133                         bioerror(bp, EFAULT);
3134                         return (-1);
3135 
3136                 case DDI_DMA_NORESOURCES:
3137                         bioerror(bp, 0);
3138                         return (-1);
3139 
3140                 default:
3141                         con_log(CL_ANN, (CE_PANIC, "ddi_dma_alloc_handle: "
3142                             "0x%x impossible\n", i));
3143                         bioerror(bp, EFAULT);
3144                         return (-1);
3145                 }
3146         }
3147 
3148         i = ddi_dma_buf_bind_handle(acmd->cmd_dmahandle, bp, dma_flags,
3149             cb, 0, &acmd->cmd_dmacookies[0], &acmd->cmd_ncookies);
3150 
3151         switch (i) {
3152         case DDI_DMA_PARTIAL_MAP:
3153                 if ((dma_flags & DDI_DMA_PARTIAL) == 0) {
3154                         con_log(CL_ANN, (CE_PANIC, "ddi_dma_buf_bind_handle: "
3155                             "DDI_DMA_PARTIAL_MAP impossible\n"));
3156                         goto no_dma_cookies;
3157                 }
3158 
3159                 if (ddi_dma_numwin(acmd->cmd_dmahandle, &acmd->cmd_nwin) ==
3160                     DDI_FAILURE) {
3161                         con_log(CL_ANN, (CE_PANIC, "ddi_dma_numwin failed\n"));
3162                         goto no_dma_cookies;
3163                 }
3164 
3165                 if (ddi_dma_getwin(acmd->cmd_dmahandle, acmd->cmd_curwin,
3166                     &acmd->cmd_dma_offset, &acmd->cmd_dma_len,
3167                     &acmd->cmd_dmacookies[0], &acmd->cmd_ncookies) ==
3168                     DDI_FAILURE) {
3169 
3170                         con_log(CL_ANN, (CE_PANIC, "ddi_dma_getwin failed\n"));
3171                         goto no_dma_cookies;
3172                 }
3173 
3174                 goto get_dma_cookies;
3175         case DDI_DMA_MAPPED:
3176                 acmd->cmd_nwin = 1;
3177                 acmd->cmd_dma_len = 0;
3178                 acmd->cmd_dma_offset = 0;
3179 
3180 get_dma_cookies:
3181                 i = 0;
3182                 acmd->cmd_dmacount = 0;
3183                 for (;;) {
3184                         acmd->cmd_dmacount +=
3185                             acmd->cmd_dmacookies[i++].dmac_size;
3186 
3187                         if (i == instance->max_num_sge ||
3188                             i == acmd->cmd_ncookies)
3189                                 break;
3190 
3191                         ddi_dma_nextcookie(acmd->cmd_dmahandle,
3192                             &acmd->cmd_dmacookies[i]);
3193                 }
3194 
3195                 acmd->cmd_cookie = i;
3196                 acmd->cmd_cookiecnt = i;
3197 
3198                 acmd->cmd_flags |= CFLAG_DMAVALID;
3199 
3200                 if (bp->b_bcount >= acmd->cmd_dmacount) {
3201                         pkt->pkt_resid = bp->b_bcount - acmd->cmd_dmacount;
3202                 } else {
3203                         pkt->pkt_resid = 0;
3204                 }
3205 
3206                 return (0);
3207         case DDI_DMA_NORESOURCES:
3208                 bioerror(bp, 0);
3209                 break;
3210         case DDI_DMA_NOMAPPING:
3211                 bioerror(bp, EFAULT);
3212                 break;
3213         case DDI_DMA_TOOBIG:
3214                 bioerror(bp, EINVAL);
3215                 break;
3216         case DDI_DMA_INUSE:
3217                 con_log(CL_ANN, (CE_PANIC, "ddi_dma_buf_bind_handle:"
3218                     " DDI_DMA_INUSE impossible\n"));
3219                 break;
3220         default:
3221                 con_log(CL_ANN, (CE_PANIC, "ddi_dma_buf_bind_handle: "
3222                     "0x%x impossible\n", i));
3223                 break;
3224         }
3225 
3226 no_dma_cookies:
3227         ddi_dma_free_handle(&acmd->cmd_dmahandle);
3228         acmd->cmd_dmahandle = NULL;
3229         acmd->cmd_flags &= ~CFLAG_DMAVALID;
3230         return (-1);
3231 }
3232 
3233 /*
3234  * megasas_dma_move(struct megasas_instance *, struct scsi_pkt *, struct buf *)
3235  *
3236  * move dma resources to next dma window
3237  *
3238  */
3239 static int
3240 megasas_dma_move(struct megasas_instance *instance, struct scsi_pkt *pkt,
3241     struct buf *bp)
3242 {
3243         int     i = 0;
3244 
3245         struct scsa_cmd *acmd = PKT2CMD(pkt);
3246 
3247         /*
3248          * If there are no more cookies remaining in this window,
3249          * must move to the next window first.
3250          */
3251         if (acmd->cmd_cookie == acmd->cmd_ncookies) {
3252                 if (acmd->cmd_curwin == acmd->cmd_nwin && acmd->cmd_nwin == 1) {
3253                         return (0);
3254                 }
3255 
3256                 /* at last window, cannot move */
3257                 if (++acmd->cmd_curwin >= acmd->cmd_nwin) {
3258                         return (-1);
3259                 }
3260 
3261                 if (ddi_dma_getwin(acmd->cmd_dmahandle, acmd->cmd_curwin,
3262                     &acmd->cmd_dma_offset, &acmd->cmd_dma_len,
3263                     &acmd->cmd_dmacookies[0], &acmd->cmd_ncookies) ==
3264                     DDI_FAILURE) {
3265                         return (-1);
3266                 }
3267 
3268                 acmd->cmd_cookie = 0;
3269         } else {
3270                 /* still more cookies in this window - get the next one */
3271                 ddi_dma_nextcookie(acmd->cmd_dmahandle,
3272                     &acmd->cmd_dmacookies[0]);
3273         }
3274 
3275         /* get remaining cookies in this window, up to our maximum */
3276         for (;;) {
3277                 acmd->cmd_dmacount += acmd->cmd_dmacookies[i++].dmac_size;
3278                 acmd->cmd_cookie++;
3279 
3280                 if (i == instance->max_num_sge ||
3281                     acmd->cmd_cookie == acmd->cmd_ncookies) {
3282                         break;
3283                 }
3284 
3285                 ddi_dma_nextcookie(acmd->cmd_dmahandle,
3286                     &acmd->cmd_dmacookies[i]);
3287         }
3288 
3289         acmd->cmd_cookiecnt = i;
3290 
3291         if (bp->b_bcount >= acmd->cmd_dmacount) {
3292                 pkt->pkt_resid = bp->b_bcount - acmd->cmd_dmacount;
3293         } else {
3294                 pkt->pkt_resid = 0;
3295         }
3296 
3297         return (0);
3298 }
3299 
3300 /*
3301  * build_cmd
3302  */
3303 static struct megasas_cmd *
3304 build_cmd(struct megasas_instance *instance, struct scsi_address *ap,
3305     struct scsi_pkt *pkt, uchar_t *cmd_done)
3306 {
3307         uint16_t        flags = 0;
3308         uint32_t        i;
3309         uint32_t        context;
3310         uint32_t        sge_bytes;
3311 
3312         struct megasas_cmd              *cmd;
3313         struct megasas_sge64            *mfi_sgl;
3314         struct scsa_cmd                 *acmd = PKT2CMD(pkt);
3315         struct megasas_pthru_frame      *pthru;
3316         struct megasas_io_frame         *ldio;
3317 
3318         /* find out if this is logical or physical drive command.  */
3319         acmd->islogical = MEGADRV_IS_LOGICAL(ap);
3320         acmd->device_id = MAP_DEVICE_ID(instance, ap);
3321         *cmd_done = 0;
3322 
3323         /* get the command packet */
3324         if (!(cmd = get_mfi_pkt(instance))) {
3325                 return (NULL);
3326         }
3327 
3328         cmd->pkt = pkt;
3329         cmd->cmd = acmd;
3330 
3331         /* lets get the command directions */
3332         if (acmd->cmd_flags & CFLAG_DMASEND) {
3333                 flags = MFI_FRAME_DIR_WRITE;
3334 
3335                 if (acmd->cmd_flags & CFLAG_CONSISTENT) {
3336                         (void) ddi_dma_sync(acmd->cmd_dmahandle,
3337                             acmd->cmd_dma_offset, acmd->cmd_dma_len,
3338                             DDI_DMA_SYNC_FORDEV);
3339                 }
3340         } else if (acmd->cmd_flags & ~CFLAG_DMASEND) {
3341                 flags = MFI_FRAME_DIR_READ;
3342 
3343                 if (acmd->cmd_flags & CFLAG_CONSISTENT) {
3344                         (void) ddi_dma_sync(acmd->cmd_dmahandle,
3345                             acmd->cmd_dma_offset, acmd->cmd_dma_len,
3346                             DDI_DMA_SYNC_FORCPU);
3347                 }
3348         } else {
3349                 flags = MFI_FRAME_DIR_NONE;
3350         }
3351 
3352         flags |= MFI_FRAME_SGL64;
3353 
3354         switch (pkt->pkt_cdbp[0]) {
3355 
3356         /*
3357          * case SCMD_SYNCHRONIZE_CACHE:
3358          *      flush_cache(instance);
3359          *      return_mfi_pkt(instance, cmd);
3360          *      *cmd_done = 1;
3361          *
3362          *      return (NULL);
3363          */
3364 
3365         case SCMD_READ:
3366         case SCMD_WRITE:
3367         case SCMD_READ_G1:
3368         case SCMD_WRITE_G1:
3369                 if (acmd->islogical) {
3370                         ldio = (struct megasas_io_frame *)cmd->frame;
3371 
3372                         /*
3373                          * preare the Logical IO frame:
3374                          * 2nd bit is zero for all read cmds
3375                          */
3376                         ldio->cmd = (pkt->pkt_cdbp[0] & 0x02) ?
3377                             MFI_CMD_OP_LD_WRITE : MFI_CMD_OP_LD_READ;
3378                         ldio->cmd_status = 0x0;
3379                         ldio->scsi_status = 0x0;
3380                         ldio->target_id       = acmd->device_id;
3381                         ldio->timeout = 0;
3382                         ldio->reserved_0 = 0;
3383                         ldio->pad_0 = 0;
3384                         ldio->flags = flags;
3385 
3386                         /* Initialize sense Information */
3387                         bzero(cmd->sense, SENSE_LENGTH);
3388                         ldio->sense_len = SENSE_LENGTH;
3389                         ldio->sense_buf_phys_addr_hi = 0;
3390                         ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
3391 
3392                         ldio->start_lba_hi = 0;
3393                         ldio->access_byte = (acmd->cmd_cdblen != 6) ?
3394                             pkt->pkt_cdbp[1] : 0;
3395                         ldio->sge_count = acmd->cmd_cookiecnt;
3396                         mfi_sgl = (struct megasas_sge64 *)&ldio->sgl;
3397 
3398                         context = ldio->context;
3399 
3400                         if (acmd->cmd_cdblen == CDB_GROUP0) {
3401                                 ldio->lba_count      = host_to_le16(
3402                                     (uint16_t)(pkt->pkt_cdbp[4]));
3403 
3404                                 ldio->start_lba_lo = host_to_le32(
3405                                     ((uint32_t)(pkt->pkt_cdbp[3])) |
3406                                     ((uint32_t)(pkt->pkt_cdbp[2]) << 8) |
3407                                     ((uint32_t)((pkt->pkt_cdbp[1]) & 0x1F)
3408                                     << 16));
3409                         } else if (acmd->cmd_cdblen == CDB_GROUP1) {
3410                                 ldio->lba_count = host_to_le16(
3411                                     ((uint16_t)(pkt->pkt_cdbp[8])) |
3412                                     ((uint16_t)(pkt->pkt_cdbp[7]) << 8));
3413 
3414                                 ldio->start_lba_lo = host_to_le32(
3415                                     ((uint32_t)(pkt->pkt_cdbp[5])) |
3416                                     ((uint32_t)(pkt->pkt_cdbp[4]) << 8) |
3417                                     ((uint32_t)(pkt->pkt_cdbp[3]) << 16) |
3418                                     ((uint32_t)(pkt->pkt_cdbp[2]) << 24));
3419                         } else if (acmd->cmd_cdblen == CDB_GROUP2) {
3420                                 ldio->lba_count       = host_to_le16(
3421                                     ((uint16_t)(pkt->pkt_cdbp[9])) |
3422                                     ((uint16_t)(pkt->pkt_cdbp[8]) << 8) |
3423                                     ((uint16_t)(pkt->pkt_cdbp[7]) << 16) |
3424                                     ((uint16_t)(pkt->pkt_cdbp[6]) << 24));
3425 
3426                                 ldio->start_lba_lo = host_to_le32(
3427                                     ((uint32_t)(pkt->pkt_cdbp[5])) |
3428                                     ((uint32_t)(pkt->pkt_cdbp[4]) << 8) |
3429                                     ((uint32_t)(pkt->pkt_cdbp[3]) << 16) |
3430                                     ((uint32_t)(pkt->pkt_cdbp[2]) << 24));
3431                         } else if (acmd->cmd_cdblen == CDB_GROUP3) {
3432                                 ldio->lba_count = host_to_le16(
3433                                     ((uint16_t)(pkt->pkt_cdbp[13])) |
3434                                     ((uint16_t)(pkt->pkt_cdbp[12]) << 8) |
3435                                     ((uint16_t)(pkt->pkt_cdbp[11]) << 16) |
3436                                     ((uint16_t)(pkt->pkt_cdbp[10]) << 24));
3437 
3438                                 ldio->start_lba_lo = host_to_le32(
3439                                     ((uint32_t)(pkt->pkt_cdbp[9])) |
3440                                     ((uint32_t)(pkt->pkt_cdbp[8]) << 8) |
3441                                     ((uint32_t)(pkt->pkt_cdbp[7]) << 16) |
3442                                     ((uint32_t)(pkt->pkt_cdbp[6]) << 24));
3443 
3444                                 ldio->start_lba_lo = host_to_le32(
3445                                     ((uint32_t)(pkt->pkt_cdbp[5])) |
3446                                     ((uint32_t)(pkt->pkt_cdbp[4]) << 8) |
3447                                     ((uint32_t)(pkt->pkt_cdbp[3]) << 16) |
3448                                     ((uint32_t)(pkt->pkt_cdbp[2]) << 24));
3449                         }
3450 
3451                         break;
3452                 }
3453                 /* fall through For all non-rd/wr cmds */
3454         default:
3455                 pthru   = (struct megasas_pthru_frame *)cmd->frame;
3456 
3457                 /* prepare the DCDB frame */
3458                 pthru->cmd = (acmd->islogical) ?
3459                     MFI_CMD_OP_LD_SCSI : MFI_CMD_OP_PD_SCSI;
3460                 pthru->cmd_status    = 0x0;
3461                 pthru->scsi_status   = 0x0;
3462                 pthru->target_id     = acmd->device_id;
3463                 pthru->lun           = 0;
3464                 pthru->cdb_len               = acmd->cmd_cdblen;
3465                 pthru->timeout               = 0;
3466                 pthru->flags         = flags;
3467                 pthru->data_xfer_len = acmd->cmd_dmacount;
3468                 pthru->sge_count     = acmd->cmd_cookiecnt;
3469                 mfi_sgl                 = (struct megasas_sge64 *)&pthru->sgl;
3470 
3471                 bzero(cmd->sense, SENSE_LENGTH);
3472                 pthru->sense_len     = SENSE_LENGTH;
3473                 pthru->sense_buf_phys_addr_hi = 0;
3474                 pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
3475 
3476                 context = pthru->context;
3477 
3478                 bcopy(pkt->pkt_cdbp, pthru->cdb, acmd->cmd_cdblen);
3479 
3480                 break;
3481         }
3482 #ifdef lint
3483         context = context;
3484 #endif
3485         /* bzero(mfi_sgl, sizeof (struct megasas_sge64) * MAX_SGL); */
3486 
3487         /* prepare the scatter-gather list for the firmware */
3488         for (i = 0; i < acmd->cmd_cookiecnt; i++, mfi_sgl++) {
3489                 mfi_sgl->phys_addr = acmd->cmd_dmacookies[i].dmac_laddress;
3490                 mfi_sgl->length    = acmd->cmd_dmacookies[i].dmac_size;
3491         }
3492 
3493         sge_bytes = sizeof (struct megasas_sge64)*acmd->cmd_cookiecnt;
3494 
3495         cmd->frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) +
3496             ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) + 1;
3497 
3498         if (cmd->frame_count >= 8) {
3499                 cmd->frame_count = 8;
3500         }
3501 
3502         return (cmd);
3503 }
3504 
3505 /*
3506  * wait_for_outstanding -       Wait for all outstanding cmds
3507  * @instance:                           Adapter soft state
3508  *
3509  * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to
3510  * complete all its outstanding commands. Returns error if one or more IOs
3511  * are pending after this time period.
3512  */
3513 static int
3514 wait_for_outstanding(struct megasas_instance *instance)
3515 {
3516         int             i;
3517         uint32_t        wait_time = 90;
3518 
3519         for (i = 0; i < wait_time; i++) {
3520                 if (!instance->fw_outstanding) {
3521                         break;
3522                 }
3523 
3524                 drv_usecwait(MILLISEC); /* wait for 1000 usecs */;
3525         }
3526 
3527         if (instance->fw_outstanding) {
3528                 return (1);
3529         }
3530 
3531         ddi_fm_acc_err_clear(instance->regmap_handle, DDI_FME_VERSION);
3532 
3533         return (0);
3534 }
3535 
3536 /*
3537  * issue_mfi_pthru
3538  */
3539 static int
3540 issue_mfi_pthru(struct megasas_instance *instance, struct megasas_ioctl *ioctl,
3541     struct megasas_cmd *cmd, int mode)
3542 {
3543         void            *ubuf;
3544         uint32_t        kphys_addr = 0;
3545         uint32_t        xferlen = 0;
3546         uint_t          model;
3547 
3548         dma_obj_t                       pthru_dma_obj;
3549         struct megasas_pthru_frame      *kpthru;
3550         struct megasas_pthru_frame      *pthru;
3551 
3552         pthru = &cmd->frame->pthru;
3553         kpthru = (struct megasas_pthru_frame *)&ioctl->frame[0];
3554 
3555         model = ddi_model_convert_from(mode & FMODELS);
3556         if (model == DDI_MODEL_ILP32) {
3557                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_pthru: DDI_MODEL_LP32"));
3558 
3559                 xferlen = kpthru->sgl.sge32[0].length;
3560 
3561                 /* SJ! - ubuf needs to be virtual address. */
3562                 ubuf    = (void *)(ulong_t)kpthru->sgl.sge32[0].phys_addr;
3563         } else {
3564 #ifdef _ILP32
3565                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_pthru: DDI_MODEL_LP32"));
3566                 xferlen = kpthru->sgl.sge32[0].length;
3567                 /* SJ! - ubuf needs to be virtual address. */
3568                 ubuf    = (void *)(ulong_t)kpthru->sgl.sge32[0].phys_addr;
3569 #else
3570                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_pthru: DDI_MODEL_LP64"));
3571                 xferlen = kpthru->sgl.sge64[0].length;
3572                 /* SJ! - ubuf needs to be virtual address. */
3573                 ubuf    = (void *)(ulong_t)kpthru->sgl.sge64[0].phys_addr;
3574 #endif
3575         }
3576 
3577         if (xferlen) {
3578                 /* means IOCTL requires DMA */
3579                 /* allocate the data transfer buffer */
3580                 pthru_dma_obj.size = xferlen;
3581                 pthru_dma_obj.dma_attr = megasas_generic_dma_attr;
3582                 pthru_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3583                 pthru_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
3584                 pthru_dma_obj.dma_attr.dma_attr_sgllen = 1;
3585                 pthru_dma_obj.dma_attr.dma_attr_align = 1;
3586 
3587                 /* allocate kernel buffer for DMA */
3588                 if (mega_alloc_dma_obj(instance, &pthru_dma_obj) != 1) {
3589                         con_log(CL_ANN, (CE_WARN, "issue_mfi_pthru: "
3590                             "could not data transfer buffer alloc."));
3591                         return (DDI_FAILURE);
3592                 }
3593 
3594                 /* If IOCTL requires DMA WRITE, do ddi_copyin IOCTL data copy */
3595                 if (kpthru->flags & MFI_FRAME_DIR_WRITE) {
3596                         if (ddi_copyin(ubuf, (void *)pthru_dma_obj.buffer,
3597                             xferlen, mode)) {
3598                                 con_log(CL_ANN, (CE_WARN, "issue_mfi_pthru: "
3599                                     "copy from user space failed\n"));
3600                                 return (1);
3601                         }
3602                 }
3603 
3604                 kphys_addr = pthru_dma_obj.dma_cookie[0].dmac_address;
3605         }
3606 
3607         pthru->cmd           = kpthru->cmd;
3608         pthru->sense_len     = kpthru->sense_len;
3609         pthru->cmd_status    = kpthru->cmd_status;
3610         pthru->scsi_status   = kpthru->scsi_status;
3611         pthru->target_id     = kpthru->target_id;
3612         pthru->lun           = kpthru->lun;
3613         pthru->cdb_len               = kpthru->cdb_len;
3614         pthru->sge_count     = kpthru->sge_count;
3615         pthru->timeout               = kpthru->timeout;
3616         pthru->data_xfer_len = kpthru->data_xfer_len;
3617 
3618         pthru->sense_buf_phys_addr_hi        = 0;
3619         /* pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr; */
3620         pthru->sense_buf_phys_addr_lo        = 0;
3621 
3622         bcopy((void *)kpthru->cdb, (void *)pthru->cdb, pthru->cdb_len);
3623 
3624         pthru->flags                 = kpthru->flags & ~MFI_FRAME_SGL64;
3625         pthru->sgl.sge32[0].length   = xferlen;
3626         pthru->sgl.sge32[0].phys_addr        = kphys_addr;
3627 
3628         cmd->sync_cmd = MEGASAS_TRUE;
3629         cmd->frame_count = 1;
3630 
3631         if (instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd)) {
3632                 con_log(CL_ANN, (CE_WARN,
3633                     "issue_mfi_pthru: fw_ioctl failed\n"));
3634         } else {
3635                 if (xferlen && (kpthru->flags & MFI_FRAME_DIR_READ)) {
3636 
3637                         if (ddi_copyout(pthru_dma_obj.buffer, ubuf,
3638                             xferlen, mode)) {
3639                                 con_log(CL_ANN, (CE_WARN, "issue_mfi_pthru: "
3640                                     "copy to user space failed\n"));
3641                                 return (1);
3642                         }
3643                 }
3644         }
3645 
3646         kpthru->cmd_status = pthru->cmd_status;
3647         kpthru->scsi_status = pthru->scsi_status;
3648 
3649         con_log(CL_ANN, (CE_NOTE, "issue_mfi_pthru: cmd_status %x, "
3650             "scsi_status %x\n", pthru->cmd_status, pthru->scsi_status));
3651 
3652         if (xferlen) {
3653                 /* free kernel buffer */
3654                 if (mega_free_dma_obj(instance, pthru_dma_obj) != DDI_SUCCESS)
3655                         return (1);
3656         }
3657 
3658         return (0);
3659 }
3660 
3661 /*
3662  * issue_mfi_dcmd
3663  */
3664 static int
3665 issue_mfi_dcmd(struct megasas_instance *instance, struct megasas_ioctl *ioctl,
3666     struct megasas_cmd *cmd, int mode)
3667 {
3668         void            *ubuf;
3669         uint32_t        kphys_addr = 0;
3670         uint32_t        xferlen = 0;
3671         uint32_t        model;
3672         dma_obj_t                       dcmd_dma_obj;
3673         struct megasas_dcmd_frame       *kdcmd;
3674         struct megasas_dcmd_frame       *dcmd;
3675 
3676         dcmd = &cmd->frame->dcmd;
3677         kdcmd = (struct megasas_dcmd_frame *)&ioctl->frame[0];
3678 
3679         model = ddi_model_convert_from(mode & FMODELS);
3680         if (model == DDI_MODEL_ILP32) {
3681                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_dcmd: DDI_MODEL_ILP32"));
3682 
3683                 xferlen = kdcmd->sgl.sge32[0].length;
3684 
3685                 /* SJ! - ubuf needs to be virtual address. */
3686                 ubuf    = (void *)(ulong_t)kdcmd->sgl.sge32[0].phys_addr;
3687         }
3688         else
3689         {
3690 #ifdef _ILP32
3691                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_dcmd: DDI_MODEL_ILP32"));
3692                 xferlen = kdcmd->sgl.sge32[0].length;
3693                 /* SJ! - ubuf needs to be virtual address. */
3694                 ubuf    = (void *)(ulong_t)kdcmd->sgl.sge32[0].phys_addr;
3695 #else
3696                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_dcmd: DDI_MODEL_LP64"));
3697                 xferlen = kdcmd->sgl.sge64[0].length;
3698                 /* SJ! - ubuf needs to be virtual address. */
3699                 ubuf    = (void *)(ulong_t)dcmd->sgl.sge64[0].phys_addr;
3700 #endif
3701         }
3702         if (xferlen) {
3703                 /* means IOCTL requires DMA */
3704                 /* allocate the data transfer buffer */
3705                 dcmd_dma_obj.size = xferlen;
3706                 dcmd_dma_obj.dma_attr = megasas_generic_dma_attr;
3707                 dcmd_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3708                 dcmd_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
3709                 dcmd_dma_obj.dma_attr.dma_attr_sgllen = 1;
3710                 dcmd_dma_obj.dma_attr.dma_attr_align = 1;
3711 
3712                 /* allocate kernel buffer for DMA */
3713                 if (mega_alloc_dma_obj(instance, &dcmd_dma_obj) != 1) {
3714                         con_log(CL_ANN, (CE_WARN, "issue_mfi_dcmd: "
3715                             "could not data transfer buffer alloc."));
3716                         return (DDI_FAILURE);
3717                 }
3718 
3719                 /* If IOCTL requires DMA WRITE, do ddi_copyin IOCTL data copy */
3720                 if (kdcmd->flags & MFI_FRAME_DIR_WRITE) {
3721                         if (ddi_copyin(ubuf, (void *)dcmd_dma_obj.buffer,
3722                             xferlen, mode)) {
3723                                 con_log(CL_ANN, (CE_WARN, "issue_mfi_dcmd: "
3724                                     "copy from user space failed\n"));
3725                                 return (1);
3726                         }
3727                 }
3728 
3729                 kphys_addr = dcmd_dma_obj.dma_cookie[0].dmac_address;
3730         }
3731 
3732         dcmd->cmd            = kdcmd->cmd;
3733         dcmd->cmd_status     = kdcmd->cmd_status;
3734         dcmd->sge_count              = kdcmd->sge_count;
3735         dcmd->timeout                = kdcmd->timeout;
3736         dcmd->data_xfer_len  = kdcmd->data_xfer_len;
3737         dcmd->opcode         = kdcmd->opcode;
3738 
3739         bcopy((void *)kdcmd->mbox.b, (void *)dcmd->mbox.b, DCMD_MBOX_SZ);
3740 
3741         dcmd->flags                  = kdcmd->flags & ~MFI_FRAME_SGL64;
3742         dcmd->sgl.sge32[0].length    = xferlen;
3743         dcmd->sgl.sge32[0].phys_addr = kphys_addr;
3744 
3745         cmd->sync_cmd = MEGASAS_TRUE;
3746         cmd->frame_count = 1;
3747 
3748         if (instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd)) {
3749                 con_log(CL_ANN, (CE_WARN, "issue_mfi_dcmd: fw_ioctl failed\n"));
3750         } else {
3751                 if (xferlen && (kdcmd->flags & MFI_FRAME_DIR_READ)) {
3752 
3753                         if (ddi_copyout(dcmd_dma_obj.buffer, ubuf,
3754                             xferlen, mode)) {
3755                                 con_log(CL_ANN, (CE_WARN, "issue_mfi_dcmd: "
3756                                     "copy to user space failed\n"));
3757                                 return (1);
3758                         }
3759                 }
3760         }
3761 
3762         kdcmd->cmd_status = dcmd->cmd_status;
3763 
3764         if (xferlen) {
3765                 /* free kernel buffer */
3766                 if (mega_free_dma_obj(instance, dcmd_dma_obj) != DDI_SUCCESS)
3767                         return (1);
3768         }
3769 
3770         return (0);
3771 }
3772 
3773 /*
3774  * issue_mfi_smp
3775  */
3776 static int
3777 issue_mfi_smp(struct megasas_instance *instance, struct megasas_ioctl *ioctl,
3778     struct megasas_cmd *cmd, int mode)
3779 {
3780         void            *request_ubuf;
3781         void            *response_ubuf;
3782         uint32_t        request_xferlen = 0;
3783         uint32_t        response_xferlen = 0;
3784         uint_t          model;
3785         dma_obj_t                       request_dma_obj;
3786         dma_obj_t                       response_dma_obj;
3787         struct megasas_smp_frame        *ksmp;
3788         struct megasas_smp_frame        *smp;
3789         struct megasas_sge32            *sge32;
3790 #ifndef _ILP32
3791         struct megasas_sge64            *sge64;
3792 #endif
3793 
3794         smp = &cmd->frame->smp;
3795         ksmp = (struct megasas_smp_frame *)&ioctl->frame[0];
3796 
3797         model = ddi_model_convert_from(mode & FMODELS);
3798         if (model == DDI_MODEL_ILP32) {
3799                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_smp: DDI_MODEL_ILP32"));
3800 
3801                 sge32                   = &ksmp->sgl[0].sge32[0];
3802                 response_xferlen        = sge32[0].length;
3803                 request_xferlen         = sge32[1].length;
3804                 con_log(CL_ANN, (CE_NOTE, "issue_mfi_smp: "
3805                     "response_xferlen = %x, request_xferlen = %x",
3806                     response_xferlen, request_xferlen));
3807 
3808                 /* SJ! - ubuf needs to be virtual address. */
3809 
3810                 response_ubuf   = (void *)(ulong_t)sge32[0].phys_addr;
3811                 request_ubuf    = (void *)(ulong_t)sge32[1].phys_addr;
3812                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_smp: "
3813                     "response_ubuf = %p, request_ubuf = %p",
3814                     response_ubuf, request_ubuf));
3815         } else {
3816 #ifdef _ILP32
3817                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_smp: DDI_MODEL_ILP32"));
3818 
3819                 sge32                   = &ksmp->sgl[0].sge32[0];
3820                 response_xferlen        = sge32[0].length;
3821                 request_xferlen         = sge32[1].length;
3822                 con_log(CL_ANN, (CE_NOTE, "issue_mfi_smp: "
3823                     "response_xferlen = %x, request_xferlen = %x",
3824                     response_xferlen, request_xferlen));
3825 
3826                 /* SJ! - ubuf needs to be virtual address. */
3827 
3828                 response_ubuf   = (void *)(ulong_t)sge32[0].phys_addr;
3829                 request_ubuf    = (void *)(ulong_t)sge32[1].phys_addr;
3830                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_smp: "
3831                     "response_ubuf = %p, request_ubuf = %p",
3832                     response_ubuf, request_ubuf));
3833 #else
3834                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_smp: DDI_MODEL_LP64"));
3835 
3836                 sge64                   = &ksmp->sgl[0].sge64[0];
3837                 response_xferlen        = sge64[0].length;
3838                 request_xferlen         = sge64[1].length;
3839 
3840                 /* SJ! - ubuf needs to be virtual address. */
3841                 response_ubuf   = (void *)(ulong_t)sge64[0].phys_addr;
3842                 request_ubuf    = (void *)(ulong_t)sge64[1].phys_addr;
3843 #endif
3844         }
3845         if (request_xferlen) {
3846                 /* means IOCTL requires DMA */
3847                 /* allocate the data transfer buffer */
3848                 request_dma_obj.size = request_xferlen;
3849                 request_dma_obj.dma_attr = megasas_generic_dma_attr;
3850                 request_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3851                 request_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
3852                 request_dma_obj.dma_attr.dma_attr_sgllen = 1;
3853                 request_dma_obj.dma_attr.dma_attr_align = 1;
3854 
3855                 /* allocate kernel buffer for DMA */
3856                 if (mega_alloc_dma_obj(instance, &request_dma_obj) != 1) {
3857                         con_log(CL_ANN, (CE_WARN, "issue_mfi_smp: "
3858                             "could not data transfer buffer alloc."));
3859                         return (DDI_FAILURE);
3860                 }
3861 
3862                 /* If IOCTL requires DMA WRITE, do ddi_copyin IOCTL data copy */
3863                 if (ddi_copyin(request_ubuf, (void *) request_dma_obj.buffer,
3864                     request_xferlen, mode)) {
3865                         con_log(CL_ANN, (CE_WARN, "issue_mfi_smp: "
3866                             "copy from user space failed\n"));
3867                         return (1);
3868                 }
3869         }
3870 
3871         if (response_xferlen) {
3872                 /* means IOCTL requires DMA */
3873                 /* allocate the data transfer buffer */
3874                 response_dma_obj.size = response_xferlen;
3875                 response_dma_obj.dma_attr = megasas_generic_dma_attr;
3876                 response_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3877                 response_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
3878                 response_dma_obj.dma_attr.dma_attr_sgllen = 1;
3879                 response_dma_obj.dma_attr.dma_attr_align = 1;
3880 
3881                 /* allocate kernel buffer for DMA */
3882                 if (mega_alloc_dma_obj(instance, &response_dma_obj) != 1) {
3883                         con_log(CL_ANN, (CE_WARN, "issue_mfi_smp: "
3884                             "could not data transfer buffer alloc."));
3885                         return (DDI_FAILURE);
3886                 }
3887 
3888                 /* If IOCTL requires DMA WRITE, do ddi_copyin IOCTL data copy */
3889                 if (ddi_copyin(response_ubuf, (void *) response_dma_obj.buffer,
3890                     response_xferlen, mode)) {
3891                         con_log(CL_ANN, (CE_WARN, "issue_mfi_smp: "
3892                             "copy from user space failed\n"));
3893                         return (1);
3894                 }
3895         }
3896 
3897         smp->cmd             = ksmp->cmd;
3898         smp->cmd_status              = ksmp->cmd_status;
3899         smp->connection_status       = ksmp->connection_status;
3900         smp->sge_count               = ksmp->sge_count;
3901         /* smp->context              = ksmp->context; */
3902         smp->timeout         = ksmp->timeout;
3903         smp->data_xfer_len   = ksmp->data_xfer_len;
3904 
3905         bcopy((void *)&ksmp->sas_addr, (void *)&smp->sas_addr,
3906             sizeof (uint64_t));
3907 
3908         smp->flags           = ksmp->flags & ~MFI_FRAME_SGL64;
3909 
3910         model = ddi_model_convert_from(mode & FMODELS);
3911         if (model == DDI_MODEL_ILP32) {
3912                 con_log(CL_ANN1, (CE_NOTE,
3913                     "handle_drv_ioctl: DDI_MODEL_ILP32"));
3914 
3915                 sge32 = &smp->sgl[0].sge32[0];
3916                 sge32[0].length = response_xferlen;
3917                 sge32[0].phys_addr =
3918                     response_dma_obj.dma_cookie[0].dmac_address;
3919                 sge32[1].length = request_xferlen;
3920                 sge32[1].phys_addr =
3921                     request_dma_obj.dma_cookie[0].dmac_address;
3922         } else {
3923 #ifdef _ILP32
3924                 con_log(CL_ANN1, (CE_NOTE,
3925                     "handle_drv_ioctl: DDI_MODEL_ILP32"));
3926                 sge32 = &smp->sgl[0].sge32[0];
3927                 sge32[0].length  = response_xferlen;
3928                 sge32[0].phys_addr =
3929                     response_dma_obj.dma_cookie[0].dmac_address;
3930                 sge32[1].length = request_xferlen;
3931                 sge32[1].phys_addr =
3932                     request_dma_obj.dma_cookie[0].dmac_address;
3933 #else
3934                 con_log(CL_ANN1, (CE_NOTE,
3935                     "issue_mfi_smp: DDI_MODEL_LP64"));
3936                 sge64 = &smp->sgl[0].sge64[0];
3937                 sge64[0].length = response_xferlen;
3938                 sge64[0].phys_addr =
3939                     response_dma_obj.dma_cookie[0].dmac_address;
3940                 sge64[1].length = request_xferlen;
3941                 sge64[1].phys_addr =
3942                     request_dma_obj.dma_cookie[0].dmac_address;
3943 #endif
3944         }
3945         con_log(CL_ANN1, (CE_NOTE, "issue_mfi_smp: "
3946             "smp->response_xferlen = %d, smp->request_xferlen = %d "
3947             "smp->data_xfer_len = %d", sge32[0].length, sge32[1].length,
3948             smp->data_xfer_len));
3949 
3950         cmd->sync_cmd = MEGASAS_TRUE;
3951         cmd->frame_count = 1;
3952 
3953         if (instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd)) {
3954                 con_log(CL_ANN, (CE_WARN,
3955                     "issue_mfi_smp: fw_ioctl failed\n"));
3956         } else {
3957                 con_log(CL_ANN1, (CE_NOTE,
3958                     "issue_mfi_smp: copy to user space\n"));
3959 
3960                 if (request_xferlen) {
3961                         if (ddi_copyout(request_dma_obj.buffer, request_ubuf,
3962                             request_xferlen, mode)) {
3963                                 con_log(CL_ANN, (CE_WARN, "issue_mfi_smp: "
3964                                     "copy to user space failed\n"));
3965                                 return (1);
3966                         }
3967                 }
3968 
3969                 if (response_xferlen) {
3970                         if (ddi_copyout(response_dma_obj.buffer, response_ubuf,
3971                             response_xferlen, mode)) {
3972                                 con_log(CL_ANN, (CE_WARN, "issue_mfi_smp: "
3973                                     "copy to user space failed\n"));
3974                                 return (1);
3975                         }
3976                 }
3977         }
3978 
3979         ksmp->cmd_status = smp->cmd_status;
3980         con_log(CL_ANN1, (CE_NOTE, "issue_mfi_smp: smp->cmd_status = %d",
3981             smp->cmd_status));
3982 
3983 
3984         if (request_xferlen) {
3985                 /* free kernel buffer */
3986                 if (mega_free_dma_obj(instance, request_dma_obj) != DDI_SUCCESS)
3987                         return (1);
3988         }
3989 
3990         if (response_xferlen) {
3991                 /* free kernel buffer */
3992                 if (mega_free_dma_obj(instance, response_dma_obj) !=
3993                     DDI_SUCCESS)
3994                         return (1);
3995         }
3996 
3997         return (0);
3998 }
3999 
4000 /*
4001  * issue_mfi_stp
4002  */
4003 static int
4004 issue_mfi_stp(struct megasas_instance *instance, struct megasas_ioctl *ioctl,
4005     struct megasas_cmd *cmd, int mode)
4006 {
4007         void            *fis_ubuf;
4008         void            *data_ubuf;
4009         uint32_t        fis_xferlen = 0;
4010         uint32_t        data_xferlen = 0;
4011         uint_t          model;
4012         dma_obj_t                       fis_dma_obj;
4013         dma_obj_t                       data_dma_obj;
4014         struct megasas_stp_frame        *kstp;
4015         struct megasas_stp_frame        *stp;
4016 
4017         stp = &cmd->frame->stp;
4018         kstp = (struct megasas_stp_frame *)&ioctl->frame[0];
4019 
4020         model = ddi_model_convert_from(mode & FMODELS);
4021         if (model == DDI_MODEL_ILP32) {
4022                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_stp: DDI_MODEL_ILP32"));
4023 
4024                 fis_xferlen     = kstp->sgl.sge32[0].length;
4025                 data_xferlen    = kstp->sgl.sge32[1].length;
4026 
4027                 /* SJ! - ubuf needs to be virtual address. */
4028                 fis_ubuf        = (void *)(ulong_t)kstp->sgl.sge32[0].phys_addr;
4029                 data_ubuf       = (void *)(ulong_t)kstp->sgl.sge32[1].phys_addr;
4030         }
4031         else
4032         {
4033 #ifdef _ILP32
4034                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_stp: DDI_MODEL_ILP32"));
4035 
4036                 fis_xferlen     = kstp->sgl.sge32[0].length;
4037                 data_xferlen    = kstp->sgl.sge32[1].length;
4038 
4039                 /* SJ! - ubuf needs to be virtual address. */
4040                 fis_ubuf        = (void *)(ulong_t)kstp->sgl.sge32[0].phys_addr;
4041                 data_ubuf       = (void *)(ulong_t)kstp->sgl.sge32[1].phys_addr;
4042 #else
4043                 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_stp: DDI_MODEL_LP64"));
4044 
4045                 fis_xferlen     = kstp->sgl.sge64[0].length;
4046                 data_xferlen    = kstp->sgl.sge64[1].length;
4047 
4048                 /* SJ! - ubuf needs to be virtual address. */
4049                 fis_ubuf        = (void *)(ulong_t)kstp->sgl.sge64[0].phys_addr;
4050                 data_ubuf       = (void *)(ulong_t)kstp->sgl.sge64[1].phys_addr;
4051 #endif
4052         }
4053 
4054 
4055         if (fis_xferlen) {
4056                 con_log(CL_ANN, (CE_NOTE, "issue_mfi_stp: "
4057                     "fis_ubuf = %p fis_xferlen = %x", fis_ubuf, fis_xferlen));
4058 
4059                 /* means IOCTL requires DMA */
4060                 /* allocate the data transfer buffer */
4061                 fis_dma_obj.size = fis_xferlen;
4062                 fis_dma_obj.dma_attr = megasas_generic_dma_attr;
4063                 fis_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
4064                 fis_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
4065                 fis_dma_obj.dma_attr.dma_attr_sgllen = 1;
4066                 fis_dma_obj.dma_attr.dma_attr_align = 1;
4067 
4068                 /* allocate kernel buffer for DMA */
4069                 if (mega_alloc_dma_obj(instance, &fis_dma_obj) != 1) {
4070                         con_log(CL_ANN, (CE_WARN, "issue_mfi_stp: "
4071                             "could not data transfer buffer alloc."));
4072                         return (DDI_FAILURE);
4073                 }
4074 
4075                 /* If IOCTL requires DMA WRITE, do ddi_copyin IOCTL data copy */
4076                 if (ddi_copyin(fis_ubuf, (void *)fis_dma_obj.buffer,
4077                     fis_xferlen, mode)) {
4078                         con_log(CL_ANN, (CE_WARN, "issue_mfi_stp: "
4079                             "copy from user space failed\n"));
4080                         return (1);
4081                 }
4082         }
4083 
4084         if (data_xferlen) {
4085                 con_log(CL_ANN, (CE_NOTE, "issue_mfi_stp: data_ubuf = %p "
4086                     "data_xferlen = %x", data_ubuf, data_xferlen));
4087 
4088                 /* means IOCTL requires DMA */
4089                 /* allocate the data transfer buffer */
4090                 data_dma_obj.size = data_xferlen;
4091                 data_dma_obj.dma_attr = megasas_generic_dma_attr;
4092                 data_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
4093                 data_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
4094                 data_dma_obj.dma_attr.dma_attr_sgllen = 1;
4095                 data_dma_obj.dma_attr.dma_attr_align = 1;
4096 
4097                 /* allocate kernel buffer for DMA */
4098                 if (mega_alloc_dma_obj(instance, &data_dma_obj) != 1) {
4099                         con_log(CL_ANN, (CE_WARN, "issue_mfi_stp: "
4100                             "could not data transfer buffer alloc."));
4101                         return (DDI_FAILURE);
4102                 }
4103 
4104                 /* If IOCTL requires DMA WRITE, do ddi_copyin IOCTL data copy */
4105                 if (ddi_copyin(data_ubuf, (void *) data_dma_obj.buffer,
4106                     data_xferlen, mode)) {
4107                         con_log(CL_ANN, (CE_WARN, "issue_mfi_stp: "
4108                             "copy from user space failed\n"));
4109                         return (1);
4110                 }
4111         }
4112 
4113         stp->cmd = kstp->cmd;
4114         stp->cmd_status      = kstp->cmd_status;
4115         stp->connection_status = kstp->connection_status;
4116         stp->target_id = kstp->target_id;
4117         stp->sge_count = kstp->sge_count;
4118         /* stp->context = kstp->context; */
4119         stp->timeout = kstp->timeout;
4120         stp->data_xfer_len = kstp->data_xfer_len;
4121 
4122         bcopy((void *)kstp->fis, (void *)stp->fis, 10);
4123 
4124         stp->flags = kstp->flags & ~MFI_FRAME_SGL64;
4125         stp->stp_flags = kstp->stp_flags;
4126         stp->sgl.sge32[0].length = fis_xferlen;
4127         stp->sgl.sge32[0].phys_addr = fis_dma_obj.dma_cookie[0].dmac_address;
4128         stp->sgl.sge32[1].length = data_xferlen;
4129         stp->sgl.sge32[1].phys_addr = data_dma_obj.dma_cookie[0].dmac_address;
4130 
4131         cmd->sync_cmd = MEGASAS_TRUE;
4132         cmd->frame_count = 1;
4133 
4134         if (instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd)) {
4135                 con_log(CL_ANN, (CE_WARN, "issue_mfi_stp: fw_ioctl failed\n"));
4136         } else {
4137 
4138                 if (fis_xferlen) {
4139                         if (ddi_copyout(fis_dma_obj.buffer, fis_ubuf,
4140                             fis_xferlen, mode)) {
4141                                 con_log(CL_ANN, (CE_WARN, "issue_mfi_stp: "
4142                                     "copy to user space failed\n"));
4143                                 return (1);
4144                         }
4145                 }
4146 
4147                 if (data_xferlen) {
4148                         if (ddi_copyout(data_dma_obj.buffer, data_ubuf,
4149                             data_xferlen, mode)) {
4150                                 con_log(CL_ANN, (CE_WARN, "issue_mfi_stp: "
4151                                     "copy to user space failed\n"));
4152                                 return (1);
4153                         }
4154                 }
4155         }
4156 
4157         kstp->cmd_status = stp->cmd_status;
4158 
4159         if (fis_xferlen) {
4160                 /* free kernel buffer */
4161                 if (mega_free_dma_obj(instance, fis_dma_obj) != DDI_SUCCESS)
4162                         return (1);
4163         }
4164 
4165         if (data_xferlen) {
4166                 /* free kernel buffer */
4167                 if (mega_free_dma_obj(instance, data_dma_obj) != DDI_SUCCESS)
4168                         return (1);
4169         }
4170 
4171         return (0);
4172 }
4173 
4174 /*
4175  * fill_up_drv_ver
4176  */
4177 static void
4178 fill_up_drv_ver(struct megasas_drv_ver *dv)
4179 {
4180         (void) memset(dv, 0, sizeof (struct megasas_drv_ver));
4181 
4182         (void) memcpy(dv->signature, "$LSI LOGIC$", strlen("$LSI LOGIC$"));
4183         (void) memcpy(dv->os_name, "Solaris", strlen("Solaris"));
4184         (void) memcpy(dv->drv_name, "megaraid_sas", strlen("megaraid_sas"));
4185         (void) memcpy(dv->drv_ver, MEGASAS_VERSION, strlen(MEGASAS_VERSION));
4186         (void) memcpy(dv->drv_rel_date, MEGASAS_RELDATE,
4187             strlen(MEGASAS_RELDATE));
4188 }
4189 
4190 /*
4191  * handle_drv_ioctl
4192  */
4193 static int
4194 handle_drv_ioctl(struct megasas_instance *instance, struct megasas_ioctl *ioctl,
4195     int mode)
4196 {
4197         int     i;
4198         int     rval = 0;
4199         int     *props = NULL;
4200         void    *ubuf;
4201 
4202         uint8_t         *pci_conf_buf;
4203         uint32_t        xferlen;
4204         uint32_t        num_props;
4205         uint_t          model;
4206         struct megasas_dcmd_frame       *kdcmd;
4207         struct megasas_drv_ver          dv;
4208         struct megasas_pci_information  pi;
4209 
4210         kdcmd = (struct megasas_dcmd_frame *)&ioctl->frame[0];
4211 
4212         model = ddi_model_convert_from(mode & FMODELS);
4213         if (model == DDI_MODEL_ILP32) {
4214                 con_log(CL_ANN1, (CE_NOTE,
4215                     "handle_drv_ioctl: DDI_MODEL_ILP32"));
4216 
4217                 xferlen = kdcmd->sgl.sge32[0].length;
4218 
4219                 /* SJ! - ubuf needs to be virtual address. */
4220                 ubuf = (void *)(ulong_t)kdcmd->sgl.sge32[0].phys_addr;
4221         } else {
4222 #ifdef _ILP32
4223                 con_log(CL_ANN1, (CE_NOTE,
4224                     "handle_drv_ioctl: DDI_MODEL_ILP32"));
4225                 xferlen = kdcmd->sgl.sge32[0].length;
4226                 /* SJ! - ubuf needs to be virtual address. */
4227                 ubuf = (void *)(ulong_t)kdcmd->sgl.sge32[0].phys_addr;
4228 #else
4229                 con_log(CL_ANN1, (CE_NOTE,
4230                     "handle_drv_ioctl: DDI_MODEL_LP64"));
4231                 xferlen = kdcmd->sgl.sge64[0].length;
4232                 /* SJ! - ubuf needs to be virtual address. */
4233                 ubuf = (void *)(ulong_t)kdcmd->sgl.sge64[0].phys_addr;
4234 #endif
4235         }
4236         con_log(CL_ANN1, (CE_NOTE, "handle_drv_ioctl: "
4237             "dataBuf=%p size=%d bytes", ubuf, xferlen));
4238 
4239         switch (kdcmd->opcode) {
4240         case MR_DRIVER_IOCTL_DRIVER_VERSION:
4241                 con_log(CL_ANN1, (CE_NOTE, "handle_drv_ioctl: "
4242                     "MR_DRIVER_IOCTL_DRIVER_VERSION"));
4243 
4244                 fill_up_drv_ver(&dv);
4245 
4246                 if (ddi_copyout(&dv, ubuf, xferlen, mode)) {
4247                         con_log(CL_ANN, (CE_WARN, "handle_drv_ioctl: "
4248                             "MR_DRIVER_IOCTL_DRIVER_VERSION : "
4249                             "copy to user space failed\n"));
4250                         kdcmd->cmd_status = 1;
4251                         rval = 1;
4252                 } else {
4253                         kdcmd->cmd_status = 0;
4254                 }
4255                 break;
4256         case MR_DRIVER_IOCTL_PCI_INFORMATION:
4257                 con_log(CL_ANN1, (CE_NOTE, "handle_drv_ioctl: "
4258                     "MR_DRIVER_IOCTL_PCI_INFORMAITON"));
4259 
4260                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, instance->dip,
4261                     0, "reg", &props, &num_props)) {
4262                         con_log(CL_ANN, (CE_WARN, "handle_drv_ioctl: "
4263                             "MR_DRIVER_IOCTL_PCI_INFORMATION : "
4264                             "ddi_prop_look_int_array failed\n"));
4265                         rval = 1;
4266                 } else {
4267 
4268                         pi.busNumber = (props[0] >> 16) & 0xFF;
4269                         pi.deviceNumber = (props[0] >> 11) & 0x1f;
4270                         pi.functionNumber = (props[0] >> 8) & 0x7;
4271                         ddi_prop_free((void *)props);
4272                 }
4273 
4274                 pci_conf_buf = (uint8_t *)&pi.pciHeaderInfo;
4275 
4276                 for (i = 0; i < (sizeof (struct megasas_pci_information) -
4277                     offsetof(struct megasas_pci_information, pciHeaderInfo));
4278                     i++) {
4279                         pci_conf_buf[i] =
4280                             pci_config_get8(instance->pci_handle, i);
4281                 }
4282 
4283                 if (ddi_copyout(&pi, ubuf, xferlen, mode)) {
4284                         con_log(CL_ANN, (CE_WARN, "handle_drv_ioctl: "
4285                             "MR_DRIVER_IOCTL_PCI_INFORMATION : "
4286                             "copy to user space failed\n"));
4287                         kdcmd->cmd_status = 1;
4288                         rval = 1;
4289                 } else {
4290                         kdcmd->cmd_status = 0;
4291                 }
4292                 break;
4293         default:
4294                 con_log(CL_ANN, (CE_WARN, "handle_drv_ioctl: "
4295                     "invalid driver specific IOCTL opcode = 0x%x",
4296                     kdcmd->opcode));
4297                 kdcmd->cmd_status = 1;
4298                 rval = 1;
4299                 break;
4300         }
4301 
4302         return (rval);
4303 }
4304 
4305 /*
4306  * handle_mfi_ioctl
4307  */
4308 static int
4309 handle_mfi_ioctl(struct megasas_instance *instance, struct megasas_ioctl *ioctl,
4310     int mode)
4311 {
4312         int     rval = 0;
4313 
4314         struct megasas_header   *hdr;
4315         struct megasas_cmd      *cmd;
4316 
4317         cmd = get_mfi_pkt(instance);
4318 
4319         if (!cmd) {
4320                 con_log(CL_ANN, (CE_WARN, "megasas: "
4321                     "failed to get a cmd packet\n"));
4322                 return (1);
4323         }
4324 
4325         hdr = (struct megasas_header *)&ioctl->frame[0];
4326 
4327         switch (hdr->cmd) {
4328         case MFI_CMD_OP_DCMD:
4329                 rval = issue_mfi_dcmd(instance, ioctl, cmd, mode);
4330                 break;
4331         case MFI_CMD_OP_SMP:
4332                 rval = issue_mfi_smp(instance, ioctl, cmd, mode);
4333                 break;
4334         case MFI_CMD_OP_STP:
4335                 rval = issue_mfi_stp(instance, ioctl, cmd, mode);
4336                 break;
4337         case MFI_CMD_OP_LD_SCSI:
4338         case MFI_CMD_OP_PD_SCSI:
4339                 rval = issue_mfi_pthru(instance, ioctl, cmd, mode);
4340                 break;
4341         default:
4342                 con_log(CL_ANN, (CE_WARN, "handle_mfi_ioctl: "
4343                     "invalid mfi ioctl hdr->cmd = %d\n", hdr->cmd));
4344                 rval = 1;
4345                 break;
4346         }
4347 
4348 
4349         return_mfi_pkt(instance, cmd);
4350         if (megasas_common_check(instance, cmd) != DDI_SUCCESS)
4351                 rval = 1;
4352         return (rval);
4353 }
4354 
4355 /*
4356  * AEN
4357  */
4358 static int
4359 handle_mfi_aen(struct megasas_instance *instance, struct megasas_aen *aen)
4360 {
4361         int     rval = 0;
4362 
4363         rval = register_mfi_aen(instance, instance->aen_seq_num,
4364             aen->class_locale_word);
4365 
4366         aen->cmd_status = (uint8_t)rval;
4367 
4368         return (rval);
4369 }
4370 
4371 static int
4372 register_mfi_aen(struct megasas_instance *instance, uint32_t seq_num,
4373     uint32_t class_locale_word)
4374 {
4375         int     ret_val;
4376 
4377         struct megasas_cmd              *cmd;
4378         struct megasas_dcmd_frame       *dcmd;
4379         union megasas_evt_class_locale  curr_aen;
4380         union megasas_evt_class_locale  prev_aen;
4381 
4382         /*
4383          * If there an AEN pending already (aen_cmd), check if the
4384          * class_locale of that pending AEN is inclusive of the new
4385          * AEN request we currently have. If it is, then we don't have
4386          * to do anything. In other words, whichever events the current
4387          * AEN request is subscribing to, have already been subscribed
4388          * to.
4389          *
4390          * If the old_cmd is _not_ inclusive, then we have to abort
4391          * that command, form a class_locale that is superset of both
4392          * old and current and re-issue to the FW
4393          */
4394 
4395         curr_aen.word = class_locale_word;
4396 
4397         if (instance->aen_cmd) {
4398                 prev_aen.word = instance->aen_cmd->frame->dcmd.mbox.w[1];
4399 
4400                 /*
4401                  * A class whose enum value is smaller is inclusive of all
4402                  * higher values. If a PROGRESS (= -1) was previously
4403                  * registered, then a new registration requests for higher
4404                  * classes need not be sent to FW. They are automatically
4405                  * included.
4406                  *
4407                  * Locale numbers don't have such hierarchy. They are bitmap
4408                  * values
4409                  */
4410                 if ((prev_aen.members.class <= curr_aen.members.class) &&
4411                     !((prev_aen.members.locale & curr_aen.members.locale) ^
4412                     curr_aen.members.locale)) {
4413                         /*
4414                          * Previously issued event registration includes
4415                          * current request. Nothing to do.
4416                          */
4417 
4418                         return (0);
4419                 } else {
4420                         curr_aen.members.locale |= prev_aen.members.locale;
4421 
4422                         if (prev_aen.members.class < curr_aen.members.class)
4423                                 curr_aen.members.class = prev_aen.members.class;
4424 
4425                         ret_val = abort_aen_cmd(instance, instance->aen_cmd);
4426 
4427                         if (ret_val) {
4428                                 con_log(CL_ANN, (CE_WARN, "register_mfi_aen: "
4429                                     "failed to abort prevous AEN command\n"));
4430 
4431                                 return (ret_val);
4432                         }
4433                 }
4434         } else {
4435                 curr_aen.word = class_locale_word;
4436         }
4437 
4438         cmd = get_mfi_pkt(instance);
4439 
4440         if (!cmd)
4441                 return (-ENOMEM);
4442 
4443         dcmd = &cmd->frame->dcmd;
4444 
4445         /* for(i = 0; i < DCMD_MBOX_SZ; i++) dcmd->mbox.b[i] = 0; */
4446         (void) memset(dcmd->mbox.b, 0, DCMD_MBOX_SZ);
4447 
4448         (void) memset(instance->mfi_evt_detail_obj.buffer, 0,
4449             sizeof (struct megasas_evt_detail));
4450 
4451         /* Prepare DCMD for aen registration */
4452         dcmd->cmd = MFI_CMD_OP_DCMD;
4453         dcmd->cmd_status = 0x0;
4454         dcmd->sge_count = 1;
4455         dcmd->flags = MFI_FRAME_DIR_READ;
4456         dcmd->timeout = 0;
4457         dcmd->data_xfer_len = sizeof (struct megasas_evt_detail);
4458         dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
4459         dcmd->mbox.w[0] = seq_num;
4460         dcmd->mbox.w[1] = curr_aen.word;
4461         dcmd->sgl.sge32[0].phys_addr =
4462             instance->mfi_evt_detail_obj.dma_cookie[0].dmac_address;
4463         dcmd->sgl.sge32[0].length = sizeof (struct megasas_evt_detail);
4464 
4465         instance->aen_seq_num = seq_num;
4466 
4467         /*
4468          * Store reference to the cmd used to register for AEN. When an
4469          * application wants us to register for AEN, we have to abort this
4470          * cmd and re-register with a new EVENT LOCALE supplied by that app
4471          */
4472         instance->aen_cmd = cmd;
4473 
4474         cmd->frame_count = 1;
4475 
4476         /* Issue the aen registration frame */
4477         /* atomic_add_16 (&instance->fw_outstanding, 1); */
4478         instance->func_ptr->issue_cmd(cmd, instance);
4479 
4480         return (0);
4481 }
4482 
4483 static void
4484 display_scsi_inquiry(caddr_t scsi_inq)
4485 {
4486 #define MAX_SCSI_DEVICE_CODE    14
4487         int             i;
4488         char            inquiry_buf[256] = {0};
4489         int             len;
4490         const char      *const scsi_device_types[] = {
4491                 "Direct-Access    ",
4492                 "Sequential-Access",
4493                 "Printer          ",
4494                 "Processor        ",
4495                 "WORM             ",
4496                 "CD-ROM           ",
4497                 "Scanner          ",
4498                 "Optical Device   ",
4499                 "Medium Changer   ",
4500                 "Communications   ",
4501                 "Unknown          ",
4502                 "Unknown          ",
4503                 "Unknown          ",
4504                 "Enclosure        ",
4505         };
4506 
4507         len = 0;
4508 
4509         len += snprintf(inquiry_buf + len, 265 - len, "  Vendor: ");
4510         for (i = 8; i < 16; i++) {
4511                 len += snprintf(inquiry_buf + len, 265 - len, "%c",
4512                     scsi_inq[i]);
4513         }
4514 
4515         len += snprintf(inquiry_buf + len, 265 - len, "  Model: ");
4516 
4517         for (i = 16; i < 32; i++) {
4518                 len += snprintf(inquiry_buf + len, 265 - len, "%c",
4519                     scsi_inq[i]);
4520         }
4521 
4522         len += snprintf(inquiry_buf + len, 265 - len, "  Rev: ");
4523 
4524         for (i = 32; i < 36; i++) {
4525                 len += snprintf(inquiry_buf + len, 265 - len, "%c",
4526                     scsi_inq[i]);
4527         }
4528 
4529         len += snprintf(inquiry_buf + len, 265 - len, "\n");
4530 
4531 
4532         i = scsi_inq[0] & 0x1f;
4533 
4534 
4535         len += snprintf(inquiry_buf + len, 265 - len, "  Type:   %s ",
4536             i < MAX_SCSI_DEVICE_CODE ? scsi_device_types[i] :
4537             "Unknown          ");
4538 
4539 
4540         len += snprintf(inquiry_buf + len, 265 - len,
4541             "                 ANSI SCSI revision: %02x", scsi_inq[2] & 0x07);
4542 
4543         if ((scsi_inq[2] & 0x07) == 1 && (scsi_inq[3] & 0x0f) == 1) {
4544                 len += snprintf(inquiry_buf + len, 265 - len, " CCS\n");
4545         } else {
4546                 len += snprintf(inquiry_buf + len, 265 - len, "\n");
4547         }
4548 
4549         con_log(CL_ANN1, (CE_CONT, inquiry_buf));
4550 }
4551 
4552 static int
4553 read_fw_status_reg_xscale(struct megasas_instance *instance)
4554 {
4555         return ((int)RD_OB_MSG_0(instance));
4556 }
4557 
4558 static int
4559 read_fw_status_reg_ppc(struct megasas_instance *instance)
4560 {
4561         return ((int)RD_OB_SCRATCH_PAD_0(instance));
4562 }
4563 
4564 static void
4565 issue_cmd_xscale(struct megasas_cmd *cmd, struct megasas_instance *instance)
4566 {
4567         atomic_inc_16(&instance->fw_outstanding);
4568 
4569         /* Issue the command to the FW */
4570         WR_IB_QPORT((host_to_le32(cmd->frame_phys_addr) >> 3) |
4571             (cmd->frame_count - 1), instance);
4572 }
4573 
4574 static void
4575 issue_cmd_ppc(struct megasas_cmd *cmd, struct megasas_instance *instance)
4576 {
4577         atomic_inc_16(&instance->fw_outstanding);
4578 
4579         /* Issue the command to the FW */
4580         WR_IB_QPORT((host_to_le32(cmd->frame_phys_addr)) |
4581             (((cmd->frame_count - 1) << 1) | 1), instance);
4582 }
4583 
4584 /*
4585  * issue_cmd_in_sync_mode
4586  */
4587 static int
4588 issue_cmd_in_sync_mode_xscale(struct megasas_instance *instance,
4589     struct megasas_cmd *cmd)
4590 {
4591         int             i;
4592         uint32_t        msecs = MFI_POLL_TIMEOUT_SECS * (10 * MILLISEC);
4593 
4594         cmd->cmd_status      = ENODATA;
4595 
4596         WR_IB_QPORT((host_to_le32(cmd->frame_phys_addr) >> 3) |
4597             (cmd->frame_count - 1), instance);
4598 
4599         mutex_enter(&instance->int_cmd_mtx);
4600 
4601         for (i = 0; i < msecs && (cmd->cmd_status == ENODATA); i++) {
4602                 cv_wait(&instance->int_cmd_cv, &instance->int_cmd_mtx);
4603         }
4604 
4605         mutex_exit(&instance->int_cmd_mtx);
4606 
4607         if (i < (msecs -1)) {
4608                 return (0);
4609         } else {
4610                 return (1);
4611         }
4612 }
4613 
4614 static int
4615 issue_cmd_in_sync_mode_ppc(struct megasas_instance *instance,
4616     struct megasas_cmd *cmd)
4617 {
4618         int             i;
4619         uint32_t        msecs = MFI_POLL_TIMEOUT_SECS * (10 * MILLISEC);
4620 
4621         con_log(CL_ANN1, (CE_NOTE, "issue_cmd_in_sync_mode_ppc: called\n"));
4622 
4623         cmd->cmd_status      = ENODATA;
4624 
4625         WR_IB_QPORT((host_to_le32(cmd->frame_phys_addr)) |
4626             (((cmd->frame_count - 1) << 1) | 1), instance);
4627 
4628         mutex_enter(&instance->int_cmd_mtx);
4629 
4630         for (i = 0; i < msecs && (cmd->cmd_status == ENODATA); i++) {
4631                 cv_wait(&instance->int_cmd_cv, &instance->int_cmd_mtx);
4632         }
4633 
4634         mutex_exit(&instance->int_cmd_mtx);
4635 
4636         con_log(CL_ANN1, (CE_NOTE, "issue_cmd_in_sync_mode_ppc: done\n"));
4637 
4638         if (i < (msecs -1)) {
4639                 return (0);
4640         } else {
4641                 return (1);
4642         }
4643 }
4644 
4645 /*
4646  * issue_cmd_in_poll_mode
4647  */
4648 static int
4649 issue_cmd_in_poll_mode_xscale(struct megasas_instance *instance,
4650     struct megasas_cmd *cmd)
4651 {
4652         int             i;
4653         uint32_t        msecs = MFI_POLL_TIMEOUT_SECS * MILLISEC;
4654         struct megasas_header *frame_hdr;
4655 
4656         frame_hdr = (struct megasas_header *)cmd->frame;
4657         frame_hdr->cmd_status        = MFI_CMD_STATUS_POLL_MODE;
4658         frame_hdr->flags     |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
4659 
4660         /* issue the frame using inbound queue port */
4661         WR_IB_QPORT((host_to_le32(cmd->frame_phys_addr) >> 3) |
4662             (cmd->frame_count - 1), instance);
4663 
4664         /* wait for cmd_status to change from 0xFF */
4665         for (i = 0; i < msecs && (frame_hdr->cmd_status ==
4666             MFI_CMD_STATUS_POLL_MODE); i++) {
4667                 drv_usecwait(MILLISEC); /* wait for 1000 usecs */
4668         }
4669 
4670         if (frame_hdr->cmd_status == MFI_CMD_STATUS_POLL_MODE) {
4671                 con_log(CL_ANN, (CE_NOTE, "issue_cmd_in_poll_mode: "
4672                     "cmd polling timed out"));
4673                 return (DDI_FAILURE);
4674         }
4675 
4676         return (DDI_SUCCESS);
4677 }
4678 
4679 static int
4680 issue_cmd_in_poll_mode_ppc(struct megasas_instance *instance,
4681     struct megasas_cmd *cmd)
4682 {
4683         int             i;
4684         uint32_t        msecs = MFI_POLL_TIMEOUT_SECS * MILLISEC;
4685         struct megasas_header *frame_hdr;
4686 
4687         con_log(CL_ANN1, (CE_NOTE, "issue_cmd_in_poll_mode_ppc: called\n"));
4688 
4689         frame_hdr = (struct megasas_header *)cmd->frame;
4690         frame_hdr->cmd_status        = MFI_CMD_STATUS_POLL_MODE;
4691         frame_hdr->flags     |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
4692 
4693         /* issue the frame using inbound queue port */
4694         WR_IB_QPORT((host_to_le32(cmd->frame_phys_addr)) |
4695             (((cmd->frame_count - 1) << 1) | 1), instance);
4696 
4697         /* wait for cmd_status to change from 0xFF */
4698         for (i = 0; i < msecs && (frame_hdr->cmd_status ==
4699             MFI_CMD_STATUS_POLL_MODE); i++) {
4700                 drv_usecwait(MILLISEC); /* wait for 1000 usecs */
4701         }
4702 
4703         if (frame_hdr->cmd_status == MFI_CMD_STATUS_POLL_MODE) {
4704                 con_log(CL_ANN, (CE_NOTE, "issue_cmd_in_poll_mode: "
4705                     "cmd polling timed out"));
4706                 return (DDI_FAILURE);
4707         }
4708 
4709         return (DDI_SUCCESS);
4710 }
4711 
4712 static void
4713 enable_intr_xscale(struct megasas_instance *instance)
4714 {
4715         MFI_ENABLE_INTR(instance);
4716 }
4717 
4718 static void
4719 enable_intr_ppc(struct megasas_instance *instance)
4720 {
4721         uint32_t        mask;
4722 
4723         con_log(CL_ANN1, (CE_NOTE, "enable_intr_ppc: called\n"));
4724 
4725         /* WR_OB_DOORBELL_CLEAR(0xFFFFFFFF, instance); */
4726         WR_OB_DOORBELL_CLEAR(OB_DOORBELL_CLEAR_MASK, instance);
4727 
4728         /*
4729          * As 1078DE is same as 1078 chip, the interrupt mask
4730          * remains the same.
4731          */
4732         /* WR_OB_INTR_MASK(~0x80000000, instance); */
4733         WR_OB_INTR_MASK(~(MFI_REPLY_1078_MESSAGE_INTR), instance);
4734 
4735         /* dummy read to force PCI flush */
4736         mask = RD_OB_INTR_MASK(instance);
4737 
4738         con_log(CL_ANN1, (CE_NOTE, "enable_intr_ppc: "
4739             "outbound_intr_mask = 0x%x\n", mask));
4740 }
4741 
4742 static void
4743 disable_intr_xscale(struct megasas_instance *instance)
4744 {
4745         MFI_DISABLE_INTR(instance);
4746 }
4747 
4748 static void
4749 disable_intr_ppc(struct megasas_instance *instance)
4750 {
4751         uint32_t        mask;
4752 
4753         con_log(CL_ANN1, (CE_NOTE, "disable_intr_ppc: called\n"));
4754 
4755         con_log(CL_ANN1, (CE_NOTE, "disable_intr_ppc: before : "
4756             "outbound_intr_mask = 0x%x\n", RD_OB_INTR_MASK(instance)));
4757 
4758         /* WR_OB_INTR_MASK(0xFFFFFFFF, instance); */
4759         WR_OB_INTR_MASK(OB_INTR_MASK, instance);
4760 
4761         con_log(CL_ANN1, (CE_NOTE, "disable_intr_ppc: after : "
4762             "outbound_intr_mask = 0x%x\n", RD_OB_INTR_MASK(instance)));
4763 
4764         /* dummy read to force PCI flush */
4765         mask = RD_OB_INTR_MASK(instance);
4766 #ifdef lint
4767         mask = mask;
4768 #endif
4769 }
4770 
4771 static int
4772 intr_ack_xscale(struct megasas_instance *instance)
4773 {
4774         uint32_t        status;
4775 
4776         /* check if it is our interrupt */
4777         status = RD_OB_INTR_STATUS(instance);
4778 
4779         if (!(status & MFI_OB_INTR_STATUS_MASK)) {
4780                 return (DDI_INTR_UNCLAIMED);
4781         }
4782 
4783         /* clear the interrupt by writing back the same value */
4784         WR_OB_INTR_STATUS(status, instance);
4785 
4786         return (DDI_INTR_CLAIMED);
4787 }
4788 
4789 static int
4790 intr_ack_ppc(struct megasas_instance *instance)
4791 {
4792         uint32_t        status;
4793 
4794         con_log(CL_ANN1, (CE_NOTE, "intr_ack_ppc: called\n"));
4795 
4796         /* check if it is our interrupt */
4797         status = RD_OB_INTR_STATUS(instance);
4798 
4799         con_log(CL_ANN1, (CE_NOTE, "intr_ack_ppc: status = 0x%x\n", status));
4800 
4801         /*
4802          * As 1078DE is same as 1078 chip, the status field
4803          * remains the same.
4804          */
4805         if (!(status & MFI_REPLY_1078_MESSAGE_INTR)) {
4806                 return (DDI_INTR_UNCLAIMED);
4807         }
4808 
4809         /* clear the interrupt by writing back the same value */
4810         WR_OB_DOORBELL_CLEAR(status, instance);
4811 
4812         /* dummy READ */
4813         status = RD_OB_INTR_STATUS(instance);
4814 
4815         con_log(CL_ANN1, (CE_NOTE, "intr_ack_ppc: interrupt cleared\n"));
4816 
4817         return (DDI_INTR_CLAIMED);
4818 }
4819 
4820 static int
4821 megasas_common_check(struct megasas_instance *instance,
4822     struct  megasas_cmd *cmd)
4823 {
4824         int ret = DDI_SUCCESS;
4825 
4826         if (megasas_check_dma_handle(cmd->frame_dma_obj.dma_handle) !=
4827             DDI_SUCCESS) {
4828                 ddi_fm_service_impact(instance->dip, DDI_SERVICE_UNAFFECTED);
4829                 if (cmd->pkt != NULL) {
4830                         cmd->pkt->pkt_reason = CMD_TRAN_ERR;
4831                         cmd->pkt->pkt_statistics = 0;
4832                 }
4833                 ret = DDI_FAILURE;
4834         }
4835         if (megasas_check_dma_handle(instance->mfi_internal_dma_obj.dma_handle)
4836             != DDI_SUCCESS) {
4837                 ddi_fm_service_impact(instance->dip, DDI_SERVICE_UNAFFECTED);
4838                 if (cmd->pkt != NULL) {
4839                         cmd->pkt->pkt_reason = CMD_TRAN_ERR;
4840                         cmd->pkt->pkt_statistics = 0;
4841                 }
4842                 ret = DDI_FAILURE;
4843         }
4844         if (megasas_check_dma_handle(instance->mfi_evt_detail_obj.dma_handle) !=
4845             DDI_SUCCESS) {
4846                 ddi_fm_service_impact(instance->dip, DDI_SERVICE_UNAFFECTED);
4847                 if (cmd->pkt != NULL) {
4848                         cmd->pkt->pkt_reason = CMD_TRAN_ERR;
4849                         cmd->pkt->pkt_statistics = 0;
4850                 }
4851                 ret = DDI_FAILURE;
4852         }
4853         if (megasas_check_acc_handle(instance->regmap_handle) != DDI_SUCCESS) {
4854                 ddi_fm_service_impact(instance->dip, DDI_SERVICE_UNAFFECTED);
4855                 ddi_fm_acc_err_clear(instance->regmap_handle, DDI_FME_VER0);
4856                 if (cmd->pkt != NULL) {
4857                         cmd->pkt->pkt_reason = CMD_TRAN_ERR;
4858                         cmd->pkt->pkt_statistics = 0;
4859                 }
4860                 ret = DDI_FAILURE;
4861         }
4862 
4863         return (ret);
4864 }
4865 
4866 /*ARGSUSED*/
4867 static int
4868 megasas_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
4869 {
4870         /*
4871          * as the driver can always deal with an error in any dma or
4872          * access handle, we can just return the fme_status value.
4873          */
4874         pci_ereport_post(dip, err, NULL);
4875         return (err->fme_status);
4876 }
4877 
4878 static void
4879 megasas_fm_init(struct megasas_instance *instance)
4880 {
4881         /* Need to change iblock to priority for new MSI intr */
4882         ddi_iblock_cookie_t fm_ibc;
4883 
4884         /* Only register with IO Fault Services if we have some capability */
4885         if (instance->fm_capabilities) {
4886                 /* Adjust access and dma attributes for FMA */
4887                 endian_attr.devacc_attr_access = DDI_FLAGERR_ACC;
4888                 megasas_generic_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
4889 
4890                 /*
4891                  * Register capabilities with IO Fault Services.
4892                  * fm_capabilities will be updated to indicate
4893                  * capabilities actually supported (not requested.)
4894                  */
4895 
4896                 ddi_fm_init(instance->dip, &instance->fm_capabilities, &fm_ibc);
4897 
4898                 /*
4899                  * Initialize pci ereport capabilities if ereport
4900                  * capable (should always be.)
4901                  */
4902 
4903                 if (DDI_FM_EREPORT_CAP(instance->fm_capabilities) ||
4904                     DDI_FM_ERRCB_CAP(instance->fm_capabilities)) {
4905                         pci_ereport_setup(instance->dip);
4906                 }
4907 
4908                 /*
4909                  * Register error callback if error callback capable.
4910                  */
4911                 if (DDI_FM_ERRCB_CAP(instance->fm_capabilities)) {
4912                         ddi_fm_handler_register(instance->dip,
4913                             megasas_fm_error_cb, (void*) instance);
4914                 }
4915         } else {
4916                 endian_attr.devacc_attr_access = DDI_DEFAULT_ACC;
4917                 megasas_generic_dma_attr.dma_attr_flags = 0;
4918         }
4919 }
4920 
4921 static void
4922 megasas_fm_fini(struct megasas_instance *instance)
4923 {
4924         /* Only unregister FMA capabilities if registered */
4925         if (instance->fm_capabilities) {
4926                 /*
4927                  * Un-register error callback if error callback capable.
4928                  */
4929                 if (DDI_FM_ERRCB_CAP(instance->fm_capabilities)) {
4930                         ddi_fm_handler_unregister(instance->dip);
4931                 }
4932 
4933                 /*
4934                  * Release any resources allocated by pci_ereport_setup()
4935                  */
4936                 if (DDI_FM_EREPORT_CAP(instance->fm_capabilities) ||
4937                     DDI_FM_ERRCB_CAP(instance->fm_capabilities)) {
4938                         pci_ereport_teardown(instance->dip);
4939                 }
4940 
4941                 /* Unregister from IO Fault Services */
4942                 ddi_fm_fini(instance->dip);
4943 
4944                 /* Adjust access and dma attributes for FMA */
4945                 endian_attr.devacc_attr_access = DDI_DEFAULT_ACC;
4946                 megasas_generic_dma_attr.dma_attr_flags = 0;
4947         }
4948 }
4949 
4950 int
4951 megasas_check_acc_handle(ddi_acc_handle_t handle)
4952 {
4953         ddi_fm_error_t de;
4954 
4955         if (handle == NULL) {
4956                 return (DDI_FAILURE);
4957         }
4958 
4959         ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION);
4960 
4961         return (de.fme_status);
4962 }
4963 
4964 int
4965 megasas_check_dma_handle(ddi_dma_handle_t handle)
4966 {
4967         ddi_fm_error_t de;
4968 
4969         if (handle == NULL) {
4970                 return (DDI_FAILURE);
4971         }
4972 
4973         ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION);
4974 
4975         return (de.fme_status);
4976 }
4977 
4978 void
4979 megasas_fm_ereport(struct megasas_instance *instance, char *detail)
4980 {
4981         uint64_t ena;
4982         char buf[FM_MAX_CLASS];
4983 
4984         (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
4985         ena = fm_ena_generate(0, FM_ENA_FMT1);
4986         if (DDI_FM_EREPORT_CAP(instance->fm_capabilities)) {
4987                 ddi_fm_ereport_post(instance->dip, buf, ena, DDI_NOSLEEP,
4988                     FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERSION, NULL);
4989         }
4990 }